66c3c6a94b
Capture mixin was not used. Loot was being saved when a zip file wasn't found. Updated file path so the module is under analyze.
90 lines
2.7 KiB
Ruby
90 lines
2.7 KiB
Ruby
##
|
|
## This module requires Metasploit: https://metasploit.com/download
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
|
##
|
|
|
|
class MetasploitModule < Msf::Auxiliary
|
|
include Msf::Auxiliary::Report
|
|
|
|
def initialize(info = {})
|
|
super(
|
|
'Name' => 'Extract zip from Modbus communication',
|
|
'Description' => %q{
|
|
This module is able to extract a zip file sent through Modbus from a pcap.
|
|
Tested with Schneider TM221CE16R
|
|
},
|
|
'Author' => [
|
|
'José Diogo Monteiro <jdlopes[at]student.dei.uc.pt>',
|
|
'Luis Rosa <lmrosa[at]dei.uc.pt)>'
|
|
],
|
|
'License' => MSF_LICENSE
|
|
)
|
|
|
|
register_options [
|
|
Opt::RPORT(502),
|
|
OptEnum.new('MODE', [true, 'Extract zip from upload/download capture', 'UPLOAD',
|
|
['UPLOAD','DOWNLOAD']]),
|
|
OptString.new('PCAPFILE', [ true, 'Pcap to read', '' ]),
|
|
OptString.new('FILENAME', [ false, 'Zip file output name'])
|
|
]
|
|
|
|
end
|
|
|
|
FIRST_BYTE_UPLOAD = 12
|
|
FIRST_BYTE_DOWNLOAD = 16
|
|
|
|
def extract_zip(packet, zip_packet, first_byte, data, packet_number)
|
|
# ZIP start signature
|
|
h = packet.payload.scan(/\x50\x4B\x03\x04.*/)
|
|
if h.size.nonzero?
|
|
print_status "Zip start on packet #{packet_number + 1}"
|
|
data = h[0]
|
|
zip_packet += 1
|
|
return zip_packet, data
|
|
end
|
|
|
|
# ZIP end signature (central directory record)
|
|
h = packet.payload.scan(/.*\x50\x4B\x05\x06................../)
|
|
if h.size.nonzero?
|
|
print_status "Zip end on packet #{packet_number + 1}"
|
|
data += h[0][first_byte..-1]
|
|
zip_packet += 1
|
|
return zip_packet, data
|
|
end
|
|
|
|
# ZIP data
|
|
if zip_packet == 1
|
|
unless packet.payload[first_byte..-1].nil?
|
|
data += packet.payload[first_byte..-1]
|
|
end
|
|
end
|
|
return zip_packet, data
|
|
end
|
|
|
|
def run
|
|
packets = PacketFu::PcapFile.read_packets datastore['PCAPFILE']
|
|
zip_packet = 0
|
|
data = ''
|
|
packets.each_with_index do |packet, i|
|
|
if datastore['MODE'] == 'UPLOAD'
|
|
if packet.respond_to?(:tcp_src) and packet.tcp_src == datastore['RPORT']
|
|
zip_packet, data = extract_zip(packet, zip_packet, FIRST_BYTE_UPLOAD, data, i)
|
|
end
|
|
elsif datastore['MODE'] == 'DOWNLOAD'
|
|
if packet.respond_to?(:tcp_dst) and packet.tcp_dst == datastore['RPORT']
|
|
zip_packet, data = extract_zip(packet, zip_packet, FIRST_BYTE_DOWNLOAD, data, i)
|
|
end
|
|
end
|
|
break if zip_packet == 2
|
|
end
|
|
|
|
filename = datastore['FILENAME'] || 'project.zip'
|
|
unless data.empty?
|
|
path = store_loot(filename, 'application/zip', datastore['RHOSTS'], data, filename, 'modbus.zip')
|
|
print_good "Zip file saved in loot: #{path}"
|
|
else
|
|
print_status "Zip file not found in #{datastore['PCAPFILE']}"
|
|
end
|
|
end
|
|
end
|