Radare2 调试:如何将程序的输出通过管道传输到另一个程序的输入?

逆向工程 雷达2
2021-06-20 00:55:44

我编写了一个 C 程序,该程序构建了一个 ROP 负载并将其发送到stdout. 使用 Radare2 的调试模式,我如何将此输出通过管道传输到我试图利用的二进制文件,该二进制文件接受输入stdin

例如,如果我编译的 C 程序是exp并且我正在利用的二进制文件是vuln,我想./exp | ./vuln在 Radare2 的调试模式下执行,以便我可以看到我的有效负载如何破坏内存。

我看到了这篇文章,但是,如果我错了,请纠正我,它似乎没有回答我的问题,只是描述了如何使用第二个终端进行输入/输出。

编辑:我暂时找到了一个解决方法,但是当我进行更改时重复执行相当烦人。我首先将输出重定向到一个新的文件:./exp > exp.output然后rarun2按如下方式制作脚本:

#!/usr/bin/rarun2
stdin=./exp.output

然后我通过r2 -e dbg.profile=dbg.rr2 -d vuln.

2个回答

这是一个很好的问题,你很幸运——radare2 提供了几种方法来实现这一点。让我们来看看更基本和更直接的选项。

配置

首先,确保运行最新的radare2。在撰写本文时,这是 v4.3.1。radare 社区建议从源代码构建radare2。在 Linux 系统上,就像克隆存储库并执行以下命令一样简单

$ cd radare2
$ ./sys/install.sh

注意:通过从包存储库安装radare2,您可能会因为旧版本而错过关键功能。

现在这部分已经过去了,我们可以继续寻找解决方案。


准备测试程序

对于以下示例,我编写了两个程序来演示我从一个程序动态传递到另一个程序的数据如何反映在其输出中。

中继器是一个接收用户输入并将其打印到控制台的程序。
资料来源: repeater.c

#include <stdio.h>

int main() {

        char user_input[100];
        fgets (user_input, 100, stdin);
        printf ("[+] Received from STDIN: %s\n", user_input);

        return 0;
}

exp是一个将字符串打印到控制台的程序。
资料来源: exp.c

#include <stdio.h>

int main() {
        // print string, hex values, and the current UNIX time
        printf ("Hello, \x41\x42\xaf\xd7, %u", (unsigned)time(NULL));
        return 0;
}

为了演示所需的行为,我们可以像这样使用这些程序:

$ ./exp | ./repeater 
[+] Received from STDIN: Hello, AB��, 1583565405

$ ./exp | ./repeater 
[+] Received from STDIN: Hello, AB��, 1583565418

方法0:rarun2配置文件

在radare2 中,当它与调试对象交互时,rarun2 是您的首选工具。

该程序用作运行具有不同环境、参数、权限、目录和覆盖的默认文件描述符的程序的启动器。
来源: man rarun2

虽然非常复杂且功能丰富,但我们将重点关注其中一项基本功能,即与 STDIO 交互。

从您的问题来看,您显然熟悉 rarun2 配置文件的概念。当我使用 rarun2 将漏洞利用的输出传递给调试对象时,我使用的配置文件看起来有点像这样:

$ cat profile.rr2 
#!/usr/bin/rarun2
stdin=!./exp

这个 rarun2 配置文件将执行./exp程序并将程序的输出设置为调试对象的标准输入。

然后,我们就可以在不离开radare2 shell的情况下,一次又一次地快速执行radare2中的程序。

首先,创建一个 rarun 配置文件,如上所示。然后,在radare2 中打开调试对象并使用以下-r标志加载此配置文件

在调试模式下加载程序并用于dc执行它:

$ r2 -r profile.rr2 -d repeater 
Process with PID 86588 started...
= attach 86588 86588
[0x7f89ba9b8100]> dc
[+] Received from STDIN: Hello, AB��, 1583567900

如您所见,您进入了调试模式,并且程序成功执行并输出了exp程序。您可以通过使用doo (as well asood`)继续执行该程序,该程序将“使用 args 在调试模式下重新打开”。

[0x7f316b76c100]> doo
Process with PID 86657 started...
= attach 86657 86657

[0x7f2aecada100]> dc
[+] Received from STDIN: Hello, AB��, 1583568042

[0x7f2aec99ace6]> doo
Process with PID 86660 started...
= attach 86660 86660

[0x7ff100166100]> dc
[+] Received from STDIN: Hello, AB��, 1583568056


[0x7f0efc9e4ce6]> doo
Process with PID 86673 started...
= attach 86673 86673

[0x7f676d6b2100]> # Define Breakpoint at main
[0x7f676d6b2100]> db main

[0x7f676d6b2100]> dc
hit breakpoint at: 5652649de159

[0x5652649de159]> dc
[+] Received from STDIN: Hello, AB��, 1583568059

方法一:rarun2规则

幸运的是,您可以跳过 rarun2 文件的创建,只需告诉radare2 应该从哪里获取标准输入。这可以通过使用-R后跟 rarun 键和值标志轻松完成

$ r2 -R stdin=\!./exp -d repeater
Process with PID 87508 started...
= attach 87508 87508

[0x7f87588c0100]> dc
[+] Received from STDIN: Hello, AB��, 1583568818

这是一次性拍摄,doo在radare2 会话中再次使用将不会再次使用相同的标准输入。但是,您可以利用该dor命令并做一些技巧;)

[0x7f8758780ce6]> dor?
| dor [rarun2]  Comma separated list of k=v rarun2 profile options (e dbg.profile)

[0x7f8758780ce6]> dor stdin=!./exp
[0x7f8758780ce6]> doo
Process with PID 87594 started...
= attach 87594 87594

[0x7f8758780ce6]> dc
[+] Received from STDIN: Hello, AB��, 1583568991


[0x7fdb45f3ece6]> # And this of course can be done with a single line
[0x7fdb45f3ece6]> dor stdin=!./exp; doo; dc
Process with PID 87627 started...
= attach 87627 87627
[+] Received from STDIN: Hello, AB��, 1583569028


方法∞

还有其他方法可以执行此类设置。由于时间太长,我会很快把它们记下来。这里有一些想法:

  1. 使用反引号:r2 -R "stdin=\"`python -c print(1234)`\"" -d repeater甚至r2 -R "stdin=\"`python -c 'print(1234)'`\"" -d repeater

  2. 使用其他终端的 tty 重定向 STDIN。您可以通过执行./exp > dev/pts/X其中 x 是 tty 编号来简单地将数据传递给tty。

  3. 使用popen于写入的过程中,或将输出重定向到的/ proc // FD / 0

  4. 使用外部 shell 脚本自动执行您遇到的繁琐任务

作为一种临时解决方法,在有人给您正确答案之前,您可以使用这样的 bash 脚本在一行中执行您想要的内容:

#!/bin/bash 
gcc -o exp exp.c   #add another compiler options if you need
./exp > exp.output 
r2 -e dbg.profile=dbg.rr2 -d vuln

所以你只需运行./nameOfScript.sh来编译和调试你的程序。

根据对这个问题的评论,你想要的功能似乎还没有在radare2中实现,但我可能错了......