GithubHelp home page GithubHelp logo

krisnova / boopkit Goto Github PK

View Code? Open in Web Editor NEW
1.5K 29.0 165.0 909 KB

Linux eBPF backdoor over TCP. Spawn reverse shells, RCE, on prior privileged access. Less Honkin, More Tonkin.

License: Apache License 2.0

Makefile 6.14% C 87.60% Shell 6.26%
tcp linux-kernel-hacking ebpf security

boopkit's People

Contributors

krisnova avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

boopkit's Issues

Userspace ignore IP set

The new #4 feature has noisy public servers firing off ncat commands against it self alot.

Ideally we offer a "denylist" that can be plumbed through to boopkit at runtime so that we only are responding to specific blocks of IPs.

I wonder if there is a good CIDR library in C?

Payload mode (single SYN mode)

Right now there are some encapsulation errors while transmitting the payload over a SYN packet.

Can be replicated:

Run boopkit in payload-only mode

boopkit -p

Boop with a single SYN packet

boopkit-boop -c "ls /"

Output:

  ** Boop EVENT_SRC_BAD_CSUM
  ** Boop source: 127.0.0.1
  -> Search xCap Ring Buffer: 127.0.0.1
  -> Taking snapshot of network traffic.
  -> Snapshot complete!
  -> Found RCE xCap!
  -> Free Snapshot
  <- Executing: ls /o
ls: cannot access '/o'$'\177': No such file or directory

Unable to build fatal error: 'bpf/bpf_endian.h' file not found

Hello,

I wasn't able to build the bin I was receiving this errors:

~/bookit/boopkit-1.3.0$$ make
bpftool btf dump file /sys/kernel/btf/vmlinux format c > vmlinux.h
  ->  Building pr0be.boop.o
clang -S \
    -target bpf \
    -D __BPF_TRACING__ \
    -I/usr/local/include \
    -Wall \
    -Werror \
    -O2 -emit-llvm -c -g pr0be.boop.c
pr0be.boop.c:25:10: fatal error: 'bpf/bpf_endian.h' file not found
#include <bpf/bpf_endian.h>
         ^~~~~~~~~~~~~~~~~~
1 error generated.
make: *** [Makefile:91: pr0be.boop.o] Error 1

I'm using Ubuntu 20.04 / 5.13.0-1022-aws / bpftool v5.13.19

Please let me know if you need more information, thank you.

Privileged access required to load eBPF probe! ๏ผŸ

-> getuid() : 0
-> getpid() : 2468
-> getppid() : 2427
-> Logs : /sys/kernel/tracing/trace_pipe
-> Loading eBPF Probe : /root/.boopkit/pr0be.safe.o
-> Starting xCap Interface : lo
-> Initalizing Ring Buffer
libbpf: prog 'handle_getdents_patch': BPF program load failed: Invalid argument
libbpf: prog 'handle_getdents_patch': -- BEGIN PROG LOAD LOG --
R1 type=ctx expected=fp
0: R1=ctx(off=0,imm=0) R10=fp0
; size_t pid_tgid = bpf_get_current_pid_tgid();
0: (85) call bpf_get_current_pid_tgid#14 ; R0_w=scalar()
; size_t pid_tgid = bpf_get_current_pid_tgid();
1: (7b) *(u64 *)(r10 -8) = r0 ; R0_w=scalar() R10=fp0 fp-8_w=mmmmmmmm
2: (bf) r2 = r10 ; R2_w=fp0 R10=fp0
;
3: (07) r2 += -8 ; R2_w=fp-8
; long unsigned int *pbuff_addr = bpf_map_lookup_elem(&map_to_patch, &pid_tgid);
4: (18) r1 = 0xffff99f6c34db400 ; R1_w=map_ptr(off=0,ks=8,vs=8,imm=0)
6: (85) call bpf_map_lookup_elem#1 ; R0_w=map_value_or_null(id=1,off=0,ks=8,vs=8,imm=0)
; if (pbuff_addr == 0) {
7: (15) if r0 == 0x0 goto pc+56 ; R0_w=map_value(off=0,ks=8,vs=8,imm=0)
; long unsigned int buff_addr = *pbuff_addr;
8: (79) r7 = *(u64 *)(r0 +0) ; R0_w=map_value(off=0,ks=8,vs=8,imm=0) R7_w=scalar()
9: (b7) r8 = 0 ; R8_w=0
; short unsigned int d_reclen_previous = 0;
10: (6b) *(u16 *)(r10 -10) = r8 ; R8_w=P0 R10=fp0 fp-16=00??????
11: (b7) r9 = 16 ; R9_w=16
12: (bf) r6 = r7 ; R6_w=scalar(id=2) R7_w=scalar(id=2)
13: (0f) r6 += r9 ; R6_w=scalar() R9_w=16
14: (bf) r1 = r10 ; R1_w=fp0 R10=fp0
;
15: (07) r1 += -10 ; R1_w=fp-10
; bpf_probe_read_user(&d_reclen_previous, sizeof(d_reclen_previous),
16: (b7) r2 = 2 ; R2_w=2
17: (bf) r3 = r6 ; R3_w=scalar(id=3) R6_w=scalar(id=3)
18: (85) call bpf_probe_read_user#112 ; R0=scalar() fp-16=mm??????
; (struct linux_dirent64 *)(buff_addr + d_reclen_previous);
19: (69) r1 = *(u16 *)(r10 -10) ; R1_w=scalar(umax=65535,var_off=(0x0; 0xffff)) R10=fp0
; (struct linux_dirent64 *)(buff_addr + d_reclen_previous);
20: (0f) r7 += r1 ; R1_w=scalar(umax=65535,var_off=(0x0; 0xffff)) R7_w=scalar()
21: (0f) r7 += r9 ; R7_w=scalar() R9=16
; short unsigned int d_reclen = 0;
22: (6b) *(u16 *)(r10 -12) = r8 ; R8=P0 R10=fp0 fp-16=mm00????
23: (bf) r1 = r10 ; R1_w=fp0 R10=fp0
;
24: (07) r1 += -12 ; R1_w=fp-12
; bpf_probe_read_user(&d_reclen, sizeof(d_reclen), &dirp->d_reclen);
25: (b7) r2 = 2 ; R2_w=2
26: (bf) r3 = r7 ; R3_w=scalar(id=4) R7_w=scalar(id=4)
27: (85) call bpf_probe_read_user#112 ; R0_w=scalar() fp-16=mmmm????
; short unsigned int d_reclen_new = d_reclen_previous + d_reclen;
28: (69) r1 = *(u16 *)(r10 -10) ; R1_w=scalar(umax=65535,var_off=(0x0; 0xffff)) R10=fp0
; short unsigned int d_reclen_new = d_reclen_previous + d_reclen;
29: (69) r2 = *(u16 *)(r10 -12) ; R2_w=scalar(umax=65535,var_off=(0x0; 0xffff)) R10=fp0
; short unsigned int d_reclen_new = d_reclen_previous + d_reclen;
30: (0f) r2 += r1 ; R1_w=scalar(umax=65535,var_off=(0x0; 0xffff)) R2_w=scalar(umax=131070,var_off=(0x0; 0x1ffff))
; short unsigned int d_reclen_new = d_reclen_previous + d_reclen;
31: (6b) *(u16 *)(r10 -14) = r2 ; R2_w=scalar(umax=131070,var_off=(0x0; 0x1ffff)) R10=fp0 fp-16=mmmmmm??
32: (bf) r2 = r10 ; R2_w=fp0 R10=fp0
;
33: (07) r2 += -14 ; R2_w=fp-14
; long ret = bpf_probe_write_user(&dirp_previous->d_reclen, &d_reclen_new,
34: (bf) r1 = r6 ; R1_w=scalar(id=3) R6=scalar(id=3)
35: (b7) r3 = 2 ; R3_w=2
36: (85) call bpf_probe_write_user#36
unknown func bpf_probe_write_user#36
processed 36 insns (limit 1000000) max_states_per_insn 0 total_states 1 peak_states 1 mark_read 1
-- END PROG LOAD LOG --
libbpf: prog 'handle_getdents_patch': failed to load: -22
libbpf: failed to load object 'pr0be_safe'
libbpf: failed to load BPF skeleton 'pr0be_safe': -22
Unable to load eBPF object: /root/.boopkit/pr0be.safe.o
Privileged access required to load eBPF probe!
Permission denied.

trigger missing?

The README (and remote/remote) makes reference to the trigger binary, but it doesn't seem that there's source nor a Makefile rule to build it. Was this intentional?

Trigger Not Working

I am opening an issue specifically for this, as I assume folks are going to find it very quickly.

Right now boopkit works by sending a malformed TCP packet. That means, a TCP packet with a bad checksum. There are a few implications of this (for example IPv6 does not have a concept of a checksum) limitation to boopkit.

Most enterprise grade networking hardware will not deal with these types of TCP packets. In other words, if a server is running behind a proxy, a firewall, or some other form of gateway there is a high chance that the networking hardware will drop the malformed TCP packet before it reaches the destination.

In this situation boopkit will still be vulnerable to malformed TCP packets, simply the trigger will not be able to reach the destination.

I will open up other issues and features to try to address this limitation, but for now at least here is the explanation on what is going on.

Build issue: invalid relo against 'pid_to_hide'

Hey there, I was trying to build this project on a fresh Ubuntu 20.04 install

I installed the following for the main dependencies:

  • linux-tools-common
  • linux-tools-5.13.0-40-generic
  • clang
  • llvm
  • gcc-multilib
  • the linux headers

For xdp tools: https://github.com/xdp-project/xdp-tools

  • m4
  • zlib1g
  • zlib1g-dev
  • libelf1
  • libelf-dev
  • libpcap-dev

I also installed libbpf from source: https://github.com/libbpf/libbpf

When I tried to run make, I got this error:

user@xb2004d2:~/git/boopkit-1.3.0$ make
bpftool btf dump file /sys/kernel/btf/vmlinux format c > vmlinux.h
  ->  Building pr0be.boop.o
clang -S \
    -target bpf \
    -D __BPF_TRACING__ \
    -I/usr/local/include \
    -Wall \
    -Werror \
    -O2 -emit-llvm -c -g pr0be.boop.c
llc -march=bpf -filetype=obj -o pr0be.boop.o pr0be.boop.ll
  ->  Building pr0be.safe.o
clang -S \
    -target bpf \
    -D __BPF_TRACING__ \
    -I/usr/local/include \
    -Wall \
    -Werror \
    -O2 -emit-llvm -c -g pr0be.safe.c
llc -march=bpf -filetype=obj -o pr0be.safe.o pr0be.safe.ll
  ->  Building pr0be.xdp.o
clang -S \
    -target bpf \
    -D __BPF_TRACING__ \
    -I/usr/local/include \
    -Wall \
    -Werror \
    -O2 -emit-llvm -c -g pr0be.xdp.c
llc -march=bpf -filetype=obj -o pr0be.xdp.o pr0be.xdp.ll
  ->  Building eBPF pr0bes
  ->  Generating pr0be.skel.safe.h
bpftool gen skeleton pr0be.safe.o -p > pr0be.skel.safe.h
libbpf: prog 'handle_getdents_exit': invalid relo against 'pid_to_hide' in special section 0xfff2; forgot to initialize global var?..
make: *** [Makefile:47: skeleton] Error 255

During this process I also noticed that a file named 'm'$'\177' appeared with the content stable\n, which makes me think there was an environment variable or something that I may have not properly set up. In any case, would love some guidance on what the possible solution might be. Thank you!

coredump on ubuntu 21.04 with libbpf 0.6.1 and libbpf 0.7.0

hi whitehat, coredump on ubuntu 21.04, and what env you used ?

env

os:ubuntu 21.04
kernel: Linux vm-server 5.11.0-49-generic #55-Ubuntu SMP Wed Jan 12 17:36:34 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
golang:go version go1.17.2 linux/amd64
clang:Ubuntu clang version 12.0.0-3ubuntu1~21.04.2
libbpf:0.6.1/0.7.0

how to reproduce

coredump

make
sudo make install
boopkit -x 127.0.0.1
  -> Logs: cat /sys/kernel/tracing/trace_pipe
  -> Loading eBPF Probe: /root/.boopkit/pr0be.safe.o
  -> Obfuscating PID: 12973
  -> eBPF Probe loaded: /root/.boopkit/pr0be.safe.o
  -> Loading eBPF Probe: /root/.boopkit/pr0be.boop.o
libbpf: failed to find BTF for extern 'inet_ntop' [28] section: -2
Segmentation fault

debug with gdb

gdb
und-section

why

why linker create two *UND* section into pr0be.boop.o for inet_ntop and inet_pton.
how can it works?

thanks.

Additional trigger (tcp_receive_reset)

Because of #3 we need to entertain alternative triggers other than tcp_bad_csum.

We can consider trying another trigger mechanism (tcp_receive_reset) which will allow the trigger to establish a TCP connection with the server, and midway through the TCP handshake send a reset.

I need to research how far along in the TCP handshake we need to be in order to trigger the eBPF probe. Regardless, most TCP connections will allow for a full handshake and data transmission regardless of authentication status. This is how SSH, Kubernetes, etc works.

Hide userspace component

Unacceptable options:

  • LD Preload example
  • Embed into another persistent Linux process (such as /usr/bin/init)

What I would like to do here is use the eBPF probe to hide itself! We should be able to hook into the systemcall filters for Linux and actually prevent userspace from finding the process itself. This would be a huge deal for eBPF backdoor communities!

Detection

We need a way to detect and ultimately stop boopkit :)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.