动态获取主要操作就是把ntdll.dll加载到驱动中,去函数地址读取汇编中的索引号

代码:
#include<ntifs.h>
#include<ntimage.h>
PULONG g_PageMapMenmory = NULL;
typedef struct _SSDTService
{
PULONG ServiceTableBase; // SSDT基址
PVOID ServiceCounterTableBase;// SSDT中服务被调用次数计数器,一般由sysenter 更新
ULONG NumberOfService; // 索引总数
PVOID ParamTableBase; // 系统服务参数表基址-系统服务参数表SSPT
}SYSTEM_SERVICE_TABLE, * PSYSTEM_SERVICE_TABLE;
typedef struct _SSDTable
{
SYSTEM_SERVICE_TABLE KernelApi;
SYSTEM_SERVICE_TABLE GuiApi;
}SYSTEM_DESCRIPTOR_TABLE, * PSYSTEM_DESCRIPTOR_TABLE;
EXTERN_C PSYSTEM_DESCRIPTOR_TABLE KeServiceDescriptorTable;
typedef NTSTATUS(NTAPI* WbOpenProcess)(//类型定义
PHANDLE ProcessHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
PCLIENT_ID ClientId
);
WbOpenProcess NtOpenProcessOldFunAddress = NULL;//用来保存原来的函数
NTSTATUS NtOpenProcess(//hook的函数
PHANDLE ProcessHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
PCLIENT_ID ClientId
) {
DbgPrint("此函数已被Hook!");
return NtOpenProcessOldFunAddress(ProcessHandle, DesiredAccess, ObjectAttributes, ClientId);
}
ULONG GetSSDTIndex(UNICODE_STRING usDLLFileName, PCHAR pFunctionName) {//获取SSDT中的Index
NTSTATUS ntStatus = STATUS_SUCCESS;
//打开dll的句柄
HANDLE hFile = NULL;
//节句柄
HANDLE hSection = NULL;
//对象属性
OBJECT_ATTRIBUTES objectAttributes = { 0 };
//状态块
IO_STATUS_BLOCK ioStatus = { 0 };
//在映射后的dll基址
PVOID pBaseAddress = NULL;
ULONG viewSize = 0;
//用来保存索引
ULONG ulFunctionIndex = 0;
//初始化对象
InitializeObjectAttributes(&objectAttributes, &usDLLFileName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
ntStatus = ZwOpenFile(&hFile, GENERIC_READ, &objectAttributes, &ioStatus, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT);
if (!NT_SUCCESS(ntStatus))
{
DbgPrint("ZwOpenFile Error!");
return 0;
}
//初始化节对象
ntStatus = ZwCreateSection(&hSection, SECTION_MAP_READ | SECTION_MAP_WRITE, NULL, 0, PAGE_READWRITE, 0x1000000, hFile);
if (!NT_SUCCESS(ntStatus))
{
ZwClose(hFile);
DbgPrint("ZwCreateSection Error!");
return 0;
}
//创建一个节对象, 以 PE 结构中的 SectionALignment 大小对齐映射文件
ntStatus = ZwMapViewOfSection(hSection, NtCurrentProcess(), &pBaseAddress, 0, 1024, 0, &viewSize, ViewShare, MEM_TOP_DOWN, PAGE_READWRITE);
if (!NT_SUCCESS(ntStatus))
{
ZwClose(hFile);
ZwClose(hSection);
DbgPrint("ZwCreateSection Error!");
return 0;
}
// Dos Header
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pBaseAddress;
// NT Header
PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((PUCHAR)pDosHeader + pDosHeader->e_lfanew);
//导出表地址
PIMAGE_EXPORT_DIRECTORY pExportable = (PIMAGE_EXPORT_DIRECTORY)((PUCHAR)pDosHeader + pNtHeaders->OptionalHeader.DataDirectory[0].VirtualAddress);
//获得有名字的函数的个数
ULONG nlNumberForNames = pExportable->NumberOfNames;
//获得函数地址表的地址
PULONG lpNameAddress = (PULONG)((PUCHAR)pDosHeader + pExportable->AddressOfNames);
PCHAR lpFuncName = NULL;
for (ULONG i = 0; i < nlNumberForNames; i++)
{
lpFuncName = (PCHAR)((PUCHAR)pDosHeader + lpNameAddress[i]);
// 判断是否查找的函数
if (0 == _strnicmp(pFunctionName, lpFuncName, strlen(pFunctionName)))
{
// 获取导出函数地址
USHORT uHint = *(USHORT*)((PUCHAR)pDosHeader + pExportable->AddressOfNameOrdinals + 2 * i);
ULONG ulFuncAddr = *(PULONG)((PUCHAR)pDosHeader + pExportable->AddressOfFunctions + 4 * uHint);
PVOID lpFuncAddr = (PVOID)((PUCHAR)pDosHeader + ulFuncAddr);
// 获取 SSDT 函数 Index
ulFunctionIndex = *(ULONG*)((PUCHAR)lpFuncAddr + 1);
break;
}
}
ZwClose(hSection);
ZwClose(hFile);
return ulFunctionIndex;
}
NTSTATUS SetHook(ULONG ulFunAddr, PCHAR pFunctionName) {
ULONG ulFunctionIndex = 0;
NTSTATUS status = STATUS_SUCCESS;
UNICODE_STRING usDllFileName;
RtlInitUnicodeString(&usDllFileName, L"\\??\\C:\\Windows\\System32\\ntdll.dll");
//获得ssdt中的index
ulFunctionIndex = GetSSDTIndex(usDllFileName, pFunctionName);
if (ulFunctionIndex == 0)
{
DbgPrint("GetSSDTIndex Error!");
return status;
}
//打印出index
DbgPrint("0x%X", ulFunctionIndex);
//内存映射文件-SSDT表
PHYSICAL_ADDRESS pHyAddress = MmGetPhysicalAddress(KeServiceDescriptorTable->KernelApi.ServiceTableBase);
g_PageMapMenmory = MmMapIoSpace(pHyAddress, PAGE_SIZE, MmCached);
//保存原来的函数地址
NtOpenProcessOldFunAddress = g_PageMapMenmory[ulFunctionIndex];
//将索引的地址改为我们HOOK的函数
g_PageMapMenmory[ulFunctionIndex] = ulFunAddr;
return status;
}
NTSTATUS UnHook(ULONG ulFunAddr, PCHAR pFunctionName) {
ULONG ulFunctionIndex = 0;
NTSTATUS status = STATUS_SUCCESS;
UNICODE_STRING usDllFileName;
RtlInitUnicodeString(&usDllFileName, L"\\??\\C:\\Windows\\System32\\ntdll.dll");
////获得ssdt中的index
ulFunctionIndex = GetSSDTIndex(usDllFileName, pFunctionName);
if (ulFunctionIndex == 0)
{
DbgPrint("GetSSDTIndex Error!");
return status;
}
DbgPrint("0x%X", ulFunctionIndex);
//内存映射文件-SSDT表
PHYSICAL_ADDRESS pHyAddress = MmGetPhysicalAddress(KeServiceDescriptorTable->KernelApi.ServiceTableBase);
g_PageMapMenmory = MmMapIoSpace(pHyAddress, PAGE_SIZE, MmCached);
//将索引的地址改为我们保存的地址
g_PageMapMenmory[ulFunctionIndex] = ulFunAddr;
return status;
}
VOID DriverUnload(PDRIVER_OBJECT pDriverObject) {
//解除hook
UnHook((ULONG)NtOpenProcessOldFunAddress, "NtOpenProcess");
MmUnmapIoSpace(g_PageMapMenmory, PAGE_SIZE);
DbgPrint("Driver UnLoad Success!");
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegPath) {
DbgPrint("Driver Load Success!");
//进行hook
SetHook((ULONG)NtOpenProcess, "NtOpenProcess");
//卸载函数
pDriverObject->DriverUnload = DriverUnload;
return STATUS_SUCCESS;
}
