跳转到主要内容
macOS 采集器(Hilt EDR 应用及其 ESensor Endpoint Security 扩展)会为每一次与安全相关的内核动作发出一个事件。这些事件通过 HTTPS 发送到 Hilt 的 edr-collector,经由 MSK Kafka 和富化服务(ENRICH_PLATFORM=macos)路由,最终落入一张专门构建的 ClickHouse 表:endpoint_events。 endpoint_events 是一张宽表,为 macOS 原生设计,以 event_class 和 event_type 分型。每个分类专属的列只会在使用它们的事件上被填充,其余列留空。此表结构中没有 Linux 的 cgroup、容器、pod 或 Kubernetes 之类的杂项——这些概念不适用于端点。 此表最本质的特性——也是 macOS 的差异化所在——在于每一行都把代码签名信任与应用归属作为一等列携带。 一次文件读取、一条网络流以及一次进程 exec,到达时都已盖好”是谁签署了这个二进制文件、我们是否信任该签名、以及哪个面向用户的应用对此负责”。在 Linux 上,内核事件层面根本不存在这些信息。而在 macOS 上,它们随每一行一同传递,从而把诸如*“哪个未签名的应用读取了 ~/.ssh?“*这样的问题变成一条 WHERE 子句。

表结构概览

每一行都是一次观测到的内核事件,包含四层列: 本文将依次介绍每一层,然后列出 event_type 的取值。

公共头部(每个事件)

头部标识何时、何地与何人——无论事件分类如何,每一行都带有相同的行为主体元数据。
wall_time_ns 是来自 Endpoint Security 消息的权威事件时间戳。event_time 是派生的 DateTime64 列,你在 ClickHouse 中用它进行过滤和分区。

代码签名标识(每个事件)——macOS 差异化

在 macOS 上,内核知道每个运行中二进制文件的签名标识,Apple 的 Endpoint Security 框架会在每条消息中把它交给 ESensor。采集器将该标识提升为专用列,因此信任在每个事件上都可查询——而不仅仅是在 exec 上。

code_signature 裁定

code_signature 将 Apple 的签名评估归并为四个信任层级之一: 正是这一列让 macOS 遥测与众不同。因为裁定存在于每一行上——文件、网络与进程皆然——你可以对任何动作提出信任层面的问题:
在 Linux 采集器上无法表达这条查询:不存在按事件划分的签名信任概念。

应用归属(每个事件)——macOS 差异化

现代 macOS 应用并非单个进程。仅 Google Chrome 就会派生出数十个 Google Chrome Helper、Google Chrome Helper (GPU) 和 Google Chrome Helper (Renderer) 进程。只看原始的 comm 值,信号会散落在对分析师毫无意义的辅助进程之中。 macOS 采集器利用 Apple Endpoint Security 的”负责进程”概念,把每个事件归拢回其所属应用,从而按照人类的思维方式对活动进行分组。 这意味着单个 WHERE application_id = 'com.google.Chrome' 就能返回 Chrome 的完整足迹——每一次辅助进程 exec、它触及的每个文件、它打开的每条流——无需枚举辅助进程名。session_id 进一步将其收窄到应用的某一次具体启动,而 responsible_pid 让你可以从任意事件转向该负责进程。
responsible_pid 和 application_id 是仪表盘的 Investigate、Files、Networks 和 Users 视图将散落的辅助进程活动归属到用户实际运行的应用的方式。折叠在富化时完成,因此在每一次查询中都保持一致。

单事件载荷

除了公共头部和两层始终存在的标识列外,每个事件分类还携带各自的载荷列。较少见的长尾属性会落入 attrs 映射。

进程载荷——exec、fork、signal

exec 是进程模型的主干:它在同一行上携带 argv、签名标识、team id 和 cdhash。signal 事件记录 kill 尝试——attrs['target_pid'] 和 attrs['signum'] 揭示谁试图终止谁,从而暴露攻击者的击杀链,以及篡改采集器自身的尝试。

文件载荷——file_open、file_unlink、file_rename、file_chmod、xattr_set、xattr_delete

file_open 主导事件量(约 95%+),这正是 ESensor 在任何数据离开主机之前就施加激进的用户态过滤的原因——参见 Agent 过滤。 xattr_* 事件为 macOS 特有且信号价值高:它们捕获对 com.apple.quarantine 的更改,这是 Gatekeeper 用来标记下载文件的扩展属性。对隔离属性的 xattr_delete 是一种经典的 Gatekeeper 绕过——剥除”从互联网下载”标志,使操作系统在不弹窗提示的情况下运行文件。

网络载荷——net_flow

网络流来自 lsof/socket 轮询器与 NetFilter NetworkExtension 内容过滤系统扩展的组合,后者将每条流的审计令牌解析回负责应用。得益于 NetFilter,一条 net_flow 行已经知道哪个应用打开了该连接——bundle_id 无需单独的进程到 socket 关联步骤即可回答”是什么发起了这个连接”。
net_flow 仅记录连接元数据——目标、端口、字节计数和负责应用。它不捕获数据包载荷,且默认不解析 DNS 名称。

持久化载荷——btm_add

btm_add 事件来自 macOS 13+ 的 Background Task Management (BTM),每当注册 launch agent、launch daemon 或 login item 时触发——即当某物将自身安装为跨重启持久化时。这是 macOS 上信号价值最高的单个持久化事件:绝大多数 macOS 恶意软件(以及合法的自启动软件)正是借此在重启后存活。

设备载荷——mount

mount 事件在文件系统被挂载时触发——最值得关注的是可移动介质(USB 驱动器)和磁盘映像(DMG),二者都是数据外泄和软件投递的常见途径。

事件类型

采集器订阅 12 个 Apple Endpoint Security 事件外加一个网络源,并向 endpoint_events 发出以下 event_type 取值:
xattr_delete 和 mount 本质上罕见(隔离移除以及 USB/DMG 挂载)——它们已被订阅并发出,但一台安静的主机在短时间窗口内可能一个都不显示。signal、file_unlink 和 file_rename 作为 AUTH 事件订阅,以便 ESensor 还能拒绝对自身的篡改,但它们仍会发出等价的遥测行。

标识与归属如何被填充

标识层与归属层并非尽力而为的元数据——它们以很高的填充率被填充,且是大多数查询所依赖的透视列。来自实时数据的已验证填充率: 关于遥测如何从 ESensor 传输到 ClickHouse 的更多内容,参见端到端数据流。关于原始事件量在离开主机之前如何被削减,参见 Agent 过滤。

采集器不会捕获的内容

与 Linux 采集器的设计理念一致,macOS 采集器仅在元数据层面观测活动。它不是内容检查工具。它不会捕获:
  • 文件内容——仅捕获路径、操作类型、标志,以及(对于重命名)目标路径
  • 数据包载荷——仅捕获流的目标、端口、字节计数和负责应用
  • DNS 查询内容——net_flow 默认不解析域名
  • 键盘输入或屏幕内容
  • 内存区域或进程内存
  • 环境变量
  • 凭据或任何用户数据——超出 ps、lsof 或 codesign 等标准工具本就会暴露的范围之外
换言之,ESensor 报告的是一个二进制文件打开了某文件、由谁签署、代表哪个应用这一事实——而绝不报告文件中有什么。所有事件发送都仅通过出站 HTTPS 发往配置的接入端点;采集器不打开任何入站 socket,也不发起任何回连(phone-home)连接。
最后修改于 2026年10月8日