win 64 Shadow ssdt hook


以下參考黑客防線2012合訂本 339頁 

//下午調代碼

搞了這個一天,總是藍屏,不斷檢查代碼,后來發現了很怪的現象.

自己寫的代碼不能讀取shadow ssdt的偏移內容,但是通過和調試作者的代碼輸出發現地址確實是一模一樣的,但是自己的讀不出來,而作者的能

讀出來,當直接使用windbg調試時也讀不出來. 后來將作者的代碼完全復制過來,發現能讀取了, ,但是又找不到原因, 只能等以后再看看了.

 

 

//晚上調代碼

晚上時還是想解決調用后來仔細再看看代碼發現自己的代碼調用sssdt hook時是在DriverEntry中的, 而shadow ssdt中的函數全是在有窗口程序時

調用時才有意義的. 而作者的代碼正是通過應用層mfc程序通過發送io控制碼通知驅動進行hook的,這時調用hook的代碼的當前進程實際上是mfc程序

,是有窗口的. 而DriverEntry是由system調用的,沒有窗口自然藍屏.

測試如下:

 

 

 

想通了之后修改代碼如下.

//hookSSSDT.h
#include <ntddk.h>
#pragma intrinsic(__readmsr)
/*
    流程:
    1.通過GetKeServiceDescriptorTableShadow64 獲取sssdt基址
    2.通過index獲取sssdt函數地址 ,通過GetSSSDTFuncCurAddr64函數實現
    3.寫好自己的假的對應的函數,並將跳板函數前若干字節修改為跳轉到假函數地址
    4.獲得跳板函數的sssdt偏移地址 並將其寫入對應的sssdt位置,這里已實現hook
    
    通過將原來的sssdt函數偏移寫回去即可

*/
typedef struct _SYSTEM_SERVICE_TABLE {
    PVOID          ServiceTableBase;
    PVOID          ServiceCounterTableBase;
    ULONGLONG      NumberOfServices;
    PVOID          ParamTableBase;
} SYSTEM_SERVICE_TABLE, *PSYSTEM_SERVICE_TABLE;
extern PSYSTEM_SERVICE_TABLE KeServiceDescriptorTableShadow;
typedef ULONG64(*NTUSERQUERYWINDOW)
(
    IN HWND        WindowHandle,
    IN ULONG64    TypeInformation
    );

typedef ULONG64(*NTUSERPOSTMESSAGE)
(
    HWND     hWnd,
    UINT     Msg,
    WPARAM     wParam,
    LPARAM     lParam
    );

//hook sssdt的變量
PSYSTEM_SERVICE_TABLE KeServiceDescriptorTableShadow = NULL;
ULONG64    ul64W32pServiceTable = 0;
ULONG64    IndexOfNtUserPostMessage = 0x100f;
ULONG64    IndexOfNtUserQueryWindow = 0x1010;
NTUSERQUERYWINDOW NtUserQueryWindow = NULL;
NTUSERPOSTMESSAGE NtUserPostMessage = NULL;
ULONG64    MyProcessId = 0;
//ULONG64    Win32kBase = 0;
ULONG64    IndexOfNtUserWindowFromPhysicalPoint = 0x1337;
ULONG64 AddressNtUserWindowFromPhysicalPoint = 0;



//聲明后就能用
NTSYSAPI NTSTATUS NTAPI ZwQuerySystemInformation
(
    IN ULONG    SystemInformationClass,
    OUT PVOID    SystemInformation,
    IN ULONG    Length,
    OUT PULONG    ReturnLength
);


ULONG64 FUCKNtUserPostMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);

VOID UNHOOK_SSSDT();
VOID HOOK_SSSDT();
VOID FuckFunc();
ULONGLONG GetSSSDTFuncCurAddr64(ULONG64 Index);
VOID ModifySSSDT(ULONG64 Index, ULONG64 Address);
ULONGLONG GetKeSeviceDescriptorTableShadow64();

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);
}


ULONG64 FUCKNtUserPostMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
    ULONG pid = NtUserQueryWindow(hWnd, 0);
    DbgPrint("called pid is %d\n", pid);
    if (pid == MyProcessId && PsGetCurrentProcessId() != (HANDLE)MyProcessId)
    {
        DbgPrint("Do not fuck with me!\n");
        return 0;
    }
    else
    {
        DbgPrint("OriNtUserPostMessage called!\n");
        return NtUserPostMessage(hWnd, Msg, wParam, lParam);
    }
}

VOID UNHOOK_SSSDT()
{
    ModifySSSDT(IndexOfNtUserPostMessage, (ULONG64)NtUserPostMessage);
    DbgPrint("UNHOOK_SSSDT OK!\n");
}

VOID HOOK_SSSDT()
{
    KIRQL irql;
    ULONG64 myfun;
    UCHAR jmp_code[] = "\xFF\x25\x00\x00\x00\x00\x90\x90\x90\x90\x90\x90\x90\x90";

    //代理函數地址
    myfun = (ULONGLONG)FUCKNtUserPostMessage;
    //填充 shellcode
    memcpy(jmp_code + 6, &myfun, 8);
    //x先寫入 准備的shellcode
    FuckFunc();
    irql = WPOFFx64();
    //再次寫入跳轉指令
    memcpy((PVOID)(AddressNtUserWindowFromPhysicalPoint + 4), jmp_code, 14);
    WPONx64(irql);
    //修改記錄原始地址的地方
    ModifySSSDT(IndexOfNtUserPostMessage, AddressNtUserWindowFromPhysicalPoint + 4);
    DbgPrint("HOOK_SSSDT OK!\n");
}

VOID FuckFunc()
{
    KIRQL irql;
    UCHAR fuckcode[] = "\x48\x33\xC0\xC3\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90";
    irql = WPOFFx64();
    memcpy((PVOID)AddressNtUserWindowFromPhysicalPoint, fuckcode, 23);
    WPONx64(irql);
}

ULONGLONG GetSSSDTFuncCurAddr64(ULONG64 Index)
{
    ULONGLONG                W32pServiceTable = 0, qwTemp = 0;
    LONG                     dwTemp = 0;
    PSYSTEM_SERVICE_TABLE    pWin32k;
    //DbgBreakPoint();
    pWin32k = (PSYSTEM_SERVICE_TABLE)((ULONG64)KeServiceDescriptorTableShadow + sizeof(SYSTEM_SERVICE_TABLE));
    DbgPrint("(ULONG64)KeServiceDescriptorTableShadow is %p\n", KeServiceDescriptorTableShadow);
    DbgPrint("pWin32k->ServiceTableBase is %p\n", pWin32k->ServiceTableBase);
    W32pServiceTable = (ULONGLONG)(pWin32k->ServiceTableBase);
    ul64W32pServiceTable = W32pServiceTable;
    qwTemp = W32pServiceTable + 4 * (Index - 0x1000);    //這里是獲得偏移地址的位置,要HOOK的話修改這里即可
    dwTemp = *(PLONG)qwTemp;
    dwTemp = dwTemp >> 4;
    qwTemp = W32pServiceTable + (LONG64)dwTemp;
    return qwTemp;
}
VOID ModifySSSDT(ULONG64 Index, ULONG64 Address)
{
    ULONGLONG W32pServiceTable = 0, qwTemp = 0;
    LONG dwTemp = 0;
    PSYSTEM_SERVICE_TABLE pWin32k;
    KIRQL irql;
    pWin32k = (PSYSTEM_SERVICE_TABLE)((ULONG64)KeServiceDescriptorTableShadow + sizeof(SYSTEM_SERVICE_TABLE)); //4*8
    W32pServiceTable = (ULONGLONG)(pWin32k->ServiceTableBase);
    qwTemp = W32pServiceTable + 4 * (Index - 0x1000); //獲取要被寫入的地址
    dwTemp = (LONG)(Address - W32pServiceTable);
    dwTemp = dwTemp << 4; //計算將寫入目標位置的內容
    DbgPrint("*(PLONG)qwTemp: %x,dwTemp: %x",*(PLONG)qwTemp,dwTemp);
    irql=WPOFFx64();
    *(PLONG)qwTemp = dwTemp;
    WPONx64(irql);
}

ULONGLONG GetKeSeviceDescriptorTableShadow64()
{
    PUCHAR startSearchAddress = (PUCHAR)__readmsr(0xC0000082);
    PUCHAR endSearchAddress = startSearchAddress + 0x500;
    PUCHAR i = 0;
    UCHAR b1 = 0, b2 = 0, b3 = 0;
    ULONG temp = 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 == 0x1d)
            {
                memcpy(&temp, i + 3, 4);
                addr = (ULONGLONG)temp + (ULONGLONG)i + 7;//加上指令長度
                KdPrint(("find ssdt is %p\n", addr));
                return addr;
            }
        }
    }
    KdPrint(("find ssdt error\n"));
    return 0;
}
//hs64.c
#include "header.h"
#include "hookSSSDT.h"

/*
    ssdt hook的一個流程:
    1.先調用GetKeSeviceDescriptorTable64給KeServiceDescriptorTable全局變量賦值,也就是找到
    ssdt 
    2. 調用GetSSDTFuncAddrById得到目標函數地址並保存到全局變量real_NtTerminateProcess
    3. 修改掉Fuck_KeBugCheckEx前12字節作為跳板
    4. 得到目標函數的偏移並保存到全局變量real_NtTerminateProcessOffset
    5. 計算KeBugCheckEx 函數的偏移並寫入到 ssdt表中 

    還原hook:
    1.直接將保存的目標函數偏移寫入到ssdt表中即可 
    這里無需還原KeBugCheckEx 函數,因為這里本來就不會執行到
*/

//DWORD isSHooked;

VOID DriverUnload(PDRIVER_OBJECT DriverObject)
{
    UNICODE_STRING DeviceName;
    UNICODE_STRING DosDeviceName;

    //刪除符號鏈接
    RtlInitUnicodeString(&DosDeviceName, LINKNAME);
    IoDeleteSymbolicLink(&DosDeviceName);

    if (DriverObject->DeviceObject != NULL)
        IoDeleteDevice(DriverObject->DeviceObject);

    KdPrint(("DriverUnload!\r\n"));
    //unHookSSDT64();
}
NTSTATUS IOControl(PDEVICE_OBJECT DeviceObject, PIRP pIrp)
{
    NTSTATUS status = STATUS_SUCCESS;
    ULONG uLen = 4;
    PIO_STACK_LOCATION ios = IoGetCurrentIrpStackLocation(pIrp);
    ULONG ccode = ios->Parameters.DeviceIoControl.IoControlCode;
    char result = 0;
    switch (ccode)
    {
    case IOCTL_HOOK:
        MyProcessId = PsGetCurrentProcessId();
        NtUserQueryWindow = (NTUSERQUERYWINDOW)GetSSSDTFuncCurAddr64(IndexOfNtUserQueryWindow);    DbgPrint("NtUserQueryWindow: %llx", (ULONG64)NtUserQueryWindow);
        NtUserPostMessage = (NTUSERPOSTMESSAGE)GetSSSDTFuncCurAddr64(IndexOfNtUserPostMessage);    DbgPrint("NtUserPostMessage: %llx", (ULONG64)NtUserPostMessage);
        AddressNtUserWindowFromPhysicalPoint = GetSSSDTFuncCurAddr64(IndexOfNtUserWindowFromPhysicalPoint);    DbgPrint("AddressNtUserWindowFromPhysicalPoint: %llx", (ULONG64)AddressNtUserWindowFromPhysicalPoint);
        DbgPrint("NtUserQueryWindow :%p\n", NtUserQueryWindow);
        DbgPrint("NtUserPostMessage :%p\n", NtUserPostMessage);
        DbgPrint("AddressNtUserWindowFromPhysicalPoint :%p\n", AddressNtUserWindowFromPhysicalPoint);
        HOOK_SSSDT();
        //isSHooked = 1;
        break;
    case IOCTL_UNHOOK:
        UNHOOK_SSSDT();
        //isSHooked = 0;
        break;
    default:
        break;
    }
    pIrp->IoStatus.Status = status;
    pIrp->IoStatus.Information = uLen;
    IoCompleteRequest(pIrp, IO_NO_INCREMENT);
    return pIrp->IoStatus.Status;
}
NTSTATUS IODispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
    Irp->IoStatus.Status = STATUS_SUCCESS;

    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return STATUS_SUCCESS;
}
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING theRegistryPath)
{
    UNICODE_STRING DeviceName;
    UNICODE_STRING DosDeviceName;
    NTSTATUS status;
    PVOID64 pvoid_driver_object;
    ULONG_PTR ul_driver_object;
    PDEVICE_OBJECT DriverDeviceObject;
    KdPrint(("Hello World WinX64\r\n"));


    //KeServiceDescriptorTable = GetKeSeviceDescriptorTable64();//1
    RtlInitUnicodeString(&DeviceName, DEVNAME);
    RtlInitUnicodeString(&DosDeviceName, LINKNAME);
    //througnAllServiceFuncAddr();
    //hookSSDT64();
    //初始化
    //initAll();
//    KeServiceDescriptorTableShadow = GetKeSeviceDescriptorTableShadow64(); //1
    //DbgPrint("param is %d\n", IndexOfNtUserPostMessage);
    //NtUserPostMessage = GetSSSDTFuncCurAddr64(IndexOfNtUserPostMessage);//備份被寫入函數地址
    //DbgPrint("NtUserPostMessage is %p\n", NtUserPostMessage);
    //NtUserQueryWindow = GetSSSDTFuncCurAddr64(IndexOfNtUserQueryWindow);
    //DbgPrint("NtUserPostMessage is %p\n", NtUserQueryWindow);
    //AddressNtUserWindowFromPhysicalPoint = GetSSSDTFuncCurAddr64(IndexOfNtUserWindowFromPhysicalPoint);

    KeServiceDescriptorTableShadow = (PSYSTEM_SERVICE_TABLE)GetKeSeviceDescriptorTableShadow64();
    
    status = IoCreateDevice(
        DriverObject,        // ptr to caller object
        0,                   // extension device allocated byte number
        &DeviceName,         // device name 
        FILE_DEVICE_UNKNOWN,
        0,                   // no special caracteristics
        FALSE,               // we can open many handles in same time
        &DriverDeviceObject); // [OUT] ptr to the created object
    if (!NT_SUCCESS(status)) {
        return STATUS_NO_SUCH_DEVICE;
    }
    status = IoCreateSymbolicLink(&DosDeviceName, &DeviceName);
    if (!NT_SUCCESS(status)) {
        IoDeleteDevice(DriverDeviceObject);
        return STATUS_NO_SUCH_DEVICE;
    }
    DriverObject->DriverUnload = DriverUnload;
    DriverObject->MajorFunction[IRP_MJ_CREATE] = IODispatch;
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = IODispatch;
    DriverObject->MajorFunction[IRP_MJ_READ] = IODispatch;
    DriverObject->MajorFunction[IRP_MJ_WRITE] = IODispatch;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IOControl;


    return STATUS_SUCCESS;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM