首页
社区
课程
招聘
[求助]SSDT 和Shadow SSDT
发表于: 2009-10-4 11:16 13812

[求助]SSDT 和Shadow SSDT

2009-10-4 11:16
13812
假设.有一个目标进程A..

在驱动中首先获取其EPROCESS..

然后用这个PsGetNextProcessThread取出其线程..

然后取出ETHREAD...也等同于KTHREAD..(是第一个字段).

然后关键就是这个ServiceTable..字段..

关于这个指针..ShadowSSDT Hook系列的文章会说.如果其不是GUI进程则此字段不会指向ShadowSSDT (也就是KeSSSDT的第二项)...

问题:
现在反过来..如果是GUI进程.已经指向Shadow SSDT..那么它调用SSDT内的函数.(比如它CreateFile一下.最终还是需要SSDT内函数...)..这个时候系统是怎么处理的?

问题二..如果其是CUI进程.指向了SSDT.那么.如果调用ShadowSSDT内函数..又是如何切换的.和问题一类似.

问题三..

如果修改其当前的地址..那么切换的时候.系统还知道切换到那里吗?

或者说.如何让系统指导.该切换到那里?

十分感谢..

[课程]Linux pwn 探索篇!

收藏
免费 0
支持
分享
最新回复 (8)
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
2
好象一直以来我们所说的ShadowSSDT的概念和系统中的KeServiceDescriptorTableShadow有一点出入,我们所说的专指GUI ServiceTable这个表,而它实际上只是KeServiceDescriptorTableShadow的一部分而已
正常情况下,ETHREAD中的ServiceTable,要么指向KeServiceDescriptorTable,要么指向KeServiceDescriptorTableShadow

答问题一:KeServiceDescriptorTableShadow中其实是四张表(后两张无效),第一张和KeServiceDescriptorTable中的那个是一样的,叫做KiServiceTabe,第二张才是真正的GUI ServiceTable,名字叫W32pServiceTable,所以不论是不是GUI线程,它的ServiceTable其实都包含有KiServiceTable这张表,所以调用win32服务当然是没有问题的,比如调用CreateFile时KiFastCallEntry会根据NtCreateFile的ServiceIndex来判断应该使用哪张表,ServiceIndex大于0x1000则用第二张表

答问题二:
有个函数叫做PsConvertToGuiThread,用来完成你所说的工作~~
NTSTATUS
PsConvertToGuiThread(
    VOID
    )

/*++

Routine Description:

    This function converts a thread to a GUI thread. This involves giving the
    thread a larger variable sized stack, and allocating appropriate w32
    thread and process objects.
*/

答问题三:
你说的是直接修改ETHREAD->ServiceTable这个字段的值吗?可以修改,在系统调用进入KiFastCallEntry时,会从当前线程的KTHREAD中取出这个表然后使用,如果修改的话,保证你提供的地址是有效的而且包含了正确的系统服务表就可以了,有一篇文章叫做《Hide your SSDT Hooks》,就是这么做的~~
2009-10-4 11:58
1
雪    币: 412
活跃值: (30)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
3
强大的achillis
2009-10-4 12:43
0
雪    币: 7992
活跃值: (2566)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
4
首先十分感谢一楼大牛的指导..

不过.我看了你的说法后.反而迷糊了..

为什么呢.

我的个人理解是.

typedef struct _SYSTEM_SERVICE_TABLE
{
        PVOID   ServiceTableBase;                        // SSDT (System Service Dispatch Table)的基地址
        PULONG  ServiceCounterTableBase;        // 用于checked builds, 包含SSDT中每个服务被调用的次数
        ULONG   NumberOfService;                        // 服务函数的个数, NumberOfService*4 就是整个地址表的大小
        ULONG   ParamTableBase;                                // SSPT (System Service Parameter Table)的基地址
} SYSTEM_SERVICE_TABLE, *PSYSTEM_SERVICE_TABLE;

typedef struct _SERVICE_DESCRIPTOR_TABLE
{
        SYSTEM_SERVICE_TABLE   ntoskrnl;        // ntoskrnl.exe的服务函数
        SYSTEM_SERVICE_TABLE   win32k;                // win32k.sys的服务函数,(gdi.dll/user.dll的内核支持)
        SYSTEM_SERVICE_TABLE   NotUsed1;
        SYSTEM_SERVICE_TABLE   NotUsed2;
} SYSTEM_DESCRIPTOR_TABLE, *PSYSTEM_DESCRIPTOR_TABLE;

PSYSTEM_DESCRIPTOR_TABLE 才是真正的 KeServiceDescriptorTable (这也是系统导出的.可惜只导出部分) SSDT只是这个KSSDT中的第一项.(这也是为什么好多人偷懒.总喜欢直接强制转换指针.把KSSDT直接当SSDT用也是对的)..Shadow SSDT是这个表中的第二项..但很可惜.没导出.用的时候不能直接操作.得自己搜地址.赋值和强制转换一次才行. (比如 PShadowSSDT=(ShadowSSDT结构)地址.)..

所以.我看了Shadow SSDT Hook系列的文章后觉得.如果指向了ShadowSSDT就认为.是指向了.第二项...

看来或许我的理解是错的吧..是不是这个指针直接指向的是 KeSSDT.(也就是他们全部)..

如果是..那么就又迷糊了.既然都包含全部了.为什么说指向第一项SSDT为主的时候.ShadowSSDT地址却是无效的?(这也是ShadowSSDT HOOK文章上经常说的)..是不是因为它没导出?还是?

..至于第三个问题.我的本意是说.如果线程指向SSDT..我就把SSDT移动一个位置.把修改指向.不知道万一这个线程要求立刻切换到ShadowSSDT内.这个时候系统怎么才能知道该切换到那..呵呵..

不过我想到这里.感觉.如果是直接指向他们全部..那么就一切好说了.不知道是不是这样??谢谢.
2009-10-4 13:08
0
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
5
正常情况下,ETHREAD中的ServiceTable,要么指向KeServiceDescriptorTable,要么指向KeServiceDescriptorTableShadow,注意这句话啊
ETHREAD->ServiceTable从来不会直接接向GUI的那张表,而是指向整体的KeServiceDescriptorTableShadow,所以你以前可能理解错了,自己用windbg观察就知道了
系统中既有KeServiceDescriptorTable也有KeServiceDescriptorTableShadow,他们各司其职,非GUI线程使用KeServiceDescriptorTable,GUI线程使用KeServiceDescriptorTableShadow,这是Windows的设计。非GUI线程如果要调用GUI服务就会用PsConvertToGuiThread把ETHREAD->ServiceTable切换为KeServiceDescriptorTableShadow,而GUI线程调用普通的Win32服务时并不需要切换,因为KeServiceDescriptorTableShadow中已经有个这张表,所以KeServiceDescriptorTableShadow可以看成是KeServiceDescriptorTable的增强版
KeServiceDescriptorTable中第二张表之所以无效,是因为非GUI线程根本不需要这张表,所以没有填充

你的第三个问题,描述得还是不太清楚啊。到底你要移动的是哪个?其实不管怎么怎么改,只要合乎系统定下的规则就可以
2009-10-4 13:20
0
雪    币: 7992
活跃值: (2566)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
6
嗯..我果然理解错误..呵呵..

感谢指导..我以为切换就是第一项和第二项的切换..

原来他们有两个整体...

那个KeServiceDescriptorTableShadow和KeServiceDescriptorTable结构一样

也是四项..只不过.前者以SSDT为主.后者以ShadowSSDT为主?.等需要调用SSDT内函数的时候..

系统就会用你说的函数自动完成转换对吧..

如果是这样.我就明白了.

第三个问题.主要是我理解上的错误..导致这个字段修改也是错误.呵呵..

我说的移动.意思是.如果指向KeServiceDescriptorTable..我就从内核文件中把这个

KeServiceDescriptorTable整个结构复制出去.换个地方放哪里.然后修改线程的指针指向到这个地方..

但是还是那个问题.就在这个时候线程要求立刻切换到KeServiceDescriptorTableShadow..怎么办?

就算我把KeServiceDescriptorTableShadow也复制出来.系统也不知道该往哪里切换啊..

怎么告诉系统如何切换?
2009-10-4 13:29
0
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
7
第三个问题,你那样搞的话还麻烦了,不如直接替换每张表的基址,这样不管系统怎么切换都逃不出你的手掌心~~
2009-10-4 14:17
0
雪    币: 7992
活跃值: (2566)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
8
嗯..谢谢了..这个思路也不错..直接把地址数组整个替换掉..呵呵...

可以结贴了...非常感激你....
2009-10-4 14:22
0
雪    币: 177
活跃值: (278)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
不知道你想干什么。Shadow SSDT的前16个字节就是SSDT
2009-10-14 09:26
0
游客
登录 | 注册 方可回帖
返回
//