Win64 驱动内核编程-20.UnHook SSDT
阅读原文时间:2023年07月13日阅读:1

UNHOOK SSDT

要恢复 SSDT,首先要获得 SSDT 各个函数的原始地址,而 SSDT 各个函数的原始地址,自然是存储在内核文件里的。于是,有了以下思路:

1.获得内核里 KiServiceTable 的地址(变量名称:KiServiceTable)

2.获得内核文件在内核里的加载地址(变量名称:NtosBase)

3.获得内核文件在 PE32+结构体里的映像基址(变量名称:NtosImageBase)

4.在自身进程里加载内核文件并取得映射地址(变量名称:NtosInProcess)

5.计算出 KiServiceTable 和 NtosBase 之间的“距离”(变量名称:RVA)

6.获得指定 INDEX 函数的地址(计算公式:*(PULONGLONG)(NtosInProcess + RVA

+ 8 * index) - NtosImageBase + NtosBase)

第六步的计算原理:

上面公式需要好好理解下,我卡在一个地方卡了好久,就是

NtosBase + RVA = KiServiceTable

NtosInProcess + RVA = 是一个地址,这个地址存的是存数组地址的。还是相对于文件的基址的。我一直觉得因为都是load到了内存:

NtosBase + RVA  = NtosInProcess + RVA

因为之前我认为只有在文件里才会存在FOA地址什么的,一担load了之后就自动修改了。根据相关桥自动修改了。结果看这个样子并不是我想的那样,load之后依然是相对于文件基址的地址而不是和NtosBase + RVA = KiServiceTable一样。这个后期整清楚了我在补充吧。但是已经验证了,资料上的公式是正确的。

接下来是细化每一个地方(下面的代码是我从资料里整理过来的,如果是要实际使用,记得重新整理并且改改,比如内存泄漏问题,比如很多东西都有函数代替不用咱们模拟,代码会精简许多)。

驱动部分代码:

MyDriver.h

#include <ntddk.h>

#define dprintf                if (DBG) DbgPrint

#define    DEVICE_NAME         L"\\Device\\MyDriver"
#define LINK_NAME            L"\\DosDevices\\MyDriver"
#define LINK_GLOBAL_NAME    L"\\DosDevices\\Global\\MyDriver"

#define IOCTL_ClrSSDTHOOK    CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS) //Clear ssdt hook
#define IOCTL_GetKiSrvTab    CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS) //Get KiServiceTable
#define IOCTL_GetFuncAddr    CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS) //Get function address
#define IOCTL_GetTest        CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS) //test

MyDriver.cpp

#include <ntddk.h>
#include <windef.h>
#include "MyDriver.h"

#pragma intrinsic(__readmsr)

typedef struct _SYSTEM_SERVICE_TABLE{
    PVOID       ServiceTableBase;
    PVOID       ServiceCounterTableBase;
    ULONGLONG   NumberOfServices;
    PVOID       ParamTableBase;
} SYSTEM_SERVICE_TABLE, *PSYSTEM_SERVICE_TABLE;

typedef struct _UNHOOK_SSDT64{
    ULONGLONG Address;
    ULONGLONG id;
}UNHOOK_SSDT64,*PUNHOOK_SSDT64;

typedef UINT64 (__fastcall *SCFN)(UINT64,UINT64);

SCFN scfn;
ULONGLONG ssdt_base_aadress, ssdt_func_address, KiServiceTable;
ULONG32 ssdt_func_index;
UNHOOK_SSDT64 uhssdt64={0};
PSYSTEM_SERVICE_TABLE KeServiceDescriptorTable;

ULONGLONG GetKeServiceDescriptorTable64()
{
    PUCHAR StartSearchAddress = (PUCHAR)__readmsr(0xC0000082);
    PUCHAR EndSearchAddress = StartSearchAddress + 0x500;
    PUCHAR i = NULL;
    UCHAR b1 = 0, b2 = 0, b3 = 0;
    ULONG templong = 0;
    ULONGLONG addr = 0;
    for (i = StartSearchAddress; i<EndSearchAddress; i++)
    {
        if (MmIsAddressValid(i) && MmIsAddressValid(i + 1) && MmIsAddressValid(i + 2))
        {
            b1 = *i;
            b2 = *(i + 1);
            b3 = *(i + 2);
            if (b1 == 0x4c && b2 == 0x8d && b3 == 0x15) //4c8d15
            {
                memcpy(&templong, i + 3, 4);
                addr = (ULONGLONG)templong + (ULONGLONG)i + 7;
                return addr;
            }
        }
    }
    return 0;
}

KIRQL WPOFFx64()
{
    KIRQL irql=KeRaiseIrqlToDpcLevel();
    UINT64 cr0=__readcr0();
    cr0 &= 0xfffffffffffeffff;
    __writecr0(cr0);
    _disable();
    return irql;
}

void WPONx64(KIRQL irql)
{
    UINT64 cr0=__readcr0();
    cr0 |= 0x10000;
    _enable();
    __writecr0(cr0);
    KeLowerIrql(irql);
}

ULONG GetOffsetAddress(ULONGLONG FuncAddr)
{
    ULONG dwtmp=0;
    PULONG ServiceTableBase=NULL;
    if(KeServiceDescriptorTable==NULL)
        KeServiceDescriptorTable=(PSYSTEM_SERVICE_TABLE)GetKeServiceDescriptorTable64();
    ServiceTableBase=(PULONG)KeServiceDescriptorTable->ServiceTableBase;
    dwtmp=(ULONG)(FuncAddr-(ULONGLONG)ServiceTableBase);
    return dwtmp<<4;
}

VOID UnHookSSDT(ULONG id, ULONGLONG FuncAddr)
{
    KIRQL irql;
    ULONG dwtmp;
    PULONG ServiceTableBase=NULL;
    dwtmp=GetOffsetAddress(FuncAddr);
    ServiceTableBase=(PULONG)KeServiceDescriptorTable->ServiceTableBase;
    irql=WPOFFx64();
    ServiceTableBase[id]=dwtmp;
    WPONx64(irql);
}

ULONGLONG GetSSDTFunctionAddress64(ULONGLONG NtApiIndex)
{
    LONG dwTemp = 0;
    ULONGLONG qwTemp = 0, stb = 0, ret = 0;
    PSYSTEM_SERVICE_TABLE ssdt = (PSYSTEM_SERVICE_TABLE)GetKeServiceDescriptorTable64();
    stb = (ULONGLONG)(ssdt->ServiceTableBase);
    qwTemp = stb + 4 * NtApiIndex;
    dwTemp = *(PLONG)qwTemp;
    dwTemp = dwTemp >> 4;
    ret = stb + (LONG64)dwTemp;
    return ret;
}

VOID DriverUnload(PDRIVER_OBJECT pDriverObj)
{
    UNICODE_STRING strLink;
    RtlInitUnicodeString(&strLink, LINK_NAME);
    IoDeleteSymbolicLink(&strLink);
    IoDeleteDevice(pDriverObj->DeviceObject);
    DbgPrint("[my driver]:DriverUnload\n");
}

NTSTATUS DispatchCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
    pIrp->IoStatus.Status = STATUS_SUCCESS;
    pIrp->IoStatus.Information = 0;
    IoCompleteRequest(pIrp, IO_NO_INCREMENT);
    return STATUS_SUCCESS;
}

NTSTATUS DispatchClose(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
    pIrp->IoStatus.Status = STATUS_SUCCESS;
    pIrp->IoStatus.Information = 0;
    IoCompleteRequest(pIrp, IO_NO_INCREMENT);
    return STATUS_SUCCESS;
}

NTSTATUS DispatchIoctl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
    NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
    PIO_STACK_LOCATION pIrpStack;
    ULONG uIoControlCode;
    PVOID pIoBuffer;
    ULONG uInSize;
    ULONG uOutSize;
    pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
    uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
    pIoBuffer = pIrp->AssociatedIrp.SystemBuffer;
    uInSize = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
    uOutSize = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;
    switch(uIoControlCode)
    {
        case IOCTL_ClrSSDTHOOK:
        {
            memcpy(&uhssdt64, pIoBuffer, sizeof(UNHOOK_SSDT64));
            UnHookSSDT((ULONG)uhssdt64.id, uhssdt64.Address);
            status = STATUS_SUCCESS;
            break;
        }
        case IOCTL_GetKiSrvTab:
        {
            if(ssdt_base_aadress==0)
                ssdt_base_aadress=GetKeServiceDescriptorTable64();
            KiServiceTable=*(PULONGLONG)ssdt_base_aadress;
            memcpy(pIoBuffer, &KiServiceTable, 8);
            status = STATUS_SUCCESS;
            break;
        }
        case IOCTL_GetFuncAddr:
        {
            memcpy(&ssdt_func_index, pIoBuffer, 4);
            ssdt_func_address=GetSSDTFunctionAddress64((ULONGLONG)ssdt_func_index);
            memcpy(pIoBuffer, &ssdt_func_address, 8);
            status = STATUS_SUCCESS;
            break;
        }
        case IOCTL_GetTest:
        {
            DbgPrint("[my driver]:IoControl is OK \n");
            break;
        }
    }
    if(status == STATUS_SUCCESS)
        pIrp->IoStatus.Information = uOutSize;
    else
        pIrp->IoStatus.Information = 0;
    pIrp->IoStatus.Status = status;
    IoCompleteRequest(pIrp, IO_NO_INCREMENT);
    return status;
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegistryString)
{
    DbgPrint("[my driver]:DriverEntry\n");

    NTSTATUS status = STATUS_SUCCESS;
    UNICODE_STRING ustrLinkName;
    UNICODE_STRING ustrDevName;
    PDEVICE_OBJECT pDevObj;
    pDriverObj->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
    pDriverObj->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
    pDriverObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctl;
    pDriverObj->DriverUnload = DriverUnload;
    RtlInitUnicodeString(&ustrDevName, DEVICE_NAME);
    status = IoCreateDevice(pDriverObj, 0, &ustrDevName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDevObj);
    if(!NT_SUCCESS(status)) return status;
    if(IoIsWdmVersionAvailable(1, 0x10))
        RtlInitUnicodeString(&ustrLinkName, LINK_GLOBAL_NAME);
    else
        RtlInitUnicodeString(&ustrLinkName, LINK_NAME);
    status = IoCreateSymbolicLink(&ustrLinkName, &ustrDevName);
    if(!NT_SUCCESS(status))
    {
        IoDeleteDevice(pDevObj);
        return status;
    }
    return STATUS_SUCCESS;
}

安装部分代码:

ScmDrvCtrl.h

#pragma comment(lib,"advapi32.lib")

class cDrvCtrl
{
public:
    cDrvCtrl()
    {
        m_pSysPath = NULL;
        m_pServiceName = NULL;
        m_pDisplayName = NULL;
        m_hSCManager = NULL;
        m_hService = NULL;
        m_hDriver = INVALID_HANDLE_VALUE;
    }
    ~cDrvCtrl()
    {
        if (m_hService) {
            CloseServiceHandle(m_hService);
        }
        if (m_hSCManager) {
            CloseServiceHandle(m_hSCManager);
        }
        if (m_hDriver) {
            CloseHandle(m_hDriver);
        }
    }
public:
    DWORD m_dwLastError;
    PCHAR m_pSysPath;
    PCHAR m_pServiceName;
    PCHAR m_pDisplayName;
    HANDLE m_hDriver;
    SC_HANDLE m_hSCManager;
    SC_HANDLE m_hService;
public:
    BOOL Install(PCHAR pSysPath,PCHAR pServiceName,PCHAR pDisplayName);
    BOOL Start();
    BOOL Stop();
    BOOL Remove();
    BOOL Open(PCHAR pLinkName);
    BOOL IoControl(DWORD dwIoCode, PVOID InBuff, DWORD InBuffLen, PVOID OutBuff, DWORD OutBuffLen, DWORD *RealRetBytes);
    BOOL IoControl(HANDLE hDrvHandle, DWORD dwIoControlCode, PVOID lpInBuffer, DWORD nInBufferSize, PVOID lpOutBuffer, DWORD nOutBufferSize);
private:
    BOOL GetSvcHandle(PCHAR pServiceName);
    DWORD CTL_CODE_GEN(DWORD lngFunction);
protected:
    //null
};

BOOL cDrvCtrl::GetSvcHandle(PCHAR pServiceName)
{
    m_pServiceName = pServiceName;
    m_hSCManager = OpenSCManagerA(NULL,NULL,SC_MANAGER_ALL_ACCESS);
    if (NULL == m_hSCManager)
    {
        m_dwLastError = GetLastError();
        return FALSE;
    }
    m_hService = OpenServiceA(m_hSCManager,m_pServiceName,SERVICE_ALL_ACCESS);
    if (NULL == m_hService)
    {
        CloseServiceHandle(m_hSCManager);
        return FALSE;
    }
    else
    {
        return TRUE;
    }
}

BOOL cDrvCtrl::Install(PCHAR pSysPath,PCHAR pServiceName,PCHAR pDisplayName)
{
    m_pSysPath = pSysPath;
    m_pServiceName = pServiceName;
    m_pDisplayName = pDisplayName;
    m_hSCManager = OpenSCManagerA(NULL,NULL,SC_MANAGER_ALL_ACCESS);
    if (NULL == m_hSCManager)
    {
        m_dwLastError = GetLastError();
        return FALSE;
    }
    m_hService = CreateServiceA(m_hSCManager,m_pServiceName,m_pDisplayName,
                                SERVICE_ALL_ACCESS,SERVICE_KERNEL_DRIVER,SERVICE_DEMAND_START,SERVICE_ERROR_NORMAL,
                                m_pSysPath,NULL,NULL,NULL,NULL,NULL);
    if (NULL == m_hService)
    {
        m_dwLastError = GetLastError();
        if (ERROR_SERVICE_EXISTS == m_dwLastError)
        {
            m_hService = OpenServiceA(m_hSCManager,m_pServiceName,SERVICE_ALL_ACCESS);
            if (NULL == m_hService)
            {
                CloseServiceHandle(m_hSCManager);
                return FALSE;
            }
        }
        else
        {
            CloseServiceHandle(m_hSCManager);
            return FALSE;
        }
    }
    return TRUE;
}

BOOL cDrvCtrl::Start()
{
    if (!StartServiceA(m_hService,NULL,NULL))
    {
        m_dwLastError = GetLastError();
        return FALSE;
    }
    return TRUE;
}

BOOL cDrvCtrl::Stop()
{
    SERVICE_STATUS ss;
    GetSvcHandle(m_pServiceName);
    if (!ControlService(m_hService,SERVICE_CONTROL_STOP,&ss))
    {
        m_dwLastError = GetLastError();
        return FALSE;
    }
    return TRUE;

}

BOOL cDrvCtrl::Remove()
{
    GetSvcHandle(m_pServiceName);
    if (!DeleteService(m_hService))
    {
        m_dwLastError = GetLastError();
        return FALSE;
    }
    return TRUE;
}

BOOL cDrvCtrl::Open(PCHAR pLinkName)//example: \\\\.\\xxoo
{
    if (m_hDriver != INVALID_HANDLE_VALUE)
        return TRUE;
    m_hDriver = CreateFileA(pLinkName, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
    if(m_hDriver != INVALID_HANDLE_VALUE)
        return TRUE;
    else
        return FALSE;
}

BOOL cDrvCtrl::IoControl(DWORD dwIoCode, PVOID InBuff, DWORD InBuffLen, PVOID OutBuff, DWORD OutBuffLen, DWORD *RealRetBytes)
{
    DWORD dw;
    BOOL b=DeviceIoControl(m_hDriver,CTL_CODE_GEN(dwIoCode),InBuff,InBuffLen,OutBuff,OutBuffLen,&dw,NULL);
    if(RealRetBytes)
        *RealRetBytes=dw;
    return b;
}

BOOL cDrvCtrl::IoControl(HANDLE hDrvHandle, DWORD dwIoControlCode, PVOID lpInBuffer, DWORD nInBufferSize, PVOID lpOutBuffer, DWORD nOutBufferSize)
{
    DWORD lDrvRetSize;
    return DeviceIoControl(hDrvHandle, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, &lDrvRetSize, 0);
}

DWORD cDrvCtrl::CTL_CODE_GEN(DWORD lngFunction)
{
    return (FILE_DEVICE_UNKNOWN * 65536) | (FILE_ANY_ACCESS * 16384) | (lngFunction * 4) | METHOD_BUFFERED;
}

main.cpp

#include "stdafx.h"
#include <string>
#include <stdio.h>
#include <Windows.h>
#include "ScmDrvCtrl.h"

#pragma warning(disable:4996)
#pragma comment(lib,"user32.lib")

using namespace std;

void GetAppPath(char *szCurFile)
{
    GetModuleFileNameA(0, szCurFile, MAX_PATH);
    for (SIZE_T i = strlen(szCurFile) - 1; i >= 0; i--)
    {
        if (szCurFile[i] == '\\')
        {
            szCurFile[i + 1] = '\0';
            break;
        }
    }
}

//start********************Dirver*************************
cDrvCtrl dcDirver;
BOOL InstallDriver(char * pSysFileName, char * pServiceName, char * pDisplayName) {
    char szSysFile[MAX_PATH] = { 0 };
    GetAppPath(szSysFile);
    strcat(szSysFile, pSysFileName);
    BOOL bInstallSuc = FALSE;

    if (dcDirver.Install(szSysFile, pServiceName, pDisplayName)) {
        if (dcDirver.Start()) {

            char pLink[1024] = "\\\\.\\";
            strcat(pLink , pDisplayName);
            dcDirver.Open(pLink);

            DWORD x = 0, y = 0, z = 0;
            dcDirver.IoControl(0x803, &x, sizeof(x), &y, sizeof(y), &z);
            bInstallSuc = TRUE;
        }
    }
    return bInstallSuc;
}

VOID UnInstallDriver() {

    CloseHandle(dcDirver.m_hDriver);
    dcDirver.Stop();
    dcDirver.Remove();
}

//end********************Dirver*************************

//start********************NtosBase*************************
//获得内核文件在内核里的加载地址(变量名称:NtosBase)
#ifndef NT_SUCCESS
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
#endif
#ifndef STATUS_SUCCESS
#define STATUS_SUCCESS       ((NTSTATUS)0x00000000L)
#endif
#ifndef STATUS_UNSUCCESSFUL
#define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L)
#endif

#define SystemModuleInformation 11
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)

typedef struct _SYSTEM_MODULE_INFORMATION_ENTRY{
    ULONG Unknow1;
    ULONG Unknow2;
    ULONG Unknow3;
    ULONG Unknow4;
    PVOID64 Base;
    ULONG Size;
    ULONG Flags;
    USHORT Index;
    USHORT NameLength;
    USHORT LoadCount;
    USHORT ModuleNameOffset;
    char ImageName[256];
} SYSTEM_MODULE_INFORMATION_ENTRY, *PSYSTEM_MODULE_INFORMATION_ENTRY;

typedef struct _SYSTEM_MODULE_INFORMATION{
    ULONG Count;//内核中以加载的模块的个数
    SYSTEM_MODULE_INFORMATION_ENTRY Module[1];
} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;

typedef long(__stdcall *ZWQUERYSYSTEMINFORMATION)(
    IN ULONG SystemInformationClass,
    IN OUT PVOID SystemInformation,
    IN ULONG SystemInformationLength,
    IN PULONG ReturnLength OPTIONAL);
ZWQUERYSYSTEMINFORMATION ZwQuerySystemInformation;

ULONGLONG NtosBase = 0;
CHAR NtosName[260] = { 0 };

char *cs(char *str1, char *str2) //connect string
{
    long newstrlen = strlen(str1) + strlen(str2) + 1;
    char *newstr = (char*)malloc(newstrlen);
    memcpy(newstr, str1, strlen(str1));
    memcpy(newstr + strlen(str1), str2, strlen(str2) + 1);
    return newstr;
}

ULONGLONG GetNtosBaseAndPath(char *ModuleName){
    ZwQuerySystemInformation = (ZWQUERYSYSTEMINFORMATION)GetProcAddress(GetModuleHandleA("ntdll.dll"), "ZwQuerySystemInformation");
    ULONG NeedSize, i, ModuleCount;
    ULONGLONG qwBase = 0;
    PSYSTEM_MODULE_INFORMATION pSystemModuleInformation;

    ULONG uBufferSize = 0x5000;
    PVOID pBuffer = malloc(uBufferSize);
    if (ZwQuerySystemInformation(SystemModuleInformation, pBuffer, uBufferSize, &NeedSize) == STATUS_INFO_LENGTH_MISMATCH) {
        free(pBuffer);
        pBuffer = malloc(NeedSize+10);
        ZwQuerySystemInformation(SystemModuleInformation, pBuffer, uBufferSize, &NeedSize);
    }

    pSystemModuleInformation = (PSYSTEM_MODULE_INFORMATION)pBuffer;
    //获得模块的总数量
    ModuleCount = pSystemModuleInformation->Count;
    if (ModuleName != NULL) {
        strcpy(ModuleName, pSystemModuleInformation->Module[0].ImageName + pSystemModuleInformation->Module[0].ModuleNameOffset);
    }
    qwBase = (ULONGLONG)pSystemModuleInformation->Module[0].Base;
    free(pBuffer);
    return qwBase;
}
VOID GetNtosBase(){
    char FileName[260] = { 0 }, *FullName;
    NtosBase = GetNtosBaseAndPath(FileName);
    FullName = cs("C:\\Windows\\system32\\", FileName);
    strcpy(NtosName, FullName);
    printf("NTOSKRNL base: %llx\n", NtosBase);
    printf("NTOSKRNL name: %s\n", NtosName);
}

//end********************NtosBase*************************

//start********************NtosImageBase*************************

ULONGLONG  NtosImageBase = 0;

DWORD FileLen(char *filename){
    WIN32_FIND_DATAA fileInfo = { 0 };
    DWORD fileSize = 0;
    HANDLE hFind;
    hFind = FindFirstFileA(filename, &fileInfo);
    if (hFind != INVALID_HANDLE_VALUE){
        fileSize = fileInfo.nFileSizeLow;
        FindClose(hFind);
    }
    return fileSize;
}

CHAR *LoadDllContext(char *filename){
    DWORD dwReadWrite, LenOfFile = FileLen(filename);
    HANDLE hFile = CreateFileA(filename, GENERIC_READ , FILE_SHARE_READ , 0, OPEN_EXISTING, 0, 0);
    if (hFile != INVALID_HANDLE_VALUE){
        PCHAR buffer = (PCHAR)malloc(LenOfFile);
        SetFilePointer(hFile, 0, 0, FILE_BEGIN);
        ReadFile(hFile, buffer, LenOfFile, &dwReadWrite, 0);
        CloseHandle(hFile);
        return buffer;
    }
    return NULL;
}

VOID GetNtosImageBase(){
    PIMAGE_NT_HEADERS64 pinths64;
    PIMAGE_DOS_HEADER pdih;
    char *NtosFileData = NULL;
    NtosFileData = LoadDllContext(NtosName);
    pdih = (PIMAGE_DOS_HEADER)NtosFileData;
    pinths64 = (PIMAGE_NT_HEADERS64)(NtosFileData + pdih->e_lfanew);
    NtosImageBase = pinths64->OptionalHeader.ImageBase;
    printf("ImageBase: %llx\n", NtosImageBase);
    free(NtosFileData);
}
//end********************NtosImageBase*************************

//start********************KiServiceTable*************************
ULONGLONG KiServiceTable;
DWORD CTL_CODE_GEN(DWORD lngFunction)
{
    return (FILE_DEVICE_UNKNOWN * 65536) | (FILE_ANY_ACCESS * 16384) | (lngFunction * 4) | METHOD_BUFFERED;
}
VOID GetKiServiceTable()
{
    dcDirver.IoControl(dcDirver.m_hDriver, CTL_CODE_GEN(0x801), NULL, 0, &KiServiceTable, 8);
    printf("KiServiceTable: %llx\n", KiServiceTable);
}
//end********************KiServiceTable*************************

//start********************AllSSDTFunction*************************

DWORD GetSSDTFunctionIndex(char *FunctionName)
{
    return *(DWORD*)((PUCHAR)GetProcAddress(LoadLibraryW(L"ntdll.dll"), FunctionName) + 4); //极限精简
    /*
    PUCHAR fptr=(PUCHAR)GetProcAddress(LoadLibraryW(L"ntdll.dll"),FunctionName);
    DWORD index=*(DWORD*)(fptr+4);
    return index;
    */
    /*
    所有的函数都像下面一样:
    00000000`775a0110 4c8bd1          mov     r10,rcx
    00000000`775a0113 b8??000000      mov     eax,??h
    00000000`775a0118 0f05            syscall
    00000000`775a011a c3              ret
    */
}

ULONGLONG NtosInProcess = 0;

ULONGLONG GetFunctionOriginalAddress(DWORD index)
{
    if (NtosInProcess == 0)
        NtosInProcess = (ULONGLONG)LoadLibraryExA(NtosName, 0, DONT_RESOLVE_DLL_REFERENCES);  //"C:\\Windows\\system32\\ntkrnlmp.exe"
    ULONGLONG RVA = KiServiceTable - NtosBase;
    ULONGLONG temp = *(PULONGLONG)(NtosInProcess + RVA + 8 * (ULONGLONG)index);
    ULONGLONG RVA_index = temp - NtosImageBase; //IMAGE_OPTIONAL_HEADER64.ImageBase=0x140000000(这个值基本是固定的)
    return RVA_index + NtosBase;
}

VOID PrintAllSSDTFunction()
{
    DWORD i = 0, fl = 0, fs_pos = 0, fe_pos = 0, PauseCnt = 0, ssdt_fun_cnt = 0;
    ULONG64 ssdt_func_addr = 0, ssdt_func_ori_addr = 0;
    CopyFileW(L"c:\\windows\\system32\\ntdll.dll", L"c:\\ntdll.txt", 0);
    fl = FileLen("c:\\ntdll.txt");
    char func_start[] = "ZwAcceptConnectPort", func_end[] = "ZwYieldExecution"; //每个函数名之间隔着\0
    char *funs = (char *)malloc(strlen(func_start)); memcpy(funs, func_start, strlen(func_start));
    char *fune = (char *)malloc(strlen(func_end)); memcpy(fune, func_end, strlen(func_end));
    char *ntdlltxt = LoadDllContext("c:\\ntdll.txt");
    for (i = 0; i<fl; i++)
    {
        if (memcmp(ntdlltxt + i, funs, strlen(func_start)) == 0)
            fs_pos = i;
        if (memcmp(ntdlltxt + i, fune, strlen(func_end)) == 0)
        {
            fe_pos = i;
            break;
        }
    }
    ntdlltxt = ntdlltxt + fs_pos;
    //打印头
    printf("ID\t当前地址\t  原始地址\t    函数名\n");
    //这里不能显示到最后一个函数
    while (strcmp(ntdlltxt, func_end) != 0)
    {
        DWORD fn_index = GetSSDTFunctionIndex(ntdlltxt);
        if (fn_index<1000)
        {
            ssdt_func_ori_addr = GetFunctionOriginalAddress(fn_index);
            dcDirver.IoControl(dcDirver.m_hDriver, CTL_CODE_GEN(0x802), &fn_index, 4, &ssdt_func_addr, 8);
            ntdlltxt[0] = 'N'; ntdlltxt[1] = 't';               //寻找的是Zw***,但是应该显示Nt***
            if (ssdt_func_ori_addr != ssdt_func_addr)
                printf("0x%-0.3X!\t%llx  %llx  %s\n", fn_index, ssdt_func_addr, ssdt_func_ori_addr, ntdlltxt);
            else
                printf("0x%-0.3X\t%llx  %llx  %s\n", fn_index, ssdt_func_addr, ssdt_func_ori_addr, ntdlltxt);
        }
        else
        {
            fn_index = 0x57;    //不同的系统,不同的编号,由于目前只有WIN7 X64,所以这里直接硬编码了
            ssdt_func_ori_addr = GetFunctionOriginalAddress(fn_index);
            dcDirver.IoControl(dcDirver.m_hDriver, CTL_CODE_GEN(0x802), &fn_index, 4, &ssdt_func_addr, 8);
            ntdlltxt[0] = 'N'; ntdlltxt[1] = 't';
            if (ssdt_func_ori_addr != ssdt_func_addr)
                printf("0x%-0.3X!\t%llx  %llx  %s\n", fn_index, ssdt_func_addr, ssdt_func_ori_addr, ntdlltxt);
            else
                printf("0x%-0.3X\t%llx  %llx  %s\n", fn_index, ssdt_func_addr, ssdt_func_ori_addr, ntdlltxt);
            /*
            0:000> u ZwQuerySystemTime
            ntdll!ZwQuerySystemTime:
            00000000`77b20450 e91b62fdff      jmp     ntdll!RtlQuerySystemTime (00000000`77af6670)
            00000000`77b20455 6666660f1f840000000000 nop word ptr [rax+rax]
            */
            /*
            nt!ZwQuerySystemTime:
            fffff800`01673fa0 488bc4          mov     rax,rsp
            fffff800`01673fa3 fa              cli
            fffff800`01673fa4 4883ec10        sub     rsp,10h
            fffff800`01673fa8 50              push    rax
            fffff800`01673fa9 9c              pushfq
            fffff800`01673faa 6a10            push    10h
            fffff800`01673fac 488d053d270000  lea     rax,[nt!KiServiceLinkage (fffff800`016766f0)]
            fffff800`01673fb3 50              push    rax
            fffff800`01673fb4 b857000000      mov     eax,57h
            fffff800`01673fb9 e9825e0000      jmp     nt!KiServiceInternal (fffff800`01679e40)
            fffff800`01673fbe 6690            xchg    ax,ax
            */
        }
        ntdlltxt = ntdlltxt + strlen(ntdlltxt) + 1;
        PauseCnt++;
        ssdt_fun_cnt++;
        if (PauseCnt == 101)
        {
            printf("\nPress [ENTER] to continue...\n");
            getchar();
            PauseCnt = 0;
        }
    }
    //显示完最后一个函数
    DWORD fn_index = GetSSDTFunctionIndex(ntdlltxt);
    ssdt_func_ori_addr = GetFunctionOriginalAddress(fn_index);
    dcDirver.IoControl(dcDirver.m_hDriver, CTL_CODE_GEN(0x802), &fn_index, 4, &ssdt_func_addr, 8);
    ntdlltxt[0] = 'N'; ntdlltxt[1] = 't';
    printf("0x%-0.3X\t%llx  %llx  %s\n", fn_index, ssdt_func_addr, ssdt_func_ori_addr, ntdlltxt);

    //显示测试的hook函数

    ssdt_fun_cnt++;
    //显示ssdt表上的函数数
    printf("\nTotal of SSDT function: %ld\n", ssdt_fun_cnt);
    DeleteFileA("c:\\ntdll.txt");
}

//end********************AllSSDTFunction*************************

//start********************UnHook*************************

typedef struct _UNHOOK_SSDT64 {
    ULONGLONG Address;
    ULONGLONG id;
}UNHOOK_SSDT64, *PUNHOOK_SSDT64;
VOID UnhookSSDT()
{
    ULONG id;
    ULONG64 ssdt_func_ori_addr = 0;
    UNHOOK_SSDT64 data = { 0 };
    printf("Input SSDT function index which you want to unhook (like 0x29): ");
    scanf("0x%x", &id);
    ssdt_func_ori_addr = GetFunctionOriginalAddress(id);
    data.Address = ssdt_func_ori_addr;
    data.id = (ULONGLONG)id;
    dcDirver.IoControl(dcDirver.m_hDriver, CTL_CODE_GEN(0x800), &data, sizeof(UNHOOK_SSDT64), 0, 0);
}

//end********************UnHook*************************
int main()
{

    //安装驱动
    if (!InstallDriver("Dri.sys", "MyDriver", "MyDriver")) {
        printf("LoadDriver=false\n");
        return 0;
    }
    else {
        printf("LoadDriver=true\n");
    }

    getchar();

    GetNtosBase();
    GetNtosImageBase();
    GetKiServiceTable();
    PrintAllSSDTFunction();

    getchar();

    UnhookSSDT();

    getchar();
    getchar();
    //卸载驱动
    UnInstallDriver();
    printf("UninstallDriver=true\n");
    return 0;
}

执行结果1:hook掉关闭进程的函数,然后加载上面的驱动。

执行结果2 Hook SSDT保护计算器不被结束

执行结果3 执行UnHook 取消掉上面SSDT HOOK 的保护并且成功结束掉计算器

最后再声明一遍,所有的代码几乎都来源于学习资料,胡文亮前辈。还有很多细节为了测试方便我就随意的改了。很多地方发现内存泄漏以及无用代码。如果是用于实际项目,一定要弄清楚原理之后好好改改代码再用。

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章