1 import usb
2 import time
3 import struct
4 from pcapdump import *
5 from daintree import *
6 from dot154decode import *
7 from zigbeedecode import *
8 from pcapdlt import *
9 from kbutils import *
10
11
12
13
14
15
16
17
18
19
20 RZ_CMD_SET_MODE = 0x07
21 RZ_CMD_SET_CHANNEL = 0x08
22 RZ_CMD_OPEN_STREAM = 0x09
23 RZ_CMD_CLOSE_STREAM = 0x0A
24
25
26 RZ_CMD_INJECT_FRAME = 0x0D
27 RZ_CMD_JAMMER_ON = 0x0E
28 RZ_CMD_JAMMER_OFF = 0x0F
29
30
31 RZ_CMD_MODE_AC = 0x00
32
33
34
35 RZ_CMD_MODE_NONE = 0x04
36
37 RZ_RESP_LOCAL_TIMEOUT = 0x00
38 RZ_RESP_SUCCESS = 0x80
39 RZ_RESP_SYNTACTICAL_ERROR = 0x81
40 RZ_RESP_SEMANTICAL_ERROR = 0x82
41 RZ_RESP_HW_TIMEOUT = 0x83
42 RZ_RESP_SIGN_ON = 0x84
43 RZ_RESP_GET_PARAMETER = 0x85
44 RZ_RESP_TRX_READ_REGISTER = 0x86
45 RZ_RESP_TRX_READ_FRAME = 0x87
46 RZ_RESP_TRX_READ_SRAM = 0x88
47 RZ_RESP_TRX_GET_PIN = 0x89
48 RZ_RESP_TRX_BUSY = 0x8A
49 RZ_RESP_PRITMITIVE_FAILED = 0x8B
50 RZ_RESP_PRITMITIVE_UNKNOWN = 0x8C
51 RZ_RESP_COMMAND_UNKNOWN = 0x8D
52 RZ_RESP_BUSY_SCANING = 0x8E
53 RZ_RESP_BUSY_CAPTURING = 0x8F
54 RZ_RESP_OUT_OF_MEMORY = 0x90
55 RZ_RESP_BUSY_JAMMING = 0x91
56 RZ_RESP_NOT_INITIALIZED = 0x92
57 RZ_RESP_NOT_IMPLEMENTED = 0x93
58 RZ_RESP_PRIMITIVE_FAILED = 0x94
59 RZ_RESP_VRT_KERNEL_ERROR = 0x95
60 RZ_RESP_BOOT_PARAM = 0x96
61
62 RZ_EVENT_STREAM_AC_DATA = 0x50
63
64
65
66
67
68
69
70 RESPONSE_MAP = {RZ_RESP_LOCAL_TIMEOUT: "Local Timeout Error",
71 RZ_RESP_SUCCESS : "Success",
72 RZ_RESP_SYNTACTICAL_ERROR : "Syntactical Error",
73 RZ_RESP_SEMANTICAL_ERROR : "Semantical Error",
74 RZ_RESP_HW_TIMEOUT : "Hardware Timeout",
75 RZ_RESP_SIGN_ON : "Sign On",
76 RZ_RESP_GET_PARAMETER : "Get Parameter",
77 RZ_RESP_TRX_READ_REGISTER : "Transceiver Read Register",
78 RZ_RESP_TRX_READ_FRAME : "Transceiver Read Frame",
79 RZ_RESP_TRX_READ_SRAM : "Transceiver Read SRAM",
80 RZ_RESP_TRX_GET_PIN : "Transceiver Get PIN",
81 RZ_RESP_TRX_BUSY : "Transceiver Busy",
82 RZ_RESP_PRITMITIVE_FAILED : "Primitive Failed",
83 RZ_RESP_PRITMITIVE_UNKNOWN : "Unknown Primitive",
84 RZ_RESP_COMMAND_UNKNOWN : "Unknown Command",
85 RZ_RESP_BUSY_SCANING : "Busy Scanning",
86 RZ_RESP_BUSY_CAPTURING : "Busy Capturing",
87 RZ_RESP_OUT_OF_MEMORY : "Out of Memory",
88 RZ_RESP_BUSY_JAMMING : "Busy Jamming",
89 RZ_RESP_NOT_INITIALIZED : "Not Initialized",
90 RZ_RESP_NOT_IMPLEMENTED : "Not Implemented by USB firmware",
91 RZ_RESP_PRIMITIVE_FAILED : "Primitive Failed",
92 RZ_RESP_VRT_KERNEL_ERROR : "Could not execute due to vrt_kernel_error",
93 RZ_RESP_BOOT_PARAM : "Boot Param Error"}
94
95 RZ_USB_VEND_ID = 0x03EB
96 RZ_USB_PROD_ID = 0x210A
97 RZ_USB_COMMAND_EP = 0x02
98 RZ_USB_RESPONSE_EP = 0x84
99 RZ_USB_PACKET_EP = 0x81
100
101 KB_CAPAB_NONE = 0x00
102 KB_CAPAB_SNIFF = 0x01
103 KB_CAPAB_SETCHAN = 0x02
104 KB_CAPAB_INJECT = 0x03
105 KB_CAPAB_PHYJAM = 0x04
106 KB_CAPAB_SELFACK = 0x05
107
110 '''
111 Instantiates the KillerBee class.
112
113 @type device: String
114 @param device: USB device identifier
115 @return: None
116 @rtype: None
117 '''
118
119 self.__cmdmode = RZ_CMD_MODE_NONE
120
121
122 self.__stream_open = False
123
124
125
126 self._capabilities = {
127 KB_CAPAB_NONE : False,
128 KB_CAPAB_SNIFF : False,
129 KB_CAPAB_SETCHAN : False,
130 KB_CAPAB_INJECT : False,
131 KB_CAPAB_PHYJAM : False,
132 KB_CAPAB_SELFACK: False}
133
134 self.handle = None
135 self.dev = None
136 self.__bus = None
137
138 self.__busses = usb.busses()
139 for bus in self.__busses:
140 if self.__search_bus(bus, device) == True:
141 self.__bus = bus
142 break
143 else:
144 self.dev = None
145
146 if self.dev != None:
147
148 self.__handle_open()
149 else:
150 raise Exception('No interface found')
151
153 devices = bus.devices
154 for self.dev in devices:
155 if self.dev.idVendor == RZ_USB_VEND_ID and self.dev.idProduct == RZ_USB_PROD_ID:
156 if device == None or (device == (''.join([bus.dirname, ":", self.dev.filename]))):
157
158 self.__set_rz_capabilities()
159 return True
160 return False
161
163 '''
164 Uses the specified capability to determine if the opened device
165 is supported. Returns True when supported, else False.
166
167 @rtype: Boolean
168 '''
169 try:
170 return self._capabilities[capab]
171 except KeyError:
172 return False
173
175 '''
176 Returns a list of capability information for the device.
177
178 @rtype: List
179 @return: Capability information for the opened device.
180 '''
181 return self._capabilities
182
184 '''
185 Sets the capability information for RZUSB devices. This should not be
186 called outside of the class.
187
188 @rtype: None
189 @return: None
190 '''
191
192
193 prod = self.dev.open().getString(self.dev.iProduct, 50)
194
195 if prod == "RZUSBSTICK":
196 self._capabilities[KB_CAPAB_SNIFF] = True
197 self._capabilities[KB_CAPAB_SETCHAN] = True
198 return
199 elif prod == "KILLERB001":
200 self._capabilities[KB_CAPAB_SNIFF] = True
201 self._capabilities[KB_CAPAB_SETCHAN] = True
202 self._capabilities[KB_CAPAB_INJECT] = True
203 return
204 else:
205 return
206
208 '''
209 Write data to the USB device opened as self.handle.
210
211 @type endpoint: Integer
212 @param endpoint: The USB endpoint to write to
213 @type data: Mixed
214 @param data: The data to send to the USB endpoint
215 '''
216 try:
217 self.handle.bulkWrite(endpoint, data)
218
219 response = self.handle.bulkRead(RZ_USB_RESPONSE_EP, 1)[0]
220 except usb.USBError, e:
221 if e.args != ('No error',):
222 raise e
223 try:
224 if response != RZ_RESP_SUCCESS:
225 raise Exception("Error: %s" % RESPONSE_MAP[response])
226 except KeyError:
227 raise Exception("Unknown USB write error: 0x%02x" % response)
228
230 '''
231 Reads data from the USB device on the specified endpoint.
232
233 @type endpoint: Integer
234 @param endpoint: The USB endpoint to read from
235 @type timeout: Integer
236 @param timeout: Timeout in usec for read operation before return
237 @rtype: String
238 @return: Data returned from USB device
239 '''
240 dataread = [RZ_RESP_LOCAL_TIMEOUT,]
241 dataread = self.handle.bulkRead(endpoint, timeout)
242
243
244 response = dataread[0]
245 try:
246 if response != RZ_RESP_SUCCESS:
247 raise Exception("Error: %s" % RESPONSE_MAP[response])
248 except KeyError:
249 raise Exception("Unknown USB read error: 0x%02x" % response)
250
251
253 '''
254 Change the operating mode of the USB device to one of the RZ_CMD_MODE_*
255 values. Currently, RZ_CMD_MODE_AC (Air Capture) is the only mode that is
256 used other than RZ_CMD_MODE_NONE.
257 @type mode: Integer
258 @param mode: Operating mode for the USB stick
259 @rtype: None
260 '''
261 self.__usb_write(RZ_USB_COMMAND_EP, [RZ_CMD_SET_MODE, RZ_CMD_MODE_AC])
262 self.__cmdmode = mode
263
270
277
279 '''
280 Turns the sniffer on such that pnext() will start returning observed
281 data. Will set the command mode to Air Capture if it is not already
282 set.
283 @type channel: Integer
284 @param channel: Sets the channel, optional
285 @rtype: None
286 '''
287 if self.check_capability(KB_CAPAB_SNIFF) != True:
288 raise Exception('Selected hardware does not support sniffing')
289
290 if self.__cmdmode != RZ_CMD_MODE_AC:
291 self._set_mode(RZ_CMD_MODE_AC)
292
293 if channel != None:
294 self.set_channel(channel)
295
296 self._open_stream()
297
299 '''
300 Turns the sniffer off, freeing the hardware for other functions. It is
301 not necessary to call this function before closing the interface with
302 close().
303 @rtype: None
304 '''
305 self._close_stream()
306
324
332
334 '''
335 Sets the radio interface to the specifid channel. Currently, support is
336 limited to 2.4 GHz channels 11 - 26.
337 @type channel: Integer
338 @param channel: Sets the channel, optional
339 @rtype: None
340 '''
341 if self.check_capability(KB_CAPAB_SETCHAN) != True:
342 raise Exception('Selected hardware does not support setting the channel')
343
344 if self.__cmdmode != RZ_CMD_MODE_AC:
345 self._set_mode(RZ_CMD_MODE_AC)
346
347 if channel >= 10 or channel <= 26:
348 self.__usb_write(RZ_USB_COMMAND_EP, [RZ_CMD_SET_CHANNEL, channel])
349 else:
350 raise Exception('Invalid channel')
351
352 - def inject(self, packet, channel=None, count=1, delay=0):
353 '''
354 Injects the specified packet contents.
355 @type packet: String
356 @param packet: Packet contents to transmit, without FCS.
357 @type channel: Integer
358 @param channel: Sets the channel, optional
359 @type count: Integer
360 @param count: Transmits a specified number of frames, def=1
361 @type delay: Float
362 @param delay: Delay between each frame, def=1
363 @rtype: None
364 '''
365 if self.check_capability(KB_CAPAB_INJECT) != True:
366 raise Exception('Selected hardware does not support packet injection')
367
368 if self.__cmdmode != RZ_CMD_MODE_AC:
369 self._set_mode(RZ_CMD_MODE_AC)
370
371 if len(packet) < 1:
372 raise Exception('Empty packet')
373 if len(packet) > 125:
374 raise Exception('Packet too long')
375
376 if channel != None:
377 self.set_channel(channel)
378
379
380 packet = ''.join([packet, "\x00\x00"])
381
382 for pnum in range(0, count):
383
384
385 self.__usb_write(RZ_USB_COMMAND_EP, struct.pack("B", RZ_CMD_INJECT_FRAME) + struct.pack("B", len(packet)) + packet)
386 time.sleep(delay)
387
388 - def pnext(self, timeout=100):
389 '''
390 Returns packet data as a string, else None.
391 @type timeout: Integer
392 @param timeout: Timeout to wait for packet reception in usec
393 @rtype: List
394 @return: Returns None is timeout expires and no packet received. When a packet is received, a list is returned, in the form [ String: packet contents | Bool: Valid CRC | Int: Unscaled RSSI ]
395 '''
396 if self.__stream_open == False:
397
398 self.sniffer_on()
399
400
401
402 pdata = None
403 try:
404 pdata = self.handle.bulkRead(RZ_USB_PACKET_EP, timeout)
405 except usb.USBError, e:
406 if e.args != ('No error',):
407 raise e
408
409
410 if pdata == None or pdata == ():
411 return None
412
413 if pdata[0] == RZ_EVENT_STREAM_AC_DATA:
414 rssi = int(pdata[6])
415 validcrc = True if (pdata[7] == 1) else False
416 frame = pdata[9:]
417
418 framedata = []
419 for byteval in frame:
420 framedata.append(struct.pack("B", byteval))
421 return [''.join(framedata), validcrc, rssi]
422 else:
423 return None
424
425
426
427 - def ping(self, da, panid, sa, channel=None):
428 '''
429 Not yet implemented.
430 @return: None
431 @rtype: None
432 '''
433 raise Exception('Not yet implemented')
434
436 '''
437 Opens the device identified as self.dev, populating self.handle
438 '''
439 try:
440 config = self.dev.configurations[0]
441 intf = config.interfaces[0]
442 alt = intf[0]
443 self.handle = self.dev.open()
444 self.handle.reset()
445 self.handle.setConfiguration(config)
446 self.handle.claimInterface(alt)
447 self.handle.setAltInterface(alt)
448 except:
449 raise Exception("Unable to open device. Ensure the device is free and plugged-in.")
450
452 '''
453 Closes the device handle. To be re-used, class should be
454 re-instantiated.
455 @return: None
456 @rtype: None
457 '''
458 self.handle.releaseInterface()
459
461 '''
462 Returns device information in a list identifying the device identifier,
463 product string and serial number in a list of strings.
464 @rtype: List
465 @return: List of strings identifying device.
466 '''
467 return [''.join([self.__bus.dirname, ":", self.dev.filename]), self.dev.open().getString(self.dev.iProduct, 50), self.dev.open().getString(self.dev.iSerialNumber, 12)]
468
470 '''
471 Return device information for all present devices.
472 @rtype: List
473 @return: List of device information present.
474 '''
475 devlist = []
476 for bus in self.__busses:
477 devices = bus.devices
478 for dev in devices:
479 if dev.idVendor == RZ_USB_VEND_ID and dev.idProduct == RZ_USB_PROD_ID:
480
481 devlist.append([''.join([bus.dirname + ":" + dev.filename]), dev.open().getString(dev.iProduct, 50), dev.open().getString(dev.iSerialNumber, 12)])
482 return devlist
483