Apple系统快防不住了,新型间谍程序无需用户交互突破防护

admin 2025-12-30 01:17:46 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 揭露新型macOS间谍软件,利用已签名并公证的Swift应用绕过Gatekeeper,无需交互即下载执行恶意脚本。该程序具备环境检测与速率限制等规避特性,反映攻击者正滥用合法签名机制。建议用户警惕不明来源的签名应用,安全团队需加强对签名滥用攻击的检测。 综合评分: 88 文章分类: 恶意软件,威胁情报,免杀,终端安全


cover_image

Apple系统快防不住了,新型间谍程序无需用户交互突破防护

原创

suntiger

二进制空间安全

2025年12月29日 15:17 北京

将二进制空间安全设为”星标⭐️”

第一时间收到文章更新

关键概念

#

在开始之前,先了解一下Apple系统的代码签名和公证技术。代码签名是Apple要求开发者在发布macOS应用时必须的一件事,本质是:用开发者证书对应用的可执行文件做数字签名,证明这个程序是谁做的,发布后没被篡改。如果用户运行未签名的程序, 双击会被Gatekeeper直接拦截, 弹出”无法验证开发者”的警告, 但签名只能说明有人为它负责,并不说明它不是恶意的。公证是Apple在代码签名之上的第二道审查,相当于:开发者把程序上传给Apple,Apple自动扫描一遍,说:我看过了,目前没发现明显恶意行为。

如果程序已签名+已公证, 则默认可以直接运行,不会弹出高风险警告,不需要”右键”后点击”打开”。

恶意程序背景

该恶意程序是一个经过代码签名并完成Apple公证的Swift应用, 具备偷取用户敏感信息等间谍行为。该程序封装在名为: zk-call-messenger-installer-3.9.2-lts.dmg的磁盘镜像中,通过https://zkcall.net/download分发传播, 完全不需要用户直接与终端交互 , 而是从远程服务器获取一个经过编码的脚本,并通过一个由Swift构建的辅助可执行文件来执行。如图:

通过检查二进制文件的Mach-O结构, 可以确认该应用既有代码签名,也完成了公证, 该恶意软件签名关联的开发者团队ID为:GNJLS3UYZ4, 如图:

随后将其代码目录哈希与 Apple 的吊销列表进行了比对,在分析时点并未发现被吊销的记录, 如图:

另一个值得注意的现象是该磁盘镜像体积异常庞大(25.5MB),这似乎是由于应用包内嵌入了大量诱饵文件而被“膨胀”所致,其中包括与 LibreOffice 应用相关的 PDF 文件, 如图:

#

初始发现

在这个案例中,触发告警的是一条用于监控混淆bash脚本执行的威胁防护Yara规则, 匹配到事件之后,发现有一个位于/tmp/runner的shell脚本正在运行, 如图:

进一步检查该事件,分析与脚本执行关联的进程对象后可以清楚地看到,该脚本是由一个已签名的应用程序启动的。appPath 还表明,该程序是直接从一个已挂载的磁盘镜像中执行的, App path details应用路径详情如下图:

通过分析/tmp/runner的Payload, 可以发现是一个混淆后脚本, 如图:

解码后,发现有一个”focusgroovy.com”的域名, 该脚本会从远程服务器下载一个zip压缩包,内容如图:

#

Swift的Mach-O简要分析

下面重点分析随恶意应用包一同分发的通用架构 runtimectl Mach-O 二进制文件,以验证此前观察到的行为。_main 函数是该二进制文件的入口点,用于初始化应用状态和日志路径,执行基础的网络连通性检查,并在成功时获取第二阶段Payload。

在通过 _NSHomeDirectory() 获取用户主目录后,应用会构建多个运行路径。它会在 ~/Library/Logs/UserSyncWorker.log 创建一个日志文件记录活动,同时在 ~/Library/Application Support/UserSyncWorker/ 下创建一个目录,并在其中维护诸如 last_up 和 gate 等文件,用于跟踪执行时间和更新状态。这些文件仅在此前不存在时才会被创建。如图:

应用会向 ~/Library/Logs/UserSyncWorker.log 写入一条表示开始执行的日志,并定义一个约 3600 秒的最小时间间隔,可能是为了防止可执行文件在短时间内重复运行。

随后,应用通过调用 checkInternet() 进行网络连通性检查,只有在确认联网的情况下,才会继续执行 runInstaller()。如图:

在调用 runInstaller()(后文详述)之后,应用会通过 log() 记录字符串 **Starting update…**。

如果没有网络连接,则会记录另一条日志 **preflight: internet=false**,并通过 \_exit(1) 正常退出进程。

无论执行路径如何,应用都会获取当前日期和时间,将其格式化为本地化字符串并使用 print() 输出到控制台,然后创建或更新 ~/Library/Logs/UserSyncWorker.log 日志文件。这种与网络可用性直接绑定的条件执行逻辑,反映了其刻意避免在离线或沙箱环境中执行的意图。

_runInstaller()函数分析

runInstaller() 实现了完整的第二阶段执行逻辑,既是下载器,也是执行流程本身。它首先通过读取位于 ~/Library/Application Support/UserSyncWorker/last_up 的时间戳文件来实施速率限制。如果文件不存在,或上一次记录的执行时间距今超过约 3600 秒,则流程继续;否则,会记录一条由于速率限制而延迟执行的日志并退出。相关日志示例显示了执行被限制的情况:

12/16/25, 12:38:10 pm GMT: Starting update...12/16/25, 12:38:10 pm GMT: rate-limit: defer, next in 3577s12/16/25, 12:38:10 pm GMT: Done

当时间条件满足后,应用会再次调用 checkInternet() 并记录结果,然后删除此前可能残留在 /tmp 下的文件,例如 /tmp/runner。示例日志显示,预执行的网络检查是成功的。

#

12/16/25, 8:56:30 am GMT: Starting update...12/16/25, 8:56:34 am GMT: preflight: internet=true12/16/25, 8:56:40 am GMT: executing (Paul Falstad's zsh script text executable, ASCII text)...12/16/25, 8:56:40 am GMT: Done.

接下来,函数会准备一个条件性的 HTTP 请求,目标地址为:https[:]//gatemaden.space/curl/985683bd660c0c47c6be513a2d1f0a554d52d241714bb17fb18ab0d0f8cc2dc6, 并使用特定的 User-Agent:UserSyncWorker/1.0 (macOS)。如图:

该请求通过 NSTask 调用 /bin/zsh -lc 构建,下载的Payload被写入 /tmp/runner,同时验证用的 HTTP 头信息被保存到 /tmp/runner.headers

值得注意的是,用于获取Payload的 curl 命令与早期变种存在明显差异。它不再使用常见的 -fsSL 组合,而是拆分为 -fL 和 -sS,并新增了如 --noproxy 等选项。这些变化,加上对动态变量的使用,表明其在Payload获取和校验方式上进行了刻意调整,可能是为了提升可靠性或规避检测。如图:

在执行Payload前,函数会通过 removeQuarantine(at:) 移除 com.apple.quarantine 属性,并通过 _NSFilePosixPermissions 将文件权限设置为 750,确保其可执行。如图:

随后会进行基础校验: 首先调用 /usr/bin/file --mime-type -b 检查 /tmp/runner 是否为脚本,并确认返回值为 text/x-shellscript; 接着运行 /usr/bin/file -b,验证输出中是否包含预期字符串(例如 Paul Falstad’s zsh script text executable, ASCII text),以确认其为 zsh 脚本; 随后通过 spctl -a -v 执行一次 Gatekeeper 检查,确保下载的文件能够通过 Apple 的安全策略。

最后,在执行完成后,/tmp/runner 会被从磁盘中删除,当前时间戳会被写回 ~/Library/Application Support/UserSyncWorker/last_update,以强制下一次运行前的最小时间间隔。

总体而言,runInstaller() 实现了一个分层、有状态且具备规避特性的投递器流程。它结合了环境检查、节流逻辑和网络请求,并通过条件更新、Gatekeeper 规避以及轻量级校验,全部封装在一个原生 Swift 可执行文件中,以实现隐蔽性和持久性。

总结

该恶意软件以一个基于 Swift、经过代码签名并完成公证的应用程序出现,能够静默地下载并执行第二阶段Payload。这种分发方式的转变反映了 macOS 恶意软件生态中的一个更广泛趋势——攻击者越来越倾向于将恶意软件隐藏在已签名、已公证的可执行文件中,使其更像合法应用。借助这些技术,对手能够显著降低被早期检测发现的概率。

#

IOC

#

#

文件名: zk-call-messenger-installer-3.9.2-lts.dmg

SHA256: be961ec5b9f4cc501ed5d5b8974b730dabcdf7e279ed4a8c037c67b5b935d51a

文件名: co.runtime.helper.b3f9a2.dmg

SHA256: 4ae745bc0e4631f676b3d0a05d5c74e37bdfc8da3076208b24e73e5bbea9178f

文件名: Installer/runtimectl

SHA256:ecfaa20f25e11878686249c7094706bc3dcd2dc0ace0f2932a39d1bfdac85863

SHA256:7cfe0b119e616ac81ddb1767a5c7f40bec67d91fdd66e53490c0225789537073

SHA256:06c74829d8eee3c47e17d01c41361d314f12277d899cc9dfa789fe767c03693e

SHA256:c4d3e5cdb264eded917cd61b8131c40715c0ee3f4d2c94c84d60fa295ca4ed97

SHA256:9990457feac0cd85f450e60c268ddf5789ed4ac81022b0d7c3021d7208ebccd3

SHA256:9d43e059111460c4f81351a062fb7eb7dbfd34988a06d756c7206f330c06cb42

文件名: runner

SHA256: 2e671bd9673d174de9b4ad8fd03049859e1d2d17ac9bc49ecc5d736505002937

TeamID: GNJLS3UYZ4

URL: https[:]//gatemaden.space/curl/985683bd660c0c47c6be513a2d1f0a554d52d241714bb17fb18ab0d0f8cc2dc6

C2: focusgroovy.com

#

(全文完)


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:二进制空间安全 suntiger《Apple系统快防不住了,新型间谍程序无需用户交互突破防护》

一次弱口令到漏洞百出 网络安全文章

一次弱口令到漏洞百出

文章总结: 本文记录了一次渗透测试,通过弱口令进入后台导致1700余条敏感信息泄露。测试中发现SQL排序注入,利用时间盲注绕过WAF;同时利用接口返回加盐MD5
评论:0   参与:  0