吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 8954|回复: 35
收起左侧

[系统底层] 【原创】TP驱动保护分析系列三 SSDT定位内核函数

  [复制链接]
lyl610abc 发表于 2021-7-10 19:02
本帖最后由 lyl610abc 于 2021-7-10 19:04 编辑

系列索引

【原创】TP驱动保护分析系列一 定位TenProtect保护

【原创】TP驱动保护分析系列二 代码定位内核函数

【原创】TP驱动保护分析系列三 SSDT定位内核函数


前言

前面在【原创】TP驱动保护分析系列二 代码定位内核函数 中介绍了通过驱动函数MmGetSystemRoutineAddress直接定位和特征码定位法两种定位方式。接下来继续介绍代码定位内核函数的方法:SSDT定位法


SSDT定位内核函数

SSDT

既然要通过SSDT来定位,首先就要知道什么是SSDT

SSDT是什么

SSDT全称System Service Descriptor TableSystem Service Dispatch Table,即系统服务描述表或系统服务分派表。一般被称作系统服务描述表居多,但要了解它和系统服务分派表是同一个东西


SSDT本质是32位操作系统内核routine的地址数组,或是64位操作系统相同routine的相对偏移量数组

这里的routine是指SSDT函数,如NtOpenProcess

也就是说:SSDT本质是32位操作系统SSDT函数的地址数组,或是64位操作系统相同SSDT函数的相对偏移量数组

简单来说:SSDT是个数组,这个数组在32位系统存储SSDT函数的地址;在64位系统存储SSDT函数的相对偏移量

SSDT是Service Descriptor Table内存结构的第一个成员,结构如下:

typedef struct tagSERVICE_DESCRIPTOR_TABLE {
    SYSTEM_SERVICE_TABLE nt; //实际上是指向SSDT本身的指针
    SYSTEM_SERVICE_TABLE win32k;
    SYSTEM_SERVICE_TABLE sst3; //指向内存地址的指针,该地址包含表中定义了多少个SSDT函数
    SYSTEM_SERVICE_TABLE sst4;
} SERVICE_DESCRIPTOR_TABLE;

PS:由于先前在WINDOWS XP上各种SSDT HOOK等修改内核的操作被大家玩得飞起,导致微软为后来的x64系统引入了PatchGuard机制。该机制会检测系统内核是否被修改,若发现被修改就无情地BSOD蓝屏,以此来对抗SSDT HOOK


通过SSDT可以干什么

通过前面的介绍,不难发现SSDT存储着和SSDT函数地址相关的数据,32位系统直接存储的就是地址,64位系统则是相对偏移量。因此通过SSDT就能够定位到SSDT函数

以NtOpenProcess为例,定位该函数的过程可简略为:

(SSDT 和 NtOpenProcess的索引)某种运算→ NtOpenProcess

关于如何获取SSDT函数对应的索引和运算的方法放在本篇的后面介绍


定位SSDT

既然知道了通过SSDT可以定位到SSDT函数,就得想办法定位SSDT

前面提到了SSDT是Service Descriptor Table内存结构的第一个成员,而我们可以通过KeServiceDescriptorTable得到Service Descriptor Table内存结构的地址

通过windbg可以通过下面的指令直接查看:

dps nt!keservicedescriptortable L4

dqs指令是将每qword(8字节)视为一个符号进行解析并显示出来,L4表示显示4个qword的长度

除此之外还有dds和dps,dds是每dword(4字节),dps是根据当前处理器架构来选择最合适的长度

查看得到:

t

即:

kd> dps nt!keservicedescriptortable L4
8055d700  80505570 nt!KiServiceTable
8055d704  00000000
8055d708  0000011c
8055d70c  805059e4 nt!KiArgumentTable

这里得到的数据分别对应先前的结构体,填入对应的结构得到:

对应结构 说明
nt 80505570 nt!KiServiceTable SSDT的首地址为80505570
win32k 00000000
sst3 0000011c SSDT函数一共有0x11c=284个
sst4 805059e4 nt!KiArgumentTable

拿到SSDT的首地址后让我们尝试从SSDT中打印出几个值

在windbg中输入指令:

dd /c1 KiServiceTable L2

/c? 指定显示中使用的列数。如果省略,则默认的列数取决于显示类型;这里为指定显示使用列数为1

查看得到:

b

即:

kd> dd /c1 KiServiceTable L2
80505570  805a5664
80505574  805f23ea

因为测试的环境为Windows XP 32位,所以SSDT存储的直接就是SSDT函数的地址

PS:关于64位系统如何通过偏移量得到对应的SSDT函数,这里不做说明,感兴趣的可以查看下面的参考链接中的第一个参考链接,里面有说明

这里得到的就是头两个SSDT函数的地址,为了验证这一点,分别查看对应地址的反汇编:

u 805a5664
u 805f23ea

查看得到:

image-20210710112823195

得到了前两个SSDT函数:NtAcceptConnectPort和NtAccessCheck

对应并验证了SSDT表中存储着SSDT函数的地址


获取SSDT函数对应索引

想要定位到SSDT函数,首先要获取SSDT函数对应的索引

下面以NtOpenProcess为例,介绍如何获取对应的索引

首先要载入ntdll.dll模块,该模块中有SSDT函数相关的调用,RING3也是通过该模块调用SSDT函数的

具体的内容不展开,留做之后的系统调用再做讲解(挖坑`(>﹏<)′)

依旧使用Windbg工具(其实用IDA Pro或其他工具也可以查看):

!process 0 0 calc.exe
.process /p eprocess
.reload /f ntdll.dll
lm ntdll

!process 扩展显示关于指定进程的信息,或关于所有进程的信息,包括EPROCESS块

.process 指定进程上下文使用哪个进程

/p 在访问之前将此进程的所有转换页表项转换为物理地址

.reload命令删除指定模块的所有符号信息,并根据需要重新加载这些符号。在某些情况下,该命令还会重新加载或卸载模块本身

/f 强制调试器立即加载符号。此参数覆盖惰性符号加载

lm 显示指定加载的模块。输出包括模块的状态和路径

指令说明:

  1. 在加载ntdll.dll模块前,需要先用windbg附加到一个非系统进程上,这里选用了系统自带的计算器(要先打开计算器)进行附加。通过!processs指令得到对应的eprocess
  2. 得到eprocess后就可以使用.process指令附加到计算器上了
  3. 附加完毕后,重新载入ntdll.dll模块
  4. 最后查看模块的加载情况,确保ntdll已成功加载

过程图如下:

image-20210710130419621


接下来使用指令查看对应SSDT函数的反汇编:

u ntdll!NtOpenProcess

显示得到:

image-20210710130907869


这里就获取到了NtOpenProcess对应的索引为:0x7A


根据索引找到对应的SSDT函数

得到SSDT的首地址,再加上索引就可以计算得到SSDT

计算公式为:

SSDT函数地址 = SSDT首地址 + 4 × SSDT函数对应函数索引

前面得到的SSDT首地址为:0x80505570 ,NtOpenProcess对应的索引为:0x7A

代入计算:

存放NtOpenProcess地址的地址 = 0x80505570  + 4 × 0x7A =0x80505758

image-20210710131432056


接着验证一下计算得到的地址是否正确:

dd 0x80505758 L1

查看得到:

image-20210710132155774

得到NtOpenProcess的地址为:0x805cc486

反汇编查看这个地址,验证是否为NtOpenProcess

u 0x805cc486

查看得到:

image-20210710132313755

验证完毕,结果正确O(∩_∩)O


小结

通常定位一个SSDT函数时会有以下步骤:

确定要定位的SSDT函数→到ntdll.dll中查看对应的函数反汇编→通过反汇编得到索引→通过KeServiceDescriptorTable获得SSDT首地址→通过首地址和索引计算得到SSDT函数地址


代码实现SSDT定位

知道了原理以后就不难用代码实现SSDT定位了

要注意的是,在WINDOWS XP中,KeServiceDescriptorTable是导出的,可以声明后直接使用

但在WIN7和WIN7之后的系统中,KeServiceDescriptorTable没有被导出,可以使用读取MSR寄存器+特征码定位法来获得KeServiceDescriptorTable的地址,这里不做赘述

代码

代码如下:

#include <ntifs.h>
//这里的结构正是之前在 SSDT是什么中 说明的
typedef struct tagSERVICE_DESCRIPTOR_TABLE {
        PULONG    nt; //实际上是指向SSDT本身的指针
        PULONG win32k;
        ULONG    sst3; //指向内存地址的指针,该地址包含表中定义了多少个SSDT函数
        PUCHAR sst4;
} SERVICE_DESCRIPTOR_TABLE, * PSERVICE_DESCRIPTOR_TABLE;
//这里直接引入即可
extern PSERVICE_DESCRIPTOR_TABLE KeServiceDescriptorTable;

/*
        根据SSDT函数对应索引获取SSDT函数地址
        index 要获取的SSDT函数对应的索引
*/
PVOID GetSSDTFunctionAddr(ULONG index)
{
        PVOID Addr;

        __asm
        {
                mov ebx, index                //ebx = index
                shl ebx, 2                        //shl xxx,2 左移两位 就是乘以4 即ebx=ebx*4=index*4
                mov eax, KeServiceDescriptorTable        // eax = KeServiceDescriptorTable       
        // eax = KeServiceDescriptorTable的dword(四个字节 正好是其第一个成员的数据宽度)的值 
        // 而KeServiceDescriptorTable的第一个成员就指向SSDT本身,故 eax = SSDT首地址
                mov eax, dword ptr ds:[eax]        
                add eax, ebx                // eax = eax + ebx = SSDT首地址 + index*4  就是前面的公式
                mov ecx, [eax]
                mov Addr, ecx
        }

        return Addr;
}

VOID DriverUnload(IN PDRIVER_OBJECT DriverObject)
{
        DbgPrint("卸载完成!\n");
}

NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{

        DbgPrint("加载完成!\n");

        DbgPrint("NtOpenProcess:%p\n", GetSSDTFunctionAddr(0x7A));

        DriverObject->DriverUnload = DriverUnload;

        return STATUS_SUCCESS;
}

运行结果

运行结果如下图所示:

image-20210710182331961

可以看到输出的NtOpenProcess地址为:0x805CC486

验证结果

使用Windbg验证结果:

u 0x805CC486

查看得到:

image-20210710182826825

验证完毕o(^▽^)┛


总结

代码实现SSDT其实并没有什么难点,直接声明后引入KeServiceDescriptorTable,然后通过之前的公式计算出对应的SSDT函数地址即可

在WINDOWS XP系统下由于KeServiceDescriptorTable有直接导出,所以实现起来相对简单。若要在WIN7和WIN7之后的系统定位SSDT函数,则需要注意要先定位KeServiceDescriptorTable,且SSDT存储的是相对偏移,计算方式略有差异。其他方面,原理都差不多,想实现的朋友可以自己研究研究,这里就不再赘述≡(▔﹏▔)≡


附件

附上本篇编译出的打印NtOpenProcess地址的驱动文件,想试验能不能用的可以测试下╰( ̄ω ̄o)

PS:环境一定要是WINDOWS XP 32位

不同版本系统的SSDT函数对应的索引号不一定相同,注意查看要编写驱动环境的ntdll.dll文件中的索引号

如果本篇提供的成品中打印的地址不对,是其他的SSDT函数的地址,可能就是由于索引号不相同导致的

附件下载地址:点我下载

本篇中用到的其他工具可回顾:【原创】TP驱动保护分析系列二 代码定位内核函数 的附件部分


参考链接

System Service Descriptor Table - SSDT - Red Teaming Experiments (ired.team)

SSDT-System-Service-Descriptor-Table - aldeid

d, da, db, dc, dd, dD, df, dp, dq, du, dw (Display Memory) - Windows drivers | Microsoft Docs

dds, dps, dqs (Display Words and Symbols) - Windows drivers | Microsoft Docs

.reload (Reload Module) - Windows drivers | Microsoft Docs

lm (List Loaded Modules) - Windows drivers | Microsoft Docs

process - Windows drivers | Microsoft Docs

.process (Set Process Context) - Windows drivers | Microsoft Docs

getSSDTFunc.zip

2.37 KB, 下载次数: 25, 下载积分: 吾爱币 -1 CB

论坛备份,土豪专属通道

免费评分

参与人数 22吾爱币 +29 热心值 +21 收起 理由
junjia215 + 1 + 1 谢谢@Thanks!
Nattevak + 1 + 1 我很赞同!
popkun222 + 1 谢谢@Thanks!
Chenda1 + 1 + 1 我很赞同!
sam喵喵 + 1 谢谢@Thanks!
5omggx + 1 + 1 用心讨论,共获提升!
xiahhhr + 1 + 1 用心讨论,共获提升!
qq258q1559949 + 1 + 1 你分析这些有个毛用,网上随便找个文章都知道,关键怎么恢复hook的钩子怎么.
qaz003 + 1 + 1 大大的赞。。太好看了
aywl47 + 1 + 1 我很赞同!
风中找感觉 + 1 + 1 谢谢@Thanks!
jy04468108 + 1 + 1 用心讨论,共获提升!
debug_cat + 2 + 1 用心讨论,共获提升!
侃遍天下无二人 + 2 + 1 小柠檬yyds
哥哥的肥皂 + 1 + 1 鼓励转贴优秀软件安全工具和文档!
zjun777 + 1 + 1 我很赞同!
风绕柳絮轻敲雪 + 4 + 1 我很赞同!
gxkyrftx + 1 + 1 不错不错,学习
正己 + 2 + 1 小柠檬tql
国际豆哥 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
niucaidi + 2 + 1 用心讨论,共获提升!
qianshang666 + 2 + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

头像被屏蔽
qq258q1559949 发表于 2021-7-13 06:22
提示: 该帖被管理员或版主屏蔽
 楼主| lyl610abc 发表于 2021-7-13 19:30
本帖最后由 lyl610abc 于 2021-7-13 19:31 编辑
qq258q1559949 发表于 2021-7-13 06:22
你分析这些有个毛用,发帖子等于放屁一样,百度网上随便找个文章都知道,关键怎么恢复hook的钩子怎么绕过tp ...

这是一个系列,前面是铺垫,先分析TP的保护,再定位,定位到之后才是HOOK和绕过。
本系列旨在梳理分析思路及原理,然后按思路步骤一步步走到最终结果,现在还在铺垫阶段,后续会更新相关恢复HOOK和绕过TP的内容。
如果觉得没用可以不看,没必要攻击我。

免费评分

参与人数 2吾爱币 +1 热心值 +2 收起 理由
sam喵喵 + 1 + 1 不用理会没素质的人
侃遍天下无二人 + 1 用心讨论,共获提升!

查看全部评分

niucaidi 发表于 2021-7-10 19:13
雨落惊鸿, 发表于 2021-7-10 19:27
感谢分享
侃遍天下无二人 发表于 2021-7-10 19:36

我擦,还有这层关系
国际豆哥 发表于 2021-7-10 20:28
吊毛终于更新了!!!!
国际豆哥 发表于 2021-7-10 20:30

一个公司的?
侃遍天下无二人 发表于 2021-7-10 21:01
国际豆哥 发表于 2021-7-10 20:28
吊毛终于更新了!!!!

骂人违规+1
李波 发表于 2021-7-10 21:51
可以的 大佬研究的还行哦~
tan567421 发表于 2021-7-10 22:39
感谢更新····
ttdz45 发表于 2021-7-11 01:00
虽然现在还看不懂,但在学习中
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-12-21 23:37

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表