
Кроссплатформенный имплант и C2 на основе системных вызовов — прямые системные вызовы (Windows), необработанные системные вызовы (Linux), каналы HTTPS/DNS/ICMP. Без слоя winapi.
Ноль WinAPI. Каждый NT-примитив разрешается во время выполнения из ntdll в памяти —
инструкции SYSCALL выполняются напрямую через ассемблерные заглушки Plan9, без таблицы
импорта, без перехватов ntdll в пользовательском режиме. C2 через HTTPS / DNS / ICMP,
AES-256-GCM для каждого сообщения. Нативно для Windows. Сборки для Linux. Сборки для macOS.
Это не библиотека-обёртка для системных вызовов. Это полноценный фреймворк для импланта,
где каждая операция — от внедрения кода до чтения файлов и закрепления в реестре —
выполняется через сырые системные вызовы Nt*, разрешаемые при загрузке из текущей
таблицы экспорта ntdll. В бинарнике нет вызовов WinAPI. EDR нечего перехватывать в
пользовательском режиме.
B8 xx xx 00 00 0F 05 (прямой) или
4C 8B D1 B8 xx xx 00 00 0F 05 (Hells Gate). Каждое имя функции хешируется во время
компиляции — в бинарнике нет строк в открытом виде.asm_amd64.s) загружает SSN в EAX,
вручную устанавливает 7 аргументов, выполняет SYSCALL. Возврат через RAX/RDX.0F 05 C3 (syscall;ret) внутри
ntdll, вызывает через него. Ловушка CPU срабатывает внутри ntdll — стек вызовов
показывает кадры ntdll, а не импланта. Ни один перехват в пользовательском режиме не выживает..text в RWX, копирует оригинальные байты из
отображённой на диск ntdll, восстанавливает защиту, сбрасывает icache, уничтожает кеш SSN.
Каждый перехват в пользовательском режиме, установленный любым EDR, исчезает.Агент автоматически чередует техники внедрения. Каждый вызов использует другой метод — никакие два внедрения не выглядят одинаково при форензике.
Запускает все проверки, возвращает оценённый отчёт об угрозе. Автоуничтожение при Critical.
Всё через системные вызовы Nt*, без WinAPI.
EnablePrivilege(index) — установить любую привилегию по LUIDEnableAllTokenPrivileges() — 20 привилегий сразу (Debug, Impersonate, TCB, Backup, Restore и т.д.)GetProcessTokenIntegrityLevel() — запросить обязательный уровень целостностиStealProcessToken(pid) — открыть + дублировать токен другого процессаImpersonateThread() / RevertToSelf()EnumVirtualMemory() — обход всех виртуальных регионов через NtQueryVirtualMemoryFindWritableExecRegions() — поиск зафиксированных регионов PAGE_EXECUTE_READWRITEHideRegion() — установить PAGE_NOACCESS, чтобы скрыть память от сканеровUnhideRegion() — восстановить оригинальную защитуNtCreateFile → NtReadFile / NtWriteFile → NtClose. Ноль вызовов CreateFileA,
ReadFile, WriteFile или DeleteFileW. ReadFileContents(),
WriteFileContents(), DeleteFileNt(), FileExists().
NtCreateKey → NtSetValueKey. AddRunKeyPersistence(), RemoveRunKeyPersistence().
Никаких RegCreateKeyEx, RegSetValueEx или любых вызовов Advapi32.
EnumerateSystemHandles() — все открытые дескрипторы в системе через
NtQuerySystemInformation(SystemHandleInformation)FindEDRHandles() — сопоставляет PID владельцев с 30+ известными именами
процессов EDR (MsSense, CrowdStrike, Sentinel, Cylance, Carbon Black и т.д.)CloseEDRHandles() — закрывает мониторинговые дескрипторы, которые EDR разместил в вашем
процессеIsProcessMonitored() — булева проверка: за нами следят?NtFreeVirtualMemory.PatchAMSI() — AmsiScanBuffer → MOV EAX, 0; RETPatchETW() — EtwEventWrite → RETPatchNtTraceEvent() — NtTraceEvent → RETPatchDbgUiRemoteBreakin() — thread breakin → RETPatchInstrumentationCallbacks() — ThreadHideFromDebuggerВсе каналы реализуют интерфейс Channel. Добавление NTP, DoH или TURN
означает реализацию интерфейса — ноль изменений в агенте.
AES-256-GCM AEAD для каждого сообщения. Уникальный 12-байтовый nonce для каждого сообщения. Keyring для каждого импланта. Доступна производная ключа на основе парольной фразы. 3 теста, все проходят.
voidsyscall/
syscallwin/ Прямые/косвенные NT-системные вызовы + обход
asm_amd64.s Syscall/IndirectSyscall/ReadGSBase/SetGSBase/asm_cpuid/asm_rdtsc
resolve.go Обход PEB→LDR→ntdll, разбор экспорта PE, кеш SSN, сканирование пролога
stubs.go ~25 обёрток Nt*, DirectSyscall, IndirectSyscallByHash
hash.go хеш djb2 (строка + указатель UTF-16)
constants.go MEM_*, PAGE_*, THREAD_*, TOKEN_*, OBJ_*, REG_*, FILE_*, STATUS_*
unhook.go UnhookNtdll, SelfDel
peb.go Патчинг PEB (BeingDebugged, NtGlobalFlag, Heap, DebugPort)
token.go Повышение привилегий, кража токена, имперсонация
vad.go Перечисление VAD, скрытие/раскрытие регионов
files.go Файловый ввод-вывод через системные вызовы Nt*
registry.go Закрепление в реестре через системные вызовы Nt*
fingerprint.go Дамп SSN, отпечаток сборки, экспорт/импорт hex
inject_advanced.go 4 метода внедрения: отображение секции, hollow, APC, module stomp
antianalysis.go Обнаружение VM/песочницы/отладки/тайминга, оценённый отчёт об угрозе
handles.go Перечисление системных дескрипторов, убийца дескрипторов EDR
memcrypt.go Vault (XOR со сменой ключа), SecureDelete, StackEncrypt, WipeMemory
syscallnix/ Сырые системные вызовы Linux/darwin
patches/ AMSI, ETW, NtTraceEvent, DbgUiRemoteBreakin, InstrumentationCallbacks
loader/ Внедрение CreateThread/APC/module-stomp
channels/ HTTP, DNS (TXT), ICMP — интерфейс Channel
crypto/ AES-256-GCM, конверт, вариант с парольной фразой (3 теста)
server/ SessionManager, очередь задач, интерактивный REPL
agent/ Конфигурация, цикл beacon, 10 обработчиков задач
cmd/server/main.go CLI с REPL
cmd/agent/main.go Точка входа только для Windows
GOOS=windows GOARCH=amd64 go build -ldflags="-s -w" -o voidsyscall-agent.exe ./cmd/agent
GOOS=windows GOARCH=amd64 go build -ldflags="-s -w" -o voidsyscall-server.exe ./cmd/server
GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o server-linux ./cmd/server
GOOS=darwin GOARCH=arm64 go build -ldflags="-s -w" -o server-darwin ./cmd/server
Обфускация с помощью garble:
GOOS=windows GOARCH=amd64 garble -literals -tiny build -ldflags="-s -w" \
-o voidsyscall-agent.exe ./cmd/agent
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes
./voidsyscall-server.exe --cert cert.pem --key key.pem --https-port 443
./voidsyscall-agent.exe -c agent/example-config.json
ReadGSBase (asm) → GS:[0x60] → TEBLdrInMemoryOrderModuleList → сопоставление ntdll.dll через хеш djb2IMAGE_DOS_HEADER → e_lfanew → IMAGE_NT_HEADERS → DataDirectory[0] = Таблица экспортаAddressOfNames[], djb2 каждого, сопоставление с цельюAddressOfFunctions[ordinal] → адрес функцииB8 xx xx 00 00 0F 05 (прямой), B8 xx xx 00 00 C3 (early-ret) или 4C 8B D1 B8 xx xx 00 00 0F 05 (Hells Gate)Никаких имён функций в бинарнике. Только хеши djb2. Инструкция syscall
обходит каждый перехват в пользовательском режиме.
TaskShell // exec via cmd.exe
TaskInject // polymorphic: section/hollow/APC/stomp
TaskPatch // AMSI/ETW/both
TaskEvasion // PEB patches + VM/sandbox/debug/timing detection
TaskHandles // enumerate + kill EDR monitoring handles
TaskFingerprint // dump SSN build fingerprint
TaskToken // privilege escalation + impersonation
TaskVault // encrypted in-memory storage
TaskSleep // jitter-aware sleep
TaskExit // clean shutdown
Реализовано: Цикл beacon, очередь задач, 3 канала C2, 4 метода внедрения,
10+ проверок обхода, перечисление/закрытие дескрипторов, манипуляция токенами, операции VAD,
файловый ввод-вывод, закрепление в реестре, отпечатки SSN, шифрование памяти,
патчи AMSI/ETW, криптография AES-GCM, управление сессиями, интерактивный REPL.
3 криптотеста проходят. go build чистый на Windows.
Ещё нет: Автономный агент для Linux (сборки есть, логики агента нет), ротация ключей сессии, поэтапный загрузчик, каналы NTP/DoH, планирование закрепления.
MIT — LICENSE
| Метод | Как работает | Почему это скрытно |
|---|
| Отображение секции | NtCreateSection → NtMapViewOfSection (удалённо) → NtCreateThreadEx | Нет RWX-выделения в VAD. Секция подкреплена файлом. Сканеры памяти видят PAGE_EXECUTE_READ, а не PAGE_EXECUTE_READWRITE. |
| Process hollow | NtCreateUserProcess (приостановлен) → NtSuspendProcess → обнуление базы образа → выделение + запись шелл-кода → NtSetContextThread (RIP = шелл-код) → NtResumeProcess | Процесс выглядит как легитимный svchost.exe в диспетчере задач. Отличается только содержимое памяти. |
| Очередь APC | Перечисление потоков через NtQuerySystemInformation → NtOpenThread → NtQueueApcThread | Новый поток не создаётся. Новый TEB не создаётся. Новое выделение стека не создаётся. Срабатывает, когда поток входит в alertable wait. |
| Module stomping | Выделение в цели → запись минимального PE-заголовка + шелл-кода → NtCreateThreadEx по точке входа | Список модулей показывает правдоподобное имя DLL. PE-заголовок достаточно валиден, чтобы обмануть перечисление модулей. |
| Проверка | Метод |
|---|
| Обнаружение VM | Сканирование сигнатуры гипервизора CPUID leaf 0x40000000 (VMware, VirtualBox, Hyper-V, KVM, Xen, QEMU, Parallels) + резервный leaf 0x40000001 |
| Обнаружение песочницы | Количество CPU, артефакты реестра (VMware Tools, VBox Guest Additions, службы VMware/VBox), сканирование процессов песочницы (30+ известных имён: wireshark, procmon, x64dbg, ida и т.д.) |
| Обнаружение отладчика | PEB.BeingDebugged, PEB.NtGlobalFlag, флаги отладки кучи, ProcessDebugPort, ProcessDebugObjectHandle, ProcessDebugFlags, аппаратные точки останова DR0-7, проверка тайминга single-step |
| Аномалия тайминга | На основе RDTSC: 50 замеров задержки NtQuerySystemInformation, среднее/стандартное отклонение, флаг если >10% замеров превышают 3σ дисперсии. Ловит накладные расходы инструментирования. |
| Обход PEB | Патчит флаги BeingDebugged, NtGlobalFlag, ProcessHeap, DebugPort, ThreadHideFromDebugger — всё через чтение сегмента GS + NtWriteVirtualMemory. Без вызовов API. |
| Канал | Формат передачи | Требования |
|---|
| HTTPS | бинарный POST, кастомный фрейминг, рандомизированный UA/путь | TLS-сертификат |
| DNS | поддомен <idx>-<total>-<base32>, ответ TXT | Разрешение DNS |
| ICMPv4 | полезная нагрузка в ID+seq echo request/reply | сырой сокет (root/Admin) |
| Задача | Байт | Полезная нагрузка |
|---|
| shell | 0x01 | Команда UTF-8 |
| inject | 0x02 | PID (4 байта LE) + шелл-код |
| patch | 0x03 | 0x01=AMSI, 0x02=ETW, 0x03=оба |
| sleep | 0x04 | секунды (4 байта LE) |
| evasion | 0x10 | 0x01=полный, 0x02=VM, 0x03=песочница, 0x04=отладка, 0x05=тайминг, 0x06=отчёт |
| handles | 0x11 | 0x01=количество, 0x02=перечислить EDR, 0x03=закрыть EDR, 0x04=под наблюдением? |
| vault | 0x12 | операции зашифрованного хранилища |
| fingerprint | 0x13 | дамп отпечатка сборки SSN |
| token | 0x14 | 0x01=включить все, 0x02=целостность, 0x03=привилегия отладки, 0x04=имперсонация |
| exit | 0xFF | — |
map[uint32]uint16