Hashdump: bypass LSA 保护机制

目录

攻防实战中,凭据抓取一直是拿高权和横向的核心手段。不过如果目标启用了 LSA 保护(RunAsPPL),想要直接 dump 凭据就没那么简单了。虽然大多数环境默认都没开,但今年初打护网的时候还真就遇到了这种启用了的情况,因此特地记录和研究一下绕过思路。

再开始之前我们先简单理解几个概念

lsass进程

老生常谈的一个东西了,简单点说:lsass.exe是 Windows 的本地安全认证进程,主要负责帮winlogon做用户身份验证,并把验证结果转成一个进程。用户认证成功后,LSASS 会生成一个会话 token(动态口令),用于启动用户的初始 shell(比如资源管理器),之后用户启动的所有进程都会继承这个 token。lsass.exe 默认位于C:\Windows\System32`下,如果在其他位置发现同名文件,那估计八成是个马子。

(在后渗透阶段,我们常用 mimikatz 抓取凭据,其实就是通过与 LSASS 进程交互,把其中的内存凭据提取出来。)

PP保护

PP(Protected Process)是 Windows 系统中的一种保护机制,它专门用来保护系统的核心进程,比如LSASS.exe,避免这些进程被恶意软件篡改或提取数据。只有具有足够权限的程序才能访问这些进程,其他进程即使是管理员权限也无法轻易访问。

Protected Process Light(PPL 进程保护)

PPL是 PP 的扩展,增加了Protection level的概念。简单来说,就是在ppl的机制下,未经合法签名的程序不能对ppl保护的进程进行任意访问,只有非常受限的权限。它可以阻止没有管理员权限或没有合法签名的程序随意访问和修改这些受保护的进程。PPL 是在原有PP(Protected Process)机制基础上的升级,PP 是微软早期为了保护系统关键进程而提出的机制,而 PPL 则是它的轻量化版本,增加了保护级别(Protection Level) 的概念。

权限说明

  • 一个PP进程可以完全访问其他PPPPL 进程,只要它的签名级别比目标进程高或相同。
  • 一个 PPL 可以打开另一个具有完全访问权限的 PPL,只要其签名者级别大于或等于
  • 无论签名级别多高,PPL进程都不能完全访问PP 进程。

可以举个例子:想象一下,你有一份非常重要的机密文件(就像LSASS.exe 或其他系统进程),你设置了只有高层(PP)才能访问它。其他没有足够权限的人(PPL 进程)只能看到这个文件的部分内容,但不能修改它。甚至即使是管理员(PP 进程),也不能随便打开这个机密文件(PP 进程无法完全访问 PPL 进程)。这种机制相当于给关键文件设置了一个“额外的防火墙”,保护它不被轻易篡改

如何启用 LSA 保护 (RunAsPPL)

如果你想在企业环境中启用这个功能,可以按照微软提供的指南,通过创建一个组策略来配置 LSA 保护。但如果你只想在一台机器上手动启用它,其实很简单:只需要在注册表中添加一个DWORD值,命名为 RunAsPPL,并把它的值设置为 1 就可以了。

绕过LSA保护

主要总结起来可以归为三种方法:

  1. 删除RunAsPPL 注册表项并重新启动(这样会导致内存中的所有凭据被清除)
  2. 通过修改EPROCESS内核结构,禁用LSASS 进程的 PPL 标志。
  3. 直接读取LSASS 进程的内存内容,而不通过打开进程的函数。

mimikatz本身绕过

mimikatz绕过的原理为上文2,Mimikatz使用数字签名驱动程序来删除内核中 Process对象的保护标志。 自带的mimidrv.sys必须位于当前文件夹中,才能使用命令加载为内核驱动程序服务!+。然后可以通过! processprotect命令取消保护并最终访问 lsass.exe.,如图

后两种方法都需要具有读取和写入内核内存的能力。实现此目的最简单的方法是通过加载驱动程序,我们可以创建自己的驱动程序,但微软有内置的产品MSI Afterburner的RTCore64.sys驱动程序。并且它已签名,并允许读写任意内存

EnumDeviceDrivers 函数 可用于泄漏内核基地址。这可用于定位指向系统进程的 EPROCESS 结构的 PsInitialSystemProcess。由于内核将进程存储在链表中,因此可以使用 EPROCESS 结构的 ActiveProcessLinks 成员来迭代链表并找到 LSASS。

如果我们查看 EPROCESS 结构(参见下面的图 2),我们可以看到我们需要修补的 5 个字段通常都对齐为连续的 4 字节。这让我们可以在单个 4 字节写入中修补 EPROCESS 结构,如下所示:
WriteMemoryPrimitive(Device, 4, CurrentProcessAddress + SignatureLevelOffset, 0x00);

现在 PPL 已经被移除,所有传统的转储 LSASS 方法都可以使用

Python & Katz绕过

访问LSASS进程的内存,通常会去通过调用 OpenProcess 来获取这个进程的句柄,很多杀软这一步就回拦住了。但有时候,我们可以不需要直接调用 OpenProcess。比如一些其他进程例如杀软可能已经打开了LSASS的句柄,这时我们可以直接把这个句柄复制到自己的进程里,然后用它来访问LSASS 的内存。这种bypass方式可以用在绕过ppl上。因为一些没有被保护到的进程可能已经通过别的方式,比如通过驱动程序,获得了LSASS的句柄,这样我们就可以利用已有的句柄来突破RunAsPPL的防护,顺利访问LSASS。这里可以借助pypykatz:

1
pypykatz live lsa--method handledup

但是这种方法有点随机。成功的机会很大程度上取决于目标环境

PPLKiller

PPLKiller是一个内核模式驱动程序,可以利用他在所有进程上一键禁用 Protected Process Light 保护https://github.com/Mattiwatti/PPLKiller

原理是通过遍历,将 Protection.level、SignatureLevel 及 SectionSignatureLevel 都更改为 0 。

非驱动式绕过

老外写的可以不使用驱动相关的程序,来进行绕过的文章:
https://blog.scrt.ch/2021/04/22/bypassing-lsa-protection-in-userland/