【随缘翻译】起底 Heroskeep:冒打包游戏之名,行散播病毒之实

译者按

本文原载于 Fitgirl Repacks:https://fitgirl-repacks.site/heroskeep-the-malware-distributor/。我平日不时在这上面发现有趣的独立游戏并试玩,无意间发现这篇文章,其专业性和火绒安全所发表的深度溯源报告竟不相上下(甚而还有相似案例)。我饶有兴致,特此译制,正好借此练习一下翻译手感。

警告/免责声明

除非出于研究目的,否则请勿试图下载或分发本文所载种子或可执行文件。风险自负!
本人和 Fitgirl 及其他利益相关方均不存在利害关系。

本文和博客其他文章一样,以 Creative Commons 署名·非商业使用·禁止演绎 4.0 许可协议分发,务请遵守。以下“笔者”均指代原文作者 Fitgirl。


前言 & 复现过程

好了,在笔者的用户帮助之下,笔者可以笃定:昨天笔者撰文公布的疑似恶意数据包确实含有恶意软件。

该数据包由名为 Heroskeep 的用户在两个大型 Torrent 索引站点——1337x 和 TPB 分发:

1
2
https://1337x.to/user/heroskeep/
https://thepiratebay.org/search.php?q=user:heroskeep

2026 年 1 月 15 日更新: 1337x 和 TPB 均已清空 Heroskeep 账户,删除其一切种子。

下面将展示 Heroskeep 发布的游戏包被植入恶意软件的实证,附复现流程。

要找出恶意软件,你仅需从 Heroskeep 的游戏包里提取以下两份文件(该流程需 10 个月左右):

  • setup.exe (集成了恶意软件加载模块的安装程序)
  • Redist.bin (内含恶意软件,任何打包均内带,大小均为 298.1 MB)

以这个种子为样例:

警告!仅限研究用途!

1
2
FIFA 22-VOICES38 [v1.0.77.45722] [ALL DLCs] [Multi21]
magnet:?xt=urn:btih:83691C96A2E8E156EAEBA9014749F26BCE5970BB

将该种子内的那两个文件下载好以后,千万不要 运行 setup.exe。建议将其重命名为 setup.exe_ 以防不测。

现在从 Source Forge 拉取解包程序 Inno Unpacker: https://innounp.sourceforge.net/。然后,将下载来的 innounp050.rar 解压到和 setup.exe_ 相同的目录下。

在该目录新建一个文本文档,用记事本打开,粘贴以下内容:

1
innounp.exe -x -a -dUnpacked -m %1

保存后将此文档改名为 Unpacker.bat。将 setup.exe_ 拖拽到 Unpacker.bat 之上。解压后的内容将出现在新目录 Unpacked 当中。
新目录里还有一个次级目录 embedded,请留意 CompiledCode.bin——这是 setup.exe 执行安装过程所需字节码的所在。

CompiledCode.bin 尚不具备人类可读性,这时要用到反编译工具:

下载工具包 IFPSTools.NET:https://github.com/Wack0/IFPSTools.NET/releases,将 ifpstools-net_v2.0.4.zip 解压到和 CompiledCode.bin 相同的目录下;然后将 CompiledCode.bin 拖拽到 ifpsdasm.exe 上方并释放。这样,我们得到了反编译为汇编代码(机器码)的文件 CompiledCode.txt

尽管人类可读性有了大幅改观,但代码里尚存在反检测的加密字符串;这些字符串以原始的双重 base64 算法进行编码,只需解码便可见庐山真面目。

笔者编写了一份简易 Python 脚本以便解码(需先安装 Python,脚本可在此下载)。运行该脚本,例如:

python.exe _decode_base64_in_asm.py CompiledCode.txt CompiledCode.decoded.txt

译者注:建议将该脚本复制到和 CompiledCode.txt 相同的目录下,Shift + 右键空白处并选择“在 Powershell 打开”,再运行上述命令。

该脚本会给汇编代码内加密字符串进行解码,保存在同一行后的注释中。注释内容示例:

1
assign Var6, UnicodeString_3("VW1Wa2FYTjBMbUpwYmc9PQ==") ;DECODED STRING: Redist.bin

其中,VW1Wa2FYTjBMbUpwYmc9PQ== 是加密的字符串,解码结果以注释形式附加于行末。

下面笔者将引用 CompiledCode.decoded.txt 内附代码所在行数来进行分析。

一、恶意软件加载模块

1.1 反检测系统

setup.exe 运用了多种手段来规避人类或反病毒软件的检测。

首先,程序会检测当前 Windows 实例的安装日期;如安装至今不足 90 日,则规避。这是考虑到某些临时启用的虚拟机会将 Windows 目录的创建日期设置在虚拟机创建当日,日期较新近。见 16246 行:

1
.function(export) BOOLEAN ISWINDOWSFOLDEROLDERTHAN90DAYS()

下一步,程序会检测并规避虚拟机环境或存在进程/网络监测进程的环境,此类环境常用于恶意软件分析。见 29536 行以下 loc_33a 函数,例如:

1
2
3
4
assign Var42, UnicodeString_3(“ZG1KdmVIUnlZWGt1WlhobA==”) ;DECODED STRING: vboxtray.exe
assign Var42, UnicodeString_3(“ZG0xMGIyOXNjMlF1WlhobA==”) ;DECODED STRING: vmtoolsd.exe
assign Var42, UnicodeString_3(“VTJGdVpHSnZlR2xsUkdOdmJVeGhkVzVqYUM1bGVHVT0=”) ;DECODED STRING: SandboxieDcomLaunch.exe
assign Var42, UnicodeString_3(“VUhKdlkyMXZiaTVsZUdVPQ==”) ;DECODED STRING: Procmon.exe

接着,出于某种原因,程序会检测大多数常见 Torrent 客户端的进程并终止。见 30297 行以下:

1
2
3
assign Var44, UnicodeString_3(“/f /im \”qbittorrent*\””)
pushtype UnicodeString_2
assign Var45, UnicodeString_3(“taskkill.exe”)

如所有检测均通过,程序进入恶意软件释放流程。

1.2 恶意软件释放

程序在 Windows Defender 规则集中为恶意软件存储目录添加白名单,见 30894 行:

1
assign Var39, UnicodeString_3("/c \"powershell Add-MpPreference -ExclusionPath \"")

恶意软件被释放到 C:\Users\<你的用户名>\AppData\Roaming\Microsoft\,见 30929 行:

1
assign Var45, UnicodeString_3(“ZTNWelpYSmhjSEJrWVhSaGZWeE5hV055YjNOdlpuUmM=”) ;DECODED STRING: {userappdata}\Microsoft\

没错,它就躲在“Microsoft”目录里。

建立目录并设置白名单后,程序从 Redist.bin 指定恶意程序进行释放;这由两个函数实现,分别见 16147 行、16190 行:

1
.function(export) void INITIALIZEPAYLOADSIZE()
1
.function(export) void INITIALIZERANDOMOFFSETS()

恶意软件选项共计 40 种,随机抽取。setup.exe 还会多次对 Redist.bin 进行检测,确保其存在(25857 行)且未被更改(MD5 校验,26001 行);当二者之一不满足时,程序自动关闭。Redist.bin 伪造了 FreeArc 头部,无法以任何 FreeArc 方式解压。硬编码的 MD5 哈希值为 03cf23c41bc7468021826f7b897f8a7f
25857 行:

1
assign Var6, UnicodeString_3(“VW1Wa2FYTjBMbUpwYmc9PQ==”) ;DECODED STRING: Redist.bin

26001 行:

1
assign Var4, UnicodeString_3(“TUROalpqSXpZelF4WW1NM05EWTRNREl4T0RJMlpqZGlPRGszWmpoaE4yWT0=”) ;DECODED STRING: 03cf23c41bc7468021826f7b897f8a7f

如两项检测均通过,程序会为恶意软件随机指派一个文件名;名称表被硬编码,总计 3652 种。见 17061 行以下,例如:

1
2
3
4
5
6
7
8
9
10
11
assign Global44[196], UnicodeString_3(“UVhSMGNtbGlkWFJs”) ;DECODED STRING: Attribute
assign Global44[197], UnicodeString_3(“UVhWa1lXTnBkSGs9”) ;DECODED STRING: Audacity
assign Global44[198], UnicodeString_3(“UVhWa2FXZG5iR1U9”) ;DECODED STRING: Audiggle
assign Global44[199], UnicodeString_3(“UVhWa2FXOD0=”) ;DECODED STRING: Audio
assign Global44[200], UnicodeString_3(“UVhWa2FXOVNaV3hoZVE9PQ==”) ;DECODED STRING: AudioRelay
assign Global44[201], UnicodeString_3(“UVhWa2FXOW5jbUZpWW1WeQ==”) ;DECODED STRING: Audiograbber
assign Global44[202], UnicodeString_3(“UVhWa2FXOTBiMjVwWXc9PQ==”) ;DECODED STRING: Audiotonic
assign Global44[203], UnicodeString_3(“UVhWeVlRPT0=”) ;DECODED STRING: Aura
assign Global44[204], UnicodeString_3(“UVhWeWIzSmg=”) ;DECODED STRING: Aurora
assign Global44[205], UnicodeString_3(“UVhWemJHOW5hV056”) ;DECODED STRING: Auslogics
assign Global44[206], UnicodeString_3(“UVhWMGIwTkJSQT09”) ;DECODED STRING: AutoCAD

其中 Aurora 这个名称在 Reddit 帖子里被提及:
https://reddit.com/r/PiratedGames/comments/1q9tji5/beware_of_user_heroskeep_on_1337x_his_uploads/

这个恶意软件和本文所述别无二致,区别只是它来自 Heroskeep 发布的另一个游戏包。

万事俱备,恶意软件和 readme.txt 等杂项被释放到 C:\Users\<你的用户名>\AppData\Roaming\Microsoft\ 目录内。

为确保恶意软件持续运行,程序还会创建计划任务,见 16695 行:

1
.function(export) void INITIALIZERANDOMSCHTASK()

其路径同样是随机指派的,形如某个 Windows 原生函数:

1
assign Var2, UnicodeString_3(“VFdsamNtOXpiMlowWEZkcGJtUnZkM05jVlhCa1lYUmxUM0pqYUdWemRISmhkRzl5WEE9PQ==”) ;DECODED STRING: Microsoft\Windows\UpdateOrchestrator\

计划任务每 30 分钟运行一次,届时如恶意软件被终止,则重新启动之。相关字符串可见于多行,如 31587 行:

1
assign Var41, UnicodeString_3(“SWlBdmMyTWdiV2x1ZFhSbElDOXRieUF6TUE9PQ==”) ;DECODED STRING: ” /sc minute /mo 30

二、恶意软件行为

上面提到恶意软件共计 40 种,实为相同二进制略微修改后的副本。它们均使用 Themida 套壳(Themida 被视为 Denuvo 的轻量化版本,主要用于隐蔽软件行为)。各副本大小约 7 MB,用特殊工具解压后约为 21 MB。它们毫无疑问,均为挖矿软件——用来挖 Monero/XMR。

笔者也制作了可用于解压这些恶意软件本体的 Python 脚本。下载链接见文末。

笔者将其中两个样本上传到 hybrid-analysis.com:

二者的检测结果基本一致。

值得留意的特征

找到了字符串 stratum+tcp://,提示 Stratum 挖矿协议。

找到了字符串 mbam.exembam.exe 是知名反恶意程序软件 Malwarebytes 的可执行二进制文件名,疑似存在对推广软件检测工具的检测。

具备检测沙箱进程的能力:

1
2
Found string “VBoxService.exe” (Indicator: “vboxservice.exe”; Source: “00000000-00007316.00000000.282950.40581000.00000002.mdmp”)
Found string “VBoxTray.exe” (Indicator: “vboxtray.exe”; Source: “00000000-00007316.00000000.282950.40581000.00000002.mdmp”)

具备通过 API 检测虚拟机环境的能力:

1
Found string “NtQuerySystemInformation” (Indicator: “NtQuerySystemInformation”; Source: “00000000-00007316.00000000.282950.40581000.00000002.mdmp”)

在二进制/内存中找到了电子邮箱地址:

1
2
Pattern match: “ncz5enfj@proxifyme50.com”
Pattern match: “ncz5enfj@proxy00002.com”

在内存中找到了注册表路径:

1
2
3
4
5
6
7
8
“SOFTWARE\Wireshark” in Source: 00000000-00007316.00000000.282950.40581000.00000002.mdmp
“SOFTWARE\GlassWire” in Source: 00000000-00007316.00000000.282950.40581000.00000002.mdmp
“SOFTWARE\Paessler” in Source: 00000000-00007316.00000000.282950.40581000.00000002.mdmp
“SOFTWARE\SolarWinds” in Source: 00000000-00007316.00000000.282950.40581000.00000002.mdmp
“SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps” in Source: 00000000-00007316.00000000.282950.40581000.00000002.mdmp
“HARDWARE\DESCRIPTION\System\CentralProcessor\%d” in Source: 00000000-00007316.00000000.282950.40581000.00000002.mdmp
“\REGISTRY\MACHINE\SOFTWARE\Classes” in Source: 00000000-00007316.00000000.282950.40A3B000.00000020.mdmp
“\Registry\Machine\Software\Classes\” in Source: 00000000-00007316.00000000.282950.40A3B000.00000020.mdmp

具备执行保护能力:

1
2
3
4
5
The analysis shows indicators which can be used as execution guardrails to ensure that payload only executes against intended targets/system. Matched sigs: Able to identify sandbox environment running process
Matched sigs: Contains ability to delay execution by waiting for signal/timeout (API string)
Matched sigs: Contains ability to retrieve the time elapsed since the system was started (API string)
Matched sigs: Able to identify virtual environment by using API string
Matched sigs: The input sample contains the RDTSCP instruction

尝试访问不存在的文件(非可执行文件):

1
2
3
“pe_0000.bad.dll.exe” trying to access non-existent file “C:\INFO.TXT”
“pe_0000.bad.dll.exe” trying to access non-existent file “C:\Users\%USERNAME%\..JSON”
“pe_0000.bad.dll.exe” trying to access non-existent file “%APPDATA%\Microsoft\README.TXT” (which is dropped by original setup.exe)

在二进制/内存中找到了疑似 IP 地址:

1
2
3
4
Potential IP “1.3.101.110” found in string “X25519:1.3.101.110”
Potential IP “1.3.101.111” found in string “X448:1.3.101.111”
Potential IP “1.3.101.112” found in string “ED25519:1.3.101.112”
Potential IP “1.3.101.113” found in string “ED448:1.3.101.113”

IP 地址定位在中国某云服务商。推测为矿池。

在二进制/内存中找到了疑似 URL:

1
2
3
4
5
6
7
Pattern match: “proxifyme50.com/launcher_077.exe”
Pattern match: “proxy00002.com/launcher_077.exe”
Heuristic match: “nicehash.com”
Heuristic match: “donate.ssl.xmrig.com”
Heuristic match: “donate.v2.xmrig.com”
Heuristic match: “vpnetworkc.com”
Heuristic match: “proxy00004.com”

在内存转储中找到了疑似 URL:

1
Found URL “ftp://fhqfg8uu:ncz5enfj@proxifyme50.com/launcher_077.exe

具备通过 API 操作远程桌面的能力:

1
Found reference to API “WTSSendMessageW” (Indicator: “WTSSendMessage”; File: “pe_0000.bad.dll”)

vx-under-ground 管理者披露了上述样本的更多细节:
https://malwaresourcecode.com/home/my-projects/write-ups/r-piratedgames-drama.-is-it-malware-yes.-is-it-cool-malware-no

译者注:这文章也拜读了,作者是恶意软件界“老司机”,自称鉴赏过逾四千万种恶意软件,行文潇洒自如,浑然天成。在他看来,这软件“称不上有多么精良,有多么诗意,简直泯然众人”(This is a pretty insignificant malware campaign in regards to sophistication and novelty. ),“一点都不好玩”(Is it cool malware? No. )。

本次溯源过程的链接已被发送给 1337x 管理团队;笔者希望永久封禁 Heroskeep、删除其一切种子。早在五年前,此人便在种子里用另一方式投毒。
https://www.reddit.com/r/PiratedGames/comments/jp71l4/beware_of_miner_unpackerexe_decompressexe/

至于 TPB——该站点没有实现举报功能,举报要靠一个人工管理的小论坛。如果你有时间和意愿,不妨登录进去提交对该用户的举报,说不定能对 Heroskeep 施以制裁。

但还须提醒,像 Heroskeep 这种人总会换个马甲卷土重来,投放的恶意软件也会更精良。

Heroskeep_Malware_Files.zip

此压缩包集合了以上所需的一切文件,供读者自行分析。

警告!仅限研究用途!

1
2
https://fuckingfast.co/kuriy5xbt5hv#Heroskeep_Malware_Files.zip
https://vikingfile.com/f/FZeDrmnbnz#Heroskeep_Malware_Files.zip