Mosart protocol ================ Mosart is a wireless communication protocol widely used by wireless mices and keyboards. Mirage includes a lot of software components allowing to communicate with Mosart devices. This page presents a subset of these components, and provides some basic examples presenting their usage. Mosart modules --------------- Mirage includes many modules allowing to analyze the security of Mosart communications. These modules can perform attacks or useful actions in order to manipulate a Mosart device. The available modules and the links to the corresponding documentation pages are listed in the following table : .. include:: list.mosart-modules.rst Importing the Mosart software components ----------------------------------------- Every software component described in this page can be easily imported from a :doc:`module ` or a :doc:`scenario ` environment using the following statement : :: from mirage.libs import mosart Then, every component is available using the ``mosart`` namespace : :: packet = mosart.MosartMouseMovementPacket(address="11:22:33:44", x1=1,x2=2,y1=-5,y2=-3) Interacting with the protocol ------------------------------ Mirage currently allows to interact with the Mosart protocol using an NRF24-based device, embedding the `RFStorm firmware `_ written by Bastille Research. The supported Devices are listed :doc:`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. Mosart packets --------------- Mirage manipulates the Mosart packets as child classes of ``MosartPacket`` (`mirage.libs.mosart_utils.packets.MosartPacket `_), 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 : * `MosartDonglePacket `_ * `MosartMouseMovementPacket `_ * `MosartMouseClickPacket `_ * `MosartKeyboardKeystrokePacket `_ If you use a sniffer such as `RFStorm `_, 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 ``MosartSniffingParameters`` (`mirage.libs.esb_utils.packets.MosartSniffingParameters `_). Mosart Dissectors ------------------ Some Mosart 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 Mosart 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 keystroke field (`mirage.libs.mosart_utils.dissectors.MosartKeystroke `_): :Example: >>> MosartKeystroke(hidCode=5,modifiers=0).data.hex() '812d' >>> MosartKeystroke(data=bytes.fromhex("812d")).hidCode 5 >>> MosartKeystroke(data=bytes.fromhex("812d")).modifiers 0 .. warning:: The Mosart protocol seems to use some arbitrary values to describe keystrokes. The values provided by this dissectors has been collected empirically and as a consequence, they are probably not complete and they probably include some mistakes. Dongle Acknowledgement and Sync packets ---------------------------------------- The Mosart protocol doesn't allow to inject keystrokes at any time: the packets have to be transmitted right after the reception of a synchonization frame transmitted by the dongle itself. Similarly, the frame are acknowledged by the same kind of frames by the dongle. In order to allow the active attacks targeting this protocol, the supported devices implements a synchronization mode, allowing to wait a sync packet before transmitting the next frame. You can enable and disable this mode using the following shared methods: * **enableSync** (`mirage.libs.mosart_utils.rfstorm.MosartRFStormDevice.enableSync `_) * **disableSync** (`mirage.libs.mosart_utils.rfstorm.MosartRFStormDevice.disableSync `_) :Example: >>> self.emitter.enableSync() >>> self.emitter.sendp(mosart.MosartMouseMovementPacket(address="11:22:33:44", x1=1,x2=2,y1=-5,y2=-3)) Similarly, if you want to passively capture this kind of frame, you have to enable the dongle packets reception using the following shared methods: * **enableDonglePackets** (`mirage.libs.mosart_utils.rfstorm.MosartRFStormDevice.enableDonglePackets `_) * **disableDonglePackets** (`mirage.libs.mosart_utils.rfstorm.MosartRFStormDevice.disableDonglePackets `_) HID helpers ------------ The Mosart protocol is commonly used by wireless mices and keyboards. As a consequence, it may be useful to manipulate the HID protocol, which is generally used in this context. In order to facilitate the interaction with this kind of devices, Mirage provides some `HID helpers `_. As an example, the `HIDMapping `_ class allows to convert a key to its code and modifiers and vice versa: :Example: >>> HIDMapping(locale="fr").getHIDCodeFromKey(key="a") (20, 0) >>> HIDMapping(locale="us").getHIDCodeFromKey(key="t",ctrl=True,alt=True) (23, 5) >>> HIDMapping(locale="fr").getKeyFromHIDCode(20,0) 'a' >>> HIDMapping(locale="us").getKeyFromHIDCode(23,0) 't' DuckyScript parser ------------------- The `DuckyScript `_ is a Domain Specific Language (DSL) allowing to describe a keystroke injection. It has initially been designed in order to control an offensive hardware component called RubberDucky, allowing to perform keystrokes injection attacks. As a consequence, this language is really interesting if you try to perform keystrokes injection attacks against a wireless mouse or keyboard. Mirage includes a simple parser (`DuckyScriptParser `_) allowing to generate a list of packets to inject according to a provided DuckyScript file. In order to use this class, you must define four functions that returns the sequence of packets for a given action: * **textFunction**: function corresponding to text injection * **keyFunction**: function corresponding to keystroke injection * **sleepFunction**: function corresponding to a sleep interval * **initFunction**: function corresponding to the initialization of the process As an example, the following code snippet shows how to use this class in order to generate a keystroke injection targeting a Mosart device: :: def addMosartKeystroke(locale="fr",key="a",ctrl=False, alt=False, gui=False,shift=False): keystrokes = [] if key == "\n": key = "ENTER" hid,mod = HIDMapping(locale=locale).getHIDCodeFromKey(key=key) if mod == 0: keystrokes.append(mosart.MosartKeyboardKeystrokePacket(sequenceNumber=counter,address="11:22:33:44",hidCode=hid,modifiers=0,state="pressed")) keystrokes.append(mosart.MosartKeyboardKeystrokePacket(sequenceNumber=counter,address="11:22:33:44",hidCode=hid,modifiers=0,state="pressed")) counter = counter + 1 if counter + 1 <= 15 else 0 else: keystrokes.append(mosart.MosartKeyboardKeystrokePacket(sequenceNumber=counter,address="11:22:33:44",hidCode=0,modifiers=mod,state="pressed")) keystrokes.append(mosart.MosartKeyboardKeystrokePacket(sequenceNumber=counter,address="11:22:33:44",hidCode=0,modifiers=mod,state="pressed")) keystrokes.append(mosart.MosartKeyboardKeystrokePacket(sequenceNumber=counter,address="11:22:33:44",hidCode=hid,modifiers=0,state="pressed")) keystrokes.append(mosart.MosartKeyboardKeystrokePacket(sequenceNumber=counter,address="11:22:33:44",hidCode=hid,modifiers=0,state="pressed")) counter = counter + 1 if counter + 1 <= 15 else 0 keystrokes.append(mosart.MosartKeyboardKeystrokePacket(sequenceNumber=counter,address="11:22:33:44",hidCode=hid,modifiers=0,state="released")) keystrokes.append(mosart.MosartKeyboardKeystrokePacket(sequenceNumber=counter,address="11:22:33:44",hidCode=hid,modifiers=0,state="released")) keystrokes.append(mosart.MosartKeyboardKeystrokePacket(sequenceNumber=counter,address="11:22:33:44",hidCode=0,modifiers=mod,state="released")) keystrokes.append(mosart.MosartKeyboardKeystrokePacket(sequenceNumber=counter,address="11:22:33:44",hidCode=0,modifiers=mod,state="released")) keystrokes.append(wireless.WaitPacket(time=0.4)) counter = counter + 1 if counter + 1 <= 15 else 0 return keystrokes def addMosartText(self,string="",locale="fr"): keystrokes = [] for letter in string: keystrokes += self.addMosartKeystroke(key=letter,locale=locale) return keystrokes def startMosartInjection(): return [] def addMosartDelay(duration=1000): keystrokes = [] keystrokes.append(wireless.WaitPacket(time=0.0001*duration)) return keystrokes parser = DuckyScriptParser(filename="/tmp/ducky.txt") attackStream = parser.generatePackets( textFunction=addMosartText, initFunction=startMosartInjection, keyFunction=addMosartKeystroke, sleepFunction=addMosartDelay ) emitter.sendp(*attackStream)