病毒木马查杀实战第019篇:病毒特征码查杀之编程实现

前言

       上次我们已经简介过了病毒特征码提取的基本方法,那么这次我们就通过编程来实现对于病毒的特征码查杀。

 

定义特征码存储结构

       为了简单起见。这次我们使用的是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[SIGNLEN+1];int i;HANDLE hFile = NULL;hFile = CreateFile(FilePath,GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);for(i=0; 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.h"DWORD CRC32(BYTE* ptr,DWORD Size)
{DWORD crcTable[256],crcTmp1;//动态生成CRC-32表for (int i=0; i<256; i++){crcTmp1 = i;for (int j=8; j>0; j--){if (crcTmp1&1) crcTmp1 = (crcTmp1 >> 1) ^ 0xEDB88320L;else crcTmp1 >>= 1;}crcTable[i] = crcTmp1;}//计算CRC32值DWORD crcTmp2= 0xFFFFFFFF;while(Size--){crcTmp2 = ((crcTmp2>>8) & 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/282924.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《ASP.NET Core 6框架揭秘》实例演示[22]:如何承载你的后台服务[补充]

借助 .NET提供的服务承载&#xff08;Hosting&#xff09;系统&#xff0c;我们可以将一个或者多个长时间运行的后台服务寄宿或者承载我们创建的应用中。任何需要在后台长时间运行的操作都可以定义成标准化的服务并利用该系统来承载&#xff0c;ASP.NET Core应用最终也体现为这…

ASP.NET Core MVC压缩样式、脚本及总是复制文件到输出目录

前言 在.NET Core之前对于压缩样式文件和脚本我们可能需要借助第三方工具来进行压缩&#xff0c;但在ASP.NET MVC Core中则无需借助第三方工具来完成&#xff0c;本节我们来看看ASP.NET Core MVC为我们提供了哪些方便。 自动压缩样式和脚本 当我们在测试环境中肯定不需要压缩脚…

京东订单自动评价方法

刚刚完成的一个京东自动订单脚本, 以后还要加入其它京东自动的脚本项目地址: https://github.com/mm333444/aox_jd_auto_script 京东自动完成脚本 目前只完成京东订单自动评价, 评价时会自动上传商品图片 一、安装 1. 程序依赖 python3.52. 安装配置 安装pipenv安装模块 pipenv…

宜建立自主可控的车用芯片和操作系统技术体系

万物互联时代&#xff0c;操作系统的边界在不断突破&#xff0c;面向“人机物”融合的泛在计算场景&#xff0c;能够支撑分布式人机物协同应用的操作系统将是产业未来之光。操作系统在经过主机时代、PC互联时代、移动互联时代之后&#xff0c;来到万物互联时代&#xff0c;这恰…

django 用户管理(1)

编辑了前端的页面展示&#xff0c;用的bootstrap 用户登录 用户信息 用户编辑 创建用户 修改密码 转载于:https://blog.51cto.com/jacksoner/2133129

qiaoye.php,全自动无限生成关键词页面(黑帽SEO优化终极方法)

如果你是做黑帽SEO的&#xff0c;如果你还停留在用栏目、租域名、劫持等手段来做黑帽SEO优化&#xff0c;我可以肯定的告诉你&#xff0c;你做的再好&#xff0c;也赚不了多少。那么今天咱们要说的就是无限生成关键词页面用内容页来做黑帽SEO优化。这是我在演示的时候做的一个站…

v1.0.25 新版发布及Smart Meetup重新开启丨SmartIDE

作者&#xff1a;徐磊文章首发地址&#xff1a;https://smartide.cn/zh/blog/2022-0892-sprint25/关于SmartIDESmartIDE是一群开发者为所有开发者开发的开源云原生IDE&#xff0c;我们的使命是“为开发者赋予云原生的超能力”&#xff01;使用SmartIDE你只需要学会一个简单的指…

vue实现首屏加载等待动画 避免首次加载白屏尴尬

为什么80%的码农都做不了架构师&#xff1f;>>> 0 直接上效果图 1背景&#xff0c;用户体验良好一直是个重要的问题。 2怎么加到自己项目里面&#xff1f; 复制css html代码到自己的index.html即可 代码链接 源码地址 Vue学习前端群493671066&#xff0c;美女多多。…

java-回调机制详解

转&#xff1a;http://blog.csdn.net/llayjun/article/details/50454148 阅读目录 一、前言二、回调的含义和用途三、Java实现接口回调 四、Android中的接口回调五、参考资料一、前言 最近在看android fragment与Activity进行数据传递的部分&#xff0c;看到了接口回调的内容&a…

lfi读取php,php LFI读php文件源码以及直接post webshell

php LFI读php文件源码以及间接post 网站shell假如如下一个场景(&#xff11;) http://vulnerable/fileincl/example&#xff11;.php?pageintro.php(该php文件包孕LFI漏洞)(&#xff12;) 然而你不有中央能够upload你的网站shell代码(三) LFI只能读取到非php文件的源码(由于无…

根据请求上下文动态设置静态文件存储目录

前言上次&#xff0c;我们实现了根据 subpath 特定格式《动态设置静态文件存储目录》。例如&#xff1a;subpath静态文件路径/userAId/1.jpgc:\abc\userAId\1.jpg/userBId/1.jpgd:\xyz\123\userBId\1.jpg但是&#xff0c;如果 subpath 不能有这种特定格式&#xff0c;只能用通用…

ImageView的scaleType理解

2019独角兽企业重金招聘Python工程师标准>>> 1.android:scaleType“center” 保持原图的大小&#xff0c;显示在ImageView的中心。当原图的size大于ImageView的size时&#xff0c;多出来的部分被截掉。 2.android:scaleType“center_inside” 以原图正常显示为目的&…

第一章 引论

1、什么是多道程序设计&#xff1f; 即内存中同时运行多道独立程序&#xff0c;宏观上所有程序同时运行&#xff0c;微观上程序串行&#xff0c;多道程序轮流占用CPU&#xff0c;提高了资源利用率。 2、什么是SPOOLING&#xff1f;读者是否认为将来的高级个人计算机会把SPOOLIN…

《ASP.NET Core 6框架揭秘》实例演示[24]:中间件的多种定义方式

ASP.NET Core的请求处理管道由一个服务器和一组中间件组成&#xff0c;位于 “龙头” 的服务器负责请求的监听、接收、分发和最终的响应&#xff0c;针对请求的处理由后续的中间件来完成。中间件最终体现为一个Func<RequestDelegate, RequestDelegate>委托&#xff0c;但…

Android之 RecyclerView,CardView 详解和相对应的上拉刷新下拉加载

为什么80%的码农都做不了架构师&#xff1f;>>> 随着 Google 推出了全新的设计语言 Material Design&#xff0c;还迎来了新的 Android 支持库 v7&#xff0c;其中就包含了 Material Design 设计语言中关于 Card 卡片概念的实现 —— CardView。RecyclerView也是谷…

Java——Arrays类操作数组的工具类

JDK中提供了一个专门用于操作数组的工具类&#xff0c;即 Arrays 类&#xff0c;位于 Java。util 包中。该类提供了一系列方法来操作数组&#xff0c;如排序、复制、比较、填充等&#xff0c;用户直接调用这些方法即可&#xff0c;不需要自己编码实现&#xff0c;降低了开发难度…

CORS——跨域请求那些事儿

【本期嘉宾介绍】睿得&#xff0c;具有多年研发、运维、安全等IT相关从业经历。目前从事CDN、存储、视频直播点播的技术支持。喜爱钻研&#xff0c;喜爱编码&#xff0c;喜爱分享。 在日常的项目开发时会不可避免的需要进行跨域操作&#xff0c;而在实际进行跨域请求时&#xf…

oracle 数据执行计划,Oracle里常见的执行计划

本文介绍了Oracle数据库里常见的执行计划&#xff0c;使用的Oracle数据库版本为11.2.0.1。1、与表访问相关的执行计划Oracle数据库里与表访问有关的两种方法&#xff1a;全表扫描和ROWID扫描。反映在执行计划上&#xff0c;与全表扫描对应的执行计划中的关键字是“TABLE ACCESS…

.NET MAUI实战 Dispatcher

详细内容这一期分享的内容非常简单&#xff0c;在之前使用过WPF的开发者对MVVM开发模式下ViewModel中后台线程转UI线程并不陌生使用Appplication.Current.Dispatcher。那么在.NET MAUI中也有同样的机制&#xff0c;存在于.NET MAUI Shell对象中。那么什么是Shell&#xff1f;官…

GDB 配置

GDB 配置 使用 GDB 扩展来配置 GDB 事实上我还是觉得原生的 GDB 就挺好&#xff0c;速度快&#xff0c;需要查看什么执行命令就可以。 GDB DashBoard https://github.com/cyrus-and/gdb-dashboard $sudo mkdir -m 777 ~/gdbinit; cd ~/gdbinit $git clone https://github.com/c…