macOS采用三层防护机制保障系统安全:Gatekeeper检查恶意软件下载,XProtect阻止运行恶意软件,XProtect Remediator修复已执行的恶意软件。它们共同构成 macOS 的纵深防御体系。
- 检查恶意软件下载和运行:Gatekeeper;
- 阻止恶意软件在消费者的系统上运行:XProtect;
- 缓解或者修复已经执行的恶意软件:XProtect Remediator
TCC
TCC(Transparency, Consent, and Control, 透明性、同意与控制)是苹果自 macOS 10.14(Mojave)引入并持续强化的一项隐私保护框架。它的核心目标是:限制应用程序对敏感用户数据和系统资源的访问,除非用户明确授权。
当应用首次使用特定服务(多数与隐私相关,例如摄像头、麦克风、磁盘访问等),会弹框提示用户,是否同意授权。Android 6.0 新增的动态权限其实就是类似于苹果的 TCC。例如,macOS 三方截屏软件向直接截屏时,会提示用户,是否允许。

除了动态弹框提示 ,设置 >隐私与安全性 中,我们可以看到有哪些应用使用了哪些服务或者说权限,并且可以修改。相比之下,移动操作系统,如鸿蒙和安卓可以在隐私和安全中显示更加详细的信息,比如某个应用过去访问过某个隐私服务多少次。
TCC 配置信息存储在 TCC.db 数据库中,可以通过 sqlite3 命令查看内容,例如
shell
sqlite3 /Library/Application\ Support/com.apple.TCC/TCC.db
select client, auth_reason, auth_value, service FROM access;
可以查看 TCC 最关键的 access 表,当然实际条目比下面列出的更多

其实从字段名称我们大概就能猜测出这个访问表的含义。
client:发出请求的客户端,标识请求访问权限的应用程序。
auth_reason:这是记录请求方式。"为什么"出现当前授权状态的原因。社区和逆向分析确认的常见值如下:
c
typedef NS_ENUM(NSInteger, TCCAuthReason) {
kTCCAuthReasonUnspecified = 0, // 未指定/未知
kTCCAuthReasonUserAllowed = 1, // 用户在弹窗中点击"允许"
kTCCAuthReasonUserDenied = 2, // 用户在弹窗中点击"不允许"
kTCCAuthReasonSystemDefault = 3, // 系统默认策略(如全新安装时的默认拒绝)
kTCCAuthReasonMDMAuthorized = 4, // 由 MDM(移动设备管理)策略授权
kTCCAuthReasonProfileAuthorized = 5, // 通过配置描述文件(.mobileconfig)授权
kTCCAuthReasonReset = 6, // 权限被 `tccutil reset` 重置
kTCCAuthReasonKernelExtension = 7, // 内核扩展相关(较旧系统)
kTCCAuthReasonTCCDatabaseCorrupt = 8, // 数据库损坏(罕见)
kTCCAuthReasonManagedByParent = 9, // 家长控制(Screen Time)
kTCCAuthReasonApprovedByAdmin = 10, // 管理员批准(如通过 MDM 或本地策略)
// macOS 13+ 可能新增其他值(如与 App Attest 相关)
};
auth_value:用户提供了什么回应,或者相应的策略如何回答这个请求的。用更简单的话来说,就是有没有批准该请求。
c
typedef NS_ENUM(NSInteger, TCCAuthValue) {
kTCCAuthValueDenied = 0, // 显式拒绝
kTCCAuthValueAllowed = 1, // 显式允许
kTCCAuthValueNotDetermined = 2, // 从未提示(默认状态)
kTCCAuthValueRestricted = 3, // 被家长控制、MDM 或系统策略限制
// macOS 12+ 可能新增(如 kTCCAuthValueLimited)
};
service:请求的服务,即权限是什么,常见服务如下
c
// 实际为 CFString / NSString 常量
extern const CFStringRef kTCCServiceCamera;
extern const CFStringRef kTCCServiceMicrophone;
extern const CFStringRef kTCCServiceAddressBook;
extern const CFStringRef kTCCServiceCalendar;
extern const CFStringRef kTCCServiceReminders;
extern const CFStringRef kTCCServicePhotos;
extern const CFStringRef kTCCServiceMediaLibrary;
extern const CFStringRef kTCCServiceMotion;
extern const CFStringRef kTCCServiceLocation;
extern const CFStringRef kTCCServiceAccessibility;
extern const CFStringRef kTCCServiceScreenCapture;
extern const CFStringRef kTCCServiceDeveloperTool;
extern const CFStringRef kTCCServiceSystemPolicyAllFiles;
extern const CFStringRef kTCCServiceSystemPolicySysAdminFiles;
extern const CFStringRef kTCCServiceSystemPolicyDesktopFolder;
extern const CFStringRef kTCCServiceSystemPolicyDownloadsFolder;
extern const CFStringRef kTCCServiceSystemPolicyNetworkVolumes;
extern const CFStringRef kTCCServiceSystemPolicyRemovableVolumes;
extern const CFStringRef kTCCServiceSystemPolicyDocumentsFolder;
extern const CFStringRef kTCCServicePostEvent; // 发送键盘事件(如自动化)
// ... 以及更多(如 kTCCServiceListenEvent, kTCCServiceSafariBookmarks 等)
直接读写 TCC.db 在 macOS 10.15+ 受 System Extension、Privacy Sandbox 和 SIP 严格保护,即使 root 也无法访问(除非在 Recovery OS 中)。
那么如何查看 TCC 状态?可以通过日志,MDM 应用,或者开发者 tccutil
shell
log show --predicate 'subsystem == "com.apple.TCC"' --info --last 1h
File Quarantine
macOS 的 File Quarantine (文件隔离)是一种安全机制 ,用于标记从互联网下载的文件(或其他潜在不信任来源),防止其在未经用户明确同意的情况下自动运行或执行,从而降低恶意软件(如木马、勒索软件)的风险。
这项功能从 macOS 10.5 Leopard(2007 年)引入,并随着系统演进不断加强,是 Apple "纵深防御"(Defense in Depth)安全策略的重要组成部分。
什么时候标记 Quarantine
当一个文件通过以下方式"来自外部"时,系统会自动为其添加一个 扩展属性(extended attribute):
- 从网页浏览器下载(Safari、Chrome、Firefox 等)
- 通过邮件附件接收(Mail.app)
- 通过即时通讯工具接收(如 Messages、Slack、微信)
- 通过
curl、wget等命令行工具从网络下载(如果调用了特定 API)
系统会记录:
- 文件来源 URL
- 下载时间
- 下载应用的 Bundle ID
这些信息以 com.apple.quarantine 扩展属性的形式存储在文件上。
如何查看 Quarantine
xattr 命令支持查看文件扩展属性
shell
xattr -l vmware-fusion-13-5-2.dmg
输出结果
字段含义
| 字段值 | 含义 |
|---|---|
0081 |
隔离标志位 (flags) • 00 = 普通下载 • 01 = 来自邮件 • 80 = 用户已确认(已解除隔离) • 0081 = 0x81 |
6725dd98 |
Unix 时间戳(十六进制) ,表示下载时间(可转为十进制再用 date -r 查看) |
Chrome |
下载应用的 Bundle ID 或名称 (如 com.apple.Safari 可能简写为 Safari) |
A4F5... |
唯一 UUID,用于追踪该下载事件(可选,较新系统才有) |
当你首次打开一个被隔离的可执行文件(如 .app, .pkg, 脚本等),会看到类似提示:
"xxx.app" 是从互联网下载的。是否确定要打开?
Apple 无法验证此应用是否包含恶意软件。
这是 Gatekeeper 和 File Quarantine 联合工作的结果:Quarantine 负责"标记来源"。Gatekeeper 负责"验证签名和公证"(notarization)。
下面的命令还可以查看特定目录下所有带有 Quarantine 属性的文件
shell
find ~/Downloads -type f -exec xattr -l {} \; | grep -A1 "com.apple.quarantine"
Gatekeeper
macOS 的 Gatekeeper (守门人)是 Apple 内置于 macOS 中的一项核心安全机制 ,用于控制哪些应用程序可以在 Mac 上运行,防止用户意外安装或运行来自不可信来源的恶意软件(如木马、勒索软件、间谍软件等)。
它首次引入于 macOS 10.8 Mountain Lion(2012 年),并随着系统演进不断强化,如今已成为 macOS "纵深防御"(Defense in Depth)安全体系中不可或缺的一环。
请注意:Gatekeeper 只会检查带有 Quarantine 扩展属性的可执行文件。如果你使用 WPS 查看一个从网络下载的恶意 PDF,不会触发 Gatekeeper 的检查。
Gatekeeper 实际上是命令 spctl 的前端。例如,下面的命令可以查看一个文件是否经过签名 和公正。
shell
spctl --verbose=4 --assess --type execute qbittorrent-5.0.4.dmg
qbittorrent-5.0.4.dmg: rejected
检查签名
macOS 内置了一些签名组织。黑名单,如 file /Library/Apple/System/Library/CoreServices/XProtect.bundle/Contents/Resources/gk.db;白名单,如 SystemPolicy,这些文件都是动态变化的。
shell
codesign --display --verbose=4 qbittorrent-5.0.4.dmg
检查公正
macOS 的 Notarization (公证)是 Apple 为提升系统安全性而强制推行的一项云端验证机制 :所有从互联网分发的 macOS 软件在用户安装或运行前,必须先提交给 Apple 服务器进行自动化恶意软件扫描,获得"公证票据"(notarization ticket)后,才能被系统默认信任。
从 spctl 命令输出的 rejected 标识此应用没有经过 Notarization。
查看 Gatekeeper 决策日志
shell
log show --predicate 'subsystem == "com.apple.syspolicy"'
XProtect
macOS 的 XProtect 是 Apple 内置于 macOS 中的一项基于签名的反恶意软件技术 (anti-malware system),用于自动检测和阻止已知的恶意软件(如病毒、木马、勒索软件、间谍软件等)在 Mac 上运行。
它从 macOS 10.5 Leopard (2007 年)开始引入,是 macOS 最早的内置安全机制之一,属于 系统级、透明运行、无需用户干预 的防护层。
🔒 简单说:XProtect 是 macOS 的"内置杀毒引擎",但只针对 Apple 已知的恶意软件,且完全由 Apple 远程更新。
XProtect 恶意软件的定义以 plist 或者 yara 规则形式存储在下面的系统路径中
shell
/Library/Apple/System/Library/CoreServices/XProtect.bundle/Contents/Resources
XProtect.meta.plist
这是最原始的 XProtect 检测规则,包含一些过时的软件,如 Java 和 Flash。如今,此文件最主要的目的是防止恶意 Safari 扩展程序。通过 bundle identifier 和 developer identifier 进行识别。

XProtect.plist
此文件会有一些更复杂的匹配模式,用于查找恶意软件,但是仍然是常见的 id,匹配对应的恶意软件。例如,下面就是筛选 LSItemContentType 为 com.apple.bundle 类型的文件。

LegacyEntitlementAllowlist.plist
LegacyEntitlementAllowlist.plist 是 macOS 系统中的一个私有(internal)属性列表(plist)文件 ,主要用于在系统升级或安全策略收紧过程中,向后兼容(backwards compatibility)某些旧版应用或系统组件 ,允许它们在没有显式声明所需 Entitlements(权限/权利) 的情况下继续运行。
XProtect.yara
yara 是现代杀软最常见的匹配恶意软件所使用的格式。允许基于文本或者二进制模式,匹配恶意软件家族。不再仅仅是根据恶意软件的哈希值或者 id,而是寻找恶意软件的共同特征。

XProtect.yara 文件中的所有 YARA 规则都经过混淆处理,这使得用户难以了解每条规则旨在阻止哪些恶意软件家族,尤其是在没有主动研究 macOS 恶意软件的情况下。目前已有超过两百条规则,并且苹果公司还在不断更新此文件,持续扩展规则集。
查看 XProtect 日志
shell
log show -info -backtrace -debug -loss -signpost -predicate 'subsystem == "com.apple.xprotect"'
如何绕过 XProtect?
恶意样本如何获得?SentineOne 的博客 How to Reverse Malware on macOS Without Getting Infected | Part 1 为我们提供了一些恶意样本的获取途径
病毒样本 KeRanger:d1ac55a4e610380f0ab239fcc1c5f5a42722e8ee1554cba8074bbae4a5f6dbe1
- 2016 年通过 Transmission 官网被黑,用户下载的安装包被植入 KeRanger。
- 它会加密用户文件(如文档、图片),并索要比特币赎金。
- 使用 AES + RSA 加密,且会等待 3 天后才启动加密,以逃避沙箱检测。
- Apple 后来通过撤销其代码签名证书、更新 XProtect(macOS 内置恶意软件防护)来清除它

XProtect 对应的 yara 规则
yara
rule KeRangerA
{
meta:
description = "OSX.KeRanger.A"
uuid = "6547EF6D-4289-41EC-8964-444D337BB848"
strings:
$a = {48 8D BD D0 EF FF FF BE 00 00 00 00 BA 00 04 00 00 31 C0 49 89 D8 ?? ?? ?? ?? ?? 31 F6 4C 89 E7 ?? ?? ?? ?? ?? 83 F8 FF 74 57 C7 85 C4 EB FF FF 00 00 00 00}
condition:
Macho and $a
}
其实在 plist 文件中,也有一份规则
xml
<dict>
<key>Description</key>
<string>OSX.KeRanger.A</string>
<key>LaunchServices</key>
<dict>
<key>LSItemContentType</key>
<string>com.apple.application-bundle</string>
</dict>
<key>Matches</key>
<array>
<dict>
<key>MatchFile</key>
<dict>
<key>NSURLTypeIdentifierKey</key>
<string>public.unix-executable</string>
</dict>
<key>MatchType</key>
<string>Match</string>
<key>Pattern</key>
<string>488DBDD0EFFFFFBE00000000BA0004000031C04989D8*31F64C89E7*83F8FF7457C785C4EBFFFF00000000</string>
</dict>
</array>
</dict>
当我实际打开这个文件 Transmission-2.90.dmg 时,macOS 的确会弹框报毒,但是实际在此二进制中并没有找到特征序列。

进一步分析发现,此文件是磁盘映像文件,需要打开来看,解压后,发现真实的可执行文件应该是 Transmission.app ,果然,我们找到了对应的病毒特征。

那么相应的绕过方式也是显而易见的,在不破坏病毒可执行的情况下,修改相应的特征。XProtect 有些匹配规则,会限制文件大小,对于这种,更简单,只需要增加文件大小即可。
shell
for i in {1..3000000}; do echo '0' >> mdworker_share; done
在最新的 macOS Sequoia 15.0.1 上发现,恶意软件没有签名,也没有移除 Quarantine,但是系统直接弹框,提示文件是恶意软件,说明现在的检测逻辑并不是 XProtect 最后,Gatekeeper 在前。

XProtect Remediator
macOS 的 XProtect Remediator 是苹果公司内置的一项自动恶意软件响应与修复机制 ,属于 macOS 内建安全体系(包括 XProtect、Gatekeeper、Notarization 等)的重要组成部分。它的主要功能是在系统检测到已知恶意软件时,自动采取措施清除或隔离威胁,以保护用户设备安全。
MRT(Malware Removal Tool)已逐步被 XPR 替代。XProtect 是苹果公司用于识别、阻止和修复 macOS 设备上恶意软件的一系列工具之一。目前,它包含三个主要组件:
- XProtect 会定期使用 YARA 规则扫描磁盘。
- XProtectRemediator (XPR) 由多个扫描器组成,这些扫描器使用 YARA 扫描和其他一些检测方法来查找和清除恶意软件。
- XProtectBehaviorService (XBS) 是最新加入监控与关键资源相关的系统行为的团队的成员。
XPR 部分包含一系列存储在 ( /Library/Apple/System/Library/CoreServices/XProtect.app/Contents/MacOS) 的可执行文件,但每个文件都针对特定的恶意软件家族。与 YARA 规则类似,其中一些文件具有有意义的名称,而另一些则是 Apple 内部使用的:
- XProtectRemediatorAdload
- XProtectRemediatorDubRobber
- XProtectRemediatorKeySteal
- XProtectRemediatorCrapyrator
可以通过 XProCheck 工具查看日志。
关于 XPR 的逆向,参考业界最新公开的会议演讲即可。