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.