测试打印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结构, 然后 会对字节进行读写!!!