Desarrollo de Tweak para iOS: Entendiendo __got y __la_symbol_ptr

You can use otool to see exactly the segment and section names for a Mach-O

En el mundo del hacking de iOS, hemos visto una evolución constante en las herramientas y técnicas utilizadas para desarrollar tweaks y modificaciones en el sistema operativo. Desde Cydia Substrate hasta Substitute, libhooker y ellekit, cada una de estas herramientas tiene un objetivo común: interceptar y redirigir funciones dentro de los binarios de Mach-O, como las aplicaciones de iOS. En este artículo, exploraremos dos conceptos fundamentales en este proceso: __got y __la_symbol_ptr.

¿Qué son GOT y __la_symbol_ptr en iOS?

Para entender estos conceptos, es importante conocer la estructura de los binarios de Mach-O en iOS y cómo se relacionan con las bibliotecas dinámicas. En Linux y Android, se utiliza el formato ELF (Executable and Linkable Format), que incluye secciones como la tabla de vínculos globales (GOT, por sus siglas en inglés) y la tabla de enlace de procedimientos (PLT, por sus siglas en inglés). Sin embargo, en iOS, la implementación es diferente.

En iOS, la tabla GOT se encuentra en la sección __DATA_CONST.__got, mientras que la PLT se encuentra en la sección __TEXT.__stubs. La sección __TEXT.__stubs es parte del segmento de código, marcado como W^X (escritura XOR ejecución), lo que significa que intentar escribir en esta sección activa la supervisión de código (CS_ENFORCEMENT).

En iOS, la sección __DATA.__la_symbol_ptr es equivalente a la sección .got.plt en Linux o Android. Esta sección es crucial para el enlace diferido de funciones, es decir, funciones que se resuelven en tiempo de ejecución.

¿Cómo funciona la tabla GOT?

Imagina que tienes un programa en C que llama a la función printf() de la biblioteca estándar de C (libc). En lugar de incluir la implementación completa de printf() dentro de tu programa, simplemente incluyes el encabezado stdio.h y llamas a la función donde la necesitas. Pero, ¿cómo sabe tu programa dónde está la implementación de printf()? Ahí es donde entra en juego la tabla GOT.

Cuando se utiliza una función de una biblioteca dinámica, el vinculador dinámico (dyld_stub_binder en iOS) crea un trampolín para cada función que se enlaza de manera diferida. El trampolín le dice al vinculador: “Necesito la función printf(), que está fuera de mi binario”. El vinculador busca la dirección real de printf() en la biblioteca libsystem_c.dylib (que Apple denomina libSystem.B.dylib) y copia esta dirección en la tabla __la_symbol_ptr dentro de tu binario.

Esto sucede solo una vez por función. La próxima vez que tu binario llame a printf(), golpeará el trampolín, pero como la función ya fue mapeada por el vinculador, puede ver la dirección en la tabla __la_symbol_ptr y llamar a la función directamente.

¿Por qué __DATA.__la_symbol_ptr y no __DATA_CONST.__got?

La distinción entre GOT y __la_symbol_ptr es importante porque depende de cuándo se resuelve la referencia. La sección __DATA_CONST.__got se reserva para enlaces no diferidos, cuyas referencias se resuelven al principio de la ejecución de tu aplicación, antes de que se ejecute la función main().

Por otro lado, la sección __DATA.__la_symbol_ptr se utiliza para referencias enlazadas de manera diferida, como funciones de la biblioteca estándar de C, que se poblarán cuando se necesiten por primera vez durante la ejecución de la aplicación.

En resumen, entender __got y __la_symbol_ptr es fundamental para desarrollar tweaks y modificaciones en iOS, ya que estas secciones juegan un papel crucial en el enlace y la resolución de funciones en tiempo de ejecución.

Discover more from sharklatan.com

Subscribe now to keep reading and get access to the full archive.

Continue reading