楼主说得很乱,有点语无伦次,虽然大概理解你要说什么……
获取KeServiceDescriptorTable的RVA后转换为文件偏移,那么读取该偏移处的数据便是KeServiceDescriptorTable结构中的第一个成员ServiceTableBase服务地址表的RVA,然后将该RVA加上内核中加载的ntosknrl.exe模块的基址
在初始化之前,ntoskrnl.exe文件的KeServiceDescriptorTable处并没有填入ServiceTableBase服务地址表的值,所以你直接从文件中的该位置读取是读取不到的。
只有在内核中的ntoskrnl.exe映像中的KeServiceDescriptorTable处才是当前的ServiceTableBase服务地址表的指针。
方法一般分为Ring3下读取原始SSDT表和Ring0下读取原始SSDT表两种思路。
1.Ring3下
此时由于没有办法直接访问内核中的KeServiceDescriptorTable,也不能直接得到其中ServiceTableBase服务地址表的指针,只能解析ntoskrnl.exe文件。
那么怎么通过解析ntoskrnl.exe文件来得到这个地址呢?
因为该表是在KiInitSystem中初始化的,KiInitSystem中有这么一行:
INIT:005EF2F4 C7 05 20 B5 48 00 B0 D8 40 00 mov ds:_KeServiceDescriptorTable, offset _KiServiceTable
只要能够定位这行代码,就知道了_KiServiceTable的位置,从而直接从ntoskrnl.exe文件中读取原始SSDT。
如何定位这行代码,普遍的方法是读取ntoskrnl.exe文件的重定位表。因为这行代码中的KeServiceDescriptorTable这个地址值需要重定位,因此对应项目必定在重定位表中。
Ring3程序通过遍历ntoskrnl.exe文件的重定位表,找到以上命令,从而得到_KiServiceTable的位置,进行得到原始的SSDT,再经重定位后传给内核驱动进行还原SSDT。
2.Ring0下
Ring0下就简单了,可以直接读取到_KiServiceTable的值,这样驱动直接读取ntoskrnl.exe中相应位置就可以得到原始的SSDT,经重定位后用于还原SSDT。
以上方法早已经有可用代码,网上搜一下再仔细看一下代码就会明白了。