shadow ssdt

假设.有一个目标进程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

答问题一: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》,就是这么做的~~


首先十分感谢一楼大牛的指导..

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

为什么呢.

我的个人理解是.


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

第三个问题,你那样搞的话还麻烦了,不如直接替换每张表的基址,这样不管系统怎么切换都逃不出你的手掌心~~

你可能感兴趣的:(windows,工作,service,table,System,Descriptor)