Created
October 25, 2015 09:01
-
-
Save marcan/ccbb0bf86bd001aeef92 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
import struct, sys | |
mfts = """ | |
c00004f0 | |
2067334f0 | |
114e7d24f0 | |
26496944f0 | |
26f39174f0 | |
27201fc4f0 | |
2765aff4f0 | |
2871fc04f0 | |
28d28d74f0 | |
2a24b4c4f0 | |
2af62574f0 | |
2b45a984f0 | |
2b7a6b04f0 | |
2bb164f4f0 | |
2bf290f4f0 | |
2c954c44f0 | |
2ca31fb0f0 | |
2ca337f0f0 | |
2d04b384f0 | |
2deb8bc4f0 | |
2f41ddc4f0 | |
2f741304f0 | |
3139d004f0 | |
31d42284f0 | |
3effcbc4f0 | |
40d5e574f0 | |
""" | |
def vint(a): | |
l = len(a) | |
v = 0 | |
for i in range(l): | |
v |= ord(a[i]) << (i*8) | |
if v & (1<<(8*l-1)): | |
v = v - (1<<(8*l)) | |
return v | |
def dump_runlist(rl, is_mft): | |
vcn = 0 | |
lcn = 0 | |
if is_mft: | |
print ">", "mft_0x%x.bin" % mft_off | |
fd = open("mft_0x%x.bin" % mft_off, "w") | |
print rl.encode("hex") | |
while rl: | |
hdr = ord(rl[0]) | |
lx = hdr & 15 | |
ox = hdr >> 4 | |
if lx == 0: | |
break | |
dl = vint(rl[1:1+lx]) | |
do = vint(rl[1+lx:1+lx+ox]) | |
rl = rl[lx+ox+1:] | |
lcn += do | |
if is_mft: | |
with open(sys.argv[1], "r") as sfd: | |
sfd.seek(lcn * cs) | |
fd.write(sfd.read(dl * cs)) | |
print " vcn=0x%x lcn=0x%x run=0x%x" % (vcn, lcn, dl) | |
#print " (0x%x, 0x%x, 0x%x)," % (vcn, lcn, dl) | |
vcn += dl | |
if is_mft: | |
fd.close() | |
def dump_standard_info(si): | |
cdate, mdate, rdate, adate = struct.unpack("<4Q", si[:32]) | |
print " date: %x" % cdate | |
def dump_name(nm): | |
nlen, ntype = struct.unpack("<BB", nm[0x40:0x42]) | |
print " %r" % nm[0x42:0x42+nlen*2].decode("utf-16le") | |
def dump_attr(attr, is_mft): | |
atype, alen, fc, nlen, noff, aflags, aid = struct.unpack( | |
"<IIBBHHH", attr[:0x10] | |
) | |
print " type 0x%x len 0x%x fc %d nlen %d noff 0x%x aflags 0x%x aid 0x%x" % ( | |
atype, alen, fc, nlen, noff, aflags, aid | |
) | |
if fc == 0: | |
clen, coff = struct.unpack("<IH", attr[0x10:0x16]) | |
if atype == 0x10: | |
dump_standard_info(attr[coff:coff+clen]) | |
elif atype == 0x30: | |
dump_name(attr[coff:coff+clen]) | |
else: | |
svcn, evcn, rloff, cunit, attrsz, dsksz, intsz = struct.unpack( | |
"<QQHH4xQQQ", attr[0x10:0x40] | |
) | |
runlist = attr[0x40:] | |
dump_runlist(runlist, is_mft and atype == 0x80) | |
def dump_entry(fr, is_mft=False): | |
if fr[:4] != "FILE": | |
print "Not an MFT entry" | |
return | |
seqoff, seqsz, seqno, hard, attr_off, flags, used, alloc, base, next_id, recno = struct.unpack( | |
"<4xHH8xHHHHIIQH2xI", fr[:0x30]) | |
print "seq %d hard %d attr 0x%x flags %04x used %d alloc %d base 0x%x next_id 0x%x recno %d" % ( | |
seqno, hard, attr_off, flags, used, alloc, base, next_id, recno | |
) | |
fixup = fr[seqoff:seqoff+seqsz*2] | |
fr = fr[:0x1fe] + fixup[2:4] + fr[0x200:0x3fe] + fixup[4:6] | |
attrs = fr[attr_off:] | |
while attrs: | |
if attrs[:4] == "\xff\xff\xff\xff": | |
break | |
atype, alen = struct.unpack("<II", attrs[:8]) | |
dump_attr(attrs[:alen], is_mft) | |
attrs = attrs[alen:] | |
fd = open(sys.argv[1], "r") | |
cs = 4096 | |
for mft_off in [int(i,16) for i in mfts.split()]: | |
mft_off -= 0x4f0 | |
fd.seek(mft_off) | |
entries = fd.read(cs) | |
print "MFT @ 0x%x" % mft_off | |
dump_entry(entries[:1024], is_mft=True) | |
dump_entry(entries[1024:2048]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment