SSDT HOOK

该文详细介绍了如何通过获取系统路径加载ntdll,使用MmCreateSection和MmMapViewInSystemSpace加载到内存,查找导出表找到目标函数,然后修改SSDT表实现函数钩子,以控制ZwOpenProcess函数为例展示了具体流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先说一下大致思路
1.首先通过SharedUserData成员NtSystemRoot获取系统路径,进而组装成ntdll的全路径
2.接着通过MmCreateSectionMmMapViewInSystemSpace将ntdll加载到内存中,然后进行导出表搜索找到目标函数的服务号
3.然后通过内核导出的变量KeServiceDescriptorTable进而找到SSDT表
4.最后通过在SSDT表修改目标函数地址为自定义地址即可
所有代码如下:

SSDT.h

#pragma once
#include <ntifs.h>

typedef struct _SsdtItem
{
	PULONG funcTable;
	ULONG_PTR totalCount;
	ULONG_PTR funcMaxNumber;
	PUCHAR paramTable;
}SsdtItem;

typedef struct _SsdtTable
{
	SsdtItem ssdt;
	SsdtItem sssdt;
}SsdtTable, * PSsdtTable;

tool.h

#pragma once
#include<ntifs.h>
PWCHAR GetSystemPath();
PVOID MapMemorry(PWCHAR systempath);
ULONG64 ExportTableFuncByName(char* pData, char* funcName);
VOID FuncDestroy();
VOID UmMapOfViewFile(PVOID mapBase);
ULONG GetFuncIndex();
VOID FuncInit();
VOID SSDTHook(char* funcName, PVOID FuncAddress);
extern PVOID address;
extern PUCHAR func;

tool.c

#include<ntifs.h>
#include<ntstrsafe.h>
#include<ntimage.h>
#include"SSDT.h"
#include<intrin.h>
#include"tool.h"
//导出服务表
extern PSsdtTable KeServiceDescriptorTable;

PVOID address = NULL;
PUCHAR func = NULL;

EXTERN_C NTSTATUS MmCreateSection(
    __deref_out PVOID* SectionObject,
    __in ACCESS_MASK DesiredAccess,
    __in_opt POBJECT_ATTRIBUTES ObjectAttributes,
    __in PLARGE_INTEGER InputMaximumSize,
    __in ULONG SectionPageProtection,
    __in ULONG AllocationAttributes,
    __in_opt HANDLE FileHandle,
    __in_opt PFILE_OBJECT FileObject
);


//关闭写保护
ULONG wpOff()
{
    ULONG cr0 = __readcr0();
    _disable();   //关闭中断
    __writecr0(cr0 & (~0x10000));   //关闭写保护
    return cr0;
}

VOID wpOn(ULONG value)
{
    __writecr0(value);
    _enable();
}

PWCHAR GetSystemPath()
{
    //获取系统目录
    PWCH systempath = (PWCH)ExAllocatePool(PagedPool, PAGE_SIZE);
    memset(systempath, 0, PAGE_SIZE);
    //拼接完整的路径
    RtlStringCbPrintfW(systempath, PAGE_SIZE, L"\\??\\%s\\system32\\ntdll.dll", SharedUserData->NtSystemRoot);
    DbgPrintEx(77, 0, "[db]:%S\r\n", systempath);

    return systempath;
}

PVOID MapMemorry(PWCHAR systempath)
{
    UNICODE_STRING Psystempath = { 0 };
    RtlInitUnicodeString(&Psystempath, systempath);
    PHANDLE hFile;
    OBJECT_ATTRIBUTES objAttributes;
    IO_STATUS_BLOCK IoStatusBlock = { 0 };
    InitializeObjectAttributes(&objAttributes, &Psystempath, OBJ_CASE_INSENSITIVE, NULL, NULL);

    NTSTATUS status = ZwCreateFile(&hFile, GENERIC_READ, &objAttributes, &IoStatusBlock, NULL,
        FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, NULL);

    if (!NT_SUCCESS(status))
    {
        NtClose(hFile);
    }

    //创建节区
    PVOID hSection = NULL;
    OBJECT_ATTRIBUTES sectionAddr;
    InitializeObjectAttributes(&sectionAddr, NULL, OBJ_CASE_INSENSITIVE, NULL, NULL);
    LARGE_INTEGER InputMaximumSize = { 0 };
    status = MmCreateSection(&hSection, SECTION_ALL_ACCESS, &sectionAddr,
        &InputMaximumSize, PAGE_EXECUTE_READWRITE, 0x1000000, hFile, NULL);

    if (!NT_SUCCESS(status))
    {
        ZwClose(hFile);
        return 0;
    }

    PVOID mapBase = NULL;
    SIZE_T viewSize = { 0 }; 
    status = MmMapViewInSystemSpace(hSection, &mapBase, &viewSize);

    ObDereferenceObject(hSection);
    ZwClose(hFile);

    if (NT_SUCCESS(status))
    {
        return mapBase;
    }

    return 0;
}

ULONG64 ExportTableFuncByName(char* pData, char* funcName)
{
    PIMAGE_DOS_HEADER pHead = (PIMAGE_DOS_HEADER)pData;
    PIMAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS)(pData + pHead->e_lfanew);
    int numberRvaAndSize = pNt->OptionalHeader.NumberOfRvaAndSizes;
    PIMAGE_DATA_DIRECTORY pDir = (PIMAGE_DATA_DIRECTORY)&pNt->OptionalHeader.DataDirectory[0];

    PIMAGE_EXPORT_DIRECTORY pExport = (PIMAGE_EXPORT_DIRECTORY)(pData + pDir->VirtualAddress);

    ULONG64 funcAddr = 0;
    for (int i = 0; i < pExport->NumberOfNames; i++)
    {
        int* funcAddress = pData + pExport->AddressOfFunctions;
        int* names = pData + pExport->AddressOfNames;
        short* fh = pData + pExport->AddressOfNameOrdinals;
        int index = -1;
        char* name = pData + names[i];

        if (strcmp(name, funcName) == 0)
        {
            index = fh[i];
        }
        if (index != -1)
        {
            funcAddr = pData + funcAddress[index];
            break;
        }
    }

    if (!funcAddr)
    {
        KdPrint(("没有找到函数%s\r\n", funcName));
    }
    else
    {
        KdPrint(("找到函数%s addr %p\r\n", funcName, funcAddr));
    }

    return funcAddr;
}

VOID FuncInit()
{
    PWCHAR path = GetSystemPath();
    address = MapMemorry(path);

    ExFreePool(path);
    return TRUE;
}

ULONG GetFuncIndex(PVOID FuncAddress)
{
    PUCHAR funcd = ExportTableFuncByName(address, FuncAddress);
    if (funcd == NULL)
    {
        return -1;
    }
    return *(PULONG)(funcd + 1);
}

VOID UmMapOfViewFile(PVOID mapBase)
{
    if (!mapBase) return;
    MmUnmapViewInSystemSpace(mapBase);
}

VOID FuncDestroy()
{
    if (!address)
    {
        return;
    }
    UmMapOfViewFile(address);
    address = NULL;
}

PSsdtTable SsdtGet()
{
    return (PSsdtTable)((PUCHAR)KeServiceDescriptorTable + 0x40);
}

VOID SSDTHook(char* funcName,PVOID FuncAddress)
{
    //获取SSDT位置
   PSsdtTable ssdtA = SsdtGet();
   if (!ssdtA)
   {
       return;
   }
   ULONG index = GetFuncIndex(funcName);
   if (index == -1)
   {
       return;
   }
   func = (PULONG)ssdtA->ssdt.funcTable[index];
   ULONG wp = wpOff();
   ssdtA->ssdt.funcTable[index] = FuncAddress;
   wpOn(wp);
}

DriverEntry.c

#include<ntifs.h>
#include"SSDT.h"
#include<ntstrsafe.h>
#include"tool.h"

typedef NTSTATUS (NTAPI* OpenProcessProc)(
	_Out_ PHANDLE ProcessHandle,
	_In_ ACCESS_MASK DesiredAccess,
	_In_ POBJECT_ATTRIBUTES ObjectAttributes,
	_In_opt_ PCLIENT_ID ClientId
); 

NTSTATUS NTAPI MyZwOpenProcess
(
	_Out_ PHANDLE ProcessHandle,
	_In_ ACCESS_MASK DesiredAccess,
	_In_ POBJECT_ATTRIBUTES ObjectAttributes,
	_In_opt_ PCLIENT_ID ClientId
)
{
	DbgPrintEx(77, 0, "[db]:%s\r\n", __FUNCTION__);
	OpenProcessProc fun = (OpenProcessProc)func;

	return fun(ProcessHandle, DesiredAccess, ObjectAttributes, ClientId);
};

VOID DriverUnload(_In_ struct _DRIVER_OBJECT* DriverObject)
{
	SSDTHook("ZwOpenProcess", func);
	FuncDestroy();
	
	LARGE_INTEGER inTime = { 0 };
	inTime.QuadPart = -10000 * 10000;  //10s
	KeDelayExecutionThread(KernelMode, FALSE, &inTime);
}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath)
{
	//映射ntdll并获取系统服务号
	FuncInit();

	SSDTHook("ZwOpenProcess", MyZwOpenProcess);

	pDriverObject->DriverUnload = DriverUnload;
	
	return STATUS_SUCCESS;
}
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值