Ejemplo n.º 1
0
 def do_ls(self, p):
     dirDict = self.volume.ls((self.curdir + "/" + p).replace("//","/")) 
     if not dirDict:
         return
     for name in sorted(dirDict.keys()):
         size = ""
         protection_class = ""
         record = dirDict[name]
         if hasattr(record, "fileID"):
             size = sizeof_fmt(record.dataFork.logicalSize)
             cprotect = self.volume.getXattr(record.fileID, "com.apple.system.cprotect")
             if cprotect:
                 protection_class = PROTECTION_CLASSES[struct.unpack("<L", cprotect[8:12])[0]]
         print "%s\t%s\t%s\t%s" % (name[:30].ljust(30), size.ljust(10), hfs_date(record.createDate), protection_class)
Ejemplo n.º 2
0
 def _catalogFileCallback(self, data, usn, filter_):
     for k, v in carveBtreeNode(data, HFSPlusCatalogKey,
                                HFSPlusCatalogData):
         if v.recordType != kHFSPlusFileRecord:
             continue
         if filter_ and not filter_(k, v):
             continue
         name = getString(k)
         #if not self.filterFileName(name):
         #    continue
         h = hashlib.sha1(HFSPlusCatalogKey.build(k)).digest()
         if self.files.has_key(h):
             continue
         if not self.fileIds.has_key(v.data.fileID):
             print "Found deleted file record", v.data.fileID, name.encode(
                 "utf-8"), "created", hfs_date(v.data.createDate)
             self.files[h] = (name, v, usn)
Ejemplo n.º 3
0
    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
Ejemplo n.º 4
0
    def getFileAtUSN(self,
                     filename,
                     filerecord,
                     filekey,
                     usn,
                     previousVersion=None,
                     exactSize=True):
        missing_pages = 0
        decrypt_offset = 0
        file_pages = []
        logicalSize = filerecord.dataFork.logicalSize
        for extent in self.volume.getAllExtents(filerecord.dataFork,
                                                filerecord.fileID):
            for bn in xrange(extent.startBlock,
                             extent.startBlock + extent.blockCount):
                pn = self.pagesForLBN(bn).get(usn)  #fail
                if pn:
                    clear = self.decryptFileBlock(pn[-1], filekey, bn,
                                                  decrypt_offset)
                    file_pages.append(clear)
                elif previousVersion:
                    file_pages.append(previousVersion[len(file_pages)])
                else:
                    file_pages.append(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, usn, filename)
        if missing_pages == 0:
            filename = "OK_" + filename
            self.okfiles += 1
        data = "".join(file_pages)
        if exactSize:
            data = data[:logicalSize]
        self.writeUndeletedFile(filename, data)
        return file_pages
Ejemplo n.º 5
0
 def _catalogFileCallback(self, data, usn, filter_):
     for k,v in carveBtreeNode(data,HFSPlusCatalogKey, HFSPlusCatalogData):
         if v.recordType != kHFSPlusFileRecord:
             continue
         if filter_ and not filter_(k,v):
             continue
         name = getString(k)
         #if not self.filterFileName(name):
         #    continue
         h = hashlib.sha1(HFSPlusCatalogKey.build(k)).digest()
         if self.files.has_key(h):
             continue
         if not self.fileIds.has_key(v.data.fileID):
             print "Found deleted file record", v.data.fileID, name.encode("utf-8"), "created", hfs_date(v.data.createDate)
             self.files[h] = (name,v, usn)               
Ejemplo n.º 6
0
    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
Ejemplo n.º 7
0
    def getFileAtUSN(self, filename, filerecord, filekey, usn, previousVersion=None, exactSize=True):
        missing_pages = 0
        decrypt_offset = 0
        file_pages = []
        logicalSize = filerecord.dataFork.logicalSize
        for extent in self.volume.getAllExtents(filerecord.dataFork, filerecord.fileID):
            for bn in xrange(extent.startBlock, extent.startBlock + extent.blockCount):
                pn = self.pagesForLBN(bn).get(usn) #fail
                if pn:
                    clear = self.decryptFileBlock(pn[-1], filekey, bn, decrypt_offset)
                    file_pages.append(clear)
                elif previousVersion:
                    file_pages.append(previousVersion[len(file_pages)])
                else:
                    file_pages.append(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, usn, filename)
        if missing_pages == 0:
            filename = "OK_" + filename
            self.okfiles += 1
        data = "".join(file_pages)
        if exactSize:
            data = data[:logicalSize]
        self.writeUndeletedFile(filename, data)
        return file_pages
    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