This blog post steps through how to convert encrypted iPhone application bundles into plaintext application bundles that are easier to analyse.
Requirements: 1) Jailbroken iPhone with OpenSSH, gdb plus other utilities (com.ericasadun.utilities etc. etc.) 2) An iPhone app 3) On your machine:
Some groundwork, taken from Apple's API docs [1, 2]:
The iPhone apps are based on Mach-O (Mach Object) file format. The image below illustrates the file format at high-level:
A Mach-O file contains three major regions: 1. At the beginning of every Mach-O file is a header structure that identifies the file as a Mach-O file. The header also contains other basic file type information, indicates the target architecture, and contains flags specifying options that affect the interpretation of the rest of the file. 2. Directly following the header are a series of variable-size load commands that specify the layout and linkage characteristics of the file. Among other information, the load commands can specify:3. Following the load commands, all Mach-O files contain the data of one or more segments. Each segment contains zero or more sections. Each section of a segment contains code or data of some particular type. Each segment defines a region of virtual memory that the dynamic linker maps into the address space of the process. The exact number and layout of segments and sections is specified by the load commands and the file type. 4. In user-level fully linked Mach-O files, the last segment is the link edit segment. This segment contains the tables of link edit information, such as the symbol table, string table, and so forth, used by the dynamic loader to link an executable file or Mach-O bundle to its dependent libraries.
- The initial layout of the file in virtual memory
- The location of the symbol table (used for dynamic linking)
- The initial execution state of the main thread of the program
- The names of shared libraries that contain definitions for the main executable's imported symbols
The iPhone apps are normally encrypted and are decrypted by the iPhone loader at run time. One of the load commands is responsible for decrypting the executable.
Push EBP Mov EBP, ESP JMP loc_6969 loc_6969:Once you have downloaded and installed an app on your iPhone, make a copy of the actual executable on your machine.
Note1: The blah.app is not the actual executable. If you browse this folder, you will find a binary file named blah. This is the actual application binary.
Note2: To find the path where your application is installed, ssh onto your iPhone and use the following command:
sudo find / | grep blap.appOnce you have copied the app binary on your machine, follow the steps below (on your local machine).
Open up a terminal and type the following command:
otool —l blah | grep cryptThis assumes that iPhone SDK or otool is already installed on your machine.
The above command will produce the following output:
If cryptid is set to 1, it implies that the app is encrypted. cryptoff and cryptsize indicates the offset and size of crypt section respectively. Now, firstly we'll have to locate the cryptid in the binary and set it to zero. This is done so that when we finally decrypt the binary and execute it on iPhone, the loader does not attempt to decrypt it again. Open the binary in a hex editor and load the binary. I did not come across any definite method of locating the cryptid. Once you have loaded the binary in a hex editor, search for “/System/Library/Frameworks”. You should be able to locate it around the address 0x1000. In the line, just above the very first instance of this statement (/System/Library/Frameworks), you will find bytes 01. Flip it to 00 and save the file.
Note3: In case you find multiple instances of 01, use coin-tossing method of choosing between them.
Use otool again to query the crypt data. You will see that the cryptid is now set to 0 (zero).
Next, we need to run the app, which was installed on iPhone and take a memory dump.
Note4: The actual application code starts at 0x2000. The cryptsize in case of our sample app is 942080 (0xE6000). Hence, we add 0x2000 and 0xE6000.
0x2000 + 0xE6000 = 0xE8000Therefore, we need to dump the running process from 0x2000 till 0xE8000. Now, ssh onto your iPhone, run the target app and look for the process id using “ps —ax” command. Once you have the process id, use the following command to dump the process:
gdb —p PID dump memory blah.bin 0x2000 0xE8000Once you have taken the memory dump, use “quit” command to exit gdb. Use the following command to get the size of memory dump:
ls —l blah.binThe size of this bin file should exactly be same as the cryptsize of the original app. Refer to screenshot above. Now pull this bin file onto your local machine. On your local machine, load the bin file in a hex editor and copy everything (using select all or whatever). Close the file and open the original app in the hex editor. (The file in which we modified cryptid 01 to 00). If you remember, the cryptoff was 4096, which is 0x1000 (in hex). Proceed to memory address 0x1000 and make sure that your hex editor is in overwrite mode, not in append mode. Once you are on memory address 0x1000, paste everything you copied from the bin file. This will overwrite the encrypted section with the decrypted one. Save the file and you're done.
Open the file in IDA pro and you'll see the difference between the encrypted and decrypted binaries. At this point, you can easily reverse engineer the app and patch it. The first image below shows an encrypted app and the second one illustrates a decrypted app:
After patching the application, ssh onto the iPhone and upload it to the application directory. This would mean replace the original binary with the patched one. Once uploaded, install a utility called "ldid" on your iphone.
apt-get install ldidFinally, sign the patched binary using ldid:
ldid -s blahThis will fix the code signatures and you will be able to run the patched app on your iPhone.
References:
1) http://developer.apple.com/library/mac/#documentation/DeveloperTools/Conceptual/MachORuntime/Reference/reference.html
2) http://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man1/otool.1.html
i have an app that i want to disassemble. Can you do it on a non App Store app but in a Cydia app?
And can you tell me the software you used?
Terminal name and for what machine(Win or MAC)
Thanks you very very much and keep posting:)
manos364
This can be performed on any iPhone application irrespective of app stores. The tools are listed in "Requirements" section above. I work on Mac os x; however, all the above-mentioned tools are also available on windows.
Hope it helps.
./saurabh
Is this approach works on version >= iOS 4.0?
Are we still able to decrypt apps, did you try to do it?
yeah, this should work on iOS 4.0. Just make sure to upgrade to latest version of ldid for fixing the signature of patched binaries.
./saurabh
What about iOS 5, did you test it? I think the cryptoff address is randomly choosen for each application in the later versions of iOS and I was just wondering if Apple deployed new things in this area maybe also they have deployed preventing methods against gdb.
0xdb
You're right about iOS5. Additionally, gdb from cydia does not work well with iOS 5 and requires some modifications.
./saurabh
The following structure breaks it down, in mach-o/loader.h:
struct encryption_info_command {
uint32_t cmd; /* LC_ENCRYPTION_INFO */
uint32_t cmdsize; /* sizeof(struct encryption_info_command) */
uint32_t cryptoff; /* file offset of encrypted range */
uint32_t cryptsize; /* file size of encrypted range */
uint32_t cryptid; /* which enryption system,
0 means not-encrypted yet */
};
LC_ENCRYPTION_INFO is going to be 0x21. So you'll see a series of the following bytes:
0x21 0x00 0x00 0x00 <4 bytes: sizeof(struct encryption_info_command)> <4 bytes: offset> <4 bytes: size> <cryptid!>
Which is exactly what you see in your screenshot.
Make sure your gdb is working fine and you're able to hook the target process and break at appropriate memory location. This should work before you take a memory dump.
Thx in advice for your answer.
When i try to decompile with ida, ida have red part on the upper bar, i think this is crypted part, i have right? THX!
And indeed, the first 0x1000 bytes of the dump (ie. what would end up overwriting 1000-2000 in the binary) is identical to the original executable, with cryptid=01.
The cryptid should be changed from 01 to 00 *after* overwriting the binary with the dumped data.
need lastest version of GDB or kernel patch?
i tested the ways of that link. but it dosen't work.
ng 5.1.1 :
http://uploading.com/files/fc3fmc5m/gdb/
(sorry it's such a crappy mirror, just posting the link I found).
es, so I am not able to pull a PID because it is not running, but it is sti=
ll backgrounded - it is in my recently used apps. Any ideas?
d, the application code starts at 0x2000, my Cryptsize is 1728512, so that =
is 1xA6000. Add the two together and I get 1xA8000, but GDB says that my st=
op address is a 'Invalid number'. I am looking are seeing if I could figure=
it out, but if anyone could offer up help that would be awesome. Thanks!