PE文件格式详解(一)

在本文中, 我并不打算大讲特讲PE文件的构成是什么,每个字段是什么意思, 这些资料可以说在网上是浩瀚如海,到处都是的, 用google一搜, 打开一看, 基本讲解的都是大同小异。 由于pe文件的结构比较庞大, 结构中套结构, 有的结构多达30多个字段, 光看这些字段都让人够晕的, 在加上有的字段是一个32位的DWORD值, 而每一位都有其特殊的含义,这样, 光把每个字段的含义看一遍过来, 估计也得2个小时。 而实际上, 这里面很多字段, 我们都不需要去了解, 也不需要去关注, 掌握那些关键字段就行了,所以如果大家有那个字段不懂的,可以上网搜一下。这次讲一下是否PE格式文件的判断。

(这个图我是从鱼C论坛转的)。

首先要明确PE文件格式的特征是什么,这样我们才能根据这个特征来判断是否是PE文件。PE文件的格式如上图所示,那么我们怎么判断呢?PE文件有DOS文件头和PE文件头,在DOS文件头前两个字节是“MZ",PE文件头的前4个字节是“PE”,所以我们可以根据这个特征来进行判断,我们怎么找到“MZ”和“PE”位置呢,PIMAGE_DOS_HEADER的e_magic字段表示“MZ”,PIMAGE_DOS_HEADER的e_lfanew表示PE头相对于文件的偏移。(我用的VS2012编译环境)

代码如下:

/************************************************************************/
/* 
功能:判断是否是PE文件。
参数:指向存放文件数据内存首地址
返回:TRUE ;是PE文件
	  FALSE:不是PE文件
*/
/************************************************************************/
BOOL IsPEFile(LPVOID lpFileBuf)
{
	//获取DOS头并判断"MZ"标志
	PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)lpFileBuf;	
	//e_magic exe标志 "MZ"
	if (IMAGE_DOS_SIGNATURE != pDos->e_magic)
		return FALSE;

	//获取PE头,并判断"PE\0\0"标志
	//e_lfanew PE头相对于文件的偏移地址
	size_t  stPEHeadAddr = (size_t)lpFileBuf + pDos->e_lfanew;
	PIMAGE_NT_HEADERS32 pNT = (PIMAGE_NT_HEADERS32)stPEHeadAddr;
	if (IMAGE_NT_SIGNATURE != pNT->Signature)
	{
		return FALSE;
	}
	return TRUE;
}

int _tmain(int argc, _TCHAR* argv[])
{

	//文件句柄
	HANDLE hFile = INVALID_HANDLE_VALUE;
	//文件路径
	LPCTSTR strInPath = _T("G:\\15pb培训课后作业\\01 VMView\\Debug\\VMView.exe");
	DWORD  dwSize = 0;
	PVOID  lpFillBuf = NULL;

	STARTUPINFO si = {0};
	GetStartupInfo(&si);
	PROCESS_INFORMATION pi = {0};
	if (!CreateProcess(											/* 创建调试线程 */
		strInPath,	//可执行模块路径
		NULL,													//命令行
		NULL,													//安全描述符
		NULL,													//线程属性是否可继承
		FALSE,													//否从调用进程处继承了句柄
		DEBUG_ONLY_THIS_PROCESS | CREATE_NEW_CONSOLE,			//以“只”调试的方式启动
		NULL,													//新进程的环境块
		NULL,													//新进程的当前工作路径(当前目录)
		&si,													//指定进程的主窗口特性
		&pi))													//接收新进程的识别信息
	{
		printf("CreateProcess Failed!\n");
	}

	//获取文件句柄
	if (INVALID_HANDLE_VALUE == (hFile = CreateFile(strInPath,	//文件路径
		GENERIC_READ,											//访问权限
		FILE_SHARE_READ,										//共享模式
		NULL,													//安全描述符
		OPEN_EXISTING,											//创建标志
		FILE_ATTRIBUTE_NORMAL,									//文件标志和属性
		NULL)))													//临时文件句柄
	{
		return 0;
	}
	//获取文件大小
	if (INVALID_FILE_SIZE == (dwSize = GetFileSize(hFile,NULL)))
	{
		CloseHandle(hFile);
		return  0;
	}
	//开辟一块内存用于存放文件数据
	if ( NULL == (lpFillBuf =VirtualAlloc(NULL,dwSize,MEM_COMMIT,PAGE_EXECUTE_READWRITE)))
	{
		CloseHandle(hFile);
		return 0;
	}
	//把文件数据读取到内存中
	DWORD dwRet ;
	if (!ReadFile(hFile,lpFillBuf,dwSize,&dwRet,NULL))
	{
		CloseHandle(hFile);
		VirtualFree(lpFillBuf,0,MEM_RELEASE);
		return 0;
	}

	if (IsPEFile(lpFillBuf))
	{
		MessageBox(NULL,_T("该文件是PE文件"),_T("PE文件格式判断"),MB_OK);
	}
	else
	{
		MessageBox(NULL,_T("该文件不是PE文件"),_T("PE文件格式判断"),MB_OK);
	}
	VirtualFree(lpFillBuf,0,MEM_RELEASE);
	CloseHandle(hFile);
	_tsystem(_T("pause"));
	return 0;
}

通过以上就可以进行判断了。

下面是一个可执行文件的二进制截图,我把IMAGE_DOS_HEADER.e_magic,IMAGE_DOS_HEADER.e_lfanew和IMAGE_NT_HEADER.Signature标记出来了。



  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值