fruitfly

a technical blog

Posts Tagged ‘cocoa

Cracking Cocoa Apps for Dummies

with 7 comments

As a first note, please understand that the intention of this post is not to encourage people to start going around and crack software. And as a second note, all shown in this post can be done by an average programmer with a basic understanding of low-level computer science anyway. This post is merely to raise awareness among those developers that might have forgotten: The average indie-application is not well-protected against crackers. Good point is that the Mac/Cocoa-community is still not as much affected by this problem then the Windows-community, but still it is worth emphasizing.

What do I mean with “cracking”? Here the definition of wikipedia:

Software cracking is the modification of software to remove or disable features which are considered undesirable by the person cracking the software, usually related to protection methods: copy protection, trial/demo version, serial number, hardware key, date checks, CD check or software annoyances like nag screens and adware.

The common example is a “demo” application made available for download that has some functionality blocked until you buy the application  and enter a valid license key. A cracker could try to modify the application binary to get around this license-checking.

To be honest, I sometimes do this myself. For example yesterday: If found a very cool cocoa app in the web that I am fully interested in buying officially (and actually did after “testing” it). But, a key part of the functionality is blocked in the demo-app. Without being able to test this feature, the whole point of a demo-app is eradicated. So, before buying the app, I wanted to fully test it. This post describes the general steps I did to unlock the application and hopefully this raises some awareness for how poorly protected most apps are (AND that a demo-app should not block a core-functionality that makes the demo-app pointless; better, make it time-limited).

Demo App: MySuperCoolApp

Obviously, I will not expose any particular application, so we will go through the steps based on a very simple dummy-application that accounts for 90% of the cocoa apps out there in regard to how demo-versions are implemented. You can get the full Xcode project on github if you want to try the steps along the way yourself.

It is a simple window-based application with a single button blocking some functionality only available in the full-version. And code-wise, it looks like this:

- (IBAction)buttonPressed:(id)sender
{
    if (!self.licensed) {
        [[NSAlert alertWithMessageText:@"Unlicensed version"
                         defaultButton:@"Ok"
                       alternateButton:nil
                           otherButton:nil
             informativeTextWithFormat:@"You did not license this app, so you miss this cool feature!"]
         runModal];
    }
    else {
        // Hidden feature not available in demo-app
        [self.label setStringValue:@"Hello World"];
    }
}

Based on some property (here called “licensed”), the if-statement either gives us access to the functionality, or shows some alert-dialog asking us to buy the full-version if we need this functionality.

Step 1: Searching for the weak spot

Obviously, we don’t have the source-code available for the average app, so where to start? We can start by disassembling the application and getting a feel of how the demo-feature might be implemented. For this, there are a number of nice tools out there and as we will see, Objective-C makes it particularly easy most times to find our way into the application:

  • otool: A command-line tool coming with the MacOS developer tools that allows to inspect the contents of a binary and disassembly its text-segment. If you know objdump from linux: this is the equivalent in the Mac-world.
  • otx: A tool set on top of otool that “enhances the disassembled output” and “displayes the names and data types of Objective-C methods even if symbols have been stripped” (cited from the website). Unfortunately, it does not support 64-bit executables, so it is getting rather useless on todays systems.
  • class-dump: Another nice tool set on top of otool that generates us the header-files of our Objective-C classes. You heard right: Run it on an executable and it regenerates the .h-files for us. The only mainstream language I know of where this is even easier, is Java. Good for Java, that there are not so many good applications out there that are worth cracking 😉
  • F-Script: A scripting language that is closely integrated with Cocoa and Objective-C. For a simple introduction go here (read “Crash Course on F-Script Syntax”). If you don’t like it already: Go here and download a service that allows you to inject an F-Script instance into a running cocoa app. This basically allows for inspecting the running application very easily. This tool is for thoses, like me, that don’t use gdb if they don’t have to.
  • hexfiend: A nice hex-editor for MacOS which we will use to patch our binary.
  • gdb: The GNU Debugger is a mighty tool, but is also hard to use master as a beginner; so, I will be using F-Script in this post only. And it is sufficient any…
Ok; after introducing our tool-chain, lets try get a feel for our “to be cracked” application. Let’s execute class-dump on our binary. If you downloaded the Xcode project and built it yourself, you will find the binary somewhere around here:
/Users/<your-username>/DLibrary/Developer/Xcode/DerivedData/MySuperCoolApp-<some-uid>/Build/Products/Debug/MySuperCoolApp.app/MySuperCoolApp
Run “class-dump -H MySuperCoolApp” and the Objective-C headers will be disassembled/regenerated for you. A quick search for terms like “license” or “registered” mostly lead to some promising result.  For our dummy-app we find the following in MySuperCoolAppAppDelegate.h:
@class NSTextField, NSWindow;

@interface MySuperCoolAppAppDelegate : NSObject <NSApplicationDelegate>
{
    NSWindow *window;
    NSTextField *label;
    BOOL licensed;
}

@property(nonatomic, getter=isLicensed) BOOL licensed; // @synthesize licensed;
@property(retain, nonatomic) NSTextField *label; // @synthesize label;
@property NSWindow *window; // @synthesize window;
- (void)buttonPressed:(id)arg1;
- (void)awakeFromNib;
- (void)applicationDidFinishLaunching:(id)arg1;

@end

A variable “licensed” and accompanying synthesized property. Lets try if we are on the right track. We could now use gdb but as I said: F-Script is much easier to handle for Cocoa applications.

Step 2: Verifying the weak spot

Install F-Script and the additional service for injecting it into a running application. When you now start MySuperCoolApp, you should be able to select the following from the services-submenu:

An additional menu-item called “F-Script” should appear after a few seconds next to the “Help” item. Select “Show Console” from the submenu. A console-like window should appear that now places us in the heart of the cocoa application.

We noticed before the property “licensed” of the class “MySuperCoolAppAppDelegate”. If you are familiar with cocoa, you should know the object hierarchy that leads you to this property. Type

NSApplication sharedApplication delegate setLicensed:YES

and try again the “Click me!” button. We have unlocked the hidden functionality.

Step 3: Understanding the machine code

As the next (and often hardest step if you are like me not a crack on intel-assembler) we will have to redo our modification done in F-Script on the level of machine- and assembly-code within the binar. For this. we first have to find the assembly-code segement for the getter of the “licensed”-property.

Run “otool -Vt MySuperCoolApp > out.txt” and search within “out.txt” for “licensed” (it could appear multiple times in a universal-binary containing 32-bit and 64-bit code; you can run “otool -vf to see what architectures are bundle in the executable and which comes first). You should find a code-segement like this:

-[MySuperCoolAppAppDelegate isLicensed]:
00000001000015e0	pushq	%rbp
00000001000015e1	movq	%rsp,%rbp
00000001000015e4	movq	%rdi,0xf8(%rbp)
00000001000015e8	movq	%rsi,0xf0(%rbp)
00000001000015ec	movq	0xf8(%rbp),%rsi
00000001000015f0	movq    0x00000a91(%rip),%rdi
00000001000015f7	movb    (%rsi,%rdi),%al
00000001000015fa	movsbl  %al,%eax
00000001000015fd	popq    %rbp
00000001000015fe	ret
00000001000015ff	nop

I am not an expert on intel assembler myself, but with some minor knowledge (and thus also the awareness that the return-value of a function is handed back via the eax-register) you basically can guess that we have to try to insert a call like “mov 0x01, %eax” which says: move the value 0x01 (which stands for YES/true) into the eax register.  With some knowledge of assembly you could also know that address 1000015f0 is basically the first instruction after the prolog of the method. So, we will basically insert our mov-instruction there either followed immeditaly by “pop %rbsp” and “ret” (which is the epilog of “every” method) or we just fill the gap to the existing “popq” and “ret” with “nop” (no operations). We will choose the second approach.

So, how do instructions actually look like in machine-code; i.e. our executable file? Espacially, we have to know how a “mov” and “nop” look like, which we want to insert. Let’s call “otool -t MySuperCoolApp” to get the raw binary data of the instructions and not the disassembled assembly code:

00000001000015b0 89 7d d8 48 8b 7d e0 89 4d d4 48 8b 4d d8 44 8b
00000001000015c0 45 d4 44 8b 4d d4 88 45 d3 e8 68 00 00 00 48 83
00000001000015d0 c4 30 5d c3 66 0f 1f 44 00 00 66 0f 1f 44 00 00
00000001000015e0 55 48 89 e5 48 89 7d f8 48 89 75 f0 48 8b 75 f8
00000001000015f0 48 8b 3d 91 0a 00 00 8a 04 3e 0f be c0 5d c3 90 
0000000100001600 55 48 89 e5 88 d0 48 89 7d f8 48 89 75 f0 88 45
0000000100001610 ef 8a 45 ef 48 8b 75 f8 48 8b 3d 69 0a 00 00 88
0000000100001620 04 3e 5d c3

Based on the first column of the previous assembly output (memory-address), we can paint a picture of the binary output we see here as follows.

  • The 7-bytes in red is the instruction “movq 0x00000a91(%rip),%rdi”
  • The green byte is the “popq %rbp”
  • The yellow byte is the “ret” return of the method
  • The blue byte is a nop
With the knowledge that “mov 0x01, %eax” in machine code is B8 01 00 00 00 and “nop” is 90, we would like to change the binary content of the file as follows:
00000001000015b0 89 7d d8 48 8b 7d e0 89 4d d4 48 8b 4d d8 44 8b
00000001000015c0 45 d4 44 8b 4d d4 88 45 d3 e8 68 00 00 00 48 83
00000001000015d0 c4 30 5d c3 66 0f 1f 44 00 00 66 0f 1f 44 00 00
00000001000015e0 55 48 89 e5 48 89 7d f8 48 89 75 f0 48 8b 75 f8
00000001000015f0 B8 01 00 00 00 90 90 90 90 90 90 90 90 5d c3 90 
0000000100001600 55 48 89 e5 88 d0 48 89 7d f8 48 89 75 f0 88 45
0000000100001610 ef 8a 45 ef 48 8b 75 f8 48 8b 3d 69 0a 00 00 88
0000000100001620 04 3e 5d c3

Like said before, in red, our “mov 0x01, %eax” instruction, after that we filled everything up with nop’s and after it follows the standard epilog that basically returns from the method so the caller gets eax=1=YES as the return value.

You might now be interested how i came up with “B8 01 00 00 00” for our “mov” instruction. Basically, you have two options: Either, you write a small C-program that hopefully produces you some assembly snippet that you expect to get, or you go the full way and have a look in Intel’s I64 and IA-32 Instruction Set Manuel. It is a though read, but if you follow along the following sections, you might be able to understand how i came up with the above bytes:

  • Beginning of Chapter 2, so you get a glimpse of understanding for Figure 2-1. Figure 2-2 and Table 2-2
  • Beginning of Chapter 3 (including 3.1.1)
  • The Section on the “mov”-instruction starting on page 3-641; our particular intrest is instruction “MOV R32, IMM32”
Step 4: Patching the executable

As a last step, we have to put our theoretical crack in the binary. Unfortunatly, the address, column that is shown by otool, is not the absolute address within the binary file, but a virtual address. We could now calculate back the absolute address in the binary (read this post on how to do it) but for all practial purposes we can just use the search-functionality of HexFiend to find the likely place of code we want to modify. Just open the binary with HexFiend and search for “48 8b 3d 91 0a 00 00 8a 04 3e 0f be c0 5d c3 90“. It is rather unlikely that it appears multiple times.

We have found the bytes we were searching for; so, lets modify them with what we already layed out in theory. It should look like this after the modification:

Save it and execute “otool -vt MySuperCoolApp” once again to see if the assembly looks like we would expect:

-[MySuperCoolAppAppDelegate isLicensed]:
00000001000015e0	pushq	%rbp
00000001000015e1	movq	%rsp,%rbp
00000001000015e4	movq	%rdi,0xf8(%rbp)
00000001000015e8	movq	%rsi,0xf0(%rbp)
00000001000015ec	movq	0xf8(%rbp),%rsi
00000001000015f0	movl	$0x00000001,%eax
00000001000015f5	nop
00000001000015f6	nop
00000001000015f7	nop
00000001000015f8	nop
00000001000015f9	nop
00000001000015fa	nop
00000001000015fb	nop
00000001000015fc	nop
00000001000015fd	popq	%rbp
00000001000015fe	ret
00000001000015ff	nop

Ok, looks good; we can give it a try an execute the application again:
Hello World! …it worked! And in most cases it is not harder to do it for a real cocoa application.

Countermeasures

The Windows scene shows us that there is really no app that cannot be cracked. So, you cannot really protect against the type of people doing it “professionally”. But you can protect against people like me that only have limited knowledge of assembly and will give up if no obvious weak spot can be found in a reasonable time. So, what should you do?

  • Don’t name your sensitiv methods in any obvious way like in our dummy app. “licensed, isLicensed, registered, …” -> bad
  • Write you license checking code in pure C. Objective-C is very chatty regarding the information on method names in the executable; even with debug symbols stripped (what you should strip anyway). This stems from the dynamic nature of it. With C, the cracker at least has to have a good knowledge of assembly to find the weak spot.

The End

I hope this post was an interesting read in two ways:

  • Firstly, it should remind everyone that in the end your app is just a sequence of bytes that can be manipulated. And especially with Objective-C’s rather verbose/dynamic nature, it is relatively easy to reverse-engineer critical parts of an application against your will as a developer.
  • Secondly, doing this stuff out of own curiosity as a developer can give you a deeper understanding of the magic that is abstracted away so nicely when you work with Xcode only.

Further Reading

Written by 38leinad

May 12, 2011 at 6:54 pm

Posted in macos, tutorial

Tagged with , ,

FIRSTSteps with GNUStep

with one comment

If you are like me and are not able to work with OSX on your regular day-job, you might sometimes have this feeling that you are not living up to your full potential. You are in the need of coding a small app or tool; too big or GUI-based that perl or python could do the job (at least from the knowledge I have of them). Java is the alternative and also the main language used at my day-job; but only what is common in the JavaEE world; so:

  • I always have to look up at google how to read in a file: I find the stream-concept very mighty, but hard to remember.
  • I don’t recall all the Swing or SWT classes by memory and how to handle them
  • and most importantly: I find java-based graphical applications ugly and disgusting as hell!

But I digress… Where I wanted to go was: I really would like to leverage my Objective-C and Cocoa knowledge more often; also on other platforms.  I was aware of GNUStep for many years, but the presentation in the web looked never very appealing compared to what I am used to in the Mac-world. Yesterday, I gave it a shot anyway and was… well I would not find it fair to judge it after such a short time. For now, I would only like to describe my first steps to help others get started. Don’t be afraid; it is quiet easy to get it running!

First of all: Here is my result after 6 intensive hours of getting comfortable. Hello-world GNUStep-style… once more.

A simple window-based app printing “Hello World” on the press of a button. Isn’t it beautiful?

As you can easily see, I have been trying it out under Windows XP; actually on a VM running on my Mac and I was pretty impressed how similar it is to Cocoa. You might say: Sure, what did you expect? Well, I don’t know; I was just suprised that it is so close to the “original”; even considering the Interface Build named “Gorm”:

Looks quiet similar to the original; and even though the UI is rather outdated, it works perfectly fine: creating action-target connection? object-outlet connections? No problem!

So, how did I get my app running? Basically, it is not very hard and I will give you the steps. Plus, a few hints that would have saved at least 4 of the 6 hours.

Download and Install the Framework

First go to GNUStep.org and get the latest windows installers for the following packages: GNUStep MSYS System, GNUStep Core, GNUStep Devel. The packages cone  with a minimal MinGW confgured to work with GNUStep (including the GNU binutils and gcc).

Install them in the order mentioned above and continue with downloading from the same page the following applications (under Applications, Frameworks and Libraries) and install them:

  • System Preferences (small preferences app to configure the GNUStep environment); I haven’t used it yetm but for completnes, I list it anyway.
  • Gorm: Gorm is the GNUStep Interface Builder and, even though with a very dated UI, still gives most things you know and love about Apple’s Interface Builder.

Developing your Hello World Application

I followed the steps for a first application in the GNUStep documentation and used it for reference. You will notice that it is not nearly complete and my only real pain-point in the whole GNUStep experience. When you get to the end, you will know what I mean. It stops right in the middle and leaves you out alone in the dark. Especially, if you are not familiar with Cocoa on the Mac. If you know, you will get past this easily.

Here a few hints that might make your life easier:

  • First thing you might ask yourself is how to actual connect outlets and actions. The document says Ctrl-drag the connection. For me, it did not work on my Windows VM (I guess this is no problem on a normal Windows System). When I noticed Ctrl = Ctrl + Cmd, everything worked… almost. When you drag connection to the destination object, the connection is not established yet. You have to select the outlet or action to connect in the Inspector and press “Connect”. I am using XCode 4 now for some time; but i think it was the same in Xcode 3, but it still took me some time…
  • Notice the line defining the variable FirstApp_OBJC FILES in the GNUmakefile given in the docu: It took me some time to notice the space between OBJC and FILES. (The linker does not find my main-method? What the hell?) Make it an underscore “_”. No thanks, Windows Notepad! Big thanks to Vim!

Now, you are at the end of the documentation. What are the last steps?

  1. When you get to the end of the doc, you will notice that the description stops with a template for the main-method. What do I have to fill it with? Well, If you are familar with Cocoa this will not be a big issue; just call NSApplicationMain(argc, argv) as you always do it and the rest is handled by the configuration in the Info-gnustep.plist, generated during a “make”. Additionally, bracket the call with an auto-release-pool.
  2. Do a make, open the MinGW-Shell and browse to your project-directory: Note that even though the windows HDs C, D, etc. are not listed on “ls”, they are still there and can be “cd’ed” to. Call make and ideally, there should be no compile or linker error and the HelloWorld.app (or however you called it) should have been built.
  3. If so, start the built app with “openapp HelloWorld.app”
  4. You did NSLog-calls and don’t see any output on the console: It goes to the Windows Logging Daemon. Right-click “My Computer” on your Desktop and select “Manage”. Browse to Computer Management/System Tools/EventViewer/Application to see NSLog-calls.

E voila. AppKit on Windows! You can get the project of my Hello-World App ongithub. It should built right away when you have done the “Download and Install Framework” step.

I might write something more on how useful GNUStep actually is in daily use in a few weeks, but for now I hope this post gives you enough information to get started on your own.

Written by 38leinad

March 23, 2011 at 6:12 pm

Posted in tutorial

Tagged with , ,