HOOK钩子技术5 SSDT Inline Hook

来源:互联网 发布:mac驱动下载 编辑:程序博客网 时间:2024/05/16 18:02

原理

内联钩子的原理在R3和R0下是相同的,就是不改变SSDT表项,而是改变函数内部前几条指令。
内联钩子的典型伪函数为:

  • 恢复原指令
  • 执行目标操作,或改写参数
  • 执行原函数
  • 返回时重新挂钩

demo

#include "stdafx.h"#ifdef __cplusplusextern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING  RegistryPath);#endiftypedef NTSTATUS (*NtCreateProcess)(                                      OUT PHANDLE           ProcessHandle,                                      IN ACCESS_MASK        DesiredAccess,                                      IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,                                      IN HANDLE             ParentProcess,                                      IN BOOLEAN            InheritObjectTable,                                      IN HANDLE             SectionHandle OPTIONAL,                                      IN HANDLE             DebugPort OPTIONAL,                                      IN HANDLE             ExceptionPort OPTIONAL ,                                      IN ULONG                JobMemberLevel  ); typedef struct _SERVICE_DESCRIPTOR_TABLE{    PULONG ServiceTableBase;    PULONG ServiceCounterTableBase;    ULONG  NumberOfService;    PUCHAR ParamTableBase;}SERVICE_DESCRIPTOR_TABLE,*PSERVICE_DESCRIPTOR_TALBE;NtCreateProcess  real_func_addr = NULL;unsigned char bOldBytes[5];unsigned char bNewBytes[5];extern "C" PSERVICE_DESCRIPTOR_TALBE KeServiceDescriptorTable;//name can't change.  import member must be global variable./*cr0 -16th bit = 0 means page can write*/bool REMOVE_ONLYREAD(){    __asm    {            push eax            mov eax,CR0            and eax, not 10000h            mov CR0,eax            pop eax    }    return TRUE;}/*cr0 -16th bit(WP) = 1,reset to the attribute of ONLY READ*/bool RESET_ONLYREAD(){    __asm    {        push eax            mov eax,CR0            or  eax,10000h            mov CR0,eax            pop eax    }    return TRUE;}VOID RelineHookCreateProcess(){    REMOVE_ONLYREAD();    //writememory with "jmp xxxxxxxx";    RtlCopyMemory((PVOID)real_func_addr,(CONST PVOID)bNewBytes,5);     RESET_ONLYREAD();}VOID UnHookCreateProcess(){    REMOVE_ONLYREAD();    //__asm int 3    RtlCopyMemory((PVOID)real_func_addr,(const PVOID)bOldBytes,5);    RESET_ONLYREAD();}void InlineSSDTHookUnload(PDRIVER_OBJECT pDriverObject) //no return ,with return compiler error{    UnHookCreateProcess();    DbgPrint("GoodBye from InlineHook!\n");}NTSTATUS MyNtCreateProcessEx(                             OUT PHANDLE           ProcessHandle,                             IN ACCESS_MASK        DesiredAccess,                             IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,                             IN HANDLE             ParentProcess,                             IN BOOLEAN            InheritObjectTable,                             IN HANDLE             SectionHandle OPTIONAL,                             IN HANDLE             DebugPort OPTIONAL,                             IN HANDLE             ExceptionPort OPTIONAL ,                             IN ULONG                JobMemberLevel                              ){    NTSTATUS Status = STATUS_SUCCESS;    UnHookCreateProcess();    Status = real_func_addr(        ProcessHandle,        DesiredAccess,        ObjectAttributes,        ParentProcess,        InheritObjectTable,        SectionHandle ,        DebugPort ,        ExceptionPort ,        JobMemberLevel        );    RelineHookCreateProcess();    DbgPrint("have hook CreateProcess!\r\n");    return Status;}NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING  RegistryPath){    unsigned i;    DbgPrint("Hello from InlineSSDTHook!\n");    DriverObject->DriverUnload = InlineSSDTHookUnload;    //hook    PULONG PSsdt = (PULONG)KeServiceDescriptorTable->ServiceTableBase;    PULONG p_real_func_addr =PSsdt+0x30;       //(unsigned char *) pssdt+0x30*4;    DbgPrint("%08x,%08x",p_real_func_addr,PSsdt+0x30); //diff compared with ssdt hook    real_func_addr = (NtCreateProcess)(*p_real_func_addr);    //__asm int 3    RtlCopyMemory((PVOID)bOldBytes,(CONST PVOID)real_func_addr,5);    bNewBytes[0] ='\xe9';    *(PULONG)&bNewBytes[1]=(ULONG)MyNtCreateProcessEx-(ULONG)real_func_addr-5;    //__asm int 3    RtlCopyMemory((PVOID)real_func_addr,(CONST PVOID)bNewBytes,5);    return STATUS_SUCCESS;}

今天在做实验的时候,老是出错,无语了。在本地加载了程序的符号文件后调试出现各种奇葩问题,比如说函数入口指令的第一个字节总是没有改回来,后来也不知道怎么解决的。

挂钩后不能打开程序,提示文件错误 ,但是停止服务后恢复正常,所以怀疑是伪函数执行时候有错误,查了半天也没有错误。最后发现是少了一个参数,我函数指针定义成nt!NtCreatProcess 的参数了,nt!NtCreateProcessExnt!ntCreateProces 多了一个参数JobMemeberLevel

typedef NTSTATUS (*NtCreateProcessEx)(                                      OUT PHANDLE           ProcessHandle,                                      IN ACCESS_MASK        DesiredAccess,                                      IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,                                      IN HANDLE             ParentProcess,                                      IN BOOLEAN            InheritObjectTable,                                      IN HANDLE             SectionHandle OPTIONAL,                                      IN HANDLE             DebugPort OPTIONAL,                                      IN HANDLE             ExceptionPort OPTIONAL ,        /*************/               IN ULONG                JobMemberLevel  ); 

可是非常奇怪,参数错误函数执行肯定出错,昨天的SSDT HOOK却也是少了这个参数,挂钩函数也是nt!ntCreateProcessEx,按理说应该出错啊,为什么昨天的又是正确的呢???参数不一致也可以?仔细研究一下。

0 0