SSDT入门

SSDT入门一 SSDT 1 SSDT 看来是一个兵家必争之地 无论是安全软件还是恶意代码都在上面做着手脚 图 SystemModule 揭示了系统各模块之间的依赖关系 有所简化 nbsp 从图中可以看出 所有的 Win32API 调用最后都转移到了 ntdll dll 而 ntdll dll 又将其转移到了 ntoskrnl exe ntdll dll 是一个操作系

一:SSDT 【1】
SSDT看来是一个兵家必争之地,无论是安全软件还是恶意代码都在上面做着手脚。

 

例如,由kernel32.dll导出的Win32 API函数DeviceIoControl()最终会调用由ntdll.dll导出的NtDeviceIoControlFile()。

NtDeviceIoControlFile:
mov   eax, 38h
lea   edx, [esp+4]
int   2Eh
ret   28h




“魔术”数字0x38是一个分派ID;INT 2Eh指令将跳转到中断描述符表(Interrupt Descriptor Table,IDT)的0x2e位置上存放的中断处理例程(interrupt handler)中,分配器(dispatcher)利用它从用户模式进入内核模式。

从NtDeviceIoControlFile示例给出的反汇编代码可看出,INT 2Eh随同传入CPU寄存器EAX和EDX的两个参数一起被调用。处理INT 2Eh的代码必须确定每个调用将被分配到哪个函数。这就是提供EAX中的”魔术”数字–分派ID的原因。位于ntoskrnl.exe中的中断处理例程将EAX中的数值作为一个索引来查询一个特定的表。这个表被称作系统服务表(System Service Table, SST)该表对应的C结构体—SYSTEM_SERVICE_TABLE:
typedef struct _SYSTEM_SERVICE_TABLE
{

    PNTPROC  ServiceTable;   // array of entry points
    PDOWRD  CounterTable;   // array of usage counters
    DWORD   ServiceLimit;    // number of table entries
    PBYTE    ArgumentTable;  // array of byte counts
}SYSTEM_SERVICE_TABLE,*PSYSTEM_SERVICE_TABLE,PPSYSTEM_SERVICE_TABLE;





但是SST并不是源头,而且内核中还存在多个SST表,所以内核维护着另外一个表结构,该结构共有四个SST类型的数组,其中的前两个用于特定目的,头两个数组保留给了ntoskrnl.exe和Win32子系统(位于win32k.sys)中的内核模式部分(来自gdi32.dll和user32.dll的调用都通过Win32k的系统服务表(SST)进行分派)。ntolkrnl.exe导出了一个指针(符号为KeServiceDescriptorTable)指向其主服务描述符表(Main SDT),内核还维护了一个替代的SDT,其名称为KeServiceDescriptorTableShadow,但这个SDT并没有被导出。
这个表被称作服务描述符表(The Service Descriptor Tables, SDT)该表对应的C结构体—SERVICE_DESCRIPTOR_TABLE:
typedef struct _SERVICE_DESCRIPTOR_TABLE
{

    SYSTEM_SERVICE_TABLE ntoskrnl;  // ntoskrnl.exe ( native api )
    SYSTEM_SERVICE_TABLE win32k;    // win32k.sys (gdi/user support)
    SYSTEM_SERVICE_TABLE Table3;    // not used
    SYSTEM_SERVICE_TABLE Table4;    // not used
}SYSTEM_DESCRIPTOR_TABLE,*PSYSTEM_DESCRIPTOR_TABLE,PPSYSTEM_DESCRIPTOR_TABLE;





啰啰嗦嗦一大堆,简单说,内核维护着_SERVICE_DESCRIPTOR_TABLE这样一个SDT结构数据,即KeServiceDescriptorTable,里面保存着ntoskrnl.exe的SST结构数据(当然还包括其他SST),其中ServiceTable指向的是由ServiceLimit个函数指针构成的数组;当执行前面提到的NtDeviceIoControlFile示例代码时,内核找到KeServiceDescriptorTable,接着找到ntoskrnl.ServiceTable,该地址是函数指针数组的首地址,所以NtDeviceIoControlFile函数地址为[ServiceTable+0x38*4]。









SSDT Call Process

【图 SSDT Call Process】SSDT查找函数地址过程

NtCreateProcess_ID

【图 NtCreateProcess_ID】NtCreateProcess ID号

IceSword
【图 IceSword】IceSword检测到NtCreateProcess被Hook

 

四:SSDT访问
也许你现在已经迫不及待的想要操控一下SSDT,好消息是,ntolkrnl.exe导出了一个指针(符号为KeServiceDescriptorTable)指向其主服务描述符表(Main SDT),从处于内核模式的模块中访问主服务描述符表是非常容易,你只需要两个C指令,首先是由extern关键字修饰的变量说明,这告诉链接器该变量并不包含在此模块中,而且不需要在链接时解析相应的符号名称,当该模块被加载到进程的地址空间后,针对该符号的引用才会动态连接到相应的模块中:
// Import SDT pointer
extern PSERVICE_DESCRIPTOR_TABLE KeServiceDescriptorTable;

其次是创建一个对KeServiceDescriptorTable的引用:
// Create SDT reference
PSERVICE_DESCRIPTOR_TABLE psdt = KeServiceDescriptorTable;

现在,你的内核模块就可以访问SSDT数据了。

到此为止,不再深入,因为文章和文章的作者都是入门级的,至于后续SSDT Hook之类的话题,你就自己玩吧。【4】


五:附录

对SSDT也只是有个初步了解,得益于一些参考资料:

【1】本文关于SSDT的描述,基本源于<<Undocumented Windows 2000 Secrets>>一书的第二章,所以针对的是Windows 2000系统,其中文翻译参见
【Undocumented Windows 2000 Secrets 中文翻译】http://blog.csdn.net/Kendiv/category/88780.aspx

【2】内核调试工具安装包和符号文件安装包,参见
【Debugging Tools for Windows】http://www.microsoft.com/whdc/DevTools/Debugging/default.mspx

【3】搭建Windbg和VMware的内核调试环境,参见
【使用WinDbg和VMware调试NDIS中间层驱动程序】http://www.cppblog.com/aurain/archive/2009/01/04/71138.html

【4】关于SSDT Hook的文章比较多,<<简单说说SSDT>>是其中一篇,比较容易理解,参见
【简单说说SSDT】http://icylife.net/yunshu/show.php?id=435
























版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/233150.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Linux操作系统的VI命令[通俗易懂]

    Linux操作系统的VI命令[通俗易懂]Linux操作系统的VI命令,VI命令详情,命令模式、插入模式和底行模式;vi命令如何查找、替换、删除、撤销、光标定位;vi命令如何切换模式。

    2022年7月3日
    26
  • 在java的方法中定义一个常量_c语言中常量和常量表达式的区别

    在java的方法中定义一个常量_c语言中常量和常量表达式的区别如果可能,修改getIndex()方法,使其返回枚举而不是整数.如果无法做到这一点,则需要将索引映射到枚举元素:鉴于以下枚举:publicenumIndex{ONE,TWO,THREE}您可以使用将索引映射到枚举元素Index.values()[index]给定你的方法IntegergetIndex(),你可以做类似的事情switch(Index.values()[getIndex()])…

    2022年9月29日
    2
  • cocoapods安装过程_如何开发ios应用

    cocoapods安装过程_如何开发ios应用原文链接: iOS开发-CocoaPods安装和使用教程本文是对原文一些错误的修正已经添加了自己的理解。CocoaPods安装和使用教程Code4App原创文章。转载请注明出处:http://code4app.com/article/cocoapods-install-usage目录CocoaPods是什么?如何下载和安装CocoaPods?如何使用CocoaPods?场景1:利用CocoaP

    2025年8月22日
    2
  • Java集合之WeakHashMap[通俗易懂]

    Java集合之WeakHashMap[通俗易懂]WeakHashMap继承于AbstractMap,同时实现了Map接口。和HashMap一样,WeakHashMap也是一个散列表,存储的内容也是键值对key-value映射,并且键和值都可以是null。WeakHashMap的键都是弱键,给定一个键,其映射的存在并不阻止垃圾回收器对该键的丢弃,使该键成为可终止,然后被回收。弱键的原理就是Entry继承了WeakReference接口,当G

    2022年5月31日
    30
  • sqlmap命令详解_sql命令大全

    sqlmap命令详解_sql命令大全SQLMAP命令详解 Options(选项):–version显示程序的版本号并退出-h,–help显示此帮助消息并退出-vVERBOSE详细级别:0-6(默认为1)Target(目标):以下至少需要设置其中一个选项,设置目标URL。-dDIRECT直接连接到数据库。-uURL,–url=URL目标URL。-lLIST…

    2025年5月23日
    2
  • linux命令之pstack[通俗易懂]

    linux命令之pstack[通俗易懂]很多时候我们想知道在Linux下后台程序到底运行到哪里了,卡住了吗,出错了吗,最简单的我们会使用#psauxf|grep来查看后台程序的状态,可是如果想知道的更多,那就可以用到pstack这个命令了。首先举一个简单的例子(test.c)来引出这个命令 #include#include#includevoid*thread_proc(void*data)

    2025年11月18日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号