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

歡迎訪問(wèn) 生活随笔!

生活随笔

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

编程问答

Win64 驱动内核编程-30.枚举与删除线程回调

發(fā)布時(shí)間:2025/6/17 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Win64 驱动内核编程-30.枚举与删除线程回调 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

枚舉與刪除線程回調(diào)

? ? 進(jìn)程回調(diào)可以監(jiān)視進(jìn)程的創(chuàng)建和退出,這個(gè)在前面的章節(jié)已經(jīng)總結(jié)過(guò)了。某些游戲保護(hù)的驅(qū)動(dòng)喜歡用這個(gè)函數(shù)來(lái)監(jiān)視有沒(méi)有黑名單中的程序運(yùn)行,如果運(yùn)行則阻止運(yùn)行或者把游戲退出。而線程回調(diào)則通常用來(lái)監(jiān)控遠(yuǎn)程線程的建立,如果發(fā)現(xiàn)有遠(yuǎn)程線程注入到了游戲進(jìn)程里,則馬上把游戲退出。現(xiàn)在來(lái)詳細(xì)講解如何繞過(guò)這個(gè)兩個(gè)監(jiān)控。

????我們注冊(cè)的進(jìn)程回調(diào),會(huì)存儲(chǔ)在一個(gè)名為?PspCreateProcessNotifyRoutine?的數(shù)組里。

PspCreateProcessNotifyRoutine?可以理解成一個(gè)?PVOID?數(shù)組,它記錄了系統(tǒng)里所有進(jìn)程回調(diào)的地址。這個(gè)數(shù)組最大長(zhǎng)度是?64*sizeof(PVOID)。所以枚舉進(jìn)程回調(diào)的思路如下:找到這個(gè)數(shù)組的地址,然后解密數(shù)組的數(shù)據(jù),得到所有回調(diào)的地址(這個(gè)數(shù)組記錄的數(shù)據(jù)并不是回調(diào)的?地?址?,?而?是?經(jīng)?過(guò)?加?密?地?址?,?需?要?解?密?才?行?)。?枚?舉?線?程?回?調(diào)?同?理?,?要?找?到PspCreateThreadNotifyRoutine?的地址(這個(gè)數(shù)組最大長(zhǎng)度也是?64*sizeof(PVOID)),然后解密數(shù)據(jù),并把解密后的地址打印出來(lái)。

? ? 至于怎么處理這些回調(diào)就簡(jiǎn)單了。可以使用標(biāo)準(zhǔn)函數(shù)(PsSetCreateProcessNotifyRoutine、PsRemoveCreateThreadNotifyRoutine)將其摘掉,也可以直接在回調(diào)函數(shù)首地址寫入?RET?把回調(diào)函數(shù)廢掉。

????首先要獲得?PspCreateProcessNotifyRoutine?的地址。PspCreateProcessNotifyRoutine?在PspSetCreateProcessNotifyRoutine?函數(shù)里出現(xiàn)了。而?PspSetCreateProcessNotifyRoutine?則在PsSetCreateProcessNotifyRoutine?中被調(diào)用(注意前一個(gè)是?PspXXX,后一個(gè)是?PsXXX)。找到PspSetCreateProcessNotifyRoutine?之后,再匹配特征碼:

?

?

? ? 于是我們根據(jù)特征碼寫出了以下代碼(僅在?WIN7X64?上有效,WIN8、8.1?需要自己重新

定義特征碼):

?

ULONG64 FindPspCreateProcessNotifyRoutine() { LONG OffsetAddr=0; ULONG64 i=0,pCheckArea=0; UNICODE_STRING unstrFunc; //獲得PsSetCreateProcessNotifyRoutine的地址 RtlInitUnicodeString(&unstrFunc, L"PsSetCreateProcessNotifyRoutine"); pCheckArea = (ULONG64)MmGetSystemRoutineAddress (&unstrFunc); //獲得PspSetCreateProcessNotifyRoutine的地址 memcpy(&OffsetAddr,(PUCHAR)pCheckArea+4,4); pCheckArea=(pCheckArea+3)+5+OffsetAddr; DbgPrint("PspSetCreateProcessNotifyRoutine: %llx",pCheckArea); //獲得PspCreateProcessNotifyRoutine的地址 for(i=pCheckArea;i<pCheckArea+0xff;i++) { if(*(PUCHAR)i==0x4c && *(PUCHAR)(i+1)==0x8d && *(PUCHAR)(i+2)==0x35) //lea r14,xxxx { LONG OffsetAddr=0; memcpy(&OffsetAddr,(PUCHAR)(i+3),4); return OffsetAddr+7+i; } } return 0; }

? ? 找到了?PspCreateProcessNotifyRoutine,枚舉操作就好辦了。需要說(shuō)明的是,在PspCreateProcessNotifyRoutine?里的數(shù)據(jù)竟然被加密了,需要把數(shù)組的值和?0xfffffffffffffff8進(jìn)行“與”位運(yùn)算才行:

?

?

?

找線程的同理:

PspCreateThreadNotifyRoutine?->?

PsSetCreateThreadNotifyRoutine?->

PspCreateThreadNotifyRoutine

?

執(zhí)行結(jié)果如下(干凈win7系統(tǒng)沒(méi)有線程回調(diào),特意注冊(cè)了兩個(gè)):

?

void EnumCreateProcessNotify() { int i=0; BOOLEAN b; ULONG64 NotifyAddr=0,MagicPtr=0; ULONG64 PspCreateProcessNotifyRoutine=FindPspCreateProcessNotifyRoutine(); DbgPrint("PspCreateProcessNotifyRoutine: %llx",PspCreateProcessNotifyRoutine); if(!PspCreateProcessNotifyRoutine) return; for(i=0;i<64;i++) { MagicPtr=PspCreateProcessNotifyRoutine+i*8; NotifyAddr=*(PULONG64)(MagicPtr); if(MmIsAddressValid((PVOID)NotifyAddr) && NotifyAddr!=0) { NotifyAddr=*(PULONG64)(NotifyAddr & 0xfffffffffffffff8); DbgPrint("[CreateProcess]%llx",NotifyAddr); } } }


代碼整理:?進(jìn)程

?

?

ULONG64 FindPspCreateProcessNotifyRoutine() { LONG OffsetAddr=0; ULONG64 i=0,pCheckArea=0; UNICODE_STRING unstrFunc; //獲得PsSetCreateProcessNotifyRoutine的地址 RtlInitUnicodeString(&unstrFunc, L"PsSetCreateProcessNotifyRoutine"); pCheckArea = (ULONG64)MmGetSystemRoutineAddress (&unstrFunc); //獲得PspSetCreateProcessNotifyRoutine的地址 memcpy(&OffsetAddr,(PUCHAR)pCheckArea+4,4); pCheckArea=(pCheckArea+3)+5+OffsetAddr; DbgPrint("PspSetCreateProcessNotifyRoutine: %llx",pCheckArea); //獲得PspCreateProcessNotifyRoutine的地址 for(i=pCheckArea;i<pCheckArea+0xff;i++) { if(*(PUCHAR)i==0x4c && *(PUCHAR)(i+1)==0x8d && *(PUCHAR)(i+2)==0x35) //lea r14,xxxx { LONG OffsetAddr=0; memcpy(&OffsetAddr,(PUCHAR)(i+3),4); return OffsetAddr+7+i; } } return 0; }void EnumCreateProcessNotify() { int i=0; BOOLEAN b; ULONG64 NotifyAddr=0,MagicPtr=0; ULONG64 PspCreateProcessNotifyRoutine=FindPspCreateProcessNotifyRoutine(); DbgPrint("PspCreateProcessNotifyRoutine: %llx",PspCreateProcessNotifyRoutine); if(!PspCreateProcessNotifyRoutine) return; for(i=0;i<64;i++) { MagicPtr=PspCreateProcessNotifyRoutine+i*8; NotifyAddr=*(PULONG64)(MagicPtr); if(MmIsAddressValid((PVOID)NotifyAddr) && NotifyAddr!=0) { NotifyAddr=*(PULONG64)(NotifyAddr & 0xfffffffffffffff8); DbgPrint("[CreateProcess]%llx",NotifyAddr); } } }


線程(包括創(chuàng)建線程回調(diào)測(cè)試代碼):

?

?

void CreateThreadNotify1 (IN HANDLE ProcessId,IN HANDLE ThreadId,IN BOOLEAN Create ) { DbgPrint("CreateThreadNotify1\n"); }void CreateThreadNotify2 (IN HANDLE ProcessId,IN HANDLE ThreadId,IN BOOLEAN Create ) { DbgPrint("CreateThreadNotify2\n"); }void CreateThreadNotifyTest(BOOLEAN Remove) { if(!Remove) { PsSetCreateThreadNotifyRoutine(CreateThreadNotify1); PsSetCreateThreadNotifyRoutine(CreateThreadNotify2); } else { PsRemoveCreateThreadNotifyRoutine(CreateThreadNotify1); PsRemoveCreateThreadNotifyRoutine(CreateThreadNotify2); } }ULONG64 FindPspCreateThreadNotifyRoutine() { ULONG64 i=0,pCheckArea=0; UNICODE_STRING unstrFunc; RtlInitUnicodeString(&unstrFunc, L"PsSetCreateThreadNotifyRoutine"); pCheckArea = (ULONG64)MmGetSystemRoutineAddress (&unstrFunc); DbgPrint("PsSetCreateThreadNotifyRoutine: %llx",pCheckArea); for(i=pCheckArea;i<pCheckArea+0xff;i++) { if(*(PUCHAR)i==0x48 && *(PUCHAR)(i+1)==0x8d && *(PUCHAR)(i+2)==0x0d) //lea rcx,xxxx { LONG OffsetAddr=0; memcpy(&OffsetAddr,(PUCHAR)(i+3),4); return OffsetAddr+7+i; } } return 0; }void EnumCreateThreadNotify() { int i=0; BOOLEAN b; ULONG64 NotifyAddr=0,MagicPtr=0; ULONG64 PspCreateThreadNotifyRoutine=FindPspCreateThreadNotifyRoutine(); DbgPrint("PspCreateThreadNotifyRoutine: %llx",PspCreateThreadNotifyRoutine); if(!PspCreateThreadNotifyRoutine) return; for(i=0;i<64;i++) { MagicPtr=PspCreateThreadNotifyRoutine+i*8; NotifyAddr=*(PULONG64)(MagicPtr); if(MmIsAddressValid((PVOID)NotifyAddr) && NotifyAddr!=0) { NotifyAddr=*(PULONG64)(NotifyAddr & 0xfffffffffffffff8); DbgPrint("[CreateThread]%llx",NotifyAddr);PsRemoveCreateThreadNotifyRoutine(NotifyAddr); } } }

宋孖健,13

?

?

?

?

總結(jié)

以上是生活随笔為你收集整理的Win64 驱动内核编程-30.枚举与删除线程回调的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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