# Blackbird API Guide
This document describes the current Blackbird control-plane and telemetry contract for engineers, detection content authors, and integrators.
## Telemetry Contract Visual
## IOCTL Record Example
## Revision and Scope
- Document revision: `2026-03-20`
- ABI source of truth: `abi/blackbird_ioctl.h`
- Compatibility note: no explicit in-band ABI version field is currently exposed; pin integration by commit/date and validate with `BlackbirdTestSuite`.
## At a Glance
- Control device:
- NT: `\Device\BlackbirdCtl`
- DOS: `\\.\Global\BlackbirdCtl` (preferred), `\\.\BlackbirdCtl` (legacy)
- IOCTL operations:
- subscribe
- unsubscribe
- get event
- get stats
- set pids
- query process image
- set shutdown mode
- IOCTL event families:
- handle
- thread
- filesystem
- Shared user-mode SDK:
- `J58.dll` / `UserMode/sensor/Blackbird_sensor_core.h`
- exported `BLACKBIRDSC*` APIs for IOCTL and ETW session management
- typed `BLACKBIRDSC_DETECTION_*` surface for ETW detection events
- ETW provider:
- name: `Blackbird.Kernel`
- GUID: `{D6C73F8A-6AD8-4F4B-A363-3D2FA31CD0E2}`
## Shared User-Mode SDK (`BlackbirdSensorCore`)
The preferred integration surface for user-mode consumers is:
- header: `user/sensor/blackbird_sensor_core.h`
- binary: `J58.dll`
Current exports:
- Protocol selection helpers:
- `BLACKBIRDSCUseServiceProtocol`
- `BLACKBIRDSCUseClientProtocol`
- `BLACKBIRDSCGetProtocolMode`
- `BLACKBIRDSCGetLastThreatIntelEnableError`
- IOCTL control-plane wrappers:
- `BLACKBIRDSCOpenControlDevice`
- `BLACKBIRDSCSubscribe`
- `BLACKBIRDSCUnsubscribe`
- `BLACKBIRDSCSetPids`
- `BLACKBIRDSCGetEvent`
- `BLACKBIRDSCGetStats`
- `BLACKBIRDSCQueryProcessImagePath`
- `BLACKBIRDSCSetShutdownMode`
- `BLACKBIRDSCParseStreamMaskA`
- ETW session wrappers:
- `BLACKBIRDSCStopSessionByName`
- `BLACKBIRDSCStartEtwSession`
- `BLACKBIRDSCStartBlackbirdEtwSession`
- `BLACKBIRDSCStartDetectionEtwSession`
- `BLACKBIRDSCRunEtwSession`
- `BLACKBIRDSCStopEtwSession`
- Typed detection callback types:
- `BLACKBIRDSC_DETECTION_EVENT`
- `BLACKBIRDSC_DETECTION_CALLBACK`
Consumers currently using these exports:
- `BlackbirdTestSuite`
- `BlackbirdController`
## IOCTL Interface
### Request/Response Matrix
- `IOCTL_BLACKBIRD_SUBSCRIBE`
- In: `BLACKBIRD_SUBSCRIBE_REQUEST`
- Out: none
- `IOCTL_BLACKBIRD_UNSUBSCRIBE`
- In: `BLACKBIRD_UNSUBSCRIBE_REQUEST`
- Out: none
- `IOCTL_BLACKBIRD_GET_EVENT`
- In: none
- Out: `BLACKBIRD_EVENT_RECORD`
- `IOCTL_BLACKBIRD_GET_STATS`
- In: none
- Out: `BLACKBIRD_STATS_RESPONSE`
- `IOCTL_BLACKBIRD_SET_PIDS`
- In: `BLACKBIRD_SET_PIDS_REQUEST`
- Out: none
- `IOCTL_BLACKBIRD_QUERY_PROCESS_IMAGE`
- In: `BLACKBIRD_QUERY_PROCESS_IMAGE_REQUEST`
- Out: `BLACKBIRD_QUERY_PROCESS_IMAGE_RESPONSE`
- `IOCTL_BLACKBIRD_SET_SHUTDOWN_MODE`
- In: none
- Out: none
### Stream Flags
- `BLACKBIRD_STREAM_HANDLE`
- `BLACKBIRD_STREAM_MEMORY`
- `BLACKBIRD_STREAM_THREAD`
- `BLACKBIRD_STREAM_FILESYSTEM`
`StreamMask` is bitwise-composable.
## Subscription and Delivery Semantics
- Subscriptions are scoped to each opened file handle to the control device.
- One client can subscribe multiple `(ProcessId, StreamMask)` entries.
- Current limits:
- max subscriptions per client: `256`
- max queue depth per client: `1024`
- max concurrent clients: `256`
- Each client has isolated:
- subscription table
- FIFO event queue
- sequence counter
- dropped-event counter
### Routing Rules
- Handle events route on `(CallerPid OR TargetPid)` + stream-mask intersection.
- Thread events route on `(ProcessId OR CreatorPid)` + stream-mask intersection.
- Per-client dedupe guarantees at most one queued copy of a given emitted record.
### Service-Broker Dynamic Expansion
When using `BlackbirdController` broker mode (`BLACKBIRDSCUseClientProtocol`), the controller can expand monitoring
beyond the initially seeded PID list by building a relation graph per client:
- Relation edges considered for expansion:
- handle events: `callerPid -> targetPid`
- thread events: `creatorPid -> processId`
- process telemetry: `creator/parent -> child process`
- broker ETW events: resolved from the explicit IPC ETW family fields (`caller/creator/process -> target/process`)
- Dynamic entries inherit the source subscription stream mask.
- Guardrails:
- max dynamic depth from explicit seed: `3`
- dynamic entry inactivity TTL: `120000 ms`
- Cleanup behavior:
- explicit `unsubscribe(rootPid)` drops dynamic descendants rooted at that PID for that client.
- explicit `subscribe(pid)` upgrades an existing dynamic entry for `pid` to explicit.
- `set-pids` replaces the explicit seed set; dynamic entries are rebuilt from fresh runtime relations.
## Event Record Structure
`BLACKBIRD_EVENT_RECORD` contains:
- `BLACKBIRD_EVENT_HEADER`
- `Size`
- `Type`
- `StreamMask`
- `Sequence` (per-client monotonic)
- `TimestampQpc`
- Union payload:
- `BLACKBIRD_HANDLE_EVENT`
- `BLACKBIRD_THREAD_EVENT`
Event type values:
- `BlackbirdEventTypeHandle`
- `BlackbirdEventTypeThread`
## Handle Event Contract
`BLACKBIRD_HANDLE_EVENT` fields:
- `CallerPid`, `TargetPid`
- `DesiredAccess`
- `ClassId` (`BLACKBIRD_HANDLE_CLASS`)
- `OriginAddress`, `OriginProtect`, `OriginPath`
- `StatusOpenProcess`, `StatusBasicInfo`, `StatusSectionName`
- Deep-path capture metadata:
- `DeepAllocationBase`
- `DeepRegionSize`
- `DeepRegionProtect`
- `DeepRegionState`
- `DeepRegionType`
- `DeepSampleSize`
- `DeepSample[BLACKBIRD_MAX_DEEP_SAMPLE_BYTES]`
- `FrameCount`, `Frames[BLACKBIRD_MAX_EVENT_FRAMES]`
### Handle Classes
- `BlackbirdHandleClassUnknown`
- `BlackbirdHandleClassLegitimateSyscall`
- `BlackbirdHandleClassDirectSyscallSuspect`
### Handle Flags
- `BLACKBIRD_HANDLE_FLAG_EXEC_PROTECT`
- `BLACKBIRD_HANDLE_FLAG_FROM_NTDLL`
- `BLACKBIRD_HANDLE_FLAG_FROM_EXE`
- `BLACKBIRD_HANDLE_FLAG_MEMORY_RELATED`
- `BLACKBIRD_HANDLE_FLAG_THREAD_OBJECT`
- `BLACKBIRD_HANDLE_FLAG_DUPLICATE_OPERATION`
- `BLACKBIRD_HANDLE_FLAG_DEEP_PATH_CANDIDATE`
- `BLACKBIRD_HANDLE_FLAG_DEEP_PATH_CAPTURED`
- `BLACKBIRD_HANDLE_FLAG_DEEP_PATH_CACHE_HIT`
## Thread Event Contract
`BLACKBIRD_THREAD_EVENT` fields:
- `ProcessId`, `ThreadId`, `CreatorPid`
- `StartAddress`
- `ImageBase`, `ImageSize`
- `Flags`
- `FrameCount`, `Frames[BLACKBIRD_MAX_EVENT_FRAMES]`
### Thread Flags
- `BLACKBIRD_THREAD_FLAG_GOT_START`
- `BLACKBIRD_THREAD_FLAG_GOT_RANGE`
- `BLACKBIRD_THREAD_FLAG_REMOTE_CREATOR`
- `BLACKBIRD_THREAD_FLAG_OUTSIDE_MAIN_IMG`
- `BLACKBIRD_THREAD_FLAG_CORRELATED_INTENT`
- `BLACKBIRD_THREAD_FLAG_CORR_MEMORY`
- `BLACKBIRD_THREAD_FLAG_CORR_THREAD_CTX`
- `BLACKBIRD_THREAD_FLAG_CORR_DUP_HANDLE`
- `BLACKBIRD_THREAD_FLAG_START_REGION_EXEC`
## Stats Contract
`BLACKBIRD_STATS_RESPONSE`:
- `SubscriptionCount`
- `QueueDepth`
- `DroppedEvents`
- `Reserved`
## ETW Contract
Provider:
- Name: `Blackbird.Kernel`
- GUID: `{D6C73F8A-6AD8-4F4B-A363-3D2FA31CD0E2}`
Current event names:
- `HandleTelemetry`
- `ThreadTelemetry`
- `ProcessTelemetry`
- `ImageTelemetry`
- `RegistryTelemetry`
- `DetectionTelemetry`
- `SystemInformationTelemetry`
- `NtApiTelemetry`
### Key ETW-Only Fields
- Thread correlation:
- `correlationFlags`
- `correlationAccessMask`
- `correlationAgeMs`
- Thread start-region metadata:
- `startRegionProtect`
- `startRegionState`
- `startRegionType`
- `startRegionStatus`
- Process metadata:
- parent/creator IDs
- `processStartKey`
- image path and command line
- Image metadata:
- signature level/type where available
- system-mode image indicator
- Registry metadata:
- operation, notify class, data type/size
- key path and value name
- high-value path marker
- Detection metadata:
- detection name
- severity
- reason
- correlation context
### IPC ETW Uplink Surface
The broker ETW IPC model (`BLACKBIRD_IPC_ETW_EVENT`) now carries both the generic ETW envelope and
event-family-specific fields so clients can build richer inspectors without reparsing raw ETW:
- Generic envelope:
- source, family, task/opcode/id
- ETW header process/thread IDs
- actor/target relation PIDs
- detection name, reason, severity
- correlation flags/access/age
- Handle/APC enrichment:
- class name, desired access
- origin address/protect/path
- frame list
- deep-path allocation/region/sample metadata
- APC duplicate-operation marker
- Thread enrichment:
- process/thread/creator IDs
- start address, image base/size
- start-region protection/state/type/status
- worker stack frames
- got-start/got-range/remote/outside-image flags
- Process/Image enrichment:
- parent/creator IDs
- creator thread ID
- process start key
- session ID
- create status / create marker
- image path and command line
- signature level/type and system-mode marker for image events
- Registry enrichment:
- operation
- session ID
- notify class
- data type/size
- key path and value name
- high-value path marker
### Current Detection Names
- `REMOTE_THREAD_WITH_RECENT_HANDLE_INTENT`
- `REMOTE_THREAD_START_IN_NON_IMAGE_EXECUTABLE_REGION`
- `REMOTE_THREAD_OUTSIDE_MAIN_IMAGE`
- `THREAD_ACTIVITY_WITH_THREAD_CONTEXT_INTENT`
- `THREAD_HIJACK_INTENT`
- `REMOTE_APC_CREATION_SUSPECT`
- `HIGH_VALUE_REGISTRY_ACTIVITY`
- `DIRECT_SYSCALL_SUSPECT_HANDLE_OPERATION`
- `POSSIBLE_PROCESS_HOLLOWING_OR_INJECTION_INTENT_CHAIN`
- `POSSIBLE_MANUAL_MAP_OR_HOLLOWING_EXECUTION`
- `KERNEL_PROCESS_HOLLOWING_MARK_CHAIN_MEDIUM`
- `KERNEL_PROCESS_HOLLOWING_MARK_CHAIN_STRONG`
- `STACK_INTEGRITY_ANOMALY_ON_HANDLE_OP`
- `SUSPICIOUS_NTDLL_IMAGE_PATH`
- `MULTIPLE_NTDLL_IMAGE_MAPPINGS`
- `DRIVER_DISPATCH_OR_OBJECT_TAMPER`
- `DRIVER_DISPATCH_OR_OBJECT_TAMPER_CLEARED`
- broker-synthesized correlation detections (controller ETW uplink):
- `PROCESS_HOLLOWING_MARK_CHAIN_MEDIUM`
- `PROCESS_HOLLOWING_MARK_CHAIN_STRONG`
- `PROCESS_HOLLOWING_TXF_SUSPECT_CHAIN`
## Quick Integration Flow (IOCTL)
1. `CreateFile("\\\\.\\Global\\BlackbirdCtl", ...)`
2. Subscribe one or more PIDs with chosen stream mask
3. Poll `IOCTL_BLACKBIRD_GET_EVENT` in a loop
4. Handle `NO_MORE_ENTRIES` as empty queue
5. Query `IOCTL_BLACKBIRD_GET_STATS` for health and drops
6. Unsubscribe and close handle
Using `BlackbirdSensorCore` helpers, the same flow is:
1. `BLACKBIRDSCOpenControlDevice`
2. `BLACKBIRDSCSubscribe`
3. loop on `BLACKBIRDSCGetEvent`
4. `BLACKBIRDSCGetStats` for queue/drop health
5. `BLACKBIRDSCUnsubscribe` and close handle
## Minimal Pseudocode
```c
HANDLE h = CreateFileW(L"\\\\.\\Global\\BlackbirdCtl", ...);
BLACKBIRD_SUBSCRIBE_REQUEST sub = { .ProcessId = pid, .StreamMask = BLACKBIRD_STREAM_HANDLE | BLACKBIRD_STREAM_THREAD };
DeviceIoControl(h, IOCTL_BLACKBIRD_SUBSCRIBE, &sub, sizeof(sub), NULL, 0, &bytes, NULL);
for (;;) {
BLACKBIRD_EVENT_RECORD rec = {0};
if (!DeviceIoControl(h, IOCTL_BLACKBIRD_GET_EVENT, NULL, 0, &rec, sizeof(rec), &bytes, NULL)) {
if (GetLastError() == ERROR_NO_MORE_ITEMS) {
Sleep(25);
continue;
}
break;
}
switch (rec.Header.Type) {
case BlackbirdEventTypeHandle:
/* consume handle payload */
break;
case BlackbirdEventTypeThread:
/* consume thread payload */
break;
}
}
```
## Error and Status Expectations
Common NTSTATUS results mapped to Win32 errors on IOCTL calls:
- `STATUS_SUCCESS`
- `STATUS_NO_MORE_ENTRIES` (empty queue)
- `STATUS_INVALID_PARAMETER` (invalid stream mask/request)
- `STATUS_NOT_FOUND` (unsubscribe for unknown PID)
- `STATUS_ACCESS_DENIED` (non-user-mode request denied)
- `STATUS_BUFFER_TOO_SMALL`
## Operational Notes
- Symbol enrichment is user-mode responsibility (see sensor/test tooling).
- Current sensor formatting uses:
- symbol-first resolution (DbgHelp)
- module-range fallback from ETW image metadata cache
- final context-only process image fallback when symbol ownership is unknown
- Kernel addresses may remain unresolved depending on symbol policy/hardening.
- High event rates can produce queue drops; monitor `DroppedEvents` and ETW counters.
- Use `BlackbirdTestSuite` to verify environment health and coverage after driver changes.
- `BlackbirdTestSuite` strictness knobs:
- `BLACKBIRD_TEST_REQUIRE_KERNEL_CORRELATION=1` to require kernel correlation-dependent checks.
- `BLACKBIRD_TEST_REQUIRE_APC=1` to require APC ETW coverage.
- Test output includes per-check elapsed timing (`ms`) and cycle deltas (`rdtsc` when available), plus suite total elapsed time.