Rootkit For Windows:Rookit技术资料

互联网 | 编辑: 杨剑锋 2007-08-20 09:15:00转载 一键看全文

Rookit技术分析三.rootkit的一些以公开的隐藏技术以及检测技术。
1.    删除进程双项链上的进程对象。
ps:用的似乎很多,连现在的一些盗号的程序也利用上了
现在所有人查看进程一般都是通过任务管理器(taskmgr.exe)来查看。了解一些编程知识的人都知道,任务管理器枚举进程信息是靠的NtQuerySystemInformation 也就是ZwQuerySystemInformation 函数。众所周知,这个Native Api (本机API)枚举进程是要通过进程活动链表的。我们就来看看这个结构。
typedef struct _OBJECT_ATTRIBUTES
{
ULONG Length;
HANDLE RootDirectory;
PUNICODE_STRING ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor;
PVOID SecurityQualityOfService;
} OBJECT_ATTRIBDTES, *POBJECT_ ATTRIBUTES;

typedef struct _IO_STATUS_BLOCK
{
NTSTATDS Status;
ULONG Information;
}IO_STATUS_BLOCK , * PIO_STATUS_BLOCK ;

typedef struct _LIST_ENTRY
{
Struct _LIST_ENTRY *Flink;
Struct _LIST_ENTRY *Blink;
}LIST_ENTRY, *PLIST_ENTRY;
双向链表的典型例子就是进程和线程链。内部变量PsActiveProcessHead是一个LIST_ENTRY结构,在ntoskrnl.exe的数据段中,指定了系统进程列表的第一个成员。仔细想想,如果我们将进程对象从进程双向链表中移除,那么调用NtQuerySystemInformation来枚举进程的任务管理器taskmgr.exe中就不会看到我们的进程了。那么就有人会担心了。如果进程从链表中删除,那还会被运行么?答案是,会。因为windows的ds,也就是线程分派器,也叫任务调度分配器(dispatcher scheduler)使用的是另一个数据结构,也就是说,进线程是否被调度处理与进程双向活动链表无关,不会被CPU忽略,不必担心。2003年pjf在安全焦点上提出的就是这个方法且给出了这个方法的实现代码。文章结尾处的参考资料中我会给出这个文章的URL。
2.修改系统调用表(sst)
rootkit可以通过在系统调用表中添加添加自己的服务然后运行想要执行的任务。He4HookInv就是这样。He4HookInv也是一个比较有名的windows rootkit。下面我们来看看He4HookInv具体的实现过程。在以前人们不知道它是如何实现的这些,一些介绍rootkit的文章也是提到一点,不过只知道是修改的SST,细节也没有过多描述。直到phrack杂志公布了He4HookInv的一些细节。
He4Hook在不同版本所使用的方法是有所不同的。公布的方法中有两种。这里只说说第一种方法。如果想了解第二种方法和原版就看文章结尾的参考资料吧(phrack的连接)。
ZwCreateFile, ZwOpenFile,IoCreateFile,ZwQueryDirectoryFile, ZwClose 这些函数在Ntdll.dll中是这样实现的。
mov eax, NumberFunction
lea edx, [esp+04h]
int 2eh; Syscall interface

当然Ntdll.dll是一个main gate,真正的函数调用是在Ntoskrnl中完成的。关于本机API的,可以看参考资料中我写的另一篇文章《浅析本机API》。
EAX中储存着系统调用号。int 2Eh代表转到中断描述符表IDT位置0x2E处的中断处理程序。中断处理程序把EAX里的值作为查找表中的索引,去找到最终的目标函数。这个表就是系统服务表SST。ntoskrnl通过KeServiceDescriptorTable符号,导出了主要SDT的一个指针。我们可以通过KeServiceDescriptorTable来访问SDT。现在来看看KeServiceDescriptorTable的结构。

typedef struct SystemServiceDescriptorTable
{
SSD SystemServiceDescriptors[4];
} SSDT, *LPSSDT;
Other structures:
typedef VOID *SSTAT[];
typedef unsigned char SSTPT[];
typedef SSTAT *LPSSTAT;
typedef SSTPT *LPSSTPT;
typedef struct SystemServiceDescriptor
{
LPSSTAT lpSystemServiceTableAddressTable;
ULONG dwFirstServiceIndex;
ULONG dwSystemServiceTableNumEntries;
LPSSTPT lpSystemServiceTableParameterTable;
} SSD, *LPSSD;
KeServiceDescriptorTable 指向的DescriptorTable 只能从内核模式访问。在用户模式下,有一个未输出的KeServiceDescriptorTableShadow 。底层服务有 :
KeServiceDescriptorTable->SystemServiceDescriptors[0]
KeServiceDescriptorTableShadow->SystemServiceDescriptors[0]
内核模式图形化用户界面服务(GUI):
KeServiceDescriptorTableShadow->SystemServiceDescriptors[1]
在WinNt4(SP3-6)和Win2k build 2195之前的所有版本中,DescriptorTable的其他的元素在写入时是空闲的,表中每个元素为SSID结构,包含有以下数据:
lpSystemServiceTableAddressTable 指针表,当相关系统调用启用时,它指向被调用的函数内存地址数组。

dwFirstServiceIndex 指向第一个函数的开始地址
dwSystemServiceTableNumEntries    表中服务数目
lpSystemServiceTableParameterTable    表示出入栈的字节数目

为了取得系统调用,He4HookInv 用一个指针替代了KeServiceDescriptorTable->SystemServiceDescriptos[0].lpSystemServiceTableAddressTableIn中存储的地址,而指向其所属表。

你可以通过在系统调用表中添加自己的服务而界入He4HookInv。He4HookInv将更新以下两表:
- KeServiceDescriptorTable
- KeServiceDescriptorTableShadow.
但是,如果He4HookInv只更新KeServiceDescriptorTable ,新的服务项在用户模式下将不能被调用。为了定位KeServiceDescriptorTable Shadow ,将用到以下技术:KeAddSystemServiceTable 函数能向内核驱动层添加服务,而且能向两个表中同时添加。如果它的0指示符是相同的,通过扫描KeAddSystemServiceTable 函数代码就可以找到shadow 表的地址,具体可以在He4HookInv.c文件中的FindShadowTable(void)函数中查看是怎么实现的。如果这个办法失败,He4Hook使用一个硬编码的地址((KeServiceDescriptorTable-0x230)来定位ShadowTable的位置.这个地址从WinNT-sp3来就没有变过.另外一个问题是如何找到系统服务的编号,这个其实很简单,由于系统服务的函数体都具有以下形式(mov eax, NumberFunction),所以我们只要把系统服务的函数地址加上1bytes,就可以得到系统服务对应的编号。
He4HookInv利用的第二个方法就是修改文件系统驱动中DRIVER_OBJECT的回调表,这里就不在详细说明了。(下一页)  

提示:试试键盘 “← →” 可以实现快速翻页 

一键看全文

本文导航

相关阅读

每日精选

点击查看更多

首页 手机 数码相机 笔记本 游戏 DIY硬件 硬件外设 办公中心 数字家电 平板电脑