Skip to content

Instantly share code, notes, and snippets.

@GeneralZero
Last active March 4, 2020 18:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save GeneralZero/18d3063cc0a331b969b1bda9ad1134fd to your computer and use it in GitHub Desktop.
Save GeneralZero/18d3063cc0a331b969b1bda9ad1134fd to your computer and use it in GitHub Desktop.
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