Cómo evitar la ingeniería inversa de un archivo APK
Estoy desarrollando una aplicación de procesamiento de pagos para Android y quiero evitar que un pirata informático acceda a recursos, activos o código fuente desde el archivo APK .
Si alguien cambia la extensión .apk a .zip, puede descomprimirla y acceder fácilmente a todos los recursos y activos de la aplicación, y utilizando dex2jar y un descompilador de Java, también puede acceder al código fuente. Es muy fácil realizar ingeniería inversa en un archivo APK de Android; para obtener más detalles, consulte la pregunta de Stack Overflow Ingeniería inversa desde un archivo APK a un proyecto .
He utilizado la herramienta Proguard proporcionada con el SDK de Android. Cuando realizo ingeniería inversa en un archivo APK generado usando un almacén de claves firmado y Proguard, obtengo un código ofuscado.
Sin embargo, los nombres de los componentes de Android permanecen sin cambios y algunos códigos, como los valores-clave utilizados en la aplicación, permanecen sin cambios. Según la documentación de Proguard, la herramienta no puede ofuscar los componentes mencionados en el archivo de manifiesto.
Ahora mis preguntas son:
- ¿Cómo puedo evitar por completo la ingeniería inversa de un APK de Android? es posible?
- ¿Cómo puedo proteger todos los recursos, activos y código fuente de la aplicación para que los piratas informáticos no puedan piratear el archivo APK de ninguna manera?
- ¿Existe alguna manera de hacer que la piratería sea más difícil o incluso imposible? ¿Qué más puedo hacer para proteger el código fuente en mi archivo APK?
1. ¿Cómo puedo evitar por completo la ingeniería inversa de un APK de Android? es posible?
AFAIK, no existe ningún truco para evitar por completo la ingeniería inversa.
Y también muy bien dicho por @inazaruk: hagas lo que hagas con tu código, un atacante potencial puede cambiarlo de la forma que considere factible . Básicamente no puedes proteger tu aplicación para que no sea modificada. Y cualquier protección que coloque allí se puede desactivar o eliminar.
2. ¿Cómo puedo proteger todos los recursos, activos y código fuente de la aplicación para que los piratas informáticos no puedan piratear el archivo APK de ninguna manera?
Sin embargo, puedes hacer diferentes trucos para dificultar la piratería. Por ejemplo, utilice ofuscación (si es código Java). Esto suele ralentizar significativamente la ingeniería inversa.
3. ¿Existe alguna manera de hacer que la piratería sea más difícil o incluso imposible? ¿Qué más puedo hacer para proteger el código fuente en mi archivo APK?
Como todo el mundo dice, y como probablemente sepas, no existe una seguridad del 100%. Pero el lugar por donde empezar para Android, que Google ha integrado, es ProGuard. Si tiene la opción de incluir bibliotecas compartidas , puede incluir el código necesario en C++ para verificar el tamaño de los archivos, la integración, etc. Si necesita agregar una biblioteca nativa externa a la carpeta de la biblioteca de su APK en cada compilación, puede usarla. por la siguiente sugerencia.
Coloque la biblioteca en la ruta de la biblioteca nativa que por defecto es "libs" en la carpeta de su proyecto. Si creó el código nativo para el objetivo 'armeabi' , colóquelo en libs/armeabi . Si se creó con armeabi-v7a , colóquelo en libs/armeabi-v7a.
<project>/libs/armeabi/libstuff.so
AFAIK, no puedes proteger los archivos en el directorio /res más de lo que están protegidos en este momento.
Sin embargo, hay pasos que puedes seguir para proteger tu código fuente, o al menos lo que hace, si no todo.
- Utilice herramientas como ProGuard. Esto ofuscará su código y hará que sea más difícil de leer cuando esté descompilado, si no imposible.
- Saque las partes más críticas del servicio de la aplicación y colóquelas en un servicio web, oculto detrás de un lenguaje del lado del servidor como PHP. Por ejemplo, si tienes un algoritmo que te ha costado un millón de dólares escribirlo. Obviamente no quieres que la gente lo robe de tu aplicación. Mueva el algoritmo y haga que procese los datos en un servidor remoto, y use la aplicación para simplemente proporcionarle los datos. O utilice el NDK para escribirlos de forma nativa en archivos .so, que tienen muchas menos probabilidades de descompilarse que los apks. No creo que exista un descompilador para archivos .so en este momento (e incluso si existiera, no sería tan bueno como los descompiladores de Java). Además, como @nikolay mencionó en los comentarios, debe usar SSL al interactuar entre el servidor y el dispositivo.
- Cuando almacene valores en el dispositivo, no los almacene en formato sin formato. Por ejemplo, si tienes un juego y estás almacenando la cantidad de moneda del juego que tiene el usuario en SharedPreferences. Supongamos que son
10000
monedas. En lugar de guardarlo10000
directamente, guárdelo usando un algoritmo como((currency*2)+1)/13
. Entonces10000
, en lugar de, guarda1538.53846154
en SharedPreferences. Sin embargo, el ejemplo anterior no es perfecto y tendrás que trabajar para encontrar una ecuación que no pierda vigencia debido a errores de redondeo, etc. - Puedes hacer algo similar para las tareas del lado del servidor. Ahora, como ejemplo, tomemos su aplicación de procesamiento de pagos. Digamos que el usuario tiene que realizar un pago de
$200
. En lugar de enviar un$200
valor sin formato al servidor, envíe una serie de valores más pequeños y predefinidos que sumen$200
. Por ejemplo, tenga un archivo o tabla en su servidor que equipare palabras con valores. Entonces digamos queCharlie
corresponde a$47
yJohn
a$3
. Entonces, en lugar de enviar$200
, puedes enviarCharlie
cuatro veces yJohn
cuatro veces. En el servidor, interpreta lo que significan y súmalo. Esto evita que un pirata informático envíe valores arbitrarios a su servidor, ya que no sabe qué palabra corresponde a qué valor. Como medida adicional de seguridad, también podría tener una ecuación similar al punto 3 y cambiar las palabras clave cada cierton
número de días. - Finalmente, puedes insertar código fuente aleatorio inútil en tu aplicación, de modo que el hacker busque una aguja en un pajar. Inserte clases aleatorias que contengan fragmentos de Internet o simplemente funciones para calcular cosas aleatorias como la secuencia de Fibonacci. Asegúrese de que estas clases se compilen, pero que no sean utilizadas por la funcionalidad real de la aplicación. Agregue suficientes clases falsas y al hacker le resultará difícil encontrar su código real.
Considerándolo todo, no hay manera de proteger tu aplicación al 100%. Puedes hacerlo más difícil, pero no imposible. Su servidor web podría estar comprometido, el hacker podría descubrir sus palabras clave al monitorear múltiples montos de transacciones y las palabras clave que usted envía, el hacker podría revisar minuciosamente la fuente y descubrir qué código es ficticio.
Sólo puedes contraatacar, pero nunca ganar.
En ningún momento de la historia de la informática ha sido posible evitar la ingeniería inversa del software cuando se le entrega una copia funcional al atacante. Además, lo más probable es que nunca sea posible .
Una vez entendido esto, existe una solución obvia: no le des tus secretos a tu atacante. Si bien no puedes proteger el contenido de tu APK, lo que puedes proteger es todo lo que no distribuyas. Por lo general, se trata de software del lado del servidor que se utiliza para cosas como activación, pagos, aplicación de reglas y otros fragmentos de código jugosos. Puede proteger activos valiosos al no distribuirlos en su APK. En su lugar, configure un servidor que responda a las solicitudes de su aplicación, "use" los activos (lo que sea que eso signifique) y luego envíe el resultado a la aplicación. Si este modelo no funciona para los activos que tiene en mente, es posible que desee reconsiderar su estrategia.
Además, si tu objetivo principal es prevenir la piratería de aplicaciones : ni te molestes. Ya ha gastado más tiempo y dinero en este problema del que cualquier medida antipiratería podría esperar salvarle. El retorno de la inversión para resolver este problema es tan bajo que no tiene sentido ni siquiera pensar en ello.
Primera regla de seguridad de las aplicaciones: cualquier máquina a la que un atacante obtenga acceso físico o electrónico sin restricciones ahora pertenece a su atacante, independientemente de dónde se encuentre realmente o cuánto haya pagado por ella.
Segunda regla de seguridad de las aplicaciones: cualquier software que salga de los límites físicos dentro de los cuales un atacante no puede penetrar ahora pertenece a su atacante, independientemente de cuánto tiempo haya dedicado a codificarlo.
Tercera regla: cualquier información que salga de esos mismos límites físicos que un atacante no puede traspasar ahora pertenece a su atacante, sin importar cuán valiosa sea para usted.
Los fundamentos de la seguridad de las tecnologías de la información se basan en estos tres principios fundamentales; La única computadora verdaderamente segura es la que está encerrada en una caja fuerte, dentro de una jaula de Farraday, dentro de una jaula de acero. Hay computadoras que pasan la mayor parte de su vida útil precisamente en este estado; Una vez al año (o menos), generan las claves privadas para las autoridades de certificación raíz de confianza (frente a una gran cantidad de testigos con cámaras que graban cada centímetro de la habitación en la que se encuentran).
Ahora, la mayoría de las computadoras no se utilizan en este tipo de entornos; están físicamente a la intemperie, conectados a Internet a través de un canal de radio inalámbrico. En resumen, son vulnerables, al igual que su software. Por lo tanto, no se puede confiar en ellos. Hay ciertas cosas que las computadoras y su software deben saber o hacer para ser útiles, pero se debe tener cuidado para garantizar que nunca puedan saber o hacer lo suficiente como para causar daño (al menos no daño permanente fuera de los límites de esa única máquina). ).
Todo esto ya lo sabías; es por eso que estás intentando proteger el código de tu aplicación. Pero ahí radica el primer problema; las herramientas de ofuscación pueden hacer que el código sea un desastre para que un humano intente profundizar en él, pero el programa aún tiene que ejecutarse; eso significa que el flujo lógico real de la aplicación y los datos que utiliza no se ven afectados por la ofuscación. Con un poco de tenacidad, un atacante puede simplemente desenmascarar el código, y eso ni siquiera es necesario en ciertos casos en los que lo que está mirando no puede ser otra cosa que lo que está buscando.
En su lugar, debería intentar asegurarse de que un atacante no pueda hacer nada con su código, sin importar lo fácil que le resulte obtener una copia clara del mismo. Eso significa que no hay secretos codificados, porque esos secretos no son secretos tan pronto como el código sale del edificio en el que lo desarrolló.
Estos valores-clave que ha codificado deben eliminarse por completo del código fuente de la aplicación. En cambio, deberían estar en uno de tres lugares; memoria volátil en el dispositivo, que es más difícil (pero no imposible) para un atacante obtener una copia fuera de línea; permanentemente en el clúster de servidores, al que controlas el acceso con mano de hierro; o en un segundo almacén de datos no relacionado con su dispositivo o servidores, como una tarjeta física o en las memorias de su usuario (lo que significa que eventualmente estará en la memoria volátil, pero no tiene que estar así por mucho tiempo).
Considere el siguiente esquema. El usuario ingresa sus credenciales para la aplicación desde la memoria del dispositivo. Desafortunadamente, debes confiar en que el dispositivo del usuario no esté ya comprometido por un registrador de teclas o un troyano; Lo mejor que puede hacer a este respecto es implementar seguridad multifactor, recordando información de identificación difícil de falsificar sobre los dispositivos que ha utilizado el usuario (MAC/IP, IMEI, etc.) y proporcionando al menos un canal adicional mediante que se puede verificar un intento de inicio de sesión en un dispositivo desconocido.
Las credenciales, una vez ingresadas, son ofuscadas por el software del cliente (usando un hash seguro) y las credenciales de texto sin formato se descartan; han cumplido su propósito. Las credenciales ofuscadas se envían a través de un canal seguro al servidor autenticado por certificado, que las codifica nuevamente para producir los datos utilizados para verificar la validez del inicio de sesión. De esta manera, el cliente nunca sabe qué se compara realmente con el valor de la base de datos, el servidor de aplicaciones nunca conoce las credenciales de texto sin formato detrás de lo que recibe para su validación, el servidor de datos nunca sabe cómo se producen los datos que almacena para su validación y un hombre en el medio sólo ve galimatías incluso si el canal seguro estuviera comprometido.
Una vez verificado, el servidor transmite un token a través del canal. El token solo es útil dentro de la sesión segura, está compuesto por ruido aleatorio o una copia cifrada (y por lo tanto verificable) de los identificadores de sesión, y la aplicación cliente debe enviar este token en el mismo canal al servidor como parte de cualquier solicitud. hacer algo. La aplicación cliente hará esto muchas veces, porque no puede hacer nada que involucre dinero, datos confidenciales o cualquier otra cosa que pueda ser dañina por sí misma; en su lugar, debe pedirle al servidor que realice esta tarea. La aplicación cliente nunca escribirá información confidencial en la memoria persistente del dispositivo, al menos no en texto plano; el cliente puede solicitar al servidor a través del canal seguro una clave simétrica para cifrar cualquier dato local, que el servidor recordará; en una sesión posterior, el cliente puede solicitar al servidor la misma clave para descifrar los datos y utilizarlos en la memoria volátil. Esos datos tampoco serán la única copia; Todo lo que el cliente almacena también debe transmitirse de alguna forma al servidor.
Obviamente, esto hace que su aplicación dependa en gran medida del acceso a Internet; el dispositivo cliente no puede realizar ninguna de sus funciones básicas sin una conexión adecuada y autenticación por parte del servidor. En realidad, no es diferente a Facebook.
Ahora, la computadora que el atacante quiere es su servidor, porque es ella y no la aplicación/dispositivo cliente lo que puede generarle dinero o causar dolor a otras personas para su disfrute. Está bien; Obtendrá mucho más por su dinero gastando dinero y esfuerzo para proteger el servidor que tratando de proteger a todos los clientes. El servidor puede estar detrás de todo tipo de cortafuegos y otros sistemas de seguridad electrónica y, además, puede protegerse físicamente detrás de acero, hormigón, acceso mediante tarjeta de acceso/PIN y videovigilancia las 24 horas. Su atacante tendría que ser muy sofisticado para obtener cualquier tipo de acceso directo al servidor, y usted (debería) saberlo inmediatamente.
Lo mejor que puede hacer un atacante es robar el teléfono y las credenciales de un usuario e iniciar sesión en el servidor con los derechos limitados del cliente. Si esto sucediera, al igual que si perdiera una tarjeta de crédito, se debe indicar al usuario legítimo que llame a un número 800 (preferiblemente fácil de recordar, y no en el reverso de una tarjeta que llevaría en su bolso, billetera o maletín, que podría ser robado junto con el dispositivo móvil) desde cualquier teléfono al que puedan acceder y que los conecte directamente con su servicio de atención al cliente. Afirman que les robaron el teléfono, proporcionan un identificador único básico y la cuenta está bloqueada, cualquier transacción que el atacante haya podido procesar se revierte y el atacante vuelve al punto de partida.
1. ¿Cómo puedo evitar por completo la ingeniería inversa de un APK de Android? es posible?
esto no es posible
2. ¿Cómo puedo proteger todos los recursos, activos y código fuente de la aplicación para que los piratas informáticos no puedan piratear el archivo APK de ninguna manera?
Cuando alguien cambia una extensión .apk a .zip, después de descomprimirla, alguien puede obtener fácilmente todos los recursos (excepto Manifest.xml ), pero con APKtool también se puede obtener el contenido real del archivo de manifiesto. De nuevo, un no.
3. ¿Existe alguna manera de hacer que la piratería sea más difícil o incluso imposible? ¿Qué más puedo hacer para proteger el código fuente en mi archivo APK?
De nuevo, no, pero puedes prevenir hasta cierto nivel, es decir,
- Descargue un recurso de la Web y realice algún proceso de cifrado
- Utilice una biblioteca nativa precompilada (C, C++, JNI, NDK)
- Realice siempre algún hash ( claves MD5 / SHA o cualquier otra lógica)
Incluso con Smali
, la gente puede jugar con tu código. Considerándolo todo, no es POSIBLE.