summaryrefslogtreecommitdiff
path: root/src/proc_connector.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/proc_connector.c')
-rw-r--r--src/proc_connector.c758
1 files changed, 758 insertions, 0 deletions
diff --git a/src/proc_connector.c b/src/proc_connector.c
new file mode 100644
index 0000000..f771ecf
--- /dev/null
+++ b/src/proc_connector.c
@@ -0,0 +1,758 @@
+
+#include <string.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <limits.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+
+#include <linux/cn_proc.h>
+#include <linux/netlink.h>
+#include <linux/connector.h>
+
+#include "net.h"
+#include "json.h"
+#include "error.h"
+#include "output.h"
+#include "md5.h"
+#include "sha256.h"
+#include "base64.h"
+#include "proc.h"
+#include "agent_context.h"
+#include "proc_ledger.h"
+#include "time_common.h"
+#include "string_common.h"
+#include "proc_connector.h"
+
+extern unsigned long maxsize;
+
+
+static void handle_proc_connector_message(struct cn_msg *cn_message, agent_context_t *ctx) {
+ struct proc_event *event;
+ json_t json = {0};
+ pid_t process;
+ struct proc_ledger_entry *entry;
+
+ event = (struct proc_event *)cn_message->data;
+
+ switch (event->what) {
+ case PROC_EVENT_NONE:
+ break;
+
+ case PROC_EVENT_FORK:
+ pid_t child = event->event_data.fork.child_pid;
+
+ entry = proc_ledger_entry_create(child, ctx);
+ if (entry) {
+ proc_ledger_add(ctx->proc_ledger, entry);
+ }
+ json = handle_PROC_EVENT_FORK(event, ctx);
+ break;
+
+ case PROC_EVENT_EXEC:
+ process = event->event_data.exec.process_pid;
+ entry = proc_ledger_entry_create(process, ctx);
+
+ if (entry) {
+ proc_ledger_replace(ctx->proc_ledger, entry);
+
+ json = handle_PROC_EVENT_EXEC(event, ctx);
+
+ json_t environment = handle_PROC_EVENT_EXEC_environment(event, ctx);
+ if (environment.data) {
+ output(json_get(&environment));
+ json_free(&environment);
+ }
+ }
+ break;
+
+ case PROC_EVENT_EXIT:
+ process = event->event_data.exit.process_pid;
+ json = handle_PROC_EVENT_EXIT(event, ctx);
+ proc_ledger_remove(ctx->proc_ledger, process);
+ break;
+
+ case PROC_EVENT_UID:
+ // update ledger with new UIDs
+ entry = proc_ledger_find(ctx->proc_ledger, event->event_data.id.process_pid);
+ if (entry) {
+ int old_ruid = entry->uid;
+ int old_euid = entry->euid;
+ entry->uid = event->event_data.id.r.ruid;
+ entry->euid = event->event_data.id.e.euid;
+ json = handle_PROC_EVENT_UID(event, ctx, old_ruid, old_euid);
+ } else {
+ json = handle_PROC_EVENT_UID(event, ctx, -1, -1);
+ }
+ break;
+
+ case PROC_EVENT_GID:
+ // update ledger with new GIDs
+ entry = proc_ledger_find(ctx->proc_ledger, event->event_data.id.process_pid);
+ if (entry) {
+ int old_rgid = entry->gid;
+ int old_egid = entry->egid;
+ entry->gid = event->event_data.id.r.rgid;
+ entry->egid = event->event_data.id.e.egid;
+ json = handle_PROC_EVENT_GID(event, ctx, old_rgid, old_egid);
+ } else {
+ json = handle_PROC_EVENT_GID(event, ctx, -1, -1);
+ }
+ break;
+
+ case PROC_EVENT_PTRACE:
+ json = handle_PROC_EVENT_PTRACE(event, ctx);
+ break;
+
+ case PROC_EVENT_SID:
+ json = handle_PROC_EVENT_SID(event, ctx);
+ break;
+
+ case PROC_EVENT_COMM:
+ // update ledger with new comm
+ char *old_comm = NULL;
+ entry = proc_ledger_find(ctx->proc_ledger, event->event_data.comm.process_pid);
+ if (entry) {
+ old_comm = strdup(entry->comm);
+ strncpy(entry->comm, event->event_data.comm.comm, sizeof(entry->comm) - 1);
+ entry->comm[sizeof(entry->comm) - 1] = '\0';
+ }
+
+ json = handle_PROC_EVENT_COMM(event, ctx, old_comm);
+ if (old_comm) {
+ free(old_comm);
+ }
+
+ break;
+
+ case PROC_EVENT_COREDUMP:
+ json = handle_PROC_EVENT_COREDUMP(event, ctx);
+ break;
+
+ default:
+ json = handle_PROC_EVENT_UNKNOWN(event, ctx);
+ break;
+ }
+
+ /* If we have data to output, deal with it. */
+ if (json.data) {
+ output(json_get(&json));
+ json_free(&json);
+ }
+}
+
+sock_t setup_proc_connector(void) {
+ int err;
+ sock_t proc_connector;
+ struct sockaddr_nl nl_userland;
+ enum proc_cn_mcast_op *mcop_msg;
+ struct cn_msg *cn_message;
+ char buf[1024] = {0};
+ struct nlmsghdr *nl_header;
+
+ proc_connector = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
+ if (proc_connector == -1) {
+ error("error creating proc_connector socket: %s", strerror(errno));
+ return -1;
+ }
+
+ nl_userland.nl_family = AF_NETLINK;
+ nl_userland.nl_groups = CN_IDX_PROC;
+ nl_userland.nl_pid = getpid();
+
+ err = bind(proc_connector, (struct sockaddr *)&nl_userland, sizeof(nl_userland));
+ if (err == -1) {
+ error("error binding proc_connector socket: %s", strerror(errno));
+ return -1;
+ }
+
+ nl_header = (struct nlmsghdr *)buf;
+ cn_message = (struct cn_msg *)NLMSG_DATA(nl_header);
+ mcop_msg = (enum proc_cn_mcast_op *)&cn_message->data[0];
+ *mcop_msg = PROC_CN_MCAST_LISTEN;
+
+ cn_message->id.idx = CN_IDX_PROC;
+ cn_message->id.val = CN_VAL_PROC;
+ cn_message->seq = 0;
+ cn_message->ack = 0;
+ cn_message->len = sizeof(enum proc_cn_mcast_op);
+
+ nl_header->nlmsg_len = NLMSG_LENGTH(sizeof(struct cn_msg) + sizeof(enum proc_cn_mcast_op));
+ nl_header->nlmsg_type = NLMSG_DONE;
+ nl_header->nlmsg_flags = 0;
+ nl_header->nlmsg_seq = 0;
+ nl_header->nlmsg_pid = getpid();
+
+ err = send(proc_connector, nl_header, nl_header->nlmsg_len, 0);
+ if (err != nl_header->nlmsg_len) {
+ error("send: %s", strerror(errno));
+ close(proc_connector);
+ return -1;
+ }
+
+ return proc_connector;
+}
+
+void select_proc_connector(sock_t proc_connector, agent_context_t *ctx) {
+ int recv_length;
+ socklen_t nl_kernel_len;
+ struct nlmsghdr *nlh;
+ struct cn_msg *cn_message;
+ struct sockaddr_nl nl_kernel;
+ char buf[1024] = {0};
+
+ nl_kernel_len = sizeof(nl_kernel);
+
+ recv_length = recvfrom(proc_connector,
+ buf,
+ sizeof(buf),
+ 0,
+ (struct sockaddr *)&nl_kernel,
+ &nl_kernel_len);
+ nlh = (struct nlmsghdr *)buf;
+
+ if ((recv_length < 1) || (nl_kernel.nl_pid != 0)) {
+ return;
+ }
+
+ while (NLMSG_OK(nlh, recv_length)) {
+ cn_message = NLMSG_DATA(nlh);
+
+ if ((nlh->nlmsg_type == NLMSG_NOOP) ||
+ (nlh->nlmsg_type == NLMSG_ERROR)) {
+ continue;
+ }
+
+ if (nlh->nlmsg_type == NLMSG_OVERRUN) {
+ break;
+ }
+
+ handle_proc_connector_message(cn_message, ctx);
+
+ if (nlh->nlmsg_type == NLMSG_DONE) {
+ break;
+ } else {
+ nlh = NLMSG_NEXT(nlh, recv_length);
+ }
+ }
+}
+
+static inline const char *safe_exe_path(struct proc_ledger_entry *entry) {
+ if (entry && entry->exe[0]) {
+ return entry->exe;
+ }
+ return "UNKNOWN";
+}
+
+/* handle_PROC_EVENT_FORK() - Handle PROC_EVENT_FORK events.
+ *
+ * The following are available for this event:
+ * - pid_t parent_pid
+ * - pid_t parent_tgid
+ * - pid_t child_pid
+ * - pid_t child_tgid
+ *
+ * Args:
+ * event - proc_event structure (linux/cn_proc.h)
+ * ctx - agent context containing process/hash hedgers
+ *
+ * Returns:
+ * json_t containing serialized JSON object describing this event.
+ *
+ * TODO: Deal with parent_pid and child_pid being the same somehow (see below)
+ */
+json_t handle_PROC_EVENT_FORK(struct proc_event *event, agent_context_t *ctx) {
+ pid_t parent_pid = event->event_data.fork.parent_pid;
+ pid_t parent_tgid = event->event_data.fork.parent_tgid;
+ pid_t child_pid = event->event_data.fork.child_pid;
+ pid_t child_tgid = event->event_data.fork.child_tgid;
+
+ struct proc_ledger_entry *parent_entry = proc_ledger_find(ctx->proc_ledger, parent_pid);
+ if (!parent_entry) {
+ json_t empty = {0};
+ return empty;
+ }
+
+ struct proc_ledger_entry *child_entry = proc_ledger_entry_create(child_pid, ctx);
+ if (child_entry && parent_entry) {
+ memcpy(child_entry, parent_entry, sizeof(struct proc_ledger_entry));
+ child_entry->pid = child_pid;
+ child_entry->tgid = child_tgid;
+ snprintf(child_entry->comm, sizeof(child_entry->comm), "%s", parent_entry->comm);
+ proc_ledger_add(ctx->proc_ledger, child_entry);
+ }
+
+ json_t buf = {0};
+ json_init(&buf);
+ json_start_object(&buf);
+
+ json_add_double(&buf, "timestamp", timestamp());
+ json_add_string(&buf, "hostname", ctx->hostname);
+ json_add_string(&buf, "event_type", "fork");
+ json_add_int(&buf, "parent_pid", parent_pid);
+ json_add_int(&buf, "parent_tgid", parent_tgid);
+ json_add_int(&buf, "child_pid", child_pid);
+ json_add_int(&buf, "child_tgid", child_tgid);
+ json_add_string(&buf, "parent_exepath", parent_entry->exe);
+ json_add_string(&buf, "parent_comm", parent_entry->comm);
+ json_add_string(&buf, "cmdline", parent_entry->cmdline);
+ bool deleted = endswith(parent_entry->exe, " (deleted)");
+ json_add_bool(&buf, "deleted", deleted);
+ json_add_int(&buf, "uid", parent_entry->uid);
+ json_add_int(&buf, "euid", parent_entry->euid);
+ json_add_int(&buf, "gid", parent_entry->gid);
+ json_add_int(&buf, "egid", parent_entry->egid);
+
+ // TODO is parent_entry correct, or child_entry?
+ struct hash_entry *hentry = hash_ledger_find(ctx->hash_ledger, parent_entry->exe);
+ if (hentry) {
+ if (hentry->md5[0]) {
+ json_add_string(&buf, "md5", hentry->md5);
+ }
+ if (hentry->sha256[0]) {
+ json_add_string(&buf, "sha256", hentry->sha256);
+ }
+
+ json_add_double(&buf, "entropy", hentry->entropy);
+ }
+
+ json_end_object(&buf);
+
+ return buf;
+}
+
+
+/* handle_PROC_EVENT_EXEC() - Handle PROC_EVENT_EXEC events.
+ *
+ * The following are available for this event:
+ * - pid_t process_pid
+ * - pid_t process_tgid
+ *
+ * Args:
+ * event - proc_event structure (linux/cn_proc.h)
+ * ctx - agent context containing process/hash hedgers
+ *
+ * Returns:
+ * json_t containing serialized JSON object describing this event.
+ */
+json_t handle_PROC_EVENT_EXEC(struct proc_event *event, agent_context_t *ctx) {
+ struct proc_ledger_entry *entry = proc_ledger_find(ctx->proc_ledger,
+ event->event_data.exec.process_pid);
+ if (!entry) {
+ json_t empty = {0};
+ return empty;
+ }
+
+ json_t buf = {0};
+ json_init(&buf);
+ json_start_object(&buf);
+
+ json_add_double(&buf, "timestamp", timestamp());
+ json_add_string(&buf, "hostname", ctx->hostname);
+ json_add_string(&buf, "event_type", "exec");
+ json_add_int(&buf, "pid", entry->pid);
+ json_add_int(&buf, "tgid", entry->tgid);
+ json_add_int(&buf, "uid", entry->uid);
+ json_add_int(&buf, "euid", entry->euid);
+ json_add_int(&buf, "gid", entry->gid);
+ json_add_int(&buf, "egid", entry->egid);
+ json_add_string(&buf, "exepath", entry->exe);
+ json_add_string(&buf, "cmdline", entry->cmdline);
+ json_add_string_or_null(&buf, "cwd", entry->cwd);
+
+ struct hash_entry *hentry = hash_ledger_find(ctx->hash_ledger, entry->exe);
+ if (hentry) {
+ json_add_string_or_null(&buf, "md5", hentry->md5);
+ json_add_string_or_null(&buf, "sha256", hentry->sha256);
+ json_add_double(&buf, "entropy", hentry->entropy);
+ }
+
+ json_end_object(&buf);
+
+ return buf;
+}
+
+/* handle_PROC_EVENT_EXEC_environment() - Grab the environment from
+ * PROC_EVENT_EXEC events.
+ *
+ * This is called after handle_PROC_EVENT_EXEC() to attempt to grab
+ * the environment from /proc/X/environ for a newly-executed
+ * process. This information may be useful from a forensics
+ * standpoint, and possibly to detect malicious activity.
+ *
+ * Since an environment can contain anything, it is base64 encoded so
+ * it doesn't break our JSON formatting.
+ *
+ * Args:
+ * event - proc_event structure (linux/cn_proc.h)
+ * ctx - agent context containing process/hash hedgers
+ *
+ * Returns:
+ * json_t containing serialized JSON object describing this event.
+ */
+json_t handle_PROC_EVENT_EXEC_environment(struct proc_event *event, agent_context_t *ctx) {
+ struct proc_ledger_entry *entry = proc_ledger_find(ctx->proc_ledger,
+ event->event_data.exec.process_pid);
+ if (!entry) {
+ json_t empty = {0};
+ return empty;
+ }
+
+ pid_t pid = event->event_data.exec.process_pid;
+
+ char *environment = proc_environ(pid);
+ if (!environment) {
+ json_t empty = {0};
+ return empty;
+ }
+
+ json_t buf = {0};
+ json_init(&buf);
+ json_start_object(&buf);
+
+ json_add_double(&buf, "timestamp", timestamp());
+ json_add_string(&buf, "hostname", ctx->hostname);
+ json_add_string(&buf, "event_type", "environment");
+ json_add_int(&buf, "pid", entry->pid);
+ json_add_int(&buf, "uid", entry->uid);
+ json_add_int(&buf, "euid", entry->euid);
+ json_add_int(&buf, "gid", entry->gid);
+ json_add_int(&buf, "egid", entry->egid);
+ json_add_string(&buf, "exepath", entry->exe);
+ json_add_string(&buf, "environment", environment);
+
+ json_end_object(&buf);
+
+ free(environment);
+ return buf;
+}
+
+/* handle_PROC_EVENT_EXIT() - Handle PROC_EVENT_EXIT events.
+ *
+ * The following are available for this event:
+ * - pid_t process_pid
+ * - pid_t process_tgid
+ * - u32 exit_code
+ * - u32 exit_signal
+ *
+ * Args:
+ * event - proc_event structure (linux/cn_proc.h)
+ * ctx - agent context containing process/hash hedgers
+ *
+ * Returns:
+ * json_t containing serialized JSON object describing this event.
+ */
+json_t handle_PROC_EVENT_EXIT(struct proc_event *event, agent_context_t *ctx) {
+ struct proc_ledger_entry *entry = proc_ledger_find(ctx->proc_ledger,
+ event->event_data.exit.process_pid);
+ if (!entry) {
+ json_t empty = {0};
+ return empty;
+ }
+
+ json_t buf = {0};
+ json_init(&buf);
+ json_start_object(&buf);
+
+ json_add_double(&buf, "timestamp", timestamp());
+ json_add_string(&buf, "hostname", ctx->hostname);
+ json_add_string(&buf, "event_type", "exit");
+ json_add_int(&buf, "pid", event->event_data.exit.process_pid);
+ json_add_int(&buf, "tgid", event->event_data.exit.process_tgid);
+ json_add_int(&buf, "exitcode", event->event_data.exit.exit_code);
+ json_add_int(&buf, "signal", event->event_data.exit.exit_signal);
+ json_add_string(&buf, "exepath", safe_exe_path(entry));
+
+ json_end_object(&buf);
+
+ return buf;
+}
+
+/* handle_PROC_EVENT_UID() - Handle PROC_EVENT_UID events.
+ * handle_PROC_EVENT_GID() - Handle PROC_EVENT_GID events.
+ *
+ * The following are availabie for this event:
+ * - pid_t process_ppid
+ * - pid_t process_tgid
+ * - union { u32 ruid; u32 rgid } r
+ * - union { u32 euid; u32 egid } e
+ *
+ * Args:
+ * event - proc_event structure (linux/cn_proc.h)
+ * ctx - agent context containing process/hash hedgers
+ * old_ruid - old real uid
+ * old_euid - old effective uid
+ *
+ * Returns:
+ * json_t containing serialized JSON object describing this event
+ *
+ * Note:
+ * The handle_PROC_EVENT_UID and handle_PROC_EVENT_GID functions
+ * are nearly identical. If no record of the old ruid/euid of the
+ * process exists, -1 will be displayed
+ */
+
+json_t handle_PROC_EVENT_UID(struct proc_event *event, agent_context_t *ctx, int old_ruid, int old_euid) {
+ struct proc_ledger_entry *entry = proc_ledger_find(ctx->proc_ledger,
+ event->event_data.id.process_pid);
+ if (!entry) {
+ json_t empty = {0};
+ return empty;
+ }
+
+ json_t buf = {0};
+ json_init(&buf);
+ json_start_object(&buf);
+
+ json_add_double(&buf, "timestamp", timestamp());
+ json_add_string(&buf, "hostname", ctx->hostname);
+ json_add_string(&buf, "event_type", "uid");
+ json_add_int(&buf, "pid", entry->pid);
+ json_add_int(&buf, "tgid", entry->tgid);
+ json_add_int(&buf, "old_ruid", old_ruid);
+ json_add_int(&buf, "new_ruid", event->event_data.id.r.ruid);
+ json_add_int(&buf, "old_euid", old_euid);
+ json_add_int(&buf, "new_euid", event->event_data.id.e.euid);
+ json_add_string(&buf, "exepath", entry->exe);
+
+ json_end_object(&buf);
+
+ return buf;
+}
+
+json_t handle_PROC_EVENT_GID(struct proc_event *event, agent_context_t *ctx, int old_rgid, int old_egid) {
+ struct proc_ledger_entry *entry = proc_ledger_find(ctx->proc_ledger,
+ event->event_data.id.process_pid);
+ if (!entry) {
+ json_t empty = {0};
+ return empty;
+ }
+
+ json_t buf = {0};
+ json_init(&buf);
+ json_start_object(&buf);
+
+ json_add_double(&buf, "timestamp", timestamp());
+ json_add_string(&buf, "hostname", ctx->hostname);
+ json_add_string(&buf, "event_type", "gid");
+ json_add_int(&buf, "pid", entry->pid);
+ json_add_int(&buf, "tgid", entry->tgid);
+ json_add_int(&buf, "old_rgid", old_rgid);
+ json_add_int(&buf, "new_rgid", event->event_data.id.r.rgid);
+ json_add_int(&buf, "old_egid", old_egid);
+ json_add_int(&buf, "new_egid", event->event_data.id.e.egid);
+ json_add_string(&buf, "exepath", entry->exe);
+
+ json_end_object(&buf);
+
+ return buf;
+}
+
+/* handle_PROC_EVENT_PTRACE() - Handle PROC_EVENT_PTRACE events.
+ *
+ * The following are availabie for this event:
+ * - pid_t process_ppid
+ * - pid_t process_tgid
+ * - pid_t tracer_pid
+ * - pid_t tracer_tgid
+ *
+ * Args:
+ * event - proc_event structure (linux/cn_proc.h)
+ * ctx - agent context containing process/hash hedgers
+ *
+ * Returns:
+ * json_t containing serialized JSON object describing this event
+ *
+ * Note:
+ * This appears to be called AFTER ptrace() calls, so obtaining the
+ * path, hash, etc of the tracer process may fail sometimes.
+ */
+json_t handle_PROC_EVENT_PTRACE(struct proc_event *event, agent_context_t *ctx) {
+ pid_t target_pid = event->event_data.ptrace.process_pid;
+ pid_t tracer_pid = event->event_data.ptrace.tracer_pid;
+
+ struct proc_ledger_entry *target_entry = proc_ledger_find(ctx->proc_ledger, target_pid);
+ struct proc_ledger_entry *tracer_entry = proc_ledger_find(ctx->proc_ledger, tracer_pid);
+
+ json_t buf = {0};
+ json_init(&buf);
+ json_start_object(&buf);
+
+ json_add_double(&buf, "timestamp", timestamp());
+ json_add_string(&buf, "hostname", ctx->hostname);
+ json_add_string(&buf, "event_type", "ptrace");
+ json_add_int(&buf, "pid", target_pid);
+ json_add_int(&buf, "tgid", event->event_data.ptrace.process_tgid);
+ json_add_int(&buf, "tracer_pid", tracer_pid);
+ json_add_int(&buf, "tracer_tgid", event->event_data.ptrace.tracer_tgid);
+
+ if (tracer_entry && tracer_entry->exe[0]) {
+ json_add_string(&buf, "tracer_exepath", tracer_entry->exe);
+ }
+
+ if (target_entry && target_entry->exe[0]) {
+ json_add_string(&buf, "target_exepath", target_entry->exe);
+ }
+
+ json_end_object(&buf);
+
+ return buf;
+}
+
+/* handle_PROC_EVENT_SID() - Handle PROC_EVENT_SID events.
+ *
+ * The following are availabie for this event:
+ * - pid_t process_ppid
+ * - pid_t process_tgid
+ *
+ * Args:
+ * event - proc_event structure (linux/cn_proc.h)
+ * ctx - agent context containing process/hash hedgers
+ *
+ * Returns:
+ * json_t containing serialized JSON object describing this event
+ *
+ * Note:
+ * This event occurs when the process calls setsid(). This can be
+ * used to detect when processes daemonize/fork/detach from a terminal.
+ *
+ * TODO: add contextual process ancestry to the output
+ */
+json_t handle_PROC_EVENT_SID(struct proc_event *event, agent_context_t *ctx) {
+ struct proc_ledger_entry *entry = proc_ledger_find(ctx->proc_ledger,
+ event->event_data.sid.process_pid);
+
+ json_t buf = {0};
+ json_init(&buf);
+ json_start_object(&buf);
+
+ json_add_double(&buf, "timestamp", timestamp());
+ json_add_string(&buf, "hostname", ctx->hostname);
+ json_add_string(&buf, "event_type", "sid");
+ json_add_int(&buf, "pid", event->event_data.sid.process_pid);
+ json_add_int(&buf, "tgid", event->event_data.sid.process_tgid);
+
+ if (entry && entry->exe[0]) {
+ json_add_string(&buf, "exepath", entry->exe);
+ }
+
+ json_end_object(&buf);
+
+ return buf;
+}
+
+/* handle_PROC_EVENT_COMM() - Handle PROC_EVENT_COMM events.
+ *
+ * The following are availabie for this event:
+ * - pid_t process_ppid
+ * - pid_t process_tgid
+ * - char comm[16]
+ *
+ * Args:
+ * event - proc_event structure (linux/cn_proc.h)
+ * ctx - agent context containing process/hash hedgers
+ * old_comm - string containing old value of comm
+ *
+ * Returns:
+ * json_t containing serialized JSON object describing this event
+ *
+ * Note:
+ * This may be triggered for prctl(PR_SET_NAME, ...) and be
+ * suitable for finding processes attempting to obfuscate
+ * themselves (ex: malware changing its name to 'sshd')
+ *
+ * Apparently this can be triggered by threads setting their names
+ * as well.
+ *
+ * TODO: show old comm if possible
+ * TODO: alert for "sketchy" names like sshd, cron, http, [kthread], ...
+ */
+json_t handle_PROC_EVENT_COMM(struct proc_event *event, agent_context_t *ctx, const char *old_comm) {
+ struct proc_ledger_entry *entry = proc_ledger_find(ctx->proc_ledger,
+ event->event_data.comm.process_pid);
+
+ json_t buf = {0};
+ json_init(&buf);
+ json_start_object(&buf);
+
+ json_add_double(&buf, "timestamp", timestamp());
+ json_add_string(&buf, "hostname", ctx->hostname);
+ json_add_string(&buf, "event_type", "comm");
+ json_add_int(&buf, "pid", event->event_data.comm.process_pid);
+ json_add_int(&buf, "tgid", event->event_data.comm.process_tgid);
+
+ json_add_string_or_null(&buf, "exepath", entry->exe);
+
+ json_add_string_or_null(&buf, "old_comm", old_comm);
+ json_add_string(&buf, "new_comm", event->event_data.comm.comm);
+
+ json_end_object(&buf);
+
+ return buf;
+}
+
+/* handle_PROC_EVENT_COREDUMP() - Handle PROC_EVENT_COREDUMP events.
+ *
+ * The following are availabie for this event:
+ * - pid_t process_ppid
+ * - pid_t process_tgid
+ * - pid_t parent_pid
+ * - pid_t parent_tgid
+ *
+ * Args:
+ * event - proc_event structure (linux/cn_proc.h)
+ * ctx - agent context containing process/hash hedgers
+ *
+ * Returns:
+ * json_t containing serialized JSON object describing this event
+ */
+json_t handle_PROC_EVENT_COREDUMP(struct proc_event *event, agent_context_t *ctx) {
+ struct proc_ledger_entry *entry = proc_ledger_find(ctx->proc_ledger,
+ event->event_data.exit.process_pid);
+
+ json_t buf = {0};
+ json_init(&buf);
+ json_start_object(&buf);
+
+ json_add_double(&buf, "timestamp", timestamp());
+ json_add_string(&buf, "hostname", ctx->hostname);
+ json_add_string(&buf, "event_type", "coredump");
+ json_add_int(&buf, "pid", event->event_data.coredump.process_pid);
+ json_add_int(&buf, "tgid", event->event_data.coredump.process_tgid);
+ json_add_int(&buf, "parent_pid", event->event_data.coredump.parent_pid);
+ json_add_int(&buf, "parent_tgid", event->event_data.coredump.parent_tgid);
+ json_add_string(&buf, "exefile", safe_exe_path(entry));
+
+ json_end_object(&buf);
+
+ return buf;
+}
+
+/* handle_PROC_EVENT_UNKNOWN() - Handle unknown events.
+ *
+ * This is a generic placeholder for unknown/unhandled events.
+ *
+ * Args:
+ * event - proc_event structure (linux/cn_proc.h)
+ * ctx - agent context
+ *
+ * Returns:
+ * char * containing serialized JSON object describing the event
+ */
+json_t handle_PROC_EVENT_UNKNOWN(struct proc_event *event, agent_context_t *ctx) {
+ json_t buf = {0};
+ json_init(&buf);
+ json_start_object(&buf);
+
+ json_add_double(&buf, "timestamp", timestamp());
+ json_add_string(&buf, "hostname", ctx->hostname);
+ json_add_string(&buf, "event_type", "unknown");
+ json_add_int(&buf, "event_code", event->what);
+
+ json_end_object(&buf);
+
+ return buf;
+}