code: def create_authenticate_message(self, user_name, password, domain_name=None, workstation=None, server_certificate_hash=None):
          
          self.authenticate_message = AuthenticateMessage(user_name, password, domain_name, workstation,
                                                          self.challenge_message, self.ntlm_compatibility,
                                                          server_certificate_hash)
          self.authenticate_message.add_mic(self.negotiate_message, self.challenge_message)
  
          # Setups up the session_security context used to sign and seal messages if wanted
          if self.negotiate_flags & NegotiateFlags.NTLMSSP_NEGOTIATE_SEAL or self.negotiate_flags & NegotiateFlags.NTLMSSP_NEGOTIATE_SIGN:
              self.session_security = SessionSecurity(struct.unpack("<I", self.authenticate_message.negotiate_flags)[0],
                                                      self.authenticate_message.exported_session_key)
  
          return base64.b64encode(self.authenticate_message.get_data())
docs: Create an NTLM AUTHENTICATE_MESSAGE based on the Ntlm context and the previous messages sent and received
  
          :param user_name: The user name of the user we are trying to authenticate with
          :param password: The password of the user we are trying to authenticate with
          :param domain_name: The domain name of the user account we are authenticated with, default is None
          :param workstation: The workstation we are using to authenticate with, default is None
          :param server_certificate_hash: The SHA256 hash string of the server certificate (DER encoded) NTLM is authenticating to. Used for Channel
                                          Binding Tokens. If nothing is supplied then the CBT hash will not be sent. See messages.py AuthenticateMessage
                                          for more details
          :return: A base64 encoded string of the AUTHENTICATE_MESSAGE