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结果