This short exercise explores how a simple heap-based buffer overrun can affect application variables. It requires a Linux environment (WSL should work) and the GNU C compiler.
Be aware that buffer overruns can get considerably more serious than this simple example, particularly if they allow the attacker to inject shellcode into a remote server running with high privileges.
Create a directory for this worksheet and download
testlogin.c into it.
DO NOT LOOK AT THE SOURCE CODE, at least until you’ve completed the exercise. The challenge here is to figure out what is going on without reference to the code!
Compile the program by entering
The version that this creates is a reasonably realistic simulation of a login process, in which the user is required to enter a seven-character password. As with real logins, keypresses will not be echoed on-screen.
You might find it easier to do the experiments below using a less
realistic simulation, in which keypresses are echoed on-screen; if you
want this version, compile the program with
make vis instead.
(The compiler helpfully issues a security warning here, which you can
safely ignore, since we are deliberately trying to trigger the problem
in this exercise!)
Run the program by entering
./testlogin. Enter the real password,
“penguin” (without the quotes). This should login you in successfully.
If you try any other seven-letter words, login should fail.
Try entering “xxxxxxx” - i.e., the letter ‘x’ repeated seven times. This, too, should be unsuccessful.
Now try a ten-character password, again consisting only of the letter ‘x’. Increase the length to 15, then 20, then 25, etc. Keep going, increasing input length by five characters each time, until you see a change in program behaviour.
Think about how this program might be making use of memory. Can you explain exactly what is going on here?
make vismemif you want to see the entered password echoed on-screen). When it runs, this version of the program will show you the relevant portions of heap memory, displaying bytes as hexadecimal integers and, where possible, as printable characters. If you do the experiments above again and examine program output carefully, you should see what is going on.