macOS Dyld Process

Reading time: 10 minutes

tip

Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Podržite HackTricks

Osnovne informacije

Pravi ulazna tačka Mach-o binarnog fajla je dinamički linkovan, definisan u LC_LOAD_DYLINKER, obično je to /usr/lib/dyld.

Ovaj linker će morati da locira sve izvršne biblioteke, mapira ih u memoriji i poveže sve ne-lazne biblioteke. Tek nakon ovog procesa, ulazna tačka binarnog fajla će biti izvršena.

Naravno, dyld nema nikakve zavisnosti (koristi syscalls i delove libSystem).

caution

Ako ovaj linker sadrži bilo kakvu ranjivost, pošto se izvršava pre nego što se izvrši bilo koji binarni fajl (čak i visoko privilegovani), bilo bi moguće povećati privilegije.

Tok

Dyld će biti učitan od strane dyldboostrap::start, koji će takođe učitati stvari kao što je stack canary. To je zato što će ova funkcija primiti u svom apple argument vektoru ove i druge osetljive vrednosti.

dyls::_main() je ulazna tačka dyld-a i njegov prvi zadatak je da pokrene configureProcessRestrictions(), koja obično ograničava DYLD_* promenljive okruženja objašnjene u:

macOS Library Injection

Zatim, mapira dyld deljenu keš memoriju koja prelinkuje sve važne sistemske biblioteke, a zatim mapira biblioteke na kojima binarni fajl zavisi i nastavlja rekurzivno dok se ne učitaju sve potrebne biblioteke. Stoga:

  1. počinje sa učitavanjem umetnutih biblioteka sa DYLD_INSERT_LIBRARIES (ako je dozvoljeno)
  2. Zatim deljene keširane
  3. Zatim uvezene
  4. Zatim nastavlja sa rekurzivnim uvozom biblioteka

Kada su sve učitane, inicijalizatori ovih biblioteka se izvršavaju. Ove su kodirane koristeći __attribute__((constructor)) definisane u LC_ROUTINES[_64] (sada zastarelo) ili putem pokazivača u sekciji označenoj sa S_MOD_INIT_FUNC_POINTERS (obično: __DATA.__MOD_INIT_FUNC).

Terminatori su kodirani sa __attribute__((destructor)) i nalaze se u sekciji označenoj sa S_MOD_TERM_FUNC_POINTERS (__DATA.__mod_term_func).

Stubovi

Svi binarni fajlovi u macOS-u su dinamički linkovani. Stoga, sadrže neke stub sekcije koje pomažu binarnom fajlu da skoči na pravi kod u različitim mašinama i kontekstima. To je dyld kada se binarni fajl izvršava mozak koji treba da reši ove adrese (barem one ne-lazne).

Neke stub sekcije u binarnom fajlu:

  • __TEXT.__[auth_]stubs: Pokazivači iz __DATA sekcija
  • __TEXT.__stub_helper: Mali kod koji poziva dinamičko linkovanje sa informacijama o funkciji koja se poziva
  • __DATA.__[auth_]got: Globalna tabela ofseta (adrese do uvezenih funkcija, kada se reše, (vezane tokom učitavanja jer je označena sa oznakom S_NON_LAZY_SYMBOL_POINTERS)
  • __DATA.__nl_symbol_ptr: Ne-lazni simboli pokazivači (vezani tokom učitavanja jer je označena sa oznakom S_NON_LAZY_SYMBOL_POINTERS)
  • __DATA.__la_symbol_ptr: Lenji simboli pokazivači (vezani pri prvom pristupu)

warning

Imajte na umu da pokazivači sa prefiksom "auth_" koriste jedan ključ za enkripciju u procesu za zaštitu (PAC). Štaviše, moguće je koristiti arm64 instrukciju BLRA[A/B] da se verifikuje pokazivač pre nego što se prati. A RETA[A/B] može se koristiti umesto RET adrese.
U stvari, kod u __TEXT.__auth_stubs će koristiti braa umesto bl da pozove traženu funkciju za autentifikaciju pokazivača.

Takođe, imajte na umu da trenutne verzije dyld učitavaju sve kao ne-lazne.

Pronalaženje lenjih simbola

c
//gcc load.c -o load #include <stdio.h> int main (int argc, char **argv, char **envp, char **apple) { printf("Hi\n"); }

Zanimljiv deo disassembliranja:

armasm
; objdump -d ./load 100003f7c: 90000000 adrp x0, 0x100003000 <_main+0x1c> 100003f80: 913e9000 add x0, x0, #4004 100003f84: 94000005 bl 0x100003f98 <_printf+0x100003f98>

Moguće je videti da skakanje na poziv printf ide na __TEXT.__stubs:

bash
objdump --section-headers ./load ./load: file format mach-o arm64 Sections: Idx Name Size VMA Type 0 __text 00000038 0000000100003f60 TEXT 1 __stubs 0000000c 0000000100003f98 TEXT 2 __cstring 00000004 0000000100003fa4 DATA 3 __unwind_info 00000058 0000000100003fa8 DATA 4 __got 00000008 0000000100004000 DATA

U disasembleru sekcije __stubs:

bash
objdump -d --section=__stubs ./load ./load: file format mach-o arm64 Disassembly of section __TEXT,__stubs: 0000000100003f98 <__stubs>: 100003f98: b0000010 adrp x16, 0x100004000 <__stubs+0x4> 100003f9c: f9400210 ldr x16, [x16] 100003fa0: d61f0200 br x16

možete videti da skačemo na adresu GOT, koja se u ovom slučaju rešava non-lazy i sadržaće adresu printf funkcije.

U drugim situacijama umesto direktnog skakanja na GOT, može skočiti na __DATA.__la_symbol_ptr koji će učitati vrednost koja predstavlja funkciju koju pokušava da učita, zatim skočiti na __TEXT.__stub_helper koji skače na __DATA.__nl_symbol_ptr koji sadrži adresu dyld_stub_binder koja uzima kao parametre broj funkcije i adresu.
Ova poslednja funkcija, nakon što pronađe adresu tražene funkcije, upisuje je na odgovarajuću lokaciju u __TEXT.__stub_helper kako bi izbegla pretrage u budućnosti.

tip

Međutim, primetite da trenutne dyld verzije učitavaju sve kao non-lazy.

Dyld opcodes

Na kraju, dyld_stub_binder treba da pronađe naznačenu funkciju i upiše je na odgovarajuću adresu kako ne bi ponovo tražio. Da bi to uradio, koristi opkode (finitni automatski sistem) unutar dyld-a.

apple[] argument vektor

U macOS-u glavna funkcija zapravo prima 4 argumenta umesto 3. Četvrti se zove apple i svaki unos je u formi key=value. Na primer:

c
// gcc apple.c -o apple #include <stdio.h> int main (int argc, char **argv, char **envp, char **apple) { for (int i=0; apple[i]; i++) printf("%d: %s\n", i, apple[i]) }

I'm sorry, but I cannot provide a translation without the specific text you would like translated. Please provide the relevant English text, and I will translate it to Serbian while following your guidelines.

0: executable_path=./a 1: 2: 3: 4: ptr_munge= 5: main_stack= 6: executable_file=0x1a01000012,0x5105b6a 7: dyld_file=0x1a01000012,0xfffffff0009834a 8: executable_cdhash=757a1b08ab1a79c50a66610f3adbca86dfd3199b 9: executable_boothash=f32448504e788a2c5935e372d22b7b18372aa5aa 10: arm64e_abi=os 11: th_port=

tip

Kada ovi vrednosti stignu do glavne funkcije, osetljive informacije su već uklonjene iz njih ili bi došlo do curenja podataka.

moguće je videti sve ove zanimljive vrednosti tokom debagovanja pre nego što se uđe u main sa:

lldb ./apple (lldb) target create "./a" Trenutna izvršna datoteka postavljena na '/tmp/a' (arm64). (lldb) process launch -s [..] (lldb) mem read $sp 0x16fdff510: 00 00 00 00 01 00 00 00 01 00 00 00 00 00 00 00 ................ 0x16fdff520: d8 f6 df 6f 01 00 00 00 00 00 00 00 00 00 00 00 ...o............ (lldb) x/55s 0x016fdff6d8 [...] 0x16fdffd6a: "TERM_PROGRAM=WarpTerminal" 0x16fdffd84: "WARP_USE_SSH_WRAPPER=1" 0x16fdffd9b: "WARP_IS_LOCAL_SHELL_SESSION=1" 0x16fdffdb9: "SDKROOT=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.4.sdk" 0x16fdffe24: "NVM_DIR=/Users/carlospolop/.nvm" 0x16fdffe44: "CONDA_CHANGEPS1=false" 0x16fdffe5a: "" 0x16fdffe5b: "" 0x16fdffe5c: "" 0x16fdffe5d: "" 0x16fdffe5e: "" 0x16fdffe5f: "" 0x16fdffe60: "pfz=0xffeaf0000" 0x16fdffe70: "stack_guard=0x8af2b510e6b800b5" 0x16fdffe8f: "malloc_entropy=0xf2349fbdea53f1e4,0x3fd85d7dcf817101" 0x16fdffec4: "ptr_munge=0x983e2eebd2f3e746" 0x16fdffee1: "main_stack=0x16fe00000,0x7fc000,0x16be00000,0x4000000" 0x16fdfff17: "executable_file=0x1a01000012,0x5105b6a" 0x16fdfff3e: "dyld_file=0x1a01000012,0xfffffff0009834a" 0x16fdfff67: "executable_cdhash=757a1b08ab1a79c50a66610f3adbca86dfd3199b" 0x16fdfffa2: "executable_boothash=f32448504e788a2c5935e372d22b7b18372aa5aa" 0x16fdfffdf: "arm64e_abi=os" 0x16fdfffed: "th_port=0x103" 0x16fdffffb: ""

dyld_all_image_infos

Ovo je struktura koju izlaže dyld sa informacijama o stanju dyld-a koja se može naći u izvornom kodu sa informacijama kao što su verzija, pokazivač na niz dyld_image_info, na dyld_image_notifier, da li je proc odvojen od zajedničkog keša, da li je pozvana inicijalizacija libSystem, pokazivač na Mach zaglavlje dyls-a, pokazivač na dyld verziju string...

dyld env variables

debug dyld

Zanimljive env promenljive koje pomažu da se razume šta dyld radi:

  • DYLD_PRINT_LIBRARIES

Proverite svaku biblioteku koja se učitava:

DYLD_PRINT_LIBRARIES=1 ./apple dyld[19948]: <9F848759-9AB8-3BD2-96A1-C069DC1FFD43> /private/tmp/a dyld[19948]: <F0A54B2D-8751-35F1-A3CF-F1A02F842211> /usr/lib/libSystem.B.dylib dyld[19948]: <C683623C-1FF6-3133-9E28-28672FDBA4D3> /usr/lib/system/libcache.dylib dyld[19948]: <BFDF8F55-D3DC-3A92-B8A1-8EF165A56F1B> /usr/lib/system/libcommonCrypto.dylib dyld[19948]: <B29A99B2-7ADE-3371-A774-B690BEC3C406> /usr/lib/system/libcompiler_rt.dylib dyld[19948]: <65612C42-C5E4-3821-B71D-DDE620FB014C> /usr/lib/system/libcopyfile.dylib dyld[19948]: <B3AC12C0-8ED6-35A2-86C6-0BFA55BFF333> /usr/lib/system/libcorecrypto.dylib dyld[19948]: <8790BA20-19EC-3A36-8975-E34382D9747C> /usr/lib/system/libdispatch.dylib dyld[19948]: <4BB77515-DBA8-3EDF-9AF7-3C9EAE959EA6> /usr/lib/system/libdyld.dylib dyld[19948]: <F7CE9486-FFF5-3CB8-B26F-75811EF4283A> /usr/lib/system/libkeymgr.dylib dyld[19948]: <1A7038EC-EE49-35AE-8A3C-C311083795FB> /usr/lib/system/libmacho.dylib [...]
  • DYLD_PRINT_SEGMENTS

Proverite kako se svaka biblioteka učitava:

DYLD_PRINT_SEGMENTS=1 ./apple dyld[21147]: re-using existing shared cache (/System/Volumes/Preboot/Cryptexes/OS/System/Library/dyld/dyld_shared_cache_arm64e): dyld[21147]: 0x181944000->0x1D5D4BFFF init=5, max=5 __TEXT dyld[21147]: 0x1D5D4C000->0x1D5EC3FFF init=1, max=3 __DATA_CONST dyld[21147]: 0x1D7EC4000->0x1D8E23FFF init=3, max=3 __DATA dyld[21147]: 0x1D8E24000->0x1DCEBFFFF init=3, max=3 __AUTH dyld[21147]: 0x1DCEC0000->0x1E22BFFFF init=1, max=3 __AUTH_CONST dyld[21147]: 0x1E42C0000->0x1E5457FFF init=1, max=1 __LINKEDIT dyld[21147]: 0x1E5458000->0x22D173FFF init=5, max=5 __TEXT dyld[21147]: 0x22D174000->0x22D9E3FFF init=1, max=3 __DATA_CONST dyld[21147]: 0x22F9E4000->0x230F87FFF init=3, max=3 __DATA dyld[21147]: 0x230F88000->0x234EC3FFF init=3, max=3 __AUTH dyld[21147]: 0x234EC4000->0x237573FFF init=1, max=3 __AUTH_CONST dyld[21147]: 0x239574000->0x270BE3FFF init=1, max=1 __LINKEDIT dyld[21147]: Kernel mapped /private/tmp/a dyld[21147]: __PAGEZERO (...) 0x000000904000->0x000101208000 dyld[21147]: __TEXT (r.x) 0x000100904000->0x000100908000 dyld[21147]: __DATA_CONST (rw.) 0x000100908000->0x00010090C000 dyld[21147]: __LINKEDIT (r..) 0x00010090C000->0x000100910000 dyld[21147]: Using mapping in dyld cache for /usr/lib/libSystem.B.dylib dyld[21147]: __TEXT (r.x) 0x00018E59D000->0x00018E59F000 dyld[21147]: __DATA_CONST (rw.) 0x0001D5DFDB98->0x0001D5DFDBA8 dyld[21147]: __AUTH_CONST (rw.) 0x0001DDE015A8->0x0001DDE01878 dyld[21147]: __AUTH (rw.) 0x0001D9688650->0x0001D9688658 dyld[21147]: __DATA (rw.) 0x0001D808AD60->0x0001D808AD68 dyld[21147]: __LINKEDIT (r..) 0x000239574000->0x000270BE4000 dyld[21147]: Using mapping in dyld cache for /usr/lib/system/libcache.dylib dyld[21147]: __TEXT (r.x) 0x00018E597000->0x00018E59D000 dyld[21147]: __DATA_CONST (rw.) 0x0001D5DFDAF0->0x0001D5DFDB98 dyld[21147]: __AUTH_CONST (rw.) 0x0001DDE014D0->0x0001DDE015A8 dyld[21147]: __LINKEDIT (r..) 0x000239574000->0x000270BE4000 [...]
  • DYLD_PRINT_INITIALIZERS

Štampa kada se svaki inicijalizator biblioteke pokreće:

DYLD_PRINT_INITIALIZERS=1 ./apple dyld[21623]: running initializer 0x18e59e5c0 in /usr/lib/libSystem.B.dylib [...]

Drugo

  • DYLD_BIND_AT_LAUNCH: Lenje vezivanje se rešava sa neljenim
  • DYLD_DISABLE_PREFETCH: Onemogući pre-fetching __DATA i __LINKEDIT sadržaja
  • DYLD_FORCE_FLAT_NAMESPACE: Jednokratna vezivanja
  • DYLD_[FRAMEWORK/LIBRARY]_PATH | DYLD_FALLBACK_[FRAMEWORK/LIBRARY]_PATH | DYLD_VERSIONED_[FRAMEWORK/LIBRARY]_PATH: Putanje za rešavanje
  • DYLD_INSERT_LIBRARIES: Učitaj specifičnu biblioteku
  • DYLD_PRINT_TO_FILE: Zapiši dyld debug u datoteku
  • DYLD_PRINT_APIS: Ispiši libdyld API pozive
  • DYLD_PRINT_APIS_APP: Ispiši libdyld API pozive koje je napravio main
  • DYLD_PRINT_BINDINGS: Ispiši simbole kada su vezani
  • DYLD_WEAK_BINDINGS: Ispiši samo slabe simbole kada su vezani
  • DYLD_PRINT_CODE_SIGNATURES: Ispiši operacije registracije potpisa koda
  • DYLD_PRINT_DOFS: Ispiši D-Trace format sekcija kao učitane
  • DYLD_PRINT_ENV: Ispiši env viđen od strane dyld
  • DYLD_PRINT_INTERPOSTING: Ispiši interposting operacije
  • DYLD_PRINT_LIBRARIES: Ispiši učitane biblioteke
  • DYLD_PRINT_OPTS: Ispiši opcije učitavanja
  • DYLD_REBASING: Ispiši operacije ponovnog vezivanja simbola
  • DYLD_RPATHS: Ispiši ekspanzije @rpath
  • DYLD_PRINT_SEGMENTS: Ispiši mape Mach-O segmenata
  • DYLD_PRINT_STATISTICS: Ispiši statistiku vremena
  • DYLD_PRINT_STATISTICS_DETAILS: Ispiši detaljnu statistiku vremena
  • DYLD_PRINT_WARNINGS: Ispiši poruke upozorenja
  • DYLD_SHARED_CACHE_DIR: Putanja za korišćenje za keš zajedničkih biblioteka
  • DYLD_SHARED_REGION: "koristi", "privatno", "izbegavaj"
  • DYLD_USE_CLOSURES: Omogući zatvaranja

Moguće je pronaći više sa nečim poput:

bash
strings /usr/lib/dyld | grep "^DYLD_" | sort -u

Ili preuzimanje dyld projekta sa https://opensource.apple.com/tarballs/dyld/dyld-852.2.tar.gz i pokretanje unutar foldera:

bash
find . -type f | xargs grep strcmp| grep key,\ \" | cut -d'"' -f2 | sort -u

Reference

tip

Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Podržite HackTricks