dylanedwards.com | Dylan Edwards

Nov/09

10

BUT WHAT DOES IT ALL MEAN? (pt. 2)

Now it’s time for some poorly-written, lengthy sentences. I’m going to go ahead and explain a basic overview of how most simple apps are cracked on OS X. You most likely won’t walk away with knowledge of how to crack applications yourself, but if you’ve understood everything so far, you can probably teach yourself. Before I go any further, I would like to firmly state that this information is for educational purposes only and should not be redistributed or used to do anything illegal/unethical. I enjoy cracking applications because it gives me a better understand of what my computer is really doing, and I hope to share the joy of understanding with you. I do not condone piracy. If I like software, I buy it (and so should you). Now time for the good stuff.

The start of nearly every Mac OS X crack begins by examining the code contained within an application. You probably don’t have access to the source code of the application you are looking to crack, so you have to yank that information out of the app itself. This is both possible and easy thanks to our friend otool. With the right arguments, otool will dump out the code contained in an app. Gathering the correct arguments and digging through code to match up Objective-C method names can be a pain even after you’ve used otool, and that’s why otx is a lifesaver. otx is a GUI app that makes life easy by dumping a prettified otool output and more into a text file.

Running otx on an application’s executable (located at MyAppName.app/Contents/MacOS/MyAppName) for x86 will yield a beautiful mess of output that looks a bit like this (from Apple’s Calculator):

-(void)[LCDController setPrecision:]
+0 00003595 55 pushl %ebp
+1 00003596 89e5 movl %esp,%ebp
+3 00003598 8b4508 movl 0x08(%ebp),%eax
+6 0000359b 8b5510 movl 0x10(%ebp),%edx
+9 0000359e 895058 movl %edx,0x58(%eax) (int)__Precision
+12 000035a1 8b1578550100 movl 0x00015578,%edx showValue
+18 000035a7 89550c movl %edx,0x0c(%ebp)
+21 000035aa 894508 movl %eax,0x08(%ebp)
+24 000035ad c9 leave
+25 000035ae e9cbc80000 jmpl 0x0000fe7e

So you’re probably wondering what all of that means, right? I’ll go ahead and explain it a bit. The first line (with the brackets around it) is a method name. The fact that we can read these is important because it often gives clues as to what the app is doing when it calls that method- for instance, in this case the App (calculator) is setting its precision.

The first column you see is a local offset, or the offset within that method. It basically gives you an idea of how far into a particular method you are. The next column is the actual offset of the code- this is important to note because it is where the code you are viewing resides within the executable file. If you wanted to patch a piece of code, you could skip right to its offset in the binary. The next column is the opcode for the current instruction. This is the part that tells the computer what to do, and it’s the part you generally end up modifying in an executable. The last few columns are the assembly language instructions for what is going on.

Now that you have a clearer idea of what you are looking at, I’ll talk about the most simple reverse engineering technique. When you are trying to crack an application, you are generally looking to circumvent some sort of registration or trial restriction on the program. Most of the time, this means finding the location of the relevant code and patching the binary to ignore it. To find the necessary code, you can search through the otx dump for key words like “Register”, “Nag”, “Trial”, “Expire”, and more. You have to use your brain and take a look at what the methods are named and where they are being called. Try to get an understanding of what the program is doing and when. Most hackers use a debugger like GDB to actually follow the flow of the program, but this is a vast over-simplification based on guesswork.

The majority of the time, a crack comes down to modifying one single line of code, and that is the conditional check for a registration (where the program is checking whether or not you have a registered copy). In Objective-C, these checks tend to follow a pattern. Below is a snippet from an otx dump that is key to a crack:

+2351 00004481 e8f8b90000 calll 0x0000fe7e -[(%esp,1) isRegistered:]
+2356 00004486 84c0 testb %al,%al
+2358 00004488 752f jne 0x000044b9

What’s going on here (skipping a lot of essential code that comes before an simplifying what’s going on) is pretty easy to understand! The program is calling (see calll?) the method isRegistered: and is then testing (see testb?) the result. What usually follows is one of two instructions: jel or in this case, jne.

What do these instructions mean? Easy. jel means “jump if equal” and jne means “jump if not equal”. Jump just means to skip to a different part of the code. In this case, if you are not registered, it is going to skip to the part of the code that kicks you out. So 99% of cracks come down to reversing or ignoring one of these instructions.

In the pasted code, the program is checking if it is registered, testing the result, and jumping if the result is not equal (if this sounds funny go learn assembly or just accept that it’s not extremely important). Since the program is going to continue jumping to kick us out as long as we’re not registered, we want to remove or ignore the jne instruction and let the program continue on as if we were in fact registered.

If you’ve read my earlier posts, you probably know where I am going, and that is to nop. nop (opcode 90) is the “do nothing” instruction in assembly language. All we want to do is replace our little jne with a nop. To do this, you simply open the app’s original executable in a hex editor, jump to the offset from the otx dump ( 0x4488 in this case) and replace the offending code (752f) with nops (9090).

Voila, our imaginary app is cracked. Sorry for the horrible writing, I’m doing this at 1:22 AM instead of stressing over homework. This probably wasn’t the most clear guide, and it certainly isn’t the most accurate (like I mentioned, almost every real cracking process involves using GDB). If you have any questions or would like my help, feel free to comment or shoot me an email.

There will be another informative (and easier to understand) post coming soon on packet sniffing in Mac OS X!

RSS Feed

No comments yet.

Leave a comment!

<<

>>

Find it!

Theme Design by devolux.org