Disabling Sketch license verification

Disclaimer: this article is for educational purposes only. Consider buying the license to support developers.

Sketch is a vector graphics editor for interface designers. It has demo version that works for 3 days or so. When the demo period is over, a blocking modal window appears at startup:

Let's see if we can outsmart it. Open Sketch executable in a disassembler, search for the "trial days remaining" string, then search for references to it.

Look, some -[MSAboutWindowController refreshTrialNoteWithLicenseManager:] method was found:

It accepts void *arg2 pointer as an argument, and as the method name suggests, it must be an instance of some "license manager". That "license manager" has numberOfDaysLeftInTrialMode method:

var_48 = [arg2 retain];
[var_48 numberOfDaysLeftInTrialMode];

Open it's implementation pseudo code, it will be found in BCLicenseManager class:

So this BCLicenseManager class has license selector, that returns some license instance, which in turn has remainingTimeInterval method. If you search for implementations of remainingTimeInterval selector, two methods with the same name from different classes will be found:

Let's open the first one, which is BCRegularLicense:

Look through the pseudo code, there're many interesting methods. For instance validityInterval or isValid. Let's check what other methods does this BCRegularLicense have. Type the class name into the procedure search field, scroll through the results. You will find some isExpired method:

Looks very promising. Maybe just return false here?

Patch jmp and mov in assembly:

Before
After

Hmm. It works!

If you don't like patching binaries, you can spoof isExpired call by injecting code at runtime. To do that, you need to write a shared library that replaces method implementation and insert it into the Sketch process using DYLD_INSERT_LIBRARIES.

#import <objc/runtime.h>
#import <Foundation/Foundation.h>
#include <AppKit/AppKit.h>

@interface BCRegularLicensePatched : NSObject
- (bool)isExpired;
@end

@implementation BCRegularLicensePatched

+(void)load {
Class origClass = NSClassFromString(@"BCRegularLicense");
    Method origMethod = class_getInstanceMethod(origClass, @selector(isExpired));
    Method replMethod = class_getInstanceMethod(NSClassFromString(@"BCRegularLicensePatched"), @selector(isExpired));

    method_exchangeImplementations(origMethod, replMethod);
}

-(bool)isExpired {
    return false;
}

@end

Save this code to main.m and build as shared library:

$ gcc -dynamiclib -framework AppKit -framework Foundation main.m -o hacksketch.dylib

Launch Sketch:

#!/bin/sh
export DYLD_INSERT_LIBRARIES=./hacksketch.dylib
/Applications/Sketch.app/Contents/MacOS/Sketch
If you have any comments, contact me by email.
powered by OpenBSD
© ch1p 2019