内存映射(Memory Maps)

对于诸多不同的逆向工程任务而言,很重要的一个能力是理解和操纵已调试程序的内存映射。Radare2提供了一组丰富的命令来处理二进制文件中的内存映射。包括列出当前调试的二进制文件的内存映射,删除内存映射,处理已加载的库等。

首先让我们看看dm的帮助信息,该命令用于处理内存映射:

[0x55f2104cf620]> dm?
Usage: dm   # Memory maps commands
| dm                               List memory maps of target process
| dm address size                  Allocate <size> bytes at <address> (anywhere if address is -1) in child process
| dm=                              List memory maps of target process (ascii-art bars)
| dm.                              Show map name of current address
| dm*                              List memmaps in radare commands
| dm- address                      Deallocate memory map of <address>
| dmd[a] [file]                    Dump current (all) debug map region to a file (from-to.dmp) (see Sd)
| dmh[?]                           Show map of heap
| dmi [addr|libname] [symname]     List symbols of target lib
| dmi* [addr|libname] [symname]    List symbols of target lib in radare commands
| dmi.                             List closest symbol to the current address
| dmiv                             Show address of given symbol for given lib
| dmj                              List memmaps in JSON format
| dml <file>                       Load contents of file into the current map region
| dmm[?][j*]                       List modules (libraries, binaries loaded in memory)
| dmp[?] <address> <size> <perms>  Change page at <address> with <size>, protection <perms> (perm)
| dms[?] <id> <mapaddr>            Take memory snapshot
| dms- <id> <mapaddr>              Restore memory snapshot
| dmS [addr|libname] [sectname]    List sections of target lib
| dmS* [addr|libname] [sectname]   List sections of target lib in radare commands
| dmL address size                 Allocate <size> bytes at <address> and promote to huge page

在本章节中,我们会通过一些简单的例子介绍dm中最有用的一些子命令。下面我们将用一个简单helloworld程序进行演示,不过其中的操作都可以推广到其他二进制文件上。

首先,以debug模式打开程序:

注意我们使用了一个不带"./"的"helloworld"作为radare2的参数,radare2在未指定"./"的情况下会首先在当前目录中搜索该文件,然后才搜索$PATH中的路径。这个行为与UNIX系统的默认行为相冲突,但是对于windows用户来说该行为与系统是一致的。

让我们用dm输出刚打开的程序的内存映射:

对于更喜欢以图形展现结果的用户,可以用dm=以ASCII风格的条柱图展示内存映射。这个特性在想查看内存映射的分布时也很方便。

如果想查看当前在内存映射中的何处可以用dm.:

使用dmm可以“列出modules(已加载到内存中的库,二进制文件)”,这也是一个很方便的命令,可以查看哪些模块被加载了。

要说明的是dm子命令的输出以及dmm命令在不同系统上以及不同二进制文件中输出结果可能不同。

可以看到,同helloworld程序一起被加载的还有ld-2.27.so。我们在里面没有找到libc,这是因为radare2在libc加载前即中断了运行过程。使用dcu命令(debug continue until)让程序执行到入口点(radare将入口点标记为entry0)。

现在可以看到libc-2.27.so被一起加载了,好耶!

再谈谈libc,二进制exploit中的一个常见工作就是找到库中一个特定符号的地址。只要有了这一信息,可以构筑比如说一个基于ROP的攻击。可以用dmi命令完成这一任务,比如说我们想获得加载到内存中libcsystem()地址,就执行如下命令:

类似dm.命令,使用dmi.可以找到距离当前地址最近的一个符号。

另一个有用的命令用于列出库文件内的节区信息,在下面的例子中我们列出了ld-2.27.so的节区:

最后更新于

这有帮助吗?