高级WIN2K ROOTKIT检测技术(转) |
这篇文章是04年5月我转载在学院小天论坛的,把当时我的签名都copy来啦。 学习Windows kernel也有一段时间了,自己觉得还不错,还有自己写一个内核级后门的想法。后来在xfocus上看到了这篇文章,实在汗……;差点都让我没有信心再学网络有关的东西了。 高级WIN2K ROOTKIT检测技术 原文: (译著:由于格式的原因,图片请参照原文.) 摘要:本文描述了一种检测内核与用户级rootkit的新技术.此技术利用处理器的单步执行模式,来测定系统内核与DLL --背景知识 一个在计算机安全领域中重要的问题是,如何判断给定的主机是否已被入侵.由于以下两点这项工作变的非常困难: --传统rootkit检测技术中的一些问题 传统的rootkit检测程序(那些我们经常在UNIX系统中见到的)只能检测一些已知的rootkit(这点使它变的像反病毒程 那检测程序是不是还应该扫描内核代码空间?这样我们就有了一个运行在内核模式中的Tripwire.但这还不够好,因为 以我看,存储扫描技术决不会成为rootkit检测的终结.这主要是因为我们不能确定具体的监测存储区域. 那到底怎样检测出我们系统中的入侵者呢? 首先我们以rootkit中所使用的技术,将其分为两类: --更改系统数据结构的rootkit 这类的rootkit不太多.有意思的例子包括fu rootkit(见[3]),通过删除内核中PsActiveProcessList链上的进程对象 *pKiDispatcherReadyListHead 后两个是处于"等待"状态的线程链头.他们之间稍有不同,但对我们来说并不重要. 从上面的信息我们可以找到一种检测隐藏进程的方法.及读取线程分派器使用的数据结构,而不是 当检测rootkit时我们应该尽可能的触及更底层的内核数据结构. 有一点应该注意,直接从线程分派器使用的链中删除要隐藏的进程是不可能的,因为隐藏的进程将分配不到CPU使用时 --更改执行路径的rootkit 这类的rootkit较为普及.他们通过修改或增加内核或系统DLL中的指令来达到目的.检测这类rootkit的问题是,我们不 --执行路径分析(Execution Path Analysis) EPA关注这样一个事实:如果入侵者通过修改执行路径隐藏了一些对象,那么当调用一些典型的系统和库的函数时,系 举个例子,如果入侵者为了隐藏文件和进程而修改了ZwQueryDirectoryFile()和ZwQuerySysteminformation(),那样 但是Windows 2000的内核是一个非常复杂的程序,即使在干净的系统中,某些系统函数每次运行的指令个数也是不同 --指令计数器的实现 单步执行模式是Intel处理器的一个好的特性,我们可以用它来实现指令计数.当处理器处在这个模式时,每执行完一 当执行int指令时,处理器会自动清TF位并进行权限切换.这意味着,如果要进行内核模式下的指令计数,则必须在中 但是,因为存在用户模式的rootkit,也应该测定在ring3级运行的指令个数.只要在用户模式下设置TF位一次就可以 以上的计数方法通过内核驱动器实现.如图2所示,驱动加载后勾连IDT 0x1和0x2e.为和用户级程序交互.驱动勾连一 --一些测试 我们可以使用上一段中描述的方法来测定任意系统服务中执行的指令个数. 例如,来检查是否有人试图隐藏任意文件,我们可以开始一个简单的测试: pfStart(); 如果有rootkit隐藏任意文件,则执行的指令数要比干净的系统多. 如果运行这个测试上百次,并计算执行指令数的平均值,我们会发现这个值是非常不确定的.考虑Win2k的复杂性,这一 假想现在有人安装了隐藏文件的rootkit,如果我们重复测试并绘制相应的条形图,就会发现频率高点向右移了,这是 在现在的代码实现中,只进行了少量的测试,包括典型的服务如:文件系统读取,枚举进程,枚举注册表项以及Socket读 这些测试将有效地检测出著名的NTRootkit(见[1]),或最近比较流行的Hacker Defender(见[4]),包括它自带的网络 --误报和执行路径跟踪 虽然对频率高点的检测有助于我们处理系统的不确定因素,但有时会发现测试得到的值有小的差值,一般来说不大于 有时这会是一个很严重的问题,因为我们不能确定那些多出来的指令意味着被入侵或只是正常的误差. 为解决这个问题,我们使用了执行路径记录模式.和单一的EPA模式比较,系统增加了对执行路径的记录(包括地址和运 我们应该使用好的反编译器来分析那些不一样的地方,以此判定他们是否可疑.图6是一个diff文件的例子. 现阶段的diff文件只记录下指令的地址,以后可能将两次测试的不同结果存为PE格式文件,并可用IDA等工具分析. --检测 ”offset-in-the-code” 的变化 想象有这样一个rootkit,它基本和上面提到的 fu rootkit (见[3]) 一样,但不从PsActiveProcessList中,而是从分 然而,rootkit可以同时更改分派器代码中所使用数据结构的地址(offset),换句话说,就是使其使用不同的链表.但只 虽然这种技术不会改变执行指令的个数,我们还是能检测到它,但需要进一步的完善现有的工具.这项功能现在还没有 --针对EPA的攻防 我们可以想到一些能骗过EPA类检测工具的方法,先把它们分为两类. 首先,我们考虑一下通用的攻击方法和怎样防止这类攻击.接着讨论针对特定工具的攻击以及怎样通过多态来预防. --对EPA类技术的通用攻击 首先,恶意程序可以勾连包含除错处理程序(debug handler)地址的IDT入口1,这样将暂停记录运行的指令数.当它完 我们可以使用intel的除错寄存器来防止这类的攻击.可以使用DR0和DR1寄存器对IDT入口1进行写保护.并且为防止 还有一种攻击的方法,在rootkit运行时,其将TF位清零,并在恶意操作完成时恢复TF位,这样检测工具也只能发现运行 另外,rootkit还能检查TF位, 如发现被跟踪,则不进行恶意操作.这种行为并不会影响rootkit的正常工作,因为只有 我们可以防止这种攻击,应该注意到的是运行每一个系统指令前,都会运行我们的除错处理程序.以下是简单的防预 如果除错处理程序发现上一个运行指令是pushf(将EFLAGS寄存器压入堆栈),则运行如下操作. and [esp], 0xfffffeff; 及清TF位.同样,如果下一条指令是popf(从堆栈载入EFLAGS的值),则运行如下操作. or [esp],0x100; 及设TF位.这样rootkit就不能更改TF位. 这样的预防几乎可够了,但还不充分.Rootkit仍能以以下方法发现其被跟踪: setTFbit(); 所以我们需要更改反检测部分的操作,使其可以记录TF位有没有被rootkit更改(比如增加一个TFbitset变量). popf/pushf不是存取EFLAGS寄存器的唯一指令,其它像iret/int等指令也可以[注2],因此还要加入对这些指令的检测. 对EGLAGS寄存器的防护部分还没有被实现.一部分原因是通过对diff文件的分析也可以发现这类攻击.但以后会增加 --对特定工具的攻击 如果攻击者了解关于特定检测工具的一切,他会有很多种欺骗的手段.比如,可以更改保存指令数的那个变量. 不过这类攻击具有很强的针对性,如果有很多不同(或非单一版本)的EPA类工具,这样的攻击将不会有效. 当然,我们还是希望可以阻止这类攻击,强大的多态代码生成器可能是唯一的方法.当管理员安装检测工具是,会产生 多态代码生成器部分还没有被实现. --相关工作 像文章开头所述,笔者还没有发现任何对rootkit的检测方法,不是基于存储扫描的. EPA技术并不被OS所局限,笔者在linux下也实现了一相关工具,参5中有对其的详述以及简单的代码实现.
注2: 参6上列举了所有和EFLAGS寄存器交互的指令. ---------------------------------------------- |