定位IAT并输出导入函数名称和对应的函数地址

 1 #include  < stdio.h >
 2 #include  < windows.h >
 3
 4 void  main()
 5 {
 6 // 取得主模块的模块句柄(即进程模块基地址)
 7 HMODULE hMod  =  GetModuleHandle(NULL);
 8
 9 // 把进程基址赋给pDosHeader,即起始基址就是PE的IMAGE_DOS_HEADER
10 IMAGE_DOS_HEADER *  pDosHeader  =  (IMAGE_DOS_HEADER * )hMod;
11
12 // 定位到PE HEADER
13 // 基址hMod加上IMAGE_DOS_HEADER结构的e_lfanew成员到达IMAGE_NT_HEADERS
14 // NT文件头的前4字节是文件签名("PE00" 字符串),然后是20字节的IMAGE_FILE_HEADER结构
15 // 即到达IMAGE_OPTIONAL_HEADER结构的地址,获取了一个指向IMAGE_OPTIONAL_HEADER结构体的指针
16 IMAGE_OPTIONAL_HEADER  *  pOptHeader  =
17 (IMAGE_OPTIONAL_HEADER  * )((BYTE * )hMod  +  pDosHeader -> e_lfanew  +   24 );
18
19 // 定位到导入表
20 // 通过IMAGE_OPTIONAL_HEADER结构中的DataDirectory结构数组中的第二个成员中的
21 // VirturalAddress字段定位到IMAGE_IMPORT_DESCRIPTOR结构的起始地址
22 // 即获得导入表中第一个IMAGE_IMPORT_DESCRIPTOR结构的指针(导入表首地址)
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 // 遍历结构的OriginalFirstThunk字段所指向的IMAGE_IMPORT_BY_NAME结构得到导出函数名
29 // 遍历IMAGE_IMPORT_DESCRIPTOR结构的FirstThunk数组得到每个函数的地址
30
31 // 导出模块的名称
32 char *  pszDllName  =  ( char * )((BYTE * )hMod  + pImportDesc -> Name);
33 printf( " /n模块名称:%s /n " , pszDllName);
34
35 //  一个IMAGE_THUNK_DATA就是一个双字,它指定了一个导入函数
36 IMAGE_THUNK_DATA *  pThunk  =  (IMAGE_THUNK_DATA * )
37 ((BYTE * )hMod  +  pImportDesc -> OriginalFirstThunk);
38 int  n  =   0 ;
39 while (pThunk -> u1.Function)
40 {
41 //  取得函数名称。hint/name表前两个字节是函数的序号,后4个字节是函数名称字符串的地址
42 char *  pszFunName  =  ( char * )
43 ((BYTE * )hMod  +  (DWORD)pThunk -> u1.AddressOfData  +   2 );
44 //  取得函数地址。IAT表就是一个DWORD类型的数组,每个成员记录一个函数的地址
45 PDWORD lpAddr  =  (DWORD * )((BYTE * )hMod  +  pImportDesc -> FirstThunk)  +  n;
46
47 //  打印出函数名称和地址
48 printf( "    从此模块导入的函数:%-25s, " , pszFunName);
49 printf( " 函数地址:%X /n " , lpAddr);
50 n ++ ; pThunk ++ ;
51 }

52
53 pImportDesc ++ ;
54 }

55 MessageBox(NULL, " Test " , " Test " , 0 );
56 }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
获取IAT表中的函数地址可以使用以下步骤: 1. 获取PE文件的基地址 2. 定位到PE文件的导入表(Import Table),获取导入表的 RVA 和 Size 3. 遍历导入表中的每一个导入描述符(Import Descriptor) 4. 对于每一个导入描述符,获取名称表(Name Table)的 RVA 和 Size,以及导入地址表(Import Address Table,也称为IAT)的 RVA 5. 遍历导入地址表中的每一个函数地址,即可获取IAT表中的函数地址。 下面是伪代码实现: ```C++ // 获取PE文件基地址 HMODULE hModule = GetModuleHandle(NULL); // 获取导入表 PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule; PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + pDosHeader->e_lfanew); PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)hModule + pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); DWORD dwImportSize = pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size; // 遍历导入表 while (pImportDesc->Name != 0) { // 获取名称表和IAT表 PIMAGE_THUNK_DATA pNameTable = (PIMAGE_THUNK_DATA)((DWORD)hModule + pImportDesc->OriginalFirstThunk); PIMAGE_THUNK_DATA pIat = (PIMAGE_THUNK_DATA)((DWORD)hModule + pImportDesc->FirstThunk); // 遍历IAT表中的每一个函数地址 while (pNameTable->u1.AddressOfData != 0) { // 获取函数名称 PIMAGE_IMPORT_BY_NAME pImportByName = (PIMAGE_IMPORT_BY_NAME)((DWORD)hModule + pNameTable->u1.AddressOfData); LPCSTR lpFunctionName = (LPCSTR)pImportByName->Name; // 获取函数地址 FARPROC fpFunction = (FARPROC)pIat->u1.Function; // 处理函数地址 // ... // 下一个函数 pNameTable++; pIat++; } // 下一个导入描述符 pImportDesc++; } ``` 注意:在遍历导入表时,需要检查导入描述符的 Name 字段是否为 0,以判断是否到达导入表的末尾。在遍历IAT表时,需要检查名称表中的 AddressOfData 字段是否为 0,以判断是否到达IAT表的末尾。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值