macOS Dyld Process
Temel Bilgiler
Bir Mach-o ikili dosyasının gerçek giriş noktası, genellikle /usr/lib/dyld
olarak tanımlanan dinamik bağlantılıdır ve LC_LOAD_DYLINKER
içinde tanımlanmıştır.
Bu bağlayıcı, tüm yürütülebilir kütüphaneleri bulmalı, bunları belleğe eşlemeli ve tüm tembel olmayan kütüphaneleri bağlamalıdır. Bu işlem tamamlandıktan sonra ikili dosyanın giriş noktası yürütülecektir.
Tabii ki, dyld
herhangi bir bağımlılığa sahip değildir (sistem çağrıları ve libSystem alıntıları kullanır).
Bu bağlayıcı herhangi bir güvenlik açığı içeriyorsa, yüksek ayrıcalıklı olanlar da dahil olmak üzere herhangi bir ikili dosya yürütülmeden önce yürütüldüğü için ayrıcalıkları yükseltmek mümkün olabilir.
Akış
Dyld, dyldboostrap::start
tarafından yüklenecek ve ayrıca yığın canary gibi şeyleri de yükleyecektir. Bu işlev, apple
argüman vektöründe bu ve diğer duyarlı değerleri alacağı için bunu yapacaktır.
dyls::_main()
, dyld'nin giriş noktasıdır ve ilk görevi genellikle DYLD_*
ortam değişkenlerini kısıtlayan configureProcessRestrictions()
işlevini çalıştırmaktır:
Daha sonra, önemli sistem kütüphanelerini önceden bağlayan dyld paylaşılan önbelleğini eşler ve ardından ikili dosyanın bağımlı olduğu kütüphaneleri eşler ve ihtiyaç duyulan tüm kütüphaneler yüklenene kadar bu işlemi tekrarlar. Dolayısıyla:
DYLD_INSERT_LIBRARIES
ile eklenen kütüphaneleri yüklemeye başlar (izin verilirse)Ardından paylaşılan önbelleğe sahip olanları
Ardından içe aktarılanları
Daha 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 genellikle LC_ROUTINES[_64]
içinde tanımlanan __attribute__((constructor))
kullanılarak kodlanmıştır (şu anda kullanımdan kaldırılmıştır) veya S_MOD_INIT_FUNC_POINTERS
bayrağı ile işaretlenmiş bir bölümde işaretçi ile.
Sonlandırıcılar __attribute__((destructor))
ile kodlanır ve genellikle S_MOD_TERM_FUNC_POINTERS
bayrağı ile işaretlenmiş bir bölümde bulunur (__DATA.__mod_term_func
).
Yer Tutucular
Tüm macOS ikili dosyaları dinamik olarak bağlanır. Bu nedenle, ikili dosyaların farklı makinelerde ve bağlamlarda doğru kod parçasına atlamasına yardımcı olan bazı yer tutucu bölümleri içerir. İkili dosya yürütüldüğünde, en azından tembel olmayanları çözmesi gereken beyin dyld'dir.
İkili dosyadaki bazı yer tutucu bölümleri:
__TEXT.__[auth_]stubs
:__DATA
bölümlerinden işaretçiler__TEXT.__stub_helper
: Çağrılacak işlev hakkında bilgi içeren küçük kodlarla dinamik bağlantıyı çağıran küçük kodlar__DATA.__[auth_]got
: Global Offset Table (çözüldüğünde ithal edilen işlevlere adresler, yükleme zamanında bağlanır çünküS_NON_LAZY_SYMBOL_POINTERS
bayrağı ile işaretlenmiştir)__DATA.__nl_symbol_ptr
: Tembel olmayan sembol işaretçileri (yükleme zamanında bağlanır çünküS_NON_LAZY_SYMBOL_POINTERS
bayrağı ile işaretlenmiştir)__DATA.__la_symbol_ptr
: Tembel sembol işaretçileri (ilk erişimde bağlanır)
"auth_" önekiyle başlayan işaretçilerin, bunu korumak için bir işlem içi şifreleme anahtarı kullanıldığını unutmayın (PAC). Ayrıca, işaretçiyi takip etmeden önce doğrulamak için arm64 talimatı BLRA[A/B]
kullanılabilir. Ve RETA[A/B], bir RET adresi yerine kullanılabilir.
Aslında, __TEXT.__auth_stubs
içindeki kod, istenen işlevi doğrulamak için braa
yerine bl
kullanacaktır.
Ayrıca, mevcut dyld sürümlerinin her şeyi tembel olmayan olarak yüklediğini unutmayın.
Tembel sembolleri Bulma
İlginç ayrıştırma bölümü:
Mümkün olan printf çağrısına yapılan atlamanın __TEXT.__stubs
'a gideceğini görmek mümkündür:
__stubs
bölümünün ayrıştırılmasında:
Görebileceğiniz gibi GOT adresine atlıyoruz, bu durumda tembelden çözülen ve printf fonksiyonunun adresini içerecek olan adres.
Başka durumlarda GOT'a doğrudan atlamak yerine, __DATA.__la_symbol_ptr
adresine atlayabilir, bu da yüklenmeye çalışılan fonksiyonu temsil eden bir değeri yükler, ardından __TEXT.__stub_helper
adresine atlar, bu da __DATA.__nl_symbol_ptr
adresine atlar, bu da dyld_stub_binder
adresini içerir ve bu adres, fonksiyon numarasını ve bir adresi parametre olarak alır.
Bu son fonksiyon, aranan fonksiyonun adresini bulduktan sonra, gelecekte aramalar yapmamak için bu adresi __TEXT.__stub_helper
içindeki ilgili konuma yazar.
Ancak şu anki dyld sürümlerinin her şeyi tembel yükleme olarak yüklediğine dikkat edin.
Dyld işlem kodları
Son olarak, dyld_stub_binder
'ın belirtilen fonksiyonu bulması ve tekrar aramamak için uygun adrese yazması gerekir. Bunun için dyld içinde işlem kodları (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ş anahtar=değer
şeklindedir. Örneğin:
Bu değerler ana işlevde ulaştığında, hassas bilgiler zaten bunlardan kaldırılmış olacak veya veri sızıntısı olacaktı.
Ana işleme girmeden önce hata ayıklama yaparak tüm bu ilginç değerleri görmek mümkündür:
dyld_all_image_infos
Bu, dyld tarafından ihraç edilen ve dyld durumu hakkında bilgi içeren bir yapıdır. Kaynak kod içinde bulunabilir ve sürüm, dyld_image_info dizisine işaretçi, dyld_image_notifier'a, işlemin paylaşılan önbellekten ayrılıp ayrılmadığına, libSystem başlatıcısının çağrılıp çağrılmadığına, dyld'nin kendi Mach başlığına işaretçi, dyld sürüm dizesine işaretçi gibi bilgiler içerir...
dyld çevresel değişkenler
dyld hata ayıklama
Dyld'ın ne yaptığını anlamaya yardımcı olan ilginç çevresel değişkenler:
DYLD_PRINT_LIBRARIES
Yüklenen her kütüphaneyi kontrol edin:
DYLD_PRINT_SEGMENTS
Her bir kütüphanenin nasıl yüklendiğini kontrol edin:
DYLD_PRINT_INITIALIZERS
Her bir kütüphane başlatıcısının çalıştırıldığında yazdırılmasını sağlar:
Diğerleri
DYLD_BIND_AT_LAUNCH
: Tembel bağlantılar tembelden 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ğlantılarDYLD_[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ıklamayı bir dosyaya yazDYLD_PRINT_APIS
: libdyld API çağrılarını yazdırDYLD_PRINT_APIS_APP
: main tarafından yapılan libdyld API çağrılarını yazdırDYLD_PRINT_BINDINGS
: Bağlandığında sembolleri yazdırDYLD_WEAK_BINDINGS
: Bağlandığında yalnızca zayıf sembolleri yazdırDYLD_PRINT_CODE_SIGNATURES
: Kod imza kayıt işlemlerini yazdırDYLD_PRINT_DOFS
: Yüklenen D-Trace nesne biçimi bölümlerini yazdırDYLD_PRINT_ENV
: dyld tarafından görülen çevreyi 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 yerleştirme işlemlerini yazdırDYLD_RPATHS
: @rpath genişlemelerini yazdırDYLD_PRINT_SEGMENTS
: Mach-O segmentlerinin eşlemelerini yazdırDYLD_PRINT_STATISTICS
: Zamanlama istatistiklerini yazdırDYLD_PRINT_STATISTICS_DETAILS
: Detaylı 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
: Kapanışları etkinleştir
Daha fazlasını şu şekilde bulmak mümkündür:
Veya dyld projesini https://opensource.apple.com/tarballs/dyld/dyld-852.2.tar.gz adresinden indirip klasör içinde çalıştırarak:
Referanslar
Last updated