diff --git a/README.md b/README.md index 3104686..214b194 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Each article directory contains three subdirectories: * ☑ [DYLD — Do You Like Death? (III)](https://karol-mazurek.medium.com/dyld-do-you-like-death-iii-af77701a3034?sk=v2%2F06c92503-2db9-40e2-b139-c9ae0a35e7b3) - handleDyldInCache | DYLD_IN_CACHE | restartWithDyldInCache | dyld_all_image_infos | calculating offset for debugging Dyld in Cache * ☑ [DYLD — Do You Like Death? (IV)](https://karol-mazurek.medium.com/dyld-do-you-like-death-iv-ede6b157752c?sk=v2%2F87ebe38d-004c-41a6-bc1f-43898494a512) - RuntimeLocks | MemoryManager | dyld_hw_tpro | Lambda Capture | withWritableMemory | PAC | arm64e_preview_abi | __ptrauth_dyld_tpro0 | WriteProtectionState | previousState | os_compiler_barrier | * ☑ [DYLD — Do You Like Death? (V)](https://karol-mazurek.medium.com/dyld-do-you-like-death-v-c40a267573cb?sk=v2%2F4c9f16b2-59bd-406a-945d-10a1fba1001b) - Linker Standard Library | EphemeralAllocator | Dyld Private Memory | PersistentAllocator | vm_allocate | vm_protect | _kernelrpc_mach_vm_allocate_trap | _kernelrpc_mach_vm_protect_trap - * ☐ [DYLD — Do You Like Death? (VI)]() - ProcessConfig | AMFI + * ☐ [DYLD — Do You Like Death? (VI)](https://karol-mazurek.medium.com/dyld-do-you-like-death-vi-1013a69118ff?sk=v2%2F37b3a61f-8483-4b38-977d-7f860944862b) - ProcessConfig | Process::Process | Process::Security | csr_check | CSR_ALLOW_APPLE_INTERNAL | csrctl | syscall_csr_check | AMFI | internalInstall | isRestricted | isFairPlayEncrypted | amfiFlags | amfi_check_dyld_policy_self | ___sandbox_ms | ___mac_syscall | mpo_policy_syscall_t | MAC policy | com.apple.driver.AppleMobileFileIntegrity | _policy_syscall | _check_dyld_policy_internal | macos_Dyld_policy_collect_state | logDyldPolicyData | DYLD_AMFI_FAKE | getAMFI | pruneEnvVars | com.apple.security.cs.allow-dyld-environment-variables * ☐ [VI. AMFI]() diff --git a/V. Dyld/python/CrimsonUroboros.py b/V. Dyld/python/CrimsonUroboros.py index 14ca89e..fee1ce3 100755 --- a/V. Dyld/python/CrimsonUroboros.py +++ b/V. Dyld/python/CrimsonUroboros.py @@ -1620,7 +1620,7 @@ class ArgumentParser: dyld_group.add_argument('--compiled_with_dyld_env', action='store_true', default=False, help="Check if binary was compiled with -dyld_env flag and print the environment variables and its values.") dyld_group.add_argument('--has_interposing', action='store_true', default=False, help="Check if binary has interposing sections.") dyld_group.add_argument('--interposing_symbols', action='store_true', default=False, help="Print interposing symbols if any.") - + def parseArgs(self): return self.parser.parse_args() diff --git a/VI. AMFI/custom/AMFI_RE/GHIDRA_macos_dyld_policy_at_path.c b/VI. AMFI/custom/AMFI_RE/GHIDRA_macos_dyld_policy_at_path.c new file mode 100644 index 0000000..c7e45bc --- /dev/null +++ b/VI. AMFI/custom/AMFI_RE/GHIDRA_macos_dyld_policy_at_path.c @@ -0,0 +1,41 @@ + +/* macos_dyld_policy_at_path(proc*, amfi_dyld_policy_state_t*) */ + +undefined8 macos_dyld_policy_at_path(proc *process,amfi_dyld_policy_state_t *policy_state) + +{ + int is_restricted_fp; + undefined8 allowAtPaths; + char *log_message; + uint flags; + + if ((*(uint *)policy_state & 0x10800) == 0) { + is_restricted_fp = procIsDyldsRestricted(policy_state); + if (is_restricted_fp == 0) { +check_CS_FORCED_LV: + is_restricted_fp = procIsDyldsRestricted(policy_state); + if ((is_restricted_fp == 0) || (((byte)*policy_state >> 4 & 1) != 0)) + goto set_allowAtPaths_to_1; + log_message = "process is not hardened, restricted and does not use Library Validation"; + } + else { + flags = *(uint *)policy_state; + if ((flags >> 6 & 1) == 0) goto check_CS_FORCED_LV; + if ((flags >> 5 & 1) == 0) { + if ((flags >> 4 & 1) != 0) goto set_allowAtPaths_to_1; + log_message = "platform process is restricted and does not use Library Validation"; + } + else { + log_message = "platform process is restricted and is not signed with Library Validation"; + } + } + logDyldPolicyRejection(process,"relative path loading disallowed",log_message); + allowAtPaths = 0; + } + else { +set_allowAtPaths_to_1: + allowAtPaths = 1; + } + return allowAtPaths; +} + diff --git a/VI. AMFI/custom/AMFI_RE/PSEUDO_macos_dyld_policy_at_path.c b/VI. AMFI/custom/AMFI_RE/PSEUDO_macos_dyld_policy_at_path.c new file mode 100644 index 0000000..8ed46c7 --- /dev/null +++ b/VI. AMFI/custom/AMFI_RE/PSEUDO_macos_dyld_policy_at_path.c @@ -0,0 +1,41 @@ +// Set amfiFlags->allowEnvVarsPrint (AMFI_DYLD_OUTPUT_ALLOW_PRINT_VARS) +// RPL == Relative Path Loading +// HR == Hardening Runtime +// LV == Library Validation +// RP == Restricted Process +// RPP == Restricted Platform Process + +macos_dyld_policy_at_path(proc *process, amfi_dyld_policy_state_t *policy_state) { + uint flags = policy_state->flags; + + // Check if process is not restricted (CS_RUNTIME == 0x10000 and CS_RESTRICT == 0x800): + if ((flags & 0x10800) == 0) { + + // Check if the process is not forcibly restricted + int is_restricted = procIsDyldsRestricted(policy_state); + if (is_restricted == 0) { + + // Check if the process does not use Library Validation (CS_FORCED_LV == 0x10): + if ((flags & 0x10) == 0) { + log("RPL: 0, HR: 0, RP: 0, LV: 0"); + } + } else { + // 0x40 == CS_EXECSEG_JIT used ?? (not sure aobut it) + if ((flags & 0x40) != 0) { + + // (macOS Only) Page invalidation allowed by task port policy (CS_INVALID_ALLOWED == 0x20) not used + if ((flags & 0x20) == 0) { + + // Check if process does not use Library Validation + if ((flags & 0x10) == 0) { + log("RPL: 0, PPR: 1, LV: 0"); + } + } else { + log("RPL: 0, PPR: 1, LV: 0"); + } + } + } + allowAtPaths == 0; + } + allowAtPaths == 1; +} diff --git a/VI. AMFI/python/check_amfi.py b/VI. AMFI/python/check_amfi.py new file mode 100644 index 0000000..8c78e26 --- /dev/null +++ b/VI. AMFI/python/check_amfi.py @@ -0,0 +1,20 @@ +import sys +flags = { + "AMFI_DYLD_OUTPUT_ALLOW_AT_PATH": 1, + "AMFI_DYLD_OUTPUT_ALLOW_PATH_VARS": 2, + "AMFI_DYLD_OUTPUT_ALLOW_CUSTOM_SHARED_CACHE": 4, + "AMFI_DYLD_OUTPUT_ALLOW_FALLBACK_PATHS": 8, + "AMFI_DYLD_OUTPUT_ALLOW_PRINT_VARS": 16, + "AMFI_DYLD_OUTPUT_ALLOW_FAILED_LIBRARY_INSERTION": 32, + "AMFI_DYLD_OUTPUT_ALLOW_LIBRARY_INTERPOSING": 64, + "AMFI_DYLD_OUTPUT_ALLOW_EMBEDDED_VARS": 128 +} +def check_flags(value): + return [flag_name for flag_name, flag_value in flags.items() if value & flag_value] + +input_value = int(sys.argv[1], 16) +set_flags = check_flags(input_value) + +if set_flags: + print("Flags set:") + print(*set_flags, sep="\n" \ No newline at end of file