【文章标题】: 被已Worm.Win32.Viking.ix搞疯了,马虎写了个东东,分享一下
【文章作者】: llydd
【作者邮箱】: llydd@163.com
【下载地址】: 自己搜索下载
【使用工具】: peid,vc++6,winhex
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
  前些天突然发现进程里出现些怪进程像Logo1_.exe,rund1l32.exe,iexp1ore.exe之类的,一看就知道不是什么好鸟
  注册表启动项里都出现了那些东东,
  本以为把它们从系统里删除了就不会出现问题了,系统里差不多每个EXE文件都被搞的面目全非了,图标都变没了
  找了个以前写的测试程序用PEID查了一下发现区块名都变成lw0x60,lw0x61之类的,运行一下发现程序半天没反应
  过了一会才运行,突然发现只要运行那些被感染的文件后,被感染的程序会被变成原先被感染的文件,突然想到正
  常程序可能被捆绑到病毒体后才出现这种情况,一旦运行感染后的程序,病毒体会先执行,然后从被感染文件中剥离
  并修改注册表启动项,释放uninstall在c:\winnt\install目录,释放rund1l32.exe在c:\winnt\目录释放Logo1_.exe
  找到这些东东都把它们删了,清除注册表,但每个EXE都被感染了,我总不能每个EXE都运行一遍,让它们恢复正常吧
  装杀毒软件吧,偶的老机子跑不动,AMD K7的老机机了~~~,权当练练手,写的清除工具
  
  #include "windows.h"
  #include "stdio.h"
  #include "string.h"
  int g_Count_File=0;
  
  void list(char *cPath)
  {
    WIN32_FIND_DATA wfd;
    HANDLE hFind;
    char cDir[MAX_PATH];
    char cSubDir[MAX_PATH];
    ::GetCurrentDirectory(sizeof(cDir),cDir);
    ::SetCurrentDirectory(cPath);
    hFind=::FindFirstFile("*.*",&wfd);
    if(hFind==INVALID_HANDLE_VALUE)
    {
      return ;
    }
    do
    {  //判断是否是目录
      if(wfd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
      {
        if(wfd.cFileName[0]!='.')
        {
          //将该目录名与当前路径合并成目录路径
          ::wsprintf(cSubDir,"%s\\%s",cPath,wfd.cFileName);
          list(cSubDir);
        }
        
      
      }
      else
      {  
        
        HANDLE hFile=::CreateFile(
                  wfd.cFileName,
                  GENERIC_READ|GENERIC_WRITE,
                  FILE_SHARE_READ|FILE_SHARE_WRITE,
                  NULL,
                  OPEN_EXISTING,
                  FILE_ATTRIBUTE_NORMAL,
                  NULL);
        
        if(hFile==INVALID_HANDLE_VALUE)
          continue ;
            
        
        HANDLE hMap=::CreateFileMapping(
              hFile,
              NULL,
              PAGE_READWRITE,
              0,
              0,
              NULL);
        void* pAdd=::MapViewOfFile(
              hMap,
              FILE_MAP_ALL_ACCESS,
              0,
              0,
              0);
        if(hMap==0)
          continue ;
        DWORD *pPe;
        PIMAGE_SECTION_HEADER pSec;
        WORD nSecNumber=0;
        DWORD dNewFileSize=0;
        DWORD *pNewFile;
        //判断是否文件首字为'MZ'
        if(*(WORD*)pAdd==0x5a4d)
        {
          pPe=(DWORD*)*((DWORD*)((char*)pAdd+0x3c));
          pPe=(DWORD*)((DWORD)pAdd+(DWORD)pPe);
          //获取文件大小,以免得到一些文件首字为'MZ'但偏移3C处的双字段值超出内存映像文件范围
          dNewFileSize=::GetFileSize(hFile,&dNewFileSize);
          //判断是否'PE\0\0'
          if ((DWORD)pPe<=((DWORD)pAdd+dNewFileSize)&&*pPe==0x004550)
          {
            
            nSecNumber=*(WORD*)((char*)pPe+6);
            pSec=(PIMAGE_SECTION_HEADER)((char*)pPe+248);
            //定位到第一个块表,判断其区名是否为lw0x60若是则被感染
            if (strcmp((const char*)(pSec->Name),"lw0x60")==0)
            {
              //定位到最后一个区块
              for(unsigned int i=1;i<nSecNumber;i++)
              {
                pSec=(PIMAGE_SECTION_HEADER)((char*)pSec+40);
              }
              //原文件大小为感染后的文件大小减去病毒体大小后的值
              dNewFileSize=dNewFileSize-(pSec->PointerToRawData+pSec->SizeOfRawData);
              pNewFile=(DWORD*)(pSec->SizeOfRawData+pSec->PointerToRawData+(char*)pAdd);
              char *temp1,*temp2;
              temp1=(char*)pAdd;
              temp2=(char*)pNewFile;
              //将原文件数据依次移到感染后文件的头部,以还原原文件
              for (i=0;i<dNewFileSize;i++)
              {
                *(temp1++)=*(temp2++);
              }
              ::FlushViewOfFile(pAdd,dNewFileSize);
              ::UnmapViewOfFile(pAdd);
              ::CloseHandle(hMap);
              //修改文件大小
              ::SetFilePointer(hFile,dNewFileSize,NULL,FILE_BEGIN);
              ::SetEndOfFile(hFile);
              g_Count_File++;
              printf("%s\t被清除\n",wfd.cFileName);
              
  
            }
  
          }
  
        }
        ::UnmapViewOfFile(pAdd);
        ::CloseHandle(hMap);
        ::CloseHandle(hFile);
        
        
  
      }
    
    }
    while(::FindNextFile(hFind,&wfd)!=0);
    ::SetCurrentDirectory(cDir);
    
  }
  
  void main()
  {
    char cDrive[4]="A:\\";
    char* p=cDrive;
    UINT uDriveType;
    for(;*p<='Z';(*p)++)
    {
      uDriveType=::GetDriveType(cDrive);
      if(uDriveType==DRIVE_REMOVABLE||uDriveType==DRIVE_FIXED)
      {
        list(cDrive);
      }
    }
  
    printf("共%d个文件被感染\n",g_Count_File);
    system("pause");
  }
  
  清除工具只能清除区块名为lw0x60之类的Win32.Viking.ix病毒,具体的分析小菜菜只能弄到这里,见笑了
  
  
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2007年03月16日 下午 11:59:43



附件在11楼~~~~~~~~~

  • 标 题:答复
  • 作 者:dragonyjd
  • 时 间:2007-04-26 20:41

请教楼主,我调试了一下楼主的代码,我感觉pPe=(DWORD*)((DWORD)pAdd+(DWORD)pPe);是不是应该改为:pPe = (DWORD*)((DWORD)pAdd + *pPe);阿?
我用楼上的代码到不到'PE\0\0'头。
基地址+e_lfanew

  • 标 题:答复
  • 作 者:llydd
  • 时 间:2007-04-26 21:35

自已感觉代码风格不是很好

引用:
  

pPe=(DWORD*)((DWORD)pAdd+(DWORD)pPe);是不是应该改为:pPe = (DWORD*)((DWORD)pAdd + *pPe);阿?
          pPe=(DWORD*)*((DWORD*)((char*)pAdd+0x3c));
执行之后pPe就存放的是该PE文件的IMAGE_NT_HEADERS结构的RVA
(DWORD*)((DWORD)pAdd+(DWORD)pPe)后便可在去判断是否PE是标志
若是你*pPe的话搞不好就内存访问异常了,而且*pPe必是错误用法

  • 标 题:答复
  • 作 者:llydd
  • 时 间:2007-04-27 12:06

被感染后的文件都被附加到病毒体尾部去了,只需把尾部的数据全部取出来便可 恢复原文件