Back to reports

How a Vietnamese Corruption Scandal Became a 6-Layer Shellcode Injector

Mustang Panda weaponizes the Thuan An Group scandal to deliver a Donut shellcode payload through AES-256 + XOR encryption

PublishedApril 1, 2026
aptmustang-pandaearth-pretavietnamdonut-shellcodeaes-256chinese-aptprocess-injection

A ZIP file named after one of the most politically radioactive companies in Vietnam. Inside, a WinRAR self-extracting archive that runs silently. Inside that, a 1.4-megabyte batch file containing 1,556 lines of PowerShell wedged between hand-carved markers. Inside that, 1,346 encrypted chunks that AES-256-CBC decrypt, XOR-decode, and reconstitute into a megabyte of Donut shellcode. The shellcode gets injected into explorer.exe. And then it waits -- in an infinite loop, watching, ready to re-inject itself the moment the process dies.

This is not a theoretical exercise. This sample was submitted to MalwareBazaar on March 31, 2026, with zero detections. It targets Vietnamese-speaking victims using one of the most effective social engineering lures we've seen this year: a real corruption scandal that gripped the nation.

This is the story of a Mustang Panda operation caught mid-deployment.

The Lure: Thuan An Group

The outer ZIP is named Cong_ty_Thuan_An.zip -- "Thuan An Company." Inside: Danh_sach_My_Pham_Cong_ty.exe -- "Cosmetics Company List." To a Vietnamese government employee, journalist, or business executive, this is catnip.

Thuan An Group was the epicenter of Vietnam's largest corruption prosecution in 2024 -- the Truong My Lan case, which involved an estimated $12.5 billion in fraud and resulted in a death sentence. The company name still radiates political gravity. It implies insider knowledge. It demands to be opened.

That's what makes this social engineering brilliant. It doesn't invent a pretext. It weaponizes a real event that the target is already emotionally and professionally invested in. The operator isn't creating curiosity -- they're exploiting it.

Layer 1: The Silent SFX

The EXE is a WinRAR self-extracting archive built with Visual Studio 2022 (MSVC 14.4x toolchain, v17.10-17.12). The PDB path gives it away:

D:\Projects\WinRAR\SFX\build\sfxrar64\Release\sfxrar.pdb

The SFX script is configured for stealth:

Setup=update.bat
Silent=1
Overwrite=1

No extraction dialog. No confirmation. The victim double-clicks what they think is a document, and update.bat is already running. This is signature Mustang Panda tradecraft -- they've been weaponizing WinRAR SFX archives with silent execution flags since at least 2019, and they haven't stopped because it keeps working.

Layer 2: The 1.4-Megabyte Batch File

update.bat is not a typical dropper script. It's 1,398,142 bytes -- over a megabyte of obfuscated batch commands wrapping a PowerShell payload. Its first move is persistence:

copy "%~f0" "%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup\update.bat"

Simple. Effective. The batch file copies itself to the Windows Startup folder, ensuring it survives reboot. Then it sets an environment variable pointing to its own location and launches PowerShell:

powershell -W Hidden -NoProfile -ExecutionPolicy Bypass -EncodedCommand <base64>

The -W Hidden flag suppresses the PowerShell window. -NoProfile prevents loading user-specific configs that might interfere. -ExecutionPolicy Bypass sidesteps script execution restrictions. The encoded command is a bootstrap -- a small Base64 blob whose only job is to extract the real payload.

Layer 3: 1,556 Lines of PowerShell

The batch file contains the PowerShell stage embedded between two markers: ###PSBEGIN### and ###PSEND###. The bootstrap extracts this block via regex, and what emerges is a 1,556-line script that constitutes the actual loader.

Before it does anything else, the script claims a mutex:

Global\fixload_ps1_mutex

Single-instance enforcement. If another copy of the loader is already running, this one exits silently. It's a small operational detail, but it matters -- it prevents the self-healing re-injection loop (more on that shortly) from spawning duplicate instances after a reboot.

The Anti-Debug Gauntlet

Before decrypting the payload, the PowerShell stage checks whether it's being watched:

  1. IsDebuggerPresent -- the classic userland debugger check
  2. PEB.BeingDebugged via NtQueryInformationProcess -- queries the Process Environment Block with ProcessDebugPort (information class 7), catching debuggers that hook at the kernel level

If either check fires, the script dies. No error message. No graceful exit. Just silence. An analyst stepping through the code in x64dbg or WinDbg hits a wall that looks like the script simply didn't work.

The Decryption Engine

The payload is stored as 1,346 Base64-encoded chunks totaling 1,345,644 characters of ciphertext. The decryption is two-layer:

AES-256-CBC with PKCS7 padding:

  • Key: 5bcc113f588e09fa25c738ae3d0c8fc94d067627dd5a9e2c6d48a51ff80ec457
  • IV: 2a13e940ab086191 1abe3a86d34ba00c

XOR 0xAA applied to the AES output.

The AES layer does the heavy lifting. The XOR pass is a secondary obfuscation layer -- trivial to reverse, but it changes the byte distribution enough to defeat naive entropy analysis on the decrypted buffer. An automated sandbox that skips the AES decryption and tries to analyze the intermediate output will see XOR-scrambled noise instead of recognizable shellcode headers.

We extracted the full crypto material and independently decrypted the payload. The result: 1,009,227 bytes of position-independent shellcode.

Layer 4: Injection into explorer.exe

With the shellcode decrypted in memory, the loader goes hunting. It uses WMI to enumerate running processes:

Get-WmiObject Win32_Process -Filter "Name = 'explorer.exe'"

But it doesn't inject into just any explorer.exe. It calls GetOwner() on each result and only targets the instance running under the current user's session. This is subtle -- on a multi-user terminal server, it avoids injecting into another user's Explorer process, which would raise immediate red flags in EDR telemetry.

The injection sequence follows the classic pattern, but with one modern twist:

  1. VirtualAllocEx -- allocates memory in explorer.exe (RW permissions)
  2. WriteProcessMemory -- copies the 1MB shellcode into the allocated region
  3. VirtualProtectEx -- changes permissions from RW to RX (no write+execute, avoiding a common EDR detection)
  4. NtCreateThreadEx -- creates a remote thread to begin execution

The use of NtCreateThreadEx instead of CreateRemoteThread is deliberate. CreateRemoteThread is one of the most heavily hooked APIs in modern EDR products. NtCreateThreadEx is the underlying NT native API -- it bypasses userland hooks that intercept the higher-level wrapper. It's not invisible, but it reduces the detection surface.

The Self-Healing Loop

Here's where the operational maturity shows. After injection, the PowerShell script does not exit. It enters an infinite loop:

while ($true) {
    # Check if explorer.exe is still alive
    # If not, find the new one and re-inject
    Start-Sleep ...
}

If the target explorer.exe process crashes, is killed by an analyst, or is restarted by Windows, the loader detects the loss and injects the shellcode into the replacement process. The implant is self-healing. Killing explorer.exe to purge the injected code accomplishes nothing -- the payload will be re-injected within seconds.

This means the actual persistence mechanism is dual-layered: the batch file in the Startup folder ensures the loader runs after reboot, and the injection loop ensures the shellcode survives process termination during a session. Together, they create a resilient presence that requires killing both the PowerShell process and removing the Startup entry to eradicate.

Layer 5: Donut Shellcode

The decrypted shellcode is a Donut loader -- a framework for generating position-independent shellcode from PE files, .NET assemblies, and other executable formats. Donut has become the go-to shellcode generator for sophisticated threat actors because it handles the complexity of in-memory execution: resolving API addresses dynamically, loading the CLR for .NET payloads, and encrypting the embedded payload to resist static analysis.

The Donut instance we extracted carries its own encryption:

  • Chaskey cipher key: fd66ceb685f86915d9d6c6f83db3b667
  • Chaskey counter/nonce: 000000004424bf2afa8938ff734e59cf
  • Instance size: 984,000 bytes
  • Module type: 0 (PE/DLL or .NET assembly via CLR bootstrap)

Chaskey is a lightweight block cipher designed for embedded systems -- fast, small, and not commonly flagged by security tools that look for AES or ChaCha patterns. Donut uses it specifically because it's obscure enough to fly under heuristic detection.

The Donut-encrypted payload is the final layer. It contains the actual implant -- the thing that phones home, exfiltrates data, and provides persistent access. Without decrypting the Chaskey layer, we cannot extract C2 infrastructure from this sample. But the surrounding evidence points in a clear direction.

Attribution: Mustang Panda

Mustang Panda (also tracked as Earth Preta, Bronze President, TA416, TEMP.Hex, HoneyMyte, and Red Lich) is a Chinese state-sponsored espionage group that has targeted Vietnam relentlessly since 2018. They are not subtle about their interest in Southeast Asia -- Vietnam, Myanmar, the Philippines, and Indonesia are perennial targets, with government agencies, military organizations, and NGOs bearing the brunt.

The attribution for this sample sits at medium-high confidence based on the convergence of eight independent indicators:

  1. Vietnamese-language lure exploiting a real political event -- this is Mustang Panda's signature move in the region
  2. WinRAR SFX with Silent=1 -- documented Mustang Panda TTP across dozens of campaigns
  3. BAT-to-PowerShell execution chain -- consistent with their post-2024 evolution away from DLL side-loading
  4. Donut shellcode loader -- adopted by Mustang Panda in 2025 campaigns
  5. Process injection into explorer.exe -- a recurring Mustang Panda persistence technique
  6. Temporal overlap with three concurrent Mustang Panda operations in March 2026:
    • 09032026_1533_GIAY MOI.doc.lnk.msi (Vietnamese "Invitation Letter" + PlugX, March 9)
    • Energy_Infrastructure_Situation_Note_Tehran_Province_2026.zip (PlugX, March 17)
    • AAM UpdatesEqn.rar (PlugX, March 24)
  7. Compilation with MSVC 14.4x (Visual Studio 2022) -- matches toolchain used in known Mustang Panda builds
  8. 0/36 initial detection rate -- consistent with the group's operational security posture of deploying fresh, undetected loaders

What reduces confidence: we haven't yet extracted C2 infrastructure from the Donut-encrypted final payload, and the specific techniques (WinRAR SFX, process injection) are not exclusive to Mustang Panda. But the combination of Vietnamese targeting, structural tradecraft overlap, and temporal alignment with active campaigns makes coincidence unlikely.

Known PlugX C2 domains active in March 2026 from concurrent Mustang Panda operations:

DomainFirst SeenReporter
airportcarrentalmiami[.]com2026-03-24DonPasci
coastallasercompany[.]com2026-03-24DonPasci
doorforum[.]com2025-12-17DonPasci

Correlation with this sample pending Donut payload decryption.

Detection: What to Hunt For

The combination of behavioral indicators makes this killchain detectable at multiple points, even without signature matches:

Startup folder persistence: Look for update.bat or any batch file appearing in %APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup\. Batch files in this location are uncommon in enterprise environments.

PowerShell execution pattern: A batch file spawning powershell.exe with -W Hidden -EncodedCommand is a high-fidelity detection signal. The combination of hidden window + encoded command + no profile is used almost exclusively by malware.

Mutex: Global\fixload_ps1_mutex is hardcoded. Any process holding this mutex is running this loader.

Process injection telemetry: VirtualAllocEx + WriteProcessMemory + VirtualProtectEx (RW -> RX) + NtCreateThreadEx targeting explorer.exe from a PowerShell process. This sequence should generate alerts in any mature EDR deployment.

WMI process enumeration: Get-WmiObject Win32_Process filtered on explorer.exe with GetOwner() calls, from a hidden PowerShell window. Unusual outside of IT administration scripts.

Indicators of Compromise

File Hashes (SHA256)

2d22c06b34bc0cd6aa01b638446526af9b043d146034f1ed9fa9b049133f1027  # Cong_ty_Thuan_An.zip
178f2fc720bda22645ce68e6e68e4a2ddfedbb59e2c4163171652a27f0db5bca  # Danh_sach_My_Pham_Cong_ty.exe (WinRAR SFX)
15a403882bbe98cc3b5a1556455a067081ebf7a014e8e7dd4ffb7c6a25fcefd1  # update.bat (1.4MB obfuscated loader)
02f0d0d86c8f7aa4d6e3baea38596c121f1a8a12bb76ff99b7562de3ceca1824  # Decrypted shellcode (Donut loader)

Additional File Indicators

# MD5
169080e34221ba5bf35a73abbfe9d576  # Cong_ty_Thuan_An.zip

# Imphash
7c75a83e117d2bdfb2814c53e840c172  # WinRAR SFX module

# SSDEEP
24576:mHI9dbaPK35X/W1JfpPTnca+O8CpcUAVOn8cn10dCt3ymPGf:00RaPK35X87PTRaCpRAVO8cnntD+

# TLSH
T15D553352F93647457B7B6DB0BE179357AEA316E43DF325AF32331677AA190A8938000C

Behavioral Indicators

# Mutex
Global\fixload_ps1_mutex

# Persistence
%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup\update.bat

# PowerShell execution
powershell -W Hidden -NoProfile -ExecutionPolicy Bypass -EncodedCommand <base64>

# Environment variable
PSBAT_SELF=%~f0

# Process injection target
explorer.exe (current user session only)

# WMI enumeration
Get-WmiObject Win32_Process -Filter "Name = 'explorer.exe'"

Cryptographic Material

# AES-256-CBC
Key: 5bcc113f588e09fa25c738ae3d0c8fc94d067627dd5a9e2c6d48a51ff80ec457
IV:  2a13e940ab0861911abe3a86d34ba00c
Mode: CBC, PKCS7 padding
Post-decryption XOR: 0xAA

# Donut Chaskey cipher
Key:     fd66ceb685f86915d9d6c6f83db3b667
Counter: 000000004424bf2afa8938ff734e59cf

MITRE ATT&CK

TechniqueIDApplication
Spearphishing AttachmentT1566.001Vietnamese business document lure
User Execution: Malicious FileT1204.002Disguised EXE inside ZIP
Windows Command ShellT1059.003update.bat batch loader
PowerShellT1059.001Hidden, encoded PowerShell stage
Startup Folder PersistenceT1547.001Copies to Startup folder
Obfuscated Files or InformationT1027AES + XOR + Chaskey triple encryption
Embedded PayloadsT1027.009Shellcode embedded in BAT between markers
Debugger EvasionT1622IsDebuggerPresent + PEB checks
Process Injection: Thread Execution HijackingT1055.003NtCreateThreadEx into explorer.exe
MasqueradingT1036.005Vietnamese business document naming
Deobfuscate/Decode FilesT1140Runtime multi-layer decryption
Process DiscoveryT1057WMI enumeration of explorer.exe
System Owner/User DiscoveryT1033GetOwner() to match current user

External References


This sample was identified via MalwareBazaar (reporter: smica83) and analyzed by Breakglass Intelligence's GHOST investigation system. All cryptographic material, shellcode, and behavioral indicators were extracted through static analysis. The Donut-encrypted final payload remains under investigation for C2 extraction.

Breakglass Intelligence | March 31, 2026

Share