def carveDeleteFiles_slow(self, catalogLBAs=None, filter_=None): self.fastMode = False self.files = {} if not self.ftlhax: self.ftlhax = self.nand.ftl.YAFTL_hax2() if not self.fileIds: self.getExistingFileIDs() if self.encrypted and len(self.keys) == 0: print "Carving attribute file for file keys" self.carveKeys() print "Carving catalog file" self.carveCatalog(catalogLBAs, filter_) self.okfiles = 0 total = 0 print "%d files" % len(self.files) for name, vv, usn in self.files.values(): keys = set(self.keys.get(vv.data.fileID, [self.emfkey])) print "%s num keys = %d" % (name, len(keys)) good_usn = 0 for filekey in keys: if good_usn: break first_block = vv.data.dataFork.HFSPlusExtentDescriptor[ 0].startBlock for usn, pn in self.pagesForLBN(first_block).items(): d = self.decryptFileBlock(pn[-1], filekey, self.first_lba + first_block, 0) if isDecryptedCorrectly(d): #print "USN for first block : ", usn good_usn = usn break if good_usn == 0: continue self.getFileAtUSN(name, vv.data, filekey, good_usn)
def carveDeleteFiles_slow(self, catalogLBAs=None, filter_=None): self.fastMode = False self.files = {} if not self.ftlhax: self.ftlhax = self.nand.ftl.YAFTL_hax2() if not self.fileIds: self.getExistingFileIDs() if self.encrypted and len(self.keys) == 0: print "Carving attribute file for file keys" self.carveKeys() print "Carving catalog file" self.carveCatalog(catalogLBAs, filter_) self.okfiles = 0 total = 0 print "%d files" % len(self.files) for name, vv, usn in self.files.values(): keys = set(self.keys.get(vv.data.fileID, [self.emfkey])) print "%s num keys = %d" % (name, len(keys)) good_usn = 0 for filekey in keys: if good_usn: break first_block = vv.data.dataFork.HFSPlusExtentDescriptor[0].startBlock for usn, pn in self.pagesForLBN(first_block).items(): d = self.decryptFileBlock(pn[-1], filekey, self.first_lba+first_block, 0) if isDecryptedCorrectly(d): #print "USN for first block : ", usn good_usn = usn break if good_usn == 0: continue self.getFileAtUSN(name, vv.data, filekey, good_usn)
def readFileHax(self, filename, filerecord, filekeys): lba0 = self.first_lba + filerecord.dataFork.HFSPlusExtentDescriptor[ 0].startBlock filekey = None good_usn = None first_vpn = 0 first_usn = 0 hax = self.ftlhax print "%d versions for first lba" % len(hax.get(lba0, [])) for k in filekeys: for vpn in hax.get(lba0, []): s, ciphertext = self.nand.ftl.YAFTL_readPage(vpn, key=None, lpn=None) if not ciphertext: continue d = self.decryptFileBlock2(ciphertext, k, lba0, 0) #hexdump(d[:16]) if isDecryptedCorrectly(d): filekey = k first_vpn = vpn first_usn = good_usn = s.usn block = vpn / self.nand.ftl.vfl.pages_per_sublk break if not filekey: return False logicalSize = filerecord.dataFork.logicalSize missing_pages = 0 file_pages = [] lbns = [] for extent in self.volume.getAllExtents(filerecord.dataFork, filerecord.fileID): for bn in xrange(extent.startBlock, extent.startBlock + extent.blockCount): lbns.append(self.first_lba + bn) datas = {} usnblocksToLookAT = sorted( filter(lambda x: x >= good_usn, self.userblocks.keys()))[:5] print usnblocksToLookAT usnblocksToLookAT.insert(0, 0) first_block = True done = False for usn in usnblocksToLookAT: if first_block: bbtoc = self.getBBTOC(block) first_block = False else: bbtoc = self.getBBTOC(self.userblocks[usn]) for lbn in bbtoc.keys(): if not lbn in lbns: continue idx = lbns.index(lbn) s, ciphertext = self.nand.ftl.YAFTL_readPage(bbtoc[lbn], key=None, lpn=None) if not ciphertext: continue ciphertext = self.decryptFileBlock2(ciphertext, filekey, lbn, idx * self.pageSize) if idx == 0: if not isDecryptedCorrectly(ciphertext): continue datas[idx * self.pageSize] = (ciphertext, lbn - self.first_lba) #if idx == len(lbns): if len(datas) == len(lbns): done = True break if done: break cleartext = "" decrypt_offset = 0 for i in xrange(0, logicalSize, self.pageSize): if datas.has_key(i): ciphertext, lbn = datas[i] cleartext += ciphertext else: cleartext += self.blankPage missing_pages += 1 decrypt_offset += self.pageSize print "Recovered %d:%s %d missing pages, size %s, created %s, contentModDate %s" % \ (filerecord.fileID, filename.encode("utf-8"), missing_pages, sizeof_fmt(logicalSize), hfs_date(filerecord.createDate), hfs_date(filerecord.contentModDate)) filename = "%d_%d_%s" % (filerecord.fileID, first_usn, filename) if missing_pages == 0: filename = "OK_" + filename self.okfiles += 1 if True: #exactSize: cleartext = cleartext[:logicalSize] self.writeUndeletedFile(filename, cleartext) return True
def readFileHax(self, filename, filerecord, filekeys): lba0 = self.first_lba + filerecord.dataFork.HFSPlusExtentDescriptor[0].startBlock filekey = None good_usn = None first_vpn = 0 first_usn = 0 hax = self.ftlhax print "%d versions for first lba" % len(hax.get(lba0, [])) for k in filekeys: for vpn in hax.get(lba0, []): s, ciphertext = self.nand.ftl.YAFTL_readPage(vpn, key=None, lpn=None) if not ciphertext: continue d = self.decryptFileBlock2(ciphertext, k, lba0, 0) #hexdump(d[:16]) if isDecryptedCorrectly(d): filekey = k first_vpn = vpn first_usn = good_usn = s.usn block = vpn / self.nand.ftl.vfl.pages_per_sublk break if not filekey: return False logicalSize = filerecord.dataFork.logicalSize missing_pages = 0 file_pages = [] lbns = [] for extent in self.volume.getAllExtents(filerecord.dataFork, filerecord.fileID): for bn in xrange(extent.startBlock, extent.startBlock + extent.blockCount): lbns.append(self.first_lba + bn) datas = {} usnblocksToLookAT = sorted(filter(lambda x: x >= good_usn, self.userblocks.keys()))[:5] print usnblocksToLookAT usnblocksToLookAT.insert(0, 0) first_block = True done = False for usn in usnblocksToLookAT: if first_block: bbtoc = self.getBBTOC(block) first_block = False else: bbtoc = self.getBBTOC(self.userblocks[usn]) for lbn in bbtoc.keys(): if not lbn in lbns: continue idx = lbns.index(lbn) s, ciphertext = self.nand.ftl.YAFTL_readPage(bbtoc[lbn], key=None, lpn=None) if not ciphertext: continue ciphertext = self.decryptFileBlock2(ciphertext, filekey, lbn, idx*self.pageSize) if idx == 0: if not isDecryptedCorrectly(ciphertext): continue datas[idx*self.pageSize] = (ciphertext, lbn - self.first_lba) #if idx == len(lbns): if len(datas) == len(lbns): done=True break if done: break cleartext = "" decrypt_offset = 0 for i in xrange(0,logicalSize, self.pageSize): if datas.has_key(i): ciphertext, lbn = datas[i] cleartext += ciphertext else: cleartext += self.blankPage missing_pages += 1 decrypt_offset += self.pageSize print "Recovered %d:%s %d missing pages, size %s, created %s, contentModDate %s" % \ (filerecord.fileID, filename.encode("utf-8"), missing_pages, sizeof_fmt(logicalSize), hfs_date(filerecord.createDate), hfs_date(filerecord.contentModDate)) filename = "%d_%d_%s" % (filerecord.fileID, first_usn, filename) if missing_pages == 0: filename = "OK_" + filename self.okfiles += 1 if True:#exactSize: cleartext = cleartext[:logicalSize] self.writeUndeletedFile(filename, cleartext) return True
def readFileHax(self, filename, filerecord, filekeys): lba0 = self.first_lba + filerecord.dataFork.HFSPlusExtentDescriptor[0].startBlock filekey = None good_usn = None first_usn = 0 lba0_versions = self.nand.ftl.findAllVersions(lba0) print "%d versions for first lba" % len(lba0_versions) for k in filekeys: for addr in lba0_versions: ciphertext = self.nand.ftl.readPage1(addr, key=None, lpn=lba0) if not ciphertext: continue d = self.decryptFileBlock2(ciphertext, k, lba0, 0) if isDecryptedCorrectly(d): hexdump(d[:16]) filekey = k weaveSeq = addr[0] break if not filekey: return False logicalSize = filerecord.dataFork.logicalSize missing_pages = 0 file_pages = [] lbns = [] for extent in self.volume.getAllExtents(filerecord.dataFork, filerecord.fileID): for bn in xrange(extent.startBlock, extent.startBlock + extent.blockCount): lbns.append(self.first_lba + bn) datas = {} first_block = True done = False for weaveSeq,lbn,ce,block,page in self.nand.ftl.findPagesInRange(weaveSeq, weaveSeq+50000): if not lbn in lbns: continue idx = lbns.index(lbn) ciphertext = self.nand.ftl.readPage1((weaveSeq,ce,block,page), key=None, lpn=lbn) if not ciphertext: continue ciphertext = self.decryptFileBlock2(ciphertext, filekey, lbn, idx*self.pageSize) if idx == 0: if not isDecryptedCorrectly(ciphertext): continue datas[idx*self.pageSize] = (ciphertext, lbn - self.first_lba) #if idx == len(lbns): if len(datas) == len(lbns): done=True break if done: break cleartext = "" decrypt_offset = 0 for i in xrange(0,logicalSize, self.pageSize): if datas.has_key(i): ciphertext, lbn = datas[i] cleartext += ciphertext else: cleartext += self.blankPage missing_pages += 1 decrypt_offset += self.pageSize print "Recovered %d:%s %d missing pages, size %s, created %s, contentModDate %s" % \ (filerecord.fileID, filename.encode("utf-8"), missing_pages, sizeof_fmt(logicalSize), hfs_date(filerecord.createDate), hfs_date(filerecord.contentModDate)) filename = "%d_%d_%s" % (filerecord.fileID, first_usn, filename) if missing_pages == 0: filename = "OK_" + filename self.okfiles += 1 if True:#exactSize: cleartext = cleartext[:logicalSize] self.writeUndeletedFile(filename, cleartext) return True