Above is a video demo of a Linear Delta-3 garage door receiver being brute forced using the rfpwnon.py script. This receiver has 8 dip switches and it takes around 2 minutes to run through all possible permutations of the code when being brute forced. This garage door is less secure than the remote control light that is shown later in the article.
Getting up and running:
This project requires a rfcat compatible dongle such as the YARDstick One, rfcat, and python2.x. (Yard Stick One can be Purchased from HakShop)
echo "On Kali 2016" sudo apt-get install rfcat pip install bitstring wget https://raw.githubusercontent.com/exploitagency/github-rfpwnon/master/rfpwnon.py python rfpwnon.py --help
Intro to rfpwnon.py:
rfpwnon.py as the name implies is able to "pwn on"(turn on/off/activate) almost any sub-ghz ask ook device. The script has the ability to send both binary and trinary signals. If your device can be triggered by sending the key once then the default de bruijn method is used but if it requires the signal to be repeated multiple times as most devices do, then you must specify the repeat times with "-r NUMBEROFREPEATS" and every possible permutation of the key is sent one by one until an event is triggered and you stop the script. Some devices will take an impractical amount of time to brute force the key(signal), so you may add padding before or after the key if that part of the key is static and is known. At the bare minimum to trigger an event you must know the frequency to transmit on, the binary key length, and the baud rate that the device expects.
Understanding the difference between the raw signal vs the pwm signal:
Lets say a device expects the raw signal(key) "1000 1110 1000 1110" to be sent 5 times on the frequency 315MHz at 2000baud in order to trigger an event. That makes this a 16 bit raw signal. But this device is actually using pulse width modulation(PWM). So the PWM encoded signal in this instance means the first four bits 1000 is only seen as a 1 when the receiver processes the key and the second four bits 1110 is actually interpretted as a 0 by the receiver. So that means the way we should look at this when attempting to brute force the signal is that we have a 4 bit pwm encoded key of 1010.
Crafting a command:
Using the above example the proper command to brute force the device to trigger an event would be
python rfpwnon.py -f 315000000 -b 2000 -l 4 -r 5
This will send every possible permutation of the key 5 times thus triggering an event.
Breaking it down:
All possible permutations of the 4 bit PWM encoded key include: "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111".
When the above command is issued it will convert the pwm encoded key "0000" back to the raw signal "1110 1110 1110 1110" and send that 5 times on 315MHz at 2000baud and then the scripts proceeds to convert "0001" to "1110 1110 1110 1000" send it 5 times and so forth.
If you want to brute force it from the raw signal perspective then you may also run the script with the "--raw" flag such as "python rfpwnon.py -f 315000000 -b 2000 -l 16 -r 5 --raw". Also note when specifying the "--raw" flag that you must use the raw binary length before pwm encoding. Though this will also send a lot of garbage data that does not actually equal a 1 or a 0. Brute forcing the raw signal will also take a much longer amount of time. The cool thing though is since your not sending what is interpreted as 1's or 0's you may be able to fuzz the receiver.
Using padding and brute forcing a Woods 32555 remote power outlet:
PWN on a Woods 32555 remote power outlet!
The command below yields faster results by utilizing padding and setting known static bits before the key to be brute forced. The known bits that do not change are "100101" so we use the argument "-p 100101". You can also add padding after the brute force portion also known as the tail using the argument "-t PADDING-HERE". Even though we are kind of cheating by using some padding we are still brute forcing more bits than some old garage doors need.
python rfpwnon.py -f 315060000 -b 1818 -p 100101 -l 10 -r 2
Also we can do the same without padding like the command below. Although it will be slow and could take up to 5-7 hours. Times are assuming we are able to send 5-7 keys a second which in testing really depends on the baud rate of the device and length of signal as well as the number of repeats.
python rfpwnon.py -f 315060000 -b 1818 -l 16 -r 2
Our Original Version of this Script was Featured in Hak5 Episode 1912 - How to Hack Radio with Brute Force Attacks
Note: You may need to edit the source and change what represents a one or zero to better suit your device. For example sometimes a one is hi.lo.lo.lo and other times hi.hi.lo.lo, if your device uses a trinary signal you must also change the binary representation in the source to suit your device. The rfpwnon.py script is loosely based off AMOOKTransmit.py by www.andrewmohawk.com. Thank you Andrew for the great examples!