病毒查杀实现
對指定文件及指定特征碼進(jìn)行查殺
??首先要求用戶輸入查殺文件的絕對路徑,通過access()函數(shù)進(jìn)行路徑正確性的驗證。access()函數(shù)位于頭文件“io.h”中,其存在兩個參數(shù),第一個參數(shù)為需要驗證的目標(biāo)文件或文件夾路徑,第二個參數(shù)為驗證模式,詳細(xì)信息如下:
| F_OK = 0 | 僅判斷是否存在 |
| X_OK = 1 | 判斷是否有執(zhí)行權(quán)限 |
| W_OK = 2 | 僅判斷是否有寫權(quán)限 |
| R_OK = 4 | 僅判斷是否有讀權(quán)限 |
??因此,我們使用參數(shù)“0”來檢測用戶輸入地址是否合法。同理完成特征碼文件指定路徑的驗證工作。部分代碼如下:
do{printf("請輸入查殺文件絕對路徑:");scanf("%s", &file_addr);judge = access(file_addr, 0);if(judge != 0) printf("------------------------\n該路徑錯誤,請重新輸入!"); }while(judge != 0);??由于目標(biāo)查殺文件大小未知,因此不妨設(shè)置一個大小為256M的char類型空間來完成對目標(biāo)文件信息的存儲,該大小由MAXSIZE預(yù)編譯定義。同理,由于特征碼一般較為精簡,設(shè)置存儲其的char類型空間為300B,該大小由SIGSIZE預(yù)編譯定義。這兩組存儲空間均在程序執(zhí)行過程中動態(tài)申請,具體代碼如下:
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;}??依次讀取兩文件信息至內(nèi)存,讀取模式均采用只讀方式讀取,具體代碼如下:
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);??當(dāng)信息加載完成后,使用前期封裝好的頭文件“BM.h”中的BM()函數(shù)來完成特征串的查找工作,具體代碼如下:
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");??利用前期實驗自行編寫的宏病毒文件提取特征碼后進(jìn)行查找測試,驗證該程序的正確性,該目標(biāo)文件及特征碼信息如下:
??對宏病毒文件進(jìn)行指定查殺,結(jié)果如下:??具體完整代碼如下:
#include <stdio.h> #include <io.h> #include <windows.h> #include <string.h> #include "BM.h"#define MAXSIZE 104857600 #define SIGSIZE 300int main(){printf("------該程序?qū)⑼瓿蓪χ付ㄎ募付ㄌ卣鞔a的查殺------\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 ; }對指定文件夾及指定特征碼進(jìn)行查殺
??程序編寫過程,首先利用access()函數(shù)對用戶輸入的地址信息進(jìn)行檢測,當(dāng)輸入地址信息正確后,對目標(biāo)文件夾字符串進(jìn)行處理,使其以字符“\”結(jié)尾,以完成與SearchFile()函數(shù)的接口。接著申請需要存目標(biāo)文件信息的空間和存特征碼的空間,將其兩者作為參數(shù)傳給SearchFile()函數(shù)進(jìn)行處理,以保證空間不會多申請或少申請,同時節(jié)省空間的申請時間。接著讀取特征碼信息至內(nèi)存中,并將其作為參數(shù)傳遞給SearchFile()函數(shù)。隨后執(zhí)行SearchFile()函數(shù),完成對指定文件夾的搜索。當(dāng)搜索完成后釋放申請到的空間信息,并結(jié)束程序。具體代碼如下:
int main(){printf("------該程序?qū)⑼瓿蓪χ付ㄎ募A下指定特征碼的查殺------\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()函數(shù)。首先介紹一下位于“io.h”頭文件中的存儲文件信息的結(jié)構(gòu)體“_finddata_t”,其結(jié)構(gòu)體具體信息如下:
??其中,“attrib”記錄文件屬性,如:是否隱藏、是否為文件夾、是否只讀等;“time_create”記錄文件創(chuàng)建時間;“time_access”記錄文件最后被訪問時間;“time_write”記錄文件最后被修改時間;“size”記錄文件大小;“name”記錄文件名,包括文件后綴。
??“attrib”作為unsigned類型,通過對應(yīng)位進(jìn)行文件屬性的存儲,而“io.h”頭文件中也給出了相關(guān)的參數(shù)信息,如下:
| _A_ARCH | 存檔 |
| _A_HIDDEN | 隱藏 |
| _A_NORMAL | 正常 |
| _A_RDONLY | 只讀 |
| _A_SUBDIR | 文件夾 |
| _A_SYSTEM | 系統(tǒng) |
??而對于每一個文件夾,其目錄下都存在兩個隱藏的文件夾,分別為“.”和“…”,表示上級目錄和下級目錄。因此在讀取文件夾信息時,需要對這兩個隱藏文件夾進(jìn)行過濾。對于文件的搜索,支持通配符搜索,因此當(dāng)我們對所有類型的文件都進(jìn)行查殺時,需要將文件路徑參數(shù)修改為“*.*”結(jié)尾。
??SearchFile(char *file_addr, char *sig, int sig_len, char *dest_file)函數(shù)參數(shù)含義如下:“file_addr”為指定搜索的文件夾路徑信息;“sig”為特征碼字符串首地址;“sig_len”為特征碼長度;“dest_file”為目標(biāo)文件信息加載到的內(nèi)存首地址。
??首先,指定文件搜索類型為所有文件,因此使用通配符“*.*”,如下:
??接著,聲明文件操作結(jié)構(gòu)體FileData,并生成文件操作句柄hfile。利用函數(shù)“_findfirst”來找到指定文件夾下的文件,當(dāng)返回值為-1時,表示該路徑下不包含任何文件,此時,對用戶進(jìn)行信息反饋并等待退出程序。代碼如下:
struct _finddata_t FileData;long hfile; //文件操作句柄 if((hfile = _findfirst(file, &FileData)) == -1L){printf("該路徑下不包含任何文件!\n");_findclose(hfile);system("pause");return;}??接著對文件夾下各文件進(jìn)行處理。當(dāng)文件夾為隱藏文件夾時,直接獲取下一個文件信息。利用按位與操作判斷獲取到的文件是否為文件夾,當(dāng)為文件夾時,需要進(jìn)入該文件夾再次執(zhí)行SearchFile()函數(shù),完成深度文件查找;此時需要注意對文件夾路徑信息進(jìn)行更改,以適應(yīng)SearchFile()函數(shù)的操作流程。當(dāng)獲取到的文件為正常文件時,以二進(jìn)制形式打開文件并存儲至dest_file數(shù)組中,隨后執(zhí)行BM算法對比是否包含特征碼,當(dāng)包含該特征碼信息時,輸出當(dāng)前文件信息。持續(xù)循環(huán)直至遍歷完文件夾。具體代碼如下:
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”獲取到的也僅為該文件夾名,并不包含“\”字符,因此在遞歸進(jìn)行深度遍歷時,需要對傳入的地址信息字符串進(jìn)行添加“\”字符操作。
??對該程序進(jìn)行測試。測試文件夾信息如下,其中“MacroVirus.txt”、“sig.txt”以及“virusin.txt”文件中包含病毒特征碼。
??指定文件夾下指定特征碼查殺程序測試結(jié)果如下:
??具體完整代碼如下:
#include <stdio.h> #include <io.h> #include <windows.h> #include <string.h> #include "BM.h"#define MAXSIZE 104857600 #define SIGSIZE 300void SearchFile(char *file_addr, char *sig, int sig_len, char *dest_file);int main(){printf("------該程序?qū)⑼瓿蓪χ付ㄎ募A下指定特征碼的查殺------\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; }多特征碼查殺
??首先定義存儲特征碼的文件格式為:病毒名、特征碼。根據(jù)該特征碼文件結(jié)構(gòu)創(chuàng)建病毒特征碼結(jié)構(gòu)體,如下:
typedef struct VirSig{char name[30];char sig[SIGSIZE];int len; }VirSig;??按照文件存儲結(jié)構(gòu)讀取特征碼信息,由于使用fgets()函數(shù)會在每一行的信息后讀取“\r\n”之后再自動添加“\0”,因此需要對讀取到的字符串進(jìn)行修改,使其成為真正的特征碼。代碼如下:
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;}??主函數(shù)框架保持不變,對BM算法部分進(jìn)行循環(huán)操作,對病毒特征碼結(jié)構(gòu)體中存儲的所有特征碼進(jìn)行遍歷,驗證是否存在病毒。代碼如下:
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);}}??對該程序進(jìn)行測試,測試文件夾信息如下。其中“copy.cpp” 、“sigs.txt”中存在復(fù)制型病毒;“MacroVirus.txt”、“sig.txt”、“sigs.txt”、“virusin.txt”中存在宏病毒。
??對該程序的測試結(jié)果如下:
??成功執(zhí)行程序功能,具體代碼如下:
#include <stdio.h> #include <io.h> #include <windows.h> #include <string.h> #include "BM2.h"#define MAXSIZE 104857600 #define SIGSIZE 300 #define NODESIZE 10typedef 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("------該程序?qū)⑼瓿蓪χ付ㄎ募A下指定特征碼的查殺------\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宏病毒設(shè)計傳播及優(yōu)化
總結(jié)
- 上一篇: opencv 美白磨皮人脸检测
- 下一篇: hive 的 left semi joi