尝试编写代码获取PE文件的信息。

首先使用 CreateFile打开一个PE文件并返回一个用于访问该对象的handle

HANDLE CreateFile(
LPCTSTR lpFileName, // pointer to name of the file
DWORD dwDesiredAccess, // access (read-write) mode
DWORD dwShareMode, // share mode
LPSECURITY_ATTRIBUTES lpSecurityAttributes, // pointer to security attributes
DWORD dwCreationDistribution, // how to create
DWORD dwFlagsAndAttributes, // file attributes
HANDLE hTemplateFile // handle to file with attributes to copy
);

然后调用CreateFileMapping函数为该文件创建一个文件映射对象(file-mapping object),此时为文件创建了一个视图,而并未将该视图映射进进程的地址空间,也就是尚未装载进入内存之中的意思吧。

Creating a file-mapping object creates the potential for mapping a view of the file but does not map the view. The MapViewOfFile and MapViewOfFileEx functions map a view of a file into a process's address space.

HANDLE CreateFileMapping(
HANDLE hFile, // handle to file to map
LPSECURITY_ATTRIBUTES lpFileMappingAttributes, // optional security attributes
DWORD flProtect, // protection for mapping object
DWORD dwMaximumSizeHigh, // high-order 32 bits of object size
DWORD dwMaximumSizeLow, // low-order 32 bits of object size
LPCTSTR lpName // name of file-mapping object
);

接着MapViewOfFile函数会将之前创建的视图对象映射进入当前调用父进程的内存地址空间中了,那也就是说此时该PE文件基址将不再会是默认的,与DLL文件被程序调用的载入方式一致。

LPVOID MapViewOfFile(
HANDLE hFileMappingObject, // file-mapping object to map into address space
DWORD dwDesiredAccess, // access mode
DWORD dwFileOffsetHigh, // high-order 32 bits of file offset
DWORD dwFileOffsetLow, // low-order 32 bits of file offset
DWORD dwNumberOfBytesToMap // number of bytes to map
);

MapViewOfFile返回值为LPVOID,为该映射视图对象在内存中的基址,指向PE文件中最开始的IMAGE_DOS_HEADER结构体,做完这些就可以开始对文件的结构进行分析了。

在写代码的时候要注意类型转换,不然运算结果可能出乎意料:)

大多数结构体中的地址成员为RVA,需要转化,我这里主要记录一下遇到的关于RVAToVA的问题。

  1. 转化RVA,可以使用ImageRvaToVa()函数,该函数在"Imagehlp.h"或"Dbghelp.h"中声明:
PVOID IMAGEAPI ImageRvaToVa(
\_In\_ PIMAGE_NT_HEADERS NtHeaders,
\_In\_ PVOID Base,
\_In\_ ULONG Rva,
\_In\_opt\_ OUT PIMAGE_SECTION_HEADER *LastRvaSection
);

在vs中碰到一个问题,编译时可能会出现引用错误之类的问题,这个在#include "imagehlp.h"下面添加#pragma comment(lib, "imagehlp.lib")即可;Dbghelp.h同理。

这里加入#pragma comment 解决问题的原因:出错的地方主要在于链接程序无法解析别引用的外部函数(此时已经编译完成),使用comment使linker根据指定的库名查找该库,从而可以识别调用的函数。

那为什么出现这种情况?谷歌一下,原因在于vs的链接器默认写入了我们常用的一些库,当是一些不常用的库则没有,这个时候链接器只找到声明,倒是没有函数的定义部分,也因此需要我们自己添加。

  1. 由于函数并不复杂,可以尝试自己手动实现一个ImageRvaToVa函数:
INT32 ImageRvaToVa(PIMAGE_NT_HEADERS pNtH, LPVOID ImageBase, DWORD Rva) {

	INT sectionTbNum = pNtH->FileHeader.NumberOfSections;		// 记录节区头的个数,便于遍历
PIMAGE_SECTION_HEADER pCurrentSection = (PIMAGE_SECTION_HEADER)((DWORD)pNtH + (pNtH->FileHeader).SizeOfOptionalHeader + 0x18); // 当前节区头VA
// printf("%x\n", pCurrentSection->VirtualAddress);
// printf("sectionTbNum : %x \npCurrentSection : %x", (DWORD)sectionTbNum, (DWORD)pCurrentSection);/////////////////// for (int i = 0; i < sectionTbNum; i++, pCurrentSection ++) {
// 判定待转化的RVA是否在当前的节区范围内
if (Rva > pCurrentSection->VirtualAddress && Rva <= pCurrentSection->VirtualAddress+pCurrentSection->SizeOfRawData) {
// return: RVA - CurrentSectionRVA + CurrentSectionRAW + ImageBase
return Rva - pCurrentSection->VirtualAddress + pCurrentSection->PointerToRawData + (DWORD)ImageBase;
}
}
return 0;
}

自己尝试写的原因在于刚开始尝试以RVA+ImageBase作为VA的时候一直出错,后面上网找写文章看看,后面又看了一下OD中该可执行文件的导入表的地址计算方式,发现时VA = RVA+ImageBase,然后又看见一个关于ImageRvaToVa函数的汇编代码,之后自己尝试调试之后根据其不复杂的逻辑可以写出代码。

根据这个情况,是不是说明通过函数将PE文件映射进入进程的地址空间的做法并没有如同通常的可执行文件一样根据VA来确定位置,而是带有基址的文件偏移作为地址。

当不使用该文件影响时,要完全关闭这个文件映射对象,需要调用CreateFileMappingCloseHandle函数,调用顺序随意。

初步了解PE分析的更多相关文章

  1. ASLR pe 分析

    ASLR 转:http://www.cnblogs.com/dliv3/p/6411814.html 3ks @author:dlive 微软从windows vista/windows server ...

  2. 基础篇-初步认识PE格式

    1 PE(Portable Executable)格式,是Win32环境可移植可执行文件(如exe.dll.vxd.sys和vdm等)的标准文件格式.PE格式衍生于早期建立在VAX(R)VMS(R)上 ...

  3. PE分析

    1 #include<windows.h> 2 #include<RichEdit.h> 3 #include "resource.h" 4 5 6 7 B ...

  4. 开源安全:PE分析

    https://github.com/JusticeRage/Manalyze.git https://github.com/JusticeRage/Manalyze https://www.free ...

  5. PE文件格式分析

    PE文件格式分析 PE 的意思是 Portable Executable(可移植的执行体).它是 Win32环境自身所带的执行文件格式.它的一些特性继承自Unix的Coff(common object ...

  6. Hybrid APP基础篇(二)->Native、Hybrid、React Native、Web App方案的分析比较

    说明 Native.Hybrid.React.Web App方案的分析比较 目录 前言 参考来源 前置技术要求 楔子 几种APP开发模式 概述 Native App Web App Hybrid Ap ...

  7. 转载:案例用Excel对会员客户交易数据进行RFM分析

    案例:用Excel对会员客户交易数据进行RFM分析                                背景: 一个会员服务的企业,有近1年约1200个会员客户的收银数据.由于公司想针对不同 ...

  8. yolov3源码分析keras(一)数据的处理

    一.前言 本次分析的源码为大佬复现的keras版本,上一波地址:https://github.com/qqwweee/keras-yolo3 初步打算重点分析两部分,第一部分为数据,即分析图像如何做等 ...

  9. 【逆向知识】PE ASLR

    1.知识点 微软从windows vista/windows server 2008(kernel version 6.0)开始采用ASLR技术,主要目的是为了防止缓冲区溢出 ASLR技术会使PE文件 ...

随机推荐

  1. Dynamics 365中自定义工作流活动更新了输入输出参数后获取的方法

    关注本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复245或者20170309可方便获取本文,同时可以在第一间得到我发布的最新的博文信息,follow me!我的网站是 www.luoyong. ...

  2. iOS----------Runtime 获取属性列表 方法列表

    导入 #import <objc/runtime.h> unsigned int count; Method *methods = class_copyMethodList([UIAler ...

  3. Active Directory 域服务安装与测试

    Active Directory 域服务安装与测试 实验原理: 安装域服务并创建用户,把另一个电脑加入域中,然后用域账户登录以及用本地账户登录测试 实验条件:windows server 2008(域 ...

  4. pytest之收集用例规则与运行指定用例

    前言 上篇文章相信大家已经了解了pytest在cmd下结合各种命令行参数如何运行测试用例,并输出我们想要看到的信息.那么今天会讲解一下pytest是如何收集我们写好的用例?我们又有哪些方式来运行单个用 ...

  5. Luogu P5284 [十二省联考2019]字符串问题

    好难写的字符串+数据结构问题,写+调了一下午的说 首先理解题意后我们对问题进行转化,对于每个字符串我们用一个点来代表它们,其中\(A\)类串的点权为它们的长度,\(B\)类串的权值为\(0\) 这样我 ...

  6. 微信小程序小结

    前几日抽空看了下小程序,发现挺好玩的,mvvm的结构,语法比vue要简单,内置了一系列的组件,很方便.然后开发者工具直接上传代码,提交审核,然后发布,感觉挺好.虽然不打算做个工具类的,但是做个介绍类小 ...

  7. Ubuntu 18.04.1 LTS + kolla-ansible 部署 openstack Rocky all-in-one 环境

    1. kolla 项目介绍 简介 kolla 的使命是为 openstack 云平台提供生产级别的.开箱即用的自动化部署能力. kolla 要实现 openetack 部署分为两步,第一步是制作 do ...

  8. centos6.7 配置Elasticsearch

    Elasticsearch(以下简称ES),是一款开源的全文搜索引擎,获得了广泛的应用.这篇博客将介绍在centos6.7上如何配置ES. 一.安装JAVA环境 centos默认安装了JAVA环境,首 ...

  9. springboot~thymeleaf页面布局的步骤

    参考:https://ultraq.github.io/thymeleaf-layout-dialect/Installation.html 依赖包 注意里面的thymeleaf-layout-dia ...

  10. docker-swarm建立本地集成开发环境

    在k8s出现之后,docker-swarm使用的人越来越少,但在本地集成开发环境的搭建上,使用它还是比较轻量级的,它比docker-compose最大的好处就是容器之间的共享和服务的治理,你不需要li ...