In-Memory Evasion

Take the File Away

On-disk evasion fights the file engine. In-memory evasion refuses the fight.

The idea: never write the payload to disk at all. Build it and run it entirely in memory. You can’t scan a file that was never created, so the most aggressive engine in the AV has nothing to do.

This is where modern malware lives, and it’s the more powerful of the two families.


Process Injection

The signature in-memory technique is process injection: smuggle your shellcode into a legitimate process and run it from there.


The classic version is a four-step dance using Windows APIs:

  1. OpenProcess gets a handle to a process you’re allowed to touch
  2. VirtualAllocEx carves out a fresh block of memory inside that process
  3. WriteProcessMemory copies your shellcode into it
  4. CreateRemoteThread runs it

Your code now executes inside a process the AV trusts. There’s no malicious file on disk, and the running code wears a legitimate process’s name.


There are stealthier variants of the same idea:

TechniqueThe trick
Reflective DLL injectionLoad a DLL straight from memory (normal loading only works from disk)
Process hollowingStart a legit process suspended, gut its code, swap in yours, resume it
Inline hookingPatch a function in memory so it detours through your code first

Inline hooking is a favorite of rootkits, the stealthiest malware. They patch system components in user space, the kernel, or even lower, which is why they need admin privileges to install.


Rename and Walk Past

Here’s how trivially signature detection can break, even for an in-memory technique.

A common move is to run the injection from a PowerShell script instead of a compiled binary. Why? A script is just interpreted text. It has no rigid executable structure to fingerprint, and if AV flags it, you can change it and rerun without recompiling anything.

The script imports VirtualAlloc, CreateThread, and memset, allocates memory, writes the shellcode in, and runs it, all inside the current PowerShell process.


But the first version often gets caught anyway. Scanned against many AV products, a textbook injection script might be flagged by roughly half of them.

Why? Because to catch malicious scripts, AV relies on static string signatures: it matches meaningful names in the code, like the class name and the variable names.


The fix is almost insultingly simple. Rename them to something generic:

OriginalRenamed
Win32iWin32
$sc$var1
$winFunc$var2

Rescan, and the script comes back clean. The signature was matching on names, and you changed the names.

The signature matched the labels, not the behavior. Nothing about what the script does changed. This is the whole game in miniature: AV recognizes what it has seen, so make it look unseen.


One operational gotcha: PowerShell’s Execution Policy may block the script first (“running scripts is disabled on this system”). It’s a per-user setting, not a security boundary:

Set-ExecutionPolicy Unrestricted -Scope CurrentUser

Or sidestep it per-run with -ExecutionPolicy Bypass. Note that Active Directory Group Policy can lock this down harder.


The Arms Race

Step back and the whole field is one feedback loop:

  • Vendors build signatures from samples they collect
  • Attackers make their code novel so there’s no sample to match
  • Vendors counter with heuristics, sandboxes, and ML that don’t need an exact match
  • Attackers counter with in-memory execution and legitimate-process disguises

Each side forces the other to get more sophisticated.

AV recognizes what it has already seen. That one fact is both the weakness you exploit and the reason evasion is never permanently solved. Today’s clean payload is tomorrow’s signature.


Practice Boxes