def strenc(data, firstkey, secondkey, thirdKey): bts_data = extend_to_16bits(data) bts_firstkey = extend_to_16bits(firstkey) bts_secondkey = extend_to_16bits(secondkey) bts_thirdkey = extend_to_16bits(thirdKey) i = 0 bts_result = [] while i < len(bts_data): bts_temp = bts_data[i:i + 8] # 将data分成每64位一段,分段加密 j, k, z = 0, 0, 0 while j < len(bts_firstkey): des_k = pyDes.des(bts_firstkey[j:j + 8], pyDes.ECB) # 分别取出 first_key 的64位作为密钥 bts_temp = list(des_k.encrypt(bts_temp)) j += 8 while k < len(bts_secondkey): des_k = pyDes.des(bts_secondkey[k:k + 8], pyDes.ECB) # 分别取出 second_key 的64位作为密钥 bts_temp = list(des_k.encrypt(bts_temp)) k += 8 while z < len(bts_thirdkey): des_k = pyDes.des(bts_thirdkey[z:z + 8], pyDes.ECB) # 分别取出 second_key 的64位作为密钥 bts_temp = list(des_k.encrypt(bts_temp)) z += 8 bts_result.extend(bts_temp) i += 8 str_result = '' for each in bts_result: str_result += '%02X' % each # 分别加密data的各段,串联成字符串 return str_result
def generateChallengeResponseV1(password, server_challenge, has_extended_security=False, client_challenge=None): """ Generate a NTLMv1 response @param password: User password string @param server_challange: A 8-byte challenge string sent from the server @param has_extended_security: A boolean value indicating whether NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY flag is enabled in the NTLM negFlag @param client_challenge: A 8-byte string representing client challenge. If None, it will be generated randomly if needed by the response generation @return: a tuple of ( NT challenge response string, LM challenge response string ) References: =========== - http://ubiqx.org/cifs/SMB.html (2.8.3.3 and 2.8.3.4) - [MS-NLMP]: 3.3.1 """ _password = (password.upper() + '\0' * 14)[:14] d1 = des(expandDesKey(_password[:7])) d2 = des(expandDesKey(_password[7:])) lm_response_key = d1.encrypt("KGS!@#$%") + d2.encrypt( "KGS!@#$%" ) # LM password hash. In [MS-NLMP], this is the result of LMOWFv1 function d = MD4() d.update(password.encode('UTF-16LE')) nt_response_key = d.digest( ) # In [MS-NLMP], this is the result of NTOWFv1 function if has_extended_security: if not client_challenge: client_challenge = '' for i in range(0, 8): client_challenge += chr(random.getrandbits(8)) assert len(client_challenge) == 8 lm_challenge_response = client_challenge + '\0' * 16 nt_challenge_response = DESL( nt_response_key, MD5(server_challenge + client_challenge).digest()[0:8]) else: nt_challenge_response = DESL( nt_response_key, server_challenge) # The result after DESL is the NT response lm_challenge_response = DESL( lm_response_key, server_challenge) # The result after DESL is the LM response d = MD4() d.update(nt_response_key) session_key = d.digest() return nt_challenge_response, lm_challenge_response, session_key
def DESL(K, D): """ References: =========== - http://ubiqx.org/cifs/SMB.html (2.8.3.4) - [MS-NLMP]: Section 6 """ d1 = des(expandDesKey(K[0:7])) d2 = des(expandDesKey(K[7:14])) d3 = des(expandDesKey(K[14:16] + "\0" * 5)) return d1.encrypt(D) + d2.encrypt(D) + d3.encrypt(D)
def DESL(K, D): """ References: =========== - http://ubiqx.org/cifs/SMB.html (2.8.3.4) - [MS-NLMP]: Section 6 """ d1 = des(expandDesKey(K[0:7])) d2 = des(expandDesKey(K[7:14])) d3 = des(expandDesKey(K[14:16] + '\0' * 5)) return d1.encrypt(D) + d2.encrypt(D) + d3.encrypt(D)
def generateChallengeResponseV1(password, server_challenge, has_extended_security=False, client_challenge=None): """ Generate a NTLMv1 response @param password: User password string @param server_challange: A 8-byte challenge string sent from the server @param has_extended_security: A boolean value indicating whether NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY flag is enabled in the NTLM negFlag @param client_challenge: A 8-byte string representing client challenge. If None, it will be generated randomly if needed by the response generation @return: a tuple of ( NT challenge response string, LM challenge response string ) References: =========== - http://ubiqx.org/cifs/SMB.html (2.8.3.3 and 2.8.3.4) - [MS-NLMP]: 3.3.1 """ _password = (password.upper() + "\0" * 14)[:14] d1 = des(expandDesKey(_password[:7])) d2 = des(expandDesKey(_password[7:])) lm_response_key = d1.encrypt("KGS!@#$%") + d2.encrypt( "KGS!@#$%" ) # LM password hash. In [MS-NLMP], this is the result of LMOWFv1 function d = MD4() d.update(password.encode("UTF-16LE")) nt_response_key = d.digest() # In [MS-NLMP], this is the result of NTOWFv1 function if has_extended_security: if not client_challenge: client_challenge = "" for i in range(0, 8): client_challenge += chr(random.getrandbits(8)) assert len(client_challenge) == 8 lm_challenge_response = client_challenge + "\0" * 16 nt_challenge_response = DESL(nt_response_key, MD5(server_challenge + client_challenge).digest()[0:8]) else: nt_challenge_response = DESL(nt_response_key, server_challenge) # The result after DESL is the NT response lm_challenge_response = DESL(lm_response_key, server_challenge) # The result after DESL is the LM response d = MD4() d.update(nt_response_key) session_key = d.digest() return nt_challenge_response, lm_challenge_response, session_key