杀毒软件的简单实现

dahubaobao [E.S.T]
#define DEBUGMSG
#include <windows.h>
#include <windef.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "Psapi.h"#pragma comment (lib,"Psapi.lib")
#define erron GetLastError ()
#define FIVE 50
#define HIGH 255TCHAR name[FIVE]={0}; //保存虫虫的文件名+路径
FILE *Gfp=NULL; //输出到文件BOOL ScanVXER (LPTSTR V_FileName,long V_FileOffset,int V_Length,TCHAR *V_Contents);
//匹配特征码函数BOOL ScanFileVXER (LPTSTR FileName);
//文件遍历函数BOOL ProcessVXER (void);
//枚举进程函数BOOL KillProc (DWORD ProcessID);
//杀进程函数BOOL EnablePrivilege(LPTSTR PrivilegeName);
//提升权限函数BOOL RegDelVXER (void);
//删除注册表项函数void Usage (LPCTSTR Parameter);
//帮助函数int main (int argc, TCHAR *argv[])
{
 if (argc!=2)
 {
 Usage(argv[0]);
 return 0;
 } #ifdef DEBUGMSG
 Gfp=fopen("VXER.txt","a+"); if (Gfp==NULL)
 {
 printf("Open \"VXER.txt\" fail\n");
 return 0;
 } fprintf(Gfp,"%s\n\n","[-------------------------File list-------------------------]");
 #endif if (strlen(argv[1])>10)
 {
 printf("Fine name no larger than \"10\"\n");
 return 0;
 } if (!(ScanFileVXER(argv[1])))
 {
 #ifdef DEBUGMSG
 printf("ScanFileVXER() GetLastError reports %d\n",erron);
 #endif
 fclose(Gfp);
 return 0;
 }

 if (!(ProcessVXER()))
 {
 #ifdef DEBUGMSG
 printf("ProcessesVXER() GetLastError reports %d\n",erron);
 #endif
 fclose(Gfp);
 return 0;
 } if (!(RegDelVXER()))
 {
 #ifdef DEBUGMSG
 printf("RegDelVXER() GetLastError reports %d\n",erron);
 #endif
 fclose(Gfp); 
 return 0;
 } fclose(Gfp);
 return 0;
}BOOL ScanFileVXER (LPTSTR FileName)
{
 WIN32_FIND_DATA FindFileData;
 DWORD lpBufferLength=HIGH;
 TCHAR lpBuffer[HIGH]={0};
 TCHAR DirBuffer[HIGH]={0};
 HANDLE hFind=NULL;
 UINT count=0; long FileOffset=0x1784; //偏移地址
 int FileLength=0x77; //长度 TCHAR Contents[]={
 0x49, 0x20, 0x6A, 0x75, 0x73, 0x74, 0x20, 0x77, 0x61, 0x6E, 0x74, 0x20, 0x74, 0x6F, 0x20, 0x73,
 0x61, 0x79, 0x20, 0x4C, 0x4F, 0x56, 0x45, 0x20, 0x59, 0x4F, 0x55, 0x20, 0x53, 0x41, 0x4E, 0x21,
 0x21, 0x20, 0x62, 0x69, 0x6C, 0x6C, 0x79, 0x20, 0x67, 0x61, 0x74, 0x65, 0x73, 0x20, 0x77, 0x68,
 0x79, 0x20, 0x64, 0x6F, 0x20, 0x79, 0x6F, 0x75, 0x20, 0x6D, 0x61, 0x6B, 0x65, 0x20, 0x74, 0x68,
 0x69, 0x73, 0x20, 0x70, 0x6F, 0x73, 0x73, 0x69, 0x62, 0x6C, 0x65, 0x20, 0x3F, 0x20, 0x53, 0x74,
 0x6F, 0x70, 0x20, 0x6D, 0x61, 0x6B, 0x69, 0x6E, 0x67, 0x20, 0x6D, 0x6F, 0x6E, 0x65, 0x79, 0x20,
 0x61, 0x6E, 0x64, 0x20, 0x66, 0x69, 0x78, 0x20, 0x79, 0x6F, 0x75, 0x72, 0x20, 0x73, 0x6F, 0x66,
 0x74, 0x77, 0x61, 0x72, 0x65, 0x21, 0x21};
 //从冲击波中提取出来的,用做特征码 //获取系统目录的完整路径
 if (GetSystemDirectory(DirBuffer,lpBufferLength)!=0)
 {
 if (SetCurrentDirectory(DirBuffer)!=0) //设置为当前目录
 {
 hFind=FindFirstFile(FileName,&FindFileData); //查找文件
 if (hFind==INVALID_HANDLE_VALUE)
 {
 #ifdef DEBUGMSG
 printf("FindFirstFile() GetLastError reports %d\n",erron);
 #endif
 if (hFind!=NULL)
 FindClose(hFind);
 return FALSE;
 }
 else
 {
 count++; //获得文件的完整路径
 if (GetFullPathName(FindFileData.cFileName,lpBufferLength,lpBuffer,NULL)!=0)
 {
 #ifdef DEBUGMSG
 fprintf(Gfp,"File:\t\t%s\n",lpBuffer);
 #else
 printf("File:\t\t%s\n",lpBuffer);
 #endif
 }
 else
 {
 #ifdef DEBUGMSG
 printf("GetFullPathName() GetLastError reports %d\n",erron);
 #endif
 if (hFind!=NULL)
 FindClose(hFind);
 return FALSE;
 }
 }

 //进行特征码匹配工作
 ScanVXER(FindFileData.cFileName,FileOffset,FileLength,Contents);
 }
 } while (FindNextFile(hFind,&FindFileData)) //继续查找文件
 {
 count++; //以"."和".."除外
 if (strcmp(".",FindFileData.cFileName)==0||strcmp("..",FindFileData.cFileName)==0)
 {
 #ifdef DEBUGMSG
 printf("File no include \".\" and \"..\"\n");
 #endif
 if (hFind!=NULL)
 FindClose(hFind); fclose(Gfp);
 exit(0);
 } if (GetFullPathName(FindFileData.cFileName,lpBufferLength,lpBuffer,NULL)!=0)
 {
 #ifdef DEBUGMSG
 fprintf(Gfp,"Next File:\t%s\n",lpBuffer);
 #else
 printf("Next File:\t%s\n",lpBuffer);
 #endif
 }
 else
 {
 #ifdef DEBUGMSG
 printf("GetFullPathName() GetLastError reports %d\n",erron);
 #endif
 if (hFind!=NULL)
 FindClose(hFind); fclose(Gfp);
 exit(0);
 }

 ScanVXER(FindFileData.cFileName,FileOffset,FileLength,Contents);

 } fprintf(Gfp,"\nFile Total:%d\n\n",count);
 fprintf(Gfp,"%s\n\n","[-------------------------File end---------------------------]\n"); printf("File Total:%d\n",count); //打印出查找到的文件各数
 if (hFind!=NULL)
 FindClose(hFind); //关闭搜索句柄
 return TRUE;
}BOOL ScanVXER (
LPTSTR V_FileName, //文件名
long V_FileOffset, //偏移地址
int V_Length, //长度
TCHAR *V_Contents) //具体内容
{
 TCHAR FileContents[HIGH]={0};
 int cmpreturn=0;
 FILE *fp=NULL; fp=fopen(V_FileName,"rb"); //以二进制只读方式打开
 if (fp==NULL)
 {
 #ifdef DEBUGMSG
 printf("fopen() File open FAIL\n");
 #endif
 fclose(fp);
 return FALSE;
 } fseek(fp,V_FileOffset,SEEK_SET); //把文件指针指向特征码在文件的偏移地址处
 fread(FileContents,V_Length,1,fp);//读取长度为特征码长度的内容
 cmpreturn=memcmp(V_Contents,FileContents,V_Length);
 //进行特征码匹配。失败返回FALSE if (cmpreturn==0)
 {
 #ifdef DEBUGMSG
 printf("File match completely\n"); //打印文件匹配消息
 #endif
 strcpy(name,V_FileName); //将文件名保存在全局变量name中
 if (fp!=NULL)
 fclose(fp);
 return TRUE;
 }
 else
 {
 fclose(fp);
 return FALSE;
 }}
BOOL ProcessVXER (void)
{
 DWORD lpidProcess[1024]={0};
 DWORD cbNeeded_1,cbNeeded_2;
 HANDLE hProc=NULL;
 HMODULE hMod[1024]={0};
 TCHAR ProcFile[MAX_PATH];
 TCHAR FileName[FIVE]={0};
 UINT Pcount=0;
 int i=0; EnablePrivilege(SE_DEBUG_NAME); //提升调试进程权限
 fprintf(Gfp,"%s\n\n","[------------------------Process list--------------------------]");
 strcpy(FileName,"C:\\WINNT\\system32\\");
 strcat(FileName,name);//把文件名+路径复制到FileName变量中 //枚举进程
 if (!(EnumProcesses(lpidProcess,sizeof(lpidProcess),&cbNeeded_1)))
 {
 #ifdef DEBUGMSG
 printf("EnumProcesses() GetLastError reports %d\n",erron);
 #endif
 if (hProc!=NULL)
 CloseHandle(hProc);
 return FALSE;
 } for (i=0;i<(int)cbNeeded_1/4;i++)
 {
 //打开找到的第一个进程
 hProc=OpenProcess(PROCESS_ALL_ACCESS,FALSE,lpidProcess[i]); if (hProc)
 {
 //枚举进程模块
 if (EnumProcessModules(hProc,hMod,sizeof(hMod),&cbNeeded_2))
 {
 //枚举进程模块文件名,包含全路径
 if (GetModuleFileNameEx(hProc,hMod[0],ProcFile,sizeof(ProcFile)))
 {
 #ifdef DEBUGMSG
 fprintf(Gfp,"[%5d]\t%s\n",lpidProcess[i],ProcFile);
 #else
 printf("[%5d]\t%s\n",lpidProcess[i],ProcFile); //输出进程
 #endif
 //可以考虑将其注释掉,这样就不会输出进程列表了
 Pcount++; //查找进程中是否包含FileName
 if (strcmp(FileName,ProcFile)==0)
 {
 //如果包含,则杀掉。KillProc为自定义的杀进程函数
 if (!(KillProc(lpidProcess[i])))
 {
 #ifdef DEBUGMSG
 printf("KillProc() GetLastError reports %d\n",erron);
 #endif
 if (hProc!=NULL)
 CloseHandle(hProc); fclose(Gfp);
 exit(0);
 } DeleteFile(FileName); //进程杀掉后,再将文件删除
 }
 }
 }
 }
 } if (hProc!=NULL)
 CloseHandle(hProc); //关闭进程句柄 fprintf(Gfp,"\nProcess total:%d\n\n",Pcount);
 fprintf(Gfp,"%s\n\n","[------------------------Process end----------------------------]"); printf("\nProcess total:%d\n\n",Pcount); //打印进程各数
 return TRUE;
}BOOL KillProc (DWORD ProcessID)
{
 HANDLE hProc=NULL; //打开由ProcessVXER()传递的进程PID
 hProc=OpenProcess(PROCESS_ALL_ACCESS,FALSE,ProcessID); if (hProc!=NULL)
 {
 //终止进程
 if (!(TerminateProcess(hProc,0)))
 {
 #ifdef DEBUGMSG
 printf("TerminateProcess() GetLastError reports %d\n",erron);
 #endif
 CloseHandle(hProc);
 return FALSE;
 }
 }
 else
 {
 #ifdef DEBUGMSG
 printf("OpenProcess() GetLastError reports %d\n",erron);
 #endif
 return FALSE;
 } if (hProc!=NULL)
 CloseHandle(hProc); return TRUE;
}BOOL EnablePrivilege(LPTSTR PrivilegeName)
{
 HANDLE hProc=NULL,hToken=NULL;
 TOKEN_PRIVILEGES TP;
 hProc=GetCurrentProcess(); //打开当前进程的一个伪句柄 //打开进程访问令牌,hToken表示新打开的访问令牌标识
 if(!OpenProcessToken(hProc,TOKEN_ADJUST_PRIVILEGES,&hToken))
 {
 #ifdef DEBUGMSG
 printf("OpenProcessToken() GetLastError reports %d\n",erron);
 #endif
 goto Close;
 } //提升权限
 if(!LookupPrivilegeValue(NULL,PrivilegeName,&TP.Privileges[0].Luid))
 {
 #ifdef DEBUGMSG
 printf("LookupPrivilegeValue() GetLastError reports %d\n",erron);
 #endif
 goto Close;
 } TP.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
 TP.PrivilegeCount=1; //允许权限,主要根据TP这个结构
 if(!AdjustTokenPrivileges(hToken,FALSE,&TP,sizeof(TP),0,0))
 {
 #ifdef DEBUGMSG
 printf("AdjustTokenPrivileges() GetLastError reports %d\n",erron);
 #endif
 goto Close;
 } Close:
 if (hProc!=NULL)
 CloseHandle(hProc); if (hToken!=NULL)
 CloseHandle(hToken); return FALSE;
 if (hProc!=NULL)
 CloseHandle(hProc); if (hToken!=NULL)
 CloseHandle(hToken); return TRUE;
}BOOL RegDelVXER (void)
{
 HKEY hkey;
 DWORD ret=0; //打开注册表的Run项
 ret=RegOpenKeyEx(HKEY_LOCAL_MACHINE,
 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\\",
 0,
 KEY_ALL_ACCESS,
 &hkey); if (!(ret==ERROR_SUCCESS))
 {
 #ifdef DEBUGMSG
 printf("RegOpenKeyEx() GetLastError reports %d\n",erron);
 #endif
 return FALSE;
 } //删除键值windows auto update。
 ret=RegDeleteValue(hkey,"windows auto update"); if (ret==ERROR_SUCCESS)
 {
 #ifdef DEBUGMSG
 printf("Success Delete\n");
 #endif
 }
 else
 {
 #ifdef DEBUGMSG
 printf("RegDeleteValue() GetLastError reports %d\n",erron);
 #endif
 RegCloseKey(hkey);
 //exit(0);
 } RegCloseKey(hkey); //关闭打开的注册表项
 return TRUE;
}void Usage (LPCTSTR Parameter)
{
 LPCTSTR Path="%SystemRoot%\\system32\\";

fprintf(stderr,"============================================================================\n"

" 杀毒软件的简单实现\n"
 "环境:Win2K Adv Server + Visual C++ 6.0\n"
 "作者:dahubaobao\n"
 "主页:[url][/url]\n"
 "OICQ:382690\n"
 "邮件:[email]382690@[/email]\n"
 "声明:本帖由环行区(RingZ)原创,转载请注明出处,谢谢!\n\n"
 "使用方法:\n"
 "%s 文件名。例如:%s msblast.exe or %s *.exe \n\n"
 "注意事项:\n"
 "本程序只是简单介绍杀毒软件的编写方法,所以有很多不完善的地方,包括:\n"
 "1,本程序是以冲击波蠕虫做的例子\n"
 "2,文件遍历只搜索了%s目录下的文件\n"
 "3,本程序不能查杀冲击波变种\n\n"
 "本程序只是用做代码交流,如有错误,还请多多包含!\n"
 "============================================================================"
 ,Parameter,Parameter,Parameter,Path);
}