Malware Analysis in 5 Minutes: Identifying Evasion and Guardrail Techniques with CAPA
Modern malware has gotten better and better at detecting sandbox and analysis environments, and at evading these environments. Malware can circumvent defenses, sandboxes, and analysts by using various techniques such as VM detection, process injection, and guardrails.
In particular, guardrails are one or more artifacts that malware looks for on the host before executing its payload. These artifacts may be specific registry keys, files, directories, network configurations, etc. If these specific artifacts do not exist on the host, the malware may assume it is running in an analysis lab, or is otherwise not the right target for infection.
One of the most tedious processes when investigating malware that is evading your sandboxes or tooling is figuring out what techniques the malware is using for this, and where in the code this occurs. CAPA can help automate this process.
CAPA is a tool written by the FireEye/Mandiant FLARE team that can be used to quickly triage and assess capabilities of a malware sample.
For this example, I have a sample that will not run in my sandboxes or in my analysis VM’s and I am trying to figure out why. Let’s throw this sample into CAPA:
capa path/to/sample.exe
CAPA provides a nice summary of the potential ATT&CK techniques the malware is using, along with its identified capabilities. This assessment can help in many malware analysis situations, but here the focus is on evasion techniques.
Based on this initial analysis, we can see several possible techniques being used, such as:
- Executing anti-VM instructions
- Hashing and data encoding (could be used to hide strings)
- Checking if a certain file exists (could be used for creating guardrails)
- Getting the hostname (could also be used for guardrails)
- Multiple process injection techniques
We can get additional information from CAPA by using the verbose mode:
capa path/to/sample.exe -vvv
Now we can focus on a few of these techniques and where they reside in code:
CAPA identified two uses of the CPUID instruction, which can be used to identify a virtual machine environment. We can now throw this sample into a disassembler and locate this code by jumping to the addresses listed in CAPA:
If we wanted to bypass this detection technique, we could NOP out (remove) the CPUID instructions, or modify their return values. More about the CPUID instruction can be seen here and here.
Additionally, CAPA identified the addresses in the binary where process injection behaviors may be occurring:
With this information, along with the offset addresses provided, we can set breakpoints on these addresses or instructions for analysis in a debugger. For more info on these process injection techniques, this write-up is old but still very relevant.
Finally, I suspect this sample is using some sort of guardrails. Guardrails are a technique used by malware to prevent sandbox analysis, hamper manual analysis, evade host defenses, and prevent unnecessary “spreading” of the malware.
As previously identified by CAPA, this sample may be using the system hostname and files/directories as guardrails. It also likely that it has hardcoded hashes of those guardrails in order to make it difficult for analysts to spot what the malware is specifically looking for:
CAPA identified that this sample is checking for a specific file at function offset 0x1400012C1, and the hostname at 0x140001020. Let’s inspect the hostname query in the sample in a dissembler. Once Ghidra disassembles this function, this is what is displayed:
In Ghidra, we can see that the sample is calling GetComputerNameA in order to get the domain hostname of the victim. It then hashes this hostname (CryptCreateHash, CryptHashData) and compares it to a hardcoded hash using memcmp (memory compare).
This instruction is comparing the DAT_target_hash (the hash of the hostname that the malware is expecting) to hashed_domain_name (the actual hostname of the victim). If these hashes do not match, the sample will terminate itself.
Since the target hash is hardcoded in the binary and will not be “un-hashed” in memory, we don’t really know what this malware sample is looking for. Our best option here is to bruteforce the hash using a rainbow table or wordlist.
Or… we can simply bypass this hash checking functionality altogether. With this information from CAPA, we can now patch the binary (in a disassembler or in a debugger) in order to completely bypass these VM detection and guardrail techniques, and allow our sample to run in our VM. We can do this by NOP’ing out instructions, modifying the function return values, or skipping the code altogether by jumping over the suspect code.
Happy reversing!