Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/auxiliary/analyze/modbus_zip.rb
19591 views
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
'Notes' => {
22
'Stability' => [CRASH_SAFE],
23
'SideEffects' => [],
24
'Reliability' => []
25
}
26
)
27
28
register_options [
29
Opt::RPORT(502),
30
OptEnum.new('MODE', [
31
true, 'Extract zip from upload/download capture', 'UPLOAD',
32
['UPLOAD', 'DOWNLOAD']
33
]),
34
OptString.new('PCAPFILE', [ true, 'Pcap to read', '' ]),
35
OptString.new('FILENAME', [ false, 'Zip file output name'])
36
]
37
end
38
39
FIRST_BYTE_UPLOAD = 12
40
FIRST_BYTE_DOWNLOAD = 16
41
42
def extract_zip(packet, zip_packet, first_byte, data, packet_number)
43
# ZIP start signature
44
h = packet.payload.scan(/\x50\x4B\x03\x04.*/)
45
if h.size.nonzero?
46
print_status "Zip start on packet #{packet_number + 1}"
47
data = h[0]
48
zip_packet += 1
49
return zip_packet, data
50
end
51
52
# ZIP end signature (central directory record)
53
h = packet.payload.scan(/.*\x50\x4B\x05\x06................../)
54
if h.size.nonzero?
55
print_status "Zip end on packet #{packet_number + 1}"
56
data += h[0][first_byte..]
57
zip_packet += 1
58
return zip_packet, data
59
end
60
61
# ZIP data
62
if zip_packet == 1 && !packet.payload[first_byte..].nil?
63
data += packet.payload[first_byte..]
64
end
65
return zip_packet, data
66
end
67
68
def run
69
packets = PacketFu::PcapFile.read_packets datastore['PCAPFILE']
70
zip_packet = 0
71
data = ''
72
packets.each_with_index do |packet, i|
73
if datastore['MODE'] == 'UPLOAD'
74
if packet.respond_to?(:tcp_src) && (packet.tcp_src == datastore['RPORT'])
75
zip_packet, data = extract_zip(packet, zip_packet, FIRST_BYTE_UPLOAD, data, i)
76
end
77
elsif datastore['MODE'] == 'DOWNLOAD'
78
if packet.respond_to?(:tcp_dst) && (packet.tcp_dst == datastore['RPORT'])
79
zip_packet, data = extract_zip(packet, zip_packet, FIRST_BYTE_DOWNLOAD, data, i)
80
end
81
end
82
break if zip_packet == 2
83
end
84
85
filename = datastore['FILENAME'] || 'project.zip'
86
if data.empty?
87
print_status "Zip file not found in #{datastore['PCAPFILE']}"
88
else
89
path = store_loot(filename, 'application/zip', datastore['RHOSTS'], data, filename, 'modbus.zip')
90
print_good "Zip file saved in loot: #{path}"
91
end
92
end
93
end
94
95