macOS Universal binaries & Mach-O Format
Temel Bilgiler
Mac OS ikili dosyaları genellikle evrensel ikili dosyalar olarak derlenir. Bir evrensel ikili dosya, aynı dosyada birden fazla mimariyi destekleyebilir.
Bu ikili dosyalar genellikle Mach-O yapısını takip eder, bu yapının temel olarak şunlardan oluşur:
Başlık
Yükleme Komutları
Veri
Yağlı Başlık
Dosyayı şu komutla arayın: mdfind fat.h | grep -i mach-o | grep -E "fat.h$"
Başlık, sihirli baytları ve dosyanın içerdiği mimari sayısını (nfat_arch
) takip eden her mimarinin bir fat_arch
yapısına sahip olduğu sayıları içerir.
Şununla kontrol edin:
veya Mach-O View aracını kullanarak:
Genellikle 2 mimari için derlenen evrensel bir ikili dosya, sadece 1 mimari için derlenen bir dosyanın boyutunu iki katına çıkarır.
Mach-O Başlık
Başlık, dosya hakkında temel bilgiler içerir, örneğin sihirli baytlarla dosyayı Mach-O dosyası olarak tanımlamak ve hedef mimari hakkında bilgi içerir. Şurada bulabilirsiniz: mdfind loader.h | grep -i mach-o | grep -E "loader.h$"
Mach-O Dosya Türleri
Farklı dosya türleri bulunmaktadır, bunlar örneğin burada tanımlanmıştır. En önemlileri şunlardır:
MH_OBJECT
: Taşınabilir nesne dosyası (derlemenin ara ürünleri, henüz yürütülebilir değil).MH_EXECUTE
: Yürütülebilir dosyalar.MH_FVMLIB
: Sabit VM kütüphane dosyası.MH_CORE
: Kod DökümleriMH_PRELOAD
: Önceden yüklenmiş yürütülebilir dosya (artık XNU'da desteklenmiyor)MH_DYLIB
: Dinamik KütüphanelerMH_DYLINKER
: Dinamik BağlayıcıMH_BUNDLE
: "Eklenti dosyaları".NSBundle
veyadlopen
tarafından açıkça yüklenen -bundle ile oluşturulur.MH_DYSM
: Eş.dSym
dosyası (hata ayıklama sembolleri içeren dosya).MH_KEXT_BUNDLE
: Çekirdek Uzantıları.
Veya Mach-O View kullanarak:
Mach-O Bayrakları
Kaynak kod ayrıca kütüphaneleri yükleme için kullanışlı birkaç bayrak tanımlar:
MH_NOUNDEFS
: Tanımsız referans yok (tam bağlantılı)MH_DYLDLINK
: Dyld bağlantısıMH_PREBOUND
: Dinamik referanslar önceden bağlanmış.MH_SPLIT_SEGS
: Dosya r/o ve r/w segmentlere bölünmüştür.MH_WEAK_DEFINES
: Binanın zayıf tanımlı sembolleri vardırMH_BINDS_TO_WEAK
: Bina zayıf sembolleri kullanırMH_ALLOW_STACK_EXECUTION
: Yığını yürütülebilir yapMH_NO_REEXPORTED_DYLIBS
: Kütüphane LC_REEXPORT komutlarına sahip değilMH_PIE
: Konum Bağımsız YürütülebilirMH_HAS_TLV_DESCRIPTORS
: İplik yerel değişkenlere sahip bir bölüm varMH_NO_HEAP_EXECUTION
: Yığın/veri sayfaları için yürütme yokMH_HAS_OBJC
: Bina Objective-C bölümlerine sahipMH_SIM_SUPPORT
: Simülatör desteğiMH_DYLIB_IN_CACHE
: Paylaşılan kütüphane önbelleğindeki dylibs/frameworks üzerinde kullanılır.
Mach-O Yükleme komutları
Dosyanın bellekteki düzeni burada belirtilir, sembol tablosunun konumu, yürütme başlangıcında ana iş parçacığının bağlamı ve gerekli paylaşılan kütüphaneler ayrıntılandırılır. Talimatlar, binary'nin belleğe yükleme süreci hakkında dinamik yükleyici (dyld) için sağlanır.
Kullanılan load_command yapısı, bahsedilen loader.h
içinde tanımlanmıştır:
Sistem farklı şekillerde işlediği yaklaşık 50 farklı yükleme komutu türü bulunmaktadır. En yaygın olanlar şunlardır: LC_SEGMENT_64
, LC_LOAD_DYLINKER
, LC_MAIN
, LC_LOAD_DYLIB
ve LC_CODE_SIGNATURE
.
LC_SEGMENT/LC_SEGMENT_64
Temelde, bu tür Yükleme Komutları, ikili dosya yürütüldüğünde __TEXT (yürütülebilir kod) ve __DATA (işlem için veri) segmentlerini yüklemenin Data bölümünde belirtilen ofsetlere göre nasıl yapılacağını tanımlar.
Bu komutlar, bir işlem yürütüldüğünde sanal bellek alanına eşlenen segmentleri tanımlar.
Farklı türlerde segmentler bulunmaktadır, örneğin bir programın yürütülebilir kodunu tutan __TEXT segmenti ve işlem tarafından kullanılan verileri içeren __DATA segmenti. Bu segmentler, Mach-O dosyasının veri bölümünde bulunmaktadır.
Her segment, daha fazla bölümlere ayrılabilir. Yükleme komutu yapısı, ilgili segment içindeki bu bölümler hakkında bilgi içerir.
Başlıkta önce segment başlığını bulursunuz:
Segment başlığının örneği:
Bu başlık, ardından başlıkları görünen bölümlerin sayısını tanımlar:
Örnek bölüm başlığı:
Eğer bölüm ofseti (0x37DC) + mimarinin başladığı ofset eklenirse, bu durumda 0x18000
--> 0x37DC + 0x18000 = 0x1B7DC
Ayrıca komut satırından başlık bilgilerini almak da mümkündür:
Bu komut tarafından yüklenen yaygın bölümler:
__PAGEZERO
: Çekirdeğe adres sıfırını haritalamayı emreder, böylece bu sayfadan okunamaz, yazılamaz veya yürütülemez. Yapıdaki maxprot ve minprot değişkenleri sıfıra ayarlanır, bu da bu sayfada okuma-yazma-yürütme haklarının olmadığını gösterir.Bu tahsis, NULL işaretçi sıfırlama güvenlik açıklarını hafifletmek için önemlidir. Bu, XNU'nun yalnızca belleğin ilk sayfasının (yalnızca ilk sayfa) erişilemez olduğunu sağlayan sert bir sayfa sıfırını zorunlu kılmasından kaynaklanmaktadır (yalnızca i386'da). Bir ikili dosya, küçük bir __PAGEZERO oluşturarak (
-pagezero_size
kullanarak) ilk 4k'yi kapsayabilir ve geri kalan 32 bit belleğin hem kullanıcı hem de çekirdek modunda erişilebilir olmasını sağlayabilir.__TEXT
: Okunabilir ve yürütülebilir izinlere sahip yürütülebilir kod içerir (yazılabilir değil). Bu segmentin yaygın bölümleri:__text
: Derlenmiş ikili kod__const
: Sabit veri (yalnızca okunabilir)__[c/u/os_log]string
: C, Unicode veya os log dizisi sabitleri__stubs
ve__stubs_helper
: Dinamik kitaplık yükleme sürecinde rol oynar__unwind_info
: Yığın açma verileri.Tüm bu içeriğin imzalandığını ancak aynı zamanda yürütülebilir olarak işaretlendiğini unutmayın (bu ayrıcalığa ihtiyaç duymayan bölümlerin söz konusu ayrıcalığı gerektirmeyen bölümlerin sömürülmesi için daha fazla seçenek yaratır).
__DATA
: Okunabilir ve yazılabilir verileri içerir (yürütülemez).__got:
Global Offset Table__nl_symbol_ptr
: Tembel olmayan (yükleme sırasında bağlanır) sembol işaretçisi__la_symbol_ptr
: Tembel (kullanımda bağlanır) sembol işaretçisi__const
: Gerçekte yalnızca okunabilir veri olmalıdır__cfstring
: CoreFoundation dizeleri__data
: Başlatılmış küresel değişkenler__bss
: Başlatılmamış statik değişkenler__objc_*
(__objc_classlist, __objc_protolist, vb.): Objective-C çalışma zamanı tarafından kullanılan bilgiler__DATA_CONST
: __DATA.__const'ın sabit olması garanti edilmez (yazma izinleri), diğer işaretçiler ve GOT de değil. Bu bölüm,__const
, bazı başlatıcılar ve GOT tablosunu (çözümlendikten sonra)mprotect
kullanarak salt okunur yapar.__LINKEDIT
: Bağlayıcı için (dyld gibi) sembol, dize ve yer değiştirme tablosu girişleri gibi bilgileri içerir. Bu, ne__TEXT
ne de__DATA
içinde olmayan içerikler için genel bir konteynerdir ve içeriği diğer yükleme komutlarında açıklanmıştır.dyld bilgileri: Yeniden konumlandırma, Tembel olmayan/tembel/zayıf bağlama işlemleri ve ihraç bilgileri
Fonksiyon başlangıçları: Fonksiyonların başlangıç adreslerinin tablosu
Kod İçindeki Veriler: __text içindeki veri adaları
Sembol Tablosu: İkili dosyadaki semboller
Dolaylı Sembol Tablosu: İşaretçi/stub sembolleri
Dize Tablosu
Kod İmzası
__OBJC
: Objective-C çalışma zamanı tarafından kullanılan bilgileri içerir. Bu bilgiler, __DATA segmentinde de bulunabilir, çeşitli __objc_* bölümlerinde.__RESTRICT
: İçeriği olmayan bir bölüm olan__restrict
adlı tek bir bölüm içerir (ayrıca boştur) ve ikili dosya çalıştırıldığında DYLD çevresel değişkenlerini yoksayar.
Kodda görülebileceği gibi, bölümler ayrıca bayrakları da destekler (ancak çok fazla kullanılmazlar):
SG_HIGHVM
: Yalnızca çekirdek (kullanılmaz)SG_FVMLIB
: KullanılmazSG_NORELOC
: Bölümde yer değiştirme yokSG_PROTECTED_VERSION_1
: Şifreleme. Örneğin Finder tarafından metni şifrelemek için__TEXT
segmentini kullanır.
LC_UNIXTHREAD/LC_MAIN
LC_UNIXTHREAD/LC_MAIN
LC_MAIN
, entryoff özniteliğindeki giriş noktasını içerir. Yükleme zamanında, dyld bu değeri (bellekteki) ikili dosyanın tabanına ekler, ardından bu talimata atlayarak ikili dosyanın kodunun yürütmesini başlatmak için bu konuma atlar.
LC_UNIXTHREAD
, ana iş parçacığını başlatırken kayıtların sahip olması gereken değerleri içerir. Bu zaten kullanımdan kaldırılmış olsa da dyld
hala bunu kullanır. Bu ile ayarlanan kayıtların değerlerini görmek mümkündür:
LC_CODE_SIGNATURE
LC_CODE_SIGNATURE
Macho-O dosyasının kod imzası hakkında bilgi içerir. Yalnızca bir imza bloğuna işaret eden bir ofset içerir. Genellikle dosyanın sonunda bulunur. Ancak, bu bölüm hakkında bazı bilgileri bu blog yazısında ve bu gists bulabilirsiniz.
LC_ENCRYPTION_INFO[_64]
LC_ENCRYPTION_INFO[_64]
Binary şifrelemesini destekler. Ancak, tabii ki, bir saldırgan süreci ele geçirmeyi başarırsa, belleği şifrelenmemiş olarak dökme yeteneğine sahip olacaktır.
LC_LOAD_DYLINKER
LC_LOAD_DYLINKER
Paylaşılan kütüphaneleri işlem adres alanına eşleyen dinamik bağlayıcı yürütülebilir dosyanın yolunu içerir. Değeri her zaman /usr/lib/dyld
olarak ayarlanmıştır. macOS'ta dylib eşlemesi çekirdek modunda değil, kullanıcı modunda gerçekleşir.
LC_IDENT
LC_IDENT
Eskidir ancak panik durumunda dökümler oluşturacak şekilde yapılandırıldığında, bir Mach-O çekirdek dökümü oluşturulur ve çekirdek sürümü LC_IDENT
komutunda ayarlanır.
LC_UUID
LC_UUID
Rastgele UUID. Doğrudan herhangi bir şey için faydalı değildir ancak XNU, işlem bilgilerinin geri kalanıyla birlikte önbelleğe alır. Çökme raporlarında kullanılabilir.
LC_DYLD_ENVIRONMENT
LC_DYLD_ENVIRONMENT
İşlem yürütülmeden önce dyld'ye çevresel değişkenleri belirtmeye izin verir. Bu, işlem içinde keyfi kod yürütmesine izin verebileceğinden oldukça tehlikeli olabilir, bu yükleme komutu yalnızca #define SUPPORT_LC_DYLD_ENVIRONMENT
ile derlenmiş dyld'de kullanılır ve yalnızca DYLD_..._PATH
biçiminde yük yollarını belirleyen değişkenlerin işlenmesini daha da kısıtlar.
LC_LOAD_DYLIB
LC_LOAD_DYLIB
Bu yükleme komutu, yükleme ve bağlama işlemini yapılacak kütüphaneyi belirten dinamik kütüphane bağımlılığını açıklar. Mach-O ikili dosyanın gerektirdiği her kütüphane için bir LC_LOAD_DYLIB
yükleme komutu bulunmaktadır.
Bu yükleme komutu, gerçek bağımlı dinamik kütüphaneyi tanımlayan bir yapı olan
dylib_command
türünde bir yapıdır (struct dylib içeren bir dylib yapısı):
Bu bilgiyi ayrıca şu komut satırı aracılığıyla da alabilirsiniz:
Objective-C Ortak Bölümler
__TEXT
segmentinde (r-x):
__objc_classname
: Sınıf isimleri (dizeler)__objc_methname
: Metod isimleri (dizeler)__objc_methtype
: Metod tipleri (dizeler)
__DATA
segmentinde (rw-):
__objc_classlist
: Tüm Objective-C sınıflarına işaretçiler__objc_nlclslist
: Tembel Olmayan Objective-C sınıflarına işaretçiler__objc_catlist
: Kategorilere işaretçi__objc_nlcatlist
: Tembel Olmayan Kategorilere işaretçi__objc_protolist
: Protokoller listesi__objc_const
: Sabit veri__objc_imageinfo
,__objc_selrefs
,objc__protorefs
...
Swift
_swift_typeref
,_swift3_capture
,_swift3_assocty
,_swift3_types, _swift3_proto
,_swift3_fieldmd
,_swift3_builtin
,_swift3_reflstr
Last updated