
简介这份文档是McAfee Application Change Control的测试方案面向企业安全运维人员、安全测试工程师及迈克菲产品实施者用于在正式部署前验证应用程序控制与变更控制能否按预期运行降低系统与业务变更带来的安全风险。资源包内为1个doc文件约3.2MB内容围绕MAC与MCC两大核心功能展开包含预安装要求、ePO与Solidcore部署流程以及五类评估情景的完整测试步骤与预期结果。具体来看情景涵盖应用程序控制使用与报告、可信任的更新者、镜像差异监控、文件系统和注册表监控与保护附录还给出客户端任务及其配置详细信息可直接对照执行白名单建立、禁止未授权代码运行、受限更新窗口设置、重要文件与注册表项读写保护等验证工作。文档逻辑按测试产品、安装部署、评估情景、附录分层组织步骤颗粒度细便于读者按情景独立开展评估并逐步核查ePO中的结果。目前已有47人学习适合需要落地主机加固与变更管控的安全从业者参考。1. 为什么 Application Change Control 的测试方案不能只跑一条阻断命令有次应急安全团队说这批服务器上了应用控制结果调查时被投毒的可执行文件照样跑起来了。翻策略才发现里面有条允许 C:\Windows\Temp 全目录执行的临时规则上线时忘了删。这暴露了测试方案的通病只测未授权程序被挡住从不测授权边界是否被放宽了。McAfee Application Change Control社区习惯称 Solidcore现归 Trellix 产品线在服务端是两块能力——Application Control 决定哪些程序能执行Change Control 决定哪些文件和注册表键能被改。测试方案要同时覆盖该挡的挡没挡和该放的放没放还要覆盖中间那层最容易被忽略的地带解释器、DLL 加载、授权窗口。否则策略看起来生效实际是一条规则漏一片。这套方案适合做等保合规、勒索防护基线、或者变更审计的运维和安全工程师。2. Application Control 白名单策略的测试矩阵与最小验证命令先明确一件事Application Control 的判定不是单一维度。同一条规则可以基于文件名、完整路径、证书签名、文件哈希四种方式匹配优先级和匹配范围直接决定测试结果。测试前必须知道当前策略用的是哪种否则你会得到看起来被拦了、换个目录又能跑的诡异现象。2.1 先确认运行模式和事件入口开测前先摸清三件事模块是否启用、当前是 Block 还是 Monitor、事件写到哪。多数版本上本地命令行工具是sadmin它同时承担状态查询和应急操作。# 查询整体状态确认 Application Control 处于 Enabled 还是 Disabled sadmin status # 输出当前的执行模式Block 会真正拦截Monitor 只记录 sadmin policy -get # 拉取事件日志-s false 表示不按严重级别过滤取全量 sadmin scroll -s falsesadmin status会给出 Overall status、Application Control status、Change Control status 三段。测试环境我一般保持 Block因为只有 Block 模式才能验证拦截动作本身是否生效Monitor 模式只能验证事件是否被记录两者测试目标不同别混着测。sadmin scroll的输出里有进程完整路径、父进程、命中的规则、最终判定把它重定向到文件后面做断言最省事。提示不同版本sadmin的子命令名和参数有差异动手前先跑sadmin help对齐别照搬别人的命令直接上生产。2.2 构造四类样本覆盖正例、反例和绕过我用一个固定目录承载所有样本方便清理和复核C:\ACTTest\ legit\allowed.exe # 已在策略白名单内 unknown\payload.exe # 完全未授权 rename\allowed_copy.exe # 授权文件改名后的副本 script\payload.ps1 # 通过解释器执行的脚本正例和反例好办难的是后两类。授权文件改名后如果规则是按路径匹配改名应该被拦如果按哈希匹配改名不影响判定但改内容应该被拦。这两个方向都要实测才能确定规则的真实匹配维度。# 1) 正例授权程序应正常启动 Start-Process C:\ACTTest\legit\allowed.exe # 2) 反例未授权程序应被拦截观察是否出现退出码或异常 Start-Process C:\ACTTest\unknown\payload.exe # 3) 改名绕过复制授权文件到新路径后执行 Copy-Item C:\ACTTest\legit\allowed.exe C:\ACTTest\rename\allowed_copy.exe Start-Process C:\ACTTest\rename\allowed_copy.exe # 4) 哈希篡改保留原文件名的前提下追加一个字节 $bytes [System.IO.File]::ReadAllBytes(C:\ACTTest\legit\allowed.exe) $bytes 0x00 [System.IO.File]::WriteAllBytes(C:\ACTTest\legit\allowed.exe, $bytes) Start-Process C:\ACTTest\legit\allowed.exe第 3 步验证规则是按路径还是按哈希第 4 步验证哈希匹配是否真的在起作用。如果第 4 步程序照样跑起来说明当前白名单只认路径或签名没做哈希校验这是个实打实的缺口。测试完记得把文件从备份还原别让被篡改的样本留在磁盘上。2.3 解释器滥用跳过可执行文件白名单的经典路径Application Control 最容易被绕过的地方不是可执行文件本身而是被放行的解释器。cmd.exe、powershell.exe、wscript.exe通常是系统进程策略默认放行。攻击者只要拿到一个脚本就能借它们执行任意逻辑可执行文件白名单形同虚设。测试方法很直接写一个会落地文件或回连的脚本用解释器跑看是否被拦。# 通过被放行的解释器执行脚本验证脚本内容是否被检查 powershell.exe -ExecutionPolicy Bypass -File C:\ACTTest\script\payload.ps1部分较新版本提供脚本内容扫描或脚本白名单能力能否拦住取决于现场配置必须实测。如果拦不住测试报告里要明确写出这条风险并在策略侧补脚本执行限制而不是假装没看见。2.4 测试矩阵与结果断言把上面几类样本整理成矩阵逐条对比预期和实际避免测完就忘。编号样本匹配维度预期判定实际观察点AC-01授权程序路径/哈希放行进程正常启动无事件AC-02未授权程序任意拦截scroll 出现 Block 事件AC-03授权文件改名路径 vs 哈希按路径则拦验证匹配维度AC-04授权文件篡改哈希拦截若放行则哈希未启用AC-05解释器执行脚本脚本策略取决于配置明确记录风险# 用事件日志做断言统计本轮测试产生的拦截事件数量 $log sadmin scroll -s false | Out-File C:\ACTTest\scroll.txt -PassThru $blocked Select-String -Path C:\ACTTest\scroll.txt -Pattern Block|Denied 本轮拦截事件数: $($blocked.Count)这段脚本把事件落盘后再统计好处是同一份日志既能做断言也能作为测试证据留档。注意sadmin scroll的输出格式随版本变化正则要按现场实际输出调整Block|Denied只是常见关键词。3. Change Control 的完整性监控测试从基线到授权变更Application Control 管能不能执行Change Control 管能不能改。它维护一个受保护对象的完整性数据库对象可以是文件、目录、注册表键。任何未授权的修改要么被记录、要么被拦截取决于对象是 Monitor 还是 Protect 状态。测试的核心就是把未授权修改被挡和授权修改被放这两条线都走通。3.1 确认受保护对象和它们的保护级别先列出当前受保护对象搞清楚哪些是 Prot一下ect、哪些只是 Monitor再决定测试预期。# 列出受保护的文件和目录 sadmin protect -list # 列出受保护的注册表键 sadmin protect -list -rProtect 级别的对象被修改时会真正阻断写入Monitor 级别只记事件不阻断。这两种预期完全相反测试用例必须分开写。我见过最常见的错误就是拿 Monitor 对象去测能不能改结果改成功了被误判成产品失效实际是保护级别本来就设计成这样。3.2 验证未授权修改被拦截挑一个 Protect 级别的系统文件尝试直接追加内容。# 尝试向受保护文件写入预期被拒绝 Add-Content -Path C:\Windows\System32\drivers\etc\hosts -Value # test # 尝试通过注册表编辑器命令行修改受保护键 reg add HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run /v TestKey /t REG_SZ /d test预期结果是写入报错、返回访问被拒同时sadmin scroll里应该出现一条 Change Control 的拒绝事件。如果写入成功了说明该对象实际是 Monitor 级别或者根本不在保护列表里要去sadmin protect -list里核对清楚别急着下结论。3.3 用授权窗口验证该放的能放只测拦截会漏掉一半问题如果授权流程本身失效日常运维、补丁安装、配置变更全都会卡死最后逼得管理员直接关掉保护防护也就没了。授权窗口是 Change Control 的关键机制允许指定账号或程序在限定范围内修改受保护对象。# 给指定账号开放对目标对象的修改授权 sadmin authorize -u CONTOSO\svc_deploy -m C:\App\config\app.config # 在授权账号上下文中执行变更预期成功 Set-Content -Path C:\App\config\app.config -Value new-config # 撤销授权后再试一次预期被拒 sadmin authorize -remove -u CONTOSO\svc_deploy -m C:\App\config\app.config Set-Content -Path C:\App\config\app.config -Value should-fail这段的关键是验证授权的开和关两个状态都生效。参数-u指账号-m指目标对象不同版本可能用--user、--target之类的长参数按现场help对齐。撤销授权后如果还能改说明授权没真正收回这在合规审计里是硬伤。3.4 覆盖删除、改名、硬链接这些边界操作写入拦住了不代表改不动。删除、重命名、创建硬链接指向受保护文件都是可能绕过的路径测试用例里必须包含。操作类型命令示例预期观察重点直接写入Add-Content拒绝事件类型为 Write删除文件Remove-Item拒绝事件类型为 Delete重命名Rename-Item拒绝是否被识别为修改硬链接mklink /H视策略是否绕过完整性校验通过服务修改由服务进程写入视授权授权是否绑定进程# 删除受保护文件验证删除路径是否也在保护范围内 Remove-Item C:\ProtectedDir\critical.dll -Force # 创建硬链接指向受保护文件验证完整性校验是否覆盖硬链接 cmd /c mklink /H C:\ACTTest\link.dll C:\ProtectedDir\critical.dll删除和重命名这两类操作是最容易被漏测的。很多团队只测了写入结果发现文件被删了没人管。硬链接测试更冷门但确实存在绕过完整性校验的路径值得放进回归用例。4. 把测试跑成回归参数化脚本与失败现象对照手工跑一遍能发现问题但撑不起持续验证。策略每次调整都要重跑所以要把上面的用例脚本化、参数化让不同环境能复用同一套断言。这块做得好不好直接决定测试方案是一次性交差还是能长期用。4.1 用配置文件驱动用例避免硬编码路径把样本路径、预期结果、匹配维度抽到配置里脚本只负责执行和断言。这样换环境时改配置就行不用动脚本本体。# cases.json 结构 # [ # {id:AC-02,cmd:C:\\ACTTest\\unknown\\payload.exe, # expect:block,pattern:Block|Denied} # ] $cases Get-Content C:\ACTTest\cases.json | ConvertFrom-Json foreach ($c in $cases) { # 每次执行前清空事件文件避免上一轮污染 Remove-Item C:\ACTTest\scroll.txt -ErrorAction SilentlyContinue try { Start-Process -FilePath $c.cmd -ErrorAction Stop $actual allow } catch { $actual block # 进程被拦截通常抛出 Win32Exception } $ok ($actual -eq $c.expect) [$($c.id)] expect$($c.expect) actual$actual $(if($ok){PASS}else{FAIL}) }这段脚本用退出异常来判断是否被拦简单但只能区分进程类样本。文件修改类样本要靠sadmin scroll里的事件做判断把事件解析函数单独抽出来复用。expect字段对应预期判定pattern用于事件文本匹配两边都断言才可靠——只看进程起没起来会漏掉进程起来了但事件没记录这种情况。4.2 校验事件完整性而不只是结果拦截成功只完成一半事件必须完整落地否则合规审计拿不出证据。测试时顺手校验事件字段是否齐全。-- 示意从导出的变更事件里统计字段缺失情况 SELECT event_type, COUNT(*) AS total, SUM(CASE WHEN actor IS NULL OR target IS NULL THEN 1 ELSE 0 END) AS incomplete FROM change_events WHERE event_time DATEADD(day, -1, GETDATE()) GROUP BY event_type;字段actor谁改的和target改了什么是审计最关心的两项。如果缺失率不为零问题往往出在事件转发的链路上不是产品本身要去查采集端和时间同步。4.3 常见失败现象和对应排查方向跑回归时遇到失败先按现象定位别一上来就怀疑产品坏。现象可能原因排查动作未授权程序能跑规则按路径放行了大目录sadmin policy -get看规则匹配范围授权修改失败授权对象路径写法不一致核对路径大小写、短名、符号链接事件缺失日志转发或时间同步异常查采集端时钟和转发配置撤销授权后仍可改授权缓存或进程上下文残留重启相关服务后复测Block 模式不拦模块实际处于 Monitorsadmin status确认模式# 排错第一步确认当前模式和规则再决定往哪个方向查 sadmin status sadmin policy -get | Select-String -Pattern mode|rule养成先看模式和规则、再看事件、最后看样本的顺序比拿着样本反复试要快得多。大部分所谓产品不生效最终都落在策略配置或模式设置上。5. 进阶用审核模式做灰度把测试数据变成规则清单策略直接上 Block 风险太大尤其是批量服务器。更稳的做法是先在目标机器上用 Monitor 模式跑一到两周收集这段时间里本应被拦但放行了的事件再把高频的未授权路径和哈希整理成规则差异清单作为上线评审的依据。这样上线前就有真实数据支撑而不是拍脑袋写白名单。灰度期的关键是能把事件聚合出可读的结论。下面这段脚本把sadmin scroll的导出按进程路径和父进程分组快速看出哪些是业务正常程序、哪些需要收紧。# 从灰度期事件里聚合出高频执行路径辅助判断规则松紧 $events sadmin scroll -s false | Select-String -Pattern Execute $events | ForEach-Object { ($_ -split \\)[-1] } | # 取文件名做粗聚合 Group-Object | Sort-Object Count -Descending | Select-Object -First 20 Count, Name | Format-Table -AutoSize聚出来的前 20 项里如果出现明显不该被执行的东西脚本解释器调用、临时目录里的程序就是优先要加禁止规则的如果是业务必需但没进白名单的就补白名单。区别对待别一刀切全放或全拦。另一个值得用的技巧是把 Change Control 的授权做成限时窗口。运维在窗口内改配置窗口一过权限自动收回不需要人工记得去撤销。验证方法是开窗口、改文件、窗口过期后再改一次确认第二次被拒。这三个动作能同时验证授权生效、过期生效、和过期后事件正确记录。灰度期结束后用同一套回归脚本在 Block 模式下再跑一遍把 Monitor 期的结论和 Block 期的实际拦截对照两次结果一致才说明策略真正收敛。把这段聚合脚本挂到每天定时任务里灰度期一结束就能直接产出一份可评审的规则差异清单。本文还有配套的精品资源点击获取