 Good day everyone. My name is Pat. I'm path to file on Twitter, GitHub, Discord and most other places and This talk is about creating and countering the next generation of Linux root kits using eBPF So today we're gonna start with an overview on what Linux kernel root kits are and we're gonna cover why root kits 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 parts of a kernel root kit without any of the risks Then finally, we're gonna cover how to detect and prevent eBPF base root kits before they take over as the preferred root kit type for attackers So firstly, what are kernel root kits? Well once an attacker compromises the 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 tack is going to 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 root kit 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 processors network connections Really, you can do anything to hide from your space programs Now by living in the kernel the root kit also has the ability to tap into all 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 guardrails 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 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 writing to a hard drive when you broke things You could end up corrupting that disk effectively breaking the entire system Doing so 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 root kit developer was very careful a kernel update has the ability to alter what a function Hooked function looks like or what a new kernel object looks like and all this just increases the likelihood of a disaster from a kernel This means that a root kit developer often has to test the root kit 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 Fully there was a way to keep the only advantages of a kernel root kit 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 that they've ever heard But when Thomas graph for my surveillance 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 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 be attached to user space programs and functions If this sounds like the same places as our kernel root kit you'd be correct But unlike the kernel root kit 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 written 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 is limited to only a number of bpf helper functions Now instead of compiling this code into a native assembly eBPF programs actually get compiled into what's called bpf bytecode Which is a 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 it 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 its systems administrator Now the kernel just doesn't blindly trust this bytecode So it 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 invalid 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 its safety guarantee Because only code that passes all of the verifiers extensive checks is allowed to actually be loaded of run Now once code has passed the verifier the kernel will then actually run a compiler To convert the bytecode into the native instructions that match that machine's architecture and kernel version So if it's an x86 machine or compile it to x86 or if it's rml we um for example Now by running as 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 Um, it actually also dynamically looks up the addresses of the bpf helper functions Or the any kernel objects that the code's using and it'll 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 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 program 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 call 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 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 want to go into what an attacker with the privileges to load and run eBPF programs Can do and how can they use it to achieve the same root kit functionality as a regular kernel root kit So the first thing we're going to cover is using eBPF to warp the network reality So this is a diagram of a fairly standard web server setup 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 administrator's 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 want to 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 want to be able to gain the same privilege access from the host That seems to be limited only to the internal vpn site 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 if it's come 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 site It can then route the traffic into the internal interface into the ssh service And so for the perspective of ssh this looks like just a regular connection from the internal systems Then and not only will ssh see this traffic as regular If an administrator is using tools such as wire shark or netstat or tcp dump Then from the 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 read and write network packets It has the ability to see any network packets before any other system So it has the ability to receive commander control information From even a a port that nothing is listening on and then it can just silently drop those packets So no security system will know that that data that commander control data has actually reached the system Then while eBPF cannot create its own connections It has the ability to clone existing packets So it could clone some existing traffic that some existing legitimate traffic that say going to the website Then alter the destination ip addresses to be the Attackers ip address and then alter the actual data within the packet With to be whatever it wants and then it can send it off to the attacker So this technique could be used to exaltrate 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 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 The data underneath the encrypted tls connection So that even from an external network monitor It would only see legitimate tls connection The legitimate tls traffic going to go from the website And it doesn't actually know that eBPF might be reaching underneath the tls And swapping out the website's data to be some exfiltrated data from the system Okay, so altering data across the network is only one type of malicious behavior eBPF can do The real strength actually lies in its kernel hooking functions and even syscall interception Because it's this ability that allows it to walk reality around files processes and even users So going back to our ssh example, it's not enough to just be able to connect to the service If logging on requires a valid password and multi-factor authentication Then it's unlikely an attacker will 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 on to the system Well, so ssh knows that there's extra requirements such as multi-factor Due to configuration files that are in the etsy-pamd 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 user space programs read actually read files using syscalls So when a process wants to read a file, it'll actually make two syscalls to the kernel So the first is to open or open apt And this will check that the file that the program wants to open actually exists And that 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 the kernel 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 file's content The kernel will then look up that fd number make sure it's a valid number Then grab the file and it'll copy the file's data into that process's 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 we can actually watch Um, we can 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 user space program By reading the contents of the buffer after the reads syscall has exited Which would be that eBPF program at the bottom But reading buffers isn't the only thing eBPF can do 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 reads 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 reads 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 program gets control again Our eBPF program is going to 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 will include the file data But there is also a bpf probe 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 the eBPF program exits and controllers return to the user space program The program will think that the contents of buffer contains the file data When in actuality it contains the faked data that's been put there by eBPF This bpf write user call can be used to overwrite any user space buffer pointer or string That gets passed into or out of these syscalls or kernel functions So things like changing what program get launched by execve Or reading and altering net lake data heaps of different stuff can be possible with this call So another thing eBPF can do is bypass the syscall all together And instead just pretend that the function ran and return an arbitrary error code or return value This can be done using the fmod ret type of eBPF program Which while these can't be attached to every function they can be attached to every syscall at least on newer kernels So for example the example in the top right This this program simply pretends to write to a file and it returns the expected success code So to indicate that the file was actually written But the file is never actually written and the the right syscall is 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 send signal helper function The program can send an unstoppable sig kill signal Which will immediately instruct the kernel to start tearing down that process regardless of whether it wants to 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 going to 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 it 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 altering Tampering with the read calls from a file only after an IP a connection from a specific IP address has occurred So looking back to our ssh example to bypass multi-factor eBPF can simply overwrite the data being read from the pam configuration files to remove any mention of multi-factor It could then even overwrite the data in xe password and xe shadow to insert a fake user account and password Which would enable logging into 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 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 Okay, the first demonstration that we're going to go through is the ability to replace text within arbitrary files So we can see in the shell on the top right that there is a folder and with a file called file And when we look inside this file, we see the text. This is real data So now we're going to go ahead and load up the first of our eBPF root kits into this shell on the left So this root kit is going to look for any time a process is opening the word file And it's going to 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 process id Which we can see That matches with our shell on the right So we're going to go ahead our root kit has 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 cat 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 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 a system administrator having a look at that file Okay So the next demonstration we're going to go through Is the ability to stealthily enable a user to use sudo to become root So typically on this machine if we have a look at this shell in the bottom right This is running as the user called loadproof And if loadproof wanted to become root using sudo Well, we can see oh loadproof is not allowed to in the sudo's file And in fact If we use the root shell on the top right we can double and triply confirm that loadproof is not in this list So first off we can use the sudo dash l command to say hey what What privileges does sudo believe this user to have? And when we run it we see user loadproof is not allowed to run And in fact we can even at this most basic level Just go and Read the etsy sudo's file And look for the user loadproof And sure enough that user is not in there So that's this user loadproof is definitely not able to become root using sudo That is until we run the second of our ebpf rootkits on the left So this one is going to Look for anytime anything that is opening specifically sudo Is going to try to open the etsy sudo's file And it's just going to alter the text in that file to say hey loadproof 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 loadproof So now this rootkitter started If loadproof 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 loadproof 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 loadproof It says hey Loadproof has the ability to do anything at once without even needing to add in a path password But even with this rootkit running If we were to check these permissions as a different user It still says hey loadproof is no longer here and if we check that file It's still so still says that loadproof 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 loadproof user The last example that we're going to go through is The ability to to kill arbitrary processes as a sort of self-protection idea so Typically an administrator can use a cool 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 system d 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 What this so we're going to 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 sort of in any sort of investigation Okay So now we're going to cover some other features of ebpf and they get into some limitations of it So three features that we haven't yet covered, but I think are definitely worth mentioning Uh, firstly on some network cards You can actually run their ebpf programs on the card in the network card 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 note Because what this means is that any packet alterations made by an ebpf program That if this program is running on the network card, this will occur after The linux kernel has potentially scanned that packet for anything malicious So if you want 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 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 user space loader were to exit Then the kernel would just assume that you also want to stop running the 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 uh this sysfs bpf 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 the ebpf programs will continue to run then when you want to stop them you just delete the files So finally the thing worth mentioning is so the as we said before the bpf verifier Put strict limits in how complex an individual ebpf Code can program can be but there exists a mechanism to chain multiple programs together Using the bpf using this helper function called a bpf tail call 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 in the riot this is four call graphs that from four different ebpf programs That actually just make up one half of that text replacing root kit that we just demonstrated Now each uh each part each individual program is pushing the limit on what a single ebpf program is allowed to do But all combined the the system as a whole can be much much more complex Now there's a number of limitations to writing a root kit using ebpf So the first one is when using the bpf write 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 window doesn't matter in single threaded programs Because the their code execution is not going to 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 to using ebpf as a root kit is that programs don't persist across a root kit across a reboot So what this means is when a machinery starts 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 can't write to kernel memory Because this would almost certainly break those safety guarantees of ebpf What this means if a security tool is running in the kernel such as audit d or ellenic security module These are going to be unaffected by ebpf's tampering But one thing to note about these is that while a security product might be running in the kernel They're usually administrated by user space tools So if a root kit were to disable the security tool in the kernel But then lie to the user space controller About this 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 going to 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 bytecode is inside a name section within that elf So what this means is that tools such as read elf or obj dump can actually be 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 tpe syscall execve enter What happens is when this gets compiled That tpe 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 the bpf 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 bytes Now it's important to note that um A lot of loaders are going to be written using this lib bpf 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 lib bpf what this library will actually do It'll actually embed the entire elf object from the compiler Inside the user space loader. So you end up with an elf inside of an elf And so therefore if you're wishing to extract the bytecode You would first need to look at the read only data inside the loader Extract the elf from there and then pass and extract that data to find the correct section to get the bpf bytecode Now once you do extract the bytecode the biggest thing to look for would be evidence of that bpf probe write user function um, it might be more difficult to Automatically tell if a network packet altering program is malicious or not But I can't imagine too many legitimate use cases of this bpf probe write user function Now I haven't touched at all On what bpf bytecode instructions actually look like Uh, but the the instruction call is that effort that comes out of the compile the first compiler Is that example on disk? Um, so they're 85 and then the 24 matches with the bpf probe user function But if you remember the bytecode is architecture 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 bytecode that's being stored inside the kernel You would actually then to not need to dynamically look up that memory address to determine that that is the probe write user function Um, and then if you're looking at the native code after after the jit compiler inside the kernel Then this is definitely just going to look like a regular call instruction So you would need to look up that again dynamically look up that memory address to determine what uh, that that is the probe write user function Okay, so to protect a running system I think one of the strongest defenses would be to monitor that bpf syscall Which you know, you could use ebpf to monitor ebpf So monitoring for what programs are loading and running ebpf programs again It's going to be a really good tactic because realistically there 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 your suspicious behavior in the code so A lot of the defenses i've covered so far I assume that an ebpf root kit 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 mode process scanning file You know that are scanning files or attempting to load an ebpf program But even kernel root kits 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 at the hardware or hypervisor or even the physical level Uh, volatility is the name of an excellent memory forensics tool And in fact at this year's black hat the team is releasing some new plugins specifically around Acquiring and analyzing linux tracing forensics Now as i'm pre recording this talk I don't know exactly what they're going to cover But I did speak briefly with a number of the team members before I recorded this And i'm really excited to actually scatter scatter handle on and play With the plugins that they're producing because they sound incredibly interesting So a one final prevention could be to just straight up disable any use of ebpf within the kernel 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 sign 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 um Now implementing this is definitely non trivial 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 based root kits Okay, before we finish quickly, uh, 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 Um, 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 want to mention is that warping reality isn't just for attackers So the 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 cores the machine uptime The number of files within the temp folder Um, it might even actually look at the manufacturer as a network card to determine. 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 Um, and they're yeah cool Uh, then so now at the end of this talk, I'm going to release a collection of ebpf programs Uh 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 demos documentation and comments to help you understand exactly how they work Uh, they cover a range of actions from hijacking exactly e-calls to load arbitrary programs Allowing the user to become sudo Or the program that replaces 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 them back addressed from a network card Okay, so we've covered a lot today. Um, and honestly the internals of ebpf and using ebpf defensively could be entire talks on their own But I hope you've at least learned things about how kernel writ kits are great But they're also incredibly risky And I hope you've learned how ebpf can remove that risk while keeping the same ability To hide data from administrators and provide backdoor access to a machine Um, and I really hope you've come away some ideas on how to detect and prevent ebpf root kits from being deployed Because I think the safety and portability Is going to mean that we're definitely going to start seeing actual ebpf root kits appear in the wild before too long Now there's a lot of links on this page. Um, I think if you're interested in ebpf I would absolutely recommend checking out the community website and 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 Um, now there's also been some other offensive ebpf talks in the past if you're interested in the offensive side So including uh, one actually just the other day from the the data dog people So I would definitely recommend checking those talks out if you're interested in this Uh, finally, I've got some thanks. Uh, thank you very much to kori For being incredibly supportive as I've delved into the corners of ebpf And definitely thanks for maybe for helping me workshop some of more of the ridiculous ideas that I had when I was designing this talk And then definitely thank you to my family Uh, this recording was done during the middle of a pretty hectic time Involving the pandemic and daycare illnesses and all that sort of fun I've been very lucky to have um a partner that's supporting me as I ramble into a camera that is many many Many miles away from uh defcon Okay, so with that I'll end this talk with a picture of my dog Uh, thanks for watching. Uh, I'll be around on the discord if you have any other questions Um, otherwise feel free to reach out to me on twitter email github, etc Um, and thank you for watching