病毒查杀实现

对指定文件及指定特征码进行查杀

  首先要求用户输入查杀文件的绝对路径,通过access()函数进行路径正确性的验证。access()函数位于头文件“io.h”中,其存在两个参数,第一个参数为需要验证的目标文件或文件夹路径,第二个参数为验证模式,详细信息如下:

参数 对应模式
F_OK = 0 仅判断是否存在
X_OK = 1 判断是否有执行权限
W_OK = 2 仅判断是否有写权限
R_OK = 4 仅判断是否有读权限

  因此,我们使用参数“0”来检测用户输入地址是否合法。同理完成特征码文件指定路径的验证工作。部分代码如下:

	do{
    
    
		printf("请输入查杀文件绝对路径:");
		scanf("%s", &file_addr);
		judge = access(file_addr, 0);
		if(judge != 0)  printf("------------------------\n该路径错误,请重新输入!"); 
	}while(judge != 0);

  由于目标查杀文件大小未知,因此不妨设置一个大小为256M的char类型空间来完成对目标文件信息的存储,该大小由MAXSIZE预编译定义。同理,由于特征码一般较为精简,设置存储其的char类型空间为300B,该大小由SIGSIZE预编译定义。这两组存储空间均在程序执行过程中动态申请,具体代码如下:

	char *dest_file = (char*)malloc(sizeof(char) * MAXSIZE);
	char *sig = (char*)malloc(sizeof(char) * SIGSIZE);
	if(dest_file == NULL || sig == NULL){
    
    
		printf("空间申请失败!\n");
		system("pause");
		return 0;
	}

  依次读取两文件信息至内存,读取模式均采用只读方式读取,具体代码如下:

	FILE *pf = fopen(file_addr, "r+");
	FILE *psig = fopen(sig_addr, "r+");
	if(pf == NULL || psig == NULL){
    
    
		printf("文件载入失败!\n");
		system("pause");
		return 0;
	}
	
	int i = 0;
	while(!feof(pf)){
    
    
		fread(dest_file + i, 1, 1, pf);
		i++;
	}
	fclose(pf);
	i = 0;
	while(!feof(psig)){
    
    
		fread(sig + i, 1, 1, psig);
		i++;
	}
	fclose(psig);

  当信息加载完成后,使用前期封装好的头文件“BM.h”中的BM()函数来完成特征串的查找工作,具体代码如下:

	int dest_len = strlen(dest_file), sig_len = strlen(sig);
	bool flag = BM(dest_file, dest_len, sig, sig_len);
	if(flag == true){
    
    
		printf("GET VIRUS!\n");
	}
	else printf("NO VIRUS!\n");

  利用前期实验自行编写的宏病毒文件提取特征码后进行查找测试,验证该程序的正确性,该目标文件及特征码信息如下:

  对宏病毒文件进行指定查杀,结果如下:

  具体完整代码如下:

#include <stdio.h>
#include <io.h>
#include <windows.h>
#include <string.h>
#include "BM.h"

#define MAXSIZE 104857600
#define SIGSIZE 300

int main(){
    
    
	printf("------该程序将完成对指定文件指定特征码的查杀------\n\n");
	char file_addr[1000];
	int judge;
	do{
    
    
		printf("请输入查杀文件绝对路径:");
		scanf("%s", &file_addr);
		judge = access(file_addr, 0);
		if(judge != 0)  printf("------------------------\n该路径错误,请重新输入!"); 
	}while(judge != 0);
	char sig_addr[1000];
	do{
    
    
		printf("请输入特征码所在文件路径:");
		scanf("%s", &sig_addr);
		judge = access(sig_addr, 0);
		if(judge != 0)  printf("------------------------\n该路径错误,请重新输入!");
	}while(judge != 0);
	printf("\n------Result------\n");
	
	char *dest_file = (char*)malloc(sizeof(char) * MAXSIZE);
	char *sig = (char*)malloc(sizeof(char) * SIGSIZE);
	if(dest_file == NULL || sig == NULL){
    
    
		printf("空间申请失败!\n");
		system("pause");
		return 0;
	}
	 
	FILE *pf = fopen(file_addr, "r+");
	FILE *psig = fopen(sig_addr, "r+");
	if(pf == NULL || psig == NULL){
    
    
		printf("文件载入失败!\n");
		system("pause");
		return 0;
	}
	
	int i = 0;
	while(!feof(pf)){
    
    
		fread(dest_file + i, 1, 1, pf);
		i++;
	}
	fclose(pf);
	i = 0;
	while(!feof(psig)){
    
    
		fread(sig + i, 1, 1, psig);
		i++;
	}
	fclose(psig);
	
	int dest_len = strlen(dest_file), sig_len = strlen(sig);
	bool flag = BM(dest_file, dest_len, sig, sig_len);
	if(flag == true){
    
    
		printf("GET VIRUS!\n");
	}
	else printf("NO VIRUS!\n");
	
	system("pause");	
	return 0 ;
} 

对指定文件夹及指定特征码进行查杀

  程序编写过程,首先利用access()函数对用户输入的地址信息进行检测,当输入地址信息正确后,对目标文件夹字符串进行处理,使其以字符“\”结尾,以完成与SearchFile()函数的接口。接着申请需要存目标文件信息的空间和存特征码的空间,将其两者作为参数传给SearchFile()函数进行处理,以保证空间不会多申请或少申请,同时节省空间的申请时间。接着读取特征码信息至内存中,并将其作为参数传递给SearchFile()函数。随后执行SearchFile()函数,完成对指定文件夹的搜索。当搜索完成后释放申请到的空间信息,并结束程序。具体代码如下:

int main(){
    
    
	printf("------该程序将完成对指定文件夹下指定特征码的查杀------\n\n");
	char file_addr[1000];
	int judge;
	do{
    
    
		printf("请输入查杀文件夹绝对路径:");
		scanf("%s", &file_addr);
		judge = access(file_addr, 0);
		if(judge != 0)  printf("------------------------\n该路径错误,请重新输入!"); 
	}while(judge != 0);
	char sig_addr[1000];
	do{
    
    
		printf("请输入特征码所在文件路径:");
		scanf("%s", &sig_addr);
		judge = access(sig_addr, 0);
		if(judge != 0)  printf("------------------------\n该路径错误,请重新输入!");
	}while(judge != 0);
	printf("\n------Result------\n");
	
	if(file_addr[strlen(file_addr) - 1] != '\\')
		strcat(file_addr, "\\");
	
	FILE *psig = fopen(sig_addr, "rb");
	if(psig == NULL){
    
    
		printf("特征码载入失败!\n");
		system("pause");
		return 0;
	}
	char *sig = (char*)malloc(sizeof(char) * SIGSIZE);
	char *dest_file = (char*)malloc(sizeof(char) * MAXSIZE);
	if(sig == NULL || dest_file == NULL){
    
    
		printf("空间申请失败!\n");
		system("pause");
		return 0;
	}
	int i = 0, sig_len;
	sig_len = fread(sig, 1, SIGSIZE, psig); 
	
	SearchFile(file_addr, sig, sig_len, dest_file);
	
	free(sig);
	free(dest_file);

	return 0 ;
}

  接下来重点解读SearchFile()函数。首先介绍一下位于“io.h”头文件中的存储文件信息的结构体“_finddata_t”,其结构体具体信息如下:

  其中,“attrib”记录文件属性,如:是否隐藏、是否为文件夹、是否只读等;“time_create”记录文件创建时间;“time_access”记录文件最后被访问时间;“time_write”记录文件最后被修改时间;“size”记录文件大小;“name”记录文件名,包括文件后缀。
  “attrib”作为unsigned类型,通过对应位进行文件属性的存储,而“io.h”头文件中也给出了相关的参数信息,如下:

参数 功能
_A_ARCH 存档
_A_HIDDEN 隐藏
_A_NORMAL 正常
_A_RDONLY 只读
_A_SUBDIR 文件夹
_A_SYSTEM 系统

  而对于每一个文件夹,其目录下都存在两个隐藏的文件夹,分别为“.”和“…”,表示上级目录和下级目录。因此在读取文件夹信息时,需要对这两个隐藏文件夹进行过滤。对于文件的搜索,支持通配符搜索,因此当我们对所有类型的文件都进行查杀时,需要将文件路径参数修改为“*.*”结尾。
  SearchFile(char *file_addr, char *sig, int sig_len, char *dest_file)函数参数含义如下:“file_addr”为指定搜索的文件夹路径信息;“sig”为特征码字符串首地址;“sig_len”为特征码长度;“dest_file”为目标文件信息加载到的内存首地址。
  首先,指定文件搜索类型为所有文件,因此使用通配符“*.*”,如下:

	char file[1000];
	strcpy(file, file_addr);
	strcat(file, "*.*");

  接着,声明文件操作结构体FileData,并生成文件操作句柄hfile。利用函数“_findfirst”来找到指定文件夹下的文件,当返回值为-1时,表示该路径下不包含任何文件,此时,对用户进行信息反馈并等待退出程序。代码如下:

	struct _finddata_t FileData;
	long hfile;  //文件操作句柄 
	if((hfile = _findfirst(file, &FileData)) == -1L){
    
    
		printf("该路径下不包含任何文件!\n");
		_findclose(hfile);
		system("pause");
		return;
	}

  接着对文件夹下各文件进行处理。当文件夹为隐藏文件夹时,直接获取下一个文件信息。利用按位与操作判断获取到的文件是否为文件夹,当为文件夹时,需要进入该文件夹再次执行SearchFile()函数,完成深度文件查找;此时需要注意对文件夹路径信息进行更改,以适应SearchFile()函数的操作流程。当获取到的文件为正常文件时,以二进制形式打开文件并存储至dest_file数组中,随后执行BM算法对比是否包含特征码,当包含该特征码信息时,输出当前文件信息。持续循环直至遍历完文件夹。具体代码如下:

	int dest_len;
	bool flag;
	do{
    
    
		if(!strcmp(FileData.name, ".") || !strcmp(FileData.name, ".."))
			continue;
		
		if(FileData.attrib & _A_SUBDIR){
    
    
			strcpy(file, file_addr);
			strcat(file, FileData.name);
			strcat(file, "\\");
			SearchFile(file, sig, sig_len, dest_file);
		}
		else{
    
    
			strcpy(file, file_addr);
			strcat(file, FileData.name);
			FILE *pf = fopen(file, "rb");
			if(pf == NULL){
    
    
				printf("%s文件载入失败!\n", FileData.name);
				continue;
			}
			dest_len = fread(dest_file, 1, MAXSIZE, pf);
			flag = BM(dest_file, dest_len, sig, sig_len);
			if(flag == true){
    
    
				printf("FIND THE VIRUS IN FILE %s\n", FileData.name);
			}			
		}			
	}while(_findnext(hfile, &FileData) == 0);
	_findclose(hfile);

  需要注意的是,即使访问的是一个文件夹,利用“FileData.name”获取到的也仅为该文件夹名,并不包含“\”字符,因此在递归进行深度遍历时,需要对传入的地址信息字符串进行添加“\”字符操作。
  对该程序进行测试。测试文件夹信息如下,其中“MacroVirus.txt”、“sig.txt”以及“virusin.txt”文件中包含病毒特征码。

  指定文件夹下指定特征码查杀程序测试结果如下:

  具体完整代码如下:

#include <stdio.h>
#include <io.h>
#include <windows.h>
#include <string.h>
#include "BM.h"

#define MAXSIZE 104857600
#define SIGSIZE 300

void SearchFile(char *file_addr, char *sig, int sig_len, char *dest_file);

int main(){
    
    
	printf("------该程序将完成对指定文件夹下指定特征码的查杀------\n\n");
	char file_addr[1000];
	int judge;
	do{
    
    
		printf("请输入查杀文件夹绝对路径:");
		scanf("%s", &file_addr);
		judge = access(file_addr, 0);
		if(judge != 0)  printf("------------------------\n该路径错误,请重新输入!"); 
	}while(judge != 0);
	char sig_addr[1000];
	do{
    
    
		printf("请输入特征码所在文件路径:");
		scanf("%s", &sig_addr);
		judge = access(sig_addr, 0);
		if(judge != 0)  printf("------------------------\n该路径错误,请重新输入!");
	}while(judge != 0);
	printf("\n------Result------\n");
	
	if(file_addr[strlen(file_addr) - 1] != '\\')
		strcat(file_addr, "\\");
	
	FILE *psig = fopen(sig_addr, "rb");
	if(psig == NULL){
    
    
		printf("特征码载入失败!\n");
		system("pause");
		return 0;
	}
	char *sig = (char*)malloc(sizeof(char) * SIGSIZE);
	char *dest_file = (char*)malloc(sizeof(char) * MAXSIZE);
	if(sig == NULL || dest_file == NULL){
    
    
		printf("空间申请失败!\n");
		system("pause");
		return 0;
	}
	int i = 0, sig_len;
	sig_len = fread(sig, 1, SIGSIZE, psig); 
	
	SearchFile(file_addr, sig, sig_len, dest_file);
	
	free(sig);
	free(dest_file);

	return 0 ;
} 

void SearchFile(char *file_addr, char *sig, int sig_len, char *dest_file){
    
    
	char file[1000];
	strcpy(file, file_addr);
	strcat(file, "*.*");
	
	struct _finddata_t FileData;
	long hfile;  //文件操作句柄 
	if((hfile = _findfirst(file, &FileData)) == -1L){
    
    
		printf("该路径下不包含任何文件!\n");
		_findclose(hfile);
		system("pause");
		return;
	}
	
	int dest_len;
	bool flag;
	do{
    
    
		if(!strcmp(FileData.name, ".") || !strcmp(FileData.name, ".."))
			continue;
		
		if(FileData.attrib & _A_SUBDIR){
    
    
			strcpy(file, file_addr);
			strcat(file, FileData.name);
			strcat(file, "\\");
			SearchFile(file, sig, sig_len, dest_file);
		}
		else{
    
    
			strcpy(file, file_addr);
			strcat(file, FileData.name);
			FILE *pf = fopen(file, "rb");
			if(pf == NULL){
    
    
				printf("%s文件载入失败!\n", FileData.name);
				continue;
			}
			dest_len = fread(dest_file, 1, MAXSIZE, pf);
			flag = BM(dest_file, dest_len, sig, sig_len);
			if(flag == true){
    
    
				printf("FIND THE VIRUS IN FILE %s\n", FileData.name);
			}			
		}			
	}while(_findnext(hfile, &FileData) == 0);
	_findclose(hfile);
	printf("\n------THAT\'S ALL IN DIR %s------\n", file_addr);
	
	return;
}

多特征码查杀

  首先定义存储特征码的文件格式为:病毒名、特征码。根据该特征码文件结构创建病毒特征码结构体,如下:

typedef struct VirSig{
    
    
	char name[30];
	char sig[SIGSIZE];
	int len;
}VirSig;

  按照文件存储结构读取特征码信息,由于使用fgets()函数会在每一行的信息后读取“\r\n”之后再自动添加“\0”,因此需要对读取到的字符串进行修改,使其成为真正的特征码。代码如下:

	int i = 0, node_size;
	while(!feof(psig)){
    
    
		fgets(sig_node[i].name, 30, psig);
		fgets(sig_node[i].sig, SIGSIZE, psig);
		sig_node[i].len = strlen(sig_node[i].sig);
		i++;
	}
	fclose(psig);
	node_size = i;
	i--;
	while(i--){
    
    
		sig_node[i].sig[sig_node[i].len - 2] = '\0';
		sig_node[i].len -= 2;
	}

  主函数框架保持不变,对BM算法部分进行循环操作,对病毒特征码结构体中存储的所有特征码进行遍历,验证是否存在病毒。代码如下:

	for(int i = 0; i < node_size; i++){
    
    
		flag = BM(dest_file, dest_len, sig_node[i].sig, sig_node[i].len);
		if(flag == true){
    
    
			printf("FIND THE VIRUS IN FILE %s\nVIRUS TYPE: %s\n", file, sig_node[i].name);
		}
	}

  对该程序进行测试,测试文件夹信息如下。其中“copy.cpp” 、“sigs.txt”中存在复制型病毒;“MacroVirus.txt”、“sig.txt”、“sigs.txt”、“virusin.txt”中存在宏病毒。

  对该程序的测试结果如下:

  成功执行程序功能,具体代码如下:

#include <stdio.h>
#include <io.h>
#include <windows.h>
#include <string.h>
#include "BM2.h"

#define MAXSIZE 104857600
#define SIGSIZE 300
#define NODESIZE 10

typedef struct VirSig{
    
    
	char name[30];
	char sig[SIGSIZE];
	int len;
}VirSig;

void SearchFile(char *file_addr, VirSig *sig_node, int node_size, char *dest_file);

int main(){
    
    
	printf("------该程序将完成对指定文件夹下指定特征码的查杀------\n\n");
	char file_addr[1000];
	int judge;
	do{
    
    
		printf("请输入查杀文件夹绝对路径:");
		scanf("%s", &file_addr);
		judge = access(file_addr, 0);
		if(judge != 0)  printf("------------------------\n该路径错误,请重新输入!"); 
	}while(judge != 0);
	char sig_addr[1000];
	do{
    
    
		printf("请输入特征码所在文件路径:");
		scanf("%s", &sig_addr);
		judge = access(sig_addr, 0);
		if(judge != 0)  printf("------------------------\n该路径错误,请重新输入!");
	}while(judge != 0);
	printf("\n------Result------\n");
	
	if(file_addr[strlen(file_addr) - 1] != '\\')
		strcat(file_addr, "\\");
	
	FILE *psig = fopen(sig_addr, "rb");
	if(psig == NULL){
    
    
		printf("特征码载入失败!\n");
		system("pause");
		return 0;
	}
	char *dest_file = (char*)malloc(sizeof(char) * MAXSIZE);
	VirSig *sig_node = (VirSig*)malloc(sizeof(VirSig) * NODESIZE);
	if(dest_file == NULL || sig_node == NULL){
    
    
		printf("空间申请失败!\n");
		system("pause");
		return 0;
	}
		
	int i = 0, node_size;
	while(!feof(psig)){
    
    
		fgets(sig_node[i].name, 30, psig);
		fgets(sig_node[i].sig, SIGSIZE, psig);
		sig_node[i].len = strlen(sig_node[i].sig);
		i++;
	}
	fclose(psig);
	node_size = i;
	i--;
	while(i--){
    
    
		sig_node[i].sig[sig_node[i].len - 2] = '\0';
		sig_node[i].len -= 2;
	}
	
	SearchFile(file_addr, sig_node, node_size, dest_file);
	printf("------THAT IS ALL!------\n");
	
	free(sig_node);
	free(dest_file);

	return 0 ;
} 

void SearchFile(char *file_addr, VirSig *sig_node, int node_size, char *dest_file){
    
    
	char file[1000];
	strcpy(file, file_addr);
	strcat(file, "*.*");
	
	struct _finddata_t FileData;
	long hfile;  //文件操作句柄 
	if((hfile = _findfirst(file, &FileData)) == -1L){
    
    
		printf("该路径下不包含任何文件!\n");
		_findclose(hfile);
		system("pause");
		return;
	}
	
	int i, dest_len;
	bool flag;
	do{
    
    
		if(!strcmp(FileData.name, ".") || !strcmp(FileData.name, ".."))
			continue;
		
		if(FileData.attrib & _A_SUBDIR){
    
    
			strcpy(file, file_addr);
			strcat(file, FileData.name);
			strcat(file, "\\");
			SearchFile(file, sig_node, node_size, dest_file);
		}
		else{
    
    
			strcpy(file, file_addr);
			strcat(file, FileData.name);
			FILE *pf = fopen(file, "rb");
			if(pf == NULL){
    
    
				printf("%s文件载入失败!\n", FileData.name);
				continue;
			}
			dest_len = fread(dest_file, 1, MAXSIZE, pf);
			fclose(pf);
			for(int i = 0; i < node_size; i++){
    
    
				flag = BM(dest_file, dest_len, sig_node[i].sig, sig_node[i].len);
				if(flag == true){
    
    
					printf("FIND THE VIRUS IN FILE %s\nVIRUS TYPE: %s\n", file, sig_node[i].name);
				}
			}		
		}			
	}while(_findnext(hfile, &FileData) == 0);
	_findclose(hfile);
		
	return;
}
参考资料

BM算法
Word宏病毒设计传播及优化

猜你喜欢

转载自blog.csdn.net/m0_46161993/article/details/107105650
今日推荐