Разрешение RVA для Импорта и Таблиц экспорта в файле PE

Я в настоящее время пишу синтаксический анализатор/загрузчик PE. Я успешно загрузил файл PE в память с помощью стандарта c файл io, получил допустимый DOS и заголовки PE (дополнительный заголовок), а также получив доступ к разделам PE. Моя следующая цель состоит в том, чтобы получить доступ к Таблице экспорта для получения экспортируемых символов. Чтобы сделать это, я использовал RVA, сохраненный в дополнительном массиве словаря данных заголовков в индексе 0 (который я верю точкам к таблице экспорта), и добавил этот адрес к адресу файла PE, загруженного в память программ, затем литую это в действительный заголовок таблицы экспорта. Я поднимаю ПУСТЫЕ адреса и данные, когда я делаю это. вот маленький фрагмент кода;

// RVA from optional headers data dictionaries array cast to Export directory type 
  IMAGE_EXPORT_DIRECTORY* ied(
  (IMAGE_EXPORT_DIRECTORY*)((void*)
  ((unsigned char*)buffer + ioh->DataDirectory[0].VirtualAddress)));

Я должен использовать IO с отображенной памятью, чтобы сделать это правильно? Я вычисляю адрес неправильно? Информация о PE RVA кажется редкой.заранее спасибо.

10
задан Péter Török 4 June 2010 в 15:46
поделиться

2 ответа

Не все образы PE будут иметь таблицу каталогов экспорта. Вам необходимо проверить поле NumberOfRvaAndSizes необязательного заголовка для Windows. Если он меньше или равен IMAGE_DIRECTORY_ENTRY_EXPORT (0), то таблица каталога экспорта отсутствует (т.е. нет ничего действительного, расположенного в ioh-> DataDirectory [IMAGE_DIRECTORY_ENTRY_EXPORT] ).

См. Ответ на этот вопрос в качестве примера.

0
ответ дан 3 December 2019 в 23:48
поделиться

Я открыл один свой старый проект с того времени, как я, как и вы, исследовал структуру каталогов импорта и экспорта (IMAGE_DIRECTORY_ENTRY_EXPORT, IMAGE_DIRECTORY_ENTRY_IMPORT, IMAGE_DIRECTORY_ENTRY_IAT и IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT). Я могу вкратце объяснить ту часть, где у вас возникла проблема. Я имею в виду часть, как узнать указатель на, например, IMAGE_EXPORT_DIRECTORY внутри PE.

Прежде всего, конечно, можно использовать файловые операции Read/Write для анализа PE файла, но гораздо проще использовать файловое отображение, как показано ниже:

hSrcFile = CreateFile (pszSrcFilename, GENERIC_READ, FILE_SHARE_READ,
                       NULL, OPEN_EXISTING, 0, NULL);
hMapSrcFile = CreateFileMapping (hSrcFile, NULL, PAGE_READONLY, 0, 0, NULL);
pSrcFile = (PBYTE) MapViewOfFile (hMapSrcFile, FILE_MAP_READ, 0, 0, 0);

после того, как у нас есть указатель pSrcFile, который указывает на PE файл, мы можем найти другие важные места внутри PE:

pDosHeader = (IMAGE_DOS_HEADER *)pSrcFile;
IMAGE_NT_HEADERS32 *pNtHdr = (IMAGE_NT_HEADERS32 *)
    ((PBYTE)pDosHeader + pDosHeader->e_lfanew);
IMAGE_SECTION_HEADER *pFirstSectionHeader = (IMAGE_SECTION_HEADER *)
    ((PBYTE)&pNtHdr->OptionalHeader +
     pNtHdr->FileHeader.SizeOfOptionalHeader);

Теперь у нас есть все необходимые виртуальные адреса любой директории. Например,

pNtHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress

- это виртуальный адрес директории export. После этого, чтобы преобразовать виртуальный адрес в указатель памяти, мы должны найти секцию PE, внутри которой находится этот виртуальный адрес. Для этого мы можем перечислить секции PE и найти i больше или равно 0 и меньше pNtHdr->FileHeader. NumberOfSections где

pFirstSectionHeader[i].VirtualAddress <= 
pNtHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress

и в то же время

pNtHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress
< pFirstSectionHeader[i].VirtualAddress + pFirstSectionHeader[i].Misc.VirtualSize

то следует искать экспортные данные в секции pFirstSectionHeader[i]:

IMAGE_SECTION_HEADER *pSectionHeader = &pFirstSectionHeader[i];
IMAGE_EXPORT_DIRECTORY *pExportDirectory =
   (IMAGE_EXPORT_DIRECTORY *)((PBYTE)pbyFile + pSectionHeader->PointerToRawData +
    pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress -
    pSectionHeader->VirtualAddress);

Ту же процедуру нужно повторить, чтобы найти (IMAGE_IMPORT_DESCRIPTOR *), который соответствует IMAGE_DIRECTORY_ENTRY_IMPORT и (IMAGE_BOUND_IMPORT_DESCRIPTOR *), который соответствует IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT для дампа информации об импорте, включая информацию о привязке (если она существует).

Для дампа информации из IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT (соответствует (ImgDelayDescr *), определенному в delayimp.h) вы должны использовать также информацию из IMAGE_DIRECTORY_ENTRY_IAT (соответствует (IMAGE_THUNK_DATA32 *)).

Для получения дополнительной информации о PE я рекомендую вам http://msdn.microsoft.com/en-us/magazine/cc301808.aspx

13
ответ дан 3 December 2019 в 23:48
поделиться