| % Scapy Bluetooth layer tests |
| |
| + Bluetooth tests |
| |
| = HCI layers |
| # a crazy packet with all classes in it! |
| pkt = HCI_ACL_Hdr()/HCI_Cmd_Complete_Read_BD_Addr()/HCI_Cmd_Connect_Accept_Timeout()/HCI_Cmd_Disconnect()/HCI_Cmd_LE_Connection_Update()/HCI_Cmd_LE_Create_Connection()/HCI_Cmd_LE_Create_Connection_Cancel()/HCI_Cmd_LE_Host_Supported()/HCI_Cmd_LE_Long_Term_Key_Request_Negative_Reply()/HCI_Cmd_LE_Long_Term_Key_Request_Reply()/HCI_Cmd_LE_Read_Buffer_Size()/HCI_Cmd_LE_Set_Advertise_Enable()/HCI_Cmd_LE_Set_Advertising_Data()/HCI_Cmd_LE_Set_Advertising_Parameters()/HCI_Cmd_LE_Set_Random_Address()/HCI_Cmd_LE_Set_Scan_Enable()/HCI_Cmd_LE_Set_Scan_Parameters()/HCI_Cmd_LE_Start_Encryption_Request()/HCI_Cmd_Read_BD_Addr()/HCI_Cmd_Reset()/HCI_Cmd_Set_Event_Filter()/HCI_Cmd_Set_Event_Mask()/HCI_Command_Hdr()/HCI_Event_Command_Complete()/HCI_Event_Command_Status()/HCI_Event_Disconnection_Complete()/HCI_Event_Encryption_Change()/HCI_Event_Hdr()/HCI_Event_LE_Meta()/HCI_Event_Number_Of_Completed_Packets()/HCI_Hdr()/HCI_LE_Meta_Advertising_Report()/HCI_LE_Meta_Connection_Complete()/HCI_LE_Meta_Connection_Update_Complete()/HCI_LE_Meta_Long_Term_Key_Request() |
| assert HCI_ACL_Hdr in pkt.layers() |
| assert HCI_Cmd_Complete_Read_BD_Addr in pkt.layers() |
| assert HCI_Cmd_Connect_Accept_Timeout in pkt.layers() |
| assert HCI_Cmd_Disconnect in pkt.layers() |
| assert HCI_Cmd_LE_Connection_Update in pkt.layers() |
| assert HCI_Cmd_LE_Create_Connection in pkt.layers() |
| assert HCI_Cmd_LE_Create_Connection_Cancel in pkt.layers() |
| assert HCI_Cmd_LE_Host_Supported in pkt.layers() |
| assert HCI_Cmd_LE_Long_Term_Key_Request_Negative_Reply in pkt.layers() |
| assert HCI_Cmd_LE_Long_Term_Key_Request_Reply in pkt.layers() |
| assert HCI_Cmd_LE_Read_Buffer_Size in pkt.layers() |
| assert HCI_Cmd_LE_Set_Advertise_Enable in pkt.layers() |
| assert HCI_Cmd_LE_Set_Advertising_Data in pkt.layers() |
| assert HCI_Cmd_LE_Set_Advertising_Parameters in pkt.layers() |
| assert HCI_Cmd_LE_Set_Random_Address in pkt.layers() |
| assert HCI_Cmd_LE_Set_Scan_Enable in pkt.layers() |
| assert HCI_Cmd_LE_Set_Scan_Parameters in pkt.layers() |
| assert HCI_Cmd_LE_Start_Encryption_Request in pkt.layers() |
| assert HCI_Cmd_Read_BD_Addr in pkt.layers() |
| assert HCI_Cmd_Reset in pkt.layers() |
| assert HCI_Cmd_Set_Event_Filter in pkt.layers() |
| assert HCI_Cmd_Set_Event_Mask in pkt.layers() |
| assert HCI_Command_Hdr in pkt.layers() |
| assert HCI_Event_Command_Complete in pkt.layers() |
| assert HCI_Event_Command_Status in pkt.layers() |
| assert HCI_Event_Disconnection_Complete in pkt.layers() |
| assert HCI_Event_Encryption_Change in pkt.layers() |
| assert HCI_Event_Hdr in pkt.layers() |
| assert HCI_Event_LE_Meta in pkt.layers() |
| assert HCI_Event_Number_Of_Completed_Packets in pkt.layers() |
| assert HCI_Hdr in pkt.layers() |
| assert HCI_LE_Meta_Advertising_Report in pkt.layers() |
| assert HCI_LE_Meta_Connection_Complete in pkt.layers() |
| assert HCI_LE_Meta_Connection_Update_Complete in pkt.layers() |
| assert HCI_LE_Meta_Long_Term_Key_Request in pkt.layers() |
| |
| + 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 |
| |
| = LE Create Connection Cancel |
| |
| expected_cmd_raw_data = hex_bytes("010e2000") |
| cmd_raw_data = raw(HCI_Hdr() / HCI_Command_Hdr() / HCI_Cmd_LE_Create_Connection_Cancel()) |
| assert(expected_cmd_raw_data == cmd_raw_data) |
| |
| = 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 |
| = 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_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(scapy_packet[EIR_Manufacturer_Specific_Data].data == b'\x00_B31147D2461\xfc\x00\x03\x0c\x00\x00') |
| assert(scapy_packet[EIR_Manufacturer_Specific_Data].company_id == 0x154) |
| |
| = 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)/Raw("A"*12) |
| 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" |
| |
| = 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\x9a;\x00\x00\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 - misc |
| a = HCI_Hdr()/HCI_Event_Hdr()/HCI_Event_LE_Meta()/HCI_LE_Meta_Advertising_Report(addr = "a1:b2:c3:d4:e5:f6", data=EIR_Hdr()/EIR_CompleteLocalName(local_name="scapy")) |
| assert raw(a) == b'\x04>\x00\x02\x00\x00\x00\xf6\xe5\xd4\xc3\xb2\xa1\x07\x06\tscapy\x00' |
| b = HCI_Hdr(raw(a)) |
| assert b.data[0][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_Report" |
| |
| = 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 |
| |
| = L2CAP layers |
| |
| # a crazy packet with all classes in it! |
| pkt = L2CAP_CmdHdr()/L2CAP_CmdRej()/L2CAP_ConfReq()/L2CAP_ConfResp()/L2CAP_ConnReq()/L2CAP_ConnResp()/L2CAP_Connection_Parameter_Update_Request()/L2CAP_Connection_Parameter_Update_Response()/L2CAP_DisconnReq()/L2CAP_DisconnResp()/L2CAP_Hdr()/L2CAP_InfoReq()/L2CAP_InfoResp() |
| assert L2CAP_CmdHdr in pkt.layers() |
| assert L2CAP_CmdRej in pkt.layers() |
| assert L2CAP_ConfReq in pkt.layers() |
| assert L2CAP_ConfResp in pkt.layers() |
| assert L2CAP_ConnReq in pkt.layers() |
| assert L2CAP_ConnResp in pkt.layers() |
| assert L2CAP_Connection_Parameter_Update_Request in pkt.layers() |
| assert L2CAP_Connection_Parameter_Update_Response in pkt.layers() |
| assert L2CAP_DisconnReq in pkt.layers() |
| assert L2CAP_DisconnResp in pkt.layers() |
| assert L2CAP_Hdr in pkt.layers() |
| assert L2CAP_InfoReq in pkt.layers() |
| assert L2CAP_InfoResp in pkt.layers() |