吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 981|回复: 6
上一主题 下一主题
收起左侧

[PC样本分析] Install_098k_银狐木马静态分析报告(二)

  [复制链接]
跳转到指定楼层
楼主
FZZZP 发表于 2026-9-2 16:03 回帖奖励
使用论坛附件上传样本压缩包时必须使用压缩密码保护,压缩密码:52pojie,否则会导致论坛被杀毒软件等误报,论坛有权随时删除相关附件和帖子!
病毒分析分区附件样本、网址谨慎下载点击,可能对计算机产生破坏,仅供安全人员在法律允许范围内研究,禁止非法用途!
禁止求非法渗透测试、非法网络攻击、获取隐私等违法内容,即使对方是非法内容,也应向警方求助!
本帖最后由 FZZZP 于 2026-9-2 16:16 编辑

银狐(Silver Fox)木马 Loader 变种静态分析报告(二)

样本仅供技术研究,勿在真实环境运行/传播
分析方法:纯静态,解密载荷仅做磁盘/内存静态还原,全程未执行样本
关联文章:本文为系列第 2 篇。第 1 篇 Install_098k.exe(Loader / Dropper 本体)分析见系列前文:https://www.52pojie.cn/thread-2123431-1-1.html
样本哈希等关键值均在文中给出,方便自行比对复现


0. 先说结论

Install_098k.exe 是银狐家族变种的 Loader。它把反虚拟机/反沙箱检测做完后,用 XTEA 解密出自己 overlay 里的一段 shellcode,再借 EnumSystemLocalesA 回调在内存里执行。这段 shellcode 是一个自实现的 PE 反射加载器(reflective loader):它内部还内嵌了一个约 320KB 的木马核心 DLL(导出名自报「登录模块.dll」),并把它反射映射进宿主进程、不落盘地运行起来,完成 C2 通信、键盘/剪贴板监视、截屏、进程注入守护、对外连接隐藏等全套后门功能。

整条链就是 EXE(文件) → shellcode(内存) → DLL(反射内存),最后一级恶意核心不落盘,只有内存特征。文末给出检测/处置思路。


1. 样本总览

1.1 三阶段样本指纹

阶段 样本 大小 MD5
Loader Install_098k.exe 351,806 B 2355241846B80ACB46365901F222CBBE
Shellcode _payload_dec.bin(XTEA 解密、去 PKCS7 填充) 322,257 B 77EC4A38ED9EDFF097E1E68E9CD309C0
载荷 DLL 登录模块.dll 320,512 B 1D098FBA1D445A0D711B47430820B9EB

一个自洽的小验证:322,257 − 320,512 = 1,745 = 0x6D1,正好是内嵌 PE 在 shellcode 里的偏移——说明 shellcode 的“代码部分”只有 1.7KB,剩下的全是被它背着跑的 DLL

1.2 载荷链全景

Install_098k.exe(Loader,第 1 篇)
├─ 读自身 → Security 目录定位 overlay → "_]P[" 标记 → 解析内嵌配置
├─ 反VM(13项)/反沙箱(7组) 门禁
├─ 自复制 %TEMP% 副本 --child 二次启动(子进程删原件)
├─ LoadLibraryA("amsi.dll" / "ws2_32.dll") 预载
└─ XTEA 解密 overlay 内载荷(322,264B)
   └─ VirtualAlloc → memcpy → VirtualProtect(RX)
      └─ EnumSystemLocalesA((LOCALE_ENUMPROC)shellcode)   ← 借“系统区域枚举回调”执行
         └─【本文】shellcode = PE 反射加载器
            └─ 内存中映射内嵌「登录模块.dll」(shellcode+0x6D1)
               └─ 调用其入口/导出 → 木马核心在当前进程内直接以内存形态运行

2. 前置:从 Loader 还原出 Shellcode(承接第 1 篇)

Loader 把载荷藏在自身文件的 overlay 里。定位方式不是按固定偏移,而是利用 PE 证书表(Security Directory, 数据目录下标 4)的 RVA 当搜索边界,从文件尾部向前找内嵌配置标记 _]P[,再按配置里的"段指针+长度"字段取出密文与密钥。

  • 密文位置:文件偏移 0x48E1,大小 322,264 B
  • XTEA 密钥:51 53 1F F4 A8 AC 0B 6A A3 09 BF A9 6A 41 8E 3E
  • 算法:XTEA,32 轮,delta 0x9E3779B9,宽松 PKCS7 去填充

解密后得到 322,257 B 的明文(MD5 见 §1.1),头部是 E9 43 04 00 00jmp +0x443),随后是 NOP 与 48 8B C4 序言——典型的内存中解析并加载 PE 的 loader shellcode。


3. Shellcode 总体布局

它是一段纯位置无关(PIC)、无导入表、无节区的自包含字节流。按内部偏移划分如下:

偏移 大小 内容 角色
0x0 8 E9 43 04 00 00 + NOP 入口跳板 → 0x448
0x8 ~0xD4 Hash_GetProcAddress 自实现导出表解析器(按名字哈希找函数)
0xDC ~0x36C ReflectiveLoader 核心:反射映射内嵌 PE 并运行
0x448 ~0x210 bootstrap 主引导 PEB 遍历 + 哈希解析 API + 构造 API 表 + 调反射器
0x65C ~0x75 载荷描述符 引导参数(标志 / 内嵌 PE 偏移)
0x6D1 320,512 内嵌完整 PE = 「登录模块.dll」 恶意核心(MZ 4D 5A 开头)

4. 引导主流程 bootstrap0x448

入口跳板跳过两个子函数,落到 0x448 的引导代码,执行顺序如下。

4.1 PEB 遍历定位 kernel32(不用任何导入)

PEB → PEB_LDR_DATA(Ldr, PEB+0x60) → InMemoryOrderModuleList(+0x18)
遍历双向链表;模块名取 BaseDllName(模块项+0x48 的 UNICODE_STRING)
每模块:小写名 → 转大写 → 逐字符哈希 → 与 0x13D21720 比对(= "KERNEL32.DLL")
命中 → 取 DllBase(模块项+0x20)

完全不依赖 GetModuleHandle / LoadLibraryA 的导入,配合下面的哈希解析,属于对抗 API Hook / IAT 分析的标准手法。

4.2 按名字哈希从 kernel32 解析 5 个函数

哈希 函数 存入 API 表槽
0x196495CA GetProcAddress [0x00]
0x5214D8E6 LoadLibraryA [0x08]
0x299DEE32 VirtualAlloc [0x10]
0x72B66139 VirtualFree [0x18]
0x04B320BF lstrcmpiA [0x20]

4.3 加载 ntdll 并再解析 2 个函数

关键细节:ntdll 不是按模块哈希找的,而是在 0x539 附近把字面量 "ntdll" 逐字节压上栈,直接 LoadLibraryA

哈希 函数 存入 API 表槽
0x74CC03AB RtlZeroMemory [0x28]
0x6DE0C632 RtlMoveMemory [0x30]

于是引导代码在栈上(lea r13,[rbp-40h])拼出一张 7 槽 API 表,整张表通过寄存器(r13/rcx)传给反射器——反射器自身没有任何静态 IAT,全部依赖这张“迷你 IAT”。

4.4 读载荷描述符(0x65C)并调用反射器

偏移 字节 含义
0x65C 00 0 标志:0 = 直接反射加载(非 0 走“先拷贝/解密到临时缓冲再反射”分支)
0x65D 00 00 00 00 0 预拷贝源/长度字段(本样本未启用)
0x669 75 00 00 00 0x75 内嵌 PE 相对描述符的偏移 → 0x65C + 0x75 = 0x6D1
call ReflectiveLoader(r13=API表, rsi/rdx=PE@0x6D1, …)
     —— DLL 被反射映射,DllMain/入口在反射器内部即被调用
返回后:call [rbp+38h]   —— 反射器写回的目标导出/入口地址,木马核心由此激活

整段引导只见 call [r13+0x10] 这类寄存器间接调用,看不到任何静态导入/导出引用;模块名、函数名、参数字符串全部哈希化或运行时压栈。这是典型的"自给自足"加载器写法。


5. 自实现哈希 API 解析(家族指纹)

5.1 哈希算法

h = 0
for c in 字符串:  h = h * 0xB1(177) + c     // 32 位回卷
return h & 0x7FFFFFFF                        // 清掉最高位
  • 模块名哈希:使用前先把名字转大写(如 KERNEL32.DLL);
  • 导出名哈希:不转大小写,PE 导出名本身就是大小写敏感 ASCII。

Hash_GetProcAddress0x8)就是按这个哈希手写遍历导出表:e_lfanew → 导出目录 → AddressOfNames / AddressOfNameOrdinals / AddressOfFunctions,比对名字哈希后返回函数地址;传入真 GetProcAddress 指针时还能处理转发函数(forwarder),与外层 Loader 的解析器一脉相承。

5.2 哈希对照表(全部经脚本逐项验算一致)

用途 字符串 计算哈希
模块名(先转大写) KERNEL32.DLL 0x13D21720
导出名 GetProcAddress 0x196495CA
导出名 LoadLibraryA 0x5214D8E6
导出名 VirtualAlloc 0x299DEE32
导出名 VirtualFree 0x72B66139
导出名 lstrcmpiA 0x04B320BF
导出名 RtlZeroMemory 0x74CC03AB
导出名 RtlMoveMemory 0x6DE0C632

5.3 值得单独说的一个点:两阶段同源

第 1 篇 Loader 找模块用的哈希、与本篇反射器找函数用的哈希,系数都是 0xB1、收尾都是 &0x7FFFFFFF。哈希函数是作者自己写的、特征极强的代码,两阶段共用同一原语,基本可以断定 Loader 与载荷出自同一作者 / 同一框架。这种“自研哈希贯穿多阶段”的写法,也常作为同源聚类(家族归属)的判据。


6. 反射加载器 ReflectiveLoader0xDC)深入

内嵌 DLL 是标准 PE32+、带 .reloc、带完整导入表——这正是反射器能把它搬进内存的前提。反射器工作流:

ReflectiveLoader(api表, pe=0x6D1, …)
├─ 1. PE 校验:'MZ' && e_lfanew 可读 && 'PE' && Machine==0x8664 && Magic==0x20B
├─ 2. 内存申请:
│      base = VirtualAlloc(NULL, SizeOfImage, MEM_COMMIT|RESERVE, PAGE_EXECUTE_READWRITE)
│      RtlMoveMemory(base, pe, SizeOfHeaders)          // 先拷头
├─ 3. 逐节映射(对每个 IMAGE_SECTION_HEADER):
│      dest = base + VirtualAddress
│      SizeOfRawData 非 0 → RtlMoveMemory(dest, pe+PointerToRawData, SizeOfRawData)
│      VirtualSize > SizeOfRawData → RtlZeroMemory 补零到 VirtualSize   // BSS 补零
├─ 4. 重定位(若带 .reloc):
│      baseDelta = 新基址 − ImageBase(0x180000000)
│      0x3000 HIGHLOW → *(u32*) += baseDelta
│      0xA000 DIR64   → *(u64*) += baseDelta
├─ 5. 导入修复:
│      for 每个 IMAGE_IMPORT_DESCRIPTOR:
│        hMod = LoadLibraryA(该 DLL 名)                  // 明文加载
│        for thunk in FirstThunk:
│          名字导入 → GetProcAddress(hMod, 明文函数名)     // 明文按名解析
│          序号导入 → 直接取 AddressOfFunctions
├─ 6. TLS 回调(可选):AddressOfCallBacks 非空则逐个调用    // 本 DLL 无 TLS,跳过
├─ 7. 调用入口:
│      (base + AddressOfEntryPoint)(…, reason=1(DLL_PROCESS_ATTACH), …)
└─ 8. (可选)按名解析导出并写回输出槽,供 bootstrap 调用

值得说明的两个反直觉点:

  1. 哈希只保护“加载链路自己”,业务 DLL 是明文修的 IAT。 反射器自己用的 7 个 API 全部哈希化、无 IAT;而被反射的 DLL,它的导入表、函数名在 DLL 文件里就是明文,反射器直接用 LoadLibraryA + GetProcAddress ——说明作者的混淆投入集中在加载/投递链路,而不是业务 DLL 内部。
  2. 入口以 reason=1(DLL_PROCESS_ATTACH)调用。 木马的“主动作”全部由带 DllMain 语义的入口函数拉起线程完成,而不是等某个导出被调。所以反射器返回前,后门核心就已经在宿主进程里跑起来了。

7. 「登录模块.dll」恶意功能拆解

7.1 概况

项目
模块名(导出表自报) 登录模块.dll(UTF-8)
架构 / ImageBase AMD64 / 0x180000000
编译时间戳 0x6A60597D = 2026-07-22(比 Loader 早 1 天,同批次构建)
入口 / SizeOfImage 0x18F20 / 0x56000
节区 6:.text/.rdata/.data/.pdata/.rsrc/.reloc带重定位,可被反射
导出 2:daohello(占位/混淆式命名)
函数规模 862 个函数
导入 14 个 DLL:KERNEL32/USER32/GDI32/ADVAPI32/SHELL32/ole32/OLEAUT32/WS2_32/bcrypt/WINMM/gdiplus/dxgi/DINPUT8/VERSION
字符串 关键串均 XOR 0x4B 的 UTF-16LE 混淆,运行期解码

导入面已经很能说明问题:CreateRemoteThread/VirtualAllocEx/WriteProcessMemory(注入)、OpenClipboard/GetClipboardData(剪贴板)、GetKeyState/DirectInput8Create(输入监听)、GDI+GDI+DXGI(截图)、WS2_32 + bcrypt(网络 + AES)、注册表 API(配置/持久化)、ClearEventLogW(清日志)。其中 DINPUT8 / VERSION / gdiplus / dxgi 组合与游戏组件相似——典型的“白加黑”侧加载布局:若该 DLL 落盘,可伪装成被带这些依赖的合法程序侧加载。

7.2 内存初始化链(反射之后它怎么跑起来)

DLL 入口 sub_180018DF8(AddressOfEntryPoint=0x18F20)
└─ StartMainThread (0x180017680)
   └─ CreateThread(主线程体 StartAddress)
      └─ 按需拉起 C2 通信、命令分发、键盘/剪贴板、截屏、守护等线程

导出 hello / dao 都通向这条启动链。反射器调用导出或入口,效果等价于让木马核心在当前进程内直接初始化——这是“内存运行、不落盘”的临门一脚。

7.3 C2 配置与协议

  • 配置存注册表HKCU\…\Software\Microsoft\Hello(值名 Hello)——项名 Hello 与导出 hello 呼应,像是作者自己的命名习惯标记。读不到 HKCU 再读 HKLM(兜底)。

  • 值格式(管道分隔)p1:IP|o1:port|t1:proto|p2|o2|t2|p3|o3|t3|ur:url…

    • p{n}/o{n}/t{n}:最多 3 组 C2 的 IP/端口/传输协议(TCP/UDP);
    • ur::备用 URL 型 C2。
  • 通信帧(bcrypt AES-CBC)

    收帧:[4B 长度 N][16B IV][N 字节 AES-CBC 密文]     // 每帧独立 IV
    发帧:同构

    另有 [0]=0xCC 这类“特殊首字节 + 紧凑结构”用于状态/心跳上行,与 AES 数据帧区分。

7.4 命令分发:C2 Dispatcher(sub_18000F8C0,203-case switch)

主循环收到命令后进一个按命令号分发、含 203 个 case 的巨型 switch(类 CLoginManager 虚表驱动)。已梳理出代表性子集:

命令号 行为
0 / 1 载荷/任务下发执行
2 事件上报(键盘/剪贴板等)
3 速率/节流控制
4 截图信息(宽高/数量)上报
5 缩略图截图(首字节 0xCD
6 接收文件 + 注册表文件关联启动
7 URL 下载(wininet,校验 MZ)→ 隐藏执行(C:\Users\Public\Downloads + 隐藏进程)
8 备注/分组 设置、删除
9 进程枚举上报
10 心跳
11 全屏截图(0x12 标识)
12 清事件日志ClearEventLogW
13 异常过滤设置
14 ExitProcess 自杀
15/16/17 注销 / 重启 / 关机
18 上报加载模式
19 配置迁移 + 重新解析
20 拉起 C2 线程
100/101 写/删 HKCU\…\Console\IpDatespecial(感染标记)
201/202 状态上报(0xCC 帧):空闲时长/前台窗口/IM 进程扫描/持久化存活/驱动 k32.sys 检测

命令面覆盖 侦察 → 控制 → 数据窃取 → 反取证 → 自杀 的完整生命周期。0xCC 状态帧里的 IM 扫描与 k32.sys(银狐常用内核对抗驱动)字段是家族行为的强特征。

7.5 隐蔽 / 附加子系统

① 键盘记录 + 剪贴板监视

  • DirectInput8Create + 轮询取键(非全局钩子,规避常见的钩子检测),叠加 GetLastInputInfo
  • 剪贴板每 ~1.5s 拉取 CF_UNICODETEXT;记录前台窗口标题;
  • 日志写 %LOCALAPPDATA%\DisplaySessionContainers.log,50MB 轮转;
  • 注册表开关门控HKCU 下某值 open == "1" 才启用——记录功能可被 C2 远程开关。

② 双进程守护(自愈对抗)

  • RemoteThreadInject0x18000BCF0):VirtualAllocEx RWX + WriteProcessMemorysvchost.exe 注入守护 shellcode + 小 API 表 → CreateRemoteThread(挂起)→ Sleep 60s → ResumeThread
  • ProcessGuardLoop0x18000C110):宿主死亡后由 svchost 里的守护体拉回;若被注入进程退出码 ≠ 259(STILL_ACTIVE)则重新注入

③ TCP 连接表隐藏

  • InitBackupC2AndHooks0x1800147A0):先备份 C2 端点到内存向量,再对 iphlpapiGetExtendedTcpTable / AllocateAndGetTcpExTableFromStack / InternalGetTcpTable214 字节 FF25(jmp [rip+…])内联 Hook
  • 替换函数返回前过滤掉与 C2 端点匹配的行netstat、第三方网络监视都看不到它的 C2 连接。

④ 屏幕截图:GDI StretchBlt 抓屏 → GDI+ JPEG 编码,按命令号(4/5/11)不同规格回传。

⑤ 插件 / 附加载荷onlyloadinmyself / plugmark 标记——仅当进程名/标记匹配才加载附加 DLL 插件(数据区 0x180051D00),避免在分析环境被动释放附加能力。

7.6 持久化与伪装(若落盘时)

手法 内容
启动项 Run迅雷服务
计划任务 \MicrosoftEdgeUpdate\Update
WMI SvcHostUpdate
侧加载 DINPUT8/VERSION 布局,“白加黑”
界面伪装 资源仅清单,配合“文件损坏”类假报错

7.7 反分析特征

  • 60 秒级延迟贯穿启动/守护注入,规避沙箱时间窗;
  • 注册表开关动态门控敏感功能;配置藏注册表值 + XOR-0x4B;
  • 状态帧回传“是否被调试/前台窗口/IM 进程”等环境情报,供 C2 决策后续动作。

8. 全程调用链(一图流)

Install_098k.exe
├─ 环境门禁(反VM/反沙箱) → 自复制二次启动 → 预载 amsi/ws2_32
└─ XTEA 解密 → ExecuteShellcode
   └─ _payload_dec.bin(反射器 shellcode)
      ├─ bootstrap 0x448:PEB→kernel32 → 哈希解析 7 函数 → LoadLibraryA("ntdll")
      ├─ 描述符 0x65C(flag=0)→ PE@0x6D1
      └─ ReflectiveLoader:校验 → VirtualAlloc(RWX) → 映射 6 节 → .reloc 重定位
                       → 明文修 IAT → 调 DllMain(1)
         └─ 登录模块.dll(内存运行、不落盘)
            ├─ StartMainThread → 主 C2 线程
            ├─ 注册表读 C2(Software\Microsoft\Hello) → TCP/UDP 外联
            ├─ AES-CBC 帧 → C2 Dispatcher(203-case) 分发
            ├─ 键盘/剪贴板(DINPUT8 轮询 + 注册表开关)
            ├─ 注入 svchost 双进程守护
            ├─ FF25 内联 Hook TCP 表 → 隐藏 C2 连接
            └─ 截图/文件/插件/清日志/注销/关机/自杀…

9. 检测与处置思路

9.1 文件侧 / 静态特征

  • YARA 关注:XTEA 常量、×0xB1 哈希循环、XOR-0x4B UTF-16、导出 dao/hello、14 字节 FF25 Hook 模板、p1:IP|o1:port 管道串;
  • 关键注册表项/值:Software\Microsoft\HelloConsole\IpDatespecial
  • 持久化:迅雷服务MicrosoftEdgeUpdate\UpdateSvcHostUpdate

9.2 内存 / 行为侧

  • 扫描其它进程内大块 RWX + 无文件映射 + 已被重定位的 PE(反射器产物特征);
  • svchost.exe 中驻留的守护 shellcode 高敏(netstat/任务管理器不可见也不代表干净)。

9.3 处置要点

  • 先断网/保留内存镜像;清 Run/计划任务/WMI;杀宿主进程的同时排查 svchost 内注入的守护体(否则会被拉回);删注册表项与 DisplaySessionContainers.log
  • 网络侧取证不要只信 netstat(TCP 表可能被 hook),配合抓包确认外联。

10. 小结

  1. 三层“免落盘”:EXE(文件) → shellcode(内存) → DLL(反射内存),最后一级恶意核心不写盘,EDR 文件扫描天然盲区,只能靠内存/行为特征兜底。
  2. 自研哈希同源h = h×0xB1 + c, &0x7FFFFFFF 贯穿 Loader 与 Shellcode 两阶段,是家族聚类的硬指纹。
  3. 反射器典型实现:PE 校验 → RWX 大块 → 逐节映射 + BSS 补零 → .reloc 重定位 → LoadLibraryA+GetProcAddress 明文修 IAT → 以 reason=1 调入口。
  4. 混淆投入偏重加载链路:反射器自身 API 全哈希、无 IAT;业务 DLL 内部反而用明文导入。
  5. 不是“只有远控”:命令面之外还有键盘/剪贴板、IM 侦察、双进程守护注入、TCP 表 Hook、插件加载、清日志、破坏动作等——是一个功能完整、带自愈与反取证能力的后门核心。

本文为纯静态分析产物,样本及解密载荷均未运行,仅载入 IDA / 十六进制工具比对。样本仅用于安全技术研究,请勿在真实环境运行或传播。本文涉及的哈希、注册表项、文件路径均为样本分析所得,仅作检测/应急参考。

免费评分

参与人数 8吾爱币 +8 热心值 +6 收起 理由
Firstm + 1 + 1 用心讨论,共获提升!
allspark + 1 + 1 用心讨论,共获提升!
DGR1 + 1 + 1 我很赞同!
wang2979633 + 1 + 1 我很赞同!
yyjopq + 1 + 1 我很赞同!
yzd522 + 1 我很赞同!
wasd71 + 1 + 1 我很赞同!
ay6666 + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

推荐
4grd26f 发表于 2026-9-2 19:33
edge的bing现在一堆银狐假官网
3#
yyjopq 发表于 2026-9-2 17:58
感觉最近银狐是不是变多了,发现有不少人中招,各种领域都有被下毒
4#
lt1108 发表于 2026-9-3 08:52
5#
stock58898 发表于 2026-9-3 14:31
最近银狐好多
6#
liukaigba 发表于 2026-9-3 16:14
年初的时候公司一台电脑中招了
7#
canku788 发表于 2026-9-4 10:54
一般人不细看

12121.png (93.99 KB, 下载次数: 0)

12121.png
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-9-9 17:01

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表