小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

NTFS文件系統(tǒng)數(shù)據(jù)恢復(fù)----解析MFT表+NTFS文件系統(tǒng)中MFT項中主要字節(jié)的標(biāo)注(**)

 sdxy 2019-10-30

MFT(主文件表(Master File Table))

鎖定

MFT,即主文件表(Master File Table)的簡稱,它是NTFS文件系統(tǒng)的核心。MFT由一個個MFT項(也稱為文件記錄)組成,每個MFT項占用1024字節(jié)的空間。每個MFT項的前部幾十個字節(jié)有著固定的頭結(jié)構(gòu),用來描述本MFT項的相關(guān)信息。后面的字節(jié)存放著“屬性”。每個文件和目錄的信息都包含在MFT中,每個文件和目錄至少有一個MFT項。除了引導(dǎo)扇區(qū)外,訪問其他任何一個文件前都需要先訪問MFT,在MFT中找到該文件的MFT項,根據(jù)MFT項中記錄的信息找到文件內(nèi)容并對其進(jìn)行訪問。NTFS(New Technology File System),是一種新型文件系統(tǒng)。

軟件名稱:Master File Table

軟件平臺:Windows NT

英文縮寫:MFT

地位:NTFS文件系統(tǒng)的核心

MFT簡介

(1)NTFS是Windows NT引入的新型文件系統(tǒng),它具有許多新特性。NTFS中,卷中所有存放的數(shù)據(jù)均在一個叫$MFT的文件中,叫主文件表(Master File Table)。而$MFT則由文件記錄(File Record)數(shù)組構(gòu)成。File Record的大小一般是固定的,通常情況下均為1KB,這個概念相當(dāng)于Linux中的inode。File Record在$MFT文件中物理上是連續(xù)的,且從0開始編號。$MFT僅供File System本身組織、架構(gòu)文件系統(tǒng)使用,這在NTFS中稱為元數(shù)據(jù)(Metadata)。

在NTFS文件系統(tǒng)里面,磁盤上的所有東西都以文件的形式出現(xiàn)。即使是元數(shù)據(jù)也是以一組文件的形式存儲的。

主文件表( MFT )是這個卷上每一個文件的索引。 MFT 為每一個文件保存著一組稱為“屬性”的記錄,每個屬性存儲了不同類型的信息。為主文件表(MFT)保留適當(dāng)?shù)目臻g。MFT在NTFS卷中扮演著重要的角色,對其性能的影響很大,系統(tǒng)空間分配、讀寫磁盤時會頻繁地訪問MFT,因此 MFT對NTFS的卷的性能有著至關(guān)重要的影響。NTFS文件系統(tǒng)的開發(fā)者在MFT附近預(yù)留著一個特定區(qū)域,用來減少MFT中的碎片,缺省狀態(tài)下,這一區(qū)域占整個卷大小的12.5%,盡管這個區(qū)域能使得MFT中的碎片最少,但它并非總是合適的。

MFT操作說明

要對MFT的空間進(jìn)行管理,可以在HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Control \FileSystem中增加一個類型為REG_DWORD的NtfsMftZoneReservation,它的缺省值是1,其范圍是1-4(1表示 MFT占整個卷的12.5%,2表示25%,3表示37.5%,4表示50%)。

NTFS 中包含一個稱為主文件表 (MFT) 的文件。MFT 是一個映射磁盤中儲存的所有對象的索引文件。在 MFT 中,NTFS 磁盤上的每個文件(包括 MFT 自身)至少有一映射項。MFT 中的各項包含如下數(shù)據(jù): 大小、時間及時間戳、安全屬性和數(shù)據(jù)位置。

一但 MFT 產(chǎn)生碎片,磁盤碎片整理程序無法對其進(jìn)行碎片整理。但是,由于可以持續(xù)使用 MFT 來存取磁盤上所有的其它文件,因此它也會逐漸形成碎片,從而導(dǎo)致磁盤存取時間加長,降低磁盤性能。NTFS 通過保留 1/8 的磁盤空間留作 MFT 專用而將此影響降至最低。磁盤的此區(qū)域(稱為 MFT 區(qū)域)盡可能在 MFT 增加時保持其連續(xù)性。

————————————————

版權(quán)聲明:本文為CSDN博主「千么漾漾」的原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。

原文鏈接:https://blog.csdn.net/qq_41786318/article/details/79791263

NTFS文件系統(tǒng)-MFT的屬性頭

2016-07-07 12:51:02 海天數(shù)據(jù)恢復(fù) 閱讀數(shù) 4461

版權(quán)聲明:本文為博主原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接和本聲明。

本文鏈接:https://blog.csdn.net/a307871404/article/details/51850356

前面說過MFT是有一個個屬性組成,那么每個屬性的具體結(jié)構(gòu)又是如何呢?MFT屬性的類型很多,但它們都有個共同的特點,那就是每個屬性都有屬性頭和屬性體。屬性頭又分為常駐屬性和非常駐屬性。常駐屬性和非常駐數(shù)據(jù)最大的區(qū)別是常駐屬性的只是在MFT內(nèi)部記錄,非常駐數(shù)據(jù)由于MFT記錄不下(一個MFT項只有1024)所以需要在其它數(shù)據(jù)區(qū)記錄。不管是常駐屬性還是非常駐屬性,它的屬性頭的前面16個字節(jié)是一樣的。

MFT屬性結(jié)構(gòu)圖

從上圖可以看出MFT頭很小,只有幾行代碼 ,剩下都是MFT的屬性。圖中10屬性和30屬性都是常駐屬性,而80屬性是非常駐屬性 ,因為80屬性是記錄文件內(nèi)容的屬性,一般不是幾個字節(jié)就能記錄的。下面我們來看下非常駐屬性的屬性頭具體結(jié)構(gòu)

偏移字節(jié)(16進(jìn)制)描述
00-03屬性類型
04-07屬性長度
08常駐屬性標(biāo)志00:常駐 ;01表示非常駐
09屬性名長度(為0表示沒有屬性名)
0A-0B屬性名偏移(相對于屬性頭)
0C-0D標(biāo)志
0E-0F屬性ID標(biāo)志
10-13屬性體大小
14-15屬性頭的大小
16索引
17保留

非常駐屬性頭的數(shù)據(jù)結(jié)構(gòu)

偏移字節(jié)(16進(jìn)制)描述
00-03屬性類型
04-07屬性長度
08常駐屬性標(biāo)志00:常駐 ;01表示非常駐
09屬性名長度(為0表示沒有屬性名)
0A-0B屬性名偏移(相對于屬性頭)
0C-0D標(biāo)志
0E-0F屬性ID標(biāo)志
10-17簇流的起始虛擬簇號(總是從0開始)
18-1F簇流的結(jié)束虛擬簇號
20-21簇流列表相對本屬性頭起始處偏移
22-23壓縮單位大小
24-27保留
28-2F為屬性內(nèi)容分配的空間大小字節(jié)數(shù)
30-37屬性內(nèi)容實際占用的大小字節(jié)數(shù)
38-3F屬性內(nèi)容初始大小字節(jié)數(shù)

非常駐屬性頭的最后3個參數(shù)都表示屬性內(nèi)容的大小, 這里可以寫成一樣大的。

NTFS文件系統(tǒng)MFT的屬性列表

原文鏈接:http://blog.51cto.com/shujvhuifu/1801556

MFT是由一個個屬性體組成,每個屬性體都有一個對應(yīng)的屬性名。如0x10類型的屬性表示標(biāo)準(zhǔn)屬性,這個屬性記錄著文件的基本信息。

NTFS文件系統(tǒng)的MFT屬性列表

MFT屬性類型值(16進(jìn)制)MFT屬性名描述
10$STANDARD_IFORMATION標(biāo)準(zhǔn)屬性,包含文件的基本屬性,只讀 創(chuàng)建時間、最后訪問時間等屬性。
20$ATTRIBUTE_LIST屬性列表
30$FILE_NAME文件名屬性(UNICODE編碼)
40$OBJECT_ID對象ID屬性,文件或目錄的16字節(jié)唯一標(biāo)志
50$SECURITY_DESCRIPTOR安全描述符屬性,文件的訪問控制安全屬性
60$VOLUME_NAME卷名屬性
70$VOLUME_INFORMATION卷信息屬性
80$DATA文件的數(shù)據(jù)屬性
90$INDEX_ROOT索引根屬性
A0$INDEX_ALLOCATION是90屬性的擴展版(90屬性只能在MFT內(nèi)記錄文件列表,A0屬性將文件列表記錄到數(shù)據(jù)區(qū)可以記錄更多的文件)
B0$BITMAP位圖屬性
C0$REPARSE_POINT重解析點屬性
D0$EA_INFORMATION擴展屬性信息
E0$EA擴展屬性
100$LOGGED_UTILITY_STREAMEFS加密屬性

紅色標(biāo)記:表示非常重要必須要記住

綠色標(biāo)記:表示比較重要最好記住

沒標(biāo)記的了解下即可

轉(zhuǎn)載于:https://blog.51cto.com/shujvhuifu/1801556

NTFS文件系統(tǒng)數(shù)據(jù)恢復(fù)----解析MFT表

2015-05-11 21:50:12 weinierbian 閱讀數(shù) 10406

分類專欄: 數(shù)據(jù)恢復(fù)

http://blog.csdn.net/jha334201553/article/details/9089119

開始先說下DBR, DBR是繼MBR 之后最先訪問的地方,MBR利用int 13h 讀取MBR并將之加載到物理地址0x7c00的地方. 然后將段地址:代碼地址入棧后retf跳過去運行.

MBR利用BIOS中斷int 13h讀取數(shù)據(jù)加載到內(nèi)存指定位置..傳統(tǒng)的int 13h調(diào)用最多只能識別1024個磁頭:

前面MBR講解MBR的時候,有結(jié)構(gòu)如下

/*+0x01*/   uchar    StartHead; // 分區(qū)起始磁頭號  (1磁頭 = 63 扇區(qū),取值 0~255 之間)  

/*+0x02*/   uint16   StartSector:10;    // 啟始柱面號 10位 (1柱面 = 255 磁頭,取值 0~1023 之間)  

/*+0x02*/   uint16   StartCylinder:6;   // 啟始扇區(qū)號 6位 (取值 1 到 63 之間) 

此結(jié)構(gòu)可容納最大值為FF FF FF (現(xiàn)在這個值基本都寫成FE FF FF, 而廢棄不用), 即最大能尋址的就是255柱面, 1023磁頭, 63扇區(qū),計算扇區(qū)個數(shù)為:

1023*255*63+255*63+63 = 16450623

再按每扇區(qū) 512 字節(jié)算, 那么它容量為 8 GB ≈ 512*16450623 B = 7.84 GB

傳統(tǒng)的int 13h中斷就受限于8G的限制, Microsoft等多家公司制定了int 13h擴展標(biāo)準(zhǔn),讓int 13h讀寫磁盤中斷可以突破8G限制. 現(xiàn)在的計算機BIOS都是按擴展int 13h標(biāo)準(zhǔn)編寫的代碼.(具體詳細(xì)內(nèi)容可參考"擴展 int 13h規(guī)范").

按MBR分區(qū)表里面的 SectionPrecedingPartition 邏輯扇區(qū)偏移(注意,這個邏輯扇區(qū)偏移是從0開始算的,讀取出來值為63,而物理扇區(qū)是從1開始計算的,邏輯扇區(qū)轉(zhuǎn)換物理扇區(qū)的時候必須+1才是正確的) 可以找到DBR的位置.可以看看winhex的顯示

以下就偷懶不從MBR尋址分區(qū)的DBR了,而是直接打開盤符讀取 (這樣打開的第一個扇區(qū)就是DBR),這樣做有個缺點,就是你用這個handle值將不能進(jìn)行內(nèi)存映射,只能一次多讀取幾個扇區(qū)來加快分析磁盤的速度(當(dāng)前用的是一次讀取20M數(shù)據(jù)然后分析)。

HANDLE  handle = CreateFile ( TEXT("\\\\.\\C:") ,

                          GENERIC_READ,

                          FILE_SHARE_READ|FILE_SHARE_WRITE,

                          NULL,

                          OPEN_EXISTING,

                          FILE_ATTRIBUTE_NORMAL,

                          NULL);

DBR結(jié)構(gòu)定義為(對照winhex模板信息查看):

////////////////////////////////////////////////////////////////////////////

// NTFS 的DBR 數(shù)據(jù)結(jié)構(gòu)

////////////////////////////////////////////////////////////////////////////

typedef struct _BIOS_PARAMETER_BLOCK {

 /*+0x0B*/    uint16  BytesPerSector;  //字節(jié)/扇區(qū)一般為0x0200 即512

 /*+0x0D*/    uchar   SectorsPerCluster; //扇區(qū)/簇 

 /*+0x0E*/    uint16  ReservedSectors; //保留扇區(qū)

 /*+0x0F*/    uchar   Fats;            //

 /*+0x11*/    uint16  RootEntries;     //

 /*+0x13*/    uint16  Sectors;         //

 /*+0x15*/    uchar   Media;           //媒介描述

 /*+0x16*/    uint16  SectorsPerFat;   //

 /*+0x18*/    uint16  SectorsPerTrack; //扇區(qū)/磁軌

 /*+0x1A*/    uint16  Heads;           //頭

 /*+0x1C*/    uint32  HiddenSectors;   //隱藏扇區(qū)

 /*+0x20*/    uint32  LargeSectors;    //checked when volume is mounted

}BIOS_PARAMETER_BLOCK, *pBIOS_PARAMETER_BLOCK;

typedef struct _NTFS_Boot_Sector{

 /*+0x00*/  uchar    JmpCode[3];      //跳轉(zhuǎn)指令

 /*+0x03*/char     OemID[8];        //文件系統(tǒng)ID

 /*+0x0B*/  BIOS_PARAMETER_BLOCK PackedBpb; //BPB

 /*+0x24*/  uchar    Unused[4];         //未使用,總是為

 /*+0x28*/  uint64   NumberSectors;     //扇區(qū)總數(shù)

 /*+0x30*/  lcn      MftStartLcn;      //開始C# $MFT  (簇) 乘以 BIOS_PARAMETER_BLOCK.SectorsPerCluster 值得到扇區(qū)號

 /*+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 結(jié)束標(biāo)記

}NTFS_Boot_Sector, *pNTFS_Boot_Sector;

在讀取DBR的時候,一些數(shù)據(jù)以后經(jīng)常會用到,那么需要根據(jù)DBR里面的信息保存以后會用到的信息,下面定義一個常用的保存信息結(jié)構(gòu):

//保存 NTFS 的基本信息

typedef struct _NTFS_INFO

    uint32 BytesPerSector;              //每扇區(qū)的字節(jié)數(shù)

    uint32 SectorsPerCluster;           //每簇的扇區(qū)數(shù)

    uint32 BytesPerCluster;             //每簇的字節(jié)數(shù)

    uint64 SectorCount;                 //扇區(qū)總數(shù)

    uint64 MftStart;                    //MFT表開始簇

    uint64 MftMirrStart;                //MFT備份表開始簇

    uint32 BytesPerFileRecord;          //每個文件記錄的字節(jié)數(shù)一般為512*2

    uint16 VolumeLabelLength;           // 卷名長度,卷名從MFT第4個項0x60屬性得到(與0x30屬性相似)

    wchar VolumeLabel[MAXIMUM_VOLUME_LABEL_LENGTH];  //卷名

    uint16 vcnlen;

    uchar vcn[VCN_LENTH];

} NTFS_INFO, *PNTFS_INFO;

其中 MAXIMUM_VOLUE_LABEL_LENGTH定義為

#define MAXIMUM_VOLUME_LABEL_LENGTH (32*sizeof(wchar))

NTFS_Boot_Sector .MftStartLcn*NTFS_Boot_Sector. PackedBpb .SectorsPerCluster得到MFT所在扇區(qū)號,這里為 786432*8 = 6291456扇區(qū)(字節(jié)偏移為 6291456*512= 3221225472 ( 十六進(jìn)制0xC0000000))。然后MFT表里面的內(nèi)容是根據(jù)簇號來讀取數(shù)據(jù)的,那么可以定義一個根據(jù)簇號,讀取數(shù)據(jù)的函數(shù),如下形式:

typedef struct _Partition_Stand_Post

{

    HANDLE handle;//分區(qū)句柄

    uint64 CluNnum; //簇號

    uint32 BytesPerCluster; //每簇字節(jié)

    uint64 CluCount;  //簇數(shù)量

    PNTFS_INFO NtfsInfo; //指向NTFS_INFO 結(jié)構(gòu)

}Partition_Stand_Post, *pPartition_Stand_Post;

//按簇讀取數(shù)據(jù),

//傳入 一個Partition_Stand_Post結(jié)構(gòu)體指針,并指定buf,讀取大小

//結(jié)果返回讀取的數(shù)據(jù)指針

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;

}

下面先說MFT表的結(jié)構(gòu):

首先,看到的是頭部,標(biāo)記為"FILE", 結(jié)構(gòu)體如下定義:

//文件記錄頭

typedef struct _FILE_RECORD_HEADER

{

 /*+0x00*/  uint32 Type;          //固定值'FILE'

 /*+0x04*/  uint16 UsaOffset;     //更新序列號偏移, 與操作系統(tǒng)有關(guān)

 /*+0x06*/  uint16 UsaCount;      //固定列表大小Size in words of Update Sequence Number & Array (S)

 /*+0x08*/  uint64 Lsn;           //日志文件序列號(LSN)

} FILE_RECORD_HEADER, *PFILE_RECORD_HEADER;

//文件記錄體

typedef struct _FILE_RECORD{

 /*+0x00*/  FILE_RECORD_HEADER Ntfs;//MFT表頭

 /*+0x10*/  uint16  SequenceNumber; //序列號(用于記錄文件被反復(fù)使用的次數(shù))

 /*+0x12*/  uint16  LinkCount;      //硬連接數(shù)

 /*+0x14*/  uint16  AttributeOffset;//第一個屬性偏移

 /*+0x16*/  uint16  Flags;          //falgs, 00表示刪除文件,01表示正常文件,02表示刪除目錄,03表示正常目錄

 /*+0x18*/  uint32  BytesInUse;     //文件記錄實時大小(字節(jié)) 當(dāng)前MFT表項長度,到FFFFFF的長度+4

 /*+0x1C*/  uint32  BytesAllocated; //文件記錄分配大小(字節(jié))

 /*+0x20*/  uint64  BaseFileRecord; //= 0 基礎(chǔ)文件記錄 File reference to the base FILE record

 /*+0x28*/  uint16  NextAttributeNumber; //下一個自由ID號

 /*+0x2A*/  uint16  Pading;         //邊界

 /*+0x2C*/  uint32  MFTRecordNumber;//windows xp中使用,本MFT記錄號

 /*+0x30*/  uint32  MFTUseFlags;    //MFT的使用標(biāo)記

}FILE_RECORD, *pFILE_RECORD;

這里主要關(guān)注的就是文件頭大小(0x38)可以找到第一個屬性地址,緊跟在后面的是文件類型,00表示被刪除的文件,01表示正常文件,02表示刪除目錄,03表示正常目錄.再后面就是這個MFT記錄的數(shù)據(jù)大小(很奇怪,為什么數(shù)據(jù)大小是從頭到0xFFFFFFFF的大小+4,這個值為什么不是直接從頭到0xFFFFFFFF的大小呢?).

根據(jù)FILE頭部數(shù)據(jù)找到下面的一個個屬性,接下來分析的就是一個個屬性了.

屬性由屬性頭跟屬性體組成,屬性頭的結(jié)構(gòu)定義如下:

//屬性頭

typedef struct

{

 /*+0x00*/  ATTRIBUTE_TYPE AttributeType;  //屬性類型

 /*+0x04*/  uint16 RecordLength;           //總長度(Header+body長度)

 /**0x06*/  uint16 unknow0;

 /*+0x08*/  uchar Nonresident;             //非常駐標(biāo)志

 /*+0x09*/  uchar NameLength;              //操作屬性名長度

                                          //0X0001為壓縮標(biāo)記

                                        //0X4000為加密標(biāo)記

                                        //0X8000為系數(shù)文件標(biāo)志

 /*+0x0A*/  uint16 NameOffset;         //屬性名偏移(從屬性起始位置的偏移)

                                              //NameLength 如果不為零,則用這個值去尋址數(shù)據(jù)偏移

 /*+0x0C*/  uint16 Flags;                  //ATTRIBUTE_xxx flags.

 /*+0x0E*/  uint16 AttributeNumber;        //The file-record-unique attribute instance number for this attribute.

} ATTRIBUTE, *PATTRIBUTE;

//屬性頭 

typedef struct _RESIDENT_ATTRIBUTE

{

 /*+0x00*/  ATTRIBUTE Attribute; //屬性

 /*+0x10*/  uint32 ValueLength;  //Data部分長度

 /*+0x14*/  uint16 ValueOffset;  //Data內(nèi)容起始偏移

 /*+0x16*/  uchar Flags;         //索引標(biāo)志

 /*+0x17*/  uchar Padding0;      //填充

} RESIDENT_ATTRIBUTE, *PRESIDENT_ATTRIBUTE;

其中ATTRIBUTE_TYPE是一個枚舉類型,里面定義了可能出現(xiàn)的所有類型。查看這個結(jié)構(gòu)主要是看AttributeType(上圖中,染上綠色的為屬性類型,跟在后面的的紅色框框內(nèi)數(shù)據(jù)為屬性頭+屬性體的大小(這個值必須是大于0x10,小于512的,程序中必須判斷),由這個值可以得到下一個屬性的地址),這個類型是什么,然后再跟去類型定義的Data部分去解析下面的屬性體。遍歷屬性的時候可以根據(jù)屬性類型來判斷是否已經(jīng)到達(dá)結(jié)尾,如果屬性類型為0xFFFFFFFF則表示已經(jīng)到達(dá)末尾(注意遍歷的時候還是要結(jié)合FILE頭部指定的大小來遍歷,這樣程序健壯性好很多,還有如果屬性頭后面跟著的大小值小于0x10也要結(jié)束遍歷,因為這時候這個MFT項已經(jīng)不可靠了,再繼續(xù)下去程序出錯可能性比較大(0x00值可能出現(xiàn)死循環(huán)))。

屬性類型定義,及各個類型屬性的結(jié)構(gòu)(缺少無關(guān)緊要的結(jié)構(gòu),其他結(jié)構(gòu)可參考nt4里面的源碼并對照winhex分析):

//屬性類型定義

typedef enum _ATTRIBUTE_TYPE

{

    AttributeStandardInformation = 0x10,

    AttributeAttributeList = 0x20,

    AttributeFileName = 0x30,

    AttributeObjectId = 0x40,

    AttributeSecurityDescriptor = 0x50,

    AttributeVolumeName = 0x60,

    AttributeVolumeInformation = 0x70,

    AttributeData = 0x80,

    AttributeIndexRoot = 0x90,

    AttributeIndexAllocation = 0xA0,

    AttributeBitmap = 0xB0,

    AttributeReparsePoint = 0xC0,

    AttributeEAInformation = 0xD0,

    AttributeEA = 0xE0,

    AttributePropertySet = 0xF0,

    AttributeLoggedUtilityStream = 0x100

} ATTRIBUTE_TYPE, *PATTRIBUTE_TYPE;

//基礎(chǔ)信息ATTRIBUTE.AttributeType == 0x10 

typedef struct _STANDARD_INFORMATION

{

    uint64 CreationTime;         //創(chuàng)建時間

    uint64 ChangeTime;           //修改時間

    uint64 LastWriteTime;        //最后寫入時間

    uint64 LastAccessTime;       //最后訪問時間

    uint32 FileAttribute;        //文件屬性

    uint32 AlignmentOrReserved[3];  //

#if 0

    uint32 QuotaId;

    uint32 SecurityId;

    uint64 QuotaCharge;

    USN Usn;

#endif

} STANDARD_INFORMATION, *PSTANDARD_INFORMATION;

//屬性列表ATTRIBUTE.AttributeType == 0x20

typedef struct _ATTRIBUTE_LIST

{

    ATTRIBUTE_TYPE AttributeType;

    uint16 Length;

    uchar NameLength;

    uchar NameOffset;

    uint64 StartVcn; //LowVcn

    uint64 FileReferenceNumber;

    uint16 AttributeNumber;

    uint16 AlignmentOrReserved[3];

} ATTRIBUTE_LIST, *PATTRIBUTE_LIST;

//文件屬性ATTRIBUTE.AttributeType == 0x30

typedef struct

{

 /*+0x00*/  uint64 DirectoryFile:48;  //父目錄記錄號(前個字節(jié))

 /*+0x06*/  uint64 ReferenceNumber:16;//+序列號(與目錄相關(guān))

 /*+0x08*/  uint64 CreationTime;      //文件創(chuàng)建時間

 /*+0x10*/  uint64 ChangeTime;        //文件修改時間      

 /*+0x18*/  uint64 LastWriteTime;     //MFT更新的時間

 /*+0x20*/  uint64 LastAccessTime;    //最后一次訪問時間

 /*+0x28*/  uint64 AllocatedSize;     //文件分配大小

 /*+0x30*/  uint64 DataSize;          //文件實際大小

 /*+0x38*/  uint32 FileAttributes;    //標(biāo)志,如目錄\壓縮\隱藏等

 /*+0x3C*/  uint32 AlignmentOrReserved; //用于EAS和重解析

 /*+0x40*/  uchar NameLength;    //以字符計的文件名長度,沒字節(jié)占用字節(jié)數(shù)由下一字節(jié)命名空間確定

            //文件名命名空間, 0 POSIX大小寫敏感,1 win32空間,2 DOS空間, 3 win32&DOS空間

 /*+0x41*/  uchar NameType;

 /*+0x42*/  wchar Name[1];       //以Unicode方式標(biāo)識的文件名

} FILENAME_ATTRIBUTE, *PFILENAME_ATTRIBUTE;

//數(shù)據(jù)流屬性 ATTRIBUTE.AttributeType == 0x80 

typedef struct _NONRESIDENT_ATTRIBUTE

{

    /*+0x00*/   ATTRIBUTE Attribute;  

    /*+0x10*/   uint64 StartVcn;   //LowVcn 起始VCN  起始簇號

    /*+0x18*/   uint64 LastVcn;    //HighVcn  結(jié)束VCN  結(jié)束簇號

    /*+0x20*/   uint16 RunArrayOffset;  //數(shù)據(jù)運行的偏移

    /*+0x22*/   uint16 CompressionUnit; //壓縮引擎

    /*+0x24*/   uint32  Padding0;     //填充

    /*+0x28*/   uint32  IndexedFlag;  //為屬性值分配大小(按分配的簇的字節(jié)數(shù)計算)

    /*+0x30*/   uint64 AllocatedSize; //屬性值實際大小

    /*+0x38*/   uint64 DataSize;   //屬性值壓縮大小

    /*+0x40*/   uint64 InitializedSize; //實際數(shù)據(jù)大小

    /*+0x48*/   uint64 CompressedSize;  //壓縮后大小

} NONRESIDENT_ATTRIBUTE, *PNONRESIDENT_ATTRIBUTE;

以下特別要說明就是數(shù)據(jù)恢復(fù)中要使用的一些結(jié)構(gòu)

;0x30 AttributeFileName屬性 (如果文件名很長,那么有多個0x30屬性,一個記錄短文件名,一個記錄長文件名),記錄了很多文件信息,可能使用到的有文件創(chuàng)建時間、文件修改時間、最后寫入時間、文件最后一次訪問時間。這里面的幾個值相當(dāng)于用GetFileTime 或者GetFileInformationByHandle得到的幾個FILETIME值,可以調(diào)用FileTimeToSystemTime轉(zhuǎn)換時間。其中DataSize為實際文件使用的大小,在0x80屬性中尋找簇恢復(fù)數(shù)據(jù)的時候會用到這個值。最后就是wchar的文件名,此名在cmd中顯示需用WideCharToMultiByte轉(zhuǎn)換后用printf顯示,如果用wprintf顯示中文會出現(xiàn)亂碼問題。數(shù)據(jù)恢復(fù)的時候如果需要目錄結(jié)構(gòu)可由此屬性中的DirectoryFile值得到,此值為父目錄的記錄號(相對于$MFT元所在扇區(qū)的偏移,即:$MFT + DirectoryFile*2)例如:

上圖,父目錄號為0x0000000002A4,從DBR中得到$MFT起始簇為786432(上面圖一簇為8扇區(qū)),則父目錄的MFT表項扇區(qū)為: 786432*8+0x0000000002A4*2 = 6292808,再查看6292808扇區(qū):

所以這個文件為 X:\windows\notepad.exe(其中X表示為根目錄,具體看前面CreateFile參數(shù)值是什么了).

0x80 AttributeData屬性( 注意:如果是目錄的話, 此結(jié)構(gòu)屬性是0xA0 )

如果有多個0x80屬性,則應(yīng)該認(rèn)為這個文件里面存在數(shù)據(jù)流文件,數(shù)據(jù)流表示形式為"0x30記錄文件名:流文件名",并且在explorer瀏覽中查看不到這個文件,NTFS剛出來的時候,文件流屬性進(jìn)程被病毒作者使用,比如如果要將hack.exe數(shù)據(jù)加到 1.txt 數(shù)據(jù)流里面,那么可以如下方式:

void CrateDataStream()

HANDLE hfile = CreateFile(  TEXT("1.txt:DataStream.exe"), //1.txt中數(shù)據(jù)流名字為DataStream.exe(隨意取的)

                                GENERIC_WRITE,

                                0,

                                NULL,

                                CREATE_ALWAYS,

                                FILE_ATTRIBUTE_NORMAL,

                                NULL);

    if (hfile == INVALID_HANDLE_VALUE)

    {

        return ; //打開文件錯誤

    }

    HANDLE hExeFile = CreateFile(   TEXT("hack.exe"), 

                                    GENERIC_READ,

                                    0,

                                    NULL,

                                    OPEN_EXISTING,

                                    FILE_ATTRIBUTE_NORMAL,

                                    NULL);

    if (hExeFile == INVALID_HANDLE_VALUE)

    {

        CloseHandle(hfile);

        return ; //打開文件錯誤

    }

    DWORD dwsize = GetFileSize(hExeFile, NULL);

    BYTE* buf = new BYTE[dwsize];

    DWORD wbytes;

    ReadFile(hExeFile, buf, dwsize, &wbytes, NULL);

    WriteFile(hfile, buf, wbytes, &wbytes, NULL);

    CloseHandle(hExeFile);

    CloseHandle(hfile);

}

一般是病毒作者將這個 1.txt 添加到壓縮文件(高級里面選上保存文件流數(shù)據(jù)), 然后搞成自解壓包, 在解壓后命令中寫入1.txt: DataStream.exe, 在用戶雙擊解壓的時候就會運行里面的數(shù)據(jù)流程序。不過現(xiàn)在殺毒軟件對這種數(shù)據(jù)流病毒基本都能殺了。

再說數(shù)據(jù)恢復(fù)的關(guān)鍵點:數(shù)據(jù)內(nèi)容由NONRESIDENT_ATTRIBUTE. RunArrayOffset偏移指定DATA數(shù)據(jù)地址。如果屬性頭 ATTRIBUTE.Nonresident標(biāo)記為1表示非常駐,則下面會解析怎么需要解析DATA部分, 如果為0則表示DATA就是文件內(nèi)容, 比如一個txt文件里面記錄的數(shù)據(jù)很少, 則此標(biāo)記為0, 記事本里面數(shù)據(jù)就保存在DATA中。上圖因為查看的是MFT自身,$MFT比較特殊,非常駐屬性設(shè)置成0(即FALSE)但是卻要像非常駐屬性一樣去分析。

      上圖藍(lán)色的部分,看不太清數(shù)據(jù),原始數(shù)據(jù)如下:

最開始的數(shù)據(jù)為32,其中高4bits表示數(shù)據(jù)起始簇地址占用字節(jié)數(shù),后4bits為數(shù)據(jù)大小(簇個數(shù))占用字節(jié)數(shù)..這里要特別注意,第一個起始簇信息是無符號的,后面第二個開始就是相對于前面一個簇的偏移,是有正負(fù)的,查了很多資料,這點基本上都沒提及,這也是數(shù)據(jù)恢復(fù)最容易出錯的地方,辛辛苦苦寫好了程序,一測試發(fā)現(xiàn)恢復(fù)出來的數(shù)據(jù)有問題。

上面第一個扇區(qū)地址為52604144(0x64559E*8,相對去當(dāng)前分區(qū)的扇區(qū)偏移),第二個扇區(qū)地址為(0x64559E - 0x 77)*8  =  6575399 扇區(qū)(這里值0x89為-119)。

恢復(fù)數(shù)據(jù)的時候可以根據(jù)簇大小讀取文件,然后保存,再根據(jù)前面的NONRESIDENT_ATTRIBUTE. DataSize值去SetFilePointer設(shè)置文件大小繼而調(diào)用SetEndOfFile。

定義一個結(jié)構(gòu)體表示這個結(jié)構(gòu):

typedef struct _VCN_FLASH

{

    uchar VcnLen:4;        //簇流長度 *8*512 才是得到的文件字節(jié)數(shù)

    uchar StartVcnLen:4;   //簇流起始位置--簇號

    uchar Data[1];         //簇流長度&Data + 簇流起始位置&Data+VcnLen 數(shù)據(jù)部分

}VCN_FLASH, *PVCN_FLASH;

再定義2個函數(shù)計算有符號與無符號數(shù):

uint64 make_uint64(uchar* buf, int lenth)

{

    int64 ui=0;

    if (lenth > 8)

    {

        return (int64)0;

    }

    for (int i=0; i<lenth; i++)

    {

        ui = (buf[i]<<8*i)|ui;

    }

    return ui;

}

int64 make_int64(uchar* buf, int lenth)

{

    int64 ui=0;

    if (lenth > 8)

    {

        return (int64)0;

    }

    for (int i=0; i<lenth; i++)

    {

        ui = (buf[i]<<8*i)|ui;

    }

    //判斷符號位,為負(fù)則需減取反

    if (buf[lenth-1] >= 0x80)

    {

        int64 xorval = 0;

        for (i=0; i<lenth; i++)

        {

            xorval = xorval|(0xFF<<8*i);

        }

        ui = -((ui - 1)^xorval);

    }

    return ui;

}

0x90  AttributeIndexRoot  屬性 ( 目錄索引B+樹結(jié)構(gòu) )

這個屬性,我也不是很清楚,等弄清楚了,再接著完善.................

NTFS文件系統(tǒng)中MFT項中主要字節(jié)的標(biāo)注(***)

強調(diào):

1、標(biāo)注是結(jié)合其它資料和自己的理解完成的,有可能標(biāo)注不一定正確,所以僅供參考!!

2、如轉(zhuǎn)載,請保持圖片的完整性,這也是對原創(chuàng)人員的尊重,謝謝!!

原始

基本標(biāo)注

文件記錄頭標(biāo)注

文件記錄頭標(biāo)志字節(jié)的注解

屬性標(biāo)注

屬性頭 屬性值標(biāo)注

常駐、無屬性名的屬性頭標(biāo)注

常駐、有屬性名的屬性頭標(biāo)注

非常駐、無屬性名的屬性頭標(biāo)注

非常駐、有屬性名的屬性頭標(biāo)注

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多