rendered paste bodyimport sysfrom Struct import Structint16 = Struct.int16int32 = Struct.int32int64 = Struct.int64uint16 = Struct.uint16uint32 = Struct.uint32uint64 = Struct.uint64class NTFS(object): def __init__(self, fn): self.fp = file(fn, 'rb') start = self.readPartTable() self.readBPB(start) i = 0 while True: ret = self.checkFile(i) if ret == None: break elif ret == True: self.loadFile(i) break i += 1 def readSector(self, addr, count): self.fp.seek(addr * 512) return self.fp.read(count * 512) def readPartTable(self): parttable = self.readSector(0, 1) self.partStart = uint32(parttable[0x1C6:0x1CA]) print '%08x' % self.partStart return self.partStart def readBPB(self, start): bpb = self.readSector(start, 1) self.sectorsPerCluster = ord(bpb[0x0D]) self.sectorsPerMFTRecord = ord(bpb[0x40]) * self.sectorsPerCluster self.MFTBase = uint32(bpb[0x30:0x34]) + start print '%08x' % (self.MFTBase) def getMFTEntry(self, entry): entry = self.readSector( entry * self.sectorsPerMFTRecord + self.MFTBase, self.sectorsPerMFTRecord ) if entry[:4] != 'FILE': return None else: return entry def findAttrByType(self, entry, type): attrOff = uint16(entry[0x14:0x16]) while True: enttype = uint32(entry[attrOff:attrOff+4]) if enttype == 0xFFFFFFFF: return False elif enttype == type: return attrOff else: attrOff += uint16(entry[attrOff+4:attrOff+6]) def checkFile(self, entry): entry = self.getMFTEntry(entry) if entry == None: return None attr = self.findAttrByType(entry, 0x30) fnlen = ord(entry[attr+0x58]) fn = entry[attr+0x5A:attr+0x5A+(fnlen*2)].decode('utf-16') if fn == u'SSB.bin' and uint16(entry[attr+0x18:attr+0x1A]) == 5: return True else: return False def loadFile(self, entry): entry = self.getMFTEntry(entry) attr = self.findAttrByType(entry, 0x80) entry = entry[attr:] nonresident = ord(entry[0x8]) if nonresident: startVCN = uint16(entry[0x10:0x12]) lastVCN = uint16(entry[0x18:0x1A]) runlistOff = uint16(entry[0x20:0x22]) vcnLeft = lastVCN - startVCN prev = self.partStart while vcnLeft > 0: size = ord(entry[runlistOff]) offSize = (size >> 4) << 3 lenSize = size & 0x0F length = ord(entry[runlistOff+1]) runlistOff += 1+lenSize offLow = uint16(entry[runlistOff:runlistOff+2]) offHigh = uint16(entry[runlistOff+2:runlistOff+4]) offLow &= ~((0xFFFF << offSize) & 0xFFFF) offHigh &= ~((0xFFFF << (offSize - 16)) & 0xFFFF) offset = (offHigh << 16) | offLow runlistOff += offSize prev += offset * self.sectorsPerCluster #print self.readSector(prev, self.sectorsPerCluster*length) vcnLeft -= length else: start = attr+uint16(entry[0x14:0x16]) data = entry[start:start+uint32(entry[0x10:0x14])] print `data`if __name__=='__main__': NTFS(*sys.argv[1:])