?1 #include? < stdio.h >
?2 #include? < windows.h >
?3
?4 void ?main()
?5 {
?6 // 取得主模塊的模塊句柄(即進(jìn)程模塊基地址)
?7 HMODULE?hMod? = ?GetModuleHandle(NULL);
?8
?9 // 把進(jìn)程基址賦給pDosHeader,即起始基址就是PE的IMAGE_DOS_HEADER
10 IMAGE_DOS_HEADER * ?pDosHeader? = ?(IMAGE_DOS_HEADER * )hMod;
11
12 // 定位到PE?HEADER
13 // 基址hMod加上IMAGE_DOS_HEADER結(jié)構(gòu)的e_lfanew成員到達(dá)IMAGE_NT_HEADERS
14 // NT文件頭的前4字節(jié)是文件簽名("PE00"?字符串),然后是20字節(jié)的IMAGE_FILE_HEADER結(jié)構(gòu)
15 // 即到達(dá)IMAGE_OPTIONAL_HEADER結(jié)構(gòu)的地址,獲取了一個(gè)指向IMAGE_OPTIONAL_HEADER結(jié)構(gòu)體的指針
16 IMAGE_OPTIONAL_HEADER? * ?pOptHeader? =
17 (IMAGE_OPTIONAL_HEADER? * )((BYTE * )hMod? + ?pDosHeader -> e_lfanew? + ? 24 );
18
19 // 定位到導(dǎo)入表
20 // 通過IMAGE_OPTIONAL_HEADER結(jié)構(gòu)中的DataDirectory結(jié)構(gòu)數(shù)組中的第二個(gè)成員中的
21 // VirturalAddress字段定位到IMAGE_IMPORT_DESCRIPTOR結(jié)構(gòu)的起始地址
22 // 即獲得導(dǎo)入表中第一個(gè)IMAGE_IMPORT_DESCRIPTOR結(jié)構(gòu)的指針(導(dǎo)入表首地址)
23 IMAGE_IMPORT_DESCRIPTOR * ?pImportDesc? = ?(IMAGE_IMPORT_DESCRIPTOR * )
24 ((BYTE * )hMod? + ?pOptHeader -> DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
25
26 while (pImportDesc -> FirstThunk)
27 {
28 // 遍歷結(jié)構(gòu)的OriginalFirstThunk字段所指向的IMAGE_IMPORT_BY_NAME結(jié)構(gòu)得到導(dǎo)出函數(shù)名
29 // 遍歷IMAGE_IMPORT_DESCRIPTOR結(jié)構(gòu)的FirstThunk數(shù)組得到每個(gè)函數(shù)的地址
30
31 // 導(dǎo)出模塊的名稱
32 char * ?pszDllName? = ?( char * )((BYTE * )hMod? + pImportDesc -> Name);
33 printf( " \n模塊名稱:%s?\n " ,?pszDllName);
34
35 // ?一個(gè)IMAGE_THUNK_DATA就是一個(gè)雙字,它指定了一個(gè)導(dǎo)入函數(shù)
36 IMAGE_THUNK_DATA * ?pThunk? = ?(IMAGE_THUNK_DATA * )
37 ((BYTE * )hMod? + ?pImportDesc -> OriginalFirstThunk);
38 int ?n? = ? 0 ;
39 while (pThunk -> u1.Function)
40 {
41 // ?取得函數(shù)名稱。hint/name表前兩個(gè)字節(jié)是函數(shù)的序號(hào),后4個(gè)字節(jié)是函數(shù)名稱字符串的地址
42 char * ?pszFunName? = ?( char * )
43 ((BYTE * )hMod? + ?(DWORD)pThunk -> u1.AddressOfData? + ? 2 );
44 // ?取得函數(shù)地址。IAT表就是一個(gè)DWORD類型的數(shù)組,每個(gè)成員記錄一個(gè)函數(shù)的地址
45 PDWORD?lpAddr? = ?(DWORD * )((BYTE * )hMod? + ?pImportDesc -> FirstThunk)? + ?n;
46
47 // ?打印出函數(shù)名稱和地址
48 printf( " ???從此模塊導(dǎo)入的函數(shù):%-25s, " ,?pszFunName);
49 printf( " 函數(shù)地址:%X?\n " ,?lpAddr);
50 n ++ ;?pThunk ++ ;
51 }

52
53 pImportDesc ++ ;
54 }

55 MessageBox(NULL, " Test " , " Test " , 0 );
56 }