This is a c/cpp library that uses capstone (https://www.capstone-engine.org) to find start addresses of an unique sequence of instruction mnemonics in a given image (main executable, dylib or a framework).
The search is done in terms of mnemonics (instruction strings like "mov", "str" etc).
You can also compare operands on specific mnemonics with this format "mov x1", "mov x2 x18", "mov x1 #0x4", "mov * x2".
* will ignore that operand but still match other operands. "mov x1" will only match first operand to x1 but will not match second operand. Per capstones formatting hex addresses need to have a leading '#' (i.e #0x192e39000). Square bracket operands need to be formatted as such: [sp, #-0x10]!
see simplePatchFinder-Test for an example of this format.
When looking for target sequences in binaries; in order to match instructions generated by our capstone to those generated by a standalone disassembler, its recommended to use radare2 (https://github.com/radareorg/radare2) because radare2's disassembly engine is also capstone.
std::vector<uint64_t> image_findInstructions(const struct mach_header_64* mh, std::vector<const char*> targetSequence)-
mh: image (mach header) to look for the target sequence in. You can pass NULL to search in the main executable. -
targetSequence: cpp vector of c strings that contains an exact sequence (so the order matters) of string representations (mnemonics) of arm64 instructions. For example "mov" or "bl". -
return: cpp vector containing start addresses of the found target sequences of instructions (these addresses take ASLR slide into account, so they should be ready for use).
extern "C" const struct mach_header_64* image_getFromBinaryName(const char* binaryName)-
binaryName: binary name of the loaded image. For example just "AppKit" for /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit or "libobjc.A.dylib" for /usr/lib/libobjc.A.dylib. -
return: mach header pointer for the target loaded image.
The library exposes the c function below so it can be used without cpp.
uint64_t* image_findInstructions(const struct mach_header_64* mh, char** targetSequence, size_t size, size_t* outCount)-
mh: image (mach header) to look for the target sequence in. You can pass NULL to search in the main executable. -
targetSequence: c array of c strings that contains an exact sequence (so the order matters) of string representations (mnemonics) of arm64 instructions. For example "mov" or "bl". -
size: count of how many instructions there are in targetSequence. -
outCount: address of a size_t variable, the variable will be the count of address entries the return array contains after this call. -
return: c array (caller is responsible for freeing) containing start addresses of the found target sequences of instructions (these addresses take ASLR slide into account, so they should be ready for use).
Depends on capstone library, you can install it via brew install capstone for more information see https://www.capstone-engine.org.
The binaries in the releases page are statically linked to capstone so it should work standalone without any dependencies.
- download the prebuilt library in the releases page.
- #include "simplePatchFinder.h".
- add the dylib to your projects Libraries & Frameworks section.
- see Example for code snippet.
see simplePatchFinder-Test.
#include "simplePatchFinder.h"
const struct mach_header_64* mh = image_getFromBinaryName("libobjc.A.dylib");
std::vector<uint64_t> addresses = image_findInstructions(mh, {"pacibsp", "stp", "stp"});
//for each address entry in `addresses`, first 3 instructions are "pacibsp", "stp", "stp"