winpr/tools/hash: added NTLM hashing tool

This commit is contained in:
Marc-André Moreau 2012-06-02 18:21:04 -04:00
parent b846f72de3
commit e8f2f7b30e
10 changed files with 358 additions and 38 deletions

View File

@ -24,3 +24,4 @@ target_link_libraries(freerdp-test freerdp-core)
target_link_libraries(freerdp-test freerdp-gdi)
target_link_libraries(freerdp-test freerdp-utils)
target_link_libraries(freerdp-test freerdp-channels ${CMAKE_DL_LIBS})

46
include/winpr/ntlm.h Normal file
View File

@ -0,0 +1,46 @@
/**
* WinPR: Windows Portable Runtime
* NTLM Utils
*
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef WINPR_UTILS_NTLM_H
#define WINPR_UTILS_NTLM_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winpr/winpr.h>
#include <winpr/wtypes.h>
WINPR_API BYTE* NTOWFv1W(LPWSTR Password, UINT32 PasswordLength, BYTE* NtHash);
WINPR_API BYTE* NTOWFv1A(LPSTR Password, UINT32 PasswordLength, BYTE* NtHash);
WINPR_API BYTE* NTOWFv2W(LPWSTR Password, UINT32 PasswordLength, LPWSTR User,
UINT32 UserLength, LPWSTR Domain, UINT32 DomainLength, BYTE* NtHash);
WINPR_API BYTE* NTOWFv2A(LPSTR Password, UINT32 PasswordLength, LPSTR User,
UINT32 UserLength, LPSTR Domain, UINT32 DomainLength, BYTE* NtHash);
#ifdef UNICODE
#define NTOWFv1 NTOWFv1W
#define NTOWFv2 NTOWFv2W
#else
#define NTOWFv1 NTOWFv1A
#define NTOWFv2 NTOWFv2W
#endif
#endif /* WINPR_UTILS_NTLM_H */

View File

@ -27,3 +27,5 @@ add_subdirectory(rpc)
add_subdirectory(sspi)
add_subdirectory(registry)
add_subdirectory(tools)

View File

@ -21,6 +21,7 @@
#include "../sspi.h"
#include <winpr/crt.h>
#include <winpr/ntlm.h>
#include <winpr/print.h>
#include "ntlm_compute.h"
@ -159,21 +160,6 @@ void ntlm_generate_timestamp(NTLM_CONTEXT* context)
}
}
void ntlm_compute_ntlm_hash(UINT16* password, UINT32 length, char* hash)
{
/* NTLMv1("password") = 8846F7EAEE8FB117AD06BDD830B7586C */
MD4_CTX md4_ctx;
/* Password needs to be in unicode */
/* Apply the MD4 digest algorithm on the password in unicode, the result is the NTLM hash */
MD4_Init(&md4_ctx);
MD4_Update(&md4_ctx, password, length);
MD4_Final((void*) hash, &md4_ctx);
}
static void ascii_hex_string_to_binary(char* str, unsigned char* hex)
{
int i;
@ -278,36 +264,16 @@ void ntlm_fetch_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash)
void ntlm_compute_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash)
{
char* p;
SecBuffer buffer;
char ntlm_hash[16];
if (context->identity.PasswordLength > 0)
{
/* First, compute the NTLMv1 hash of the password */
ntlm_compute_ntlm_hash(context->identity.Password, context->identity.PasswordLength, ntlm_hash);
}
sspi_SecBufferAlloc(&buffer, context->identity.UserLength + context->identity.DomainLength);
p = (char*) buffer.pvBuffer;
/* Concatenate(Uppercase(username),domain)*/
CopyMemory(p, context->identity.User, context->identity.UserLength);
CharUpperBuffW((LPWSTR) p, context->identity.UserLength / 2);
CopyMemory(&p[context->identity.UserLength], context->identity.Domain, context->identity.DomainLength);
if (context->identity.PasswordLength > 0)
{
/* Compute the HMAC-MD5 hash of the above value using the NTLMv1 hash as the key, the result is the NTLMv2 hash */
HMAC(EVP_md5(), (void*) ntlm_hash, 16, buffer.pvBuffer, buffer.cbBuffer, (void*) hash, NULL);
NTOWFv2W((LPWSTR) context->identity.Password, context->identity.PasswordLength,
(LPWSTR) context->identity.User, context->identity.UserLength,
(LPWSTR) context->identity.Domain, context->identity.DomainLength, (BYTE*) hash);
}
else
{
ntlm_fetch_ntlm_v2_hash(context, hash);
}
sspi_SecBufferFree(&buffer);
}
void ntlm_compute_lm_v2_response(NTLM_CONTEXT* context)

View File

@ -0,0 +1,21 @@
# WinPR: Windows Portable Runtime
# winpr cmake build script
#
# Copyright 2011 O.S. Systems Software Ltda.
# Copyright 2011 Otavio Salvador <otavio@ossystems.com.br>
# Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
add_subdirectory(hash)

View File

@ -0,0 +1,24 @@
# WinPR: Windows Portable Runtime
# winpr-hash cmake build script
#
# Copyright 2011 O.S. Systems Software Ltda.
# Copyright 2011 Otavio Salvador <otavio@ossystems.com.br>
# Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
add_executable(winpr-hash
hash.c)
target_link_libraries(winpr-hash winpr-utils)

125
winpr/tools/hash/hash.c Normal file
View File

@ -0,0 +1,125 @@
/**
* WinPR: Windows Portable Runtime
* NTLM Hashing Tool
*
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <winpr/ntlm.h>
/**
* Define NTOWFv1(Password, User, Domain) as
* MD4(UNICODE(Password))
* EndDefine
*
* Define LMOWFv1(Password, User, Domain) as
* ConcatenationOf(DES(UpperCase(Password)[0..6], "KGS!@#$%"),
* DES(UpperCase(Password)[7..13], "KGS!@#$%"))
* EndDefine
*
* Define NTOWFv2(Password, User, Domain) as
* HMAC_MD5(MD4(UNICODE(Password)),
* UNICODE(ConcatenationOf(UpperCase(User), Domain)))
* EndDefine
*
* Define LMOWFv2(Password, User, Domain) as
* NTOWFv2(Password, User, Domain)
* EndDefine
*
*/
int main(int argc, char* argv[])
{
int index = 1;
BYTE NtHash[16];
char* User = NULL;
UINT32 UserLength;
char* Domain = NULL;
UINT32 DomainLength;
char* Password = NULL;
UINT32 PasswordLength;
while (index < argc)
{
if (strcmp("-d", argv[index]) == 0)
{
index++;
if (index == argc)
{
printf("missing domain\n");
exit(1);
}
Domain = argv[index];
}
else if (strcmp("-u", argv[index]) == 0)
{
index++;
if (index == argc)
{
printf("missing username\n");
exit(1);
}
User = argv[index];
}
else if (strcmp("-p", argv[index]) == 0)
{
index++;
if (index == argc)
{
printf("missing password\n");
exit(1);
}
Password = argv[index];
}
else if (strcmp("-h", argv[index]) == 0)
{
printf("winpr-hash: NTLM hashing tool\n");
printf("Usage: winpr-hash -u <username> -p <password> [-d <domain>]\n");
exit(1);
}
index++;
}
if ((!User) || (!Password))
{
printf("missing username or password\n");
exit(1);
}
UserLength = strlen(User);
PasswordLength = strlen(Password);
DomainLength = (Domain) ? strlen(Domain) : 0;
NTOWFv2A(Password, PasswordLength, User, UserLength, Domain, DomainLength, NtHash);
for (index = 0; index < 16; index++)
printf("%02x", NtHash[index]);
printf("\n");
return 0;
}

BIN
winpr/tools/hash/winpr-hash Executable file

Binary file not shown.

View File

@ -18,6 +18,7 @@
# limitations under the License.
set(WINPR_UTILS_SRCS
ntlm.c
print.c
stream.c)
@ -29,5 +30,8 @@ if (NOT WIN32)
target_link_libraries(winpr-utils winpr-crt)
endif()
target_link_libraries(winpr-utils ${ZLIB_LIBRARIES})
target_link_libraries(winpr-utils ${OPENSSL_LIBRARIES})
install(TARGETS winpr-utils DESTINATION ${CMAKE_INSTALL_LIBDIR})

131
winpr/utils/ntlm.c Normal file
View File

@ -0,0 +1,131 @@
/**
* WinPR: Windows Portable Runtime
* NTLM Utils
*
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <winpr/ntlm.h>
#include <winpr/crt.h>
#include <winpr/windows.h>
#include <time.h>
#include <openssl/des.h>
#include <openssl/md4.h>
#include <openssl/md5.h>
#include <openssl/rc4.h>
#include <openssl/hmac.h>
#include <openssl/rand.h>
#include <openssl/engine.h>
/**
* Define NTOWFv1(Password, User, Domain) as
* MD4(UNICODE(Password))
* EndDefine
*/
BYTE* NTOWFv1W(LPWSTR Password, UINT32 PasswordLength, BYTE* NtHash)
{
MD4_CTX md4_ctx;
if (!Password)
return NULL;
if (!NtHash)
NtHash = malloc(16);
MD4_Init(&md4_ctx);
MD4_Update(&md4_ctx, Password, PasswordLength);
MD4_Final((void*) NtHash, &md4_ctx);
return NtHash;
}
BYTE* NTOWFv1A(LPSTR Password, UINT32 PasswordLength, BYTE* NtHash)
{
LPWSTR PasswordW = NULL;
PasswordW = (LPWSTR) malloc(PasswordLength * 2);
MultiByteToWideChar(CP_ACP, 0, Password, PasswordLength, PasswordW, PasswordLength);
NtHash = NTOWFv1W(PasswordW, PasswordLength, NtHash);
free(PasswordW);
return NtHash;
}
/**
* Define NTOWFv2(Password, User, Domain) as
* HMAC_MD5(MD4(UNICODE(Password)),
* UNICODE(ConcatenationOf(UpperCase(User), Domain)))
* EndDefine
*/
BYTE* NTOWFv2W(LPWSTR Password, UINT32 PasswordLength, LPWSTR User,
UINT32 UserLength, LPWSTR Domain, UINT32 DomainLength, BYTE* NtHash)
{
BYTE* buffer;
BYTE NtHashV1[16];
if ((!User) || (!Password))
return NULL;
if (!NtHash)
NtHash = (BYTE*) malloc(16);
NTOWFv1W(Password, PasswordLength, NtHashV1);
buffer = (BYTE*) malloc(UserLength + DomainLength);
/* Concatenate(UpperCase(User), Domain) */
CopyMemory(buffer, User, UserLength);
CharUpperBuffW((LPWSTR) buffer, UserLength / 2);
CopyMemory(&buffer[UserLength], Domain, DomainLength);
/* Compute the HMAC-MD5 hash of the above value using the NTLMv1 hash as the key, the result is the NTLMv2 hash */
HMAC(EVP_md5(), (void*) NtHashV1, 16, buffer, UserLength + DomainLength, (void*) NtHash, NULL);
free(buffer);
return NtHash;
}
BYTE* NTOWFv2A(LPSTR Password, UINT32 PasswordLength, LPSTR User,
UINT32 UserLength, LPSTR Domain, UINT32 DomainLength, BYTE* NtHash)
{
LPWSTR UserW = NULL;
LPWSTR DomainW = NULL;
LPWSTR PasswordW = NULL;
UserW = (LPWSTR) malloc(UserLength * 2);
DomainW = (LPWSTR) malloc(DomainLength * 2);
PasswordW = (LPWSTR) malloc(PasswordLength * 2);
MultiByteToWideChar(CP_ACP, 0, User, UserLength, UserW, UserLength);
MultiByteToWideChar(CP_ACP, 0, Domain, DomainLength, DomainW, DomainLength);
MultiByteToWideChar(CP_ACP, 0, Password, PasswordLength, PasswordW, PasswordLength);
NtHash = NTOWFv2W(PasswordW, PasswordLength * 2, UserW, UserLength * 2, DomainW, DomainLength * 2, NtHash);
free(UserW);
free(DomainW);
free(PasswordW);
return NtHash;
}