寒江独钓学习笔记 -- 第四章 Hook分发函数 过滤键盘输入
生活随笔
收集整理的這篇文章主要介紹了
寒江独钓学习笔记 -- 第四章 Hook分发函数 过滤键盘输入
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
轉(zhuǎn)載請注明出處:http://blog.csdn.net/lup7in/article/details/7015497
最近在學習windows內(nèi)核編程,下面是《寒江獨釣》第四章hook分發(fā)函數(shù)過濾鍵盤輸入的源代碼,書上沒有提供完整的代碼,經(jīng)過調(diào)試完成了這部分代碼,下面把代碼分享出來,有不對的地方,希望大牛指教。
#include <ntddk.h> #include <ntddkbd.h> #define NTSTRSAFE_LIB #include <Ntstrsafe.h>extern POBJECT_TYPE IoDriverObjectType;#define KBD_DRIVER_NAME L"\\Driver\\Kbdclass"//用于延時的宏定義 #define DELAY_ONE_MICROSECOND (-10) #define DELAY_ONE_MILLISECOND (DELAY_ONE_MICROSECOND * 1000) #define DELAY_ONE_SECOND (DELAY_ONE_MILLISECOND * 1000)//表示幾個特殊鍵的宏 #define S_SHIFT 0x01//shift鍵 #define S_CAPS 0x02//大寫鎖定鍵 #define S_NUM 0x04//數(shù)字鎖定鍵ULONG gC2pKeyCount = 0;unsigned char asciiTbl[]={ 0x00, 0x1B, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x2D, 0x3D, 0x08, 0x09,//normal 0x71, 0x77, 0x65, 0x72, 0x74, 0x79, 0x75, 0x69, 0x6F, 0x70, 0x5B, 0x5D, 0x0D, 0x00, 0x61, 0x73, 0x64, 0x66, 0x67, 0x68, 0x6A, 0x6B, 0x6C, 0x3B, 0x27, 0x60, 0x00, 0x5C, 0x7A, 0x78, 0x63, 0x76, 0x62, 0x6E, 0x6D, 0x2C, 0x2E, 0x2F, 0x00, 0x2A, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x38, 0x39, 0x2D, 0x34, 0x35, 0x36, 0x2B, 0x31, 0x32, 0x33, 0x30, 0x2E, 0x00, 0x1B, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x2D, 0x3D, 0x08, 0x09,//caps 0x51, 0x57, 0x45, 0x52, 0x54, 0x59, 0x55, 0x49, 0x4F, 0x50, 0x5B, 0x5D, 0x0D, 0x00, 0x41, 0x53, 0x44, 0x46, 0x47, 0x48, 0x4A, 0x4B, 0x4C, 0x3B, 0x27, 0x60, 0x00, 0x5C, 0x5A, 0x58, 0x43, 0x56, 0x42, 0x4E, 0x4D, 0x2C, 0x2E, 0x2F, 0x00, 0x2A, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x38, 0x39, 0x2D, 0x34, 0x35, 0x36, 0x2B, 0x31, 0x32, 0x33, 0x30, 0x2E, 0x00, 0x1B, 0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A, 0x28, 0x29, 0x5F, 0x2B, 0x08, 0x09,//shift 0x51, 0x57, 0x45, 0x52, 0x54, 0x59, 0x55, 0x49, 0x4F, 0x50, 0x7B, 0x7D, 0x0D, 0x00, 0x41, 0x53, 0x44, 0x46, 0x47, 0x48, 0x4A, 0x4B, 0x4C, 0x3A, 0x22, 0x7E, 0x00, 0x7C, 0x5A, 0x58, 0x43, 0x56, 0x42, 0x4E, 0x4D, 0x3C, 0x3E, 0x3F, 0x00, 0x2A, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x38, 0x39, 0x2D, 0x34, 0x35, 0x36, 0x2B, 0x31, 0x32, 0x33, 0x30, 0x2E, 0x00, 0x1B, 0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A, 0x28, 0x29, 0x5F, 0x2B, 0x08, 0x09,//caps + shift 0x71, 0x77, 0x65, 0x72, 0x74, 0x79, 0x75, 0x69, 0x6F, 0x70, 0x7B, 0x7D, 0x0D, 0x00, 0x61, 0x73, 0x64, 0x66, 0x67, 0x68, 0x6A, 0x6B, 0x6C, 0x3A, 0x22, 0x7E, 0x00, 0x7C, 0x7A, 0x78, 0x63, 0x76, 0x62, 0x6E, 0x6D, 0x3C, 0x3E, 0x3F, 0x00, 0x2A, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x38, 0x39, 0x2D, 0x34, 0x35, 0x36, 0x2B, 0x31, 0x32, 0x33, 0x30, 0x2E };//儲存舊的分發(fā)函數(shù)的數(shù)組 PDRIVER_DISPATCH OldMajorFunction[IRP_MJ_MAXIMUM_FUNCTION+1];//用于根據(jù)驅(qū)動名稱打開驅(qū)動對象 這個函數(shù)文檔沒公布 所以要聲明一下 NTSTATUS ObReferenceObjectByName( PUNICODE_STRING ObjectName, ULONG Attributes, PACCESS_STATE AccessState, ACCESS_MASK DesiredAccess, POBJECT_TYPE ObjectType, KPROCESSOR_MODE AccessMode, PVOID ParseContext, PVOID *Object );PDRIVER_OBJECT pKbdDriverObject = NULL; UNICODE_STRING uniNtNameString;//打開驅(qū)動對象的函數(shù) NTSTATUS OpenKbdDriver() { NTSTATUS status; RtlInitUnicodeString(&uniNtNameString,KBD_DRIVER_NAME); status = ObReferenceObjectByName(&uniNtNameString,OBJ_CASE_INSENSITIVE,NULL,0,IoDriverObjectType,KernelMode,NULL,&pKbdDriverObject); if(NT_SUCCESS(status)) { ObDereferenceObject(pKbdDriverObject); DbgPrint("open the kbd driver success!"); } else { DbgPrint("open the kbd driver fail!"); } return status; }static int kb_status = S_NUM; //用于打印實際按鍵字符的函數(shù) //2011/11/10 void _stdcall print_keystroke(UCHAR sch,USHORT Flags) { UCHAR ch = 0; int off = 0; //kb_status = S_NUM; //DbgPrint("%x\n",sch); //按下 if(Flags == KEY_MAKE/*(sch & 0x80) == 0*/) { switch(sch) { case 0x3A: kb_status ^= S_CAPS; break; case 0x2A: case 0x36: kb_status |= S_SHIFT; break; case 0x45: kb_status ^= S_NUM; break; } } else if(Flags == KEY_BREAK) //彈起 { if(sch == 0x2A || sch == 0x36) kb_status &= ~S_SHIFT; }if(kb_status & S_CAPS) { off = 84 * 1; } if(kb_status & S_SHIFT) { off = 84 * 2; } if((kb_status & S_SHIFT) && (kb_status & S_CAPS)) { off = 84 * 3; } //DbgPrint("%d\n",off);if((sch < 0x47) || ((sch >= 0x47 && sch < 0x54) && (kb_status & S_NUM))) { ch = asciiTbl[off + sch]; } if(Flags == KEY_MAKE){ if(ch >= 0x20 && ch < 0x7F) { DbgPrint("%C\n",ch); } } }NTSTATUS c2pReadComplete(PDEVICE_OBJECT DeviceObject,PIRP Irp,PVOID Context) { PIO_STACK_LOCATION IrpSp; ULONG buf_len = 0; //systembuffer 的數(shù)據(jù)結(jié)構(gòu)形式 是一個結(jié)構(gòu)體 KEYBOARD_INPUT_DATA PUCHAR buf = NULL; size_t i; ULONG numKeys = 0; PKEYBOARD_INPUT_DATA KeyData = NULL;IrpSp = IoGetCurrentIrpStackLocation(Irp);//如果成功 if(NT_SUCCESS(Irp->IoStatus.Status)) { //獲取讀請求完成后的輸出緩沖區(qū) buf = Irp->AssociatedIrp.SystemBuffer; KeyData = (PKEYBOARD_INPUT_DATA)buf; //獲得緩沖區(qū)長度 buf_len = Irp->IoStatus.Information; numKeys = buf_len / sizeof(KEYBOARD_INPUT_DATA); for(i = 0;i < numKeys;i++) { //打印出一些按鍵信息 //DbgPrint("numKeys:%d",numKeys); //DbgPrint("ScanCode:%x",KeyData->MakeCode); //DbgPrint("%s\n",KeyData->Flags ? "UP" : "DOWN"); print_keystroke((UCHAR)KeyData->MakeCode,KeyData->Flags); //這里是一個小實驗 當用戶按下ctrl鍵時 //把其掃描碼改成大寫鎖定鍵CAPS_LOCK的掃描碼 //當按下ctrl鍵時就會啟動大寫鎖定 //這說明按鍵是可以被截獲并且人為修改的 //if(KeyData->MakeCode == LCONTROL) //{ // KeyData->MakeCode = CAPS_LOCK; //} }//這里可以做其他事情 //打印按鍵的掃描碼 //for(i = 0;i < buf_len;i++) //{ // DbgPrint("ctrl2cap:%2x\r\n",buf[i]); //} } gC2pKeyCount--; //DbgPrint("count:%d",gC2pKeyCount); if(Irp->PendingReturned) { IoMarkIrpPending(Irp); } return Irp->IoStatus.Status; }//自己寫的分發(fā)函數(shù) NTSTATUS MyDispatchFunction (IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp ) { PUCHAR buf = NULL; ULONG buf_len = 0; ULONG i; PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation(Irp); //如果是讀請求 就hook之 if(irpsp->MajorFunction == IRP_MJ_READ) { irpsp->Control = SL_INVOKE_ON_SUCCESS | SL_INVOKE_ON_ERROR | SL_INVOKE_ON_CANCEL; //保留原來的完成函數(shù),如果有的話 irpsp->Context = irpsp->CompletionRoutine; irpsp->CompletionRoutine = (PIO_COMPLETION_ROUTINE)c2pReadComplete; //DbgPrint("已設(shè)置回調(diào)函數(shù).../n"); gC2pKeyCount++; //DbgPrint("count:%d",gC2pKeyCount); //調(diào)用原來的分發(fā)函數(shù),完成應(yīng)該有的內(nèi)容 return OldMajorFunction[irpsp->MajorFunction](DeviceObject,Irp); } else { return OldMajorFunction[irpsp->MajorFunction](DeviceObject,Irp); } }//替換分發(fā)函數(shù)指針的函數(shù) VOID ReplaceDispatch() { ULONG i; for(i = 0;i < IRP_MJ_MAXIMUM_FUNCTION + 1;i++) { //保存分發(fā)函數(shù)指針 OldMajorFunction[i] = pKbdDriverObject->MajorFunction[i]; //把分發(fā)函數(shù)指針設(shè)置成我們自己寫的分發(fā)函數(shù) 這個函數(shù)替換指針是原子操作 防止替換時被打斷 InterlockedExchangePointer(&pKbdDriverObject->MajorFunction[i],MyDispatchFunction); DbgPrint("replace successful!"); } }//恢復(fù)分發(fā)函數(shù)指針的函數(shù) VOID ReSetDispatchFunction() { ULONG i; for(i = 0;i < IRP_MJ_MAXIMUM_FUNCTION + 1;i++) { InterlockedExchangePointer(&pKbdDriverObject->MajorFunction[i],OldMajorFunction[i]); DbgPrint("reset dispatch function success!"); } }//卸載函數(shù) //2011/11/19 VOID HookDispatchUnload(IN PDRIVER_OBJECT DriverObject) { PDEVICE_OBJECT DeviceObject; PRKTHREAD pCurrentThread; LARGE_INTEGER lDelay;lDelay = RtlConvertLongToLargeInteger(100 * DELAY_ONE_MILLISECOND); pCurrentThread = KeGetCurrentThread(); //把線程設(shè)置成低實時模式 減少對其他程序的影響 KeSetPriorityThread(pCurrentThread,LOW_REALTIME_PRIORITY);UNREFERENCED_PARAMETER(DriverObject); KdPrint(("DriverEntry unLoading...\n"));//恢復(fù)分發(fā)函數(shù)指針 ReSetDispatchFunction();while(gC2pKeyCount) { KeDelayExecutionThread(KernelMode,FALSE,&lDelay); } KdPrint(("DriverEntry unLoad OK!\n")); }//入口函數(shù) NTSTATUS DriverEntry( PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath ) { NTSTATUS status; DriverObject->DriverUnload = HookDispatchUnload; //打開鍵盤內(nèi)核對象 status = OpenKbdDriver(); if(NT_SUCCESS(status)) { //替換分發(fā)函數(shù) ReplaceDispatch(); } return status; }總結(jié)
以上是生活随笔為你收集整理的寒江独钓学习笔记 -- 第四章 Hook分发函数 过滤键盘输入的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 玩转视频类信息流广告平台,投放技巧及运营
- 下一篇: python用keras库做个股票分析小