def initConnection(self): self.connect() #This is copied from tds.py resp = self.preLogin() if resp['Encryption'] == TDS_ENCRYPT_REQ or resp[ 'Encryption'] == TDS_ENCRYPT_OFF: LOG.debug("Encryption required, switching to TLS") # Switching to TLS now ctx = SSL.Context(SSL.TLSv1_METHOD) ctx.set_cipher_list('RC4, AES256') tls = SSL.Connection(ctx, None) tls.set_connect_state() while True: try: tls.do_handshake() except SSL.WantReadError: data = tls.bio_read(4096) self.sendTDS(TDS_PRE_LOGIN, data, 0) tds = self.recvTDS() tls.bio_write(tds['Data']) else: break # SSL and TLS limitation: Secure Socket Layer (SSL) and its replacement, # Transport Layer Security(TLS), limit data fragments to 16k in size. self.packetSize = 16 * 1024 - 1 self.tlsSocket = tls self.resp = resp return True
def toTGS(self, newSPN=None): tgs_rep = TGS_REP() tgs_rep['pvno'] = 5 tgs_rep['msg-type'] = int( constants.ApplicationTagNumbers.TGS_REP.value) tgs_rep['crealm'] = self['server'].realm['data'] # Fake EncryptedData tgs_rep['enc-part'] = noValue tgs_rep['enc-part']['etype'] = 1 tgs_rep['enc-part']['cipher'] = '' seq_set(tgs_rep, 'cname', self['client'].toPrincipal().components_to_asn1) ticket = types.Ticket() ticket.from_asn1(self.ticket['data']) if newSPN is not None: if newSPN.upper() != str(ticket.service_principal).upper(): LOG.debug( 'Changing sname from %s to %s and hoping for the best' % (ticket.service_principal, newSPN)) ticket.service_principal = types.Principal( newSPN, type=int(ticket.service_principal.type)) seq_set(tgs_rep, 'ticket', ticket.to_asn1) cipher = crypto._enctype_table[self['key']['keytype']]() tgs = dict() tgs['KDC_REP'] = encoder.encode(tgs_rep) tgs['cipher'] = cipher tgs['sessionKey'] = crypto.Key(cipher.enctype, str(self['key']['keyvalue'])) return tgs
def hBaseRegQueryValue(dce, hKey, lpValueName, dataLen=512): request = BaseRegQueryValue() request['hKey'] = hKey request['lpValueName'] = checkNullString(lpValueName) retries = 1 # We need to be aware the size might not be enough, so let's catch ERROR_MORE_DATA exception while True: try: request['lpData'] = ' ' * dataLen request['lpcbData'] = dataLen request['lpcbLen'] = dataLen resp = dce.request(request) except DCERPCSessionError, e: if retries > 1: LOG.debug( 'Too many retries when calling hBaseRegQueryValue, aborting' ) raise if e.get_error_code() == system_errors.ERROR_MORE_DATA: # We need to adjust the size dataLen = e.get_packet()['lpcbData'] continue else: raise else: break
def get_address(self): address = get_bytes(self.buffer, 5, self.get_address_length()) if self.get_protocol() == AddressDetails.PROTOCOL_IP: return socket.inet_ntoa(address) else: LOG.error("Address not IP") return address
def __init__(self, server_address=('0.0.0.0', 1080), handler_class=SocksRequestHandler): LOG.info('SOCKS proxy started. Listening at port %d', server_address[1] ) self.activeRelays = {} self.socksPlugins = {} self.restAPI = None self.activeConnectionsWatcher = None self.supportedSchemes = [] SocketServer.TCPServer.allow_reuse_address = True SocketServer.TCPServer.__init__(self, server_address, handler_class) # Let's register the socksplugins plugins we have from nebulousAD.modimpacket.examples.ntlmrelayx.servers.socksplugins import SOCKS_RELAYS for relay in SOCKS_RELAYS: LOG.info('%s loaded..' % relay.PLUGIN_NAME) self.socksPlugins[relay.PLUGIN_SCHEME] = relay self.supportedSchemes.append(relay.PLUGIN_SCHEME) # Let's create a timer to keep the connections up. self.__timer = RepeatedTimer(KEEP_ALIVE_TIMER, keepAliveTimer, self) # Let's start our RESTful API self.restAPI = Thread(target=webService, args=(self, )) self.restAPI.daemon = True self.restAPI.start() # Let's start out worker for active connections self.activeConnectionsWatcher = Thread(target=activeConnectionsWatcher, args=(self, )) self.activeConnectionsWatcher.daemon = True self.activeConnectionsWatcher.start()
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 transferResponse(self): data = self.relaySocket.recv(self.packetSize) headerSize = data.find(EOL + EOL) headers = self.getHeaders(data) try: bodySize = int(headers['content-length']) readSize = len(data) # Make sure we send the entire response, but don't keep it in memory self.socksSocket.send(data) while readSize < bodySize + headerSize + 4: data = self.relaySocket.recv(self.packetSize) readSize += len(data) self.socksSocket.send(data) except KeyError: try: if headers['transfer-encoding'] == 'chunked': # Chunked transfer-encoding, bah LOG.debug('Server sent chunked encoding - transferring') self.transferChunked(data, headers) else: # No body in the response, send as-is self.socksSocket.send(data) except KeyError: # No body in the response, send as-is self.socksSocket.send(data)
def enumerateMethods(iInterface): methods = dict() typeInfoCount = iInterface.GetTypeInfoCount() if typeInfoCount['pctinfo'] == 0: LOG.error( 'Automation Server does not support type information for this object' ) return {} iTypeInfo = iInterface.GetTypeInfo() iTypeAttr = iTypeInfo.GetTypeAttr() for x in range(iTypeAttr['ppTypeAttr']['cFuncs']): funcDesc = iTypeInfo.GetFuncDesc(x) names = iTypeInfo.GetNames(funcDesc['ppFuncDesc']['memid'], 255) print names['rgBstrNames'][0]['asData'] funcDesc.dump() print '=' * 80 if names['pcNames'] > 0: name = names['rgBstrNames'][0]['asData'] methods[name] = {} for param in range(1, names['pcNames']): methods[name][names['rgBstrNames'][param]['asData']] = '' if funcDesc['ppFuncDesc']['elemdescFunc'] != NULL: methods[name]['ret'] = funcDesc['ppFuncDesc']['elemdescFunc'][ 'tdesc']['vt'] return methods
def decode(self, aBuffer): i = ImpactPacket.IP(aBuffer) self.set_decoded_protocol(i) off = i.get_header_size() end = i.get_ip_len() # If ip_len == 0 we might be facing TCP segmentation offload, let's calculate the right len if end == 0: LOG.warning( 'IP len reported as 0, most probably because of TCP segmentation offload. Attempting to fix its size' ) i.set_ip_len(len(aBuffer)) end = i.get_ip_len() if i.get_ip_p() == ImpactPacket.UDP.protocol: self.udp_decoder = UDPDecoder() packet = self.udp_decoder.decode(aBuffer[off:end]) elif i.get_ip_p() == ImpactPacket.TCP.protocol: self.tcp_decoder = TCPDecoder() packet = self.tcp_decoder.decode(aBuffer[off:end]) elif i.get_ip_p() == ImpactPacket.ICMP.protocol: self.icmp_decoder = ICMPDecoder() packet = self.icmp_decoder.decode(aBuffer[off:end]) elif i.get_ip_p() == ImpactPacket.IGMP.protocol: self.igmp_decoder = IGMPDecoder() packet = self.igmp_decoder.decode(aBuffer[off:end]) else: self.data_decoder = DataDecoder() packet = self.data_decoder.decode(aBuffer[off:end]) i.contains(packet) return i
def __init__(self, url, baseDN='', dstIp=None): """ LDAPConnection class :param string url: :param string baseDN: :param string dstIp: :return: a LDAP instance, if not raises a LDAPSessionError exception """ self._SSL = False self._dstPort = 0 self._dstHost = 0 self._socket = None self._baseDN = baseDN self._messageId = 1 self._dstIp = dstIp if url.startswith('ldap://'): self._dstPort = 389 self._SSL = False self._dstHost = url[7:] elif url.startswith('ldaps://'): self._dstPort = 636 self._SSL = True self._dstHost = url[8:] elif url.startswith('gc://'): self._dstPort = 3268 self._SSL = False self._dstHost = url[5:] else: raise LDAPSessionError(errorString="Unknown URL prefix: '%s'" % url) # Try to connect if self._dstIp is not None: targetHost = self._dstIp else: targetHost = self._dstHost LOG.debug('Connecting to %s, port %d, SSL %s' % (targetHost, self._dstPort, self._SSL)) try: af, socktype, proto, _, sa = socket.getaddrinfo( targetHost, self._dstPort, 0, socket.SOCK_STREAM)[0] self._socket = socket.socket(af, socktype, proto) except socket.error as e: raise socket.error('Connection error (%s:%d)' % (targetHost, 88), e) if self._SSL is False: self._socket.connect(sa) else: # Switching to TLS now ctx = SSL.Context(SSL.TLSv1_METHOD) # ctx.set_cipher_list('RC4') self._socket = SSL.Connection(ctx, self._socket) self._socket.connect(sa) self._socket.do_handshake()
def run(self): while True: mtime = os.stat(self.targetprocessor.filename).st_mtime if mtime > self.lastmtime: LOG.info('Targets file modified - refreshing') self.lastmtime = mtime self.targetprocessor.readTargets() time.sleep(1.0)
def initConnection(self): self.session = imaplib.IMAP4(self.targetHost, self.targetPort) self.authTag = self.session._new_tag() LOG.debug('IMAP CAPABILITIES: %s' % str(self.session.capabilities)) if 'AUTH=NTLM' not in self.session.capabilities: LOG.error('IMAP server does not support NTLM authentication!') return False return True
def skipAuthentication(self): LOG.debug('Wrapping client connection in TLS/SSL') self.wrapClientConnection() if not HTTPSocksRelay.skipAuthentication(self): # Shut down TLS connection self.socksSocket.shutdown() return False return True
def handle_one_request(self): try: SimpleHTTPServer.SimpleHTTPRequestHandler.handle_one_request(self) except KeyboardInterrupt: raise except Exception, e: LOG.error('Exception in HTTP request handler: %s' % e) LOG.debug(traceback.format_exc())
def run(self): if self.config.queries is None: LOG.error('No SQL queries specified for MSSQL relay!') else: for query in self.config.queries: LOG.info('Executing SQL: %s' % query) self.client.sql_query(query) self.client.printReplies() self.client.printRows()
def initConnection(self): self.session = smtplib.SMTP(self.targetHost, self.targetPort) # Turn on to debug SMTP messages # self.session.debuglevel = 3 self.session.ehlo() if 'AUTH NTLM' not in self.session.ehlo_resp: LOG.error('SMTP server does not support NTLM authentication!') return False return True
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)))
def createFile(self, treeId, pathName, desiredAccess=GENERIC_ALL, shareMode=FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, creationOption=FILE_NON_DIRECTORY_FILE, creationDisposition=FILE_OVERWRITE_IF, fileAttributes=FILE_ATTRIBUTE_NORMAL, impersonationLevel=SMB2_IL_IMPERSONATION, securityFlags=0, oplockLevel=SMB2_OPLOCK_LEVEL_NONE, createContexts=None): """ creates a remote file :param HANDLE treeId: a valid handle for the share where the file is to be created :param string pathName: the path name of the file to create :return: a valid file descriptor, if not raises a SessionError exception. """ if self.getDialect() == smb.SMB_DIALECT: _, flags2 = self._SMBConnection.get_flags() pathName = pathName.replace('/', '\\') pathName = pathName.encode( 'utf-16le') if flags2 & smb.SMB.FLAGS2_UNICODE else pathName ntCreate = smb.SMBCommand(smb.SMB.SMB_COM_NT_CREATE_ANDX) ntCreate['Parameters'] = smb.SMBNtCreateAndX_Parameters() ntCreate['Data'] = smb.SMBNtCreateAndX_Data(flags=flags2) ntCreate['Parameters']['FileNameLength'] = len(pathName) ntCreate['Parameters']['AccessMask'] = desiredAccess ntCreate['Parameters']['FileAttributes'] = fileAttributes ntCreate['Parameters']['ShareAccess'] = shareMode ntCreate['Parameters']['Disposition'] = creationDisposition ntCreate['Parameters']['CreateOptions'] = creationOption ntCreate['Parameters']['Impersonation'] = impersonationLevel ntCreate['Parameters']['SecurityFlags'] = securityFlags ntCreate['Parameters']['CreateFlags'] = 0x16 ntCreate['Data']['FileName'] = pathName if flags2 & smb.SMB.FLAGS2_UNICODE: ntCreate['Data']['Pad'] = 0x0 if createContexts is not None: LOG.error("CreateContexts not supported in SMB1") try: return self._SMBConnection.nt_create_andx(treeId, pathName, cmd=ntCreate) except (smb.SessionError, smb3.SessionError), e: raise SessionError(e.get_error_code(), e.get_error_packet())
def skipAuthentication(self): LOG.debug('Wrapping IMAP client connection in TLS/SSL') self.wrapClientConnection() try: if not IMAPSocksRelay.skipAuthentication(self): # Shut down TLS connection self.socksSocket.shutdown() return False except Exception, e: LOG.debug('IMAPS: %s' % str(e)) return False
def __getitem__(self, key): if key == 'Data': try: return ''.join([chr(i) for i in self.fields[key]]) except ValueError: # We might have Unicode chars in here, let's use unichr instead LOG.debug('ValueError exception on %s' % self.fields[key]) LOG.debug('Switching to unichr()') return ''.join([unichr(i) for i in self.fields[key]]) else: return NDR.__getitem__(self, key)
def getSMBPacket(self): data = self.__NBSession.recv_packet() try: packet = NewSMBPacket(data=data.get_trailer()) smbCommand = SMBCommand(packet['Data'][0]) except Exception, e: # Maybe a SMB2 packet? try: packet = SMB2Packet(data = data.get_trailer()) smbCommand = None except Exception, e: LOG.error('SOCKS: %s' % str(e))
def getUserInfo(self, domainDumper, samname): entries = self.client.search(domainDumper.root, '(sAMAccountName=%s)' % escape_filter_chars(samname), attributes=['objectSid']) try: dn = self.client.entries[0].entry_dn sid = self.client.entries[0]['objectSid'] return (dn, sid) except IndexError: LOG.error('User not found in LDAP: %s' % samname) return False
def getPage(self, pageNum): LOG.debug("Trying to fetch page %d (0x%x)" % (pageNum, (pageNum + 1) * self.__pageSize)) self.__DB.seek((pageNum + 1) * self.__pageSize, 0) data = self.__DB.read(self.__pageSize) while len(data) < self.__pageSize: remaining = self.__pageSize - len(data) data += self.__DB.read(remaining) # Special case for the first page if pageNum <= 0: return data else: return ESENT_PAGE(self.__DBHeader, data)
def createService(self, handle, share, path): LOG.info("Creating service %s on %s....." % (self.__service_name, self.connection.getRemoteHost())) # First we try to open the service in case it exists. If it does, we remove it. try: resp = scmr.hROpenServiceW(self.rpcsvc, handle, self.__service_name + '\x00') except Exception, e: if str(e).find('ERROR_SERVICE_DOES_NOT_EXIST') >= 0: # We're good, pass the exception pass else: raise e
def getCredential(self, server, anySPN=True): for c in self.credentials: if c['server'].prettyPrint().upper() == server.upper() or c['server'].prettyPrint().upper().split('@')[0] == server.upper() \ or c['server'].prettyPrint().upper().split('@')[0] == server.upper().split('@')[0]: LOG.debug('Returning cached credential for %s' % c['server'].prettyPrint().upper()) return c LOG.debug('SPN %s not found in cache' % server.upper()) if anySPN is True: LOG.debug('AnySPN is True, looking for another suitable SPN') for c in self.credentials: # Let's search for any TGT/TGS that matches the server w/o the SPN's service type/port, returns # the first one if c['server'].prettyPrint().find('/') >= 0: # Let's take the port out for comparison cachedSPN = '%s@%s' % (c['server'].prettyPrint().upper( ).split('/')[1].split('@')[0].split(':')[0], c['server'].prettyPrint().upper( ).split('/')[1].split('@')[1]) searchSPN = '%s@%s' % ( server.upper().split('/')[1].split('@')[0].split(':') [0], server.upper().split('/')[1].split('@')[1]) if cachedSPN == searchSPN: LOG.debug('Returning cached credential for %s' % c['server'].prettyPrint().upper()) return c return None
def __getBlock(self, offset): self.fd.seek(4096 + offset, 0) sizeBytes = self.fd.read(4) data = sizeBytes + self.fd.read(unpack('<l', sizeBytes)[0] * -1 - 4) if len(data) == 0: return None else: block = REG_HBINBLOCK(data) if StructMappings.has_key(block['Data'][:2]): return StructMappings[block['Data'][:2]](block['Data']) else: LOG.debug("Unknown type 0x%s" % block['Data'][:2]) return block return None
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 do_attack(self): # Check if SOCKS is enabled and if we support the target scheme if self.server.config.runSocks and self.target.scheme.upper() in self.server.config.socksServer.supportedSchemes: # Pass all the data to the socksplugins proxy activeConnections.put((self.target.hostname, self.client.targetPort, self.target.scheme.upper(), self.authUser, self.client, self.client.sessionData)) return # If SOCKS is not enabled, or not supported for this scheme, fall back to "classic" attacks if self.target.scheme.upper() in self.server.config.attacks: # We have an attack.. go for it clientThread = self.server.config.attacks[self.target.scheme.upper()](self.server.config, self.client.session, self.authUser) clientThread.start() else: LOG.error('No attack configured for %s' % self.target.scheme.upper())
def sendReceive(data, host, kdcHost): if kdcHost is None: targetHost = host else: targetHost = kdcHost messageLen = struct.pack('!i', len(data)) LOG.debug('Trying to connect to KDC at %s' % targetHost) try: af, socktype, proto, canonname, sa = socket.getaddrinfo( targetHost, 88, 0, socket.SOCK_STREAM)[0] s = socket.socket(af, socktype, proto) s.connect(sa) except socket.error, e: raise socket.error("Connection error (%s:%s)" % (targetHost, 88), e)
def sendAuth(self, authenticateMessageBlob, serverChallenge=None): if unpack('B', str(authenticateMessageBlob) [:1])[0] == SPNEGO_NegTokenResp.SPNEGO_NEG_TOKEN_RESP: respToken2 = SPNEGO_NegTokenResp(authenticateMessageBlob) token = respToken2['ResponseToken'] else: token = authenticateMessageBlob auth = base64.b64encode(token) self.session.putcmd(auth) typ, data = self.session.getreply() if typ == 235: self.session.state = 'AUTH' return None, STATUS_SUCCESS else: LOG.error('SMTP: %s' % ''.join(data)) return None, STATUS_ACCESS_DENIED