r77-rootkit
r77-rootkit copied to clipboard
Hide CPU Usage Not Fully Work
It works at the details column on task manager,but at Processes,Users and Performance columns of task manager,the cpu usage remains intact.Tested On Windows 10. SystemProcessorPerformanceInformation and SystemProcessorIdleCycleTimeInformation never gets triggered
Yeah... I'm actually aware of this issue and documented it in section 5.4 Known Issues. Most notably is that different task managers use different routines to check CPU usage. I managed to hide CPU usage in procmon and ProcessHacker, but not in TaskMgr and PerformanceMonitor.
If I only knew, which API calls those are, I would probably also solve #7 (hiding GPU usage).
In the past, I did some blackbox testing with TaskMgr and checked various ntdll functions that were actually imported. Some of them were called, but no matter what random data I have replaced the returned data with, it didn't change the graph at all - which means I did not hook the right function.
So, starting at square one - do you or anybody who reads this have any ideas or contributions to solve this long lasting issue? I would certainly credit anybody who helps to fix bugs, even if they just know what the correct function is to hook.
I wish I know since the same problem has bothered me for years. I wonder if it uses pdh counter data coz taskmgr loads pdh.dll,need to test it.
Glad to hear I'm not alone...
I still have the test code that I used to find the correct function to hook. These are ones that I tried:
- PerfQueryCounterData
- PdhGetRawCounterArrayW
- PdhGetFormattedCounterArrayW
- PdhGetFormattedCounterValue
- PdhGetRawCounterValue
- PdhCollectQueryData
- PdhCollectQueryDataEx
- PdhCollectQueryDataWithTime
- NtQueryPerformanceCounter
- HookedNtQuerySystemInformation
- SystemProcessorPerformanceDistribution
- SystemBasicPerformanceInformation
- SystemQueryPerformanceCounterInformation
- SystemProcessorPerformanceInformationEx
- SystemCpuQuotaInformation
- SystemCpuSetInformation
- SystemCpuSetTagInformation
I didn't bother to try and hook HKEY_PERFORMANCE_DATA
, because I assume that TaskMgr uses WinAPI instead of this pseudo registry hive.
And to share my notes with you: TaskMgr calls NtQuerySystemInformationEx
with SystemLogicalProcessorAndGroupInformation
and SystemProcessorCycleTimeInformation
, so I tried to set those to zero or random values, with no effect.
I have also disassembled some functions of TaskMgr and everything seems to point to PDH. That's why my testing with PDH was so extensive... I even searched for examples on how to get CPU usage using PDH to get an idea of how this library is actually used.
LONG GetCPUUsage() { HQUERY hQuery; char CPUUsage[] = "\Processor(_Total)\% Processor Time"; HCOUNTER hCounter; PDH_FMT_COUNTERVALUE fmtValue; DWORD ctrType;
if (PdhOpenQuery(0,0,&hQuery) == ERROR_SUCCESS) { if (PdhAddCounter(hQuery,CPUUsage,0,&hCounter) == ERROR_SUCCESS) { if (PdhCollectQueryData(hQuery) == ERROR_SUCCESS) { Sleep(1000); if (PdhCollectQueryData(hQuery) == ERROR_SUCCESS) { if (PdhGetFormattedCounterValue(hCounter,PDH_FMT_LONG,&ctrType,&fmtValue) == ERROR_SUCCESS) { PdhCloseQuery(hQuery); return fmtValue.longValue; } else { printf("Fail To Format Value %d %d\n",GetLastError(),fmtValue.longValue); } } } else { printf("Fail To Collect Data\n"); } } else { printf("Fail To Open Query\n"); } PdhCloseQuery(hQuery); } return -1; }
the return value is the cpu usage.if it uses pdh,it's fine;I am afraid it uses WMI,it would be hard to hook
In issue #9 I have found out that AIDA64 is using WMI to populate process lists and that injecting WmiPrvSE.exe
is required. This works automagically, because the WMI service is just using the same NtQuerySystemInformation
that every application uses.
But about CPU usage... The thing is, during my tests, I only injected TaskMgr.exe
and didn't bother to inject WmiPrvSE.exe
with my test code. Maybe I should hook the PDH methods again and inject the WMI service and see what happens.
wish it works out
look like pdh getting the gpu stuff,but not cpu usage
Interesting... what tool is this?
TaskMgr (Windows 11) definitely calls PdhGetFormattedCounterArrayW
and PdhCollectQueryData
.
But when fuzzing this function with random values, it does not change anything in the UI - even when injecting all processes. Let me keep looking...
static PDH_STATUS WINAPI HookedPdhGetFormattedCounterArrayW(PDH_HCOUNTER hCounter, DWORD dwFormat, LPDWORD lpdwBufferSize, LPDWORD lpdwItemCount, PPDH_FMT_COUNTERVALUE_ITEM_W ItemBuffer)
{
//TaskMgr calls this (*lpdwItemCount == 285)
PDH_STATUS status = OriginalPdhGetFormattedCounterArrayW(hCounter, dwFormat, lpdwBufferSize, lpdwItemCount, ItemBuffer);
if (status == ERROR_SUCCESS)
{
for (DWORD i = 0; i < *lpdwItemCount; i++)
{
ItemBuffer[i].FmtValue.longValue = GetTickCount64() % 100;
ItemBuffer[i].FmtValue.doubleValue = (GetTickCount64() % 1000) / 1000.0;
ItemBuffer[i].FmtValue.largeValue = GetTickCount64();
//ItemBuffer[i].FmtValue.AnsiStringValue = "ABC";
//ItemBuffer[i].FmtValue.WideStringValue = L"XYZ";
}
}
return status;
}
the tool is dbgview,just showing the debug output taskmgr calls pdh api,but the query is all about gpu stuff PdhGetFormattedCounterArrayW will handle the "\GPU Engine(*)\Utilization Percentage" query value.If you hook PdhAddCounterW and save the counter handle,and comparing the counter handle from PdhGetFormattedCounterArrayW call.
chatgpt is very certain taskmgr using WMI to get the cpu usage,but I still doubt it.I hooked PdhGetFormattedCounterValue PdhGetRawCounterValue PdhGetFormattedCounterArrayA PdhGetFormattedCounterArrayW PdhGetRawCounterArrayA PdhGetRawCounterArrayW
doesn't find any query about cpu usage
I spent some time playing with PDH. So far, I have successfully hidden GPU usage, which was on the ToDo list for 2 years. I have commited my work in progress on this branch: https://github.com/bytecode77/r77-rootkit/tree/PDH
I hooked both PdhGetRawCounterArrayW
and PdhGetFormattedCounterArrayW
, checking for these weird "\GPU Engine(*)" strings. The item array contains strings like "pid_1234_luid_0x00000000_0x0000C9DE_phys_0_eng_0_engtype_3D", so I parse the PID from that string.
This is either the wrong way to go about it - or PDH is just string cancer. I don't know yet, but I'm sharing my code with you as it contains working PDH hooks. Another issue except the excessive string use is that I would really like to see some NtQuery...
function to hook instead of this higher level PDH.dll.
... In the meantime, I'll do some more research about the CPU usage.
I tested GetSystemTimes(),doesn't use this API to get cpu usage as well.
GetSystemTimes
calls NtQuerySystemInformation
with SystemProcessorPerformanceInformation
, which is what Process Hacker is using to retrieve the CPU usage. There is a hook in place.
I now know which API is used for both CPU and GPU stats. It's PcwCollectData
, which is completely undocumented. Internally, it calls the driver pcw.sys
by calling NtDeviceIoControlFile
with \Device\PcwDrv
and IOCTL 0x224013
.
I'm already hooking NtDeviceIoControlFile
to filter the TCPView table, which was a completely undocumented blackbox as well. Next, I'm going to figure out the PCW driver, so wish me luck...
Here's an excerpt of what the driver returns, which obviously resembles PPDH_COUNTER_INFO_W
. Other binaries seem to be related to CPU usage.
pretty much like the gpu stuff,and good luck
GetProcessTimes API get called a lot
PcwCollectData seem to be native call of pdhcollectquerydata
So, being busy reverse engineering PDH, I have figured out how to hide GPU usage and released version 1.5.1 with that feature. I have implemented the hook in pdh.dll
, not NtDeviceIoControlFile
, because I couldn't reverse engineer the exact format of the data that the PCW driver returns.
CPU usage is still not fixed, but I'm at least closer, because I know more about the PWC driver now. I'll pick up on that sometime next.
good to know
something not about the cpu usage hiding but PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY.when r77 rootkit is installed,no doubt creating new process with PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY still get injected because r77 rookit interrupts the ntresumethread call,and inject the dll before the newer created process even starts.However,I create a process with PROCESS_CREATION_MITIGATION_POLICY_BLOCK_NON_MICROSOFT_BINARIES_ALWAYS_ON before running the install.exe,the process still get injected,I wonder why.
Maybe the reflective injection only inject codes other than pe files so it bypasses the check?
I can't find out anything useful about that "PROCESS_CREATION_MITIGATION_POLICY_BLOCK_NON_MICROSOFT_BINARIES_ALWAYS_ON
", except that it's used in UpdateProcThreadAttribute
prior to a call to CreateProcess
. Since I never had any problems injecting processes, I didn't stumpble upon this value. Only problem I had is with services.exe, which is just impossible to inject, because it's protected.
a process with PROCESS_CREATION_MITIGATION_POLICY_BLOCK_NON_MICROSOFT_BINARIES_ALWAYS_ON set supposes to block 3rd party module injection but with Microsoft digital signature.If I inject the r77's dll with normal injection,some error windows will pop up,but it's ok using reflective injection.I assume this mechanism needs to check file for the signature,no file then no check.
Does this "Bad Image" error ocurr when you inject using a normal injector, or does it also happen when using the reflective loader (Test Console / full installation) ?
By the way, while I was working on the initial release in 2020, I only had a normal injector before I implemented the reflective injector. At least back then there were no issues injecting into any process. So I assume it's a new security measure.
that error won't occur using test console/full installation.As long as the injection won't involve dll file on disk,no error shows up.