测试打印PE输出表信息
主要是RVA 和 FOA 之间的转换要注意, 单独写了一个函数进行转换
转换函数
DWORD RVAToFileOffset(LPVOID pFileBuffer,DWORD dwRva) { PIMAGE_DOS_HEADER pDosHeader = NULL; PIMAGE_NT_HEADERS pNTHeader = NULL; PIMAGE_FILE_HEADER pPEHeader = NULL; PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL; PIMAGE_SECTION_HEADER pSectionHeader = NULL; if(!pFileBuffer) { printf("文件读取失败\n"); return NULL; } //Header信息 pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer; pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer+pDosHeader->e_lfanew); pPEHeader = (PIMAGE_FILE_HEADER)(((DWORD)pNTHeader)+4); pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader+IMAGE_SIZEOF_FILE_HEADER); pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader+pPEHeader->SizeOfOptionalHeader); DWORD ImageSize = pOptionHeader->SizeOfImage; int Section_Number = pPEHeader->NumberOfSections; int i=0; for(i=0;i<Section_Number;i++) { printf("VirualSize : %x\n",pSectionHeader->Misc); printf("VirualAddress: %x\n",pSectionHeader->VirtualAddress); DWORD dumpVirualSize = pSectionHeader->Misc.VirtualSize; DWORD dumpVirualAddress = pSectionHeader->VirtualAddress; if(dwRva>=dumpVirualAddress && dwRva <=dumpVirualAddress+dumpVirualSize) { printf("地址在第:%d 节 %s \n",i+1,pSectionHeader->Name); break; } //下一个节表 pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pSectionHeader+40); } //确定是第i+1节 //确定偏移距离 DWORD fileOff = pSectionHeader->PointerToRawData + (dwRva-pSectionHeader->VirtualAddress); return fileOff; }
实际代码
void TestExportDirectory(LPSTR lpszFile) { LPVOID pFileBuffer = NULL; pFileBuffer= ReadPEFile(lpszFile); if(!pFileBuffer) { printf("文件读取失败\n"); return; } PIMAGE_DOS_HEADER pDosHeader = NULL; PIMAGE_NT_HEADERS pNTHeader = NULL; PIMAGE_FILE_HEADER pPEHeader = NULL; PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL; PIMAGE_SECTION_HEADER pSectionHeader = NULL; PIMAGE_DATA_DIRECTORY DataDirectory=NULL; //Header信息 pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer; pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer+pDosHeader->e_lfanew); pPEHeader = (PIMAGE_FILE_HEADER)(((DWORD)pNTHeader)+4); pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader+IMAGE_SIZEOF_FILE_HEADER); pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader+pPEHeader->SizeOfOptionalHeader); //定位Directory_Data; DataDirectory = pOptionHeader->DataDirectory; //导出表 printf("IMAGE_DIRECTORY_ENTRY_EXPORT: Address: %x ,Size: %x \n",DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress, DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size); //DWORD RVAToFileOffset(LPVOID pFileBuffer,DWORD dwRva) DWORD FoA = RVAToFileOffset(pFileBuffer,0x2df10); //printf("%x \n",FoA); DWORD Export_Directory_Address = DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; DWORD Export_Directory_Size = DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size; FoA = RVAToFileOffset(pFileBuffer,Export_Directory_Address); /* typedef struct _IMAGE_EXPORT_DIRECTORY { DWORD Characteristics; DWORD TimeDateStamp; WORD MajorVersion; WORD MinorVersion; DWORD Name; //指向该导出表文件名字符串 DWORD Base; //导出函数起始序号 DWORD NumberOfFunctions; //所有导出函数的个数 DWORD NumberOfNames; //以函数名字导出的函数个数 DWORD AddressOfFunctions; // 导出函数地址表 RVA DWORD AddressOfNames; // 导出函数名称表 RVA DWORD AddressOfNameOrdinals; // 导出函数序号表 RVA } IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY; */ //定位导出表的位置 PIMAGE_EXPORT_DIRECTORY pExDirectory = NULL; pExDirectory = (PIMAGE_EXPORT_DIRECTORY)((DWORD)pFileBuffer + FoA); printf("Characteristics: %x\n",pExDirectory->Characteristics); printf("TimeDateStamp: %x\n",pExDirectory->TimeDateStamp); printf("MajorVersion: %x\n",pExDirectory->MajorVersion); printf("MinorVersion: %x\n",pExDirectory->MinorVersion); printf("Name: %x\n",pExDirectory->Name); printf("Base: %x\n",pExDirectory->Base); printf("NumberOfFunctions: %x\n",pExDirectory->NumberOfFunctions); printf("NumberOfNames: %x\n",pExDirectory->NumberOfNames); printf("AddressOfFunctions: %x\n",pExDirectory->AddressOfFunctions); printf("AddressOfNames: %x\n",pExDirectory->AddressOfNames); printf("AddressOfNameOrdinals: %x\n",pExDirectory->AddressOfNameOrdinals); printf("------------------------\n"); //输出函数地址表信息 //AddressOfFunctions DWORD ExAddressOfFunctions = pExDirectory->AddressOfFunctions; DWORD ExAddressOfFunctionsFoA = RVAToFileOffset(pFileBuffer,ExAddressOfFunctions); DWORD ExNumberOfFunctions = pExDirectory->NumberOfFunctions; PDWORD pExAddressOfFunctions = NULL; pExAddressOfFunctions = (PDWORD)((DWORD)pFileBuffer + ExAddressOfFunctionsFoA); //输出每个函数地址表信息 DWORD k =0; for(k=0;k<ExNumberOfFunctions;k++) { printf("%d : %x \n",k,*pExAddressOfFunctions); pExAddressOfFunctions++; } printf("------------------------\n"); //函数名称表 DWORD ExAddressOfNames = pExDirectory->AddressOfNames; DWORD ExAddressOfNamesFoA = RVAToFileOffset(pFileBuffer,ExAddressOfNames); DWORD ExNumberOfNames = pExDirectory->NumberOfNames; PDWORD pExAddressOfNames = NULL; pExAddressOfNames = (PDWORD)((DWORD)pFileBuffer + ExAddressOfNamesFoA); for(k=0;k<ExNumberOfNames;k++) { printf("%d : %x \n",k,*pExAddressOfNames); //函数名的地址转换为FoA ,输出函数名 PDWORD NameAddress = (PDWORD)RVAToFileOffset(pFileBuffer,*pExAddressOfNames); //输出函数名 printf("%s \n",(char*)((DWORD)pFileBuffer + (DWORD)NameAddress)); pExAddressOfNames++; } //函数序号表 printf("------------------------\n"); DWORD ExAddressOfNameOrdinals = pExDirectory->AddressOfNameOrdinals; DWORD ExAddressOfNameOrdinalsFoA = RVAToFileOffset(pFileBuffer,ExAddressOfNameOrdinals); ExNumberOfNames = pExDirectory->NumberOfNames; PWORD pExAddressOfNameOrdinals = NULL; pExAddressOfNameOrdinals = (PWORD)((DWORD)pFileBuffer + ExAddressOfNameOrdinalsFoA); for(k=0;k<ExNumberOfNames;k++) { printf("%d : %x \n",k,*pExAddressOfNameOrdinals); pExAddressOfNameOrdinals++; } }
我写代码比较随意, 不好看,见谅, 明天要去考试科目一了, 今天早点睡觉!!
其实关键在于 理解PE结构, 然后 会对字节进行读写!!!
0则评论给“打印PE输出表的信息”