Skip to content

Steganographic C2

Malware hides commands and payloads inside the pixels or metadata of image and media files, so C2 rides in objects that look like harmless media.

Steganographic C2 hides tasking, configuration, or entire payloads inside the data of an innocuous-looking media file — most often a PNG, JPEG, GIF, or BMP, sometimes audio or video. The implant downloads or receives the image from a normal-looking host (a CDN, an image-sharing site, a web service), extracts the hidden bytes, and acts on them. To any inspecting device the transfer is just a picture: a valid file that renders correctly, with the C2 content woven into least-significant bits, appended after the image's logical end, or tucked into metadata fields.

The technique defeats content filters that judge files by type and rendering validity, and it pairs naturally with web-service or dead-drop channels — the image is hosted somewhere trusted, and only the implant knows it carries a payload. Stegoloader pulled its core module out of a PNG via least-significant-bit encoding, ZeroT delivered Cobalt Strike shellcode hidden in a bitmap, and the Lurk downloader concealed encrypted payloads inside image data.

For an analyst, the challenge is that the network and file artefacts look benign in isolation. The work is to recover the extraction routine from the implant, identify which carrier files it consumes, and pull the hidden bytes back out to recover the real commands or stage-two code.

How it works

The implant reads a downloaded image, walks the pixel data extracting hidden bits by a fixed scheme, and reassembles the concealed payload:

c
// Illustrative LSB extractor — descriptive, not deployable.
// Hidden bytes are recovered from the low bits of pixel channels.
size_t steg_extract(const uint8_t *pixels, size_t npix,
                    uint8_t *out, size_t out_cap)
{
    size_t bit = 0;
    for (size_t i = 0; i < npix && (bit / 8) < out_cap; i++) {
        // pull 1 bit per channel byte from the least-significant bit
        uint8_t b = pixels[i] & 0x01;
        out[bit / 8] = (out[bit / 8] << 1) | b;
        bit++;
    }
    size_t n = bit / 8;
    decrypt_inplace(out, n, EMBED_KEY);   // payload usually encrypted too
    return n;                              // -> shellcode or C2 config
}

The extracted bytes are typically encrypted, then either executed as shellcode/loaded as a module or parsed as a C2 config. Tells for a reverser: an image-parsing/decoding step (PNG/JPEG loader, GDI+/Bitmap calls) whose output feeds a bit-extraction loop and then a decrypt-and-execute path; a magic header or length field marking the start of the embedded blob; and an embed key constant. A normal image viewer renders pixels — it never harvests their low bits into executable memory.

Detection & analysis

Static analysis:

  • Identify the carrier format handling and the extraction scheme (LSB walk, appended-data offset, specific metadata/chunk such as a PNG tEXt/zTXt or a JPEG comment segment). The combination of image decoding followed by a bit/byte harvesting loop and a decrypt-then-run path is the defining static marker. Recover the embed key and the start-marker so you can extract from captured carriers.
  • Trace whether the extracted bytes are executed (allocated RWX, VirtualProtect, function-pointer call) or parsed as config. Execution of bytes lifted from image data is conclusive evidence of stegware.
  • Recover the carrier source URL(s); these reveal where the operator stages payloads and let defenders fetch and analyse the live image.

Dynamic analysis:

  • Capture downloaded media in a sandbox and run steganalysis: compare LSB-plane entropy, chi-square, and RS-analysis statistics against clean reference images. A weaponised carrier shows abnormal randomness in the low bit planes or unexpected data after the image's logical EOF.
  • Diff carrier file size and structure against a baseline of the same source — appended bytes after the terminating chunk (e.g. after a PNG IEND) or oversized metadata fields flag a hidden payload.
  • Run the reversed extractor against the captured image to pull and decrypt the embedded bytes, recovering the shellcode, module, or C2 configuration directly.

Detection rule hint:

Flag processes that fetch an image and then load or execute memory derived from its pixel/byte content — an image decode followed by allocation of executable memory or a config parse — and hunt carriers whose least-significant-bit planes show near-random entropy or that contain data past the format's logical end marker; pixels harvested into executable or config bytes, plus statistically anomalous LSB planes, are the signature of steganographic C2.

Votes

Comments(0)