Listen to this Post

Introduction:
Endpoint Detection and Response (EDR) systems form the backbone of modern Windows security, operating at the intersection of kernel drivers, user-mode hooks, and runtime analysis to detect malicious behaviors like remote shellcode injection. Building a basic EDR from scratch—leveraging kernel callbacks, static analysis, DLL injection detection, and API hooking—provides deep insight into how advanced security tools identify threats before they execute.
Learning Objectives:
- Implement a kernel driver that registers process creation and image load callbacks to monitor for anomalous memory operations.
- Deploy user-mode API hooks to detect remote thread creation and shellcode injection techniques such as `CreateRemoteThread` and
QueueUserAPC. - Combine static analysis of DLL imports with dynamic hooking to differentiate benign code from reflective DLL injection and shellcode stagers.
You Should Know:
- Kernel Driver Callbacks: The First Line of Defense
A Windows kernel driver can register callbacks that fire on process creation, thread creation, and image loading. This enables early detection of suspicious processes attempting to allocate executable memory or inject shellcode.
Step‑by‑step:
- Set up a kernel-mode driver framework using Visual Studio with WDK (Windows Driver Kit).
- Register `PsSetCreateProcessNotifyRoutineEx` to inspect new process creation events.
- Inside the callback, filter for processes that request `PAGE_EXECUTE_READWRITE` protection via `NtAllocateVirtualMemory` (requires hooking at syscall level or using `ObRegisterCallbacks` for handle operations).
Code snippet (kernel callback registration):
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) {
PsSetCreateProcessNotifyRoutineEx(ProcessNotifyCallbackEx, FALSE);
return STATUS_SUCCESS;
}
void ProcessNotifyCallbackEx(PEPROCESS Process, HANDLE ProcessId, PPS_CREATE_NOTIFY_INFO CreateInfo) {
if (CreateInfo) {
DbgPrint("[bash] New process: %wZ PID: %d\n", &CreateInfo->ImageFileName, ProcessId);
// Check for suspicious flags like CREATE_SUSPENDED
if (CreateInfo->CreationFlags & CREATE_SUSPENDED) {
DbgPrint("[!] Suspended process creation detected!\n");
}
}
}
4. Load the driver using `sc.exe create edr_driver binPath= C:\path\to\driver.sys type= kernel` and start with sc start edr_driver.
Windows commands to verify driver loading:
sc query edr_driver fltmc filters | findstr "edr"
2. User‑Mode Hooks for API Monitoring
Hooking critical Windows APIs like CreateRemoteThread, WriteProcessMemory, and `VirtualAllocEx` allows detection of remote shellcode injection from user space. Libraries like Microsoft Detours or minhook are ideal.
Step‑by‑step using Detours:
- Install Detours (or minhook) and link against your DLL injector.
- Hook `Kernel32!CreateRemoteThread` to inspect the target process handle and thread start address.
- If the start address resides in a region marked
MEM_COMMIT | PAGE_EXECUTE_READWRITE, trigger an alert.
Example hook function (C++):
static HANDLE (WINAPI Real_CreateRemoteThread)(HANDLE, LPSECURITY_ATTRIBUTES, SIZE_T, LPTHREAD_START_ROUTINE, LPVOID, DWORD, LPDWORD) = CreateRemoteThread;
HANDLE WINAPI Hook_CreateRemoteThread(HANDLE hProcess, LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId) {
// Check if target process is not a known system process
if (GetProcessId(hProcess) > 1000) {
OutputDebugString(L"[bash] Remote thread injection attempt detected!\n");
// Log to file or send to analysis engine
}
return Real_CreateRemoteThread(hProcess, lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, lpThreadId);
}
4. Compile as a DLL and inject into all running processes via `SetWindowsHookEx` or AppInit_DLLs registry.
- Static Analysis of DLL Imports to Spot Reflective Loaders
Reflective DLL injection avoids `LoadLibrary` by manually mapping a DLL into memory. Static analysis of suspicious imports (e.g.,NtMapViewOfSection,RtlMoveMemory,VirtualAlloc) can flag potential loaders.
Command‑line check using PowerShell:
Get-Process | ForEach-Object { $<em>.Modules | Where-Object { $</em>.ModuleName -like "reflective" -or $_.FileName -match "kernel32.WriteProcessMemory" } }
Advanced static analysis with `dumpbin` or `pe-sieve`:
dumpbin /imports suspicious.exe | findstr "NtMapViewOfSection VirtualAlloc"
Integrate this into your EDR by scanning PE headers on process creation using the kernel callback’s image load notification (PsSetLoadImageNotifyRoutine).
4. Detecting Remote Shellcode Injection via ETW
Event Tracing for Windows (ETW) provides low‑overhead telemetry. Use `Microsoft-Windows-Threat-Intelligence` provider to catch `VirtualAllocEx` and `WriteProcessMemory` events without hooking.
Step‑by‑step ETW consumer setup:
1. Register for `EVENT_TRACE_FLAG_PROCESS` and `EVENT_TRACE_FLAG_VIRTUAL_ALLOC`.
- Parse events containing `EventId` 10 (VirtualAllocEx) and check for
PAGE_EXECUTE_READWRITE. - Correlate with the calling process to distinguish legitimate allocators (e.g., debuggers) from malware.
PowerShell ETW session example:
logman create trace edr_session -p Microsoft-Windows-Kernel-Memory (event ID 10) -o edr.etl -ets logman start edr_session -ets
Then analyze the `.etl` file with `tracerpt` or a custom parser.
- Monitoring DLL Injection via AppInit_DLLs and Known Injection Vectors
Malware often injects DLLs using `SetWindowsHookEx` or by abusing the `AppInit_DLLs` registry key. Harden detection by monitoring changes toHKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs.
Registry monitoring with PowerShell (usable in your EDR agent):
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows"
$watcher.Filter = "AppInit_DLLs"
Register-ObjectEvent $watcher "Changed" -Action { Write-Host "AppInit_DLLs modified – potential persistence!" }
Additionally, implement a user‑mode hook for `NtSetInformationProcess` to detect `ProcessMitigationPolicy` tampering that could disable DLL loading protections.
6. Combining Callbacks, Hooks, and Shellcode Heuristics
A robust DIY EDR correlates kernel callbacks (process birth) with user‑mode hooks (API abuse) and static analysis (PE anomalies). For shellcode detection, implement a heuristic: if a remote thread start address lies outside any loaded module and the memory region is both writable and executable, flag it as shellcode.
Pseudo‑logic for the detection engine:
On CreateRemoteThread hook:
startAddr = lpStartAddress
if (GetModuleHandleEx(startAddr) == NULL) {
regionInfo = VirtualQuery(startAddr)
if (regionInfo.Protect & PAGE_EXECUTE_READWRITE) {
LOG("Suspicious shellcode thread at 0x%p in PID %d", startAddr, targetPid)
}
}
Deploy this logic inside a DLL injected into `services.exe` and `lsass.exe` to catch high‑value process injections.
7. Testing Your DIY EDR with Real Shellcode
Use a benign shellcode generator (e.g., msfvenom with a harmless payload like windows/messagebox) to validate detection.
Generate test shellcode (Linux/WSL or Windows with msfvenom):
msfvenom -p windows/x64/messagebox TEXT="EDR Test" -f raw -o shellcode.bin
Injector code (C++):
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, targetPID); LPVOID addr = VirtualAllocEx(hProc, NULL, sizeof(shellcode), MEM_COMMIT, PAGE_EXECUTE_READWRITE); WriteProcessMemory(hProc, addr, shellcode, sizeof(shellcode), NULL); CreateRemoteThread(hProc, NULL, 0, (LPTHREAD_START_ROUTINE)addr, NULL, 0, NULL);
Your EDR should alert on `VirtualAllocEx` with PAGE_EXECUTE_READWRITE, followed by `WriteProcessMemory` and `CreateRemoteThread` to the same region.
What Undercode Say:
- Key Takeaway 1: Building a basic Windows EDR from kernel callbacks and user‑mode hooks demystifies how commercial products detect remote shellcode injection, empowering defenders to craft custom detections.
- Key Takeaway 2: Combining multiple monitoring layers—kernel, ETW, static analysis, and heuristic memory checks—drastically reduces false positives while catching evasive injection techniques like reflective DLL loading.
Analysis: The provided guide from core‑jmp.org and Aurélien Chalot’s research at blog.whiteflag.io highlight a critical trend: defenders are moving from relying solely on vendor EDRs to building modular, DIY detection systems. This shift is driven by the need for transparency, customization against zero‑day injection vectors, and cost efficiency for smaller security teams. However, kernel driver development carries stability risks—a buggy callback can BSOD the system. Proper testing in isolated VMs and signing drivers with a test certificate are mandatory. The integration of ETW provides a safer alternative to inline hooks, though it requires parsing structured event data. Ultimately, a hybrid approach (kernel callbacks for process creation, ETW for memory operations, and user‑mode hooks for API arguments) offers the best balance of visibility and resilience.
Prediction:
As attack techniques increasingly abuse legitimate Windows mechanisms (e.g., CallbackObjs, `ProcessHollowing` through NtUnmapViewOfSection), DIY EDR frameworks will evolve into open‑source, community‑driven projects that rival commercial products in specific detection domains. Expect to see more kernel‑bypass‑resistant EDRs leveraging hardware‑assisted virtualization (Intel VT‑x) and direct hypervisor calls to monitor syscalls without ring‑0 hooking, making injection detection truly rootkit‑proof. Within 18 months, we anticipate standardized blueprints for automated kernel‑driver generation using eBPF for Windows, lowering the barrier to custom EDR development for every security engineer.
▶️ Related Video (82% Match):
🎯Let’s Practice For Free:
IT/Security Reporter URL:
Reported By: Abelousova Building – Hackers Feeds
Extra Hub: Undercode MoN
Basic Verification: Pass ✅


