Log in

View Full Version : Ruby for Pen-Testers: Announcing Ruby Black Bag


Matasano
March 9th, 2009, 16:17
http://github.com/emonti/rbkb/raw/master/doctor-bag.jpg

This post is part of an informal series discussing the Ruby programming language for various tasks related to penetration testing. Many of us at Matasano do a lot of our coding in Ruby. We like using it when we need to write our own tools (which we do frequently) because it helps us rapidly get off the ground doing all kinds of bespoke things that would be more tedious and time-consuming (or even impossible) using off-the-shelf tools. Go ahead! Call us fanboys (and girls!!!). We can live with it. We want to share some practical tips based on our experiences in this realm.

Introducing, Ruby BlackBag (rbkb).

‘rbkb’ is an ever growing collection of reversing and pen-testing related ruby libraries and tools I’ve been using and evolving for a long time now. It’s at version 0.6.2 by my arbitrary version numbering scheme. I recently decided to gem-ify rbkb and make it public. This was mostly so I could get to it myself more easily when i needed to. A bit to my suprise, it seems to have kicked up some interest. So I figured I should give it a proper announcement here on our blog without further ado.

Rationale

Code:
Disclaimer:
Most of what's in the black bag came from a desire to do less typing.
But there might be a few clever things that were added by accident.
rbkb was originally inspired by Matasano BlackBag ("http://www.matasano.com/log/552/code-release-blackbag-09-binary-protocol-reversing-unix-thingies/") (a set of similar tools written in C).

Here’s a rbkb backup link ("http://github.com/emonti/rbkb/raw/master/reference/blackbag-0.9.1.tgz") to the latest version of blackbag, in-case you’re interested.

Things go into the black bag as they are stolen (as a compliment!) or dreamed up, usually for simplifying some repetetive task or a desire for a new tool.

Along the way, some of tools in the blackbag spirit make their way into ‘rbkb’ that may or may not make it to ‘bkb’ right away (if ever). Similarly some of the things in ‘bkb’ have not yet made it to ‘rbkb’ (and may not).

Command Line Tools

Code:
Usage: b64 [options] <data | blank for stdin> bgrep [options] <subject> <file | blank for stdin> blit [options] <data | blank for stdin> c 100 A; # print 100 A's' crc32 [options] d64 [options] <data | blank for stdin> dedump [options] <input-file | blank for stdin> hexify [options] <data | blank for stdin> len [options] <data | blank for stdin> plugsrv [options] target:tport[@[laddr:]lport] rstrings [options] <file | blank for stdin> slice [options] start (no args when using -r|-x) telson [options] hostort unhexify [options] <data | blank for stdin> urldec [options] <data | blank for stdin> urlenc [options] <data | blank for stdin> xor [options] -k|-s <key> <data | stdin>
Note: See this page ("http://github.com/emonti/rbkb/blob/master/cli_usage.rdoc") for an up to date intro.

Plug

Ruby Black Bag includes several tools for testing network protocols using plugboard proxies. Users of the original Matasano BlackBag may be familiar with the commands ‘bkb replug’, ‘bkb telson’, and ‘bkb blit’. Ruby BlackBag has a similar set of network tools:


‘blit’ : Uses a simple homegrown OOB IPC mechanism (local socket) to communicate with ‘blit-capable’ tools like telson and plugsrv and send data to network endpoints through them. Use ‘blit’ to send raw messages to servers or clients then watch how they respond (see below).
‘telson’ : Similar to ‘bkb telson’. Opens a TCP or UDP client connection which is little more than a receiver for ‘blit’ messages. Use this to pretend to be a client and send raw messages to some service while observing raw replies.
‘plugsrv’ : Similar to ‘bkb replug’. Sits as a reverse TCP proxy between one or more clients and a server. Accepts ‘blit’ messages which can be directed at client or server ends of a conversation. The original ‘replug’ didn’t do this, which makes plugsrv kind-of neat.
Monkey Patches

Much of rbkb is implemented as a bunch of monkeypatches to Array, String, Numeric, Object and other base classes. If this suits your fancy (some people despise monkeypatches, this is not their fancy) then you can ‘require “rbkb”’ from your irb sessions and own scripts. See ‘lib_fun.rdoc’ for more info.

Obligatory Demos:

My dirty secret: I use IRB for like… everything!

The monkey-patches were designed to let you approximate use of the rbkb shell commands from IRB or ruby scripts.

Using the rbkb library in ruby will let you do things like the following:

Code:
# Right, um. this first!
require 'rubygems'
require 'rbkb'
Do stuff with strings:

Code:
## sexify with hexify
foo = "helu foo" #=> "helu foo"
foo.hexify #=> "68656c7520666f6f" ## a little easier to read
foo.hexify(:delim => ' ') #=> "68 65 6c 75 20 66 6f 6f" # and back
_.unhexify #=> "helu foo" ## break out your hexdump -C styles
foodump = "helu foo".hexdump(ut => StringIO.new)
#=> "00000000 68 65 6c 75 20 66 6f 6f |helu foo|&#92;n00000008&#92;n"
puts foodump
# 00000000 68 65 6c 75 20 66 6f 6f |helu foo|
# 00000008
# => nil
foo.hexdump(ut => $stdout)
# 00000000 68 65 6c 75 20 66 6f 6f |helu foo|
# 00000008
# => nil ## reverse a hexdump
foodump.dehexdump #=> "helu foo" ## 'strings' like /usr/bin/strings
dat = File.read("/bin/ls"
pp dat.strings
# [[4132, 4143, :ascii, "__PAGEZERO00"],
# [4188, 4195, :ascii, "__TEXT00"],
# ...
# [72427, 72470, :ascii, "*Apple Code Signing Certification Authority"],
# [72645, 72652, :ascii, "X[N~EQ "]] ## look for stuff in binaries
dat.bgrep("__PAGEZERO"
#=> [[4132, 4142, "__PAGEZERO"], [40996, 41006, "__PAGEZERO"]] dat.bgrep(0xCAFEBABE.to_bytes) #=> [[0, 4, "&#92;312&#92;376&#92;272&#92;276"]]
Do stuff with numbers:

Code:
## Do you have an irrational distaste for pack/unpack? I do.
0xff.to_bytes #=> "000000&#92;377"
be = 0xff.to_bytes(:big) #=> "000000&#92;377"
le = 0xff.to_bytes(:little) #=> "&#92;377000000"
le16 = 0xff.to_bytes(:little,2) #=> "&#92;37700" ## Strings can go the other way too
[be, le, le16].map {|n| n.dat_to_num(:big) } # default
#=> [255, 4278190080, 65280]
[be, le, le16].map {|n| n.dat_to_num(:little) }
#=> [4278190080, 255, 255] ## Calculate padding for a given alignment
10.pad(16) #=> 6
16.pad(16) #=> 0
30.pad(16) #=> 2
32.pad(16) #=> 0
Interact with ‘telson’ and ‘plugsrv’ directly from IRB:

Code:
## In a separate window from your irb session do something like:
#
# $ telson rubyforge.com:80 -r
# ** BLITSRV-127.0.0.1:25195(TCP) Started
# ** TELSON-....:58118(TCP) CONNECTED TO PEER-....:80(TCP) ## You can blit any string from within IRB! ## A minor setup step is required... (I put this in my .irbrc)
Plug::Blit.blit_init #=> nil "GET / HTTP/1.0&#92;r&#92;n&#92;r&#92;n".blit #=> 28
## Watch the basic HTTP request get made and responded to in the
## other window. ("GET /"+ "A"*30 +" HTTP/1.0&#92;r&#92;n&#92;r&#92;n".blit #=> 58
## Watch the bogus HTTP request get made and responded to in the
## other window.
Some simple web encoding helpers:

Code:
xss="" # URL percent-encode stuff
xss.urlenc
#=> "%3cscript%3ealert%28%27helu%3a%20%27%20%2b%20document.
# cookie%29%3c%2fscript%3e" # Base64 encode stuff
_.b64
#=> "JTNjc2NyaXB0JTNlYWxlcnQlMjglMjdoZWx1JTNhJTIwJTI3JTIwJTJiJTIwZG9
# jdW1lbnQuY29va2llJTI5JTNjJTJmc2NyaXB0JTNl" ## And back
_.d64
#=> "%3cscript%3ealert%28%27helu%3a%20%27%20%2b%20document.
# cookie%29%3c%2fscript%3e" _.urldec
#=> ""
Miscellaneous stuff:

Code:
# featuring rediculous laziness!
0x41.printable? #=> true
0x01.printable? #=> false # Make random gobbledygook and insults
"helu foo".randomize #=> "ouofleh "
"helu foo".randomize #=> "foul hoe"
Pretend (badly) to be smart:

Code:
# Cletus say's he's "sneaky"
cletus = "my secrets are safe".xor("sneaky"
#=> "3627E22163201&#92;v2122K3001&#92;vE22&#92;n3726" # Only not really so sneaky
cletus.xor "my secrets" #=> "sneakysnea&a!x qxzb"
cletus.xor "my secrets are" #=> "sneakysneakysn(k*ls"
cletus.xor "sneaky" #=> "my secrets are safe" # Now make Cletus feel worse. With... MATH!
# (ala entropy scores)
"A".entropy #=> 0.0
"AB".entropy #=> 1.0
"BC".entropy #=> 1.0
(0..255).map {|x| x.chr}.join.entropy #=> 8.0 # "You see, Cletus, you might have done this..."
sdat = "my secrets are very secret "*60
require 'openssl'
c = OpenSSL::Cipher::Cipher.new("aes-256-cbc"
c.encrypt
c.key = Digest::SHA1.hexdigest("sneaky"
c.iv = c.random_iv # "So, Cletus, when you say 'sneaky'... this is exactly how 'sneaky' you are"
c.update(sdat).entropy #=> 7.64800383393901
sdat.xor("sneaky".entropy #=> 3.77687372599433
sdat.entropy #=> 3.07487577558377
Note: This page ("http://github.com/emonti/rbkb/blob/master/lib_usage.rdoc") may have more up to date information depending on when you read this.

I recommend installing the gem and clicking around rdoc if you’re interested in more of these little helpers and how some of the cli tools use the library. Time permitting, my goal is to try to keep the docs useful and up to date.

Interested?

Head over to the github page for ‘rbkb’ ("http://www.github.com/emonti/rbkb").

Comments Welcome

Constructive comments and feedback are welcome. Just remember this just kinda sprang up out of project work. There are no doubt lots of bugs and rough edges but I’m interested in polishing it up.



http://www.matasano.com/log/1473/ruby-for-pen-testers-announcing-ruby-black-bag/