NTFS檔案系統資料恢復----解析MFT表
阿新 • • 發佈:2019-02-18
http://blog.csdn.net/jha334201553/article/details/9089119
開始先說下DBR, DBR是繼MBR 之後最先訪問的地方,MBR利用int 13h 讀取MBR並將之載入到實體地址0x7c00的地方. 然後將段地址:程式碼地址入棧後retf跳過去執行.
MBR利用BIOS中斷int 13h讀取資料載入到記憶體指定位置..傳統的int 13h呼叫最多隻能識別1024個磁頭:
前面MBR講解MBR的時候,有結構如下
/*+0x01*/ uchar StartHead; // 分割槽起始磁頭號 (1磁頭 = 63 扇區,取值 0~255 之間)
/*+0x02*/ uint16 StartSector:10; // 啟始柱面號 10位 (1柱面 = 255 磁頭,取值 0~1023 之間)
/*+0x02*/ uint16 StartCylinder:6; // 啟始扇區號 6位 (取值 1 到 63 之間)
此結構可容納最大值為FF FF FF (現在這個值基本都寫成FE FF FF, 而廢棄不用), 即最大能定址的就是255柱面, 1023磁頭, 63扇區,計算扇區個數為:
1023*255*63+255*63+63 = 16450623
再按每扇區 512 位元組算, 那麼它容量為 8 GB ≈ 512*16450623 B = 7.84 GB
傳統的int 13h中斷就受限於8G的限制, Microsoft等多家公司制定了int 13h擴充套件標準,讓int 13h讀寫磁碟中斷可以突破8G限制. 現在的計算機BIOS都是按擴充套件int 13h標準編寫的程式碼.(具體詳細內容可參考"擴充套件 int 13h規範").
按MBR分割槽表裡面的 SectionPrecedingPartition 邏輯扇區偏移(注意,這個邏輯扇區偏移是從0開始算的,讀取出來值為63,而物理扇區是從1開始計算的,邏輯扇區轉換物理扇區的時候必須+1才是正確的) 可以找到DBR的位置.可以看看winhex的顯示
以下就偷懶不從MBR定址分割槽的DBR了,而是直接開啟碟符讀取 (這樣開啟的第一個扇區就是DBR),這樣做有個缺點,就是你用這個handle值將不能進行記憶體對映,只能一次多讀取幾個扇區來加快分析磁碟的速度(當前用的是一次讀取20M資料然後分析)。
- HANDLE handle = CreateFile ( TEXT("\\\\.\\C:") ,
- GENERIC_READ,
- FILE_SHARE_READ|FILE_SHARE_WRITE,
- NULL,
- OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL,
- NULL);
DBR結構定義為(對照winhex模板資訊檢視):
- ////////////////////////////////////////////////////////////////////////////
- //
- // NTFS 的DBR 資料結構
- //
- ////////////////////////////////////////////////////////////////////////////
- typedefstruct _BIOS_PARAMETER_BLOCK {
- /*+0x0B*/ uint16 BytesPerSector; // 位元組/扇區一般為0x0200 即512
- /*+0x0D*/ uchar SectorsPerCluster; // 扇區/簇
- /*+0x0E*/ uint16 ReservedSectors; // 保留扇區
- /*+0x0F*/ uchar Fats; //
- /*+0x11*/ uint16 RootEntries; //
- /*+0x13*/ uint16 Sectors; //
- /*+0x15*/ uchar Media; // 媒介描述
- /*+0x16*/ uint16 SectorsPerFat; //
- /*+0x18*/ uint16 SectorsPerTrack; // 扇區/磁軌
- /*+0x1A*/ uint16 Heads; // 頭
- /*+0x1C*/ uint32 HiddenSectors; // 隱藏扇區
- /*+0x20*/ uint32 LargeSectors; // checked when volume is mounted
- }BIOS_PARAMETER_BLOCK, *pBIOS_PARAMETER_BLOCK;
- typedefstruct _NTFS_Boot_Sector{
- /*+0x00*/ uchar JmpCode[3]; // 跳轉指令
- /*+0x03*/char OemID[8]; // 檔案系統ID
- /*+0x0B*/ BIOS_PARAMETER_BLOCK PackedBpb; // BPB
- /*+0x24*/ uchar Unused[4]; // 未使用,總是為
- /*+0x28*/ uint64 NumberSectors; // 扇區總數
- /*+0x30*/ lcn MftStartLcn; // 開始C# $MFT (簇) 乘以 BIOS_PARAMETER_BLOCK.SectorsPerCluster 值得到扇區號
- /*+0x38*/ lcn Mft2StartLcn; // 開始C# $MFTMirr (簇)
- /*+0x40*/ uchar ClustersPerFileRecordSegment; // 檔案記錄大小指示器
- /*+0x41*/ uchar Reserved0[3]; // 未使用
- /*+0x44*/ uchar DefaultClustersPerIndexAllocationBuffer; // 簇/索引塊
- /*+0x45*/ uchar Reserved1[3]; // 未使用
- /*+0x48*/ uint64 SerialNumber; // 64位序列號
- /*+0x50*/ uint32 Checksum; // 校驗和
- /*+0x54*/ uchar BootStrap[426]; // 啟動程式碼
- /*+0x1FE*/ uint16 RecordEndSign; // 0xAA55 結束標記
- }NTFS_Boot_Sector, *pNTFS_Boot_Sector;
- // 儲存 NTFS 的基本資訊
- typedefstruct _NTFS_INFO
- {
- uint32 BytesPerSector; // 每扇區的位元組數
- uint32 SectorsPerCluster; // 每簇的扇區數
- uint32 BytesPerCluster; // 每簇的位元組數
- uint64 SectorCount; // 扇區總數
- uint64 MftStart; // MFT表開始簇
- uint64 MftMirrStart; // MFT備份表開始簇
- uint32 BytesPerFileRecord; // 每個檔案記錄的位元組數一般為512*2
- uint16 VolumeLabelLength; // 卷名長度,卷名從MFT第4個項0x60屬性得到(與0x30屬性相似)
- wchar VolumeLabel[MAXIMUM_VOLUME_LABEL_LENGTH]; // 卷名
- uint16 vcnlen;
- uchar vcn[VCN_LENTH];
- } NTFS_INFO, *PNTFS_INFO;
- #define MAXIMUM_VOLUME_LABEL_LENGTH (32*sizeof(wchar))
- typedefstruct _Partition_Stand_Post
- {
- HANDLE handle; // 分割槽控制代碼
- uint64 CluNnum; // 簇號
- uint32 BytesPerCluster; // 每簇位元組
- uint64 CluCount; // 簇數量
- PNTFS_INFO NtfsInfo; // 指向NTFS_INFO 結構
- }Partition_Stand_Post, *pPartition_Stand_Post;
- // 按簇讀取資料,
- // 傳入 一個Partition_Stand_Post結構體指標,並指定buf,讀取大小
- // 結果返回讀取的資料指標
- PBYTE ReadClues(pPartition_Stand_Post post, PBYTE buf, DWORD lenth)
- {
- DWORD dwbytes = 0;
- LARGE_INTEGER li = {0};
- li.QuadPart = post->CluNnum*post->BytesPerCluster;
- SetFilePointer(post->handle, li.LowPart, &li.HighPart, FILE_BEGIN);
- ReadFile(post->handle, buf, lenth, &dwbytes, NULL);
- if (lenth == dwbytes)
- {
- return buf;
- }
- return NULL;
- }
首先,看到的是頭部,標記為"FILE", 結構體如下定義:
- // 檔案記錄頭
- typedefstruct _FILE_RECORD_HEADER
- {
- /*+0x00*/ uint32 Type; // 固定值'FILE'
- /*+0x04*/ uint16 UsaOffset; // 更新序列號偏移, 與作業系統有關
- /*+0x06*/ uint16 UsaCount; // 固定列表大小Size in words of Update Sequence Number & Array (S)