一个仅头文件的 Windows x64 库,允许你调用任何 NT 系统调用而无需触及 ntdll 导入,无需在二进制文件中留下字符串,并且没有那些会让 EDR 崩溃的常见红旗标志。
无 CRT。无 STL。无 IAT。整个库编译后仅约 19KB,且完全没有 DLL 依赖。
设计上避免了现有系统调用库的常见陷阱——明文字符串、已知哈希常量、来自非 ntdll 内存的直接系统调用、大声宣告“我在做奇怪的事情”的 IAT 导入、SEC_NO_CHANGE IOC、CRT 臃肿。这些通通不存在。
系统调用引擎
syscall; ret gadget,因此当 syscall 指令触发时 RIP 始终位于 ntdll 内部\KnownDlls\ntdll.dll 节映射中提取系统调用(无需文件系统访问,对 ProcMon 不可见)反断点
逃逸
AmsiScanBuffer 使其返回 S_OKEtwEventWrite 使其返回 SUCCESS代码质量
stealth/ 文件夹放入你的项目即可使用
initialize() 通过 \KnownDlls 节打开 ntdll,解析 PE 导出表,获取每个系统调用号.text 段以查找 syscall; ret gadget——实际执行 syscall 指令的地方sc::invoke() 时:
emit_stub() 构建一个唯一的多态存根——前后随机垃圾指令、使用每调用密钥异或混淆的系统调用号、间接跳转到 ntdll gadget过程中绝不存在 RWX 内存。绝不存在 syscall 指令在 ntdll 之外执行的情况。绝不存在系统调用号以明文存储的情况。
调用 tramp::invoke() 并传入目标函数。如果没有断点——函数正常运行,零开销。如果调试器放置了 0xCC:
调试器的断点列表仍然显示为激活状态。只是断点永远不会在我们的调用中触发。
cmake -B build -A x64
cmake --build build --config Release
需要 MSVC(VS 2019+)和 CMake 3.15+。输出约 19KB,零导入。
#include "stealth/syscall.hpp"
stealth::sc::initialize();
PVOID base = nullptr;
SIZE_T size = 0x1000;
NTSTATUS status = stealth::sc::invoke<NTSTATUS>(
HASH("NtAllocateVirtualMemory"),
NtCurrentProcess(), &base, (ULONG_PTR)0, &size,
(ULONG)(MEM_COMMIT | MEM_RESERVE), (ULONG)PAGE_READWRITE
);
#include "stealth/trampoline.hpp"
// 即使 x64dbg 在 MessageBoxA 上设置了断点也能工作
int ret = stealth::tramp::invoke<int>(
HASH_CI("user32.dll"), HASH("MessageBoxA"),
(HWND)nullptr, (LPCSTR)"hello", (LPCSTR)"title", (UINT)MB_OK
);
#include "stealth/bypass.hpp"
stealth::bypass::patch_etw();
stealth::bypass::patch_amsi();
stealth::tramp::shutdown();
stealth::sc::shutdown();
stealth/
common.hpp — 内存操作、自旋锁、静态映射、PRNG、调试输出
hash.hpp — 编译时自定义哈希
xorstr.hpp — 编译时 XOR 字符串加密
peb.hpp — PEB 遍历、PE 导出解析器、钩子检测
syscall.hpp — 间接系统调用引擎、存根生成器、W^X、反转储
trampoline.hpp — 基于 VEH 的反断点
bypass.hpp — AMSI + ETW 修补
MIT —— 你可以随意使用它。