Bluetooth Low Energy protocol

Mirage includes a lot of software components allowing to communicate with Bluetooth Low Energy (BLE) devices. This page presents a subset of these components, and provides some basic examples presenting their usage.

Bluetooth Low Energy modules

Mirage includes many modules allowing to analyze the security of Bluetooth Low Energy communications. These modules can perform attacks or useful actions in order to manipulate a Bluetooth Low Energy device. The available modules and the links to the corresponding documentation pages are listed in the following table :

Name

Description

Documentation

ble_info

This module displays useful informations about a given interface.

here

ble_connect

This module connects to a Peripheral’s device as Central.

here

ble_master

This module simulates a Central device.

here

ble_slave

This module simulates a Peripheral device.

here

ble_discover

This module allows to dump the ATT/GATT database of a Peripheral.

here

ble_adv

This module sends advertisements.

here

ble_scan

This module discovers Advertisers and Peripherals by scanning advertisements.

here

ble_pair

This module performs a pairing with a Peripheral or a Central.

here

ble_mitm

This module performs a Man-in-the-Middle attack.

here

ble_sniff

This module sniffs the advertisements and new / existing connections.

here

ble_jam

This module jams the advertisements or connections.

here

ble_hijack

This module hijacks an existing connection.

here

ble_crack

This module cracks a Temporary Key.

here

ble_monitor

This module monitors an HCI communication.

here

Importing the Bluetooth Low Energy software components

Every software component described in this page can be easily imported from a module or a :doc:`scenario <scenarios>`_ environment using the following statement :

from mirage.libs import ble

Then, every component is available using the ble namespace :

packet = ble.BLEReadRequest(handle=0x0021)

Interacting with the protocol

Mirage can use multiple hardware component in order to interact with the protocol : it provides some drivers supporting standard HCI devices or the most used sniffers (such as BTLEJack, Ubertooth or NRFSniffer). You can also monitor an HCI communication using ADB or HCIDump. Finally, you can read or write a PCAP file containing Link Layer packets using the PCAP Device. Every devices can be used to send and/or receive BLE frames but can also provide some specific features by providing shared methods. The supported Devices are listed here.

If you want to manipulate a specific device, you need to use the corresponding Emitter and / or Receiver with an interface related to your device. The following page explains how to use these software components.

Bluetooth Low Energy packets

Mirage manipulates the Bluetooth Low Energy packets as child classes of BLEPacket (mirage.libs.ble_utils.packets.BLEPacket), which is itself a child class of Packet (mirage.libs.wireless_utils.packets.Packet). The following list describes the available packets and provides some links to the corresponding documentation pages :

If you use a sniffer such as BTLEJack,`NRFSniffer <devices.html#nrfsniffer-device>`_ or Ubertooth, some additional informations provided by the sniffer can be included in the packet using the additionalInformations attribute. The additional informations are stored as instance of the class BLESniffingParameters (mirage.libs.ble_utils.packets.BLESniffingParameters).

ATT, GATT and Security Manager Dissectors

Some Bluetooth Low Energy packets may include complex fields, that’s why Mirage provides some dissectors allowing to easily manipulate them. A dissector is a class allowing to easily convert a complex data structure to the corresponding raw bytes, or the raw bytes to the corresponding data structure. Every Bluetooth Low Energy dissectors inherits from Dissector (mirage.libs.wireless_utils.dissectors) and are documented here.

The Dissector class includes some magic methods in order to facilite the manipulation of the complex data structure. Indeed, it is represented as a dictionary, but every key of this dictionary can be accessed as a standard attribute of the class. Two main methods are provided, build (allowing to convert the data structure to the corresponding raw bytes) and dissect (allowing to convert the raw bytes to the corresponding data structure). The complex data structure is stored in the attribute named content while the raw bytes are stored in the attribute named data.

Mirage provides a dissector for the permissions Flag linked to the ATT/GATT layers (mirage.libs.ble_utils.dissectors.PermissionsFlag):

Example
>>> dissector=PermissionsFlag(permissions=["Write", "Read"])
>>> dissector.data.hex()
'0a'
>>> dissector2=PermissionsFlag(data=bytes.fromhex("0a"))
>>> dissector2.permissions
['Write', 'Read']
>>> for permission in dissector2:
...     print(permission)
...
Write
Read
>>> dissector2.permissions += ["Write Without Response"]
>>> dissector2.data.hex()
'0e'
>>> dissector.data = bytes.fromhex("0e")
>>> dissector.dissect()
>>> dissector.permissions
['Write', 'Write Without Response', 'Read']

You can also manipulate the UUID, commonly used in Bluetooth Low Energy communications (mirage.libs.ble_utils.dissectors.UUID) :

Example
>>> UUID(name="Generic Access").data.hex()
'1800'
>>> UUID(data=bytes.fromhex('1800')).name
'Generic Access'
>>> UUID(data=bytes.fromhex('1800')).UUID16
6144
>>> UUID(data=bytes.fromhex('1800')).UUID128.hex()
'0000180000001000800000805f9b34fb'
>>> UUID(data=bytes.fromhex('1801'))
UUID(128bits:00001801-0000-1000-8000-00805f9b34fb, 16bits:0x1801, name:Generic Attribute )

Mirage allows to manipulate some datas stored in an ATT / GATT server using the following dissectors :

  • CharacteristicDeclaration (mirage.libs.ble_utils.dissectors.CharacteristicDeclaration) :

    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))
    >>> CharacteristicDeclaration(data=bytes.fromhex('2a00000302')).UUID
    UUID(128bits:00002a00-0000-1000-8000-00805f9b34fb, 16bits:0x2a00, name:Device Name )
    >>> CharacteristicDeclaration(data=bytes.fromhex('2a00000302')).valueHandle
    3
    >>> CharacteristicDeclaration(data=bytes.fromhex('2a00000302')).permissionsFlag
    Flag(Read)
    >>> CharacteristicDeclaration(UUID=UUID(name="Device Name"),valueHandle=0x0003,permissionsFlag=PermissionsFlag(permissions=["Read"])).data.hex()
    '2a00000302'
    
  • CharacteristicDescriptor (mirage.libs.ble_utils.dissectors.CharacteristicDescriptor) : :Example:

    >>> CharacteristicDescriptor(data=bytes.fromhex("2901"))
    Characteristic Descriptor( UUID=UUID(128bits:00002901-0000-1000-8000-00805f9b34fb, 16bits:0x2901, name:Characteristic User Description ) )
    >>> CharacteristicDescriptor(UUID=UUID(UUID16=0x2901)).data.hex()
    '2901'
    
  • Service (mirage.libs.ble_utils.dissectors.Service) : :Example:

    >>> Service(data=bytes.fromhex("1800"))
    Service( UUID=UUID(128bits:00001800-0000-1000-8000-00805f9b34fb, 16bits:0x1800, name:Generic Access ) )
    >>> Service(data=bytes.fromhex("1800")).UUID
    UUID(128bits:00001800-0000-1000-8000-00805f9b34fb, 16bits:0x1800, name:Generic Access )
    >>> Service(UUID=UUID(UUID16=0x1800)).data.hex()
    '1800'
    

Finally, Mirage allows to manipulate some complex data structure used in the Security Manager (SM) layer :

  • InputOutputCapability (mirage.libs.ble_utils.dissectors.InputOutputCapability) : :Example:

    >>> InputOutputCapability(display=True, yesno=False, keyboard=True).data.hex()
    '04'
    >>> InputOutputCapability(data=data=bytes.fromhex("04"))
    Input Output Capability(0x4,keyboard:yes|yesno:no|display:yes)
    
  • AuthReqFlag (mirage.libs.ble_utils.dissectors.AuthReqFlag) : :Example:

    >>> AuthReqFlag(bonding=True, mitm=True).data.hex()
    '05'
    >>> AuthReqFlag(data=data=bytes.fromhex("05"))
    AuthReq Flag(0x5,bonding:yes|mitm:yes|secureConnections:no|keypress:no|ct2:no)
    
  • KeyDistributionFlag (mirage.libs.ble_utils.dissectors.KeyDistributionFlag) : :Example:

    >>> KeyDistributionFlag(idKey=True,encKey=True).data.hex()
    '03'
    >>> KeyDistributionFlag(data=bytes.fromhex("03"))
    Key Distribution Flag(0x3,encKey:yes|idKey:yes|signKey:no|linkKey:no)
    

ATT / GATT server

_images/att.png

The Bluetooth Low Energy provides two main applicative layers : ATT (Attribute Protocol) and GATT (Generic Attribute Profile). If you want to implement a Peripheral device, you need to instantiate a GATT Server in order to send the right responses to the Central’s ATT requests. Mirage provides a basic ATT Server implementation (mirage.libs.ble_utils.att_server.ATT_Server) and a GATT Server (mirage.libs.ble_utils.att_server.GATT_Server) based on it. Please refer to the documentation of the submodule named att_server for more details (mirage.libs.ble_utils.att_server).

Cryptographic functions

Mirage provides multiple cryptographic functions, commonly used in the Security Manager layer of the Bluetooth Low Energy protocol stack. These functions are stored in two main classes, included in the crypto submodule (mirage.libs.ble_utils.crypto) :

  • BLECrypto (mirage.libs.ble_utils.crypto.BLECrypto) : this class provides multiple class methods implementing the cryptographic functions listed in the Security Manager specification, such as \(E\), \(S1\) or \(C1\) and their inverse functions. It also provides a method named crackTemporaryKey, allowing to crack a temporary key by providing the corresponding paremeters.

  • BLELinkLayerCrypto (mirage.libs.ble_utils.crypto.BLELinkLayerCrypto) : this class provides an API allowing to encrypt and decrypt the link layer frames.

Warning

The implementation of BLELinkLayerCrypto is not mature nor user friendly. It may be improved in the next release.