Last updated at Tue, 23 Jan 2024 21:32:08 GMT

So you wanna be a Metasploit exploit developer huh?

Well you are in luck because I have been working on an an "in-depth" exploit development tutorial series  that takes users behind the scenes on the process of exploit development and metasploit module creation. This series has been specifically designed with you "the community" in mind. It will cover step by step detail and explanation. This post is meant to be part 1 of a series of exploit posts to come. The goal is to raise awareness on the steps needed to build a simple exploit and work our way up to sophisticated metasploit modules that will help increase community contributions via our pull request system. Companies are also trying to drive up the cost of exploit development, and I say it doesn't matter because were not going anywhere. Programs like Metasploit secure the net, and kickstart vendors into action and prevents them from using the bluff card because proven exploits are offered to ensure customers/companies are safe from vulnerabilities.

What you will learn:

Part 1 is aimed at newcomers in the exploit field, and concentrates on exploiting a simple FTP server with a buffer overflow vulnerability to eventually land us a bind shell. Dont worry, we will systematically progress onto more difficult, and modern exploitation vectors in the upcoming series. Part 1 is a very easy demonstration and details old techniques, but will allow you to move onto more advanced exploitation techniques like ROP, Heap Spraying, and begin to understand how to bypass current memory protections like DEP/ASLR for the next series. I want you to struggle a bit with the old school way. (and how it changed the game) will be covered in depth in the upcoming series as well. You cant know where exploit development/memory protections are going, or are currently at until you know where they have been. This experience is key because it gives you a solid grasp on the awesome functionality of the Metasploit framework, and how to write modules yourself, and gives you the confidence/ability to follow along as we progress deeper into exploit development in our future series posts. The skills you learn here can aid you in your current role and enable you to port exploits from other languages to Metasploit, and craft your own. Also, have you ever been on a pen test, and found a vulnerable service/daemon, and navigated to and found several public exploits listed, only to find yourself without the knowledge or experience to modify/port those exploits to suit your pen test, and essentially not gain access?

Before we start:

I want to give an extra special thanks to Wei "sinn3r" Chen, Tod "todb" Beardsley, and Juan Vazquez from the Metasploit Team for performing the technical proof reading on the post, and for emailing me a "long" list of items to correct/update. Also for providing the extra special "Quick Tips" that are detailed throughout this post. Those quick tips will no doubt help myself and our community on our exploit development path. With their guidance I was able to learn new concepts, and I was able to refine my personal exploit process. This article would not be what it is if it wasn't for their input. Thanks !!

According to Wei "sinn3r" Chen, Exploit Engineer and Juan Vazquez, Exploit Developer on the Metasploit Team, " Having an exploit dev on a pentest team can be handy, but not always possible to deploy them due time restrictions or permissions.  Ideally, exploits should constantly be prepared as early as possible, that way you can work on your reliability more, hence better results in your pentest. A last-min exploit will only be prone to failures, making your pentest unsuccessful.  Also, people should use Metasploit to build exploits because the whole package we provide -- we have a large collection of good payloads that are open source, so if needed you can always customize it.  We also have a large collection of post exploitation modules that your MSF payload can use, and good post exploitation is often where you get to add a lot more value to your pentest. "

Concentrating on exploit development during a pen test leaves the customer in a better spot because it uncovers actual business risk and exposure to compromise.

Metasploit exploit series goals:

  • Main goal is to raise the numbers of acceptable pull requests while learning cool Metasploit/ruby programming techniques in the process
  • Detail new modules and perform an in-depth anatomy deep dive on them, and demystify how they were created so we can learn how to emulate them

To ensure your success, if you havent done so already please familiarize yourself with the following (in order of relevance):

1. Learn Ruby The Hard Way then move on to Programming Ruby 1.9

2. Helpful Exploitation Theory | Assembly Memory Corruption Intro to exploits videos  | Myne-us | it-sec-catalog

3. Writing a Windows Exploit for the Metasploit Framework

4. Metasploit The Pen Testers Guide

5. Start to look at /modify/play and port actual Metasploit exploit code ['EDB',1, 2, 3, 4, 5']

6. Join the Metasploit hackers-developer list and invest time in learning the MSF Wiki processes:

msf to the fullest | msfdev | porting exploit modules | dev environment | using git | msf acceptance guidelines | get your feet wet | bad coding practice | Top 50 most wanted exploits

According to Wei "sinn3r" Chen, Exploit Engineer and Juan Vazquez, Exploit Developer on the Metasploit Team, " Exploitation steps can change depending on the compiler or the environment. Sometimes certain Windows API can change the stack layout a bit.  This is why sometimes you'll see an exploit working for a specific service-pack even though it's using application-specific memory addresses.  The same problem can also occur if you let your students compile their own vuln app, so make sure you don't let them compile from source. "

Exploit Building steps covered in this tutorial (steps used depends on the exploit/series covered):

We will stick to this exploit building format for the duration of the series.

Step 1.    Stack Based Buffer Overflows and vulnerable C/C functions

Step 2.    Why the overflow occurs (deep dive into IDA Pro and ImmunityDBG)

Step 3.    Noisy fuzzer to identify vulns => (fuzz.rb)

Step 4.    Crash the app => (isolate.rb)

Step 5.    Control the crash, uncover memory protections, and zone in on the command that crashed.

Step 6.    Uncover bad characters, and calculate shellcode space => (isolate.rb)

Step 7.    Confirm shellcode space by subtracting the end ESP address from the start ESP address

Step 8.    Overwrite "the stack including the RETN address with pattern analysis => (isolate.rb)

Step 9.    Gather jmp esp address in core application.dll not kernel32.dll (details why are shown)

Step 10.  Develop PoC exploit and pop calc.exe => (PoC.rb)

Step 11.  Weaponize it with shellcode => (weaponize.rb)

Step 12.  Exploit QA process and re-confirm BadCharacters => (weaponize.rb)

Step 13.  Port exploit into a metasploit module (msf.rb)

If you have any questions, need clarification or having any issues going thru the labs. Simply post a question in the metasploit discussion page. This encourages people to collaborate/share/answer for points and helps us track answers to provide the community with better material and quicker turnaround time on questions.

Tutorial series learning format:

We understand that different people learn in different ways so we are going to incorporate all the learning styles into this tutorial series. This series will emphasize practical hands on exercises, required reading, and the option of completing the homework (metasploit modules) and contribute your shiny new modules back to the community. This is the first exploit series of its kind, and we are truly excited!

Environment setup:

To ensure you can follow along during the series, I will provide version numbers regarding my dev environment where applicable. This series Part1. has been tested to run on the following versions and Operating systems only. Please set your environment accordingly before proceeding to the hands on exercises, and homework. I am using the following in my environment:

Step 1.  Theory - Stack Based Buffer Overflows and vulnerable****C/C functions

Since part 1 is an entry level series it is best to discuss some of the fundamentals of the stack, and how it relates to Assembly and the exploit process.

An overflow happens in an application as the program writes more information in an array or the buffer, than the space allocated in memory for it. This causes the adjacent area, the areas above the direction of buffer growth, to be overwritten. When this occurs all previously stored values are corrupted.

Overflows are defined as programming errors that are introduced into a application as a result of failing to enforce boundary conditions on the data being copied into the buffer. The flaws are so common in fact that Microsoft is prohibiting the use of banned functions due to dangerous C library functions being used to handle strings. Familiarize yourself with assembly tutorials 1 and 2 before proceeding. Stacks in computing architectures are regions of memory where data is added or removed in a last-in-first-out (LIFO) manner.

Figure 0x1: Stack LIFO structure.

In a stack, the topmost item, which is added last, is taken out first. Hence a stack is a LIFO structure.

A strcpy example

#include <string.h>  
void foo (char *bar)  
  char  c[12];  
  strcpy(c, bar);  // no bounds checking...  
int main (int argc, char **argv)  

Figure 0x2: Vulnerable code.

Figure 0x3: Buffer overflow process.

A. The code at Figure 0x2 above takes an argument from the command line and copies it to a local stack variable c at A above.

B. This works fine for command line arguments smaller than 12 characters.

C. Any arguments larger than 11 characters long will result in corruption of the stack. (The maximum number of characters that is safe is one less than the size of the buffer here because in the C programming language strings are terminated by a zero byte character.

When the "func" procedure returns, it moves EBP back into ESP, and POP's the return address (EIP) off the stack (4 bytes). When the above code executes it overflows the buffer, writing 'A's over the old value of EBP and over the return address. By overwriting the return address, you can seriously alter the execution flow of the program by controlling EIP and eventually jumping to our evil shellcode (ESP).

Figure 0x4: Typical layout of the stack during the function call.

As an example in Windows/Intel, typically, when the function call takes place, data elements are stored on the stack in the following way:

  1. The function parameters are pushed on the stack before the function is called.  The parameters are pushed from right to left.
  2. The function return address is placed on the stack by the x86 CALL instruction, which stores the current value of the EIP register.
  3. Then, the frame pointer that is the previous value of the EBP register is placed on the stack.
  4. If a function includes try/catch or any other exception handling construct such as SEH (Structured Exception Handling - Microsoft implementation), the compiler will include exception handling information on the stack.
  5. Next, the locally declared variables.
  6. Then the buffers are allocated for temporary data storage.
  7. Finally, the call save registers such as ESI, EDI, and EBX are stored if they are used at any point during the functions execution.

Step 2. Theory - Why the buffer overflow occurs (deep dive into Immunity Debugger)

Step 3.  Noisy fuzzer to identify vulns

Lets get started. First I will install/start Freefloat FTP server on the Microsoft XP Pro SP3 victim (the virtual machine you just created based on all the above steps).

According to Wei "sinn3r" Chen, Exploit Engineer and Juan Vazquez, Exploit Developer on the Metasploit Team, " There is a way you can get a shell against FreeFloat FTP server without using a buffer overflow and much more reliable, btw :-)  Hint: You can upload to ANYWHERE. "

Figure 1: Start the FTP Server on the victim.

Next I do a quick banner grab to verify the version to verify its correct.

Figure 2: Quick netcat banner grab.

#!/usr/bin/env ruby  
#require '/var/lib/gems/1.9.2/gems/rainbow-1.1.4/lib/rainbow.rb'  
# FILE: fuzz.rb  
# DESCRIPTION: # A quick rewrite of by "isomorphix"  
# can be customized quickly.  
# BUGS:    None reported :::  
# NOTES:  Works on Nix x64  
# AUTHOR:  Rick Flores nanoquetz9l<@>  
# VERSION: "SEAL Team v.1"  
# CREATED: 07/8/11  
$: << '.'  
  require 'rainbow'  
  require 'socket'  
rescue LoadError => e  
  puts "ERROR: Missing ruby gem. Please see README file."  
  puts e.inspect  
@version = "SEAL Team v.1"  
# my 1337 banner  
def banner()  
  puts "___________________________________________________________________"  
  puts "  _  _                  _____            _                      "  
  puts " | \ | |                |  ___|          | |                      "  
  puts " |  \| | __ _ _ __  ___ | |__ _ __  __ _| |_ __  ___  ___ _ __  "  
  puts " | . ` |/ _` | '_ \ / _ \|  __| '_ \ / _` | | '_ \ / _ \/ _ \ '__| "  
  puts " | |\  | (_| | | | | (_) | |__| | | | (_| |_| | | |  __/  __/ |    "  
  puts " \_| \_/\__,_|_| |_|\___/\____/_| |_|\__, (_)_| |_|\___|\___|_|    "  
  puts "                                      __/ |                        "  
  puts "                                    |___/  " + @version  
  puts "                                                                  "  
  puts "      Quick & dirty fuzzer that can be customized quickly."  
  puts "___________________________________________________________________"  
# GNU license  
def license()  
  puts "# Copyright (C) 2011 Rick Flores"  
  puts "# This program comes with ABSOLUTELY NO WARRANTY."  
  puts "# This is free software, and you are welcome to redistribute it"  
  puts "# under certain conditions. See GNU GPLv3."  
#puts banner ()  
# Variables to be passed at the command line and assigned for  
# use in identifying buffer overflow.  
unless ARGV.length == 2  
        puts "The correct use of fuzz.rb is as follows:".foreground(:yellow)  
        puts "Usage: ruby fuzz.rb Target_IP_Address Target_Destination_Port".foreground(:yellow)  
        puts "Example: ./fuzz.rb 666".foreground(:red).bright.blink  
# Declare needed variables  
target = ARGV[0]  
port  = ARGV[1]  
buffer = ["A"]  
c      =20  
while buffer.length <=40  
  buffer << "A" * c  
  c += 100  
commands = ["MKD","ACCL","APPE","TOP","CWD","AUTH","STOR","STAT","LIST","RETR","NLST","LS","DELE","RSET","NOOP","UIDL","USER"]  
commands.each {|cmd|  
  buffer.each {|str|  
    puts "Sending #{cmd} command with #{str.length} bytes".foreground(:red).bright  
  socket =, port)  
  socket.puts('USER test\r\n')  
  puts socket.gets  
  socket.puts('PASS test\r\n')  
  puts socket.gets  
  socket.puts(cmd + " " + str + "\r\n")  
  puts socket.gets  

Figure 3: fuzz.rb script we will be using (can be downloaded below).

Step 4. Crash the application.

Below we see that the fuzzer has crashed while sending 1720 bytes to the MKD command.

Figure 4: fuzzer crashed at exactly 1720 bytes with the MKD command.

The Freefloat FTP Server has crashed.

Figure 5: The FTP server crashed.

Next we isolate in on the MKD command at step 5 below, and see the crash in detail so we can study it.

We first restart the FTP server then attach it to Immunity Debugger to eventually see which magic 4 bytes overwrite "the stack including the RETN address.

Dont forget to run the program when finished attaching it.

Figure 6: After restarting the FTP server, fire up Immunity and go to File>Attach

Figure 7: Dont forget to start the app because it is paused by default by pressing .

Step 5. Control the crash, u****ncover memory protections, and zone in on the command that crashed**.**

We are only concerned with DEP/ASLR at this point, and those bypass techniques are not covered until Part 2 of this series. Keep an eye out for it soon.

Wei "sinn3r" Chen, Exploit Engineer and Juan Vazquez, Exploit Developer on the Metasploit Team, comment on memory protections, " Memory protections can be compiler specific. For example, you will probably never see programs compiled by the latest DevC with default settings protected by any memory protection such as SafeSEH, ASLR, NX, etc. But you will see the opposite in the latest Visual Studio. "

#!/usr/bin/env ruby  
#More informations about the flaw can be found here  
#What i do?  
#Only a script, to demonstrate the crash in FreeFloatFtpServer 1.00.  
#After sending the very long MKD command, close the socket connection, then open another socket on the server,  
#wait a second using "sleep(1)" and close the connection.  
#For the program to crash it is necessary to connect again.  
require 'socket'  
###### [ 1 ]  
buf = "X" * 1000 # original qk_fuzz.rb buffer ESP should be overwritten by 58:58:58:58  
###### [ 2 ]  
# Pattern analysis by sending unique string to identify which 4 bytes overwrite EIP !  
#buf = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2B"  
###### [ 3 ]  
    # 58        # 56      # 5a  
#buf = "X" * 247 + "V" * 4 + "Z" * 749 # EIP should get overwritten by exactly 4 V's or 56:56:56:56  
s ='',21)  
print "<< "+s.recv(10000)  
s.puts("USER admin\r\n")  
print "<< "+s.recv(10000)  
s.puts("PASS admin\r\n")  
print "<< "+s.recv(10000)  
s.puts("MKD #{buf}\r\n")  
s.close # Here Maybe don't crash the program.  
so ='',21) # Connect again,  
so.close # Now Crash  
print "[-]Error: #{$!}\n"  

Figure 8: Run the isolate.rb script to verify which bytes overwrite "the stack including the RETN address.

Run the above script

Figure 9: Ran the isolate.rb script to crash the application.

Now return to Immunity Debugger and glance at the output of ESP and EIP.

Figure 10: You have overwritten the stack including the RETN address.

You have successfully overwriten the stack including the RETN address. That means that you know have execution flow of the program. The next important task is to control the execution flow by knowing which exact 4 bytes overwrite EIP.

Dave, (CEO Immunity, Inc.), comments on bad characters, and calculating shellcode early in the process. " You need your bad-bytes check and size check first, What if the 4 in "247" is a bad byte, you have no way of knowing ahead of time unless you test for it. "

In our unique situation, our padding buffer size is 247 bytes, the EIP overwrite is the immediate 4 bytes after the 247th byte. Dave is simply making the case that it may be possible that your padding buffer might contain bad characters.

Step 6. Uncover Bad Characters and calculate shellcode space.

See step 12 for details on how to test for bad characters.

You can see from the picture below that we have massive space for our shellcode. You can also see the end of the 247 byte junk data, the 4 "VVVV" bytes that overwrite EIP, and the beginning our huge shellcode space.

Figure 16: Immunity registers, & memory at time of crash. End of the 247 byte misc junk (XXXXXXXXXXXX), 4 byte (VVVV) EIP overwrite, and the start of our wonderful shellcode space (ZZZZZZZZZZZZ).

Now we get to the details (the devil is in the details). We have to make a note of the start and end of the ESP memory address within Immunity Debugger.

Lets quickly do that now.

Figure 17. Glorious shellcode space.

Figure 18. ESP start address.

![](/content/images/post-images/9670/Screen%20Shot%202012-06-28 at 11.02.04%20PM.png)

Figure 19. ESP end address.

Step 7. Confirm shellcode space by subtracting the end ESP address from the start ESP address

Wei "sinn3r" Chen, Exploit Engineer and Juan Vazquez, Exploit Developer on the Metasploit Team, explain why the end address is technically not 0x00AFFF04 as shown in Figure 19. " _0x00AFFF04_only indicates the begging of that row, not down to the last byte of it.  So the end address should be 0x00AFFF04 7. "

The exploit still works, however these corrections have not been made so the readers can learn about them, and remember this important lesson.

Now we can quickly calculate the shellcode space more accurately. The most important part here is to subtract the ESP end address from the ESP start address. See the figures below for details.


AFFC24 -

That equals to:

Figure 20. Calculating shellcode space by subtracting the end address from the start address.

Now convert the 2E0 value to a decimal.

Figure 21. The result indicates that we have 736 bytes for our shellcode space.

We have verified that we have 736 bytes of shellcode space. That is plenty space for almost all payloads.

Wei "sinn3r" Chen, Exploit Engineer and Juan Vazquez, Exploit Developer on the Metasploit Team, comment on the use of pattern_create.rb, " To us exploit devs, using pattern_create.rb is almost not needed, because you can just use the pattern_create() function in your module.  This is really the same thing as pattern_create.rb_. "_

Step 8. Determine stack overwrite including the RETN address with pattern analysis.

Restart the FTP server, and re-attach it to Immunity. Also comment out line 17 in isolate.rb, and uncomment line 22 to begin the pattern analysis buffer string validation. The unique string was generated via metasploits pattern_create.rb script (this can also be done via ( revolutionized the game).

#!/usr/bin/env ruby  
#More informations about the flaw can be found here  
#What i do?  
#Only a script, to demonstrate the crash in FreeFloatFtpServer 1.00.  
#After sending the very long MKD command, close the socket connection, then open another socket on the server,  
#wait a second using "sleep(1)" and close the connection.  
#For the program to crash it is necessary to connect again.  
require 'socket'  
###### [ 1 ]  
#buf = "X" * 1000 # original qk_fuzz.rb buffer ESP should be overwritten by 58:58:58:58  
###### [ 2 ]  
# Pattern analysis by sending unique string to identify which 4 bytes overwrite EIP !  
buf = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2B"  
###### [ 3 ]  
    # 58        # 56      # 5a  
#buf = "X" * 247 + "V" * 4 + "Z" * 749 # EIP should get overwritten by exactly 4 V's or 56:56:56:56  
s ='',21)  
print "<< "+s.recv(10000)  
s.puts("USER admin\r\n")  
print "<< "+s.recv(10000)  
s.puts("PASS admin\r\n")  
print "<< "+s.recv(10000)  
s.puts("MKD #{buf}\r\n")  
s.close # Here Maybe don't crash the program.   
so ='',21) # Connect again,  
so.close # Now Crash  
print "[-]Error: #{$!}\n"  

Figure 11: Prepped the isolate.rb script per the above instructions.

Figure 12: isolate.rb was executed to determine magic 4 bytes that overwrite EIP.

You can know see that the stack including the RETN address was overwritten by a truly unique buffer string. This allows us to determine which exact 4 bytes overwrote EIP by using Metasploit and how much payload space we have by examining Immunity CPU registers and memory at time of crash.

Figure 13: Confirmed stack including the RETN address overwrite by a unique string.

The *Important note to take away from this that you have to remember the four bytes that caused the EIP overwrite. In this case the four bytes are EIP = 69413269.

Figure 14: The magic four bytes that overwrote EIP.

Armed with this information we navigate to the Metasploit tools directory and execute the pattern_offset.rb script as shown below.

Figure 15: Determined the offset for the four bytes via pattern_offset.rb | EIP = 247.

According to Wei "sinn3r" Chen, Exploit Engineer and Juan Vazquez, Exploit Developer on the Metasploit Team, _" Using the jmp esp address from kernel32.dll _is a bad habit, it's something that we keep trying to remind contributors to avoid doing. This is due to the fact that most system DLLs change way too often due to patch levels, or by other Microsoft software such as Office.  Very hard to use in a practical situation, so we pretty much consider them as unreliable. "

Wei "sinn3r" Chen, Exploit Engineer and Juan Vazquez, Exploit Developer on the Metasploit Team, also commented on claiming your exploit as universal. " Regarding using "jmp addr from a core.dll. Ideally you want to find an address from the application, so if core.dll comes from the FreeFloat, that would be a choice. However, calling a module "universal" is a big claim. I have seen a lot of people make that mistake saying their exploit is "universal", but when I go through the QA phase with it, the exploit starts to fail.

Here are the common causes:

  1. The most common reason is probably because they didn't realize the DLL could rebase. For example, often you will see an ActiveX control being loaded at 0x10000000, they usually rebase when you load more.
  2. The second common is probably due to the lack of understanding of the vulnerability.  For example, say you're exploiting the way a vulnerable sever constructs its debugging string when you send a request, like this:  n = sprintf(buffer, IP: %s requests: %s, client, req). Sometimes an inexperienced developer may only know he's overflowing the server with a long request, but he doesn't realize the length of his IP also affects the offset in the buffer.  So maybe the exploit will work all the time in his test environment because his IP is always the same, but obviously this type of exploit will suck if you actually try to deploy it against a real target.
  3. Sometimes the stack can also be constructed differently due to some race condition, or some API is different than the other, causing the offset to be different.

As you can see, even a simple question like "Can my exploit be reliable if I use an application DLL?" can give you a long answer like that.  And that, my friend, is why exploit development is an art.  I remember this one time our dev James Lee (egypt) said in a presentation: "Writing an exploit is never easy. Pretty much every step you do, it's like the vulnerable application wants you to fail".... I cannot agree more. "

Step 9. Gather jmp esp address.

This is one of thee most critical steps in the exploit dev process. Not having the right jmp esp address will make your exploit fail. Also having bad characters in your shellcode will render great shellcode useless.

Fire up the FTP Server>Open Immunity>Attach the FTP service>click on the show modules icon or press (Alt E), and select the kernel32.dll module.

Figure 22. kernel32.dll loaded module.

![](/content/images/post-images/9670/Screen%20Shot%202012-06-29 at 12.51.33%20AM.png)

Figure 23. RIght click in the results window and select the following jmp esp command search.

Figure 24. Search for the jmp esp command.

Figure 25. JMP ESP will be displayed at the top in red.

Figure 26. With this information we update our PoC.rb script.

Figure 27. Update our PoC.rb script.

The important item to note here is that we input the enter the jmp esp address as little endian architecture (the order in which the bytes are stored in memory).

Figure 28. Little endian architecture.

Step 10. Develop Proof of concept exploit (PoC.rb).

For this step it is important to comment out line 20 in isolate.rb, and uncomment line 24. Details shown below.

Figure 29: Prepping isolate.rb for our PoC exploit.

Figure 30: Our new buffer string.

After the execution of our modified isolate.rb script EIP should be overwritten by exactly 4 V's or 56:56:56:56.

Figure 31: EIP was overwritten by 56565656.

Figure 32: You now control the execution flow of this program!

We are now ready to execute our PoC.rb exploit to deploy calc as a proof of concept. Remember that all crashes dont always lead to a compromise as detailed in this buffer overflow exploit.

Figure 33: Pop calc.exe on victim computer as proof-of-concept!

Figure 34: Execute poc.rb to pop calc on victim.

Figure 35: Calc on victim.

Step 11. Weaponize PoC with shellcode (weaponize.rb).

Important information to take away from here is:

  1. I used the x86/alpha_upper payload (see advise from sinn3r & Juan below).
  2. EXITFUNC="process" // SEH will crash and 'process' will kill the process
  3. msfencode -e x86/alpha_upper -s 700 // -s keeps the payload under 700 bytes

Wei "sinn3r" Chen, Exploit Engineer and Juan Vazquez, Exploit Developer on the Metasploit Team, comment on the use of the x86/alpha_upper payload. " You only have a few badchars, so there's seems to be no point of using an alpha_upper payload... it actually makes the payload bigger than it should be. "

sinn3r and Juan Vazquez elaborate on BadCharacters. " Again, PoCs are not meant to be reliable, and you should never trust a badchar set coming from a PoC.  The author could have been just lazy, threw a few badchars enough to make the exploit work... often not enough when you choose a different payload.  You should ALWAYS do your badchar analysis. "

Step 12. Exploit QA process and re-confirm BadChars (weaponize.rb).

We are almost done, good job hanging in there. Now on to one of the most fun/tedious aspects of exploit dev. This step is needed to ensure finesse and reliability when submitting your exploits. We have to confirm our shellcode lands/exits gracefully onto the stack via our NOP slide like a panther swooping down to capture its prey in pitch darkness. That's what separates a true craftsman from the rest of the pack; its the QA process the developer implements on the exploits. This is the most critical steps because it will make or break your exploits. If it were compared to U.S Navy SEAL training, it would be considered Hell week.

Dealing with, manually uncovering, and testing for bad characters

  1. Metasploit/WritingWindowsExploit - Wikibooks, open books for an open world

  2. Security Basics: RE: Finding Bad Characters in Exploit Research?

  3. Using Backtrack to spot and fix bad characters in custom buffer-overflow development

From the insidetrust [3.] blog post we were able to determine that "\x00", "\x0a" and "\x0d" are a safe bet to be BadChars for text based protocols.

So we can confirm this and move on and execute our exploit weaponize.rb now (if this had not been the case we would have had to uncover bad characters as detailed in his Bens blog).

Figure 36: For whom the shell tolls.

The victim is compromised. Lets quickly turn  this exploit into a metasploit module.

Step 13. Port exploit into a Metasploit module.


Figure 37: Freefloat FTP server metasploit module.

Figure 38: Successfully compromised the victim

Take some time and study this module. You will see that not a whole lot of information is used from everything we extracted manually. That is the beauty of the framework, code reuse & mixins!!

The more important options in the module are:

  1. 'Default Options'  <= we harvested this info manually above

  2. 'Payload'            <= we harvested this info manually above

  3. 'Space' = 700      <= we harvested this info manually above

  4. "BadChars" =    "\x00\x0a\x0d" <= we harvested this info manually above

  5. 'Platform'

  6. 'Targets'

  7. 'Ret' address = kernel32.dll <= we harvested this info manually above

  8. 'Offset' = 247    <= we harvested this info manually above


Original exploit developer: C4SS``!``0 G0M3S [FreeFloat FTP Server 1.00 MKD Buffer Overflow Exploit](

Original metasploit module developer James Fitts: Freefloat FTP Server MKD Buffer Overflow (MSF)

Javier Godinez @isomorphix for help with fuzz.rb.

A Unique Examination of the Buffer Overflow Condition by Terry Bruce Gillette

Application Security and Vulnerability Analysis - Reverse Engineering

Buffer Overflow stack layout

Stack Buffer Overflow


Metasploit/WritingWindowsExploit - Wikibooks, open books for an open world

Exploitation - The Penetration Testing Execution Standard

Past, Present, Future of Windows Exploitation | Abysssec Security Research

Making Something Go Boom - Metasploit Unleashed

Fuzzing with Metasploit : Simple FTP fuzzer | Corelan Team rs-PAPER.pdf