Last active
December 16, 2015 18:19
-
-
Save ericbroska/5476629 to your computer and use it in GitHub Desktop.
Code injection for CleanMyMac 2.0.3. Uses mach_override.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <objc/runtime.h> | |
#import <Security/Security.h> | |
#import <Security/SecCode.h> | |
#import <Security/SecRequirement.h> | |
#include "mach_override.h" | |
OSStatus CESStaticCodeCreateWithPath (CFURLRef path, SecCSFlags flags, SecStaticCodeRef *staticCode); | |
OSStatus CESStaticCodeCreateWithPath (CFURLRef path, SecCSFlags flags, SecStaticCodeRef *staticCode) | |
{ | |
if ([(NSURL *)[path path] hasPrefix: [[[NSBundle mainBundle] bundleURL] path]]) { | |
CFURLRef fake_url = (CFURLRef)[NSURL fileURLWithPath: @"/Applications/Contacts.app"]; | |
return SecStaticCodeCreateWithPathAndAttributes(fake_url, flags, NULL, staticCode); | |
} | |
return SecStaticCodeCreateWithPathAndAttributes(path, flags, NULL, staticCode); | |
} | |
@interface EBInjector : NSObject @end | |
@implementation EBInjector | |
+ (void)replaceMethod: (SEL)selector inClass: (Class)class | |
{ | |
Method originalMethod = class_getInstanceMethod(class, selector); | |
if (!originalMethod) return; | |
Method newMethod = class_getInstanceMethod(self, selector); | |
if (!newMethod) return; | |
IMP newImp = method_getImplementation(newMethod); | |
if (!class_addMethod(class, selector, newImp, method_getTypeEncoding(originalMethod))) { | |
method_exchangeImplementations(originalMethod, newMethod); | |
} | |
} | |
/* | |
* CMMainWindowController | |
*/ | |
- (void)applicationDidFinishLaunching | |
{ | |
/* Hide the «Unlock Full Version» button */ | |
SEL unlockFullVersionButton_sel = NSSelectorFromString(@"unlockFullVersionButton"); | |
if ([self respondsToSelector: unlockFullVersionButton_sel]) { | |
[(NSButton *)[self performSelector: unlockFullVersionButton_sel] setHidden: YES]; | |
} | |
/* And make it unavailable for anybody */ | |
[EBInjector replaceMethod: NSSelectorFromString(@"unlockFullVersionButton") | |
inClass: NSClassFromString(@"CMMainWindowController")]; | |
} | |
- (id)unlockFullVersionButton | |
{ | |
return nil; | |
} | |
- (void)updateTrialSizeLeft: (id)size | |
{ | |
return; | |
} | |
- (void)scannerController: (id)controller shouldPauseCleaningForItemSize: (id)size | |
{ | |
return; | |
} | |
/* | |
* CMActivationManager | |
*/ | |
- (void)showCleanActivationReminderIfNeedsWithContinueHandler: (void *)handler | |
{ | |
/* Really, we don't care about anything, so just call this handlers */ | |
void (^myBlock)() = Block_copy(handler); | |
myBlock(); | |
Block_release(myBlock); | |
} | |
- (NSInteger)appActivationStatus | |
{ | |
NSInteger magic = 0x6d3; | |
/* We can not be sure, that this value won't be read from the ivar directly */ | |
object_setInstanceVariable(self, [@"_appActivationStatus" UTF8String], *(NSInteger **)&magic); | |
return magic; | |
} | |
- (NSInteger)isAppActivated { return 0x1; } | |
/* Just for fun; actually has no effect until you remove | |
-appActivationStatus and -isAppActivated | |
from |todo| dictionary in +load | |
*/ | |
- (NSUInteger)trialSizeLeft { return 0xffffffffffffff; } | |
/* | |
* CMActivationInfoStepController | |
*/ | |
- (void)restoreState:(id)state | |
{ | |
id usernamefield = [self performSelector: NSSelectorFromString(@"userNameField")]; | |
[usernamefield performSelector: NSSelectorFromString(@"setStringValue:") withObject: NSFullUserName()]; | |
id idfield = [self performSelector: NSSelectorFromString(@"serialNumberField")]; | |
[idfield performSelector: NSSelectorFromString(@"setStringValue:") withObject: @"[email protected]"]; | |
id expiration = [self performSelector: NSSelectorFromString(@"expirationDateField")]; | |
[expiration performSelector: NSSelectorFromString(@"setStringValue:") withObject: @"Nevermoar"]; | |
} | |
+ (void)load | |
{ | |
NSDictionary *todo = @ { | |
@"CMActivationManager" : @[@"isAppActivated", | |
@"appActivationStatus", | |
@"trialSizeLeft", | |
@"showCleanActivationReminderIfNeedsWithContinueHandler:"], | |
@"CMMainWindowController": @[@"applicationDidFinishLaunching", | |
@"scannerController:shouldPauseCleaningForItemSize:", | |
@"updateTrialSizeLeft:"], | |
@"CMActivationInfoStepController" : @[@"restoreState:"] | |
}; | |
[todo enumerateKeysAndObjectsUsingBlock: ^(NSString *class_name, NSArray *selectors, BOOL *stop1) { | |
[selectors enumerateObjectsUsingBlock: ^(NSString *selector_name, NSUInteger index, BOOL *stop2) { | |
[self replaceMethod: NSSelectorFromString(selector_name) | |
inClass: NSClassFromString(class_name)]; | |
}]; | |
}]; | |
if (mach_override_ptr(SecStaticCodeCreateWithPath, CESStaticCodeCreateWithPath, NULL) != 0) { | |
printf("ERROR: mach_override_ptr() failed! We have no way so.\n"); | |
} | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment