找回密码
 用户注册

QQ登录

只需一步,快速开始

查看: 3307|回复: 0

[原]VC++信息安全编程(12)实现杀毒程序,杀灭D3病毒范例

[复制链接]
发表于 2012-3-8 15:01:05 | 显示全部楼层 |阅读模式
下面我们用代码亲自来实践一个杀毒程序,清除程序的可读可写,并扫描程序的特征码,对病毒进行删除


  1. #include "stdafx.h"
  2. #include "ScanDisk.h"
  3. #include "ScanDiskDlg.h"
  4. #ifdef _DEBUG
  5. #define new DEBUG_NEW
  6. #undef THIS_FILE
  7. static char THIS_FILE[] = __FILE__;
  8. #endif
  9. UINT ThreadProc(LPVOID param){
  10. CScanDiskDlg *ScanDisk=(CScanDiskDlg*)param;
  11. CString part;
  12. int i=0;
  13. int cy=ScanDisk->m_Disk.GetLength()/2;
  14. do{
  15.         part=ScanDisk->m_Disk.Mid(2*i,2);
  16.     ScanDisk->SearchFolder((char*)part.GetBuffer(0));       
  17.         i++;
  18. }while(i<cy&&ScanDisk->Status);
  19. char s[256];
  20. sprintf(s,"扫描的文件总数 =%d",ScanDisk->TotalFileNum);
  21. ScanDisk->m_Static.SendMessage(WM_SETTEXT,0,(LPARAM)(LPCTSTR)s);
  22. return 0;
  23. }
  24. /////////////////////////////////////////////////////////////////////////////
  25. // CScanDiskDlg dialog
  26. CScanDiskDlg::CScanDiskDlg(CWnd* pParent /*=NULL*/)
  27.         : CDialog(CScanDiskDlg::IDD, pParent)
  28. {
  29.         //{{AFX_DATA_INIT(CScanDiskDlg)
  30.         m_Disk = _T("");
  31.         //}}AFX_DATA_INIT
  32.         // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
  33.         m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
  34.         TotalFileNum=0;  //扫描文件总数
  35. }
  36. void CScanDiskDlg::DoDataExchange(CDataExchange* pDX)
  37. {
  38.         CDialog::DoDataExchange(pDX);
  39.         //{{AFX_DATA_MAP(CScanDiskDlg)
  40.         DDX_Control(pDX, IDC_STATIC1, m_Static);
  41.         DDX_Control(pDX, IDC_LIST1, m_List);
  42.         DDX_Control(pDX, IDC_Bstart, m_Bstart);
  43.         DDX_Text(pDX, IDC_Epartition, m_Disk);
  44.         //}}AFX_DATA_MAP
  45. }
  46. BEGIN_MESSAGE_MAP(CScanDiskDlg, CDialog)
  47.         //{{AFX_MSG_MAP(CScanDiskDlg)
  48.         ON_WM_PAINT()
  49.         ON_WM_QUERYDRAGICON()
  50.         ON_BN_CLICKED(IDC_Bstart, OnBstart)
  51.         ON_BN_CLICKED(IDC_Bstop, OnBstop)
  52.         ON_EN_CHANGE(IDC_Epartition, OnChangeEpartition)
  53.         ON_BN_CLICKED(IDC_Bsave, OnBsave)
  54.         //}}AFX_MSG_MAP
  55. END_MESSAGE_MAP()
  56. /////////////////////////////////////////////////////////////////////////////
  57. // CScanDiskDlg message handlers
  58. BOOL CScanDiskDlg::OnInitDialog()
  59. {
  60.         CDialog::OnInitDialog();
  61.         // Set the icon for this dialog.  The framework does this automatically
  62.         //  when the application's main window is not a dialog
  63.         SetIcon(m_hIcon, TRUE);                        // Set big icon
  64.         SetIcon(m_hIcon, FALSE);                // Set small icon
  65.        
  66. DWORD disk=GetLogicalDrives();
  67. DWORD va=1;
  68. char s[]="A:";
  69. for(int i=0;i<32;i++){
  70.         if(disk&(va<<i)){
  71.         s[0]=0x41+(char)i;
  72.         m_Disk+=s;
  73. }}
  74. UpdateData(FALSE);
  75. Status=FALSE;
  76.        
  77.         return TRUE;  // return TRUE  unless you set the focus to a control
  78. }
  79. // If you add a minimize button to your dialog, you will need the code below
  80. //  to draw the icon.  For MFC applications using the document/view model,
  81. //  this is automatically done for you by the framework.
  82. void CScanDiskDlg::OnPaint()
  83. {
  84.         if (IsIconic())
  85.         {
  86.                 CPaintDC dc(this); // device context for painting
  87.                 SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
  88.                 // Center icon in client rectangle
  89.                 int cxIcon = GetSystemMetrics(SM_CXICON);
  90.                 int cyIcon = GetSystemMetrics(SM_CYICON);
  91.                 CRect rect;
  92.                 GetClientRect(&rect);
  93.                 int x = (rect.Width() - cxIcon + 1) / 2;
  94.                 int y = (rect.Height() - cyIcon + 1) / 2;
  95.                 // Draw the icon
  96.                 dc.DrawIcon(x, y, m_hIcon);
  97.         }
  98.         else
  99.         {
  100.                 CDialog::OnPaint();
  101.         }
  102. }
  103. // The system calls this to obtain the cursor to display while the user drags
  104. //  the minimized window.
  105. HCURSOR CScanDiskDlg::OnQueryDragIcon()
  106. {
  107.         return (HCURSOR) m_hIcon;
  108. }
  109. void CScanDiskDlg::OnBstart()
  110. {
  111. if(Status==FALSE){
  112.   m_List.ResetContent();
  113.   TotalFileNum=0;
  114.   Status=TRUE;
  115.   SubThread=(CWinThread*)AfxBeginThread(&ThreadProc,this,THREAD_PRIORITY_BELOW_NORMAL,0,0);
  116.   m_Bstart.SetWindowText("停止");
  117. }
  118. else{
  119.   Status=FALSE;
  120.   m_Bstart.SetWindowText("开始");
  121. }       
  122. }
  123. void CScanDiskDlg::OnBstop()
  124. {
  125. Status=FALSE;
  126. ExitProcess(0);       
  127. }
  128. //处理搜索到的可执行文件
  129. BOOL CScanDiskDlg::ProcessFile(char *FileName)
  130. {
  131. CFile file;
  132. CFileStatus rStatus;
  133. CString inf;
  134. DWORD FileLen=0;
  135. BOOL re;
  136. IMAGE_DOS_HEADER      dos_header;
  137. IMAGE_NT_HEADERS      nt_header;
  138. IMAGE_SECTION_HEADER  section_header;
  139. DWORD len;
  140. BYTE *ptr;
  141. //inf=FileName;
  142. //inf.MakeLower();
  143. //if(-1==inf.Find("\\aaa.exe",1))return FALSE;
  144. //m_List.AddString(FileName);
  145. //return FALSE;
  146. re=file.GetStatus(FileName,rStatus);    //包含了文件的时间、属性等
  147. if(!re){
  148. //    inf="无法操作的文件:";
  149. //    inf+=FileName;
  150. //    m_List.AddString(inf);
  151.     return FALSE;
  152. }
  153.   
  154. if(rStatus.m_attribute==1){  //只读
  155.   re=SetFileAttributes(FileName,rStatus.m_attribute-1);//去掉只读属性
  156.   if(re){
  157.     inf="无法修改只读属性:";
  158.     inf+=FileName;
  159.     m_List.AddString(inf);
  160.     return FALSE;
  161.   }
  162. }
  163. if(file.Open(FileName,CFile::modeReadWrite|CFile::typeBinary)){
  164.   FileLen=file.GetLength();
  165.   if(FileLen==0)goto endthis_1;//文件长度为0,不处理
  166.   len=file.Read(&dos_header,sizeof(IMAGE_DOS_HEADER));
  167.   if(dos_header.e_magic==0x5a4d&&len==sizeof(IMAGE_DOS_HEADER)){//含有"MZ"
  168.   //判断dos_header.e_lfanew防止偶然
  169.   if(dos_header.e_lfanew&&(FileLen>(DWORD)dos_header.e_lfanew+sizeof(IMAGE_NT_HEADERS))){
  170. //        m_List.AddString(FileName);
  171. //            goto endthis_1;
  172.     file.Seek(dos_header.e_lfanew,CFile::begin);
  173.     len=file.Read(&nt_header,sizeof(IMAGE_NT_HEADERS));
  174.     if(nt_header.Signature==0x4550&&len==sizeof(IMAGE_NT_HEADERS)){  //含有"PE"
  175.         //定位到最后一个节
  176.       file.Seek(dos_header.e_lfanew+sizeof(IMAGE_NT_HEADERS)+
  177.                 (nt_header.FileHeader.NumberOfSections-1)*sizeof(IMAGE_SECTION_HEADER),CFile::begin);
  178.       len=file.Read(§ion_header,sizeof(section_header));
  179.           if((len==sizeof(section_header))&&(!strncmp((char*)section_header.Name,".SD-3",5))){//发现SD-3并处理病毒
  180. //  m_List.AddString(FileName);
  181. //  goto endthis_1;
  182.                 BYTE VirusChar[15]={0x55,0x8b,0xec,0x81,0xc4,0xb8,   //病毒特征码
  183.                   0xfe,0xff,0xff,0x60,0xb0,0x2a,0x88,0x45,0xfa};
  184.         file.Seek(section_header.PointerToRawData,CFile::begin);
  185.             ptr=new BYTE[section_header.Misc.VirtualSize];
  186.             file.Read(ptr,section_header.Misc.VirtualSize);
  187.         for(int i=0;i<(int)section_header.Misc.VirtualSize-15;i++){
  188.                         if(!memcmp(ptr+i,VirusChar,15)){  //发现了病毒特征码
  189.               file.Seek(section_header.PointerToRawData+i-4,CFile::begin);
  190.                           DWORD oldEntry;
  191.                           file.Read(&oldEntry,4);   //把特征码上面的jmp oldEntry的原来入口地址值读出
  192.               //得到原来入口地址相对虚拟地址
  193.               //例如在0x00403059行,有 0xE9A2D8FFFF   jmp 1000
  194.                           //则计算方法为section_header.VirtualAddress+i=0x305E
  195.                           //0x305E+0xFFFFd8A2=0x1000
  196.                           //0x305E为指令jmp 1000的下条指令的相对虚拟地址
  197.               //修改入口地址
  198.               nt_header.OptionalHeader.AddressOfEntryPoint=section_header.VirtualAddress+i+oldEntry;
  199.                           //得到病毒代码开始区域在文件中的偏移
  200.                           DWORD strPos=section_header.PointerToRawData+i;
  201.               //需要抹去的病毒区域长度
  202.                           len=file.GetLength()-strPos;
  203. //  inf.Format("len=%x,strPos=%x,i=%x--",len,strPos,i);
  204. //  m_List.AddString(inf+FileName);
  205. //  goto endthis_1;
  206.               delete []ptr;
  207.                           ptr=new BYTE[len];
  208.                           //清0
  209.                           memset(ptr,0,len);
  210.               file.Seek(strPos,CFile::begin);
  211.                           file.Write(ptr,len);//覆盖病毒区域
  212.               file.Seek(dos_header.e_lfanew,CFile::begin);
  213.                           strcpy((char*)section_header.Name,".kill");   //修改节名
  214.                           //修改PE头(包含有入口地址)
  215.                           file.Write(&nt_header,sizeof(nt_header));
  216.                           //定位到最后一个节表位置,修改
  217.               file.Seek(dos_header.e_lfanew+sizeof(nt_header)+(nt_header.FileHeader.NumberOfSections-1)*
  218.                                   sizeof(section_header),CFile::begin);
  219.               file.Write(§ion_header,sizeof(section_header));
  220.                           delete []ptr;
  221.                           inf="发现SD-3,清除:";
  222.                           inf+=FileName;
  223.               m_List.AddString(inf+FileName);
  224.                           break;
  225.                         }
  226.                 }
  227.           }
  228.   }
  229.   }
  230.   }
  231. endthis_1:
  232.   file.Close();
  233.   file.SetStatus(FileName,rStatus);
  234.   }
  235. /*
  236. else{   //不能打开文件,则只读方式打开。只分析有无病毒
  237.   if(!file.Open(FileName,CFile::modeRead|CFile::typeBinary)){
  238.    inf="不能修改:";
  239.    inf+=FileName;
  240.    m_List.AddString(inf);
  241.   }
  242.   FileLen=file.GetLength();
  243.   if(FileLen==0)goto endthis_2;//文件长度为0,不处理
  244.   len=file.Read(&dos_header,sizeof(IMAGE_DOS_HEADER));
  245.   if(dos_header.e_magic==0x5a4d&&len==sizeof(IMAGE_DOS_HEADER)){//含有"MZ"
  246.   //考虑到后面的dos_header.e_lfanew-1,必要
  247.   if(dos_header.e_lfanew&&FileLen>(DWORD)dos_header.e_lfanew){
  248.     file.Seek(dos_header.e_lfanew,CFile::begin);
  249.     len=file.Read(&nt_header,sizeof(IMAGE_NT_HEADERS));
  250.     if(nt_header.Signature==0x4550&&len==sizeof(IMAGE_NT_HEADERS)){  //含有"PE"
  251.       file.Seek(dos_header.e_lfanew+sizeof(IMAGE_NT_HEADERS)+
  252.                 (nt_header.FileHeader.NumberOfSections-1)*sizeof(IMAGE_SECTION_HEADER),CFile::begin);
  253.       file.Read(§ion_header,sizeof(section_header));  
  254.           if(!strncmp((char*)section_header.Name,".SD-3",5)){//发现SD-3病毒
  255.         BYTE VirusChar[15]={0x55,0x8b,0xec,0x81,0xc4,0xb8,   //病毒特征码
  256.                   0xfe,0xff,0xff,0x60,0xb0,0x2a,0x88,0x45,0xfa};
  257.         file.Seek(section_header.PointerToRawData,CFile::begin);
  258.             ptr=new BYTE[section_header.Misc.VirtualSize];
  259.             file.Read(ptr,section_header.Misc.VirtualSize);
  260.         for(int i=0;i<(int)section_header.Misc.VirtualSize-15;i++){
  261.                         if(!memcmp(ptr+i,VirusChar,15)){  //发现了病毒特征码
  262.                       inf="无法清除的SD-3病毒:";
  263.               inf+=FileName;
  264.               m_List.AddString(inf);
  265.           }}}
  266. }}}
  267. endthis_2:
  268.   file.Close();
  269.   file.SetStatus(FileName,rStatus);
  270. }
  271. */
  272. return TRUE;
  273. }
  274. //搜索其下所有子目录及文件.
  275. void CScanDiskDlg::SearchFolder(char *path)
  276. {
  277. HANDLE h;
  278. WIN32_FIND_DATA dat;
  279. BOOL re;
  280. char dir[300];
  281. strcpy(dir,path);
  282. strcat(dir,"\\*.*");
  283. h=FindFirstFile(dir,&dat);
  284. if(h==INVALID_HANDLE_VALUE){
  285.   //AfxMessageBox(dir);
  286.   return;
  287. }
  288. char FullName[300];
  289. do{
  290.   re=FindNextFile(h,&dat);
  291.   if(!re)break;
  292.   if(!strncmp(dat.cFileName,"..",2))continue;
  293.   if(!(FILE_ATTRIBUTE_DIRECTORY&dat.dwFileAttributes)){  //不是目录
  294.     strcpy(FullName,path);  
  295.     strcat(FullName,"\\\0");
  296.     strcat(FullName,dat.cFileName);
  297.         //CString exe=dat.cFileName;
  298.         //exe.MakeLower();
  299.     //if(-1!=exe.Find(".exe",2))m_List.AddString(FullName);
  300.     m_Static.SendMessage(WM_SETTEXT,0,(LPARAM)(LPCTSTR)FullName);
  301.     ProcessFile(FullName);
  302.     TotalFileNum++;
  303.   }
  304.   else {     //是目录,进入子目录
  305.    char next[300];
  306.    strcpy(next,path);
  307.    strcat(next,"\\\0");
  308.    strcat(next,dat.cFileName);
  309.    //m_List.AddString(next);
  310.    SearchFolder(next);
  311.   }
  312. }while(Status);                    
  313. FindClose(h);
  314. }
  315. void CScanDiskDlg::OnChangeEpartition()
  316. {
  317. UpdateData();
  318. }
  319. void CScanDiskDlg::OnBsave()
  320. {
  321. AfxMessageBox("结果保存在c:\\inf.txt");       
  322. CFile fp;
  323. fp.Open("c:\\inf.txt",CFile::modeCreate|CFile.modeWrite);
  324. if(!fp)return;
  325. int col=m_List.GetCount();
  326. if(col==LB_ERR){ fp.Close(); return; }
  327. char s[400];
  328. for(int i=0;i<col;i++){
  329.   memset(s,0,400);
  330.   m_List.GetText(i,s);
  331.   strcat(s,"\r\n");
  332.   fp.Write(s,strlen(s));
  333. }
  334. fp.Close();
  335. }
复制代码
作者:yincheng01 发表于2011-12-14 23:58:56 原文链接

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

本版积分规则

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

GMT+8, 2024-5-3 22:33 , Processed in 0.017897 second(s), 6 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

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