Let's look at some design concepts.
Detector provides a common interface for loading eBPF programs, initializing maps and attaching programs to hook points. All detector programs are viewed externally as a single entity that delivers events. EBPF part of detectors is located here. User mode part is here. Detectors also can provide information not only for user but for other detectors storing it in maps. Some parts of the detectors can be reused across different detectors. Detectors submit events to user space using ring buffer. Detectors use YAML config files for initialization.
Monitor observes new low level events (messages) and extracts them from ring buffer.
Transmuter converts (transmutes) low kernel event into serializable (json, for example) data structure. It also can enrich kernel event with some user mode data.
Transmitter sends serialized events (byte arrays) to different sources (unix socket, stdout, file, etc).
Config holds global agent configuration. It also have list of the detectors to load during start up.
Registry stores loaded detectors. It can load/unload detectors and possibly interact with them (change config maps).
GTFOBins detector tries to detect GTFOBins execution. It checks if privileged binary is executed and returns the binary name with command line args as an event. List of GTFOBins is provided in YAML config.
HistFile detector's goal is to detect cases when user stops writing bash
history to ~/.bash_history
. It can be done using this commands:
export HISTFILESIZE=0
export HISTSIZE=0
Detector attaches to /bin/bash
readline
func with uretprobe and uses lpm_trie
map to check for commands above.