Skip to content

Instantly share code, notes, and snippets.

@ericbroska
Last active December 16, 2015 18:19
Show Gist options
  • Save ericbroska/5476629 to your computer and use it in GitHub Desktop.
Save ericbroska/5476629 to your computer and use it in GitHub Desktop.
Code injection for CleanMyMac 2.0.3. Uses mach_override.
#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: @"eric.broska@me.com"];
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