-
Notifications
You must be signed in to change notification settings - Fork 34
/
Copy pathDylibInserts.m
executable file
·403 lines (328 loc) · 10.9 KB
/
DylibInserts.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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
//
// LaunchItems.m
// KnockKnock
//
#import "File.h"
#import "Utilities.h"
#import "AppDelegate.h"
#import "DylibInserts.h"
/*
# for launch agents
# edit com.blah.blah.plist
# <key>EnvironmentVariables</key>
# <dict>
# <key>DYLD_INSERT_LIBRARIES</key>
# <string>/path/to/dylib</string>
# </dict>
#
# for apps
# <key>LSEnvironment</key>
# <dict>
# <key>DYLD_INSERT_LIBRARIES</key>
# <string>/path/to/dylib</string>
# </dict>
# /System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -v -f /Applications/ApplicationName.app
*/
//plugin name
#define PLUGIN_NAME @"Library Inserts"
//plugin description
#define PLUGIN_DESCRIPTION NSLocalizedString(@"libs inserted by DYLD_INSERT_LIBRARIES", @"libs inserted by DYLD_INSERT_LIBRARIES")
//plugin icon
#define PLUGIN_ICON @"dylibIcon"
//(base) directory that has overrides for launch* and apps
#define OVERRIDES_DIRECTORY @"/private/var/db/launchd.db/"
@implementation DylibInserts
//init
// ->set name, description, etc
-(id)init
{
//super
self = [super init];
if(self)
{
//set name
self.name = PLUGIN_NAME;
//set description
self.description = PLUGIN_DESCRIPTION;
//set icon
self.icon = PLUGIN_ICON;
}
return self;
}
//scan for launch items and installed applications
// ->looking for plists that contain DYLD_INSERT_LIBRARYs
-(void)scan
{
//dbg msg
//NSLog(@"%@: scanning", PLUGIN_NAME);
//scan for launch items w/ DYLD_INSERT_LIBRARIES or __XPC_DYLD_INSERT_LIBRARIES
// ->will report any findings to UI
[self scanLaunchItems];
//scan for applications w/ DYLD_INSERT_LIBRARIES or __XPC_DYLD_INSERT_LIBRARIES
// ->will report any findings to UI
[self scanApplications];
return;
}
//scan all launch items
// ->looks in their plists for DYLD_INSERT_LIBRARIES or __XPC_DYLD_INSERT_LIBRARIES
-(void)scanLaunchItems
{
//all launch items
NSArray* launchItems = nil;
//disable items
NSArray* disabledItems = nil;
//plist data
NSDictionary* plistContents = nil;
//environment var dictionary
NSDictionary* enviroVars = nil;
//path to inserted dylib
NSString* dylibPath = nil;
//detected (auto-started) login item
File* fileObj = nil;
//wait for shared item enumerator to complete enumeration of launch items
do
{
//nap
[NSThread sleepForTimeInterval:0.1f];
//try grab launch items
// ->will only !nil, when enumeration is complete
launchItems = sharedItemEnumerator.launchItems;
//keep trying until we get em!
} while(nil == launchItems);
//get disabled items
disabledItems = [self getDisabledItems];
//iterate over all launch items
// ->scan/process each
for(NSString* launchItemPlist in launchItems)
{
//load launch item's plist
plistContents = [NSDictionary dictionaryWithContentsOfFile:launchItemPlist];
/*
//skip disabled launch items
if(YES == [disabledItems containsObject:plistContents[@"Label"]])
{
//skip
continue;
}
//skip items that aren't auto launched
// ->neither 'RunAtLoad' *and* 'KeepAlive' is set to YES
if( (YES != [plistContents[@"RunAtLoad"] isKindOfClass:[NSNumber class]]) ||
(YES != [plistContents[@"RunAtLoad"] boolValue]) )
{
//also check 'KeepAlive'
if( (YES != [plistContents[@"KeepAlive"] isKindOfClass:[NSNumber class]]) ||
(YES != [plistContents[@"KeepAlive"] boolValue]) )
{
//skip
continue;
}
}
*/
//extact environment vars dictionary
enviroVars = plistContents[LAUNCH_ITEM_DYLD_KEY];
//skip apps that don't have env var dictionary w/ 'DYLD_INSERT_LIBRARIES' or '__XPC_DYLD_INSERT_LIBRARIES'
if( (nil == enviroVars) ||
(YES != [enviroVars isKindOfClass:[NSDictionary class]]) ||
( (nil == enviroVars[@"DYLD_INSERT_LIBRARIES"]) && (nil == enviroVars[@"__XPC_DYLD_INSERT_LIBRARIES"]) ))
{
//skip
continue;
}
//grab dylib path
// ->first attempt via 'DYLD_INSERT_LIBRARIES'
if(nil != enviroVars[@"DYLD_INSERT_LIBRARIES"])
{
//grab
dylibPath = enviroVars[@"DYLD_INSERT_LIBRARIES"];
}
//grab dylib path
// ->check in '__XPC_DYLD_INSERT_LIBRARIES'
else
{
//grab
dylibPath = enviroVars[@"__XPC_DYLD_INSERT_LIBRARIES"];
}
//create File object for injected dylib
// ->skip those that err out for any reason
if(nil == (fileObj = [[File alloc] initWithParams:@{KEY_RESULT_PLUGIN:self, KEY_RESULT_PATH:dylibPath, KEY_RESULT_PLIST:launchItemPlist}]))
{
//skip
continue;
}
//process item
// ->save and report to UI
[super processItem:fileObj];
}
return;
}
//scan all installed applications
// ->looks in their plists for DYLD_INSERT_LIBRARYs
-(void)scanApplications
{
//installed apps
NSArray* installedApps = nil;
//app's bundle
NSBundle* appBundle = nil;
//path to app's plist
NSURL* appPlist = nil;
//environment var dictionary
NSDictionary* enviroVars = nil;
//path to inserted dylib
NSString* dylibPath = nil;
//detected (auto-started) login item
File* fileObj = nil;
//wait for shared item enumerator to complete enumeration of installed apps
// ->give up after 5 minutes
for(NSUInteger i=0; i<(10*60)*5; i++)
{
//nap
[NSThread sleepForTimeInterval:0.1f];
//try grab installed apps
// ->will only !nil, when enumeration is complete
installedApps = sharedItemEnumerator.applications;
//exit loop once we have apps
if(nil != installedApps)
{
//break
break;
}
}//try up to 5 minutes?
//make sure installed apps were found
// ->i.e. didn't time out
if(nil == installedApps)
{
//bail
goto bail;
}
//iterate over all install apps
// ->scan/process each
for(NSDictionary* installedApp in installedApps)
{
//skip apps that don't have paths
if(nil == installedApp[@"path"])
{
//skip
continue;
}
//try grab app's bundle
appBundle = [NSBundle bundleWithPath:installedApp[@"path"]];
//skip apps that don't have bundle/info dictionary
if( (nil == appBundle) ||
(nil == appBundle.infoDictionary) )
{
//skip
continue;
}
//extact environment vars dictionary
enviroVars = appBundle.infoDictionary[APPLICATION_DYLD_KEY];
//skip apps that don't have env var dictionary w/ 'DYLD_INSERT_LIBRARIES' or '__XPC_DYLD_INSERT_LIBRARIES'
if( (nil == enviroVars) ||
(YES != [enviroVars isKindOfClass:[NSDictionary class]]) ||
( (nil == enviroVars[@"DYLD_INSERT_LIBRARIES"]) && (nil == enviroVars[@"__XPC_DYLD_INSERT_LIBRARIES"]) ))
{
//skip
continue;
}
//get path to app's Info.plist
appPlist = appBundle.infoDictionary[@"CFBundleInfoPlistURL"];
//skip apps that this fails
if(nil == appPlist)
{
//skip
continue;
}
//grab dylib path
// ->first attempt via 'DYLD_INSERT_LIBRARIES'
if(nil != enviroVars[@"DYLD_INSERT_LIBRARIES"])
{
//grab
dylibPath = enviroVars[@"DYLD_INSERT_LIBRARIES"];
}
//grab dylib path
// ->will be in '__XPC_DYLD_INSERT_LIBRARIES'
else
{
//grab
dylibPath = enviroVars[@"__XPC_DYLD_INSERT_LIBRARIES"];
}
//create File object for injected dylib
// ->skip those that err out for any reason
if(nil == (fileObj = [[File alloc] initWithParams:@{KEY_RESULT_PLUGIN:self, KEY_RESULT_PATH:dylibPath, KEY_RESULT_PLIST:appPlist.path}]))
{
//skip
continue;
}
//process item
// ->save and report to UI
[super processItem:fileObj];
}
//bail
bail:
return;
}
//get all disabled launch items
// ->specified in various overrides.plist files
-(NSArray*)getDisabledItems
{
//disable items
NSMutableArray* disabledItems = nil;
//override directories
NSArray* overrideDirectories = nil;
//override path
NSString* overridePath = nil;
//overrides user id
uid_t overridesUserID = 0;
//override contents
NSDictionary* overrideContents = nil;
//alloc array
disabledItems = [NSMutableArray array];
//get all override directories
overrideDirectories = directoryContents(OVERRIDES_DIRECTORY, @"self BEGINSWITH 'com.apple.launchd'");
//iterate over all directories
// ->open/parse 'overrides.plist'
for(NSString* overrideDirectory in overrideDirectories)
{
//init full path
overridePath = [NSString stringWithFormat:@"%@%@%@", OVERRIDES_DIRECTORY, overrideDirectory, @"/overrides.plist"];
//skip files that don't exist/aren't accessible
if(YES != [[NSFileManager defaultManager] fileExistsAtPath:overridePath])
{
//try resolve
overridePath = which(overridePath);
if( (nil == overridePath) ||
(YES != [[NSFileManager defaultManager] fileExistsAtPath:overridePath]))
{
//skip
continue;
}
}
//extract overrides UID from its directory name
// ->e.g. 'com.apple.launchd.peruser.501' -> 501
overridesUserID = [[overrideDirectory pathExtension] intValue];
//for override UID's over 500
// ->ignore unless it matches current users
if( (overridesUserID > 500) &&
(overridesUserID != getuid()) )
{
//skip
continue;
}
//load override plist
overrideContents = [NSDictionary dictionaryWithContentsOfFile:overridePath];
//iterate over all items in override plist file
// ->save any that are disabled
for(NSString* overrideItem in overrideContents)
{
//skip enabled items
if(YES != [overrideContents[overrideItem][@"Disabled"] boolValue])
{
//skip
continue;
}
//save disabled item
[disabledItems addObject:overrideItem];
}
}
return disabledItems;
}
@end