Otworzyłem jeden mój stary projekt od czasu jak podoba Ci się zbadać strukturę katalogów importu i eksportu (IMAGE_DIRECTORY_ENTRY_EXPORT
, IMAGE_DIRECTORY_ENTRY_IMPORT
, IMAGE_DIRECTORY_ENTRY_IAT
i IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
). Mogę w skrócie wyjaśnić część, w której masz problem. Mam na myśli część, w jaki sposób dowiedzieć się wskaźnik do np. IMAGE_EXPORT_DIRECTORY
wewnątrz PE.
Przede wszystkim, bo to jest możliwe użycie operacji odczytu plików/Zapis do analizy pliku PE, ale jest o wiele łatwiejsze w użyciu pliku mapowania jak następuje:
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);
po mamy wskaźnik pSrcFile
które wskazują na plik PE, możemy znaleźć inne ważne miejsca w 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);
Teraz mamy wszystkie potrzebne adresy wirtualne dowolnego katalogu. Na przykład:
pNtHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress
to wirtualny adres katalogu eksportu. Następnie, aby przekonwertować adres wirtualny na wskaźnik pamięci, , powinniśmy znaleźć sekcję PE, która ma ten wirtualny adres wewnątrz.Aby to zrobić, możemy wyliczyć sekcje PE i znaleźć i
tarce lub równa 0
i mniej niż pNtHdr->FileHeader.NumberOfSection
s gdzie
pFirstSectionHeader[i].VirtualAddress <=
pNtHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress
i jednocześnie
pNtHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress
< pFirstSectionHeader[i].VirtualAddress + pFirstSectionHeader[i].Misc.VirtualSize
następnie należy wyszukać dane eksportu w sekcji 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);
Taką samą procedurę należy powtórzyć, aby znaleźć (IMAGE_IMPORT_DESCRIPTOR *)
WH ich odpowiada IMAGE_DIRECTORY_ENTRY_IMPORT
i (IMAGE_BOUND_IMPORT_DESCRIPTOR *)
, co odpowiada IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
w celu zrzucenia informacji o imporcie włącznie z informacją o powiązaniu (jeśli istnieje).
Aby zrzucić dane z IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
(odpowiada (ImgDelayDescr *)
określonym w delayimp.h) należy użyć także informacje z IMAGE_DIRECTORY_ENTRY_IAT
(odpowiada (IMAGE_THUNK_DATA32 *)
).
Aby uzyskać więcej informacji na temat PE polecam http://msdn.microsoft.com/en-us/magazine/cc301808.aspx
Zbiór artykułów wskazał w tym SO odpowiedzi może być pomocne: http://stackoverflow.com/questions/2307754/within-a-dll-how-is-function-table-structured/2307850#2307850 –