Adds the sniffer extension for testing
git-svn-id: file:///home/svn/framework3/trunk@6762 4d416f70-5f16-0410-b530-b9f4589650daunstable
parent
608ca7aae8
commit
82cf85680c
Binary file not shown.
|
@ -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
|
|
@ -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
|
|
@ -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
|
Loading…
Reference in New Issue