网站 制作 报价,学做网站的基本,导航网站php,怎样创建网站app前言上次我们已经简介过了病毒特征码提取的基本方法#xff0c;那么这次我们就通过编程来实现对于病毒的特征码查杀。定义特征码存储结构为了简单起见。这次我们使用的是setup.exe以及unpacked.exe这两个病毒样本。经过上次的分析#xff0c;我们对setup.exe样本的特征码提取… 前言 上次我们已经简介过了病毒特征码提取的基本方法那么这次我们就通过编程来实现对于病毒的特征码查杀。 定义特征码存储结构 为了简单起见。这次我们使用的是setup.exe以及unpacked.exe这两个病毒样本。经过上次的分析我们对setup.exe样本的特征码提取例如以下\x2a\x2a\x2a\xce\xe4\x2a\xba\xba\x2a\xc4\xd0\x2a\xc9\xfa\x2a\xb8\xd0\x2a\xc8\xbe\x2a\xcf\xc2\x2a\xd4\xd8\x2a\xd5\xdf\x2a\x2a\x2a 为了方便起见这里同一时候也将该特征码的文件偏移保存下来。即0x0c040。然后是unpacked.exe的特征码\x13\x8b\x45\xf0\xe8\x00\x00\x00\x00\x81\x04\x24\xd7\x86\x00\x00\xff\xd0\xeb\x11\x6a\x10\x68\x30\x80\x40\x00\xff\x75\xfc\x53\xff 它的文件偏移为0x1921。 有了以上的信息就能够開始进行编程了。首先须要定义一个数据结构。用于保存特征码和文件偏移。该结构例如以下#define NAMELEN 20
#define SIGNLEN 32
typedef struct SIGN
{char szVirusName[NAMELEN];LONG lFileOffset;BYTE bVirusSign[SIGNLEN 1];
}_SIGN, *PSIGN; 利用该数据结构定义一个全局变量该全局变量保存有上述两个病毒的特征码定义例如以下SIGN Sign[2]
{
{// setup.exe“setup.exe”,0x0c040,“\x2a\x2a\x2a\xce\xe4\x2a\xba\xba\x2a\xc4\xd0\x2a\xc9\xfa\x2a\xb8” \“\xd0\x2a\xc8\xbe\x2a\xcf\xc2\x2a\xd4\xd8\x2a\xd5\xdf\x2a\x2a\x2a”
},
{// unpacked.exe“unpacked.exe”,0x1920,“\x13\x8b\x45\xf0\xe8\x00\x00\x00\x00\x81\x04\x24\xd7\x86\x00\x00” \“\xff\xd0\xeb\x11\x6a\x10\x68\x30\x80\x40\x00\xff\x75\xfc\x53\xff”
}
}; 至此。病毒特征码的基础定义部分就到这里。上述程序中我是将病毒特征码保存在一个全局变量中大家也能够另外创建一个文件。相似于PEiD的userdb.txt文件。从而专门保存病毒的特征码。现实中的杀毒软件的特征库也是以专门的文件的形式保存在本地计算机中的。这里我为了简单起见选择以全局变量的形式进行保存。 主体程序的编写 首先须要编写一个函数用于对目标程序指定位置处的十六进制代码进行检測BOOL CheckSig(char* FilePath)
{DWORD dwSigNum 0;DWORD dwNum 0;BYTE buffer[SIGNLEN1];int i;HANDLE hFile NULL;hFile CreateFile(FilePath,GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);for(i0; i 1; i){// 将待检測程序的文件指针指向特征码的偏移位置SetFilePointer(hFile, Sign[i].lFileOffset, NULL, FILE_BEGIN);// 读取目标程序指定偏移位置的特征码ReadFile(hFile, buffer, sizeof(buffer), dwNum, NULL);// 特征码的比对if(memcmp(Sign[i].bVirusSign, buffer, SIGNLEN) 0){printf(发现病毒程序%s\n, FilePath);CloseHandle(hFile);return TRUE;}}CloseHandle(hFile);return FALSE;
} 然后就是main函数的编写int main()
{WIN32_FIND_DATA stFindFile;HANDLE hFindFile;char *szFilter *.exe; // 保存搜索的筛选条件全部exe文件char szFindFile[MAX_PATH]; // 保存欲检測的程序的路径char szSearch[MAX_PATH]; // 保存完整筛选路径int ret 0; // 搜索的返回值lstrcpy(szFindFile, E:\\);lstrcpy(szSearch, E:\\);lstrcat(szSearch, szFilter);hFindFile FindFirstFile(szSearch, stFindFile);if(hFindFile ! INVALID_HANDLE_VALUE){do{// 组成完整的待检測程序的路径lstrcat(szFindFile, stFindFile.cFileName);// 利用特征码检測目标程序是不是病毒程序if(!CheckSig(szFindFile)){printf(%s不是病毒程序\n,szFindFile);}// 删除程序名称仅仅保留“E:\”szFindFile[3] \0;ret FindNextFile(hFindFile, stFindFile);}while( ret ! 0 );}FindClose(hFindFile);return 0;
} 上述程序仅仅是检測E盘根文件夹下全部后缀为exe的程序是否为病毒程序其实还能够进行改动。使其能够全盘搜索大家能够參考“熊猫烧香专杀工具”的相关代码部分。另外为了谨慎起见仅仅通过后缀进行exe程序的检測是不严谨的。经常使用的检測一个程序是不是exe程序的方法。就是解析目标程序中的对应位置是否为“MZ”以及“PE”。我这里为了简单起见。就不採用该方法有兴趣的朋友能够自行编程实现。 程序的測试 这里我使用的是Code::Blocks13.12这款开源而且免费的开发环境。由于这款软件能够自己主动计算程序的执行时间便于我们之后的对照操作。为了进行測试我已经在E盘的根文件夹下放置了10个程序。当中4个程序是我们之前讲过的病毒样本。还有6个程序是我们曾经也曾使用过的一些工具软件图1 上图中前方带有小方块的就是病毒样本。然后我们在Code::Blocks中编译执行程序图2 可见程序已经非常成功地识别出了setup.exe以及unpacked.exe这两个病毒样本。其实cf.exe以及OSO.exe也是病毒程序但由于我并没有把这两个样本的特征码增加我们程序的特征库。因此并没能识别出来。最后Code::Blocks还显示出了本次程序的执行时间当然每次的执行时间可能都不一样包含在不同的计算机上执行的结果应该也是不同的。可是通过多次执行进行观察。基本上是0.016秒。也就是16毫秒。 与CRC32病毒识别方式的对照 我们曾经的程序使用的CRC32算法来识别病毒那么我们这里能够对照一下。看看这次我们所讲的方法和CRC32算法在程序运算时间上的优劣。CRC32病毒特征识别的程序例如以下#include stdio.h
#include windows.hDWORD CRC32(BYTE* ptr,DWORD Size)
{DWORD crcTable[256],crcTmp1;//动态生成CRC-32表for (int i0; i256; i){crcTmp1 i;for (int j8; j0; j--){if (crcTmp11) crcTmp1 (crcTmp1 1) ^ 0xEDB88320L;else crcTmp1 1;}crcTable[i] crcTmp1;}//计算CRC32值DWORD crcTmp2 0xFFFFFFFF;while(Size--){crcTmp2 ((crcTmp28) 0x00FFFFFF) ^ crcTable[ (crcTmp2^(*ptr)) 0xFF ];ptr;}return (crcTmp2^0xFFFFFFFF);
}
//
// 计算程序的CRC32值。输入为文件路径输出为DWORD类型的CRC32值
//
DWORD CalcCRC32(char* FilePath)
{HANDLE hFile CreateFile(FilePath,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);if (hFile INVALID_HANDLE_VALUE){printf(Create Error);return FALSE;}DWORD dwSize GetFileSize(hFile,NULL);if (dwSize 0xFFFFFFFF){printf(GetFileSize Error);return FALSE;}BYTE *pFile (BYTE*)malloc(dwSize);if (pFile NULL){printf(malloc Error);return FALSE;}DWORD dwNum 0;ReadFile(hFile,pFile,dwSize,dwNum,NULL);DWORD dwCrc32 CRC32(pFile,dwSize);if (pFile ! NULL){free(pFile);pFile NULL;}CloseHandle(hFile);return dwCrc32;
}int main()
{WIN32_FIND_DATA stFindFile;HANDLE hFindFile;char *szFilter *.exe; // 保存搜索的筛选条件全部exe文件char szFindFile[MAX_PATH]; // 保存欲检測的程序的路径char szSearch[MAX_PATH]; // 保存完整筛选路径int ret 0; // 搜索的返回值lstrcpy(szFindFile, E:\\);lstrcpy(szSearch, E:\\);lstrcat(szSearch, szFilter);DWORD dwTmpCRC32;hFindFile FindFirstFile(szSearch, stFindFile);if(hFindFile ! INVALID_HANDLE_VALUE){do{// 组成完整的待检測程序的路径lstrcat(szFindFile, stFindFile.cFileName);// 利用CRC32算法检測目标程序是不是病毒程序dwTmpCRC32 CalcCRC32(szFindFile);// 匹配setup.exe的CRC32值if(dwTmpCRC32 0x89240FCD){printf(发现病毒程序%s\n,szFindFile);}// 匹配unpacked.exe的CRC32值else if(dwTmpCRC32 0xC427A090){printf(发现病毒程序%s\n,szFindFile);}else{printf(%s不是病毒程序\n,szFindFile);}// 删除程序名称仅仅保留“C:\”szFindFile[3] \0;ret FindNextFile(hFindFile, stFindFile);}while( ret ! 0 );}FindClose(hFindFile);return 0;
} 相比而言程序的主体部分还是基本一致的仅仅只是是对于病毒特征的验证方式稍有不同。由于关于CRC32算法我们已经在前几次的课程中运用过所以这里不再赘述。看一下执行结果图3 可见利用CRC32算法提取出来的病毒特征码的检測方式在结果上与上一个程序是一样的相同是发现了两个病毒没有特征码的病毒就没能识别。然后再看一下用时我的測试结果是0.063秒也就是63毫秒是之前的时间的3.9375倍那么也就说明了CRC32算法在效率上是不如传统的特征码查杀方式的。 小结 本文讨论了病毒特征码查杀的编程实现。并与CRC32算法在效率上进行了对照。由于我们仅仅有两个特征码为了便于课程的解说。我採用的是直接利用if…else语句进行特征码的对照。假设病毒的特征码的数量非常庞大那么有多少特征码就须要使用多少个if语句那么这显然是非常没有效率的。能否够利用一定的算法来优化大量的特征码的比对工作不是我们讨论的重点。有兴趣的朋友能够研究一下。转载于:https://www.cnblogs.com/yangykaifa/p/7258833.html