Radare2 在堆栈中查找命令行参数和位置

逆向工程 二元分析 雷达2
2021-06-29 08:26:38

这可能有一个简单的解决方案,但我在任何地方都找不到。

$> ./be1 11 AAAAA

使用gdb, 查找argv[]argc很简单:

(gdb) print argv[0]@argc
$7 = {0xbffff872 "be1", 0xbffff89a "11", 0xbffff89d "AAAAA"}

但是,我们如何使用radare2 做到这一点?

2个回答

radare2 目前不标记 argvargc然而,它的实现不应该是复杂的。

虽然这些参数没有被radare2标记,但我们可以通过检查寄存器很容易地看到它们。让我们一步一步来。

假设我们有以下程序:

$ cat example.c

#include <stdio.h>

int main(int argc, char *argv[]) {

   printf( "argv[1]: %s\n", argv[1]);

   return 0;
}

程序所做的就是打印给它的第一个参数。就那么简单。

让我们编译它gccradare2使用-d标志在调试模式下打开它,并向它传递一个参数:

$ gcc example.c -o example.elf
$ r2 -d example.elf ABCDEFGH
Process with PID 104 started...
= attach 104 104
bin.baddr 0x00400000
Using 0x400000
asm.bits 64
 -- Nothing to see here. Move along.
[0x7f3c8f000c30]> 

让我们使用aa以下命令快速分析程序

[0x7f3c8f000c30]> aa
[x] Analyze all flags starting with sym. and entry0 (aa)

现在,让我们执行程序,直到到达main()我们可以通过在mainusing处设置断点db main并继续执行,直到程序到达using断点来做到这一点dc或者,我们可以简单地使用dcu [addr]-- 一个非常好的命令,它将继续执行直到特定地址。

[0x7f3c8f000c30]> dcu main
Continue until 0x00400526 using 1 bpsize
hit breakpoint at: 400526

radare2 在 处停止了程序的执行main伟大的!让我们继续并打印函数:

[0x00400526]> pdf
            ;-- main:
            ;-- rax:
            ;-- rip:
╭ (fcn) sym.main 51
│   sym.main ();
│           ; var int local_10h @ rbp-0x10
│           ; var int local_4h @ rbp-0x4
│           ; DATA XREF from 0x0040044d (entry0)
│           0x00400526      55             push rbp
│           0x00400527      4889e5         mov rbp, rsp
│           0x0040052a      4883ec10       sub rsp, 0x10
│           0x0040052e      897dfc         mov dword [local_4h], edi
│           0x00400531      488975f0       mov qword [local_10h], rsi
│           0x00400535      488b45f0       mov rax, qword [local_10h]
│           0x00400539      4883c008       add rax, 8
│           0x0040053d      488b00         mov rax, qword [rax]
│           0x00400540      4889c6         mov rsi, rax
│           0x00400543      bfe4054000     mov edi, str.argv_1_:__s    ; 0x4005e4 ; "argv[1]: %s\n"
│           0x00400548      b800000000     mov eax, 0
│           0x0040054d      e8aefeffff     call sym.imp.printf         ; int printf(const char *format)
│           0x00400552      b800000000     mov eax, 0
│           0x00400557      c9             leave
╰           0x00400558      c3             ret

您可能知道,在 GCC 编译的程序中, atmain的入口edi将保持argc并且rsi(堆栈上的指针)将保持argv

我们可以这样打印他们的地址:

[0x00400526]> dr rsi
0x7ffff02302b8
[0x00400526]> dr edi
0x00000002

所以argc( edi)的值0x2是预期的,因为参数是文件名和“ABCDEFGH”。指针argv( rsi)的地址0x7ffff02302b8为了打印* argv( rsi)的内容,我们可以简单地使用以下命令:

[0x00400526]> psb @ [rsi]
0x7ffff02304b7 ./example.elf
0x7ffff02304c4 ABCDEFGH
0x7ffff02304cd SHELL=/bin/bash
0x7ffff02304dd TERM=xterm-256color
0x7ffff02304f1 OLDPWD=<truncated>
0x7ffff023050e USER=beet
0x7ffff0230518 NAME=<truncated>

psb用于p RINT小号trings在当前b锁。由于此时我们知道argc等于 2,因此我们可以忽略输出第二行下方的任何内容。

radare2 还为您提供了一个使用drr. 通过这种方式,您可以轻松查看rsi指向的位置:

[0x00400526]> drr~rsi
   rsi 0x00007ffff1a56ab8  rsi stack R W 0x7ffff1a56cb7 -->  stack R W 0x6c706d6178652f2e (./example.elf) -->  ascii

如您所见,rsivalue0x7ffff1a56ab8指向堆栈 ( 0x7ffff1a56cb7)上的一个地址,该地址包含一个 ascii 字符串“./example.elf”。
~是radare的内部grep

请考虑打开一个问题来请求这个功能,或者更好的是,实现它并发送一个请求请求。

info 命令保存所有传递给radare2 的参数,您也可以使用内部grep 来查找它

:\>radare2 -Q -c "i~ref" -d cmdlnargs.exe firstarg secarg thirdarg
Spawned new process with pid 6032, tid = 3196
r_sys_pid_to_path: Cannot get module filename.= attach 6032 3196
bin.baddr 0x01330000
Using 0x1330000
Spawned new process with pid 872, tid = 2512
r_sys_pid_to_path: Cannot get module filename.asm.bits 32
referer  dbg://cmdlnargs.exe firstarg secarg thirdarg

在radare而不是shell中执行的相同命令

:\>radare2 -d cmdlnargs.exe firstarg secarg thirdarg
Spawned new process with pid 5356, tid = 2704
r_sys_pid_to_path: Cannot get module filename.= attach 5356 2704
bin.baddr 0x01330000
Using 0x1330000
Spawned new process with pid 5296, tid = 6036
r_sys_pid_to_path: Cannot get module filename.asm.bits 32
 -- Are you still there?
[0x779d70d8]> i~ref
referer  dbg://cmdlnargs.exe firstarg secarg thirdarg
[0x779d70d8]> q
Do you want to quit? (Y/n) y
Do you want to kill the process? (Y/n) y

:\>