1. 项目概述一次典型的本地权限提升漏洞挖掘之旅最近在分析一些主流硬件厂商的驱动和配套软件时碰到了一个挺有意思的案例。它不是什么惊天动地的远程代码执行漏洞而是一个在安全测试中非常经典却又容易被忽视的本地权限提升路径。整个过程围绕着AMD显卡驱动软件包中一个文件权限配置错误展开最终成功实现了从普通用户到SYSTEM权限的跨越。这类漏洞虽然攻击范围有限但在特定场景下比如企业内网渗透、攻防演练中价值非常高。它完美诠释了“细节决定成败”——一个粗心的默认配置就可能为整个系统打开一扇后门。这次挖掘的目标环境是Windows系统涉及的软件是AMD Adrenalin Edition显卡驱动套件。对于安全研究人员、系统管理员甚至是对安全感兴趣的开发者来说理解这类漏洞的成因、挖掘方法和利用思路远比单纯知道一个漏洞编号更有价值。它能帮你建立一种“攻击者视角”在日常开发、运维或安全加固时提前发现并堵住类似的逻辑缺陷。下面我就把这次从发现问题到完成利用的完整过程拆解开来希望能给想入门漏洞挖掘或者对Windows安全机制感兴趣的朋友一些实实在在的参考。2. 漏洞挖掘的核心思路与前期准备2.1 目标选取与攻击面分析在开始任何漏洞挖掘之前明确目标和缩小攻击面是第一步。我选择AMD显卡驱动作为目标主要基于几个考量首先它是拥有海量用户的系统级软件安装基数大影响面广其次驱动和配套控制面板软件通常以高权限SYSTEM或管理员运行并与内核交互一旦出现问题往往意味着高权限的丢失最后这类软件通常包含大量服务、守护进程、安装程序、配置文件和计划任务攻击面非常宽广。我的初步思路是进行“本地权限提升”挖掘。这意味着攻击者起点是一个已经进入系统的低权限用户例如普通用户权限目标是获取更高的权限如管理员或SYSTEM。相比于远程漏洞本地提权漏洞的利用链往往更依赖于对操作系统机制和软件行为的深度理解。常见的切入点包括服务漏洞寻找以高权限运行但配置不当的服务错误的权限、可写的路径、不安全的服务交互。计划任务分析系统或软件创建的计划任务看是否有任务以高权限执行用户可控的程序或脚本。文件系统权限检查高权限进程会访问或执行的目录、文件看低权限用户是否有权修改或替换它们。进程注入与劫持利用高权限进程加载DLL的机制通过DLL劫持或进程注入执行代码。注册表权限检查高权限进程读取的注册表键值看低权限用户是否有权写入从而影响进程行为。这次案例核心就落在了第三条文件系统权限配置错误。2.2 环境搭建与基础工具工欲善其事必先利其器。为了高效地进行分析我搭建了以下测试环境操作系统Windows 10/11 专业版虚拟机。使用虚拟机便于快照和还原避免反复重装系统。目标软件从AMD官网下载了特定版本的AMD Software: Adrenalin Edition显卡驱动安装包。在漏洞挖掘中版本锁定很重要因为不同版本的配置可能存在差异。分析账户创建一个标准的非管理员用户账户用于模拟攻击者的初始立足点。关键工具集AccessChk (Sysinternals Suite)微软官方工具用于快速检查文件、目录、注册表、服务等对象的权限是发现权限配置问题的“神器”。Process Monitor (ProcMon)同样是Sysinternals套件中的利器可以实时监控文件系统、注册表、进程/线程活动。通过过滤器设置可以精准捕捉高权限进程的所有操作。PowerShellWindows自带的强大脚本环境用于执行各种查询和自动化检查。Sysinternals的Process Explorer比任务管理器更强大的进程查看工具可以查看进程的权限、加载的模块、句柄等信息。我的策略是先安装AMD驱动软件然后使用低权限账户利用上述工具对安装后的系统进行“地毯式”扫描重点寻找那些本应以高权限运行的程序或服务所依赖的文件或目录却意外地向低权限用户开放了写入权限的情况。3. 问题发现脆弱的日志目录权限安装过程很顺利。安装完成后我切换到之前创建的低权限用户账户开始了第一轮排查。我首先使用AccessChk对AMD软件可能的安装目录进行了一次快速权限审计。一个典型的命令是检查C:\Program Files\AMD目录及其子目录的权限accesschk.exe -accepteula -wus C:\Program Files\AMD\*这个命令会递归地列出指定目录下所有低权限用户-wus参数代表Write权限 forUsers组具有写入权限的对象。很快一个路径引起了我的注意C:\Program Files\AMD\CIM\Log。AccessChk的输出显示Users组对这个Log目录拥有FILE_ADD_FILE添加文件和FILE_ADD_SUBDIRECTORY添加子目录的权限。这意味着任何登录到系统的普通用户都可以在这个目录下创建新的文件或文件夹。注意FILE_ADD_FILE和FILE_ADD_SUBDIRECTORY是Windows访问控制列表中的特定权限。拥有它们并不意味着可以修改或删除已有的文件除非文件本身权限也很松但“创建”这个动作已经足够危险。如果高权限进程会从这个目录加载或执行某些东西攻击者就可以通过“创建”一个恶意文件来实现劫持。接下来我需要确认是否有高权限进程会访问这个目录。这时就该Process Monitor上场了。我以管理员身份运行ProcMon清空现有记录然后设置过滤器路径包含C:\Program Files\AMD\CIM\Log操作包含CreateFile,ReadFile,WriteFile等文件操作设置好过滤器后我触发了一些可能会让AMD相关服务或进程活动的操作比如打开AMD Radeon Settings控制面板或者运行一个GPU负载较高的应用。ProcMon的窗口立刻开始滚动大量日志。经过筛选和分析我发现了一个关键线索一个名为AMDRSServ.exe的进程从路径看是AMD相关服务在运行时会尝试在C:\Program Files\AMD\CIM\Log目录下创建或写入日志文件。更重要的是ProcMon显示这个服务是以NT AUTHORITY\SYSTEM权限运行的漏洞的轮廓逐渐清晰一个以SYSTEM权限运行的服务AMDRSServ.exe。该服务会向一个目录C:\Program Files\AMD\CIM\Log写入文件。低权限用户Users组对这个目录拥有“创建文件/目录”的权限。这构成了一个典型的“可写目录高权限服务”的提权场景。但仅仅能创建文件还不够我们需要让服务执行我们创建的东西。这就需要进一步分析这个服务的行为细节。4. 深入分析服务行为与DLL劫持机会4.1 服务行为监控与DLL加载分析我使用Process Explorer查看了AMDRSServ.exe进程的详细信息。在“Image”标签页下可以看到它加载的所有DLL模块。同时我在ProcMon中增加了针对该进程的DLL加载监控操作类型包含Load Image。分析发现AMDRSServ.exe在启动和运行过程中会从C:\Program Files\AMD\CIM\Log目录加载一个名为log.dll此处为举例实际名称可能不同如amsg.dll或其它日志相关模块的DLL文件。这是一个非常关键的信息Windows系统在加载DLL时有一个固定的搜索顺序KnownDLLs除外通常包括应用程序所在目录。系统目录C:\Windows\System32。16位系统目录。Windows目录。当前工作目录。PATH环境变量中列出的目录。如果服务在它的搜索路径中有一个目录是低权限用户可写的并且它试图加载一个不存在的DLL或者加载一个可以被替换的DLL那么就存在DLL劫持的可能。4.2 构造攻击链结合前面的发现攻击链可以这样构造目标目录C:\Program Files\AMD\CIM\LogUsers组可创建文件。目标进程AMDRSServ.exe以SYSTEM权限运行。目标行为该进程会尝试从上述目录加载一个特定的DLL例如log.dll。攻击手法作为低权限用户我们可以在Log目录下预先放置一个恶意的log.dll文件。触发执行当AMDRSServ.exe服务启动或执行到需要该DLL的流程时它会加载我们放置的恶意DLL。由于服务是SYSTEM权限我们的恶意DLL中的代码也将以SYSTEM权限执行。这里有一个细节需要确认服务是每次都会加载这个DLL还是只在特定条件下通过多次重启服务、观察ProcMon日志我确认该服务在启动初期进行日志初始化时会尝试加载这个DLL。如果DLL不存在它可能只是记录一个错误然后继续运行如果存在则正常加载。这为我们的攻击提供了稳定的触发点。5. 漏洞利用从概念到代码实现5.1 恶意DLL的编写既然要利用DLL劫持就需要编写一个恶意的DLL。这个DLL需要满足两个基本要求导出目标进程预期加载的相同函数至少是它要调用的那个否则加载会失败。在DLL被加载时例如在DllMain函数中执行我们的提权代码。一个最简单的PoC概念验证DLL代码如下使用C语言和MinGW编译#include windows.h #include stdio.h // 假设目标进程会调用一个名为‘LogInitialize’的导出函数 __declspec(dllexport) void LogInitialize(void) { // 这个函数可以什么都不做或者简单返回只要存在即可 return; } BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: { // 当DLL被加载到进程时执行 // 这里放置提权代码 MessageBoxA(NULL, DLL Hijacked! Running as SYSTEM!, PoC, MB_OK); // 实际攻击中这里可以启动一个反向shell、添加用户等 // 例如system(net user hacker Pssw0rd /add net localgroup administrators hacker /add); break; } case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; }编译命令示例使用x86_64-w64-mingw32-gccx86_64-w64-mingw32-gcc -shared -o log.dll log.c -lws2_32实操心得在编写PoC时为了避免对系统造成实际破坏我通常先用弹窗MessageBox或创建文件的方式来证明代码执行了。在实际渗透测试中则需要替换为建立持久化后门、添加管理员用户等具体操作。另外需要搞清楚目标进程到底调用了DLL中的哪个函数可以通过逆向工程如IDA Pro分析原版DLL或者用ProcMon看加载DLL后的函数调用栈来推断。如果无法确定可以尝试使用dumpbin /exports查看原版DLL的导出函数列表进行模仿。5.2 权限利用与文件放置现在我们有了恶意的log.dll。接下来需要以低权限用户的身份将其放置到目标目录。切换到我们的低权限用户会话。尝试将编译好的log.dll复制到C:\Program Files\AMD\CIM\Log目录。由于我们有FILE_ADD_FILE权限这个操作应该会成功。copy .\log.dll C:\Program Files\AMD\CIM\Log\如果提示需要权限说明之前的权限判断有误或权限已变更。如果成功则证明漏洞可利用。触发服务加载DLL。有多种方式重启服务如果服务是自动启动且当前正在运行可以先停止再启动它。# 在管理员命令行中操作或者等待系统事件触发重启 sc stop AMDRSServ sc start AMDRSServ重启计算机服务通常随系统启动。等待服务自动重启某些服务在失败或特定事件后会自动重启。在我的测试中我选择了重启AMDRSServ服务。服务启动后几秒钟内一个标题为“PoC”的对话框弹了出来内容正是“DLL Hijacked! Running as SYSTEM!”。最关键的是这个对话框的进程所有者是SYSTEM可以通过Process Explorer查看MessageBox的进程树确认。这证明我们的恶意DLL确实在以SYSTEM权限执行5.3 利用链的稳定性与优化最初的PoC虽然成功了但存在一些不稳定因素和可优化点DLL导出函数匹配我们的恶意DLL只导出了一个猜测的函数LogInitialize。如果服务实际调用的是其他函数加载可能会失败或导致服务崩溃从而引起注意。更稳妥的做法是使用与原版DLL完全相同的导出函数转发Forwarding将除了我们劫持的函数外的所有调用都转发到系统目录下一个合法的备份DLL。隐蔽性弹窗非常显眼。在实际利用中代码应该静默执行。同时放置DLL和触发服务的行为可能会在安全日志中留下记录如文件创建、服务控制事件。需要评估目标环境的安全审计级别。持久化一次性的DLL劫持在服务更新或文件被修复后就会失效。为了实现持久化可以考虑将恶意DLL写入后进一步利用该SYSTEM权限在系统中安装后门服务、计划任务或启动项。6. 漏洞根源与安全启示6.1 漏洞的根本原因这个漏洞的产生根本原因在于软件安装程序在创建目录时设置了过于宽松的访问控制列表。C:\Program Files\下的目录默认应该只允许管理员和SYSTEM进行修改普通用户最多只有读取和执行权限。然而AMD的安装程序错误地将Log目录的“创建文件/子目录”权限赋予了Users组。这可能是由于开发或打包脚本中的错误例如在创建目录时直接应用了某个模板权限而没有考虑到该目录位于敏感的系统程序目录下。也可能是在后续的版本更新中为了便于日志收集而错误地放宽了权限。6.2 修复建议对于软件厂商如AMD而言修复方案非常直接修正目录权限在安装程序或软件初始化时确保C:\Program Files\AMD\CIM\Log目录的权限设置正确。应该移除Users组的Write、Create files、Create folders等权限只保留Read execute、List folder contents和Read权限。正确的权限应类似于SYSTEM: Full ControlAdministrators: Full ControlUsers: Read execute, List folder contents, Read安全开发生命周期将文件系统、注册表权限审计纳入代码审查和QA测试环节。使用类似AccessChk的工具进行自动化扫描。最小权限原则服务进程应遵循最小权限原则即使日志目录被篡改也应限制服务进程能执行的操作。对于系统管理员和个人用户定期权限审计可以使用脚本定期扫描Program Files、Program Files (x86)、Windows\System32等关键目录下是否存在配置不当的权限。PowerShell的Get-Acl命令可以辅助完成这项工作。及时更新关注厂商安全公告及时安装驱动和软件更新。使用专用工具部署端点检测与响应解决方案它们通常能检测到异常的DLL加载和文件创建行为。6.3 对漏洞挖掘者的启发这次挖掘过程展示了一条清晰的本地提权漏洞挖掘路径目标选择关注以高权限运行的系统级软件、驱动、服务。信息收集安装软件枚举其创建的服务、进程、计划任务、文件和目录。权限分析使用AccessChk等工具快速定位低权限用户可写的高权限进程资源文件、目录、注册表键、命名管道等。行为监控使用ProcMon等工具动态分析高权限进程如何访问这些资源。重点是“写”之后能否“执行”或“影响执行流”。构造利用根据进程行为如加载DLL、执行脚本、读取配置文件构造相应的恶意载荷恶意DLL、脚本、配置文件。验证与优化在测试环境中验证利用链的有效性并优化利用的稳定性和隐蔽性。这种基于权限配置错误的漏洞逻辑清晰不需要复杂的逆向工程非常适合作为漏洞挖掘的入门练习。它提醒我们在安全评估中不能只盯着代码层面的缓冲区溢出这些“配置层”的疏忽同样能带来严重的安全风险。7. 拓展思考与类似漏洞模式这次发现的“可写目录DLL劫持”模式只是本地提权漏洞的冰山一角。在实际挖掘中还有许多类似的模式值得探索可写服务路径如果服务的“ImagePath”存储在注册表HKLM\SYSTEM\CurrentControlSet\Services\ServiceName中指向的目录是低权限用户可写的攻击者就可以将合法的服务exe替换为恶意程序重启服务后即获得权限。不安全的服务权限服务本身的访问控制列表配置错误允许低权限用户修改服务的配置如SERVICE_CHANGE_CONFIG从而可以更改其执行的二进制文件路径。计划任务权限计划任务Task Scheduler的XML定义文件或相关操作如运行程序所在的目录权限配置不当允许低权限用户修改任务内容使其执行恶意代码。安装程序回滚漏洞一些安装程序或更新程序在失败回滚时会以高权限删除或移动文件。如果回滚逻辑存在竞争条件Time-of-Check Time-of-Use攻击者可以在检查之后、移动之前将目标文件替换为指向恶意程序的符号链接Symbolic Link。注册表键权限高权限进程会读取某些注册表键值来获取配置。如果这些键值允许低权限用户写入就可以通过篡改配置来引导进程执行恶意操作。挖掘这类漏洞本质上是一场“权限与信任”的审计游戏。你需要不断追问这个高权限的实体进程、服务、任务信任了哪些来自低权限环境的数据或资源这种信任是否被过度授予了通过系统性地回答这些问题往往就能发现通往系统最高权限的隐蔽小径。