ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Linux 内核防御机制:`__ro_after_init` 只读数据保护与 `mmap_min_addr` 空指针防护解析(CTF-Wiki 内核 Pwn 篇)

Linux 内核防御机制:`__ro_after_init` 只读数据保护与 `mmap_min_addr` 空指针防护解析(CTF-Wiki 内核 Pwn 篇) 文档网络安全教程【免费下载链接】ctf-wikiCome and join us, we need you!项目地址https://gitcode.com/gh_mirrors/ct/ctf-wiki点击查看免费下载导读在内核 Pwn 的攻防博弈中只读数据保护与低地址空间封锁是两种极易被初学者忽略、却直接影响漏洞利用成败的访问控制机制。本篇技术指南基于 CTF-Wiki 内核安全文档体系中「防御Defense→ 访问控制Access Control」章节的内容深入剖析__ro_after_init标记的初始化后只读数据段的作用原理、其背后的post-init read-only内核加固演进背景以及攻击者借助set_memory_rw()改写页权限的对抗手法同时讲解mmap_min_addr如何抵御 NULL 指针解引用利用链。读完本篇你将能够在内核镜像分析中快速识别这两类防护的开启状态理解它们与 vDSO 写入利用、modprobe_path 数据流攻击等经典内核 Pwn 攻击路径的关联并掌握相应的绕过思路与代码模板。一、__ro_after_init初始化后只读的数据段1.1 机制介绍Linux 内核中存在着大量数据它们只会在__init阶段即内核启动初始化阶段被赋值之后在整个运行期间都不再改变。对于这类一次性初始化、长期只读的数据内核提供了一种特殊的标记__ro_after_init使用__ro_after_init标记的内存在内核 init 阶段结束之后便不能再被修改。该标记的本质是将这些数据放置到内核镜像中独立的只读区段中——在初始化尚未完成时该区段以可写属性存在一旦 init 阶段结束内核会调用mark_rodata_ro()一类的例程把整个ro_after_init区段的页权限从可写切换为只读。此后任何针对该区段数据的写入尝试无论来自内核自身的 bug 还是攻击者的任意写原语都会触发页错误从而在早期阻断攻击链。从源码结构的角度看这一机制的引入与 vDSO 防护有着直接渊源。在 CTF-Wiki 的权限提升章节中可以看到早期 Linux 的 vDSO 是可写的攻击者可以修改高特权进程周期性调用的 vDSO 函数为 shellcode 来实现提权。为此Kees Cook 提出引入post-init read-only初始化后只读数据即将那些初始化后不再被写入的数据统一标记为只读以防御此类利用。这一提议正是__ro_after_init标记的由来可参见 lwn.net 的相关讨论文章。引入前后vDSO 对应的raw_data数组声明发生了如下变化——引入前仅标记对齐属性fprintf(outfile, /* AUTOMATICALLY GENERATED -- DO NOT EDIT */\n\n); fprintf(outfile, #include linux/linkage.h\n); fprintf(outfile, #include asm/page_types.h\n); fprintf(outfile, #include asm/vdso.h\n); fprintf(outfile, \n); fprintf(outfile, static unsigned char raw_data[%lu] __page_aligned_data {, mapping_size);引入之后则被标记为初始化后只读fprintf(outfile, /* AUTOMATICALLY GENERATED -- DO NOT EDIT */\n\n); fprintf(outfile, #include linux/linkage.h\n); fprintf(outfile, #include asm/page_types.h\n); fprintf(outfile, #include asm/vdso.h\n); fprintf(outfile, \n); fprintf(outfile, static unsigned char raw_data[%lu] __ro_after_init __aligned(PAGE_SIZE) {, mapping_size);对比可见vDSO 的raw_data从__page_aligned_data变为__ro_after_init __aligned(PAGE_SIZE)同时仍保持页对齐。这既保证了 vDSO 数据本身页对齐以便映射又使得 init 完成后这段 ELF 内容不可被写入。这一改动直接封堵了修改 vDSO 代码这一经典提权路径。1.2 常见__ro_after_init目标在内核攻防实战中以下类型的数据经常使用__ro_after_init标记也是 CTF 题目中值得关注的目标关键的配置与策略指针如modprobe_path相关的辅助数据、部分 sysctl 处理相关结构各种初始化后固定的函数指针表、ops结构体一旦被写即可劫持控制流vDSO 的raw_data镜像数据如前述。这些数据一旦被写入往往意味着获得了控制流劫持或提权的直接跳板因此它们既是内核加固的重点也是攻击者的首选目标。1.3 攻击手法set_memory_rw()改写页权限__ro_after_init保护的只是页权限而非内容的不可变性。攻击者可以调用内核提供的页属性修改接口将对应页重新置为可写set_memory_rw(unsigned long addr, int numpages)该函数用于修改指定虚拟地址起始、跨numpages个页面的权限为可读可写。攻击流程通常为泄漏或计算目标__ro_after_init数据的虚拟地址如 vDSO 的raw_data或某个 ops 结构体借助任意写原语或内核漏洞调用set_memory_rw(addr, numpages)把对应页从只读改为可写正常写入目标数据完成数据流攻击例如改写 vDSO 函数为 shellcode或篡改函数指针表。需要注意set_memory_rw()属于内核导出的接口用户态无法直接调用在 CTF 场景中通常是先获得内核态任意函数调用如通过 ROP 调用该函数或利用能够修改页表项/直接映射区属性的漏洞原语来完成权限翻转。此外攻击者也可考虑直接操作内核页表如修改对应 PTE 的写位这与调用set_memory_rw()是等价的思路。与绕过思路相关的背景FGKASLR 章节中提到.text等区段不参与函数级随机化而.data区段相对内核镜像的偏移固定其中就包含modprobe_path等数据配合只读区段的权限绕过可构成完整的数据定位 → 权限翻转 → 改写 → 触发提权链。详见 FGKASLR 文档。二、mmap_min_addr封锁低地址空间的空指针防线2.1 机制介绍mmap_min_addr是内核用于对抗 NULL Pointer Dereference空指针解引用的机制它指定了用户进程通过mmap可以使用的最低的虚拟内存地址。其核心逻辑是如果用户进程无法在低地址尤其是0x0附近映射任何内存那么即使内核或用户态代码中存在空指针解引用漏洞解引用NULL所访问的地址也没有对应的物理映射从而会触发缺页异常page fault而不是成功读写攻击者也就无法通过在低地址预先布置数据来接住空指针写入进而无法构造利用原语。Linux 内核通过CONFIG_DEFAULT_MMAP_MIN_ADDR配置项与/proc/sys/vm/mmap_min_addr运行时接口控制该值典型取值如65536即 0x10000x86 上用于保留低 64KB。其值通常需要满足足够大覆盖 NULL 页0x0及其周边阻止空指针利用不能过大以免影响需要低地址映射的合法场景如某些架构的 ABI 兼容、老式程序对低地址映射的依赖。2.2 攻击与绕过视角从攻击者角度看mmap_min_addr只是提高了空指针利用的门槛而非根除漏洞本身需要可控的空指针解引用若要绕过该防护攻击者必须找到内核中可被控制为NULL的解引用点并配合其他原语如直接修改进程的 mmap 下限、利用MAP_FIXED在受限场景下的行为差异、或在开启该防护前完成低地址映射来实现低地址布局关注配置差异不同发行版/内核配置下mmap_min_addr的默认值不同某些环境可能将其设为0即关闭防护。CTF 题目中若mmap_min_addr未生效或值过小空指针利用链的可行性会显著提升。结合 CTF-Wiki 内核防御章节的整体框架mmap_min_addr属于访问控制型防御与dmesg_restrict内核日志访问限制、kptr_restrict内核地址输出限制保护/proc/kallsyms等接口共同构成信息与访问层面的防护组合详见访问控制章节导读与信息泄漏防护文档。三、实战要点小结针对本篇涉及的两项防御机制给出内核 Pwn 实战中的检查与利用速查防御机制作用对象检查方式典型对抗思路__ro_after_init初始化后不再写入的内核数据含 vDSOraw_data内核镜像中搜索__ro_after_init标记readelf -S vmlinux查看ro_after_init相关区段通过set_memory_rw()或改写页表项将目标页置回可写后再篡改mmap_min_addr用户态低地址空间NULL 页cat /proc/sys/vm/mmap_min_addr寻找可控空指针解引用点或在防护缺失/取值过小时直接利用四、参考lwn.net: Kernel self-protection project__ro_after_init背景讨论lwn.net: post-init read-only 数据相关讨论lore.kernel.org: 相关补丁讨论本仓库相关延伸阅读change-others.md含 vDSO 修改提权与 raw_data 代码对比、FGKASLR 文档、访问控制章节导读说明本篇以 CTF-Wiki 中docs/zh-tw/docs/pwn/linux/kernel-mode/defense/access-control/misc.md文档为主体骨架结合仓库内权限提升与随机化相关章节的源码级代码片段进行了交叉印证与扩充文中所涉内核接口的具体行为以目标内核版本实际实现为准。赞分享文档网络安全教程【免费下载链接】ctf-wikiCome and join us, we need you!项目地址https://gitcode.com/gh_mirrors/ct/ctf-wiki点击查看免费下载相关推荐ctf-wiki 内核 Pwn 防御机制解读dmesg_restrict 与 kptr_restrict 信息泄漏防护详解ctf wiki 内核 Pwn 防御机制解读dmesg_restrict 与 kptr_restrict 信息泄漏防护详解 导读 本文聚焦 ctf wiki文档网络安全教程CTF-Wiki 内核 Pwn 基础Linux Kernel 特权模型、cred 提权与防护机制全解CTF Wiki 内核 Pwn 基础Linux Kernel 特权模型、cred 提权与防护机制全解 本文是 CTF Wiki 开源项目 docs/zh t文档网络安全教程ctf-wiki 内核篇Linux 内核防御机制全景解析——隔离、访问控制、异常检测与随机化ctf wiki 内核篇Linux 内核防御机制全景解析——隔离、访问控制、异常检测与随机化 导读 本文基于 ctf wiki 仓库 pwn/linux/k文档网络安全教程上一篇PHPWord生成PDF文档5个简单步骤实现无缝转换下一篇OpenRGB一站式跨平台RGB设备统一控制解决方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表