From 49904f5cb5eda4a41cf132949b07550f76ff39d6 Mon Sep 17 00:00:00 2001 From: huoji Date: Tue, 9 May 2023 01:03:55 +0800 Subject: [PATCH] demo --- .vscode/c_cpp_properties.json | 4 +- ebpf/build.sh | 2 + ebpf/core.ebpf.c | 35 ++++++++++ ebpf/main | Bin 0 -> 99160 bytes ebpf/main.cpp | 125 ++++++++++++++++++++++++++++++++++ ebpf/test.py | 69 +++++++++++++++++++ 6 files changed, 233 insertions(+), 2 deletions(-) create mode 100755 ebpf/build.sh create mode 100644 ebpf/core.ebpf.c create mode 100755 ebpf/main create mode 100644 ebpf/main.cpp create mode 100644 ebpf/test.py diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 4e03bb2..10077a6 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -21,9 +21,9 @@ ], "compilerPath": "/usr/bin/g++-11", "cStandard": "c23", - "cppStandard": "c++11", + "cppStandard": "c++23", "intelliSenseMode": "linux-gcc-x64" } ], "version": 4 -} \ No newline at end of file +} diff --git a/ebpf/build.sh b/ebpf/build.sh new file mode 100755 index 0000000..94fb097 --- /dev/null +++ b/ebpf/build.sh @@ -0,0 +1,2 @@ +#!/bin/bash +g++ main.cpp -o main -lbcc -pthread -lstdc++fs diff --git a/ebpf/core.ebpf.c b/ebpf/core.ebpf.c new file mode 100644 index 0000000..f8cccf7 --- /dev/null +++ b/ebpf/core.ebpf.c @@ -0,0 +1,35 @@ +#include +#include + +struct event_data_t { + int type; + u32 pid; + u32 ppid; +} __attribute__((packed)); + +BPF_PERF_OUTPUT(events); + +int trace_process_start(struct pt_regs *ctx, struct filename *filename) { + struct event_data_t event_data; + + u32 pid = bpf_get_current_pid_tgid(); + u32 ppid = bpf_get_current_pid_tgid() >> 32; + event_data.type = 0; + event_data.pid = pid; + event_data.ppid = ppid; + events.perf_submit(ctx, &event_data, sizeof(event_data)); + return 0; +} + +int trace_process_exit(struct pt_regs *ctx) { + struct event_data_t event_data; + + u32 pid = bpf_get_current_pid_tgid(); + u32 ppid = bpf_get_current_pid_tgid() >> 32; + event_data.type = 1; + event_data.pid = pid; + event_data.ppid = ppid; + events.perf_submit(ctx, &event_data, sizeof(event_data)); + + return 0; +} diff --git a/ebpf/main b/ebpf/main new file mode 100755 index 0000000000000000000000000000000000000000..b149fb4c936e7de8c2fd569e390bbcc5b4655133 GIT binary patch literal 99160 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 QZ^#J0VFT4l$=BBZ0F2&OQvd(} literal 0 HcmV?d00001 diff --git a/ebpf/main.cpp b/ebpf/main.cpp new file mode 100644 index 0000000..4ca6ef1 --- /dev/null +++ b/ebpf/main.cpp @@ -0,0 +1,125 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +const std::string EBPF_SOURCE_PATH = "core.ebpf.c"; + +volatile bool interrupted = false; + +void signal_handler(int signal) { interrupted = true; } + +std::pair get_process_path(int pid) { + try { + char path[4096] = {0}; + std::string symlink_path = "/proc/" + std::to_string(pid) + "/exe"; + ssize_t len = readlink(symlink_path.c_str(), path, sizeof(path)); + if (len != -1) { + return {true, std::string(path)}; + } + } catch (...) { + } + return {false, "unknown"}; +} + +std::string get_process_name(pid_t pid) { + std::string process_name; + std::ifstream comm_file("/proc/" + std::to_string(pid) + "/comm"); + + if (comm_file.is_open()) { + std::getline(comm_file, process_name); + comm_file.close(); + } else { + process_name = "unknown"; + } + + return process_name; +} + +std::string get_process_cmdline(pid_t pid) { + std::string cmdline; + std::ifstream cmdline_file("/proc/" + std::to_string(pid) + "/cmdline"); + + if (cmdline_file.is_open()) { + std::getline(cmdline_file, cmdline, '\0'); + cmdline_file.close(); + } else { + cmdline = "unknown"; + } + + return cmdline; +} +void print_event(void *context, void *data, int data_size) { + struct event_data_t { + int type; + uint32_t pid; + uint32_t ppid; + }; + + auto event = static_cast(data); + auto [process_exists, path] = get_process_path(event->pid); + if (event->type == 0 && process_exists == false) { + // 进程启动如果路径为空说明取不到了 + // 进程结束路径一定是取不到的 + return; + } + auto process_name = get_process_name(event->pid); + auto cmdline = get_process_cmdline(event->pid); + auto event_type = event->type == 0 ? "start" : "exit"; + printf("type: %s pid: %d ppid: %d path: %s name: %s cmdline: %s\n", + event_type, event->pid, event->ppid, path.c_str(), + process_name.c_str(), cmdline.c_str()); +} + +int main() { + ebpf::BPF bpf; + std::ifstream ebpf_file(EBPF_SOURCE_PATH, std::ios::binary); + // 检查文件是否存在 + if (ebpf_file.fail()) { + std::cerr << "Failed to open " << EBPF_SOURCE_PATH << std::endl; + return 1; + } + std::vector ebpf_program((std::istreambuf_iterator(ebpf_file)), + std::istreambuf_iterator()); + auto init_res = + bpf.init(std::string(ebpf_program.data(), ebpf_program.size())); + if (init_res.code() != 0) { + std::cerr << "Failed to initialize BPF program: " << init_res.msg() + << std::endl; + return 1; + } + + std::string execve_fnname = bpf.get_syscall_fnname("execve"); + std::string exit_group_fnname = bpf.get_syscall_fnname("exit_group"); + + auto attach_res1 = bpf.attach_kprobe(execve_fnname, "trace_process_start"); + auto attach_res2 = + bpf.attach_kprobe(exit_group_fnname, "trace_process_exit"); + + if (attach_res1.code() != 0 || attach_res2.code() != 0) { + std::cerr << "Failed to attach kprobes: " << attach_res1.msg() << " " + << attach_res2.msg() << std::endl; + return 1; + } + + signal(SIGINT, signal_handler); + + auto ret = + bpf.open_perf_buffer("events", print_event, nullptr, nullptr, 256); + if (ret.code() != 0) { + fprintf(stderr, "Error: open_perf_buffer: %s\n", ret.msg().c_str()); + return EXIT_FAILURE; + } + auto table = bpf.get_table("events"); + auto perf_buffer = bpf.get_perf_buffer("events"); + + while (!interrupted) { + perf_buffer->poll(1000); + } + + return 0; +} diff --git a/ebpf/test.py b/ebpf/test.py new file mode 100644 index 0000000..92346c8 --- /dev/null +++ b/ebpf/test.py @@ -0,0 +1,69 @@ +from bcc import BPF +from time import sleep + +# eBPF program to trace process creation and exit +program = """ +#include +#include + +struct event_data_t { + int type; + u32 pid; + u32 ppid; +} __attribute__((packed)); + +BPF_PERF_OUTPUT(events); + +int trace_process_start(struct pt_regs *ctx, struct filename *filename) { + struct event_data_t event_data; + + u32 pid = bpf_get_current_pid_tgid(); + u32 ppid = bpf_get_current_pid_tgid() >> 32; + event_data.type = 0; + event_data.pid = pid; + event_data.ppid = ppid; + events.perf_submit(ctx, &event_data, sizeof(event_data)); + return 0; +} + +int trace_process_exit(struct pt_regs *ctx) { + struct event_data_t event_data; + + u32 pid = bpf_get_current_pid_tgid(); + u32 ppid = bpf_get_current_pid_tgid() >> 32; + event_data.type = 1; + event_data.pid = pid; + event_data.ppid = ppid; + events.perf_submit(ctx, &event_data, sizeof(event_data)); + + return 0; +} +""" + +# initialize BPF and attach tracepoints +b = BPF(text=program) +b.attach_kprobe(event=b.get_syscall_fnname("execve"), fn_name="trace_process_start") +b.attach_kprobe(event=b.get_syscall_fnname("exit_group"), fn_name="trace_process_exit") + +import psutil + +def get_process_path(pid): + try: + proc = psutil.Process(pid) + return proc.exe() + except (psutil.NoSuchProcess, psutil.AccessDenied): + return "unknown" + +# process event data +def print_event(cpu, data, size): + event = b["events"].event(data) + path = get_process_path(event.pid) + print(f"type: {event.type} pid: {event.pid}, ppid: {event.ppid} path: {path}") + +b["events"].open_perf_buffer(print_event) + +while True: + try: + b.perf_buffer_poll() + except KeyboardInterrupt: + exit()