Я открыл один свой старый проект того времени, поскольку мне нравится, что вы изучали структуру каталогов импорта и экспорта (IMAGE_DIRECTORY_ENTRY_EXPORT
, IMAGE_DIRECTORY_ENTRY_IMPORT
, IMAGE_DIRECTORY_ENTRY_IAT
и IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
). Я могу вкратце объяснить ту часть, где у вас есть проблема. Я имею в виду часть, как найти указатель, например, на IMAGE_EXPORT_DIRECTORY
внутри PE.
Прежде всего, для анализа 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
- это виртуальный адрес каталога экспорта. После этого, чтобы преобразовать виртуальный адрес в указатель памяти, , мы должны выяснить секцию PE, в которой этот виртуальный адрес находится внутри . Для этого мы можем перечислить участки PE и найти i
терку или равную 0
и меньше pNtHdr->FileHeader.NumberOfSection
s, где
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