2025.02.07 更新:Google 从 Google Play 中移除了恶意应用程序。
2025.02.06 更新:Apple 从 App Store 中移除了恶意应用程序。
2023 年 3 月,ESET 的研究人员发现恶意软件植入了各种消息应用程序模块。其中一些模块扫描了用户的图片库,以搜索加密钱包访问恢复短语。搜索采用了 OCR 模型,该模型选择了受害者设备上的图像以进行窃取并发送到 C2 服务器。该活动针对 Android 和 Windows 用户,恶意软件通过非官方来源传播。2024 年末,我们发现了一个新的恶意软件活动,我们将其称为“SparkCat”,其运营商在通过官方和非官方应用商店攻击 Android 和 iOS 用户时使用了类似的策略。我们的结论简而言之:
-
我们发现一些 Android 和 iOS 应用程序(其中一些可在 Google Play 和 App Store 上找到)嵌入了用于窃取加密钱包恢复短语的恶意 SDK/框架。Google Play 中受感染的应用程序下载量超过 242,000 次。这是首次在 Apple 的 App Store 中发现窃取程序。
-
Android 恶意软件模块会解密并启动使用 Google 的 ML Kit 库构建的 OCR 插件,并使用该插件识别图库内图片中的文本。与从 C2 收到的关键字匹配的图片会被发送到服务器。iOS 专用恶意模块具有类似的设计,也依赖 Google 的 ML Kit 库进行 OCR。
-
该恶意软件被我们称为“SparkCat”,它使用一种以 Rust(一种非典型移动应用程序语言)实现的未识别协议与 C2 进行通信。
-
根据恶意软件文件中的时间戳和 GitLab 存储库中配置文件的创建日期判断,SparkCat 自 2024 年 3 月起一直处于活跃状态。
Google Play 应用中存在恶意软件 SDK
第一个引起我们怀疑的应用程序是阿联酋和印度尼西亚的一款食品配送应用程序,名为“ComeCome”(APK名称:com.bintiger.mall.android),研究时该应用程序已在Google Play上架,下载量超过10,000次。
Application 子类中的 onCreate 方法(应用程序的入口点之一)在版本 2.0.0 中被重写(f99252b23f42b9b054b7233930532fcd)。此方法初始化名为“Spark”的 SDK 组件。它最初是经过混淆的,因此我们在分析之前对其进行了静态反混淆。
调用可疑 SDK
Spark 是用 Java 编写的。初始化时,它会从恶意软件主体中嵌入的 GitLab URL 下载 JSON 配置文件。使用 base64 解码 JSON,然后使用 CBC 模式下的 AES-128 解密。
正在解密 GitLab 的配置
如果 SDK 无法检索配置,则使用默认设置。
我们设法从 GitLab 下载了以下配置:
{
"http": ["https://api.aliyung.org"],
"rust": ["api.aliyung.com:18883"],
"tfm": 1
}
“http” 和 “rust” 字段包含特定于 SDK 的 C2 地址,tfm 标志用于选择 C2。当 tfm 等于 1 时,“rust” 将用作 C2,如果 tfm 为任何其他值,则使用“http”。
Spark 使用 POST 请求与“http”服务器通信。它在发送前使用 CBC 模式下的 AES-256 加密数据,并使用 CBC 模式下的 AES-128 解密服务器响应。在这两种情况下,密钥都是硬编码常量。
向“rust”发送数据的过程包括三个阶段:
-
数据以 CBC 模式通过 AES-256 加密,使用与“http”服务器相同的密钥。
-
恶意软件生成一个 JSON,其中 <PATH> 是数据上传路径,<DATA> 是上一阶段的加密数据。
{
"path": "upload@<PATH>",
"method": "POST",
"contentType": "application/json",
"data": "<DATA>"
}
-
JSON 在本机 libmodsvmp.so 库的帮助下通过未识别的协议通过 TCP 套接字发送到服务器。该库用 Rust 编写,伪装成流行的 Android 混淆器。
对该库进行静态分析并不容易,因为 Rust 使用非标准调用约定,并且文件中没有函数名称。在使用 Frida 进行动态分析后,我们成功重建了交互模式。在将数据发送到服务器之前,该库会为 AES-GCM-SIV 密码生成一个 32 字节密钥。使用此密钥,它会加密使用 ZSTD 预压缩的数据。算法的 nonce 值不会生成,也不会在代码中设置为“unique nonce”(原文如此)。
使用硬编码的 nonce 值扩展 AES 密钥
AES 密钥使用 RSA 加密,然后也发送到服务器。从恶意 SDK 调用本机方法时,将传递此 RSA 加密的公钥(格式为 PEM)。在 AES 密钥加密之前,该消息会填充 224 个随机字节。收到请求后,攻击者的服务器会使用私钥 RSA 密钥解密 AES 密钥,解码收到的数据,然后使用 ZSTD 压缩响应并使用 AES-GCM-SIV 算法对其进行加密。在本机库中解密后,服务器响应将传递到 SDK,并根据与“http”服务器通信的相同原理进行 base64 解码和解密。请参阅下面的恶意软件模块与“rust”服务器之间通信的示例。
与“rust”服务器通信的示例
下载配置后,Spark 会从资产中解密有效载荷并在单独的线程中执行。它使用 XOR 和 16 字节密钥进行加密。
正在解密的有效载荷
有效载荷 (c84784a5a0ee6fedc2abe1545f933655) 是 Google ML Kit 库中 TextRecognizer接口的包装器。它根据系统语言加载不同的 OCR 模型,以识别图像中的拉丁文、韩文、中文或日文字符。然后,SDK 将设备信息上传到 C2 服务器上的 /api/e/d/u。服务器响应一个控制进一步恶意软件活动的对象。该对象是一个 JSON 文件,其结构如下所示。uploadSwitch 标志允许恶意软件继续运行(值 1)。
{
"code": 0,
"message": "success",
"data": {
"uploadSwitch": 1,
"pw": 0,
"rs": ""
}
}
然后,SDK 注册一个应用程序活动生命周期回调。每当用户发起与支持团队的聊天时(使用合法的第三方 Easemob HelpDesk SDK 实现),处理程序都会请求访问设备的图片库。如果上述对象中的 pw 标志等于 1,则模块将在被拒绝的情况下继续请求访问权限。SDK 请求背后的理由乍一看似乎很合理:用户可能会在联系支持时附加图片。
请求图库的读取权限时给出的原因
如果获得访问权限,SDK 将运行其主要功能。首先向 C2 上的 /api/e/config/rekognition 发送请求,然后获取用于处理 OCR 结果的参数作为响应。
{
"code": 0,
"message": "success",
"data": {
"letterMax": 34,
"letterMin": 2,
"enable": 1,
"wordlistMatchMin": 9,
"interval": 100,
"lang": 1,
"wordMin": 12,
"wordMax": 34
}
}
这些参数由处理器类使用,用于通过 OCR 识别的单词过滤图像。恶意软件还会在 /api/e/config/keyword 中请求 KeywordsProcessor 的关键字列表,后者会使用这些关键字选择要上传到 C2 服务器的图像。
在OCR图像处理结果中搜索关键字
除了 KeywordsProcessor,该恶意软件还包含另外两个处理器:DictProcessor 和 WordNumProcessor。前者使用资产中 rapp.binary 内解密存储的本地化词典过滤图像,后者按长度过滤单词。每个进程的 letterMin 和 letterMax 参数定义允许的单词长度范围。对于 DictProcessor,wordlistMatchMin 设置图像中字典单词匹配的最小阈值。对于 WordNumProcessor,wordMin 和 wordMax 定义识别单词总数的可接受范围。注册受感染设备的请求响应中的 rs 字段控制将使用哪个处理器。
符合搜索条件的图像分三步从设备下载。首先,将包含图像 MD5 哈希的请求发送到 C2 上的 /api/e/img/uploadedCheck。接下来,将图像上传到亚马逊的云存储或“rust”服务器上的 file@/api/res/send。之后,将图像链接上传到 C2 上的 /api/e/img/rekognition。因此,从软件包名称 com.spark.stat 可以看出,专为分析而设计的 SDK 实际上是选择性窃取图库内容的恶意软件。
上传图片链接
我们问自己,攻击者在寻找什么样的图像。为了找到答案,我们从 C2 服务器请求了一系列关键字,以便进行基于 OCR 的搜索。在每种情况下,我们都会收到中文、日语、韩语、英语、捷克语、法语、意大利语、波兰语和葡萄牙语的单词。这些词都表明攻击者是出于经济动机,专门针对恢复短语(也称为“助记符”),这些短语可用于重新获得对加密货币钱包的访问权限。
{
"code": 0,
"message": "success",
"data": {
"keywords": ["助记词", "助記詞", "ニーモニック", "기억코드", "Mnemonic",
"Mnemotecnia", "Mnémonique", "Mnemonico", "Mnemotechnika", "Mnemônico",
"클립보드로복사", "복구", "단어", "문구", "계정", "Phrase"]
}
}
不幸的是,ComeCome 并不是我们发现的唯一一款嵌入恶意内容的应用程序。我们还发现了许多其他不相关的应用程序,涉及各种主题。截至撰写本文时,这些应用程序的安装次数总计超过 242,000 次,其中一些应用程序仍可在 Google Play 上访问。完整清单可在“入侵指标”部分找到。我们提醒 Google 其商店中存在受感染的应用程序。
包含恶意负载的热门应用程序
此外,我们的遥测显示,恶意应用程序也通过非官方渠道传播。
不同应用的 SDK 功能可能略有不同。ComeCome 中的恶意软件仅在用户打开支持聊天时请求权限,而在其他一些情况下,启动核心功能会充当触发器。
一个小细节……
当我们分析被木马感染的 Android 应用程序时,我们注意到 SDK 在发送给 C2 的设备信息中将 deviceType 设置为“android”,这表明其他平台上也存在类似的木马。
收集有关受感染 Android 设备的信息
随后的调查发现,App Store 中的恶意应用程序感染了包含相同木马的框架。例如,iOS 版 ComeCome 的感染方式与 Android 版相同。这是已知的第一例在 Apple 官方应用市场中发现感染 OCR 间谍软件的应用程序案例。
App Store 中的 ComeCome 页面
关于 ComeCome 的负面用户反馈
App Store 应用中的恶意框架
我们在 App Store 中检测到一系列嵌入恶意框架的应用程序。我们无法确定感染是供应链攻击的结果还是开发人员的蓄意行为。其中一些应用程序(例如送餐服务)似乎是合法的,而其他一些应用程序显然是为了引诱受害者而构建的。例如,我们看到了同一开发人员开发的几款类似的具有 AI 功能的“消息应用程序”:
App Store 中的通讯应用旨在引诱受害者
除了恶意框架本身之外,一些受感染的应用程序在根文件夹中还包含一个modify_gzip.rb脚本。开发人员显然使用它来将框架嵌入到应用程序中:
modify_gzip.rb的内容
该框架本身是用 Objective-C 编写的,并使用HikariLLVM进行混淆。在我们检测到的应用程序中,它有以下三个名称之一:
-
压缩;
-
谷歌应用程序开发工具包;
-
統計。
与 Android 版本一样,iOS 恶意软件使用了ML Kit接口,该接口可以访问经过训练的 Google OCR 模型来识别文本,以及实现自定义 C2 通信协议的 Rust 库。但是,在这种情况下,它直接嵌入到恶意可执行文件中。与 Android 版本不同,iOS 框架保留了调试符号,这使我们能够识别出几个独特的细节:
-
这些行显示了框架创建者设备上存储项目的路径,包括用户名:
-
/Users/qiongwu/:项目作者的主目录
-
/Users/quiwengjing/:Rust 库创建者的主目录
-
C2-rust 通信模块名为im_net_sys。除了客户端之外,它还包含攻击者服务器可能用来与受害者通信的代码。
-
该项目的原始名称是GZIP。
恶意框架代码行中的项目详细信息
该框架包含多个恶意类。以下是特别值得关注的:
-
MMMaker:下载配置并收集有关设备的信息。
-
ApiMgr:发送设备数据。
-
PhotoMgr:在设备上搜索包含关键字的照片并将其上传到服务器。
-
MMCore:存储有关 C2 会话的信息。
-
MMLocationMgr:收集设备的当前位置。在我们的测试期间,它没有发送任何数据,因此此类的确切用途尚不清楚。
某些类(例如MMMaker)可能在框架的早期版本中缺失或使用不同的名称,但这并没有改变恶意软件的核心功能。
混淆大大增加了样本的静态分析的复杂性,因为字符串是加密的,程序的控制流也被模糊了。为了快速解密感兴趣的字符串,我们选择了动态分析。我们在 Frida 下运行该应用程序,并捕获了存储这些字符串的_data部分的转储。引起我们注意的是,应用程序的 bundleID 位于解密数据之中:
com.lc.btdj:+[MMCore config]选择器中使用的ComeCome bundleID
事实证明,该框架还存储了+[MMCore config]选择器中使用的其他应用程序包标识符。
我们的结论如下:
-
该木马的行为会根据其运行的应用程序而有所不同。
-
可能被感染的应用程序比我们原先想象的要多。
在调查期间,与这些 ID 关联的部分应用已从 App Store 中移除,而其他一些应用仍然存在且包含恶意代码。列表中的部分 ID 指的是调查期间不包含恶意框架的应用:
-
com.kh-super.ios.superapp
-
im.token.app
-
com.unicornsoft.unicornhttpsforios
与 Android 专用版本一样,该木马实现了三种 OCR 输出过滤模式:关键字、单词长度和以加密形式存储在框架内部的“wordlists”文件夹中的本地化词典。遗憾的是,我们无法确定该恶意软件确实使用了最后一种方法。我们分析的所有样本均未包含词典链接或在运行时访问过这些词典。
发送包含关键字的选定照片是恶意框架运行的关键步骤。与 Android 应用程序类似,该木马仅在启动负责显示支持聊天的视图控制器时请求访问图库的权限。在初始化阶段,该木马根据其运行的应用程序,用自己的包装器替换相关控制器中的viewDidLoad或viewWillAppear方法,并调用方法+[PhotoMgr startTask:]。然后后者检查应用程序是否有权访问图库,并在需要时请求访问。接下来,如果获得访问权限,PhotoMgr会在可用且未处理过的照片中搜索符合发送条件的照片。
恶意包装器的代码片段围绕着 viewDidLoad 方法,该方法确定木马在哪个应用程序中运行
虽然尝试了几次,我们还是成功让该应用将图片上传到亚马逊云,然后将相关信息发送到攻击者的服务器。该应用使用 HTTPS 与服务器通信,而不是自定义的“rust”协议:
与C2的通信并上传到AWS
发送的数据如下:
POST /api/e/img/uploadedCheck
{
"imgSign": <imgMD5>,
"orgId": <implantId>,
"deviceId": <deviceUUID>
}
POST api/e/img/rekognition
{
"imgUrl": "https://dmbucket102.s3.ap-northeast-
1.amazonaws.com/"<app_name>_<device_uuid>"/photo_"<timestamp>".jpg",
"deviceName": "ios",
"appName": <appName>,
"deviceUUID": <deviceUUID>,
"imgSign": <imgMD5>,
"imgSize": <imgSize>,
"orgId":<implantId>,
"deviceChannel": <iphoneModel>,
"keyword":<keywordsFoundOnPicture>,
"reksign":<processor type>
}
我们正在调查的恶意框架的最旧版本构建于 2024 年 3 月 15 日。虽然它与新版本没有太大区别,但这个版本包含更多未加密的字符串,包括 API 端点和单个硬编码的 C2 地址。服务器响应以纯文本形式接收。
硬编码到最旧版本的恶意框架中的 URL
应用程序中的文件创建日期
活动特色
在分析 Android 应用程序时,我们发现文字处理器代码包含中文注释。C2 服务器响应格式错误的请求返回的错误描述也是中文的。这些以及我们在分析 iOS 特定版本时获得的框架开发人员主目录的名称表明,恶意模块的创建者能说一口流利的中文。话虽如此,我们没有足够的数据将该活动归咎于已知的网络犯罪团伙。
我们的调查显示,攻击者的目标是加密钱包恢复短语,这些短语足以完全控制受害者的加密钱包并窃取资金。必须注意的是,该恶意软件非常灵活,不仅可以窃取这些短语,还可以窃取图库中的其他敏感数据,例如可能已在屏幕截图中捕获的消息或密码。多种 OCR 结果处理模式可减轻模型错误的影响,如果仅使用关键字处理,这些错误可能会影响访问恢复短语图像的识别。
我们对 iOS 框架内的恶意 Rust 代码进行了分析,发现了用于与“rust”服务器和服务器端加密组件进行通信的客户端代码。这表明攻击者的服务器可能也使用 Rust 进行协议处理。
服务器端私钥RSA导入
我们认为,此次攻击活动至少针对的是欧洲和亚洲的 Android 和 iOS 用户,如下所示:
-
所使用的关键词是欧洲和亚洲国家居民的各种母语。
-
资产内的词典以与关键字相同的方式本地化。
-
一些应用程序似乎在多个国家运营。一些送餐应用程序支持使用阿联酋、哈萨克斯坦、中国、印度尼西亚、津巴布韦和其他国家的电话号码进行注册。
我们怀疑除欧洲和亚洲之外的其他地区的移动用户也可能成为此次恶意活动的目标。
我们开始调查的第一个恶意模块名为“Spark”。当我们分析 iOS 专用木马时,恶意框架本身的捆绑包 ID“bigCat.GZIPApp”引起了我们的注意。因此得名“SparkCat”。以下是此恶意软件的一些特征:
-
跨平台兼容性;
-
使用在移动应用中很少见的 Rust 编程语言;
-
官方应用市场作为传播载体;
-
隐秘性,C2 域经常模仿合法服务和伪装成系统包的恶意框架;
-
混淆,阻碍分析和检测。
结论
不幸的是,尽管官方市场进行了严格审查,并且人们普遍意识到了基于 OCR 的加密钱包盗窃骗局,但受感染的应用程序仍然进入了 Google Play 和 App Store。这种木马特别危险的原因在于,没有迹象表明应用程序中隐藏了恶意植入物。它请求的权限可能看起来像是其核心功能所需的权限,或者乍一看似乎无害。该恶意软件的运行也相当隐秘。这个案例再次打破了 iOS 在某种程度上不受针对 Android 的恶意应用程序威胁影响的神话。以下是一些可以帮助您避免成为此恶意软件受害者的提示:
-
如果您的设备上安装了受感染的应用程序,请将其删除,并且避免重新安装,直到修复程序发布为止。
-
避免将包含敏感信息的截图(例如加密钱包恢复短语)存储在图库中。您可以将密码、机密文件和其他敏感信息存储在特殊应用中。
-
在所有设备上使用强大的安全产品。
我们的安全产品在检测到与此活动相关的恶意软件时返回以下结论:
-
HEUR:Trojan.IphoneOS.SparkCat.*
-
HEUR:Trojan.AndroidOS.SparkCat.*
指标
感染的 Android 应用程序
0ff6a5a204c60ae5e2c919ac39898d4f
21bf5e05e53c0904b577b9d00588e0e7
a4a6d233c677deb862d284e1453eeafb
66b819e02776cb0b0f668d8f4f9a71fd
f28f4fd4a72f7aab8430f8bc91e8acba
51cb671292eeea2cb2a9cc35f2913aa3
00ed27c35b2c53d853fafe71e63339ed
7ac98ca66ed2f131049a41f4447702cd
6a49749e64eb735be32544eab5a6452d
10c9dcabf0a7ed8b8404cd6b56012ae4
24db4778e905f12f011d13c7fb6cebde
4ee16c54b6c4299a5dfbc8cf91913ea3
a8cd933b1cb4a6cae3f486303b8ab20a
ee714946a8af117338b08550febcd0a9
0b4ae281936676451407959ec1745d93
f99252b23f42b9b054b7233930532fcd
21bf5e05e53c0904b577b9d00588e0e7
eea5800f12dd841b73e92d15e48b2b71
iOS 框架 MD5:
35fce37ae2b84a69ceb7bbd51163ca8a
cd6b80de848893722fa11133cbacd052
6a9c0474cc5e0b8a9b1e3baed5a26893
bbcbf5f3119648466c1300c3c51a1c77
fe175909ac6f3c1cce3bc8161808d8b7
31ebf99e55617a6ca5ab8e77dfd75456
02646d3192e3826dd3a71be43d8d2a9e
1e14de6de709e4bf0e954100f8b4796b
54ac7ae8ace37904dcd61f74a7ff0d42
caf92da1d0ff6f8251991d38a840fb4a
db128221836b9c0175a249c7f567f620
GitLab 中的木马配置
hxxps://gitlab[.]com/group6815923/ai/-/raw/main/rel.json
hxxps://gitlab[.]com/group6815923/kz/-/raw/main/rel.json
C2
api.firebaseo[.]com
api.aliyung[.]com
api.aliyung[.]org
uploads.99ai[.]world
socket.99ai[.]world
api.googleapps[.]top
原文始发于微信公众号(Ots安全):拿走我的钱:Google Play 和 App Store 中的 OCR 加密货币窃取者
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论