Skip to content

Commit

Permalink
add example of 34
Browse files Browse the repository at this point in the history
  • Loading branch information
yunwei37 committed Oct 16, 2023
1 parent 010e61c commit 32e23bb
Show file tree
Hide file tree
Showing 11 changed files with 289 additions and 2 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ Android:

安全:

- [使用 eBPF 修改系统调用参数](src/34-syscall/README.md)
- [使用 eBPF 隐藏进程或文件信息](src/24-hide/README.md)
- [使用 bpf_send_signal 发送信号终止进程](src/25-signal/README.md)
- [使用 eBPF 添加 sudo 用户](src/26-sudo/README.md)
Expand Down
1 change: 1 addition & 0 deletions README_en.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ Networking and tracing:

Security:

- [Use eBPF to modify syscall parameters](src/34-syscall/README.md)
- [Hiding process or file information using eBPF](src/24-hide/README_en.md)
- [Terminating processes by sending signals using bpf_send_signal](src/25-signal/README_en.md)
- [Adding sudo users using eBPF](src/26-sudo/README_en.md)
Expand Down
2 changes: 0 additions & 2 deletions src/27-replace/replace.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
#include <unistd.h>
#include "replace.skel.h"
#include "replace.h"


#include <bpf/bpf.h>
#include <bpf/libbpf.h>
#include <unistd.h>
Expand Down
15 changes: 15 additions & 0 deletions src/34-syscall/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.vscode
package.json
*.o
*.skel.json
*.skel.yaml
package.yaml
ecli
bootstrap
.output
bpf-mocker
victim
victim2
test.txt
hijacked
my_test.txt
2 changes: 2 additions & 0 deletions src/34-syscall/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
victim: victim.cpp
g++ victim.cpp -o victim
20 changes: 20 additions & 0 deletions src/34-syscall/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# ebpf modify syscall parameters

## modify open filename

```bash
make
./victim
```

```bash
sudo ./ecli run package.json -- --rewrite --target_pid=$(pidof victim)
```

## modify exec commands

TODO

## reference

- <https://github.com/pathtofile/bad-bpf/blob/main/src/exechijack.bpf.c>
68 changes: 68 additions & 0 deletions src/34-syscall/exechijack.bpf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// SPDX-License-Identifier: BSD-3-Clause
#include "vmlinux.h"
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include <bpf/bpf_core_read.h>
#include "exechijack.h"

char LICENSE[] SEC("license") = "Dual BSD/GPL";

// Ringbuffer Map to pass messages from kernel to user
struct {
__uint(type, BPF_MAP_TYPE_RINGBUF);
__uint(max_entries, 256 * 1024);
} rb SEC(".maps");

// Optional Target Parent PID
const volatile int target_ppid = 0;

SEC("tp/syscalls/sys_enter_execve")
int handle_execve_enter(struct trace_event_raw_sys_enter *ctx)
{
size_t pid_tgid = bpf_get_current_pid_tgid();
// Check if we're a process of interest
if (target_ppid != 0) {
struct task_struct *task = (struct task_struct *)bpf_get_current_task();
int ppid = BPF_CORE_READ(task, real_parent, tgid);
if (ppid != target_ppid) {
return 0;
}
}

// Read in program from first arg of execve
char prog_name[TASK_COMM_LEN];
char prog_name_orig[TASK_COMM_LEN];
__builtin_memset(prog_name, '\x00', TASK_COMM_LEN);
bpf_probe_read_user(&prog_name, TASK_COMM_LEN, (void*)ctx->args[0]);
bpf_probe_read_user(&prog_name_orig, TASK_COMM_LEN, (void*)ctx->args[0]);
prog_name[TASK_COMM_LEN-1] = '\x00';
bpf_printk("[EXECVE_HIJACK] %s\n", prog_name);

// Program can't be less than out two-char name
if (prog_name[1] == '\x00') {
bpf_printk("[EXECVE_HIJACK] program name too small\n");
return 0;
}

// Attempt to overwrite with hijacked binary path
prog_name[0] = '/';
prog_name[1] = 'a';
for (int i = 2; i < TASK_COMM_LEN ; i++) {
prog_name[i] = '\x00';
}
long ret = bpf_probe_write_user((void*)ctx->args[0], &prog_name, 3);

// Send an event
struct event *e;
e = bpf_ringbuf_reserve(&rb, sizeof(*e), 0);
if (e) {
e->success = (ret == 0);
e->pid = (pid_tgid >> 32);
for (int i = 0; i < TASK_COMM_LEN; i++) {
e->comm[i] = prog_name_orig[i];
}
bpf_ringbuf_submit(e, 0);
}

return 0;
}
18 changes: 18 additions & 0 deletions src/34-syscall/exechijack.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// SPDX-License-Identifier: BSD-3-Clause
#ifndef BAD_BPF_COMMON_H
#define BAD_BPF_COMMON_H

// Used when replacing text
#define FILENAME_LEN_MAX 50
#define TEXT_LEN_MAX 20

// Simple message structure to get events from eBPF Programs
// in the kernel to user spcae
#define TASK_COMM_LEN 16
struct event {
int pid;
char comm[TASK_COMM_LEN];
bool success;
};

#endif // BAD_BPF_COMMON_H
112 changes: 112 additions & 0 deletions src/34-syscall/open_modify.bpf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2019 Facebook
// Copyright (c) 2020 Netflix
#include <vmlinux.h>
#include <bpf/bpf_helpers.h>
#include "open_modify.h"

const volatile bool targ_failed = false;
const volatile bool rewrite = false;
const volatile int target_pid = 0;

struct args_t {
const char *fname;
int flags;
};

struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, 10240);
__type(key, u32);
__type(value, struct args_t);
} start SEC(".maps");

struct {
__uint(type, BPF_MAP_TYPE_RINGBUF);
__uint(max_entries, 256 * 1024);
} rb SEC(".maps");

SEC("tracepoint/syscalls/sys_enter_open")
int tracepoint__syscalls__sys_enter_open(struct trace_event_raw_sys_enter *ctx)
{
u64 pid = bpf_get_current_pid_tgid() >> 32;

/* store arg info for later lookup */
struct args_t args = {};
args.fname = (const char *)ctx->args[0];
if (rewrite) {
bpf_probe_write_user((char*)ctx->args[1], "hijacked", 9);
}
args.flags = (int)ctx->args[1];
bpf_map_update_elem(&start, &pid, &args, 0);

return 0;
}

SEC("tracepoint/syscalls/sys_enter_openat")
int tracepoint__syscalls__sys_enter_openat(struct trace_event_raw_sys_enter *ctx)
{
u64 pid = bpf_get_current_pid_tgid() >> 32;
/* use kernel terminology here for tgid/pid: */
if (target_pid && pid != target_pid) {
return 0;
}
/* store arg info for later lookup */
// since we can manually specify the attach process in userspace,
// we don't need to check the process allowed here

struct args_t args = {};
args.fname = (const char *)ctx->args[1];
args.flags = (int)ctx->args[2];
if (rewrite) {
bpf_probe_write_user((char*)ctx->args[1], "hijacked", 9);
}
bpf_map_update_elem(&start, &pid, &args, 0);
return 0;
}

static __always_inline int trace_exit(struct trace_event_raw_sys_exit *ctx)
{
struct event *event;
struct args_t *ap;
int ret;
u32 pid = bpf_get_current_pid_tgid();

ap = bpf_map_lookup_elem(&start, &pid);
if (!ap)
return 0; /* missed entry */
ret = ctx->ret;

event = bpf_ringbuf_reserve(&rb, sizeof(*event), 0);
if (!event)
return 0;

/* event data */
event->pid = bpf_get_current_pid_tgid() >> 32;
event->uid = bpf_get_current_uid_gid();
bpf_get_current_comm(&event->comm, sizeof(event->comm));
bpf_probe_read_user_str(&event->fname, sizeof(event->fname), ap->fname);
event->flags = ap->flags;
event->ret = ret;

/* emit event */
bpf_ringbuf_submit(event, 0);
return 0;
cleanup:
bpf_map_delete_elem(&start, &pid);
return 0;
}

SEC("tracepoint/syscalls/sys_exit_open")
int tracepoint__syscalls__sys_exit_open(struct trace_event_raw_sys_exit *ctx)
{
return trace_exit(ctx);
}

SEC("tracepoint/syscalls/sys_exit_openat")
int tracepoint__syscalls__sys_exit_openat(struct trace_event_raw_sys_exit *ctx)
{
return trace_exit(ctx);
}

char LICENSE[] SEC("license") = "GPL";
19 changes: 19 additions & 0 deletions src/34-syscall/open_modify.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
#ifndef __SYSCALL_TRACER_H
#define __SYSCALL_TRACER_H

#define TASK_COMM_LEN 16
#define NAME_MAX 255
#define INVALID_UID ((uid_t)-1)

struct event {
/* user terminology for pid: */
pid_t pid;
uid_t uid;
int ret;
int flags;
char comm[TASK_COMM_LEN];
char fname[NAME_MAX];
};

#endif /* __SYSCALL_TRACER_H */
33 changes: 33 additions & 0 deletions src/34-syscall/victim.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#include <cassert>
#include <cstdio>
#include <fcntl.h>
#include <iostream>
#include <ostream>
#include <unistd.h>

int main()
{
char filename[100] = "my_test.txt";
// print pid
int pid = getpid();
std::cout << "current pid: " << pid << std::endl;
system("echo \"hello\" > my_test.txt");
system("echo \"world\" >> hijacked");
while (true) {
std::cout << "Opening my_test.txt" << std::endl;

int fd = open(filename, O_RDONLY);
assert(fd != -1);

std::cout << "test.txt opened, fd=" << fd << std::endl;
usleep(1000 * 300);
// print the file content
char buf[100] = {0};
int ret = read(fd, buf, 5);
std::cout << "read " << ret << " bytes: " << buf << std::endl;
std::cout << "Closing test.txt..." << std::endl;
close(fd);
std::cout << "test.txt closed" << std::endl;
}
return 0;
}

0 comments on commit 32e23bb

Please sign in to comment.