Skip to content

Commit

Permalink
[new] misc::netntlm , to ask locally NTLM challenge/response (experim…
Browse files Browse the repository at this point in the history
…ents with NTLM2-ESS, Credential Guard, etc.)
  • Loading branch information
gentilkiwi committed May 1, 2018
1 parent 5847bda commit cdd96ab
Show file tree
Hide file tree
Showing 3 changed files with 337 additions and 1 deletion.
2 changes: 2 additions & 0 deletions inc/globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
#pragma once
#include <ntstatus.h>
#define WIN32_NO_STATUS
#define SECURITY_WIN32
#include <winsock2.h>
#include <Ws2tcpip.h>
#include <windows.h>
#include <security.h>
#include <stdio.h>
#include <sddl.h>
#include <ntsecapi.h>
Expand Down
207 changes: 207 additions & 0 deletions kekeo/modules/kuhl_m_misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const KUHL_M_C kuhl_m_c_misc[] = {
{kuhl_m_misc_convert, L"convert", L"Convert tickets"},
{kuhl_m_misc_storm, L"storm", L"Kerberos Storm!"},
{kuhl_m_misc_arch, L"arch", L"Ask RPC for NDR64 support"},
{kuhl_m_misc_netntlm, L"netntlm", L"Ask a local NetNTLM challenge/response"},
};
const KUHL_M kuhl_m_misc = {
L"misc", L"Miscellaneous module", NULL,
Expand Down Expand Up @@ -462,4 +463,210 @@ NTSTATUS kuhl_m_misc_arch(int argc, wchar_t * argv[])
kull_m_sock_termSocket(&sock);
}
return STATUS_SUCCESS;
}

NTSTATUS kuhl_m_misc_netntlm(int argc, wchar_t * argv[])
{
KIWI_NTLM_CHALLENGE_MESSAGE littleChallenge = {NTLMSSP_Signature_ULL, NTLMSSP_TypeTwoMessage,
{0, 0, FIELD_OFFSET(KIWI_NTLM_CHALLENGE_MESSAGE, Payload)},
NTLMSSP_NEGOTIATE_VERSION | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_UNICODE,
{0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88},
{0},
{0, 0, FIELD_OFFSET(KIWI_NTLM_CHALLENGE_MESSAGE, Payload)},
{6, 1, 7601, {0}, 15},
};
SECURITY_STATUS status;
CredHandle Credentials;
TimeStamp CredentialsExpiry, SecurityContextExpiry;
CtxtHandle NewContext = {0};
SecBuffer
InBuff = {FIELD_OFFSET(KIWI_NTLM_CHALLENGE_MESSAGE, Payload), SECBUFFER_TOKEN, &littleChallenge},
OutBuff = {0, SECBUFFER_TOKEN, NULL},
Out2Buff = {0, SECBUFFER_TOKEN, NULL};
SecBufferDesc Output = {SECBUFFER_VERSION, 1, &OutBuff}, Input = {SECBUFFER_VERSION, 1, &InBuff}, Output2 = {SECBUFFER_VERSION, 1, &Out2Buff};
ULONG ContextAttr;

if(kull_m_string_args_byName(argc, argv, L"ess", NULL, NULL))
littleChallenge.NegotiateFlags |= NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY;
status = AcquireCredentialsHandle(NULL, L"NTLM", SECPKG_CRED_OUTBOUND, NULL, NULL, NULL, NULL, &Credentials, &CredentialsExpiry);
if(status == SEC_E_OK)
{
kprintf(L"NEGOTIATE :\n");
status = InitializeSecurityContext(&Credentials, NULL, NULL, ISC_REQ_CONNECTION | ISC_REQ_ALLOCATE_MEMORY, 0, SECURITY_NATIVE_DREP, NULL, 0, &NewContext, &Output, &ContextAttr, &SecurityContextExpiry);
if(status == SEC_I_CONTINUE_NEEDED)
{
kuhl_m_misc_netntlm_descrNegotiate(&Output);
kprintf(L"CHALLENGE :\n");
kuhl_m_misc_netntlm_descrChallenge(&Input);
kprintf(L"AUTHENTICATE:\n");
status = InitializeSecurityContext(&Credentials, &NewContext, NULL, ISC_REQ_CONNECTION | ISC_REQ_ALLOCATE_MEMORY, 0, SECURITY_NATIVE_DREP, &Input, 0, &NewContext, &Output2, &ContextAttr, &SecurityContextExpiry);
if(status == SEC_E_OK)
{
kuhl_m_misc_netntlm_descrAuthenticate(&Output2);
FreeContextBuffer(Out2Buff.pvBuffer);
}
else PRINT_ERROR(L"InitializeSecurityContext(2/2): 0x%08x\n", status);
FreeContextBuffer(OutBuff.pvBuffer);
}
else PRINT_ERROR(L"InitializeSecurityContext(1/2): 0x%08x\n", status);
FreeCredentialHandle(&Credentials);
}
else PRINT_ERROR(L"AcquireCredentialsHandle: 0x%08x\n", status);
return STATUS_SUCCESS;
}

const PCWCHAR KIWI_NEGOTIATE_FLAGS[] = {
L"UNICODE", L"OEM", L"ReqTARGET", L"RESERVED_10",
L"SIGN", L"SEAL", L"DATAGRAM", L"LM_KEY",
L"RESERVED_9", L"NTLM", L"RESERVED_8", L"ANONYMOUS",
L"OEM_DOMAIN_SUPPLIED", L"OEM_WORKSTATION_SUPPLIED", L"RESERVED_7", L"ALWAYS_SIGN",
L"TARGET_TYPE_DOMAIN", L"TARGET_TYPE_SERVER", L"TARGET_TYPE_SHARE", L"EXTENDED_SESSIONSECURITY",
L"IDENTIFY", L"RESERVED_5", L"ReqNON_NT_SESSION_KEY", L"TARGET_INFO",
L"RESERVED_4", L"VERSION", L"RESERVED_3", L"RESERVED_2",
L"RESERVED_1", L"128", L"KEY_EXCH", L"56",
};

void kuhl_m_misc_netntlm_descrNegotiateFlags(ULONG flags)
{
BYTE i;
kprintf(L"0x%08x ( ", flags);
for(i = 0; i < sizeof(ULONG) * 8; i++)
if((flags >> i) & 1)
kprintf(L"%s ", KIWI_NEGOTIATE_FLAGS[i]);
kprintf(L")\n");
}

void kuhl_m_misc_netntlm_descrAuthenticate(PSecBufferDesc buff)
{
PKIWI_NTLM_AUTHENTICATE_MESSAGE pAuth = (PKIWI_NTLM_AUTHENTICATE_MESSAGE) buff->pBuffers[0].pvBuffer;
PKIWI_NTLM_LMv2_RESPONSE pLMv2;
PKIWI_NTLM_NTLMv2_RESPONSE pNTLMv2;
PKIWI_NTLM_LM_RESPONSE pLMv1;
PKIWI_NTLM_NTLM_RESPONSE pNTLMv1;

kprintf(L" NegotiateFlags: ");
kuhl_m_misc_netntlm_descrNegotiateFlags(pAuth->NegotiateFlags);
kprintf(L" DomainName : ");
if(pAuth->DomainNameFields.Len)
kprintf(L"%.*s\n", pAuth->DomainNameFields.Len / sizeof(wchar_t), (PBYTE) pAuth + pAuth->DomainNameFields.Offset);
else kprintf(L"<NULL>\n");
kprintf(L" UserName : ");
if(pAuth->UserNameFields.Len)
kprintf(L"%.*s\n", pAuth->UserNameFields.Len / sizeof(wchar_t), (PBYTE) pAuth + pAuth->UserNameFields.Offset);
else kprintf(L"<NULL>\n");
kprintf(L" Workstation : ");
if(pAuth->WorkstationFields.Len)
kprintf(L"%.*s\n", pAuth->WorkstationFields.Len / sizeof(wchar_t), (PBYTE) pAuth + pAuth->WorkstationFields.Offset);
else kprintf(L"<NULL>\n");
if(pAuth->NegotiateFlags & NTLMSSP_NEGOTIATE_KEY_EXCH)
{
kprintf(L" SessionKey : ");
if(pAuth->EncryptedRandomSessionKeyFields.Len)
kull_m_string_wprintf_hex((PBYTE) pAuth + pAuth->EncryptedRandomSessionKeyFields.Offset, pAuth->EncryptedRandomSessionKeyFields.Len, 0);
else kprintf(L"<NULL>");
kprintf(L"\n");
}
if(pAuth->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
kprintf(L" Version : %hhu.%hhu (%hu) - rev. %hhu\n", pAuth->Version.ProductMajorVersion, pAuth->Version.ProductMinorVersion, pAuth->Version.ProductBuild, pAuth->Version.NTLMRevisionCurrent);
if((MIMIKATZ_NT_BUILD_NUMBER > 3790) || (pAuth->Version.ProductBuild > 3790))
{
kprintf(L" MIC : ");
kull_m_string_wprintf_hex(pAuth->MIC, sizeof(pAuth->MIC), 0);
kprintf(L"\n");
}
if(pAuth->NtChallengeResponseFields.Len >= sizeof(KIWI_NTLM_NTLMv2_RESPONSE))
{
if(pAuth->LmChallengeResponseFields.Len == sizeof(KIWI_NTLM_LMv2_RESPONSE))
{
pLMv2 = (PKIWI_NTLM_LMv2_RESPONSE) ((PBYTE) pAuth + pAuth->LmChallengeResponseFields.Offset);
kprintf(L" LMv2:\n");
kprintf(L" Response : ");
kull_m_string_wprintf_hex(pLMv2->Response, sizeof(pLMv2->Response), 0);
kprintf(L"\n");
kprintf(L" ClientChallenge: ");
kull_m_string_wprintf_hex(pLMv2->ChallengeFromClient, sizeof(pLMv2->ChallengeFromClient), 0);
kprintf(L"\n");
}
pNTLMv2 = (PKIWI_NTLM_NTLMv2_RESPONSE) ((PBYTE) pAuth + pAuth->NtChallengeResponseFields.Offset);
kprintf(L" NTLMv2:\n");
kprintf(L" Response : ");
kull_m_string_wprintf_hex(pNTLMv2->Response, sizeof(pNTLMv2->Response), 0);
kprintf(L"\n");
kprintf(L" ClientChallenge: ");
kull_m_string_wprintf_hex(pNTLMv2->ClientChallenge.ChallengeFromClient, sizeof(pNTLMv2->ClientChallenge.ChallengeFromClient), 0);
kprintf(L"\n");
kprintf(L" TimeStamp : ");
kull_m_string_displayLocalFileTime(&pNTLMv2->ClientChallenge.TimeStamp);
kprintf(L"\n");
}
else if(pAuth->NtChallengeResponseFields.Len == sizeof(KIWI_NTLM_NTLM_RESPONSE))
{
if(pAuth->LmChallengeResponseFields.Len == sizeof(KIWI_NTLM_LM_RESPONSE))
{
pLMv1 = (PKIWI_NTLM_LM_RESPONSE) ((PBYTE) pAuth + pAuth->LmChallengeResponseFields.Offset);
kprintf(L" LMv1:\n");
if(pAuth->NegotiateFlags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY)
{
kprintf(L" NTLM2 ESS : ");
kull_m_string_wprintf_hex(pLMv1->Response, 8, 0);
}
else
{
kprintf(L" Response : ");
kull_m_string_wprintf_hex(pLMv1->Response, sizeof(pLMv1->Response), 0);
}
kprintf(L"\n");
}
pNTLMv1 = (PKIWI_NTLM_NTLM_RESPONSE) ((PBYTE) pAuth + pAuth->NtChallengeResponseFields.Offset);
kprintf(L" NTLMv1:\n");
kprintf(L" Response : ");
kull_m_string_wprintf_hex(pNTLMv1->Response, sizeof(pNTLMv1->Response), 0);
kprintf(L"\n");
}
else PRINT_ERROR(L"NtChallengeResponseFields.Len = %hu\n", pAuth->NtChallengeResponseFields.Len);
}

void kuhl_m_misc_netntlm_descrChallenge(PSecBufferDesc buff)
{
PKIWI_NTLM_CHALLENGE_MESSAGE pChal = (PKIWI_NTLM_CHALLENGE_MESSAGE) buff->pBuffers[0].pvBuffer;
kprintf(L" NegotiateFlags: ");
kuhl_m_misc_netntlm_descrNegotiateFlags(pChal->NegotiateFlags);
kprintf(L" Challenge : "); kull_m_string_wprintf_hex(pChal->Challenge, sizeof(pChal->Challenge), 0); kprintf(L"\n");
if(pChal->NegotiateFlags & NTLMSSP_REQUEST_TARGET)
{
kprintf(L" TargetName : (%hu)\n", pChal->TargetNameFields.Len);
kull_m_string_wprintf_hex((PBYTE) pChal + pChal->TargetNameFields.Offset, pChal->TargetNameFields.Len, 1 | (16 << 16));
kprintf(L"\n");
}
if(pChal->NegotiateFlags & NTLMSSP_NEGOTIATE_TARGET_INFO)
{
kprintf(L" TargetInfo : (%hu)\n", pChal->TargetInfoFields.Len);
kull_m_string_wprintf_hex((PBYTE) pChal + pChal->TargetInfoFields.Offset, pChal->TargetInfoFields.Len, 1 | (16 << 16));
kprintf(L"\n");
}
if(pChal->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
kprintf(L" Version : %hhu.%hhu (%hu) - rev. %hhu\n", pChal->Version.ProductMajorVersion, pChal->Version.ProductMinorVersion, pChal->Version.ProductBuild, pChal->Version.NTLMRevisionCurrent);
}

void kuhl_m_misc_netntlm_descrNegotiate(PSecBufferDesc buff)
{
PKIWI_NTLM_NEGOTIATE_MESSAGE pNeg = (PKIWI_NTLM_NEGOTIATE_MESSAGE) buff->pBuffers[0].pvBuffer;
kprintf(L" NegotiateFlags: ");
kuhl_m_misc_netntlm_descrNegotiateFlags(pNeg->NegotiateFlags);
if(pNeg->NegotiateFlags & NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED)
{
kprintf(L" DomainName : ");
if(pNeg->DomainNameFields.Len)
kprintf(L"%.*S\n", pNeg->DomainNameFields.Len, (PBYTE) pNeg + pNeg->DomainNameFields.Offset);
else kprintf(L"<NULL>\n");
}
if(pNeg->NegotiateFlags & NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED)
{
kprintf(L" Workstation : ");
if(pNeg->WorkstationFields.Len)
kprintf(L"%.*S\n", pNeg->WorkstationFields.Len, (PBYTE) pNeg + pNeg->WorkstationFields.Offset);
else kprintf(L"<NULL>\n");
}
if(pNeg->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
kprintf(L" Version : %hhu.%hhu (%hu) - rev. %hhu\n", pNeg->Version.ProductMajorVersion, pNeg->Version.ProductMinorVersion, pNeg->Version.ProductBuild, pNeg->Version.NTLMRevisionCurrent);
}
129 changes: 128 additions & 1 deletion kekeo/modules/kuhl_m_misc.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ NTSTATUS kuhl_m_misc_changepw(int argc, wchar_t * argv[]);
NTSTATUS kuhl_m_misc_convert(int argc, wchar_t * argv[]);
NTSTATUS kuhl_m_misc_storm(int argc, wchar_t * argv[]);
NTSTATUS kuhl_m_misc_arch(int argc, wchar_t * argv[]);
NTSTATUS kuhl_m_misc_netntlm(int argc, wchar_t * argv[]);

typedef struct _KULL_M_KADMIN_PASSWD_ERR{
DWORD id;
Expand Down Expand Up @@ -127,4 +128,130 @@ typedef struct _rpcconn_bind_ack_hdr_t {
/* restore 4-octet alignment */
p_result_list_t p_result_list; /* variable size */
} rpcconn_bind_ack_hdr_t, *prpcconn_bind_ack_hdr_t;
#pragma pack(pop)
#pragma pack(pop)

#define NTLMSSP_NEGOTIATE_56 0x80000000
#define NTLMSSP_NEGOTIATE_KEY_EXCH 0x40000000
#define NTLMSSP_NEGOTIATE_128 0x20000000
#define NTLMSSP_RESERVED_1 0x10000000
#define NTLMSSP_RESERVED_2 0x08000000
#define NTLMSSP_RESERVED_3 0x04000000
#define NTLMSSP_NEGOTIATE_VERSION 0x02000000
#define NTLMSSP_RESERVED_4 0x01000000
#define NTLMSSP_NEGOTIATE_TARGET_INFO 0x00800000
#define NTLMSSP_REQUEST_NON_NT_SESSION_KEY 0x00400000
#define NTLMSSP_RESERVED_5 0x00200000
#define NTLMSSP_NEGOTIATE_IDENTIFY 0x00100000
#define NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY 0x00080000
#define NTLMSSP_TARGET_TYPE_SHARE 0x00040000 // RESERVED_6
#define NTLMSSP_TARGET_TYPE_SERVER 0x00020000
#define NTLMSSP_TARGET_TYPE_DOMAIN 0x00010000
#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x00008000
#define NTLMSSP_RESERVED_7 0x00004000
#define NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED 0x00002000
#define NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED 0x00001000
#define NTLMSSP_NEGOTIATE_ANONYMOUS 0x00000800
#define NTLMSSP_RESERVED_8 0x00000400
#define NTLMSSP_NEGOTIATE_NTLM 0x00000200
#define NTLMSSP_RESERVED_9 0x00000100
#define NTLMSSP_NEGOTIATE_LM_KEY 0x00000080
#define NTLMSSP_NEGOTIATE_DATAGRAM 0x00000040
#define NTLMSSP_NEGOTIATE_SEAL 0x00000020
#define NTLMSSP_NEGOTIATE_SIGN 0x00000010
#define NTLMSSP_RESERVED_10 0x00000008
#define NTLMSSP_REQUEST_TARGET 0x00000004
#define NTLMSSP_NEGOTIATE_OEM 0x00000002
#define NTLMSSP_NEGOTIATE_UNICODE 0x00000001

#define NTLMSSP_Signature "NTLMSSP"
#define NTLMSSP_Signature_ULL 0x005053534d4c544e
#define NTLMSSP_TypeOneMessage 0x00000001
#define NTLMSSP_TypeTwoMessage 0x00000002
#define NTLMSSP_TypeThreeMessage 0x00000003

#pragma pack(push, 1)
typedef struct _KIWI_NTLM_VERSION {
UCHAR ProductMajorVersion;
UCHAR ProductMinorVersion;
USHORT ProductBuild;
UCHAR Reserver[3];
UCHAR NTLMRevisionCurrent;
} KIWI_NTLM_VERSION, *PKIWI_NTLM_VERSION;

typedef struct _KIWI_NTLM_BUFFER {
USHORT Len;
USHORT MaxLen;
ULONG Offset;
} KIWI_NTLM_BUFFER, *PKIWI_NTLM_BUFFER;

typedef struct _KIWI_NTLM_LM_RESPONSE {
UCHAR Response[24];
} KIWI_NTLM_LM_RESPONSE, *PKIWI_NTLM_LM_RESPONSE;

typedef struct _KIWI_NTLM_NTLM_RESPONSE {
UCHAR Response[24];
} KIWI_NTLM_NTLM_RESPONSE, *PKIWI_NTLM_NTLM_RESPONSE;

typedef struct _KIWI_NTLM_LMv2_RESPONSE {
UCHAR Response[16];
UCHAR ChallengeFromClient[8];
} KIWI_NTLM_LMv2_RESPONSE, *PKIWI_NTLM_LMv2_RESPONSE;

typedef struct _KIWI_NTLM_NTLMv2_CLIENT_CHALLENGE {
UCHAR RespType;
UCHAR HiRespType;
USHORT Reserved1;
ULONG Reserved2;
FILETIME TimeStamp;
UCHAR ChallengeFromClient[8];
ULONG Reserved3;
// AvPairs;
} KIWI_NTLM_NTLMv2_CLIENT_CHALLENGE, *PKIWI_NTLM_NTLMv2_CLIENT_CHALLENGE;

typedef struct _KIWI_NTLM_NTLMv2_RESPONSE {
UCHAR Response[16];
KIWI_NTLM_NTLMv2_CLIENT_CHALLENGE ClientChallenge;
} KIWI_NTLM_NTLMv2_RESPONSE, *PKIWI_NTLM_NTLMv2_RESPONSE;

typedef struct _KIWI_NTLM_NEGOTIATE_MESSAGE {
ULONGLONG Signature;
ULONG MessageType;
ULONG NegotiateFlags;
KIWI_NTLM_BUFFER DomainNameFields;
KIWI_NTLM_BUFFER WorkstationFields;
KIWI_NTLM_VERSION Version;
UCHAR Payload[ANYSIZE_ARRAY];
} KIWI_NTLM_NEGOTIATE_MESSAGE, *PKIWI_NTLM_NEGOTIATE_MESSAGE;

typedef struct _KIWI_NTLM_CHALLENGE_MESSAGE {
ULONGLONG Signature;
ULONG MessageType;
KIWI_NTLM_BUFFER TargetNameFields;
ULONG NegotiateFlags;
UCHAR Challenge[8];
CHAR Reserved[8];
KIWI_NTLM_BUFFER TargetInfoFields;
KIWI_NTLM_VERSION Version;
UCHAR Payload[ANYSIZE_ARRAY];
} KIWI_NTLM_CHALLENGE_MESSAGE, *PKIWI_NTLM_CHALLENGE_MESSAGE;

typedef struct _KIWI_NTLM_AUTHENTICATE_MESSAGE {
ULONGLONG Signature;
ULONG MessageType;
KIWI_NTLM_BUFFER LmChallengeResponseFields;
KIWI_NTLM_BUFFER NtChallengeResponseFields;
KIWI_NTLM_BUFFER DomainNameFields;
KIWI_NTLM_BUFFER UserNameFields;
KIWI_NTLM_BUFFER WorkstationFields;
KIWI_NTLM_BUFFER EncryptedRandomSessionKeyFields;
ULONG NegotiateFlags;
KIWI_NTLM_VERSION Version;
UCHAR MIC[16];
UCHAR Payload[ANYSIZE_ARRAY];
} KIWI_NTLM_AUTHENTICATE_MESSAGE, *PKIWI_NTLM_AUTHENTICATE_MESSAGE;
#pragma pack(pop)

void kuhl_m_misc_netntlm_descrNegotiateFlags(ULONG flags);
void kuhl_m_misc_netntlm_descrAuthenticate(PSecBufferDesc buff);
void kuhl_m_misc_netntlm_descrChallenge(PSecBufferDesc buff);
void kuhl_m_misc_netntlm_descrNegotiate(PSecBufferDesc buff);

0 comments on commit cdd96ab

Please sign in to comment.