NTFS文件系统学习笔记挺全的网上搜的ntfs学习笔记.docx

上传人:b****4 文档编号:24598697 上传时间:2023-05-29 格式:DOCX 页数:89 大小:37.49KB
下载 相关 举报
NTFS文件系统学习笔记挺全的网上搜的ntfs学习笔记.docx_第1页
第1页 / 共89页
NTFS文件系统学习笔记挺全的网上搜的ntfs学习笔记.docx_第2页
第2页 / 共89页
NTFS文件系统学习笔记挺全的网上搜的ntfs学习笔记.docx_第3页
第3页 / 共89页
NTFS文件系统学习笔记挺全的网上搜的ntfs学习笔记.docx_第4页
第4页 / 共89页
NTFS文件系统学习笔记挺全的网上搜的ntfs学习笔记.docx_第5页
第5页 / 共89页
点击查看更多>>
下载资源
资源描述

NTFS文件系统学习笔记挺全的网上搜的ntfs学习笔记.docx

《NTFS文件系统学习笔记挺全的网上搜的ntfs学习笔记.docx》由会员分享,可在线阅读,更多相关《NTFS文件系统学习笔记挺全的网上搜的ntfs学习笔记.docx(89页珍藏版)》请在冰豆网上搜索。

NTFS文件系统学习笔记挺全的网上搜的ntfs学习笔记.docx

NTFS文件系统学习笔记挺全的网上搜的ntfs学习笔记

NTFS研究笔记[466字节wuguan2009-8-2 23:

19:

8回复:

8/336版块:

Delphi]引用

1前言

   NTFS是现在流行的磁盘格式.想想当年FAT32的时代都差不多过去了,现在装机差不多都是NTFS.我们平时编程时使用文件操作函数基于操作系统,所以不管磁盘是何种格式,都只是用相同的几个函数就可搞掂,似乎分析NTFS文件系统没有什么必要.但是如果要搞些底层一点的东西,比如数据恢复啊,磁盘分析啊等等,甚至搞一些高级病毒之类,了解NTFS文件系统都很有必要!

   现在我准备开始这个研究,现在的我对于这个是一窍不通,所以也不知从哪里开始,只能见一步学一步.所以借爱delphi()网站发一些杂乱无章的笔记.

  先定一个目标,要实现NTFS文件系统解析,写出一个程序,能在NTFS下1.读取所有文件目录结构. 2.建立新文件/目录 3.删除文件/目录. 4.读出存在文件的数据. 5.向存在文件写入数据.

  从今天起,将要开始这个笔记,直到完成目标.每有什么新的发现或研究成果我都会到这个贴子下跟贴发表,其间可能遇到好多好多的困难,希望得到各位高手的帮助.在此先谢谢各位!

[Q][U]作者:

wuguan主题:

NTFS研究笔记[/U][BR]1前言NTFS是现在流行的磁盘格式.想想当年FAT32的时代都差不多过去了,现在装机差不多都是NTFS.我们平时编程时使用文件操作函数基于操作系统,所以不管磁盘是何种格式,都只是用相同的几个函数就可搞掂,似乎分析NTFS文件系统没有什么必要.但是如果要搞些底层一点的东西,比如数据恢复啊,磁盘分析啊等等,甚至搞一些高级病毒之类,了解NTFS文件系统都很有必要!

现在我准备开始这......[/Q]

NTFS研究笔记

签名:

 

      

  1

<精华>2磁盘数据[2634字节wuguan2009-8-2 23:

24:

50回复:

0/316版块:

Delphi]引用

要分析NTFS文件系统,必须先获得分区上的数据.可以写一个函数获取指定分区上指定扇区(512字节)的数据.

添加一个单元用来做这个任务.

unit Wu_DiskSectorUnit;

interface

uses

  Windows,SysUtils,Wu_BasicUnit;

function Wu_OpenDiskSector(Drive:

char):

boolean;    //打开指定分区,准备读取数据 Drive:

代表指定分区A-Z 例:

Wu_OpenDiskSector('C');

function Wu_ReadDiskSector(SectorNum:

cardinal;var retbuf:

Pchar):

boolean;  //读取分区指定扇区的数据(512字节),并将数据指针返回retbuf

function Wu_WriteDiskSector(SectorNum:

cardinal;inbuf:

Pchar):

boolean;   //将数据写入分区指定扇区(512字节),inbuf代表要写入内容的指针

procedure Wu_CloseDiskSector();   //退出时用来结束打开指定分区

implementation

var

 hDeviceHandle:

cardinal;

 ReadBuf:

array[0..511] of char;

 WriteBuf:

array[0..511] of char;

procedure Wu_CloseDiskSector();

begin

 if closehandle(hDeviceHandle) then

 begin

  hDeviceHandle:

=INVALID_HANDLE_VALUE;

 end;

end;

function Wu_OpenDiskSector(Drive:

char):

boolean;

var

 D:

string;

begin

  Wu_CloseDiskSector();

  D:

='\\.\'+Drive+':

';

  hDeviceHandle :

= CreateFile(Pchar(D), GENERIC_ALL,FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING,0, 0);

  if (hDeviceHandle <> INVALID_HANDLE_VALUE) then

  begin

   result:

=true;

  end

  else

  begin

   result:

=false;

  end;

end;

function Wu_ReadDiskSector(SectorNum:

cardinal;var retbuf:

Pchar):

boolean;

var

 n:

integer;

 I_LARGE:

LARGE_INTEGER;

 I_INT64:

INT64;

 I_SectorNum:

INT64;

begin

 for n:

=0 to 511 do

 begin

  ReadBuf[n]:

=#0;

 end;

 if (hDeviceHandle <> INVALID_HANDLE_VALUE) then

 begin

  //FileSeek(hDevicehandle,SectorNum*512,0);这样写有一个错误,就是不支持大于2146959360的数

  I_SectorNum:

=SectorNum;

  I_INT64:

=I_SectorNum*512;

  Wu_Copy(@I_INT64,1,8,@I_LARGE,1);

  SetFilePointer(hDevicehandle,I_LARGE.LowPart,@I_LARGE.highpart,0);

  if FileRead(hDevicehandle,ReadBuf[0],512)=512 then

  begin

   result:

=true;

  end

  else

  begin

   result:

=false;

  end;

 end

 else

 begin

  result:

=false;

 end;

 retbuf:

=@ReadBuf[0];

end;

function Wu_WriteDiskSector(SectorNum:

cardinal;inbuf:

Pchar):

boolean;

var

 n:

integer;

 I_LARGE:

LARGE_INTEGER;

 I_INT64:

INT64;

 I_SectorNum:

INT64;

begin

 for n:

=0 to 511 do

 begin

  WriteBuf[n]:

=inbuf[n];

 end;

 if (hDeviceHandle <> INVALID_HANDLE_VALUE) then

 begin

  //FileSeek(hDevicehandle,SectorNum*512,0);这样写有一个错误,就是不支持大于2146959360的数

  I_SectorNum:

=SectorNum;

  I_INT64:

=I_SectorNum*512;

  Wu_Copy(@I_INT64,1,8,@I_LARGE,1);

  SetFilePointer(hDevicehandle,I_LARGE.LowPart,@I_LARGE.highpart,0);

  if FileWrite(hDevicehandle,WriteBuf[0],512)=512 then

  begin

   result:

=true;

  end

  else

  begin

   result:

=false;

  end;

 end

 else

 begin

  result:

=false;

 end;

end;

end.

[Q][U]作者:

wuguan主题:

2磁盘数据[/U][BR]要分析NTFS文件系统,必须先获得分区上的数据.可以写一个函数获取指定分区上指定扇区(512字节)的数据.添加一个单元用来做这个任务.[COLOR=red]unitWu_DiskSectorUnit;interfaceusesWindows,SysUtils,Wu_BasicUnit;functionWu_OpenDiskSector(D......[/Q]

2磁盘数据

签名:

 

      

  2

<精华>3引导扇区[2029字节wuguan2009-8-2 23:

27:

35回复:

0/273版块:

Delphi]引用

现在我们用Wu_ReadDiskSector读取分区第一个扇区的数据

var

 P:

Pchar;

Wu_OpenDiskSector('G');    //打开G盘

Wu_ReadDiskSector(0,P);    //读取G盘0扇区

Wu_CloseDiskSector;

获得这个扇区称为引导扇区,512个字节数据的意义如下表(这个表从网上拿来的)

字节偏移 长度(字节) 常用值 意义

0X00 3 0XEB5290 JMP指令

0X03 4 NTFS 文件系统 ID

0X0B 2 0X0002 每扇区字节数

0X0D 1 0X08 每簇扇区数

0X0E 2 0X0000 保留扇区

0X10 3 0X000000 总为0

0X13 2 0X0000 NTFS未使用,为0

0X15 1 0XF8 介质描述

0X16 1 0X0000 总为0

0X18 2 0X3F00 每磁道扇区数

0X1A 2 0XFF00 磁头数

0X1C 4 0X3F000000 隐含扇区

0X20 4 0X00000000 NTFS未使用,为0

0X24 4 0X80008000 NTFS未使用,为0

0X28 8 0X4AF57F0000000000 扇区总数

0X30 8 0X0400000000000000 $MFT的逻辑簇号

0X38 8 0X54FF070000000000 $MFTMirr的逻辑簇号

0X40 4 0XF6000000 每MFT记录簇数

0X44 4 0X0100000 每索引簇数

0X48 8 0X14A51B74C91B741C 卷标

0X50 4 0X00000000 校验和

0X54 430 略 引导代码

0X1FE 2 0X55AA 签名

根据此表我们写出数据结构.

type

 R_Wu_NTFSBPB=packed record

  bJmp:

array[0..2] of byte;     //跳转指令[0]

  bNTFlags:

array[0..3] of char;   //"NTFS"标识[3]

  breserve1:

array[0..3] of char;  //这个上表没有说明[7]

  wBytePerSector:

word;    //每扇区字节数(一般都是512)(重要)[B]

  bSectorPerCluster:

byte;  //每簇扇区数(重要)[D]

  wReserveSectors:

word;   //保留扇区数(重要)[E]

  bFatNum:

byte;           //?

?

?

未知[10]

  wRootDirNum:

word;       //?

?

?

未知[11]

  wSectorOfParti:

word;    //?

?

?

未知[13]

  bMedium:

byte;           //介质描述[15]

  wSectorPerFat:

word;     //?

?

?

未知[16]

  wSectorPerTrack:

word;   //每磁道扇区数[18]

  wHeadNum:

word;          //磁头数[1A]

  dwHideSector:

cardinal;  //隐含扇区[1C]

  dwSectoOfParti:

cardinal;//NTFS未使用,为0[20]

  bDeviceFlag:

byte;       //?

?

?

未知[24]

  bReserve2:

byte;         //?

?

?

未知[25]

  wReserve3:

word;         //?

?

?

未知[26]

  ullSectorsOfParti:

int64;//扇区总数(这里理论上是一个64位无符号类型,不知用int64是否有错)(重要)[28]

  ullMFTAddr:

int64;       //$MFT的起始逻辑簇号(这里理论上是一个64位无符号类型,不知用int64是否有错)(重要)[30]

  ullMFTMirrAddr:

int64;   //$MFTMirr的起始逻辑簇号(这里理论上是一个64位无符号类型,不知用int64是否有错)(重要)[38]

  bClusterPerFile:

cardinal;//每MFT记录簇数[40]

  dwClusterPerINDX:

cardinal;//每索引簇数[44]

  bSerialID:

array[0..7] of char;//卷标[48]

  //[50] 

end;

[Q][U]作者:

wuguan主题:

3引导扇区[/U][BR]现在我们用Wu_ReadDiskSector读取分区第一个扇区的数据[COLOR=red]varP:

Pchar;Wu_OpenDiskSector(\39G\39);//打开G盘Wu_ReadDiskSector(0,P);//读取G盘0扇区Wu_CloseDiskSector;[/COLOR]获得这个扇区称为引导扇区,512个字节数据......[/Q]

3引导扇区

签名:

 

      

  3

<精华>引导扇区[1024字节wuguan2009-8-6 0:

48:

56回复:

0/282版块:

Delphi]引用

现在我们已经可以分析引导扇区所记录的内容.

var

 P:

Pchar;

 BPR:

R_Wu_NTFSBPB;

Wu_OpenDiskSector('G');    //打开G盘

Wu_ReadDiskSector(0,P);    //读取G盘0扇区

wu_Copy(P,1,80,@BPR,1);    //将数据直接拷贝到结构变量中即可

Wu_CloseDiskSector;

下面我们可以根据BPR的数据来进行一些初始化的设置

unit Wu_NTFSLook;

interface

uses

 Wu_DiskSectorUnit,Wu_NTFSTypeUnit,Wu_BasicUnit;

procedure OpenDisk(Disk:

Char);    //打开某个盘

procedure CloseDisk;              //退出时关闭

implementation

var

 BPR:

R_Wu_NTFSBPR;    //用来保存当前打开分区的引导数据

 ClusterSize:

cardinal;//定义当前打开分区中每一个簇等于多少个基本扇区

 MFTRecordSize:

cardinal=2; //定义当前打开分区中每一个MFT等于多少个基本扇区

 MFTBegin:

int64;   //定义当前打开分区中MFT的起始位置(每几个基本扇区)

procedure OpenDisk(Disk:

Char);

var

 P:

Pchar;

begin

 Wu_CloseDiskSector;

 Wu_OpenDiskSector(Disk);

 Wu_ReadDiskSector(0,P);    //读取指定盘0扇区

 Wu_Copy(P,1,80,@BPR,1);

 ClusterSize:

=BPR.wBytePerSector div 512 * BPR.bSectorPerCluster;

 MFTBegin:

=BPR.ullMFTAddr * ClusterSize;

end;

procedure CloseDisk;

begin

 Wu_CloseDiskSector;

end;

end.

[Q][U]作者:

wuguan主题:

引导扇区[/U][BR]现在我们已经可以分析引导扇区所记录的内容.[COLOR=red]varP:

Pchar;BPR:

R_Wu_NTFSBPB;Wu_OpenDiskSector(\39G\39);//打开G盘Wu_ReadDiskSector(0,P);//读取G盘0扇区wu_Copy(P,1,80,@BPR,1);//将数据直接拷贝到结构变量中即可Wu_......[/Q]

引导扇区

签名:

 

      

  4

<精华>MFT记录[2093字节wuguan2009-8-6 0:

52:

7回复:

0/253版块:

Delphi]引用

下一步就可以通过[$MFT的起始逻辑簇号]来访问$MFT.

MFT应该是一个数据结构,由每一条MFT整齐排列组成一整个MFT列表,用来记录磁盘内所有文件目录的关系.

既然MFT是一个接着一个排列的,那么我们必须要知道每一个MFT的大小,以方便我们的指针对应位置.

(注:

这里MFT的大小是一个很奇怪的问题,现在所查到的资料都说得不清不楚,有些说固定大小为1024字节,有些又说不固定,有待研究)

我们暂且定义MFT的大小为1024字节.

const

 MFTRecordSize=1024;  //不管怎样都一定是512的整数倍这是肯定的

 

然后[$MFT的起始逻辑簇号]指向了列表第一项的位置.

BPR.ullMFTAddr;

 

下面是从网上找来的MFT文件记录属性头结构

偏移 长度 描述    

0X00 4 固定值“FILE”    

0X04 2 更新序列号偏移,与操作系统有关    

0X06 2 固定列表大小    

0X08 8 日志文件序列号    

0X10 2 序列号(用于记录文件被反复使用的次数)    

0X12 2 硬连接数,跟目录中的项目关联,非常重要的参数    

0X14 2 第一个属性的偏移    

0X16 2 标志字节①    

0X18 4 文件记录实时大小(字节)②    

0X1C 4 文件记录分配大小(字节)    

0C20 8 基础记录 (0:

 itself)    

0X28 2 下一个自由ID号    

0X2A 2 边界    

0X2C 4 WINDOWS XP中使用,本MFT记录号    

0X30 4 MFT的使用标记③  

 

经详细研究,MFT记录中前52($34)个字节的内容所表达的意思是固定的,那么我们又可以写数据结构了

type

  R_Wu_MFT1=packed record

   bHeadID:

array [0..3] of char;   //MFT标志,'FILE'[0]

   usFixupOffset:

word;             //更新序列号偏移,与操作系统有关[4]

   usFixupNum:

word;                //更新序列号的大小,固定列表大小[6]

   bReserve1:

array [0..7] of byte; //日志文件序列号[8]

   wUnknownSeqNum:

word;            //序列号(用于记录文件被反复使用的次数)[10]

   usLinkNum:

word;                 //硬连接数[12]

   usAttrOffset:

word;              //第一个属性的偏移地址(重要)[14]

   wResident:

word;                 //文件属性标志(重要,表示这个MFT文件的状态1:

普通文件 0:

文件被删除 3:

普通目录 2:

目录被删除)[16]

   ulMFTSize:

cardinal;             //文件记录的实际长度,用来记录本MFT的实时大小(重要,用于MFT中每个属性分析到结束)[18]

   ulMFTAllocSize:

cardinal;        //记录分配的大小(重要?

?

)[1C]

   ullMainMFT:

int64;               //基本文件记录的文件索引号(重要?

?

)[20]

   wNextFreeID:

word;               //下一个自由ID号(重要?

?

)[28]

   wBianJie:

word;                  //边界[2A]

   ulXpMFTNum:

cardinal;            //WINDOWS XP中使用,本MFT记录号[2C]

   MFTusesID:

word;                 //MFT的使用标记(重要,它在MFT记录的两个扇区中与每扇区的最末两个字节相对应,如若不然,系统将示此记录为非法记录)[30]

   //[32]

   MFTUsesTemp:

array of word;      //MFT的使用标记(重要,上面由于MFT记录扇区将每个扇区中最后的两个字节占用掉了,所以在这里补回来)[32]

end;

 

MFT是由一个固定的头52($34)字节和一系列属性(不固定,每一条属性长度不固定,属性列表是由哪一些属性组成也不固定)组成,但总大小不超过1024字节(超过时由多条记录组成).

那么现在我们就可以读取指定一项MFT的记录

[Q][U]作者:

wuguan主题:

MFT记录[/U][BR]下一步就可以通过[$MFT的起始逻辑簇号]来访问$MFT.MFT应该是一个数据结构,由每一条MFT整齐排列组成一整个MFT列表,用来记录磁盘内所有文件目录的关系.既然MFT是一个接着一个排列的,那么我们必须要知道每一个MFT的大小,以方便我们的指针对应位置.(注:

这里MFT的大小是一个很奇怪的问题,现在所查到的资料都说得不清不楚,有些说固定大小为1024字节,有些又说不固定,有待研究)......[/Q]

MFT记录

签名:

 

★    

  5

<精华>MFT属性[880字节wuguan2009-8-10 23:

53:

32回复:

0/598版块:

Delphi]引用

我们写一个函数用来获得指定第几个MFT的MFT头数据.

var

 MFTHead:

R_Wu_MFT1;  //用来保存调用GetMFTHead所获得的MFT记录基本头数据

functi

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 小学教育 > 学科竞赛

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1