Class: Rex::Post::Meterpreter::Ui::Console::CommandDispatcher::Sniffer

Inherits:
Object
  • Object
show all
Includes:
Rex::Post::Meterpreter::Ui::Console::CommandDispatcher
Defined in:
lib/rex/post/meterpreter/ui/console/command_dispatcher/sniffer.rb

Overview

Packet sniffer extension user interface.

Constant Summary collapse

Klass =
Console::CommandDispatcher::Sniffer

Instance Attribute Summary

Attributes included from Ui::Text::DispatcherShell::CommandDispatcher

#shell, #tab_complete_items

Instance Method Summary collapse

Methods included from Rex::Post::Meterpreter::Ui::Console::CommandDispatcher

check_hash, #client, #log_error, #msf_loaded?, set_hash

Methods included from Ui::Text::DispatcherShell::CommandDispatcher

#cmd_help, #cmd_help_tabs, #print, #print_error, #print_good, #print_line, #print_status, #tab_complete_filenames, #update_prompt

Constructor Details

#initialize(shell) ⇒ Sniffer

Initializes an instance of the sniffer command interaction.



22
23
24
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/sniffer.rb', line 22

def initialize(shell)
	super
end

Instance Method Details

#cmd_sniffer_dump(*args) ⇒ Object



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/sniffer.rb', line 100

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
	
	path_cap = args[1]
	path_raw = args[1] + '.raw'
	
	fd = ::File.new(path_raw, 'wb+')
	
	print_status("Flushing packet capture buffer for interface #{intf}...")
	res = client.sniffer.capture_dump(intf)
	print_status("Flushed #{res[:packets]} packets (#{res[:bytes]} bytes)")
	
	bytes_all = res[:bytes] || 0
	bytes_got = 0
	bytes_pct = 0

	while (bytes_all > 0)
		res = client.sniffer.capture_dump_read(intf,1024*512)
		
		bytes_got += res[:bytes]

		pct = ((bytes_got.to_f / bytes_all.to_f) * 100).to_i
		if(pct > bytes_pct)
			print_status("Downloaded #{"%.3d" % pct}% (#{bytes_got}/#{bytes_all})...")
			bytes_pct = pct
		end		
		break if res[:bytes] == 0
		fd.write(res[:data])
	end
	
	fd.close
	
	print_status("Download completed, converting to PCAP...")
	
	fd = nil
	if(::File.exist?(path_cap))
		fd = ::File.new(path_cap, 'ab+')
	else
		fd = ::File.new(path_cap, 'wb+')
		fd.write([0xa1b2c3d4, 2, 4, 0, 0, 65536, 1].pack('NnnNNNN'))
	end	

	pkts = {}		
	od = ::File.new(path_raw, 'rb')


	# TODO: reorder packets based on the ID (only an issue if the buffer wraps)
	while(true)
		buf = od.read(20)
		break if not buf
	
		idh,idl,thi,tlo,len = buf.unpack('N5')
		break if not len
		if(len > 10000) 
			print_error("Corrupted packet data (length:#{len})")
			break
		end
		
		pkt_id = (idh << 32) +idl
		pkt_ts = Rex::Proto::SMB::Utils.time_smb_to_unix(thi,tlo)
		pkt    = od.read(len)
		
		fd.write([pkt_ts,0,len,len].pack('NNNN')+pkt)
	end
	od.close
	fd.close
	
	::File.unlink(path_raw)
	print_status("PCAP file written to #{path_cap}")
end

#cmd_sniffer_interfaces(*args) ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/sniffer.rb', line 40

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

#cmd_sniffer_start(*args) ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/sniffer.rb', line 58

def cmd_sniffer_start(*args)
	intf = args.shift.to_i
	if (intf == 0)
		print_error("Usage: sniffer_start [interface-id] [packet-buffer (1-200000)] [bpf filter (posix meterpreter only)]")
		return
	end
	maxp = (args.shift || 50000).to_i
	bpf  = args.join(" ")
	
	client.sniffer.capture_start(intf, maxp, bpf)
	print_status("Capture started on interface #{intf} (#{maxp} packet buffer)")
	return true
end

#cmd_sniffer_stats(*args) ⇒ Object



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/sniffer.rb', line 84

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

#cmd_sniffer_stop(*args) ⇒ Object



72
73
74
75
76
77
78
79
80
81
82
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/sniffer.rb', line 72

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

#commandsObject

List of supported commands.



29
30
31
32
33
34
35
36
37
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/sniffer.rb', line 29

def commands
	{
		"sniffer_interfaces" => "Enumerate all sniffable network interfaces",
		"sniffer_start" => "Start packet capture on a specific interface",
		"sniffer_stop"  => "Stop packet capture on a specific interface",
		"sniffer_stats" => "View statistics of an active capture",
		"sniffer_dump"  => "Retrieve captured packet data to PCAP file",
	}
end

#nameObject

Name for this dispatcher sni



178
179
180
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/sniffer.rb', line 178

def name
	"Sniffer"
end