Windows驱动开发学习笔记(六)—— Inline HOOK
生活随笔
收集整理的這篇文章主要介紹了
Windows驱动开发学习笔记(六)—— Inline HOOK
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
Windows驅(qū)動(dòng)開(kāi)發(fā)學(xué)習(xí)筆記(六)—— Inline HOOK
- SSDT HOOK
- Inline Hook
- 掛鉤
- 執(zhí)行流程
- 脫鉤
- 實(shí)驗(yàn)一:3環(huán) Inline Hook
- 實(shí)驗(yàn)二:0環(huán) Inline Hook
SSDT HOOK
缺點(diǎn):
Inline Hook
JMP的偏移 = 跳轉(zhuǎn)地址 - 補(bǔ)丁地址 -5
掛鉤
執(zhí)行流程
脫鉤
實(shí)驗(yàn)一:3環(huán) Inline Hook
#include <stdio.h> #include <windows.h>BYTE* ProcAddr = 0; //原函數(shù)地址 DWORD OldProtect = 0; //保存舊的內(nèi)存保護(hù) BYTE OldCmd[20] = {0}; //存儲(chǔ)原函數(shù)頭部原始指令 在最后面構(gòu)造返回到原函數(shù)的指令BYTE* HookProcAddr = 0; //鉤子函數(shù)的地址//函數(shù)指針 將數(shù)據(jù)作為指令執(zhí)行 typedef void (*POLDCMD)(); POLDCMD pOldCmd = (POLDCMD)(char*)OldCmd; //printf的格式 char *format = "%x";DWORD add(DWORD a, DWORD b) {return a + b; }void __declspec(naked) HookProc() {//保存現(xiàn)場(chǎng)__asm{pushadpushfd}//獲得參數(shù)1printf("a = ");__asm{mov eax, espadd eax, 40push [eax]push formatcall printfadd esp, 8}//獲得參數(shù)2printf("\nb = ");__asm{mov eax, espadd eax, 44push [eax]push formatcall printfadd esp, 8}printf("\n");//還原現(xiàn)場(chǎng)__asm{popfdpopad//執(zhí)行原函數(shù)頭部指令 并返回到原函數(shù)下一行繼續(xù)執(zhí)行jmp pOldCmd} }void InlineHook() {//獲得需要掛鉤的函數(shù)地址ProcAddr = (BYTE*)add + 1;ProcAddr += *(DWORD*)ProcAddr + 4;//修改內(nèi)存保護(hù)VirtualProtect(ProcAddr, 6, PAGE_EXECUTE_READWRITE, &OldProtect);//將被覆蓋的指令復(fù)制到數(shù)組中strncpy((char*)OldCmd, (char*)ProcAddr, 6);//數(shù)組末尾添上跳轉(zhuǎn)指令 用于返回到被掛鉤的函數(shù)OldCmd[6] = 0xE9;*(DWORD*)&OldCmd[7] = (DWORD)(ProcAddr+6) - (DWORD)&OldCmd[6] - 5;//獲得鉤子函數(shù)的地址HookProcAddr = (BYTE*)HookProc + 1;HookProcAddr += *(DWORD*)HookProcAddr + 4;//修改原函數(shù)的頭部 跳轉(zhuǎn)到鉤子函數(shù)ProcAddr[0] = 0xE9;*(DWORD*)&ProcAddr[1] = HookProcAddr - ProcAddr - 5;//跳轉(zhuǎn)指令只占五個(gè)字節(jié) 原函數(shù)頭部三行指令占六個(gè)字節(jié) 因此將多余字節(jié)填充為nopProcAddr[5] = 0x90;}void UnInlineHook() {//判斷函數(shù)是否被掛鉤if(ProcAddr[0] == 0xE9){strncpy((char*)ProcAddr, (char*)OldCmd, 6);} }int main() {DWORD sum;//掛鉤InlineHook();sum = add(1, 2);printf("sum = %x\n", sum);//脫鉤UnInlineHook();sum = add(3, 4);printf("sum = %x\n", sum);return 0; }執(zhí)行結(jié)果:
實(shí)驗(yàn)二:0環(huán) Inline Hook
#include <ntddk.h> #include <ntstatus.h>PUCHAR pNtOpenProcess; UCHAR OldCmd[20] = {0}; //函數(shù)指針 用于將數(shù)據(jù)作為指令執(zhí)行 typedef VOID (*POLDCMD)(); POLDCMD pOldCmd = (POLDCMD)(PUCHAR)OldCmd;PCHAR format = "%x %x %x %x \r\n";typedef NTSTATUS (*NTOPENPROCESS)(PHANDLE ProcessHandle,ACCESS_MASK DesiredAccess,POBJECT_ATTRIBUTES ObjectAttributes,PCLIENT_ID ClientId);typedef struct _KSYSTEM_SERVICE_TABLE { PULONG ServiceTableBase; // 服務(wù)函數(shù)地址表基址 PULONG ServiceCounterTableBase; // SSDT函數(shù)被調(diào)用的次數(shù)ULONG NumberOfService; // 服務(wù)函數(shù)的個(gè)數(shù) PULONG ParamTableBase; // 服務(wù)函數(shù)參數(shù)表基址 } KSYSTEM_SERVICE_TABLE, *PKSYSTEM_SERVICE_TABLE; typedef struct _KSERVICE_TABLE_DESCRIPTOR { KSYSTEM_SERVICE_TABLE ntoskrnl; // ntoskrnl.exe 的服務(wù)函數(shù) KSYSTEM_SERVICE_TABLE win32k; // win32k.sys 的服務(wù)函數(shù)(GDI32.dll/User32.dll 的內(nèi)核支持) KSYSTEM_SERVICE_TABLE notUsed1; KSYSTEM_SERVICE_TABLE notUsed2; }KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR;// KeServiceDescriptorTable 是 ntoskrnl.exe 所導(dǎo)出的全局變量 申明一下就可以直接使用了 extern PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable;VOID PageProtectOn() {__asm{//開(kāi)啟內(nèi)存保護(hù)mov eax,cr0or eax,10000hmov cr0,eaxsti} }VOID PageProtectOff() {__asm{//關(guān)閉內(nèi)存保護(hù)cli mov eax,cr0and eax,not 10000hmov cr0,eax} }VOID __declspec(naked) HookProc(){__asm{//保存現(xiàn)場(chǎng)pushadpushfdmov eax, espadd eax, 40 //eflags + 8個(gè)通用寄存器 + 返回地址add eax, 12 //定位到最后一個(gè)參數(shù)push [eax] //ClientIdpush [eax-0x4] //ObjectAttributespush [eax-0x8] //DesiredAccesspush [eax-0xC] //ProcessHandlepush formatcall DbgPrintadd esp, 20//還原現(xiàn)場(chǎng)popfdpopad//調(diào)用原本的指令,然后返回到原函數(shù)jmp pOldCmd} }NTSTATUS InlineHook() {NTSTATUS status;status = STATUS_SUCCESS;PageProtectOff();//保存原來(lái)的指令pNtOpenProcess = (PUCHAR)KeServiceDescriptorTable->ntoskrnl.ServiceTableBase[0x7A];RtlMoveMemory(OldCmd, pNtOpenProcess, 5);//構(gòu)造回去的指令,用于返回到原函數(shù)OldCmd[5] = 0xE9;*(PULONG)&OldCmd[6] = ((ULONG)pNtOpenProcess+5) - (ULONG)&OldCmd[5] - 5;//內(nèi)核函數(shù)不存在中間人(call后通過(guò)jmp跳轉(zhuǎn)),函數(shù)地址為實(shí)際地址pNtOpenProcess[0] = 0xE9;*(PULONG)&pNtOpenProcess[1] = (ULONG)HookProc - (ULONG)pNtOpenProcess - 5;PageProtectOn();return status; }NTSTATUS UnInlineHook() {NTSTATUS status;status = STATUS_SUCCESS;if(pNtOpenProcess[0] == 0xE9){PageProtectOff();RtlMoveMemory(pNtOpenProcess, OldCmd, 5);PageProtectOn();}return status; }//卸載函數(shù) VOID DriverUnload(PDRIVER_OBJECT driver) {//卸載驅(qū)動(dòng)時(shí)脫鉤UnInlineHook();DbgPrint("驅(qū)動(dòng)程序已停止.\r\n"); }//驅(qū)動(dòng)程序入口函數(shù),相當(dāng)于控制臺(tái)的main函數(shù) NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath) {DbgPrint("驅(qū)動(dòng)程序已運(yùn)行.\r\n");//運(yùn)行驅(qū)動(dòng)時(shí)掛鉤InlineHook();//設(shè)置一個(gè)卸載函數(shù) 便于退出DriverObject->DriverUnload = DriverUnload;return STATUS_SUCCESS; }執(zhí)行結(jié)果:
總結(jié)
以上是生活随笔為你收集整理的Windows驱动开发学习笔记(六)—— Inline HOOK的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Windows驱动开发学习笔记(五)——
- 下一篇: Windows驱动开发学习笔记(七)——