| 79 | } |
| 80 | |
| 81 | ULONG KernelTimer::GetKernelTimerCount(KernelTimerData* pData) { |
| 82 | PULONG_PTR KiProcessorBlock = (PULONG_PTR)pData->pKiProcessorBlock; |
| 83 | ULONG k = 0; |
| 84 | |
| 85 | #ifdef _WIN64 |
| 86 | Helpers::KiWaitAlways = *(ULONG_PTR*)pData->pKiWaitAlways; |
| 87 | Helpers::KiWaitNever = *(ULONG_PTR*)pData->pKiWaitNever; |
| 88 | #endif // _WIN64 |
| 89 | ULONG maxCount = pData->maxEntryCount; |
| 90 | ULONG tableOffset = pData->tableOffset; |
| 91 | ULONG entriesOffset = pData->entriesOffset; |
| 92 | |
| 93 | for (KAFFINITY i = 0; i < KeNumberProcessors; i++) { |
| 94 | ULONG_PTR kprcbAddr = KiProcessorBlock[i]; |
| 95 | ULONG_PTR tableAddr = kprcbAddr + tableOffset; |
| 96 | ULONG_PTR entriesAddr = tableAddr + entriesOffset; |
| 97 | PKTIMER_TABLE_ENTRY pTableEntry = (PKTIMER_TABLE_ENTRY)entriesAddr; |
| 98 | if (!MmIsAddressValid(pTableEntry)) { |
| 99 | continue; |
| 100 | } |
| 101 | for (int j = 0; j < maxCount; j++) { |
| 102 | PLIST_ENTRY pListHead = &pTableEntry[j].Entry; |
| 103 | |
| 104 | for (PLIST_ENTRY pListEntry = pListHead->Flink; pListEntry != pListHead; pListEntry = pListEntry->Flink) { |
| 105 | if (!MmIsAddressValid(pListEntry)) |
| 106 | break; |
| 107 | PKTIMER pTimer = CONTAINING_RECORD(pListEntry, KTIMER, TimerListEntry); |
| 108 | #ifdef _WIN64 |
| 109 | ULONG_PTR salt = (ULONG_PTR)pTimer; |
| 110 | PKDPC pKDpc = (PKDPC)Helpers::KiDecodePointer((ULONG_PTR)pTimer->Dpc, salt); |
| 111 | if (!MmIsAddressValid(pKDpc)) |
| 112 | continue; |
| 113 | k++; |
| 114 | #else |
| 115 | if (!MmIsAddressValid(pTimer->Dpc)) { |
| 116 | continue; |
| 117 | } |
| 118 | k++; |
| 119 | #endif // _WIN64 |
| 120 | } |
| 121 | } |
| 122 | } |
| 123 | |
| 124 | LogInfo("Total Kernel Timer: %d\n", k); |
| 125 | return k; |
| 126 | } |