当前位置:编程学习 > Delphi >>

用Delphi编写U盘整盘数据清除程序

由于U盘小巧易携、使用方便、容量适度,使用频度较其他移动存储介质要高,信息安全隐患也要大得多。黑客、病毒和木马都将目标瞄准了移动存储介质特有的“信息安全软肋”,目前移动存储介质的摆渡、木马、远程控制程序多达百种,很多还采用了隐藏技术,防护的难度越来越大。一般的删除不能使原文档彻底清除,有时甚至是“文件粉碎”这样的工具也不能保证万无一失,因为像很多Word这样的应用软件在打开文档时,会生成一个临时文件,所有操作都在临时文件上进行,只在关闭时才将临时文件拷回到原文件的名录上。这样,在一个存储介质上会存在多个“有实无名”的隐身文档副本,没有名录信息对操作系统而言是不可见的,一般方法访问不到,但是通过特殊的技术可以将“实体”的大部分内容恢复。因此,针对U盘流动性大、数据易泄漏的特点,在保护隐私、跨网使用和清除摆渡泄密的需求下,开发出对U盘数据安全可靠清除的程序很有必要。目前市场上的数据清除设备动辄上万元,基本上是使用嵌入式系统开发的专用产品,本文介绍的方法和程序在原理和实际效果上与其没有差别,在某些方面甚至有更好的拓展性、适应性和灵活性。当然,技术到产品的跃升还需做很多艰苦的工作,希望此文能抛砖引玉、与大家共享技术带来的便利。
 
2 文件系统的原理
无论是FAT还是NTFS文件系统,尽管安全机制和存取的效率差别很大,但是原理基本相同,都是由索引部分和文件数据实体部分组成,索引提供名录的有效存取、检索,数据实体存放文件的真正内容。为了提高文件系统对文件处理的效率,在删除文件时并不是将上述的两部分全部消除,只是在索引部分标记为“已删除”,而文件的实体数据依然原封不动地存在介质上,从表面上已经查不到这些删除文件的存在,但是通过一定的方法,还是可以一定程度上进行恢复,这是多种文件恢复工具的工作原理。
即使采用高级格式化,也只是将文件系统的索引部分清除,而数据实体部分基本上没有涉及,仍可进行数据恢复和提取。
 
3 U盘的特点
U盘与磁介质移动盘不同,U盘是内部的FLASH(电可擦除芯片组)的电荷来维持电位高低,从而进行二进制数据存储的,一旦电荷发生变化,则二进制数据也会发生根本性的改变,或者说物理上不太可能恢复和还原。但是磁介质不同,由于每次的磁头位置不可能完全重合,可能会有微弱的磁化残留,也就是上一次写的数据虽然被覆盖,在磁力显微镜下仍可看出其残留的痕迹,至于是否能将被覆盖的上一次信息完整地恢复出来,学术界目前争论不休,鲜见实测检验的权威报告。光介质存储也存在类似的问题,只是使用频度远低于前两者,还未引起重视。

U盘因为电荷清除后信息就消失了,不会有类似弱磁残留的问题,可以保证清除效果。
 
4 关键技术
4.1 U盘容量的获取
获取U盘容量有两个API函数,第一个是:
GetDiskFreeSpaceEx(Directory:PChar;var FreeAvailable,TotalSpace:TLargeInteger;TotalFree: PLargeInteger): Bool;//此函数在SysUtils单元
这个函数返回的容量(int64类型变量TotalSpace所返回的值)就是U盘标写的容量,但是这个函数必须是在U盘已经格式化后才能正常工作,否则返回的容量是错误值。
另一个函数是:
DeviceIoControl(hDevice: THandle; dwIoControlCode: DWORD; lpInBuffer: Pointer;nInBufferSize: DWORD;lpOutBuffer: Pointer; nOutBufferSize: DWORD;var lpBytesReturned: DWORD; lpOverlapped: POverlapped): BOOL;//这个函数在Windows单元。
这个函数是向设备级发送请求,返回的是底层设备的原始值。在使用这个函数时,不要求U盘设备已经格式化,在“属性”里的“文件系统”一栏可以显示为“RAW”,即没有任何格式的移动盘。笔者在实验中发现,这个函数是在设备层进行请求,有时在资源管理器中不显示该盘符时,使用物理硬设备符(如用文件方式打开设备生成句柄hDevice时,用'\\.\PHYSICALDRIVE1'而不是'\\.\u:'),仍然可以得到U盘的容量,这对U盘数据恢复很有意义。但是这个函数与前一个函数相比,其返回的容量总是小于前函数的结果,并且没有规律。
4.2 真实容量分析
要对U盘进行完全彻底的数据清除,首先必须要知道它的容量。由于U盘本身的特性,一般在商标上标写的容量并不一定是真正的容量。原因有三:1、正规品牌的U盘标写的是正常使用的容量,在其内部还有一部分是作为坏区补偿的备用容量,当检测有坏片时,U盘内部的电路会将坏区与补偿部分进行互相置换,所以其真正容量会大于标写的容量;2、某些不良商家会将小容量的U盘Mask成大容量的盘,这时所注的容量也不正确;3、目前很多黑客、木马会将大容量的U盘改写成小容量,使一部分存储区成为一般手段无法访问的隐蔽区,作为恶意信息的真正藏身地。表面上似乎如何检测U盘真正的容量是关键,实质上能否完全清除U盘上的所有存储信息才是安全保障的根本所在。
4.3 覆盖U盘所有存储空间
由上可知,无论哪个函数,包括系统显示的的容量,都不是U盘真正的容量,而且多出来的容量不同厂家的产品各不相同。笔者通过测试,发现多出来的容量和额定的容量在连续的地址空间,即多出来的部分紧接在额定的后面。
因此,有效的解决方法是:当清除到额定容量时,并不停止,继续清除,直到发生“写错误”时才退出清除过程。(笔者曾对一枚128M的U盘清除到135M时才显示清除完毕)
看到这里读者可能会问:如果用这种解决方法,获取U盘容量有什么意义?实际上获取容量是为了大概估算清除时间,在程序设计时进度条控件需要总量来计算进度的百分比,前述介绍的U盘容量获取的结果与真实容量差别不大,可以作为参考值。
 
5 主要代码实现
5.1 程序界面与控件布局\
      

                                                                          图5-1
 
 
5.2 搜索当前在线的U盘
因为U盘的数据清除与移动硬盘不同,U盘可以从逻辑的0扇区开始一直清除下去,
 
 
 
 
 
也就是从活动分区DBR开始清除下去,U盘一般没有硬盘引导扇区MBR,即使有也可以进行清除,而移动硬盘不能从从MBR开始清除,因为MBR扇区里存有划分的多个分区的信息和整个硬盘的容量信息。从设备检测来说,U盘属于移动设备(DRIVE_REMOVABLE),而移动硬盘属性仍然是固定设备(DRIVE_FIXED),关于移动硬盘的数据清除将另文介绍。
搜索当前在线的U盘列表的程序代码如下:
procedure TForm1.Button1Click(Sender: TObject);
var
   buf:array [0..MAX_PATH-1] of char;
   m_Result:Integer;
   i:Integer;
   str_temp:string;
begin
 m_Result:=GetLogicalDriveStrings(MAX_PATH,buf);
//获取当前逻辑驱动器的排列和数量
 ListBox1.Items.Clear;
 for i:=0 to (m_Result div 4) do
 begin
   str_temp:=string(buf[i*4]+buf[i*4+1]+buf[i*4+2]);
if GetDriveType(pchar(str_temp)) = DRIVE_REMOVABLE then
//这里确定是U盘驱动器符
    begin
      //ShowMessage(str_temp+'盘为U盘');
      ListBox1.Items.Add(str_temp);
    end;
 end;
end;
 
5.3 容量估算与显示
对ListBox1的OnClick事件进行处理,一方面保证所处理的盘肯定是U盘,另一方面可以确认清除的目标盘无误,因为数据是永久性的清除,无法恢复。
事件处理程序如下:
procedure TForm1.ListBox1Click(Sender: TObject);
var
  dr:string;
  i,j,k:Integer;
 c: Char;
 totalsize:int64;
 userFreeBytes,totalBytes,freeBytes:Int64;
 nOutput:ULONG;
 actget:DWORD;
 getbuff:DISK_GEOMETRY;
 fbuf:pchar;
begin
  i:=ListBox1.ItemIndex;//当前U盘列表 www.zzzyk.com
  dr:=copy(ListBox1.Items[i],1,1);//查找逻辑盘符第一个字母
  driver:=pchar('\\.\'+dr+':'); //这里也可以用硬件设备名
//如'\\.\PHYSICALDRIVE1'
  hDeviceHandle := CreateFile(driver, GENERIC_ALL, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING,0, 0);
  if (hDeviceHandle<> INVALID_HANDLE_VALUE) then
  begin
   DeviceIoControl(hDeviceHandle,
                   IOCTL_DISK_GET_DRIVE_GEOMETRY,
            
补充:软件开发 , Delphi ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,