王新年吧 关注:13贴子:314
  • 3回复贴,共1

Rootkit For Windows[1]

只看楼主收藏回复

 Rootkit For Windows 
*************************
一.先说几句与技术无关的话。
现在很多人对rootkit认识不够,可以说空白。而此愚文的目的就是让菜鸟认识rootkit→了解rootkit。也让一些想研究它的人把这篇文章当作一个参考或是入门级的指导。文章中介绍的rootkit的隐藏方法只是一部分。还有很多技术没有提到,另外还有一些未公开的技术。有些地方我未引用代码,因为不想占用过多的篇幅。以免有玩弄代码的嫌疑,不过写完以后还是觉得代码太多,请个位见谅。一-三的内容适合菜鸟看,也许第四部分之后对很多人来说都有些意义吧。如果高手不幸看到了,请准备好,不要吐到屏幕上或身上。
以往的文章写的比较乱,而且格式不公正,这样的形式写文章也是第一次。以前文章中引用代码和文字也没有详细说明,再此也对作者表示谦意。感谢XX提的这个建议。
今天是9月11号,庆祝一下童童的生日。顺便为911事件中的遇难者祈祷。同时也感谢MGF病毒的作者指点。
*************************
二.简单的说说rootkit.
Rootkit的历史已经很悠久了。存在于windows,unix,linux等操作系统中,不只局限在windows,此文我只以windows平台为例来说rootkit。Root在英语中是根,扎根的意思,kit是包的意思。rootkit我们可以把它理解成一个利用很多技术来潜伏在你系统中的一个后门,并且包含了一个功能比较多的程序包,例如有、清除日志,添加用户,b7cmdshell,添加删除启动服务等功能。当然它的设计者也要用一些技术来隐藏自己,确保不被发现。隐藏包括隐藏进程,隐藏文件,端口,或句柄,注册表的项,键值等等。总之,写rootkit的人是狡尽乳汁利用很多办法不被发现。
现在人们最熟悉的windows rootkit 就是hacker defender和ntrootkit了,还有使用了baiyuanfan在XCON提出的ring3 rootkit新思路的byshell,呵呵。而linux下就是knark了。
*************************
三.rootkit的一些以公开的隐藏技术以及检测技术。
1. 删除进程双项链上的进程对象。
ps:用的似乎很多,连现在的一些盗号的程序也利用上了
现在所有人查看进程一般都是通过任务管理器(taskmgr.exe)来查看。了解一些编程知识的人都知道,任务管理器枚举进程信息是靠的NtQuerySystemInformation 也就是ZwQuerySystemInformation 函数。众所周知,这个Native Api (本机API)枚举进程是要通过进程活动链表的。我们就来看看这个结构。
typedef struct _OBJECT_ATTRIBUTES
{
ULONG Length;
HANDLE RootDirectory;
PUNICODE_STRING ObjectName;
ULONG Attributes;
PVOID SecurityDescrīptor;
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的一些细节。



IP属地:湖北1楼2007-12-31 12:44回复
    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通过KeServiceDescrīptorTable符号,导出了主要SDT的一个指针。我们可以通过KeServiceDescrīptorTable来访问SDT。现在来看看KeServiceDescrīptorTable的结构。
    typedef struct SystemServiceDescrīptorTable
    {
    SSD SystemServiceDescrīptors[4];
    } SSDT, *LPSSDT;
    Other structures:
    typedef VOID *SSTAT[];
    typedef unsigned char SSTPT[];
    typedef SSTAT *LPSSTAT;
    typedef SSTPT *LPSSTPT;
    typedef struct SystemServiceDescrīptor
    {
    LPSSTAT lpSystemServiceTableAddressTable;
    ULONG dwFirstServiceIndex;
    ULONG dwSystemServiceTableNumEntries;
    LPSSTPT lpSystemServiceTableParameterTable;
    } SSD, *LPSSD;
    KeServiceDescrīptorTable 指向的DescrīptorTable 只能从内核模式访问。在用户模式下,有一个未输出的KeServiceDescrīptorTableShadow 。底层服务有 :
    KeServiceDescrīptorTable->SystemServiceDescrīptors[0]
    KeServiceDescrīptorTableShadow->SystemServiceDescrīptors[0]
    内核模式图形化用户界面服务(GUI):
    KeServiceDescrīptorTableShadow->SystemServiceDescrīptors[1]
    在WinNt4(SP3-6)和Win2k build 2195之前的所有版本中,DescrīptorTable的其他的元素在写入时是空闲的,表中每个元素为SSID结构,包含有以下数据:
    lpSystemServiceTableAddressTable 指针表,当相关系统调用启用时,它指向被调用的函数内存地址数组。
    dwFirstServiceIndex 指向第一个函数的开始地址
    dwSystemServiceTableNumEntries 表中服务数目
    lpSystemServiceTableParameterTable 表示出入栈的字节数目
    为了取得系统调用,He4HookInv 用一个指针替代了KeServiceDescrīptorTable->SystemServiceDescrīptos[0].lpSystemServiceTableAddressTableIn中存储的地址,而指向其所属表。
    你可以通过在系统调用表中添加自己的服务而界入He4HookInv。He4HookInv将更新以下两表:
    - KeServiceDescrīptorTable
    - KeServiceDescrīptorTableShadow.
    但是,如果He4HookInv只更新KeServiceDescrīptorTable ,新的服务项在用户模式下将不能被调用。为了定位KeServiceDescrīptorTable Shadow ,将用到以下技术:KeAddSystemServiceTable 函数能向内核驱动层添加服务,而且能向两个表中同时添加。如果它的0指示符是相同的,通过扫描KeAddSystemServiceTable 函数代码就可以找到shadow 表的地址,具体可以在He4HookInv.c文件中的FindShadowTable(void)函数中查看是怎么实现的。如果这个办法失败,He4Hook使用一个硬编码的地址((KeServiceDescrīptorTable-0x230)来定位ShadowTable的位置.这个地址从WinNT-sp3来就没有变过.另外一个问题是如何找到系统服务的编号,这个其实很简单,由于系统服务的函数体都具有以下形式(mov eax, NumberFunction),所以我们只要把系统服务的函数地址加上1bytes,就可以得到系统服务对应的编号。
    He4HookInv利用的第二个方法就是修改文件系统驱动中DRIVER_OBJECT的回调表,这里就不在详细说明了。
    


    IP属地:湖北2楼2007-12-31 12:44
    回复
      2025-05-31 03:31:44
      广告
      NTSTATUS NtQueryDirectoryFile(
      IN HANDLE FileHandle,
      IN HANDLE Event OPTIONAL,
      IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
      IN PVOID ApcContext OPTIONAL,
      OUT PIO_STATUS_BLOCK IoStatusBlock,
      OUT PVOID FileInformation,
      IN ULONG FileInformationLength,
      IN FILE_INFORMATION_CLASS FileInformationClass,
      IN BOOLEAN ReturnSingleEntry,
      IN PUNICODE_STRING FileName OPTIONAL,
      IN BOOLEAN RestartScan
      );
      在《The Undocumented Functions-Microsoft Windows NT_2000》中对这些参数的描述
      FileHandle
      HANDLE to File Object opened with FILE_DIRECTORY_FILE option and FILE_LIST_DIRECTORY access. 
      Event
      Optional HANDLE to Event Object signaled after query complete. 
      ApcRoutine
      Optinal pointer to user's APC routine queued after query complete. 
      ApcContext
      Parameter for ApcRoutine. 
      IoStatusBlock
      IO result of call. 
      FileInformation
      User's allocated buffer for output data. 
      Length
      Length of FileInformation buffer, in bytes. 
      FileInformationClass
      Information class. Can be one of: 
      FileDirectoryInformation 
      FileFullDirectoryInformation 
      FileBothDirectoryInformation 
      FileNamesInformation 
      FileOleDirectoryInformation 
      ReturnSingleEntry
      If set, only one entry is returned. 
      FileMask
      If specified, only information about files matches this wildchar mask will be returned. 
      RestartScan
      Used with ReturnSingleEntry parameter. If set, NtQueryDirectoryFile continue enumeration after
      last enumerated element in previous call. If no, returns the first entry in directory. 
      与隐藏文件相关的重要参数是FileHandle,FileInformation,FileInformationClass.
      FileInformationClass中的相关信息过多,只说其中重要的四个。
      FileDirectoryInformation
      FileFullDirectoryInformation 
      FileBothDirectoryInformation 
      FileNamesInformation 
      要写入FileInformation的FileDirecoryInformation记录的结构:
      typedef struct _FILE_DIRECTORY_INFORMATION { 
      ULONG NextEntryOffset;
      ULONG Unknown;
      LARGE_INTEGER CreationTime;
      LARGE_INTEGER LastAccessTime;
      LARGE_INTEGER LastWriteTime;
      LARGE_INTEGER ChangeTime;
      LARGE_INTEGER EndOfFile;
      LARGE_INTEGER AllocationSize; 
      ULONG FileAttributes;
      ULONG FileNameLength;
      WCHAR FileName[1];
      } FILE_DIRECTORY_INFORMATION, *PFILE_DIRECTORY_INFORMATION;

      FileFullDirectoryInformation:
      typedef struct _FILE_FULL_DIRECTORY_INFORMATION {
      ULONG NextEntryOffset;
      ULONG Unknown;
      LARGE_INTEGER CreationTime;
      LARGE_INTEGER LastAccessTime;
      LARGE_INTEGER LastWriteTime;
      LARGE_INTEGER ChangeTime;
      LARGE_INTEGER EndOfFile;
      LARGE_INTEGER AllocationSize;
      ULONG FileAttributes;
      ULONG FileNameLength;
      ULONG EaInformationLength;
      WCHAR FileName[1];
      } FILE_FULL_DIRECTORY_INFORMATION, *PFILE_FULL_DIRECTORY_INFORMATION;

      FileBothDirectoryInformation:
      typedef struct _FILE_BOTH_DIRECTORY_INFORMATION { 
      ULONG NextEntryOffset;
      ULONG Unknown;
      LARGE_INTEGER CreationTime;
      LARGE_INTEGER LastAccessTime;
      LARGE_INTEGER LastWriteTime;
      LARGE_INTEGER ChangeTime;
      LARGE_INTEGER EndOfFile;
      LARGE_INTEGER AllocationSize;
      ULONG FileAttributes;
      ULONG FileNameLength;
      ULONG EaInformationLength;
      UCHAR AlternateNameLength;
      WCHAR AlternateName[12];
      WCHAR FileName[1];
      


      IP属地:湖北4楼2007-12-31 12:44
      回复
        • 113.132.226.*
        bd,主要意思写的很好理解,谢谢


        7楼2009-09-08 08:27
        回复