% Scapy Bluetooth layer tests + Bluetooth tests = HCI layers # HCI_Command_Hdr # default construction hci_cmd_hdr = HCI_Command_Hdr() assert hci_cmd_hdr.ogf == 0 assert hci_cmd_hdr.ocf == 0 assert hci_cmd_hdr.len == None assert raw(hci_cmd_hdr) == b'\x00\x00\x00' # parsing hci_cmd_hdr = HCI_Command_Hdr(raw(hci_cmd_hdr)) assert hci_cmd_hdr.ogf == 0 assert hci_cmd_hdr.ocf == 0 assert hci_cmd_hdr.len == 0 # HCI_Cmd_Inquiry default construction hci_cmd_inquiry = HCI_Command_Hdr() / HCI_Cmd_Inquiry() assert hci_cmd_inquiry.ogf == 0x01 assert hci_cmd_inquiry.ocf == 0x01 assert hci_cmd_inquiry.len == None assert hci_cmd_inquiry.lap == 0x9e8b33 assert hci_cmd_inquiry.inquiry_length == 0 assert hci_cmd_inquiry.num_responses == 0 # parsing hci_cmd_inquiry = HCI_Command_Hdr(raw(hci_cmd_inquiry)) assert hci_cmd_inquiry.ogf == 0x01 assert hci_cmd_inquiry.ocf == 0x01 assert hci_cmd_inquiry.len == 5 assert hci_cmd_inquiry.lap == 0x9e8b33 assert hci_cmd_inquiry.inquiry_length == 0 assert hci_cmd_inquiry.num_responses == 0 # HCI_Cmd_Inquiry constructing an invalid packet hci_cmd_inquiry = HCI_Command_Hdr(len = 10) / HCI_Cmd_Inquiry() assert hci_cmd_inquiry.ogf == 0x01 assert hci_cmd_inquiry.ocf == 0x01 assert hci_cmd_inquiry.len == 10 assert hci_cmd_inquiry.lap == 0x9e8b33 assert hci_cmd_inquiry.inquiry_length == 0 assert hci_cmd_inquiry.num_responses == 0 assert raw(hci_cmd_inquiry)[2] == 10 # parse the invalid packet hci_cmd_inquiry = HCI_Command_Hdr(raw(hci_cmd_inquiry)) assert hci_cmd_inquiry.ogf == 0x01 assert hci_cmd_inquiry.ocf == 0x01 assert hci_cmd_inquiry.len == 10 assert hci_cmd_inquiry.lap == 0x9e8b33 assert hci_cmd_inquiry.inquiry_length == 0 assert hci_cmd_inquiry.num_responses == 0 # HCI_Cmd_Inquiry_Cancel default construction hci_cmd_inquiry_cancel = HCI_Command_Hdr() / HCI_Cmd_Inquiry_Cancel() assert hci_cmd_inquiry_cancel.ogf == 0x01 assert hci_cmd_inquiry_cancel.ocf == 0x02 assert hci_cmd_inquiry_cancel.len == None # hci_cmd_inquiry_cancel parsing hci_cmd_inquiry_cancel = HCI_Command_Hdr(raw(hci_cmd_inquiry_cancel)) assert hci_cmd_inquiry_cancel.ogf == 0x01 assert hci_cmd_inquiry_cancel.ocf == 0x02 assert hci_cmd_inquiry_cancel.len == 0 # Hci_Cmd_Hold_Mode hci_cmd_hold_mode = HCI_Command_Hdr() / HCI_Cmd_Hold_Mode() assert hci_cmd_hold_mode.ogf == 0x02 assert hci_cmd_hold_mode.ocf == 0x01 assert hci_cmd_hold_mode.len == None # parsing hci_cmd_hold_mode = HCI_Command_Hdr(raw(hci_cmd_hold_mode)) assert hci_cmd_hold_mode.ogf == 0x02 assert hci_cmd_hold_mode.ocf == 0x01 assert hci_cmd_hold_mode.len == 6 # HCI_Cmd_Set_Event_Mask hci_cmd_set_event_mask = HCI_Command_Hdr() / HCI_Cmd_Set_Event_Mask() assert hci_cmd_set_event_mask.ogf == 0x03 assert hci_cmd_set_event_mask.ocf == 0x01 assert hci_cmd_set_event_mask.len == None # parsing hci_cmd_set_event_mask = HCI_Command_Hdr(raw(hci_cmd_set_event_mask)) assert hci_cmd_set_event_mask.ogf == 0x03 assert hci_cmd_set_event_mask.ocf == 0x01 assert hci_cmd_set_event_mask.len == 8 # HCI_Cmd_Read_BD_Addr hci_cmd_read_bd_addr = HCI_Command_Hdr() / HCI_Cmd_Read_BD_Addr() assert hci_cmd_read_bd_addr.ogf == 0x04 assert hci_cmd_read_bd_addr.ocf == 0x09 assert hci_cmd_read_bd_addr.len == None # parsing hci_cmd_read_bd_addr = HCI_Command_Hdr(raw(hci_cmd_read_bd_addr)) assert hci_cmd_read_bd_addr.ogf == 0x04 assert hci_cmd_read_bd_addr.ocf == 0x09 assert hci_cmd_read_bd_addr.len == 0 # HCI_Cmd_Read_Link_Quality hci_cmd_read_link_quality = HCI_Command_Hdr() / HCI_Cmd_Read_Link_Quality() assert hci_cmd_read_link_quality.ogf == 0x05 assert hci_cmd_read_link_quality.ocf == 0x03 assert hci_cmd_read_link_quality.len == None # parsing hci_cmd_read_link_quality = HCI_Command_Hdr(raw(hci_cmd_read_link_quality)) assert hci_cmd_read_link_quality.ogf == 0x05 assert hci_cmd_read_link_quality.ocf == 0x03 assert hci_cmd_read_link_quality.len == 2 # HCI_Cmd_Read_Loopback_Mode hci_cmd_read_loopback_mode = HCI_Command_Hdr() / HCI_Cmd_Read_Loopback_Mode() assert hci_cmd_read_loopback_mode.ogf == 0x06 assert hci_cmd_read_loopback_mode.ocf == 0x01 assert hci_cmd_read_loopback_mode.len == None # parsing hci_cmd_read_loopback_mode = HCI_Command_Hdr(raw(hci_cmd_read_loopback_mode)) assert hci_cmd_read_loopback_mode.ogf == 0x06 assert hci_cmd_read_loopback_mode.ocf == 0x01 assert hci_cmd_read_loopback_mode.len == 0 # HCI_Cmd_LE_Read_Buffer_Size_V1 hci_cmd_le_read_buffer_size_v1 = HCI_Command_Hdr() / HCI_Cmd_LE_Read_Buffer_Size_V1() assert hci_cmd_le_read_buffer_size_v1.ogf == 0x08 assert hci_cmd_le_read_buffer_size_v1.ocf == 0x02 assert hci_cmd_le_read_buffer_size_v1.len == None # parsing hci_cmd_le_read_buffer_size_v1 = HCI_Command_Hdr(raw(hci_cmd_le_read_buffer_size_v1)) assert hci_cmd_le_read_buffer_size_v1.ogf == 0x08 assert hci_cmd_le_read_buffer_size_v1.ocf == 0x02 assert hci_cmd_le_read_buffer_size_v1.len == 0 + Bluetooth Transport Layers = Test HCI_PHDR_Hdr pkt = HCI_PHDR_Hdr()/HCI_Hdr()/HCI_ACL_Hdr()/L2CAP_Hdr()/L2CAP_CmdHdr()/L2CAP_InfoReq() assert raw(pkt) == b'\x00\x00\x00\x00\x02\x00\x00\n\x00\x06\x00\x05\x00\n\x00\x02\x00\x00\x00' pkt = HCI_PHDR_Hdr(raw(pkt)) assert HCI_Hdr in pkt assert L2CAP_InfoReq in pkt + HCI Commands = Create Connection cmd = HCI_Hdr(hex_bytes("0105040d76d56f95010018cc0200000001")) assert HCI_Cmd_Create_Connection in cmd assert cmd[HCI_Cmd_Create_Connection].bd_addr == "00:01:95:6f:d5:76" assert cmd[HCI_Cmd_Create_Connection].packet_type == 52248 assert cmd[HCI_Cmd_Create_Connection].page_scan_repetition_mode == 2 assert cmd[HCI_Cmd_Create_Connection].reserved == 0 assert cmd[HCI_Cmd_Create_Connection].clock_offset == 0 assert cmd[HCI_Cmd_Create_Connection].allow_role_switch == 1 = Authentication Requested cmd = HCI_Hdr(hex_bytes("011104020001")) assert HCI_Cmd_Authentication_Requested in cmd assert cmd[HCI_Cmd_Authentication_Requested].handle == 256 = Link Key Request Reply cmd = HCI_Hdr(hex_bytes("010b041676d56f9501006c9016a48a009180086a39200f03d3dd")) assert HCI_Cmd_Link_Key_Request_Reply in cmd assert cmd[HCI_Cmd_Link_Key_Request_Reply].bd_addr == "00:01:95:6f:d5:76" assert cmd[HCI_Cmd_Link_Key_Request_Reply].link_key == 0x6c9016a48a009180086a39200f03d3dd = Set Connection Encryption cmd = HCI_Hdr(hex_bytes("01130403000101")) assert HCI_Cmd_Set_Connection_Encryption in cmd assert cmd[HCI_Cmd_Set_Connection_Encryption].handle == 256 assert cmd[HCI_Cmd_Set_Connection_Encryption].encryption_enable == 1 = Remote Name Request cmd = HCI_Hdr(hex_bytes("0119040a76d56f95010002000000")) assert HCI_Cmd_Remote_Name_Request in cmd assert cmd[HCI_Cmd_Remote_Name_Request].bd_addr == "00:01:95:6f:d5:76" assert cmd[HCI_Cmd_Remote_Name_Request].page_scan_repetition_mode == 2 assert cmd[HCI_Cmd_Remote_Name_Request].reserved == 0 assert cmd[HCI_Cmd_Remote_Name_Request].clock_offset == 0 = 7.3.12 Read Local Name cmd = HCI_Hdr() / HCI_Command_Hdr() / HCI_Cmd_Read_Local_Name() assert raw(cmd) == hex_bytes("01140c00") # Response response = HCI_Hdr(hex_bytes("040efc01140c00546865726d6973746f7200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")) assert HCI_Cmd_Complete_Read_Local_Name in response assert response[HCI_Cmd_Complete_Read_Local_Name].local_name.decode('utf-8').rstrip('\x00') == 'Thermistor' assert response.answers(cmd) = 7.4.1 Read Local Version Information cmd = HCI_Hdr() / HCI_Command_Hdr() / HCI_Cmd_Read_Local_Version_Information() assert raw(cmd) == hex_bytes("01011000") # Response response = HCI_Hdr(hex_bytes("040e0c010110000900100931010c22")) assert HCI_Cmd_Complete_Read_Local_Version_Information in response assert response[HCI_Cmd_Complete_Read_Local_Version_Information].hci_version == 9 assert response[HCI_Cmd_Complete_Read_Local_Version_Information].hci_subversion == 4096 assert response[HCI_Cmd_Complete_Read_Local_Version_Information].lmp_version == 9 assert response[HCI_Cmd_Complete_Read_Local_Version_Information].company_identifier == 0x0131 assert response[HCI_Cmd_Complete_Read_Local_Version_Information].lmp_subversion == 8716 assert response.answers(cmd) = 7.4.4 Read Local Extended Features cmd = HCI_Hdr() / HCI_Command_Hdr() / HCI_Cmd_Read_Local_Extended_Features(page_number=1) assert raw(cmd) == hex_bytes("0104100101") # Response response = HCI_Hdr(hex_bytes("040e0e0104100001020000000000000000")) assert HCI_Cmd_Complete_Read_Local_Extended_Features in response assert response[HCI_Cmd_Complete_Read_Local_Extended_Features].page == 1 assert response[HCI_Cmd_Complete_Read_Local_Extended_Features].max_page == 2 assert response[HCI_Cmd_Complete_Read_Local_Extended_Features].extended_features == 0 assert response.answers(cmd) = LE Create Connection # Request data cmd = HCI_Hdr(hex_bytes("010d2019600060000001123456677890001800280000002a0000000000")) assert HCI_Cmd_LE_Create_Connection in cmd assert cmd[HCI_Cmd_LE_Create_Connection].paddr == '90:78:67:56:34:12' assert cmd[HCI_Cmd_LE_Create_Connection].patype == 1 # Response data pending = HCI_Hdr(hex_bytes("040f0400020d20")) assert pending.answers(cmd) complete = HCI_Hdr(hex_bytes("043e1301020000000112345667789000000000000000")) assert HCI_LE_Meta_Connection_Complete in complete assert complete[HCI_LE_Meta_Connection_Complete].paddr == '90:78:67:56:34:12' assert complete.answers(cmd) # Invalid combinations assert not cmd.answers(cmd) assert not pending.answers(pending) assert not complete.answers(complete) assert not pending.answers(complete) assert not complete.answers(pending) = LE Create Connection Cancel # Craft a request... expected_cmd_raw_data = hex_bytes("010e2000") cmd = HCI_Hdr() / HCI_Command_Hdr() / HCI_Cmd_LE_Create_Connection_Cancel() assert expected_cmd_raw_data == raw(cmd) assert raw(HCI_Hdr(expected_cmd_raw_data)) == expected_cmd_raw_data other_raw_data = hex_bytes("01060403341213") other_cmd = HCI_Hdr(other_raw_data) # Craft a response... for p in ( HCI_Event_Command_Complete(opcode=0x200e), HCI_Event_Command_Status(opcode=0x200e), ): res = HCI_Hdr() / HCI_Event_Hdr() / p # For debugging res # Check that the response packet thinks it is an answer to the request assert res.answers(cmd) # Check that it self isn't a match assert not res.answers(res) # Check that another request wouldn't match assert not res.answers(other_cmd) "OK!" = Disconnect expected_cmd_raw_data = hex_bytes("01060403341213") cmd_raw_data = raw(HCI_Hdr() / HCI_Command_Hdr() / HCI_Cmd_Disconnect(handle=0x1234)) assert expected_cmd_raw_data == cmd_raw_data = LE Connection Update Command expected_cmd_raw_data = hex_bytes("0113200e47000a00140001003c000100ffff") cmd_raw_data = raw( HCI_Hdr() / HCI_Command_Hdr() / HCI_Cmd_LE_Connection_Update( handle=0x47, min_interval=10, max_interval=20, latency=1, timeout=60, min_ce=1, max_ce=0xffff)) assert expected_cmd_raw_data == cmd_raw_data + HCI Events = Inquiry Complete evt_raw_data = hex_bytes("04010100") evt_pkt = HCI_Hdr(evt_raw_data) assert HCI_Event_Inquiry_Complete in evt_pkt assert evt_pkt[HCI_Event_Inquiry_Complete].status == 0 = Inquiry Result evt_pkt = HCI_Event_Inquiry_Result(b'\x01\xcb\x7f\xdbn\x8c\x9c\x01\x00\x00<\x04\x08\x8di') assert HCI_Event_Inquiry_Result in evt_pkt assert evt_pkt[HCI_Event_Inquiry_Result].num_response == 1 assert evt_pkt[HCI_Event_Inquiry_Result].addr[0] == '9c:8c:6e:db:7f:cb' assert evt_pkt[HCI_Event_Inquiry_Result].page_scan_repetition_mode[0] == 1 assert evt_pkt[HCI_Event_Inquiry_Result].device_class[0] == 0x8043c assert evt_pkt[HCI_Event_Inquiry_Result].clock_offset[0] == 27021 = Connection Complete evt_raw_data = hex_bytes("04030b000b00093491e5b7540100") evt_pkt = HCI_Hdr(evt_raw_data) assert HCI_Event_Connection_Complete in evt_pkt assert evt_pkt[HCI_Event_Connection_Complete].status == 0 assert evt_pkt[HCI_Event_Connection_Complete].handle == 0x000b assert evt_pkt[HCI_Event_Connection_Complete].bd_addr == "54:b7:e5:91:34:09" assert evt_pkt[HCI_Event_Connection_Complete].link_type == 1 assert evt_pkt[HCI_Event_Connection_Complete].encryption_enabled == 0 = Disconnection Complete evt_raw_data = hex_bytes("04050400400016") evt_pkt = HCI_Hdr(evt_raw_data) assert HCI_Event_Disconnection_Complete in evt_pkt assert evt_pkt[HCI_Event_Disconnection_Complete].status == 0 assert evt_pkt[HCI_Event_Disconnection_Complete].handle == 0x0040 assert evt_pkt[HCI_Event_Disconnection_Complete].reason == 0x16 = Remote Name Request Complete evt_raw_data = hex_bytes("0407ff0076d56f950100746573742d6c6170746f70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") evt_pkt = HCI_Hdr(evt_raw_data) assert HCI_Event_Remote_Name_Request_Complete in evt_pkt assert evt_pkt[HCI_Event_Remote_Name_Request_Complete].status == 0 assert evt_pkt[HCI_Event_Remote_Name_Request_Complete].bd_addr == "00:01:95:6f:d5:76" assert evt_pkt[HCI_Event_Remote_Name_Request_Complete].remote_name == b"test-laptop".ljust(248, b"\x00") = Encryption Change evt_raw_data = hex_bytes("040804000b0001") evt_pkt = HCI_Hdr(evt_raw_data) assert HCI_Event_Encryption_Change in evt_pkt assert evt_pkt[HCI_Event_Encryption_Change].status == 0 assert evt_pkt[HCI_Event_Encryption_Change].handle == 0x000b assert evt_pkt[HCI_Event_Encryption_Change].enabled == 1 = Read Remote Supported Features Complete evt_raw_data = hex_bytes("040b0b000b00fffe8ffedbff5b87") evt_pkt = HCI_Hdr(evt_raw_data) assert HCI_Event_Read_Remote_Supported_Features_Complete in evt_pkt assert evt_pkt[HCI_Event_Read_Remote_Supported_Features_Complete].status == 0 assert evt_pkt[HCI_Event_Read_Remote_Supported_Features_Complete].handle == 0x000b assert evt_pkt[HCI_Event_Read_Remote_Supported_Features_Complete].lmp_features == 0x875bffdbfe8ffeff = Read Remote Version Information Complete evt_raw_data = hex_bytes("040c080002000bb0022c04") evt_pkt = HCI_Hdr(evt_raw_data) assert HCI_Event_Read_Remote_Version_Information_Complete in evt_pkt assert evt_pkt[HCI_Event_Read_Remote_Version_Information_Complete].status == 0 assert evt_pkt[HCI_Event_Read_Remote_Version_Information_Complete].handle == 0x0002 assert evt_pkt[HCI_Event_Read_Remote_Version_Information_Complete].version == 0x0b assert evt_pkt[HCI_Event_Read_Remote_Version_Information_Complete].manufacturer_name == 0x02b0 assert evt_pkt[HCI_Event_Read_Remote_Version_Information_Complete].subversion == 1068 = Command Complete evt_raw_data = hex_bytes("040e0a010b04002587ceedd668") evt_pkt = HCI_Hdr(evt_raw_data) assert HCI_Event_Command_Complete in evt_pkt assert evt_pkt[HCI_Event_Command_Complete].number == 1 assert evt_pkt[HCI_Event_Command_Complete].opcode == 0x040b assert evt_pkt[HCI_Event_Command_Complete].status == 0 = Command Status evt_raw_data = hex_bytes("040f0400011904") evt_pkt = HCI_Hdr(evt_raw_data) assert HCI_Event_Command_Status in evt_pkt assert evt_pkt[HCI_Event_Command_Status].status == 0 assert evt_pkt[HCI_Event_Command_Status].number == 1 assert evt_pkt[HCI_Event_Command_Status].opcode == 0x0419 = Number Of Completed Packets evt_raw_data = hex_bytes("0413050103000300") evt_pkt = HCI_Hdr(evt_raw_data) assert HCI_Event_Number_Of_Completed_Packets in evt_pkt assert evt_pkt[HCI_Event_Number_Of_Completed_Packets].num_handles == 1 assert evt_pkt[HCI_Event_Number_Of_Completed_Packets].connection_handle_list[0] == 0x0003 assert evt_pkt[HCI_Event_Number_Of_Completed_Packets].num_completed_packets_list[0] == 3 = Link Key Request evt_raw_data = hex_bytes("041706093491e5b754") evt_pkt = HCI_Hdr(evt_raw_data) assert HCI_Event_Link_Key_Request in evt_pkt assert evt_pkt[HCI_Event_Link_Key_Request].bd_addr == '54:b7:e5:91:34:09' = Inquiry Result with RSSI # TODO = Read Remote Extended Features Complete evt_raw_data = hex_bytes("04230d000b0001020300000000000000") evt_pkt = HCI_Hdr(evt_raw_data) assert HCI_Event_Read_Remote_Extended_Features_Complete in evt_pkt assert evt_pkt[HCI_Event_Read_Remote_Extended_Features_Complete].status == 0 assert evt_pkt[HCI_Event_Read_Remote_Extended_Features_Complete].handle == 0x000b assert evt_pkt[HCI_Event_Read_Remote_Extended_Features_Complete].page == 1 assert evt_pkt[HCI_Event_Read_Remote_Extended_Features_Complete].max_page == 2 assert evt_pkt[HCI_Event_Read_Remote_Extended_Features_Complete].extended_features == 0x0000000000000003 = Extended Inquiry Result evt_raw_data = hex_bytes("042fff01093491e5b75401001404247c37c2091001000a00ffffffff020a040b020d110b110a110e110f110c095354414e4d4f524520494900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") evt_pkt = HCI_Hdr(evt_raw_data) assert HCI_Event_Extended_Inquiry_Result in evt_pkt assert evt_pkt[HCI_Event_Extended_Inquiry_Result].num_response == 1 assert evt_pkt[HCI_Event_Extended_Inquiry_Result].bd_addr == '54:b7:e5:91:34:09' assert evt_pkt[HCI_Event_Extended_Inquiry_Result].page_scan_repetition_mode == 1 assert evt_pkt[HCI_Event_Extended_Inquiry_Result].device_class == 0x240414 assert evt_pkt[HCI_Event_Extended_Inquiry_Result].clock_offset == 0x377c assert evt_pkt[HCI_Event_Extended_Inquiry_Result].rssi == -62 assert EIR_Hdr in evt_pkt[HCI_Event_Extended_Inquiry_Result].eir_data[0] assert Raw in evt_pkt[HCI_Event_Extended_Inquiry_Result].eir_data[-1] assert len(evt_pkt[HCI_Event_Extended_Inquiry_Result].eir_data[-1].load) == 200 = IO Capability Response evt_raw_data = hex_bytes("043209093491e5b754030002") evt_pkt = HCI_Hdr(evt_raw_data) assert HCI_Event_IO_Capability_Response in evt_pkt assert evt_pkt[HCI_Event_IO_Capability_Response].bd_addr == '54:b7:e5:91:34:09' assert evt_pkt[HCI_Event_IO_Capability_Response].io_capability == 0x03 assert evt_pkt[HCI_Event_IO_Capability_Response].oob_data_present == 0 assert evt_pkt[HCI_Event_IO_Capability_Response].authentication_requirements == 0x02 = LE Meta evt_raw_data = hex_bytes("043e0414400000") evt_pkt = HCI_Hdr(evt_raw_data) assert HCI_Event_LE_Meta in evt_pkt assert evt_pkt[HCI_Event_LE_Meta].event == 0x14 = LE Connection Update Event evt_raw_data = hex_bytes("043e0a03004800140001003c00") evt_pkt = HCI_Hdr(evt_raw_data) assert evt_pkt[HCI_LE_Meta_Connection_Update_Complete].handle == 0x48 assert evt_pkt[HCI_LE_Meta_Connection_Update_Complete].interval == 20 assert evt_pkt[HCI_LE_Meta_Connection_Update_Complete].latency == 1 assert evt_pkt[HCI_LE_Meta_Connection_Update_Complete].timeout == 60 + Bluetooth LE Advertising / Scan Response Data Parsing = Parse EIR_IncompleteList32BitServiceUUIDs p = HCI_Hdr(hex_bytes('042fff019cc888f640c401000c025af32cb09904f6dc73222396f640c40c025a40dbca09000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000')) assert EIR_IncompleteList32BitServiceUUIDs in p assert len(p[EIR_IncompleteList32BitServiceUUIDs].svc_uuids) == 38 = Parse EIR_CompleteList32BitServiceUUIDs p = HCI_Hdr(hex_bytes('042fff0106ec883aef1801003c04285758b30e0954562064656c2073616cc3b36e09030a110c110e1100120105810700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000')) assert EIR_CompleteList32BitServiceUUIDs in p assert p[EIR_CompleteList32BitServiceUUIDs].svc_uuids == [] = Parse EIR_ClassOfDevice p = HCI_Hdr(hex_bytes('043e2b020100000a1bb44ce0001f02010503ff000106084d4920524303021218040d040500020a0004fe06ec88a2')) assert EIR_ClassOfDevice in p assert p[EIR_ClassOfDevice].major_service_classes == 0 assert p[EIR_ClassOfDevice].major_device_class == 5 assert p[EIR_ClassOfDevice].minor_device_class == 1 = Parse EIR_ServiceData32BitUUID p = HCI_Hdr(hex_bytes('042fff01c47c80894df801000c0128a269a30c4a125d13f30196894df80c012820f61a1a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000')) assert EIR_ServiceData32BitUUID in p assert p[EIR_ServiceData32BitUUID].svc_uuid == 0x001a1af6 = Parse EIR_Flags, EIR_CompleteList16BitServiceUUIDs, EIR_CompleteLocalName and EIR_TX_Power_Level ad_report_raw_data = \ hex_bytes("043e2b020100016522c00181781f0201020303d9fe1409" \ "506562626c652054696d65204c452037314536020a0cde") scapy_packet = HCI_Hdr(ad_report_raw_data) assert scapy_packet[EIR_Flags].flags == 0x02 assert scapy_packet[EIR_CompleteList16BitServiceUUIDs].svc_uuids == [0xfed9] assert scapy_packet[EIR_CompleteLocalName].local_name == b'Pebble Time LE 71E6' assert scapy_packet[EIR_TX_Power_Level].level == 12 = Parse EIR_Manufacturer_Specific_Data scan_resp_raw_data = \ hex_bytes("043e2302010401be5e0eb9f04f1716ff5401005f423331" \ "3134374432343631fc00030c0000de") scapy_packet = HCI_Hdr(scan_resp_raw_data) assert raw(scapy_packet[EIR_Manufacturer_Specific_Data].payload) == b'\x00_B31147D2461\xfc\x00\x03\x0c\x00\x00' assert scapy_packet[EIR_Manufacturer_Specific_Data].company_id == 0x154 = Parse EIR_Manufacturer_Specific_Data with magic class ScapyManufacturerPacket(Packet): magic = b'SCAPY!' fields_desc = [ StrFixedLenField("header", magic, len(magic)), ShortField("x", None), ] class ScapyManufacturerPacket2(Packet): magic = b'!SCAPY' fields_desc = [ StrFixedLenField("header", magic, len(magic)), ShortField("y", None), ] @classmethod def magic_check(cls, payload): return payload.startswith(cls.magic) EIR_Manufacturer_Specific_Data.register_magic_payload( ScapyManufacturerPacket, lambda p: p.startswith(ScapyManufacturerPacket.magic)) EIR_Manufacturer_Specific_Data.register_magic_payload(ScapyManufacturerPacket2) # Test decode p = EIR_Hdr(b'\x0b\xff\xff\xffSCAPY!\xab\x12') p.show() assert p[EIR_Manufacturer_Specific_Data].company_id == 0xffff assert p[ScapyManufacturerPacket].x == 0xab12 p = EIR_Hdr(b'\x0b\xff\xff\xff!SCAPY\x12\x34') p.show() assert p[EIR_Manufacturer_Specific_Data].company_id == 0xffff assert p[ScapyManufacturerPacket2].y == 0x1234 # Test encode p = EIR_Hdr()/EIR_Manufacturer_Specific_Data(company_id=0xffff)/ScapyManufacturerPacket(x=0x5678) assert raw(p) == b'\x0b\xff\xff\xffSCAPY!\x56\x78' # Test bad setup try: EIR_Manufacturer_Specific_Data.register_magic_payload(conf.raw_layer) except TypeError: pass else: assert False, "expected exception" = Parse EIR_ServiceData16BitUUID d = hex_bytes("043e1902010001abcdef7da97f0d020102030350fe051650fee6c2ac") p = HCI_Hdr(d) p.show() assert p[EIR_CompleteList16BitServiceUUIDs].svc_uuids == [0xfe50] assert p[EIR_ServiceData16BitUUID].svc_uuid == 0xfe50 assert raw(p[EIR_ServiceData16BitUUID].payload) == hex_bytes("e6c2") = Basic L2CAP dissect a = L2CAP_Hdr(b'\x08\x00\x06\x00\t\x00\xf6\xe5\xd4\xc3\xb2\xa1') assert a[SM_Identity_Address_Information].address == 'a1:b2:c3:d4:e5:f6' assert a[SM_Identity_Address_Information].atype == 0 a.show() = Basic HCI_ACL_Hdr build & dissect a = HCI_Hdr()/HCI_ACL_Hdr(handle=0xf4c, PB=2, BC=2, len=20)/L2CAP_Hdr(len=16)/L2CAP_CmdHdr(code=8, len=12)/L2CAP_EchoReq(data="AAAAAAAAAAAA") assert raw(a) == b'\x02L\xaf\x14\x00\x10\x00\x05\x00\x08\x00\x0c\x00AAAAAAAAAAAA' b = HCI_Hdr(raw(a)) assert a == b = Complex HCI - L2CAP build a = HCI_Hdr()/HCI_ACL_Hdr()/L2CAP_Hdr()/L2CAP_CmdHdr()/L2CAP_ConnReq(scid=1) assert raw(a) == b'\x02\x00\x00\x0c\x00\x08\x00\x05\x00\x02\x00\x04\x00\x00\x00\x01\x00' a.show() = Complex HCI - L2CAP dissect a = HCI_Hdr(b'\x02\x00\x00\x11\x00\r\x00\x05\x00\x0b\x00\t\x00\x01\x00\x00\x00debug') assert a[L2CAP_InfoResp].result == 0 assert a[L2CAP_InfoResp].data == b"debug" = HCI - L2CAP Echo test rq = HCI_Hdr()/HCI_ACL_Hdr()/L2CAP_Hdr()/L2CAP_CmdHdr()/L2CAP_EchoReq(data=b"data") assert bytes(rq) == b'\x02\x00\x00\x0c\x00\x08\x00\x05\x00\x08\x00\x04\x00data' rsp = HCI_Hdr()/HCI_ACL_Hdr()/L2CAP_Hdr()/L2CAP_CmdHdr()/L2CAP_EchoResp(data=b"data") assert bytes(rsp) == b'\x02\x00\x00\x0c\x00\x08\x00\x05\x00\t\x00\x04\x00data' assert rsp.answers(rq) = HCI - L2CAP Create Channel request p = HCI_Hdr()/HCI_ACL_Hdr()/L2CAP_Hdr()/L2CAP_CmdHdr()/L2CAP_Create_Channel_Request(psm="SDP") assert bytes(p) == b'\x02\x00\x00\r\x00\t\x00\x05\x00\x0c\x00\x05\x00\x01\x00\x00\x00\x00' p = HCI_Hdr(bytes(p)) assert p[L2CAP_Create_Channel_Request].psm == 1 = L2CAP Conn Answers a = HCI_Hdr(b'\x02\x00\x00\x0c\x00\x08\x00\x05\x00\x02\x00\x04\x00\x00\x00\x9a;') b = HCI_Hdr(b'\x02\x00\x00\x10\x00\x0c\x00\x05\x00\x03\x00\x08\x00\xff\xff\x9a;\x00\x00\x01\x00') assert b.answers(a) assert not a.answers(b) a = HCI_Hdr(b'\x02\x00\x00\x0c\x00\x08\x00\x05\x00\x04\x00\x04\x00\x15\x00\x00\x00') b = HCI_Hdr(b'\x02\x00\x00\x0e\x00\n\x00\x05\x00\x05\x00\x06\x00\x15\x00\x00\x00\x02\x00') assert b.answers(a) assert not a.answers(b) = EIR_Hdr - HCI_LE_Meta_Advertising_Report (single report) a = HCI_Hdr()/HCI_Event_Hdr()/HCI_Event_LE_Meta()/HCI_LE_Meta_Advertising_Reports(reports=[ HCI_LE_Meta_Advertising_Report( addr="a1:b2:c3:d4:e5:f6", data=[ EIR_Hdr()/EIR_Flags(flags=['br_edr_not_supported']), EIR_Hdr()/EIR_CompleteLocalName(local_name="scapy"), ] ) ]) assert raw(a) == b'\x04>\x16\x02\x01\x00\x00\xf6\xe5\xd4\xc3\xb2\xa1\n\x02\x01\x04\x06\tscapy\x00' b = HCI_Hdr(raw(a)) b.show() assert b[HCI_Event_Hdr].len > 0 assert b[EIR_CompleteLocalName].local_name == b"scapy" assert b[HCI_LE_Meta_Advertising_Report].addr == "a1:b2:c3:d4:e5:f6" assert a.summary() == "HCI Event / HCI_Event_Hdr / HCI_Event_LE_Meta / HCI_LE_Meta_Advertising_Reports" = EIR_Hdr - HCI_LE_Meta_Advertising_Report (duplicate reports) # When duplicate reports are allowed, there are "Connectable Unidirected # Advertising" reports, and "Scan Responses", for the same device/MAC, in the # same packet. a = HCI_Hdr()/HCI_Event_Hdr()/HCI_Event_LE_Meta()/HCI_LE_Meta_Advertising_Reports(reports=[ HCI_LE_Meta_Advertising_Report( addr="a1:b2:c3:d4:e5:f6", data=[ EIR_Hdr()/EIR_Flags(flags=['br_edr_not_supported']), EIR_Hdr()/EIR_CompleteLocalName(local_name="scapy"), ] ), HCI_LE_Meta_Advertising_Report( type=4, # Scan Response addr="a1:b2:c3:d4:e5:f6", data=[ EIR_Hdr()/EIR_Manufacturer_Specific_Data( company_id=0xffff, )/Raw(b"ypacs"), EIR_Hdr()/EIR_TX_Power_Level(level=10), EIR_Hdr()/EIR_CompleteList128BitServiceUUIDs(svc_uuids=[ "01234567-89ab-cdef-1023-456789abcdfe", ]) ] ) ]) assert raw(a) == b'\x04>>\x02\x02\x00\x00\xf6\xe5\xd4\xc3\xb2\xa1\n\x02\x01\x04\x06\tscapy\x00\x04\x00\xf6\xe5\xd4\xc3\xb2\xa1\x1e\x08\xff\xff\xffypacs\x02\n\n\x11\x07\xfe\xcd\xab\x89gE#\x10\xef\xcd\xab\x89gE#\x01\x00' b = HCI_Hdr(raw(a)) b.show() assert b[HCI_Event_Hdr].len > 0 assert b[EIR_CompleteLocalName].local_name == b"scapy" assert b[HCI_LE_Meta_Advertising_Report].addr == "a1:b2:c3:d4:e5:f6" assert b[EIR_Manufacturer_Specific_Data].company_id == 0xffff assert raw(b[EIR_Manufacturer_Specific_Data].payload) == b"ypacs" assert b[EIR_TX_Power_Level].level == 10 assert b[EIR_CompleteList128BitServiceUUIDs].svc_uuids[0] == UUID("01234567-89ab-cdef-1023-456789abcdfe") assert a.summary() == "HCI Event / HCI_Event_Hdr / HCI_Event_LE_Meta / HCI_LE_Meta_Advertising_Reports" = ATT_Hdr - misc a = HCI_Hdr()/HCI_ACL_Hdr()/L2CAP_Hdr()/ATT_Hdr()/ATT_Read_By_Type_Request_128bit(uuid1=0xa14, uuid2=0xa24) a = HCI_Hdr(raw(a)) a.show() a.mysummary() assert ATT_Read_By_Type_Request_128bit in a assert not Raw in a b = HCI_Hdr()/HCI_ACL_Hdr()/L2CAP_Hdr()/ATT_Hdr()/ATT_Read_By_Type_Request(uuid=0xa14) b = HCI_Hdr(raw(b)) b.show() b.mysummary() assert ATT_Read_By_Type_Request in b assert not Raw in b = ATT Read_By_Type_Response pkt = HCI_Hdr(hex_bytes('0248201b001700040009070200020300002a0400020500012a0600020700042a')) assert pkt[ATT_Read_By_Type_Response].len == 7 assert len(pkt.handles) == 3 assert pkt.handles[0].handle == 0x2 assert pkt.handles[1].handle == 0x4 assert pkt.handles[2].handle == 0x6 pkt.handles[0].value == b'\x02\x03\x00\x00*' pkt.handles[1].value == b'\x02\x05\x00\x01*' pkt.handles[2].value == b'\x02\x07\x00\x04*' = SM_Public_Key() tests r = raw(SM_Hdr()/SM_Public_Key(key_x="sca", key_y="py")) assert r == b'\x0csca\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00py\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' p = SM_Hdr(r) assert SM_Public_Key in p and p.key_x[:3] == b"sca" and p.key_y[:2] == b"py" = SM_DHKey_Check() tests r = raw(SM_Hdr()/SM_DHKey_Check(dhkey_check="scapy")) assert r == b'\rscapy\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' p = SM_Hdr(r) assert SM_DHKey_Check in p and p.dhkey_check[:5] == b"scapy" + HCIMon tests = HCI_Mon - Bluetooth Monitor Pcap Header p = HCI_Mon_Pcap_Hdr(hex_bytes("00000008")) assert HCI_Mon_Pcap_Hdr in p assert p[HCI_Mon_Pcap_Hdr].adapter_id == 0 assert p[HCI_Mon_Pcap_Hdr].opcode == 8 = HCI_Mon - Bluetooth Monitor HCI_Mon_New_Index p = HCI_Mon_Pcap_Hdr(hex_bytes("0000000000030000109a81206863693000000000")) assert HCI_Mon_New_Index in p assert p[HCI_Mon_New_Index].bus == 0 assert p[HCI_Mon_New_Index].type == 3 assert p[HCI_Mon_New_Index].addr == '20:81:9a:10:00:00' assert p[HCI_Mon_New_Index].devname.decode('utf-8').rstrip('\x00') == 'hci0' = HCI_Mon - Bluetooth Monitor HCI_Mon_Delete_Index p = HCI_Mon_Pcap_Hdr(hex_bytes("00000001")) assert HCI_Mon_Pcap_Hdr in p assert p[HCI_Mon_Pcap_Hdr].opcode == 1 = HCI_Mon - Bluetooth Monitor HCI_Mon_Index_Info p = HCI_Mon_Pcap_Hdr(hex_bytes("0000000a0000109a81203101")) assert HCI_Mon_Index_Info in p assert p[HCI_Mon_Index_Info].addr == '20:81:9a:10:00:00' assert p[HCI_Mon_Index_Info].manufacturer == 0x131 = HCI_Mon - Bluetooth Monitor HCI_Mon_System_Note p = HCI_Mon_Pcap_Hdr(hex_bytes("ffff000c426c7565746f6f74682073756273797374656d2076657273696f6e20322e323200")) assert HCI_Mon_System_Note in p assert p[HCI_Mon_System_Note].note == b'Bluetooth subsystem version 2.22'