def __init__(self, config_path=None): path = os.getenv('FIBRATUS_CONFIG_PATH', __DEFAULT_CONFIG_PATH__) path = config_path or path try: self._yaml = anyconfig.load(path, ignore_missing=False) except FileNotFoundError: IO.write_console('ERROR - %s configuration file does not exist' % path) sys.exit()
def __init__(self, filament, **kwargs): try: log_path = os.path.join(os.path.expanduser('~'), '.fibratus', 'fibratus.log') FileHandler(log_path, mode='w+').push_application() except PermissionError: IO.write_console("ERROR - Unable to open log file for writing due to permission error") sys.exit(0) self.logger = Logger(Fibratus.__name__) self._config = YamlConfig() self.logger.info('Starting fibratus...') self.kevt_streamc = KEventStreamCollector(etw.KERNEL_LOGGER_NAME.encode()) self.kcontroller = KTraceController() self.ktrace_props = KTraceProps() self.ktrace_props.enable_kflags() self.ktrace_props.logger_name = etw.KERNEL_LOGGER_NAME enum_handles = kwargs.pop('enum_handles', True) self.handle_repository = HandleRepository() self._handles = [] # query for handles on the # start of the kernel trace if enum_handles: self.logger.info('Enumerating system handles...') self._handles = self.handle_repository.query_handles() self.logger.info('%s handles found' % len(self._handles)) self.handle_repository.free_buffers() self.thread_registry = ThreadRegistry(self.handle_repository, self._handles) self.kevent = KEvent(self.thread_registry) self.keventq = Queue() self._adapter_classes = dict(smtp=SmtpAdapter, amqp=AmqpAdapter) self._output_adapters = self._construct_adapters() if filament: filament.keventq = self.keventq filament.logger = log_path filament.setup_adapters(self._output_adapters) self._filament = filament self.fsio = FsIO(self.kevent, self._handles) self.hive_parser = HiveParser(self.kevent, self.thread_registry) self.tcpip_parser = TcpIpParser(self.kevent) self.dll_repository = DllRepository(self.kevent) self.output_kevents = {} self.filters_count = 0
def render(self): """Renders the kevent to standard output stream. Uses the default output format to render the kernel event to standard output stream. The default output format is as follows: id timestamp cpu process (process id) - kevent (parameters) -- --------- --- ------- ----------- ------- ------------ Example: 160 13:27:27.554 0 wmiprvse.exe (1012) - CloseFile (file=C:\\WINDOWS\\SYSTEM32\\RSAENH.DLL, tid=2668) """ self._thread = self.thread if self._thread: kevt = RENDER_FORMAT % (self._id, self._ts.time(), self._cpuid, self._thread.name, self._thread.pid, self._name, self._format_params()) else: # figure out the process id from thread # if the process can't be found in # thread registry pid = NA if self._pid is None: if self._tid: # get the thread handle handle = open_thread(THREAD_QUERY_INFORMATION, False, self._tid) if handle: pid = get_process_id_of_thread(handle) close_handle(handle) else: pid = self._pid kevt = RENDER_FORMAT % (self._id, self._ts.time(), self._cpuid, NA, pid, self._name, self._format_params()) IO.write_console(kevt) self._id += 1
def render(self): """Renders the kevent to standard output stream. Uses the default output format to render the kernel event to standard output stream. The default output format is as follows: id timestamp cpu process (process id) - kevent (parameters) -- --------- --- ------- ----------- ------- ------------ Example: 160 13:27:27.554 0 wmiprvse.exe (1012) - CloseFile (file=C:\\WINDOWS\\SYSTEM32\\RSAENH.DLL, tid=2668) """ self._thread = self.thread if self._thread: kevt = RENDER_FORMAT % (self._id, self._ts.time(), self._cpuid, self._thread.name, self._thread.pid, self._name, self._format_params()) else: # figure out the process id from thread # if the process can't be found in # thread registry pid = NA if self._pid is None: if self._tid: # get the thread handle handle = open_thread(THREAD_QUERY_INFORMATION, False, self._tid) if handle: pid = get_process_id_of_thread(handle) close_handle(handle) else: pid = self._pid kevt = RENDER_FORMAT % (self._id, self._ts.time(), self._cpuid, NA, pid, self._name, self._format_params()) IO.write_console(kevt) self._id += 1
def render_tabular(self): """Renders the table to the console. """ if len(self._cols) > 0: tabular = self._tabular.get_string(start=1, end=self._limit) if self._sort_by: tabular = self._tabular.get_string(start=1, end=self._limit, sortby=self._sort_by, reversesort=self._sort_desc) self._tabular.clear_rows() if not _ansi_term.term_ready: try: _ansi_term.setup_console() except TermInitializationError: IO.write_console( 'fibratus run: ERROR - console initialization failed') _ansi_term.cls() _ansi_term.write_output(tabular)
def start_ktrace(self, name, kprops): """Starts a new trace. Parameters --------- name: str the name for the trace session kprops: KTraceProps an instance of the kernel trace properties """ self._trace_name = name handle = TRACEHANDLE() kp = kprops.get() status = start_trace(byref(handle), self._trace_name, kp) self._handle = handle if status == ERROR_ALREADY_EXISTS: # the kernel logger trace session # is already running. Restart the trace. self.stop_ktrace() status = start_trace(byref(handle), self._trace_name, kp) if status != ERROR_SUCCESS: raise FibratusError('Unable to start fibratus') self._handle = handle elif status == ERROR_ACCESS_DENIED: # insufficient privileges IO.write_console("ERROR - You don't have administrative privileges. Stopping fibratus...") sys.exit() elif status == ERROR_BAD_LENGTH: raise FibratusError('Incorrect buffer size for the trace buffer') elif status == ERROR_INVALID_PARAMETER: raise FibratusError('Invalid trace handle or provider GUID') elif status != ERROR_SUCCESS: raise FibratusError('Unable to start fibratus')
def load_filament(self, name): if not os.path.exists(FILAMENTS_DIR): IO.write_console('fibratus run: ERROR - filaments path %s does not exist.' % FILAMENTS_DIR) sys.exit(0) [filament_path] = [os.path.join(FILAMENTS_DIR, filament) for filament in os.listdir(FILAMENTS_DIR) if filament.endswith('.py') and name == filament[:-3]] or [None] if filament_path: loader = SourceFileLoader(name, filament_path) self._filament = loader.load_module() # check for required methods # on the filament module doc = inspect.getdoc(self._filament) if not doc: raise FilamentError("Please provide a short description for the filament") [on_next_kevent] = self._find_func('on_next_kevent') if on_next_kevent: args_spec = inspect.getargspec(on_next_kevent) if len(args_spec.args) != 1: raise FilamentError('Missing one argument on_next_kevent method on filament') else: raise FilamentError('Missing required on_next_kevent method on filament') else: raise FilamentError('%s filament not found' % name)
def _assert_root_dir(cls): if not os.path.exists(FILAMENTS_DIR): IO.write_console('fibratus run: ERROR - %s path does not exist.' % FILAMENTS_DIR) sys.exit(0)
def on_kstream_open(): if self._filament is None: IO.write_console('Done! ')
def stop_ktrace(self): IO.write_console('Stopping fibratus...') if self._filament: self._filament.close() self.kcontroller.stop_ktrace(self.ktrace_props) self.kevt_streamc.close_kstream()
def test_write_console_same_line(self, byref_mock, write_console_unicode_mock): IO._stdout_handle = 10 IO.write_console('Fibratus', False) write_console_unicode_mock.assert_called_with(10, 'Fibratus\r', 9, 8, None)
def _check_kevent(kevent): if not kevent in KEvents.all(): IO.write_console('fibratus run: ERROR - %s is not a valid kernel event. Run list-kevents to see' ' the available kernel events' % kevent) sys.exit() if __name__ == '__main__': if args['run']: if len(kevent_filters) > 0 and not filament_name: for kfilter in kevent_filters: _check_kevent(kfilter) filament = None filament_filters = [] if not filament_name: IO.write_console('Starting fibratus...', False) else: if not Filament.exists(filament_name): IO.write_console('fibratus run: ERROR - %s filament does not exist. Run list-filaments to see' ' the availble filaments' % filament_name) sys.exit() filament = Filament() try: filament.load_filament(filament_name) except FilamentError as e: IO.write_console('fibratus run: ERROR - %s' % e) sys.exit() filament.initialize_filament() filament_filters = filament.filters
def stop_ktrace(self): IO.write_console('Stopping fibratus...') if self._filament: self._filament.close() self.kcontroller.stop_ktrace(self.ktrace_props) self.kevt_streamc.close_kstream()
def _assert_root_dir(cls): if not os.path.exists(FILAMENTS_DIR): IO.write_console('fibratus run: ERROR - %s path does not exist.' % FILAMENTS_DIR) sys.exit(0)
def main(): if args['run']: if len(kevent_filters) > 0 and not filament_name: for kfilter in kevent_filters: _check_kevent(kfilter) enum_handles = False if args['--no-enum-handles'] else True cswitch = True if args['--cswitch'] else False filament = None filament_filters = [] if not filament_name: IO.write_console('Starting fibratus...', False) else: if not Filament.exists(filament_name): IO.write_console( 'fibratus run: ERROR - %s filament does not exist. Run list-filaments to see ' 'the availble filaments' % filament_name) sys.exit() filament = Filament() try: filament.load_filament(filament_name) except FilamentError as e: IO.write_console('fibratus run: ERROR - %s' % e) sys.exit() filament_filters = filament.filters if len(filament_filters) > 0: for kfilter in filament_filters: _check_kevent(kfilter) filament.render_tabular() try: fibratus = Fibratus(filament, enum_handles=enum_handles, cswitch=cswitch) except KeyboardInterrupt: # the user has stopped command execution # before opening the kernel event stream sys.exit(0) @PHANDLER_ROUTINE def handle_ctrl_c(event): if event == 0: fibratus.stop_ktrace() return 0 set_console_ctrl_handler(handle_ctrl_c, True) if not filament: if len(kevent_filters) > 0: fibratus.add_filters(kevent_filters) else: if len(filament_filters) > 0: fibratus.add_filters(filament_filters) else: fibratus.add_filters([]) try: fibratus.run() except KeyboardInterrupt: set_console_ctrl_handler(handle_ctrl_c, False) elif args['list-filaments']: filaments = Tabular(['Filament', 'Description'], 'Description', sort_by='Filament') for filament, desc in Filament.list_filaments().items(): filaments.add_row([filament, desc]) filaments.draw() elif args['list-kevents']: kevents = Tabular(['KEvent', 'Category', 'Description'], 'Description', sort_by='Category') for kevent, meta in KEvents.meta_info().items(): kevents.add_row([kevent, meta[0].name, meta[1]]) kevents.draw()
def _check_kevent(kevent): if kevent not in KEvents.all(): IO.write_console( 'fibratus run: ERROR - %s is not a valid kernel event. Run list-kevents to see' ' the available kernel events' % kevent) sys.exit()
def test_write_console_unicode(self): IO.write_console('aaaàçççñññ skräms inför på fédéra')
def on_kstream_open(): if self._filament is None: IO.write_console('Done! ')
def draw(self): IO.write_console(self.get_string())
def _check_kevent(kevent): if not kevent in KEvents.all(): IO.write_console('fibratus run: ERROR - %s is not a valid kernel event. Run list-kevents to see' ' the available kernel events' % kevent) sys.exit()
IO.write_console( 'fibratus run: ERROR - %s is not a valid kernel event. Run list-kevents to see' ' the available kernel events' % kevent) sys.exit() if __name__ == '__main__': if args['run']: if len(kevent_filters) > 0 and not filament_name: for kfilter in kevent_filters: _check_kevent(kfilter) filament = None filament_filters = [] if not filament_name: IO.write_console('Starting fibratus...', False) else: if not Filament.exists(filament_name): IO.write_console( 'fibratus run: ERROR - %s filament does not exist. Run list-filaments to see' ' the availble filaments' % filament_name) sys.exit() filament = Filament() try: filament.load_filament(filament_name) except FilamentError as e: IO.write_console('fibratus run: ERROR - %s' % e) sys.exit() filament.initialize_filament() filament_filters = filament.filters