ProcessHider Utilization Analysis

Onedaysec
3 min read
3 views
ProcessHider Utilization Analysis — One Day Sec default thumbnail

0x00 Preface

---

ProcessHider can hide specified processes in monitoring tools such as Task Manager and Process Explorer. This article will introduce its implementation principles and analyze code details.

0x01 Introduction

---

This article will cover the following:

  • ProcessHider Testing
  • Implementation Principles of ProcessHider
  • Code Analysis of ProcessHider
  • Detection of ProcessHider

0x01 Introduction

---

ProcessHider can hide specified processes in monitoring tools such as Task Manager and Process Explorer

The address is as follows:

https://github.com/M00nRise/ProcessHider

Supports the following parameters:

  • pid
  • process name

Two startup forms:

  • exe
  • powershell

ProcessHider can automatically identify the operating system version and process bitness, inject Payload.dll into 32-bit and 64-bit processes respectively, and achieve process hiding by hooking the API NtQuerySystemInformation()

The injected code uses DLL reflection, address as follows:

https://github.com/stephenfewer/ReflectiveDLLInjection

The hook code uses NtHookEngine, address as follows:

https://www.codeproject.com/Articles/21414/Powerful-x86-x64-Mini-Hook-Engine

Parameter example:

ProcessHider.exe -n "putty.exe" -x "procexp.exe"

Can hide the process named putty.exe in procexp.exe, and by default hides the following processes:

  • Taskmgr.exe
  • powershell.exe
  • procexp.exe
  • procexp64.exe
  • perfmon.exe

Note:

Currently, hiding the tasklist.exe process is not supported

Issues to note during compilation:

The ProcessHider project must be compiled as 32-bit, not 64-bit

This is because the ProcessHider project includes code for identifying and exploiting 64-bit processes

0x02 Implementation Principle of ProcessHider

---

The implementation flow of the ProcessHider project is as follows:

1. Determine the current operating system version

Corresponding code isSystem64BitWow()

For 32-bit systems:

(1) Monitor process list

Corresponding code: LaunchDaemon(InjectAll);

(2) Inject Payload.dll into eligible processes

Corresponding code: reactToProcess((DWORD) pCurrent->ProcessId, pCurrent->ImageName.Buffer);

The injection code uses code from ReflectiveDLLInjection

For 64-bit systems:

(1) Release file x64Hider.exe in the same directory, used as a 64-bit daemon process

Corresponding code: CopyResourceIntoFile(x64filesList[i], MAKEINTRESOURCE(x64resourceIDint[i])

(2) Parse command line parameters

Corresponding code: createCommandLine(argc, argv, buffer, MAX_COMMANDLINE_LEN);

(3) Start the 64-bit daemon process x64Hider.exe

Corresponding code: CreateProcessFromLine(buffer,false);

Pass startup parameters

Example as follows:

"c:\test\x64Hider.exe" "-n" "putty.exe" "-x" "cmd.exe"

(4) Write Payload.dll into the process space of x64Hider.exe

This process does not write files to the hard disk, increasing stealth

Corresponding code: WriteDLLsToProcess(pi)

The functions of x64Hider.exe are as follows:

  1. Monitor the 64-bit process list
  2. Inject 64-bit Payload.dll into eligible 64-bit processes

(5) Monitor the 32-bit process list

Corresponding code: LaunchDaemon(InjectAll);

(6) Inject 32-bit Payload.dll into eligible 32-bit processes

Corresponding code: reactToProcess((DWORD) pCurrent->ProcessId, pCurrent->ImageName.Buffer);

Payload.dll corresponds to the projects x64Payload and x86Payload respectively

This is based on ReflectiveDLLInjection for DLL reflection

The advantage is that after successful injection, the DLL name does not exist in the process space

The process is as follows:

1. Create mutex

Corresponding code: hMutex = CreateMutex(0, TRUE, NULL);

2. Read parameters

If parameters are empty, read parameters from the fixed file "C:\Program Files\Internet Explorer\mdsint.isf"

3. Hook API NtQuerySystemInformation()

Code for hiding processes:

NTSTATUS WINAPI HookedNtQuerySystemInformation(
__in SYSTEM_INFORMATION_CLASS SystemInformationClass,
__inout PVOID SystemInformation,
__in ULONG SystemInformationLength,
__out_opt PULONG ReturnLength
)
{
NTSTATUS status = RealNTQueryFunc(SystemInformationClass,
SystemInformation,
SystemInformationLength,
ReturnLength);

if (SystemProcessInformation == SystemInformationClass && NT_SUCCESS(status))
{
//
// Loop through the list of processes
//

PSYSTEM_PROCESS_INFO pCurrent = NULL;
PSYSTEM_PROCESS_INFO pNext = (PSYSTEM_PROCESS_INFO)SystemInformation;

do
{
pCurrent = pNext;
pNext = (PSYSTEM_PROCESS_INFO)((PUCHAR)pCurrent + pCurrent->NextEntryOffset);

if (isHiddenProcess((int)pNext->ProcessId,pNext->ImageName.Buffer))
{
if (0 == pNext->NextEntryOffset)
{
pCurrent->NextEntryOffset = 0;
}
else
{
pCurrent->NextEntryOffset += pNext->NextEntryOffset;
}

pNext = pCurrent;
}
} while (pCurrent->NextEntryOffset != 0);
}

return status;
}

This code is essentially identical to the previously open-sourced AppInitGlobalHooks-Mimikatz code from SubTee.

I introduced in a previous article 'Hiding Processes on Windows 7 Using Global API Hooks'

SubTee's GitHub is currently inaccessible, but I forked his code at the time, the address is as follows:

An open-source project

Therefore, we can achieve the same functionality using the previous code

1. Compile the DLL

Using the code:

An open-source project

Compile to generate the DLL

2. Inject the DLL

Here you can use the DLL injection code I wrote earlier, the address is as follows:

An open-source project

But the functionality of FreeDll() needs to be removed

In summary, the implementation principle of ProcessHider is as follows:

By injecting a DLL to hook the API NtQuerySystemInformation(), process hiding is achieved

0x03 Detection of ProcessHider

---

The detection primarily identifies the following behaviors:

  • DLL injection
  • Hook API NtQuerySystemInformation()

0.04 Summary

---

This article introduces the implementation principles and code details of ProcessHider, analyzes exploitation approaches, and provides detection recommendations.

Related Questions & Answers

What methods can be used to detect ProcessHider activity?

Detection focuses on identifying DLL injection and API hooking. Monitoring for unexpected DLLs loaded into processes and checking for hooks on NtQuerySystemInformation() are key. Security tools can also look for reflective DLL injection artifacts and unusual process creation, such as the appearance of x64Hider.exe. The [ProcessHider Utilization Analysis](/news/processhider-utilization-analysis) provides additional detection recommendations.

How does ProcessHider handle process hiding on 64-bit Windows systems?

On 64-bit systems, ProcessHider releases and starts a separate 64-bit daemon process named x64Hider.exe. This daemon monitors 64-bit processes and injects a 64-bit Payload.dll using reflective DLL injection, while the main 32-bit ProcessHider handles 32-bit processes. This dual-process approach ensures both 32-bit and 64-bit targets are effectively hooked.

Why must ProcessHider be compiled as a 32-bit application?

ProcessHider must be compiled as 32-bit because it includes code to identify and inject into both 32-bit and 64-bit processes. On 64-bit systems, it spawns a 64-bit daemon (x64Hider.exe) to inject 64-bit payloads, but the main binary's compatibility relies on being 32-bit. This design ensures all target processes can be hooked regardless of bitness.

How does ProcessHider hide processes from monitoring tools like Task Manager?

ProcessHider achieves process hiding by injecting a payload DLL into target processes, which hooks the Windows API NtQuerySystemInformation(). This API is used by tools like Task Manager and Process Explorer to enumerate processes; the hook filters out specified processes from the returned list, making them invisible. For full technical details, see the [ProcessHider Utilization Analysis](/news/processhider-utilization-analysis).

Continue Reading