Inline Hook

本文讲 用inline hook的方式修改NtOpenKey函数的一个小例子, 自己的学习笔记

hook 计算机里面一般是指 挂钩某函数,也可以是替换掉原来的函数。

inline hook 是直接在以前的函数替里面修改指令,用一个跳转或者其他指令来达到挂钩的目的。 这是相对普通的hook来说,因为普通的hook只是修改函数的调用地址,而不是在原来的函数体里面做修改。
一般来说 普通的hook比较稳定使用。 inline hook 更加高级一点,一般也跟难以被发现。所以很多人比如病毒制作者都比较推崇inline hook。

SSDT的全称是System Services Descriptor Table,系统服务描述符表
一般来说此表与链接系统内核的API密切相关,对此有一项应用就是杀毒软件的主动防御,当然病毒也可以通过修改主动防御的SSDT来绕过杀软的主动防御。SSDT hook一般是用来隐藏进程运行程序的,前面已经讲了。

先用PCHunter查看下NtOpenKey的序号

1. hook 内核函数NtOpenKey, 把 函数开头的前5个字节的指令 改成 call xxxxxxxx
2. 把前5个字节的指令 替换成 call 相对偏移, 实现跳转到 newNtOpenKey
公式: 相对偏移 = hook后函数地址 - 原函数地址 -指令长度
机器码: E8 XXXXXXXX

3. 完成 newNtOpenKey 函数

void FilterNtOpenKey()
{
KdPrint(("%s",(char*)PsGetCurrentProcess()+0x16c));
}
void NewNtOpenKey()
{
__asm{
call FilterNtOpenKey
pop eax
mov edi,edi
push ebp
mov ebp,esp
jmp g_jmp_orig_ntopenkey
}
}

完整代码

  1 #include "ntddk.h"
  2 //windbg命令:
  3 //dd KeServiceDescriptorTable
  4 //dt _EPROCESS
  5 extern "C"
  6 {
  7
  8 void PageProtectOn()
  9 {
 10     __asm{//恢复内存保护
 11         mov  eax,cr0
 12             or   eax,10000h
 13             mov  cr0,eax
 14             sti
 15     }
 16 }
 17 void PageProtectOff()
 18 {
 19     __asm{//去掉内存保护
 20         cli
 21             mov  eax,cr0
 22             and  eax,not 10000h
 23             mov  cr0,eax
 24     }
 25 }
 26
 27 #pragma pack(1)
 28 typedef struct ServiceDescriptorEntry {
 29     unsigned int *ServiceTableBase;
 30     unsigned int *ServiceCounterTableBase; //仅适用于checked build版本
 31     unsigned int NumberOfServices;
 32     unsigned char *ParamTableBase;
 33 } ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t;
 34 #pragma pack()
 35 __declspec(dllimport) ServiceDescriptorTableEntry_t KeServiceDescriptorTable;
 36
 37 NTSTATUS PsLookupProcessByProcessId(IN HANDLE ProcessId, OUT PEPROCESS *Process);
 38
 39 ULONG    g_ntopenprocess;
 40 ULONG    g_ntocreatesection;
 41
 42 typedef NTSTATUS (*NTOPENPROCESS) (
 43                                    __out PHANDLE ProcessHandle,
 44                                    __in ACCESS_MASK DesiredAccess,
 45                                    __in POBJECT_ATTRIBUTES ObjectAttributes,
 46                                    __in_opt PCLIENT_ID ClientId);
 47
 48 typedef NTSTATUS (*NtCreateSection)(
 49                                     OUT PHANDLE  SectionHandle ,
 50                                     IN ACCESS_MASK  DesiredAccess ,
 51                                     IN POBJECT_ATTRIBUTES  ObjectAttributes OPTIONAL,
 52                                     IN PLARGE_INTEGER  MaximumSize OPTIONAL,
 53                                     IN ULONG  SectionPageProtection ,
 54                                     IN ULONG  AllocationAttributes ,
 55                                     IN HANDLE  FileHandle OPTIONAL);
 56
 57
 58
 59 NTSTATUS IoQueryFileDosDeviceName(IN PFILE_OBJECT  FileObject,OUT POBJECT_NAME_INFORMATION  *ObjectNameInformation );
 60
 61 NTSTATUS NewNtCreateSection(
 62                             OUT PHANDLE  SectionHandle ,
 63                             IN ACCESS_MASK  DesiredAccess ,
 64                             IN POBJECT_ATTRIBUTES  ObjectAttributes OPTIONAL,
 65                             IN PLARGE_INTEGER  MaximumSize OPTIONAL,
 66                             IN ULONG  SectionPageProtection ,
 67                             IN ULONG  AllocationAttributes ,
 68                             IN HANDLE  FileHandle OPTIONAL
 69                             )
 70 {
 71     ULONG isrun =1;
 72     PFILE_OBJECT    FileObject;
 73     POBJECT_NAME_INFORMATION wcFilePath;
 74     if (SectionPageProtection & (PAGE_EXECUTE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE|PAGE_EXECUTE_WRITECOPY) ){
 75         if (NT_SUCCESS(ObReferenceObjectByHandle(FileHandle,0,NULL,KernelMode,(PVOID *)(&FileObject),NULL)))
 76         {
 77             if (IoQueryFileDosDeviceName(FileObject,&wcFilePath)==STATUS_SUCCESS)
 78             {
 79                 ExFreePool(wcFilePath);
 80                 wchar_t wstr[260]=L"";
 81                 wcscpy(wstr, wcFilePath->Name.Buffer);
 82                 _wcslwr(wstr);
 83                 DbgPrint("[TrueCell] %ws\r\n",wstr);
 84                 if (wcsstr(wstr, L"360safe.exe")!=0)
 85                 {
 86                     ObDereferenceObject(FileObject);
 87                     return STATUS_UNSUCCESSFUL;
 88                 }
 89             }
 90             ObDereferenceObject(FileObject);
 91         }
 92     }
 93     return ((NtCreateSection)g_ntocreatesection)(SectionHandle,DesiredAccess,ObjectAttributes,MaximumSize,SectionPageProtection,AllocationAttributes,FileHandle);
 94 }
 95
 96
 97 NTSTATUS NewNtOpenProcess (
 98                            __out PHANDLE ProcessHandle,
 99                            __in ACCESS_MASK DesiredAccess,
100                            __in POBJECT_ATTRIBUTES ObjectAttributes,
101                            __in_opt PCLIENT_ID ClientId)
102 {
103     NTSTATUS    status;
104     PEPROCESS    process_obj;
105     char strpname[30]="calc.exe";
106     HANDLE ProcessId=(HANDLE)(ClientId->UniqueProcess);
107     if (!MmIsAddressValid(strpname))return FALSE;
108     if (ProcessId==0)    return FALSE;
109     status = PsLookupProcessByProcessId(ProcessId,&process_obj);
110     if (!NT_SUCCESS(status)){
111         KdPrint(("error code:%X---ProcessId:%d",status,ProcessId));
112         return FALSE;
113     }
114     char sname[15]="";
115     strcpy(sname, (char*)process_obj+0x16c);
116     _strlwr(sname);
117     if (strstr(strpname, sname)!=0)
118     {
119         ObDereferenceObject(process_obj);
120         return STATUS_UNSUCCESSFUL;
121     }
122     ObDereferenceObject(process_obj);
123
124     return ((NTOPENPROCESS)g_ntopenprocess)(ProcessHandle,DesiredAccess,ObjectAttributes,ClientId);
125 }
126
127
128 NTSTATUS HookNtFun()
129 {
130     NTSTATUS    status;
131     status = STATUS_SUCCESS;
132
133     PageProtectOff();
134
135     g_ntopenprocess = KeServiceDescriptorTable.ServiceTableBase[190];
136     KeServiceDescriptorTable.ServiceTableBase[190] = (unsigned int)NewNtOpenProcess;
137
138     g_ntocreatesection = KeServiceDescriptorTable.ServiceTableBase[84];//84
139     KeServiceDescriptorTable.ServiceTableBase[84] = (unsigned int)NewNtCreateSection;
140     PageProtectOn();
141     return status;
142 }
143 VOID UnHookNtFun()
144 {
145     PageProtectOff();
146     KeServiceDescriptorTable.ServiceTableBase[190] = (unsigned int)g_ntopenprocess;
147     KeServiceDescriptorTable.ServiceTableBase[84] = (unsigned int)g_ntocreatesection;
148     PageProtectOn();
149 }
150 VOID MyUnload(PDRIVER_OBJECT pDriverObject)
151 {
152     UnHookNtFun();
153 }
154 NTSTATUS    DriverEntry(PDRIVER_OBJECT    pDriverObject,PUNICODE_STRING Reg_Path)
155 {
156     HookNtFun();
157     pDriverObject->DriverUnload = MyUnload;
158     return STATUS_SUCCESS;
159 }
160
161 }
时间: 2024-08-09 19:51:56

Inline Hook的相关文章

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

一.前言 之前文章中所讨论的恶意程序的应对方法,都是十分被动的,即只有当恶意程序被执行后,才考虑补救措施.这样,我们就会一直处于后手状态,而如果说病毒的危害性极大,那么即便我们完美地修复了诸如注册表项,服务项等敏感位置,并且删除了病毒本身,但是它依旧可能已经破坏了系统中非常重要的文件,造成了不可逆的损伤.因此这篇文章就来简单讨论一下利用Inline 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

Android inline hook手记[转载]

原网址:http://blog.dbgtech.net/blog/?p=51 作者:NetRoc Android inline hook手记 说到Inline hook,了解这个词的同志们都应该知道,无非是修改目标函数处的指令,跳转到自己的函数,并且提供调用原函数的stub,即可完成整个流程.但是在ARM下面情况和我们熟悉的x86有所不同.ARM芯片的运行状态分为arm和thumb两种模式,分别有不同的指令集,arm指令为定长32位,thumb指令为定长16位(thumb-2中进行了扩展,可以使

对付ring0 inline hook

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

android inline hook

最近终于沉下心来对着书把hook跟注入方面的代码敲了一遍,打算写几个博客把它们记录下来. 第一次介绍一下我感觉难度最大的inline hook,实现代码参考了腾讯GAD的游戏安全入门. inline hook的大致流程如下: 首先将目标指令替换为跳转指令,跳转地址为一段我们自己编写的汇编代码,这段汇编代码先是执行用户指定的代码,如修改寄存器的值,然后执行被替换掉的原指令2,最后再跳转回原指令3处,恢复程序的正常运行. 为了避开注入过程,我们通过hook自己进程加载的动态连接库进行演示. 1.实现

x86平台inline hook原理和实现

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

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)

c# r3 inline hook

前言 老婆喜欢在QQ游戏玩拖拉机,且安装了一个记牌器小软件,打开的时候弹出几个IE页面加载很多广告,于是叫我去掉广告.想想可以用OD进行nop填充,也可以写api hook替换shellexecute函数的调用,以前也有见过有人使用hex editor修改shellexecute函数的,但搞了多年C#,其它很多原来就不熟悉的都忘记了,迫于无奈于是选择Api Hook这个方式.选择这Api Hook也面临很多难题,如何远程注入,如何让远程进程加载.net的程序集,.net程序集如何完成Api的ho

实现win10下Delphi 10.3和易语言 inline hook之GetLocalTime

1 library Project1; 2 3 { Important note about DLL memory management: ShareMem must be the 4 first unit in your library's USES clause AND your project's (select 5 Project-View Source) USES clause if your DLL exports any procedures or 6 functions that