论坛首页 编程语言技术论坛

C/C++ 如何实现文件在NTFS文件系统中的绝对定位(一)

浏览 9763 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-07-17   最后修改:2010-04-19

  其实在上个月写完FAT32之后,我就有想写NTFS中文件定位的冲动,但是迟迟没有敢动笔,一方面是因为将近考试,没有足够的时间来理清NTFS庞大的结构,另一方面就向前面所说,NTFS的复杂度是FAT系列文件系统无法比拟的,正因为如此,对于依旧无法认识它全貌的我来说,写NTFS是需要很大勇气的,一旦写错,完全是误人子弟啊,虽然如此,我还是想在我这部分知识没有风化之前写下点什么,因为我对C++只是一知半解,代码可能写的很糟糕,但是下面我所写的思路流程,绝对是没问题的!

关于实现文件在NTFS中的绝对定位,我们需要了解NTFS文件系统的2个主要结构: DBRMFT,关于DBR,和FAT32一样,通常为0号逻辑扇区,为引导扇区,如果您对DBR不明白,请参考相关资料。关于MFT,是NTFS文件系统的特有专利”,NTFS文件系统中的所有目录与文件,都会形成一个或多个MFT(不知道这算不算多个MFT,时间有点长了..但是在文件定位中,基本不可能出现一个目录多个MFT的情况),一个MFT2个扇区.

 

   如果您对MFT不明白,请参考相关资料,网上讲解MFT的资料很多,google一下,比我权威多了,所以定位NTFS的文件,就是找到这个文件的MFT的首扇区,再根据MFT的参数,找到这个文件DATA区的详细地址(这部分您可以去阅读MFT的相关参数,这里不详细介绍)。

  好,现在进入正题,因为每个目录都有一个MFT,而子目录的MFT的首地址正是根据他的父目录的MFT来定位的,所以NTFS的文件系统中MFT正好形成了一棵树(是不是和FDT差不多,但是复杂多了),所以大家可以想到,要定位树上叶子的位置,你必须知道ROOT(根)的位置吧,自然而然,我们就必须得到根目录的MFT的首扇子区号。大家看到这里,想必都MFT有个大概的了解了吧,通过查阅MFT的相关资料,我们可以得知:5MFT,遍是根目录的MFT区!!那么如何得到5MFT的首扇区号呢.?我们可以通过DBR,通过DBR的参数(具体请自己查阅)我们可以获得0MFT的首簇号,因为一个MFT占用2个扇区,我们可以轻松得知5MFT的首扇区号(这个都不会算的话,那我也没办法了…),好现在知道了根目录的MFT…那我们就可以通过这个MFT寻找他所有直接子结点的MFT,好,现在基本方法大家都知道了吧,比如我们要定位D:\\a\\b\\c.txt这个c.txt文件,那么通过根目录的MFT我们可以定位到aMFT,再由aMFT获取bMFT,由bMFT获取c.txtMFT,最后由c.txtMFT分析可得这个TXT文件的DATA扇区号。这样大家的思路是不是清楚了,但是最大的问题还没开始呢。

  其实上面的思路一点都不复杂,最复杂的地方就在于这个MFT的分析,如何由父目录的MFT得知子目录的MFT!!!这里是代码最复杂,也是NTFS最让人恶心的地方,下面我们慢慢分析:(我也要休息一下,我不知道该怎么说了

 (顺便说一下,这套定位方法对使用过NTFS自带的压缩或加密后的文件是无法适用的,至少我没试验过,所以还是不冒这个险了)

  我们用winhex打开任意磁盘的任何MFT(为什么用winhex呢,方便理解)大家有没有发现一个问题:颜色怎么不一样。

 

 

  不错,这就是MFT的结构,这里我还是说一下吧,除去MFT的基本头结构外,MFT还有10H20H30H40H …… B0H当中的某几个块,那些块代表的含义是不一样的,作用当然也不一样,大家可以详细看下,一个块基本有2个颜色组成,你们的鼠标放在上面可以得到提示,分别由HeaderBody两部分组成,再仔细观察每个块是不是以10H20H30H40H …… B0H中的一个开头的,那就对了,这个MFT的重要结构,我们定位文件必须分析90HA0H2个块,那第一个问题出现了,如何定位这个块?因为各个文件的MFT是不同的,可能这个MFT40H块,那个MFT没有,相同的块在不同的MFT中长度可能是不一样的,所以那些块是没有固定的地址的,那么如何定位呢?可能大家已经知道了,就是一个个往下分析!!!下面我来详细介绍下如何分析。首先我们知道,MFT的头结构长度是不变的,查表或直接数长度就可以得知MFT的头结构的长度,我们来模拟下用C实现,比如头结构长度为6416进制数,那我们现在的指针指向0,我们跳过64位,我们指向65,我们来匹配下,他到底是10H呢,还是20H呢,还是30H呢……我们发现居然是10H(事实证明却是如此),我们又可以通过之前的学习和自己的发现得知,不同MFT相同块的Header长度是不变的,变的只是他的body长度,如何计算10Hbody长度呢,通过前面的学习得知…(晕,大家好好看看基础)header中有个数值专门表示body的长度(具体哪个不记得了,大家还是去查查吧,查不到留言问我,我来找找),这样我们终于计算出了10H的长度,假设为3016进制数,我们的指针再次跳过30,来到了95….下面不用我教了吧,直到我们可爱的指针发现了90HA0H块,我们就停手….下面我来介绍下为什么我们要90HAOH….(上面还有个问题,有时候会发现有2A0H或者B0H,这时候大家通过winhex得知,第2A0H后面有显示[in slack …… ]的英文字母,我不太记得了,大家请放心,这个A0H无需理会,我们只理会第一个A0H,所以大家在查到第一个A0H后就可以直接return)

一个MFT只有2个扇区所以大家不要天真的以为如果一个目录的有1000+个子目录,我们可爱的2个扇区放得下所以,他必须放在外面!!说通俗的解释就是,家里的钱太多了,放不下了,我们就存在银行,而A0H就是银行卡,只有通过分析A0H的数据我们才能找到存进去的钱….但是值得高兴的是,我们分析一个MFT通常只需要分析90HA0H,不需要同时分析的。还是那个例子,当我们的钱太多了,放在银行了,我们必须找A0H,那么我们家本来就没钱,几毛钱放抽屉就可以了,不需要放银行,放银行里银行也要收是不是那么90H就是你放几毛钱的抽屉号 ….事实证明(非官方统计,是我的统计,大家可以自己去统计下是不是如此,可能因为操作系统的不同导致不一样吧),当目录下的文件(包括目录)小于等于2个时候,就没有A0H,因为MFT中就可以放得下好我们来整理下:

  1.  当子目录(文件)数量小于等于2个时候那么目录的信息就存放在90Hbody中。没有A0H这个块在此MFT中。

 

 

  2.  当子目录(文件)数量大于2个时候那么目录的信息就存放在其他簇中(可能有N个不连续的簇存放),对此我们就需要分析A0Hbody(就是DATA RUN)来获得那些不连续簇的簇号,而90H此时存放的只是其中2个目录或文件的信息,我们完全忽略,因为在银行里,这些信息还有,90H就可以完全忽视,我们去银行找正版的……

    

 

                 友情提醒 :  如果你到这看不明白了,请别往下看了。

  前面我们说到子目录或子文件是存放在其他的簇中,这些簇称为Index,下面一直用这种说法,要得到这些index,必须分析A0Hbody,我们称之为分析 data run,下面也一直用这种说法,关于分析data run,明天吧我会发个帖子专门详细介绍分析data run,因为有些复杂,我得去重新整理整理, 那我们现在就假设我们已经获得了index的所有簇号,由簇号我们也计算出了扇区号,那么如何看懂index就是我们的第三个问题了,第2个问题是分析data run,这个问题我们先搁置….

  

 

   关于第三个问题,大家别看这个index怎么那么复杂,其实这是非常简单的,首先我们要检索我们需要检索的目录(文件)名,index中,如果一个文件名是abc.txt 那么他是这样显示的: 文件全部名的大小(这里是07H+03H+abc.txt 文件名的每一个字符占2个字节,所以他显示的是 07H 03H 61H 00H 62H 00H 63H 00H 2EH 00H 8AH 00H 8EH 00H 8AH 00H (自己心算的 可能在字母上有点错 但就是这个意思)所以我们只要寻找这一段代码就可以了,那有的人就开始问了,一个个匹配,这算法效率也太那个了吧这里细心的人就会发现,一个文件的开头,我们还是用上面的例子,首偏移就是07H,他总是放在00H 08H这两个偏移其中之一上的,(这里可能有点说不清,不懂自己用winhex看看吧),就算某个文件是用1016进制数表示的,那么表示下个文件的时候,绝对是跳到下面某个00H08H偏移开始表示的,空出来的空间用乱七八糟的东西填满,用这种方法,逐个搜索index 指导匹配成功,我们定位到文件的头偏移。那么他的MFT的地址在哪里呢??资料可得..(又是资料),在头偏移往前8016进制的地方,有几个数,这几个数就是这个目录或文件的MFT现在我们知道MFT号,知道了0MFT的簇号,我们还有什么理由得不出此MFT所在的首扇区号呢?(恶心一次)…90Hbody也是用此方法分析,但是相比起来,这就简单多了,因为不需要考虑跨簇,跨扇区的问题。

  除了data run的问题,所有的问题都一一为你们解答了,最后再罗嗦一句,得到一个文件的MFT后,他的90HA0H其实就是记录的DATA区的地址,分析方法一样,不过这里要考虑多个MFT的情况,相当变态,我自己也没有分析过,希望有兴趣的人自己去分析分析,还是那句话,有问题留言,一定解答,没有问题麻烦也顶个,那么多字,手都酸了

我还上传了点我学习过的资料,希望对你们有好处,但是版权不是我的,请大家切勿用做商业用途,仅做学术讨论,一经下载,概不负责(其实我也是下载的..没事啦..哈哈)

 

  • 大小: 7.1 KB
  • 大小: 31.3 KB
  • 大小: 15.1 KB
  • 大小: 19.7 KB
  • 大小: 23.4 KB
  • 大小: 23.4 KB
   发表时间:2009-08-07  
有没有见过文件的MFT跟主要MFT并不是连续存在的情况,今天发现了一个状况就是$MFT的地址是0x0C0000000,而0x6A48号的地址却是0x11D9ED800,这样的结果显示文件的MFT并不是跟$MFT连续存在的,那样的话我得到的0x6A48号的mft要算出它的mft所在地址的话就是错误的,这时候该怎么办呢?
如图:
$MFT的mft区:


0x6A48号mft区:

  • 大小: 64.5 KB
  • 大小: 70.5 KB
0 请登录后投票
   发表时间:2009-08-08  
怎么可能...是连续存在的
0 请登录后投票
   发表时间:2009-09-24  
呵呵!!!!!!!!!
0 请登录后投票
   发表时间:2009-09-24  
写Rootkit用得着……
0 请登录后投票
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics