Example #1
0
def remove_exploit(img3):
    assert len(img3) > 0x24000
    assert img3[16:20] == 'illb'[::-1]

    obj = image3.Image3(img3)
    if obj.getDecryptedPayload()[:4] != '\x0e\x00\x00\xea':
        # This is a 24Kpwn implementation which changes DATA tag. First dword of DATA tag should look like a shellcode address.
        shellcode_address, = struct.unpack('<I', img3[64:68])
        assert img3[52:56] == 'DATA'[::-1]
        assert 0x84000000 <= shellcode_address and shellcode_address <= 0x84024000

        # Try to find the correct value for the first dword.
        found = False
        for pos in xrange(shellcode_address - 0x84000000, len(img3)):
            obj = image3.Image3(img3[:64] + img3[pos:pos + 4] + img3[68:])
            if obj.getDecryptedPayload()[:4] == '\x0e\x00\x00\xea':
                found = True
                break
        assert found

    obj.shrink24KpwnCertificate()

    img3 = obj.newImage3(decrypted=False)
    assert len(img3) <= 0x24000
    return img3
Example #2
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)
Example #3
0
def getKeybag(der, k):
    if der[:4] == "3gmI":
        if verbose: print("Reading IMG3 for " + k)
        kbag = image3.Image3(der).getKeybag()
        if kbag == None: return (None, None)
        ivenc = kbag[:16]
        keyenc = kbag[16:]
        keys = None
        if 'PWND:[checkm8]' in serial_number:
            pwned = usbexec.PwnedUSBDevice()
            keys = pwned.aes((ivenc + keyenc), usbexec.AES_DECRYPT,
                             usbexec.AES_GID_KEY).encode('hex')
        else:
            device = dfuexec.PwnedDFUDevice()
            keys = device.aes((ivenc + keyenc), dfuexec.AES_DECRYPT,
                              dfuexec.AES_GID_KEY).encode("hex")
        return (keys[:32], keys[32:])
    else:
        if verbose: print("Reading IMG4 for " + k)
        dec = asn1_node_next(
            der,
            asn1_node_next(
                der,
                asn1_node_next(der,
                               asn1_node_first_child(der,
                                                     asn1_node_root(der)))))
        if dec[2] >= len(der) - 4:
            return (None, None)
        if verbose: print("Reading kbag")
        kbag = asn1_get_value_of_type(der, asn1_node_next(der, dec),
                                      'OCTET STRING')
        if verbose: print("Extracting kbag")
        dec = asn1_node_next(
            kbag,
            asn1_node_first_child(
                kbag, asn1_node_first_child(kbag, asn1_node_root(kbag))))
        if verbose: print("Reading values from kbag")
        ivenc = asn1_get_value_of_type(kbag, dec, 'OCTET STRING')
        keyenc = asn1_get_value_of_type(kbag, asn1_node_next(kbag, dec),
                                        'OCTET STRING')
        keys = None

        if "SEP" in k:
            return ("KBAG", str(ivenc + keyenc).encode('hex'))
        else:
            if verbose: print("Decrypting key with device GID")
            if 'PWND:[checkm8]' in serial_number:
                pwned = usbexec.PwnedUSBDevice()
                keys = pwned.aes((ivenc + keyenc), usbexec.AES_DECRYPT,
                                 usbexec.AES_GID_KEY).encode('hex')
            else:
                device = dfuexec.PwnedDFUDevice()
                keys = device.aes_hex((ivenc + keyenc), dfuexec.AES_DECRYPT,
                                      dfuexec.AES_GID_KEY)
            return (keys[:32], keys[32:])
Example #4
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