
memory search and patch tool on debuggable apk without root & ndk
Apk-medit is a memory search and patch tool for debuggable apk without root & ndk. It was created for mobile game security testing. Many mobile games have rooting detection, but apk-medit does not require root privileges, so memory modification can be done without bypassing the rooting detection.
Memory modification is the easiest way to cheat in games, it is one of the items to be checked in the security test. There are also cheat tools that can be used casually like GameGuardian. However, there were no tools available for non-root device and CUI. So I made it as a security testing tool. The version that targets iOS apps is sterrasec/ipa-medit.
This is a demo that uses apk-medit to clear a game that requires one million taps to clear.


Download the binary from GitHub Releases, please push the binary in /data/local/tmp/ on an android device.
Binaries are provided for arm64 (physical devices) and amd64 (x86_64 Android emulators, e.g. on Windows PCs). Check the ABI of your device with adb shell getprop ro.product.cpu.abi.
$ adb push medit /data/local/tmp/medit
medit: 1 file pushed. 29.0 MB/s (3135769 bytes in 0.103s)
You can build with make command. It requires a go compiler.
After the build is complete, if adb is connected, it pushes the built binary in /data/local/tmp/ on an android device.
$ make
GOOS=linux GOARCH=arm64 GOARM=7 go build -o medit
/bin/sh -c "adb push medit /data/local/tmp/medit"
medit: 1 file pushed. 23.7 MB/s (3131205 bytes in 0.126s)
To build for an x86_64 Android emulator, use the build-x86_64 target instead.
$ make build-x86_64 deploy
GOOS=linux GOARCH=amd64 go build -o medit
/bin/sh -c "adb push medit /data/local/tmp/medit"
On Windows 10 Cmd and PowerShell the always-on command description panel drifts upward and covers the prompt (#37).
When medit detects a Windows-like console (a native Windows build, or TERM empty/dumb), it prints the command list once at startup and disables the live panel instead; Tab still completes command names.
APK_MEDIT_LIVE_HELP=1 / 0 forces the live panel on or off.APK_MEDIT_WINDOWS_CONSOLE=1 / 0 overrides the console detection.Use the run-as command to read files used by the target app, so apk-medit can only be used with apps that have the debuggable attribute enabled.
To enable the debuggable attribute, open AndroidManifest.xml, add the following xml attribute in application xml node:
android:debuggable="true"
You can also use sterrasec/apkutil to easily enable the debuggable attribute without editing AndroidManifest.xml, it is useful.
$ apkutil debuggable <target-apk-name>.apk
After running the run-as command, directory is automatically changed. So copy medit from /data/local/tmp/.
Running medit launches an interactive prompt.
$ adb shell
$ pm list packages # to check <target-package-name>
$ run-as <target-package-name>
$ cp /data/local/tmp/medit ./medit
$ ./medit
You can also choose not to use ptrace when writing to memory. This avoids debugger detection by ptrace, but don't work on Android 10 or later due to SELinux.
$ ./medit -without-ptrace
Here are the commands available in an interactive prompt.
Search the specified integer on memory.
> find 999982
Search UTF-8 String...
Target Value: 999982([57 57 57 57 56 50])
Found: 0!
------------------------
Search Word...
parsing 999982: value out of range
------------------------
Search Double Word...
Target Value: 999982([46 66 15 0])
Found: 1!
Address: 0xe7021f70
You can also specify datatype such as string, word, dword, qword.
> find dword 999996
Search Double Word...
Target Value: 999996([60 66 15 0])
Found: 1!
Address: 0xe7021f70
Filter previous search results that match the current search results.
> filter 993881
Check previous results of searching dword...
Target Value: 993881([89 42 15 0])
Found: 1!
Address: 0xe7021f70
Write the specified value on the address found by search.
> patch 10
...
Successfully patched!
Find the target process and if there is only one, specify it as the target. ps runs automatically on startup.
> ps
Package: jp.sterrasec.tap1000000, PID: 4398
Target PID has been set to 4398.
If target pid set by ps, attach to the target process, stop all processes in the app by ptrace.
> attach
Target PID: 4398
Attached TID: 4398
Attached TID: 4405
Attached TID: 4407
Attached TID: 4408
Attached TID: 4410
Attached TID: 4411
Attached TID: 4412
Attached TID: 4413
Attached TID: 4414
Attached TID: 4415
Attached TID: 4418
Attached TID: 4420
Attached TID: 4424
Attached TID: 4429
Attached TID: 4430
Attached TID: 4436
Attached TID: 4437
Attached TID: 4438
Attached TID: 4439
Attached TID: 4440
Attached TID: 4441
Attached TID: 4442
If target pid is not set, it can be specified on the command line.
> attach <pid>
Detach from the attached process.
> detach
Detached TID: 4398
Detached TID: 4405
Detached TID: 4407
Detached TID: 4408
Detached TID: 4410
Detached TID: 4411
Detached TID: 4412
Detached TID: 4413
Detached TID: 4414
Detached TID: 4415
Detached TID: 4418
Detached TID: 4420
Detached TID: 4424
Detached TID: 4429
Detached TID: 4430
Detached TID: 4436
Detached TID: 4437
Detached TID: 4438
Detached TID: 4439
Detached TID: 4440
Detached TID: 4441
Detached TID: 4442
Display memory dump like hexdump.