管理有效载荷注入的输入?

逆向工程 linux 开发 二进制
2021-06-20 03:24:23

我正在寻找在 Unix (Linux) 上下文中根据程序打开的输入在易受攻击的程序中注入有效负载的方法的完整列表。

我知道有几个技巧和技巧,但详尽的清单肯定会在这里有所帮助。

1个回答

通过程序输入注入有效负载和十六进制地址取决于您获得的输入类型。这里列出了所有可能的输入以及使用纯 shell 环境和从gdb.

获取输入 char *argv[]

在这种情况下,参数是从初始命令行读取的,因此最方便的是:

$> ./program $(echo -ne "\xef\xbe\xad\xde")

在 中gdb,您需要run像这样通过命令行传递参数

(gdb) run $(echo -ne "\xef\xbe\xad\xde")

从文件中获取输入

在这里,您别无选择,只能写入文件,然后将这个文件输入您的程序,如下所示:

$> ./program ./myfile.txt

并且,在 内gdb,它应该是这样的:

(gdb) run myfile.txt

然后,gdb您可以在外部重写文件的内容并在gdb.

获取输入 stdin

获取输入通过stdin能够实现通过各种各样的功能,例如fgets()scanf()getline()read()和其他。它引发了一些问题,因为程序在执行时停止并等待输入字符。而且,您更愿意在开始时只使用一个提要来尝试您的东西并查看结果。让我们看看如何处理这个输入。

如果您必须处理多个输入(例如登录名、密码等),则需要在输入之间使用分隔符。通常每个输入之间的分隔符只是一个换行符(\n\r取决于您所在的系统)。

现在,您有两种方法可以为stdin. 要么你通过一个文件,像这样:

$> cat ./mycommands.txt | ./program

stdin需要通过这样一个文件或者运行以下命令:

(gdb) run < ./mycommands.txt

并按照前一个案例中的说明进行操作。

另一种选择是将命令的输出通过管道传输到stdin程序的 ,如下所示:

$> echo -ne "\xef\xbe\xad\xde" | ./program

gdb你可以使用bash 过程中替换 <(cmd)的技巧:

(gdb) run < <(echo -ne "\xef\xbe\xad\xde")

这种方式比有效地创建命名管道并按照几个网站上的建议在其上分支您的程序要快得多。在外部创建命名管道gdb需要许多不必要的步骤,您可以使用以前的技术立即获得它。

还要注意的是,有些人是这样使用的<<$(cmd)

(gdb) run <<< $(echo -ne "\xef\xbe\xad\xde")

但是,最后一种技术似乎过滤掉了所有 NULL 字节(无论出于何种原因),因此您应该更喜欢第一种(特别是如果您想传递 NULL 字节)。

从网络获取输入

在这里,您需要使用另一种称为netcat(网络的瑞士军刀)的工具,通常缩写为nc. 基本上,如果您的易受攻击的程序正在侦听,localhost:666那么命令行将是:

$> echo -ne "\xef\xbe\xad\xde" | nc -vv localhost 666

在 中gdb,重点是运行 ( r) 程序并从另一个终端连接到它。

stdin注射后保持开放

大多数技术stdin都会将漏洞利用字符串发送到程序,该程序将在输入终止后不久结束。之后保持打开状态并获得活动 shell 的最佳方法是cat在其stdin. 如果你浏览一个文件,它应该是这样的:

$> (cat ./mycommands.txt; cat) | ./program

或者,如果你想要一个 shell 命令,就像这样:

$> (echo -ne "\xef\xbe\xad\xde"; cat) | ./program

或者,最后,如果您要通过网络:

$> (echo -ne "\xef\xbe\xad\xde"; cat) | nc -vv localhost 666

请注意,我没有找到如何gdb在有效负载交付后保持输入打开的方法。


关于 Python3 的更新

您可能已经注意到 Python 在执行函数时改变了处理原始字节的方式print()例如,您可以有这种行为(这里是 Python2 和 Python3 行为的比较):

#> python2.7 -c 'print("\xde\xad\xbe\xef")' | xxd
00000000: dead beef 0a                                ....
#> python3.9 -c 'print("\xde\xad\xbe\xef")' | xxd
00000000: c39e c2ad c2be c3af 0a                   .........

如您所见,在 Python3 中, 的输出print()以 UTF-8 字符表示,这会极大地改变命令的结果。当您尝试将一系列选定字节发送到您攻击的程序时,这并不方便。

因此,如果您坚持使用只提供 Python3 解释器的系统,这里是要使用的命令行:

python3.9 -c 'import sys; sys.stdout.buffer.write(b"\xde\xad\xbe\xef")' | xxd
00000000: dead beef                                ....

您可能会注意到 Python3 中的命令比 Python2 中的命令复杂得多,这在某种程度上破坏了原始命令的简单性。如果有人有更短更简单的方法来实现这一点,请对本文发表评论,我真的很期待!

另一种方法可以使用这样的echo命令:

#> echo -ne "\xde\xad\xbe\xef" | xxd
00000000: dead beef                                ....

但是,您不能使用通常的 Python 语法,例如,"\x90" * 12 + "\xde\xad\xbe\xef"如果您想寻找合适的填充这会很烦人。