Library / SDK
MJx0/KittyMemory avatar
MJx0/KittyMemory

KittyMemory gives mobile reverse engineers a native memory API

C++ library for runtime memory patching, scanning, dumping, and module (ELF / Mach-O) introspection, targeting Android and iOS.

565 stars159 forksC++MIT

At a glance

What is it?
KittyMemory is a C++ library for runtime memory patching, pattern scanning, dumping and ELF and Mach-O introspection on Android and iOS, with a syscall-based scan mode that skips unmapped pages instead of crashing. It is MIT licensed, needs C++17, and the Keystone assembler is optional rather than required.
Who is it for?
Adopt KittyMemory if you are writing an Android or iOS reverse engineering tool and want patching, scanning and module introspection from C++ without an agent framework. Skip it if you need cross-platform desktop support or a scripting interface, since the library covers Android and iOS only and has no JavaScript or Python layer.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 35 days ago.
What is it written in?
Mainly C++, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A native library rather than an instrumentation framework

KittyMemory is a native C++ library for runtime memory patching, scanning, dumping and module introspection, targeting Android and iOS. The word native is the framing that matters, because the tool sits underneath a custom app or tweak rather than attaching to a running process the way an instrumentation framework does. There is no host, no script binding and no server, which makes it a building block rather than a finished product. The features are grouped into four families. Memory patching with backup, through `MemoryPatch` and `MemoryBackup`, supports snapshot-then-modify-then-restore workflows over arbitrary code or data, and the patch can be built from raw bytes, from a hex string, or from hand-written assembly through the Keystone engine. Pattern scanning is the second family. ELF introspection on Android and Mach-O introspection on iOS are the third. Memory maps, memory regions and instruction decoding make up the fourth, along with the dump utilities. The scope is wide for a library this size, and the requirements are modest: C++17 or newer, with Android needing the NDK at API level 21 or newer, and iOS needing Theos or Xcode for building tweaks and dylibs with a deployment target of iOS 14.0 or later.

The scanner has two modes and the difference is a crash

The pattern scanning API is the piece most worth understanding before use. `KittyScanner` exposes `findBytesFirst` and `findBytesAll`, `findHexFirst` and `findHexAll`, `findIdaPatternFirst` and `findIdaPatternAll`, and `findDataFirst` and `findDataAll`, which between them cover byte-mask searches, hex-mask searches, IDA-style patterns written as something like `"33 ? 55 66 ? 77 88 ? 99"`, and exact raw-value searches. The mode distinction is the important part. There is a fast in-process mode and a safe syscall-based mode, enabled with `setPatternScanSafeMode`, and the difference in behaviour is described bluntly: the safe mode skips unmapped pages instead of crashing. That is a real design decision rather than a performance footnote, because a scanner that reads process memory will walk into an unmapped region sooner or later, and whether that is a segfault or a skipped page depends entirely on which mode you picked. If you are scanning a stable, well-known library the fast mode is fine. If you are scanning across a large address space with libraries mapped in unusual ways, the syscall mode is the difference between a tool that works and a tool that takes the process down with it.

ELF introspection reads the loaded image, not the file on disk

On Android, `ElfScanner` parses a loaded library's program headers, dynamic section, and symbol and hash tables directly out of memory, and the README is explicit that the file on disk is not needed, including for libraries mapped from inside a split APK or zip. That distinction is the whole point of the class. The file on disk and the loaded image are different objects, and for a packed, encrypted or renamed library they can differ substantially. Symbol lookup covers both the live dynamic symbol table through `findSymbol` and on-disk debug symbols through `dsymbols` and `findDebugSymbol`, the latter being for symbols that are not dynamically exported. Segment discovery exposes the module's main segment with `baseSegment()`, all mapped segments with `segments()`, and the BSS segments with `bssSegments()`, each represented as a `KittyMemory::ProcMap`. `ElfScanner::dumpToDisk` completes the loop by writing the loaded library's ELF image straight from memory to a file, which the README describes as useful for pulling packed, decrypted or renamed libraries. That is a forensics workflow, not a patching one, and it is the clearest statement of what the library is for.

The solist walker and the native bridge case

Two Android-specific pieces handle the case where the usual enumeration does not work. `LinkerScanner` walks the Android dynamic linker's internal `solist` to enumerate every natively-loaded library, which reaches libraries that a normal loader query would not report. `NativeBridgeScanner` does the same job for libraries running under an ISA emulation layer, naming libhoudini and libndk_translation, and it also detects the implementation and the native bridge callback table through `nbItfData()`. The `NativeBridgeLinker` companion then lets you call `dlopen`, `dlsym`, `dlclose`, `dladdr` and `dl_iterate_phdr` directly against those emulated libraries. This is the part of the library with the sharpest edge, because it depends on internals of the platform linker rather than a public API, so it is the part most likely to need revisiting after an OS update. The same caveat applies in a milder form to the solist walk. Both are exactly the tools you need when a library is hidden from the normal loader, and exactly the tools that break first when the platform changes.

Mach-O on iOS and the ASLR problem it solves

On iOS the equivalent surface is `MachOImage`, which resolves a loaded image, meaning the app binary or a named framework or dylib, through `findMachOImage`, `getMainImage` and `getAllImages`. Symbol lookup comes in two forms, `symbols()` for all non-STAB symbols and `findSymbol(name)` for a specific one, and segment and section discovery works through `segments()` and `sections()` keyed by name, plus the targeted `findSegment("__TEXT")` and `findSection("__TEXT", "__text")`. The one function that deserves its own mention is `KittyMemory::getAbsoluteAddress`, which turns an on-disk offset into a live ASLR-slid address. That is the operation you cannot do with a file offset on its own, and on a platform with pointer authentication and per-process slide it is the difference between a patch that lands and a patch that corrupts memory.

Maps, regions and the dump utilities

The remaining surface is bookkeeping and output. On Android, `KittyMemory::ProcMap` models a single `/proc/self/maps` entry with its bounds, permissions and backing file, and `getAllMaps()`, `getMaps(EProcMapFilter, name)` with the `Equal`, `Contains`, `StartWith`, `EndWith` and `Regex` filters, and `getAddressMap(address)` enumerate and filter them. On iOS the same shape exists over Mach `vm_region` calls, with `KittyMemory::mem_range_info_t` holding the bounds, the protection and maximum protection and the name, and `getAllRegions()`, `getRegions(EMemRegionFilter, name)` and `getAddressRegion(address)` doing the work. Both platforms offer `getFileMappings(path)`, which groups a backing file's mappings into contiguous runs and handles files split across several mappings. The dump utilities build on that: `KittyMemory::dumpMemToDisk` writes an arbitrary address range to a file, and `KittyMemory::dumpFileMappingsToDisk` writes every contiguous mapping of a memory-mapped file to disk, one output file per mapping if it is split, with Unity's `global-metadata.dat` given as the example. `KittyAsm` with the `KittyArm32` and `KittyArm64` namespaces is a lightweight ARM32 and ARM64 instruction decoder sitting alongside all of this.

Editorial conclusion

Adopt KittyMemory if you are writing an Android or iOS reverse engineering tool and want patching, scanning and module introspection from C++ without an agent framework. Skip it if you need cross-platform desktop support or a scripting interface, since the library covers Android and iOS only and has no JavaScript or Python layer. Before you commit, read the scan mode decision, because the fast in-process mode will crash on unmapped pages while the safe syscall mode is slower, and check the build scripts for Keystone if you want assembly patches.

Frequently asked questions

What platforms does KittyMemory target?

Android and iOS. Android needs the NDK with API level 21 or newer, and iOS needs Theos or Xcode for building tweaks and dylibs with a deployment target of iOS 14.0 or later. The library itself requires C++17 or newer.

What is the difference between the two KittyMemory scanning modes?

There is a fast in-process mode and a safe syscall-based mode enabled with `setPatternScanSafeMode`. The safe mode skips unmapped pages instead of crashing, so it is the one to use when a scan might walk into a region that is not mapped.

Does KittyMemory need the Keystone assembler?

Only for `MemoryPatch::createWithAsm`. Prebuilt static libraries for both platforms are vendored under `KittyMemory/Deps/Keystone`, and you can rebuild them with `Deps/Keystone/build_keystone_android.sh` and `build_keystone_ios.sh`. Defining `kNO_KEYSTONE` in your C++ flags removes the dependency and with it the assembly patch entry point.

What can ElfScanner on Android do that reading the file on disk cannot?

It parses a loaded library's program headers, dynamic section, and symbol and hash tables directly out of memory, including for libraries mapped from inside a split APK or zip, and `ElfScanner::dumpToDisk` can write that loaded image to disk, which the README describes as useful for pulling packed, decrypted or renamed libraries.

Official sources

  1. Issues
  2. License: MIT
  3. MJx0/KittyMemory on GitHub
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/mjx0-kittymemory.svg)](https://hysenlabs.com/projects/mjx0-kittymemory)

Was this useful?