CrimsonEDR is an open-source project engineered to identify specific malware patterns, offering a tool for honing skills in circumventing Endpoint Detection and Response (EDR). By leveraging diverse detection methods, it empowers users to deepen their understanding of security evasion tactics.
Detection | Description |
---|---|
Direct Syscall | Detects the usage of direct system calls, often employed by malware to bypass traditional API hooks. |
NTDLL Unhooking | Identifies attempts to unhook functions within the NTDLL library, a common evasion technique. |
AMSI Patch | Detects modifications to the Anti-Malware Scan Interface (AMSI) through byte-level analysis. |
ETW Patch | Detects byte-level alterations to Event Tracing for Windows (ETW), commonly manipulated by malware to evade detection. |
PE Stomping | Identifies instances of PE (Portable Executable) stomping. |
Reflective PE Loading | Detects the reflective loading of PE files, a technique employed by malware to avoid static analysis. |
Unbacked Thread Origin | Identifies threads originating from unbacked memory regions, often indicative of malicious activity. |
Unbacked Thread Start Address | Detects threads with start addresses pointing to unbacked memory, a potential sign of code injection. |
API hooking | Places a hook on the NtWriteVirtualMemory function to monitor memory modifications. |
Custom Pattern Search | Allows users to search for specific patterns provided in a JSON file, facilitating the identification of known malware signatures. |
To get started with CrimsonEDR, follow these steps:
bash sudo apt-get install gcc-mingw-w64-x86-64
bash git clone https://github.com/Helixo32/CrimsonEDR
bash cd CrimsonEDR; chmod +x compile.sh; ./compile.sh
Windows Defender and other antivirus programs may flag the DLL as malicious due to its content containing bytes used to verify if the AMSI has been patched. Please ensure to whitelist the DLL or disable your antivirus temporarily when using CrimsonEDR to avoid any interruptions.
To use CrimsonEDR, follow these steps:
ioc.json
file is placed in the current directory from which the executable being monitored is launched. For example, if you launch your executable to monitor from C:\Users\admin\
, the DLL will look for ioc.json
in C:\Users\admin\ioc.json
. Currently, ioc.json
contains patterns related to msfvenom
. You can easily add your own in the following format:{
"IOC": [
["0x03", "0x4c", "0x24", "0x08", "0x45", "0x39", "0xd1", "0x75"],
["0xf1", "0x4c", "0x03", "0x4c", "0x24", "0x08", "0x45", "0x39"],
["0x58", "0x44", "0x8b", "0x40", "0x24", "0x49", "0x01", "0xd0"],
["0x66", "0x41", "0x8b", "0x0c", "0x48", "0x44", "0x8b", "0x40"],
["0x8b", "0x0c", "0x48", "0x44", "0x8b", "0x40", "0x1c", "0x49"],
["0x01", "0xc1", "0x38", "0xe0", "0x75", "0xf1", "0x4c", "0x03"],
["0x24", "0x49", "0x01", "0xd0", "0x66", "0x41", "0x8b", "0x0c"],
["0xe8", "0xcc", "0x00", "0x00", "0x00", "0x41", "0x51", "0x41"]
]
}
Execute CrimsonEDRPanel.exe
with the following arguments:
-d <path_to_dll>
: Specifies the path to the CrimsonEDR.dll
file.
-p <process_id>
: Specifies the Process ID (PID) of the target process where you want to inject the DLL.
For example:
.\CrimsonEDRPanel.exe -d C:\Temp\CrimsonEDR.dll -p 1234
Here are some useful resources that helped in the development of this project:
For questions, feedback, or support, please reach out to me via:
DllNotificationInection is a POC of a new “threadless” process injection technique that works by utilizing the concept of DLL Notification Callbacks in local and remote processes.
An accompanying blog post with more details is available here:
https://shorsec.io/blog/dll-notification-injection/
DllNotificationInection works by creating a new LDR_DLL_NOTIFICATION_ENTRY in the remote process. It inserts it manually into the remote LdrpDllNotificationList by patching of the List.Flink of the list head and the List.Blink of the first entry (now second) of the list.
Our new LDR_DLL_NOTIFICATION_ENTRY will point to a custom trampoline shellcode (built with @C5pider's ShellcodeTemplate project) that will restore our changes and execute a malicious shellcode in a new thread using TpWorkCallback.
After manually registering our new entry in the remote process we just need to wait for the remote process to trigger our DLL Notification Callback by loading or unloading some DLL. This obviously doesn't happen in every process regularly so prior work finding suitable candidates for this injection technique is needed. From my brief searching, it seems that RuntimeBroker.exe and explorer.exe are suitable candidates for this, although I encourage you to find others as well.
This is a POC. In order for this to be OPSEC safe and evade AV/EDR products, some modifications are needed. For example, I used RWX when allocating memory for the shellcodes - don't be lazy (like me) and change those. One also might want to replace OpenProcess, ReadProcessMemory and WriteProcessMemory with some lower level APIs and use Indirect Syscalls or (shameless plug) HWSyscalls. Maybe encrypt the shellcodes or even go the extra mile and modify the trampoline shellcode to suit your needs, or at least change the default hash values in @C5pider's ShellcodeTemplate project which was utilized to create the trampoline shellcode.
MemTracer is a tool that offers live memory analysis capabilities, allowing digital forensic practitioners to discover and investigate stealthy attack traces hidden in memory. The MemTracer is implemented in Python language, aiming to detect reflectively loaded native .NET framework Dynamic-Link Library (DLL). This is achieved by looking for the following abnormal memory region’s characteristics:
The tool starts by scanning the running processes, and by analyzing the allocated memory regions characteristics to detect reflective DLL loading symptoms. Suspicious memory regions which are identified as DLL modules are dumped for further analysis and investigation.
Furthermore, the tool features the following options:
python.exe memScanner.py [-h] [-r] [-m MODULE]
-h, --help show this help message and exit
-r, --reflectiveScan Looking for reflective DLL loading
-m MODULE, --module MODULE Looking for spcefic loaded DLL
The script needs administrator privileges in order incepect all processes.
While DLL sideloading can be used for legitimate purposes, such as loading necessary libraries for a program to function, it can also be used for malicious purposes. Attackers can use DLL sideloading to execute arbitrary code on a target system, often by exploiting vulnerabilities in legitimate applications that are used to load DLLs.
To automate the DLL sideloading process and make it more effective, Chimera was created a tool that include evasion methodologies to bypass EDR/AV products. These tool can automatically encrypt a shellcode via XOR with a random key and create template Images that can be imported into Visual Studio to create a malicious DLL.
Also Dynamic Syscalls from SysWhispers2 is used and a modified assembly version to evade the pattern that the EDR search for, Random nop sleds are added and also registers are moved. Furthermore Early Bird Injection is also used to inject the shellcode in another process which the user can specify with Sandbox Evasion mechanisms like HardDisk check & if the process is being debugged. Finally Timing attack is placed in the loader which using waitable timers to delay the execution of the shellcode.
This tool has been tested and shown to be effective at bypassing EDR/AV products and executing arbitrary code on a target system.
Chimera is written in python3 and there is no need to install any extra dependencies.
Chimera currently supports two DLL options either Microsoft teams or Microsoft OneDrive.
Someone can create userenv.dll which is a missing DLL from Microsoft Teams and insert it to the specific folder to
%USERPROFILE%/Appdata/local/Microsoft/Teams/current
For Microsoft OneDrive the script uses version DLL which is common because its missing from the binary example onedriveupdater.exe
python3 ./chimera.py met.bin chimera_automation notepad.exe teams
python3 ./chimera.py met.bin chimera_automation notepad.exe onedrive
Once the compilation process is complete, a DLL will be generated, which should include either "version.dll" for OneDrive or "userenv.dll" for Microsoft Teams. Next, it is necessary to rename the original DLLs.
For instance, the original "userenv.dll" should be renamed as "tmpB0F7.dll," while the original "version.dll" should be renamed as "tmp44BC.dll." Additionally, you have the option to modify the name of the proxy DLL as desired by altering the source code of the DLL exports instead of using the default script names.
Step 1: Creating a New Visual Studio Project with DLL Template
Step 2: Importing Images into the Visual Studio Project
Step 3: Build Customization
Step 4: Enable MASM
Step 5:
Step 1: Change optimization
Step 2: Remove Debug Information's
To the maximum extent permitted by applicable law, myself(George Sotiriadis) and/or affiliates who have submitted content to my repo, shall not be liable for any indirect, incidental, special, consequential or punitive damages, or any loss of profits or revenue, whether incurred directly or indirectly, or any loss of data, use, goodwill, or other intangible losses, resulting from (i) your access to this resource and/or inability to access this resource; (ii) any conduct or content of any third party referenced by this resource, including without limitation, any defamatory, offensive or illegal conduct or other users or third parties; (iii) any content obtained from this resource
https://evasions.checkpoint.com/
https://github.com/Flangvik/SharpDllProxy
https://github.com/jthuraisamy/SysWhispers2
https://github.com/Mr-Un1k0d3r
This tool allows you to list protected processes, get the protection level of a specific process, or set an arbitrary protection level. For more information, you can read this blog post: Debugging Protected Processes.
You can get a copy of the MSI driver RTCore64.sys
here: PPLKiller/driver.
Disclaimer: it goes without saying that you should never install this driver on your host machine. Use a VM!
sc.exe create RTCore64 type= kernel start= auto binPath= C:\PATH\TO\RTCore64.sys DisplayName= "Micro - Star MSI Afterburner"
net start RTCore64
List protected processes.
PPLcontrol.exe list
Get the protection level of a specific process.
PPLcontrol.exe get 1234
Set an arbitrary protection level.
PPLcontrol.exe set 1234 PPL WinTcb
Protect a non-protected process with an arbitrary protection level. This will also automatically adjust the signature levels accordingly.
PPLcontrol.exe protect 1234 PPL WinTcb
Unprotect a protected process. This will set the protection level to 0
(i.e. None
) and the EXE/DLL signature levels to 0
(i.e. Unchecked
).
PPLcontrol.exe unprotect 1234
net stop RTCore64
sc.exe delete RTCore64
WinDbg just needs to open the target process, so you can use PPLcontrol to set an arbitrary protection level on your windbg.exe
process.
windbg.exe
process.C:\Temp>tasklist | findstr /i windbg
windbg.exe 1232 Console 1 24,840 K
C:\Temp>PPLcontrol.exe protect 1232 PPL WinTcb
[+] The Protection 'PPL-WinTcb' was set on the process with PID 1232, previous protection was: 'None-None'.
[+] The Signature level 'WindowsTcb' and the Section signature level 'Windows' were set on the process with PID 1232.
In addition to opening the target process, API monitor injects a DLL into it. Therefore, setting an arbitrary protection level on your apimonitor.exe
process won't suffice. Since the injected DLL is not properly signed for this purpose, the Section signature flag of the target process will likely prevent it from being loaded. However, you can temporarily disable the protection on the target process, start monitoring it, and restore the protection right after.
Failed to load module in target process - Error: 577, Windows cannot verify the digital signature for this file. A recent hardware or software change might have installed a file that is signed incorrectly or damaged, or that might be malicious software from an unknown source.
C:\Temp>tasklist | findstr /i target
target.exe 1337 Services 1 14,160 K
C:\Temp>PPLcontrol.exe get 1337
[+] The process with PID 1337 is a PPL with the Signer type 'WinTcb' (6).
C:\Temp>PPLcontrol.exe unprotect 1337
[+] The process with PID 1337 is no longer a PP(L).
C:\Temp>PPLcontrol.exe protect 1337 PPL WinTcb
[+] The Protection 'PPL-WinTcb' was set on the process with PID 1337, previous protection was: 'None-None'.
[+] The Signature level 'WindowsTcb' and the Section signature level 'Windows' were set on the process with PID 1337.
Release/x64
(x86
is not supported and will probably never be).If you have seen the film Spartacus from 1960, you will remember the scene where the Romans are asking for Spartacus to give himself up. The moment the real Spartacus stood up, a lot of others stood up as well and claimed to be him using the "I AM SPARTACUS" phrase.
When a process that is vulnerable to DLL Hijacking is asking for a DLL to be loaded, it's kind of asking "WHO IS VERSION.DLL?" and random directories start claiming "I AM VERSION.DLL" and "NO, I AM VERSION.DLL". And thus, Spartacus.
...but with a twist as Spartacus is utilising the SysInternals Process Monitor and is parsing raw PML log files. You can leave ProcMon running for hours and discover 2nd and 3rd level (ie an app that loads another DLL that loads yet another DLL when you use a specific feature of the parent app) DLL Hijacking vulnerabilities. It will also automatically generate proxy DLLs with all relevant exports for vulnerable DLLs.
version.dll
, Spartacus will create a version.dll.cpp
file for you with all the exports included in it. Then you can insert your payload/execution technique and compile.[Defence]
Monitoring mode trying to identify running applications proxying calls, as in "DLL Hijacking in progress". This is just to get any low hanging fruit and should not be relied upon.DllMain
. This technique was inspired and implemented from the walkthrough described at https://www.redteam.cafe/red-team/dll-sideloading/dll-sideloading-not-by-dllmain, by Shantanu Khandelwal. For this to work Ghidra is required.CreateFile
..dll
.procmon.exe
or procmon64.exe
.Drop Filtered Events
to ensure minimum PML output size.Auto Scroll
.ENTER
.Argument | Description |
---|---|
--pml | Location (file) to store the ProcMon event log file. If the file exists, it will be overwritten. When used with --existing-log it will indicate the event log file to read from and will not be overwritten. |
--pmc | Define a custom ProcMon (PMC) file to use. This file will not be modified and will be used as is. |
--csv | Location (file) to store the CSV output of the execution. This file will include only the DLLs that were marked as NAME_NOT_FOUND, PATH_NOT_FOUND, and were in user-writable locations (it excludes anything in the Windows and Program Files directories) |
--exe | Define process names (comma separated) that you want to track, helpful when you are interested only in a specific process. |
--exports | Location (folder) in which all the proxy DLL files will be saved. Proxy DLL files will only be generated if this argument is used. |
--procmon | Location (file) of the SysInternals Process Monitor procmon.exe or procmon64.exe
|
--proxy-dll-template | Define a DLL template to use for generating the proxy DLL files. Only relevant when --exports is used. All #pragma exports are inserted by replacing the %_PRAGMA_COMMENTS_% string, so make sure your template includes that string in the relevant location. |
--existing-log | Switch to indicate that Spartacus should process an existing ProcMon event log file (PML). To indicate the event log file use --pml , useful when you have been running ProcMon for hours or used it in Boot Logging. |
--all | By default any DLLs in the Windows or Program Files directories will be skipped. Use this to include those directories in the output. |
--detect | Try to identify DLLs that are proxying calls (like 'DLL Hijacking in progress'). This isn't a feature to be relied upon, it's there to get the low hanging fruit. |
--verbose | Enable verbose output. |
--debug | Enable debug output. |
--generate-proxy | Switch to indicate that Spartacus will be creating proxy functions for all identified export functions. |
--ghidra | Used only with --generate-proxy. Absolute path to Ghidra's 'analyzeHeadless.bat' file. |
--dll | Used only with --generate-proxy. Absolute path to the DLL you want to proxy. |
--output-dir | Used only with --generate-proxy. Absolute path to the directory where the solution of the proxy will be stored. This directory should not exist, and will be auto-created. |
--only-proxy | Used only with --generate-proxy. Comma separated string to indicate functions to clone. Such as 'WTSFreeMemory,WTSFreeMemoryExA,WTSSetUserConfigA' |
Collect all events and save them into C:\Data\logs.pml
. All vulnerable DLLs will be saved as C:\Data\VulnerableDLLFiles.csv
and all proxy DLLs in C:\Data\DLLExports
.
--procmon C:\SysInternals\Procmon.exe --pml C:\Data\logs.pml --csv C:\Data\VulnerableDLLFiles.csv --exports C:\Data\DLLExports --verbose
Collect events only for Teams.exe
and OneDrive.exe
.
--procmon C:\SysInternals\Procmon.exe --pml C:\Data\logs.pml --csv C:\Data\VulnerableDLLFiles.csv --exports C:\Data\DLLExports --verbose --exe "Teams.exe,OneDrive.exe"
Collect events only for Teams.exe
and OneDrive.exe
, and use a custom proxy DLL template at C:\Data\myProxySkeleton.cpp
.
--procmon C:\SysInternals\Procmon.exe --pml C:\Data\logs.pml --csv C:\Data\VulnerableDLLFiles.csv --exports C:\Data\DLLExports --verbose --exe "Teams.exe,OneDrive.exe" --proxy-dll-template C:\Data\myProxySkeleton.cpp
Collect events only for Teams.exe
and OneDrive.exe
, but don't generate proxy DLLs.
--procmon C:\SysInternals\Procmon.exe --pml C:\Data\logs.pml --csv C:\Data\VulnerableDLLFiles.csv --verbose --exe "Teams.exe,OneDrive.exe"
Parse an existing PML event log output, save output to CSV, and generate proxy DLLs.
--existing-log --pml C:\MyData\SomeBackup.pml --csv C:\Data\VulnerableDLLFiles.csv --exports C:\Data\DLLExports
Run in monitoring mode and try to detect any applications that is proxying DLL calls.
--detect
Create proxies for all identified export functions.
--generate-proxy --ghidra C:\ghidra\support\analyzeHeadless.bat --dll C:\Windows\System32\userenv.dll --output-dir C:\Projects\spartacus-wtsapi32 --verbose
Create a proxy only for a specific export function.
--generate-proxy --ghidra C:\ghidra\support\analyzeHeadless.bat --dll C:\Windows\System32\userenv.dll --output-dir C:\Projects\spartacus-wtsapi32 --verbose --only-proxy "ExpandEnvironmentStringsForUserW"
Note: When generating proxies for export functions, the solution that is created also replicates VERSIONINFO
and timestomps the target DLL to match the date of the source one (using PowerShell).
Below is the template that is used when generating proxy DLLs, the generated #pragma
statements are inserted by replacing the %_PRAGMA_COMMENTS_%
string.
The only thing to be aware of is that the pragma
DLL will be using a hardcoded path of its location rather than trying to load it dynamically.
#pragma once
%_PRAGMA_COMMENTS_%
#include <windows.h>
#include <string>
#include <atlstr.h>
VOID Payload() {
// Run your payload here.
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
Payload();
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
If you wish to use your own template, just make sure the %_PRAGMA_COMMENTS_%
is in the right place.
Whether it's a typo, a bug, or a new feature, Spartacus is very open to contributions as long as we agree on the following: