设为首页 加入收藏

TOP

驱动开发:Win10枚举完整SSDT地址表(一)
2023-07-23 13:29:49 】 浏览:133
Tags:Win10 SSDT

在前面的博文《驱动开发:Win10内核枚举SSDT表基址》中已经教大家如何寻找SSDT表基地址了,找到后我们可根据序号获取到指定SSDT函数的原始地址,而如果需要输出所有SSDT表信息,则可以定义字符串列表,以此循环调用GetSSDTFunctionAddress()函数得到,当然在此之间也可以调用系统提供的MmGetSystemRoutineAddress()函数顺便把当前地址拿到,并通过循环方式得到完整的SSDT列表。

调用MmGetSystemRoutineAddress()得到当前地址很容易实现,只需要将函数名字符串通过RtlInitUnicodeString()格式化一下即可。

// 署名权
// right to sign one's name on a piece of work
// PowerBy: LyShark
// Email: me@lyshark.com

#include <ntifs.h>

VOID UnDriver(PDRIVER_OBJECT driver)
{
	DbgPrint(("驱动程序卸载成功! \n"));
}

NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
	DbgPrint("hello lyshark.com \n");

	// 获取SSDT起源地址
	UNICODE_STRING uncode;
	RtlInitUnicodeString(&uncode, L"NtOpenFile");
	PULONGLONG source_address = MmGetSystemRoutineAddress(&uncode);
	DbgPrint("[LyShark] NtOpenFile起源地址 = %p \n", source_address);

	DriverObject->DriverUnload = UnDriver;
	return STATUS_SUCCESS;
}

代码获得NtOpenFile这个函数的内存地址,输出效果如下所示:

根据上一章节的内容扩展,枚举完整SSDT表我们可以这样来实现。

// 署名权
// right to sign one's name on a piece of work
// PowerBy: LyShark
// Email: me@lyshark.com

#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;

ULONGLONG ssdt_base_aadress;
PSYSTEM_SERVICE_TABLE KeServiceDescriptorTable;

typedef UINT64(__fastcall *SCFN)(UINT64, UINT64);
SCFN scfn;

// 解密算法
VOID DecodeSSDT()
{
	UCHAR strShellCode[36] = "\x48\x8B\xC1\x4C\x8D\x12\x8B\xF8\xC1\xEF\x07\x83\xE7\x20\x4E\x8B\x14\x17\x4D\x63\x1C\x82\x49\x8B\xC3\x49\xC1\xFB\x04\x4D\x03\xD3\x49\x8B\xC2\xC3";
	/*
	48:8BC1                  | mov rax,rcx                             |  rcx=index
	4C:8D12                  | lea r10,qword ptr ds:[rdx]              |  rdx=ssdt
	8BF8                     | mov edi,eax                             |
	C1EF 07                  | shr edi,7                               |
	83E7 20                  | and edi,20                              |
	4E:8B1417                | mov r10,qword ptr ds:[rdi+r10]          |
	4D:631C82                | movsxd r11,dword ptr ds:[r10+rax*4]     |
	49:8BC3                  | mov rax,r11                             |
	49:C1FB 04               | sar r11,4                               |
	4D:03D3                  | add r10,r11                             |
	49:8BC2                  | mov rax,r10                             |
	C3                       | ret                                     |
	*/
	scfn = ExAllocatePool(NonPagedPool, 36);
	memcpy(scfn, strShellCode, 36);
}

// 获取 KeServiceDescriptorTable 首地址
ULONGLONG GetKeServiceDescriptorTable()
{
	// 设置起始位置
	PUCHAR StartSearchAddress = (PUCHAR)__readmsr(0xC0000082) - 0x1806FE;

	// 设置结束位置
	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.com
			// 4c 8d 15 e5 9e 3b 00  lea r10,[nt!KeServiceDescriptorTable (fffff802`64da4880)]
			// 4c 8d 1d de 20 3a 00  lea r11,[nt!KeServiceDescriptorTableShadow (fffff802`64d8ca80)]
			if (OpCodeA == 0x4c && OpCodeB == 0x8d &&
首页 上一页 1 2 3 4 5 6 7 下一页 尾页 1/7/7
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇驱动开发:内核特征码扫描PE代码段 下一篇驱动开发:Win10内核枚举SSDT表基..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目