| name | ida-hub |
| description | IDA Pro reverse engineering assistant that interacts with a remote IDA Hub Server over HTTP API. Used for binary analysis, function analysis, string search, cross-references, decompilation, and related reverse engineering tasks. |
IDA Hub Skill
Interact with a remote IDA Hub Server over HTTP API to perform reverse engineering tasks.
When to Use
This skill is suitable for:
- Querying remote IDA instances and selecting a target database
- Performing read-only reverse engineering tasks: functions, strings, xrefs, pseudocode, and current cursor context
- Collecting, filtering, and aggregating results on the IDA side first, then returning only summaries and key evidence
The default goal is not to retrieve the full raw dataset, but to organize data inside IDA first and return structured results.
Execution Context
- When the user says "this project", "current binary", "this file", or "IDA database", they refer to the database currently opened in the remote IDA instance.
- Code runs inside the IDA process and accesses the database through the
db object (ida-domain API).
- Use
print() to emit results. Output is returned in the output field of /api/execute.
/api/* endpoints require Authorization: Bearer <token>.
Available runtime objects:
db — ida-domain database object (primary interface)
idaapi — Native IDA API module
idautils — IDA utility helpers module
idc — IDA core functions module
ida_kernwin — IDA UI interaction helpers (cursor, navigation, etc.)
Environment Requirements
The default path does not require curl or jq.
Recommended environment:
Use curl / jq only as a fallback or for quick diagnostics.
Quick Reference — Common Tasks
These are the most frequently used operations. Use these snippets directly — do NOT guess or experiment with API names.
CRITICAL: The db object does NOT have a decompile method. Decompilation uses ida_hexrays.decompile(ea). The func_t object has no .name or .address attribute — use db.functions.get_name(func) and func.start_ea instead. See snippets below for correct usage.
Decompile a function
import ida_hexrays, ida_lines
func = db.functions.get_at(0x704c)
if func:
cfunc = ida_hexrays.decompile(func.start_ea)
for sline in cfunc.get_pseudocode():
print(ida_lines.tag_remove(sline.line))
Key point: Decompilation uses ida_hexrays.decompile(ea), NOT db.functions.decompile(). The db object has no decompile method.
Search functions by name
import json
results = []
for func in db.functions:
name = db.functions.get_name(func)
if "fid" in name.lower():
results.append({"name": name, "start": f"0x{func.start_ea:08X}"})
print(json.dumps(results, indent=2))
Search strings by keyword
import json
results = []
for s in db.strings:
text = str(s)
if "fid" in text.lower():
results.append({"addr": f"0x{s.address:08X}", "text": text})
print(json.dumps(results[:20], indent=2))
Get cross-references (callers / callees)
import json
callers = []
for ea in db.xrefs.calls_to_ea(0x704c):
func = db.functions.get_at(ea)
name = db.functions.get_name(func) if func else "unknown"
callers.append({"from": f"0x{ea:08X}", "func": name})
print("Callers:", json.dumps(callers, indent=2))
callees = []
for ea in db.xrefs.calls_from_ea(0x704c):
func = db.functions.get_at(ea)
name = db.functions.get_name(func) if func else "unknown"
callees.append({"to": f"0x{ea:08X}", "func": name})
print("Callees:", json.dumps(callees, indent=2))
List all named locations
import json
for ea, name in db.names:
print(f"0x{ea:08X}: {name}")
Get function disassembly
func = db.functions.get_at(0x704c)
if func:
lines = db.functions.get_disassembly(func)
for line in lines:
print(line)
Read bytes at address
addr = 0x704c
data = db.bytes.get_bytes(addr, 64)
print(data.hex())
Rename a function
func = db.functions.get_at(0x6FB8)
if func:
ok = db.functions.set_name(func, "get_serial_number")
print(f"Rename: {'ok' if ok else 'failed'}")
Rename a local variable
import ida_hexrays
ok = ida_hexrays.rename_lvar(0x704c, "v2", "serial_number")
print(f"Rename lvar: {'ok' if ok else 'failed'}")
Set function signature / type
import idc
ok = idc.SetType(0x6FB8, "unsigned __int64 __fastcall get_serial_number(_QWORD *out_sn)")
print(f"SetType: {'ok' if ok else 'failed'}")
Add a comment
db.comments.set_at(0x704c, "Gets FID via SN + JTAG_ID KDF")
Combined analysis example (recommended pattern)
One script for a complete function analysis — search, decompile, callers, callees, related strings:
import json, ida_hexrays, ida_lines
TARGET = "get_fid"
target_ea = None
for func in db.functions:
name = db.functions.get_name(func)
if TARGET in name.lower():
target_ea = func.start_ea
print(f"Found: {name} @ 0x{target_ea:X}")
break
if not target_ea:
print(f"Function '{TARGET}' not found")
else:
try:
cfunc = ida_hexrays.decompile(target_ea)
print("\n=== Pseudocode ===")
for sline in cfunc.get_pseudocode():
print(ida_lines.tag_remove(sline.line))
except Exception as e:
print(f"Decompile failed: {e}")
print(f"\n=== Callers ===")
for caller in db.xrefs.get_callers(target_ea):
print(f" 0x{caller.ea:08X} in {caller.name} ({caller.xref_type.name})")
print(f"\n=== Callees ===")
for ea in db.xrefs.calls_from_ea(target_ea):
func = db.functions.get_at(ea)
name = db.functions.get_name(func) if func else "?"
print(f" 0x{ea:08X} {name}")
print(f"\n=== Related Strings ===")
for s in db.strings:
if TARGET.lower() in str(s).lower():
print(f" 0x{s.address:08X}: {s}")
print(f"\n=== Applying Renames ===")
renames = {
0x6FB8: "get_serial_number",
0xA01C: "snprintf_wrapper",
0xA6F0: "strlen_wrapper",
}
for ea, new_name in renames.items():
func = db.functions.get_at(ea)
if func:
old = db.functions.get_name(func)
if db.functions.set_name(func, new_name):
print(f" 0x{ea:X}: {old} -> {new_name}")
db.comments.set_at(target_ea, "FID = KDF(SN + JTAG_ID, label='*#*#cardapp#*#*')")
print(" Comment added")
Shortest Path to Success — run_script.py CLI
This plugin includes a CLI tool run_script.py (located at ../../run_script.py). It has zero external dependencies and uses only Python standard library.
Important: Copy run_script.py to your working directory (e.g., .ida_tmp/) before using it. Do not reference the original file directly from the skill directory.
Setup
mkdir -p .ida_tmp
cp <path_to_skill>/../../run_script.py .ida_tmp/
Usage
python .ida_tmp/run_script.py -u <hub_url> -k <token> <instance_id> <script_file>
| Parameter | Description |
|---|
-u / --url | Hub URL (e.g., http://127.0.0.1:10086) |
-k / --token | Bearer token |
instance_id | Target IDA instance ID |
script_file | Python script file to execute |
Output Behavior
- Execution error → stderr, exit 1
- Output ≤ 4000 chars → printed to stdout
- Output > 4000 chars → written to temp file, file path printed to stdout (Agent can read via Read tool)
Recommended Workflow
- Get
BASE_URL, TOKEN, INSTANCE_ID from Hub Web UI or /api/agent_config.
- Copy
run_script.py to .ida_tmp/.
- Write analysis script to
.ida_tmp/<task>.py — use db, idaapi, etc. directly, output via print().
- Execute:
python .ida_tmp/run_script.py -u <BASE_URL> -k <TOKEN> <INSTANCE_ID> .ida_tmp/<task>.py
- Iterate based on output.
Difference from old helper approach: run_script.py is a standalone CLI. No need to write a .ida_tmp/ida_hub.py helper file first. Recommended as the primary execution method.
Fallback — Helper Module
If run_script.py is not available, fall back to the helper module approach:
- Get agent config from Hub Web UI or
/api/agent_config.
- Extract:
BASE_URL, TOKEN, an example INSTANCE_ID.
- Write helper to
.ida_tmp/ida_hub.py in current working directory.
- Run a smoke test first (e.g.,
print(42) or print(db.module)).
- Create a dedicated task script and iterate.
If the user only has the Hub address but not the agent config, they must also provide a token and target instance information.
Scripting Best Practices
Think like a reverse engineer, not a script writer:
- Combine related queries into one script — If you need to decompile a function AND get its callers AND search for related strings, do it all in ONE script. Do not write a separate script file for each query.
- Write reusable utility scripts — Instead of hardcoding addresses and names, write small CLI tools that accept arguments. For example:
- A
rename.py that reads address:new_name pairs from args or stdin
- A
set_type.py that takes an address and type string
- A
decompile.py that takes an address and prints pseudocode
- Keep these in
.ida_tmp/ and reuse them across the session.
- Write once, iterate minimally — A typical analysis task should be 1-2 scripts total. If you find yourself writing 4+ scripts for a single question, you are doing it wrong.
- Avoid API guesswork — Use the Quick Reference snippets above. If you need an API not listed there, read the relevant
shared/API_REFERENCE_*.md file BEFORE writing the script, not after it fails.
- Handle errors in-script — Use
try/except for decompilation and other fallible operations rather than relying on retry with a new script.
Example: Reusable Rename Tool
Create .ida_tmp/rename.py once, then use the Edit tool to update the rename map and re-run:
RENAMES = {
0x6FB8: "get_serial_number",
0xA01C: "snprintf_wrapper",
0xA6F0: "strlen_wrapper",
}
for ea, new_name in RENAMES.items():
func = db.functions.get_at(ea)
if func:
old = db.functions.get_name(func)
if db.functions.set_name(func, new_name):
print(f" 0x{ea:X}: {old} -> {new_name}")
else:
print(f" 0x{ea:X}: rename failed")
else:
print(f" 0x{ea:X}: no function")
Similarly, build .ida_tmp/set_types.py for idc.SetType(), .ida_tmp/rename_lvars.py for ida_hexrays.rename_lvar(), etc. Edit the data dict and re-run as analysis progresses.
Remote scripts should follow these defaults:
- Do not print the full dataset.
- Only output summaries, Top N, counts, key addresses, and necessary evidence by default.
- Sort, deduplicate, and trim bulk results before printing.
- If the result is still too large, return statistics and next-step suggestions instead of printing everything with
for ...: print(...).
Recommended patterns:
count
top_matches[:10]
sorted(...)[0:20]
json.dumps(summary, indent=2)
Operation Levels
Proactive Analysis (Recommended)
A skilled reverse engineer does not just observe — they improve the database as they analyze. While reading and decompiling code, you should proactively:
- Rename functions — When you understand what
sub_6FB8 does (e.g., it gets the serial number), rename it to get_serial_number.
- Rename local variables — When decompilation shows
v2, v5, v19 and you can infer their purpose, rename them (e.g., serial_number, jtag_id, kdf_seed).
- Set function signatures — When you deduce parameter types and return values, apply them with
idc.SetType().
- Add comments — Annotate key logic, algorithm steps, or non-obvious behavior directly in the disassembly/pseudocode.
- Recover structures — When you identify a data layout accessed via offsets, create or apply a struct type.
Apply these changes as part of the analysis script itself — do not wait for a separate step. For example, after decompiling get_fid and understanding its logic, the same script should rename sub_6FB8 to get_serial_number, rename local variables, and add comments.
After applying changes, briefly mention what you renamed/typed/commented so the user knows what was improved.
Must Explicitly Confirm: High-risk or Bulk Modifications
- patch bytes / revert bytes
- Delete or recreate functions
- Navigation or batch operations that significantly alter the user's current UI state
Must Explicitly Confirm: High-risk or Bulk Modifications
- patch bytes / revert bytes
- Delete or recreate functions
- Bulk renaming / bulk comments
- Navigation or batch operations that significantly alter the user's current UI state
Cross-Instance Analysis
When analyzing external symbols (imported functions, externs, PLT stubs), first evaluate whether cross-instance analysis is necessary.
When NOT Needed
Skip cross-instance analysis if the external symbol falls into these categories:
- Well-known libc / system calls — e.g.,
mmap, malloc, free, open, read, write, pthread_create, dlopen. These are standard APIs with known semantics.
- Self-explanatory function names — The name clearly conveys purpose and no deeper analysis is needed (e.g.,
log_error, get_timestamp, calculate_checksum).
- Common third-party libraries with stable APIs — e.g., OpenSSL
SSL_read, zlib deflate, SQLite sqlite3_open. Unless investigating a bug or vulnerability in the library itself.
In these cases, continue analysis without interrupting the workflow.
When It IS Needed
Proceed with cross-instance analysis when:
- Custom / proprietary library — The external symbol belongs to a non-standard library specific to this project (e.g.,
lib_custom_protocol.dll!parse_packet).
- Unclear behavior — The function name is generic or obfuscated, and understanding its internals is critical to the analysis goal.
- Suspected vulnerability or anti-analysis trick — Need to verify implementation details in the external module.
Workflow
- Query Hub instance list — Call
GET /api/instances to check if the target binary is already loaded on another instance.
- Cross-instance execution — If found, use that
instance_id to run analysis (decompile, get xrefs, etc.) and bring results back.
- Ask the user — Only if the analysis genuinely requires it AND the instance is not available on the Hub, prompt the user to load the corresponding binary.
Example:
- Analyzing
main.exe, found call to crypto_utils.dll!obfuscate_data (custom DLL) → query Hub → if found, cross-instance decompile → if not found, ask user to load crypto_utils.dll
- Analyzing
app.bin, found call to libc.so!mmap → skip, standard API, continue with current context
User Intent to Recommended Entry Point
- "Analyze the current function / current cursor / what I am looking at" → read
../../shared/IDA.md first
- "Find strings, xrefs, call relationships, suspicious functions" → read
../../shared/ANALYSIS_PATTERNS.md first
- "How should I organize scripts / control output / troubleshoot" → read
../../shared/USAGE.md first
- "How do I call a specific ida-domain API" → go directly to the relevant
../../shared/API_REFERENCE_*.md
- "Pseudocode, ctree, microcode, Hex-Rays variable renaming" → read
../../shared/HEXRAYS.md first
Fallback / Diagnostic Path
Only use curl when doing a quick connectivity check, when the user explicitly asks for it, or when the local helper is unavailable.
List Instances
curl -s "${IDA_HUB_URL}/api/instances" \
-H 'Authorization: Bearer ${IDA_HUB_TOKEN}'
Execute Code
curl -s -X POST "${IDA_HUB_URL}/api/execute" \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer ${IDA_HUB_TOKEN}' \
-d '{"instance_id": "<INSTANCE_ID>", "code": "print(42)"}'
Response Format
Successful /api/execute response:
{
"success": true,
"output": "summary...",
"error": null,
"request_id": "abc123"
}
Error Handling
| HTTP Status | Meaning | Suggested Handling |
|---|
| 400 | Invalid parameters | Check request parameters |
| 401 | Missing auth or invalid token | Get a new token from /api/agent_config |
| 404 | Instance not found | List instances and confirm instance_id |
| 422 | Validation failed | Check instance_id, code, and length limits |
| 503 | Connection error | IDA instance may have disconnected |
| 504 | Execution timeout | Narrow scope or split the task |
| 500 | Server error | Check Hub Server logs |
Code execution failures return stack traces in the error field.
Security Notes
- The Bearer token carries permissions scoped to the current user. Do not leak it into untrusted environments.
- Even with authentication, the Hub Server should only be used in a trusted local network.
- Do not expose the Hub to the public internet unless additional reverse proxying, TLS, and stronger access controls are in place.
- Code runs inside the IDA process and has full IDA API privileges.
- Only connect to trusted Hub Servers.
Reference Documents
Start with the main index: ../../shared/README.md
Read on demand:
- ../../shared/USAGE.md: script organization, output budgeting, troubleshooting
- ../../shared/ANALYSIS_PATTERNS.md: common RE playbooks and templates
- ../../shared/API_REFERENCE_CORE.md:
Database, Functions, Instructions, Operands, FlowChart
- ../../shared/API_REFERENCE_MEMORY.md:
Segments, Heads, Bytes
- ../../shared/API_REFERENCE_SYMBOLS.md:
Strings, Names, Comments, Entries, Xrefs
- ../../shared/API_REFERENCE_TYPES.md:
Types, Signature Files
- ../../shared/API_REFERENCE_ENUMS.md: common enum definitions
- ../../shared/IDA.md: current location, selected ranges, navigation, UI interactions
- ../../shared/HEXRAYS.md: pseudocode, ctree, microcode, Hex-Rays hooks