Files
Objective-See 26ec32c816 v.1.3.0
- improved output (JSON)
- universal build (intel + arm64)
- ui updates (icon, dark mode++)
2020-12-14 20:48:58 -10:00

289 lines
7.8 KiB
Objective-C

//
// File.m
// FileMonitor
//
// Created by Patrick Wardle on 9/1/19.
// Copyright © 2020 Objective-See. All rights reserved.
//
#import <libproc.h>
#import <bsm/libbsm.h>
#import <sys/sysctl.h>
#import "utilities.h"
#import "FileMonitor.h"
/* GLOBALS */
//process cache
extern NSCache* processCache;
/* FUNCTIONS */
@implementation File
@synthesize process;
@synthesize timestamp;
@synthesize sourcePath;
@synthesize destinationPath;
//init
-(id)init:(es_message_t*)message csOption:(NSUInteger)csOption
{
//process audit token
NSData* auditToken = nil;
//init super
self = [super init];
if(nil != self)
{
//set type
self.event = message->event_type;
//set timestamp
self.timestamp = [NSDate date];
//sync for process creation
@synchronized (processCache) {
//init audit token
auditToken = [NSData dataWithBytes:&message->process->audit_token length:sizeof(audit_token_t)];
//check cache for process
// not found? create process obj...
self.process = [processCache objectForKey:auditToken];
if(nil == self.process)
{
//create process
self.process = [[Process alloc] init:message csOption:csOption];
}
//sanity check
// process creation failed?
if(nil == process)
{
//unset
self = nil;
//bail
goto bail;
}
//add to cache
[processCache setObject:process forKey:auditToken];
}
//extract file path(s)
// logic is specific to event
[self extractPaths:message];
}
bail:
return self;
}
//extract source & destination path
// this requires event specific logic
-(void)extractPaths:(es_message_t*)message
{
//event specific logic
switch (message->event_type) {
//create
case ES_EVENT_TYPE_NOTIFY_CREATE:
{
//directory
NSString* directory = nil;
//file name
NSString* fileName = nil;
//existing file?
// grab file path
if(ES_DESTINATION_TYPE_EXISTING_FILE == message->event.create.destination_type)
{
//set path
self.destinationPath = convertStringToken(&message->event.create.destination.existing_file->path);
}
//new file
// build file path from directory + name
else
{
//extract directory
directory = convertStringToken(&message->event.create.destination.new_path.dir->path);
//extact file name
fileName = convertStringToken(&message->event.create.destination.new_path.filename);
//combine
self.destinationPath = [directory stringByAppendingPathComponent:fileName];
}
break;
}
//open
case ES_EVENT_TYPE_NOTIFY_OPEN:
//set path
self.destinationPath = convertStringToken(&message->event.open.file->path);
break;
//write
case ES_EVENT_TYPE_NOTIFY_WRITE:
//set path
self.destinationPath = convertStringToken(&message->event.write.target->path);
break;
//close
case ES_EVENT_TYPE_NOTIFY_CLOSE:
//set path
self.destinationPath = convertStringToken(&message->event.close.target->path);
break;
//link
case ES_EVENT_TYPE_NOTIFY_LINK:
//set (src) path
self.sourcePath = convertStringToken(&message->event.link.source->path);
//set (dest) path
// combine dest dir + dest file
self.destinationPath = [convertStringToken(&message->event.link.target_dir->path) stringByAppendingPathComponent:convertStringToken(&message->event.link.target_filename)];
break;
//rename
case ES_EVENT_TYPE_NOTIFY_RENAME:
//set (src) path
self.sourcePath = convertStringToken(&message->event.rename.source->path);
//existing file ('ES_DESTINATION_TYPE_EXISTING_FILE')
if(ES_DESTINATION_TYPE_EXISTING_FILE == message->event.rename.destination_type)
{
//set (dest) file
self.destinationPath = convertStringToken(&message->event.rename.destination.existing_file->path);
}
//new path ('ES_DESTINATION_TYPE_NEW_PATH')
else
{
//set (dest) path
// combine dest dir + dest file
self.destinationPath = [convertStringToken(&message->event.rename.destination.new_path.dir->path) stringByAppendingPathComponent:convertStringToken(&message->event.rename.destination.new_path.filename)];
}
break;
//unlink
case ES_EVENT_TYPE_NOTIFY_UNLINK:
//set path
self.destinationPath = convertStringToken(&message->event.unlink.target->path);
break;
default:
break;
}
return;
}
//for pretty printing
// though we convert to JSON
-(NSString *)description
{
//description
NSMutableString* description = nil;
//init output string
description = [NSMutableString string];
//start JSON
[description appendString:@"{"];
//add event
[description appendString:@"\"event\":"];
//add event
switch(self.event)
{
//create
case ES_EVENT_TYPE_NOTIFY_CREATE:
[description appendString:@"\"ES_EVENT_TYPE_NOTIFY_CREATE\","];
break;
//open
case ES_EVENT_TYPE_NOTIFY_OPEN:
[description appendString:@"\"ES_EVENT_TYPE_NOTIFY_OPEN\","];
break;
//write
case ES_EVENT_TYPE_NOTIFY_WRITE:
[description appendString:@"\"ES_EVENT_TYPE_NOTIFY_WRITE\","];
break;
//close
case ES_EVENT_TYPE_NOTIFY_CLOSE:
[description appendString:@"\"ES_EVENT_TYPE_NOTIFY_CLOSE\","];
break;
//rename
case ES_EVENT_TYPE_NOTIFY_RENAME:
[description appendString:@"\"ES_EVENT_TYPE_NOTIFY_RENAME\","];
break;
//link
case ES_EVENT_TYPE_NOTIFY_LINK:
[description appendString:@"\"ES_EVENT_TYPE_NOTIFY_LINK\","];
break;
//unlink
case ES_EVENT_TYPE_NOTIFY_UNLINK:
[description appendString:@"\"ES_EVENT_TYPE_NOTIFY_UNLINK\","];
break;
default:
break;
}
//add timestamp
[description appendFormat:@"\"timestamp\":\"%@\",", self.timestamp];
//start file
[description appendString:@"\"file\":{"];
//src path
// option, so check
if(0 != self.sourcePath)
{
//add
[description appendFormat: @"\"source\":\"%@\",", self.sourcePath];
}
//dest path
[description appendFormat: @"\"destination\":\"%@\",", self.destinationPath];
//add process
[description appendFormat: @"%@", self.process];
//terminate file
[description appendString:@"}"];
//terminate entire JSON
[description appendString:@"}"];
return description;
}
@end