如何通过命令行参数向程序传入含\x00的字节形式内存地址
解决通过argv传递含\x00字节的缓冲区溢出payload问题
核心限制说明
shell在处理命令行参数时,会将所有参数视为C风格字符串(以\x00结尾),因此直接输入包含\x00的内容会被shell截断,无法完整传递给目标程序。要传递包含\x00的原始字节,必须绕过shell的字符串解析限制。
可行解决方案
1. 编写辅助C程序(通用可靠)
通过execve系统调用直接传递字节序列,绕过shell的截断。示例代码如下:
#include <unistd.h> int main() { // 构造目标payload:对应\x00\x00\x41\xab\x00\xab的字节序列 unsigned char payload[] = {0x00, 0x00, 0x41, 0xAB, 0x00, 0xAB}; // 构造argv数组:第一个元素是目标程序路径,第二个是payload,末尾为NULL char *argv[] = {"./vuln_program", (char *)payload, NULL}; // 调用execve执行目标程序,传递构造好的参数 execve("./vuln_program", argv, NULL); return 0; }
使用步骤:
- 将上述代码保存为
inject.c,编译:gcc inject.c -o inject - 运行辅助程序:
./inject
注意事项:
- 确保目标程序的
end参数是payload的实际长度(比如示例中是6)。如果目标程序通过strlen(input)获取end,会在第一个\x00处停止计数,导致无法写入完整payload。这种情况下,需要修改目标程序逻辑,或者在辅助程序中额外传递payload长度作为第二个参数,让目标程序读取该数值作为end。
2. 使用zsh的特殊语法(仅限zsh环境)
zsh支持$''语法解析转义序列,包括\x00,并且能将完整字节序列传递给程序。直接执行:
./vuln_program $'\x00\x00\x41\xab\x00\xab'
局限性:
- 仅适用于zsh,bash等其他shell不支持完整传递含
\x00的参数。 - 同样需要目标程序的
end参数是payload的实际长度,否则strlen会截断数据。
关键原理
execve系统调用允许直接传递字节数组作为参数,无需遵循C风格字符串的\x00结尾规则(内核会处理参数的传递,目标程序可以通过原始内存访问获取完整字节序列)。而shell的命令行解析依赖C字符串,因此必须绕过shell直接调用execve。
内容的提问来源于stack exchange,提问作者artisticaligator
相关产品推荐
相关产品推荐

