diff --git a/README.md b/README.md index 245e0f3..796a1b3 100644 --- a/README.md +++ b/README.md @@ -26,9 +26,15 @@ Each article directory contains three subdirectories: * ☑ [DYLD — Do You Like Death? (X)](https://karol-mazurek.medium.com/dyld-do-you-like-death-x-76408570c357?sk=v2%2F8b69c2f1-ce13-4d05-bba1-e0164c3de381) - ExternallyViewableState | externallyViewable.init | dyld_all_image_info | exec_prefault_data | task_info | com.apple.security.get-task-allow | get_dyld_info | lsl:Vector | ProcessSnapshot | compact info | makeUnique | release | setDyldState | setInitialExternallyVisibleState | setShareCacheInfo | setDyld | inDyldCache | DYLD_IN_CACHE | recordFromInfo | FileRecord | Image | addImage | _snapshot | addImageInfo | setInitialImageCount | commit | compactInfoData | RemoteNotificationResponder * ☑ [DYLD — Do You Like Death? (XI)](https://karol-mazurek.medium.com/dyld-do-you-like-death-xi-cef76bc8dc14?sk=v2%2F0b88b392-ae94-43d0-9120-109306051e00) - prepare | APIs | isSimulatorPlatform | state.initializeClosureMode() | PrebuiltLoaders | JustInTimeLoader | PrebuilLoaderSet | dyld3 | dyld4 | Closures | initializeClosureMode | Loaders | validHeader | hasValidMagic | kmagic | dontUsePrebuiltForApp | findLaunchLoaderSet | cachePBLS | hasLaunchLoaderSetWithCDHash | findLaunchLoaderSetWithCDHash | findLaunchLoaderSet | allowOsProgramsToSaveUpdatedClosures | reserve | bit_ceil | allowNonOsProgramsToSaveUpdatedClosures | DYLD_USE_CLOSURES | reserveExact | getOnDiskBinarySliceOffset | STACK_ALLOC_OVERFLOW_SAFE_ARRAY | topLevelLoaders | loadDependents | notifyDebuggerLoad | notifyDtrace | DOF | addPermamentRanges | STACK_ALLOC_ARRAY | weakDefMap | buildInterposingTables | handleStrongWeakDefOverrides | visibility | applyFixups | applyCachePatches | doSingletonPatching | applyInterposingToDyldCache | Libdyld.dylib | libdyld4Section | allImageInfos | storeProcessInfoPointer | __chkstk_darwin | partitionDelayLoads | DYLD_JUST_BUILD_CLOSURE | prewarming | notifyMonitorNeeded | LC_MAIN | LC_THREAD | getEntry | appMain | restorePreviousState | TPRO | libSystemHelpers | __exit * ☑ [VI. AMFI](https://karol-mazurek.medium.com/snake-apple-vi-amfi-31c48fb92d33?sk=v2%2F8116bf86-e0a7-42be-ada9-5348447c01fd) +* ☐ [VII. Antivirus]() +* ☐ [VIII. Sandbox]() +* ☐ [IX. Process]() +* ☐ [X. NU]() + * ☑ [Kernel Debugging Setup on MacOS](https://karol-mazurek.medium.com/kernel-debugging-setup-on-macos-07dd8c86cdb6?sk=v2%2F782bf539-a057-4f14-bbe7-f8e1ace26701) + ## TOOLS -[CrimsonUroboros](#crimsonuroboros) • [MachOFileFinder](#machofilefinder) • [TrustCacheParser](#trustcacheparser) • [SignatureReader](#signaturereader) • [extract_cms.sh](#extract_cmssh) • [ModifyMachOFlags](#modifymachoflags) • [LCFinder](#lcfinder) • [MachODylibLoadCommandsFinder](#machodylibloadcommandsfinder) +[CrimsonUroboros](#crimsonuroboros) • [MachOFileFinder](#machofilefinder) • [TrustCacheParser](#trustcacheparser) • [SignatureReader](#signaturereader) • [extract_cms.sh](#extract_cmssh) • [ModifyMachOFlags](#modifymachoflags) • [LCFinder](#lcfinder) • [MachODylibLoadCommandsFinder](#machodylibloadcommandsfinder) •[AMFI_test.sh](VI.%20AMFI/custom/AMFI_test.sh) *** ### [CrimsonUroboros](tests/CrimsonUroboros.py) diff --git a/VII. Antivirus/mac/_hook_vnode_check_setextattr.c b/VII. Antivirus/mac/_hook_vnode_check_setextattr.c new file mode 100644 index 0000000..7e3c77d --- /dev/null +++ b/VII. Antivirus/mac/_hook_vnode_check_setextattr.c @@ -0,0 +1,56 @@ +bool __fastcall hook_vnode_check_setextattr(__int64 a1, __int64 a2, __int64 a3, const char *a4) +{ + _BOOL8 v4; // x20 + __int64 v5; // x16 + __int64 v7; // x0 + __int64 v8; // x19 + os_ref_atomic_t *v9; // x21 + __int64 v10; // x0 + __int64 v11; // x0 + __int64 v12; // x1 + __int64 v13; // x0 + __int64 v14; // x1 + + v4 = 0LL; + if ( a1 && sandbox_enforce ) + { + v5 = *(_QWORD *)(a1 + 120); + if ( v5 && (v7 = mac_label_get(v5, (unsigned int)label_slot)) != 0 ) + { + v8 = v7; + os_ref_retain_external((os_ref_atomic_t *)(v7 + 16), 0LL); + if ( *(_QWORD *)v8 + && (os_ref_retain_external((os_ref_atomic_t *)(*(_QWORD *)v8 + 60LL), 0LL), (v9 = *(os_ref_atomic_t **)v8) != 0LL) ) + { + v4 = (v9[14] & 2) != 0 && strcmp(a4, "com.apple.quarantine") == 0; + if ( !os_ref_release_barrier_external(v9 + 15, 0LL) ) + { + if ( *((_QWORD *)v9 + 6) ) + matchFree(); + v10 = *(_QWORD *)v9; + *(_QWORD *)v9 = 0LL; + kfree_data_addr(v10); + v11 = *((_QWORD *)v9 + 2); + v12 = *((_QWORD *)v9 + 3); + *((_QWORD *)v9 + 2) = 0LL; + kfree_data(v11, v12); + v13 = *((_QWORD *)v9 + 4); + v14 = *((_QWORD *)v9 + 5); + *((_QWORD *)v9 + 4) = 0LL; + kfree_data(v13, v14); + kfree_type_impl(&qtnstate_destroy_kalloc_type_view_281, v9); + } + } + else + { + v4 = 0LL; + } + cred_label_rele(v8); + } + else + { + return 0LL; + } + } + return v4; +} \ No newline at end of file diff --git a/VII. Antivirus/python/CrimsonUroboros.py b/VII. Antivirus/python/CrimsonUroboros.py index 27379c3..c56c570 100755 --- a/VII. Antivirus/python/CrimsonUroboros.py +++ b/VII. Antivirus/python/CrimsonUroboros.py @@ -2452,6 +2452,12 @@ class AntivirusProcessor: if args.has_quarantine: # Print if quarantine is set on file print("QUARANTINE: " + str(snake_instance.hasQuarantine())) + if args.remove_quarantine: # Remoe quarantine from a file + snake_instance.removeQuarantine() + + if args.add_quarantine: # Add quarantine to a file + snake_instance.addQuarantine() + class SnakeVII(SnakeVI): def __init__(self, binaries, file_path): super().__init__(binaries, file_path) @@ -2500,7 +2506,18 @@ class SnakeVII(SnakeVI): if "com.apple.quarantine" in all_atributes: return True return False - + + def removeQuarantine(self): + ''' Remove com.apple.quarantine extended attribute from the file. ''' + xattr.removexattr(self.file_path, 'com.apple.quarantine') + + def addQuarantine(self): + ''' Add com.apple.quarantine extended attribute to the file. ''' + value = f'0082;{int(time.time())};CrimsonUroboros;' + value_as_bytes = value.encode() + xattr.setxattr(self.file_path, 'com.apple.quarantine', value_as_bytes) + + ### --- ARGUMENT PARSER --- ### class ArgumentParser: def __init__(self): @@ -2628,6 +2645,8 @@ class ArgumentParser: antivirus_group.add_argument('--xattr_value', metavar='xattr_name', help="Print single extended attribute value") antivirus_group.add_argument('--xattr_all', action='store_true', help="Print all extended attributes names and their values") antivirus_group.add_argument('--has_quarantine', action='store_true', help="Check if the file has quarantine extended attribute") + antivirus_group.add_argument('--remove_quarantine', action='store_true', help="Remove com.apple.quarantine extended attribute from the file") + antivirus_group.add_argument('--add_quarantine', action='store_true', help="Add com.apple.quarantine extended attribute to the file") diff --git a/X. NU/mac/DEF CON 25 - Min-Spark-Zheng-macOS-iOS-Kernel-Debugging.pdf b/X. NU/mac/DEF CON 25 - Min-Spark-Zheng-macOS-iOS-Kernel-Debugging.pdf new file mode 100644 index 0000000..7181323 Binary files /dev/null and b/X. NU/mac/DEF CON 25 - Min-Spark-Zheng-macOS-iOS-Kernel-Debugging.pdf differ diff --git a/tests/test_CrimsonUroboros.py b/tests/test_CrimsonUroboros.py index ba9ff67..80edd63 100644 --- a/tests/test_CrimsonUroboros.py +++ b/tests/test_CrimsonUroboros.py @@ -1951,7 +1951,7 @@ class TestSnakeVII(): expected_output = '30 30 38 33 3b 30 30 30 30 30 30 30 30 3b 53 61' assert expected_output in uroboros_output - + def test_has_quarantine(self): '''Test the --has_quarantine flag of SnakeVII.''' args_list = ['-p', "hello_7", '--has_quarantine'] @@ -1968,3 +1968,38 @@ class TestSnakeVII(): assert expected_output in uroboros_output + def test_remove_quarantine(self): + '''Test the --remove_quarantine flag of SnakeVII.''' + args_list = ['-p', "hello_7", '--remove_quarantine'] + args, file_path = argumentWrapper(args_list) + + def code_block(): + macho_processor = MachOProcessor(file_path) + macho_processor.process(args) + antivirus_processor = AntivirusProcessor() + antivirus_processor.process(args) + + uroboros_output = executeCodeBlock(code_block) + expected_output_1 = '' + expected_output_2 = 'com.apple.quarantine:' + + assert expected_output_1 in uroboros_output + assert expected_output_2 not in run_and_get_stdout("xattr -l hello_7") + + def test_add_quarantine(self): + '''Test the --add_quarantine flag of SnakeVII.''' + args_list = ['-p', "hello_7", '--add_quarantine'] + args, file_path = argumentWrapper(args_list) + + def code_block(): + macho_processor = MachOProcessor(file_path) + macho_processor.process(args) + antivirus_processor = AntivirusProcessor() + antivirus_processor.process(args) + + uroboros_output = executeCodeBlock(code_block) + expected_output_1 = '' + expected_output_2 = 'com.apple.quarantine:' + + assert expected_output_1 in uroboros_output + assert expected_output_2 in run_and_get_stdout("xattr -l hello_7")