In the post on malicious LNK file analysis, I mentioned that malicious LNK file contained encrypted VBScript. Of course I wanted to check the script, so I started Googling for tools to decrypt VBScript files.
There is some research about the used encryption algorithm and few tools as well. The most useful to me seemed article explaining the algorithm behind script encoder. Its author also has released several versions of his scrdec tool which is supposed to decrypt VBE files.
But, as it usually happens, publicly available tools tend to blow up in the most unexpected ways on non-standard scripts.
I'm gonna fix that!
Cause of the problems
All publicly available tools assume that the encrypted file will be using ANSI encoding. But it doesn't have to! smile All the operations in vbscript.dll use wide chars and wide strings.
For example, here's a simple encrypted VBScript that is saved as a "unicode" file: https://www.mediafire.com/?cd98w73v12fpdq7. This one you can actually open in notepad, save as ANSI and then decode using scrdec.exe.
But how about this one? https://www.mediafire.com/?xdj6dfxsrcgbdr1. You can open it in text editor and save as ANSI - but after that it will not work anymore and script decoders will fail as well. How about that? wink
Writing my own script decoder
Taking into account these problems, I decided to write my own decoder in C#. C# seemed to be a logical choice as .NET uses wide strings internally and it has StreamReader class that can take care of ANSI/Unicode/UTF8 string encoding automatically - so that I can focus on the actual decryption algorithm instead.
.NET Framework contains Base64 decoding functions. Unfortunately, VBE files use a nonstandard approach to Base64. So, I had to implement simple Base64 decoder from scratch, taking into account all the weirdness of the VBE files. But that's a very simple thing to do.
First version of decoder took me few hours to make. And it worked nicely! smile But I still wasn't satisfied because vbscript.dll disassembly showed me quite a few "weird" jumps. They were not taken in my examples but I was sure I could make up some test files that would force these jumps to be taken.
Oh boy, I rather wish I hadn't done that..
Bug-features of VBScript.dll
It turns out that not only you can use wide chars, you can do some other really hairy stuff:
- you can mix encrypted code blocks with plain VBS in one file;
- and you can put several encrypted code blocks in one file;
- if encrypted code block length cannot be decoded or is larger than the filesize, this block will be considered to be plain VBS;
- if encrypted code block checksum cannot be decoded or doesn't match the calculated one, this block will be considered to be plain VBS;
Having fun already?
It took me a few more hours to get my script decoder right. Now it should work almost the same way Microsoft's vbscript.dll works. But I wonder how many AV engines got this implementation right? We shall test and see!
Testing AV engines
OK, OK, I didn't really test AV engines. I just used VirusTotal to scan the files. This approach is really flawed (for many reasons that deserve a separate blog post) but it gives you some estimate how good or bad the situation really is.
I googled for some really common and easily detected VBScript malware. In few minutes I found this great example named aiasfacoafiasksf.vbs.
Let's see what VirusTotal says for the original file:
File name: aiasfacoafiasksf.vbs
Detection ratio: 38 / 56
Analysis date: 2015-06-30 12:10:06 UTC
OK, that's pretty decent. Should I try encrypting it using Microsoft's screnc.exe?
Hmm, VT results are 24/55. Looks like some antiviruses don't even know that VBScript can be encrypted..
Let's see what happens when we start pushing the limits:
- Converting VBE to unicode we get: 19/55. Wide strings? Who needs that, the entire world speaks English;
- VBE file consisting of multiple blocks: 12/55. I know, for loop is hard to implement;
- Mixing plain text and encrypted VBE blocks: 10/55. Nah, that lonely jmp will never be taken;
- Mixing plain/encrypted blocks and using unicode: 7/55. I feel really protected now;
Please note, I haven't modified a single byte in the plain-text representation of the malicious script. All I did is change the way the script is encoded.
Let's see what happens when I add some comments to the malicious script. Again, these are cosmetic changes, I am not changing a single variable name or functionality of the script. Any AV engine that normalizes input data before scanning should still detect malware.
- Plain VBS with extra comments: 14/55. Apparently they don't normalize input data;
- VBE with extra comments: 10/55. That's kinda expected;
- Extra comment containing VBE start marker: 10/55. Suddenly getting "BehavesLike.JS.Autorun.mx" from McAfee. Excuse me? Are you using PRNG to generate those detections?
OK, so adding comments to VBScript is not that bad. But what happens when we put it all together?
Add extra comments + one VBE start marker in comment + one encrypted VBE block + use unicode: 3/53.
What can I say? Apparently some AV companies love to talk about their script engine features - but they don't implement these features properly. It would be extremely easy to detect most of my test files as malformed VBScript - as there is no way to generate such files using standard tools. But they don't do even that. Considering all this misery, I will not release any code that could be used to create super-duper-awesome-FUD VBScript encoder - even though it takes less than an hour to make one.
Note - it took me few weeks to get this post from a working draft to a published version. I'm sure that current VirusTotal results will be different, as most AV companies have had chance to process script files and make signatures for them. wink Also, any decent AV company should be able to get those samples from VirusTotal if they wish to fix their VBScript processing.
Have fun and keep it safe!
Windows Script Encoder v1.0
My VBScript decoder: https://www.mediafire.com/?9pqowl05um4jums
I am not posting the source code but this is a non-obfuscated application made in C#. So feel free to use any decompiler you like..
Set of non-malicious VBE files demonstrating some edge cases of what you can do: https://www.mediafire.com/?bu3u62t858dn4id
Article in klaphek.nl, explaining the algorithm behind script encoder
vbs_dec.pas by Andreas Marx