在研究一段HOOK SSDT的代码中看到有这样一段宏:
#define SYSTEMSERVICE(_function) KeServiceDescriptorTable.ServiceTableBase[ *(PULONG)((PUCHAR)_function+1)]
根据代码注释得知次宏是用来获得SSDT基地址。但是对于这个宏的为何如此定义,一直无法理解。希望有内核驱动开发经验的朋友指点一下。

解决方案 »

  1.   

    看这个,或许有帮助http://bbs.pediy.com/showthread.php?t=42422&highlight=%E5%BF%85%E5%A4%87+%E5%A4%87%E7%BB%9D+%E7%BB%9D%E6%8A%80
      

  2.   

    呵呵。先谢谢了。看雪的这段代码我也看过了,在HOOK SSDT时也用到了那个宏。只是我对这个宏的定义方法不明白。
      

  3.   

    驱动没写过,不过这个宏展开:
    #define SYSTEMSERVICE(_function) KeServiceDescriptorTable.ServiceTableBase[ *(PULONG)((PUCHAR)_function+1)] 如:
    SYSTEMSERVICE(test)
    ==>
     KeServiceDescriptorTable.ServiceTableBase[ *(PULONG)((PUCHAR)test+1)] 
      

  4.   

    function+1即ServiceID所在地址。整个表达式即取得_function对应的System Service的入口地址在线性内存中的位置看这个   再谈Windows NT/2000内部数据结构http://www.3800hk.com/news/w31/6643.html如果还不理解,只能取下win nt的源代码看看了
      

  5.   

    KeServiceDescriptorTable
    是一个系统定义的全局的结构体变量,ServiceTableBase指向SSDT基地址。
      

  6.   

    要获得哪个应用程序对系统注册表有过操作,只要在对其有操作的System Service中注入自己的代码,也就是改变这些System Service的执行流程,先执行自己的代码(Regmon中用于记录供GUI部分使用),接着返回至原先处继续执行即可。通过以上分析,我们知道只要修改ServiceTableBase到ServiceTableBase+NumberOfService*4范围的数据就可以改变System Service的执行流程,而只要知道System Service的ServiceID就可以改变这一System Service入口地址在这一区域的位置,那么又如何得到System Service的Service ID呢!我们可以随便以ZwOpenKey作个例子:  :u ZwOpenKey
      ntoskrnl!ZwOpenKey
      0008:80400E2A B867000000       MOV     EAX,00000067             
                    |                       |_ServiceID
                    |_机器码(其中第二字节即ZwOpenKey线性地址加一处就是ServiceID)
      0008:80400E2F 8D542404         LEA     EDX,[ESP+04]
      0008:80400E33 CD2E           INT     2E
      0008:80400E35 C20C00         RET     000C

      这样只要知道Zwxxx例程名(即System Service在内存中的线性地址),是不是就可以实现我们的目的了呢?来看看Regmon的具体实现代码吧:      .
          .
          .
          // 保存ZwOpenKey原先入口,在HookRegOpenKey中使用
        RealRegOpenKey = SYSCALL( ZwOpenKey );           // 修改ZwOpenKey流程,指向新的入口,即调用ZwOpenKey时转向执行HookRegOpenKey
        SYSCALL( ZwOpenKey ) = (PVOID) HookRegOpenKey; 
          .
          .
          .  SYSCALL在intel平台是如下定义的:
        #define SYSCALL(_function) ServiceTable->ServiceTable[ *(PULONG)((PUCHAR)_function+1)]   
      ServiceTable->ServiceTable就是我们上面所述的 ServiceDescriptorTableEntry->ServiceTableBase(为了便于描述)。_function+1即ServiceID所在地址。整个表达式即取得_function对应的System Service的入口地址在线性内存中的位置。其它定义请参阅Regsys.c与Regsys.h!
      

  7.   

    非常感谢ILOVEDRV!问题解决。希望跟高手进一步探讨内核驱动。
      

  8.   

    _function应该是个索引值,KeServiceDescriptorTable.ServiceTableBase数组里保存这这个索引处的函数地址。