The evasion techniques malware writers use to bypass detection systems – with real malware code examples.

In the ongoing cat-and-mouse game between malware creators and security systems, malware writers employ a variety of evasion techniques to bypass detection. Although defenders increasingly depend on behavioral analysis and AI to combat these tactics, the evasion methods remain challenging to detect.

How malware detection systems work

Malware detection systems—such as antivirus software and endpoint detection and response (EDR) solutions—are at the forefront of defending organizations against cyber threats. Ironically, these very systems are also prime targets for attackers seeking to disable or bypass security controls. To maintain their integrity and effectiveness, modern detection solutions are engineered with robust self-protection mechanisms.

Process and File Protection

A foundational defense for malware detection systems is the protection of their own processes and files. Many solutions deploy kernel-level self-defense drivers that intercept and control access to security-critical resources. This ensures that unauthorized users—or malware with elevated privileges—cannot terminate, modify, or delete essential components. Access controls further restrict interactions to only trusted, signed processes, minimizing the risk of tampering.

Behavioral and Heuristic Analysis

Modern threats are increasingly sophisticated, often employing techniques that evade traditional, signature-based detection. To counter this, security systems utilize heuristic and behavioral analysis, monitoring for suspicious activity that deviates from normal patterns. Machine learning models and anomaly detection algorithms can identify attempts to disable or compromise the detection software, even from previously unknown threats.

Application Allowlisting and Integrity Checks

Another layer of defense is application allowlisting, which ensures that only trusted and verified software can run alongside detection tools. Regular integrity checks verify that critical files and processes remain unaltered, quickly identifying any unauthorized changes that could signal a compromise.

Privilege Separation

Adhering to the principle of least privilege, malware detection software operates with only the permissions required for its functions. This limits the potential impact of any vulnerability. Administrative actions, such as disabling protection, are tightly controlled and often require multi-factor authentication to prevent unauthorized changes.

Isolation and Sandboxing

To analyze potentially malicious files safely, detection systems leverage sandboxing technology. Suspicious code is executed in isolated virtual environments, ensuring that any harmful behavior is contained and cannot impact the host system or the security software itself. Additionally, critical detection components often run in separate, protected memory spaces, making it difficult for malware to interfere with their operation.

Evading malware detection systems

Assuming that all systems have some form of malware defense mechanisms, malware authors must take these protection methods into consideration in an attempt to avoid detection. Unfortunately, they are extremely clever and can employ a wide variety of techniques in this cat-and-mouse game.

Polymorphic and Metamorphic Techniques

Polymorphic and metamorphic techniques alter code structure to avoid signature-based detection.

Polymorphic malware

Polymorphic malware changes its appearance per infection while retaining core functionality. For example, register swapping modifies instructions without altering behavior.

; Original
MOV EAX, 1
ADD EBX, EAX

; Polymorphic variant
MOV ECX, 1
ADD EBX, ECX

It may use encryption to hide its code (often with a different encryption key for each instance) or use subroutine permutation to rearrange functions to obscure code flow.

Metamorphic malware

Metamorphic malware rewrites its own code with each iteration using equivalent instructions. For instance, zeroing the EAX register can be achieved through a variety of methods. Each variant generates unique code while performing identical operations.

MOV EAX, 0       ; Direct assignment
XOR EAX, EAX     ; Self-XOR
SUB EAX, EAX     ; Self-subtraction

It may alter its code with techniques like instruction substitution Instead of MOV EAX, 0, the malware may use XOR EAX, EAX or SUB EAX, EAX), register renaming (MOV EAX, [value] becomes MOV ECX, [value]), code permutation (malware divides its logic into blocks and randomly shuffles them), or even junk code insertion (e.g., adding NOP instructions that serve no purpose). No part of the code will remain the same between generations, in effect, creating a new variant with each compile.

Sandbox Detection

The first thing most malware does is check for analysis environments using various indicators to determine if it is being run in a sandbox that could potentially study its operation or flag its presence as malicious.

Registry key inspection

It may use registry key inspection to identify virtualized systems. The code below checks for a specific sandbox product key.

push offset SubKey       ; "Software\Microsoft\Windows\CurrentVersion"
call RegOpenKeyExA
cmp eax, offset a55274640267306 ; "55274-640-2673064-23950"
jnz terminate           ; Exit if sandbox ID matches

This detects artifacts like default sandbox configurations.

Human interaction checks

It may look for human interaction checks, such as monitoring mouse movements or foreground window activity, to distinguish user environments from automated analysis. Mouse dynamics: Infrequent movement or clicks (e.g., FIN7 malware requires 3+ clicks). Or it may examine the target’s browser history (empty/cached data suggests non-user environments). It may even count processes on the machine (fewer than 50 running processes indicate artificial setups).

Virtualization artifacts (e.g., VMware processes, Hyper-V drivers).

Malware will try to determine if it is present in a VM environment by looking for well-known indicators.

mov eax, 0x40000000  ; Hypervisor CPUID leaf
cpuid
cmp ebx, "KVMK"      ; KVM hypervisor
je sandbox_detected

Common identification strings include VMwareVMware, VBoxVBox, and XenVMMXenVMM and common MAC addresses used for VMware NICs (e.g., 00:0C:29, 00:1C:14) are targeted for identification. Malware knows that failed sensor readings (e.g. CPU temperature) often indicate emulation. And there are common virtualization drivers with names like `vmmouse.sys` (VMware) or `VBoxGuest.sys` (VirtualBox) that can be scanned for.

Get-ItemProperty "HKLM:\SYSTEM\ControlSet001\Control\Class\{4D36E968-E325-11CE-BFC1-08002BE10318}\0000"  
# Checks for "DriverDesc" = "VMware SCSI Controller"[2][5]

Security tools

Simiarly, malware may scan for security tools via DLL name checks (e.g., GetModuleHandle("sbiedll.dll") for Sandboxie). And it may check for analysis utilities like Wireshark (wireshark.exe) or Sysinternals (procmon.exe). Malware commonly checks for security tools by scanning for specific DLL names associated with antivirus, EDR, and analysis software. This technique helps malware evade detection by terminating or altering behavior when security tools are present.

Malware uses Windows API functions like GetModuleHandle() or LoadLibrary() to detect loaded security DLLs.

// Example: Check for CrowdStrike Falcon sensor
if (GetModuleHandleA("csagent.dll") != NULL) {
    exit(0); // Terminate if detected
}

// Check for Carbon Black
if (GetModuleHandleA("carbonblack.dll")) {
    disable_malicious_activity();
}

Or like this:

const char* sec_dlls[] = {"xagt.dll", "edrsensor.dll", "aswamsi.dll"}; // Elastic, EDR, Avast
for (int i = 0; i < 3; i++) {
    if (GetModuleHandleA(sec_dlls[i]) {
        sleep(86400000); // Sleep 24 hours
    }
}

Process and Registry Enumeration

Malware often scans running processes for security services.

Get-Process | Where-Object { $_.Modules.ModuleName -match "edr|av|sensor" }

And checks installation paths via registry:

RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\CrowdStrike\\", ...);

Hardware indicators

There are a variety of hardware indicators that malware authors check to evade sandboxes.

  • Low screen resolution (e.g., 800×600)
  • Memory thresholds: Systems with <4GB RAM trigger suspicion.
  • Storage limits: Disks <64GB suggest artificial environments.
  • CPU core count: Single-core processors are flagged as atypical for modern hardware.
  • Low traffic: High uptime with minimal data transfer flags sandboxes.
  • Decoy C&C servers: Malware connects to fake servers if network patterns seem monitored.

Evasion

If the malware does not believe it is in a sandbox environment or cannot detect the defensive measure, it will rely on a variety of other techniques to avoid detection.

Encryption

Encryption may be used to obfuscate payloads to evade static analysis. Malware often employs AES or custom ciphers to hide malicious code. Encryption is a core technique malware authors use to obfuscate payloads and evade static analysis by security tools. Methods and implementations may include the following:

XOR Encoding

A lightweight method that applies bitwise XOR operations with a key to each byte of the payload. Static analysis tools struggle to identify the original code without the decryption key.

// Simple XOR obfuscation in C
char payload[] = {0x48, 0x65, 0x6C, 0x6C, 0x6F}; // "Hello"
char key = 0xAA;
for (int i = 0; i < sizeof(payload); i++) {
    payload[i] ^= key; // Obfuscates each byte
}

This transforms readable strings into gibberish, bypassing signature-based detection.

AES Encryption

Advanced Encryption Standard (AES) in Cipher Block Chaining (CBC) mode is increasingly used for robust payload protection.

// C# AES decryption (malware example)
byte[] ciphertext = File.ReadAllBytes("payload.enc");
using Aes aes = Aes.Create();
aes.Key = keyBytes; // Hidden in PE overlay
aes.IV = ivBytes;   // Unique per block
ICryptoTransform decryptor = aes.CreateDecryptor();
byte[] decrypted = decryptor.TransformFinalBlock(ciphertext, 0, ciphertext.Length);

String Encryption

Encrypting strings within the code prevents easy identification of sensitive actions or data.

# Original string
sensitive_string = "Delete all files"

# Obfuscated (encrypted) example
import base64
obfuscated = base64.b64encode(sensitive_string.encode()).decode()
print(obfuscated)  # Output: RGV0ZWxldCBhbGwgZmlsZXM=

To use the string, the code must decrypt it at runtime.

Packers

Packers (e.g., UPX) compress executables, requiring a runtime unpacking routine that complicates static inspection. Packers like UPX (Ultimate Packer for eXecutables) compress executable files to reduce their size and obfuscate their content, serving both legitimate and malicious purposes.

How Packers Work

Packers combine three core components into a single executable:

1. Original executable: The uncompressed target program.
2. Compression algorithm: Reduces file size (e.g., UPX uses UCL or LZMA).
3. Decompression stub: A small routine that unpacks the executable in memory at runtime.

When a packed file is executed:

1. The decompression stub loads into memory.
2. It unpacks the compressed executable.
3. Control transfers to the unpacked code’s original entry point (OEP).

upx -o malicious_packed.exe malware.exe

Stegosploit

Stegosploit is a sophisticated malware delivery technique that combines steganography and polyglot files to hide malicious code—typically JavaScript browser exploits—within standard image files such as JPG or PNG. This approach allows attackers to bypass traditional security measures by leveraging the unsuspecting nature of image files.

Steganographic Encoding

Malicious JavaScript code is embedded into the least significant bits (LSB) of an image’s pixel data. This process is known as steganography and ensures that the image’s visual appearance remains unchanged, making detection via visual inspection or traditional antivirus tools difficult.

Polyglot Files

The image file is crafted to function both as a valid image and as an HTML or JavaScript file. When loaded in a browser, the image appears normal, but the embedded code is decoded and executed, triggering the exploit without user interaction.

Exploit Delivery

The exploit is automatically decoded and executed when the image is loaded in a browser. This technique is often used for drive-by attacks, where simply viewing an image on a malicious website can compromise the user’s system.

// Load image into canvas and extract hidden data
var img = new Image();
img.onload = function() {
  var canvas = document.createElement('canvas');
  canvas.width = img.width; canvas.height = img.height;
  var ctx = canvas.getContext('2d');
  ctx.drawImage(img, 0, 0);
  var data = ctx.getImageData(0, 0, img.width, img.height).data;
  var payload = decodeLSB(data); // Custom function to extract exploit
  eval(payload); // Executes the hidden exploit
};
img.src = 'malicious.jpg';

Example: Stegosploit Toolkit and Exploit

A well-known case study involves embedding an Internet Explorer Use-After-Free exploit (CVE-2014-0282) into a JPG image. The exploit code, written in JavaScript, is hidden within the image and automatically executed when the image is loaded in a vulnerable browser. The workflow looks like this:

1. Generate Exploit Code:
The attacker prepares a JavaScript exploit targeting a specific vulnerability (e.g., CVE-2014-0282).
2. Encode Exploit into Image:
Using tools from the Stegosploit toolkit, the exploit code is steganographically encoded into an image file.
3. Create Polyglot Image:
The image is modified to be a valid HTML/JavaScript file as well as an image. This is done by appending or embedding HTML/JavaScript code in specific segments or chunks of the image file (e.g., APP0 segment in JPG, tEXt chunks in PNG).
4. Deliver to Target:
The polyglot image is delivered via email or hosted on a website. When the victim’s browser loads the image, the hidden JavaScript is executed, triggering the exploit.

Example Code Snippet (Conceptual)

Below is a simplified example of how JavaScript code can be embedded and extracted using steganography. Note that real-world Stegosploit uses specialized tools for encoding and polyglot creation.

// Example: Embedding data in LSB of image pixels (simplified)
function encodeLSB(imageData, payload) {
  for (let i = 0; i < payload.length; i++) {
    // Set LSB of each color channel to payload bits
    imageData[i*4] = (imageData[i*4] & 0xFE) | (payload[i] & 0x01);
    // (In practice, more sophisticated encoding is used)
  }
}

// Example: Extracting data from LSB
function decodeLSB(imageData, length) {
  let result = [];
  for (let i = 0; i < length; i++) {
    result.push(imageData[i*4] & 0x01);
  }
  return result;
}

Detection and Mitigation

Stegosploit is challenging to detect because the image appears normal and the exploit code is not present as plain strings. Advanced steganalysis or file sanitization tools are required to identify and remove embedded scripts. Content Disarm and Reconstruction (CDR) technologies can sanitize image files by stripping out embedded scripts, rendering the attack harmless.

Other ways malware hides itself

Control Flow Obfuscation

Altering the logical flow of the code by inserting unnecessary branches, loops, or jumps.

# Original code
if condition:
    do_something()
else:
    do_another_thing()

# Obfuscated control flow
import random
rand = random.randint(0,1)
if (condition and rand) or (not condition and not rand):
    do_something()
else:
    do_another_thing()

This makes code analysis more complex.

Variable and Function Renaming

Replacing meaningful names with meaningless or random ones.

# Original
def delete_files(files):
    for file in files:
        os.remove(file)

# Obfuscated
def a1b2c3(xyz):
    for abc in xyz:
        os.remove(abc)

This confuses analysts but does not change behavior.

Dead Code Insertion

Adding useless code that does nothing.

def main():
    x = 5
    y = x + 1  # Useless calculation
    if False:
        print("This will never run")
    # Actual code here

This increases the complexity of static analysis.

Code Packing and Compression

Using tools like UPX to compress and encrypt executables.

upx -o malware_packed.exe malware.exe

This makes the binary harder to analyze statically.

XOR Obfuscation

Performing bitwise XOR operations with a key.

data = b"malicious_payload"
key = 0xAA
obfuscated = bytes([b ^ key for b in data])

To deobfuscate, apply the same XOR operation again.

Instruction Substitution

Replacing straightforward instructions with equivalent but complex ones.

# Original
x = 10

# Obfuscated
x = 100 - 90

Behavioral Evasion

Similar to how malware may look for signs of human interaction to detect a sandbox, they may use behavioral techniques to evade detection.

Extended sleeps

Extended sleeps (e.g., Sleep(600000) for 10 minutes) might be used to bypass sandbox timeouts.

Delay Execution

Similarly, malware may use system APIs (such as Sleep, NtDelayExecution, or SleepEx on Windows) to pause its execution for extended periods—sometimes minutes or even hours. This causes automated analysis environments to time out before the malware activates its payload. For example:

// Windows example: Sleep for 10 minutes (600,000 milliseconds)
Sleep(600000);

Or, using shell commands:

ping 127.0.0.1 -n 5693 > nul  # Delays for about 94 minutes

Logic bombs

Logic bombs that activate only after specific dates or system uptime thresholds. Malware is programmed to activate only on a specific date, time, or after a certain system uptime. This ensures it does not trigger in analysis environments that simulate a short period, and allows “holes” to close before detonating.

import datetime
if datetime.datetime.now() >= datetime.datetime(2025, 12, 1):
    execute_payload()