中文字幕理论片,69视频免费在线观看,亚洲成人app,国产1级毛片,刘涛最大尺度戏视频,欧美亚洲美女视频,2021韩国美女仙女屋vip视频

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
NTFS文件系統(tǒng)數(shù)據(jù)恢復(fù)----解析MFT表
標(biāo)題:  【原創(chuàng)】NTFS文件系統(tǒng)數(shù)據(jù)恢復(fù)----解析MFT表
作者: 黑貓①號(hào)
時(shí)間:  2013-06-13 19:00
轉(zhuǎn)載請(qǐng)注明出處  鏈接:  http://blog.csdn.net/jha334201553/article/details/9089119
開(kāi)始先說(shuō)下DBR, DBR是繼MBR 之后最先訪問(wèn)的地方,MBR利用int 13h 讀取MBR并將之加載到物理地址0x7c00的地方. 然后將段地址:代碼地址入棧后retf跳過(guò)去運(yùn)行.
MBR利用BIOS中斷int 13h讀取數(shù)據(jù)加載到內(nèi)存指定位置..傳統(tǒng)的int 13h調(diào)用最多只能識(shí)別1024個(gè)磁頭:
前面MBR講解MBR的時(shí)候,有結(jié)構(gòu)如下
/*+0x01*/   uchar    StartHead;         // 分區(qū)起始磁頭號(hào)  (1磁頭 = 63 扇區(qū),取值 0~255 之間)
/*+0x02*/   uint16   StartSector:10;    // 啟始柱面號(hào) 10位 (1柱面 = 255 磁頭,取值 0~1023 之間)
/*+0x02*/   uint16   StartCylinder:6;   // 啟始扇區(qū)號(hào) 6位 (取值 1 到 63 之間)
此結(jié)構(gòu)可容納最大值為FF FF FF (現(xiàn)在這個(gè)值基本都寫(xiě)成FE FF FF, 而廢棄不用), 即最大能尋址的就是255柱面, 1023磁頭, 63扇區(qū),計(jì)算扇區(qū)個(gè)數(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擴(kuò)展標(biāo)準(zhǔn),讓int 13h讀寫(xiě)磁盤(pán)中斷可以突破8G限制. 現(xiàn)在的計(jì)算機(jī)BIOS都是按擴(kuò)展int 13h標(biāo)準(zhǔn)編寫(xiě)的代碼.(具體詳細(xì)內(nèi)容可參考"擴(kuò)展 int 13h規(guī)范").
按MBR分區(qū)表里面的 SectionPrecedingPartition 邏輯扇區(qū)偏移(注意,這個(gè)邏輯扇區(qū)偏移是從0開(kāi)始算的,讀取出來(lái)值為63,而物理扇區(qū)是從1開(kāi)始計(jì)算的,邏輯扇區(qū)轉(zhuǎn)換物理扇區(qū)的時(shí)候必須+1才是正確的) 可以找到DBR的位置.可以看看winhex的顯示
以下就偷懶不從MBR尋址分區(qū)的DBR了,而是直接打開(kāi)盤(pán)符讀取 (這樣打開(kāi)的第一個(gè)扇區(qū)就是DBR),這樣做有個(gè)缺點(diǎn),就是你用這個(gè)handle值將不能進(jìn)行內(nèi)存映射,只能一次多讀取幾個(gè)扇區(qū)來(lái)加快分析磁盤(pán)的速度(當(dāng)前用的是一次讀取20M數(shù)據(jù)然后分析)。
[cpp] view plaincopy
HANDLE  handle = CreateFile ( TEXT("\\\\.\\C:") ,
GENERIC_READ,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
DBR結(jié)構(gòu)定義為(對(duì)照winhex模板信息查看):
[cpp] view plaincopy
////////////////////////////////////////////////////////////////////////////
//
//  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;        // 開(kāi)始C# $MFT  (簇) 乘以 BIOS_PARAMETER_BLOCK.SectorsPerCluster 值得到扇區(qū)號(hào)
/*+0x38*/  lcn      Mft2StartLcn;       // 開(kāi)始C# $MFTMirr (簇)
/*+0x40*/  uchar    ClustersPerFileRecordSegment;  // 文件記錄大小指示器
/*+0x41*/  uchar   Reserved0[3];       // 未使用
/*+0x44*/  uchar DefaultClustersPerIndexAllocationBuffer;     // 簇/索引塊
/*+0x45*/  uchar   Reserved1[3];       // 未使用
/*+0x48*/  uint64  SerialNumber;       // 64位序列號(hào)
/*+0x50*/  uint32  Checksum;           // 校驗(yàn)和
/*+0x54*/  uchar   BootStrap[426];     // 啟動(dòng)代碼
/*+0x1FE*/ uint16  RecordEndSign;      // 0xAA55 結(jié)束標(biāo)記
}NTFS_Boot_Sector, *pNTFS_Boot_Sector;
在讀取DBR的時(shí)候,一些數(shù)據(jù)以后經(jīng)常會(huì)用到,那么需要根據(jù)DBR里面的信息保存以后會(huì)用到的信息,下面定義一個(gè)常用的保存信息結(jié)構(gòu):[cpp] view plaincopy
// 保存 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表開(kāi)始簇
uint64 MftMirrStart;                // MFT備份表開(kāi)始簇
uint32 BytesPerFileRecord;          // 每個(gè)文件記錄的字節(jié)數(shù)一般為512*2
uint16 VolumeLabelLength;           //  卷名長(zhǎng)度,卷名從MFT第4個(gè)項(xiàng)0x60屬性得到(與0x30屬性相似)
wchar VolumeLabel[MAXIMUM_VOLUME_LABEL_LENGTH];  // 卷名
uint16 vcnlen;
uchar vcn[VCN_LENTH];
} NTFS_INFO, *PNTFS_INFO;
其中 MAXIMUM_VOLUE_LABEL_LENGTH定義為
[cpp] view plaincopy
#define MAXIMUM_VOLUME_LABEL_LENGTH (32*sizeof(wchar))
NTFS_Boot_Sector .MftStartLcn*NTFS_Boot_Sector. PackedBpb .SectorsPerCluster得到MFT所在扇區(qū)號(hào),這里為 786432*8 = 6291456扇區(qū)(字節(jié)偏移為 6291456*512= 3221225472 ( 十六進(jìn)制0xC0000000))。然后MFT表里面的內(nèi)容是根據(jù)簇號(hào)來(lái)讀取數(shù)據(jù)的,那么可以定義一個(gè)根據(jù)簇號(hào),讀取數(shù)據(jù)的函數(shù),如下形式:[cpp] view plaincopy
typedef struct _Partition_Stand_Post
{
HANDLE handle;  // 分區(qū)句柄
uint64 CluNnum; // 簇號(hào)
uint32 BytesPerCluster; // 每簇字節(jié)
uint64 CluCount;  // 簇?cái)?shù)量
PNTFS_INFO NtfsInfo; // 指向NTFS_INFO 結(jié)構(gòu)
}Partition_Stand_Post, *pPartition_Stand_Post;
// 按簇讀取數(shù)據(jù),
// 傳入 一個(gè)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;
}
下面先說(shuō)MFT表的結(jié)構(gòu):
首先,看到的是頭部,標(biāo)記為"FILE", 結(jié)構(gòu)體如下定義:
[cpp] view plaincopy
// 文件記錄頭
typedef struct _FILE_RECORD_HEADER
{
/*+0x00*/  uint32 Type;            // 固定值'FILE'
/*+0x04*/  uint16 UsaOffset;       // 更新序列號(hào)偏移, 與操作系統(tǒng)有關(guān)
/*+0x06*/  uint16 UsaCount;        // 固定列表大小Size in words of Update Sequence Number & Array (S)
/*+0x08*/  uint64 Lsn;             // 日志文件序列號(hào)(LSN)
} FILE_RECORD_HEADER, *PFILE_RECORD_HEADER;
// 文件記錄體
typedef struct _FILE_RECORD{
/*+0x00*/  FILE_RECORD_HEADER Ntfs;  // MFT表頭
/*+0x10*/  uint16  SequenceNumber;   // 序列號(hào)(用于記錄文件被反復(fù)使用的次數(shù))
/*+0x12*/  uint16  LinkCount;        // 硬連接數(shù)
/*+0x14*/  uint16  AttributeOffset;  // 第一個(gè)屬性偏移
/*+0x16*/  uint16  Flags;            // falgs, 00表示刪除文件,01表示正常文件,02表示刪除目錄,03表示正常目錄
/*+0x18*/  uint32  BytesInUse;       // 文件記錄實(shí)時(shí)大小(字節(jié)) 當(dāng)前MFT表項(xiàng)長(zhǎng)度,到FFFFFF的長(zhǎng)度+4
/*+0x1C*/  uint32  BytesAllocated;   // 文件記錄分配大小(字節(jié))
/*+0x20*/  uint64  BaseFileRecord;   // = 0 基礎(chǔ)文件記錄 File reference to the base FILE record
/*+0x28*/  uint16  NextAttributeNumber; // 下一個(gè)自由ID號(hào)
/*+0x2A*/  uint16  Pading;           // 邊界
/*+0x2C*/  uint32  MFTRecordNumber;  // windows xp中使用,本MFT記錄號(hào)
/*+0x30*/  uint32  MFTUseFlags;      // MFT的使用標(biāo)記
}FILE_RECORD, *pFILE_RECORD;
這里主要關(guān)注的就是文件頭大小(0x38)可以找到第一個(gè)屬性地址,緊跟在后面的是文件類(lèi)型,00表示被刪除的文件,01表示正常文件,02表示刪除目錄,03表示正常目錄.再后面就是這個(gè)MFT記錄的數(shù)據(jù)大小(很奇怪,為什么數(shù)據(jù)大小是從頭到0xFFFFFFFF的大小+4,這個(gè)值為什么不是直接從頭到0xFFFFFFFF的大小呢?).
根據(jù)FILE頭部數(shù)據(jù)找到下面的一個(gè)個(gè)屬性,接下來(lái)分析的就是一個(gè)個(gè)屬性了.
屬性由屬性頭跟屬性體組成,屬性頭的結(jié)構(gòu)定義如下:[cpp] view plaincopy
// 屬性頭
typedef struct
{
/*+0x00*/  ATTRIBUTE_TYPE AttributeType;    // 屬性類(lèi)型
/*+0x04*/  uint16 RecordLength;             // 總長(zhǎng)度(Header+body長(zhǎng)度)
/**0x06*/  uint16 unknow0;
/*+0x08*/  uchar Nonresident;               // 非常駐標(biāo)志
/*+0x09*/  uchar NameLength;                // 操作屬性名長(zhǎng)度
// 0X0001為壓縮標(biāo)記
// 0X4000為加密標(biāo)記
// 0X8000為系數(shù)文件標(biāo)志
/*+0x0A*/  uint16 NameOffset;           // 屬性名偏移(從屬性起始位置的偏移)
// NameLength 如果不為零,則用這個(gè)值去尋址數(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部分長(zhǎng)度
/*+0x14*/  uint16 ValueOffset;    // Data內(nèi)容起始偏移
/*+0x16*/  uchar Flags;           // 索引標(biāo)志
/*+0x17*/  uchar Padding0;        // 填充
} RESIDENT_ATTRIBUTE, *PRESIDENT_ATTRIBUTE;
其中  ATTRIBUTE_TYPE 是一個(gè)枚舉類(lèi)型,里面定義了可能出現(xiàn)的所有類(lèi)型。查看這個(gè)結(jié)構(gòu)主要是看AttributeType(上圖中,染上綠色的為屬性類(lèi)型,跟在后面的的紅色框框內(nèi)數(shù)據(jù)為屬性頭+屬性體的大?。ㄟ@個(gè)值必須是大于0x10,小于512的,程序中必須判斷),由這個(gè)值可以得到下一個(gè)屬性的地址),這個(gè)類(lèi)型是什么,然后再跟去類(lèi)型定義的Data部分去解析下面的屬性體。遍歷屬性的時(shí)候可以根據(jù)屬性類(lèi)型來(lái)判斷是否已經(jīng)到達(dá)結(jié)尾,如果屬性類(lèi)型為0xFFFFFFFF則表示已經(jīng)到達(dá)末尾(注意遍歷的時(shí)候還是要結(jié)合FILE頭部指定的大小來(lái)遍歷,這樣程序健壯性好很多,還有如果屬性頭后面跟著的大小值小于0x10也要結(jié)束遍歷,因?yàn)檫@時(shí)候這個(gè)MFT項(xiàng)已經(jīng)不可靠了,再繼續(xù)下去程序出錯(cuò)可能性比較大(0x00值可能出現(xiàn)死循環(huán)))。
屬性類(lèi)型定義,及各個(gè)類(lèi)型屬性的結(jié)構(gòu)(缺少無(wú)關(guān)緊要的結(jié)構(gòu),其他結(jié)構(gòu)可參考nt4里面的源碼并對(duì)照winhex分析):[cpp] view plaincopy
// 屬性類(lèi)型定義
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)建時(shí)間
uint64 ChangeTime;           // 修改時(shí)間
uint64 LastWriteTime;        // 最后寫(xiě)入時(shí)間
uint64 LastAccessTime;       // 最后訪問(wèn)時(shí)間
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;    // 父目錄記錄號(hào)(前個(gè)字節(jié))
/*+0x06*/  uint64 ReferenceNumber:16;  // +序列號(hào)(與目錄相關(guān))
/*+0x08*/  uint64 CreationTime;        // 文件創(chuàng)建時(shí)間
/*+0x10*/  uint64 ChangeTime;          // 文件修改時(shí)間
/*+0x18*/  uint64 LastWriteTime;       // MFT更新的時(shí)間
/*+0x20*/  uint64 LastAccessTime;      // 最后一次訪問(wèn)時(shí)間
/*+0x28*/  uint64 AllocatedSize;       // 文件分配大小
/*+0x30*/  uint64 DataSize;            // 文件實(shí)際大小
/*+0x38*/  uint32 FileAttributes;      // 標(biāo)志,如目錄\壓縮\隱藏等
/*+0x3C*/  uint32 AlignmentOrReserved; // 用于EAS和重解析
/*+0x40*/  uchar NameLength;      // 以字符計(jì)的文件名長(zhǎng)度,沒(méi)字節(jié)占用字節(jié)數(shù)由下一字節(jié)命名空間確定
// 文件名命名空間, 0 POSIX大小寫(xiě)敏感,1 win32空間,2 DOS空間, 3 win32&DOS空間
/*+0x41*/  uchar NameType;
/*+0x42*/  wchar Name[1];         // 以Unicode方式標(biāo)識(shí)的文件名
} FILENAME_ATTRIBUTE, *PFILENAME_ATTRIBUTE;
// 數(shù)據(jù)流屬性 ATTRIBUTE.AttributeType == 0x80
typedef struct _NONRESIDENT_ATTRIBUTE
{
/*+0x00*/   ATTRIBUTE Attribute;
/*+0x10*/   uint64 StartVcn;     // LowVcn 起始VCN  起始簇號(hào)
/*+0x18*/   uint64 LastVcn;      // HighVcn  結(jié)束VCN  結(jié)束簇號(hào)
/*+0x20*/   uint16 RunArrayOffset;    // 數(shù)據(jù)運(yùn)行的偏移
/*+0x22*/   uint16 CompressionUnit;   // 壓縮引擎
/*+0x24*/   uint32  Padding0;       // 填充
/*+0x28*/   uint32  IndexedFlag;    // 為屬性值分配大小(按分配的簇的字節(jié)數(shù)計(jì)算)
/*+0x30*/   uint64 AllocatedSize;   // 屬性值實(shí)際大小
/*+0x38*/   uint64 DataSize;     // 屬性值壓縮大小
/*+0x40*/   uint64 InitializedSize;   // 實(shí)際數(shù)據(jù)大小
/*+0x48*/   uint64 CompressedSize;    // 壓縮后大小
} NONRESIDENT_ATTRIBUTE, *PNONRESIDENT_ATTRIBUTE;
以下特別要說(shuō)明就是數(shù)據(jù)恢復(fù)中要使用的一些結(jié)構(gòu)
0x30 AttributeFileName屬性 (如果文件名很長(zhǎng),那么有多個(gè)0x30屬性,一個(gè)記錄短文件名,一個(gè)記錄長(zhǎng)文件名),記錄了很多文件信息,可能使用到的有文件創(chuàng)建時(shí)間、文件修改時(shí)間、最后寫(xiě)入時(shí)間、文件最后一次訪問(wèn)時(shí)間。這里面的幾個(gè)值相當(dāng)于用GetFileTime 或者GetFileInformationByHandle得到的幾個(gè)FILETIME值,可以調(diào)用FileTimeToSystemTime轉(zhuǎn)換時(shí)間。其中DataSize為實(shí)際文件使用的大小,在0x80屬性中尋找簇恢復(fù)數(shù)據(jù)的時(shí)候會(huì)用到這個(gè)值。最后就是wchar的文件名,此名在cmd中顯示需用WideCharToMultiByte轉(zhuǎn)換后用printf顯示,如果用wprintf顯示中文會(huì)出現(xiàn)亂碼問(wèn)題。數(shù)據(jù)恢復(fù)的時(shí)候如果需要目錄結(jié)構(gòu)可由此屬性中的DirectoryFile值得到,此值為父目錄的記錄號(hào)(相對(duì)于$MFT元所在扇區(qū)的偏移,即:$MFT + DirectoryFile*2)例如:
上圖,父目錄號(hào)為0x0000000002A4,從DBR中得到$MFT起始簇為786432(上面圖一簇為8扇區(qū)),則父目錄的MFT表項(xiàng)扇區(qū)為: 786432*8+0x0000000002A4*2 = 6292808,再查看6292808扇區(qū):
所以這個(gè)文件為 X:\windows\notepad.exe(其中X表示為根目錄,具體看前面CreateFile參數(shù)值是什么了).
0x80 AttributeData屬性( 注意:如果是目錄的話, 此結(jié)構(gòu)屬性是0xA0 )
如果有多個(gè)0x80屬性,則應(yīng)該認(rèn)為這個(gè)文件里面存在數(shù)據(jù)流文件,數(shù)據(jù)流表示形式為"0x30記錄文件名:流文件名",并且在explorer瀏覽中查看不到這個(gè)文件,NTFS剛出來(lái)的時(shí)候,文件流屬性進(jìn)程被病毒作者使用,比如如果要將hack.exe數(shù)據(jù)加到 1.txt 數(shù)據(jù)流里面,那么可以如下方式:
[cpp] view plaincopy
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 ; // 打開(kāi)文件錯(cuò)誤
}
HANDLE hExeFile = CreateFile(   TEXT("hack.exe"),
GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hExeFile == INVALID_HANDLE_VALUE)
{
CloseHandle(hfile);
return ; // 打開(kāi)文件錯(cuò)誤
}
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);
}
一般是病毒作者將這個(gè) 1.txt 添加到壓縮文件(高級(jí)里面選上保存文件流數(shù)據(jù)), 然后搞成自解壓包, 在解壓后命令中寫(xiě)入1.txt: DataStream.exe, 在用戶雙擊解壓的時(shí)候就會(huì)運(yùn)行里面的數(shù)據(jù)流程序。不過(guò)現(xiàn)在殺毒軟件對(duì)這種數(shù)據(jù)流病毒基本都能殺了。
再說(shuō)數(shù)據(jù)恢復(fù)的關(guān)鍵點(diǎn):數(shù)據(jù)內(nèi)容由NONRESIDENT_ATTRIBUTE. RunArrayOffset偏移指定DATA數(shù)據(jù)地址。如果屬性頭 ATTRIBUTE.Nonresident標(biāo)記為1表示非常駐,則下面會(huì)解析怎么需要解析DATA部分, 如果為0則表示DATA就是文件內(nèi)容, 比如一個(gè)txt文件里面記錄的數(shù)據(jù)很少, 則此標(biāo)記為0, 記事本里面數(shù)據(jù)就保存在DATA中。上圖因?yàn)椴榭吹氖荕FT自身,$MFT比較特殊,非常駐屬性設(shè)置成0(即FALSE)但是卻要像非常駐屬性一樣去分析。
上圖藍(lán)色的部分,看不太清數(shù)據(jù),原始數(shù)據(jù)如下:
最開(kāi)始的數(shù)據(jù)為32,其中高4bits表示數(shù)據(jù)起始簇地址占用字節(jié)數(shù),后4bits為數(shù)據(jù)大小(簇個(gè)數(shù))占用字節(jié)數(shù)..這里要特別注意,第一個(gè)起始簇信息是無(wú)符號(hào)的,后面第二個(gè)開(kāi)始就是相對(duì)于前面一個(gè)簇的偏移,是有正負(fù)的,查了很多資料,這點(diǎn)基本上都沒(méi)提及,這也是數(shù)據(jù)恢復(fù)最容易出錯(cuò)的地方,辛辛苦苦寫(xiě)好了程序,一測(cè)試發(fā)現(xiàn)恢復(fù)出來(lái)的數(shù)據(jù)有問(wèn)題。
上面第一個(gè)扇區(qū)地址為52604144(0x64559E*8,相對(duì)去當(dāng)前分區(qū)的扇區(qū)偏移),第二個(gè)扇區(qū)地址為(0x64559E - 0x 77)*8  =  6575399 扇區(qū)(這里值0x89為-119)。
恢復(fù)數(shù)據(jù)的時(shí)候可以根據(jù)簇大小讀取文件,然后保存,再根據(jù)前面的NONRESIDENT_ATTRIBUTE. DataSize值去SetFilePointer設(shè)置文件大小繼而調(diào)用SetEndOfFile。
定義一個(gè)結(jié)構(gòu)體表示這個(gè)結(jié)構(gòu):
[cpp] view plaincopy
typedef struct _VCN_FLASH
{
uchar VcnLen:4;        // 簇流長(zhǎng)度 *8*512 才是得到的文件字節(jié)數(shù)
uchar StartVcnLen:4;   // 簇流起始位置--簇號(hào)
uchar Data[1];         // 簇流長(zhǎng)度&Data + 簇流起始位置&Data+VcnLen 數(shù)據(jù)部分
}VCN_FLASH, *PVCN_FLASH;
再定義2個(gè)函數(shù)計(jì)算有符號(hào)與無(wú)符號(hào)數(shù):[cpp] view plaincopy
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;
}
// 判斷符號(hào)位,為負(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+樹(shù)結(jié)構(gòu) )
這個(gè)屬性,我也不是很清楚,等弄清楚了,再接著完善.................
相關(guān)資料: test-disk源碼. http://www.cgsecurity.org/                   nt4 源碼
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
NTFS文件系統(tǒng)數(shù)據(jù)恢復(fù)----解析MFT表+NTFS文件系統(tǒng)中MFT項(xiàng)中主要字節(jié)的標(biāo)注(**)
格式化的原理
對(duì)MFT偏移的修正---親歷一次數(shù)據(jù)修復(fù)
Windows操作系統(tǒng)引導(dǎo)過(guò)程(上部)
解讀NTFS
NTFS格式化為FAT32的數(shù)據(jù)恢復(fù)
更多類(lèi)似文章 >>
生活服務(wù)
熱點(diǎn)新聞
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服