基于FAT32的文件隐藏方法及在Linux上的实现
2012-07-13江祖敏
袁 杰,江祖敏
(武汉大学 计算机学院,湖北 武汉 430072)
为了使个人的重要文件对其他人具有透明、不可见的效果,人们往往使用文件隐藏来达到目的。针对文件隐藏,一个重要的技术衡量指标是文件的隐藏强度,即顺利获取被隐藏文件所需的时间复杂度。现有文件隐藏技术包括:利用回收站特性,将文件伪装为回收站中的文件[1];修改注册表,使得无法通过常规方法显示隐藏文件[2];改变API执行流程,用自定义的文件相关函数入口地址替代原文件管理相关函数的入口地址,过滤掉待隐藏文件的有关内容后再重新调用原函数;直接修改底层驱动,对底层模块返回的信息进行过滤来实现文件隐藏[3-4]等。
FAT32文件系统[5-6]是微软公司发明并拥有部分专利的文件系统,是一种规定文件在磁盘上的具体存储形式的“格式标准”,通过它可有效地对物理磁盘进行管理。由于它采用了以32位为一个表项的文件分配表 (File Allocation Table,FAT)来解决分区大小的局限,故称之为FAT32。虽然微软已经推出了新一代文件系统NTFS(New Technology File System,NTFS)来改善文件系统的性能、可靠性和磁盘利用率等指标,但FAT32仍然占据有极大的使用场合,目前众多移动设备上的文件系统,如U盘、手机SD卡、PDA上的扩展存储器大多采用FAT32文件格式,因此,研究基于FAT32文件系统的文件隐藏具有应用价值。
在详细分析FAT32文件系统组织文件和Linux虚拟文件系统(Virtual File System,VFS)支持多种文件系统原理的基础上,本文基于FAT32管理文件和操作系统显示文件的相关机理,采用修改文件目录项有关属性和重构文件FAT表项序列排列结构等技术,在逻辑上改变文件簇的位置,提出了一种具有高隐藏强度的文件隐藏方法。同时,根据Linux操作系统对FAT32的支持,利用Linux内核提供的缓冲机制,在Linux系统上进行了实验验证。实验结果和分析表明,本文提出的方法不仅能实现与操作系统无关的文件隐藏,且相比已有方法,具有更好的隐藏效果,文件隐藏方法实现简单,没有较大增加技术难度和系统消耗,对现实应用具有一定意义。
1 FAT32文件系统简介
FAT32文件系统采用一种基于位示图的方法来实现对磁盘文件的管理和检索,并将簇(cluster)作为文件的分配计量单位,而一个具体文件也以磁盘簇的大小为单位,同样地被划分为若干个文件簇。在低于4 G的分区中,每簇一般包括8个扇区,共4 k字节。FAT32宏观上由3部分组成,即:引导记录区(Dos Boot Record,DBR)、FAT表和数据区,如图 1所示。引导记录区描述了FAT32文件系统总体的有关属性,如每个扇区的大小、每个簇所占有的扇区数等。FAT表以4个字节为单位作为一个表项,记录着簇的使用情况,按表项值的不同,可分为空簇未使用、已分配簇、坏簇、系统保留簇等类型。数据区是存放磁盘数据的具体区域,目录项文件和文件的具体内容都存放在该区域内。
图1 FAT32存储结构Fig.1 Storage structure of FAT32
FAT32实现对文件的有效管理,依赖于两个重要的元素:FAT表和目录项。FAT表实质上是一张磁盘空间分配情况登记表,它以簇号的方式记录了簇的分配情况。FAT表项和磁盘簇一一对应,由于一个文件在磁盘上不一定是连续存放,为了让整个文件在逻辑上形成一个连续的磁盘簇链,FAT32文件系统通过在磁盘簇所对应的FAT表项中记录下该簇的下一簇的磁盘簇号来达到上述目的。目录项是一个以32字节为单位、有特定含义的数据结构,新建的目录项被分配有一个磁盘簇。目录项存放在上层目录对应的磁盘簇中,记录了对应文件的有关属性,如文件的文件名、扩展名、文件创建时间等,其中与本文有关的重要属性有:字节偏移量为0BH处的“文件属性”、字节偏移量为14H~15H处的“文件起始簇号高16位”和字节偏移量为1AH~1BH的“文件起始簇号低16位”。
如图2所示,操作系统对文件进行访问时,总是先访问文件的目录项,得到文件的起始簇簇号,再找到该簇号对应的FAT表项,读取出其中的内容来得到下一簇的簇号,再在下一簇对应的FAT表项中找到再下一簇的簇号,以此类推,直到在FAT表项中找到文件最后一簇的标志0FFFFFFFH,对该文件的查找才结束。
图2 FAT32磁盘数据结构及进行文件隐藏后的结果Fig.2 Disk data structures of FAT32 and results of file hidden
2 一种基于FAT32的文件隐藏方法
文献[7]申请了一项基于FAT32文件隐藏的专利,其利用操作系统不显示卷标文件的基本原理,将待隐藏文件目录项中的“文件属性”字段修改为卷标属性值而实现文件隐藏。如用户想隐藏图2中的HiddenData.txt文件,则只需将目录项HiddenData.txt的第12个字节的第4位数据位置1(00001000)即可。该方法不受操作系统的限制,可实现永久隐藏,且隐藏速度不受文件大小影响,具有一定优势。但由于该方法主要是利用操作系统显示文件的有关原理,并没有从根本上改变文件的存储位置,因此,只要找出文件系统中多余的具有卷标属性的目录项,然后根据找到的目录项和FAT表便可以找到所有隐藏文件。
2.1 新方法的提出
由上述FAT32文件系统的介绍可知,操作系统查找文件在磁盘上的具体位置时,以FAT表项值为查找索引,故每一个文件都存在一个FAT表项序列。文献[7]存在的不足在于根据多余的具有卷标属性的目录项后便可以顺利获得隐藏文件,因此,若先将一个文件的FAT表项序列的排列结构保存起来,然后随机打乱重排该结构后再写回到FAT表中,那么即使找到了隐藏的目录项,由此目录项也无法顺利获得被隐藏的文件信息。基于此,本文提出了一种重构FAT表项序列的文件安全隐藏方法。
为了有效存储文件的FAT表项序列,本文先定义如下的序列比较规则:
根据以上比较规则,每种FAT表项序列的排列方案对应一个整数编号 N,且 N∈[1,k!]。
2.2 重构FAT表项序列的文件安全隐藏方法
在得到待隐藏文件的路径信息后,具体的隐藏步骤如下:1)根据路径名分离出每一层目录的名称;
2)读取DBR中有关属性的信息,得到根目录所在的磁盘簇号;
3)遍历根目录磁盘簇中的所有目录项,找到待隐藏文件第一层目录的目录项;
4)根据找到的目录项中的“文件起始簇号”找到该层目录的磁盘簇号;
5)搜索该层目录所对应的磁盘簇,得到下一层目录的目录项;
6)重复步骤4、5,直到找到待隐藏文件的最后一层目录的目录项;
7)在最后一层目录对应的磁盘簇中找到待隐藏文件的目录项,得到文件的起始簇号n1;
8)从FAT表中找到文件起始簇号对应的FAT表项,得到下一簇的磁盘簇号n2;
9)读取出FAT表中第n2个表项的表项值,即n3。如此循环,直到读取出来的FAT表项值为结束标记值0FFFFFFFH;
10)根据序列比较规则计算 n1、n2、n3…nm…对应的编号值N,修改待隐藏文件的目录项,使其具有卷标属性,同时,将目录项的“起始簇号”由n1修改为nm;
11)随机重排序列 n1、n2、n3…nm…,使其变为 nm、…,并将重排后的结果序列写回到对应FAT表项中;
12)返回编号值N给用户,作为用户以后获取隐藏文件的“访问密码”。文件隐藏结束。
例如,使用上述隐藏方案隐藏图2中的HiddenData.txt文件后,磁盘结构如图2右部所示。
当用户访问隐藏文件时,只需要输入“访问密码”,程序便可根据“访问密码”恢复FAT表项序列的正确排列顺序,从而正确访问文件。
2.3 对新方法的分析
文中提出的文件隐藏方法不仅不依赖于具体的操作系统,而且隐藏强度高。
虽然新方法仍然是基于操作系统不显示卷标文件的基本原理实现文件隐藏,但该方法通过修改目录项中的起始簇号和FAT表项序列的排列结构,即使找到了多余的具有卷标属性的目录项,由该目录项获得被隐藏文件也无法实现,这是因为依赖于打乱的FAT表项序列,被隐藏文件在磁盘上的逻辑存储位置被改变。
3 Linux对FAT32的支持
Linux通过VFS机制支持多种文件系统[8]。每个挂载到Linux系统下的文件系统都由一个super_block描述,其中的一个成员变量s_fs_info指向一个特定文件系统定义的super_block,对FAT32文件系统来说,这个结构就是msdos_sb_info。该结构体描述了FAT32文件系统的特有属性,当FAT32文件系统被挂载 (mount)时,内核通过调用fat_fill_super函数读取磁盘上的第一个扇区,并将相应参数填充到已分配的super_block,如此,便在内存中建立了该FAT32文件系统的所有描述信息,直到该文件系统被卸载(unmount)时,该 super_block 才会被销毁。
Linux操作系统中的每个文件都使用一个被定义为inode的结构体描述。FAT32文件系统的目录项在Linux中被定义为一个msdos_dir_entry结构体。为了与VFS接合,Linux内核根据从磁盘上读取的目录项信息,利用函数fat_fill_inode动态构建inode,而FAT32下的inode结构——msdos_inode_info,可通过函数 MSDOS_I(inode)得到。 其中,msdos_inode_info的成员域i_start指出了文件起始簇对应的磁盘簇号。
为保持从目录访问inode的高效率,Linux维护了表达路径与inode对应关系的目录项对象dentry,被操作系统访问过的目录项有关信息会被存入dentry结构中。每个文件或目录项都至少有一个dentry结构,操作系统通过dentry在内存中逐渐构建一棵描述物理磁盘上文件层次关系的树型目录。当同一目录被再次访问时,操作系统不需要重复访问磁盘进行逐级查找,而是先在内存中查找dentry组成的目录树,找到目标文件对应的dentry后,就可以根据结构体成员d_inode找到该文件对应的inode,进而进行与文件有关的各种操作。这种机制有效地减少了系统访问磁盘的次数,提高了系统的整体性能。
若想获得一个文件簇在磁盘中的具体位置,Linux内核并不是把整个FAT表读到内存中,然后从文件起始簇开始逐个查找FAT表。为了避免频繁读磁盘,它通过一个cache_lru链表来加快查找速度。cache_lru是msdos_inode_info的一个成员变量,它记录最近访问过的FAT表表项,每个链表元素为结构体fat_cache,fat_cache描述了一个文件簇在磁盘上的实际位置。内核调用函数fat_get_cluster查找一个文件簇在磁盘中的实际位置时,先通过fat_cache_lookup函数从cache_lru链表中查找,当链表中不存在时,才从磁盘FAT表中进行查找。因此,通过每个inode的fat_cache队列,系统可以快速获得文件在磁盘上的实际位置。
4 实验过程
文中提出的文件隐藏方法需要对FAT表项进行重构,故首先必须找到FAT表在磁盘中的具体位置,这通过采用sb_bread函数读取磁盘第一个扇区得到实现。DBR中的具体信息在Linxu中被定义为结构体fat_boot_sector,根据fat_boot_sector中的相关成员可获得FAT表的起始位置及其占有的磁盘扇区的大小。
获得一个路径对应的inode时,文中使用了函数open_namei,该函数可由路径得到相应的nameidata结构,进而可得到待隐藏文件的 inode; 根据 inode获得对应msdos_inode_info后,由它的成员i_start可得到文件的起始簇号,最后使用函数fat_ent_read可找到待隐藏文件的所有磁盘簇号序列。在Linux系统中,卷标属性被定义为一个宏:#define ATTR_VOLUME 8,为了修改目录项中的有关属性,文中使用了函数fat_notify_change,程序部分源代码如下所示。
为了验证上述方法的可行性,文中在Ubuntu10.04.4操作系统中挂载一个文件系统为FAT32的4G U盘后,执行上述程序,成功实现了文件隐藏,故上述方法具有实际可行性。
5 结束语
文中分析了FAT32文件系统基本原理和现有基于FAT32的文件隐藏方法,研究了Linux内核中有关FAT32的重要数据结构和函数,讨论了Linux通过VFS支持多种文件系统的机制。在此基础上,提出了一种新的文件隐藏方法,并在Linux操作系统上进行了具体实现。实验结果和分析表明,该方法不仅能实现高强度的文件隐藏,而且隐藏方法简单、轻量,只需修改部分FAT表项便能实现。将文中提出的文件隐藏方法与其他文件安全技术结合,运用到Android智能手机等资源有限的设备上的SD卡的文档保护中,是将来进一步的研究内容。
[1]刘安洁,崔广润.在Dos下恢复Windows回收站中的文件[J].科技情报开发与经济,2006,16(23):250-251.
LIU An-jie,CUI Guang-run.Recovering the files in windows recycle bin in DOS[J].Sci-Tech Information Development&Economy,2006,16(23):250-251.
[2]郭建伟.简单操作让文件隐藏更彻底[J].电脑迷,2010(20):61.
GUO Jian-wei.Simple operation makes files hidden more completely[J].PC Fan,2010(20):61.
[3]王全民,王淞,金华锋,等.基于Windows NT平台文件隐藏和检测系统的设计[J].计算机安全,2010(6):27-29.
WANG Quan-min,WANG Song,JIN Hua-feng,et al.The design of file hiding and detection system based on the windows NT platform [J].Network and Computer Security,2010(6):27-29.
[4]何耀彬,李祥和,孙岩.基于驱动堆栈单元的文件隐藏方法[J].计算机工程,2011,37(13):9-12.
HE Yao-bin,LI Xiang-he,SUN Yan.File hide method based on drive Stack unit[J].Computer Engineering,2011, 37(13):9-12.
[5]Microsoft Corporation.Microsoft extensible firmware initiative FAT32 file system specification:FAT:general overview of ondisk format[S].Version 1.03,December 6,2000.
[6]党潇瑜.一种轻量化FAT文件系统 [J].电子科技,2011(5):91-93.
DANG Xiao-yu.A lightweight FAT file system[J].Electronic Science and Technology,2011(5):91-93.
[7]华中科技大学.基于 FAT32磁盘文件系统结构的文件隐藏方法:中国,ZL03118544.4[P].2003:1-9.
[8]敖青云.存储技术原理分析:基于Linux 2.6内核源代码[M].北京:电子工业出版社,2011.