Skip to content

Commit

Permalink
edriver-rust: adding process impl with maps
Browse files Browse the repository at this point in the history
  • Loading branch information
chriskaliX committed Sep 22, 2024
1 parent a5f18ec commit 20d9215
Show file tree
Hide file tree
Showing 17 changed files with 172 additions and 32 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,6 @@ ncp-rst
plugins/edriver/test/dist/2.txt
target/
plugins/edriver-rust/src/bpf/hades.skel.rs
# under dev
plugins/edriver-rust/src/bpf/common/libs/*
plugins/edriver-rust/src/bpf/common/rasp/*
3 changes: 2 additions & 1 deletion plugins/edriver-rust/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "edrivers"
name = "edriver"
version = "0.1.0"
edition = "2021"
authors = ["chriskali <chriskalix@protonmail.com>"]
Expand All @@ -21,6 +21,7 @@ twox-hash = "1.6"
hex = "0.4"
libbpf-rs = {version = "0.23.3", features = ["static"]}
libbpf-sys = { version = "1.4.3" }
bitflags = "1.2.1"
sdk = { path = "../../SDK/rust" }

[build-dependencies]
Expand Down
6 changes: 3 additions & 3 deletions plugins/edriver-rust/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@ build: \
headers/libbpf/libbpf.a

cargo fmt
cargo build --release --bin edrivers --target $(PLATFORM)-unknown-linux-gnu --features=static
cargo build --release --bin edriver --target $(PLATFORM)-unknown-linux-gnu --features=static

debug: \
headers/libbpf/libbpf.a

cargo fmt
cargo build --release --bin edrivers --target $(PLATFORM)-unknown-linux-gnu --features=static,debug
cargo build --release --bin edriver --target $(PLATFORM)-unknown-linux-gnu --features=static,debug

test:
cargo fmt
cargo test --bin edrivers --target $(PLATFORM)-unknown-linux-gnu --features=static,debug
cargo test --target $(PLATFORM)-unknown-linux-gnu --features=static,debug -- --include-ignored --show-output
2 changes: 1 addition & 1 deletion plugins/edriver-rust/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ fn main() {
"-c",
"-D__BPF_TRACING__",
"-DCORE",
"-D__aarch64__",
"-Isrc/bpf/headers/",
"-I../libs/core/",
"-I../libs/bpfheaders/",
"-Isrc/bpf/",
"-O2 -g",
"-mcpu=v2",
])
.debug(false)
.build_and_generate(&out)
.unwrap();
}
5 changes: 3 additions & 2 deletions plugins/edriver-rust/src/bpf/common/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,12 +176,13 @@ static __noinline struct sock *find_sock_internal(struct file **fds, int nr, int
goto out;

socket_state state = BPF_CORE_READ(sock, state);
if (state == SS_CONNECTING || state == SS_CONNECTED ||
state == SS_DISCONNECTING) {
/* https://elixir.bootlin.com/linux/v6.10/source/include/uapi/linux/net.h#L51 */
if (state == SS_CONNECTING || state == SS_CONNECTED || state == SS_DISCONNECTING) {
sk = BPF_CORE_READ(sock, sk);
if (!sk)
goto out;
family = BPF_CORE_READ(sk, sk_family);
/* https://elixir.bootlin.com/linux/v6.10/source/include/linux/socket.h#L193 */
if (family == AF_INET || family == AF_INET6)
return sk;
}
Expand Down
22 changes: 11 additions & 11 deletions plugins/edriver-rust/src/bpf/common/edriver.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later

#ifndef __EDRIVERS_H__
#define __EDRIVERS_H__
#ifndef __EDRIVER_H__
#define __EDRIVER_H__
#include <vmlinux.h>
#include <missing_definitions.h>
#include "consts.h"
Expand All @@ -19,14 +19,17 @@ static __always_inline int proc_info_creds(struct proc_info *, struct task_struc
static __noinline int prepend_pid_tree(struct proc_info *, struct task_struct *);
static __noinline int match_key(char *, int, uint64_t, int);

// trace/events/sched.h: TP_PROTO(struct task_struct *p, pid_t old_pid, struct linux_binprm *bprm)
SEC("raw_tracepoint/sched_process_exec")
int rtp__process_exec(struct bpf_raw_tracepoint_args *ctx)
{
struct task_struct *task = (struct task_struct *) bpf_get_current_task();
if (task == NULL)
return 0;

/* ingore kernel threads */
/* ingore kernel threads
* https://elixir.bootlin.com/linux/v6.10/source/include/linux/sched.h#L1644
*/
u32 flags = BPF_CORE_READ(task, flags);
if (flags & PF_KTHREAD)
return 0;
Expand All @@ -39,9 +42,7 @@ int rtp__process_exec(struct bpf_raw_tracepoint_args *ctx)
proc_info_envs(proc_i, task);
proc_pid_tree(proc_i, task);

/* report */
struct hds_context c = init_context(ctx, SYS_ENTER_EXECVE);

SBT((&c), &c.data_type, S_U32);
SBT((&c), &proc_i->pid, S_U32);
SBT((&c), &proc_i->tgid, S_U32);
Expand All @@ -63,9 +64,8 @@ int rtp__process_exec(struct bpf_raw_tracepoint_args *ctx)
struct path pwd = BPF_CORE_READ(task, fs, pwd);
void *pwd_ptr = get_path(__builtin_preserve_access_index(&pwd));
SBT_CHAR((&c), pwd_ptr);
/* stdin */
/* stdin & stdout */
SBT_CHAR((&c), get_fd(task, 0));
/* stdout */
SBT_CHAR((&c), get_fd(task, 1));
/* exe */
struct path exe = BPF_CORE_READ(task, mm, exe_file, f_path);
Expand Down Expand Up @@ -113,7 +113,7 @@ static struct proc_info *proc_info_init(struct task_struct *task)
if (ret < 0)
return NULL;
/* socket */
struct sock *sk = proc_socket_info(task, &proc_i->socket_pid);
struct sock *sk = proc_socket_info(task, (pid_t *)&proc_i->socket_pid);
if (!sk) {
proc_i->socket_pid = 0;
} else {
Expand Down Expand Up @@ -195,13 +195,13 @@ static unsigned int proc_info_envs(struct proc_info *info, struct task_struct *t
if (sl <= 0)
goto out; /* notice: break do not work on unroll */
len = len + sl;
if (match_key(&cache->buf[0], sl, 0x4e4e4f435f485353UL, 14)) {
if (match_key((char *)&cache->buf[0], sl, 0x4e4e4f435f485353UL, 14)) {
/* SSH_CONN */
bpf_probe_read_str(info->ssh_conn, MAX_STR_ENV, &cache->buf[15]);
} else if (match_key(&cache->buf[0], sl, 0x4f4c4552505f444cUL, 10)) {
} else if (match_key((char *)&cache->buf[0], sl, 0x4f4c4552505f444cUL, 10)) {
/* LD_PRELO */
bpf_probe_read_str(info->ld_pre, MAX_STR_ENV, &cache->buf[11]);
} else if (match_key(&cache->buf[0], sl, 0x415242494c5f444cUL, 15)) {
} else if (match_key((char *)&cache->buf[0], sl, 0x415242494c5f444cUL, 15)) {
/* LD_LIBRA */
bpf_probe_read_str(info->ld_lib, MAX_STR_ENV, &cache->buf[16]);
} else {
Expand Down
9 changes: 1 addition & 8 deletions plugins/edriver-rust/src/bpf/hades.bpf.c
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
// #include "include/hades_exec.h"
// #include "include/hades_net.h"
// #include "include/hades_privilege.h"
// #include "include/hades_rootkit.h"
// #include "include/hades_file.h"
// #include "include/hades_uprobe.h"
// #include "include/hades_honeypot.h"

#include "common/edriver.h"
// #include "common/rasp/java.h"

__u32 _version SEC("version") = 0xFFFFFFFE;
char LICENSE[] SEC("license") = "GPL";
13 changes: 9 additions & 4 deletions plugins/edriver-rust/src/bpfmgr.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
mod hades_skel {
include!("bpf/hades.skel.rs");
}
use crate::cache::Transformer;
use crate::events::{execve::Execve, Event};
use anyhow::{anyhow, Context, Result};
use hades_skel::*;
use lazy_static::lazy_static;
use libbpf_rs::{
skel::{OpenSkel, Skel, SkelBuilder},
Expand All @@ -18,6 +14,15 @@ use std::{
time::{Duration, SystemTime, UNIX_EPOCH},
};

mod hades_skel {
include!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/src/bpf/hades.skel.rs"
));
}

use hades_skel::*;

lazy_static! {
pub static ref LOSS_CNT: Arc<Mutex<u64>> = Arc::new(Mutex::new(0));
}
Expand Down
4 changes: 4 additions & 0 deletions plugins/edriver-rust/src/events/execve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ use anyhow::Result;
pub struct Execve {}

impl Event for Execve {
fn init() -> Result<()> {
Result::Ok(())
}

fn parse(data: &[u8], trans: &mut Transformer) -> Result<HashMap<String, String>> {
let mut m: HashMap<_, _> = HashMap::new();
let mut idx: usize = 0;
Expand Down
3 changes: 3 additions & 0 deletions plugins/edriver-rust/src/events/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ use std::{
};

pub mod execve;
pub mod rasp_java;

pub trait Event {
fn init() -> Result<()>;
fn parse(data: &[u8], trans: &mut Transformer) -> Result<HashMap<String, String>>;
}

Expand Down
13 changes: 13 additions & 0 deletions plugins/edriver-rust/src/events/rasp_java.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use super::{parse_sinfo, parse_str, parse_u16, parse_u32, Event};
use crate::process::*;
use anyhow::Result;

pub struct RaspJava {}

struct JavaInstance {}

// impl Event for RaspJava {
// // fn init() -> Result<()> {

// // }
// }
1 change: 1 addition & 0 deletions plugins/edriver-rust/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod bpfmgr;
pub mod cache;
pub mod events;
pub mod process;
4 changes: 2 additions & 2 deletions plugins/edriver-rust/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use anyhow::Result;
use edrivers::*;
use edriver::*;
use log::*;
use sdk::{logger::*, Client};
use std::path::PathBuf;
Expand All @@ -13,7 +13,7 @@ fn main() -> Result<()> {
// log init
set_boxed_logger(Box::new(Logger::new(Config {
max_size: 1024 * 1024 * 5,
path: PathBuf::from("./edrivers.log"),
path: PathBuf::from("./edriver.log"),
#[cfg(not(feature = "debug"))]
file_level: LevelFilter::Info,
#[cfg(feature = "debug")]
Expand Down
99 changes: 99 additions & 0 deletions plugins/edriver-rust/src/process/maps.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
use anyhow::{bail, Result};
use bitflags::bitflags;
use std::fs::read_to_string;

type PermFlag = u8;

/// Process is the trait to inspect system running process
pub trait Process {
/// Return the process identifier
fn pid() -> u32;
}

/// Information about the process memory mapping
#[derive(Default, Debug)]
pub struct Mapping {
/// Start address for virtual memory
pub vaddr_start: u64,
/// End address for virual memory
vaddr_end: u64,
/// Permissions of the page. 'p' flag means private
perm: PermFlag,
/// Offset for the mapping begins.
offset: u64,
/// Device is the major and minor device number (in hex) where the file lives.
device_id: String,
/// Inode of the file
inode: u64,
// Path contains the file name for file backed mappings
path: Option<String>,
}

bitflags! {
#[derive(Default)]
pub struct MPermissions: PermFlag {
/// No permissions
const NONE = 0;
/// Read permission
const READ = 1 << 0;
/// Write permission
const WRITE = 1 << 1;
/// Execute permission
const EXECUTE = 1 << 2;
/// Memory is shared with another process.
/// Mutually exclusive with PRIVATE.
const SHARED = 1 << 3;
/// Memory is private (and copy-on-write)
/// Mutually exclusive with SHARED.
const PRIVATE = 1 << 4;
}
}

impl MPermissions {
fn from_str(s: &str) -> Result<Self> {
if s.len() != 4 {
bail!("Permission length {}", s.len());
}
let mut permissions = MPermissions::NONE;
for (_, c) in s.chars().enumerate() {
match c {
'r' => permissions |= MPermissions::READ,
'w' => permissions |= MPermissions::WRITE,
'x' => permissions |= MPermissions::EXECUTE,
'p' => permissions |= MPermissions::PRIVATE,
's' => permissions |= MPermissions::SHARED,
_ => continue,
}
}
Ok(permissions)
}
}

/// Parse mapping
pub fn parse_mapping(pid: u32) -> Result<Vec<Mapping>> {
// Read the maps from file
let maps = read_to_string(format!("/proc/{}/maps", pid))?;
let mut ret: Vec<Mapping> = Vec::with_capacity(maps.len());
for line in maps.lines() {
if let Ok(m) = parse_mapping_line(line) {
ret.push(m)
}
}
Ok(ret)
}

fn parse_mapping_line(line: &str) -> Result<Mapping> {
let mut m = Mapping::default();
// Split fields with blanks
let fields = line.split_whitespace().collect::<Vec<&str>>();
// Extract vaddr
let vaddr: Vec<&str> = fields[0].split('-').collect();
m.vaddr_start = u64::from_str_radix(vaddr[0], 16)?;
m.vaddr_end = u64::from_str_radix(vaddr[1], 16)?;
m.perm = MPermissions::from_str(fields[1])?.bits();
m.offset = u64::from_str_radix(fields[2], 16)?;
m.device_id = fields[3].to_string();
m.inode = fields[4].parse()?;
m.path = fields.get(5).map(|s| s.to_string());
Ok(m)
}
2 changes: 2 additions & 0 deletions plugins/edriver-rust/src/process/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod maps;
pub mod process;
5 changes: 5 additions & 0 deletions plugins/edriver-rust/src/process/process.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#[derive(Debug, Clone, Default)]
pub struct ProcessInfo {
pub pid: u32,
pub cmdline: Option<String>,
}
10 changes: 10 additions & 0 deletions plugins/edriver-rust/tests/process_test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
use edrivers::process::maps::parse_mapping;

#[test]
fn test_parse_mapping() {
if let Ok(e) = parse_mapping(1) {
assert_ne!(e.len(), 0);
} else {
panic!("parse mapping failed");
}
}

0 comments on commit 20d9215

Please sign in to comment.