Brainpan Vulnhub Walkthrough

To open executable files in Linux, we install Wine.

Next, we would need a simple script in order to connect to the port specified by the executable file. Hence we use sockets to connect to our local host and at port 9999, with our first payload being admin. (It can be anything as long as it is a possible password i guess)

And it says here that we copied 5 bytes to buffer. Hmm looks like a buffer overflow? Let’s try and see if we can actually overflow it

Let’s try a thousand As

Well, our executable file crashed. Hence it is likely a buffer overflow exploit we would need to do.

Now we would require tools such as Immunity Debugger and mona.py

  1. Immunity Debugger – https://www.immunityinc.com/products/debugger/
  2. Mona.py – https://github.com/corelan/mona/blob/master/mona.py

Mona.py has to be placed in PyCommands Immunity Debugger directory

First, we attach brainpan.exe to Immunity Debugger

So roughly, the steps i will use to do a simple buffer overflow (Without ret2libc, etc) will be:

  1. Find the exact number of bytes before crash -> This is where the next 4 bytes will override EIP
  2. Find bad characters
  3. Check for memory protection with mona
  4. Generate shellcode
  5. Find and override EIP to JMP ESP location
  6. Complete and run the exploit script
  7. Root? User? shell

1. Find the exact number of bytes before crash

In order to find the exact number of bytes in the buffer before the program crash, we would need the 2 files, namely pattern_create and pattern_offset, which are written in ruby

Pattern_create create a series of characters to be stored in the buffer, while pattern_offset will take a specified string of bytes and output the number of bytes to reach the specified string. Hence, we create a pattern of perhaps 1000 characters, and with the overridden EIP address, we will know how many bytes it takes to reach the new bytes that overridden the EIP address

Here’s the example usage and the options available. Hence for 1000 characters, we will do ./pattern_create.rb -l 1000

And this will now be our payload

And in Immunity Debugger, we hit “play” button on the top

And you can see the new address, with EIP overridden to 35724134

Now with pattern_offset, we specify this address

Usage and example, so with this, our command will be ./pattern_offset.rb -q 35724134

And it appears that the EIP address is located from 524th byte onwards. Let’s test it by first putting 528 As, since EIP address is 4 bytes long, with 528 As in the buffer, in theory, the new EIP will then be 41414141

And as expected we are correct. But to confirm it, If we fill the byte with 527 As, then it will have one less 41.

And we are correct, as EIP is now 00414141.

2. Finding bad characters

Finding bad characters is important as well, because some byte characters can cause issues with our exploit code. For example, if our shellcode contains the null byte (x00), then our shellcode will be cut short. Of course, null byte could be the only bad character, but we should test it in order not to waste precious time while wondering how come our exploit script doesn’t work! Besides, if you are studying BOF solely for OSCP, then i strongly believe OSCP will not just leave null byte as the only bad character anyway. Hahah

In order to get a list of bytes from 00 to FF, we can always do a simple Google search, or you can use https://bulbsecurity.com/finding-bad-characters-with-immunity-debugger-and-mona-py/ as the variable is named and we simply just copy and paste it into our exploit script

So we make 3 changes

  1. Remove \x00 if present in the badchar, because the null byte will truncate the string and you will simply not see the rest of the badchar
  2. Add badchar after 524 As
  3. s.send(payload.encode()) becomes s.send(payload) as they are not needed!

Now we send it to Immunity Debugger, and on the right side, we click the ESP value and “Follow in Dump”

Once done, the bottom left side will change and we can manually eye-ball to see if there are bad characters inside. After the buffer is filled, you can see that the byte 01 shows up, followed by 02, 03, 04… until FF. Since they are in correct running order, then we know that only \x00 is the only bad character https://veteransec.com/2018/09/10/32-bit-windows-buffer-overflows-made-easy/ -> This link shows another example for when there are other bad characters present, then you see that occasionally, the order of the bytes do not go in order, and we know that the one out of place is a bad character.

3. Check for memory protection with mona

Now the next step will utilise the mona.py script we added, to use it, we reset Immunity Debugger, attach brainpan again, and at the bottom there is a white box which we can type commands in, and we type !mona modules

So we see that for brainpan.exe, everything is false, meaning that it does not have any memory protection, such as ASLR as you can see from the header! That’s good because we do not need to do other types of buffer overflow such as return to lib c, where the stack is non-executable, or for the case that ASLR is not turned on, we do not need to keep running the exploit in hopes that the address hits the same as our overridden EIP address.

4. Generate shellcode

To generate shellcode, we use msfvenom, since the target machine is a linux machine, we use a linux reverse tcp

Remember to specify the bad characters!

5. Find and override EIP to JMP ESP location

So now that we have all the parts, we are left with the final JMP ESP location where we will then override this address with EIP. If you are wondering why JMP ESP is better instead of hardcoding a location to say the start of the buffer, then read this: https://security.stackexchange.com/questions/157478/why-jmp-esp-instead-of-directly-jumping-into-the-stack

For those who done the machine, you would have realised that JMP ESP points to the start of the buffer, hence rather than guess/hardcode the address, JMP ESP would do be more reliable.

To find JMP ESP, we simply run the brainpan.exe, without using exploit script.

You will see that on the left side there are instructions, we simply look for JMP ESP by going to any instruction, right click and search for all commands in modules

And look for jmp esp

And we have the address 311712F3.

6. Complete and run the exploit script

Next we fill in the address obtained previously and form our payload, we add a few bytes of NOPsled as buffer.

And we also change the IP address to our target, and not 127.0.0.1 or we will simply be getting a reverse shell of our own host machine.

7. Obtaining a shell

First we use metasploit multi/handler (Allowed in OSCP so it’s fine) we are using this as we specified a meterpreter shell earlier when we generate the shellcode

And once we run the exploit, we have a shell! 😀