 We're going to get started this morning with what looks to be a very exciting talk with a couple uh, couple recorded demos because these guys are smart and they don't do live demos at DEF CON. That is- that's- well, you're allowed but it's just a really, really terrible idea. Um, so if you- if this is your first time in track four, which we are calling fancy track, here in fancy track you cannot vape, you cannot smoke. Anything of any kind. Uh, you are not supposed to be having any kind of outside beverages other than water. There you go. Um, like I said, if you want to kind of move towards the center so that people can get in and out, that will help because we're going to have a lot of people come into a lot of really good talks today. With that said, let's get TOEFL and Michael up here. Um, how many people use antivirus at work? How many people believe it does anything? There we go. How many people use EDR at work? Yeah? How many people believe it does something? Uh-huh. Suckers. Let's give Michael a tough or a big round of applause. Hi, thank you for coming. Uh, on an early uh, Saturday morning, this is uh, EDR's coming. Hi, Joe Shit. Um, I'm really happy to uh, be here this year. This sort of uh, came about as a hallway conversation at DEF CON last year. We had some ideas. We talked it over. It turned into some research and uh, here we are and that's pretty exciting. So go out there and talk to all the people and have all the ideas and submit something next year. Alright, so um, who are we? Well, first of all, we don't speak for our employer. These are, these are speaking all on behalf of ourselves and nothing that we're saying is to be construed as, you know, from our employer. Uh, uh, I'm Michael Liebowitz. I like to uh, on my, in my free time write uh, or make hardware implants, re-implementing NSA uh, hardware implants and uh, I'm a principal troublemaker. Ann? And uh, I'm Joe Fritimzen. I like doing like C sharp mower stuff so hilariously enough some of the things you're gonna see in this talk. I've talked about uh, previously at DEF CON 23 so it's kinda like the old is still new. Uh, I'm a principal vulnerability enthusiast. We both work on red teams and as you can see by our matching attire we uh, we just wanna drink coffee and write malware. Alright, so uh, here's what we're gonna go through and we have a lot to cover so we're gonna go through it pretty fast but basically what EDR is, why we care. Uh, UEFI and the thing to note about UEFI is UEFI is cross platform which is why we're doing a Windows and a Linux demo and why we have a Windows and Linux payload. Of course you know what everyone's wondering what does this all mean and then you know some mitigation or whatever and then future work and then conclusions. Uh, so we're gonna kinda start off with talking about EDR so a lot of you raised your hands that you use this and think it works so we're about to you know kinda ruin that for you. Um, so kind of uh, so it's ten o'clock the slides are a little bit hung over so uh EDR is end point detection and response not enterprise. Uh, thanks slides for being up early with us. Um, the biggest thing about EDR is that it's really just defensive tooling that focuses on like detecting, investigating and mitigating suspicious activities going on within an environment. The big thing that it really provides blue teams is a hunt capability so this is how and a lot of uh, organizations they're making like large scale like correlations for hunt stages so like, oh this machine over here is doing these sorts of things that's not really typical. This alert fired on our scene, let's go investigate. Um, typically it really just means that like for us on red teams that blue team's gonna find you and we don't wanna be found. Uh, so we're gonna sort of look at how we avoid that. Um, and then like the one big thing with EDR is that typically everything's mapped to uh like mitre attack and if you're not familiar with mitre attack that's essentially just like this huge knowledge base of uh, of things that attackers tend to do based off of real world observation. So like you probably hear the term like TTP thrown around everywhere. Um, in essence it's really just this huge table that lists things that attackers like to do so you kinda like think back to previous life when you were in kindergarten and you get like a gold star for like turning in your homework on time and like being polite. It's essentially like that but for like us as bad guys so we get gold stars and when we do like persistence we get a gold star for privilege escalation. Uh, so like we wanna fill out all the things but not have anybody know so we don't actually get the gold stars. Uh, we just wanna do it. Um, so like I'm saying like EDR is really just tuned like in actuality for like processes, commands and API calls. So if you're like running say like uh cmd.exe or PowerShell or doing like some registry stuff or trying to set up persistence. Because those are like TTPs in the mitre attack framework those tend to be flagged and mapped and then alerted on for the blue team. Um, and we wanna make sure that none of that actually happens. So, uh, a lot of people talk about you know the risk curve and um, you know this is the other side of the risk curve basically. You know no, no attack, no breach lasts forever right? You can see from the right side of the graph that eventually you're gonna get busted. And you, you land your shell, you know that's kind of the highest risk time you move around a little bit and eventually sort of settle into persistence. And like the longer you hold on the more chance it is that someone's gonna roll you up and really what we want to do is you know make this curve flatten a little bit. And you know what, what does it mean when you know the breach gets detected? Like no one's sleeping well tonight. This is, this is terrible. You know you're lovingly crafted. Payload becomes the analyst sample. You're like very upset because all these months of work and crafting that. Super awesome. Payload are just down the drain and the analyst is like oh shit there goes my Friday night. Nobody's happy. So what we want to do is we want to modify this risk curve. We want to make it such that you know you're, we're not gonna flatten that initial shell pop kind of, kind of part like that's kind of the same but we just want to, we just want to hang on to the good stuff for longer. Eventually we're, eventually you're gonna get rolled up but we just, just hang out and chill out for a little bit longer. So as we were investigating ways that we can hide from a UEF or from a EDR, Mike and I had some pre-existing platform experience, a particular UEFI platform experience, a like platform firmware. So in sort of this research it's like we were thinking that we can utilize this sort of functionality to evade all of these detections and make that risk curve and the dwell time for us last a little bit longer. So if you're not familiar with UEFI, I have to include this awesome diagram of it because John Luke Hades told everybody ever talking about UEFI that they have to. Essentially if you're not familiar with UEFI it's essentially what modern BIOS is now. So it does all of the things that you don't really care about like CPU and it, change your memory, it loads a bunch of option ROMs from like your PCI devices. There's other talks that go over what this actually means but what we're concerned about is if you look at the bottom there's this notion of runtime services and after the OS boots those are exposed at the operating system level. Some of the things that get exposed within the runtime services stage of UEFI are UEFI firmware variables. So these are persistent variables that actually live within your NVRAM on your platform that are accessible both to UEFI applications like if you're familiar with secure boot, all of your secure boot like variables and stuff live there so like boot order, like your, the keys that secure boot utilizes things of that nature. So we're gonna take advantage of the fact that we can persist within NVRAM within the UEFI platform that we can then access at operating system runtime. So sort of like you're probably thinking at this point well why UEFI firmware variables? Well like I was saying it's a way that you can hide your payloads from all of these detective capabilities because it's a blind spot for all of them. Nobody looks here like really at all especially within AV and EDR platforms. If you're not familiar really with what UEFI firmware variables are either it essentially consists of like a name and a grid so it's like this tuple and if you are able to set or get that tuple you can pull the contents of what that variable is out of NVRAM and we're gonna kinda showcase that we can execute those live on the system to both stash our stuff and to sort of have like this persistence mechanism. So really quickly like UEFI firmware variables have a couple of types. There's authenticated and unauthenticated. This isn't so much important but we kinda just wanted to briefly touch on it just in case you're concerned at all with the specification or what we're doing. Like if you've heard of like authenticated variables these are signed like X509 certs that perform like a certificate check when writing. We're not gonna worry about those. There are unauthenticated variables that are also present at that runtime stage. These have no verification on write. The majority of variables on a platform as we'll show you in a demo are unauthenticated. So it's not really abnormal for these to be there and it's not atypical for things to necessarily be writing or reading from there. If you're like a platform researcher or something you know about this. There's a couple of attributes as well to UEFI firmware variables within the specification. We're gonna really just focus on three out of the six because as I'll showcase in the Windows 10 API you have to have non-volatile boot service access and runtime access in order to have UEFI variables that persist within the Windows runtime after boot on your NVRAM. So just note that those three are gonna be utilized and that'll be shown in the demo as well. Sort of the hilarious little thing here too with why we sort of started thinking about UEFI as a way to hide from EDR. In an old old life we're walking with some blue team folks and we're talking about ways that we've been being tricky on engagements and sharing some techniques. And we're kinda talking about like IOT devices and how it'd be cool to hide like an IOT firmware. And they're like yeah that'd be cool but like please don't ever hide like in platform firmware and you know Mike and I kinda stopped and were like oh shit. So we're gonna do Windows and Linux like Mike said UEFI is platform agnostic so it doesn't matter what it's running on. It's part of your platform. It helps boot Intel like processors. It also works like on AMD. It's kinda different there. It's a specification whatever. So UEFI and Windows. Basically I was re-looking at the MSDN articles for Windows 10 and I recognized so they had taken this off and then they reintroduced the ability to do UEFI platform stuff within 18.03. So I was kinda like reading the documents. They listed all of these requirements for actually being able to use this API functionality within Windows now. So it was kinda concerning because there's a lot there that they say you need this otherwise it wouldn't work. Such as you need to declare firmware read and write and your application manifest. You need to have it be a protected app so like a signed app that the Microsoft store signs needs to be signed. You need to be an admin that has access to the special privilege SE system environment name like privilege token in your process space. So looking at it it was kinda daunting because it's such a long list of requirements but you know we're hackers that doesn't mean anything. So we started looking at ways to bypass this like SpecterOps puts out a lot of like WDAC bypasses which is a way to execute signed Windows binaries with that will unsigned Windows binary so like unsigned Windows binaries you can still execute. Obviously on red teams we sometimes jump to conclusions or we make some leaps forward to speed up engagement time with like assume breach type scenarios or sort of the methodology and thinking that we're gonna wind up being admin why don't we just become admin now. So like that sort of stuff for our purposes of doing this sort of thing on red team engagements wasn't necessarily impactful so we just kinda went with it with the assumption that we're gonna be we can be an admin on a box and we're not gonna need it to be assigned a Windows application. So like just to showcase what the read and write firmware variable API looks like from the MSDN articles you can do set and get firmware variables from NVRAM. Really the key thing here is you just have like the name and GWD tuple that I was mentioning earlier and for set all you do is you point the buffer you wanna write into the variable you give it the size and the attributes that you wanna have it be declared as and it just sets it in NVRAM for you and then forget it's the same sort of idea you give it a name and a GWD tuple and then you give it the buffer you wanna read into and then it reads the NVRAM out into some memory buffer that you control as the attacker and of course you'll wind up executing that once you get the variable out of NVRAM. These are the attributes not really important it's on the slide more for reference but this is from the MSDN article note that for variable attribute runtime services it says if you want this to be accessible during RT it needs to also be accessible to boot services so that's kind of why we're gonna have to set all three in Windows so NVBS and RT variables. So when I was initially implementing this it was sort of the decision between if I wanted it to be in C++ or in C sharp so I initially implemented all of this in C++ just because it was easy because the MSDN articles basically just give you the code you need but as I was kind of doing the research it occurred to me that C++ wasn't a viable option because AV flags it very easily. Like one thing that you have to do obviously if we're getting a firmware variable is you need RWX memory so doing a lot of calls to like virtual alloc, virtual protect. It's kind of a red flag right now especially for EDR products as they start querying all these APIs like most applications aren't like making an RWX memory buffer and then executing it like it was shell code so we're not gonna do that. C sharp can basically do everything C++ can either with P invoke or reflection and having C sharp malware experience in the past was like yeah let's just do it in C sharp. Furthermore most of the C sharp bypasses or some of the most of the WDAC bypasses are in C sharp anyway so that kind of like checked that flag off for us and then in order to make things kind of easier for all of our red team friends to use particularly on Windows environments we wanted to make sure that they could that they could use it in C sharp is like kind of the direction that malware authors in Windows are kind of going for red team engagements these days or or going. But there's reference code for both on the repo which we'll showcase later after the talk. So essentially the steps for writing a UEFI variable in Windows is really easy once you have that admin privilege. You essentially just need to obtain the SE system environment name with set priv. This is the only case of like P invoke that we're gonna be using. Furthermore like I was saying like in the manifest where you needed read and write capabilities. The MSDian article is weird in that it lists all of those things for C plus plus applications. It makes no notion of ever doing the stuff in C sharp. So I've never had to declare those things and I don't really know what Microsoft is stating in that. So just ignore that completely. You don't need it for C sharp. You can then get the address of your pin buffer. So that's our payload. And then we just write the UEFI variable to NVRAM and now it's persistent storage. So here's some code really quickly to set the privilege. It's just P invoke so you get process. You say that you want the new token privilege. You set it. Boom. We're good. Then you can get the address of your pin buffer in C sharp. Like I said this was your payload. So you initialize an end pointer. You call interop services to get a pin to ray of your buffer that you want to write. You pin it so the garbage collector and nothing can touch it as you're working with it. And then you just simply write that UEFI variable with the set firmware variable call with the tuple. And in this case it's going to be C sharp UEFI. And then I have a super secret, uh, super secret quid. Say that five times fast. Um, that you can Google and figure out what it is. Uh, so the steps for executing UEFI variable are pretty much similar. You still need that token. And the first thing I did in C sharp was I did P invoke with virtual alloc to obtain an RWX memory pointer that I can execute. And then I was just obtaining that UEFI variable back into that buffer so I can execute it. Uh, so the first step, same idea, you need that privilege. Second step is I start P invoking some memory so I have RWX. Uh, but you can't actually really do that in C sharp because it's abnormal to bring things into your import address table that aren't actually C sharp specific. Um, so like all of the virtual calls are more suspicious than getting a new process token. Cause uh, within like C sharp there's no real way to do like process token stuff. You have to pretty much P invoke so it's not suspicious. It is suspicious for EDR products that you're doing virtual alloc, virtual free and virtual protect within C sharp. It's like whoa, stop right there. We're going to tell the blue team about this and they're going to hunt you down. So we can't do that. Hilariously enough as we were going through this research, um, OJ is working on like a C sharp C alarm interpreter and he was dealing with some stuff and he also says the same thing like don't P invoke your dot net apps. Like EDR is going to find you. Like as he says it's the proverbial solution for them hunting you down. Uh, so we are, we're not going to have to, we're going to lose the ability to P invoke to get RWX memory. Uh, which is kind of a problem. So we can't do step two anymore, but fear not. Uh, the CLR and C sharp is fantastic for malware. So we're going to actually just now instead of doing any virtual calls, we're going to use reflection within C sharp to obtain RWX JIT memory which just in time compilation leaves RWX memory pages if you're not familiar with it. To read the UEFI variable into that, then we're going to write the UEFI variable into a method table pointer and then we're going to execute the method as if nothing actually ever happened. Uh, so those are the steps. I'm going to actually go through that in detail because that was probably a little bit jarring. Basically in C sharp, if you're not familiar with it, because it's an intermediate level language representation of code, it has to get just in time compiled to assembly code before it gets executed by the processor. So within C sharp, there's this huge method table that contains all of the methods that the C sharp application knows about. And all of those contain a JIT stub for those classes methods. So essentially what that means is at the time of just in time compilation, the method table gets referenced. You then get a function pointer to the executable assembly code that the processor will run, which is RWX due to the notion of JIT. You can grab that method pointer, dereference the function pointer that the assembly code lives to, which is just a location of the method that you're clobbering and override it. So this essentially means we can declare a method that we don't care about, force it to just in time compile, get the pointer to it and then override it. Uh, so it's basically like retolib C, but in C sharp and it's like more fucky. So the steps for that look like this, we're essentially going to now obtain an RWX JIT memory page to read the variable into. That's gonna consist of defining a method to overwrite, jitting the method, obtaining the pointer to the method, and then overwriting it and calling it. So we'll define a method to overwrite. This is in the code that I'm going to be releasing. It's just called overwrite me. It does nothing. We'll JIT the method. So here you can see in reflection I'm doing a type of the program I'm in. Get method overwrite me. I call compile service runtime helpers prepare method, which is essentially just going to JIT that with the method handle. So I have my method dot method handle that's dereferencing one of the pointers. And then I obtain the pointer to the method, which is just get function pointer once I've jitted it. So now I have the location of the raw assembly code after JIT and that RWX memory location. So now I write the UEFI variable payload that's stored in NVRAM into the pointer to method. So I just call get firmware variable EX. You can see the third argument there after the tuple is pointer to method with then in the fourth argument being buffer length. That's going to take the NVRAM out, plop it in, and then I can just execute the method called overwrite me as if it was actual C sharp code and I hadn't done anything malice. So we're going to do a quick demo of what that looks like to kind of tie it all together in Windows. Step one, you obtain your shell on target. We've already done that, so step one's kind of skipped. We're then going to run write UEFI C sharp. You'll see this with the writer binary that I've written. In an actual like red team engagement or in a campaign, you'd probably do this with like whatever C2 framework you were using. So you can use the C sharp code say like in cobalt strike with some of the functionality there and do it on Windows boxes. You'll then do some sort of persistence mechanism for the reader binary, which is going to go through and do the steps I just demonstrated with reflection. It's like a four kilobyte binary you'll use for persistence. You can, you know, we're not giving you a persistent mechanism. I'm sure all of you have lots in your bag. You just need to throw this binary somewhere and run it. And then we'll run it to showcase what it looks like. So the Windows demo, this one, computers are hard. So here I am on Windows. I'm going to first go through and run a really quick chip sec module. If you're not familiar with chip sec, it's a UEFI platform security tool that helps security researchers analyze platform firmware. It does a lot of cool things for UEFI, particularly variables. So I added here as I just ran a module to dump and list what all the UEFI variables currently on my system are. You can see that there's a lot of them. Do note that most of these are NVBS plus RT. So most of them are accessible at runtime services to the operating system and they're, of course, because they're persistent, they're persistent and NVRAM. So there they are. You didn't see mine. Here I'm going to dump really quickly the variable list to show you that there's contents of all of these variables. Like this one is kind of funny, like test zero, this is a test. So there's lots of variables here. Nobody really ever audits them. Like I said, AV and EDR doesn't look here. So now what I'm going to do is I'm going to run write UEFI or UEFI write C sharp. That's going to write a UEFI variable to NVRAM. I ran chip sec again to show you that it's now there. There it is. C sharp dash UEFI. So now that that's there on box, I can execute what the payload is. But first I'm going to show you what, that there's actual like shell code there. So I'll go into the UEFI variables directory with chip sec. I'll dump it out. And there you can see that I have some shell code there that I'm going to execute out of NVRAM with the reader binary. That payload for demo purposes is going to be our favorite demo, Metasploit. So it's just an interpreter shell that I'm going to spin up. I'm going to go through run UEFI read seed sharp. And then as you can see from that, I successfully just executed a payload out of NVRAM with like a four kilobyte binary using reflection. Thank you. So the fun doesn't actually end there. So because this is a persistence mechanism and it's persistent in NVRAM, this means it's going to survive reboots. It's going to survive reinstalling your operating system. The only way to clear this out is to like clobber over that variable or pull NVRAM with like a deadie prog and rewrite your UEFI variable space. So I'm going to shut down the box, reboot it, go back to my Metasploit shell, rerun the console and then it's a cooking show. It takes a long time for Windows to boot. So speed it up. You know, I just put the payload in the oven. It's going to be done pretty quickly. The machine's booting. It's still booting. It's a cooking show. Wait a minute. There it is. Let's see. And there we go. I just executed my payload out of NVRAM again with a persistence mechanism out of a UEFI variable. The fresh cookies. Yay cookies. And shells. It baked from shells. Awesome. So we kind of like have hand waived the persistence thing. We're going to leave that as an exercise up to the reader. Like I said, WDAC bypasses are a great way to do this. In actuality, your payload is a UEFI variable. Like good luck, have fun analysts. We love you still though. Like we're going to help you, but this is fun. So like what about Windows EDR products? We haven't necessarily touched on that. Like obviously this is a way to mitigate detection. So we looked at a couple of EDR vendors and we found no relevant information pertaining to the usage of either these API calls. Executing out a UEFI variable or anything of that nature. The only thing they're really going to see is that you're executing this binary. But like there's binaries executed on systems all the time. That's not really something too relevant that's going to trigger a hunt. Furthermore, there's a lot of ways currently to sync whole or to tamper with EDR products. So here's like a five line power shell script that you can use to like sync whole EDR products. This works on a lot of them. Like EDR products are things of software running on a box. Software have configs. Configs can be tampered with. So just tampered with configs a lot of the times and you can get away with anything on a box on Windows. There's a lot of other ways to go about it. We can chat like after the talk about it. This isn't really a talk about this. So it's a talk about hiding your shit and that's how you hide your shit in Windows. Some WDAC bypass is just for references. Now that I've talked about hiding your shit in Windows, Mike's going to talk about some Linux stuff. Boy, Windows is silly. Let's talk about Linux. Linux is, you know, everyone knows that's where the real loot is. So let's talk about the problem space. Basically let's introduce our players here. We have, you know, the kernel. We have the EDR and we have, on the right, we have your sample. And, you know, EDR is looking at your sample and that's as bad. That's what makes it your sample and not your payload. And, you know, the EDR and your sample are actually kind of peers, right? We're both running as privileged processes and the EDR has some hooks into kernel space to help it do its job. And so that's what that sort of rectangle, just above the eyeballs is. Eyeballs are obviously EDR. And so, like, what does our solution space look like? Well, you know, what we really want is just to make, you know, just to sucker punch the EDR a little bit, you know, while it's not looking and make sure that it just doesn't look at us at all and then it's back to being our payload. So, you know, how are we going to do that? We need to, like, we need to show up early to the fight, right? So that it never sees us coming. So we need to infect something. So, you know, how does your computer, how does your computer boot? And what can we infect? Well, the first thing that boots is a platform firmware and that's signed by the OEM. You can't really infect that easily. Boo. The next thing, that's signed by Microsoft, the shim, that's signed by Microsoft and it pivots the key over to the distro. That's a little bit harder to infect. Uh, grub, you know, signed by the distro, no good. Kernel, signed by the distro, no good. But the RAM disk is generated on system and not signed. This sounds like a good time. And then sometime later, some shit happens in the EDR is started. So obviously what we need to infect is the RAM disk. So how are we gonna, what capabilities do we have, what tools do we have at our disposal in the Linux environment to make things happen and make the EDR not look at us? So, uh, the first sort of, uh, wonderful sys call to, uh, introduce is ptrace, right? And this is, you know, why we say the 90s are back again, like ptrace, uh, exploitation of processes has been, like, uh, as old as time itself. But, you know, in, in, it's, it's tapered off in the, in the modern era because we have policies that prevent you from doing it. We have like Yama and SE Linux and App Armor and silly stuff like Smack and Timoio and whatever. But the best part about all this stuff is the policy is implied, is, is applied in user space. Alrighty. So let's, let's, let's go through this, um, let's go through this in flowchart sort of land. So we have, um, the RAM disk is actually the original PID 1. That's actually where, uh, a NIT starts from. And then, it finds your root file system, you know, draws some pretty stuff on screen, like make sure you have the Ray fonts, whatever. And then it does, it actually deletes everything out of the, out of the root file system except for the target directory and then it moves the mount from the target to root and then it execs systemd. And that will come up again, this sort of deleting everything. And then like systemd starts and like, you know, the thumbs down is the policy being loaded that prevents you from attacking the EDR and then of course our eyeballs here are the EDR. So let's, let's talk about some other things. We have FA Notify. FA Notify is kind of a obscure API but like it's designed for AV. I don't think any AV actually uses it but, you know, who cares? Exploding security, or using security APIs for unintended things is like one of my favorite things. So basically what this lets you do is this lets you, um, you know, do the AV thing, right? Like a file is accessed, you get to stop that process from accessing that file, decide whether it's okay and then you can say if it is to go ahead which effectively allows us to inhibit start up of other processes. Uh, another fantastic utility is, uh, MemFD Create. Um, this has been talked about a lot in, in, in the, in the hacker scene but essentially like you can create uh, an anonymous file and uh, this works like a file, get a file descriptor uh, and then you can actually access it through you know, Procpid, FD, uh, even from other processes. This is fantastic. Uh, and you know, the best part is like everyone says, never touch disk kids. Uh, and then another API that we can use is, and this is also somewhat obscure and not really security relevant, is, um, a PRCTL, a PRCET timer select. So we need some marker for our process uh, to say to the EDR, don't look at this. And so we need something that's inheritable, right? So you know, you can, you can have your militia shell, you can cat shadow and when cat does, cat also inherits the marker. So um, we do the set timer slack, this basically uh, controls how often you wake up the CPU, it's designed to save power but I don't care about that. And then lastly like config EFI virus, this is the kernel config to make the EFI virus file system. You saw what a pain in the ass it was to do stuff with UFI on Windows. Windows is dumb. It's just a file system. You just read them right files. It's super easy. You can do it from a shell script. And then I talked previously about MS move, like basically um, this, if you look in the code, this is labeled as black magic fuckery. Um, I can go through these steps but it's really convoluted but essentially um, if you want to have a malicious process that survives pivoting the root file system out from under you, there's a whole lot of really weird stuff involving containers and charoots and namespaces and weird stuff to do to so that your malicious process sees the real root file system as opposed to seeing the init root file system which has nothing in it. Um, funny story like even though you can never have two root file systems in Linux, if you don't do this you have two root file systems in that process and uh, the real one and the init one and you, and nothing is there it's like really messed up. So anyway, let's go through how this is, how, how this works in practice. So our little uh, our little devil emoji here, I like emojis, uh, is our malicious demon. This is, this is effectively stage one. Um, we, in the, the init script in the ramfs, forks and execs that, we open the uh, EFI vars, we actually mount the EFI vars file system uh, and mount proc and all that. And then we fetch it out of the uh, we fetch stage two and three out of EFI, out of UEFI land. And then we just kind of stay there and we cross that boundary between init ramfs land and you know, the real system land. And that execs you know, our friend system D, which then spawns all kinds of other garbage. And when it spawns the policy load, which we detect through FAA notify, we give a stop signal to sysctl, right? Sysctl is gonna apply the policy that says you cannot ptrace. And there's our EDR over there. I think you can figure out the next step. Uh, we're gonna ptrace the uh, the EDR and then like have our way with it. So uh, what ptrace allows us to do is basically we stop the process. You can see uh, we probably end up stopping it right after or before a syscall. And we can just back up uh, we can just back up to the syscall. We can control the IP and back it to the syscall. And then we can just set EAX and set what syscalls we'd like to make. So we're effectively coercing syscalls into the process. So we can call memfdcreate. Then in our other process, because we can access procfd, procpidfd, we can shove stage, stage three in there, which is embedded in stage two. Which by the way, I never touched disk. And then we can do an M-Map. Uh, fortunately unlike in, in Windows uh, M-Mapping rewired execute pages is like totally normal, libc does it all the time. Um, and then we can just put our shell code in there. And then we set, oops, I went too fast. Then we set our EIP to the sled there. And we actually just jump over. And then we effectively return to, return to DL open as um, as was, as we learned yesterday and as I kind of already knew like. Uh, I'm sorry, I forgot the speaker's name. We talked about it yesterday. It's on my no card. It's on my no card. Oh no. I'm out of sync. Anyway. So uh, libc has an internal DL open. We can do uh, the old school uh, LD preload trick. It's separate without LD preloading. We can call the internal DL open. Then we can, and have our malicious SO. And that malicious SO can clobber whatever we need to clobber. And then we return. All right. So now we can send the continue to our uh, policy load and load the actual policy that prevents us from doing this. And our EDR is actually now looking the other way. So basically um, if you look in the code and you see our payload um, and this is sort of a, a point that also Tofer touched on. That uh, you don't want to, you don't, there's two options here about clobbering the EDR. Either the input stage or the output stage. And the input stage is complicated. You have to understand how it processes information from the kernel. The output stage is super simple. You, you've already looked at the logs. You know what they say. You just want to compromise its ability to write things to the output log. Or things you don't want to the output log. And then there's our malicious process and everybody's happy. The EDR is looking away and we can plunder away. So uh, let's do a little demo. Um, what I'm going to do is uh, we're going to uh, tune up AuditD. AuditD is our example EDR. Uh, you know, I know that like AuditD is not a commercial EDR vendor and you're wondering does this work on commercial EDR vendor? Yep, probably. Uh, and uh, we'll install our implant, we'll reboot, we'll set the marker, we'll do the exploit again and we'll show that we're invisible. Alright, let's do the demo. Okay, uh, oh god, how do you do this? Windows is hard. What do I do? Oh god! I, I know how to use Windows. This Windows shit is complicated. Alright, here we go. We got the analyst on the, on the right. We got the hacker on the left. And um, what we're going to do is the analyst is going to turn on the audit rules. He's going to tune up AuditD so that it just uh, has every exec. Then we're going to tailor the audit log. We're going to exploit the enterprise tool. You can see we're root. We're making all this noise. It's terrible. You know, they're going to roll this up. You can see it on the right. All that noise. Then we're going to run our infector binary. Our infector binary is going to make a whole lot of noise. But um, this noise is actually really normal because uh, systems generate uh, init ram fs's all the time. So it's fine. So it's going to make basically all the noise that it makes on a uh, on a UEFI or on a init ram fs update. Uh, this is kind of a lot of reused harness from my horse pill talk from a few years ago. But you know, it's as true today as it was there. And like, you know, everything's in fact they'd have a nice day. And then we're going to reboot. Doo doo doo doo. Let's do some cooking show time. Let's see. Let's see if I edited this video well enough. Oh, here we are. Waiting. Okay. Waiting. I'll edit it tighter next time. Okay. And again, we've tuned up audit and you can see we, we're um, displaying the audit log there. Let's, let's see, make a little space there. Doo doo doo. Okay. And then we're going to do the same thing we're going to x, we're actually, we're going to set our marker first and that's going to make a little bit of noise. But once you set the timer slack, that's what that PRCTL call is. You can see, uh, the marker is set. And you can also see that there's no noise in the audit log. We're, and then I, I game root again. And you can see again, no noise. We're, we're invisible. We can, we can do all those nasty things we did before. Invisible. It's awesome. Ta-da. And then uh, we can show that, we can show the policy is applied. You can see like YMMO3 means Ptrace is, is completely disabled in the system and that is true. Like Ptrace is now completely disabled in the system but we inhibited the policy load that prevented us from doing that. And then, uh, like I said, everything's a file, a file system or everything's a file in Linux. Like there's an e5 or a file system. If you look like, uh, somewhere in there, there should be a law key. Yeah, there it is. Yeah, right around there. Cause hacking is funny. And then ta-da, we did it. How do we get back to the slides? Okay. Thank you. And, you know, everyone on a Saturday morning at DEF CON is always thinking themselves, what, what does this all mean? You know, we just want to bring happiness to everyone. Everyone's going to sleep well tonight. This is the net happiness increase. You're happy. The analyst is happy. That, that payload that you spent months working on is still your payload and not their sample. Everything is good. That's what we're all about. Bringing happiness to the world. All right. I don't really care about mitigation so I'm going to have Tofer talk about that. I mean, I don't really care either but we felt it necessary. Um, there's a couple of things that you can do to mitigate this. Like the one biggest thing is cause we're utilizing UEFI variables is to actually monitor and audit those against your organization's fleet. That would uh, that would be like the first step to sort of mitigating these risks that we've presented. Um, furthermore, EDR vendors, if any of you are out there, you should be detecting UEFI APIs and this functionality in Windows and in Linux bases if you happen to be doing like Linux EDR. Um, it's not really common for applications to set and get firmware variables. Um, and furthermore, like after the installation of a platform, uh, NV, BS and RT variables being set is pretty weird. Uh, I've never actually seen that in practice. If you have seen that in practice, come talk to me about it cause I'd like to know where cause I want to abuse it. Um, furthermore, as we kind of showcased, EDR tamper resistance is not at all effective. Uh, it's very easy to like sync all uh, the sensor, kill the sensor. As Mike showed, it's very easy to P trace the sensor. Um, so vendors really just need to work on securing their agents and their processes a little bit better. Um, furthermore, Mike kind of said this in his horse pull talk at Black Hat a few years ago, but assembling RAN disks on systems is just silly. Stop doing that if you're a Linux distro. Um, so like, as far as closing the rest goes, uh, we have some future work. So, you know, the system firmware is uh, a great place to hide and there's all kinds of goodies in there and we are just touching the surface of it. And it's interesting like, as we were doing this research, a lot of companies started announcing that they are going to start looking at the firmware space as a place to hunt. But, you know, this is a cat mouse game and uh, as far as I can tell the uh, are we the mouse? Are we the cat? Anyway, one of us is already ahead. And I think it's us. I'm not sure if we're the cat or the mouse. All right. So like, in closing, we're bringing net happiness to everybody. We're going to have ourselves a UEFI dot party. We're plundering away our loot. We're sucker punching that pesky EDR. Um, and all of our code is located on this GitHub link, uh, perturbed platypus. Or, you know, as we like to call ourselves, APTPP. Uh, we, we just pushed the code, we just confirmed it. We had a, we had a timer on a box that pushed it exactly 1045. Uh, it's live. So go, go have at it, plunder away. Uh, here's some references that you can look at. Uh, that, that's all we got for you.