19 Commits

Author SHA1 Message Date
Florian Magin 48461fbd17 Update nearly all examples to Python3 2020-03-25 22:47:46 +01:00
Florian Magin a3d418a262 Fix Nexus6P KNOB PoC 2020-03-25 22:26:34 +01:00
Jiska Classen a435466c01 breakpoint handling and stacktrace parsing 2020-03-25 19:33:22 +01:00
Jiska Classen 5863b11104 linux issue in ioscore, cyw20819 launch_ram note 2020-03-25 03:41:55 +01:00
Florian Magin 8e93878e08 Fix import related issues
Two problems were fixed:
__future__ imports must be the first import of a file, otherwise python
just refuses the file

The Address Type was used but not correctly imported (and not properly
defined as a NewType, just a Type Alias)
2020-03-24 12:54:45 +01:00
Florian Magin a210025dc5 Add explicit Python 3.6 requirement 2020-03-24 12:35:40 +01:00
Jiska Classen f9c38dfd49 rpi3 install 2020-03-24 01:32:53 +01:00
Jiska Classen aa127b7148 minor bugfixes when working with raspberry pi 3/3+/4 2020-03-23 02:00:30 +01:00
Jiska Classen 5792bca5b8 iOS: recv queue full no longer crashes 2020-03-21 23:25:19 +01:00
Jiska Classen 4df388c37a all firmware files should be python3 now, sendhcicmd cli fixed 2020-03-21 21:56:55 +01:00
Jiska Classen 733cd9ca56 iOS: fixed event len>128 2020-03-21 20:57:24 +01:00
Jiska Classen a8a6623658 python3 ioscore/usbmux issues 2020-03-21 19:50:37 +01:00
Jiska Classen b599213104 iOS & python 2 readme 2020-03-21 03:21:54 +01:00
Jiska Classen df5636b9b8 Nexus 6P / Galaxy S6 fw file fixed 2020-03-21 03:05:17 +01:00
Dennis Heinze 25fa80a416 Introducing the new version of the ios-proxy: internalblued 2020-03-20 17:06:14 +01:00
Dennis Heinze fd7310330b iOSCore uses usbmuxd now 2020-03-20 16:52:42 +01:00
Jiska Classen 65a8ce61e6 Python 3: Nexus 5 stack dump, connection event 2020-03-20 00:41:08 +01:00
Jiska Classen 67ec7f5347 readMemAligned Python3 bug fixed 2020-03-19 18:40:19 +01:00
Jiska Classen 8dce7f86a4 Python 3 \o/ 2020-03-19 16:40:03 +01:00
69 changed files with 1608 additions and 1330 deletions
+23 -10
View File
@@ -8,6 +8,14 @@ therefore implement monitoring and injection tools for the lower layers of
the Bluetooth protocol stack.
Recent Changes
--------------
* We upgraded from Python 2 to Python 3. If you wrote your own scripts, this might break them. In this case, use
the [python2](https://github.com/seemoo-lab/internalblue/releases/tag/python2) release.
* We reworked the *iOS* implementation.
Publications and Background
---------------------------
@@ -64,6 +72,9 @@ was also recorded and gives a more high level overview.
We did some work on improving blacklisting performance of BLE data connections. Currently in a separate *blacklisting* branch.
* **CiderSecCon Talk** (03/2020)
TROOPERS was canceled, but we did a stream of a talk that was recorded on [YouTube](https://www.youtube.com/watch?v=Nx2ZDLaJ1-0&t=4920).
@@ -98,6 +109,7 @@ On selected Broadcom Bluetooth chips:
* NiNo example
* MAC address filter example
* KNOB attack test for various devices, including Raspberry Pi 3+/4
* BLE receptoin statistics
A comprehensive list of chips and which devices have them can be found in the [firmware](internalblue/fw/README.md) module documentation.
@@ -110,19 +122,20 @@ Requirements
Android:
* Ideally recompiled `bluetooth.default.so`, but also works on any rooted smartphone, see [Android instructions](android_bluetooth_stack/README.md)
* Android device connected via ADB
* Best support is currently given for Nexus 5 / BCM4339 and Evaluation Boards
* Best support is currently given for Nexus 5 / BCM4339
* Optional: Patch for Android driver to support Broadcom H4 forwarding
* Optional, if H4: Wireshark [Broadcom H4 Dissector Plugin](https://github.com/seemoo-lab/h4bcm_wireshark_dissector)
Linux:
* BlueZ, instructions see [here](linux_bluez/README.md)
* Best support for Raspberry Pi 3/3+/4
* Best support for Raspberry Pi 3/3+/4 and Cypress evaluation boards
* For most commands: Privileged access
iOS:
* A jailbroken iOS device (tested on iOS 12.1.2/12.4 with iPhone 6, SE, 7, 8, X)
* The included `ios-proxy` (instructions in [here](ios-proxy/README.md))
* Optional: a Mac with `xcode` to compile the proxy yourself
* A jailbroken iOS device (tested on iOS 12 and 13 with iPhone 6, SE, 7, 8, X , does not work on iPhones newer than XR, these devices have a Bluetooth chip connected via PCIe)
* `usbmuxd`, which is pre installed on macOS but is available on most Linux distributions as well. Alternatively it can be obtained from [here](https://github.com/libimobiledevice/usbmuxd).
* The [``internalblued`` daemon](ios-internalblued/README.md) installed on the iOS device
* Optional, no jailbreak required: install [iOS Bluetooth Debug Profile](https://developer.apple.com/bug-reporting/profiles-and-logs/) to obtain
HCI and diagnostic messages, either via diagnostic report feature (all iOS versions) or live with PacketLogger (since iOS 13)
@@ -151,7 +164,7 @@ with all dependencies by using pip:
git clone https://github.com/seemoo-lab/internalblue.git
cd internalblue
pip2 install .
pip install .
It will install the following dependencies:
* pwntools
@@ -171,7 +184,7 @@ All steps on a plain Ubuntu 18.04:
sudo apt install git python-setuptools binutils-arm-linux-gnueabi adb pip python-dev gcc
git clone https://github.com/seemoo-lab/internalblue
cd internalblue
sudo pip2 install .
sudo pip install .
cd ..
sudo apt-get install wireshark-dev wireshark cmake
@@ -183,10 +196,10 @@ All steps on a plain Ubuntu 18.04:
make
make install
Packets required on a current (July 2019) Raspian:
Packets required on a current (March 2020) Raspbian:
sudo apt-get --allow-releaseinfo-change update
sudo apt-get install git python-setuptools binutils-arm-none-eabi adb python-pip python-dev gcc libffi-dev
sudo apt-get install git python3-setuptools binutils-arm-none-eabi adb python3-pip python3-dev gcc libffi-dev
@@ -195,7 +208,7 @@ Usage
The CLI (Command Line Interface) of InternalBlue can be started by running:
python2 -m internalblue.cli
python -m internalblue.cli
The setup.py installation will also place a shortcut to the CLI into the $PATH
so that it can be started from a command line using:
+5 -7
View File
@@ -1,11 +1,9 @@
#!/usr/bin/python2
#!/usr/bin/env python3
# Jiska Classen, Secure Mobile Networking Lab
from pwn import *
from internalblue import Address
from internalblue.hcicore import HCICore
from internalblue.utils.pwnlib_wrapper import log, asm
"""
@@ -32,10 +30,10 @@ log.info("Installing patch which ensures that send_LMP_encryptoin_key_size_req i
# modify function lm_SendLmpEncryptKeySizeReq
patch = asm("mov r2, #0x1", vma=0x7402A) # connection struct key entropy
internalblue.patchRom(0x7402A, patch)
internalblue.patchRom(Address(0x7402A), patch)
# modify global variable for own setting
internalblue.writeMem(0x280F13, '\x01') # global key entropy
internalblue.writeMem(0x280F13, b'\x01') # global key entropy
internalblue.shutdown()
+2 -2
View File
@@ -1,14 +1,14 @@
#!/usr/bin/env python2
#!/usr/bin/env python3
# Jiska Classen
# Get receive statistics on a Nexus 5 for BLE connection events
from builtins import range
from pwn import *
from internalblue.adbcore import ADBCore
import internalblue.hci as hci
import internalblue.cli as cli
from internalblue.utils.pwnlib_wrapper import log, asm, u8, u16
internalblue = ADBCore(serial=False)
device_list = internalblue.device_list()
@@ -1,10 +1,9 @@
#!/usr/bin/env python2
# Dennis Mantz
from pwn import *
from internalblue import Address
from internalblue.adbcore import ADBCore
from internalblue.utils.pwnlib_wrapper import log, asm
#internalblue = core.InternalBlue()
internalblue = ADBCore()
@@ -15,9 +14,9 @@ if len(device_list) == 0:
internalblue.interface = device_list[0][1] # just use the first device
PK_RECV_HOOK_ADDRESS = 0x2FED8
PK_SEND_HOOK_ADDRESS = 0x030098
GEN_PRIV_KEY_ADDRESS = 0x48eba
PK_RECV_HOOK_ADDRESS = Address(0x2FED8)
PK_SEND_HOOK_ADDRESS = Address(0x030098)
GEN_PRIV_KEY_ADDRESS = Address(0x48eba)
HOOKS_LOCATION = 0xd7800
ASM_HOOKS = """
b pk_recv_hook
+6 -8
View File
@@ -1,15 +1,13 @@
#!/usr/bin/python2
#!/usr/bin/python3
# Jiska Classen, Secure Mobile Networking Lab
from pwn import *
from internalblue import Address
from internalblue.adbcore import ADBCore
import internalblue.cli as cli
import internalblue.cmds as cmd
import internalblue.hci as hci
from internalblue.cmds import auto_int
from internalblue.utils.pwnlib_wrapper import log, asm, u8, p16, u16
"""
@@ -36,10 +34,10 @@ log.info("Installing patch which ensures that send_LMP_encryptoin_key_size_req i
# modify function lm_SendLmpEncryptKeySizeReq
patch = asm("mov r2, #0x1", vma=0x5AED0) # connection struct key entropy
internalblue.patchRom(0x5AED0, patch)
internalblue.patchRom(Address(0x5AED0), patch)
# modify global variable for own setting
internalblue.writeMem(0x203797, '\x01') # global key entropy
internalblue.writeMem(0x203797, b'\x01') # global key entropy
log.info("-----------------------KNOB-----------------------\n"
@@ -67,7 +65,7 @@ class CmdKnob(cmd.Cmd):
def work(self):
args = self.getArgs()
internalblue.sendHciCommand(0x1408, p16(args.hnd))
internalblue.sendHciCommand(hci.HCI_COMND.Encryption_Key_Size, p16(args.hnd))
return True
+6 -6
View File
@@ -1,10 +1,10 @@
#!/usr/bin/python2
#!/usr/bin/env python3
# Jiska Classen, Secure Mobile Networking Lab
from pwn import *
from internalblue import Address
from internalblue.adbcore import ADBCore
from internalblue.utils.pwnlib_wrapper import log, asm
from binascii import unhexlify
"""
Filter connections by MAC address before entering LMP dispatcher.
Enter MAC addresses you trust into whitelist.
@@ -12,8 +12,8 @@ Enter MAC addresses you trust into whitelist.
"""
WHITELIST = ["aabbccddeeff", "133713371337", "affedeadbeef"]
WHITELIST_BYTES = ''.join(WHITELIST).decode("hex")[::-1] # change mac addr byte order
HOOK_LMP_FILTER = 0x3f3f4 # This function is in ROM
WHITELIST_BYTES = unhexlify(''.join(WHITELIST))[::-1] # change mac addr byte order
HOOK_LMP_FILTER = Address(0x3f3f4) # This function is in ROM
ASM_LOCATION_LMP_FILTER = 0x00211900 # 0xD5900
ASM_SNIPPET_LMP_FILTER = """
b lmp_dispatcher_filter
+4 -4
View File
@@ -1,12 +1,12 @@
#!/usr/bin/python2
#!/usr/bin/env python3
# Jiska Classen, Secure Mobile Networking Lab
import sys
from pwn import *
from internalblue import Address
from internalblue.adbcore import ADBCore
from internalblue.utils.pwnlib_wrapper import log, asm
"""
@@ -40,7 +40,7 @@ TODO
"""
HOOK_IO_CAP_RESP = 0x303D4 # we just change the complete simple pairing state machine
HOOK_IO_CAP_RESP = Address(0x303D4) # we just change the complete simple pairing state machine
ASM_LOCATION_IO_CAP_RESP = 0x00211800 #0xd7800
ASM_SNIPPET_IO_CAP_RESP = """
//restore original 8 bytes of instructions which we overwrite by patching a branch into it
+3 -4
View File
@@ -3,13 +3,12 @@
# Jiska Classen, Secure Mobile Networking Lab
from pwn import *
from internalblue.adbcore import ADBCore
import internalblue.cli as cli
import internalblue.cmds as cmd
import internalblue.hci as hci
from internalblue.cmds import auto_int
from internalblue.utils.pwnlib_wrapper import u8, p16, u16, log
"""
This is a standalone PoC for the KNOB attack on a Nexus 6P.
@@ -39,7 +38,7 @@ log.info("Installing patch which ensures that send_LMP_encryption_key_size_req i
# this somehow crashes on the Nexus 6P, but the global variable seems to be sufficient :)
# modify global variable for own setting
internalblue.writeMem(0x204147, '\x01') # global key entropy
internalblue.writeMem(0x204147, b'\x01') # global key entropy
log.info("-----------------------KNOB-----------------------\n"
@@ -67,7 +66,7 @@ class CmdKnob(cmd.Cmd):
def work(self):
args = self.getArgs()
internalblue.sendHciCommand(0x1408, p16(args.hnd))
internalblue.sendHciCommand(hci.HCI_COMND.Encryption_Key_Size, p16(args.hnd))
return True
+4 -5
View File
@@ -1,12 +1,11 @@
#!/usr/bin/env python2
#!/usr/bin/env python3
# Jiska Classen
# Get receive statistics on a Raspberry Pi 3 for BLE connection events
from pwn import *
from internalblue import Address
from internalblue.hcicore import HCICore
from internalblue.utils.pwnlib_wrapper import log, asm
internalblue = HCICore()
device_list = internalblue.device_list()
@@ -16,7 +15,7 @@ if len(device_list) == 0:
internalblue.interface = device_list[0][1] # just use the first device
RX_DONE_HOOK_ADDRESS = 0x35fbc # _connTaskRxDone
RX_DONE_HOOK_ADDRESS = Address(0x35fbc) # _connTaskRxDone
HOOKS_LOCATION = 0x210500
ASM_HOOKS = """
+5 -6
View File
@@ -1,9 +1,8 @@
#!/usr/bin/python2
#!/usr/bin/python3
# Jiska Classen, Secure Mobile Networking Lab
from pwn import *
from internalblue import Address
from internalblue.utils.pwnlib_wrapper import log, asm
from internalblue.hcicore import HCICore
@@ -32,10 +31,10 @@ log.info("Installing patch which ensures that send_LMP_encryptoin_key_size_req i
# modify function lm_SendLmpEncryptKeySizeReq
patch = asm("mov r2, #0x1", vma=0x689F0) # connection struct key entropy
internalblue.patchRom(0x689F0, patch)
internalblue.patchRom(Address(0x689F0), patch)
# modify global variable for own setting
internalblue.writeMem(0x204127, '\x01') # global key entropy
internalblue.writeMem(0x204127, b'\x01') # global key entropy
internalblue.shutdown()
+4 -5
View File
@@ -1,12 +1,11 @@
#!/usr/bin/env python2
#!/usr/bin/env python3
# Jiska Classen
# Get receive statistics on a Raspberry Pi 3 for BLE connection events
from pwn import *
from internalblue import Address
from internalblue.hcicore import HCICore
from internalblue.utils.pwnlib_wrapper import log, asm
internalblue = HCICore()
device_list = internalblue.device_list()
@@ -16,7 +15,7 @@ if len(device_list) == 0:
internalblue.interface = device_list[0][1] # just use the first device
RX_DONE_HOOK_ADDRESS = 0x56622 # _connTaskRxDone
RX_DONE_HOOK_ADDRESS = Address(0x56622) # _connTaskRxDone
HOOKS_LOCATION = 0x210500
ASM_HOOKS = """
+5 -7
View File
@@ -1,11 +1,9 @@
#!/usr/bin/python2
#!/usr/bin/python3
# Jiska Classen, Secure Mobile Networking Lab
from pwn import *
from internalblue import Address
from internalblue.hcicore import HCICore
from internalblue.utils.pwnlib_wrapper import log, asm
"""
@@ -32,10 +30,10 @@ log.info("Installing patch which ensures that send_LMP_encryptoin_key_size_req i
# modify function lm_SendLmpEncryptKeySizeReq
patch = asm("mov r2, #0x1", vma=0x3B3D4) # connection struct key entropy
internalblue.patchRom(0x3B3D4, patch)
internalblue.patchRom(Address(0x3B3D4), patch)
# modify global variable for own setting
internalblue.writeMem(0x204A5F, '\x01') # global key entropy
internalblue.writeMem(0x204A5F, b'\x01') # global key entropy
internalblue.shutdown()
+2 -3
View File
@@ -1,15 +1,14 @@
#!/usr/bin/env python2
#!/usr/bin/env python3
# Jiska Classen
# Get receive statistics on a Samsung Galaxy S8 for BLE connection events
from builtins import range
from pwn import *
from internalblue.adbcore import ADBCore
import internalblue.hci as hci
import internalblue.cli as cli
from internalblue.utils.pwnlib_wrapper import log, asm, u8, u16
internalblue = ADBCore(serial=True)
device_list = internalblue.device_list()
if len(device_list) == 0:
+5 -7
View File
@@ -1,11 +1,9 @@
#!/usr/bin/python2
#!/usr/bin/python3
# Jiska Classen, Secure Mobile Networking Lab
from pwn import *
from internalblue import Address
from internalblue.adbcore import ADBCore
from internalblue.utils.pwnlib_wrapper import log, asm
"""
@@ -32,10 +30,10 @@ log.info("Installing patch which ensures that send_LMP_encryptoin_key_size_req i
# modify function lm_SendLmpEncryptKeySizeReq
patch = asm("mov r2, #0x1", vma=0x530F6) # connection struct key entropy
internalblue.patchRom(0x530F6, patch)
internalblue.patchRom(Address(0x530F6), patch)
# modify global variable for own setting
internalblue.writeMem(0x255E8F, '\x01') # global key entropy
internalblue.writeMem(0x255E8F, b'\x01') # global key entropy
internalblue.shutdown()
+1 -2
View File
@@ -17,8 +17,7 @@ from typing import (
Dict,
)
# Address = NewType("Address", int)
Address = int
Address = NewType("Address", int)
ConnectionNumber = NewType("ConnectionNumber", int)
ConnectionIndex = NewType("ConnectionIndex", int)
+21 -26
View File
@@ -238,35 +238,30 @@ def internalblue_cli(argv, args=None):
replay_devices
)
)
elif args.ios_device:
from .ioscore import iOSCore
connection_methods = [
iOSCore(args.ios_device, log_level=log_level, data_directory=data_directory)
]
elif platform == "darwin":
from .macoscore import macOSCore
connection_methods = [
macOSCore(
log_level=log_level,
data_directory=data_directory,
replay=(args.replay and args.device == "mac"),
),
ADBCore(log_level=log_level, data_directory=data_directory),
]
if args.trace:
hook(macOSCore, HookClass)
elif args.save:
hook(macOSCore, TraceToFileHook, filename=args.save)
else:
connection_methods = [
# if /var/run/usbmuxd exists, we can check for iOS devices
if os.path.exists("/var/run/usbmuxd"):
from .ioscore import iOSCore
connection_methods.append(iOSCore(log_level=log_level, data_directory=data_directory))
if platform == "darwin":
try:
from .macoscore import macOSCore
connection_methods.append(macOSCore(log_level=log_level, data_directory=data_directory, replay=(args.replay and args.device == "mac")))
except ImportError:
pwnlib.log.warn("Couldn't import macOSCore. Is IOBluetoothExtended.framework installed?")
if args.trace:
hook(macOSCore, HookClass)
elif args.save:
hook(macOSCore, TraceToFileHook, filename=args.save)
else:
connection_methods.append(HCICore(log_level=log_level, data_directory=data_directory))
# ADB core can always be used
connection_methods.append(
ADBCore(
log_level=log_level, data_directory=data_directory, serial=args.serialsu
),
HCICore(log_level=log_level, data_directory=data_directory),
]
))
devices = [] # type: List[DeviceTuple]
for connection_method in connection_methods:
+2 -2
View File
@@ -1196,7 +1196,7 @@ class CmdSendHciCmd(Cmd):
if data_part[0:2] == "0x":
data += p32(auto_int(data_part))
else:
data += data_part.decode("hex")
data += bytearray.fromhex(data_part)
return self.internalblue.sendHciCommand(args.cmdcode, data)
@@ -1784,7 +1784,7 @@ class CmdBreakpoint(Cmd):
return True
log.info("Inserting breakpoint at 0x%x..." % args.address)
self.internalblue.patchRom(args.address, "\x00\xbe\x00\x00")
self.internalblue.patchRom(args.address, b'\x00\xbe\x00\x00') # on ARM, hex code for a break point is 0xBE00
return True
+6 -3
View File
@@ -1100,7 +1100,7 @@ class InternalBlue(with_metaclass(ABCMeta, object)):
return False
if hcipkt.event_code != 0xFF:
return False
if hcipkt.data[0:4] != "READ":
if hcipkt.data[0:4] != bytes("READ", "utf-8"):
return False
return True
@@ -1108,7 +1108,9 @@ class InternalBlue(with_metaclass(ABCMeta, object)):
read_addr = address
byte_counter = 0
outbuffer = ""
outbuffer = (
bytearray()
)
if bytes_total == 0:
bytes_total = length
while read_addr < address + length:
@@ -1846,7 +1848,8 @@ class InternalBlue(with_metaclass(ABCMeta, object)):
)
conn_handle = u16(hcipkt.data[1:3])
btaddr = hcipkt.data[3:9][::-1]
btaddr_str = ":".join([b.encode("hex") for b in btaddr])
#btaddr_str = ":".join([b.encode("hex") for b in btaddr])
btaddr_str = bytes_to_hex(btaddr)
log.info(
"[Connect Complete: Handle=0x%x Address=%s status=%s]"
% (conn_handle, btaddr_str, status_str)
+1 -1
View File
@@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python
# fw.py
#
+129 -128
View File
@@ -1,5 +1,3 @@
from __future__ import absolute_import
# fw_0x420e.py
#
# Generic firmware file in case we do not know something...
@@ -22,139 +20,142 @@ from __future__ import absolute_import
# out of or in connection with the Software or the use or other dealings in the
# Software.
from .fw import MemorySection
# Firmware Infos
# Samsung S10/S10e/S10+
FW_NAME = "BCM4375B1"
from __future__ import absolute_import
from .fw import MemorySection, FirmwareDefinition
# Device Infos
DEVICE_NAME = 0x207F2A
BD_ADDR = 0x2026E2
class BCM4375B1(FirmwareDefinition):
# Firmware Infos
# Samsung S10/S10e/S10+
FW_NAME = "BCM4375B1"
# Memory Sections
# start, end, is_rom? is_ram?
SECTIONS = [
MemorySection(0x00000000, 0x0013FFFF, True, False), # Internal ROM
MemorySection(0x00160000, 0x0017FFFF, False, True), # Patches
MemorySection(0x00200000, 0x00288000, False, True), # Internal Memory Cortex M3
MemorySection(0x00300000, 0x0037FFFF, False, True),
]
# Device Infos
DEVICE_NAME = 0x207F2A
BD_ADDR = 0x2026E2
# Patchram
PATCHRAM_TARGET_TABLE_ADDRESS = 0x310000
PATCHRAM_ENABLED_BITMAP_ADDRESS = 0x310404
PATCHRAM_VALUE_TABLE_ADDRESS = 0x160000
PATCHRAM_NUMBER_OF_SLOTS = 256
PATCHRAM_ALIGNED = False
BLOC_HEAD = 0x20075C
BLOC_NG = True
# Memory Sections
# start, end, is_rom? is_ram?
SECTIONS = [
MemorySection(0x00000000, 0x0013FFFF, True, False), # Internal ROM
MemorySection(0x00160000, 0x0017FFFF, False, True), # Patches
MemorySection(0x00200000, 0x00288000, False, True), # Internal Memory Cortex M3
MemorySection(0x00300000, 0x0037FFFF, False, True),
]
# Assembler snippet for tracepoints
# In contrast to the Nexus 5 patch, we uninstall ourselves automatically and use internal debug functions
# TODO S10e does no longer have a patch uninstall function... writemem works to remove patches, but copying
# Assembly of the original function from an eval board does not work...
# TRACEPOINT_BODY_ASM_LOCATION = 0x00218300
# TRACEPOINT_HOOKS_LOCATION = 0x00218500
# TRACEPOINT_HOOK_SIZE = 40
TRACEPOINT_HOOK_ASM = """
push {r0-r12, lr} // save all registers on the stack (except sp and pc)
ldr r6, =0x%x // addTracepoint() injects pc of original tracepoint here
mov r9, %d // addTracepoint() injects the patchram slot of the hook patch
bl 0x%x // addTracepoint() injects TRACEPOINT_BODY_ASM_LOCATION here
pop {r0-r12, lr} // restore registers
# Patchram
PATCHRAM_TARGET_TABLE_ADDRESS = 0x310000
PATCHRAM_ENABLED_BITMAP_ADDRESS = 0x310404
PATCHRAM_VALUE_TABLE_ADDRESS = 0x160000
PATCHRAM_NUMBER_OF_SLOTS = 256
PATCHRAM_ALIGNED = False
// branch back to the original instruction
b 0x%x // addTracepoint() injects the address of the tracepoint
"""
BLOC_HEAD = 0x20075C
BLOC_NG = True
TRACEPOINT_BODY_ASM_SNIPPET = """
# Assembler snippet for tracepoints
# In contrast to the Nexus 5 patch, we uninstall ourselves automatically and use internal debug functions
# TODO S10e does no longer have a patch uninstall function... writemem works to remove patches, but copying
# Assembly of the original function from an eval board does not work...
# TRACEPOINT_BODY_ASM_LOCATION = 0x00218300
# TRACEPOINT_HOOKS_LOCATION = 0x00218500
# TRACEPOINT_HOOK_SIZE = 40
TRACEPOINT_HOOK_ASM = """
push {r0-r12, lr} // save all registers on the stack (except sp and pc)
ldr r6, =0x%x // addTracepoint() injects pc of original tracepoint here
mov r9, %d // addTracepoint() injects the patchram slot of the hook patch
bl 0x%x // addTracepoint() injects TRACEPOINT_BODY_ASM_LOCATION here
pop {r0-r12, lr} // restore registers
// branch back to the original instruction
b 0x%x // addTracepoint() injects the address of the tracepoint
"""
mov r8, lr // save link register in r8
b delete_slot
// dump registers like before
// save status register in r5
mrs r5, cpsr
// malloc HCI event buffer
mov r0, 0xff // event code is 0xff (vendor specific HCI Event)
mov r1, 76 // buffer size: size of registers (68 bytes) + type and length + 'TRACE_'
bl 0x6cfe2 // hci_allocateEventBlockWithLen(0xff, 78) #DONE
mov r4, r0 // save pointer to the buffer in r4
// append our custom header (the word 'TRACE_') after the event code and event length field
add r0, 2 // write after the length field
ldr r1, =0x43415254 // 'TRAC'
str r1, [r0]
add r0, 4 // advance the pointer.
ldr r1, =0x5f45 // 'E_'
strh r1, [r0]
add r0, 2 // advance the pointer. r0 now points to the start of the register values
// store pc
str r6, [r0] // r6 still contains the address of the original pc
add r0, 4 // advance the pointer.
// store sp
mov r1, 56 // 14 saved registers * 4
add r1, sp
str r1, [r0]
add r0, 4 // advance the pointer.
// store status register
str r5, [r0]
add r0, 4 // advance the pointer.
// store other registers
mov r1, sp
mov r2, 56
bl 0x2774 // memcpy(dst, src, len) #DONE
// send HCI buffer to the host
mov r0, r4 // r4 still points to the beginning of the HCI buffer
bl 0x6cfa8 // hci_sendEvent #DONE
// restore status register
msr cpsr_f, r5
bl 0x6af24 // bthci_event_vs_DBFW_CoreDumpRAMImageEvent #DONE
// not possible... could not find patch_uninstallPatchEntry(slot)
// -> disable TP by hand, we stored in r9
// TODO - does not work??
delete_slot:
mov r0, #0
mov r1, r0
lsl r0, r0, #0x2
ldr r3, =0x00310404
sub.w r0, r0, #0x400
add r3, #0x3c
add r0, r3
movw r2, #0xffff
str r2, [r0, #0x0]
ldr r0,=0x00310404
add r0, #0x2c
ldr r2, [r0,#0x0]
mov r3, #0x1
lsl r3, r1
bic r2, r3
str r2, [r0, #0x0]
mov lr, r8 // restore lr from r8
bx lr // return
.align
patchram:
.byte 0x04
.byte 0x04
.byte 0x31
.byte 0x00
"""
TRACEPOINT_BODY_ASM_SNIPPET = """
mov r8, lr // save link register in r8
b delete_slot
// dump registers like before
// save status register in r5
mrs r5, cpsr
// malloc HCI event buffer
mov r0, 0xff // event code is 0xff (vendor specific HCI Event)
mov r1, 76 // buffer size: size of registers (68 bytes) + type and length + 'TRACE_'
bl 0x6cfe2 // hci_allocateEventBlockWithLen(0xff, 78) #DONE
mov r4, r0 // save pointer to the buffer in r4
// append our custom header (the word 'TRACE_') after the event code and event length field
add r0, 2 // write after the length field
ldr r1, =0x43415254 // 'TRAC'
str r1, [r0]
add r0, 4 // advance the pointer.
ldr r1, =0x5f45 // 'E_'
strh r1, [r0]
add r0, 2 // advance the pointer. r0 now points to the start of the register values
// store pc
str r6, [r0] // r6 still contains the address of the original pc
add r0, 4 // advance the pointer.
// store sp
mov r1, 56 // 14 saved registers * 4
add r1, sp
str r1, [r0]
add r0, 4 // advance the pointer.
// store status register
str r5, [r0]
add r0, 4 // advance the pointer.
// store other registers
mov r1, sp
mov r2, 56
bl 0x2774 // memcpy(dst, src, len) #DONE
// send HCI buffer to the host
mov r0, r4 // r4 still points to the beginning of the HCI buffer
bl 0x6cfa8 // hci_sendEvent #DONE
// restore status register
msr cpsr_f, r5
bl 0x6af24 // bthci_event_vs_DBFW_CoreDumpRAMImageEvent #DONE
// not possible... could not find patch_uninstallPatchEntry(slot)
// -> disable TP by hand, we stored in r9
// TODO - does not work??
delete_slot:
mov r0, #0
mov r1, r0
lsl r0, r0, #0x2
ldr r3, =0x00310404
sub.w r0, r0, #0x400
add r3, #0x3c
add r0, r3
movw r2, #0xffff
str r2, [r0, #0x0]
ldr r0,=0x00310404
add r0, #0x2c
ldr r2, [r0,#0x0]
mov r3, #0x1
lsl r3, r1
bic r2, r3
str r2, [r0, #0x0]
mov lr, r8 // restore lr from r8
bx lr // return
.align
patchram:
.byte 0x04
.byte 0x04
.byte 0x31
.byte 0x00
"""
+58 -67
View File
@@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python
# fw_0x6119.py
#
@@ -25,77 +25,68 @@
# out of or in connection with the Software or the use or other dealings in the
# Software.
# Firmware Infos
# This runs on Rasperry Pi 3
from builtins import object
FW_NAME = "BCM43430A1"
# Device Infos
DEVICE_NAME = 0x20401C
BD_ADDR = 0x201C64
# Memory Sections
class MemorySection(object):
def __init__(self, start_addr, end_addr, is_rom, is_ram):
self.start_addr = start_addr
self.end_addr = end_addr
self.is_rom = is_rom
self.is_ram = is_ram
def size(self):
return self.end_addr - self.start_addr
from __future__ import absolute_import
from .fw import MemorySection, FirmwareDefinition
# Memory Sections
# start, end, is_rom? is_ram?
SECTIONS = [
MemorySection(0x0, 0x90000, True, False),
MemorySection(0xD0000, 0xD8000, False, True),
# MemorySection(0xe0000, 0x1f0000, True , False),
MemorySection(0x200000, 0x21FFFF, False, True),
# MemorySection(0x260000, 0x268000, True , False), # might crash? issue 14
# MemorySection(0x280000, 0x2a0000, True , False),
MemorySection(0x318000, 0x320000, False, False),
MemorySection(0x324000, 0x360000, False, False),
MemorySection(0x362000, 0x362100, False, False),
MemorySection(0x363000, 0x363100, False, False),
MemorySection(0x600000, 0x600800, False, False),
MemorySection(0x640000, 0x640800, False, False),
MemorySection(0x650000, 0x650800, False, False),
# MemorySection(0x680000, 0x800000, False, False)
]
class BCM43430A1(FirmwareDefinition):
# Firmware Infos
# This runs on Rasperry Pi 3
FW_NAME = "BCM43430A1"
# Connection Structure and Table
# CONNECTION_LIST_ADDRESS = 0x204ba8
CONNECTION_MAX = 11
CONNECTION_STRUCT_LENGTH = 0x150 # TODO
# Device Infos
DEVICE_NAME = 0x20401C
BD_ADDR = 0x201C64
# Patchram
PATCHRAM_ENABLED_BITMAP_ADDRESS = 0x310204
PATCHRAM_TARGET_TABLE_ADDRESS = 0x310000
PATCHRAM_VALUE_TABLE_ADDRESS = 0xD0000
PATCHRAM_NUMBER_OF_SLOTS = 128
PATCHRAM_ALIGNED = False
# Memory Sections
# start, end, is_rom? is_ram?
SECTIONS = [
MemorySection(0x0, 0x90000, True, False),
MemorySection(0xD0000, 0xD8000, False, True),
# MemorySection(0xe0000, 0x1f0000, True , False),
MemorySection(0x200000, 0x21FFFF, False, True),
# MemorySection(0x260000, 0x268000, True , False), # might crash? issue 14
# MemorySection(0x280000, 0x2a0000, True , False),
MemorySection(0x318000, 0x320000, False, False),
MemorySection(0x324000, 0x360000, False, False),
MemorySection(0x362000, 0x362100, False, False),
MemorySection(0x363000, 0x363100, False, False),
MemorySection(0x600000, 0x600800, False, False),
MemorySection(0x640000, 0x640800, False, False),
MemorySection(0x650000, 0x650800, False, False),
# MemorySection(0x680000, 0x800000, False, False)
]
# Heap
BLOC_HEAD = 0x200588 # g_dynamic_memory_GeneralUsePools
BLOC_NG = True # Next Generation Bloc Buffer
# Connection Structure and Table
# CONNECTION_LIST_ADDRESS = 0x204ba8
CONNECTION_MAX = 11
CONNECTION_STRUCT_LENGTH = 0x150 # TODO
# Snippet for sendLcpPacket()
SENDLCP_CODE_BASE_ADDRESS = 0x21A000
SENDLCP_ASM_CODE = """
push {r4,lr}
# Patchram
PATCHRAM_ENABLED_BITMAP_ADDRESS = 0x310204
PATCHRAM_TARGET_TABLE_ADDRESS = 0x310000
PATCHRAM_VALUE_TABLE_ADDRESS = 0xD0000
PATCHRAM_NUMBER_OF_SLOTS = 128
PATCHRAM_ALIGNED = False
// we want to call lmulp_sendLcp(conn_index, input, length)
# Heap
BLOC_HEAD = 0x200588 # g_dynamic_memory_GeneralUsePools
BLOC_NG = True # Next Generation Bloc Buffer
mov r0, %d // connection index, starts at 0
ldr r1, =payload
mov r2, %d // length
bl 0x8389A // lmulp_sendLcp
pop {r4,pc} // go back
.align // The payload (LMP packet) must be 4-byte aligend (memcpy needs aligned addresses)
payload: // Note: the payload will be appended here by the sendLmpPacket() function
"""
# Snippet for sendLcpPacket()
SENDLCP_CODE_BASE_ADDRESS = 0x21A000
SENDLCP_ASM_CODE = """
push {r4,lr}
// we want to call lmulp_sendLcp(conn_index, input, length)
mov r0, %d // connection index, starts at 0
ldr r1, =payload
mov r2, %d // length
bl 0x8389A // lmulp_sendLcp
pop {r4,pc} // go back
.align // The payload (LMP packet) must be 4-byte aligend (memcpy needs aligned addresses)
payload: // Note: the payload will be appended here by the sendLmpPacket() function
"""
+2 -2
View File
@@ -1,5 +1,3 @@
from __future__ import absolute_import
# fw_0x420e.py
#
# Generic firmware file in case we do not know something...
@@ -21,6 +19,8 @@ from __future__ import absolute_import
# liability, whether in an action of contract, tort or otherwise, arising from,
# out of or in connection with the Software or the use or other dealings in the
# Software.
from __future__ import absolute_import
from .fw import MemorySection, FirmwareDefinition
+42 -24
View File
@@ -1,5 +1,3 @@
from __future__ import absolute_import
# fw_0x420e.py
#
# Generic firmware file in case we do not know something...
@@ -22,28 +20,48 @@ from __future__ import absolute_import
# out of or in connection with the Software or the use or other dealings in the
# Software.
from .fw import MemorySection
# Firmware Infos
# Evaluation Kit CYW920819
FW_NAME = "CYW20819A1"
from __future__ import absolute_import
from .fw import MemorySection, FirmwareDefinition
# Memory Sections
# start, end, is_rom? is_ram?
SECTIONS = [
MemorySection(0x00000000, 0x001FFFFF, True, False), # Internal ROM
MemorySection(0x00200000, 0x0024FFFF, False, True), # Internal Memory Cortex M3
MemorySection(
0x00270000, 0x0027FFFF, False, True
), # Internal Memory Patchram Contents
MemorySection(0x00310000, 0x00321FFF, False, True), # HW Regs Cortex M3 (readable)
]
class CYW20819A1(FirmwareDefinition):
"""
CYW20819 is a Cypress evaluation board, the newest one that is currently available.
Known issues:
* `Launch_RAM` does not terminate and crashes the board.
To get this working anyway:
The `Launch_RAM` handler HCI callback is at `0xF2884` and it can be overwritten with the
address of the memory snippet you want to launch. For example, at `0x219000` there is some
free memory. Put the function there. Then:
`internalblue.patchRom(0xF2884, b'\x01\x90\x21\x00'): # 0x219001 when you write code to 0x219000`
"""
# Firmware Infos
# Evaluation Kit CYW920819
FW_NAME = "CYW20819A1"
# Memory Sections
# start, end, is_rom? is_ram?
SECTIONS = [
MemorySection(0x00000000, 0x001FFFFF, True, False), # Internal ROM
MemorySection(0x00200000, 0x0024FFFF, False, True), # Internal Memory Cortex M3
MemorySection(
0x00270000, 0x0027FFFF, False, True
), # Internal Memory Patchram Contents
MemorySection(0x00310000, 0x00321FFF, False, True), # HW Regs Cortex M3 (readable)
]
# Patchram
PATCHRAM_TARGET_TABLE_ADDRESS = 0x310000
PATCHRAM_ENABLED_BITMAP_ADDRESS = 0x310404
PATCHRAM_VALUE_TABLE_ADDRESS = 0x270000
PATCHRAM_NUMBER_OF_SLOTS = 256
PATCHRAM_ALIGNED = False
# only seems to work 4-byte aligned here ...
# Patchram
PATCHRAM_TARGET_TABLE_ADDRESS = 0x310000
PATCHRAM_ENABLED_BITMAP_ADDRESS = 0x310404
PATCHRAM_VALUE_TABLE_ADDRESS = 0x270000
PATCHRAM_NUMBER_OF_SLOTS = 256
PATCHRAM_ALIGNED = False
# only seems to work 4-byte aligned here ...
+16 -15
View File
@@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python
#
# fw_0x220e.py
#
@@ -22,21 +22,22 @@
# liability, whether in an action of contract, tort or otherwise, arising from,
# out of or in connection with the Software or the use or other dealings in the
# Software.
from __future__ import absolute_import
from .fw import MemorySection
from .fw import MemorySection, FirmwareDefinition
# Firmware Infos
FW_NAME = "BCM20702A1 (USB Bluetooth dongle)"
# Device Infos
# DEVICE_NAME = 0x280CD0 # rm_deviceLocalName, FIXME has no longer a length byte prepended
# BD_ADDR = 0x280CA4 # rm_deviceBDAddr
class BCM20702A1(FirmwareDefinition):
# Firmware Infos
FW_NAME = "BCM20702A1" # (USB Bluetooth dongle)
# Memory Sections
# start, end, is_rom? is_ram?
SECTIONS = [
MemorySection(0x00000000, 0x5FFFF, True, False), # Internal ROM
MemorySection(0x80000, 0x9BFFF, False, True), # Internal RAM
]
BLOC_HEAD = 0x3166C
# Device Infos
# DEVICE_NAME = 0x280CD0 # rm_deviceLocalName, FIXME has no longer a length byte prepended
# BD_ADDR = 0x280CA4 # rm_deviceBDAddr
# Memory Sections
# start, end, is_rom? is_ram?
SECTIONS = [
MemorySection(0x00000000, 0x5FFFF, True, False), # Internal ROM
MemorySection(0x80000, 0x9BFFF, False, True), # Internal RAM
]
BLOC_HEAD = 0x3166C
+24 -26
View File
@@ -1,9 +1,5 @@
#!/usr/bin/env python2
#!/usr/bin/env python
# fw_default.py
#
# Generic firmware file in case we do not know something...
#
# Copyright (c) 2019 Jiska Classen. (MIT License)
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
@@ -23,27 +19,29 @@
# Software.
from __future__ import absolute_import
from .fw import MemorySection
from .fw import MemorySection, FirmwareDefinition
# Firmware Infos
FW_NAME = "BCM20703A2 (MacBook Pro 2016)"
# Symbols contained in:
# ./WICED-Studio-6.2/20706-A2_Bluetooth/Wiced-BT/BLD_ROM/A_20703A2/20703.symdefs
# ./WICED-Studio-6.2/20706-A2_Bluetooth/Wiced-BT/tier2/brcm/wiced_uart/bld/A_20703A2/20703_ram_ext.lst
class BCM20703A2(FirmwareDefinition):
# Firmware Infos
FW_NAME = "BCM20703A2 (MacBook Pro 2016)"
# Memory Sections
# start, end, is_rom? is_ram?
SECTIONS = [
MemorySection(0x0, 0xC7FFF, True, False), # 0x000c0a97
MemorySection(0xD0000, 0xE0000, False, False), # 0x000dd78c
MemorySection(0x200000, 0x240000, False, True), # 0x00217a38
MemorySection(0x260000, 0x268FFF, True, False), # 0x0026841d
MemorySection(0x318000, 0x320000, False, False),
MemorySection(0x324000, 0x338000, False, False),
MemorySection(0x362000, 0x362100, False, False),
MemorySection(0x363000, 0x363100, False, False),
MemorySection(0x600000, 0x600800, False, False),
MemorySection(0x640000, 0x640800, False, False),
MemorySection(0x650000, 0x650800, False, False),
]
# Symbols contained in:
# ./WICED-Studio-6.2/20706-A2_Bluetooth/Wiced-BT/BLD_ROM/A_20703A2/20703.symdefs
# ./WICED-Studio-6.2/20706-A2_Bluetooth/Wiced-BT/tier2/brcm/wiced_uart/bld/A_20703A2/20703_ram_ext.lst
# Memory Sections
# start, end, is_rom? is_ram?
SECTIONS = [
MemorySection(0x0, 0xC7FFF, True, False), # 0x000c0a97
MemorySection(0xD0000, 0xE0000, False, False), # 0x000dd78c
MemorySection(0x200000, 0x240000, False, True), # 0x00217a38
MemorySection(0x260000, 0x268FFF, True, False), # 0x0026841d
MemorySection(0x318000, 0x320000, False, False),
MemorySection(0x324000, 0x338000, False, False),
MemorySection(0x362000, 0x362100, False, False),
MemorySection(0x363000, 0x363100, False, False),
MemorySection(0x600000, 0x600800, False, False),
MemorySection(0x640000, 0x640800, False, False),
MemorySection(0x650000, 0x650800, False, False),
]
+129 -131
View File
@@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python
# fw.py
#
@@ -26,146 +26,144 @@
# Software.
from __future__ import absolute_import
from .fw import MemorySection
# Firmware Infos
# This runs on Nexus 6P, Samsung Galaxy S6, Samsung Galaxy S6 edge
FW_NAME = "BCM4358A3"
# Device Infos
DEVICE_NAME = 0x213994 # [type: 1byte] [len: 1byte] [name: len byte] #works
BD_ADDR = 0x201C48 # works
from .fw import MemorySection, FirmwareDefinition
# Memory Sections
# start, end, is_rom? is_ram?
SECTIONS = [
MemorySection(0x0, 0x9EF00, True, False),
MemorySection(
0xD0000, 0xD8000, False, True
), # Patchram values with actual code / hooks
# MemorySection(0xe0000, 0x1e0000, True , False), # all zero
MemorySection(0x200000, 0x22A000, False, True),
MemorySection(0x260000, 0x268000, True, False),
# MemorySection(0x280000, 0x2a0000, True , False), # all zero
MemorySection(0x300000, 0x301000, False, False),
MemorySection(0x310000, 0x318000, False, True), # Patchram addresses
MemorySection(0x318000, 0x322000, False, False),
MemorySection(0x324000, 0x368000, False, False),
MemorySection(0x600000, 0x600800, False, False),
MemorySection(0x640000, 0x640800, False, False),
MemorySection(0x650000, 0x650800, False, False),
# MemorySection(0x680000, 0x800000, False, False)
# MemorySection(0x770000, 0x78ffff, False, False), #TODO maybe more, but all zero
]
class BCM4358A3(FirmwareDefinition):
# Firmware Infos
# This runs on Nexus 6P, Samsung Galaxy S6, Samsung Galaxy S6 edge
FW_NAME = "BCM4358A3"
# Device Infos
DEVICE_NAME = 0x213994 # [type: 1byte] [len: 1byte] [name: len byte] #works
BD_ADDR = 0x201C48 # works
# Memory Sections
# start, end, is_rom? is_ram?
SECTIONS = [
MemorySection(0x0, 0x9EF00, True, False),
MemorySection(
0xD0000, 0xD8000, False, True
), # Patchram values with actual code / hooks
# MemorySection(0xe0000, 0x1e0000, True , False), # all zero
MemorySection(0x200000, 0x22A000, False, True),
MemorySection(0x260000, 0x268000, True, False),
# MemorySection(0x280000, 0x2a0000, True , False), # all zero
MemorySection(0x300000, 0x301000, False, False),
MemorySection(0x310000, 0x318000, False, True), # Patchram addresses
MemorySection(0x318000, 0x322000, False, False),
MemorySection(0x324000, 0x368000, False, False),
MemorySection(0x600000, 0x600800, False, False),
MemorySection(0x640000, 0x640800, False, False),
MemorySection(0x650000, 0x650800, False, False),
# MemorySection(0x680000, 0x800000, False, False)
# MemorySection(0x770000, 0x78ffff, False, False), #TODO maybe more, but all zero
]
# Connection Struct and Table
# Nexus 6P works differently:
# address 0x21AD5C holds a list with pointers to connection structs!
# CONNECTION_ARRAY_ADDRESS = 0x21ad88 #potentially the first valid address... but not part of an array
# CONNECTION_ARRAY_SIZE = 11 #is still 11 for Nexus 6P, but no longer hard-coded
CONNECTION_LIST_ADDRESS = 0x21AD5C
CONNECTION_MAX = 11
CONNECTION_STRUCT_LENGTH = 0x168 # ??
# Patchram
PATCHRAM_ENABLED_BITMAP_ADDRESS = 0x310204
PATCHRAM_TARGET_TABLE_ADDRESS = 0x310000
PATCHRAM_VALUE_TABLE_ADDRESS = 0xD0000
PATCHRAM_NUMBER_OF_SLOTS = 192
PATCHRAM_ALIGNED = False # we can use standard ReadRAM HCI on Nexus 6P
LAUNCH_RAM_PAUSE = 8 # bugfix: pause between multiple readMemAligned() calls in seconds
# not a problem: doing multiple writeMem in a row
# the thing that crashes: executing multiple launchRam() in a row: sendhcicmd 0xfc4e 0x473CC
# crashes even when executing 0x5E860 twice, which is just a nullsub
# also crashes during the pause if there are other hci events
# Snippet for sendLmpPacket()
SENDLMP_CODE_BASE_ADDRESS = 0xD5130
# TODO already works except for correct mac address - so still a problem with the connection #
SENDLMP_ASM_CODE = """
push {r4,lr}
// malloc buffer for LMP packet
bl 0x3AAA8 // malloc_0x20_bloc_buffer_memzero
mov r4, r0 // store buffer for LMP packet inside r4
// fill buffer
add r0, 0xC // The actual LMP packet must start at offset 0xC in the buffer.
// The first 12 bytes are (supposely?) unused and remain zero.
ldr r1, =payload // LMP packet is stored at the end of the snippet
mov r2, 20 // Max. size of an LMP packet is 19 (I guess). The send_LMP_packet
// function will use the LMP opcode to lookup the actual size and
// use it for actually transmitting the correct number of bytes.
bl 0x63900+1 // memcpy
// load conn struct pointer (needed for determine if we are master or slave)
mov r0, %d // connection number is injected by sendLmpPacket()
bl 0x473CC // find connection struct from conn nr (r0 will hold pointer to conn struct) //FIXME
//FIXME: mac address is always 1f:8d:00:00:00:00
// set tid bit if we are the slave
ldr r1, [r0, 0x1c] // Load a bitmap from the connection struct into r1.
lsr r1, 15 // The 'we are master'-bit is at position 15 of this bitmap
eor r1, 0x1 // invert and isolate the bit to get the correct value for the TID bit
and r1, 0x1
ldr r2, [r4, 0xC] // Load the LMP opcode into r2. Note: The opcode was already shifted
// left by 1 bit (done by sendLmpPacket()). The TID bit goes into
// the LSB (least significant bit) of this shifted opcode byte.
orr r2, r1 // insert the TID bit into the byte
str r2, [r4, 0xC] // Store the byte back into the LMP packet buffer
# Connection Struct and Table
// send LMP packet
mov r1, r4 // load the address of the LMP packet buffer into r1.
// r0 still contains the connection number.
pop {r4,lr} // restore r4 and the lr
b 0xAF4C // branch to send_LMP_packet. send_LMP_packet will do the return for us.
# Nexus 6P works differently:
# address 0x21AD5C holds a list with pointers to connection structs!
# CONNECTION_ARRAY_ADDRESS = 0x21ad88 #potentially the first valid address... but not part of an array
# CONNECTION_ARRAY_SIZE = 11 #is still 11 for Nexus 6P, but no longer hard-coded
CONNECTION_LIST_ADDRESS = 0x21AD5C
CONNECTION_MAX = 11
CONNECTION_STRUCT_LENGTH = 0x168 # ??
.align // The payload (LMP packet) must be 4-byte aligend (memcpy needs aligned addresses)
payload: // Note: the payload will be appended here by the sendLmpPacket() function
"""
# Patchram
PATCHRAM_ENABLED_BITMAP_ADDRESS = 0x310204
PATCHRAM_TARGET_TABLE_ADDRESS = 0x310000
PATCHRAM_VALUE_TABLE_ADDRESS = 0xD0000
PATCHRAM_NUMBER_OF_SLOTS = 192
PATCHRAM_ALIGNED = False # we can use standard ReadRAM HCI on Nexus 6P
# Assembler snippet for the readMemAligned() function
READ_MEM_ALIGNED_ASM_LOCATION = 0xD5030
READ_MEM_ALIGNED_ASM_SNIPPET = """
push {r4, lr}
// malloc HCI event buffer
mov r1, 0xff // event code is 0xff (vendor specific HCI Event)
mov r2, %d // readMemAligned() injects the number of bytes it wants to read here
add r2, 4 // + 'READ'
mov r0, r2
adds r0, #2 // r0 needs to be 2 higher than r2 in all malloc_hci_event_buffer calls
bl 0x22C4 // malloc_hci_event_buffer (will automatically copy event code and length into the buffer)
mov r4, r0 // save pointer to the buffer in r4
LAUNCH_RAM_PAUSE = 8 # bugfix: pause between multiple readMemAligned() calls in seconds
# not a problem: doing multiple writeMem in a row
# the thing that crashes: executing multiple launchRam() in a row: sendhcicmd 0xfc4e 0x473CC
# crashes even when executing 0x5E860 twice, which is just a nullsub
# also crashes during the pause if there are other hci events
// append our custom header (the word 'READ') after the event code and event length field
add r0, 10 // write after the length field (offset 10 in event struct)
ldr r1, =0x44414552 // 'READ'
str r1, [r0]
add r0, 4 // advance the pointer. r0 now points to the beginning of our read data
// copy data to buffer
ldr r1, =0x%x // readMemAligned() injects the read_address here. r1 will be used as src pointer in the loop
mov r2, %d // readMemAligned() injects the number of dwords to read here. r2 will be the loop counter
loop:
ldr r3, [r1] // read 4 bytes from the read_address
str r3, [r0] // store them inside the HCI buffer
add r0, 4 // advance the buffer pointer
add r1, 4 // advance the read_address
subs r2, 1 // decrement the loop variable
bne loop // branch if r2 is not zero yet
# Snippet for sendLmpPacket()
SENDLMP_CODE_BASE_ADDRESS = 0xD5130
# TODO already works except for correct mac address - so still a problem with the connection #
SENDLMP_ASM_CODE = """
push {r4,lr}
// send HCI buffer to the host
mov r0, r4 // r4 still points to the beginning of the HCI buffer
// malloc buffer for LMP packet
bl 0x3AAA8 // malloc_0x20_bloc_buffer_memzero
mov r4, r0 // store buffer for LMP packet inside r4
pop {r4, lr} // return
b 0x20F4 // send_hci_event()
// fill buffer
add r0, 0xC // The actual LMP packet must start at offset 0xC in the buffer.
// The first 12 bytes are (supposely?) unused and remain zero.
ldr r1, =payload // LMP packet is stored at the end of the snippet
mov r2, 20 // Max. size of an LMP packet is 19 (I guess). The send_LMP_packet
// function will use the LMP opcode to lookup the actual size and
// use it for actually transmitting the correct number of bytes.
bl 0x63900+1 // memcpy
// load conn struct pointer (needed for determine if we are master or slave)
mov r0, %d // connection number is injected by sendLmpPacket()
bl 0x473CC // find connection struct from conn nr (r0 will hold pointer to conn struct) //FIXME
//FIXME: mac address is always 1f:8d:00:00:00:00
// set tid bit if we are the slave
ldr r1, [r0, 0x1c] // Load a bitmap from the connection struct into r1.
lsr r1, 15 // The 'we are master'-bit is at position 15 of this bitmap
eor r1, 0x1 // invert and isolate the bit to get the correct value for the TID bit
and r1, 0x1
ldr r2, [r4, 0xC] // Load the LMP opcode into r2. Note: The opcode was already shifted
// left by 1 bit (done by sendLmpPacket()). The TID bit goes into
// the LSB (least significant bit) of this shifted opcode byte.
orr r2, r1 // insert the TID bit into the byte
str r2, [r4, 0xC] // Store the byte back into the LMP packet buffer
// send LMP packet
mov r1, r4 // load the address of the LMP packet buffer into r1.
// r0 still contains the connection number.
pop {r4,lr} // restore r4 and the lr
b 0xAF4C // branch to send_LMP_packet. send_LMP_packet will do the return for us.
.align // The payload (LMP packet) must be 4-byte aligend (memcpy needs aligned addresses)
payload: // Note: the payload will be appended here by the sendLmpPacket() function
"""
# Assembler snippet for the readMemAligned() function
READ_MEM_ALIGNED_ASM_LOCATION = 0xD5030
READ_MEM_ALIGNED_ASM_SNIPPET = """
push {r4, lr}
// malloc HCI event buffer
mov r1, 0xff // event code is 0xff (vendor specific HCI Event)
mov r2, %d // readMemAligned() injects the number of bytes it wants to read here
add r2, 4 // + 'READ'
mov r0, r2
adds r0, #2 // r0 needs to be 2 higher than r2 in all malloc_hci_event_buffer calls
bl 0x22C4 // malloc_hci_event_buffer (will automatically copy event code and length into the buffer)
mov r4, r0 // save pointer to the buffer in r4
// append our custom header (the word 'READ') after the event code and event length field
add r0, 10 // write after the length field (offset 10 in event struct)
ldr r1, =0x44414552 // 'READ'
str r1, [r0]
add r0, 4 // advance the pointer. r0 now points to the beginning of our read data
// copy data to buffer
ldr r1, =0x%x // readMemAligned() injects the read_address here. r1 will be used as src pointer in the loop
mov r2, %d // readMemAligned() injects the number of dwords to read here. r2 will be the loop counter
loop:
ldr r3, [r1] // read 4 bytes from the read_address
str r3, [r0] // store them inside the HCI buffer
add r0, 4 // advance the buffer pointer
add r1, 4 // advance the read_address
subs r2, 1 // decrement the loop variable
bne loop // branch if r2 is not zero yet
// send HCI buffer to the host
mov r0, r4 // r4 still points to the beginning of the HCI buffer
pop {r4, lr} // return
b 0x20F4 // send_hci_event()
"""
+60 -57
View File
@@ -20,67 +20,70 @@
# out of or in connection with the Software or the use or other dealings in the
# Software.
from .fw import MemorySection
# Firmware Infos
# iPhone 6
FW_NAME = "BCM4345B0"
from __future__ import absolute_import
from .fw import MemorySection, FirmwareDefinition
# Memory Sections
# start, end, is_rom? is_ram?
SECTIONS = [
MemorySection(0x00000000, 0x000C07FF, True, False), # Internal ROM
MemorySection(
0x000D0000, 0x000DFFFF, False, True
), # Internal Memory Patchram Contents
MemorySection(0x00200400, 0x00201CFF, False, True), # Internal Memory Cortex M3
]
# Patchram
PATCHRAM_TARGET_TABLE_ADDRESS = 0x310000 # needs to be aligned read
PATCHRAM_ENABLED_BITMAP_ADDRESS = 0x310204
PATCHRAM_VALUE_TABLE_ADDRESS = 0xD0000
PATCHRAM_NUMBER_OF_SLOTS = 128
PATCHRAM_ALIGNED = True
class BCM4345B0(FirmwareDefinition):
# Firmware Infos
# iPhone 6
FW_NAME = "BCM4345B0"
# Assembler snippet for the readMemAligned() function
READ_MEM_ALIGNED_ASM_LOCATION = 0x215000 # there is nothing free until 0xdffff, but 0x215000 looks okay during runtime
READ_MEM_ALIGNED_ASM_SNIPPET = """
push {r4, lr}
# Memory Sections
# start, end, is_rom? is_ram?
SECTIONS = [
MemorySection(0x00000000, 0x000C07FF, True, False), # Internal ROM
MemorySection(
0x000D0000, 0x000DFFFF, False, True
), # Internal Memory Patchram Contents
MemorySection(0x00200400, 0x00201CFF, False, True), # Internal Memory Cortex M3
]
// malloc HCI event buffer
mov r0, 0xff // event code is 0xff (vendor specific HCI Event)
mov r1, %d // readMemAligned() injects the number of bytes it wants to read here
add r1, 6 // + type and length + 'READ'
bl 0x15DD4 // hci_sendEvent (will automatically copy event code and length into the buffer)
mov r4, r0 // save pointer to the buffer in r4
# Patchram
PATCHRAM_TARGET_TABLE_ADDRESS = 0x310000 # needs to be aligned read
PATCHRAM_ENABLED_BITMAP_ADDRESS = 0x310204
PATCHRAM_VALUE_TABLE_ADDRESS = 0xD0000
PATCHRAM_NUMBER_OF_SLOTS = 128
PATCHRAM_ALIGNED = True
// append our custom header (the word 'READ') after the event code and event length field
add r0, 2 // write after the length field
ldr r1, =0x44414552 // 'READ'
str r1, [r0]
add r0, 4 // advance the pointer. r0 now points to the beginning of our read data
// copy data to buffer
ldr r1, =0x%x // readMemAligned() injects the read_address here. r1 will be used as src pointer in the loop
mov r2, %d // readMemAligned() injects the number of dwords to read here. r2 will be the loop counter
loop:
ldr r3, [r1] // read 4 bytes from the read_address
str r3, [r0] // store them inside the HCI buffer
add r0, 4 // advance the buffer pointer
add r1, 4 // advance the read_address
subs r2, 1 // decrement the loop variable
bne loop // branch if r2 is not zero yet
// send HCI buffer to the host
mov r0, r4 // r4 still points to the beginning of the HCI buffer
bl 0x573B8 // send_hci_event_without_free()
// free HCI buffer
mov r0, r4
bl 0x581AE // osapi_blockPoolFree
pop {r4, pc} // return
"""
# Assembler snippet for the readMemAligned() function
READ_MEM_ALIGNED_ASM_LOCATION = 0x215000 # there is nothing free until 0xdffff, but 0x215000 looks okay during runtime
READ_MEM_ALIGNED_ASM_SNIPPET = """
push {r4, lr}
// malloc HCI event buffer
mov r0, 0xff // event code is 0xff (vendor specific HCI Event)
mov r1, %d // readMemAligned() injects the number of bytes it wants to read here
add r1, 6 // + type and length + 'READ'
bl 0x15DD4 // hci_sendEvent (will automatically copy event code and length into the buffer)
mov r4, r0 // save pointer to the buffer in r4
// append our custom header (the word 'READ') after the event code and event length field
add r0, 2 // write after the length field
ldr r1, =0x44414552 // 'READ'
str r1, [r0]
add r0, 4 // advance the pointer. r0 now points to the beginning of our read data
// copy data to buffer
ldr r1, =0x%x // readMemAligned() injects the read_address here. r1 will be used as src pointer in the loop
mov r2, %d // readMemAligned() injects the number of dwords to read here. r2 will be the loop counter
loop:
ldr r3, [r1] // read 4 bytes from the read_address
str r3, [r0] // store them inside the HCI buffer
add r0, 4 // advance the buffer pointer
add r1, 4 // advance the read_address
subs r2, 1 // decrement the loop variable
bne loop // branch if r2 is not zero yet
// send HCI buffer to the host
mov r0, r4 // r4 still points to the beginning of the HCI buffer
bl 0x573B8 // send_hci_event_without_free()
// free HCI buffer
mov r0, r4
bl 0x581AE // osapi_blockPoolFree
pop {r4, pc} // return
"""
+27 -24
View File
@@ -20,31 +20,34 @@
# out of or in connection with the Software or the use or other dealings in the
# Software.
from .fw import MemorySection
# Firmware Infos
# Samsung Galaxy S8
FW_NAME = "BCM4347B0"
from __future__ import absolute_import
from .fw import MemorySection, FirmwareDefinition
# Memory Sections
# start, end, is_rom? is_ram?
SECTIONS = [
MemorySection(0x00000000, 0x00100000, True, False), # Internal ROM
MemorySection(
0x00130000, 0x00150000, False, True
), # Internal Memory Patchram Contents
MemorySection(0x00200000, 0x0023FFFF, False, True), # Internal Memory Cortex M3
]
# Patchram
PATCHRAM_TARGET_TABLE_ADDRESS = 0x310000
PATCHRAM_ENABLED_BITMAP_ADDRESS = 0x310404
PATCHRAM_VALUE_TABLE_ADDRESS = 0x130000
PATCHRAM_NUMBER_OF_SLOTS = 256
PATCHRAM_ALIGNED = False
class BCM4347B0(FirmwareDefinition):
# Firmware Infos
# Samsung Galaxy S8
FW_NAME = "BCM4347B0"
# Heap
BLOC_HEAD = 0x20067C # g_dynamic_memory_GeneralUsePools
BLOC_NG = True # Next Generation Bloc Buffer
# Memory Sections
# start, end, is_rom? is_ram?
SECTIONS = [
MemorySection(0x00000000, 0x00100000, True, False), # Internal ROM
MemorySection(
0x00130000, 0x00150000, False, True
), # Internal Memory Patchram Contents
MemorySection(0x00200000, 0x0023FFFF, False, True), # Internal Memory Cortex M3
]
# Patchram
PATCHRAM_TARGET_TABLE_ADDRESS = 0x310000
PATCHRAM_ENABLED_BITMAP_ADDRESS = 0x310404
PATCHRAM_VALUE_TABLE_ADDRESS = 0x130000
PATCHRAM_NUMBER_OF_SLOTS = 256
PATCHRAM_ALIGNED = False
# Heap
BLOC_HEAD = 0x20067C # g_dynamic_memory_GeneralUsePools
BLOC_NG = True # Next Generation Bloc Buffer
+1 -1
View File
@@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python
#
# fw_0x220e.py
#
+5 -5
View File
@@ -19,15 +19,15 @@
# liability, whether in an action of contract, tort or otherwise, arising from,
# out of or in connection with the Software or the use or other dealings in the
# Software.
from __future__ import absolute_import
from .fw import MemorySection, FirmwareDefinition
# Firmware Infos
# Evaluation Kit CYW920735
from .. import Address
class CYW20735B1(FirmwareDefinition):
# Firmware Infos
# Evaluation Kit CYW920735
FW_NAME = "CYW20735B1"
# Device Infos
@@ -37,7 +37,7 @@ class CYW20735B1(FirmwareDefinition):
BD_ADDR = 0x280CA4 # rm_deviceBDAddr
# Heap
BLOC_HEAD = Address(0x200474) # g_dynamic_memory_GeneralUsePools
BLOC_HEAD = 0x200474 # g_dynamic_memory_GeneralUsePools
BLOC_NG = True # Next Generation Bloc Buffer
# Memory Sections
+3 -2
View File
@@ -19,8 +19,9 @@
# liability, whether in an action of contract, tort or otherwise, arising from,
# out of or in connection with the Software or the use or other dealings in the
# Software.
from .fw import MemorySection, FirmwareDefinition
from __future__ import absolute_import
from .fw import MemorySection, FirmwareDefinition
from .. import Address
@@ -37,7 +38,7 @@ class CYW20739B1(FirmwareDefinition):
BD_ADDR = 0x280CA4 # rm_deviceBDAddr
# Heap
BLOC_HEAD = Address(0x0200C7C) # g_dynamic_memory_GeneralUsePools
BLOC_HEAD = 0x0200C7C # g_dynamic_memory_GeneralUsePools
BLOC_NG = True # Next Generation Bloc Buffer
# Memory Sections
+22 -19
View File
@@ -20,25 +20,28 @@
# out of or in connection with the Software or the use or other dealings in the
# Software.
from .fw import MemorySection
from __future__ import absolute_import
from .fw import MemorySection, FirmwareDefinition
# Firmware Infos
# iPhone 8/X/XR
FW_NAME = "BCM4347B1"
# Memory Sections
# start, end, is_rom? is_ram?
SECTIONS = [
MemorySection(0x00000000, 0x00103FFF, True, False), # Internal ROM
MemorySection(
0x00130000, 0x0014FFFF, False, True
), # Internal Memory Patchram Contents
MemorySection(0x00200000, 0x0024FFFF, False, True), # Internal Memory Cortex M3
]
class BCM4347B1(FirmwareDefinition):
# Firmware Infos
# iPhone 8/X/XR
FW_NAME = "BCM4347B1"
# Patchram
PATCHRAM_TARGET_TABLE_ADDRESS = 0x310000
PATCHRAM_ENABLED_BITMAP_ADDRESS = 0x310404
PATCHRAM_VALUE_TABLE_ADDRESS = 0x130000
PATCHRAM_NUMBER_OF_SLOTS = 256
PATCHRAM_ALIGNED = False
# Memory Sections
# start, end, is_rom? is_ram?
SECTIONS = [
MemorySection(0x00000000, 0x00103FFF, True, False), # Internal ROM
MemorySection(
0x00130000, 0x0014FFFF, False, True
), # Internal Memory Patchram Contents
MemorySection(0x00200000, 0x0024FFFF, False, True), # Internal Memory Cortex M3
]
# Patchram
PATCHRAM_TARGET_TABLE_ADDRESS = 0x310000
PATCHRAM_ENABLED_BITMAP_ADDRESS = 0x310404
PATCHRAM_VALUE_TABLE_ADDRESS = 0x130000
PATCHRAM_NUMBER_OF_SLOTS = 256
PATCHRAM_ALIGNED = False
+14 -12
View File
@@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python
# MacBook 15" early 2011 tested with Ubuntu
#
@@ -22,17 +22,19 @@
# out of or in connection with the Software or the use or other dealings in the
# Software.
from .fw import MemorySection
from .fw import MemorySection, FirmwareDefinition
# Firmware Infos
FW_NAME = "BCM2070B0 (MacBook Pro 2011)"
# Build date: Jul 9 2008
# Memory Sections
# start, end, is_rom? is_ram?
SECTIONS = [
MemorySection(0x0, 0x58000, True, False),
MemorySection(0x80000, 0x9B000, False, True),
]
class BCM2070B0(FirmwareDefinition):
# Firmware Infos
FW_NAME = "BCM2070B0 (MacBook Pro 2011)"
# Build date: Jul 9 2008
BLOC_HEAD = 0x88518
# Memory Sections
# start, end, is_rom? is_ram?
SECTIONS = [
MemorySection(0x0, 0x58000, True, False),
MemorySection(0x80000, 0x9B000, False, True),
]
BLOC_HEAD = 0x88518
+33 -30
View File
@@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python
# fw_0x6103.py
#
@@ -20,36 +20,39 @@
# out of or in connection with the Software or the use or other dealings in the
# Software.
from .fw import MemorySection
from __future__ import absolute_import
from .fw import MemorySection, FirmwareDefinition
# Firmware Infos
# This runs on an iPhone 7
FW_NAME = "BCM4355C0"
# Device Infos
DEVICE_NAME = 0x204C60
class BCM4355C0(FirmwareDefinition):
# Firmware Infos
# This runs on an iPhone 7
FW_NAME = "BCM4355C0"
# Memory Sections
# start, end, is_rom? is_ram?
SECTIONS = [
MemorySection(0x0, 0x90000, True, False),
MemorySection(0xD0000, 0xD8000, False, True),
# MemorySection(0xe0000, 0x1f0000, True , False),
MemorySection(0x200000, 0x228000, False, True),
MemorySection(0x260000, 0x268000, True, False),
# MemorySection(0x280000, 0x2a0000, True , False),
MemorySection(0x318000, 0x320000, False, False),
MemorySection(0x324000, 0x360000, False, False),
MemorySection(0x362000, 0x362100, False, False),
MemorySection(0x363000, 0x363100, False, False),
MemorySection(0x600000, 0x600800, False, False),
MemorySection(0x640000, 0x640800, False, False),
MemorySection(0x650000, 0x650800, False, False),
# MemorySection(0x680000, 0x800000, False, False)
]
# Device Infos
DEVICE_NAME = 0x204C60
PATCHRAM_TARGET_TABLE_ADDRESS = 0x310000
PATCHRAM_ENABLED_BITMAP_ADDRESS = 0x310204
PATCHRAM_VALUE_TABLE_ADDRESS = 0xD0000
PATCHRAM_NUMBER_OF_SLOTS = 192
PATCHRAM_ALIGNED = False
# Memory Sections
# start, end, is_rom? is_ram?
SECTIONS = [
MemorySection(0x0, 0x90000, True, False),
MemorySection(0xD0000, 0xD8000, False, True),
# MemorySection(0xe0000, 0x1f0000, True , False),
MemorySection(0x200000, 0x228000, False, True),
MemorySection(0x260000, 0x268000, True, False),
# MemorySection(0x280000, 0x2a0000, True , False),
MemorySection(0x318000, 0x320000, False, False),
MemorySection(0x324000, 0x360000, False, False),
MemorySection(0x362000, 0x362100, False, False),
MemorySection(0x363000, 0x363100, False, False),
MemorySection(0x600000, 0x600800, False, False),
MemorySection(0x640000, 0x640800, False, False),
MemorySection(0x650000, 0x650800, False, False),
# MemorySection(0x680000, 0x800000, False, False)
]
PATCHRAM_TARGET_TABLE_ADDRESS = 0x310000
PATCHRAM_ENABLED_BITMAP_ADDRESS = 0x310204
PATCHRAM_VALUE_TABLE_ADDRESS = 0xD0000
PATCHRAM_NUMBER_OF_SLOTS = 192
PATCHRAM_ALIGNED = False
+3 -1
View File
@@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python
# fw_0x6109.py
#
@@ -24,6 +24,8 @@
# liability, whether in an action of contract, tort or otherwise, arising from,
# out of or in connection with the Software or the use or other dealings in the
# Software.
from __future__ import absolute_import
from .fw import MemorySection, FirmwareDefinition
+55 -62
View File
@@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python
# fw_0x6119.py
#
@@ -27,74 +27,67 @@
# Firmware Infos
# This runs on Rasperry Pi 3+
from builtins import object
FW_NAME = "BCM4345C0"
# Device Infos
DEVICE_NAME = 0x204954
# Memory Sections
class MemorySection(object):
def __init__(self, start_addr, end_addr, is_rom, is_ram):
self.start_addr = start_addr
self.end_addr = end_addr
self.is_rom = is_rom
self.is_ram = is_ram
def size(self):
return self.end_addr - self.start_addr
# Memory Sections
# start, end, is_rom? is_ram?
SECTIONS = [
MemorySection(0x0, 0x90000, True, False),
MemorySection(0xD0000, 0xD8000, False, True),
# MemorySection(0xe0000, 0x1f0000, True , False),
MemorySection(0x200000, 0x228000, False, True),
MemorySection(0x260000, 0x268000, True, False),
# MemorySection(0x280000, 0x2a0000, True , False),
MemorySection(0x318000, 0x320000, False, False),
MemorySection(0x324000, 0x360000, False, False),
MemorySection(0x362000, 0x362100, False, False),
MemorySection(0x363000, 0x363100, False, False),
MemorySection(0x600000, 0x600800, False, False),
MemorySection(0x640000, 0x640800, False, False),
MemorySection(0x650000, 0x650800, False, False),
# MemorySection(0x680000, 0x800000, False, False)
]
from __future__ import absolute_import
from .fw import MemorySection, FirmwareDefinition
# Connection Structure and Table
CONNECTION_ARRAY_ADDRESS = 0x204BA8
CONNECTION_MAX = 11
CONNECTION_STRUCT_LENGTH = 0x150
# Patchram
PATCHRAM_ENABLED_BITMAP_ADDRESS = 0x310204
PATCHRAM_TARGET_TABLE_ADDRESS = 0x310000
PATCHRAM_VALUE_TABLE_ADDRESS = 0xD0000
PATCHRAM_NUMBER_OF_SLOTS = 128
PATCHRAM_ALIGNED = False
class BCM4345C0(FirmwareDefinition):
FW_NAME = "BCM4345C0"
# Heap
BLOC_HEAD = 0x200490 # g_dynamic_memory_GeneralUsePools
BLOC_NG = True # Next Generation Bloc Buffer
# Device Infos
DEVICE_NAME = 0x204954
# Snippet for sendLcpPacket()
SENDLCP_CODE_BASE_ADDRESS = 0x21F000
SENDLCP_ASM_CODE = """
push {r4,lr}
# Memory Sections
# start, end, is_rom? is_ram?
SECTIONS = [
MemorySection(0x0, 0x90000, True, False),
MemorySection(0xD0000, 0xD8000, False, True),
# MemorySection(0xe0000, 0x1f0000, True , False),
MemorySection(0x200000, 0x228000, False, True),
MemorySection(0x260000, 0x268000, True, False),
# MemorySection(0x280000, 0x2a0000, True , False),
MemorySection(0x318000, 0x320000, False, False),
MemorySection(0x324000, 0x360000, False, False),
MemorySection(0x362000, 0x362100, False, False),
MemorySection(0x363000, 0x363100, False, False),
MemorySection(0x600000, 0x600800, False, False),
MemorySection(0x640000, 0x640800, False, False),
MemorySection(0x650000, 0x650800, False, False),
# MemorySection(0x680000, 0x800000, False, False)
]
// we want to call lmulp_sendLcp(conn_index, input, length)
# Connection Structure and Table
CONNECTION_ARRAY_ADDRESS = 0x204BA8
CONNECTION_MAX = 11
CONNECTION_STRUCT_LENGTH = 0x150
mov r0, %d // connection index, starts at 0
ldr r1, =payload
mov r2, %d // length
bl 0x92062 // lmulp_sendLcp
# Patchram
PATCHRAM_ENABLED_BITMAP_ADDRESS = 0x310204
PATCHRAM_TARGET_TABLE_ADDRESS = 0x310000
PATCHRAM_VALUE_TABLE_ADDRESS = 0xD0000
PATCHRAM_NUMBER_OF_SLOTS = 128
PATCHRAM_ALIGNED = False
pop {r4,pc} // go back
# Heap
BLOC_HEAD = 0x200490 # g_dynamic_memory_GeneralUsePools
BLOC_NG = True # Next Generation Bloc Buffer
.align // The payload (LMP packet) must be 4-byte aligend (memcpy needs aligned addresses)
payload: // Note: the payload will be appended here by the sendLmpPacket() function
"""
# Snippet for sendLcpPacket()
SENDLCP_CODE_BASE_ADDRESS = 0x21F000
SENDLCP_ASM_CODE = """
push {r4,lr}
// we want to call lmulp_sendLcp(conn_index, input, length)
mov r0, %d // connection index, starts at 0
ldr r1, =payload
mov r2, %d // length
bl 0x92062 // lmulp_sendLcp
pop {r4,pc} // go back
.align // The payload (LMP packet) must be 4-byte aligend (memcpy needs aligned addresses)
payload: // Note: the payload will be appended here by the sendLmpPacket() function
"""
+24 -21
View File
@@ -20,27 +20,30 @@
# out of or in connection with the Software or the use or other dealings in the
# Software.
from .fw import MemorySection
# Firmware Infos
# iPhone 6
FW_NAME = "BCM4345B0"
from __future__ import absolute_import
from .fw import MemorySection, FirmwareDefinition
# Memory Sections
# start, end, is_rom? is_ram?
SECTIONS = [
MemorySection(0x00000000, 0x000C07FF, True, False), # Internal ROM
MemorySection(
0x000D0000, 0x000DFFFF, False, True
), # Internal Memory Patchram Contents
MemorySection(0x00200400, 0x00201CFF, False, True), # Internal Memory Cortex M3
]
class BCM4345B0(FirmwareDefinition):
# Firmware Infos
# iPhone 6
FW_NAME = "BCM4345B0"
# Patchram
# PATCHRAM_TARGET_TABLE_ADDRESS = 0x310000 #TODO needs to be aligned read
# PATCHRAM_ENABLED_BITMAP_ADDRESS = 0x310204
# PATCHRAM_VALUE_TABLE_ADDRESS = 0xd0000
# PATCHRAM_NUMBER_OF_SLOTS = 128
# PATCHRAM_ALIGNED = True
# only seems to work 4-byte aligned here ...
# Memory Sections
# start, end, is_rom? is_ram?
SECTIONS = [
MemorySection(0x00000000, 0x000C07FF, True, False), # Internal ROM
MemorySection(
0x000D0000, 0x000DFFFF, False, True
), # Internal Memory Patchram Contents
MemorySection(0x00200400, 0x00201CFF, False, True), # Internal Memory Cortex M3
]
# Patchram
# PATCHRAM_TARGET_TABLE_ADDRESS = 0x310000 #TODO needs to be aligned read
# PATCHRAM_ENABLED_BITMAP_ADDRESS = 0x310204
# PATCHRAM_VALUE_TABLE_ADDRESS = 0xd0000
# PATCHRAM_NUMBER_OF_SLOTS = 128
# PATCHRAM_ALIGNED = True
# only seems to work 4-byte aligned here ...
+24 -21
View File
@@ -20,27 +20,30 @@
# out of or in connection with the Software or the use or other dealings in the
# Software.
from .fw import MemorySection
# Firmware Infos
# iPhone SE
FW_NAME = "BCM4345C1"
from __future__ import absolute_import
from .fw import MemorySection, FirmwareDefinition
# Memory Sections
# start, end, is_rom? is_ram?
SECTIONS = [
MemorySection(0x00000000, 0x000C07FF, True, False), # Internal ROM
MemorySection(
0x000D0000, 0x000DFFFF, False, True
), # Internal Memory Patchram Contents
MemorySection(0x00200400, 0x00201CFF, False, True), # Internal Memory Cortex M3
]
class BCM4345C1(FirmwareDefinition):
# Firmware Infos
# iPhone SE
FW_NAME = "BCM4345C1"
# Patchram
PATCHRAM_TARGET_TABLE_ADDRESS = 0x310000
PATCHRAM_ENABLED_BITMAP_ADDRESS = 0x310204
PATCHRAM_VALUE_TABLE_ADDRESS = 0xD0000
PATCHRAM_NUMBER_OF_SLOTS = 128
PATCHRAM_ALIGNED = False
# only seems to work 4-byte aligned here ...
# Memory Sections
# start, end, is_rom? is_ram?
SECTIONS = [
MemorySection(0x00000000, 0x000C07FF, True, False), # Internal ROM
MemorySection(
0x000D0000, 0x000DFFFF, False, True
), # Internal Memory Patchram Contents
MemorySection(0x00200400, 0x00201CFF, False, True), # Internal Memory Cortex M3
]
# Patchram
PATCHRAM_TARGET_TABLE_ADDRESS = 0x310000
PATCHRAM_ENABLED_BITMAP_ADDRESS = 0x310204
PATCHRAM_VALUE_TABLE_ADDRESS = 0xD0000
PATCHRAM_NUMBER_OF_SLOTS = 128
PATCHRAM_ALIGNED = False
# only seems to work 4-byte aligned here ...
+3 -1
View File
@@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python
# fw_default.py
#
@@ -21,6 +21,8 @@
# liability, whether in an action of contract, tort or otherwise, arising from,
# out of or in connection with the Software or the use or other dealings in the
# Software.
from __future__ import absolute_import
from .fw import MemorySection, FirmwareDefinition
+21 -17
View File
@@ -30,6 +30,7 @@ from builtins import hex
from builtins import range
from builtins import object
from enum import Enum
from datetime import datetime
from internalblue.utils.pwnlib_wrapper import (
p8,
@@ -931,7 +932,7 @@ class StackDumpReceiver(object):
def __init__(self, data_directory="."):
self.data_directory = data_directory
self.stack_dump_filename = data_directory + "/internalblue_stackdump.bin"
self.stack_dump_filename = data_directory + ("/internalblue_stackdump_%s.bin" % datetime.now())
def recvPacket(self, record):
hcipkt = record[0]
@@ -956,20 +957,23 @@ class StackDumpReceiver(object):
""" Data should be a byte string containing all payload bytes
beginning with the checksum byte.
"""
return sum([ord(x) for x in data]) % 0x100 == 0
return sum(data) % 0x100 == 0
def handleRamDump(self, data):
""" Data should be a byte string containing the address (4 byte)
followed by the actual ram dump (at this address)
"""
addr = u32(data[:4])
if self.memdump_addr == None:
if self.memdump_addr is None:
self.memdump_addr = addr
self.memdumps[addr - self.memdump_addr] = data[4:]
self.memdumps[addr - self.memdump_addr] = bytes(data[4:]) # convert from bytearray to bytes
log.debug("Stack dump handling addr %08x", addr - self.memdump_addr)
def finishStackDump(self):
dump = flat(self.memdumps)
"""
Write the stack dump to a file once it is finished.
"""
dump = flat(self.memdumps) # flatten, as we have one entry per address chunk
log.warn(
"Stack dump @0x%08x written to %s!"
% (self.memdump_addr, self.stack_dump_filename)
@@ -983,7 +987,7 @@ class StackDumpReceiver(object):
def handleNexus5StackDump(self, hcipkt):
checksum_correct = self.verifyChecksum(hcipkt.data[5:])
packet_type = u8(hcipkt.data[4])
packet_type = hcipkt.data[4]
if packet_type == 0x2C:
data = hcipkt.data[6:]
@@ -995,10 +999,10 @@ class StackDumpReceiver(object):
"\n".join([hex(x) for x in values]),
)
)
if data[0] == "\x02":
if data[0] == 0x02:
# This is the second stack dump event (contains register values)
log.warn(
"Received Stack-Dump Event (contains %d registers):" % (u8(data[1]))
"Received Stack-Dump Event (contains %d registers):" % (data[1])
)
registers = (
"pc: 0x%08x lr: 0x%08x sp: 0x%08x r0: 0x%08x r1: 0x%08x\n"
@@ -1023,8 +1027,8 @@ class StackDumpReceiver(object):
def handleNexus6pStackDump(self, hcipkt):
checksum_correct = self.verifyChecksum(hcipkt.data[8:])
packet_nr = u8(hcipkt.data[2])
packet_type = u8(hcipkt.data[7])
packet_nr = hcipkt.data[2]
packet_type = hcipkt.data[7]
if packet_type in [0x2C, 0x4C]:
data = hcipkt.data[9:]
@@ -1038,10 +1042,10 @@ class StackDumpReceiver(object):
)
)
if packet_type == 0x2C and data[0] == "\x02":
if packet_type == 0x2C and data[0] == 0x02:
# This is the second stack dump event (contains register values)
log.warn(
"Received Stack-Dump Event (contains %d registers):" % (u8(data[1]))
"Received Stack-Dump Event (contains %d registers):" % (data[1])
)
registers = (
"pc: 0x%08x lr: 0x%08x sp: 0x%08x r0: 0x%08x r1: 0x%08x\n"
@@ -1087,7 +1091,7 @@ class StackDumpReceiver(object):
:return: returns True if dump could be decoded.
"""
checksum_correct = self.verifyChecksum(hcipkt.data[3:])
packet_type = u8(hcipkt.data[2])
packet_type = hcipkt.data[2]
log.debug("packet type %x", packet_type)
@@ -1104,11 +1108,11 @@ class StackDumpReceiver(object):
"\n".join([hex(x) for x in values]),
)
)
if data[0] == "\x02":
if data[0] == 0x02:
# This is the second stack dump event (contains register values)
log.warn(
"Received Evaluation Stack-Dump Event (contains %d registers):"
% (u8(data[1]))
% (data[1])
)
registers = (
"pc: 0x%08x lr: 0x%08x sp: 0x%08x r0: 0x%08x r1: 0x%08x\n"
@@ -1160,7 +1164,7 @@ class StackDumpReceiver(object):
"""
checksum_correct = self.verifyChecksum(hcipkt.data[3:])
packet_type = u8(hcipkt.data[2])
packet_type = hcipkt.data[2]
if packet_type == 0x90:
data = hcipkt.data[4:]
@@ -1174,7 +1178,7 @@ class StackDumpReceiver(object):
)
# Values different than in other stack dump formats, experimental output!
log.warn(
"Received S10 Stack-Dump Event (contains %d registers):" % (u8(data[1]))
"Received S10 Stack-Dump Event (contains %d registers):" % (data[1])
)
registers = (
"pc: 0x%08x lr: 0x%08x sp: 0x%08x r0: 0x%08x r1: 0x%08x\n"
+49 -29
View File
@@ -14,6 +14,7 @@ from . import hci
from internalblue.utils.pwnlib_wrapper import log, context
from .usbmux import USBMux, MuxError
from .core import InternalBlue
@@ -22,7 +23,6 @@ class iOSCore(InternalBlue):
def __init__(
self,
ios_addr,
queue_size=1000,
btsnooplog_filename="btsnoop.log",
log_level="info",
@@ -32,21 +32,25 @@ class iOSCore(InternalBlue):
super(iOSCore, self).__init__(
queue_size, btsnooplog_filename, log_level, fix_binutils, data_directory="."
)
parts = ios_addr.split(":")
if len(parts) != 2:
log.critical("iOS device address should be of format HOSTNAME:PORT")
exit(-1)
self.ios_addr = parts[0]
self.ios_port = parts[1]
self.serial = False
self.doublecheck = True
self.buffer = b""
try:
self.mux = USBMux()
# on Linux, this can result in ConnectionRefusedError if no iOS device is present
except ConnectionRefusedError:
self.muxconnecterror = True
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()
@@ -54,9 +58,21 @@ class iOSCore(InternalBlue):
log.warn("Already running. Call shutdown() first!")
return []
# assume that a explicitly specified iPhone exists
# 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 = []
device_list.append((self, "iPhone", "iPhone"))
for dev in self.devices:
dev_id = "iOS Device (" + dev.serial.decode("utf-8") + ")"
device_list.append((self, dev, dev_id))
return device_list
@@ -90,27 +106,38 @@ class iOSCore(InternalBlue):
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"
"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
def _setupSockets(self):
"""
Connect to the iOS bluetooth device over internalblue-ios-proxy
Connect to the iOS Bluetooth device over usbmuxd and internalblued
"""
self.s_inject = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
self.s_inject.connect((self.ios_addr, int(self.ios_port)))
self.s_inject.settimeout(0.5)
except socket.error:
log.warn("Could not connect to iPhone, is internalblue-ios-proxy running?")
self.s_inject = self.mux.connect(self.interface, 1234)
except MuxError:
log.warn("Could not connect to iOS proxy. Is internalblued running on the connected device?")
return False
self.s_inject.settimeout(0.5)
# with ios proxy the send and receive sockets are the same
# with on iOS the send and receive sockets are the same
self.s_snoop = self.s_inject
# empty the socket (can sometimes still hold data if the previous execution
# of internalblue was cancelled or crashed)
try:
self.s_inject.recv(1024)
except socket.error:
pass
return True
def _getLatestH4Blob(self, new_data: bytes = b""):
@@ -122,18 +149,17 @@ class iOSCore(InternalBlue):
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]
acl_len = self.buffer[3]
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]
hci_len = self.buffer[3]
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]
hci_len = self.buffer[2]
required_len = hci_len + 3
# for BCM data the length should always be 64
elif self.buffer[0] == 0x07:
@@ -143,7 +169,6 @@ class iOSCore(InternalBlue):
# 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:
@@ -155,12 +180,10 @@ class iOSCore(InternalBlue):
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)
@@ -184,10 +207,7 @@ class iOSCore(InternalBlue):
except socket.timeout:
continue # this is ok. just try again without error
# because the iOS socket is rather unreliable (blame the iOS proxy developer) we
# need to do some length checks and get the H4/HCI data in the right format
# log.info("H4 Data received")
# log.info(received_data.encode('hex'))
log.debug("H4 Data: %s", received_data)
(record_data, is_more) = self._getLatestH4Blob(new_data=received_data)
while record_data is not None:
@@ -206,7 +226,7 @@ class iOSCore(InternalBlue):
): # TODO filter_function not working with bluez modifications
try:
queue.put(record, block=False)
except queue.Full:
except queue2k.Full:
log.warn(
"recvThreadFunc: A recv queue is full. dropping packets.."
)
+234
View File
@@ -0,0 +1,234 @@
#
# usbmux.py - usbmux client library for Python
#
# Copyright (C) 2009 Hector Martin "marcan" <hector@marcansoft.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 or version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
import socket, struct, select, sys
try:
import plistlib
haveplist = True
except:
haveplist = False
class MuxError(Exception):
pass
class MuxVersionError(MuxError):
pass
class SafeStreamSocket:
def __init__(self, address, family):
self.sock = socket.socket(family, socket.SOCK_STREAM)
self.sock.connect(address)
def send(self, msg):
totalsent = 0
while totalsent < len(msg):
sent = self.sock.send(msg[totalsent:])
if sent == 0:
raise MuxError("socket connection broken")
totalsent = totalsent + sent
def recv(self, size):
msg = b''
while len(msg) < size:
chunk = self.sock.recv(size-len(msg))
if chunk == b'':
raise MuxError("socket connection broken")
msg = msg + chunk
return msg
class MuxDevice(object):
def __init__(self, devid, usbprod, serial, location):
self.devid = devid
self.usbprod = usbprod
self.serial = serial
self.location = location
def __str__(self):
return "<MuxDevice: ID %d ProdID 0x%04x Serial '%s' Location 0x%x>"%(self.devid, self.usbprod, self.serial, self.location)
class BinaryProtocol(object):
TYPE_RESULT = 1
TYPE_CONNECT = 2
TYPE_LISTEN = 3
TYPE_DEVICE_ADD = 4
TYPE_DEVICE_REMOVE = 5
VERSION = 0
def __init__(self, socket):
self.socket = socket
self.connected = False
def _pack(self, req, payload):
if req == self.TYPE_CONNECT:
return struct.pack("IH", payload['DeviceID'], payload['PortNumber']) + b'\x00\x00'
elif req == self.TYPE_LISTEN:
return b""
else:
raise ValueError("Invalid outgoing request type %d"%req)
def _unpack(self, resp, payload):
if resp == self.TYPE_RESULT:
return {'Number':struct.unpack("I", payload)[0]}
elif resp == self.TYPE_DEVICE_ADD:
devid, usbpid, serial, pad, location = struct.unpack("IH256sHI", payload)
serial = serial.split(b'\00')[0]
return {'DeviceID': devid, 'Properties': {'LocationID': location, 'SerialNumber': serial, 'ProductID': usbpid}}
elif resp == self.TYPE_DEVICE_REMOVE:
devid = struct.unpack("I", payload)[0]
return {'DeviceID': devid}
else:
raise MuxError("Invalid incoming request type %d"%req)
def sendpacket(self, req, tag, payload={}):
payload = self._pack(req, payload)
if self.connected:
raise MuxError("Mux is connected, cannot issue control packets")
length = 16 + len(payload)
data = struct.pack("IIII", length, self.VERSION, req, tag) + payload
self.socket.send(data)
def getpacket(self):
if self.connected:
raise MuxError("Mux is connected, cannot issue control packets")
dlen = self.socket.recv(4)
dlen = struct.unpack("I", dlen)[0]
body = self.socket.recv(dlen - 4)
version, resp, tag = struct.unpack("III",body[:0xc])
if version != self.VERSION:
raise MuxVersionError("Version mismatch: expected %d, got %d"%(self.VERSION,version))
payload = self._unpack(resp, body[0xc:])
return (resp, tag, payload)
class PlistProtocol(BinaryProtocol):
TYPE_RESULT = "Result"
TYPE_CONNECT = "Connect"
TYPE_LISTEN = "Listen"
TYPE_DEVICE_ADD = "Attached"
TYPE_DEVICE_REMOVE = "Detached" #???
TYPE_PLIST = 8
VERSION = 1
def __init__(self, socket):
if not haveplist:
raise Exception("You need the plistlib module")
BinaryProtocol.__init__(self, socket)
def _pack(self, req, payload):
return payload
def _unpack(self, resp, payload):
return payload
def sendpacket(self, req, tag, payload={}):
payload['ClientVersionString'] = 'usbmux.py by marcan'
if isinstance(req, int):
req = [self.TYPE_CONNECT, self.TYPE_LISTEN][req-2]
payload['MessageType'] = req
payload['ProgName'] = 'tcprelay'
BinaryProtocol.sendpacket(self, self.TYPE_PLIST, tag, plistlib.dumps(payload))
def getpacket(self):
resp, tag, payload = BinaryProtocol.getpacket(self)
if resp != self.TYPE_PLIST:
raise MuxError("Received non-plist type %d"%resp)
payload = plistlib.loads(payload)
return payload['MessageType'], tag, payload
class MuxConnection(object):
def __init__(self, socketpath, protoclass):
self.socketpath = socketpath
if sys.platform in ['win32', 'cygwin']:
family = socket.AF_INET
address = ('127.0.0.1', 27015)
else:
family = socket.AF_UNIX
address = self.socketpath
self.socket = SafeStreamSocket(address, family)
self.proto = protoclass(self.socket)
self.pkttag = 1
self.devices = []
def _getreply(self):
while True:
resp, tag, data = self.proto.getpacket()
if resp == self.proto.TYPE_RESULT:
return tag, data
else:
raise MuxError("Invalid packet type received: %d"%resp)
def _processpacket(self):
resp, tag, data = self.proto.getpacket()
if resp == self.proto.TYPE_DEVICE_ADD:
self.devices.append(MuxDevice(data['DeviceID'], data['Properties']['ProductID'], data['Properties']['SerialNumber'], data['Properties']['LocationID']))
elif resp == self.proto.TYPE_DEVICE_REMOVE:
for dev in self.devices:
if dev.devid == data['DeviceID']:
self.devices.remove(dev)
elif resp == self.proto.TYPE_RESULT:
raise MuxError("Unexpected result: %d"%resp)
else:
raise MuxError("Invalid packet type received: %d"%resp)
def _exchange(self, req, payload={}):
mytag = self.pkttag
self.pkttag += 1
self.proto.sendpacket(req, mytag, payload)
recvtag, data = self._getreply()
if recvtag != mytag:
raise MuxError("Reply tag mismatch: expected %d, got %d"%(mytag, recvtag))
return data['Number']
def listen(self):
ret = self._exchange(self.proto.TYPE_LISTEN)
if ret != 0:
raise MuxError("Listen failed: error %d"%ret)
def process(self, timeout=None):
if self.proto.connected:
raise MuxError("Socket is connected, cannot process listener events")
rlo, wlo, xlo = select.select([self.socket.sock], [], [self.socket.sock], timeout)
if xlo:
self.socket.sock.close()
raise MuxError("Exception in listener socket")
if rlo:
self._processpacket()
def connect(self, device, port):
ret = self._exchange(self.proto.TYPE_CONNECT, {'DeviceID':device.devid, 'PortNumber':((port<<8) & 0xFF00) | (port>>8)})
if ret != 0:
raise MuxError("Connect failed: error %d"%ret)
self.proto.connected = True
return self.socket.sock
def close(self):
self.socket.sock.close()
class USBMux(object):
def __init__(self, socketpath=None):
if socketpath is None:
if sys.platform == 'darwin':
socketpath = "/var/run/usbmuxd"
else:
socketpath = "/var/run/usbmuxd"
self.socketpath = socketpath
self.listener = MuxConnection(socketpath, BinaryProtocol)
try:
self.listener.listen()
self.version = 0
self.protoclass = BinaryProtocol
except MuxVersionError:
self.listener = MuxConnection(socketpath, PlistProtocol)
self.listener.listen()
self.protoclass = PlistProtocol
self.version = 1
self.devices = self.listener.devices
def process(self, timeout=None):
self.listener.process(timeout)
def connect(self, device, port):
connector = MuxConnection(self.socketpath, self.protoclass)
return connector.connect(device, port)
+1 -1
View File
@@ -25,7 +25,7 @@ from pwn import log
from pwnlib.term import text
from pwnlib.ui import options, yesno
from pwnlib.util.packing import flat
from pwnlib.asm import disasm
from pwnlib.asm import disasm, asm
from pwnlib.util.fiddling import isprint, unbits, bits_str, bits
+2
View File
@@ -0,0 +1,2 @@
.theos
.DS_STORE
+14
View File
@@ -0,0 +1,14 @@
include $(THEOS)/makefiles/common.mk
TOOL_NAME = internalblued
internalblued_FILES = main.m ios-proxy.m
internalblued_CFLAGS = -fobjc-arc
include $(THEOS_MAKE_PATH)/tool.mk
SUBPROJECTS += internalbluedprefs
include $(THEOS_MAKE_PATH)/aggregate.mk
after-internalblued-stage::
$(ECHO_NOTHING)$(FAKEROOT) chown root:wheel $(THEOS_STAGING_DIR)/Library/LaunchDaemons/com.ttdennis.internalblued.plist$(ECHO_END)
+25
View File
@@ -0,0 +1,25 @@
# internalblued
This project is a proxy that redirects the *iOS* Bluetooth socket and exposes it as a
TCP socket which can be used to send HCI commands to the Bluetooth controller of the device.
A jailbroken device is required.
A compiled version of `internalblued` can be found in [`packages/com.ttdennis.internalblued_0.0.1_iphoneos-arm.deb`](packages/com.ttdennis.internalblued_0.0.1_iphoneos-arm.deb).
## Installing
1. Transfer the `.deb` file to your iOS device
2. Run `dpkg -i your-deb-file.deb` to install `internalblued` on your device
## Running internalblued
Once installed, `internalblued` runs as a `LaunchDaemon` and is ready to be used. By default it will listen to port 1234 (TCP) on localhost. If `usbmux` is installed, `internalblue` will be able to connect to the phone as the port is passed through `usbmuxd`.
During usage with `internalblue` Bluetooth has to be disabled in the phones Settings App.
In case the Bluetooth chip stops responding, Bluetooth has to be turned on and off again in the Settings App.
There is a Settings App pane for `internalblued` to turn off the daemon and adapt the listening port. However, this is usually not required. As long as `internalblue` is not connected to `internalblued`'s socket, Bluetooth can be used without any restrictions.
## Building internalblued
1. Install [theos](https://github.com/theos/theos)
2. Run `make`
3. A `.deb` file should be in the `packages` folder now
@@ -0,0 +1,5 @@
#import <Preferences/PSListController.h>
@interface IBDRootListController : PSListController
@end
@@ -0,0 +1,80 @@
#include <xpc/xpc.h>
#include "IBDRootListController.h"
#import <Preferences/PSListController.h>
#import <Preferences/PSViewController.h>
#import <Preferences/PSSpecifier.h>
#include "../xpc_protocol.h"
#define PREF_FILE @"/var/mobile/Library/Preferences/com.ttdennis.internalblue-prefs.plist"
@implementation IBDRootListController
xpc_connection_t get_connection() {
xpc_connection_t connection = xpc_connection_create_mach_service(
"com.ttdennis.internalblued", NULL, 0);
// we don't expect any responses anyway
xpc_connection_set_event_handler(connection, ^(xpc_object_t some_object) { });
xpc_connection_resume(connection);
NSLog(@"connection %@", connection);
return connection;
}
-(bool) should_stop {
for (PSSpecifier *spec in [self specifiers]) {
if ([[spec identifier] isEqualToString:@"enabled"]) {
bool isEnabled = [[self readPreferenceValue:spec] boolValue];
NSLog(@"Toggle is: %d", isEnabled);
return !isEnabled;
}
}
return false;
}
- (void)toggle:(NSNotification *)notification {
// close the number keyboard
[self.view endEditing:YES];
// force write the preference file so that the daemon will pick up the correct value
CFPreferencesSynchronize(CFSTR("com.ttdennis.internalblue-prefs"), kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);
sleep(1);
xpc_connection_t connection = get_connection();
xpc_object_t object = xpc_dictionary_create(NULL, NULL, 0);
if ([self should_stop]){
xpc_dictionary_set_uint64(object, "message", CMD_STOP_PROXY);
} else {
xpc_dictionary_set_uint64(object, "message", CMD_START_PROXY);
}
xpc_connection_send_message(connection, object);
}
void notify_ns() {
[[NSNotificationCenter defaultCenter] postNotificationName:@"com.ttdennis.internalblue/toggle" object:nil];
}
- (id) init {
self = [super init];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(toggle:)
name:@"com.ttdennis.internalblue/toggle"
object:nil];
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), (__bridge const void *)(self), (CFNotificationCallback)notify_ns,
CFSTR("com.ttdennis.internalblue/toggle"), NULL, 0);
return self;
}
- (NSArray *)specifiers {
if (!_specifiers) {
_specifiers = [self loadSpecifiersFromPlistName:@"Root" target:self];
}
return _specifiers;
}
@end
@@ -0,0 +1,15 @@
include $(THEOS)/makefiles/common.mk
BUNDLE_NAME = internalbluedprefs
internalbluedprefs_FILES = IBDRootListController.m
internalbluedprefs_INSTALL_PATH = /Library/PreferenceBundles
internalbluedprefs_FRAMEWORKS = UIKit
internalbluedprefs_PRIVATE_FRAMEWORKS = Preferences
internalbluedprefs_CFLAGS = -fobjc-arc
include $(THEOS_MAKE_PATH)/bundle.mk
internal-stage::
$(ECHO_NOTHING)mkdir -p $(THEOS_STAGING_DIR)/Library/PreferenceLoader/Preferences$(ECHO_END)
$(ECHO_NOTHING)cp entry.plist $(THEOS_STAGING_DIR)/Library/PreferenceLoader/Preferences/internalbluedprefs.plist$(ECHO_END)
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>internalbluedprefs</string>
<key>CFBundleIdentifier</key>
<string>com.ttdennis.internalblue-prefs</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>NSPrincipalClass</key>
<string>IBDRootListController</string>
</dict>
</plist>
@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>items</key>
<array>
<dict>
<key>cell</key>
<string>PSGroupCell</string>
<key>footerText</key>
<string>Enable the InternalBlue proxy. For a reliable performance Bluetooth must be disabled in the settings.</string>
</dict>
<dict>
<key>cell</key>
<string>PSSwitchCell</string>
<key>default</key>
<false/>
<key>defaults</key>
<string>com.ttdennis.internalblue-prefs</string>
<key>key</key>
<string>isEnabled</string>
<key>label</key>
<string>Enable InternalBlue Proxy</string>
<key>PostNotification</key>
<string>com.ttdennis.internalblue/toggle</string>
<key>id</key>
<string>enabled</string>
</dict>
<dict>
<key>cell</key>
<string>PSGroupCell</string>
<key>footerText</key>
<string>This sets the port the proxy is listening on. InternalBlue assumes 1234. Changing this port requires adapting InternalBlue and restarting the proxy.</string>
</dict>
<dict>
<key>cell</key>
<string>PSEditTextCell</string>
<key>default</key>
<string>1234</string>
<key>defaults</key>
<string>com.ttdennis.internalblue-prefs</string>
<key>key</key>
<string>port</string>
<key>label</key>
<string>Proxy Port</string>
<key>isNumeric</key>
<true/>
<key>id</key>
<string>port</string>
</dict>
</array>
<key>title</key>
<string>InternalBlue Proxy Settings</string>
</dict>
</plist>
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>entry</key>
<dict>
<key>bundle</key>
<string>internalbluedprefs</string>
<key>cell</key>
<string>PSLinkCell</string>
<key>detail</key>
<string>IBDRootListController</string>
<key>icon</key>
<string>icon.png</string>
<key>isController</key>
<true/>
<key>label</key>
<string>InternalBlue Proxy</string>
</dict>
</dict>
</plist>
+29
View File
@@ -0,0 +1,29 @@
//
// ios-proxy.h
// ios-proxy
//
// Copyright © 2019 ttdennis. All rights reserved.
//
#ifndef ios_proxy_h
#define ios_proxy_h
#include <stdio.h>
#define IOAOSSKYSETCHANNELSPEC 0x800C5414
#define IOAOSSKYGETCHANNELUUID 0x40105412
#define CTLIOCGINFO 0xC0644E03
typedef struct ctl_info {
uint32_t ctl_id;
char ctl_name[96];
} ctl_info_t;
int connect_bt_device();
int create_server(int port);
int wait_for_connection(int server_fd);
void proxy_bt_socket(int client, int bt);
#endif /* ios_proxy_h */
@@ -1,12 +1,11 @@
//
// internalblue-ios-proxy.c
// internalblue-ios-proxy
// ios-proxy.m
// ios-proxy
//
// Created by ttdennis on 03.05.19.
// Copyright © 2019 ttdennis. All rights reserved.
//
#include "internalblue-ios-proxy.h"
#include "ios-proxy.h"
#include <stdlib.h>
#include <fcntl.h>
@@ -24,23 +23,6 @@
#include <unistd.h>
#include <termios.h>
#define IOAOSSKYSETCHANNELSPEC 0x800C5414
#define IOAOSSKYGETCHANNELUUID 0x40105412
#define CTLIOCGINFO 0xC0644E03
typedef struct ctl_info {
uint32_t ctl_id;
char ctl_name[96];
} ctl_info_t;
int btwake_fd, bt_fd;
/*
This code has been put together by reverse-engineering BlueTool and bluetoothd on
iOS. Some of the things that happen here are not completely understood but the goal
was to just get it to work.
*/
int connect_bt_device() {
int socket_fd = socket(32, 1, 2);
int error = 0;
@@ -50,7 +32,7 @@ int connect_bt_device() {
struct termios term;
if (socket_fd == 0) {
printf("[!] Unable to get Bluetooth socket\n");
NSLog(@"[!] Unable to get Bluetooth socket\n");
return -1;
}
@@ -58,8 +40,8 @@ int connect_bt_device() {
ctl_inf->ctl_id = 0;
strcpy(ctl_inf->ctl_name, "com.apple.uart.bluetooth");
if ((error = ioctl(socket_fd, CTLIOCGINFO, ctl_inf))) {
printf("[!] ioctl(CTLIOCGINFO) = %d - errno: %d\n", error, errno);
printf("[!] error: %s\n", strerror(errno));
NSLog(@"[!] ioctl(CTLIOCGINFO) = %d - errno: %d\n", error, errno);
NSLog(@"[!] error: %s\n", strerror(errno));
return -1;
}
@@ -67,27 +49,27 @@ int connect_bt_device() {
*(int *)&sock_addr.sa_data[2] = ctl_inf->ctl_id;
ret = connect(socket_fd, &sock_addr, 0x20);
if (ret != 0) {
printf("[!] connect() = %d - errno: %d\n", ret, errno);
printf("[!] error: %s\n", strerror(errno));
NSLog(@"[!] connect() = %d - errno: %d\n", ret, errno);
NSLog(@"[!] error: %s\n", strerror(errno));
return -1;
}
printf("[*] Connected to Bluetooth chip H4 socket\n");
NSLog(@"[*] Connected to Bluetooth chip H4 socket\n");
socklen_t len = 72;
ret = getsockopt(socket_fd, 2, TIOCGETA, &term, &len);
if (ret != 0) {
printf("[!] getsockopt(TIOCGETA) = %d - errno: %d\n", ret, errno);
printf("[!] error: %s\n", strerror(errno));
NSLog(@"[!] getsockopt(TIOCGETA) = %d - errno: %d\n", ret, errno);
NSLog(@"[!] error: %s\n", strerror(errno));
return -1;
}
cfmakeraw(&term);
ret = cfsetspeed(&term, 3000000);
if (ret != 0) {
printf("[!] cfsetspeed() = %d - errno: %d\n", ret, errno);
printf("[!] error: %s\n", strerror(errno));
NSLog(@"[!] cfsetspeed() = %d - errno: %d\n", ret, errno);
NSLog(@"[!] error: %s\n", strerror(errno));
return -1;
}
@@ -95,8 +77,8 @@ int connect_bt_device() {
term.c_cflag = 232192;
ret = setsockopt(socket_fd, 2, TIOCSETA, &term, 0x48);
if (ret != 0) {
printf("[!] setsockopt() = %d - errno: %d\n", ret, errno);
printf("[!] error: %s\n", strerror(errno));
NSLog(@"[!] setsockopt() = %d - errno: %d\n", ret, errno);
NSLog(@"[!] error: %s\n", strerror(errno));
return -1;
}
@@ -114,28 +96,28 @@ int create_server(int port) {
server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd < 0) {
printf("[!] Unable to create server socket\n");
NSLog(@"[!] Unable to create server socket\n");
return -1;
}
addrlen = sizeof(server);
memset(&server, '\0', addrlen);
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_port = htons(port);
setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &on, 4);
if (bind(server_fd, (struct sockaddr *)&server, sizeof(server)) < 0) {
printf("[!] Error binding socket\n");
NSLog(@"[!] Error binding socket\n");
return -1;
}
if (listen(server_fd, 5) < 0) {
printf("[!] Failed listening on port %d, Error: %s\n", port, strerror(errno));
NSLog(@"[!] Failed listening on port %d, Error: %s\n", port, strerror(errno));
return -1;
}
printf("[*] Listening on port %d\n", port);
NSLog(@"[*] Listening on port %d\n", port);
return server_fd;
}
@@ -149,7 +131,7 @@ int wait_for_connection(int server_fd) {
client_fd = accept(server_fd, (struct sockaddr *)&client, (socklen_t *)&len);
if (client_fd < 0) {
printf("[!] Accepting connection failed\n");
NSLog(@"[!] Accepting connection failed\n");
return -1;
}
@@ -184,7 +166,7 @@ void proxy_bt_socket(int client, int bt) {
write(bt, client_buf, n);
} else {
close(client);
printf("[!] Client read failed\n");
NSLog(@"[!] Client read failed\n");
return;
}
}
@@ -195,12 +177,12 @@ void proxy_bt_socket(int client, int bt) {
write(client, bt_buf, n);
} else {
close(client);
printf("[!] H4 socket read failed\n");
NSLog(@"[!] H4 socket read failed\n");
return;
}
}
} else if (x < 0 && errno != EINTR){
printf("[!] Select failed with %s\n", strerror(errno));
NSLog(@"[!] Select failed with %s\n", strerror(errno));
close(client);
return;
}
@@ -208,54 +190,4 @@ void proxy_bt_socket(int client, int bt) {
}
}
void __exit(int sig) {
close(bt_fd);
close(btwake_fd);
exit(0);
}
int main(int argc, char **argv) {
int server_fd, client_fd;
int port;
if (argc != 2) {
printf("Usage: %s <port_number>\n", argv[0]);
return 1;
}
port = atoi(argv[1]);
while (1) {
// wake BT device
btwake_fd = open("/dev/btwake", 0);
bt_fd = connect_bt_device();
if (bt_fd < 0) {
printf("[!] Error connecting to bluetooth device\n");
return -1;
}
server_fd = create_server(port);
if (server_fd < 0) {
printf("[!] Unable to create proxy server\n");
return -1;
}
printf("[*] Created proxy server\n");
signal(SIGINT, __exit);
printf("[*] Waiting for remote connection\n");
client_fd = wait_for_connection(server_fd);
if (client_fd < 0)
printf("[!] Unable to connect remote device to proxy\n");
// currently only one connection is supported
proxy_bt_socket(client_fd, bt_fd);
close(client_fd);
close(server_fd);
close(bt_fd);
close(btwake_fd);
}
return 0;
}
+9
View File
@@ -0,0 +1,9 @@
Package: com.ttdennis.internalblued
Name: internalblued
Depends:
Version: 0.0.1
Architecture: iphoneos-arm
Description: InternalBlue iOS Proxy Daemon
Maintainer: Dennis Heinze
Author: Dennis Heinze
Section: System
+2
View File
@@ -0,0 +1,2 @@
#!/bin/sh
launchctl load /Library/LaunchDaemons/com.ttdennis.internalblued.plist
+2
View File
@@ -0,0 +1,2 @@
#!/bin/sh
launchctl unload /Library/LaunchDaemons/com.ttdennis.internalblued.plist 2>&1 > /dev/null
+2
View File
@@ -0,0 +1,2 @@
#!/bin/sh
launchctl unload /Library/LaunchDaemons/com.ttdennis.internalblued.plist
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.ttdennis.internalblued</string>
<key>MachServices</key>
<dict>
<key>com.ttdennis.internalblued</key>
<true/>
</dict>
<key>ProgramArguments</key>
<array>
<string>/usr/bin/internalblued</string>
</array>
<key>UserName</key>
<string>mobile</string>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
</dict>
</plist>
+179
View File
@@ -0,0 +1,179 @@
#include <xpc/xpc.h>
#include <pthread.h>
#include <spawn.h>
#include "ios-proxy.h"
#include "xpc_protocol.h"
#define PREF_FILE @"/var/mobile/Library/Preferences/com.ttdennis.internalblue-prefs.plist"
int manual_port = -1;
bool proxy_is_running = false;
pthread_t proxy_thread;
int get_proxy_port() {
int port = 0;
if (manual_port != -1) {
return manual_port;
}
NSMutableDictionary *prefs = [[NSMutableDictionary alloc] initWithContentsOfFile: PREF_FILE];
if (prefs) {
port = [[prefs objectForKey:@"port"] intValue];
} else {
NSLog(@"Preference file not found, chosing standard port 1234");
}
if (port == 0)
port = 1234;
return port;
}
bool proxy_pref_on() {
bool res = true;
NSMutableDictionary *prefs = [[NSMutableDictionary alloc] initWithContentsOfFile: PREF_FILE];
if (prefs) {
id obj = [prefs objectForKey:@"isEnabled"];
// no object exists, this means the user never toggled the switch
// which means the server is on (because it is by default), and we
// should stop -> return true
if (!obj) {
return true;
}
res = [obj boolValue];
} else {
NSLog(@"Preference file not found, chosing standard value true");
}
return res;
}
void *proxy_fn() {
int port = get_proxy_port();
int server_fd, client_fd, btwake_fd, bt_fd;
while (proxy_is_running) {
server_fd = create_server(port);
if (server_fd < 0) {
NSLog(@"Unable to create proxy server: %s", strerror(errno));
break;
}
NSLog(@"Created proxy server, waiting for connection");
client_fd = wait_for_connection(server_fd);
if (client_fd < 0) {
NSLog(@"Unable to establish connection: %s", strerror(errno));
close(server_fd);
}
// now that a client connection from internalblue is established
// we can claim the BT device
btwake_fd = open("/dev/btwake", O_RDONLY);
bt_fd = connect_bt_device();
if (bt_fd < 0) {
NSLog(@"Unable to connect to Bluetooth device: %s", strerror(errno));
close(server_fd);
close(client_fd);
close(btwake_fd);
}
// currently only one connection is supported
proxy_bt_socket(client_fd, bt_fd);
close(client_fd);
close(server_fd);
close(bt_fd);
close(btwake_fd);
}
return NULL;
}
void start_proxy() {
if (proxy_is_running) {
NSLog(@"Cannot start proxy, it is already running");
} else {
pthread_create(&proxy_thread, NULL, &proxy_fn, NULL);
proxy_is_running = true;
}
}
void stop_proxy() {
if (proxy_is_running) {
pthread_kill(proxy_thread, SIGKILL);
proxy_is_running = false;
} else {
NSLog(@"Cannot stop proxy, it is not running");
}
}
void _ib_xpc_recv_handler(xpc_object_t object) {
uint64_t opcode = xpc_dictionary_get_uint64(object, "message");
if ((void*)opcode == NULL) {
NSLog(@"Received invalid message.");
return;
}
NSLog(@"Got message with opcode %llu", opcode);
switch(opcode) {
case CMD_START_PROXY:
start_proxy();
break;
case CMD_STOP_PROXY:
stop_proxy();
break;
}
}
int main(int argc, char *argv[], char *envp[]) {
@autoreleasepool {
if (argc > 1) {
int port = atoi(argv[1]);
NSLog(@"Hi, looks like you manually started internalblued on port %d", port);
if (proxy_pref_on()) {
int _configured_port = get_proxy_port();
NSLog(@"internalblued is already running on port %d. Please turn it off in the iPhone's preferences first, before launching it manually.", _configured_port);
exit(-1);
}
manual_port = port;
start_proxy();
[[NSRunLoop currentRunLoop] run];
} else {
// Start the proxy if pref allows us to
if (proxy_pref_on()) {
NSLog(@"Starting proxy because it is enabled.");
start_proxy();
}
// Attempt to create the server, exit if this fails
xpc_connection_t connection = xpc_connection_create_mach_service("com.ttdennis.internalblued", NULL, XPC_CONNECTION_MACH_SERVICE_LISTENER);
if (!connection) {
NSLog(@"Failed to create XPC server. Exiting.");
return 0;
}
// Configure event handler
xpc_connection_set_event_handler(connection, ^(xpc_object_t object) {
xpc_type_t type = xpc_get_type(object);
if (type == XPC_TYPE_CONNECTION) {
NSLog(@"XPC server received incoming connection: %s", xpc_copy_description(object));
xpc_connection_set_event_handler(object, ^(xpc_object_t some_object) {
NSLog(@"XPC connection received object: %s", xpc_copy_description(some_object));
_ib_xpc_recv_handler(some_object);
});
xpc_connection_resume(object);
} else if (type == XPC_TYPE_ERROR) {
NSLog(@"XPC server error: %s", xpc_dictionary_get_string(object, XPC_ERROR_KEY_DESCRIPTION));
} else {
NSLog(@"XPC server received unknown object: %s", xpc_copy_description(object));
}
});
xpc_connection_resume(connection);
[[NSRunLoop currentRunLoop] run];
}
return 0;
}
}
+4
View File
@@ -0,0 +1,4 @@
#define CMD_RESTART_BLUETOOTHD 0
#define CMD_START_PROXY 1
#define CMD_STOP_PROXY 2
#define CMD_RESTART_PROXY 3
-38
View File
@@ -1,38 +0,0 @@
# internalblue-ios-proxy
This project is a proxy that redirects the *iOS* Bluetooth socket and exposes it as a
TCP socket which can be used to send HCI commands to the Bluetooth controller of the device.
A jailbroken device is required. To compile the project, a Mac with xcode is required.
The precompiled `ios-proxy` binary was tested on the iPhone 6 (12.1.2, 12.4), iPhone SE (12.4),
iPhone 7 (12.1.2, 12.4), and iPhone X (12.4).
## Building internalblue-ios-proxy
Open the project with xcode and compile it. Xcode will create a single binary that can then be transferred onto the device.
## Installing internalblue-ios-proxy
1. Right-click the `internalblue-ios-proxy` binary and click "Show in Finder". This will open the location the compiled binary resides in.
2. Move the binary onto the device (e.g. with scp) at a location where applications are allowed to be executed (e.g. `/bin` or `/sbin`).
3. The binary needs the `platform-application` entitlement. This is achieved by signing the binary with the included `entitlements.xml` file.
Sign it using `ldid -Sentitlements.xml internalblue-ios-proxy`. `ldid` should be on a jailbroken device with Cydia by default.
If `ldid` was not installed with your jailbreak, try opening [sileo://package/ldid](sileo://package/ldid).
## Running internalblue-ios-proxy
Run the proxy by executing `internalblue-ios-proxy <port-number>`.
The phone will then listen on this port and can be accessed either when on the same Wi-Fi or
by proxying the port through USB (using [usbmuxd](https://iphonedevwiki.net/index.php/SSH_Over_USB)).
When enabling a personal hotspot, you can also run `dhclient` on *Linux* on the new local ethernet interface.
A few things to note:
- To increase reliability of the proxy, *Bluetooth should be disabled*
(either by manually stopping the Bluetooth daemon or by shutting of Bluetooth in the
settings on the phone). Despite shutting down Bluetooth, the RAM will still have the same contents
as during previous usage, and you can analyze it.
- The current implementation sometimes returns wrong results, thus we double-check results of
commands that read ROM/RAM. We show warnings, but firmware dumps should complete nonetheless.
- To get sufficient performance, access the `ios-proxy` over USB and not using Wi-Fi.
- In case the Bluetooth chip crashes or does not respond anymore over the proxy,
the proxy should be stopped and Bluetooth should be turned off and on again in the UI.
- Sometimes the Bluetooth socket will not respond anymore after establishing a second connection,
just restart the proxy then.
This project is based on Brandon Azad's [iOS command line tool](https://github.com/bazad/ios-command-line-tool) template.
-8
View File
@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>platform-application</key>
<true/>
</dict>
</plist>
@@ -1,285 +0,0 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 50;
objects = {
/* Begin PBXBuildFile section */
BB958F25227BA4580029C2D6 /* internalblue-ios-proxy.c in Sources */ = {isa = PBXBuildFile; fileRef = BB958F24227BA4580029C2D6 /* internalblue-ios-proxy.c */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
551A88C4208E671F0048DFA0 /* internalblue-ios-proxy */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = "internalblue-ios-proxy"; sourceTree = BUILT_PRODUCTS_DIR; };
BB958F23227BA4580029C2D6 /* internalblue-ios-proxy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "internalblue-ios-proxy.h"; sourceTree = "<group>"; };
BB958F24227BA4580029C2D6 /* internalblue-ios-proxy.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "internalblue-ios-proxy.c"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
551A88C1208E671F0048DFA0 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
551A88BB208E671F0048DFA0 = {
isa = PBXGroup;
children = (
551A88C6208E671F0048DFA0 /* internalblue-ios-proxy */,
551A88C5208E671F0048DFA0 /* Products */,
);
sourceTree = "<group>";
};
551A88C5208E671F0048DFA0 /* Products */ = {
isa = PBXGroup;
children = (
551A88C4208E671F0048DFA0 /* internalblue-ios-proxy */,
);
name = Products;
sourceTree = "<group>";
};
551A88C6208E671F0048DFA0 /* internalblue-ios-proxy */ = {
isa = PBXGroup;
children = (
BB958F23227BA4580029C2D6 /* internalblue-ios-proxy.h */,
BB958F24227BA4580029C2D6 /* internalblue-ios-proxy.c */,
);
path = "internalblue-ios-proxy";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
551A88C3208E671F0048DFA0 /* internalblue-ios-proxy */ = {
isa = PBXNativeTarget;
buildConfigurationList = 551A88CD208E671F0048DFA0 /* Build configuration list for PBXNativeTarget "internalblue-ios-proxy" */;
buildPhases = (
551A88C0208E671F0048DFA0 /* Sources */,
551A88C1208E671F0048DFA0 /* Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = "internalblue-ios-proxy";
productName = "ios-command-line-tool";
productReference = 551A88C4208E671F0048DFA0 /* internalblue-ios-proxy */;
productType = "com.apple.product-type.library.dynamic";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
551A88BC208E671F0048DFA0 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0930;
ORGANIZATIONNAME = ttdennis;
TargetAttributes = {
551A88C3208E671F0048DFA0 = {
CreatedOnToolsVersion = 9.3;
};
};
};
buildConfigurationList = 551A88BF208E671F0048DFA0 /* Build configuration list for PBXProject "internalblue-ios-proxy" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = 551A88BB208E671F0048DFA0;
productRefGroup = 551A88C5208E671F0048DFA0 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
551A88C3208E671F0048DFA0 /* internalblue-ios-proxy */,
);
};
/* End PBXProject section */
/* Begin PBXSourcesBuildPhase section */
551A88C0208E671F0048DFA0 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
BB958F25227BA4580029C2D6 /* internalblue-ios-proxy.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
551A88CB208E671F0048DFA0 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
};
name = Debug;
};
551A88CC208E671F0048DFA0 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;
};
name = Release;
};
551A88CE208E671F0048DFA0 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = RSU3RMH9UZ;
DYLIB_COMPATIBILITY_VERSION = "";
DYLIB_CURRENT_VERSION = "";
EXECUTABLE_PREFIX = "";
EXECUTABLE_SUFFIX = "";
MACH_O_TYPE = mh_execute;
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
551A88CF208E671F0048DFA0 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = RSU3RMH9UZ;
DYLIB_COMPATIBILITY_VERSION = "";
DYLIB_CURRENT_VERSION = "";
EXECUTABLE_PREFIX = "";
EXECUTABLE_SUFFIX = "";
MACH_O_TYPE = mh_execute;
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
551A88BF208E671F0048DFA0 /* Build configuration list for PBXProject "internalblue-ios-proxy" */ = {
isa = XCConfigurationList;
buildConfigurations = (
551A88CB208E671F0048DFA0 /* Debug */,
551A88CC208E671F0048DFA0 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
551A88CD208E671F0048DFA0 /* Build configuration list for PBXNativeTarget "internalblue-ios-proxy" */ = {
isa = XCConfigurationList;
buildConfigurations = (
551A88CE208E671F0048DFA0 /* Debug */,
551A88CF208E671F0048DFA0 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 551A88BC208E671F0048DFA0 /* Project object */;
}
@@ -1,80 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1020"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "551A88C3208E671F0048DFA0"
BuildableName = "internalblue-ios-proxy"
BlueprintName = "internalblue-ios-proxy"
ReferencedContainer = "container:internalblue-ios-proxy.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "551A88C3208E671F0048DFA0"
BuildableName = "internalblue-ios-proxy"
BlueprintName = "internalblue-ios-proxy"
ReferencedContainer = "container:internalblue-ios-proxy.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "551A88C3208E671F0048DFA0"
BuildableName = "internalblue-ios-proxy"
BlueprintName = "internalblue-ios-proxy"
ReferencedContainer = "container:internalblue-ios-proxy.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
@@ -1,14 +0,0 @@
//
// internalblue-ios-proxy.h
// internalblue-ios-proxy
//
// Created by ttdennis on 03.05.19.
// Copyright © 2019 ttdennis. All rights reserved.
//
#ifndef internalblue_ios_proxy_h
#define internalblue_ios_proxy_h
#include <stdio.h>
#endif /* internalblue_ios_proxy_h */
Binary file not shown.
+4 -3
View File
@@ -4,11 +4,11 @@ from setuptools import setup
setup(
name="internalblue",
version="0.3",
version="0.4",
description="A Bluetooth Experimentation Framework based on the Broadcom Bluetooth Controller Family.",
url="http://github.com/seemoo-lab/internalblue",
author="Dennis Mantz",
author_email="dennis.mantz@googlemail.com",
author="The InternalBlue Team",
author_email="jiska@bluetooth.lol",
license="MIT",
packages=[
"internalblue",
@@ -16,6 +16,7 @@ setup(
"internalblue/objects",
"internalblue/utils",
],
python_requires='>=3.6',
install_requires=["pwntools>=4.0.1", "pyelftools", "future"],
extras_require={"macoscore": ["pyobjc"], "ipython": ["IPython"]},
tests_require=["nose", "pytest", "pwntools>=4.2.0.dev0"],