Resource
The source-bound architecture begins with an embedded resource.
Review resource size, entropy and access path together.
Bound to primary researchMalware Analysis / Artefact: decrypt_payload.py · SHA-256 d44d008e7203…
Technical source review of the configurable Windows loader: resource format, layered decryption, anti-analysis, execution paths, persistence and defensible detection signals.
No first-party sample or telemetry analysis; no independent confirmation of C2, payload distribution, initial access or attribution.
The strongest lead is not a screenshot from a report but the format encoded in the extractor: footer, XOR stage and AES-GCM form a reviewable chain. We did not hold a 2CLoader binary.
d44d008e720351ba346aef227934800568721e9babbb2aa77c4c21a13abd7f2baa8b55c63411a0ec691b4023cfdf6a81e48e1641A footer and fixed magic identify the embedded configuration. The report binds this structure to the published companion code.
Rolling XOR, a second XOR step and AES-GCM form the documented decryption chain; optional Xpress Huffman decompression follows.
Depending on configuration, the loader selects different execution and persistence paths. Without a sample, their actual use remains explicitly unresolved.
Explanatory diagram, not live telemetry or an audit score. The article documents the assessment and its limits.
The analysis path for this report. Every node shows what is supported, where detection can start and where the claim stops.
The source-bound architecture begins with an embedded resource.
Review resource size, entropy and access path together.
Bound to primary researchA footer with a fixed marker describes the configuration location.
Validate the structure marker and offset relationships.
Bound to primary researchSeveral documented decoding and decryption steps prepare the payload.
Capture primitive, order and buffer hand-offs.
Bound to primary researchOptional decompression depends on the parsed configuration.
Join API use with the configuration branch.
Bound to primary researchThe source describes alternative execution paths; use in a concrete sample remains unresolved.
Separate memory, process and persistence signals by path.
Bounded or unresolvedReview pivots derived from the report — not a live configuration or universal family indicator.
Source, validation and limits accompany every rule.
rule Windows_Loader_2CLoader_Footer_Candidate {
meta:
author = "Ruhrdigital Studio"
scope = "synthetic structural hunt; not family attribution"
strings:
$footer_magic = { 2C 3D 4E 5F }
condition:
uint16(0) == 0x5a4d and filesize > 0xDC and $footer_magic in (filesize-0xDC..filesize-1)
}title: 2CLoader-style scheduled task persistence candidate
status: experimental
logsource:
product: windows
category: process_creation
detection:
task_tool:
Image|endswith: '\\schtasks.exe'
CommandLine|contains|all:
- '/create'
- '/sc'
- 'onlogon'
suspicious_name:
CommandLine|contains: 'SecurityHealthService.exe'
condition: task_tool and suspicious_name
falsepositives:
- Legitimate software using the same filename or task pattern
level: mediumThreatLabz published a technical analysis of 2CLoader and a Python payload-extraction tool on 30 September 2026. This review reads both primary sources against each other: which structure is actually encoded in the tool, which behavioural claims depend exclusively on ThreatLabz sample and telemetry analysis, and which defensive consequences follow?
We did not possess a 2CLoader sample. The companion code was not executed with malware. Runtime behaviour, delivered families and infrastructure therefore remain explicitly attributed to the primary source.
d44d008e720351ba346aef227934800568721e9babbb2aa77c4c21a13abd7f2bOfficial ThreatLabz companion tool pinned at commit aa8b55c6; read statically only for this review.
The report and companion code form two different evidence layers. The report describes observed samples, execution options and campaign telemetry. The tool implements resource discovery, footer structure and the decryption sequence. Without an original sample, this implementation cannot be replayed here against a concrete build.
The map separates the published report, reproducible tool snapshot and unavailable malware sample.
A file reference does not establish runtime behaviour. Recorded processing is not a new execution.
Two public primary sources; no local malware artifact.
Behavioural, sample and telemetry claims from the primary source.
The primary report links the ThreatLabz decryptor; its commit and file were pinned.
Hash-bound official parser and decryptor.
The primary report links the ThreatLabz decryptor; its commit and file were pinned.
No extraction, decryption or decompression was run without a sample.
No first-party binary, runtime or C2 evidence.
No extraction, decryption or decompression was run without a sample.
Limit: Publishing a decryptor establishes its intended handling of ThreatLabz-reviewed builds, not compatibility with every variant.
The public tool expects exactly 0xDC bytes of configuration at the end of the PE resource. A magic value identifies the footer; size fields separate the main payload, an optional additional file and an optional message. Other fields control persistence, anti-analysis, target process, sleep time and scheduled task.
This matters defensively because the footer links a statically visible structure to later behaviour. A magic value alone would be too brittle for detection; combined with PE-resource placement, plausible size relationships and subsequent process activity it becomes stronger.
SHA-256 d44d008e720351ba346aef227934800568721e9babbb2aa77c4c21a13abd7f2bdef parse_footer(footer_bytes: bytes) -> configfooter:
if struct.unpack_from("<I", footer_bytes, 0)[0] != FOOTER_MAGIC:
fail()
dwords = struct.unpack("<55I", footer_bytes)
return configfooter(
magic=dwords[0],
fl=dwords[1],
final_payload_size=dwords[2],
aes_gcm_nonce_size=dwords[3],
aes_gcm_tag_size=dwords[4],
aes_gcm_nonce=footer_bytes[0x14:0x20],
aes_gcm_tag=footer_bytes[0x20:0x30],
sha256_seed_xor2=footer_bytes[0x30:0x40],
sha256_seed_xor1=footer_bytes[0x40:0x50],
sum_of_bytes_checksum=dwords[20],
persistence=dwords[21],
opt_flag=dwords[22],
optional_payload_size=dwords[23],
optional_message_size=dwords[24],
xor_add_after_rolling_xor=footer_bytes[0x64],
xor_key_after_rolling_xor=footer_bytes[0x65],
rolling_xor_seed=footer_bytes[0x66],
unk_67=footer_bytes[0x67],
sleeptime=dwords[26],
beacon_id=footer_bytes[0x6C:0x7C],
target_executable_name_used_in_injection=footer_bytes[0x7C:0xBC],
bt=dwords[47],
pn=footer_bytes[0xC0:0xD0],
unk_D0=dwords[52],
scheduled_tasks_trigger_interval_hours=dwords[53],
decompressed_buffer_size=dwords[54],
)
Original source-file lines. Choose a note to highlight its range.
The documented processing path is fixed: locate the resource, apply rolling XOR, apply a second XOR stage, derive a key from configuration and code hash, perform authenticated AES-GCM decryption and optionally decompress Xpress Huffman. Only then are the main payload, optional extra file and message block separated.
AES-GCM does not protect the victim here; it protects the embedded payload from simple static extraction. The authentication tag also creates a hard validation step: incorrect key derivation or altered data breaks the chain.
SHA-256 d44d008e720351ba346aef227934800568721e9babbb2aa77c4c21a13abd7f2bdef extract_decode_and_write(pe_path: str | Path, out_dir: str | Path):
resource = find_footer_resource(pe_path)
footer = resource["footer"]
out_dir = Path(out_dir)
out_dir.mkdir(parents=True, exist_ok=True)
section_sha256_seed = compute_section_sha256_seed(pe_path)
stage1 = decode_resource_stage(resource["body"], footer.rolling_xor_seed)
stage2 = xor_decrypt_payload(bytearray(stage1), footer.xor_add_after_rolling_xor, footer.xor_key_after_rolling_xor)
aes_key = generate_aes_key(footer, section_sha256_seed)
aes_plaintext = aes_gcm_decrypt(stage2, footer, aes_key)
final_buffer = decompress_final_payload(aes_plaintext, footer)
main_payload, dropped_payload, message_block = split_body_parts(final_buffer, footer)
Original source-file lines. Choose a note to highlight its range.
ThreatLabz describes VM, debugger, timing and user-activity checks. Most importantly, one timing check is coupled to decryption: it can alter the intermediate SHA-256 value and thereby produce an incorrect AES key. This does not require a separate visible exit; it makes the payload chain fail cryptographically.
ThreatLabz also reports indirect system calls and inline trampolines intended to influence what user-mode security products and the delivered payload observe. Their runtime effect was not measured independently here.
The primary report describes in-memory .NET execution, manual LoadPE in the loader process and RunPE in a suspended target process. Configuration flags can control fallbacks between the native paths. An optional second dropped file and decoy message may be added.
Persistence can use Run, RunOnce, the Startup folder, scheduled tasks, the Load registry value or UserInitMprLogonScript. For defenders, the useful signal is not one method alone but the sequence of new autorun configuration, suspicious process start or manipulation and subsequent beacon traffic.
A defensible model should connect three layers. First, static structure: a PE resource with the matching footer magic, plausible size relationships and option fields. Second, host behaviour: new persistence followed by process manipulation or in-memory CLR loading. Third, network: a timely HTTP POST from a newly started, unexpected process.
The Sigma example below is a defensive correlation model for one high-signal persistence branch. It was not validated with a Sigma engine here and must be adapted to product fields, legitimate software distribution and local naming conventions.
title: 2CLoader-style scheduled task persistence candidate
status: experimental
logsource:
product: windows
category: process_creation
detection:
task_tool:
Image|endswith: '\\schtasks.exe'
CommandLine|contains|all:
- '/create'
- '/sc'
- 'onlogon'
suspicious_name:
CommandLine|contains: 'SecurityHealthService.exe'
condition: task_tool and suspicious_name
falsepositives:
- Legitimate software using the same filename or task pattern
level: medium
Line numbers refer to this excerpt. Choose a note to highlight its range.
ThreatLabz observed 2CLoader primarily delivering Vidar and Remus, with XWorm also present. This describes delivery relationships in the reviewed campaigns. It does not establish common authorship of loader and payloads, nor that every future 2CLoader build delivers the same families.
Likewise, filenames, message text, target process or individual C2 indicators do not establish operator identity. This report therefore makes no actor attribution.
The report and official decryptor agree on the core structural claims: footer size and magic, three-part resource, staged decryption, code-bound key derivation and optional decompression. The primary source adds anti-analysis, persistence, execution options and campaign observations.
What is not established is first-party replay against a sample. This review therefore assesses architecture and defensive consequences, not the functionality of a specific sample or completeness across variants.
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 — 2CLoader technical analysis ↗ThreatLabz tools — decrypt_payload.py (commit aa8b55c6) ↗2CLoader combines payload protection, anti-analysis, flexible execution and persistence in a configurable intermediate layer. That breadth also creates signals that can be joined: resource structure, decryption parameters, autorun changes, process manipulation and status traffic. The strongest defensive approach correlates these layers instead of treating a name, hash or magic value as family proof.
Start a conversation