Last active
March 4, 2020 18:28
-
-
Save GeneralZero/18d3063cc0a331b969b1bda9ad1134fd to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import hashlib, sys, os, hmac | |
from Crypto.Cipher import DES | |
def expand_DES_key(key): | |
# Expand the key from a 7-byte password key into a 8-byte DES key | |
if not isinstance(key, bytes): | |
key = bytes(key, encoding='utf8') | |
key = bytearray(key[:7]).ljust(7, b'\x00') | |
s = bytearray() | |
s.append(((key[0] >> 1) & 0x7f) << 1) | |
s.append(((key[0] & 0x01) << 6 | ((key[1] >> 2) & 0x3f)) << 1) | |
s.append(((key[1] & 0x03) << 5 | ((key[2] >> 3) & 0x1f)) << 1) | |
s.append(((key[2] & 0x07) << 4 | ((key[3] >> 4) & 0x0f)) << 1) | |
s.append(((key[3] & 0x0f) << 3 | ((key[4] >> 5) & 0x07)) << 1) | |
s.append(((key[4] & 0x1f) << 2 | ((key[5] >> 6) & 0x03)) << 1) | |
s.append(((key[5] & 0x3f) << 1 | ((key[6] >> 7) & 0x01)) << 1) | |
s.append((key[6] & 0x7f) << 1) | |
return bytes(s) | |
def DES_block(key, msg): | |
key = expand_DES_key(key) | |
cipher = DES.new(key,DES.MODE_ECB) | |
return cipher.encrypt(msg) | |
def NT(password): | |
return hashlib.new("md4", password.encode('utf_16le')).digest() | |
def NTLMv2(input_hash, user_name, domain_name): | |
return hmac.new(input_hash, user_name + domain_name, "md5").digest() | |
def LM(password): | |
password = password.upper() | |
lmhash = DES_block(password[:7], b"KGS!@#$%") | |
lmhash += DES_block(password[7:14], b"KGS!@#$%") | |
return lmhash | |
if __name__ == '__main__': | |
#server_challenge = os.urandom(8) | |
server_challenge = b"\x01\x23\x45\x67\x89\xab\xcd\xef" | |
client_challenge = b"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" | |
domain_name = "Domain" | |
user_name = "User" | |
password = "Password" | |
server_name = b"Server" | |
#server_name = b'\x02\x00\x0c\x00\x44\x00\x6f\x00\x6d\x00\x61\x00\x69\x00\x6e\x00\x01\x00\x0c\x00\x53\x00\x65\x00\x72\x00\x76\x00\x65\x00\x72\x00\x00\x00\x00\x00' | |
nt_hash = NT(password) | |
lm_hash = LM(password) | |
### Local Hashes | |
print("Password: {}".format(password)) | |
print("Server Nonce: {}".format(server_challenge.hex())) | |
print("NT Hash: {}".format(nt_hash.hex())) | |
print("LM Hash: {}\n".format(lm_hash.hex())) | |
### Version 1 Net Hashes | |
nt_response = DES_block(nt_hash[:7], server_challenge) + DES_block(nt_hash[7:14], server_challenge) + DES_block(nt_hash[14:], server_challenge) | |
lm_response = DES_block(lm_hash[:7], server_challenge) + DES_block(lm_hash[7:14], server_challenge) + DES_block(lm_hash[14:], server_challenge) | |
print("Net-NTv1 Response: {}".format(nt_response.hex())) | |
print("Net-LMv1 Response: {}".format(lm_response.hex())) | |
shared_key = hashlib.new("md4", nt_hash).digest() | |
print("Net-NTLMv1 Shared Key: {}\n".format(shared_key.hex())) | |
### Version 2 Net Hashes | |
nt_response_key_v2 = NTLMv2(nt_hash, user_name.upper().encode('utf_16le'), domain_name.encode('utf_16le')) | |
lm_response_key_v2 = NTLMv2(lm_hash, user_name.upper().encode('utf_16le'), domain_name.encode('utf_16le')) | |
# Response Server Version + \x00\x00\x00\x00\x00\x00 + Time Stamp + Client Challenge + \x00\x00\x00\x00 + server_name + \x00\x00\x00\x00 | |
temp = b'\x01\x01' + b'\x00' * 6 + b'\x00' * 8 + client_challenge + b'\x00' * 4 + server_name + b'\x00' * 4 | |
temp_response = NTLMv2(nt_response_key_v2, server_challenge, temp) | |
nt_response_v2 = temp_response + temp | |
lm_response_v2 = NTLMv2(nt_response_key_v2, server_challenge, client_challenge) + client_challenge | |
shared_key_v2 = NTLMv2(nt_response_key_v2, temp_response, b"") + b"" | |
print("Net-NTv2 Response Key: {}".format(nt_response_key_v2.hex())) | |
print("Net-LMv2 Response Key: {}".format(lm_response_key_v2.hex())) | |
print("Net-NTv2 Response: {}".format(nt_response_v2.hex())) | |
print("Net-LMv2 Response: {}".format(lm_response_v2.hex())) | |
print("Net-NTLMv2 Shared Key: {}".format(shared_key_v2.hex())) | |
#Verify asserts from https://github.com/SecureAuthCorp/impacket/blob/429f97a894d35473d478cbacff5919739ae409b4/tests/SMB_RPC/test_ntlm.py | |
assert(lm_hash == bytearray(b'\xe5,\xacgA\x9a\x9a"J;\x10\x8f?\xa6\xcbm')) | |
assert(nt_hash == bytearray(b'\xa4\xf4\x9c\x40\x65\x10\xbd\xca\xb6\x82\x4e\xe7\xc3\x0f\xd8\x52')) | |
assert(nt_response == bytearray(b'\x67\xC4\x30\x11\xF3\x02\x98\xA2\xAD\x35\xEC\xE6\x4F\x16\x33\x1C\x44\xBD\xBE\xD9\x27\x84\x1F\x94')) | |
assert(lm_response == bytearray(b'\x98\xDE\xF7\xB8\x7F\x88\xAA\x5D\xAF\xE2\xDF\x77\x96\x88\xA1\x72\xde\xf1\x1c\x7d\x5c\xcd\xef\x13')) | |
assert(shared_key == bytearray(b'\xD8\x72\x62\xB0\xCD\xE4\xB1\xCB\x74\x99\xBE\xCC\xCD\xF1\x07\x84')) | |
assert(nt_response_key_v2==bytearray(b'\x0c\x86\x8a\x40\x3b\xfd\x7a\x93\xa3\x00\x1e\xf2\x2e\xf0\x2e\x3f')) | |
assert(lm_response_key_v2==bytearray(b'\xc2\xd6\x9a\xca\xe7\x12\x59\xa9\xc7\xcd\x95\x81\x63\xa9\x8b\x1c')) | |
assert(nt_response_v2[:16]==bytearray(b'\x35\x6c\x72\x25\x90\x7b\x92\x6d\x1b\xac\xf4\x0a\x41\x77\xe0\x58')) | |
assert(lm_response_v2==bytearray(b'\x86\xc3\x50\x97\xac\x9c\xec\x10\x25\x54\x76\x4a\x57\xcc\xcc\x19\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa')) | |
assert(shared_key_v2==bytearray(b'\x8e\x63\xba\x6e\x5f\x82\x76\x30\xca\xaf\x3e\xc7\xa8\x9b\xd8\xa8')) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment