x64枚举DPC定时器
                                                            生活随笔
收集整理的這篇文章主要介紹了
                                x64枚举DPC定时器
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.                        
                                
                            
                            
                            @寫在前面
? ???不同于x86,x64的DPC是被加密了的。對于x64DPC的興趣始于我已經流產的scalpel計劃。當時問某牛怎么遍歷,得到的答案是“500大洋給代碼”。真是R了狗了,好歹小哥我也是搞技術的,自己搞吧。
PS:這個代碼編輯功能。。。醉的不行了。
@前言
? ???在早期的x86系統上面,DPCTimer都是裸奔的,直接用過已導出的KiTimerTableListHead就可以遍歷,網上的枚舉資料也是一大把。但是等DPC被加密之后,突然就沒有資料了(資料約等于拿來直接F7的代碼)。So,搞起。
? ? ? ? 簡單整理下思路,枚舉DPC可以分為兩道工序:
1.? ? ? ? 找到x64的”KiTimerTableListHead”
2.? ? ? ? 把加密了的DPC進行解密
PS:其實PG_Disable里面有代碼的,奈何從來沒人說過啊。。。
@找到x64的” KiTimerTableListHead”
? ?? ? 翻翻以前的資料,在早期的windows中導出了一個名為“KiTimerTableListHead”的神奇東西,直接就可以遍歷DPC定時器。但是到了win7 x64上面,符號表抹去了這個可憐的小家伙。因此我們需要找一條新的道路來找到所有的DPC定時器。
? ?? ?參考論壇里的一個帖子:http://bbs.pediy.com/showthread.php?t=148135
? ?? ?枚舉DPC的新路線就是:_KPRCB->_KTIMER->_KDPC
? ?? ?先簡單說一下_KPRCB,這個結構體是與CPU的核心對應的,一個核心對應一個。獲取方法以及判斷數量的方法,都可以通過一個未導出的變量nt!KiProcessorBlock來獲取:
? ?? ?KiProcessorBlock就是一個數組,數組里有幾個元素就是CPU有幾個核心and每個元素對應一個_KPRCB的結構體。
? ?? ?這個結構體實在有點大,其他的我們都不關心,只需要看offset在0x2200處的TimerTable就行了。
? ?? ?接下來是把所有的KTIMER都枚舉出來。KTIMER在TimerTable中的存儲方式是:數組+雙向鏈表。
 ? ? ? ? 
? ? ? ? 到了_KTIMER_TABLE_ENTRY這里,Entry開始的雙向鏈表,每一個元素都對應一個Timer,也就是說我們已經可以愉快的遍歷所有未解密的Timer了。
@愉快的解密DPC
? ?? ?想找解密代碼,最好的辦法就是去找到他是怎么加密的。So,我們跟蹤一下KeSetTimer的流程就好了。
? ?? ?流程就是:KeSetTimer/KeSetTimerEx->KiSetTimerEx->加密DPC。
? ?? ?OK,這坨蛋疼的x64匯編我就不多說了。看不懂的拖進ida然后f5。如果還是看不懂,就看我下面的代碼。(其實就是把待加密的DPC用KTimer、KiWaitNever和KiWaitAlways進行異或操作,中間再進行一些ror,bswap的位移操作。)
@寫一下代碼自己擼個痛快
代碼里沒有過多的注釋,上面的看懂了,這個代碼看一眼就行。
里面的三個未導出符號的獲取,可以通過PDB或者硬編碼
@最后
? ?? ?其實很簡單,奈何沒人說啊,寫個帖子也當是給自己做個筆記了吧。
? ?? ?最后鳴謝:論壇若干DPC科普貼 and PG_Disable.
Ps:其實還是愉快的做伸手黨舒服啊。。。
                        
                        
                        ? ???不同于x86,x64的DPC是被加密了的。對于x64DPC的興趣始于我已經流產的scalpel計劃。當時問某牛怎么遍歷,得到的答案是“500大洋給代碼”。真是R了狗了,好歹小哥我也是搞技術的,自己搞吧。
PS:這個代碼編輯功能。。。醉的不行了。
@前言
? ???在早期的x86系統上面,DPCTimer都是裸奔的,直接用過已導出的KiTimerTableListHead就可以遍歷,網上的枚舉資料也是一大把。但是等DPC被加密之后,突然就沒有資料了(資料約等于拿來直接F7的代碼)。So,搞起。
? ? ? ? 簡單整理下思路,枚舉DPC可以分為兩道工序:
1.? ? ? ? 找到x64的”KiTimerTableListHead”
2.? ? ? ? 把加密了的DPC進行解密
PS:其實PG_Disable里面有代碼的,奈何從來沒人說過啊。。。
@找到x64的” KiTimerTableListHead”
? ?? ? 翻翻以前的資料,在早期的windows中導出了一個名為“KiTimerTableListHead”的神奇東西,直接就可以遍歷DPC定時器。但是到了win7 x64上面,符號表抹去了這個可憐的小家伙。因此我們需要找一條新的道路來找到所有的DPC定時器。
? ?? ?參考論壇里的一個帖子:http://bbs.pediy.com/showthread.php?t=148135
? ?? ?枚舉DPC的新路線就是:_KPRCB->_KTIMER->_KDPC
? ?? ?先簡單說一下_KPRCB,這個結構體是與CPU的核心對應的,一個核心對應一個。獲取方法以及判斷數量的方法,都可以通過一個未導出的變量nt!KiProcessorBlock來獲取:
| 1 2 3 4 5 6 7 8 9 | kd> dq nt!KiProcessorBlock fffff800`040fd900? [COLOR="red"]fffff800`0403ee80[/COLOR] 00000000`00000000 fffff800`040fd910? 00000000`00000000 00000000`00000000 fffff800`040fd920? 00000000`00000000 00000000`00000000 fffff800`040fd930? 00000000`00000000 00000000`00000000 fffff800`040fd940? 00000000`00000000 00000000`00000000 fffff800`040fd950? 00000000`00000000 00000000`00000000 fffff800`040fd960? 00000000`00000000 00000000`00000000 fffff800`040fd970? 00000000`00000000 00000000`00000000 | 
? ?? ?KiProcessorBlock就是一個數組,數組里有幾個元素就是CPU有幾個核心and每個元素對應一個_KPRCB的結構體。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | kd> dt _KPRCB fffff800`0403ee80 ntdll!_KPRCB ???+0x000 MxCsr??????????? : 0x1f80 ???+0x004 LegacyNumber???? : 0 '' ???+0x005 ReservedMustBeZero : 0 '' ???+0x006 InterruptRequest : 0 '' ???+0x007 IdleHalt???????? : 0x1 '' ???+0x008 CurrentThread??? : 0xfffff800`0404ccc0 _KTHREAD ???+0x010 NextThread?????? : (null) ?……….. ???[COLOR="Red"]+0x2200 TimerTable?????? : _KTIMER_TABLE[/COLOR] ???+0x4400 DpcGate????????? : _KGATE ???+0x4418 PrcbPad52??????? : (null) ?………… | 
? ?? ?這個結構體實在有點大,其他的我們都不關心,只需要看offset在0x2200處的TimerTable就行了。
? ?? ?接下來是把所有的KTIMER都枚舉出來。KTIMER在TimerTable中的存儲方式是:數組+雙向鏈表。
| 1 2 3 4 | kd> dt _KTIMER_TABLE fffff800`0403ee80+0x2200 ntdll!_KTIMER_TABLE ???+0x000 TimerExpiry????? : [64] (null) ???[COLOR="red"]+0x200 TimerEntries???? : [256] _KTIMER_TABLE_ENTRY[/COLOR] | 
| 1 2 3 4 5 | kd> dt _KTIMER_TABLE_ENTRY fffff800`0403ee80+0x2200+0x200 ntdll!_KTIMER_TABLE_ENTRY ???+0x000 Lock???????????? : 0 ???[COLOR="red"]+0x008 Entry??????????? : _LIST_ENTRY [ 0xfffff800`04041288 - 0xfffff800`04041288 ][/COLOR] ???+0x018 Time???????????? : _ULARGE_INTEGER 0xffffffff`9cac3e4d | 
? ? ? ? 到了_KTIMER_TABLE_ENTRY這里,Entry開始的雙向鏈表,每一個元素都對應一個Timer,也就是說我們已經可以愉快的遍歷所有未解密的Timer了。
@愉快的解密DPC
? ?? ?想找解密代碼,最好的辦法就是去找到他是怎么加密的。So,我們跟蹤一下KeSetTimer的流程就好了。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | kd> u nt!KeSetTimer nt!KeSetTimer: fffff800`03ed80a8 4883ec38??????? sub???? rsp,38h fffff800`03ed80ac 4c89442420????? mov???? qword ptr [rsp+20h],r8 fffff800`03ed80b1 4533c9????????? xor???? r9d,r9d fffff800`03ed80b4 4533c0????????? xor???? r8d,r8d [COLOR="red"]fffff800`03ed80b7 e814000000????? call??? nt!KiSetTimerEx (fffff800`03ed80d0)[/COLOR] fffff800`03ed80bc 4883c438??????? add???? rsp,38h fffff800`03ed80c0 c3????????????? ret fffff800`03ed80c1 90????????????? nop kd> u nt!KiSetTimerEx l20 nt!KiSetTimerEx: fffff800`03ed80d0 48895c2408????? mov???? qword ptr [rsp+8],rbx fffff800`03ed80d5 4889542410????? mov???? qword ptr [rsp+10h],rdx fffff800`03ed80da 55????????????? push??? rbp fffff800`03ed80db 56????????????? push??? rsi fffff800`03ed80dc 57????????????? push??? rdi fffff800`03ed80dd 4154??????????? push??? r12 fffff800`03ed80df 4155??????????? push??? r13 fffff800`03ed80e1 4156??????????? push??? r14 fffff800`03ed80e3 4157??????????? push??? r15 fffff800`03ed80e5 4883ec50??????? sub???? rsp,50h [COLOR="red"]fffff800`03ed80e9 488b0518502200? mov???? rax,qword ptr [nt!KiWaitNever (fffff800`040fd108)] fffff800`03ed80f0 488b1de9502200? mov???? rbx,qword ptr [nt!KiWaitAlways (fffff800`040fd1e0)] fffff800`03ed80f7 4c8bb424b0000000 mov???? r14,qword ptr [rsp+0B0h] fffff800`03ed80ff 4933de????????? xor???? rbx,r14 fffff800`03ed8102 488bf1????????? mov???? rsi,rcx[/COLOR] fffff800`03ed8105 450fb6f9??????? movzx?? r15d,r9b [COLOR="red"]fffff800`03ed8109 480fcb????????? bswap?? rbx[/COLOR] fffff800`03ed810c 418bf8????????? mov???? edi,r8d [COLOR="red"]fffff800`03ed810f 4833d9????????? xor???? rbx,rcx fffff800`03ed8112 8bc8??????????? mov???? ecx,eax fffff800`03ed8114 48d3cb????????? ror???? rbx,cl fffff800`03ed8117 4833d8????????? xor???? rbx,rax[/COLOR] fffff800`03ed811a 450f20c4??????? mov???? r12,cr8 fffff800`03ed811e b802000000????? mov???? eax,2 fffff800`03ed8123 440f22c0??????? mov???? cr8,rax fffff800`03ed8127 65488b2c2520000000 mov?? rbp,qword ptr gs:[20h] fffff800`03ed8130 33d2??????????? xor???? edx,edx fffff800`03ed8132 488bce????????? mov???? rcx,rsi fffff800`03ed8135 e88ae6ffff????? call??? nt!KiCancelTimer (fffff800`03ed67c4) [COLOR="red"]fffff800`03ed813a 48895e30??????? mov???? qword ptr [rsi+30h],rbx[/COLOR] fffff800`03ed813e 488b9c2498000000 mov???? rbx,qword ptr [rsp+98h] fffff800`03ed8146 440fb6e8??????? movzx?? r13d,al | 
? ?? ?流程就是:KeSetTimer/KeSetTimerEx->KiSetTimerEx->加密DPC。
? ?? ?OK,這坨蛋疼的x64匯編我就不多說了。看不懂的拖進ida然后f5。如果還是看不懂,就看我下面的代碼。(其實就是把待加密的DPC用KTimer、KiWaitNever和KiWaitAlways進行異或操作,中間再進行一些ror,bswap的位移操作。)
@寫一下代碼自己擼個痛快
代碼里沒有過多的注釋,上面的看懂了,這個代碼看一眼就行。
里面的三個未導出符號的獲取,可以通過PDB或者硬編碼
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | #include<ntddk.h> typedefstruct_KTIMER_TABLE_ENTRY { ????ULONG_PTR?? Lock; ????LIST_ENTRY? Entry; ????ULONG_PTR?? Time; }KTIMER_TABLE_ENTRY, *PKTIMER_TABLE_ENTRY; #defineKTIMER_TABLE_ENTRY_MAX?? (256) typedefstruct_KTIMER_TABLE { ????ULONG_PTR?????????? TimerExpiry[64]; ????KTIMER_TABLE_ENTRY? TimerEntries[KTIMER_TABLE_ENTRY_MAX]; }KTIMER_TABLE, *PKTIMER_TABLE; ULONG_PTR?????? ptrKiProcessorBlock???? = 0; ULONG_PTR?????? ptrOffsetKTimerTable??? = 0; ULONG_PTR?????? ptrKiWaitNever????????? = 0; ULONG_PTR?????? ptrKiWaitAlways???? = 0; int???????????? nTotalCount???????? = 0; #definep2dq(x)? (*((ULONG_PTR*)x)) void DPC_Print(PKTIMERptrTimer) { ????ULONG_PTR?? ptrDpc? = (ULONG_PTR)ptrTimer->Dpc; ????KDPC*?????? DecDpc? = NULL; ????int???????? nShift? = (p2dq(ptrKiWaitNever) & 0xFF); ????//_RSI->Dpc = (_KDPC *)v19; ????//_RSI = Timer; ????ptrDpc ^= p2dq(ptrKiWaitNever);//v19 = KiWaitNever ^ v18; ????ptrDpc = _rotl64(ptrDpc, nShift);//v18 = __ROR8__((unsigned __int64)Timer ^ _RBX, KiWaitNever); ????ptrDpc ^= (ULONG_PTR)ptrTimer; ????ptrDpc = _byteswap_uint64(ptrDpc);//__asm { bswap?? rbx } ????ptrDpc ^= p2dq(ptrKiWaitAlways);//_RBX = (unsigned __int64)DPC ^ KiWaitAlways; ????//real DPC ????if (MmIsAddressValid((PVOID)ptrDpc)) ????{ ????????nTotalCount++; ????????DecDpc = (KDPC*)ptrDpc; ????????DbgPrint("[dpc]dpc:%p,routine:%p\n", DecDpc, DecDpc->DeferredRoutine); ????} } void DPC_Enum() { ????PKTIMER_TABLE?????? ptrKTimerTable????? = 0; ????//PKTIMER_TABLE_ENTRY?? ptrTimerTabEntry??? = NULL; ????PKTIMER???????????? ptrTimer??????????? = NULL; ????PLIST_ENTRY???????? ptrListEntry??????? = NULL; ????PLIST_ENTRY???????? ptrListEntryHead??? = NULL; ????int???????????????? i?????????????? = 0; ????DbgBreakPoint(); ????ptrKTimerTable = (PKTIMER_TABLE)(p2dq(ptrKiProcessorBlock) + ptrOffsetKTimerTable); ????KdPrint(("ptrKTimerTable:%p\n", ptrKTimerTable)); ????for (i = 0; i<KTIMER_TABLE_ENTRY_MAX; i++) ????{ ????????DbgPrint("\n[dpc]ptrTimerTabEntry:%d\n", i); ????????ptrListEntryHead = &(ptrKTimerTable->TimerEntries[i].Entry); ????????for (ptrListEntry = ptrListEntryHead->Flink; ptrListEntry != ptrListEntryHead; ptrListEntry = ptrListEntry->Flink) ????????{ ????????????ptrTimer = CONTAINING_RECORD(ptrListEntry, KTIMER, TimerListEntry); ????????????if (!MmIsAddressValid(ptrTimer))??? ????????????????continue; ????????????if (!ptrTimer->Dpc) ????????????????continue; ????????????DPC_Print(ptrTimer); ????????} ????} ????DbgPrint("TotalDPC:%d\n", nTotalCount); } void DriverUnload(INPDRIVER_OBJECTDriverObject) { } NTSTATUS DriverEntry(INPDRIVER_OBJECTDriverObject, INPUNICODE_STRINGRegistryPath) { ????DriverObject->DriverUnload = DriverUnload; ????ptrKiProcessorBlock???? = 0xfffff800040fd900; ????ptrOffsetKTimerTable??? = 0x2200; ????ptrKiWaitNever????????? = 0xfffff800040fd108; ????ptrKiWaitAlways???? = 0xfffff800040fd1e0; ????DPC_Enum(); ????returnSTATUS_SUCCESS; } | 
@最后
? ?? ?其實很簡單,奈何沒人說啊,寫個帖子也當是給自己做個筆記了吧。
? ?? ?最后鳴謝:論壇若干DPC科普貼 and PG_Disable.
Ps:其實還是愉快的做伸手黨舒服啊。。。
jpg改rar?
轉載于:https://www.cnblogs.com/kuangke/p/9397511.html
總結
以上是生活随笔為你收集整理的x64枚举DPC定时器的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: SpringBoot word文档转pd
- 下一篇: i78700k配什么显卡好_八代i7 8
