My friend Daniel “Mooky” Robertson provided this brief tutorial on Metasploit module creation. Rather than incorporating it into the remote buffer overflow tutorial, his work deserves its own, stand-alone post. This post references some of the research provided in the remote buffer overflow tutorial, so you may want to read both to get the full picture. Mooky solved he CTF about which the remote buffer overflow tutorial was written, and I thank him for his help and support!
Metasploit Module Creation
Author: Daniel “Mooky” Robertson
Revisions: 20110521 - to clarify language.
Metasploit module creation is as simple, or as complicated as you want to make it. Some modules require exploit code longer than the entirety of this blog post. Some others, on the other hand, are as little as 5 lines. In this module, I’m going to make a few assumptions. First being that you know the basics of the ruby scripting language. If you don’t, please Google some tutorials. There is a plethora of material, and I learned most of what I know about ruby from doing this myself. Second, I’m going to assume you are using the template provided here.
We’re only going to hit the important parts of the code, and discuss those. The rest of the code is commented, and should be easy to adjust.
First we take our information we have gathered thus far:
Filler: 260 bytes
Location of JMP ESP: 0×77C6AFEE
Max Payload: 1784
Server port: 1337
The first area of importance we want to edit is the Payload area. Payload is the amount of contiguous space we have to insert our payload. Now I’m not going to go too deep into the different types of payload options that Metasploit has. Suffice to say, there are ways to work with less space more efficiently. But in this case, back to our math. We shove 260 bytes of data in the front, then 4 for the memory address that we will place in EIP, and afterward we have 1784 bytes of data. So we have 2 options, 260, or 1784. Well, it is possible to stick a bind-back shell into 260 bytes of space. But the object of this CTF challenge was to stick a meterpreter, and that requires a bit more. So since the space is divided by the 4 bytes for EIP, and the space must be contiguous we discount the first 260 bytes entirely. Our payload space therefore equals 1784. Metasploit uses this data to determine what possible payloads can fit in an exploit module. If a payload size exceeds the space allotted within the module, then it will not be shown.
Note: If you want to test this, try this out. Make the size 260, then enter Metasploit, load the module, and type “show payloads.” Exit Metasploit, then change the number to 1784, and see how many more payload options show up. Meterpreter is all of the sudden, an option, among other things.
The other aspect within Payload we need to consider is BadChars. BadChars are characters that the encoder will avoid in the process of packaging the payload. I’m not going to go into detail about how to figure out which characters are bad. Other people out on the web will do a far better job than I could. But for the sake of this, understand that we are using a TCP connection, basically sending a char array across the wire. A null byte, or “\x00” is a termination character. Therefore we do not want to have our payload include this char in the encoding process.
Next to edit is the Targets section. The format is: “[ 'Dispayed name of the system/version', {'Ret' =>0xReturnMemoryAddress } ]”. The first area in apostrophes is merely a human readable name so when you type “show targets,” you can choose the appropriate system platform of your intended victim. The Ret value is the memory address which we want to stick into EIP. Remember: EIP is the address of the next instruction to be executed, not the actual instruction itself. In our case, the return value we found was 0×77c6afee. In my experience the Ret value has not been case sensitive.
Now we get to skip on to the good stuff. “def exploit”… Doesn’t that just sound nice? Anyway, before I digress too much… the coding….
First things first. “connect” to the target.
Next we build the string that we’ll send to the remote application. We basically already know what the string is we have to build. It would look something like this:
“{260 bytes of filler}{packed return address to stick in EIP}{the shellcode/payload of our choosing}”
Using the variable name buffer, we initially set its value to be 260 “A”’s. The “<<” statements after this basically mean “tack whatever is to the right of this onto the end of the variable to the left.” Next we have to stick in our return address for EIP. But take note we cannot just write it as is!! It HAS to be packed. This is what the .pack(’V') function does for us. Using the [target.ret].pack(’V'), you have the option of simply adding more targets to the appropriate section, and having a single module work for multiple platforms/OS versions. If you pack the return address yourself, then unless you error check what the value of “target” was, you will essentially lock the module to only be applicable to a single OS version.
The “make_nops()” function returns what is called a NOP Sled. NOP stands for NO Operation. In assembly, there are certain function calls that essentially do not do anything. The most famous one is \x90. This basically tells it to call a sleep function for a clock cycle. Certain IDS’ have come to sniff network traffic for the existence of NOPs, and will subsequently catch and prevent the traffic from getting to your intended victim. Therefore other ways of making NOPs have been discovered. These include, but are not limited to doing such things as sending the bytes for the code “xor eax,eax”, or other legitimate instruction that will eat a few clock cycles, but still have the same result: which is will not mess with the execution of our payload. In our case, since we know an exact location for where the call to JMP ESP is located, we don’t need a NOP sled, so I could remove it.
Finally the good stuff… we insert our payload. But we have to tack on the “.encode” function.
So at this point our exploit string, buffer, is completely ready to go. We print a status message(please use these when debugging your code. They make like so much easier.) and we write it to the sock with the sock.put() method. The handler starts whatever process are required to handle any interaction that the attacker and victim will have. In our case it starts the module that will interact with the meterpreter payload we sent to our victim. In other cases it will open a port on your local machine to listen for a reverse_tcp connection, or it will connect to a port that we set up a listening station on in the victim machine. Lastly we disconnect.
Launch of msfconsole, load the module, set your options and exploit!
If all went well, it’s “game over man! GAME OVER!!!!”
[Posted on behalf of Mooky]