|
下面我们用代码亲自来实践一个杀毒程序,清除程序的可读可写,并扫描程序的特征码,对病毒进行删除
- #include "stdafx.h"
- #include "ScanDisk.h"
- #include "ScanDiskDlg.h"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- UINT ThreadProc(LPVOID param){
- CScanDiskDlg *ScanDisk=(CScanDiskDlg*)param;
- CString part;
- int i=0;
- int cy=ScanDisk->m_Disk.GetLength()/2;
- do{
- part=ScanDisk->m_Disk.Mid(2*i,2);
- ScanDisk->SearchFolder((char*)part.GetBuffer(0));
- i++;
- }while(i<cy&&ScanDisk->Status);
- char s[256];
- sprintf(s,"扫描的文件总数 =%d",ScanDisk->TotalFileNum);
- ScanDisk->m_Static.SendMessage(WM_SETTEXT,0,(LPARAM)(LPCTSTR)s);
- return 0;
- }
- /////////////////////////////////////////////////////////////////////////////
- // CScanDiskDlg dialog
- CScanDiskDlg::CScanDiskDlg(CWnd* pParent /*=NULL*/)
- : CDialog(CScanDiskDlg::IDD, pParent)
- {
- //{{AFX_DATA_INIT(CScanDiskDlg)
- m_Disk = _T("");
- //}}AFX_DATA_INIT
- // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
- m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
- TotalFileNum=0; //扫描文件总数
- }
- void CScanDiskDlg::DoDataExchange(CDataExchange* pDX)
- {
- CDialog::DoDataExchange(pDX);
- //{{AFX_DATA_MAP(CScanDiskDlg)
- DDX_Control(pDX, IDC_STATIC1, m_Static);
- DDX_Control(pDX, IDC_LIST1, m_List);
- DDX_Control(pDX, IDC_Bstart, m_Bstart);
- DDX_Text(pDX, IDC_Epartition, m_Disk);
- //}}AFX_DATA_MAP
- }
- BEGIN_MESSAGE_MAP(CScanDiskDlg, CDialog)
- //{{AFX_MSG_MAP(CScanDiskDlg)
- ON_WM_PAINT()
- ON_WM_QUERYDRAGICON()
- ON_BN_CLICKED(IDC_Bstart, OnBstart)
- ON_BN_CLICKED(IDC_Bstop, OnBstop)
- ON_EN_CHANGE(IDC_Epartition, OnChangeEpartition)
- ON_BN_CLICKED(IDC_Bsave, OnBsave)
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
- /////////////////////////////////////////////////////////////////////////////
- // CScanDiskDlg message handlers
- BOOL CScanDiskDlg::OnInitDialog()
- {
- CDialog::OnInitDialog();
- // Set the icon for this dialog. The framework does this automatically
- // when the application's main window is not a dialog
- SetIcon(m_hIcon, TRUE); // Set big icon
- SetIcon(m_hIcon, FALSE); // Set small icon
-
- DWORD disk=GetLogicalDrives();
- DWORD va=1;
- char s[]="A:";
- for(int i=0;i<32;i++){
- if(disk&(va<<i)){
- s[0]=0x41+(char)i;
- m_Disk+=s;
- }}
- UpdateData(FALSE);
- Status=FALSE;
-
- return TRUE; // return TRUE unless you set the focus to a control
- }
- // If you add a minimize button to your dialog, you will need the code below
- // to draw the icon. For MFC applications using the document/view model,
- // this is automatically done for you by the framework.
- void CScanDiskDlg::OnPaint()
- {
- if (IsIconic())
- {
- CPaintDC dc(this); // device context for painting
- SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
- // Center icon in client rectangle
- int cxIcon = GetSystemMetrics(SM_CXICON);
- int cyIcon = GetSystemMetrics(SM_CYICON);
- CRect rect;
- GetClientRect(&rect);
- int x = (rect.Width() - cxIcon + 1) / 2;
- int y = (rect.Height() - cyIcon + 1) / 2;
- // Draw the icon
- dc.DrawIcon(x, y, m_hIcon);
- }
- else
- {
- CDialog::OnPaint();
- }
- }
- // The system calls this to obtain the cursor to display while the user drags
- // the minimized window.
- HCURSOR CScanDiskDlg::OnQueryDragIcon()
- {
- return (HCURSOR) m_hIcon;
- }
- void CScanDiskDlg::OnBstart()
- {
- if(Status==FALSE){
- m_List.ResetContent();
- TotalFileNum=0;
- Status=TRUE;
- SubThread=(CWinThread*)AfxBeginThread(&ThreadProc,this,THREAD_PRIORITY_BELOW_NORMAL,0,0);
- m_Bstart.SetWindowText("停止");
- }
- else{
- Status=FALSE;
- m_Bstart.SetWindowText("开始");
- }
- }
- void CScanDiskDlg::OnBstop()
- {
- Status=FALSE;
- ExitProcess(0);
- }
- //处理搜索到的可执行文件
- BOOL CScanDiskDlg::ProcessFile(char *FileName)
- {
- CFile file;
- CFileStatus rStatus;
- CString inf;
- DWORD FileLen=0;
- BOOL re;
- IMAGE_DOS_HEADER dos_header;
- IMAGE_NT_HEADERS nt_header;
- IMAGE_SECTION_HEADER section_header;
- DWORD len;
- BYTE *ptr;
- //inf=FileName;
- //inf.MakeLower();
- //if(-1==inf.Find("\\aaa.exe",1))return FALSE;
- //m_List.AddString(FileName);
- //return FALSE;
- re=file.GetStatus(FileName,rStatus); //包含了文件的时间、属性等
- if(!re){
- // inf="无法操作的文件:";
- // inf+=FileName;
- // m_List.AddString(inf);
- return FALSE;
- }
-
- if(rStatus.m_attribute==1){ //只读
- re=SetFileAttributes(FileName,rStatus.m_attribute-1);//去掉只读属性
- if(re){
- inf="无法修改只读属性:";
- inf+=FileName;
- m_List.AddString(inf);
- return FALSE;
- }
- }
- if(file.Open(FileName,CFile::modeReadWrite|CFile::typeBinary)){
- FileLen=file.GetLength();
- if(FileLen==0)goto endthis_1;//文件长度为0,不处理
- len=file.Read(&dos_header,sizeof(IMAGE_DOS_HEADER));
- if(dos_header.e_magic==0x5a4d&&len==sizeof(IMAGE_DOS_HEADER)){//含有"MZ"
- //判断dos_header.e_lfanew防止偶然
- if(dos_header.e_lfanew&&(FileLen>(DWORD)dos_header.e_lfanew+sizeof(IMAGE_NT_HEADERS))){
- // m_List.AddString(FileName);
- // goto endthis_1;
- file.Seek(dos_header.e_lfanew,CFile::begin);
- len=file.Read(&nt_header,sizeof(IMAGE_NT_HEADERS));
- if(nt_header.Signature==0x4550&&len==sizeof(IMAGE_NT_HEADERS)){ //含有"PE"
- //定位到最后一个节
- file.Seek(dos_header.e_lfanew+sizeof(IMAGE_NT_HEADERS)+
- (nt_header.FileHeader.NumberOfSections-1)*sizeof(IMAGE_SECTION_HEADER),CFile::begin);
- len=file.Read(§ion_header,sizeof(section_header));
- if((len==sizeof(section_header))&&(!strncmp((char*)section_header.Name,".SD-3",5))){//发现SD-3并处理病毒
- // m_List.AddString(FileName);
- // goto endthis_1;
- BYTE VirusChar[15]={0x55,0x8b,0xec,0x81,0xc4,0xb8, //病毒特征码
- 0xfe,0xff,0xff,0x60,0xb0,0x2a,0x88,0x45,0xfa};
- file.Seek(section_header.PointerToRawData,CFile::begin);
- ptr=new BYTE[section_header.Misc.VirtualSize];
- file.Read(ptr,section_header.Misc.VirtualSize);
- for(int i=0;i<(int)section_header.Misc.VirtualSize-15;i++){
- if(!memcmp(ptr+i,VirusChar,15)){ //发现了病毒特征码
- file.Seek(section_header.PointerToRawData+i-4,CFile::begin);
- DWORD oldEntry;
- file.Read(&oldEntry,4); //把特征码上面的jmp oldEntry的原来入口地址值读出
- //得到原来入口地址相对虚拟地址
- //例如在0x00403059行,有 0xE9A2D8FFFF jmp 1000
- //则计算方法为section_header.VirtualAddress+i=0x305E
- //0x305E+0xFFFFd8A2=0x1000
- //0x305E为指令jmp 1000的下条指令的相对虚拟地址
- //修改入口地址
- nt_header.OptionalHeader.AddressOfEntryPoint=section_header.VirtualAddress+i+oldEntry;
- //得到病毒代码开始区域在文件中的偏移
- DWORD strPos=section_header.PointerToRawData+i;
- //需要抹去的病毒区域长度
- len=file.GetLength()-strPos;
- // inf.Format("len=%x,strPos=%x,i=%x--",len,strPos,i);
- // m_List.AddString(inf+FileName);
- // goto endthis_1;
- delete []ptr;
- ptr=new BYTE[len];
- //清0
- memset(ptr,0,len);
- file.Seek(strPos,CFile::begin);
- file.Write(ptr,len);//覆盖病毒区域
- file.Seek(dos_header.e_lfanew,CFile::begin);
- strcpy((char*)section_header.Name,".kill"); //修改节名
- //修改PE头(包含有入口地址)
- file.Write(&nt_header,sizeof(nt_header));
- //定位到最后一个节表位置,修改
- file.Seek(dos_header.e_lfanew+sizeof(nt_header)+(nt_header.FileHeader.NumberOfSections-1)*
- sizeof(section_header),CFile::begin);
- file.Write(§ion_header,sizeof(section_header));
- delete []ptr;
- inf="发现SD-3,清除:";
- inf+=FileName;
- m_List.AddString(inf+FileName);
- break;
- }
- }
- }
- }
- }
- }
- endthis_1:
- file.Close();
- file.SetStatus(FileName,rStatus);
- }
- /*
- else{ //不能打开文件,则只读方式打开。只分析有无病毒
- if(!file.Open(FileName,CFile::modeRead|CFile::typeBinary)){
- inf="不能修改:";
- inf+=FileName;
- m_List.AddString(inf);
- }
- FileLen=file.GetLength();
- if(FileLen==0)goto endthis_2;//文件长度为0,不处理
- len=file.Read(&dos_header,sizeof(IMAGE_DOS_HEADER));
- if(dos_header.e_magic==0x5a4d&&len==sizeof(IMAGE_DOS_HEADER)){//含有"MZ"
- //考虑到后面的dos_header.e_lfanew-1,必要
- if(dos_header.e_lfanew&&FileLen>(DWORD)dos_header.e_lfanew){
- file.Seek(dos_header.e_lfanew,CFile::begin);
- len=file.Read(&nt_header,sizeof(IMAGE_NT_HEADERS));
- if(nt_header.Signature==0x4550&&len==sizeof(IMAGE_NT_HEADERS)){ //含有"PE"
- file.Seek(dos_header.e_lfanew+sizeof(IMAGE_NT_HEADERS)+
- (nt_header.FileHeader.NumberOfSections-1)*sizeof(IMAGE_SECTION_HEADER),CFile::begin);
- file.Read(§ion_header,sizeof(section_header));
- if(!strncmp((char*)section_header.Name,".SD-3",5)){//发现SD-3病毒
- BYTE VirusChar[15]={0x55,0x8b,0xec,0x81,0xc4,0xb8, //病毒特征码
- 0xfe,0xff,0xff,0x60,0xb0,0x2a,0x88,0x45,0xfa};
- file.Seek(section_header.PointerToRawData,CFile::begin);
- ptr=new BYTE[section_header.Misc.VirtualSize];
- file.Read(ptr,section_header.Misc.VirtualSize);
- for(int i=0;i<(int)section_header.Misc.VirtualSize-15;i++){
- if(!memcmp(ptr+i,VirusChar,15)){ //发现了病毒特征码
- inf="无法清除的SD-3病毒:";
- inf+=FileName;
- m_List.AddString(inf);
- }}}
- }}}
- endthis_2:
- file.Close();
- file.SetStatus(FileName,rStatus);
- }
- */
- return TRUE;
- }
- //搜索其下所有子目录及文件.
- void CScanDiskDlg::SearchFolder(char *path)
- {
- HANDLE h;
- WIN32_FIND_DATA dat;
- BOOL re;
- char dir[300];
- strcpy(dir,path);
- strcat(dir,"\\*.*");
- h=FindFirstFile(dir,&dat);
- if(h==INVALID_HANDLE_VALUE){
- //AfxMessageBox(dir);
- return;
- }
- char FullName[300];
- do{
- re=FindNextFile(h,&dat);
- if(!re)break;
- if(!strncmp(dat.cFileName,"..",2))continue;
- if(!(FILE_ATTRIBUTE_DIRECTORY&dat.dwFileAttributes)){ //不是目录
- strcpy(FullName,path);
- strcat(FullName,"\\\0");
- strcat(FullName,dat.cFileName);
- //CString exe=dat.cFileName;
- //exe.MakeLower();
- //if(-1!=exe.Find(".exe",2))m_List.AddString(FullName);
- m_Static.SendMessage(WM_SETTEXT,0,(LPARAM)(LPCTSTR)FullName);
- ProcessFile(FullName);
- TotalFileNum++;
- }
- else { //是目录,进入子目录
- char next[300];
- strcpy(next,path);
- strcat(next,"\\\0");
- strcat(next,dat.cFileName);
- //m_List.AddString(next);
- SearchFolder(next);
- }
- }while(Status);
- FindClose(h);
- }
- void CScanDiskDlg::OnChangeEpartition()
- {
- UpdateData();
- }
- void CScanDiskDlg::OnBsave()
- {
- AfxMessageBox("结果保存在c:\\inf.txt");
- CFile fp;
- fp.Open("c:\\inf.txt",CFile::modeCreate|CFile.modeWrite);
- if(!fp)return;
- int col=m_List.GetCount();
- if(col==LB_ERR){ fp.Close(); return; }
- char s[400];
- for(int i=0;i<col;i++){
- memset(s,0,400);
- m_List.GetText(i,s);
- strcat(s,"\r\n");
- fp.Write(s,strlen(s));
- }
- fp.Close();
- }
复制代码 作者:yincheng01 发表于2011-12-14 23:58:56 原文链接
|
|