diff --git a/include/secDetector_topic.h b/include/secDetector_topic.h index ebbb76bf91f4d53b38ff9fe9f5ab6194a26a08e0..7320042eac8d8954b91cd0faf89d6c303208d818 100644 --- a/include/secDetector_topic.h +++ b/include/secDetector_topic.h @@ -50,4 +50,5 @@ /* memory corruption kmodule list */ #define KMODULELIST 0x00800000 +#define ALL_TOPIC 0xFFFFFFFF #endif diff --git a/observer_agent/CMakeLists.txt b/observer_agent/CMakeLists.txt index a4439357925e2d2e078e127d398d7805e74160d8..8465044160538c88781c07c0ffa8910fd487d3df 100644 --- a/observer_agent/CMakeLists.txt +++ b/observer_agent/CMakeLists.txt @@ -7,8 +7,9 @@ set(GRPC_PATH ${CMAKE_CURRENT_SOURCE_DIR}/grpc_comm) add_custom_target(grpc_demo ALL COMMAND make -C ${GRPC_PATH}) -add_executable(secDetectord grpc_comm/client.cpp grpc_comm/server.cpp service/main.cpp service/ringbuffer.cpp - service/ebpf_converter.cpp) +add_executable(secDetectord grpc_comm/client.cpp grpc_comm/server.cpp + service/main.cpp service/ringbuffer.cpp + service/ebpf_converter.cpp) add_dependencies(secDetectord ebpf file_ebpf) target_include_directories(secDetectord PUBLIC service grpc_comm ${CMAKE_SOURCE_DIR}/include .) diff --git a/observer_agent/ebpf/CMakeLists.txt b/observer_agent/ebpf/CMakeLists.txt index 64fdae10d6932a582a244f6f57e82b2941905cea..6b97de4085d26ce8c18bca6ee9adf8a2ef06faac 100644 --- a/observer_agent/ebpf/CMakeLists.txt +++ b/observer_agent/ebpf/CMakeLists.txt @@ -6,7 +6,7 @@ add_custom_target(ebpf COMMAND bpftool btf dump file /sys/kernel/btf/vmlinux format c > ${CMAKE_CURRENT_BINARY_DIR}/.output/vmlinux.h COMMAND clang -g -O2 -target bpf -D__TARGET_ARCH_x86 -I${CMAKE_SOURCE_DIR}/include -I${CMAKE_CURRENT_BINARY_DIR}/.output -c ${CMAKE_CURRENT_SOURCE_DIR}/fentry.bpf.c -o ${CMAKE_CURRENT_BINARY_DIR}/.output/fentry.bpf.o COMMAND bpftool gen skeleton ${CMAKE_CURRENT_BINARY_DIR}/.output/fentry.bpf.o > ${CMAKE_CURRENT_BINARY_DIR}/.output/fentry.skel.h - COMMAND cc -g -Wall -fPIC -I${CMAKE_CURRENT_BINARY_DIR}/.output -I${CMAKE_CURRENT_SOURCE_DIR} -c ${CMAKE_CURRENT_SOURCE_DIR}/fentry.c -o ${CMAKE_CURRENT_BINARY_DIR}/.output/fentry.o + COMMAND cc -g -Wall -fPIC -I${CMAKE_SOURCE_DIR}/include -I${CMAKE_CURRENT_BINARY_DIR}/.output -I${CMAKE_CURRENT_SOURCE_DIR} -c ${CMAKE_CURRENT_SOURCE_DIR}/fentry.c -o ${CMAKE_CURRENT_BINARY_DIR}/.output/fentry.o ) add_executable(test_fentry ${CMAKE_CURRENT_SOURCE_DIR}/test_fentry.c) diff --git a/observer_agent/ebpf/fentry.c b/observer_agent/ebpf/fentry.c index c3e026f977b6b0053ee8cc7d09c56aed73eba9f8..cf7787ac8cad029a3e106ef78dfba877fdbd8fe0 100644 --- a/observer_agent/ebpf/fentry.c +++ b/observer_agent/ebpf/fentry.c @@ -14,6 +14,7 @@ * Description: secDetector process hook */ #include "fentry.h" +#include "secDetector_topic.h" #include "ebpf_types.h" #include "fentry.skel.h" #include @@ -32,7 +33,49 @@ void StopProcesseBPFProg() exiting = 1; } -int StartProcesseBPFProg(ring_buffer_sample_fn cb, unsigned int rb_sz) +static void DisableProg(struct bpf_object_skeleton *s, const char *prog_name) +{ + int n = s->prog_cnt; + + for (int i = 0; i < n; i++) { + if (strcmp(s->progs[i].name, prog_name) == 0) { + fprintf(stderr, "%s is not enabled\n", prog_name); + bpf_link__destroy(*s->progs[i].link); + s->progs[i].link = NULL; + + /* exchange the last one */ + s->progs[i].prog = s->progs[n - 1].prog; + s->progs[i].link = s->progs[n - 1].link; + s->progs[i].name = s->progs[n - 1].name; + s->prog_cnt--; + } + } +} + + +static void DisableProgBasedOnMask(struct bpf_object_skeleton *skel, int mask) +{ + if ((mask & CREATPROCESS) == 0) { + DisableProg(skel, "handle_exec"); + DisableProg(skel, "handle_fork"); + DisableProg(skel, "handle_bprm_check"); + } + + if ((mask & DESTROYPROCESS) == 0) { + DisableProg(skel, "handle_exit"); + } + + if ((mask & SETPROCESSATTR) == 0) { + DisableProg(skel, "handle_commit_creds"); + } + + if ((mask & EXECCMD) == 0) { + DisableProg(skel, "handle_execve_cmd"); + } +} + + +int StartProcesseBPFProg(ring_buffer_sample_fn cb, unsigned int rb_sz, int mask) { struct fentry_bpf *skel; struct ring_buffer *rb = NULL; @@ -70,6 +113,8 @@ int StartProcesseBPFProg(ring_buffer_sample_fn cb, unsigned int rb_sz) goto cleanup; } + DisableProgBasedOnMask(skel->skeleton, mask); + while (exiting == 0) { err = ring_buffer__poll(rb, 1000 /* timeout ms*/); diff --git a/observer_agent/ebpf/fentry.h b/observer_agent/ebpf/fentry.h index b0819f3c29bdb7d69acc34a68398ef60998aaa95..172bafe7d41e87f36900921aee66a529e498680c 100644 --- a/observer_agent/ebpf/fentry.h +++ b/observer_agent/ebpf/fentry.h @@ -19,13 +19,15 @@ extern "C" { #endif +#include "fentry.h" #include +extern struct fentry_bpf *process_bpf_skel; void StopProcesseBPFProg(); -int StartProcesseBPFProg(ring_buffer_sample_fn cb, unsigned int rb_sz); +int StartProcesseBPFProg(ring_buffer_sample_fn cb, unsigned int rb_sz, int mask); void StopFileBPFProg(); -int StartFileBPFProg(ring_buffer_sample_fn cb, unsigned int rb_sz); +int StartFileBPFProg(ring_buffer_sample_fn cb, unsigned int rb_sz, int mask); #ifdef __cplusplus } #endif diff --git a/observer_agent/ebpf/file_ebpf/CMakeLists.txt b/observer_agent/ebpf/file_ebpf/CMakeLists.txt index 024379e6abccbd8a5d0863b57dd8328d3f1849a2..9517832da60437b777fc3918273e62940ca7ec29 100644 --- a/observer_agent/ebpf/file_ebpf/CMakeLists.txt +++ b/observer_agent/ebpf/file_ebpf/CMakeLists.txt @@ -7,7 +7,7 @@ add_custom_target(file_ebpf COMMAND bpftool btf dump file /sys/kernel/btf/vmlinux format c > ${CMAKE_CURRENT_BINARY_DIR}/.output/vmlinux.h COMMAND clang -g -O2 -target bpf -D__TARGET_ARCH_x86 -I${CMAKE_SOURCE_DIR}/include -I${CMAKE_CURRENT_BINARY_DIR}/.output -c ${CMAKE_CURRENT_SOURCE_DIR}/file_fentry.bpf.c -o ${CMAKE_CURRENT_BINARY_DIR}/.output/file_fentry.bpf.o COMMAND bpftool gen skeleton ${CMAKE_CURRENT_BINARY_DIR}/.output/file_fentry.bpf.o > ${CMAKE_CURRENT_BINARY_DIR}/.output/file_fentry.skel.h - COMMAND cc -g -Wall -fPIC -I${CMAKE_CURRENT_BINARY_DIR}/.output -I${CMAKE_CURRENT_SOURCE_DIR} -c ${CMAKE_CURRENT_SOURCE_DIR}/file_fentry.c -o ${CMAKE_CURRENT_BINARY_DIR}/.output/file_fentry.o + COMMAND cc -g -Wall -fPIC -I${CMAKE_SOURCE_DIR}/include -I${CMAKE_CURRENT_BINARY_DIR}/.output -I${CMAKE_CURRENT_SOURCE_DIR} -c ${CMAKE_CURRENT_SOURCE_DIR}/file_fentry.c -o ${CMAKE_CURRENT_BINARY_DIR}/.output/file_fentry.o ) add_executable(test_file_fentry ${CMAKE_CURRENT_SOURCE_DIR}/test_file_fentry.c) diff --git a/observer_agent/ebpf/file_ebpf/file_fentry.bpf.c b/observer_agent/ebpf/file_ebpf/file_fentry.bpf.c index d5f72750d1ddf192e837496abc05c8947b9f7990..84faf54a8df372af7afe3e35e95373fd6303669d 100644 --- a/observer_agent/ebpf/file_ebpf/file_fentry.bpf.c +++ b/observer_agent/ebpf/file_ebpf/file_fentry.bpf.c @@ -163,7 +163,7 @@ int BPF_PROG(fexit_vfs_unlink, struct inode *dir, struct dentry *dentry, struct if (!e) return 0; - e->type = 2; + e->type = DELFILE; get_common_info(e); __builtin_memcpy(e->event_name, "vfs_unlink", sizeof("vfs_unlink")); bpf_probe_read(e->file_info.filename, MAX_TEXT_SIZE, dentry->d_name.name); diff --git a/observer_agent/ebpf/file_ebpf/file_fentry.c b/observer_agent/ebpf/file_ebpf/file_fentry.c index 8e83723c5e71af9d7857584206f7b6d2be218339..bf445ab07c6e3aeda8747102f8edde6abfa9d7df 100644 --- a/observer_agent/ebpf/file_ebpf/file_fentry.c +++ b/observer_agent/ebpf/file_ebpf/file_fentry.c @@ -5,6 +5,7 @@ #include "../ebpf_types.h" #include "../fentry.h" #include "file_fentry.skel.h" +#include "secDetector_topic.h" #include #include #include @@ -21,7 +22,55 @@ void StopFileBPFProg() exiting = 1; } -int StartFileBPFProg(ring_buffer_sample_fn cb, unsigned int rb_sz) +static void DisableProg(struct bpf_object_skeleton *s, const char *prog_name) +{ + int n = s->prog_cnt; + + for (int i = 0; i < n; i++) { + if (strcmp(s->progs[i].name, prog_name) == 0) { + fprintf(stderr, "%s is not enabled\n", prog_name); + bpf_link__destroy(*s->progs[i].link); + s->progs[i].link = NULL; + + /* exchange the last one */ + s->progs[i].prog = s->progs[n - 1].prog; + s->progs[i].link = s->progs[n - 1].link; + s->progs[i].name = s->progs[n - 1].name; + s->prog_cnt--; + break; + } + } +} + +static void DisableProgBasedOnMask(struct bpf_object_skeleton *skel, int mask) +{ + if ((mask & CREATFILE) == 0) { + DisableProg(skel, "do_filp_open_exit"); + } + + if ((mask & DELFILE) == 0) { + DisableProg(skel, "fexit_vfs_unlink"); + } + + if ((mask & WRITEFILE) == 0) { + DisableProg(skel, "fexit_vfs_write"); + } + + if ((mask & READFILE) == 0) { + DisableProg(skel, "fexit_vfs_read"); + } + + if ((mask & SETFILEATTR) == 0) { + DisableProg(skel, "fexit_vfs_utimes"); + DisableProg(skel, "fexit_chown_common"); + DisableProg(skel, "fexit_chmod_common"); + DisableProg(skel, "fentry__vfs_setxattr_noperm"); + DisableProg(skel, "fentry__vfs_removexattr_locked"); + DisableProg(skel, "fentry_vfs_rename"); + } +} + +int StartFileBPFProg(ring_buffer_sample_fn cb, unsigned int rb_sz, int mask) { struct file_fentry_bpf *skel; struct ring_buffer *rb = NULL; @@ -59,6 +108,8 @@ int StartFileBPFProg(ring_buffer_sample_fn cb, unsigned int rb_sz) goto cleanup; } + DisableProgBasedOnMask(skel->skeleton, mask); + while (exiting == 0) { err = ring_buffer__poll(rb, 1000 /* timeout ms*/); diff --git a/observer_agent/ebpf/file_ebpf/test_file_fentry.c b/observer_agent/ebpf/file_ebpf/test_file_fentry.c index 3a49a5c043ae403547d717599c3056dda0bf5df2..a9ea778c1a1713fe054cf912658a78b910f1e986 100644 --- a/observer_agent/ebpf/file_ebpf/test_file_fentry.c +++ b/observer_agent/ebpf/file_ebpf/test_file_fentry.c @@ -26,5 +26,5 @@ int main() { /* Set up libbpf errors and debug info callback */ libbpf_set_print(libbpf_print_fn); - StartFileBPFProg(handle_event, 4 * 1024 * 1024); + StartFileBPFProg(handle_event, 4 * 1024 * 1024, 0xffffffff); } diff --git a/observer_agent/ebpf/test_fentry.c b/observer_agent/ebpf/test_fentry.c index 039153bc94d118155c073e9e87d841aec9fd1071..0616958ddd1d5c197ea4124867299ad3d843dd79 100644 --- a/observer_agent/ebpf/test_fentry.c +++ b/observer_agent/ebpf/test_fentry.c @@ -39,5 +39,5 @@ int main() { /* Set up libbpf errors and debug info callback */ libbpf_set_print(libbpf_print_fn); - StartProcesseBPFProg(handle_event, 4 * 1024 * 1024); + StartProcesseBPFProg(handle_event, 4 * 1024 * 1024, 0xffffffff); } diff --git a/observer_agent/service/ebpf_converter.cpp b/observer_agent/service/ebpf_converter.cpp index eddc96ebc6ccec83711286b00ed6904881c6851b..6e42b6c8881e4e9a6426d21ee286e8199fb6326c 100644 --- a/observer_agent/service/ebpf_converter.cpp +++ b/observer_agent/service/ebpf_converter.cpp @@ -76,7 +76,7 @@ static std::string extract_common_info(struct ebpf_event *e) { std::ostringstream ss; ss << "timestamp:" << get_local_time() << " event_name:" << e->event_name << " exe:" << FindProcessPathFromPid(e) - << " pid:" << e->pid << " tgid:" << e->tgid << " uid:" << e->uid << " gid:" << e->gid << " comm:" << e->comm + << " pid:" << e->pid << " tgid:" << e->tgid << " pgid:" << e->pgid << " uid:" << e->uid << " gid:" << e->gid << " comm:" << e->comm << " sid:" << e->sid << " ppid:" << e->ppid << " pcomm:" << e->pcomm << " nodename:" << e->nodename << " pns:" << e->pns << " root_pns:" << e->pns; return ss.str(); diff --git a/observer_agent/service/main.cpp b/observer_agent/service/main.cpp index 3e784c7993c04e62b79bf3f892c76dba5ccfd464..940cf83c08f59e783a99e5b95e6bca20c0850c08 100644 --- a/observer_agent/service/main.cpp +++ b/observer_agent/service/main.cpp @@ -18,6 +18,7 @@ #include "ebpf/fentry.h" #include "ebpf_converter.h" #include "ringbuffer.h" +#include "secDetector_topic.h" #include #include #include @@ -44,6 +45,7 @@ using grpc::ServerWriter; #define MAX_RINGBUF_SIZE 1024 static unsigned int ringbuf_size_bytes; static unsigned int ringbuf_size = MIN_RINGBUF_SIZE; +static int topic_mask = ALL_TOPIC; static bool power_of_2(unsigned int num) { @@ -65,7 +67,7 @@ static bool ringbuf_size_check(void) std::cerr << "[secDetector] ringbuf_size should be power of 2" << std::endl; return false; } - + std::cout << "ringbuf size is set to " << ringbuf_size << "Mb" << std::endl; ringbuf_size_bytes = ringbuf_size * 1024 * 1024; return true; @@ -80,6 +82,9 @@ static bool debug = false; static void push_log(int type, const std::string &content) { + if ((topic_mask & type) == 0) + return; + // push to console if debug if (debug) { @@ -122,10 +127,9 @@ int main(int argc, char *argv[]) { int r; int opt; - unsigned int rb_sz; set_signal_handler(); - while ((opt = getopt(argc, argv, "ds:")) != -1) + while ((opt = getopt(argc, argv, "ds:t:")) != -1) { switch (opt) { @@ -135,9 +139,17 @@ int main(int argc, char *argv[]) case 's': ringbuf_size = strtoul(optarg, NULL, 0); break; + case 't': + topic_mask = strtoul(optarg, NULL, 0); + break; } } - + + if (topic_mask == 0) { + std::cerr << "not a valid topic_mask" << std::endl; + return -1; + } + if (!ringbuf_size_check()) { std::cerr << "Not a valid ring buffer size" << std::endl; return -1; @@ -165,8 +177,8 @@ int main(int argc, char *argv[]) } std::thread thread_grpc = std::thread(RunServer); - std::thread thread_ebpf_process = std::thread(StartProcesseBPFProg, ebpf_cb, ringbuf_size_bytes); - std::thread thread_ebpf_file = std::thread(StartFileBPFProg, ebpf_cb, ringbuf_size_bytes); + std::thread thread_ebpf_process = std::thread(StartProcesseBPFProg, ebpf_cb, ringbuf_size_bytes, topic_mask); + std::thread thread_ebpf_file = std::thread(StartFileBPFProg, ebpf_cb, ringbuf_size_bytes, topic_mask); while (exiting == 0) {