打印PE输出表的信息

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




原文链接: 打印PE输出表的信息 版权所有,转载时请注明出处,违者必究。
注明出处格式:流沙团 ( http://gyarmy.com/post-305.html )

发表评论

0则评论给“打印PE输出表的信息”