日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Win64 驱动内核编程-19.HOOK-SSDT

發(fā)布時間:2025/6/17 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Win64 驱动内核编程-19.HOOK-SSDT 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

HOOK?SSDT

????在?WIN64?上?HOOK?SSDT?和?UNHOOK?SSDT?在原理上跟?WIN32?沒什么不同,甚至說?HOOK?和?UNHOOK?在本質(zhì)上也沒有不同,都是在指定的地址上填寫一串?dāng)?shù)字而已

(填寫代理函數(shù)的地址時叫做?HOOK,填寫原始函數(shù)的地址時叫做?UNHOOK)。不過實現(xiàn)起來還是很大不同的。

一?、?HOOK?SSDT

????要掛鉤?SSDT,必然要先得到?ServiceTableBase?的地址。和?SSDT?相關(guān)的兩個結(jié)構(gòu)體?SYSTEM_SERVICE_TABLE?以及?SERVICE_DESCRIPTOR_TABLE?并沒有發(fā)生

什么的變化(除了整個結(jié)構(gòu)體的長度胖了一倍):

typedef struct _SYSTEM_SERVICE_TABLE{ PVOID ServiceTableBase; PVOID ServiceCounterTableBase; ULONGLONG NumberOfServices; PVOID ParamTableBase; } SYSTEM_SERVICE_TABLE, *PSYSTEM_SERVICE_TABLE;typedef struct _SERVICE_DESCRIPTOR_TABLE{ SYSTEM_SERVICE_TABLE ntoskrnl; // ntoskrnl.exe (native api) SYSTEM_SERVICE_TABLE win32k; // win32k.sys (gdi/user) SYSTEM_SERVICE_TABLE Table3; // not used SYSTEM_SERVICE_TABLE Table4; // not used }SERVICE_DESCRIPTOR_TABLE,*PSERVICE_DESCRIPTOR_TABLE;


得到?ServiceTableBase?的地址后,就能得到每個服務(wù)函數(shù)的地址了。但和WIN32?不一樣,這個表存放的并不是?SSDT?函數(shù)的完整地址,而是其相對于ServiceTableBase[Index]>>4?的數(shù)據(jù)(我稱它為偏移地址),每個數(shù)據(jù)占四個字節(jié),所以計算指定?Index?函數(shù)完整地址的公式是:ServiceTableBase[Index]>>4+?ServiceTableBase。代碼如下(這個上一個博客已經(jīng)說過):

ULONGLONG GetSSDTFuncCurAddr(ULONG id) { LONG dwtmp=0; PULONG ServiceTableBase=NULL; ServiceTableBase=(PULONG)KeServiceDescriptorTable->ServiceTableBase; dwtmp=ServiceTableBase[id]; dwtmp=dwtmp>>4; return (LONGLONG)dwtmp + (ULONGLONG)ServiceTableBase; }

反之,從函數(shù)的完整地址獲得函數(shù)偏移地址的代碼也就出來了:

ULONG GetOffsetAddress(ULONGLONG FuncAddr) { ULONG dwtmp=0; PULONG ServiceTableBase=NULL; ServiceTableBase=(PULONG)KeServiceDescriptorTable->ServiceTableBase; dwtmp=(ULONG)(FuncAddr-(ULONGLONG)ServiceTableBase); return dwtmp<<4; }
以下是我目前正在看的資料的作者?胡文亮?的吐槽:

? ? 知道了這一套機制,HOOK?SSDT?就很簡單了,首先獲得待?HOOK?函數(shù)的序號Index,然后通過公式把自己的代理函數(shù)的地址轉(zhuǎn)化為偏移地址,然后把偏移地址的數(shù)據(jù)填入?ServiceTableBase[Index]。也許有些讀者看到這里,已經(jīng)覺得勝利在望了,我當(dāng)時也是如此。但實際上我在這里栽了個大跟頭,整整郁悶了很長時間!因為我低估了設(shè)計這套算法的工程師的智商,我沒有考慮一個問題,為什么?WIN64?的?SSDT?表存放地址的形式這么奇怪?只存放偏移地址,而不存放完整地址?難道是為了節(jié)省內(nèi)存?這肯定是不可能的,要知道現(xiàn)在內(nèi)存白菜價。那么不是為了節(jié)省內(nèi)存,唯一的可能性就是要給試圖掛鉤?SSDT?的人制造麻煩!要知道,WIN64?內(nèi)核里每個驅(qū)動都?不在同一個?B?4GB??里,而?4?字節(jié)的整數(shù)只能表示?4GB的范圍!所以無論你怎么修改這個值,都跳不出?ntoskrnl?的手掌心。如果你想通過修改這個值來跳轉(zhuǎn)到你的代理函數(shù),那是絕對不可能的。?因為你的驅(qū)動的地址不?可能跟?l?ntoskrnl??在同一個?B?4GB??里。然而,這位工程師也低估了我們中國人的智商,在中國有兩句成語,這位工程師一定沒聽過,叫“明修棧道,暗渡陳倉”以及“上有政策,下有對策”。雖然不能直接用?4?字節(jié)來表示自己的代理函數(shù)所在的地址,但是還是可以修改這個值的。要知道,ntoskrnl?雖然有很多地方的代碼通常是不會被執(zhí)行的,比如?KeBugCheckEx。所以我的辦法是:?修改這個偏移地址的值,使之跳轉(zhuǎn)到??KeBugCheckEx?,然后在?x?KeBugCheckEx??的頭部寫一個?2?12??字節(jié)的??mov?-?-?jmp?,這是一個可以跨越??4GB ?!?的跳轉(zhuǎn),跳到我們的函數(shù)里!代碼如下:

VOID FuckKeBugCheckEx() { KIRQL irql; ULONGLONG myfun; UCHAR jmp_code[]="\x48\xB8\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xE0"; myfun=(ULONGLONG)Fake_NtTerminateProcess; memcpy(jmp_code+2,&myfun,8); irql=WPOFFx64(); memset(KeBugCheckEx,0x90,15); memcpy(KeBugCheckEx,jmp_code,12); WPONx64(irql); }VOID HookSSDT() { KIRQL irql; ULONGLONG dwtmp=0; PULONG ServiceTableBase=NULL; //get old address NtTerminateProcess=(NTTERMINATEPROCESS)GetSSDTFuncCurAddr(41); dprintf("Old_NtTerminateProcess: %llx",(ULONGLONG)NtTerminateProcess); //set kebugcheckex FuckKeBugCheckEx(); //show new address ServiceTableBase=(PULONG)KeServiceDescriptorTable->ServiceTableBase; OldTpVal=ServiceTableBase[41]; //record old offset value irql=WPOFFx64(); ServiceTableBase[41]=GetOffsetAddress((ULONGLONG)KeBugCheckEx); WPONx64(irql); dprintf("KeBugCheckEx: %llx",(ULONGLONG)KeBugCheckEx); dprintf("New_NtTerminateProcess: %llx",GetSSDTFuncCurAddr(41)); }回調(diào)函數(shù)保護(hù)計算器不被結(jié)束:

NTSTATUS __fastcall Fake_NtTerminateProcess(IN HANDLE ProcessHandle, IN NTSTATUS ExitStatus) { PEPROCESS Process; NTSTATUS st = ObReferenceObjectByHandle (ProcessHandle, 0, *PsProcessType, KernelMode, &Process, NULL); DbgPrint("Fake_NtTerminateProcess called!"); if(NT_SUCCESS(st)) { if(!_stricmp(PsGetProcessImageFileName(Process),"calc.exe")) return STATUS_ACCESS_DENIED; else return NtTerminateProcess(ProcessHandle,ExitStatus); } else return STATUS_ACCESS_DENIED; }
完整測試代碼:

#include <ntddk.h> typedef struct _SYSTEM_SERVICE_TABLE{ PVOID ServiceTableBase; PVOID ServiceCounterTableBase; ULONGLONG NumberOfServices; PVOID ParamTableBase; } SYSTEM_SERVICE_TABLE, *PSYSTEM_SERVICE_TABLE;typedef struct _SERVICE_DESCRIPTOR_TABLE{ SYSTEM_SERVICE_TABLE ntoskrnl; // ntoskrnl.exe (native api) SYSTEM_SERVICE_TABLE win32k; // win32k.sys (gdi/user) SYSTEM_SERVICE_TABLE Table3; // not used SYSTEM_SERVICE_TABLE Table4; // not used }SERVICE_DESCRIPTOR_TABLE,*PSERVICE_DESCRIPTOR_TABLE;typedef NTSTATUS (__fastcall *NTTERMINATEPROCESS)(IN HANDLE ProcessHandle, IN NTSTATUS ExitStatus);NTKERNELAPI UCHAR * PsGetProcessImageFileName(PEPROCESS Process);PSYSTEM_SERVICE_TABLE KeServiceDescriptorTable; NTTERMINATEPROCESS NtTerminateProcess=NULL; ULONG OldTpVal;NTSTATUS __fastcall Fake_NtTerminateProcess(IN HANDLE ProcessHandle, IN NTSTATUS ExitStatus) { PEPROCESS Process; NTSTATUS st = ObReferenceObjectByHandle (ProcessHandle, 0, *PsProcessType, KernelMode, &Process, NULL); DbgPrint("Fake_NtTerminateProcess called!"); if(NT_SUCCESS(st)) { if(!_stricmp(PsGetProcessImageFileName(Process),"calc.exe")) return STATUS_ACCESS_DENIED; else return NtTerminateProcess(ProcessHandle,ExitStatus); } else return STATUS_ACCESS_DENIED; }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); }ULONGLONG GetKeServiceDescriptorTable64() { PUCHAR StartSearchAddress = (PUCHAR)__readmsr(0xC0000082); PUCHAR EndSearchAddress = StartSearchAddress + 0x500; PUCHAR i = NULL; UCHAR b1 = 0, b2 = 0, b3 = 0; ULONG templong = 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 == 0x15) //4c8d15 { memcpy(&templong, i + 3, 4); addr = (ULONGLONG)templong + (ULONGLONG)i + 7; return addr; } } } return 0; }ULONGLONG GetSSDTFuncCurAddr(ULONG id) { LONG dwtmp=0; PULONG ServiceTableBase=NULL; ServiceTableBase=(PULONG)KeServiceDescriptorTable->ServiceTableBase; dwtmp=ServiceTableBase[id]; dwtmp=dwtmp>>4; return (LONGLONG)dwtmp + (ULONGLONG)ServiceTableBase; }ULONG GetOffsetAddress(ULONGLONG FuncAddr) { ULONG dwtmp=0; PULONG ServiceTableBase=NULL; ServiceTableBase=(PULONG)KeServiceDescriptorTable->ServiceTableBase; dwtmp=(ULONG)(FuncAddr-(ULONGLONG)ServiceTableBase); return dwtmp<<4; }VOID FuckKeBugCheckEx() { KIRQL irql; ULONGLONG myfun; UCHAR jmp_code[]="\x48\xB8\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xE0"; myfun=(ULONGLONG)Fake_NtTerminateProcess; memcpy(jmp_code+2,&myfun,8); irql=WPOFFx64(); memset(KeBugCheckEx,0x90,15); memcpy(KeBugCheckEx,jmp_code,12); WPONx64(irql); }/* 填寫KeBugCheckEx的地址 在KeBugCheckEx填寫jmp,跳到Fake_NtTerminateProcess 不能直接填寫Fake_NtTerminateProcess的地址,因為它們不再同一個4GB */ VOID HookSSDT() { KIRQL irql; ULONGLONG dwtmp=0; PULONG ServiceTableBase=NULL; //get old address NtTerminateProcess=(NTTERMINATEPROCESS)GetSSDTFuncCurAddr(41); dprintf("Old_NtTerminateProcess: %llx",(ULONGLONG)NtTerminateProcess); //set kebugcheckex FuckKeBugCheckEx(); //show new address ServiceTableBase=(PULONG)KeServiceDescriptorTable->ServiceTableBase; OldTpVal=ServiceTableBase[41]; //record old offset value irql=WPOFFx64(); ServiceTableBase[41]=GetOffsetAddress((ULONGLONG)KeBugCheckEx); WPONx64(irql); dprintf("KeBugCheckEx: %llx",(ULONGLONG)KeBugCheckEx); dprintf("New_NtTerminateProcess: %llx",GetSSDTFuncCurAddr(41)); }VOID UnhookSSDT() { KIRQL irql; PULONG ServiceTableBase=NULL; ServiceTableBase=(PULONG)KeServiceDescriptorTable->ServiceTableBase; //set value irql=WPOFFx64(); ServiceTableBase[41]=GetOffsetAddress((ULONGLONG)NtTerminateProcess); //OldTpVal;//直接填寫這個舊值也行 WPONx64(irql); //沒必要恢復(fù)KeBugCheckEx的內(nèi)容了,反正執(zhí)行到KeBugCheckEx時已經(jīng)完蛋了。 dprintf("NtTerminateProcess: %llx",GetSSDTFuncCurAddr(41)); }調(diào)用: DriverEntry里KeServiceDescriptorTable = (PSYSTEM_SERVICE_TABLE)GetKeServiceDescriptorTable64(); HookSSDT(); DriverUnload里UnhookSSDT();
執(zhí)行結(jié)果:


????下一節(jié)是UNHOOK?SSDT?取消掉機器上別人的HOOK?這個資源的作者其實是寫在一起的,我是分兩次學(xué)習(xí)這個,所以總結(jié)兩次筆記。聲明一下,我這里所有的思路和筆記都來源于資料,我只是理解,把所有的例子都做了一遍,學(xué)習(xí)整理,有一些沒理解了的我會去別的資料里面找,然后把所有相關(guān)整理在同一個資料里。大家一起學(xué)習(xí),一起進(jìn)步。

總結(jié)

以上是生活随笔為你收集整理的Win64 驱动内核编程-19.HOOK-SSDT的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产农村妇女毛片精品久久 | 人妖av在线 | 麻豆国产一区二区三区四区 | 美丽的小蜜桃2:美丽人生 | 欧美熟妇精品一区二区蜜桃视频 | 国产aⅴ无码片毛片一级一区2 | 五月激情片| 美攻壮受大胸奶汁(高h) | 中文字幕11页中文字幕11页 | 国产精品久久久久久久久免费桃花 | 三级福利视频 | 夜夜撸| 精品一区二区免费视频 | 国产精品每日更新 | 国产91精品高潮白浆喷水 | av亚州| 日本三级大全 | 大奶子在线 | 91日韩欧美| 亚洲精品aⅴ中文字幕乱码 国产精品调教视频 | ,国产精品国产三级国产 | 亚洲精品免费在线观看 | 国产精品h | porn国产 | 一级黄色播放 | 少妇激情网| 久久性片| 国产伦精品一区二区三区视频1 | 久久久成人精品一区二区三区 | 性欧美又大又长又硬 | 国产精品一区二区三区在线免费观看 | 亚洲精品婷婷 | 天天激情站 | www夜片内射视频日韩精品成人 | 黑巨茎大战欧美白妞 | 蜜臀网在线 | 日本伦理片在线看 | 亚洲精品av中文字幕在线在线 | 精品无码在线视频 | 韩产日产国产欧产 | 中文字幕av一区二区三区 | 亚洲成人免费在线 | 特级西西www444人体聚色 | 久久无吗视频 | avwww.| 蜜桃麻豆视频 | 亚洲一区二区在线视频 | 欧美视频在线观看视频 | 国产小视频你懂的 | 制服 丝袜 综合 日韩 欧美 | 中文字幕乱码中文乱码b站 国产一区二区三区在线观看视频 | 51国产偷自视频区视频 | 欧美日韩精选 | 国产中文字字幕乱码无限 | 男女羞羞动态图 | 欧美成人精品在线视频 | 26uuu精品一区二区在线观看 | 久久久久69| 久久久天堂 | 致单身男女免费观看完整版 | 欧美午夜免费 | 日本美女裸体视频 | 午夜老司机免费视频 | 免费网站污 | 日韩中文娱乐网 | 国产精品高潮呻吟久久 | 五月激情小说 | 欧美一区二区三区视频在线 | 色一区二区三区 | 中文字幕日韩精品在线 | 日本高清视频www夜色资源 | 一级片在线 | 国产精品资源网 | 国产激情视频在线观看 | 国语av| 精品人人人 | 国产在线18 | 国产天天综合 | 女性生殖扒开酷刑vk | 鲁片一区二区三区 | 免费性爱视频 | 欧美不卡在线视频 | 亚洲精品一二三 | 一区二区三区在线观看免费视频 | 亚洲欧美一区二区三区情侣bbw | 性欧美一区二区三区 | 毛片自拍| 91免费黄| a一级视频 | 黄色大片黄色大片 | 成人亚洲免费 | 色吧在线视频 | 草逼免费视频 | www.亚洲天堂.com | 亚洲女人的天堂 | 天堂中文字幕在线观看 | 国产精品乱码久久久久久久久 | 亚洲一区精品在线观看 | 国产自偷自拍 |