Introduction to Keypatch
1. Problem of the built-in IDA assembler
IDA Pro is the de-facto binary analysis tool widely used in the security community. While browsing the assembly code in IDA, we may want to modify the original code to change the behavior of the executable file. IDA offers this functionality in its menu “Edit \ Patch program \ Assemble”, in which we can type in new assembly to overwrite the existing code, as in the screenshot below.
However, this built-in assembler suffers from several significant issues, as follows.
- Except X86, it does not support any other architectures. Due to this, when we open the menu on an ARM binary, IDA refuses with a message “Sorry, this processor module doesn’t support the assembler”.
- Even on X86, IDA assembler fails to handle many simple X86_64 instructions. For example, the instruction “PUSH RAX” is refused with error “Invalid operand”.
- We anticipated that IDA assembler misses all the latest X86 instructions (such as those from SGX extension), but actually it also fails on many not-so-modern X86 instructions. For example, AVX instruction “VDIVSS XMM2, XMM6, XMM4” is (wrongly) considered illegal with error “Invalid mnemonic”.
- X86 assembler seems quite buggy, with many minor issues here and there. Example: if you enter invalid code “PUSH ESI” on an X86_64 binary, IDA assembler would happily accept that, but then overwrite the existing code with one byte “56”, which is actually for “PUSH RSI”.
- If the new patched code is shorter than the original code, the orphan bytes after the new code are kept intact, which is mostly undesired. In the example below, 3 original bytes “48 89 FB” (for “MOV RBX, RDI”) are overwritten with 2 bytes “31 C0” (for “XOR EAX, EAX”). The orphan byte “FB” is still there, and decoded as instruction “STI”. Due to this, we need to perform one more step to patch this left-over byte with “NOP” opcode. Unfortunately, IDA does not do clear the orphan code.
- IDA assembler does not log any changes, making it hard to track what and where code were modified. We would have to keep note on what we patched, which is cumbersome.
Unfortunately, there was no solution for all the above problems of IDA assembler. We decided to accept the challange, and build a new assembler plugin for IDA named Keypatch to solve all the existing issues.
Our tool offers some nice features as follows.
Keypatch leverages the power of Keystone assembler engine, so it can support 8 CPUs: X86, ARM, ARM64, Hexagon, Mips, PowerPC, Sparc & SystemZ. On each architecture, Keystone is able to handle the latest CPU instruction sets.
Our GUI makes it much easier to see what you would do: it shows the original code (before modifying), and new code that will patch your binary.
We have an option to automatically pad all the orphan bytes with NOP opcode.
Keypatch can understand & accept IDA symbols, so you can conveniently use them in assembly code, without having to convert them to immediates beforehand.
We make it easier to track what and where the code were modified by logging all the changes in the “Output” window of IDA, with content like:
- Keypatch has another functionality in its own menu “Edit \ Keypatch \ Assembler”, in which you can experimentally assemble arbitrary code on any architectures supported by Keystone. This convenient tool does not modify the original binary under analysis, so can be an extra weapon in reversing process.
- Last but not least, Keypatch is open source, so it easy to fix bugs & add more features.
To summary, Keypatch has everything to replace the internal IDA assembler because it can do more, and do better. We believe that this little IDA plugin will be indispensible in your toolset of reverse engineering.