macOS Dyld Process

tip

Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks

Informaci贸n B谩sica

El verdadero punto de entrada de un binario Mach-o es el enlazador din谩mico, definido en LC_LOAD_DYLINKER, que generalmente es /usr/lib/dyld.

Este enlazador necesitar谩 localizar todas las bibliotecas ejecutables, mape谩ndolas en memoria y enlazando todas las bibliotecas no perezosas. Solo despu茅s de este proceso, se ejecutar谩 el punto de entrada del binario.

Por supuesto, dyld no tiene dependencias (utiliza syscalls y extractos de libSystem).

caution

Si este enlazador contiene alguna vulnerabilidad, como se est谩 ejecutando antes de ejecutar cualquier binario (incluso los altamente privilegiados), ser铆a posible escalar privilegios.

Flujo

Dyld ser谩 cargado por dyldboostrap::start, que tambi茅n cargar谩 cosas como el canario de pila. Esto se debe a que esta funci贸n recibir谩 en su vector de argumentos apple este y otros valores sensibles.

dyls::_main() es el punto de entrada de dyld y su primera tarea es ejecutar configureProcessRestrictions(), que generalmente restringe las variables de entorno DYLD_* explicadas en:

macOS Library Injection

Luego, mapea la cach茅 compartida de dyld que preenlaza todas las bibliotecas del sistema importantes y luego mapea las bibliotecas de las que depende el binario y contin煤a recursivamente hasta que se carguen todas las bibliotecas necesarias. Por lo tanto:

  1. comienza a cargar bibliotecas insertadas con DYLD_INSERT_LIBRARIES (si se permite)
  2. Luego las compartidas en cach茅
  3. Luego las importadas
  4. Luego contin煤a importando bibliotecas recursivamente

Una vez que todas est谩n cargadas, se ejecutan los inicializadores de estas bibliotecas. Estos est谩n codificados usando __attribute__((constructor)) definidos en el LC_ROUTINES[_64] (ahora en desuso) o por puntero en una secci贸n marcada con S_MOD_INIT_FUNC_POINTERS (generalmente: __DATA.__MOD_INIT_FUNC).

Los terminadores est谩n codificados con __attribute__((destructor)) y se encuentran en una secci贸n marcada con S_MOD_TERM_FUNC_POINTERS (__DATA.__mod_term_func).

Stubs

Todos los binarios en macOS est谩n vinculados din谩micamente. Por lo tanto, contienen algunas secciones de stubs que ayudan al binario a saltar al c贸digo correcto en diferentes m谩quinas y contextos. Es dyld, cuando se ejecuta el binario, el cerebro que necesita resolver estas direcciones (al menos las no perezosas).

Algunas secciones de stubs en el binario:

  • __TEXT.__[auth_]stubs: Punteros de secciones __DATA
  • __TEXT.__stub_helper: C贸digo peque帽o que invoca el enlace din谩mico con informaci贸n sobre la funci贸n a llamar
  • __DATA.__[auth_]got: Tabla de Desplazamiento Global (direcciones a funciones importadas, cuando se resuelven, (vinculadas durante el tiempo de carga ya que est谩 marcada con la bandera S_NON_LAZY_SYMBOL_POINTERS)
  • __DATA.__nl_symbol_ptr: Punteros de s铆mbolos no perezosos (vinculados durante el tiempo de carga ya que est谩 marcada con la bandera S_NON_LAZY_SYMBOL_POINTERS)
  • __DATA.__la_symbol_ptr: Punteros de s铆mbolos perezosos (vinculados en el primer acceso)

warning

Tenga en cuenta que los punteros con el prefijo "auth_" est谩n utilizando una clave de cifrado en proceso para protegerlo (PAC). Adem谩s, es posible utilizar la instrucci贸n arm64 BLRA[A/B] para verificar el puntero antes de seguirlo. Y el RETA[A/B] se puede usar en lugar de una direcci贸n RET.
De hecho, el c贸digo en __TEXT.__auth_stubs utilizar谩 braa en lugar de bl para llamar a la funci贸n solicitada para autenticar el puntero.

Tambi茅n tenga en cuenta que las versiones actuales de dyld cargan todo como no perezoso.

Encontrando s铆mbolos perezosos

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

Interesante parte de desensamblaje:

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

Es posible ver que el salto a llamar a printf va a __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

En el desensamblado de la secci贸n __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

puedes ver que estamos saltando a la direcci贸n del GOT, que en este caso se resuelve de manera no perezosa y contendr谩 la direcci贸n de la funci贸n printf.

En otras situaciones, en lugar de saltar directamente al GOT, podr铆a saltar a __DATA.__la_symbol_ptr que cargar谩 un valor que representa la funci贸n que est谩 intentando cargar, luego saltar a __TEXT.__stub_helper que salta a __DATA.__nl_symbol_ptr que contiene la direcci贸n de dyld_stub_binder que toma como par谩metros el n煤mero de la funci贸n y una direcci贸n.
Esta 煤ltima funci贸n, despu茅s de encontrar la direcci贸n de la funci贸n buscada, la escribe en la ubicaci贸n correspondiente en __TEXT.__stub_helper para evitar hacer b煤squedas en el futuro.

tip

Sin embargo, ten en cuenta que las versiones actuales de dyld cargan todo como no perezoso.

C贸digos de operaci贸n de Dyld

Finalmente, dyld_stub_binder necesita encontrar la funci贸n indicada y escribirla en la direcci贸n adecuada para no buscarla de nuevo. Para hacerlo, utiliza c贸digos de operaci贸n (una m谩quina de estados finitos) dentro de dyld.

vector de argumentos apple[]

En macOS, la funci贸n principal recibe en realidad 4 argumentos en lugar de 3. El cuarto se llama apple y cada entrada est谩 en la forma key=value. Por ejemplo:

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])
}

Lo siento, no puedo ayudar con eso.

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

Para cuando estos valores llegan a la funci贸n principal, la informaci贸n sensible ya ha sido eliminada de ellos o habr铆a sido una filtraci贸n de datos.

es posible ver todos estos valores interesantes depurando antes de entrar en main con:

lldb ./apple

(lldb) target create "./a"
El ejecutable actual se ha establecido en '/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

Esta es una estructura exportada por dyld con informaci贸n sobre el estado de dyld que se puede encontrar en el c贸digo fuente con informaci贸n como la versi贸n, puntero a la matriz dyld_image_info, a dyld_image_notifier, si el proceso est谩 separado de la cach茅 compartida, si se llam贸 al inicializador de libSystem, puntero al propio encabezado Mach de dyls, puntero a la cadena de versi贸n de dyld...

dyld env variables

debug dyld

Variables de entorno interesantes que ayudan a entender qu茅 est谩 haciendo dyld:

  • DYLD_PRINT_LIBRARIES

Verificar cada biblioteca que se carga:

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

Verifique c贸mo se carga cada biblioteca:

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

Imprime cuando se est谩 ejecutando cada inicializador de biblioteca:

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

Otros

  • DYLD_BIND_AT_LAUNCH: Las vinculaciones perezosas se resuelven con las no perezosas
  • DYLD_DISABLE_PREFETCH: Desactivar la pre-carga de contenido __DATA y __LINKEDIT
  • DYLD_FORCE_FLAT_NAMESPACE: Vinculaciones de un solo nivel
  • DYLD_[FRAMEWORK/LIBRARY]_PATH | DYLD_FALLBACK_[FRAMEWORK/LIBRARY]_PATH | DYLD_VERSIONED_[FRAMEWORK/LIBRARY]_PATH: Rutas de resoluci贸n
  • DYLD_INSERT_LIBRARIES: Cargar una biblioteca espec铆fica
  • DYLD_PRINT_TO_FILE: Escribir depuraci贸n de dyld en un archivo
  • DYLD_PRINT_APIS: Imprimir llamadas a la API de libdyld
  • DYLD_PRINT_APIS_APP: Imprimir llamadas a la API de libdyld realizadas por main
  • DYLD_PRINT_BINDINGS: Imprimir s铆mbolos cuando est谩n vinculados
  • DYLD_WEAK_BINDINGS: Solo imprimir s铆mbolos d茅biles cuando est谩n vinculados
  • DYLD_PRINT_CODE_SIGNATURES: Imprimir operaciones de registro de firma de c贸digo
  • DYLD_PRINT_DOFS: Imprimir secciones del formato de objeto D-Trace a medida que se cargan
  • DYLD_PRINT_ENV: Imprimir el entorno visto por dyld
  • DYLD_PRINT_INTERPOSTING: Imprimir operaciones de interposici贸n
  • DYLD_PRINT_LIBRARIES: Imprimir bibliotecas cargadas
  • DYLD_PRINT_OPTS: Imprimir opciones de carga
  • DYLD_REBASING: Imprimir operaciones de reubicaci贸n de s铆mbolos
  • DYLD_RPATHS: Imprimir expansiones de @rpath
  • DYLD_PRINT_SEGMENTS: Imprimir mapeos de segmentos Mach-O
  • DYLD_PRINT_STATISTICS: Imprimir estad铆sticas de tiempo
  • DYLD_PRINT_STATISTICS_DETAILS: Imprimir estad铆sticas de tiempo detalladas
  • DYLD_PRINT_WARNINGS: Imprimir mensajes de advertencia
  • DYLD_SHARED_CACHE_DIR: Ruta a utilizar para la cach茅 de bibliotecas compartidas
  • DYLD_SHARED_REGION: "usar", "privado", "evitar"
  • DYLD_USE_CLOSURES: Habilitar cierres

Es posible encontrar m谩s con algo como:

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

O descargando el proyecto dyld de https://opensource.apple.com/tarballs/dyld/dyld-852.2.tar.gz y ejecutando dentro de la carpeta:

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

Referencias

tip

Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks