缓冲区溢出覆盖返回地址调用低地址函数(0x57d)时的问题咨询
缓冲区溢出问题的解析与解决方案
让我一步步帮你拆解这两个疑问,并给出可行的解决思路:
1. Bash的null字节警告是否意味着忽略了payload中的\x00\x00?
没错,这个警告直接点明了问题:bash会忽略输入中的null字节(\x00)。
因为bash处理命令行参数时遵循C风格字符串规则——字符串以null字节作为结束标志。当你通过$(...)做命令替换生成payload时,bash遇到第一个\x00就会判定字符串已结束,后面的内容(包括剩余的\x00)都会被直接截断,根本不会传递给目标程序。这就是你的payload里\x00\x00没生效的核心原因。
2. 为什么触发SIGSEGV的地址是0x5600057d,而不是预期的0x0000057d?怎么构造正确的payload?
这个问题和程序的PIE(位置无关执行)特性直接相关:
- 默认情况下,gcc编译的程序会开启PIE,程序加载到内存时会被分配一个随机的基地址(比如你这里的
0x56000000)。 - 你拿到的
0x57d其实是目标函数not_called相对于程序基地址的偏移量,而非绝对内存地址。当你把\x7d\x05\x00\x00写入返回地址时,程序实际计算的绝对地址是「基地址 + 偏移量」,也就是0x56000000 + 0x57d = 0x5600057d,这就是你看到的崩溃地址。 - 另外,
0x0000057d本身是无效的用户空间地址(用户程序的内存地址不会这么低),哪怕你能传递这个地址,程序也会直接崩溃。
正确的payload构造方法:
- 获取函数的实际绝对地址:
在gdb中启动程序后,用命令p ¬_called查看not_called的真实绝对地址。比如如果输出是$1 = (void (*)()) 0x5600057d,那这个就是你要写入返回地址的目标值。 - 绕过bash的null字节限制:
既然bash无法传递包含null字节的命令行参数,我们可以换方式传递payload:- 方法一:将payload写入二进制文件,通过标准输入传递给程序:
python -c 'import sys; sys.stdout.write("A"*0x6c + "BBBB" + "\x7d\x05\x00\x00")' > payload.bin ./victim < payload.bin - 方法二:直接通过管道传递payload:
python -c 'import sys; sys.stdout.write("A"*0x6c + "BBBB" + "\x7d\x05\x00\x00")' | ./victim
- 方法一:将payload写入二进制文件,通过标准输入传递给程序:
- 临时简化方案(适合实验/作业):
按照你提到的技巧,用静态链接编译程序:
静态链接后的程序会禁用PIE,函数的绝对地址会是固定的高地址(不会包含null字节),这样你就可以直接用命令行传递payload,无需担心null字节被截断。gcc -static -o victim victim.c
内容的提问来源于stack exchange,提问作者Jolly Roger
相关产品推荐
相关产品推荐

