内核漏洞挖掘技术系列(3)——bochspwn-reloaded(1)
字数 1984 2025-08-05 11:39:26

内核漏洞挖掘技术:bochspwn-reloaded 原理与实现

1. 信息泄露漏洞概述

信息泄露漏洞是内核安全中的重要问题,主要源于C语言特性和内核设计模式两方面。

1.1 C语言导致的问题

未初始化变量

  • 未初始化变量会继承内存区域的旧值
  • 示例:系统调用泄露栈上4字节
int sys_leak() {
    int uninitialized;  // 未初始化
    copy_to_user(..., &uninitialized, sizeof(uninitialized));
}

结构体对齐和填充

  • 结构体对齐会插入填充字节
  • 填充字节会继承内存旧值
  • 解决方案:
    1. 显式声明并初始化填充字节
    2. 使用__attribute__((packed))禁止对齐
    3. 序列化为字节缓冲区

联合体不同大小成员

  • 只设置较小成员时,较大成员的剩余字节未初始化
union {
    int a;
    long b;
} u;
u.a = 1;  // b的高4字节未初始化

1.2 内核设计和编程模式问题

动态分配内存重用

  • 栈和堆上的内存重用机制

固定长度数组

  • 大缓冲区未全部使用时可能泄露
char path[260];
RtlGetSystemPath(path);  // 可能只使用部分但拷贝全部260字节

分配缓冲区未全部初始化

  • 根据用户传入大小分配缓冲区但未完全初始化
void* buf = kmalloc(user_size);
copy_to_user(..., buf, user_size);  // 可能泄露未初始化部分

2. bochspwn-reloaded设计原理

2.1 Shadow Memory机制

32位系统元数据结构

  • 每个字节映射到元数据:
    • Taint标记
    • Size:内存分配大小
    • Base address:分配起始地址
    • Tag/flags:池分配tag或堆分配flag
    • Origin:分配请求的指令地址

64位系统优化

  • 使用std::unordered_map<uint64_t, uint64_t> origins存储origin
  • 去除size、base address和tag/flags以节省空间

内存分配策略

  1. 使用VirtualAllocMEM_RESERVE保留shadow memory
  2. 设置异常处理程序
  3. 异常处理中提交shadow memory并继续执行

内存填充策略

  • 新分配堆/池用0xaa填充
  • 栈用0xbb填充

2.2 污点标记策略

栈污点标记

伪代码逻辑:

on_instruction_execute:
    if instruction_modifies_esp and esp_decreased:
        mark_taint(esp_new - esp_old)

特殊处理:

  1. 32位Windows的chkstk函数:从EAX读取更新后的ESP
  2. __SEH_prolog4__SEH_prolog4_GS:从[EBP-8]读取origin

Windows内存分配污点标记

x86架构

  • Hook ExAllocatePoolWithTag函数
  • 参数通过栈传递,返回值在EAX

x64架构

  • 需要两次hook:
    1. 第一次获取origin和size
    2. 第二次获取base address
  • 处理特殊分配器如win32k!AllocFreeTmpBuffer

Linux内存分配污点标记

  • Hook多个分配函数(kmalloc, vmalloc等)
  • 原理与Windows类似

2.3 污点传播机制

Windows x86

  • 监控函数:memcpy/memmove/RtlCopyMemory/RtlMoveMemory
  • 大部分基于rep movs指令
  • 特殊情况处理:
    1. 缓冲区重叠
    2. 目标指针未对齐
    3. 复制长度小于32字节
    4. 长度未对齐

解决方案

  • Patch代码修改cmp ecx, 8cmp ecx, 0

Windows x64

  1. 内存拷贝函数使用mov/SSE指令
    • 配置memcpy_signature匹配
    • 调用handle_memcpy传播污点
  2. 内联mov指令序列

Linux x86

  • 设置内核配置:
    CONFIG_X86_GENERIC=y
    CONFIG_X86_USE_3DNOW=n
    
  • Patch代码使所有memcpy调用__memcpy

2.4 漏洞检测机制

通用检测

  • 监控内核到用户的数据拷贝
  • 发现未初始化字节时报告漏洞

Linux特殊处理

  • copy_to_user:等价memcpy,通用检测有效
  • put_user:通过寄存器传递数据

解决方案
修改put_user宏,添加指令:

prefetcht1  ; 作为信号
prefetcht2  ; 禁用信号
  • 在Bochs中由BX_CPU_C::NOP处理
  • 检测prefetcht1执行作为信号

3. 实现关键技术点

3.1 内存管理

  • Shadow memory的稀疏分配策略
  • 异常处理机制实现按需提交内存
  • 64位系统的哈希表优化

3.2 指令级插桩

  • 精确控制流追踪
  • 寄存器状态监控
  • 特殊指令处理(如rep movs

3.3 系统特定处理

  • Windows池分配tag跟踪
  • Linux分配flag跟踪
  • 不同架构调用约定处理

3.4 性能优化

  • 选择性污点传播
  • 元数据压缩存储
  • 热点代码路径优化

4. 应用与局限性

4.1 适用场景

  • 内核未初始化内存泄露检测
  • 复杂控制流中的数据传播分析
  • 历史代码的安全审计

4.2 局限性

  • 性能开销较大
  • 需要修改目标代码(如memcpy patch)
  • 对某些编译器优化敏感

5. 扩展与改进方向

  1. 结合静态分析减少运行时开销
  2. 支持更多架构和操作系统
  3. 自动化漏洞验证机制
  4. 机器学习辅助误报过滤

通过bochspwn-reloaded这样的工具,安全研究人员可以系统性地发现内核中潜在的信息泄露漏洞,提高操作系统安全性。

内核漏洞挖掘技术:bochspwn-reloaded 原理与实现 1. 信息泄露漏洞概述 信息泄露漏洞是内核安全中的重要问题,主要源于C语言特性和内核设计模式两方面。 1.1 C语言导致的问题 未初始化变量 未初始化变量会继承内存区域的旧值 示例:系统调用泄露栈上4字节 结构体对齐和填充 结构体对齐会插入填充字节 填充字节会继承内存旧值 解决方案: 显式声明并初始化填充字节 使用 __attribute__((packed)) 禁止对齐 序列化为字节缓冲区 联合体不同大小成员 只设置较小成员时,较大成员的剩余字节未初始化 1.2 内核设计和编程模式问题 动态分配内存重用 栈和堆上的内存重用机制 固定长度数组 大缓冲区未全部使用时可能泄露 分配缓冲区未全部初始化 根据用户传入大小分配缓冲区但未完全初始化 2. bochspwn-reloaded设计原理 2.1 Shadow Memory机制 32位系统元数据结构 每个字节映射到元数据: Taint标记 Size:内存分配大小 Base address:分配起始地址 Tag/flags:池分配tag或堆分配flag Origin:分配请求的指令地址 64位系统优化 使用 std::unordered_map<uint64_t, uint64_t> origins 存储origin 去除size、base address和tag/flags以节省空间 内存分配策略 使用 VirtualAlloc 和 MEM_RESERVE 保留shadow memory 设置异常处理程序 异常处理中提交shadow memory并继续执行 内存填充策略 新分配堆/池用 0xaa 填充 栈用 0xbb 填充 2.2 污点标记策略 栈污点标记 伪代码逻辑: 特殊处理: 32位Windows的 chkstk 函数:从EAX读取更新后的ESP __SEH_prolog4 和 __SEH_prolog4_GS :从 [EBP-8] 读取origin Windows内存分配污点标记 x86架构 : Hook ExAllocatePoolWithTag 函数 参数通过栈传递,返回值在EAX x64架构 : 需要两次hook: 第一次获取origin和size 第二次获取base address 处理特殊分配器如 win32k!AllocFreeTmpBuffer Linux内存分配污点标记 Hook多个分配函数( kmalloc , vmalloc 等) 原理与Windows类似 2.3 污点传播机制 Windows x86 监控函数: memcpy / memmove / RtlCopyMemory / RtlMoveMemory 大部分基于 rep movs 指令 特殊情况处理: 缓冲区重叠 目标指针未对齐 复制长度小于32字节 长度未对齐 解决方案 : Patch代码修改 cmp ecx, 8 为 cmp ecx, 0 Windows x64 内存拷贝函数使用mov/SSE指令 配置 memcpy_signature 匹配 调用 handle_memcpy 传播污点 内联mov指令序列 Linux x86 设置内核配置: Patch代码使所有 memcpy 调用 __memcpy 2.4 漏洞检测机制 通用检测 监控内核到用户的数据拷贝 发现未初始化字节时报告漏洞 Linux特殊处理 copy_to_user :等价 memcpy ,通用检测有效 put_user :通过寄存器传递数据 解决方案 : 修改 put_user 宏,添加指令: 在Bochs中由 BX_CPU_C::NOP 处理 检测 prefetcht1 执行作为信号 3. 实现关键技术点 3.1 内存管理 Shadow memory的稀疏分配策略 异常处理机制实现按需提交内存 64位系统的哈希表优化 3.2 指令级插桩 精确控制流追踪 寄存器状态监控 特殊指令处理(如 rep movs ) 3.3 系统特定处理 Windows池分配tag跟踪 Linux分配flag跟踪 不同架构调用约定处理 3.4 性能优化 选择性污点传播 元数据压缩存储 热点代码路径优化 4. 应用与局限性 4.1 适用场景 内核未初始化内存泄露检测 复杂控制流中的数据传播分析 历史代码的安全审计 4.2 局限性 性能开销较大 需要修改目标代码(如memcpy patch) 对某些编译器优化敏感 5. 扩展与改进方向 结合静态分析减少运行时开销 支持更多架构和操作系统 自动化漏洞验证机制 机器学习辅助误报过滤 通过bochspwn-reloaded这样的工具,安全研究人员可以系统性地发现内核中潜在的信息泄露漏洞,提高操作系统安全性。