Essay 0: Intro to OS X Reversing

Run it. Dasm it. Crack it. Patch it. Now Upgrade it.
by KellogS, May 2007.


Creative Commons License


This work is licensed under a
Creative Commons Attribution-Noncommercial-Share Alike 2.5 License.


0.0 Intro

As already mentioned in earlier posts, the target for this essay is Apple's Dashcode. A Dashboard's widgets creation program. Now in beta, it'll expire on the 15th of July (as Apple probably don't want to have to support it when the final come out). It's free for registered apple developer (also free). As a free tool, you may wonder that patching this program is kinda useless... and you will be right! Read on.
What you'll get by the end of this essay is NOT a link to a ready made crack, NOR a 699$ app. No, what you may get is some tools and techniques used to reverse softwares (and that's the priceless part). If you want some pirated softwares or cracks, you may better stop reading this and leave now. As an old master once said: "you don't need to crack its protection scheme at all: you'll find it on most Warez sites, complete and already regged, farewell, don't come back."

Still here ? Good.

This article is targeted at newbies, if you have even basic experience in software reversing on other platforms, you'll not learn that much:

The protection is simple, the patch obvious and the reverser rusted.

However, this article will show you (some) OS X particularities and the tools needed to accomplish your task. If you have no experience at all, every steps will be explained (but you may need to read some docs if you want to have a better understanding of some parts (mainly assembly). I may also say semi-truths when we don't need to go deeper on a subject to move on. So please forgive me for that and for my English, which is still not my mother tongue....


0.1 Tools of the trade

As the tools needed were mentioned in previous posts, you should already have them but let's do a recap:

* XCode, for the invaluable Docs and the GCC compiler (needed for patcher.c).
* otx, disassembler.
* 0xED, or any other hexadecimal editor.
* TextWrangler, or your favorite text editor (shoulds handle big files).
* NASM, The Netwide Assembler installable through Darwinports.

See previous posts, tools and links sections if you miss anything.


0.2 Mac Applications (or what the hell is a ".app" ?)

First, let me tell you something about "Mac" Applications that you may already know. Macintosh (and in our case OS X) apps rarely need to be installed, instead you just drop the "Application.app" in your Applications folder and that's it. Now, Have a closer look at a ".app" file... it's a folder! There is several ways to find this out. One is to go in a Terminal window and cd to something.app/. A second one is to right click (or command-click, whatever is your stuff) on a .app and select the "Show Package Contents" option, which open a new Finder window. So now that we've found out that a .app is just a folder, let's see what kind of files lies inside (taken from Dashcode.app):



Dashcode.app/
|__Contents/
| |__Frameworks/
| |__...
|__Info.plist
|__version.plist
|__MacOS/
| |__Dashcode
|__PkgInfo
|__Resources/
|__...
|__English.lproj/
|__MainMenu.nib
|__...




As you have guessed, I didn't list every freaking files, only the interesting ones. I'll be quick on the Framework folder, let's say for now that it contains libraries. .plist files are just XML files that may contain various informations (versions, application's default settings and such). You'll not need to alter them in most case. Then the Resources folder which contains a shit load of (drum roll),
resources; application's scripts, icons, images, etc. Inside the Resources folder is an English.lproj folder, which holds a lot of ".nib" files.

NIB stands for (let's take a guess): NeXT Interface Builder. If you don't know what NeXT stands for, you may want to check the wikipedia article referenced in the appendix. NIBs are resources files, Defining items such as Menu, Windows, Buttons, Text Fields, and whatnot. Using the resources could come handy for some target - but that'll be for another essay. If you try to open any of this NIBs files it should launch XCode's Interface Builder. And last but not least, the MacOS folder which contains a single file named "Dashcode". That's the one we're interested in, that's the "binary". That's the part we'll disassemble, we may get clues about a protection from other files (e.g. NIBs) that's still in this file that we well analyze and patch thee program logical flow to alter its behavior.

As you may have heard, the so called Universal Binaries contains code for both architectures, PowerPC and x86. As the otx disassembler will take care of giving us an aligned assembly listing for the Intel part of the code. We don't need to bother with the file header. We should have everything, let's start looking at our target.


0.3 Dashcode


Download Dashcode and run it, play with it, quit it. Set your system's clock to some date later than 15th July 2007. Run it again, It shoulds pop up a box telling you than this beta software has expired.
Set your date back, and run it again... Now that we know how the software behave we'll disassemble it. Fire
otx, open Dashcode.app/Contents/MacOS/Dashcode, be sure to select x86 and save the disassembly listing somewhere. Open the listing in your favorite text editor. Now let's talk a bit about assembly.




0.4 A few things about x86 assembly language



This section is by no way an extensive introduction to x86 assembly. This is just the basis. For a complete introduction to x86 asm, check the appendix section at the end. So let's have look at a line of disassembly. Go to your text editor and look a the beginning of the file, you should see this first line of assembly:



+0 00008ae4 6a00 pushl $0x00
L O M I S D


* L is line number from the beginning of the function.
* O is the offset, the address the instruction.
* M is machine code, the hexadecimal representation of the instruction.
* I is the actual assembly instruction.
* S the source parameter of the instruction.
* D the destination parameter not the instruction (none in this example).


The important part on this line is obviously pushl $0x00, the assembly instruction. This instruction, puts $0x00 on top of the stack (it's a LIFO, last in, first out, stack). Instruction have two parts, the opcode (pushl) and the operand(s) (0x00). Now look at the machine code for this instruction, that's this 6a00 you see in the M column. The 6a part is the actual instruction and 00 its operand. In this example we've seen the pushl instruction but it's only one in many (thanks Intel). Most of the time you'll encounter the same few ones. Let's have a look at the the most common opcodes (or family of instructions):

* Working with the stack, pushing/pulling data.
* Copying data between registers and memory (e.g. mov, movl, lea)
* Comparing data, between registers, memory (cmp, test)
* Branching, jumping to some offset under certain conditions (jmp, jne, jel)
* Calling functions (call,calll,lea)
* Arithmetic and Boolean functions (xor, inc, mul, sub)
* No Operation (nop), which does exactly what it mean.


Some instructions take two parameters (mov) some one (push) some none (nop). The instruction's first parameter is the source, the second one the destination. Example in:



mov ecx,eax


The content of eax is copied to the eax register. Registers are just memory slots inside the CPU. They holds value/data that the processor will need to... well, process. Certain registers have special purposes (like holding the program counter) and other have purpose by compiler convention (e.g. the same register will always get the return value of a function). I'll not elaborate more on assembly here, I'll explain the few instructions and patterns that we'll encounter but again, refer to the Appendix for documentations links.




0.5 Locating code in the dead listing


First, let me tell you a little secret about software reversing. The most difficult part is not altering the code (shamelessly easy in Dashcode). Sometimes, not even understanding the protection (obvious here). No. Sometimes, the most difficult part is finding where to start, where to look in thousands of lines.
As you'll see in future essays you don't look for the protection routine you look at the symptoms it may express, hook on them and trace back. This will be even more true when we'll debug - as opposed to disassemble - a target). In our particular example (expiration date check) this is not really an issue since we have other ways to find the relevant part of the code. We know, that somewhere, the program get the current date, checks it against July 15 2007 and if it's later, show an alert box and quit. At this point we may fire up the XCode documentation's browser and start looking for *date* methods (functions). But wait! There is an easier way to find the relevant section in the assembly listing. 2007 is probably not a number that the program use a lot. So let's look for it. Convert 2007 to its hexadecimal equivalent, 7d7. Call your text editor's find function and look for 000007d7. You should get only one result at offset 0001ed51. Let's look closer a this offset and some above:



0001ed41 c74424100f000000 movl $0x0000000f,0x10(%esp,1)
0001ed49 c744240c07000000 movl $0x00000007,0x0c(%esp,1)
0001ed51 c7442408d7070000 movl $0x000007d7,0x08(%esp,1)


So we already know that 7d7 is 2007. The two others, 07 = 7 and 0F = 15. Together they looks a lot like 15.7.2007. So this code section may not be far from the actual check routine we're looking for. But first let's explain what this movl instruction does. movl copy $source to $destination. Here a value ($0x000007d7) to a register
(esp). So basically here's the expiration date loaded in an array (different position of the same register - that's these 0x08, 0x0c, 0x10). Let's have a look at some lines below (omitting the machine code):



0001ed73 movl 0x001eafb4,%eax compare
0001ed7f calll 0x001e6469 _msgSend
0001ed84 addl $0x01,%eax
0001ed87 jel 0x0001efd1
0001ed96 movl 0x001eec60,%eax NSAlert


At offset 001ed96 we find an interesting comment (put here by our dsassembler), NSAlert. If you check the NSAlert function in the XCode documentation, you'll find what you may already have guessed: it display an alert box. So not too far from the date loading code, we found an alert box call. And just above a conditionnal jump (that's this jel instruction). Looks promising, let's review this snippet code in a whole.



0001ed09 movl 0x001eafbc,%eax calendarDate
0001ed0e movl %eax,0x04(%esp,1)
0001ed12 movl 0x001eec64,%eax NSCalendarDate
0001ed17 movl %eax,(%esp,1)
0001ed1a calll 0x001e6469 _objc_msgSend
0001ed1f movl %eax,%ebx
0001ed21 movl $0x00000000,0x20(%esp,1)
0001ed29 movl $0x00000000,0x1c(%esp,1)
0001ed31 movl $0x00000000,0x18(%esp,1)
0001ed39 movl $0x00000000,0x14(%esp,1)
0001ed41 movl $0x0000000f,0x10(%esp,1)
0001ed49 movl $0x00000007,0x0c(%esp,1)
0001ed51 movl $0x000007d7,0x08(%esp,1)
0001ed59 movl 0x001eafb8,%eax dateWithYear:month:...
0001ed5e movl %eax,0x04(%esp,1)
0001ed62 movl 0x001eec64,%eax NSCalendarDate
0001ed67 movl %eax,(%esp,1)
0001ed6a calll 0x001e6469 _objc_msgSend
0001ed6f movl %eax,0x08(%esp,1)
0001ed73 movl 0x001eafb4,%eax compare
0001ed78 movl %eax,0x04(%esp,1)
0001ed7c movl %ebx,(%esp,1)
0001ed7f calll 0x001e6469 _msgSend
0001ed84 addl $0x01,%eax
0001ed87 jel 0x0001efd1
0001ed8d movl 0x001eaf48,%eax
0001ed92 movl %eax,0x04(%esp,1)
0001ed96 movl 0x001eec60,%eax NSAlert
0001ed9b movl %eax,(%esp,1)
0001ed9e calll 0x001e6469 _msgSend


At offset 0001ed59 we find a nice comment again: dateWithYear:..., a structure, with structure's members name (Year, month, and so on) and the ordering. We may start to comment our code:



0001ed09 movl 0x001eafbc,%eax calendarDate
0001ed0e movl %eax,0x04(%esp,1)
0001ed12 movl 0x001eec64,%eax NSCalendarDate
0001ed17 movl %eax,(%esp,1)
0001ed1a calll 0x001e6469 _objc_msgSend
0001ed1f movl %eax,%ebx ;today's date in ebx
;($currentdate)
0001ed21 movl $0x00000000,0x20(%esp,1) ;timeZone
0001ed29 movl $0x00000000,0x1c(%esp,1) ;seconds
0001ed31 movl $0x00000000,0x18(%esp,1) ;minutes
0001ed39 movl $0x00000000,0x14(%esp,1) ;hours
0001ed41 movl $0x0000000f,0x10(%esp,1) ;day = 15
0001ed49 movl $0x00000007,0x0c(%esp,1) ;month = 7
0001ed51 movl $0x000007d7,0x08(%esp,1) ;Year = 2007
0001ed59 movl 0x001eafb8,%eax ;eax = *15.07.2007*
;($expiredate)
0001ed5e movl %eax,0x04(%esp,1) ;mov $expiredate in 04(esp)
0001ed62 movl 0x001eec64,%eax ;load NSCalendarDate method
0001ed67 movl %eax,(%esp,1) ;load method in the calling
;register
0001ed6a calll 0x001e6469 ;call *NSCalendarDate*
;method via _objc_msgSend
0001ed6f movl %eax,0x08(%esp,1) ;push $expiredate as second
;parameter of the
0001ed73 movl 0x001eafb4,%eax ;compare method
0001ed78 movl %eax,0x04(%esp,1) ;load method in register
0001ed7c movl %ebx,(%esp,1) ;push $curentdate as first
;parameter.
0001ed7f calll 0x001e6469 ;call method via _msgSend
0001ed84 addl $0x01,%eax ;another way to do
;test $0x01,eax
0001ed87 jel 0x0001efd1 ;if hasn't expired continue
;program flow at 00001efd1
0001ed8d movl 0x001eaf48,%eax alloc
0001ed92 movl %eax,0x04(%esp,1)
0001ed96 movl 0x001eec60,%eax ;load NSAlert method to tell
;expired
0001ed9b movl %eax,(%esp,1)
0001ed9e calll 0x001e6469 ;call NSAlert via _msgSend


After commenting, the expiration check becomes obvious. jel means jump if equal or less, so if current_date is equal or less than expiration_date the program will continue execution at offset 0x0001efd1. As I'm really a nice guy, I'll even write this snippet in pseudo code:



$current_date = NSCalendarDate(Today)
$expiration_date = NSCalendarDate(2007,7,15,0,0,0,0)

if ($current_date <= $expiration_date) then
Continue_at_ 0x0001efd1
else
NSAlert("Expired")
Quit
end if


So now that we've a good understanding of what our program is doing, let's alter
the program flow to make it acts like we want it to act.





0.6 Altering the program flow


As you'll find out there is more than one way to change the program behavior, like there was more than one way to find the check routine (we could have looked for the NSAlert function or NSCalendarDate one instead of the 2007 value). What we want to achieve is that whatever today's date is, we want to go to at offset x0001efd1 (normal flow). For this, all we have to do is to be sure that the program jumps on this jel instruction. For example we could change the 0x000007d7 at offset 0001ed51 to 0x000000bbf. Instead of expiring on the 15th of July 2007, it'll expire on the 5th July of 3007. But let's go for a more common way. We'll simply force this jel jump conditional) to an unconditional one (jmp). But how do we find out wich machine code stands for a conditional jmp ? And for the instruction's operand ? That's why there is the next section my dear reader.




0.7 Assembling new opcode


We need to change this jel 0x0001efd1 to a jmp 0x00001efd1. Looking at the machine code for the instruction, we see nothing looking like 1efd1. That's because the jump don't really point to the offset 0x00001efd1, it's a relative jump taking as operands the delta to the destination offset. So the distance between the jump's address and the destination is 0x1efd1 + 2 - 0x1ed87 = 0x248.

The + 2 is for the Two's complement, a way to distinguish positive from negative number in binary (and in our case a forward jump, positive). Check the wikipedia article in the appendix to learn more about the Two's complement.
We need to know the machine code for jmp 0x284. We may calculate it by hand but since we are big lazzy arse we'll gently ask NASM to assemble it for us.

Create a new opcode.asm file and write jmp 0x248 in it, save it. Assemble the file with:



nasm opcode.asm -o opcode.bin


Open opcode.bin in any hexeditor to see the corresponding machine code. You may
want to write a small assemble script like this one:



echo $1 >> temp.asm && nasm temp.asm -o temp.bin
&& rm temp.asm
od -N 16 -t x1 temp.bin && rm temp.bin


Save it as assemble somewhere in your $PATH, chmod it executable:



chmod +x assmble


Now you can assemble instruction and have the machine code in one step, issuing this command:



assemble "jmp 0x248"


And getting this in return:



0000000 e9 45 02


Having the new instruction's machine code we can now patch our binary.




0.8 modifying our target in a hexadecimal editor


Now that we know the new machine code, we're ready to modify our target code in an hex editor. Open the binary in 0xED and go to the offset 1ed87. The bytes doesn't look our old sequence, so search for the bytes sequence instead (the offset doesn't match since there is the PPC part - Mach-O header and offset computation for a next essay).
Now write our new instruction's bytes and put three nop (90 in hex) after to match the old instruction's length. Save it.

Put your clock to 2008, run Dashcode. 15th of July 2007, Here we come!





0.9 Writing a small patcher in C



First, let me say that I'm by no mean a C expert so be gentle. If you've never done any programming don't worry the code should be simple enough to follow, just check the C functions documentation, and you may well learn something in the process. What this patcher does is exactly the same thing we've done in the previous section, opening our target binary blob, seeking to the right offset, and changing the old machine code to the new one. The source.



/* Kellogs' Dashcode beat patchcode.c */

#include <stdio.h>
#include <string.h>

long Offset = 0x1ED87;
const OldBytes = 0x0244840f;
const NewBytes = 0x000245e9;

int main(int argc, char *argv[])
{

FILE * fBinary;
int ByteBuffer;

printf("KellogS' Dashcode Beta Trial Crack");
printf("\n -> Opening %s",strcat(argv[1],"/Contents/MacOS/Dashcode"));

fBinary=fopen(argv[1], "r+");
fseek(fBinary,Offset,SEEK_SET);
fread(&ByteBuffer, 4,1, fBinary);

if (OldBytes == ByteBuffer) {
printf("\n -> Sequence found.");
fseek(fBinary,Offset,SEEK_SET);
printf("\n -> Patching Dashcode.");
fwrite(&NewBytes, 4,1, fBinary);
printf("\n -> Patching Done. Enjoy!\n");
}
else {
printf("\n -> Sequence not found! Quitting.\n");
}

fclose(fBinary);
return 0;
}


Let's do a quick review. We've our variables at the top, namely offset, old sequence and new sequence. Some printings then the opening of the code file. Seeking to the offset, checking if offset's bytes are the same as old sequence. Writing the new bytes, informing the user. Some if to glue them all.

Compile it with:



gcc patchcode.c -o patchcode


then run it on Dashcode wtih:



./patchcode Dashcode.app




0.A Conclusion



Well, that's it. We've covered OS X applications structure, tools needed, enough assembly to understand and patch the target and even written a patcher! We'll not go in such great details in the next essays.

Hope you've enjoyed this article. If you've found any errors don't hesitate to leave a message.


0.B Greetings


This essay couldn't have been possible if I didn't have learn from these peoples.

ORC+ - He had teached the masters, enough said.
Fravia - bloatware reverser, reality cracker, search lord. Best school ever.
Frog's Print - zen master cracker and great teacher.
Spath - You're one of the best!
CyberbobJr - great cracker and a cool guy (la voila l'URL).

Btw, If any of you guys are still alive, drop me a line.

Thanks All!



That's all folks!


KellogS
kellogs.osx(at)gmail(dot)com
May 2007




0.C Appendix


Next article
Two's complement
Assembly language
Intel Assembly Doc
Apple Developer Connection
Fravia's old reversing site
Fravia's Searchlores

Google, Wikipedia and the Apple documentation are your friends.

I know, I know, I'm late....

The essay takes me more time to write that I first thought but I promise it'll be online for this weekend.