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


