ExfilGuardian
Backend

Contributor Guide

Where to code each feature, backend development roadmap

Overview

This guide maps each ExfilGuardian feature to the exact files and functions where development happens. Use it to know where to start coding, what exists, and what's missing.

Status Legend

StatusMeaning
DoneCode exists and works
PartialScaffold or partial implementation exists
TODONot yet implemented

Feature Map

F1: WFP Kernel Filtering

Status: Done

WhatWhere
Driver entry/unloaddriver/src/lib.rsDriverEntry, DriverUnload
WFP callout registrationdriver/src/security/filter.rsregister_callouts()
WFP API bindingsdriver/src/security/wfp.rs
Packet capture callbackdriver/src/security/filter.rsclassify_fn()
Device IOCTL handlerdriver/src/device/io.rsdevice_control()
IRP inversé modeldriver/src/device/io.rs → pending IRP completion on packet arrival

Corrected driver version: rust-driver-rectified-version/ contains the latest working driver. Compare with driver/ for any divergences.

To modify WFP behavior: Edit driver/src/security/filter.rs. The classify_fn callback receives each packet from WFP and decides whether to pass, block, or queue it for the agent.


F2: Local Telemetry Agent

Status: Done

WhatWhere
Service mainagent/src/main.rsrun() (SCM dispatcher + console fallback)
IOCTL loopagent/src/main.rsrun_agent() (DeviceIoControl blocking loop)
Packet conversionagent/src/main.rsExfilPacketKernelNetworkPacket
Registry configagent/src/main.rs → reads HKLM\SOFTWARE\ExfilGuardian\TargetUrl
gRPC clientagent/src/main.rstonic client + ReceiverStream

To add agent-side logic: The agent is currently a single main.rs. To add pre-filtering or flow tracking on the agent side, use the analysis crate's agent modules:

use exfil_analysis::agent::pre_filter::PreFilter;
use exfil_analysis::agent::flow_tracker::FlowTracker;

These modules are already implemented in analysis/src/agent/ but not yet wired into the agent binary.


F3: SQLite WAL Queue

Status: Done

WhatWhere
Queue initagent/src/main.rsConnection::open("exfil_queue.db") + WAL pragma
Produceragent/src/main.rs → IOCTL loop inserts Protobuf bytes into packets table
Consumeragent/src/main.rs → Tokio task reads 50 packets, sends via gRPC, deletes on success
Wake mechanismagent/src/main.rsmpsc::channel between producer and consumer

To modify queue behavior: Edit the consumer task in agent/src/main.rs. The batch size (50), retry delay (5s), and queue table schema are all in that file.


F4: gRPC/Protobuf Transport

Status: Done

WhatWhere
Proto definitionproto/exfil.protoExfilService, NetworkPacket, StreamResponse
Server receiverserver/src/grpc/receiver.rsExfilServerImpl::stream_packets()
Agent clientagent/src/main.rsExfilServiceClient::stream_packets()
Code generationagent/build.rs and server/build.rstonic_build::compile_protos()

To add new RPCs: Edit proto/exfil.proto, add the RPC definition, then implement the handler in server/src/grpc/receiver.rs. The agent side goes in agent/src/main.rs (or a new module).


F5: mTLS Dynamic Authentication

Status: Partial (certificates generated, mTLS disabled for debugging)

WhatWhere
CA + server cert generationserver/src/main.rsensure_certs() (uses rcgen)
Agent cert generationserver/src/api/enroll.rs → per-enrollment client cert signed by CA
Certs generator CLIcerts/src/main.rs → standalone cert generation tool
TLS config (disabled)server/src/main.rs → commented out .tls_config(tls)?

To re-enable mTLS:

  1. In server/src/main.rs, uncomment the TLS configuration block:
let grpc_server = Server::builder()
    .tls_config(tls)?  // Uncomment this line
    .add_service(ExfilServiceServer::new(grpc_service))
    .serve(grpc_addr);
  1. In the agent, configure tonic to use the client certificate:
let tls = ClientTlsConfig::new()
    .ca_certificate(Certificate::from_pem(ca_pem))
    .identity(Identity::from_pem(client_cert, client_key));
let channel = Channel::from_shared(url)?
    .tls_config(tls)?
    .connect().await?;
  1. Ensure the agent reads its certificate files from C:\Program Files\ExfilGuardian\certs\ (written by the enrollment script).

F6: Zero-Touch Deployment

Status: Done

WhatWhere
Token generationserver/src/api/enroll.rsPOST /api/v1/agent/tokens
Token storageserver/src/api/enroll.rsHashSet<String> in AppState
PowerShell scriptserver/src/api/enroll.rsGET /api/v1/enroll/windows (generates script dynamically)
Static file servingserver/src/api/routes.rsServeDir for server/static/
Installer (manual alt)installer/src/main.rssc.exe create for both services

To modify the enrollment script: Edit the PowerShell template string in server/src/api/enroll.rs. The script is generated dynamically with the server IP, agent certificate, and binary download URLs embedded.


F7: Anti-Kill Process Protection

Status: Done

WhatWhere
ObRegisterCallbacksdriver/src/security/process.rsregister_process_protection()
Handle strippingdriver/src/security/process.rspre_operation_callback() strips PROCESS_TERMINATE
Registrationdriver/src/lib.rs → called from DriverEntry

To modify protection: Edit driver/src/security/process.rs. The pre_operation_callback function receives each handle-open request and can strip specific access rights. Currently strips PROCESS_TERMINATE and PROCESS_SUSPEND_RESUME.


F8: Registry Tamper Protection

Status: Done

WhatWhere
CmRegisterCallbackExdriver/src/security/registry.rsregister_registry_protection()
Key filteringdriver/src/security/registry.rsregistry_callback() blocks operations on EXFILGUARDIAN keys
Covered operationsRegNtPreDeleteKey, RegNtPreSetValueKey, RegNtPreDeleteValueKey, RegNtPreRenameKey

To protect additional keys: Edit the key name filter in driver/src/security/registry.rs. Currently only protects SOFTWARE\EXFILGUARDIAN.


F9: DKOM Bypass

Status: Done (development only)

WhatWhere
Force Integrity flagdriver/src/lib.rsfind_and_set_flag()
Module list traversaldriver/src/lib.rs → walks PsLoadedModuleList linked list
Flag modificationSets bit 0x20 on LDR_DATA_TABLE_ENTRY.Flags

Note: This is a development-only technique. In production, the driver should be signed with an EV certificate, making DKOM unnecessary.


F10: Cloud-Native Async Backend

Status: Done

WhatWhere
Server entryserver/src/main.rstokio::select! for gRPC + REST
gRPC serverserver/src/grpc/receiver.rs → Tonic-based ExfilService
REST APIserver/src/api/routes.rs → Axum router
Config loadingserver/src/core/config.rsServerConfig::load("config.yaml")
Pipelineserver/src/core/pipeline.rsServerPipeline (FlowTracker + AnalysisPipeline)
Bridgeserver/src/core/bridge.rs → gRPC NetworkPacket → analysis PacketMetadata

To add REST endpoints: Add a handler function in server/src/api/ and register the route in server/src/api/routes.rscreate_router().

To modify the pipeline: Edit server/src/core/pipeline.rs. The process_packet() method is the entry point for all incoming packets.


F11: Multi-Layer Analysis

Status: Done (analysis crate), partially wired (signature field gap)

The analysis engine is fully implemented in analysis/src/. Here's what exists and what needs work:

DPI (Deep Packet Inspection)

AnalyzerFileStatus
DNS (entropy, DGA, tunneling)analysis/src/server/dpi/dns_analyzer.rsDone
TLS (JA3, cert anomaly, SNI)analysis/src/server/dpi/tls_analyzer.rsDone
ICMP (covert channel, payload)analysis/src/server/dpi/icmp_analyzer.rsDone

Signatures

ComponentFileStatus
Rule structanalysis/src/server/signatures/rule.rsDone
Condition evaluatoranalysis/src/server/signatures/condition.rsDone (12 operators, 23 fields)
Engineanalysis/src/server/signatures/engine.rsDone
YAML loaderanalysis/src/server/signatures/loader.rsDone (hot-reload)
YAML rulessignatures/{dns,flow,icmp,tls,http}/*.yamlDone (16 rules)

Known gap: The extract_fields() function in engine.rs only populates flow-level fields (23 fields: flow.*, net.*, process.*). Protocol-specific fields used in HTTP and TLS rules (like content_length, cert_self_signed, sni_cert_match) are not yet populated. DNS, HTTP, and TLS rules that reference these fields will silently fail to match.

To fix: Add protocol-specific field extraction in analysis/src/server/signatures/engine.rsextract_fields(). The data is available in FlowRecord.dns_metadata and FlowRecord.tls_metadata; it just needs to be unpacked into the fields HashMap.

Behavioral

AnalyzerFileStatus
Baseline (Welford)analysis/src/server/behavioral/baseline.rsDone
Anomaly (Z-score, CUSUM)analysis/src/server/behavioral/anomaly.rsDone
Beaconing (CV)analysis/src/server/behavioral/beaconing.rsDone
Volume (EMA)analysis/src/server/behavioral/volume.rsDone

Correlation

ComponentFileStatus
Temporal windowanalysis/src/server/correlation/temporal.rsDone
Bayesian scoreranalysis/src/server/correlation/scorer.rsDone
Alert engineanalysis/src/server/correlation/engine.rsDone

Pipeline Orchestrator

ComponentFileStatus
Fan-out/fan-inanalysis/src/server/pipeline.rsDone
Server integrationserver/src/core/pipeline.rsDone

F12: All-Rust Ecosystem

Status: Done

All crates are pure Rust. No C, no FFI (except the kernel driver's WDK bindings which are Rust crates wrapping kernel APIs).


F13: Multi-Platform (Linux)

Status: TODO

The analysis crate already compiles on Linux/macOS. To add Linux endpoint support:

  1. Create driver-linux/: An eBPF/XDP program that captures packets (equivalent of the WFP driver)
  2. Modify agent/: Add #[cfg(target_os = "linux")] paths for reading from eBPF maps instead of DeviceIoControl
  3. Server: No changes needed; the server is already platform-agnostic

Where to Start for Each Task

"I need to add a new detection rule"

  1. Create a new .yaml file in signatures/<protocol>/
  2. Use available fields: flow.*, net.*, process.* (see engine.rsextract_fields())
  3. The rule is picked up automatically by the hot-reload watcher
  4. See Signatures for the full YAML format

"I need to detect a new protocol"

  1. Add a new analyzer in analysis/src/server/dpi/ (e.g., http_analyzer.rs)
  2. Register it in analysis/src/server/dpi/mod.rs
  3. Call it from analysis/src/server/pipeline.rsanalyze_flow()
  4. Add new ThreatCategory variants in analysis/src/types/detection.rs

"I need to add a REST endpoint"

  1. Create handler in server/src/api/ (e.g., agents.rs)
  2. Add pub mod agents; in server/src/api/mod.rs
  3. Register routes in server/src/api/routes.rscreate_router()
  4. The handler receives State<Arc<ServerPipeline>> for access to pipeline data

"I need to modify the gRPC protocol"

  1. Edit proto/exfil.proto, add fields or new RPCs
  2. Run cargo build -p exfil-server and cargo build -p exfil-agent (build.rs regenerates the code)
  3. Implement the server handler in server/src/grpc/receiver.rs
  4. Implement the client call in agent/src/main.rs

"I need to wire the frontend to real data"

  1. Implement the IPC handlers in desktop/electron/ipc/index.ts
  2. Each handler should call the Rust REST API (http://server:8080/api/v1/*)
  3. The frontend hooks in desktop/src/hooks/ already use the window.exfilguardian API
  4. Replace mock store data with TanStack Query hooks that call through IPC

"I need to change analysis configuration"

  1. Edit config.yamlanalysis.server.* section
  2. Config structs are in analysis/src/config.rs
  3. The server loads config in server/src/core/config.rsServerConfig::load()
  4. Analysis pipeline reads config in analysis/src/server/pipeline.rsAnalysisPipeline::new()

On this page