summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--README.md4
-rwxr-xr-xsketch.sh1
-rw-r--r--sketchtrial.c103
-rw-r--r--sketchtrial.m28
5 files changed, 33 insertions, 107 deletions
diff --git a/Makefile b/Makefile
index 9c717ea..21116b5 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
-CFLAGS = -dynamiclib -lpthread
+CFLAGS = -dynamiclib -framework AppKit -framework Foundation
all:
- $(CC) $(CFLAGS) sketchtrial.c -o libsketchtrial.dylib
+ $(CC) $(CFLAGS) sketchtrial.m -o libsketchtrial.dylib
clean:
rm -rf *.o libsketchtrial.dylib
diff --git a/README.md b/README.md
index c7b608f..995367f 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,8 @@
# sketchtrial
-To bypass Sketch trial verification process you just need to spoof a couple of NSDate calls when the app starts. This repository contains a shared library code that can be inserted (using `DYLD_INSERT_LIBRARIES`) to the Sketch process that spoofs the right `gettimeofday` calls.
+This is a shared library that spoofs some ObjC method calls to disable Sketch license verification.
+
+Tested on Sketch 55.2.
## Building
```
diff --git a/sketch.sh b/sketch.sh
index 73dcdfc..f9d9dad 100755
--- a/sketch.sh
+++ b/sketch.sh
@@ -1,5 +1,4 @@
#!/bin/bash
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
-export DYLD_FORCE_FLAT_NAMESPACE=1
export DYLD_INSERT_LIBRARIES=$DIR/libsketchtrial.dylib
/Applications/Sketch.app/Contents/MacOS/Sketch
diff --git a/sketchtrial.c b/sketchtrial.c
deleted file mode 100644
index 388f8ab..0000000
--- a/sketchtrial.c
+++ /dev/null
@@ -1,103 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <string.h>
-#include <sys/time.h>
-#include <unistd.h>
-#include <execinfo.h>
-#include <dlfcn.h>
-#include <pthread.h>
-
-static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
-static int calls_left = 9;
-static bool done = false;
-static char buf[32];
-static long days = -5000;
-
-// pointer to the original function
-int (*orig_gettimeofday) (struct timeval *restrict tp, void *restrict tzp) = NULL;
-
-void parse_bt_source(char* src, char* dst, int len) {
- int pos = 0;
- int state = 0;
- for (char *c = src; *c != '\0' && pos < len-1; c++) {
- if (!state) {
- if (*c == ' ') {
- state = 1;
- }
- continue;
- }
- if (state == 1) {
- if (*c != ' ') {
- state = 2;
- }
- }
- if (state == 2) {
- if (*c != ' ') {
- dst[pos++] = *c;
- } else {
- dst[pos] = '\0';
- break;
- }
- }
- }
-}
-
-int gettimeofday(struct timeval *restrict tp, void *restrict tzp) {
- if (!orig_gettimeofday) {
- orig_gettimeofday = dlsym(RTLD_NEXT, "gettimeofday");
- }
-
- int result = orig_gettimeofday(tp, tzp);
- if (result != 0 || done) {
- return result;
- }
-
- pthread_mutex_lock(&mutex);
- if (!calls_left) {
- goto end;
- }
-
- void *callstack[128];
- int frames = backtrace(callstack, 128);
- char **strs = backtrace_symbols(callstack, frames);
- int i;
- bool call_sketch = false;
- bool call_nsdate = false;
-
- for (i = 0; i < frames; ++i) {
- parse_bt_source(strs[i], buf, 32);
- if (strstr(strs[i], "NSNotification") != NULL || !strcmp(buf, "CFNetwork")) {
- call_sketch = false;
- break;
- }
- if (!call_nsdate && strstr(strs[i], "NSDate") != NULL) {
- call_nsdate = true;
- }
- if (!call_sketch && !strcmp(buf, "Sketch")) {
- call_sketch = true;
- }
- }
-
- if (call_sketch && call_nsdate) {
- tp->tv_sec += days * 86400;
- tp->tv_usec = tp->tv_sec * 1000000;
- calls_left--;
-
- printf("spoofed time on call stack:\n");
- for (i = 0; i < frames; i++) {
- printf(" %s\n", strs[i]);
- }
- printf("\n");
- }
-
- free(strs);
- if (!calls_left) {
- done = true;
- }
-
-end:
- pthread_mutex_unlock(&mutex);
-
- return result;
-}
diff --git a/sketchtrial.m b/sketchtrial.m
new file mode 100644
index 0000000..26875d6
--- /dev/null
+++ b/sketchtrial.m
@@ -0,0 +1,28 @@
+#import <objc/runtime.h>
+#import <Foundation/Foundation.h>
+#include <AppKit/AppKit.h>
+
+
+//
+// BCRegularLicense
+//
+
+@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