如何从原始内存转储中检索程序集?

逆向工程 部件 记忆 数字取证
2021-06-12 08:01:59

我有一个保存为原始二进制文件的运行内存转储。这不是一个独立的可执行文件——它实际上只是运行内存的快照。

我正在寻找一种工具来帮助我识别这个二进制文件中的汇编指令。有这样的工具吗?

我知道你可以使用 OllyDebug 或 IDAPRO 来分析可执行文件。然而,由于这是一个完整的内存转储,我不清楚这些工具是否仍然适用。对于原始内存转储,没有 IDA 可以开始的明确入口点。

任何建议都会非常有帮助。谢谢!

2个回答

拆卸

您可以在 WinDbg 中的任何内存地址进行反汇编,例如

0:067> db 000007fe`ff4d0000
000007fe`ff4d0000  4d 5a 90 00 03 00 00 00-04 00 00 00 ff ff 00 00  MZ..............
000007fe`ff4d0010  b8 00 00 00 00 00 00 00-40 00 00 00 00 00 00 00  ........@.......
000007fe`ff4d0020  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
000007fe`ff4d0030  00 00 00 00 00 00 00 00-00 00 00 00 e0 00 00 00  ................
000007fe`ff4d0040  0e 1f ba 0e 00 b4 09 cd-21 b8 01 4c cd 21 54 68  ........!..L.!Th
000007fe`ff4d0050  69 73 20 70 72 6f 67 72-61 6d 20 63 61 6e 6e 6f  is program canno
000007fe`ff4d0060  74 20 62 65 20 72 75 6e-20 69 6e 20 44 4f 53 20  t be run in DOS 
000007fe`ff4d0070  6d 6f 64 65 2e 0d 0d 0a-24 00 00 00 00 00 00 00  mode....$.......

0:067> u 000007fe`ff4d0000 L1
advapi32!WmipBuildReceiveNotification <PERF> (advapi32+0x0):
000007fe`ff4d0000 4d5a            pop     r10

但是正如您所看到的,这或多或少是无用的(在我的示例中,对于反汇编MZDLL 标头魔术字节是无用的)。

因此,找到正确的拆卸起点是关键部分。

查找作为 DLL 一部分的代码

代码应该主要在 DLL 或 EXE 中(在 WinDbg 中称为图像或模块)。要在内存转储(内核或用户模式)中找到它们,您可以运行 WinDbg 命令

.imgscan

从 WinDbg 帮助:

.imgscan 命令扫描虚拟内存中的图像头。

.imgscan 命令显示它找到的任何图像标题和标题类型。标头类型包括可移植可执行 (PE) 标头和 Microsoft MS-DOS MZ 标头。

我能够在用户模式下验证这一点,但是使用我目前唯一的 Windows XP 内核模式转储,它不会输出任何内容。

用户模式转储的示例输出:

MZ at 000007fe`ff4d0000, prot 00000004, type 00020000 - size db000
  Name: ADVAPI32.dll

因此,获取 DLL 的所有必要信息都可用。如果我使用了用户模式转储

.writemem <FileName> <Range>

将 DLL 写入磁盘并稍后分析。

<Range>是根据地址和范围语法,例如

.writemem advapi32.dll 000007fe`ff4d0000 Ldb000

这可能不适用于内核模式转储,因为模块的某些部分可能已交换到磁盘,因此内存中的 DLL 不再完整。

这种方法也不会找到即时生成的代码。

寻找潜在的可执行代码

可以执行的代码必须驻留在executable设置标志的内存块中

不幸的是命令

!address -f:<filter>

在 WinDbg 6.2.9200 中已损坏。它应该在用户模式转储中工作并输出可执行的起始和结束地址列表。

目前我只得到

0:067> !address -f:PAGE_EXECUTE

        BaseAddress      EndAddress+1        RegionSize     Type       State                 Protect             Usage
------------------------------------------------------------------------------------------------------------------------

0:067> !address -f:PAGE_EXECUTE_READ
Invalid filter arguments. Type !address -? to get the list of supported parameters
0:067> !address -f:PAGE_EXECUTE_READWRITE
Invalid filter arguments. Type !address -? to get the list of supported parameters
0:067> !address -f:PAGE_EXECUTE_WRITECOPY
Invalid filter arguments. Type !address -? to get the list of supported parameters

虽然我有一个完整的内存转储

0:067> .dumpdebug
...
Flags           40002
                0002 MiniDumpWithFullMemory
                40000 MiniDumpWithTokenInformation

但是你明白了这个想法,也许可以将它应用到其他工具中。

如果您知道处理器类型以及它的小端或大端,您可以搜索函数中使用的常见操作码。

例如在 x86 中,常见的有:

push    ebp
mov     ebp, esp
add     esp ...

它是二进制的 55 8B EC 83 C4,然后在转储中搜索它。

如果您会发现包含高密度操作码的区域,则它可能是代码。