Patch History UI
What is the feature you'd like to have? It would be really nice to see, at a glance, what the history of your patches is within the database with information like:
- What address was the patch created at?
- What were the bytes before the patch?
- What were the bytes after the patch?
- When was the patch made?
- (Enterprise) Who made the patch?
- (Optional) Enter a name/comments for the patch
- (Optional) Toggle the patch on/off
- (Optional) Do most of the above through an API
You can do a lot of this right now, manually, with custom tags...but, it's not super easy to work with.
Is your feature request related to a problem? This feedback is from an Enterprise customer of ours that recently had to perform a number of patching exercises under strict time constraints. Having this feature would have helped save them even more time than Binary Ninja already did, thanks to its quick patching out-of-the-box.
Are any alternative solutions acceptable? Anything is acceptable that would let you see what patches have been made and quickly manage them. My suggestion above is based off of feedback from our Enterprise customer and, I think, the best solution.
This is great. One comment:
The ability to toggle the patch is critical for my workflow. I work on malware signatures that are based on the original unpatched bytes. I also need to do many patches to perform effective analysis. I need to be able to quickly return the database to an unpatched state and back.
Ome more thought about this feature: I'm working on a packer that has tons of junk code. I can't patch all of it to nops at once, so if there is a patch UI with a toggle for patches, it would be great to be able to group patches together and toggle all of them at once.
There isn’t a dedicated patch UI yet, but the underlying functionality already exists through the MemoryMap and MemoryRegion APIs.
Example:
-
Create a patch:
bv.memory_map.add_memory_region("PATCH1", 0x418CA0, b'\xA5' * 0x20) -
Enable or disable the patch:
bv.memory_map.set_memory_region_enabled("PATCH1", False)
You can currently manage patches by name—maintaining your own list or grouping related patches together to toggle them as a set.
I also see several opportunities to build on the current MemoryMap facilities, such as:
- Native group support for organizing and toggling related patches
- Bulk modification capabilities for applying or reverting multiple patches at once
- Using the logical memory map to automatically hide all the internal patch segments created at patch boundaries
These could form the basis for a more integrated patch management UI in the future. I'll look into extending support to make the UI portion of this a breeze.
The underlying functionality exists, but it isn't hooked up in the way users expect. For example, if I make a patch in linear view or hex view right now, that doesn't go through memory map. It's a separate thing. That's what this issue is about.
You're absolutely right — the existing patching functionality in the UI uses a completely different underlying mechanism.
What I meant above is that while there isn’t a dedicated patch UI tied into the MemoryMap system yet, the core facilities (MemoryMap and MemoryRegion) already provide a foundation that could support a more flexible patching workflow in the future.
My comment was more about those lower-level capabilities being available now, not that the current UI patching is already built on them.
ability to just change code back to original form is critical. Undo affects more than just binary hex editing.
This issue will need to remain open as we have plans for a true patch manager UI, but it's worth nothing we do have one related features that might help some users who stumble across this issue. The history viewer lets you see (and revert) changes though it includes other changes as well and doesn't let you manually prune a specific change as @greggjaskiewicz notes above. However, in a pinch you could use it to just extract the original file and apply the raw bytes over your later changes. Again, not the best solution but at least a workaround that might be helpful to some users.
I don't want to open a separate issue if this one covers the following use case. @fuzyll let me know if this is covered or not. I'll open a separate issue if this one doesn't do this:
I have a plugin that removes all comments, highlights, and tags for a screenshot. It uses the undo functionality to put it all back when i'm done. Separately, there have been a bunch of awesome bug fixes recently with regards to analysis. If I undefine a function and create it again, all the new hotness with regards to analysis appear in the freshly analyzed function. I want to reuse the code for the screenshot plugin and then add a few more items to be removed (or stored if i can't just remove them): function signature, symbol, renamed variables, and variable type changes. I can see that there is a set of undo entries in the history stack. There is a big chunky one for all the annotations I removed with the plugin. Then there are two entries: one for undefining the function and the other for creating a new function in its place. I can get to the undo entry for the annotation removal and i can list the actions it contains. I want to select that undo entry and "cherrypick undo" just that entry without also undoing all the others between now and that entry.
Here I can see the exact entry I want and all the actions it contains.
I want to undo that entry and that entry only, leaving the two that are after it.