假设.有一个目标进程A..
在驱动中首先获取其EPROCESS..
然后用这个PsGetNextProcessThread取出其线程..
然后取出ETHREAD...也等同于KTHREAD..(是第一个字段).
然后关键就是这个ServiceTable..字段..
关于这个指针..ShadowSSDT Hook系列的文章会说.如果其不是GUI进程则此字段不会指向ShadowSSDT (也就是KeSSSDT的第二项)...
问题:
现在反过来..如果是GUI进程.已经指向Shadow SSDT..那么它调用SSDT内的函数.(比如它CreateFile一下.最终还是需要SSDT内函数...)..这个时候系统是怎么处理的?
问题二..如果其是CUI进程.指向了SSDT.那么.如果调用ShadowSSDT内函数..又是如何切换的.和问题一类似.
问题三..
如果修改其当前的地址..那么切换的时候.系统还知道切换到那里吗?
或者说.如何让系统指导.该切换到那里?
十分感谢..
好象一直以来我们所说的ShadowSSDT的概念和系统中的KeServiceDescriptorTableShadow有一点出入,我们所说的专指GUI ServiceTable这个表,而它实际上只是KeServiceDescriptorTableShadow的一部分而已
正常情况下,ETHREAD中的ServiceTable,要么指向KeServiceDescriptorTable,要么指向KeServiceDescriptorTableShadow你说的是直接修改ETHREAD->ServiceTable这个字段的值吗?可以修改,在系统调用进入KiFastCallEntry时,会从当前线程的KTHREAD中取出这个表然后使用,如果修改的话,保证你提供的地址是有效的而且包含了正确的系统服务表就可以了,有一篇文章叫做《Hide your SSDT Hooks》,就是这么做的~~
首先十分感谢一楼大牛的指导..
不过.我看了你的说法后.反而迷糊了..
为什么呢.
我的个人理解是.
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内.这个时候系统怎么才能知道该切换到那..呵呵..
不过我想到这里.感觉.如果是直接指向他们全部..那么就一切好说了.不知道是不是这样??谢谢.
正常情况下,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线程根本不需要这张表,所以没有填充
你的第三个问题,描述得还是不太清楚啊。到底你要移动的是哪个?其实不管怎么怎么改,只要合乎系统定下的规则就可以
嗯..我果然理解错误..呵呵..
感谢指导..我以为切换就是第一项和第二项的切换..
原来他们有两个整体...
那个KeServiceDescriptorTableShadow和KeServiceDescriptorTable结构一样
也是四项..只不过.前者以SSDT为主.后者以ShadowSSDT为主?.等需要调用SSDT内函数的时候..
系统就会用你说的函数自动完成转换对吧..
如果是这样.我就明白了.
第三个问题.主要是我理解上的错误..导致这个字段修改也是错误.呵呵..
我说的移动.意思是.如果指向KeServiceDescriptorTable..我就从内核文件中把这个
KeServiceDescriptorTable整个结构复制出去.换个地方放哪里.然后修改线程的指针指向到这个地方..
但是还是那个问题.就在这个时候线程要求立刻切换到KeServiceDescriptorTableShadow..怎么办?
就算我把KeServiceDescriptorTableShadow也复制出来.系统也不知道该往哪里切换啊..
怎么告诉系统如何切换?
不知道你想干什么。Shadow SSDT的前16个字节就是SSDT