A modern, stealthy DLL injector using direct syscalls to bypass EDR/AV hooks on Windows.
| Detection Method | Bypass Technique |
|---|---|
| API Hooking | Direct syscalls (bypass kernel32/ntdll hooks) |
| NtProtectVirtualMemory Hook | RWX allocation (never calls this function) |
| LoadLibrary Hooking | Manual PE mapping |
| Module Enumeration | No PEB/LDR entry created |
| PE Signature Scanning | Optional PE header wiping |
| Address Prediction | Random base address allocation |
| Shellcode Detection | Shellcode wiped after execution |
- Direct Syscalls: Executes
syscallinstruction directly via assembly stubs, completely bypassing any userland hooks placed by security software - Dynamic SSN Resolution: System Service Numbers are resolved at runtime from
ntdll.dll, making it compatible across all Windows versions - Halo's Gate: Recovers SSN from hooked functions by examining neighboring syscall stubs
- RWX Bypass: Allocates memory with
PAGE_EXECUTE_READWRITEdirectly, avoiding the commonly-hookedNtProtectVirtualMemory
- Windows 10/11 x64
- Visual Studio 2019+ or CMake 3.15+
- MASM (included with Visual Studio)
mkdir build
cd build
cmake .. -G "Visual Studio 17 2022" -A x64
cmake --build . --config ReleaseOpen SyscallInjector.sln and build in Release x64 configuration.
#include "injector.h"
#include <Windows.h>
int main() {
// Open target process
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, targetPid);
// Inject DLL from file
InjectionStatus result = Injector::InjectFromFile(hProcess, L"C:\\path\\to\\dll.dll");
if (result == InjectionStatus::Success) {
printf("Injected at: %p\n", Injector::GetLastInjectedBase());
} else {
printf("Failed: %s\n", InjectionStatusToString(result));
}
CloseHandle(hProcess);
return 0;
}// Read DLL into memory
std::vector<BYTE> dllData = ReadFileToMemory("payload.dll");
// Inject from memory buffer
InjectionStatus result = Injector::Inject(hProcess, dllData.data(), dllData.size());# By process ID
example.exe 1234 C:\path\to\payload.dll
# By process name
example.exe notepad.exe payload.dllSyscallInjector/
├── include/
│ ├── syscall.h # Syscall declarations and NT structures
│ └── injector.h # Injection API
├── src/
│ ├── syscall.cpp # SSN resolution with Halo's Gate
│ ├── syscalls.asm # Direct syscall assembly stubs (MASM x64)
│ └── injector.cpp # Manual PE mapping implementation
└── example/
└── main.cpp # Example injector application
- Syscall Initialization: Resolves System Service Numbers from
ntdll.dllat runtime - Hook Detection: Checks if functions are hooked (non-standard prologue)
- Halo's Gate: If hooked, recovers SSN from neighboring clean syscall stubs
- Memory Allocation: Uses
NtAllocateVirtualMemorysyscall with RWX protection - PE Mapping: Writes headers and sections via
NtWriteVirtualMemorysyscall - Shellcode Execution: Creates remote thread via
NtCreateThreadExsyscall - Import Resolution: Shellcode resolves imports and calls DllMain
- Cleanup: Wipes shellcode, optionally wipes PE headers
Edit include/injector.h to customize behavior:
namespace InjectorConfig {
constexpr bool WIPE_HEADERS = true; // Remove MZ/PE signature
constexpr bool RANDOMIZE_BASE = true; // Random allocation address
constexpr bool ENABLE_SEH = true; // x64 exception handling
}- GoSneak - Original Golang implementation that inspired this project
- Hell's Gate - Direct syscall technique
- Halo's Gate - SSN recovery from hooked functions
- Red Team Notes - Various evasion techniques
This tool is for educational and authorized security testing purposes only. Do not use for malicious purposes. The authors are not responsible for any misuse or damage caused by this software.
MIT License - See LICENSE file for details.