def findWritableShare(self, shares): # Check we can write a file on the shares, stop in the first one writeableShare = None for i in shares['Buffer']: if i['shi1_type'] == srvs.STYPE_DISKTREE or i[ 'shi1_type'] == srvs.STYPE_SPECIAL: share = i['shi1_netname'][:-1] tid = 0 try: tid = self.connection.connectTree(share) self.connection.openFile( tid, '\\', FILE_WRITE_DATA, creationOption=FILE_DIRECTORY_FILE) except: LOG.critical("share '%s' is not writable." % share) pass else: LOG.info('Found writable share %s' % share) writeableShare = str(share) break finally: if tid != 0: self.connection.disconnectTree(tid) return writeableShare
def copy_file(self, src, tree, dst): LOG.info("Uploading file %s" % dst) if isinstance(src, str): # We have a filename fh = open(src, 'rb') else: # We have a class instance, it must have a read method fh = src f = dst pathname = string.replace(f, '/', '\\') try: self.connection.putFile(tree, pathname, fh.read) except: LOG.critical("Error uploading file %s, aborting....." % dst) raise fh.close()
def uninstall(self): fileCopied = True serviceCreated = True # Do the stuff here try: # Let's get the shares svcManager = self.openSvcManager() if svcManager != 0: resp = scmr.hROpenServiceW(self.rpcsvc, svcManager, self.__service_name + '\x00') service = resp['lpServiceHandle'] LOG.info('Stopping service %s.....' % self.__service_name) try: scmr.hRControlService(self.rpcsvc, service, scmr.SERVICE_CONTROL_STOP) except: pass LOG.info('Removing service %s.....' % self.__service_name) scmr.hRDeleteService(self.rpcsvc, service) scmr.hRCloseServiceHandle(self.rpcsvc, service) scmr.hRCloseServiceHandle(self.rpcsvc, svcManager) LOG.info('Removing file %s.....' % self.__binary_service_name) self.connection.deleteFile(self.share, self.__binary_service_name) except Exception: LOG.critical("Error performing the uninstallation, cleaning up") try: scmr.hRControlService(self.rpcsvc, service, scmr.SERVICE_CONTROL_STOP) except: pass if fileCopied is True: try: self.connection.deleteFile(self.share, self.__binary_service_name) except: try: self.connection.deleteFile(self.share, self.__binary_service_name) except: pass pass if serviceCreated is True: try: scmr.hRDeleteService(self.rpcsvc, service) except: pass
class TargetsProcessor: def __init__(self, targetListFile=None, singleTarget=None, protocolClients=None): # Here we store the attacks that already finished, mostly the ones that have usernames, since the # other ones will never finish. self.finishedAttacks = [] self.protocolClients = protocolClients if targetListFile is None: self.filename = None self.originalTargets = self.processTarget(singleTarget, protocolClients) else: self.filename = targetListFile self.originalTargets = [] self.readTargets() self.candidates = [x for x in self.originalTargets] @staticmethod def processTarget(target, protocolClients): # Check if we have a single target, with no URI form if target.find('://') <= 0: # Target is a single IP, assuming it's SMB. return [urlparse('smb://%s' % target)] # Checks if it needs to expand the list if there's a all://* retVals = [] if target[:3].upper() == 'ALL': strippedTarget = target[3:] for protocol in protocolClients: retVals.append(urlparse('%s%s' % (protocol, strippedTarget))) return retVals else: return [urlparse(target)] def readTargets(self): try: with open(self.filename, 'r') as f: self.originalTargets = [] for line in f: target = line.strip() if target != '': self.originalTargets.extend( self.processTarget(target, self.protocolClients)) except IOError, e: LOG.error("Could not open file: %s - " % (self.filename, str(e))) if len(self.originalTargets) == 0: LOG.critical("Warning: no valid targets specified!") self.candidates = [ x for x in self.originalTargets if x not in self.finishedAttacks ]
def __compareHash(self, magic, hashData, key): if magic == 'lf': hashRec = REG_HASH(hashData) if hashRec['KeyName'].strip('\x00') == key[:4]: return hashRec['OffsetNk'] elif magic == 'lh': hashRec = REG_HASH(hashData) if unpack('<L', hashRec['KeyName'])[0] == self.__getLhHash(key): return hashRec['OffsetNk'] elif magic == 'ri': # Special case here, don't know exactly why, an ri pointing to a NK :-o offset = unpack('<L', hashData[:4])[0] nk = self.__getBlock(offset) if nk['KeyName'] == key: return offset else: LOG.critical("UNKNOWN Magic %s" % magic) sys.exit(1) return None
def getShares(self): # Setup up a DCE SMBTransport with the connection already in place LOG.info("Requesting shares on %s....." % (self.connection.getRemoteHost())) try: self._rpctransport = transport.SMBTransport( self.connection.getRemoteHost(), self.connection.getRemoteHost(), filename=r'\srvsvc', smb_connection=self.connection) dce_srvs = self._rpctransport.get_dce_rpc() dce_srvs.connect() dce_srvs.bind(srvs.MSRPC_UUID_SRVS) resp = srvs.hNetrShareEnum(dce_srvs, 1) return resp['InfoStruct']['ShareInfo']['Level1'] except: LOG.critical("Error requesting shares on %s, aborting....." % (self.connection.getRemoteHost())) raise
def openSvcManager(self): LOG.info("Opening SVCManager on %s....." % self.connection.getRemoteHost()) # Setup up a DCE SMBTransport with the connection already in place self._rpctransport = transport.SMBTransport( self.connection.getRemoteHost(), self.connection.getRemoteHost(), filename=r'\svcctl', smb_connection=self.connection) self.rpcsvc = self._rpctransport.get_dce_rpc() self.rpcsvc.connect() self.rpcsvc.bind(scmr.MSRPC_UUID_SCMR) try: resp = scmr.hROpenSCManagerW(self.rpcsvc) except: LOG.critical("Error opening SVCManager on %s....." % self.connection.getRemoteHost()) raise Exception('Unable to open SVCManager') else: return resp['lpScHandle']
from nebulousAD.modimpacket import LOG, hresult_errors from nebulousAD.modimpacket.dcerpc.v5.ndr import NDRCALL, NDRSTRUCT, NDRPOINTER, NDRUniConformantArray, NDRUNION, NDR, NDRENUM from nebulousAD.modimpacket.dcerpc.v5.dtypes import PUUID, DWORD, NULL, GUID, LPWSTR, BOOL, ULONG, UUID, LONGLONG, ULARGE_INTEGER, LARGE_INTEGER from nebulousAD.modimpacket import system_errors from nebulousAD.modimpacket.structure import Structure from nebulousAD.modimpacket.uuid import uuidtup_to_bin, string_to_bin from nebulousAD.modimpacket.dcerpc.v5.enum import Enum from nebulousAD.modimpacket.dcerpc.v5.rpcrt import DCERPCException from nebulousAD.modimpacket.krb5 import crypto from pyasn1.type import univ from pyasn1.codec.ber import decoder try: from Cryptodome.Cipher import ARC4, DES except Exception: LOG.critical( "Warning: You don't have any crypto installed. You need pycryptodomex") LOG.critical("See https://pypi.org/project/pycryptodomex/") MSRPC_UUID_DRSUAPI = uuidtup_to_bin( ('E3514235-4B06-11D1-AB04-00C04FC2DCD2', '4.0')) class DCERPCSessionError(DCERPCException): def __init__(self, error_string=None, error_code=None, packet=None): DCERPCException.__init__(self, error_string, error_code, packet) def __str__(self): key = self.error_code if hresult_errors.ERROR_MESSAGES.has_key(key): error_msg_short = hresult_errors.ERROR_MESSAGES[key][0] error_msg_verbose = hresult_errors.ERROR_MESSAGES[key][1]
def negotiateSession( self, preferredDialect=None, flags1=smb.SMB.FLAGS1_PATHCASELESS | smb.SMB.FLAGS1_CANONICALIZED_PATHS, flags2=smb.SMB.FLAGS2_EXTENDED_SECURITY | smb.SMB.FLAGS2_NT_STATUS | smb.SMB.FLAGS2_LONG_NAMES, negoData='\x02NT LM 0.12\x00\x02SMB 2.002\x00\x02SMB 2.???\x00'): """ Perform protocol negotiation :param string preferredDialect: the dialect desired to talk with the target server. If None is specified the highest one available will be used :param string flags1: the SMB FLAGS capabilities :param string flags2: the SMB FLAGS2 capabilities :param string negoData: data to be sent as part of the nego handshake :return: True, raises a Session Error if error. """ # If port 445 and the name sent is *SMBSERVER we're setting the name to the IP. This is to help some old # applications still believing # *SMSBSERVER will work against modern OSes. If port is NETBIOS_SESSION_PORT the user better know about i # *SMBSERVER's limitations if self._sess_port == nmb.SMB_SESSION_PORT and self._remoteName == '*SMBSERVER': self._remoteName = self._remoteHost elif self._sess_port == nmb.NETBIOS_SESSION_PORT and self._remoteName == '*SMBSERVER': # If remote name is *SMBSERVER let's try to query its name.. if can't be guessed, continue and hope for the best nb = nmb.NetBIOS() try: res = nb.getnetbiosname(self._remoteHost) except: pass else: self._remoteName = res hostType = nmb.TYPE_SERVER if preferredDialect is None: # If no preferredDialect sent, we try the highest available one. packet = self.negotiateSessionWildcard(self._myName, self._remoteName, self._remoteHost, self._sess_port, self._timeout, True, flags1=flags1, flags2=flags2, data=negoData) if packet[0] == '\xfe': # Answer is SMB2 packet self._SMBConnection = smb3.SMB3( self._remoteName, self._remoteHost, self._myName, hostType, self._sess_port, self._timeout, session=self._nmbSession, negSessionResponse=SMB2Packet(packet)) else: # Answer is SMB packet, sticking to SMBv1 self._SMBConnection = smb.SMB(self._remoteName, self._remoteHost, self._myName, hostType, self._sess_port, self._timeout, session=self._nmbSession, negPacket=packet) else: if preferredDialect == smb.SMB_DIALECT: self._SMBConnection = smb.SMB(self._remoteName, self._remoteHost, self._myName, hostType, self._sess_port, self._timeout) elif preferredDialect in [ SMB2_DIALECT_002, SMB2_DIALECT_21, SMB2_DIALECT_30 ]: self._SMBConnection = smb3.SMB3( self._remoteName, self._remoteHost, self._myName, hostType, self._sess_port, self._timeout, preferredDialect=preferredDialect) else: LOG.critical("Unknown dialect %s", preferredDialect) raise # propagate flags to the smb sub-object, except for Unicode (if server supports) # does not affect smb3 objects if isinstance(self._SMBConnection, smb.SMB): if self._SMBConnection.get_flags()[1] & smb.SMB.FLAGS2_UNICODE: flags2 |= smb.SMB.FLAGS2_UNICODE self._SMBConnection.set_flags(flags1=flags1, flags2=flags2) return True
from binascii import unhexlify from pyasn1.codec.ber import encoder, decoder from pyasn1.error import SubstrateUnderrunError from pyasn1.type.univ import noValue from nebulousAD.modimpacket import LOG from nebulousAD.modimpacket.ldap.ldapasn1 import * from nebulousAD.modimpacket.ntlm import getNTLMSSPType1, getNTLMSSPType3 from nebulousAD.modimpacket.spnego import SPNEGO_NegTokenInit, TypesMech try: import OpenSSL from OpenSSL import SSL, crypto except: LOG.critical("pyOpenSSL is not installed, can't continue") raise __all__ = [ 'LDAPConnection', 'LDAPFilterSyntaxError', 'LDAPFilterInvalidException', 'LDAPSessionError', 'LDAPSearchError', 'Control', 'SimplePagedResultsControl', 'ResultCode', 'Scope', 'DerefAliases', 'Operation', 'CONTROL_PAGEDRESULTS',
def install(self): if self.connection.isGuestSession(): LOG.critical("Authenticated as Guest. Aborting") self.connection.logoff() del self.connection else: fileCopied = False serviceCreated = False # Do the stuff here try: # Let's get the shares shares = self.getShares() self.share = self.findWritableShare(shares) if self.share is None: return False self.copy_file(self.__exeFile, self.share, self.__binary_service_name) fileCopied = True svcManager = self.openSvcManager() if svcManager != 0: serverName = self.connection.getServerName() if self.share.lower() == 'admin$': path = '%systemroot%' else: if serverName != '': path = '\\\\%s\\%s' % (serverName, self.share) else: path = '\\\\127.0.0.1\\' + self.share service = self.createService(svcManager, self.share, path) serviceCreated = True if service != 0: # Start service LOG.info('Starting service %s.....' % self.__service_name) try: scmr.hRStartServiceW(self.rpcsvc, service) except: pass scmr.hRCloseServiceHandle(self.rpcsvc, service) scmr.hRCloseServiceHandle(self.rpcsvc, svcManager) return True except Exception, e: LOG.critical( "Error performing the installation, cleaning up: %s" % e) try: scmr.hRControlService(self.rpcsvc, service, scmr.SERVICE_CONTROL_STOP) except: pass if fileCopied is True: try: self.connection.deleteFile(self.share, self.__binary_service_name) except: pass if serviceCreated is True: try: scmr.hRDeleteService(self.rpcsvc, service) except: pass return False
# It exists, remove it scmr.hRDeleteService(self.rpcsvc, resp['lpServiceHandle']) scmr.hRCloseServiceHandle(self.rpcsvc, resp['lpServiceHandle']) # Create the service command = '%s\\%s' % (path, self.__binary_service_name) try: resp = scmr.hRCreateServiceW(self.rpcsvc, handle, self.__service_name + '\x00', self.__service_name + '\x00', lpBinaryPathName=command + '\x00', dwStartType=scmr.SERVICE_DEMAND_START) except: LOG.critical( "Error creating service %s on %s" % (self.__service_name, self.connection.getRemoteHost())) raise else: return resp['lpServiceHandle'] def openSvcManager(self): LOG.info("Opening SVCManager on %s....." % self.connection.getRemoteHost()) # Setup up a DCE SMBTransport with the connection already in place self._rpctransport = transport.SMBTransport( self.connection.getRemoteHost(), self.connection.getRemoteHost(), filename=r'\svcctl', smb_connection=self.connection) self.rpcsvc = self._rpctransport.get_dce_rpc()