/* * bof.c * * A quick, simple, buffer overflow example. * * std / c89 * cflags / -z execstack -ggdb -fno-stack-protector -no-pie */ #include /* printf, gets */ #define BUF_SZ 8 /* Something small, easy to exploit */ /* * The function `get_rich_fast` is the function we are going to try to jump to. * - paddr = 0x1136 * - vaddr = 0x401136 */ void get_rich_fast(void) { /* The following instruction at (vaddr = 0x40113a). */ printf("woohoo!!! free money"); } void get_input(void) { /* Declare the buffer we want to put the input in. */ char buf[BUF_SZ]; /* * Table of the parts of `rsp` we want to pay attention to at this point. * * Address start: 0x7fffffffe590 * * ------------------------------------------------------------------------------------------------ * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e | f | * |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----| * | | | | | | | buf ---> | [------- -------] | * |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----| * | ? | ? | ? | ? | ? | ? | ? | ? | 9a | 11 | 40 | <--- (1) | | | | * |____|_____|_____|_____|_____|_____|_____|_____|_____|_____|_____|_____|_____|_____|_____|_____| * * (1) Saved base pointer, but also is the return address back into the function main. * We know that 0x40119a is where the program will jump back to at the end of this function. * However, we want it to jump to 0x40115a. This is where we want to attack. * * Simply, in a debugger (lldb), we can do the following: * * - [ break set -name get_input ] <--- ( set a breakpoint at the function name get_input ) * - [ run ] * - [ step ] until the current line is AFTER the `gets` call and before we jump back to main. * - [ mem write 0x7fffffffdf78 0x5a ] <--- ( writing 0x5a to replace 0x9a, so that we jump to the printf statement ) * * In the debugger, if we did not change that value, it should show something like the following: * * ________________________ * | | * | ---> return 0; | * |_______________________| * * However, since we changed the address we wanted to jump to, we should see: * * ________________________ * | | * | ----> printf(.....) | * | } | * |_______________________| * * * Testing this, we know we want to fill our buffer with some character (such as a). We can see in memory that there * is data stored between addresses 0x7ffffffffa5a0-7, and we want to keep that the same. We may come up with a payload * such as: 'aaaaaaaa' + '\x00\xe3\xff\xff\xff\x7f\x00\x00' + '\x3a\x11\x40' and send that data into stdin using something like * `printf`. * * In one compilation of the program where the vaddr of `get_rich_fast(void)` is 0x401156, the chunk of data after is * [0xffffe300, 0x00007fff], we can overwrite the saved base pointer (where we would like to return to at the end of the * `get_input` function by piping 'aaaaaaaa\x00\xe3\xff\xff\xff\x7f\x00\x00\x56\x11\x40' into our execution of [this] binary. * * Reference: https://localhost22.com/ref/bofpl.png * */ gets(buf); } int main(void) { /* Call the `get_input` function, which gives us access to our buffer and the `gets` call. */ get_input(); /* Exit code 0. */ return 0; }