Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Ресурсы exe-файла и PE-формат, Проблема с ресурсами 
:(
    Опции темы
Vitam1n
Дата 7.6.2014, 13:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 2
Регистрация: 7.6.2014

Репутация: нет
Всего: нет



Привет всем!
Сейчас изучаю PE-формат, вкуриваю это дело потихоньку. Но вот с ресурсами зашел в тупик. Проблема в следующем: не могу получить указатель на сегмент ресурсов (либо получаю его, но все равно как-то криво). Вот код:

Код

LPBYTE GetFilePointer(LPBYTE pBase, DWORD dwRVA) {
  if (pBase == NULL)
    return NULL;
  // Ищем секцию, содержащий данный RVA.
  IMAGE_SECTION_HEADER* pSectHeader = GetSection(GetHeader(pBase), dwRVA);
  if (pSectHeader == NULL) // Если секция не найдена,
    return pBase + dwRVA; // то RVA равно смещению в файле,
  // иначе вычисляем смещение относительно начала секции в файле.
  return pBase + pSectHeader->PointerToRawData + (dwRVA - pSectHeader->VirtualAddress);
}


IMAGE_RESOURCE_DIRECTORY* pResourceDir = ((IMAGE_RESOURCE_DIRECTORY*)GetFilePointer((LPBYTE)pHeader, dwResourceDirStart));


Вот. Тут уже код с небольшими следами экспериментов, я пробовал разные способы из разных источников.

Далее. Если предположить, что указатель я получил правильно, то все равно какая-то чушь получается. Если верить МСДН и миллиону других источников, то этот указатель либо указывает на потомка типа IMAGE_RESOURCE_DIRECTORY_ENTRY, либо непосредственно на ресурс, но, как правило, нужно пройти пару поддиректорий. ОК:

Код

PIMAGE_RESOURCE_DIRECTORY_ENTRY dd = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)pResourceDir+1;
while(!dd->DataIsDirectory)
{
    dd++;
}
dd = dd->OffsetToDirectory + (PIMAGE_RESOURCE_DIRECTORY_ENTRY)pResourceDir;


Тут тоже код уже со следами экспериментов, я уже начал путаться. В цикле я ищу узел, который указывает на потомка (свойство DataIsDirectory), нахожу, но отладчик опять показывает какую-то чушь. В частности, кол-во ресурсов в приложении определяется суммой значений полей NumberOfNamedEntries и NumberOfIdEntries. Но у меня во время "прогулки" по простому виндовому блокноту сумма значений = 33 тысячи с лишним ресурсов. И, если смотреть под отладчиком, то я ни разу не получу Id ресурса < 19000. А ведь предопределенных ресурсов не так много, и, например, id иконки = 3.

В общем, я окончательно запутался, помогите, пожалуйста, кто может.
Только прошу, не посылайте в гугл, МСДН, в поиск, на сайт журнала "Хакер", к статьям Питрека и Криса Касперски, а также на форумы wasm.ru, exelab.ru и прочие. Я там уже был и читал похожие темы. Везде только теория, во всех книгах и статьях, как правило, разбор секции импорта, а действительно толковых кодов по перебору ресурсов нет. Ну или есть, но на асме, я а я с ним еще не подружился.

Спасибо за внимание.
PM MAIL   Вверх
tzirechnoy
Дата 7.6.2014, 14:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1173
Регистрация: 30.1.2009

Репутация: 2
Всего: 16



Учитывая, что никакого рабочего кода Вы не представили -- мы тожэ можэт только гадать, что Вы написали неправильно.

PS И да, если непонятен формат -- то писать на Си -- довольно сложный метод его для себя усянить. Возьмите HEX-редактор, калькулятор и блокнот для записей.
PM MAIL   Вверх
Vitam1n
Дата 7.6.2014, 19:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 2
Регистрация: 7.6.2014

Репутация: нет
Всего: нет



Сам формат-то я более-менее понял. С точки зрения теории там не так уж все сложно. Гораздо больше меня интересует практическая реализация.

Вот полный код, который я запускаю. Код взят из интернета, мое "творчество" начинается уже на работе с ресурсами.

Код

#include <iostream>
#include <Windows.h>
#include "MyWinNt.h"


using namespace std;

 IMAGE_NT_HEADERS* GetHeader(LPBYTE pBase);
 IMAGE_SECTION_HEADER* GetSection(IMAGE_NT_HEADERS* pHeader, DWORD dwRVA);
 LPBYTE GetFilePointer(LPBYTE pBase, DWORD dwRVA);
 LPBYTE OpenPEFile(LPCTSTR lpszFileName);
 void ClosePEFile(LPBYTE pBase);

int main(int argc, char* argv[])
{
  LPBYTE pBase = OpenPEFile(argv[1]);
  if (pBase == NULL) 
 {
    cout << "File not found!" << endl;
    return 0;
}
  IMAGE_NT_HEADERS* pHeader = GetHeader(pBase);
  if (pHeader == NULL)
  {
    cout << "It is not a PE file!" << endl;
    return -200;
  }
  cout << "Dir\tRVA\tSize\tFilePtr" << endl;
  IMAGE_DATA_DIRECTORY* pDataDir = pHeader->OptionalHeader.DataDirectory;
  for (UINT i = 0; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++, pDataDir++) 
  {
    if (pDataDir->Size != 0) {
      ULONG nFilePtr = (ULONG)(ULONG_PTR)GetFilePointer(pBase, pDataDir->VirtualAddress);
      cout << dec << i << ":\t" << hex << pDataDir->VirtualAddress << '\t'
        << pDataDir->Size << '\t' << nFilePtr << endl;
    }
  }
  ClosePEFile(pBase);
  
  return 0;
}

IMAGE_NT_HEADERS* GetHeader(LPBYTE pBase) {
  // Проверка правильности аргументов.
  if (pBase == NULL)
    return NULL;
  // Получаем указатель на заголовок DOS.
  IMAGE_DOS_HEADER* pDosHeader = (IMAGE_DOS_HEADER*)pBase;
  // Проверяем корректность указателя.
  if (IsBadReadPtr(pDosHeader, sizeof(IMAGE_DOS_HEADER)))
    return NULL;
  // Сначала проверяем сигнатуру DOS.
  if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
    return NULL;
  // Берем указатель на заголовок PE.
  IMAGE_NT_HEADERS* pHeader = (IMAGE_NT_HEADERS*)(pBase + pDosHeader->e_lfanew);
  // Проверяем корректность указателя.
  if (IsBadReadPtr(pHeader, sizeof(IMAGE_NT_HEADERS)))
    return NULL;
  // Наконец проверяем сигнатуру PE.
  if (pHeader->Signature != IMAGE_NT_SIGNATURE)
    return NULL;
  return pHeader;
}

IMAGE_SECTION_HEADER* GetSection(IMAGE_NT_HEADERS* pHeader, DWORD dwRVA) {
  // Проверка правильности аргументов.
  if (pHeader == NULL)
    return NULL;
  // Перебор всех заголовков секций.
  IMAGE_SECTION_HEADER* pSectHeader = IMAGE_FIRST_SECTION(pHeader);
  for (UINT i = 0; i < pHeader->FileHeader.NumberOfSections; i++, pSectHeader++) {
      const char* nn = (const char*)pSectHeader->Name;
      const char* nn2 = (const char*)".rsrc";
      if(strstr(nn, nn2))
      {
 
          cout << "Resource table" << endl;

      
                  DWORD dwResourceDirStart = pSectHeader->VirtualAddress;
          // Получаем указатели на таблицу ресурсов и все связанные с ней таблицы.
          IMAGE_RESOURCE_DIRECTORY* pResourceDir = ((IMAGE_RESOURCE_DIRECTORY*)GetFilePointer((LPBYTE)pHeader, dwResourceDirStart));
          

         
          PIMAGE_RESOURCE_DIRECTORY_ENTRY dd = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)pResourceDir+1;
                  
          while(!dd->DataIsDirectory)
          {
              dd++;
          }

          dd = dd->OffsetToDirectory + (PIMAGE_RESOURCE_DIRECTORY_ENTRY)pResourceDir;


          PIMAGE_RESOURCE_DIRECTORY_ENTRY dd2 = dd + dd->OffsetToData;
          if(dd->NameIsString)
              cout << "dd->Name = " << dd->Name << endl;
          else
              cout << "dd->Id = " << dd->Id << endl;
          
      }
    // Если RVA находится внутри секции, то возвращаем указатель на ее заголовок.
    if (dwRVA >= pSectHeader->VirtualAddress && dwRVA < pSectHeader->VirtualAddress + pSectHeader->Misc.VirtualSize)
      return pSectHeader;
  }
  return NULL; // секция не найдена
}

LPBYTE GetFilePointer(LPBYTE pBase, DWORD dwRVA) {
  // Проверка правильности аргументов.
  if (pBase == NULL)
    return NULL;
  // Ищем секцию, содержащий данный RVA.
  IMAGE_SECTION_HEADER* pSectHeader = GetSection(GetHeader(pBase), dwRVA);
  if (pSectHeader == NULL) // Если секция не найдена,
    return pBase + dwRVA; // то RVA равно смещению в файле,
  // иначе вычисляем смещение относительно начала секции в файле.
  return pBase + pSectHeader->PointerToRawData + (dwRVA - pSectHeader->VirtualAddress);
}


LPBYTE OpenPEFile(LPCTSTR lpszFileName) {
  HANDLE hFile = CreateFile(lpszFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
    OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  if (hFile == INVALID_HANDLE_VALUE)
    return NULL;
  HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
  CloseHandle(hFile);
  LPBYTE pBase = NULL;
  if (hMapping != NULL) {
    pBase = (LPBYTE)MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
    CloseHandle(hMapping);
  }
  return pBase;
}

void ClosePEFile(LPBYTE pBase) {
  if (pBase != NULL)
    UnmapViewOfFile(pBase);
}

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0424 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.