macOS Dyld Process
Podstawowe informacje
Rzeczywistym punktem wejścia binarnej Mach-o jest dynamiczny linker, zdefiniowany w LC_LOAD_DYLINKER
, zazwyczaj znajduje się w /usr/lib/dyld
.
Ten linker będzie musiał zlokalizować wszystkie biblioteki wykonywalne, zmapować je w pamięci i połączyć wszystkie biblioteki nie-leniwie. Dopiero po tym procesie zostanie wykonany punkt wejścia binarny.
Oczywiście dyld
nie ma żadnych zależności (korzysta z wywołań systemowych i fragmentów libSystem).
Jeśli ten linker zawiera jakąkolwiek podatność, ponieważ jest wykonywany przed wykonaniem jakiegokolwiek binarnego (nawet tych o wysokich uprawnieniach), byłoby możliwe eskalowanie uprawnień.
Przepływ
Dyld zostanie załadowany przez dyldboostrap::start
, który również załaduje rzeczy takie jak canary stosu. Dzieje się tak, ponieważ ta funkcja otrzyma w swoim argumencie apple
ten i inne wrażliwe wartości.
dyls::_main()
jest punktem wejścia dyld i jego pierwszym zadaniem jest uruchomienie configureProcessRestrictions()
, która zazwyczaj ogranicza zmienne środowiskowe DYLD_*
wyjaśnione w:
Następnie mapuje współdzieloną pamięć podręczną dyld, która prelinkuje wszystkie ważne biblioteki systemowe, a następnie mapuje biblioteki, od których zależy binarny, i kontynuuje rekurencyjnie, aż wszystkie potrzebne biblioteki zostaną załadowane. Dlatego:
zaczyna ładować wstawione biblioteki za pomocą
DYLD_INSERT_LIBRARIES
(jeśli jest to dozwolone)Następnie te współdzielone podręczne
Następnie importowane
Następnie kontynuuje importowanie bibliotek rekurencyjnie
Gdy wszystkie są załadowane, uruchamiane są inicjatory tych bibliotek. Są one kodowane za pomocą __attribute__((constructor))
zdefiniowane w LC_ROUTINES[_64]
(obecnie przestarzałe) lub za pomocą wskaźnika w sekcji oznaczonej flagą S_MOD_INIT_FUNC_POINTERS
(zazwyczaj: __DATA.__MOD_INIT_FUNC
).
Terminatory są kodowane za pomocą __attribute__((destructor))
i znajdują się w sekcji oznaczonej flagą S_MOD_TERM_FUNC_POINTERS
(__DATA.__mod_term_func
).
Wskaźniki
Wszystkie binarne pliki w macOS są dynamicznie łączone. Dlatego zawierają pewne sekcje stubs, które pomagają binarnemu skoczyć do poprawnego kodu w różnych maszynach i kontekstach. To dyld, gdy binarny jest wykonywany, musi rozwiązać te adresy (przynajmniej te nie-leniwie).
Niektóre sekcje stubs w binarnym:
__TEXT.__[auth_]stubs
: Wskaźniki z sekcji__DATA
__TEXT.__stub_helper
: Mały kod wywołujący dynamiczne łączenie z informacją o funkcji do wywołania__DATA.__[auth_]got
: Globalna tabela przesunięć (adresy do importowanych funkcji, rozwiązane podczas czasu ładowania, ponieważ jest oznaczone flagąS_NON_LAZY_SYMBOL_POINTERS
)__DATA.__nl_symbol_ptr
: Wskaźniki symboli nie-leniwych (rozwiązane podczas czasu ładowania, ponieważ jest oznaczone flagąS_NON_LAZY_SYMBOL_POINTERS
)__DATA.__la_symbol_ptr
: Wskaźniki symboli leniwych (rozwiązane przy pierwszym dostępie)
Zauważ, że wskaźniki z prefiksem "auth_" używają jednego klucza szyfrowania w procesie do ochrony (PAC). Ponadto możliwe jest użycie instrukcji arm64 BLRA[A/B]
do weryfikacji wskaźnika przed jego śledzeniem. A zamiast adresu RET można użyć RETA[A/B].
Faktycznie kod w __TEXT.__auth_stubs
będzie używał braa
zamiast bl
do wywołania żądanej funkcji w celu uwierzytelnienia wskaźnika.
Zauważ również, że obecne wersje dyld ładują wszystko jako nie-lenwe.
Wyszukiwanie symboli leniwych
Interesujący fragment rozkładu:
Możliwe jest zauważenie, że skok do wywołania printf przechodzi do __TEXT.__stubs
:
Podczas analizy sekcji __stubs
:
Możesz zauważyć, że skaczemy do adresu GOT, który w tym przypadku jest rozwiązany natychmiastowo i będzie zawierał adres funkcji printf.
W innych sytuacjach zamiast bezpośrednio skakać do GOT, można skoczyć do __DATA.__la_symbol_ptr
, który załaduje wartość reprezentującą funkcję, którą próbuje załadować, a następnie skoczyć do __TEXT.__stub_helper
, który skacze do __DATA.__nl_symbol_ptr
, który zawiera adres dyld_stub_binder
, który jako parametry przyjmuje numer funkcji i adres.
Ta ostatnia funkcja, po znalezieniu adresu poszukiwanej funkcji, zapisuje go w odpowiednim miejscu w __TEXT.__stub_helper
, aby uniknąć przeszukiwania w przyszłości.
Zauważ jednak, że obecne wersje dyld ładują wszystko jako natychmiastowe.
Opcodes Dyld
W końcu, dyld_stub_binder
musi znaleźć wskazaną funkcję i zapisać ją pod odpowiednim adresem, aby nie szukać jej ponownie. Aby to zrobić, używa operacji (maszyny stanów skończonych) wewnątrz dyld.
apple[] argument vector
W macOS funkcja główna faktycznie otrzymuje 4 argumenty zamiast 3. Czwarty nazywa się apple, a każdy wpis ma formę klucz=wartość
. Na przykład:
macOS Dynamic Linker (dyld) Process
macOS Biblioteka Wstrzykiwania
Biblioteka dynamiczna (dyld) w systemie macOS jest odpowiedzialna za ładowanie plików wykonywalnych i bibliotek do pamięci procesu. Atakujący może wykorzystać proces ładowania bibliotek przez dyld do wstrzyknięcia złośliwego kodu do procesu lub do nadpisania istniejących funkcji bibliotecznych. To może prowadzić do eskalacji uprawnień lub innych ataków na system. Aby zabezpieczyć system macOS przed tego typu atakami, należy podjąć odpowiednie środki ostrożności, takie jak monitorowanie procesów, ograniczanie uprawnień procesów oraz regularne aktualizacje systemu.
Do czasu dotarcia tych wartości do funkcji głównej, wrażliwe informacje zostały już z nich usunięte lub doszłoby do wycieku danych.
można zobaczyć wszystkie te interesujące wartości debugując przed wejściem do funkcji głównej za pomocą:
dyld_all_image_infos
Jest to struktura eksportowana przez dyld z informacjami o stanie dyld, które można znaleźć w kodzie źródłowym z informacjami takimi jak wersja, wskaźnik do tablicy dyld_image_info, do dyld_image_notifier, czy proces jest odłączony od pamięci podręcznej współdzielonej, czy został wywołany inicjalizator libSystem, wskaźnik do własnego nagłówka Mach dyld, wskaźnik do ciągu wersji dyld...
Zmienne środowiskowe dyld
debug dyld
Interesujące zmienne środowiskowe pomagające zrozumieć, co robi dyld:
DYLD_PRINT_LIBRARIES
Sprawdź każdą bibliotekę, która jest ładowana:
DYLD_PRINT_SEGMENTS
Sprawdź, jak jest ładowana każda biblioteka:
DYLD_PRINT_INITIALIZERS
Drukuj, kiedy uruchamiany jest każdy inicjalizator biblioteki:
Inne
DYLD_BIND_AT_LAUNCH
: Leniwe wiązania są rozwiązywane z wiązaniami natychmiastowymiDYLD_DISABLE_PREFETCH
: Wyłącza wczytywanie wstępne zawartości __DATA i __LINKEDITDYLD_FORCE_FLAT_NAMESPACE
: Wiązania jednopoziomoweDYLD_[FRAMEWORK/LIBRARY]_PATH | DYLD_FALLBACK_[FRAMEWORK/LIBRARY]_PATH | DYLD_VERSIONED_[FRAMEWORK/LIBRARY]_PATH
: Ścieżki rozwiązaniaDYLD_INSERT_LIBRARIES
: Ładuje określoną bibliotekęDYLD_PRINT_TO_FILE
: Zapisuje debugowanie dyld do plikuDYLD_PRINT_APIS
: Wyświetla wywołania API libdyldDYLD_PRINT_APIS_APP
: Wyświetla wywołania API libdyld dokonane przez główny programDYLD_PRINT_BINDINGS
: Wyświetla symbole podczas wiązaniaDYLD_WEAK_BINDINGS
: Wyświetla tylko słabe symbole podczas wiązaniaDYLD_PRINT_CODE_SIGNATURES
: Wyświetla operacje rejestracji sygnatur koduDYLD_PRINT_DOFS
: Wyświetla sekcje formatu obiektu D-Trace jako załadowaneDYLD_PRINT_ENV
: Wyświetla środowisko widziane przez dyldDYLD_PRINT_INTERPOSTING
: Wyświetla operacje interpostowaniaDYLD_PRINT_LIBRARIES
: Wyświetla załadowane bibliotekiDYLD_PRINT_OPTS
: Wyświetla opcje ładowaniaDYLD_REBASING
: Wyświetla operacje przesunięcia symboliDYLD_RPATHS
: Wyświetla rozwinięcia @rpathDYLD_PRINT_SEGMENTS
: Wyświetla odwzorowania segmentów Mach-ODYLD_PRINT_STATISTICS
: Wyświetla statystyki czasoweDYLD_PRINT_STATISTICS_DETAILS
: Wyświetla szczegółowe statystyki czasoweDYLD_PRINT_WARNINGS
: Wyświetla komunikaty ostrzegawczeDYLD_SHARED_CACHE_DIR
: Ścieżka do użycia dla pamięci podręcznej współdzielonych bibliotekDYLD_SHARED_REGION
: "use", "private", "avoid"DYLD_USE_CLOSURES
: Włącza zamknięcia
Możliwe jest znalezienie więcej za pomocą:
Lub pobierając projekt dyld z https://opensource.apple.com/tarballs/dyld/dyld-852.2.tar.gz i uruchamiając go wewnątrz folderu:
Odnośniki
Last updated