getsystem底层原理:从令牌机制到服务模拟的提权组合拳
有过内网测试经验的人基本都敲过这个命令Meterpreter 里直接输入getsystem几秒钟后getuid显示NT AUTHORITY\SYSTEM一条管理员会话就这样变成了系统权限。很多人把它当成“提权玄学”但仔细拆开看这个命令背后的逻辑一点也不神秘——它只是把 Windows 令牌机制、服务机制和进程模拟机制组合起来替你尝试了各种可行的“换身份”路径。这篇文章我会把getsystem的底层原理拆开讲清楚包括它到底动了哪些 Windows 权限对象、为什么有时一下就成功有时反复失败、以及防守方该从哪些维度拦住它。无论你是刚开始学内网渗透测试还是已经在做安全防御这篇文章都值得花几分钟读完。看完你会明白getsystem不是“一条命令搞定提权”而是一整套权限切换思路的集合理解这套思路比记住命令本身有用得多。1. 先说结论getsystem 不是万能提权而是一套权限提升的组合拳1.1 一条命令的背后为什么管理员权限还不够很多人第一次产生疑惑是在一个奇怪的现象里明明已经是管理员账户了但在拿到会话后执行某些命令还是提示“拒绝访问”尤其是访问注册表 SAM 键值、读取 LSASS 进程的内存、或者加载驱动这类操作。这是因为 Windows 里有两套“身份”体系在一同起作用一套是账户 SID你是谁另一套是特权你能做什么。Administrator账户虽然能通过 UAC 提升到管理员权限但它并不是 Windows 系统里权限最高的身份。真正掌管系统内核级操作的是LocalSystem也就是我们常说的 SYSTEM 账户。它是一个独立于所有用户的基础系统账户SID 是S-1-5-18几乎所有系统服务、驱动加载、SAM 数据库读取都要求进程至少以 SYSTEM 身份在运行。管理员能做很多事但和 SYSTEM 之间还隔着一道明显的权限墙。getsystem就是为了跨过这道墙而存在的。它的目标很纯粹把当前 Meterpreter 会话所在的进程身份切换成 SYSTEM。如果会话本身已经是 SYSTEM它会告诉你已经具备权限如果不是它就会尝试用各种机制去拿一个 SYSTEM 令牌然后用这个令牌去创建新进程或替换当前进程的身份。1.2 实测中 getsystem 的行为逻辑自动尝试与手动指定在默认情况下直接执行getsystem时命令后台会按照一组预设的技术列表逐个尝试。不同能力和场景下它会优先尝试当前会话具备条件的技术。比如当前进程有足够特权那就直奔令牌相关技术如果当前账户具备服务创建权限则可能走服务路径。你可以用getsystem -h查看参数常见的是-t指定技术编号。不同版本的 Meterpreter 对技术编号的实现有差异有些版本的技术列表是服务方式、命名管道模拟、令牌复制有些版本会有更多细分。老实说我见过不少人习惯于反复执行getsystem直到成功但这并不是一个好习惯因为默认自动模式会浪费不少时间在不适用的技术上。理解每种技术的适用条件才能做到“知其然也知其所以然”也能在失败时准确定位问题。2. 原理地基访问令牌、特权与进程身份的底层关联2.1 Access Token 到底存了哪些东西Windows 里的访问令牌Access Token是一个内核对象它描述了一个进程或线程的安全上下文。你可以把它想象成一张工牌上面写着你是谁、属于哪些组、有哪些权限。进程在创建时会关联一个主令牌Primary Token线程在执行时还可以临时挂上一个模拟令牌Impersonation Token用来以别的身份执行一部分操作。令牌里主要包括用户 SID 和组的 SID 列表特权列表Privileges所有者、默认 DACL令牌类型主令牌或模拟令牌完整性级别Integrity Level其他安全属性当你执行getsystem时本质上就是在寻找一个 SYSTEM 令牌然后把当前会话挂载到那个令牌上。SYSTEM 令牌和普通管理员令牌最大的区别并不是“用户名叫 SYSTEM”而是它的特权列表里几乎包含了所有关键特权同时它的完整性级别是系统级别可以访问大多数保护程度较高的系统资源。2.2 特权列表才是提权目标SeDebugPrivilege 与 SeImpersonatePrivilege在 Windows 的权限模型里特权有时比 SID 更重要。getsystem涉及的几个关键特权是SeDebugPrivilege允许调试他人进程也就是可以用OpenProcess打开系统进程句柄从而读取 SYSTEM 进程的令牌。这是令牌复制技术的地基。SeImpersonatePrivilege允许线程模拟某个已认证用户。这是命名管道模拟和 Potato 类技术的核心。SeAssignPrimaryTokenPrivilege允许把令牌分配给主令牌某些场景下需要用它来创建新进程。很多初学者以为“管理员就是一切”这是误解。就算你是管理员如果系统策略显式收回了这些特权getsystem也可能失败。反过来有些服务账户虽然不是管理员但具备SeImpersonatePrivilege反而可以通过 Potato 类技术轻松拿到 SYSTEM 令牌。这也是为什么在实战中不一定要追求“管理员会话”一个服务账户的会话有时更具提权潜力。2.3 主令牌与模拟令牌为什么“换个身份”不是简单的赋值令牌分为主令牌和模拟令牌两者在 Windows 内部的使用场景不同。主令牌决定一个进程的完整身份用来执行大多数系统调用模拟令牌是线程临时借用来的身份只能用于执行某些操作不能直接作为新进程的主令牌。getsystem在做的事情通常是把获取到的 SYSTEM 令牌经过DuplicateTokenEx复制转换变成一个新主令牌然后用CreateProcessWithTokenW或CreateProcessAsUser创建出真正以 SYSTEM 身份运行的新进程。如果是模拟令牌则需要先提升模拟级别再转换令牌类型否则很多操作仍然受限。理解了主令牌和模拟令牌的区别你就能明白为什么有时提权之后还要迁移进程或者为什么明明是 SYSTEM 却仍然打不开某些进程——大概率是令牌类型或模拟级别不对。3. getsystem 的几种底层实现逐个拆解3.1 谁的令牌可以偷目标进程的选择逻辑令牌复制技术的第一步是找到一个合适的“持卡人”——一个正在以 SYSTEM 身份运行的进程。常见目标包括winlogon.exe登录进程以 SYSTEM 运行services.exe服务控制管理器以 SYSTEM 运行lsass.exe本地安全认证进程以 SYSTEM 运行svchost.exe很多系统服务宿主进程多数也是 SYSTEM选择目标进程时有一个讲究进程的完整性级别和保护级别。Windows 8 之后引入了受保护进程Protected Process LightPPL比如lsass.exe在某些配置下受保护普通进程即使拥有SeDebugPrivilege也很难打开。所以在老系统上喜欢打lsass.exe的思路在现在不一定好用反而是winlogon.exe和services.exe更容易成为突破口。拿到目标进程句柄后调用OpenProcessToken打开令牌再调用DuplicateTokenEx复制成新的主令牌整个链条就完成了大半。3.2 令牌复制提速DuplicateToken CreateProcessWithToken这是最容易理解、也最经典的一条路径。我用一个简化的 API 调用序列来说明HANDLE processHandle OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, targetPid); HANDLE tokenHandle NULL; OpenProcessToken(processHandle, TOKEN_DUPLICATE | TOKEN_QUERY, tokenHandle); HANDLE newToken NULL; DuplicateTokenEx(tokenHandle, TOKEN_ALL_ACCESS, NULL, SecurityImpersonation, TokenPrimary, newToken); CreateProcessWithTokenW(newToken, LOGON_NETCREDENTIALS_ONLY, LC:\\Windows\\System32\\cmd.exe, NULL, ...);这段代码展示了核心思想从 SYSTEM 进程那里“借”令牌复制出一个主令牌再用这个新令牌创建进程。创建出来的进程就是 SYSTEM 权限。Meterpreter 的getsystem在成功获取令牌后往往不是直接在当前进程里切换而是让会话以新身份继续运行。这也是为什么getsystem之后有时会有短暂的停顿因为后面可能在启动一个新进程来完成会话接管。这条路径能不能成功最大的变量是OpenProcess能否拿到目标进程句柄。如果你没有SeDebugPrivilege系统会直接拒绝你打开 SYSTEM 进程所以那些“普通用户跑 getsystem”的想法在这条路径上基本不会成功。3.3 服务方式提权临时服务为何能直接 SYSTEM服务方式是一条非常稳定的提权路径。Windows 服务控制管理器SCM在启动服务时默认以LocalSystem身份创建服务进程。如果你当前账户具备创建服务的权限就可以创建一个临时服务指定一个需要执行的命令然后让系统帮你以 SYSTEM 身份把这个命令跑起来。流程大致如下调用OpenSCManager打开服务控制管理器调用CreateService创建一个临时服务指定服务类型、启动方式和执行路径调用StartService启动这个服务命令执行完成后调用DeleteService清理痕迹关键点是CreateService默认创建的服务会以SERVICE_LOCAL_SYSTEM账户运行。所以哪怕你只是一个有服务创建权限的管理员也可以利用这个机制轻松获得一个 SYSTEM 身份来执行指定程序。这条路径最怕的是防护软件盯上服务创建行为。现在的 EDR 基本都会监控CreateService和StartService的关键调用临时服务突然出现又消失本来就是一个典型风险信号。我见过不少场景getsystem走服务方式时被杀软直接干掉了临时服务进程导致会话异常退出。遇到这种情况可以考虑先迁移到一个可信的进程中再尝试或者服务进程的路径尽量伪装成系统常见路径而不是直接用临时目录。3.4 命名管道模拟与 Potato 家族SeImpersonatePrivilege 的高价值命名管道模拟的路线更像一种“借力打力”的思路。攻击者不需要直接打开 SYSTEM 进程而是创建一个命名管道然后想方设法诱导一个 SYSTEM 权限的进程向这个管道发起连接请求。Windows 在服务端接受到命名管道连接时会执行ImpersonateNamedPipeClient从而在管道服务线程上获得客户端的模拟令牌而这个客户端是 SYSTEM所以模拟令牌也就是 SYSTEM 令牌。网上常说的 Potato 家族利用的是 Windows 的各种 RPC 接口中某些“受害者会自动回连”的特性。比如某些系统组件会以 SYSTEM 身份主动去连接指定的 RPC 服务攻击者通过中间人的方式把这次连接引到自己的命名管道上来在连接建立的瞬间调用ImpersonateNamedPipeClient就拿到了 SYSTEM 模拟令牌。这条路径的核心前置条件是当前进程必须拥有SeImpersonatePrivilege。而很多服务账户、IIS 应用池账户天生具备这个特权因此 Potato 家族在实战中的价值相当高。getsystem的部分新版本也已经把命名管道模拟纳入技术列表所以当你对一个服务账户会话执行getsystem时成功路径往往不是令牌复制而是这种模拟技术。3.5 各种实现技术的适用场景对比技术类型核心前置权限关键 API 或机制典型适用场景主要风险令牌复制SeDebugPrivilegeOpenProcessToken / DuplicateTokenEx已拿到管理员会话或高特权账户受保护进程拦截、EDR 监控进程句柄服务方式服务创建权限CreateService / StartServiceCentOS、Windows 服务类环境管理员权限杀软监控服务创建与启动命名管道模拟SeImpersonatePrivilegeImpersonateNamedPipeClient服务账户、IIS 应用池账户依赖系统版本部分新系统已缓解4. 实战操作从输入 getsystem 到确认 SYSTEM 的完整链路4.1 参数选择-t 技术编号该怎么理解getsystem的参数并不多最重要的是-t。不过不同版本的技术编号不完全相同所以最稳妥的做法是先执行getsystem -h看本机的技术列表。通常你能看到类似这样的输出Usage: getsystem [options] OPTIONS: -t opt Technique to use if you want to force a specific technique这里的-t后面跟的数字对应不同的实现方式有的版本里 1 表示服务方式2 表示命名管道模拟3 表示令牌复制。不要死记硬背某个编号因为 payload 升级后技术顺序可能变化。我的经验是先用默认自动模式跑一次如果失败再用-t逐项试观察每项技术失败时的提示能帮你更清楚地判断当前会话到底缺什么条件。4.2 一次完整的命令行演示假设我现在已经拿到一个 Meterpreter 会话先看当前身份和特权再执行提权meterpreter getuid Server username: LAB-DEMO\UserA meterpreter getprivs Enabled Process Privileges: SeDebugPrivilege SeTcbPrivilege SeAssignPrimaryTokenPrivilege ... meterpreter getsystem ...getsystem: Service technique failed. (Next technique: 2/3) ...getsystem: Named Pipe technique succeeded. meterpreter getuid Server username: NT AUTHORITY\SYSTEM从SeDebugPrivilege存在开始我就知道会话具备令牌类技术的条件而SeTcbPrivilege的存在意味着会话本身已经有较高的系统权限。实际执行时我看到前一个技术失败、后一个技术成功这说明自动模式在按顺序尝试遇到不适用的技术会跳到下一个直到成功或全部失败。提权后再次执行getuid确认身份已经切换为NT AUTHORITY\SYSTEM这一步不能省略因为不是所有输出都明确写着成功。4.3 常见失败信号与排查路径最让人头疼的自然是getsystem执行之后直接返回失败。我遇到的失败场景大致可以归为以下几类现象可能原因排查方式Failed to get SYSTEM当前用户权限过低令牌复制打不开系统进程先尝试 UAC 绕过或换一个管理员会话再执行进程消失或会话掉线杀软拦截了服务创建或进程注入检查杀软日志尝试其他技术编号或迁移进程一直卡在某个技术编号当前会话架构与系统位数不匹配确认是 x86 还是 x64 Meterpreter必要时迁移到相同位数进程The token is already elevated当前本来就是 SYSTEM 或等效权限直接用getuid验证特定技术编号报错该技术依赖的特权被禁用或系统版本不支持逐项测试其他技术编号优先走-t手动模式另外一个常见的坑是进程位数。如果你的 Meterpreter 是 x86 版本运行在 64 位系统上在尝试打开某些 64 位 SYSTEM 进程时可能会遇到兼容性问题导致OpenProcess失败。解决办法是先把 Meterpreter 迁移到一个同为 x64 的进程中再重新执行getsystem。4.4 提权后的权限验证与局限性提权成功后建议做两件事。第一执行getuid确认当前身份已经变成NT AUTHORITY\SYSTEM第二直接执行某个需要 SYSTEM 权限的操作来验证实际能力比如尝试读取注册表 SAM 键值或者执行ps查看当前会话是否能够列出所有进程。有些场景下虽然getuid显示 SYSTEM但令牌是模拟令牌完整性级别不一定够。此时可以执行shell进入一个交互式命令行用whoami /all看看当前令牌的完整信息。还要明白getsystem的局限性它不是一个“从普通用户直接变 SYSTEM”的万能工具。多数技术路径都要求会话本身已经是本地管理员或至少具备某些高级特权。如果当前会话是低权限普通用户直接调用getsystem大概率会失败这时候应该先想办法提升到管理员权限再做 SYSTEM 级提权。5. 防守方视角怎么让这套组合拳失效5.1 削减令牌攻击面既然getsystem的核心是拿到 SYSTEM 令牌那防守重点就很明确了让令牌不能被轻易获取和复制。具体可以做的事不少移除普通管理员不必要的SeDebugPrivilege对关键系统进程启用受保护进程PPL尤其是lsass.exe开启 Credential Guard让 LSASS 进程内维护的凭据得到隔离保护限制管理员账户的令牌窃取能力通过组策略调整用户权限指派实战中我遇到过不少系统其实已经做了部分加固执行getsystem时能看到打开了目标进程但后续的令牌复制被拒绝原因就是 PPL 或 Credential Guard 介入了。这说明检测侧不需要等到进程创建才告警令牌相关 API 的调用本身就很值得关注。5.2 服务创建与管道模拟的检测维度服务创建是一条非常容易被防守方发现的路径。比如可以通过以下事件监控服务创建与启动Windows 事件 ID 4697服务创建Windows 事件 ID 7045服务安装系统日志进程创建事件中父进程是 services.exe 的可疑进程使用svchost.exe -k之外的可执行路径命名管道模拟的检测则更隐蔽但也不是无迹可寻。关键看两个点进程是否创建了命名管道以及是否调用了ImpersonateNamedPipeClient。在 EDR 的监控规则里这两类调用的组合出现是 Potato 类攻击的典型特征。另外高权限进程主动连接低权限进程创建的命名管道本身就是一个异常行为可以通过管道创建与访问的审计来发现。5.3 测试工作的边界授权与还原这里必须多说一句。getsystem也好更底层的提权技术也好都应该只在明确授权的环境中使用。做测试时我会在项目开始时记录当前会话权限、系统版本、补丁情况提权成功后及时做截图留档测试结束时把临时创建的服务、计划任务都清理干净恢复到初始状态。这既是对目标系统负责也是安全测试的基本职业素养。不要为了“看起来厉害”就无边界地使用这些技术合规才是最重要的底线。6. 写在最后一点个人经验说实话我第一次成功执行getsystem是在本地虚拟机里当时我以为是某种“玄学命令”敲下去就成功了。后来仔细读完系统原理和相关的实现代码才发现这个命令只是在不断尝试“换一张更高级的工牌”。当你真正理解了令牌、特权、服务、命名管道这些机制后再回头看getsystem它就不再有神秘感了。最后分享一个排查小技巧如果你在目标机上发现当前会话是普通用户别急着反复敲getsystem。先确认会话有没有可用的提权路径比如 UAC 绕过、已知漏洞或服务配置弱点。先把权限提成管理员再执行getsystem成功率会高得多也节省大量时间。理解这条路之后你会发现真正的提权能力不在于命令本身而在于对 Windows 安全模型的理解深度。