(52)系统调用阶段测试——基于 SSDT HOOK 的 FindWindowA 监视器
生活随笔
收集整理的這篇文章主要介紹了
(52)系统调用阶段测试——基于 SSDT HOOK 的 FindWindowA 监视器
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
一、項目說明
SSDT HOOK 內核函數我們已經會了,請看這兩篇博客:
SSDT HOOK 實現進程保護
補充內容:SSDT HOOK 模板
此次考試和 hook NtOpenProcess 或 NtTerminateProcess 有所區別,FindWindowA 是 GDI 函數,這意味著系統調用走的是第二張系統服務表:
win32k.sys 系統服務表可能會缺頁,要在驅動里訪問它,做法是創建一個已經調用過GDI函數的進程(不一定是窗口程序),然后通過 DeviceIoControl 函數和驅動通信,這樣執行驅動代碼時所屬進程已經給win32k.sys 系統服務表掛上物理頁了,訪問就不會藍屏。
其他就和之前的項目沒什么不同了,最大的坑點已經解決了。
oh, 還有一個注意點,我們hook的是 NtUserFindWindowEx 函數,因為 FindWindowA 在三環最終是調用這個函數的。系統調用號是 0x117A,注意,這個值當成下標用時,要把12位清零。
項目分為兩部分,驅動部分負責 SSDT HOOK,當有函數調用,就打印一下;3環監控程序通過 DeviceIoControl 命令驅動進行 SSDT HOOK,只有這樣,驅動訪問 win32k.sys 系統服務表時才不會藍屏。
二、項目代碼
驅動程序
#include <ntddk.h> #include <ntstatus.h>/************************************************************************/ /* 宏定義 */ /************************************************************************/// 系統調用號 #define NTUSERFINDWINDOWEX_SERVICE (0x117A & 0x0FFF)// 驅動通信相關 #define DEVICE_NAME L"\\Device\\HbgHookDev" #define DRIVER_LINK L"\\??\\FindWindowAWatcherLnk" #define OP_HOOK CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) #define OP_UNHOOK CTL_CODE(FILE_DEVICE_UNKNOWN,0x801,METHOD_BUFFERED,FILE_ANY_ACCESS)/************************************************************************/ /* 類型聲明 */ /************************************************************************/// 系統服務表 typedef struct _KSYSTEM_SERVICE_TABLE {PULONG ServiceTableBase; // 函數地址表PULONG ServiceCounterTableBase; // SSDT 函數被調用的次數ULONG NumberOfService; // 函數個數PULONG ParamTableBase; // 函數參數表 } KSYSTEM_SERVICE_TABLE, *PKSYSTEM_SERVICE_TABLE;// SSDT表 typedef struct _KSERVICE_TABLE_DESCRIPTOR {KSYSTEM_SERVICE_TABLE ntoskrnl; // 內核函數KSYSTEM_SERVICE_TABLE win32k; // win32k.sys 函數KSYSTEM_SERVICE_TABLE unUsed1;KSYSTEM_SERVICE_TABLE unUsed2; } KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR;// NTOPENPROCESS typedef NTSTATUS (*NTUSERFINDWINDOWEX) (ULONG p1,ULONG p2,ULONG lpClassName,ULONG lpWindowName,ULONG p5);/************************************************************************/ /* 函數聲明 */ /************************************************************************/VOID DriverUnload(PDRIVER_OBJECT pDriver); NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING reg_path); VOID PageProtectOff(); VOID PageProtectOn(); VOID HookNtUserFindWindowEx(); VOID UnHookNtUserFindWindowEx(); NTSTATUS HbgNtUserFindWindowEx(ULONG p1,ULONG p2,ULONG lpClassName,ULONG lpWindowName,ULONG p5); NTSTATUS IrpCreateProc(PDEVICE_OBJECT pDevObj, PIRP pIrp); NTSTATUS IrpCloseProc(PDEVICE_OBJECT pDevObj, PIRP pIrp); NTSTATUS IrpDeviceControlProc(PDEVICE_OBJECT pDevObj, PIRP pIrp); VOID PrintCurrentProcessInfo();/************************************************************************/ /* 全局變量 */ /************************************************************************/extern PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable; // ntoskrnl.exe 導出的全局變量 PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTableShadow; ULONG uOldNtUserFindWindowEx; // 舊的函數地址/************************************************************************/ /* 函數定義 */ /************************************************************************/// 驅動入口 NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING reg_path) {NTSTATUS status;ULONG uIndex = 0;PDEVICE_OBJECT pDeviceObj = NULL; // 設備對象指針UNICODE_STRING DeviceName; // 設備名,0環用UNICODE_STRING SymbolicLinkName; // 符號鏈接名,3環用KeServiceDescriptorTableShadow = (PKSERVICE_TABLE_DESCRIPTOR)((ULONG)KeServiceDescriptorTable - 0x40);// 創建設備名稱RtlInitUnicodeString(&DeviceName,DEVICE_NAME);// 創建設備status = IoCreateDevice(pDriver,0,&DeviceName,FILE_DEVICE_UNKNOWN,FILE_DEVICE_SECURE_OPEN,FALSE,&pDeviceObj);if (status != STATUS_SUCCESS){IoDeleteDevice(pDeviceObj);DbgPrint("創建設備失敗.\n");return status;}//DbgPrint("創建設備成功.\n");// 設置交互數據的方式pDeviceObj->Flags |= DO_BUFFERED_IO;// 創建符號鏈接RtlInitUnicodeString(&SymbolicLinkName, DRIVER_LINK);IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName);// 設置分發函數pDriver->MajorFunction[IRP_MJ_CREATE] = IrpCreateProc;pDriver->MajorFunction[IRP_MJ_CLOSE] = IrpCloseProc;pDriver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IrpDeviceControlProc;pDriver->DriverUnload = DriverUnload;return STATUS_SUCCESS; }// 卸載驅動 VOID DriverUnload(PDRIVER_OBJECT pDriver) {UNICODE_STRING SymbolicLinkName;// 刪除符號鏈接,刪除設備RtlInitUnicodeString(&SymbolicLinkName, DRIVER_LINK);IoDeleteSymbolicLink(&SymbolicLinkName);IoDeleteDevice(pDriver->DeviceObject);DbgPrint("Driver unloaded.\n"); }// 關閉頁保護 VOID PageProtectOff() {__asm{cli; // 關閉中斷mov eax, cr0;and eax, not 0x10000; // WP位置0mov cr0, eax;} }// 開啟頁保護 VOID PageProtectOn() {__asm{mov eax, cr0;or eax, 0x10000; // WP位置1mov cr0, eax;sti; // 恢復中斷} }// HOOK NtUserFindWindowEx VOID HookNtUserFindWindowEx() {PageProtectOff();uOldNtUserFindWindowEx = KeServiceDescriptorTableShadow->win32k.ServiceTableBase[NTUSERFINDWINDOWEX_SERVICE];KeServiceDescriptorTableShadow->win32k.ServiceTableBase[NTUSERFINDWINDOWEX_SERVICE] = (ULONG)HbgNtUserFindWindowEx;PageProtectOn();DbgPrint("Hooked: %p -> %p\n", uOldNtUserFindWindowEx, KeServiceDescriptorTableShadow->win32k.ServiceTableBase[NTUSERFINDWINDOWEX_SERVICE]); }// UnHOOK NtUserFindWindowEx VOID UnHookNtUserFindWindowEx() {PageProtectOff();KeServiceDescriptorTableShadow->win32k.ServiceTableBase[NTUSERFINDWINDOWEX_SERVICE] = uOldNtUserFindWindowEx;PageProtectOn();DbgPrint("UnHooked: %p\n", KeServiceDescriptorTableShadow->win32k.ServiceTableBase[NTUSERFINDWINDOWEX_SERVICE]); }// 被修改的 NtUserFindWindowEx 函數,簡單打印參數 NTSTATUS HbgNtUserFindWindowEx(ULONG p1,ULONG p2,ULONG lpClassName,ULONG lpWindowName,ULONG p5) {DbgPrint("NtUserFindWindowEx(%x, %x, %x, %x, %x)\n", p1,p2,lpClassName,lpWindowName,p5);return ((NTUSERFINDWINDOWEX)uOldNtUserFindWindowEx)(p1,p2,lpClassName,lpWindowName,p5); }// IRP_MJ_CREATE 處理函數 NTSTATUS IrpCreateProc(PDEVICE_OBJECT pDevObj, PIRP pIrp) {//DbgPrint("應用層連接設備.\n");// 返回狀態如果不設置,Ring3返回值是失敗pIrp->IoStatus.Status = STATUS_SUCCESS;pIrp->IoStatus.Information = 0;IoCompleteRequest(pIrp, IO_NO_INCREMENT);return STATUS_SUCCESS; }// IRP_MJ_CLOSE 處理函數 NTSTATUS IrpCloseProc(PDEVICE_OBJECT pDevObj, PIRP pIrp) {//DbgPrint("應用層斷開連接設備.\n");// 返回狀態如果不設置,Ring3返回值是失敗pIrp->IoStatus.Status = STATUS_SUCCESS;pIrp->IoStatus.Information = 0;IoCompleteRequest(pIrp, IO_NO_INCREMENT);return STATUS_SUCCESS; }// IRP_MJ_DEVICE_CONTROL 處理函數 NTSTATUS IrpDeviceControlProc(PDEVICE_OBJECT pDevObj, PIRP pIrp) {NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;PIO_STACK_LOCATION pIrpStack;ULONG uIoControlCode;PVOID pIoBuffer;ULONG uInLength;ULONG uOutLength;// 獲取IRP數據pIrpStack = IoGetCurrentIrpStackLocation(pIrp);// 獲取控制碼uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;// 獲取緩沖區地址(輸入輸出是同一個)pIoBuffer = pIrp->AssociatedIrp.SystemBuffer;// Ring3 發送數據的長度uInLength = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;// Ring0 發送數據的長度uOutLength = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;switch (uIoControlCode){case OP_HOOK:{HookNtUserFindWindowEx();//DbgPrint("HOOK成功.\n");//PrintCurrentProcessInfo();status = STATUS_SUCCESS;pIrp->IoStatus.Information = 0; // 返回給3環的數據量break;}case OP_UNHOOK:{UnHookNtUserFindWindowEx();//DbgPrint("UnHOOK成功.\n");//PrintCurrentProcessInfo();status = STATUS_SUCCESS;pIrp->IoStatus.Information = 0; // 返回給3環的數據量break;}}// 返回狀態如果不設置,Ring3返回值是失敗pIrp->IoStatus.Status = status;IoCompleteRequest(pIrp, IO_NO_INCREMENT);return STATUS_SUCCESS; }// 打印進程鏡像名和PID VOID PrintCurrentProcessInfo() {PEPROCESS pEprocess = NULL;PCHAR ImageFileName;ULONG pid;__asm{mov eax, fs:[0x124];mov eax, [eax + 0x220];mov pEprocess, eax;mov eax, [eax + 0x84];mov pid, eax;}ImageFileName = (PCHAR)pEprocess + 0x174;DbgPrint("pid: %x, ImageFileName:%s\n",pid, ImageFileName); }3環監控程序
// DriverLoader.cpp : 定義控制臺應用程序的入口點。 //#include "stdafx.h" #include <Windows.h>#define DRIVER_NAME L"FindWindowAWatcher" #define DRIVER_PATH L"FindWindowAWatcher.sys" #define DRIVER_LINK L"\\\\.\\FindWindowAWatcherLnk" #define OP_HOOK CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) #define OP_UNHOOK CTL_CODE(FILE_DEVICE_UNKNOWN,0x801,METHOD_BUFFERED,FILE_ANY_ACCESS)BOOL LoadDriver(PCWSTR lpszDriverName, PCWSTR lpszDriverPath); void UnLoadDriver(PCWSTR lpszDriverName); BOOL Hook(); BOOL UnHook();int _tmain(int argc, _TCHAR* argv[]) {HWND hwnd = FindWindowA(NULL,"notepad.exe"); // win32k.sys系統服務表掛物理頁,沒有這行可能會藍屏LoadDriver(DRIVER_NAME, DRIVER_PATH);Hook();getchar();UnHook();UnLoadDriver(DRIVER_NAME);getchar();return 0; }// 加載驅動 BOOL LoadDriver(PCWSTR lpszDriverName, PCWSTR lpszDriverPath) {// 獲取驅動完整路徑WCHAR szDriverFullPath[MAX_PATH] = { 0 };GetFullPathNameW(lpszDriverPath,MAX_PATH,szDriverFullPath,NULL);//printf("%s\n", szDriverFullPath);// 打開服務控制管理器SC_HANDLE hServiceMgr = NULL; // SCM管理器句柄 hServiceMgr = OpenSCManagerW(NULL,NULL,SC_MANAGER_ALL_ACCESS);if (NULL == hServiceMgr){printf("OpenSCManagerW 失敗, %d\n", GetLastError());return FALSE;}//printf("打開服務控制管理器成功.\n");// 創建驅動服務SC_HANDLE hServiceDDK = NULL; // NT驅動程序服務句柄hServiceDDK = CreateServiceW(hServiceMgr,lpszDriverName,lpszDriverName,SERVICE_ALL_ACCESS,SERVICE_KERNEL_DRIVER,SERVICE_DEMAND_START,SERVICE_ERROR_IGNORE,szDriverFullPath,NULL,NULL,NULL,NULL,NULL);if (NULL == hServiceDDK){DWORD dwErr = GetLastError();if (dwErr != ERROR_IO_PENDING && dwErr != ERROR_SERVICE_EXISTS){printf("創建驅動服務失敗, %d\n", dwErr);return FALSE;}}//printf("創建驅動服務成功.\n");// 驅動服務已經創建,打開服務hServiceDDK = OpenServiceW(hServiceMgr,lpszDriverName,SERVICE_ALL_ACCESS);if (!StartService(hServiceDDK, NULL, NULL)){DWORD dwErr = GetLastError();if (dwErr != ERROR_SERVICE_ALREADY_RUNNING){printf("運行驅動服務失敗, %d\n", dwErr);return FALSE;}}//printf("運行驅動服務成功.\n");if (hServiceDDK){CloseServiceHandle(hServiceDDK);}if (hServiceMgr){CloseServiceHandle(hServiceMgr);}return TRUE; }// 卸載驅動 void UnLoadDriver(PCWSTR lpszDriverName) {SC_HANDLE hServiceMgr = OpenSCManagerW(0,0,SC_MANAGER_ALL_ACCESS);SC_HANDLE hServiceDDK = OpenServiceW(hServiceMgr,lpszDriverName,SERVICE_ALL_ACCESS);SERVICE_STATUS SvrStatus;ControlService(hServiceDDK,SERVICE_CONTROL_STOP,&SvrStatus);DeleteService(hServiceDDK);if (hServiceDDK){CloseServiceHandle(hServiceDDK);}if (hServiceMgr){CloseServiceHandle(hServiceMgr);} }BOOL Hook() {HANDLE hDevice = CreateFileW(DRIVER_LINK, GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);DWORD bRet;if (hDevice == INVALID_HANDLE_VALUE){printf("HOOK失敗.\n");return FALSE;}DeviceIoControl(hDevice,OP_HOOK,NULL,0,NULL,0,&bRet,NULL);// 關閉設備CloseHandle(hDevice);return TRUE; }BOOL UnHook() {HANDLE hDevice = CreateFileW(DRIVER_LINK, GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);DWORD bRet;if (hDevice == INVALID_HANDLE_VALUE){printf("UnHook失敗.\n");return FALSE;}DeviceIoControl(hDevice,OP_UNHOOK,NULL,0,NULL,0,&bRet,NULL);// 關閉設備CloseHandle(hDevice);return TRUE; }執行結果:
總結
以上是生活随笔為你收集整理的(52)系统调用阶段测试——基于 SSDT HOOK 的 FindWindowA 监视器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (51)SSDT HOOK 实现进程保护
- 下一篇: (53)进程结构体EPROCESS,擦除