Skip to content

Commit 91e0517

Browse files
111
1 parent e7773cd commit 91e0517

5 files changed

Lines changed: 143 additions & 9 deletions

File tree

Filerestore_CLI/src/analysis/ImageTable.cpp

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ ULONGLONG ImageTableAnalyzer::GetFuncaddressByName(string name,string file)
5757
PIMAGE_IMPORT_BY_NAME pImportByName = (PIMAGE_IMPORT_BY_NAME)((DWORD_PTR)lpBuffer + RVAtoFOA((DWORD)IAT->u1.AddressOfData,lpBuffer));
5858
if (name.compare(string((char*)pImportByName->Name))==0) {
5959
funcAddress = IAT->u1.Function+pOptionalHeader64->ImageBase;
60+
CleanupMappedFile();
6061
return funcAddress;
6162
}
6263
}
@@ -65,6 +66,7 @@ ULONGLONG ImageTableAnalyzer::GetFuncaddressByName(string name,string file)
6566
pImportDescriptor++;
6667
}
6768
}
69+
CleanupMappedFile();
6870
return 0;
6971
}
7072
//遍历导入表中的DLL名称
@@ -128,6 +130,7 @@ vector<string> ImageTableAnalyzer::AnalyzeTableForDLL(string file)
128130
dllList.push_back(string(dllName));
129131
pImportDescriptor++;
130132
}
133+
CleanupMappedFile();
131134
return dllList;
132135
}
133136
//遍历导入表中的函数名称
@@ -226,6 +229,7 @@ map<string, vector<string>> ImageTableAnalyzer::AnalyzeTableForFunctions(string
226229
funcList[string(dllName)] = funcNames;
227230
pImportDescriptor++;
228231
}
232+
CleanupMappedFile();
229233
return funcList;
230234
}
231235
bool ImageTableAnalyzer::IsImagineTable(LPVOID lpBuffer)
@@ -332,7 +336,19 @@ BOOL ImageTableAnalyzer::CheckIsAdmin()
332336
ImageTableAnalyzer::ImageTableAnalyzer() {
333337
}
334338
ImageTableAnalyzer::~ImageTableAnalyzer() {
335-
CloseHandle(ImageTableAnalyzer::hFileMapping);
336-
CloseHandle(ImageTableAnalyzer::hFile);
337-
UnmapViewOfFile(lpBuffer);
339+
CleanupMappedFile();
340+
}
341+
void ImageTableAnalyzer::CleanupMappedFile() {
342+
if (lpBuffer) {
343+
UnmapViewOfFile(lpBuffer);
344+
lpBuffer = NULL;
345+
}
346+
if (hFileMapping) {
347+
CloseHandle(hFileMapping);
348+
hFileMapping = NULL;
349+
}
350+
if (hFile && hFile != INVALID_HANDLE_VALUE) {
351+
CloseHandle(hFile);
352+
hFile = NULL;
353+
}
338354
}

Filerestore_CLI/src/analysis/ImageTable.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ class ImageTableAnalyzer
3333
// - BOOL ElevatePrivilegeForSystem(wstring Privilege);
3434
// - BOOL DLLImplantForSystemProcess(string dllfile, int PID);
3535

36+
private:
37+
void CleanupMappedFile();
38+
3639
public:
3740
ImageTableAnalyzer();
3841
~ImageTableAnalyzer();

Filerestore_CLI/src/fileRestore/MFTReader.cpp

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,47 @@ bool MFTReader::ReadMFTBatch(ULONGLONG startRecordNumber, ULONGLONG recordCount,
296296
return false;
297297
}
298298

299-
// 计算需要读取的簇范围
299+
// 碎片化 MFT 路径:逐簇读取,缓存避免重复 I/O
300+
if (mftDataRunsLoaded && mftDataRuns.size() > 1) {
301+
LOG_DEBUG("Using fragmented MFT batch read path");
302+
303+
ULONGLONG lastLCN = (ULONGLONG)-1;
304+
vector<BYTE> cachedCluster;
305+
306+
for (ULONGLONG i = 0; i < recordCount; i++) {
307+
ULONGLONG recordNumber = startRecordNumber + i;
308+
ULONGLONG lcn, offsetInCluster;
309+
310+
if (!GetMFTRecordLCN(recordNumber, lcn, offsetInCluster)) {
311+
LOG_WARNING_FMT("Record #%llu: cannot resolve LCN, skipping", recordNumber);
312+
continue;
313+
}
314+
315+
// 同一个簇内的多条记录只读一次磁盘
316+
if (lcn != lastLCN) {
317+
if (!ReadClusters(lcn, 1, cachedCluster)) {
318+
LOG_WARNING_FMT("Failed to read cluster at LCN %llu for record #%llu", lcn, recordNumber);
319+
continue;
320+
}
321+
lastLCN = lcn;
322+
}
323+
324+
if (offsetInCluster + bytesPerFileRecord > cachedCluster.size()) {
325+
LOG_WARNING_FMT("Record #%llu offset out of bounds, skipping", recordNumber);
326+
continue;
327+
}
328+
329+
vector<BYTE> record(bytesPerFileRecord);
330+
memcpy(record.data(), cachedCluster.data() + offsetInCluster, bytesPerFileRecord);
331+
ApplyUSAFixup(record, bytesPerSector);
332+
records.push_back(move(record));
333+
}
334+
335+
LOG_DEBUG_FMT("ReadMFTBatch (fragmented) completed: extracted %zu valid records", records.size());
336+
return true;
337+
}
338+
339+
// 连续 MFT 路径:批量读取(原始代码)
300340
ULONGLONG startCluster = startRecordNumber / recordsPerCluster;
301341
ULONGLONG endRecord = startRecordNumber + recordCount - 1;
302342
ULONGLONG endCluster = endRecord / recordsPerCluster;

Filerestore_CLI/src/fileRestore/OverwriteDetector.cpp

Lines changed: 73 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ using namespace std::chrono;
1616
OverwriteDetector::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)
168189
bool 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
// 读取可变长度的无符号整数

Filerestore_CLI/src/fileRestore/OverwriteDetector.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,13 @@ class OverwriteDetector
8686
bool HasValidFileStructureFromPointer(const BYTE* data, size_t size);
8787
bool CheckClusterAllocation(ULONGLONG clusterNumber);
8888

89+
// $Bitmap 簇分配检测
90+
vector<pair<ULONGLONG, ULONGLONG>> bitmapRuns; // $Bitmap 文件的 data runs
91+
bool bitmapLoaded;
92+
ULONGLONG cachedBitmapLCN; // 缓存的 bitmap 簇 LCN
93+
vector<BYTE> cachedBitmapData; // 缓存的 bitmap 簇数据
94+
bool LoadBitmapDataRuns();
95+
8996
// 解析Data Runs的辅助函数
9097
ULONGLONG ReadVariableLength(const BYTE* data, int length);
9198
LONGLONG ReadVariableLengthSigned(const BYTE* data, int length);

0 commit comments

Comments
 (0)