This repo is an example of cracking an Objective-C app by using SIMBL. SIMBL injects code into an application during its load. We will try to create a plugin that hooks the registration scheme of a simple app we will build.
SIMBL is designed to load bundles into an application to extend/change functionality of an app.
Our target application contains a simple 'registration scheme' that just checks the validity of an input key and notifies the user if the application is registered or not:
Our goal here is to crack this application without making binary modifications to the original app. Although we have the source code for this app, we will pretend that we are doing some black box analysis on it. In order to gain a high level view of what is going on here, we can dump the class and method structure using the very useful tool class-dump
.
Below is the (slightly redacted) output of class-dump:
class-dump CrackMe
/*
* Generated by class-dump 3.4 (64 bit).
*
* class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2012 by Steve Nygard.
*/
#pragma mark -
/*
* File: CrackMe
* Arch: x86_64
* Source version: 0.0.0.0.0
* Minimum Mac OS X version: 10.8.0
* SDK version: 10.8.0
*
* Objective-C Garbage Collection: Unsupported
*/
--- Omitted unuseful stuff here ---
@interface AppDelegate : NSObject <NSApplicationDelegate>
{
NSWindow *_window;
NSTextField *_registrationTextBox;
NSTextField *_registrationStatus;
NSButton *_registrationButton;
}
--- Omitted unuseful stuff here ---
@property NSWindow *window; // @synthesize window=_window;
- (void).cxx_destruct;
- (BOOL)isValidSerial:(id)arg1;
- (void)doRegistration:(id)arg1;
- (void)applicationDidFinishLaunching:(id)arg1;
@end
The only function it looks like we really care about is isValidSerial
that returns a boolean.
Our general approach here is going to be to hook calls to [AppDelegate isValidSerial:] and replace it with our own function -- something that always returns true.
The tutorial I followed to create the bundle SIMBL tutorial
While developing the SIMBL plugin, I found it easier to symlink the bundle into the plugin folder rather than having to manually copy the bundle after every build:
ln -s /Users/fuzion24/Library/Developer/Xcode/DerivedData/Swizzler-awlqvopkqunralfrlyrqcwxoipui/Build/Products/Debug/Swizzler.bundle ~/Library/Application\ Support/SIMBL/Plugins
The actual meat of the hack:
@implementation CrackMePlugin
- (BOOL) isValidSerial:(NSString*)key{
NSLog(@"Tried to get validity for serial: %@", key, nil);
return true;
}
/**
* load is a special method called by SIMBL once the application has started and all classes are initialized.
*/
+ (void) load
{
NSLog(@"CrackMePlugin installed");
Class appDelegate = objc_getClass("AppDelegate");
Class this = self.class;
Method instMeth = class_getInstanceMethod(this, @selector(isValidSerial:));
IMP haxxed = method_getImplementation(instMeth);
Method origValidSerialCheck = class_getInstanceMethod(appDelegate, @selector(isValidSerial:));
method_setImplementation(origValidSerialCheck, haxxed);
}
@end
Since SIMBL is somewhat depreciated, I chose to use EasySIMBL:
---Notes--- I ran into some issues using SIMBL with some applications. For instance, I wanted to change the behavior of a function that was called immediately upon startup of the application. SIML has some lag time before being injected into the app and therefore was not properly hooking the early function call.