![](https://habrastorage.org/webt/sc/cl/os/scclosmhrxygm1sxytg94as3z_i.jpeg)
Since we do not know the internal features of the work of commercial sandboxes, in some cases we do double-check - manually analyze the samples that passed the test. Recently, we have come across several times that some commercial sandboxes (for objective reasons, we cannot say which ones) did not detect certain malicious files during dynamic analysis, and if the static analyzer was also silent, the file was skipped altogether.
The sandbox scan managed to bypass such well-known malware families as Pony, Loki and Hawkeye. Only one thing united them - they were covered by a packer written in Visual Basic.
Given that these HPE families have long been nothing new, the “positive” sandbox verdict is very depressing. Therefore, we decided to describe the general principle of operation of this packer and the observations made by us over some time.
The general scheme of the packer’s work is conditionally divided into 4 stages and is shown in the diagram below.
![](https://habrastorage.org/webt/fk/c9/of/fkc9of6pras7-cd55luw1l1mpai.jpeg)
The entry point of the malicious file looks typical for Visual Basic applications:
![](https://habrastorage.org/webt/vj/ia/he/vjiaheueiyapa2swzf8_cqrwzka.jpeg)
We met different variants of this packer, and the VB Wrapper code changed frequently, but the task performed remained the same: transfer control to the Stage 1 code. In earlier samples, control was transferred using the Enum * class API functions (for example, EnumWindows, EnumCalendarInfo, etc.). e) for which the address Stage 1 of the code was indicated as a parameter. Recently, we observe that control is transferred directly.
Stage 1
The control receives the code Stage 1. This code is not encrypted, but obfuscated. Obfuscation methods vary from sample to sample, but the general operation algorithm does not change:
- A cycle with many (including garbage) instructions, which generates the key necessary for decoding the Stage 2 code. The peculiarity of this code fragment is that there are no Sleep-functions, but due to the large number of iterations, its execution takes an average of 1-2 minutes.
- Decryption (regular XOR) and transfer of control to Stage 2 code.
The screenshot below shows examples of obfuscation methods used:
![](https://habrastorage.org/webt/--/p-/xl/--p-xlue_skm9loofz_wj3tmeic.jpeg)
2 stage
The main task of the code in Stage 2 is to check the environment and implement anti-debugging methods. Some sections of the code are encrypted (decrypted before execution, and after that, encrypted back with the same XOR algorithm) to make it difficult to detect by signatures. After decryption, the characteristic features are visible, according to which the Stage 2 code can be recognized by manual analysis.
![](https://habrastorage.org/webt/eb/n8/oq/ebn8oqw9vqcysrl-c98pdfdrdjq.jpeg)
The list of checks is quite large and differs in different versions of the packer, so we will give several methods that were found in all versions, with screenshots, and at the end we list the entire list in the table.
1) GetTickCount + Sleep
The current timestamp is taken, Sleep is called for 2 seconds, after which another timestamp is immediately taken.
After that, the difference between the marks is checked (whether 2 seconds actually passed).
![](https://habrastorage.org/webt/mp/ip/pj/mpippjhsogyg_uvk0eikkuehm_w.jpeg)
2) SetErrorMode
Checks the correct operation of the SetErrorMode API call. The function is called twice in a row with parameters 0x800 and 0x0, after which the result of the second call is checked: it must be equal to 0x800.
![](https://habrastorage.org/webt/gp/kr/vx/gpkrvxff7l4irukw4oqifs6ai4a.jpeg)
3) SetLastError
First, SetLastError is called with the parameter 0x5, after which it is checked that the value of Last error code in the TEB is correctly set (that is, it is 0x5).
![](https://habrastorage.org/webt/3k/am/vh/3kamvhsb_z6nw8tlchtlcuhxa0q.jpeg)
4) Checking cursor movement
The code enters an endless loop waiting for the mouse to move.
![](https://habrastorage.org/webt/aq/1w/wo/aq1wwopzjhbmihs8mxnmmkcxoma.jpeg)
5) DbgBreakPoint and DbgUiRemoteBreakin
These functions are modified to prevent the debugger from connecting to the process.
![](https://habrastorage.org/webt/aw/we/qd/awweqdnasj4ztgfjk1bdv-lcfw4.jpeg)
Technics
| A comment
|
GetTickCount + Sleep
| Checking Timestamps
|
SetErrorMode
| Checking the function is working correctly
|
SetLastError
| Checking the function is working correctly
|
GetCursorPos
| Check cursor movement
|
Dbgbreakpoint
| Modification of the function to prevent debugger attachment
|
DbgUiRemoteBreakin
| Modification of the function to prevent debugger attachment
|
Hook deletion
| The first 5 bytes of functions are restored in ntdll.dll in case there are hooks
|
NtSetInformationThread
| Parameter 0x11 (ThreadHideFromDebugger)
|
GetThreadContext + check DR
| Debug registers DR0-DR3, DR6, DR7 are checked.
|
Check breakpoints
| The instructions INT3 (0xCC), int 3 (0xCD 0x03) and ud2 (0x0F 0x0B) at the beginning of some functions are checked
|
cpuid (EAX = 0x0)
| Registers EAX, ECX, EDX are checked
|
cpuid (EAX = 0x40000000)
| Registers EAX, ECX, EDX are checked
|
cpuid (EAX = 0x1)
| 31st ECX bit checked
|
PEB (BeingDebugged)
| Checks value 0x1
|
PEB (NtGlobalFlag)
| Checked value 0x70
|
NtQueryInformationProcess
| Called with the flags ProcessDebugPort (0x7), ProcessDebugFlags (0x1F), ProcessDebugObjectHandle (0x1E)
|
Process name check
| The strings “sample”, “sandbox”, “virus”, “malware”, “self.” Are checked
|
If all the techniques of stage 2 are completed, the command line is checked for compliance with the special format. If the verification fails, the following actions are performed:
1) The CreateProcess function is called with the CREATE_SUSPENDED flag to restart the current process. In this case, the command line has the required format.
2) Using the GetContextThread and SetContextThread functions, the entry point is changed to a new one, which is located in the Stage 1 code.
3) Repeat steps 1 and 2 (including a long cycle and all checks). This time, the command line check is successful and the process proceeds to the next step.
3 stage
At this stage, the body of the main virus is decrypted and the Process Hollowing technique is performed on the current process, after which control is transferred to the entry point of the main virus.
Lesson learneded
We cannot say for sure that in this case it causes problems for a particular sandbox, but I want to believe that the ability to use the malware described in the article has long been provided by vendors, and the problem lies only in the long time delay at the first stage of the packer’s work .
Despite the fact that modern sandboxes are for the most part positioned as part of protection systems against APT attacks, our observations suggest that even malicious families well known to the community penetrate the infrastructure with enviable constancy. Since there are no guarantees that the sample that bypassed the sandbox will not have a couple of antivirus bypass techniques in its arsenal, you cannot rely only on this bunch of protective solutions. In such cases, a properly constructed monitoring process, including information security events from end hosts, can ensure timely response and minimize potential damage.