EDR的“自毁”开关

admin 2026-06-18 06:21:39 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文揭示TrendMicroDeepSecurityAgent存在本地低权限安全缺陷,攻击者可通过高频文件系统操作触发内核监控模块的自我卸载机制,利用防护空窗期绕过安全检测。文章详细分析了技术原理、PoC构造及厂商披露过程,指出了该防御机制失效的严重性及应对思考。 综合评分: 88 文章分类: 漏洞分析,红队,软文广告,渗透测试,终端安全


不是 0day,不是提权,不是远程攻击。只是一个本地普通用户,对着文件系统狂写、狂删、狂重命名,终端安全软件的监控模块就自己卸了。

参考原文:Trend Micro Deep Security Agent Research by 0xMatheuZ


你家的防盗门,被敲门敲到自动打开

近日,安全研究员 0xMatheuZ 公开发布了一份针对 Trend Micro Deep Security Agent(趋势科技深度安全代理)Linux 版本的安全研究报告。

报告揭示了一个令人意外的安全缺陷:在特定条件下,这款企业级端点安全产品会主动卸载自身的关键内核监控模块,从而在攻击者可控的情况下制造出可被利用的防护空窗期。

想象一下这个场景:

你家装了防盗门,门上有传感器,有人在撬门、砸窗、乱晃,传感器都会报警。但有一天你发现,只要用一个机械臂以极高频率反复敲门——不是撬,就是正常的敲——防盗门的传感器就过热重启了。在它重启的那几秒里,你干什么它都看不见。

这不是小说。这就是安全研究员 0xMatheuZ 对 Trend Micro Deep Security Agent 做的一次安全研究。

他用一个本地普通用户权限的进程,生成了大量文件写入、重命名、符号链接、进程创建和退出事件。结果,Trend Micro 的内核监控模块自己把自己卸载了。

没有 root 权限。没有内核漏洞。没有崩溃。

是安全产品自己的恢复机制,主动执行了 rmmod


模块是怎么自己消失的

先理解一下 Trend Micro 在 Linux 上的监控架构。它有两个关键内核模块:

tmhook:通用系统调用钩子层。用 Linux livepatch 机制挂在系统调用路径上。

bmhook:行为监控模块。依赖 tmhook,负责真正的事件分析、队列、扫描、上报。

简单说:tmhook 是”耳朵”,bmhook 是”大脑”。所有用户态的系统调用,先经过 tmhook 这个耳廓,再传到 bmhook 这个听觉中枢。

关系的静态证据在模块符号里很清楚:

bmhook_add_hook()
  -> tmhook_register_hook()
  -> syscall dispatch path

然后研究者做了什么事呢?他写了一个 PoC,在 /dev/shm 下疯狂制造文件事件:创建、写入、截断、重命名、符号链接、fork 子进程再退出。64 个 worker 同时跑,每个管 512 个文件。

一开始只是正常的资源压力——dmesg 里出现 fork 压力、perf 降采样率。然后,真正有趣的东西出现了:

livepatch: 'tmhook': starting unpatching transition
livepatch: signaling remaining tasks
livepatch: 'tmhook': unpatching complete
tmhook: tmhook 1.2.2129 unloaded

模块没了。


深入 PoC:这个”敲门器”到底长什么样

此节为技术深潜,面向想自己复现或理解攻击面的读者。如果你只关心安全影响,可以直接跳到下一节。

作者没有公开完整的 PoC 源码,但给出了足够让有经验的 Linux 研究人员自己写出来的细节。这种做法本身就值得认可——提供可验证的技术细节,却不给脚本小子一键武器化的工具。

命令行参数

./exploit /dev/shm/trend-poc 6006451244

| 参数 | 值 | 含义 | | — | — | — | | 工作目录 | /dev/shm/trend-poc | tmpfs 内存文件系统,避免磁盘 I/O 瓶颈,纯粹压测内核事件路径 | | 运行时长 | 600 | 600 秒(10 分钟),足够触发阈值 | | worker 线程 | 64 | 文件事件工作线程 | | 每 worker 文件数 | 512 | 64 × 512 = 32768 个文件被反复操作 | | fork 线程 | 4 | 专门制造进程创建/退出事件 | | symlink 线程 | 4 | 专门制造符号链接操作 |

它到底干了哪几件事

PoC 同时执行七类操作,每一类都精准命中行为监控的关注点:

| 操作 | 行为 | 为何命中监控 | | — | — | — | | write + truncate | 写入文件内容后截断 | 文件内容变化 | | close + reopen | 反复关闭和重新打开 | 文件句柄生命周期 | | rename | 重命名文件 | 文件元数据变化 | | symlink + unlink | 创建符号链接后立即删除 | 文件系统拓扑变化 | | fork + exit | 创建子进程后立即退出 | 进程生命周期 | | open + read + close | 打开、读取、关闭 | 文件访问事件 | | 批量创建 | 每个 worker 处理 512 个文件 | 增加总事件密度 |

没有什么”高级漏洞利用技术”。就是大量高频覆盖多个监控路径的普通操作。

核心代码骨架

模块监控线程——每秒读一次 /proc/modules,检测 bmhook/tmhook 是否消失:

void*monitor_thread() {
    while (running) {
        // 读 /proc/modules,检查 bmhook 和 tmhook
        FILE*fp=fopen("/proc/modules", "r");
        while (fgets(line, sizeof(line), fp)) {
            if (strstr(line, "bmhook")) bmhook_ok=1;
            if (strstr(line, "tmhook")) tmhook_ok=1;
        }
        fclose(fp);

        if (!bmhook_ok||!tmhook_ok) {
            // 检测到盲区!此时可以执行本来会被拦截的操作
            perform_action_during_window();
        }
        sleep(1);
    }
}

文件 worker 线程——对每个文件反复执行 create/write/truncate/rename/read/unlink:

void*file_worker(void*arg) {
    charpath[256];
&nbsp; &nbsp;&nbsp;for&nbsp;(inti=0;&nbsp;i<512;&nbsp;i++) {
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;sprintf(path,&nbsp;"%s/file_%d_%d",&nbsp;base_dir,&nbsp;worker_id,&nbsp;i);

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;intfd=open(path,&nbsp;O_CREAT|O_WRONLY,&nbsp;0644); &nbsp;// 创建
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;write(fd,&nbsp;data,&nbsp;4096); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// 写入
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;close(fd); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// 关闭

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;truncate(path,&nbsp;1024); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// 截断

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;charnewpath[256];
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;sprintf(newpath,&nbsp;"%s/file_%d_%d.renamed", ...);
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;rename(path,&nbsp;newpath); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// 重命名

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;fd=open(newpath,&nbsp;O_RDONLY); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// 重新打开
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;read(fd,&nbsp;buf,&nbsp;1024); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// 读取
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;close(fd);

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;unlink(newpath); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// 删除
&nbsp; &nbsp; }
}

fork 和 symlink worker 更简单,就是死循环里 fork() + exit() 和 symlink() + unlink()

PoC 的输出长这样

[*] dir=/dev/shm/trend-poc seconds=600 workers=64 files/worker=512 forkers=4 symlinkers=4
[*] monitoring /proc/modules for bmhook/tmhook unload
[ &nbsp;75s] events= &nbsp; &nbsp; 5479173 bmhook=1 tmhook=1 window_seen=0
[!] hook reload window detected: bmhook=0 tmhook=1
[+] benign marker actions completed during window
[ 241s] events= &nbsp; &nbsp;64584240 bmhook=1 tmhook=1 window_seen=1

几个关键数字:

  • 75 秒时触发了第一次盲区检测
  • 547 万个事件后 bmhook 消失
  • 从 75 秒到 241 秒,系统处理了约 5900 万个事件
  • bmhook=0 tmhook=1 说明行为监控模块先于底层钩子层消失——”大脑”已经瞎了,”耳朵”还在

关键复现条件一览

| 条件 | 说明 | | — | — | | 工作目录在 tmpfs | /dev/shm,纯内存,不碰磁盘 I/O | | 持续时间够长 | 600 秒,给 loop prevention 阈值足够的累积时间 | | 并发度够高 | 72 个线程同时制造不同类型的事件 | | 覆盖多个监控路径 | 不只是写文件——fork、symlink、rename 一起上 | | 持续监控模块状态 | 每秒检查 /proc/modules,窗口一开就行动 |

对熟悉 Linux 系统编程的人,这些信息完全足够写出可用的 PoC。这不是脚本小子的工具,而是一份干净的安全研究复现指南。


不是崩溃,是自己卸的

研究员用 bpftrace 抓了 execve 和 module_free 事件,找到了真正的凶手:

EXEC rmmod pid=135640 comm=ds_am.init file=/usr/sbin/rmmod cmdline=rmmod bmhook
FREE module=bmhook by rmmod pid=135640 comm=rmmod

EXEC rmmod pid=136069 comm=ds_am.init file=/usr/sbin/rmmod cmdline=rmmod tmhook
FREE module=tmhook by rmmod pid=136069 comm=rmmod

是 Trend Micro 自己的进程 ds_am.init 调用了 rmmod

不是内核崩溃。不是 PoC 调了 rmmod。不是你想象的任何”外部攻击”。

安全产品自己的行为监控模块被自己的恢复逻辑主动卸载了。从二进制逆向看,触发链很可能是:

事件风暴 → 行为队列压力 → loop prevention 阈值触发
&nbsp; → ds_am.init 重启行为监控
&nbsp; → rmmod bmhook
&nbsp; → rmmod tmhook
&nbsp; → 重新 insmod + livepatch

模块符号中有 enable_loop_preventionbmhook_throttle_checkTELEMETRY_EVENT_DROPPED_COUNT 等关键词,模块日志中有 startBM enableBLP=1 thresholdBLP=100。整个恢复路径在二进制和日志里都有迹可循。


卸了就卸了?问题在”窗口”里

关键不是模块会卸,而是:模块卸了之后会发生什么。

研究者在正常状态下做了一次测试:Trend Micro 默认会拦截某个已知的恶意测试文件写入磁盘,文件不会留在目标目录。

然后他在模块 reload 窗口期间做了同样的操作。

结果:文件落盘了。

-rwxrwxr-x 1 ubuntu ubuntu 18K Jun &nbsp;3 15:41 test-artifact
Bypass worked

时间窗口多长?一个观测周期里:

  • livepatch 完整过渡:约 19.6 秒
  • tmhook 真正缺失:约 1.3 秒
  • bmhook 先消失,此时 tmhook 可能还在,但行为监控已经瞎了

1.3 秒够干什么?

够写一个文件。够改权限。够启动一个短进程。够重命名、移动、删掉痕迹。

而且这个过程可以重复触发。PoC 跑了 600 秒,出现了多次 reload 循环。每次窗口只有一两秒,但攻击者可以等,可以反复触发,每次做一个小动作。

就算模块回来了,窗口里发生的事它已经不知道了。


为什么这算漏洞而不是”特性”

你可能想:这不就是产品自己的保护机制吗?压力太大了重启一下很正常吧?

对,恢复机制本身没问题。问题是两个叠加条件:

  1. 触发门槛太低:不需要 root,不需要漏洞,不需要特殊权限。一个普通用户写了个循环脚本就够了。
  2. 被恢复的恰好是保护层本身:loop prevention 为了”防止行为监控死循环”而卸载了行为监控模块——这就像火灾报警器因为太吵而自己把电源拔了。

安全边界被击穿的点不是系统权限,而是保护的连续性

CWE 分类的话:

  • CWE-693:保护机制失效
  • CWE-400:不受控的资源消耗

研究员给的严重程度是 High——因为它是本地的、临时的,但直接影响了安全控制,而且在实际测试中确认了 bypass。

不是 Critical 的原因:不是远程、没提权、没内核代码执行、不是永久卸载。


时间线:报告 4 个月,石沉大海

这个漏洞的披露过程本身也是一个值得关注的点:

  • 2026-02-06:初次报告给 Trend Micro
  • 2026-02-26:厂商确认收到,PoC 和复现视频交付
  • 2026-03-18:厂商怀疑是 ds_am 的 OOM 机制触发,要求诊断包
  • 2026-03-18:诊断包交付(PoC 运行时一份,模块卸载后一份)
  • 2026-03-20:厂商确认诊断包已转交后端团队
  • 2026-04-09:回复”后端团队仍在处理日志”
  • 2026-05-04:第四次跟进
  • 2026-05-31:第五次跟进
  • 2026-06-03:自行确认 bypass 成立,决定公开

从初报到公开,近 4 个月。没有 CVE 编号,没有修复时间线,没有最终 triage 结论。

这本身也是一个值得安全行业思考的问题:当一个漏洞被反复确认但厂商迟迟不回,研究者有多大的耐心是”足够”的?


最后说一句

这个研究最打动我的,不是技术多复杂——恰恰相反,触发条件简单得令人不安。一个低权限用户、一个循环脚本、一个 /dev/shm 目录,就能让一家头部安全厂商的端点防护出现可观测的保护盲区。

安全产品是防线,不是铜墙铁壁。它们自己也是软件,有 bug,有阈值,有恢复路径。把它们当作不可突破的”保险箱”是危险的。

这篇文章的价值也在于研究者的思维过程值得学习——从观察到假设,从假设到验证,从验证到归因,从归因到影响评估。这是一条清晰的安全研究链路,适合每一个做安全或做系统的人参考。

💎 服务

本文演示的攻击手法在真实环境中屡试不爽。如果你需要在其他EDR环境中测试这种技术手法,或者需要专业的红队工具与评估服务,我们提供:

✅ 各大 EDR 端点授权 Token 包括但不限于 SentinelOne、Trend Micro、CrowdStrike、等主流平台的合法测试授权,助你搭建真实的攻防演练环境。

CrowdStrike800一个端点,其他300一个。

培训课程:

第一期

第二期

第三期

第四期

第五期

第六期


免责声明:

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

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

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

本文转载自:老鑫安全 老鑫安全 老鑫安全《EDR 的“自毁”开关》

评论:0   参与:  0