Filaments are scheduled as independent Python Virtual Machines and thus they have their own memory and other resources allocated. Fibratus takes as an input a Python module consisting of various functions and converts them into a running instance of the Python interpreter that knows how to process incoming kernel events. It also augments the Python module with numerous functions that permit a filament to interact with alerts and other state exposed by Fibratus.
The backbone of a filament is the on_next_kevent
function. It's executed whenever a new kernel event arrives. The parameter of this function is the Python dictionary that contains event data. Here is the structure of such a dictionary object:
{
'seq': 122344,
'pid': 2034,
'tid': 2453,
'ppid': 45,
'cwd': 'C:\Windows\system32',
'exe': 'cmd.exe',
'comm': 'cmd.exe rm /r',
'sid': 'archrabbit\SYSTEM',
'cpu': 2,
'name': 'CreateFile',
'category': 'file',
'timestamp': '2013-08-23 16:15:13.4323',
'host': 'archrabbit',
'description': 'Creates or opens a file or I/O device',
'kparams': {
'file_name': 'C:\WINDOWS\system32\config\systemprofile\AppData\WindowsApps\',
'file_object': 'ffffa88c7ea077d0',
'irp': 'ffffa88c746b2a88',
'operation': 'supersede',
'share_mask': 'rw-',
'type': 'directory'
}
}
For a more convenient dictionary accesses, you can annotate the function with the dotdictify
decorator.
from utils.dotdict import dotdictify
@dotdictify
def on_next_kevent(kevent):
print(f'{kevent.name} generated by {kevent.exe}')
If the on_init
function is declared in the filament, any logic wrapped inside this function is executed prior to event processing. This is a convenient place for configuring the table columns or establishing the on_interval
function triggering intervals among other initialization tasks.
def on_init():
interval(1)
The on_stop
function is called right before the Python interpreter is teared down. You can place any code you would like to get executed when the filament is stopped.
def on_stop():
f.close()
Filament has built-in support for scheduling timers. The timer, associated with the on_interval
function, is fired after the interval specified by the interval
function elapses. The minimum interval granularity is one second.
def on_interval():
for ip, count in __connections__.copy().items():
f.write(f'{ip.count}')
The kfilter
function defines a filter expression for the life span of a filament. Filaments give an appealing approach for constructing the filters dynamically. For example, this following code snippet defines a filter from the list:
kfilter("ps.name in (%s)" % (', '.join([f'\'{ps}\'' for ps in __procs__])))
Filaments are able to render tabular data on the console in a flicker-free fashion by using the frame buffers. To render a table, you start by defining the columns with the columns
function. It's possible to sort the data by specifying the column via sort_by
function. Finally, the add_row
function appends rows to the table. When you're ready to draw the table, invoke the render_table
function.
def on_init():
columns(["Source", "Count"])
sort_by('Count')
interval(1)
def on_interval():
for ip, count in __connections__.copy().items():
add_row([ip, count])
render_table()
Fibratus bundles embedded Python 3.7 distribution. Installing additional packages can be achieved by running the pip
command from the %PROGRAM FILES%\Fibratus\Python\Scripts
directory.