Aerosol Posted December 7, 2014 Report Posted December 7, 2014 IntroductionIn this tutorial we’ll take a look at a Pafish tool, which performs anti debugger/vm/sandbox tricks to detect whether the malware is being executed in a debugger, in a virtual machine or in a sandbox.Malware analysis today depends on a great deal of factors, but we’re often using a virtual machine in order to analyze malware: this is because virtual machines are easy to reinstall and configure. There are a lot of options regarding networking, where we can use host-only, internal, NAT or bridged networking that enables virtual machines to have full, partial or none access to the network. One great feature of virtual machines is that they provide snapshots where we can create a snapshot, install malware and infect the whole system, and later revert the snapshot to restore the system to the old state (without malware infection). This happens in a matter of minutes, but imagine how long it would take to reinstall a system or restore from the last image when a physical host is involved. Malware is often also executed in a sandbox, which is how most of the online scanning solutions are analyzing malware. Additionally, we’re also using different debuggers to analyse malware samples to figure out their internals.All those techniques greatly speed up malware analysis, which is why authors are thinking of ways to detect when malware is being executed under such environment/conditions in order to make the analysis more difficult. When malware detects that it’s being executed under a debugger/vm/sandbox, it can deviate from its original path and do something legitimate or terminate immediately. On the other hand, when malware doesn’t detect it’s being executed under debugger/vm/sandbox, it will run its malicious payload and infect the system.Getting the CodePafish is being developed in wxDev-C++ as it says on its official Github website. First we have to download wxDev-C++ from [11] and click on the “wxDev-C++ Full Installer”, so we will have the full environment installed and won’t have to download additional parts of the installation package afterwards. The installation executable is 117MB large, so the download will take a while.The installation of wxDev-C++ will look as presented on the picture below.After the installation, we have to open the Pafish wxDev-C++ configuration file, which will also initialize the wxDev-C++ when run for the first time (if defaults are accepted). Once we’ve opened the project there will be different source files each used for different detection purposes:Detect a debugger: debuggers.cDetect a sandbox: gensandbox.cDetect hooked functions: hooks.cDetect Sandboxie: sandboxie.cDetect Wine: wine.cDetect VirtualBox: vbox.cDetect VMWare: vmware.cDetect Qemu: qemu.cEach of the outlined source files contains checks used to detect the specific environment. In the next sections we’ll take a look at each of the methods used to detect the environment.Detecting a DebuggerFirst method: the IsDebuggerPresent function is a Win32 API function that can be used to determine whether the calling process is being debugged by a debugger.The CheckRemoteDebuggerPresent function checks whether the process is debugged by a remote debugger, which doesn’t necessarily reside on a separate computer, but is a separate process.The OutputDebugString function sends a string to the debugger for display. If the application is not running under a debugger, the string will be sent to system’s debugger to be displayed with the DbgPrint function. If the application is not running in a debugger and there is no system debugger, then the OutputDebugString does nothing. If the function doesn’t return an error, the process is not being debugged, otherwise it’s running under a debugger.Detecting a SandboxPafish contains four methods to detect the sandbox. The first method is using a quick mouse movement, where the GetCursorPos is used to retrieve the position of the mouse cursor. The GetCursorPos has the following syntax [1], where the lpPoint parameter accepts a pointer to a POINT structure where the screen’s coordinates of the cursor will be saved. The function returns nonzero if it was completed successfully, otherwise it returns zero.Let’s now take a look at the actual detection function as used by Pafish to detect whether the program is running in a sandbox (seen on the picture below). The function first calls the GetCursorPos in order to receive cursor coordinates and saves them into the position1 variable. After that it sleeps for a while and then calls the GetCursorPos for the second time and saves the mouse coordinates into the position2 variable. Afterwards, the x and y coordinates of the mouse cursor are compared to each other, which determines whether the mouse cursor has changed during the last GetCursorPos function call. If the position of the mouse cursor has changed, then there was mouse activity during the sleep function, which means it’s probably running in a simulated environment (most probably in a sandbox). A clear indication of the application running in a sandbox is that a human couldn’t possibly move the mouse in such a short period of time.The second method that’s used by Pafish to detect a debugger is using a GetUserName function that retrieves the name of the user associated with the current thread [2]. The syntax of the function can be seen below, where it’s evident that a function accepts two parameters. The first parameter lpBuffer is a pointer to the buffer where the user’s logon name will be saved. The buffer must be large enough to enable the whole username to be saved to the buffer, otherwise the function will fail. The second parameter lpnSize specifies the size of the lpBuffer buffer, which is overwritten upon the function’s completion – the lpnSize will contain the length of the username copied to the lpBuffer buffer. The function will return a nonzero value when successful, otherwise a zero is returned and a detailed error log can be obtained by calling GetLastError.The code used in Pafish can be seen below, where we’re first reserving a buffer on the stack to hold the username buffer of size 200 bytes and integer number i. After that we’re calling the GetUserName, which will copy the logon username to the username buffer previously allocated. After that all the lowercase letters are changed to their upper-case letters and the name is compared to the following strings: SANDBOX, VIRUS and MALWARE. The strstr function returns a pointer to the first occurrence of the presented strings if found, otherwise it returns NULL. If the SANDBOX, VIRUS or MALWARE strings are found inside the username, the function will return 0, which specifies that the program is being run inside a sandbox. Otherwise 1 is returned, which signifies that the program is not being run in a sandbox: more specifically, that the logon username doesn’t contain the strings SANDBOX, VIRUS or MALWARE.The next method is using GetModuleFileName, which retrieves the fully qualified path for the file that contains the specified module [3]. The function syntax can be seen below. The function accepts three parameters, the hModule, the lpFilename and the nSize. The hModule contains a pointer to the requested module whose path we would like to obtain. If the parameter is NULL (as it is in our case), then the function will retrieve the path of the current executable instead. The lpFilename parameter is a pointer to a buffer, where the module/executable path will be stored; the buffer size must be larger than the size of the returned path if we want the function to succeed. The nSize parameter specifies the size of the lpFilename buffer, which must exceed the length of the returned path.We should also describe the DeviceIoControl function, which sends a control code to the device driver instructing the device to perform a certain action [5]. The function accepts eight parameters: hDevice, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesReturned and lpOverlapped.The hDevice contains a handle to the device on which the action will be executed, which can be a file, a directory, or a stream of a volume (the handle is obtained by previous call to the CreateFile function). The dwIoControlCode specifies the operation to be executed on the device. The lpInBuffer specifies the buffer, which contains the data required to perform the requested operation, but can be set to NULL if the dwIoControlCode doesn’t require any input data (the nInBufferSize contains the size of the input buffer). The lpOutBuffer specifies the buffer where the data of the operation will be written to, while the nOutBufferSize specifies the number size of the buffer. If the function completes successfully, a nonzero return value will be returned.Detecting SandboxieSandboxie is a program that enables us to run a program in a sandbox to prevent malware from making permanent changes to our machine [6]. Sandboxie can easily be downloaded from the official Sandboxie website and installed on our machine. After Sandboxie has been installed, it will start a window like the one below.I won’t go into the details about how Sandboxie works, but let’s just look in the C:\Program Files\Sandboxie\ folder to check what it contains. I’ve specifically highlighted the SbieDll.dll library, which is used by Sandboxie.Detecting VirtualBoxThe code below uses the RegOpenKeyEx function to open the registry key seen on the picture below. If the function finds the specified registry entry, it will return ERROR_SUCCESS, otherwise a value of nonzero will be returned. Afterwards the type and data of “Identifier” registry key is retrieved: the value is stored in the lpData parameter. The retrieved data is then converted to uppercase letters and compared to the VBOX string. The value represents the SCSI disk name, which contains VBOX when the program is running under VirtualBox, otherwise it is not.The method below is actually very similar to the method above, except that we’re checking whether the SystemBiosVersion value contains the string VBOX, in which case the program is running under VirtualBox.The function below is practically the same as the function above, which checks whether the VideoBisVersion contains a string VIRTUALBOX, in which case the program is running in a debugger.The code below checks whether the “SOFTWAREOracleVirtualBox Guest Additions” exists in a registry, in which case the program is running under VirtualBox; otherwise it is not.The code below checks whether the mouse driver for the VirtualBox exists: C:WINDOWSsystem32driversVBoxMouse.sys. If the file exists, the program is running in a VirtualBox.Detecting VMWareThe function below is the same as the one used to detect VirtualBox, but it compares the SCSI hard drive identifier with a string VMWARE. If the string is found inside the identifier, the program is running under VMWare, otherwise it is not.The function below checks whether the “Vmware Tools” registry key exists in a registry, which means the system is running under VMWare.The function below checks whether the driver which enables the shared folders exists in the C:\WINDOWS\system32\drivers\ directory, in which case the operating system is running inside VMWare.Detecting QemuThe function below checks whether the SCSI hard driver identifier contains the word QEMU, in which case the operating system is running inside Qemu.Let’s now check whether the specified registry key exists in the operating system running in Qemu. We’ve run regedit and opened the DEVICEMAP entry, where there is no such field as Scsi, which is being checked by the previous function. Since the Scsi entry doesn’t exist, that Pafish function won’t be able to detect that our Windows operating system is running inside Qemu. It should be noted that the Scsi identifier is available only if SCSI disk is enabled by using the “-drive file=file,if=scsi” option in qemu. Since we’re not using the SCSI interface, that option is not available under the registry and the function above won’t be able to detect Qemu.The next function checks whether the SystemBiosVersion contains the string QEMU, in which case the operating system is running inside Qemu.If we open registry editor and open the HKLM\HARDWARE\Description\System\SystemBiosVersion key, we’ll see the “ACRSYS – 1? value as presented below. Since the value doesn’t contain a substring QEMU, the function above won’t be able to detect Qemu.Now it’s finally the time to run pafish.exe to check whether any of the checks inside Pafish can actually detect whether the code is being executed in debugger/vm/sandbox. When pafish.exe is being run inside Windows 7 running under the Qemu virtual machine, none of the functions will be able to detect it (as we’ve already figured out). The output from running the pafish.exe can be seen on the picture below, where the most interesting part is the Qemu section – this is where the already identified checks are executed, but neither is able to detect that the Qemu virtual machine is used.ConclusionIn this article we’ve presented different methods of checking whether the program is running under a debugger, virtual machine or a sandbox, where we’ve specifically taken a look at each function used to check that.Malware authors today are using the same checks to check whether their malware malicious sample is being executed under a controller environment, in which case the malware will not perform any malicious checks to avoid detection for as long as possible. Malware authors are often using VirtualBox or VMWare virtual machines where the analysis of malware samples is taking place. We’ve seen a number of checks used to detect whether malware is being executed under VirtualBox/VMWare, which need to be bypassed in order perform a complete analysis of the malicious malware sample. Since bypassing all those checks takes a lot of time and knowledge, wouldn’t it be better if we could simplify things? One of the options is using Qemu as virtualization technology, which is a very customizable program; I’m not saying that VirtualBox/VMWare can’t be customized, but it’s far easier to do so with Qemu (especially when wanting to change an option not usually supported by a graphical user interface used by VirtualBox/VMWare).When analyzing a malicious sample we have to remember that any of the above checks can be employed by an attacker to determine whether the malware is being run in a controlled environment, in which case, the malware will most probably terminate its execution. If we suspect that some of the above checks are being used by the malware sample, we can install the appropriate operating system (usually Windows) into Qemu and try to analyze the malware there. That means only that we’ve bypassed the WMWare/VirtualBox/Qemu checks, but if we want to use a debugger, we must also bypass the debugger checks, but that is a story for another time.This short introduction was meant for all malware analysts out there to improve their knowledge about analyzing malicious malware samples. Remember that an attacker can put arbitrary checks into the malware in order to check whether the code is being executed in other environments, like different online malware scanners: VirusTotal, Anubis, etc.When a user receives an executable, he usually submits it to the online malware scanner, which is used to give the first insight into the program’s execution. If the executable was able to detect whether it is being executed in such an environment, incomplete data could be given back to the user as a result of an online malware scan. The user could conclude that the executable is not malicious and execute it, unknowingly installing a backdoor on their own system. This is particularly useful for spreading malware among normal users, who are not malware analysis experts. We have to remember that such checks play an important role in malware analysis, and we have to check whether they are contained in an executable to confirm whether the executable is malicious or not. Remember that even if all automatic analysis tools are reporting that an executable is not malicious, that might not necessarily be the case, as we’ve seen in this article. An executable might still be malicious with proper checks in place to deter the analysis systems into flagging the executable as a valid non-malicious executable.References:[1] GetCursorPos function,GetCursorPos function (Windows).[2] GetUserName function,GetUserName function (Windows).[3] GetModuleFileName function,GetModuleFileName function (Windows).[4] CreateFile function,CreateFile function (Windows).[5] DeviceIoControl function,DeviceIoControl function (Windows).[6] Protection from rogue software, spyware and malware is just a click away…,Sandboxie - Sandbox software for application isolation and secure Web browsing.[7] GetModuleHandle function,GetModuleHandle function (Windows).[8] GetProcAddress function,GetProcAddress function (Windows).[9] RegOpenKeyEx function,RegOpenKeyEx function (Windows).[10] Github Pafish,https://github.com/a0rtega/pafish.[11] wxDev-C++ Downloads,Downloads | wxDev-C++.Source Quote