A technical look at a sandbox evading malware
Introduction
It's an endless war between malware writers and hunters very much like a cat and mouse game.Constantly we researchers trying to come up with techniques and ways to automate the process of investigating,examining malware to recover as quickly as possible from a malware attack incident,this gave a birth to variety of techniques.
Detonating malware in a sandbox and watching what happens as the malware executes is one of those ways to get an initial assessment/insight into the malware capabilities.Many of the publicly available sandbox solutions out there still heavily relying on a heavily monitored technique called user-mode hooks to watch for what APIs the malware invokes.
In this article we will be taking a look at #PLAY ransomware which has in it functionality to detect user-mode hooks and explain as we go how malware detects user-mode hooks.
Identifying Hooks
Work Flow
First the malware is obtaining a pseudo handle to itself using GetCurrentProcess .Process pseudo handle is nothing more than a special constant that as of now can be calculated as (HANDLE)-1,that handle will be used in later function calls to reference the malware process.
The returned handle value was passed along with var_121C(array pointer to receive handle values) as arguments to a wrapper function which internally calls the EnumProcessModules which retrieves a handle for each module in the process memory.
Having obtained handles for each module in the process memory, malware invokes check_for_userland_hooks function that will iterate through each of the module's exports to check for hooks.
Let's head into this function
malware initially is going to obtain the path of the module of concern , then reads the module name and moves it into a buffer , then opens a handle with read access mask , having the handle value we get the file size then allocate process memory equal to the file size before lastly we read the file in memory to parse.
Now having loaded the module , let's dissect how the malware is walking the module to get to exports.
I have commented and annotated the code as much as possible , first we see the return value of VirtualAlloc_wrapper function (which was responsible for allocating process memory so we can read the file in) has been assigned to base,then added to that 0x3c(60 in decimal) to get to the NT headers of the module , then added to that 0x18 which is the size of the COFF header to get to IMAGE_OPTIONAL_HEADER
Then we're checking IMAGE_OPTIONAL_HEADER.Magic which is an indication of whether that's a 32-bit or 64-bit binary.In may case we are checking if that's equal to 0x10B (checking if it's 32-bit) if so v16 is assigned 0x78 (will be used later to get to the exports directory struct ).
Following We see a function sub_401380 with many calls to. What's in common between these calls is it takes in always the module's base as an argument however the other one is different for each of the calls.
领英推荐
The v16 which was set earlier is used in the first call.
I kind of like went through these function dynamically seeing the return value for each.
Internally this function is walking the module's headers the same way we explained earlier but for a different other argument they return different things.
For the the first function call , the other argument turned out to be the absolute address of where to find the exports structure RVA.
We can see when opening ntdll.dll in PE-bear that at an offset of 0x168 is a pointer to the exports directory structure of the module.
The return value however is the beginning of the structure.
For the second call to the function the other argument is the AddressofNames RVA (RVA to an array of DWORD RVAs to function names exported by the dll).
The return value if the beginning of the DWORD RVAs AddressOfNames
So the pattern is that function sub_401380 takes in an address along with base and reads the DWORD value at this address , the same way the last call takes the AddressofNameOrdianls RVA (RVA to array of WORD sized ordinal values) along with base and returns back the beginning of the array of ordinals
Now to the part where malware is walking iteratively the exports of the module and checking for function hooks.
The malware sets up an infinite loop that will walk the exports of the module checking to see if either of the functions is hooked .
We can see that the same function sub_401380 used earlier is used here to get the exported function name that will be then used in GetProcAddress to resolve the exported function address , then checking if the function at this address starts with 0xE9 which is the opcode of the relative unconditional JMP or 0xFF which perhaps is the call instruction opcode.
You see in case we resolved the function address and checked the first byte of the exported function and turned out to be not hooked then we go somewhere where we increment our loop and continue to iterate through the rest of the exports
Conclusion
Malware evasion techniques are getting more complex overtime , here we have investigated the methodology of how malware can detect that it's under surveillance of the analyst and perhaps exits or do something else in that case .