using System; using System.IO; namespace app { public class NtfsApp { static void Main(String[] args) { String path = @"C:\$Volume"; // volume file FileStream vol = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); // // Read the file in 1KB at a time, looking for MFT records (beginning wth FILE) // int n = 0; byte[] b = new byte[1024]; while (vol.Read(b,0,b.Length) > 0) { n += b.Length; if (b[0] == 'F' && b[1] == 'I' && b[2] == 'L' && b[3] == 'E') { Console.WriteLine("\nBLOCK " + n.ToString("X4")); if (n > 0xffffff) return; ParseNTFSFileRecord(b); } } } static uint S(byte[] b, uint o) { return (uint)(b[o+1] << 8) + b[o]; } static uint I(byte[] b, uint o) { return (uint)(S(b,o+2) << 16) + S(b,o); } static String U(byte[] b, uint beg, uint end) { string s = ""; for (uint i = beg; i < end-1; i += 2) { string t; int v = (int) S(b, i); if (0x20 <= v && v < 127) { t = Char.ConvertFromUtf32( v ); } else { t = "?"; } s += t; } return s; } static String X(byte[] b, uint beg, uint end) { String s = ""; for (uint i = beg; i < end; i++) s += b[i].ToString("x2") + " "; return s; } static void ParseNTFSFileRecord(byte[] b) { uint attr = S(b, 0x14); uint rend = I(b, 0x18); uint delta; uint atype = 0; while (attr < rend) { atype = I(b, attr + 0); if (atype == 0xffffffff) return; ParseNTFSAttrRecord(b, attr); delta = I(b, attr + 4); attr += delta; } if (atype != 0xffffffff) { Console.WriteLine("WARNING: END not found at offset 0x" + attr.ToString("x4")); } } static void ParseNTFSAttrRecord(byte[] b, uint o) { uint typecode = I(b, o+0); Console.WriteLine("Type 0x" + typecode.ToString("x")); uint formcode = b[o+8]; if (formcode != 0) { Console.WriteLine("NONRESIDENT"); return; } uint namelen = b[o+9]; if (namelen > 0) { uint nameoffset = S(b, o+0xa); Console.WriteLine("AttrName: " + U(b, o+nameoffset, o+nameoffset+namelen)); } uint valuelen = I(b, o+0x10); uint valueoffset = S(b, o+0x14); if (typecode != 0x30) { //Console.WriteLine("Value: " + X(b, o+valueoffset, o+valueoffset+valuelen)); //Console.WriteLine("Value: " + U(b, o+valueoffset, o+valueoffset+valuelen)); } else { // for $FILE_NAME skip the other gunk in the attribute to reach the filename //Console.WriteLine("Value: " + X(b, o+valueoffset, o+valueoffset+valuelen)); Console.WriteLine("Value: " + U(b, o+valueoffset+0x42, o+valueoffset+valuelen)); } } } }