最近在学习Ring0层Hook的一些知识点,很久就写完SSDTHook的代码了,但是一直没有整理成笔记,最近有时间也就整理整理。

介绍:

SSDTHook 实质是利用Ntoskrnl.exe 中全局导出的SSDT来进行Hook,SSDT(SystemServiceDescriptorTable,系统服务描述表),为什么要去用到SSDT表呢?

我们看一下ZwOpenProcess实现就明白了。为什么不用Nt系列函数,可以看我之前的文章。

kd> u 0x8485acd8
nt!ZwOpenProcess:
8485acd8 b8 be000000 mov eax,0BEh
8485acdd 8d542404 lea edx,[esp+]
8485ace1 9c pushfd
8485ace2 6a08 push
8485ace4 e8d5190000 call nt!KiSystemService (8485c6be)
8485ace9 c21000 ret 10h
nt!ZwOpenProcessToken:
8485acec b8bf000000 mov eax,0BFh
8485acf1 8d542404 lea edx,[esp+]

KiSystemService是系统调用的内核入口,也是从Ring3陷入Ring0的关键点。在第一句中mov eax,0BEh 中的BEh在我看来就是一个序号,相当于中断向量表中的中断类型号一样,在SSDT表中通过这序号,才找到真正的NtOpenProcess函数的代码出。很容易就能理解,我们为什么要找这个。原因在于:我们要把SSDT表中相应位置的函数地址替换掉,就实现了Hook。

 (一)

⚪首先找到全局导出的KeServiceDescriptorTable。

⚪然后从MmGetSystemRoutineAddress函数中获取ZwOpenProcess函数地址。

⚪从ZwOpenProcess中获取序号。

⚪将SSDT表所在页属性改为可读可写的状态。

⚪将自己写好的Fake函数地址替换进去即可。

Hook之前:                                                                               Hook之后:

             

(二)

/*
typedef struct _SYSTEM_SERVICE_DESCRIPTOR_TABLE_
{
PVOID ServiceTableBase; //这个指向系统服务函数地址表
PULONG ServiceCounterTableBase;
ULONG NumberOfService; //服务函数的个数
ULONG ParamTableBase;
}SYSTEM_SERVICE_DESCRIPTOR_TABLE, *PSYSTEM_SERVICE_DESCRIPTOR_TABLE; 0x84988b00 struct _SYSTEM_SERVICE_DESCRIPTOR_TABLE_ *
ServiceTableBase 0x8489d43c
ServiceCounterTableBase 0x00000000
NumberOfService 0x191
ParamTableBase 0x8489da84
*/
extern PSYSTEM_SERVICE_DESCRIPTOR_TABLE KeServiceDescriptorTable;
PUCHAR __ZwOpenProcess = NULL;
PMDL __MDL = NULL;
PVOID *__ServiceTableBase = NULL;
LPFN_NTOPENPROCESS __NtOpenProcess = NULL;
BOOLEAN __IsHook = FALSE; #define SSDT_INDEX(ZwFunctionAddress) * (PULONG)((PUCHAR)ZwFunctionAddress +1)
#define SSDT_HOOK(ZwFunctionAddress,FakeFunctionAddress,OriginalFunctionAddress)\
OriginalFunctionAddress = (PVOID) InterlockedExchange((PLONG)&__ServiceTableBase[SSDT_INDEX(ZwFunctionAddress)],(LONG)FakeFunctionAddress)
#define SSDT_UNHOOK(ZwFunctionAddress,OriginalFunctionAddress)\
(PVOID) InterlockedExchange((PLONG)&__ServiceTableBase[SSDT_INDEX(ZwFunctionAddress)],(LONG)OriginalFunctionAddress)
NTSTATUS SSDTHook(BOOLEAN IsOk)
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
UNICODE_STRING v1;
RtlInitUnicodeString(&v1, L"ZwOpenProcess"); if (IsOk)
{
__ZwOpenProcess = (PUCHAR)MmGetSystemRoutineAddress(&v1);
/*
2: kd> u 0x8485acd8
nt!ZwOpenProcess:
8485acd8 b8 be000000 mov eax,0BEh
8485acdd 8d542404 lea edx,[esp+4]
8485ace1 9c pushfd
8485ace2 6a08 push 8
8485ace4 e8d5190000 call nt!KiSystemService (8485c6be)
8485ace9 c21000 ret 10h
nt!ZwOpenProcessToken:
8485acec b8bf000000 mov eax,0BFh
8485acf1 8d542404 lea edx,[esp+4] */
if (__ZwOpenProcess)
{
if (__MDL == NULL)
{
__MDL = MmCreateMdl(NULL, KeServiceDescriptorTable->ServiceTableBase,
KeServiceDescriptorTable->NumberOfService * sizeof(PVOID));
if (!__MDL)
{
return Status;
}
MmBuildMdlForNonPagedPool(__MDL);
//设置标志让内存变成读写
__MDL->MdlFlags = __MDL->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;
__ServiceTableBase = MmMapLockedPages(__MDL, KernelMode);
} if (__ServiceTableBase)
{
if (!__IsHook)
{
//开始HOOK
SSDT_HOOK(__ZwOpenProcess, FakeNtOpenProcess, __NtOpenProcess);
Status = STATUS_SUCCESS;
/*
2: kd> u 0x84a31ba1
nt!NtOpenProcess:
84a31ba1 8bff mov edi,edi
84a31ba3 55 push ebp
84a31ba4 8bec mov ebp,esp
84a31ba6 51 push ecx
84a31ba7 51 push ecx
84a31ba8 64a124010000 mov eax,dword ptr fs:[00000124h]
84a31bae 8a803a010000 mov al,byte ptr [eax+13Ah]
84a31bb4 8b4d14 mov ecx,dword ptr [ebp+14h] */ __IsHook = TRUE;
} }
}
}
else
{
if (__IsHook)
{
SSDT_UNHOOK(__ZwOpenProcess, __NtOpenProcess);
__IsHook = FALSE;
}
if (__MDL)
{
MmUnmapLockedPages(__ServiceTableBase, __MDL);
IoFreeMdl(__MDL);
__MDL = NULL;
Status = STATUS_SUCCESS; } } return Status;
} NTSTATUS FakeNtOpenProcess( PHANDLE ProcessHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PCLIENT_ID ClientId)
{ __try
{
PEPROCESS EProcess = PsGetCurrentProcess();
if (EProcess != NULL && IsRealProcess(EProcess))
{
char * ProcessName = (ULONG_PTR)EProcess + x86_IMAGEFILENAME_OFFSET;
if (strcmp(ProcessName, "HookRing3.exe")==)
{
return STATUS_ACCESS_DENIED;
}
}
}
__except ()
{
return GetExceptionCode();
}
return ((LPFN_NTOPENPROCESS)__NtOpenProcess)(ProcessHandle, DesiredAccess, ObjectAttributes, ClientId); }
 

Hook集合----SSDTHook(x86 Win7)的更多相关文章

  1. 一个简单的Object Hook的例子(win7 32bit)

    Object Hook简单的来说就是Hook对象,这里拿看雪上的一个例子,因为是在win7 32位上的,有些地方做了些修改. _OBJECT_HEADER: kd> dt _OBJECT_HEA ...

  2. Android的so注入( inject)和函数Hook(基于got表) - 支持arm和x86

    本文博客地址:http://blog.csdn.net/qq1084283172/article/details/53942648 前面深入学习了古河的Libinject注入Android进程,下面来 ...

  3. android hook 框架 libinject2 简介、编译、运行

    Android so注入-libinject2 简介.编译.运行 Android so注入-libinject2  如何实现so注入 Android so注入-Libinject 如何实现so注入 A ...

  4. 01.WAMP搭建 [Win7+Apache2.4+MySQL5.7+PHP7

    WAMP搭建[Win7+Apache2.4+MySQL5.7+PHP7 一.背景 将电脑光驱位拆换成固态硬盘(120g),专门装了一个系统用于工作.之前一直使用PHPstudy和WAMP这种集成环境, ...

  5. win7 xp 双系统安装记录

    原机win7 64 增加xp x86 win7在c盘,xp装h盘 1.老毛桃pe,雨林木风gho,蓝屏,0000007b 2.通用pe.雨林木风gho,蓝屏,00000007b 3.pe设置h盘为系统 ...

  6. Android下so注入和hook

    一.前言 总结一下这两天学习的Android注入so文件,通过遍历got表hook函数调用 1.注入so文件 2.so文件中遍历got表hook函数 二.注入so文件 1)注入进程 1.编程思路分为以 ...

  7. android hook 框架 libinject 如何实现so注入

    前面两篇 android hook 框架 libinject2 简介.编译.运行 android hook 框架 libinject2 如何实现so注入 实际运行并分析了 Android中的so注入( ...

  8. CApiHook__Api钩子类

    见过网上有很多ApiHook的类,但是都不尽入人意,要么就是写的不够好不够完善,要么就是跑不起来. 用别人写的代码总是有种不安心,所以自己就花了一晚上写了CApiHook类.已经尽量确保自己写的类是非 ...

  9. UDP收发buffer尺寸对收发包流量的影响

    下午验证一个高流量发包问题时,发现了一个值得记录的问题:socket的收发buffer尺寸是会影响收发包的效率的,高流量通讯时,若socket的收发buffer尺寸过小会一定程度降低收发包效率. 自己 ...

随机推荐

  1. 恭祝2018元旦快乐!转发享福利(⊙o⊙)…

    来源:中国工信出版集团-电子工业出版社赠送给作者的原书. 为感谢2017年你的不离不弃,在2018新年之际来一发,转发朋友圈集齐20个赞,即参与活动, 活动规则: 1   转发朋友圈+集齐20个赞?, ...

  2. 用 Python 读写 Excel 表格

    Python 可以读写 Excel 表格吗? 当然可以. Python 下有很多类库可以做到, openpyxl 就是其中的佼佼者. openpyxl 的设计非常漂亮 ,你一定会喜欢它!不信请往下看: ...

  3. Nginx之常用基本配置(二)

    上一篇我们把nginx的主配置文件结构大概介绍了下,全局配置段比较常用的指令说了一下,http配置段关于http服务器配置指令介绍了下,以及有几个调优的指令,server_name的匹配机制,错误页面 ...

  4. Java中的成员内部类

    */ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.java * 作者:常轩 * 微信公众号:Worldh ...

  5. linux学习--2.文件管理的基本命令

    文件的基本操作 前言: 看完这篇图文我应该能保证读者在Linux系统下对文件的操作能跟用Windows环境下一样流畅吧,好了下面正文 正文: 基础知识: linux里共有以下几类文件,分别为目录(di ...

  6. mongodb 修改oplogSize

    oplog是local库下的一个固定集合,Secondary就是通过查看Primary的oplog这个集合来进行复制的.每个节点都有oplog,记录从主节点复制过来的信息,这样每个成员都可以作为同步源 ...

  7. sql-- 找到重复数据并删除、有重复数据不插入或更新的处理方法

    表结构: 需求:找到相同的内容并删除 方法1: 通过分组找出筛选出count大于1的数据 group by可以利用聚合函数(count. sum. avg)进行分组 having 对分组的数据进行下一 ...

  8. go语言指南之斐波纳契闭包

    练习:斐波纳契闭包 让我们用函数做些好玩的事情. 实现一个 fibonacci 函数,它返回一个函数(闭包),该闭包返回一个斐波纳契数列 `(0, 1, 1, 2, 3, 5, ...)`. 这是一个 ...

  9. CMSampleBufferRef解析

    CMTime:64位的value,32位的scale, media的时间格式 CMVideoFormatDesc:video的格式,包括宽高.颜色空间.编码格式.SPS.PPS CVPixelBuff ...

  10. 简单说 通过CSS的滤镜 实现 火焰效果

    说明 上次我们了解了一些css滤镜的基础知识, 简单说 CSS滤镜 filter属性 这次我们就来用css的滤镜实现一个 火焰的效果. 解释 要实现上面的火焰效果,我们先来了解一些必要的东西. 上次我 ...