开发一个网站需要多久,wordpress开玩笑 呵,全国物流网站,为一个村做网站在Windows内核中#xff0c;SSSDT#xff08;System Service Shadow Descriptor Table#xff09;是SSDT#xff08;System Service Descriptor Table#xff09;的一种变种#xff0c;其主要用途是提供Windows系统对系统服务调用的阴影拷贝。SSSDT表存储了系统调用的函数…在Windows内核中SSSDTSystem Service Shadow Descriptor Table是SSDTSystem Service Descriptor Table的一种变种其主要用途是提供Windows系统对系统服务调用的阴影拷贝。SSSDT表存储了系统调用的函数地址类似于SSDT表但在某些情况下Windows系统会使用SSSDT表来对系统服务进行引导和调用。
SSSDT表的存在是为了加强系统的安全性和稳定性。通过使用SSSDT表操作系统可以在运行时检查系统服务的合法性并确保其不被非法修改。这有助于防止恶意软件或恶意行为修改系统服务地址提高系统的整体安全性。
在笔者上一篇文章《枚举完整SSDT地址表》实现了针对SSDT表的枚举功能本章继续实现对SSSDT表的枚举ShadowSSDT中文名影子系统服务描述表SSSDT其主要的作用是管理系统中的图形化界面其Win32子系统的内核实现是Win32k.sys驱动属于GUI线程的一部分其自身没有导出表枚举SSSDT表其与SSDT原理基本一致。
如下是闭源ARK工具的枚举效果: 首先需要找到SSSDT表的位置通过《Win10内核枚举SSDT表基址》文章中的分析可知SSSDT就在SSDT的下面只需要枚举4c8d1dde1e3a00特征即可如果你找不到上一篇具体分析流程了那么多半你是看到了转载文章。 先实现第一个功能得到SSSDT表的基地址以及SSDT函数个数完整代码如下所示。
#include ntifs.h
#pragma intrinsic(__readmsr)typedef struct _SYSTEM_SERVICE_TABLE
{PVOID ServiceTableBase;PVOID ServiceCounterTableBase;ULONGLONG NumberOfServices;PVOID ParamTableBase;
} SYSTEM_SERVICE_TABLE, *PSYSTEM_SERVICE_TABLE;PSYSTEM_SERVICE_TABLE KeServiceDescriptorTableShadow 0;
ULONG64 ul64W32pServiceTable 0;// 获取 KeServiceDescriptorTableShadow 首地址
ULONGLONG GetKeServiceDescriptorTableShadow()
{// 设置起始位置PUCHAR StartSearchAddress (PUCHAR)__readmsr(0xC0000082) - 0x1808FE;// 设置结束位置PUCHAR EndSearchAddress StartSearchAddress 0x8192;// DbgPrint(扫描起始地址: %p -- 扫描结束地址: %p \n, StartSearchAddress, EndSearchAddress);PUCHAR ByteCode NULL;UCHAR OpCodeA 0, OpCodeB 0, OpCodeC 0;ULONGLONG addr 0;ULONG templong 0;for (ByteCode StartSearchAddress; ByteCode EndSearchAddress; ByteCode){// 使用MmIsAddressValid()函数检查地址是否有页面错误if (MmIsAddressValid(ByteCode) MmIsAddressValid(ByteCode 1) MmIsAddressValid(ByteCode 2)){OpCodeA *ByteCode;OpCodeB *(ByteCode 1);OpCodeC *(ByteCode 2);// 对比特征值 寻找 nt!KeServiceDescriptorTable 函数地址/*lyshark kd u KiSystemServiceRepeatnt!KiSystemServiceRepeat:fffff8027c1d2b94 4c8d15e59c3b00 lea r10,[nt!KeServiceDescriptorTable (fffff8027c58c880)]fffff8027c1d2b9b 4c8d1dde1e3a00 lea r11,[nt!KeServiceDescriptorTableShadow (fffff8027c574a80)]fffff8027c1d2ba2 f7437880000000 test dword ptr [rbx78h],80hfffff8027c1d2ba9 7413 je nt!KiSystemServiceRepeat0x2a (fffff8027c1d2bbe)fffff8027c1d2bab f7437800002000 test dword ptr [rbx78h],200000hfffff8027c1d2bb2 7407 je nt!KiSystemServiceRepeat0x27 (fffff8027c1d2bbb)fffff8027c1d2bb4 4c8d1d051f3a00 lea r11,[nt!KeServiceDescriptorTableFilter (fffff8027c574ac0)]fffff8027c1d2bbb 4d8bd3 mov r10,r11*/if (OpCodeA 0x4c OpCodeB 0x8d OpCodeC 0x1d){// 获取高位地址fffff802memcpy(templong, ByteCode 3, 4);// 与低位64da4880地址相加得到完整地址addr (ULONGLONG)templong (ULONGLONG)ByteCode 7;return addr;}}}return 0;
}// 得到SSSDT个数
ULONGLONG GetSSSDTCount()
{PSYSTEM_SERVICE_TABLE pWin32k;ULONGLONG W32pServiceTable;pWin32k (PSYSTEM_SERVICE_TABLE)((ULONG64)KeServiceDescriptorTableShadow sizeof(SYSTEM_SERVICE_TABLE));W32pServiceTable (ULONGLONG)(pWin32k-ServiceTableBase);// DbgPrint(Count %d \n, pWin32k-NumberOfServices);return pWin32k-NumberOfServices;
}VOID UnDriver(PDRIVER_OBJECT driver)
{DbgPrint((驱动程序卸载成功! \n));
}NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{DbgPrint(hello lyshark \n);KeServiceDescriptorTableShadow (PSYSTEM_SERVICE_TABLE)GetKeServiceDescriptorTableShadow();DbgPrint([LyShark] SSSDT基地址 0x%p \n, KeServiceDescriptorTableShadow);ULONGLONG count GetSSSDTCount();DbgPrint([LyShark] SSSDT个数 %d \n, count);DriverObject-DriverUnload UnDriver;return STATUS_SUCCESS;
}这段代码运行后即可得到SSSDT表基地址以及该表中函数个数。 在此基础之上增加枚举计算过程即可完整源代码如下所示。
SSSDT 函数起始index是0x1000但W32pServiceTable是从基址开始记录的这个误差则需要(index-0x1000)来得到至于4则是下一个元素与上一个元素的偏移。
计算公式
W32pServiceTable 4 * (index-0x1000)
#include ntifs.h
#pragma intrinsic(__readmsr)typedef struct _SYSTEM_SERVICE_TABLE
{PVOID ServiceTableBase;PVOID ServiceCounterTableBase;ULONGLONG NumberOfServices;PVOID ParamTableBase;
} SYSTEM_SERVICE_TABLE, *PSYSTEM_SERVICE_TABLE;PSYSTEM_SERVICE_TABLE KeServiceDescriptorTableShadow 0;
ULONG64 ul64W32pServiceTable 0;// 获取 KeServiceDescriptorTableShadow 首地址
ULONGLONG GetKeServiceDescriptorTableShadow()
{// 设置起始位置PUCHAR StartSearchAddress (PUCHAR)__readmsr(0xC0000082) - 0x1808FE;// 设置结束位置PUCHAR EndSearchAddress StartSearchAddress 0x8192;// DbgPrint(扫描起始地址: %p -- 扫描结束地址: %p \n, StartSearchAddress, EndSearchAddress);PUCHAR ByteCode NULL;UCHAR OpCodeA 0, OpCodeB 0, OpCodeC 0;ULONGLONG addr 0;ULONG templong 0;for (ByteCode StartSearchAddress; ByteCode EndSearchAddress; ByteCode){// 使用MmIsAddressValid()函数检查地址是否有页面错误if (MmIsAddressValid(ByteCode) MmIsAddressValid(ByteCode 1) MmIsAddressValid(ByteCode 2)){OpCodeA *ByteCode;OpCodeB *(ByteCode 1);OpCodeC *(ByteCode 2);// 对比特征值 寻找 nt!KeServiceDescriptorTable 函数地址/*lyshark kd u KiSystemServiceRepeatnt!KiSystemServiceRepeat:fffff8027c1d2b94 4c8d15e59c3b00 lea r10,[nt!KeServiceDescriptorTable (fffff8027c58c880)]fffff8027c1d2b9b 4c8d1dde1e3a00 lea r11,[nt!KeServiceDescriptorTableShadow (fffff8027c574a80)]fffff8027c1d2ba2 f7437880000000 test dword ptr [rbx78h],80hfffff8027c1d2ba9 7413 je nt!KiSystemServiceRepeat0x2a (fffff8027c1d2bbe)fffff8027c1d2bab f7437800002000 test dword ptr [rbx78h],200000hfffff8027c1d2bb2 7407 je nt!KiSystemServiceRepeat0x27 (fffff8027c1d2bbb)fffff8027c1d2bb4 4c8d1d051f3a00 lea r11,[nt!KeServiceDescriptorTableFilter (fffff8027c574ac0)]fffff8027c1d2bbb 4d8bd3 mov r10,r11*/if (OpCodeA 0x4c OpCodeB 0x8d OpCodeC 0x1d){// 获取高位地址fffff802memcpy(templong, ByteCode 3, 4);// 与低位64da4880地址相加得到完整地址addr (ULONGLONG)templong (ULONGLONG)ByteCode 7;return addr;}}}return 0;
}// 得到SSSDT个数
ULONGLONG GetSSSDTCount()
{PSYSTEM_SERVICE_TABLE pWin32k;ULONGLONG W32pServiceTable;pWin32k (PSYSTEM_SERVICE_TABLE)((ULONG64)KeServiceDescriptorTableShadow sizeof(SYSTEM_SERVICE_TABLE));W32pServiceTable (ULONGLONG)(pWin32k-ServiceTableBase);// DbgPrint(Count %d \n, pWin32k-NumberOfServices);return pWin32k-NumberOfServices;
}VOID UnDriver(PDRIVER_OBJECT driver)
{DbgPrint((驱动程序卸载成功! \n));
}NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{DbgPrint(hello lyshark \n);KeServiceDescriptorTableShadow (PSYSTEM_SERVICE_TABLE)GetKeServiceDescriptorTableShadow();DbgPrint([LyShark] SSSDT基地址 0x%p \n, KeServiceDescriptorTableShadow);ULONGLONG count GetSSSDTCount();DbgPrint([LyShark] SSSDT个数 %d \n, count);// 循环枚举SSSDTfor (size_t Index 0; Index count; Index){PSYSTEM_SERVICE_TABLE pWin32k;ULONGLONG W32pServiceTable;pWin32k (PSYSTEM_SERVICE_TABLE)((ULONG64)KeServiceDescriptorTableShadow sizeof(SYSTEM_SERVICE_TABLE));W32pServiceTable (ULONGLONG)(pWin32k-ServiceTableBase);// 获取SSSDT地址//ln win32k!W32pServiceTable((poi(win32k!W32pServiceTable4*(1-1000))0x00000000ffffffff)4)-10000000//u win32k!W32pServiceTable((poi(win32k!W32pServiceTable4*(Index-0x1000))0x00000000ffffffff)4)-0x10000000//u poi(win32k!W32pServiceTable4*(1-0x1000))//u poi(win32k!W32pServiceTable4*(1-0x1000))0x00000000ffffffff//u (poi(win32k!W32pServiceTable4*(1-0x1000))0x00000000ffffffff)4//u win32k!W32pServiceTable((poi(win32k!W32pServiceTable4*(1-0x1000))0x00000000ffffffff)4)-0x10000000ULONGLONG qword_temp 0;LONG dw 0;// SSSDT 下标从1000开始而W32pServiceTable是从0开始// 4 则是每次向下4字节就是下一个地址qword_temp W32pServiceTable 4 * (Index - 0x1000);dw *(PLONG)qword_temp;// dw qword_temp 0x00000000ffffffff;dw dw 4;qword_temp W32pServiceTable (LONG64)dw;DbgPrint([LyShark] ID: %d | SSSDT: 0x%p \n, Index, qword_temp);}DriverObject-DriverUnload UnDriver;return STATUS_SUCCESS;
}枚举效果如下图所示所示注意这一步必须要在GUI线程中执行否则会异常建议将枚举过程写成DLL文件注入到explorer.exe进程内执行