forked from p15670423/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_use_vbs_download = True
|
||||
|
||||
# smb/wmi exploiter
|
||||
smb_download_timeout = 300 # timeout in seconds
|
||||
|
||||
# system info collection
|
||||
collect_system_info = True
|
||||
|
||||
|
|
|
@ -65,6 +65,7 @@
|
|||
"psexec_user": "Administrator",
|
||||
"range_size": 30,
|
||||
"rdp_use_vbs_download": true,
|
||||
"smb_download_timeout": 300,
|
||||
"retry_failed_explotation": true,
|
||||
"scanner_class": "TcpScanner",
|
||||
"self_delete_in_cleanup": true,
|
||||
|
|
|
@ -2,6 +2,7 @@ from abc import ABCMeta, abstractmethod
|
|||
|
||||
__author__ = 'itamar'
|
||||
|
||||
|
||||
class HostExploiter(object):
|
||||
__metaclass__ = ABCMeta
|
||||
_target_os_type = []
|
||||
|
|
|
@ -79,7 +79,8 @@ class SmbExploiter(HostExploiter):
|
|||
self._config.psexec_user,
|
||||
password,
|
||||
src_path,
|
||||
self._config.dropper_target_path)
|
||||
self._config.dropper_target_path,
|
||||
self._config.smb_download_timeout)
|
||||
|
||||
if remote_full_path is not None:
|
||||
LOG.debug("Successfully logged in %r using SMB (%s : %s)",
|
||||
|
@ -131,6 +132,7 @@ class SmbExploiter(HostExploiter):
|
|||
return False
|
||||
|
||||
smb_conn = rpctransport.get_smb_connection()
|
||||
break
|
||||
|
||||
# We don't wanna deal with timeouts from now on.
|
||||
smb_conn.setTimeout(100000)
|
||||
|
|
|
@ -22,6 +22,7 @@ from impacket.dcerpc.v5.dtypes import NULL
|
|||
class DceRpcException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
__author__ = 'itamar'
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
@ -111,7 +112,6 @@ class WmiTools(object):
|
|||
DCOMConnection.PINGTIMER.join()
|
||||
DCOMConnection.PINGTIMER = None
|
||||
|
||||
|
||||
@staticmethod
|
||||
def get_object(wmi_connection, object_name):
|
||||
assert isinstance(wmi_connection, WmiTools.WmiConnection)
|
||||
|
@ -132,7 +132,7 @@ class WmiTools(object):
|
|||
wql_query = "SELECT %s FROM %s" % (fields_query, object_name)
|
||||
|
||||
if where:
|
||||
wql_query += " WHERE %s" % (where, )
|
||||
wql_query += " WHERE %s" % (where,)
|
||||
|
||||
LOG.debug("Execution WQL query: %r", wql_query)
|
||||
|
||||
|
@ -166,13 +166,13 @@ class WmiTools(object):
|
|||
|
||||
class SmbTools(object):
|
||||
@staticmethod
|
||||
def copy_file(host, username, password, src_path, dst_path):
|
||||
assert monkeyfs.isfile(src_path), "Source file to copy (%s) is missing" % (src_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,)
|
||||
|
||||
config = __import__('config').WormConfiguration
|
||||
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:
|
||||
return None
|
||||
|
||||
|
@ -183,7 +183,8 @@ class SmbTools(object):
|
|||
|
||||
try:
|
||||
smb.logoff()
|
||||
except: pass
|
||||
except:
|
||||
pass
|
||||
|
||||
return None
|
||||
|
||||
|
@ -236,9 +237,9 @@ class SmbTools(object):
|
|||
'share_path': share_path}
|
||||
|
||||
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
|
||||
|
||||
|
@ -248,7 +249,7 @@ class SmbTools(object):
|
|||
share_path = share['share_path']
|
||||
|
||||
if not smb:
|
||||
smb, _ = SmbTools.new_smb_connection(host, username, password)
|
||||
smb, _ = SmbTools.new_smb_connection(host, username, password, timeout)
|
||||
if not smb:
|
||||
return None
|
||||
|
||||
|
@ -271,7 +272,7 @@ class SmbTools(object):
|
|||
if file_info:
|
||||
if src_file_size == file_info[0].get_filesize():
|
||||
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")
|
||||
except:
|
||||
|
@ -279,6 +280,8 @@ class SmbTools(object):
|
|||
|
||||
try:
|
||||
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)
|
||||
|
||||
file_uploaded = True
|
||||
|
@ -308,7 +311,7 @@ class SmbTools(object):
|
|||
return remote_full_path
|
||||
|
||||
@staticmethod
|
||||
def new_smb_connection(host, username, password):
|
||||
def new_smb_connection(host, username, password, timeout=60):
|
||||
try:
|
||||
smb = SMBConnection(host.ip_addr, host.ip_addr, sess_port=445)
|
||||
except Exception, exc:
|
||||
|
@ -334,6 +337,7 @@ class SmbTools(object):
|
|||
host, username, password, exc)
|
||||
return None, dialect
|
||||
|
||||
smb.setTimeout(timeout)
|
||||
return smb, dialect
|
||||
|
||||
@staticmethod
|
||||
|
@ -341,7 +345,7 @@ class SmbTools(object):
|
|||
dce = SmbTools.get_dce_bind(smb)
|
||||
rpc_method_wrapper = getattr(srvs, rpc_func, None)
|
||||
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)
|
||||
|
||||
|
@ -396,7 +400,7 @@ def get_target_monkey(host):
|
|||
if not monkey_path:
|
||||
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 (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():
|
||||
monkey_path = sys.executable
|
||||
|
||||
|
@ -425,5 +429,4 @@ def report_failed_login(exploiter, machine, user, password):
|
|||
from control import ControlClient
|
||||
ControlClient.send_telemetry('exploit', {'result': False, 'machine': machine.__dict__,
|
||||
'exploiter': exploiter.__class__.__name__,
|
||||
'user':user,'password':password})
|
||||
|
||||
'user': user, 'password': password})
|
||||
|
|
|
@ -81,7 +81,8 @@ class WmiExploiter(HostExploiter):
|
|||
self._config.psexec_user,
|
||||
password,
|
||||
src_path,
|
||||
self._config.dropper_target_path)
|
||||
self._config.dropper_target_path,
|
||||
self._config.smb_download_timeout)
|
||||
|
||||
if not remote_full_path:
|
||||
wmi_connection.close()
|
||||
|
|
Loading…
Reference in New Issue