One of the characteristics of malware that we follow closely is its use of evasion techniques; that is, techniques that the malware uses to hide its true malicious nature from traditional sandboxes, until it reaches a specific target machine. In other posts, we have discussed the adoption of different evasive techniques in binary programs, and, more recently, we have looked at the use of evasion in malicious Office documents through VBA macros. Here we examine the use of evasion in JScript scripts.
In addition to actual malicious activity, JScript programs often implement one or more evasive techniques that may enable them to run undetected on sandbox systems. Here are some of the techniques that caught our attention.
The idea of stalling code is simple: slow down the execution so that analysis systems will terminate the analysis early and conclude that the program under analysis is not doing anything malicious (anything at all, in some cases). Of course, on a real user’s machine, the actual malicious activity would run right after the stalling code has finished running.
A simple way of implementing this technique consists of sprinkling the code with useless loops: these are loops in which some relatively expensive operation is performed, but whose outcome is never actually used. For example, we found a sample that dynamically computes a string value by decoding values in a loop that is executed thousands of times, and a simple check reveals that the resulting value is not used outside of the loop:
If the analysis successfully bypasses the loop (or executes it fast enough), a number of malicious activities are revealed, including C&C network traffic.
COM Object Emulation Detection
JScript programs can instantiate COM objects via the WScript.CreateObject method, passing it the desired object’s Programmatic Identifier (ProgID). For example, invoking CreateObject with the “Scripting.FileSystemObject” ProgID would lead to the instantiation of the FileSystemObject object, which exposes several methods that are useful to interact with the file system. For this operation to work, the corresponding COM object must of course be correctly installed and registered on the system.
Since COM objects often expose security relevant functionality, their instantiation and use are closely monitored by analysis systems. In many cases, simply observing how the program wants to interact with the COM object, even if the object is not actually available on the analysis system, provides useful indicators as to whether the program is malicious or not. For example, a script that tries to load an unknown object and then invokes a method with an overly long string as a parameter may be attempting to exploit a buffer overflow vulnerability. As a consequence, some analysis systems pretend that any ProgID is valid, and, for ProgIDs that don’t have a corresponding COM control installed, they return a stub object that keeps track of all the methods called on the object. This technique enables analysis systems to have visibility into less popular COM objects that may not be readily available on the analysis environment.
Unfortunately, this technique can also be used by malicious scripts to differentiate analysis systems from a real user environment. For example, we found the following (slightly de-obfuscated) code in the same sample we looked at before:
In this case, the script attempts to load an inexistent COM control (with the invalid ProgID “dcc”): if the instantiation succeeds, the variable BKYMHYNV will take a non-false value (indicating that the script is executing on an analysis environment), otherwise it will have the “false” value. Later in the code, the variable is checked: if BKYMHYNV is false, the script will attempt to perform its malicious activity, otherwise no malicious behavior will be revealed.
A simple yet effective evasion technique consists of “activating” the malicious behavior only during a specific time interval: analyses performed outside of this time range would not see any malicious activity and would classify the sample as benign.
The sample we looked at before (a really evasive one!) gives us a simple example of this technique:
In this case, the code checks that the current date’s year, as returned by a call to Date, is 2016: only in this case, malicious activity is performed.
A popular group of evasion techniques consists of checking if the environment where the script executes has characteristics that are expected in a “regular” user environment. Some of these characteristics are correlated with expected user activity (“did the user open at least five Office documents recently?”); others are related to the hardware specification of the environment (“is there at least 1GB of RAM in the system?”). Anomalous characteristics are taken as indications that the script is executing inside an analysis environment (where user activity may be limited and hardware resources may be constrained).
We observed some JScript samples using the number of processors present in the system to distinguish regular devices from analysis systems:
Here, the code reads the value of the %NUMBER_OF_PROCESSORS% environment variable, which contains the number of processors running on the machine. If the value is outside of the expected values (less than 1 or more than 8), the script terminates the execution right away; otherwise, it proceeds with downloading a second-stage payload.
We have discussed some of the evasion techniques that are used in malicious JScript files: we presented several tricks that a JScript program running in the WSH can use to distinguish analysis systems from a real user's environment, and, in turn, to avoid triggering a detection.
We have noted that these techniques are not unique or peculiar to JScript files; they actually closely resemble techniques we have seen being used in executable malware and more recently in malicious Office documents. The silver lining here is that the anti-evasion techniques that are effective in those contexts are also likely to help when analyzing evasive JScript files.
These are the samples mentioned in this post: