Process Hollowing on Windows 11 24H2
Process Hollowing (a.k.a. RunPE) is probably the oldest, and the most popular process impers 2025-1-26 22:16:1 Author: hshrzd.wordpress.com(查看原文) 阅读量:74 收藏

Process Hollowing (a.k.a. RunPE) is probably the oldest, and the most popular process impersonation technique (it allows to run a malicious executable under the cover of a benign process). It is used in variety of PE loaders, PoCs, and offensive tooling. It was also used in one of the demos involving my library, libPEconv. Recently I’ve got a github issue from a user complaining that the demo no longer works on the latest Windows 11, 24H2 . This Windows release was published October 1, 2024, so it is still fresh, but slowly gaining popularity. Searching for the solution I found out, that many people encountered the same problem with different implementations of RunPE, and it is a problem with the technique itself. Still, the answers that I found were not really reaching the root of the problem, so I decided to investigate it deeper. In this short blog I describe my findings, in hopes that it will help other people who experienced the same issue.

The observed symptoms

After the PE was implanted into the newly created, suspended process, we resume the process, and the implant is supposed to load, using the typical Windows loader mechanism. However, when we resume the 64-bit process on Windows 11 24H2, the loading will get interrupted with an error: 0xC0000141.

The root cause

This problem comes from changes that were implemented in the Windows loader. However, unlike some people suspected, it is not related to Control Flow Guard. It turns out the reason is much simpler.

The implementation of Run PE involves loading the payload into the newly allocated memory. Depending on the variant of the technique, it may be implemented in two ways:

  • unmapping the original PE, allocating memory at exactly the same address, and writing the implant there
  • allocating a new memory region, writing the implant there, then setting the new region as a base address of the main module in the PEB structure

In both cases, the new PE is stored in the private memory (MEM_PRIVATE), unlike the normally mapped PE, which will be stored as image (MEM_IMAGE). This is going to make a big difference further on.

During the loading process, the subsequent functions are called:

LdrpInitializeProcess -> LdrpProcessMappedModule -> RtlpInsertOfRemoveScpCfgFunctionTable -> ZwQueryVirtualMemory

The function ZwQueryVirtualMemory is meant to retrieve the properties of each module in memory. It is called with the new argument MemoryImageExtensionInformation that can be used only on images (MEM_IMAGE). Since the implanted PE is not an image, but MEM_PRIVATE, the function will failed will the error (STATUS_INVALID_ADDRESS).

This further causes the loading to terminate with an error.

The solution

There are two approaches with which we can solve this problem:

  1. Use alternative technique, that stores the implant as MEM_IMAGE, instead of MEM_PRIVATE
  2. Patch the NTDLL to bypass the check

Alternative techniques

While RunPE is still the most known and popular process impersonation technique, in the meantime, multiple alternatives evolved, using which we can map our implant as MEM_IMAGE, not as MEM_PRIVATE.

There is a group of techniques that create a section first (using NtCreateSection), and then create the process from the section, using the native API NtCreateProcessEx. This group contains the following techniques:

However, this group of techniques is not as convenient to use as the classic RunPE. It involves filling a lot of structures manually. Another problem is, the process will distinguish itself from the normally created one, since it is created from an unnamed module (GetProcessImageFileName returns an empty string). This does not happen in case of RunPE. So, although they are a nice addition to the arsenal of techniques, they don’t make a perfect replacement of the classic.

With time more options appeared to replace the Run PE. Process Doppelganging and Process Ghosting inspired hybrid techniques, that are closer in their implementation to the Process Hollowing, yet, contain the major improvement of using the PE mapped as MEM_IMAGE. Those hybrids are:

In case of those techniques, GetProcessImageFileName returns the target’s path, and the process resembles more the one that is loaded normally. The payload is mapped as unnamed MEM_IMAGE.

Later, I came up with one more variant of the loader, that would map the payload as named MEM_IMAGE, making it yet more similar to a legitimately loaded PE. Details of the implementation, and comparison to other techniques, can be found in the repository:

  • Process Overwriting [PoC], [FAQ]

According to my latest tests, Transacted/Ghostly Hollowing, as well as Process Overwriting, successfully loaded PEs on Windows 11 24H2, without the need of any additional changes or patches.

Demo (Process Overwriting on Windows 11 24H2):

Patching NTDLL

If, for whatever reason, we insist to use the original RunPE, and run our payload from MEM_PRIVATE, it is still possible to achieve it. However, it will require patching of the function that causes the error (ZwQueryVirtualMemory). Of course we want the patch to have a minimal impact on the rest of the execution, so it has to filter only one particular case when we are making a query about the specific memory region containing our payload.

First, we check if our loaded is running on Windows 11 24H2 or higher, because lower versions don’t have this problem. Also, only the 64-bit processes should be affected.

The functionality of the patch can be described by the following pseudocode:

  • if MEMORY_INFORMATION_CLASS != MemoryImageExtensionInformation -> call the original ZwQueryVirtualMemory
  • if ImageBase != implant_ptr -> call the original ZwQueryVirtualMemory
  • otherwise – return with a benign error: STATUS_NOT_SUPPORTED

The full implementation of the patch can be found here:

https://github.com/hasherezade/libpeconv/blob/master/run_pe/patch_ntdll.cpp

As a result, loading of our implant won’t be interrupted, and we can enjoy having Process Hollowing on Windows 11 24H2!


文章来源: https://hshrzd.wordpress.com/2025/01/27/process-hollowing-on-windows-11-24h2/
如有侵权请联系:admin#unsafe.sh