这可能有一个简单的解决方案,但我在任何地方都找不到。
$> ./be1 11 AAAAA
使用gdb
, 查找argv[]
和argc
很简单:
(gdb) print argv[0]@argc
$7 = {0xbffff872 "be1", 0xbffff89a "11", 0xbffff89d "AAAAA"}
但是,我们如何使用radare2 做到这一点?
这可能有一个简单的解决方案,但我在任何地方都找不到。
$> ./be1 11 AAAAA
使用gdb
, 查找argv[]
和argc
很简单:
(gdb) print argv[0]@argc
$7 = {0xbffff872 "be1", 0xbffff89a "11", 0xbffff89d "AAAAA"}
但是,我们如何使用radare2 做到这一点?
radare2 目前不标记 argv
和argc
。然而,它的实现不应该是复杂的。
虽然这些参数没有被radare2标记,但我们可以通过检查寄存器很容易地看到它们。让我们一步一步来。
假设我们有以下程序:
$ cat example.c
#include <stdio.h>
int main(int argc, char *argv[]) {
printf( "argv[1]: %s\n", argv[1]);
return 0;
}
程序所做的就是打印给它的第一个参数。就那么简单。
让我们编译它gcc
并radare2
使用-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()
。我们可以通过在main
using处设置断点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
如您所见,rsi
value0x7ffff1a56ab8
指向堆栈 ( 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
:\>