rewrite
This commit is contained in:
parent
e22e14ddb1
commit
d3c5951bb4
4
Makefile
4
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
|
||||
|
@ -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
|
||||
```
|
||||
|
@ -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
|
||||
|
103
sketchtrial.c
103
sketchtrial.c
@ -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;
|
||||
}
|
28
sketchtrial.m
Normal file
28
sketchtrial.m
Normal file
@ -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
|
Loading…
x
Reference in New Issue
Block a user