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

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

写作时间:2024-09-19
# Rootkit
# Windows
# 内核
# 安全

概述

在第一部分的结尾,我们有了一个小型反Rootkit驱动,可以检测手动映射到无后备内存的恶意驱动。本篇文章将介绍针对这种反Rootkit的规避方法,以及如何检测这些规避。

检测1:检测驱动"踩踏"

驱动踩踏是将Rootkit加载到现有驱动内存之上的技术。检测方法很简单——比较驱动在磁盘上的.text节与内存中的.text节。

实现步骤:

  1. 遍历\Driver目录获取PDRIVER_OBJECT
  2. 获取驱动服务名称并在注册表中查找路径
  3. 读取磁盘上的镜像文件
  4. 使用RtlCompareMemory比较磁盘与内存中的.text节
  5. 如果不同,则检测到踩踏

注意:如果mapper使用.data或.rdata节而非.text节,则需要额外的检测方法。

Windows线程内部机制:句柄表与PspCidTable

unKover中检查线程起始地址的技术都使用PsLookupThreadByThreadId,这是ntoskrnl.exe导出的例程。通过IDA反编译可以看到它内部调用了PspReferenceCidTableEntry,该函数引用了全局符号PspCidTable。

PspCidTable是一个句柄表,包含线程和进程的句柄。这就是为什么进程和线程ID永远不会重复——它们共享同一个ID池。

漏洞利用

如果ExpLookupHandleTableEntry找不到查询的ID,函数返回NULL。这就是攻击unKover的方法:如果从PspCidTable中移除Rootkit的线程ID,任何依赖此表的函数都将找不到该线程。

定位PspCidTable

两种方法:

  1. 签名扫描: 扫描PspReferenceCidTableEntry函数中的mov rbp, cs:指令
  2. KeCapturePersistentThreadState: 使用未文档化的Windows内核函数检索包含解密KdDebuggerDataBlock的小型内存转储

移除句柄表条目

扫描ExMapHandleToPointer、ExpLookupHandleTableEntry和ExDestroyHandle,使用简单函数调用即可移除条目。

检测2:通过不一致性检测篡改

检测篡改的通用策略是检查不一致性。

遍历进程的线程链表

每个进程在内核中表示为KPROCESS/EPROCESS对象,包含ThreadListHead链表。所有内核驱动默认运行在PID 4的系统进程下。

通过KTHREAD结构中的ThreadListEntry(偏移0x2f8)遍历链表,枚举所有系统进程下的驱动线程。如果发现某个线程ID无法通过PsLookupThreadByThreadId找到,则找到了隐藏线程。

展望

在用户态恶意软件领域,当线程回调开始检测各种代码注入技术时,人们发现无线程(threadless)是出路。由于unKover严重依赖线程检测,第三部分将实现无线程Rootkit。

avatar

陌小杨

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

RECOMMENDED

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

2024-03-23

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

2025-02-16

Driver Reverse Engineering 101 - Part I: Static Analysis

2025-08-15

Table of Contents