一个仅头文件的 Windows x64 库,让你无需触碰 ntdll 导入即可调用任意 NT 系统调用,无需在二进制文件中留下字符串,也不会出现那些让 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() 构建一个独特的变形存根——前后插入随机垃圾指令,使用每次调用独立的密钥对系统调用号进行 XOR 混淆,间接跳转到 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 — 内存操作、自旋锁、static_map、PRNG、调试输出
hash.hpp — 编译期自定义哈希
xorstr.hpp — 编译期 XOR 字符串加密
peb.hpp — PEB 遍历、PE 导出解析器、钩子检测
syscall.hpp — 间接系统调用引擎、存根生成器、W^X、反转储
trampoline.hpp — 基于 VEH 的反断点
bypass.hpp — AMSI + ETW 修补
MIT——随你怎么用。