APP下载

Windows系统下Rootkit的隐藏与检测

2010-03-23

通化师范学院学报 2010年4期
关键词:注册表调用线程

徐 睿

(上海交通大学 软件学院,上海 200240)

1 Windows rootkit概述

Rootkit是计算机安全领域的一个术语,来自root和kit两个单词的组合,其中root是Unix系统中超级用户的名称,拥有系统的最高权限;kit则是工具套件的意思.而Rootkit具体是指其主要功能为隐藏其他程式进程的软件,是能够持久或可靠地、无法检测地存在于计算机上的一组程序和代码.黑客通过修改系统程序,把这些系统程序变为后门程序.从而使得攻击者能够保持访问计算机上具有最高权限的用户“root”.Rootkit一般都和木马、后门等其他恶意程序结合使用.

Rootkit功能和被植入操作系统的木马相似,根据Windows系统下程序运行模式的不同,可以将Windows下的Rootkit分为应用程序级Rootkit,内核级Rootkit两类.

Rootkit的攻击过程主要包括:①收集目标系统信息.攻击者在攻击某个系统之前,需要知道目标系统有哪些漏洞,使用什么操作系统,有哪些帐号等.②获得管理员等级的用户的访问权限.在得到目标系统足够的信息后,攻击者便开始利用其漏洞发起进攻.比较常见的是先获得普通用户访问权限,然后再利用目标系统的本地漏洞提高到超级用户访问权限.还有一种方式是直接利用ftp和telnet等网络服务的漏洞获得超级用户访问权限.③在目标操作系统上安装Rootkit.获得超级用户访问权限后,攻击者就可以在目标系统上安装Rootkit,来隐藏攻击行为,创建各种后门.④控制目标系统.在目标系统上安装Rootkit后,就可以持久的控制目标系统,对其进行各种攻击,而且不被目标系统的管理员察觉.例如:利用目标系统攻击其它系统,使目标系统拒绝提供某些服务等等.

2 Windows Rootkit隐藏技术

Rootkit隐藏的实现过程主要有:(1)用户态下的API Hook.在用户态,一种常用的隐藏方法就是修改PE文件的IAT(Import Address Table)来实现.IAT中记录了该文件运行时需要调用的所有函数链接库.PE文件运行时会将自己和IAT中记录的链接库都加载到内存,然后在当前进程空间的地址间建立库函数符号名和相应代码的映射,以后就通过IAT来调用这些函数.Rootkit采取的手段是在进程加载时修改IAT,将Hook的API函数地址改为Rootkit代码的地址.这样,进程每次调用此函数时,其实执行的是Rootkit代码.另一种方法则是将被拦截函数的前几条代码改成JMP跳转指令,使程序的执行跳转到Rootkit代码.Rootkit进行额外处理后,执行事先保存下来的被改写部分的原指令,并跳转回原函数相应位置,这样,在Rootkit监视函数调用的时候,函数的原有功能依然能得到完整的调用,从而更好的隐藏了自身.

动态库陷阱方法则是直接用重写的DLL文件来替换系统中原有的DLL,并将原DLL改名.重写的DLL的IAT和原DLL的EAT(Export Address Table)之间存在一个一一映射.这样在系统调用对应DLL的时候就会直接去调用Rootkit的相关代码.但是在Windows的文件保护机制中,当系统关键文件被修改时,操作系统会自动修复受损的文件.因此使用这一机制的Rootkit会通过改写SFCDisable注册表项和修改Sfc.dll来终止文件保护机制.

(2)IDT Hooks和SYSENTER Hook.在Windows 2000系统中,通过中断描述符表进行系统调用.IDT有256个入口,每个入口说明对应的中断处理程序的地址.Rootkit通过修改IDT的0x2e入口来拦截系统调用,这种方法的缺点是仅能简单地阻止请求,不能修改返回数据.Intel x86平台上的Windows XP系统用SYSENTER指令取代中断,使系统陷入系统服务调用程序(AMD平台上的Windows XP使用syscall指令实现相同功能),相应产生了新的Hook方法,即把IA32_ SYSENTER_EIP寄存器的值修改为要运行的Rootkit代码的地址.

(3)SSDT Hook.系统服务调度表(SSDT)中存放了所有系统服务函数的入口地址.系统服务调度程序通过查找SSDT来调用相应的系统服务.因此,Rootkit可以将SSDT中的系统服务地址替换为自己代码的地址.这样,当调用系统服务时,实际运行的是Rootkit代码,由Rootkit代码调用真正的系统服务并对结果作相应处理.系统中存在2个SSDT,位于文件ntoskrnl.exe中,分别由指针KeServiceDescriptorTable和KeServiceDescriptorTableShadow导出,对应了2类不同的系统服务.前者对应的系统服务,功能代码在ntoskrnl.exe中实现,用户模式下的访问接口由NTDLL.dll提供,通常kernel32.dll/advapi32.dll导出的API最终调用的都是这类系统服务;后者对应的是USER和GDI系统服务,访问接口由User32.dll/Gdi32.dll提供,功能代码在Win32k.sys中实现.Rootkit关注的主要是对进程、文件、注册表等的操作,对应的系统服务属于第一类,需修改KeService Descriptor Table导出的SSDT.KeServiceDescriptor-Table指向一个KSERVICE_TABLE_ DESCRIPTOR结构,其中的Service TableBase指针指向真正的系统服务入口地址表.如要Hook某个系统服务,将该表中相应的代码入口地址修改为钩子函数的地址即可.例如,ZwQuerySystem-Information是系统列举进程时需调用的系统服务,通过挂钩它来实现进程的隐藏.

3 Windows Rootkit检测方法

3.1 基于交叉视图的检测方法

在操作系统中,用户态下的程序最终都要切换到内核态继续执行.因此无论针对用户态的Rootkit还是内核态的Rootkit,必须使用更加底层的方法查询系统信息.这样才能回避Rootkit的监视,从而反过来找出系统中隐藏的Rootkit信息.

基于交叉视图的检测方法是指:对于可能被Rootkit隐藏的信息,检测程序进行两次扫描检测,第一次从高层次扫描,第二次从另外一个层次扫描,将两次扫描的结果相比较,列举出被Rootkit隐藏的信息.最常用的交叉视图检测程序分为两个部分:用户态部分负责第一次扫描;内核态部分负责底层的扫描,同时将扫描的结果返回给用户态对比输出.

(1)文件隐藏检测.第一次扫描使用Kenrel32.dll的FindFirstFile和KerneI32.dll的FindNextFile函数枚举磁盘上的文件,第二次扫描直接和磁盘驱动程序交互,读取物理磁盘设备,得到磁盘上的文件信息,这样就能够跳过有可能被Rootkit挂钩的函数,发现隐藏文件.

(2)注册表隐藏检测.第一次扫描使用Advapi32的RegEnumKey和RegEnumValue函数枚举用户能得到的注册表子键(键值),第二次扫描直接和磁盘驱动交互,读取磁盘上的注册表备份文件,从而检测出被Rootkit隐藏的注册表信息.Windows系统中注册表各个项在磁盘上都有备份,例如c:windowssystem32configsystem文件存储了HKLMsystem键,用户配置文件信息文件夹下的ntuser.dat文件HKU主键下的每一个用户相应的注册表项的配置信息.

在用户态下可以用以下的程序直接读取磁盘扇区:

HANDLE hFile=CerateFile(“\.PhysicalDriveO,

GENERIC_READ,FILE_SHARE_READ, NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL, NULL);

Char sBuffer[512];

DWORD dwReadLength;

ReadFile(hFile, sBuffer, 512, &dwReadLength, NULL);

HANDLE hFile2 = CreateFile(“\.C:”, GENERIC_READ,

FILE_SHARE_READ,NULL,OPEN_EXISTING, FILE_ATRIBUTE_NORMAL, NULL);pReadFile(hFile, sBuffer, 512, &dwReadLength, NULL);

读取了硬盘的分区表,就能得到磁盘上所有分区的磁盘格式;按照每个分区上文件系统的磁盘数据格式对磁盘上的文件进行枚举就得到第二次扫描(注册表或文件)的结果.

(3)隐藏端口的检测.对于被Rootkit隐藏的端口,用户可以使用扫描软件对本地主机进行一次扫描,将扫描结果和使用端口查看工具得到的结果比较,就能检测出被Rootkit隐藏的端口,这种检测本地开放端口的方法比较准确.

(4)隐藏进程的检测.Rootkit可以从多个方面对进程进行隐藏,有的修改系统服务表的ZwQuerySystemInfomation函数;有的直接修改内核数据链PsActiveProcessList的节点,例如fu_rootkit.Rootkit检测程序检测被隐藏的进程时,第一次扫描可以使用CreateToolhelp32Snapshot() , ProcessFirst()和ProcessNext()函数进行枚举;第二次扫描则需要根据Windows操作系统的线程调度实现.在Windows操作系统中,线程要想运行,必须接受操作系统的线程调度,接受操作系统的线程切换.在Windows系统下,线程切换是通过Ntoskrnl.Exe的SwapContext()函数实现的.这样,检测程序只需要挂钩Ntoskrnl.exe中的SwapContext()函数,就能得到正在进行切换的线程,进而得到系统中所有正在运行的线程.

操作系统调用SwapContext()函数时,ESI指向将被切换进来的线程的_EIHREAD结构体指针,EDI指向将被切换出的线程的_ETHREAD结构体指针,根据ESI和EDI就能够得到正在切换的线程的信息.可以根据_ETHREAD结构体中的ThreadsPorcess成员得到该线程所属进程_EPROCESS结构体的指针,再由该进程的_EPROCFSS结构体ImageFileNam,就可以得到进程映像名.挂钩SwapContext()函数的方法采用改写SwapContext()函数前几个字节的方法实现.

在Windows2000/XP下可以使用如下代码得到SwapContext()的函数地址:

PCHAR GetSwapAddr(){

PCHARres = 0 ;

NTSTATUS Status;

PETHEREAD Thread;

if(*NtBuildNumber<=2195)

Status= PsLookupThreadByThreadId((PVOID)4, &Thread);

else

Status = PsLookupThreadByThreadId((PVOID)8, &Thread);

if(NT_SUCCESS(Status)) {

if(MmIsAddressValid (Tluead))

res=(PCHAR)*PULONG(PCHAR(Therad)+0x28);

if(MmIsAddressValid(res+8))

res = (PCHAR)*P ULON G(res+ 8 );

else

res = 0 ;

}

return res;

}

将两次扫描的结果对比,就能得到系统中被隐藏的进程.

基于交叉视图的检测方法优点是不论Rootkit使用了哪一层的隐蔽技术,检测程序都能够检测出被隐蔽的信息;缺点是检测程序需要使用比Rootkit更底层的检测方法.

3.2 基于内存扫描的检测方法

无论是修改函数的执行路径还是修改内核数据结构,Windows下Rootkit都通过改变内存中的数据实现信息的隐藏,因此通过内存扫描的方法就能够检测出Windows下的Rootkit.

(1)代码完整性扫描.代码完整性扫描针对修改程序执行的Rootkit,此类Rootkit主要功能通过修改函数人口指令、修改系统服务表、修改中断服务表甚至修改驱动对象的派遣函数实现.因此,通过检测代码的执行路径是否被修改就能判断系统是否安装了Rootkit.

扫描方法:检测程序读取所有可能被Rootkit修改过的代码,如果该代码所在的模块不在系统预定的模块地址空间范围中,就可以认为系统被安装了Rootkit.例如:如果系统服务表中NtDeviceIoControl()函数指针不在Ntoskml.exe模块的地址空间,则表示系统服务表已被Rootkit修改.

(2)系统模块扫描.有的 Rootkit并不修改函数的执行路径,而是直接修改内核数据对象达到隐蔽进程(或者驱动)的功能,然而被隐藏的进程(或者驱动)仍然在系统内存中.因此,通过扫描整个系统的内存单元,就可以得到系统中正在运行的进程(或者驱动)信息.例如,Windows操作系统中系统代码数据地址范围为0x80000000-OxFFFFFFFF,这样通过扫描这一段地址范围内的内存数据就能枚举系统中所有设备驱.

4 Windows下Rootkit检测思考

(1)操作系统一旦安装了Rootkit就进入了不可信任状态,系统中得到的任何数据可能经过Rootkit的修改.例如Hacker Defender通过挂钩NtReadVirtualMemory()来防止用户态的检测程序读取被挂钩函数的前几个字节.一旦有程序读取前几个字节,Hacker Defender立刻返回没有修改的内存值.

(2)尽管检测程序的内核部分得到了系统的真实信息,但是它和用户态的应用程序的通信也会被Rootkit监听到,甚至用于显示结果的GUI函数也会被Rootkit修改.

(3)从多个角度检测被Rootkit隐藏的信息.例如检测被隐藏进程时,可以使用挂钩SwapContext()函数的方法,也可以使用读取Csrss.exe句柄表的方法.因为Csrss.exe句柄表中也包含了系统中所有进程的信息.

随着计算机技术的发展,Rootkit及其相关的后门程序成为信息安全的严重威胁.由于Rootkit使用的技术也是常用的编程技术,这就使它们更难被检测出来.下一代Rootkit将使用什么技术,暂时还难下结论,Rootkit检测技术也必然随着Rootkit技术的发展而发展.

参考文献:

[1]周瑞丽,潘剑锋,谭小彬,奚宏生.应用专家系统开发Windows恶意代码检测系统的研究[J].信息安全与通信保密,2009(09).

[2]胡永涛,康学斌,李柏松.Windows Rootkit病毒进化与检测[J].信息网络安全,2009(09).

[3]刘哲元,戴冠中,王晓伶.基于文件系统异常的内核级Rootkit检测[J].计算机应用研究,2009(09).

[4]侯春明,陈斌.基于分层驱动的Windows内核rootkit关键技术[J].吉首大学学报(自然科学版),2009(09)

猜你喜欢

注册表调用线程
基于C#线程实验探究
基于国产化环境的线程池模型研究与实现
核电项目物项调用管理的应用研究
LabWindows/CVI下基于ActiveX技术的Excel调用
更上一层楼 用好注册表编辑器
浅谈linux多线程协作
注册表的便捷用法
基于系统调用的恶意软件检测技术研究
利用RFC技术实现SAP系统接口通信
注册表编辑器也玩“失忆”