目前绕过沙箱是做免杀必须要经过的一步,很多的杀毒软件已经加入了云查杀功能.其原理就是将样本上传到沙箱服务器,沙箱运行样本跑出结果,根据返回的结果对你的样本进行阈值进行评判,如果超过了他设定的阈值就说明此文件为有害文件,杀软接到结果后对样本进行拦截或者删除.
沙箱的原理
这里拿简单的开源项目cuckoo(布谷鸟)为例说明:
1.首先启动你的样本程序,进行挂起状态.
2.将DLL(动态链接库)注入到程序中,恢复状态运行.
3.在有限的时间内对你调用的API,申请的内存进行抓取.
4.将结果返回给规则文件进行匹配.
5.显示在网页上进行输出.
这里有几点我们需要知道的一点是他注入DLL都做了哪些事情,在cuckoo的代码里面是Hook一些WindowsAPI当然这些API是可以自己添加的,如果你的执行程序调用了这些API,就会走到他HOOK的位置,从而对你的API操作了哪些参数进行判断/或者写入到文件,在后期的规则匹配中将获取到的参数或者API调用顺序进行已有规则匹配,如果现在有一个Cobalt Strike的规则匹配上了样本,那本就可以给出结果此样本为Cobalt Strike了.
沙箱利用点
以上步骤中我们可以看出,沙箱检测样本必须要在你的样本中注入DLL,此时如果想检测的话可以遍历进程模块进行过滤当前是否为沙箱环境,当然有些杀毒软件也会往你的程序中注入DLL,比如说ESET等.
上面也说道有限的时间,因为他启动你的程序不能太长时间,这样会导致占用过大,因为沙箱一般不是服务于一个样本,是服务于一大批样本,那么为了检测的准确性,一般是一个实例开机后对应一个样本,检测完毕后关闭实例等待下一个样本.这里也不排除有些商家为了快或者说性能对准确性的减少,也就是一个实例中运行多个样本.这里其实我们可以利用等待的时间来绕过沙箱.
验证
1.测试代码
[AppleScript] 纯文本查看 复制代码 #include <iostream>
#include <chrono>
#include <Windows.h>
int main()
{
auto start = std::chrono::high_resolution_clock::now();
// 休眠10秒
Sleep(10000);
auto end = std::chrono::high_resolution_clock::now();
// 获取时间差
std::chrono::duration<double> duration = end - start;
std::cout << duration.count() << std::endl;
// 比如说以下为恶意代码
std::string number = std::to_string(duration.count());
MessageBoxA(nullptr, number.c_str(), nullptr, MB_OK);
return 0;
}
此代码如果在我们正常的环境下跑应该输出的10秒以上的时间,因为我们Sleep休眠了10秒,我们看下在本机跑和在沙箱跑的区别.(注意以上代码需要CXX20)
本机结果
沙箱结果
可以看出他也是等待10秒的,如果这里我们改成5分钟沙箱会不会跑完我们的结果呢?
可以看出这里并没有跑完我们的样本,因为默认分配的时间是不够的,虽然这个ANY.RUN是可以进行时间添加的.这里我们再去测试一款沙箱去看下跑出来的结果.
可以看出这里也没经过我们的有害代码.
其他方法
以上只是最简单的对抗沙箱的办法,比较暴力也比较容易绕过,当然很多情况下这种方式是无效的,因为可以通过Hook Sleep函数来达到绕过,或者通过加速器来绕过.
我们还可以通过:开机时间,环境检测,沙箱特征,网络测试,固件检测,模块信息等来检测出当前环境是否为沙箱环境,如果是沙箱环境可以选择退出或者是执行假的流程等.
|