typeanalysisfamilyunclassified-batch-selfextract-dotnet-dropperconfidencemediumcreated2026-07-08updated2026-07-08scriptdropperdotnetobfuscationdefense-evasionexecutionc2
SHA-256: 51500e40881f7a9c6c0a556af80e9c93d35dd0f08472dafa3bf8ce899769f0c8

Unclassified Batch Self-Extract .NET Dropper: 51500e40 — Shipping-invoice BAT→PowerShell→ConfuserEx .NET chain with byte-reversed gzip payload

Executive Summary

A 2.4 MB batch-script dropper masquerading as a shipping-container arrival notice (Arrival_Notice_Invoice_for_Container_No_FBLU0089027.bat). The outer .bat uses Unicode Armenian/Cyrillic variable-name obfuscation and a copy /b /y self-extraction trick (renaming itself to .Seu) to hide a gzip+Base64-encoded .NET Framework 4.5 payload inside the script body. A PowerShell cradle decodes the payload, byte-reverses it, and reflectively loads the resulting PE. The inner PE is a ConfuserEx-obfuscated .NET assembly with two embedded encrypted resources, System.Web imports, and no recoverable C2 at static time. No CAPE detonation possible (text file). ^[file.txt] ^[strings.txt:1-50]

What It Is

Field Value
SHA-256 51500e40881f7a9c6c0a556af80e9c93d35dd0f08472dafa3bf8ce899769f0c8
Filename Arrival_Notice_Invoice_for_Container_No_FBLU0089027.bat
Size 2,441,640 bytes (2.4 MB)
File type Unicode text, UTF-8, very long lines (56,650 chars), CRLF
OpenCTI labels bat, malware-bazaar
Family (preliminary) unattributed
Compile timestamp Sep 6 02:19:39 2024 (inner PE)

The batch script is a polyglot: valid DOS batch syntax on top, a self-contained gzip archive appended below the exit command. The attacker reuses the container-shipping social-engineering theme (FBLU0089027 — a plausible container ID format).

How It Works

Stage 1: Self-Extraction (BAT)

The outer batch uses three tricks:

  1. Unicode variable-name obfuscationSET commands use Armenian block characters (U+0530–U+058F) and Cyrillic extensions as variable names, making static reconstruction impossible without parsing the expansion. ^[strings.txt:1-30]
  2. Archive self-attachment — The script copies itself to %~0.Seu, creating a valid archive file (.Seu is interpreted as an extension, not an archive format per se; the payload lives after the exit line). ^[strings.txt:232-250]
  3. Silent attribute flipattrib +s +h on the .Seu copy to hide it. ^[strings.txt:21-22]

Stage 2: PowerShell Cradle

A single-line %VARNAME% expansion reassembles into:

powershell.exe -WindowStyle Hidden -command "..."

The PowerShell payload:

  • Reads the .bat file from disk
  • Extracts everything after the exit line (offset ~8886)
  • Base64-decodes the trailing string
  • GZip-decompresses the result
  • Byte-reverses the entire decompressed buffer (reversal detected: first byte 0x00, last byte 0x4d, reversed → MZ\x90...)
  • Loads the resulting PE reflectively via [System.Reflection.Assembly]::Load ^[reconstructed from strings.txt:60-250]

Stage 3: Inner .NET Payload

After reversal, the payload is a valid PE32 .NET Framework 4.5 assembly:

Property Value
Module name Arrival Notice Invoice for Container No FBLU0089027.exe
MVID eb399d60-1f72-4ae7-05cc-fed47baee125
Assembly version 1.0.0.0
Sections .text (2,091,008 bytes), .rsrc (2,048 bytes), .reloc (512 bytes)
Imports mscoree.dll!_CorExeMain only
Compile timestamp 2024-09-06 02:19:39 UTC

Obfuscation: ConfuserEx — method and type names are mangled to base64-like tokens (#=q…== not observed; instead the obfuscator uses plausible English semantic names like ImageResizer.Workers.TokenDatabaseWorker, ResolveWrapper, LoginWrapper, QueryWrapper, etc.). This is consistent with ConfuserEx's "rename to dictionary words" option rather than the classic #=q…== mangling. ^[dnfile]

Resources: Two embedded .NET manifest resources:

  • Qsskqqjy.Properties.Resources.resources — 1,625,306 bytes, .resources format (magic 0xBEEFCACE), containing 145 named entries (likely encrypted config / stage data). ^[dnfile]
  •    ​           (Unicode whitespace name) — 16,511 bytes, high-entropy, no recognizable header. Repeating bigram 44 7d suggests XOR or stream-cipher encryption. ^[dnfile]

Assembly references: mscorlib, System.Web, System, System.Configuration, System.Drawing, System.Xml, System.Core. The System.Web reference is notable for HTTP C2 or web-shell behaviors. ^[dnfile]

Decompiled Behavior

Ghidra / radare2 are not applicable here (scripted dropper, not a native PE). The decompilation of the inner .NET payload via dnfile reveals:

  • No hardcoded C2 — all strings observed are framework / obfuscator artifacts. C2 is likely runtime-decrypted from the 16 KB encrypted resource.
  • Web-facing surfaceSystem.Web namespace imports (HttpException, HttpContext, HttpApplication, HttpRequest, HttpResponse, HttpRuntime, IHttpHandler, IHttpModule) indicate the payload may function as a hidden HTTP handler, web-shell, or C2 client. ^[dnfile]
  • No persistence hooks visible in static metadata. Persistence may be established by the .NET payload at runtime.

C2 Infrastructure

Not recoverable statically. No IP, domain, URL, mutex, or named pipe found in:

  • Batch script strings (obfuscated via variable expansion)
  • Inner .NET strings (encrypted at rest by ConfuserEx)
  • Resource data (encrypted / compressed)

The 16,511-byte encrypted resource is the most likely C2 config carrier. Decryption would require runtime instrumentation or deobfuscation of the ConfuserEx layer.

Interesting Tidbits

  • Container-ID lureFBLU0089027 follows the ISO 6346 container-code format (4-letter owner code + 6-digit serial + 1 check digit). This is a high-effort social-engineering detail. ^[strings.txt:232-250]
  • Self-attaching archive — The payload is not fetched from the internet; it is embedded in the .bat itself. This makes the sample fully self-contained and operational offline. ^[reconstructed from strings.txt:232-250]
  • Byte reversal — The gzip-decompressed payload is stored backwards. This is an uncommon anti-signature trick: standard tools scanning for MZ at the start of a gzip stream will find nothing. ^[payload extraction]
  • 2010 copyright masquerade — VS_VERSIONINFO claims copyright 2010, product name matching the lure. ^[rabin2-info.txt]
  • Batch-to-.NET size ratio — The outer batch is 2.4 MB, the inner PE is 2.09 MB. The overhead is the obfuscated variable-assignment noise (~300 KB of SET lines). ^[file.txt]

How To Mess With It (Homelab Replication)

  1. Build the chain
    # Encode your payload
    $bytes = [IO.File]::ReadAllBytes("payload.exe")
    [Array]::Reverse($bytes)
    $gz = [Convert]::ToBase64String((New-Object IO.MemoryStream(,($bytes | ForEach-Object {$_}))).ToArray())
    # ... then gzip-compress and base64-wrap
    
  2. Embed in batch
    • Write a .bat with Armenian-variable SET assignments.
    • Append the gzip+Base64 payload after an exit line.
    • Use %~0.Seu self-copy to hide the archive copy.
  3. Verify evasion
    • Static string extraction on the .bat should not surface powershell, FromBase64String, or the payload MZ header.
    • Only the expanded %VAR% line (at runtime) reveals the cradle.

Deployable Signatures

YARA rule

rule Batch_GZip_Reversed_NET_Dropper {
    meta:
        description = "Batch self-extract dropper with gzip+reversed .NET payload"
        author = "PacketPursuit SOC"
        date = "2026-07-08"
        sha256 = "51500e40881f7a9c6c0a556af80e9c93d35dd0f08472dafa3bf8ce899769f0c8"
    strings:
        $a = "%~0.Seu" ascii
        $b = "attrib" ascii wide
        $c = "H4sI" ascii wide               // gzip magic in base64
        $d = "powershell" ascii wide nocase
        $e = "-WindowStyle Hidden" ascii wide nocase
        $f = /set\s+"[\x{0530}-\x{058F}]+=/ wide
    condition:
        filesize > 1MB and
        #a >= 1 and
        #c >= 1 and
        4 of them
}

Sigma rule

title: Batch Self-Extract PowerShell Reversed .NET Payload
logsource:
    product: windows
    category: process_creation
detection:
    selection:
        CommandLine|contains:
            - 'powershell'
            - '-WindowStyle Hidden'
        ParentImage|endswith: '\cmd.exe'
        ParentCommandLine|contains:
            - '.bat'
            - '.cmd'
    condition: selection
falsepositives:
    - Legitimate IT automation scripts
level: medium

IOC list

Indicator Type Note
Arrival_Notice_Invoice_for_Container_No_FBLU0089027.bat Filename Lure
Arrival_Notice_Invoice_for_Container_No_FBLU0089027.exe Internal module name Inner PE
51500e40881f7a9c6c0a556af80e9c93d35dd0f08472dafa3bf8ce899769f0c8 SHA-256 Outer batch
eb399d60-1f72-4ae7-05cc-fed47baee125 MVID Inner .NET assembly
~0.Seu File artifact Self-extraction archive copy

Behavioral fingerprint

This sample is a text-file dropper that spawns powershell.exe -WindowStyle Hidden with a command-line exceeding 56,000 characters (the expanded %VAR% chain). The PowerShell reads its own parent .bat from disk, extracts a gzip+Base64 payload after the exit line, decompresses it, byte-reverses the result, and reflectively loads a 2 MB .NET Framework 4.5 assembly. The inner assembly imports System.Web and carries two encrypted manifest resources totaling ~1.64 MB. No network indicators are visible statically.

Detection Signatures

Capability Evidence ATT&CK
Batch script execution cmd.exe running .bat file T1059.003
PowerShell reflective execution Assembly.Load(byte[]) in decoded PowerShell T1059.001
Obfuscated command line Unicode variable expansion >56K chars T1027.010
Self-extraction copy /b /y %~0 %~0.Seu T1027.002
In-memory payload loading Reflective .NET assembly load T1620
Data encoding GZip + Base64 + byte reversal T1027

References

Provenance

  • Outer file type: file(1) on batch script ^[file.txt]
  • Inner PE analysis: rabin2 -I, dnfile, pefile on extracted reversed payload ^[rabin2-info.txt]
  • String extraction: strings on both outer batch and inner PE ^[strings.txt]
  • Resource enumeration: dnfile dn.net.resources and dn.net.mdtables.ManifestResource ^[dnfile]
  • FLOSS: Not applicable (text file, not a PE) ^[floss.txt]
  • CAPA: Not applicable ^[capa.txt]
  • CAPE: Skipped — unsupported file type for detonation ^[dynamic-analysis.md]