Things explained in the part 1 could be skipped.
Multiple architectures and PIE
In case apps support multiple architectures, you need to choose the right architecture working on your device to find the right cryptid/cryptoff/cryptsize. You should also check if an app under test is built with PIE (Position Independent Executables) as the app’s code, data and stack memory addresses are changing every time whenever you load the app. If an app supports PIE, you have to know the exact memory address the app is loaded at to calculate the offset of the decrypted area.
Let’s take a look at a sample app.
Log into your jailbroken device via ssh, and go to the directory where an app you want to decrypt resides. The directory will be under “/var/mobile/Applications/”. Copy the executable to your Mac.
Run otool to see how the app is built on your Mac (see Figure 1).
You can find this app supports two architectures (nfat_arch 2) which are armv7 and armv7s. Run the app and attach gdb to see which architecture is used (Figure 2).
If you confirmed armv7 was picked, kill the app and quit gdb.
Run “otool -arch armv7 -l ColorLEDFlashlightPro | grep crypt” to get the encryption data (Figure 3) and confirm this app is encrypted.
So far we have found which instance of program we should select (Figure 1) and its cryptoff (8192) and cryptsize (3047424).
Let’s check PIE for this app by using otool again (Figure 4).
You can see this app is built with the PIE option.
Check the loading address in the file’s header using “otool -l” (Figure 5).
Based on Figure 5, you can expect the app will be loaded at 0x1000. Run the app and attach gdb to check if the app is loaded at 0x1000 (see Figure 6).
Try to read some data at 0x1000, 0x2000 and 0x3000 (Figure 7).
As you see, you can’t access those addresses. Let’s find out where the app is loaded using “info sharedlibrary” (Figure 8). You can see the app is loaded at the address, 0x4f000 not 0x1000.
Now you can read data from the loading address (Figure 9).
It’s time to calculate the starting and ending address we will dump. The app’s base address is 0x4f000 and its cryptoff (8192 or 0x2000) and cryptsize (3047424 or 0x2e8000). Hence we should dump memory between 0x51000 (the base address + cryptoff) and 0x339000 (the base address + cryptoff + cryptsize)
Run the following instruction on gdb.
dump memory decrypted2.bin 0x51000 0x339000
Copy the dumped file to your Mac. Before you overwrite the app’s executable, let’s run class-dump-z and confirm it is encrypted (Figure 11).
$ ./class-dump-z ColorLEDFlashlightPro
There is a difference between an app for a single architecture and an app for multiple architectures. A starting offset of a program instance is 0 for a single architecture case, but the starting offsets for the program instances in an app supporting multiple architectures differ. You should check the starting offset of the program instance you deal with.
Overwrite the executable with the dumped file. In this example, the starting offset of the first program instance we deal with is 0x1000 (see Figure 1). Therefore we will overwrite the executable from the offset 0x3000 (0x1000(the starting offset) + 0x2000(cryptoff)).
$ dd seek=0x3000 bs=1 conv=notrunc if=./decrypted2.bin of=./ColorLEDFlashlightPro
Update cryptid as you see in the part 1 (Figure 12, 13).
Confirm if cryptid is changed using otool again (Figure 14).
As a final step, run class-dump-z again to see if the app is decrypted successfully.
$ ./class-dump-z ColorLEDFlashlightPro
Testing environment
- OS: iOS 6.01
- Device: jailbroken iPod 4G
- tools: otool, gdb, class-dump-z
Reference
- Hacking and Securing iOS Applications – O’REILLY: chapter 7
- http://www.trailofbits.com/resources/ios4_security_evaluation_paper.pdf
Thank you, for a very easy and understandable tutorial. Worked like a charm.
Reb, I’m glad to hear that!
Thanks for a fantastic guide to decrypting apps.
I followed the guide and managed to get to the class-dumb-z stage which failed with Segmentation fault: 11.
This was unexpected as the app still ran once I’d copied the memory dumb into the application binary.
I hunted around and came across the following article: http://www.peterfillmore.com/2013/01/disabling-aslr-on-individual-ios.html, which discusses the use of ASLR as a means to change memory addresses of libraries during runtime, which may have resulted in the issues I’m having. I followed through this guide and also tried the removePIE (which runs on the device) tool http://www.peterfillmore.com/2013/01/removepie-tool-for-disabling-aslr-on.html, but had the same issues:
1 – ldid caused the same Segmentation fault: 11 failure.
2 – removePIE failed with “File is not a Mach_O binary”
I exported a project from XCode and tried the various tools I’ve come across during my attempt to decrypt an app, and this has been successful. I understand this is because the app hasn’t been encrypted and the PIE setting has not been applied; I just needed a sanity check 🙂
I have a spare iPhone 4s running 6.0.1, which I aim to jailbreak and try the process again, in case the issue is related to iOS 5.0.1, I’ll report back how I get on, in the meanwhile if do have any suggestions on where I’m going wrong.
Thanks again.
Hi parmby,
Unfortunately I don’t have suggestions for you. 😦 However, if you let me know the app causing this fault, I will try to take a look at it later this week.
Hi Mate
Thanks for getting back to me and the kind offer. I’m not sure if you’ll have access to the app, as I think it’s only available in the UK App store. The app is called: Millionaire (as in W:h:o W:a:n:t:s T:o B:e A M:i:l:l:i:o:n:a:i:r:e).
If you’re unable to get the app, will it help if I package the app for you, or send you the application binary and the dgb memory dump?
Thanks again, I really appreciate your offer to help, as I’m losing it here 🙂
Hi
I solved it. It was me not being able to follow the simple instructions you laid out.
In the end the error came down to not setting the encryption id for both apps – I only set it for the first (armv7) app. Hence following figures 12 and 13 above, I should have set both encryption id’s to 0.
Thanks again for your help, please feel free to delete my posts and replace with the summary:
If the final step: ./class-dumb-z fails with Segmentation fault: 11, make sure both “cryptic” are set to 0; using your example:
otool -l ColorLEDFlashLightPro | grep crypt
should return:
cryptoff 4096
cryptsize 3027424
cryptid 0
cryptoff 8192
cryptsize 3027424
cryptid 0
Thanks again, and a fantastic post 🙂
It seems you decrypted the code of the second architecture. So you need to set the second cryptid to 0 not the first one. I think when you set both cryptid to 0 and run the app on the first architecture, the app might not be able to run properly.
Thanks for your brilliant job:
I also fetch the same problem which class-dumb-z failed with Segmentation fault: 11.
I hunted around and try to remove ALSR discusses in other articles. But still had the same issues:
1 – removePIE successed, but l did caused the same Segmentation fault: 11 failure.
2 – the command “otool -f MyApp” did not output anything.
3 – when I type in the instruction “otool -l MyApp | grep crypt”, I got the right return i think :
cryptoff 8192
cryptsize 5128192
cryptid 0
so I think this app has only one architecture, in the meanwhile if do have any suggestions on where I’m going wrong.
Thanks very much.
I’ve got 2 problems and then solved it. First the GDB for my iOS6 did not work so i downloaded the one in here cydia.radare.org and update the one i had. Second i had the Segmentation fault: 11 because of dd seek i used the starting offset + crypt off , then i used only the starting offset and it worked.
thanks