initial checkin

This commit is contained in:
Patrick Wardle
2019-09-05 20:32:45 -10:00
parent c0cf94f17c
commit b4d9f952fa
9 changed files with 1153 additions and 0 deletions
+1
View File
@@ -61,3 +61,4 @@ fastlane/test_output
# https://github.com/johnno1962/injectionforxcode
iOSInjectionProject/
FileMonitor.xcodeproj/project.xcworkspace/contents.xcworkspacedata
+292
View File
@@ -0,0 +1,292 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 50;
objects = {
/* Begin PBXBuildFile section */
CE56C7ED231DAAD10046EDA3 /* File.m in Sources */ = {isa = PBXBuildFile; fileRef = CE56C7EC231DAAD10046EDA3 /* File.m */; };
CE91B743231A0E6D003273AF /* FileMonitor.h in Headers */ = {isa = PBXBuildFile; fileRef = CE91B742231A0E6D003273AF /* FileMonitor.h */; };
CE91B745231A0E6D003273AF /* FileMonitor.m in Sources */ = {isa = PBXBuildFile; fileRef = CE91B744231A0E6D003273AF /* FileMonitor.m */; };
CE91B74E231A129D003273AF /* Process.m in Sources */ = {isa = PBXBuildFile; fileRef = CE91B74C231A129D003273AF /* Process.m */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
CE56C7EC231DAAD10046EDA3 /* File.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = File.m; sourceTree = "<group>"; };
CE91B73F231A0E6D003273AF /* libFileMonitor.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libFileMonitor.a; sourceTree = BUILT_PRODUCTS_DIR; };
CE91B742231A0E6D003273AF /* FileMonitor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FileMonitor.h; sourceTree = "<group>"; };
CE91B744231A0E6D003273AF /* FileMonitor.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FileMonitor.m; sourceTree = "<group>"; };
CE91B74C231A129D003273AF /* Process.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Process.m; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
CE91B73D231A0E6D003273AF /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
CE91B736231A0E6D003273AF = {
isa = PBXGroup;
children = (
CE91B741231A0E6D003273AF /* Source */,
CE91B740231A0E6D003273AF /* Products */,
);
sourceTree = "<group>";
};
CE91B740231A0E6D003273AF /* Products */ = {
isa = PBXGroup;
children = (
CE91B73F231A0E6D003273AF /* libFileMonitor.a */,
);
name = Products;
sourceTree = "<group>";
};
CE91B741231A0E6D003273AF /* Source */ = {
isa = PBXGroup;
children = (
CE91B742231A0E6D003273AF /* FileMonitor.h */,
CE91B744231A0E6D003273AF /* FileMonitor.m */,
CE91B74C231A129D003273AF /* Process.m */,
CE56C7EC231DAAD10046EDA3 /* File.m */,
);
path = Source;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
CE91B73B231A0E6D003273AF /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
CE91B743231A0E6D003273AF /* FileMonitor.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
CE91B73E231A0E6D003273AF /* FileMonitor */ = {
isa = PBXNativeTarget;
buildConfigurationList = CE91B748231A0E6D003273AF /* Build configuration list for PBXNativeTarget "FileMonitor" */;
buildPhases = (
CE91B73B231A0E6D003273AF /* Headers */,
CE91B73C231A0E6D003273AF /* Sources */,
CE91B73D231A0E6D003273AF /* Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = FileMonitor;
productName = processMonitor;
productReference = CE91B73F231A0E6D003273AF /* libFileMonitor.a */;
productType = "com.apple.product-type.library.static";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
CE91B737231A0E6D003273AF /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1100;
ORGANIZATIONNAME = "Objective-See";
TargetAttributes = {
CE91B73E231A0E6D003273AF = {
CreatedOnToolsVersion = 11.0;
};
};
};
buildConfigurationList = CE91B73A231A0E6D003273AF /* Build configuration list for PBXProject "FileMonitor" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = CE91B736231A0E6D003273AF;
productRefGroup = CE91B740231A0E6D003273AF /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
CE91B73E231A0E6D003273AF /* FileMonitor */,
);
};
/* End PBXProject section */
/* Begin PBXSourcesBuildPhase section */
CE91B73C231A0E6D003273AF /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
CE56C7ED231DAAD10046EDA3 /* File.m in Sources */,
CE91B745231A0E6D003273AF /* FileMonitor.m in Sources */,
CE91B74E231A129D003273AF /* Process.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
CE91B746231A0E6D003273AF /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.15;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
};
name = Debug;
};
CE91B747231A0E6D003273AF /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.15;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = macosx;
};
name = Release;
};
CE91B749231A0E6D003273AF /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
EXECUTABLE_PREFIX = lib;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
};
name = Debug;
};
CE91B74A231A0E6D003273AF /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
EXECUTABLE_PREFIX = lib;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
CE91B73A231A0E6D003273AF /* Build configuration list for PBXProject "FileMonitor" */ = {
isa = XCConfigurationList;
buildConfigurations = (
CE91B746231A0E6D003273AF /* Debug */,
CE91B747231A0E6D003273AF /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
CE91B748231A0E6D003273AF /* Build configuration list for PBXNativeTarget "FileMonitor" */ = {
isa = XCConfigurationList;
buildConfigurations = (
CE91B749231A0E6D003273AF /* Debug */,
CE91B74A231A0E6D003273AF /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = CE91B737231A0E6D003273AF /* Project object */;
}
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
+145
View File
@@ -0,0 +1,145 @@
//
// Process.m
// ProcessMonitor
//
// Created by Patrick Wardle on 9/1/19.
// Copyright © 2019 Objective-See. All rights reserved.
//
#import <libproc.h>
#import <bsm/libbsm.h>
#import <sys/sysctl.h>
#import "utilities.h"
#import "FileMonitor.h"
//events
extern NSDictionary* eventsOfInterest;
/* FUNCTIONS */
@implementation File
@synthesize process;
@synthesize sourcePath;
@synthesize destinationPath;
//init
-(id)init:(es_message_t*)message
{
//init super
self = [super init];
if(nil != self)
{
//set type
self.event = message->event_type;
//set process
self.process = [[Process alloc] init:message];
//extract path(s)
// logic is specific to event
[self extractPaths:message];
}
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:
//set path
self.destinationPath = convertStringToken(&message->event.create.target->path);
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
-(NSString *)description
{
//pretty print
return [NSString stringWithFormat: @"%@: \nsource path: %@\ndestination path: %@\nprocess: %@", eventsOfInterest[[NSNumber numberWithInt:self.event]], self.sourcePath, self.destinationPath, process];
}
@end
+109
View File
@@ -0,0 +1,109 @@
//
// FileMonitor.h
// FileMonitor
//
// Created by Patrick Wardle on 9/1/19.
// Copyright © 2019 Objective-See. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <EndpointSecurity/EndpointSecurity.h>
/* CONSTS */
//code signing keys
#define KEY_SIGNATURE_CDHASH @"cdHash"
#define KEY_SIGNATURE_FLAGS @"csFlags"
#define KEY_SIGNATURE_IDENTIFIER @"signatureIdentifier"
#define KEY_SIGNATURE_TEAM_IDENTIFIER @"teamIdentifier"
#define KEY_SIGNATURE_PLATFORM_BINARY @"isPlatforBinary"
/* CLASSES */
@class File;
@class Process;
/* TYPEDEFS */
//block for library
typedef void (^FileCallbackBlock)(File* _Nonnull);
@interface FileMonitor : NSObject
//start monitoring
-(BOOL)start:(FileCallbackBlock _Nonnull )callback;
//stop monitoring
-(BOOL)stop;
@end
/* OBJECT: FILE */
@interface File : NSObject
/* PROPERTIES */
//event
// create, write, etc...
@property u_int32_t event;
//src path
@property(nonatomic, retain)NSString* _Nullable sourcePath;
//dest path
@property(nonatomic, retain)NSString* _Nullable destinationPath;
//process
@property(nonatomic, retain)Process* _Nullable process;
/* METHODS */
//init
-(id _Nullable)init:(es_message_t* _Nonnull)message;
@end
/* OBJECT: PROCESS */
@interface Process : NSObject
/* PROPERTIES */
//pid
@property pid_t pid;
//ppid
@property pid_t ppid;
//user id
@property uid_t uid;
//event
// exec, fork, exit
@property u_int32_t event;
//exit code
@property u_int32_t exit;
//path
@property(nonatomic, retain)NSString* _Nullable path;
//args
@property(nonatomic, retain)NSMutableArray* _Nonnull arguments;
//ancestors
@property(nonatomic, retain)NSMutableArray* _Nonnull ancestors;
//signing info
@property(nonatomic, retain)NSMutableDictionary* _Nonnull signingInfo;
//timestamp
@property(nonatomic, retain)NSDate* _Nonnull timestamp;
/* METHODS */
//init
-(id _Nullable)init:(es_message_t* _Nonnull)message;
@end
+230
View File
@@ -0,0 +1,230 @@
//
// FileMonitor.m
// FileMonitor
//
// Created by Patrick Wardle on 9/1/19.
// Copyright © 2019 Objective-See. All rights reserved.
//
// Inspired by https://gist.github.com/Omar-Ikram/8e6721d8e83a3da69b31d4c2612a68ba
// NOTE: requires a) root b) the 'com.apple.developer.endpoint-security.client' entitlement
#import "utilities.h"
#import "FileMonitor.h"
#import <Foundation/Foundation.h>
#import <EndpointSecurity/EndpointSecurity.h>
//endpoint
es_client_t *endpointClient = nil;
//file events of interest
NSDictionary* eventsOfInterest = nil;
@implementation FileMonitor
//init
-(id)init
{
//init super
self = [super init];
if(nil != self)
{
//init events of interest
eventsOfInterest = @{[NSNumber numberWithInt:ES_EVENT_TYPE_NOTIFY_CREATE]:@"ES_EVENT_TYPE_NOTIFY_CREATE",
[NSNumber numberWithInt:ES_EVENT_TYPE_NOTIFY_OPEN]:@"ES_EVENT_TYPE_NOTIFY_OPEN",
[NSNumber numberWithInt:ES_EVENT_TYPE_NOTIFY_WRITE]:@"ES_EVENT_TYPE_NOTIFY_WRITE",
[NSNumber numberWithInt:ES_EVENT_TYPE_NOTIFY_CLOSE]:@"ES_EVENT_TYPE_NOTIFY_CLOSE",
[NSNumber numberWithInt:ES_EVENT_TYPE_NOTIFY_RENAME]:@"ES_EVENT_TYPE_NOTIFY_RENAME",
[NSNumber numberWithInt:ES_EVENT_TYPE_NOTIFY_LINK]:@"ES_EVENT_TYPE_NOTIFY_LINK",
[NSNumber numberWithInt:ES_EVENT_TYPE_NOTIFY_UNLINK]:@"ES_EVENT_TYPE_NOTIFY_UNLINK"};
}
return self;
}
//start monitoring
-(BOOL)start:(FileCallbackBlock)callback
{
//flag
BOOL started = NO;
//events (as array)
es_event_type_t* events = NULL;
//result
es_new_client_result_t result = 0;
//alloc events
events = malloc(sizeof(es_event_type_t) * eventsOfInterest.count);
//init events
// es_* APIs expect a C-array...
for(int i = 0; i < eventsOfInterest.count; i++)
{
//add event
events[i] = [eventsOfInterest.allKeys[i] intValue];
}
//sync
@synchronized (self)
{
//create client
// callback invokes (user) callback for new processes
result = es_new_client(&endpointClient, ^(es_client_t *cleint, const es_message_t *message)
{
//new file event
File* file = nil;
//ignore non-notify messages
if(ES_ACTION_TYPE_NOTIFY != message->action_type)
{
//ignore
return;
}
//ignore non-msg's of interest
if(nil == [eventsOfInterest objectForKey:[NSNumber numberWithInt:message->event_type]])
{
//ignore
return;
}
//init process obj
file = [[File alloc] init:(es_message_t* _Nonnull)message];
if(nil != file)
{
//invoke user callback
callback(file);
}
});
//error?
if(ES_NEW_CLIENT_RESULT_SUCCESS != result)
{
//err msg
NSLog(@"ERROR: es_new_client() failed with %d", result);
//bail
goto bail;
}
//clear cache
if(ES_CLEAR_CACHE_RESULT_SUCCESS != es_clear_cache(endpointClient))
{
//err msg
NSLog(@"ERROR: es_clear_cache() failed");
//bail
goto bail;
}
//mute self
// note: you might not want this, but for a cmdline-based filemonitor
// this ensures we don't constantly report writes to /dev/tty
es_mute_path_literal(endpointClient, [NSProcessInfo.processInfo.arguments[0] UTF8String]);
//subscribe
if(ES_RETURN_SUCCESS != es_subscribe(endpointClient, events, (u_int32_t)eventsOfInterest.count))
{
//err msg
NSLog(@"ERROR: es_subscribe() failed");
//bail
goto bail;
}
} //sync
//happy
started = YES;
bail:
//free events
if(NULL != events)
{
//free
free(events);
events = NULL;
}
return started;
}
//stop
-(BOOL)stop
{
//flag
BOOL stopped = NO;
//sync
@synchronized (self)
{
//unsubscribe & delete
if(NULL != endpointClient)
{
//unsubscribe
if(ES_RETURN_SUCCESS != es_unsubscribe_all(endpointClient))
{
//err msg
NSLog(@"ERROR: es_unsubscribe_all() failed");
//bail
goto bail;
}
//delete
if(ES_RETURN_SUCCESS != es_delete_client(endpointClient))
{
//err msg
NSLog(@"ERROR: es_delete_client() failed");
//bail
goto bail;
}
//unset
endpointClient = NULL;
//happy
stopped = YES;
}
} //sync
bail:
return stopped;
}
@end
//helper function
// convert es_string_token_t to string
NSString* convertStringToken(es_string_token_t* stringToken)
{
//string
NSString* string = nil;
//init to empty string
string = [NSString string];
//sanity check(s)
if( (NULL == stringToken) ||
(0 == stringToken->length) ||
(NULL == stringToken->data) )
{
//bail
goto bail;
}
//convert to data, then to string
string = [NSString stringWithUTF8String:[[NSData dataWithBytes:stringToken->data length:stringToken->length] bytes]];
bail:
return string;
}
+315
View File
@@ -0,0 +1,315 @@
//
// Process.m
// ProcessMonitor
//
// Created by Patrick Wardle on 9/1/19.
// Copyright © 2019 Objective-See. All rights reserved.
//
#import <libproc.h>
#import <bsm/libbsm.h>
#import <sys/sysctl.h>
#import "utilities.h"
#import "FileMonitor.h"
/* FUNCTIONS */
//helper function
// get parent of arbitrary process
pid_t getParentID(pid_t child);
@implementation Process
@synthesize pid;
@synthesize exit;
@synthesize path;
@synthesize ppid;
@synthesize event;
@synthesize ancestors;
@synthesize arguments;
@synthesize timestamp;
@synthesize signingInfo;
//init
-(id)init:(es_message_t*)message
{
//init super
self = [super init];
if(nil != self)
{
//process from msg
es_process_t* process = NULL;
//alloc array for args
self.arguments = [NSMutableArray array];
//alloc array for parents
self.ancestors = [NSMutableArray array];
//alloc dictionary for signing info
self.signingInfo = [NSMutableDictionary dictionary];
//init exit
self.exit = -1;
//init user id
self.uid = -1;
//init event
self.event = -1;
//set start time
self.timestamp = [NSDate date];
//set type
self.event = message->event_type;
//event specific logic
// set type
// extract (relevant) process object, etc
switch (message->event_type) {
//exec
case ES_EVENT_TYPE_NOTIFY_EXEC:
//set process (target)
process = message->event.exec.target;
//extract/format args
[self extractArgs:&message->event];
break;
//fork
case ES_EVENT_TYPE_NOTIFY_FORK:
//set process (child)
process = message->event.fork.child;
break;
//exit
case ES_EVENT_TYPE_NOTIFY_EXIT:
//set process
process = message->process;
//set exit code
self.exit = message->event.exit.stat;
break;
//default
default:
//set process
process = message->process;
break;
}
//init pid
self.pid = audit_token_to_pid(process->audit_token);
//init ppid
self.ppid = process->ppid;
//init uuid
self.uid = audit_token_to_euid(process->audit_token);
//init path
self.path = convertStringToken(&process->executable->path);
//extract/format code signing info
[self extractSigningInfo:process];
//enum ancestors
[self enumerateAncestors];
}
return self;
}
//extract/format args
-(void)extractArgs:(es_events_t *)event
{
//number of args
uint32_t count = 0;
//get # of args
count = es_exec_arg_count(&event->exec);
if(0 == count)
{
//bail
goto bail;
}
//extact all args
for(uint32_t i = 0; i < count; i++)
{
//current arg
es_string_token_t currentArg = {0};
//extract current arg
currentArg = es_exec_arg(&event->exec, i);
//append
[self.arguments addObject:convertStringToken(&currentArg)];
}
bail:
return;
}
//extract/format signing info
-(void)extractSigningInfo:(es_process_t *)process
{
//cd hash
NSMutableString* cdHash = nil;
//alloc string for hash
cdHash = [NSMutableString string];
//add flags
self.signingInfo[KEY_SIGNATURE_FLAGS] = [NSNumber numberWithUnsignedInt:process->codesigning_flags];
//add signing id
self.signingInfo[KEY_SIGNATURE_IDENTIFIER] = convertStringToken(&process->signing_id);
//add team id
self.signingInfo[KEY_SIGNATURE_TEAM_IDENTIFIER] = convertStringToken(&process->team_id);
//add platform binary
self.signingInfo[KEY_SIGNATURE_PLATFORM_BINARY] = [NSNumber numberWithBool:process->is_platform_binary];
//format cdhash
for(uint32_t i = 0; i<CS_CDHASH_LEN; i++)
{
//append
[cdHash appendFormat:@"%X", process->cdhash[i]];
}
//add cdhash
self.signingInfo[KEY_SIGNATURE_CDHASH] = cdHash;
return;
}
//generate list of ancestors
-(void)enumerateAncestors
{
//current process id
pid_t currentPID = -1;
//parent pid
pid_t parentPID = -1;
//add parent
if(-1 != self.ppid)
{
//add
[self.ancestors addObject:[NSNumber numberWithInt:self.ppid]];
//set current to parent
currentPID = self.ppid;
}
//don't know parent
// just start with self
else
{
//start w/ self
currentPID = self.pid;
}
//complete ancestry
while(YES)
{
//get parent pid
parentPID = getParentID(currentPID);
if( (0 == parentPID) ||
(-1 == parentPID) ||
(currentPID == parentPID) )
{
//bail
break;
}
//update
currentPID = parentPID;
//add
[self.ancestors addObject:[NSNumber numberWithInt:parentPID]];
}
return;
}
//for pretty printing
-(NSString *)description
{
//description
NSString* description = nil;
//exec/fork events
// don't add exit code...
if(ES_EVENT_TYPE_NOTIFY_EXIT != self.event)
{
//pretty print
description = [NSString stringWithFormat: @"pid: %d\npath: %@\nuid: %d\nargs: %@\nancestors: %@\nsigning info: %@", self.pid, self.path, self.uid, self.arguments, self.ancestors, self.signingInfo];
}
//exit event
// add exit code
else
{
description = [NSString stringWithFormat: @"pid: %d\npath: %@\nuid: %d\nargs: %@\nancestors: %@\nsigning info: %@\nexit code: %d", self.pid, self.path, self.uid, self.arguments, self.ancestors, self.signingInfo, self.exit];
}
return description;
}
@end
//helper function
// get parent of arbitrary process
pid_t getParentID(pid_t child)
{
//parent id
pid_t parentID = -1;
//kinfo_proc struct
struct kinfo_proc processStruct = {0};
//size
size_t procBufferSize = 0;
//mib
const u_int mibLength = 4;
//syscall result
int sysctlResult = -1;
//init buffer length
procBufferSize = sizeof(processStruct);
//init mib
int mib[mibLength] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, child};
//make syscall
sysctlResult = sysctl(mib, mibLength, &processStruct, &procBufferSize, NULL, 0);
//check if got ppid
if( (noErr == sysctlResult) &&
(0 != procBufferSize) )
{
//save ppid
parentID = processStruct.kp_eproc.e_ppid;
}
return parentID;
}
+18
View File
@@ -0,0 +1,18 @@
//
// utilities.h
// ProcessMonitor
//
// Created by Patrick Wardle on 9/1/19.
// Copyright © 2019 Objective-See. All rights reserved.
//
#ifndef utilities_h
#define utilities_h
#import <Foundation/Foundation.h>
#import <EndpointSecurity/EndpointSecurity.h>
//convert es_string_token_t to string
NSString* convertStringToken(es_string_token_t* stringToken);
#endif /* utilities_h */
+35
View File
@@ -0,0 +1,35 @@
//
// utilities.m
// ProcessMonitor
//
// Created by Patrick Wardle on 9/1/19.
// Copyright © 2019 Objective-See. All rights reserved.
//
#import "utilities.h"
//convert es_string_token_t to string
NSString* convertStringToken(es_string_token_t* stringToken)
{
//string
NSString* string = nil;
//init to empty string
string = [NSString string];
//sanity check(s)
if( (NULL == stringToken) ||
(0 == stringToken->length) ||
(NULL == stringToken->data) )
{
//bail
goto bail;
}
//convert to data, then to string
string = [NSString stringWithUTF8String:[[NSData dataWithBytes:stringToken->data length:stringToken->length] bytes]];
bail:
return string;
}