forked from theevilbit/Shield
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ProcessMonitor.m
160 lines (124 loc) · 4.84 KB
/
ProcessMonitor.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
//
// ProcessMonitor.m
// ProcessMonitor
//
// 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 "ProcessMonitor.h"
#import "../Common/Constants.h"
#import <Foundation/Foundation.h>
#import <EndpointSecurity/EndpointSecurity.h>
//endpoint
es_client_t* endpointClient = nil;
@implementation ProcessMonitor
//start monitoring
// pass in events of interest, count of said events, flag for codesigning, and callback
-(BOOL)start:(es_event_type_t*)events count:(uint32_t)count csOption:(NSUInteger)csOption callback:(ProcessCallbackBlock)callback
{
//flag
BOOL started = NO;
//check if already running
//result
es_new_client_result_t result = 0;
//sync
@synchronized (self) {
//create client
// callback invokes (user) callback for new processes
result = es_new_client(&endpointClient, ^(es_client_t *client,const es_message_t *message)
{
//new process event
Process* process = nil;
//init process obj
// do static check as well
process = [[Process alloc] init:(es_message_t* _Nonnull)message csOption:csOption];
if(nil != process)
{
//invoke user callback
callback(process, client, (es_message_t* _Nonnull)message);
}
});
if(result == ES_NEW_CLIENT_RESULT_SUCCESS) logMsg(LOG_TO_FILE|LOG_NOTICE, @"SUCCESS: es_new_client() registered");
//error?
if(ES_NEW_CLIENT_RESULT_SUCCESS != result)
{
//err msg
logMsg(LOG_TO_FILE|LOG_ERR, @"ERROR: es_new_client() failed");
//provide more info
switch (result) {
//not entitled
case ES_NEW_CLIENT_RESULT_ERR_NOT_ENTITLED:
logMsg(LOG_TO_FILE|LOG_ERR, @"ES_NEW_CLIENT_RESULT_ERR_NOT_ENTITLED: \"The caller is not properly entitled to connect\"");
break;
//not permitted
case ES_NEW_CLIENT_RESULT_ERR_NOT_PERMITTED:
logMsg(LOG_TO_FILE|LOG_ERR, @"ES_NEW_CLIENT_RESULT_ERR_NOT_PERMITTED: \"The caller is not permitted to connect. They lack Transparency, Consent, and Control (TCC) approval form the user.\"");
break;
//not privileged
case ES_NEW_CLIENT_RESULT_ERR_NOT_PRIVILEGED:
logMsg(LOG_TO_FILE|LOG_ERR, @"ES_NEW_CLIENT_RESULT_ERR_NOT_PRIVILEGED: \"The caller is not running as root\"");
break;
default:
break;
}
//bail
goto bail;
}
//clear cache
if(ES_CLEAR_CACHE_RESULT_SUCCESS != es_clear_cache(endpointClient))
{
//err msg
logMsg(LOG_TO_FILE|LOG_ERR, @"ERROR: es_clear_cache() failed");
//bail
goto bail;
}
//subscribe
if(ES_RETURN_SUCCESS != es_subscribe(endpointClient, events, count))
{
//err msg
logMsg(LOG_TO_FILE|LOG_ERR, @"ERROR: es_subscribe() failed");
//bail
goto bail;
}
} //sync
//happy
started = YES;
bail:
return started;
}
//stop
-(BOOL)stop
{
//flag
BOOL stopped = NO;
//sync
@synchronized (self) {
//unsubscribe & delete
//unsubscribe
if(ES_RETURN_SUCCESS != es_unsubscribe_all(endpointClient))
{
//err msg
logMsg(LOG_TO_FILE|LOG_ERR, @"ERROR: es_unsubscribe_all() failed");
//bail
goto bail;
}
//delete client
if(ES_RETURN_SUCCESS != es_delete_client(endpointClient))
{
//err msg
logMsg(LOG_TO_FILE|LOG_ERR, @"ERROR: es_delete_client() failed");
//bail
goto bail;
}
//unset
endpointClient = NULL;
//happy
stopped = YES;
} //sync
bail:
return stopped;
}
@end