Smashing the stack
Download the access control program named, appropriately enough, vulnerable. Like the other programs we've been experimenting with, it doesn't actually grant access to anything, it just prints messages. Unlike the other programs we've been experimenting with, it chooses a random password every time it runs, so there is no way to gain access other than by astronomically good luck.
Or is thereā¦
The program is compiled from C code that looks like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define SIZE 16
void choosepassword(char secret[SIZE]) {
int i;
for (i = 0; i < SIZE - 1; ++i)
secret[i] = 'a' + (rand() % 26);
secret[i] = '\0';
return;
}
int checkpassword(void) {
char secret[SIZE];
char input[SIZE];
choosepassword(secret);
gets(input);
return strcmp(input, secret) == 0;
}
int main() {
srand(time(0));
if (checkpassword())
printf("Access granted!\n");
else
printf("ACCESS DENIED\n");
return 0;
}
void donotcallthisfunction(void) {
printf("Something strange is going on...\n");
exit(EXIT_FAILURE);
}
The critical function is checkpassword
, which reads in the password
using the notorious gets
(get string) library function. Nobody uses
gets
anymore, and in fact I got a lot of warnings when I compiled
this code for you, because it is vulnerable to a buffer overflow attack.
You might find the following resources helpful for understanding what's
going on with this kind of attack.
Smashing the stack for fun and profit, by Aleph One. This is the original tutorial on stack smashing, published in the infamous Phrack Magazine in 1996.
Smashing the Stack For Fun and Profit (Today), a 2016 article revisiting the classic in light of modern defenses. You don't have to worry, because I have already disabled all of the defenses on poor
vulnerable
, but it's a good summary of the sorts of defenses there are.Stack-Based Buffer Overflow Attacks: Explained and Examples, which has code that inspired the particular vulnerability in our example, along with some additional details about how it works and how to exploit it.
Stack frames, for review about how the critical information is stored on the stack.
Tenouk's buffer overflow tutorial, an incredibly long and detailed deep dive on the topic of buffer overflows in C and C++, including a lot of information that overlaps with other topics we've covered in this class.
To satisfy this assignment, I want you to produce two exploits and
then write up how you designed them. An exploit is a file that can be
provided as input to the vulnerable program with the result of changing
its behavior. I like to use xxd -r -p
to convert hexadecimal into raw
binary files to generate exploits; it's also quite common to use Python
or other languages to make short programs that output the exploit. If
you've generated your exploit in a file named exploit
, you can feed
it into vulnerable
using shell redirection.
./vulnerable < exploit
The first exploit should overwrite the buffer to replace the secret
with one you can control, causing the program to print "Access
granted!" and exit normally. Call that exploit file smashsecret
when you submit it.
The second exploit should overwrite the saved return address so that
checkpassword
returns to donotcallthisfunction
instead of main
,
causing the program to print "Something strange is going on..." and
exit. Call that exploit file smashreturn
when you submit it.
If you cannot get one or both of those exploits working, submit any input
that causes vulnerable
to crash, e.g. with a segmentation fault, for
partial credit. Conversely, there are numerous variations on this sort of
attack; if you want to go the extra mile, consider embedding machine code
in the exploit itself and overwriting the return address to execute your
injected code. Or, you could look into return-oriented programming (ROP).
In addition to your exploit files, submit a writeup in PDF format explaining how you found the information you needed and how you generated and tested the exploits.
Have fun smashing the stack!