Path: blob/master/modules/auxiliary/analyze/modbus_zip.rb
19591 views
##1## This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Auxiliary6include Msf::Auxiliary::Report78def initialize(_info = {})9super(10'Name' => 'Extract zip from Modbus communication',11'Description' => %q{12This module is able to extract a zip file sent through Modbus from a pcap.13Tested with Schneider TM221CE16R.14},15'Author' => [16'José Diogo Monteiro <jdlopes[at]student.dei.uc.pt>',17'Luis Rosa <lmrosa[at]dei.uc.pt)>'18],19'License' => MSF_LICENSE,20'Notes' => {21'Stability' => [CRASH_SAFE],22'SideEffects' => [],23'Reliability' => []24}25)2627register_options [28Opt::RPORT(502),29OptEnum.new('MODE', [30true, 'Extract zip from upload/download capture', 'UPLOAD',31['UPLOAD', 'DOWNLOAD']32]),33OptString.new('PCAPFILE', [ true, 'Pcap to read', '' ]),34OptString.new('FILENAME', [ false, 'Zip file output name'])35]36end3738FIRST_BYTE_UPLOAD = 1239FIRST_BYTE_DOWNLOAD = 164041def extract_zip(packet, zip_packet, first_byte, data, packet_number)42# ZIP start signature43h = packet.payload.scan(/\x50\x4B\x03\x04.*/)44if h.size.nonzero?45print_status "Zip start on packet #{packet_number + 1}"46data = h[0]47zip_packet += 148return zip_packet, data49end5051# ZIP end signature (central directory record)52h = packet.payload.scan(/.*\x50\x4B\x05\x06................../)53if h.size.nonzero?54print_status "Zip end on packet #{packet_number + 1}"55data += h[0][first_byte..]56zip_packet += 157return zip_packet, data58end5960# ZIP data61if zip_packet == 1 && !packet.payload[first_byte..].nil?62data += packet.payload[first_byte..]63end64return zip_packet, data65end6667def run68packets = PacketFu::PcapFile.read_packets datastore['PCAPFILE']69zip_packet = 070data = ''71packets.each_with_index do |packet, i|72if datastore['MODE'] == 'UPLOAD'73if packet.respond_to?(:tcp_src) && (packet.tcp_src == datastore['RPORT'])74zip_packet, data = extract_zip(packet, zip_packet, FIRST_BYTE_UPLOAD, data, i)75end76elsif datastore['MODE'] == 'DOWNLOAD'77if packet.respond_to?(:tcp_dst) && (packet.tcp_dst == datastore['RPORT'])78zip_packet, data = extract_zip(packet, zip_packet, FIRST_BYTE_DOWNLOAD, data, i)79end80end81break if zip_packet == 282end8384filename = datastore['FILENAME'] || 'project.zip'85if data.empty?86print_status "Zip file not found in #{datastore['PCAPFILE']}"87else88path = store_loot(filename, 'application/zip', datastore['RHOSTS'], data, filename, 'modbus.zip')89print_good "Zip file saved in loot: #{path}"90end91end92end939495