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,103 @@
---
name: writing-yara-rules-from-reversed-code
description: 'Turns reverse-engineering findings into durable YARA detections: selecting stable
code constructs and constants over volatile strings, extracting opcode/byte patterns with
wildcards, and validating rules for low false positives. Activates for requests to write a
YARA rule from reversed code, create a detection signature, or convert RE findings into
hunting rules.'
domain: cybersecurity
subdomain: reverse-engineering
tags:
- reverse-engineering
- yara
- detection
- signatures
- threat-hunting
version: 1.0.0
author: analyst-ai-pack
license: Apache-2.0
mitre_attack:
- T1027.001
- T1587.001
d3fend:
- D3-FCR
- D3-FA
references:
- 'YARA documentation — https://yara.readthedocs.io/'
- 'YARA writing-better-rules guidance — https://github.com/Neo23x0/YARA-Style-Guide'
---
# Writing YARA Rules from Reversed Code
## When to Use
- You finished reversing a sample/family and want a detection that survives recompilation and
cosmetic changes.
- You need byte-pattern signatures from decryptors, API-hash constants, or unique algorithms
rather than fragile strings.
- You are converting RE notes into hunting/scanning rules for a corpus.
**Do not use** volatile artifacts (file paths, mutex names that change per build, packer stubs
shared across unrelated families) as your primary anchor — they cause drift and false hits.
## Prerequisites
- The `yara` engine (and ideally `yara-python`) for testing.
- A small corpus: target samples (true positives) and clean/unrelated files (false-positive
control).
## Workflow
### Step 1: Choose stable anchors
Prefer, in order: a unique algorithm's opcode sequence (decryptor, hashing loop), embedded
magic constants (API hashes, XOR keys, S-box), then distinctive strings only if intrinsic.
### Step 2: Extract byte patterns with wildcards
Pull the relevant opcodes and wildcard volatile operands (addresses, immediates) so the rule
survives relocation/recompilation:
```text
$dec = { 8A 04 ?? 34 ?? 88 04 ?? 41 3B ?? 7? ?? } ; xor-decrypt loop, regs/disp wildcarded
```
### Step 3: Assemble the rule
Combine 2–3 independent anchors with a `condition` requiring enough of them, plus a cheap
prefilter (file size, PE magic) to keep scanning fast:
```bash
python scripts/analyst.py scaffold --name family_xyz --hash 0xABCDEF12
```
### Step 4: Validate against the corpus
Run the rule across true positives and the clean control set; require all TPs match and zero
FPs on the control.
```bash
yara -r rules/family_xyz.yar ./corpus
```
### Step 5: Tune and document
Adjust thresholds, add `meta` (author, date, reference, hash), and record which construct each
string anchors so future analysts can maintain it.
## Validation
- Rule matches all intended samples and produces zero hits on the clean control set.
- Anchors map to intrinsic code/constants, not build-specific noise.
- `meta` documents source samples and the reasoning for each pattern.
## Pitfalls
- Wildcarding too little (brittle) or too much (false positives); wildcard only volatile bytes.
- Anchoring on shared library/packer code present in unrelated binaries.
- Skipping the clean-corpus test, shipping a noisy rule.
## References
- See [`references/api-reference.md`](references/api-reference.md) for the rule scaffolder.
- YARA documentation and style guide (linked in frontmatter).

View File

@@ -0,0 +1,40 @@
# API Reference: Writing YARA Rules from Reversed Code
## Overview
`scripts/analyst.py` scaffolds a structured YARA rule with `meta`, placeholder byte-pattern
strings, an optional API-hash constant (emitted little-endian), and a multi-anchor condition
with a PE prefilter. It emits text only and scans nothing.
## Dependencies
| Package | Version | Purpose |
|---------|---------|---------|
| (stdlib) | — | text generation |
## External tools
| Tool | Purpose |
|------|---------|
| yara | Compile and test rules against the corpus |
| yara-python | Programmatic testing/automation |
## Core functions
### `scaffold(name, api_hash, author)`
Returns a YARA rule skeleton; if `api_hash` is given, adds a little-endian byte-pattern string
and includes it in the condition.
## Usage
```bash
python scripts/analyst.py scaffold --name family_xyz --hash 0xABCDEF12
yara -r rules/family_xyz.yar ./corpus
```
## Sources
- YARA documentation — https://yara.readthedocs.io/
- YARA style guide (writing maintainable, low-FP rules) —
https://github.com/Neo23x0/YARA-Style-Guide
- Preference for code/constant anchors over volatile strings, established RE detection practice

View File

@@ -0,0 +1,60 @@
#!/usr/bin/env python3
"""Scaffold a YARA rule from reverse-engineering findings.
Generates a well-structured rule skeleton with ``meta``, placeholder byte-pattern strings, an
optional API-hash constant, and a sensible multi-anchor condition with a PE prefilter. The
analyst fills in the real opcode bytes. This only emits text; it does not scan anything.
"""
from __future__ import annotations
import argparse
import datetime as _dt
import sys
def scaffold(name: str, api_hash: str | None, author: str) -> str:
today = _dt.date.today().isoformat()
hash_line = ""
hash_cond = ""
if api_hash:
val = int(api_hash, 0)
hash_line = f" $h_api = {{ {val & 0xFF:02X} {(val >> 8) & 0xFF:02X} " \
f"{(val >> 16) & 0xFF:02X} {(val >> 24) & 0xFF:02X} }} // API hash LE\n"
hash_cond = " and $h_api"
return f"""rule {name}
{{
meta:
author = "{author}"
date = "{today}"
description = "Detects {name} based on reversed code constructs"
reference = "<analysis report / sample hash>"
sample_sha256 = "<fill in>"
strings:
// Replace with the real decryptor/algorithm opcodes; wildcard volatile operands.
$code1 = {{ 8A 04 ?? 34 ?? 88 04 ?? 41 3B ?? }}
$code2 = {{ 0F B6 ?? 33 ?? C1 ?? ?? }}
{hash_line}
condition:
// Cheap prefilter then require multiple independent anchors.
uint16(0) == 0x5A4D and filesize < 5MB and
(2 of ($code*)){hash_cond}
}}
"""
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(description="Scaffold a YARA rule")
sub = parser.add_subparsers(dest="cmd", required=True)
p = sub.add_parser("scaffold")
p.add_argument("--name", required=True)
p.add_argument("--hash", dest="api_hash", default=None,
help="optional API-hash constant, e.g. 0xABCDEF12")
p.add_argument("--author", default="analyst-ai-pack")
args = parser.parse_args(argv)
print(scaffold(args.name, args.api_hash, args.author))
return 0
if __name__ == "__main__":
sys.exit(main())