Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compile C to allow for Buffer Overflow

I am learning about buffer overflows and am trying to make one. I have this code:

#include <stdio.h>

char *secret = "password";

void go_shell() {
    char *shell =  "/bin/sh";
    char *cmd[] = { "/bin/sh", 0 };
    setreuid(0);
    execve(shell,cmd,0);
}

int authorize() {
    char password[64];
    printf("Enter Password: ");
    gets(password);
    if (!strcmp(password,secret)) {
        return 1;
    }
    else {
        return 0;
    }
}

int main() {
    if (authorize()) {
        printf("login successful\n");
        go_shell();
    } else {
        printf("Incorrect password\n");
    }
    return 0;
}

I compile this with gcc and then run it in gdb

I enter about 100 "A"s as the password and the program crashes.

The problem is no register is overwritten to 0x4141414141414141

I googled this and added the -fno-stack-protector flag to gcc, which allowed RBP to be overwritten to 0x4141414141414141 but nothing else.

I was wondering if there was a way to compile the code so that RIP can be overwritten.

like image 434
carloabelli Avatar asked Feb 09 '13 15:02

carloabelli


2 Answers

Your code already does what you want if you compile with -fno-stack-protector. The reason you don't see RIP with a value of 0x4141414141414141 in GDB is that a general protection fault is thrown before RIP is updated. (If a page fault occurs, the GPF handler usually loads the page from swap and resumes execution by starting with the failed instruction.)

like image 167
nwellnhof Avatar answered Oct 16 '22 20:10

nwellnhof


The reason you get a crash of EIP 0×41414141 on x32 is because when the program pops the previously saved EIP value off the stack and back into EIP the CPU then tries to execute the instruction at memory address 0×41414141 which causes a segfault. (it must fetch the page prior to execution of course)

Now, during x64 execution when the program pops the previously saved RIP value back into the RIP register the kernel then tries to execute the instructions at memory address 0×4141414141414141. Firstly, due to canonical form addressing, bits 48 through 63 of any virtual address must be copies of bit 47 (in a manner akin to sign extension), or the processor will raise an exception. If that was not an issue- the kernel does additional checks before invoking the page fault handler since the max user space address is 0x00007FFFFFFFFFF.

To recap, in x32 architecture the address is passed without any “validation” to the page fault handler which attempts to load the page which triggers the kernel to send the program segfault but x64 does not get this far.

Test it, overwrite RIP with 0×0000414141414141 and you will see the expected value is placed in RIP since the prechecks by the kernel pass and then the the page fault handler is invoked like the x32 case (which of course, then causes the program to crash).

like image 24
import os.boom.headshot Avatar answered Oct 16 '22 19:10

import os.boom.headshot