CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/docs/metasploit-framework.wiki/Get-Started-Writing-an-Exploit.md
Views: 11766

On this page

The real kung-fu behind exploit development isn't actually about which language you choose to build it; it's about your precise understanding of how input is processed by the application you're debugging, and how to gain control by manipulating it. That's right; the keyword is "debugging." Your binjitsu (reverse-engineering) is where the real kung-fu is. However, if your goal isn't just about popping a calculator, but actually want to weaponize, to maintain, and to provide use in the practical world, you need a development framework. And this is where Metasploit comes in. It's a framework that's free and open-source, actively contributed by researchers around the world. So when you write a Metasploit exploit, you don't have to worry about any dependency issues, or having the wrong version, or not having enough payloads for different pentesting scenarios to choose from, etc. The idea is all you need to do is focus on building that exploit, and nothing more.

Plan your module

First, ask yourself will exploiting this vulnerability result in executing a payload? If not, then despite exploiting a vulnerability, for Metasploit's purposes the module would fall into the [[auxiliary|How-to-get-started-with-writing-an-auxiliary-module]] category.

Unlike writing a proof-of-concept, when you write a Metasploit module, you need to think about how users might use it in the real world. Stealth is usually an important element to think about. Can your exploit achieve code execution without dropping a file? Can the input look more random, so it's more difficult to detect? How about obfuscation? Is it generating unnecessary traffic? Can it be more stable without crashing the system?

Try to be precise about exploitable requirements. Usually, a bug is specific to a range of versions or even builds. If you can't automatically check that, you need to at least mention it in the description somewhere.

Some of your exploit's techniques might also be application-specific. For example, you can take advantage of a specific behavior in the application to generate heap allocations the way you want, but maybe it's noisier in the newer version, so that gives you some stability issues. Does it need a 3rd-party component to work that may not even be installed by everyone? Even if it is, is the component revised often enough that it could make your exploit less reliable?

Know that in the real world, your exploit can break or fail in a lot of different ways. You should try to find out and fix it during the development and testing phase before learning the hard way.

Ranking

As you can see, reliability is important to Metasploit, and we try to be more friendly about this for the users. I know what you're thinking: "Well, if they're using the exploit, they should understand how it works, so they know what they're getting themselves into." In the perfect world, yes. Knowing how a vulnerability works or how an exploit works will only benefit the user, but you see, we don't live in the perfect world. If you're in the middle of a penetration test, it's very unlikely to always find the time to recreate the vulnerable environment, strip the exploit to the most basic form to debug what's going on, and then do testing. Chances are you have a tight schedule to break into a large network, so you need to use your time carefully. Because of this, it's important to at least have a good description and good references for the module. And of course, a ranking system that can be trusted.

The Metasploit Framework has seven different rankings to indicate how reliable an exploit is. See [[Exploit Ranking]] for more details.

Template

If you have read this far, we think you are pretty impressive because it's a lot to digest. You are probably wondering why we haven't had a single line of code to share in the writeup. Well, as you recall, exploit development is mostly about your reversing skills. If you have all that, we shouldn't be telling you how to write an exploit. What we've done so far is hopefully get your mindset dialed-in correctly about what it means to become a Metasploit exploit developer for the security community; the rest is more about how to use our mixins to build that exploit. Well, there are A LOT of mixins, so it's impossible to go over all of them in a single page, so you must either read the API documentation, existing code examples, or look for more wiki pages we've written to cover specific mixins.

For example, if you're looking for a writeup about how to interact with an HTTP server, you might be interested in: [[How to send an HTTP Request Using HTTPClient|./How-to-write-a-browser-exploit-using-HttpServer.md]]. If you're interested in browser exploit writing, definitely check out: [[How to write a browser exploit using BrowserExploitServer|./How-to-write-a-browser-exploit-using-BrowserExploitServer.md]], etc.

But of course, to begin, you most likely need a template to work with, and here it is. We'll also explain how to fill out the required fields:

## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking def initialize(info = {}) super( update_info( info, 'Name' => '[Vendor] [Software] [Root Cause] [Vulnerability type]', 'Description' => %q{ Say something that the user might need to know }, 'License' => MSF_LICENSE, 'Author' => [ 'Name' ], 'References' => [ [ 'URL', '' ] ], 'Platform' => 'win', 'Targets' => [ [ 'System or software version', { 'Ret' => 0x41414141 # This will be available in `target.ret` } ] ], 'Payload' => { 'BadChars' => "\x00" }, 'Privileged' => false, 'DisclosureDate' => '', 'DefaultTarget' => 0, 'Notes' => { 'Stability' => [CRASH_SAFE], 'Reliability' => [REPEATABLE_SESSION], 'SideEffects' => [ARTIFACTS_ON_DISK, IOC_IN_LOGS] }, ) ) end def check # For the check command end def exploit # Main function end end
  • Name - The Name field should begin with the name of the vendor, followed by the software. Ideally, the "Root Cause" field means which component or function the bug is found. And finally, the type of vulnerability the module is exploiting.

  • Description - The Description field should explain what the module does, things to watch out for, specific requirements, the more, the better. The goal is to let the user understand what he's using without the need to actually read the module's source and figure things out. And trust me, most of them don't.

  • Author field is where you put your name. The format should be "Name ". If you want to have your Twitter handle there, leave it as a comment, for example: "Name # handle"

  • References - The References field is an array of references related to the vulnerability or the exploit. For example, an advisory, a blog post, etc. Make sure you use known reference identifiers -- see [[Module reference identifiers]] for a list.

  • Platform - The Platform field indicates what platforms are supported, for example: win, linux, osx, unix, bsd.

  • Targets - The Targets field is an array of systems, applications, setups, or specific versions your exploit is targeting. The second element or each target array is where you store specific metadata about that target, for example, a specific offset, a gadget, a ret address, etc. When a target is selected by the user, the metadata is loaded and tracked by a "target index", and can be retrieved by using the target method.

  • Payloads - The Payloads field specifies how the payload should be encoded and generated. You can specify: Space, SaveRegisters, Prepend, PrependEncoder, BadChars, Append, AppendEncoder, MaxNops, MinNops, Encoder, Nop, EncoderType, EncoderOptions, ExtendedOptions, EncoderDontFallThrough.

  • DisclosureDate - The DisclosureDate is about when the vulnerability was disclosed in public, in the format of: "M D Y". For example: "Apr 04 2014"

  • Notes - The Notes field is a hash always containing three keys. The value of each key is an array of constants. The list of available constants can be found in the [[Definition of Module Reliability Side Effects and Stability|./Definition-of-Module-Reliability-Side-Effects-and-Stability.md]]. The key should be present even if the array is empty.

    • Stability - The Stability field describes how the exploit affects the system it's being run on, ex: CRASH_SAFE, CRASH_OS_DOWN

    • Reliability - The Reliability field describes how reliable the session is that gets returned by the exploit, ex: REPEATABLE_SESSION, UNRELIABLE_SESSION

    • SideEffects - The SideEffects field describes the side effects cause by the exploit that the user should be aware of, ex: ARTIFACTS_ON_DISK, IOC_IN_LOGS, ACCOUNT_LOCKOUTS.

Your exploit should also have a check method to support the check command, but this is optional in case it's not possible.

And finally, the exploit method is like your main method. Start writing your code there.

An example exploit module is also available: example.rb

Basic git commands

Metasploit no longer uses svn for source code management. Instead, we use git, so knowing some tricks with git go a long way. We're not here to lecture you about how awesome git is; we know it has a learning curve, and it's not surprising to find new users making mistakes. Every once a while, your git "rage" will kick in, and we understand. However, it's important for you to take advantage of branching.

Every time you make a module or make some changes to existing code, you should not do so on the default master branch. Why? Because when you do a msfupdate, which is Metasploit's utility for updating your repository, it will do a git reset before merging the changes, and all your code goes away.

Another mistake people tend to do is have all the changes on master before submitting a pull request. This is a bad idea because most likely; you're submitting other crap you don't intend to change, or you're probably asking us to merge other unnecessary commit histories when there only needs to be one commit. Thanks for contributing your module to the community, but no thanks to your crazy commit history.

So as a habit, when you want to make something new, or change something, begin with a new branch that's up to date to master. First off, make sure you're on master. If you do a git status it will tell you what branch you're currently on:

$ git status # On branch upstream-master nothing to commit, working directory clean

Ok, now do a git pull to download the latest changes from Metasploit:

$ git pull Already up-to-date.

At this point, you're ready to start a new branch. In this case, we'll name our new branch "my_awesome_branch":

$ git checkout -b my_awesome_branch Switched to a new branch 'my_awesome_branch'

And then you can go ahead and add that module. Make sure it's in the appropriate path:

$ git add [module path]

When you decide to save the changes, commit (if there's only one module, you can do git commit -a too so you don't have to type the module path. Note -a really means EVERYTHING):

$ git commit [module path]

When you're done, push your changes, which will upload your code to your remote branch "my_awesome_branch". You must push your changes in order to submit the pull request or share it with others on the Internet.

$ git push origin my_awesome_branch

References