Skip to content

Instantly share code, notes, and snippets.

@0xdevalias
Last active October 3, 2025 07:45
Show Gist options
  • Save 0xdevalias/ca17d9b2653a869f14efe6937ed74115 to your computer and use it in GitHub Desktop.
Save 0xdevalias/ca17d9b2653a869f14efe6937ed74115 to your computer and use it in GitHub Desktop.
Some notes on reverse-engineering the macOS Passwords System Settings pane — following its path from `Passwords.prefPane` to ExtensionKit `PasswordsSettingsExtension.appex`, uncovering dependencies in private frameworks and the dyld shared cache, and probing for hidden `x-apple.systempreferences` URL anchors or parameters beyond the documented b…

Reverse Engineering macOS Passwords Pane Internals: Searching for Hidden x-apple.systempreferences URL Anchors through Passwords.prefPane, PasswordsSettingsExtension.appex, PrivateFrameworks (PasswordManagerUI.framework, Settings.framework), dyld Cache, etc

Some notes on reverse-engineering the macOS Passwords System Settings pane — following its path from Passwords.prefPane to ExtensionKit PasswordsSettingsExtension.appex, uncovering dependencies in private frameworks and the dyld shared cache, and probing for hidden x-apple.systempreferences URL anchors or parameters beyond the documented basics.

Table of Contents

Notes

On older systems, we could find the System Settings 'panes' as .prefPane bundles in /System/Library/PreferencePanes/.

So for Passwords it would be /System/Library/PreferencePanes/Passwords.prefPane:

⇒ file /System/Library/PreferencePanes/Passwords.prefPane
/System/Library/PreferencePanes/Passwords.prefPane: directory

But on macOS Sonoma 14.7.5, this was an empty placeholder:

⇒ du -sh /System/Library/PreferencePanes/Passwords.prefPane
  0B  /System/Library/PreferencePanes/Passwords.prefPane

On newer systems, we can find the panes as .appex bundles in /System/Library/ExtensionKit/Extensions/.

But PasswordsSettingsExtension was a .appexlist instead; which seemed to just be an XML document:

⇒ file /System/Library/ExtensionKit/Extensions/PasswordsSettingsExtension.appexlist
/System/Library/ExtensionKit/Extensions/PasswordsSettingsExtension.appexlist: XML 1.0 document text, ASCII text

Which appeared to be an XML plist, with an AppExtensions key pointing to /System/Cryptexes/App/System/Library/CoreServices/PasswordsSettingsExtension.appex:

⇒ cat /System/Library/ExtensionKit/Extensions/PasswordsSettingsExtension.appexlist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>AppExtensions</key>
  <dict>
    <key>/System/Cryptexes/App/System/Library/CoreServices/PasswordsSettingsExtension.appex</key>
    <dict/>
  </dict>
</dict>
</plist>

And looking at /System/Cryptexes/App/System/Library/CoreServices/PasswordsSettingsExtension.appex, we find the .appex we were after:

⇒ file /System/Cryptexes/App/System/Library/CoreServices/PasswordsSettingsExtension.appex
/System/Cryptexes/App/System/Library/CoreServices/PasswordsSettingsExtension.appex: directory

The .appex is just a bundle folder, so we can look at the Contents/Info.plist file within it, which is also an XML plist:

⇒ ls /System/Cryptexes/App/System/Library/CoreServices/PasswordsSettingsExtension.appex
Contents/

⇒ ls /System/Cryptexes/App/System/Library/CoreServices/PasswordsSettingsExtension.appex/Contents
Info.plist  MacOS/  Resources/  _CodeSignature/  version.plist

⇒ file /System/Cryptexes/App/System/Library/CoreServices/PasswordsSettingsExtension.appex/Contents/Info.plist
/System/Cryptexes/App/System/Library/CoreServices/PasswordsSettingsExtension.appex/Contents/Info.plist: XML 1.0 document text, Unicode text, UTF-8 text

And we can extract the most interesting/relevant section of that as follows:

⇒ plutil -convert json -o - "/System/Cryptexes/App/System/Library/CoreServices/PasswordsSettingsExtension.appex/Contents/Info.plist" | jq '.EXAppExtensionAttributes.SettingsExtensionAttributes'
{
  "legacyPrefPaneBundleName": "Passwords.prefPane",
  "legacyBundleIdentifier": "com.apple.Passwords",
  "allowsXAppleSystemPreferencesURLScheme": true,
  "searchTermsFileName": "PasswordsPrefPane",
  "urlSchemes": [
    "otpauth",
    "apple-otpauth"
  ]
}

Which basically tells us:

  • The Passwords pane explicitly allows the x-apple.systempreferences: URL scheme (allowsXAppleSystemPreferencesURLScheme: true):
    • Legacy bundle identifier: com.apple.Passwords
    • Legacy bundle name: Passwords.prefPane
    • The combination of the bundle identifier and the URL scheme allowance is what makes x-apple.systempreferences:com.apple.Passwords work as the entry point.
  • The urlSchemes list (otpauth, apple-otpauth) shows that this extension also registers itself to handle OTP/2FA provisioning URIs.

We can check the extension binary for potentially exposed identifiers or anchors by dumping its strings with gstrings (from brew install binutils):

⇒ gstrings /System/Cryptexes/App/System/Library/CoreServices/PasswordsSettingsExtension.appex/Contents/MacOS/PasswordsSettingsExtension | subl
..snip..

From that scan, one of the more immediately notable parts was references to two private frameworks:

  • /System/Library/PrivateFrameworks/PasswordManagerUI.framework/Versions/A/PasswordManagerUI
  • /System/Library/PrivateFrameworks/Settings.framework/Versions/A/Settings

These frameworks are likely where the pane’s UI and any anchor definitions are implemented, rather than in the extension binary itself.

⇒ file /System/Library/PrivateFrameworks/PasswordManagerUI.framework
/System/Library/PrivateFrameworks/PasswordManagerUI.framework: directory

⇒ file /System/Library/PrivateFrameworks/Settings.framework
/System/Library/PrivateFrameworks/Settings.framework: directory

When listing PasswordManagerUI.framework/Versions/A/ only Resources/ and _CodeSignature/ appear. This means the actual binary is not present in the framework bundle; instead, it is stored in the dyld shared cache.

Since Big Sur, Apple moved most system and private framework binaries into the shared cache. The framework directories under /System/Library/PrivateFrameworks/... are just stubs for resources and code signing.

We need a tool to extract binaries from the dyld shared cache. While it’s possible to tweak and build Apple’s own dyld_shared_cache_util from their open source releases, the easier path is to use dyld-shared-cache-extractor, which is packaged for Homebrew:

Install it with:

brew install keith/formulae/dyld-shared-cache-extractor

Next we need to find where the dyld cache files are; which you could probably do with something like this if you need to:

⇒ fd --type file 'dyld_shared_cache_*' /System

But on my system was:

⇒ ls /System/Volumes/Preboot/Cryptexes/OS/System/Library/dyld
dyld_shared_cache_x86_64h*     dyld_shared_cache_x86_64h.03*  dyld_shared_cache_x86_64h.map*
dyld_shared_cache_x86_64h.01*  dyld_shared_cache_x86_64h.04*
dyld_shared_cache_x86_64h.02*  dyld_shared_cache_x86_64h.05*

Looking at the types of those files, we can see that /System/Volumes/Preboot/Cryptexes/OS/System/Library/dyld/dyld_shared_cache_x86_64h.map seems to be ASCII text:

⇒ file /System/Volumes/Preboot/Cryptexes/OS/System/Library/dyld/*
/System/Volumes/Preboot/Cryptexes/OS/System/Library/dyld/dyld_shared_cache_x86_64h:     Dyld shared cache version 1 x86_64h
/System/Volumes/Preboot/Cryptexes/OS/System/Library/dyld/dyld_shared_cache_x86_64h.01:  Dyld shared cache version 1 x86_64h
/System/Volumes/Preboot/Cryptexes/OS/System/Library/dyld/dyld_shared_cache_x86_64h.02:  Dyld shared cache version 1 x86_64h
/System/Volumes/Preboot/Cryptexes/OS/System/Library/dyld/dyld_shared_cache_x86_64h.03:  Dyld shared cache version 1 x86_64h
/System/Volumes/Preboot/Cryptexes/OS/System/Library/dyld/dyld_shared_cache_x86_64h.04:  Dyld shared cache version 1 x86_64h
/System/Volumes/Preboot/Cryptexes/OS/System/Library/dyld/dyld_shared_cache_x86_64h.05:  Dyld shared cache version 1 x86_64h
/System/Volumes/Preboot/Cryptexes/OS/System/Library/dyld/dyld_shared_cache_x86_64h.map: ASCII text

Opening it, we can search for /System/Library/PrivateFrameworks/PasswordManagerUI.framework/Versions/A/PasswordManagerUI and see:

/System/Library/PrivateFrameworks/PasswordManagerUI.framework/Versions/A/PasswordManagerUI
            __TEXT 0x7FFC0193C000 -> 0x7FFC01BBAFF7
      __DATA_CONST 0x7FFC42B29488 -> 0x7FFC42B41D10
            __DATA 0x7FFC40A85790 -> 0x7FFC40AA43B8
        __LINKEDIT 0x7FFC80000000 -> 0x7FFC898A0000

So that confirms its there.

Apparently dyld-shared-cache-extractor is a simple wrapper around Apple’s private dsc_extractor.bundle; and it will only loop through and extract everything. dsc_extractor.bundle apparently does have the ability to extract just one dylib/framework if called directly; and supposedly Apple’s own tool dyld_shared_cache_util exposes it via -path.

TODO: Continue the investigation by figuring how to extract the thing we want.

TODO: Then examine that with gstrings to search for anchor names or navigation constants, and tools like nm -g or otool -ov to check for exported symbols that might include usable identifiers, etc

Unsorted

dyld_info

  • dyld_infoStatic analysis: Inspecting binaries and their dyld-related metadata.
  • Purpose:
    • dyld_info is a diagnostic and inspection tool. It shows you the information that the dynamic linker (dyld) uses when loading binaries and dynamic libraries (.dylib).
  • What it’s useful for:
    • Checking what platform a binary was built for (macOS, iOS, etc.).
    • Listing segments and sections in the binary.
    • Showing dependent dylibs (what libraries it links against).
    • Inspecting initializers (+load methods, static init functions).
    • Listing symbols that the binary exports or imports.
    • Inspecting Objective-C classes and categories defined inside.
    • Looking at how fixups are encoded:
      • Old opcode-based fixups (rebasing, binding).
      • Modern chained fixups (used on Apple Silicon and newer macOS versions).
    • Debugging issues with symbol resolution, fixups, or malformed binaries.
    • Validating binaries (with -validate_only).
  • Analogy: Similar to otool or nm, but focused specifically on the metadata that dyld cares about at runtime. It’s essentially a “what does dyld see here?” inspector.

dyld_usage

  • dyld_usageDynamic tracing: Watching dyld in action as processes run.
  • Purpose:
    • dyld_usage is a runtime tracing tool. It shows dynamic linker activity in real time across processes.
  • What it’s useful for:
    • Monitoring what binaries a process is loading, when it calls dlopen, dlsym, etc.
    • Seeing timestamps, operations, durations, and which process/thread triggered the activity.
    • Debugging slow app launches (e.g. if a process spends lots of time binding libraries).
    • Tracing dynamic linking operations across the system to understand performance or dependency issues.
    • Exporting raw trace files for later analysis.
    • Integrating with automated tools/scripts (it has JSON output, timeouts, filtering).
  • Analogy: Like fs_usage but for dyld operations instead of file system calls. It’s a live tracer rather than a static inspector.

See Also

My Other Related Deepdive Gist's and Projects

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment