TW / Independent
← Research audits

Malware Analysis / Artefact: BlueLoader bot payload · SHA-256 672320eb064f…

Inside BlueLoader: BoxedApp, DNGuard and a two-stage .NET bot

This investigation connects three distinct layers of the same ecosystem: a native BoxedApp container, a DNGuard-protected management panel and a two-stage .NET bot with an authenticated C2 protocol and process hollowing.

EVIDENCEStatic + dumpLAYERSBoxedApp / DNGuardPROTOCOL10 protobufSTATUSBounded recovery
Scope
BoxedApp-packaged panel, DNGuard-protected panel assembly, outer .NET bot loader, extracted inner assembly, static reconstructions and protocol models.
Method
Static container inspection and bot unpacking, offline analysis of an existing isolated panel minidump, metadata/JIT inventory, string and delegate resolution, and structural protocol comparison. No sample was re-executed for this report.
Evidence
Private manifested evidence set; static analysis and an existing isolated dump.
Finding

The BoxedApp wrapper, DNGuard protection layer, two-stage bot loading chain, ten message models and material host capabilities are supported in the reviewed snapshot.

No successful C2 contact, no dynamic behaviour measurement and no attribution to a person or operator group.

Analyst note

What the evidence actually supports.

BlueLoader was not a single finding but a layered investigation: wrapper, protection layer, loader and inner bot had to be separated before any capability could be tied to the correct artefact.

Evidence anchorchecked locally
Artefact
BlueLoader bot payload
SHA-256
672320eb064f6d971e98c7cbfc5bfdd48541a992ccedac9b5550030953587c39
Analysis basis
Private manifested evidence set; static analysis and an existing isolated dump.
Research anatomyInteractive method model

One shell. One bot. Ten messages.

The first stage decrypts and decompresses an embedded assembly. It is camouflage and loading path, not the bot itself.

Explanatory diagram, not live telemetry or an audit score. The article documents the assessment and its limits.

Malware / Evidence Atlas

Container → Host action

The analysis path for this report. Every node shows what is supported, where detection can start and where the claim stops.

5flow nodes 4detection artefacts 4rule formats
Claim

Container

A native BoxedApp wrapper forms the outer package of the reviewed evidence set.

Detection focus

Combine PE traits, embedded files and wrapper artefacts.

Supported by review evidence
Config Surface

Configuration fingerprint

Review pivots derived from the report — not a live configuration or universal family indicator.

01
ContainerBoxedApp
core
02
Protection layerDNGuard
support
03
Message modelprotobuf × 10
core
04
Runtime boundarybounded dump
boundary
MODEL / D9AC302ECore, support and boundary — not risk scores
Detection Pack

Defensive artefacts

Source, validation and limits accompany every rule.

SourceOriginal defensive derivation already documented in the report.ValidationSource copied; the original validation status remains authoritative.LimitApplies only within the sample and telemetry boundaries stated in the report.
YARAOpen rule
Defensive model
import "hash"

rule TW_BlueLoader_Exact_Samples_2026_10
{
    meta:
        description = "Exact BlueLoader artifacts from static review"
        author = "TW Research"
        date = "2026-10-17"
        confidence = "high / exact hash only"

    condition:
        filesize < 5MB and (
            hash.sha256(0, filesize) == "672320eb064f6d971e98c7cbfc5bfdd48541a992ccedac9b5550030953587c39" or
            hash.sha256(0, filesize) == "c706546279ba2781d349bdf8512651e0ec1e82e3172a1a700dd991d1d562b77f" or
            hash.sha256(0, filesize) == "46e5ca3417006841884c4cca9d76a6fd03772ec54f4692079df9af8319a1505c"
        )
}

Evidence status Supported by review evidenceBound to primary researchBounded or unresolved

Key findings

The analysis does not produce one monolithic “unpacked sample”; it establishes an evidence-backed architecture across separately examined components.

01 · Panel container. Product-specific BoxedApp symbols and resource layout support the native packaging assessment; wrapper code was kept separate from BlueLoader application logic.

02 · Protected panel. An existing isolated minidump enabled offline reconstruction of the loaded BlueLoader.dll, two DNGuard runtime modules and strictly attributed native JIT bodies.

03 · Bot loader. The separate 460 KB .NET loader decrypts an embedded stage with TripleDES-CBC, removes a four-byte length field, decompresses GZip and loads the result exclusively from memory.

04 · Technical linkage. Bot and panel implement the same ten protobuf message types with matching tags, field numbers and normalised types. This protocol parity is the strongest technical relationship in the corpus.

05 · Impact. The bot combines scheduled-task persistence, encrypted C2, PowerShell, download-and-execute, process hollowing, cleanup and self-removal routines.

Analysis scope and evidence model

The evidence set has two separate entry points. The bot branch starts with a 460 KB .NET loader and leads through TripleDES and GZip to the inner assembly. The panel branch starts with a 98,218,496-byte native PE64 container whose BoxedApp wrapper was identified statically; the panel assembly running inside it is additionally protected by DNGuard.

The report therefore documents three evidence layers: container identification, bounded DNGuard reconstruction from an existing isolated memory image, and static bot deobfuscation. Only the subsequent protocol comparison technically links bot and panel. Original samples and secrets remain outside the website.

ARTIFACT MANIFEST

Files and checksums

ResearchWorkspace/BlueLoader/Analyse/Sample_672320eb/DeobfuscatedDeproxied/Source/Nsxxizdy/GvrK920rQnDRhivANl8/q3T9KG0qeBMgBQWIWaL.cs
b366867eb2a36257eb9e5b372f5cc8078b92e2a50388af90bd2fcd6a30628bcb

Decompiled transport class from the inner assembly

CoreProjection/TransportProfile.cs
8d1200016033d40ea3aa4469533aa30c322a424f8d488655cb2b46019a161962

Readable static reconstruction of the transport profile

ResearchWorkspace/BlueLoader/Analyse/BotDeobfuscationComparison_20261016/build_comparison.py
85a21ee7a1bfc216b18f97086079f950bbac9147c44f5c41b107fbf526561511

Static tool for comparing bot and panel schemas

ResearchWorkspace/BlueLoader/Analyse/Sample_672320eb/Decompiled_current/Invrpnbqjnp/Procedures/ProcRunner.cs
ae4cc6f3c530c3d5f90f3b358e979b11e7f45d94b1fa690d9ad172d515252ef3

Decompiled TripleDES decryption path of the outer loader

ResearchWorkspace/BlueLoader/Analyse/Sample_672320eb/Decompiled_current/Invrpnbqjnp/Tracking/OperationalTracker.cs
8497d74f9c84cfc15b3ef144f207f2532229abcaea4105d9a7d2a12458c04f6f

Decompiled length validation and GZip decompression

ResearchWorkspace/BlueLoader/Analyse/Sample_672320eb/Decompiled_current/Invrpnbqjnp/Qhtid.cs
808cd9d2e80e6250da691320c3f9e1db549a7823a4dad1aca0e45d198b536b59

Call chain from decryption through decompression to Assembly.Load

ResearchWorkspace/BlueLoader/Analyse.md
fd519190b4797d680a8564f2e339940a27e21cbc5035be06c9ee4f8c1433b965

Static identification and scoping of the BoxedApp wrapper

ResearchWorkspace/BlueLoader/Analyse/PanelDump_20261013/ManagedExtract/README.md
ffbe0ea270a76cbede69b586fc328d4b99b3a7f4d77db6515c8d04929a8b052c

Offline reconstruction of the DNGuard-protected panel assembly from the minidump

ResearchWorkspace/BlueLoader/Analyse/PanelBoundedGapAudit_20261017/REPORT.md
1698c4130405e9a55c6c6e97afd50501542041cd6ccd84faa3ddae5b54d33727

Token-level completeness and limits audit for panel reconstruction

Relationship to public PureCrypter research

In 2022, Zscaler ThreatLabz described PureCrypter as a multi-stage .NET loader using obfuscation, compression, encryption, protobuf-based configuration, persistence and process injection. That publication provides a useful structural comparison for the loader portion of our corpus.

The evidence examined here takes a different direction and substantially broadens the view: in addition to the bot loader, it includes a standalone native BoxedApp container, a DNGuard-protected management panel, recovered panel metadata, native JIT evidence and a field-level bot-to-panel protocol comparison. This does not equate the sample with PureCrypter or imply shared developers. The comparison concerns architecture; family assessment rests solely on the local evidence set.

Technical analysis I — BoxedApp panel container

The 98 MB panel container is not a directly decompilable .NET program: the outer AMD64 PE has no CLR directory. Its attribution to BoxedApp instead rests on several independent features—numerous BoxedAppSDK symbols, PackerStubEntryPoint, embedded vendor build paths and the unusually large resource 10/15/0.

01 · Separate wrapper from payload. Wrapper APIs and helper files were not automatically attributed to BlueLoader code. Four valid PE helpers were byte-identical to known wrapper components; the .NET helper contained no application code.

02 · Test carving hypotheses. MZ/PE, BSJB, archive, GZip, zlib and short periodic XOR/addition searches produced no defensible embedded assembly. Those bounded heuristic failures were recorded as negative results, not as proof of a specific encryption algorithm.

03 · Match tools to evidence. A public unboxing tool expected a .bxpck section absent from the sample and would overwrite its input. It was therefore not run against the original. The BoxedApp finding reliably identifies the packaging, but does not claim a universal static unpacking success.

textStatic features of the outer BoxedApp containerSample excerpt
ResearchWorkspace/BlueLoader/Analyse.md · Lines 16-20
Show file hashSHA-256 fd519190b4797d680a8564f2e339940a27e21cbc5035be06c9ee4f8c1433b965
Zahlreiche `BoxedAppSDK_*`-Symbole, insbesondere `BoxedAppSDK_PackerStubEntryPoint`, und eingebettete BoxedApp-Buildpfade belegen einen BoxedApp-bezogenen Wrapper. Die eingebetteten Buildpfade sind Hersteller-/Buildinformationen, keine beobachteten Dateien auf diesem Rechner.

PE-Sektionen: `.text`, `.rdata`, `.data`, `.pdata`, `.Lmc`, `.rsrc`.

Die Ressource `10/15/0` umfasst 91.035.348 Bytes. Ihr Inhalt wurde nicht entpackt oder ausgeführt. Weitere Ressourcen enthalten Icon-, Versions- und Manifestdaten. Der geprüfte Standard-Signaturwert eines .NET-Single-File-Bundles wurde nicht gefunden.
Read the code

Technical analysis II — DNGuard-protected panel

The DNGuard layer was not removed with a single “deobfuscate” switch. The basis was an existing full minidump from an isolated Windows VM with no active network adapters. Every subsequent step only read that image; no extracted PE file or entry point was re-executed.

01 · Bind loaded modules. BlueLoader.dll, DNRuntime.dll and DNGuard.Runtime.dll were separately inventoried through memory addresses, CLR module attribution and SHA-256. The loaded main module had erased CLI and metadata headers; intact secondary copies in the same dump enabled repair of the metadata streams.

02 · Attribute JIT bodies strictly. A native body was accepted only when declaring module, ClrMD signature, valid MethodDef token, positive JIT hot region and uniqueness all matched. This excluded token collisions with framework and DevExpress methods.

03 · Separate reconstruction from projection. The final inventory counts 3,400 protected MethodDefs, 998 locally bounded native bodies and 742 integrated analysis bodies. Of those 742, 346 are runtime-derived and 396 are explicitly semantic projections—not a claim that the original CIL or C# was fully recovered.

04 · Quantify gaps. 498 bounded native bodies remain outside the analysis DLL. Only two are locally and transitively complete, both without a useful additional product finding. The other 496 require further target attribution or call-graph closure. That explicit boundary prevents partial reconstructions from being presented as a complete DNGuard unpack.

textRecovery of damaged .NET metadata in the dumpSample excerpt
ResearchWorkspace/BlueLoader/Analyse/PanelDump_20261013/ManagedExtract/README.md · Lines 22-26
Show file hashSHA-256 ffbe0ea270a76cbede69b586fc328d4b99b3a7f4d77db6515c8d04929a8b052c
`BlueLoader.dll` war als DNGuard-geschütztes, gemapptes Image bei
`0x32370000` geladen. Der gemappte CLI-Header war gelöscht; eine intakte
Zweitkopie lag bei `0x32370208`. Der ebenfalls gelöschte Metadatenkopf ließ
sich aus der intakten CLR-Kopie bei `0x14c78f3c` wiederherstellen. Danach
lesen `dnfile` und ILSpy alle fünf Metadatenstreams.
Read the code

Technical analysis III — Bot loader and inner assembly

The decryption was not guessed and the loader was not executed. The starting point was the static call chain in Qhtid.cs: the step labelled “Decrypt” passes three byte arrays to ProcRunner.ExecuteConfigurableProc; its result flows directly into the step labelled “Decompress” and then into Assembly.Load(byte[]).

01 · Identify the primitive. ProcRunner.cs instantiates TripleDESCryptoServiceProvider. The numeric .NET enum values Mode = 1 and Padding = 2 resolve to CBC and PKCS#7. It also requires 24 bytes for the key and 8 bytes for the IV before decryption.

02 · Follow the data flow. The embedded byte buffer is written to a CryptoStream backed by CreateDecryptor(); FlushFinalBlock() materialises the decrypted buffer. The conclusion rests not on one string but on the connected input, key, IV and output along the same call graph.

03 · Confirm the container format. OperationalTracker.cs reads the first four bytes as a little-endian Int32, starts a MemoryStream at offset 4 and feeds the remainder to GZipStream. It checks the resulting length against the prefix. This functionally establishes the prefix instead of merely inferring it from magic bytes.

04 · Verify the destination stage. The decompressed buffer is passed directly to Assembly.Load(byte[]) without a file write. That sink confirms the output is intended as a managed .NET assembly.

05 · Preserve reproducibility. Every evidence file is SHA-256-bound in the manifest; line ranges and hand-offs were cross-checked separately. The result is a static reconstruction. It supports the implemented unpacking chain, not successful execution on a victim system.

csharpGZip stage after the four-byte length prefixSample excerpt
ResearchWorkspace/BlueLoader/Analyse/Sample_672320eb/Decompiled_current/Invrpnbqjnp/Tracking/OperationalTracker.cs · Lines 64-77
Show file hashSHA-256 8497d74f9c84cfc15b3ef144f207f2532229abcaea4105d9a7d2a12458c04f6f
				using (MemoryStream memoryStream = new MemoryStream(task, mean_visitor, task.Length - mean_visitor))
				{
					GZipStream gzipStream = new GZipStream(memoryStream, 0);
					try
					{
						using (MemoryStream memoryStream2 = new MemoryStream((num2 <= 0) ? 0 : num2))
						{
							gzipStream.CopyTo(memoryStream2);
							byte[] array = memoryStream2.ToArray();
							if (array.Length != num2)
							{
								throw new InvalidDataException();
							}
							return array;
Read the code

Component flow and evidence chain

The investigation uses three evidence classes: immutable source artifacts, reproducible analysis tooling and explicitly labelled semantic projections. The map shows more than file relationships: it marks where a conclusion moves from observed bytes to analytical derivation. Runtime evidence, static findings and reconstruction therefore remain distinguishable.

FILE / EVIDENCE MAP

File relationships and analysis path

Switchable map with hash-bound sources and evidenced derivations.

A file reference does not establish runtime behaviour. Recorded processing is not a new execution.

SourceToolDerivedEvidenceMissingVerified referenceRecordedUnresolved

Files

Transport class, readable projection and panel comparison form distinct evidence layers.

q3T9KG0qeBMgBQWIWaL.cs

Decompiled transport logic with obfuscated identifiers.

File
ResearchWorkspace/BlueLoader/Analyse/Sample_672320eb/DeobfuscatedDeproxied/Source/Nsxxizdy/GvrK920rQnDRhivANl8/q3T9KG0qeBMgBQWIWaL.cs
SHA-256
b366867eb2a36257eb9e5b372f5cc8078b92e2a50388af90bd2fcd6a30628bcb
Location
41-66
  • q3T9KG0qeBMgBQWIWaL.cs → TransportProfile.csstatically reconstructed · Recorded

    Algorithms, sizes and layout were derived from decompiled paths.

Related report section →
TransportProfile.cs

Readable summary of cryptography and packet layout.

File
CoreProjection/TransportProfile.cs
SHA-256
8d1200016033d40ea3aa4469533aa30c322a424f8d488655cb2b46019a161962
Location
8-15
  • q3T9KG0qeBMgBQWIWaL.cs → TransportProfile.csstatically reconstructed · Recorded

    Algorithms, sizes and layout were derived from decompiled paths.

  • TransportProfile.cs → Panel schemaschema matched · Verified reference

    Field numbers and normalized field types match for tags 1 through 10.

Related report section →
Panel schema

Ten structurally matching protobuf message types.

  • TransportProfile.cs → Panel schemaschema matched · Verified reference

    Field numbers and normalized field types match for tags 1 through 10.

Related report section →

Analysis path

From decompiled sources through schema extraction to the secret-free projection.

Decompiled C#

Static C# views of bot and panel.

File
ResearchWorkspace/BlueLoader/Analyse/Sample_672320eb/DeobfuscatedDeproxied/Source/Nsxxizdy/GvrK920rQnDRhivANl8/q3T9KG0qeBMgBQWIWaL.cs
SHA-256
b366867eb2a36257eb9e5b372f5cc8078b92e2a50388af90bd2fcd6a30628bcb
Location
1-165
  • Decompiled C# → build_comparison.pyread · Recorded

    The tool processes stored C# files, not binary samples.

Related report section →
build_comparison.py

Reads decompiled sources and normalizes protobuf signatures.

File
ResearchWorkspace/BlueLoader/Analyse/BotDeobfuscationComparison_20261016/build_comparison.py
SHA-256
85a21ee7a1bfc216b18f97086079f950bbac9147c44f5c41b107fbf526561511
Location
33-60
  • Decompiled C# → build_comparison.pyread · Recorded

    The tool processes stored C# files, not binary samples.

  • build_comparison.py → TransportProfile.csnormalized · Recorded

    Names are separated from field numbers and normalized types.

Related report section →
TransportProfile.cs

Statically supported projection without the shared secret.

File
CoreProjection/TransportProfile.cs
SHA-256
8d1200016033d40ea3aa4469533aa30c322a424f8d488655cb2b46019a161962
Location
8-15
  • build_comparison.py → TransportProfile.csnormalized · Recorded

    Names are separated from field numbers and normalized types.

  • TransportProfile.cs → Analysis reportcross-checked · Verified reference

    Projection, protocol report and hash manifest were cross-checked statically.

Related report section →
Analysis report

Findings with limits and non-clickable IOCs.

  • TransportProfile.cs → Analysis reportcross-checked · Verified reference

    Projection, protocol report and hash manifest were cross-checked statically.

Related report section →

Limit: The map documents files and derivations; it is not live telemetry.

Deobfuscation at scale: strings, proxies and schema

The inner bot assembly contains 1,923 types and 9,748 methods; 6,189 methods retain a readable IL body. The cleanup pass replaced 990 verified string-resolver calls and rewrote 9,514 delegate proxies to direct targets. A complete expression scan showed that four initially suspicious sites invoke a random-name generator—an important negative finding because they must not be reported as missing plaintext.

Protocol reconstruction was then performed independently from behavioural control flow. The analysis tool extracts ProtoInclude relationships from decompiled sources, normalises signatures and rejects the result unless the complete expected tag set from 1 through 10 is present.

pythonStatic extraction of the ProtoInclude mappingAnalysis tool excerpt
ResearchWorkspace/BlueLoader/Analyse/BotDeobfuscationComparison_20261016/build_comparison.py · Lines 33-60
Show file hashSHA-256 85a21ee7a1bfc216b18f97086079f950bbac9147c44f5c41b107fbf526561511
def read_sources(root: Path) -> list[tuple[Path, str]]:
    return [(p, p.read_text(encoding="utf-8-sig", errors="replace")) for p in root.rglob("*.cs")]


def class_region(sources: list[tuple[Path, str]], class_name: str) -> tuple[Path, str]:
    pattern = re.compile(r"\bclass\s+" + re.escape(class_name) + r"\b")
    for path, text in sources:
        match = pattern.search(text)
        if not match:
            continue
        start = match.start()
        next_namespace = text.find("\nnamespace ", match.end())
        end = len(text) if next_namespace < 0 else next_namespace
        return path, text[start:end]
    raise KeyError(f"class not found: {class_name}")


def include_map(sources: list[tuple[Path, str]], base_class: str) -> tuple[Path, dict[int, str]]:
    path, region = class_region(sources, base_class)
    # Attributes are before the class declaration, so collect a bounded prefix.
    text = path.read_text(encoding="utf-8-sig", errors="replace")
    class_pos = re.search(r"\bclass\s+" + re.escape(base_class) + r"\b", text).start()
    prefix = text[max(0, class_pos - 2500) : class_pos]
    pairs = re.findall(r"\[ProtoInclude\((\d+),\s*typeof\(([^)]+)\)\)\]", prefix)
    mapping = {int(tag): name.strip() for tag, name in pairs}
    if set(mapping) != set(range(1, 11)):
        raise ValueError(f"{base_class}: expected tags 1..10, found {sorted(mapping)}")
    return path, mapping
Read the code

C2 cryptography: original path and analytical projection

The obfuscation removes semantic meaning from identifiers, but not the observable cryptography. AES key size, CBC mode, PKCS#7 padding, random IV generation and HMAC computation remain directly visible in the decompiled transport path. The comparison reduces that path to verifiable protocol properties and explicitly labels reconstructed names as analyst terminology. The shared secret is neither displayed nor published in derivable form.

ARTIFACT / RECONSTRUCTION

Obfuscated transport → readable profile

Source artifact · hash of the full file, not the excerpt

File
ResearchWorkspace/BlueLoader/Analyse/Sample_672320eb/DeobfuscatedDeproxied/Source/Nsxxizdy/GvrK920rQnDRhivANl8/q3T9KG0qeBMgBQWIWaL.cs
SHA-256
b366867eb2a36257eb9e5b372f5cc8078b92e2a50388af90bd2fcd6a30628bcb
Location
Lines 46–65 in the encryption path
01 · Before processingOriginal excerpt with non-semantic identifiers
						using (AesCryptoServiceProvider aesCryptoServiceProvider = new AesCryptoServiceProvider())
						{
							aesCryptoServiceProvider.KeySize = 256;
							aesCryptoServiceProvider.BlockSize = 128;
							aesCryptoServiceProvider.Mode = CipherMode.CBC;
							aesCryptoServiceProvider.Padding = PaddingMode.PKCS7;
							aesCryptoServiceProvider.Key = this.U260suBvbl;
							aesCryptoServiceProvider.GenerateIV();
							for (;;)
							{
								using (CryptoStream cryptoStream = new CryptoStream(memoryStream, aesCryptoServiceProvider.CreateEncryptor(), CryptoStreamMode.Write))
								{
									memoryStream.Write(aesCryptoServiceProvider.IV, 0, aesCryptoServiceProvider.IV.Length);
									cryptoStream.Write(\u0020, 0, \u0020.Length);
									cryptoStream.FlushFinalBlock();
									using (HMACSHA256 hmacsha = new HMACSHA256(this.BDg0C5xXGU))
									{
										byte[] array = hmacsha.ComputeHash(memoryStream.ToArray(), 32, memoryStream.ToArray().Length - 32);
										memoryStream.Position = 0L;
										memoryStream.Write(array, 0, array.Length);
02 · ReconstructionReadable projection without the shared secret
public static class TransportProfile
{
    public const string Framing = "4-byte little-endian encrypted-payload length";
    public const string Serialization = "protobuf-net base message with ProtoInclude tags 1..10";
    public const string Encryption = "AES-256-CBC with PKCS#7 padding and a random 16-byte IV";
    public const string Authentication = "HMAC-SHA256 over IV || ciphertext";
    public const string WireLayout = "32-byte HMAC || 16-byte IV || ciphertext";
    public const string KeyDerivation = "PBKDF2/Rfc2898DeriveBytes, 5,000 iterations";
Reconstruction file and its own checksum
Reconstruction file
CoreProjection/TransportProfile.cs
SHA-256
8d1200016033d40ea3aa4469533aa30c322a424f8d488655cb2b46019a161962
Reconstruction location
Lines 8–15 of the static projection

Text view · no execution · original remains unchanged

Identify primitives

AES key size, CBC mode, PKCS#7 and a random IV are directly visible.

Derive layout

The stream reserves 32 bytes, writes the IV and then places the HMAC at the start.

Preserve limits

The projection documents behaviour but is not a runtime measurement.

Limit: The shared secret is neither displayed nor published in derivable form.

Command-and-control protocol

Each message is serialised as a protobuf object and then encrypted with AES-256-CBC and PKCS#7 padding. A random 16-byte IV precedes the ciphertext; HMAC-SHA256 authenticates the IV and ciphertext together. The resulting packet starts with the 32-byte HMAC, followed by the IV and ciphertext. A four-byte little-endian length field frames transmission on the TCP stream.

This construction provides confidentiality and integrity inside the proprietary protocol. It does not conceal the destination or connection metadata and does not prevent host-based detection. The structure shown is a defensive protocol model, not an operational client.

csharpStatically supported transport profileReconstructed sample excerpt
CoreProjection/TransportProfile.cs · Lines 8-15
Show file hashSHA-256 8d1200016033d40ea3aa4469533aa30c322a424f8d488655cb2b46019a161962
public static class TransportProfile
{
    public const string Framing = "4-byte little-endian encrypted-payload length";
    public const string Serialization = "protobuf-net base message with ProtoInclude tags 1..10";
    public const string Encryption = "AES-256-CBC with PKCS#7 padding and a random 16-byte IV";
    public const string Authentication = "HMAC-SHA256 over IV || ciphertext";
    public const string WireLayout = "32-byte HMAC || 16-byte IV || ciphertext";
    public const string KeyDerivation = "PBKDF2/Rfc2898DeriveBytes, 5,000 iterations";
Read the code

Execution chain: persistence, tasking and process hollowing

After registration, the second stage can install under Local Application Data and persist through a scheduled task. Its tasking model covers file transfer, execution from disk or memory, PowerShell, status acknowledgement, cleanup and complete uninstall.

The in-memory path implements separate 32-bit and 64-bit process-hollowing helpers: create a suspended target, prepare image regions, allocate and write remote memory, update thread context and resume the primary thread. On Windows builds from 26100 onward, an additional compatibility or bypass branch modifies functions inside the target process's ntdll.

For defenders, this sequence is more reliable than any single indicator: a new scheduled task, RegisteredHandlers/Current, PowerShell, remote-memory writes, context modification and ResumeThread on the same host.

csharpDefensive behaviour matrix with ATT&CK mappingReconstructed sample excerpt
CoreProjection/BehaviorModel.cs · Lines 12-22
Show file hashSHA-256 0c9a01896488877b5933af083ca80aefec385e50c58ef66c524fcf4de213f131
    public static IReadOnlyList<BehaviorFinding> Findings { get; } = new[]
    {
        new BehaviorFinding("BL-001", "Two-stage loader", "Outer decrypts and decompresses a managed inner assembly.", "Exact/static", "T1027,T1140"),
        new BehaviorFinding("BL-002", "Custom TCP C2", "protobuf messages are protected with AES-CBC and HMAC-SHA256 and framed with a little-endian length.", "Static", "T1095"),
        new BehaviorFinding("BL-003", "Scheduled task persistence", "The install path creates and removes a configured scheduled task.", "Static", "T1053.005"),
        new BehaviorFinding("BL-004", "Download and execute", "Tag 4 selects disk, PowerShell or in-memory handling.", "Static", "T1105,T1059.001"),
        new BehaviorFinding("BL-005", "Process hollowing", "Separate 32-bit and 64-bit helpers replace a suspended process image.", "Static", "T1055.012"),
        new BehaviorFinding("BL-006", "Aggressive cleanup", "The cleanup path can terminate processes and delete startup material.", "Static", "T1070.004"),
        new BehaviorFinding("BL-007", "Host inventory", "Registration includes HWID, OS, user, AV, privilege, bitness, process and GPU data.", "Static", "T1082,T1518.001"),
        new BehaviorFinding("BL-008", "Windows 26100 compatibility patch", "The hollowing path patches functions inside target-process ntdll on newer builds.", "Static", "T1055.012")
    };
Read the code

Indicators of compromise and confidence

The filters separate file hashes, configured server values and local artifacts. A configured target is not evidence of successful contact or current control.

INDICATOR LEDGER

Indicators and attribution

Five statically supported indicators with context and evidentiary limit.

HASH-OUTERTelemetryhistorically supported
672320eb064f6d971e98c7cbfc5bfdd48541a992ccedac9b5550030953587c39
Role
SHA-256 of the outer sample
Evidence
Recorded as the initial sample in the manifested evidence set.
Source
Local hash manifest, checked 17 October 2026
Limit
No claim about current distribution or execution.
HASH-INNERTelemetryderivation supported
46e5ca3417006841884c4cca9d76a6fd03772ec54f4692079df9af8319a1505c
Role
SHA-256 of the inner assembly
Evidence
Mapped to the outer sample through the statically reconstructed unpacking chain.
Source
Local evidence set dated 17 October 2026
Limit
No claim about variants outside this evidence set.
C2-ADDRESSBackendconfigured; contact not observed
82[.]102[.]27[.]163
Role
Configured C2 target
Evidence
Reconstructed statically from bot configuration.
Source
Inner assembly, 17 October 2026 snapshot
Limit
No claim about reachability, ownership or present use.
C2-PORTSInfrastructureconfigured
TCP 45080 / 45050
Role
Alternative configured C2 ports
Evidence
Both values are embedded in configuration.
Source
Static configuration projection
Limit
Ports alone are a weak indicator.
HOST-PATHInfrastructuresupported in code
LocalAppData / RegisteredHandlers / Current
Role
Local installation, file and task components
Evidence
Components are referenced in installation and persistence paths.
Source
Static control-flow projection
Limit
Treat generic individual components as useful only in combination.

YARA: exact sample detection

The baseline rule relies exclusively on the three SHA-256 values confirmed in the evidence set. It is highly precise but will not detect rebuilt or modified variants. The size gate limits unnecessary hashing; the rule contains neither sample bytes nor reconstruction logic.

yaraHash-based YARA rule for the reviewed snapshotDefensive model
import "hash"

rule TW_BlueLoader_Exact_Samples_2026_10
{
    meta:
        description = "Exact BlueLoader artifacts from static review"
        author = "TW Research"
        date = "2026-10-17"
        confidence = "high / exact hash only"

    condition:
        filesize < 5MB and (
            hash.sha256(0, filesize) == "672320eb064f6d971e98c7cbfc5bfdd48541a992ccedac9b5550030953587c39" or
            hash.sha256(0, filesize) == "c706546279ba2781d349bdf8512651e0ec1e82e3172a1a700dd991d1d562b77f" or
            hash.sha256(0, filesize) == "46e5ca3417006841884c4cca9d76a6fd03772ec54f4692079df9af8319a1505c"
        )
}
Read the code

Sigma: local installation trace

The Sigma rule models a narrow filesystem trace: the combination of the reconstructed RegisteredHandlers directory component and the Current name component. It requires file-event telemetry and is intended for hunting. Environments should add known legitimate matches as filters first.

yamlSigma hunting rule for the reconstructed installation pathDefensive model
title: BlueLoader-Like LocalAppData Installation Trace
id: 4262753e-797b-46d0-96df-a84521dbf3f2
status: experimental
description: Detects the reviewed directory and filename components together
author: TW Research
date: 2026-10-17
logsource:
  category: file_event
  product: windows
detection:
  selection_path:
    TargetFilename|contains: '\\RegisteredHandlers\\'
  selection_name:
    TargetFilename|endswith:
      - '\\Current'
      - '\\Current.exe'
  condition: selection_path and selection_name
falsepositives:
  - Legitimate software using the same generic components
level: medium
tags:
  - attack.persistence
  - attack.t1053.005
Read the code

Suricata: configured infrastructure

This network rule is deliberately narrow and time-bound. It alerts only on outbound TCP connections to the address configured in the sample over either reviewed port. Before deployment, check reputation, current address ownership and local allowlists. A hit supports a connection attempt, not successful C2 communication.

suricataTime-bound IDS rule for destination and portsDefensive model
alert tcp $HOME_NET any -> 82.102.27.163 [45050,45080] (
    msg:"TW BlueLoader configured destination / review 2026-10-17";
    flow:to_server;
    classtype:trojan-activity;
    sid:99001701; rev:1;
    metadata:created_at 2026_10_17, confidence High, deployment Perimeter;
)
Read the code

KQL: correlate network and host

The hunting query combines the stronger approach: connections to the configured target must coincide within 15 minutes with the local path trace on the same device. It is written for Microsoft Defender XDR and must be adapted to the tables and retention actually available.

kqlCorrelation of network and file eventsDefensive model
let NetworkSignal = DeviceNetworkEvents
| where RemoteIP == "82.102.27.163"
| where RemotePort in (45050, 45080)
| project DeviceId, DeviceName, NetTime=Timestamp, RemoteIP, RemotePort;
let HostSignal = DeviceFileEvents
| where FolderPath contains @"\RegisteredHandlers\"
| where FileName in~ ("Current", "Current.exe")
| project DeviceId, HostTime=Timestamp, FolderPath, FileName;
NetworkSignal
| join kind=inner HostSignal on DeviceId
| where abs(datetime_diff('minute', NetTime, HostTime)) <= 15
| project NetTime, HostTime, DeviceName, RemoteIP, RemotePort, FolderPath, FileName
| order by NetTime desc
Read the code

Panel-to-bot correlation

The independent panel corpus contains structural counterparts for all ten protobuf message types implemented by the bot. Comparison did not rely on class names; it used ProtoInclude tags, field numbers, normalised field types and their call sites. The matched set covers configuration, registration, task delivery, acknowledgement, heartbeat, cleanup and uninstall.

This 10-of-10 parity is stronger than a shared string or similar user interface: it shows that both components implement the same message contract. The panel also adds licensing and update paths plus a local scanner for reverse-engineering tools. This supports a local anti-analysis path, but not an automatic server-side ban, operator identity or byte-identical build provenance.

Attribution assessment

We assess the bot as BlueLoader-compatible with high technical confidence. The basis is ten matching message contracts, corresponding control flows and the functional complement between client and panel. This assessment classifies software components—not people.

The evidence does not support conclusions about developers, customers, operators or infrastructure owners. The configuration value 12.09.2025 is likewise treated only as an embedded label; without an independent time source it is neither a build date nor a campaign start.

Conclusion

The reviewed evidence exposes a broader BlueLoader ecosystem than a loader-only analysis: a natively packaged management panel, a DNGuard-protected .NET application and a separate two-stage remote-control bot. BoxedApp obstructs direct access to the panel, DNGuard moves material logic into runtime-dependent native bodies, and the bot protects its proprietary protobuf protocol with AES-CBC and HMAC.

These layers still leave defensible detection opportunities. The strongest signal comes from correlated host and network behaviour: installation under Local Application Data, a scheduled task, recurring TCP connections to a configured destination, PowerShell and the characteristic process-hollowing sequence. The accompanying YARA, Sigma, Suricata and KQL examples operationalise those distinct evidence layers.

Findings at a glance

  • The panel sits behind a statically supported BoxedApp wrapper and a separately evidenced DNGuard protection layer.
  • The 460 KB loader decrypts and decompresses a second .NET assembly.
  • Metadata, protection runtimes and strictly attributed JIT bodies were reconstructed offline from the existing isolated panel minidump.
  • 9,514 delegate proxies and 990 string-resolver calls were resolved statically.
  • Bot and panel structurally match across all ten protobuf message types.
  • The strongest detection signal combines persistence, dual-port C2, PowerShell and process hollowing.

Review limits

  • The analysis reconstructs behaviour from code; it does not prove successful execution on a victim device.
  • Configured infrastructure proves neither current reachability nor ownership.
  • Reconstructed names are analytical labels, not recovered original source code.

Context, not evidence

The Evidence Anchor at the start identifies the binary, file or revision actually used. These links provide context and reported observations; they do not substitute for local sample analysis.

Zscaler ThreatLabz — Technical Analysis of PureCrypter (public structural comparison) ↗
Final assessment

Conclusion

Conclusion: structure survives obfuscation

BlueLoader combines heavy .NET obfuscation with a functionally complete bot. Its protection layers slowed analysis but did not permanently hide the transport profile or host capabilities. Independent matching of all ten message models is the strongest technical link to the panel.

Next steps

  • Correlate host and network signals as a timeline, not as isolated indicators.
  • Share IOCs with role, review date and evidentiary limit.
Basis of this judgmentHigh confidence in statically supported structure and capabilities; no claim about current infrastructure or operator identity.
BoxedApp-packaged panel, DNGuard-protected panel assembly, outer .NET bot loader, extracted inner assembly, static reconstructions and protocol models.
← All research audits

Start a conversation

Discuss your project.

Start a conversation