reverse-skills-max: initial public release (restored, redacted, hardened)
This commit is contained in:
@@ -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
|
||||
@@ -0,0 +1,92 @@
|
||||
---
|
||||
name: scripting-ida-with-idapython
|
||||
description: 'Automates IDA Pro analysis with IDAPython by generating scripts that enumerate
|
||||
functions, decode strings, rename by signature, and export analysis results, and by documenting
|
||||
the headless idat batch invocation. Activates for requests to script IDA Pro, write IDAPython
|
||||
automation, or run IDA in batch/headless mode.'
|
||||
domain: cybersecurity
|
||||
subdomain: reverse-engineering
|
||||
tags:
|
||||
- reverse-engineering
|
||||
- ida-pro
|
||||
- idapython
|
||||
- automation
|
||||
- batch-analysis
|
||||
version: 1.0.0
|
||||
author: analyst-ai-pack
|
||||
license: Apache-2.0
|
||||
mitre_attack:
|
||||
- T1027
|
||||
- T1059
|
||||
- T1620
|
||||
d3fend:
|
||||
- D3-DA
|
||||
- D3-SDA
|
||||
references:
|
||||
- 'Hex-Rays IDAPython API documentation — https://hex-rays.com/products/ida/support/idapython_docs/'
|
||||
- 'IDA batch/headless (idat -A -S) usage — https://hex-rays.com/products/ida/'
|
||||
---
|
||||
|
||||
# Scripting IDA Pro With IDAPython
|
||||
|
||||
## When to Use
|
||||
|
||||
- You use IDA Pro and want to automate repetitive analysis — enumerate functions, decode strings,
|
||||
apply signature-based renames, and export results — via IDAPython.
|
||||
- You need a headless `idat` batch invocation to process many samples.
|
||||
|
||||
**Do not use** IDA's debugger (`-r`) on untrusted samples on your host — these scripts drive
|
||||
*static* analysis. Work in an isolated environment.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- IDA Pro with IDAPython, and the samples to analyze.
|
||||
|
||||
## Safety & Handling
|
||||
|
||||
- IDA static analysis does not execute the sample; keep the input directory isolated.
|
||||
|
||||
## Workflow
|
||||
|
||||
### Step 1: Generate an analysis script
|
||||
|
||||
```bash
|
||||
python scripts/analyst.py script --emit functions,strings --out ida_export.py
|
||||
```
|
||||
|
||||
Emits an IDAPython script using the real API (`idautils.Functions`, `idc.get_func_name`,
|
||||
`idautils.Strings`) that writes results to JSON next to the IDB.
|
||||
|
||||
### Step 2: Generate the headless batch command
|
||||
|
||||
```bash
|
||||
python scripts/analyst.py batch --script ida_export.py --input sample.exe
|
||||
```
|
||||
|
||||
Builds the `idat -A -S"script" input` invocation (auto-mode, run script, no UI) for batch runs.
|
||||
|
||||
### Step 3: Run and collect
|
||||
|
||||
Execute the batch command per sample and aggregate the JSON exports.
|
||||
|
||||
### Step 4: Iterate
|
||||
|
||||
Extend the generated script with signature renames (FLIRT) and decompiler (`ida_hexrays`) output
|
||||
as needed.
|
||||
|
||||
## Validation
|
||||
|
||||
- The generated script uses real IDAPython API calls.
|
||||
- The batch command uses `-A` (auto) and `-S` (script) correctly.
|
||||
- JSON output is produced per processed IDB.
|
||||
|
||||
## Pitfalls
|
||||
|
||||
- IDAPython API drift between IDA 7.x and 9.x — target your version.
|
||||
- Forgetting `-A` leaves IDA waiting for interactive input in batch.
|
||||
- Decompiler calls require a licensed Hex-Rays decompiler.
|
||||
|
||||
## References
|
||||
|
||||
- See [`references/api-reference.md`](references/api-reference.md) for the generator.
|
||||
- IDAPython and idat batch references (linked in frontmatter).
|
||||
@@ -0,0 +1,42 @@
|
||||
# API Reference: Scripting IDA Pro With IDAPython
|
||||
|
||||
## Overview
|
||||
|
||||
`scripts/analyst.py` generates an IDAPython analysis script (enumerate functions/strings → JSON)
|
||||
and the headless `idat` batch command to run it. It only generates text — it does not run IDA or
|
||||
any sample.
|
||||
|
||||
## Dependencies
|
||||
|
||||
| Package | Version | Purpose |
|
||||
|---------|---------|---------|
|
||||
| (stdlib) | — | shlex, JSON, file IO |
|
||||
| IDA Pro + IDAPython | 7.x/9.x | runs the generated script (separately) |
|
||||
|
||||
## Core functions
|
||||
|
||||
### `script(out, emit)`
|
||||
Writes an IDAPython script using `idautils.Functions`, `idc.get_func_name`, `idautils.Strings`,
|
||||
and `ida_auto.auto_wait()`, exiting via `ida_pro.qexit`.
|
||||
|
||||
### `batch(script_path, input_path)`
|
||||
Builds `idat -A -S"<script>" <input>` (autonomous mode, run script).
|
||||
|
||||
## Key IDA batch flags
|
||||
|
||||
- `-A` — autonomous/auto mode (no dialogs).
|
||||
- `-S<script>` — run the script after load.
|
||||
- `-L<file>` — log output. Use `idat64` for 64-bit inputs.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
python scripts/analyst.py script --emit functions,strings --out ida_export.py
|
||||
python scripts/analyst.py batch --script ida_export.py --input sample.exe
|
||||
```
|
||||
|
||||
## Sources
|
||||
|
||||
- Hex-Rays IDAPython API docs — https://hex-rays.com/products/ida/support/idapython_docs/
|
||||
- IDA batch/headless `idat -A -S` usage from Hex-Rays documentation
|
||||
- `idautils.Functions`/`Strings` and `ida_auto.auto_wait` from the IDAPython API
|
||||
@@ -0,0 +1,82 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Generate IDAPython analysis scripts and the headless idat batch command.
|
||||
|
||||
`script` emits an IDAPython script that enumerates functions and/or strings and exports JSON.
|
||||
`batch` builds the `idat -A -S"<script>" <input>` invocation. This tool only generates text — it
|
||||
does not run IDA or any sample.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import shlex
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
FUNCTIONS_SNIPPET = '''
|
||||
import idautils, idc
|
||||
for ea in idautils.Functions():
|
||||
result["functions"].append({
|
||||
"name": idc.get_func_name(ea),
|
||||
"start": hex(ea),
|
||||
})
|
||||
'''
|
||||
|
||||
STRINGS_SNIPPET = '''
|
||||
import idautils
|
||||
for s in idautils.Strings():
|
||||
result["strings"].append({"ea": hex(s.ea), "value": str(s)})
|
||||
'''
|
||||
|
||||
|
||||
def script(out: str, emit: list[str]) -> dict:
|
||||
keys, body = [], []
|
||||
if "functions" in emit:
|
||||
keys.append('"functions": []')
|
||||
body.append(FUNCTIONS_SNIPPET)
|
||||
if "strings" in emit:
|
||||
keys.append('"strings": []')
|
||||
body.append(STRINGS_SNIPPET)
|
||||
text = (
|
||||
"# IDAPython analysis script (generated skeleton).\n"
|
||||
"import json\n"
|
||||
"import ida_pro\n"
|
||||
"import ida_auto\n\n"
|
||||
"def run():\n"
|
||||
" ida_auto.auto_wait() # ensure auto-analysis is complete\n"
|
||||
" result = {%s}\n%s"
|
||||
" with open(ida_pro.idainfo_get_path() + '.ida.json', 'w') as fh:\n"
|
||||
" fh.write(json.dumps(result, indent=2))\n\n"
|
||||
"run()\n"
|
||||
"ida_pro.qexit(0) # exit IDA after the script in batch mode\n"
|
||||
) % (", ".join(keys), "".join(body))
|
||||
Path(out).write_text(text, encoding="utf-8")
|
||||
return {"output": out, "emits": emit}
|
||||
|
||||
|
||||
def batch(script_path: str, input_path: str) -> dict:
|
||||
# -A: autonomous (no dialogs), -S: run script, then the input file.
|
||||
cmd = f'idat -A -S{shlex.quote(script_path)} {shlex.quote(input_path)}'
|
||||
return {"command": cmd,
|
||||
"note": "use idat64 for 64-bit inputs; add -L<logfile> to capture output"}
|
||||
|
||||
|
||||
def main(argv: list[str] | None = None) -> int:
|
||||
parser = argparse.ArgumentParser(description="Generate IDAPython automation")
|
||||
sub = parser.add_subparsers(dest="cmd", required=True)
|
||||
ps = sub.add_parser("script")
|
||||
ps.add_argument("--emit", default="functions,strings")
|
||||
ps.add_argument("--out", required=True)
|
||||
pb = sub.add_parser("batch")
|
||||
pb.add_argument("--script", required=True)
|
||||
pb.add_argument("--input", required=True)
|
||||
args = parser.parse_args(argv)
|
||||
if args.cmd == "script":
|
||||
print(json.dumps(script(args.out, [e.strip() for e in args.emit.split(",")]), indent=2))
|
||||
else:
|
||||
print(json.dumps(batch(args.script, args.input), indent=2))
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user