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 binêre word gewoonlik gecompileer as universele binêre. 'n Universele binêre kan meerdere argitekture in dieselfde lêer ondersteun.
Hierdie binêre volg die Mach-O struktuur wat basies bestaan uit:
Kop
Laai Opdragte
Data
Soek vir die lêer met: mdfind fat.h | grep -i mach-o | grep -E "fat.h$"
Die kop het die magiese bytes 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 hulpmiddel te gebruik:
Soos jy dalk dink, verdubbel 'n universele binêre wat vir 2 argitekture gecompileer is gewoonlik die grootte van een wat net vir 1 argitektuur gecompileer is.
Die kop bevat basiese inligting oor die lêer, soos magiese bytes om dit as 'n Mach-O lêer te identifiseer en inligting oor die teiken argitektuur. 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
: Herlokasiebare objeklêer (tussenprodukte van kompilasie, nog nie uitvoerbaar nie).
MH_EXECUTE
: Uitvoerbare lêers.
MH_FVMLIB
: Vaste VM-biblioteeklêer.
MH_CORE
: Kode-dumps
MH_PRELOAD
: Vooraf gelaaide uitvoerbare lêer (nie meer ondersteun in XNU nie)
MH_DYLIB
: Dinamiese biblioteke
MH_DYLINKER
: Dinamiese skakelaar
MH_BUNDLE
: "Plugin-lêers". Gegenereer met -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.
Or using Mach-O View:
Die bronkode definieer ook verskeie vlaggies wat nuttig is vir die laai van biblioteke:
MH_NOUNDEFS
: Geen ongedefinieerde verwysings nie (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 het nie LC_REEXPORT opdragte nie
MH_PIE
: Posisie Onafhanklike Uitvoerbare
MH_HAS_TLV_DESCRIPTORS
: Daar is 'n afdeling met draad plaaslike veranderlikes
MH_NO_HEAP_EXECUTION
: Geen uitvoering vir heap/data bladsye nie
MH_HAS_OBJC
: Binêre het oBject-C afdelings
MH_SIM_SUPPORT
: Simulator ondersteuning
MH_DYLIB_IN_CACHE
: Gebruik op dylibs/raamwerke in gedeelde biblioteek kas.
Die lêer se uitleg in geheue word hier gespesifiseer, wat die simbol tabel se ligging, die konteks van die hoofdraad by uitvoering begin, en die vereiste gedeelde biblioteke detail. Instruksies word aan die dinamiese laaier (dyld) gegee oor die binêre se laai proses in geheue.
Die gebruik die load_command struktuur, gedefinieer in die genoemde loader.h
:
There are about 50 different types of load commands that the system handles differently. The most common ones are: LC_SEGMENT_64
, LC_LOAD_DYLINKER
, LC_MAIN
, LC_LOAD_DYLIB
, and LC_CODE_SIGNATURE
.
Basies definieer hierdie tipe Laaiopdrag hoe om die __TEXT (uitvoerbare kode) en __DATA (data vir die proses) segmente te laai volgens die offsets wat in die Data-seksie aangedui word wanneer die binêre uitgevoer word.
Hierdie opdragte definieer segmente wat in die virtuele geheue ruimte van 'n proses gemap 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 dataseksie van die Mach-O-lêer.
Elke segment kan verder verdeeld word in meerdere seksies. Die laaiopdragstruktuur bevat inligting oor hierdie seksies binne die onderskeie segment.
In die kop vind jy eers die segmentkop:
Voorbeeld van segmentkop:
Hierdie kop definieer die aantal seksies waarvan die koppe na dit verskyn:
Example of section header:
As jy die seksie offset (0x37DC) + die offset waar die arch begin, in hierdie geval 0x18000
--> 0x37DC + 0x18000 = 0x1B7DC
Dit is ook moontlik om koptekst inligting van die opdraglyn te verkry met:
Common segments loaded by this cmd:
__PAGEZERO
: Dit instrueer die kernel om die adres nul te map, sodat dit nie gelees, geskryf of uitgevoer kan word nie. Die maxprot en minprot veranderlikes in die struktuur is op nul gestel om aan te dui dat daar geen lees-skrif-uitvoer regte op hierdie bladsy is.
Hierdie toewysing is belangrik om NULL pointer dereference kwesbaarhede te verminder. Dit is omdat XNU 'n harde bladsy nul afdwing wat verseker dat die eerste bladsy (slegs die eerste) van geheue ontoeganklik is (behalwe in i386). 'n Binêre kan aan hierdie vereistes voldoen deur 'n klein __PAGEZERO te skep (met die -pagezero_size
) om die eerste 4k te dek en die res van 32bit geheue in beide gebruiker- en kernelmodus toeganklik te hê.
__TEXT
: Bevat uitvoerbare kode met lees en uitvoer toestemmings (geen skryfbare). Algemene afdelings van hierdie segment:
__text
: Gecompileerde binêre kode
__const
: Konstant data (slegs lees)
__[c/u/os_log]string
: C, Unicode of os logs string konstantes
__stubs
en __stubs_helper
: Betrokke tydens die dinamiese biblioteek laai proses
__unwind_info
: Stapel ontrafel data.
Let daarop dat al hierdie inhoud onderteken is, maar ook as uitvoerbaar gemerk is (wat meer opsies vir die uitbuiting van afdelings skep wat nie noodwendig hierdie voorreg benodig nie, soos string toegewyde afdelings).
__DATA
: Bevat data wat leesbaar en skryfbaar is (geen uitvoerbare).
__got:
Globale Offset Tabel
__nl_symbol_ptr
: Nie lui (bind by laai) simbool pointer
__la_symbol_ptr
: Lui (bind by gebruik) simbool pointer
__const
: Moet slegs leesbare data wees (nie regtig nie)
__cfstring
: CoreFoundation strings
__data
: Globale veranderlikes (wat geinitialiseer is)
__bss
: Statiese veranderlikes (wat nie geinitialiseer is nie)
__objc_*
(__objc_classlist, __objc_protolist, ens): Inligting wat deur die Objective-C runtime gebruik word
__DATA_CONST
: __DATA.__const is nie gewaarborg om konstant te wees nie (skryf toestemmings), en ander pointers en die GOT ook nie. Hierdie afdeling maak __const
, sommige inisialisators en die GOT tabel (sodra dit opgelos is) slegs lees met behulp van mprotect
.
__LINKEDIT
: Bevat inligting vir die linker (dyld) soos simbool, string, en herlokasie tabel inskrywings. Dit is 'n generiese houer vir inhoud wat nie in __TEXT
of __DATA
is nie en sy inhoud word in ander laaiopdragte beskryf.
dyld inligting: Herbasis, Nie-lui/lui/swak binding opcodes en uitvoer inligting
Funksies begin: Tabel van begin adresse van funksies
Data In Kode: Data-eilande in __text
Simbool Tabel: Simbole in binêre
Indirekte Simbool Tabel: Pointer/stub simbole
String Tabel
Kode Handtekening
__OBJC
: Bevat inligting wat deur die Objective-C runtime 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 uitgevoer word, dit DYLD omgewingsveranderlikes sal ignoreer.
Soos dit moontlik was om in die kode te sien, ondersteun segmente ook vlae (alhoewel hulle nie baie gebruik word nie):
SG_HIGHVM
: Slegs kern (nie gebruik nie)
SG_FVMLIB
: Nie gebruik nie
SG_NORELOC
: Segment het geen herlokasie nie
SG_PROTECTED_VERSION_1
: Enkripsie. Gebruik byvoorbeeld deur Finder om teks in die __TEXT
segment te enkripteer.
LC_UNIXTHREAD/LC_MAIN
LC_MAIN
bevat die toegangspunt in die entryoff attribuut. By laai tyd, dyld voeg eenvoudig hierdie waarde by die (in-geheue) basis van die binêre, dan spring dit 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 was reeds verouderd, maar dyld
gebruik dit steeds. Dit is moontlik om die waardes van die registers wat deur hierdie gestel is, te sien met:
LC_CODE_SIGNATURE
Bevat inligting oor die kodehandtekening van die Macho-O lêer. Dit bevat slegs 'n offset wat na die handtekening blob wys. Dit is tipies aan die einde van die lêer. U kan egter 'n paar inligting oor hierdie afdeling vind in hierdie blogpos en hierdie gists.
LC_ENCRYPTION_INFO[_64]
Ondersteuning vir binêre versleuteling. Dit is egter, natuurlik, as 'n aanvaller daarin slaag om die proses te kompromitteer, sal hy in staat wees om die geheue onversleuteld te dump.
LC_LOAD_DYLINKER
Bevat die pad na die dinamiese skakelaar uitvoerbare lêer wat gedeelde biblioteke in die prosesadresruimte in kaart bring. Die waarde is altyd ingestel op /usr/lib/dyld
. Dit is belangrik om te noem dat in macOS, dylib-mapping in gebruikermodus plaasvind, nie in kernmodus nie.
LC_IDENT
Verouderd, maar wanneer dit gekonfigureer is om dumps op paniek te genereer, word 'n Mach-O kern dump geskep en die kern weergawe word in die LC_IDENT
opdrag ingestel.
LC_UUID
Ewekansige UUID. Dit is nuttig vir enigiets direk, maar XNU kas dit saam met die res van die prosesinligting. Dit kan in ongelukverslae gebruik word.
LC_DYLD_ENVIRONMENT
Stel in staat om omgewingsveranderlikes aan die dyld aan te dui voordat die proses uitgevoer word. Dit kan baie gevaarlik wees aangesien dit die uitvoering van arbitrêre kode binne die proses kan toelaat, so hierdie laaiopdrag word slegs in dyld-bou met #define SUPPORT_LC_DYLD_ENVIRONMENT
gebruik en beperk die verwerking verder slegs tot veranderlikes van die vorm DYLD_..._PATH
wat laai paden spesifiseer.
LC_LOAD_DYLIB
Hierdie laaiopdrag beskryf 'n dinamiese biblioteek afhanklikheid wat die laaier (dyld) instrueer om die gesê biblioteek te laai en te skakel. Daar is 'n LC_LOAD_DYLIB
laaiopdrag vir elke biblioteek wat die Mach-O binêre benodig.
Hierdie laaiopdrag is 'n struktuur van tipe dylib_command
(wat 'n struktuur dylib bevat, wat die werklike afhanklike dinamiese biblioteek beskryf):
Jy kan ook hierdie inligting van die cli kry met:
Some potential malware related libraries are:
DiskArbitration: Monitering USB skyfies
AVFoundation: Neem audio en video op
CoreWLAN: Wifi skande.
'n Mach-O binêre kan een of meer konstruktors bevat, wat uitgevoer sal word voor die adres wat in LC_MAIN gespesifiseer is. Die verskuiwings van enige konstruktors word in die __mod_init_func afdeling van die __DATA_CONST segment gehou.
In die kern van die lêer lê die datastreek, wat uit verskeie segmente bestaan soos gedefinieer in die laai-opdragte streek. 'n Verskeidenheid dataseksies kan binne elke segment gehuisves word, met elke afdeling wat kode of data spesifiek vir 'n tipe hou.
Die data is basies die deel wat al die inligting bevat wat deur die laai-opdragte LC_SEGMENTS_64 gelaai word.
This includes:
Funksietabel: Wat inligting oor die programfunksies hou.
Simboltabel: Wat inligting bevat oor die eksterne funksie wat deur die binêre gebruik word
Dit kan ook interne funksies, veranderlike name sowel as meer bevat.
To check it you could use the Mach-O View tool:
Or from the cli:
In __TEXT
segment (r-x):
__objc_classname
: Klasname (stringe)
__objc_methname
: Metode name (stringe)
__objc_methtype
: Metode tipes (stringe)
In __DATA
segment (rw-):
__objc_classlist
: Pointers na alle Objetive-C klasse
__objc_nlclslist
: Pointers na Non-Lazy Objective-C klasse
__objc_catlist
: Pointer na Kategories
__objc_nlcatlist
: Pointer na Non-Lazy Kategories
__objc_protolist
: Protokollys
__objc_const
: Konstant data
__objc_imageinfo
, __objc_selrefs
, objc__protorefs
...
_swift_typeref
, _swift3_capture
, _swift3_assocty
, _swift3_types, _swift3_proto
, _swift3_fieldmd
, _swift3_builtin
, _swift3_reflstr
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)