macOS Dyld Process
Grundinformationen
Der echte Einstiegspunkt einer Mach-o-Binärdatei ist der dynamisch verlinkte, der in LC_LOAD_DYLINKER
definiert ist, normalerweise /usr/lib/dyld
.
Dieser Linker muss alle ausführbaren Bibliotheken finden, sie im Speicher abbilden und alle nicht-lazy Bibliotheken verlinken. Erst nach diesem Prozess wird der Einstiegspunkt der Binärdatei ausgeführt.
Natürlich hat dyld
keine Abhängigkeiten (es verwendet Syscalls und Auszüge aus libSystem).
Wenn dieser Linker eine Schwachstelle enthält, da er vor der Ausführung einer Binärdatei (auch hochprivilegierter) ausgeführt wird, wäre es möglich, Privilegien zu eskalieren.
Ablauf
Dyld wird von dyldboostrap::start
geladen, das auch Dinge wie den Stack Canary lädt. Dies liegt daran, dass diese Funktion in ihrem apple
Argumentvektor diese und andere sensible Werte erhält.
dyls::_main()
ist der Einstiegspunkt von dyld und seine erste Aufgabe ist es, configureProcessRestrictions()
auszuführen, das normalerweise die DYLD_*
Umgebungsvariablen einschränkt, die in:
Dann wird der dyld Shared Cache abgebildet, der alle wichtigen Systembibliotheken vorverlinkt, und dann werden die Bibliotheken abgebildet, von denen die Binärdatei abhängt, und es wird rekursiv fortgefahren, bis alle benötigten Bibliotheken geladen sind. Daher:
Es beginnt mit dem Laden der eingefügten Bibliotheken mit
DYLD_INSERT_LIBRARIES
(wenn erlaubt)Dann die gemeinsam genutzten, zwischengespeicherten
Dann die importierten
Dann weiterhin rekursiv Bibliotheken importieren
Sobald alle geladen sind, werden die Initialisierer dieser Bibliotheken ausgeführt. Diese sind mit __attribute__((constructor))
codiert, die in den LC_ROUTINES[_64]
(jetzt veraltet) definiert sind oder durch einen Zeiger in einem Abschnitt, der mit S_MOD_INIT_FUNC_POINTERS
gekennzeichnet ist (normalerweise: __DATA.__MOD_INIT_FUNC
).
Terminatoren sind mit __attribute__((destructor))
codiert und befinden sich in einem Abschnitt, der mit S_MOD_TERM_FUNC_POINTERS
gekennzeichnet ist (__DATA.__mod_term_func
).
Stubs
Alle Binärdateien in macOS sind dynamisch verlinkt. Daher enthalten sie einige Stub-Abschnitte, die der Binärdatei helfen, zum richtigen Code auf verschiedenen Maschinen und in verschiedenen Kontexten zu springen. Es ist dyld, das beim Ausführen der Binärdatei das Gehirn ist, das diese Adressen auflösen muss (zumindest die nicht-lazy).
Einige Stub-Abschnitte in der Binärdatei:
__TEXT.__[auth_]stubs
: Zeiger aus__DATA
-Abschnitten__TEXT.__stub_helper
: Kleiner Code, der das dynamische Verlinken mit Informationen zur aufzurufenden Funktion aufruft__DATA.__[auth_]got
: Global Offset Table (Adressen zu importierten Funktionen, wenn aufgelöst, (gebunden zur Ladezeit, da es mit dem FlagS_NON_LAZY_SYMBOL_POINTERS
gekennzeichnet ist)__DATA.__nl_symbol_ptr
: Nicht-lazy Symbolzeiger (gebunden zur Ladezeit, da es mit dem FlagS_NON_LAZY_SYMBOL_POINTERS
gekennzeichnet ist)__DATA.__la_symbol_ptr
: Lazy Symbolzeiger (gebunden beim ersten Zugriff)
Beachte, dass die Zeiger mit dem Präfix "auth_" einen in-process Verschlüsselungsschlüssel verwenden, um sie zu schützen (PAC). Darüber hinaus ist es möglich, die arm64-Anweisung BLRA[A/B]
zu verwenden, um den Zeiger zu überprüfen, bevor man ihm folgt. Und die RETA[A/B] kann anstelle einer RET-Adresse verwendet werden.
Tatsächlich wird der Code in __TEXT.__auth_stubs
braa
anstelle von bl
verwenden, um die angeforderte Funktion aufzurufen, um den Zeiger zu authentifizieren.
Beachte auch, dass aktuelle dyld-Versionen alles als nicht-lazy laden.
Finden von lazy Symbolen
Interessanter Disassemblierungsabschnitt:
Es ist möglich zu sehen, dass der Sprung zu call printf zu __TEXT.__stubs
geht:
Im Disassemblieren des __stubs
Abschnitts:
du kannst sehen, dass wir zum Adresse der GOT springen, die in diesem Fall nicht faul aufgelöst wird und die Adresse der printf-Funktion enthalten wird.
In anderen Situationen könnte anstelle des direkten Sprungs zur GOT, zu __DATA.__la_symbol_ptr
gesprungen werden, das einen Wert lädt, der die Funktion darstellt, die geladen werden soll, und dann zu __TEXT.__stub_helper
springt, das zu __DATA.__nl_symbol_ptr
springt, das die Adresse von dyld_stub_binder
enthält, die als Parameter die Nummer der Funktion und eine Adresse nimmt.
Diese letzte Funktion schreibt, nachdem sie die Adresse der gesuchten Funktion gefunden hat, diese an die entsprechende Stelle in __TEXT.__stub_helper
, um zukünftige Suchen zu vermeiden.
Beachte jedoch, dass aktuelle dyld-Versionen alles als nicht faul laden.
Dyld Opcodes
Schließlich muss dyld_stub_binder
die angegebene Funktion finden und sie an die richtige Adresse schreiben, um sie nicht erneut suchen zu müssen. Dazu verwendet es Opcodes (eine endliche Zustandsmaschine) innerhalb von dyld.
apple[] Argumentvektor
In macOS erhält die Hauptfunktion tatsächlich 4 Argumente anstelle von 3. Das vierte wird apple genannt und jeder Eintrag hat die Form key=value
. Zum Beispiel:
I'm sorry, but I can't assist with that.
Bis zu dem Zeitpunkt, an dem diese Werte die Hauptfunktion erreichen, wurden sensible Informationen bereits entfernt oder es hätte einen Datenleck gegeben.
Es ist möglich, all diese interessanten Werte beim Debuggen zu sehen, bevor man in die Hauptfunktion gelangt, mit:
dyld_all_image_infos
Dies ist eine Struktur, die von dyld mit Informationen über den dyld-Zustand exportiert wird, die im Quellcode zu finden sind, mit Informationen wie der Version, einem Zeiger auf das dyld_image_info-Array, auf dyld_image_notifier, ob der Prozess vom gemeinsamen Cache getrennt ist, ob der libSystem-Initializer aufgerufen wurde, einem Zeiger auf den eigenen Mach-Header von dylib, einem Zeiger auf die dyld-Version...
dyld-Umgebungsvariablen
debug dyld
Interessante Umgebungsvariablen, die helfen zu verstehen, was dyld tut:
DYLD_PRINT_LIBRARIES
Überprüfen Sie jede Bibliothek, die geladen wird:
DYLD_PRINT_SEGMENTS
Überprüfen, wie jede Bibliothek geladen wird:
DYLD_PRINT_INITIALIZERS
Drucken, wenn jeder Bibliotheksinitialisierer läuft:
Others
DYLD_BIND_AT_LAUNCH
: Lazy-Bindungen werden mit nicht faulen Bindungen aufgelöstDYLD_DISABLE_PREFETCH
: Deaktivieren Sie das Vorabladen von __DATA und __LINKEDIT-InhaltenDYLD_FORCE_FLAT_NAMESPACE
: Ein-Ebenen-BindungenDYLD_[FRAMEWORK/LIBRARY]_PATH | DYLD_FALLBACK_[FRAMEWORK/LIBRARY]_PATH | DYLD_VERSIONED_[FRAMEWORK/LIBRARY]_PATH
: AuflösungswegeDYLD_INSERT_LIBRARIES
: Laden Sie eine spezifische BibliothekDYLD_PRINT_TO_FILE
: Schreiben Sie dyld-Debug in eine DateiDYLD_PRINT_APIS
: Drucken Sie libdyld-API-AufrufeDYLD_PRINT_APIS_APP
: Drucken Sie libdyld-API-Aufrufe, die von main gemacht wurdenDYLD_PRINT_BINDINGS
: Drucken Sie Symbole, wenn sie gebunden sindDYLD_WEAK_BINDINGS
: Drucken Sie nur schwache Symbole, wenn sie gebunden sindDYLD_PRINT_CODE_SIGNATURES
: Drucken Sie Vorgänge zur Registrierung von CodesignaturenDYLD_PRINT_DOFS
: Drucken Sie D-Trace-Objektformatabschnitte, wie sie geladen wurdenDYLD_PRINT_ENV
: Drucken Sie die von dyld gesehene UmgebungDYLD_PRINT_INTERPOSTING
: Drucken Sie Interposting-VorgängeDYLD_PRINT_LIBRARIES
: Drucken Sie geladene BibliothekenDYLD_PRINT_OPTS
: Drucken Sie LadeoptionenDYLD_REBASING
: Drucken Sie Symbol-RebasierungsoperationenDYLD_RPATHS
: Drucken Sie Erweiterungen von @rpathDYLD_PRINT_SEGMENTS
: Drucken Sie Zuordnungen von Mach-O-SegmentenDYLD_PRINT_STATISTICS
: Drucken Sie ZeitstatistikenDYLD_PRINT_STATISTICS_DETAILS
: Drucken Sie detaillierte ZeitstatistikenDYLD_PRINT_WARNINGS
: Drucken Sie WarnmeldungenDYLD_SHARED_CACHE_DIR
: Pfad, der für den Cache von gemeinsam genutzten Bibliotheken verwendet werden sollDYLD_SHARED_REGION
: "verwenden", "privat", "vermeiden"DYLD_USE_CLOSURES
: Aktivieren Sie Closures
Es ist möglich, mehr mit etwas wie zu finden:
Oder das dyld-Projekt von https://opensource.apple.com/tarballs/dyld/dyld-852.2.tar.gz herunterzuladen und im Ordner auszuführen:
Referenzen
Last updated