SSDT HOOK

首先要明白SSDTHOOK就是自己再写一份函数,替换了SSDT表中的地址替换掉

如何访问系统服务表呢?

SSDT 的全称是 System Services Descriptor Table,系统服务描述符表

下面这个是个全局变量
kd> dd KeServiceDescriptorTable(SSDT)

这个导出的 声明一下就可以使用了

kd> dd KeServiceDescriptorTableShadow(SSDT Shadow)

这个未导出 需要用其他的方式来查找

kd> dd KeServiceDescriptorTable
83fac9c0  83ec0d9c 00000000 00000191 83ec13e4
83fac9d0  00000000 00000000 00000000 00000000
83fac9e0  83f1f6af 00000000 025355a9 000000bb
83fac9f0  00000011 00000100 5385d2ba d717548f
83faca00  83ec0d9c 00000000 00000191 83ec13e4
83faca10  956d6000 00000000 00000339 956d702c
83faca20  00000000 00000000 83faca24 00000340
83faca30  00000340 865fab00 00000007 00000000

其中83ec0d9c是函数地址,00000191是函数个数,83ec13e4是函数参数个数,单位是一个字节,除以4就是函数地址表上对应函数的个数,第一个函数对第一个个数。

下面就是函数地址表

kd> dd 83ec0d9c
83ec0d9c  840bcc28 83f0340d 8404cb68 83e6788a
83ec0dac  840be4ff 83f403fa 8412eb05 8412eb4e
83ec0dbc  840413bd 84148368 841495c1 84037b95
83ec0dcc  840c8b35 84121963 84074a56 840446cc
83ec0ddc  83fda928 84113898 8402b14e 8406da62
83ec0dec  840b9df1 8401b238 840b91fe 84038c0c
83ec0dfc  840ca5bc 8403b28f 840ca39c 840c2afc
83ec0e0c  8404d0f0 8410e657 840bfec9 840ca7ee根据这个定义一个结构体
//下面这个是系统服务表的结构体
typedef struct _KSYSTEM_SERVICE_TABLE
{  PULONG  ServiceTableBase;                                       // 服务函数地址表基址  PULONG  ServiceCounterTableBase;                                ULONG   NumberOfService;                                        // 服务函数的个数  PULONG   ParamTableBase;                                        // 服务函数参数表基址
} KSYSTEM_SERVICE_TABLE, *PKSYSTEM_SERVICE_TABLE;  

下面就是函数参数个数表除四就是真正个数


kd> db 83ec13e4
83ec13e4  18 20 2c 2c 40 2c 40 44-0c 08 08 18 18 08 04 04  . ,,@,@D........
83ec13f4  0c 0c 10 18 24 0c 2c 0c-18 10 0c 0c 0c 0c 0c 0c  ....$.,.........
83ec1404  08 0c 18 18 14 18 0c 20-10 08 08 08 0c 08 0c 0c  ....... ........
83ec1414  08 04 04 0c 08 08 08 08-0c 04 04 20 08 10 0c 20  ........... ...
83ec1424  14 0c 2c 10 0c 0c 1c 10-20 20 10 38 10 14 10 20  ..,.....  .8...
83ec1434  24 24 28 1c 1c 14 10 20-2c 10 34 28 18 2c 14 28  $$(.... ,.4(.,.(
83ec1444  08 0c 08 04 04 04 04 04-0c 04 08 28 00 04 04 1c  ...........(....
83ec1454  18 00 08 08 18 0c 14 18-08 18 0c 08 08 0c 04 00  ................

如何得到函数表地址


//这个就是SSDT的结构体,即系统服务描述表,里面就是多个系统服务表
typedef struct _KSERVICE_TABLE_DESCRIPTOR
{  KSYSTEM_SERVICE_TABLE   ntoskrnl;                       // ntoskrnl.exe 的服务函数  KSYSTEM_SERVICE_TABLE   win32k;                         // win32k.sys 的服务函数(GDI32.dll/User32.dll 的内核支持)  KSYSTEM_SERVICE_TABLE   notUsed1;  KSYSTEM_SERVICE_TABLE   notUsed2;
}KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR;  

//导出由 ntoskrnl(10-10-12)所导出的 SSDT
extern PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable;

//这个是导出的,要到内核文件找,所以名字不能瞎起

下面的代码是查看到SSDT表地址的代码,可以打印显示

#include <ntddk.h>
#include<ntstatus.h>typedef struct _KSYSTEM_SERVICE_TABLE
{PULONG  ServiceTableBase;                                       // 服务函数地址表基址  PULONG  ServiceCounterTableBase;ULONG   NumberOfService;                                        // 服务函数的个数  PULONG   ParamTableBase;                                        // 服务函数参数表基址
} KSYSTEM_SERVICE_TABLE, *PKSYSTEM_SERVICE_TABLE;typedef struct _KSERVICE_TABLE_DESCRIPTOR
{KSYSTEM_SERVICE_TABLE   ntoskrnl;                       // ntoskrnl.exe 的服务函数  KSYSTEM_SERVICE_TABLE   win32k;                         // win32k.sys 的服务函数(GDI32.dll/User32.dll 的内核支持)  KSYSTEM_SERVICE_TABLE   notUsed1;KSYSTEM_SERVICE_TABLE   notUsed2;
}KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR;//导出由 ntoskrnl所导出的 SSDT
extern PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable;//这个是导出的,要到内核文件找,所以名字不能瞎起VOID DriverUnload(PDRIVER_OBJECT pDriver) {UNREFERENCED_PARAMETER(pDriver);KdPrint(("My Dirver is unloading..."));
}NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pPath) {UNREFERENCED_PARAMETER(pPath);KdPrint(("->%x \n", KeServiceDescriptorTable));pDriver->DriverUnload = DriverUnload;return STATUS_SUCCESS;
}

通过页表基址修改页属性

SSDT所在的物理页是只读的,如果要修改,先要修改页属性为可写:

1、第一种办法,用我们学过的知识,通过页表基址直接修改

if(RCR4 & 0x00000020)
{//说明是2-9-9-12分页KdPrint(("2-9-9-12分页 %p\n",RCR4));KdPrint(("PTE1 %p\n",*(DWORD*)(0xC0000000 + ((HookFunAddr >> 9) & 0x007FFFF8))));*(DWORD64*)(0xC0000000 + ((HookFunAddr >> 9) & 0x007FFFF8)) |= 0x02; KdPrint(("PTE1 %p\n",*(DWORD*)(0xC0000000 + ((HookFunAddr >> 9) & 0x007FFFF8))));
}
else
{//说明是10-10-12分页KdPrint(("10-10-12分页\n"));KdPrint(("PTE1 %p\n",*(DWORD*)(0xC0000000 + ((HookFunAddr >> 10) & 0x003FFFFC))));*(DWORD*)(0xC0000000 + ((HookFunAddr >> 10) & 0x003FFFFC)) |= 0x02;KdPrint(("PTE2 %p\n",*(DWORD*)(0xC0000000 + ((HookFunAddr >> 10) & 0x003FFFFC))));
}

通过修改CR0寄存器(WP位置改成0)

比如我们要SSDTHOOKNtOpenProcess,就要先通过IDA找到kernelBase的OpenProcess,在经过一系列查看最后在ntdll里找到ZWOpenProcess,所在位置看到了NtOpenProcess

.text:77F05D88                 mov     eax, 0BEh       ; NtOpenProcess
.text:77F05D8D                 mov     edx, 7FFE0300h
.text:77F05D92                 call    dword ptr [edx]
.text:77F05D94                 retn    10h
kd> dd KeServiceDescriptorTable
83f789c0  83e8cd9c 00000000 00000191 83e8d3e4
83f789d0  00000000 00000000 00000000 00000000
83f789e0  83eeb6af 00000000 025355a9 000000bb
83f789f0  00000011 00000100 5385d2ba d717548f
83f78a00  83e8cd9c 00000000 00000191 83e8d3e4
83f78a10  95d46000 00000000 00000339 95d4702c
83f78a20  00000000 00000000 83f78a24 00000340
83f78a30  00000340 865fab00 00000007 00000000
kd> dd 83e8cd9c+4*BE
83e8d094  840219dc 84073fff 84061b37 83f8d0c7
83e8d0a4  84079674 83ff50c6 84096977 8405db6f
83e8d0b4  8406dd87 840882e4 84061c4e 84119e0f
83e8d0c4  841026f1 84103989 83ff3506 84050970
83e8d0d4  841022a2 84101fc2 8410235a 8410207a
83e8d0e4  8400693f 83fd5f60 83ff0a51 841040e4
83e8d0f4  841041aa 84052403 840a35a7 840679a1
83e8d104  84114a3e 84114e83 83ed2d34 84086b8c
kd> u 840219dc
nt!NtOpenProcess:
840219dc 8bff            mov     edi,edi
840219de 55              push    ebp
840219df 8bec            mov     ebp,esp
840219e1 51              push    ecx
840219e2 51              push    ecx
840219e3 64a124010000    mov     eax,dword ptr fs:[00000124h]
840219e9 8a803a010000    mov     al,byte ptr [eax+13Ah]
840219ef 8b4d14          mov     ecx,dword ptr [ebp+14h]

下面说一下通过MDL修改页属性。
就是 Memory Descriptor List,简称 MDL。有的同学可能会问了,MDL究竟是个什么东西呢?从字面意思看,不难理解,内存描述符列表。MDL包含了内存区域的起始、拥有者proc、字节数、标记等。OK,我们需要先定义一个MDL的指针。


PMDL MDLSystemCall;

定义了MDL的指针以后,我们要通过MAPPED系列的参数来使内存拥有可写性,然后锁定内存中的MDL,那么我们就要定义一个PVOID的指针,来供MmMap操作。

PVOID *MappedSCT;
MDLSystemCall = MmCreateMdl(
NULL, //内存描述符列表
KeServiceDescriptorTable.ServiceTableBase,//
内存地址
KeServiceDescriptorTable.NumberOfServices*4);//内存长度
if(!MDLSystemCall)return STATUS_UNSUCCESSFUL;

建立了MDL,填充一下页数组

MmBuildMdlForNonPagedPool(MDLSystemCall);//建立内存页的MDL描述
MDLSystemCall->MdlFlags = MDLSystemCall->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA; //设置MDL标记为可写
MappedSCT = MmMapLockedPages(MDLSystemCall, KernelMode);

然后做自己的操作,比如这里的Hook

然后另外还有释放MDL的代码

if(MDSystemCall){MmUnmapLockedPages(MappedSCT, MDSystemCall);IoFreeMdl(MDSystemCall);}

下面是SSDT-Hook代码

#include <ntddk.h>
#include<ntstatus.h>
//1.找到系统服务表的函数地址表
//定义一个全局变量用来存放之前的NtOpenProcess地址
ULONG uOldNtOpenProcess;
//有了地址还需要一个函数NtOpenProcess指针,用于调用原来的NtOpenProcess//定义修复和恢复页属性的函数
PMDL MDSystemCall;
PVOID *MappedSCT;typedef NTSTATUS(*NTOPENPROCESS)(__out PHANDLE  ProcessHandle,__in ACCESS_MASK  DesiredAccess,__in POBJECT_ATTRIBUTES  ObjectAttributes,__in_opt PCLIENT_ID  ClientId);typedef struct _KSYSTEM_SERVICE_TABLE
{PULONG  ServiceTableBase;                                       // 服务函数地址表基址  PULONG  ServiceCounterTableBase;ULONG   NumberOfService;                                        // 服务函数的个数  PULONG   ParamTableBase;                                        // 服务函数参数表基址
} KSYSTEM_SERVICE_TABLE, *PKSYSTEM_SERVICE_TABLE;typedef struct _KSERVICE_TABLE_DESCRIPTOR
{KSYSTEM_SERVICE_TABLE   ntoskrnl;                       // ntoskrnl.exe 的服务函数  KSYSTEM_SERVICE_TABLE   win32k;                         // win32k.sys 的服务函数(GDI32.dll/User32.dll 的内核支持)  KSYSTEM_SERVICE_TABLE   notUsed1;KSYSTEM_SERVICE_TABLE   notUsed2;
}KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR;//导出由 ntoskrnl所导出的 SSDT
extern PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable;//这个是导出的,要到内核文件找,所以名字不能瞎起//准备用于替换的函数
NTSTATUS NTAPI MyNtOpenProcess(__out PHANDLE  ProcessHandle,__in ACCESS_MASK  DesiredAccess,__in POBJECT_ATTRIBUTES  ObjectAttributes,__in_opt PCLIENT_ID  ClientId
)
{NTSTATUS Status;Status = STATUS_SUCCESS;//这里填自己的业务。。。各种过滤,修改返回结构等KdPrint(("MyNtOpenProcess %x %x %x %x \n", ProcessHandle, DesiredAccess, ObjectAttributes, ClientId));//后面这里填的是打开原来的函数,因为这个函数也要实现原来的功能,不然就乱套了,除非你自己在自己业务里实现了return ((NTOPENPROCESS)uOldNtOpenProcess)(ProcessHandle, DesiredAccess, ObjectAttributes, ClientId);
}void PageProtectOff() {//MDSystemCall = MmCreateMdl(NULL, KeServiceDescriptorTable->ntoskrnl.ServiceTableBase, KeServiceDescriptorTable->ntoskrnl.NumberOfService * 4);//if (!MDSystemCall)//  //return STATUS_UNSUCCESSFUL;//  return;//MmBuildMdlForNonPagedPool(MDSystemCall);//MDSystemCall->MdlFlags = MDSystemCall->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;//MappedSCT = MmMapLockedPages(MDSystemCall, KernelMode);__asm { //关闭内存保护push eax;mov eax, cr0;and eax, ~0x10000;mov cr0, eax;pop eax;}
}void PageProtectOn() {解锁、释放MDL//if (MDSystemCall)//{//  MmUnmapLockedPages(MappedSCT, MDSystemCall);//  IoFreeMdl(MDSystemCall);//}__asm { //恢复内存保护push eax;mov eax, cr0;or eax, 0x10000;mov cr0, eax;pop eax;}
}
//3.修改函数地址,准备个函数用来修改函数地址
void HookNtOpenProcess() {NTSTATUS Status;Status = STATUS_SUCCESS;PageProtectOff();uOldNtOpenProcess = KeServiceDescriptorTable->ntoskrnl.ServiceTableBase[0xBE];KeServiceDescriptorTable->ntoskrnl.ServiceTableBase[0xBE] = (ULONG)MyNtOpenProcess;PageProtectOn();
}
//4.恢复
void UnHookNtOpenProcess() {PageProtectOff();KeServiceDescriptorTable->ntoskrnl.ServiceTableBase[0xBE] = (ULONG)uOldNtOpenProcess;PageProtectOn();
}VOID DriverUnload(PDRIVER_OBJECT pDriver) {UNREFERENCED_PARAMETER(pDriver);UnHookNtOpenProcess();KdPrint(("My Dirver is unloading..."));}NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pPath) {UNREFERENCED_PARAMETER(pPath);KdPrint(("->%x \n", KeServiceDescriptorTable->ntoskrnl.ServiceTableBase[0xBE]));//得到函数地址表HookNtOpenProcess();pDriver->DriverUnload = DriverUnload;return STATUS_SUCCESS;
}

然后操作时可以用PChunt观察HOOk前后这个函数地址变化

这是hook前

这是Hook后

SSDT—Hook和MDL相关推荐

  1. 也谈SSDT Hook(二)

    一.实战篇 本不想摘代码,既然实战,就不多讲废话了,还是贴上吧,谁都有违背原则的时候:). 代码一:经典案例,替换NtQuerySystemInformation,列取所有查询到的进程名,我使用修改C ...

  2. SSDT HOOK技术轻松让最新版冰刃、XueTr失效

    刚开始学驱动,成功HOOK NtOpenProces 现在本想试试HOOK NtQuerySystemInformation,没想打它的结构N多N长,也让我很惊讶,这个API居然能获取或者设置超过50 ...

  3. FSD HOOK与SSDT HOOK恢复简单思路

    FSD 解释: File System Driver文件系统驱动程序,分为本地FSD和远程FSD. (1) 本地FSD:允许用户访问本地计算机上的数据 --本地FSD负责向I/O管理器注册自己,当开始 ...

  4. Win64 驱动内核编程-22.SHADOW SSDT HOOK(宋孖健)

    SHADOW SSDT HOOK HOOK 和 UNHOOK SHADOW SSDT 跟之前的 HOOK/UNHOOK SSDT 类似,区别是查找SSSDT的特征码,以及根据索引计算函数地址的公式,还 ...

  5. (52)系统调用阶段测试——基于 SSDT HOOK 的 FindWindowA 监视器

    一.项目说明 SSDT HOOK 内核函数我们已经会了,请看这两篇博客: SSDT HOOK 实现进程保护 补充内容:SSDT HOOK 模板 此次考试和 hook NtOpenProcess 或 N ...

  6. (51)SSDT HOOK 实现进程保护

    一.回顾 在前面的课程里,我们逆向分析了 KiSystemService / KiFastCallEntry 的部分代码,我们发现这两个函数找系统服务表 SystemServiceTable 的方法是 ...

  7. (50)补充内容:SSDT HOOK 模板

    代码 下面的驱动代码ssdt hook了NtOpenProcess函数,可以监视打开进程的操作. #include <ntddk.h> #include <ntstatus.h> ...

  8. Windows驱动开发学习笔记(五)—— SSDT HOOK

    Windows驱动开发学习笔记(五)-- SSDT HOOK 系统服务表 系统服务描述符表 实验一:通过代码获取SSDT表地址 通过页表基址修改页属性 方法1:修改页属性 方法2:修改CR0寄存器 实 ...

  9. 进程隐藏与进程保护(SSDT Hook 实现)(三)

    文章目录: 1. 引子: 2. 获取当前系统下所有进程: 3. 服务管理(安装,启动,停止,卸载): 4. 应用程序和内核程序通信: 5. 小结: 1. 引子: 关于这个 SSDT Hook 实现进程 ...

最新文章

  1. VirtualBox虚拟机中启用usb3.0却无法显示u盘的解决方法
  2. 导入旧版本Android项目时的“Unable to resolve target ‘android
  3. Powershell基础(一)
  4. Java杂记之JVM内存模型
  5. 列举在移动Web开发中经常会设置的特殊样式!
  6. SpringBoot自动配置【源码分析】-初始加载自动配置类
  7. git远程强制更新到本地
  8. Nginx_查看并发连接数
  9. 【转】雷军自曝创业第一年:掏自己的钱创业成功率最高
  10. 数据库创建索引有什么优点和缺点
  11. 张量(tensor)
  12. Handler看这一篇就够了
  13. 基因组变异类型详解及区分
  14. Android 实现电话拨号界面带按键声demo
  15. Unirech腾讯云国际代充-云服务器cvm常见问题解答
  16. 解决微信公众号链接被举报的问题
  17. 网络基础知识:10M、50M、100M宽带下载速率一般是多少?
  18. mac上Python版本不同时,给指定的版本安装库
  19. MATLAB 像素画绘制APP
  20. markdown自动生成导航目录

热门文章

  1. ecshop常用修改
  2. 寻找假币问题(二分法)
  3. 【实验】流量控制之分为流量抑制和风暴控制
  4. vue自定以鼠标样式cursor
  5. 基于QTC++的线激光标定+测距模型
  6. js的for循环中return可以跳出循环,而使用forEach等不可以跳出循环
  7. unity ugui改变width,height,pos
  8. 短视频2020,快手、抖音的分化之年
  9. This connection has been closed
  10. 计算机英语 单词201-300