Linux x86_64下objdump输出解读及sprintf漏洞利用问题咨询
解决sprintf漏洞利用中的NULL字符传递与指针解读问题
嘿,我来帮你梳理下sprintf漏洞利用到这一步该怎么突破——你遇到的NULL字符传递问题和指针解读困惑,都是x86_64平台上利用这类漏洞的常见卡点,咱们一步步拆解:
一、搞定NULL字符无法正常传递的问题
sprintf本身遇到\x00就会截断输出,而且如果是通过命令行传递payload,shell也会把\x00当成参数分隔符,导致后面的内容丢失。这里有两个靠谱的解决思路:
- 利用格式化字符串的写操作间接写入0:不用直接在payload里塞
\x00,而是用%hhn(写1字节)来构造0值。比如你需要往某个内存位置写入0,先计算当前payload已经输出的字符数,然后用%Xc%hhn,其中X = (0 - 当前输出字符数) % 256,这样当printf执行到这个格式符时,就会把0写入指定的字节位置。 - 通过二进制方式传递payload:如果是命令行参数的问题,别直接在shell里输入,用Python的subprocess模块来传递包含
\x00的二进制payload,比如:
这样就能绕过shell对import subprocess payload = b'A'*20 + b'\x00' + b'your_remaining_payload_here' subprocess.run(['./your_vulnerable_program', payload])\x00的解析,让完整payload传递到程序里。
二、验证指针解读是否正确
不确定指针解读错了?可以通过格式化字符串漏洞的泄露功能来验证:
- 泄露栈上的指针对比objdump结果:用
%1$p、%2$p……逐个打印栈上的指针值,把这些值和objdump输出的地址(比如程序的GOT表、PLT表地址)对比。比如objdump显示printf的GOT项地址是0x404018,你可以在payload里加入多个%p,找到栈上对应位置打印出的地址是否和这个值一致,同时注意x86_64的小端字节序——内存中存储地址是逆序的,比如0x12345678会被存成\x78\x56\x34\x12。 - 验证GOT表泄露:如果能通过
%x$s(x是GOT地址在栈上的偏移)泄露GOT表项的内容,对比libc中对应函数的偏移,也能确认你解读的地址是否正确。
三、后续推进的具体步骤
当解决了NULL问题、确认指针解读没问题后,可以按这几步走:
- 泄露libc基地址:利用格式化字符串漏洞泄露某个已解析的GOT表项(比如
printf的GOT地址内容),然后减去该函数在libc中的偏移(可以通过objdump -d /lib/x86_64-linux-gnu/libc.so.6 | grep printf得到),就能算出libc的基地址。 - 构造目标地址:通过libc基地址算出
system函数和/bin/sh字符串的地址(同样查libc的偏移)。 - 控制程序执行流:如果是格式化字符串漏洞,用
%n系列格式符把system的地址写入返回地址或者函数指针位置;如果是sprintf导致的栈溢出,就构造ROP链,把system("/bin/sh")的调用链写到栈上,覆盖返回地址。 - 调试验证:用gdb断点在sprintf调用后,查看内存中的payload是否正确写入,比如用
x/32gx $rsp查看栈内容,或者用x/1gx <target_address>查看是否成功覆盖目标位置。
内容的提问来源于stack exchange,提问作者oxagast
相关产品推荐
相关产品推荐

