找回密码
 用户注册

QQ登录

只需一步,快速开始

查看: 6023|回复: 0

[原]VC++信息安全编程(16)安全删除NTFS磁盘数据文件

[复制链接]
发表于 2012-3-8 15:04:43 | 显示全部楼层 |阅读模式
很多时候,为了保护商业秘密,一些文件仅仅许可出现一次,就必须删除。
但是windows的删除是不完善的,可以通过回收站找回,即使windows的彻底删除,也不是彻底删除。也可以通过数据恢复软件找回,
我们如何实现彻底删除,用二进制数据填充磁盘,来彻底清除相关数据呢
我们来亲身实践360自带的功能。
详细类源码如下,请见源码分析,安全删除NTFS file:
  1. #include "stdafx.h"
  2. #include "SecureDelNTFS.h"
  3. #include <time.h>
  4. #ifdef _DEBUG
  5. #undef THIS_FILE
  6. static char THIS_FILE[]=__FILE__;
  7. #define new DEBUG_NEW
  8. #endif
  9. #define OVERWRITE_PASSES 1
  10. #define BUFFER_SIZE 1024
  11. //////////////////////////////////////////////////////////////////////
  12. // Construction/Destruction
  13. //////////////////////////////////////////////////////////////////////
  14. CSecureDelNTFS::CSecureDelNTFS()
  15. {
  16.         Recurse = true;
  17.         ZapFreeSpace = true;
  18.         CleanCompressedFiles = FALSE;
  19.         NumPasses = 1;
  20.         FilesFound = 0;
  21.         firstCall = false;
  22.         deleteDirectories = false;
  23.         //  以系统时间为种子构造随机数
  24.         srand( (unsigned)time( NULL ));
  25. }
  26. CSecureDelNTFS::~CSecureDelNTFS()
  27. {
  28. }
  29. /////////////////////////////////////////////////////////////////////////////
  30. // 函数名:  OverwriteFileName( PTCHAR FileName, PTCHAR LastFileName )
  31. // 参数列表:PTCHAR FileName
  32. //                         PTCHAR LastFileName
  33. // 函数功能:该函数的功能是安全删除文件名
  34. /////////////////////////////////////////////////////////////////////////////
  35. VOID CSecureDelNTFS::OverwriteFileName( PTCHAR FileName, PTCHAR LastFileName )
  36. {
  37.         TCHAR                newName[MAX_PATH];
  38.         PTCHAR                lastSlash;
  39.         DWORD                i, j, index;
  40.         _tcscpy( LastFileName, FileName );
  41.         lastSlash = _tcsrchr( LastFileName, _T('\\'));
  42.         index = (lastSlash - LastFileName)/sizeof(TCHAR);
  43.         //  产生一个新的名称
  44.         CString sz="abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
  45.         if(index>125)
  46.                 sz=sz.Left((130-(index-125)));
  47.         CString NewName=((CString) LastFileName).Left(index)+"\"+CryptString(sz);
  48.         sprintf(LastFileName,"%s",NewName);
  49.         MoveFile( FileName, NewName );
  50.        
  51.         _tcscpy( LastFileName, NewName );
  52.         lastSlash = _tcsrchr( LastFileName, _T('\\'));
  53.         index = (lastSlash - LastFileName)/sizeof(TCHAR);
  54.         int k=_tcsclen( LastFileName );
  55.         _tcscpy( newName, NewName );
  56.         int number=rand()*20/32767+2;
  57.         for( i = 0; i < number; i++ )
  58.         {
  59.                 //        用随机产生的符号替换文件名中非'.'符号
  60.                 for( j = index+1 ; j < _tcsclen( LastFileName ); j++ )
  61.                 {
  62.                         if( LastFileName[j] != _T('.'))       
  63.                         {
  64.                                 int random=int((rand()*74/32767));
  65.                                 if(random>=10 && random<=16)        random=17;
  66.                                 if(random>=43 && random<=48)        random=49;
  67.                                 newName[j] = (TCHAR) random + _T('0');  
  68.                         }
  69.                 }
  70.                 //        用产生的新名称重命名
  71.                 MoveFile( LastFileName, newName );
  72.                 _tcscpy( LastFileName, newName );
  73.         }
  74. }
  75. /////////////////////////////////////////////////////////////////////////////
  76. // 函数名:  OverwriteDirectoryName( PTCHAR FileName, PTCHAR LastFileName )
  77. // 参数列表:PTCHAR FileName
  78. //                         PTCHAR LastFileName
  79. // 函数功能:该函数的功能是安全删除文件名
  80. /////////////////////////////////////////////////////////////////////////////
  81. VOID CSecureDelNTFS::OverwriteDirectoryName( PTCHAR FileName, PTCHAR LastFileName )
  82. {
  83.         TCHAR                newName[MAX_PATH];
  84.         PTCHAR                lastSlash;
  85.         DWORD                i, j, index;
  86.         _tcscpy( LastFileName, FileName );
  87.         lastSlash = _tcsrchr( LastFileName, _T('\\'));
  88.         index = (lastSlash - LastFileName)/sizeof(TCHAR);
  89.         //  产生一个新的名称
  90.         CString NewName=((CString) LastFileName).Left(index)+"\"+CryptString("abcdefgh.XYZ");
  91.         sprintf(LastFileName,"%s",NewName);
  92.         MoveFile( FileName, NewName );
  93.        
  94.         _tcscpy( LastFileName, NewName );
  95.         lastSlash = _tcsrchr( LastFileName, _T('\\'));
  96.         index = (lastSlash - LastFileName)/sizeof(TCHAR);
  97.         int k=_tcsclen( LastFileName );
  98.         _tcscpy( newName, NewName );
  99.         int number=rand()*20/32767+2;
  100.         for( i = 0; i < number; i++ )
  101.         {
  102.                 //        用随机产生的符号替换文件名中非'.'符号
  103.                 for( j = index+1 ; j < _tcsclen( LastFileName ); j++ )
  104.                 {
  105.                         if( LastFileName[j] != _T('.'))       
  106.                         {
  107.                                 int random=int((rand()*74/32767));
  108.                                 if(random>=10 && random<=16)        random=17;
  109.                                 if(random>=43 && random<=48)        random=49;
  110.                                 newName[j] = (TCHAR) random + _T('0');  
  111.                         }
  112.                 }
  113.                 //        用产生的新名称重命名
  114.                 MoveFile( LastFileName, newName );
  115.                 _tcscpy( LastFileName, newName );
  116.         }
  117. }
  118. /////////////////////////////////////////////////////////////////////////////
  119. // 函数名:  CryptString(CString string)
  120. // 参数列表:CString string
  121. // 函数功能:该函数的功能是根据已有的字符串产生一个加密的字符串
  122. /////////////////////////////////////////////////////////////////////////////
  123. CString CSecureDelNTFS::CryptString(CString string)
  124. {
  125.         TCHAR                FirstString[MAX_PATH];       
  126.         _tcscpy( FirstString, string );
  127.         srand( (unsigned)time( NULL ) );
  128.         //        产生一个随机字符替换字符串中非'.'字符
  129.         for( int j = 0 ; j < _tcsclen( FirstString ); j++ )
  130.         {
  131.                 if( FirstString[j] != _T('.'))               
  132.                 {
  133.                         int random=int((rand()*74/32767));
  134.                         if(random>=10 && random<=16)        random=17;
  135.                         if(random>=43 && random<=48)        random=49;
  136.                         FirstString[j] = (TCHAR) random + _T('0');  
  137.                 }
  138.         }
  139.         return (CString) FirstString;
  140. }
  141. /////////////////////////////////////////////////////////////////////////////
  142. // 函数名:  SecureOverwrite( HANDLE FileHandle, DWORD Length )
  143. // 参数列表:HANDLE FileHandle
  144. //                         DWORD Length
  145. // 函数功能:该函数的功能是安全删除文件
  146. /////////////////////////////////////////////////////////////////////////////
  147. BOOLEAN CSecureDelNTFS::SecureOverwrite( HANDLE FileHandle, DWORD Length )
  148. {
  149. #define CLEANBUFSIZE 65536
  150.         static PBYTE        cleanBuffer[3];
  151.         static BOOLEAN        buffersAlloced = FALSE;
  152.         DWORD                i, j, passes;
  153.         DWORD                bytesWritten, bytesToWrite, totalWritten;
  154.         LONG                seekLength;
  155.         BOOLEAN                status;
  156.         //        分配执行清除操作所需的缓冲区
  157.         if( !buffersAlloced )
  158.         {
  159.                 //        设置系统时间为随机数种子
  160.                 srand( (unsigned)time( NULL ) );
  161.                 for( i = 0; i < 3; i++ )
  162.                 {
  163.                         //  设置清除缓冲区内容
  164.                         cleanBuffer[i] = (unsigned char *)VirtualAlloc( NULL, CLEANBUFSIZE, MEM_COMMIT, PAGE_READWRITE );
  165.                         if( !cleanBuffer[i] )
  166.                         {
  167.                                 for( j = 0; j < i; j++ )
  168.                                 {
  169.                                         VirtualFree( cleanBuffer[j], 0, MEM_RELEASE );
  170.                                 }
  171.                                 return FALSE;
  172.                         }
  173.                         switch( i )
  174.                         {
  175.                         case 0:
  176.                                 // 缓冲区内容为0
  177.                                 break;
  178.                         case 1:
  179.                                 // 缓冲区内容为0 - 0xFF
  180.                                 memset( cleanBuffer[i], 0x00, CLEANBUFSIZE );
  181.                                 break;
  182.                         case 2:
  183.                                 // 缓冲区内容为随机值
  184.                                 for( j = 0; j < CLEANBUFSIZE; j++ ) cleanBuffer[i][j] = (BYTE) rand();
  185.                                 break;
  186.                         }
  187.                 }       
  188.                 buffersAlloced = TRUE;
  189.         }
  190.         // 执行覆盖操作
  191.         seekLength = (LONG) Length;
  192.         for( passes = 0; passes < NumPasses; passes++ )
  193.         {
  194.                 if( passes != 0 )
  195.                 {
  196.                         // 将指针设置为最开始
  197.                         SetFilePointer( FileHandle, -seekLength, NULL, FILE_CURRENT );
  198.                 }
  199.                 for( i = 0; i < 2; i++ )
  200.                 {
  201.                         // 将指针设置为最开始
  202.                         if( i != 0 )
  203.                         {
  204.                                 SetFilePointer( FileHandle, -seekLength, NULL, FILE_CURRENT );
  205.                         }
  206.                         // 循环并覆盖
  207.                         bytesToWrite = Length;
  208.                         totalWritten = 0;
  209.                         while( totalWritten < Length )
  210.                         {
  211.                                 bytesToWrite = Length - totalWritten;
  212.                                 if( bytesToWrite > CLEANBUFSIZE ) bytesToWrite = CLEANBUFSIZE;
  213.                                 status = WriteFile( FileHandle, cleanBuffer[i], bytesToWrite, &bytesWritten, NULL );
  214.                                 if( !status ) return FALSE;
  215.                                 totalWritten += bytesWritten;
  216.                         }
  217.                 }
  218.         }
  219.         return TRUE;
  220. }
  221. /////////////////////////////////////////////////////////////////////////////
  222. // 函数名:  SecureDelete( PTCHAR FileName, DWORD FileLengthHi,        DWORD FileLengthLo )
  223. // 参数列表:PTCHAR FileName
  224. //                         DWORD FileLengthHi
  225. //                         DWORD FileLengthLo
  226. //                         DWORD Length
  227. // 函数功能:该函数的功能是安全删除指定的文件
  228. /////////////////////////////////////////////////////////////////////////////
  229. VOID CSecureDelNTFS::SecureDelete( PTCHAR FileName, DWORD FileLengthHi,
  230.                                         DWORD FileLengthLo )
  231. {
  232.         HANDLE        hFile;
  233.         ULONGLONG bytesToWrite, bytesWritten;
  234.         ULARGE_INTEGER fileLength;
  235.         TCHAR   lastFileName[MAX_PATH];
  236.         //        首先以覆盖的模式打开文件
  237.         hFile = CreateFile( FileName, GENERIC_WRITE,
  238.                                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
  239.                                                 NULL, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH, NULL );
  240.         if( hFile == INVALID_HANDLE_VALUE )
  241.                 return;
  242.         // 如果文件的长度不为零,则将文件所占的所有簇填入0
  243.         if( FileLengthLo || FileLengthHi )
  244.         {
  245.                 //  找文件的后一簇
  246.                 FileLengthLo--;
  247.                 if( FileLengthLo == (DWORD) -1 && FileLengthHi ) FileLengthHi--;
  248.                 SetFilePointer( hFile, FileLengthLo, (long *) &FileLengthHi, FILE_BEGIN );
  249.                 // 在文件中填入0
  250.                 if( !SecureOverwrite( hFile, 1 ))
  251.                 {
  252.                         CloseHandle( hFile );
  253.                         return;
  254.                 }
  255.                 // 回到文件的头部,处理文件剩下的部分
  256.                 SetFilePointer( hFile, 0, NULL, FILE_BEGIN );
  257.                 fileLength.LowPart = FileLengthLo;
  258.                 fileLength.HighPart = FileLengthHi;
  259.                 bytesWritten = 0;
  260.                 while( bytesWritten < fileLength.QuadPart )
  261.                 {
  262.                         bytesToWrite = min( fileLength.QuadPart - bytesWritten, 65536 );
  263.                         if( !SecureOverwrite( hFile, (DWORD) bytesToWrite ))
  264.                         {
  265.                                 CloseHandle( hFile );
  266.                                 return;
  267.                         }
  268.                         bytesWritten += bytesToWrite;
  269.                 }
  270.         }
  271.         //  完成后关闭文件
  272.         CloseHandle( hFile );
  273.         //  重命名文件
  274.         OverwriteFileName( FileName, lastFileName );
  275.         //  删除文件
  276.         if( !DeleteFile( lastFileName ) )
  277.                 return;
  278. }
  279. /////////////////////////////////////////////////////////////////////////////
  280. // 函数名:  BOOLEAN CSecureDelNTFS::ScanFile( HANDLE VolumeHandle,  DWORD ClusterSize,
  281. //                                  HANDLE FileHandle, PBOOLEAN ReallyCompressed, PBOOLEAN ZappedFile )
  282. // 参数列表:ANDLE VolumeHandle
  283. //           DWORD ClusterSize
  284. //           HANDLE FileHandle
  285. //           PBOOLEAN ReallyCompressed
  286. //           PBOOLEAN ZappedFilePTCHAR
  287. // 函数功能:该函数的功能是当NTFS卷是压缩、加密时调用进行文件扫描
  288. /////////////////////////////////////////////////////////////////////////////
  289. BOOLEAN CSecureDelNTFS::ScanFile( HANDLE VolumeHandle,  DWORD ClusterSize,
  290.                                   HANDLE FileHandle, PBOOLEAN ReallyCompressed, PBOOLEAN ZappedFile )
  291. {
  292.         DWORD                                                status;
  293.         int                                                        i;
  294.         IO_STATUS_BLOCK                                ioStatus;
  295.         ULONGLONG                                        startVcn, prevVcn;
  296.         LARGE_INTEGER                                clusterOffset;
  297.         ULONGLONG                                        endOfPrevRun;
  298.         PGET_RETRIEVAL_DESCRIPTOR        fileMappings;
  299.         ULONGLONG                                        fileMap[ FILEMAPSIZE ];
  300.         int                                                        lines = 0;
  301.         // 假设文件位于MFT记录中
  302.         *ReallyCompressed = FALSE;
  303.         *ZappedFile = FALSE;
  304.         startVcn = 0;
  305.         endOfPrevRun = LLINVALID;
  306.         fileMappings = (PGET_RETRIEVAL_DESCRIPTOR) fileMap;
  307.         while( !(status = NtFsControlFile( FileHandle, NULL, NULL, 0, &ioStatus,
  308.                                                 FSCTL_GET_RETRIEVAL_POINTERS,
  309.                                                 &startVcn, sizeof( startVcn ),
  310.                                                 fileMappings, FILEMAPSIZE * sizeof(ULONGLONG) ) ) ||
  311.                          status == STATUS_BUFFER_OVERFLOW ||
  312.                          status == STATUS_PENDING )
  313.         {
  314.                 // 如果操作正在进行,则等待完成
  315.                 if( status == STATUS_PENDING )
  316.                 {
  317.                         WaitForSingleObject( FileHandle, INFINITE );
  318.                         // 获取状态参数
  319.                         if( ioStatus.Status != STATUS_SUCCESS && ioStatus.Status != STATUS_BUFFER_OVERFLOW )
  320.                         {
  321.                                 return ioStatus.Status == STATUS_SUCCESS;
  322.                         }
  323.                 }
  324.                 startVcn = fileMappings->StartVcn;
  325.                 prevVcn  = fileMappings->StartVcn;
  326.                 for( i = 0; i < (ULONGLONG) fileMappings->NumberOfPairs; i++ )
  327.                 {         
  328.                         if( fileMappings->Pair[i].Lcn != LLINVALID )
  329.                         {
  330.                                 // 压缩模式
  331.                                 *ReallyCompressed = TRUE;
  332.                                 // 覆盖所在的簇
  333.                                 if( VolumeHandle != INVALID_HANDLE_VALUE )
  334.                                 {
  335.                                         clusterOffset.QuadPart = fileMappings->Pair[i].Lcn * ClusterSize;
  336.                                         SetFilePointer( VolumeHandle, clusterOffset.LowPart,
  337.                                                                         &clusterOffset.HighPart, FILE_BEGIN );
  338.                                         if( !SecureOverwrite( VolumeHandle,
  339.                                                                         ClusterSize * (DWORD) (fileMappings->Pair[i].Vcn - startVcn) ))
  340.                                                 return TRUE;
  341.                                 }
  342.                                 else
  343.                                         return TRUE;       
  344.                         }
  345.                         startVcn = fileMappings->Pair[i].Vcn;
  346.                 }
  347.                 if( !status ) break;
  348.         }
  349.         if( status == STATUS_SUCCESS ) *ZappedFile = TRUE;
  350.         return status == STATUS_SUCCESS;
  351. }
  352. /////////////////////////////////////////////////////////////////////////////
  353. // 函数名:  SecureDeleteCompressed( PTCHAR FileName )
  354. // 参数列表:PTCHAR FileName
  355. // 函数功能:该函数的功能是删除压缩磁盘中的文件
  356. /////////////////////////////////////////////////////////////////////////////
  357. BOOLEAN CSecureDelNTFS::SecureDeleteCompressed( PTCHAR FileName )
  358. {
  359.         HANDLE                        hFile;
  360.         BOOLEAN                        reallyCompressed = FALSE;
  361.         BOOLEAN                        zappedFile = FALSE;
  362.         TCHAR                        lastFileName[MAX_PATH];
  363.         static TCHAR        volumeName[] = _T("\\\\.\\A:");
  364.         static TCHAR        volumeRoot[] = _T("A:\");
  365.         static HANDLE        hVolume = INVALID_HANDLE_VALUE;
  366.         static DWORD        clusterSize;
  367.         DWORD                        sectorsPerCluster, bytesPerSector, freeClusters, totalClusters;
  368.         // 打开卷
  369.         if( hVolume == INVALID_HANDLE_VALUE )
  370.         {
  371.                 volumeName[4] = FileName[0];
  372.                 hVolume = CreateFile( volumeName, GENERIC_READ|GENERIC_WRITE,
  373.                                                         FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
  374.                                                         0, 0 );
  375.                 volumeRoot[0] = FileName[0];
  376.                 GetDiskFreeSpace( volumeRoot, §orsPerCluster, &bytesPerSector,
  377.                                                 &freeClusters, &totalClusters );
  378.                 clusterSize = bytesPerSector * sectorsPerCluster;
  379.         }
  380.         // 打开文件
  381.         hFile = CreateFile( FileName, GENERIC_READ,
  382.                                                 0,NULL, OPEN_EXISTING, 0, NULL );
  383.         if( hFile == INVALID_HANDLE_VALUE )
  384.                 return TRUE;
  385.         // 确定文件的位置
  386.         if( !ScanFile( hVolume, clusterSize, hFile,
  387.                         &reallyCompressed, &zappedFile ))
  388.         {
  389.                 CloseHandle( hFile );
  390.                 return TRUE;
  391.         }
  392.         // 关闭文件
  393.         CloseHandle( hFile );
  394.         if( reallyCompressed )
  395.         {
  396.                 // 重新命名文件名
  397.                 OverwriteFileName( FileName, lastFileName );
  398.                 //  文件长度修改为0
  399.                 FILE *fp=fopen(lastFileName,"w");
  400.                 fclose(fp);
  401.                 //  删除文件
  402.                 if( !DeleteFile( lastFileName ))
  403.                 {
  404.                         MoveFile( lastFileName, FileName );
  405.                         return TRUE;
  406.                 }
  407.                 // 如果不能直接覆盖文件的簇,则通过清除磁盘的自由空间来覆盖
  408.                 if( !zappedFile ) CleanCompressedFiles = TRUE;
  409.         }
  410.         return reallyCompressed;
  411. }
  412. /////////////////////////////////////////////////////////////////////////////
  413. // 函数名:  ProcessFile( PWIN32_FIND_DATA FindData, TCHAR *FileName )
  414. // 参数列表:PWIN32_FIND_DATA FindData
  415. //                         TCHAR *FileName
  416. // 函数功能:该函数的功能是处理文件的删除
  417. /////////////////////////////////////////////////////////////////////////////
  418. VOID CSecureDelNTFS::ProcessFile( PWIN32_FIND_DATA FindData, TCHAR *FileName )
  419. {
  420.         // 如果是目录的删除,则直接返回
  421.         if( FindData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) return;
  422.         FilesFound++;
  423.         // 如果文件是压缩的
  424.         if( FindData->dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED ||
  425.                 FindData->dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED  ||
  426.                 FindData->dwFileAttributes & FILE_ATTRIBUTE_SPARSE_FILE )
  427.         {
  428.                 // 处理压缩磁盘中的文件
  429.                 if( SecureDeleteCompressed( FileName )) return;
  430.         }
  431.         // 删除常规(非压缩、非加密磁盘)文件
  432.         SecureDelete( FileName, FindData->nFileSizeHigh,
  433.                                                         FindData->nFileSizeLow );
  434. }
  435. /////////////////////////////////////////////////////////////////////////////
  436. // 函数名:  ProcessDirectory( TCHAR *PathName, TCHAR *SearchPattern )
  437. // 参数列表:TCHAR *PathName
  438. //                         TCHAR *SearchPattern
  439. // 函数功能:该函数的功能是处理目录的删除
  440. /////////////////////////////////////////////////////////////////////////////
  441. void CSecureDelNTFS::ProcessDirectory( TCHAR *PathName, TCHAR *SearchPattern )
  442. {
  443.         TCHAR                        subName[MAX_PATH], fileSearchName[MAX_PATH], searchName[MAX_PATH];
  444.         HANDLE                        dirHandle, patternHandle;
  445.         WIN32_FIND_DATA foundFile;
  446.         TCHAR                        lastFileName[MAX_PATH];
  447.         // 遍历所有的文件和目录
  448.         if( firstCall )
  449.         {
  450.                 if( _tcsrchr( PathName, '*' ) )
  451.                 {
  452.             if( _tcsrchr( PathName, '\\' ) )
  453.                         {
  454.                 _stprintf( SearchPattern, _tcsrchr( PathName, '\\' )+1 );
  455.                 _tcscpy( searchName, PathName );
  456.                 _tcscpy( _tcsrchr( searchName, '\\')+1, _T("*.*") );
  457.                                 if( !_tcscmp( SearchPattern, _T("*.*")) || !_tcscmp( SearchPattern, _T("*")))
  458.                                 {
  459.                                         deleteDirectories = TRUE;
  460.                                 }
  461.             }
  462.                         else
  463.                         {
  464.                 _stprintf( SearchPattern, PathName );
  465.                 _tcscpy( searchName, PathName );
  466.             }
  467.             _stprintf( fileSearchName, _T("%s"), PathName );
  468.                 }
  469.                 else
  470.                 {
  471.                         _stprintf( SearchPattern, _T("*.*") );
  472.                         _stprintf( searchName, _T("%s"), PathName );
  473.             _stprintf( fileSearchName, _T("%s"), PathName );
  474.                         deleteDirectories = TRUE;
  475.                 }
  476.         }
  477.         else
  478.         {
  479.                 _stprintf( searchName, _T("%s\\*.*"), PathName );
  480.                 _stprintf( fileSearchName, _T("%s\\%s"), PathName, SearchPattern );
  481.         }
  482.         // 处理所有的文件
  483.         if( (patternHandle = FindFirstFile( fileSearchName, &foundFile )) !=
  484.                 INVALID_HANDLE_VALUE  )
  485.         {
  486.                 do
  487.                 {
  488.                         if( _tcscmp( foundFile.cFileName, _T(".") ) &&        _tcscmp( foundFile.cFileName, _T("..") ))
  489.                         {
  490.                                 _tcscpy( subName, searchName );
  491.                                 if( _tcsrchr( subName, '\\' ) )
  492.                                         _tcscpy( _tcsrchr( subName, '\\')+1, foundFile.cFileName );
  493.                                 else
  494.                                         _tcscpy( subName, foundFile.cFileName );
  495.                                 // 处理文件
  496.                                 ProcessFile( &foundFile, subName );
  497.                         }
  498.                 }
  499.                 while( FindNextFile( patternHandle, &foundFile ));
  500.                 FindClose( patternHandle );
  501.         }
  502.         // 进行递归删除
  503.         if( Recurse )
  504.         {
  505.         if( firstCall && !_tcsrchr( searchName, L'\\') )
  506.                 {
  507.             if( _tcsrchr( searchName, L'*' ))
  508.                         {
  509.                 if( (dirHandle = FindFirstFile( _T("*.*"), &foundFile )) == INVALID_HANDLE_VALUE)
  510.                     return;
  511.             }
  512.                         else
  513.                         {
  514.                 if( (dirHandle = FindFirstFile( searchName, &foundFile )) == INVALID_HANDLE_VALUE)
  515.                     return;
  516.             }
  517.         }
  518.                 else
  519.                 {
  520.             if( (dirHandle = FindFirstFile( searchName, &foundFile )) == INVALID_HANDLE_VALUE)
  521.                 return;
  522.         }
  523.         firstCall = FALSE;
  524.                 do
  525.                 {
  526.                         if( (foundFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
  527.                                 _tcscmp( foundFile.cFileName, _T(".") ) &&
  528.                                 _tcscmp( foundFile.cFileName, _T("..") ))
  529.                         {
  530.                                 _tcscpy( subName, searchName );
  531.                                 if( _tcsrchr( subName, '\\' ) )
  532.                                         _tcscpy( _tcsrchr( subName, '\\')+1, foundFile.cFileName );
  533.                                 else
  534.                                         _tcscpy( subName, foundFile.cFileName );
  535.                                 // 处理目录
  536.                                 ProcessDirectory( subName, SearchPattern );
  537.                                 // 删除目录
  538.                                 if( deleteDirectories )
  539.                                 {
  540.                                         //  重新命名文件名
  541.                                         OverwriteDirectoryName( subName, lastFileName );
  542.                                         SetFileAttributes(lastFileName,FILE_ATTRIBUTE_NORMAL);
  543.                                         RemoveDirectory( lastFileName );
  544.                                 }
  545.                         }
  546.                 }
  547.                 while( FindNextFile( dirHandle, &foundFile ));
  548.                 FindClose( dirHandle );
  549.         }
  550. }
  551. /////////////////////////////////////////////////////////////////////////////
  552. // 函数名:  CleanFreeSpace( PTCHAR DrivePath )
  553. // 参数列表:PTCHAR DrivePath
  554. // 函数功能:该函数的功能是清除磁盘的自由空间
  555. /////////////////////////////////////////////////////////////////////////////
  556. BOOLEAN CSecureDelNTFS::CleanFreeSpace( PTCHAR DrivePath )
  557. {
  558.         TCHAR                tempFileName[MAX_PATH];
  559.         ULARGE_INTEGER bytesAvail, totalBytes, freeBytes;
  560.         DWORD                sectorsPerCluster, bytesPerSector, totalClusters, freeClusters;
  561.         ULONGLONG        tempSize = 0;
  562.         HANDLE                hTempFile;
  563.         BOOLEAN                createdFile;
  564.         DWORD                cleanSize, mftFilesCreated;
  565.         DWORD                prevSize;
  566.         CString                strText;
  567.         if( DrivePath[1] != ':' )
  568.                 return FALSE;
  569.         // 磁盘分区路径
  570.         DrivePath[3] = 0;
  571.         if( !GetDiskFreeSpace( DrivePath, §orsPerCluster, &bytesPerSector,
  572.                 &freeClusters, &totalClusters ))
  573.                 return FALSE;
  574. #if UNICODE
  575.         if( !(pGetDiskFreeSpaceEx = (int (__stdcall *)(const char *,union _ULARGE_INTEGER *,union _ULARGE_INTEGER *,union _ULARGE_INTEGER *)) GetProcAddress( GetModuleHandle( _T("kernel32.dll") ),
  576.                                                                                         "GetDiskFreeSpaceExW" ))) {
  577. #else
  578.         if( !(pGetDiskFreeSpaceEx = (int (__stdcall *)(const char *,union _ULARGE_INTEGER *,union _ULARGE_INTEGER *,union _ULARGE_INTEGER *)) GetProcAddress( GetModuleHandle( _T("kernel32.dll") ),
  579.                                                                                         "GetDiskFreeSpaceExA" ))) {
  580. #endif
  581.                 bytesAvail.QuadPart = sectorsPerCluster * freeClusters * bytesPerSector;
  582.         freeBytes.QuadPart = bytesAvail.QuadPart;
  583.         }
  584.         else
  585.         {
  586.                 if( !pGetDiskFreeSpaceEx( DrivePath, &bytesAvail, &totalBytes, &freeBytes ))
  587.                         return FALSE;
  588.         }
  589.         if( bytesAvail.QuadPart != freeBytes.QuadPart )
  590.                 return FALSE;
  591.         _stprintf( tempFileName, _T("%sSDELTEMP"), DrivePath );
  592.         hTempFile = CreateFile( tempFileName, GENERIC_WRITE,
  593.                                         0, NULL, CREATE_NEW,
  594.                                         FILE_FLAG_NO_BUFFERING|FILE_FLAG_SEQUENTIAL_SCAN|
  595.                                         FILE_FLAG_DELETE_ON_CLOSE|FILE_ATTRIBUTE_HIDDEN, NULL );
  596.         if( hTempFile == INVALID_HANDLE_VALUE )
  597.                 return FALSE;
  598.         // 分配清除缓冲区
  599.         cleanSize = sectorsPerCluster * bytesPerSector * 128;
  600.         // 增大簇的容量直到超过极限
  601.         while( cleanSize > bytesPerSector * sectorsPerCluster )
  602.         {
  603.                 if( SecureOverwrite( hTempFile, cleanSize ))
  604.                 {
  605.                         tempSize += cleanSize;
  606.                 }
  607.                 else
  608.                 {
  609.                         cleanSize -= bytesPerSector * sectorsPerCluster;
  610.                 }
  611.         }
  612.         // 最后存在一个小于一个完整簇的空间,利用另外一个临时文件覆盖
  613.         _stprintf( tempFileName, _T("%sSDELTEMP1"), DrivePath );
  614.         hTempFile = CreateFile( tempFileName, GENERIC_WRITE,
  615.                                         0, NULL, CREATE_NEW,
  616.                                         FILE_FLAG_SEQUENTIAL_SCAN|FILE_FLAG_DELETE_ON_CLOSE|
  617.                                         FILE_ATTRIBUTE_HIDDEN|FILE_FLAG_WRITE_THROUGH, NULL );
  618.         if( hTempFile != INVALID_HANDLE_VALUE )
  619.         {
  620.                 while( cleanSize )
  621.                 {
  622.                         if( SecureOverwrite( hTempFile, cleanSize ))
  623.                         {
  624.                                 tempSize += cleanSize;
  625.                         }else
  626.                         {
  627.                                 cleanSize--;
  628.                         }
  629.                 }
  630.         }
  631.         if( ZapFreeSpace )
  632.         {
  633.                 mftFilesCreated = 0;
  634.                 // 最大的 MFT 记录大小
  635.                 prevSize = 4096;
  636.                 while( 1 )
  637.                 {
  638.                         _stprintf( tempFileName, _T("%sSDELMFT%06d"), DrivePath, mftFilesCreated++ );
  639.                         hTempFile = CreateFile( tempFileName, GENERIC_WRITE,
  640.                                                         0, NULL, CREATE_NEW,
  641.                                                         FILE_FLAG_SEQUENTIAL_SCAN|FILE_FLAG_DELETE_ON_CLOSE|
  642.                                                         FILE_ATTRIBUTE_HIDDEN, NULL );
  643.                         if( hTempFile == INVALID_HANDLE_VALUE )
  644.                         {
  645.                                 break;
  646.                         }
  647.                         cleanSize = prevSize;
  648.                         createdFile = FALSE;
  649.                         while( cleanSize )
  650.                         {
  651.                                 if( !SecureOverwrite( hTempFile, cleanSize ))
  652.                                 {
  653.                                         cleanSize--;
  654.                                 }
  655.                                 else
  656.                                 {
  657.                                         prevSize = cleanSize;
  658.                                         createdFile = TRUE;
  659.                                         tempSize += cleanSize;
  660.                                 }
  661.                         }       
  662.                         if( !createdFile ) break;
  663.                 }
  664.         }
  665.         return TRUE;
  666. }
  667. /////////////////////////////////////////////////////////////////////////////
  668. // 函数名:  LocateNativeEntryPoints()
  669. // 参数列表:
  670. // 函数功能:该函数的功能是定位NTDLL的入口点
  671. /////////////////////////////////////////////////////////////////////////////
  672. VOID CSecureDelNTFS::LocateNativeEntryPoints()
  673. {
  674.         // 如果当前的Windows版本是Win9x,则直接返回
  675.         if( GetVersion() >= 0x80000000) return;
  676.     // 装入所需的NTDLL入口点
  677.         if( !(NtFsControlFile = (unsigned int (__stdcall *)(void *,void *,void (__cdecl *)(void *,struct _IO_STATUS_BLOCK *,unsigned long),void *,struct _IO_STATUS_BLOCK *,
  678.                 unsigned long,void *,unsigned long,void *,unsigned long)) GetProcAddress( GetModuleHandle(_T("ntdll.dll")),
  679.                         "NtFsControlFile" )) )
  680.         {
  681.                 AfxMessageBox("Could not find NtFsControlFile entry point in NTDLL.DLL",MB_OK | MB_ICONERROR);
  682.                 exit(1);
  683.         }
  684.         if( !(RtlNtStatusToDosError = (unsigned long (__stdcall *)(unsigned int)) GetProcAddress( GetModuleHandle(_T("ntdll.dll")),
  685.                                                         "RtlNtStatusToDosError" )) )
  686.         {
  687.                 AfxMessageBox("Could not find RtlNtStatusToDosError entry point in NTDLL.DLL",MB_OK | MB_ICONERROR);
  688.                 exit(1);
  689.         }
  690. }
  691. /////////////////////////////////////////////////////////////////////////////
  692. // 函数名:  WipeFileContent(LPCTSTR pFilePath)
  693. // 参数列表:
  694. // 函数功能:该函数主要用于将需要删除的文件全部清零
  695. /////////////////////////////////////////////////////////////////////////////
  696. BOOL CSecureDelNTFS::WipeFileContent(CString strfilename)
  697. {
  698.         char        filename[MAX_PATH];
  699.         sprintf(filename, "%s", strfilename);
  700.         HANDLE hFile = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
  701.                                                         NULL, OPEN_ALWAYS, FILE_FLAG_WRITE_THROUGH, NULL);
  702.         if (hFile == INVALID_HANDLE_VALUE)
  703.                 return false;
  704.         DWORD fileSize = GetFileSize(hFile, 0);
  705.         // 如果文件是空,则直接返回
  706.         if (!fileSize)
  707.         {
  708.                 CloseHandle(hFile);
  709.                 return false;
  710.         }
  711.         DWORD j=0;
  712.         for (int passes = 0; passes < OVERWRITE_PASSES; passes++)
  713.         {
  714.                 char newStorage[BUFFER_SIZE];
  715.                 srand((unsigned)time(NULL));
  716.                 if(passes<(OVERWRITE_PASSES-1))
  717.                         FillMemory((void*)newStorage, BUFFER_SIZE, rand() % 255);
  718.                 else
  719.                         FillMemory((void*)newStorage, BUFFER_SIZE, 0);
  720.                 SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
  721.                 DWORD left = fileSize;
  722.                 int write = BUFFER_SIZE;
  723.                 DWORD written = 0;
  724.                
  725.                 while (left)
  726.                 {
  727.                         j=j+1;
  728.                         if (left < BUFFER_SIZE) write = left;
  729.                         BOOL status = WriteFile(hFile, newStorage, write, &written, NULL);
  730.                         if (!status)
  731.                         {
  732.                                 CloseHandle(hFile);
  733.                                 return false;
  734.                         }
  735.                         left -= write;
  736.                 }
  737.         }
  738.         CloseHandle(hFile);
  739.         return true;
  740. }
  741. 类中的调用源码如下void CSDeleteNTFSDlg::OnButtonSecuredel()
  742. {
  743.         // TODO: Add your control notification handler code here
  744.         if(m_filename!="")
  745.         {
  746.                 //  采用全部清零的方法删除文件的内容
  747.                 m_SdelNTFS.WipeFileContent(m_filename);
  748.                 //  设置文件的长度为零
  749.                 FILE *fp=fopen(m_filename,"w");
  750.                 fclose(fp);
  751.                 //        删除该文件的文件名       
  752.                 TCHAR       searchPattern[MAX_PATH];
  753.                 TCHAR                searchPath[MAX_PATH];
  754.                 sprintf(searchPath, "%s", m_filename);
  755.                 m_SdelNTFS.firstCall = true;
  756.                 m_SdelNTFS.deleteDirectories =false;
  757.                 m_SdelNTFS.ProcessDirectory( searchPath, searchPattern );               
  758.        
  759.                 AfxMessageBox("安全删除完毕!");
  760.                 m_filename="";
  761.         }
  762.         UpdateData(false);
  763.        
  764. }
复制代码

作者:yincheng01 发表于2011-12-15 7:53:30 原文链接

您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

Archiver|手机版|小黑屋|ACE Developer ( 京ICP备06055248号 )

GMT+8, 2024-12-22 18:14 , Processed in 0.018272 second(s), 5 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表