其他
内核层的三种Hook技术的使用
本文为看雪论坛优秀文章
看雪论坛作者ID:1900
1
前言
2
实现原理
HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, dwPid);
#define PROCESS_TERMINATE (0x0001)
NTSTATUS
ZwOpenProcess(
__out PHANDLE ProcessHandle,
__in ACCESS_MASK DesiredAccess,
__in POBJECT_ATTRIBUTES ObjectAttributes,
__in_opt PCLIENT_ID ClientId
);
typedef struct _CLIENT_ID {
HANDLE UniqueProcess;
HANDLE UniqueThread;
} CLIENT_ID;
typedef CLIENT_ID *PCLIENT_ID;
3
代码框架
安装和卸载驱动 根据要保护的进程名获取进程PID,以传给内核层供内核层使用 根据用户输入选择安装或者卸载HOOK,向内核层发送相应的IoControlCode并把返回结果告诉用户
#include <cstdio>
#include <Windows.h>
#include <TlHelp32.h>
#define IOCTRL_BASE 0x800
#define MYIOCTRL_CODE(i) CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTRL_BASE + i, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define CTL_HOOK MYIOCTRL_CODE(0)
#define CTL_UNHOOK MYIOCTRL_CODE(1)
#define LINK_NAME "\\\\.\\HookDeviceLink" //符号名
#define DRIVER_NAME "HookDriver" //驱动名称
#define OUT_BUFFER_LENGTH 1 //输出缓冲区的长度
#define INPUT_BUFFER_LENGTH 4 //输入缓冲区的长度
#define PROTECTED_NAME "demo.exe" //要保护的进程名
BOOL InstallService(); //安装驱动服务
BOOL UnInstallService(); //卸载驱动
DWORD GetPid(); //获得要保护的进程PID
int main()
{
DWORD dwAns; //用来输入控制程序执行
HANDLE hDevice = NULL;
BOOLEAN bRes = FALSE; //输出缓冲区,用来判断是否Hook成功
DWORD dwRetLength = 0; //接受缓冲区长度
if (InstallService())
{
// 获取设备句柄
hDevice = CreateFile(LINK_NAME, GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (hDevice == INVALID_HANDLE_VALUE)
{
printf("CreateFile Error %d.\n", GetLastError());
goto exit;
}
while (TRUE)
{
dwAns = 0;
bRes = TRUE;
printf("选择操作,(输入1 2 3):\n");
printf("1是开启HOOK,2是关闭HOOK,3是退出程序\n");
scanf("%d", &dwAns);
if (dwAns == 3) break;
else if (dwAns == 1)
{
DWORD dwPid = GetPid();
if (dwPid == 0)
{
printf("没有找到进程\n");
continue;
}
//开启HOOK
if (!DeviceIoControl(hDevice, CTL_HOOK, &dwPid, INPUT_BUFFER_LENGTH,
&bRes, OUT_BUFFER_LENGTH, &dwRetLength, NULL))
{
printf("DeviceIoControl CTL_HOOK Error\n");
break;
}
if (bRes) printf("Hook 成功\n");
else printf("Hook 失败\n");
}
else if (dwAns == 2)
{
//关闭HOOK
if (!DeviceIoControl(hDevice, CTL_UNHOOK, NULL, 0,
&bRes, OUT_BUFFER_LENGTH, &dwRetLength, NULL))
{
printf("DeviceIoControl CTL_UNHOOK Error\n");
break;
}
if (bRes) printf("UnHook 成功\n");
else printf("UnHook 失败\n");
}
}
exit:
if (hDevice) CloseHandle(hDevice);
if (!UnInstallService())
{
printf("卸载驱动失败\n");
}
}
else
{
printf("驱动加载失败\n");
}
system("pause");
return 0;
}
BOOL UnInstallService()
{
BOOL bRet = TRUE;
SC_HANDLE hService = NULL, hSCMHandle = NULL;
SERVICE_STATUS ServiceStatus = { 0 };
hSCMHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); //建立服务控制管理器连接
if (hSCMHandle == NULL)
{
printf("OpenSCManager error %d\n", GetLastError());
bRet = FALSE;
goto exit;
}
hService = OpenService(hSCMHandle, DRIVER_NAME, SERVICE_ALL_ACCESS);
if (hService == NULL)
{
printf("CreateService error %d\n", GetLastError());
bRet = FALSE;
goto exit;
}
if (!ControlService(hService, SERVICE_CONTROL_STOP, &ServiceStatus)) //停止驱动服务
{
printf("ControlService error %d\n", GetLastError());
bRet = FALSE;
goto exit;
}
if (!DeleteService(hService)) //删除驱动
{
printf("DeleteService error %d\n", GetLastError());
bRet = FALSE;
goto exit;
}
printf("驱动卸载成功\n");
exit:
if (hSCMHandle) CloseServiceHandle(hSCMHandle);
if (hService) CloseServiceHandle(hService);
return bRet;
}
BOOL InstallService()
{
SC_HANDLE hSCMHandle = NULL, hService = NULL;
BOOL bRet = TRUE;
CHAR szDriverPath[MAX_PATH] = { 0 };
hSCMHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); //建立服务控制管理器连接
if (hSCMHandle == NULL)
{
printf("OpenSCManager error %d\n", GetLastError());
bRet = FALSE;
goto exit;
}
//获取当前程序运行目录
GetCurrentDirectory(MAX_PATH, szDriverPath);
strcat(szDriverPath, "\\");
strcat(szDriverPath, DRIVER_NAME);
strcat(szDriverPath, ".sys");
//创建一个服务对象
hService = CreateService(hSCMHandle,
DRIVER_NAME, //驱动名称
DRIVER_NAME, //显示的名称
SERVICE_ALL_ACCESS,
SERVICE_KERNEL_DRIVER, //指定内核驱动程序
SERVICE_DEMAND_START, //需要时候开启
SERVICE_ERROR_NORMAL,
szDriverPath, //驱动的路径
NULL, NULL, NULL, NULL, NULL);
if (hService == NULL)
{
printf("CreateService error %d\n", GetLastError());
bRet = FALSE;
goto exit;
}
if (!StartService(hService, 0, NULL)) //启动服务
{
printf("StartService error %d\n", GetLastError());
bRet = FALSE;
goto exit;
}
printf("驱动安装成功\n");
exit:
if (hSCMHandle) CloseServiceHandle(hSCMHandle);
if (hService) CloseServiceHandle(hService);
return bRet;
}
DWORD GetPid()
{
DWORD dwPid = 0;
PROCESSENTRY32 pe32 = { 0 };
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
BOOL bRet = FALSE;
if (hSnap == INVALID_HANDLE_VALUE)
{
printf("CreateToolhelp32Snapshot process %d\n", GetLastError());
return 0;
}
pe32.dwSize = sizeof(pe32);
bRet = Process32First(hSnap, &pe32);
while (bRet)
{
if (lstrcmp(pe32.szExeFile, PROTECTED_NAME) == 0)
{
dwPid = pe32.th32ProcessID;
break;
}
bRet = Process32Next(hSnap, &pe32);
}
CloseHandle(hSnap);
return dwPid;
}
#include <ntifs.h>
#define IOCTRL_BASE 0x800
#define MYIOCTRL_CODE(i) CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTRL_BASE + i, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define CTL_HOOK MYIOCTRL_CODE(0)
#define CTL_UNHOOK MYIOCTRL_CODE(1)
#define DEVICE_NAME L"\\Device\\HookDevice"
#define SYMBOL_LINK_XP L"\\DosDevices\\HookDeviceLink"
#define SYMBOL_LINK_WIN7 L"\\DosDevices\\Global\\HookDeviceLink"
// 进程访问权限,允许关闭进程
#define PROCESS_TERMINATE (0x0001)
VOID DriverUnload(IN PDRIVER_OBJECT driverObject);
NTSTATUS DispatchCommon(PDEVICE_OBJECT pObj, PIRP pIrp);
NTSTATUS DispatchIoctrl(PDEVICE_OBJECT pObj, PIRP pIrp);
BOOLEAN Hook();
BOOLEAN UnHook();
ULONG g_uPID = 0; //要保护的进程的PID
ULONG g_uOrgFuncAddr = 0; //保存原函数地址
NTSTATUS DriverEntry(IN PDRIVER_OBJECT driverObject, IN PUNICODE_STRING registryPath)
{
NTSTATUS status = STATUS_SUCCESS;
UNICODE_STRING uDeviceName, uSymbolLinkName;
ULONG i = 0;
PDEVICE_OBJECT pDeviceOjb = NULL;
//创建设备
RtlInitUnicodeString(&uDeviceName, DEVICE_NAME);
status = IoCreateDevice(driverObject, NULL, &uDeviceName, FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN, FALSE, &pDeviceOjb);
if (!NT_SUCCESS(status))
{
DbgPrint("IoCreateDevice %X\r\n", status);
goto exit;
}
//设置数据交互方式
pDeviceOjb->Flags |= DO_BUFFERED_IO;
//创建符号链接
if (IoIsWdmVersionAvailable(1, 0x10)) //根据操作系统版本来初始化符号名
{
RtlInitUnicodeString(&uSymbolLinkName, SYMBOL_LINK_WIN7);
}
else
{
RtlInitUnicodeString(&uSymbolLinkName, SYMBOL_LINK_XP);
}
status = IoCreateSymbolicLink(&uSymbolLinkName, &uDeviceName);
if (!NT_SUCCESS(status))
{
DbgPrint("IoCreateSymbolicLink %X\r\n", status);
goto exit;
}
for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
{
driverObject->MajorFunction[i] = DispatchCommon;
}
driverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctrl;
DbgPrint("驱动成功加载\r\n");
exit:
driverObject->DriverUnload = DriverUnload;
return STATUS_SUCCESS;
}
NTSTATUS DispatchIoctrl(PDEVICE_OBJECT pObj, PIRP pIrp)
{
BOOLEAN bRes = FALSE;
NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
PIO_STACK_LOCATION pIrpStack;
ULONG uIoControlCode = 0, uInformation = 0;
PVOID pIoBuffer = NULL;
//获取设备栈
pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
//获取控制码
uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
//获取输入输出缓冲区
pIoBuffer = pIrp->AssociatedIrp.SystemBuffer;
switch(uIoControlCode)
{
case CTL_HOOK:
{
memcpy(&g_uPID, pIoBuffer, sizeof(g_uPID)); //保存用户层传入的进程PID
bRes = Hook();
memcpy(pIoBuffer, &bRes, sizeof(bRes));
uInformation = sizeof(bRes);
if (bRes)
{
DbgPrint("Hook 成功\r\n");
DbgPrint("要保护的进程PID是:%d\r\n", g_uPID);
status = STATUS_SUCCESS;
}
break;
}
case CTL_UNHOOK:
{
bRes = UnHook();
g_uPID = 0;
memcpy(pIoBuffer, &bRes, sizeof(bRes));
uInformation = sizeof(bRes);
status = STATUS_SUCCESS;
if (bRes) DbgPrint("UnHook 成功\r\n");
break;
}
default:
{
uInformation = 0;
DbgPrint("Unknown IoControlCode\r\n");
status = STATUS_SUCCESS;
break;
}
}
pIrp->IoStatus.Status = status;
pIrp->IoStatus.Information = uInformation;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
BOOLEAN Hook()
{
BOOLEAN bRes = TRUE;
return bRes;
}
BOOLEAN UnHook()
{
BOOLEAN bRes = TRUE;
return bRes;
}
NTSTATUS DispatchCommon(PDEVICE_OBJECT pObj, PIRP pIrp)
{
pIrp->IoStatus.Status = STATUS_SUCCESS;
pIrp->IoStatus.Information = 0;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
VOID DriverUnload(IN PDRIVER_OBJECT driverObject)
{
UNICODE_STRING uSymbolLinkName;
if (driverObject->DeviceObject)
{
IoDeleteDevice(driverObject->DeviceObject);
if (IoIsWdmVersionAvailable(1, 0x10))
{
RtlInitUnicodeString(&uSymbolLinkName, SYMBOL_LINK_WIN7);
}
else
{
RtlInitUnicodeString(&uSymbolLinkName, SYMBOL_LINK_XP);
}
IoDeleteSymbolicLink(&uSymbolLinkName);
}
DbgPrint("驱动卸载完成\r\n");
}
4
InlineHook
VOID NtMyOpenProcess(PHANDLE ProcessHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
PCLIENT_ID ClientId); //Hook以后要执行的函数
PVOID g_pNtOpenProcessMap_5 = NULL; //NtOpenProcess函数地址-5的地址映射得指针
PMDL g_pMDL = NULL; //内存描述符指针
UCHAR g_szOrgBytes[7]; //存储HOOK之前函数中的七个字节
BOOLEAN Hook()
{
BOOLEAN bRes = TRUE;
UCHAR szShellCode[7] = { 0xE9, 0x0, 0x0, 0x0, 0x0, 0xEB, 0xF9 }; //构造热补丁
PVOID pNtOpenProcessAddr_5 = NULL; //NtOpenProcess-5的地址
UNICODE_STRING uStrFuncName = RTL_CONSTANT_STRING(L"NtOpenProcess");
ULONG i = 0;
pNtOpenProcessAddr_5 = (PVOID)((UINT32)MmGetSystemRoutineAddress(&uStrFuncName) - 5); //获得NtOpenProcess的函数地址-5的数
g_uOrgFuncAddr = (PVOID)((UINT32)pNtOpenProcessAddr_5 + 7); //取得要执行得原函数得代码地址
//创建MDL,并为内存属性添加可写属性
g_pMDL = MmCreateMdl(NULL, pNtOpenProcessAddr_5, sizeof(szShellCode));
if (g_pMDL == NULL)
{
bRes = FALSE;
goto exit;
}
MmBuildMdlForNonPagedPool(g_pMDL); //建立内存页的MDL描述
g_pMDL->MdlFlags |= MDL_MAPPED_TO_SYSTEM_VA; //改变MDL的标记为可写
g_pNtOpenProcessMap_5 = MmMapLockedPages(g_pMDL, KernelMode); //映射MDL空间
*(PUINT32)(szShellCode + 1) = (UINT32)NtMyOpenProcess - ((UINT32)pNtOpenProcessAddr_5 + 5); //填充szShellCode使其跳转到目标地址
__asm cli;
for (i = 0; i < 7; i++)
{
g_szOrgBytes[i] = *((PUCHAR)g_pNtOpenProcessMap_5 + i); //将原来的字节保存起来
*((PUCHAR)g_pNtOpenProcessMap_5 + i) = szShellCode[i]; //将ShellCode写入到地址中
}
__asm sti;
exit:
return bRes;
}
BOOLEAN UnHook()
{
BOOLEAN bRes = TRUE;
ULONG i = 0;
if (g_pNtOpenProcessMap_5)
{
__asm cli;
for (i = 0; i < 7; i++)
{
*((PUCHAR)g_pNtOpenProcessMap_5 + i) = g_szOrgBytes[i]; //恢复原来的字节
g_szOrgBytes[i] = 0;
}
__asm sti;
}
//释放MDL,将函数的内存空间改为初始状态
if (g_pMDL)
{
MmUnmapLockedPages(g_pNtOpenProcessMap_5, g_pMDL);
IoFreeMdl(g_pMDL);
g_pMDL = NULL;
}
return bRes;
}
VOID __declspec(naked) NtMyOpenProcess(PHANDLE ProcessHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
PCLIENT_ID ClientId)
{
__asm
{
push ebp
mov ebp, esp //把ebp挪上来,为了后面方便使用参数
pushfd //保存寄存器环境
pushad
}
if (ClientId)
{
if ((UINT32)ClientId->UniqueProcess == g_uPID) //操作得是否是要保护得进程
{
if (DesiredAccess & PROCESS_TERMINATE) //是否是要关闭进程 如果是删掉它
{
DesiredAccess &= ~PROCESS_TERMINATE;
}
}
}
__asm
{
popad //恢复寄存器环境
popfd
mov esp, ebp
pop ebp
jmp g_uOrgFuncAddr
}
}
5
SysenterHook
.text:77F05D88 ; NTSTATUS __stdcall ZwOpenProcess(PHANDLE ProcessHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PCLIENT_ID ClientId)
.text:77F05D88 public ZwOpenProcess
.text:77F05D88 ZwOpenProcess proc near ; CODE XREF: RtlQueryProcessDebugInformation+8F↑p
.text:77F05D88 ; sub_77EDD774+64C3A↓p ...
.text:77F05D88
.text:77F05D88 ProcessHandle = dword ptr 4
.text:77F05D88 DesiredAccess = dword ptr 8
.text:77F05D88 ObjectAttributes= dword ptr 0Ch
.text:77F05D88 ClientId = dword ptr 10h
.text:77F05D88
.text:77F05D88 mov eax, 0BEh ; NtOpenProcess
.text:77F05D8D mov edx, 7FFE0300h
.text:77F05D92 call dword ptr [edx]
.text:77F05D94 retn 10h
.text:77F05D94 ZwOpenProcess endp
BOOL CanSysenter()
{
BOOL bRet = FALSE;
__asm
{
mov eax, 1
cpuid
and edx, 0x0800 //与第11位为1的二进制进行与
mov bRet, edx
}
return bRet;
}
.text:77F070B0 public KiFastSystemCall
.text:77F070B0 KiFastSystemCall proc near ; DATA XREF: .text:off_77EF61B8↑o
.text:77F070B0 mov edx, esp
.text:77F070B2 sysenter
.text:77F070B2 KiFastSystemCall endp
随后函数会调用sysenter指令,此时这个指令就会从特殊模块寄存器(MSRs)寄存器中取出在内核中要运行的代码地址以及要设置的代码段等信息取出,并将它们赋给相应的寄存器。MSRs中包含的不同功能的寄存器有上百种,但是与sysenter配合的MSRs一共有下表的三个:
名称 | 偏移 | 功能 |
SYSENTER_CS_MSR | 0x174 | 指定切换到内核层的CS |
SYSENTER_ESP_MSR | 0x175 | 指定切换到内核层的ESP |
SYSENTER_EIP_MSR | 0x176 | 指定切换到内核层的EIP |
VOID MyKiFastCallEntry(); //Hook以后要执行的函数
ULONG g_uSSDT_Index = 0; //保存调用的SSDT函数的下标
PACCESS_MASK g_pAccessMask = 0; //保存调用ZwOpenProcess时候传入的访问权限
PCLIENT_ID g_ClientId = 0; //保存调用ZwOpenProcess时候传入的
//edx保存的参数和返回地址的栈地址,但是注意这时候有两个返回地址,详细如上图所示
__declspec(naked) VOID MyKiFastCallEntry()
{
__asm
{
mov g_uSSDT_Index, eax; //获取调用号
push EDX
add DWORD PTR [ESP], 0x0C
pop g_pAccessMask //取得保存AccessMask的栈地址
push DWORD PTR [EDX + 0x14]
pop g_ClientId; //取出参数ClientId
}
__asm
{
pushfd //保存寄存器环境
pushad
}
if (g_uSSDT_Index == 0xBE) //根据调用号判断调用的是否是ZwOpenProcess
{
if (g_ClientId)
{
if ((ULONG)g_ClientId->UniqueProcess == g_uPID ) //是否是要保护的进程
{
if (*g_pAccessMask & PROCESS_TERMINATE)
{
*g_pAccessMask = (*g_pAccessMask) & (~PROCESS_TERMINATE); //具有关闭进程的权限,删除它
}
}
}
}
__asm
{
popad //恢复寄存器环境
popfd
jmp g_uOrgFuncAddr //跳回原来的代码执行
}
}
BOOLEAN Hook()
{
BOOLEAN bRes = TRUE;
__asm
{
cli
mov ecx, 0x176 //指向SYSENTER_EIP_MSR
rdmsr
mov g_uOrgFuncAddr, eax //将原来要执行得代码地址保存起来
mov eax, MyKiFastCallEntry //Hook为要新执行的代码
wrmsr
sti
}
return bRes;
}
BOOLEAN UnHook()
{
BOOLEAN bRes = TRUE;
__asm
{
cli
mov ecx, 0x176 //指向SYSENTER_EIP_MSR
xor edx, edx
mov eax, g_uOrgFuncAddr //将原来执行的代码的地址恢复回去
wrmsr
sti
}
return bRes;
}
6
SSDT Hook
typedef struct _KSERVICE_TABLE_DESCRIPTOR
{
KSYSTEM_SERVICE_TABLE ntoskrnl;
KSYSTEM_SERVICE_TABLE win32k;
KSYSTEM_SERVICE_TABLE NotUsed1; //未使用
KSYSTEM_SERVICE_TABLE NotUsed2;
} KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR;
typedef struct _KSYSTEM_SERVICE_TABLE
{
PULONG pServiceTableBase; //保存函数地址的表
ULONG pServiceCounterTable; //通常为0
ULONG uNumberFunc; //保存函数个数
PUCHAR pParamTableBase; //保存了参数个数的表,以字节为单位(除4得到参数个数)
} KSYSTEM_SERVICE_TABLE, *PKSYSTEM_SERVICE_TABLE;
#pragma pack(1)
// 系统服务表
typedef struct _KSYSTEM_SERVICE_TABLE
{
PULONG pServiceTableBase; //保存函数地址的表
ULONG pServiceCounterTable; //通常为0
ULONG uNumberFunc; //保存函数个数
PUCHAR pParamTableBase; //保存了参数个数的表,以字节为单位(除4得到参数个数)
} KSYSTEM_SERVICE_TABLE, *PKSYSTEM_SERVICE_TABLE;
typedef struct _KSERVICE_TABLE_DESCRIPTOR
{
KSYSTEM_SERVICE_TABLE ntoskrnl;
KSYSTEM_SERVICE_TABLE win32k;
KSYSTEM_SERVICE_TABLE unUsedTable1; //系统未使用
KSYSTEM_SERVICE_TABLE unUsedTable2; //系统未使用
} KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR;
#pragma pack()
VOID OpenPageProtect(); //开起页保护
VOID ClosePageProtect(); //关闭页保护
typedef NTSTATUS (*pFnOpenProcess)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PCLIENT_ID);
NTSTATUS MyZwOpenProcess(PHANDLE ProcessHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
PCLIENT_ID ClientId); //HOOK以后要执行的函数
extern PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable; //获取导出的地址
BOOLEAN Hook()
{
BOOLEAN bRes = TRUE;
ClosePageProtect(); //关闭页保护
g_uOrgFuncAddr = KeServiceDescriptorTable->ntoskrnl.pServiceTableBase[0xBE]; //原函数进行备份
KeServiceDescriptorTable->ntoskrnl.pServiceTableBase[0xBE] = (ULONG)MyZwOpenProcess; //修改为要执行的函数地址
OpenPageProtect(); //开启页保护
return bRes;
}
BOOLEAN UnHook()
{
BOOLEAN bRes = TRUE;
ClosePageProtect(); //关闭页保护
KeServiceDescriptorTable->ntoskrnl.pServiceTableBase[0xBE] = g_uOrgFuncAddr; //还原成原来的函数
OpenPageProtect(); //开启页保护
return bRes;
}
NTSTATUS MyZwOpenProcess(PHANDLE ProcessHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PCLIENT_ID ClientId)
{
if ((ULONG)ClientId->UniqueProcess == g_uPID) //是否是要保护的进程
{
if (DesiredAccess & PROCESS_TERMINATE) //是否具有关闭进程的权限
{
DesiredAccess &= ~PROCESS_TERMINATE;
}
}
return ((pFnOpenProcess)g_uOrgFuncAddr)(ProcessHandle, DesiredAccess, ObjectAttributes, ClientId); //调用原函数
}
// 关闭页保护
VOID ClosePageProtect()
{
__asm
{
cli
mov eax, cr0 //将cr0中的数值赋给eax
and eax, ~0x10000 // 将第16位,也就是WP位置0
mov cr0, eax
}
}
// 开起页保护
VOID OpenPageProtect()
{
__asm
{
mov eax, cr0 // 将cr0中的数值赋给eax
or eax, 0x10000 // WP位置1
mov cr0, eax
sti
}
}
7
实验结果
看雪ID:1900
https://bbs.pediy.com/user-home-835440.htm
# 往期推荐
2.通过CmRegisterCallback学习注册表监控与反注册表监控
3.BCTF2018-houseofatum-Writeup题解
球分享
球点赞
球在看
点击“阅读原文”,了解更多!