一例所有文件都打不开的数据恢复过程

  1. 云栖社区>
  2. 博客>
  3. 正文

一例所有文件都打不开的数据恢复过程

余二五 2017-11-07 20:52:00 浏览995
展开阅读全文

    保存出来后,打开,文件正常。

    接下来对其他文件做分析,发现篡改的算法均是全部文件对某个值xor,但此值不确定,按字节概率计算,应该有256种可能,加上文件数量及类型众多,显然不能手动进行修正。需要分析其xor加数的生成规律。

    分析过程如下:

        1、推断是否与路径相关:在同一路径下打开不同的文件分析篡改的异或加数,发现不尽相同,排除。

        2、推断是否与文件名称相关:查找所有文件,按名称排序,找到相同文件名称但大小不同的文件,打开后分析篡改的异或加数,发现不相同,排除。

        3、推断是否与类型相关:找到同一类型的几个不同文件,分析篡改的异或加数,发现不相同,排除。

        4、推断是否与存储的物理位置相关:在WINHEX中按不同文件起始位置进行分析篡改的异或加数,未发现相关性,排除。

        5、推断是否与文件头部相关:查找头部相同的文件(有同一文件的不同更新,头部是相同的),进行分析,也排除。

        6、推断尾部相关的可能性不大。(当然如果后面分析仍无法得到规律,则需返回此项再做验证)

        7、推断是否与文件创建时间相关:分别查找相同创建时间、相同访问时间、相同最后一次访问时间的2个文件,进行分析,发现与此无关,排除。

        8、推断是否与大小相关:简单验证后,未举出反例推翻,但需要完全证明与大小相关,同时要得到算法,需要有足够多的样本。

对是否与大小相关的验证

    首先通过命令方式打印所有文件的大小,WINDOWS很不擅长此操作,改用LINUX处理:    


find ./  |xargs ls -ld 2>/dev/null|awk '{printf($5"\t\t"$9"\n");}' >../list.txt 

    之后用excel打开此列表文件,如下图:

EA932F2CFDAC4EEB8D2E5C1D5E07AD59

     因篡改的异或加数只有一个字节,故推断,如果与大小相关,极有可能是对文件大小mod 256后关系对应,于是在excel中计算所有文件大小值 的mod 256,如下图:

A73F605C302D4CFD82DA6EE69231D665

    对mod 256的值进行排序,excel可能可以直接实现,不过,至少可以复制整列,再以数字方式粘贴:

9BBD42A51DCD4067B6A022378B72E6D0

    排序后如下图:

623C99A9521A493A8E9EDE010E3C68AE

    对相同mod 256的文件进行篡改验证,未发现不符合规律者,基本断定篡改值与文件大小mod 256的值存在完全映射关系。

    对所有可能做抽样分析后,得到篡改异或加数的生成规律:

CE1BDEB95D824081A23C1DADFC079D1A

    至此,篡改算法得到,同时修正算法也自然就容易多了。

【解决方案】   

通过VS2010下编写程序解决,修复程序源码如下:

 


  1. //北亚数据恢复中心,张宇,www.datahf.net 
  2. //文件夹遍历算法,来源于互联网,仅做了简单修正。 
  3. #include "stdafx.h" 
  4. #include <iostream> 
  5. #include "windows.h" 
  6. #include <string.h> 
  7. using namespace std; 
  8.  
  9. #define BUFFSIZE (256*1024) 
  10. byte buff[BUFFSIZE]; 
  11. bool xor_file(LPCTSTR swfile) 
  12.     LARGE_INTEGER liSize; 
  13.     HANDLE hFile; 
  14.     hFile = CreateFile(swfile, 
  15.         GENERIC_READ|GENERIC_WRITE,  
  16.         FILE_SHARE_READ|FILE_SHARE_WRITE, 
  17.         NULL,  
  18.         OPEN_EXISTING,  
  19.         FILE_FLAG_SEQUENTIAL_SCAN, 
  20.         NULL); 
  21.     if(hFile == INVALID_HANDLE_VALUE) 
  22.     { 
  23.         _tprintf(_T("%s canot open!\n"),swfile); 
  24.         return false
  25.     } 
  26.     GetFileSizeEx(hFile,&liSize); 
  27.     int t = liSize.QuadPart % (long long)256; 
  28.     int xor_value = 0; 
  29.  
  30.     if( (t>=0) && (t<9)) 
  31.         xor_value += (t+0x37); 
  32.  
  33.     else if((t>=9) && (t<73)) 
  34.         xor_value += (t-9+0xC0); 
  35.  
  36.     else if((t>=73) && (t<137)) 
  37.         xor_value += (t-73+0x80); 
  38.  
  39.     else if((t>=137) && (t<201)) 
  40.         xor_value += (t-137+0x40); 
  41.  
  42.     else 
  43.         xor_value += (t-201+0x00); 
  44.  
  45.     DWORD nb= liSize.QuadPart / (long long) BUFFSIZE; 
  46.     DWORD tb= liSize.QuadPart % (long long) BUFFSIZE; 
  47.     DWORD bRead; 
  48.     DWORD bWrite; 
  49.     DWORD i; 
  50.     for(i=0;i<nb;i++) 
  51.     { 
  52.         ReadFile(hFile,buff,BUFFSIZE,&bRead,NULL); 
  53.         if(bRead != BUFFSIZE) 
  54.             _tprintf(_T("%s canot read,Pos:%I64d!\n"),swfile,i*(long long)BUFFSIZE); 
  55.         for(int ii=0;ii<BUFFSIZE;ii++) 
  56.             buff[ii] ^= xor_value; 
  57.         SetFilePointer(hFile,-BUFFSIZE,NULL,FILE_CURRENT); 
  58.         WriteFile(hFile,buff,BUFFSIZE,&bWrite,NULL); 
  59.         if(bWrite != BUFFSIZE) 
  60.             _tprintf(_T("%s canot write,Pos:%I64d!\n"),swfile,i*(long long)BUFFSIZE); 
  61.     } 
  62.  
  63.     { 
  64.         ReadFile(hFile,buff,tb,&bRead,NULL); 
  65.         if(tb != bRead) 
  66.             _tprintf(_T("%s canot read,Pos:%I64d!\n"),swfile,i*(long long)BUFFSIZE); 
  67.         for(int ii=0;ii<tb;ii++) 
  68.             buff[ii] ^= xor_value; 
  69.         SetFilePointer(hFile,-tb,NULL,FILE_CURRENT); 
  70.         WriteFile(hFile,buff,tb,&bWrite,NULL); 
  71.         if(tb != bWrite) 
  72.             _tprintf(_T("%s canot write,Pos:%I64d!\n"),swfile,i*(long long)BUFFSIZE); 
  73.     } 
  74.     CloseHandle(hFile); 
  75.     return true
  76. void TraverseDirectory(TCHAR Dir[MAX_PATH]); 
  77. bool select_file(LPCTSTR Dir,WIN32_FIND_DATA &FindFileData) 
  78.     if((FindFileData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)!=0&&_tcscmp(FindFileData.cFileName,L".")==0||_tcscmp(FindFileData.cFileName,L"..")==0)        //判断是文件夹&&表示为"."||表示为"." 
  79.     { 
  80.         return false
  81.     } 
  82.     TCHAR DirAdd[MAX_PATH]; 
  83.     StringCchCopy(DirAdd,MAX_PATH,Dir); 
  84.     StringCchCat(DirAdd,MAX_PATH,TEXT("\\")); 
  85.     StringCchCat(DirAdd,MAX_PATH,FindFileData.cFileName);       //拼接得到此文件夹的完整路径 
  86.  
  87.     if((FindFileData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)!=0)      //判断如果是文件夹 
  88.     { 
  89.         TraverseDirectory(DirAdd);                                  //实现递归调用 
  90.     } 
  91.     if((FindFileData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)==0)    //如果不是文件夹 
  92.     { 
  93.         _tprintf (_T("%s\n"), DirAdd); 
  94.         xor_file(DirAdd); 
  95.     } 
  96.     return true
  97. //传入要遍历的文件夹路径,并遍历相应文件夹 
  98. void TraverseDirectory(TCHAR Dir[MAX_PATH])     
  99.     WIN32_FIND_DATA FindFileData; 
  100.     HANDLE hFind=INVALID_HANDLE_VALUE; 
  101.     TCHAR DirSpec[MAX_PATH];                  //定义要遍历的文件夹的目录 
  102.     DWORD dwError; 
  103.     StringCchCopy(DirSpec,MAX_PATH,Dir); 
  104.     StringCchCat(DirSpec,MAX_PATH,TEXT("\\*"));   //定义要遍历的文件夹的完整路径\* 
  105.  
  106.     hFind=FindFirstFile(DirSpec,&FindFileData);          //找到文件夹中的第一个文件 
  107.  
  108.     if(hFind==INVALID_HANDLE_VALUE)                               //如果hFind句柄创建失败,输出错误信息 
  109.     { 
  110.         FindClose(hFind);  
  111.         return;   
  112.     } 
  113.     else  
  114.     { 
  115.         select_file(Dir,FindFileData); 
  116.         while(FindNextFile(hFind,&FindFileData)!=0)                            //当文件或者文件夹存在时 
  117.         { 
  118.             select_file(Dir,FindFileData); 
  119.         } 
  120.         FindClose(hFind); 
  121.     } 
  122.  
  123. int _tmain( int argc, TCHAR *argv[] ) 
  124.     locale loc( "chs" );                //支持中文输出,否则wchar可能无法输出值为中文的变量 
  125.     cout.imbue( loc ); 
  126.     if( argc != 2 ) 
  127.     { 
  128.         _tprintf(_T("Usage: %s [workdir]\n"), argv[0]); 
  129.         return -1; 
  130.     } 
  131.     _tprintf (_T("work dir is %s\n"), argv[1]); 
  132.  
  133.     TraverseDirectory(argv[1]);  
  134.  
  135.     return 0; 

【验证】

    程序运行完成后,对文件进行抽检,无报错,为进一步确定可靠性,查找所有JPG文件,显示缩略图,无异常。

ECDA308D10FC4BD1B9FB2F92EEC20DD2

查找所有doc文件,显示作者,标题(这两个信息是通过内容部分得到的),未发现异常(只是OS盗版的痕迹挺重,呵呵),至此,确定算法正确。数据恢复完成。

0FACC224859949108055ACD47D5F47F6





本文转自 张宇 51CTO博客,原文链接:xxxxxxx,如需转载请自行联系原作者

网友评论

登录后评论
0/500
评论