Red de conocimiento informático - Conocimiento informático - ¿Cómo evitar que los programadores descompilen?

¿Cómo evitar que los programadores descompilen?

Desde su nacimiento, el gen de Java ha sido el espíritu de apertura. Es precisamente por esto que puede obtener el apoyo y la dedicación de la mayoría de los entusiastas y eventualmente desarrollarse muy rápidamente. ¡Es lo que es hoy! Sin embargo, dado que JAVA se utiliza cada vez más, especialmente cuando algunas funciones deben lanzarse a los usuarios finales (como aplicaciones de desarrollo de Android), a veces, para considerar la confidencialidad de la tecnología comercial, las empresas no quieren que algunos códigos centrales se publiquen. descifrado (craqueado), incluso se puede publicar con modificaciones simples, lo que puede alterar el mercado normal de software de la empresa si es grave. En este momento, se requiere que estos códigos centrales se puedan descifrar (descifrar o incluso publicar). con modificaciones simples, que pueden alterar el mercado normal de software de la empresa si es grave). comportamiento), lo que requiere que el código java no se pueda descompilar.

El fenómeno de la descompilación ya está aquí. Debido a que Java siempre se ha adherido al concepto de apertura y uso compartido, todos saben que cuando compartimos un paquete jar escrito, también compartiremos el paquete de código fuente correspondiente. Pero esto todavía no tiene nada que ver con la descompilación, pero la filosofía compartida de Java no solo nos recomienda hacer esto, ¡sino que también nos "obliga" a hacerlo sutilmente! Los archivos Java escritos en Java se compilan en archivos de clase usando javac. Durante el proceso de compilación, los archivos compilados no se cifran ni se ofuscan como C/C o C#. Es un proceso de compilación simbólico y tokenizado directo, por lo que todavía hay un proceso inverso. Problema de ingeniería: ¡se puede analizar en el archivo Java original basándose en la ingeniería inversa del archivo de clase! Aquí es donde entra en juego la compilación inversa.

Pero muchas veces, debido a las consideraciones anteriores, algunas empresas realmente no quieren que otros descompilen el código que escriben, ¡especialmente aquellas aplicaciones pagas o software de escritorio (incluso algunos proyectos j2ee wen)! ¡En este punto, prevenir la descompilación se convierte en una necesidad! Pero como se mencionó anteriormente, las clases se pueden descompilar debido al concepto abierto. Ahora que existe tal necesidad, ¿hay alguna forma de evitar la descompilación? Después de estudiar el código fuente de Java y algunas implementaciones técnicas (resulta que todos han pensado en ello antes, por lo que en los capítulos correspondientes publicaré algunos artículos más detallados y lo explicaré brevemente, lo que puede considerarse vago) ), He resuelto los siguientes métodos:

Ofrecimiento de código

Como sugiere el nombre, este método consiste en alterar el código y mezclar algún código aleatorio o caracteres especiales, que. Reduce en gran medida la legibilidad del código y logra el llamado cifrado como "curvar el país para salvarlo". De hecho, la esencia del código curvo es alterar el orden del código y reemplazar varios símbolos (como nombres de clases, nombres de métodos, nombres de atributos) con nombres aleatorios o desordenados para que no tengan sentido, de modo que a las personas les resulte difícil Lea el código. ¡Está cansado y la gente pensará que el código está cifrado de un vistazo!

Se puede ver en su implementación que su principio de implementación es solo perturbar la legibilidad normal del código, no el cifrado real. Si una persona es muy paciente, aún puede descifrar todo el programa. ¿Qué está haciendo? Es más, el código central de una aplicación es lo que la gente quiere entender, por lo que el alcance de la lectura del código se reduce considerablemente.

Por supuesto, este método existe y es relativamente popular. La razón es que básicamente puede evitar que algunos técnicos lo descompilen (como yo, déjenme descifrar un código ofuscado, preferiría reescribirlo yo mismo). )! Además, su implementación es relativamente simple y el código del proyecto no tiene un desarrollo intrusivo. Hay muchas herramientas de este tipo en la industria, tanto comerciales como gratuitas. La herramienta gratuita más popular es proguard (que es la que uso por el momento).

Como se mencionó anteriormente, este método no es un código de cifrado real. De hecho, el código aún se puede descompilar (algunas personas pueden decir que usar las opciones de optimización en proguard puede cambiar el código desde el nivel de flujo de bytes). , imposibilitando incluso que el software de descompilación JD obtenga el contenido.

Tiene sentido, pero hay dos problemas: 1. El uso de la optimización tiene altos requisitos para el JDK y el entorno, lo que fácilmente puede hacer que el código ofuscado no se ejecute normalmente. 2. Este método todavía está ofuscado, y hay; algunos problemas con la descompilación de JD. Puede haber herramientas más potentes y existen ideas contradictorias en todas partes ^_^). Entonces, ¿cómo puedo hacer que mi código de clase no pueda descompilarse? ¡Entonces necesitamos la siguiente "clase de cifrado"!

Clase de cifrado

Antes de hablar de clases de cifrado, primero debemos comprender algunos conceptos básicos de Java, como por ejemplo: ClassLoader: Cualquiera que haga Java sabe o sabrá cuando un programa Java se está ejecutando, la clase lógica se ejecuta en la JVM y en este artículo no se analiza cómo se carga la clase en la JVM (JVM Insider, etc.). , no en este artículo, así que vayamos directo al grano)? La respuesta es cómo ClassLoader.JVM inicializa todo el entorno cuando se inicia. ¿Qué es ClassLoader y qué papel desempeña? No se discutirá en este artículo.

¡Comencemos con el código más común y descubramos ClassLoader poco a poco! Mire el siguiente código:

¿Código Java?

public?class?Demo{?

public?static?void?main(String[]?args){

System.out.println(? "¿Hola? ¡Mundo!");?

}?

}?

Todo el mundo conoce el código anterior. Pero lo que quiero preguntar es: si lo compilamos usando javac y luego lo ejecutamos usando java (¿por qué no usar Ejecutar en Eclipse? Porque Eclipse lo desactiva para nosotros, simplificando tantas cosas que podemos ignorar. Hay demasiadas bajas). -Detalles a nivel, la esencia solo se puede ver en la operación original), entonces, ¿cómo se carga en la JVM? La respuesta es: cargar a través de AppClassLoader (para obtener puntos de conocimiento relacionados, consulte la introducción en el artículo /java/l-secureclass/.

¡Este método parece resolver el problema de la descompilación del código! ¡Respuesta! Allí Es un gran peligro oculto. Porque nuestro ClassLoader personalizado no se puede cifrar; de lo contrario, la JVM no puede reconocerlo y todo terminará. Si descompilo, descompilaré el ClassLoader personalizado y escribiré el contenido descifrado en el archivo especificado. y luego vuelva a poner en funcionamiento la lógica del ClassLoader personalizado. ¿Cuál cree que será el resultado? Sí, querrá morir porque el algoritmo de cifrado que probó de todas las formas posibles hará que las personas no necesiten descifrarlo. todo, pero evitándolo directamente.

Ahora, resumamos las ventajas y desventajas de este método: es simple y efectivo de implementar, sin apenas alterar el código y no afectar el desarrollo normal. liberar.

La desventaja también es obvia: ¡es fácil descifrar!

Por supuesto, desde el punto de vista de las desventajas, también puedes hacer esto: ofuscar todo el código y luego cifrarlo para asegurar que: 1) no se descifre fácilmente 2) no se descifre fácilmente; ; 3) no es fácilmente pirateable: 1) No es fácil encontrar nuestro ClassLoader personalizado; 2) Incluso si lo encontramos y lo desciframos, el código sigue siendo difícil de leer, por lo que lo verás ejecutándose en tu sangre. (Hay un artículo que creo que está muy bien escrito, puedes leerlo: /#blog/851544)

Bueno, creo que este método es muy bueno y casi me conmueve esta idea. Pero, como programador riguroso, ¡realmente no quiero dejar ningún peligro oculto aquí! ¡Así que sigo pensando!

Clase de cifrado avanzado

Dijimos que había una emboscada, ¿recuerdas? Así es, ¡es un programa local! ¿Cuáles son los métodos definidos localmente? ¡Esta es nuestra legendaria llamada JNI! Como se mencionó en un artículo presentado anteriormente, de hecho, la verdadera identidad de jvm no es java, sino jvm.dll (versión de Windows) escrito en C. ¡La llamada de archivos java y dll se implementa a través de JNI! Por lo tanto, podemos pensarlo de esta manera: JNI puede llamar a la biblioteca de clases de un lenguaje de terceros, por lo que podemos descifrar y cargar la biblioteca de clases escrita en un lenguaje de terceros (como C, porque la biblioteca de clases que generan no es fácil de descompilar), por lo que ¿podemos llamar directamente a la interfaz de carga de jvm.dll para inicializar el contenido descifrado de la clase en una clase y luego devolverlo a nuestro ClassLoader? De esta manera, siempre que nuestro ClassLoader personalizado use JNI para llamar al componente escrito en este lenguaje de terceros, todo el proceso de descifrado se realizará en una caja negra y otros no podrán descifrarlo.

¡Pues este método es realmente bueno! Pero hay dos pequeños problemas: 1. Al escribir en un idioma de terceros, debes comprender el idioma de terceros. Cuando digo capaz, quiero decir que es muy resbaladizo. 2. Para diferentes sistemas operativos, o incluso diferentes versiones del mismo sistema operativo, es posible que se necesiten códigos diferentes para generar componentes en el entorno correspondiente (como exe para Windows, entonces para Linux, etc.). Si no le importan estos dos temas, creo que este método es realmente bueno. Pero para mí, mi mantra es que cuanto más complejo sea el método, más probabilidades habrá de que se cometan errores. Personalmente, soy un gran admirador de la belleza de la simplicidad, ¡así que no tomo este enfoque a la ligera!

Por cierto, si crees que este enfoque todavía es posible, puedo recomendarte algo que escuché (que ni siquiera he usado todavía): Jinstall,

Cambiar JVM

Creo que te sorprenderás cuando veas el título. Sí, leíste bien, como programador, uno debe tener la creencia de cuestionarlo todo y pensar las cosas detenidamente. Si prestas atención, encontrarás que en realidad existen varias versiones de JVM en la industria, como Sun, IBM, Apache, Google...

Así que no obstaculices tu imaginación, la incapacidad actual Hacer esto no significa que sea imposible. Entonces se me ocurrió que si cambiaba el jvm para descifrar las clases cargadas en él, ¿no estaría bien? Durante el proceso de diseño y concepción, de repente me di cuenta: ¡las personas tienden a confundirse fácilmente cuando crecen! El uso de un lenguaje de terceros para implementar el descifrado tiene los dos primeros problemas. Simplemente cambiar la JVM enfrentará dos problemas más, y hay un problema mayor: ¡esta JVM tiene que seguir el proyecto en todas partes!