| name | data |
| description | Query strings, bytes, data items, memory blocks, and relocations through ghidrasql. |
| allowed-tools | ["Bash","Read","Glob","Grep"] |
Data
Trigger Intents
Use this skill when the user asks to:
- search strings
- inspect or pattern-search bytes and hexdumps
- explore data items and typed globals
- inspect memory blocks or relocations
- trace data-oriented evidence in a binary
Route to:
xrefs when string or data references matter (use string_refs view)
analysis for higher-level suspiciousness or summarization
annotations if the next step is naming or typing the data
debugger for byte patches via UPDATE bytes
Performance Contract
| Surface | Predicate | Pushdown? | Notes |
|---|
strings | any | Indexed | Cheap |
data_items | any | Indexed | Cheap (sub-second for tens of thousands of rows) |
bytes | addr = X or range | Yes (streamed window) | Point/range predicates stream only the window; an unconstrained scan visits every mapped byte |
byte_search | required pattern; optional bounds / result cap | Yes (lazy pages) | 32 Ki candidate pages with overlap; SQL LIMIT and max_results stop future reads |
memory_blocks, segments | any | Indexed | Cheap, small cardinality |
relocations | any | Indexed | Cheap |
Composition views: memory_layout, memory_hexdump, memory_byte_detail, memory_byte_items, typed_data_items, relocation_map, string_hotspots, string_refs.
Do This First
Lightest useful surface — strings:
SELECT printf('0x%X', addr) AS addr, length, type, encoding, content
FROM strings
WHERE content LIKE '%password%'
ORDER BY addr
LIMIT 50;
type and encoding come from Ghidra. Run SELECT DISTINCT type, encoding FROM strings; to enumerate what's present on this binary.
Bounded FlexHex byte-pattern search:
SELECT printf('0x%X', addr) AS addr, matched_hex
FROM byte_search
WHERE pattern = '48 8B ?? 4?'
AND start_addr = 0x401000
AND end_addr = 0x402000
ORDER BY addr
LIMIT 20;
end_addr is exclusive. Search runs in bounded pages, includes the overlap needed
for cross-page matches, and stops fetching pages once LIMIT or max_results is met.
Common Patterns
Typed globals (only data items that have a Ghidra-recognised type):
SELECT printf('0x%X', addr) AS addr, name, data_type, size
FROM data_items
WHERE data_type IS NOT NULL AND data_type != ''
ORDER BY addr
LIMIT 50;
Discover the actual data_type values on this binary (don't hard-code — the set varies by binary, processor, and Ghidra version):
SELECT DISTINCT data_type
FROM data_items
WHERE data_type IS NOT NULL AND data_type != ''
LIMIT 50;
Typical results include Ghidra primitives (byte, word, dword, undefined1/2/4/8, pointer, string, unicode, TerminatedCString, TerminatedUnicode). Format-specific structures (PE, ELF, Mach-O, etc.) appear when Ghidra recognises the container — names depend on the binary in front of you. Don't hard-code — enumerate live.
Hexdump for a specific address:
SELECT *
FROM memory_hexdump
WHERE addr = 0x403000;
Memory blocks (per-segment metadata; perm flags as is_read, is_write, is_exec):
SELECT printf('0x%X', start_addr) AS start,
printf('0x%X', end_addr) AS end,
name, class, size,
is_read, is_write, is_exec
FROM memory_blocks
ORDER BY start_addr;
Relocations (note: table is named relocations, not relocation_items):
SELECT printf('0x%X', addr) AS at,
printf('0x%X', target_addr) AS target,
reloc_type, width, symbol_name
FROM relocations
ORDER BY addr;
Create a typed data item only after verifying that the target is an unused,
writable data address (replace <unused_data_addr> with that address):
INSERT INTO data_items (addr, data_type)
VALUES (<unused_data_addr>, 'dword');
String References
Functions that reference a string — use the string_refs view, which pre-attributes the function context:
SELECT printf('0x%X', func_addr) AS func, func_name, string_value
FROM string_refs
WHERE string_value LIKE '%error%'
ORDER BY func_addr
LIMIT 50;
For "which strings are referenced most", use string_hotspots.
When imports is Empty
Some PE binaries (packed, stripped, or unusually crafted) parse with imports empty but their IAT entries surface as data_items named PTR_<API>_<address>.
SELECT printf('0x%X', addr) AS addr, name
FROM data_items
WHERE name LIKE 'PTR_%'
ORDER BY name
LIMIT 50;
If this fallback returns rows, route the agent to think of those as imports for fan-in / call-target analysis.
Critical Rules
- Keep
bytes queries bounded by addr — constrained queries stream only the requested window; an unconstrained scan streams every mapped byte.
- Prefer
strings, data_items, memory_hexdump, memory_blocks, relocations over raw byte scans.
- When a string matters semantically, hand off to
string_refs (read it as a data query, then route to xrefs if you need callers).
Additional Resources