PE文件学习系列笔记四-C++实现PE文件的分析
Q Q:408365330 E-Mail:egojit@qq.com
综述:
首先说明我也只是PE文件的初学者,我所写的都是自己的学习记录。前3节学习了PE的一些结构,其中包括DOS头和PE头部分。总是这样去学习这些机构和理论的分析我想大家和我一样毫无兴趣,提不起精神。所以我尝试着在自己对PE了解的基础上用C++写一个小程序分析PE结构文件。我所接触的教程都是Win32汇编去实现一些小工具对PE文件进行分析。我只是能看懂汇编,让我去写那没什么劲,所以我还是用C++去实现。我只是对C比较了解,至于面向对象的知识是在学习C#时候接触的。所以这里的案例的C++代码很大的可能还是继承了C的风格。为什么是C++,主要是MFC写界面比Windows API写界面方便多了。当然如果大家有兴趣,可以留言我写一个C#版本的。当然这一节也不可能实现所有的功能,暂时展示一些小功能。废话不多说了,上代码:
C++代码实现:

首先实现这些如图程序的功能,其中包括识别是否是PE文件,其次是给出,PE文件在磁盘中的对齐尺寸和内存中的对齐尺寸,另一个就是实现知道程序的装载入口地址,都是以16进制的方式表现出来的。
//选择文件按钮
void CPEinfoDlg::OnBnClickedBtnSelectfile()
{
CFileDialog dilog(TRUE);
dilog.m_ofn.lpstrTitle=_T("请选择PE文件");
if(IDOK==dilog.DoModal()){
CString fileName= dilog.GetFileName();
CString filePath= dilog.GetPathName();
//给路径文本框赋值
this->GetDlgItem(IDC_EDIT1)->SetWindowTextW(filePath); HANDLE fileHandle= CreateFile(filePath,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(INVALID_HANDLE_VALUE!=fileHandle){
HANDLE mapHandle= CreateFileMapping(fileHandle,NULL,PAGE_READONLY,0,0,NULL);
if(mapHandle==NULL){
AfxMessageBox(L"打开文件映射对象失败!");
}
else
{
strContet= MapViewOfFile(mapHandle,FILE_MAP_READ,0,0,0);
LPBYTE lpBaseAddress = (LPBYTE)strContet; PIMAGE_DOS_HEADER dosHead=(PIMAGE_DOS_HEADER)lpBaseAddress; PIMAGE_NT_HEADERS ntHead=(PIMAGE_NT_HEADERS)(lpBaseAddress+dosHead->e_lfanew); //根据DOS头和PE头判断是否是PE文件
if(dosHead->e_magic==IMAGE_DOS_SIGNATURE&&ntHead->Signature==IMAGE_NT_SIGNATURE){
//AfxMessageBox(L"说明是正常的PE!");
CString show=L"0x";
wchar_t r[10]=L"";
int h=ntHead->OptionalHeader.FileAlignment;
_itow_s(h,r,16);
show+=r;
this->GetDlgItem(IDC_STATIC_FileA)->SetWindowTextW(show); //内存对齐尺寸 int ss= ntHead->OptionalHeader.SectionAlignment;
_itow_s(ss,r,16);
show=L"0x";
show+=r;
this->GetDlgItem(IDC_STATIC_SESSIONSIZE)->SetWindowTextW(show); //入口地址
int ept= ntHead->OptionalHeader.AddressOfEntryPoint; _itow_s(ept,r,16);
show=L"0x";
show+=r;
this->GetDlgItem(IDC_STATIC_BaseEntry)->SetWindowTextW(show); }
else
{
AfxMessageBox(L"请打开PE格式文件!");
} //撤销映射
UnmapViewOfFile(strContet);
//关闭文件映射对象句柄
CloseHandle(mapHandle);
}
//关闭文件对象
CloseHandle(fileHandle);
}
else
{
AfxMessageBox(L"打开文件句柄失败!");
} }
delete dilog;
// TODO: 在此添加控件通知处理程序代码
}
我就主要上主要代码,当然在这里我们最起码得知道MFC框架的简单开发。
这些小功能的原理就是读文件,不过我这里用的读文件的方式是文件映射的方式,直接将文件映射到内存中。
1.首先是打开文件,返回一个文件内核对象(什么是内核对象?这个我就不多做解释了,要想了解请参照《Windows 核心编程》。这绝对是Windows开发的一本葵花宝典),
HANDLE fileHandle= CreateFile(filePath,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
2.然后创建一个文件映射对象
HANDLE mapHandle= CreateFileMapping(fileHandle,NULL,PAGE_READONLY,0,0,NULL);
当然是以读方式打开。
3.然后就是文件内存视图映射
strContet= MapViewOfFile(mapHandle,FILE_MAP_READ,0,0,0);
其中strContet是LPVOID类型,这个指针就指向了PE文件被映射到内存中的起始地址
4.找DOS头和PE头
PIMAGE_DOS_HEADER dosHead=(PIMAGE_DOS_HEADER)lpBaseAddress; PIMAGE_NT_HEADERS ntHead=(PIMAGE_NT_HEADERS)(lpBaseAddress+dosHead->e_lfanew);
PIMAGE_DOS_HEADER 和PIMAGE_NT_HEADERS结构体就是广义上的DOS头和PE头结构。这两个结构体在WinNT.h头文件中能找到。
5.判断是否是PE文件
if(dosHead->e_magic==IMAGE_DOS_SIGNATURE&&ntHead->Signature==IMAGE_NT_SIGNATURE)
就和我们在前面所说的dosHead->e_magic是DOS头的标志,里面是MZ所以DOS头又称作MZ头,ntHead->Signature就是PE头的标志,内容是ASIIC码PE00。我用UE打开:

在WinNT.h头文件中被定义为IMAGE_DOS_SIGNATURE和IMAGE_NT_SIGNATURE,顾名思义,DOS头标志和PE头标志。这样即使你随便将一个文件修改成.exe后缀或者.dll后缀的PE格式文件依然不通过验证。

通过这个动态图片我们很容易看到我想打开一个.txt文本这是不行的。我现在去把他改成exe再打开:

可以看见修改txt后缀为.exe是不行的。
6.显示内存对齐尺寸程序入口地址等信息
int h=ntHead->OptionalHeader.FileAlignment;
_itow_s(h,r,16);
show+=r;
this->GetDlgItem(IDC_STATIC_FileA)->SetWindowTextW(show); //内存对齐尺寸 int ss= ntHead->OptionalHeader.SectionAlignment;
_itow_s(ss,r,16);
show=L"0x";
show+=r;
this->GetDlgItem(IDC_STATIC_SESSIONSIZE)->SetWindowTextW(show); //入口地址
int ept= ntHead->OptionalHeader.AddressOfEntryPoint; _itow_s(ept,r,16);
show=L"0x";
show+=r;
this->GetDlgItem(IDC_STATIC_BaseEntry)->SetWindowTextW(show);
其中没什么复杂度,只是将结构成员数据处理显示出来。这里也验证了。一般PE文件在磁盘中的对齐粒度是200H在内存中的对齐粒度是1000H也就是4K,一分页大小。
这一节就记到这里,后续的功能等我们学习到的时候再去添加。
PE文件学习系列笔记四-C++实现PE文件的分析的更多相关文章
- Html5 学习系列(四)文件操作API
原文:Html5 学习系列(四)文件操作API 引言 在之前我们操作本地文件都是使用flash.silverlight或者第三方的activeX插件等技术,由于使用了这些技术后就很难进行跨平台.或者跨 ...
- 【Silverlight】Bing Maps学习系列(四):使用图钉层(Pushpin layer)及地图图层(MapLayer)(转)
[Silverlight]Bing Maps学习系列(四):使用图钉层(Pushpin layer)及地图图层(MapLayer) 如果我们需要在Bing Maps中加入一个小图钉标记,该如何实现了? ...
- Python学习系列(四)(列表及其函数)
Python学习系列(四)(列表及其函数) Python学习系列(一)(基础入门) Python学习系列(二)(基础知识) Python学习系列(三)(字符串) 一.基本概念 1,列表是什么? ...
- Python学习系列(四)Python 入门语法规则2
Python学习系列(四)Python 入门语法规则2 2017-4-3 09:18:04 编码和解码 Unicode.gbk,utf8之间的关系 2.对于py2.7, 如果utf8>gbk, ...
- 万恶技术系列笔记-jupyter工作路径和源文件打开方式
万恶技术系列笔记-jupyter工作路径和源文件打开方式 脚本文件,ipynb的正确打开姿势: ipynb不能直接打开,需要复制到工作路径.例如 10_monkeys_model_1.ipynb ...
- PE文件学习系列三-PE头详解
合肥程序员群:49313181. 合肥实名程序员群:128131462 (不愿透露姓名和信息者勿加入) Q Q:408365330 E-Mail:egojit@qq.com 最近比较忙 ...
- PE文件学习系列一为什么是PE
合肥程序员群:49313181. 合肥实名程序员群:128131462 (不愿透露姓名和信息者勿加入)Q Q:408365330 E-Mail:egojit@qq.com PE概述: ...
- 分布式缓存技术redis学习系列(四)——redis高级应用(集群搭建、集群分区原理、集群操作)
本文是redis学习系列的第四篇,前面我们学习了redis的数据结构和一些高级特性,点击下面链接可回看 <详细讲解redis数据结构(内存模型)以及常用命令> <redis高级应用( ...
- RabbitMQ学习系列(四): 几种Exchange 模式
上一篇,讲了RabbitMQ的具体用法,可以看看这篇文章:RabbitMQ学习系列(三): C# 如何使用 RabbitMQ.今天说些理论的东西,Exchange 的几种模式. AMQP协议中的核心思 ...
随机推荐
- exp_tools
#pwntools # github https://github.com/Gallopsled/pwntools 在线帮助文档 https://docs.pwntools.com/en/stable ...
- 自己写的java excel导出工具类
最近项目要用到excel导出功能,之前也写过类似的代码.因为这次项目中多次用到excel导出.这次长了记性整理了一下 分享给大伙 欢迎一起讨论 生成excel的主工具类: public class E ...
- Javascript中bind、call、apply函数用法
js 里函数调用有 4 种模式:方法调用.正常函数调用.构造器函数调用.apply/call 调用. 同时,无论哪种函数调用除了你声明时定义的形参外,还会自动添加 2 个形参,分别是 this 和ar ...
- 自己动手写ORM框架
提起ORM框架,大家都很熟悉,网上流行的ORM框架有很多,其中出名的有一些,不出名的更是数不胜数. 下面是自己实现的一个简单的ORM框架,实现了常用的增删查改功能,供大家研究ORM实现原理. 功能描述 ...
- webpack react基础配置一
简单介绍webpack react基本配置,入门型: 环境配置: 依赖nodejs,官网下载最新版的nodejs:nodejs.org/en 安装完nodejs npm便自动集成了,通过npm安装其 ...
- laravel框架总结(十三) -- redis使用
一切的前提都是已经安装好了redis服务器,并且能启动(我只总结了mac的安装方法:传送门) 我自己使用的是mac系统,有个教程可以参考下,传送门: 1.安装PHP PRedis 1>PRedi ...
- selenium定位元素(本内容从https://my.oschina.net/flashsword/blog/147334处转载)
注明:本内容从https://my.oschina.net/flashsword/blog/147334处转载. 在使用selenium webdriver进行元素定位时,通常使用findElemen ...
- GOLANG 常用命令
golang常用命令: 命令 功能 build 编译包和依赖 run 编译并且直接运行 install 编译安装包和依赖 get 下载并安装包和依赖 fmt 调用gofmt格式化源码文件 d ...
- Redis3.20阅读-SDS实现
声明:这是本人参考黄建宏的<redis设计与实现>(源码版本是redis3.0)来学习redis3.20源码的笔记,如果有什么不对的地方,欢迎大家指正,大家一起学习.一起进步,QQ:499 ...
- Freemarker中日期时间格式出错
今天遇到一个奇怪的问题.同事访问我电脑发布的程序页面,freemarker日期格式报错.而其他电脑访问则没有问题. 先贴出错误信息. FreeMarker template error The str ...