6 formas de ocultar datos en una aplicaci贸n de Android

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 estoy feliz en este momento, porque no tengo que estudiar el c贸digo ofuscado de alguien.


imagen


En este art铆culo, me gustar铆a compartir mi visi贸n de ofuscaci贸n, as铆 como hablar sobre un m茅todo interesante para ocultar la l贸gica de negocios en aplicaciones con NDK, que encontr茅 hace relativamente poco. Entonces, si est谩 interesado en ejemplos en vivo de c贸digo ofuscado en Android, le pido gato.


Bajo la ofuscaci贸n en el marco de este art铆culo, entendemos la reducci贸n del c贸digo ejecutable de una aplicaci贸n de Android a un formulario que es dif铆cil de analizar. Hay varias razones para dificultar el an谩lisis de c贸digo:


  1. Ning煤n negocio quiere ser hurgado en su "interior".
  2. Incluso si tiene una aplicaci贸n ficticia, siempre puede encontrar cosas interesantes all铆 (un 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 escucha esto, consulte la wiki ).


Quiero exponer un caso, por qu茅 la supuesta "protecci贸n" con ProGuard no funciona. Tome cualquier ejemplo simple de Google Samples.


imagen


Despu茅s de haber conectado ProGuard con una configuraci贸n est谩ndar, obtenemos un c贸digo descompilado:


imagen


"Ohhh, nada est谩 claro", decimos y nos calmamos. Pero despu茅s de un par de minutos de cambiar entre archivos, encontramos piezas de c贸digo similares:


imagen


En este ejemplo, el c贸digo de la aplicaci贸n parece bastante d茅bil (registro de datos, creaci贸n de 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 procesar con la configuraci贸n ProGuard.


Adem谩s, eche 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 propia clase.


Clase de datos de origen:


imagen


Puede convertirse en un tidbit para un reverso:


imagen
(autogeneraci贸n 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 falta de eficacia para proteger el c贸digo de esta manera, entonces intentemos dejar el atributo ".source" en nuestro proyecto.


-keepattributes SourceFile 

Esta l铆nea est谩 en muchos proyectos de c贸digo abierto. Le permite ver StackTrace cuando la aplicaci贸n falla. Sin embargo, al extraer ".source" del c贸digo smali, obtenemos toda la jerarqu铆a del proyecto con los nombres completos de las clases.


Por definici贸n, la ofuscaci贸n es "llevar el c贸digo fuente a una forma ilegible para contrarrestar los diferentes tipos de recepci贸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, comprimiendo nombres y eliminando clases adicionales del proyecto.


Tal uso de ProGuard es una soluci贸n f谩cil, pero no del todo adecuada para una buena ofuscaci贸n. Un buen desarrollador necesita hacer que el revendedor (o el atacante) tenga miedo de los "caracteres chinos", que son dif铆ciles de desofuscar.


Si est谩 interesado en aprender m谩s sobre ProGuard, le propongo el siguiente art铆culo informativo .


Que estamos escondiendo


Ahora veamos qu茅 suele estar oculto en las aplicaciones.


  • Claves de cifrado:

imagen


  • L贸gica de aplicaci贸n espec铆fica:

imagen


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


  • Nombres de desarrolladores de proyectos
  • Camino completo al proyecto
  • Client_secret para el protocolo Oauth2
  • Libro en PDF "C贸mo desarrollar para Android" (probablemente siempre a mano)

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


Formas de ocultar datos


Opci贸n 1: no escondas nada, deja todo a la vista


En este caso, solo te muestro esta foto :)


"Ayuda a Dasha a encontrar la l贸gica de negocios"


imagen


Esta soluci贸n rentable 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 usan solo la API p煤blica.

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


Esta decisi贸n todav铆a tiene derecho a la vida, porque, antes que nada, es simple y gratuita. A pesar de las desventajas mencionadas anteriormente, tiene una ventaja importante: 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 ensamblaje requiere que el desarrollador descompile y verifique si todo est谩 bien. Despu茅s de pasar varios minutos estudiando el archivo APK, el desarrollador (y su compa帽铆a) pueden confiar m谩s en la seguridad de su producto.


C贸mo estudiar el archivo APK

Verificar la solicitud de ofuscaci贸n es bastante simple.


Para obtener el archivo APK del proyecto, hay varias formas:


  • tomar del directorio del proyecto (en Android Studio, generalmente el nombre de la carpeta es "compilar");
  • instale la aplicaci贸n en su tel茅fono inteligente y obtenga el APK utilizando la aplicaci贸n "Apk Extractor".

Despu茅s de eso, usando la utilidad Apktool, obtenemos el c贸digo Smali (instrucciones para llegar aqu铆 https://ibotpeaches.imtqy.com/Apktool/documentation ) e intentamos encontrar algo sospechosamente le铆do en las l铆neas del proyecto. Por cierto, para buscar c贸digos legibles, puede abastecerse con comandos bash prefabricados.


Esta soluci贸n es adecuada para:


  • Aplicaciones de juguetes, aplicaciones de tiendas en l铆nea, etc.
  • Aplicaciones que son clientes realmente delgados, y todos los datos llegan exclusivamente del lado del servidor;
  • Aplicaciones que no escriben en todos sus banners "Aplicaci贸n segura No. 1".

Opci贸n 3: usar ofuscador de c贸digo abierto


Desafortunadamente, no conozco los ofuscadores gratuitos realmente buenos para aplicaciones m贸viles. Y los ofuscadores que se pueden encontrar en la red pueden causarle mucho dolor de cabeza, ya que ser谩 demasiado dif铆cil armar un proyecto de este tipo para nuevas versiones de la API.


Hist贸ricamente, los ofuscadores geniales existentes se hacen bajo c贸digo de m谩quina (para C / C ++). Buenos ejemplos:



Por ejemplo, Movfuscator reemplaza todos los c贸digos de operaci贸n con mov, hace que el c贸digo sea lineal y elimina todas las ramas. Sin embargo, no se recomienda utilizar este m茅todo de ofuscaci贸n en un proyecto de combate, porque el c贸digo corre el riesgo de ser muy lento y pesado.


Esta soluci贸n es adecuada para aplicaciones donde la parte principal del c贸digo es NDK.


Opci贸n 4: usar una soluci贸n patentada


Esta es la opci贸n m谩s competente 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 puedes ver:


  1. Los nombres de variables m谩s incomprensibles (con la presencia de letras rusas);
  2. Caracteres chinos en las l铆neas que no dejan en claro lo que realmente est谩 sucediendo en el proyecto;
  3. Hay muchas trampas agregadas al proyecto ("switch", "goto"), que cambian enormemente el flujo de c贸digo de la aplicaci贸n.

Esta soluci贸n es adecuada para:


  • Bancos
  • Compa帽铆as de seguros;
  • Operadores m贸viles, aplicaciones de almacenamiento de contrase帽a, etc.

Opci贸n 5: usar React-Native


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


Adem谩s de una comunidad muy grande, JS tiene una gran cantidad de ofuscadores abiertos. Por ejemplo, pueden convertir su aplicaci贸n en emoticones:


imagen


Realmente me gustar铆a aconsejarle sobre esta soluci贸n, pero su proyecto funcionar谩 muy poco m谩s r谩pido que una tortuga.


Pero al reducir el requisito de ofuscaci贸n de c贸digo, podemos crear un proyecto realmente bien protegido. As铆 que google "js obfuscator" 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.


Xamarin

Ser铆a muy interesante saber acerca de los ofuscadores en Xamarin, si tienes experiencia us谩ndolos, cu茅ntanoslo en los comentarios.


Opci贸n 6: usar NDK


Yo mismo a menudo ten铆a que usar NDK en mi c贸digo. Y s茅 que algunos desarrolladores creen que usar NDK guarda su aplicaci贸n de los inversores. Esto no es del todo cierto. Primero debe comprender c贸mo funciona la ocultaci贸n con el NDK.


imagen


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


NativeSummator Native Class:


imagen


Implementaci贸n del m茅todo de suma nativa:


imagen


Implementaci贸n del m茅todo nativo de suma est谩tica:


imagen


Queda claro que para llamar al m茅todo nativo, utiliza la Java_<package name>_<Static?><class>_<method> en la biblioteca din谩mica.


Si observa el c贸digo Dalvik / ART, encontraremos las siguientes l铆neas:


imagen


( fuente )


Primero, generaremos la siguiente l铆nea Java_<package name>_<class>_<method> partir del objeto Java, y luego intentaremos resolver el m茅todo en la biblioteca din谩mica usando la llamada "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


Por lo tanto, debemos encontrar una soluci贸n para que la direcci贸n de la funci贸n est茅 ofuscada.


Al principio intent茅 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. Luego decid铆 averiguar qu茅 m茅todos proporciona el NDK a los desarrolladores.


Y, he aqu铆 , hab铆a un 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 que se inicializa la biblioteca din谩mica, miles ):


imagen


Hurra, nosotros mismos escondimos la funci贸n "hideFunc". Ahora aplique nuestro ofuscador llvm favorito y disfrute de la seguridad del c贸digo en su forma final.


Esta soluci贸n es adecuada para aplicaciones que ya usan NDK (la conexi贸n de NDK trae muchas dificultades al proyecto, por lo que esta soluci贸n no es tan relevante para las aplicaciones que no son NDK).


Conclusi贸n


De hecho, la aplicaci贸n no deber铆a almacenar ning煤n dato confidencial, o deber铆a ser accesible 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 lo ayude si no desea compartir datos tan sensibles y ser un "libro abierto" para los escribas.


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


隆Piense cuidadosamente sobre los problemas de ocultaci贸n de c贸digo y no busque formas f谩ciles! :)


Por cierto, gracias al usuario miproblema por su ayuda en algunos problemas. Suscr铆base a su canal de telegramas, es interesante all铆.


Y tambi茅n muchas gracias a los usuarios de sverkunchik y SCaptainCAP por su ayuda en la edici贸n del art铆culo.

Source: https://habr.com/ru/post/es436908/


All Articles