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,88 @@
---
name: identifying-cryptographic-routines-in-binaries
description: 'Identifies cryptographic algorithms embedded in a binary by scanning for well-known
constants and tables (AES S-box, SHA-256/MD5 init constants, ChaCha sigma, CRC32 table, base64
alphabet). Activates for requests to identify crypto in a binary, find AES/SHA constants, or
detect which encryption algorithm a sample uses.'
domain: cybersecurity
subdomain: reverse-engineering
tags:
- reverse-engineering
- cryptography
- constants
- aes
- detection
version: 1.0.0
author: analyst-ai-pack
license: Apache-2.0
mitre_attack:
- T1027
- T1486
- T1573
d3fend:
- D3-SDA
- D3-DA
references:
- 'FIPS 197 (AES) S-box — https://csrc.nist.gov/publications/detail/fips/197/final'
- 'FIPS 180-4 (SHA-2) constants — https://csrc.nist.gov/publications/detail/fips/180/4/final'
---
# Identifying Cryptographic Routines in Binaries
## When to Use
- You need to determine which cryptographic algorithms a sample implements (ransomware crypto, C2
encryption, config protection) by locating constant tables.
- You want fast triage before manually reversing the crypto routine.
**Do not use** constant detection as proof of a specific mode/usage — it identifies the primitive,
not how it is applied. This skill reads the binary statically and executes nothing.
## Prerequisites
- The binary (read inertly).
## Safety & Handling
- Read bytes statically; treat the sample as malicious data.
## Workflow
### Step 1: Scan for crypto constants
```bash
python scripts/analyst.py scan sample.bin
```
Searches for AES S-box/Te tables, SHA-256 H/K init constants, MD5 init, ChaCha/Salsa `expand
32-byte k` sigma, the CRC32 polynomial table, and the base64 alphabet, reporting offsets.
### Step 2: Corroborate with imports/strings
Pair constant hits with crypto API imports (`CryptDecrypt`, `BCryptEncrypt`, `EVP_*`) or library
strings to confirm.
### Step 3: Locate the routine
Use the constant offset to find the referencing function for deeper reversing/key extraction.
### Step 4: Document
Record which primitives are present and where, mapping to behavior (e.g., AES → file encryption).
## Validation
- Each hit references a real, named constant table (not a coincidental byte run).
- Detected primitives are corroborated by imports/strings where possible.
- Offsets point into the binary and can be navigated in a disassembler.
## Pitfalls
- Statically linked crypto libraries adding constants unused by the malware's logic.
- Custom/modified S-boxes evading exact-match detection.
- Assuming AES presence implies ransomware — corroborate with behavior.
## References
- See [`references/api-reference.md`](references/api-reference.md) for the scanner.
- FIPS 197 and FIPS 180-4 constant references (linked in frontmatter).

View File

@@ -0,0 +1,40 @@
# API Reference: Identifying Cryptographic Routines in Binaries
## Overview
`scripts/analyst.py` scans a binary for well-known cryptographic constants — the AES S-box, SHA-256
init values (LE/BE), MD5 init constants, ChaCha/Salsa sigma strings, a CRC32 table prefix, and the
base64 alphabet — and reports their offsets. It reads bytes statically and executes nothing.
## Dependencies
| Package | Version | Purpose |
|---------|---------|---------|
| (stdlib) | — | struct, JSON, file IO |
## Core functions
### `scan(path)`
Returns the set of detected algorithms and per-constant offset hits.
### `_crc32_table_prefix()`
Computes the first entries of the standard `0xEDB88320` CRC32 table to anchor detection.
## Constants anchored
- AES S-box first 16 bytes (`0x63 0x7c 0x77 0x7b ...`).
- SHA-256 H0..H7; MD5 A/B/C/D init words.
- `expand 32-byte k` (ChaCha) / `expand 16-byte k` (Salsa20).
- Base64 standard alphabet.
## Usage
```bash
python scripts/analyst.py scan sample.bin
```
## Sources
- FIPS 197 (AES, S-box) — https://csrc.nist.gov/publications/detail/fips/197/final
- FIPS 180-4 (SHA-2 init/round constants) — https://csrc.nist.gov/publications/detail/fips/180/4/final
- RFC 8439 (ChaCha20 `expand 32-byte k` constant); CRC-32 polynomial 0xEDB88320 (ITU-T V.42)

View File

@@ -0,0 +1,91 @@
#!/usr/bin/env python3
"""Scan a binary for well-known cryptographic constants and tables.
Detects the AES S-box, SHA-256 init/round constants, MD5 init constants, ChaCha/Salsa sigma,
the CRC32 (0xEDB88320) table, and the base64 alphabet by exact byte-pattern match, reporting
offsets. Reads bytes statically; executes nothing.
"""
from __future__ import annotations
import argparse
import json
import struct
import sys
from pathlib import Path
# AES S-box (FIPS 197) first 16 bytes are a stable, distinctive anchor.
AES_SBOX_PREFIX = bytes([
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
])
# SHA-256 initial hash values H0..H7 (FIPS 180-4), little- and big-endian.
SHA256_H = [0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19]
# MD5 init constants A,B,C,D.
MD5_INIT = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476]
CHACHA_SIGMA = b"expand 32-byte k"
SALSA_SIGMA16 = b"expand 16-byte k"
BASE64_ALPHABET = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
def _ints_le(values: list[int]) -> bytes:
return b"".join(struct.pack("<I", v) for v in values)
def _ints_be(values: list[int]) -> bytes:
return b"".join(struct.pack(">I", v) for v in values)
def _crc32_table_prefix() -> bytes:
poly = 0xEDB88320
table = []
for n in range(8): # first 8 entries are enough to anchor
c = n
for _ in range(8):
c = (poly ^ (c >> 1)) if (c & 1) else (c >> 1)
table.append(c)
return _ints_le(table)
def _find_all(data: bytes, needle: bytes, label: str, limit: int = 10) -> list[dict]:
hits = []
start = 0
while len(hits) < limit:
idx = data.find(needle, start)
if idx == -1:
break
hits.append({"algorithm": label, "offset": idx})
start = idx + 1
return hits
def scan(path: str) -> dict:
data = Path(path).read_bytes()
findings: list[dict] = []
findings += _find_all(data, AES_SBOX_PREFIX, "AES S-box")
findings += _find_all(data, _ints_le(SHA256_H), "SHA-256 init (LE)")
findings += _find_all(data, _ints_be(SHA256_H), "SHA-256 init (BE)")
findings += _find_all(data, _ints_le(MD5_INIT), "MD5 init (LE)")
findings += _find_all(data, _crc32_table_prefix(), "CRC32 table")
findings += _find_all(data, CHACHA_SIGMA, "ChaCha sigma")
findings += _find_all(data, SALSA_SIGMA16, "Salsa20 sigma (16)")
findings += _find_all(data, BASE64_ALPHABET, "Base64 alphabet")
algos = sorted({f["algorithm"].split(" (")[0] for f in findings})
return {"algorithms_detected": algos, "constant_hits": findings}
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(description="Identify crypto constants in a binary")
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())