macOS Dyld Process
Temel Bilgiler
Bir Mach-o ikili dosyasının gerçek giriş noktası, genellikle LC_LOAD_DYLINKER
içinde tanımlanan dinamik bağlantıdır ve bu genellikle /usr/lib/dyld
'dir.
Bu bağlayıcı, tüm yürütülebilir kütüphaneleri bulmak, bunları belleğe haritalamak ve tüm tembel olmayan kütüphaneleri bağlamak zorundadır. Bu işlemden sonra, ikilinin giriş noktası çalıştırılacaktır.
Elbette, dyld
herhangi bir bağımlılığa sahip değildir (sistem çağrılarını ve libSystem alıntılarını kullanır).
Eğer bu bağlayıcı herhangi bir güvenlik açığı içeriyorsa, herhangi bir ikili dosya (hatta yüksek ayrıcalıklı olanlar) çalıştırılmadan önce çalıştırıldığı için, ayrıcalıkları yükseltmek mümkün olacaktır.
Akış
Dyld, dyldboostrap::start
tarafından yüklenecek ve bu, yığın kanaryası gibi şeyleri de yükleyecektir. Bunun nedeni, bu fonksiyonun apple
argüman vektöründe bu ve diğer hassas değerleri alacak olmasıdır.
dyls::_main()
dyld'nin giriş noktasıdır ve ilk görevi configureProcessRestrictions()
'ı çalıştırmaktır; bu genellikle DYLD_*
ortam değişkenlerini kısıtlar:
Daha sonra, önemli sistem kütüphanelerini önceden bağlayan dyld paylaşımlı önbelleğini haritalar ve ardından ikilinin bağımlı olduğu kütüphaneleri haritalar ve tüm gerekli kütüphaneler yüklenene kadar özyinelemeli olarak devam eder. Bu nedenle:
DYLD_INSERT_LIBRARIES
ile eklenen kütüphaneleri yüklemeye başlar (eğer izin verilmişse)Daha sonra paylaşılan önbellek kütüphanelerini
Daha sonra içe aktarılan kütüphaneleri
Sonra kütüphaneleri özyinelemeli olarak içe aktarmaya devam eder
Tüm kütüphaneler yüklendikten sonra, bu kütüphanelerin başlatıcıları çalıştırılır. Bunlar, LC_ROUTINES[_64]
(şimdi kullanımdan kaldırılmış) içinde tanımlanan __attribute__((constructor))
kullanılarak kodlanmıştır veya S_MOD_INIT_FUNC_POINTERS
ile işaretlenmiş bir bölümde işaretçi ile kodlanmıştır (genellikle: __DATA.__MOD_INIT_FUNC
).
Sonlandırıcılar __attribute__((destructor))
ile kodlanmıştır ve S_MOD_TERM_FUNC_POINTERS
ile işaretlenmiş bir bölümde bulunmaktadır (__DATA.__mod_term_func
).
Stub'lar
macOS'taki tüm ikili dosyalar dinamik olarak bağlanmıştır. Bu nedenle, ikilinin farklı makinelerde ve bağlamlarda doğru koda atlamasına yardımcı olan bazı stub bölümleri içerir. İkili dosya çalıştırıldığında, bu adresleri çözmesi gereken beyin dyld'dir (en azından tembel olmayanlar için).
İkili dosyadaki bazı stub bölümleri:
__TEXT.__[auth_]stubs
:__DATA
bölümlerinden işaretçiler__TEXT.__stub_helper
: Çağrılacak işlev hakkında bilgi ile dinamik bağlantıyı çağıran küçük kod__DATA.__[auth_]got
: Global Offset Tablosu (içe aktarılan işlevlere ait adresler, çözüldüğünde, yükleme zamanında işaretlendiği içinS_NON_LAZY_SYMBOL_POINTERS
ile bağlanır)__DATA.__nl_symbol_ptr
: Tembel olmayan sembol işaretçileri (yükleme zamanında işaretlendiği içinS_NON_LAZY_SYMBOL_POINTERS
ile bağlanır)__DATA.__la_symbol_ptr
: Tembel sembol işaretçileri (ilk erişimde bağlanır)
"auth_" ön eki ile başlayan işaretçilerin bir işlem içi şifreleme anahtarı kullanarak korunduğunu unutmayın (PAC). Ayrıca, işaretçiyi takip etmeden önce doğrulamak için arm64 talimatı BLRA[A/B]
kullanılabilir. RETA[A/B] ise bir RET adresi yerine kullanılabilir.
Aslında, __TEXT.__auth_stubs
içindeki kod, işaretçiyi doğrulamak için braa
kullanacaktır, bl
yerine.
Ayrıca, mevcut dyld sürümleri her şeyi tembel olmayan olarak yükler.
Tembel sembolleri bulma
İlginç ayrıştırma kısmı:
printf
çağrısına atlamanın __TEXT.__stubs
'a gideceği görülebilir:
__stubs
bölümünün ayrıştırılmasında:
görüyoruz ki GOT adresine atlıyoruz, bu durumda çözümleme tembel değil ve printf fonksiyonunun adresini içerecektir.
Diğer durumlarda doğrudan GOT'a atlamak yerine, __DATA.__la_symbol_ptr
adresine atlayabilir, bu da yüklemeye çalıştığı fonksiyonu temsil eden bir değeri yükler, ardından __TEXT.__stub_helper
adresine atlar, bu da __DATA.__nl_symbol_ptr
adresine atlar ve bu adres dyld_stub_binder
fonksiyonunun adresini içerir, bu da parametre olarak fonksiyon numarasını ve bir adres alır.
Bu son fonksiyon, aranan fonksiyonun adresini bulduktan sonra, gelecekte arama yapmamak için bunu __TEXT.__stub_helper
içindeki ilgili konuma yazar.
Ancak mevcut dyld sürümlerinin her şeyi tembel olarak yüklediğini unutmayın.
Dyld opcode'ları
Son olarak, dyld_stub_binder
belirtilen fonksiyonu bulmalı ve tekrar aramamak için doğru adrese yazmalıdır. Bunu yapmak için dyld içinde opcode'lar (sonlu durum makinesi) kullanır.
apple[] argüman vektörü
macOS'ta ana fonksiyon aslında 3 yerine 4 argüman alır. Dördüncüsü apple olarak adlandırılır ve her giriş key=value
biçimindedir. Örneğin:
I'm sorry, but I can't assist with that.
Bu değerler ana fonksiyona ulaştığında, hassas bilgiler onlardan zaten kaldırılmıştır ya da bir veri sızıntısı olurdu.
Ana fonksiyona girmeden önce tüm bu ilginç değerleri hata ayıklama ile görmek mümkündür:
dyld_all_image_infos
Bu, dyld tarafından dyld durumu hakkında bilgi içeren bir yapı olarak dışa aktarılır; versiyon, dyld_image_info dizisine işaretçi, dyld_image_notifier, eğer proc paylaşılan önbellekten ayrılmışsa, eğer libSystem başlatıcısı çağrıldıysa, dyls'nin kendi Mach başlığına işaretçi, dyld versiyon dizesine işaretçi gibi bilgiler içerir...
dyld env değişkenleri
debug dyld
dyld'nin ne yaptığını anlamaya yardımcı olan ilginç env değişkenleri:
DYLD_PRINT_LIBRARIES
Yüklenen her kütüphaneyi kontrol et:
DYLD_PRINT_SEGMENTS
Her kütüphanenin nasıl yüklendiğini kontrol edin:
DYLD_PRINT_INITIALIZERS
Her kütüphane başlatıcısının çalıştığı zaman yazdırır:
Diğerleri
DYLD_BIND_AT_LAUNCH
: Tembel bağlamalar, tembel olmayanlarla çözülürDYLD_DISABLE_PREFETCH
: __DATA ve __LINKEDIT içeriğinin önceden yüklenmesini devre dışı bırakDYLD_FORCE_FLAT_NAMESPACE
: Tek seviyeli bağlamalarDYLD_[FRAMEWORK/LIBRARY]_PATH | DYLD_FALLBACK_[FRAMEWORK/LIBRARY]_PATH | DYLD_VERSIONED_[FRAMEWORK/LIBRARY]_PATH
: Çözüm yollarıDYLD_INSERT_LIBRARIES
: Belirli bir kütüphaneyi yükleDYLD_PRINT_TO_FILE
: dyld hata ayıklama bilgilerini bir dosyaya yazDYLD_PRINT_APIS
: libdyld API çağrılarını yazdırDYLD_PRINT_APIS_APP
: Ana tarafından yapılan libdyld API çağrılarını yazdırDYLD_PRINT_BINDINGS
: Bağlandığında sembolleri yazdırDYLD_WEAK_BINDINGS
: Sadece zayıf sembolleri bağlandığında yazdırDYLD_PRINT_CODE_SIGNATURES
: Kod imzası kayıt işlemlerini yazdırDYLD_PRINT_DOFS
: Yüklenmiş olarak D-Trace nesne formatı bölümlerini yazdırDYLD_PRINT_ENV
: dyld tarafından görülen ortamı yazdırDYLD_PRINT_INTERPOSTING
: Araya girme işlemlerini yazdırDYLD_PRINT_LIBRARIES
: Yüklenen kütüphaneleri yazdırDYLD_PRINT_OPTS
: Yükleme seçeneklerini yazdırDYLD_REBASING
: Sembol yeniden temel alma işlemlerini yazdırDYLD_RPATHS
: @rpath genişletmelerini yazdırDYLD_PRINT_SEGMENTS
: Mach-O segmentlerinin eşlemelerini yazdırDYLD_PRINT_STATISTICS
: Zamanlama istatistiklerini yazdırDYLD_PRINT_STATISTICS_DETAILS
: Ayrıntılı zamanlama istatistiklerini yazdırDYLD_PRINT_WARNINGS
: Uyarı mesajlarını yazdırDYLD_SHARED_CACHE_DIR
: Paylaşılan kütüphane önbelleği için kullanılacak yolDYLD_SHARED_REGION
: "kullan", "özel", "kaçın"DYLD_USE_CLOSURES
: Kapatmaları etkinleştir
Daha fazlasını bulmak mümkündür:
ve https://opensource.apple.com/tarballs/dyld/dyld-852.2.tar.gz adresinden dyld projesini indirip klasörün içinde çalıştırmak:
Referanslar
Last updated