SSDT Hook的妙用-对抗ring0 inline hook

SSDT Hook技术详解与应用 SSDT Hook技术详解与应用SSDT Hook技术详解与应用 一SSDT简介 1什么是SSDT 2SSDT结构 3应用层调用 Win32 API 的完整执行流程 二SSDT Hook原理 1SSDT Hook原理简介 2进程隐藏与保护 3文件隐藏与保护 4端口隐藏一、SSDT简介1、什么是SSDT​ SSDT 的全称是 System Services Descriptor Table,系统服 阅读详情
 转载】SSDT Hook的妙用-对抗ring0 inline hook
作 者: 堕落天才
时 间: 2007-03-10,15:18
链 接: http://bbs.pediy.com/showthread.php?threadid=40832

*******************************************************
*标题:【转载】SSDT Hook的妙用-对抗ring0 inline hook *
*作者:堕落天才 *
*日期:2007年3月10号 *
*声明:本文章的目的仅为技术交流讨论 *
*******************************************************

1,SSDT
SSDT即系统服务描述符表,它的结构如下(参考《Undocument Windows 2000 Secretes》第二章):
typedef struct _SYSTEM_SERVICE_TABLE
{
PVOID ServiceTableBase; //这个指向系统服务函数地址表
PULONG ServiceCounterTableBase;
ULONG NumberOfService; //服务函数的个数,NumberOfService*4 就是整个地址表的大小
ULONG ParamTableBase;
}SYSTEM_SERVICE_TABLE,*PSYSTEM_SERVICE_TABLE;

typedef struct _SERVICE_DESCRIPTOR_TABLE
{
SYSTEM_SERVICE_TABLE ntoskrnel; //ntoskrnl.exe的服务函数
SYSTEM_SERVICE_TABLE win32k; //win32k.sys的服务函数,(gdi.dll/user.dll的内核支持)
SYSTEM_SERVICE_TABLE NotUsed1;
SYSTEM_SERVICE_TABLE NotUsed2;
}SYSTEM_DESCRIPTOR_TABLE,*PSYSTEM_DESCRIPTOR_TABLE;

内核中有两个系统服务描述符表,一个是KeServiceDescriptorTable(由ntoskrnl.exe导出),一个是 KeServieDescriptorTableShadow(没有导出)。两者的区别是,KeServiceDescriptorTable仅有 ntoskrnel一项,KeServieDescriptorTableShadow包含了ntoskrnel以及win32k。一般的Native API的服务地址由KeServiceDescriptorTable分派,gdi.dll/user.dll的内核API调用服务地址由 KeServieDescriptorTableShadow分派。还有要清楚一点的是win32k.sys只有在GUI线程中才加载,一般情况下是不加载的,所以要Hook KeServieDescriptorTableShadow的话,一般是用一个GUI程序通过IoControlCode来触发(想当初不明白这点,蓝屏死机了N次都想不明白是怎么回事)。

2,SSDT HOOK
SSDT HOOK 的原理其实非常简单,我们先实际看看KeServiceDescriptorTable是什么样的。
lkd> dd KeServiceDescriptorTable
8055ab80 804e3d20 00000000 0000011c 804d9f48
8055ab90 00000000 00000000 00000000 00000000
8055aba0 00000000 00000000 00000000 00000000
8055abb0 00000000 00000000 00000000 00000000
在windbg.exe中我们就看得比较清楚,KeServiceDescriptorTable中就只有第一项有数据,其他都是0。其中804e3d20就是
KeServiceDescriptorTable.ntoskrnel.ServiceTableBase,服务函数个数为0x11c个。我们再看看804e3d20地址里是什么东西:
lkd> dd 804e3d20
804e3d20 80587691 805716ef 8057ab71 80581b5c
804e3d30 80599ff7 80637b80 80639d05 80639d4e
804e3d40 8057741c 8064855b 80637347 80599539
804e3d50 8062f4ec 8057a98c 8059155e 8062661f
如上,80587691 805716ef 8057ab71 80581b5c 这些就是系统服务函数的地址了。比如当我们在ring3调用OpenProcess时,进入sysenter的ID是0x7A(XP SP2),然后系统查KeServiceDescriptorTable,大概是这样 KeServiceDescriptorTable.ntoskrnel.ServiceTableBase(804e3d20) + 0x7A * 4 = 804E3F08,然后804E3F08 ->8057559e 这个就是OpenProcess系统服务函数所在,我们再跟踪看看:
lkd> u 8057559e
nt!NtOpenProcess:
8057559e 68c4000000 push 0C4h
805755a3 6860b54e80 push offset nt!ObReferenceObjectByPointer+0x127 (804eb560)
805755a8 e8e5e4f6ff call nt!InterlockedPushEntrySList+0x79 (804e3a92)
805755ad 33f6 xor esi,esi
原来8057559e就是NtOpenProcess函数所在的起始地址。
嗯,如果我们把8057559e改为指向我们函数的地址呢?比如 MyNtOpenProcess,那么系统就会直接调用MyNtOpenProcess,而不是原来的NtOpenProcess了。这就是SSDT HOOK 原理所在。

3, ring0 inline hook
ring0 inline hook 跟ring3的没什么区别了,如果硬说有的话,那么就是ring3发生什么差错的话程序会挂掉,ring0发生什么差错的话系统就挂掉,所以一定要很小心。inline hook的基本思想就是在目标函数中JMP到自己的监视函数,做一些判断然后再JMP回去。一般都是修改函数头,不过再其他地方JMP也是可以的。下面我们来点实际的吧:
lkd> u nt!NtOpenProcess
nt!NtOpenProcess:
8057559e e95d6f4271 jmp f199c500
805755a3 e93f953978 jmp f890eae7
805755a8 e8e5e4f6ff call nt!InterlockedPushEntrySList+0x79 (804e3a92)
...
同时打开“冰刃”跟“Rootkit Unhooker”我们就能在NtOpenProcess函数头看到这样的“奇观”,第一个jmp是“冰刃”的,第二个jmp是“Rootkit Unhooker”的。他们这样是防止被恶意程序通过TerminateProcess关闭。当然“冰刃”还Hook了 NtTerminateProcess等函数。

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

typedef struct _SERVICE_DESCRIPTOR_TABLE
{
PVOID ServiceTableBase;
PULONG ServiceCounterTableBase;
ULONG NumberOfService;
ULONG ParamTableBase;
}SERVICE_DESCRIPTOR_TABLE,*PSERVICE_DESCRIPTOR_TABLE; //由于KeServiceDescriptorTable只有一项,这里就简单点了
extern PSERVICE_DESCRIPTOR_TABLE KeServiceDescriptorTable;//KeServiceDescriptorTable为导出函数

/////////////////////////////////////
VOID Hook();
VOID Unhook();
VOID OnUnload(IN PDRIVER_OBJECT DriverObject);
//////////////////////////////////////
ULONG JmpAddress;//跳转到NtOpenProcess里的地址
ULONG OldServiceAddress;//原来NtOpenProcess的服务地址
//////////////////////////////////////
__declspec(naked) NTSTATUS __stdcall MyNtOpenProcess(PHANDLE ProcessHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
PCLIENT_ID ClientId)
{
DbgPrint("NtOpenProcess() called");
__asm{
push 0C4h
push 804eb560h //共十个字节
jmp [JmpAddress]
}
}
///////////////////////////////////////////////////
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath)
{
DriverObject->DriverUnload = OnUnload;
DbgPrint("Unhooker load");
Hook();
return STATUS_SUCCESS;
}
/////////////////////////////////////////////////////
VOID OnUnload(IN PDRIVER_OBJECT DriverObject)
{
DbgPrint("Unhooker unload!");
Unhook();
}
/////////////////////////////////////////////////////
VOID Hook()
{
ULONG Address;
Address = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 0x7A * 4;//0x7A为NtOpenProcess服务ID
DbgPrint("Address:0x%08X",Address);

OldServiceAddress = *(ULONG*)Address;//保存原来NtOpenProcess的地址
DbgPrint("OldServiceAddress:0x%08X",OldServiceAddress);

DbgPrint("MyNtOpenProcess:0x%08X",MyNtOpenProcess);

JmpAddress = (ULONG)NtOpenProcess + 10; //跳转到NtOpenProcess函数头+10的地方,这样在其前面写的JMP都失效了
DbgPrint("JmpAddress:0x%08X",JmpAddress);

__asm{//去掉内存保护
cli
mov eax,cr0
and eax,not 10000h
mov cr0,eax
}

*((ULONG*)Address) = (ULONG)MyNtOpenProcess;//HOOK SSDT

__asm{//恢复内存保护
mov eax,cr0
or eax,10000h
mov cr0,eax
sti
}
}
//////////////////////////////////////////////////////
VOID Unhook()
{
ULONG Address;
Address = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 0x7A * 4;//查找SSDT

__asm{
cli
mov eax,cr0
and eax,not 10000h
mov cr0,eax
}

*((ULONG*)Address) = (ULONG)OldServiceAddress;//还原SSDT

__asm{
mov eax,cr0
or eax,10000h
mov cr0,eax
sti
}

DbgPrint("Unhook");
}
××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
就这么多了,或许有人说,没必要那么复杂,直接恢复NtOpenProcess不就行了吗?对于象“冰刃”“Rookit Unhooker”这些“善良”之辈的话是没问题的,但是象NP这些“穷凶极恶”之流的话,它会不断检测NtOpenProcess是不是已经被写回去,是的话,嘿嘿,机器马上重启。这也是这种方法的一点点妙用
ldpc编解码器设计与仿真 计算校验节点到变量节点的消息 m_{c \to v}=2 \cdot atanh(\prod_{v’ \in N©\setminus v}tanh(\frac{m_{v’ \to c}}{2}))。计算变量节点到校验节点的消息 m_{v \to c}=L_{v,0}+\sum_{c’ \in M(v)\setminus c}m_{c’ \to v}。◦ 对于每个变量节点 v,计算最终 LLR 值 L_{v,f}=L_{v,0}+\sum_{c \in M(v)}m_{c \to v}。 阅读详情

相关推荐

STM32F407实现LwIP的MQTT客户端并连接到服务器

这个是用LwIP协议栈中自带的MQTT客户端API写成的,代码注释很详细,附带有服务端的展示。LwIP版本是2.1.2.

wait_for_STM32的博客 6399

【SSDT】SSDT hook技术

通过修改此表的函数地址可以对常用Windows函数及API进行Hook,从而实现对一些关心的系统动作进行过滤、监控等目的。在NT4.0 以上的Windpws 操作系统中,默认存在两个系统服务描述表,两个调度表对应两类不同的系统服务。要Hook SSDT表,首选需要这个表是可写的,但是在XP之后的系统都是只读的,有三种方式修改内存保护机制。其中第1位叫做保护属性位,控制着页的读或写属性。如果为0,则只能读/执行。SSDT,IDT(中断描述符表)的页属性在默认情况下只读,可执行,但不能写。例如进程保护(驱动)

dr0op's blog 2784

开源DIY龙门架:从零构建可编程运动控制平台

运动控制是自动化与机器人技术的核心基础,它通过精确指令驱动执行机构,实现物体的定位与轨迹规划。其原理通常涉及控制器、驱动器、电机与传动机构的协同工作,核心价值在于将数字指令转化为精准的物理运动,从而解放人力并提升作业一致性。在工业自动化、桌面制造(如3D打印、激光雕刻)及教育机器人等领域应用广泛。本文聚焦于一个具体的工程实践案例:使用**铝型材**、**3D打印**零件、Arduino控制器及步进电机,从机械结构设计、电路连接到代码编写,手把手教你打造一个模块化、可扩展的开源龙门架系统。该系统不仅成本可控,

weixin_33168937的博客 625

API钩取技术研究(四)——SSDT Hook

简单起见,我将要保护的进程PID硬性编码为cmd.exe的PID。自定义钩取函数MyZwOpenProcess()的实现思路类似于IAT Hook中自定义钩取函数的实现思路,通过修改进程参数Desired Access的值为0,然后再将修改的参数传入正常调用的原ZwOpenProcess() API即可实现进程保护。

m0_55220082的博客 972

10.2 在新能源、储能及电网节点的应用实践

构网型变流器技术在电力系统中的应用进展 构网型变流器技术正从理论研究走向规模化工程应用,为新能源并网提供主动支撑能力。该技术在光伏电站采用"部分构网"混合架构,由构网单元实现黑启动和弱网稳定;在风电场利用叶轮动能提供惯量响应。储能系统是理想的构网载体,可提供快速调频和动态电压支撑。在电网节点,构网型STATCOM可增强弱电网电压稳定性,大容量变流器可替代传统调相机。当前面临标准滞后、宽频振荡风险等共性挑战,需在可靠性、经济性间取得平衡。系统级协调控制和精确阻抗建模是应用成功的关键。

技术工作者 1112

手把手教你从入门到精通C# MES通信

本文是C#与MES通信通信的目录,使用C#与各种MES系统通信的方法我都会在专栏中讲到,比如WebService、Http、Ftp、共享文件夹、串口通信等,绝对是上位机软件工程师实现与MES系统通信的必备教程!

qq_34059233的博客 8752

SSDT —— Hook

Win7 x32:注:SSDTShadow包含SSDT,在Xp系统下,SSDTShadow在SSDT上面(偏移0x40)在WIN7 x32下,SSDTShadow在SSDT下面(偏移0x40),如上图0x9C0+0x40=0xA00。

weixin_48257887的博客 580

高斯过程的数学理解

G澳大利亚的过程是有益的,特别是当我们有少量数据时。当我在制造业担任数据科学家时,我们的团队使用这种算法来揭示我们接下来应该进行哪些实验条件。但是,此算法不如其他算法流行。在这篇博客中,我将通过可视化和 Python 实现来解释高斯过程 [1] 的数学背景。

gongdiwudu的专栏 3611

逆向基础-Windows驱动开发【SSDT HOOK】

驱动开发,SSDT HOOK

AppWhite_Star的博客 2218

get_ccopt系列命令介绍

get_ccopt_property:用来获取cts阶段,clock tree上所有的参数信息,可以通过get_ccopt_property –help *获取所有参数。get_ccopt_skew_group_delay:用来获取skew group的相关信息,可以通过筛选出特定条件下skew_group的参数,如skew_group下latency最长是多少;get_ccopt_clock_tree_source_groups:获取clock tree的source group名字;

芯冰乐 283

PyTorch深度学习实战(25)——从零开始实现Mask R-CNN实例分割

Mask R-CNN 是一种在目标检测任务中引入了语义分割的强大框架,通过在 Faster R-CNN 基础上进行扩展,添加了额外的分支网络,不仅可以准确地检测对象的位置和类别,还可以生成每个实例的精确像素级别的语义分割掩码。其模块化的设计可以轻松地应用于不同的任务和数据集,并且可以通过添加更多的分支进行功能扩展,如实例关键点检测等。

盼小辉丶的博客 1万+

转:SSDT Hook的妙用-对抗ring0 inline hook

转:SSDT Hook的妙用-对抗ring0 inline hook

创造神话,实现梦想! 955

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

上一篇: 脱壳高级篇之认识Import表
下一篇: NMFilter.sys(4.3.2.2485)逆向源代码
iiprogram
博客等级 码龄25年 1068粉丝 1515原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值