内存Dump出PE

Posted 不会写代码的丝丽

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了内存Dump出PE相关的知识,希望对你有一定的参考价值。

前言

我们常常会对内存数据导出从而得到运行时相关数据或者原始程序二进制,比如JAVA堆转储分析内存泄漏,android 从内存导出脱壳后dex或者so。本文记录作者在学习在Windows下dump出原始二进制文件。

PE

PE全称为Portable Executable是Windows下二进制文件格式。微软PE官方解释

大致结构如下所示

你可以大致理解为主要有两个部分组成一个是头部另一个是节区数据.当然头部节区存在8字节的空白区域
您可以看以下更详细图片

其中我们详细看看节区格式:

下图每一个小空格标识一个字节

其中我们介绍若干介绍会在Dump使用的字段:

VirtualSize:标识这个节区别加载到内存后的有效数据大小

VirtualAddress:加载的内存地址,注意这个地址是一个相对基础模块的地址偏移值。

SizeOfRawData:这个节区存储在文件中大小

PointerToRawData存储节区数据在文件中的位置的偏移

简单理解就是,拷贝文件偏移地址PointerToRawData的数据到内存位置为VirtualAddress.拷贝的大小为SizeOfRawData.

举个例子:
下图一个程序文件某个节区信息(蓝色高亮区域)

Name:.text

VirtualSize:0x36

VirtualAddress:0x1F8

SizeOfRawData: 0x38

PointerToRawData: 0x1F8

我们看看位于PointerToRawData0x1F8)位置,大小为SizeOfRawData0x38)的截图(注意我们看看到):

随后我们将这个程序加入内存中的截图:

这个程序模块基础地址为:0x400000h (头文件有描述)
程序一共两个节区 (头文件有描述)

因此我们这个节区在内存的地址为0x400000h+0x1F8h = 0x4001F8h

我们将这个程序载入内存中 跳转到0x4001F8h并高亮0x36个数据(文件中是0x38)

开始dump

有上述知识后我们开始从内存dump一个程序,要求dump这个程序可以直接运行。

我们首先用winhex打开一个程序的主模块

首先无脑拷贝1A0+8字节+28*2=0x56h内存到另一个空白二进制文件中.其中1A0是头部的大小,8字节是空白区域,0x56是两个节区大小综合.

因为这个模块的基础地址为00400000,所以我们拷贝0x00400000h0x4001F7h即可(注意需要减一,因为文件偏移是从0开始的)

因为这个程序有两个节区,所以我们要分析两个节区信息拷贝回另一个文件。(下图高亮区域标识节区大小头部信息可自行查表)

我们这里举例其中一个节区区域拷贝.
下图高亮区域便是一个节区

VirtualSize:0x36
VirtualAddress:0x1F8
SizeOfRawData: 0x38
PointerToRawData: 0x1F8

根据上面的信息我们从 0x400000h+0x1F8h=0x4001F8h 拷贝38字节(SizeOfRawData)到文件偏移为 0x1F8(PointerToRawData)地方.

另一个节区不在演示直接看粘贴结果

我们将上面拷贝的文件的后可以直接运行。

所有的内存dump 都可运行?

答案是否定的

因为你dump的节区数据可能被更改,所以你应该在程序OEP处进行dump。

举个例子:


#include <iostream>
#include<Windows.h>


long *p = nullptr;

int main()

	if (p==nullptr)
	
		p = new long;
	

	int i = 0;

	while (true)
	
		Sleep(100);
		*p = ++i;
	
	

如果你在while(true) 进行dump那么会触发内存非法访问的异常。因为p数据会放在未初始化区域,但是你dump后可能导致把初始化new long也给带出了。

以上是关于内存Dump出PE的主要内容,如果未能解决你的问题,请参考以下文章

LordPE修复从进程dump出来的内存文件

python dump_pe.py

PE中的两种状态

[转载] 从正在运行的Linux进程中dump出内存内容

使用sa-jdi.jar dump 内存中的class

PE文件动态加载执行过程