关于SSDT,描述得最清楚的应该算《SSDT Hook的妙用-对抗ring0 inline hook》一文了,作者是堕落天才。 这个 就是传说中的SSDT Hook了。 这段代码基本和《SSDT Hook的妙用-对抗ring0 inline hook》一文一样,我只是注释了一下而已,另外在MyNtOpenProcess处加了个判断是不是某个特定PID的功能。 STATUS_SUCCESS; } // 驱动卸载 VOID OnUnload(IN PDRIVER_OBJECT DriverObject) { Unhook( ); } // 此处修改SSDT mov eax, cr0 and eax, not 10000h mov cr0, eax } // 修改SSDT
SSDT 的全称是 System Services Descriptor Table,系统服务描述符表。 SSDT表已经导出了,通过ntoskrnl.exe的导出表可以查看到。 ,所以我们只需要告诉内核需要调用的服务所在 SSDT 中的索引就 OK 了,然后内核根据这个索引值就可以在 SSDT 中找到相对应的服务了,然后再由内核调用服务完成应用程序 API 的调用请求即可。 数组中找到索引值为eax 寄存器中存放的值的那个 SSDT 项,最后就是根据这个 SSDT 项中所存放的系统服务的地址来调用这个系统函数了。 844993a4 84498d5c 就是SSDT表的起始地址。
SSDT 中文名称为系统服务描述符表,该表的作用是将Ring3应用层与Ring0内核层,两者的API函数连接起来,起到承上启下的作用,SSDT并不仅仅只包含一个庞大的地址索引表,它还包含着一些其它有用的信息 NtOpenProccess) 读取 SSDT 获得函数地址 上面的实验我们通过一个函数的调用流程了解到了用户层与内核层的通信过程,其中提到了SSDT索引号的相关概念,SSDT索引号在系统中是固定不变的 Windows 系统提供的SSDT表其作用就是方便应用层之间API的调用,所有的API调用都会转到SSDT这张表中进行参考,这样就能够使不同的API调用全部都转到对应的SSDT表中,从而方便管理。 LONG *SSDT_Adr, STB_addr, SSDT_NtOpenProcess_Addr; DbgPrint("驱动程序已加载! ); SSDT_NtOpenProcess_Addr = *SSDT_Adr; DbgPrint("当前NtOpenProcess地址 %x \n", SSDT_NtOpenProcess_Addr
SSDT 中文名称为系统服务描述符表,该表的作用是将Ring3应用层与Ring0内核层,两者的API函数连接起来,起到承上启下的作用,SSDT并不仅仅只包含一个庞大的地址索引表,它还包含着一些其它有用的信息 &NtOpen); DbgPrint("原始函数的地址是: %x\n", SSDT_Addr); return SSDT_Addr; } VOID UnDriver(PDRIVER_OBJECT ,eax // 将结果赋值给变量 } DbgPrint("原始函数的地址是: %x\n", SSDT_Addr); return SSDT_Addr; } VOID UnDriver Get_Origin_SSDT = Get_Origin_SSDTAddr(); // 获取原始的NTOpenProcess的地址 if (Get_Now_SSDT ! Get_Origin_SSDT = Get_Origin_SSDTAddr(); // 获取原始的NTOpenProcess的地址 if (Get_Now_SSDT !
SSDT 中文名称为系统服务描述符表,该表的作用是将Ring3应用层与Ring0内核层,两者的API函数连接起来,起到承上启下的作用,SSDT并不仅仅只包含一个庞大的地址索引表,它还包含着一些其它有用的信息 );DbgPrint("原始函数的地址是: %x\n", SSDT_Addr);return SSDT_Addr;}VOID UnDriver(PDRIVER_OBJECT driver){DbgPrint NtOpen);__asm{push eaxmov eax,SSDT_Addradd eax,50ahmov SSDT_Addr,eax}DbgPrint("原始函数的地址是: %x\n", SSDT_Addr , Get_Now_SSDT;JMPDATE JmpDate;Get_Now_SSDT = Get_Now_SSDTAddr(); // 获取NTOpenProcess的当前地址Get_Origin_SSDT , Get_Now_SSDT;JMPDATE JmpDate;Get_Now_SSDT = Get_Now_SSDTAddr(); // 获取NTOpenProcess的当前地址Get_Origin_SSDT
=ssdt+(ssdt+4 * Index)>>4 0: kd> uf nt! (SSDT Shadow)。 同时SSDT在ntoskrnl.exe中是导出的,而SSDT Shadow如其名是未被Windows所导出的,而关于SSDT的全部内容都是通KeServiceDescriptorTable来完成的。 如图: ZwQSystemInfor 随后根据该索引值检索SSDT项,最后根据该SSDT项中所存放的系统服务地址来调用这个系统服务。 0x02 详解SSDT 这节内我们用WinDbg来调试XP系统,借此说明SSDT是个什么鬼。
SSDT 中文名称为系统服务描述符表,该表的作用是将Ring3应用层与Ring0内核层,两者的API函数连接起来,起到承上启下的作用,SSDT并不仅仅只包含一个庞大的地址索引表,它还包含着一些其它有用的信息 NtOpenProccess) 图片读取 SSDT 获得函数地址上面的实验我们通过一个函数的调用流程了解到了用户层与内核层的通信过程,其中提到了SSDT索引号的相关概念,SSDT索引号在系统中是固定不变的 Windows 系统提供的SSDT表其作用就是方便应用层之间API的调用,所有的API调用都会转到SSDT这张表中进行参考,这样就能够使不同的API调用全部都转到对应的SSDT表中,从而方便管理。 LONG *SSDT_Adr, STB_addr, SSDT_NtOpenProcess_Addr;DbgPrint("驱动程序已加载! );SSDT_NtOpenProcess_Addr = *SSDT_Adr;DbgPrint("当前NtOpenProcess地址 %x \n", SSDT_NtOpenProcess_Addr);pDriver
我们可以通过枚举ntdll.dll的导出函数来间接枚举SSDT所有表项所对应的函数,因为所有的内核服务函数对应于ntdll.dll的同名函数都是这样开头的: 汇编代码 mov eax, <ServiceIndex
目录 64位下读取SSDT表并且获取SSDT函数 一丶读取SSDT表 (KeServiceDescriptorTable) 1.1 原理 1.2 手动获取SSDT表 1.2.1 重点1 了解引用流程以及其它方式寻找 SSDT表的方式 1.2.2 重要点2 获取SSDT表以及Shadow表位置 1.2.3 重要点3 SSDT表的加密获取以及使用 二丶两种方式实现获取SSDT表 2.1 常规方式获取SSDT表. 2.2 通过API寻找方式来找寻SSDT 64位下读取SSDT表并且获取SSDT函数 一丶读取SSDT表 (KeServiceDescriptorTable) 1.1 原理 在64位系统下我们可以通过读取msr 表或者SSDTShadow表 例子: 1.2.2 重要点2 获取SSDT表以及Shadow表位置 重要点2位置的两行代码则是获取SSDT表与Shadow表. 表 2.1 常规方式获取SSDT表.
目录 SSDTHOOK 1.SSDTHOOK 原理. 1.x32下的SSDT HOOK 2.SSDT HOOK代码 3.结果 4.总结 SSDTHOOK 1.SSDTHOOK 原理. x32下,直接获取系统描述符表 .以及调用号.就可以进行HOOK了. x64下可以设置回调来进行过滤我们想要的功能.当然如果你简单的过一下PatchGuard也可以设置SSDT HOOK. 1.x32下的SSDT HOOK 首先SSDT SSDT表的结构如下: typedef struct _KSERVICE_TABLE_DESCRIPTOR { PULONG_PTR Base; PULONG Count; ULONG 则获得SSDT表的地址 获取你想HOOK函数的位置 进行HOOK HOOK之前关闭一下CR0得写保护 代码如下: 2.SSDT HOOK代码 #include "Driver.h" NTKERNELAPI
要恢复SSDT,首先要获得SSDT各个函数的原始地址,而SSDT各个函数的原始地址,自然是存储在内核文件里的。 ) 6.获得指定INDEX函数的地址(计算公式:*(PULONGLONG)(NtosInProcess+RVA+8*index)-NtosImageBase+NtosBase) 思路和WIN32下获得SSDT temp-NtosImageBase; returnRVA_index+NtosBase; } 接下来测试一下效果,在测试前,运行SSDTHOOKNtTerminateProcess的DEMO(检测出了SSDT 其实恢复SSDT本质上和挂钩SSDT本质上没有不同,都是在KiServiceTable的指定偏移处写入一个INT32值。 再次运行这个枚举SSDT的程序,发现NtTerminateProcess项目已经没异常了: ? 至此,全文完。
在前面的章节《X86驱动:挂接SSDT内核钩子》我们通过代码的方式直接读取 KeServiceDescriptorTable 这个被导出的表结构从而可以直接读取到SSDT表的基址,而在Win64系统中 Base= %11x", Get_SSTD_Base());DriverObject->DriverUnload = UnDriver;return STATUS_SUCCESS;}3.接着我们则需要获取到SSDT \n"));}ULONGLONG Get_SSDT_Base(){PUCHAR Base = (PUCHAR)__readmsr(0xC0000082); // 读取C0000082寄存器PUCHAR GetSSDTFunction(ULONGLONG Index){LONG dwTemp = 0;ULONGLONG qwTemp = 0, stb = 0, ret = 0;PSYSTEM_SERVICE_TABLE ssdt = (PSYSTEM_SERVICE_TABLE)Get_SSDT_Base();stb = (ULONGLONG)(ssdt->ServiceTableBase);qwTemp = stb + 4
在前面的章节《X86驱动:挂接SSDT内核钩子》我们通过代码的方式直接读取 KeServiceDescriptorTable 这个被导出的表结构从而可以直接读取到SSDT表的基址,而在Win64系统中 11x", Get_SSTD_Base()); DriverObject->DriverUnload = UnDriver; return STATUS_SUCCESS; } 3.接着我们则需要获取到SSDT \n")); } ULONGLONG Get_SSDT_Base() { PUCHAR Base = (PUCHAR)__readmsr(0xC0000082); // 读取C0000082 ULONGLONG Index) { LONG dwTemp = 0; ULONGLONG qwTemp = 0, stb = 0, ret = 0; PSYSTEM_SERVICE_TABLE ssdt = (PSYSTEM_SERVICE_TABLE)Get_SSDT_Base(); stb = (ULONGLONG)(ssdt->ServiceTableBase); qwTemp = stb
SSDT-hook,IDT-hook,sysenter-hook 一.SSDT-hook (一)一般思路: 1.先来了解一下,什么是SSDT SSDT既System Service Dispath 从上可知,SSDT就是一个表,这个表中有内核调用的函数地址。 下来详细了解一下,SSDT的结构,如下图: SSDT.jpg SSDT.JPG KeServiceDescriptorTable:是由内核(Ntoskrnl.exe)导出的一个表,这个表是访问SSDT 下来就是去改变SSDT所指向的函数,使之指向我们自己的函数。 2.Hook前的准备-改变SSDT内存的保护 系统对SSDT都是只读的,不能写。如果试图去写,等你的就是蓝脸。 macro:获得Zw*函数的地址并返回与之通信的函数在SSDT中的索引。
安装SSIS 和 SSDT 使用安装光盘安装SSIS和SSDT。 注意:对于SQL Server 2014,安装光盘没有附带安装文件,需要从官网下载Visual Studio对应的SSDT安装程序。 二、修复SSDT 如果本机还安装了其它版本的SQL Server并覆盖了注册表,那么SSDT可能需要修复。例如,出现如下的错误。 ? 解决方案:使用安装光盘,重新安装SSDT。 三、启用SSDT 1. SSDT简介 SSDT 是一个特殊的 Visual Studio 版本。也可以看作是 Visual Studio 集成环境中添加了一些商业智能的模板。 在SQL Server 2012之前的版本中,SSDT被称为BIDS。关于SSDT的介绍,详见 http://jimshu.blog.51cto.com/3171847/1336662 2.
在前面的博文《驱动开发:内核读取SSDT表基址》中已经教大家如何寻找SSDT表基地址了,今天给大家分享两个适用于WinDBG调试器上的脚本文件,该脚本文件可以很好的枚举出当前系统内的SSDT以及SSSDT 第一段脚本可用于枚举64位系统下所有的SSDT表,将脚本保存为enum_ssdt.log写入以下内容。 ufLinkE} (%y)\n", @$t0, @$t3, @$t3, @$t3, @$t3; } .printf "\n- end -\n"; 回到WinDBG中输入命令$><d://enum_ssdt.log
结构导出表》中我们封装了两个函数KernelMapFile()函数可用来读取内核文件,GetAddressFromFunction()函数可用来在导出表中寻找指定函数的导出地址,本章将以此为基础实现对特定SSDT // 署名权// right to sign one's name on a piece of work// PowerBy: LyShark// Email: me@lyshark.com// 挂钩SSDT FileInformation,Length,FileInformationClass,ReturnSingleEntry,FileMask,RestartScan);return status;}// 挂钩SSDT ulNewFuncAddr, sizeof(ULONG));// 释放MmUnmapLockedPages(pNewAddress, pMdl);IoFreeMdl(pMdl);return TRUE;}// 恢复SSDT
在笔者上一篇文章《驱动开发:内核实现SSDT挂钩与摘钩》中介绍了如何对SSDT函数进行Hook挂钩与摘钩的,本章将继续实现一个新功能,如何检测SSDT函数是否挂钩,要实现检测挂钩状态有两种方式,第一种方式则是类似于
在前面的博文《驱动开发:Win10内核枚举SSDT表基址》中已经教大家如何寻找SSDT表基地址了,找到后我们可根据序号获取到指定SSDT函数的原始地址,而如果需要输出所有SSDT表信息,则可以定义字符串列表 以此循环调用GetSSDTFunctionAddress()函数得到,当然在此之间也可以调用系统提供的MmGetSystemRoutineAddress()函数顺便把当前地址拿到,并通过循环方式得到完整的SSDT 表我们可以这样来实现,通过将完整的SSDT结构字符串放入到SSDT变量内,然后通过不间断的循环取出每一个SSDT函数的相对地址信息。 == 0) { // 得到ssdt基地址 ssdt_base_aadress = GetKeServiceDescriptorTable(); } if (scfn == NULL) = GetKeServiceDescriptorTable(); // DbgPrint("SSDT基地址 = %p \n", ssdt_address); // 根据序号得到函数地址
在笔者上一篇文章《驱动开发:内核实现SSDT挂钩与摘钩》中介绍了如何对SSDT函数进行Hook挂钩与摘钩的,本章将继续实现一个新功能,如何检测SSDT函数是否挂钩,要实现检测挂钩状态有两种方式,第一种方式则是类似于