Analyzing obfuscated scripts using nothing but a text editor

In this blog post, we will perform an analysis on some obfuscated scripts that we received. These files were already detected by automated scanners but as these are mainly malware droppers, we figured it could be interesting to do some manual analysis to determine where the actual malware is hosted.

The first sample we will investigate is a .wsf file. This type of file is a Windows script file and can contain various scripting languages. In this case, we’re dealing with an obfuscated VBScript.

Due to the obfuscation, it’s impossible to see on first sight what this script is trying to accomplish. We could run it in a virtual machine and dynamically monitor actions taken by the script such as network connections or processes started, but first we’d like to have an idea of the code.

Some script code structures that are interesting to look for are functions that execute commands, such as:

Execute

Eval

ExecuteGlobal

Exec

In the script above, we can identify some “eval” statements and “executeglobal”. When the script is started, it will first run “InItIalIZe()”, followed by “ExecGlOBal()”. Let’s take a look at the contents of the Initialize function.

Initialize

The first statement assigns a large encoded string to a parameter. Not much we can do there. The second statement performs a split on the encoded string using “chr(EvAl(31080/740))”. If you calculate 31080/740 from the top of your head, you get 42. Unsurprisingly, using “chr()”, this is translated to “*”, which is used as the splitting character in the obfuscated string. Don’t panic.

In the next step, a loop runs through all the integers from the string above, translates them to characters and appends them to one large string. This string is then passed as the parameter to the “ExecuteGlobal” command.

ExecuteGlobal

We can piggyback on the deobfuscation that the malicious script is already performing by itself. Instead of letting it execute the deobfuscated code in the “ExecuteGlobal” command, we replace this command by something that will print the parameter to output. For Windows scripting, we can do this using “Wscript.echo”.

Using a command prompt and the “wscript” command, we can run the modified script. Our printing command shows us the decoded output in a pop-up window, which is too small to contain the entire code:

Copy pasting the entire text is not feasible either. Luckily, there’s an alternative: “cscript”. Using “csript file.wsf > deobfuscated.txt” we can print the deobfuscated string to a new file.

The result is similar to what we started with. We will follow the same approach again and replace the “execute” with a new printing statement and save the script as .vbs. Alternatively, we could surround the script with a “” and “// <![CDATA[
” tag and specify the scripting language in the “” tag. Then we could save and run the script as .wsf, similarly to the original script.

Now we get something that is actually readable. Nice! On first sight, we can see the script runs some persistence commands, including: writing the script to startup folders and adding some registry keys. This is interesting but these are not the juicy details we were looking for. We’ve added the persistence code below, along with the relevant parameters.

What follows is a loop that looks a lot more interesting. We can see that it makes a POST call using host and port parameters that are defined at the start of the script. The user-agent is set using pre-defined parameters as well (client & auth). This might allow the malware authors to determine what version of their malware is trying to communicate back to them. This is also a reason why user-agent string monitoring can be interesting for security analysts. Anomalies such as these can easily be detected.

Based on the result of this POST call, the script continues its execution through one of three functions. All of them make use of the function “D()”, that is defined a bit further in the code, presumably for deobfuscation of the POST response. The two quotes functions seem to be unused (for now).

If we want to further analyse this script, we need to have a response from the command and control server. The time to actually run the script has come!

Running the script

When executing the script and sniffing the traffic using Wireshark, we can see the POST call flying by, containing the user-agent set by the script. The response is another encoded string, prefixed with “s0”. We can use Wireshark’s “Export Objects” functionality to extract the response. If we go back to the script, we can see a case statement for this string. Looks like “Func0” will be executed on our newly obtained string! Time to let the script do the deobfuscation by replacing the execution command in “Func0” and pasting the obfuscated C&C response in our script! Note that we snipped most of the obfuscated string for the image below. Don’t forget to quit the loop or it’ll keep on running.

This final script we receive is not obfuscated at all. Looks like this malware is fingerprinting our computer. Adding an additional “echo” command would show us the information contained in the “ret” parameter. We can give you a small hint: it’s our computer and user name, OS, anti-virus,.. being sent through a POST call to the C&C. We have also observed this call in the traffic capture from before, so we could export the contents through Wireshark as well. There’s a sample of the AV fingerprinting code below.

Unfortunately, we won’t be able to figure out what the other functions (Func1 & Func2) do, since the command and control server did not send us any other command. Some possible causes could be that it decided our system is not interesting based on the information it received or it might just have been in an information gathering phase. If you want more information on this malware, look for Houdini!