跳转到内容
Argus
开发版
下载GitHub
文档/架构/特权服务

特权服务

crates/argus-service 提供可选的 Windows 服务,以 LocalSystem 在后台运行。它执行已授权的进程操作、自动规则、服务控制和 IPv4 TCP 断开请求,按需查询句柄、每进程网络与磁盘计数,以及内核传感器读数。设置入口见权限。

模块

模块职责
lib.rs服务与安装助手启动分流、宿主调用入口、开发版与发布版隔离
install.rsSCM 状态查询、UAC 安装助手、受保护副本、安装/更新/启动/卸载与更新失败回退
server.rsSCM 入口、运行/停止状态、停止事件和退出清理
pipe.rs本机命名管道、有限长消息、连接身份校验、异步 I/O 与取消
protocol.rs版本化操作白名单、参数校验和 argus-core 调用
security.rsSID、管道 ACL、调用者令牌、文件及目录权限检查
network.rs服务侧的 ETW 租期、累计字节数、计数来源与代次
disk.rs服务侧的完整进程信息磁盘快照(只含 PID、创建时间和累计字节数);宿主侧的磁盘读取线程,只把最新快照交给采样线程换算速率
sensors/服务侧 PawnIO 模块、固定 CPU 寄存器配置、温度与功耗换算;宿主异步读取及过期缓存清理
driver/手动开启内核传感器时的驱动准备;固定安装包、下载与签名校验、独立 UAC 助手、SCM 身份与运行状态检查
background.rs宿主侧的规则线程和网络读取线程;只把最新结果交给采样线程
handles.rs句柄查询辅助进程的启动、Job 管理、超时续扫、部分结果回收与本地降级
taskmgr/系统任务管理器替换、恢复状态机、独立启动器和界面就绪握手

安装与授权

服务名称为 ArgusPrivileged,开发版为 ArgusPrivilegedDev。宿主仅在设置页的明确操作后通过 ShellExecuteExW 的 runas 请求管理员授权;取消 UAC 时不退出界面,也不更改服务。助手在原生窗口和单实例处理之前处理参数,避免被已运行的界面吞掉。

助手把自身程序复制到系统已知文件夹 Program Files 下的 Argus Privileged(开发版为 Argus Privileged Dev),以带引号的绝对路径注册自动启动的 LocalSystem 服务。目录、可执行文件和 owner.sid 的所有者为 Administrators,只有 Administrators 与 SYSTEM 可写;拒绝目录重解析点、不可信所有者和其他账户的写入权限。不依赖安装目录或免安装版所在的位置,复制操作不覆盖已有文件。

复制的来源是正在提权运行的 argus.exe 本身,目标目录的写权限保护在复制后生效。安装版位于 Program Files,只有管理员能写入,来源可信;免安装版若放在标准用户可写的文件夹,本机的恶意程序可以在授权前替换它,被替换的程序会以管理员身份运行并被注册为 SYSTEM 服务。这是已知且接受的风险(免安装版不校验来源),用户文档提示使用安装版或把免安装版放在仅管理员可写的位置。

owner.sid 记录安装时界面进程的 Windows 账户,即使 UAC 输入了另一个管理员的凭据也不改变授权对象。服务通过账户与令牌验证调用者:同一账户的其他中等及以上完整性级别的本机程序也可持续调用固定的管理操作。这些操作本身作用于整台电脑:结束任意非关键进程、启停任意服务并修改启动类型(只保护 Argus 自己的服务)、断开任意 IPv4 TCP 连接、以 SYSTEM 身份查询文件占用,因此授权等同于让该账户获得部分管理员能力,界面的安装确认框会逐项列出。不能借此执行任意程序、写入任意文件、更改服务可执行路径或加载驱动。其他账户、低完整性进程,以及受限令牌和 AppContainer 令牌(同一账户的沙盒进程)都被拒绝;授权对象只能是用户账户的 SID(S-1-5-21-… 或 Microsoft Entra 的 S-1-12-1-…),不接受组与内置 SID。

更新先生成新副本,再停止服务并切换 SCM 路径;配置或启动失败时尝试恢复旧路径和原来的运行状态。停止时既等待 SCM 的停止状态,也等待服务进程退出,避免删除仍被映射的可执行文件。只有确认 SCM 不再引用某个副本才清理它。卸载检查同名服务确实指向 Argus 的专用目录,停止并删除服务,再删除已知文件;不递归删除目录。失败时保留仍被引用的副本。

服务与 GUI 分开安装:安装程序的安装后钩子检测到服务的注册表项时,以 argus.exe --argus-service-refresh 在安装程序已有的管理员权限下更新服务,授权账户沿用服务目录中 owner.sid 记录的账户,失败不影响安装。这一步与设置页的“更新服务”走同一个助手:任务管理器替换处于启用状态时,先把替换所用的启动器、恢复程序和界面副本更新到新版本,IFEO 的值不变,替换保持开启,再更新服务,见系统任务管理器替换。更新失败时,GUI 首次启动检测到服务版本不一致会询问是否更新服务。卸载 GUI 时,NSIS 卸载程序检测到服务的注册表项就询问是否一并卸载;同意后以 argus.exe --argus-service-remove 走与设置页相同的 UAC 助手(先恢复任务管理器),取消授权或失败时由用户选择继续卸载 GUI 或停止。升级安装中“先卸载再安装”的就地卸载不触发这一步。

IPC 边界

  • 管道为 \\.\pipe\Argus.Privileged.v1,开发版为 \\.\pipe\Argus.Privileged.Dev.v1,拒绝远程连接。第一个实例独占创建,下一监听实例在移交当前连接前创建,避免管道名称被抢占。
  • 客户端在接入前断开时,服务断开并复用当前监听实例,继续处理后续请求;接入时的管道关闭错误(109、232、233)按单次连接结束处理。连接数达到上限时同样复用监听实例,保持管道名称占用和实例数量上限。
  • ACL 只允许 SYSTEM、提升后的 Administrators 和授权账户访问。授权账户只获得读写数据、读属性与同步权限,不获得 FILE_CREATE_PIPE_INSTANCE。原因见 Microsoft 的命名管道访问权限说明。
  • 客户端用 SCM 的服务 PID 核对管道服务端 PID,并持有进程同步句柄,避免 PID 复用。服务只给授权账户开放自身进程的查询和同步权限。客户端限制为身份识别级别,不能被管道服务端借去执行操作。
  • 服务通过管道模拟调用者,按实际令牌验证账户 SID 与完整性级别,然后恢复自身身份。恢复失败时终止服务。
  • 协议为第 9 版,保留管道名称和第 1 版 Ping 信封,以便发现旧服务并提示更新。其他请求拒绝不匹配的版本、未知操作和未知字段。请求上限仍为 16 KiB,回复上限为 1 MiB,以容纳网络累计计数和句柄结果;最多同时处理 8 个请求。读取超时 5 秒,手动操作请求超时 30 秒,后台规则、网络、磁盘及传感器请求超时 2 秒,句柄请求超时 20 秒(连接等待另限 1 秒)。I/O 取消后等待完成,再释放缓冲区。
  • 进程操作必须同时提供 PID 与正的启动时间,沿用 actions::open_instance 的校验。结束进程不接受绕过系统关键进程检查的 force 参数;不允许客户端结束自身或服务。服务控制也不能停止、更改 Argus 特权服务自身。
  • 进程操作、规则和服务控制发出后若丢失回复,执行结果未知,宿主禁止重放。非 Ping 请求的协议版本不匹配时,服务必须在执行前拒绝并关闭管道。宿主持有原服务进程的句柄并用第 1 版信封补发 Ping,确认对方使用旧协议后,才按本地权限执行。权限不足时返回 ActionError::ServiceOutdated,并提示“更新服务”。规则在该服务进程退出前也改为本地执行。周期采集、只读句柄查询及幂等的任务管理器恢复分别按下文处理。pipe.rs 使用子进程验证错版请求的拒绝行为。

系统任务管理器替换

系统任务管理器替换只通过服务提供固定的恢复操作,开启走管理员维护助手;更新与卸载先恢复系统入口。状态机、独立程序与验证边界见系统任务管理器替换。

句柄查询

FindHandles 是只读请求,使用服务的账户和完整性级别校验。服务不可用或查询失败时,宿主以当前账户权限重试并保留服务错误。协议版本过旧时可在设置中更新服务。

每次扫描启动自身程序的辅助模式,在原生窗口、单实例与采样器初始化之前分流。子进程先等待一个启动字节,父进程将它放入关闭即终止的 Job 后才放行;Job 限制为一个进程、256 MiB 私有内存。子进程不创建窗口,工作目录固定为系统目录,避免自己制造待查目录的占用。

argus-core::handles 用 NtQuerySystemInformation(SystemExtendedHandleInformation) 读取句柄表,并根据自己持有的 NUL 句柄动态识别 File 类型索引。结构布局参考 phnt,读取前检查返回长度与条目数。源进程打开后核对创建时间,再用 DuplicateHandle 复制句柄;复核类型、排除管道和设备后,以 NtQueryObject 读取名称。只关闭复制件,不关闭来源句柄。

文件优先比较卷号与文件 ID,识别硬链接;不提供文件 ID 时退回名称匹配。目录按路径分隔符边界匹配自身及其后代,不将 folder-other 算作 folder。结果包含 PID、启动时间、进程名、首个匹配路径和句柄数,Restart Manager 的结果仍用于补充加载模块等引用。

复制、名称查询、文件信息和关闭句柄都在辅助进程中进行。它在查询前发出进度游标并逐项返回匹配;父进程通过 PeekNamedPipe 读取已有字节,避免另起一个可能永久阻塞的读线程。单个游标 500 ms 无进度就终止辅助进程,保留已发现项,并从游标之后重新启动,最多重启 4 次。准备阶段限 3 秒,控制器总预算 15 秒;辅助进程本身也有 12 秒预算。超时或提前退出均返回已找到的结果,创建进程和清理资源的耗时另计。

每个父进程一次只运行一个句柄扫描;最多检查 200,000 个可查询/跳过的候选,返回 128 个进程,长名称与路径会截短显示。拒绝网络、设备、相对路径、数据流和路径穿越;目标只映射到 \Device\HarddiskVolume…,并以 OBJ_DONT_REPARSE 打开,避免 SYSTEM 被目录联接引到远程共享。链接目标可另行选择;界面仍保留 Restart Manager 的结果和限制说明。

扫描反映查询时的文件引用,也会列出允许共享删除的句柄;保护进程、权限不足、关闭/复用中的句柄和仅剩映射的文件都可能使结果不完整。界面按 PID 与启动时间合并来源,结束进程时继续使用查询时的实例信息。

自动规则与网络采样

宿主 RuleRunner 线程按 PID、启动时间和名称匹配规则。线程忙时仅保留最新快照,RPC 在释放配置与统计锁后执行。规则修改后,已发出的操作可能完成,未发出的旧操作和旧版本统计随之丢弃。

每个匹配使用一个 ApplyRule 请求,先设置效率模式,再设置显式优先级,两步都校验进程实例。一次传输失败后,本批次其余目标记为失败,不继续等待相同服务的超时;不自动重放不确定的操作。下一次规则保存或服务 PID/可用状态变化时重新检查已有进程,并清空上一轮统计。

服务首次收到 NetworkSnapshot 时启动自己的 ETW 会话,发布版名为 Argus Service Network,开发版名为 Argus Service Network (dev)。启动时清理同名残留会话,连续 15 秒无读取时关闭会话,退出时等待消费者线程结束。ETW 启动失败或消费者退出时返回不可用,重试间隔至少 30 秒。

网络回复包括来源 epoch、来源时钟(微秒)、最多 8192 个 PID 的累计收发字节与计数代次。只有服务的网络线程从 tracker 取走原始增量;不同客户端读取同一份累计计数,互不消耗数据。30 秒不活跃的条目回收,再出现时获得新代次;超过容量或计数溢出时关闭该来源并返回不可用。

宿主的 NetworkClient 只保留一个待执行读取和一个完成结果。本地 ETW 可用时优先使用本地结果;否则采样线程读取后台缓存、按来源时钟计算速率,再交给界面和历史。来源变化或观察到 PID 启动时间变化时重新建立基线,重复读取同一快照不重复计算字节。后台通信通常使网络数据落后一个刷新周期;缓存超过两个采样间隔(取本次与上一次采样中较长的节拍)加 2 秒即失效。服务断线返回空结果后隐藏网络列,恢复后的第一份数据只作基线,避免虚假峰值。

每进程磁盘读写

DiskSnapshot {} 无参数,回复仅包含来源单调时钟及最多 8192 个进程的 PID、创建时间、累计读取和写入字节数,不传输完整进程信息中的路径、命令行或账户字段;查询失败时回复 DiskFailed,只含失败类别与 NTSTATUS。后备来源为 SystemFullProcessInformation 的磁盘计数扩展,与通用 I/O 分开;不创建跟踪会话,不加载驱动,不修改系统计数开关。

普通进程查询已提供有效磁盘计数时,宿主直接使用该结果,不发起服务请求。其余情况下,DiskClient 在独立线程读取;管理员权限下查询完整信息,标准权限下通过已授权服务查询。采样线程只读取缓存并计算速率。缓存超过两个采样间隔(取本次与上一次采样中较长的节拍,窗口回到前台的第一拍仍使用上一个后台拍取得的快照)加 2 秒、服务不可用、计数器回退或进程身份变化时不复用旧值;首次观察和长间隔(超过 35 秒,最长的后台间隔 30 秒加上采样时刻的抖动)后重新建立基线。上一份快照中没有、创建时间又晚于该快照取时的进程以零为基线(来源时钟为 GetTickCount64,按本机墙上时间换算),因此新进程在下一份快照即有速率,与普通进程查询的做法一致。表头与应用分组的合计只累加有读数的进程,全部缺失时才显示为缺失,缺失值不作为零值计算。

宿主记录磁盘查询的失败来源、NTSTATUS 或 Windows 错误码,以及记录越界、响应类型错误等类别。每种原因按运行实例记录一次,最多八条。服务在回复中携带失败原因。缺少服务或管理员权限时,特权查询标为不可用。服务解析扩展记录时先检查边界,再读取定长字段。

CPU 内核传感器

SensorSnapshot {} 使用第 9 版协议及相同的令牌校验,拒绝额外字段。服务返回固定类型的温度、电压、电流、功耗、频率、限制状态、每核读数、风扇转速及主板传感器读数。模块、寄存器和 IOCTL 均由服务端固定。

模块固定为 PawnIO.Modules 0.2.11 的 IntelMSR、IntelMCHBAR、AMDFamily10、AMDFamily17、RyzenSMU 与 LpcIO,编译时嵌入签名二进制。PawnIO 模块目录 包含固定 SHA-256、上游版本、完整对应源码及 LGPL 许可证;许可生成脚本同时检查文件摘要。CPU 调用仅包含寄存器读取及固定的 SMU 表定位、刷新和读取;SMN 与 SMU 的访问通过 Global\Access_PCI 与其他监控工具协调,等待不超过 20 ms。模块本身具有的其他入口不向 IPC 开放。

IntelMCHBAR 仅在单插槽 Comet Lake S/H(Family 6、Model A5h)使用 Intel 615212-003 定义的布局,固定读取 5948h(频率与 VID)、5980h(GT 温度)、5998h(频率能力)、5918h(共享内存时钟)、5848h/5858h(GT/媒体活动计数)、5900h(限制状态)。不读取 CPU 温度来代替 GPU 温度,不写寄存器、清除锁存状态或主动唤醒 GPU。活动计数按第 9.8/9.9 节规定的 24 MHz 时基与采样时间差计算,失败、复位及过长间隔后重新建立基线。核显字段作为 CpuSensors.integratedGpu 可选快照传回,旧服务缺少字段时按不可用处理,协议请求不变。宿主按 Intel 厂商 ID、PCI 0:2:0 和唯一适配器匹配读数,不补充到独显或多插槽系统。

GPU 页区分当前频率字段与能力范围:频率字段为零时,核心频率与共享逻辑频率直接显示 0 MHz;RC6 休眠和切片关闭均可产生零频率。当前倍率按第 9.32 节的标称 16.666 MHz 步进换算,能力范围按第 9.38 节的 50 MHz 步进换算。5918h 的 QCLK 比例为 [6:0]、参考选择为 bit 7;按第 9.41 节的 DCLK = QCLK / 2 显示配置内存时钟;DDR 传输率约为 DCLK 的两倍。此布局没有已确认的实测基准时钟来源,不读取 5F60h 或套用其他代际的 [9:2]/bit 10 位域。GT/媒体活动率不覆盖 Windows 引擎利用率。核显 RAPL 功耗优先采用服务直接读取的有效 PP1 能量差分,缺失时回退 Windows 计数器;Windows 报告零值时仍优先采用有效的直接读数,厂商原生读数保持原有优先级。

设置默认关闭。服务首次收到请求后打开已经安装的 PawnIO 设备,采集线程不安装或启动驱动。模块加载失败重试间隔为 30 秒;检测到驱动出现或版本改变后立即重试,15 秒没有请求即释放模块。Intel 按处理器组设置并恢复采集线程的亲和性,单次最多读取 256 个逻辑处理器,循环预算为 500 ms。AMD 仅在单插槽配置读取节点 0;未知 CCD / 电压布局不猜测。服务读取等待有 800 ms 上限,GUI 读取在独立线程进行,采样线程不等待 RPC。过期缓存被丢弃。

手动开启开关时,宿主先确认特权服务运行且已授权,再检查 PawnIO;需要安装或启动时,以 --argus-sensor-driver-manage 启动独立 UAC 助手。该模式不接受额外参数、安装路径、下载地址或自定义服务名。固定包为 PawnIO 2.2.0,地址、大小与 SHA-256 存于 安装包清单。下载仅允许 HTTPS 及固定 GitHub 发布域名,大小与完整摘要匹配后再通过 WinVerifyTrust 验证签名和证书吊销状态。

安装程序写入 Program Files 下只允许管理员与 SYSTEM 修改的暂存目录,执行前保持文件只读句柄,阻止替换;执行参数固定为 -install -silent。不同 Argus 实例共用安装锁,等待安装程序退出后仅清理本次创建的安装文件与目录,不中途结束驱动安装。启动只接受 PawnIO 内核服务,核对受保护的官方驱动位置及最低版本,不覆盖同名异类服务。兼容版本还需核对该服务对应的 PnP 设备:服务与设备均运行正常时才视为就绪;设备被禁用时提示在设备管理器启用后重试。设备枚举带 CM_GETIDLIST_DONOTGENERATE,只枚举已有设备节点。启动完成后用固定的版本 IOCTL 确认设备可访问。仅在检查就绪后保存开启状态。关闭开关或卸载 Argus 会保留系统中的共享 PawnIO 驱动。具体传感器语义见硬件数据。

官方 2.0.1 安装包中的签名驱动没有 VERSIONINFO,driver/legacy.rs 通过文件大小与完整 SHA-256 识别已知的 x64、ARM64 官方文件;其他缺少版本资源的文件会被拒绝。迁移还要求驱动位于默认 Program Files\PawnIO,两个注册表视图中存在的卸载信息均指向此目录、版本属于 2.0,且注册表键的所有者可信。

Windows 默认的卸载项权限可包含 Terminal Server User 写权限。执行旧版卸载程序前,助手临时改名原记录,在原位置创建仅管理员与 SYSTEM 可写的副本,复制并重新校验全部值后移除原记录。更换键对象使已有写句柄无法修改新副本;复制失败时尝试恢复原记录,名称被占用时保留备份并停止。非预期子项、注册表链接或在原位置抢先创建的其他键会使迁移停止,不递归删除未知注册表内容。

官方 2.2.0 安装器仅支持从 2.1.0 直接升级,因此 2.0 迁移先准备并验证新旧两个安装包,再重新检查现有安装,使用固定的 2.0.1 安装器执行 -uninstall -silent。不执行注册表中的卸载命令。旧版安装器的地址、大小与摘要固定在 legacy-installer.json,同样验证 Windows 签名;子进程的 TEMP/TMP 指向受保护暂存目录,避免旧版卸载程序跨卷移动文件失败。旧版返回的 NTSTATUS 转换为 Win32 错误;只有卸载成功且旧服务已不存在才安装 2.2.0,服务仍在使用或待删除时停止并提示重启,不结束其他监控程序、不强制删除服务。

开启失败时,宿主向 argus.log 附加一次只读诊断快照:当前权限、特权服务状态与授权结果、PawnIO 服务类型与状态、启动类型、驱动路径所属类别、权限检查所在层级、数值版本、版本资源大小与语言/代码页、原始文件名是否符合预期、是否匹配官方旧版摘要、缺少版本资源的驱动文件大小与 SHA-256、PnP 设备数量与启动数量、问题代码和待重启标记,以及校验失败阶段和错误码。缺少版本资源时只对不超过 1 MiB 的文件计算摘要,超出上限仍拒绝;摘要一致也须通过路径和卸载信息校验。设备标记为待重启时,即使服务仍运行也要求重启后再启用。快照不加载或启动驱动;记录驱动实际路径、被拒的父目录或文件、失败 API、所有者类别、ACE 索引、类型、标志及权限掩码,不记录设备实例标识、账户名或资源中的自由文本。路径限长并转义。操作当时的失败与随后查询到的当前状态分别记录,避免重查结果掩盖原始原因。

驱动路径检查覆盖文件及各级父目录。即使驱动文件本身只读,父目录允许普通用户修改时仍会拒绝启用。错误信息分别指出驱动存储目录可写、驱动路径不安全或安装暂存目录不安全,便于管理员定位权限问题;检查过程只读。

SMU 只按内嵌精确版本布局解析,字段有限值和单位范围校验;总线短暂繁忙时最多复用 3 秒内的读数;完整表与物理地址不进入 IPC。布局来源及许可证位于 CPU 布局目录。每核能量按物理核心计数,APERF/MPERF 按逻辑处理器采样后合并;计数重置、单位变化和过长间隔重新建立基线,SMT 共享的功耗不重复相加。

Nuvoton 传感器访问使用 Global\Access_ISABUS.HTP.Method,等待不超过 20 ms。芯片 ID、BAR、厂商 ID 和固定寄存器均校验后才读取;只暂时调整配置选择器、银行选择器和监测 I/O 门控,随后恢复原值。接口不提供 PWM、风扇曲线或任意端口写入。风扇按硬件通道编号输出。主板电压和温度仅在主板厂商、型号及芯片 ID 匹配时输出;电压使用对应分压,温度先核对多路复用源,再读取固定备用寄存器。电池监测沿用固件当前的启用状态。

验证

cargo test -p argus-service 使用临时命名管道和自己创建的子进程验证通信、身份与参数校验、进程实例保护、规则执行顺序、大回复、断线和取消;模拟慢执行器与累计计数验证并发、规则重查、PID 复用和过期缓存。

cargo run -p argus-service --example sampling_bridge --release 测量真实采样上新增的队列提交与缓存读取开销,不配置规则或安装服务。

cargo run -p argus-service --example handle_lockers --release -- <绝对路径> 通过同样的隔离流程打印句柄查询结果,不安装服务或请求提权。回归测试覆盖辅助进程终止、超时续扫、结果保留和按实例合并。

诊断传递

宿主按观察到的服务状态变化记录异常停止及退出码;重复查询同一次停止保持原状态,服务重新启动、正常停止或移除后可记录下一次故障。标准权限下本地网络 ETW 因权限不足而转向特权服务的路径记为 INFO;服务侧或管理员环境中的 ETW 启动失败仍记为警告。

服务在内存中保存最近 32 条失败记录,每条最多 4096 个字符;Ping 回复通过可选字段携带记录,宿主按服务进程身份和序号去重后写入 argus.log。旧版服务可不返回该字段,旧版宿主忽略该字段,不改变协议版本。网络或传感器读取失败时,后台客户端每分钟至多额外查询一次诊断,正常采样不增加请求;驱动打开、模块加载和 ETW 失败保留原始错误码,模块的可选寄存器读取仅记首次失败。

提权助手在 GUI 日志初始化前运行,失败详情写入 %ProgramFiles%\Argus Sensor Setup 下受管理员权限保护的报告。宿主以启动时取得的进程句柄核对 PID、创建时间和退出码,并检查目录与文件权限后读取;报告不可用时同时保留助手退出码和报告读取错误。每份报告上限 256 KiB,最多保留最近 16 份。设置页和主程序仍只需提供常规诊断日志。诊断报告与操作结果分别处理,驱动和目录始终按相同规则校验。