Files
metasploit-gs/dev/Metasploit-Development-Environment.md
T

386 lines
18 KiB
Markdown
Raw Normal View History

2012-05-03 17:07:12 -05:00
# Metasploit Development Environment
2012-05-03 17:06:39 -05:00
2012-05-04 11:59:45 -07:00
The Metasploit Framework is a pretty complex hunk of software, at least according to [Ohloh](http://www.ohloh.net/p/metasploit). So, getting started with development can be daunting even for veteran exploit developers. This page attempts to demystify the process of setting up your Metasploit development environment to submitting a "pull request" to get your exploit into the standard distribution.
2012-05-03 16:01:23 -05:00
This documentation assumes you're on some recent version of Ubuntu Linux. If not, then you're going to be on your own on how to get all your dependencies lined up. If you've successfully set up a development environment on something non-Ubuntu, and you'd like to share, let us know and we'll link to your tutorial from here.
2012-05-03 16:45:51 -05:00
Throughout this documentation, we'll be using the example user of "Fakey McFakepants," who has the e-mail address of "mcfakepants@packetfu.com" and a login username of "fakey."
2012-05-03 16:01:23 -05:00
2012-05-04 10:15:06 -05:00
<h2 id="apt">Apt-Get Install</h2>
2012-05-03 16:01:23 -05:00
2012-05-03 17:25:05 -05:00
The bare minimum for working on Metasploit effectively is:
2012-05-03 17:06:39 -05:00
2012-05-03 17:25:05 -05:00
````bash
$ sudo apt-get -y install \
2012-05-03 16:01:23 -05:00
build-essential zlib1g zlib1g-dev \
libxml2 libxml2-dev libxslt-dev locate \
libreadline6-dev libcurl4-openssl-dev git-core \
libssl-dev libyaml-dev openssl autoconf libtool \
ncurses-dev bison curl wget postgresql \
2012-09-23 08:34:25 -07:00
postgresql-contrib libpq-dev \
libapr1 libaprutil1 libsvn1 \
libpcap-dev
2012-05-03 16:01:23 -05:00
````
2012-05-03 17:06:39 -05:00
2012-05-04 11:59:45 -07:00
Note that this does **not** include an appropriate text editor or IDE, nor does it include the Ruby interpreter. We'll get to that in a second.
2012-05-03 16:01:23 -05:00
2012-05-04 12:12:18 -05:00
<h2 id="rvm">Getting Ruby</h2>
2012-05-03 16:01:23 -05:00
2013-01-28 12:27:21 -08:00
Many standard distributions of Ruby are lacking in one regard or another. Lucky for all of us, Wayne Seguin's RVM has become quite excellent at providing several proven Ruby interpreters. Visit [https://rvm.io/](https://rvm.io/) to read up on it or just trust that it'll all work out with a simple:
2012-05-03 16:01:23 -05:00
````bash
2013-01-28 12:27:21 -08:00
$ \curl -L https://get.rvm.io | bash -s stable --ruby
2012-05-03 16:01:23 -05:00
````
2013-01-28 12:27:21 -08:00
Note the *lack* of sudo; you will nearly always want to install this as a regular user, and not as root.
Sometimes, depending on your particular platform, this incantation may not be reliable. This is nearly identical, but more typing:
2012-09-11 14:39:16 -07:00
````bash
2013-01-28 12:27:21 -08:00
$ \curl -o rvm.sh -L get.rvm.io && cat rvm.sh | bash -s stable
2012-09-11 14:39:16 -07:00
````
Also, if you're sketchy about piping a web site directly to bash, you can perform each step individually, without the &&:
````bash
2013-01-28 12:27:21 -08:00
$ \curl -o rvm.sh -L get.rvm.io
2012-09-11 14:39:16 -07:00
$ less rvm.sh
$ cat rvm.sh | bash -s stable
````
2013-01-28 12:27:21 -08:00
Next, load the RVM scripts by either opening a new terminal window, or just run:
2012-05-03 16:01:23 -05:00
````bash
2012-05-03 16:43:20 -05:00
$ source ~/.rvm/scripts/rvm
2012-05-03 16:01:23 -05:00
````
2013-01-28 12:27:21 -08:00
RVM by default installs a sensible 1.9.3 patchlevel for Ruby these days. No more installing Ruby 1.8 to bootstrap to 1.9. However, you will need to tick the `Run command as login shell` on the default profile of gnome-terminal (assuming stock Ubuntu), or else you will get the error message that [RVM is not a function](http://stackoverflow.com/questions/9336596/rvm-installation-not-working-rvm-is-not-a-function).
Assuming all goes as planned, you should end up with something like this in your shell:
2012-05-03 16:01:23 -05:00
2012-05-03 16:43:20 -05:00
[[/screens/rvm02.png]]
2013-01-28 12:27:21 -08:00
*TODO: update this screenshot with the new docs, namely new rvm sequence and versions*
2012-05-03 16:01:23 -05:00
Once that's finished, it would behoove you to set your default ruby and gemset, as described [in this gist](https://gist.github.com/2625441) by [@claudijd](https://github.com/claudijd) . What I use is:
````bash
2013-02-17 07:46:25 -08:00
$ rvm use --create --default 1.9.3-p385@msf
````
2013-02-17 07:46:25 -08:00
This will set a default gemset to "msf" which you will be populating a little bit later.
2012-05-04 12:12:18 -05:00
<h2 id="editor">Your Editor</h2>
2012-05-03 17:25:05 -05:00
2013-01-28 13:10:31 -08:00
Once that's done, you can set up your preferred editor. Far be it from us to tell you what editor you use -- people get really attached to these things for some reason. An informal straw poll shows that many Metasloit developers use [vim](http://www.vim.org/), some use [Rubymine](https://www.jetbrains.com/ruby/), and a few use [emacs](http://i.imgur.com/dljEqtL.gif). For this document, let's say you're a vim kind of person, since it's free.
2013-01-28 13:01:17 -08:00
First, get vim, your usual way. Vim-gnome is a pretty safe bet.
````bash
2013-02-17 07:42:12 -08:00
$ sudo apt-get install vim-gnome -y
2013-01-28 13:01:17 -08:00
````
Next, get Janus. Janus is a set of super-useful plugins and conveniences for Vim. You can read up on it here: https://github.com/carlhuda/janus . Or, again, just trust that Things Will Be Fine, and:
````bash
2013-02-17 07:42:12 -08:00
$ curl -Lo- https://bit.ly/janus-bootstrap | bash
2013-01-28 13:01:17 -08:00
````
This will checkout a version of Janus (using Git) to your ~/.vim directory. Yep, you now have a git repo in one of your more important dot-directories.
2013-02-17 07:42:12 -08:00
Finally, I have a very small set of defaults, here: https://gist.github.com/4658778 . Drop this in your `~/.vimrc.after` file. Note, the important bit is our slightly wacky use of hard tabs, as prescribed in the [HACKING](https://github.com/rapid7/metasploit-framework/blob/master/HACKING) guide.
2013-01-28 13:01:17 -08:00
*TODO: Add Rubymine docs, add screenshots for this*
2012-05-03 16:01:23 -05:00
2012-05-04 12:12:18 -05:00
<h2 id="github">Using GitHub</h2>
2012-05-03 16:01:23 -05:00
2012-05-04 12:12:18 -05:00
The entire Metasploit code base is hosted here on GitHub. If you have an old Redmine account over at dev.metasploit.com, that's not going to do much for you since the switch-over -- you're going to need a GitHub account. That process is pretty simple.
2012-05-03 17:25:05 -05:00
### Find the Signup button
[[/screens/new01.png]]
2012-05-04 11:59:45 -07:00
### Create a free user account
2012-05-03 17:25:05 -05:00
[[/screens/new02.png]]
### Come up with a decent username and password
2012-05-03 17:25:26 -05:00
[[/screens/new04.png]]
2012-05-03 17:25:05 -05:00
2012-05-03 17:48:27 -05:00
None of this is exactly rocket science.
2012-05-03 16:01:23 -05:00
2012-05-04 10:25:18 -05:00
<h2 id="ssh">SSH for GitHub</h2>
2012-05-03 17:48:27 -05:00
2012-05-04 11:59:45 -07:00
After that's done, you need to set up an SSH key to associate with your new GitHub identity (this step is **not** optional, so good on GitHub for forcing this minimal level of security).
2012-05-03 17:48:27 -05:00
### Create a new key
2012-05-04 11:59:45 -07:00
We recommend you set up a new SSH key pair to associate with GitHub, rather than reuse that same old key you have in 50 other authorized_keys files around the world. Why not just start fresh? It's easy and fun:
2012-05-03 17:48:27 -05:00
````bash
# mkdir ~/.ssh # If you don't already have one
$ ssh-keygen -t rsa -C "mcfakepants@packetfu.com"
2012-05-03 17:48:27 -05:00
````
Just follow the prompts, pick a name for your key pair (I use "id_rsa.github"), set a password, and you should end up with something like:
[[/screens/ssh01.png]]
### Add your key
2012-05-04 11:59:45 -07:00
Next, go to [https://github.com/settings/ssh](https://github.com/settings/ssh) (which can be navigated to via _Account Settings > SSH Keys_), and click "Add SSH key":
2012-05-03 17:48:27 -05:00
[[/screens/ssh02.png]]
2012-05-04 11:59:45 -07:00
You'll be presented with a screen to copy-paste your public SSH key (not the private one!). The easiest thing to do is to cat your newly created key, select, and copy-paste it:
2012-05-03 17:48:27 -05:00
[[/screens/ssh03.png]]
[[/screens/ssh04.png]]
### Confirm your key
2012-05-04 11:59:45 -07:00
After that's done, you'll have a key associated, and you'll get e-mail about it. Eyeball the fingerprint and make sure it matches up.
2012-05-03 17:48:27 -05:00
[[/screens/ssh05.png]]
2012-05-04 11:59:45 -07:00
The real moment of truth is when you test your SSH key. If you named it something funny like I did, don't forget the -i flag, use -T to avoid allocating a terminal (you won't get one anyway). Also note that you are going to literally use "git@github.com" as the username (not your name or anything like that).
2012-05-03 17:48:27 -05:00
````bash
$ ssh -i ~/.ssh/id_rsa.github -T git@github.com
````
2012-05-04 11:59:45 -07:00
Your console should look like this:
2012-05-03 17:48:27 -05:00
[[/screens/ssh07.png]]
### Alias GitHub in .ssh/config
2012-05-04 11:59:45 -07:00
I hate having to remember usernames for anything anymore, so I've gotten in the habit of creating Host entries for lots of things in my ~/.ssh/config file. You should try it, it's fun, and it can shorten most of your ssh logins to two words.
2012-05-03 17:48:27 -05:00
2012-05-04 11:59:45 -07:00
For the rest of these instructions, I'm going to assume you have something like this in your config file:
2012-05-03 17:48:27 -05:00
````config
Host github
Hostname github.com
User git
PreferredAuthentications publickey
IdentityFile ~/.ssh/id_rsa.github
````
2012-05-04 11:59:45 -07:00
To check that it works, just `ssh -T github`, and your result should look like this:
2012-05-03 17:48:27 -05:00
[[/screens/ssh10.png]]
### Minimal Git config
Finally, you're ready to set up your local git config file, if you haven't already:
````bash
git config --global user.name "Fakey McFakepants"
git config --global user.email "mcfakepants@packetfu.com"
````
2012-05-03 18:01:14 -05:00
2012-05-04 11:59:45 -07:00
Cat your ~/.gitconfig to ensure you have that set (and remember, your e-mail address needs to match the address you set back when you ssh-keygen'ed):
2012-05-03 17:48:27 -05:00
2012-05-04 09:34:46 -05:00
[[/screens/ssh11.png]]
2012-05-03 16:01:23 -05:00
2012-05-04 10:24:34 -05:00
<h1 id="git">Working with Git</h2>
2012-05-03 16:01:23 -05:00
2012-05-04 11:59:45 -07:00
The rest of this document will walk through the usual use case of working with Git and GitHub to get a local source checkout, commit something new, and get it submitted to be part of the Metasploit Framework distribution.
The example here will commit the file _2.txt_ to _test/git/_ , but imagine that we're committing some new module like _ms_12_020_code_exec.rb_ to _modules/exploits/windows/rdp/_.
2012-05-03 18:01:14 -05:00
2012-05-04 10:26:27 -05:00
<h2 id="fork">Forking Metasploit</h2>
2012-05-04 10:10:25 -05:00
2012-05-04 11:59:45 -07:00
Now that you have a GitHub account, it's time to fork the Metasploit Framework. First, go to https://github.com/rapid7/metasploit-framework, and click the Fork button:
2012-05-04 10:10:25 -05:00
[[/screens/fork01.png]]
2012-05-04 11:59:45 -07:00
Hang out for a few seconds, and behold the animated "Hardcore Forking Action":
2012-05-04 10:10:25 -05:00
[[/screens/fork02.png]]
After that's done, switch back over to your terminal, make a sub-directory for your git clones, and use your previously defined .ssh/config alias to clone up a copy of Metasploit. Note that usernames on GitHub are case-sensitive; McFakePants is different from mcfakepants.
2012-05-04 10:10:25 -05:00
````bash
$ mkdir git
$ cd git
$ git clone github:mcfakepants/metasploit-framework.git
2012-05-04 10:10:25 -05:00
````
2013-01-31 11:32:56 -08:00
2012-05-04 11:59:45 -07:00
You should end up with a complete copy of Metasploit in the metasploit-framework sub-directory:
2012-05-04 10:10:25 -05:00
[[/screens/fork03.png]]
<h3 id="prompt">Setting Your Prompt</h3>
2012-05-04 10:10:25 -05:00
Now might be a good time to decorate your prompt. At the minimum, you will want [something like this](https://gist.github.com/2555109) in your ~/.bash_aliases to let you know on the prompt which branch you're in, if you're in a git repo. I have no idea how else you would be able to track what branch you're in, honestly.
2012-05-04 10:10:25 -05:00
In the end, you'll have a prompt that looks like:
2012-05-04 10:10:25 -05:00
````
(master) fakey@mazikeen:~/git/metasploit-framework$
````
2012-05-04 10:10:25 -05:00
where the master bit changes depending on what branch you're in.
2012-05-04 10:10:25 -05:00
2012-05-04 10:24:34 -05:00
## Start Metasploit
2012-05-04 10:10:25 -05:00
Now that you have a source checkout of Metasploit, and you have all your prerequisite components from apt and rvm, you should be able to run it straight from your git clone with `./msfconsole -L`:
2012-05-04 10:27:29 -05:00
[[/screens/fork06.png]]
2012-05-03 16:01:23 -05:00
Note that if you need resources that only root has access to, you'll want to run `rvmsudo ./msfconsole -L` instead.
2012-05-04 10:24:34 -05:00
<h2 id="sync">Keeping in sync</h2>
2012-05-04 11:09:24 -05:00
One of the main reasons to use Git and GitHub is this whole idea of branching in order to keep all the code changes straight. In other source control management systems, branching quickly becomes a nightmare, but in Git, branching happens all the time.
You start off with your first branch, "master," which you pretty much never work in. That branch's job is to keep in sync with everyone else. In the case of Metasploit, "everyone else" is `rapid7/metasploit-framework/branches/master`. Let's see how you can keep up with the upstream changes via regular rebasing from upstream's master branch to your master branch.
2012-05-04 11:02:27 -05:00
### Check out the upstream master branch
This is pretty straightforward. From your local branch on the command line, you can:
````bash
$ git remote add upstream git://github.com/rapid7/metasploit-framework.git
$ git fetch upstream
$ git checkout upstream/master
2012-05-04 11:02:27 -05:00
````
This lets you peek in on upstream, after giving a warning about being in the "detatched HEAD" state (don't worry about that now). From here you can do things like read the change log:
````bash
$ git log --pretty=oneline --name-only -3
````
It should all look like this in your command window:
[[/screens/git02.png]]
2012-05-04 11:59:45 -07:00
It's pretty handy to have this checkout be persistent so you can reference it later. So, type this:
2012-05-04 11:02:27 -05:00
````bash
$ git checkout -b upstream-master
````
And this will create a new local branch called "upstream-master." Now, switch back to your master branch and fetch anything new from there:
2012-05-04 11:02:27 -05:00
````bash
$ git checkout master
$ git fetch
````
And finally, rebase against your local checkout of the upstream master branch:
````bash
$ git rebase upstream-master
````
2012-05-04 11:59:45 -07:00
Rebasing is the easiest way to make sure that your master branch is identical to the upstream master branch. If you have any local changes, those are "rewound," all the remote changes get laid down, and then your changes get reapplied. It should all look like this:
2012-05-04 11:02:27 -05:00
[[/screens/git03.png]]
Of course, you might occasionally run into rebase conflicts, but let's just assume you won't for now. :) Resolving merge conflicts is a little beyond the scope of this document, but the [Git Community Book](http://book.git-scm.com/) should be able to help. In the meantime, we're working up another wiki page to deal specifically with the details of merging, rebasing, and conflict resolution.
> Note that you can skip the checkout to a local branch and simply always `git rebase upstream/master` as well, but you then lose the chance to review the changes in a local branch first -- this can make unwinding merge problems a little harder.
2012-05-04 11:02:27 -05:00
2012-05-04 11:26:54 -05:00
> A note on terminology: In Git, we often refer to "origin" and "master," which can be confusing. "Origin" is a remote repository which contains all of **your** branches. "Master" is a branch of the source code -- usually the first branch, and the branch you don't tend to commit directly to.
2012-05-04 11:02:27 -05:00
> "Origin" **isn't** Rapid7's repository -- we usually refer to that repo as "Upstream." In other words, "upstream" is just another way of referring to the "rapid7" remote.
2012-05-04 11:25:51 -05:00
2012-05-04 11:26:54 -05:00
> Got it? "Origin" is your repo up at GitHub, "upstream" is Rapid7's GitHub repo, and "master" is the primary branch of their respective repos.
2012-05-04 11:02:27 -05:00
2012-05-04 11:09:24 -05:00
All right, moving on.
2012-05-04 11:02:27 -05:00
### Syncing changes
Any time you rebase from upstream (like just now), you're likely to bring in new changes because we're committing stuff all the time. This means that when you rebase, your local branch will be ahead of your remote branch. To get your remote fork up to speed:
2012-05-04 11:02:27 -05:00
````bash
$ git push origin master
````
It should all look something like this:
[[/screens/git04.png]]
2012-05-04 11:09:24 -05:00
Switch back to your browser, refresh, and you should see the new changes reflected in your repo immediately (those GitHub guys are super fast):
2012-05-04 11:02:27 -05:00
[[/screens/git05.png]]
2012-05-04 10:24:34 -05:00
<h2 id="pull">Pull Requests</h2>
2012-05-03 16:01:23 -05:00
Finally, let's get to pull requests. That's why you're reading all this, after all. Thanks to [@corelanc0d3r](https://github.com/corelanc0d3r) for initially writing this all down from a contributor's perspective.
2012-05-04 12:05:10 -05:00
First, create a new branch from your master branch:
2012-05-04 12:05:10 -05:00
````bash
git checkout master
2012-05-04 12:05:10 -05:00
git checkout -b module-ms12-020
````
2012-05-04 11:59:45 -07:00
Write the module, putting it in the proper sub-directory. Once it's all done and tested, add the module to your repo and push it up to origin:
2012-05-04 12:05:10 -05:00
````bash
git add <path to new module>
git commit -m "added MS012-020 RCE for Win2008 R2"
git push origin module-ms12-020
````
**Please make sure your commit messages conform to this guide: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html**. TL;DR - First line should be 50 characters or less, then a blank line, then more explanatory text if necessary, with lines no longer than 72 characters.
2012-05-04 12:05:10 -05:00
That command set should look something like this:
[[/screens/pull02.png]]
2012-05-04 11:59:45 -07:00
In your browser, go to your newly created branch, and click Pull Request.
2012-05-04 12:05:10 -05:00
[[/screens/pull03.png]]
This will automatically reference upstream's master as the branch to land your pull request, and give you an opportunity to talk about how great your module is, what it does, how to test it, etc.
[[/screens/pull04.png]]
Once you click Send Pull Request, you'll be on upstream's pull queue (in this case, mcfakepants has created pull request #356, which is one of 17 open pull requests).
[[/screens/pull05.png]]
Depending on the position of the stars, someone from the Metasploit core development team will review your pull request, and land it, like so:
[[/screens/pull06.png]]
2012-05-04 11:59:45 -07:00
Now, keep in mind that actually [[landing a pull request]] is a little more involved than just taking your commit and applying it directly to the tree. Usually, there are a few changes to be made, sometimes there's some back and forth on the pull request to see if some technique works better, etc. To have the best chance of actually getting your work merged, you would be wise to consult the [[Acceptance Guidelines]].
2012-05-04 12:05:10 -05:00
The upshot is, what's committed to Metasploit is rarely exactly what you initially sent, so once the change is committed, you'll want to rebase your checkout against master to pick up all the changes. If you've been developing in a branch (as you should), you shouldn't hit any conflicts with that.
### Cleaning up
Now that everything's committed and you're rebased, if you'd like to clean out your development branches, you can just do the following:
````bash
$ git branch -D module-ms12-020
$ git push origin :module-ms12-020
````
Note that Git branches are cheap (nearly free, in terms of disk space), so this shouldn't happen too terribly often.
2012-05-03 16:01:23 -05:00
***
<h2 id="rspec">Rspec Tests</h2>
2013-02-17 11:20:34 -08:00
We are slowly lurching toward a normal testing environment, and will soon be requiring spec tests to validate changes to the framework. To get in the habit now, run the standard set of tests against your local Metasploit branch. First, make sure you have all the gems installed, then run the `rake spec` task.
2013-02-17 11:20:34 -08:00
````
$ gem bundle install
$ rake spec # Do this in the top-level Metasploit root
````
For more on rpsec (which is the de-facto testing standard for Ruby projects), see http://rspec.info/ . To add tests, drop them someplace sensible in the `spec` directory, and name your tests `whatever_spec.rb`.
Adding rspec tests with your functional changes significantly increases your chances of getting your pull request landed in a timely manner.
2012-05-04 12:05:10 -05:00
## Thanks and Feedback
First off, thanks to [@corelanc0d3r](https://github.com/corelanc0d3r) for articulating much of this. If you have suggestions for this wiki, please let [@todb-r7](https://github.com/todb-r7) know.
2012-05-04 12:05:10 -05:00
This document should be enough to get your Metasploit development career started, but it doesn't address huge areas of Git source control management. For that, you'll want to look at the [Git Community Book](http://book.git-scm.com/), the many answered questions on [StackOverflow](http://stackoverflow.com/questions/tagged/git), and the [git cheat sheet](http://cheat.errtheblog.com/s/git/).