get version from pe file

19 篇文章 0 订阅

// read version information from pe file

#include <iostream>
#include <cstdio>
#include <iomanip>

#include "custom_winnt.h" // refer to part of <winnt.h>

using namespace std;

const char *fnout_ver(const char *buf, int ilayer = 0)
{
	int idistance = 0;
	int i = 0;
	unsigned short *pvalue = NULL;
	//¼ÆËã°æ±¾ÐÅÏ¢¿é´óС
	struct _version_info
	{
		unsigned short wLength;//½á¹¹×ܳ¤¶È
		unsigned short wValueLength;//ÐÅÏ¢³¤¶È
		unsigned short wType;//ÐÅÏ¢ÀàÐÍ(1-×Ö·û´®,0-¶þ½øÖÆ)
		unsigned short szKey[1];//Unicode ×Ö·û´® KEY Óò
	} *head = (_version_info *)buf;

	for(idistance = 0; head->szKey[idistance];idistance++);//skip 'VS_VERSION_INFO'
	idistance = (char*)(head->szKey + idistance + 1) - buf;//distance.
	idistance = (idistance + 3) /4*4;//4 bytes align.
	pvalue = (unsigned short *)(buf + idistance);
	idistance += head->wValueLength * (head->wType ? 2 : 1);// is string or binrary.
	idistance = (idistance + 3) /4*4;//align.
 
	//Êä³ö°æ±¾ÐÅÏ¢¿é
	for(i=0;i<ilayer;i++)
		cout<<"\t";

	if(head->wValueLength == sizeof(VS_FIXEDFILEINFO))// 52
	{
		wcout<<head->szKey<<L" VERSIONINFO"<<endl;
		VS_FIXEDFILEINFO *Info = (VS_FIXEDFILEINFO*)pvalue;
		cout<<" FILEVERSION "
			<<(Info->dwFileVersionMS>>16)<<", "<<(Info->dwFileVersionMS&0xFFFF)<<", "
			<<(Info->dwFileVersionLS>>16)<<", "<<(Info->dwFileVersionLS&0xFFFF)
			<<endl;
		cout<<" PRODUCTVERSION "
			<<(Info->dwProductVersionMS>>16)<<", "<<(Info->dwProductVersionMS&0xFFFF)<<", "
			<<(Info->dwProductVersionLS>>16)<<", "<<(Info->dwProductVersionLS&0xFFFF)
			<<endl;
		cout<<" FILEFLAGSMASK 0x"<<Info->dwFileFlagsMask<<endl;
		cout<<" FILEFLAGS 0x"<<Info->dwFileFlags<<endl;
		cout<<" FILEOS 0x"<<Info->dwFileOS<<endl;
		cout<<" FILETYPE 0x"<<Info->dwFileType<<endl;
		cout<<" FILESUBTYPE 0x"<<Info->dwFileSubtype<<endl;
	}
	else if(idistance < head->wLength)
	{
		if(head->wType)
			wcout<<L"BLOCK \""<<head->szKey<<L"\""<<endl;//unicode string
		else
			wcout<<L"BLOCK \""<<head->szKey<<L"\", 0x"<<std::hex<<pvalue[0]<<L", "<<std::dec<<pvalue[1]<<endl;
	}
	else
	{//if( idestance >= head->wLength )
		if(head->wType)
		{
			wcout<<L"VALUE \""<<head->szKey<<L"\", \"";
			for(i=0;i<(head->wValueLength);i++)
				wprintf(L"%c",pvalue[i]);
			if(head->wValueLength == 0)
				cout<<"\\0\""<<endl;
			else
				cout<<"\""<<endl;
		}
		else
		{
			wprintf(L"VALUE \"%s\", %#x, %d\n",head->szKey,pvalue[0],pvalue[1]);//value
		}
		return buf + head->wLength;
	}
	//µÝ¹éÊä³ö×ÓÐÅÏ¢¿é
	for(i=0;i<ilayer;i++)
		cout<<"\t";
	ilayer++;
	cout<<"BEGIN\n";
	while(idistance < head->wLength)
	{
		idistance = fnout_ver(buf + idistance, ilayer) - buf;
		idistance = (idistance + 3) /4*4;// align.
	}
	ilayer--;
	for(i=0;i<ilayer;i++)
		cout<<"\t";
	cout<<"END\n";
	//
	return buf + head->wLength;
}

bool fnget_ver_from_file(const char *pfile)
{
	unsigned long i = 0;
	unsigned long j = 0;
	IMAGE_DOS_HEADER idh = {0};
	IMAGE_NT_HEADERS inh = {0};
	IMAGE_SECTION_HEADER ish = {0};
	FILE *pf = NULL;
	bool bret = false;
	unsigned long dwrs_rva = 0;//relative virtual address of resource data.
	unsigned long dwrs_addr = 0;//file offset for resource.
	IMAGE_RESOURCE_DIRECTORY rsd[3] = {0};//generally speeking, there are three layers.
	IMAGE_RESOURCE_DIRECTORY_ENTRY rsd_entry[3] = {0};//directory entry.
	IMAGE_RESOURCE_DATA_ENTRY rsdata = {0};//data entry.

	pf = fopen(pfile,"rb");
	if(pf == NULL)
		return false;
	rewind(pf);//goto begin.
	
	//get dos header.///
	fread(&idh,sizeof(IMAGE_DOS_HEADER),1,pf);
	if(idh.e_magic != IMAGE_DOS_SIGNATURE)
	{
		cerr<<"is not a pe app file."<<endl;
		return false;
	}//cout<<std::hex<<std::showbase<<idh.e_magic<<endl;//
	
	//get nt header.
	fseek(pf,idh.e_lfanew,SEEK_SET);
	fread(&inh,sizeof(IMAGE_NT_HEADERS),1,pf);//get nt header.
	
	dwrs_rva = inh.OptionalHeader.DataDirectory[2].VirtualAddress;//rva of resource data.

	for(i =0;i<inh.FileHeader.NumberOfSections;i++)
	{
		fread(&ish,sizeof(IMAGE_SECTION_HEADER),1,pf);//get section header.
		char szsect_name[9] = {0};//8 bit length.
		memcpy(szsect_name,ish.Name,8);// section name.
		//cout<<i<<". section name: "<<szsect_name<<endl;
		if(dwrs_rva >= (ish.VirtualAddress) && //rva for start section.
			dwrs_rva < (ish.VirtualAddress + ish.SizeOfRawData) )//end section.
		{//RVAµ½Îļþʵ¼ÊÆ«ÒƵÄת»»
			dwrs_addr = dwrs_rva - ish.VirtualAddress + ish.PointerToRawData;// [section rva] - [data rva] + [file offset]
			break;
		}
	}
	//cout<<endl<<"offset of resouce data: "<<std::hex<<std::showbase<<dwrs_addr<<endl;

	fseek(pf,dwrs_addr,SEEK_SET);//get resource
	fread(&rsd[0],sizeof(IMAGE_RESOURCE_DIRECTORY),1,pf);

	for(i=0;i< (rsd[0].NumberOfIdEntries + rsd[0].NumberOfNamedEntries);i++)
	{
		unsigned long dwoffset = dwrs_addr + sizeof(IMAGE_RESOURCE_DIRECTORY) + (i * sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY) );
		fseek(pf,dwoffset,SEEK_SET);
		fread(&rsd_entry[0],sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY),1,pf);
		// cout<<std::dec<<i<<". name: "<<rsd_entry[0].Name<<endl;
		if(rsd_entry[0].Name == 16)//verinfo.
		{
			for(j =1;j<3;j++)
			{
				dwoffset = dwrs_addr + rsd_entry[j -1].OffsetToDirectory;
				fseek(pf,dwoffset,SEEK_SET);
				fread(&rsd[j],sizeof(IMAGE_RESOURCE_DIRECTORY),1,pf);
				fread(&rsd_entry[j],sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY),1,pf);
			}
			dwoffset = dwrs_addr + rsd_entry[j -1].OffsetToData;
			fseek(pf,dwoffset,SEEK_SET);
			fread(&rsdata,sizeof(IMAGE_RESOURCE_DATA_ENTRY),1,pf);
			char *pbuffer = new char [rsdata.Size]();
			if(pbuffer == NULL)
			{
				fclose(pf);
				return false;
			}
			dwoffset = rsdata.OffsetToData - ish.VirtualAddress + ish.PointerToRawData;
			fseek(pf,dwoffset,SEEK_SET);
			fread(pbuffer,1,rsdata.Size,pf);
			//cout<<"version offset: "<<dwoffset<<", size: "<<std::dec<<std::noshowbase<<rsdata.Size<<endl<<endl;
			fnout_ver(pbuffer);
			delete [] pbuffer;
		}
	}
	fclose(pf);
	return bret;
}


int main(void)
{
	fnget_ver_from_file("debug\\test.exe");
	return 0;
}

reference links:
PE文件解析-资源中的版本信息结构_zhyulo的博客-CSDN博客_pe文件版本
PE文件解析-文件头与整体介绍_zhyulo的博客-CSDN博客_pe文件头
PE文件解析-资源(Resource)_zhyulo的博客-CSDN博客_pe文件资源解析
 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值