Bypass AM PPL
Bypass AM PPL
2022
How to bypass AM-PPL (Antimalware Protected Process
Light) and disable EDRs - a Red Teamer's story
Juan Sacco
Stephen Kho
Avast Confidential
Agenda
1. Who we are?
2. Endpoint security evolution (so far)
3. How EDR/AVs work?
4. 2022 EDR/AV bypass techniques
5. AM-PPL bypass research
6. Bypassing AM-PPL
7. Chain of attack and timeline
8. What can you do about it?
9. Q&A
Avast Confidential
Who we are
• $ whoami : Stephen Kho <[email protected]> – Team Lead Avast Red Team
• $ whoami : Juan Sacco <[email protected]> – Co Team Lead Avast Red Team
Avast Confidential
Endpoint security evolution (so far)
Heuristic AV EDR (Endpoint Detection and Response)
• 1987 McAfee, Inc. released VirusScan • 2013 Term coined by Anton Chuvakin from Gartner
• First heuristic AV released - FlushShot Plus and Anti4us • Real-time continuous monitoring and collection of endpoint data
• 1988 Avira release AntiVir (Luke Filewalker) • Machine learning and behavior analysis to evaluate system
• 1988 Avast was founded and released Avast Antivirus and events and identify anomalies
SecureLine VPN ○ VMware Carbon Black
○ Crowdstrike Falcon
○ Microsoft Defender for Endpoint
• Windows NT 3.1 (1993) first to feature user mode and kernel mode
• The kernel provides the foundation for the executive and the subsystems.
All code that runs in kernel mode shares a single virtual address space but
only drivers that have been sent to Microsoft for signing will load into the
Windows kernel.
• Less BSODs! Avast Confidential
• Userland
• processthreadsapi.h
1. Call function in NTDLL • Win32 API
CreateRemoteThread
Avast Confidential
How EDR/AVs work? – Windows API hooking/Userland hooking
SYSCALL
NtCreateThreadEx functions
• Userland
• Userland
• NTDLL.dll • Check • Kernel
• processthreadsapi.h
parameters mode
CreateRemote EDR/AV
Thread functions
Avast Confidential
2022 EDR/AV bypass techniques
Avast Confidential
First line of defense: Signature detection
It’s the process of analyzing the signatures of files for known malware
previously identified. Tipically implemented at kernel level using file system
filters. Files get scanned at opening phase, and if a signature is triggered the
filter driver blocks the access.
While most of the sandboxes uses CFG analysis, meaning the recompilation of
binaries or other small changes will still produce the same CFG regardless of
the executable having a partial or complete different signature.
As shown below “aswhook.dll” coming from the AV, will be most likely
monitoring Windows API Calls. If a program loads a function from
kernel32.dll a copy of this dll is placed into memory. Then the AV can
manipulate the in memory copy at will, hooking into it, using a trampolin
function to control the flow of the hooked API native call. This technique is
called Userland-Hooking.
Patching the patch
When the in-memory copy of Kernel32.dll or NTDLL.dll is loaded into memory
tipically EDR/AVs will patch some of the functions using trampolin hooks placing
a JMP or similar at the beginning of the code to redirect the Windows API
function to some inspecting code controlled by the EDR/AV itself.
If the analysis outcome is positive (or bad in our case) the execution continues, if
not the execution is flagged and the API call gets blocked.
Unhooking
To be able to unhook, or restore the hooked functions we need to know how it
looked like before it got modified. This can be achieved by comparing the
function definitions in the DLL on the disk with their definitions on memory.
Direct system calls access:
The main goal of this technique is to bypass Userland-Hooking by not loading
any function from ntdll.dll during runtime. But instead calling directly the
corresponding assembler code ( obtained previously from a dissasembly of
the ntdll.dll ) in-line from your program itself.
ZwWriteVirtualMemory80 proc
mov r10, rcx
mov eax, 38h
syscall
ret
ZwWriteVirtualMemory80 endp
Using this technique will bypass Userland-Hooking and the EDR/Avs will not
see any Windows API function at all. No imports and no patches or hooks.
SysWhispers ( Direct Access but Next-Gen ):
In a nutshell, it helps with evasion by generating custom headers/ASM file
implants to make the usage of direct system calls easier. So, with a tool, not
more manual disassembly. And yes, works on Visual Studio ;-)
P/Invoke & D/Invoke
Platform Invoke allows .NET applications to access data and APIs in
unmanaged DLLS. By using P/Invoke you may make calls to the standard
Windows APIs allowing a malicious program to perform post-exploitation
on-memory without droping files to disk. In a nutshell you can access structs,
callbacks and functions in unmanaged libraries from your managed code.
But all references get an entry in the .NET assembly Import Table. This static
reference, from the perspective of your program, will get you caught. Tipically
EDR/Avs will inspect the IAT of the running programs to learn about their
behavior. And so is born.. D/Invoke
In a nutshell, if we first learn the offset and call directly the function we can
make those references at runtime using a pointer to its location.
// NtWriteVirtualMemory
stub = Generic.GetSyscallStub("NtWriteVirtualMemory");
NtWriteVirtualMemory ntWriteVirtualMemory = (NtWriteVirtualMemory)
Marshal.GetDelegateForFunctionPointer(stub, typeof(NtWriteVirtualMemory));
uint bytesWritten = 0;
result = ntWriteVirtualMemory(
hProcess,
baseAddress,
buffer,
(uint)_shellcode.Length,
ref bytesWritten);
Unhooking the Hookers
It’s possible to completly unhook a hooked DLL loaded in memory by reading
the .text section and overwriting the .text section mapped into memory.
Mapping a copy of, on this example, NTDLL.DLL from disk into memory, then
get the NTDLL.DLL base address, find the offset to the .text section Vadress.
Then simply copy the .text section into the hooked DLL and apply the original
memory protections set to NTDLL by the EDR/AV.
Direct Entry Point Patching
Using Windows Debug API to listen for LOAD_DLL_DEBUG_EVENTS it’s
possible to patch the EntryPoint of the injected DLL attempt and return only
TRUE instead of actually attaching the DLL into the process, avoiding
User-Land Hooks all together.
BEFORE
AFTER
What is PPL?
The Protected Process Light (PPL) is a technology that has been
implemented since Windows 8.1>, and it’s used to protect specific
critical processes. These processes should have an internal or external
signature to meet the Windows requirements.
● Process termination
● Access to virtual memory
● Debugging
● Copying of descriptors
● Access to memory
● Thread interaction
● Token impersonation
ACCESS DENIED. Trying to interact with an
unprotected process even as NT/System.
PPL Processes - The basics
PPL effectively prevents an unprotected process from accessing
protected processes with extended access rights.
“Object Manager directories are unrelated to normal file directories. The directories are created
and manipulated using a separate set of system calls such as NtCreateDirectoryObject rather
than NtCreateFile. Even though they’re not file directories they’re vulnerable to many of the
same classes of issues as you’d find on a file system including privileged creation and symbolic
link planting attacks.”
Source: https://googleprojectzero.blogspot.com/2018/08/windows-exploitation-tricks-exploiting.html
Proof of concept: https://bugs.chromium.org/p/project-zero/issues/detail?id=1550#c5
How the exploit works:
DLLs are only verified when the file is mapped. When a Section is created. This means that, if
you are able to add an arbitrary entry to the \KnownDlls directory, you can then inject an
arbitrary DLL and execute unsigned code into a PPL protected process.
Restriction: Only protected processes that have a level higher than or equal to WinTcb can
request write access to this directory.
We needed to use GLOBALROOT\KnownDlls\FOO.dll as the device name. The target path of this
device is the location of the DLL. The service creates the symbolic link \KnownDlls\FOO.dll with a
target path we control.
The target must be a Section Object, rather than the DLL file path
Phantom DLL hollowing:
Once we have the symbolic link pointing to our DLL from the KnownDLL
objects, if a program loads a DLL named FOO.dll and the Section object
\KnownDlls\FOO.dll exists, then the loader will use this image rather than
mapping the file again.
The essence of phantom DLL hollowing is that an attacker can open a TxF
handle to a Microsoft signed DLL file on disk, infect its .text section with his
shellcode, and then generate a phantom section from this malware-implanted
image and map a view of it to the address space of a process of his choice.
The file object underlying the mapping will still point back to the legitimate
Microsoft signed DLL on disk (which has not changed) however the view in
memory will contain his shellcode hidden in its .text section with +RX
permissions.
Source: https://www.forrest-orr.net/post/malicious-memory-artifacts-part-i-dll-hollowing
Exploit #2 .NETProfiler
We have “debug” and “impersonate” privileges, so we can list the current processes, find one
that runs as LOCAL SERVICE, duplicate the primary token and temporarily impersonate this
user. But we needed Administrator rights to begin with.
.NET can be coerced into loading a profiling DLL into any .NET assembly when launched. This is
done when a handful of environment variables and registry keys are set.
COR_ENABLE_PROFILING=1
COR_PROFILER={GUID}
COR_PROFILER_PATH=C:\path\to\some.dll
And in order to make it work you can hook your custom DLL:
REG ADD "HKCU\Software\Classes\CLSID\{FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF}\InprocServer32" /ve /t REG_EXPAND_SZ
/d "C:\Temp\test.dll" /f
REG ADD "HKCU\Environment" /v "COR_PROFILER" /t REG_SZ /d "{FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF}" /f
REG ADD "HKCU\Environment" /v "COR_ENABLE_PROFILING" /t REG_SZ /d "1" /f
REG ADD "HKCU\Environment" /v "COR_PROFILER_PATH" /t REG_SZ /d "C:\Temp\test.dll" /f
.NET Profiler
Tsk Scheduler
Execution
.NET Profiler
Tsk Scheduler
Start execution to get System
Target machine
Microsoft Servicing Criteria for MS Windows
The criteria used by Microsoft when evaluating whether to provide a security update or guidance for a
reported vulnerability. Even a non-admin to PPL bypass is not a serviceable issue.
Source: https://www.microsoft.com/en-us/msrc/windows-security-servicing-criteria?rtc=1
Credits & PoC ( Github ):
Download the PoC: https://github.com/jsacco/PPL_Bypass/tree/main
To all the work and research done by James Forshaw from Project Zero:
https://googleprojectzero.blogspot.com/2018/08/windows-exploitation-tricks-exploiting.html
For making publicly available an implementation of NT/System token impersonation, thanks! FULLSHADE
https://github.com/FULLSHADE/Auto-Elevate
Thanks to:
Avast Red Team for the technical feedback !
$ questions /? > /dev/null 2>&1