HOOK钩子技术5 SSDT Inline Hook

原理

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

内联钩子的典型伪函数为:

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

demo

#include "stdafx.h"

#ifdef __cplusplus
extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING  RegistryPath);
#endif

typedef 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,按理说应该出错啊,为什么昨天的又是正确的呢???参数不一致也可以?仔细研究一下。

时间: 2024-11-08 05:57:57

HOOK钩子技术5 SSDT Inline Hook的相关文章

Inline Hook

本文讲 用inline hook的方式修改NtOpenKey函数的一个小例子, 自己的学习笔记 hook 计算机里面一般是指 挂钩某函数,也可以是替换掉原来的函数. inline hook 是直接在以前的函数替里面修改指令,用一个跳转或者其他指令来达到挂钩的目的. 这是相对普通的hook来说,因为普通的hook只是修改函数的调用地址,而不是在原来的函数体里面做修改.一般来说 普通的hook比较稳定使用. inline hook 更加高级一点,一般也跟难以被发现.所以很多人比如病毒制作者都比较推崇

Ring3 下 API Inline Hook 优化方案探索与实现

??本博文由CSDN博主zuishikonghuan所作,版权归zuishikonghuan所有,转载请注明出处:http://blog.csdn.net/zuishikonghuan/article/details/51302024 ?? 以前写过两篇"[Win32] API Hook(1)在32/64位系统上的实现"博客,介绍并给出了 API inline hook 代码,如下: ????blog.csdn.net/zuishikonghuan/article/details/47

反病毒攻防研究第012篇:利用Inline HOOK实现主动防御

一.前言 之前文章中所讨论的恶意程序的应对方法,都是十分被动的,即只有当恶意程序被执行后,才考虑补救措施.这样,我们就会一直处于后手状态,而如果说病毒的危害性极大,那么即便我们完美地修复了诸如注册表项,服务项等敏感位置,并且删除了病毒本身,但是它依旧可能已经破坏了系统中非常重要的文件,造成了不可逆的损伤.因此这篇文章就来简单讨论一下利用Inline HOOK技术实现主动防御,在病毒执行前,就主动将危险函数劫持,如同一道防火墙,保护我们计算机的安全. 二.Inline HOOK原理 我们平时所使用

逆向实用干货分享,Hook技术第一讲,之Hook Windows API

逆向实用干货分享,Hook技术第一讲,之Hook Windows API 作者:IBinary出处:http://www.cnblogs.com/iBinary/版权所有,欢迎保留原文链接进行转载:) 一丶什么是Hook,以及Hook能干啥 首先这一个小标题主要介绍神马是Hook,如果知道的,则不用看了. 这里我偷袭啊懒,贴出Hook的意思  https://baike.baidu.com/item/%E9%92%A9%E5%AD%90%E7%A8%8B%E5%BA%8F Hook,英文单词中成

对付ring0 inline hook

对付ring0 inline hook的基本思路是这样的,自己写一个替换的内核函数,以NtOpenProcess为例,就是MyNtOpenProcess.然后修改SSDT表,让系统服务进入自己的函数MyNtOpenProcess.而MyNtOpenProcess要做的事就是,实现NtOpenProcess前10字节指令,然后再JMP到原来的NtOpenProcess的十字节后.这样NtOpenProcess函数头写的JMP都失效了,在ring3直接调用OpenProcess再也毫无影响.

x86平台inline hook原理和实现

概念 inline hook是一种通过修改机器码的方式来实现hook的技术. 原理 对于正常执行的程序,它的函数调用流程大概是这样的: 0x1000地址的call指令执行后跳转到0x3000地址处执行,执行完毕后再返回执行call指令的下一条指令. 我们在hook的时候,可能会读取或者修改call指令执行之前所压入栈的内容.那么,我们可以将call指令替换成jmp指令,jmp到我们自己编写的函数,在函数里call原来的函数,函数结束后再jmp回到原先call指令的下一条指令.如图: 通过修改机器

Windows API 教程(七) hook 钩子监听

Windows API 教程(七) hook 钩子监听 Posted on 2013-08-15 茵蒂克丝 如何创建一个窗口 手动创建窗口的流程 实际代码 安装钩子 (Install hook) 钩子简介 SetWindowsHookEx 函数 设置监听[键盘]消息 设置监听[鼠标]消息 如何创建一个窗口 另外一个再录的 Windows SDK教程 里面有讲到快捷创建窗口的方式,不过这样的话要分好几个文件,感觉有点混所以这里就用原始的方式创建一个窗口. 那么,为什么讲到 hook(钩子)的时候要

【转】Hook钩子C#实例

[转]Hook钩子C#实例 转过来的文章,出处已经不知道了,但只这篇步骤比较清晰,就贴出来了. 一.写在最前 本文的内容只想以最通俗的语言说明钩子的使用方法,具体到钩子的详细介绍可以参照下面的网址: http://www.microsoft.com/china/community/program/originalarticles/techdoc/hook.mspx 二.了解一下钩子 从字面上理解,钩子就是想钩住些东西,在程序里可以利用钩子提前处理些Windows消息. 例子:有一个Form,Fo

HOOK钩子 - 钩子函数说明

翻译参考自MaybeHelios的blog: http://blog.csdn.net/maybehelios/ 通过SetWindowsHookEx方法安装钩子,该函数指定处理拦截消息的钩子函数(回调函数),可在钩子函数中自定义消息的处理,可修改消息或屏蔽消息.钩子函数的格式是固定为:LRESULT CALLBACK CallBackProc(                Int nCode,          WPARAM wParam,          LPARAM lParam);