Ipa-medit is a memory search and patch tool for resigned ipa without jailbreaking. It supports iOS apps running on iPhone and Apple Silicon Mac. It was created for mobile game security testing. Many mobile games have jailbreak detection, but ipa-medit does not require jailbreaking, so memory modification can be done without bypassing the jailbreak 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 GameGem and iGameGuardian. However, there were no tools available for un-jailbroken device and CUI, Apple Silicon Mac. So I made it as a security testing tool. Android version is aktsk/apk-medit.
- macOS
- You need to have a valid iOS Development certificate installed.
- Only when targeting iOS apps running on an iPhone.
$ brew install --HEAD libplist
$ brew install --HEAD usbmuxd
$ brew install --HEAD libimobiledevice
$ brew install --HEAD ideviceinstaller
Download the binary from GitHub Releases and drop it in your $PATH.
You can build it by using the make command.
Go compiler is required to build.
If you are targeting an iOS app that runs on an Apple Silicon Mac, you will need to sign it, but script/codesign.sh
will be executed and signed automatically.
$ git clone git@github.com:aktsk/ipa-medit.git
$ cd ipa-medit
$ make build
The target .ipa file must be signed with a certificate installed on your computer. If you want to modify memory on third-party applications, please use a tool such as ipautil for re-signing.
$ ipautil decode tap1000000.ipa # unzip
$ ipautil build Payload # re-sign and generate .ipa file
To launch it, you need to specify the executable file path contained in the .ipa file with -bin
and the bundle id with -id
.
$ unzip tap1000000.ipa
$ ipa-medit -bin="./Payload/tap1000000.app/tap1000000" -id="jp.hoge.tap1000000"
To launch it, you need to specify the process name with -name
or the pid with -pid
.
The process name and pid of the iOS app can be checked in the Activity Monitor.
$ ipa-medit -name <process name>
Here are the commands available in an interactive prompt.
Search the specified integer on memory.
> find 999986
Success to halt process
Scanning: 0x00000001025e4000-0x00000001025e8000
Scanning: 0x00000001025f4000-0x00000001025fc000
Scanning: 0x0000000102604000-0x0000000102608000
....
Scanning: 0x000000016eb34000-0x000000016ebbc000
Scanning: 0x000000016ebc0000-0x000000016ebe8000
Scanning: 0x000000016ebec000-0x000000016ec74000
Scanning: 0x000000016ec78000-0x000000016ed00000
Found: 1!!
Address: 0x10a2feea0
By default, only integers are searched when targeting iOS apps running on iPhone, because the LLDB API is slow. When targeting an iOS app running on Apple Silicon Mac, strings will also be searched.
You can also specify datatype such as string, word, dword, qword.
> find dword 999994
Search Double Word...
Target Value: 999994([58 66 15 0])
Found: 1!!
Address: 0x11378aea0
Filter previous search results that match the current search results.
> filter 999842
Success to halt process
Found: 1!!
Address: 0x1087beea0
Write the specified value on the address found by search.
> patch 10
Successfully patched!
Attach to the target process.
> attach
Success to halt process
Detach from the attached process.
> detach
Success to continue process
Get information about the target process. It will only work if you are targeting an iOS app running on an iPhone.
> ps
SBProcess: pid = 926, state = running, threads = 37, executable = tap1000000
State: Running
thread #1: tid = 0x545ee, 0x00000001bd6552d0 libsystem_kernel.dylib`mach_msg_trap + 8, queue = 'com.apple.main-thread'
thread #3: tid = 0x54619, 0x00000001bd67a184 libsystem_kernel.dylib`__workq_kernreturn + 8
thread #4: tid = 0x5461a, 0x00000001bd67a184 libsystem_kernel.dylib`__workq_kernreturn + 8
thread #5: tid = 0x5461b, 0x00000001bd67a184 libsystem_kernel.dylib`__workq_kernreturn + 8
thread #6: tid = 0x5461c, 0x00000001bd67a184 libsystem_kernel.dylib`__workq_kernreturn + 8
thread #7: tid = 0x5461d, 0x00000001bd6552d0 libsystem_kernel.dylib`mach_msg_trap + 8, name = 'com.apple.uikit.eventfetch-thread'
thread #8: tid = 0x5461e, 0x00000001bd6791ac libsystem_kernel.dylib`__psynch_cvwait + 8, name = 'GC Finalizer'
thread #9: tid = 0x5461f, 0x00000001bd65530c libsystem_kernel.dylib`semaphore_wait_trap + 8, name = 'Job.Worker 0'
thread #10: tid = 0x54620, 0x00000001bd65530c libsystem_kernel.dylib`semaphore_wait_trap + 8, name = 'Job.Worker 1'
thread #11: tid = 0x54621, 0x00000001bd65530c libsystem_kernel.dylib`semaphore_wait_trap + 8, name = 'Job.Worker 2'
...
thread #35: tid = 0x54659, 0x00000001bd6552d0 libsystem_kernel.dylib`mach_msg_trap + 8, name = 'AURemoteIO::IOThread'
thread #36: tid = 0x54662, 0x00000001bd679814 libsystem_kernel.dylib`__semwait_signal + 8
thread #37: tid = 0x54663, 0x00000001bd6552d0 libsystem_kernel.dylib`mach_msg_trap + 8, name = 'com.apple.CoreMotion.MotionThread'
thread #38: tid = 0x54664, 0x00000001bd65530c libsystem_kernel.dylib`semaphore_wait_trap + 8, name = 'Loading.PreloadManager'
To exit medit, use the exit
command or Ctrl-D
.
> exit
Bye!
If you get the error /private/var/containers/Bundle/Application/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/hoge.app: error: failed to get reply to handshake packet
and can't communicate properly with iOS device and lldb, launch Xcode and build some app, and it will work.
If you get the error Could not connect to lockdownd.
and can't communicate properly with iOS device and ideviceinstaller, launch Xcode and build some app, and it will work.
If this does not solve the problem, please update ideviceinstaller and libimobiledevice to the latest versions using the example of commands in the Requirements section.
This can be fixed by installing the latest unversioned code of libimobiledevice and ideviceinstaller by adding the --HEAD
option when doing brew install
.
MIT License