陌小杨の小站
首页项目归档照片墙音乐灵境说说杂谈友链关于
封面

(Anti-)Anti-Rootkit Techniques - Part III: Hijacking Pointers

写作时间:2025-02-16
# Rootkit
# Windows
# 内核
# 安全

概述

在第二部分中,我们探讨了通过篡改PspCidTable来隐藏Rootkit线程。在这三部曲的最后一部分,我们将移除Rootkit中的主线程,实现一种"无线程"的用户到内核通信。

用户到内核通信

既不能使用IOCTL,也不能使用循环内核线程——那么我们如何从用户态调用内核代码?

每次执行Nt*系统调用时,你都在做这件事——设置参数并进入系统调用中断,将控制权转移到内核。因此我们可以对内核代码进行跳板钩子。

但直接在.text段做钩子和驱动踩踏一样嘈杂。如果驱动程序从.data段调用函数指针呢?

.DATA指针交换

.data段包含所有静态变量,在运行时可能发生变化。可以从用户态发起并调用存储在.data段中函数指针的函数随处可见。会话驱动程序Win32k.sys、win32kbase.sys和win32kfull.sys包含许多此类函数。

利用kCFG寻找指针

内核控制流保护(kCFG)实际上为我们提供了一个寻找指针的方便方法。__guard_dispatch_icall_fptr_是kCFG插入的调用,通过交叉引用对该函数的调用,我们就得到了驱动程序中所有.data指针的列表。

如果VBS被禁用,kCFG检查基本上被绕过——guard_icall_bitmap和retpoline_image_bitmap都为NULL。

综合运用

将此技术与第一部分中的共享内存技术结合,我们可以使用任何指针,无论参数数量如何。我们只需将命令写入共享内存区域,让被钩住的指针触发Rootkit从缓冲区轮询命令。

选择目标函数

以NtUserCreateWindowStation为例,它包装了ApiSetEditionCreateWindowStationEntryPoint。该函数中的.data指针在一个简单检查后被调用,任何对该例程的调用都会触发我们的Rootkit代码。

实现步骤

  1. 签名扫描找到NtUserCreateWindowStation
  2. 在其附近搜索.data指针模式
  3. 用_InterlockedExchangePointer交换指针
  4. 在钩子函数中轮询共享内存对象中的命令负载
  5. 用户态客户端写入命令到共享内存,触发钩子

检测向量

检测这些技术的直观方法是查找标准驱动程序中所有可能的.data指针,检查它们是否指向由驱动程序支持的内存。然而检查所有指针是一项艰巨任务,因为可以使用指针链。

所有来自第一部分的基于调用栈的检测方法(尤其是基于NMI的方法)仍然有效。但我们确实减少了驱动程序的检测面——指向我们内存的系统线程仅在Rootkit代码实际需要执行时才运行。

总结

这结束了关于反反Rootkit措施的三部曲。通过交换良性驱动.data段中的指针实现无线程通信,大大减少了被检测的可能性。仍有更多可以探讨和发现的内容。

avatar

陌小杨

热爱折腾代码的开发者,记录学习与生活的点点滴滴。

RECOMMENDED

(Anti-)Anti-Rootkit Techniques - Part I: UnKovering Mapped Rootkits

2024-03-23

(Anti-)Anti-Rootkit Techniques - Part II: Stomped Drivers and Hidden Threads

2024-09-19

Driver Reverse Engineering 101 - Part I: Static Analysis

2025-08-15

Table of Contents