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,90 @@
---
name: analyzing-webshells
description: 'Analyzes suspected webshells (PHP, ASPX/ASP, JSP) by detecting dynamic-execution
sinks, input-to-sink data flow, and common encoder/obfuscation chains, then decoding obvious
layers to reveal the command interface. Activates for requests to analyze a webshell, identify a
PHP/ASPX/JSP backdoor, or deobfuscate server-side malicious scripts.'
domain: cybersecurity
subdomain: malware-analysis
tags:
- malware-analysis
- webshell
- php
- aspx
- server-side
version: 1.0.0
author: analyst-ai-pack
license: Apache-2.0
mitre_attack:
- T1505.003
- T1059
- T1027
d3fend:
- D3-FCR
- D3-DA
references:
- 'MITRE ATT&CK T1505.003 Web Shell — https://attack.mitre.org/techniques/T1505/003/'
- 'OWASP web shell detection guidance — https://owasp.org/'
---
# Analyzing Webshells
## When to Use
- You found a suspicious server-side script (`.php`, `.aspx`, `.jsp`, `.asp`) and need to confirm
it is a webshell and understand its command interface.
- You are triaging a web-server compromise and want to classify dropped scripts.
**Do not use** a live web server to execute the script to "test" it — that runs attacker code.
Analyze the source statically.
## Prerequisites
- The suspect script file(s), read inertly.
## Safety & Handling
- Read the file statically; never deploy or request it on a live server. Defang any URLs.
## Workflow
### Step 1: Detect execution sinks and input flow
```bash
python scripts/analyst.py scan shell.php
```
Flags dynamic-execution sinks (`eval`, `assert`, `system`, `exec`, `passthru`, `Runtime.exec`,
ASPX `eval()`/`Process.Start`) and whether request input (`$_GET`/`$_POST`/`Request`) reaches them.
### Step 2: Identify obfuscation/encoder chains
Detects `base64_decode`, `gzinflate`, `str_rot13`, `eval(chr(...))`, hex `\x` strings, and
`FromBase64String` chains commonly wrapping the payload.
### Step 3: Decode obvious layers
Apply base64/rot13/gzinflate where present to reveal the inner command interface (best-effort,
non-executing).
### Step 4: Classify and report
Note the language, the password/parameter gate (if any), and capabilities (file manager, command
exec, SQL, upload); defang IOCs.
## Validation
- A flagged file pairs an execution sink with attacker-controlled input.
- Encoder chains are identified and, where safe, decoded statically.
- Capability classification is backed by concrete code evidence.
## Pitfalls
- Legitimate admin tools that also use `eval`/`system` — corroborate with input flow.
- Multi-stage shells that fetch the real logic remotely.
- Deeply nested or runtime-built obfuscation that static decode only partly unwinds.
## References
- See [`references/api-reference.md`](references/api-reference.md) for the scanner.
- ATT&CK T1505.003 (linked in frontmatter).

View File

@@ -0,0 +1,41 @@
# API Reference: Analyzing Webshells
## Overview
`scripts/analyst.py` scans a server-side script (PHP/ASPX/JSP) for dynamic-execution sinks,
request-input-to-sink data flow, and encoder chains, and best-effort decodes base64/raw-deflate
layers that wrap webshell logic. It reads the file statically, executes nothing, and defangs URLs.
## Dependencies
| Package | Version | Purpose |
|---------|---------|---------|
| (stdlib) | — | base64, zlib, regex, JSON, file IO |
## Core functions
### `scan(path)`
Returns language, execution sinks, input sources, an input-to-sink flow flag, encoder chains,
decoded layers, defanged URLs, and a webshell likelihood flag.
### `_decode_layers(text)`
Decodes base64 (and raw-deflate) blobs and keeps those whose plaintext contains execution sinks.
## Detection logic
- **Sinks**: PHP `eval`/`system`/`passthru`/`preg_replace /e`; ASPX `eval`/`Process.Start`;
JSP `Runtime.exec`/`ProcessBuilder`.
- **Input flow**: a sink plus `$_GET`/`$_POST`/`Request`/`getParameter` raises confidence.
- **Encoders**: `base64_decode`, `gzinflate`, `str_rot13`, `FromBase64String`, `\x` hex.
## Usage
```bash
python scripts/analyst.py scan shell.php
```
## Sources
- MITRE ATT&CK T1505.003 Web Shell — https://attack.mitre.org/techniques/T1505/003/
- Server-side execution sink and encoder-chain patterns from public webshell research
- PHP/ASP/JSP language execution APIs from their official documentation

View File

@@ -0,0 +1,91 @@
#!/usr/bin/env python3
"""Scan a server-side script for webshell indicators and decode obvious obfuscation.
Detects dynamic-execution sinks, request-input-to-sink flow, and common encoder chains across PHP,
ASP/ASPX, and JSP, then best-effort decodes base64/rot13/gzinflate layers. Reads the file
statically; executes nothing and never deploys the script. Defangs recovered URLs.
"""
from __future__ import annotations
import argparse
import base64
import binascii
import json
import re
import sys
import zlib
from pathlib import Path
SINKS = {
"php": ["eval(", "assert(", "system(", "exec(", "passthru(", "shell_exec(", "popen(",
"proc_open(", "preg_replace(/.*/e"],
"aspx": ["eval(", "process.start", "executereader", "createobject(\"wscript.shell\")",
"scriptengine"],
"jsp": ["runtime.getruntime().exec", "processbuilder", "scriptengine", ".eval("],
}
INPUT_SOURCES = ["$_get", "$_post", "$_request", "$_cookie", "request.form", "request.querystring",
"request.getparameter", "request[", "php://input"]
ENCODERS = ["base64_decode", "gzinflate", "gzuncompress", "str_rot13", "frombase64string",
"eval(chr", "\\x", "hex2bin", "convert.frombase64string"]
RE_URL = re.compile(r"https?://[^\s\"'<>)]+", re.I)
RE_B64 = re.compile(r"[A-Za-z0-9+/]{40,}={0,2}")
def _defang(s: str) -> str:
return s.replace("http", "hxxp").replace(".", "[.]")
def _decode_layers(text: str) -> list[str]:
out = []
for blob in RE_B64.findall(text)[:50]:
try:
raw = base64.b64decode(blob, validate=True)
except (binascii.Error, ValueError):
continue
candidate = raw
try:
candidate = zlib.decompress(raw, -15) # gzinflate (raw deflate)
except zlib.error:
pass
printable = candidate.decode("latin-1", "ignore")
if any(s in printable.lower() for lst in SINKS.values() for s in lst):
out.append(printable[:200])
return out[:10]
def scan(path: str) -> dict:
text = Path(path).read_text(encoding="utf-8-sig", errors="replace")
low = text.lower()
lang = ("php" if "<?php" in low or path.endswith(".php")
else "aspx" if path.endswith((".aspx", ".asp")) or "<%@" in low
else "jsp" if path.endswith(".jsp") or "<%@ page" in low else "unknown")
sink_set = SINKS.get(lang, [s for lst in SINKS.values() for s in lst])
sinks = sorted({s.rstrip("(") for s in sink_set if s in low})
inputs = sorted({i for i in INPUT_SOURCES if i in low})
encoders = sorted({e for e in ENCODERS if e in low})
urls = sorted({_defang(u) for u in RE_URL.findall(text)})
input_reaches_sink = bool(sinks and inputs)
return {
"language": lang,
"execution_sinks": sinks,
"input_sources": inputs,
"input_to_sink_flow": input_reaches_sink,
"encoder_chains": encoders,
"decoded_layers": _decode_layers(text),
"urls": urls[:50],
"is_likely_webshell": bool(sinks and (inputs or encoders)),
}
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(description="Analyze a suspected webshell")
sub = parser.add_subparsers(dest="cmd", required=True)
p = sub.add_parser("scan")
p.add_argument("file")
args = parser.parse_args(argv)
print(json.dumps(scan(args.file), indent=2))
return 0
if __name__ == "__main__":
sys.exit(main())