debugger
Manage breakpoints and patch bytes through ghidrasql — the breakpoints table and bytes single-byte UPDATE.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Manage breakpoints and patch bytes through ghidrasql — the breakpoints table and bytes single-byte UPDATE.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
Analyze binaries with ghidrasql using safe, high-signal query patterns.
Apply persistent ghidrasql annotations such as names, comments, signatures, and local-variable edits.
Connect to ghidrasql sources, verify live access, and route to the right analysis skill.
Query strings, bytes, data items, memory blocks, and relocations through ghidrasql.
Decompile functions with ghidrasql and work with pseudocode, locals, parameters, and ctree pattern views safely.
Inspect code structure through ghidrasql tables for functions, instructions, blocks, CFG, loops, switches, dominators, and tail calls.
| name | debugger |
| description | Manage breakpoints and patch bytes through ghidrasql — the breakpoints table and bytes single-byte UPDATE. |
| allowed-tools | ["Bash","Read","Glob","Grep"] |
ghidrasql exposes Ghidra's breakpoint metadata table and a single-byte patch path through bytes.value. This is not an active debugger control plane — Ghidra itself is not a runtime debugger in the JTAG sense — but it covers static breakpoint definition for tooling that consumes the project (e.g. running it under a real debugger later) and direct byte patching.
Use this skill when the user asks to:
bookmarks (lightweight notes that often double as patch markers)Route to:
disassembly for context around a breakpoint or patch siteannotations to document a patch via a comment or bookmarkanalysis for triage that uncovered the patchstep, no continue, no register read/write.breakpoints.type value reflecting the kind, but ghidrasql does not exercise it.bytes writes one byte at a time. For multi-byte patches, batch UPDATEs in a single transaction-like script.breakpoints is a writable virtual table. 11 columns:
| Column | Type | Writable? |
|---|---|---|
addr | int | – (key) |
enabled | int | UPDATE |
type | int | UPDATE |
type_name | text | – (computed from type) |
size | int | UPDATE |
flags | int | – |
pass_count | int | – |
condition | text | UPDATE |
group | text | UPDATE |
loc_type | int | – |
loc_type_name | text | – (computed from loc_type) |
INSERT signature (positional argv):
INSERT INTO breakpoints (addr, enabled, type, size, condition, "group")
VALUES (0x401234, 1, 0, 1, '', 'review');
Required: addr. Defaults: enabled = 1, type = 0, size = 1, condition = '', group = ''.
Common queries:
-- List every breakpoint with its decoded type and location names
SELECT printf('0x%X', addr) AS at, enabled, type_name, size, condition, "group", loc_type_name
FROM breakpoints
ORDER BY addr;
-- Disable a breakpoint without removing it
UPDATE breakpoints SET enabled = 0 WHERE addr = 0x401234;
-- Add a conditional breakpoint
UPDATE breakpoints
SET condition = 'EAX == 0',
"group" = 'crashes'
WHERE addr = 0x401234;
-- Delete
DELETE FROM breakpoints WHERE addr = 0x401234;
To discover the actual type and loc_type integer values used by Ghidra on this binary, consult type_name / loc_type_name:
SELECT DISTINCT type, type_name FROM breakpoints;
SELECT DISTINCT loc_type, loc_type_name FROM breakpoints;
Empty until at least one breakpoint exists — set one through the GUI or via INSERT first.
bytes.value is the single writable byte column. Each UPDATE patches one address:
-- Single-byte patch (NOP an instruction byte)
UPDATE bytes SET value = 0x90 WHERE addr = 0x401234;
-- Verify
SELECT printf('0x%X', addr) AS at, value, ascii, is_printable
FROM bytes
WHERE addr = 0x401234;
Multi-byte patch (NOP a 5-byte instruction):
UPDATE bytes SET value = 0x90 WHERE addr = 0x401234;
UPDATE bytes SET value = 0x90 WHERE addr = 0x401235;
UPDATE bytes SET value = 0x90 WHERE addr = 0x401236;
UPDATE bytes SET value = 0x90 WHERE addr = 0x401237;
UPDATE bytes SET value = 0x90 WHERE addr = 0x401238;
SELECT save_database();
There is no separate WriteBytes / PatchBytes SQL surface — bytes.value is the path.
Only initialized bytes are patchable. bytes now surfaces every mapped
byte, including uninitialized-block bytes where value is NULL and
is_initialized = 0; an UPDATE against such a byte is rejected (no backing
storage until the block is initialized). Patch targets should carry
is_initialized = 1.
To find bytes that have been patched (i.e. differ from the original image), join bytes against itself by source_kind:
-- Discover what source_kind values exist on this binary
SELECT DISTINCT source_kind FROM bytes WHERE source_kind IS NOT NULL LIMIT 10;
Document each patch with a bookmark so the patch survives rediscovery:
INSERT INTO bookmarks (addr, type, category, comment)
VALUES (0x401234, 'Note', 'patch', 'NOPed magic check at the entry to authValidate');
bytes is a streaming windowed generator. Keep the guard WHERE addr = X (or a tight range) on every UPDATE so only the requested window is streamed; an unconstrained scan still visits every mapped byte.SELECT save_database(); (or run with --shutdown save, the default in managed mode).--readonly --shutdown discard so accidental UPDATEs cannot persist.UPDATE bytes returned without error but the byte didn't change. Re-read the same address and check program_revision() / cache_stats(). Libghidra live sources refresh automatically when Ghidra's native modification number or program identity changes; inside a batched script, drop the cache first (SELECT cache_invalidate('bytes');) and then re-read. If the address is in a non-writable segment (e.g. .rdata mapped read-only), Ghidra accepts the write into its program model but a runtime debugger may refuse to apply it.SELECT * FROM funcs WHERE addr <= 0xN AND end_addr > 0xN;); breakpoints set on data are often dropped by Ghidra.