mirror of https://github.com/FreeRDP/FreeRDP
winpr/tools/hash: added NTLM hashing tool
This commit is contained in:
parent
b846f72de3
commit
e8f2f7b30e
|
@ -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})
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
@ -27,3 +27,5 @@ add_subdirectory(rpc)
|
|||
add_subdirectory(sspi)
|
||||
add_subdirectory(registry)
|
||||
|
||||
add_subdirectory(tools)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
@ -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)
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
Binary file not shown.
|
@ -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})
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue