-
Notifications
You must be signed in to change notification settings - Fork 20
NTFSParser is running into an assertion failure #1
Comments
I know there are some issues with the first parse of the mft. For example, if your mft is fragmented just rigt, the program will continue reading past one of the chunks and get garbage data. I haven't had the time to make a separate ntfs parser just for the initial run of the mfts file record. (At the time we parse that, we have nothing to build the parsers I already have). Sent from my iPhone
|
I see... It's quite hard to find any information about "MFT fragmentation" at all. I could reproduce the error from a very small USB thumb drive (256MB) formatted with different cluster sizes in windows 10. With that thumb drive of 256MB (NTFS formatted, empty) and a cluster size of 4096, I've seen that "FileRecordCount" is set to 256 (NTFSParser.cs line 151 in the loop). I couldn't find any difference between "Quick format" and "Full format" of the volume though. |
What your describing is exactly fragmentation of the mft file. What happens is that record 0 contains $mft and one of the attributes will tell you the fragments. The parsers do not react on this. The code simply assumes that the mft is not fragmented. If you were to defrag the mft using tools from either sysinternals (contig) or piriform (defraggler). In either tool you can defrag the mft. Sent from my iPhone
|
Thanks for your hints regarding the defragmentation of the MFT. I have seen that in NTFSParser the data fragments are being retrieved for the MFT (I assume the data fragments are the fragments you were talking about?), from which are then being read from in NTFSDiskStream (Depending on the read position the associated fragment is being loaded). So to me this looks like it's already parsing the fragments, but I'm probably missing an important step? Fixing the MFT parsing doesn't look very easy indeed... :-) Anyways, I fully understand you do not find time to fix it, as I probably don't find time either to have a deeper look at it, so don't worry. |
It isn't quite - that's why I haven't jumped at it :) You're entirely correct on NTFSDiskStream. If I remember correctly, I read the MFT itself as an NTFSDiskStream, but at the time I instantiate it, I don't have the full overview of the MFT fragments .. I don't have that overview, because to be able to read the MFT's file record (record 0), I need to use the NTFSDiskStream ... (we're now in a chicken/egg problem here). One way to solve it would be to simply read record 0 using the NtfsFileRecord (iirc) which can take a byte array. In most cases (98%) the MFT is not so fragmented, so all its details are in that one 1024-byte record (or 4096-byte record). In the last 2%, the MFT is very fragmented, and file record 0 will refer to a number of other records - and that's where it gets complicated. I've been thinking about the latter solution, but it's nontrivial. |
I think I understand what you are saying but what I observe is still not clear to me.
In CMD then:
Also I checked that given MFT is really fragmented using "PassMark Fragger": Stepping through the DataFragments in the code also gives the same LCN and offsets as "PassMark Fragger" says. Printing From what I understand what you're saying should not work, I should get only the first fragment and only the records of that fragment and then run in an exception when I try to read a file record from the second fragment. However I still get both fragments content and all FileRecords. For verification purposes, I also copied the contents of _mftStream to a byte buffer, parsing a new FileRecord from that byte buffer and creating a new Stream using that new FileRecord. Contents were the same though. This is really driving me crazy and probably above my heads. |
Heh. You're following along very nicely :) Try fragmenting the file "a lot".. The goal here is for the fragments part (the If that's the case, then it's clear to me that the issue happens with external attributes (or non-resident attributes) not being read by the constructors of the MFT parsers. Fragments are okay as long as they're all described in that 1024-byte file record that constitutes $MFT. |
Okay, here are my observations: I have managed to fragment the $Mft of a 250MB volume to 404 fragments (Harder than it sounds, since Fragger doesn't support fragmenting the MFT, so I created a few large and a lot of small files on the volume): Screenshot. With that fragmented MFT, i noticed that I'm getting a different error: Screenshot. I assume this is the error you are talking about? After this, I noticed that the MFT From that base, I extracted the fragments and appended it to the existing What I changed: NTFSParser NtfsDiskStream After that changes, I dont get the said exception anymore and can read the file tree. Note: I didn't verify this with any compressed objects. Maybe this could give you a start? Some code is maybe not written in your style, but you may adapt it. Notabene: My original exception still exists (And I now realised it is probably unrelated to the MFT-fragmentation issue): I'm getting the exception there, because the code assumes that the last record breaks the while(true) loop, but this last record doesn't necessarily need to be used. // last record, not in use This at least doesn't produce any exceptions, not sure if some records are skipped though? |
I believe your first exception (reg. fragment being null) is what I was referring to. Iirc the fragment is found in a loop which returns null if it doesn't find the appropriate fragment. (A Debug.Assert should have been placed there - to make the exact issue more obvious). I should note that the convenience features I've made are more an experiment than actual production ready code. This entire library is very low level, and it's possible to build higher level features out of it. That being said - of course it has to work. If I find time, I might dedicate some to NTFS again. It's a fun project, digging around in filesystems and the way they work :). But I probably won't, as there are other usable NTFS parser in C# out there now (there weren't many when I started). One that should work is DiscUtils. Depends on your end-goal ;). |
Hi
I'm trying to get the "TestApplication" running but I'm stuck at one point:
In the line "foreach (FileRecord record in parser.GetRecords(true))" (Line 33) of the file "Program.cs" the parser should read all records. However it encounters the error:
NTFSLib.Objects.FileRecord.Parse on Line 69 throws an Assert failure, because the signature is not "FILE" but "\0\0\0\0".
It then crashes on Line 90 because res.USNSizeWords is zero.
This happens on a newly formatted NTFS volume as well as on existing volumes that work just fine in Windows.
Interestingly, the "NTFSWrapper" class seems to have no problem parsing the file system structure, as I can read all existing files (Program.cs after Lines 45).
Maybe a wrong cluster/offset is being read?
The text was updated successfully, but these errors were encountered: