When a 32-bit PE Turned Into a Fully Interactive .NET RAT

Author: Danyal Rana

SHA-256: cddd5e55137fa3c041b5c3471a2b4eb8754663bbbe59eb0a4061461498b6a507

MD5: 0a5ca858cd51dea094ab07ee1f52f89b

Executive Summary

What initially presented itself as a relatively unremarkable Windows PE quickly turned into something considerably more interesting.

The initial executable is a 32-bit .NET PE measuring approximately 1.36 MB, with a large .text section and comparatively small resource and relocation sections. Static metadata identifies it as CIL/.NET rather than native code, and the binary is unsigned.

Early string analysis was largely useless. Instead of conventional readable API names and configuration values, the binary contained heavily obfuscated data, mathematical expressions, and resource-related strings. However, the PE’s own strings exposed an important clue: it references both Debule.exe and DeluxeLauncher-1.2.exe, alongside System.Resources.ResourceReader and System.Resources.RuntimeResourceSet.

Following the embedded .NET component led to a much more capable program.

The recovered code demonstrates:

  • extensive string obfuscation and runtime decoding
  • aggressive control-flow obfuscation
  • WMI-based system interrogation
  • registry manipulation
  • persistence functionality
  • process enumeration and termination
  • native API resolution
  • memory-protection manipulation
  • dynamic assembly loading
  • TCP C2 communication
  • host fingerprinting
  • periodic timers and reconnection behaviour
  • a custom length-prefixed network protocol
  • a second encoding/transformation layer around C2 messages
  • multiple C2 command handlers
  • Base64-encoded command data
  • the ability to receive and process dynamically supplied functionality

Most importantly, the latest stage of analysis established the actual C2 framing protocol, moving the investigation from “this communicates over TCP” to a concrete description of how messages are transported and dispatched.

1. Initial PE Triage

The first pass established that the initial executable is a PE32 .NET assembly.

The binary contains three primary sections:

Β 
.text ~0x14c000
.rsrc 0x600
.reloc 0x200
Β 

The image base is 0x00400000, with an image size of approximately 0x152000. The PE’s COM descriptor is present, confirming the managed-code nature of the executable.

The metadata reported:

Β 
Architecture: x86
Format: PE32
Language: CIL
Subsystem: .NET
Signed: No
NX: Enabled
Β 

The recorded compilation timestamp was 10 August 2026, although timestamps embedded in malware should never be treated as authoritative provenance without corroboration.

The first interesting clue

The string table contained:

Β 
System.Resources.ResourceReader
System.Resources.RuntimeResourceSet
PADPADP\
Debule.exe
DeluxeLauncher-1.2.exe
Β 

The presence of .NET resource infrastructure alongside executable names strongly suggested that the initial executable was not simply a monolithic payload.

That became the first major pivot in the investigation.

2. Following the Embedded .NET Component

The embedded managed component was extracted and opened with ILSpy.

The resulting decompilation produced approximately 48,700 lines of C#, immediately demonstrating that there was considerably more functionality underneath the initial carrier than the first-pass strings suggested.

The assembly identifies itself generically as a client:

Β 
Β 
AssemblyTitle: Client
AssemblyProduct: Client
AssemblyVersion: 1.0.0.0
Β 

It also contains a large number of classes with intentionally meaningless identifiers.

Among the recovered classes was the network component containing:

Β 
Β 
Socket YhMWbBblOYJDUpW;
Β 

and the socket initialization and connection logic.

At this point, the investigation shifted from PE triage to full-scale .NET reverse engineering.

3. The Obfuscation Is Deliberately Annoying

The code is heavily obfuscated using several overlapping techniques.

The most obvious is control-flow flattening.

Instead of:

Β 
Β 
Connect();
CollectInformation();
SendData();
Wait();
Β 

the decompiler repeatedly produces structures resembling:

Β 
Β 
int num = 1234;
Β 
do
{
if (num == 1234)
num = 5678;
Β 
if (num == 5678)
…
}
while (num != 9012);
Β 

The actual values are frequently disguised using expressions such as:

Β 
Β 
Math.Floor()
Math.Ceiling()
Math.Round()
Math.Sin()
Math.Cos()
Math.Tan()
Math.Sqrt()
Math.Log()
Math.Tanh()
Math.Abs()
Β 

This isn’t cryptography.

It’s analyst-hostile arithmetic decoration designed to make otherwise trivial constants look complicated and make automated decompilation considerably uglier.

For example, a value that is ultimately just 4 may be represented as:

Β 
Β 
Convert.ToInt32(2.0 + Math.Floor(2.0))
Β 

The same technique appears throughout the networking and command-dispatch logic.

4. Runtime String Resolution

The second major obfuscation layer is the string resolver.

Rather than placing strings such as:

Β 
Socket
Process
Registry
Software
Run
PowerShell
Β 

directly into the relevant functions, the program repeatedly calls a resolver:

Β 
uPvdKJgKgB.PRXZURztnrYSv(…)
Β 

The resolver is used throughout the entire program, including WMI queries, registry paths, filesystem operations, networking, process manipulation and C2 command identifiers.

This means that understanding the malware requires resolving the string layer before the actual logic becomes readable.

It also explains why the initial static strings were so poor.

The useful strings are there β€” they’re just hidden behind a ridiculous number of wrappers.

5. System Discovery

Once the string-resolution layer was followed into the actual functionality, the malware revealed substantial host-information gathering.

The code contains multiple WMI queries through:

Β 
Β 
ManagementObjectSearcher
ManagementObject
ManagementBaseObject
Β 

including dynamically resolved query strings and properties.

The C2 registration data constructed by the malware also includes direct environmental information.

Among the recovered values are:

Β 
Β 
Environment.MachineName
Environment.ProcessorCount
Β 

The machine name is explicitly inserted into the registration/identification data, while the processor count is converted to a string and included as another field.

This is important because the malware isn’t simply establishing a blind socket connection.

It appears to identify the victim machine to the remote operator.

6. C2 Initialization

The networking component creates a standard TCP socket:

Β 
SocketType.Stream
Β 

and connects it to an IP/port pair resolved from the malware’s configuration.

Once connected, the socket is wrapped in a:

Β 
NetworkStream
Β 

and asynchronous reads begin immediately.

The program then creates timers for various recurring activities.

The timers use randomized intervals rather than simply executing at fixed periodic boundaries.

This gives the malware a more persistent, long-running architecture rather than the behaviour of a simple one-shot downloader.

7. The Victim Registration Message

One of the more interesting functions builds a large string array and concatenates it into a single registration message.

The fields include environmental information such as:

Β 
Β 
Machine name
Processor count
Β 

alongside numerous configuration and runtime values.

The resulting string is then passed to:

Β 
Β 
MssqjsAxorqcv(…)
Β 

which is the malware’s outbound network-send routine.

The message is therefore constructed locally and then passed into the C2 encoding/framing layer.

8. C2 Error Reporting

The same network channel is used for error reporting.

The function:

Β 
gFEwUesECso(string Message)
Β 

simply prefixes the supplied message and hands it to:

Β 

MssqjsAxorqcv(…)
Β 

The network exception handler invokes this function when communication fails.

This gives the operator visibility into certain runtime failures rather than silently discarding every exception.

9. The Network Protocol β€” Finally, Something Concrete

This is where the latest analysis became particularly useful.

The receive routine begins by allocating a 4-byte buffer.

It reads those four bytes from the NetworkStream and interprets them using:

Β 
BitConverter.ToInt32(…)
Β 

The resulting integer becomes the size of the next message.

Therefore the outer protocol is definitively:

Β 
Β 
+———————-+———————-+
| 4-byte length (LE) | payload |
+———————-+———————-+
Β 

where the first field is a signed 32-bit little-endian integer.

The malware then allocates a buffer of exactly that size and continues reading until the entire payload has arrived.

Only after the complete message is received does it create a new thread to process the data.

This is not a guess.

The implementation explicitly demonstrates the length-prefix framing.

10. Outbound C2 Uses the Same Framing

The send routine confirms the other side of the protocol.

The malware first transforms the UTF-8 message:

Β 
Β 
Encoding.UTF8.GetBytes(mess)
Β 

then passes it through:

Β 
Β 
XCqWboGziWovRar.oLUvxGSFPvQEU(…)
Β 

The resulting byte array’s length is calculated:

Β 
Β 
BitConverter.GetBytes(array.Length)
Β 

and those four bytes are sent before the transformed payload.

The effective wire format is therefore:

Β 
Β 
CLIENT β†’ SERVER
Β 
[4-byte LE payload length]
[transformed payload]
Β 

and:

Β 
Β 
SERVER β†’ CLIENT
Β 
[4-byte LE payload length]
[transformed payload]
Β 

11. There Is a Second Layer Inside the TCP Frame

The outer length prefix isn’t the whole story.

The outbound transformation routine begins by writing another four-byte value:

Β 
byte[] bytes = BitConverter.GetBytes(input.Length);
memoryStream.Write(bytes, 0, 4);
Β 

before passing the stream and input into another transformation routine.

The corresponding receive-side transformation function consumes the first four bytes from its input stream before passing the remainder into another routine:

Β 
Β 
byte[] array = new byte[4];
Β 
memoryStream.Read(array, 0, 4);
Β 
return AFupTJMbpTU.eMZrKwMeMBRiLMl(array, memoryStream);
Β 

This establishes an inner length field as well.

At the current stage, the exact algorithm implemented by the two transformation functions has not yet been resolved, so it would be premature to label it encryption, compression, or any particular cipher.

What we can say with confidence is:

Β 
Β 
TCP
β”‚
β”œβ”€β”€ 4-byte outer payload length
β”‚
└── encoded payload
β”‚
β”œβ”€β”€ 4-byte inner length
β”‚
└── transformed content
Β 

That inner transformation is now the obvious next reverse-engineering target.

12. Decoding C2 Messages

Once a complete network frame arrives, the malware performs:

Β 
Β 
XCqWboGziWovRar.LKjRpjuBaxqe(…)
Β 

The resulting bytes are converted to UTF-8:

Β 
Β 
Encoding.UTF8.GetString(…)
Β 

and then split into fields using a delimiter resolved through the string-decoding layer.

The resulting array is passed to:

Β 
Β 
DwaReeCOiT(messages);
Β 

That function acts as the central command dispatcher.

13. Command Dispatcher

The dispatcher currently exposes eight separate command-handler paths:

Β 
Β 
DgFmeatBSTMfpm
RVekAnllhRBNf
rRaQxpGfgCRQ
IziWssClYtHFBRu
VdNOabBlOsx
locSkqcmyuIU
pSYTKvXMHKZD
WhxwIAvZ
Β 

The handlers are reached through another flattened state machine, making the actual command flow look much more complicated than it is.

The command identifiers themselves are still hidden behind the runtime string resolver.

However, the individual handlers reveal what the framework is capable of doing.

14. Base64-Encoded Command Data

One handler checks the first command field and then performs:

Convert.FromBase64String(Messages[2])
Β 
before passing the resulting bytes into another routine.

This gives us a concrete indication that at least one C2 command carries binary data as Base64 inside the decoded command structure.

This is particularly useful for future traffic analysis:

Β 
C2 frame
↓
inner transformation
↓
UTF-8 command string
↓
delimiter split
↓
command identifier
↓
arguments
↓
Base64 β†’ binary
Β 

15. Dynamic Assembly Loading

One of the more significant capabilities appears in another handler.

The recovered code contains:

Β 
Β 
AppDomain.CurrentDomain.Load(…)
Β 

followed by:

Β 
Β 
GetType(…)
Β 

and:

Β 
Β 
Activator.CreateInstance(…)
Β 

The loaded assembly is then used to create an object dynamically.

This is substantially more interesting than ordinary command execution.

It suggests that the C2 framework can receive or otherwise obtain managed code and dynamically load it into the existing process.

The exact protocol and payload format used for this mechanism still require further analysis, but the execution primitive itself is directly visible in the recovered code.

16. Process Manipulation

The malware contains a native API wrapper layer exposing functionality including:

OpenProcess
CreateToolhelp32Snapshot
Process32First
Process32Next
TerminateProcess
NtProtectVirtualMemory
CloseHandle
Β 
The presence of CreateToolhelp32Snapshot and the process enumeration APIs demonstrates that the program can enumerate processes independently of the higher-level .NET Process API.

OpenProcess and TerminateProcess provide direct process-control capability.

More interestingly, NtProtectVirtualMemory is also resolved through the native API layer.

That combination is significant because changing memory protections is a common prerequisite for manipulating executable memory.

At this stage, however, the presence of the primitive alone should not be interpreted as proof of process injection. The relevant call chain needs to be followed before assigning a specific injection technique.

17. Registry Manipulation and Persistence

The program contains extensive registry interaction.

Recovered code opens registry paths dynamically and writes values using RegistryKey.SetValue().

Additional code manipulates:

  • HKEY_LOCAL_MACHINE
  • HKEY_CURRENT_USER
  • HKEY_CLASSES_ROOT

and creates nested subkeys.

This is particularly notable because the registry activity isn’t restricted to a single obvious persistence location.

The malware appears to contain functionality for modifying multiple registry areas, including file-association-related structures.

Further investigation is required to distinguish:

  1. persistence,
  2. configuration storage,
  3. file association hijacking,
  4. operational state,
  5. or other registry-based behaviour.

What is already clear is that registry modification is a deliberate component of the malware’s architecture rather than incidental configuration handling.

18. Temporary File and Process Execution Capability

Several handlers construct temporary paths using:

Β 
Β 
Path.GetTempFileName()
Β 

and then append dynamically resolved extensions.

Other code creates ProcessStartInfo objects and launches processes, including restarting or re-executing the current executable.

This gives the malware a fairly broad execution model:

C2
↓
command
↓
argument / payload
↓
temporary file or dynamic assembly
↓
process / managed execution
Β 

Again, not every command has been completely decoded yet, but the underlying execution mechanisms are already visible.

19. Periodic Behaviour and Long-Lived C2

The malware does not simply connect once and exit.

After establishing the network stream, it initializes multiple timers.

Some timers use randomized initial delays and randomized recurrence intervals.

This architecture is consistent with a long-lived client that periodically performs background operations while maintaining its C2 channel.

The receive routine also continuously schedules another asynchronous read after processing each portion of the protocol.

In other words:

Β 
Β 
Connect
↓
Register
↓
Wait for C2
↓
Receive frame
↓
Decode
↓
Dispatch
↓
Execute
↓
Return to receive loop
↓
Repeat
Β 

This is a proper RAT-style communication architecture.

20. What the Malware Looks Like Architecturally

At this point, the most useful way to understand the malware isn’t as one giant executable.

It looks more like a collection of cooperating layers:

Β 
Β 
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Initial PE Carrier β”‚
β”‚ β”‚
β”‚ .NET loader / resource handling β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Embedded .NET Payload β”‚
β”‚ β”‚
β”‚ String decoding β”‚
β”‚ Control-flow flattening β”‚
β”‚ Configuration β”‚
β”‚ Host discovery β”‚
β”‚ Registry manipulation β”‚
β”‚ Process manipulation β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ C2 Engine β”‚
β”‚ β”‚
β”‚ TCP socket β”‚
β”‚ NetworkStream β”‚
β”‚ Registration β”‚
β”‚ Timers β”‚
β”‚ Reconnection / error handling β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Custom Protocol β”‚
β”‚ β”‚
β”‚ 4-byte LE outer length β”‚
β”‚ Inner 4-byte length β”‚
β”‚ Transformation layer β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Command Layer β”‚
β”‚ β”‚
β”‚ 8 command handlers β”‚
β”‚ Base64 arguments β”‚
β”‚ Dynamic assembly loading β”‚
β”‚ Process/file operations β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
Β 

That is a considerably more capable architecture than the initial PE suggested.

21. What We Know vs. What We Don’t

One thing worth emphasizing is that reverse engineering is much more useful when we distinguish confirmed behaviour from assumptions.

Confirmed

  • 32-bit .NET PE architecture.
  • Embedded-resource infrastructure.
  • Large-scale string indirection.
  • WMI-based system interrogation.
  • Machine-name and processor-count collection.
  • TCP socket communication.
  • NetworkStream communication.
  • 4-byte little-endian outer length prefix.
  • Matching 4-byte outbound length prefix.
  • Secondary payload transformation layer.
  • UTF-8 command processing.
  • Eight command-dispatch paths.
  • Base64-decoded command data.
  • Dynamic AppDomain assembly loading.
  • Process enumeration and termination APIs.
  • NtProtectVirtualMemory capability.
  • Extensive registry manipulation.
  • Randomized timers.

Not yet conclusively established

  • The exact algorithm implemented by the inner C2 transformation.
  • Whether that transformation is encryption, compression, serialization, or a combination.
  • The plaintext names of all eight C2 commands.
  • The complete payload format for dynamically loaded assemblies.
  • Whether NtProtectVirtualMemory is ultimately used for injection in this sample.
  • The complete purpose of every registry modification.
  • The full set of C2 configuration values.

Those are not gaps in the investigation so much as the next targets.

22. Current Assessment

The evidence collected so far supports classifying the payload as a modular .NET remote-access framework/RAT, rather than a simple downloader or single-purpose stealer.

Its architecture combines:

  • host reconnaissance,
  • persistent network communication,
  • custom binary framing,
  • command dispatch,
  • dynamic code loading,
  • process manipulation,
  • filesystem interaction,
  • registry modification,
  • and runtime-obfuscated configuration.

The interesting part isn’t that any one of those capabilities exists independently.

It’s that they’re all tied together by a persistent C2 framework.

The operator gets a client that can identify the host, maintain a socket, receive structured commands, decode supplied data, dynamically load managed code, interact with processes and manipulate the Windows environment.

And the authors went out of their way to hide practically every useful string behind layers of resolvers and mathematical nonsense.

Updated Findings

C2-Directed Payload Execution

Analysis of the command dispatcher identified a dedicated payload-execution handler capable of receiving Base64-encoded data from the command-and-control server. The handler decodes the supplied data, creates a temporary file, writes the decoded payload to disk, and passes the resulting path to an internal execution routine. This confirms that the RAT supports server-directed secondary payload delivery and execution rather than merely executing functionality embedded within the primary implant.

Confirmed capabilities:

  • C2-directed payload delivery
  • Base64 payload decoding
  • Temporary file creation
  • Payload written to disk
  • Payload execution
  • Post-execution process termination/cleanup behavior