@@ -16,7 +16,8 @@ using namespace std::chrono;
1616OverwriteDetector::OverwriteDetector (MFTReader* mftReader)
1717 : reader(mftReader), detectionMode(MODE_BALANCED),
1818 threadingStrategy(THREADING_AUTO),
19- cachedStorageType(STORAGE_UNKNOWN), storageTypeDetected(false ) {
19+ cachedStorageType(STORAGE_UNKNOWN), storageTypeDetected(false ),
20+ bitmapLoaded(false ), cachedBitmapLCN((ULONGLONG)-1) {
2021 bytesPerCluster = reader->GetBytesPerSector () * reader->GetSectorsPerCluster ();
2122 threadPool = std::make_unique<OverwriteDetectionThreadPool>(this );
2223 LOG_DEBUG (" OverwriteDetector 已初始化,支持多线程" );
@@ -164,12 +165,79 @@ bool OverwriteDetector::HasValidFileStructure(const vector<BYTE>& data) {
164165 return false ;
165166}
166167
168+ // 加载 $Bitmap (MFT记录#6) 的 data runs
169+ bool OverwriteDetector::LoadBitmapDataRuns () {
170+ if (bitmapLoaded) return !bitmapRuns.empty ();
171+ bitmapLoaded = true ;
172+
173+ vector<BYTE> bitmapRecord;
174+ if (!reader->ReadMFT (6 , bitmapRecord)) {
175+ LOG_ERROR (" Failed to read $Bitmap MFT record (#6)" );
176+ return false ;
177+ }
178+
179+ if (!ExtractDataRuns (bitmapRecord, bitmapRuns)) {
180+ LOG_ERROR (" Failed to extract $Bitmap data runs" );
181+ return false ;
182+ }
183+
184+ LOG_INFO_FMT (" $Bitmap data runs loaded: %zu runs" , bitmapRuns.size ());
185+ return true ;
186+ }
187+
167188// 检查簇是否已分配给其他文件(通过读取$Bitmap)
168189bool OverwriteDetector::CheckClusterAllocation (ULONGLONG clusterNumber) {
169- // TODO: 实现$Bitmap读取功能
170- // 这需要读取MFT记录#6($Bitmap),检查对应位是否为1
171- // 暂时返回false(假设未分配)
172- return false ;
190+ if (!LoadBitmapDataRuns ()) {
191+ return false ; // 无法读取 $Bitmap,假设未分配
192+ }
193+
194+ // 计算该簇号在 bitmap 中的字节偏移和位位置
195+ ULONGLONG byteOffset = clusterNumber / 8 ;
196+ BYTE bitMask = 1 << (clusterNumber % 8 );
197+
198+ // 计算这个字节落在 $Bitmap 文件的哪个簇中
199+ ULONGLONG bitmapBytesPerCluster = (ULONGLONG)reader->GetBytesPerSector () * reader->GetSectorsPerCluster ();
200+ ULONGLONG bitmapClusterIndex = byteOffset / bitmapBytesPerCluster;
201+ ULONGLONG offsetInCluster = byteOffset % bitmapBytesPerCluster;
202+
203+ // 通过 $Bitmap 的 data runs 找到实际的物理 LCN
204+ ULONGLONG currentClusterOffset = 0 ;
205+ ULONGLONG targetLCN = 0 ;
206+ bool found = false ;
207+
208+ for (const auto & run : bitmapRuns) {
209+ if (bitmapClusterIndex < currentClusterOffset + run.second ) {
210+ targetLCN = run.first + (bitmapClusterIndex - currentClusterOffset);
211+ found = true ;
212+ break ;
213+ }
214+ currentClusterOffset += run.second ;
215+ }
216+
217+ if (!found) {
218+ return false ; // 簇号超出 bitmap 范围
219+ }
220+
221+ // 检查缓存:如果上次读的就是这个 bitmap 簇,直接查表
222+ if (cachedBitmapLCN == targetLCN && !cachedBitmapData.empty ()) {
223+ if (offsetInCluster >= cachedBitmapData.size ()) return false ;
224+ return (cachedBitmapData[offsetInCluster] & bitMask) != 0 ;
225+ }
226+
227+ // 读取 bitmap 簇并缓存
228+ vector<BYTE> clusterData;
229+ if (!reader->ReadClusters (targetLCN, 1 , clusterData)) {
230+ return false ;
231+ }
232+
233+ if (offsetInCluster >= clusterData.size ()) {
234+ return false ;
235+ }
236+
237+ cachedBitmapLCN = targetLCN;
238+ cachedBitmapData = move (clusterData);
239+
240+ return (cachedBitmapData[offsetInCluster] & bitMask) != 0 ;
173241}
174242
175243// 读取可变长度的无符号整数
0 commit comments