mirror of
https://github.com/Karmaz95/Snake_Apple.git
synced 2026-05-19 16:58:03 +02:00
This commit is contained in:
@@ -303,4 +303,7 @@ Each Snake class will be a child of the previous one and infinitely "eat itself"
|
||||
* Make testing branch and implement tests, before pushing new updates.
|
||||
* Create `RottenApple.app` in another repository and use it for testing.
|
||||
* Add Dyld Closure chapter to Snake&Apple V - Dyld
|
||||
* Move `dumpPrelink_info` and `dumpPrelink_text` to Snake & Apple chapter about Kernel Extensions when ready.
|
||||
* Move `kext_prelinkinfo`, `dumpPrelink_info` and `dumpPrelink_text` to Snake & Apple chapter about Kernel Extensions when ready.
|
||||
* Add kernelcache parser.
|
||||
* Add `LC_FILESET_ENTRY` method to `dumpKernelExtension`.
|
||||
* Consider moving methods like `removeNullBytesAlignment`, `calcTwoComplement64` etc. to `Utils` class.
|
||||
@@ -0,0 +1,215 @@
|
||||
void _initializeAppleMobileFileIntegrity(void)
|
||||
|
||||
{
|
||||
bool bVar1;
|
||||
int iVar2;
|
||||
int iVar3;
|
||||
undefined8 uVar4;
|
||||
ulong uVar5;
|
||||
long *plVar6;
|
||||
long lVar7;
|
||||
uint local_d4;
|
||||
ulong local_d0;
|
||||
undefined8 uStack_c8;
|
||||
undefined8 uStack_c0;
|
||||
undefined8 uStack_b8;
|
||||
undefined8 local_b0;
|
||||
undefined8 uStack_a8;
|
||||
undefined8 uStack_a0;
|
||||
undefined8 local_98;
|
||||
undefined8 local_90;
|
||||
undefined8 uStack_88;
|
||||
undefined8 uStack_80;
|
||||
undefined8 uStack_78;
|
||||
undefined8 local_70;
|
||||
undefined8 uStack_68;
|
||||
undefined8 uStack_60;
|
||||
undefined8 uStack_58;
|
||||
undefined8 local_50;
|
||||
undefined8 uStack_48;
|
||||
undefined8 local_38;
|
||||
|
||||
local_38 = *(undefined8 *)PTR_DAT_fffffe0007e6ba68;
|
||||
uVar4 = func_0xfffffe0008c3cf30();
|
||||
func_0xfffffe00085a8e38();
|
||||
uVar5 = func_0xfffffe0008bbcd34(0,uVar4,&_driverLock);
|
||||
if ((uVar5 & 1) == 0) {
|
||||
return;
|
||||
}
|
||||
_AMFILockGroup = func_0xfffffe00085a8478("AMFI",0);
|
||||
initLibraryConstraints();
|
||||
_overrideUnrestrictedDebugging = 0;
|
||||
func_0xfffffe0008aa1474(&_sysctl__hw_features_allows_security_research);
|
||||
_allows_security_research = 0;
|
||||
uStack_48 = 0;
|
||||
local_50 = 0;
|
||||
uStack_68 = 0;
|
||||
local_70 = 0;
|
||||
uStack_58 = 0;
|
||||
uStack_60 = 0;
|
||||
uStack_88 = 0;
|
||||
local_90 = 0;
|
||||
uStack_78 = 0;
|
||||
uStack_80 = 0;
|
||||
uStack_a8 = 0;
|
||||
local_b0 = 0;
|
||||
local_98 = 0;
|
||||
uStack_a0 = 0;
|
||||
uStack_c8 = 0;
|
||||
local_d0 = 0;
|
||||
uStack_b8 = 0;
|
||||
uStack_c0 = 0;
|
||||
uVar4 = func_0xfffffe0009915f8c();
|
||||
iVar2 = func_0xfffffe0009910330(uVar4,&local_d0);
|
||||
if (iVar2 != 0) {
|
||||
func_0xfffffe0008da4510("\"AMFI: No chip from IMG4? errno: %d\" @%s:%d");
|
||||
return;
|
||||
}
|
||||
if ((uStack_a0._5_1_ != '\0') || ((int)local_98 == 1)) {
|
||||
_allows_security_research = 1;
|
||||
}
|
||||
local_d4 = 0;
|
||||
iVar2 = func_0xfffffe0008d70830("amfi_allow_research",&local_d4,4);
|
||||
if ((iVar2 != 0) && (local_d4 != 0)) {
|
||||
func_0xfffffe0008c3c908("AMFI: Allowing research due to amfi_allow_research boot arg");
|
||||
_allows_security_research = 1;
|
||||
}
|
||||
local_d0 = local_d0 & 0xffffffff00000000;
|
||||
iVar2 = func_0xfffffe0008a49ecc(8);
|
||||
if (iVar2 == 0) {
|
||||
local_d4 = 0;
|
||||
func_0xfffffe0008d70830("amfi",&local_d4,4);
|
||||
iVar2 = func_0xfffffe0008d70830("amfi_unrestrict_task_for_pid",&local_d0,4);
|
||||
if (((iVar2 != 0) && ((int)local_d0 != 0)) || ((local_d4 & 1) != 0)) {
|
||||
func_0xfffffe0008c3c908("%s: unrestricted task_for_pid enabled by boot-arg\n");
|
||||
_overrideUnrestrictedDebugging = 1;
|
||||
_BootedDevice = 1;
|
||||
}
|
||||
iVar2 = func_0xfffffe0008d70830("amfi_dev_mode_policy",&local_d0,4);
|
||||
if ((iVar2 != 0) && ((int)local_d0 != 0)) {
|
||||
func_0xfffffe0008c3c908("%s: developer mode internal policy disabled by boot-arg\n");
|
||||
DAT_fffffe0007e74790 = 1;
|
||||
}
|
||||
iVar2 = func_0xfffffe0008d70830("amfi_allow_any_signature",&local_d0,4);
|
||||
if (((iVar2 != 0) && ((int)local_d0 != 0)) || (((byte)local_d4 >> 1 & 1) != 0)) {
|
||||
func_0xfffffe0008c3c908("%s: signature enforcement disabled by boot-arg\n");
|
||||
/* WARNING: Read-only address (ram,0xfffffe0007e7478b) is written */
|
||||
_DAT_fffffe0007e7478a = CONCAT11(DAT_fffffe0007e7478b,1);
|
||||
}
|
||||
iVar2 = func_0xfffffe0008d70830("amfi_get_out_of_my_way",&local_d0,4);
|
||||
if (((iVar2 != 0) && ((int)local_d0 != 0)) || ((local_d4 >> 7 & 1) != 0)) {
|
||||
func_0xfffffe0008c3c908("%s: signature enforcement disabled by boot-arg\n");
|
||||
_DAT_fffffe0007e7478a = 0x101;
|
||||
}
|
||||
if ((local_d4 >> 2 & 1) != 0) {
|
||||
func_0xfffffe0008c3c908
|
||||
("%s: library validation will not mark external binaries as platform\n");
|
||||
DAT_fffffe0007e7478f = 1;
|
||||
}
|
||||
iVar2 = func_0xfffffe0008d70830("amfi_unrestricted_local_signing",&local_d0,4);
|
||||
if ((iVar2 != 0) && ((int)local_d0 != 0)) {
|
||||
func_0xfffffe0008c3c908("%s: unrestricted AMFI local signing enabled by boot-arg\n");
|
||||
DAT_fffffe0007e7478c = 1;
|
||||
}
|
||||
}
|
||||
iVar2 = func_0xfffffe0008d70830("amfi_ready_to_roll",&local_d0,4);
|
||||
if ((iVar2 != 0) && ((int)local_d0 != 0)) {
|
||||
func_0xfffffe0008c3c908("%s: practice a key roll\n");
|
||||
_readyToRoll = 1;
|
||||
}
|
||||
iVar2 = func_0xfffffe0008d70830("cs_enforcement_disable",&local_d0,4);
|
||||
bVar1 = (int)local_d0 != 0;
|
||||
if (iVar2 != 0 && bVar1) {
|
||||
func_0xfffffe0008c3c908("%s: cs_enforcement disabled by boot-arg\n");
|
||||
iVar3 = func_0xfffffe0008a49ecc(8);
|
||||
if (iVar3 != 0) goto LAB_fffffe0009ac1ba8;
|
||||
}
|
||||
DAT_fffffe0007e7478e = iVar2 != 0 && bVar1;
|
||||
InitializeDenylist();
|
||||
_initializeCoreEntitlementsSupport(1);
|
||||
precookExemptionProfile();
|
||||
numJitHashCacheEntries = 0;
|
||||
jitHashCache = 0;
|
||||
jitHashCacheLock = func_0xfffffe0008c3cf30();
|
||||
dyldSimCacheLock = func_0xfffffe0008c3cf30();
|
||||
supplementalSigningInit();
|
||||
_swiftPlaygroundsJIT = '\x01';
|
||||
plVar6 = (long *)func_0xfffffe0008c45154("/",*(undefined8 *)PTR_DAT_fffffe0007e6bb00,0,0,0);
|
||||
if (plVar6 == (long *)0x0) {
|
||||
_initializeAppleMobileFileIntegrity();
|
||||
LAB_fffffe0009ac1ba0:
|
||||
_initializeAppleMobileFileIntegrity();
|
||||
}
|
||||
else {
|
||||
uVar4 = (**(code **)(*plVar6 + 0x2d8))(plVar6,"model");
|
||||
plVar6 = (long *)func_0xfffffe0008bbdca0(uVar4,*(undefined8 *)PTR_DAT_fffffe0007e6ba08);
|
||||
if (plVar6 == (long *)0x0) goto LAB_fffffe0009ac1ba0;
|
||||
uVar4 = (**(code **)(*plVar6 + 0x198))();
|
||||
func_0xfffffe0008c3c908("AMFI: queried model name from device tree: %s\n");
|
||||
lVar7 = func_0xfffffe00086ac444(uVar4,"iPhone",6);
|
||||
if (lVar7 == 0) {
|
||||
if (_swiftPlaygroundsJIT == '\0') goto LAB_fffffe0009ac17f4;
|
||||
}
|
||||
else {
|
||||
func_0xfffffe0008c3c908("AMFI: disabling Swift Playgrounds JIT services on iPhone devices\n");
|
||||
_swiftPlaygroundsJIT = '\0';
|
||||
LAB_fffffe0009ac17f4:
|
||||
func_0xfffffe0008ab4fe8(0x10000000);
|
||||
func_0xfffffe0008ab4fe8(0x20000000);
|
||||
}
|
||||
_unrestrictedCDHashLock = func_0xfffffe0008c3cf30();
|
||||
initTrustCacheAccess();
|
||||
DAT_fffffe0007e747d0 = _cred_check_label_update_execve;
|
||||
DAT_fffffe0007e747f8 = _cred_label_associate;
|
||||
DAT_fffffe0007e74808 = _cred_label_destroy;
|
||||
DAT_fffffe0007e74820 = _cred_label_init;
|
||||
DAT_fffffe0007e74830 = _cred_label_update_execve;
|
||||
DAT_fffffe0007e74b58 = _proc_check_inherit_ipc_ports;
|
||||
DAT_fffffe0007e75120 = _vnode_check_signature;
|
||||
DAT_fffffe0007e749a0 = _file_check_library_validation;
|
||||
DAT_fffffe0007e74b40 = _policy_initbsd;
|
||||
DAT_fffffe0007e74b48 = _policy_syscall;
|
||||
DAT_fffffe0007e74ab8 = _task_id_token_get_task;
|
||||
DAT_fffffe0007e747f0 = _cred_label_associate_kernel;
|
||||
DAT_fffffe0007e748f8 = _proc_check_launch_constraints;
|
||||
DAT_fffffe0007e74ba0 = amfi_exc_action_check_exception_send;
|
||||
DAT_fffffe0007e74ba8 = amfi_exc_action_label_associate;
|
||||
DAT_fffffe0007e74bb0 = amfi_exc_action_label_populate;
|
||||
DAT_fffffe0007e74bb8 = amfi_exc_action_label_destroy;
|
||||
DAT_fffffe0007e74bc0 = amfi_exc_action_label_init;
|
||||
DAT_fffffe0007e74bc8 = amfi_exc_action_label_update;
|
||||
DAT_fffffe0007e74d88 = macos_task_get_movable_control_port;
|
||||
DAT_fffffe0007e75178 = hsp_proc_check_map_anon;
|
||||
DAT_fffffe0007e74aa8 = macos_task_policy;
|
||||
DAT_fffffe0007e74ab0 = macos_task_policy;
|
||||
DAT_fffffe0007e74c88 = macos_task_control_policy;
|
||||
DAT_fffffe0007e75138 = macos_proc_check_run_cs_invalid;
|
||||
DAT_fffffe0007e75040 = hook_vnode_check_setextattr;
|
||||
DAT_fffffe0007e74fc0 = hook_vnode_check_getextattr;
|
||||
DAT_fffffe0007e748c0 = _file_check_mmap;
|
||||
DAT_fffffe0007e751c0 = _vnode_notify_open;
|
||||
DAT_fffffe0007e74cf8 = core_dump_policy;
|
||||
DAT_fffffe0007e75158 = supplementalVnodeCheckSignature;
|
||||
mac_policy = "AMFI";
|
||||
DAT_fffffe0007e75220 = "Apple Mobile File Integrity";
|
||||
DAT_fffffe0007e75228 = &_initializeAppleMobileFileIntegrity()::labelnamespaces;
|
||||
DAT_fffffe0007e75230 = 1;
|
||||
DAT_fffffe0007e75238 = &mac_ops;
|
||||
DAT_fffffe0007e75240 = 0;
|
||||
DAT_fffffe0007e75248 = &_amfi_mac_slot;
|
||||
DAT_fffffe0007e75250 = 0;
|
||||
iVar2 = func_0xfffffe0008d75b64(&mac_policy,&amfiPolicyHandle,0);
|
||||
if (iVar2 == 0) {
|
||||
configurationSettingsInit();
|
||||
hardeningInit();
|
||||
/* WARNING: Bad instruction - Truncating control flow here */
|
||||
halt_baddata();
|
||||
}
|
||||
}
|
||||
_initializeAppleMobileFileIntegrity();
|
||||
LAB_fffffe0009ac1ba8:
|
||||
_initializeAppleMobileFileIntegrity();
|
||||
func_0xfffffe0008c3c908("%s\n");
|
||||
func_0xfffffe0008da4510("\"Cannot unload AMFI - policy is not dynamic\\n\" @%s:%d");
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
// Initialization function for Apple's Mobile File Integrity (AMFI) system
|
||||
initializeAppleMobileFileIntegrity() {
|
||||
|
||||
// Allocating and locking mutex for thread safety
|
||||
lock = IOLockAlloc();
|
||||
lck_mtx_lock(lock);
|
||||
|
||||
// Checking if driver lock is not already set
|
||||
if (OSCompareAndSwapPtr(0, lock, &driverLock))
|
||||
// Initializing AMFI lock group
|
||||
AMFILockGroup = lck_grp_alloc_init("AMFI", 0);
|
||||
|
||||
// Initializing library constraints
|
||||
initLibraryConstraints();
|
||||
|
||||
// Registering system control variable
|
||||
sysctl_register_oid(&sysctl__hw_features_allows_security_research);
|
||||
|
||||
// Selecting personalized chip(pointer to img4_chip_t)
|
||||
chip = img4_chip_select_personalized_ap();
|
||||
|
||||
// Instantiating chip and checking for errors
|
||||
chip_error = img4_chip_instantiate(chip);
|
||||
if (chip_error)
|
||||
panic("AMFI: No chip from IMG4? errno" + chip_error);
|
||||
|
||||
// Checking chip properties to enable security research (Apple Security Research Device Program - https://security.apple.com/research-device/?)
|
||||
if (allow_security_reserach(chip))
|
||||
allows_security_research = 1;
|
||||
|
||||
// Checking for boot-arg, e.g.:
|
||||
// sudo nvram boot-args="amfi_get_out_of_my_way=1"
|
||||
if (PE_parse_boot_argn("amfi_allow_research"))
|
||||
IOLog("AMFI: Allowing research due to amfi_allow_research boot-arg");
|
||||
allows_security_research = 1;
|
||||
|
||||
// Without this boor-arg, the entitlements get-task-allow and task_for_pid-allow are required to use task_for_pid if binary is signed
|
||||
if (PE_parse_boot_argn("amfi_unrestrict_task_for_pid"))
|
||||
IOLog("unrestricted task_for_pid enabled by boot-arg");
|
||||
unrestricted_debugging = 1;
|
||||
boot_device = 1;
|
||||
|
||||
if (PE_parse_boot_argn("amfi_dev_mode_policy"))
|
||||
IOLog("developer mode internal policy disabled by boot-arg");
|
||||
dev_mode = 1
|
||||
|
||||
if (PE_parse_boot_argn("amfi_allow_any_signature" | "amfi_get_out_of_my_way"))
|
||||
IOLog("signature enforcement disabled by boot-arg");
|
||||
IOLog("library validation will not mark external binaries as platform"); // NOT SURE
|
||||
|
||||
if (PE_parse_boot_argn("amfi_unrestricted_local_signing"))
|
||||
IOLog("unrestricted AMFI local signing enabled by boot-arg");
|
||||
|
||||
if (PE_parse_boot_argn("amfi_ready_to_roll"))
|
||||
IOLog("practice a key roll");
|
||||
readyToRoll = true;
|
||||
|
||||
// Disabling code signing enforcement based on the boot-arg
|
||||
if (PE_parse_boot_argn("cs_enforcement_disable"))
|
||||
IOLog("cs_enforcement disabled by boot-arg")
|
||||
|
||||
// Finalizing initialization
|
||||
InitializeDenylist();
|
||||
_initializeCoreEntitlementsSupport(1); // Initialize support for entitlements and AMFI trust cache interface
|
||||
// Initialize UDID enforcement the exemption profile (define components allowed to execute despite AMFI
|
||||
precookExemptionProfile();
|
||||
jitHashCacheLock = IOLockAlloc()
|
||||
dyldSimCacheLock = IOLockAlloc()
|
||||
supplementalSigningInit(); // Another lock
|
||||
|
||||
// Access device tree to get model name
|
||||
model_name = IORegistryEntry::fromPath("/")
|
||||
model_name = OSMetaClassBase::safeMetaCast(OSData::gMetaClass)
|
||||
IOLog("AMFI: queried model name from device tree:" + model_name);
|
||||
|
||||
// Check if the model is iPhone
|
||||
// If true disable Swift Playgrounds JIT services && some CS features
|
||||
if (model_name == 'iPhone')
|
||||
IOLog("AMFI: disabling Swift Playgrounds JIT services on iPhone devices");
|
||||
_swiftPlaygroundsJIT == 0
|
||||
disable_code_signing_feature(0x10000000);
|
||||
disable_code_signing_feature(0x20000000);
|
||||
|
||||
// For not iPhones - initialize function pointers to AMFI handlers for various security checks
|
||||
if (_swiftPlaygroundsJIT)
|
||||
pointers_list = {
|
||||
_cred_check_label_update_execve
|
||||
_cred_label_associate
|
||||
_cred_label_destroy
|
||||
_cred_label_init
|
||||
_cred_label_update_execve
|
||||
_proc_check_inherit_ipc_ports
|
||||
_vnode_check_signature // Check Code Signature handler
|
||||
_file_check_library_validation // Check validation of a library file
|
||||
_policy_initbsd // Final call from BSD for finalizing initialization of MACF ?
|
||||
_policy_syscall // MACF policy syscall handler
|
||||
_task_id_token_get_task
|
||||
_cred_label_associate_kernel
|
||||
_proc_check_launch_constraints // Check launch constraints for a process
|
||||
amfi_exc_action_check_exception_send
|
||||
amfi_exc_action_label_associate
|
||||
amfi_exc_action_label_populate
|
||||
amfi_exc_action_label_destroy
|
||||
amfi_exc_action_label_init
|
||||
amfi_exc_action_label_update
|
||||
macos_task_get_movable_control_port
|
||||
hsp_proc_check_map_anon
|
||||
macos_task_policy
|
||||
macos_task_control_policy
|
||||
macos_proc_check_run_cs_invalid
|
||||
hook_vnode_check_setextattr
|
||||
hook_vnode_check_getextattr
|
||||
_file_check_mmap
|
||||
_vnode_notify_open
|
||||
core_dump_policy
|
||||
}
|
||||
|
||||
// Register MAC policy
|
||||
mac_policy_register("AMFI", amfiPolicyHandle, 0)
|
||||
|
||||
// Set security policies and constraints for AMFI
|
||||
configurationSettingsInit();
|
||||
|
||||
// Initialize a lock for exception list
|
||||
hardeningInit()
|
||||
|
||||
// Unlocking driver lock
|
||||
lck_mtx_unlock(driverLock);
|
||||
|
||||
// Unlocking mutex and freeing memory
|
||||
lck_mtx_unlock(lock);
|
||||
IOLockFree(lock);
|
||||
lck_mtx_lock(driverLock);
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
-restore
|
||||
BATS_TESTPLAN_ID
|
||||
amfi
|
||||
amfi_allow_3p_launch_constraints
|
||||
amfi_allow_any_signature
|
||||
amfi_allow_non_platform
|
||||
amfi_allow_only_tc
|
||||
amfi_allow_only_tc_override
|
||||
amfi_allow_research
|
||||
amfi_block_unsigned_code
|
||||
amfi_dev_mode_policy
|
||||
amfi_enforce_cc_types
|
||||
amfi_enforce_launch_constraints
|
||||
amfi_enforce_tcc_hardening
|
||||
amfi_force_cs_kill
|
||||
amfi_get_out_of_my_way
|
||||
amfi_hsp_disable
|
||||
amfi_hsp_logging
|
||||
amfi_no_aot_tc
|
||||
amfi_prevent_old_entitled_platform_binaries
|
||||
amfi_ready_to_roll
|
||||
amfi_unrestrict_task_for_pid
|
||||
amfi_unrestricted_local_signing
|
||||
cs_enforcement_disable
|
||||
@@ -0,0 +1,30 @@
|
||||
__ZN24AppleMobileFileIntegrity15copyEntitlementEP4procPKc
|
||||
__ZN24AppleMobileFileIntegrity15copyEntitlementEP5ucredPKc
|
||||
__ZN24AppleMobileFileIntegrity15getEntitlementsEP5ucred
|
||||
__ZN24AppleMobileFileIntegrity16copyEntitlementsEP4proc
|
||||
__ZN24AppleMobileFileIntegrity16copyEntitlementsEP5ucred
|
||||
__ZN24AppleMobileFileIntegrity18copyEntitlementKeyEP4procP17__opaque_amfi_key
|
||||
__ZN24AppleMobileFileIntegrity18copyEntitlementKeyEP5ucredP17__opaque_amfi_key
|
||||
__ZN24AppleMobileFileIntegrity18isHardeningEnabledEv
|
||||
__ZN24AppleMobileFileIntegrity19AMFIGetQueryContextEP4procPP14CEQueryContext
|
||||
__ZN24AppleMobileFileIntegrity19AMFIGetQueryContextEP5ucredPP14CEQueryContext
|
||||
__ZN24AppleMobileFileIntegrity21AMFIEntitlementGetKeyEPKc
|
||||
__ZN24AppleMobileFileIntegrity21copySigningIdentifierEP5ucred
|
||||
__ZN24AppleMobileFileIntegrity22AMFIEntitlementGetBoolEP4procPKcPb
|
||||
__ZN24AppleMobileFileIntegrity22AMFIEntitlementGetBoolEP5ucredPKcPb
|
||||
__ZN24AppleMobileFileIntegrity22AMFIEntitlementPresentEP4procPKcPb
|
||||
__ZN24AppleMobileFileIntegrity22AMFIEntitlementPresentEP5ucredPKcPb
|
||||
__ZN24AppleMobileFileIntegrity25AMFIEntitlementReleaseKeyEP17__opaque_amfi_key
|
||||
__ZN24AppleMobileFileIntegrity26AMFIEntitlementGetConstKeyEPKc
|
||||
__ZN24AppleMobileFileIntegrity27AMFIEntitlementKeyIsPresentEP4procP17__opaque_amfi_keyPb
|
||||
__ZN24AppleMobileFileIntegrity27AMFIEntitlementKeyIsPresentEP5ucredP17__opaque_amfi_keyPb
|
||||
__ZN24AppleMobileFileIntegrity28AMFIEntitlementKeyIsBoolTrueEP4procP17__opaque_amfi_keyPb
|
||||
__ZN24AppleMobileFileIntegrity28AMFIEntitlementKeyIsBoolTrueEP5ucredP17__opaque_amfi_keyPb
|
||||
__ZN24AppleMobileFileIntegrity29isCodeDirectoryHashInJitCacheEP4procPKh
|
||||
__ZN24AppleMobileFileIntegrity9metaClassE
|
||||
_amfi_register_mac_policy
|
||||
_kmod_info
|
||||
InitFunc_1
|
||||
InitFunc_2
|
||||
InitFunc_3
|
||||
InitFunc_4
|
||||
@@ -0,0 +1,652 @@
|
||||
_Assert
|
||||
_CTEvaluateAMFICodeSignatureCMS
|
||||
_CTEvaluateAMFICodeSignatureCMSPubKey
|
||||
_CTEvaluateProvisioningProfile
|
||||
_IOCurrentTaskHasEntitlement
|
||||
_IOFreeData
|
||||
_IOFreeTypeImpl
|
||||
_IOFreeTypeVarImpl
|
||||
_IOLockAlloc
|
||||
_IOLockFree
|
||||
_IOLockLock
|
||||
_IOLockUnlock
|
||||
_IOLog
|
||||
_IOLogv
|
||||
_IOMallocData
|
||||
_IOMallocTypeImpl
|
||||
_IOMallocTypeVarImpl
|
||||
_IOMallocZeroData
|
||||
_IORWLockAlloc
|
||||
_IORWLockRead
|
||||
_IORWLockUnlock
|
||||
_IORWLockWrite
|
||||
_NDR_record
|
||||
_OSCompareAndSwapPtr
|
||||
_OSIncrementAtomic
|
||||
_OSObject_typed_operator_delete
|
||||
_OSObject_typed_operator_new
|
||||
_PAGE_SHIFT_CONST
|
||||
_PE_parse_boot_argn
|
||||
_SecureDTGetProperty
|
||||
_SecureDTLookupEntry
|
||||
_VNOP_IOCTL
|
||||
__Block_object_assign
|
||||
__Block_object_dispose
|
||||
__NSConcreteStackBlock
|
||||
__Z16OSUnserializeXMLPKcmPP8OSString
|
||||
__ZN11OSMetaClass21_RESERVEDOSMetaClass0Ev
|
||||
__ZN11OSMetaClass21_RESERVEDOSMetaClass1Ev
|
||||
__ZN11OSMetaClass21_RESERVEDOSMetaClass2Ev
|
||||
__ZN11OSMetaClass21_RESERVEDOSMetaClass3Ev
|
||||
__ZN11OSMetaClass21_RESERVEDOSMetaClass4Ev
|
||||
__ZN11OSMetaClass21_RESERVEDOSMetaClass5Ev
|
||||
__ZN11OSMetaClass21_RESERVEDOSMetaClass6Ev
|
||||
__ZN11OSMetaClass21_RESERVEDOSMetaClass7Ev
|
||||
__ZN11OSMetaClassC2EPKcPKS_j
|
||||
__ZN11OSMetaClassC2EPKcPKS_jPP4zoneS1_19zone_create_flags_t
|
||||
__ZN11OSMetaClassD2Ev
|
||||
__ZN12IOUserClient10clientDiedEv
|
||||
__ZN12IOUserClient10gMetaClassE
|
||||
__ZN12IOUserClient10getServiceEv
|
||||
__ZN12IOUserClient12initWithTaskEP4taskPvj
|
||||
__ZN12IOUserClient13connectClientEPS_
|
||||
__ZN12IOUserClient18clientHasPrivilegeEPvPKc
|
||||
__ZN12IOUserClient19clientMemoryForTypeEjPjPP18IOMemoryDescriptor
|
||||
__ZN12IOUserClient20exportObjectToClientEP4taskP8OSObjectPS3_
|
||||
__ZN12IOUserClient22_RESERVEDIOUserClient0Ev
|
||||
__ZN12IOUserClient22_RESERVEDIOUserClient1Ev
|
||||
__ZN12IOUserClient22_RESERVEDIOUserClient2Ev
|
||||
__ZN12IOUserClient22_RESERVEDIOUserClient3Ev
|
||||
__ZN12IOUserClient22_RESERVEDIOUserClient4Ev
|
||||
__ZN12IOUserClient22_RESERVEDIOUserClient5Ev
|
||||
__ZN12IOUserClient22_RESERVEDIOUserClient6Ev
|
||||
__ZN12IOUserClient22_RESERVEDIOUserClient7Ev
|
||||
__ZN12IOUserClient22_RESERVEDIOUserClient8Ev
|
||||
__ZN12IOUserClient22_RESERVEDIOUserClient9Ev
|
||||
__ZN12IOUserClient23_RESERVEDIOUserClient10Ev
|
||||
__ZN12IOUserClient23_RESERVEDIOUserClient11Ev
|
||||
__ZN12IOUserClient23_RESERVEDIOUserClient12Ev
|
||||
__ZN12IOUserClient23_RESERVEDIOUserClient13Ev
|
||||
__ZN12IOUserClient23_RESERVEDIOUserClient14Ev
|
||||
__ZN12IOUserClient23_RESERVEDIOUserClient15Ev
|
||||
__ZN12IOUserClient23getExternalTrapForIndexEj
|
||||
__ZN12IOUserClient24getNotificationSemaphoreEjPP9semaphore
|
||||
__ZN12IOUserClient24getTargetAndTrapForIndexEPP9IOServicej
|
||||
__ZN12IOUserClient24registerNotificationPortEP8ipc_portjj
|
||||
__ZN12IOUserClient24registerNotificationPortEP8ipc_portjy
|
||||
__ZN12IOUserClient25getExternalMethodForIndexEj
|
||||
__ZN12IOUserClient26getTargetAndMethodForIndexEPP9IOServicej
|
||||
__ZN12IOUserClient30getExternalAsyncMethodForIndexEj
|
||||
__ZN12IOUserClient31getAsyncTargetAndMethodForIndexEPP9IOServicej
|
||||
__ZN12IOUserClient4freeEv
|
||||
__ZN12IOUserClient4initEP12OSDictionary
|
||||
__ZN12IOUserClient4initEv
|
||||
__ZN12IOUserClient8DispatchE5IORPC
|
||||
__ZN12IOUserClientC2EPK11OSMetaClass
|
||||
__ZN12IOUserClientD2Ev
|
||||
__ZN12OSDictionary12withCapacityEj
|
||||
__ZN12OSDictionary9metaClassE
|
||||
__ZN12OSDictionary9setObjectEPKcRK11OSSharedPtrIK15OSMetaClassBaseE
|
||||
__ZN12OSDictionary9setObjectERK11OSSharedPtrIK8OSSymbolERKS0_IK15OSMetaClassBaseE
|
||||
__ZN15IORegistryEntry11detachAboveEPK15IORegistryPlane
|
||||
__ZN15IORegistryEntry11setLocationEPK8OSSymbolPK15IORegistryPlane
|
||||
__ZN15IORegistryEntry11setLocationEPKcPK15IORegistryPlane
|
||||
__ZN15IORegistryEntry11setPropertyEPK8OSStringP8OSObject
|
||||
__ZN15IORegistryEntry11setPropertyEPK8OSSymbolP8OSObject
|
||||
__ZN15IORegistryEntry11setPropertyEPKcP8OSObject
|
||||
__ZN15IORegistryEntry11setPropertyEPKcPvj
|
||||
__ZN15IORegistryEntry11setPropertyEPKcS1_
|
||||
__ZN15IORegistryEntry11setPropertyEPKcb
|
||||
__ZN15IORegistryEntry11setPropertyEPKcyj
|
||||
__ZN15IORegistryEntry13attachToChildEPS_PK15IORegistryPlane
|
||||
__ZN15IORegistryEntry13childFromPathEPKcPK15IORegistryPlanePcPi
|
||||
__ZN15IORegistryEntry13setPropertiesEP8OSObject
|
||||
__ZN15IORegistryEntry14attachToParentEPS_PK15IORegistryPlane
|
||||
__ZN15IORegistryEntry14removePropertyEPK8OSString
|
||||
__ZN15IORegistryEntry14removePropertyEPK8OSSymbol
|
||||
__ZN15IORegistryEntry14removePropertyEPKc
|
||||
__ZN15IORegistryEntry15detachFromChildEPS_PK15IORegistryPlane
|
||||
__ZN15IORegistryEntry16detachFromParentEPS_PK15IORegistryPlane
|
||||
__ZN15IORegistryEntry16setPropertyTableEP12OSDictionary
|
||||
__ZN15IORegistryEntry17runPropertyActionEPFiP8OSObjectPvS2_S2_S2_ES1_S2_S2_S2_S2_
|
||||
__ZN15IORegistryEntry25_RESERVEDIORegistryEntry0Ev
|
||||
__ZN15IORegistryEntry25_RESERVEDIORegistryEntry1Ev
|
||||
__ZN15IORegistryEntry25_RESERVEDIORegistryEntry2Ev
|
||||
__ZN15IORegistryEntry25_RESERVEDIORegistryEntry3Ev
|
||||
__ZN15IORegistryEntry25_RESERVEDIORegistryEntry4Ev
|
||||
__ZN15IORegistryEntry25_RESERVEDIORegistryEntry5Ev
|
||||
__ZN15IORegistryEntry25_RESERVEDIORegistryEntry6Ev
|
||||
__ZN15IORegistryEntry25_RESERVEDIORegistryEntry7Ev
|
||||
__ZN15IORegistryEntry25_RESERVEDIORegistryEntry8Ev
|
||||
__ZN15IORegistryEntry25_RESERVEDIORegistryEntry9Ev
|
||||
__ZN15IORegistryEntry26_RESERVEDIORegistryEntry10Ev
|
||||
__ZN15IORegistryEntry26_RESERVEDIORegistryEntry11Ev
|
||||
__ZN15IORegistryEntry26_RESERVEDIORegistryEntry12Ev
|
||||
__ZN15IORegistryEntry26_RESERVEDIORegistryEntry13Ev
|
||||
__ZN15IORegistryEntry26_RESERVEDIORegistryEntry14Ev
|
||||
__ZN15IORegistryEntry26_RESERVEDIORegistryEntry15Ev
|
||||
__ZN15IORegistryEntry26_RESERVEDIORegistryEntry16Ev
|
||||
__ZN15IORegistryEntry26_RESERVEDIORegistryEntry17Ev
|
||||
__ZN15IORegistryEntry26_RESERVEDIORegistryEntry18Ev
|
||||
__ZN15IORegistryEntry26_RESERVEDIORegistryEntry19Ev
|
||||
__ZN15IORegistryEntry26_RESERVEDIORegistryEntry20Ev
|
||||
__ZN15IORegistryEntry26_RESERVEDIORegistryEntry21Ev
|
||||
__ZN15IORegistryEntry26_RESERVEDIORegistryEntry22Ev
|
||||
__ZN15IORegistryEntry26_RESERVEDIORegistryEntry23Ev
|
||||
__ZN15IORegistryEntry26_RESERVEDIORegistryEntry24Ev
|
||||
__ZN15IORegistryEntry26_RESERVEDIORegistryEntry25Ev
|
||||
__ZN15IORegistryEntry26_RESERVEDIORegistryEntry26Ev
|
||||
__ZN15IORegistryEntry26_RESERVEDIORegistryEntry27Ev
|
||||
__ZN15IORegistryEntry26_RESERVEDIORegistryEntry28Ev
|
||||
__ZN15IORegistryEntry26_RESERVEDIORegistryEntry29Ev
|
||||
__ZN15IORegistryEntry26_RESERVEDIORegistryEntry30Ev
|
||||
__ZN15IORegistryEntry26_RESERVEDIORegistryEntry31Ev
|
||||
__ZN15IORegistryEntry7setNameEPK8OSSymbolPK15IORegistryPlane
|
||||
__ZN15IORegistryEntry7setNameEPKcPK15IORegistryPlane
|
||||
__ZN15IORegistryEntry8fromPathEPKcPK15IORegistryPlanePcPiPS_
|
||||
__ZN15IORegistryEntry9detachAllEPK15IORegistryPlane
|
||||
__ZN15OSMetaClassBase12safeMetaCastEPKS_PK11OSMetaClass
|
||||
__ZN15OSMetaClassBase25_RESERVEDOSMetaClassBase0Ev
|
||||
__ZN15OSMetaClassBase25_RESERVEDOSMetaClassBase1Ev
|
||||
__ZN15OSMetaClassBase25_RESERVEDOSMetaClassBase2Ev
|
||||
__ZN15OSMetaClassBase25_RESERVEDOSMetaClassBase3Ev
|
||||
__ZN15OSMetaClassBase25_RESERVEDOSMetaClassBase4Ev
|
||||
__ZN15OSMetaClassBase25_RESERVEDOSMetaClassBase5Ev
|
||||
__ZN15OSMetaClassBase25_RESERVEDOSMetaClassBase6Ev
|
||||
__ZN15OSMetaClassBase25_RESERVEDOSMetaClassBase7Ev
|
||||
__ZN15OSMetaClassBase8DispatchE5IORPC
|
||||
__ZN16CoreAnalyticsHub22analyticsSendEventLazyEP8OSStringP8OSObject
|
||||
__ZN16CoreAnalyticsHub9metaClassE
|
||||
__ZN18IOMemoryDescriptor11withAddressEPvyj
|
||||
__ZN20OSCollectionIterator14withCollectionEPK12OSCollection
|
||||
__ZN6OSData9metaClassE
|
||||
__ZN6OSData9withBytesEPKvj
|
||||
__ZN7OSArray12withCapacityEj
|
||||
__ZN7OSArray9metaClassE
|
||||
__ZN7OSArray9setObjectERK11OSSharedPtrIK15OSMetaClassBaseE
|
||||
__ZN8OSNumber10withNumberEyj
|
||||
__ZN8OSNumber9metaClassE
|
||||
__ZN8OSObject10gMetaClassE
|
||||
__ZN8OSObject18_RESERVEDOSObject0Ev
|
||||
__ZN8OSObject18_RESERVEDOSObject1Ev
|
||||
__ZN8OSObject18_RESERVEDOSObject2Ev
|
||||
__ZN8OSObject18_RESERVEDOSObject3Ev
|
||||
__ZN8OSObject18_RESERVEDOSObject4Ev
|
||||
__ZN8OSObject18_RESERVEDOSObject5Ev
|
||||
__ZN8OSObject18_RESERVEDOSObject6Ev
|
||||
__ZN8OSObject18_RESERVEDOSObject7Ev
|
||||
__ZN8OSObject18_RESERVEDOSObject8Ev
|
||||
__ZN8OSObject18_RESERVEDOSObject9Ev
|
||||
__ZN8OSObject19_RESERVEDOSObject10Ev
|
||||
__ZN8OSObject19_RESERVEDOSObject11Ev
|
||||
__ZN8OSObject19_RESERVEDOSObject12Ev
|
||||
__ZN8OSObject19_RESERVEDOSObject13Ev
|
||||
__ZN8OSObject19_RESERVEDOSObject14Ev
|
||||
__ZN8OSObject19_RESERVEDOSObject15Ev
|
||||
__ZN8OSObject4initEv
|
||||
__ZN8OSObject8DispatchE5IORPC
|
||||
__ZN8OSObjectC2EPK11OSMetaClass
|
||||
__ZN8OSObjectD2Ev
|
||||
__ZN8OSObjectdlEPvm
|
||||
__ZN8OSObjectnwEm
|
||||
__ZN8OSString11withCStringEPKc
|
||||
__ZN8OSString11withCStringEPKcm
|
||||
__ZN8OSString17withCStringNoCopyEPKc
|
||||
__ZN8OSString9metaClassE
|
||||
__ZN8OSSymbol10withStringEPK8OSString
|
||||
__ZN8OSSymbol11withCStringEPKc
|
||||
__ZN8OSSymbol17withCStringNoCopyEPKc
|
||||
__ZN8OSSymbol9metaClassE
|
||||
__ZN9IODTNVRAM9metaClassE
|
||||
__ZN9IOService10adjustBusyEi
|
||||
__ZN9IOService10gMetaClassE
|
||||
__ZN9IOService10handleOpenEPS_jPv
|
||||
__ZN9IOService10joinPMtreeEPS_
|
||||
__ZN9IOService11getPlatformEv
|
||||
__ZN9IOService11handleCloseEPS_j
|
||||
__ZN9IOService12didTerminateEPS_jPb
|
||||
__ZN9IOService12getBusyStateEv
|
||||
__ZN9IOService12getResourcesEv
|
||||
__ZN9IOService12requestProbeEj
|
||||
__ZN9IOService12tellChangeUpEm
|
||||
__ZN9IOService12updateReportEP19IOReportChannelListjPvS2_
|
||||
__ZN9IOService13addPowerChildEPS_
|
||||
__ZN9IOService13askChangeDownEm
|
||||
__ZN9IOService13matchLocationEPS_
|
||||
__ZN9IOService13messageClientEjP8OSObjectPvm
|
||||
__ZN9IOService13newUserClientEP4taskPvjP12OSDictionaryPP12IOUserClient
|
||||
__ZN9IOService13newUserClientEP4taskPvjPP12IOUserClient
|
||||
__ZN9IOService13setPowerStateEmPS_
|
||||
__ZN9IOService13willTerminateEPS_j
|
||||
__ZN9IOService14activityTickleEmm
|
||||
__ZN9IOService14applyToClientsEPFvPS_PvES1_
|
||||
__ZN9IOService14causeInterruptEi
|
||||
__ZN9IOService14messageClientsEjPvm
|
||||
__ZN9IOService14tellChangeDownEm
|
||||
__ZN9IOService14waitForServiceEP12OSDictionaryP13mach_timespec
|
||||
__ZN9IOService15comparePropertyEP12OSDictionaryPK8OSString
|
||||
__ZN9IOService15comparePropertyEP12OSDictionaryPKc
|
||||
__ZN9IOService15configureReportEP19IOReportChannelListjPvS2_
|
||||
__ZN9IOService15enableInterruptEi
|
||||
__ZN9IOService15errnoFromReturnEi
|
||||
__ZN9IOService15getDeviceMemoryEv
|
||||
__ZN9IOService15nextIdleTimeoutEyyj
|
||||
__ZN9IOService15powerChangeDoneEm
|
||||
__ZN9IOService15registerServiceEj
|
||||
__ZN9IOService15serviceMatchingEPKcP12OSDictionary
|
||||
__ZN9IOService15setDeviceMemoryEP7OSArray
|
||||
__ZN9IOService15terminateClientEPS_j
|
||||
__ZN9IOService16allowPowerChangeEm
|
||||
__ZN9IOService16applyToProvidersEPFvPS_PvES1_
|
||||
__ZN9IOService16disableInterruptEi
|
||||
__ZN9IOService16getInterruptTypeEiPi
|
||||
__ZN9IOService16registerInterestEPK8OSSymbolPFiPvS3_jPS_S3_mES3_S3_
|
||||
__ZN9IOService16removePowerChildEP17IOPowerConnection
|
||||
__ZN9IOService16requestTerminateEPS_j
|
||||
__ZN9IOService16stringFromReturnEi
|
||||
__ZN9IOService16tellNoChangeDownEm
|
||||
__ZN9IOService17addNeededResourceEPKc
|
||||
__ZN9IOService17applyToInterestedEPK8OSSymbolPFvP8OSObjectPvES5_
|
||||
__ZN9IOService17cancelPowerChangeEm
|
||||
__ZN9IOService17comparePropertiesEP12OSDictionaryP12OSCollection
|
||||
__ZN9IOService17getAggressivenessEmPm
|
||||
__ZN9IOService17registerInterruptEiP8OSObjectPFvS1_PvPS_iES2_
|
||||
__ZN9IOService17setAggressivenessEmm
|
||||
__ZN9IOService18lockForArbitrationEb
|
||||
__ZN9IOService18matchPropertyTableEP12OSDictionary
|
||||
__ZN9IOService18matchPropertyTableEP12OSDictionaryPi
|
||||
__ZN9IOService18setIdleTimerPeriodEm
|
||||
__ZN9IOService18systemWillShutdownEj
|
||||
__ZN9IOService19_RESERVEDIOService0Ev
|
||||
__ZN9IOService19_RESERVEDIOService1Ev
|
||||
__ZN9IOService19_RESERVEDIOService2Ev
|
||||
__ZN9IOService19_RESERVEDIOService3Ev
|
||||
__ZN9IOService19_RESERVEDIOService4Ev
|
||||
__ZN9IOService19_RESERVEDIOService5Ev
|
||||
__ZN9IOService19_RESERVEDIOService6Ev
|
||||
__ZN9IOService19_RESERVEDIOService7Ev
|
||||
__ZN9IOService19_RESERVEDIOService8Ev
|
||||
__ZN9IOService19_RESERVEDIOService9Ev
|
||||
__ZN9IOService19registerPowerDriverEPS_P14IOPMPowerStatem
|
||||
__ZN9IOService19unregisterInterruptEi
|
||||
__ZN9IOService20_RESERVEDIOService10Ev
|
||||
__ZN9IOService20_RESERVEDIOService11Ev
|
||||
__ZN9IOService20_RESERVEDIOService12Ev
|
||||
__ZN9IOService20_RESERVEDIOService13Ev
|
||||
__ZN9IOService20_RESERVEDIOService14Ev
|
||||
__ZN9IOService20_RESERVEDIOService15Ev
|
||||
__ZN9IOService20_RESERVEDIOService16Ev
|
||||
__ZN9IOService20_RESERVEDIOService17Ev
|
||||
__ZN9IOService20_RESERVEDIOService18Ev
|
||||
__ZN9IOService20_RESERVEDIOService19Ev
|
||||
__ZN9IOService20_RESERVEDIOService20Ev
|
||||
__ZN9IOService20_RESERVEDIOService21Ev
|
||||
__ZN9IOService20_RESERVEDIOService22Ev
|
||||
__ZN9IOService20_RESERVEDIOService23Ev
|
||||
__ZN9IOService20_RESERVEDIOService24Ev
|
||||
__ZN9IOService20_RESERVEDIOService25Ev
|
||||
__ZN9IOService20_RESERVEDIOService26Ev
|
||||
__ZN9IOService20_RESERVEDIOService27Ev
|
||||
__ZN9IOService20_RESERVEDIOService28Ev
|
||||
__ZN9IOService20_RESERVEDIOService29Ev
|
||||
__ZN9IOService20_RESERVEDIOService30Ev
|
||||
__ZN9IOService20_RESERVEDIOService31Ev
|
||||
__ZN9IOService20_RESERVEDIOService32Ev
|
||||
__ZN9IOService20_RESERVEDIOService33Ev
|
||||
__ZN9IOService20_RESERVEDIOService34Ev
|
||||
__ZN9IOService20_RESERVEDIOService35Ev
|
||||
__ZN9IOService20_RESERVEDIOService36Ev
|
||||
__ZN9IOService20_RESERVEDIOService37Ev
|
||||
__ZN9IOService20_RESERVEDIOService38Ev
|
||||
__ZN9IOService20_RESERVEDIOService39Ev
|
||||
__ZN9IOService20_RESERVEDIOService40Ev
|
||||
__ZN9IOService20_RESERVEDIOService41Ev
|
||||
__ZN9IOService20_RESERVEDIOService42Ev
|
||||
__ZN9IOService20_RESERVEDIOService43Ev
|
||||
__ZN9IOService20_RESERVEDIOService44Ev
|
||||
__ZN9IOService20_RESERVEDIOService45Ev
|
||||
__ZN9IOService20_RESERVEDIOService46Ev
|
||||
__ZN9IOService20_RESERVEDIOService47Ev
|
||||
__ZN9IOService20callPlatformFunctionEPK8OSSymbolbPvS3_S3_S3_
|
||||
__ZN9IOService20callPlatformFunctionEPKcbPvS2_S2_S2_
|
||||
__ZN9IOService20getDeviceMemoryCountEv
|
||||
__ZN9IOService20unlockForArbitrationEv
|
||||
__ZN9IOService21powerStateDidChangeToEmmPS_
|
||||
__ZN9IOService22copyClientWithCategoryEPK8OSSymbol
|
||||
__ZN9IOService22powerStateWillChangeToEmmPS_
|
||||
__ZN9IOService22waitForMatchingServiceEP12OSDictionaryy
|
||||
__ZN9IOService23acknowledgeNotificationEPvj
|
||||
__ZN9IOService23addMatchingNotificationEPK8OSSymbolP12OSDictionaryPFbPvS5_PS_P10IONotifierES5_S5_i
|
||||
__ZN9IOService23requestPowerDomainStateEmP17IOPowerConnectionm
|
||||
__ZN9IOService24getDeviceMemoryWithIndexEj
|
||||
__ZN9IOService24mapDeviceMemoryWithIndexEjj
|
||||
__ZN9IOService24powerStateForDomainStateEm
|
||||
__ZN9IOService27maxCapabilityForDomainStateEm
|
||||
__ZN9IOService31initialPowerStateForDomainStateEm
|
||||
__ZN9IOService4freeEv
|
||||
__ZN9IOService4initEP12OSDictionary
|
||||
__ZN9IOService4initEP15IORegistryEntryPK15IORegistryPlane
|
||||
__ZN9IOService4openEPS_jPv
|
||||
__ZN9IOService4stopEPS_
|
||||
__ZN9IOService5closeEPS_j
|
||||
__ZN9IOService5probeEPS_Pi
|
||||
__ZN9IOService6PMinitEv
|
||||
__ZN9IOService6PMstopEv
|
||||
__ZN9IOService6attachEPS_
|
||||
__ZN9IOService6detachEPS_
|
||||
__ZN9IOService7messageEjPS_Pv
|
||||
__ZN9IOService8DispatchE5IORPC
|
||||
__ZN9IOService8finalizeEj
|
||||
__ZN9IOService9terminateEj
|
||||
__ZN9IOServiceC2EPK11OSMetaClass
|
||||
__ZN9IOServiceD2Ev
|
||||
__ZN9OSBoolean11withBooleanEb
|
||||
__ZN9OSBoolean9metaClassE
|
||||
__ZNK11OSMetaClass12getClassNameEv
|
||||
__ZNK11OSMetaClass12getMetaClassEv
|
||||
__ZNK11OSMetaClass12taggedRetainEPKv
|
||||
__ZNK11OSMetaClass13taggedReleaseEPKv
|
||||
__ZNK11OSMetaClass13taggedReleaseEPKvi
|
||||
__ZNK11OSMetaClass14getRetainCountEv
|
||||
__ZNK11OSMetaClass19instanceConstructedEv
|
||||
__ZNK11OSMetaClass6retainEv
|
||||
__ZNK11OSMetaClass7releaseEi
|
||||
__ZNK11OSMetaClass7releaseEv
|
||||
__ZNK11OSMetaClass9serializeEP11OSSerialize
|
||||
__ZNK15IORegistryEntry11compareNameEP8OSStringPS1_
|
||||
__ZNK15IORegistryEntry11getLocationEPK15IORegistryPlane
|
||||
__ZNK15IORegistryEntry11getPropertyEPK8OSString
|
||||
__ZNK15IORegistryEntry11getPropertyEPK8OSStringPK15IORegistryPlanej
|
||||
__ZNK15IORegistryEntry11getPropertyEPK8OSSymbol
|
||||
__ZNK15IORegistryEntry11getPropertyEPK8OSSymbolPK15IORegistryPlanej
|
||||
__ZNK15IORegistryEntry11getPropertyEPKc
|
||||
__ZNK15IORegistryEntry11getPropertyEPKcPK15IORegistryPlanej
|
||||
__ZNK15IORegistryEntry12compareNamesEP8OSObjectPP8OSString
|
||||
__ZNK15IORegistryEntry12copyLocationEPK15IORegistryPlane
|
||||
__ZNK15IORegistryEntry12copyPropertyEPK8OSString
|
||||
__ZNK15IORegistryEntry12copyPropertyEPK8OSStringPK15IORegistryPlanej
|
||||
__ZNK15IORegistryEntry12copyPropertyEPK8OSSymbol
|
||||
__ZNK15IORegistryEntry12copyPropertyEPK8OSSymbolPK15IORegistryPlanej
|
||||
__ZNK15IORegistryEntry12copyPropertyEPKc
|
||||
__ZNK15IORegistryEntry12copyPropertyEPKcPK15IORegistryPlanej
|
||||
__ZNK15IORegistryEntry13getChildEntryEPK15IORegistryPlane
|
||||
__ZNK15IORegistryEntry14applyToParentsEPFvPS_PvES1_PK15IORegistryPlane
|
||||
__ZNK15IORegistryEntry14copyChildEntryEPK15IORegistryPlane
|
||||
__ZNK15IORegistryEntry14getParentEntryEPK15IORegistryPlane
|
||||
__ZNK15IORegistryEntry15applyToChildrenEPFvPS_PvES1_PK15IORegistryPlane
|
||||
__ZNK15IORegistryEntry15copyParentEntryEPK15IORegistryPlane
|
||||
__ZNK15IORegistryEntry16getChildIteratorEPK15IORegistryPlane
|
||||
__ZNK15IORegistryEntry16getPathComponentEPcPiPK15IORegistryPlane
|
||||
__ZNK15IORegistryEntry17getParentIteratorEPK15IORegistryPlane
|
||||
__ZNK15IORegistryEntry24dictionaryWithPropertiesEv
|
||||
__ZNK15IORegistryEntry7getNameEPK15IORegistryPlane
|
||||
__ZNK15IORegistryEntry7getPathEPcPiPK15IORegistryPlane
|
||||
__ZNK15IORegistryEntry7inPlaneEPK15IORegistryPlane
|
||||
__ZNK15IORegistryEntry7isChildEPS_PK15IORegistryPlaneb
|
||||
__ZNK15IORegistryEntry8copyNameEPK15IORegistryPlane
|
||||
__ZNK15IORegistryEntry8getDepthEPK15IORegistryPlane
|
||||
__ZNK15IORegistryEntry8isParentEPS_PK15IORegistryPlaneb
|
||||
__ZNK15OSMetaClassBase9isEqualToEPKS_
|
||||
__ZNK8OSObject12taggedRetainEPKv
|
||||
__ZNK8OSObject13taggedReleaseEPKv
|
||||
__ZNK8OSObject13taggedReleaseEPKvi
|
||||
__ZNK8OSObject14getRetainCountEv
|
||||
__ZNK8OSObject6retainEv
|
||||
__ZNK8OSObject7releaseEi
|
||||
__ZNK8OSObject7releaseEv
|
||||
__ZNK8OSObject9serializeEP11OSSerialize
|
||||
__ZNK9IOService11getProviderEv
|
||||
__ZNK9IOService11getWorkLoopEv
|
||||
__ZNK9IOService12handleIsOpenEPKS_
|
||||
__ZNK9IOService17getClientIteratorEv
|
||||
__ZNK9IOService19getProviderIteratorEv
|
||||
__ZNK9IOService19serializePropertiesEP11OSSerialize
|
||||
__ZNK9IOService21getOpenClientIteratorEv
|
||||
__ZNK9IOService23getOpenProviderIteratorEv
|
||||
__ZNK9IOService6isOpenEPKS_
|
||||
__ZNK9IOService8getStateEv
|
||||
__ZNK9IOService9getClientEv
|
||||
__ZTV12IOUserClient
|
||||
__ZTV8OSObject
|
||||
__ZTV9IOService
|
||||
__ZdlPv
|
||||
___cxa_pure_virtual
|
||||
___memcpy_chk
|
||||
___stack_chk_fail
|
||||
___stack_chk_guard
|
||||
___strlcpy_chk
|
||||
__img4_chip_ap_software_ff00
|
||||
__img4_chip_ap_software_ff01
|
||||
__img4_chip_ap_software_ff06
|
||||
__img4_chip_ap_supplemental
|
||||
__img4_chip_cryptex1_asset
|
||||
__img4_chip_cryptex1_boot_reduced
|
||||
__img4_chip_cryptex1_generic
|
||||
__img4_chip_cryptex1_generic_supplemental
|
||||
__img4_nonce_domain_cryptex
|
||||
__img4_nonce_domain_ddi
|
||||
__img4_nonce_domain_ephemeral_cryptex
|
||||
__img4_nonce_domain_pdi
|
||||
__img4_nonce_domain_trust_cache
|
||||
__os_log_default
|
||||
__os_log_internal
|
||||
_amfi_interface_register
|
||||
_bcmp
|
||||
_bzero
|
||||
_ccder_blob_decode_len
|
||||
_ccder_blob_decode_range
|
||||
_ccder_blob_decode_sequence_tl
|
||||
_ccder_blob_decode_tag
|
||||
_ccder_blob_decode_tl
|
||||
_ccder_decode_rsa_pub_n
|
||||
_ccder_decode_tag
|
||||
_ccder_decode_tl
|
||||
_ccder_decode_uint64
|
||||
_ccder_encode_tl
|
||||
_ccder_sizeof_len
|
||||
_ccder_sizeof_tag
|
||||
_ccdigest
|
||||
_ccdigest_init
|
||||
_ccdigest_update
|
||||
_ccec_cp_256
|
||||
_ccec_import_pub
|
||||
_ccec_verify
|
||||
_ccrsa_import_pub
|
||||
_ccrsa_verify_pkcs1v15
|
||||
_ccsha1_di
|
||||
_ccsha224_di
|
||||
_ccsha256_di
|
||||
_ccsha384_di
|
||||
_ccsha512_di
|
||||
_cczp_bitlen
|
||||
_check_trust_cache_runtime_for_uuid
|
||||
_code_signing_configuration
|
||||
_copyin
|
||||
_copyout
|
||||
_copyoutstr
|
||||
_cs_blob_reset_cache
|
||||
_cs_debug
|
||||
_cs_debug_fail_on_unsigned_code
|
||||
_cs_debug_unsigned_exec_failures
|
||||
_cs_debug_unsigned_mmap_failures
|
||||
_cs_entitlement_flags
|
||||
_cs_identity_get
|
||||
_cs_process_enforcement
|
||||
_cs_require_lv
|
||||
_cs_restricted
|
||||
_cs_system_require_lv
|
||||
_cs_valid
|
||||
_cs_vm_supports_4k_translations
|
||||
_csblob_find_blob_bytes
|
||||
_csblob_get_addr
|
||||
_csblob_get_base_offset
|
||||
_csblob_get_cdhash
|
||||
_csblob_get_code_directory
|
||||
_csblob_get_der_entitlements
|
||||
_csblob_get_entitlements
|
||||
_csblob_get_flags
|
||||
_csblob_get_hashtype
|
||||
_csblob_get_identity
|
||||
_csblob_get_platform_binary
|
||||
_csblob_get_signer_type
|
||||
_csblob_get_size
|
||||
_csblob_get_teamid
|
||||
_csblob_get_validation_category
|
||||
_csblob_os_entitlements_copy
|
||||
_csblob_os_entitlements_get
|
||||
_csblob_os_entitlements_set
|
||||
_csblob_register_profile_uuid
|
||||
_csblob_set_validation_category
|
||||
_csfg_get_csblob
|
||||
_csfg_get_supplement_cdhash
|
||||
_csfg_get_supplement_csblob
|
||||
_csfg_get_supplement_linkage_cdhash
|
||||
_csfg_get_supplement_teamid
|
||||
_csfg_get_teamid
|
||||
_csm_resolve_os_entitlements_from_proc
|
||||
_csproc_check_invalid_allowed
|
||||
_csproc_disable_enforcement
|
||||
_csproc_forced_lv
|
||||
_csproc_get_blob
|
||||
_csproc_get_platform_binary
|
||||
_csproc_get_teamid
|
||||
_csproc_hardened_runtime
|
||||
_csproc_mark_invalid_allowed
|
||||
_csr_check
|
||||
_csvnode_get_blob
|
||||
_csvnode_invalidate_flags
|
||||
_current_proc
|
||||
_developer_mode_state
|
||||
_disable_code_signing_feature
|
||||
_enable_developer_mode
|
||||
_fg_get_vnode
|
||||
_gIODTPlane
|
||||
_gIOPublishNotification
|
||||
_garbage_collect_provisioning_profiles
|
||||
_get_local_signing_public_key
|
||||
_host_get_special_port
|
||||
_host_priv_self
|
||||
_img4_chip_instantiate
|
||||
_img4_chip_select_categorized_ap
|
||||
_img4_chip_select_cryptex1_boot
|
||||
_img4_chip_select_cryptex1_preboot
|
||||
_img4_chip_select_personalized_ap
|
||||
_img4_firmware_attach_manifest
|
||||
_img4_firmware_destroy
|
||||
_img4_firmware_execute
|
||||
_img4_firmware_init
|
||||
_img4_firmware_init_from_buff
|
||||
_img4_image_get_bytes
|
||||
_img4_nonce_domain_copy_nonce
|
||||
_ipc_kernel_map
|
||||
_kalloc_data
|
||||
_kalloc_type_impl
|
||||
_kalloc_type_var_impl
|
||||
_kauth_cred_issuser
|
||||
_kauth_cred_proc_ref
|
||||
_kauth_cred_unref
|
||||
_kern_os_zfree
|
||||
_kernel_map
|
||||
_kernproc
|
||||
_kfree_data
|
||||
_kfree_type_impl
|
||||
_kfree_type_var_impl
|
||||
_kmem_alloc_kobject
|
||||
_kmem_free
|
||||
_launch_constraint_data_get_launch_type
|
||||
_lck_grp_alloc_init
|
||||
_lck_rw_destroy
|
||||
_lck_rw_init
|
||||
_lck_rw_lock_exclusive
|
||||
_lck_rw_lock_shared
|
||||
_lck_rw_unlock_exclusive
|
||||
_lck_rw_unlock_shared
|
||||
_load_trust_cache
|
||||
_load_trust_cache_with_type
|
||||
_mac_file_getxattr
|
||||
_mac_label_get
|
||||
_mac_label_set
|
||||
_mac_policy_register
|
||||
_mac_vnop_getxattr
|
||||
_mach_msg_destroy_from_kernel_proper
|
||||
_mach_msg_rpc_from_kernel_proper
|
||||
_match_compilation_service_cdhash
|
||||
_memchr
|
||||
_memcmp
|
||||
_memcpy
|
||||
_memmove
|
||||
_memset
|
||||
_memset_s
|
||||
_mig_dealloc_reply_port
|
||||
_mig_get_reply_port
|
||||
_mig_put_reply_port
|
||||
_mig_strncpy
|
||||
external
|
||||
_os_log_create
|
||||
_panic
|
||||
_printf
|
||||
_proc_chrooted
|
||||
_proc_find
|
||||
_proc_find_ident
|
||||
_proc_getexecutablevnode
|
||||
_proc_is_translated
|
||||
_proc_isinitproc
|
||||
_proc_issetugid
|
||||
_proc_name
|
||||
_proc_pid
|
||||
_proc_pidversion
|
||||
_proc_platform
|
||||
_proc_rele
|
||||
_proc_self
|
||||
_proc_selfpid
|
||||
_proc_selfppid
|
||||
_proc_suser
|
||||
_ptrauth_utils_auth_blob_generic
|
||||
_ptrauth_utils_sign_blob_generic
|
||||
_query_trust_cache
|
||||
_scnprintf
|
||||
_set_compilation_service_cdhash
|
||||
_set_local_signing_public_key
|
||||
_snprintf
|
||||
_strcmp
|
||||
_strlen
|
||||
_strncmp
|
||||
_strnlen
|
||||
_strnstr
|
||||
_sysctl__hw_features_children
|
||||
_sysctl__security_mac_children
|
||||
_sysctl_handle_int
|
||||
_sysctl_register_oid
|
||||
_sysctlbyname
|
||||
_thread_call_allocate_with_options
|
||||
_thread_call_enter1
|
||||
_thread_call_free
|
||||
_unrestrict_local_signing_cdhash
|
||||
_vfs_context_create
|
||||
_vfs_context_proc
|
||||
_vfs_context_rele
|
||||
_vfs_context_ucred
|
||||
_vfs_flags
|
||||
_vm_allocate
|
||||
_vm_deallocate
|
||||
_vm_map_copyin
|
||||
_vm_map_copyout
|
||||
_vm_map_page_mask
|
||||
_vm_map_unwire
|
||||
_vm_map_wire
|
||||
_vn_getpath
|
||||
_vn_rdwr
|
||||
_vnode_close
|
||||
_vnode_getattr
|
||||
_vnode_isdir
|
||||
_vnode_isreg
|
||||
_vnode_mount
|
||||
_vnode_open
|
||||
_vnode_put
|
||||
_vsnprintf
|
||||
_zalloc_flags
|
||||
_zalloc_ro
|
||||
_zalloc_ro_mut
|
||||
_zfree_ro
|
||||
_zone_create_ro
|
||||
_zone_require_ro
|
||||
@@ -10,6 +10,7 @@ import plistlib
|
||||
import json
|
||||
import sys
|
||||
import treelib
|
||||
import ctypes
|
||||
|
||||
### --- I. MACH-O --- ###
|
||||
class MachOProcessor:
|
||||
@@ -53,19 +54,34 @@ class MachOProcessor:
|
||||
if args.load_commands: # Print binary load commands
|
||||
load_commands_list = snake_instance.getLoadCommands()
|
||||
print("Load Commands:", " ".join(load_command.command.name for load_command in load_commands_list))
|
||||
|
||||
|
||||
if args.has_cmd: # Check if LC exist
|
||||
snake_instance.printHasLoadCommand(args.has_cmd)
|
||||
|
||||
if args.segments: # Print binary segments in human friendly form
|
||||
for segment in snake_instance.getSegments():
|
||||
print(segment)
|
||||
|
||||
if args.has_segment: # Check if binary has given __SEGMENT
|
||||
snake_instance.printHasSegment(args.has_segment)
|
||||
|
||||
if args.sections: # Print binary sections in human friendly form
|
||||
for section in snake_instance.getSections():
|
||||
print(section)
|
||||
|
||||
if args.has_section: # Check if binary has given __SEGMENT,__section
|
||||
snake_instance.printHasSection(args.has_section)
|
||||
|
||||
if args.symbols: # Print symbols
|
||||
for symbol in snake_instance.getSymbols():
|
||||
print(f"0x{symbol.value:016X} {symbol.name}")
|
||||
|
||||
if args.imports: # Print imported symbols
|
||||
snake_instance.printImports()
|
||||
|
||||
if args.exports: # Print exported symbols
|
||||
snake_instance.printExports()
|
||||
|
||||
if args.imported_symbols:
|
||||
snake_instance.printImportedSymbols()
|
||||
|
||||
@@ -130,6 +146,12 @@ class MachOProcessor:
|
||||
print('\n<=== ENTRYPOINT ===>')
|
||||
snake_instance.printMain()
|
||||
|
||||
if args.dump_data: # Dump {size} bytes starting from {offset} to a given {filename}.
|
||||
snake_instance.dumpDataArgParser(args.dump_data)
|
||||
|
||||
if args.calc_offset: # Calculate the real address of the Virtual Memory in the file.
|
||||
snake_instance.printCalcRealAddressFromVM(args.calc_offset)
|
||||
|
||||
class SnakeI:
|
||||
def __init__(self, binaries, file_path):
|
||||
'''
|
||||
@@ -158,6 +180,19 @@ class SnakeI:
|
||||
0x8: 'SG_PROTECTED_VERSION_1',
|
||||
0x10: 'SG_READ_ONLY',
|
||||
}
|
||||
self.symbol_types = {
|
||||
'N_STAB': 0xE0, # DEBUG SYMBOL
|
||||
'N_PEXT': 0x10, # PRIVATE EXTERNAL SYMBOL
|
||||
'N_TYPE': 0x0E, # CHECK N_TYPES
|
||||
'N_EXT' : 0x01, # EXTERNAL SYMBOL
|
||||
'N_TYPES': {
|
||||
'N_UNDF': 0x00, # UNDEFINED
|
||||
'N_ABS': 0x02, # ABSOLUTE
|
||||
'N_SECT': 0x0E, # DEFINED IN SECTION
|
||||
'N_PBUD': 0x0C, # PREBOUND UNDEFINED (in dylib)
|
||||
'N_INDR': 0x0A, # INDIRECT
|
||||
}
|
||||
}
|
||||
|
||||
def mapProtection(self, numeric_protection):
|
||||
'''Maps numeric protection to its string representation.'''
|
||||
@@ -207,6 +242,15 @@ class SnakeI:
|
||||
'''https://lief-project.github.io/doc/stable/api/python/macho.html#loadcommand'''
|
||||
return self.binary.commands
|
||||
|
||||
def getSegment(self, segment_name):
|
||||
''' Return segment object for the given {segment_name} __SEGMENT. '''
|
||||
segment_name = segment_name.lower()
|
||||
|
||||
for segment in self.binary.segments:
|
||||
if (segment.name).lower() == segment_name:
|
||||
return segment
|
||||
return None
|
||||
|
||||
def getSegments(self):
|
||||
'''Extract segmenents from binary and return a human readable string: https://lief-project.github.io/doc/stable/api/python/macho.html#lief.MachO.SegmentCommand'''
|
||||
segment_info = []
|
||||
@@ -225,6 +269,18 @@ class SnakeI:
|
||||
segment_info.append(f'{name.ljust(16)}{init_prot}/{max_prot.ljust(8)} VM: {va_start}-{va_end.ljust(24)} FILE: {file_start}-{file_end}')
|
||||
return segment_info
|
||||
|
||||
def hasSegment(self, segment_name):
|
||||
''' Check if binary has given segment {segment_name}. '''
|
||||
for segment in self.binary.segments:
|
||||
if segment.name == segment_name:
|
||||
return True
|
||||
return False
|
||||
|
||||
def printHasSegment(self, segment_name):
|
||||
''' Printing function for --has_segment. '''
|
||||
if self.hasSegment(segment_name):
|
||||
print(f'{self.file_path} has {segment_name}')
|
||||
|
||||
def calcSectionRange(self, section):
|
||||
'''
|
||||
The function calculates a section's start and end offset by adding the FAT slide in case of fat binary.
|
||||
@@ -248,6 +304,18 @@ class SnakeI:
|
||||
return section_offset_start, section_offset_end
|
||||
return False, False
|
||||
|
||||
def getSection(self, segment_section):
|
||||
''' Return segment object for the given {segment_section} __SEGMENT,__section. '''
|
||||
segment_section = segment_section.lower()
|
||||
|
||||
for section in self.binary.sections:
|
||||
current_segment_section = f'{section.segment_name},{section.name}'.lower()
|
||||
|
||||
if current_segment_section == segment_section:
|
||||
return section
|
||||
|
||||
return None
|
||||
|
||||
def getSections(self):
|
||||
'''Extract sections from binary and return in human readable format: https://lief-project.github.io/doc/stable/api/python/macho.html#lief.MachO.Section'''
|
||||
sections_info = []
|
||||
@@ -272,6 +340,38 @@ class SnakeI:
|
||||
'''Get all symbols from the binary (LC_SYMTAB, Chained Fixups, Exports Trie): https://lief-project.github.io/doc/stable/api/python/macho.html#symbol'''
|
||||
return self.binary.symbols
|
||||
|
||||
def getImports(self):
|
||||
''' Imported symbols are undefined and external. '''
|
||||
imported_symbols = []
|
||||
|
||||
for symbol in self.getSymbols():
|
||||
if (symbol.type & self.symbol_types['N_EXT']):
|
||||
if (symbol.type & self.symbol_types['N_TYPE']) == self.symbol_types['N_TYPES']['N_UNDF']:
|
||||
imported_symbols.append(symbol)
|
||||
|
||||
return(imported_symbols)
|
||||
|
||||
def printImports(self):
|
||||
''' Printing only imported symbol names. '''
|
||||
for symbol in self.getImports():
|
||||
print(symbol.name)
|
||||
|
||||
def getExports(self):
|
||||
''' Exported symbols are external but not undefined or private. '''
|
||||
exported_symbols = []
|
||||
|
||||
for symbol in self.getSymbols():
|
||||
if (symbol.type & self.symbol_types['N_EXT']):
|
||||
if (symbol.type & self.symbol_types['N_TYPE']) != self.symbol_types['N_TYPES']['N_UNDF']:
|
||||
exported_symbols.append(symbol)
|
||||
|
||||
return(exported_symbols)
|
||||
|
||||
def printExports(self):
|
||||
''' Printing only exported symbol names. '''
|
||||
for symbol in self.getExports():
|
||||
print(symbol.name)
|
||||
|
||||
def getChainedFixups(self):
|
||||
'''Return Chained Fixups information: https://lief-project.github.io/doc/latest/api/python/macho.html#chained-binding-info'''
|
||||
return self.binary.dyld_chained_fixups
|
||||
@@ -293,17 +393,29 @@ class SnakeI:
|
||||
return uuid_string
|
||||
|
||||
def getMain(self):
|
||||
'''Determine the entry point of an executable.'''
|
||||
return self.binary.main_command
|
||||
'''Determine the entry point of an executable (LC_MAIN or LC_THREAD or LC_UNIXTHREAD)'''
|
||||
LC_MAIN = self.binary.main_command
|
||||
|
||||
if LC_MAIN:
|
||||
return LC_MAIN
|
||||
|
||||
LC_UNIXTHREAD = self.binary.thread_command
|
||||
return LC_UNIXTHREAD
|
||||
|
||||
def printMain(self):
|
||||
'''Prints entry point and stack size if exists.'''
|
||||
'''Prints entry point and stack size or Thread flavor if exists.'''
|
||||
entry_point = self.getMain()
|
||||
if entry_point:
|
||||
print(f'Entry point: {hex(self.getMain().entrypoint)}')
|
||||
print(f'Stack size: {hex(self.getMain().stack_size)}')
|
||||
|
||||
if entry_point and hasattr(entry_point, 'entrypoint'):
|
||||
print(f'Entry point: {hex(entry_point.entrypoint)}')
|
||||
print(f'Stack size: {hex(entry_point.stack_size)}')
|
||||
|
||||
elif entry_point and hasattr(entry_point, 'pc'):
|
||||
print(f'Entry point (PC): {hex(entry_point.pc)}')
|
||||
print(f'Thread flavor: {hex(entry_point.flavor)}')
|
||||
|
||||
else:
|
||||
print(f"{self.file_path} has no entry point.")
|
||||
print(f"{self.file_path} has no entry point (LC_MAIN or LC_THREAD or LC_UNIXTHREAD).")
|
||||
|
||||
def getStringSection(self):
|
||||
'''Return strings from the __cstring (string table).'''
|
||||
@@ -372,18 +484,79 @@ class SnakeI:
|
||||
extracted_bytes = file.read(size)
|
||||
return extracted_bytes
|
||||
|
||||
def saveEcryptedData(self,output_path):
|
||||
def saveBytesToFile(self, data, filename):
|
||||
''' Save bytes to a file. '''
|
||||
with open(filename, 'wb') as file:
|
||||
file.write(data)
|
||||
|
||||
def readBytesFromFile(self, filename):
|
||||
''' Read bytes from a file. '''
|
||||
with open(filename, 'rb') as file:
|
||||
data = file.read()
|
||||
|
||||
return data
|
||||
|
||||
def dumpData(self, offset, size, filename):
|
||||
''' Extract {size} bytes starting from {offset} to a given {filename}. '''
|
||||
extracted_bytes = self.extractBytesAtOffset(offset, size)
|
||||
|
||||
if extracted_bytes:
|
||||
self.saveBytesToFile(extracted_bytes, filename)
|
||||
|
||||
def dumpDataArgParser(self, args):
|
||||
''' Parse comma separated values for dumpData from --dump_data 'offset,size,filename'. '''
|
||||
offset, size, filename = args.split(',')
|
||||
|
||||
offset = offset.strip().lower()
|
||||
if offset.startswith("0x"):
|
||||
offset = int(offset, 16)
|
||||
|
||||
size = size.strip().lower()
|
||||
if size.startswith("0x"):
|
||||
size = int(size, 16)
|
||||
|
||||
filename = filename.strip()
|
||||
|
||||
self.dumpData(offset, size, filename)
|
||||
|
||||
def saveEcryptedData(self, output_path):
|
||||
'''Method for saving encrypted data sector to specified file.'''
|
||||
_, cryptoff, cryptsize = self.getEncryptionInfo()
|
||||
self.saveBytesToFile(self.extractBytesAtOffset(cryptoff + self.fat_offset, cryptsize), output_path)
|
||||
|
||||
def hasSection(self, segment_section):
|
||||
'''
|
||||
Takes "__SEGMENT,__section" as an input.
|
||||
Return True if it exists.
|
||||
'''
|
||||
segment_section = segment_section.lower()
|
||||
|
||||
for section in self.binary.sections:
|
||||
current_segment_section = f'{section.segment_name},{section.name}'.lower()
|
||||
|
||||
if current_segment_section == segment_section:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def printHasSection(self, segment_section):
|
||||
''' Printing function for --has_section. '''
|
||||
if self.hasSection(segment_section):
|
||||
print(f'{self.file_path} has {segment_section}')
|
||||
|
||||
def extractSection(self, segment_name, section_name):
|
||||
'''
|
||||
As argument takes segment name (e.g. "__PRELINK_INFO") and section name that is a part of the segment (e.g. '__text').
|
||||
Return data (bytes) stored in a given section.
|
||||
If section was not found, return False.
|
||||
If section was not found or is empty -> return False.
|
||||
'''
|
||||
segment_section = f'{segment_name},{section_name}'
|
||||
|
||||
if not self.hasSection(segment_section): # If section was not found, break.
|
||||
return False
|
||||
|
||||
section_offset_start, section_offset_end = self.getSectionRange(segment_name, section_name)
|
||||
|
||||
if section_offset_start and section_offset_end:
|
||||
size = section_offset_end - section_offset_start
|
||||
extracted_bytes = self.extractBytesAtOffset(section_offset_start, size)
|
||||
@@ -401,6 +574,57 @@ class SnakeI:
|
||||
return True
|
||||
return False
|
||||
|
||||
def hasLoadCommand(self, load_command):
|
||||
''' Check if the given Load Command exists in the binary. '''
|
||||
if load_command.startswith("LC_"):
|
||||
load_command = load_command[3:]
|
||||
load_command = load_command.lower()
|
||||
|
||||
for cmd in self.load_commands:
|
||||
cmd = str(cmd.command.name).lower()
|
||||
if load_command == cmd:
|
||||
return True
|
||||
return False
|
||||
|
||||
def printHasLoadCommand(self, load_command):
|
||||
''' Printing function for has_cmd. '''
|
||||
original_user_input = load_command
|
||||
if self.hasLoadCommand(load_command):
|
||||
print(f'{self.file_path} has {original_user_input}')
|
||||
|
||||
def getVirtualMemoryStartingAddress(self):
|
||||
''' Get start VM base addr of the __TEXT segment '''
|
||||
vm_base = 0
|
||||
if self.hasSegment('__TEXT'):
|
||||
for segment in self.binary.segments:
|
||||
if segment.name == '__TEXT':
|
||||
vm_base = segment.virtual_address + self.fat_offset
|
||||
return vm_base
|
||||
|
||||
def calcRealAddressFromVM(self, vm_offset):
|
||||
'''
|
||||
Calculate the real address of the Virtual Memory in the file.
|
||||
vm_start == __TEXT segment
|
||||
vm_offset == your address
|
||||
real = vm_offset - vm_start
|
||||
'''
|
||||
# Handling strings and hexes
|
||||
if type(vm_offset) is not int:
|
||||
if (vm_offset.lower()).startswith("0x"):
|
||||
vm_offset = int(vm_offset, 16)
|
||||
else:
|
||||
vm_offset = int(vm_offset)
|
||||
|
||||
vm_base = self.getVirtualMemoryStartingAddress()
|
||||
vm_offset = vm_offset - vm_base
|
||||
return vm_offset
|
||||
|
||||
def printCalcRealAddressFromVM(self, vm_offset):
|
||||
''' Printing function for --calc_offset '''
|
||||
real_offset = self.calcRealAddressFromVM(vm_offset)
|
||||
real_offset_hex = hex(real_offset)
|
||||
print(f'{vm_offset} : {real_offset_hex}')
|
||||
|
||||
### --- II. CODE SIGNING --- ###
|
||||
class CodeSigningProcessor:
|
||||
def __init__(self):
|
||||
@@ -480,11 +704,6 @@ class SnakeII(SnakeI):
|
||||
cms_signature = cs_content[offset + 8:offset + 8 + cms_len_in_int]
|
||||
return cms_signature
|
||||
|
||||
def saveBytesToFile(self, data, filename):
|
||||
'''Save bytes to a file.'''
|
||||
with open(filename, 'wb') as file:
|
||||
file.write(data)
|
||||
|
||||
def extractCertificatesFromCodeSignature(self, cert_name):
|
||||
'''Extracts certificates from the CMS Signature and saves them to a file with _0, _1, _2 indexes at the end of the file names.'''
|
||||
subprocess.run(["codesign", "-d", f"--extract-certificates={cert_name}_", self.file_path], capture_output=True)
|
||||
@@ -1584,7 +1803,7 @@ class AMFIProcessor:
|
||||
def __init__(self):
|
||||
'''This class contains part of the code from the main() for the SnakeVI: AMFI.'''
|
||||
pass
|
||||
|
||||
|
||||
def process(self, args):
|
||||
if args.dump_prelink_info is not None: # nargs="?", const='PRELINK_info.txt' # Dump '__PRELINK_INFO,__info' to a given file (default: 'PRELINK_info.txt')
|
||||
snake_instance.dumpPrelink_info(args.dump_prelink_info)
|
||||
@@ -1592,12 +1811,63 @@ class AMFIProcessor:
|
||||
if args.dump_prelink_text is not None: # Dump '__PRELINK_TEXT,__text' to a given file (default: 'PRELINK_text.txt')
|
||||
snake_instance.dumpPrelink_text(args.dump_prelink_text)
|
||||
|
||||
if args.dump_prelink_kext is not None: # Dump prelinked KEXT from decompressed Kernel Cache to a file named: prelinked_{kext_name}.bin
|
||||
snake_instance.dumpKernelExtensionFromPRELINK_TEXT(args.dump_prelink_kext)
|
||||
|
||||
if args.kext_prelinkinfo: # Print _Prelink properties from PRELINK_INFO,__info for a give kext
|
||||
snake_instance.printParsedPRELINK_INFO_plist(args.kext_prelinkinfo)
|
||||
|
||||
if args.kmod_info: # Print parsed kmod_info for the given kext
|
||||
snake_instance.printParsedkmod_info(args.kmod_info)
|
||||
|
||||
if args.kext_entry: # Print kext entrypoint
|
||||
snake_instance.printKextEntryPoint(args.kext_entry)
|
||||
|
||||
if args.kext_exit: # Print kext exitpoint
|
||||
snake_instance.printKextExitPoint(args.kext_exit)
|
||||
|
||||
if args.amfi:
|
||||
pass
|
||||
snake_instance.printExports()
|
||||
|
||||
class SnakeVI(SnakeV):
|
||||
def __init__(self, binaries, file_path):
|
||||
super().__init__(binaries, file_path)
|
||||
# This map is just a helper for --dump_kext so the user can specify different names for the same kext.
|
||||
# For instance, amfi instead of AppleMobileFileIntegrity.kext
|
||||
self.kext_map = {
|
||||
'amfi' : 'applemobilefileintegrity',
|
||||
'com.apple.driver.applemobilefileintegrity' : 'applemobilefileintegrity',
|
||||
'applemobilefileintegrity.kext' : 'applemobilefileintegrity',
|
||||
}
|
||||
|
||||
def loadPRELINK_INFOFromFile(self, prelink_info_filename): # Not used yet.
|
||||
'''
|
||||
Read PRELINK_INFO,__info section from file (with alignment).
|
||||
The last line in the dumped section plist is broken, because of alignment.
|
||||
This function remove it so the plistlib.loads work.
|
||||
It returns loaded PLIST {prelink_info_plist}.
|
||||
'''
|
||||
prelink_info_plist_bytes = self.readBytesFromFile(prelink_info_filename)
|
||||
prelink_as_bytes_without_last_line = self.removeNullBytesAlignment(prelink_info_plist_bytes)
|
||||
prelink_info_plist = plistlib.loads(prelink_as_bytes_without_last_line)
|
||||
return prelink_info_plist
|
||||
|
||||
def calcTwoComplement64(self, value):
|
||||
''' Convert negative int to hex representation. '''
|
||||
return hex((value + (1 << 64)) % (1 << 64))
|
||||
|
||||
def removeNullBytesAlignment(self, string_as_bytes):
|
||||
'''
|
||||
The last line in the PLISTs and other files dumped from memory will almost always be aligned with 0x00 bytes.
|
||||
This function:
|
||||
Detects lines in a given bytes {string_as_bytes}.
|
||||
Removes the last line.
|
||||
Returns a new {string_as_bytes}.
|
||||
'''
|
||||
decoded_string = string_as_bytes.decode('utf-8')
|
||||
decoded_string_without_last_line = decoded_string[:decoded_string.rfind('\n')]
|
||||
string_as_bytes_without_last_line = decoded_string_without_last_line.encode()
|
||||
return string_as_bytes_without_last_line
|
||||
|
||||
def dumpPrelink_info(self, filename):
|
||||
''' Dump '__PRELINK_INFO,__info' to a given file (default: 'PRELINK_info.txt') '''
|
||||
@@ -1611,6 +1881,141 @@ class SnakeVI(SnakeV):
|
||||
section_name = '__text'
|
||||
self.dumpSection(segment_name, section_name, filename)
|
||||
|
||||
def extractPRELINK_INFO_plist(self):
|
||||
''' Extract '__PRELINK_INFO,__info' and return it. '''
|
||||
segment_name = '__PRELINK_INFO'
|
||||
section_name = '__info'
|
||||
extracted_bytes = self.extractSection(segment_name, section_name)
|
||||
return extracted_bytes
|
||||
|
||||
def parsePRELINK_INFO_plist(self, kext_name):
|
||||
''' Extract PLIST properties values from '__PRELINK_INFO,__info' section for the given {kext_name}:
|
||||
_PrelinkBundlePath
|
||||
_PrelinkExecutableLoadAddr
|
||||
_PrelinkExecutableRelativePath
|
||||
_PrelinkExecutableSize
|
||||
_PrelinkExecutableSourceAddr
|
||||
_PrelinkKmodInfo
|
||||
'''
|
||||
#prelink_info_plist = self.loadPRELINK_INFO(prelink_info_filename) # For loading PRELINK_INFO from file
|
||||
prelink_as_bytes = self.extractPRELINK_INFO_plist()
|
||||
prelink_as_bytes_without_last_line = self.removeNullBytesAlignment(prelink_as_bytes)
|
||||
prelink_info_plist = plistlib.loads(prelink_as_bytes_without_last_line)
|
||||
|
||||
kext_name = kext_name.lower()
|
||||
if kext_name in self.kext_map:
|
||||
kext_name = self.kext_map[kext_name]
|
||||
|
||||
# Iterate over the parsed dictionary
|
||||
for item in prelink_info_plist['_PrelinkInfoDictionary']:
|
||||
PrelinkExecutableRelativePath = item.get('_PrelinkExecutableRelativePath', '').lower()
|
||||
|
||||
# Check if the '_PrelinkExecutableRelativePath' contains {kext_name} in its path
|
||||
if kext_name in PrelinkExecutableRelativePath:
|
||||
# Extract the desired keys and their corresponding values
|
||||
bundle_path = item.get('_PrelinkBundlePath')
|
||||
|
||||
executable_load_addr = str(item.get('_PrelinkExecutableLoadAddr')).lower()
|
||||
if executable_load_addr.startswith("0x"):
|
||||
executable_load_addr = int(executable_load_addr, 16)
|
||||
elif executable_load_addr.startswith("-"):
|
||||
executable_load_addr = self.calcTwoComplement64(int(executable_load_addr))
|
||||
|
||||
executable_relative_path = item.get('_PrelinkExecutableRelativePath')
|
||||
|
||||
executable_size = str(item.get('_PrelinkExecutableSize')).lower()
|
||||
if executable_size.startswith("0x"):
|
||||
executable_size = int(executable_size, 16)
|
||||
elif executable_size.startswith("-"):
|
||||
executable_size = self.calcTwoComplement64(int(executable_size))
|
||||
|
||||
source_addr = str(item.get('_PrelinkExecutableSourceAddr')).lower()
|
||||
if source_addr.startswith("0x"):
|
||||
source_addr = int(source_addr, 16)
|
||||
elif source_addr.startswith("-"):
|
||||
source_addr = self.calcTwoComplement64(int(source_addr))
|
||||
|
||||
kmod_info = str(item.get('_PrelinkKmodInfo')).lower()
|
||||
if kmod_info.startswith("0x"):
|
||||
kmod_info = int(kmod_info, 16)
|
||||
elif kmod_info.startswith("-"):
|
||||
kmod_info = self.calcTwoComplement64(int(kmod_info))
|
||||
|
||||
return bundle_path, executable_load_addr, executable_relative_path, executable_size, source_addr, kmod_info
|
||||
|
||||
def printParsedPRELINK_INFO_plist(self, kext_name):
|
||||
''' Print extracted properties for PRELINK_INFO Plist for a given kext. '''
|
||||
bundle_path, executable_load_addr, executable_relative_path, executable_size, source_addr, kmod_info = self.parsePRELINK_INFO_plist(kext_name)
|
||||
print(f'_PrelinkBundlePath: {bundle_path}')
|
||||
print(f'_PrelinkExecutableLoadAddr: {executable_load_addr}')
|
||||
print(f'_PrelinkExecutableRelativePath: {executable_relative_path}')
|
||||
print(f'_PrelinkExecutableSize: {hex(int(executable_size))}')
|
||||
print(f'_PrelinkExecutableSourceAddr: {source_addr}')
|
||||
print(f'_PrelinkKmodInfo: {kmod_info}')
|
||||
|
||||
def dumpKernelExtensionFromPRELINK_TEXT(self, kext_name):
|
||||
''' Dump prelinked KEXT {kext_name} from decompressed Kernel Cache PRELINK_TEXT segment -p {file_path} to a file named: prelinked_{kext_name}.bin '''
|
||||
segment_section = '__PRELINK_TEXT,__text'
|
||||
|
||||
if not self.hasSection(segment_section): # If segment does not exist - break
|
||||
print(f'Specified binary file does not have {segment_section} - the extension was not dumped.')
|
||||
return False
|
||||
|
||||
_, kext_load_addr, _, kext_size, source_addr, _ = self.parsePRELINK_INFO_plist(kext_name)
|
||||
kext_load_addr = int(kext_load_addr, 16)
|
||||
kext_size = int(kext_size, 16)
|
||||
output_path = f'prelinked_{kext_name}.bin'
|
||||
|
||||
kext_offset = self.calcRealAddressFromVM(kext_load_addr)
|
||||
self.dumpData(kext_offset, kext_size, output_path)
|
||||
|
||||
def parsekmod_info(self, kext_name):
|
||||
''' Parse kmod_info structure for the given {kext_name} from Kernel Cache '''
|
||||
_, _, _, _, _, kmod_info_vm_addr = self.parsePRELINK_INFO_plist(kext_name)
|
||||
kmod_info_in_file = self.calcRealAddressFromVM(kmod_info_vm_addr)
|
||||
kmod_info_size = ctypes.sizeof(AppleStructuresManager.kmod_info)
|
||||
extracted_kmod_info_bytes = self.extractBytesAtOffset(kmod_info_in_file, kmod_info_size)
|
||||
# debug +
|
||||
#Utils.printQuadWordsLittleEndian64(extracted_kmod_info_bytes)
|
||||
# debug -
|
||||
kmod_info_as_dict = AppleStructuresManager.parsekmod_info(extracted_kmod_info_bytes)
|
||||
return kmod_info_as_dict
|
||||
|
||||
def printParsedkmod_info(self, kext_name):
|
||||
''' Printing function for --kmod_info '''
|
||||
kmod_info_as_dict = self.parsekmod_info(kext_name)
|
||||
for k, v in kmod_info_as_dict.items():
|
||||
print(f'{k.ljust(16)}: {v}')
|
||||
|
||||
def calcKextEntryPoint(self, kext_name):
|
||||
''' Calculate the __start for the given {kext_name} Kernel Extension '''
|
||||
kmod_info_as_dict = self.parsekmod_info(kext_name)
|
||||
start = int(kmod_info_as_dict['start'], 16) & 0xFFFFFFFF
|
||||
|
||||
kernelcache_text_segment = self.getSegment('__TEXT')
|
||||
kernelcache_text_segment_base = kernelcache_text_segment.virtual_address
|
||||
|
||||
return start + kernelcache_text_segment_base
|
||||
|
||||
def printKextEntryPoint(self, kext_name):
|
||||
''' Printing function for --kext_entry flag. '''
|
||||
kext_entrypoint = hex(self.calcKextEntryPoint(kext_name))
|
||||
print(f'{kext_name} entrypoint: {kext_entrypoint}')
|
||||
|
||||
def calcKextExitPoint(self, kext_name):
|
||||
''' Calculate the __stop for the given {kext_name} Kernel Extension '''
|
||||
kmod_info_as_dict = self.parsekmod_info(kext_name)
|
||||
stop = int(kmod_info_as_dict['stop'], 16) & 0xFFFFFFFF
|
||||
|
||||
kernelcache_text_segment = self.getSegment('__TEXT')
|
||||
kernelcache_text_segment_base = kernelcache_text_segment.virtual_address
|
||||
|
||||
return stop + kernelcache_text_segment_base
|
||||
|
||||
def printKextExitPoint(self, kext_name):
|
||||
''' Printing function for --kext_exit flag. '''
|
||||
kext_exitpoint = hex(self.calcKextEntryPoint(kext_name))
|
||||
print(f'{kext_name} exitpoint: {kext_exitpoint}')
|
||||
|
||||
### --- ARGUMENT PARSER --- ###
|
||||
class ArgumentParser:
|
||||
@@ -1635,10 +2040,15 @@ class ArgumentParser:
|
||||
macho_group.add_argument('--endian', action='store_true', help="Print binary endianess")
|
||||
macho_group.add_argument('--header', action='store_true', help="Print binary header")
|
||||
macho_group.add_argument('--load_commands', action='store_true', help="Print binary load commands names")
|
||||
macho_group.add_argument('--has_cmd', metavar='LC_MAIN', help="Check of binary has given load command")
|
||||
macho_group.add_argument('--segments', action='store_true', help="Print binary segments in human-friendly form")
|
||||
macho_group.add_argument('--has_segment', help="Check if binary has given '__SEGMENT'", metavar='__SEGMENT')
|
||||
macho_group.add_argument('--sections', action='store_true', help="Print binary sections in human-friendly form")
|
||||
macho_group.add_argument('--has_section', help="Check if binary has given '__SEGMENT,__section'", metavar='__SEGMENT,__section')
|
||||
macho_group.add_argument('--symbols', action='store_true', help="Print all binary symbols")
|
||||
macho_group.add_argument('--imported_symbols', action='store_true', help="Print symbols imported from external libraries")
|
||||
macho_group.add_argument('--imports', action='store_true', help="Print imported symbols")
|
||||
macho_group.add_argument('--exports', action='store_true', help="Print exported symbols")
|
||||
macho_group.add_argument('--imported_symbols', action='store_true', help="Print symbols imported from external libraries with dylib names")
|
||||
macho_group.add_argument('--chained_fixups', action='store_true', help="Print Chained Fixups information")
|
||||
macho_group.add_argument('--exports_trie', action='store_true', help="Print Export Trie information")
|
||||
macho_group.add_argument('--uuid', action='store_true', help="Print UUID")
|
||||
@@ -1648,6 +2058,8 @@ class ArgumentParser:
|
||||
macho_group.add_argument('--all_strings', action='store_true', help="Print strings from all sections")
|
||||
macho_group.add_argument('--save_strings', help="Parse all sections, detect strings, and save them to a file", metavar='all_strings.txt')
|
||||
macho_group.add_argument('--info', action='store_true', default=False, help="Print header, load commands, segments, sections, symbols, and strings")
|
||||
macho_group.add_argument('--dump_data', help="Dump {size} bytes starting from {offset} to a given {filename} (e.g. '0x1234,0x1000,out.bin')", metavar=('offset,size,output_path'), nargs="?")
|
||||
macho_group.add_argument('--calc_offset', help="Calculate the real address (file on disk) of the given Virtual Memory {vm_offset} (e.g. 0xfffffe000748f580)", metavar='vm_offset')
|
||||
|
||||
def addCodeSignArgs(self):
|
||||
codesign_group = self.parser.add_argument_group('CODE SIGNING ARGS')
|
||||
@@ -1692,7 +2104,7 @@ class ArgumentParser:
|
||||
dylibs_group.add_argument('--reexport_paths', action='store_true', default=False, help="Print paths from LC_REEXPORT_DLIB")
|
||||
dylibs_group.add_argument('--hijack_sec', action='store_true', default=False, help="Check if binary is protected against Dylib Hijacking")
|
||||
dylibs_group.add_argument('--dylib_hijacking', metavar='(optional) cache_path' ,nargs="?", const="default", help="Check for possible Direct and Indirect Dylib Hijacking loading paths. The output is printed to console and saved in JSON format to /tmp/dylib_hijacking_log.json(append mode). Optionally, specify the path to the Dyld Shared Cache")
|
||||
dylibs_group.add_argument('--dylib_hijacking_a', metavar='cache_path' ,nargs="?", const="default", help="Like --dylib_hijacking, but shows only possible vectors (without protected binaries)")
|
||||
dylibs_group.add_argument('--dylib_hijacking_a', metavar='cache_path', nargs="?", const="default", help="Like --dylib_hijacking, but shows only possible vectors (without protected binaries)")
|
||||
dylibs_group.add_argument('--prepare_dylib', metavar='(optional) target_dylib_name', nargs="?", const='', help="Compile rogue dylib. Optionally, specify target_dylib_path, it will search for the imported symbols from it in the dylib specified in the --path argument and automatically add it to the source code of the rogue lib. Example: --path lib1.dylib --prepare_dylib /path/to/lib2.dylib")
|
||||
|
||||
def addDyldArgs(self):
|
||||
@@ -1707,7 +2119,12 @@ class ArgumentParser:
|
||||
dyld_group = self.parser.add_argument_group('AMFI ARGS')
|
||||
dyld_group.add_argument('--dump_prelink_info', metavar='(optional) out_name', nargs="?", const='PRELINK_info.txt', help='Dump "__PRELINK_INFO,__info" to a given file (default: "PRELINK_info.txt")')
|
||||
dyld_group.add_argument('--dump_prelink_text', metavar='(optional) out_name', nargs="?", const='PRELINK_text.txt', help='Dump "__PRELINK_TEXT,__text" to a given file (default: "PRELINK_text.txt")')
|
||||
dyld_group.add_argument('--amfi', action='store_true', default=False, help="a")
|
||||
dyld_group.add_argument('--dump_prelink_kext', metavar='kext_name', nargs="?", help='Dump prelinked KEXT {kext_name} from decompressed Kernel Cache PRELINK_TEXT segment to a file named: prelinked_{kext_name}.bin')
|
||||
dyld_group.add_argument('--kext_prelinkinfo', metavar='kext_name', nargs="?", help='Print _Prelink properties from PRELINK_INFO,__info for a give {kext_name}')
|
||||
dyld_group.add_argument('--kmod_info', metavar='kext_name', help="Parse kmod_info structure for the given {kext_name} from Kernel Cache")
|
||||
dyld_group.add_argument('--kext_entry', metavar='kext_name', help="Calculate the virtual memory address of the __start (entrpoint) for the given {kext_name} Kernel Extension")
|
||||
dyld_group.add_argument('--kext_exit', metavar='kext_name', help="Calculate the virtual memory address of the __stop (exitpoint) for the given {kext_name} Kernel Extension")
|
||||
dyld_group.add_argument('--amfi', help="a")
|
||||
|
||||
|
||||
|
||||
@@ -1748,6 +2165,92 @@ void myconstructor(int argc, const char **argv)
|
||||
clang_command = ["clang", file_name_c, "-o", output_filename, *flag_list]
|
||||
subprocess.run(clang_command, check=True)
|
||||
|
||||
### --- APPLE CODE --- ###
|
||||
class AppleStructuresManager:
|
||||
''' It stores Apple structures and their parsers. '''
|
||||
class kmod_info(ctypes.Structure):
|
||||
''' REF: https://github.com/apple-oss-distributions/xnu/blob/1031c584a5e37aff177559b9f69dbd3c8c3fd30a/osfmk/mach/kmod.h#L87 '''
|
||||
_pack_ = 1 # Specify the byte order (little-endian)
|
||||
_fields_ = [
|
||||
("next", ctypes.c_uint64), # Simplifying the structure, it should be: struct kmod_info * next;
|
||||
("info_version", ctypes.c_int32),
|
||||
("id", ctypes.c_uint32),
|
||||
("name", ctypes.c_char * 64),
|
||||
("version", ctypes.c_char * 64),
|
||||
("reference_count", ctypes.c_int32),
|
||||
("reference_list", ctypes.c_uint64),
|
||||
("address", ctypes.c_uint64),
|
||||
("size", ctypes.c_uint64),
|
||||
("hdr_size", ctypes.c_uint64),
|
||||
("start", ctypes.c_uint64),
|
||||
("stop", ctypes.c_uint64)
|
||||
]
|
||||
|
||||
def parsekmod_info(data):
|
||||
# Create an instance of the kmod_info structure
|
||||
info = AppleStructuresManager.kmod_info()
|
||||
# Cast the binary data to the structure
|
||||
ctypes.memmove(ctypes.byref(info), data, ctypes.sizeof(info))
|
||||
|
||||
# Convert name and version to strings
|
||||
name = info.name.decode('utf-8').rstrip('\x00')
|
||||
version = info.version.decode('utf-8').rstrip('\x00')
|
||||
|
||||
# Return parsed data as a dictionary
|
||||
return {
|
||||
"next": info.next,
|
||||
"info_version": info.info_version,
|
||||
"id": hex(info.id),
|
||||
"name": name,
|
||||
"version": version,
|
||||
"reference_count": info.reference_count,
|
||||
"reference_list": hex(info.reference_list),
|
||||
"address": hex(info.address),
|
||||
"size": hex(info.size),
|
||||
"hdr_size": hex(info.hdr_size),
|
||||
"start": hex(info.start),
|
||||
"stop": hex(info.stop)
|
||||
}
|
||||
|
||||
### --- UTILS / DEBUG --- ###
|
||||
class Utils:
|
||||
def printQuadWordsLittleEndian64(byte_string, columns=2):
|
||||
''' Print Q values from given {byte_string} in {columns} columns (default 2)
|
||||
0000000000000000 FFFFFFFF00000001
|
||||
6C7070612E6D6F63 7265766972642E65
|
||||
'''
|
||||
# Ensure the byte string length is a multiple of 8
|
||||
while len(byte_string) % 8 != 0:
|
||||
byte_string += b'\x00' # Add padding to make it divisible by 8
|
||||
|
||||
# Convert the byte string to a list of integers
|
||||
byte_list = list(byte_string)
|
||||
|
||||
# Group the bytes into 8-byte chunks
|
||||
chunks = [byte_list[i:i+8] for i in range(0, len(byte_list), 8)]
|
||||
|
||||
# Print the raw bytes in 64-bit little-endian order
|
||||
print("Raw bytes (64-bit little-endian):")
|
||||
i = 1
|
||||
for chunk in chunks:
|
||||
chunk_value = int.from_bytes(chunk, byteorder='little')
|
||||
if i < columns:
|
||||
print(f"{chunk_value:016X}", end=" ")
|
||||
else:
|
||||
print(f"{chunk_value:016X}", end="\n")
|
||||
i = 0
|
||||
i+=1
|
||||
print()
|
||||
|
||||
def printRawHex(byte_string):
|
||||
'''
|
||||
Print bytes as raw hexes (without endianess).
|
||||
01 00 00 00 ff ff ...
|
||||
'''
|
||||
hex_string = ' '.join(f'{byte:02x}' for byte in byte_string)
|
||||
print(hex_string)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
arg_parser = ArgumentParser()
|
||||
args = arg_parser.parseArgs()
|
||||
@@ -1776,4 +2279,4 @@ if __name__ == "__main__":
|
||||
|
||||
### --- VI. AMFI --- ###
|
||||
amfi_processor = AMFIProcessor()
|
||||
amfi_processor.process(args)
|
||||
amfi_processor.process(args)
|
||||
|
||||
-108996
File diff suppressed because one or more lines are too long
Binary file not shown.
@@ -201,7 +201,6 @@ def run_and_get_stdout(command):
|
||||
command_with_stdout = f"{command} 2>&1"
|
||||
return os.popen(command_with_stdout).read().strip()
|
||||
|
||||
|
||||
class TestSnakeI():
|
||||
'''Testing I. MACH-O'''
|
||||
@classmethod
|
||||
@@ -315,6 +314,20 @@ class TestSnakeI():
|
||||
|
||||
assert expected_output in uroboros_output
|
||||
|
||||
def test_has_cmd(self):
|
||||
'''Test the --has_cmd flag of SnakeI.'''
|
||||
args_list = ['-p', 'hello_1', '--has_cmd', 'LC_MAIN']
|
||||
args, file_path = argumentWrapper(args_list)
|
||||
|
||||
def code_block():
|
||||
macho_processor = MachOProcessor(file_path)
|
||||
macho_processor.process(args)
|
||||
|
||||
uroboros_output = executeCodeBlock(code_block)
|
||||
expected_output = 'hello_1 has LC_MAIN'
|
||||
|
||||
assert expected_output in uroboros_output
|
||||
|
||||
def test_segments(self):
|
||||
'''Test the --segments flag of SnakeI.'''
|
||||
args_list = ['-p', 'hello_1', '--segments']
|
||||
@@ -335,6 +348,20 @@ class TestSnakeI():
|
||||
assert expected_output_3 in uroboros_output
|
||||
assert expected_output_4 in uroboros_output
|
||||
|
||||
def test_has_segment(self):
|
||||
'''Test the --has_segment flag of SnakeI.'''
|
||||
args_list = ['-p', 'hello_1', '--has_segment', '__TEXT']
|
||||
args, file_path = argumentWrapper(args_list)
|
||||
|
||||
def code_block():
|
||||
macho_processor = MachOProcessor(file_path)
|
||||
macho_processor.process(args)
|
||||
|
||||
uroboros_output = executeCodeBlock(code_block)
|
||||
expected_output = 'hello_1 has __TEXT'
|
||||
|
||||
assert expected_output in uroboros_output
|
||||
|
||||
def test_sections(self):
|
||||
'''Test the --sections flag of SnakeI.'''
|
||||
args_list = ['-p', 'hello_1', '--sections']
|
||||
@@ -356,7 +383,21 @@ class TestSnakeI():
|
||||
assert expected_output_3 in uroboros_output
|
||||
assert expected_output_4 in uroboros_output
|
||||
assert expected_output_5 in uroboros_output
|
||||
|
||||
|
||||
def test_has_section(self):
|
||||
'''Test the --has_section flag of SnakeI.'''
|
||||
args_list = ['-p', 'hello_1', '--has_section', '__TEXT,__text']
|
||||
args, file_path = argumentWrapper(args_list)
|
||||
|
||||
def code_block():
|
||||
macho_processor = MachOProcessor(file_path)
|
||||
macho_processor.process(args)
|
||||
|
||||
uroboros_output = executeCodeBlock(code_block)
|
||||
expected_output = 'hello_1 has __TEXT,__text'
|
||||
|
||||
assert expected_output in uroboros_output
|
||||
|
||||
def test_symbols(self):
|
||||
'''Test the --symbols flag of SnakeI.'''
|
||||
args_list = ['-p', 'hello_1', '--symbols']
|
||||
@@ -537,6 +578,40 @@ class TestSnakeI():
|
||||
assert expected_output_4 in uroboros_output
|
||||
assert expected_output_5 in uroboros_output
|
||||
|
||||
def test_dump_data(self):
|
||||
'''Test the --dump_data flag of SnakeI.'''
|
||||
args_list = ['-p', 'hello_1', '--dump_data', '0x00,0x08,hello_1_header_dump.bin']
|
||||
args, file_path = argumentWrapper(args_list)
|
||||
|
||||
def code_block():
|
||||
macho_processor = MachOProcessor(file_path)
|
||||
macho_processor.process(args)
|
||||
|
||||
executeCodeBlock(code_block)
|
||||
|
||||
assert os.path.exists('hello_1_header_dump.bin')
|
||||
|
||||
with open('hello_1_header_dump.bin', 'rb') as file:
|
||||
file_output = file.read()
|
||||
expected_output = b'\xcf\xfa\xed\xfe\x0c\x00\x00\x01'
|
||||
|
||||
assert expected_output in file_output
|
||||
os.remove('hello_1_header_dump.bin')
|
||||
|
||||
def test_calc_offset(self):
|
||||
'''Test the --calc_offset flag of SnakeI.'''
|
||||
args_list = ['-p', 'hello_1', '--calc_offset', "0x0000000100003f20"]
|
||||
args, file_path = argumentWrapper(args_list)
|
||||
|
||||
def code_block():
|
||||
macho_processor = MachOProcessor(file_path)
|
||||
macho_processor.process(args)
|
||||
|
||||
uroboros_output = executeCodeBlock(code_block)
|
||||
expected_output = "0x0000000100003f20 : 0x3f20"
|
||||
|
||||
assert expected_output in uroboros_output
|
||||
|
||||
class TestSnakeII():
|
||||
'''Testing II. CODE SIGNING'''
|
||||
@classmethod
|
||||
@@ -1472,7 +1547,7 @@ class TestSnakeVI():
|
||||
os.system("rm -rf kernelcache")
|
||||
assert not os.path.exists("kernelcache")
|
||||
|
||||
def test_dumpPrelink_info(self):
|
||||
def test_dump_prelink_info(self):
|
||||
'''Test the --dump_prelink_info flag of SnakeVI.'''
|
||||
args_list = ['-p', self.kernelcache_path, '--dump_prelink_info']
|
||||
args, file_path = argumentWrapper(args_list)
|
||||
@@ -1483,12 +1558,13 @@ class TestSnakeVI():
|
||||
amfi_processor = AMFIProcessor()
|
||||
amfi_processor.process(args)
|
||||
|
||||
uroboros_output = executeCodeBlock(code_block)
|
||||
executeCodeBlock(code_block)
|
||||
|
||||
assert os.path.exists('PRELINK_info.txt')
|
||||
os.remove('PRELINK_info.txt')
|
||||
|
||||
def test_dumpPrelink_text(self):
|
||||
'''Test the --dump_prelink_info flag of SnakeVI.'''
|
||||
def test_dump_prelink_text(self):
|
||||
'''Test the --dump_prelink_text flag of SnakeVI.'''
|
||||
args_list = ['-p', self.kernelcache_path, '--dump_prelink_text']
|
||||
args, file_path = argumentWrapper(args_list)
|
||||
|
||||
@@ -1498,6 +1574,87 @@ class TestSnakeVI():
|
||||
amfi_processor = AMFIProcessor()
|
||||
amfi_processor.process(args)
|
||||
|
||||
uroboros_output = executeCodeBlock(code_block)
|
||||
executeCodeBlock(code_block)
|
||||
|
||||
assert os.path.exists('PRELINK_text.txt')
|
||||
assert os.path.exists('PRELINK_text.txt')
|
||||
os.remove('PRELINK_text.txt')
|
||||
|
||||
def test_dump_prelink_kext(self):
|
||||
'''Test the --dump_prelink_kext flag of SnakeVI.'''
|
||||
args_list = ['-p', self.kernelcache_path, '--dump_prelink_kext', 'amfi']
|
||||
args, file_path = argumentWrapper(args_list)
|
||||
|
||||
def code_block():
|
||||
macho_processor = MachOProcessor(file_path)
|
||||
macho_processor.process(args)
|
||||
amfi_processor = AMFIProcessor()
|
||||
amfi_processor.process(args)
|
||||
|
||||
executeCodeBlock(code_block)
|
||||
|
||||
assert os.path.exists('prelinked_amfi.bin')
|
||||
os.remove('prelinked_amfi.bin')
|
||||
|
||||
def test_kext_prelinkinfo(self):
|
||||
'''Test the --kext_prelinkinfo flag of SnakeVI.'''
|
||||
args_list = ['-p', self.kernelcache_path, '--kext_prelinkinfo', 'amfi']
|
||||
args, file_path = argumentWrapper(args_list)
|
||||
|
||||
def code_block():
|
||||
macho_processor = MachOProcessor(file_path)
|
||||
macho_processor.process(args)
|
||||
amfi_processor = AMFIProcessor()
|
||||
amfi_processor.process(args)
|
||||
|
||||
uroboros_output = executeCodeBlock(code_block)
|
||||
expected_output = '_PrelinkBundlePath: /System/Library/Extensions/AppleMobileFileIntegrity.kext'
|
||||
|
||||
assert expected_output in uroboros_output
|
||||
|
||||
def test_kmod_info(self):
|
||||
'''Test the --kmod_info flag of SnakeVI.'''
|
||||
args_list = ['-p', self.kernelcache_path, '--kmod_info', 'amfi']
|
||||
args, file_path = argumentWrapper(args_list)
|
||||
|
||||
def code_block():
|
||||
macho_processor = MachOProcessor(file_path)
|
||||
macho_processor.process(args)
|
||||
amfi_processor = AMFIProcessor()
|
||||
amfi_processor.process(args)
|
||||
|
||||
uroboros_output = executeCodeBlock(code_block)
|
||||
expected_output = 'name : com.apple.driver.AppleMobileFileIntegrity'
|
||||
|
||||
assert expected_output in uroboros_output
|
||||
|
||||
def test_kext_entry(self):
|
||||
'''Test the --kext_entry flag of SnakeVI.'''
|
||||
args_list = ['-p', self.kernelcache_path, '--kext_entry', 'amfi']
|
||||
args, file_path = argumentWrapper(args_list)
|
||||
|
||||
def code_block():
|
||||
macho_processor = MachOProcessor(file_path)
|
||||
macho_processor.process(args)
|
||||
amfi_processor = AMFIProcessor()
|
||||
amfi_processor.process(args)
|
||||
|
||||
uroboros_output = executeCodeBlock(code_block)
|
||||
expected_output = 'amfi entrypoint:'
|
||||
|
||||
assert expected_output in uroboros_output
|
||||
|
||||
def test_kext_exit(self):
|
||||
'''Test the --kext_exit flag of SnakeVI.'''
|
||||
args_list = ['-p', self.kernelcache_path, '--kext_exit', 'amfi']
|
||||
args, file_path = argumentWrapper(args_list)
|
||||
|
||||
def code_block():
|
||||
macho_processor = MachOProcessor(file_path)
|
||||
macho_processor.process(args)
|
||||
amfi_processor = AMFIProcessor()
|
||||
amfi_processor.process(args)
|
||||
|
||||
uroboros_output = executeCodeBlock(code_block)
|
||||
expected_output = 'amfi exitpoint:'
|
||||
|
||||
assert expected_output in uroboros_output
|
||||
|
||||
Reference in New Issue
Block a user