# Windows 认证理论

我们在之前已经讨论了 NTLM 认证、Kerberos 认证、LSA 与 LSASS、SAM 等概念。在这小节，我们将对 Windows 认证理论做一个整合、归纳以及延伸。

*本章节所使用的原理示意图和部分理论来自 [https://attl4s.github.io/assets/pdf/Understanding\_Windows\_Lateral\_Movements\_2023.pdf](https://attl4s.github.io/assets/pdf/Understanding_Windows_Lateral_Movements_2023.pdf) 。*

## **Windows 认证类型与形式**

发生在 Windows 环境中的认证过程，可以是本地认证，以及域认证。

#### **本地认证**

本地认证，例如是使用本地账户登陆主机。我们对于个人用的主机进行登陆往往就是本地登陆。本地用户只存在于特定系统，即只有该系统才知道有哪些本地用户，例如 **SRV01\\David**。尽管系统与系统之间是互相独立的，但是不同的系统却可能有着相似甚至相同的帐号密码。例如 **SRV01\\David**，**SRV02\\David**。我们之前知道了本地系统的信息存储于 SAM 之中，当用户以本地账户认证的时候，Windows 会根据 SAM 中的记录验证凭证。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/L5CyeSwieqxKryJr-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/L5CyeSwieqxKryJr-image.png)

#### **域认证**

域认证，例如是员工通过分发的域账户登陆工作站并访问内部资源。总之，域认证与本地认证是不同的机制。域用户和群组呈现在具体的 AD 域中，所有的域系统， (或在受信任的域中) 知道如何应对认证，它们会将认证的流程委派给域控制器。域用户和主机数据存储于 NTDS (NT 目录服务) 数据库中，当有用户尝试认证，域控制器则根据记录来验证凭证。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/JfDpjjMoX2bl5bIe-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/JfDpjjMoX2bl5bIe-image.png)

而认证的形式，可以笼统地分为物理认证以及远程认证。

#### **物理认证**

当用户在电脑面前，输入凭证并登陆，那么这是物理认证，适用于本地用户和域用户，只要目标系统知道认证的帐号。在 AD 中，默认情况下，**任何域用户**可以物理登陆**任何域主机**。但是，绝大多数情况下，我们没有机会在目标的环境中实现物理登陆。

#### **远程认证**

与物理认证有所不同的是，默认情况下需要特定权限才能进行远程登陆，例如属于**本地管理员分组**，**远程桌面用户分组**。因此，我们应该关心的还是远程认证。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/lhbRE19QYJBafpog-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/lhbRE19QYJBafpog-image.png)

为了理解接下来的概念，我们需要对 Windows 认证机制很熟悉。

###   


## **Windows 认证重要概念**

#### **认证包/安全支持提供程序 AP/SSP**

虽然在前面的小节有讨论过了，让我们再回顾一下。AP/SSP 通过分析登陆数据来认证 Windows 用户，不同的 AP/SSP 对多种登陆过程以及认证协议提供支持。AP/SSP 以 **DLL** 形式存在，被 LSA 所加载和使用。常见的 AP/SSP 有 NTLM，Kerberos，WDigest，Credman 等。微软所提供的 AP 有 **CSSP**，**Microsoft Negotiate**，**Microsoft NTLM**，**Microsoft Kerberos**，**Microsoft Digest SSP**，以及 **Secure Channel**。

AP 提供了 Windows 充当客户端和认证服务器所需的逻辑。对于客户端，想要通过 Windows 认证连接到特定服务。对于服务器，想要让服务或应用程序支持 Windows 认证

#### **SSP 接口**

微软提供 SSP 接口以简单地将应用程序与认证系统无缝继承。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/DTKCEfZ9m13LLRo1-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/DTKCEfZ9m13LLRo1-image.png)

SSPI 的作用主要有这些：**安全包管理**、**凭证管理**、**安全上下文管理**、**消息支持**。

#### **交互式登陆 vs 非交互式登陆**

本地认证与域认证、物理认证与远程认证，这样的分类还不够。认证还有**交互式**与**非交互式**之分。

交互式登陆，通常需要**指定明文凭证**，例如通过 **Windows 的登陆页面**进行认证。最重要的一点是用户凭证会缓存在 LSA 进程的内存中，为各个 AP 做准备。缓存的凭证还能让 Windows 给用户提供 SSO 体验。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/kxhDgHOcCFkDuZT0-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/kxhDgHOcCFkDuZT0-image.png)

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/oWvMgQyADG5ps42L-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/oWvMgQyADG5ps42L-image.png)

而非交互式认证，应用程序代表用户使用缓存的凭证，也就是非交互式认证只应在**交互式认证之后**发生，也就是**缓存凭证可用**时。一些应用通过 SSPI 来实现这些认证。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/IVpRquck7vE65Pgk-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/IVpRquck7vE65Pgk-image.png)

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/WAtRbvHwPangCayQ-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/WAtRbvHwPangCayQ-image.png)

#### **登陆会话**

登陆会话会在成功的认证之后创建，无论是物理认证、远程认证、域认证、本地认证、交互式登陆还是非交互式登陆。**AP 缓存的凭证**绑定在了**登陆会话**上。而在用户登出后结束。

当认证成功时，被选中的 AP 将执行这两个重要任务：**创建一个新的登陆会话**，以及**向 LSA 提供认证用户的安全信息**。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/uHTXLl1YkJ6dxSZk-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/uHTXLl1YkJ6dxSZk-image.png)

**LSA** 使用该信息创建**访问令牌**来代表用户在系统中的的**安全上下文**。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/Aq2vGVh61IFzAF7p-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/Aq2vGVh61IFzAF7p-image.png)

**通常来说**，登陆会话通常在交互式认证之后会有缓存的凭证，而非交互式的认证普遍会导致不缓存凭证的登陆会话。

#### **登陆类型**

在 Windows 中，所有的认证都应当作为以下登陆类型之一处理，无论是何种认证协议以及认证形式。

<table border="1" id="bkmrk-%E7%99%BB%E9%99%86%E7%B1%BB%E5%9E%8B-%E7%BC%96%E5%8F%B7-%E8%AE%A4%E8%AF%81%E5%BD%A2%E5%BC%8F-%E5%87%AD%E8%AF%81%E6%98%AF%E5%90%A6%E5%AD%98%E5%82%A8%E4%BA%8E" style="border-collapse: collapse; width: 100%; height: 236.8px;"><colgroup><col style="width: 12.4815%;"></col><col style="width: 12.4815%;"></col><col style="width: 24.9629%;"></col><col style="width: 24.9629%;"></col><col style="width: 24.9629%;"></col></colgroup><tbody><tr style="height: 29.6px;"><td style="height: 29.6px;">**登陆类型**</td><td style="height: 29.6px;">**编号**</td><td style="height: 29.6px;">**认证形式**</td><td style="height: 29.6px;">**凭证是否存储于 LSA 中**</td><td style="height: 29.6px;">**案例**</td></tr><tr style="height: 29.6px;"><td style="height: 29.6px;">交互式</td><td style="height: 29.6px;">2</td><td style="height: 29.6px;">密码，智能卡，其他</td><td style="height: 29.6px;">是</td><td style="height: 29.6px;">物理登陆

runas

IIS 6 之前的基本认证

</td></tr><tr style="height: 29.6px;"><td style="height: 29.6px;">网络</td><td style="height: 29.6px;">3</td><td style="height: 29.6px;">密码，NT 哈希，Kerberos 票据</td><td style="height: 29.6px;">否 (除非委派被启用)</td><td style="height: 29.6px;">NET USER

RPC 调用

远程注册表

集成 Windows 认证的 IIS

SQL Windows 认证

</td></tr><tr style="height: 29.6px;"><td style="height: 29.6px;">批处理</td><td style="height: 29.6px;">4</td><td style="height: 29.6px;">存储于 LSA 机密中的密码</td><td style="height: 29.6px;">是</td><td style="height: 29.6px;">计划任务</td></tr><tr style="height: 29.6px;"><td style="height: 29.6px;">服务</td><td style="height: 29.6px;">5</td><td style="height: 29.6px;">同上</td><td style="height: 29.6px;">是</td><td style="height: 29.6px;">Windows 服务</td></tr><tr style="height: 29.6px;"><td style="height: 29.6px;">网络明文</td><td style="height: 29.6px;">8</td><td style="height: 29.6px;">密码</td><td style="height: 29.6px;">是</td><td style="height: 29.6px;">IIS 6 及之后的基本认证

带有 CredSSP 的 Windows PowerShell

</td></tr><tr style="height: 29.6px;"><td style="height: 29.6px;">新凭证</td><td style="height: 29.6px;">9</td><td style="height: 29.6px;">密码</td><td style="height: 29.6px;">是</td><td style="height: 29.6px;">runas /network</td></tr><tr style="height: 29.6px;"><td style="height: 29.6px;">远程交互式</td><td style="height: 29.6px;">10</td><td style="height: 29.6px;">密码，智能卡，其他</td><td style="height: 29.6px;">是</td><td style="height: 29.6px;">远程桌面</td></tr></tbody></table>

导入 Get-LogonSession.ps1 脚本 ([https://github.com/leechristensen/Random/blob/master/PowerShellScripts/Get-LogonSession.ps1](https://github.com/leechristensen/Random/blob/master/PowerShellScripts/Get-LogonSession.ps1))。查看 Web02 目前的会话列表 (大家自己操作得到的结果可能有所不同)，仅筛选出 white-bird 域中的用户

```powershell
get-logonsession | where-object {$_.Domain -eq 'WHITE-BIRD'}|select UserName, LogonType, AuthenticationPackage
```

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/xmob5HpQYpMinxmT-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/xmob5HpQYpMinxmT-image.png)

因为 Web02 设置了 serveradm 的自动登陆，那么 serveradm 的交互式登陆自然是预期之中的。而 Web02 上同样运行着 SQL 服务，服务账号是 sql\_service，因此服务登陆以及网络登陆同样是预期之中的。

#### **令牌**

当一个登陆会话被创建后，返回给 LSA 的信息被用于创建一个**访问令牌**。访问令牌是被保护的对象，它包含了一个认证用户的本地安全上下文。每个**访问令牌**被绑定给了一个**登陆会话**，访问令牌与进程或线程有关。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/tMZcOg9KvWfQq8WP-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/tMZcOg9KvWfQq8WP-image.png)

访问令牌包含了用户与其上下文的重要数据：**用户 SID**、**用户组归属**、**特权列表**、**会话 ID**、**完整度等级**、**令牌类型**等。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/iifjTNSxyOxv4jnp-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/iifjTNSxyOxv4jnp-image.png)

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/qtHrb2l7MLVYReKg-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/qtHrb2l7MLVYReKg-image.png)

在 Windows 中，相同的用户可以有着不同的上下文，例如 UAC 区分了中等和高完整度等级。这是因为 Windows 允许相同用户在同一个系统中有着不同的访问令牌和登陆会话。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/qCg7wOgB0pANUO8Z-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/qCg7wOgB0pANUO8Z-image.png)

Windows 使用访问令牌实施访问控制决定。Windows 对象有着访问控制列表，访问这样的对象的进程或线程有着访问令牌，而令牌信息被拿来与对象的 DACL 进行比较从而决定是否允许访问。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/O70ps8s67Fi0whbb-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/O70ps8s67Fi0whbb-image.png)

令牌的类型有**主要令牌**与**模仿令牌**。主要令牌又被称为**进程令牌**，每个进程都有关联的主要令牌，当有新的进程被创建，默认是**继承父进程的主要令牌**。

**模仿令牌**又被称为**线程令牌**，得以让一个线程运行在**与父进程所不同**的安全上下文中，通常用于客户端服务端的情景。当每个客户端连接到服务，新线程得以创建。正是因为模仿令牌，线程得以运行在不同客户端的上下文中，这使得服务可以通过 ACL 控制访问。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/LepqaworT57wPnVV-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/LepqaworT57wPnVV-image.png)

支持 Windows 认证的服务执行被称为客户端模仿的操作。当一个客户端连接到服务，客户端的凭证会被验证，以这个客户端为安全上下文的访问令牌被创建，服务在新的线程中置入令牌的备份，进而该线程可以代表这个客户端，并且受 ACL 的限制。因为一些服务只需要客户端的部分信息，即不需要完全的模仿。根据服务的配置，模仿令牌可以有着不同的模仿等级：

SecurityAnonymous：**服务器不能模仿客户端的身份**

SecurityIdentification：**服务器可以获得客户端的身份和特权但不能模仿**

SecurityImpersonation：**服务器可以在本地主机上模仿用户的安全上下文**

SecurityDelegation：**服务器可以在远程主机上模仿用户的安全上下文**

### **用户模仿**

用户模仿即**创建**或**劫持**另一个用户的安全上下文以在网络中代表这个用户。创建一个安全上下文通常需要凭证，而劫持一个安全上下文则需要特权。用户模仿可以通过这些途径实现：**令牌操纵**、**密码**、**NT 哈希**、**Kerberos 票据**等。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/4UE8CELvIXIQikQY-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/4UE8CELvIXIQikQY-image.png)

请回顾跟登陆会话绑定的凭证，通常是交互式认证的产物。如果想通过使用一个令牌来访问网络资源，这个令牌必须与一个有着凭证的会话相关联。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/uHCKhOBLIxubbaqV-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/uHCKhOBLIxubbaqV-image.png)

Windows API 提供了能用于操纵令牌的功能，例如**复制令牌**。但是，我们需要特权：**本地管理员或者 SYSTEM**，**服务账号** (土豆家族)。而低权限用户只能操纵自己的令牌。

**DuplicateTokenEx** API 可用于创建一个复制现有令牌的新访问令牌。

```c++
BOOL DuplicateTokenEx(
  [in]           HANDLE                       hExistingToken,
  [in]           DWORD                        dwDesiredAccess,
  [in, optional] LPSECURITY_ATTRIBUTES        lpTokenAttributes,
  [in]           SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
  [in]           TOKEN_TYPE                   TokenType,
  [out]          PHANDLE                      phNewToken
);
```

如果是劫持一个已有令牌的方法，有着**令牌模仿**与**进程注入**的方法。前者**复制目标的令牌**并且将其用于已有进程或者新进程，后者将载荷注入到**目标令牌所寄居的进程**。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/wfKY1ylbvSI4dDTb-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/wfKY1ylbvSI4dDTb-image.png)

SharpToken ([https://github.com/BeichenDream/SharpToken](https://github.com/BeichenDream/SharpToken)) 是一款可以通过操纵令牌来实现用户模仿的工具，在 本地管理员或者 SYSTEM 权限下，我们可以列举所有可用令牌，并窃取想要的令牌。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/0KDd5Bt6u5u6vMej-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/0KDd5Bt6u5u6vMej-image.png)

Cobalt Strike 中的内置命令 **steal\_token** 也可实现令牌窃取

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/11vfYsMRQXEcRIfB-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/11vfYsMRQXEcRIfB-image.png)

而通过**进程注入实**现令牌劫持的流程图如下：

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/GMlGjNi2VmXfV5bi-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/GMlGjNi2VmXfV5bi-image.png)

#### **有明文密码！**

##### **runas.exe**

Windows 原生程序 runas.exe 可以通过提供额外的凭证来创建进程，例如用户想以另一个账户的身份运行特定进程。runas.exe 默认 (不提供其他选项) 会通过 LSA 验证提供的凭证的正确与否，类似于交互式认证。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/qjnHOIipnb3OsnEu-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/qjnHOIipnb3OsnEu-image.png)

对本地账户以及域账户都成立。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/ef2N0jJFkhhjkpZU-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/ef2N0jJFkhhjkpZU-image.png)

如果没有提供正确的凭证，则会失败。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/2jJu9rC4ViA1AfeL-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/2jJu9rC4ViA1AfeL-image.png)

在 Cobalt Strike 中，**runas** 命令则是对 Windows 系统中 runas.exe 的实现。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/u5z0upvv7RkG77Fe-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/u5z0upvv7RkG77Fe-image.png)

C# 工具 runascs ([https://github.com/antonioCoco/RunasCs](https://github.com/antonioCoco/RunasCs)) 也有着相似的功能和实现，并且自定义程度更高，用户可以指定登陆类型。例如，指定 **-l** 为 **2**，则是交互式认证。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/jfeYCQvxvhUywzdx-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/jfeYCQvxvhUywzdx-image.png)

在使用 runas.exe 以 **white-bird\\condrey** 身份创建的 **cmd.exe** 进程以及使用 runascs.exe 以 wanh 身份创建 cmd.exe 进程后，我们可以用之前的脚本命令发现新增了用户的登陆会话。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/dKBmTAsLfeqKUZv4-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/dKBmTAsLfeqKUZv4-image.png)

##### **runas.exe /netonly**

runas.exe 程序有着 **/netonly** 的选项，它告诉 runas.exe 这个指定的凭证仅用于远程访问，而 LSA 并不会验证凭证的正确与否，也就是即便输入错误的凭证也不会有报错信息。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/dsWFC98OgxCwaRCD-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/dsWFC98OgxCwaRCD-image.png)

指定了 **/netonly** 选项后，假设提供的凭证是有效的，那么新的进程在**本地层面**保持原来的身份，但在**网络层面**却是新的身份，即有着 **2 个不同的安全上下文**。**prod\\john** 对于 **Srv01** 具有 **WinRM** 访问。通过 /netonly 创建的新 **powershell.exe** 进程中，我们发现身份还是 **prod\\alice**，但如果使用 john 的访问在 Srv01 上远程执行命令，身份则是 **john** 了。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/Iye9koeSKz1rPTPx-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/Iye9koeSKz1rPTPx-image.png)

runas.exe 的实现使用的是 **CreateProcessWithLogonW** API，即以提供的凭证的安全上下文创建新的进程。/netonly 选项使用了 **LOGON\_NETCREDENTIALS\_ONLY** 登陆选项，**创建和使用新的登陆会话**，但是**令牌还是原来的**。

```c++
BOOL CreateProcessWithLogonW(
  [in]                LPCWSTR               lpUsername,
  [in, optional]      LPCWSTR               lpDomain,
  [in]                LPCWSTR               lpPassword,
  [in]                DWORD                 dwLogonFlags,
  [in, optional]      LPCWSTR               lpApplicationName,
  [in, out, optional] LPWSTR                lpCommandLine,
  [in]                DWORD                 dwCreationFlags,
  [in, optional]      LPVOID                lpEnvironment,
  [in, optional]      LPCWSTR               lpCurrentDirectory,
  [in]                LPSTARTUPINFOW        lpStartupInfo,
  [out]               LPPROCESS_INFORMATION lpProcessInformation
);
```

##### **make\_token**

多个 C2 工具中都有着类似于 **make\_token** 功能的命令，Cobalt Strike 自然也是有这样的功能和命令的。make\_token 允许我们在知道其他用户明文密码的情况下模仿他们，调用的是 **LogonUserA** API。

```c++
BOOL LogonUserA(
  [in]           LPCSTR  lpszUsername,
  [in, optional] LPCSTR  lpszDomain,
  [in, optional] LPCSTR  lpszPassword,
  [in]           DWORD   dwLogonType,
  [in]           DWORD   dwLogonProvider,
  [out]          PHANDLE phToken
);
```

LogonUserA 相比 CreateProcessWithLogon 更好的地方在于，我们可以在**不创建新的进程**的情况下创建新的**登陆会话**/**令牌对**，并且可以指定不同的登陆类型 (在调用 LogonUserA 获得令牌后，可以创建新的进程)。Cobalt Strike 中的 make\_token 使用的是 **LOGON32\_LOGON\_NEW\_CREDENTIALS** 登陆类型，与 **runas.exe /netonly** 一致、

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/zmzWu5G8MFJW0mfj-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/zmzWu5G8MFJW0mfj-image.png)

调用该 API 得到的令牌可以被传递给 **ImpersonateLoggedOnUser** API，这允许调用的线程模仿令牌的上下文 (被模样的用户的上下文)。

```c++
BOOL ImpersonateLoggedOnUser(
  [in] HANDLE hToken
);
```

当不需要模仿的时候，使用 rev2self 命令退出。

```c++
BOOL RevertToSelf();
```

总之，在**高完整度**下，操纵令牌是容易的，我们可以做这些事情：**窃取系统内的任何令牌**、**注入到任何进程**、**将窃取的令牌应用于当前的上下文**、**用窃取的凭证创建新的进程**。如果是低完整度下，我们**不能使用令牌创建新的进程** (**CreateProcessAsUser** 或**CreateProcessWithToken** API 需要管理员特权)，因此考虑内联执行，例如 BOF。

#### **有 NT 哈希！**

如果我们没有明文密码，只有 NTLM 哈希呢？如何实现用户模仿？可惜的是，Windows 没有这样的认证功能，没有 LogonUserWithHash 或者 CreateProcessWithHash API。如果我们想通过 LSA 来利用哈希，我们需要与 LSASS 进程打交道。LSASS 存储着所有登陆会话以及缓存凭证，需要高权限，而且还很有风险。

但我们其实也不必依赖于 LSA，这不局限于有 NTLM 哈希，包括有明文密码或者其他类型的凭证。我们可以使用对 NTLM 或者 Kerberos 有原生支持的工具。

##### **与 LSA 交互**

Mimikatz 可以用来完成基于 LSA 的哈希传递。换句话说，哈希传递也可以不必依赖于 LSA。Mimikatz 可以使用 NTLM 哈希而非明文密码来创建进程，通过向 lsass 进程注入数据实现。因为需要修改 lsass 进程，自然需要高权限。

在 **Web02** 上，任何目前可用的令牌都不足以访问 **Dc05**。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/Qp2zKUG2qSs9QNhk-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/Qp2zKUG2qSs9QNhk-image.png)

在 SYSTEM 权限下，使用 mimikatz 的 PTH 命令

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/jEXMwUdfy1VTHKsd-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/jEXMwUdfy1VTHKsd-image.png)

我们可以看到现在 lsass.exe 进程是 **RW** 权限了。这个命令将新凭证通过**命名管道**传递，然后 Beacon 再模仿它。

Mimikatz 的 PTH 相当于提供哈希而非明文密码版本的 runas.exe /netonly。先通过 **CreateProcessWithLogon** API 创建新的进程，其中使用的是 **LOGON\_NETCREDENTIALS\_ONLY** 登陆选项。然后，识别出新创建的登陆会话，将**凭证内容**填充到**目标的登陆会话**中。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/b1hoRPm2FZi9ICgm-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/b1hoRPm2FZi9ICgm-image.png)

现在，我们可以访问 Dc05 了。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/9RaO0B8zbWzR5kUT-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/9RaO0B8zbWzR5kUT-image.png)

用图来显示普通认证流程以及 Mimikatz 的 PTH 的话，如下所示：

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/bFSpeXVEcUUQJX75-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/bFSpeXVEcUUQJX75-image.png)

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/mXQj2mLrrsYnFV8B-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/mXQj2mLrrsYnFV8B-image.png)

##### **不与 LSA 交互**

不与 LSA 交互的 PTH 则就简单多了，只需要找到原生支持我们想要使用的协议的工具即可，例如 Impacket，CrackMapExec 等，而不需要与复杂的 Windows 组件打交道。

如果是 **NTLM** 协议：

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/U0wa1ZE0lgLCZ93l-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/U0wa1ZE0lgLCZ93l-image.png)

如果是 **Kerberos** 协议，我们可以使用 Rubeus 或者 Impacket，这类工具可以产生获得 TGT/TGS 的 Kerberos 原始流量。至于如何利用得到的票据，我们下文就说。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/MyfPX5xXnkkrPhDd-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/MyfPX5xXnkkrPhDd-image.png)

####   


#### **有 Kerberos 票据！**

虽然 Windows 没有基于 NTLM 哈希的认证功能，但对于 Kerberos 票据是有的。我们同样可以选择与 LSASS 交互，或者不与 LSASS 交互。

##### **与 LSA 交互**

我们可以将票据导入到存在的登陆会话中。将票据导入到**当前的会话**中不需要特权，而导入到**其他会话**中则需要特权。

假如我们已经得到或伪造了其他用户的 Kerberos 票据，并且打算使用它们。**PTK**，即**票据传递**是将这样的票据导入到**攻击者所控制的登陆会话**的技术，这使得我们可以在网络中模仿受害者。如果导入了一张 TGT 到现有会话中，那么原来的会被覆盖。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/jI2CkzIYBf7bGOZP-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/jI2CkzIYBf7bGOZP-image.png)

Rubeus 的 **PTT** 命令正是这样的原理

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/VrmcuQHtckJsnknx-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/VrmcuQHtckJsnknx-image.png)

Cobalt Strike 的命令 **kerberos\_ticket\_use** 具有同样作用。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/HMS318Ou9VfZgerM-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/HMS318Ou9VfZgerM-image.png)

这项技术的实现，是使用了 **LsaCallAuthenticationPackege** API。这个 API 使得应用程序可以与 Windows AP 进行对话

```c++
NTSTATUS LsaCallAuthenticationPackage(
  [in]  HANDLE    LsaHandle,
  [in]  ULONG     AuthenticationPackage,
  [in]  PVOID     ProtocolSubmitBuffer,
  [in]  ULONG     SubmitBufferLength,
  [out] PVOID     *ProtocolReturnBuffer,
  [out] PULONG    ReturnBufferLength,
  [out] PNTSTATUS ProtocolStatus
);
```

总之，如果使用**与 LSA 交互**的方法导入票据，我们可以在**低权限**的情况下将票据导入到**当前会话**。可以是使用 **make\_token** 创建并模仿一个**新的登陆会话**，导入票据以防止覆盖原有的 TGT。在 alice 会话的 file01 Beacon 中，我们使用 make\_token 命令创建并模仿一个新的登陆会话，密码不需要是有效的。此时，这个新登陆会话的还不存在任何票据，我们使用 **kerberos\_ticket\_use** 导入 white-bird\\administrator 的票据，发现可以访问 Dc05 了。如果使用 **rev2self** 退出模仿，便不能访问了。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/BFHkgSJunkUwAfmS-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/BFHkgSJunkUwAfmS-image.png)

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/Wcb3rDAR1AK3B99J-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/Wcb3rDAR1AK3B99J-image.png)

或者在**高权限**的情况下，先**创建一个牺牲进程**用来导入票据，因为一个登陆会话每次只能持有 **1** 张 TGT，在当前会话导入 TGT 可能导致认证紊乱。将票据导入到该牺牲会话之后，**窃取令牌**或者在该进程**注入载荷**。

目前，我们在 Web02 上不能访问 Dc05 (清除了现有票据以避免干扰)。使用 **createnetonly** 命令创建一个新的隐藏进程，我们可以看到新的会话 ID 以及进程 ID。但目前这个会话里还没有 TGT。我们还指定了**域名**、**帐号**、**密码**(不会被验证)，这是为了在日志中看起来更加清白，毕竟 Rubeus 随机生成的这些数据会成为嫌疑。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/X6xiH77d3lWLyOww-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/X6xiH77d3lWLyOww-image.png)

因此，我们导入 Administrator 的 TGT，指定**目标 LUID**。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/ks7VTDnM7EmIVHkt-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/ks7VTDnM7EmIVHkt-image.png)

**窃取令牌**后，方可访问了。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/BEXzQVVaFu6nPpyQ-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/BEXzQVVaFu6nPpyQ-image.png)

##### **不与 LSA 交互**

我们可以用 Impacket 之类的工具来使用得到的票据。我们可以使用 Impacket 中的 **ticketConverter** 将票据在 **kirbi** 格式与 **ccache** 格式直接互相转换。在 Linux 端，所接受的格式是 ccache，我们需要设置 **KRB5CCNAME** 环境变量指向该 ccache 票据。

[![image.png](https://raven-medicine.com/uploads/images/gallery/2023-05/scaled-1680-/PiPOczMaUKeewBR8-image.png)](https://raven-medicine.com/uploads/images/gallery/2023-05/PiPOczMaUKeewBR8-image.png)