- Good everyone, my name is Pat,
I'm PathToFile on Twitter, Github, Discord,
and most other places.
And this talk is about Creating and Countering
the Next Generation of Linux rootkits using eBPF.
So today we're gonna start with an overview
on what Linux Kernel rootkits are,
and we're gonna cover why rootkits
are such a powerful tool for attackers,
but why they're so dangerous to use.
Next, we're gonna introduce eBPF,
and we're gonna discuss on how it can enable
an attacker to have all the best odds of a kernel rootkit
without any of the risks.
Then finally, we're gonna cover how to detect
and prevent eBPF based rootkits
before they take over as the preferred
rootkit type for attackers.
So firstly, what are kernel rootkits?
Well, once an attacker compromises a machine,
they're going to want to maintain that access.
So perhaps they exploited a vulnerability
in a web application or use some stolen credentials.
These holes can be closed.
And when they are,
the attacker is gonna want a way to regain access
to that machine,
preferably with root privileges and preferably
in a way that is undetectable to security systems
or systems administrators.
This is the role of a root kit.
And in terms of access,
there's no better places to put a root kit,
than in the kernel.
When a program wants to list the files
in a directory, it'll use a syscall to ask the kernel
to read the data from the hard drive on its behalf.
If a rootkit can hook or intercept this call
then it can simply remove any sensitive file
from the directory listing before passing
it back to the kernel.
This same technique can be used to hide files,
processes, network connections really cannot do anything
to hide from user space programs.
Now by living in the kernel the rootkit also has the ability
to tap into old network traffic before any firewall
and has the ability to launch processes with root privileges
or alter the privileges of existing processes.
So this all sounds incredibly useful for an attacker,
so what's the problem?
Well, by running code in the kernel
it's very easy to turn a small mistake
into a very big problem.
There isn't any guard rails or safety lines in the kernel.
Once code is running there,
it has the ability to read and write to almost anything.
This means if there's a bug in your code
and you write to the wrong part of memory,
you're likely to crash the kernel
and you crash the kernel you crash the entire system.
And it could be even worse,
if the kernel happened to be riding to a hard drive,
when you broke things,
you could end up corrupting that disc effectively breaking
the entire system.
Doing this will almost certainly bring in administrators
and incident responders to determine what happened.
So this is far from an ideal outcome for an attacker.
Now, even if the rootkit developer was very careful,
a kernel update has the ability to alter
what hooked function looks like
or what new kernel object looks like.
And all of this just increases the likelihood
of a disaster from occurring.
This means that a rootkit developer
often has to test the rootkit against
every single kernel version that it plans
to be deployed upon.
So the good parts of kernel root kits
sound really good for an attacker,
but the risks are often too high to make it viable.
If only there was a way to keep the only
advantages of a kernel rootkit,
but have the safety and portability
of a user space program.
So, how about we add JavaScript-like
capabilities to the Linux Kernel?
Now to some people, this quote might sound like
the most wildest thing they I've ever heard.
But when Thomas Graff from Isovalent made it,
he wasn't talking literally about putting JavaScript
in the Kernel.
What he was talking about was introducing a way
to run a certain type of code that has the visibility
of the Kernel, but with the ease safety
and portability of such user space systems,
such as JavaScript programs.
And really what he was talking about was eBPF.
So what is eBPF?
So eBPF stands for, Extended Berkeley Packet Filtering,
but it has grown so much from the original BPF,
particularly in the last two years,
that any comparison to this classic version
isn't really relevant today.
So what it is, it's a system within the Linux Kernel
that allows you to create programmable trace points
known as eBPF programs.
These programs can be attached to network interfaces
to observe network traffic or the entry or exit points
of Kernel functions, including syscalls
and can even actually attach
to user space programs and functions.
If this sounds like the same places
as our kernel rootkit, you'd be correct.
But unlike the Kernel rootkit eBPF programs are guaranteed
to be safe from crashing the system.
And they're even portable across Kernel versions
and even system architectures.
So to explain how eBPF can achieve this,
let's have a look at how eBPF programs
get written and loaded.
So we'll start with writing the eBPF program.
So these are typically written in a restricted
version of C or Rust,
and there's an example of one in the bottom left.
So the programs have variables, loops, IF statements,
all the standard parts of the language,
but they're heavily restricted
in what external functions they can call.
And it's limited to only a number of BPF helper functions.
Now, instead of compiling this code into native assembly,
eBPF programs actually get compiled
into what's called BPF bytecode.
Which is fairly simple, but straightforward instruction set,
but the most important thing about this
is that the BPF bytecode is independent
of the architecture or kernel version that was compiled on.
Now, once this bytecode has been compiled,
it is now ready to be sent to the Kernel.
So this code is sent to the Kernel
using a user space program called a loader,
which makes use of the BPF syscall
to send it up into the Kernel.
Now, technically non root users
can load some eBPF programs on some kernel configurations,
but these programs are extremely limited
in what they can do,
so they're out of scope for this sort of talk.
So for the purpose of this talk,
this loading has to occur from either the root user
or systems administrator.
Now the Kernel just doesn't blindly trust this bytecode,
so if the kernel runs what's called the BPF verifier,
which checks every branch and every possible value
of every possible variable in this code
to make sure that it is not doing things
such as trying to read in ballad memory
or slow the system down,
or by being too big or complex, or do really anything else,
that might cause the kernel to crash.
So this is where eBPF gets a safety guarantee
because only code that passes
all of the verifies extensive checks
is allowed to actually be loaded and run.
Now, once code has passed the verifier,
the coder will then actually run a compile
to convert the bytecode into the native instructions
that match that machine's architecture in kernel version.
So if it's an X86 machine or compiler it to 2X86
or if it's (indistinct) for example.
Now, by running this native instructions,
eBPF code can run as fast as efficient
as regular kernel code for that machine.
But this is not only this, what this compiler does,
it actually also dynamically looks up the addresses
of the BPF helper functions
or the any Kernel objects that the code is using,
and it will actually patch the instructions
to match that specific kernel version.
And so this is where the code can be portable
because this compilation step knows exactly
what the format of that helper function
and what that object looks like for that specific kernel.
And so by patching the instructions
as it goes to compile it,
it means that that code will be specifically
designed to run on that system.
Now once these programs are compiled,
they are attached to either the network interface
or the kernel function that they need
to be attached to where they
will run once for every packet or function code.
Now programs can't retain state from one run to the next,
but they can make use of a global key value store
called an eBPF map.
And so programs can actually store their state
in that between runs,
and then the next time it runs,
it can read that state and then pick up where it left off.
Now that is an extremely quick overview on what eBPF is,
I'll have links to much more,
in-depth documentation at the end of this.
But for now I wanna go into what are the attacker
with the privileges to load
and run eBPF programs can do?
And how can they use it to achieve the same rootkit
functionality as a regular kernel rootkit?
So, the first thing we're gonna cover is using
eBPF to warp the network reality.
So this is a diagram of a fairly standard web service
set up, it has two network interfaces.
So on the left,
we have the internet facing network interface.
Where a firewall only allows traffic
to and from a website that's listening on, say port 443.
Now on the right, we have the administrators access.
So this is via a separate network interface
that is attached to an internal VPN network.
And there's an SSH server listing on this internal section.
And that's how the administrators,
when they wanna access the machine
they will go through the internal network
and SSH onto this machine.
But to make things interesting,
let's say this SSH connection requires
multi-factor authentication.
Now an attacker who's gained access to this machine
will probably want the ability to connect
in from the internet,
but they still wanna be able to gain
the same privilege access from the host,
that seems to be limited only to the internal VPN side.
So eBPF programs have the ability to read and write
all network packets across all interfaces.
And before the firewall has the ability
to block the connection.
What this means is if there was a connection
to come in from an attacker's IP address,
even to a closed port,
it was coming from the internet.
Then eBPF can actually alter both the destination
and source IP addresses and ports
to make it look like this traffic is
actually coming from a fake IP address
that matches the internal VPN side.
It can then route the traffic into the internal interface,
into the SSH service.
And so for the prospective of SSH
this looks like just a regular connection
from the internal systems.
Then not only will SSH see this traffic is regular,
if an administrator is using tools such
as Wireshark or Netstat or TCP Dome,
then from the perspective of these tools,
the network connection also only appears
to be coming from the fake IP address
on the internal network.
And they will have no idea that the connection
is actually being routed from the internet.
Now this isn't the only tactic eBPF can employ
because it has the ability to read
and write network packets.
It has ability to see any network packets
before any other system.
So it has the ability to receive command and control
information from even a port that nothing is listening on,
and then it can just silently drop those pockets,
so no security system will know that
that come out of control data has actually
reached the system.
Then while eBPF can not create its own connections,
it has the ability to clone existing packets.
So it could close some existing traffic that some existing,
legitimate traffic, that say going to the website,
then alter the destination IP addresses
to be the attacker's IP address,
and then alter the actual data within the packet
to be whatever it wants,
and then it can send it off to the attacker.
So this technique could be used to exfiltrate arbitrary data
from the machine.
Then finally, eBPF programs can be attached
to the user space programs.
So for example, it could be attached to the website
and hook into the functions that do the TLS encryption
and decryption for the website.
Now we'll explain in more detail how that function hooking
works in the next section,
but what this does enable, is it actually enables eBPF
to change out the data underneath
the encrypted TLS connection.
So that even from an external network monitor,
it would only see
legitimate TLS traffic going to it from the website.
And it doesn't actually know that eBPF
might be reaching underneath VTLS
and swapping out the website's data to be
some exfiltrated data from the system.
So altering data across the network is only one type
of malicious behavior eBPF can do.
The real strength actually lies in its codal
hooking functions and even syscall deception.
Because it's the disability that allows it to walk reality
around files, processes, and even uses.
So going back to my SSH example,
it's not enough to just be able to connect to the service.
If logging on requires a valid password and multifactor
authentication, then it's unlikely the attacker
we'll be able to easily log on.
But what if there was a way to make SSH ignore this
multi-factor requirement or even the username and password
requirement, and just allow anybody to log onto the system?
SSH knows that there's extra requirements
such as multi-factor due to configuration files
that are in the Etsy pam D folder.
And when a user is going to authenticate a user's name
and password, it'll look inside the Etsy password
and Etsy shadow files to make sure
that the supplied username and passwords are correct.
So is there a way that eBPF can lie about the contents
of all of these files?
So, yes.
And to explore how eBPF can do this,
let's first quickly revisit how you user space programs
actually read files using the syscalls.
So when a person wants to read a file, it actually
make true syscalls to the Kernel.
So the first is to open or open at,
and this will check that the file that the program
wants to open, actually exists
and the user that's wanting to read the file,
is actually allowed to do so.
Now, if they are, the Kernel will return,
what's called a file descriptor number or FD number,
which is simply a reference to that file for that process.
Then the process will make a second syscall
this time to read where
asking the kernel to read the file
that matches the supplied FD number
it got from the open call.
And it'll actually give a memory buffer to the kernel
to fill in with the files, content.
The kernel then look up that FD number,
make sure it's a valid number,
then grab the file and I'll copy the file
of the data into that process as a buffer,
before returning to the user space process.
What this means is, if we have four different eBPF programs,
we can observe what's going on
and we can actually watch,
what is both being sent to and from
these two different sets of syscalls.
What this means is we're able to track
what FD number corresponds to what file name.
And we can even actually read what the data is contained
within the file before the youth space program,
by reading the contents of the buffer
after the Etsy call has as exited,
which would be that eBPF program at the bottom.
But reading buffers, isn't the only thing eBPF can do,
it can also write to them.
So let's have a look at this basic example.
On the left is a very simple user space program,
it is looking to open the file called read me,
and then it's asking the Kernel using the read syscall
to read the data from that file into a buffer called buffer.
Now on the right is the eBPF program
that is attached to the exit of the read syscall.
So after the file has been opened,
and after the user space program, asked the Kernel
to read the file,
the kernel will read the file into the buffer
but before the user space programs gets control again,
our eBPF program is going run.
So you can see at the start of this program
that it's using the BPF probe read user function
to read the contents of that buffer,
which at this stage we'll include the file data.
But, there was also a BPF program write user function.
Now this program, this actually allows us
to alter the data within that buffer,
and then write it back into user space memory
before the user space program sees it.
What this means is once a eBDF program exits
and controllers returned to the user space program,
the program will think that the contents of buffer
contains the file data,
when in actuality it contains
the fetched data been put there by eBPF.
This BPF right user code can be used to override
any user of space, buffer pointer, or string
that gets passed into or out of the
syscalls kernel functions.
So things like changing what program getting launched
by execve or reading an altering
net like data heaps of different stuff
can be possible with this call.
So another thing eBPF can do is bypass
the syscall altogether.
And instead, just pretend that the function ran
and return an arbitrary error code or return value.
This can be done using the F mode read type of EPF program.
Which while these can be attached to every function,
they can be attached to every syscalls
at least on newer kernels.
So for example, the example in the top, right,
this program simply pretends to write to a file
and it returns the expected success code
to indicate that the file was actually written,
but the file is never actually written
then the right syscall was never actually called.
Now, if the goal is to prevent a process from discovering
or stopping the rootkit,
a more drastic option can be to simply kill the process.
So by using the eBPF sends signal helper function,
the program can send an unstoppable SIGKILL signal,
which will immediately instruct the code
on to start tearing down that process,
regardless of whether it wants to what or not.
Now, this is a pretty drastic action
that could probably be noticed,
but it's certainly a possible way to prevent
an action from occurring.
Now, killing every process that attempts to open any file
is gonna be a quick way to having a really bad time.
So thankfully, eBPF programs have lots of ways
to tailor an action based on who or what is performing.
So eBPF programs can do different things
based upon the process name, the user ID,
the value of arguments being passed
or returned from that function.
And it can even take cues from other eBPF programs.
So for example, it could only start
tampering with the read calls from a file
only after connection
from a specific IP address has occurred.
So looking back to our SSH example,
to bypass multifactor eBPF can simply overwrite
the data being read from the Pam configuration files
to remove any mention of multifactor.
It could then even overwrite the data
in Etsy password and Etsy shadow,
to insert a fake user account and password,
which would enable logging in to the machine
with a completely fake set of accounts.
By having eBPF only target the SSH process,
it means to an administrator using tools
like cat or vim or a security tool,
or even to file forensics looking
at the actual file on disk.
All of these will only show the normal unedited file.
Only SSH will be presented with the warped
reality version of this data.
Okay, so now it's time for some demo.
The first demonstration that we're gonna go through
is the ability to replace text within the arbitrary files.
So we can see in the shell on the top, right,
that there is a folder with a file called file.
And when we look inside this file,
we see the text, this is real data.
So now we're gonna go ahead and load up the first
of our eBPF rootkits into this shell on the left.
So this rootkit is going to look for any type of process,
that means the word file,
and it's gonna replace any data that contains
the text real with the word fake.
But specifically it's not going to affect every process,
it's only going to affect children
of this specific person's ID.
Which we can see, that matches with our shell on the right.
So, we're gonna go ahead,
our rootkit is now started,
and now back to our shell, when we go to read this file,
we can see that the data has been changed
and it says, this is fake data.
And in fact, the log from the root kit actually
says that it did detect that this process started,
which was cut, and it replaced the text that
that process read.
But what is interesting if we go to this shell now
on the bottom, right,
because this is a different shell
with a different process ID,
even though we're in the same folder,
and we you look at the same file,
it sees the unaltered data.
So this is a technique that has many, many uses.
The example that we've used in the presentation
is this is a way that you can add a user
into the Etsy password file,
but only do that for an SSH process
and not for any auditing software or system administrator,
having you look at that file.
So the next demonstration we're gonna go through
is the ability to stealthily enable
a user to use Sudo to (indistinct).
So typically on this machine,
if we have a look at this shell in the bottom right,
this is running as the user called Lonpriv.
And if word priv wanted to become root using Sudo,
what we can see...
Oh Lonprtiv is not allowed in the sudoers file.
And in fact, if we use the root shell on the top right,
we can double and triple confirmed that lonpriv
is not in this list.
So first off we can use the sudo dash L command
to say, hey, what privileges
does Sudo believe this user to have?
And when we run it,
we see user Lonpriv is not allowed to run
and in fact, we can even add this most basic level,
just go and read
the Etsy Sudo's file
and look for the user Lonpriv
and sure enough, that user is not in there.
So this user Lonpriv is definitely
not able to become root user in Sudo.
That is until we run the second
of our eBPF rootkits on the left.
So this one is going to look for any time,
anything that is opening, specifically Sudo,
is going to try to open the Etsy Sudo file.
And it's just going to alter the text in that file
to say, hey, Lonpriv is actually in there
and they do actually have those privileges.
But it's only going to do this,
not only when just Sudo is running,
but only when sudo is being run specifically
from Lonpriv.
So now this root could have started
if Lonpriv were to use Sudo again and say, who am I?
Well, look at this, it can become root.
In fact, it didn't even need to enter its password.
So how does that work?
Well, so if as Lonpriv,
we now ask Sudo to tell us, hey what privileges
do you think I have?
Well, we can see that from when Sudo
is running as Lonpriv it says,
hey lonpriv has the ability to do anything it wants
without even needing to add in any password.
But even with this rootkit running,
if we were to check these permissions as a different user,
it still says, hey Lonpriv is no longer here,
and if we check that file, it still says
that Lonpriv is not in there.
So this file is only altered,
not only when it's just a Sudo process running,
but only when it is a Sudo process being run
by that Lonpriv user.
The last example that we're gonna go through
is the ability
to kill arbitrary processes
as a sort of self protection idea.
So, typically an administrator can use a tool
called BPF tool,
and this lists, the running eBPF programs
that are running on that system.
And it's got the ability to see what programs are running.
So for example, we can see a lot of eBPF programs
that actually relate to that system deed
currently running on this system.
And BPF tool has the ability to list
the running processes,
to dump out the instructions
and even seeing what process IDs
are actually related to that eBPF program.
So, this is a good way for administrator
to see what eBPF programs are running
to potentially discover something like
an eBPF rootkit.
So we're gonna load up a rootkit that is running
on the left.
And now, if we attempt to use BPF tool
to list the processes,
oh, the process just gets killed before
that information happens.
So this is pretty extreme,
but this demonstrates that eBPF has the ability
to sort of protect itself by just killing
any process that it's attempting
to do any sort of investigation.
So now we're gonna cover some other features of eBPF
and then get into some limitations of it.
So three features that we haven't yet covered,
but I think are definitely worth mentioning.
Firstly, on some network cards,
you can actually run the eBPF programs
on the the network kernel hardware itself,
instead of in the kernel.
So for regular developers,
this is great because this can drastically increase
the packet processing speeds.
But from a rootkit perspective,
this is interesting to know because what this means
is that any packet alterations made by an eBPF program,
that if this program is running on network card,
this will occur after the Linux kernel
has tentatively scanned that packet for anything malicious.
So if you were to send a packet to add malicious IP address,
but send it to a benign IP address,
then only once it's left the kernel and then inside the
network card do you alter it to the dodgy IP address,
well, any security system that's running in the kernel
won't see that alteration.
So, secondly, up until recently eBPF programs
that are attached to Kernel functions or syscalls
require their user space loader
to continue to run once the program is up and running.
And in fact, if that you user space loader where to exit,
then the kernel would just assume that you also want
to stop running eBPF programs and shut them down.
Now, if newer kernels there's been the introduction
of these F entry and F exit type of BPF programs.
Now these actually have the ability to be pinned
to add this SIS SBPF folder,
which what this means is a special file gets created
under this folder one for each BPF program,
and then for as long as this file remains there,
the loader is free to exit, delete itself,
be completely removed and eBPF of programs
will continue to run.
Then when you want to stop them,
you just delete the files.
So finally, the thing worth mentioning is
as we said before, the BPF verifier
put strict limits in how complex
an individual eBPF program can be,
but they exist in mechanism to chain multiple programs
together using the BPF,
using this helper function called a BPF tail code.
Now this requires some preparation and making use
of those eBPF maps we mentioned,
but the end result is the system as a whole
can be much more complex than what a single eBPF program
is allowed to be.
So for example the right,
this is full code graphs that are from four different
eBPF programs that actually just make up one half
of that text, replacing rootkit that we just demonstrated.
Now each individual program is pushing the limit
on what a single eBPF program is allowed to do,
but all combined the system as a whole can be
much, much more complex.
Now there's a number of limitations to writing
a rootkit using eBPF.
So the first one is when using the BPF right user function
to overwrite the buffer,
there is a small window of time between
when the syscall fills the data inside the buffer,
and when eBPF overwrites it.
Now this time, I know it doesn't matter
in single-threaded programs because
the current execution is not gonna return
to the user space program until after eBPF
has done its thing,
but in a multi-threaded program,
a second thread could be constantly reading
the contents of that buffer and actually get read
what is the true data from the syscall
before eBPF has a chance to tamper with it.
Now, the first major issue do you using eBPF
as a rootkit, is program's don't persist across the reboot.
So what this means is when a machine restarts
the user space loader is needed to run again
to load and attach all those eBPF programs
back into the kernel.
Now, the second major thing is that eBPF programs
caught right to kernel memory,
because this would almost certainly break
those safety guarantees of eBPF.
What is means if a security tool is running in the kernel
such as audit D or a Linux security module,
these are gonna be unaffected by eBPF tampering.
But one thing to note about these is that
wireless security product might be running in the kernel
they usually administrated by user space tools.
So if a rootkit were to disable the security tool
in the kernel, but then lie to the user space controller
about the current running status of the system,
that might be enough to fool the system
into thinking that it's more secure than it actually is.
Okay, let's talk about the defensive side of things.
So we're gonna start with file forensics.
So if you're looking to detect files
that contain eBPF code,
there's a couple of things to think about.
So for starters, the file that gets generated
by the compiler, when compiling a program to BPF bytecode
is actually an ELF file.
Where the byte code is inside a named section
within that ELF.
So what this means is that tools such as read ELF
or object jump can actually used to pass these files
and extract the BPF bytecode.
So for example, the eBPF program on the top right,
is being attached to the execve trace point
that TP syscall exactly in top.
What happens is when this gets compiled,
that TP syscall execve is actually
becomes the name of the section inside the ELF
that contains the raw bytes.
So you can use a tool then to read that section
and extract the eBPF bytecode.
Now it's important to note,
that's just the object from the compiler,
that's not the user space loader.
Because what gets sent to the kernel is just the BPF bites.
Now it's important to note that
a lot of loaders are gonna be written
using this LIBBPF library.
Because this is a library that is actually
part of the Linux source tree
and makes it a lot easier to read, and write
and manage eBPF programs.
Now, if a loader is using LIBBBPF,
what this library will actually do,
it'll actually embed the entire ELF object
from the compiler inside the users space loader.
So you end up with an ELF inside of an ELF.
And so therefore if you're wishing to extract the byte code,
you would first need to look at the read only data
inside the load up, extract the ELF from there,
and then possibly extract that data
to find the correct section, to get the BPF bytecode.
Now, once you do extract the byte code,
the biggest thing to look for would be evidence
of that BPF probe right user function.
It might be more difficult to automatically tell
if network packet altering program is malicious or not,
but I can't imagine too many legitimate use cases
of this BPF pro right user function.
Now I haven't touched at all on what BPF byte code
instructions actually look like,
but the instruction code
that comes out of the first compiler
is that example on disk.
So the 85, and then the 24 batches
with the BPF probe write user function.
But if you remember, the byte code is architectural
and kernel version agnostic.
And so what happens is when this bytecode
gets sent into the kernel as we explained,
the kernel will actually patch that 24
to match up with what is the correct address
for that kernel.
So if you're looking at the byte code
that's being stored inside the kernel
you would actually then to not need to dynamically
look up that memory address
to determine that is the appropriate user function.
And then if you're looking at the native card
after the JIT compiler inside the kernel
then this is definitely
just gonna look like a regular kernel instruction.
So you would need to look up that
again, dynamically look up that memory address
to determine that is the probe write user function.
So to protect a running system,
I think one of the strongest defenses
would be to monitor that BPF, syscall
which, you could use eBPF to monitor eBPF.
So monitoring for what programs are loading
and running eBPF programs, is gonna be a really good tactic.
Because realistically, this should only be a small
number of known programs
that are actually interacting with eBPF.
Now, if a program actually sounds suspicious
because eBPF has intercepted the syscall,
you could actually extract the program's bytecode,
and then send it to somewhere else to be analyzed
where you could detect (indistinct)
suspicious behavior in the code.
So a lot of the things I've covered so far,
assume that and eBPF rootkit is not already
an installed and tampering with the system.
Because if it is already running,
it actually would have the ability to either block
or hide a bunch of these user memory process scanning file,
that a standing files or attempting
to load an eBPF program.
But even kernel rootkits have a hard time
hiding from memory forensics.
Which particularly if the machine is virtualized,
the memory forensics can be acquired from underneath
the kernel hardware, a hypervisor,
or even the physical level.
Volatility is the name of an excellent
memory forensics tool.
And in fact, at this years is black card,
the team is releasing some new plugins specifically
around acquiring and analyzing Linux tracing forensics.
Now, as I'm prerecording this talk,
I don't know exactly what they're gonna cover,
but I did speak briefly with a number of the team members
before I recorded this,
and I'm really excited to actually get ahead
a lot and play with the plugins
that they're producing, because
they sound incredibly interesting.
So one final prevention could be to just straight up disable
any use of eBPF within the code.
Now this requires you to recompile the kernel
with the relevant flags disabled and by doing so,
you'd lose all the advantages of using eBPF
for your own reasons,
but this is definitely an option for some.
So a different additionally at the moment,
there is some discussions going on within the community
about how to cryptographically signed eBPF programs
in the same way that you can sign kernel modules.
Doing so would allow a system to load
only trusted eBPF programs,
but prevent unknown or untrusted programs
from being loaded and used.
Now, implementing this is definitely nontrivial,
particularly due to that compilation step,
but some smart people are really looking at this.
And so in the future, this may end up being
the best defense against eBPF base rootkits.
Before we finish quickly, what else can eBPF do?
So, firstly, eBPF now runs on Windows.
So in May Microsoft released the start of a project
on GitHub called eBPF for Windows.
It's in the early stages at the moment,
it's only got the network observability side of things
and not the function hook or syscall hooking.
But a lot of people including myself,
are really interested in seeing how this project evolves.
So if you're interested in Windows at all,
I would highly recommend checking out this project.
Now, another thing I wanted to mention
is that warping reality, isn't just for attackers.
So these same ideas around altering file
or network data is also incredibly useful
to reverse engineers.
Either doing malware analysis or even bug hunting.
So for example, it's not uncommon for malware
to perform a series of checks
to determine if it's actually running on a victim machine,
or if it's running in an analysis Sandbox, such as Cuckoo.
Now, the malware will check things
such as the number of CPU calls, the machine uptime,
the number of files within the template folder.
It might even actually look at the manufacturers,
of the network cards to determined
is that a real card or a virtual machine.
So thanks to eBPF we can fake the responses
to all of these questions.
And in fact, we can fake them only for the malware,
so we don't accidentally break some critical
piece of software that's running inside the Sandbox.
So now at the end of this talk,
I'm gonna release a collection of eBPF programs
and loaders that I've called bad BPF.
So these programs demonstrate a number of the techniques
we've discussed and demonstrated today,
and they should have enough documentation
and comments to help you understand exactly how they work.
They cover a range of actions from hijacking execve calls
to load arbitrary programs,
allowing the user to become Sudo
all the program that replaces the arbitrary text
in arbitrary programs.
Which because basically everything in Linux is a file,
this can be used to hide kernel modules,
adding fake users to Etsy password,
or faking the Mac address from the network card.
So we've covered a lot today and honestly,
the internals of EBF I'm using eBPF defensively
could be entire talks on their own.
But, I hope you've at least learn things about
how kernel rootkits are great,
but they're also incredibly risky.
And I hope you've learnt how eBPF can remove that risk
while keeping the same ability
to hide data from administrators
and provide backdoor access to a machine.
And I really hope you've come away with some ideas
on how to detect and prevent eBPF rootkit
from being deployed.
Because I think the safety and portability
is gonna mean that we're definitely
gonna start seeing actual eBPF rootkit
appear in world before too long.
Now there's a lot of links on this page,
I think if you're interested in eBPF,
I would absolutely recommend checking out
the community website in Slack,
there's a bunch of really cool people sitting
on that Slack who are really great at helping people learn
more about the system and answering
any questions that people have.
Now, there's also been some other offensive eBPF talks
in the past, if you're interested in the offensive side.
So including (indistinct) just the other day
from the Data Dog people.
So I would definitely recommend checking those talks out,
if you're interested in this.
Finally, I've got some thanks.
Thank you very much to Cory for being incredibly supportive
as I've delved into the quarters of eBPF.
And definitely thanks for Maybe for helping me
workshops are more than ridiculous ideas that I had,
when I was designing this talk
and then definitely thank you to my family.
This recording was done during the middle
of a pretty hectic time,
involving the pandemic and (indistinct) lots of fun.
I've been very lucky to have a partner
that supporting me as I ramble into a camera
that is many, many, many miles away from DEFCON.
So with that, I will end this talk
with a picture of my dog, thanks for watching.
I'll be around on the Discord,
if you have any other questions,
otherwise, feel free to reach out to me on Twitter,
email, GitHub et cetera.
And thank you for watching.