本文的目的是深入了解黑客世界中最隐藏的秘密以及他们最神圣工具的内部工作原理,或者它可能只是一篇如何读取和解析 LSASS 内存转储的文章。
TL; DR
一个基于 PowerShell 的工具,用于解析 LSASS 转储PowerExtract。
挖掘内存是为了什么?
在我们动手(和奇思妙想)之前,第一个问题是我们为什么要这样做?
是的,这是一个好问题。因此,退一步来说,当黑客登陆目标计算机(并且假设它运行的是 Windows)时,一个重要的步骤就是收集凭据。Windows 内有多个有趣的目标,但有两个首选凭据存储 - 本地安全数据库(安全帐户管理器)和 LSASS(本地安全机构子系统服务)进程。Microsoft对登录过程和所涉及的过程进行了很好的记录。
Windows 的安全帐户管理器(简称 SAM)数据库位于注册表 - SAM 配置单元内。该配置单元保存本地帐户(例如本地管理员)的凭据。因此,这对于本地网络内的密码重用攻击可能很有趣 - 但由于 LAPS(本地管理员密码解决方案)或其他机制的进一步分发和使用,这个向量变得越来越没有吸引力(我正在看你 LocalAccountTokenFilterPolicy )。下图是根据微软文档制作的。
LSASS 进程是一种不同类型的动物 - 在 Windows 中,该进程负责管理身份验证。这意味着该进程是处理来自不同服务的身份验证请求的中央枢纽。由于 Windows 已针对单点登录体验进行了调整,因此此过程捆绑并构建了身份验证流程。这意味着,在此过程中实现了不同的身份验证包,例如 NTLM、Kerberos、WDigest 等。此外,此过程管理并存储这些凭据包当前使用的凭据。非常复杂、有价值,并且充满了有趣的东西 - 黑客的完美目标。因此,LSASS 进程保存当前 Windows 会话(所有登录身份)的各种凭据(以加密和散列形式)。因此,当我们想要破坏整个活动目录基础设施时,我们需要网络凭据 - 这些凭据(通常)存储在 LSASS 进程中。
这里有一个小问题 - 注册表数据库中的秘密可以从系统硬盘中离线提取。LSASS 进程仅在系统运行时保存敏感信息(在某些情况下,甚至当系统处于半活跃状态时,如快照中)。
所以,现在应该很清楚 LSASS 过程是一个有价值的目标。那么我们如何进去(或者有价值的东西出去)呢?- 是的,这是一个重要的问题。目前已知有两条主要途径可以做到这一点:
-
live - 该进程将在运行时(通常具有调试权限)期间被触及并提取秘密 -此方法最流行的工具是Mimikatz。根据我个人的经验,这种方式通常很吵,并且可以被各种防病毒和 EDR 解决方案检测到。此外,您需要混淆Mimikatz二进制文件,以便能够在您的目标上执行它。
-
内存转储 - 对于此方法,将转储 LSASS 进程。这意味着该进程的全部内容将被写入一个文件中。生成的转储文件包含秘密。当然,这种方法也会引起 AV 和 EDR 的一些关注——具体取决于方法,但它通常比尝试执行Mimikatz和接触实时进程更成功。
因此,正如本文标题所述,我们将重点关注从 LSASS 转储中提取凭据 - 第二种方法(第一种方法稍微复杂一些)。不,如何获得这样的转储文件也不是本文的一部分(这样的转储文件太多了:P) - 所以让我们开始挖掘吧!
你能读懂吗?
我们确定了为什么要读取 LSASS 内存转储 - 那么我们该怎么做呢?
此外,由于我个人的野心和受苦的意愿 - 我们可以使用内置的 Windows 工具(最好是 PowerShell)来做到这一点吗?
为了能够读取某些内容,我们需要了解我们想要读取的数据的结构 - 在我们的例子中是小内存转储。到目前为止,我还没有找到一张漂亮(且简单)的图片来解释内存转储的内部结构。于是,我尝试自己画一张:现在为了更好地理解结构,这里有一些解释:
-
标头 - 文件以标头开头,其中包含有关文件的基本信息,如版本、时间戳等。用于进一步分析的相关信息是“NumberOfStreams”和“StreamDirectoryRVA”。其余数据被组织在不同的“流”中,其中包含多种类型的信息(例如,系统信息、凭证等)。
-
目录 - 因此,对于我们想要解析的每个流(由 NumbersOfStreams 表示),我们需要识别流的类型以及开始和结束地址。这为我们提供了内存转储的目录。
-
数据流 - 现在我们可以根据指示的类型解析每个可用的流。这意味着当识别到流类型“7”时,它被映射到“SystemInfoStream”,因此需要使用相应的模板来解析流的数据。
在转储中有多个流 - 为了获得我们想要的东西(提醒 - 哈希值、票证等),我们“仅”需要以下流。
-
ThreadListStream:包含有关转储时运行的线程的信息,包括线程 ID、堆栈跟踪和寄存器值。
-
ModuleListStream:提供有关进程地址空间中加载的模块(DLL 和可执行文件)的信息,包括模块名称、基址、大小和文件路径。
-
MemoryInfoListStream:包含有关内存区域的信息以及分配基础等其他详细信息。
-
ThreadInfoListStream:存储线程状态信息。
-
SystemInfoStream:提供转储时的一般系统信息,例如操作系统版本、处理器体系结构和其他特定于系统的详细信息。
-
Memory64ListStream:与 MemoryListStream 类似,但提供 64 位内存地址的扩展信息。
这让我们对结构有了一个粗略的了解。现在——我们如何阅读它?
如前所述,我个人想使用 PowerShell 来完成此操作。因此,在 PowerShell 中,有多种方法可以读取文件 - 我尝试了“获取内容”等方法 - 但这会导致内存使用量较高,并使导航变得相当困难。我通过“ System.IO.FileStream ”获得了最好的结果,它提供了对原始文件内容的直接访问。结合“ System.IO.BinaryReader ”方法,我们可以按字节读取文件的内容,这正是我们需要的详细程度。
$PathToDMP = "C:Templsass.dmp"
$fileStream = New-Object –TypeName System.IO.FileStream –ArgumentList ($PathToDMP, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read)
$fileReader = New-Object –TypeName System.IO.BinaryReader –ArgumentList $fileStream
$fileReader.BaseStream.Position=0
$Signature = ([System.BitConverter]::ToString($fileReader.ReadBytes(4))).replace('-','')
...
现在我们知道我们想要读取什么以及如何使用 PowerShell 按字节读取文件 - 结果如下图所示。这使我们能够根据文档解析不同的流。让我们开始提取美味的部分。
凭证提取
在我们开始研究花哨的记忆内容之前,我们应该关注我们想要提取的内容。正如一开始所解释的,LSASS 过程相当复杂,包含多个凭证包。因此,没有一个中央凭证存储可以处理所有事情。实际上,每个凭证包都拥有自己的凭证。因此,我们需要决定从哪个包开始 - 由于文章已经很长,我们采用简单的包 - 登录密码(Kerberos 稍微复杂一点)。保存登录密码的凭据包称为“MSV1_0”。
幸运的是,凭证不是以明文形式存储的 - 它们是加密的,因此我们需要获取加密材料以确保 NT 哈希值、密码等可以解密。
重点
那么在哪里可以找到加密材料呢?这是最巧妙的部分:所需的密钥也存储在 LSASS 进程中,因此也存储在转储中。那么我们怎样才能找到它呢?
微软在这里发挥了创意——因为密钥的存储位置取决于Windows版本、lsasrv.dll版本和底层系统架构。因此,我们需要知道创建 LSASS 转储的系统版本 - 您还记得我们解析的不同流吗?- 太好了,这里我们可以从“SystemInfoStream”中提取相关信息。该流包含“ProcessorArchitecture”和“Buildnumber”。
此外,我们需要从“ModuleListStream”中提取“lsasrv.dll”的时间戳。通过收集到的信息,我们可以选择正确的加密模板。该模板定义了某些模式和偏移量来识别内存结构内的加密材料。Windows 版本之间也有所不同。
以下清单显示了一个示例加密模板:
Pattern : 8364243000488D45E0448B4DD8488D15
AES-Offset : 16
IV-Offset : 58
DES-Offset : -89
key-handle : Get-BCRYPT_HANDLE_KEY
key-struct : Get-BCRYPT_KEY81
该模板由一个模式组成,该模式是所有后续操作的起点 - 因此我们需要首先找到该模式。LSASS 进程的加密材料是运行时数据 - 这意味着它在每次重新启动后都会更改(是的,我知道我指出的是显而易见的)。那么,我们在哪里寻找这个模式呢?- 你还记得下面这张图吗?是的,凭证管理的中心实例(对于像“MSV1_0”这样的凭证包)是“lsasrv.dll”。在这个 dll 中,还存储了加密材料。“ModuleListStream”为我们提供了该模块在内存中的起始和结束地址。因此,我们知道在哪里搜索指定模式的区域。获取模式的地址后,我们可以从加密材料的不同部分开始。IV、DES 和 AES 密钥彼此独立。因此,无论我们首先获取 IV 还是 DES 密钥,都无关紧要。这是一个简短的总结:
-
IV - 提取 IV 的步骤是 - 我们需要将 IV 偏移添加到已识别模式的地址。我们需要提取四个字节——这是一个指向 IV 数据的指针。现在我们需要将 IV 偏移量、提取的指针和四个字节添加到模式的地址中 - 这样我们就得到了 IV。 -
DES / AES - DES 和 AES 密钥的过程是相同的(但具有不同的偏移量) - 因此我们通过将偏移量添加到模式地址来重新开始。这让我们再次看到一个指针,我们在其中提取四个字节。在下一步中,我们将提取的指针和偏移量添加到模式地址,这将我们带到密钥句柄。该句柄有点特殊,因为这是我们需要解析的附加结构的起点(在我的脚本中,我将其称为 BCRYPT_HANDLE_KEY)。在解析该结构的过程中,我们能够提取一个指针 - 这将我们带到关键结构。此外,这里可以应用不同类型的结构来解析密钥数据(您可能会注意到加密模板中的“key-struct”条目)。根据模板提供的关键结构,
下面是结果的示例:
DESKey : 1CD7CCC70EA46FAA77DE8F592695A71A454A20F425A0758A
IV : 2AF4C45FD1786BA8D237DA9166E51CF5
AESKey : 48FE7A5E250B8336F51C4E1BA51AF879
太好了,现在我们已经获得了加密货币,我们是否可以获得一些哈希值或什么?
NT哈希值
在哈希下雨之前——我们需要找到它们。为了确定这些信息的存储位置,我们需要提醒我们
-好吧,我们想要登录密码以及 LSA 进程如何处理这些密码?
基本上,凭据最初由 Winlogon 进程提供并发送到 LSA 进程。这里LSA进程调用MSV1_0凭证包来处理这些。MSV1_0 包将凭据与内部 SAM 数据库(注册表配置单元)中的凭据进行比较,或者使用 netlogon 协议将它们发送到域控制器。因此此凭据包还保存系统运行时期间的登录凭据。
因此,我们需要识别内存转储中的 MSV1_0 凭证包 - 为此,我们遵循与加密材料类似的过程。目前我不知道如何完成此操作的官方文档,因此我使用Pypykatz和Mimikatz作为参考来做到这一点。因此,这两种工具都使用模式和偏移(例如加密材料)。以下是可用于标识 MSV1_0 凭据包的条目位置的模板示例:
Pattern : 33FF4189374C8BF34585C074
SessionNo : -4
FirstEntry : 23
ParsingFunction : Get-MSV1_0_LIST_63
CredParsingFunction : Parse-PrimaryCredential-Win10-1607
因此,您可能还记得加密货币方面的内容,我们从在内存转储中搜索模式开始。MSV 包的一个特点是该模式位于 lsasrv.dll 中,而不是位于 msv1_0.dll 中。当我们识别出模式地址时,我们可以提取登录会话的数量并接收 MSV 条目的地址。
现在,我们关注 MSV 条目 - 为了接收这些条目,我们将 FirstEntry 偏移量添加到模式地址。这给了我们一个指针 - 当我们将其添加到模式地址和 FirstEntry 偏移量时,我们收到一个存储第一个条目地址的地址。因此,当我们提取第一个地址时,我们可以直接跳转到下一个条目,该条目存储在第一个条目旁边的八个字节中。因此,我们可以通过始终跳转到接下来的八个字节来读取完整的条目列表,直到内存流显示 8 个字节的“0”。
这设置了 NT 哈希提取的起点 - 我们解析 MSV 条目。
MSV解析
MSV 条目也有一些特殊的结构 - 您可能已经注意到它们在 Windows 版本之间也有所不同 - 因此对于每个版本,我们都有一个单独的模板。此外,条目被组织为链表,这意味着我们检查 MSV 结构,直到再次到达开头。在 MSV 条目中,可以使用各种信息 - 对于我们来说,我们的主要关注点是“主要凭证”结构。其中存储了加密的凭据。
因此,当我们根据所选模板解析 MSV 条目时,我们可以提取加密的凭据。
哈希提取
最后,我们到了,我们有一个加密的东西 - 太棒了。因此,据我所知,解密机制尚未正式记录 - 除了通过工具Mimikatz或其他)。通过查看这些工具,我们可以识别出 MSV 结构的主要凭证是使用 3DES 密钥和 IV 加密的(我知道这是显而易见的,因为加密内容已经这样命名了......)。当我们应用提取的 Key 和 IV 时,我们收到……NT 哈希!
太棒了 - 所有这些都在 PowerShell 内完成,无需任何其他工具。此外,所有这些都在内存中执行,并且(当前)没有被任何 AV 或 EDR 标记(也许除了内存转储)
把它包起来
我们就完成了。我们讨论了如何使用 PowerShell 读取内存转储以及如何解析和读取转储文件的内容。此外,我们能够识别不同的凭据包并提取登录密码的相关数据。
这样,您就拥有了在 PowerShell 中创建自己的 LSASS 转储解析器所需的一切 - 如果您不想(并且有一些很好的理由,例如心理健康),您也可以使用我的PowerExtract。我希望您通过本文了解了一些安全工具的内部工作原理。此外,我们的工作还没有结束。这就是无聊的事情。在下一篇文章中,我们将探索 Kerberos - 它更复杂,为此我在开发过程中获得了超能力,能够读取十六进制编码的 Kerberos 票证(也许不是非常有用,但我们会看到) - 所以请继续关注:)
PS:因为没有猫参与解析这个 LSASS 转储(并且因为我的老板不会在没有猫的情况下批准这篇文章) - 这是一只猫:
原文地址:https://cyvisory.hashnode.dev/read-memory-dumps-without-a-cat
若有侵权请联系删除
技术交流加下方vx
原文始发于微信公众号(红蓝公鸡队):使用PowerShell解析LSASS内存转储并提取凭据
- 左青龙
- 微信扫一扫
- 右白虎
- 微信扫一扫
评论