Complete code
#include <stdio.h> #include <windows.h> int main(int argc,char* argv[]){ /* typedef struct _IMAGE_IMPORT_DESCRIPTOR { union{ DWORD Characteristics; DWORD OriginalFirstThunk; }; DWORD TimeDateStamp; DWORD ForwarderChain; DWORD Name; // DLL RVA offset for name DWORD FirstThunk; // IAT RVA offset of real address }IMAGE_IMPORT_DESCRIPTOR; */ /* typedef struct _IMAGE_THUNK_DATA32{ union{ DWORD ForwarderString; DWORD Function; DWORD Ordinal; DWORD AddressOfData; // RVA Point to image import by name }u1; }IMAGE_THUNK_DATA32; */ /* typedef struct _IMAGE_IMPORT_BY_NAME{ WORD Hint; BYTE Name[1]; }IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME; */ HMODULE hmod; PIMAGE_DOS_HEADER pdos; PIMAGE_NT_HEADERS pnt; PIMAGE_OPTIONAL_HEADER popt; PIMAGE_IMPORT_DESCRIPTOR piid; PIMAGE_THUNK_DATA pfuncname_addr,pfunc_addr; hmod = GetModuleHandle(NULL); // HMODULE type cannot be directly involved in the operation. It should be cast to byte stream pdos = (PIMAGE_DOS_HEADER)hmod; pnt = (PIMAGE_NT_HEADERS)((BYTE *)hmod + pdos->e_lfanew); // NT_offset = dos.e_lfanew popt = (PIMAGE_OPTIONAL_HEADER)(&(pnt->OptionalHeader)); piid = (PIMAGE_IMPORT_DESCRIPTOR)((BYTE *)hmod+popt->DataDirectory[1].VirtualAddress); // Base_addr + RVA_addr while(piid->FirstThunk){ pfuncname_addr = (PIMAGE_THUNK_DATA)((BYTE *)hmod + piid->OriginalFirstThunk); pfunc_addr = (PIMAGE_THUNK_DATA)((BYTE *)hmod + piid->FirstThunk); char* pdll_name = (char *)((BYTE *)hmod + piid->Name); printf("DLL:%s\n",pdll_name); printf("|\n"); while(pfuncname_addr->u1.Function){ char* func_name = (char *)((BYTE *)hmod + pfuncname_addr->u1.AddressOfData+2); DWORD lpAddr = pfunc_addr->u1.AddressOfData; printf("Func_Name:%s\t",func_name); // OriginalFirstThunk corresponds to an array of structs, which are the names of each function printf("Addr:0x%04x\n",lpAddr); // First thunk corresponds to an array of structs, which starts with the same as original first thunk, and then fills in the real address of the function pfuncname_addr++; pfunc_addr++; } printf("\n"); piid++; // Each DLL corresponds to an IID item } getchar(); return 0; }
Simple explanation
Get the module handle of this process to locate the memory area of file loading! Then use e﹤ lfanew of DOS header to offset to NT header, and use NT header to find Optional header. The first index entry of Optional DataDirectory corresponds to the first IID entry, and then locate to OriginalFirstThunk and FirstThunk through IID. Cycle to get the name and memory address of each function! And then outer loop every DLL! Finally print out the IAT function name and memory address of all DLLs!
Operation result
Be careful
u1.AddressOfData pointed by OriginalFirstThunk is the structure of Hint/Name
u1.AddressOfData pointed by FirstThunk is now filled with the real address of the function in memory