decrypt iOS appsI’m going to walk through the steps it takes to decrypt an iOS app. Since iOS encrypts all of its apps it makes it basically impossible to do any static analysis on an app without decrypting first. If you want to be able to check out an app within IDA you will first have to decrypt it and repackage it. At a high level we will make iOS decrypt the binary. While its decrypted we will extract the decrypted portions with GDB. We will then take the unencrypted portion and patch it over the encrypted portion of the binary with dd.  This post doesn’t talk about the reversing process once you get the app to IDA but what you need to do to start reversing an app in IDA and what you need to do to get the reversed app running on the phone again. And it goes without saying this must all be done on a phone that you have root on.

1. Extract the application
iOS apps live in /private/var/mobile/Applications/UID where the UID is the universally unique identifier of the app. You will have to cd into the different directories until you find what the app you are looking to analyze. My example below.

cd /private/var/mobile/Applications/A54D09EF-E8CD-41AD-A10E-090302B62562/

While its a bit overkill, once you find the correct directory you can just scp down the whole .app folder down to your machine.

2. Find the binary
Now we have the whole working directory we just need to find the binary that we will be decrypting. This can be done with otool that comes with Xcode. Just run otool within the directory you just pulled down. As you see below have an have an ARM binary. This will be the binary we will want to decrypt.

otool -arch all -Vh Free\ Chess 
Free Chess:
Mach header
      magic cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
   MH_MAGIC     ARM         V6  0x00     EXECUTE    23       2672   NOUNDEFS DYLDLINK TWOLEVEL BINDS_TO_WEAK

3. Find encrypted area
We now need to find what area of the binary is encrypted. We will use this information to patch the decrypted portion over the encrypted portion using dd.

otool -arch all -Vl Free\ Chess | grep -A5 LC_ENCRYP
          cmd LC_ENCRYPTION_INFO
      cmdsize 20
    cryptoff  4096
    cryptsize 192512
    cryptid   1
Load command 10

As you can see cryptoff is 4096 which is the start of the encrypted portion and cryptsize is 192512 showing the size of the encrypted area. Note cryptid which is 1. This means the application is encrypted. We will flip this later so iOS thinks it decrypted and won’t try to decrypt the app again.

Running the below command will show you the LC_SEGMENT load command within the TEXT segment.

otool -arch all -Vl Free\ Chess 
Free Chess:
Load command 0
      cmd LC_SEGMENT
  cmdsize 56
  segname __PAGEZERO
   vmaddr 0x00000000
   vmsize 0x00001000
  fileoff 0
 filesize 0
  maxprot ---
 initprot ---
   nsects 0
    flags (none)
Load command 1
      cmd LC_SEGMENT
  cmdsize 328
  segname __TEXT
   vmaddr 0x00001000
   vmsize 0x00030000
  fileoff 0
 filesize 196608
  maxprot r-x
 initprot r-x
   nsects 4
    flags (none)

So we see the app is starting at 0x00001000 and we know our encrypted data starts at 4096 from cryptoff. Pull out a hex calculator and you will find 4096 is 0x1000. We now have all the information we need about the encrypted portion of the app so we can extract it once its unencrypted and patch it over with the encrypted portion. We know the app starts at 0x00001000 and and the encrypted portion starts at 0x1000 within the app. This is why will now add these together to get where the encrypted portion starts within the app. 0x00001000 + 0x1000 = 0x2000. 0x200 is where we will want to begin to extract a binary dump.

4. Extract unencrypted data
Now that we know what portions of the app we want to extract we need to load the app on the phone so we can get it to decrypt. We can just run that app and attached to the pid to ensure its been decrypted. Once the app is unencrypted we can dump the portions we need to patch the binary. Before you begin fooling around with GDB on your phone uninstall the default one that comes with Cydia. I always just add the Radare repo and install GDB from there. At the time of writing this it was at version 1708. I like radare as a cydia source because it has other useful tools you will be using down the road.

Note: Some of you may get the “Illegal instruction: 4” when trying to run within GDB. This is due to old compiled binaries. You can patch the binary with the below command. You have to install sed and ldid(Link Identity Editor).

sed -i'' 's/\x00\x30\x93\xe4/\x00\x30\x93\xe5/g;s/\x00\x30\xd3\xe4/\x00\x30\xd3\xe5/g;' ios_binary
ldid -s ios_binary

(gdb) attach Free\ Chess.2545 
Attaching to process 2545.
Reading symbols for shared libraries . done
Reading symbols for shared libraries...................................................... done
0x3a468e30 in mach_msg_trap ()
(gdb) dump binary memory memorydump.bin 0x2000 (0x2000 + 192512)
(gdb) q 
The program is running.  Quit anyway (and detach it)? (y or n) y
Detaching from process 2545.

As you can see we just load GDB type the app you want to attach to and just tab and it will complete the correct PID. The example above is PID 2545. The line below is what you want to pay attention to.

(gdb) dump binary memory memorydump.bin 0x2000 (0x2000 + 192512)

Dumped memory from 0x2000 to 0x2000 + 192512.

5. Patch Binary
Now we will want to patch our binary. We can scp our recent memory dump down to our directory on our machine and patch the encrypted binary we already have. This can be done with the below command.  Seek is set to cryptoff and patched_chess is the name of the file I copied the original binary to.

Note: Always backup your binaries before any modifications. 

dd bs=1 seek=4096 conv=notrunc if=memorydump.bin of=patched_chess
192512+0 records in
192512+0 records out
192512 bytes transferred in 0.401887 secs (479020 bytes/sec)

You should now have a unencrypted file of the same size as the original. You can now name this new file with original binary name. You are all set to plug it into IDA and look under the hood. Once you are done reversing and making any hex editor changes you can scp the binary back to the phone. The one thing you want to do before is to disable load encryption.

6. Disable Load Encryption
Within the binary there is a simple flag that tell iOS to decrypt the app on load. Now that our binary is already decrypted we need to turn that off. As you see below cryptid is 1. We will want to change that to 0.

otool -arch all -Vl Free\ Chess | grep -A5 LC_ENCRYP
          cmd LC_ENCRYPTION_INFO
      cmdsize 20
    cryptoff  4096
    cryptsize 192512
    cryptid   1
Load command 10

I typically just eyeball it with a hex editor but a nice way to see this is with MachOView. In MachOView you can go under Load Commands > LC_ENCRYPTION_INFO to view the offset of CryptID.

machoview

Now we know the location of cryptid we can open the binary in a hex editor. I use Hex Fiend in this example. We know the offset already but I always just search for the first instance /System/Library/Frameworks and just above it you will see bytes 01. It typically stands out pretty easily. Now in the hex editor flip this to 00. As you see in the screenshot it is at the offset we found in MachOView and just above /System/Library/Frameworks. So you can pick your poison. Make a backup before you save the changes.

hexfiend

Now once you flipped the bit you can verify this be running the same command. As you can see cryptid is now 0.

otool -arch all -Vl Free\ Chess | grep -A5 LC_ENCRYP
          cmd LC_ENCRYPTION_INFO
      cmdsize 20
    cryptoff  4096
    cryptsize 192512
    cryptid   0
Load command 10

Now that you have made all the reversing changes you needed and flipped cryptid you can now upload this new shiny binary into the working directory on the phone. Make sure the app is not running and to run ldid.

ldid -s Free\ Chess

References:
http://www.sensepost.com/blog/6254.html
http://iphonesdkdev.blogspot.com
http://my.opera.com/iphonedev/blog/2008/08/11/how-to-crack-apple-apps
http://dvlabs.tippingpoint.com/blog/2009/03/06/reverse-engineering-iphone-appstore-binaries
http://www.mandalorian.com/2013/05/decrypting-ios-binaries/
http://lightbulbone.com/post/27887705317/reversing-ios-applications-part-1
http://www.pod2g.org/2012/02/working-gnu-debugger-on-ios-43.html

Tools:

  • otool (from  Xcode or cydia) –  object file displaying tool
  • ldid (from cydia) – Link Identity Editor
  • gdb (from cydia radar repo) – GNU Debugger for iOS build 1708
  • MachOView – visual Mach-O file browser
  • Hex Fiend – open source hex editor for Mac OS X