Skip to content

P1: Byte patching for the decompiler CLI (patch set/get/list/delete)#210

Closed
mahaloz wants to merge 1 commit into
feat/cli-define-undefinefrom
feat/cli-patching
Closed

P1: Byte patching for the decompiler CLI (patch set/get/list/delete)#210
mahaloz wants to merge 1 commit into
feat/cli-define-undefinefrom
feat/cli-patching

Conversation

@mahaloz

@mahaloz mahaloz commented Jul 17, 2026

Copy link
Copy Markdown
Member

What & why

DecLib already models Patch and IDA/Binja had partial implementations, but there was no CLI command and backend parity was incomplete. This exposes patching and fills the gaps.

New capabilities

  • decompiler patch set|get|list|delete.
  • IDA: set via patch_bytes (existing), list via visit_patched_bytes (existing), and a new _del_patch that reverts to original bytes (get_original_byte). Full set/get/list/delete(revert).
  • Ghidra: implemented _set_patch via Memory.setBytes — flips the block writable and clears the conflicting code unit first (setBytes refuses to overwrite bytes under a defined instruction: "Memory change conflicts with instruction"), then re-disassembles.
  • Binary Ninja: implemented _set_patch via bv.write (was a warn-stub returning False).
  • angr: no user-patch store → set reports rejected.
  • Base public get_patch/delete_patch (direct reads) + client proxies.

Example

$ decompiler patch set 0x71d "9090"
addr: 1821
size: 2
bytes: 9090
success: True
$ decompiler read_memory 0x71d 2 --format hex
9090
$ decompiler patch list
0x71d   2   9090
$ decompiler patch delete 0x71d      # revert (IDA)
$ decompiler read_memory 0x71d 2 --format hex
5548                                 # original bytes back

Tests

test_patch_set_reflects_in_memory (set → read_memory shows patched bytes → revert restores originals on IDA) and test_patch_get_and_list (IDA).

  • IDA: full pass (set/get/list/revert). Ghidra: set verified in memory. angr: set correctly rejected.

Support matrix

IDA Ghidra Binary Ninja angr
patch set ✅ (new) ✅ (new)
patch get/list/delete

Seventh PR in the IDALib-parity series. Based on feat/cli-define-undefine (#209).

🤖 Generated with Claude Code

https://claude.ai/code/session_01HfZHdprXg38re1XyKxzGg5

DecLib already had a Patch artifact; this exposes it via the CLI and fills
backend gaps.

- New `decompiler patch set|get|list|delete`.
- IDA: set via patch_bytes (existing), enumerate via visit_patched_bytes
  (existing), plus new `_del_patch` that reverts to original bytes
  (get_original_byte). Full get/list/delete/revert support.
- Ghidra: implemented `_set_patch` via Memory.setBytes — flips the block
  writable and clears the conflicting code unit first (setBytes refuses to
  overwrite bytes under a defined instruction), then re-disassembles.
- Binary Ninja: implemented `_set_patch` via bv.write (was a warn-stub).
- angr: no user-patch store (patch set reports rejected).
- Base public get_patch/delete_patch (direct reads) + client proxies.
- Tests: patch set reflects in read_memory + revert restores original
  bytes (IDA); get/list enumeration (IDA); Ghidra set verified; angr set
  rejected. SKILL.md / docs updated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HfZHdprXg38re1XyKxzGg5
@mahaloz
mahaloz deleted the branch feat/cli-define-undefine July 17, 2026 16:35
@mahaloz mahaloz closed this Jul 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant