Cómo cifrar software de mensajería instantánea usando lenguaje java
1. Ideas básicas para el cifrado de software Java
El autor considera la protección del software de aplicaciones desde dos aspectos: el primero es prevenir la piratería del software y el segundo es prevenir. impedir que los competidores utilicen el software, es decir, evitar la ingeniería inversa del software.
1. Prevenir la piratería
Juzgar la legalidad de su propia existencia cuando el software se está ejecutando. Si cree que su existencia y funcionamiento son autorizados y legales, ejecutarlo en caso contrario; correr. De esta forma, incluso si el software se puede copiar a voluntad, los usuarios pirateados no podrán utilizar el software mientras no tengan la información de autorización correspondiente.
2. Evitar la descompilación
Cifre el archivo de clase generado por la compilación y descifrelo en tiempo de ejecución. El descifrador no puede descompilar el software.
2. El proceso general de cifrado de software Java
Para proteger el software desarrollado en lenguaje Java, diseñamos e implementamos un algoritmo de cifrado práctico y de alta resistencia. En lo sucesivo, el software Java que debe protegerse se denominará "programa protegido" y el software que cifra el "programa protegido" se denominará "programa de cifrado". El proceso de protección de cifrado de software se muestra en la Figura 1.
3. Análisis y diseño del algoritmo de cifrado
1. Diseño del extractor de información del usuario
Para evitar que los usuarios publiquen números de serie, lo que da como resultado "una vez emitido". , en todas partes" Para resolver el problema de la piratería, extraiga la información única relacionada con el hardware en la máquina del usuario: el número de serie de la partición C del disco duro de la computadora del usuario, y pídale al usuario que devuelva esta información junto con el nombre de usuario. y luego use el "generador de números de serie" para El usuario devuelve la información para generar un número de serie de registro de software único y legal y lo envía de regreso al usuario, y el usuario puede usar este número para registrarse y usar el software.
Este extractor de información se implementa como un pequeño programa independiente utilizando el ensamblaje Winclows 32. El código del programa se muestra en la Figura 2.
2. Diseño del generador de números de serie y la función de juicio de validez del número de serie
El algoritmo de cifrado RSA se utiliza en el generador de números de serie y en la función de juicio de validez del número de serie. En el generador de números de serie, la clave privada se utiliza para cifrar la información devuelta por el usuario (número de serie del disco duro, nombre de usuario) para obtener el número de serie de registro correspondiente; en la función de juicio de validez del número de serie, la clave privada se utiliza para; cifre el número de serie de registro ingresado por el usuario, descifre y luego compárelo con (número de serie del disco duro, nombre de usuario). Si son consistentes, llame al cargador de programas para descifrar y cargar otras partes del programa en la memoria. elimine el entorno y ejecute el cuerpo principal del programa; de lo contrario, salga.
La implementación del algoritmo de cifrado RSA requiere el uso de una biblioteca de operaciones de números grandes. Usamos la biblioteca de números grandes MIRACL para implementar los cálculos RSA. El código principal del generador de números de serie es el siguiente:
p>char szlnputString[] = "Cadena compuesta por código de máquina y nombre de usuario";
char szSerial[256]=[0] //Se utiliza para almacenar el código de registro generado
bign, d, c, m; //Escriba números grandes en MIRACL
mip→IBASE=16; //En modo hexadecimal
n= mlrvar(0) ; //Inicializa número grande Número
d= mirvar(0);
c= mirvar(0); //C almacena el número de cadena de entrada
m= mlrva( o);
bytes a big(len, szlnputString, c);
//Convierte la cadena de entrada en un número grande y guárdala en la variable c
cinstr(n, "módulo expresado como una cadena"); //Inicializa el módulo
cinstr(d, "clave pública expresada como una cadena"): //Inicializa el público key Key
powmod(c, d, n, m); //Calcular m=cdmod n
cotstr(m, szSerial); //La cadena hexadecimal de m es For el código de registro
El código principal de la función de detección de validez del número de serie es el siguiente:
char szlnputStringL]=”Una cadena compuesta por código de máquina y nombre de usuario”;
char szSerial[ 256] = "Número de serie ingresado por el usuario"
bign, e, c, m //Tipo de número grande en MIRACL
mip→IBASE =16; //En modo hexadecimal
cinstr(m, szSerial); //Convierte el número de serie hexadecimal en forma de número grande
cinstr(n, "modulo n String form" ); //Inicializa el módulo n
cinstr(e, "Clave pública en forma de cadena"); //Inicializa la clave pública
if compare(m, n)==-1. ) //mlt; descifrar solo cuando n
{
powmod(m, e, n, c); //Calcular m=me mod n
big_to _bytes(0, c, szSerial, 0); //Convertir a cadena
return lstrcmp(szlnputString, szSerial);
}
3. de fuerte relación de acoplamiento
Si simplemente usa el proceso que se muestra en la Figura 3 en la función de detección de legalidad del número de serie:
El descifrador puede usar los siguientes varios métodos para atacar:
(1) Modifique la instrucción de devolución de la "Subfunción de Legalidad del Juez" para que siempre devuelva el valor correcto, de modo que cualquier número de serie pueda usarse para instalar/usar el software.
(2) Modifique la instrucción de salto después del juicio para que el programa siempre salte a la rama correcta. El efecto es el mismo que el anterior.
(3) Ejecute una instrucción de salto antes de la "subfunción de legalidad del juicio" para omitir el juicio y saltar directamente a la rama de "ejecución normal" para ejecutar. De esta manera puede instalar/usar el software sin él. ingresando un número de serie.
Para evitar los métodos de ataque anteriores, el autor agregó una "función de detección de legalidad del número de serie" al programa para que esté "fuertemente acoplado" con otras partes del programa (es decir, para mejorar su correlación). con otras partes del programa y convertirse en el programa como un todo (una parte inseparable, una vez modificado, el programa no funcionará correctamente) (ver Figura 1), y se configura una "función de detección de integridad" para determinar si el código relevante ha sido modificado.
Por supuesto, por la misma razón, la "función de detección de integridad" también debe tener una relación de "fuerte acoplamiento" con otras partes del programa.
Las relaciones de acoplamiento fuertes se establecen de las siguientes maneras:
El acceso aleatorio a funciones en otras partes del programa (como la función A) requiere una "función de detección de validez del número de serie" fuertemente acoplada. " y "Función de detección de integridad" eligen aleatoriamente usar un número de serie incorrecto o el número de serie ingresado por el usuario al llamar, y eligen ejecutar el código de función normal en A o el código de función que sale con un error según el resultado devuelto El proceso se muestra en la Figura 4.
Después de esta mejora, si el cracker se descifra modificando el código, el programa se cerrará debido a una falla en la "detección de integridad" si se utiliza SMC y otras tecnologías para evitar la "función de juicio de legalidad del número de serie"; " y saltar directamente a la entrada de ejecución cuando el número de secuencia sea correcto; en ejecuciones posteriores, el programa saldrá debido a fallas de llamada de acoplamiento aleatorio. Un pirata informático que quiera descifrar el software tendrá que rastrear todas las funciones que realizan llamadas acopladas, lo que obviamente es una tarea difícil.
4. Diseño de la función de detección de integridad
Utilizamos el algoritmo CRC para calcular el código de verificación del archivo cuya integridad debe verificarse y utilizamos la clave pública del cifrado RSA. El algoritmo (diferente de la secuencia El par de clave pública/clave privada utilizado en la prueba de legalidad) se cifra y se almacena en un archivo específico. Durante la prueba, el algoritmo CRC se utiliza primero para regenerar el archivo cuya integridad debe verificarse.
Código de verificación y use la clave privada para descifrar el código de verificación guardado. Compare los dos; si son iguales, la operación se ejecutará normalmente; de lo contrario, salga.
5. Diseño del cargador de programas
A diferencia de los programas compilados en código de máquina para su ejecución, los programas Java sólo pueden ser interpretados y ejecutados por la máquina virtual Java. El cargador incluye: inicializar la máquina virtual Java; descifrar el archivo de clase que se ejecutará actualmente en la memoria; ejecutar el archivo c:lass descifrado en la máquina virtual y descifrar otro archivo de clase cuando sea necesario; La Figura 5 es el código utilizado para inicializar la JVM:
Lo anterior presenta el método de protección de cifrado que diseñamos para el software Java, que utiliza una variedad de tecnologías de cifrado y tiene una alta resistencia a la piratería; Se utiliza, bajo costo. El autor lo probó en la plataforma de la serie Windows y descubrió que funciona de manera estable y tiene buenos resultados.
Durante el proceso de investigación y desarrollo, también resumimos algunas experiencias en software de protección de cifrado:
1. Los códigos clave y los datos deben cifrarse estáticamente y luego descifrarse y ejecutarse dinámicamente; la plataforma de trabajo utiliza tecnología anti-rastreo/depuración;
2. Aproveche al máximo las funciones del sistema, por ejemplo, utilizando archivos DLL o formularios de controladores en Windows para obtener la máxima riqueza y limitación. uso completo del sistema Tiene varias funciones;
3. Si es posible, el código clave debe almacenarse en un lugar que no se pueda copiar.
4. estar relacionado con la información del usuario, como el código de máquina, para evitar el número de serie de Yanfubu;
5. La racionalidad del proceso de cifrado es más importante que la solidez del algoritmo de cifrado en sí.