内存映射(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命令完成这一任务,比如说我们想获得加载到内存中libc的system()地址,就执行如下命令:
类似dm.命令,使用dmi.可以找到距离当前地址最近的一个符号。
另一个有用的命令用于列出库文件内的节区信息,在下面的例子中我们列出了ld-2.27.so的节区:
最后更新于
这有帮助吗?