Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 48461fbd17 | |||
| a3d418a262 | |||
| a435466c01 | |||
| 5863b11104 | |||
| 8e93878e08 | |||
| a210025dc5 | |||
| f9c38dfd49 | |||
| aa127b7148 | |||
| 5792bca5b8 | |||
| 4df388c37a | |||
| 733cd9ca56 | |||
| a8a6623658 | |||
| b599213104 | |||
| df5636b9b8 | |||
| 25fa80a416 | |||
| fd7310330b | |||
| 65a8ce61e6 | |||
| 67ec7f5347 | |||
| 8dce7f86a4 |
@@ -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:
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,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
|
||||
|
||||
|
||||
|
||||
@@ -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 = """
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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 = """
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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,4 +1,4 @@
|
||||
#!/usr/bin/env python2
|
||||
#!/usr/bin/env python
|
||||
|
||||
# fw.py
|
||||
#
|
||||
|
||||
+129
-128
@@ -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
|
||||
|
||||
"""
|
||||
|
||||
@@ -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
|
||||
"""
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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 ...
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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()
|
||||
|
||||
"""
|
||||
|
||||
@@ -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
|
||||
"""
|
||||
|
||||
@@ -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,4 +1,4 @@
|
||||
#!/usr/bin/env python2
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# fw_0x220e.py
|
||||
#
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
"""
|
||||
|
||||
@@ -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 ...
|
||||
|
||||
@@ -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 ...
|
||||
|
||||
@@ -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
@@ -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
@@ -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.."
|
||||
)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
.theos
|
||||
.DS_STORE
|
||||
@@ -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)
|
||||
@@ -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>
|
||||
@@ -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 */
|
||||
+24
-92
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
Executable
+2
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
launchctl load /Library/LaunchDaemons/com.ttdennis.internalblued.plist
|
||||
Executable
+2
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
launchctl unload /Library/LaunchDaemons/com.ttdennis.internalblued.plist 2>&1 > /dev/null
|
||||
Executable
+2
@@ -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>
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,4 @@
|
||||
#define CMD_RESTART_BLUETOOTHD 0
|
||||
#define CMD_START_PROXY 1
|
||||
#define CMD_STOP_PROXY 2
|
||||
#define CMD_RESTART_PROXY 3
|
||||
@@ -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.
|
||||
@@ -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 */;
|
||||
}
|
||||
-80
@@ -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,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"],
|
||||
|
||||
Reference in New Issue
Block a user