This commit is contained in:
huoji
2023-05-09 01:03:55 +08:00
parent 7f1d3e37d3
commit 49904f5cb5
6 changed files with 233 additions and 2 deletions

View File

@@ -21,9 +21,9 @@
],
"compilerPath": "/usr/bin/g++-11",
"cStandard": "c23",
"cppStandard": "c++11",
"cppStandard": "c++23",
"intelliSenseMode": "linux-gcc-x64"
}
],
"version": 4
}
}

2
ebpf/build.sh Executable file
View File

@@ -0,0 +1,2 @@
#!/bin/bash
g++ main.cpp -o main -lbcc -pthread -lstdc++fs

35
ebpf/core.ebpf.c Normal file
View File

@@ -0,0 +1,35 @@
#include <uapi/linux/ptrace.h>
#include <linux/sched.h>
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;
}

BIN
ebpf/main Executable file

Binary file not shown.

125
ebpf/main.cpp Normal file
View File

@@ -0,0 +1,125 @@
#include <iostream>
#include <string>
#include <unistd.h>
#include <fstream>
#include <vector>
#include <bcc/BPF.h>
#include <signal.h>
#include <sstream>
const std::string EBPF_SOURCE_PATH = "core.ebpf.c";
volatile bool interrupted = false;
void signal_handler(int signal) { interrupted = true; }
std::pair<bool, std::string> 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<event_data_t *>(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<char> ebpf_program((std::istreambuf_iterator<char>(ebpf_file)),
std::istreambuf_iterator<char>());
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;
}

69
ebpf/test.py Normal file
View File

@@ -0,0 +1,69 @@
from bcc import BPF
from time import sleep
# eBPF program to trace process creation and exit
program = """
#include <uapi/linux/ptrace.h>
#include <linux/sched.h>
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()