首页
社区
课程
招聘
[求助]从ntosknrl.exe读取SSDT表的问题,菜鸟虚心求教
发表于: 2009-8-9 02:38 6978

[求助]从ntosknrl.exe读取SSDT表的问题,菜鸟虚心求教

2009-8-9 02:38
6978
看了看雪很多关于这个的话题,看来看去有点糊,看到多数的是把ntosknrl.exe按照内存对齐的方式载入继而处理的
         
        我自己的方法是将ntosknrl.exe直接文件映射,不按内存对齐的方式,然后通过导出表来定位 KeServiceDescriptorTable的RVA,进而将RVA转换为文件偏移,来定位该数据在文件中的结构
      已证实直到获取KeServiceDescriptorTable的RVA这一步还是成功的。但是后面的就不知道怎么处理了,因为听说KeServiceDescriptorTable是在KiInitSystem中被初始化的,所以本人不知道磁盘文件中读取的信息是否有用
     
      我的思路是获取KeServiceDescriptorTable的RVA后转换为文件偏移,那么读取该偏移处的数据便是KeServiceDescriptorTable结构中的第一个成员ServiceTableBase服务地址表的RVA,然后将该RVA加上内核中加载的ntosknrl.exe模块的基址,那么就得到了ServiceTableBase服务地址表在内存中的真实地址了,然后根据调用号来获取真实的系统服务函数地址

     不知道这个过程有什么问题,我自己觉得在定位ServiceTableBase服务地址表这个地方有问题,但是又不知道怎么不对,请高手指点一二

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (7)
雪    币: 722
活跃值: (123)
能力值: ( LV12,RANK:300 )
在线值:
发帖
回帖
粉丝
2
楼主说得很乱,有点语无伦次,虽然大概理解你要说什么……
获取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。

以上方法早已经有可用代码,网上搜一下再仔细看一下代码就会明白了。
2009-8-9 20:58
0
雪    币: 146
活跃值: (33)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
3
不好意思,由于水平有限,所以表述不清楚,请问网上这个方法是什么意思:

找到内核表地址 减去基址 就是这个地址在硬盘内核文件中的偏移了  
把文件指针指到这个文件偏移地址 或者映射内核文件 从该地址取4个字节 就是原始表在文件中的偏移位置  把它加上内核基址 最后 减掉一个映像加载地址 0x400000  就是原始的SSDT服务地址..

这里的内核表是指ServiceTableBase还是KeServiceDescriptorTable ??
2009-8-10 00:11
0
雪    币: 247
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
学习,膜拜,再学习
2009-8-10 00:25
0
雪    币: 522
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
5
有点眼熟...
是ring3定位表获取原使地址的方法.
内核表指的是stablebase
这个方法不可取 总的来说还是要用到驱动
所以还是按2楼说的内核方式获取原始地址吧。简单方便
2009-8-10 04:11
0
雪    币: 146
活跃值: (33)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
6
各位,R3下获取原始SDT可取,昨晚弄了一个晚上成功了
     从重定位中进行定位,感谢 轩辕小聪的帮助,也感谢各位的关注
2009-8-10 15:26
0
雪    币: 724
活跃值: (81)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
7
更暴力一点的方法:
    HMODULE hMod=LoadLibrary("ntoskrnl.exe");
    DWORD dwVA=(DWORD)GetProcAddress(hMod,"KeServiceDescriptorTable");
    此时的dwVA是重定位过的,取模块的ImageBase重新校正, 然后在模块中找 C7 05 XX XX XX XX即可。XX XX XX XX为校正后的KeServiceDescriptorTable地址。
2009-8-11 09:50
0
雪    币: 0
活跃值: (954)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
8
你如果第一次 读SDT表的话,还是先拿RING3练练!
2009-8-11 16:22
0
游客
登录 | 注册 方可回帖
返回
//