update python3

main
mpgn 2019-11-10 18:12:35 -05:00
parent c3c4b3192d
commit a29cf6760c
17 changed files with 171 additions and 170 deletions

View File

@ -1,4 +1,5 @@
import logging
from os.path import isfile
# from traceback import format_exc
from gevent.lock import BoundedSemaphore
from gevent.socket import gethostbyname
@ -77,7 +78,7 @@ class connection(object):
self.call_cmd_args()
def call_cmd_args(self):
for k, v in vars(self.args).iteritems():
for k, v in vars(self.args).items():
if hasattr(self, k) and hasattr(getattr(self, k), '__call__'):
if v is not False and v is not None:
logging.debug('Calling {}()'.format(k))
@ -163,7 +164,7 @@ class connection(object):
self.logger.error("Invalid database credential ID!")
for user in self.args.username:
if type(user) is file:
if isfile(user):
for usr in user:
if self.args.hash:
with sem:
@ -191,7 +192,7 @@ class connection(object):
if self.plaintext_login(self.domain, usr.strip(), f_pass.strip()): return True
password.seek(0)
elif type(user) is not file:
elif isfile(user) == False:
if hasattr(self.args, 'hash') and self.args.hash:
with sem:
for ntlm_hash in self.args.hash:
@ -208,14 +209,14 @@ class connection(object):
elif self.args.password:
with sem:
for password in self.args.password:
if type(password) is not file:
if isfile(password) == False:
if not self.over_fail_limit(user):
if hasattr(self.args, 'domain'):
if self.plaintext_login(self.domain, user, password): return True
else:
if self.plaintext_login(user, password): return True
elif type(password) is file:
elif isfile(password) is file:
for f_pass in password:
if not self.over_fail_limit(user):
if hasattr(self.args, 'domain'):

View File

@ -14,5 +14,5 @@ class Context:
self.conf = configparser.ConfigParser()
self.conf.read(os.path.expanduser('~/.cme/cme.conf'))
for key, value in vars(args).iteritems():
for key, value in vars(args).items():
setattr(self, key, value)

View File

@ -56,7 +56,7 @@ class CMEAdapter(logging.LoggerAdapter):
return u'{:<24} {:<15} {:<6} {:<16} {}'.format(module_name,
self.extra['host'],
self.extra['port'],
self.extra['hostname'].decode('utf-8') if self.extra['hostname'] else 'NONE',
self.extra['hostname'] if self.extra['hostname'] else 'NONE',
msg), kwargs
def info(self, msg, *args, **kwargs):

View File

@ -19,12 +19,12 @@ class CMEModule:
if output:
context.log.success('Found Anti-Spyware product:')
for entry in output:
for k,v in entry.iteritems():
for k,v in entry.items():
context.log.highlight('{} => {}'.format(k,v['value']))
output = connection.wmi('Select * from AntiVirusProduct', 'root\\SecurityCenter2')
if output:
context.log.success('Found Anti-Virus product:')
for entry in output:
for k,v in entry.iteritems():
for k,v in entry.items():
context.log.highlight('{} => {}'.format(k,v['value']))

View File

@ -52,7 +52,7 @@ class CMEModule:
else:
domain_data[rtype] = ["{}: {}".format(rname, rvalue)]
for k, v in sorted(domain_data.iteritems()):
for k, v in sorted(domain_data.items()):
context.log.highlight("Record Type: {}".format(k))
data += "Record Type: {}\n".format(k)
for d in sorted(v):

View File

@ -68,7 +68,7 @@ class CMEModule:
context.log.success('Found credentials in {}'.format(path))
context.log.highlight('Password: {}'.format(password))
for k,v in props.iteritems():
for k,v in props.items():
if k != 'cpassword':
context.log.highlight('{}: {}'.format(k, v))

View File

@ -13,7 +13,7 @@ class navigator(DatabaseNavigator):
# links = self.db.get_links(credID=credID)
data.append([credID, url.decode('utf-8'), username.decode('utf-8'), password.decode('utf-8')])
data.append([credID, url, username, password])
self.print_table(data, title='Credential(s)')

View File

@ -170,9 +170,9 @@ class mssql(connection):
if self.admin_privs:
self.db.add_admin_user('plaintext', domain, username, password, self.host)
out = u'{}{}:{} {}'.format('{}\\'.format(domain.decode('utf-8')) if self.args.auth_type is 'windows' else '',
username.decode('utf-8'),
password.decode('utf-8'),
out = u'{}{}:{} {}'.format('{}\\'.format(domain) if self.args.auth_type is 'windows' else '',
username,
password,
highlight('({})'.format(self.config.get('CME', 'pwn3d_label')) if self.admin_privs else ''))
self.logger.success(out)
return True
@ -201,8 +201,8 @@ class mssql(connection):
if self.admin_privs:
self.db.add_admin_user('hash', domain, username, ntlm_hash, self.host)
out = u'{}\\{} {} {}'.format(domain.decode('utf-8'),
username.decode('utf-8'),
out = u'{}\\{} {} {}'.format(domain,
username,
ntlm_hash,
highlight('({})'.format(self.config.get('CME', 'pwn3d_label')) if self.admin_privs else ''))
@ -230,7 +230,7 @@ class mssql(connection):
if hasattr(self, 'server'): self.server.track_host(self.host)
output = u'{}'.format(raw_output.decode('utf-8'))
output = u'{}'.format(raw_output)
if self.args.execute or self.args.ps_execute:
#self.logger.success('Executed command {}'.format('via {}'.format(self.args.exec_method) if self.args.exec_method else ''))

View File

@ -19,7 +19,7 @@ class navigator(DatabaseNavigator):
links = self.db.get_admin_relations(userID=credID)
data.append([credID, str(len(links)) + ' Host(s)', credtype, domain.decode('utf-8'), username.decode('utf-8'), password.decode('utf-8')])
data.append([credID, str(len(links)) + ' Host(s)', credtype, domain, username, password])
self.print_table(data, title='Credentials')
@ -38,7 +38,7 @@ class navigator(DatabaseNavigator):
links = self.db.get_admin_relations(hostID=hostID)
data.append([hostID, str(len(links)) + ' Cred(s)', ip, hostname.decode('utf-8'), domain.decode('utf-8'), os, instances])
data.append([hostID, str(len(links)) + ' Cred(s)', ip, hostname, domain, os, instances])
self.print_table(data, title='Hosts')
@ -67,7 +67,7 @@ class navigator(DatabaseNavigator):
domain = host[3]
os = host[4]
data.append([hostID, ip, hostname.decode('utf-8'), domain.decode('utf-8'), os])
data.append([hostID, ip, hostname, domain, os])
self.print_table(data, title='Host(s)')
@ -87,7 +87,7 @@ class navigator(DatabaseNavigator):
credtype = cred[4]
# pillaged_from = cred[5]
data.append([credID, credtype, domain.decode('utf-8'), username.decode('utf-8'), password.decode('utf-8')])
data.append([credID, credtype, domain, username, password])
self.print_table(data, title='Credential(s) with Admin Access')
@ -146,7 +146,7 @@ class navigator(DatabaseNavigator):
username = cred[3]
password = cred[4]
data.append([credID, credType, domain.decode('utf-8'), username.decode('utf-8'), password.decode('utf-8')])
data.append([credID, credType, domain, username, password])
self.print_table(data, title='Credential(s)')
@ -165,7 +165,7 @@ class navigator(DatabaseNavigator):
domain = host[3]
os = host[4]
data.append([hostID, ip, hostname.decode('utf-8'), domain.decode('utf-8'), os])
data.append([hostID, ip, hostname, domain, os])
self.print_table(data, title='Admin Access to Host(s)')

View File

@ -60,13 +60,13 @@ def requires_smb_server(func):
except IndexError:
pass
if kwargs.has_key('payload'):
if 'payload' in kwargs:
payload = kwargs['payload']
if kwargs.has_key('get_output'):
if 'get_output' in kwargs:
get_output = kwargs['get_output']
if kwargs.has_key('methods'):
if 'methods' in kwargs:
methods = kwargs['methods']
if not payload and self.args.execute:
@ -202,9 +202,9 @@ class smb(connection):
try:
self.conn.login('' , '')
except SessionError as e:
if "STATUS_ACCESS_DENIED" in e.message:
pass
except:
#if "STATUS_ACCESS_DENIED" in e:
pass
self.domain = self.conn.getServerDomain()
self.hostname = self.conn.getServerName()
@ -240,8 +240,8 @@ class smb(connection):
def print_host_info(self):
self.logger.info(u"{}{} (name:{}) (domain:{}) (signing:{}) (SMBv1:{})".format(self.server_os,
' x{}'.format(self.os_arch) if self.os_arch else '',
self.hostname.decode('utf-8'),
self.domain.decode('utf-8'),
self.hostname,
self.domain,
self.signing,
self.smbv1))
@ -258,9 +258,9 @@ class smb(connection):
if self.admin_privs:
self.db.add_admin_user('plaintext', domain, username, password, self.host)
out = u'{}\\{}:{} {}'.format(domain.decode('utf-8'),
username.decode('utf-8'),
password.decode('utf-8'),
out = u'{}\\{}:{} {}'.format(domain,
username,
password,
highlight('({})'.format(self.config.get('CME', 'pwn3d_label')) if self.admin_privs else ''))
self.logger.success(out)
@ -268,9 +268,9 @@ class smb(connection):
return True
except SessionError as e:
error, desc = e.getErrorString()
self.logger.error(u'{}\\{}:{} {} {}'.format(domain.decode('utf-8'),
username.decode('utf-8'),
password.decode('utf-8'),
self.logger.error(u'{}\\{}:{} {} {}'.format(domain,
username,
password,
error,
'({})'.format(desc) if self.args.verbose else ''))
@ -303,8 +303,8 @@ class smb(connection):
if self.admin_privs:
self.db.add_admin_user('hash', domain, username, ntlm_hash, self.host)
out = u'{}\\{} {} {}'.format(domain.decode('utf-8'),
username.decode('utf-8'),
out = u'{}\\{} {} {}'.format(domain,
username,
ntlm_hash,
highlight('({})'.format(self.config.get('CME', 'pwn3d_label')) if self.admin_privs else ''))
@ -313,8 +313,8 @@ class smb(connection):
return True
except SessionError as e:
error, desc = e.getErrorString()
self.logger.error(u'{}\\{} {} {} {}'.format(domain.decode('utf-8'),
username.decode('utf-8'),
self.logger.error(u'{}\\{} {} {} {}'.format(domain,
username,
ntlm_hash,
error,
'({})'.format(desc) if self.args.verbose else ''))
@ -431,7 +431,7 @@ class smb(connection):
if hasattr(self, 'server'): self.server.track_host(self.host)
output = u'{}'.format(exec_method.execute(payload, get_output).strip().decode('utf-8',errors='replace'))
output = u'{}'.format(exec_method.execute(payload, get_output).strip())
if self.args.execute or self.args.ps_execute:
self.logger.success('Executed command {}'.format('via {}'.format(self.args.exec_method) if self.args.exec_method else ''))
@ -683,7 +683,7 @@ class smb(connection):
wmi_results = query.Next(0xffffffff, 1)[0]
record = wmi_results.getProperties()
records.append(record)
for k,v in record.iteritems():
for k,v in record.items():
self.logger.highlight('{} => {}'.format(k,v['value']))
self.logger.highlight('')
except Exception as e:

View File

@ -141,8 +141,7 @@ class database:
cur.close()
logging.debug('add_credential(credtype={}, domain={}, username={}, password={}, groupid={}, pillaged_from={}) => {}'.encode().format(credtype, domain, username, password,
groupid, pillaged_from, user_rowid))
logging.debug('add_credential(credtype={}, domain={}, username={}, password={}, groupid={}, pillaged_from={}) => {}'.format(credtype, domain, username, password, groupid, pillaged_from, user_rowid))
return user_rowid

View File

@ -19,7 +19,7 @@ class navigator(DatabaseNavigator):
links = self.db.get_admin_relations(userID=credID)
data.append([credID, str(len(links)) + ' Host(s)', credtype, domain.decode('utf-8'), username.decode('utf-8'), password.decode('utf-8')])
data.append([credID, str(len(links)) + ' Host(s)', credtype, domain, username, password])
self.print_table(data, title='Credentials')
@ -33,7 +33,7 @@ class navigator(DatabaseNavigator):
name = group[2]
members = len(self.db.get_group_relations(groupID=groupID))
data.append([groupID, domain.decode('utf-8'), name, members])
data.append([groupID, domain, name, members])
self.print_table(data, title='Groups')
@ -51,7 +51,7 @@ class navigator(DatabaseNavigator):
links = self.db.get_admin_relations(hostID=hostID)
data.append([hostID, str(len(links)) + ' Cred(s)', ip, hostname.decode('utf-8'), domain.decode('utf-8'), os])
data.append([hostID, str(len(links)) + ' Cred(s)', ip, hostname, domain, os])
self.print_table(data, title='Hosts')
@ -77,7 +77,7 @@ class navigator(DatabaseNavigator):
domain = group[1]
name = group[2]
data.append([groupID, domain.decode('utf-8'), name.decode('utf-8')])
data.append([groupID, domain, name])
self.print_table(data, title='Group')
@ -98,7 +98,7 @@ class navigator(DatabaseNavigator):
credtype = cred[4]
pillaged_from = cred[5]
data.append([credID, credtype, pillaged_from, domain.decode('utf-8'), username.decode('utf-8'), password.decode('utf-8')])
data.append([credID, credtype, pillaged_from, domain, username, password])
self.print_table(data, title='Member(s)')
@ -128,7 +128,7 @@ class navigator(DatabaseNavigator):
os = host[4]
dc = host[5]
data.append([hostID, ip, hostname.decode('utf-8'), domain.decode('utf-8'), os, dc])
data.append([hostID, ip, hostname, domain, os, dc])
self.print_table(data, title='Host(s)')
@ -148,7 +148,7 @@ class navigator(DatabaseNavigator):
credtype = cred[4]
# pillaged_from = cred[5]
data.append([credID, credtype, domain.decode('utf-8'), username.decode('utf-8'), password.decode('utf-8')])
data.append([credID, credtype, domain, username, password])
self.print_table(data, title='Credential(s) with Admin Access')
@ -212,7 +212,7 @@ class navigator(DatabaseNavigator):
credtype = cred[4]
pillaged_from = cred[5]
data.append([credID, credtype, pillaged_from, domain.decode('utf-8'), username.decode('utf-8'), password.decode('utf-8')])
data.append([credID, credtype, pillaged_from, domain, username, password])
self.print_table(data, title='Credential(s)')
@ -229,7 +229,7 @@ class navigator(DatabaseNavigator):
domain = group[1]
name = group[2]
data.append([groupID, domain.decode('utf-8'), name.decode('utf-8')])
data.append([groupID, domain, name])
self.print_table(data, title='Member of Group(s)')
@ -248,7 +248,7 @@ class navigator(DatabaseNavigator):
domain = host[3]
os = host[4]
data.append([hostID, ip, hostname.decode('utf-8'), domain.decode('utf-8'), os])
data.append([hostID, ip, hostname, domain, os])
self.print_table(data, title='Admin Access to Host(s)')

View File

@ -8,121 +8,122 @@ from impacket.dcerpc.v5.dcom import wmi
from impacket.dcerpc.v5.dtypes import NULL
class WMIEXEC:
def __init__(self, target, share_name, username, password, domain, smbconnection, hashes=None, share=None):
self.__target = target
self.__username = username
self.__password = password
self.__domain = domain
self.__lmhash = ''
self.__nthash = ''
self.__share = share
self.__smbconnection = smbconnection
self.__output = None
self.__outputBuffer = ''
self.__share_name = share_name
self.__shell = 'cmd.exe /Q /c '
self.__pwd = 'C:\\'
self.__aesKey = None
self.__doKerberos = False
self.__retOutput = True
def __init__(self, target, share_name, username, password, domain, smbconnection, hashes=None, share=None):
self.__target = target
self.__username = username
self.__password = password
self.__domain = domain
self.__lmhash = ''
self.__nthash = ''
self.__share = share
self.__smbconnection = smbconnection
self.__output = None
self.__outputBuffer = ''
self.__share_name = share_name
self.__shell = 'cmd.exe /Q /c '
self.__pwd = 'C:\\'
self.__aesKey = None
self.__doKerberos = False
self.__retOutput = True
if hashes is not None:
#This checks to see if we didn't provide the LM Hash
if hashes.find(':') != -1:
self.__lmhash, self.__nthash = hashes.split(':')
else:
self.__nthash = hashes
if hashes is not None:
#This checks to see if we didn't provide the LM Hash
if hashes.find(':') != -1:
self.__lmhash, self.__nthash = hashes.split(':')
else:
self.__nthash = hashes
if self.__password is None:
self.__password = ''
if self.__password is None:
self.__password = ''
self.__dcom = DCOMConnection(self.__target, self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, self.__aesKey, oxidResolver = True, doKerberos=self.__doKerberos)
iInterface = self.__dcom.CoCreateInstanceEx(wmi.CLSID_WbemLevel1Login,wmi.IID_IWbemLevel1Login)
iWbemLevel1Login = wmi.IWbemLevel1Login(iInterface)
iWbemServices= iWbemLevel1Login.NTLMLogin('//./root/cimv2', NULL, NULL)
iWbemLevel1Login.RemRelease()
self.__dcom = DCOMConnection(self.__target, self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, self.__aesKey, oxidResolver = True, doKerberos=self.__doKerberos)
iInterface = self.__dcom.CoCreateInstanceEx(wmi.CLSID_WbemLevel1Login,wmi.IID_IWbemLevel1Login)
iWbemLevel1Login = wmi.IWbemLevel1Login(iInterface)
iWbemServices= iWbemLevel1Login.NTLMLogin('//./root/cimv2', NULL, NULL)
iWbemLevel1Login.RemRelease()
self.__win32Process,_ = iWbemServices.GetObject('Win32_Process')
self.__win32Process,_ = iWbemServices.GetObject('Win32_Process')
def execute(self, command, output=False):
self.__retOutput = output
if self.__retOutput:
self.__smbconnection.setTimeout(100000)
def execute(self, command, output=False):
self.__retOutput = output
if self.__retOutput:
self.__smbconnection.setTimeout(100000)
self.execute_handler(command)
self.__dcom.disconnect()
return self.__outputBuffer
self.execute_handler(command)
self.__dcom.disconnect()
return self.__outputBuffer
def cd(self, s):
self.execute_remote('cd ' + s)
if len(self.__outputBuffer.strip('\r\n')) > 0:
print(self.__outputBuffer)
self.__outputBuffer = ''
else:
self.__pwd = ntpath.normpath(ntpath.join(self.__pwd, s))
self.execute_remote('cd ')
self.__pwd = self.__outputBuffer.strip('\r\n')
self.__outputBuffer = ''
def cd(self, s):
self.execute_remote('cd ' + s)
if len(self.__outputBuffer.strip('\r\n')) > 0:
print(self.__outputBuffer)
self.__outputBuffer = ''
else:
self.__pwd = ntpath.normpath(ntpath.join(self.__pwd, s))
self.execute_remote('cd ')
self.__pwd = self.__outputBuffer.strip('\r\n')
self.__outputBuffer = ''
def output_callback(self, data):
self.__outputBuffer += data
def output_callback(self, data):
self.__outputBuffer += data.decode("utf-8")
def execute_handler(self, data):
if self.__retOutput:
try:
self.execute_fileless(data)
except:
self.cd('\\')
self.execute_remote(data)
else:
self.execute_remote(data)
def execute_handler(self, data):
if self.__retOutput:
try:
logging.debug('Executing remote')
self.execute_remote(data)
except:
self.cd('\\')
self.execute_remote(data)
else:
self.execute_remote(data)
def execute_remote(self, data):
self.__output = '\\Windows\\Temp\\' + gen_random_string(6)
def execute_remote(self, data):
self.__output = '\\Windows\\Temp\\' + gen_random_string(6)
command = self.__shell + data
if self.__retOutput:
command += ' 1> ' + '\\\\127.0.0.1\\%s' % self.__share + self.__output + ' 2>&1'
command = self.__shell + data
if self.__retOutput:
command += ' 1> ' + '\\\\127.0.0.1\\%s' % self.__share + self.__output + ' 2>&1'
logging.debug('Executing command: ' + command)
self.__win32Process.Create(command, self.__pwd, None)
self.get_output_remote()
logging.debug('Executing command: ' + command)
self.__win32Process.Create(command, self.__pwd, None)
self.get_output_remote()
def execute_fileless(self, data):
self.__output = gen_random_string(6)
local_ip = self.__smbconnection.getSMBServer().get_socket().getsockname()[0]
def execute_fileless(self, data):
self.__output = gen_random_string(6)
local_ip = self.__smbconnection.getSMBServer().get_socket().getsockname()[0]
command = self.__shell + data + ' 1> \\\\{}\\{}\\{} 2>&1'.format(local_ip, self.__share_name, self.__output)
command = self.__shell + data + ' 1> \\\\{}\\{}\\{} 2>&1'.format(local_ip, self.__share_name, self.__output)
logging.debug('Executing command: ' + command)
self.__win32Process.Create(command, self.__pwd, None)
self.get_output_fileless()
logging.debug('Executing command: ' + command)
self.__win32Process.Create(command, self.__pwd, None)
self.get_output_fileless()
def get_output_fileless(self):
while True:
try:
with open(os.path.join('/tmp', 'cme_hosted', self.__output), 'r') as output:
self.output_callback(output.read())
break
except IOError:
sleep(2)
def get_output_fileless(self):
while True:
try:
with open(os.path.join('/tmp', 'cme_hosted', self.__output), 'r') as output:
self.output_callback(output.read())
break
except IOError:
sleep(2)
def get_output_remote(self):
if self.__retOutput is False:
self.__outputBuffer = ''
return
def get_output_remote(self):
if self.__retOutput is False:
self.__outputBuffer = ''
return
while True:
try:
self.__smbconnection.getFile(self.__share, self.__output, self.output_callback)
break
except Exception as e:
if str(e).find('STATUS_SHARING_VIOLATION') >=0:
# Output not finished, let's wait
sleep(2)
pass
else:
#print str(e)
pass
while True:
try:
self.__smbconnection.getFile(self.__share, self.__output, self.output_callback)
break
except Exception as e:
if str(e).find('STATUS_SHARING_VIOLATION') >=0:
# Output not finished, let's wait
sleep(2)
pass
else:
#print str(e)
pass
self.__smbconnection.deleteFile(self.__share, self.__output)
self.__smbconnection.deleteFile(self.__share, self.__output)

View File

@ -58,14 +58,14 @@ class ssh(connection):
self.conn.connect(self.host, port=self.args.port, username=username, password=password)
self.check_if_admin()
self.logger.success(u'{}:{} {}'.format(username.decode('utf-8'),
password.decode('utf-8'),
self.logger.success(u'{}:{} {}'.format(username,
password,
highlight('({})'.format(self.config.get('CME', 'pwn3d_label')) if self.admin_privs else '')))
return True
except Exception as e:
self.logger.error(u'{}:{} {}'.format(username.decode('utf-8'),
password.decode('utf-8'),
self.logger.error(u'{}:{} {}'.format(username,
password,
e))
return False
@ -74,6 +74,6 @@ class ssh(connection):
stdin, stdout, stderr = self.conn.exec_command(self.args.execute)
self.logger.success('Executed command')
for line in stdout:
self.logger.highlight(line.decode('utf-8').strip())
self.logger.highlight(line.strip())
return stdout

View File

@ -118,17 +118,17 @@ class winrm(connection):
# we could just authenticate without running a command :) (probably)
self.conn.run_cmd('hostname')
self.admin_privs = True
self.logger.success(u'{}\\{}:{} {}'.format(self.domain.decode('utf-8'),
username.decode('utf-8'),
password.decode('utf-8'),
self.logger.success(u'{}\\{}:{} {}'.format(self.domain,
username,
password,
highlight('({})'.format(self.config.get('CME', 'pwn3d_label')) if self.admin_privs else '')))
return True
except Exception as e:
self.logger.error(u'{}\\{}:{} "{}"'.format(self.domain.decode('utf-8'),
username.decode('utf-8'),
password.decode('utf-8'),
self.logger.error(u'{}\\{}:{} "{}"'.format(self.domain,
username,
password,
e))
return False
@ -137,14 +137,14 @@ class winrm(connection):
if response_obj.status_code == 0:
buf = StringIO(response_obj.std_out).readlines()
for line in buf:
self.logger.highlight(line.decode('utf-8').strip())
self.logger.highlight(line.strip())
return response_obj.std_out
else:
buf = StringIO(response_obj.std_err).readlines()
for line in buf:
self.logger.highlight(line.decode('utf-8').strip())
self.logger.highlight(line.strip())
return response_obj.std_err

View File

@ -32,7 +32,7 @@ class CMESMBServer(threading.Thread):
pass
def shutdown(self):
self._Thread__stop()
#self._Thread__stop()
# make sure all the threads are killed
for thread in threading.enumerate():
if thread.isAlive():

@ -1 +1 @@
Subproject commit cb340028808b7a1e802d3ace3d40e8f24a56a6c5
Subproject commit 2dcf64854b5d111b5ee34b891f7a6480569ab993