def __init__(self, project_name=None): self.show_banner() self.logger = Logger(level='DEBUG', module=self.__module__) if project_name is not None: BphSession.project_name = project_name else: raise BphSessionNameException('Session Name was not provided') try: sample_abs_path = sys.argv[1] except IndexError: self.logger.log('Starting session without setting up a sample file...') else: self.tmp_sample_abs_path = sample_abs_path self.logger.log('Setting sample: {}'.format(self.tmp_sample_abs_path)) BphSession.sample_md5 = LabFile.md5hash(self.tmp_sample_abs_path) # Session files, folders and identifiers here. self.project_folder = os.path.join(BPH_USER_DATA, BphSession.project_name) self.session_log_file = os.path.join(self.project_folder, 'session.log') self.launcher_folder = os.path.join(self.project_folder, 'launcher') self.project_folder_check() if BphSession.sample_md5 == '': self.sid_folder = os.path.join(BPH_USER_DATA, BphSession.project_name, '', BphSession.sid) else: self.sid_folder = os.path.join(BPH_USER_DATA, BphSession.project_name, BphSession.sample_md5, BphSession.sid) BphSession.sample_folder = os.path.join(BPH_USER_DATA, BphSession.project_name, BphSession.sample_md5) BphSession.sid_folder = self.sid_folder # Create session directory if doesn't exist. Directory(self.sid_folder).check_and_create()
class BphDirectory(BphFileSystem): def __init__(self, directory): self.directory = directory self.logger = Logger(level='INFO', module=self.__module__) def check_and_create(self): self.logger.log(f"Verifying directory existence: {self.directory}", level='DEBUG') try: if os.path.isdir(self.directory): self.logger.log(f"Directory ({self.directory}) exists.", level='DEBUG') else: self.logger.log(f"Creating directory: {self.directory}", level='DEBUG') os.makedirs(self.directory, 0o777, exist_ok=True) except OSError: raise
def __init__(self): self.logger = Logger(level='INFO', module=self.__module__) client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.client_socket = client_socket self.vm_data = None self.connection_status = False
class BphVmControl(BphVm): def __init__(self): self.logger = Logger(level='INFO', module=self.__module__) client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.client_socket = client_socket self.vm_data = None self.connection_status = False def __client_connector(self): try: self.client_socket.connect( (BPH_VIRTUALBOX_SERVER_IP, BPH_VIRTUALBOX_SERVER_PORT)) except socket.error: self.logger.log( "Can't connect to VM manager. Attempting in 5 seconds") time.sleep(5) self.__client_connector() else: self.logger.log('Connected...!') self.connection_status = True def send_data(self): if self.connection_status: if self.vm_data is not None: self.logger.log('Sending: {}'.format(self.vm_data)) self.client_socket.send(bytes(self.vm_data, 'ascii')) while True: self.logger.log('Awaiting response from Agent...') time.sleep(3) data = self.client_socket.recv(128) if b"OK" in data: self.logger.log('Data received from Agent => OK') self.logger.log(data, level='DEBUG') break def __update_cmd(self, action): self.logger.log('Updating cmd action to: {}'.format(action), level='DEBUG') self._vm_data['action'] = action self.vm_data = "|".join([ self._vm_data['action'], self._vm_data['vm_id'], self._vm_data['snapshot_id'], self._vm_data['network_id'] ]) self.logger.log('New VM Data: {}'.format(self.vm_data)) def set_vm(self, exec_type, network_id=None): _exec_type = "".join(exec_type.split('_')) self.logger.log(f'[{exec_type}] VM Analysis was selected') data = {} for vm_data in BphVm.vm_config.VIRTUALMACHINES: if _exec_type in vm_data: if exec_type not in BphVm.vm_config.VIRTUALMACHINES[vm_data]: _vm_data = BphVm.vm_config.VIRTUALMACHINES[vm_data] if "machineid" in vm_data: vm_id = _vm_data self.logger.log(f"VmId: {vm_id}", level='INFO') data['vm_id'] = vm_id if "snapshotid" in vm_data: snapshot_id = _vm_data self.logger.log(f"SnapshotId: {snapshot_id}", level='INFO') data['snapshot_id'] = snapshot_id if "networkconnection" in vm_data: net_id = _vm_data self.logger.log(f"NetworkConnectionId: {net_id}", level='INFO') if network_id is not None: data['network_id'] = str(network_id) else: data['network_id'] = net_id self._vm_data = data self.logger.log('VM Data: {}'.format(self._vm_data)) self.__client_connector() def start(self): self.logger.log('Starting VM') self.__update_cmd('start') self.send_data() if self.connection_status: self.logger.log('VM Started OK.') time.sleep(5) def stop(self): self.logger.log('Stopping VM') self.__update_cmd('stop') self.send_data() if not self.connection_status: self.logger.log('VM Shutdown OK') time.sleep(2)
def __init__(self): self.logger = Logger(level='INFO', module=self.__module__) self.thread_flag = False self._scan_bph_tmp_file(clean=True)
class BphTemplateServer(BphToolTemplateExecutor): BphToolTemplateExecutor.server_status = False BphToolTemplateExecutor.template_delivered = False def __init__(self): self.logger = Logger(level='INFO', module=self.__module__) self.thread_flag = False self._scan_bph_tmp_file(clean=True) def start(self): self.logger.log('Initializing BLACKPHENIX C&C Template Server...') try: serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) except socket.error as e: self.logger.log('Initialization Socket Error: {e}'.format(e.errno), level='DEBUG') else: self._socket_handle = serversocket self.logger.log('Socket Ready') self._socket_handle.bind( (BPH_TEMPLATE_SERVER_IP, BPH_TEMPLATE_SERVER_PORT)) self.logger.log('Starting server listener..') self._socket_handle.listen(0) self.logger.log('Accepting new connections now....') self.thread = threading.Thread(target=self.accept_connections, daemon=True) self.thread.start() def __cleanup(self, template_file): if os.path.isfile(template_file): self.logger.log('Removing template file: {}'.format(template_file), level='DEBUG') try: os.remove(template_file) except OSError: self.logger.log( 'Error while deleting the file: {}'.format(template_file), level='DEBUG') else: self.logger.log('File deleted: {}'.format(template_file), level='DEBUG') def accept_connections(self): while True: try: # Accepting connections from Agent clientsocket, addr = self._socket_handle.accept() if clientsocket: BphToolTemplateExecutor.server_status = True self.logger.log(f"Agent connected: {addr}") # Continuous scan for temporary template files while True: self.logger.log('Agent Loop...', level='DEBUG') time.sleep(1) template_file = self._scan_bph_tmp_file() self.logger.log( 'Template File: {}'.format(template_file), level='DEBUG') if template_file is not None: if os.path.isfile(template_file): self.logger.log( 'Template: {}'.format(template_file), level='DEBUG') self.send_template(template_file, clientsocket) template_file = None except (BrokenPipeError): self.logger.log('Agent down? Running server once again...') BphToolTemplateExecutor.server_status = False self.accept_connections() def send_template(self, template_file, clientsocket): self.logger.log('Delivering Template', level='DEBUG') BphToolTemplateExecutor.template_delivered = False # If temp template is found, send it to agent if os.path.isfile( template_file) and os.path.getsize(template_file) != 0: self.logger.log('Sending template...') self.logger.log(template_file, level='DEBUG') # Temp file is a Boxed & Pickled data tmp_file = open(template_file, 'rb') dat = tmp_file.read() clientsocket.send(dat) tmp_file.close() self.logger.log('Waiting response from client...') if clientsocket.recv(128) == b"ok": self.logger.log('Template was delivered correctly') self.__cleanup(template_file) BphToolTemplateExecutor.template_delivered = True else: self.logger.log('Template was not delivered correctly.') time.sleep(5) def stop(self): self.logger.log('Stopping Template server...') self._socket_handle.close() def restart(self): self.logger.log('Restarting Template Server') self.stop() self.start()
def __init__(self, directory): self.directory = directory self.logger = Logger(level='INFO', module=self.__module__)
class BphSession: # Class variables are being used when a template is generated project_name = "" sample_md5 = "" sid = "" sid_folder = "" sample_folder = "" launcher_abs_path = "" def __init__(self, project_name=None): self.show_banner() self.logger = Logger(level='DEBUG', module=self.__module__) if project_name is not None: BphSession.project_name = project_name else: raise BphSessionNameException('Session Name was not provided') try: sample_abs_path = sys.argv[1] except IndexError: self.logger.log('Starting session without setting up a sample file...') else: self.tmp_sample_abs_path = sample_abs_path self.logger.log('Setting sample: {}'.format(self.tmp_sample_abs_path)) BphSession.sample_md5 = LabFile.md5hash(self.tmp_sample_abs_path) # Session files, folders and identifiers here. self.project_folder = os.path.join(BPH_USER_DATA, BphSession.project_name) self.session_log_file = os.path.join(self.project_folder, 'session.log') self.launcher_folder = os.path.join(self.project_folder, 'launcher') self.project_folder_check() if BphSession.sample_md5 == '': self.sid_folder = os.path.join(BPH_USER_DATA, BphSession.project_name, '', BphSession.sid) else: self.sid_folder = os.path.join(BPH_USER_DATA, BphSession.project_name, BphSession.sample_md5, BphSession.sid) BphSession.sample_folder = os.path.join(BPH_USER_DATA, BphSession.project_name, BphSession.sample_md5) BphSession.sid_folder = self.sid_folder # Create session directory if doesn't exist. Directory(self.sid_folder).check_and_create() #self.collect_session_files() def show_banner(self): logo = r""" ____ __ ___ ________ __ ____ __ _________ _______ __ / __ )/ / / | / ____/ //_// __ \/ / / / ____/ | / / _/ |/ / / __ / / / /| |/ / / ,< / /_/ / /_/ / __/ / |/ // / | / / /_/ / /___/ ___ / /___/ /| |/ ____/ __ / /___/ /| // / / | /_____/_____/_/ |_\____/_/ |_/_/ /_/ /_/_____/_/ |_/___//_/|_| -=[v.1.0.0]=- MALWARE ANALYSIS + AUTOMATION FRAMEWORK Developed by Chris Navarrete @ FortiGuard Labs Copyright (c) 2019 Fortinet, Inc. Contact: [email protected] """ print(colored(logo, 'green', attrs=['bold'])) def project_folder_check(self): if os.path.isdir(self.project_folder): self.logger.log('Project folder already exists', level='DEBUG') if os.path.isfile(self.session_log_file): self.logger.log('Session log already exists', level='DEBUG') self.session_log(action='read') else: self.logger.log('Generating sid...', level='DEBUG') BphSession.sid = self.generate_session_id() self.logger.log('Session ID: {}'.format(self.sid)) @staticmethod def get_session_id(): return BphSession.sid def generate_session_id(self): return str(uuid.uuid4()) def session_log(self, action=None): if action == 'write': try: self.logger.log('Writing Session file...', level='DEBUG') log_file = open(self.session_log_file, 'w+') log_file.write(self.sid) except IOError: self.logger.log('Error when writing session log file', level='DEBUG') else: if os.path.isfile(self.session_log_file): self.logger.log('Saved SessionID: {}'.format(self.sid), level='DEBUG') self.logger.log(self.session_log_file, level='DEBUG') elif action == 'read': try: log_file = open(self.session_log_file, 'r') BphSession.sid = log_file.readline() log_file.close() except IOError: self.logger.log('Error when reading the log file.', level='DEBUG') else: self.logger.log('Stored SessionID: {}'.format(self.sid), level='DEBUG') def set_launcher(self, move_sample=True): try: if not os.path.isdir(self.launcher_folder): os.mkdir(self.launcher_folder) sample_file_set = os.path.join(self.launcher_folder, os.path.split(self.tmp_sample_abs_path)[1]) if not os.path.isfile(sample_file_set): if move_sample: self.logger.log('MOVING SAMPLE', level='INFO') shutil.move(self.tmp_sample_abs_path, self.launcher_folder) else: self.logger.log('COPYING SAMPLE', level='INFO') shutil.copy(self.tmp_sample_abs_path, self.launcher_folder) except shutil.Error as e: self.logger.log('Error when copying the sample file: {}'.format(e), level='DEBUG') raise else: BphSession.launcher_abs_path = os.path.join(self.launcher_folder, os.path.basename(sample_file_set)) def start(self): self.logger.log('Starting session: {}'.format(self.project_name)) if os.path.isdir(self.project_folder): self.logger.log('Session folder OK', level='DEBUG') if os.path.isfile(self.session_log_file): self.logger.log('Session Log file OK', level='DEBUG') # Checking if file is empty with open(self.session_log_file, 'r') as lf: if len(lf.readline()) == 0: self.session_log(action='write') else: self.session_log(action='read') else: self.logger.log('No session folder. Creating one...', level='DEBUG') self.session_log(action='write') def stop(self): self.logger.log('Stopping session: {}'.format(self.session_log_file)) os.remove(self.session_log_file) def collect_session_files(self, tool_name=None): session_files = [] for root, dirs, files in os.walk(self.sid_folder): if len(dirs) == 0 and len(files) != 0: for file in files: file_abs_path = os.path.join(root, file) if tool_name is not None: if tool_name in file: print('Filtered: {}'.format(file_abs_path)) if file not in session_files: session_files.append(file_abs_path) else: print('Unfiltered: {}'.format(file_abs_path)) if file_abs_path not in session_files: session_files.append(file_abs_path) return session_files