VX Heaven

Library Collection Sources Engines Constructors Simulators Utilities Links Forum

Inline JScript For x86 Cryptography

Valhalla #3
December 2012

[Back to index] [Comments]

About Unit00

I have written a lot of script viruses, and even more machine code viruses. In Valhalla 1, I wrote a JScript that used the .NET Framework to get obfuscated and compiled into an executable file. It was the first time I put JScript in binary file. However this time I present a new and different technique. This is my first W32 virus to have inline JScript code using it for cryptography. I call it W32/Unit00. You get the best of both worlds. ;)

MSScript - What is it?

Microsoft's ScriptControl, is an ActiveX control that gives the power to applications to run script code pretty much in the same fashion as if it was the Windows Script Host. Except that WSH is not involved here, it does however, shares the same DLL that are commonly use to interpret the code (jscript.dll, for example).

We must deal with OLE32, which can be tedious and difficult, but having the script and the possibility to control it, is a chance that we should not let go.

It is also very interesting approach for extension of functionality. The ScriptControl offers various methods to help us achieve our goal.

How we do it

Scripts can be loaded using AddCode(sourcecode) method. Only functions (JS/VBS) or subrutines (VBS) should loaded using this method. However, you do can load code that is not wrapped into a function/subroutine, but this does not return anything that functions/subroutine might return (there are workarounds, like loading an object into the control, if the object have properties that accept that information to be assigned, you then can use it to transfer data from one context to another).

AddCode performs an automatic parse to find syntax mistakes, an exception happens if any.

The official method to run the script is using Run method. This method calls a previously loaded function, so this one does returns data.

We also have Eval, for expressions, and we have ExecuteStatement for single code line.

Outputs from methods such as Run or Eval are a _variant_t class. We can use Extractors to assist us on the conversion. For strings we will get BSTR that you could convert if you want.

Eval expressions

Here is a very simple example. C++ code this time. :)

CoInitialize(NULL); {
        MSScriptControl::IScriptControlPtr scriptScriptControl(__uuidof(MSScriptControl::ScriptControl));

        /* set Language property: JScript/VBScript only. default is VBScript, but it fails if you don't set it. */
        scriptScriptControl->Language = "JScript";

        /* now use Eval method */
        unsigned long uintOut = (unsigned long)scriptScriptControl->Eval("1 + 1").operator unsigned long();


Static detection might work for some script viruses. Detection through emulation can be hard when it comes to script viruses. With both worlds combined, the script code does not need to be very complex.

I use it for decryption. We load IScriptControl and retrieve its interface for setting it up.

When we use the AddCode code we must send our script code formatted as a BSTR data string. Since it is actually a pointer to an Unicode string, it is not necessary to set the string length prefix. We then run the code using Run method.

My script code function in Unit00 simply returns Unit00's body encoded (but decrypted) as a large string of hexadecimals. The output is also a BSTR, so we must convert it back to machine code, and we are done.

Tales from the Crypt

The algorithm I implement in this code for encryption/decryption is the RC4. It is a pretty small algorithm, and very simple. It was very easy to implement in JScript. I took the pseudocode in Wikipedia's entry for the description and it was pretty straight forward to create the JScript code.

This is how it looks the key-schedule initialisation:

    s = [];
    for(i = 0; i < 256; i++) {
        s[i] = i;

    j = 0;

    for(i = 0; i < 256; i++) {
        j = (j + s[i] + k[i % k.length]) % 256;
        t = s[i];
        s[i] = s[j];
        s[j] = t;

And this is the pseudo-random generation algorithm:

    i = 0;
    j = 0;
    for(u = 0; u < b.length; u++) {
        i = (i + 1) % 256;
        j = (j + s[i]) % 256;
        t = s[i];
        s[i] = s[j];
        s[j] = t;
        o[u] = (b[u] ^ s[(s[i] + s[j]) % 256]);

An implementation in x86 code of the RC4 algorithm is also required to encrypt and encode the virus for the first time.

No 64-bit

The OCX is only available for 32-bit applications, no 64-bit official port is there for Windows. Not good even for script files: on 64-bit OS Windows default behavior is run WSH from System32 and not from SysWOW64, therefore the object cannot be created. Switch to SysWOW64 on 64-bit platforms.

September 2012
By accessing, viewing, downloading or otherwise using this content you agree to be bound by the Terms of Use! aka