def getRaw(self): return ( super(HCI_Cmd, self).getRaw() + p16(self.opcode) + p8(self.length) + self.data )
def recvPacket(self, record): hcipkt = record[0] if not issubclass(hcipkt.__class__, HCI_Event): return if hcipkt.event_code != 0xFF: return # TODO Android 8 introduced special handling for 0x57 HCI_VSE_SUBCODE_DEBUG_INFO_SUB_EVT, # stackdumps might no longer work if hcipkt.data[0] == 0x57: self.handleNexus6pStackDump(hcipkt) if hcipkt.data[0:4] == p32(0x039200F7): self.handleNexus5StackDump(hcipkt) # same header for S10 and evaluation board... if hcipkt.data[0:2] == p16( 0x031B ): # generated by bthci_event_vs_initializeCoredumpHdr() self.handleEvalStackDump(hcipkt) self.handleS10StackDump(hcipkt)
def work(self, args): """Debugs which key length is currently active within a connection handle.""" internalblue.sendHciCommand(hci.HCI_COMND.Encryption_Key_Size, p16(args.hnd)) return True
def _hciEventHandler(self, h4_record): event = h4_record.event_code hci_data = h4_record.data status = hci_data[0] # connection complete event if event == 3: # connection complete - sucess if status == 0: handle = struct.unpack_from("h", hci_data[1:])[0] self.handle = handle log.info("Connection to %s complete", binascii.hexlify(self.remote_addr).decode("utf-8")) self.keepalive_active = True self._keepaliveTimer() # connection complete - page timeout elif status == 4: log.info("Page timeout while connecting to %s", binascii.hexlify(self.remote_addr).decode("utf-8")) # disconnection complete event elif event == 5: self.handle = None log.info("Disconnected from " + binascii.hexlify(self.remote_addr).decode("utf-8")) if self.reconnect_counter < self.reconnect: log.info("Trying to reconnect (attempt %d of %d)", self.reconnect_counter, self.reconnect) # wait a second, otherwise we sometimes don't get the connection complete event... time.sleep(1) self.connect() self.reconnect_counter += 1 # authentication complete elif event == 6: # workaround as there is apparently a bug in pythons struct (status, ) = struct.unpack_from("b", hci_data) (handle, ) = struct.unpack_from("h", hci_data[1:]) log.info("got Authentication Complete from handle %s, status: %d", hex(handle), status) if status == 0: # authentication was successful, now set connection encryption self.core.sendHciCommand(0x0413, p16(handle) + "\x01") self.encrypted = True if self.encryption_callback: self.encryption_callback() pass else: handle = 0 # encryption change complete elif event == 8: (handle, encrypt) = struct.unpack_from("hb", hci_data) log.info( "Got Encryption Change Complete from handle %s, encrypt: %d", hex(handle), encrypt) # pin code request elif event == 0x16: (bd_addr, ) = struct.unpack_from("6s", hci_data) log.info("Got Pin Code Request for %s", binascii.hexlify(bd_addr).decode("utf-8")) self.core.sendHciCommand(0x040d, bd_addr + "\x00" + "\x41" * 0x10) # link key request elif event == 0x17: (bd_addr, ) = struct.unpack_from("6s", hci_data) log.info("Got Link Key request from %s", binascii.hexlify(bd_addr).decode("utf-8")) # link keys are not really implemented yet, just return a random link key self.core.sendHciCommand( 0x040b, bd_addr + bytes.fromhex("0d2017c7f90a78cefeeed32210e6519a")) return if bd_addr in self.link_keys: # we have a link key for this device, set it lkey_buf = self.link_keys[bd_addr][::-1] self.core.sendHciCommand(0x040b, bd_addr + lkey_buf) else: # send negative link key reply, we don't have a key self.core.sendHciCommand(0x040c, bd_addr) # link key notification elif event == 0x18: (bd_addr, link_key) = struct.unpack_from("6s16s", hci_data) log.info("Got Link Key notification from %s, key: %s", bd_addr, binascii.hexlify(link_key).decode("utf-8")) self.link_keys[bd_addr] = link_key # io capability request elif event == 0x31: (bd_addr, ) = struct.unpack_from("6s", hci_data) log.info("Got IO capability request from %s", binascii.hexlify(bd_addr).decode("utf-8")) # pretend to not have a display or oob data present # no display: 0x03, no oob: 0x00, auth requirements: 0x02 self.core.sendHciCommand(0x042b, bd_addr + "\x03\x00\x02") # user confirmation request elif event == 0x33: (bd_addr, ) = struct.unpack_from("6s", hci_data) log.info("Got user confirmation request from %s", binascii.hexlify(bd_addr).decode("utf-8")) # we just accept any confirmation requests self.core.sendHciCommand(0x42c, bd_addr) # simple pairing complete elif event == 0x36: (bd_addr, ) = struct.unpack_from("6s", hci_data) log.info("Got simple pairing complete from %s", binascii.hexlify(bd_addr).decode("utf-8")) # le event # everything from le lands here... elif event == 0x3e: le_event_type = hci_data[0] le_handle = struct.unpack_from("h", hci_data[2:4])[0] # enhanced connection complete if le_event_type == 0x0a: log.info( "Got le enhanced connection complete, removing device from whitelist" ) self.core.sendHciCommand( 0x2012, bytes.fromhex("00") + self.remote_addr[::-1]) elif le_event_type == 0x01: # sometimes we get connection complete events from previous sessions log.info("got le connection complete with handle %d", le_handle) if self.started_connection: self.handle = le_handle else: log.info( "but ignoring it as we did not initiate this connection" )
def sendACL(self, data): data_len = p16(len(data)) handle = p16(self.handle | 0x2000) log.debug("Sent acl data: %s", binascii.hexlify(data).decode("utf-8")) self.core.sendH4(0x02, handle + data_len + data)
def getRaw(self): raw = bits(p16(self.handle))[4:] raw.extend(bits(p8(self.ps))[6:]) raw.extend(bits(p8(0))[6:]) raw.extend(bits(p8(self.length))) return super(HCI_Sco, self).getRaw() + unbits(raw) + self.data
def do_knob(self, args): """Introduce a new CLI command to make KNOB debugging easier...""" internalblue.sendHciCommand(hci.HCI_COMND.Encryption_Key_Size, p16(args.hnd)) return None
def sendCFrame(self, code, identifier, data): data_len = len(data) / 2 self.sendCFrameRaw(code, identifier, p16(data_len), data)
def sendData(self, data, cid): data_len = len(data) # if data_len > mtu log.debug("Sent L2CAP data to channel: %d, data: %s", cid, binascii.hexlify(data)) self.connection.sendACL(p16(data_len) + p16(cid) + data)