内存映射

The ability to understand and manipulate the memory maps of a debugged program is important for many different Reverse Engineering tasks. radare2 offers a rich set of commands to handle memory maps in the binary. This includes listing the memory maps of the currently debugged binary, removing memory maps, handling loaded libraries and more.

First, let's see the help message for dm, the command which is responsible for handling memory maps:

[0x55f2104cf620]> dm?
|Usage: dm # Memory maps commands
| dm              List memory maps of target process
| dm addr 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.            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 (see Sl)
| dmm[?][j*]      List modules (libraries, binaries loaded in memory)
| dmi [addr|libname] [symname]     List symbols of target lib
| dmi* [addr|libname] [symname]    List symbols of target lib in radare commands
| dmp[?] <address> <size> <perms>  Change page at <address> with <size>, protection <perms> (rwx)
| 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

In this chapter, we'll go over some of the most useful subcommands of dm using simple examples. For the following examples, we'll use a simple helloworld program for Linux but it'll be the same for every binary.

First things first - open a program in debugging mode:

Note that we passed "helloworld" to radare2 without "./". radare2 will try to find this program in the current directory and then in $PATH, even if no "./" is passed. This is contradictory with UNIX systems, but makes the behaviour consistent for windows users

Let's use dm to print the memory maps of the binary we've just opened:

For those of you who prefer a more visual way, you can use dm= to see the memory maps using an ASCII-art bars. This will be handy when you want to see how these maps are located in the memory.

If you want to know the memory-map you are currently in, use dm.:

Using dmm we can "List modules (libraries, binaries loaded in memory)", this is quite a handy command to see which modules were loaded.

Note that the output of dm subcommands, and dmm specifically, might be different in various systems and different binaries.

We can see that along with our helloworld binary itself, another library was loaded which is ld-2.27.so. We don't see libc yet and this is because radare2 breaks before libc is loaded to memory. Let's use dcu (debug continue until) to execute our program until the entry point of the program, which radare flags as entry0.

Now we can see that libc-2.27.so was loaded as well, great!

Speaking of libc, a popular task for binary exploitation is to find the address of a specific symbol in a library. With this information in hand, you can build, for example, an exploit which uses ROP. This can be achieved using the dmi command. So if we want, for example, to find the address of system() in the loaded libc, we can simply execute the following command:

Similar to the dm. command, with dmi. you can see the closest symbol to the current address.

Another useful command is to list the sections of a specific library. In the following example we'll list the sections of ld-2.27.so:

最后更新于

这有帮助吗?