Windows2003 内核级进程隐藏、侦测技术(3)
作者:佚名; 更新时间:2014-12-05
}

    }

CloseServiceHandle(schService);

    CloseServiceHandle(hSCManager);

    return TRUE;

}

  以上对驱动程序大致框架做了一个非常简单的介绍,这仅仅是驱动程序中的一个”Hello World!”。驱动程序是相当复杂的,由于我们只是利用驱动程序的特权,对windows内核进行修改,所以就不对驱动驱动程序进行深入讨论了。

  通过Hook SSDT (System Service Dispath Table) 隐藏进程

  1.原理介绍:

  Windows操作系统是一种分层的架构体系。应用层的程序是通过API来访问操作系统。而API又是通过ntdll里面的核心API来进行系统服务的查询。核心API通过对int 2e的切换,从用户模式转换到内核模式。2Eh中断的功能是通过NTOSKRNL.EXE的一个函数KiSystemService()来实现的。在你使用了一个系统调用时,必须首先装载要调用的函数索引号到EAX寄存器中。把指向参数区的指针被保存在EDX寄存器中。中断调用后,EAX寄存器保存了返回的结果。KiSystemService()是根据EAX的值来决定哪个函数将被调用。而系统在SSDT中维持了一个数组,专门用来索引特定的函数服务地址。在Windows 2000中有一个未公开的由ntoskrnl.exe导出的KeServiceDescriptorTable变量,我们可以通过它来完成对SSDT的访问与修改。KeServiceDescriptorTable对应于一个数据结构,定义如下:

typedef struct SystemServiceDescriptorTable
{
    UINT    *ServiceTableBase;
    UINT    *ServiceCounterTableBase;
    UINT    NumberOfService;
    UCHAR    *ParameterTableBase;
}SystemServiceDescriptorTable,*PSystemServiceDescriptorTable;

  其中ServiceTableBase指向系统服务程序的地址(SSDT),ParameterTableBase则指向SSPT中的参数地址,它们都包含了NumberOfService这么多个数组单元。在windows 2000 sp4中NumberOfService的数目是248个。

  我们的任务管理器,是通过用户层的API来枚举当前的进程的。Ring3级枚举的方法:

• PSAPI

– EnumProcesses()

• ToolHelp32

– Process32First()

- Process32Next()

  来对进程进行枚举。而她们最后都是通过NtQuerySystemInformation来进行查询的。所以我们只需要Hook掉NtQuerySystemInformation,把真实NtQuerySystemInformation返回的数进行添加或者是删改,就能有效的欺骗上层API。从而达到隐藏特定进程的目的。

  2. Hook

  Windows2000中NtQuerySystemInformation在SSDT里面的索引号是0x97,所以只需要把SSDT中偏移0x97*4处把原来的一个DWORD类型的读出来保存一个全局变量中然后再把她重新赋值成一个新的Hook函数的地址,就完成了Hook。

OldFuncAddress = KeServiceDescriptorTable-> ServiceCounterTableBase[0x97];

KeServiceDescriptorTable-> ServiceCounterTableBase[0x97] = NewFuncAddress;

  在其他系统中这个号就不一定一样。所以必须找一种通用的办法来得到这个索引号。在《Undocument Nt》中介绍了一种办法可以解决这个通用问题,从未有效的避免了使用硬编码。在ntoskrnl 导出的 ZwQuerySystemInformation中包含有索引号的硬编码:

kd> u ZwQuerySystemInformation

804011aa    b897000000      mov         eax,0x97

804011af    8d542404        lea         edx,[esp+0x4]

804011b3    cd2e            int         2e

804011b5    c21000          ret         0x10

  所以只需要把ZwQuerySystemInformation入口处的第二个字节取出来就能得到相应的索引号了。例如:

ID = *(PULONG)((PUCHAR)ZwQuerySystemInformation+1);

RealZwQuerySystemInformation=((PServiceDescriptorTableEntry)KeServiceDescriptorTable)->ServiceTableBase[ID]);

((PServiceDescriptorTableEntry)KeServiceDescriptorTable)->ServiceTableBase[ID] = HookZwQuerySystemInformation;

  3.对NtQuerySystemInformation返回的数据进行删改

NtQuerySystemInformation的原型:

NtQuerySystemInformation(

        IN ULONG SystemInformationClass,   //查询系统服务类型

        IN PVOID SystemInformation,        //接收系统信息缓冲区

     IN ULONG SystemInformationLength,   //接收信息缓冲区大小         OUT PULONG ReturnLength);       //实际接收到的大小

  NtQuerySystemInformation可以对系统的很多状态进行查询,不仅仅是对进程的查询,通过SystemInformationClass号来区分功能,当SystemInformationClass等于5的时候是在进行进程的查询。此时返回的SystemInformation 是一个 _SYSTEM_PROCESSES结构。

struct _SYSTEM_PROCESSES

{

    ULONG NextEntryDelta;   //下一个进程信息的偏移量,如果为0表示无一个进程信息

    ULONG ThreadCount;     //线程数量

    ULONG Reserved[6];     //

    LARGE_INTEGER CreateTime;      //创建进程的时间

    LARGE_INTEGER UserTime;         //进程中所有线程在用户模式运行时间的总和

    LARGE_INTEGER KernelTime;      //进程中所有线程在内核模式运行时间的总和

    UNICODE_STRING ProcessName;     //进程的名字

    KPRIORITY

核心期刊快速发表
Copyright@2000-2030 论文期刊网 Corporation All Rights Reserved.
《中华人民共和国信息产业部》备案号:ICP备07016076号;《公安部》备案号:33010402003207
本网站专业、正规提供职称论文发表和写作指导服务,并收录了海量免费论文和数百个经国家新闻出版总署审批过的具有国内统一CN刊号与国际标准ISSN刊号的合作期刊,供诸位正确选择和阅读参考,免费论文版权归原作者所有,谨防侵权。联系邮箱:256081@163.com