分别从静态,动态两种方法来hook
静态是直接根据openProcess的调用号0xbe
动态是防止地址发生改变或者其他,来动态函数索引进而HOOK的
#include<ntifs.h>
#include<ntimage.h> //提供 PE结构
PULONG g_PageMapMemory = NULL;
typedef struct _SSDTItem {
PULONG FunAddressTable;
ULONG Pknum;
ULONG uIndexCount;
PCHAR pcParam;
}SSDTItem,*PSSDTItem;
//代表两张表的
typedef struct _RKSSDT {
SSDTItem KernelItem;
SSDTItem GuiItem;
}RLSSDT,*PRSSDT;
//x86情况下,是根据名字来找到这张表的
EXTERN_C PRSSDT KeServiceDescriptorTable;
typedef NTSTATUS (NTAPI *rkOpenProcess)(//hook用来替换原来的函数,hook之后要还原,所以要保存一下类型
PHANDLE ProcessHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
PCLIENT_ID ClientId
);
rkOpenProcess NtOpenProcessOldFunAddr = NULL;
NTSTATUS NtOpenProcess(
PHANDLE ProcessHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
PCLIENT_ID ClientId
) {
DbgPrint("你已被hook\n");
return NtOpenProcessOldFunAddr(ProcessHandle, DesiredAccess, ObjectAttributes, ClientId);
}
//ntdll pe ssdt index
ULONG GetSSDTIndex(UNICODE_STRING usDllFileName,PCHAR pcFunctionName) {
NTSTATUS ntStatus = STATUS_SUCCESS;
HANDLE hFile = NULL;
HANDLE hSection = NULL;//解析PE
OBJECT_ATTRIBUTES objectAttr = { 0 };
IO_STATUS_BLOCK ioStatus = { 0 };
PVOID pBaseAddress = NULL;
SIZE_T viewSize = 0;
ULONG ulFunctionIndex = 0;
//初始化对象
InitializeObjectAttributes(&objectAttr, &usDllFileName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
//打开对象
ntStatus = ZwOpenFile(&hFile, GENERIC_READ, &objectAttr, &ioStatus, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT);
if (!NT_SUCCESS(ntStatus))
{
DbgPrint("ZwOpenFile error\n");
return 0;
}
ntStatus = ZwCreateSection(&hSection, SECTION_MAP_READ | SECTION_MAP_WRITE, NULL, 0, PAGE_READWRITE, 0x1000000, hFile);
if (!NT_SUCCESS(ntStatus))
{
DbgPrint("ZwCreateSection error\n");
return 0;
}
//例程将部分视图映射到主题进程的虚拟地址空间。
ntStatus = ZwMapViewOfSection(hSection, NtCurrentProcess(), pBaseAddress, 0, 1024, 0, &viewSize, ViewShare, MEM_TOP_DOWN, PAGE_READWRITE);
if (!NT_SUCCESS(ntStatus))
{
DbgPrint("ZwMapViewOfSection error\n");
return 0;
}
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pBaseAddress;
PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PUCHAR)pDosHeader + pDosHeader->e_lfanew);
PIMAGE_EXPORT_DIRECTORY pExportTable = (PIMAGE_EXPORT_DIRECTORY)((PUCHAR)pDosHeader + pNtHeader->OptionalHeader.DataDirectory[0].VirtualAddress);
ULONG ulNameberForNames = pExportTable->NumberOfNames;
PULONG lpNameAddressArray = (PULONG)((PUCHAR)pDosHeader + pExportTable->AddressOfNames);
PCHAR lpFunName = NULL;
for (size_t i = 0; i < ulNameberForNames; i++)
{
lpFunName = (PCHAR)((PUCHAR)pDosHeader + lpNameAddressArray[i]);
if (_strnicmp(pcFunctionName, lpFunName, strlen(pcFunctionName)) == 0) {
USHORT uHint =*(USHORT *)(pDosHeader + pExportTable->AddressOfNameOrdinals + 2 * i);
ULONG ulFUNAddr = *(ULONG*)((PUCHAR)pDosHeader + pExportTable->AddressOfFunctions + 4*i);
PVOID lpFuncAddr = (PVOID)((PUCHAR)pDosHeader + ulFUNAddr);
ulFunctionIndex = *(ULONG*)((PUCHAR)lpFuncAddr + 1);
break;
}
}
ZwClose(hSection);
ZwClose(hFile);
return ulFunctionIndex;
}
NTSTATUS SetHook(ULONG ulFuncAddr, PCHAR pcFunctionName) {
LONG ulFunctionIndex = 0;
NTSTATUS status = STATUS_SUCCESS;
UNICODE_STRING usDllFileName;
RtlInitUnicodeString(&usDllFileName, L"\\??\\C:\\Windows\\System32\\ntdll.dll");
ulFunctionIndex = GetSSDTIndex(usDllFileName, pcFunctionName);
if (ulFunctionIndex == 0) {
DbgPrint("GetSSDTIndex error!\n");
return status;
}
DbgPrint("ulFunctionIndex is 0x%x\n", ulFunctionIndex);
PHYSICAL_ADDRESS phyAddress = MmGetPhysicalAddress(KeServiceDescriptorTable->KernelItem.FunAddressTable);//获取物理地址
g_PageMapMemory = MmMapIoSpace(phyAddress, PAGE_SIZE, MmCached); //映射
NtOpenProcessOldFunAddr = g_PageMapMemory[ulFunctionIndex];
g_PageMapMemory[ulFunctionIndex] = NtOpenProcess;
return status;
}
VOID DriverUnload(PDRIVER_OBJECT pDriverObject) {
//关闭映射
//g_PageMapMemory[0xbe] = NtOpenProcessOldFunAddr;//还原回去
SetHook(NtOpenProcessOldFunAddr, "NtOpenProcess");//动态还原回去
MmUnmapIoSpace(g_PageMapMemory, PAGE_SIZE);//解除hook
DbgPrint("卸载成功!\n");
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegPath) {
pDriverObject->DriverUnload = DriverUnload;
//hook 调用号是0xbe
//修改CR0寄存器
//MDR
//内存映射
//获取物理地址
//静态根据索引hook
//PHYSICAL_ADDRESS phyAddress= MmGetPhysicalAddress(KeServiceDescriptorTable->KernelItem.FunAddressTable);
//映射
// g_PageMapMemory = MmMapIoSpace(phyAddress, PAGE_SIZE, MmCached);
//现在g_PageMapMemory和KeServiceDescriptorTable->KernelItem.FunAddressTable等值了
// NtOpenProcessOldFunAddr = g_PageMapMemory[0xbe];
// g_PageMapMemory[0xbe] = NtOpenProcess;
//最后结束时候要结束映射,在驱动卸载函数里
//动态获取索引号
SetHook((ULONG)NtOpenProcess,"NtOpenProcess");
DbgPrint("加载成功!\n");
return STATUS_SUCCESS;
}
结果