reverse-skills-max: initial public release (restored, redacted, hardened)
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Automate radare2/rizin static analysis through r2pipe.
|
||||
|
||||
`check` reports tool availability. `summary` opens a binary, runs static analysis (aaa), and
|
||||
collects functions (aflj), imports (iij), and strings (izj) as JSON. r2pipe is optional; without
|
||||
it the script reports that automation is unavailable. Drives static analysis commands only and
|
||||
does not run the sample in a debugger.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import shutil
|
||||
import sys
|
||||
|
||||
try:
|
||||
import r2pipe # type: ignore
|
||||
HAVE_R2PIPE = True
|
||||
except ImportError:
|
||||
HAVE_R2PIPE = False
|
||||
|
||||
|
||||
def _r2_binary() -> str | None:
|
||||
for name in ("radare2", "r2", "rizin"):
|
||||
if shutil.which(name):
|
||||
return name
|
||||
return None
|
||||
|
||||
|
||||
def check() -> dict:
|
||||
return {
|
||||
"r2pipe_available": HAVE_R2PIPE,
|
||||
"r2_binary": _r2_binary(),
|
||||
"ready": HAVE_R2PIPE and _r2_binary() is not None,
|
||||
}
|
||||
|
||||
|
||||
def _cmdj(r2, command: str): # noqa: ANN001
|
||||
try:
|
||||
return r2.cmdj(command) or []
|
||||
except Exception:
|
||||
return []
|
||||
|
||||
|
||||
def summary(path: str) -> dict:
|
||||
if not HAVE_R2PIPE:
|
||||
return {"error": "r2pipe not installed", "r2pipe_available": False}
|
||||
r2 = r2pipe.open(path, flags=["-2"]) # -2 closes stderr noise
|
||||
try:
|
||||
r2.cmd("aaa")
|
||||
funcs = _cmdj(r2, "aflj")
|
||||
imports = _cmdj(r2, "iij")
|
||||
strings = _cmdj(r2, "izj")
|
||||
result = {
|
||||
"function_count": len(funcs),
|
||||
"functions": [{"name": f.get("name"), "offset": f.get("offset"),
|
||||
"size": f.get("size")} for f in funcs[:200]],
|
||||
"imports": [i.get("name") for i in imports if i.get("name")][:200],
|
||||
"strings": [s.get("string") for s in strings if s.get("string")][:200],
|
||||
}
|
||||
finally:
|
||||
r2.quit()
|
||||
return result
|
||||
|
||||
|
||||
def main(argv: list[str] | None = None) -> int:
|
||||
parser = argparse.ArgumentParser(description="Automate r2/rizin via r2pipe")
|
||||
sub = parser.add_subparsers(dest="cmd", required=True)
|
||||
sub.add_parser("check")
|
||||
ps = sub.add_parser("summary")
|
||||
ps.add_argument("file")
|
||||
args = parser.parse_args(argv)
|
||||
if args.cmd == "check":
|
||||
print(json.dumps(check(), indent=2))
|
||||
else:
|
||||
print(json.dumps(summary(args.file), indent=2))
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user