尝试编写代码获取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. 虹软人脸识别ArcFace2.0 Android SDK使用教程

    一.获取SDK 1.进入ArcFace2.0的申请地址 https://ai.arcsoft.com.cn/product/arcface.html 2.填写信息申请并提交 申请通过后即可下载SDK, ...

  2. Git 学习总结

    概况 CVS 及 SVN 都是集中式的版本控制系统,而 Git 是分布式版本控制系统. 集中式版本控制系统最大的毛病就是必须联网才能工作: 分布式版本控制系统根本没有“中央服务器”,每个人的电脑上都是 ...

  3. Exp4恶意代码分析 20164312 马孝涛

    1.实践目标 1.1是监控你自己系统的运行状态,看有没有可疑的程序在运行.  1.2是分析一个恶意软件,就分析Exp2或Exp3中生成后门软件:分析工具尽量使用原生指令或sysinternals,sy ...

  4. erlang 删除老版本 安装新版本

    [root@izbp1buyhgwtrvlxv3u2gqz ~]# yum remove erlang-erts-R16B-03.18.el7.x86_64Loaded plugins: fastes ...

  5. ASP.NET的版本?

    问题源于这么一本书: <ASP.NET 4 解密(卷1)>,这本书大约是六七年前买的了,根据其名字,它讲述的是ASP.NET 4,那么ASP.NET现在究竟是什么版本?与.NET Fram ...

  6. js设置回车键触发事件

    设置按回车键时触发查询事件: document.onkeydown = function(e){ var ev = document.all ? window.event : e; if(ev.key ...

  7. 【Caffe篇】--Caffe从入门到初始及各层介绍

    一.前述 Caffe,全称Convolutional Architecture for Fast Feature Embedding.是一种常用的深度学习框架,主要应用在视频.图像处理方面的应用上.c ...

  8. redis的string类型!!!!

    value的最大存储量为512m,可储存图像数据或json数据等 1.redis的增加操作 127.0.0.1:6379> set name China     --返回ok,说明增加成功,若n ...

  9. 【反编译系列】四、反编译so文件(IDA_Pro)

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 概述 安卓应用程序的开发语言是java,但是由于java层的代码很容易被反编译,而反编译c/c++程序的难度比较大,所以现在很多安卓应用程 ...

  10. Spring Boot 2.x 系列教程:WebFlux 系列教程大纲(一)

    摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! WebFlux 系列教程大纲 一.背景 大家都知道,Sprin ...