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.
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.
- Legacy bundle identifier:
- 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.
- https://www.nowsecure.com/blog/2024/09/11/reversing-ios-system-libraries-using-radare2-a-deep-dive-into-dyld-cache-part-1/
- https://www.nowsecure.com/blog/2024/09/12/reversing-ios-system-libraries-using-radare2-a-deep-dive-into-dyld-cache-part-2/
- https://www.nowsecure.com/blog/2024/09/13/reversing-ios-system-libraries-using-radare2-a-deep-dive-into-dyld-cache-part-3/
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:
- https://github.com/keith/dyld-shared-cache-extractor
- https://github.com/arandomdev/DyldExtractor
- https://lapcatsoftware.com/articles/bigsur.html
- https://mjtsai.com/blog/2020/06/26/reverse-engineering-macos-11-0/
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:
- https://stackoverflow.com/questions/73376007/where-are-the-shared-libs-in-macos
/System/Library/dyld/
/System/Volumes/Preboot/Cryptexes/OS/System/Library/dyld/
- https://khronokernel.com/macos/2022/06/22/VENTURA-DYLD.html
⇒ 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
dyld_info
→ Static 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
ornm
, but focused specifically on the metadata that dyld cares about at runtime. It’s essentially a “what does dyld see here?” inspector.
dyld_usage
→ Dynamic 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).
- Monitoring what binaries a process is loading, when it calls
- Analogy:
Like
fs_usage
but for dyld operations instead of file system calls. It’s a live tracer rather than a static inspector.
- https://github.com/0xdevalias
- https://gist.github.com/0xdevalias
- https://github.com/0xdevalias/chatgpt-source-watch : Analyzing the evolution of ChatGPT's codebase through time with curated archives and scripts.
- Reverse Engineering on macOS (0xdevalias' gist)
- Reverse Engineering Golang (0xdevalias' gist)
- Integrating Workflow Automation Tools (Apple Shortcuts, Alfred, BetterTouchTool, etc) via CLI, etc (0xdevalias' gist)
- Event / Workflow Automation Systems (0xdevalias' gist)
- Decompile Apple Shortcuts into raw XML 'source code' (0xdevalias' gist)
- Deobfuscating / Unminifying Obfuscated Web App Code (0xdevalias' gist)
- Reverse Engineering Webpack Apps (0xdevalias' gist)
- React Server Components, Next.js v13+, and Webpack: Notes on Streaming Wire Format (
__next_f
, etc) (0xdevalias' gist)) - Fingerprinting Minified JavaScript Libraries / AST Fingerprinting / Source Code Similarity / Etc (0xdevalias' gist)
- Bypassing Cloudflare, Akamai, etc (0xdevalias' gist)
- Debugging Electron Apps (and related memory issues) (0xdevalias' gist)
- devalias' Beeper CSS Hacks (0xdevalias' gist)