-
-
Notifications
You must be signed in to change notification settings - Fork 396
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
289 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
victim: victim.cpp | ||
g++ victim.cpp -o victim |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |