Hydra Engine

Recipes

Short, complete snippets for what agents and tools do all day.

Each recipe is a whole task in a few lines, with a link to the page that explains it.

Ask an analysed project a question

Open the project read-only (no lock, no copy), find the program by hash, and check you're answering about the right build.

python
1import hashlib, ghidra_session as gs2 3digest = hashlib.sha256(open("target.exe", "rb").read()).hexdigest()4with gs.connect(client="triage", harness="codex") as s:5    s.call("open_project", path="/re/Game")6    hit = s.call("list", sha256=digest, programsOnly=True)["entries"][0]7    s.call("open_program", path=hit["key"])8    assert s.call("info")["sha256"] == digest9    print(s.call("decompile", address="rva:0x5d53a0")["c"])

More in Projects.

Test a hypothesis without touching anyone's view

Rename and retype a function in a private overlay, decompile it to see if the result reads right, and promote it into a working copy only if it does.

python
1s.call("open_program", path="p1:/game.exe", overlay="tick")2s.call("apply_overlay", overlay="tick", ops=[3    {"op": "rename", "address": "rva:0x67bc40", "name": "PlayerTick"},4    {"op": "signature", "address": "rva:0x67bc40",5     "signature": "void PlayerTick(void *self, float dt)"},6])7print(s.call("decompile", overlay="tick", address="rva:0x67bc40")["c"])8 9s.call("promote_overlay", overlay="tick", fork={"path": "/work/tick"})  # or drop_overlay

More in Overlays.

Two agents annotating one program

Both open it in shared mode. expect turns a silent overwrite into a conflict that names who got there first.

python
1s.call("open_program", path="game.exe", writable=True, share=True)2try:3    s.call("rename", address="rva:0x1a2b30", name="g_playerList", expect="DAT_1401a2b30")4except gs.SessionError as e:5    if e.code == "conflict":6        print("changed by", e.details["lastEdit"])  # re-read, then decide7s.call("save")

More in Shared writing.

A long export that can be watched and cancelled

Scripts that write big files run on the long lane, report progress, and stop at the next monitor check when cancelled.

python
1rid = s.send("script", script="ExportJsonl.java", args=[out], artifact=out,2             parallel=True, maxChars=1000)3print(s.call("status")["clients"])        # progress of every unanswered request4s.call("cancel", target=rid, parallel=True)  # leaves out + ".part", valid up to its last line

More in Scheduling.

Handle a busy program like a colleague would

Errors say who holds what and suggest the next step. A ready request is often attached.

python
1try:2    s.call("rename", address="rva:0x1000", name="Init")3except gs.SessionError as e:4    d = e.details5    if e.code == "busy":6        print("held by", d["holder"], "- retry or raise wait")7    elif e.code == "not_owner":8        s.call(**d["overlaySuggestion"])   # annotate privately instead

More in Error codes.

From a shell script, without Python code

A private session over stdin: one process, one sequence of requests, no daemon.

bash
1python $GS stdio <<'EOF'2{"id": 1, "cmd": "open_project", "path": "/re/MyProject"}3{"id": 2, "cmd": "open_program", "path": "target.exe"}4{"id": 3, "cmd": "functions", "contains": "crypt", "limit": 20}5EOF

More in CLI.