macOS Universal binaries & Mach-O Format
Last updated
Last updated
Leer & oefen AWS-hacking:HackTricks Opleiding AWS Red Team Expert (ARTE) Leer & oefen GCP-hacking: HackTricks Opleiding GCP Red Team Expert (GRTE)
Mac OS-bineêre lêers is gewoonlik saamgestel as universele bineêre lêers. 'n Universele bineêre lêer kan verskeie argitekture in dieselfde lêer ondersteun.
Hierdie bineêre lêers volg die Mach-O-struktuur wat basies bestaan uit:
Kop
Laai-opdragte
Data
Soek na die lêer met: mdfind fat.h | grep -i mach-o | grep -E "fat.h$"
Die kop het die magic-byte gevolg deur die aantal argitekture wat die lêer bevat (nfat_arch
) en elke argitektuur sal 'n fat_arch
struktuur hê.
Kontroleer dit met:
of deur die Mach-O View gereedskap te gebruik:
Soos jy dalk dink, verdubbel 'n universele bineêre wat vir 2 argitekture saamgestel is die grootte van een wat net vir 1 argitektuur saamgestel is.
Die kop bevat basiese inligting oor die lêer, soos die magiese byte om dit as 'n Mach-O-lêer te identifiseer en inligting oor die teikenargitektuur. Jy kan dit vind in: mdfind loader.h | grep -i mach-o | grep -E "loader.h$"
Daar is verskillende lêertipes, jy kan hulle gedefinieer vind in die bronkode byvoorbeeld hier. Die belangrikste is:
MH_OBJECT
: Herplaasbare objeklêer (tussenproduk van samestelling, nog nie uitvoerbare lêers nie).
MH_EXECUTE
: Uitvoerbare lêers.
MH_FVMLIB
: Vasgehegte VM-biblioteeklêer.
MH_CORE
: Kode-afsettings
MH_PRELOAD
: Voorafgelaai uitvoerbare lêer (nie meer ondersteun in XNU nie)
MH_DYLIB
: Dinamiese Biblioteke
MH_DYLINKER
: Dinamiese Skakelaar
MH_BUNDLE
: "Inprop-lêers". Opgestel deur -bundle in gcc en eksplisiet gelaai deur NSBundle
of dlopen
.
MH_DYSM
: Metgesel .dSym
lêer (lêer met simbole vir foutopsporing).
MH_KEXT_BUNDLE
: Kernel-uitbreidings.
Of deur Mach-O View te gebruik:
Die bronkode definieer ook verskeie vlae wat nuttig is vir die laai van biblioteke:
MH_NOUNDEFS
: Geen ongedefinieerde verwysings (volledig gekoppel)
MH_DYLDLINK
: Dyld koppeling
MH_PREBOUND
: Dinamiese verwysings vooraf gebind.
MH_SPLIT_SEGS
: Lêer verdeel r/o en r/w segmente.
MH_WEAK_DEFINES
: Binêre het swak gedefinieerde simbole
MH_BINDS_TO_WEAK
: Binêre gebruik swak simbole
MH_ALLOW_STACK_EXECUTION
: Maak die stapel uitvoerbaar
MH_NO_REEXPORTED_DYLIBS
: Biblioteek nie LC_REEXPORT-opdragte nie
MH_PIE
: Posisioneel Onafhanklike Uitvoerbare lêer
MH_HAS_TLV_DESCRIPTORS
: Daar is 'n afdeling met draadlokale veranderlikes
MH_NO_HEAP_EXECUTION
: Geen uitvoering vir heap/data-bladsye
MH_HAS_OBJC
: Binêre het oBject-C afdelings
MH_SIM_SUPPORT
: Simulator-ondersteuning
MH_DYLIB_IN_CACHE
: Gebruik op dylibs/frameworks in gedeelde biblioteekkas.
Die lêer se uitleg in geheue word hier gespesifiseer, met inligting oor die simbooltabel se ligging, die konteks van die hoofdraad by uitvoerbegin, en die vereiste gedeelde biblioteke. Instruksies word aan die dinamiese laaier (dyld) verskaf oor die binêre se laaiproses in geheue.
Dit maak gebruik van die load_command struktuur, gedefinieer in die genoemde loader.h
:
Daar is ongeveer 50 verskillende tipes laai-opdragte wat die stelsel anders hanteer. Die mees algemene is: LC_SEGMENT_64
, LC_LOAD_DYLINKER
, LC_MAIN
, LC_LOAD_DYLIB
, en LC_CODE_SIGNATURE
.
Basies definieer hierdie tipe Laai-opdrag hoe om die __TEXT (uitvoerbare kode) en __DATA (data vir die proses) segmente te laai volgens die offsets aangedui in die Data-seksie wanneer die binêre lêer uitgevoer word.
Hierdie opdragte definieer segmente wat in die virtuele geheue-ruimte van 'n proses ingevoeg word wanneer dit uitgevoer word.
Daar is verskillende tipes segmente, soos die __TEXT segment, wat die uitvoerbare kode van 'n program bevat, en die __DATA segment, wat data bevat wat deur die proses gebruik word. Hierdie segmente is geleë in die data-seksie van die Mach-O lêer.
Elke segment kan verder verdeel word in verskeie seksies. Die laai-opdragstruktuur bevat inligting oor hierdie seksies binne die betrokke segment.
In die kop vind jy die segmentkop:
Voorbeeld van segmentkop:
Hierdie kop definieer die aantal seksies waarvan die koppe daarna verskyn:
Voorbeeld van seksie-kop:
As jy die seksie-offset (0x37DC) + die offset waar die arg begin, in hierdie geval 0x18000
byvoeg --> 0x37DC + 0x18000 = 0x1B7DC
Dit is ook moontlik om koppe-inligting van die opdraglyn te kry met:
Gemeenskaplike segmente wat deur hierdie cmd gelaai word:
__PAGEZERO
: Dit instrueer die kernel om die adres nul te kaart sodat dit nie gelees, geskryf of uitgevoer kan word nie. Die maxprot en minprot veranderlikes in die struktuur word na nul ingestel om aan te dui dat daar geen lees-skuif-uitvoer regte op hierdie bladsy is nie.
Hierdie toewysing is belangrik om NULL-aanwyservulnerabiliteite te verminder. Dit is omdat XNU 'n harde bladsy nul afdwing wat verseker dat die eerste bladsy (slegs die eerste) van geheue onbereikbaar is (behalwe in i386). 'n Binêre kan aan hierdie vereistes voldoen deur 'n klein __PAGEZERO (met die -pagezero_size
) te skep om die eerste 4k te dek en die res van die 32-bis geheue toeganklik te hê in beide gebruiker- en kernelmodus.
__TEXT
: Bevat uitvoerbare kode met lees en uitvoer regte (nie skryfbare). Gewone afdelings van hierdie segment:
__text
: Opgestelde binêre kode
__const
: Konstante data (slegs leesbaar)
__[c/u/os_log]string
: C, Unicode of os-logstring konstantes
__stubs
en __stubs_helper
: Betrokke tydens die dinamiese biblioteeklaaiproses
__unwind_info
: Stok ontwar data.
Let daarop dat al hierdie inhoud onderteken is maar ook as uitvoerbaar gemerk is (skep meer opsies vir uitbuiting van afdelings wat nie noodwendig hierdie voorreg nodig het nie, soos string-toegewyde afdelings).
__DATA
: Bevat data wat leesbaar en skryfbaar is (nie uitvoerbaar).
__got:
Globale Verskuiwingstabel
__nl_symbol_ptr
: Nie lui (bind by laai) simboolaanduider
__la_symbol_ptr
: Lui (bind by gebruik) simboolaanduider
__const
: Behoort lees-slegs data te wees (nie regtig)
__cfstring
: CoreFoundation strings
__data
: Globale veranderlikes (wat geïnisialiseer is)
__bss
: Statiese veranderlikes (wat nie geïnisialiseer is nie)
__objc_*
(__objc_classlist, __objc_protolist, ens.): Inligting wat deur die Objective-C-uitvoertyd gebruik word
__DATA_CONST
: __DATA.__const is nie gewaarborg om konstant te wees (skryfregte nie), en ook nie ander aanwysers en die GOT nie. Hierdie afdeling maak __const
, sommige inisialiseerders en die GOT-tabel (eenmaal opgelos) leesbaar slegs deur mprotect
te gebruik.
__LINKEDIT
: Bevat inligting vir die koppelaar (dyld) soos simbool-, string- en herlokasie-tabelinskrywings. Dit is 'n generiese houer vir inhoud wat nie in __TEXT
of __DATA
is nie en sy inhoud word in ander laaibefehle beskryf.
dyld-inligting: Herbasis, Nie-luie/lui/swak bindopkode en uitvoer inligting
Funksies begin: Tabel van beginadresse van funksies
Data In Kode: Data-eilande in __text
Simbooltabel: Simbole in binêr
Indirekte Simbooltabel: Aanduider/stub simbole
Stringtabel
Kodehandtekening
__OBJC
: Bevat inligting wat deur die Objective-C-uitvoertyd gebruik word. Alhoewel hierdie inligting ook in die __DATA-segment gevind kan word, binne verskeie in __objc_* afdelings.
__RESTRICT
: 'n Segment sonder inhoud met 'n enkele afdeling genaamd __restrict
(ook leeg) wat verseker dat wanneer die binêre lopende is, dit DYLD-omgewingsveranderlikes ignoreer.
Soos in die kode gesien kon word, ondersteun segmente ook vlae (al word hulle nie baie gebruik nie):
SG_HIGHVM
: Slegs kern (nie gebruik nie)
SG_FVMLIB
: Nie gebruik nie
SG_NORELOC
: Segment het geen herlokasie
SG_PROTECTED_VERSION_1
: Versleuteling. Gebruik byvoorbeeld deur Finder om teks in __TEXT
-segment te versleutel.
LC_UNIXTHREAD/LC_MAIN
LC_MAIN
bevat die ingangspunt in die entryoff-eienskap. Met laai-tyd voeg dyld eenvoudig hierdie waarde by die (in-geheue) basis van die binêre, spring dan na hierdie instruksie om die uitvoering van die binêre se kode te begin.
LC_UNIXTHREAD
bevat die waardes wat die register moet hê wanneer die hoofdraad begin. Dit is reeds verouderd maar dyld
gebruik dit nog steeds. Dit is moontlik om die waardes van die register wat deur hierdie ingestel is, te sien met:
LC_CODE_SIGNATURE
Bevat inligting oor die kodesignatuur van die Macho-O-lêer. Dit bevat slegs 'n offset wat na die handtekeningblob wys. Dit is tipies aan die einde van die lêer. Jy kan egter inligting oor hierdie afdeling vind in hierdie blogpos en hierdie gists.
LC_ENCRYPTION_INFO[_64]
Ondersteuning vir binêre versleuteling. Indien 'n aanvaller egter die proses kan kompromiteer, sal hy die geheue onversleuteld kan aflaai.
LC_LOAD_DYLINKER
Bevat die pad na die dinamiese skakeluitvoerbare lêer wat gedeelde biblioteke in die proses-adresruimte in kaart bring. Die waarde is altyd ingestel op /usr/lib/dyld
. Dit is belangrik om daarop te let dat in macOS, dylib-afbeelding in gebruikermodus plaasvind, nie in kernelmodus nie.
LC_IDENT
Verouderd, maar wanneer dit ingestel is om damps by paniek te genereer, word 'n Mach-O-kern-damp geskep en die kernweergawe word in die LC_IDENT
-bevel ingestel.
LC_UUID
Willekeurige UUID. Dit is nie direk nuttig vir enigiets nie, maar XNU stoor dit saam met die res van die prosesinligting. Dit kan in botsingsverslae gebruik word.
LC_DYLD_ENVIRONMENT
Laat toe om omgewingsveranderlikes aan die dyld aan te dui voordat die proses uitgevoer word. Dit kan baie gevaarlik wees omdat dit kan toelaat om arbitrêre kode binne die proses uit te voer, dus word hierdie laai-bevel slegs gebruik in dyld-geboue met #define SUPPORT_LC_DYLD_ENVIRONMENT
en beperk verdere verwerking slegs tot veranderlikes van die vorm DYLD_..._PATH
wat laaipaaie spesifiseer.
LC_LOAD_DYLIB
Hierdie laaibevolking beskryf 'n dinamiese biblioteekafhanklikheid wat die laaier (dyld) instrueer om genoemde biblioteek te laai en te skakel. Daar is 'n LC_LOAD_DYLIB
-laaibevolking vir elke biblioteek wat die Mach-O-binêre lêer benodig.
Hierdie laaibevolking is 'n struktuur van die tipe dylib_command
(wat 'n struktuur dylib bevat wat die werklike afhanklike dinamiese biblioteek beskryf):
Jy kan ook hierdie inligting kry van die opdraggelynpunt met:
Some potensiële kwaadwillige biblioteke is:
DiskArbitration: Monitering van USB-aandrywings
AVFoundation: Vang klank en video
CoreWLAN: Wifi-skanderings.
'n Mach-O binêre lêer kan een of meer konstrukteurs bevat, wat uitgevoer sal word voor die adres gespesifiseer in LC_MAIN. Die offsette van enige konstrukteurs word gehou in die __mod_init_func afdeling van die __DATA_CONST segment.
In die kern van die lêer lê die data-gebied, wat bestaan uit verskeie segmente soos gedefinieer in die laai-opdragte-gebied. 'n Verskeidenheid data-afdelings kan binne elke segment gehuisves word, met elke afdeling wat kode of data bevat wat spesifiek is vir 'n tipe.
Die data is basies die gedeelte wat al die inligting bevat wat deur die laai-opdragte LC_SEGMENTS_64 gelaai word.
Dit sluit in:
Funksie-tabel: Wat inligting oor die programfunksies bevat.
Simbooltabel: Wat inligting oor die eksterne funksie bevat wat deur die binêre gebruik word
Dit kan ook interne funksie, veranderlike name en meer bevat.
Om dit te kontroleer, kan jy die Mach-O View gereedskap gebruik:
Of vanaf die opdraglyn:
In die __TEXT
segment (r-x):
__objc_classname
: Klasname (strings)
__objc_methname
: Metode name (strings)
__objc_methtype
: Metode tipes (strings)
In die __DATA
segment (rw-):
__objc_classlist
: Aanwysers na alle Objective-C klasse
__objc_nlclslist
: Aanwysers na Nie-Luie Objective-C klasse
__objc_catlist
: Aanwyser na Kategorieë
__objc_nlcatlist
: Aanwyser na Nie-Luie Kategorieë
__objc_protolist
: Protokolle lys
__objc_const
: Konstante data
__objc_imageinfo
, __objc_selrefs
, objc__protorefs
...
_swift_typeref
, _swift3_capture
, _swift3_assocty
, _swift3_types, _swift3_proto
, _swift3_fieldmd
, _swift3_builtin
, _swift3_reflstr