Android permitirá a los operadores ocultarnos información importante

Hola querido lector, llevo bastante tiempo estudiando aplicaciones móviles. La mayoría de las aplicaciones no intentan ocultarme de alguna manera su funcionalidad “secreta”. Y en este momento me alegro, porque no tengo que estudiar el código ofuscado de alguien.

imagen

En este artículo, me gustaría compartir mi visión de la ofuscación, así como hablar sobre un método interesante para ocultar la lógica empresarial en las aplicaciones con el NDK, que descubrí hace relativamente poco tiempo. Entonces, si está interesado en ejemplos en vivo de código ofuscado en Android, vaya a cat.

A los efectos de este artículo, la ofuscación significa llevar el código ejecutable de una aplicación de Android a una forma que es difícil de analizar. Hay varias razones para dificultar el análisis del código:

  1. Ni una sola empresa quiere que la hurguen en su “interior”.
  2. Incluso si tiene una aplicación ficticia, siempre puede encontrar algo interesante allí (ejemplo con Instagram).

Muchos desarrolladores resuelven el problema simplemente bifurcando la configuración de ProGuard. Esta no es la mejor manera de proteger los datos (si es la primera vez que lo escucha, consulte la wiki).

Quiero dar un ejemplo ilustrativo de por qué no funciona la supuesta “protección” con ProGuard. Tomemos cualquier ejemplo simple de Google Samples.

imagen

Al conectar ProGuard con una configuración estándar, obtenemos el código descompilado:

imagen

“Ay, nada está claro”, decimos y nos calmamos. Pero después de un par de minutos de cambiar de archivo, encontraremos fragmentos de código similares:

imagen

En este ejemplo, el código de la aplicación parece bastante complicado (registro de datos, creación de una captura de video), por lo que algunos de los métodos utilizados en el código original se entienden fácilmente incluso después de ser procesados ​​por la configuración de ProGuard.

Además, echemos un vistazo a las clases de datos en Kotlin. La clase de datos predeterminada crea el método “toString”, que contiene los nombres de las variables de instancia y el nombre de la clase misma.

imagen

Puede convertirse en un sabroso bocado para un inversor:

imagen

(generación automática del método toString en Kotlin)

Resulta que ProGuard se esconde lejos de todo el código fuente del proyecto.

Si todavía no te he convencido de la inconveniencia de proteger el código de esta manera, intentemos dejar el atributo “.source” en nuestro proyecto.

Esta línea está en muchos proyectos de código abierto. Le permite ver StackTrace cuando la aplicación falla. Sin embargo, al extraer el “.source” del código smali, obtendremos la jerarquía completa del proyecto con los nombres completos de las clases.

READ
Qué relojes obtendrán Android Wear 2.0 y cuándo

Por definición, la ofuscación es “hacer que el código fuente sea ilegible para contrarrestar varios tipos de investigación”. Sin embargo, ProGuard (cuando se usa con una configuración estándar) no hace que el código sea ilegible; funciona como un minificador que comprime nombres y descarta clases innecesarias del proyecto.

Este uso de ProGuard es una solución fácil, pero no del todo adecuada, para una buena ofuscación al azar. Un buen desarrollador necesita hacer que el investigador (o atacante) tenga miedo de los “caracteres chinos” que son difíciles de desofuscar.

Si está interesado en obtener más información sobre ProGuard, le sugiero el siguiente artículo informativo.

que estamos escondiendo

Ahora veamos qué suele ocultarse en las aplicaciones.

imagen

  • Lógica específica de la aplicación:

imagen

Algo más inesperado (observaciones de la experiencia personal) a menudo se puede ocultar en el código, por ejemplo:

  • Nombres de los desarrolladores del proyecto.
  • Ruta completa al proyecto
  • “client_secret” para el protocolo Oauth2
  • PDF-libro “Cómo desarrollar para Android” (probablemente para tener siempre a mano)

Ahora sabemos qué se puede ocultar en las aplicaciones de Android y podemos pasar a lo principal, es decir, las formas de ocultar estos datos.

Maneras de ocultar datos

Opción 1: No escondas nada, déjalo todo a la vista

:)

En ese caso, solo te mostraré esta imagen.

“Ayuda a Dasha a encontrar la lógica empresarial”

imagen

Esta solución de bajo costo y completamente gratuita es adecuada para:

  • Aplicaciones simples que no interactúan con la red y no almacenan información confidencial del usuario;
  • Aplicaciones que solo usan la API pública.

Opción 2: use ProGuard con la configuración correcta

Esta solución todavía tiene derecho a la vida, porque, en primer lugar, es simple y gratuita. A pesar de las desventajas antes mencionadas, tiene una ventaja significativa: si las reglas de ProGuard están configuradas correctamente, la aplicación realmente puede ofuscarse.

Sin embargo, debe comprender que dicha solución después de cada compilación requiere que el desarrollador descompile y verifique si todo está bien. Al dedicar unos minutos a estudiar el archivo APK, el desarrollador (y su empresa) pueden confiar más en la seguridad de su producto.

Verificar una aplicación por ofuscación es bastante simple.

Hay varias formas de obtener el archivo APK del proyecto:

  • tomar del directorio del proyecto (en Android Studio, el nombre de la carpeta suele ser “construir”);
  • instale la aplicación en su teléfono inteligente y extraiga el APK usando la aplicación “Apk Extractor”.
READ
Cómo cambiará Google la multitarea en Android Q

Después de eso, usando la utilidad Apktool, obtenemos el código Smali (instrucciones para obtenerlo aquí https://ibotpeaches.github.io/Apktool/documentation) e intentamos encontrar algo sospechosamente legible en las líneas del proyecto. Por cierto, para buscar códigos legibles, puede abastecerse de comandos bash prefabricados.

Esta solución es adecuada para:

  • aplicaciones de juguetes, aplicaciones de compras en línea, etc.;
  • Aplicaciones que son realmente clientes ligeros, y todos los datos llegan exclusivamente del lado del servidor;
  • Aplicaciones que no dicen “Aplicación segura n.º 1” en todos sus banners.

Opción 3: Usar ofuscador de código abierto

Desafortunadamente, no conozco ningún ofuscador gratuito realmente bueno para aplicaciones móviles. Y los ofuscadores que se pueden encontrar en la web pueden causarle muchos dolores de cabeza, ya que será demasiado difícil construir un proyecto de este tipo para las nuevas versiones de la API.

Históricamente, los ofuscadores geniales existentes están hechos para código de máquina (para C/C++). Buenos ejemplos:

  • Ofuscador-LLVM, https://github.com/obfuscator-llvm/obfuscator
  • Movfuscator, https://github.com/xoreaxeaxeax/movfuscator

Por ejemplo, Movfuscator reemplaza todos los códigos de operación con movs, hace que el código sea lineal y elimina todas las ramas. Sin embargo, se desaconseja encarecidamente utilizar este tipo de ofuscación en un proyecto de producción, porque entonces el código corre el riesgo de volverse muy lento y pesado.

Esta solución es adecuada para aplicaciones en las que la mayor parte del código es NDK.

Opción 4: usar una solución propietaria

Esta es la opción más inteligente para aplicaciones serias, como software propietario:
a) apoyado;
b) siempre será relevante.

Un ejemplo de código ofuscado al usar tales soluciones:

imagen

En este fragmento de código se puede ver:

  1. Los nombres de variables más incomprensibles (con la presencia de letras rusas);
  2. Caracteres chinos en líneas que no dejan claro lo que realmente está pasando en el proyecto;
  3. Se agregaron muchas trampas al proyecto (“cambiar”, “ir a”) que cambian en gran medida el flujo de código de la aplicación.

Esta solución es adecuada para:

  • Bancos;
  • las compañías de seguros;
  • Operadores móviles, aplicaciones de almacenamiento de contraseñas, etc.

Opción 5: Usar React-Native

Decidí resaltar este punto, ya que escribir aplicaciones multiplataforma se ha convertido en una actividad muy popular ahora.

Además de una comunidad muy grande, JS tiene una gran cantidad de ofuscadores públicos. Por ejemplo, pueden convertir tu aplicación en emoji:

READ
Google confirma que los Nexus 5X y 6P no recibirán la actualización de Android P

imagen

Realmente me gustaría aconsejarle sobre esta solución, pero entonces su proyecto se ejecutará un poco más rápido que la tortuga.

Por otro lado, al reducir el requisito de ofuscación de código, podemos crear un proyecto muy bien protegido. Así que busque en Google “js ofuscator” y ofusque nuestro archivo de paquete de salida.

Esta solución es adecuada para aquellos que están listos para escribir una aplicación multiplataforma en React Native.

Sería muy interesante conocer acerca de los ofuscadores de Xamarin, si tienes experiencia usándolos, cuéntanoslo en los comentarios.

Opción 6: Usar NDK

Yo mismo tuve que usar a menudo el NDK en mi código. Y sé que algunos desarrolladores sienten que usar el NDK salva su aplicación de los reversores. Esto no es enteramente verdad. Primero, debe comprender exactamente cómo funciona la ocultación con el NDK.

imagen

Resulta que es muy simple. Hay alguna convención JNI en el código que cuando se llama al código C/C++ en un proyecto, se convertirá de la siguiente manera.

Clase nativa NativeSummator:

imagen

Implementación del método de suma nativa:

imagen

Implementación del método de suma estática nativa:

imagen

Queda claro que para llamar al método nativo, se utiliza una búsqueda de una función Java___ en la biblioteca dinámica.

Si observamos el código Dalvik/ART, encontraremos las siguientes líneas:

imagen

Primero generamos la siguiente cadena Java___ a partir del objeto Java y luego intentamos resolver el método en la biblioteca dinámica llamando a “dlsym”, que intentará encontrar la función que necesitamos en el NDK.

Así es como funciona JNI. Su principal problema es que al descompilar la biblioteca dinámica, veremos todos los métodos a la vista:

imagen

Entonces, necesitamos encontrar una solución para que la dirección de la función esté ofuscada.

Al principio traté de escribir datos directamente en nuestra tabla JNI, pero me di cuenta de que los mecanismos ASLR y las diferentes versiones de Android simplemente no me permitían hacer que este método funcionara en todos los dispositivos. Entonces decidí averiguar qué métodos ofrece el NDK a los desarrolladores.

Y he aquí que se encontró el método “RegisterNatives”, que hace exactamente lo que necesitamos (llama a la función interna dvmRegisterJNIMethod).

Definimos una matriz que describe nuestro método nativo:

imagen

Y registramos nuestro método declarado en la función JNI_OnLoad (el método se llama después de la inicialización de la biblioteca dinámica, tyts):

READ
Características geniales de Android 12 que llegarán a iOS 16

imagen

Hurra, ocultamos la función “hideFunc” nosotros mismos. Ahora apliquemos nuestro ofuscador llvm favorito y disfrutemos de la seguridad del código en la forma final.

Esta solución es adecuada para aplicaciones que ya usan el NDK (conectar el NDK trae muchas dificultades al proyecto, por lo que esta solución no es tan relevante para aplicaciones que no son NDK).

conclusión

De hecho, no se deben almacenar datos confidenciales en la aplicación, o deben estar disponibles solo después de la autenticación del usuario. Sin embargo, sucede que la lógica empresarial obliga a los desarrolladores a almacenar tokens, claves y elementos específicos de la lógica del código dentro de la aplicación. Espero que este artículo te ayude si no quieres compartir datos tan sensibles y ser un “libro abierto” para los investigadores.

Creo que la ofuscación es una parte estructural importante de cualquier aplicación moderna.

:)

¡Piense detenidamente en ocultar el código y no busque formas fáciles!

Por cierto, gracias al usuario miproblema por ayudarme con algunos problemas. Suscríbete a su canal de telegram, es interesante allí.

Y también muchas gracias a los usuarios sverkunchik y SCaptainCAP por su ayuda en la edición del artículo.

Mi teléfono estaba a mi lado, y de repente vi que la pantalla se encendió y apareció una notificación: ¿Tenemos una semana de cine? 7 días gratis, más….
Sí. Otra ventana emergente molesta. Vale la pena presionar accidentalmente Aceptar y se emitirá la suscripción y se debitará dinero de la cuenta. Sabemos que pasamos. Luego llama al operador, pide desconectar, en respuesta escucha que lo conectó usted mismo. Todo sigue como siempre y cientos de miles de personas se enfrentan a esto. No parece publicidad intrusiva, pero después de todo, muchos, sin saberlo, o sin darse cuenta, pueden, después de todo, confirmar la suscripción. Qué movimiento tan deshonesto por parte de los operadores.

Así es como se veía la notificación:

El teléfono fue bloqueado. Además, las notificaciones emergentes en la pantalla de bloqueo están deshabilitadas en mi configuración de seguridad. En general, no me gusta que algo aparezca y se muestre. Y aquí está, por sí mismo.
Si tiene este tipo de mensajes constantemente, entonces es mejor presionar el botón “atrás” o el botón “inicio” en su teléfono, porque cuando intenta hacer clic en la inscripción “cancelar”, puede presionar “ok” sin darse cuenta. Y considera que tu suscripción está activada.

READ
Sony revela cuándo los propietarios de Xperia Z3 obtendrán Android Lollipop

Por supuesto, podría pensar que se trata de un anuncio viral de aplicaciones de terceros. Pero esto es fácil de comprobar. En mi teléfono Samsung, por ejemplo, para verificar, debe ingresar la configuración, el elemento de la aplicación y, en la búsqueda, ingresar la palabra SIM

Abra las propiedades de la aplicación Beeline y vea lo que se muestra en el elemento “notificaciones”. Y se demuestra que efectivamente, había dos ventanas emergentes de la aplicación (en realidad solo vi uno):

Primero debe desmarcar las notificaciones permitidas, el menú Sim, el kit de herramientas Sim y los indicadores de iconos en la configuración de notificaciones. Y luego, estando en las propiedades de la aplicación, simplemente la detenemos a la fuerza haciendo clic en la inscripción “detener” correspondiente

Si tiene un teléfono con dos tarjetas SIM, como el mío, debe detener la segunda aplicación de la segunda tarjeta SIM:

Este método funciona hasta que se reinicia el teléfono. Pero es simple y no requiere ninguna acción compleja.

Y para aquellos que quieren deshacerse de las ventanas emergentes de forma permanente, existe una forma más difícil.

Active el menú del desarrollador, habilite la depuración de USB. En la computadora a través de ADB, debe ejecutar estos comandos de desarrollo:
adb shell pm inhabilitar-usuario com.androide.stk

adb shell am force-stop com.android.stk

No describo específicamente en detalle cómo y qué hacer, para que aquellos que no entienden el problema no rompan su teléfono. Y aquellos que entienden, saben exactamente cómo ejecutar estos dos comandos.

Después de completarlos, el menú de la tarjeta SIM debería desaparecer por completo en la lista de aplicaciones (y si no hay aplicación, entonces no emitirá notificaciones con suscripciones).

Bueno, en realidad eso es todo. Elige el método que más te convenga. El primer método es más fácil, pero después de cada reinicio del teléfono, debe detener la aplicación nuevamente. El segundo método es más difícil, requiere manos directas y una computadora, pero es más confiable.

Bueno, si aún hizo clic en Aceptar y confirmó la suscripción, entonces ya debe llamar al soporte técnico del operador y solicitar que se deshabiliten todas las suscripciones. Para algunos operadores, aún puede hacerlo a través de su cuenta o aplicación personal. Todo depende del operador. Pero, por supuesto, es mejor deshacerse del problema como un todo. Qué entonces decidir sus consecuencias.

Rating
( No ratings yet )
Like this post? Please share to your friends:
Leave a Reply

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: