Índice del Contenido

Ofuscaciones y tú

Seguridad de la aplicación Esto ya es de sobra conocido. Todo el mundo sabe que lo necesita, y los atacantes saben cómo burlar las protecciones básicas; lanzar una aplicación sin protección simplemente no es una opción. Todas las protecciones robustas constan de dos partes: prevención mediante análisis estático y detección dinámica de ataques. El análisis estático es una herramienta potente que proporciona a los atacantes información valiosa sobre los detalles de implementación específicos de la aplicación. Expone las partes más vulnerables de una aplicación, lo que ayuda a acelerar un ataque o a robar propiedad intelectual valiosa de la empresa. El código fuente, así como los datos, ofuscación es una parte importante de cualquier protección contra el análisis estático. Aquí hay algunas maneras en que el código y los datos pueden transformarse para ralentizar a los atacantes. Cuanto más tengan que trabajar, más fácil será. safer nuestro mundo puede ser.

Privatiza tu protección

Si bien las aplicaciones no deberían distribuirse sin algún tipo de ofuscación, no todas las ofuscaciones son iguales. Dos componentes cruciales para una ofuscación sólida son la propiedad intelectual privada y la aleatorización. Los ofuscadores de código abierto disponibles actualmente pueden ser tan útiles para los atacantes como para los desarrolladores de aplicaciones. El nivel de protección que ofrecen estos ofuscadores no es lo suficientemente potente como para asegurar de forma fiable aplicaciones de calidad empresarial. Las ofuscaciones efectivas deben transformar el código fuente en algo ilegible para los humanos e irreversible para las herramientas de ataque automatizadas. Las técnicas de ofuscación disponibles públicamente funcionan como una piedra Rosetta para contrarrestarlas. El uso de técnicas de ofuscación personalizadas, y no accesibles públicamente, impide que alguien como Timmy Turner revierta la ofuscación de una aplicación usando sus Hadas de IA Generativa. Combinar esos algoritmos privados con aleatoriedad inherente garantiza que ningún ser humano, ni LLM, pueda descifrar el código.

El generador de números aleatorios contraataca

Los atacantes pueden obtener mucha información comparando diferentes versiones de la misma aplicación. Que la ofuscación cambie entre versiones es absolutamente necesario. La mayoría de los motores de pseudoaleatorización usan una semilla para forzar la predictibilidad manteniendo la aleatoriedad inherente, y la ofuscación no es diferente. Simplemente incrementar o decrementar el valor de una semilla afectará drásticamente la ofuscación aplicada a una aplicación. Esto proporciona reproducibilidad cuando es necesario, pero obliga a los atacantes a empezar de cero al realizar ingeniería inversa tras el lanzamiento de una nueva versión. Es como si el atacante paleara la mitad de la entrada, se tomara un descanso para tomar chocolate caliente y volviera a encontrar nieve fresca. Una seguridad sólida se centra en desperdiciar recursos. ingeniería inversa El tiempo, y un paisaje en constante cambio, es una de las mejores maneras de perder el tiempo.

Ofuscación Ofuscando Ofuscaciones

Conceptualmente, la ofuscación es lo opuesto a la optimización. Al igual que los compiladores suelen tener múltiples fases de optimización, nosotros tenemos múltiples fases de ofuscación. Esto significa que aplicamos ofuscación a las ofuscaciones que se acaban de añadir. El resultado es increíblemente difícil de leer.

Figura 1: Las múltiples pasadas de ofuscación reducen significativamente la eficacia de herramientas como Ghidra para resolver el flujo de control del programa.

Instrucciones simples como `add` o `mov` pueden convertirse rápidamente en cincuenta o cientos de instrucciones. Ofuscar correctamente las combinaciones de `adrp add` puede diezmar la capacidad de una herramienta automatizada (como Ghidra o IDA) para resolver el flujo de control del programa. Ofuscas aparentemente menores pueden hacer casi imposible que un atacante encuentre el inicio, el final o la parte central de la llamada a la función `acceptUserCredentials`. Cientos de ofuscas variadas y acumulativas dejan a los posibles atacantes intentando averiguar cómo es posible que el código se ejecute correctamente.

¡Hazlo sonar, gíralo, configúralo!

No todas las llamadas a métodos o funciones son sensibles en una aplicación, y algunas pueden ser cruciales para el rendimiento. Si bien aplicar ofuscación de forma uniforme en toda la aplicación es significativamente mejor que no hacer nada, esta estrategia puede afectar considerablemente el rendimiento en tiempo de ejecución. Brindar a los ingenieros de seguridad la capacidad de ofuscar exhaustivamente las llamadas sensibles, a la vez que ofuscan ligeramente las llamadas que consumen muchos recursos, es fundamental para ofrecer una herramienta de protección de primer nivel. Cualquier protección dinámica (Guards) inyectada en la aplicación requiere tanta ofuscación como el código fuente subyacente. Aplicar las mismas técnicas de ofuscación de alta seguridad a estos guards activos ayuda a mantenerlos protegidos y en funcionamiento, y dificulta los intentos de los atacantes por identificarlos y eliminarlos. La configurabilidad es crucial para cualquier organización centrada en la seguridad, y las herramientas de protección deben evolucionar al ritmo de la estrategia de la empresa. Como se mencionó anteriormente, algunas ofuscas se construyen de forma diferente. A continuación, se presentan algunos conceptos que proporciona cualquier motor de ofuscación serio y cómo puede bloquear el tráfico aéreo no autorizado.

Flujo de control computado

Los atacantes pueden obtener mucha información sobre una aplicación simplemente analizando el flujo de llamadas a funciones. Para contrarrestar esto, nuestras técnicas de ofuscación utilizan el Flujo de Control Computado (CFF). El CFF impide que los descompiladores conecten las llamadas a funciones y las referencias a etiquetas con el punto de entrada principal de las aplicaciones. Es un componente fundamental de cualquier protección de primer nivel. Cuando un descompilador analiza un binario, suele ser trivial observar cómo una función llama a otra. Por ejemplo, con instrucciones como `b.eq 0x10055bc42` y `bl 0x100abcdef`, un descompilador sabe exactamente qué se encuentra en esas ubicaciones de memoria virtual. En el caso de las dos instrucciones anteriores, se trata de etiquetas dentro de una función o de la propia llamada a función. Cualquier descompilador competente generará un diagrama de red de llamadas a funciones interconectadas, mostrando una ruta de ejecución clara a través de la aplicación. Si a esto se le suman otras técnicas básicas, como observar dónde se utiliza el mensaje de "inicio de sesión exitoso" en el código ensamblador, resulta trivial para un atacante identificar código vulnerable. El flujo de control computado consiste en un conjunto de operaciones matemáticas inyectadas antes de las llamadas obvias al flujo de control. Estas operaciones matemáticas impiden que un descompilador conozca la dirección virtual relativa exacta a la que se realiza el salto, anulando así su capacidad para generar un grafo de flujo de control.

Figura 2: El flujo de control calculado (derecha) impide que un descompilador conozca la dirección virtual relativa exacta a la que se salta, destruyendo su capacidad para generar un gráfico de flujo de control funcional (izquierda).

Aplanamiento del flujo de control

El flujo de control computado ya supone un verdadero quebradero de cabeza para los descompiladores; sería una lástima empeorarlo aún más. Otra estrategia para desviar el flujo de control lógico se denomina aplanamiento del flujo de control (CFF). Existen diversas variantes de CFF, pero una recientemente añadida (llamada Nexus) revitaliza esta técnica de ofuscación crucial. Todos hemos programado alguna vez un juego de ajedrez en `main`, pero ¿qué tal programar una aplicación completa de nivel de producción en una única instrucción `switch` autorreferencial? Nexus hace precisamente eso, priorizando al mismo tiempo el rendimiento en tiempo de ejecución. Existe abundante información sobre CFF, su importancia y su funcionamiento. Es imposible exagerar lo difícil que esta técnica de ofuscación supone para los atacantes, y ninguna aplicación debería salir del entorno de pruebas sin ella.

Hopup C

Ningún juego de cuchillos de acero inoxidable estaría completo sin unas tijeras a juego, y Chopup complementa la ofuscación del flujo de control de forma muy similar. Los formatos de archivo binarios suelen estar muy comprimidos para ahorrar espacio en disco. Esto significa que la mayoría de las llamadas a funciones relacionadas están bastante cerca unas de otras. Como resultado, un binario desensamblado tiende a agrupar las funciones relacionadas y casi siempre las presenta como un bloque contiguo. Esto es demasiado fácil de leer y resulta muy molesto. Chopup cambia esto. No existe ninguna restricción técnica en un binario que exija que las llamadas a funciones sean contiguas en la memoria, y unas buenas tijeras (con un poco de flexibilidad) pueden dejar un binario funcionando como se espera, pero obligando a los atacantes a explorar cada rincón del binario en busca del flujo de control lógico.

Figura 3: Chopup obliga a los atacantes a saltar a cada rincón del binario en busca del flujo de control lógico.

mgDaea y reparación

Si bien ofuscar el flujo del código en sí es una capa de protección crucial, ofuscar los datos subyacentes de la aplicación es igualmente necesario. El daño y la reparación son el equivalente caótico y el bien en las protecciones contra el análisis estático, y casi siempre van de la mano. Dañar un dato, o incluso en algunos casos, un fragmento de código, y luego repararlo justo antes de leerlo o ejecutarlo, hace que el análisis estático sea prácticamente imposible. El daño transforma los datos especificados en lo que parece ser memoria basura. Cuando esos mismos datos se exponen a una llamada de reparación, se revierten a su forma original, muchas veces justo antes de usarse. Esos datos pueden dañarse nuevamente después de salir del ámbito y no se usarán hasta la próxima vez que se llame a la función. Esa clave API podría ser "1#&at0d$*nd@@z" en el binario al principio, pero tenga la seguridad de que se corregirá antes de usarse.

Cambio de nombre de símbolo

Incluso con ofuscación de código fuente y de datos, aún quedan nombres de símbolos en el código fuente dentro de un binario compilado. Por ejemplo, un símbolo para una función como «acceptContinuousPayment» puede proporcionar fácilmente un enlace directo a su implementación. Una vez encontrado, es muy sencillo modificar el código ensamblador y acceder a funciones premium sin pagar. El renombrado completo de símbolos oculta los símbolos restantes y no deja nada a los atacantes con qué trabajar. Eliminar cualquier indicio o pista sobre funcionalidades sensibles en un binario protegido puede obligar a los atacantes a abandonar por completo el análisis estático.

Figura 4: El cambio de nombre completo de los símbolos oculta los artefactos restantes y no deja nada con lo que los atacantes puedan trabajar.

El fin

Estos son solo ejemplos de prácticas y metodologías de ofuscación robustas, y esta lista no es exhaustiva. Dejar una aplicación sin protección permite que cualquiera tenga acceso completo a la propiedad intelectual única y proporciona a cualquier atacante una visión clara de la lógica de negocio. Con el auge meteórico de la IA generativa y la popularización de las herramientas de análisis de código fuente, escribir código, e incluso realizar ingeniería inversa, se ha vuelto mucho más fácil. Un compromiso organizacional con la implementación de soluciones de seguridad sólidas es la única vía viable en un entorno tan acelerado. No permita que el arduo trabajo de sus desarrolladores se vea comprometido sin esta protección.

 

Lea la opinión de IDC sobre la importancia de ofuscación y protección contra la manipulación como parte de tu DevSecOps práctica.

jungla de marcador de posición de demostración

Autor

Cole Herzog

¿Estás listo para expandir tu empresa?

Explorar

¿Qué hay de nuevo en el mundo de Digital.ai

Febrero 10, 2026

El muro invisible: por qué las aplicaciones seguras rompen la automatización de pruebas

Las aplicaciones móviles modernas están más protegidas que nunca. Y eso es...

Más información
Febrero 2, 2026

La evolución de Application Security Documentación, paso a paso

En 2024, el equipo de documentación de Digital.ai lanzó un nuevo…

Más información
Enero 26, 2026

El mito de la “seguridad por diseño”

He hablado con líderes de seguridad que creen que sus aplicaciones móviles…

Más información