Tuesday, December 5, 2017

Threading based Sleep Evasion

Recently we came across an interesting sample: MD5: 52540f430c060a7e5753c999891514a1. A first look at the analysis revealed the following characteristics:

Besides a small spike in the classification chart towards Evader, the sample does not show any interesting behavior. It becomes more intriguing when we look at the slideshow, there we can see that the executable crashes on launch.

If we dig in further and look at the process we find some interesting sleeps:

The sample sleeps twelve times 0.1 seconds and one time 30 seconds. Thanks to Hybrid Decompilation we can easily understand the goal of the two delays:

This is the entry point of the sample. It first initializes a variable named _v8 and then creates a thread and passes _v8 by reference. Right after it sleeps for 30 seconds (0x4e20 >> 1 + 0x4e20 = 30'000). Finally, it uses the variable _v8 to calculate a function address which is added to 0x40b917. This function address is also called (passing _v12 as an argument).

Let us now have a look at the thread entry point, function 408B56:

The function is very simple. It is an endless loop that increases _a4, which is the address of _v8. For each increase, it sleeps for 0.1 seconds. When Sleep in the main function ends, _v8 is equal to 300 because the Sleep was for 30 seconds and the thread function increases _v8 by one for every 0.1 seconds.

As we saw at the beginning, the sample crashes, so the calculation of function address and _v8 must be wrong. But why?

Sleep evasions are a common trick to evade sandboxes. The simplest trick is just a sleep which delays execution of the payload. The delay usually is greater then the time the sandbox executes the sample. As a result, the payload is never executed during analysis.

To tackle this evasion, sandboxes automatically modify sleep values. In Joe Sandbox this can be defined by the user:

Let us assume we used the command _JBShortenSleepsGreaterThan(20000, 100) in the analysis above. With this setting, all sleeps greater than 20 seconds are shortened to 0.1s.

What is the effect on the code above? Well, the sleep in line 11 does not take 30 seconds anymore but rather 0.1s:

Due to that, the thread function 408B56 only runs for 0.1 seconds and _v8 is equal to 1. Therefore the function address called in line 12 is wrong and the sample crashes.

To summarize, the sample exploits the fact that sandboxes shorten sleeps/delays based on a threshold.

Full Joe Sandbox Report (with evasion working) below:

By changing _JBShortenSleepsGreaterThan we can easily bypass the evasion and see that sample is a ransomware:

Interested in trying Joe Sandbox? Register for free at Joe Sandbox Cloud Basic or contact us for an in-depth technical demo!