Type annotations, typing fixes and simple refactors
This commit is contained in:
+19
-11
@@ -1,27 +1,34 @@
|
||||
|
||||
from future import standard_library
|
||||
standard_library.install_aliases()
|
||||
|
||||
import datetime
|
||||
|
||||
from queue import Queue
|
||||
from typing import List, Optional, Any, TYPE_CHECKING, Tuple, Union, NewType, Callable, Dict
|
||||
|
||||
#Address = NewType("Address", int)
|
||||
Address = int
|
||||
ConnectionNumber = NewType("ConnectionNumber", int)
|
||||
ConnectionIndex = NewType("ConnectionIndex", int)
|
||||
|
||||
BluetoothAddress = NewType("BluetoothAddress", bytes)
|
||||
ConnectionDict = NewType("ConnectionDict", Dict[str, Any])
|
||||
HeapInformation = NewType("HeapInformation", Dict[str, Any])
|
||||
QueueInformation = NewType('QueueInformation', Dict[str, Any])
|
||||
|
||||
try:
|
||||
from queue import Queue
|
||||
from typing import List, Optional, Any, TYPE_CHECKING, Tuple, Union, NewType, Callable, Dict
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import datetime
|
||||
from internalblue.hci import HCI
|
||||
from internalblue.core import InternalBlue
|
||||
Address = NewType("Address", int)
|
||||
|
||||
Record = Tuple[HCI, int, int, int, Any, datetime.datetime]
|
||||
FilterFunction = Callable[[Record], bool]
|
||||
ConnectionNumber = NewType("ConnectionNumber", int)
|
||||
ConnectionIndex = NewType("ConnectionIndex", int)
|
||||
|
||||
BluetoothAddress = NewType("BluetoothAddress", bytes)
|
||||
ConnectionDict = NewType("ConnectionDict", Dict[str,Any])
|
||||
HeapInformation = NewType("HeapInformation", Dict[str, Any])
|
||||
QueueInformation = NewType('QueueInformation', Dict[str, Any])
|
||||
Opcode = NewType('Opcode', int)
|
||||
HCI_CMD = NewType('HCI_CMD', int)
|
||||
Task = Tuple[HCI_CMD, bytes, Queue.Queue, Callable[[Record], bool]]
|
||||
Task = Tuple[HCI_CMD, bytes, Queue, Callable[[Record], bool]]
|
||||
|
||||
Device = NewType("Device", Dict[str, Any])
|
||||
"""{"dev_id": dev_id,
|
||||
@@ -35,3 +42,4 @@ try:
|
||||
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
+33
-31
@@ -36,7 +36,8 @@ import pwnlib
|
||||
from pwnlib.asm import asm
|
||||
from pwnlib.exception import PwnlibException
|
||||
from pwnlib.util.fiddling import bits, unbits
|
||||
from .utils.pwnlib_wrapper import p16, p8, u32, u16, p32, u8
|
||||
from .utils.pwnlib_wrapper import p16, p8, u32, u16, p32, u8, log, context, flat
|
||||
from .fw import FirmwareDefinition
|
||||
|
||||
standard_library.install_aliases()
|
||||
from builtins import hex
|
||||
@@ -56,7 +57,6 @@ from .objects.connection_information import ConnectionInformation
|
||||
from future.utils import with_metaclass
|
||||
from internalblue.utils import bytes_to_hex
|
||||
|
||||
from internalblue.utils.pwnlib_wrapper import log, context, flat
|
||||
|
||||
try:
|
||||
from typing import List, Optional, Any, TYPE_CHECKING, Tuple, Union, NewType, Callable
|
||||
@@ -80,7 +80,7 @@ class InternalBlue(with_metaclass(ABCMeta, object)):
|
||||
context.arch = "thumb"
|
||||
|
||||
self.interface = None # holds the context.device / hci interaface which is used to connect, is set in cli
|
||||
self.fw = None # holds the firmware file
|
||||
self.fw: FirmwareDefinition = None # holds the firmware file
|
||||
|
||||
|
||||
self.data_directory = data_directory
|
||||
@@ -114,16 +114,16 @@ class InternalBlue(with_metaclass(ABCMeta, object)):
|
||||
# firmware (the response is recognized with the help of the filter function).
|
||||
# Once the response arrived, it puts the response into the response_queue from
|
||||
# the tuple. See sendH4() and sendHciCommand().
|
||||
self.sendQueue = queue2k.Queue(queue_size) # type: Queue.Queue[Task]
|
||||
self.sendQueue = queue2k.Queue(queue_size) # type: queue2k.Queue[Task]
|
||||
|
||||
self.recvThread = None # The thread which is responsible for the HCI snoop socket
|
||||
self.sendThread = None # The thread which is responsible for the HCI inject socket
|
||||
self.recvThread: Optional[pwnlib.context.Thread] = None # The thread which is responsible for the HCI snoop socket
|
||||
self.sendThread: Optional[pwnlib.context.Thread] = None # The thread which is responsible for the HCI inject socket
|
||||
|
||||
self.tracepoints = [] # A list of currently active tracepoints
|
||||
# The list contains tuples:
|
||||
# [0] target address
|
||||
# [1] address of the hook code
|
||||
self.tracepoint_registers = None # Last captured register values from a tracepoint
|
||||
self.tracepoint_registers: Optional[List[int]] = None # Last captured register values from a tracepoint
|
||||
self.tracepoint_memdump_parts = {} # Last captured RAM dump from a tracepoint
|
||||
self.tracepoint_memdump_address = None # Start address of the RAM dump
|
||||
|
||||
@@ -139,7 +139,7 @@ class InternalBlue(with_metaclass(ABCMeta, object)):
|
||||
# filter_function will be called for each packet that is received and only if it returns
|
||||
# True, the packet will be put into the queue. The filter_function can be None in order
|
||||
# to put all packets into the queue.
|
||||
self.registeredHciRecvQueues = [] # type: List[Tuple[Queue.Queue[Record], FilterFunction]]
|
||||
self.registeredHciRecvQueues = [] # type: List[Tuple[queue2k.Queue[Record], FilterFunction]]
|
||||
|
||||
self.exit_requested = False # Will be set to true when the framework wants to shut down (e.g. on error or user exit)
|
||||
self.running = False # 'running' is True once the connection to the HCI sockets is established
|
||||
@@ -343,16 +343,16 @@ class InternalBlue(with_metaclass(ABCMeta, object)):
|
||||
|
||||
if hcipkt.data[0:6] == "TRACE_": # My custom header (see hook code)
|
||||
data = hcipkt.data[6:]
|
||||
self.tracepoint_registers = [u32(data[i:i+4]) for i in range(0, 68, 4)]
|
||||
pc = self.tracepoint_registers[0]
|
||||
tracepoint_registers = [u32(data[i:i+4]) for i in range(0, 68, 4)]
|
||||
pc = tracepoint_registers[0]
|
||||
registers = "pc: 0x%08x lr: 0x%08x sp: 0x%08x cpsr: 0x%08x\n" % \
|
||||
(pc, self.tracepoint_registers[16], self.tracepoint_registers[1], self.tracepoint_registers[2])
|
||||
(pc, tracepoint_registers[16], tracepoint_registers[1], tracepoint_registers[2])
|
||||
registers += "r0: 0x%08x r1: 0x%08x r2: 0x%08x r3: 0x%08x r4: 0x%08x\n" % \
|
||||
tuple(self.tracepoint_registers[3:8])
|
||||
tuple(tracepoint_registers[3:8])
|
||||
registers += "r5: 0x%08x r6: 0x%08x r7: 0x%08x r8: 0x%08x r9: 0x%08x\n" % \
|
||||
tuple(self.tracepoint_registers[8:13])
|
||||
tuple(tracepoint_registers[8:13])
|
||||
registers += "r10: 0x%08x r11: 0x%08x r12: 0x%08x\n" % \
|
||||
tuple(self.tracepoint_registers[13:16])
|
||||
tuple(tracepoint_registers[13:16])
|
||||
log.info("Tracepoint 0x%x was hit and deactivated:\n" % pc + registers)
|
||||
|
||||
filename = self.data_directory + "/" + "internalblue_tracepoint_registers_%s.bin" % datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
|
||||
@@ -360,7 +360,7 @@ class InternalBlue(with_metaclass(ABCMeta, object)):
|
||||
f = open(filename, "w")
|
||||
f.write(registers)
|
||||
f.close()
|
||||
|
||||
self.tracepoint_registers = tracepoint_registers
|
||||
# remove tracepoint from self.tracepoints
|
||||
for tp in self.tracepoints:
|
||||
if tp[0] == pc:
|
||||
@@ -675,7 +675,7 @@ class InternalBlue(with_metaclass(ABCMeta, object)):
|
||||
log.warn("registerHciCallback: no such callback is registered!")
|
||||
|
||||
def registerHciRecvQueue(self, queue, filter_function=None):
|
||||
# type: (Queue.Queue[Record], FilterFunction) -> None
|
||||
# type: (queue2k.Queue[Record], FilterFunction) -> None
|
||||
"""
|
||||
Add a new queue to self.registeredHciRecvQueues.
|
||||
The queue will be filled by the recvThread every time the thread receives
|
||||
@@ -698,7 +698,7 @@ class InternalBlue(with_metaclass(ABCMeta, object)):
|
||||
self.registeredHciRecvQueues.append((queue, filter_function))
|
||||
|
||||
def unregisterHciRecvQueue(self, queue):
|
||||
# type: (Queue.Queue[Tuple[HCI, int, int, int, Any, datetime]]) -> None
|
||||
# type: (queue2k.Queue[Tuple[HCI, int, int, int, Any, datetime]]) -> None
|
||||
"""
|
||||
Remove a queue from self.registeredHciRecvQueues.
|
||||
"""
|
||||
@@ -806,7 +806,7 @@ class InternalBlue(with_metaclass(ABCMeta, object)):
|
||||
return None
|
||||
|
||||
def readMem(self, address, length, progress_log=None, bytes_done=0, bytes_total=0):
|
||||
# type: (int, int, Optional[Any], int, int) -> Optional[bytes]
|
||||
# type: (Address, int, Optional[Any], int, int) -> Optional[bytes]
|
||||
"""
|
||||
Reads <length> bytes from the memory space of the firmware at the given
|
||||
address. Reading from unmapped memory or certain memory-mapped-IO areas
|
||||
@@ -1103,7 +1103,7 @@ class InternalBlue(with_metaclass(ABCMeta, object)):
|
||||
return (table_addresses, table_values, slot_bits)
|
||||
|
||||
def patchRom(self, address, patch, slot=None):
|
||||
# type: (int, Any, Optional[Any]) -> bool
|
||||
# type: (Address, Any, Optional[Any]) -> bool
|
||||
"""
|
||||
Patch a 4-byte value (DWORD) inside the ROM section of the firmware
|
||||
(0x0 - 0x8FFFF) using the patchram mechanism. There are 128 available
|
||||
@@ -1262,11 +1262,11 @@ class InternalBlue(with_metaclass(ABCMeta, object)):
|
||||
return None
|
||||
|
||||
if is_array:
|
||||
connection = self.readMem(self.fw.CONNECTION_ARRAY_ADDRESS +
|
||||
self.fw.CONNECTION_STRUCT_LENGTH*(conn_number-1),
|
||||
connection = self.readMem(Address(self.fw.CONNECTION_ARRAY_ADDRESS +
|
||||
self.fw.CONNECTION_STRUCT_LENGTH*(conn_number-1)),
|
||||
self.fw.CONNECTION_STRUCT_LENGTH)
|
||||
else:
|
||||
connection_memaddr = u32(self.readMem(self.fw.CONNECTION_LIST_ADDRESS + 4*(conn_number-1), 4))
|
||||
connection_memaddr = Address(u32(self.readMem(Address(self.fw.CONNECTION_LIST_ADDRESS + 4*(conn_number-1)), 4)))
|
||||
if (connection_memaddr == 0x00000000):
|
||||
return None
|
||||
connection = self.readMem(connection_memaddr, self.fw.CONNECTION_STRUCT_LENGTH)
|
||||
@@ -1332,14 +1332,14 @@ class InternalBlue(with_metaclass(ABCMeta, object)):
|
||||
#log.info("packet: " + p16(conn_handle) + p8(len(data)) + data)
|
||||
result = self.sendHciCommand(0xfc58, p16(conn_handle) + p8(len(payload + opcode_data)) + data)
|
||||
|
||||
if result == None:
|
||||
if result is None:
|
||||
log.warn("sendLmpPacket: did not get a result from firmware, maybe crashed internally?")
|
||||
return False
|
||||
else:
|
||||
error_status = u8(result[3])
|
||||
|
||||
result = u8(result[3])
|
||||
|
||||
if result != 0:
|
||||
log.warn("sendLmpPacket: got error status 0x%02x" % result)
|
||||
if error_status != 0:
|
||||
log.warn("sendLmpPacket: got error status 0x%02x" % error_status)
|
||||
return False
|
||||
|
||||
return True
|
||||
@@ -1514,11 +1514,13 @@ class InternalBlue(with_metaclass(ABCMeta, object)):
|
||||
Create Connection
|
||||
"""
|
||||
|
||||
hcipkt = record[0] # get HCI Event packet
|
||||
_hcipkt = record[0]
|
||||
if not issubclass(_hcipkt.__class__, hci.HCI_Event):
|
||||
return
|
||||
hcipkt: hci.HCI_Event = _hcipkt # get HCI Event packet
|
||||
timestamp = record[5] # get timestamp
|
||||
|
||||
if not issubclass(hcipkt.__class__, hci.HCI_Event):
|
||||
return
|
||||
|
||||
|
||||
# Check if event is Connection Create Status Event
|
||||
if hcipkt.event_code == 0x0f:
|
||||
@@ -1592,7 +1594,7 @@ class InternalBlue(with_metaclass(ABCMeta, object)):
|
||||
return False
|
||||
|
||||
# Read address of first bloc struct:
|
||||
first_bloc_struct_address = u32(self.readMem(self.fw.BLOC_HEAD, 4))
|
||||
first_bloc_struct_address = Address(u32(self.readMem(self.fw.BLOC_HEAD, 4)))
|
||||
|
||||
# Traverse the double-linked list
|
||||
bloclist = []
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
from .fw import FirmwareDefinition
|
||||
+78
-15
@@ -25,10 +25,73 @@
|
||||
|
||||
from builtins import hex
|
||||
from builtins import object
|
||||
from types import ModuleType
|
||||
from typing import List
|
||||
|
||||
|
||||
from internalblue import Address
|
||||
from pwn import log
|
||||
|
||||
class MemorySection(object):
|
||||
"""
|
||||
All firmwares have memory sections that can be RAM, ROM or neither of both.
|
||||
"""
|
||||
def __init__(self, start_addr, end_addr, is_rom, is_ram):
|
||||
self.start_addr: Address = start_addr
|
||||
self.end_addr: Address= end_addr
|
||||
self.is_rom: bool = is_rom
|
||||
self.is_ram: bool = is_ram
|
||||
|
||||
def size(self) -> int:
|
||||
return self.end_addr - self.start_addr
|
||||
|
||||
class FirmwareDefinition:
|
||||
|
||||
SECTIONS: List[MemorySection]
|
||||
TRACEPOINT_BODY_ASM_SNIPPET: str
|
||||
TRACEPOINT_HOOKS_LOCATION: int
|
||||
TRACEPOINT_RAM_DUMP_PKT_COUNT = None
|
||||
|
||||
CONNECTION_STRUCT_LENGTH: int
|
||||
|
||||
FW_NAME: str
|
||||
|
||||
QUEUE_NAMES: List[str]
|
||||
QUEUE_HEAD: Address
|
||||
BLOC_HEAD: Address
|
||||
SENDLCP_CODE_BASE_ADDRESS: Address
|
||||
|
||||
SENDLCP_ASM_CODE: str
|
||||
|
||||
SENDLMP_CODE_BASE_ADDRESS: Address
|
||||
SENDLMP_ASM_CODE: str
|
||||
|
||||
FUZZLMP_HOOK_ADDRESS: Address
|
||||
FUZZLMP_CODE_BASE_ADDRESS: Address
|
||||
FUZZLMP_ASM_CODE: str
|
||||
|
||||
CONNECTION_LIST_ADDRESS: Address
|
||||
CONNECTION_ARRAY_ADDRESS: Address
|
||||
CONNECTION_MAX: int
|
||||
|
||||
PATCHRAM_VALUE_TABLE_ADDRESS: Address
|
||||
PATCHRAM_TARGET_TABLE_ADDRESS: Address
|
||||
PATCHRAM_ENABLED_BITMAP_ADDRESS: Address
|
||||
PATCHRAM_ALIGNED: bool
|
||||
PATCHRAM_NUMBER_OF_SLOTS: int
|
||||
|
||||
LAUNCH_RAM_PAUSE = None
|
||||
|
||||
READ_MEM_ALIGNED_ASM_LOCATION: Address
|
||||
READ_MEM_ALIGNED_ASM_SNIPPET: str
|
||||
|
||||
TRACEPOINT_HOOK_SIZE = None
|
||||
TRACEPOINT_BODY_ASM_LOCATION: Address
|
||||
TRACEPOINT_HOOK_ASM = None
|
||||
|
||||
|
||||
class Firmware(object):
|
||||
firmware: FirmwareDefinition
|
||||
def __init__(self, version=None, iOS=False):
|
||||
"""
|
||||
Load and initialize the actual firmware add-ons for Nexus 5, Raspi3, etc.
|
||||
@@ -37,7 +100,6 @@ class Firmware(object):
|
||||
"""
|
||||
|
||||
self.version = version
|
||||
self.firmware = None
|
||||
|
||||
if version:
|
||||
# get LMP Subversion
|
||||
@@ -47,30 +109,31 @@ class Firmware(object):
|
||||
try:
|
||||
# Fix for duplicate version number of evaluation board / iPhones
|
||||
if iOS and version==0x420e:
|
||||
self.firmware = __import__(__name__ + '_' + hex(version) + '_iphone', fromlist=[''])
|
||||
self.firmware = self._module_to_firmware_definition(__import__(__name__ + '_' + hex(version) + '_iphone', fromlist=['']))
|
||||
log.info("Using fw_" + hex(version) + "_iphone.py")
|
||||
else:
|
||||
self.firmware = __import__(__name__ + '_' + hex(version), fromlist=[''])
|
||||
self.firmware = self._module_to_firmware_definition(__import__(__name__ + '_' + hex(version), fromlist=['']))
|
||||
log.info("Using fw_" + hex(version) + ".py")
|
||||
except ImportError:
|
||||
self.firmware = None
|
||||
pass
|
||||
|
||||
if not version or not self.firmware:
|
||||
self.firmware = __import__(__name__ + '_default', fromlist=[''])
|
||||
self.firmware = self._module_to_firmware_definition(__import__(__name__ + '_default', fromlist=['']))
|
||||
|
||||
log.info("Loaded firmware information for " + self.firmware.FW_NAME + ".")
|
||||
|
||||
def _module_to_firmware_definition(self, fw: ModuleType) -> FirmwareDefinition:
|
||||
"""
|
||||
Wrap existing usages where the module was used and extract the new FirmwareDefinition class
|
||||
|
||||
class MemorySection(object):
|
||||
"""
|
||||
All firmwares have memory sections that can be RAM, ROM or neither of both.
|
||||
"""
|
||||
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
|
||||
:param fw:
|
||||
:return:
|
||||
"""
|
||||
_types = {name: cls for name, cls in fw.__dict__.items() if isinstance(cls, type)
|
||||
and issubclass(cls, FirmwareDefinition)
|
||||
and not cls is FirmwareDefinition}
|
||||
|
||||
if len(_types) == 1:
|
||||
return list(_types.values())[0]
|
||||
|
||||
def size(self):
|
||||
return self.end_addr - self.start_addr
|
||||
|
||||
@@ -20,27 +20,27 @@ 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 .fw import MemorySection, FirmwareDefinition
|
||||
|
||||
from .fw import MemorySection
|
||||
|
||||
# Firmware Infos
|
||||
# Evaluation Kit CYW20706
|
||||
FW_NAME = "CYW20706"
|
||||
class CYW20706(FirmwareDefinition):
|
||||
# Firmware Infos
|
||||
# Evaluation Kit CYW20706
|
||||
FW_NAME = "CYW20706"
|
||||
|
||||
|
||||
# Memory Sections
|
||||
# start, end, is_rom? is_ram?
|
||||
SECTIONS = [ MemorySection(0x00000000, 0x000c7fff, True, False), # Internal ROM
|
||||
MemorySection(0x000d0000, 0x000dffff, False, True ),
|
||||
MemorySection(0x00200000, 0x00247fff, False, True), # Internal Memory Cortex M3
|
||||
]
|
||||
# Memory Sections
|
||||
# start, end, is_rom? is_ram?
|
||||
SECTIONS = [ MemorySection(0x00000000, 0x000c7fff, True, False), # Internal ROM
|
||||
MemorySection(0x000d0000, 0x000dffff, False, True ),
|
||||
MemorySection(0x00200000, 0x00247fff, False, True), # Internal Memory Cortex M3
|
||||
]
|
||||
|
||||
# Patchram
|
||||
#PATCHRAM_TARGET_TABLE_ADDRESS = 0x310000
|
||||
#PATCHRAM_ENABLED_BITMAP_ADDRESS = 0x310404
|
||||
#PATCHRAM_VALUE_TABLE_ADDRESS = 0x0d0000
|
||||
#PATCHRAM_NUMBER_OF_SLOTS = 256
|
||||
PATCHRAM_ALIGNED = True
|
||||
# only seems to work 4-byte aligned here ...
|
||||
# Patchram
|
||||
#PATCHRAM_TARGET_TABLE_ADDRESS = 0x310000
|
||||
#PATCHRAM_ENABLED_BITMAP_ADDRESS = 0x310404
|
||||
#PATCHRAM_VALUE_TABLE_ADDRESS = 0x0d0000
|
||||
#PATCHRAM_NUMBER_OF_SLOTS = 256
|
||||
PATCHRAM_ALIGNED = True
|
||||
# only seems to work 4-byte aligned here ...
|
||||
|
||||
|
||||
|
||||
+187
-185
@@ -19,203 +19,205 @@
|
||||
# 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 .fw import MemorySection
|
||||
|
||||
# Firmware Infos
|
||||
# Evaluation Kit CYW920735
|
||||
FW_NAME = "CYW20735B1"
|
||||
|
||||
# Device Infos
|
||||
DEVICE_NAME = 0x280CD0 # rm_deviceLocalName, FIXME has no longer a length byte prepended
|
||||
BD_ADDR = 0x280CA4 # rm_deviceBDAddr
|
||||
|
||||
#Heap
|
||||
BLOC_HEAD = 0x200474 # g_dynamic_memory_GeneralUsePools
|
||||
BLOC_NG = True # Next Generation Bloc Buffer
|
||||
|
||||
# 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(0x00280000, 0x00283fff, False, True), # ToRam
|
||||
MemorySection(0x00300000, 0x00307fff, False, True), # HW Regs Cortex M3 (readable)
|
||||
MemorySection(0x00310000, 0x00321fff, False, True), # HW Regs Cortex M3 (readable)
|
||||
MemorySection(0x00326000, 0x0032ffff, False, True), # HW Regs Cortex M3 (readable)
|
||||
MemorySection(0x00338000, 0x00367fff, False, True), # HW Regs Cortex M3 (readable) + Pka Top
|
||||
MemorySection(0x00370000, 0x0037ffff, False, True), # RTX FIFO
|
||||
MemorySection(0x00390000, 0x00397fff, False, True), # Power WD
|
||||
#MemorySection(0x00404000, 0x00407fff, False, True), # EF Registers (seem to be sometimes unavailable)
|
||||
MemorySection(0x00410000, 0x00413fff, False, True), # BT Modem Registers
|
||||
MemorySection(0x00420000, 0x00423fff, False, True), # FM Modem Registers
|
||||
MemorySection(0x00430000, 0x00433fff, False, True), # MAC 15.4
|
||||
MemorySection(0x00440000, 0x00443fff, False, True), # SecEng Top
|
||||
MemorySection(0x00450000, 0x00453fff, False, True), # Capscan Top
|
||||
MemorySection(0x00500000, 0x006007ff, False, True), # EPM RAM (readable) + RF Regs
|
||||
MemorySection(0x00640000, 0x006407ff, False, True), # CLB Regs
|
||||
MemorySection(0x00650000, 0x006507ff, False, True), # GCI Regs
|
||||
MemorySection(0x20000000, 0x2024ffff, False, True), # SRAM
|
||||
MemorySection(0x20270000, 0x20283fff, False, True), # SRAM
|
||||
MemorySection(0x20500000, 0x200fffff, False, True), # SRAM
|
||||
MemorySection(0x22000000, 0x2226ffff, False, True), # SRAM Bits?
|
||||
|
||||
MemorySection(0x40000000, 0x40003fff, False, True), # ToRam Alias / Peripherals
|
||||
MemorySection(0x42000000, 0x4207ffff, False, True), # ToRam Bits
|
||||
#MemorySection(0x60000000, 0x60000000, False, True), # Extern BlueRF SRAM (range TBD)
|
||||
#MemorySection(0xa0000000, 0xa0000000, False, True), # Extern Device Address (range TBD)
|
||||
MemorySection(0xe0000000, 0xe0100000, False, True), # Base PPB Address
|
||||
]
|
||||
|
||||
# Patchram
|
||||
PATCHRAM_TARGET_TABLE_ADDRESS = 0x310000
|
||||
PATCHRAM_ENABLED_BITMAP_ADDRESS = 0x310404
|
||||
PATCHRAM_VALUE_TABLE_ADDRESS = 0x270000
|
||||
PATCHRAM_NUMBER_OF_SLOTS = 192
|
||||
PATCHRAM_ALIGNED = False
|
||||
# only seems to work 4-byte aligned here ...
|
||||
from .. import Address
|
||||
|
||||
|
||||
# Connection Struct and Table
|
||||
CONNECTION_LIST_ADDRESS = 0x216F98 # pRm_whole_conn = 0x280C9C points to this
|
||||
CONNECTION_MAX = 11 # g_bt_max_connections = 0 in firmware
|
||||
CONNECTION_STRUCT_LENGTH = 0x168 # ??
|
||||
class CYW20735B1(FirmwareDefinition):
|
||||
FW_NAME = "CYW20735B1"
|
||||
|
||||
# Snippet for fuzzLmp()
|
||||
FUZZLMP_HOOK_ADDRESS = 0xB08D8 # execute standard SendLmpPdu HCI to fill parameters
|
||||
FUZZLMP_CODE_BASE_ADDRESS = 0x271A00 # memory area of other WICED patches
|
||||
FUZZLMP_ASM_CODE = """
|
||||
// This hook is put into the end of bthci_cmd_vs_SendLmpPdu_B08AC,
|
||||
// so command parsing is still performed as normal. We jump in
|
||||
// before bthci_cmd_vs_SendLmpPdu pops and calls DHM_LMPTx.
|
||||
# Device Infos
|
||||
DEVICE_NAME = 0x280CD0 # rm_deviceLocalName, FIXME has no longer a length byte prepended
|
||||
BD_ADDR = 0x280CA4 # rm_deviceBDAddr
|
||||
|
||||
mov r0, r6 // 4 byte alignment
|
||||
# Heap
|
||||
BLOC_HEAD = Address(0x200474) # g_dynamic_memory_GeneralUsePools
|
||||
BLOC_NG = True # Next Generation Bloc Buffer
|
||||
|
||||
// put length argument into table_entry
|
||||
// payload[5] holds the size argument
|
||||
ldr r5, =table_entry
|
||||
add r5, #4 // length offset within table entry
|
||||
ldrb r6, [r4, #5] // size is in position r4+5
|
||||
strb r6, [r5]
|
||||
# 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(0x00280000, 0x00283fff, False, True), # ToRam
|
||||
MemorySection(0x00300000, 0x00307fff, False, True), # HW Regs Cortex M3 (readable)
|
||||
MemorySection(0x00310000, 0x00321fff, False, True), # HW Regs Cortex M3 (readable)
|
||||
MemorySection(0x00326000, 0x0032ffff, False, True), # HW Regs Cortex M3 (readable)
|
||||
MemorySection(0x00338000, 0x00367fff, False, True), # HW Regs Cortex M3 (readable) + Pka Top
|
||||
MemorySection(0x00370000, 0x0037ffff, False, True), # RTX FIFO
|
||||
MemorySection(0x00390000, 0x00397fff, False, True), # Power WD
|
||||
# MemorySection(0x00404000, 0x00407fff, False, True), # EF Registers (seem to be sometimes unavailable)
|
||||
MemorySection(0x00410000, 0x00413fff, False, True), # BT Modem Registers
|
||||
MemorySection(0x00420000, 0x00423fff, False, True), # FM Modem Registers
|
||||
MemorySection(0x00430000, 0x00433fff, False, True), # MAC 15.4
|
||||
MemorySection(0x00440000, 0x00443fff, False, True), # SecEng Top
|
||||
MemorySection(0x00450000, 0x00453fff, False, True), # Capscan Top
|
||||
MemorySection(0x00500000, 0x006007ff, False, True), # EPM RAM (readable) + RF Regs
|
||||
MemorySection(0x00640000, 0x006407ff, False, True), # CLB Regs
|
||||
MemorySection(0x00650000, 0x006507ff, False, True), # GCI Regs
|
||||
MemorySection(0x20000000, 0x2024ffff, False, True), # SRAM
|
||||
MemorySection(0x20270000, 0x20283fff, False, True), # SRAM
|
||||
MemorySection(0x20500000, 0x200fffff, False, True), # SRAM
|
||||
MemorySection(0x22000000, 0x2226ffff, False, True), # SRAM Bits?
|
||||
|
||||
// we need to do the original pop...
|
||||
pop {r4-r6, lr}
|
||||
MemorySection(0x40000000, 0x40003fff, False, True), # ToRam Alias / Peripherals
|
||||
MemorySection(0x42000000, 0x4207ffff, False, True), # ToRam Bits
|
||||
# MemorySection(0x60000000, 0x60000000, False, True), # Extern BlueRF SRAM (range TBD)
|
||||
# MemorySection(0xa0000000, 0xa0000000, False, True), # Extern Device Address (range TBD)
|
||||
MemorySection(0xe0000000, 0xe0100000, False, True), # Base PPB Address
|
||||
]
|
||||
|
||||
// now we simply continue like the original DHM_LMPTx_3453E function
|
||||
cmp r1, #0
|
||||
itt eq
|
||||
moveq r0, #4
|
||||
bxeq lr
|
||||
push {r4-r10, lr} // code at 0x34546
|
||||
mov r7, r0
|
||||
# Patchram
|
||||
PATCHRAM_TARGET_TABLE_ADDRESS = Address(0x310000)
|
||||
PATCHRAM_ENABLED_BITMAP_ADDRESS = 0x310404
|
||||
PATCHRAM_VALUE_TABLE_ADDRESS = 0x270000
|
||||
PATCHRAM_NUMBER_OF_SLOTS = 192
|
||||
PATCHRAM_ALIGNED = False
|
||||
# only seems to work 4-byte aligned here ...
|
||||
|
||||
// part of the check if hook_LMP_TxFilter is installed
|
||||
ldr r0, =0x203144 //dhmAvLinkAutoDetectEnable
|
||||
mov r4, r1
|
||||
ldr r2, [r0, #12]
|
||||
//cbz r2, loc_34564
|
||||
# Connection Struct and Table
|
||||
CONNECTION_LIST_ADDRESS = 0x216F98 # pRm_whole_conn = 0x280C9C points to this
|
||||
CONNECTION_MAX = 11 # g_bt_max_connections = 0 in firmware
|
||||
CONNECTION_STRUCT_LENGTH = 0x168 # ??
|
||||
|
||||
ldr.w r8, [r7] // code at 0x34564
|
||||
mov r0, r8
|
||||
bl 0x93E60 // rm_getDHMAclPtr
|
||||
movs r5, r0
|
||||
// skip check if we actually got a ptr
|
||||
// continue at 0x3457A
|
||||
ldrb r0, [r4, #12]
|
||||
tst.w r0, #0xfe // test for extended op ...
|
||||
add.w r0, r3, #0xc
|
||||
|
||||
# Snippet for fuzzLmp()
|
||||
FUZZLMP_HOOK_ADDRESS = 0xB08D8 # execute standard SendLmpPdu HCI to fill parameters
|
||||
FUZZLMP_CODE_BASE_ADDRESS = 0x271A00 # memory area of other WICED patches
|
||||
FUZZLMP_ASM_CODE = """
|
||||
// This hook is put into the end of bthci_cmd_vs_SendLmpPdu_B08AC,
|
||||
// so command parsing is still performed as normal. We jump in
|
||||
// before bthci_cmd_vs_SendLmpPdu pops and calls DHM_LMPTx.
|
||||
|
||||
mov r0, r6 // 4 byte alignment
|
||||
|
||||
// put length argument into table_entry
|
||||
// payload[5] holds the size argument
|
||||
ldr r5, =table_entry
|
||||
add r5, #4 // length offset within table entry
|
||||
ldrb r6, [r4, #5] // size is in position r4+5
|
||||
strb r6, [r5]
|
||||
|
||||
// we need to do the original pop...
|
||||
pop {r4-r6, lr}
|
||||
|
||||
// now we simply continue like the original DHM_LMPTx_3453E function
|
||||
cmp r1, #0
|
||||
itt eq
|
||||
moveq r0, #4
|
||||
bxeq lr
|
||||
push {r4-r10, lr} // code at 0x34546
|
||||
mov r7, r0
|
||||
|
||||
// part of the check if hook_LMP_TxFilter is installed
|
||||
ldr r0, =0x203144 //dhmAvLinkAutoDetectEnable
|
||||
mov r4, r1
|
||||
ldr r2, [r0, #12]
|
||||
//cbz r2, loc_34564
|
||||
|
||||
ldr.w r8, [r7] // code at 0x34564
|
||||
mov r0, r8
|
||||
bl 0x93E60 // rm_getDHMAclPtr
|
||||
movs r5, r0
|
||||
// skip check if we actually got a ptr
|
||||
// continue at 0x3457A
|
||||
ldrb r0, [r4, #12]
|
||||
tst.w r0, #0xfe // test for extended op ...
|
||||
add.w r0, r3, #0xc
|
||||
|
||||
|
||||
// now we regularily would call the opcode conversion table function
|
||||
// however, we do not use lm_getLmpInfoType_86A82 but insert our own table here
|
||||
ldr r1, =table_entry // table_ptr with exactly one entry, so no offsets included here
|
||||
ldr r0, =table_entry
|
||||
|
||||
// branch back to DHM_LMPTx position after bl lm_getLmpInfoType
|
||||
b 0x3458A
|
||||
|
||||
.align
|
||||
table_entry:
|
||||
.byte 0x40 //lm_LmpUnsupportedPdu
|
||||
.byte 0x6A
|
||||
.byte 0x08
|
||||
.byte 0x00
|
||||
.byte 0x20 //length, will be overwritten by us anyways, but can not be longer than one buffer (0x20)
|
||||
.byte 0x00
|
||||
.byte 0x00
|
||||
.byte 0x00
|
||||
"""
|
||||
|
||||
// now we regularily would call the opcode conversion table function
|
||||
// however, we do not use lm_getLmpInfoType_86A82 but insert our own table here
|
||||
ldr r1, =table_entry // table_ptr with exactly one entry, so no offsets included here
|
||||
ldr r0, =table_entry
|
||||
# Assembler snippet for tracepoints
|
||||
# In contrast to the Nexus 5 patch, we uninstall ourselves automatically and use internal debug functions
|
||||
TRACEPOINT_BODY_ASM_LOCATION = 0x00218500
|
||||
TRACEPOINT_HOOKS_LOCATION = 0x00218700
|
||||
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 r0, %d // addTracepoint() injects the patchram slot of the hook patch
|
||||
bl 0x28794 // patch_uninstallPatchEntry(slot)
|
||||
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
|
||||
"""
|
||||
|
||||
// branch back to DHM_LMPTx position after bl lm_getLmpInfoType
|
||||
b 0x3458A
|
||||
|
||||
.align
|
||||
table_entry:
|
||||
.byte 0x40 //lm_LmpUnsupportedPdu
|
||||
.byte 0x6A
|
||||
.byte 0x08
|
||||
.byte 0x00
|
||||
.byte 0x20 //length, will be overwritten by us anyways, but can not be longer than one buffer (0x20)
|
||||
.byte 0x00
|
||||
.byte 0x00
|
||||
.byte 0x00
|
||||
"""
|
||||
|
||||
|
||||
# Assembler snippet for tracepoints
|
||||
# In contrast to the Nexus 5 patch, we uninstall ourselves automatically and use internal debug functions
|
||||
TRACEPOINT_BODY_ASM_LOCATION = 0x00218500
|
||||
TRACEPOINT_HOOKS_LOCATION = 0x00218700
|
||||
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 r0, %d // addTracepoint() injects the patchram slot of the hook patch
|
||||
bl 0x28794 // patch_uninstallPatchEntry(slot)
|
||||
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
|
||||
"""
|
||||
|
||||
TRACEPOINT_BODY_ASM_SNIPPET = """
|
||||
mov r8, lr // save link register in r8
|
||||
|
||||
// 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 0x2DEF4 // hci_allocateEventBlockWithLen(0xff, 78)
|
||||
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 0xEAB4 // memcpy(dst, src, len)
|
||||
|
||||
// send HCI buffer to the host
|
||||
mov r0, r4 // r4 still points to the beginning of the HCI buffer
|
||||
bl 0x2DEC0 // hci_sendEvent
|
||||
|
||||
// restore status register
|
||||
msr cpsr_f, r5
|
||||
|
||||
bl 0x26C7A // bthci_event_vs_DBFW_CoreDumpRAMImageEvent
|
||||
|
||||
mov lr, r8 // restore lr from r8
|
||||
bx lr // return
|
||||
|
||||
"""
|
||||
TRACEPOINT_BODY_ASM_SNIPPET = """
|
||||
mov r8, lr // save link register in r8
|
||||
|
||||
// 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 0x2DEF4 // hci_allocateEventBlockWithLen(0xff, 78)
|
||||
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 0xEAB4 // memcpy(dst, src, len)
|
||||
|
||||
// send HCI buffer to the host
|
||||
mov r0, r4 // r4 still points to the beginning of the HCI buffer
|
||||
bl 0x2DEC0 // hci_sendEvent
|
||||
|
||||
// restore status register
|
||||
msr cpsr_f, r5
|
||||
|
||||
bl 0x26C7A // bthci_event_vs_DBFW_CoreDumpRAMImageEvent
|
||||
|
||||
mov lr, r8 // restore lr from r8
|
||||
bx lr // return
|
||||
|
||||
"""
|
||||
|
||||
+101
-98
@@ -19,110 +19,113 @@
|
||||
# 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 .fw import MemorySection
|
||||
|
||||
# Firmware Infos
|
||||
# Evaluation Kit CYW920719
|
||||
FW_NAME = "CYW20739B1 (NOT iPhone X/XR!)"
|
||||
# TODO this is not the iPhone firmware, we need to add a switch in fw.py
|
||||
|
||||
# Device Infos
|
||||
DEVICE_NAME = 0x280CD0 # rm_deviceLocalName, FIXME has no longer a length byte prepended
|
||||
BD_ADDR = 0x280CA4 # rm_deviceBDAddr
|
||||
|
||||
#Heap
|
||||
BLOC_HEAD = 0x0200c7c # g_dynamic_memory_GeneralUsePools
|
||||
BLOC_NG = True # Next Generation Bloc Buffer
|
||||
|
||||
# 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(0x00280000, 0x00283fff, False, True), # ToRam
|
||||
]
|
||||
|
||||
# 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 ...
|
||||
from .. import Address
|
||||
|
||||
|
||||
# Assembler snippet for tracepoints
|
||||
# In contrast to the Nexus 5 patch, we uninstall ourselves automatically and use internal debug functions
|
||||
TRACEPOINT_BODY_ASM_LOCATION = 0x00223100
|
||||
TRACEPOINT_HOOKS_LOCATION = 0x00223200
|
||||
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 r0, %d // addTracepoint() injects the patchram slot of the hook patch
|
||||
bl 0x34964 // patch_uninstallPatchEntry(slot)
|
||||
bl 0x%x // addTracepoint() injects TRACEPOINT_BODY_ASM_LOCATION here
|
||||
pop {r0-r12, lr} // restore registers
|
||||
class CYW20739B1(FirmwareDefinition):
|
||||
# Firmware Infos
|
||||
# Evaluation Kit CYW920719
|
||||
FW_NAME = "CYW20739B1 (NOT iPhone X/XR!)"
|
||||
# TODO this is not the iPhone firmware, we need to add a switch in fw.py
|
||||
|
||||
// branch back to the original instruction
|
||||
b 0x%x // addTracepoint() injects the address of the tracepoint
|
||||
"""
|
||||
# Device Infos
|
||||
DEVICE_NAME = 0x280CD0 # rm_deviceLocalName, FIXME has no longer a length byte prepended
|
||||
BD_ADDR = 0x280CA4 # rm_deviceBDAddr
|
||||
|
||||
TRACEPOINT_BODY_ASM_SNIPPET = """
|
||||
mov r8, lr // save link register in r8
|
||||
#Heap
|
||||
BLOC_HEAD = Address(0x0200c7c) # g_dynamic_memory_GeneralUsePools
|
||||
BLOC_NG = True # Next Generation Bloc Buffer
|
||||
|
||||
// dump registers like before
|
||||
# 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(0x00280000, 0x00283fff, False, True), # ToRam
|
||||
]
|
||||
|
||||
// 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 0xF7B6 // hci_allocateEventBlockWithLen(0xff, 78)
|
||||
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 0xAF0BC // memcpy(dst, src, len)
|
||||
|
||||
// send HCI buffer to the host
|
||||
mov r0, r4 // r4 still points to the beginning of the HCI buffer
|
||||
bl 0xF782 // hci_sendEvent
|
||||
|
||||
// restore status register
|
||||
msr cpsr_f, r5
|
||||
|
||||
bl 0x2D702 // bthci_event_vs_DBFW_CoreDumpRAMImageEvent
|
||||
|
||||
mov lr, r8 // restore lr from r8
|
||||
bx lr // return
|
||||
|
||||
"""
|
||||
# Patchram
|
||||
PATCHRAM_TARGET_TABLE_ADDRESS = Address(0x310000)
|
||||
PATCHRAM_ENABLED_BITMAP_ADDRESS = Address(0x310404)
|
||||
PATCHRAM_VALUE_TABLE_ADDRESS = Address(0x270000)
|
||||
PATCHRAM_NUMBER_OF_SLOTS = 256
|
||||
PATCHRAM_ALIGNED = False
|
||||
# only seems to work 4-byte aligned here ...
|
||||
|
||||
|
||||
# Assembler snippet for tracepoints
|
||||
# In contrast to the Nexus 5 patch, we uninstall ourselves automatically and use internal debug functions
|
||||
TRACEPOINT_BODY_ASM_LOCATION = 0x00223100
|
||||
TRACEPOINT_HOOKS_LOCATION = 0x00223200
|
||||
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 r0, %d // addTracepoint() injects the patchram slot of the hook patch
|
||||
bl 0x34964 // patch_uninstallPatchEntry(slot)
|
||||
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
|
||||
"""
|
||||
|
||||
TRACEPOINT_BODY_ASM_SNIPPET = """
|
||||
mov r8, lr // save link register in r8
|
||||
|
||||
// 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 0xF7B6 // hci_allocateEventBlockWithLen(0xff, 78)
|
||||
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 0xAF0BC // memcpy(dst, src, len)
|
||||
|
||||
// send HCI buffer to the host
|
||||
mov r0, r4 // r4 still points to the beginning of the HCI buffer
|
||||
bl 0xF782 // hci_sendEvent
|
||||
|
||||
// restore status register
|
||||
msr cpsr_f, r5
|
||||
|
||||
bl 0x2D702 // bthci_event_vs_DBFW_CoreDumpRAMImageEvent
|
||||
|
||||
mov lr, r8 // restore lr from r8
|
||||
bx lr // return
|
||||
|
||||
"""
|
||||
|
||||
|
||||
|
||||
+340
-340
@@ -24,363 +24,363 @@
|
||||
# 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 .fw import MemorySection
|
||||
class BCM4335C0(FirmwareDefinition):
|
||||
# Firmware Infos
|
||||
# This runs on Nexus 5, Xperia Z3, Samsung Galaxy Note 3
|
||||
FW_NAME = "BCM4335C0"
|
||||
|
||||
# Firmware Infos
|
||||
# This runs on Nexus 5, Xperia Z3, Samsung Galaxy Note 3
|
||||
FW_NAME = "BCM4335C0"
|
||||
|
||||
# Device Infos
|
||||
DEVICE_NAME = 0x2178B4 # [type: 1byte] [len: 1byte] [name: len byte]
|
||||
BD_ADDR = 0x210C2C
|
||||
# Device Infos
|
||||
DEVICE_NAME = 0x2178B4 # [type: 1byte] [len: 1byte] [name: len byte]
|
||||
BD_ADDR = 0x210C2C
|
||||
|
||||
|
||||
# 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)
|
||||
]
|
||||
# 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)
|
||||
]
|
||||
|
||||
# BLOC struct head which points to the first bloc struct (double-linked list)
|
||||
BLOC_HEAD = 0x203094
|
||||
# BLOC struct head which points to the first bloc struct (double-linked list)
|
||||
BLOC_HEAD = 0x203094
|
||||
|
||||
# QUEU struct head which points to the first queue struct (double-linked list)
|
||||
QUEUE_HEAD = 0x20307C
|
||||
QUEUE_NAMES = ["tran_HCIEvent", "tran_ACLData", "tran_SCOData", "tran_UartBridgeNonHCIEvent", "tran_DiagData",
|
||||
"tran_HIDUsbKBEvt", "tran_HIDUsbMSEvt", "tran_HIDUsbMSCtrl", "tran_HIDUsbKBCtrl", "tran_HidAuxData",
|
||||
"lm_Cmd", "hci_HciCommand", "lm_deferredAction", "lrmmsm_cmd", "liteHostEvent", "litehostRcvdL2capData"
|
||||
]
|
||||
# QUEU struct head which points to the first queue struct (double-linked list)
|
||||
QUEUE_HEAD = 0x20307C
|
||||
QUEUE_NAMES = ["tran_HCIEvent", "tran_ACLData", "tran_SCOData", "tran_UartBridgeNonHCIEvent", "tran_DiagData",
|
||||
"tran_HIDUsbKBEvt", "tran_HIDUsbMSEvt", "tran_HIDUsbMSCtrl", "tran_HIDUsbKBCtrl", "tran_HidAuxData",
|
||||
"lm_Cmd", "hci_HciCommand", "lm_deferredAction", "lrmmsm_cmd", "liteHostEvent", "litehostRcvdL2capData"
|
||||
]
|
||||
|
||||
|
||||
# Connection Structure and Table
|
||||
CONNECTION_ARRAY_ADDRESS = 0x002038E8
|
||||
CONNECTION_MAX = 11
|
||||
CONNECTION_STRUCT_LENGTH = 0x14C
|
||||
# Connection Structure and Table
|
||||
CONNECTION_ARRAY_ADDRESS = 0x002038E8
|
||||
CONNECTION_MAX = 11
|
||||
CONNECTION_STRUCT_LENGTH = 0x14C
|
||||
|
||||
|
||||
# Patchram
|
||||
PATCHRAM_ENABLED_BITMAP_ADDRESS = 0x310204
|
||||
PATCHRAM_TARGET_TABLE_ADDRESS = 0x310000
|
||||
PATCHRAM_VALUE_TABLE_ADDRESS = 0xd0000
|
||||
PATCHRAM_NUMBER_OF_SLOTS = 128
|
||||
PATCHRAM_ALIGNED = True #use readMemAligned, not accessible via ReadRAM HCI command on Nexus 5
|
||||
# Patchram
|
||||
PATCHRAM_ENABLED_BITMAP_ADDRESS = 0x310204
|
||||
PATCHRAM_TARGET_TABLE_ADDRESS = 0x310000
|
||||
PATCHRAM_VALUE_TABLE_ADDRESS = 0xd0000
|
||||
PATCHRAM_NUMBER_OF_SLOTS = 128
|
||||
PATCHRAM_ALIGNED = True #use readMemAligned, not accessible via ReadRAM HCI command on Nexus 5
|
||||
|
||||
|
||||
# Snippet for sendLcpPacket()
|
||||
SENDLCP_CODE_BASE_ADDRESS = 0x00211900
|
||||
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 0x66760 // lmulp_sendLcp
|
||||
|
||||
pop {r4,pc} // go back
|
||||
# Snippet for sendLcpPacket()
|
||||
SENDLCP_CODE_BASE_ADDRESS = 0x00211900
|
||||
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 0x66760 // 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
|
||||
"""
|
||||
|
||||
.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 sendLmpPacketLegacy()
|
||||
SENDLMP_CODE_BASE_ADDRESS = 0xd7500
|
||||
SENDLMP_ASM_CODE = """
|
||||
push {r4,lr}
|
||||
|
||||
// malloc buffer for LMP packet
|
||||
bl 0x3F17E // 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 0x2e03c // memcpy
|
||||
|
||||
// load conn struct pointer (needed for determine if we are master or slave)
|
||||
mov r0, %d // connection number is injected by sendLmpPacket()
|
||||
bl 0x42c04 // find connection struct from conn nr (r0 will hold pointer to conn struct)
|
||||
|
||||
// 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
|
||||
and r1, 0x1 // isolate the bit to get the correct value for the TID bit
|
||||
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 0xf81a // 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
|
||||
"""
|
||||
|
||||
|
||||
# Snippet for fuzzLmp()
|
||||
FUZZLMP_HOOK_ADDRESS = 0x1e48c # execute standard SendLmpPdu HCI to fill parameters
|
||||
FUZZLMP_CODE_BASE_ADDRESS = 0xd7500
|
||||
FUZZLMP_ASM_CODE = """
|
||||
// This hook is put into the end of bthci_cmd_vs_SendLmpPdu_1E45A,
|
||||
// so command parsing is still performed as normal. We jump in
|
||||
// before bthci_cmd_vs_SendLmpPdu pops and calls DHM_LMPTx.
|
||||
|
||||
// put length argument into table_entry
|
||||
// payload[5] holds the size argument
|
||||
ldr r7, =table_entry
|
||||
add r7, #4 // length offset within table entry
|
||||
ldrb r6, [r4, #5]
|
||||
strb r6, [r7]
|
||||
|
||||
// we need to do the original pop...
|
||||
pop {r4-r8, lr}
|
||||
|
||||
// now we simply continue like the original DHM_LMPTx function
|
||||
push {r4-r10, lr} // code at 0xF81A
|
||||
mov r8, r0
|
||||
movs r4, r1
|
||||
|
||||
// part of the check if hook_LMP_TxFilter_200D38 is installed
|
||||
ldr.w r9, =0x200D80
|
||||
sub.w r9, r9, #0x50
|
||||
ldr.w r2, [r9, #8]
|
||||
|
||||
mov r1, r4 // code at 0xF840
|
||||
mov r0, r8
|
||||
bl 0x50050 // rm_getDHMAclPtr_50050
|
||||
cmp r0, #1
|
||||
// skip check if we actually got a ptr
|
||||
// get connection struct, code at 0xF850
|
||||
ldr r0, =0x206eac // table_for_bt_tx_structs_206EAC
|
||||
ldr.w r7, [r8]
|
||||
add.w r6, r0, r7, lsl #5
|
||||
ldrb r0, [r6, #0x1f]
|
||||
cmp r0, #1
|
||||
// skip check in conection struct
|
||||
ldrb r0, [r4, #0xc] // ptr_to_opcode = buffer_cpy + 12;
|
||||
lsrs r1, r0, #1 // buffer_cpy[12] >> 1
|
||||
add.w r0, r4, #0x0c
|
||||
|
||||
// enable for debugging: ignore the remaining code and continue like normal opcode
|
||||
//b 0xF870
|
||||
|
||||
// now we regularily would call the opcode conversion table function
|
||||
// however, we do not use lm_getLmpInfoType_3F2D8 but insert our own table here
|
||||
ldr r1, =table_entry // table_ptr with exactly one entry, so no offsets included here
|
||||
ldr r0, =table_entry
|
||||
|
||||
// branch back to DHM_LMPTx position after bl lm_getLmpInfoType
|
||||
b 0xF874
|
||||
|
||||
.align
|
||||
table_entry:
|
||||
.byte 0x35 //nullsub1+1
|
||||
.byte 0xAC
|
||||
.byte 0x00
|
||||
.byte 0x00
|
||||
.byte 0x20 //length, will be overwritten by us anyways, but can not be longer than one buffer (0x20)
|
||||
.byte 0x00
|
||||
.byte 0x00
|
||||
.byte 0x00
|
||||
"""
|
||||
|
||||
|
||||
# Assembler snippet for the readMemAligned() function
|
||||
READ_MEM_ALIGNED_ASM_LOCATION = 0xd7900
|
||||
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 0x7AFC // 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, 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 0x398c1 // send_hci_event_without_free()
|
||||
|
||||
// free HCI buffer
|
||||
mov r0, r4
|
||||
bl 0x3FA36 // free_bloc_buffer_aligned
|
||||
|
||||
pop {r4, pc} // return
|
||||
"""
|
||||
|
||||
# Snippet for sendLmpPacketLegacy()
|
||||
SENDLMP_CODE_BASE_ADDRESS = 0xd7500
|
||||
SENDLMP_ASM_CODE = """
|
||||
push {r4,lr}
|
||||
|
||||
// malloc buffer for LMP packet
|
||||
bl 0x3F17E // 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 0x2e03c // memcpy
|
||||
|
||||
// load conn struct pointer (needed for determine if we are master or slave)
|
||||
mov r0, %d // connection number is injected by sendLmpPacket()
|
||||
bl 0x42c04 // find connection struct from conn nr (r0 will hold pointer to conn struct)
|
||||
|
||||
// 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
|
||||
and r1, 0x1 // isolate the bit to get the correct value for the TID bit
|
||||
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 0xf81a // 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
|
||||
"""
|
||||
|
||||
|
||||
# Snippet for fuzzLmp()
|
||||
FUZZLMP_HOOK_ADDRESS = 0x1e48c # execute standard SendLmpPdu HCI to fill parameters
|
||||
FUZZLMP_CODE_BASE_ADDRESS = 0xd7500
|
||||
FUZZLMP_ASM_CODE = """
|
||||
// This hook is put into the end of bthci_cmd_vs_SendLmpPdu_1E45A,
|
||||
// so command parsing is still performed as normal. We jump in
|
||||
// before bthci_cmd_vs_SendLmpPdu pops and calls DHM_LMPTx.
|
||||
|
||||
// put length argument into table_entry
|
||||
// payload[5] holds the size argument
|
||||
ldr r7, =table_entry
|
||||
add r7, #4 // length offset within table entry
|
||||
ldrb r6, [r4, #5]
|
||||
strb r6, [r7]
|
||||
|
||||
// we need to do the original pop...
|
||||
pop {r4-r8, lr}
|
||||
|
||||
// now we simply continue like the original DHM_LMPTx function
|
||||
push {r4-r10, lr} // code at 0xF81A
|
||||
mov r8, r0
|
||||
movs r4, r1
|
||||
|
||||
// part of the check if hook_LMP_TxFilter_200D38 is installed
|
||||
ldr.w r9, =0x200D80
|
||||
sub.w r9, r9, #0x50
|
||||
ldr.w r2, [r9, #8]
|
||||
|
||||
mov r1, r4 // code at 0xF840
|
||||
mov r0, r8
|
||||
bl 0x50050 // rm_getDHMAclPtr_50050
|
||||
cmp r0, #1
|
||||
// skip check if we actually got a ptr
|
||||
// get connection struct, code at 0xF850
|
||||
ldr r0, =0x206eac // table_for_bt_tx_structs_206EAC
|
||||
ldr.w r7, [r8]
|
||||
add.w r6, r0, r7, lsl #5
|
||||
ldrb r0, [r6, #0x1f]
|
||||
cmp r0, #1
|
||||
// skip check in conection struct
|
||||
ldrb r0, [r4, #0xc] // ptr_to_opcode = buffer_cpy + 12;
|
||||
lsrs r1, r0, #1 // buffer_cpy[12] >> 1
|
||||
add.w r0, r4, #0x0c
|
||||
|
||||
// enable for debugging: ignore the remaining code and continue like normal opcode
|
||||
//b 0xF870
|
||||
|
||||
// now we regularily would call the opcode conversion table function
|
||||
// however, we do not use lm_getLmpInfoType_3F2D8 but insert our own table here
|
||||
ldr r1, =table_entry // table_ptr with exactly one entry, so no offsets included here
|
||||
ldr r0, =table_entry
|
||||
|
||||
// branch back to DHM_LMPTx position after bl lm_getLmpInfoType
|
||||
b 0xF874
|
||||
|
||||
.align
|
||||
table_entry:
|
||||
.byte 0x35 //nullsub1+1
|
||||
.byte 0xAC
|
||||
.byte 0x00
|
||||
.byte 0x00
|
||||
.byte 0x20 //length, will be overwritten by us anyways, but can not be longer than one buffer (0x20)
|
||||
.byte 0x00
|
||||
.byte 0x00
|
||||
.byte 0x00
|
||||
"""
|
||||
|
||||
|
||||
# Assembler snippet for the readMemAligned() function
|
||||
READ_MEM_ALIGNED_ASM_LOCATION = 0xd7900
|
||||
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 0x7AFC // 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, 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 0x398c1 // send_hci_event_without_free()
|
||||
|
||||
// free HCI buffer
|
||||
mov r0, r4
|
||||
bl 0x3FA36 // free_bloc_buffer_aligned
|
||||
|
||||
pop {r4, pc} // return
|
||||
# Assembler snippet for tracepoints
|
||||
TRACEPOINT_BODY_ASM_LOCATION = 0xd7a00
|
||||
TRACEPOINT_HOOKS_LOCATION = 0xd7b00
|
||||
TRACEPOINT_HOOK_SIZE = 28
|
||||
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 r7, %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
|
||||
"""
|
||||
|
||||
# Assembler snippet for tracepoints
|
||||
TRACEPOINT_BODY_ASM_LOCATION = 0xd7a00
|
||||
TRACEPOINT_HOOKS_LOCATION = 0xd7b00
|
||||
TRACEPOINT_HOOK_SIZE = 28
|
||||
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 r7, %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
|
||||
"""
|
||||
TRACEPOINT_RAM_DUMP_PKT_COUNT = 670 # <ramsize> / <packetsize> where packetsize is 244
|
||||
TRACEPOINT_BODY_ASM_SNIPPET = """
|
||||
mov r8, lr // save link register in r8
|
||||
|
||||
// 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 0x7AFC // 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 '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 0x2e03c+1 // memcpy(dst, src, len)
|
||||
|
||||
// send HCI buffer to the host
|
||||
mov r0, r4 // r4 still points to the beginning of the HCI buffer
|
||||
bl 0x398c1 // send_hci_event_without_free()
|
||||
|
||||
// free HCI buffer
|
||||
mov r0, r4
|
||||
bl 0x3FA36 // free_bloc_buffer_aligned
|
||||
|
||||
mov r0, r7 // r7 still contains the patchram slot number
|
||||
bl 0x311AA // disable_patchram_slot(slot)
|
||||
|
||||
// restore status register
|
||||
msr cpsr_f, r5
|
||||
|
||||
// dump ram
|
||||
bl dump_ram
|
||||
|
||||
mov lr, r8 // restore lr from r8
|
||||
bx lr // return
|
||||
|
||||
|
||||
// function to dump the RAM as multiple HCI packets:
|
||||
dump_ram:
|
||||
push {r4-r6,lr}
|
||||
|
||||
// malloc HCI event buffer
|
||||
mov r0, 0xff // event code is 0xff (vendor specific HCI Event)
|
||||
mov r1, 252 // buffer size
|
||||
bl 0x7AFC // 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 'RAM___') after the event code and event length field
|
||||
add r0, 2 // write after the length field
|
||||
ldr r1, =0x5f4d4152 // 'RAM_'
|
||||
str r1, [r0]
|
||||
add r0, 4 // advance the pointer.
|
||||
ldr r1, =0x5f5f // '__'
|
||||
strh r1, [r0]
|
||||
add r0, 2 // advance the pointer. r0 now points to the start of the actual payload
|
||||
|
||||
mov r5, 0x200000 // start of ram
|
||||
ldr r6, =%d // number of ramdump packets to be sent
|
||||
|
||||
dump_ram_loop:
|
||||
// Set r0 to point to the beginning of the payload in the hci buffer
|
||||
mov r0, r4
|
||||
add r0, 8
|
||||
|
||||
// store current address
|
||||
str r5, [r0] // r5 contains the address in RAM which is send next
|
||||
TRACEPOINT_RAM_DUMP_PKT_COUNT = 670 # <ramsize> / <packetsize> where packetsize is 244
|
||||
TRACEPOINT_BODY_ASM_SNIPPET = """
|
||||
mov r8, lr // save link register in r8
|
||||
|
||||
// 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 0x7AFC // 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 '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.
|
||||
|
||||
// copy ram to hci buffer
|
||||
mov r1, r5
|
||||
mov r2, 244
|
||||
bl 0x2e03c // memcpy
|
||||
|
||||
|
||||
// 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 0x2e03c+1 // memcpy(dst, src, len)
|
||||
|
||||
// send HCI buffer to the host
|
||||
mov r0, r4 // r4 still points to the beginning of the HCI buffer
|
||||
bl 0x398c1 // send_hci_event_without_free()
|
||||
|
||||
// delay loop; Workaround: without the delay, a lot of packets are not actually sent
|
||||
// through HCI.
|
||||
mov r0, 0x1000
|
||||
delay_loop:
|
||||
subs r0, 1
|
||||
bne delay_loop
|
||||
|
||||
// increment the RAM pointer; decrement the counter
|
||||
add r5, 244
|
||||
subs r6, 1
|
||||
|
||||
bne dump_ram_loop
|
||||
|
||||
// free HCI buffer
|
||||
mov r0, r4
|
||||
bl 0x3FA36 // free_bloc_buffer_aligned
|
||||
|
||||
pop {r4-r6,pc}
|
||||
""" % TRACEPOINT_RAM_DUMP_PKT_COUNT
|
||||
|
||||
// free HCI buffer
|
||||
mov r0, r4
|
||||
bl 0x3FA36 // free_bloc_buffer_aligned
|
||||
|
||||
mov r0, r7 // r7 still contains the patchram slot number
|
||||
bl 0x311AA // disable_patchram_slot(slot)
|
||||
|
||||
// restore status register
|
||||
msr cpsr_f, r5
|
||||
|
||||
// dump ram
|
||||
bl dump_ram
|
||||
|
||||
mov lr, r8 // restore lr from r8
|
||||
bx lr // return
|
||||
|
||||
|
||||
// function to dump the RAM as multiple HCI packets:
|
||||
dump_ram:
|
||||
push {r4-r6,lr}
|
||||
|
||||
// malloc HCI event buffer
|
||||
mov r0, 0xff // event code is 0xff (vendor specific HCI Event)
|
||||
mov r1, 252 // buffer size
|
||||
bl 0x7AFC // 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 'RAM___') after the event code and event length field
|
||||
add r0, 2 // write after the length field
|
||||
ldr r1, =0x5f4d4152 // 'RAM_'
|
||||
str r1, [r0]
|
||||
add r0, 4 // advance the pointer.
|
||||
ldr r1, =0x5f5f // '__'
|
||||
strh r1, [r0]
|
||||
add r0, 2 // advance the pointer. r0 now points to the start of the actual payload
|
||||
|
||||
mov r5, 0x200000 // start of ram
|
||||
ldr r6, =%d // number of ramdump packets to be sent
|
||||
|
||||
dump_ram_loop:
|
||||
// Set r0 to point to the beginning of the payload in the hci buffer
|
||||
mov r0, r4
|
||||
add r0, 8
|
||||
|
||||
// store current address
|
||||
str r5, [r0] // r5 contains the address in RAM which is send next
|
||||
add r0, 4 // advance the pointer.
|
||||
|
||||
// copy ram to hci buffer
|
||||
mov r1, r5
|
||||
mov r2, 244
|
||||
bl 0x2e03c // memcpy
|
||||
|
||||
// send HCI buffer to the host
|
||||
mov r0, r4 // r4 still points to the beginning of the HCI buffer
|
||||
bl 0x398c1 // send_hci_event_without_free()
|
||||
|
||||
// delay loop; Workaround: without the delay, a lot of packets are not actually sent
|
||||
// through HCI.
|
||||
mov r0, 0x1000
|
||||
delay_loop:
|
||||
subs r0, 1
|
||||
bne delay_loop
|
||||
|
||||
// increment the RAM pointer; decrement the counter
|
||||
add r5, 244
|
||||
subs r6, 1
|
||||
|
||||
bne dump_ram_loop
|
||||
|
||||
// free HCI buffer
|
||||
mov r0, r4
|
||||
bl 0x3FA36 // free_bloc_buffer_aligned
|
||||
|
||||
pop {r4-r6,pc}
|
||||
""" % TRACEPOINT_RAM_DUMP_PKT_COUNT
|
||||
|
||||
@@ -21,15 +21,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 .fw import MemorySection, FirmwareDefinition
|
||||
|
||||
from .fw import MemorySection
|
||||
class DefaultFirmware(FirmwareDefinition):
|
||||
# Firmware Infos
|
||||
FW_NAME = "default (unknown firmware)"
|
||||
|
||||
# Firmware Infos
|
||||
FW_NAME = "default (unknown firmware)"
|
||||
|
||||
# Memory Sections
|
||||
# start, end, is_rom? is_ram?
|
||||
SECTIONS = [ MemorySection(0x0, 0x90000, True , False),
|
||||
MemorySection(0xd0000, 0xd8000, False, True ),
|
||||
MemorySection(0x200000, 0x228000, False, True )
|
||||
# Memory Sections
|
||||
# start, end, is_rom? is_ram?
|
||||
SECTIONS = [ MemorySection(0x0, 0x90000, True , False),
|
||||
MemorySection(0xd0000, 0xd8000, False, True ),
|
||||
MemorySection(0x200000, 0x228000, False, True )
|
||||
]
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ from pwnlib.util.packing import flat
|
||||
HCI_UART_TYPE_CLASS = {}
|
||||
|
||||
class HCI(object):
|
||||
|
||||
data: bytes
|
||||
"""
|
||||
HCI Packet types for UART Transport layer
|
||||
Core specification 4.1 [vol 4] Part A (Section 2) - Protocol
|
||||
|
||||
@@ -30,7 +30,7 @@ class macOSCore(InternalBlue):
|
||||
self.iobe = None
|
||||
self.serial = None
|
||||
if not replay:
|
||||
import objc
|
||||
import objc # type: ignore
|
||||
objc.initFrameworkWrapper("IOBluetoothExtended",
|
||||
frameworkIdentifier="de.tu-darmstadt.seemoo.IOBluetoothExtended",
|
||||
frameworkPath=objc.pathForFramework(
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
from builtins import object
|
||||
from internalblue.utils.pwnlib_wrapper import u32, u16, u8
|
||||
from typing import Any
|
||||
|
||||
|
||||
|
||||
class ConnectionInformation(object):
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
from builtins import object
|
||||
from typing import Any
|
||||
|
||||
|
||||
class QueueElement(object):
|
||||
index = 0
|
||||
next_item = 0
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
|
||||
[mypy-internalblue]
|
||||
|
||||
python_version = 3.8
|
||||
warn_return_any = True
|
||||
|
||||
|
||||
[mypy-internalblue.fw.*]
|
||||
|
||||
ignore_errors = True
|
||||
|
||||
[mypy-internalblue.socket_hooks]
|
||||
ignore_errors = True
|
||||
|
||||
[mypy-pwnlib.*]
|
||||
ignore_missing_imports = True
|
||||
|
||||
[mypy-future.*]
|
||||
ignore_missing_imports = True
|
||||
|
||||
[mypy-past.*]
|
||||
ignore_missing_imports = True
|
||||
|
||||
[mypy-IPython]
|
||||
ignore_missing_imports = True
|
||||
Reference in New Issue
Block a user