diff --git a/lib/src/modules/macho/parser.rs b/lib/src/modules/macho/parser.rs index f18385e96..1c247c89a 100644 --- a/lib/src/modules/macho/parser.rs +++ b/lib/src/modules/macho/parser.rs @@ -1,5 +1,6 @@ use crate::modules::protos; use bstr::{BStr, ByteSlice}; +use itertools::Itertools; #[cfg(feature = "logging")] use log::error; use nom::bytes::complete::take; @@ -799,8 +800,8 @@ impl<'a> MachOFile<'a> { if blob.magic == CS_MAGIC_EMBEDDED_ENTITLEMENTS { let xml_data = &super_data [offset + size_of_blob..offset + length]; - let xml_string = std::str::from_utf8(xml_data) - .unwrap_or_default(); + let xml_string = + std::str::from_utf8(xml_data).unwrap_or_default(); let opt = roxmltree::ParsingOptions { allow_dtd: true, @@ -812,13 +813,25 @@ impl<'a> MachOFile<'a> { xml_string, opt, ) { - for node in parsed_xml - .descendants() - .filter(|n| n.has_tag_name("key")) - { + for node in parsed_xml.descendants().filter(|n| { + n.has_tag_name("key") + || n.has_tag_name("array") + }) { if let Some(entitlement) = node.text() { - self.entitlements - .push(entitlement.to_string()); + if node.has_tag_name("array") { + node.descendants() + .filter_map(|n| n.text()) + .filter(|t| !t.trim().is_empty()) + .unique() + .map(|t| t.to_string()) + .for_each(|array_entitlement| { + self.entitlements + .push(array_entitlement) + }); + } else { + self.entitlements + .push(entitlement.to_string()); + } } } } diff --git a/lib/src/modules/macho/tests/testdata/chess.out b/lib/src/modules/macho/tests/testdata/chess.out index 34cf6f9e9..40333ad8c 100644 --- a/lib/src/modules/macho/tests/testdata/chess.out +++ b/lib/src/modules/macho/tests/testdata/chess.out @@ -817,6 +817,7 @@ dyld_info: entitlements: - "com.apple.developer.game-center" - "com.apple.private.tcc.allow" + - "kTCCServiceMicrophone" - "com.apple.security.app-sandbox" - "com.apple.security.device.microphone" - "com.apple.security.files.user-selected.read-write"