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
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 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:])
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