前言
提到杀软那就不得不提360了,从一开始被大家认为是流氓软件,到现在免费杀软的 god,这与它强大的查杀能力是分不开的,那么360的查杀原理究竟是什么,这篇文章带你剖析360。
引擎分析
这里我用的是360安全卫士,已经更新到最新版本了。
目前360主要是依赖这个五个查杀引擎,而360的查杀结果主要是依赖云查杀引擎和QVM引擎,还有一个启发式引擎,接下来我们就围绕者者三个引擎进行分析。
云查杀引擎
这是360查杀引擎的关键之一,很多伪装的很好的exe都败在这一步了,当我们扫描伪装好的exe时,360做的第一件事可能并不是在本地进行复杂的分析,而是计算我们文件的哈希值 (MD5/SHA256),然后将这个哈希值上传到它庞大的云端威胁情报中心。
我们或其他研究者之前可能已经把某个中间版本的、特征更明显的加载器上传到过各种在线沙箱(如VT, 微步, 安恒等)。这些沙箱的分析结果会被威胁情报提供商(包括360)订阅和抓取。即使沙箱只给了“低危”或“可疑”的结论,360的云端后台也会将我们的那个旧文件的哈希标记为“高度可疑的注入器样本”。
更重要的是,360的后台引擎会分析这些可疑样本的代码相似性。我们的终极加载器虽然加了很多优秀的手法,但其一些核心的函数、哈希算法、API哈希解析逻辑、等函数的二进制代码片段,与我们之前被标记为“可疑”的版本是高度相似甚至完全相同的。
360的云端引擎通过代码相似性分析,得出结论:“这个新文件与我们样本库里已知的多个‘可疑注入器’的代码有超过90%的相似度。因此,它也是一个木马。”
云端将这个结论下发到你的客户端,于是360“秒杀”了你的程序。
启发式引擎
这个引擎更多的是去思考,比如申请内存 —> 修改内存属性 —> 向内存写入数据 —> 创建线程,这是典型的shellcode注入流程。又或者一个很小的没什么功能的程序,它的熵值居然非常混乱,这种情况,启发式引擎就会决定不正常,于是打上木马的标签。
QVM II 人工智能引擎
这可以说是360的大杀器,这个引擎早已超越了简单的查哈希或代码片段,它们会分析一些 “元特征” ,我们的程序是用哪个版本的Visual Studio、哪套优化参数编译的?这会留下特定的启动函数、库代码和数据对齐模式。我们的程序代码量很小,但控制流却涉及了动态解析函数地址、多层数据重组等对于其体积来说“过于复杂”的逻辑。即使API被哈希了,引擎也可以通过分析代码结构,推断出“这里在加载一个库”、“这里在遍历导出表”、“这里在调用一个刚解析出来的函数指针”,从而绘制出一张无名的API调用图,并与已知的恶意模式进行比对。
简单来说,云查杀引擎就是通过大数据找到你,QVM II 人工智能引擎和启发式引擎通过分析和思考发现你
实验验证
代码结构对比
下面我们通过实验来验证引擎是怎么进行查杀的,以及查杀了什么。
这里我准备了两份代码,功能完全一样,只是结构不同。
#include <iostream>
int main() {
cout << "hhhh"; // 打印一个字符串常量
return 0;
}
#include <iostream>
void print(char a) {
cout << a;
}
int main() {
char a = 'hhh'; // 这是一个非常有问题的代码!
print(a);
return 0;
}
360查杀的结果也不同,一个是标签是Trojan.Generic:表示“一个具有木马共性的通用威胁”。另一个是HEUR/QVM...Malware.Gen,HEUR代表启发式(Heuristic),QVM就是QVM引擎,Malware.Gen代表泛型恶意软件。这个结果等于直接告诉你:“我是QVM引擎,我根据这个文件的结构和行为特征,判断它是一个恶意软件。”
我们来分析一下结果,相同功能的代码但是结构不同,导致查杀结果也不同,这表明了360云引擎会根据代码的“写法”和“结构”进行对比,哪怕功能相同,实现方式的差异也会导致引擎做出完全不同的判断。
同时,我们还发现一个十分关键的点,char a = 'hhh'这是一句十分不合常规、语法上合法但逻辑上很怪异的代码写法,这正是启发式引擎和AI引擎重点怀疑的对象!QVM会认为这是一种混淆技术或低质量代码的特征,而这些特征在恶意软件中出现的频率远高于正常软件。
一个极小的程序,执行了一个非标准操作然后退出。这种“短小精悍”且“行为怪异”的程序,非常符合一些恶意“下载器(Downloader)”或“加载器(Loader)”的初期行为特征。
综合以上可疑点,QVM的AI模型给出的分数超过了“恶意”的阈值。由于它不是某个已知的特定病毒家族,所以报了一个泛型名称。
这里我得到第二个结论,360启发式/AI引擎对“不常见”、“不规范”的编程模式特别敏感。
文件hash对比
这里我又准备了两份代码,功能结构完全相同,只是函数名也不同,目的是为了文件的hash不同。
#include <iostream>
using namespace std;
void print(char a) {
cout << a;
}
int main() {
char a = 'h';
print(a);
return 0;
}
#include <iostream>
using namespace std;
void ttt(char a) {
cout << a;
}
int main() {
char a = 'h';
ttt(a);
return 0;
}
直接来看一下查杀结果,可以看到结果标签一模一样。
这表明了360云引擎会对比文件的hash,360的云端服务器上一定有一个庞大的、由标准哈希值组成的黑名单库。这是最快、最高效的查杀方式。如果一个文件的哈希值在黑名单里,就会被“秒杀”。但是远不止于此,360引入模糊哈希的概念,核心思想是:内容相似的文件,其模糊哈希值也应该相似。
所以如果你仅是通过修改函数名,字符串常量等,是不足以对抗360云引擎的查杀的,即使模糊哈希也无法识别,QVM依然会分析文件的结构和行为模式。在我们的两个例子中,程序的控制流图是完全一样的:main函数调用另一个函数,那个函数再调用IO库输出。QVM会认为这种“代码结构”本身就是可疑的(可能是因为它过于简单,符合某些恶意加载器的特征)。
代码行为对比
这是两份功能相同,但是行为不同的代码。
#include <iostream>
#include <windows.h>
using namespace std;
void Sleep(DWORD dwMilliseconds);
int main() {
Sleep(11);
cout << "h";
Sleep(11);
cout << "h";
Sleep(11);
cout << "h";
return 0;
}
#include <iostream>
using namespace std;
int main() {
cout << "hhh";
return 0;
}
360查杀的结果依旧一样。
这说明一个非常直观的现象,单是修改文件的行为并不足以躲过360的查杀。
代码1行为序列:[程序启动] -> [调用C++运行时库] -> **[调用windows.h中的Sleep函数]** -> [调用控制台输出] -> **[调用Sleep]** -> [调用控制台输出] -> **[调用Sleep]** -> [调用控制台输出] -> [程序退出]
代码2行为序列:[程序启动] -> [调用C++运行时库] -> [调用操作系统接口进行控制台输出] -> [程序退出]
这两个程序的行为是截然不同的。一个直接了当,另一个则夹杂了多次延时调用。然而,QVM引擎依然将它们识别为同一种威胁 (HEUR/QVM202.0.C2C3.Malware.Gen)。这证明了QVM引擎做的不是简单的、逐字的API序列比对,而是进行了一种更高维度的 “意图” 分析和 “行为模式” 抽象。
降噪处理 (Noise Reduction):
在QVM引擎的“知识库”里,Sleep()函数是一个非常特殊的API。
-
一方面,正常软件会用它来做延时、轮询等。
-
另一方面,恶意软件极度频繁地使用它来进行“反沙箱”、“反调试”。很多自动化分析沙箱为了效率,只会运行程序几秒钟。恶意软件通过长时间Sleep,可以“熬过”沙箱的分析时间,从而逃避检测。
-
因此,QVM引擎在分析时,不会孤立地看待Sleep调用。它会结合程序的其他特征来判断Sleep的意图。在你的例子中,Sleep(11)(11毫秒)的延时非常短,且程序整体结构极其简单,QVM可能会将其归类为“无意义的延时”或“干扰性操作”,在进行最终判定时,降低了Sleep这个行为的权重。
核心行为模式提取 (Core Behavior Pattern Extraction):
QVM引擎会透过这些“噪音”(如Sleep调用),去抓取程序最核心的“骨架”。
-
在这两个例子中,核心骨架都是:“一个体积微小、结构简单的程序,执行了极少量的IO操作后迅速退出”。
-
这种“短、小、快、怪”的行为模式,恰恰是无数**恶意下载器 (Downloader)、加载器 (Loader) 或木马的“先遣部队”(Dropper)**的典型特征。它们的任务就是进入系统后,立刻去下载或释放真正的、更庞大的恶意主体。
-
QVM引擎在其庞大的恶意样本库中学习到了这种模式。因此,无论你的程序是直接输出"hhh",还是“抖动着”输出"hhh",QVM都识别出了这个相同的、可疑的底层行为模式。
至此得到结论,单是修改文件局部的、非关键性的行为,并不足以躲过先进的AI杀毒引擎,通过用大量的“良性行为”来包裹、稀释恶意的“核心行为”,才能增加AI引擎的误判难度,这正是现代对抗杀软的核心思想之一。
Tips
360还有个很强大的功能,短时间大量用户上传同一exe,就会引起引擎的重视。
或者当一个程序被污染时也会产生告警,比如APC注入,父程序往正常的子程序进行注入时,对于360来说子程序已经被污染了,即使你子程序原本就是正常的,也会产生告警。
还有就是360的云传,要是显示未知风险的话,只能说明现在还没被查杀,可能过一会就被杀掉了,除非是安全。
对抗方法
对抗基于代码相似度和大数据信誉的云查杀引擎,是现代免杀技术的“圣杯”之一。
初级可以通过改变编译方式、编译参数、自定义hash算法、代码虚化等方式改变自身的文件的hash值。
高级点的就是 “代码白化” 与 “程序膨胀” 。
原理其实也很简单,不要做一个纯粹的加载器。让我们的程序真正地成为一个有用的工具。比如,从开源社区找一个计算器、文本编辑器或图片查看器的源代码,然后将核心逻辑(API哈希解析、数据重组、APC注入)巧妙地、零散地**“移植”**到这个巨大的、合法的项目代码中。
再进阶一点的就是将恶意代码执行逻辑,绑定到一个不那么引人注目的事件上。例如,“当用户点击‘帮助’->‘关于’菜单时”、“当程序启动30分钟后”、“当用户在文本框里输入特定暗号时”等等。
最终我们的产物是一个99%的功能都是合法的、行为看起来也正常的程序。360的云引擎在分析它时,会发现它的代码与成千上万个合法的计算器或编辑器程序有极高的相似度,从而大幅降低其“恶意评分”。换句话说代码的“恶意基因”,稀释到了汪洋大海之中。
总结
对抗360云引擎的策略梯度是:
-
初级: 换编译器、换编译选项。
-
中级: 自定义所有算法,打乱代码逻辑(函数拆分/内联)。
-
高级: 使用LLVM等工具进行自动化的深度代码混淆。
-
终极 (也是最有效的): “代码白化”。将你的加载器逻辑作为一个“寄生虫”,植入到一个庞大而合法的宿主程序源代码中。
最后,以上仅为个人的拙见,如何有不对的地方,欢迎各位师傅指正与补充,有兴趣的师傅可以一起交流学习。