Indirect Waffles - Shellcode Loader to Bypass EDRs
A shellcode loader that leverages advanced techniques such as HellHall's indirect syscalls, Early Bird APC injection, and more, to evade EDR detection and enhance payload delivery.
While preparing for CRTO 2 and learning from Maldev Academy, I wanted to put everything I had learned into practice. That’s when I created Indirect Waffles, a custom shellcode loader designed for EDR evasion and enhanced by many of the advanced techniques I’ve been studying.
Table of contents
Demo
Demo showcasing Indirect Waffles.
Key Features
- Enumeration: Uses
NtQuerySystemInformation
to enumerate processes for PPID spoofing andNtOpenProcess
syscall to obtain process handles. - Custom Dynamic HTTP/s Payload Staging
- Check it out on my GitHub.
- Shellcode Decryption: RC4 with runtime key brute-forcing.
- Process Creation with
NtCreateUserProcess
and the following enhancements:- Suspended process creation for APC Injection.
- Parent Process ID (PPID) spoofing.
- Block DLL injection policy, preventing third-party DLLs (non-Microsoft signed) from being injected, mitigating some EDR hooking techniques.
- Injection: Remote Mapped Injection via syscalls with RX (Read Execute) permissions for improved evasion from memory scanners.
- Execution: Early Bird APC Injection using syscalls to queue the payload for execution before the target thread resumes execution.
- Resumes process via
NtResumeThread
syscall. - Extra Enhancements:
- Custom string literal obfuscation: Works on both normal and wide strings.
- Compile-time IAT API hashing using
MurmurHash
to evade static API detection techniques. - HellHalls’ Indirect Syscall implementation with compile-time hashing via
MurmurHash
.
- Anti-Debugging:
- Checks the PEB flag for the
IsDebugged
flag to detect the presence of a debugger. - Anti-debug loop (30 seconds total):
- 3-second sleep intervals using
NtWaitForSingleObject
. - API hammering to make the sleep appear more benign.
- 3-second sleep intervals using
- Uses
QueryPerformanceCounter
to measure total loop time; if it exceeds 35 seconds, it is likely being debugged.
- Checks the PEB flag for the
- Spoofed Binary Metadata:
.DLL
: Spoofed as Notepad++’slibcurls.dll
..EXE
: Spoofed as Notepad++’sgup.exe
.
Spoofing Binary Metadata
To make your malware less suspicious, you can spoof the malware’s metadata to resemble that of a legitimate, benign file.
- Add a new item to your project.
- Add a Resource (
.rc
) File. - Exit Resource Viewer
- Edit Resource File
- Insert Metadata
- Scroll down to the bottom of the file and insert the following contents.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
1 VERSIONINFO
FILEVERSION 112, 0, 5615, 88 // File version separated by commas
PRODUCTVERSION 1, 0, 0, 0
FILEFLAGSMASK 0x0L
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x0L
FILETYPE 0x0L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904B0"
BEGIN
// Modify the values below
VALUE "CompanyName", "Google LLC."
VALUE "FileDescription", "Google Chrome"
VALUE "InternalName", "Chrome"
VALUE "LegalCopyright", "Copyright 2023 Google LLC."
VALUE "OriginalFilename", "chrome.exe"
VALUE "ProductName", "Google Chrome"
VALUE "ProductVersion", "112.0.5615.86"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
6. The example above is from Chrome’s binary metadata, you can use this PowerShell script I created to extract the metadata from any file, DLLs included.
1
2
3
4
5
6
7
8
9
10
11
# Use the first argument as the file path
$path = $args[0]
# Get the file version information
$file = Get-Item $path
$versionInfo = $file.VersionInfo
# Iterate over all the properties of $versionInfo
foreach ($property in $versionInfo.PSObject.Properties) {
Write-Output "VALUE `"$($property.Name)`", `"$($property.Value)`""
}
Conclusion
This project was incredibly useful for testing everything I’ve learned so far, but I think I can make a better and smaller loader.
My next goal is to take the lessons learned from this project and build a DLL payload loader inspired by NUL0x4C’s AtomLdr, focusing on leveraging DLL Sideloading to run the DLL payload. The plan is to use shellcode injection via Module Stomping and execute the payload through Fibers for thread callstack spoofing.
Stay tuned for updates!
Happy hacking! 😄