CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/auxiliary/analyze/modbus_zip.rb
Views: 11623
1
##
2
## This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Auxiliary
7
include Msf::Auxiliary::Report
8
9
def initialize(info = {})
10
super(
11
'Name' => 'Extract zip from Modbus communication',
12
'Description' => %q{
13
This module is able to extract a zip file sent through Modbus from a pcap.
14
Tested with Schneider TM221CE16R
15
},
16
'Author' => [
17
'José Diogo Monteiro <jdlopes[at]student.dei.uc.pt>',
18
'Luis Rosa <lmrosa[at]dei.uc.pt)>'
19
],
20
'License' => MSF_LICENSE
21
)
22
23
register_options [
24
Opt::RPORT(502),
25
OptEnum.new('MODE', [true, 'Extract zip from upload/download capture', 'UPLOAD',
26
['UPLOAD','DOWNLOAD']]),
27
OptString.new('PCAPFILE', [ true, 'Pcap to read', '' ]),
28
OptString.new('FILENAME', [ false, 'Zip file output name'])
29
]
30
31
end
32
33
FIRST_BYTE_UPLOAD = 12
34
FIRST_BYTE_DOWNLOAD = 16
35
36
def extract_zip(packet, zip_packet, first_byte, data, packet_number)
37
# ZIP start signature
38
h = packet.payload.scan(/\x50\x4B\x03\x04.*/)
39
if h.size.nonzero?
40
print_status "Zip start on packet #{packet_number + 1}"
41
data = h[0]
42
zip_packet += 1
43
return zip_packet, data
44
end
45
46
# ZIP end signature (central directory record)
47
h = packet.payload.scan(/.*\x50\x4B\x05\x06................../)
48
if h.size.nonzero?
49
print_status "Zip end on packet #{packet_number + 1}"
50
data += h[0][first_byte..-1]
51
zip_packet += 1
52
return zip_packet, data
53
end
54
55
# ZIP data
56
if zip_packet == 1
57
unless packet.payload[first_byte..-1].nil?
58
data += packet.payload[first_byte..-1]
59
end
60
end
61
return zip_packet, data
62
end
63
64
def run
65
packets = PacketFu::PcapFile.read_packets datastore['PCAPFILE']
66
zip_packet = 0
67
data = ''
68
packets.each_with_index do |packet, i|
69
if datastore['MODE'] == 'UPLOAD'
70
if packet.respond_to?(:tcp_src) and packet.tcp_src == datastore['RPORT']
71
zip_packet, data = extract_zip(packet, zip_packet, FIRST_BYTE_UPLOAD, data, i)
72
end
73
elsif datastore['MODE'] == 'DOWNLOAD'
74
if packet.respond_to?(:tcp_dst) and packet.tcp_dst == datastore['RPORT']
75
zip_packet, data = extract_zip(packet, zip_packet, FIRST_BYTE_DOWNLOAD, data, i)
76
end
77
end
78
break if zip_packet == 2
79
end
80
81
filename = datastore['FILENAME'] || 'project.zip'
82
unless data.empty?
83
path = store_loot(filename, 'application/zip', datastore['RHOSTS'], data, filename, 'modbus.zip')
84
print_good "Zip file saved in loot: #{path}"
85
else
86
print_status "Zip file not found in #{datastore['PCAPFILE']}"
87
end
88
end
89
end
90
91