Win64 驱动内核编程-28.枚举消息钩子
枚舉消息鉤子
?簡單粘貼點百度的解釋,科普下消息鉤子:
鉤子是WINDOWS中消息處理機制的一個要點,通過安裝各種鉤子,應用程序能夠設置相應的子例程來監視系統里的消息傳遞以及在這些消息到達目標窗口程序之前處理它們。?鉤子的種類很多,每種鉤子可以截獲并處理相應的消息,如鍵盤鉤子可以截獲鍵盤消息,鼠標鉤子可以截獲鼠標消息,外殼鉤子可以截獲啟動和關閉應用程序的消息,日志鉤子可以監視和記錄輸入事件。
?
鉤子的類型:
(1)?鍵盤鉤子和低級鍵盤鉤子可以監視各種鍵盤消息。
(2)?鼠標鉤子和低級鼠標鉤子可以監視各種鼠標消息。
(3)?外殼鉤子可以監視各種?Shell?事件消息。比如啟動和關閉應用程序。
(4)?日志鉤子可以記錄從系統消息隊列中取出的各種事件消息。
(5)?窗口過程鉤子監視所有從系統消息隊列發往目標窗口的消息。
此外,還有一些特定事件的鉤子提供給我們使用,不一一列舉。
?
常用的?Hook?類型:
1、WH_CALLWNDPROC?和?WH_CALLWNDPROCRET?Hooks
WH_CALLWNDPROC?和?WH_CALLWNDPROCRET?Hooks?使你可以監視發送到窗口過程的消息。系統在消息發送到接
收窗口過程之前調用?WH_CALLWNDPROC?Hook?子程,并且在窗口過程處理完消息之后調用?WH_CALLWNDPRO
CRET?Hook?子程。WH_CALLWNDPROCRET?Hook?傳遞指針到?CWPRETSTRUCT?結構,再傳遞到?Hook?子程。
CWPRETSTRUCT?結構包含了來自處理消息的窗口過程的返回值,同樣也包括了與這個消息關聯的消息參數。
2、WH_CBT?Hook
在以下事件之前,系統都會調用?WH_CBT?Hook?子程,這些事件包括:
1.?激活,建立,銷毀,最小化,最大化,移動,改變尺寸等窗口事件;
2.?完成系統指令;
3.?來自系統消息隊列中的移動鼠標,鍵盤事件;
4.?設置輸入焦點事件;
5.?同步系統消息隊列事件。
Hook?子程的返回值確定系統是否允許或者防止這些操作中的一個。
3、WH_DEBUG?Hook
在系統調用系統中與其他?Hook?關聯的?Hook?子程之前,系統會調用?WH_DEBUG?Hook?子程。你可以使用這個
Hook?來決定是否允許系統調用與其他?Hook?關聯的?Hook?子程。
4、WH_FOREGROUNDIDLE?Hook
當應用程序的前臺線程處于空閑狀態時,可以使用?WH_FOREGROUNDIDLE?Hook?執行低優先級的任務。當應用
程序的前臺線程大概要變成空閑狀態時,系統就會調用?WH_FOREGROUNDIDLE?Hook?子程。
5、WH_GETMESSAGE?Hook
應用程序使用?WH_GETMESSAGE?Hook?來監視從?GetMessage?或?PeekMessage?函數返回的消息。你可以使用
WH_GETMESSAGE?Hook?去監視鼠標和鍵盤輸入,以及其他發送到消息隊列中的消息。
6、WH_JOURNALPLAYBACK?Hook
????WH_JOURNALPLAYBACK?Hook?使應用程序可以插入消息到系統消息隊列。可以使用這個?Hook?回放通過使用WH_JOURNALRECORD?Hook?記錄下來的連續的鼠標和鍵盤事件。只要?WH_JOURNALPLAYBACK?Hook?已經安裝,正常的鼠標和鍵盤事件就是無效的。WH_JOURNALPLAYBACK?Hook?是全局?Hook,它不能象線程特定?Hook?一樣
使用。WH_JOURNALPLAYBACK?Hook?返回超時值,這個值告訴系統在處理來自回放?Hook?當前消息之前需要等待多長時間(毫秒)。這就使?Hook?可以控制實時事件的回放。WH_JOURNALPLAYBACK?是?system-wide?localhooks,它們不會被注射到任何進程地址空間。(估計按鍵精靈是用這個?hook?做的)
7、WH_JOURNALRECORD?Hook
WH_JOURNALRECORD?Hook?用來監視和記錄輸入事件。典型的,可以使用這個?Hook?記錄連續的鼠標和鍵盤事件,然后通過使用?WH_JOURNALPLAYBACK?Hook?來回放。WH_JOURNALRECORD?Hook?是全局?Hook,它不能象線程特定?Hook?一樣使用。WH_JOURNALRECORD?是?system-wide?local?hooks,它們不會被注射到任何進程地址空間。
?
枚舉內核消息鉤子??
????枚舉消息鉤子的總體思路。首先獲得名為?gSharedInfo的全局變量的地址(此變量在?user32.dll?里被導出),它的值其實是一個內核結構體?win32k!tagsharedinfo?的地址:
接下來?tagSERVERINFO.cHandleEntries?的值,這個值記錄了當前消息鉤子的數目(記為?count):
????然后讀取?gSharedInfo+8?的值,獲得?aheList?的值(記為?phe),此值為?首個
HANDLEENTRY?結構體的地址:
????接下來,從?phe?首地址開始,獲得【count-1】個的?HANDLEENTRY?結構體的指針,HANDLEENTRY.phead?記錄的值指向一個?HEAD?結構體,HEAD?結構體才記錄了
每個消息鉤子的具體信息。當然也不是每個?HANDLEENTRY?都是消息鉤子,只有當
HANDLEENTRY.bType?為?5?時才是消息鉤子。
?
然后就是把資料上的那個寫的比較精簡的函數拿出來,枚舉消息鉤子:
注意這個函數實在R3里面:
void EnumMsgHook() { int i=0; UINT64 pgSharedInfo=0; pgSharedInfo = (UINT64)GetProcAddress(GetModuleHandleA("user32.dll"), "gSharedInfo"); UINT64 phe = GetQWORD(pgSharedInfo+8); UINT64 count = GetQWORD(GetQWORD(pgSharedInfo)+8); HANDLEENTRY heStruct={0}; HOOK_INFO Hook={0}; for(i=0;i<count;i++) { memcpy(&heStruct,(PVOID)(phe + i*sizeof(HANDLEENTRY)),sizeof(HANDLEENTRY)); if(heStruct.bType==5) { RKM(heStruct.phead,&Hook,sizeof(HOOK_INFO)); printf("hHandle: 0x%llx\n",Hook.hHandle); printf("iHookFlags: %s\n",GetHookFlagString(Hook.iHookFlags)); printf("iHookType: %s\n",GetHookType(Hook.iHookType)); printf("OffPfn: 0x%llx\n",Hook.OffPfn); printf("ETHREAD: 0x%llx\n",GetQWORD((UINT64)(Hook.Win32Thread))); printf("ProcessName: %s\n\n",GetPNbyET(GetQWORD((UINT64)(Hook.Win32Thread)))); } } }?接下來是驅動部分代碼,感覺里面的那些讀寫內存什么的寫的比較歸整(來源于資料,胡文亮),這里也整理下方便以后使用:
先是內存拷貝:
BOOLEAN VxkCopyMemory( PVOID pDestination, PVOID pSourceAddress, SIZE_T SizeOfCopy ) {PMDL pMdl = NULL;PVOID pSafeAddress = NULL;pMdl = IoAllocateMdl( pSourceAddress, (ULONG)SizeOfCopy, FALSE, FALSE, NULL );if( !pMdl ) return FALSE;__try{MmProbeAndLockPages( pMdl, KernelMode, IoReadAccess );}__except(EXCEPTION_EXECUTE_HANDLER){IoFreeMdl( pMdl );return FALSE;}pSafeAddress = MmGetSystemAddressForMdlSafe( pMdl, NormalPagePriority );if( !pSafeAddress ) return FALSE;RtlCopyMemory( pDestination, pSafeAddress, SizeOfCopy );MmUnlockPages( pMdl );IoFreeMdl( pMdl );return TRUE; } ULONG64 rwkm_adr=0, rwkm_len=0;然后是內存讀寫---R3
DWORD CTL_CODE_GEN(DWORD lngFunction) { return (FILE_DEVICE_UNKNOWN * 65536) | (FILE_ANY_ACCESS * 16384) | (lngFunction * 4) | METHOD_BUFFERED; }BOOL 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); }void RKM(UINT64 Address, PVOID Buffer, SIZE_T Length) { IoControl(dcDirver.m_hDriver, CTL_CODE_GEN(0x809), &Address, 8, NULL, 0); //address IoControl(dcDirver.m_hDriver, CTL_CODE_GEN(0x80A), &Length, 8, NULL, 0); //length IoControl(dcDirver.m_hDriver, CTL_CODE_GEN(0x804), NULL, 0, Buffer, Length); //get buffer }void WKM(UINT64 Address, PVOID Buffer, SIZE_T Length) { IoControl(dcDirver.m_hDriver, CTL_CODE_GEN(0x809), &Address, 8, NULL, 0); //address IoControl(dcDirver.m_hDriver, CTL_CODE_GEN(0x80A), &Length, 8, NULL, 0); //length IoControl(dcDirver.m_hDriver, CTL_CODE_GEN(0x805), Buffer, Length, NULL, 0); //set buffer }UINT64 GetQWORD(UINT64 address) { UINT64 y = 0; RKM(address, &y, 8); return y; }UINT32 GetDWORD(UINT64 address) { UINT32 y = 0; RKM(address, &y, 4); return y; }PUCHAR GetPNbyET(UINT64 ethread) { PUCHAR y = (PUCHAR)malloc(16); IoControl(dcDirver.m_hDriver, CTL_CODE_GEN(0x7FF), eread, 8, y, 16); return y; }然后是內存讀寫---R0
#define IOCTL_READ_KRNL_MM CTL_CODE(FILE_DEVICE_UNKNOWN, 0x804, METHOD_BUFFERED, FILE_ANY_ACCESS) //read kernel #define IOCTL_MODIFY_KN_MM CTL_CODE(FILE_DEVICE_UNKNOWN, 0x805, METHOD_BUFFERED, FILE_ANY_ACCESS) //write kernel #define IOCTL_SET_RWKM_ADR CTL_CODE(FILE_DEVICE_UNKNOWN, 0x809, METHOD_BUFFERED, FILE_ANY_ACCESS) //set address #define IOCTL_SET_RWKM_LEN CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80A, METHOD_BUFFERED, FILE_ANY_ACCESS) //set length #define IOCTL_GET_PN_BY_ET CTL_CODE(FILE_DEVICE_UNKNOWN, 0x7FF, METHOD_BUFFERED, FILE_ANY_ACCESS) //set lengthNTSTATUS 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_SET_RWKM_ADR: { rwkm_adr=*(UINT64 *)pIoBuffer; DbgPrint("rwkm_adr: %lld\n",rwkm_adr); status = STATUS_SUCCESS; break; } case IOCTL_SET_RWKM_LEN: { rwkm_len=*(UINT64 *)pIoBuffer; DbgPrint("rwkm_len: %lld\n",rwkm_len); status = STATUS_SUCCESS; break; } case IOCTL_READ_KRNL_MM: { VxkCopyMemory(pIoBuffer,(PVOID)rwkm_adr,(SIZE_T)rwkm_len); status = STATUS_SUCCESS; break; } case IOCTL_MODIFY_KN_MM: { VxkCopyMemory((PVOID)rwkm_adr,pIoBuffer,(SIZE_T)rwkm_len); status = STATUS_SUCCESS; break; } case IOCTL_GET_PN_BY_ET: { PETHREAD et; PEPROCESS ep; PUCHAR pn; et=*(PETHREAD *)pIoBuffer; ep=IoThreadToProcess(et); pn=PsGetProcessImageFileName(ep); memcpy(pIoBuffer,pn,16); status = STATUS_SUCCESS; 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; }執行結果:
下面是備份上資料里的整體代碼(部分已經被我改過)
MyDriver.h-----r0
#include <ntddk.h> #define dprintf DbgPrint #define DEVICE_NAME L"\\Device\\MyDriver" #define LINK_NAME L"\\DosDevices\\MyDriver" #define LINK_GLOBAL_NAME L"\\DosDevices\\Global\\MyDriver"#define IOCTL_READ_KRNL_MM CTL_CODE(FILE_DEVICE_UNKNOWN, 0x804, METHOD_BUFFERED, FILE_ANY_ACCESS) //read kernel #define IOCTL_MODIFY_KN_MM CTL_CODE(FILE_DEVICE_UNKNOWN, 0x805, METHOD_BUFFERED, FILE_ANY_ACCESS) //write kernel #define IOCTL_SET_RWKM_ADR CTL_CODE(FILE_DEVICE_UNKNOWN, 0x809, METHOD_BUFFERED, FILE_ANY_ACCESS) //set address #define IOCTL_SET_RWKM_LEN CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80A, METHOD_BUFFERED, FILE_ANY_ACCESS) //set length #define IOCTL_GET_PN_BY_ET CTL_CODE(FILE_DEVICE_UNKNOWN, 0x7FF, METHOD_BUFFERED, FILE_ANY_ACCESS) //set lengthMyDriver.c-----r0 #include <ntddk.h> #include "MyDriver.h" #include "rwkm.h"NTKERNELAPI PUCHAR PsGetProcessImageFileName( IN PEPROCESS Process ); NTKERNELAPI PEPROCESS IoThreadToProcess( IN PETHREAD Thread );VOID DriverUnload(PDRIVER_OBJECT pDriverObj) { UNICODE_STRING strLink; RtlInitUnicodeString(&strLink, LINK_NAME); IoDeleteSymbolicLink(&strLink); IoDeleteDevice(pDriverObj->DeviceObject); }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_SET_RWKM_ADR: { rwkm_adr=*(UINT64 *)pIoBuffer; DbgPrint("rwkm_adr: %lld\n",rwkm_adr); status = STATUS_SUCCESS; break; } case IOCTL_SET_RWKM_LEN: { rwkm_len=*(UINT64 *)pIoBuffer; DbgPrint("rwkm_len: %lld\n",rwkm_len); status = STATUS_SUCCESS; break; } case IOCTL_READ_KRNL_MM: { VxkCopyMemory(pIoBuffer,(PVOID)rwkm_adr,(SIZE_T)rwkm_len); status = STATUS_SUCCESS; break; } case IOCTL_MODIFY_KN_MM: { VxkCopyMemory((PVOID)rwkm_adr,pIoBuffer,(SIZE_T)rwkm_len); status = STATUS_SUCCESS; break; } case IOCTL_GET_PN_BY_ET: { PETHREAD et; PEPROCESS ep; PUCHAR pn; et=*(PETHREAD *)pIoBuffer; ep=IoThreadToProcess(et); pn=PsGetProcessImageFileName(ep); memcpy(pIoBuffer,pn,16); status = STATUS_SUCCESS; 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) { 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; }
Rwkm.h-----r0
BOOLEAN VxkCopyMemory( PVOID pDestination, PVOID pSourceAddress, SIZE_T SizeOfCopy ) {PMDL pMdl = NULL;PVOID pSafeAddress = NULL;pMdl = IoAllocateMdl( pSourceAddress, (ULONG)SizeOfCopy, FALSE, FALSE, NULL );if( !pMdl ) return FALSE;__try{MmProbeAndLockPages( pMdl, KernelMode, IoReadAccess );}__except(EXCEPTION_EXECUTE_HANDLER){IoFreeMdl( pMdl );return FALSE;}pSafeAddress = MmGetSystemAddressForMdlSafe( pMdl, NormalPagePriority );if( !pSafeAddress ) return FALSE;RtlCopyMemory( pDestination, pSafeAddress, SizeOfCopy );MmUnlockPages( pMdl );IoFreeMdl( pMdl );return TRUE; }ULONG64 rwkm_adr=0, rwkm_len=0;ScmDrvCtrl.h----r3 /*============================ Drvier Control Class (SCM way) ============================*/#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 = NULL; //m_hService = OpenServiceA(m_hSCManager, pServiceName, SERVICE_ALL_ACCESS); if (m_hService != NULL) { return TRUE; }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; }InstallDri.cpp----r3
?
#include "stdafx.h" #include <string> #include <stdio.h> #include <Windows.h> #include "ScmDrvCtrl.h" #include <iostream>#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*************************DWORD CTL_CODE_GEN(DWORD lngFunction) { return (FILE_DEVICE_UNKNOWN * 65536) | (FILE_ANY_ACCESS * 16384) | (lngFunction * 4) | METHOD_BUFFERED; }BOOL 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); }void RKM(UINT64 Address, PVOID Buffer, SIZE_T Length) { IoControl(dcDirver.m_hDriver, CTL_CODE_GEN(0x809), &Address, 8, NULL, 0); //address IoControl(dcDirver.m_hDriver, CTL_CODE_GEN(0x80A), &Length, 8, NULL, 0); //length IoControl(dcDirver.m_hDriver, CTL_CODE_GEN(0x804), NULL, 0, Buffer, Length); //get buffer }void WKM(UINT64 Address, PVOID Buffer, SIZE_T Length) { IoControl(dcDirver.m_hDriver, CTL_CODE_GEN(0x809), &Address, 8, NULL, 0); //address IoControl(dcDirver.m_hDriver, CTL_CODE_GEN(0x80A), &Length, 8, NULL, 0); //length IoControl(dcDirver.m_hDriver, CTL_CODE_GEN(0x805), Buffer, Length, NULL, 0); //set buffer }UINT64 GetQWORD(UINT64 address) { UINT64 y = 0; RKM(address, &y, 8); return y; }UINT32 GetDWORD(UINT64 address) { UINT32 y = 0; RKM(address, &y, 4); return y; }PUCHAR GetPNbyET(UINT64 ethread) { PUCHAR y = (PUCHAR)malloc(16); IoControl(dcDirver.m_hDriver, CTL_CODE_GEN(0x7FF), eread, 8, y, 16); return y; }/* lkd> dt win32k!tagsharedinfo +0x000 psi : Ptr64 tagSERVERINFO +0x008 aheList : Ptr64 _HANDLEENTRY +0x010 HeEntrySize : Uint4B +0x018 pDispInfo : Ptr64 tagDISPLAYINFO +0x020 ulSharedDelta : Uint8B +0x028 awmControl : [31] _WNDMSG +0x218 DefWindowMsgs : _WNDMSG +0x228 DefWindowSpecMsgs : _WNDMSGlkd> dt win32k!tagSERVERINFO +0x000 dwSRVIFlags : Uint4B +0x008 cHandleEntries : Uint8B +0x010 mpFnidPfn : [32] Ptr64 int64 +0x110 aStoCidPfn : [7] Ptr64 int64 [省略......] *//*win32k!_HANDLEENTRY +0x000 phead : Ptr64 _HEAD +0x008 pOwner : Ptr64 Void +0x010 bType : UChar +0x011 bFlags : UChar +0x012 wUniq : Uint2B*/typedef struct _HANDLEENTRY { UINT64 phead; UINT64 pOwner; UCHAR bType; UCHAR bFlags; USHORT wUniq; }HANDLEENTRY, *PHANDLEENTRY;/* lkd> dt win32k!taghook +0x000 head : _THRDESKHEAD +0x028 phkNext : Ptr64 tagHOOK +0x030 iHook : Int4B +0x038 offPfn : Uint8B +0x040 flags : Uint4B +0x044 ihmod : Int4B +0x048 ptiHooked : Ptr64 tagTHREADINFO +0x050 rpdesk : Ptr64 tagDESKTOP +0x058 nTimeout : Pos 0, 7 Bits +0x058 fLastHookHung : Pos 7, 1 Bit lkd> dt_THRDESKHEAD win32k!_THRDESKHEAD +0x000 h : Ptr64 Void +0x008 cLockObj : Uint4B +0x010 pti : Ptr64 tagTHREADINFO +0x018 rpdesk : Ptr64 tagDESKTOP +0x020 pSelf : Ptr64 UChar */typedef struct _HOOK_INFO { HANDLE hHandle; //鉤子的句柄 句柄是全局的 可以UnhookWindowsHookEx 把鉤子卸掉 int Unknown1; PVOID Win32Thread; //一個指向 win32k!_W32THREAD 結構體的指針 PVOID Unknown2; PVOID SelfHook; //指向結構體的首地址 PVOID NextHook; //指向下一個鉤子結構體 int iHookType; //鉤子的類型, winuser.h 中有定義 PVOID OffPfn; //鉤子函數的地址偏移,相對于所在模塊的偏移 int iHookFlags; int iMod; //鉤子函數做在模塊的索引號碼,通過查詢 WowProcess 結構可以得到模塊的基地址。 PVOID Win32ThreadHooked; // ???被鉤的線程的結構指針,不知道 //下面還有,省略。。。 } HOOK_INFO, *PHOOK_INFO;char *GetHookType(int Id) { char *string; string = (char*)malloc(32); switch (Id) { case -1: { strcpy(string, "WH_MSGFILTER"); break; } case 0: { strcpy(string, "WH_JOURNALRECORD"); break; } case 1: { strcpy(string, "WH_JOURNALPLAYBACK"); break; } case 2: { strcpy(string, "WH_KEYBOARD"); break; } case 3: { strcpy(string, "WH_GETMESSAGE"); break; } case 4: { strcpy(string, "WH_CALLWNDPROC"); break; } case 5: { strcpy(string, "WH_CBT"); break; } case 6: { strcpy(string, "WH_SYSMSGFILTER"); break; } case 7: { strcpy(string, "WH_MOUSE"); break; } case 8: { strcpy(string, "WH_HARDWARE"); break; } case 9: { strcpy(string, "WH_DEBUG"); break; } case 10: { strcpy(string, "WH_SHELL"); break; } case 11: { strcpy(string, "WH_FOREGROUNDIDLE"); break; } case 12: { strcpy(string, "WH_CALLWNDPROCRET"); break; } case 13: { strcpy(string, "WH_KEYBOARD_LL"); break; } case 14: { strcpy(string, "WH_MOUSE_LL"); break; } default: { strcpy(string, "????"); break; } } return string; }char *GetHookFlagString(int Flag) { char *string; string = (char*)malloc(8); if (Flag == 1 || Flag == 3) strcpy(string, "Global"); else strcpy(string, "Local"); return string; }void EnumMsgHook() { int i = 0; UINT64 pgSharedInfo = (UINT64)GetProcAddress(LoadLibraryA("user32.dll"), "gSharedInfo");cout << "user32.dll.gSharedInfo:" << pgSharedInfo << endl;UINT64 phe = GetQWORD(pgSharedInfo + 8); //+0x008 aheList : Ptr64 _HANDLEENTRY UINT64 count = GetQWORD(GetQWORD(pgSharedInfo) + 8); HANDLEENTRY heStruct = { 0 }; HOOK_INFO Hook = { 0 }; cout << count << endl; for (i = 0; i<count; i++) { memcpy(&heStruct, (PVOID)(phe + i * sizeof(HANDLEENTRY)), sizeof(HANDLEENTRY)); if (heStruct.bType == 5) { RKM(heStruct.phead, &Hook, sizeof(HOOK_INFO)); printf("hHandle: 0x%llx\n", Hook.hHandle); printf("iHookFlags: %s\n", GetHookFlagString(Hook.iHookFlags)); printf("iHookType: %s\n", GetHookType(Hook.iHookType)); printf("OffPfn: 0x%llx\n", Hook.OffPfn); printf("ETHREAD: 0x%llx\n", GetQWORD((UINT64)(Hook.Win32Thread))); printf("ProcessName: %s\n\n", GetPNbyET(GetQWORD((UINT64)(Hook.Win32Thread)))); } } }//end********************UnHook************************* int main() { //安裝驅動 if (!InstallDriver("Dri.sys", "MyDriver", "MyDriver")) { printf("LoadDriver=false\n"); return 0; } else { printf("LoadDriver=true\n"); }getchar(); EnumMsgHook(); getchar();//getchar(); //getchar(); //卸載驅動 UnInstallDriver(); printf("UninstallDriver=true\n"); return 0; }?
總結
以上是生活随笔為你收集整理的Win64 驱动内核编程-28.枚举消息钩子的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Win64 驱动内核编程-26.强制结束
- 下一篇: Win64 驱动内核编程-29.强制解锁