88 lines
3.4 KiB
C
88 lines
3.4 KiB
C
/*
|
|
* bof.c
|
|
*
|
|
* A quick, simple, buffer overflow example.
|
|
*
|
|
* std / c89
|
|
* cflags / -z execstack -ggdb -fno-stack-protector -no-pie
|
|
*/
|
|
|
|
#include <stdio.h> /* 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;
|
|
}
|
|
|