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-mach-o-binaries-on-macos
description: 'Statically analyzes macOS Mach-O malware: parsing the header and load commands,
handling fat/universal binaries, reading linked dylibs and entitlements, and checking code
signatures to infer capability and trust. Activates for requests to analyze a Mach-O binary,
inspect macOS malware, or parse load commands and entitlements.'
domain: cybersecurity
subdomain: malware-analysis
tags:
- malware-analysis
- mach-o
- macos
- static-analysis
- code-signing
version: 1.0.0
author: analyst-ai-pack
license: Apache-2.0
mitre_attack:
- T1027
- T1059.002
d3fend:
- D3-FCR
- D3-DA
references:
- 'Apple Mach-O file format reference — https://github.com/apple-oss-distributions/xnu/blob/main/EXTERNAL_HEADERS/mach-o/loader.h'
- 'macOS code signing overview — https://developer.apple.com/documentation/security/code_signing_services'
---
# Analyzing Mach-O Binaries on macOS
## When to Use
- You have a macOS sample (Mach-O) and need a static capability and trust read.
- You must handle a fat/universal binary containing multiple architecture slices.
- You need to inspect linked dylibs, entitlements, and code-signing status.
**Do not use** Windows PE tooling on Mach-O — the formats differ entirely; use Mach-O-aware
parsers.
## Prerequisites
- A Mach-O parser (Python stdlib `struct`, or `macholib`/LIEF); the sample handled inertly.
- For signing/entitlements on macOS, `codesign`/`otool` are authoritative.
## Safety & Handling
- Parse statically; never execute the sample, especially on a real macOS host.
- Keep the sample password-protected at rest and reference it by hash.
## Workflow
### Step 1: Detect fat vs. thin and architecture
Check the magic: `0xCAFEBABE` (fat/universal) vs. `0xFEEDFACE`/`0xFEEDFACF` (Mach-O 32/64). For
fat binaries, enumerate and analyze each slice.
```bash
python scripts/analyst.py header sample.macho
```
### Step 2: Parse load commands
Read load commands for linked dylibs (`LC_LOAD_DYLIB`), entry point (`LC_MAIN`), and signing
(`LC_CODE_SIGNATURE`). The dylib list hints at capability (networking, crypto).
### Step 3: Inspect entitlements and signing
On macOS, use `codesign`/`otool` to read entitlements and verify the signature. Ad-hoc or absent
signatures and suspicious entitlements are risk indicators.
### Step 4: Infer capability and route
Map linked frameworks/symbols to behaviors and route to disassembly/RE for deeper analysis.
## Validation
- Fat binaries are decomposed and each slice is analyzed, not just the first.
- Load commands, dylibs, and signing status are enumerated correctly.
- Capability inferences are corroborated by linked frameworks/symbols.
## Pitfalls
- Analyzing only one slice of a universal binary.
- Trusting a present signature without verifying it (ad-hoc signatures verify but aren't trusted).
- Applying PE assumptions (sections/imports) to Mach-O structures.
## References
- See [`references/api-reference.md`](references/api-reference.md) for the Mach-O header parser.
- Apple Mach-O loader.h and code signing docs (linked in frontmatter).

View File

@@ -0,0 +1,42 @@
# API Reference: Analyzing Mach-O Binaries on macOS
## Overview
`scripts/analyst.py` parses Mach-O headers with stdlib `struct`: it detects fat/universal vs. thin
binaries, enumerates slices, and reads load commands for linked dylibs, the entry point, and the
presence of a code signature. It parses statically and never executes the sample.
## Dependencies
| Package | Version | Purpose |
|---------|---------|---------|
| (stdlib) | — | struct parsing, file IO |
## External tools
| Tool | Purpose |
|------|---------|
| codesign | Verify signature and read entitlements on macOS |
| otool | Inspect load commands and linked libraries |
## Core functions
### `parse(path)`
Dispatches on magic to handle fat vs. thin binaries; returns format, slices, and per-slice data.
### `parse_thin(data, base)`
Parses one Mach-O image's load commands (dylibs, LC_MAIN, LC_CODE_SIGNATURE).
## Usage
```bash
python scripts/analyst.py header sample.macho
```
## Sources
- Apple Mach-O `loader.h` (header and load-command structures) —
https://github.com/apple-oss-distributions/xnu/blob/main/EXTERNAL_HEADERS/mach-o/loader.h
- macOS code signing overview —
https://developer.apple.com/documentation/security/code_signing_services
- Fat/universal binary layout (FAT_MAGIC + slice table), Mach-O format documentation

View File

@@ -0,0 +1,85 @@
#!/usr/bin/env python3
"""Parse a Mach-O (or fat/universal) binary header and key load commands.
Detects fat vs. thin Mach-O, enumerates architecture slices, and parses load commands for linked
dylibs, the main entry point, and the presence of a code signature. Uses stdlib ``struct`` only.
It parses bytes statically and never executes the sample.
"""
from __future__ import annotations
import argparse
import json
import struct
import sys
from pathlib import Path
MH_MAGIC = 0xFEEDFACE
MH_MAGIC_64 = 0xFEEDFACF
MH_CIGAM = 0xCEFAEDFE
MH_CIGAM_64 = 0xCFFAEDFE
FAT_MAGIC = 0xCAFEBABE
FAT_CIGAM = 0xBEBAFECF
LC_LOAD_DYLIB = 0x0C
LC_MAIN = 0x80000028
LC_CODE_SIGNATURE = 0x1D
def _u32(data: bytes, off: int, be: bool) -> int:
return struct.unpack_from(">I" if be else "<I", data, off)[0]
def parse_thin(data: bytes, base: int) -> dict:
magic = struct.unpack_from(">I", data, base)[0]
be = magic in (MH_MAGIC, MH_MAGIC_64)
is64 = magic in (MH_MAGIC_64, MH_CIGAM_64)
hdr = base
ncmds = _u32(data, hdr + 16, be)
off = hdr + (32 if is64 else 28)
dylibs, signed, entry = [], False, None
for _ in range(ncmds):
cmd = _u32(data, off, be)
cmdsize = _u32(data, off + 4, be)
if cmdsize == 0:
break
if cmd == LC_LOAD_DYLIB:
name_off = _u32(data, off + 8, be)
raw = data[off + name_off:off + cmdsize].split(b"\x00", 1)[0]
dylibs.append(raw.decode("latin-1"))
elif cmd == (LC_MAIN & 0xFFFFFFFF) or cmd == LC_MAIN:
entry = "LC_MAIN"
elif cmd == LC_CODE_SIGNATURE:
signed = True
off += cmdsize
return {"arch": "64-bit" if is64 else "32-bit", "dylibs": dylibs,
"has_code_signature": signed, "entry": entry}
def parse(path: str) -> dict:
data = Path(path).read_bytes()
magic = struct.unpack_from(">I", data, 0)[0]
if magic in (FAT_MAGIC, FAT_CIGAM):
nfat = struct.unpack_from(">I", data, 4)[0]
slices = []
for i in range(nfat):
entry_off = 8 + i * 20
offset = struct.unpack_from(">I", data, entry_off + 8)[0]
slices.append(parse_thin(data, offset))
return {"format": "fat/universal", "slice_count": nfat, "slices": slices}
if magic in (MH_MAGIC, MH_MAGIC_64, MH_CIGAM, MH_CIGAM_64):
return {"format": "thin Mach-O", **parse_thin(data, 0)}
return {"error": "not a Mach-O binary"}
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(description="Parse Mach-O header/load commands")
sub = parser.add_subparsers(dest="cmd", required=True)
p = sub.add_parser("header")
p.add_argument("file")
args = parser.parse_args(argv)
print(json.dumps(parse(args.file), indent=2))
return 0
if __name__ == "__main__":
sys.exit(main())