reverse-skills-max: initial public release (restored, redacted, hardened)

This commit is contained in:
baradok609hecl1pq6qi
2026-10-20 02:17:15 +03:00
commit da24c2bd20
2227 changed files with 443931 additions and 0 deletions

View File

@@ -0,0 +1,9 @@
Apache License 2.0 — see the repository root LICENSE file for the full text.
Copyright the AnalystAIPack contributors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0

View File

@@ -0,0 +1,111 @@
---
name: deobfuscating-malicious-powershell
description: 'Deobfuscates malicious PowerShell by decoding -EncodedCommand, reversing string
and format obfuscation, resolving base64/gzip/IEX layers, and recovering the final payload
and IOCs. Activates for requests to deobfuscate, decode, or analyze obfuscated PowerShell
commands or scripts.'
domain: cybersecurity
subdomain: malware-analysis
tags:
- malware
- powershell
- deobfuscation
- base64
- script-analysis
- windows
version: 1.0.0
author: analyst-ai-pack
license: Apache-2.0
mitre_attack:
- T1059.001
- T1027
- T1140
d3fend:
- D3-FCR
- D3-DA
references:
- 'PowerShell about_PowerShell.exe -EncodedCommand — https://learn.microsoft.com/powershell/'
- 'PSDecode — https://github.com/R3MRUM/PSDecode'
---
# Deobfuscating Malicious PowerShell
## When to Use
- You captured an obfuscated PowerShell command from a log, maldoc, or phishing payload.
- You need to recover the real intent: download URLs, dropped paths, shellcode, or next stage.
- You are unrolling layered encoding (base64 → gzip → IEX) to reach the final script.
**Do not use** `Invoke-Expression` or run the script to "see what it does" on a working host.
Decode statically; only execute in the isolated lab with logging if dynamic confirmation is
required.
## Prerequisites
- Python (bundled script handles base64/gzip/deflate and common transforms), or a sandbox.
- The command/script text captured as a string.
## Safety & Handling
- Never pipe attacker PowerShell into a live shell. Replace `IEX`/`Invoke-Expression` with
output (print) when transforming.
- Treat decoded URLs/IPs as live; defang before sharing.
## Workflow
### Step 1: Decode -EncodedCommand
`-EncodedCommand` (`-enc`) is base64 of UTF-16LE. Decode it first:
```bash
python scripts/analyst.py decode --encodedcommand "<base64>"
```
### Step 2: Identify the obfuscation style
Common patterns:
```text
String reversal : [array]::Reverse / -join with [-1..]
Format operator : ("{1}{0}" -f 'b','a') -> 'ab'
Char codes : [char]104 + [char]105
Concatenation/splits : 'po'+'wer'+'shell', -split / -replace tricks
Backtick/casing noise : I`E`X, iEx, &('i'+'ex')
```
### Step 3: Unroll encoding layers
Resolve nested `FromBase64String`, gzip/deflate (`IO.Compression`), and re-IEX layers until
you reach plain script. The script peels base64/gzip layers automatically.
```bash
python scripts/analyst.py deobfuscate payload.ps1
```
### Step 4: Neutralize execution sinks
Replace `IEX`, `Invoke-Expression`, `&`, and `.Invoke()` with a print so the recovered script
is rendered, not run.
### Step 5: Extract IOCs
Pull `DownloadString`/`DownloadFile` URLs, C2 hosts, dropped paths, and any embedded
base64 shellcode for separate analysis.
## Validation
- The fully decoded script is human-readable PowerShell with no remaining base64 blobs.
- Execution sinks are neutralized; nothing in your workflow actually ran the payload.
- Extracted URLs/paths are consistent with the script's logic.
## Pitfalls
- Running the script to decode it — the fastest way to get compromised.
- Stopping after one base64 layer when several are nested.
- Missing UTF-16LE vs UTF-8 when decoding `-enc` (it is UTF-16LE).
- Ignoring `-replace`/`-f` transforms that rebuild commands at runtime.
## References
- See [`references/api-reference.md`](references/api-reference.md) for the decoder/deobfuscator.
- PowerShell encoded-command docs and PSDecode (linked in frontmatter).

View File

@@ -0,0 +1,48 @@
# API Reference: Deobfuscating Malicious PowerShell
## Overview
`scripts/analyst.py` decodes `-EncodedCommand` (base64 UTF-16LE), peels nested base64 plus
gzip/deflate layers, neutralizes execution sinks (`IEX`, `Invoke-Expression`), and extracts
URLs. It never runs PowerShell.
## Dependencies
| Package | Version | Purpose |
|---------|---------|---------|
| (stdlib) | — | base64, gzip, zlib, regex |
## External tools
| Tool | Purpose |
|------|---------|
| PSDecode | Emulated unrolling of heavily layered scripts |
| CyberChef | Interactive multi-step decoding |
## Core functions
### `decode_encodedcommand(b64)`
Decodes a `-EncodedCommand`/`-enc` blob (base64 of UTF-16LE) to text.
### `peel_layers(text, max_depth)`
Iteratively decodes the largest base64 blob and attempts gzip/deflate/UTF-16 decompression,
returning each layer.
### `neutralize(text)`
Replaces `IEX`/`Invoke-Expression` with output statements so recovered scripts are not run.
### `extract_iocs(text)`
Collects URLs across all decoded layers.
## Usage
```bash
python scripts/analyst.py decode --encodedcommand "<base64>"
python scripts/analyst.py deobfuscate payload.ps1
```
## Sources
- PowerShell `-EncodedCommand` semantics (UTF-16LE base64) — https://learn.microsoft.com/powershell/
- PSDecode — https://github.com/R3MRUM/PSDecode
- Common PowerShell obfuscation transforms (format operator, char codes, reversal)

View File

@@ -0,0 +1,111 @@
#!/usr/bin/env python3
"""Deobfuscate malicious PowerShell without executing it.
Decodes ``-EncodedCommand`` (base64 UTF-16LE), peels nested base64 + gzip/deflate layers,
applies a few common string transforms, and extracts IOCs. It transforms text only and never
invokes PowerShell.
"""
from __future__ import annotations
import argparse
import base64
import binascii
import gzip
import json
import re
import sys
import zlib
from pathlib import Path
_URL = re.compile(r"https?://[^\s\"'<>)]+", re.I)
_B64 = re.compile(r"[A-Za-z0-9+/]{40,}={0,2}")
def decode_encodedcommand(b64: str) -> str:
raw = base64.b64decode(b64)
# -EncodedCommand payloads are UTF-16LE
try:
return raw.decode("utf-16-le")
except UnicodeDecodeError:
return raw.decode("latin-1", "replace")
def _try_decompress(raw: bytes) -> str | None:
for fn in (lambda b: gzip.decompress(b),
lambda b: zlib.decompress(b),
lambda b: zlib.decompress(b, -15)):
try:
return fn(raw).decode("utf-8", "replace")
except (OSError, zlib.error, binascii.Error):
continue
return None
def peel_layers(text: str, max_depth: int = 6) -> list[str]:
"""Return successive decoded layers, peeling base64(+gzip/deflate) blobs."""
layers = [text]
current = text
for _ in range(max_depth):
blobs = _B64.findall(current)
if not blobs:
break
blob = max(blobs, key=len)
try:
raw = base64.b64decode(blob + "=" * (-len(blob) % 4))
except binascii.Error:
break
decoded = _try_decompress(raw)
if decoded is None:
try:
decoded = raw.decode("utf-16-le")
except UnicodeDecodeError:
decoded = raw.decode("utf-8", "replace")
if not decoded or decoded == current:
break
layers.append(decoded)
current = decoded
return layers
def neutralize(text: str) -> str:
"""Render execution sinks inert for safe display."""
text = re.sub(r"\bI`?E`?X\b", "echo", text, flags=re.I)
text = re.sub(r"\bInvoke-Expression\b", "Write-Output", text, flags=re.I)
return text
def extract_iocs(text: str) -> dict:
return {"urls": sorted(set(_URL.findall(text)))}
def deobfuscate(text: str) -> dict:
layers = peel_layers(text)
final = neutralize(layers[-1])
return {
"layer_count": len(layers),
"final_script": final,
"iocs": extract_iocs("\n".join(layers)),
}
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(description="Deobfuscate PowerShell")
sub = parser.add_subparsers(dest="cmd", required=True)
p_e = sub.add_parser("decode", help="decode -EncodedCommand")
p_e.add_argument("--encodedcommand", required=True)
p_d = sub.add_parser("deobfuscate", help="peel layers from a script file")
p_d.add_argument("file")
args = parser.parse_args(argv)
if args.cmd == "decode":
print(decode_encodedcommand(args.encodedcommand))
return 0
text = Path(args.file).read_text(encoding="utf-8", errors="replace")
print(json.dumps(deobfuscate(text), indent=2))
return 0
if __name__ == "__main__":
sys.exit(main())