From 34630c9920fdbe934b359b9a531fd3cb05d8b789 Mon Sep 17 00:00:00 2001 From: Benjamin DELPY Date: Tue, 8 May 2018 19:50:37 +0200 Subject: [PATCH] [new] ntlm module for netntlm challenge/response (self or http) (again...) --- inc/NTSecPKG.h | 2133 +++++++++++++++++++++++++++++++++++ inc/globals.h | 1 + inc/winhttp.h | 1255 +++++++++++++++++++++ kekeo.sln | 4 + kekeo/kekeo.c | 1 + kekeo/kekeo.h | 1 + kekeo/kekeo.vcxproj | 4 +- kekeo/kekeo.vcxproj.filters | 6 + kekeo/modules/kuhl_m_misc.c | 207 ---- kekeo/modules/kuhl_m_misc.h | 129 +-- kekeo/modules/kuhl_m_ntlm.c | 843 ++++++++++++++ kekeo/modules/kuhl_m_ntlm.h | 178 +++ lib/Win32/winhttp.lib | Bin 0 -> 8822 bytes lib/x64/winhttp.lib | Bin 0 -> 8304 bytes modules/kull_m_string.c | 799 ++++++------- 15 files changed, 4836 insertions(+), 725 deletions(-) create mode 100644 inc/NTSecPKG.h create mode 100644 inc/winhttp.h create mode 100644 kekeo/modules/kuhl_m_ntlm.c create mode 100644 kekeo/modules/kuhl_m_ntlm.h create mode 100644 lib/Win32/winhttp.lib create mode 100644 lib/x64/winhttp.lib diff --git a/inc/NTSecPKG.h b/inc/NTSecPKG.h new file mode 100644 index 0000000..e52c79b --- /dev/null +++ b/inc/NTSecPKG.h @@ -0,0 +1,2133 @@ +/*++ BUILD Version: 0000 Increment this if a change has global effects + +Copyright (c) Microsoft Corporation. All rights reserved. + +Module Name: + + ntsecpkg.h + +Abstract: + + This module defines the structures and APIs for use by a + authentication or security package. + +Revision History: + +--*/ + +#ifndef _NTSECPKG_ +#define _NTSECPKG_ + +#ifdef __cplusplus +extern "C" { +#endif + + +///////////////////////////////////////////////////////////////////////// +// // +// Data types used by authentication packages // +// // +///////////////////////////////////////////////////////////////////////// + +// +// opaque data type which represents a client request +// + +typedef PVOID *PLSA_CLIENT_REQUEST; + + +// +// When a logon of a user is requested, the authentication package +// is expected to return one of the following structures indicating +// the contents of a user's token. +// + +typedef enum _LSA_TOKEN_INFORMATION_TYPE { + LsaTokenInformationNull, // Implies LSA_TOKEN_INFORMATION_NULL data type + LsaTokenInformationV1, // Implies LSA_TOKEN_INFORMATION_V1 data type + LsaTokenInformationV2 // Implies LSA_TOKEN_INFORMATION_V2 data type +} LSA_TOKEN_INFORMATION_TYPE, *PLSA_TOKEN_INFORMATION_TYPE; + + +// +// The NULL information is used in cases where a non-authenticated +// system access is needed. For example, a non-authentication network +// circuit (such as LAN Manager's null session) can be given NULL +// information. This will result in an anonymous token being generated +// for the logon that gives the user no ability to access protected system +// resources, but does allow access to non-protected system resources. +// + +typedef struct _LSA_TOKEN_INFORMATION_NULL { + + // + // Time at which the security context becomes invalid. + // Use a value in the distant future if the context + // never expires. + // + + LARGE_INTEGER ExpirationTime; + + // + // The SID(s) of groups the user is to be made a member of. This should + // not include WORLD or other system defined and assigned + // SIDs. These will be added automatically by LSA. + // + // Each SID is expected to be in a separately allocated block + // of memory. The TOKEN_GROUPS structure is also expected to + // be in a separately allocated block of memory. + // + + PTOKEN_GROUPS Groups; + +} LSA_TOKEN_INFORMATION_NULL, *PLSA_TOKEN_INFORMATION_NULL; + + +// +// The V1 token information structure is superceeded by the V2 token +// information structure. The V1 strucure should only be used for +// backwards compatability. +// This structure contains information that an authentication package +// can place in a Version 1 NT token object. +// + +typedef struct _LSA_TOKEN_INFORMATION_V1 { + + // + // Time at which the security context becomes invalid. + // Use a value in the distant future if the context + // never expires. + // + + LARGE_INTEGER ExpirationTime; + + // + // The SID of the user logging on. The SID value is in a + // separately allocated block of memory. + // + + TOKEN_USER User; + + // + // The SID(s) of groups the user is a member of. This should + // not include WORLD or other system defined and assigned + // SIDs. These will be added automatically by LSA. + // + // Each SID is expected to be in a separately allocated block + // of memory. The TOKEN_GROUPS structure is also expected to + // be in a separately allocated block of memory. + // + + PTOKEN_GROUPS Groups; + + // + // This field is used to establish the primary group of the user. + // This value does not have to correspond to one of the SIDs + // assigned to the user. + // + // The SID pointed to by this structure is expected to be in + // a separately allocated block of memory. + // + // This field is mandatory and must be filled in. + // + + TOKEN_PRIMARY_GROUP PrimaryGroup; + + + + // + // The privileges the user is assigned. This list of privileges + // will be augmented or over-ridden by any local security policy + // assigned privileges. + // + // Each privilege is expected to be in a separately allocated + // block of memory. The TOKEN_PRIVILEGES structure is also + // expected to be in a separately allocated block of memory. + // + // If there are no privileges to assign to the user, this field + // may be set to NULL. + // + + PTOKEN_PRIVILEGES Privileges; + + + + // + // This field may be used to establish an explicit default + // owner. Normally, the user ID is used as the default owner. + // If another value is desired, it must be specified here. + // + // The Owner.Sid field may be set to NULL to indicate there is no + // alternate default owner value. + // + + TOKEN_OWNER Owner; + + // + // This field may be used to establish a default + // protection for the user. If no value is provided, then + // a default protection that grants everyone all access will + // be established. + // + // The DefaultDacl.DefaultDacl field may be set to NULL to indicate + // there is no default protection. + // + + TOKEN_DEFAULT_DACL DefaultDacl; + +} LSA_TOKEN_INFORMATION_V1, *PLSA_TOKEN_INFORMATION_V1; + +// +// The V2 information is used in most cases of logon. The structure is identical +// to the V1 token information structure, with the exception that the memory allocation +// is handled differently. The LSA_TOKEN_INFORMATION_V2 structure is intended to be +// allocated monolithiclly, with the privileges, DACL, sids, and group array either part of +// same allocation, or allocated and freed externally. +// + +typedef LSA_TOKEN_INFORMATION_V1 LSA_TOKEN_INFORMATION_V2, *PLSA_TOKEN_INFORMATION_V2; + + +///////////////////////////////////////////////////////////////////////// +// // +// Interface definitions available for use by authentication packages // +// // +///////////////////////////////////////////////////////////////////////// + + + +typedef NTSTATUS +(NTAPI LSA_CREATE_LOGON_SESSION) ( + IN PLUID LogonId + ); + +typedef NTSTATUS +(NTAPI LSA_DELETE_LOGON_SESSION) ( + IN PLUID LogonId + ); + +typedef NTSTATUS +(NTAPI LSA_ADD_CREDENTIAL) ( + IN PLUID LogonId, + IN ULONG AuthenticationPackage, + IN PLSA_STRING PrimaryKeyValue, + IN PLSA_STRING Credentials + ); + +typedef NTSTATUS +(NTAPI LSA_GET_CREDENTIALS) ( + IN PLUID LogonId, + IN ULONG AuthenticationPackage, + IN OUT PULONG QueryContext, + IN BOOLEAN RetrieveAllCredentials, + IN PLSA_STRING PrimaryKeyValue, + OUT PULONG PrimaryKeyLength, + IN PLSA_STRING Credentials + ); + +typedef NTSTATUS +(NTAPI LSA_DELETE_CREDENTIAL) ( + IN PLUID LogonId, + IN ULONG AuthenticationPackage, + IN PLSA_STRING PrimaryKeyValue + ); + +typedef PVOID +(NTAPI LSA_ALLOCATE_LSA_HEAP) ( + IN ULONG Length + ); + +typedef VOID +(NTAPI LSA_FREE_LSA_HEAP) ( + IN PVOID Base + ); + +typedef PVOID +(NTAPI LSA_ALLOCATE_PRIVATE_HEAP) ( + IN SIZE_T Length + ); + +typedef VOID +(NTAPI LSA_FREE_PRIVATE_HEAP) ( + IN PVOID Base + ); + +typedef NTSTATUS +(NTAPI LSA_ALLOCATE_CLIENT_BUFFER) ( + IN PLSA_CLIENT_REQUEST ClientRequest, + IN ULONG LengthRequired, + OUT PVOID *ClientBaseAddress + ); + +typedef NTSTATUS +(NTAPI LSA_FREE_CLIENT_BUFFER) ( + IN PLSA_CLIENT_REQUEST ClientRequest, + IN PVOID ClientBaseAddress + ); + +typedef NTSTATUS +(NTAPI LSA_COPY_TO_CLIENT_BUFFER) ( + IN PLSA_CLIENT_REQUEST ClientRequest, + IN ULONG Length, + IN PVOID ClientBaseAddress, + IN PVOID BufferToCopy + ); + +typedef NTSTATUS +(NTAPI LSA_COPY_FROM_CLIENT_BUFFER) ( + IN PLSA_CLIENT_REQUEST ClientRequest, + IN ULONG Length, + IN PVOID BufferToCopy, + IN PVOID ClientBaseAddress + ); + +typedef LSA_CREATE_LOGON_SESSION * PLSA_CREATE_LOGON_SESSION; +typedef LSA_DELETE_LOGON_SESSION * PLSA_DELETE_LOGON_SESSION; +typedef LSA_ADD_CREDENTIAL * PLSA_ADD_CREDENTIAL; +typedef LSA_GET_CREDENTIALS * PLSA_GET_CREDENTIALS; +typedef LSA_DELETE_CREDENTIAL * PLSA_DELETE_CREDENTIAL; +typedef LSA_ALLOCATE_LSA_HEAP * PLSA_ALLOCATE_LSA_HEAP; +typedef LSA_FREE_LSA_HEAP * PLSA_FREE_LSA_HEAP; +typedef LSA_ALLOCATE_PRIVATE_HEAP * PLSA_ALLOCATE_PRIVATE_HEAP; +typedef LSA_FREE_PRIVATE_HEAP * PLSA_FREE_PRIVATE_HEAP; +typedef LSA_ALLOCATE_CLIENT_BUFFER * PLSA_ALLOCATE_CLIENT_BUFFER; +typedef LSA_FREE_CLIENT_BUFFER * PLSA_FREE_CLIENT_BUFFER; +typedef LSA_COPY_TO_CLIENT_BUFFER * PLSA_COPY_TO_CLIENT_BUFFER; +typedef LSA_COPY_FROM_CLIENT_BUFFER * PLSA_COPY_FROM_CLIENT_BUFFER; + +// +// The dispatch table of LSA services which are available to +// authentication packages. +// +typedef struct _LSA_DISPATCH_TABLE { + PLSA_CREATE_LOGON_SESSION CreateLogonSession; + PLSA_DELETE_LOGON_SESSION DeleteLogonSession; + PLSA_ADD_CREDENTIAL AddCredential; + PLSA_GET_CREDENTIALS GetCredentials; + PLSA_DELETE_CREDENTIAL DeleteCredential; + PLSA_ALLOCATE_LSA_HEAP AllocateLsaHeap; + PLSA_FREE_LSA_HEAP FreeLsaHeap; + PLSA_ALLOCATE_CLIENT_BUFFER AllocateClientBuffer; + PLSA_FREE_CLIENT_BUFFER FreeClientBuffer; + PLSA_COPY_TO_CLIENT_BUFFER CopyToClientBuffer; + PLSA_COPY_FROM_CLIENT_BUFFER CopyFromClientBuffer; +} LSA_DISPATCH_TABLE, *PLSA_DISPATCH_TABLE; + + + +//////////////////////////////////////////////////////////////////////////// +// // +// Interface definitions of services provided by authentication packages // +// // +//////////////////////////////////////////////////////////////////////////// + + + +// +// Routine names +// +// The routines provided by the DLL must be assigned the following names +// so that their addresses can be retrieved when the DLL is loaded. +// + +#define LSA_AP_NAME_INITIALIZE_PACKAGE "LsaApInitializePackage\0" +#define LSA_AP_NAME_LOGON_USER "LsaApLogonUser\0" +#define LSA_AP_NAME_LOGON_USER_EX "LsaApLogonUserEx\0" +#define LSA_AP_NAME_CALL_PACKAGE "LsaApCallPackage\0" +#define LSA_AP_NAME_LOGON_TERMINATED "LsaApLogonTerminated\0" +#define LSA_AP_NAME_CALL_PACKAGE_UNTRUSTED "LsaApCallPackageUntrusted\0" +#define LSA_AP_NAME_CALL_PACKAGE_PASSTHROUGH "LsaApCallPackagePassthrough\0" + + +// +// Routine templates +// + + +typedef NTSTATUS +(NTAPI LSA_AP_INITIALIZE_PACKAGE) ( + IN ULONG AuthenticationPackageId, + IN PLSA_DISPATCH_TABLE LsaDispatchTable, + IN PLSA_STRING Database OPTIONAL, + IN PLSA_STRING Confidentiality OPTIONAL, + OUT PLSA_STRING *AuthenticationPackageName + ); + +typedef NTSTATUS +(NTAPI LSA_AP_LOGON_USER) ( + IN PLSA_CLIENT_REQUEST ClientRequest, + IN SECURITY_LOGON_TYPE LogonType, + IN PVOID AuthenticationInformation, + IN PVOID ClientAuthenticationBase, + IN ULONG AuthenticationInformationLength, + OUT PVOID *ProfileBuffer, + OUT PULONG ProfileBufferLength, + OUT PLUID LogonId, + OUT PNTSTATUS SubStatus, + OUT PLSA_TOKEN_INFORMATION_TYPE TokenInformationType, + OUT PVOID *TokenInformation, + OUT PLSA_UNICODE_STRING *AccountName, + OUT PLSA_UNICODE_STRING *AuthenticatingAuthority + ); + +typedef NTSTATUS +(NTAPI LSA_AP_LOGON_USER_EX) ( + IN PLSA_CLIENT_REQUEST ClientRequest, + IN SECURITY_LOGON_TYPE LogonType, + IN PVOID AuthenticationInformation, + IN PVOID ClientAuthenticationBase, + IN ULONG AuthenticationInformationLength, + OUT PVOID *ProfileBuffer, + OUT PULONG ProfileBufferLength, + OUT PLUID LogonId, + OUT PNTSTATUS SubStatus, + OUT PLSA_TOKEN_INFORMATION_TYPE TokenInformationType, + OUT PVOID *TokenInformation, + OUT PUNICODE_STRING *AccountName, + OUT PUNICODE_STRING *AuthenticatingAuthority, + OUT PUNICODE_STRING *MachineName + ); + +typedef NTSTATUS +(NTAPI LSA_AP_CALL_PACKAGE) ( + IN PLSA_CLIENT_REQUEST ClientRequest, + IN PVOID ProtocolSubmitBuffer, + IN PVOID ClientBufferBase, + IN ULONG SubmitBufferLength, + OUT PVOID *ProtocolReturnBuffer, + OUT PULONG ReturnBufferLength, + OUT PNTSTATUS ProtocolStatus + ); + +typedef NTSTATUS +(NTAPI LSA_AP_CALL_PACKAGE_PASSTHROUGH) ( + IN PLSA_CLIENT_REQUEST ClientRequest, + IN PVOID ProtocolSubmitBuffer, + IN PVOID ClientBufferBase, + IN ULONG SubmitBufferLength, + OUT PVOID *ProtocolReturnBuffer, + OUT PULONG ReturnBufferLength, + OUT PNTSTATUS ProtocolStatus + ); + +typedef VOID +(NTAPI LSA_AP_LOGON_TERMINATED) ( + IN PLUID LogonId + ); + +typedef LSA_AP_CALL_PACKAGE LSA_AP_CALL_PACKAGE_UNTRUSTED; + +typedef LSA_AP_INITIALIZE_PACKAGE * PLSA_AP_INITIALIZE_PACKAGE; +typedef LSA_AP_LOGON_USER * PLSA_AP_LOGON_USER; +typedef LSA_AP_LOGON_USER_EX * PLSA_AP_LOGON_USER_EX; +typedef LSA_AP_CALL_PACKAGE * PLSA_AP_CALL_PACKAGE; +typedef LSA_AP_CALL_PACKAGE_PASSTHROUGH * PLSA_AP_CALL_PACKAGE_PASSTHROUGH; +typedef LSA_AP_LOGON_TERMINATED * PLSA_AP_LOGON_TERMINATED; +typedef LSA_AP_CALL_PACKAGE_UNTRUSTED * PLSA_AP_CALL_PACKAGE_UNTRUSTED; + + +#ifndef _SAM_CREDENTIAL_UPDATE_DEFINED +#define _SAM_CREDENTIAL_UPDATE_DEFINED + +typedef NTSTATUS (*PSAM_CREDENTIAL_UPDATE_NOTIFY_ROUTINE) ( + __in PUNICODE_STRING ClearPassword, + __in_bcount(OldCredentialSize) PVOID OldCredentials, + __in ULONG OldCredentialSize, + __in ULONG UserAccountControl, + __in_opt PUNICODE_STRING UPN, + __in PUNICODE_STRING UserName, + __in PUNICODE_STRING NetbiosDomainName, + __in PUNICODE_STRING DnsDomainName, + __deref_out_bcount(*NewCredentialSize) PVOID * NewCredentials, + __out ULONG * NewCredentialSize + ); + +#define SAM_CREDENTIAL_UPDATE_NOTIFY_ROUTINE "CredentialUpdateNotify" + +typedef BOOLEAN (*PSAM_CREDENTIAL_UPDATE_REGISTER_ROUTINE) ( + __out PUNICODE_STRING CredentialName + ); + +#define SAM_CREDENTIAL_UPDATE_REGISTER_ROUTINE "CredentialUpdateRegister" + +typedef VOID (*PSAM_CREDENTIAL_UPDATE_FREE_ROUTINE) ( + __in PVOID p + ); + +#define SAM_CREDENTIAL_UPDATE_FREE_ROUTINE "CredentialUpdateFree" + +typedef struct { + PSTR Original; + PSTR Mapped; + BOOLEAN Continuable; // only honored for some operations +} SAM_REGISTER_MAPPING_ELEMENT, *PSAM_REGISTER_MAPPING_ELEMENT; + +typedef struct { + ULONG Count; + __ecount(Count) PSAM_REGISTER_MAPPING_ELEMENT Elements; +} SAM_REGISTER_MAPPING_LIST, *PSAM_REGISTER_MAPPING_LIST; + +typedef struct { + ULONG Count; + __ecount(Count) PSAM_REGISTER_MAPPING_LIST Lists; +} SAM_REGISTER_MAPPING_TABLE, *PSAM_REGISTER_MAPPING_TABLE; + +typedef NTSTATUS (*PSAM_CREDENTIAL_UPDATE_REGISTER_MAPPED_ENTRYPOINTS_ROUTINE) ( + __out SAM_REGISTER_MAPPING_TABLE *Table + ); + +#define SAM_CREDENTIAL_UPDATE_REGISTER_MAPPED_ENTRYPOINTS_ROUTINE "RegisterMappedEntrypoints" + +#endif // _SAM_CREDENTIAL_UPDATE_DEFINED + + +#ifdef SECURITY_KERNEL +// +// Can't use the windows.h def'ns in kernel mode. +// +typedef PVOID SEC_THREAD_START; +typedef PVOID SEC_ATTRS; +#else +typedef LPTHREAD_START_ROUTINE SEC_THREAD_START; +typedef LPSECURITY_ATTRIBUTES SEC_ATTRS; +#endif + + +#define SecEqualLuid(L1, L2) \ + ( ( ((PLUID)L1)->LowPart == ((PLUID)L2)->LowPart ) && \ + ( ((PLUID)L1)->HighPart == ((PLUID)L2)->HighPart ) ) \ + +#define SecIsZeroLuid( L1 ) \ + ( ( L1->LowPart | L1->HighPart ) == 0 ) + +// +// The following structures are used by the helper functions +// + +typedef struct _SECPKG_CLIENT_INFO { + LUID LogonId; // Effective Logon Id + ULONG ProcessID; // Process Id of caller + ULONG ThreadID; // Thread Id of caller + BOOLEAN HasTcbPrivilege; // Client has TCB + BOOLEAN Impersonating; // Client is impersonating + BOOLEAN Restricted; // Client is restricted + + // + // NT 5.1 + // + + UCHAR ClientFlags; // Extra flags about the client + SECURITY_IMPERSONATION_LEVEL ImpersonationLevel; // Impersonation level of client + + // + // NT 6 + // + + HANDLE ClientToken; + +} SECPKG_CLIENT_INFO, * PSECPKG_CLIENT_INFO; + +#define SECPKG_CLIENT_PROCESS_TERMINATED 0x01 // The client process has terminated +#define SECPKG_CLIENT_THREAD_TERMINATED 0x02 // The client thread has terminated + +typedef struct _SECPKG_CALL_INFO { + ULONG ProcessId; + ULONG ThreadId; + ULONG Attributes; + ULONG CallCount; + PVOID MechOid; // mechanism objection identifer +} SECPKG_CALL_INFO, * PSECPKG_CALL_INFO; + +#define SECPKG_CALL_KERNEL_MODE 0x00000001 // Call originated in kernel mode +#define SECPKG_CALL_ANSI 0x00000002 // Call came from ANSI stub +#define SECPKG_CALL_URGENT 0x00000004 // Call designated urgent +#define SECPKG_CALL_RECURSIVE 0x00000008 // Call is recursing +#define SECPKG_CALL_IN_PROC 0x00000010 // Call originated in process +#define SECPKG_CALL_CLEANUP 0x00000020 // Call is cleanup from a client +#define SECPKG_CALL_WOWCLIENT 0x00000040 // Call is from a WOW client process +#define SECPKG_CALL_THREAD_TERM 0x00000080 // Call is from a thread that has term'd +#define SECPKG_CALL_PROCESS_TERM 0x00000100 // Call is from a process that has term'd +#define SECPKG_CALL_IS_TCB 0x00000200 // Call is from TCB +#define SECPKG_CALL_NETWORK_ONLY 0x00000400 // Call asks for network logon only, no cached logons +#define SECPKG_CALL_WINLOGON 0x00000800 // the caller of LsaLogonuser() is Winlogon +#define SECPKG_CALL_ASYNC_UPDATE 0x00001000 // asynchronous update for unlock +#define SECPKG_CALL_SYSTEM_PROC 0x00002000 // Call originated from the System process +#define SECPKG_CALL_NEGO 0x00004000 // Called by SPNEGO +#define SECPKG_CALL_NEGO_EXTENDER 0x00008000 // Called by NEGO extender +#define SECPKG_CALL_BUFFER_MARSHAL 0x00010000 // Buffer passed is marshaled (by RPC) + +typedef struct _SECPKG_SUPPLEMENTAL_CRED { + UNICODE_STRING PackageName; + ULONG CredentialSize; +#ifdef MIDL_PASS + [size_is(CredentialSize)] +#endif // MIDL_PASS + PUCHAR Credentials; +} SECPKG_SUPPLEMENTAL_CRED, *PSECPKG_SUPPLEMENTAL_CRED; + +typedef struct _SECPKG_BYTE_VECTOR +{ + ULONG ByteArrayOffset; // each element is a byte + USHORT ByteArrayLength; +} SECPKG_BYTE_VECTOR, *PSECPKG_BYTE_VECTOR; + +typedef struct _SECPKG_SHORT_VECTOR +{ + ULONG ShortArrayOffset; // each element is a short + USHORT ShortArrayCount; // number of characters +} SECPKG_SHORT_VECTOR, *PSECPKG_SHORT_VECTOR; + +// +// the supplied credential structure +// + +typedef struct _SECPKG_SUPPLIED_CREDENTIAL { + USHORT cbHeaderLength; // the length of the header + USHORT cbStructureLength; // pay load length including the header + SECPKG_SHORT_VECTOR UserName; // unicode only + SECPKG_SHORT_VECTOR DomainName; // unicode only + SECPKG_BYTE_VECTOR PackedCredentials; // SEC_WINNT_AUTH_PACKED_CREDENTIALS + ULONG CredFlags; // authidentity flags +} SECPKG_SUPPLIED_CREDENTIAL, *PSECPKG_SUPPLIED_CREDENTIAL; + +// +// the credential structure used by Nego2-SPMI +// + +#define SECPKG_CREDENTIAL_VERSION 201 + +// +// credentials flags +// + +#define SECPKG_CREDENTIAL_FLAGS_CALLER_HAS_TCB 0x1 + +typedef struct _SECPKG_CREDENTIAL { + ULONG64 Version; // contains SECPKG_CREDENTIAL_VERSION + USHORT cbHeaderLength; // the length of the header + ULONG cbStructureLength; // pay load length including the header, + // all the content of this structure is within a contiguous buffer + ULONG ClientProcess; // the caller's identity + ULONG ClientThread; // the caller's identity + LUID LogonId; // the caller's identity + HANDLE ClientToken; // the caller's identity + ULONG SessionId; // the caller's identity + LUID ModifiedId; // the caller's identity + ULONG fCredentials; // inbound or outbound? + ULONG Flags; // contains SECPKG_CREDENTIAL_FLAGS + SECPKG_BYTE_VECTOR PrincipalName; // not used + SECPKG_BYTE_VECTOR PackageList; // list of packages, relevant only to SPNEGO + SECPKG_BYTE_VECTOR MarshaledSuppliedCreds; // contains a SECPKG_SUPPLIED_CREDENTIAL structure +} SECPKG_CREDENTIAL, *PSECPKG_CREDENTIAL; + +typedef ULONG_PTR LSA_SEC_HANDLE; +typedef LSA_SEC_HANDLE * PLSA_SEC_HANDLE; +typedef struct _SECPKG_SUPPLEMENTAL_CRED_ARRAY { + ULONG CredentialCount; +#ifdef MIDL_PASS + [size_is(CredentialCount)] SECPKG_SUPPLEMENTAL_CRED Credentials[*]; +#else // MIDL_PASS + SECPKG_SUPPLEMENTAL_CRED Credentials[1]; +#endif // MIDL_PASS +} SECPKG_SUPPLEMENTAL_CRED_ARRAY, *PSECPKG_SUPPLEMENTAL_CRED_ARRAY; + +// +// This flag is used for to indicate which buffers in the LSA are located +// in the client's address space +// + +#define SECBUFFER_UNMAPPED 0x40000000 + +// +// This flag is used to indicate that the buffer was mapped into the LSA +// from kernel mode. +// + +#define SECBUFFER_KERNEL_MAP 0x20000000 + +typedef NTSTATUS +(NTAPI LSA_CALLBACK_FUNCTION)( + ULONG_PTR Argument1, + ULONG_PTR Argument2, + PSecBuffer InputBuffer, + PSecBuffer OutputBuffer + ); + +typedef LSA_CALLBACK_FUNCTION * PLSA_CALLBACK_FUNCTION; + + + +#define PRIMARY_CRED_CLEAR_PASSWORD 0x1 +#define PRIMARY_CRED_OWF_PASSWORD 0x2 +#define PRIMARY_CRED_UPDATE 0x4 // this is a change of existing creds +#define PRIMARY_CRED_CACHED_LOGON 0x8 +#define PRIMARY_CRED_LOGON_NO_TCB 0x10 +#define PRIMARY_CRED_LOGON_LUA 0x20 +#define PRIMARY_CRED_INTERACTIVE_SMARTCARD_LOGON 0x40 +#define PRIMARY_CRED_REFRESH_NEEDED 0x80 // unlock refresh needed + + +#define PRIMARY_CRED_LOGON_PACKAGE_SHIFT 24 +#define PRIMARY_CRED_PACKAGE_MASK 0xff000000 + +// +// For cached logons, the RPC id of the package doing the logon is identified +// by shifting the flags to the right by the PRIMARY_CRED_LOGON_PACKAGE_SHIFT. +// + +typedef struct _SECPKG_PRIMARY_CRED { + LUID LogonId; + UNICODE_STRING DownlevelName; // Sam Account Name + UNICODE_STRING DomainName; // Netbios domain name where account is located + UNICODE_STRING Password; + UNICODE_STRING OldPassword; + PSID UserSid; + ULONG Flags; + UNICODE_STRING DnsDomainName; // DNS domain name where account is located (if known) + UNICODE_STRING Upn; // UPN of account (if known) + + UNICODE_STRING LogonServer; + UNICODE_STRING Spare1; + UNICODE_STRING Spare2; + UNICODE_STRING Spare3; + UNICODE_STRING Spare4; +} SECPKG_PRIMARY_CRED, *PSECPKG_PRIMARY_CRED; + +// +// Maximum size of stored credentials. +// + +#define MAX_CRED_SIZE 1024 + +// Values for MachineState + +#define SECPKG_STATE_ENCRYPTION_PERMITTED 0x01 +#define SECPKG_STATE_STRONG_ENCRYPTION_PERMITTED 0x02 +#define SECPKG_STATE_DOMAIN_CONTROLLER 0x04 +#define SECPKG_STATE_WORKSTATION 0x08 +#define SECPKG_STATE_STANDALONE 0x10 + +typedef struct _SECPKG_PARAMETERS { + ULONG Version; + ULONG MachineState; + ULONG SetupMode; + PSID DomainSid; + UNICODE_STRING DomainName; + UNICODE_STRING DnsDomainName; + GUID DomainGuid; +} SECPKG_PARAMETERS, *PSECPKG_PARAMETERS; + + +// +// Extended Package information structures +// + +typedef enum _SECPKG_EXTENDED_INFORMATION_CLASS { + SecpkgGssInfo = 1, + SecpkgContextThunks, + SecpkgMutualAuthLevel, + SecpkgWowClientDll, + SecpkgExtraOids, + SecpkgMaxInfo, + SecpkgNego2Info, +} SECPKG_EXTENDED_INFORMATION_CLASS; + +typedef struct _SECPKG_GSS_INFO { + ULONG EncodedIdLength; + UCHAR EncodedId[4]; +} SECPKG_GSS_INFO, * PSECPKG_GSS_INFO; + +typedef struct _SECPKG_CONTEXT_THUNKS { + ULONG InfoLevelCount; + ULONG Levels[1]; +} SECPKG_CONTEXT_THUNKS, *PSECPKG_CONTEXT_THUNKS; + +typedef struct _SECPKG_MUTUAL_AUTH_LEVEL { + ULONG MutualAuthLevel; +} SECPKG_MUTUAL_AUTH_LEVEL, * PSECPKG_MUTUAL_AUTH_LEVEL; + +typedef struct _SECPKG_WOW_CLIENT_DLL { + SECURITY_STRING WowClientDllPath; +} SECPKG_WOW_CLIENT_DLL, * PSECPKG_WOW_CLIENT_DLL; + +#define SECPKG_MAX_OID_LENGTH 32 + +typedef struct _SECPKG_SERIALIZED_OID { + ULONG OidLength; + ULONG OidAttributes; + UCHAR OidValue[ SECPKG_MAX_OID_LENGTH ]; +} SECPKG_SERIALIZED_OID, * PSECPKG_SERIALIZED_OID; + +typedef struct _SECPKG_EXTRA_OIDS { + ULONG OidCount; + SECPKG_SERIALIZED_OID Oids[ 1 ]; +} SECPKG_EXTRA_OIDS, * PSECPKG_EXTRA_OIDS; + +// used by Nego2 +typedef struct _SECPKG_NEGO2_INFO { + UCHAR AuthScheme[16]; // auth id + ULONG PackageFlags; +} SECPKG_NEGO2_INFO, * PSECPKG_NEGO2_INFO; + +typedef struct _SECPKG_EXTENDED_INFORMATION { + SECPKG_EXTENDED_INFORMATION_CLASS Class; + union { + SECPKG_GSS_INFO GssInfo; + SECPKG_CONTEXT_THUNKS ContextThunks; + SECPKG_MUTUAL_AUTH_LEVEL MutualAuthLevel; + SECPKG_WOW_CLIENT_DLL WowClientDll; + SECPKG_EXTRA_OIDS ExtraOids; + SECPKG_NEGO2_INFO Nego2Info; + } Info; +} SECPKG_EXTENDED_INFORMATION, * PSECPKG_EXTENDED_INFORMATION; + +typedef struct _SECPKG_TARGETINFO +{ + PSID DomainSid; + PCWSTR ComputerName; +} SECPKG_TARGETINFO, *PSECPKG_TARGETINFO; + +#define SECPKG_ATTR_SASL_CONTEXT 0x00010000 + +typedef struct _SecPkgContext_SaslContext { + PVOID SaslContext; +} SecPkgContext_SaslContext, * PSecPkgContext_SaslContext; + +// +// Setting this value as the first context thunk value will cause all +// calls to go to the LSA: +// + +#define SECPKG_ATTR_THUNK_ALL 0x00010000 + + +#ifndef SECURITY_USER_DATA_DEFINED +#define SECURITY_USER_DATA_DEFINED + +typedef struct _SECURITY_USER_DATA { + SECURITY_STRING UserName; // User name + SECURITY_STRING LogonDomainName; // Domain the user logged on to + SECURITY_STRING LogonServer; // Server that logged the user on + PSID pSid; // SID of user +} SECURITY_USER_DATA, *PSECURITY_USER_DATA; + +typedef SECURITY_USER_DATA SecurityUserData, * PSecurityUserData; + + +#define UNDERSTANDS_LONG_NAMES 1 +#define NO_LONG_NAMES 2 + +#endif // SECURITY_USER_DATA_DEFINED + +////////////////////////////////////////////////////////////////////////// +// +// The following prototypes are to functions that are provided by the SPMgr +// to security packages. +// +////////////////////////////////////////////////////////////////////////// + +typedef NTSTATUS +(NTAPI LSA_IMPERSONATE_CLIENT) ( + VOID + ); + + +typedef NTSTATUS +(NTAPI LSA_UNLOAD_PACKAGE)( + VOID + ); + +typedef NTSTATUS +(NTAPI LSA_DUPLICATE_HANDLE)( + IN HANDLE SourceHandle, + OUT PHANDLE DestionationHandle); + + +typedef NTSTATUS +(NTAPI LSA_SAVE_SUPPLEMENTAL_CREDENTIALS)( + IN PLUID LogonId, + IN ULONG SupplementalCredSize, + IN PVOID SupplementalCreds, + IN BOOLEAN Synchronous + ); + + +typedef HANDLE +(NTAPI LSA_CREATE_THREAD)( + IN SEC_ATTRS SecurityAttributes, + IN ULONG StackSize, + IN SEC_THREAD_START StartFunction, + IN PVOID ThreadParameter, + IN ULONG CreationFlags, + OUT PULONG ThreadId + ); + + +typedef NTSTATUS +(NTAPI LSA_GET_CLIENT_INFO)( + OUT PSECPKG_CLIENT_INFO ClientInfo + ); + + +typedef HANDLE +(NTAPI LSA_REGISTER_NOTIFICATION)( + IN SEC_THREAD_START StartFunction, + IN PVOID Parameter, + IN ULONG NotificationType, + IN ULONG NotificationClass, + IN ULONG NotificationFlags, + IN ULONG IntervalMinutes, + IN OPTIONAL HANDLE WaitEvent + ); + + +typedef NTSTATUS +(NTAPI LSA_CANCEL_NOTIFICATION)( + IN HANDLE NotifyHandle + ); + +typedef NTSTATUS +(NTAPI LSA_MAP_BUFFER)( + IN PSecBuffer InputBuffer, + OUT PSecBuffer OutputBuffer + ); + +typedef NTSTATUS +(NTAPI LSA_CREATE_TOKEN) ( + IN PLUID LogonId, + IN PTOKEN_SOURCE TokenSource, + IN SECURITY_LOGON_TYPE LogonType, + IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, + IN LSA_TOKEN_INFORMATION_TYPE TokenInformationType, + IN PVOID TokenInformation, + IN PTOKEN_GROUPS TokenGroups, + IN PUNICODE_STRING AccountName, + IN PUNICODE_STRING AuthorityName, + IN PUNICODE_STRING Workstation, + IN PUNICODE_STRING ProfilePath, + OUT PHANDLE Token, + OUT PNTSTATUS SubStatus + ); + +typedef enum _SECPKG_SESSIONINFO_TYPE { + SecSessionPrimaryCred // SessionInformation is SECPKG_PRIMARY_CRED +} SECPKG_SESSIONINFO_TYPE; + +typedef NTSTATUS +(NTAPI LSA_CREATE_TOKEN_EX) ( + IN PLUID LogonId, + IN PTOKEN_SOURCE TokenSource, + IN SECURITY_LOGON_TYPE LogonType, + IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, + IN LSA_TOKEN_INFORMATION_TYPE TokenInformationType, + IN PVOID TokenInformation, + IN PTOKEN_GROUPS TokenGroups, + IN PUNICODE_STRING Workstation, + IN PUNICODE_STRING ProfilePath, + IN PVOID SessionInformation, + IN SECPKG_SESSIONINFO_TYPE SessionInformationType, + OUT PHANDLE Token, + OUT PNTSTATUS SubStatus + ); + +typedef VOID +(NTAPI LSA_AUDIT_LOGON) ( + IN NTSTATUS Status, + IN NTSTATUS SubStatus, + IN PUNICODE_STRING AccountName, + IN PUNICODE_STRING AuthenticatingAuthority, + IN PUNICODE_STRING WorkstationName, + IN OPTIONAL PSID UserSid, + IN SECURITY_LOGON_TYPE LogonType, + IN PTOKEN_SOURCE TokenSource, + IN PLUID LogonId + ); + +typedef NTSTATUS +(NTAPI LSA_CALL_PACKAGE) ( + IN PUNICODE_STRING AuthenticationPackage, + IN PVOID ProtocolSubmitBuffer, + IN ULONG SubmitBufferLength, + OUT PVOID *ProtocolReturnBuffer, + OUT PULONG ReturnBufferLength, + OUT PNTSTATUS ProtocolStatus + ); + +typedef NTSTATUS +(NTAPI LSA_CALL_PACKAGEEX) ( + IN PUNICODE_STRING AuthenticationPackage, + IN PVOID ClientBufferBase, + IN PVOID ProtocolSubmitBuffer, + IN ULONG SubmitBufferLength, + OUT PVOID *ProtocolReturnBuffer, + OUT PULONG ReturnBufferLength, + OUT PNTSTATUS ProtocolStatus + ); + +typedef NTSTATUS +(NTAPI LSA_CALL_PACKAGE_PASSTHROUGH) ( + IN PUNICODE_STRING AuthenticationPackage, + IN PVOID ClientBufferBase, + IN PVOID ProtocolSubmitBuffer, + IN ULONG SubmitBufferLength, + OUT PVOID *ProtocolReturnBuffer, + OUT PULONG ReturnBufferLength, + OUT PNTSTATUS ProtocolStatus + ); + +typedef BOOLEAN +(NTAPI LSA_GET_CALL_INFO) ( + OUT PSECPKG_CALL_INFO Info + ); + +typedef PVOID +(NTAPI LSA_CREATE_SHARED_MEMORY)( + ULONG MaxSize, + ULONG InitialSize + ); + +typedef PVOID +(NTAPI LSA_ALLOCATE_SHARED_MEMORY)( + PVOID SharedMem, + ULONG Size + ); + +typedef VOID +(NTAPI LSA_FREE_SHARED_MEMORY)( + PVOID SharedMem, + PVOID Memory + ); + +typedef BOOLEAN +(NTAPI LSA_DELETE_SHARED_MEMORY)( + PVOID SharedMem + ); + +// +// Account Access +// + +typedef enum _SECPKG_NAME_TYPE { + SecNameSamCompatible, + SecNameAlternateId, + SecNameFlat, + SecNameDN, + SecNameSPN +} SECPKG_NAME_TYPE; + +typedef NTSTATUS +(NTAPI LSA_OPEN_SAM_USER)( + PSECURITY_STRING Name, + SECPKG_NAME_TYPE NameType, + PSECURITY_STRING Prefix, + BOOLEAN AllowGuest, + ULONG Reserved, + PVOID * UserHandle + ); + +typedef NTSTATUS +(NTAPI LSA_GET_USER_CREDENTIALS)( + PVOID UserHandle, + PVOID * PrimaryCreds, + PULONG PrimaryCredsSize, + PVOID * SupplementalCreds, + PULONG SupplementalCredsSize + ); + +typedef NTSTATUS +(NTAPI LSA_GET_USER_AUTH_DATA)( + PVOID UserHandle, + PUCHAR * UserAuthData, + PULONG UserAuthDataSize + ); + +typedef NTSTATUS +(NTAPI LSA_CLOSE_SAM_USER)( + PVOID UserHandle + ); + +typedef NTSTATUS +(NTAPI LSA_GET_AUTH_DATA_FOR_USER)( + PSECURITY_STRING Name, + SECPKG_NAME_TYPE NameType, + PSECURITY_STRING Prefix, + PUCHAR * UserAuthData, + PULONG UserAuthDataSize, + PUNICODE_STRING UserFlatName + ); + +typedef NTSTATUS +(NTAPI LSA_CONVERT_AUTH_DATA_TO_TOKEN)( + IN PVOID UserAuthData, + IN ULONG UserAuthDataSize, + IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, + IN PTOKEN_SOURCE TokenSource, + IN SECURITY_LOGON_TYPE LogonType, + IN PUNICODE_STRING AuthorityName, + OUT PHANDLE Token, + OUT PLUID LogonId, + OUT PUNICODE_STRING AccountName, + OUT PNTSTATUS SubStatus + ); + +typedef NTSTATUS +(NTAPI LSA_CRACK_SINGLE_NAME)( + IN ULONG FormatOffered, + IN BOOLEAN PerformAtGC, + IN PUNICODE_STRING NameInput, + IN PUNICODE_STRING Prefix OPTIONAL, + IN ULONG RequestedFormat, + OUT PUNICODE_STRING CrackedName, + OUT PUNICODE_STRING DnsDomainName, + OUT PULONG SubStatus + ); + +typedef NTSTATUS +(NTAPI LSA_AUDIT_ACCOUNT_LOGON)( + IN ULONG AuditId, + IN BOOLEAN Success, + IN PUNICODE_STRING Source, + IN PUNICODE_STRING ClientName, + IN PUNICODE_STRING MappedName, + IN NTSTATUS Status + ); + + +typedef NTSTATUS +(NTAPI LSA_CLIENT_CALLBACK)( + __in PCHAR Callback, + __in ULONG_PTR Argument1, + __in ULONG_PTR Argument2, + __in PSecBuffer Input, + __out PSecBuffer Output + ); + +typedef +NTSTATUS +(NTAPI LSA_REGISTER_CALLBACK)( + ULONG CallbackId, + PLSA_CALLBACK_FUNCTION Callback + ); + +#define NOTIFIER_FLAG_NEW_THREAD 0x00000001 +#define NOTIFIER_FLAG_ONE_SHOT 0x00000002 +#define NOTIFIER_FLAG_SECONDS 0x80000000 + +#define NOTIFIER_TYPE_INTERVAL 1 +#define NOTIFIER_TYPE_HANDLE_WAIT 2 +#define NOTIFIER_TYPE_STATE_CHANGE 3 +#define NOTIFIER_TYPE_NOTIFY_EVENT 4 +#define NOTIFIER_TYPE_IMMEDIATE 16 + +#define NOTIFY_CLASS_PACKAGE_CHANGE 1 +#define NOTIFY_CLASS_ROLE_CHANGE 2 +#define NOTIFY_CLASS_DOMAIN_CHANGE 3 +#define NOTIFY_CLASS_REGISTRY_CHANGE 4 + +typedef struct _SECPKG_EVENT_PACKAGE_CHANGE { + ULONG ChangeType; + LSA_SEC_HANDLE PackageId; + SECURITY_STRING PackageName; +} SECPKG_EVENT_PACKAGE_CHANGE, * PSECPKG_EVENT_PACKAGE_CHANGE; + +#define SECPKG_PACKAGE_CHANGE_LOAD 0 +#define SECPKG_PACKAGE_CHANGE_UNLOAD 1 +#define SECPKG_PACKAGE_CHANGE_SELECT 2 + +typedef struct _SECPKG_EVENT_ROLE_CHANGE { + ULONG PreviousRole; + ULONG NewRole; +} SECPKG_EVENT_ROLE_CHANGE, * PSECPKG_EVENT_ROLE_CHANGE; + +typedef struct _SECPKG_PARAMETERS SECPKG_EVENT_DOMAIN_CHANGE; +typedef struct _SECPKG_PARAMETERS * PSECPKG_EVENT_DOMAIN_CHANGE; + + +typedef struct _SECPKG_EVENT_NOTIFY { + ULONG EventClass; + ULONG Reserved; + ULONG EventDataSize; + PVOID EventData; + PVOID PackageParameter; +} SECPKG_EVENT_NOTIFY, *PSECPKG_EVENT_NOTIFY; + + +typedef +NTSTATUS +(NTAPI LSA_UPDATE_PRIMARY_CREDENTIALS)( + IN PSECPKG_PRIMARY_CRED PrimaryCredentials, + IN OPTIONAL PSECPKG_SUPPLEMENTAL_CRED_ARRAY Credentials + ); + +typedef +VOID +(NTAPI LSA_PROTECT_MEMORY)( + IN PVOID Buffer, + IN ULONG BufferSize + ); + +typedef +NTSTATUS +(NTAPI LSA_OPEN_TOKEN_BY_LOGON_ID)( + IN PLUID LogonId, + OUT HANDLE *RetTokenHandle + ); + +typedef +NTSTATUS +(NTAPI LSA_EXPAND_AUTH_DATA_FOR_DOMAIN)( + IN PUCHAR UserAuthData, + IN ULONG UserAuthDataSize, + IN PVOID Reserved, + OUT PUCHAR * ExpandedAuthData, + OUT PULONG ExpandedAuthDataSize + ); + +typedef LSA_IMPERSONATE_CLIENT * PLSA_IMPERSONATE_CLIENT; +typedef LSA_UNLOAD_PACKAGE * PLSA_UNLOAD_PACKAGE; +typedef LSA_DUPLICATE_HANDLE * PLSA_DUPLICATE_HANDLE; +typedef LSA_SAVE_SUPPLEMENTAL_CREDENTIALS * PLSA_SAVE_SUPPLEMENTAL_CREDENTIALS; +typedef LSA_CREATE_THREAD * PLSA_CREATE_THREAD; +typedef LSA_GET_CLIENT_INFO * PLSA_GET_CLIENT_INFO; +typedef LSA_REGISTER_NOTIFICATION * PLSA_REGISTER_NOTIFICATION; +typedef LSA_CANCEL_NOTIFICATION * PLSA_CANCEL_NOTIFICATION; +typedef LSA_MAP_BUFFER * PLSA_MAP_BUFFER; +typedef LSA_CREATE_TOKEN * PLSA_CREATE_TOKEN; +typedef LSA_AUDIT_LOGON * PLSA_AUDIT_LOGON; +typedef LSA_CALL_PACKAGE * PLSA_CALL_PACKAGE; +typedef LSA_CALL_PACKAGEEX * PLSA_CALL_PACKAGEEX; +typedef LSA_GET_CALL_INFO * PLSA_GET_CALL_INFO; +typedef LSA_CREATE_SHARED_MEMORY * PLSA_CREATE_SHARED_MEMORY; +typedef LSA_ALLOCATE_SHARED_MEMORY * PLSA_ALLOCATE_SHARED_MEMORY; +typedef LSA_FREE_SHARED_MEMORY * PLSA_FREE_SHARED_MEMORY; +typedef LSA_DELETE_SHARED_MEMORY * PLSA_DELETE_SHARED_MEMORY; +typedef LSA_OPEN_SAM_USER * PLSA_OPEN_SAM_USER; +typedef LSA_GET_USER_CREDENTIALS * PLSA_GET_USER_CREDENTIALS; +typedef LSA_GET_USER_AUTH_DATA * PLSA_GET_USER_AUTH_DATA; +typedef LSA_CLOSE_SAM_USER * PLSA_CLOSE_SAM_USER; +typedef LSA_CONVERT_AUTH_DATA_TO_TOKEN * PLSA_CONVERT_AUTH_DATA_TO_TOKEN; +typedef LSA_CLIENT_CALLBACK * PLSA_CLIENT_CALLBACK; +typedef LSA_REGISTER_CALLBACK * PLSA_REGISTER_CALLBACK; +typedef LSA_UPDATE_PRIMARY_CREDENTIALS * PLSA_UPDATE_PRIMARY_CREDENTIALS; +typedef LSA_GET_AUTH_DATA_FOR_USER * PLSA_GET_AUTH_DATA_FOR_USER; +typedef LSA_CRACK_SINGLE_NAME * PLSA_CRACK_SINGLE_NAME; +typedef LSA_AUDIT_ACCOUNT_LOGON * PLSA_AUDIT_ACCOUNT_LOGON; +typedef LSA_CALL_PACKAGE_PASSTHROUGH * PLSA_CALL_PACKAGE_PASSTHROUGH; +typedef LSA_PROTECT_MEMORY * PLSA_PROTECT_MEMORY; +typedef LSA_OPEN_TOKEN_BY_LOGON_ID * PLSA_OPEN_TOKEN_BY_LOGON_ID; +typedef LSA_EXPAND_AUTH_DATA_FOR_DOMAIN * PLSA_EXPAND_AUTH_DATA_FOR_DOMAIN; +typedef LSA_CREATE_TOKEN_EX * PLSA_CREATE_TOKEN_EX; + +#ifdef _WINCRED_H_ + +// +// When passing a credential around, the CredentialBlob field is encrypted. +// This structure describes this encrypted form. +// +// +#ifndef _ENCRYPTED_CREDENTIAL_DEFINED +#define _ENCRYPTED_CREDENTIAL_DEFINED + +typedef struct _ENCRYPTED_CREDENTIALW { + + // + // The credential + // + // The CredentialBlob field points to the encrypted credential + // The CredentialBlobSize field is the length (in bytes) of the encrypted credential + // + + CREDENTIALW Cred; + + // + // The size in bytes of the clear text credential blob + // + + ULONG ClearCredentialBlobSize; +} ENCRYPTED_CREDENTIALW, *PENCRYPTED_CREDENTIALW; +#endif // _ENCRYPTED_CREDENTIAL_DEFINED + +// +// Values for CredFlags parameter +// + +#define CREDP_FLAGS_IN_PROCESS 0x01 // Caller is in-process. Password data may be returned +#define CREDP_FLAGS_USE_MIDL_HEAP 0x02 // Allocated buffer should use MIDL_user_allocte +#define CREDP_FLAGS_DONT_CACHE_TI 0x04 // TargetInformation shouldn't be cached for CredGetTargetInfo +#define CREDP_FLAGS_CLEAR_PASSWORD 0x08 // Credential blob is passed in in-the-clear +#define CREDP_FLAGS_USER_ENCRYPTED_PASSWORD 0x10 // Credential blob is passed protected by RtlEncryptMemory +#define CREDP_FLAGS_TRUSTED_CALLER 0x20 // Caller is a trusted process (eg. logon process). + +// +// Possible forms of the username returned from CredMan +// + +typedef enum _CredParsedUserNameType +{ + parsedUsernameInvalid = 0, + parsedUsernameUpn, + parsedUsernameNt4Style, + parsedUsernameCertificate, + parsedUsernameNonQualified +} CredParsedUserNameType; + + +typedef NTSTATUS +(NTAPI CredReadFn) ( + IN PLUID LogonId, + IN ULONG CredFlags, + IN LPWSTR TargetName, + IN ULONG Type, + IN ULONG Flags, + OUT PENCRYPTED_CREDENTIALW *Credential + ); + +typedef NTSTATUS +(NTAPI CredReadDomainCredentialsFn) ( + IN PLUID LogonId, + IN ULONG CredFlags, + IN PCREDENTIAL_TARGET_INFORMATIONW TargetInfo, + IN ULONG Flags, + OUT PULONG Count, + OUT PENCRYPTED_CREDENTIALW **Credential + ); + +typedef VOID +(NTAPI CredFreeCredentialsFn) ( + IN ULONG Count, + IN PENCRYPTED_CREDENTIALW *Credentials OPTIONAL + ); + +typedef NTSTATUS +(NTAPI CredWriteFn) ( + IN PLUID LogonId, + IN ULONG CredFlags, + IN PENCRYPTED_CREDENTIALW Credential, + IN ULONG Flags + ); + +typedef NTSTATUS +(NTAPI CrediUnmarshalandDecodeStringFn)( + IN LPWSTR MarshaledString, + OUT LPBYTE *Blob, + OUT ULONG *BlobSize, + OUT BOOLEAN *IsFailureFatal + ); + + +NTSTATUS +CredMarshalTargetInfo ( + __in PCREDENTIAL_TARGET_INFORMATIONW InTargetInfo, + __deref_out PUSHORT *Buffer, + __out PULONG BufferSize + ); + +NTSTATUS +CredUnmarshalTargetInfo ( + __in_bcount(BufferSize) PUSHORT Buffer, + __in ULONG BufferSize, + __out_opt PCREDENTIAL_TARGET_INFORMATIONW *RetTargetInfo, + __out_opt PULONG RetActualSize + ); + +// Number of bytes consumed by the trailing size ULONG +#define CRED_MARSHALED_TI_SIZE_SIZE 12 + +NTSTATUS +CredParseUserNameWithType ( + __inout LPWSTR szParseName, + __out_opt PUNICODE_STRING pUserName, + __out_opt PUNICODE_STRING pDomainName, + __out CredParsedUserNameType * pParseType + ); + +#endif // _WINCRED_H_ + + +// +// Pure 32-bit versions of credential structures for packages +// running wow64: +// + +typedef struct _SEC_WINNT_AUTH_IDENTITY32 { + ULONG User; + ULONG UserLength; + ULONG Domain; + ULONG DomainLength; + ULONG Password; + ULONG PasswordLength; + ULONG Flags; +} SEC_WINNT_AUTH_IDENTITY32, * PSEC_WINNT_AUTH_IDENTITY32; + +typedef struct _SEC_WINNT_AUTH_IDENTITY_EX32 { + ULONG Version; + ULONG Length; + ULONG User; + ULONG UserLength; + ULONG Domain; + ULONG DomainLength; + ULONG Password; + ULONG PasswordLength; + ULONG Flags; + ULONG PackageList; + ULONG PackageListLength; +} SEC_WINNT_AUTH_IDENTITY_EX32, * PSEC_WINNT_AUTH_IDENTITY_EX32; + +// Functions provided by the SPM to the packages: +typedef struct _LSA_SECPKG_FUNCTION_TABLE { + PLSA_CREATE_LOGON_SESSION CreateLogonSession; + PLSA_DELETE_LOGON_SESSION DeleteLogonSession; + PLSA_ADD_CREDENTIAL AddCredential; + PLSA_GET_CREDENTIALS GetCredentials; + PLSA_DELETE_CREDENTIAL DeleteCredential; + PLSA_ALLOCATE_LSA_HEAP AllocateLsaHeap; + PLSA_FREE_LSA_HEAP FreeLsaHeap; + PLSA_ALLOCATE_CLIENT_BUFFER AllocateClientBuffer; + PLSA_FREE_CLIENT_BUFFER FreeClientBuffer; + PLSA_COPY_TO_CLIENT_BUFFER CopyToClientBuffer; + PLSA_COPY_FROM_CLIENT_BUFFER CopyFromClientBuffer; + PLSA_IMPERSONATE_CLIENT ImpersonateClient; + PLSA_UNLOAD_PACKAGE UnloadPackage; + PLSA_DUPLICATE_HANDLE DuplicateHandle; + PLSA_SAVE_SUPPLEMENTAL_CREDENTIALS SaveSupplementalCredentials; + PLSA_CREATE_THREAD CreateThread; + PLSA_GET_CLIENT_INFO GetClientInfo; + PLSA_REGISTER_NOTIFICATION RegisterNotification; + PLSA_CANCEL_NOTIFICATION CancelNotification; + PLSA_MAP_BUFFER MapBuffer; + PLSA_CREATE_TOKEN CreateToken; + PLSA_AUDIT_LOGON AuditLogon; + PLSA_CALL_PACKAGE CallPackage; + PLSA_FREE_LSA_HEAP FreeReturnBuffer; + PLSA_GET_CALL_INFO GetCallInfo; + PLSA_CALL_PACKAGEEX CallPackageEx; + PLSA_CREATE_SHARED_MEMORY CreateSharedMemory; + PLSA_ALLOCATE_SHARED_MEMORY AllocateSharedMemory; + PLSA_FREE_SHARED_MEMORY FreeSharedMemory; + PLSA_DELETE_SHARED_MEMORY DeleteSharedMemory; + PLSA_OPEN_SAM_USER OpenSamUser; + PLSA_GET_USER_CREDENTIALS GetUserCredentials; + PLSA_GET_USER_AUTH_DATA GetUserAuthData; + PLSA_CLOSE_SAM_USER CloseSamUser; + PLSA_CONVERT_AUTH_DATA_TO_TOKEN ConvertAuthDataToToken; + PLSA_CLIENT_CALLBACK ClientCallback; + PLSA_UPDATE_PRIMARY_CREDENTIALS UpdateCredentials; + PLSA_GET_AUTH_DATA_FOR_USER GetAuthDataForUser; + PLSA_CRACK_SINGLE_NAME CrackSingleName; + PLSA_AUDIT_ACCOUNT_LOGON AuditAccountLogon; + PLSA_CALL_PACKAGE_PASSTHROUGH CallPackagePassthrough; +#ifdef _WINCRED_H_ + CredReadFn *CrediRead; + CredReadDomainCredentialsFn *CrediReadDomainCredentials; + CredFreeCredentialsFn *CrediFreeCredentials; +#else // _WINCRED_H_ + PLSA_PROTECT_MEMORY DummyFunction1; + PLSA_PROTECT_MEMORY DummyFunction2; + PLSA_PROTECT_MEMORY DummyFunction3; +#endif // _WINCRED_H_ + PLSA_PROTECT_MEMORY LsaProtectMemory; + PLSA_PROTECT_MEMORY LsaUnprotectMemory; + PLSA_OPEN_TOKEN_BY_LOGON_ID OpenTokenByLogonId; + PLSA_EXPAND_AUTH_DATA_FOR_DOMAIN ExpandAuthDataForDomain; + PLSA_ALLOCATE_PRIVATE_HEAP AllocatePrivateHeap; + PLSA_FREE_PRIVATE_HEAP FreePrivateHeap; + PLSA_CREATE_TOKEN_EX CreateTokenEx; +#ifdef _WINCRED_H_ + CredWriteFn *CrediWrite; + CrediUnmarshalandDecodeStringFn *CrediUnmarshalandDecodeString; +#else // _WINCRED_H_ + PLSA_PROTECT_MEMORY DummyFunction4; + PLSA_PROTECT_MEMORY DummyFunction5; +#endif // _WINCRED_H_ +} LSA_SECPKG_FUNCTION_TABLE, *PLSA_SECPKG_FUNCTION_TABLE; + + +typedef +PVOID +(NTAPI LSA_LOCATE_PKG_BY_ID)( + __in ULONG PackgeId + ); + +typedef LSA_LOCATE_PKG_BY_ID * PLSA_LOCATE_PKG_BY_ID; + +typedef struct _SECPKG_DLL_FUNCTIONS { + PLSA_ALLOCATE_LSA_HEAP AllocateHeap; + PLSA_FREE_LSA_HEAP FreeHeap; + PLSA_REGISTER_CALLBACK RegisterCallback; + PLSA_LOCATE_PKG_BY_ID LocatePackageById; +} SECPKG_DLL_FUNCTIONS, * PSECPKG_DLL_FUNCTIONS; + + +// +// The following prototypes are to functions that will be called only while +// in the Security Package Manager context. +// + +typedef NTSTATUS +(NTAPI SpInitializeFn)( + IN ULONG_PTR PackageId, + IN PSECPKG_PARAMETERS Parameters, + IN PLSA_SECPKG_FUNCTION_TABLE FunctionTable + ); + +typedef NTSTATUS +(NTAPI SpShutdownFn)( + VOID + ); + +typedef NTSTATUS +(NTAPI SpGetInfoFn)( + OUT PSecPkgInfo PackageInfo + ); + +typedef NTSTATUS +(NTAPI SpGetExtendedInformationFn)( + IN SECPKG_EXTENDED_INFORMATION_CLASS Class, + OUT PSECPKG_EXTENDED_INFORMATION * ppInformation + ); + +typedef NTSTATUS +(NTAPI SpSetExtendedInformationFn)( + IN SECPKG_EXTENDED_INFORMATION_CLASS Class, + IN PSECPKG_EXTENDED_INFORMATION Info + ); + +typedef NTSTATUS +(LSA_AP_LOGON_USER_EX2) ( + __in PLSA_CLIENT_REQUEST ClientRequest, + __in SECURITY_LOGON_TYPE LogonType, + __in_bcount(SubmitBufferSize) PVOID ProtocolSubmitBuffer, + __in PVOID ClientBufferBase, + __in ULONG SubmitBufferSize, + __deref_out_bcount(*ProfileBufferSize) PVOID *ProfileBuffer, + __out PULONG ProfileBufferSize, + __out PLUID LogonId, + __out PNTSTATUS SubStatus, + __out PLSA_TOKEN_INFORMATION_TYPE TokenInformationType, + __deref_out PVOID *TokenInformation, + __out PUNICODE_STRING *AccountName, + __out PUNICODE_STRING *AuthenticatingAuthority, + __out PUNICODE_STRING *MachineName, + __out PSECPKG_PRIMARY_CRED PrimaryCredentials, + __deref_out PSECPKG_SUPPLEMENTAL_CRED_ARRAY * SupplementalCredentials + ); + +typedef LSA_AP_LOGON_USER_EX2 *PLSA_AP_LOGON_USER_EX2; +#define LSA_AP_NAME_LOGON_USER_EX2 "LsaApLogonUserEx2\0" + +typedef NTSTATUS +(NTAPI SpAcceptCredentialsFn)( + IN SECURITY_LOGON_TYPE LogonType, + IN PUNICODE_STRING AccountName, + IN PSECPKG_PRIMARY_CRED PrimaryCredentials, + IN PSECPKG_SUPPLEMENTAL_CRED SupplementalCredentials + ); +#define SP_ACCEPT_CREDENTIALS_NAME "SpAcceptCredentials\0" + +typedef NTSTATUS +(NTAPI SpAcquireCredentialsHandleFn)( + IN OPTIONAL PUNICODE_STRING PrincipalName, + IN ULONG CredentialUseFlags, + IN OPTIONAL PLUID LogonId, + IN PVOID AuthorizationData, + IN PVOID GetKeyFunciton, + IN PVOID GetKeyArgument, + OUT PLSA_SEC_HANDLE CredentialHandle, + OUT PTimeStamp ExpirationTime + ); + +typedef NTSTATUS +(NTAPI SpFreeCredentialsHandleFn)( + IN LSA_SEC_HANDLE CredentialHandle + ); + +typedef NTSTATUS +(NTAPI SpQueryCredentialsAttributesFn)( + IN LSA_SEC_HANDLE CredentialHandle, + IN ULONG CredentialAttribute, + IN OUT PVOID Buffer + ); + +typedef NTSTATUS +(NTAPI SpSetCredentialsAttributesFn)( + IN LSA_SEC_HANDLE CredentialHandle, + IN ULONG CredentialAttribute, + IN PVOID Buffer, + IN ULONG BufferSize ); + +typedef NTSTATUS +(NTAPI SpAddCredentialsFn)( + IN LSA_SEC_HANDLE CredentialHandle, + IN OPTIONAL PUNICODE_STRING PrincipalName, + IN PUNICODE_STRING Package, + IN ULONG CredentialUseFlags, + IN PVOID AuthorizationData, + IN PVOID GetKeyFunciton, + IN PVOID GetKeyArgument, + OUT PTimeStamp ExpirationTime + ); + +typedef NTSTATUS +(NTAPI SpSaveCredentialsFn)( + IN LSA_SEC_HANDLE CredentialHandle, + IN PSecBuffer Credentials); + +typedef NTSTATUS +(NTAPI SpGetCredentialsFn)( + IN LSA_SEC_HANDLE CredentialHandle, + IN OUT PSecBuffer Credentials + ); + +typedef NTSTATUS +(NTAPI SpDeleteCredentialsFn)( + IN LSA_SEC_HANDLE CredentialHandle, + IN PSecBuffer Key + ); + +typedef NTSTATUS +(NTAPI SpInitLsaModeContextFn)( + IN OPTIONAL LSA_SEC_HANDLE CredentialHandle, + IN OPTIONAL LSA_SEC_HANDLE ContextHandle, + IN OPTIONAL PUNICODE_STRING TargetName, + IN ULONG ContextRequirements, + IN ULONG TargetDataRep, + IN PSecBufferDesc InputBuffers, + OUT PLSA_SEC_HANDLE NewContextHandle, + IN OUT PSecBufferDesc OutputBuffers, + OUT PULONG ContextAttributes, + OUT PTimeStamp ExpirationTime, + OUT PBOOLEAN MappedContext, + OUT PSecBuffer ContextData + ); + + + + +typedef NTSTATUS +(NTAPI SpDeleteContextFn)( + IN LSA_SEC_HANDLE ContextHandle + ); + +typedef NTSTATUS +(NTAPI SpApplyControlTokenFn)( + IN LSA_SEC_HANDLE ContextHandle, + IN PSecBufferDesc ControlToken); + + +typedef NTSTATUS +(NTAPI SpAcceptLsaModeContextFn)( + IN OPTIONAL LSA_SEC_HANDLE CredentialHandle, + IN OPTIONAL LSA_SEC_HANDLE ContextHandle, + IN PSecBufferDesc InputBuffer, + IN ULONG ContextRequirements, + IN ULONG TargetDataRep, + OUT PLSA_SEC_HANDLE NewContextHandle, + OUT PSecBufferDesc OutputBuffer, + OUT PULONG ContextAttributes, + OUT PTimeStamp ExpirationTime, + OUT PBOOLEAN MappedContext, + OUT PSecBuffer ContextData + ); + + + + +typedef NTSTATUS +(NTAPI SpGetUserInfoFn)( + IN PLUID LogonId, + IN ULONG Flags, + OUT PSecurityUserData * UserData + ); + +typedef NTSTATUS +(NTAPI SpQueryContextAttributesFn)( + IN LSA_SEC_HANDLE ContextHandle, + IN ULONG ContextAttribute, + IN OUT PVOID Buffer); + +typedef NTSTATUS +(NTAPI SpSetContextAttributesFn)( + IN LSA_SEC_HANDLE ContextHandle, + IN ULONG ContextAttribute, + IN PVOID Buffer, + IN ULONG BufferSize ); + +typedef NTSTATUS +(NTAPI SpChangeAccountPasswordFn)( + __in PUNICODE_STRING pDomainName, + __in PUNICODE_STRING pAccountName, + __in PUNICODE_STRING pOldPassword, + __in PUNICODE_STRING pNewPassword, + __in BOOLEAN Impersonating, + __inout PSecBufferDesc pOutput + ); + +typedef NTSTATUS +(NTAPI SpQueryMetaDataFn)( + __in_opt LSA_SEC_HANDLE CredentialHandle, + __in_opt PUNICODE_STRING TargetName, + __in ULONG ContextRequirements, + __out PULONG MetaDataLength, + __deref_out_bcount(*MetaDataLength) PUCHAR* MetaData, + __inout PLSA_SEC_HANDLE ContextHandle + ); + +typedef NTSTATUS +(NTAPI SpExchangeMetaDataFn)( + __in_opt LSA_SEC_HANDLE CredentialHandle, + __in_opt PUNICODE_STRING TargetName, + __in ULONG ContextRequirements, + __in ULONG MetaDataLength, + __in_bcount(MetaDataLength) PUCHAR MetaData, + __inout PLSA_SEC_HANDLE ContextHandle + ); + +typedef NTSTATUS +(NTAPI SpGetCredUIContextFn)( + __in LSA_SEC_HANDLE ContextHandle, + __in GUID* CredType, + __out PULONG FlatCredUIContextLength, + __deref_out_bcount(*FlatCredUIContextLength) PUCHAR* FlatCredUIContext + ); + +typedef NTSTATUS +(NTAPI SpUpdateCredentialsFn)( + __in LSA_SEC_HANDLE ContextHandle, + __in GUID* CredType, + __in ULONG FlatCredUIContextLength, + __in_bcount(FlatCredUIContextLength) PUCHAR FlatCredUIContext + ); + +typedef NTSTATUS +(NTAPI SpValidateTargetInfoFn) ( + __in_opt PLSA_CLIENT_REQUEST ClientRequest, + __in_bcount(SubmitBufferLength) PVOID ProtocolSubmitBuffer, + __in PVOID ClientBufferBase, + __in ULONG SubmitBufferLength, + __in PSECPKG_TARGETINFO TargetInfo + ); + +typedef struct _SECPKG_FUNCTION_TABLE { + PLSA_AP_INITIALIZE_PACKAGE InitializePackage; + PLSA_AP_LOGON_USER LogonUser; + PLSA_AP_CALL_PACKAGE CallPackage; + PLSA_AP_LOGON_TERMINATED LogonTerminated; + PLSA_AP_CALL_PACKAGE_UNTRUSTED CallPackageUntrusted; + PLSA_AP_CALL_PACKAGE_PASSTHROUGH CallPackagePassthrough; + PLSA_AP_LOGON_USER_EX LogonUserEx; + PLSA_AP_LOGON_USER_EX2 LogonUserEx2; + SpInitializeFn * Initialize; + SpShutdownFn * Shutdown; + SpGetInfoFn * GetInfo; + SpAcceptCredentialsFn * AcceptCredentials; + SpAcquireCredentialsHandleFn * AcquireCredentialsHandle; + SpQueryCredentialsAttributesFn * QueryCredentialsAttributes; + SpFreeCredentialsHandleFn * FreeCredentialsHandle; + SpSaveCredentialsFn * SaveCredentials; + SpGetCredentialsFn * GetCredentials; + SpDeleteCredentialsFn * DeleteCredentials; + SpInitLsaModeContextFn * InitLsaModeContext; + SpAcceptLsaModeContextFn * AcceptLsaModeContext; + SpDeleteContextFn * DeleteContext; + SpApplyControlTokenFn * ApplyControlToken; + SpGetUserInfoFn * GetUserInfo; + SpGetExtendedInformationFn * GetExtendedInformation; + SpQueryContextAttributesFn * QueryContextAttributes; + SpAddCredentialsFn * AddCredentials; + SpSetExtendedInformationFn * SetExtendedInformation; + SpSetContextAttributesFn * SetContextAttributes; + SpSetCredentialsAttributesFn * SetCredentialsAttributes; + SpChangeAccountPasswordFn * ChangeAccountPassword; + SpQueryMetaDataFn* QueryMetaData; + SpExchangeMetaDataFn* ExchangeMetaData; + SpGetCredUIContextFn* GetCredUIContext; + SpUpdateCredentialsFn* UpdateCredentials; + SpValidateTargetInfoFn* ValidateTargetInfo; +} SECPKG_FUNCTION_TABLE, *PSECPKG_FUNCTION_TABLE; + +// +// The following prototypes are to functions that will be called while in the +// context of a user process that is using the functions through the security +// DLL. +// +typedef NTSTATUS +(NTAPI SpInstanceInitFn)( + IN ULONG Version, + IN PSECPKG_DLL_FUNCTIONS FunctionTable, + OUT PVOID * UserFunctions + ); + +typedef NTSTATUS +(NTAPI SpInitUserModeContextFn)( + IN LSA_SEC_HANDLE ContextHandle, + IN PSecBuffer PackedContext + ); + +typedef NTSTATUS +(NTAPI SpMakeSignatureFn)( + IN LSA_SEC_HANDLE ContextHandle, + IN ULONG QualityOfProtection, + IN PSecBufferDesc MessageBuffers, + IN ULONG MessageSequenceNumber + ); + +typedef NTSTATUS +(NTAPI SpVerifySignatureFn)( + IN LSA_SEC_HANDLE ContextHandle, + IN PSecBufferDesc MessageBuffers, + IN ULONG MessageSequenceNumber, + OUT PULONG QualityOfProtection + ); + +typedef NTSTATUS +(NTAPI SpSealMessageFn)( + IN LSA_SEC_HANDLE ContextHandle, + IN ULONG QualityOfProtection, + IN PSecBufferDesc MessageBuffers, + IN ULONG MessageSequenceNumber + ); + +typedef NTSTATUS +(NTAPI SpUnsealMessageFn)( + IN LSA_SEC_HANDLE ContextHandle, + IN PSecBufferDesc MessageBuffers, + IN ULONG MessageSequenceNumber, + OUT PULONG QualityOfProtection + ); + + +typedef NTSTATUS +(NTAPI SpGetContextTokenFn)( + IN LSA_SEC_HANDLE ContextHandle, + OUT PHANDLE ImpersonationToken + ); + + +typedef NTSTATUS +(NTAPI SpExportSecurityContextFn)( + LSA_SEC_HANDLE phContext, // (in) context to export + ULONG fFlags, // (in) option flags + PSecBuffer pPackedContext, // (out) marshalled context + PHANDLE pToken // (out, optional) token handle for impersonation + ); + +typedef NTSTATUS +(NTAPI SpImportSecurityContextFn)( + PSecBuffer pPackedContext, // (in) marshalled context + HANDLE Token, // (in, optional) handle to token for context + PLSA_SEC_HANDLE phContext // (out) new context handle + ); + + +typedef NTSTATUS +(NTAPI SpCompleteAuthTokenFn)( + IN LSA_SEC_HANDLE ContextHandle, + IN PSecBufferDesc InputBuffer + ); + + +typedef NTSTATUS +(NTAPI SpFormatCredentialsFn)( + IN PSecBuffer Credentials, + OUT PSecBuffer FormattedCredentials + ); + +typedef NTSTATUS +(NTAPI SpMarshallSupplementalCredsFn)( + IN ULONG CredentialSize, + IN PUCHAR Credentials, + OUT PULONG MarshalledCredSize, + OUT PVOID * MarshalledCreds); + +typedef struct _SECPKG_USER_FUNCTION_TABLE { + SpInstanceInitFn * InstanceInit; + SpInitUserModeContextFn * InitUserModeContext; + SpMakeSignatureFn * MakeSignature; + SpVerifySignatureFn * VerifySignature; + SpSealMessageFn * SealMessage; + SpUnsealMessageFn * UnsealMessage; + SpGetContextTokenFn * GetContextToken; + SpQueryContextAttributesFn * QueryContextAttributes; + SpCompleteAuthTokenFn * CompleteAuthToken; + SpDeleteContextFn * DeleteUserModeContext; + SpFormatCredentialsFn * FormatCredentials; + SpMarshallSupplementalCredsFn * MarshallSupplementalCreds; + SpExportSecurityContextFn * ExportContext; + SpImportSecurityContextFn * ImportContext; +} SECPKG_USER_FUNCTION_TABLE, *PSECPKG_USER_FUNCTION_TABLE; + + +typedef NTSTATUS +(SEC_ENTRY * SpLsaModeInitializeFn)( + IN ULONG LsaVersion, + OUT PULONG PackageVersion, + OUT PSECPKG_FUNCTION_TABLE * ppTables, + OUT PULONG pcTables); + +typedef NTSTATUS +(SEC_ENTRY * SpUserModeInitializeFn)( + IN ULONG LsaVersion, + OUT PULONG PackageVersion, + OUT PSECPKG_USER_FUNCTION_TABLE *ppTables, + OUT PULONG pcTables + ); + +#define SECPKG_LSAMODEINIT_NAME "SpLsaModeInitialize" +#define SECPKG_USERMODEINIT_NAME "SpUserModeInitialize" + +// +// Version of the security package interface. +// +// These defines are used for all of the following: +// +// * Passed by the LSA to SpLsaModeInitializeFn to indicate the version of the LSA. +// All packages currently expect the LSA to pass SECPKG_INTERFACE_VERSION. +// +// * Passed by secur32.dll to SpUserModeInitialzeFn to indicate the version of the secur32 DLL. +// All packages currently expect secur32 to pass SECPKG_INTERFACE_VERSION. +// +// * Returned from SpLsaModeInitializeFn to indicate the version of SECPKG_FUNCTION_TABLE. +// SECPKG_INTERFACE_VERSION indicates all fields through SetExtendedInformation are defined (potentially to NULL) +// SECPKG_INTERFACE_VERSION_2 indicates all fields through SetContextAttributes are defined (potentially to NULL) +// SECPKG_INTERFACE_VERSION_3 indicates all fields through SetCredentialsAttributes are defined (potentially to NULL) +// SECPKG_INTERFACE_VERSION_4 indicates all fields through ChangeAccountPassword are defined (potentially to NULL) +// SECPKG_INTERFACE_VERSION_5 indicates all fields through UpdateCredentials are defined (potentially to NULL) +// SECPKG_INTERFACE_VERSION_6 indicates all fields through ValidateTargetInfo are defined (potentially to NULL) +// +// * Returned from SpUserModeInitializeFn to indicate the version of the auth package. +// All packages currently return SECPKG_INTERFACE_VERSION +// + +#define SECPKG_INTERFACE_VERSION 0x00010000 +#define SECPKG_INTERFACE_VERSION_2 0x00020000 +#define SECPKG_INTERFACE_VERSION_3 0x00040000 +#define SECPKG_INTERFACE_VERSION_4 0x00080000 +#define SECPKG_INTERFACE_VERSION_5 0x00100000 +#define SECPKG_INTERFACE_VERSION_6 0x00200000 + +typedef enum _KSEC_CONTEXT_TYPE { + KSecPaged, + KSecNonPaged +} KSEC_CONTEXT_TYPE; + +typedef struct _KSEC_LIST_ENTRY { + LIST_ENTRY List; + LONG RefCount; + ULONG Signature; + PVOID OwningList; + PVOID Reserved; +} KSEC_LIST_ENTRY, * PKSEC_LIST_ENTRY; + +#define KsecInitializeListEntry( Entry, SigValue ) \ + ((PKSEC_LIST_ENTRY) Entry)->List.Flink = ((PKSEC_LIST_ENTRY) Entry)->List.Blink = NULL; \ + ((PKSEC_LIST_ENTRY) Entry)->RefCount = 1; \ + ((PKSEC_LIST_ENTRY) Entry)->Signature = SigValue; \ + ((PKSEC_LIST_ENTRY) Entry)->OwningList = NULL; \ + ((PKSEC_LIST_ENTRY) Entry)->Reserved = NULL; + + + +typedef PVOID +(SEC_ENTRY KSEC_CREATE_CONTEXT_LIST)( + IN KSEC_CONTEXT_TYPE Type + ); + +typedef VOID +(SEC_ENTRY KSEC_INSERT_LIST_ENTRY)( + IN PVOID List, + IN PKSEC_LIST_ENTRY Entry + ); + +typedef NTSTATUS +(SEC_ENTRY KSEC_REFERENCE_LIST_ENTRY)( + IN PKSEC_LIST_ENTRY Entry, + IN ULONG Signature, + IN BOOLEAN RemoveNoRef + ); + +typedef VOID +(SEC_ENTRY KSEC_DEREFERENCE_LIST_ENTRY)( + IN PKSEC_LIST_ENTRY Entry, + OUT BOOLEAN * Delete OPTIONAL + ); + +typedef NTSTATUS +(SEC_ENTRY KSEC_SERIALIZE_WINNT_AUTH_DATA)( + __in PVOID pvAuthData, + __out PULONG Size, + __deref_out PVOID * SerializedData ); + +typedef NTSTATUS +(SEC_ENTRY KSEC_SERIALIZE_SCHANNEL_AUTH_DATA)( + __in PVOID pvAuthData, + __out PULONG Size, + __deref_out PVOID * SerializedData ); + +#ifndef MIDL_PASS + +KSEC_CREATE_CONTEXT_LIST KSecCreateContextList; +KSEC_INSERT_LIST_ENTRY KSecInsertListEntry; +KSEC_REFERENCE_LIST_ENTRY KSecReferenceListEntry; +KSEC_DEREFERENCE_LIST_ENTRY KSecDereferenceListEntry; +KSEC_SERIALIZE_WINNT_AUTH_DATA KSecSerializeWinntAuthData; +KSEC_SERIALIZE_SCHANNEL_AUTH_DATA KSecSerializeSchannelAuthData; + +#endif // not valid for MIDL_PASS + +typedef KSEC_CREATE_CONTEXT_LIST * PKSEC_CREATE_CONTEXT_LIST; +typedef KSEC_INSERT_LIST_ENTRY * PKSEC_INSERT_LIST_ENTRY; +typedef KSEC_REFERENCE_LIST_ENTRY * PKSEC_REFERENCE_LIST_ENTRY; +typedef KSEC_DEREFERENCE_LIST_ENTRY * PKSEC_DEREFERENCE_LIST_ENTRY; +typedef KSEC_SERIALIZE_WINNT_AUTH_DATA * PKSEC_SERIALIZE_WINNT_AUTH_DATA; +typedef KSEC_SERIALIZE_SCHANNEL_AUTH_DATA * PKSEC_SERIALIZE_SCHANNEL_AUTH_DATA; + +typedef PVOID +(SEC_ENTRY KSEC_LOCATE_PKG_BY_ID)( + __in ULONG PackageId + ); + +typedef KSEC_LOCATE_PKG_BY_ID * PKSEC_LOCATE_PKG_BY_ID; + +#ifndef MIDL_PASS + +KSEC_LOCATE_PKG_BY_ID KSecLocatePackageById; + +#endif // not valid for MIDL_PASS + +typedef struct _SECPKG_KERNEL_FUNCTIONS { + PLSA_ALLOCATE_LSA_HEAP AllocateHeap; + PLSA_FREE_LSA_HEAP FreeHeap; + PKSEC_CREATE_CONTEXT_LIST CreateContextList; + PKSEC_INSERT_LIST_ENTRY InsertListEntry; + PKSEC_REFERENCE_LIST_ENTRY ReferenceListEntry; + PKSEC_DEREFERENCE_LIST_ENTRY DereferenceListEntry; + PKSEC_SERIALIZE_WINNT_AUTH_DATA SerializeWinntAuthData; + PKSEC_SERIALIZE_SCHANNEL_AUTH_DATA SerializeSchannelAuthData; + PKSEC_LOCATE_PKG_BY_ID LocatePackageById; +} SECPKG_KERNEL_FUNCTIONS, *PSECPKG_KERNEL_FUNCTIONS; + +typedef NTSTATUS +(NTAPI KspInitPackageFn)( + PSECPKG_KERNEL_FUNCTIONS FunctionTable + ); + +typedef NTSTATUS +(NTAPI KspDeleteContextFn)( + IN LSA_SEC_HANDLE ContextId, + OUT PLSA_SEC_HANDLE LsaContextId + ); + +typedef NTSTATUS +(NTAPI KspInitContextFn)( + IN LSA_SEC_HANDLE ContextId, + IN PSecBuffer ContextData, + OUT PLSA_SEC_HANDLE NewContextId + ); + +typedef NTSTATUS +(NTAPI KspMakeSignatureFn)( + IN LSA_SEC_HANDLE ContextId, + IN ULONG fQOP, + IN OUT PSecBufferDesc Message, + IN ULONG MessageSeqNo + ); + +typedef NTSTATUS +(NTAPI KspVerifySignatureFn)( + IN LSA_SEC_HANDLE ContextId, + IN OUT PSecBufferDesc Message, + IN ULONG MessageSeqNo, + OUT PULONG pfQOP + ); + + +typedef NTSTATUS +(NTAPI KspSealMessageFn)( + IN LSA_SEC_HANDLE ContextId, + IN ULONG fQOP, + IN OUT PSecBufferDesc Message, + IN ULONG MessageSeqNo + ); + +typedef NTSTATUS +(NTAPI KspUnsealMessageFn)( + IN LSA_SEC_HANDLE ContextId, + IN OUT PSecBufferDesc Message, + IN ULONG MessageSeqNo, + OUT PULONG pfQOP + ); + +typedef NTSTATUS +(NTAPI KspGetTokenFn)( + IN LSA_SEC_HANDLE ContextId, + OUT PHANDLE ImpersonationToken, + OUT OPTIONAL PACCESS_TOKEN * RawToken + ); + +typedef NTSTATUS +(NTAPI KspQueryAttributesFn)( + IN LSA_SEC_HANDLE ContextId, + IN ULONG Attribute, + IN OUT PVOID Buffer + ); + +typedef NTSTATUS +(NTAPI KspCompleteTokenFn)( + IN LSA_SEC_HANDLE ContextId, + IN PSecBufferDesc Token + ); + + +typedef NTSTATUS +(NTAPI KspMapHandleFn)( + IN LSA_SEC_HANDLE ContextId, + OUT PLSA_SEC_HANDLE LsaContextId + ); + +typedef NTSTATUS +(NTAPI KspSetPagingModeFn)( + IN BOOLEAN PagingMode + ); + +typedef NTSTATUS +(NTAPI KspSerializeAuthDataFn)( + IN PVOID pvAuthData, + OUT PULONG Size, + OUT PVOID * SerializedData + ); + +typedef struct _SECPKG_KERNEL_FUNCTION_TABLE { + KspInitPackageFn * Initialize; + KspDeleteContextFn * DeleteContext; + KspInitContextFn * InitContext; + KspMapHandleFn * MapHandle; + KspMakeSignatureFn * Sign; + KspVerifySignatureFn * Verify; + KspSealMessageFn * Seal; + KspUnsealMessageFn * Unseal; + KspGetTokenFn * GetToken; + KspQueryAttributesFn * QueryAttributes; + KspCompleteTokenFn * CompleteToken; + SpExportSecurityContextFn * ExportContext; + SpImportSecurityContextFn * ImportContext; + KspSetPagingModeFn * SetPackagePagingMode; + KspSerializeAuthDataFn * SerializeAuthData; +} SECPKG_KERNEL_FUNCTION_TABLE, *PSECPKG_KERNEL_FUNCTION_TABLE; + +SECURITY_STATUS +SEC_ENTRY +KSecRegisterSecurityProvider( + __in PSECURITY_STRING ProviderName, + __in PSECPKG_KERNEL_FUNCTION_TABLE Table + ); + +extern SECPKG_KERNEL_FUNCTIONS KspKernelFunctions; + + +#ifdef __cplusplus +} +#endif + +#endif /* _NTSECPKG_ */ + + diff --git a/inc/globals.h b/inc/globals.h index 7503ff0..35662e3 100644 --- a/inc/globals.h +++ b/inc/globals.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include "../modules/kull_m_output.h" #ifdef _M_X64 diff --git a/inc/winhttp.h b/inc/winhttp.h new file mode 100644 index 0000000..875028c --- /dev/null +++ b/inc/winhttp.h @@ -0,0 +1,1255 @@ + +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + +Module Name: + + winhttp.h + +Abstract: + + Contains manifests, macros, types and prototypes for Windows HTTP Services + +--*/ + +#if !defined(_WINHTTPX_) +#define _WINHTTPX_ + + + +/* + * Set up Structure Packing to be 4 bytes for all winhttp structures + */ + +#if defined(_WIN64) +#include +#else +#include +#endif + + + +#if defined(__cplusplus) +extern "C" { +#endif + + +#if !defined(_WINHTTP_INTERNAL_) +#define WINHTTPAPI DECLSPEC_IMPORT +#else +#define WINHTTPAPI + +#endif + +#define BOOLAPI WINHTTPAPI BOOL WINAPI +// +// types +// + +typedef LPVOID HINTERNET; +typedef HINTERNET * LPHINTERNET; + +typedef WORD INTERNET_PORT; +typedef INTERNET_PORT * LPINTERNET_PORT; + +// +// manifests +// + +#define INTERNET_DEFAULT_PORT 0 // use the protocol-specific default +#define INTERNET_DEFAULT_HTTP_PORT 80 // " " HTTP " +#define INTERNET_DEFAULT_HTTPS_PORT 443 // " " HTTPS " + +// flags for WinHttpOpen(): +#define WINHTTP_FLAG_ASYNC 0x10000000 // this session is asynchronous (where supported) + +// flags for WinHttpOpenRequest(): +#define WINHTTP_FLAG_SECURE 0x00800000 // use SSL if applicable (HTTPS) +#define WINHTTP_FLAG_ESCAPE_PERCENT 0x00000004 // if escaping enabled, escape percent as well +#define WINHTTP_FLAG_NULL_CODEPAGE 0x00000008 // assume all symbols are ASCII, use fast convertion +#define WINHTTP_FLAG_BYPASS_PROXY_CACHE 0x00000100 // add "pragma: no-cache" request header +#define WINHTTP_FLAG_REFRESH WINHTTP_FLAG_BYPASS_PROXY_CACHE +#define WINHTTP_FLAG_ESCAPE_DISABLE 0x00000040 // disable escaping +#define WINHTTP_FLAG_ESCAPE_DISABLE_QUERY 0x00000080 // if escaping enabled escape path part, but do not escape query + + +#define SECURITY_FLAG_IGNORE_UNKNOWN_CA 0x00000100 +#define SECURITY_FLAG_IGNORE_CERT_DATE_INVALID 0x00002000 // expired X509 Cert. +#define SECURITY_FLAG_IGNORE_CERT_CN_INVALID 0x00001000 // bad common name in X509 Cert. +#define SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE 0x00000200 + + +// +// WINHTTP_ASYNC_RESULT - this structure is returned to the application via +// the callback with WINHTTP_CALLBACK_STATUS_REQUEST_COMPLETE. It is not sufficient to +// just return the result of the async operation. If the API failed then the +// app cannot call GetLastError() because the thread context will be incorrect. +// Both the value returned by the async API and any resultant error code are +// made available. The app need not check dwError if dwResult indicates that +// the API succeeded (in this case dwError will be ERROR_SUCCESS) +// + +typedef struct +{ + DWORD_PTR dwResult; // indicates which async API has encountered an error + DWORD dwError; // the error code if the API failed +} +WINHTTP_ASYNC_RESULT, * LPWINHTTP_ASYNC_RESULT; + + +// +// HTTP_VERSION_INFO - query or set global HTTP version (1.0 or 1.1) +// + +typedef struct +{ + DWORD dwMajorVersion; + DWORD dwMinorVersion; +} +HTTP_VERSION_INFO, * LPHTTP_VERSION_INFO; + + +// +// INTERNET_SCHEME - URL scheme type +// + +typedef int INTERNET_SCHEME, * LPINTERNET_SCHEME; + +#define INTERNET_SCHEME_HTTP (1) +#define INTERNET_SCHEME_HTTPS (2) + + +// +// URL_COMPONENTS - the constituent parts of an URL. Used in WinHttpCrackUrl() +// and WinHttpCreateUrl() +// +// For WinHttpCrackUrl(), if a pointer field and its corresponding length field +// are both 0 then that component is not returned. If the pointer field is NULL +// but the length field is not zero, then both the pointer and length fields are +// returned if both pointer and corresponding length fields are non-zero then +// the pointer field points to a buffer where the component is copied. The +// component may be un-escaped, depending on dwFlags +// +// For WinHttpCreateUrl(), the pointer fields should be NULL if the component +// is not required. If the corresponding length field is zero then the pointer +// field is the address of a zero-terminated string. If the length field is not +// zero then it is the string length of the corresponding pointer field +// + +#pragma warning( disable : 4121 ) // disable alignment warning + +typedef struct +{ + DWORD dwStructSize; // size of this structure. Used in version check + LPWSTR lpszScheme; // pointer to scheme name + DWORD dwSchemeLength; // length of scheme name + INTERNET_SCHEME nScheme; // enumerated scheme type (if known) + LPWSTR lpszHostName; // pointer to host name + DWORD dwHostNameLength; // length of host name + INTERNET_PORT nPort; // converted port number + LPWSTR lpszUserName; // pointer to user name + DWORD dwUserNameLength; // length of user name + LPWSTR lpszPassword; // pointer to password + DWORD dwPasswordLength; // length of password + LPWSTR lpszUrlPath; // pointer to URL-path + DWORD dwUrlPathLength; // length of URL-path + LPWSTR lpszExtraInfo; // pointer to extra information (e.g. ?foo or #foo) + DWORD dwExtraInfoLength; // length of extra information +} +URL_COMPONENTS, * LPURL_COMPONENTS; + +typedef URL_COMPONENTS URL_COMPONENTSW; +typedef LPURL_COMPONENTS LPURL_COMPONENTSW; + +#pragma warning( default : 4121 ) // restore alignment warning + +// +// WINHTTP_PROXY_INFO - structure supplied with WINHTTP_OPTION_PROXY to get/ +// set proxy information on a WinHttpOpen() handle +// + +typedef struct +{ + DWORD dwAccessType; // see WINHTTP_ACCESS_* types below + LPWSTR lpszProxy; // proxy server list + LPWSTR lpszProxyBypass; // proxy bypass list +} +WINHTTP_PROXY_INFO, * LPWINHTTP_PROXY_INFO; + +typedef WINHTTP_PROXY_INFO WINHTTP_PROXY_INFOW; +typedef LPWINHTTP_PROXY_INFO LPWINHTTP_PROXY_INFOW; + + +typedef struct +{ + DWORD dwFlags; + DWORD dwAutoDetectFlags; + LPCWSTR lpszAutoConfigUrl; + LPVOID lpvReserved; + DWORD dwReserved; + BOOL fAutoLogonIfChallenged; +} +WINHTTP_AUTOPROXY_OPTIONS; + + + +#define WINHTTP_AUTOPROXY_AUTO_DETECT 0x00000001 +#define WINHTTP_AUTOPROXY_CONFIG_URL 0x00000002 +#define WINHTTP_AUTOPROXY_HOST_KEEPCASE 0x00000004 +#define WINHTTP_AUTOPROXY_HOST_LOWERCASE 0x00000008 +#define WINHTTP_AUTOPROXY_RUN_INPROCESS 0x00010000 +#define WINHTTP_AUTOPROXY_RUN_OUTPROCESS_ONLY 0x00020000 + + +// +// Flags for dwAutoDetectFlags +// +#define WINHTTP_AUTO_DETECT_TYPE_DHCP 0x00000001 +#define WINHTTP_AUTO_DETECT_TYPE_DNS_A 0x00000002 + +// +// WINHTTP_CERTIFICATE_INFO lpBuffer - contains the certificate returned from +// the server +// + +typedef struct +{ + // + // ftExpiry - date the certificate expires. + // + + FILETIME ftExpiry; + + // + // ftStart - date the certificate becomes valid. + // + + FILETIME ftStart; + + // + // lpszSubjectInfo - the name of organization, site, and server + // the cert. was issued for. + // + + LPWSTR lpszSubjectInfo; + + // + // lpszIssuerInfo - the name of orgainzation, site, and server + // the cert was issues by. + // + + LPWSTR lpszIssuerInfo; + + // + // lpszProtocolName - the name of the protocol used to provide the secure + // connection. + // + + LPWSTR lpszProtocolName; + + // + // lpszSignatureAlgName - the name of the algorithm used for signing + // the certificate. + // + + LPWSTR lpszSignatureAlgName; + + // + // lpszEncryptionAlgName - the name of the algorithm used for + // doing encryption over the secure channel (SSL) connection. + // + + LPWSTR lpszEncryptionAlgName; + + // + // dwKeySize - size of the key. + // + + DWORD dwKeySize; + +} +WINHTTP_CERTIFICATE_INFO; + +#ifdef _WS2DEF_ + +typedef struct +{ + DWORD cbSize; + SOCKADDR_STORAGE LocalAddress; // local ip, local port + SOCKADDR_STORAGE RemoteAddress; // remote ip, remote port + +}WINHTTP_CONNECTION_INFO; + +#endif + +// +// prototypes +// + +// +// constants for WinHttpTimeFromSystemTime +// + +#define WINHTTP_TIME_FORMAT_BUFSIZE 62 + +BOOLAPI +WinHttpTimeFromSystemTime +( + __in CONST SYSTEMTIME *pst, // input GMT time + __out_bcount(WINHTTP_TIME_FORMAT_BUFSIZE) LPWSTR pwszTime // output string buffer +); + +BOOLAPI +WinHttpTimeToSystemTime +( + __in_z LPCWSTR pwszTime, // NULL terminated string + __out SYSTEMTIME *pst // output in GMT time +); + + +// +// flags for CrackUrl() and CombineUrl() +// + +#define ICU_NO_ENCODE 0x20000000 // Don't convert unsafe characters to escape sequence +#define ICU_DECODE 0x10000000 // Convert %XX escape sequences to characters +#define ICU_NO_META 0x08000000 // Don't convert .. etc. meta path sequences +#define ICU_ENCODE_SPACES_ONLY 0x04000000 // Encode spaces only +#define ICU_BROWSER_MODE 0x02000000 // Special encode/decode rules for browser +#define ICU_ENCODE_PERCENT 0x00001000 // Encode any percent (ASCII25) + + // signs encountered, default is to not encode percent. + + +BOOLAPI +WinHttpCrackUrl +( + __in_ecount(dwUrlLength) LPCWSTR pwszUrl, + __in DWORD dwUrlLength, + __in DWORD dwFlags, + __inout LPURL_COMPONENTS lpUrlComponents +); + +BOOLAPI +WinHttpCreateUrl +( + __in LPURL_COMPONENTS lpUrlComponents, + __in DWORD dwFlags, + __out_ecount_part_opt(*pdwUrlLength, *pdwUrlLength) LPWSTR pwszUrl, + __inout LPDWORD pdwUrlLength +); + +// +// flags for WinHttpCrackUrl() and WinHttpCreateUrl() +// +#define ICU_ESCAPE 0x80000000 // (un)escape URL characters +#define ICU_ESCAPE_AUTHORITY 0x00002000 //causes InternetCreateUrlA to escape chars in authority components (user, pwd, host) +#define ICU_REJECT_USERPWD 0x00004000 // rejects usrls whick have username/pwd sections + +BOOLAPI +WinHttpCheckPlatform(void); + + +WINHTTPAPI BOOL WINAPI WinHttpGetDefaultProxyConfiguration( IN OUT WINHTTP_PROXY_INFO * pProxyInfo); +WINHTTPAPI BOOL WINAPI WinHttpSetDefaultProxyConfiguration( IN WINHTTP_PROXY_INFO * pProxyInfo); + + +WINHTTPAPI +HINTERNET +WINAPI +WinHttpOpen +( + __in_z_opt LPCWSTR pszAgentW, + __in DWORD dwAccessType, + __in_z_opt LPCWSTR pszProxyW, + __in_z_opt LPCWSTR pszProxyBypassW, + __in DWORD dwFlags +); + +// WinHttpOpen dwAccessType values (also for WINHTTP_PROXY_INFO::dwAccessType) +#define WINHTTP_ACCESS_TYPE_DEFAULT_PROXY 0 +#define WINHTTP_ACCESS_TYPE_NO_PROXY 1 +#define WINHTTP_ACCESS_TYPE_NAMED_PROXY 3 + +// WinHttpOpen prettifiers for optional parameters +#define WINHTTP_NO_PROXY_NAME NULL +#define WINHTTP_NO_PROXY_BYPASS NULL + +BOOLAPI +WinHttpCloseHandle +( + IN HINTERNET hInternet +); + + +WINHTTPAPI +HINTERNET +WINAPI +WinHttpConnect +( + IN HINTERNET hSession, + IN LPCWSTR pswzServerName, + IN INTERNET_PORT nServerPort, + IN DWORD dwReserved +); + + +BOOLAPI +WinHttpReadData +( + IN HINTERNET hRequest, + __out_bcount_part(dwNumberOfBytesToRead, *lpdwNumberOfBytesRead) __out_data_source(NETWORK) LPVOID lpBuffer, + IN DWORD dwNumberOfBytesToRead, + OUT LPDWORD lpdwNumberOfBytesRead +); + +BOOLAPI +WinHttpWriteData +( + IN HINTERNET hRequest, + __in_bcount_opt(dwNumberOfBytesToWrite) LPCVOID lpBuffer, + IN DWORD dwNumberOfBytesToWrite, + OUT LPDWORD lpdwNumberOfBytesWritten +); + + +BOOLAPI +WinHttpQueryDataAvailable +( + IN HINTERNET hRequest, + __out_data_source(NETWORK) LPDWORD lpdwNumberOfBytesAvailable +); + + +__success(return != FALSE) +BOOLAPI +WinHttpQueryOption +( + IN HINTERNET hInternet, + IN DWORD dwOption, + __out_bcount_part_opt(*lpdwBufferLength, *lpdwBufferLength) __out_data_source(NETWORK) LPVOID lpBuffer, + IN OUT LPDWORD lpdwBufferLength +); + +#define WINHTTP_NO_CLIENT_CERT_CONTEXT NULL + +BOOLAPI +WinHttpSetOption +( + IN HINTERNET hInternet, + IN DWORD dwOption, + __in_awcount((dwOption != WINHTTP_OPTION_USERNAME && + dwOption != WINHTTP_OPTION_PASSWORD && + dwOption != WINHTTP_OPTION_PROXY_USERNAME && + dwOption != WINHTTP_OPTION_PROXY_PASSWORD && + dwOption != WINHTTP_OPTION_USER_AGENT), + dwBufferLength) + __typefix(LPCWSTR) LPVOID lpBuffer, + IN DWORD dwBufferLength +); + +BOOLAPI +WinHttpSetTimeouts +( + IN HINTERNET hInternet, // Session/Request handle. + IN int nResolveTimeout, + IN int nConnectTimeout, + IN int nSendTimeout, + IN int nReceiveTimeout +); + +WINHTTPAPI +DWORD +WINAPI +WinHttpIsHostInProxyBypassList +( + __in const WINHTTP_PROXY_INFO *pProxyInfo, + __in_z PCWSTR pwszHost, + __in INTERNET_SCHEME tScheme, + __in INTERNET_PORT nPort, + __out BOOL *pfIsInBypassList +); + +// +// options manifests for WinHttp{Query|Set}Option +// + +#define WINHTTP_FIRST_OPTION WINHTTP_OPTION_CALLBACK + +#define WINHTTP_OPTION_CALLBACK 1 +#define WINHTTP_OPTION_RESOLVE_TIMEOUT 2 +#define WINHTTP_OPTION_CONNECT_TIMEOUT 3 +#define WINHTTP_OPTION_CONNECT_RETRIES 4 +#define WINHTTP_OPTION_SEND_TIMEOUT 5 +#define WINHTTP_OPTION_RECEIVE_TIMEOUT 6 +#define WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT 7 +#define WINHTTP_OPTION_HANDLE_TYPE 9 +#define WINHTTP_OPTION_READ_BUFFER_SIZE 12 +#define WINHTTP_OPTION_WRITE_BUFFER_SIZE 13 +#define WINHTTP_OPTION_PARENT_HANDLE 21 +#define WINHTTP_OPTION_EXTENDED_ERROR 24 +#define WINHTTP_OPTION_SECURITY_FLAGS 31 +#define WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT 32 +#define WINHTTP_OPTION_URL 34 +#define WINHTTP_OPTION_SECURITY_KEY_BITNESS 36 +#define WINHTTP_OPTION_PROXY 38 + + +#define WINHTTP_OPTION_USER_AGENT 41 +#define WINHTTP_OPTION_CONTEXT_VALUE 45 +#define WINHTTP_OPTION_CLIENT_CERT_CONTEXT 47 +#define WINHTTP_OPTION_REQUEST_PRIORITY 58 +#define WINHTTP_OPTION_HTTP_VERSION 59 +#define WINHTTP_OPTION_DISABLE_FEATURE 63 + +#define WINHTTP_OPTION_CODEPAGE 68 +#define WINHTTP_OPTION_MAX_CONNS_PER_SERVER 73 +#define WINHTTP_OPTION_MAX_CONNS_PER_1_0_SERVER 74 +#define WINHTTP_OPTION_AUTOLOGON_POLICY 77 +#define WINHTTP_OPTION_SERVER_CERT_CONTEXT 78 +#define WINHTTP_OPTION_ENABLE_FEATURE 79 +#define WINHTTP_OPTION_WORKER_THREAD_COUNT 80 +#define WINHTTP_OPTION_PASSPORT_COBRANDING_TEXT 81 +#define WINHTTP_OPTION_PASSPORT_COBRANDING_URL 82 +#define WINHTTP_OPTION_CONFIGURE_PASSPORT_AUTH 83 +#define WINHTTP_OPTION_SECURE_PROTOCOLS 84 +#define WINHTTP_OPTION_ENABLETRACING 85 +#define WINHTTP_OPTION_PASSPORT_SIGN_OUT 86 +#define WINHTTP_OPTION_PASSPORT_RETURN_URL 87 +#define WINHTTP_OPTION_REDIRECT_POLICY 88 +#define WINHTTP_OPTION_MAX_HTTP_AUTOMATIC_REDIRECTS 89 +#define WINHTTP_OPTION_MAX_HTTP_STATUS_CONTINUE 90 +#define WINHTTP_OPTION_MAX_RESPONSE_HEADER_SIZE 91 +#define WINHTTP_OPTION_MAX_RESPONSE_DRAIN_SIZE 92 +#define WINHTTP_OPTION_CONNECTION_INFO 93 +#define WINHTTP_OPTION_CLIENT_CERT_ISSUER_LIST 94 +#define WINHTTP_OPTION_SPN 96 + +#define WINHTTP_OPTION_GLOBAL_PROXY_CREDS 97 +#define WINHTTP_OPTION_GLOBAL_SERVER_CREDS 98 + +#define WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT 99 +#define WINHTTP_OPTION_REJECT_USERPWD_IN_URL 100 +#define WINHTTP_OPTION_USE_GLOBAL_SERVER_CREDENTIALS 101 + + +#define WINHTTP_OPTION_RECEIVE_PROXY_CONNECT_RESPONSE 103 +#define WINHTTP_OPTION_IS_PROXY_CONNECT_RESPONSE 104 + + +#define WINHTTP_OPTION_SERVER_SPN_USED 106 +#define WINHTTP_OPTION_PROXY_SPN_USED 107 + +#define WINHTTP_OPTION_SERVER_CBT 108 + + +#define WINHTTP_LAST_OPTION WINHTTP_OPTION_SERVER_CBT + +#define WINHTTP_OPTION_USERNAME 0x1000 +#define WINHTTP_OPTION_PASSWORD 0x1001 +#define WINHTTP_OPTION_PROXY_USERNAME 0x1002 +#define WINHTTP_OPTION_PROXY_PASSWORD 0x1003 + + +// manifest value for WINHTTP_OPTION_MAX_CONNS_PER_SERVER and WINHTTP_OPTION_MAX_CONNS_PER_1_0_SERVER +#define WINHTTP_CONNS_PER_SERVER_UNLIMITED 0xFFFFFFFF + + +// values for WINHTTP_OPTION_AUTOLOGON_POLICY +#define WINHTTP_AUTOLOGON_SECURITY_LEVEL_MEDIUM 0 +#define WINHTTP_AUTOLOGON_SECURITY_LEVEL_LOW 1 +#define WINHTTP_AUTOLOGON_SECURITY_LEVEL_HIGH 2 + +#define WINHTTP_AUTOLOGON_SECURITY_LEVEL_DEFAULT WINHTTP_AUTOLOGON_SECURITY_LEVEL_MEDIUM + +// values for WINHTTP_OPTION_REDIRECT_POLICY +#define WINHTTP_OPTION_REDIRECT_POLICY_NEVER 0 +#define WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP 1 +#define WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS 2 + +#define WINHTTP_OPTION_REDIRECT_POLICY_LAST WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS +#define WINHTTP_OPTION_REDIRECT_POLICY_DEFAULT WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP + +#define WINHTTP_DISABLE_PASSPORT_AUTH 0x00000000 +#define WINHTTP_ENABLE_PASSPORT_AUTH 0x10000000 +#define WINHTTP_DISABLE_PASSPORT_KEYRING 0x20000000 +#define WINHTTP_ENABLE_PASSPORT_KEYRING 0x40000000 + + +// values for WINHTTP_OPTION_DISABLE_FEATURE +#define WINHTTP_DISABLE_COOKIES 0x00000001 +#define WINHTTP_DISABLE_REDIRECTS 0x00000002 +#define WINHTTP_DISABLE_AUTHENTICATION 0x00000004 +#define WINHTTP_DISABLE_KEEP_ALIVE 0x00000008 + +// values for WINHTTP_OPTION_ENABLE_FEATURE +#define WINHTTP_ENABLE_SSL_REVOCATION 0x00000001 +#define WINHTTP_ENABLE_SSL_REVERT_IMPERSONATION 0x00000002 + +// values for WINHTTP_OPTION_SPN +#define WINHTTP_DISABLE_SPN_SERVER_PORT 0x00000000 +#define WINHTTP_ENABLE_SPN_SERVER_PORT 0x00000001 +#define WINHTTP_OPTION_SPN_MASK WINHTTP_ENABLE_SPN_SERVER_PORT + +typedef struct tagWINHTTP_CREDS +{ + LPSTR lpszUserName; + LPSTR lpszPassword; + LPSTR lpszRealm; + DWORD dwAuthScheme; + LPSTR lpszHostName; + DWORD dwPort; +} WINHTTP_CREDS, *PWINHTTP_CREDS; + +// structure for WINHTTP_OPTION_GLOBAL_SERVER_CREDS and +// WINHTTP_OPTION_GLOBAL_PROXY_CREDS +typedef struct tagWINHTTP_CREDS_EX +{ + LPSTR lpszUserName; + LPSTR lpszPassword; + LPSTR lpszRealm; + DWORD dwAuthScheme; + LPSTR lpszHostName; + DWORD dwPort; + LPSTR lpszUrl; +} WINHTTP_CREDS_EX, *PWINHTTP_CREDS_EX; + +// +// winhttp handle types +// +#define WINHTTP_HANDLE_TYPE_SESSION 1 +#define WINHTTP_HANDLE_TYPE_CONNECT 2 +#define WINHTTP_HANDLE_TYPE_REQUEST 3 + +// +// values for auth schemes +// +#define WINHTTP_AUTH_SCHEME_BASIC 0x00000001 +#define WINHTTP_AUTH_SCHEME_NTLM 0x00000002 +#define WINHTTP_AUTH_SCHEME_PASSPORT 0x00000004 +#define WINHTTP_AUTH_SCHEME_DIGEST 0x00000008 +#define WINHTTP_AUTH_SCHEME_NEGOTIATE 0x00000010 + +// WinHttp supported Authentication Targets + +#define WINHTTP_AUTH_TARGET_SERVER 0x00000000 +#define WINHTTP_AUTH_TARGET_PROXY 0x00000001 + +// +// values for WINHTTP_OPTION_SECURITY_FLAGS +// + +// query only +#define SECURITY_FLAG_SECURE 0x00000001 // can query only +#define SECURITY_FLAG_STRENGTH_WEAK 0x10000000 +#define SECURITY_FLAG_STRENGTH_MEDIUM 0x40000000 +#define SECURITY_FLAG_STRENGTH_STRONG 0x20000000 + + + +// Secure connection error status flags +#define WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED 0x00000001 +#define WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT 0x00000002 +#define WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED 0x00000004 +#define WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA 0x00000008 +#define WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID 0x00000010 +#define WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID 0x00000020 +#define WINHTTP_CALLBACK_STATUS_FLAG_CERT_WRONG_USAGE 0x00000040 +#define WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR 0x80000000 + + +#define WINHTTP_FLAG_SECURE_PROTOCOL_SSL2 0x00000008 +#define WINHTTP_FLAG_SECURE_PROTOCOL_SSL3 0x00000020 +#define WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 0x00000080 +#define WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 0x00000200 +#define WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2 0x00000800 +#define WINHTTP_FLAG_SECURE_PROTOCOL_ALL (WINHTTP_FLAG_SECURE_PROTOCOL_SSL2 | \ + WINHTTP_FLAG_SECURE_PROTOCOL_SSL3 | \ + WINHTTP_FLAG_SECURE_PROTOCOL_TLS1) + + +// +// callback function for WinHttpSetStatusCallback +// + +typedef +VOID +(CALLBACK * WINHTTP_STATUS_CALLBACK)( + IN HINTERNET hInternet, + IN DWORD_PTR dwContext, + IN DWORD dwInternetStatus, + IN LPVOID lpvStatusInformation OPTIONAL, + IN DWORD dwStatusInformationLength + ); + +typedef WINHTTP_STATUS_CALLBACK * LPWINHTTP_STATUS_CALLBACK; + + +WINHTTPAPI +WINHTTP_STATUS_CALLBACK +WINAPI +WinHttpSetStatusCallback +( + IN HINTERNET hInternet, + IN WINHTTP_STATUS_CALLBACK lpfnInternetCallback, + IN DWORD dwNotificationFlags, + IN DWORD_PTR dwReserved +); + + +// +// status manifests for WinHttp status callback +// + +#define WINHTTP_CALLBACK_STATUS_RESOLVING_NAME 0x00000001 +#define WINHTTP_CALLBACK_STATUS_NAME_RESOLVED 0x00000002 +#define WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER 0x00000004 +#define WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER 0x00000008 +#define WINHTTP_CALLBACK_STATUS_SENDING_REQUEST 0x00000010 +#define WINHTTP_CALLBACK_STATUS_REQUEST_SENT 0x00000020 +#define WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE 0x00000040 +#define WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED 0x00000080 +#define WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION 0x00000100 +#define WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED 0x00000200 +#define WINHTTP_CALLBACK_STATUS_HANDLE_CREATED 0x00000400 +#define WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING 0x00000800 +#define WINHTTP_CALLBACK_STATUS_DETECTING_PROXY 0x00001000 +#define WINHTTP_CALLBACK_STATUS_REDIRECT 0x00004000 +#define WINHTTP_CALLBACK_STATUS_INTERMEDIATE_RESPONSE 0x00008000 +#define WINHTTP_CALLBACK_STATUS_SECURE_FAILURE 0x00010000 +#define WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE 0x00020000 +#define WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE 0x00040000 +#define WINHTTP_CALLBACK_STATUS_READ_COMPLETE 0x00080000 +#define WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE 0x00100000 +#define WINHTTP_CALLBACK_STATUS_REQUEST_ERROR 0x00200000 +#define WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE 0x00400000 + + +// API Enums for WINHTTP_CALLBACK_STATUS_REQUEST_ERROR: +#define API_RECEIVE_RESPONSE (1) +#define API_QUERY_DATA_AVAILABLE (2) +#define API_READ_DATA (3) +#define API_WRITE_DATA (4) +#define API_SEND_REQUEST (5) + + +#define WINHTTP_CALLBACK_FLAG_RESOLVE_NAME (WINHTTP_CALLBACK_STATUS_RESOLVING_NAME | WINHTTP_CALLBACK_STATUS_NAME_RESOLVED) +#define WINHTTP_CALLBACK_FLAG_CONNECT_TO_SERVER (WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER | WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER) +#define WINHTTP_CALLBACK_FLAG_SEND_REQUEST (WINHTTP_CALLBACK_STATUS_SENDING_REQUEST | WINHTTP_CALLBACK_STATUS_REQUEST_SENT) +#define WINHTTP_CALLBACK_FLAG_RECEIVE_RESPONSE (WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE | WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED) +#define WINHTTP_CALLBACK_FLAG_CLOSE_CONNECTION (WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION | WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED) +#define WINHTTP_CALLBACK_FLAG_HANDLES (WINHTTP_CALLBACK_STATUS_HANDLE_CREATED | WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING) +#define WINHTTP_CALLBACK_FLAG_DETECTING_PROXY WINHTTP_CALLBACK_STATUS_DETECTING_PROXY +#define WINHTTP_CALLBACK_FLAG_REDIRECT WINHTTP_CALLBACK_STATUS_REDIRECT +#define WINHTTP_CALLBACK_FLAG_INTERMEDIATE_RESPONSE WINHTTP_CALLBACK_STATUS_INTERMEDIATE_RESPONSE +#define WINHTTP_CALLBACK_FLAG_SECURE_FAILURE WINHTTP_CALLBACK_STATUS_SECURE_FAILURE +#define WINHTTP_CALLBACK_FLAG_SENDREQUEST_COMPLETE WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE +#define WINHTTP_CALLBACK_FLAG_HEADERS_AVAILABLE WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE +#define WINHTTP_CALLBACK_FLAG_DATA_AVAILABLE WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE +#define WINHTTP_CALLBACK_FLAG_READ_COMPLETE WINHTTP_CALLBACK_STATUS_READ_COMPLETE +#define WINHTTP_CALLBACK_FLAG_WRITE_COMPLETE WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE +#define WINHTTP_CALLBACK_FLAG_REQUEST_ERROR WINHTTP_CALLBACK_STATUS_REQUEST_ERROR + + +#define WINHTTP_CALLBACK_FLAG_ALL_COMPLETIONS (WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE \ + | WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE \ + | WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE \ + | WINHTTP_CALLBACK_STATUS_READ_COMPLETE \ + | WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE \ + | WINHTTP_CALLBACK_STATUS_REQUEST_ERROR) +#define WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS 0xffffffff + +// +// if the following value is returned by WinHttpSetStatusCallback, then +// probably an invalid (non-code) address was supplied for the callback +// + +#define WINHTTP_INVALID_STATUS_CALLBACK ((WINHTTP_STATUS_CALLBACK)(-1L)) + + +// +// WinHttpQueryHeaders info levels. Generally, there is one info level +// for each potential RFC822/HTTP/MIME header that an HTTP server +// may send as part of a request response. +// +// The WINHTTP_QUERY_RAW_HEADERS info level is provided for clients +// that choose to perform their own header parsing. +// + + +#define WINHTTP_QUERY_MIME_VERSION 0 +#define WINHTTP_QUERY_CONTENT_TYPE 1 +#define WINHTTP_QUERY_CONTENT_TRANSFER_ENCODING 2 +#define WINHTTP_QUERY_CONTENT_ID 3 +#define WINHTTP_QUERY_CONTENT_DESCRIPTION 4 +#define WINHTTP_QUERY_CONTENT_LENGTH 5 +#define WINHTTP_QUERY_CONTENT_LANGUAGE 6 +#define WINHTTP_QUERY_ALLOW 7 +#define WINHTTP_QUERY_PUBLIC 8 +#define WINHTTP_QUERY_DATE 9 +#define WINHTTP_QUERY_EXPIRES 10 +#define WINHTTP_QUERY_LAST_MODIFIED 11 +#define WINHTTP_QUERY_MESSAGE_ID 12 +#define WINHTTP_QUERY_URI 13 +#define WINHTTP_QUERY_DERIVED_FROM 14 +#define WINHTTP_QUERY_COST 15 +#define WINHTTP_QUERY_LINK 16 +#define WINHTTP_QUERY_PRAGMA 17 +#define WINHTTP_QUERY_VERSION 18 // special: part of status line +#define WINHTTP_QUERY_STATUS_CODE 19 // special: part of status line +#define WINHTTP_QUERY_STATUS_TEXT 20 // special: part of status line +#define WINHTTP_QUERY_RAW_HEADERS 21 // special: all headers as ASCIIZ +#define WINHTTP_QUERY_RAW_HEADERS_CRLF 22 // special: all headers +#define WINHTTP_QUERY_CONNECTION 23 +#define WINHTTP_QUERY_ACCEPT 24 +#define WINHTTP_QUERY_ACCEPT_CHARSET 25 +#define WINHTTP_QUERY_ACCEPT_ENCODING 26 +#define WINHTTP_QUERY_ACCEPT_LANGUAGE 27 +#define WINHTTP_QUERY_AUTHORIZATION 28 +#define WINHTTP_QUERY_CONTENT_ENCODING 29 +#define WINHTTP_QUERY_FORWARDED 30 +#define WINHTTP_QUERY_FROM 31 +#define WINHTTP_QUERY_IF_MODIFIED_SINCE 32 +#define WINHTTP_QUERY_LOCATION 33 +#define WINHTTP_QUERY_ORIG_URI 34 +#define WINHTTP_QUERY_REFERER 35 +#define WINHTTP_QUERY_RETRY_AFTER 36 +#define WINHTTP_QUERY_SERVER 37 +#define WINHTTP_QUERY_TITLE 38 +#define WINHTTP_QUERY_USER_AGENT 39 +#define WINHTTP_QUERY_WWW_AUTHENTICATE 40 +#define WINHTTP_QUERY_PROXY_AUTHENTICATE 41 +#define WINHTTP_QUERY_ACCEPT_RANGES 42 +#define WINHTTP_QUERY_SET_COOKIE 43 +#define WINHTTP_QUERY_COOKIE 44 +#define WINHTTP_QUERY_REQUEST_METHOD 45 // special: GET/POST etc. +#define WINHTTP_QUERY_REFRESH 46 +#define WINHTTP_QUERY_CONTENT_DISPOSITION 47 + +// +// HTTP 1.1 defined headers +// + +#define WINHTTP_QUERY_AGE 48 +#define WINHTTP_QUERY_CACHE_CONTROL 49 +#define WINHTTP_QUERY_CONTENT_BASE 50 +#define WINHTTP_QUERY_CONTENT_LOCATION 51 +#define WINHTTP_QUERY_CONTENT_MD5 52 +#define WINHTTP_QUERY_CONTENT_RANGE 53 +#define WINHTTP_QUERY_ETAG 54 +#define WINHTTP_QUERY_HOST 55 +#define WINHTTP_QUERY_IF_MATCH 56 +#define WINHTTP_QUERY_IF_NONE_MATCH 57 +#define WINHTTP_QUERY_IF_RANGE 58 +#define WINHTTP_QUERY_IF_UNMODIFIED_SINCE 59 +#define WINHTTP_QUERY_MAX_FORWARDS 60 +#define WINHTTP_QUERY_PROXY_AUTHORIZATION 61 +#define WINHTTP_QUERY_RANGE 62 +#define WINHTTP_QUERY_TRANSFER_ENCODING 63 +#define WINHTTP_QUERY_UPGRADE 64 +#define WINHTTP_QUERY_VARY 65 +#define WINHTTP_QUERY_VIA 66 +#define WINHTTP_QUERY_WARNING 67 +#define WINHTTP_QUERY_EXPECT 68 +#define WINHTTP_QUERY_PROXY_CONNECTION 69 +#define WINHTTP_QUERY_UNLESS_MODIFIED_SINCE 70 + + + +#define WINHTTP_QUERY_PROXY_SUPPORT 75 +#define WINHTTP_QUERY_AUTHENTICATION_INFO 76 +#define WINHTTP_QUERY_PASSPORT_URLS 77 +#define WINHTTP_QUERY_PASSPORT_CONFIG 78 + +#define WINHTTP_QUERY_MAX 78 + +// +// WINHTTP_QUERY_CUSTOM - if this special value is supplied as the dwInfoLevel +// parameter of WinHttpQueryHeaders() then the lpBuffer parameter contains the name +// of the header we are to query +// + +#define WINHTTP_QUERY_CUSTOM 65535 + +// +// WINHTTP_QUERY_FLAG_REQUEST_HEADERS - if this bit is set in the dwInfoLevel +// parameter of WinHttpQueryHeaders() then the request headers will be queried for the +// request information +// + +#define WINHTTP_QUERY_FLAG_REQUEST_HEADERS 0x80000000 + +// +// WINHTTP_QUERY_FLAG_SYSTEMTIME - if this bit is set in the dwInfoLevel parameter +// of WinHttpQueryHeaders() AND the header being queried contains date information, +// e.g. the "Expires:" header then lpBuffer will contain a SYSTEMTIME structure +// containing the date and time information converted from the header string +// + +#define WINHTTP_QUERY_FLAG_SYSTEMTIME 0x40000000 + +// +// WINHTTP_QUERY_FLAG_NUMBER - if this bit is set in the dwInfoLevel parameter of +// HttpQueryHeader(), then the value of the header will be converted to a number +// before being returned to the caller, if applicable +// + +#define WINHTTP_QUERY_FLAG_NUMBER 0x20000000 + + + +// +// HTTP Response Status Codes: +// + +#define HTTP_STATUS_CONTINUE 100 // OK to continue with request +#define HTTP_STATUS_SWITCH_PROTOCOLS 101 // server has switched protocols in upgrade header + +#define HTTP_STATUS_OK 200 // request completed +#define HTTP_STATUS_CREATED 201 // object created, reason = new URI +#define HTTP_STATUS_ACCEPTED 202 // async completion (TBS) +#define HTTP_STATUS_PARTIAL 203 // partial completion +#define HTTP_STATUS_NO_CONTENT 204 // no info to return +#define HTTP_STATUS_RESET_CONTENT 205 // request completed, but clear form +#define HTTP_STATUS_PARTIAL_CONTENT 206 // partial GET fulfilled +#define HTTP_STATUS_WEBDAV_MULTI_STATUS 207 // WebDAV Multi-Status + +#define HTTP_STATUS_AMBIGUOUS 300 // server couldn't decide what to return +#define HTTP_STATUS_MOVED 301 // object permanently moved +#define HTTP_STATUS_REDIRECT 302 // object temporarily moved +#define HTTP_STATUS_REDIRECT_METHOD 303 // redirection w/ new access method +#define HTTP_STATUS_NOT_MODIFIED 304 // if-modified-since was not modified +#define HTTP_STATUS_USE_PROXY 305 // redirection to proxy, location header specifies proxy to use +#define HTTP_STATUS_REDIRECT_KEEP_VERB 307 // HTTP/1.1: keep same verb + +#define HTTP_STATUS_BAD_REQUEST 400 // invalid syntax +#define HTTP_STATUS_DENIED 401 // access denied +#define HTTP_STATUS_PAYMENT_REQ 402 // payment required +#define HTTP_STATUS_FORBIDDEN 403 // request forbidden +#define HTTP_STATUS_NOT_FOUND 404 // object not found +#define HTTP_STATUS_BAD_METHOD 405 // method is not allowed +#define HTTP_STATUS_NONE_ACCEPTABLE 406 // no response acceptable to client found +#define HTTP_STATUS_PROXY_AUTH_REQ 407 // proxy authentication required +#define HTTP_STATUS_REQUEST_TIMEOUT 408 // server timed out waiting for request +#define HTTP_STATUS_CONFLICT 409 // user should resubmit with more info +#define HTTP_STATUS_GONE 410 // the resource is no longer available +#define HTTP_STATUS_LENGTH_REQUIRED 411 // the server refused to accept request w/o a length +#define HTTP_STATUS_PRECOND_FAILED 412 // precondition given in request failed +#define HTTP_STATUS_REQUEST_TOO_LARGE 413 // request entity was too large +#define HTTP_STATUS_URI_TOO_LONG 414 // request URI too long +#define HTTP_STATUS_UNSUPPORTED_MEDIA 415 // unsupported media type +#define HTTP_STATUS_RETRY_WITH 449 // retry after doing the appropriate action. + +#define HTTP_STATUS_SERVER_ERROR 500 // internal server error +#define HTTP_STATUS_NOT_SUPPORTED 501 // required not supported +#define HTTP_STATUS_BAD_GATEWAY 502 // error response received from gateway +#define HTTP_STATUS_SERVICE_UNAVAIL 503 // temporarily overloaded +#define HTTP_STATUS_GATEWAY_TIMEOUT 504 // timed out waiting for gateway +#define HTTP_STATUS_VERSION_NOT_SUP 505 // HTTP version not supported + +#define HTTP_STATUS_FIRST HTTP_STATUS_CONTINUE +#define HTTP_STATUS_LAST HTTP_STATUS_VERSION_NOT_SUP + +// +// prototypes +// + +WINHTTPAPI +HINTERNET +WINAPI +WinHttpOpenRequest +( + IN HINTERNET hConnect, + IN LPCWSTR pwszVerb, + IN LPCWSTR pwszObjectName, + IN LPCWSTR pwszVersion, + IN LPCWSTR pwszReferrer OPTIONAL, + IN LPCWSTR FAR * ppwszAcceptTypes OPTIONAL, + IN DWORD dwFlags +); + +// WinHttpOpenRequest prettifers for optional parameters +#define WINHTTP_NO_REFERER NULL +#define WINHTTP_DEFAULT_ACCEPT_TYPES NULL + +BOOLAPI +WinHttpAddRequestHeaders +( + IN HINTERNET hRequest, + __in_ecount(dwHeadersLength) LPCWSTR pwszHeaders, + IN DWORD dwHeadersLength, + IN DWORD dwModifiers +); + +// +// values for dwModifiers parameter of WinHttpAddRequestHeaders() +// + +#define WINHTTP_ADDREQ_INDEX_MASK 0x0000FFFF +#define WINHTTP_ADDREQ_FLAGS_MASK 0xFFFF0000 + +// +// WINHTTP_ADDREQ_FLAG_ADD_IF_NEW - the header will only be added if it doesn't +// already exist +// + +#define WINHTTP_ADDREQ_FLAG_ADD_IF_NEW 0x10000000 + +// +// WINHTTP_ADDREQ_FLAG_ADD - if WINHTTP_ADDREQ_FLAG_REPLACE is set but the header is +// not found then if this flag is set, the header is added anyway, so long as +// there is a valid header-value +// + +#define WINHTTP_ADDREQ_FLAG_ADD 0x20000000 + +// +// WINHTTP_ADDREQ_FLAG_COALESCE - coalesce headers with same name. e.g. +// "Accept: text/*" and "Accept: audio/*" with this flag results in a single +// header: "Accept: text/*, audio/*" +// + +#define WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA 0x40000000 +#define WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON 0x01000000 +#define WINHTTP_ADDREQ_FLAG_COALESCE WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA + +// +// WINHTTP_ADDREQ_FLAG_REPLACE - replaces the specified header. Only one header can +// be supplied in the buffer. If the header to be replaced is not the first +// in a list of headers with the same name, then the relative index should be +// supplied in the low 8 bits of the dwModifiers parameter. If the header-value +// part is missing, then the header is removed +// + +#define WINHTTP_ADDREQ_FLAG_REPLACE 0x80000000 + +#define WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH 0 + +BOOLAPI +WinHttpSendRequest +( + IN HINTERNET hRequest, + __in_ecount_opt(dwHeadersLength) LPCWSTR lpszHeaders, + IN DWORD dwHeadersLength, + __in_bcount_opt(dwOptionalLength) LPVOID lpOptional, + IN DWORD dwOptionalLength, + IN DWORD dwTotalLength, + IN DWORD_PTR dwContext +); + +// WinHttpSendRequest prettifiers for optional parameters. +#define WINHTTP_NO_ADDITIONAL_HEADERS NULL +#define WINHTTP_NO_REQUEST_DATA NULL + + +BOOLAPI WinHttpSetCredentials +( + + IN HINTERNET hRequest, // HINTERNET handle returned by WinHttpOpenRequest. + + + IN DWORD AuthTargets, // Only WINHTTP_AUTH_TARGET_SERVER and + // WINHTTP_AUTH_TARGET_PROXY are supported + // in this version and they are mutually + // exclusive + + IN DWORD AuthScheme, // must be one of the supported Auth Schemes + // returned from WinHttpQueryAuthSchemes() + + IN LPCWSTR pwszUserName, // 1) NULL if default creds is to be used, in + // which case pszPassword will be ignored + + IN LPCWSTR pwszPassword, // 1) "" == Blank Password; 2)Parameter ignored + // if pszUserName is NULL; 3) Invalid to pass in + // NULL if pszUserName is not NULL + IN LPVOID pAuthParams +); + + +BOOLAPI WinHttpQueryAuthSchemes +( + IN HINTERNET hRequest, // HINTERNET handle returned by WinHttpOpenRequest + OUT LPDWORD lpdwSupportedSchemes, // a bitmap of available Authentication Schemes + OUT LPDWORD lpdwFirstScheme, // returns the first auth scheme returned by the server + OUT LPDWORD pdwAuthTarget +); + +BOOLAPI WinHttpQueryAuthParams( + IN HINTERNET hRequest, // HINTERNET handle returned by WinHttpOpenRequest + IN DWORD AuthScheme, + OUT LPVOID* pAuthParams // Scheme-specific Advanced auth parameters + ); + + +WINHTTPAPI +BOOL +WINAPI +WinHttpReceiveResponse +( + IN HINTERNET hRequest, + IN LPVOID lpReserved +); + +__success(return != FALSE) +BOOLAPI +WinHttpQueryHeaders +( + IN HINTERNET hRequest, + IN DWORD dwInfoLevel, + IN LPCWSTR pwszName OPTIONAL, + __out_bcount_part_opt(*lpdwBufferLength, *lpdwBufferLength) __out_data_source(NETWORK) LPVOID lpBuffer, + IN OUT LPDWORD lpdwBufferLength, + IN OUT LPDWORD lpdwIndex OPTIONAL +); + +// WinHttpQueryHeaders prettifiers for optional parameters. +#define WINHTTP_HEADER_NAME_BY_INDEX NULL +#define WINHTTP_NO_OUTPUT_BUFFER NULL +#define WINHTTP_NO_HEADER_INDEX NULL + + +BOOLAPI +WinHttpDetectAutoProxyConfigUrl +( + DWORD dwAutoDetectFlags, + __deref_out_opt LPWSTR * ppwstrAutoConfigUrl +); + +BOOLAPI +WinHttpGetProxyForUrl +( + IN HINTERNET hSession, + IN LPCWSTR lpcwszUrl, + IN WINHTTP_AUTOPROXY_OPTIONS * pAutoProxyOptions, + OUT WINHTTP_PROXY_INFO * pProxyInfo +); + + +typedef struct +{ + BOOL fAutoDetect; + LPWSTR lpszAutoConfigUrl; + LPWSTR lpszProxy; + LPWSTR lpszProxyBypass; +} WINHTTP_CURRENT_USER_IE_PROXY_CONFIG; + + +BOOLAPI +WinHttpGetIEProxyConfigForCurrentUser +( + IN OUT WINHTTP_CURRENT_USER_IE_PROXY_CONFIG * pProxyConfig +); + + +//#if !defined(_WINERROR_) + +// +// WinHttp API error returns +// + +#define WINHTTP_ERROR_BASE 12000 + +#define ERROR_WINHTTP_OUT_OF_HANDLES (WINHTTP_ERROR_BASE + 1) +#define ERROR_WINHTTP_TIMEOUT (WINHTTP_ERROR_BASE + 2) +#define ERROR_WINHTTP_INTERNAL_ERROR (WINHTTP_ERROR_BASE + 4) +#define ERROR_WINHTTP_INVALID_URL (WINHTTP_ERROR_BASE + 5) +#define ERROR_WINHTTP_UNRECOGNIZED_SCHEME (WINHTTP_ERROR_BASE + 6) +#define ERROR_WINHTTP_NAME_NOT_RESOLVED (WINHTTP_ERROR_BASE + 7) +#define ERROR_WINHTTP_INVALID_OPTION (WINHTTP_ERROR_BASE + 9) +#define ERROR_WINHTTP_OPTION_NOT_SETTABLE (WINHTTP_ERROR_BASE + 11) +#define ERROR_WINHTTP_SHUTDOWN (WINHTTP_ERROR_BASE + 12) + + +#define ERROR_WINHTTP_LOGIN_FAILURE (WINHTTP_ERROR_BASE + 15) +#define ERROR_WINHTTP_OPERATION_CANCELLED (WINHTTP_ERROR_BASE + 17) +#define ERROR_WINHTTP_INCORRECT_HANDLE_TYPE (WINHTTP_ERROR_BASE + 18) +#define ERROR_WINHTTP_INCORRECT_HANDLE_STATE (WINHTTP_ERROR_BASE + 19) +#define ERROR_WINHTTP_CANNOT_CONNECT (WINHTTP_ERROR_BASE + 29) +#define ERROR_WINHTTP_CONNECTION_ERROR (WINHTTP_ERROR_BASE + 30) +#define ERROR_WINHTTP_RESEND_REQUEST (WINHTTP_ERROR_BASE + 32) + +#define ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED (WINHTTP_ERROR_BASE + 44) + +// +// WinHttpRequest Component errors +// +#define ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN (WINHTTP_ERROR_BASE + 100) +#define ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND (WINHTTP_ERROR_BASE + 101) +#define ERROR_WINHTTP_CANNOT_CALL_AFTER_SEND (WINHTTP_ERROR_BASE + 102) +#define ERROR_WINHTTP_CANNOT_CALL_AFTER_OPEN (WINHTTP_ERROR_BASE + 103) + + +// +// HTTP API errors +// + +#define ERROR_WINHTTP_HEADER_NOT_FOUND (WINHTTP_ERROR_BASE + 150) +#define ERROR_WINHTTP_INVALID_SERVER_RESPONSE (WINHTTP_ERROR_BASE + 152) +#define ERROR_WINHTTP_INVALID_HEADER (WINHTTP_ERROR_BASE + 153) +#define ERROR_WINHTTP_INVALID_QUERY_REQUEST (WINHTTP_ERROR_BASE + 154) +#define ERROR_WINHTTP_HEADER_ALREADY_EXISTS (WINHTTP_ERROR_BASE + 155) +#define ERROR_WINHTTP_REDIRECT_FAILED (WINHTTP_ERROR_BASE + 156) + + + +// +// additional WinHttp API error codes +// + +// +// additional WinHttp API error codes +// +#define ERROR_WINHTTP_AUTO_PROXY_SERVICE_ERROR (WINHTTP_ERROR_BASE + 178) +#define ERROR_WINHTTP_BAD_AUTO_PROXY_SCRIPT (WINHTTP_ERROR_BASE + 166) +#define ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT (WINHTTP_ERROR_BASE + 167) + +#define ERROR_WINHTTP_NOT_INITIALIZED (WINHTTP_ERROR_BASE + 172) +#define ERROR_WINHTTP_SECURE_FAILURE (WINHTTP_ERROR_BASE + 175) + + +// +// Certificate security errors. These are raised only by the WinHttpRequest +// component. The WinHTTP Win32 API will return ERROR_WINHTTP_SECURE_FAILE and +// provide additional information via the WINHTTP_CALLBACK_STATUS_SECURE_FAILURE +// callback notification. +// +#define ERROR_WINHTTP_SECURE_CERT_DATE_INVALID (WINHTTP_ERROR_BASE + 37) +#define ERROR_WINHTTP_SECURE_CERT_CN_INVALID (WINHTTP_ERROR_BASE + 38) +#define ERROR_WINHTTP_SECURE_INVALID_CA (WINHTTP_ERROR_BASE + 45) +#define ERROR_WINHTTP_SECURE_CERT_REV_FAILED (WINHTTP_ERROR_BASE + 57) +#define ERROR_WINHTTP_SECURE_CHANNEL_ERROR (WINHTTP_ERROR_BASE + 157) +#define ERROR_WINHTTP_SECURE_INVALID_CERT (WINHTTP_ERROR_BASE + 169) +#define ERROR_WINHTTP_SECURE_CERT_REVOKED (WINHTTP_ERROR_BASE + 170) +#define ERROR_WINHTTP_SECURE_CERT_WRONG_USAGE (WINHTTP_ERROR_BASE + 179) + + +#define ERROR_WINHTTP_AUTODETECTION_FAILED (WINHTTP_ERROR_BASE + 180) +#define ERROR_WINHTTP_HEADER_COUNT_EXCEEDED (WINHTTP_ERROR_BASE + 181) +#define ERROR_WINHTTP_HEADER_SIZE_OVERFLOW (WINHTTP_ERROR_BASE + 182) +#define ERROR_WINHTTP_CHUNKED_ENCODING_HEADER_SIZE_OVERFLOW (WINHTTP_ERROR_BASE + 183) +#define ERROR_WINHTTP_RESPONSE_DRAIN_OVERFLOW (WINHTTP_ERROR_BASE + 184) +#define ERROR_WINHTTP_CLIENT_CERT_NO_PRIVATE_KEY (WINHTTP_ERROR_BASE + 185) +#define ERROR_WINHTTP_CLIENT_CERT_NO_ACCESS_PRIVATE_KEY (WINHTTP_ERROR_BASE + 186) + +#define WINHTTP_ERROR_LAST (WINHTTP_ERROR_BASE + 186) + + +//#endif // !defined(_WINERROR_) + + +#if defined(__cplusplus) +} +#endif + + +/* + * Return packing to whatever it was before we + * entered this file + */ +#include + + +#endif // !defined(_WINHTTPX_) + + diff --git a/kekeo.sln b/kekeo.sln index f6cffc4..53fa582 100644 --- a/kekeo.sln +++ b/kekeo.sln @@ -14,6 +14,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "inc", "inc", "{F673A1F0-9FB inc\globals.h = inc\globals.h inc\Midles.h = inc\Midles.h inc\NtDsAPI.h = inc\NtDsAPI.h + inc\NTSecPKG.h = inc\NTSecPKG.h inc\ossasn1.h = inc\ossasn1.h inc\osstype.h = inc\osstype.h inc\schannel.h = inc\schannel.h @@ -21,6 +22,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "inc", "inc", "{F673A1F0-9FB inc\schnlsp.h = inc\schnlsp.h inc\WinBer.h = inc\WinBer.h inc\WinDNS.h = inc\WinDNS.h + inc\winhttp.h = inc\winhttp.h inc\Winldap.h = inc\Winldap.h EndProjectSection EndProject @@ -34,6 +36,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Win32", "Win32", "{2D5BE43F lib\Win32\ossiphlp.lib = lib\Win32\ossiphlp.lib lib\Win32\samlib.lib = lib\Win32\samlib.lib lib\Win32\soeddefa.lib = lib\Win32\soeddefa.lib + lib\Win32\winhttp.lib = lib\Win32\winhttp.lib EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "x64", "x64", "{71D007E1-9E34-49BC-91C3-65CC186A9A52}" @@ -44,6 +47,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "x64", "x64", "{71D007E1-9E3 lib\x64\ossiphlp.lib = lib\x64\ossiphlp.lib lib\x64\samlib.lib = lib\x64\samlib.lib lib\x64\soeddefa.lib = lib\x64\soeddefa.lib + lib\x64\winhttp.lib = lib\x64\winhttp.lib EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samba", "samba", "{8B68E870-E7A4-446D-9853-3E1042FFD15A}" diff --git a/kekeo/kekeo.c b/kekeo/kekeo.c index 466bc8d..eb08db3 100644 --- a/kekeo/kekeo.c +++ b/kekeo/kekeo.c @@ -13,6 +13,7 @@ const KUHL_M * mimikatz_modules[] = { &kuhl_m_misc, &kuhl_m_kerberos, &kuhl_m_smb, + &kuhl_m_ntlm, }; int wmain(int argc, wchar_t * argv[]) diff --git a/kekeo/kekeo.h b/kekeo/kekeo.h index b97cf69..fef47b5 100644 --- a/kekeo/kekeo.h +++ b/kekeo/kekeo.h @@ -13,6 +13,7 @@ #include "modules/kuhl_m_misc.h" #include "modules/kerberos/kuhl_m_kerberos.h" #include "modules/kuhl_m_smb.h" +#include "modules/kuhl_m_ntlm.h" #include "../modules/kull_m_file.h" #include "../modules/asn1/kull_m_kerberos_asn1.h" diff --git a/kekeo/kekeo.vcxproj b/kekeo/kekeo.vcxproj index c6a5d0f..df3d3b4 100644 --- a/kekeo/kekeo.vcxproj +++ b/kekeo/kekeo.vcxproj @@ -81,7 +81,7 @@ false true true - advapi32.lib;crypt32.lib;dnsapi.lib;netapi32.lib;ntdsapi.lib;ole32.lib;rpcrt4.lib;samlib.lib;secur32.lib;shlwapi.lib;shell32.lib;user32.lib;wldap32.lib;ws2_32.lib;cryptdll.lib;advapi32.hash.lib;ntdll.min.lib;soeddefa.lib;ossiphlp.lib;%(AdditionalDependencies) + advapi32.lib;crypt32.lib;dnsapi.lib;netapi32.lib;ntdsapi.lib;ole32.lib;rpcrt4.lib;samlib.lib;secur32.lib;shlwapi.lib;shell32.lib;user32.lib;wldap32.lib;ws2_32.lib;cryptdll.lib;winhttp.lib;advapi32.hash.lib;ntdll.min.lib;soeddefa.lib;ossiphlp.lib;%(AdditionalDependencies) false true NoErrorReport @@ -116,6 +116,7 @@ + @@ -149,6 +150,7 @@ + diff --git a/kekeo/kekeo.vcxproj.filters b/kekeo/kekeo.vcxproj.filters index b2b7384..4838f42 100644 --- a/kekeo/kekeo.vcxproj.filters +++ b/kekeo/kekeo.vcxproj.filters @@ -103,6 +103,9 @@ common modules + + local modules + @@ -196,6 +199,9 @@ common modules + + local modules + diff --git a/kekeo/modules/kuhl_m_misc.c b/kekeo/modules/kuhl_m_misc.c index a00ba95..dcd309b 100644 --- a/kekeo/modules/kuhl_m_misc.c +++ b/kekeo/modules/kuhl_m_misc.c @@ -10,7 +10,6 @@ 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, @@ -463,210 +462,4 @@ 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"\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"\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"\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""); - 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"\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"\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); } \ No newline at end of file diff --git a/kekeo/modules/kuhl_m_misc.h b/kekeo/modules/kuhl_m_misc.h index 68880c0..6459441 100644 --- a/kekeo/modules/kuhl_m_misc.h +++ b/kekeo/modules/kuhl_m_misc.h @@ -19,7 +19,6 @@ 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; @@ -128,130 +127,4 @@ 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) - -#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); \ No newline at end of file +#pragma pack(pop) \ No newline at end of file diff --git a/kekeo/modules/kuhl_m_ntlm.c b/kekeo/modules/kuhl_m_ntlm.c new file mode 100644 index 0000000..569d546 --- /dev/null +++ b/kekeo/modules/kuhl_m_ntlm.c @@ -0,0 +1,843 @@ +/* Benjamin DELPY `gentilkiwi` + http://blog.gentilkiwi.com + benjamin@gentilkiwi.com + Licence : https://creativecommons.org/licenses/by/4.0/ +*/ +#include "kuhl_m_ntlm.h" + +const KUHL_M_C kuhl_m_c_ntlm[] = { + {kuhl_m_ntlm_netntlm, L"netntlm", NULL}, + {kuhl_m_ntlm_http, L"http", NULL}, +}; +const KUHL_M kuhl_m_ntlm = { + L"ntlm", L"NTLM module", NULL, + ARRAYSIZE(kuhl_m_c_ntlm), kuhl_m_c_ntlm, NULL, NULL +}; + +NTSTATUS kuhl_m_ntlm_netntlm(int argc, wchar_t * argv[]) +{ + SECURITY_STATUS status; + CredHandle Credentials; + TimeStamp CredentialsExpiry, SecurityContextExpiry; + CtxtHandle NewContext = {0}; + SecBuffer InBuff, 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, flags = 0; + PCWCHAR TargetName = NULL, DomainName = NULL, ComputerName = NULL, FileName = NULL; + + if(!kull_m_string_args_byName(argc, argv, L"in", &FileName, NULL)) + { + kull_m_string_args_byName(argc, argv, L"target", &TargetName, NULL); + kull_m_string_args_byName(argc, argv, L"domain", &DomainName, NULL); + kull_m_string_args_byName(argc, argv, L"computer", &ComputerName, NULL); + if(!kull_m_string_args_byName(argc, argv, L"no56", NULL, NULL)) + flags |= NTLMSSP_NEGOTIATE_56; + if(!kull_m_string_args_byName(argc, argv, L"no128", NULL, NULL)) + flags |= NTLMSSP_NEGOTIATE_128; + if(!kull_m_string_args_byName(argc, argv, L"noAlwaysSign", NULL, NULL)) + flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; + if(!kull_m_string_args_byName(argc, argv, L"noESS", NULL, NULL)) + flags |= NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY; + if(kull_m_string_args_byName(argc, argv, L"keyx", NULL, NULL)) + flags |= NTLMSSP_NEGOTIATE_KEY_EXCH; + if(kull_m_string_args_byName(argc, argv, L"seal", NULL, NULL)) + flags |= NTLMSSP_NEGOTIATE_SEAL; + if(kull_m_string_args_byName(argc, argv, L"sign", NULL, NULL)) + flags |= NTLMSSP_NEGOTIATE_SIGN; + } + 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_ntlm_descrGeneric(&Output, NTLMSSP_TypeOneMessage); + kprintf(L"CHALLENGE :\n"); + if(kuhl_m_ntlm_netntlm_buildChallenge(&InBuff, FileName, NULL, NULL, TargetName, DomainName, ComputerName, NULL, flags)) + { + kuhl_m_ntlm_descrGeneric(&Input, NTLMSSP_TypeTwoMessage); + 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_ntlm_descrGeneric(&Output2, NTLMSSP_TypeThreeMessage); + FreeContextBuffer(Out2Buff.pvBuffer); + } + else PRINT_ERROR(L"InitializeSecurityContext(2/2): 0x%08x\n", status); + LocalFree(InBuff.pvBuffer); + } + 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; +} + +BOOL kuhl_m_ntlm_netntlm_buildChallenge(SecBuffer *buffer, const wchar_t *FileName, const UCHAR Challenge[8], KIWI_NTLM_VERSION *Version, const wchar_t *TargetName, const wchar_t *DomainName, const wchar_t *ComputerName, const FILETIME *timeStamp, ULONG AdditionnalFlags) +{ + PUCHAR TiBuffer = NULL; + USHORT TaSize = 0, TiSize = 0; + ULONG FileLen; + PKIWI_NTLM_CHALLENGE_MESSAGE pChal; + FILETIME ft; + + buffer->cbBuffer = 0; + buffer->pvBuffer = NULL; + buffer->BufferType = SECBUFFER_TOKEN; + + if(FileName) + { + if(kull_m_file_readData(FileName, (PBYTE *) &buffer->pvBuffer, &FileLen)) + { + if((FileLen > (sizeof(ULONGLONG) + sizeof(ULONG))) && (FileLen <= MAXWORD)) + buffer->cbBuffer = (USHORT) FileLen; + else + { + PRINT_ERROR(L"File size: %u\n", FileLen); + LocalFree(buffer->pvBuffer); + buffer->pvBuffer = NULL; + } + } + else PRINT_ERROR_AUTO(L"kull_m_file_readData"); + } + else + { + if(TargetName) + TaSize = (USHORT) lstrlen(TargetName) * sizeof(wchar_t); + if(DomainName && ComputerName) + { + if(!timeStamp) + { + GetSystemTimeAsFileTime(&ft); + timeStamp = &ft; + } + kuhl_m_ntlm_netntlm_buildAvPairs(&TiBuffer, &TiSize, MsvAvNbDomainName, DomainName, MsvAvNbComputerName, ComputerName, MsvAvTimestamp, timeStamp, MsvAvEOL); + } + buffer->cbBuffer = FIELD_OFFSET(KIWI_NTLM_CHALLENGE_MESSAGE, Payload) + TaSize + TiSize; + if(buffer->pvBuffer = LocalAlloc(LPTR, buffer->cbBuffer)) + { + pChal = (PKIWI_NTLM_CHALLENGE_MESSAGE) buffer->pvBuffer; + pChal->Signature = NTLMSSP_Signature_ULL; + pChal->MessageType = NTLMSSP_TypeTwoMessage; + pChal->TargetNameFields.Len = pChal->TargetNameFields.MaxLen = TaSize; + pChal->TargetNameFields.Offset = FIELD_OFFSET(KIWI_NTLM_CHALLENGE_MESSAGE, Payload); + pChal->NegotiateFlags = NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_VERSION | AdditionnalFlags; + if(Challenge) + RtlCopyMemory(pChal->Challenge, Challenge, sizeof(pChal->Challenge)); + else + CDGenerateRandomBits(pChal->Challenge, sizeof(pChal->Challenge)); + RtlZeroMemory(pChal->Reserved, 8); + pChal->TargetInfoFields.Len = pChal->TargetInfoFields.MaxLen = TiSize; + pChal->TargetInfoFields.Offset = pChal->TargetNameFields.Offset + pChal->TargetNameFields.MaxLen; + if(Version) + pChal->Version = *Version; + else + { + pChal->Version.ProductMajorVersion = 6; + pChal->Version.ProductMinorVersion = 1; + pChal->Version.ProductBuild = 7601; + RtlZeroMemory(pChal->Version.Reserved, sizeof(pChal->Version.Reserved)); + pChal->Version.NTLMRevisionCurrent = 15; + } + if(TaSize) + { + pChal->NegotiateFlags |= NTLMSSP_REQUEST_TARGET | NTLMSSP_TARGET_TYPE_DOMAIN; + RtlCopyMemory((PUCHAR) pChal + pChal->TargetNameFields.Offset, TargetName, TaSize); + } + if(TiSize) + { + pChal->NegotiateFlags |= NTLMSSP_NEGOTIATE_TARGET_INFO; + RtlCopyMemory((PUCHAR) pChal + pChal->TargetInfoFields.Offset, TiBuffer, TiSize); + } + } + if(TiBuffer) + LocalFree(TiBuffer); + } + return (buffer->pvBuffer != NULL); +} + +void kuhl_m_ntlm_netntlm_buildAvPairs(PUCHAR *buffer, USHORT *size, ...) +{ + va_list vaList; + MSV1_0_AVID type; + PKIWI_NTLM_AV_PAIR pair; + PVOID data; + + *buffer = NULL; + *size = 0; + va_start(vaList, size); + do + { + type = va_arg(vaList, MSV1_0_AVID); + *size += FIELD_OFFSET(KIWI_NTLM_AV_PAIR, Value); + switch(type) + { + case MsvAvNbComputerName: + case MsvAvNbDomainName: + case MsvAvDnsComputerName: + case MsvAvDnsDomainName: + case MsvAvDnsTreeName: + case MsvAvTargetName: + *size += lstrlen(va_arg(vaList, wchar_t *)) * (USHORT) sizeof(wchar_t); + break; + case MsvAvFlags: + *size += sizeof(ULONG); + va_arg(vaList, ULONG); + break; + case MsvAvTimestamp: + *size += sizeof(FILETIME); + va_arg(vaList, FILETIME *); + break; + case MsvAvRestrictions: + *size += (USHORT) va_arg(vaList, PKIWI_NTLM_Single_Host_Data)->Size; + break; + case MsvAvChannelBindings: + *size += MD5_DIGEST_LENGTH; + va_arg(vaList, PVOID); + break; + case MsvAvEOL: + break; + } + } while(type != MsvAvEOL); + va_end(vaList); + + if(*buffer = (PUCHAR) LocalAlloc(LPTR, *size)) + { + va_start(vaList, size); + pair = (PKIWI_NTLM_AV_PAIR) *buffer; + do + { + data = NULL; + type = va_arg(vaList, MSV1_0_AVID); + pair->AvId = type; + switch(type) + { + case MsvAvNbComputerName: + case MsvAvNbDomainName: + case MsvAvDnsComputerName: + case MsvAvDnsDomainName: + case MsvAvDnsTreeName: + case MsvAvTargetName: + data = va_arg(vaList, wchar_t *); + pair->AvLen = (USHORT) lstrlen((wchar_t *) data) * sizeof(wchar_t); + break; + case MsvAvFlags: + data = vaList; + va_arg(vaList, ULONG); + pair->AvLen = sizeof(ULONG); + break; + case MsvAvTimestamp: + data = va_arg(vaList, FILETIME *); + pair->AvLen = sizeof(FILETIME); + break; + case MsvAvRestrictions: + data = va_arg(vaList, PKIWI_NTLM_Single_Host_Data); + pair->AvLen = (USHORT) ((PKIWI_NTLM_Single_Host_Data) data)->Size; + break; + case MsvAvChannelBindings: + data = va_arg(vaList, PVOID); + pair->AvLen = MD5_DIGEST_LENGTH; + break; + case MsvAvEOL: + default: + pair->AvLen = 0; + data = NULL; + break; + } + if(pair->AvLen && data) + RtlCopyMemory(pair->Value, data, pair->AvLen); + pair = (PKIWI_NTLM_AV_PAIR) ((PUCHAR) pair + FIELD_OFFSET(KIWI_NTLM_AV_PAIR, Value) + pair->AvLen); + } while(type != MsvAvEOL); + va_end(vaList); + } +} + +DECLARE_UNICODE_STRING(uNTLM, L"NTLM"); +DECLARE_UNICODE_STRING(uNegotiate, L"Negotiate"); +NTSTATUS kuhl_m_ntlm_http(int argc, wchar_t * argv[]) +{ + PKIWI_HTTP pHttp; + DWORD dwIndex, dwLen, dwDisableRedirect = WINHTTP_OPTION_REDIRECT_POLICY_NEVER; + WORD httpStatus; + wchar_t *text; + UNICODE_STRING scheme; + BOOL isNTLM, isNego; + + SECURITY_STATUS status; + CredHandle Credentials; + TimeStamp CredentialsExpiry, SecurityContextExpiry; + CtxtHandle NewContext = {0}; + SecBuffer InBuff, 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; + PCWCHAR szUrl; + PWCHAR package, negoHeader, authHeader; + SEC_WINNT_AUTH_IDENTITY altIdentity = {NULL, 0, NULL, 0, NULL, 0, SEC_WINNT_AUTH_IDENTITY_UNICODE}; + + if(kull_m_string_args_byName(argc, argv, L"url", &szUrl, NULL)) + { + if(kull_m_string_args_byName(argc, argv, L"user", (PCWCHAR *) &altIdentity.User, NULL)) + { + altIdentity.UserLength = lstrlen((LPCWSTR) altIdentity.User); + if(kull_m_string_args_byName(argc, argv, L"domain", (PCWCHAR *) &altIdentity.Domain, NULL)) + altIdentity.DomainLength = lstrlen((LPCWSTR) altIdentity.Domain); + if(kull_m_string_args_byName(argc, argv, L"password", (PCWCHAR *) &altIdentity.Password, NULL)) + altIdentity.PasswordLength = lstrlen((LPCWSTR) altIdentity.Password); + } + + if(pHttp = kuhl_m_ntlm_http_giveHTTP(szUrl, NULL)) + { + kprintf(L"\n[Server]\n"); + if(kuhl_m_ntlm_http_sendReceiveHTTP(pHttp, WINHTTP_NO_ADDITIONAL_HEADERS, NULL, NULL, &httpStatus)) + { + if(kuhl_m_ntlm_http_getHeaders(pHttp, WINHTTP_QUERY_SERVER, WINHTTP_NO_HEADER_INDEX, (PBYTE *) &text, &dwLen)) + { + kprintf(L" Server: %.*s\n", dwLen / sizeof(wchar_t), text); + LocalFree(text); + } + if(httpStatus == HTTP_STATUS_DENIED) + { + kprintf(L" WWW-Authenticate: "); + for(isNTLM = isNego = FALSE, dwIndex = 0; kuhl_m_ntlm_http_getHeaders(pHttp, WINHTTP_QUERY_WWW_AUTHENTICATE, &dwIndex, (PBYTE *) &text, &dwLen);) + { + scheme.Length = scheme.MaximumLength = (WORD) dwLen; + scheme.Buffer = text; + kprintf(L"`%wZ`, ", &scheme); + if(RtlEqualUnicodeString(&uNTLM, &scheme, TRUE)) + isNTLM = TRUE; + else if(RtlEqualUnicodeString(&uNegotiate, &scheme, TRUE)) + isNego = TRUE; + LocalFree(text); + } + kprintf(L"\n"); + + if(isNego || isNTLM) + { + package = isNego ? L"Negotiate" : L"NTLM"; + status = AcquireCredentialsHandle(NULL, L"NTLM"/*package*/, SECPKG_CRED_OUTBOUND, NULL, altIdentity.UserLength ? &altIdentity : NULL, NULL, NULL, &Credentials, &CredentialsExpiry); + if(status == SEC_E_OK) + { + kprintf(L"\n[SSPI - 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_ntlm_descrGeneric(&Output, NTLMSSP_TypeOneMessage); + if(negoHeader = kuhl_m_ntlm_http_encodeAuthNTLMB64(package, &Output)) + { + kprintf(L"[Client]\n %s\n\n[Server]\n", negoHeader); + if(kuhl_m_ntlm_http_sendReceiveHTTP(pHttp, negoHeader, NULL, NULL, &httpStatus)) + { + kprintf(L" WWW-Authenticate: "); + if(kuhl_m_ntlm_http_getHeaders(pHttp, WINHTTP_QUERY_WWW_AUTHENTICATE, WINHTTP_NO_HEADER_INDEX, (PBYTE *) &text, &dwLen)) + { + kprintf(L"%.*s\n[SSPI - CHALLENGE]\n", dwLen / sizeof(wchar_t), text); + if(kuhl_m_ntlm_http_decodeB64NTLMAuth(package, text, &Input)) + { + kuhl_m_ntlm_descrGeneric(&Input, NTLMSSP_TypeTwoMessage); + if(altIdentity.UserLength || kull_m_string_args_byName(argc, argv, L"auth", NULL, NULL)) + { + kprintf(L"\n[SSPI - 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_ntlm_descrGeneric(&Output2, NTLMSSP_TypeThreeMessage); + if(authHeader = kuhl_m_ntlm_http_encodeAuthNTLMB64(package, &Output2)) + { + kprintf(L"[Client]\n %s\n\n[Server]\n", authHeader); + if(!WinHttpSetOption(pHttp->hRequest, WINHTTP_OPTION_REDIRECT_POLICY, &dwDisableRedirect, sizeof(dwDisableRedirect))) + PRINT_ERROR_AUTO(L"WinHttpSetOption(WINHTTP_OPTION_REDIRECT_POLICY, WINHTTP_OPTION_REDIRECT_POLICY_NEVER)"); + if(kuhl_m_ntlm_http_sendReceiveHTTP(pHttp, authHeader, NULL, NULL, &httpStatus)) + { + if((httpStatus >= 300) && (httpStatus < 400)) + { + if(kuhl_m_ntlm_http_getHeaders(pHttp, WINHTTP_QUERY_LOCATION, WINHTTP_NO_HEADER_INDEX, (PBYTE *) &text, &dwLen)) + { + kprintf(L" Location: %.*s\n", dwLen / sizeof(wchar_t), text); + LocalFree(text); + } + } + } + LocalFree(authHeader); + } + FreeContextBuffer(Out2Buff.pvBuffer); + } + else PRINT_ERROR(L"InitializeSecurityContext(2/2): 0x%08x\n", status); + } + LocalFree(Input.pBuffers[0].pvBuffer); + } + LocalFree(text); + } + } + LocalFree(negoHeader); + } + 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); + } + } + } + kuhl_m_ntlm_http_closeHTTP(pHttp, TRUE); + } + } + else PRINT_ERROR(L"Missing /url:http[s]://server[:port][/...]\n"); + return STATUS_SUCCESS; +} + +PKIWI_HTTP kuhl_m_ntlm_http_giveHTTP(LPCWSTR url, LPCWSTR verb) +{ + KIWI_HTTP kHttp = {0}, *kReturn = NULL; + BOOL status = FALSE; + URL_COMPONENTS urlComponents = {0}; + DWORD dwDisableAuth = WINHTTP_DISABLE_AUTHENTICATION, dwDisableCertErrors = SECURITY_FLAG_IGNORE_UNKNOWN_CA | SECURITY_FLAG_IGNORE_CERT_CN_INVALID | SECURITY_FLAG_IGNORE_CERT_DATE_INVALID | SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE; + wchar_t *hostname = NULL; + + urlComponents.dwStructSize = sizeof(urlComponents); + urlComponents.dwHostNameLength = (DWORD) -1; + urlComponents.dwUrlPathLength = (DWORD) -1; + if(WinHttpCrackUrl(url, 0, 0, &urlComponents)) + { + kprintf(L"Using: %.*s on port %hu for \'%s\'", urlComponents.dwHostNameLength, urlComponents.lpszHostName, urlComponents.nPort, urlComponents.lpszUrlPath); + if(urlComponents.nScheme == INTERNET_SCHEME_HTTPS) + kprintf(L" - SSL\n"); + else kprintf(L"\n"); + if(hostname = (wchar_t *) LocalAlloc(LPTR, (urlComponents.dwHostNameLength + 1) * sizeof(wchar_t))) + { + RtlCopyMemory(hostname, urlComponents.lpszHostName, urlComponents.dwHostNameLength * sizeof(wchar_t)); + if(kHttp.hSession = WinHttpOpen(NULL, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0)) + { + if(kHttp.hConnect = WinHttpConnect(kHttp.hSession, hostname, urlComponents.nPort, 0)) + { + if(kHttp.hRequest = WinHttpOpenRequest(kHttp.hConnect, verb ? verb : L"GET", urlComponents.lpszUrlPath, NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, (urlComponents.nScheme == INTERNET_SCHEME_HTTPS) ? WINHTTP_FLAG_SECURE : 0)) + { + if(WinHttpSetOption(kHttp.hRequest, WINHTTP_OPTION_DISABLE_FEATURE, &dwDisableAuth, sizeof(dwDisableAuth))) + { + if(!(status = WinHttpSetOption(kHttp.hRequest, WINHTTP_OPTION_SECURITY_FLAGS, &dwDisableCertErrors, sizeof(dwDisableCertErrors)))) + PRINT_ERROR_AUTO(L"WinHttpSetOption(WINHTTP_OPTION_SECURITY_FLAGS, certificate)"); + } + else PRINT_ERROR_AUTO(L"WinHttpSetOption(WINHTTP_OPTION_DISABLE_FEATURE, WINHTTP_DISABLE_AUTHENTICATION)"); + } + else PRINT_ERROR_AUTO(L"WinHttpOpenRequest"); + } + else PRINT_ERROR_AUTO(L"WinHttpConnect"); + } + else PRINT_ERROR_AUTO(L"WinHttpOpen"); + LocalFree(hostname); + } + } + else PRINT_ERROR_AUTO(L"WinHttpCrackUrl"); + + if(status) + { + if(kReturn = (PKIWI_HTTP) LocalAlloc(LPTR, sizeof(KIWI_HTTP))) + *kReturn = kHttp; + } + else kuhl_m_ntlm_http_closeHTTP(&kHttp, FALSE); + return kReturn; +} + +void kuhl_m_ntlm_http_closeHTTP(PKIWI_HTTP kHttp, BOOL freeIt) +{ + if(kHttp) + { + if(kHttp->hRequest) + WinHttpCloseHandle(kHttp->hRequest); + if(kHttp->hConnect) + WinHttpCloseHandle(kHttp->hConnect); + if(kHttp->hSession) + WinHttpCloseHandle(kHttp->hSession); + if(freeIt) + LocalFree(kHttp); + } +} + +BOOL kuhl_m_ntlm_http_getHeaders(PKIWI_HTTP pHttp, DWORD dwInfoLevel, PDWORD pdwIndex, PBYTE *data, DWORD *len) +{ + BOOL status = FALSE; + if(!WinHttpQueryHeaders(pHttp->hRequest, dwInfoLevel, WINHTTP_HEADER_NAME_BY_INDEX, WINHTTP_NO_OUTPUT_BUFFER, len, pdwIndex) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) + { + if(*data = (PBYTE) LocalAlloc(LPTR, *len)) + { + if(!(status = WinHttpQueryHeaders(pHttp->hRequest, dwInfoLevel, WINHTTP_HEADER_NAME_BY_INDEX, *data, len, pdwIndex))) + { + PRINT_ERROR_AUTO(L"WinHttpQueryHeaders(2/2"); + LocalFree(*data); + } + } + } + else if(GetLastError() != ERROR_WINHTTP_HEADER_NOT_FOUND) PRINT_ERROR_AUTO(L"WinHttpQueryHeaders(1/2)"); + return status; +} + +BOOL kuhl_m_ntlm_http_sendReceiveHTTP(PKIWI_HTTP pHttp, PCWCHAR headers, PBYTE *data, DWORD *len, WORD *httpStatus) +{ + BOOL status = FALSE; + DWORD dwStatusCode, dwLen = sizeof(dwStatusCode), dwText; + PBYTE text; + + if(WinHttpSendRequest(pHttp->hRequest, headers, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0)) + { + if(WinHttpReceiveResponse(pHttp->hRequest, NULL)) + { + kprintf(L" Status: "); + if(WinHttpQueryHeaders(pHttp->hRequest, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, WINHTTP_HEADER_NAME_BY_INDEX, &dwStatusCode, &dwLen, WINHTTP_NO_HEADER_INDEX)) + { + if(dwStatusCode <= MAXWORD) + { + kprintf(L"%u", dwStatusCode); + if(httpStatus) + *httpStatus = (WORD) dwStatusCode; + } + } + kprintf(L" - "); + if(kuhl_m_ntlm_http_getHeaders(pHttp, WINHTTP_QUERY_STATUS_TEXT, WINHTTP_NO_HEADER_INDEX, &text, &dwText)) + kprintf(L"%.*s", dwText / sizeof(wchar_t), text); + kprintf(L"\n"); + + if(data && len) + { + if(WinHttpQueryDataAvailable(pHttp->hRequest, &dwLen)) + { + if(*data = (PBYTE) LocalAlloc(LPTR, dwLen)) + { + *len = 0; + if(!(status = WinHttpReadData(pHttp->hRequest, *data, dwLen, len))) + { + PRINT_ERROR_AUTO(L"WinHttpReadData"); + LocalFree(*data); + } + } + } + else PRINT_ERROR_AUTO(L"WinHttpQueryDataAvailable"); + } + else status = TRUE; + } + else PRINT_ERROR_AUTO(L"WinHttpReceiveResponse"); + } + else PRINT_ERROR_AUTO(L"WinHttpSendRequest"); + return status; +} + +PWCHAR kuhl_m_ntlm_http_encodeAuthNTLMB64(LPCWCHAR Scheme, PSecBufferDesc pBuf) +{ + PWCHAR out = NULL, Base64, ptr; + DWORD dwNeed = 0; + if(CryptBinaryToString((LPCBYTE) pBuf->pBuffers[0].pvBuffer, pBuf->pBuffers[0].cbBuffer, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, NULL, &dwNeed)) + { + if(Base64 = (PWCHAR) LocalAlloc(LPTR, dwNeed * sizeof(wchar_t))) + { + if(CryptBinaryToString((LPCBYTE) pBuf->pBuffers[0].pvBuffer, pBuf->pBuffers[0].cbBuffer, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, Base64, &dwNeed)) + { + if(MIMIKATZ_NT_MAJOR_VERSION < 6) + for(ptr = Base64; ptr = wcsstr(ptr, L"\r\n"); RtlMoveMemory(ptr, ptr + 2, (lstrlen(ptr + 2) + 1) * sizeof(wchar_t))); + kull_m_string_sprintf(&out, L"Authorization: %s %s", Scheme, Base64); + } + else PRINT_ERROR_AUTO(L"CryptBinaryToString(data)"); + LocalFree(Base64); + } + } + else PRINT_ERROR_AUTO(L"CryptBinaryToString(init)"); + return out; +} + +BOOL kuhl_m_ntlm_http_decodeB64NTLMAuth(LPCWCHAR Scheme, PCWCHAR b64, PSecBufferDesc pBuf) +{ + BOOL status = FALSE; + PWCHAR tmp; + size_t off; + pBuf->pBuffers[0].cbBuffer = 0; + pBuf->pBuffers[0].pvBuffer = NULL; + pBuf->pBuffers[0].BufferType = SECBUFFER_TOKEN; + + if(kull_m_string_sprintf(&tmp, L"%s ", Scheme)) + { + if(wcsstr(b64, tmp) == b64) + { + off = wcslen(tmp); + if(CryptStringToBinary(b64 + off, 0, CRYPT_STRING_BASE64, NULL, &pBuf->pBuffers[0].cbBuffer, NULL, NULL)) + { + if(pBuf->pBuffers[0].pvBuffer = LocalAlloc(LPTR, pBuf->pBuffers[0].cbBuffer)) + { + if(!(status = CryptStringToBinary(b64 + off, 0, CRYPT_STRING_BASE64, (PBYTE) pBuf->pBuffers[0].pvBuffer, &pBuf->pBuffers[0].cbBuffer, NULL, NULL))) + { + PRINT_ERROR_AUTO(L"CryptStringToBinary(data)"); + LocalFree(pBuf->pBuffers[0].pvBuffer); + pBuf->pBuffers[0].cbBuffer = 0; + pBuf->pBuffers[0].pvBuffer = NULL; + } + } + } + else PRINT_ERROR_AUTO(L"CryptStringToBinary(init)"); + } + LocalFree(tmp); + } + return status; +} + +void kuhl_m_ntlm_descrGeneric(PSecBufferDesc buff, ULONG WantedMessageType) +{ + ULONGLONG Signature; + ULONG MessageType; + if(buff) + { + if(buff->ulVersion == SECBUFFER_VERSION) + { + if(buff->cBuffers == 1) + { + if(buff->pBuffers) + { + if((buff->pBuffers[0].BufferType & ~SECBUFFER_ATTRMASK) == SECBUFFER_TOKEN) + { + if(buff->pBuffers[0].cbBuffer > (sizeof(ULONGLONG) + sizeof(ULONG))) + { + if(buff->pBuffers[0].pvBuffer) + { + Signature = *(PULONGLONG) buff->pBuffers[0].pvBuffer; + MessageType = ((PULONG) buff->pBuffers[0].pvBuffer)[2]; + if(Signature == NTLMSSP_Signature_ULL) + { + if(!WantedMessageType || (WantedMessageType == MessageType)) + { + switch(MessageType) + { + case NTLMSSP_TypeOneMessage: + kuhl_m_ntlm_descrNegotiate((PKIWI_NTLM_NEGOTIATE_MESSAGE) buff->pBuffers[0].pvBuffer); + break; + case NTLMSSP_TypeTwoMessage: + kuhl_m_ntlm_descrChallenge((PKIWI_NTLM_CHALLENGE_MESSAGE) buff->pBuffers[0].pvBuffer); + break; + case NTLMSSP_TypeThreeMessage: + kuhl_m_ntlm_descrAuthenticate((PKIWI_NTLM_AUTHENTICATE_MESSAGE) buff->pBuffers[0].pvBuffer); + break; + default: + PRINT_ERROR(L"Unknown MessageType: 0x%08x\n", MessageType); + } + } + else PRINT_ERROR(L"Invalid MessageType: 0x%08x\n", MessageType); + } + else PRINT_ERROR(L"Invalid Signature: %016llx\n", _byteswap_uint64(Signature)); + } + else PRINT_ERROR(L"SecBuffer - pvBuffer is NULL\n"); + } + else PRINT_ERROR(L"SecBuffer - cbBuffer (%u)\n", buff->pBuffers[0].BufferType); + } + else PRINT_ERROR(L"SecBuffer - BufferType (0x%08x)\n", buff->pBuffers[0].BufferType); + } + else PRINT_ERROR(L"SecBufferDesc - pBuffers is NULL\n"); + } + else PRINT_ERROR(L"SecBufferDesc - cbBuffers (%u)\n", buff->cBuffers); + } + else PRINT_ERROR(L"SecBufferDesc - ulVersion (%u)\n", buff->ulVersion); + } + else PRINT_ERROR(L"SecBufferDesc - No buffer\n"); +} + +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_ntlm_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"); +} + +const PCWCHAR KIWI_MSV1_0_AVIDS[] = {L"EOL", L"NbComputerName", L"NbDomainName", L"DnsComputerName", L"DnsDomainName", L"DnsTreeName", L"Flags", L"Timestamp", L"Restrictions", L"TargetName", L"ChannelBindings",}; +const PCWCHAR KIWI_MSV1_0_AVFLAGS[] = {L"FORCE_GUEST", L"MIC_HANDSHAKE_MESSAGES", L"UNVERIFIED_TARGET"}; +void kuhl_m_ntlm_descrAvPairs(PKIWI_NTLM_AV_PAIR pPair, USHORT len) +{ + ULONG i, flags; + PKIWI_NTLM_Single_Host_Data pData; + while(pPair->AvId) + { + kprintf(L" [%04x] %-15s - ", pPair->AvId, (pPair->AvId < ARRAYSIZE(KIWI_MSV1_0_AVIDS)) ? KIWI_MSV1_0_AVIDS[pPair->AvId] : L"?"); + switch(pPair->AvId) + { + case MsvAvNbComputerName: + case MsvAvNbDomainName: + case MsvAvDnsComputerName: + case MsvAvDnsDomainName: + case MsvAvDnsTreeName: + case MsvAvTargetName: + kprintf(L"\'%.*s\'", pPair->AvLen / sizeof(wchar_t), pPair->Value); + break; + case MsvAvFlags: + flags = *(PULONG) pPair->Value; + kprintf(L"%08x - ", flags); + for(i = 0; i < sizeof(flags) * 8; i++) + if((flags >> i) & 1) + kprintf(L"%s ; ", (i < ARRAYSIZE(KIWI_MSV1_0_AVFLAGS)) ? KIWI_MSV1_0_AVFLAGS[i] : L"?"); + break; + case MsvAvTimestamp: + kull_m_string_displayLocalFileTime((PFILETIME) pPair->Value); + break; + case MsvAvRestrictions: + pData = (PKIWI_NTLM_Single_Host_Data) pPair->Value; + kprintf(L"CustomData: "); + kull_m_string_wprintf_hex(pData->CustomData, sizeof(pData->CustomData), 0); + kprintf(L" ; MachineID: "); + kull_m_string_wprintf_hex(pData->MachineID, sizeof(pData->MachineID), 0); + if(pData->Size > FIELD_OFFSET(KIWI_NTLM_Single_Host_Data, AdditionnalData)) + { + kprintf(L" ; ?: "); + kull_m_string_wprintf_hex(pData->AdditionnalData, pData->Size - FIELD_OFFSET(KIWI_NTLM_Single_Host_Data, AdditionnalData), 0); + } + break; + case MsvAvChannelBindings: + default: + kull_m_string_wprintf_hex(pPair->Value, pPair->AvLen, 0); + break; + } + kprintf(L"\n"); + pPair = (PKIWI_NTLM_AV_PAIR) ((PUCHAR) pPair + FIELD_OFFSET(KIWI_NTLM_AV_PAIR, Value) + pPair->AvLen); + } +} + +void kuhl_m_ntlm_descrAuthenticate(PKIWI_NTLM_AUTHENTICATE_MESSAGE pAuth) +{ + 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_ntlm_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"\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"\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"\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""); + 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 Response : "); + kull_m_string_wprintf_hex(pLMv2->Response, sizeof(pLMv2->Response), 0); + kprintf(L"\n 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 Response : "); + kull_m_string_wprintf_hex(pNTLMv2->Response, sizeof(pNTLMv2->Response), 0); + kprintf(L"\n ClientChallenge: "); + kull_m_string_wprintf_hex(pNTLMv2->ClientChallenge.ChallengeFromClient, sizeof(pNTLMv2->ClientChallenge.ChallengeFromClient), 0); + kprintf(L"\n TimeStamp : "); + kull_m_string_displayLocalFileTime(&pNTLMv2->ClientChallenge.TimeStamp); + kprintf(L"\n"); + if(pAuth->NtChallengeResponseFields.Len >= (sizeof(KIWI_NTLM_NTLMv2_RESPONSE) + FIELD_OFFSET(KIWI_NTLM_AV_PAIR, Value))) + kuhl_m_ntlm_descrAvPairs((PKIWI_NTLM_AV_PAIR) ((PUCHAR) pNTLMv2 + sizeof(KIWI_NTLM_NTLMv2_RESPONSE)), pAuth->NtChallengeResponseFields.Len - sizeof(KIWI_NTLM_NTLMv2_RESPONSE)); + } + 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 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); +} + +const BYTE KIWI_NTLM_BLACK_CHALLENGES[][8] = { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}, + {0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00}, + {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}, + {'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A'}, + {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}, +}; +void kuhl_m_ntlm_descrChallenge(PKIWI_NTLM_CHALLENGE_MESSAGE pChal) +{ + DWORD i; + kprintf(L" NegotiateFlags: "); + kuhl_m_ntlm_descrNegotiateFlags(pChal->NegotiateFlags); + kprintf(L" Challenge : "); kull_m_string_wprintf_hex(pChal->Challenge, sizeof(pChal->Challenge), 0); kprintf(L"\n"); + for(i = 0; i < ARRAYSIZE(KIWI_NTLM_BLACK_CHALLENGES); i++) + if(RtlEqualMemory(KIWI_NTLM_BLACK_CHALLENGES[i], pChal->Challenge, 8)) + { + kprintf(L" ** BLACKLISTED CHALLENGE! **\n"); + break; + } + if(pChal->NegotiateFlags & NTLMSSP_REQUEST_TARGET) + kprintf(L" TargetName : %.*s\n", pChal->TargetNameFields.Len / sizeof(wchar_t), (PUCHAR) pChal + pChal->TargetNameFields.Offset); + if(pChal->NegotiateFlags & NTLMSSP_NEGOTIATE_TARGET_INFO) + { + kprintf(L" TargetInfo :\n"); + kuhl_m_ntlm_descrAvPairs((PKIWI_NTLM_AV_PAIR) ((PBYTE) pChal + pChal->TargetInfoFields.Offset), pChal->TargetInfoFields.Len); + } + 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_ntlm_descrNegotiate(PKIWI_NTLM_NEGOTIATE_MESSAGE pNeg) +{ + kprintf(L" NegotiateFlags: "); + kuhl_m_ntlm_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"\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"\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); +} \ No newline at end of file diff --git a/kekeo/modules/kuhl_m_ntlm.h b/kekeo/modules/kuhl_m_ntlm.h new file mode 100644 index 0000000..c218d6c --- /dev/null +++ b/kekeo/modules/kuhl_m_ntlm.h @@ -0,0 +1,178 @@ +/* Benjamin DELPY `gentilkiwi` + http://blog.gentilkiwi.com + benjamin@gentilkiwi.com + Licence : https://creativecommons.org/licenses/by/4.0/ +*/ +#pragma once +#include "kuhl_m.h" +#include +#include "../../modules/kull_m_string.h" +#include "../../modules/kull_m_file.h" +#include "../../modules/kull_m_crypto_system.h" + +const KUHL_M kuhl_m_ntlm; + +NTSTATUS kuhl_m_ntlm_netntlm(int argc, wchar_t * argv[]); +NTSTATUS kuhl_m_ntlm_http(int argc, wchar_t * argv[]); + +#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) + +#ifndef MSV1_0_AV_FLAG_UNVERIFIED_TARGET +#define MSV1_0_AV_FLAG_UNVERIFIED_TARGET 0x00000004 +#endif + +typedef struct _KIWI_NTLM_Single_Host_Data { + ULONG Size; + ULONG Z4; + UCHAR CustomData[8]; + UCHAR MachineID[32]; + UCHAR AdditionnalData[ANYSIZE_ARRAY]; +} KIWI_NTLM_Single_Host_Data, *PKIWI_NTLM_Single_Host_Data; + +typedef struct _KIWI_NTLM_AV_PAIR { + USHORT AvId; + USHORT AvLen; + UCHAR Value[ANYSIZE_ARRAY]; +} KIWI_NTLM_AV_PAIR, *PKIWI_NTLM_AV_PAIR; + +typedef struct _KIWI_NTLM_VERSION { + UCHAR ProductMajorVersion; + UCHAR ProductMinorVersion; + USHORT ProductBuild; + UCHAR Reserved[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) + +typedef struct _KIWI_HTTP { + HINTERNET hSession; + HINTERNET hConnect; + HINTERNET hRequest; +} KIWI_HTTP, *PKIWI_HTTP; + +BOOL kuhl_m_ntlm_netntlm_buildChallenge(SecBuffer *buffer, const wchar_t *FileName, const UCHAR Challenge[8], KIWI_NTLM_VERSION *Version, const wchar_t *TargetName, const wchar_t *DomainName, const wchar_t *ComputerName, const FILETIME *timeStamp, ULONG AdditionnalFlags); +void kuhl_m_ntlm_netntlm_buildAvPairs(PUCHAR *buffer, USHORT *size, ...); + +PKIWI_HTTP kuhl_m_ntlm_http_giveHTTP(LPCWSTR url, LPCWSTR verb); +void kuhl_m_ntlm_http_closeHTTP(PKIWI_HTTP kHttp, BOOL freeIt); +BOOL kuhl_m_ntlm_http_getHeaders(PKIWI_HTTP pHttp, DWORD dwInfoLevel, PDWORD pdwIndex, PBYTE *data, DWORD *len); +BOOL kuhl_m_ntlm_http_sendReceiveHTTP(PKIWI_HTTP pHttp, PCWCHAR headers, PBYTE *data, DWORD *len, WORD *httpStatus); +PWCHAR kuhl_m_ntlm_http_encodeAuthNTLMB64(LPCWCHAR Scheme, PSecBufferDesc pBuf); +BOOL kuhl_m_ntlm_http_decodeB64NTLMAuth(LPCWCHAR Scheme, PCWCHAR b64, PSecBufferDesc pBuf); + +void kuhl_m_ntlm_descrGeneric(PSecBufferDesc buff, ULONG WantedMessageType); +void kuhl_m_ntlm_descrNegotiateFlags(ULONG flags); +void kuhl_m_ntlm_descrAvPairs(PKIWI_NTLM_AV_PAIR pPair, USHORT len); +void kuhl_m_ntlm_descrAuthenticate(PKIWI_NTLM_AUTHENTICATE_MESSAGE pAuth); +void kuhl_m_ntlm_descrChallenge(PKIWI_NTLM_CHALLENGE_MESSAGE pChal); +void kuhl_m_ntlm_descrNegotiate(PKIWI_NTLM_NEGOTIATE_MESSAGE pNeg); \ No newline at end of file diff --git a/lib/Win32/winhttp.lib b/lib/Win32/winhttp.lib new file mode 100644 index 0000000000000000000000000000000000000000..9ac9fa537a335261e8a902472d62720e4ee3914d GIT binary patch literal 8822 zcmcIpJ#Z686n_5U$2I|DFwU$NFd{ zME=c3ql?#XE-cN@%k6XGGdeea(|di`4FEp^^lkw39Rc*e2AJ*>^cMJ0_Qu`J%5r)cGWYYvRo6X8=l9ud$KFpp zDYg2ZaMbRlZ0K|%|9wTmYcVW@dc%mdcva5R5N|n6Bd20 zFqdWB<+5v&aq`7cch4kPn{%a;+qR=!UYw@NuW7E`A_Kr45@p9>MR&Wz9Nl`=5f}Y# z97drCiG`ml9T?u!FV~G$g%9O@H&CvataJL_NY1^1qas^Mo`@UZOIE z4jNDqH!3(X$`G=Aeo6LgnU&mlRNY6FDRh=|Iia%3tQ>PnK_tD1(8q};9G1f!%Ugv~ zJgSRc*Q=u{(2>M(oH$`=FiMJIr=dv?j)DwpH~P)k2S(Hz;mScLjciXfWjca%m~2j6u?XT zo*e~vh2JmnIfKe?u>I3GKoaG9#{ixV0KA<9SV8K%2=HM7;1K!GkoN`Y0e*kPK3|~j zXOzW6&C3&rzy+9s(=Y*ja1u^I4|KtIa0bpoKa9c{jKFyqhhZ2*g>LADb1(^=Z~}&) z4cc4K?tqMGY5kmTj0w6e^^GnhZR!n96XWVMbVNHA_b zIEWz{;}OX?LR=RP!b4$5EH*`Ua}6X$fgJ>ghK-t>T+@&OkZ9J|poAGxKgua1SpC*7 zk42$t^cX42>-|O+@oO^dRU0uAst-x(iYLju&|<<+Nz>9;>doX~l3=|uR~4?~ZK}9h zTT1+@=LK3rDfItNEL|7(2@kv1+dAOfrIEFsHoz=h`L)gF z*iQM;Ov?KNSjHE;PLO_a=>2&%pTi<=Ch9XT;LBe~|B8kVe8yq!ose4;&6xcGz9RW@ zygd$)ckTG>!}@^#ddQ?MLx1lnY~%g$AD8Gl>bsZEI(Et4bt6}jS0n3d8+R*QQ6*09Bb-t%bKo_#g4(y#p+XFaBr;yjj6>_HkZzbd%{eWGT^@fAhpGrM+S)e^v&^ zhX`6r$yHdjKg3e5`>otk{_sD#Wvr7xlO^h1XBa`eE{aDgSPDqq8=Ie> z;xPtMkC{fiZV8Xn#RTLVJmrRdhSw0Whaeit?UwLwgzP9!I%f!eohrVyF@&r-58?dQ z!;cnqkK!$jBIc(bW$!QHD9*~GP|h3_mb^D)aSI`+cu9n}I<>j`CmGUz^WGcN+uHYt z)vI8U^AUw?+JhJUQb<|VD~NfXVCs%t6qvj>w63NM)TiRASE>Z8d5?}6GC{wJOwNcD zl)N`I+n8ZzFQ}NcqZ@(whItxd^8mr52U-e9-W!`^h^KJ>9F*|XV=_THR-YLnsLJ7+ zLN@I)rbsj_VXFUqp|Iq=q4hOof)N?jbW=cJzrm(LG6B!Oqw*Mz$%;*JVoXL1-b}VO tSA)-v%gFS)q$Nz#Y$ph&_7iR!MCj5s;*|BaUWcPq2mUP1oxPPL*=t zRB`ElfK&-_;7o5EIB=;{Aywi6qIZNi^-ACD&g{<2?rgo78oli9yf^ckdGo$zIR33+ zm8;(;zDdfz`BZA*>|$mila|}hu+RC$dG>lE0RZ0t^gjX^cmXij4=^{*=pH_iMn@U# z;S*{2nM-4J07^4CmqywG8=#@*; z&jB3T!Y5L)$EB&a*biy)zDpC2u^-apDVL`9kdHKS!KK*;h>J8_bZMxH<5x?i)oUB; z`C=(|v5?KLZWPz^rR%F}E5+glluB!xSFZ*I;AbY`@{22*YgbCS<>E42uQgX}d#6}y zkV}@?DBNk;q(Q%MtXgBIq~{Bqq8Zgs;<8>@%P8O4wCXa7*Xl_T!zLkOyqU{YN%_`B z-LSV!tDy`jv6%d2V&}-V(XQJYmU;V5)@*LqZniDMu9;1_d!!^AtmTv{L>Go$i-RE6^9$B=YEn)?<5+%zVk#AW)gCkE7Jk#Y!Ae8cn=fC|5~?C@Xb(h+MH3o&WN# zQL7tUb!BQ!Kbh~X$fyJtp2xj$TA5U~ZnnsZ(X6Ngiwq`r$qK`W2 zC}9%~dY0PD^Dl`J;$;E81ENo+z+SSjLxM_y>C~!N3ovYZa_^PNX;s(7dBWrt zSTklzfcHpTjO^HgV$*UqdwJVG-Jt!ER2qnN&Oy97Ez?4ki1Qb{*n~fcu>*3qK!h4*b-vdQ4c~jy`UIK8Y zTjedz;#?dilcqA*2|SsM-$L7y^bh;d(E-l0FZ$?#JpTQlD62J;gs|L>EG3oUHyhMa zdK^pn-I*MnB0!j>R9u$#SFn_`ypdYUZ~TKjsipic7SPGQVs(hR)?7}+*4pAiz`tH1 zfV;`zT8r?n3|AEOPwHRdZwZ#Tf2DalmHUf-uqT!K=-Ta6vs#0UtJ%yVzjveeYt%_A zcWLzc5?9%a&aJO31SHYvJMx0exp34k5OqKPV>MH-UJ*fK`(B0{QBq#(2}C_0psHn% z2r9gHwo;xL6wKp@dCE zuGW^;SSubmF^BnByuuX0g!hhiE`2^+k2J6)L@Zvn3IOr7xZvG?%eHw6(fWKeZ83Gw7FQARY+1 zK}>7*8!uPzhQqUD_uwtKr-0ef-ew}A!GMgz4=(~ld^?VcvB!M8z?nz{72Z2rqsD$| z4jWW3mD|E@G@A;K4@pEFQc(H%O;}lMFNxa8VFiz0U&8o>tY}(7^{z5RmBzQ)h*&q{zVU0{o5P?022QKnd#U! literal 0 HcmV?d00001 diff --git a/modules/kull_m_string.c b/modules/kull_m_string.c index 47ac7a3..2837d5c 100644 --- a/modules/kull_m_string.c +++ b/modules/kull_m_string.c @@ -1,389 +1,410 @@ -/* Benjamin DELPY `gentilkiwi` - http://blog.gentilkiwi.com - benjamin@gentilkiwi.com - Licence : https://creativecommons.org/licenses/by/4.0/ -*/ -#include "kull_m_string.h" - -//BOOL kull_m_string_suspectUnicodeStringStructure(IN PUNICODE_STRING pUnicodeString) -//{ -// return ( -// pUnicodeString->Length && -// !((pUnicodeString->Length & 1) || (pUnicodeString->MaximumLength & 1)) && -// (pUnicodeString->Length < sizeof(wchar_t)*0xff) && -// (pUnicodeString->Length <= pUnicodeString->MaximumLength) && -// ((pUnicodeString->MaximumLength - pUnicodeString->Length) < 4*sizeof(wchar_t)) && -// pUnicodeString->Buffer -// ); -//} - -BOOL kull_m_string_suspectUnicodeString(IN PUNICODE_STRING pUnicodeString) -{ - int unicodeTestFlags = IS_TEXT_UNICODE_STATISTICS; - return ((pUnicodeString->Length == sizeof(wchar_t)) && IsCharAlphaNumeric(pUnicodeString->Buffer[0])) || IsTextUnicode(pUnicodeString->Buffer, pUnicodeString->Length, &unicodeTestFlags); -} - -void kull_m_string_printSuspectUnicodeString(PVOID data, DWORD size) -{ - UNICODE_STRING uString = {(USHORT) size, (USHORT) size, (LPWSTR) data}; - if(kull_m_string_suspectUnicodeString(&uString)) - kprintf(L"%wZ", &uString); - else - kull_m_string_wprintf_hex(uString.Buffer, uString.Length, 1); -} - -void kull_m_string_MakeRelativeOrAbsoluteString(PVOID BaseAddress, PLSA_UNICODE_STRING String, BOOL relative) -{ - if(String->Buffer) - String->Buffer = (PWSTR) ((ULONG_PTR)(String->Buffer) + ((relative ? -1 : 1) * (ULONG_PTR)(BaseAddress))); -} - -BOOL kull_m_string_copyUnicodeStringBuffer(PUNICODE_STRING pSource, PUNICODE_STRING pDestination) -{ - BOOL status = FALSE; - if(pSource && pDestination && pSource->MaximumLength && pSource->Buffer) - { - *pDestination = *pSource; - if(pDestination->Buffer = (PWSTR) LocalAlloc(LPTR, pSource->MaximumLength)) - { - status = TRUE; - RtlCopyMemory(pDestination->Buffer, pSource->Buffer, pSource->MaximumLength); - } - } - return status; -} - -void kull_m_string_freeUnicodeStringBuffer(PUNICODE_STRING pString) -{ - if(pString && pString->Buffer) - pString->Buffer = (PWSTR) LocalFree(pString->Buffer); -} - -wchar_t * kull_m_string_qad_ansi_to_unicode(const char * ansi) -{ - wchar_t * buffer = NULL; - if(ansi) - buffer = kull_m_string_qad_ansi_c_to_unicode(ansi, strlen(ansi)); - return buffer; -} - -wchar_t * kull_m_string_qad_ansi_c_to_unicode(const char * ansi, SIZE_T szStr) -{ - wchar_t * buffer = NULL; - SIZE_T i; - - if(ansi && szStr) - if(buffer = (wchar_t *) LocalAlloc(LPTR, (szStr + 1) * sizeof(wchar_t))) - for(i = 0; i < szStr; i++) - buffer[i] = ansi[i]; - return buffer; -} - -char * kull_m_string_unicode_to_ansi(const wchar_t * unicode) -{ - int needed; - char * buffer = NULL; - if(needed = WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, unicode, -1, NULL, 0, NULL, NULL)) - if(buffer = (char *) LocalAlloc(LPTR, needed)) - if(needed != WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, unicode, -1, buffer, needed, NULL, NULL)) - buffer = (char *) LocalFree(buffer); - return buffer; -} - -BOOL kull_m_string_stringToHex(IN LPCWCHAR string, IN LPBYTE hex, IN DWORD size) -{ - DWORD i, j; - BOOL result = (wcslen(string) == (size * 2)); - if(result) - { - for(i = 0; i < size; i++) - { - swscanf_s(&string[i*2], L"%02x", &j); - hex[i] = (BYTE) j; - } - } - return result; -} - -BOOL kull_m_string_stringToHexBuffer(IN LPCWCHAR string, IN LPBYTE *hex, IN DWORD *size) -{ - BOOL result = FALSE; - *size = (DWORD) wcslen(string); - if(!(*size % 2)) - { - *size >>= 1; - if(*hex = (PBYTE) LocalAlloc(LPTR, *size)) - { - result = kull_m_string_stringToHex(string, *hex, *size); - if(!result) - { - *hex = (PBYTE) LocalFree(*hex); - *size = 0; - } - } - } - return result; -} - -PCWCHAR WPRINTF_TYPES[] = -{ - L"%02x", // WPRINTF_HEX_SHORT - L"%02x ", // WPRINTF_HEX_SPACE - L"0x%02x, ", // WPRINTF_HEX_C - L"\\x%02x", // WPRINTF_HEX_PYTHON -}; - -void kull_m_string_wprintf_hex(LPCVOID lpData, DWORD cbData, DWORD flags) -{ - DWORD i, sep = flags >> 16; - PCWCHAR pType = WPRINTF_TYPES[flags & 0x0000000f]; - - if((flags & 0x0000000f) == 2) - kprintf(L"\nBYTE data[] = {\n\t"); - - for(i = 0; i < cbData; i++) - { - kprintf(pType, ((LPCBYTE) lpData)[i]); - if(sep && !((i+1) % sep)) - { - kprintf(L"\n"); - if((flags & 0x0000000f) == 2) - kprintf(L"\t"); - } - } - if((flags & 0x0000000f) == 2) - kprintf(L"\n};\n"); -} - -void kull_m_string_displayFileTime(IN PFILETIME pFileTime) -{ - SYSTEMTIME st; - wchar_t buffer[0xff]; - if(pFileTime) - { - if(FileTimeToSystemTime(pFileTime, &st )) - { - if(GetDateFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buffer, ARRAYSIZE(buffer))) - { - kprintf(L"%s ", buffer); - if(GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buffer, ARRAYSIZE(buffer))) - kprintf(L"%s", buffer); - } - } - } -} - -void kull_m_string_displayLocalFileTime(IN PFILETIME pFileTime) -{ - FILETIME ft; - if(pFileTime) - if(FileTimeToLocalFileTime(pFileTime, &ft)) - kull_m_string_displayFileTime(&ft); -} - -BOOL kull_m_string_FileTimeToString(IN PFILETIME pFileTime, OUT WCHAR string[14 + 1]) -{ - BOOL status = FALSE; - FILETIME ft; - SYSTEMTIME st; - if(pFileTime) - if(FileTimeToLocalFileTime(pFileTime, &ft)) - if(FileTimeToSystemTime(&ft, &st)) - if(GetDateFormat(LOCALE_USER_DEFAULT, 0, &st, L"yyyyMMdd", string, 8 + 1)) - status = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, L"HHmmss", string + 8, 6 + 1); - return status; -} - -void kull_m_string_displayGUID(IN LPCGUID pGuid) -{ - UNICODE_STRING uString; - if(NT_SUCCESS(RtlStringFromGUID(pGuid, &uString))) - { - kprintf(L"%wZ", &uString); - RtlFreeUnicodeString(&uString); - } -} - -void kull_m_string_displaySID(IN PSID pSid) -{ - LPWSTR stringSid; - if(ConvertSidToStringSid(pSid, &stringSid)) - { - kprintf(L"%s", stringSid); - LocalFree(stringSid); - } - else PRINT_ERROR_AUTO(L"ConvertSidToStringSid"); -} -#ifndef MIMIKATZ_W2000_SUPPORT -PWSTR kull_m_string_getRandomGUID() -{ - UNICODE_STRING uString; - GUID guid; - PWSTR buffer = NULL; - if(NT_SUCCESS(UuidCreate(&guid))) - { - if(NT_SUCCESS(RtlStringFromGUID(&guid, &uString))) - { - if(buffer = (PWSTR) LocalAlloc(LPTR, uString.MaximumLength)) - RtlCopyMemory(buffer, uString.Buffer, uString.MaximumLength); - RtlFreeUnicodeString(&uString); - } - } - return buffer; -} -#endif -void kull_m_string_ptr_replace(PVOID ptr, DWORD64 size) -{ - PVOID tempPtr = NULL; - if(size) - if(tempPtr = LocalAlloc(LPTR, (SIZE_T) size)) - RtlCopyMemory(tempPtr, *(PVOID *) ptr, (size_t) size); - *(PVOID *) ptr = tempPtr; -} - -BOOL kull_m_string_args_byName(const int argc, const wchar_t * argv[], const wchar_t * name, const wchar_t ** theArgs, const wchar_t * defaultValue) -{ - BOOL result = FALSE; - const wchar_t *pArgName, *pSeparator; - SIZE_T argLen, nameLen = wcslen(name); - int i; - for(i = 0; i < argc; i++) - { - if((wcslen(argv[i]) > 1) && ((argv[i][0] == L'/') || (argv[i][0] == L'-'))) - { - pArgName = argv[i] + 1; - if(!(pSeparator = wcschr(argv[i], L':'))) - pSeparator = wcschr(argv[i], L'='); - - argLen = (pSeparator) ? (pSeparator - pArgName) : wcslen(pArgName); - if((argLen == nameLen) && _wcsnicmp(name, pArgName, argLen) == 0) - { - if(theArgs) - { - if(pSeparator) - { - *theArgs = pSeparator + 1; - result = *theArgs[0] != L'\0'; - } - } - else - result = TRUE; - break; - } - } - } - if(!result && theArgs) - { - if(defaultValue) - { - *theArgs = defaultValue; - result = TRUE; - } - else *theArgs = NULL; - } - return result; -} - -BOOL kull_m_string_args_bool_byName(int argc, wchar_t * argv[], LPCWSTR name, PBOOL value) // TRUE when name exist (not value related) -{ - BOOL status = FALSE; - LPCWSTR szData; - if(status = kull_m_string_args_byName(argc, argv, name, &szData, NULL)) - { - if((_wcsicmp(szData, L"on") == 0) || (_wcsicmp(szData, L"true") == 0) || (_wcsicmp(szData, L"1") == 0)) - *value = TRUE; - else if((_wcsicmp(szData, L"off") == 0) || (_wcsicmp(szData, L"false") == 0) || (_wcsicmp(szData, L"0") == 0)) - *value = FALSE; - else PRINT_ERROR(L"%s argument need on/true/1 or off/false/0\n", name); - } - return status; -} - -BOOL kull_m_string_copy(LPWSTR *dst, LPCWSTR src) -{ - BOOL status = FALSE; - size_t size; - if(src && dst && (size = wcslen(src))) - { - size = (size + 1) * sizeof(wchar_t); - if(*dst = (LPWSTR) LocalAlloc(LPTR, size)) - { - RtlCopyMemory(*dst, src, size); - status = TRUE; - } - } - return status; -} - -BOOL kull_m_string_copyA(LPSTR *dst, LPCSTR src) -{ - BOOL status = FALSE; - size_t size; - if(src && dst && (size = strlen(src))) - { - size = (size + 1) * sizeof(char); - if(*dst = (LPSTR) LocalAlloc(LPTR, size)) - { - RtlCopyMemory(*dst, src, size); - status = TRUE; - } - } - return status; -} - -BOOL kull_m_string_quickxml_simplefind(LPCWSTR xml, LPCWSTR node, LPWSTR *dst) -{ - BOOL status = FALSE; - DWORD lenNode, lenBegin, lenEnd; - LPWSTR begin, end, curBeg, curEnd; - lenNode = (DWORD) wcslen(node) * sizeof(wchar_t); - lenBegin = lenNode + 3 * sizeof(wchar_t); - lenEnd = lenNode + 4 * sizeof(wchar_t); - if(begin = (LPWSTR) LocalAlloc(LPTR, lenBegin)) - { - if(end = (LPWSTR) LocalAlloc(LPTR, lenEnd)) - { - begin[0] = end[0] = L'<'; - end[1] = L'/'; - begin[lenBegin / sizeof(wchar_t) - 2] = end[lenEnd / sizeof(wchar_t) - 2] = L'>'; - RtlCopyMemory(begin + 1, node, lenNode); - RtlCopyMemory(end + 2, node, lenNode); - if(curBeg = wcsstr(xml, begin)) - { - curBeg += lenBegin / sizeof(wchar_t) - 1; - if(curEnd = wcsstr(curBeg, end)) - { - if(status = (curBeg <= curEnd)) - { - lenNode = (DWORD) (curEnd - curBeg) * sizeof(wchar_t); - if((*dst) = (LPWSTR) LocalAlloc(LPTR, lenNode + sizeof(wchar_t))) - { - RtlCopyMemory(*dst, curBeg, lenNode); - } - } - } - } - LocalFree(end); - } - LocalFree(begin); - } - return status; -} -#ifndef MIMIKATZ_W2000_SUPPORT -BOOL kull_m_string_quick_base64_to_Binary(PCWSTR base64, PBYTE *data, DWORD *szData) -{ - BOOL status = FALSE; - *data = NULL; - *szData = 0; - if(CryptStringToBinary(base64, 0, CRYPT_STRING_BASE64, NULL, szData, NULL, NULL)) - { - if(*data = (PBYTE) LocalAlloc(LPTR, *szData)) - { - status = CryptStringToBinary(base64, 0, CRYPT_STRING_BASE64, *data, szData, NULL, NULL); - if(!status) - *data = (PBYTE) LocalFree(*data); - } - } - return status; -} -#endif \ No newline at end of file +/* Benjamin DELPY `gentilkiwi` + http://blog.gentilkiwi.com + benjamin@gentilkiwi.com + Licence : https://creativecommons.org/licenses/by/4.0/ +*/ +#include "kull_m_string.h" + +//BOOL kull_m_string_suspectUnicodeStringStructure(IN PUNICODE_STRING pUnicodeString) +//{ +// return ( +// pUnicodeString->Length && +// !((pUnicodeString->Length & 1) || (pUnicodeString->MaximumLength & 1)) && +// (pUnicodeString->Length < sizeof(wchar_t)*0xff) && +// (pUnicodeString->Length <= pUnicodeString->MaximumLength) && +// ((pUnicodeString->MaximumLength - pUnicodeString->Length) < 4*sizeof(wchar_t)) && +// pUnicodeString->Buffer +// ); +//} + +BOOL kull_m_string_suspectUnicodeString(IN PUNICODE_STRING pUnicodeString) +{ + int unicodeTestFlags = IS_TEXT_UNICODE_STATISTICS; + return ((pUnicodeString->Length == sizeof(wchar_t)) && IsCharAlphaNumeric(pUnicodeString->Buffer[0])) || IsTextUnicode(pUnicodeString->Buffer, pUnicodeString->Length, &unicodeTestFlags); +} + +void kull_m_string_printSuspectUnicodeString(PVOID data, DWORD size) +{ + UNICODE_STRING uString = {(USHORT) size, (USHORT) size, (LPWSTR) data}; + if(kull_m_string_suspectUnicodeString(&uString)) + kprintf(L"%wZ", &uString); + else + kull_m_string_wprintf_hex(uString.Buffer, uString.Length, 1); +} + +void kull_m_string_MakeRelativeOrAbsoluteString(PVOID BaseAddress, PLSA_UNICODE_STRING String, BOOL relative) +{ + if(String->Buffer) + String->Buffer = (PWSTR) ((ULONG_PTR)(String->Buffer) + ((relative ? -1 : 1) * (ULONG_PTR)(BaseAddress))); +} + +BOOL kull_m_string_copyUnicodeStringBuffer(PUNICODE_STRING pSource, PUNICODE_STRING pDestination) +{ + BOOL status = FALSE; + if(pSource && pDestination && pSource->MaximumLength && pSource->Buffer) + { + *pDestination = *pSource; + if(pDestination->Buffer = (PWSTR) LocalAlloc(LPTR, pSource->MaximumLength)) + { + status = TRUE; + RtlCopyMemory(pDestination->Buffer, pSource->Buffer, pSource->MaximumLength); + } + } + return status; +} + +void kull_m_string_freeUnicodeStringBuffer(PUNICODE_STRING pString) +{ + if(pString && pString->Buffer) + pString->Buffer = (PWSTR) LocalFree(pString->Buffer); +} + +wchar_t * kull_m_string_qad_ansi_to_unicode(const char * ansi) +{ + wchar_t * buffer = NULL; + if(ansi) + buffer = kull_m_string_qad_ansi_c_to_unicode(ansi, strlen(ansi)); + return buffer; +} + +wchar_t * kull_m_string_qad_ansi_c_to_unicode(const char * ansi, SIZE_T szStr) +{ + wchar_t * buffer = NULL; + SIZE_T i; + + if(ansi && szStr) + if(buffer = (wchar_t *) LocalAlloc(LPTR, (szStr + 1) * sizeof(wchar_t))) + for(i = 0; i < szStr; i++) + buffer[i] = ansi[i]; + return buffer; +} + +char * kull_m_string_unicode_to_ansi(const wchar_t * unicode) +{ + int needed; + char * buffer = NULL; + if(needed = WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, unicode, -1, NULL, 0, NULL, NULL)) + if(buffer = (char *) LocalAlloc(LPTR, needed)) + if(needed != WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, unicode, -1, buffer, needed, NULL, NULL)) + buffer = (char *) LocalFree(buffer); + return buffer; +} + +BOOL kull_m_string_stringToHex(IN LPCWCHAR string, IN LPBYTE hex, IN DWORD size) +{ + DWORD i, j; + BOOL result = (wcslen(string) == (size * 2)); + if(result) + { + for(i = 0; i < size; i++) + { + swscanf_s(&string[i*2], L"%02x", &j); + hex[i] = (BYTE) j; + } + } + return result; +} + +BOOL kull_m_string_stringToHexBuffer(IN LPCWCHAR string, IN LPBYTE *hex, IN DWORD *size) +{ + BOOL result = FALSE; + *size = (DWORD) wcslen(string); + if(!(*size % 2)) + { + *size >>= 1; + if(*hex = (PBYTE) LocalAlloc(LPTR, *size)) + { + result = kull_m_string_stringToHex(string, *hex, *size); + if(!result) + { + *hex = (PBYTE) LocalFree(*hex); + *size = 0; + } + } + } + return result; +} + +PCWCHAR WPRINTF_TYPES[] = +{ + L"%02x", // WPRINTF_HEX_SHORT + L"%02x ", // WPRINTF_HEX_SPACE + L"0x%02x, ", // WPRINTF_HEX_C + L"\\x%02x", // WPRINTF_HEX_PYTHON +}; + +void kull_m_string_wprintf_hex(LPCVOID lpData, DWORD cbData, DWORD flags) +{ + DWORD i, sep = flags >> 16; + PCWCHAR pType = WPRINTF_TYPES[flags & 0x0000000f]; + + if((flags & 0x0000000f) == 2) + kprintf(L"\nBYTE data[] = {\n\t"); + + for(i = 0; i < cbData; i++) + { + kprintf(pType, ((LPCBYTE) lpData)[i]); + if(sep && !((i+1) % sep)) + { + kprintf(L"\n"); + if((flags & 0x0000000f) == 2) + kprintf(L"\t"); + } + } + if((flags & 0x0000000f) == 2) + kprintf(L"\n};\n"); +} + +void kull_m_string_displayFileTime(IN PFILETIME pFileTime) +{ + SYSTEMTIME st; + wchar_t buffer[0xff]; + if(pFileTime) + { + if(FileTimeToSystemTime(pFileTime, &st )) + { + if(GetDateFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buffer, ARRAYSIZE(buffer))) + { + kprintf(L"%s ", buffer); + if(GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buffer, ARRAYSIZE(buffer))) + kprintf(L"%s", buffer); + } + } + } +} + +void kull_m_string_displayLocalFileTime(IN PFILETIME pFileTime) +{ + FILETIME ft; + if(pFileTime) + if(FileTimeToLocalFileTime(pFileTime, &ft)) + kull_m_string_displayFileTime(&ft); +} + +BOOL kull_m_string_FileTimeToString(IN PFILETIME pFileTime, OUT WCHAR string[14 + 1]) +{ + BOOL status = FALSE; + FILETIME ft; + SYSTEMTIME st; + if(pFileTime) + if(FileTimeToLocalFileTime(pFileTime, &ft)) + if(FileTimeToSystemTime(&ft, &st)) + if(GetDateFormat(LOCALE_USER_DEFAULT, 0, &st, L"yyyyMMdd", string, 8 + 1)) + status = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, L"HHmmss", string + 8, 6 + 1); + return status; +} + +void kull_m_string_displayGUID(IN LPCGUID pGuid) +{ + UNICODE_STRING uString; + if(NT_SUCCESS(RtlStringFromGUID(pGuid, &uString))) + { + kprintf(L"%wZ", &uString); + RtlFreeUnicodeString(&uString); + } +} + +void kull_m_string_displaySID(IN PSID pSid) +{ + LPWSTR stringSid; + if(ConvertSidToStringSid(pSid, &stringSid)) + { + kprintf(L"%s", stringSid); + LocalFree(stringSid); + } + else PRINT_ERROR_AUTO(L"ConvertSidToStringSid"); +} +#ifndef MIMIKATZ_W2000_SUPPORT +PWSTR kull_m_string_getRandomGUID() +{ + UNICODE_STRING uString; + GUID guid; + PWSTR buffer = NULL; + if(NT_SUCCESS(UuidCreate(&guid))) + { + if(NT_SUCCESS(RtlStringFromGUID(&guid, &uString))) + { + if(buffer = (PWSTR) LocalAlloc(LPTR, uString.MaximumLength)) + RtlCopyMemory(buffer, uString.Buffer, uString.MaximumLength); + RtlFreeUnicodeString(&uString); + } + } + return buffer; +} +#endif +void kull_m_string_ptr_replace(PVOID ptr, DWORD64 size) +{ + PVOID tempPtr = NULL; + if(size) + if(tempPtr = LocalAlloc(LPTR, (SIZE_T) size)) + RtlCopyMemory(tempPtr, *(PVOID *) ptr, (size_t) size); + *(PVOID *) ptr = tempPtr; +} + +BOOL kull_m_string_args_byName(const int argc, const wchar_t * argv[], const wchar_t * name, const wchar_t ** theArgs, const wchar_t * defaultValue) +{ + BOOL result = FALSE; + const wchar_t *pArgName, *pSeparator; + SIZE_T argLen, nameLen = wcslen(name); + int i; + for(i = 0; i < argc; i++) + { + if((wcslen(argv[i]) > 1) && ((argv[i][0] == L'/') || (argv[i][0] == L'-'))) + { + pArgName = argv[i] + 1; + if(!(pSeparator = wcschr(argv[i], L':'))) + pSeparator = wcschr(argv[i], L'='); + + argLen = (pSeparator) ? (pSeparator - pArgName) : wcslen(pArgName); + if((argLen == nameLen) && _wcsnicmp(name, pArgName, argLen) == 0) + { + if(theArgs) + { + if(pSeparator) + { + *theArgs = pSeparator + 1; + result = *theArgs[0] != L'\0'; + } + } + else + result = TRUE; + break; + } + } + } + if(!result && theArgs) + { + if(defaultValue) + { + *theArgs = defaultValue; + result = TRUE; + } + else *theArgs = NULL; + } + return result; +} + +BOOL kull_m_string_args_bool_byName(int argc, wchar_t * argv[], LPCWSTR name, PBOOL value) // TRUE when name exist (not value related) +{ + BOOL status = FALSE; + LPCWSTR szData; + if(status = kull_m_string_args_byName(argc, argv, name, &szData, NULL)) + { + if((_wcsicmp(szData, L"on") == 0) || (_wcsicmp(szData, L"true") == 0) || (_wcsicmp(szData, L"1") == 0)) + *value = TRUE; + else if((_wcsicmp(szData, L"off") == 0) || (_wcsicmp(szData, L"false") == 0) || (_wcsicmp(szData, L"0") == 0)) + *value = FALSE; + else PRINT_ERROR(L"%s argument need on/true/1 or off/false/0\n", name); + } + return status; +} + +BOOL kull_m_string_copy(LPWSTR *dst, LPCWSTR src) +{ + BOOL status = FALSE; + size_t size; + if(src && dst && (size = wcslen(src))) + { + size = (size + 1) * sizeof(wchar_t); + if(*dst = (LPWSTR) LocalAlloc(LPTR, size)) + { + RtlCopyMemory(*dst, src, size); + status = TRUE; + } + } + return status; +} + +BOOL kull_m_string_copyA(LPSTR *dst, LPCSTR src) +{ + BOOL status = FALSE; + size_t size; + if(src && dst && (size = strlen(src))) + { + size = (size + 1) * sizeof(char); + if(*dst = (LPSTR) LocalAlloc(LPTR, size)) + { + RtlCopyMemory(*dst, src, size); + status = TRUE; + } + } + return status; +} + +BOOL kull_m_string_quickxml_simplefind(LPCWSTR xml, LPCWSTR node, LPWSTR *dst) +{ + BOOL status = FALSE; + DWORD lenNode, lenBegin, lenEnd; + LPWSTR begin, end, curBeg, curEnd; + lenNode = (DWORD) wcslen(node) * sizeof(wchar_t); + lenBegin = lenNode + 3 * sizeof(wchar_t); + lenEnd = lenNode + 4 * sizeof(wchar_t); + if(begin = (LPWSTR) LocalAlloc(LPTR, lenBegin)) + { + if(end = (LPWSTR) LocalAlloc(LPTR, lenEnd)) + { + begin[0] = end[0] = L'<'; + end[1] = L'/'; + begin[lenBegin / sizeof(wchar_t) - 2] = end[lenEnd / sizeof(wchar_t) - 2] = L'>'; + RtlCopyMemory(begin + 1, node, lenNode); + RtlCopyMemory(end + 2, node, lenNode); + if(curBeg = wcsstr(xml, begin)) + { + curBeg += lenBegin / sizeof(wchar_t) - 1; + if(curEnd = wcsstr(curBeg, end)) + { + if(status = (curBeg <= curEnd)) + { + lenNode = (DWORD) (curEnd - curBeg) * sizeof(wchar_t); + if((*dst) = (LPWSTR) LocalAlloc(LPTR, lenNode + sizeof(wchar_t))) + { + RtlCopyMemory(*dst, curBeg, lenNode); + } + } + } + } + LocalFree(end); + } + LocalFree(begin); + } + return status; +} +#ifndef MIMIKATZ_W2000_SUPPORT +BOOL kull_m_string_quick_base64_to_Binary(PCWSTR base64, PBYTE *data, DWORD *szData) +{ + BOOL status = FALSE; + *data = NULL; + *szData = 0; + if(CryptStringToBinary(base64, 0, CRYPT_STRING_BASE64, NULL, szData, NULL, NULL)) + { + if(*data = (PBYTE) LocalAlloc(LPTR, *szData)) + { + status = CryptStringToBinary(base64, 0, CRYPT_STRING_BASE64, *data, szData, NULL, NULL); + if(!status) + *data = (PBYTE) LocalFree(*data); + } + } + return status; +} +#endif + +BOOL kull_m_string_sprintf(PWSTR *outBuffer, PCWSTR format, ...) +{ + BOOL status = FALSE; + int varBuf; + va_list args; + va_start(args, format); + varBuf = _vscwprintf(format, args); + if(varBuf > 0) + { + varBuf++; + if(*outBuffer = (PWSTR) LocalAlloc(LPTR, varBuf * sizeof(wchar_t))) + { + varBuf = vswprintf_s(*outBuffer, varBuf, format, args); + if(varBuf > 0) + status = TRUE; + else *outBuffer = (PWSTR) LocalFree(outBuffer); + } + } + return status; +} \ No newline at end of file