流沙团
打印PE输出表的信息
2017-11-12 流沙团


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













发表评论:
昵称

邮件地址 (选填)

个人主页 (选填)

内容