32位/64位WINDOWS驱动之 遍历+HOOK_SSDT_NtOpenProcess函数_w7_w10通用系统版本

32位/64位WINDOWS驱动之 遍历+HOOK_SSDT_NtOpenProcess函数_w7_w10通用系统版本

前言

/*
aria v1.0
*在易编程学院发布。
*HOOK_NtOpenProcess
*版权所有 2023
*许可证:ybc-cn
*修改时间:2024年1月21日17:42:26(中国标准时间)
这个写法是正确的不知道为什么在我自己的W10_64位系统中不起作用,在w7_64位中正常,
可能是系统版本导致的,我的系统版本是
‘版本Windows 10 专业版 版本号 22H2,操作系统内部版本19045.3570 不行
’版本Windows 10 专业版 版本号 1909,操作系统内部版本18363.592 不行
‘版本Windows 10 专业版 版本号 1709,操作系统内部版本16299. 可以
'版本Windows 7 旗航舰 版本号 6.1,操作系统内部版本7601. 可以

*/


一、定义代码

KIRQL WPOFF()//关闭写保护
{
	KIRQL irql = KeRaiseIrqlToDpcLevel();
	ULONG64 cr0 = __readcr0();
	//ULONG_PTR 这个类型在x86上是32位  x64就是64位
#ifdef _X86_
	cr0 &= 0xfffeffff;
#else
	cr0 &= 0xfffffffffffeffff;
#endif
	//cr0 &= 0xFFFFFFFFFFFEFFFF;
	_disable();//关闭中断
	__writecr0(cr0);//关闭写保护位
	return irql;
}

VOID WPON(KIRQL irql)//打开写保护
{
	ULONG64 cr0 = __readcr0();
	cr0 |= 0x10000;
	__writecr0(cr0);//恢复写保护位
	_enable();//恢复中断
	KeLowerIrql(irql);
}

/*
aria v1.0
	*在易编程学院发布。
	*HOOK_NtOpenProcess
	*版权所有 2023
	*许可证:ybc-cn
	*修改时间:2024年1月21日17:42:26(中国标准时间)
这个写法是正确的不知道为什么在我自己的W10_64位系统中不起作用,在w7_64位中正常,
可能是系统版本导致的,我的系统版本是
‘版本Windows 10 专业版  版本号 22H2,操作系统内部版本19045.3570   不行
’版本Windows 10 专业版  版本号 1909,操作系统内部版本18363.592   不行
‘版本Windows 10 专业版  版本号 1709,操作系统内部版本16299.   可以
'版本Windows 7 旗航舰  版本号 6.1,操作系统内部版本7601.   可以
*/

//用到的内核函数,该函数使用前需要声明  上面已经声明
//PCHAR PsGetProcessImageFileName(PEPROCESS Process);

typedef NTSTATUS(*_NtOpenProcess)
(
	PHANDLE ProcessHandle,
	ACCESS_MASK DesiredAccess,
	POBJECT_ATTRIBUTES ObjectAttributes,
	PCLIENT_ID ClientId);
_NtOpenProcess oldNtOpenProcess = NULL;

PVOID S_OpenProcess;

//要HOOK的函数原型声明,win x64系统的API函数调用约定为__fastcall
typedef NTSTATUS(__fastcall* pMyOpenProcess)(OUT PHANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN PCLIENT_ID ClientId OPTIONAL);
typedef NTSTATUS(__fastcall* pMyReadVirtualMemory)(IN HANDLE ProcessHandle, IN PVOID BaseAddress, OUT PVOID Buffer, IN ULONG BufferLength, OUT PULONG ReturnLength OPTIONAL);


NTSTATUS MyNtOpenProcess(
	PHANDLE ProcessHandle,
	ACCESS_MASK DesiredAccess,
	POBJECT_ATTRIBUTES ObjectAttributes,
	PCLIENT_ID ClientId)
{
	DbgPrint("yjx:HOOK_NtOpenProcess 
");
	// 在这里添加你的Hook逻辑
	//HOOK了NtOpenProcess函数,CE不能打开进程,OD,XDBG64找不到服加的程序
	//想HOOK其他函数就要改一下要HOOK的函数名,加上hook操作,改变要HOOK的程序名称。
	PEPROCESS process = 0;
	if (STATUS_SUCCESS == PsLookupProcessByProcessId(ClientId->UniqueProcess, &process))
	{
		if (strcmp(PsGetProcessImageFileName(process), "NMQD.exe") == 0)
		{
			KdPrint(("要保护进程:%s", PsGetProcessImageFileName(process)));
			return STATUS_PNP_INVALID_ID;
		}
	}
	return oldNtOpenProcess(ProcessHandle, DesiredAccess, ObjectAttributes, ClientId);
}

LONG g_oldfunoffset_OpenProcess = 0;
LONG g_funcIndex_OpenProcess = -1;
BOOL g_isHook_OpenProcess = FALSE;
VOID InitHook_NtOpenProcess()//HOOK函数
{
	//在X64DBG空白处中输入
	//000000007759252E | 48:B8 9064BD7E03F8FFFF | mov rax, FFFFF8037EBD6490 |
	//0000000077592538 | FFE0					| jmp rax |
	// 操作:选择两段代码-二进制-编辑-复制数据-C样式字节(十六进制)-复制  就得到下面的代码
	/*
	{
		0x48, 0xB8, 0x90, 0x64, 0xBD, 0x7E, 0x03, 0xF8, 0xFF, 0xFF, 0xFF, 0xE0
	};
	*/
	//DbgBreakPoint();
	char ShellCode[] = { 0x48, 0xB8, 0x90, 0x64, 0xBD, 0x7E, 0x03, 0xF8, 0xFF, 0xFF, 0xFF, 0xE0 };
	ULONG64 MyNtOpenProcessAddr = (ULONG64)MyNtOpenProcess;
	RtlCopyMemory(&ShellCode[2], &MyNtOpenProcessAddr, 8);
	PVOID BugCheckExAddr = (PVOID)KeBugCheckEx;
	KIRQL irql = WPOFF();
	RtlCopyMemory(BugCheckExAddr, ShellCode, sizeof(ShellCode));

	PCHAR SystemCall64 = (PUCHAR)__readmsr(0xC0000082);
	UCHAR s1, s2, s3;
	PKE_SERVICED_ESCRIPTOR_TABLE ServiceDescriptorTable = NULL;
	for (int i = 0; i < 500; ++i)
	{
		s1 = SystemCall64[i];
		s2 = SystemCall64[i + 1];
		s3 = SystemCall64[i + 2];
		if (s1 == 0x4C && s2 == 0x8D && s3 == 0x15) //4c 8d 15 是W10_64位特征码    4c8d15
		{
			LONG offset = *(PLONG)(SystemCall64 + i + 3);
			ServiceDescriptorTable = SystemCall64 + i + 7 + offset;
			break;
		}
	}
	if (!ServiceDescriptorTable)
	{
		DbgPrint("yjx:函数走到这里为失败1");
		return;
	}
	

	PCHAR funAddr = NULL;
	for (int i = 0; i < ServiceDescriptorTable->funNumber; ++i)
	{
		LONG funoffset = ServiceDescriptorTable->tableBase[i];
		funAddr = (PCHAR)ServiceDescriptorTable->tableBase + (funoffset >> 4);
		if ((ULONG64)funAddr == (ULONG64)NtOpenProcess)
		{
			g_oldfunoffset_OpenProcess = funoffset;
			g_funcIndex_OpenProcess = i;
			oldNtOpenProcess = funAddr;
			LONG MyFuncOffset = (PCHAR)BugCheckExAddr - (PCHAR)ServiceDescriptorTable->tableBase;
			ServiceDescriptorTable->tableBase[i] = MyFuncOffset << 4;
			g_isHook_OpenProcess = TRUE;
			break;
		}
		//DbgPrint("yjx:函数地址:%p,编号:%d 
", funAddr, i);
		//遍历
	}
	DbgPrint("yjx:函数走到这里为成功2");
	WPON(irql);
}

VOID UnInitHook_NtOpenProcess()//恢复HOOK的函数
{
	//DbgBreakPoint();
	if (g_funcIndex_OpenProcess != -1 && g_isHook_OpenProcess)
	{
		PCHAR SystemCall64 = (PUCHAR)__readmsr(0xC0000082);
		UCHAR s1, s2, s3;
		PKE_SERVICED_ESCRIPTOR_TABLE ServiceDescriptorTable = NULL;
		for (int i = 0; i < 500; ++i)
		{
			s1 = SystemCall64[i];
			s2 = SystemCall64[i + 1];
			s3 = SystemCall64[i + 2];
			if (s1 == 0x4C && s2 == 0x8D && s3 == 0x15) //4c 8d 15 是W10_64位特征码    4c8d15
			{
				LONG offset = *(PLONG)(SystemCall64 + i + 3);
				ServiceDescriptorTable = SystemCall64 + i + 7 + offset;
				break;
			}
		}
		if (!ServiceDescriptorTable)
		{
			DbgPrint("yjx:函数走到这里失败1");
			return;
		}
		KIRQL irql = WPOFF();
		ServiceDescriptorTable->tableBase[g_funcIndex_OpenProcess] = g_oldfunoffset_OpenProcess;
		WPON(irql);
		g_isHook_OpenProcess = FALSE;
		g_funcIndex_OpenProcess = -1;
	}
	return;
}

二、入口函数调用

NTSTATUS DriverEntry(PDRIVER_OBJECT pDvier, PUNICODE_STRING strPath)
{
	NTSTATUS status;
	pDvier->DriverUnload = DriverUnload1;
	DbgPrint("yjx:驱动加载
");
	//DbgBreakPoint();
	//HOOK函数  注意两个HOOK不能同时开启,代码没进行优化,优化后才能进行多个一起HOOK
	//InitHook_NtClose();
	InitHook_NtOpenProcess();
	return STATUS_SUCCESS;

}

2.卸载函数调用

NTSTATUS DriverUnload1(PDRIVER_OBJECT pDvier)
{
	//UnInitHook_NtClose();//恢复HOOK的函数  注意两个HOOK不能同时开启,代码没进行优化,优化后才能进行多个一起HOOK
	UnInitHook_NtOpenProcess();//恢复HOOK的函数
	DbgPrint("yjx:驱动卸载
");
	return STATUS_SUCCESS;
}

HOOK结果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述