首页
课程
问答
CTF
社区
招聘
峰会
发现
排行榜
知识库
工具下载
看雪20年
看雪商城
证书查询
登录
注册
首页
社区
课程
招聘
发现
问答
CTF
排行榜
知识库
工具下载
峰会
看雪商城
证书查询
社区
Android安全
发新帖
4
4
[原创]内存访问蜜罐页的五次进化:从静态陷阱到多维度 PMU 统计检测
发表于: 2026-6-6 04:19
5334
[原创]内存访问蜜罐页的五次进化:从静态陷阱到多维度 PMU 统计检测
blackr0ck
2
2026-6-6 04:19
5334
# 内存访问蜜罐页的五次进化:从静态陷阱到多维度 PMU 统计检测 > ARM64 Android 平台 `process_vm_readv` 跨进程内存读取的检测方案演进 ## 摘要 在 ARM64 Android (Linux 5.4.210) 平台上,本文设计并实验验证了五代蜜罐页(Honey Page)检测方案,探索从简单的静态内存陷阱到融合 ARMv8 PMU 硬件计数器的六维度统计检测的完整进化路径。核心发现:MADV_DONTNEED 轮换 + mincore 自检构成最强检测信号(SNR=∞),每个被攻击页产生精确 1 次 minor fault(1:1 对应);但 root 攻击者通过 `/proc/pid/pagemap` 可规避内存层信号,仅残留 PMU 级别的跨核副作用(DTLB Walk +101%,访问延迟 -33%)。纯驻留页读取在当前消费级 ARM64 SoC 上不可检测。 **关键词**: process_vm_readv, 蜜罐页, MADV_DONTNEED, mincore, ARMv8 PMU, FOLL_REMOTE, pagemap --- ## 1. 引言 `process_vm_readv` 是 Linux 提供的跨进程内存读取系统调用,允许一个进程直接读取另一个进程的地址空间。在内核实现中,它通过 `FOLL_REMOTE` 标志调用 `pin_user_pages_remote`,在目标进程的页表上执行缺页处理。这意味着: - 读取已回收(MADV_DONTNEED)的页面会在目标进程触发 minor page fault - 但 `FOLL_REMOTE` 不设置 Accessed bit,不触发 swap-in,不改变 I/O 计数器 检测方案的核心思路是:**通过 MADV_DONTNEED 主动制造"陷阱页",利用 process_vm_readv 触发的 FOLL_REMOTE 缺页作为检测信号**。本文通过五代迭代,从基础陷阱页开始,逐步引入 PMU 硬件计数器、访问时延测量、VMA 布局等维度,探索检测能力的上限与边界。 ### 权限模型 - **防御者**:非 root shell 用户,独立进程,通过 mincore() 自检、/proc/self/stat 监控 min_flt、perf_event_open 读取 PMU 计数器 - **攻击者**:root 权限,独立进程,通过 `/proc/<pid>/pagemap` 跨进程探测,使用 `process_vm_readv` 跨进程读取 --- ## 2. 测试平台 | 参数 | 值 | |------|-----| | 设备 | Android (ADB connected) | | 架构 | aarch64 (ARM64) | | 内核 | Linux 5.4.210 | | 编译器 | aarch64-linux-android26-clang -O2 | | 页大小 | 4096 bytes | | 测试页数 | 256 (1MB) per generation | | PMU | ARMv8 PMUv3 (L1D refill, DTLB walk, CPU cycles via perf_event) | --- ## 3. 五代实验 ### 3.1 G1 — 静态蜜罐页(基线) **方法**:预先分配页面并写入数据使其驻留。不主动回收(无 MADV_DONTNEED)。攻击者读取后,检查页面状态是否有可观测变化。 **结果**: ``` mincore: attacked=100.0% control=100.0% diff=0.0% latency: attacked=216ns control=332ns diff=116ns min_flt: attacked=1 control=1 ``` **分析**:所有页面在初始化时已被 touch(驻留态),process_vm_readv 读取驻留页不产生 min_flt。mincore 始终 100%。延迟差异来自测量顺序的微小缓存效应(~116ns),不足以作为可靠检测信号。 **结论**:静态页面无法提供检测能力。验证了理论基础——必须主动制造状态差异。 --- ### 3.2 G2 — MADV_DONTNEED 轮换(Fault Trap) **方法**:每轮用 MADV_DONTNEED 回收蜜罐页使其变为非驻留态,然后等待攻击窗口。下一轮用 mincore() 检查页面是否被外部 fault-in 变回驻留态。 **结果**: ``` Control rounds: mincore = 0.0% (DONTNEED 后全部非驻留) Attack rounds: mincore = 100.0% (攻击者读取后全部变驻留) 差异: 100% SNR: ∞ (baseline variance = 0) ``` **分析**:这是最干净的信号。MADV_DONTNEED 将页面回收后,process_vm_readv 触发缺页调入。防御者在下一轮用 mincore 检查时,被攻击页面 100% 驻留,对照页 0% 驻留。无重叠区域,二分类完美。 **结论**:G2 是最有效的检测策略。简单、可靠、纯用户态操作,无需任何特殊内核配置。 --- ### 3.3 G3 — PMU/min_flt 关联(Fault Counting) **方法**:在 G2 基础上,同步监控 `/proc/self/stat` 的 `min_flt` 字段,精确计算被攻击的陷阱页数量。 **结果**: ``` Control rounds: min_flt/rnd = 0 Attack rounds: min_flt/rnd = 64 (exactly!) SNR: 999x ``` **分析**:每个 DONTNEED 蜜罐页被 process_vm_readv 读取时,精确触发一次 minor page fault。64 个蜜罐页 → 64 次 min_flt。一一对应,无一遗漏,无一误报。 **结论**:min_flt 增量与蜜罐页数量呈精确 1:1 对应。不需要 PMU 硬件也能实现计数级的精确度。这是所有 fault 类检测的数学基础。 --- ### 3.4 G4 — 三区访问时延测量 **方法**:设计三个内存区域,通过 `clock_gettime` 测量访问延迟: ``` Zone A [0..128): 热参考区 — 永不 DONTNEED, 始终驻留 测延迟可检测 LLC/TLB 污染 Zone B [128..256): 蜜罐区 — DONTNEED + 攻击者读取 攻击者 fault-in 后变热 (~150ns) Zone C [256..384): 对照冷区 — DONTNEED, 不被攻击 始终为冷页 (~1500ns) ``` **结果**: **信号 1 — 热参考区延迟升高(缓存/TLB 污染)**: ``` Control: Zone A avg=443ns (热页, 无干扰) Attack: Zone A avg=642ns (+199ns, +45%) Round 4 峰值: 1132ns (2.5x 基线!) ``` **信号 2 — 蜜罐区 fault-in 变热**: ``` Round 4: Honey=246ns (0% cold) | Ctl=1433ns (2% cold) ← 攻击者预热 Round 5: Honey=332ns (1% cold) | Ctl=3322ns (3% cold) ← 攻击者预热 ``` **分析**:三区设计捕获了两个独立的检测信号: 1. **热参考区延迟升高**:攻击者扫描产生的缓存/TLB 竞争导致本地访问变慢 2. **蜜罐区延迟降低**:攻击者 fault-in 后页面从冷变热 两个信号互补:信号 1 在攻击者读取任何内存时都可能出现(包括驻留页),信号 2 在攻击者读取 DONTNEED 页时触发。组合使用提高检测鲁棒性。 **结论**:三区时延检测是唯一能间接感知 LLC/TLB 级别副作用的纯用户态方法。Zone A 的 +45% 延迟升高直接印证了"外部扫描 → 缓存污染 → 本地延迟增加"的理论预测。 --- ### 3.5 G5 — Honey VMA(防御纵深) **方法**:将蜜罐区拆分为大量独立的小 VMA(256 个 4KB VMA),而非单个大缓冲区。 **结果**: ``` 256 个 4KB VMA: Attacker scan time: 11.2 ms (43.9 μs/VMA) 单大缓冲区: Attacker scan time: ~0.4 ms (1.6 μs/page) 放大倍数: ~26x /proc/self/maps: 833 bytes, 10 lines (256 个 VMA 在 maps 中表现为 256 条独立映射项) ``` **分析**:大量小 VMA 不直接检测 process_vm_readv,但大幅增加攻击者遍历 `/proc/pid/maps` 和逐 VMA 读取的开销。结合 `inotify` 监控 `/proc/self/maps` 的读取事件,可间接感知内存扫描行为。 **结论**:Honey VMA 是优秀的防御纵深策略,放大攻击成本 26x,但不提供独立的确定性检测信号。 --- ### 3.6 五代总结 | 世代 | 方法 | 可检测 | SNR | 关键信号 | |------|------|:---:|-----|----------| | G1 | 静态蜜罐页 | ⚠️ 弱 | 1.00 | min_flt(不显著) | | G2 | MADV_DONTNEED 轮换 | ✅ 完美 | ∞ | mincore 0%→100% | | G3 | PMU/min_flt 关联 | ✅ 100% | 999x | min_flt 1:1 per page | | G4 | 三区访问时延 | ✅ 强 | — | Hot Ref +45%, Honey latency 反转 | | G5 | Honey VMA | ✅ 放大 | 26x | scan time 26x | **核心验证**: - `process_vm_readv` 在 ARM64 Linux 5.4 上确实触发 DONTNEED 页的 minor fault - 每个蜜罐页产生精确 1 次 min_flt(1:1 对应) - 被攻击页访问延迟更低(pre-fault 变热,~1500ns → ~150ns) - 攻击者持续扫描导致热参考区延迟升高(+45%,缓存/TLB 竞争) --- ## 4. 六维度 PMU 统计检测 在 G2-G4 基础上引入 ARMv8 PMU 硬件计数器(perf_event_open),构建六个独立检测维度: | 维度 | 名称 | 数据源 | 检测机制 | |------|------|--------|----------| | **D1** | Honey Resident Count | mincore() | 攻击者 fault-in 后页面变驻留 | | **D2** | Recovery Rate | D1 / round_time | 反映攻击者扫描吞吐量 | | **D3** | Minor Fault Delta | /proc/self/stat | 缺页次数 = 被读页数的精确计数 | | **D4** | Cache Miss | ARMv8 PMU: L1D refill | 缓存行竞争导致的 L1 缓存失效 | | **D5** | DTLB Walk | ARMv8 PMU: DTLB walk | TLB 缺失导致的页表遍历 | | **D6** | Access Latency | 本核 load-to-use | 热参考区 + 蜜罐区访问延迟 | ### 4.1 攻击者三种模式 | 模式 | 权限 | 策略 | 预探测方法 | 规避 D1/D3 | |------|------|------|-----------|:---:| | **blind** | root | 无条件读全部蜜罐页 | 无 | 0% | | **smart** | root | 只读热参考区,完全跳过蜜罐 | 解析 /proc/pid/maps 推断活跃区域 | 100% | | **pagemap** | root | /proc/pid/pagemap 逐页检查,只读 resident 页 | pagemap(跨进程驻留查询) | 99.87% | **关键差异**:mincore() 只能检查调用者自身地址空间,外部进程调用返回 -ENOMEM。跨进程驻留探测的唯一用户态手段是 `/proc/<pid>/pagemap`,且需要 root 权限。 ### 4.2 三模式六维度对比 ``` BLIND SMART PAGEMAP (root) 维度 baseline → attack Δ% baseline → attack Δ% baseline → attack Δ% ────────────┼──────────────────────────┼──────────────────────────┼────────────────────────── D1 HoneyR │ 0 → 256 ★★★ ∞ │ 0 → 0 — 规避 │ 0 → 0 — 规避 D2 Rate/s │ 0 → 1280 ★★★ ∞ │ 0 → 0 — 规避 │ 0 → 0 — 规避 D3 MinFlt │ 0 → 255 ★★★ ∞ │ 0 → 0 — 规避 │ 0 → 0 — 规避 D4 $Miss │ 153 → 242 +58% ★★★ │ 162 → 233 +44% ★★ │ 181 → 171 -6% ★ D5 DTLB │ 97 → 130 +34% ★★ │ 104 → 132 +27% ★★ │ 62 → 126 +101% ★★★ D6 RefLat │ 391 → 352 -10% ★ │ 390 → 267 -32% ★★ │ 332 → 222 -33% ★★ D6 HonLat │1172 → 117 -90% ★★★ │1120 → 1146 +2% — │1002 → 944 -6% ★ ────────────┼──────────────────────────┼──────────────────────────┼────────────────────────── Signals │ 4/6 │ 3/6 │ 3/6 Verdict │ DETECTED │ BORDERLINE │ BORDERLINE ``` **Pagemap 攻击者实际行为**: ``` pagemap 检查 47,872 次 → 23,967 页驻留 → 读 23,936 页参考区 蜜罐区: 仅 31 次误读, 跳过 23,905 次 (99.87% 准确率) D1/D3 = 0 (99.87% 规避,31 次误读), 但 D5 DTLB +101%, D6 RefLat -33% ``` ### 4.3 PMU 信号方向编码攻击策略 不同攻击模式产生的 PMU 信号具有**方向性和强度差异**,可以反向推断攻击者的探测手段: | 场景 | D5 DTLB Walk 变化 | 机制 | |------|:---:|------| | Blind(直接读全部) | **+34%** | 外部 GUP 缺页导致目标核 TLB 失效 | | Smart(跳过陷阱区) | **+27%** | GUP 无缺页但仍有 TLB 压力 | | Pagemap(逐页检查) | **+101%** | pagemap 页表遍历 + 驻留页 GUP 的组合效应 | Pagemap 模式的 D5 信号最强(+101%),因为它同时进行了 47,872 次 pagemap 页表遍历和 23,936 次 process_vm_readv,双重 TLB 压力叠加。 --- ## 5. 非陷阱页检测:纯驻留页的极限 ### 5.1 实验设计 上述所有检测的基础是:DONTNEED → 攻击者读 → 缺页。如果攻击者**只读驻留页**(永不 DONTNEED),能否通过纯缓存/TLB 副作用检测? - 256 页 Target Zone(攻击者读取)+ 256 页 Reference Zone(对照) - 全部页面驻留,**永不 DONTNEED** - 20 轮基线 + 270+ 轮攻击 ### 5.2 结果 | 指标 | Baseline | Attack | Δ | |------|----------|--------|-----| | Target P50 | 365-417ns | 365-417ns | **0ns** | | Reference P50 | 365-417ns | 365-417ns | **0ns** | | Signal rate | — | 2.2% (6/270) | 噪声级 | | **Verdict** | | | **NOT DETECTABLE** | ### 5.3 陷阱页 vs 非陷阱页对比 | | 陷阱页 (DONTNEED) | 非陷阱页 (Resident-only) | |---|---|---| | process_vm_readv 副作用 | minor fault | 无 | | mincore 变化 | 0% → 100% | 始终 100% | | min_flt 增量 | 精确 1/page | 始终 0 | | 蜜罐访问延迟 | ~1500ns → ~150ns | 始终 ~400ns | | 检测率 | **100%** | **≈ 2%(噪声级)** | **结论**:在 Linux 5.4 ARM64 上,process_vm_readv 读取纯驻留页不产生可测量的本地缓存/TLB 副作用。纯缓存污染检测在当前消费级 ARM64 SoC 上不可行。检测必须基于 DONTNEED 制造的状态差异。 --- ## 6. 核心发现 ### 6.1 DONTNEED 陷阱可被 root pagemap 完全规避 `/proc/<pid>/pagemap` 为 root 攻击者提供跨进程驻留查询能力(bit 63 = present,bit 62 = swapped),无需触碰目标页面即可区分陷阱页/数据页。D1/D3 降至 0。 **但 pagemap 本身产生反向 PMU 异常**: - D5 DTLB Walk +101%(62→126)—— pagemap 页表遍历副作用 - D6 RefLat -33%(332→222ns)—— 目标核 L1 缓存被攻击者预热 - "异常安静"(缺页消失)结合"异常加速"(延迟骤降)构成 PMU 级双向偏离特征 ### 6.2 Smart 模式无法消除 PMU 信号 非 root 攻击者通过解析 `/proc/pid/maps` 推断活跃区域,只读热参考区驻留页。D1/D3=0。但 PMU 仍捕获: - D4 Cache Miss +44% — 驻留页 process_vm_readv 的缓存一致性开销 - D5 DTLB Walk +27% — 外部 GUP 操作的 TLB 失效 - D6 RefLat -32% — 攻击者预热 L1 缓存 ### 6.3 不存在完美隐身的跨进程内存扫描 | 攻击者能力 | 权限 | 规避 D1/D3 | 不可消除信号 | 检测难度 | |------------|------|:---:|-------------|:---:| | Blind(直接读全部) | root | 0% | D1-D6 全维度 | 极低 | | Smart(跳过陷阱区) | root | 100% | D4+44%, D5+27%, D6-32% | 中等 | | Pagemap(逐页检查) | root | 99.87% | D5+101%, D6-33% | 中等 | | Pagemap + 限速 | root | ~100% | PMU 信号减弱 | 高 | **即使 root 攻击者通过 pagemap 将 DONTNEED 陷阱命中率降至 0.13%(31/23936 误读),仍无法完全消除 PMU 级别的跨核副作用(D5 DTLB +101%, D6 RefLat -33%)。检测需要同时监控正向和负向偏离。** --- ## 7. 局限性 1. **Pagemap 规避**:root 攻击者通过 `/proc/pid/pagemap` 可规避 D1/D3,仅 PMU 维度残留 2. **PMU 可用性**:D4/D5 依赖 `perf_event_open`,需要内核未禁用(`perf_event_paranoid ≤ 1`) 3. **竞态窗口**:DONTNEED 后、mincore 前存在微秒级窗口,但逐页 pagemap 可将其压缩至无意义 4. **误报源**:kswapd、内存压缩等系统活动也可能触发 min_flt 5. **SoC 差异**:本文结果基于 Linux 5.4 ARM64,其他内核版本/架构可能不同 --- ## 8. 推荐检测策略 多层防御纵深: ``` 第一层: G2 DONTNEED 轮换 + mincore (非 root 攻击者 100% 检出) 第二层: G3 min_flt 精确计数 (每页 1:1, 无 PMU 依赖) 第三层: D4-D5 PMU 硬件计数器 (捕获 smart/pagemap 规避) 第四层: D6 双向延迟监控 (正向+负向异常) 第五层: G5 Honey VMA (放大攻击成本 26x) ``` --- ## 9. 对分析结论的验证 | 分析结论 | 实验验证 | |---------|---------| | PerfEvent 跨通道可检测(stat vs perf 差值) | D3 (MinFlt) = 外部 fault 精确 1:1 计数 | | 时延检测需配合陷阱页 | D6 HonLat: 陷阱页 -90%,非陷阱页 0% | | ARM64 PMU task-context 隔离 | D4/D5 检测到的是本核自身的副作用,非直接外部事件 | | pagemap 预探测可绕过 fault 类检测 | Pagemap 模式 D1/D3=0(99.87% 规避) | | 残余 PMU 信号不可消除 | D5 +101%, D6 -33% | | mincore 无跨进程能力 | 外部进程 mincore → ENOMEM;跨进程唯一手段是 pagemap(root) |
传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!!
收藏
・
4
点赞
・
4
打赏
分享
分享到微信
分享到QQ
分享到微博
赞赏记录
参与人
雪币
留言
时间
Lnju
这个讨论对我很有帮助,谢谢!
2026-6-11 12:11
x1a0f3n9
非常支持你的观点!
2026-6-9 10:21
Yangser
期待更多优质内容的分享,论坛有你更精彩!
2026-6-6 11:02
ngiokweng
谢谢你的细致分析,受益匪浅!
2026-6-6 09:27
查看更多
赞赏
×
1 雪花
5 雪花
10 雪花
20 雪花
50 雪花
80 雪花
100 雪花
150 雪花
200 雪花
支付方式:
微信支付
赞赏留言:
快捷留言
感谢分享~
精品文章~
原创内容~
精彩转帖~
助人为乐~
感谢分享~
最新回复
(
1
)
墨穹呢
雪 币:
4770
活跃值:
(8232)
能力值:
( LV3,RANK:20 )
在线值:
发帖
2
回帖
231
粉丝
18
关注
私信
墨穹呢
2
楼
感谢分享
2026-6-12 00:07
0
游客
登录
|
注册
方可回帖
回帖
表情
雪币赚取及消费
高级回复
返回
blackr0ck
2
8
发帖
16
回帖
90
RANK
关注
私信
他的文章
[原创]一加ACE5至尊版 kernel 6.6.89尝试利用GhostLock / IonStack 进行root提权
48931
[原创]领域特定虚拟机DSVM指令完整还原
3808
[原创]APatch KPM 开发:绕过 DirtySepolicy / Duck Detector 的 SELinux Root 检测
3076
[原创]ARM64 页表断点——基于 PTE 缺页异常的透明拦截、上下文捕获与寄存器实时修改
15266
[原创]内核驱动级内存读写的用户层检测与绕过:一次攻防对抗实践
42707
关于我们
联系我们
企业服务
看雪公众号
专注于PC、移动、智能设备安全研究及逆向工程的开发者社区
看原图
赞赏
×
雪币:
+
留言:
快捷留言
为你点赞!
返回
顶部