Documente Academic
Documente Profesional
Documente Cultură
2008
Primer on Reversing Jailbroken
iPhone Native Applications
Shub-Nigurrath
ARTeam
May 2008
PRIMER ON REVERSING JAILBROKEN IPHONE NATIVE APPLICATIONS
DISCLAIMER
All code included with this tutorial is free to use and modify; we only ask that you mention where you found it.
This tutorial is also free to distribute in its current unaltered form, with all the included supplements.
All the commercial programs used within this tutorial have been used only for the purpose of
demonstrating the theories and methods described. No distribution of patched applications has been done
under any media or host. The applications used were most of the times already been patched by other
fellows, and cracked versions were available since a lot of time. ARTeam or the authors of the papers
shouldn’t be considered responsible for damages to the companies holding rights on those programs. The
scope of this document as well as any other ARTeam tutorial is of sharing knowledge and teaching how to
patch applications, how to bypass protections and generally speaking how to improve the RCE art. We are
not releasing any cracked application.
VERIFICATION
ARTeam.esfv can be opened in the ARTeamESFVChecker to verify all files have been released by ARTeam and
are unaltered. The ARTeamESFVChecker can be obtained in the release section of the ARTeam site:
http://releases.accessroot.com
TABLE OF CONTENTS
Disclaimer ........................................................................................................................................................ 2
Verification ...................................................................................................................................................... 2
Forewords ....................................................................................................................................................... 5
2.3 Essential Notes on the reversing of objective-C: the role of objc_msgsend ........................................ 20
3.1 ScreenShots........................................................................................................................................ 29
5 CONCLUSIONS 58
5.2 History................................................................................................................................................ 60
FOREWORDS
With all these limitations the iPhone should have disappeared from
the market, instead it is alive and kicking, collecting records: it
conquered in a very short timeframe about a third of the overall smartphones market and it is responsible of
about ¾ of the overall online traffic of the mobile devices. The iPhone is not only an iPood with advanced
multimedia features, equipped with WiFi, but it has a real powerful system under the wood, a complete
operative system with a full web browser (Safari) and applications, built to go on the Web 2.0.
Once unlocked (using techniques I will not explain with much in details) a new world opens up: a lot of native
programs (not web) are awaiting your patches and customizations. It’s a completely different world for those
of you already accustomed to the Win32 environment, but also has some differences for those already
reversing in the Mac world. The OS is an OSX, build up from FreeBSD, but it isn't the MAC OSX and the
processor is an ARM, then RISC assembler not easy to handle at all (like for Symbian phones). The
programming technologies are anyway the same already used for MAC: COCOA/Darwin and underneath
objective-C.
At the moment all the existing native applications are built using the unofficial SDK (but the official SDK is
announced soon) and are most of the times, but not always, completely free. Users must before jailbreak their
devices and it’s not a thing anyone could/would do. Most of the applications are just experiments meanwhile
the real SDK is not here, just few are donation-ware and even less are shareware.
I will assume you have already got the basics of the ARM disassembler and IDA things. If not I suggest to read
the “Primer on Reversing Symbian S60 Applications”[12] or the “Symbian Symphony For 4 Crackmes And A
Commercial Program”*13+ I already released, at least just about the details on the ARM platform and
assembler there explained.
All along the document I spread a lot of links to references and further readings, keep attention to them to
dive some aspects..
When I did for the first time the jailbreak of the iPhone it was a quite complex and risky procedure: you had to
1
downgrade the firmware to version 1.1 and then break it, using a failure in the handing of TIFF images of that
firmware. Starting from this you had to upgrade backward (or forward) to the latest firmware. The procedure
was, theoretically simple: downgrade to firmware 1.1, exploit of a TIFF handling bug, which gave permission to
execute arbitrary code as native. The hole was large enough to be finally able to install any application.
Upgrade where done on an already compromised system, which was then able then to re-create the backdoor
on newest firmware too.
On the net you can find several guides which explain completely what you have to do.
As described in [1] the original procedure used for the first time to unlock the firmware was possible with
some collaboration of an Apple employee (rumours). Anyway what is sure is that the distribution file of the
firmware iPhone1,1_1.0.2_1C28 was incredibly easy to decrypt.
You should know that the firmware is downloaded from the apple site as files with the ipsw extension. These
2
files are indeed zip files which contains among other things an encrypted MAC disk image, in the dmg format .
This format was well encrypted using AES, and theoretically very hard to decrypt. What is the strange is that
the encryption key was clearly buried inside the dmg file as clear string. It was possible to run a bat file like the
3
following to find it :
which in other words finds a string made of literals and numbers long 72 chars then prints it.
Then this string was used to decrypt the file using vfdecrypt, using this line:
vfdecrypt.exe -i 694-5298-5.dmg -k
7d5962d0b582ec2557c2cade50de90f4353a1c1de07b74212513fef9cc71fb890574bfe5 -o
dmg_image_decrypted.dmg
The vfdecrypt sources are available on the net [2] and the early lines of the source code tell:
This is a tool that was developed for Macs, not for iPhones! This makes me wondering that Apple was indeed
4
willing to have jailbroken iPhones
Anyway, using this procedure is even possible to decrypt the whole dmg file on a Windows PC (you must install
5
some dlls from the cgywin distribution and find some other things but it’s not difficult) .
1
http://blog.metasploit.com/2007/10/cracking-iphone-part-1.html
2
The ONLY tool I found able to read iPhone dmg files is TransMac 8.x (www.asy.com), all the others, including
PowerISO, fails.
3
To be precise, these files contain the string "encrcdsa" at the beginning then are Mac Encrypted Sparsedisk
4
http://iphonejtag.blogspot.com/2008/01/iphone-secret-key.html
What you get once you are able to look inside the dmg files is the complete control of the system files,
applications and so on.
As I told I will not stop longer on this issue, even because this tutorial concentrates on reversing the iPhone
6
apps build using the unofficial SDK (for the moment the official SDK is only in beta).
Remember, unlocking is totally up to your responsibility, be sure to know what you are doing. I will ever never
provide help on this. Look in sites such this: http://www.iphonehacks.com
What follows is my personal very concise guide on unlocking an iPod Touch mainly (I do not have an iPhone).
The unlocking processes for iPod Touch or iPhone are a little different. First we must distinguish among the
different operations you can do.
downgrading: the unlocking process uses some bugs of specific versions of the firmware. This bug is
used to inject code into the system that then runs natively. This first hole is then used as a trampoline
attack for the following patches. The result is that from a modded initial version you can return to the
original latest firmware. You must then downgrade your device which comes pre-equipped with the
latest firmware.
jailbreaking: unlock the operative system so as you can install third party native applications. This
implies that you will get full control over the system, becoming able to do the following steps. This is
the basic operation for any other optimization you may want.
activating: this operation activates back the jailbroken phone but doesn't patch the system in order to
operate with different carriers. Apple inserted some blocks which prevent unlocked phones from
doing some operations, activation skip these blocks.
unlocking: given that your device has been jailbroken you can then modify the system either native or
installed applications. If you patch the native applications responsible of locking the device to a
specific carrier you are performing the “unlock” of your device.
5
You can find all the required steps and tools at [1, 2]
6
Unofficial SDK, http://www.iphoneatlas.com/2007/09/19/the-unofficial-iphone-sdk-guide-to-writing-native-
iphone-applications/
There are different tools you can use to unlock the system. As I told before I only did the jailbreaking
procedure on an iPod Touch. These tools anyway are almost completely automated and it's just a matter of
which button you will press.
ZiPhone (http://www.ziphone.org/) and all its alternative interfaces (like the excellent eZiPhoneTools
http://eziphone.blogspot.com/). This one is now open-source so you can also write your own
interface and optimize it as you like. This is the ancestor of any other tool you may find around. All the
other tools are just repackaging or refinements of this one.
ZiPhone is a conglomerate of others work. It copies a new fstab for write access to system, runs
iPatcher to patch lockdown, copies installer, and runs my gunlock to unlock. It is a good way to restore
from most problems, and true jailbreak 1.1.3 My program is just patched to change the default
IMEI(0049) to the user entered IMEI; although I would strongly advise against changing your IMEI. The
7
exploit he uses runs an unsigned ramdisk with all these programs.
You can find other news in [14] and http://iphonejtag.blogspot.com/ and even here for all the problems you
may have: http://www.hackthatifone.com/forum/index.php?action=forum
Note
•You can find almost all the needed tools you may
need at: ftp://ftp.iphonefix.de/ or http://iphone-
dev.org/ [17,18]
http://ipluspwns.blogspot.com/
the result of the operation (on PC side) is something like the following:
C:\iPlus2.0>iplus -u
----------------------------------------------------------------------------
iPlus 2.0a by Aviegas starting...
----------------------------------------------------------------------------
Downloading payload to iPhone
----------------------------------------------------------------------------
Will now jailbreak, activate and optionally unlock the iPhone
The iPhone will reboot twice. One to jailbreak and another for all other operations
7
http://iphonejtag.blogspot.com/2008/02/11246unlock-good-enough-for-prize.html
Loading iplus.dat.
Searching for iPhone...
Entering recovery mode.
Working...
Please wait 2'30".
Done!
----------------------------------------------------------------------------
Pass 1: Jailbreak and setup for next pass completed.
----------------------------------------------------------------------------
Pass 2: unlock/downgrade, activatioan and package installation starting...
----------------------------------------------------------------------------
iPlus 2.0a Processing completed. Enjoy your iPhone!
The log file "iplus.log" was retrieved from the iPhone.
----------------------------------------------------------------------------
The program also generates a log file with the list of packages that are automatically installed on the device.
These packages are the most important ones, those which you usually would install anyway. (term-vt100,
openssh, installer.app, etc):
You then need to exit from this mode. Manually or through a command sent by the PC (via USB cable)
8
The DFU mode is a debug mode used by the device when it is upgrading the system, see
http://limitededitioniphone.com/how-to-put-the-iphone-into-dfu-mode/
This tool has some interesting functionalities really handy. Some of them are those to enter and exit from DFU
and recovery modes like "exit recovery mode - normal boot":
Sometimes I got problems with iPlus, the unlocked device is somehow buggy, and one example which occurs
was that the device hangs whenever I try to use the virtual keyboard. Sometimes (depending on the device)
instead everything goes fine. Dunno why, but what is sure is that ZiPhone never gave such problems. The only
drawback is that this program doesn't automatically install any program on the unlocked device. You will have
to do it manually, despite this, on iPod at least, the whole jailbreaking process is faster.
•Sometimes the unlocking process hangs in loop and the patched bootloader
Note
As already said if you have an iPod Touch you must only use the jailbreak not the “unlock” (the modifications
done by the “unlock” applies to the iPod touch too, because that part of the system is still present, but are
useless because the telephony hardware is not).
After you finish the operation you will have to manually install the most useful packages:
system/bsd subsystem - useful to install a subset of the BSD (freeBSD system) commands.
system/openSSH - this installs the OpenSSH drivers used to connect to the device through ftps (ftp
secure)
utilities\respring - useful to restart the springboard program (the main view, similar to windows
desktop). It refresh the list of applications only at the startup then if you install a new application,
springboard must be restarted in order to see it.
Reassuming:
1. It is impossible to permanently transform your iPod Touch into a brick (this isn't always true with iPhones),
the iPod can always be restored to its original status and you can do again the operation.
2. It is always possible to recover from a not terminated jailbreak process or a loop. You can enter in DFU
mode and:
- press the off and home buttons (the only two buttons present!) together till the device goes off
- connect the device to the USB port holding the home button till a connecting sync cable
animated icon appears.
- when iTunes warns that it detected a DFU mode device you can leave all the buttons
- then press on the "Restore" button of iTunes, pressing the shift key. This opens an openfile
dialogbox from where you can select the ipsw file you already downloaded before (for example
for the version 1.1.4 google some location of this file "iPod1,1_1.1.4_4A102_Restore.ipsw" and
9
download it to the PC disk)
- when process completes you can start again trying to jailbreak the device.
9
You can find all the firmware here: http://www.hackthatifone.com/forum/index.php?topic=60.0
Suppose that you were able to unlock the iPhone or the iPod Touch
devices. What you have in hands is an OSX system, which is a customized
version of the already known MAC OSX. Indeed at Apple they call OSX the
general system which becomes iPhone OS if customized for iPhones or
MAX OSX if customized for MACs. Anyway it’s basically a FreebBSD
system with all the typical MAC programming interfaces: COCOA and most
of all everything has been built using Objective-C [5]. Being basically an
unix system, all the processes of the iPhone or iPod are running as root,
with full rights.
Reassuming
Figure 3 – file system of firmware The file system resembles one of an Unix system (actually FreeBSD)
1.1.x
Figure 3 shows that all the applications are stored under the Applications folder (system applications too, like
safari for example).
The “Usr” folder holds the home directory of the root user, the only user existing on these devices. The
complete structure is anyway quite complex and you can browse it just to understand what you might find
inside.
At the moment I will work on the PC, using a decrypted image of the firmware, simulating what we will find on
the unlocked device. This is handy because allows us to concentrate on the problem of reversing some
applications. We will learn how to install, copy to PC, patch the applications then move to the device.
The Calculator.app is inside the folder Applications\Calculator.app. This folder contains these files:
English.lproj\
Calculator
CalculatorBackground.png
Default.png
icon.png
Info.plist
LCDBackground.png
PkgInfo
ring.png
The real application is Calculator, without extensions in the name. The png files are actually customized png
10
files and you cannot open them directly on the PC . The Info.plist is the Apple equivalent of the jad files of
mobile J2ME java installers.
The Calculator file is an executable stored in the MATCH-O format, the executable file format used on Macs.
Different syntax but same ancestor of the PE file format (both shares their origins from the Unix executable file
formats). Fortunately IDA 5.2 can read them (see Figure 4)! Just take care to switch the Processor type to ARM.
Leave this application to IDA and wait, when it is ready you can see what it found inside.
10
As you will see later the iPod PNG format is not really the PNG format, it requires a little program on PCs to
see them (see section 3.2).
The Mach-O file format is well documented on the net [6], it is organized in sections like PE files (see Figure 5).
A Mach-O file contains three major regions (as shown in Figure 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.
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:
The names of shared libraries that contain definitions for the main executable’s imported
symbols
Following the load commands, all Mach-O files contain the data of one or more segments. Each
segment contains zero or more sections. The term ‘segment’ in Mach-O files is roughly equivalent to
the term ‘section’ in the Windows Portable Executable format. 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.
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 segments have standard names: __PAGEZERO, __TEXT, __DATA, __OBJC, __IMPORT, __LINKEDIT
The static linker creates a __PAGEZERO segment as the first segment of an executable file. This
segment is located at virtual memory location 0 and has no protection rights assigned, the
combination of which causes accesses to NULL, a common C programming error, to immediately
crash. The __PAGEZERO segment is the size of one full VM page for the current architecture (for Intel-
based and PowerPC-based Macintosh computers, this is 4096 bytes or 0x1000 in hexadecimal).
Because there is no data in the __PAGEZERO segment, it occupies no space in the file (the file size in
the segment command is 0).
The __TEXT segment contains executable code and other read-only data. To allow the kernel to map
it directly from the executable into sharable memory, the static linker sets this segment’s virtual
memory permissions to disallow writing. When the segment is mapped into memory, it can be shared
among all processes interested in its contents. (This is primarily used with frameworks, bundles, and
shared libraries, but it is possible to run multiple copies of the same executable in Mac OS X, and this
applies in that case as well.) The read-only attribute also means that the pages that make up the
__TEXT segment never need to be written back to disk. When the kernel needs to free up physical
memory, it can simply discard one or more __TEXT pages and re-read them from disk when they are
next needed.
The __DATA segment contains writable data. The static linker sets the virtual memory permissions of
this segment to allow both reading and writing. Because it is writable, the __DATA segment of a
framework or other shared library is logically copied for each process linking with the library. When
memory pages such as those making up the __DATA segment are readable and writable, the kernel
marks them copy-on-write; therefore when a process writes to one of these pages, that process
receives its own private copy of the page.
The __OBJC segment contains data used by the Objective-C language runtime support library.
The __IMPORT segment contains symbol stubs and non-lazy pointers to symbols not defined in the
executable. This segment is generated only for executables targeted for the IA-32 architecture.
The __LINKEDIT segment contains raw data used by the dynamic linker, such as symbol, string, and
relocation table entries.
Each segment can have different sections which usually have standard names too [6]:
the compiler to use immediate load instructions rather than adding to this
section.
__TEXT,__literal8 8-byte literal values. The compiler places double-precision floating point
constants in this section. The static linker coalesces these values, removing
duplicates, when building the final product. With some architectures, it’s more
efficient for the compiler to use immediate load instructions rather than adding
to this section.
•Mac OS X uses Mach-O and not ELF simply because NEXTSTEP used
Mach-O. Apple had a large enough TODO list that moving to ELF for the
sake of mainstream conformity was not justified. Like NEXTSTEP, Mac OS
X supports "fat" binaries where an executable image contains binaries
for more than one platform (such as PowerPC and x86). Apple's port of
GNU CC allow for fat binaries to be produced (provided assemblers and
libraries are available for each specified architecture).
IDA can actually show the list of recognized sections into the application we are disassembling (calculator). You
can find several of the section names we introduced in previous tables.
Double click on the __cfstring section and you land where the strings are stored. Just for example follow the
first one:
Find its unique x-ref and you land here (the strings are referenced by pointers tables):
We meet here for the first time the function _objc_msgSend. This function is the real base of
any objective-C program.
Like for the MACOSX programming model, also iPhone (which has an OSX system) uses objective-C as its main
programming language for the native applications. All the native applications on the iPhones or iPod Touch are
written using objective-C. It’s then useful to have a little understanding of what it is. I will only report the
things you mostly need to know to reverse the programs at a Primer level (for further reading, see [7,8,9]).
Objective-C, often referred to as ObjC and sometimes as Objective C or Obj-C, is a reflective, object-oriented
programming language which adds Smalltalk-style messaging to C. Today it is used primarily on Mac OS X and
OS X in general [8].
Objective-C is a very "thin" layer on top of C. Objective-C is a strict superset of C. That is, it is possible to
compile any C program with an Objective-C compiler. Objective-C derives its syntax from both C and Smalltalk.
Most of the syntax (including pre-processing, expressions, function declarations, and function calls) is inherited
from C, while the syntax for object-oriented features was created to enable Smalltalk-style message passing.
The added syntax is for built-in support of object-oriented programming. The Objective-C model of object-
oriented programming is based on sending messages to objects, similar to the model of Smalltalk. This is unlike
the Simula programming model, which is used by C++ among other programming languages. This distinction is
semantically important. The basic difference is that in Objective-C, one does not call a method; one sends a
message.
An object called obj whose class has a method doSomething implemented is said to respond to the message
doSomething. If we wish to send a doSomething message to obj, we write
[obj doSomething];
obj.doSomething();
This mechanism allows messages to be sent to an object even if the object is not able to respond to them. This
differs from statically typed languages such as C++ and Java in which all method calls to objects must be
predefined (see also dynamic typing concepts).
Objective-C requires the interface and implementation of a class to be in separately declared code blocks. By
convention, the interface is put in a header file and the implementation in a code file; the header files, suffixed
.h, are similar to C header files.
Objective-C is then an object Oriented language, like C++, having them functions and classes with methods.
Methods are written in a different way from C-style functions. For example, a function in both C and Objective-
C follows this general form:
int do_something(int i) {
return square_root(i);
with int do_something(int) as the prototype. When this is implemented as a method, this becomes:
- (int) do_something:(int) i {
Objective-C foresees the sending of a message to objects. These might not respond to it: an object has a
number of things it can do with the message, forward, ignore or handle. One of these things could be to
forward the message on to an object which can respond to it. Forwarding can be used to implement certain
design patterns, such as the Observer pattern or the Proxy pattern very simply.
As you understood the structure of the objective-C programs, once complied is based on a continuous flow of
messages coming and going among the different classes and methods. This flow is handled by an unique
function, extremely important: _objC_msgSend(). As we said above the objC layer is a very thin layer on top
of C and then this is a normal C function.
[foo doIt];
objc_msgSend(foo, @selector(doIt));
The compiler generates calls to the messaging function. You (as programmer) should never call it directly in the
code you write.
What is important here is that the selectors are just the names of the methods. Method
selectors are used to represent the name of a method at runtime. A method selector is a C
11
string that has been registered (or “mapped“) with the Objective-C runtime (in the _cstring or
_cfstring sections). Selectors generated by the compiler are automatically mapped by the
runtime when the class is loaded. You can anyway add new selectors at runtime and retrieve existing selectors
using the function sel_registerName (another interesting point).
Yes, you correctly understood: a string representing the name of the method is given as second argument of
the above call, the first if the address of the object.
objc_msgSend(foo, “doIt”);
11
This somehow the same thing happening with Delphi programs, the handler of events (message handlers)
can be recognized through strings or labels.
Note that the objc_msgSend is documented only in the Objective-C 2.0 specifications [10] (but [11] too):
objc_msgSend
Sends a message with a simple return value to an instance of a class.
id objc_msgSend(id theReceiver, SEL theSelector, ...)
int objc_msgSend(DWORD theReceiver, DWORD theSelector, ...) using C
Parameters
theReceiver, A pointer that points to the instance of the class that is to receive the message.
theSelector, The selector of the method that handles the message.
... A variable argument list containing the arguments to the method.
Return Value
The return value of the method.
Discussion
When it encounters a method call, the compiler generates a call to one of the functions objc_msgSend,
objc_msgSend_stret, objc_msgSendSuper, or objc_msgSendSuper_stret. Messages sent to an object’s
superclass (using the super keyword) are sent using objc_msgSendSuper; other messages are sent
using objc_msgSend. Methods that have data structures as return values are sent using
objc_msgSendSuper_stret and objc_msgSend_stret.
Reassuming:
1. Since most (not all) message sends go through this single entry point, tracing and logging can be
implemented right here, in one central location.
2. The programmer usually don’t directly use the functions like objc_msgSend, them are placed by the
compiler.
3. The names of the methods are directly translated from the source code to the compiled code and you
can directly see them from IDA. Programmers will need to do some obfuscation of the sources before
compiling
4. Programmers can choose to dynamically add selectors but the usage of the function
sel_registerName can be used to detect these tentatives.
5. The unique exception to the objC_msgSend rule is the variant functions which receive a variable list
of parameters (like printf in C). In these cases the function used is objc_msgSendv.
What practically you can do is to start with the reference to objective-C here:
http://developer.apple.com/documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html
and the objc runtime header files in /usr/include/objc. You can also download the runtime source if you want
to dig deeper, I did it for curiosity but in 99.99% of the cases you don't need more than the header files.
After you read the above, it becomes easy to understand disassembled code because the "selector" (passed to
every objc_mgSend()) is just a pointer to the string method name.
12
Some more links (mostly for Intel-based Objective-C applications):
class-dump http://www.codethecode.com/projects/class-dump/
it is a great utility that will dump objective-c headers from the compiled app. This makes it great for
figuring out the structure of programs. For a decent overview check this out.
http://www.phrack.com/issues.html?issue=63&id=16&mode=txt
It applies just as well to x86. GDB might not be as nice as Olly but it has knowledge of objective-c so
once you dump the headers you can set breakpoints based on method names.
HT Editor (http://hte.sf.net/). A really awesome binary viewer and editor forMach-O files. It allows to
modify also the file headers.
otool and gdb. Shipped with MacOS X. Once you've learned how to use them, they are great!
Unfortunately as I said iPhone runs on ARM then most of these tools cannot be used (except ht editor), we’ll
have to manually find the way to go.
You should know (especially if you already had a look at [12] and [13] or if you already know ARM assembler)
that the calling convention of the ARM uses the registers as arguments:
12
Thanks to mkfeldman and scknight on woodmann for head-up with these links.
R0=_objc_msgSend(R0,R1,R2,R5,..);
R0 = [R5 isEqualToString:cfstr_Testname1];
if(R0==-1) …
The code is then is just a string comparison between the object hold in R5 (a string object, the object “self”)
and the string “testname1” (you can also find some other examples at [14])
Being the Calculator one of the simpler applications of the iPhone we cannot say much more. Anyway we
clearly understood how important strings for the objective-C programs are. The strings are not only referenced
directly like I shown before, but are also contained into CFString objects. Simply, if the string is a constant or a
variable created by the programmer into the source code, the compiler insert it into a CFString object; if the
strings are inserted by the compiler during the compilation process (e.g. the parameters of the objC_msgSend)
are instead referenced as normal strings, like it happens with C.
13
The objects of type CFString (CoreFoundation Strings) are objects containing the string plus the length .
Looking into the program we can easily find that the object stores the file offset of the C string:
13
You can look here:
http://www.krugle.org/kse/files/svn/svn.sourceforge.net/guliverkli/guliverkli/include/qt/CFString.h
The byte sequence that is characteristic of this object is: 4C 7A 00 00 18 (keep it in mind how we found it).
Following this object we find that it is referenced at the address 00005684, that I directly converted to a C-like
code:
[UImage imageNamed:background]
Reassuming:
1. the strings explicitly used by the programmer are stored into CFString objects (like nags, warnings and
so on).
2. the strings added by the compiler are normal C strings not stored into any object (like the strings
passed to objc_msgsend as argument)
3. the CFString objects store the length of the string and the file offset pointer to the string: if the string
is at the offset AABB and is long CC then the object is represented by the sequence BB AA 00 00 CC
4. all these objects are stored into a __cfstring section of the program (it is the standard behavior,
according to Table 1, Table 2, Table 3)
We already introduced that the selectors are actually strings, but the selectors are associated to message
handlers, which are in turn stored into the application into association arrays. An example is shown here:
Figure 7
The map of Figure 7 shows the association among strings and functions, which is what we are interested to
exploit. This structure is perfect for inline patching of applications, injecting code and changing the general
behaviour of a program (for example adding an extra handler before the real one, like rootkits are used to do).
For example we can see from Figure 7 that the selectors “_button0Press”, “_button1Press” and
“_button2Press”are associated to the routines sub_5174, sub_5100 and sub_5128. Each of these functions in
turn just sends out the event “_digitPress” with a different parameter each (Figure 8).
Further looking into the selector-handler map you can find that the “_digitPress:” selector is associated to the
handler sub_4CF0. A good exercise is to completely understand how the Calculator application works and
rebuild the messages flow...
Reassuming:
2. The associations are stored into a selector-handler array which is fundamental to find the events
handlers
3. It is possible to inject code into these arrays to alter the messages flow inserting extra handler, for
example for patching the application or to do some sort of inline patch. It is clearly discussed here, for
the big Mac: http://www.felinemenace.org/~nemo/slides/mach-o_infection.ppt
4. This particular table is used for a well known infection method called “Method Swizzling”. Indeed it’s
an objective-C feature, but can be abused:
The Objective-C runtime lets you modify the mappings from a selector (method name) to an
implementation (the method code itself). This allows you to "patch" methods in code you don't have
the source to (AppKit, FoundationKit, etc). Unlike creating a category method with the same name as
the original method (effectively replacing the original method), MethodSwizzling lets your
replacement method make use of the original method, almost like subclassing.
Now it is time to unlock the iPhone or the iPod Touch (I did all with an iPod Touch) for real. With the iPod
Touch it is simpler because you only have to unlock the operative system and not to jailbreak the mobile
connectivity carrier in order to support your, but the process is not any different. My iPod Touch was updated
to firmware 1.1.4 (at time of writing is the latest). The process as I said consists of some different steps:
2. Use one of the known exploits (ram disk, tiff pictures and so) to inject some code at the system’s
level. Usually the code rewrite the boot loader of the system extending it so as it will allow a
“customized” upgrading process
3. Upgrade the system from the “compromised” one, one release after the other, up to the latest one
(1.1.4)
4. Jailbreak the system removing the lock to a single telecom provider. It’s just a system patch you can
do because you got control over the system, you will see that once you unlock the OS the control you
get is total and complete.
Fortunately these steps have been automated by some famous tools like
ZiPhone (which is opensource too) or iPlus 2.0b. This last works only for
firmware 1.1.4 but with a single button press does all the above steps and
gets you a completely unlocked and working iPhone or iPod Touch (all
you need is to run “iPlus –u” form a Dos window). It will downgrade the
bootloader, unlock, jailbreak and activate the iPhone. And even better, it
will also install the most important and common packages as well as
several fixes, with a custom payload for installing other packages.
14
Bootloader downgrading uses BL 3.9FakeBlank, so it is fully reversible .
I will not go further in details into this process because it’s not easy to
explain all the steps as I would, anyway you can find a lot of places where
to find explanations. Consider it as an excellent example of applied
reversing, well built software and a really working community.
What you will have then is a system where you can install native applications, some already there:
Latest Installer: the program used to install programs from the web, through a standard web format. This
is a native application used to ease the installation process of new applications (see Figure 9).
Latest Community Sources: latest online database of installable applications, you can extend it or just
browse.
Pre-Installed Packages:
14
You look here: http://www.hackint0sh.org/forum/showthread.php?t=34155 or
http://forum.gsmhosting.com/vbb/showthread.php?t=514129
o BSD Subsystem: basic BSD Linux subsystem, useful for porting of Unix-like applications
o OpenSSH
o Term VT-100
These will come handy, especially the installer and the OpenSSH.
The underlying system is mainly a FreeBSD system where all the process are running as root, all the programs
are built using objective-C, the common MACOSX programming interfaces like COCOA are still present. Porting
of existing software like OpenSSH was simplified by all these elements.
Figure 9 – How the installer (left) and the community source (right) looks like.
3.1 SCREENSHOTS
The first application you need to install on your own (or that I needed to install) is a screenshot application.
There are two available:
ScreeShoot is freeware and to install it you have to add this repository to the community sources
installs: iphone.robota.nl
The next step is to connect to the device. There are several options..
Through Secure FTP. You must install on the device the OpenSSH subsystem (but you should already
have it) and then do an ftps:// (ftp secure) connection the device. The device must be connected to
your same Wi-Fi of course and its IP must be visible from your PC. The login and password to be used
are always the same for all the Apple devices (“root/alpine” as username/password). You can use any
of the ftps clients for windows (for example is good WinSCP, http://winscp.net/eng/index.php), but
since I prefer using Total Commander I use the ftps plugin for this file manager:
On the PC
15
1. Install SFTP extension for Total Commander (available on the total commander’ site too)
2. create a profile to the IP of the device (on the WAN) using root/alpine as
username/password
15
Or directly here: http://developer.berlios.de/projects/sftp4tc/
3. Total Commander connects to the root home folder (as it happens with any unix system) and
you can go up to the root. When connecting for the first time it takes almost 45 seconds to
generate the keys pair.
4. Now you can fully manage file, rights and folders (also the file rights in the unix-way, with
separate rights for user, group and world).
On the device
3. Reboot it.
Through iTunes hacked USB protocol. This other connection method is easier and is fine for those not
having a Wi-Fi, but has also some limitations, because you cannot for example handle the file rights.
Anyway I again suggest using Total Commander, but with a different plugin which uses the same
16 17
protocol iTunes uses to talk with the device (it has been reversed ). The plugin is called T-PoT and is
a plug-in for Total Commander allowing browsing the Apple iPod Touch and iPhone contents via USB.
What it allows is mainly to browse the unlocked iPhone/iPod like any other network file system.
Among the other things it can fix the modified PNG iPod file format automatically so as you can see
the images on the PC, it has too a stand-alone Windows program to fix the iPod PNG images and
convert them to true PNG files you can see with any viewer/graphics editor.
18
Using iBrickr . This is a Windows tool that also offers the possibility to browse the device’s file
system. It comes handy to those of you not using Total Commander at all. Anyway what is nice with
this program is that it also allows installing programs on the device without having to use the installer,
directly launching the pxl files (look http://iphone.nullriver.com/beta/ section “How to make a
package - Draft documentation”, but you can consider it as an xml based installer). This will come
handy if you plan to release patched installer for some applications and want to do some tests before.
16
The iTunes API allows to access the iPod file system by the USB; unfortunately this API isn't publicly
documented yet. For the moment, some features are either not part of the API or were not discovered so far.
17
http://code.google.com/p/t-pot/
18
iBricks home page, http://cre.ations.net/creation/ibrickr
Note that I am a Windows user then life for us is not so easy when using iPhone or iPod, the reason is simple
the two systems on a MAC and on the iPhone/iPod are two sides of the same coin, two version of the OSX
system. As a matter of facts it’s much easier for a MAC to talk with these gadgets. For example the equivalent
19 20
of iBrickr is iFuntastic or Breezy which works fine.
Just to finish this section, as I told guides are all around you, like the one at [15].
19
iFuntastic, http://bitsplit-enterprises.com/iFuntastic/
20
Breezy home page, http://code.google.com/p/pxl/
21
AcceleroLog is the first application we will approach. It is relatively useless but at the same
time has some nags which we will remove, just to show how it can be done. We will not anyway
completely break it, just because it’s a free application.
What it does is to show the accelerometers graphs in real time and allows storing them into a file (see Figure
12).
After installation on the device (using installer or after addition of the robota community source link, see
above) you will find the following folder \Applications\AcceleroLog.app, inside the executable file is
“AcceleroLog”
21
AcceleroLog, http://www.robota.nl/products/iPhone%20AcceleroLog.html
Ok, it’s enough, time to go! Open with IDA the file, wait, search the strings in the strings view and find where
are referenced on the code:
Fine, we found the strings and we can think about the code that handles them, but... but there’s a problem: if
you press X to find the references to the two strings you will not find anything. Some strings are referenced
but the only important ones are not instead. What happens then? Why IDA is not able to find references to
these strings?
We are using now the conclusions we came analyzing the Calculator app, in section 2.6.
1. The string are explicitly inserted by the programmer and not by the compilation process
2. The strings are stored into a CFString object which IDA cannot identify
a. F0 7B 00 00 CF
b. 00 7D 00 00 13
c. 20 7D 00 00 1D
PRIMER ON REVERSING JAILBROKEN IPHONE NATIVE APPLICATIONS
Let see where these strings are stored: go into the hex-view of the program and use the search binary
function, then search for all the occurrences of these patterns: the first one is found here:
Figure 13
Figure 13 reports the finding. The logical conclusions are the followings:
1. the value is supposed to be a CFString object and the memory pattern corresponds
2. the object is stored into a __const section instead of a __cfstring like it should be
3. The executable uses a non standard method to store cfstrings, placing then into the wrong section
What we will do is to change the name of the section using a Hex-Editor to the name the IDA Math-O loader
(and the standard) wants: see Figure 14 and Figure 15.
Save the modified file as AcceleroLog_1 and open it with another istance of IDA. Go to the address we found
before (0x92B0) and you will magically see the following CFString objects:
The magic is now really complete, the CFString is correctly recognized and the references to the object too.
Figure 16 shows that the code is now as it should be!
Figure 16 reports just the portion of the function where the string is referenced, the whole function is named
as __2B__5B_AcceleroLogApp_20_singleton_5D_. The question is: how can IDA give a name to this
function?
The answer is simple: the message, handler, selectors, events associations are stored into an association map
into the executable. This table is clearly found using the cross-references of the strings. In this case it is stored
here:
The “askDonate” and the “alert:” selectors have handlers which are stored here:
Reassuming:
1. The applications built using the unofficial SDK stores the CFStrings into a __const section instead of
22
the standard __cfstring . This doesn’t imply anything for the device running the application, but the
IDA mach-o loader is then not able to correctly find the CFString objects, the reversing is not easy
then.
2. The association selectors-message-handler is stored into some maps which can be found into the
program.
3. If we change the __const section name to the standard __cfstring using an hex-editor IDA will be able
to correctly find all the things we need (see Figure 17)
22
All the applications I saw have this characteristic
The first half of the code shown in Figure 16 can be decompiled manually or using Desquirr (I explained it in
[12]). The result is the following:
ASM code:
__text:000044A8 LDR R0, [R7,#-0x1C] ; ///////////// start here
__text:000044AC STR R0, [R7,#-0x114]
__text:000044B0 LDR R3, =loc_6CA0
__text:000044B4 LDR R1, [PC,R3] ; "alert:"
__text:000044B8 LDR R3, =__2D__5B_AcceleroLogApp_20_initDefaults_5D_
__text:000044BC ADD R2, PC, R3 ; "WE TRUST YOU DONATE!
__text:000044BC ; The green, red and blue graphs represent
the accelerometer's XYZ.
__text:000044BC ; Move your iPhone to see the action.
__text:000044BC ; Use Settings to change the sample rate.
__text:000044BC ; Collected data contains timing
information."
__text:000044C0 BL _objc_msgSend
Desquirr result:
The “alert:” method receives also a function as parameter. This becomes evident if you try to do this
experiment (I did it): if you null this call the program won’t anymore draw the graphs. The function
__2D__5B_AcceleroLogApp_20_initDefaults_5D init the program graphical routine.
We will patch it then just to have a different message, skipping the “WE TRUST” part.
I want to skip the first row, then the new beginning is at offset 7C05. The only thing to do is then to adjust the
offset in the CFString object:
It is simple. Fortunately as we seen the parameter of the call functions in the ARM architecture are not stack
based, but rather registry based. This means that to skip a call it enough to skip the real call to the function
without much worries of the parameters. The program will not hang.
•Do not trust Desquirr results too much when working with
objectiveC applications. The plugin is not able to correctly
resolve the strings references, and the compiled code is
somehow confusing.
I previously mentioned about the first nag at __text:000044C0 which is used to display the remainder nag
dialog, but also to call the init function which inits the drawing system.
If you elaborate the first half of code shown in Figure 16 using Desquirr, you will get this code:
The second argument is the real problem patching this nag call, because if you NOP the call to objc_msgsend
the function used as arg2 is not called then the program won’t work correctly.
What I will do is then to switch the call to objc_msgSend() with a call to the function
__2D__5B_AcceleroLogApp_20_initDefaults_5D_.
The ARM assembler doesn’t have a real CALL among its instructions, rather only branches of different flavors
(conditions). You can then use the instruction BL (Branch Link) that is a branch without conditions (always
done), it can be used to emulate a call to a function (remember all the parameters are on registry, not on
stack).
BL __2D__5B_AcceleroLogApp_20_initDefaults_5D_
The problem is now, how to calculate the destination address of the branch, we do not have any assembler
like OllyDbg to use and then we must do everything manually, without any help. Interesting, isn’t?
Reading the specification manual we can draw this simple formula, which you can use onward for calculation
of the destination address of a jump or a call.
InstrAfterBRANCHaddr = is the address of the instruction just after the instruction BL we are coding
(actually being 4 bytes the constant dimension of any ARM assembler bytecode, it is equal to the
address at which we are assembling + 4: BL_address + 4)
Given that all the instructions of any ARM processors are expressed using 4 bytes, you have this resulting
formula:
-1 is present in the formula because the dimension of the BL opcode without the destination address is 1 byte,
and must not be considered in the jump address value.
Returning to the example of the application we are considering, applying the rule we have:
InstrAfterBRANCHaddr = 44BC
The value 0249 is the value of the jump opcode, but must be converted using LSB and used as argument of the
BL instruction (opcode of BL is EB):
__text:000044B8 49 02 00 EB BL
__2D__5B_AcceleroLogApp_20_initDefaults_5D_
The almost final patch is then the following one (with opcodes too):
This, with some other refinements, adjusts the problem of the first nag and of the initialization done by that
call.
Reassuming:
Using branches to skip portions of code is always a good think, use the above formula to calculate the
opcodes of these jumps
Given that objc_msgsend calls doesn’t involve parameters on stack (all are given through registry), a
very fast method to skip a call is to find the corresponding selector (see about the selectors-handlers
array) and comment the call to objc_msgsend. This avoid calling the handler and do not corrupt any
stack or the program status.
with different conditions. The branch always done (like calls) is BL,
which has no conditions set.
•The opcode of BL is EB (can be calculated using ARM specifications and I
already explained it in [13])
•The destination address of the BL is relative and can be calculated using
a simple formula.
•You generally speaking must pay attention to arguments of
objc_msgsend
•Desquirr helps speeding up things at the beginning. It gives a fast
decompilation which helps you out with ARM assembler.
•Fast patching can be done just NOPping out the call to objc_msgsend
wich is using the selector associated to the function you want to skip.
This second application is a video recording suite which is quite useful; it’s a real retail application with a
registration schema and some limitations for unregistered users. Have no protection, no obfuscations and it’s
ideal then for steps two of this document.
Limitation: recording of only 5 seconds, after which asks for registration and stops recording.
Notes:
This application changes frequently, so I will only stick to the version 1.1b, with some notes on version
1.2b.
The saved video files can be taken from this folder: \private\var\mobile\Media\PBFVideo\
It's, like all the iPhone native programs an objective C program. You can easily disassemble it using
IDA 5.2, selecting ARM processor.
To correctly resolve the references to the cfstring objects IDA requires the change of the sections
name from “__const” to “__cfstring”, like discussed in Section 4.1
Now the program has been updated then what I am reporting here doesn’t “exactly” apply anymore...
1. Change __const to __cfstring like done for all the other applications.
2. Search for string "You have entered an incorrect license key." you land at function
___LicenseTextView_webView_shouldInsertText_replacingDOMRange_givenAction__:
Which is:
The solution should be to change the branch to loc_32B4 into a NOP, but it can be easily understood that the
serial check is just a test against a fixed string. The only serial accepted is "PBF07-0110-8369-6582" which is an
old blacklisted serial (note that there are some checks above you should remove too).
This patch removes the check forcing the registration dialog to accept any serial you enter. Unfortunately
when you go testing the so patched application on the device you’ll realize that there is also a start-up check
you should skip too. To complete the patch do this:
This also skips the initial dialog and overrides the limit, no real need to enter a fake serial number anymore.
The power of selectors come evident if you look at the following snapshot: can you realize how I found these
two branches? The first one (0000721C) is just above the second one (000074E4) that is clearly associated to
the initial check of the licence.
By the way a better look at the application clearly shows that near loc_36F there is an interesting instruction
which moves into R2 the value #0 or#1 setting or not the recording limit:
Remember that the selectors-handlers array is really important when reversing these applications, like shown
in underneath picture all the relevant information are there, clearly visible.
Note
•"Functions" in Cocoa/Objective-C are a little different then C functions. Actually they
aren’t even called functions, they are called "Methods". Objective C calls these
functions, and then finally call the real methods. The calls to objc_msgSend and its
variants (99% of the total are just objc_msgsend) are really important.
•Obj-C ARM programs stored using Mach-O file format are generated by Apple’s
development tools. The result is an easy-to-analyze executable, in general it’s easy to
understand the code flow.
•To learn the basic conventions the best option is to start to reverse your own (simple)
programs, by comparing the source with the disassembly, you’ll soon understand how
things work.
•A good tutorial is at: http://george.zjlotto.com/index.php/2007/12/10/a-better-carrier-
logo-patch-for-springboard/
iSIM is a SIM card contacts copier. It can copy SIM contacts to iPhone and vice versa but with a limitation, you
cannot copy all contacts in one go. If you try it says “AVAILABLE IN REGISTERED VERSION ONLY” (Figure 19).
The interesting things of this program are a better registration routine (IMEI based), which also stores the
registration status somewhere in the system and an online check of the registration number. The patch is a
little more complex.
Figure 19 – iSIM welcome screen, the premium features are clearly shown.
4.3.1 FIND THE CORRECT INSTALLER URL THROUGH THE .PLIST FILE
The interesting thing is that we must also reverse a bit the installation procedure. As I said the .plist files are
installation xml files. The distribution site is available at this URL:
This page reports a tinyurl which you can use to directly download and install the application on the device.
http://tinyurl.com/3544mp
the r.plist file is an xml containing the final real URLs of all the programs distributed by makayama (see Section
23
2) and is one of the so called community sources which the Installer application handles .
http://www.makayama.net/iphone/iSIM.1.07.zip
As I said the serial number is checked online. The activation routine sends to a specific URL the data collected:
http://www.makayama.net/isim/%@.html
You can easily find where the online check is performed looking at the event “btnOrder:” and its handler:
23
The standard is specified by the NullRiver installer
The function opens a connection sending an “openURL:” command with the url
http://www.imatrix.lt/app/iSIM.aspx concatenated with the following parametric string: %@?DEVICE=%@
Looking better into the selectors-handlers map you can see that one of the events is the most interesting:
There is a problem: IDA considers this function as _data and not _code ( ):
This is a problem only if you want to use the graphic view of the function, otherwise not.
Note
•You can select the function and then press ‘P’ to define the
selected code as a function, but the result IDA gives is wrong,
the function graph is not correctly drawn. The correct
method is the following, which also give us the possibility to
learn a little about Mach-O sections.
If you look at it you can see that the problem is the “Class” of the section, which is DATA instead of CODE.
Editing the section from IDA doesn’t change things, because the Mach-O loader reads the section information
from the application headers only at the beginning, and then we need to change the executable using an Hex-
Editor.
We want to change the application header to transform this part of into a “CODE” Class.
First of all I must tell you how the sections are stored in the application file. Using the specification of [6] we
find the section “section” describing the structure of a section (contained into a segment):
struct section
{
char sectname[16]; //this
char segname[16]; //this
uint32_t addr; //this
uint32_t size; //this
uint32_t offset; //this
uint32_t align; //this
uint32_t reloff; //this
uint32_t nreloc; //this
uint32_t flags; //this
uint32_t reserved1; //this
uint32_t reserved2; //this
};
Then the structure looks like this in the hex-editor (I report also the first _text section which has the correct
Class):
5F5F 7465 7874 0000 0000 0000 0000 0000 5F5F 5445 5854 0000 0000 0000 0000 0000 2021 0000 90DC
0400 2011 0000 0400 0000 0000 0000 0000 0000 0000 0080 0000 0000 0000 0000
__text..........__TEXT.......... ! ..........................
The initial address of the section is 00002120 and the final address is 00002120+0004DC90=0004FDB0
5F5F 6373 7472 696E 6700 0000 0000 0000 5F5F 5445 5854 0000 0000 0000 0000 0000 B0FD 0400 3076
0000 B0ED 0400 0400 0000 0000 0000 0000 0000 0200 0000 0000 0000 0000 0000
__cfstring......__TEXT..............0v..................................
An integer divided into two parts. The least significant 8 bits contain the section type, while the most
significant 24 bits contain a set of flags that specify other attributes of the section. These types and flags
are primarily used by the static linker and file analysis tools, such as otool, to determine how to
modify or display the section.
We are then interested in modifying only the section type from DATA to CODE; then the least significant 8 bits.
Modify the least significant 8 bits using the LSB notation means to modify the leftmost 8 bits. Consider anyway
that the remaining 24 bits must be set accordingly. The second example above has a new flags field value:
Do this change using an hex-editor and write the result on a new file. Open it with IDA and you get the
following result:
Note: The same operation can also be done using the HT Editor (see Section Where to go deeper
Now we can continue with the analysis of the function function ___iSIMApplication_Activate__ which
is now a real function into a CODE segment.
Now you can select all the function from the end to the beginning and then press ‘P’ to transform this function
into a piece of code which is then transformed by IDA into a graph.
Now we have a really correct graph of the function which is responsible of activating the program. What we
have to do is just to force it to always return the goodboy message and skip the online activation. Quite simple
once you get there then I will only report the modifications without further comments.
The interesting is that you can even overwrite the patched application again with the original application, still
being registered.
Note: Having full control over the system means also you can change vital parts of the device such as for
example the IMEI (Figure 21).
We are rapidly learning all the required things to patch normal (not obfuscated) applications, to show you how
well we are preceding this is a fast application that resembles what we just done with the previous one. I will
skip a lot of descriptions assuming you should have understood them.
4.4.1 FIND THE CORRECT INSTALLER URL THROUGH THE .PLIST FILE
Like already done with iSIM we must reverse a bit the installation procedure. As I said the .plist files are
installation xml files. The distribution site is available at this URL:
This page reports a tinyurl which you can use to directly download and install the applications on the device.
If you change the __const section name with __cfstring all the references to the strings are correctly
resolved by IDA.
The patch is, exactly like already shown with iSIM (the deepest registration routine is the same for all the
targets of this company), the following one:
After registering with any serial number you will see that the application remains registered because it has
stored the registration details somewhere.
This is another really simple application, at this stage of the document. I did this section very concise to
24
underline how much you know now .
http://www.catamount.com/packages/iPhone/PocketMoney/PocketMoney_10.zip
3. Find the string "Your registration code was accepted. Thank you. ", and you land at the end at
function __2D__5B_RegistrationView_20_keyboardInputChanged_3A__5D_
4. This function is really simple, a classic two way good/bad boy function.
Clearly the R0 is set by the function I renamed as _ValidRegistration. If you go inside, the only
point where R0 is set to a value not 0 (actually R3 which is later moved to R0), is the following one:
loc_17154
MOV R3, #0 ; patch to MOV R3, #1
STR R3, [R7,#-0x24]
STR R3, [R7,#-0xC] ; the value [R7,#-0xC] is later moved to R0
24
The program has already been update then this patch doesn’t apply anymore. That’s fine, according to our
own rules..
This is the first roughly protected application I found. The events selector strings are obfuscated; selectors are
not recalling their scope and the only strings clearly visible are those inserted by the compilation process (not
stored into CFString objects then and not directly controlled by the programmer). The registration routine is on
the other hand also professional, being the registration number composed by fields. The limitation is 21 days
of free usage. The authors clearly used a source obfuscator which scrambled the selectors of the program; the
selectors-handlers array doesn’t give many hints.
As you can see most of the selectors are replaced with random strings. The problem is that this process cannot
be undone.
Luckily the obfuscation process cannot obfuscate also the strings returned to the users, and then we can find
the following interesting strings:
The problems is that no one of them is referenced (according to IDA) in the code! What a pity.
Finding the references to a string is not that easy, if you do it backward, starting from the address of the string,
because the references are relative, the PC is involved.
If you noticed the second instruction shows a reference to a string as a comment, instead of being part of the
instruction. This happens because in ARM the PC (program counter) is equal to the address of instruction plus
double the current instruction size (i.e. plus 8 in ARM mode and plus 4 in Thumb mode).
The address of the second LDR is 5184, the PC value becomes then 5184+8=518C.
If you go to the address 0x1D1A4, you will likely see there an offset to the string "objectForKey:", which is
displayed in the comment. IDA just tried to be helpful showing you the actual final value loaded into R1 rather
than the raw intermediate delta loaded into R2.
If IDA miss some reference it’s not that easy to find the place where the string is referenced.
We cannot directly approach the registration routine, because we are not able to find the references to the
goodboy/badboy strings. We can anyway find the routine indirectly, using the string “Register”, which is one of
the two buttons of the registration dialog. This string is references into the function sub_41CC which I
renamed with “EnterRegistrationNumDlg”.
This function is responsible of drawing the registration dialog and then, assuming that a registered program
25
won’t ask me to register, you must concentrate on the conditions driving this program to the function.
The EnterRegistrationNumDlg function just creates the two buttons (see Figure 23) and repeats 4 times the
same loop, in order to insert the four parts of any registration number.
We can do now is to follow the references of this selector to find where the registration dialog is invoked and
understand from these places which are the conditions why such a dialog is hit and modify the program.
To proceed you must understand that this even is issues when the application wants to create the registration
dialog. Then problem is that the application shouldn’t will to do such thing, then to patch the application you
must instead navigate through the calling functions, or better the functions invoking the selector we identified.
25
The piece of code of Figure 24 implements what described at http://www.tuaw.com/2007/08/16/iphone-
coding-working-with-the-navigation-bar/
Reassuming:
objective-C programs do very few direct calls (in the C way), most of the calls are indirectly called
through calls to objc_msgsend, using the selectors associated to the function that must be called.
Finding all the places where a specific function is called needs to find where the corresponding
selector strings are used (using the selectors-handlers array), this means to find each selector and all
its occurrences.
A very fast explorative patch is to NOP just the call to objc_msgsend without worrying of the
surrounding code.
We can then briefly list the sequence I did to patch this program:
1. One of the places where the selector EnterRegistrationMsg is referenced is the sub_5558.
2. If you look this sub it comes evident that it is the menu handler, this is associated to the selector
5. And is called by the function sub_94B4 which is responsible of drawing the bottom buttons (it’s clear
if you see it).
6. Into the function sub_94B4 we find the first patch I can tell you about:
This patch simply skips the chain of events we just identified in the above steps.
7. This patch extends the trial forever, but the nag still remains.
8. The nag is shown a little below, at this stage you should be able to go down with IDA and complete
the process.
This solves the program skipping all the annoying nags but the application is indeed still not registered. I will
leave finding of the registration routine for your own pleasure.
There are a lot of applications you can install over you iPhone or your iPod, at the moment the marked is quite
closed and experimental, because to run them you must unlock the system. It is then a thing that not anyone
could or would do. These applications most of the times are just experiments. As a matter of facts most of the
applications you can find are free, under GPL license. Just some are donation-ware and very few are
shareware. At the moment the most interesting thing you can reverse is the operative system itself!
This will surely change in the future when the official SDK will be released, then a real market will open.
Reasonably the reversing approach will not be different, because the operative system running underneath is
always the same. Reasonably it will also be possible to have at the same time applications developed using the
official and not official SDKs. Meanwhile, to train yourself, take a look to these repositories:
http://www.modmyifone.com/nativeapps/the-list/
http://mac.softpedia.com/get/iPhone-Applications/
http://modmyifone.com/forums/forumdisplay.php?f=29
http://www.imatrix.lt
http://george.zjlotto.com/index.php/2008/02/05/patch-mobilesafari-to-open-local-file/
http://george.zjlotto.com/
5 CONCLUSIONS
It should be evident that the system running under the hood of iPhone is quite complex and reveals to be an
interesting field for reversing.
The developers guide by Apple [19] reports this about the system of iPhones/iPoods:
If you are an existing Mac OS X developer, some aspects of iPhone OS should seem very familiar. Many
of the same underlying technologies used to build Mac OS X applications are also used to build iPhone
applications. iPhone OS leverages the maturity of the Mac OS X architecture and framework stack to
provide a reliable and already tested platform for developing applications. Even the newer
frameworks that do not have direct analogs in Mac OS X still borrow from the basic structure and
design methodologies that have already been proven on that platform.
Objective-C programs revealed to have a quite linear structure and to be generally speaking simpler than C
programs. This makes reversing of not protected programs (just as the compiler creates them) on the iPhone
simpler than, for example, Symbian. I also have shown how simple now is to jailbreak the system with the
mess of available tools.
Specifically, when you thing about the jailbreaking process, you must imagine it as a controlled exploitation,
controlled because the mean of this exploitation is to improve the system. But the same exploitation’s
techniques can be used by a malware.
As a matter of facts it comes evident how weak the security structure of the iPhone is:
relatively easy to jailbreak the system (for some cases it’s even possible through some web sites),
26
o the Pwnage Project recently found really interesting things
unprotected applications, most are relatively easy to be reversed, and definitely all the system
applications are the easiest.
possibility to modify all the parts of the system (i.e. even the browser) when you get into it (there are
no security zones or rings, to use a Windows terminology).
All these aspects have been used till now for good purposes: opening of a system to a community, developing
of interesting programs and generic improvements, but transforming all these efforts into malware production
27
is just here, behind the corner . I think there will not be much to wait before having some malware for
iPhones. Why iPhones? Simple: where there are moneys it is worth to create a malware.
26
http://www.modiphone.net/custom-firmware-images-jailbreak-and-more-through-itunes/ and
http://iphone-dev.org/
27
Just to give the idea: http://blog.metasploit.com/2007/10/cracking-iphone-part-1.html and
http://blog.washingtonpost.com/securityfix/2007/08/iphone_exploits_revealed.html
Conclusions 58
PRIMER ON REVERSING JAILBROKEN IPHONE NATIVE APPLICATIONS
When the official SDK or the new OS 2.0 will be out I think it will not be different (beta of OS 2.0 has already
28
leaked out and exploited ), probably it will be a much improved system but native applications will still be
29,30
objective-C programs like it happens now .
So I wish to join the credits most of reversers worldwide are giving to Apple for creating a so wonderful
hackable toy. Already now a lot of reversing teams started to actively look at the MAC world (more than ever),
because of different facts.
First, this system is now out of the ghetto for enthusiastic-only where it was before, now the system is starting
to be used for different usage than graphic and multimedia.
Second, the MAC experience and sophistication of the system against exploits and security is far less than the
Windows one (which is under attack since years), resulting in a much more vulnerable system. Third, people
started to realize, following to the iPhone experiences, how simple/nice it is to reverse the OSX system and
starts to look at the bigger brother (the same applies for me).
As usual feel free to come to our forum for discussions and sharing of ideas. I also wish to thanks who read the
betas of this tutorial seeking for errors (Gunther, Y0shu4, ntoskrnl). This doesn’t mean that this is now error
free, but surely there are less
5.1 REFERENCES
28
http://gizmodo.com/366751/iphone-20-unlocked-runs-all-apps
29
[HOWTO] Use Apple SDK to build 1.1.4 apps, http://hackint0sh.org/forum/showthread.php?t=37998
30
winChain is really handy. Read “HowToUse, A quick walkthrough on winChain 1.0”,
http://code.google.com/p/winchain/wiki/HowToUse
Conclusions 59
PRIMER ON REVERSING JAILBROKEN IPHONE NATIVE APPLICATIONS
[15] How To: Install Apps on Your iPhone for Total Dummies (Mac OS X and Windows Edition),
http://gizmodo.com/gadgets/update/how-to-install-apps-on-your-iphone-for-total-dummies-mac-os-
x-and-windows-edition-292561.php
[17] ftp://ftp.iphonefix.de
[18] http://iphone-dev.org/
[19] iPhone OS Programming Guide (you must register, for free, into the developers site to get this file)
http://developer.apple.com/iPhone/library/documentation/iPhone/Conceptual/iPhoneOSProgrammi
ngGuide/iPhoneOSProgrammingGuide.pdf
5.2 HISTORY
Version 1.0
- Initial release
Conclusions 60