From idasql
Provides persistent key-value storage in IDA databases via netnode_kv SQL interface. Use for metadata storage, analysis progress tracking, or session state persistence.
npx claudepluginhub allthingsida/idasql-skills --plugin idasqlThis skill is limited to using the following tools:
---
Connects to IDA databases (.idb/.i64) via idasql CLI/REPL/HTTP. Bootstraps analysis sessions with orientation queries, schema introspection, and skill routing.
Guides binary analysis with IDA Pro's Domain API for examining program structure, functions, disassembly, cross-references, and strings using Python.
Manages persistent local memory in .nemp/memories.json for Claude Code agents, storing project stack, architecture decisions, user preferences, and enabling cross-session context retention.
Share bugs, ideas, or general feedback.
Persistent key-value store backed by IDA netnodes. Data is saved inside the IDB automatically. Supports full CRUD and O(1) key lookup via WHERE key = '...'.
| Column | Type | Writable | Description |
|---|---|---|---|
key | TEXT | — | Unique key (identity, read-only) |
value | TEXT | Yes | Arbitrary-length value (blob storage) |
-- Store a value
INSERT OR REPLACE INTO netnode_kv(key, value) VALUES('author', 'alice');
-- Read by key (O(1) lookup)
SELECT value FROM netnode_kv WHERE key = 'author';
-- List all entries
SELECT * FROM netnode_kv;
-- Update a value
UPDATE netnode_kv SET value = '2.0' WHERE key = 'version';
-- Delete an entry
DELETE FROM netnode_kv WHERE key = 'author';
-- Track analysis progress
INSERT OR REPLACE INTO netnode_kv(key, value) VALUES('annotated_funcs', '["main","init_config"]');
-- Update progress
UPDATE netnode_kv SET value = '["main","init_config","process_input"]'
WHERE key = 'annotated_funcs';
-- Read progress in a new session
SELECT value FROM netnode_kv WHERE key = 'annotated_funcs';
| Operation | Complexity | Notes |
|---|---|---|
WHERE key = '...' | O(1) | IDA's netnode hashval_long() — always use exact key lookup |
WHERE key LIKE 'prefix%' | O(n) | Scans all entries; acceptable for small datasets |
SELECT * FROM netnode_kv | O(n) | Full netnode scan; fine for typical use (dozens to hundreds of entries) |
Key rules:
WHERE key = '...') is O(1) — this is the preferred access pattern.LIKE 'prefix%') iterate all entries but are fast for typical netnode sizes.save_database().Store structured analysis state as JSON for richer querying:
-- Store progress with structured metadata
INSERT OR REPLACE INTO netnode_kv(key, value)
VALUES('progress:overview', json_object(
'total_funcs', (SELECT COUNT(*) FROM funcs),
'named_funcs', (SELECT COUNT(*) FROM funcs WHERE name NOT LIKE 'sub_%'),
'timestamp', datetime('now')
));
-- Read and parse progress
SELECT json_extract(value, '$.total_funcs') AS total,
json_extract(value, '$.named_funcs') AS named,
json_extract(value, '$.timestamp') AS ts
FROM netnode_kv WHERE key = 'progress:overview';
Track which functions have been annotated and what was done:
-- Mark a function as annotated
INSERT OR REPLACE INTO netnode_kv(key, value)
VALUES('re_source:' || printf('0x%X', 0x401000),
json_object('status', 'done', 'summary', 'DriverEntry init',
'analyst', 'alice', 'date', date('now')));
-- Find unannotated functions by joining with funcs
SELECT f.name, printf('0x%X', f.address) AS addr
FROM funcs f
WHERE f.name NOT LIKE 'sub_%'
AND NOT EXISTS (
SELECT 1 FROM netnode_kv
WHERE key = 're_source:' || printf('0x%X', f.address)
)
ORDER BY f.size DESC
LIMIT 20;
Use a namespace:entity:id format for organized storage:
re_source:0x401000 → per-function annotation status
config:string_minlen → analysis configuration
snapshot:2024-01-15 → point-in-time analysis snapshot
tag:crypto:0x401000 → function tags/categories
-- List all keys in a namespace
SELECT key, value FROM netnode_kv WHERE key LIKE 'tag:crypto:%';
-- Count entries per namespace
SELECT SUBSTR(key, 1, INSTR(key, ':') - 1) AS namespace,
COUNT(*) AS entries
FROM netnode_kv
WHERE key LIKE '%:%'
GROUP BY namespace
ORDER BY entries DESC;