定位IAT可根据读取exe的方法分为两类:pe装载器以装载的exe文件/通过内存映射方法读取exe文件。 1.简单方法: 直接通过以运行的exe文件来定位IAT #include <stdio.h> #include <windows.h> void main() { HMODULE hMod = ::GetModuleHandle(NULL); //已运行的exe文件在内存中的基地址 为一般0x400000h //,也就是通常所说的IMAGEBASE IMAGE_DOS_HEADER* pDosHeader = (IMAGE_DOS_HEADER*)hMod; IMAGE_OPTIONAL_HEADER * pOptHeader = (IMAGE_OPTIONAL_HEADER *)((BYTE*)hMod + pDosHeader->e_lfanew + 24); IMAGE_IMPORT_DESCRIPTOR* pImportDesc = (IMAGE_IMPORT_DESCRIPTOR*) ((BYTE*)hMod + pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress/*RVA值*/); while(pImportDesc->FirstThunk) { char* pszDllName = (char*)((BYTE*)hMod +pImportDesc->Name/*RVA值*/); printf("\n模块名称:%s \n", pszDllName); // 一个IMAGE_THUNK_DATA就是一个双字,它指定了一个导入函数 IMAGE_THUNK_DATA* pThunk = (IMAGE_THUNK_DATA*) ((BYTE*)hMod + pImportDesc->OriginalFirstThunk); int n = 0; while(pThunk->u1.Function) { // 取得函数名称。hint/name表前两个字节是函数的序号,后4个字节是函数名称字符串的地址 char* pszFunName = (char*) ((BYTE*)hMod + (DWORD)pThunk->u1.AddressOfData + 2); // 取得函数地址。IAT表就是一个DWORD类型的数组,每个成员记录一个函数的地址 PDWORD lpAddr = (DWORD*)((BYTE*)hMod + pImportDesc->FirstThunk) + n;//RVA+ImageBase // 打印出函数名称和地址 printf(" 从此模块导入的函数:%-25s,", pszFunName); printf("函数地址:%X \n", lpAddr); n++; pThunk++; //指向下一个FirstThunk结构 } pImportDesc++;//下一个导入表descriptor,也就是在本进程载入的下一个dll文件中查找 } } 2.通过内存映射文件读取exe文件来到处IAT 先转载一下别人提供的代码, #include "stdafx.h" #include <stdio.h> #include <windows.h> DWORD RVAToOffset(LPVOID lpBase,DWORD VirtualAddress) { IMAGE_DOS_HEADER *dosHeader; IMAGE_NT_HEADERS *ntHeader; IMAGE_SECTION_HEADER *SectionHeader; int NumOfSections; dosHeader=(IMAGE_DOS_HEADER*)lpBase; ntHeader=(IMAGE_NT_HEADERS*)((BYTE*)lpBase+dosHeader->e_lfanew); NumOfSections=ntHeader->FileHeader.NumberOfSections; for (int i=0;i<NumOfSections;i++) { SectionHeader=(IMAGE_SECTION_HEADER*)((BYTE*)lpBase+dosHeader->e_lfanew+sizeof(IMAGE_NT_HEADERS))+i; if(VirtualAddress>SectionHeader->VirtualAddress&&VirtualAddress<SectionHeader->VirtualAddress+SectionHeader->SizeOfRawData) { DWORD AposRAV=VirtualAddress-SectionHeader->VirtualAddress; DWORD Offset=SectionHeader->PointerToRawData+AposRAV; return Offset; } } return 0; } int main(int argc, char* argv[]) { //打开文件 HANDLE hFile=CreateFile(argv[1],GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); if(hFile==INVALID_HANDLE_VALUE) { printf("CreateFile Failed\n"); return 0; } //创建内存映射文件的内核对象 HANDLE hMap=CreateFileMapping(hFile,NULL,PAGE_READONLY,NULL,NULL,NULL); if(hMap==INVALID_HANDLE_VALUE) { printf("CreateFileMapping Failed\n"); return 0; } //把文件映射入内存 LPVOID lpBase=MapViewOfFile(hMap,FILE_MAP_READ,0,0,0); if(lpBase==NULL) { printf("MapViewOfFile Failed\n"); return 0; } IMAGE_DOS_HEADER *dosHeader; IMAGE_NT_HEADERS *ntHeader; IMAGE_IMPORT_BY_NAME *ImportName; //lpBase由MapViewOfFile函数返回 dosHeader=(IMAGE_DOS_HEADER*)lpBase; //检测是否是有效的PE文件 if (dosHeader->e_magic!=IMAGE_DOS_SIGNATURE) { printf("This is not a windows file\n"); return 0; } //定位到PE header ntHeader=(IMAGE_NT_HEADERS*)((BYTE*)lpBase+dosHeader->e_lfanew); if(ntHeader->Signature!=IMAGE_NT_SIGNATURE) { printf("This is not a win32 file\n"); return 0; } //定位到导入表 IMAGE_IMPORT_DESCRIPTOR *ImportDec=(IMAGE_IMPORT_DESCRIPTOR*)((BYTE*)lpBase+RVAToOffset(lpBase,ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)); while(ImportDec->FirstThunk) { //得到DLL文件名 char *pDllName=(char*)((BYTE*)lpBase+RVAToOffset(lpBase,ImportDec->Name)); printf("\nDLL文件名:%s\n",pDllName); //通过OriginalFirstThunk定位到PIMAGE_THUNK_DATA结构数组 PIMAGE_THUNK_DATA pThunk=(PIMAGE_THUNK_DATA)((BYTE*)lpBase+RVAToOffset(lpBase,ImportDec->OriginalFirstThunk)); while(pThunk->u1.Function) { //判断函数是用函数名导入的还是序号导入的 if(pThunk->u1.Ordinal& IMAGE_ORDINAL_FLAG32) { //输出序号 printf("从此DLL模块导出的函数的序号:%x\n",pThunk->u1.Ordinal&0xFFFF); } else { //得到IMAGE_IMPORT_BY_NAME结构中的函数名 ImportName=(IMAGE_IMPORT_BY_NAME*)((BYTE*)lpBase+RVAToOffset(lpBase,(DWORD)pThunk->u1.AddressOfData)); printf("从此DLL模块导出的函数的函数名:%s\n",ImportName->Name); } pThunk++; } ImportDec++; } UnmapViewOfFile(lpBase); CloseHandle(hMap); CloseHandle(hFile); return 0; }
定位IAT表
最新推荐文章于 2023-04-16 23:05:09 发布