The antivirus is a useful tool in the prevention, detection and removal of malicious processes within the system, with additional objectives of preventing the spread of malicious elements and the protection of the storage system.
Given that this type of software is evolving, adapting to different types of threats and providing additional functions, there is a wide variety of options.
One such option is EDR (Endpoint Detection and Response), which aims to identify, detect and prevent advanced threats (APTs) by providing continuous monitoring and analysis of the endpoint and the network.
While these systems often facilitate threat management and allow for network-level actions, threat detection still uses engine-based methods, which will determine the number of threats they will be able to detect.
There are different types or methods on which antiviruses are based:
- Signature or static detection: searching for matches in a signature database (patterns created to detect a certain sequence of bytes) that is stored in the computer itself or in a system located in the same network as the computer we want to analyse. In general, each manufacturer is responsible for adding and updating the signatures in its database, which is why malware may be detected by some manufacturers and not by others. The main problem with these antiviruses is that it is possible to evade protection by using completely new malware or by modifying parts of existing malware. Moreover, if databases are not up to date, it is easier to carry out this type of attack.
- Sandbox or dynamic execution detection: by using a controlled and process-constrained environment, the antivirus is able to execute software by detecting its malicious actions.
- Heuristic: a technique for detecting malicious payloads by defining some rules and algorithms, so that if the code contains a certain set of code, instructions or executable segments that perform certain actions that could be malicious, the alert is triggered.
- Behaviour-based: this technique analyses the behaviour of the binary file and classifies it into malicious and non-malicious. For example, a file containing a reverse shell (a process that tries to connect to an attacking machine by providing an interactive shell) could be detected if the antivirus detects that this is normally malicious behaviour, regardless of whether the malicious file has associated signatures. There is a general problem with this type of antivirus, which is the rate of false positives, i.e., detections of legitimate applications as malware. This increases the burden of managing and reviewing these alerts.
It is also worth mentioning the file or code unpacking functionality, which is present in many antiviruses and makes it possible to scan the contents of compressed files, or even the contents of disk drives in virtual machines or ISO files. An ISO file allows a file system to be stored in a single file. It is named after the ISO 9660 or 13346 standards.
Evasion techniques consist of applying certain changes to malicious code to evade antivirus protection. They can be classified according to what and how these changes are made:
- Disk-resident malware: whose evasion techniques are based on modifying the files stored on the victim machine.
- Memory-resident malware: which works at the memory level, without needing to be stored on disk.
It should be noted that evading an antivirus will most likely require a combination of several techniques, as antiviruses are capable of detecting malicious behaviour in several ways.
Obfuscation is a technique that consists of hiding malicious code in the legitimate code of the process. If we have a code that is detected by antiviruses, because there is a signature for it, we could apply a number of changes, such as reordering code, adding dead code or changing the semantics of existing instructions, to change its signature and make it harder to detect.
Obfuscation is especially useful for bypassing signature-based antiviruses but would not work with behaviour-based antiviruses.
There are many open-source tools to modify payloads (part of the malware code that performs the malicious action on the system) and evade antiviruses. Next, we will explain some of the tools that are commonly used. These tools do not work to bypass many of the current antiviruses, as they also identify re-encryption variants.
- Msfvenom is a Linux framework that combines a payload library and an encoder library, allowing you to generate an obfuscated payload directly.
- Veil is a Linux tool for generating obfuscated metasploit payloads (an open-source framework with a set of tools for exploiting vulnerabilities). Other tools similar to Veil may include GreatSCT, Unicorn, Shelter, etc.
- Py2Exe is a Python extension that converts Python scripts into executable Windows programs, capable of running without the need for a Python installation. This tool works very well to bypass antiviruses on a Windows machine. In addition, it can be used together with Msfvenom to convert a payload generated with some encoder into a Windows executable.
- Invoke-Obfuscation is a Powershell script obfuscator.
It is also worth mentioning the existence of several scripts that allow bypassing the security of most versions of Windows Defender using obfuscation:
- Hoaxshell: a script that allows to obtain an obfuscated reverse shell
- Mimikatz Ofuscator: a script to obfuscate the Mimikatz tool (credential stealing).
Knowing the type of tools used will make it easier to detect them in the system, for example, by comparing hashes or using tools in addition to the antivirus software itself.
It is advisable to update our antiviruses and signature databases and to use a mixed antivirus that uses signatures but also checks for anomalous behaviour.
The use of Yara rules is not effective, considering that just by changing one part of the chain to be detected, the system would no longer detect the threat. Therefore, it is advisable to use them as an additional layer of protection, always in combination with other tools.
This technique involves cryptographically modifying the code of the program or executable, also creating a function or sub-process for decryption that is hidden during transmission, making the encrypted program undetectable by the antivirus.
Subsequently, the code will be decrypted in memory, leaving the malicious code executable on disk, so that the antivirus would not be able to remove it before executing it.
This type of technique has two sub-techniques: oligomorphic coding, where the malware uses several decryptors using a different one each time it runs on the system, and polymorphic coding, where the malware uses more sophisticated systems to choose a decryptor to load and check that the encrypted code actually matches the decryption it will use.
Nowadays, packers not only reduce the size of the executable, but also create a completely new binary structure for the file. This sometimes makes it possible to bypass these engines.
Most unpacking techniques use numerous self-injection techniques that inject a shellcode or blob into a predefined region of memory, thus transferring execution to the injected code and then overwriting its own process.
These protections, which were designed to prevent reversing, debugging, and testing of code in emulation processes, can also be used to fool antiviruses by creating a payload under the protectors and sending it to the victim.
In-memory process injection
By making use of Windows API handles for processes that are already running or where execution permissions are held, it is possible to create threads in memory that will load and run automatically, bypassing antiviruses.
Using the OpenProcess() function, we will open one of these processes and allocate memory to it using VirtualAllocEx() and then write into it using WriteProcessMemory(). The next step will be to obtain the handle, GetModuleHandle(), and the process address, GetProcessAddress(), with which we will be able to create our own remote thread in memory, using CreateRemoteThread().
-Creating Remote Thread into another Process (Victim Process). Source-
This method can be detected by identifying the use of certain Windows API calls, such as CreateRemoteThread, SuspendThread/SetThreadContext/ResumeThread or QueueUserAPC/NtQueueApcThread, and others that can be used to modify memory within another process, such as VirtualAllocEx/WriteProcessMemory.
This method is identical to in-memory process injection. Here we inject the DLL into memory and execute it. This method is not the same as injecting the DLL into disk and calling it via LoadLibrary().
The way to mitigate it is the same as for memory injection attacks, i.e., by detecting the calls that are used to carry it out.
Interception of function calls
This method is based on creating a subroutine within a legitimate function, basically adding code and changing the course of the execution flow, so that during the execution of the legitimate function the malicious code is also executed unnoticed by the antivirus.
Replacement of legitimate processes
This technique consists of replacing legitimate processes in a suspended state with duplicate processes containing the malicious code and then resuming the suspended process, leading to the execution of arbitrary code on the system. In order to replace the process, it will be necessary to determine the address of the legitimate process via PEB.imageBaseAddress.
The most effective way to prevent this is by detecting parent-child kinship by comparing PEB and VAD structures or by detecting suspicious memory protections.
At this point, how can we prevent attackers from evading our antivirus?
There is no completely effective way, we must have a robust configuration of our systems and networks, as well as be aware of all the techniques used by attackers to try to prevent, detect and respond to them appropriately.
As general protective measures, applicable to all operating systems, it is recommended:
- Updating our systems and components: most system or application updates fix security flaws or vulnerabilities that can be exploited by attackers. Therefore, having up-to-date equipment will prevent the successful exploitation of known vulnerabilities.
- Whitelists of legitimate programs and libraries that can be installed on computers: having a list of resources that can be installed on computers protects us from any attacker installing their malware, because the computer's configuration would prevent them from doing so.
- Preventing execution: it is necessary to have control over the execution of processes. In many cases, this feature is built into the EDRs. Otherwise, external tools can be used, or it can be done with the permissions management of the equipment.
- Event detection: using system monitoring tools, such as Windows Sysinternals' Sysmon, to provide detailed information on process creation, network connections and changes in file creation time. By collecting the events it generates, using event collection tools or SIEM agents, and then analysing them, it is possible to identify malicious or anomalous activity and understand how intruders and malware operate in the network.
- Static detection: Yara can be used for static and dynamic analysis or even for process injection detection. This tool enables the identification and classification of malware samples and the definition of indicators of compromise (IOCs).
It can be concluded that antiviruses are necessary security measures, but they do not, per se, guarantee total protection of computers. As we have seen, there are a number of ways to evade these antiviruses and execute malicious code. Therefore, it will be necessary to implement additional basic mechanisms such as awareness raising, perimeter security and access control. This makes it difficult for an attacker to gain access to the computers, but even if they do gain access, having them up to date and with the appropriate permissions increases the complexity of completing a successful evasion of the antivirus system.